From 866630589efe0a7c550453643ee3fa0fac04f424 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Tue, 9 Jan 2018 15:44:00 +0000 Subject: [PATCH 01/17] Unity 2018.1.0b2 C# reference source code --- .../2D/SpriteEditorModule/SpriteEditorData.cs | 6 +- .../SpriteFrameModuleBase.cs | 1 + .../2D/SpriteEditorModule/TextureImporter.cs | 2 +- Editor/Mono/Commands/GOCreationCommands.cs | 7 +- Editor/Mono/EditorGUI.cs | 10 +- Editor/Mono/GUI/ColorMutator.cs | 53 +- Editor/Mono/GUI/ColorPicker.cs | 82 +- .../Mono/GUIDebugger/GUIViewDebuggerWindow.cs | 51 +- .../SubstanceImporterInspector.cs | 532 ------- .../AddComponent/AddComponentDataSource.cs | 107 ++ .../Inspector/AddComponent/AddComponentGUI.cs | 65 + .../AddComponent/AddComponentWindow.cs | 93 +- ...ownElement.cs => ComponentDropdownItem.cs} | 34 +- ...ownElement.cs => NewScriptDropdownItem.cs} | 46 +- .../AdvancedDropdownDataSource.cs | 93 ++ .../AdvancedDropdown/AdvancedDropdownGUI.cs | 151 ++ .../AdvancedDropdown/AdvancedDropdownItem.cs | 202 +++ .../AdvancedDropdownSimpleDataSource.cs} | 21 +- .../AdvancedDropdownWindow.cs | 292 ++-- .../StatefulAdvancedDropdown.cs | 14 +- .../StatelessAdvancedDropdown.cs | 16 +- Editor/Mono/Inspector/InspectorWindow.cs | 8 +- .../Inspector/LightProbeProxyVolumeEditor.cs | 5 +- Editor/Mono/Inspector/MaterialEditor.cs | 3 +- .../Inspector/ProceduralMaterialInspector.cs | 1354 ----------------- .../Inspector/ProceduralTextureInspector.cs | 93 -- .../SearchableDropdown/DropdownElement.cs | 178 --- .../GroupDropdownElement.cs | 36 - Editor/Mono/Inspector/TextureInspector.cs | 9 +- Editor/Mono/Inspector/UnityEventDrawer.cs | 6 +- Editor/Mono/ObjectNames.cs | 8 - Editor/Mono/PlayerSettings.deprecated.cs | 13 + Editor/Mono/PlayerSettingsIOS.bindings.cs | 15 +- Editor/Mono/PluginImporter.bindings.cs | 33 + .../ScriptAttributeGUI/PropertyHandler.cs | 2 +- Editor/Mono/ShaderUtil.bindings.cs | 102 +- .../Mono/SpriteEditor/SpriteEditorWindow.cs | 6 +- Editor/Mono/SubstanceImporter.cs | 160 -- .../SpriteShapeUtility.bindings.cs | 1 + .../Substance/SubstanceUtility.bindings.cs | 24 + Modules/Substance/SubstanceUtility.cs | 334 ++++ .../Public/WebRequestExtensions.cs | 5 - .../Camera/XRCameraInstance.bindings.cs | 28 + .../XRCameraSubsystemDescriptor.bindings.cs | 24 + .../Environment/Depth/XRDepth.bindings.cs | 110 ++ .../Environment/Planes/XRPlane.bindings.cs | 232 +++ .../Environment/Raycast/XRRaycast.bindings.cs | 136 ++ .../XRReferencePoint.bindings.cs | 110 ++ .../Environment/Session/XRSession.bindings.cs | 86 ++ .../Environment/XREnvironment.bindings.cs | 145 ++ ...EnvironmentSubsystemDescriptor.bindings.cs | 30 + .../Input/XRInputInstance.bindings.cs | 18 + .../XRInputSubsystemDescriptor.bindings.cs | 17 + Modules/XR/XRSubsystemManager.bindings.cs | 2 + Projects/CSharp/UnityEditor.csproj | 72 +- Projects/CSharp/UnityEngine.csproj | 52 +- README.md | 2 +- .../SpriteDataAccess.bindings.cs | 2 + Runtime/Export/GI/Lightmapping.cs | 25 +- .../GI/ScriptBindings/Lights.bindings.cs | 37 - Runtime/Export/Graphics.bindings.cs | 147 +- Runtime/Export/iOS/iOSDevice.bindings.cs | 22 + Runtime/Export/iOSSystemGestureDeferMode.cs | 19 + .../Core/SubstanceUtilityBindings.gen.cs | 405 ----- .../Editor/BuildPipelineBindings.gen.cs | 4 +- .../Editor/EditorGUIUtilityBindings.gen.cs | 60 +- .../InternalEditorUtilityBindings.gen.cs | 4 + .../PlayerSettingsAndroidBindings.gen.cs | 2 +- .../SubstanceEditorUtilityBindings.gen.cs | 120 -- 69 files changed, 2650 insertions(+), 3534 deletions(-) delete mode 100644 Editor/Mono/ImportSettings/SubstanceImporterInspector.cs create mode 100644 Editor/Mono/Inspector/AddComponent/AddComponentDataSource.cs create mode 100644 Editor/Mono/Inspector/AddComponent/AddComponentGUI.cs rename Editor/Mono/Inspector/AddComponent/{ComponentDropdownElement.cs => ComponentDropdownItem.cs} (69%) rename Editor/Mono/Inspector/AddComponent/{NewScriptDropdownElement.cs => NewScriptDropdownItem.cs} (76%) create mode 100644 Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownDataSource.cs create mode 100644 Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs create mode 100644 Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownItem.cs rename Editor/Mono/Inspector/{SearchableDropdown/AdvancedDropdown.cs => AdvancedDropdown/AdvancedDropdownSimpleDataSource.cs} (75%) rename Editor/Mono/Inspector/{SearchableDropdown => AdvancedDropdown}/AdvancedDropdownWindow.cs (50%) rename Editor/Mono/Inspector/{SearchableDropdown => AdvancedDropdown}/StatefulAdvancedDropdown.cs (71%) rename Editor/Mono/Inspector/{SearchableDropdown => AdvancedDropdown}/StatelessAdvancedDropdown.cs (85%) delete mode 100644 Editor/Mono/Inspector/ProceduralMaterialInspector.cs delete mode 100644 Editor/Mono/Inspector/ProceduralTextureInspector.cs delete mode 100644 Editor/Mono/Inspector/SearchableDropdown/DropdownElement.cs delete mode 100644 Editor/Mono/Inspector/SearchableDropdown/GroupDropdownElement.cs delete mode 100644 Editor/Mono/SubstanceImporter.cs create mode 100644 Modules/Substance/SubstanceUtility.bindings.cs create mode 100644 Modules/Substance/SubstanceUtility.cs create mode 100644 Modules/XR/Subsystems/Camera/XRCameraInstance.bindings.cs create mode 100644 Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.bindings.cs create mode 100644 Modules/XR/Subsystems/Environment/Depth/XRDepth.bindings.cs create mode 100644 Modules/XR/Subsystems/Environment/Planes/XRPlane.bindings.cs create mode 100644 Modules/XR/Subsystems/Environment/Raycast/XRRaycast.bindings.cs create mode 100644 Modules/XR/Subsystems/Environment/ReferencePoints/XRReferencePoint.bindings.cs create mode 100644 Modules/XR/Subsystems/Environment/Session/XRSession.bindings.cs create mode 100644 Modules/XR/Subsystems/Environment/XREnvironment.bindings.cs create mode 100644 Modules/XR/Subsystems/Environment/XREnvironmentSubsystemDescriptor.bindings.cs create mode 100644 Modules/XR/Subsystems/Input/XRInputInstance.bindings.cs create mode 100644 Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.bindings.cs delete mode 100644 Runtime/Export/GI/ScriptBindings/Lights.bindings.cs create mode 100644 Runtime/Export/iOSSystemGestureDeferMode.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SubstanceUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/SubstanceEditorUtilityBindings.gen.cs diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs index 55b3fe3139..c4260d6208 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs @@ -16,6 +16,9 @@ internal class SpriteDataExt : SpriteRect { public List spriteBone; public float tessellationDetail = 0; + + // The following lists are to be left un-initialized. + // If they never loaded or assign explicitly, we avoid writing empty list to metadata. public List spriteOutline; public List vertices; public List indices; @@ -36,9 +39,6 @@ internal SpriteDataExt(SpriteRect sr) spriteID = sr.spriteID; alignment = sr.alignment; pivot = sr.pivot; - spriteOutline = new List(); - spritePhysicsOutline = new List(); - spriteBone = new List(); } public void Apply(SerializedObject so) diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs index 718542eb43..5f9ebae02e 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs @@ -50,6 +50,7 @@ public override void OnModuleActivate() textureActualHeight = height; m_RectsCache = ScriptableObject.CreateInstance(); m_RectsCache.spriteRects = m_SpriteDataProvider.GetSpriteRects().ToList(); + spriteEditor.spriteRects = m_RectsCache.spriteRects; if (spriteEditor.selectedSpriteRect != null) spriteEditor.selectedSpriteRect = m_RectsCache.spriteRects.FirstOrDefault(x => x.spriteID == spriteEditor.selectedSpriteRect.spriteID); } diff --git a/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs b/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs index dbc2f1544a..b12631bf6f 100644 --- a/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs +++ b/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs @@ -32,7 +32,7 @@ SpriteRect[] ISpriteEditorDataProvider.GetSpriteRects() void ISpriteEditorDataProvider.SetSpriteRects(SpriteRect[] spriteRects) { - if (spriteImportMode == SpriteImportMode.Single && spriteRects.Length == 1) + if (spriteImportMode != SpriteImportMode.Multiple && spriteImportMode != SpriteImportMode.None && spriteRects.Length == 1) { m_SpriteSingle.CopyFromSpriteRect(spriteRects[0]); } diff --git a/Editor/Mono/Commands/GOCreationCommands.cs b/Editor/Mono/Commands/GOCreationCommands.cs index 025069073e..098ebca656 100644 --- a/Editor/Mono/Commands/GOCreationCommands.cs +++ b/Editor/Mono/Commands/GOCreationCommands.cs @@ -21,7 +21,7 @@ internal static void Place(GameObject go, GameObject parent) if (parent != null) { var transform = go.transform; - transform.SetParent(parent.transform, false); + Undo.SetTransformParent(transform, parent.transform, "Reparenting"); transform.localPosition = Vector3.zero; transform.localRotation = Quaternion.identity; transform.localScale = Vector3.one; @@ -30,7 +30,10 @@ internal static void Place(GameObject go, GameObject parent) if (parent.GetComponent()) ObjectFactory.AddComponent(go); } - SceneView.PlaceGameObjectInFrontOfSceneView(go); + else + { + SceneView.PlaceGameObjectInFrontOfSceneView(go); + } EditorWindow.FocusWindowIfItsOpen(); Selection.activeGameObject = go; } diff --git a/Editor/Mono/EditorGUI.cs b/Editor/Mono/EditorGUI.cs index a2f37b235f..a90a1d3e47 100644 --- a/Editor/Mono/EditorGUI.cs +++ b/Editor/Mono/EditorGUI.cs @@ -1431,6 +1431,12 @@ internal static string TextFieldInternal(Rect position, GUIContent label, string return text; } + internal static string ToolbarSearchField(Rect position, string text, bool showWithPopupArrow) + { + int id = GUIUtility.GetControlID(s_SearchFieldHash, FocusType.Keyboard, position); + return ToolbarSearchField(id, position, text, showWithPopupArrow); + } + internal static string ToolbarSearchField(int id, Rect position, string text, bool showWithPopupArrow) { bool dummy; @@ -4195,6 +4201,8 @@ private static Color DoColorField(Rect position, int id, Color value, bool showE { Color c = EyeDropper.GetPickedColor(); c.a = value.a; + if (hdr) + c = c.linear; EditorGUIUtility.DrawColorSwatch(position2, c, showAlpha, hdr); } else @@ -4246,7 +4254,7 @@ private static Color DoColorField(Rect position, int id, Color value, bool showE Color c = EyeDropper.GetLastPickedColor(); c.a = value.a; s_ColorPickID = 0; - return c; + return hdr ? c.linear : c; case EventCommandNames.EyeDropperCancelled: HandleUtility.Repaint(); s_ColorPickID = 0; diff --git a/Editor/Mono/GUI/ColorMutator.cs b/Editor/Mono/GUI/ColorMutator.cs index d8965785de..aa6ff8f2c7 100644 --- a/Editor/Mono/GUI/ColorMutator.cs +++ b/Editor/Mono/GUI/ColorMutator.cs @@ -20,6 +20,32 @@ internal class ColorMutator // this is the value used by Photoshop private const byte k_MaxByteForOverexposedColor = 191; + internal static void DecomposeHdrColor(Color linearColorHdr, out Color32 baseLinearColor, out float exposure) + { + baseLinearColor = linearColorHdr; + var maxColorComponent = linearColorHdr.maxColorComponent; + // replicate Photoshops's decomposition behaviour + if (maxColorComponent == 0f || maxColorComponent <= 1f && maxColorComponent > 1 / 255f) + { + exposure = 0f; + + baseLinearColor.r = (byte)Mathf.RoundToInt(linearColorHdr.r * 255f); + baseLinearColor.g = (byte)Mathf.RoundToInt(linearColorHdr.g * 255f); + baseLinearColor.b = (byte)Mathf.RoundToInt(linearColorHdr.b * 255f); + } + else + { + // calibrate exposure to the max float color component + var scaleFactor = k_MaxByteForOverexposedColor / maxColorComponent; + exposure = Mathf.Log(255f / scaleFactor) / Mathf.Log(2f); + + // maintain maximal integrity of byte values to prevent off-by-one errors when scaling up a color one component at a time + baseLinearColor.r = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.r)); + baseLinearColor.g = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.g)); + baseLinearColor.b = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.b)); + } + } + public Color originalColor { get { return m_OriginalColor; } @@ -177,28 +203,11 @@ void OnRgbaHdrChannelChanged(int channel) if (channel == (int)RgbaChannel.A) return; - var newColor = exposureAdjustedColor; - var maxColorComponent = newColor.maxColorComponent; - // replicate Photoshops's decomposition behaviour - if (maxColorComponent == 0f || maxColorComponent <= 1f && maxColorComponent > 1 / 255f) - { - m_ExposureValue = 0f; - - m_Color[(int)RgbaChannel.R] = (byte)Mathf.RoundToInt(newColor.r * 255f); - m_Color[(int)RgbaChannel.G] = (byte)Mathf.RoundToInt(newColor.g * 255f); - m_Color[(int)RgbaChannel.B] = (byte)Mathf.RoundToInt(newColor.b * 255f); - } - else - { - // calibrate exposure to the max float color component - var scaleFactor = k_MaxByteForOverexposedColor / maxColorComponent; - m_ExposureValue = Mathf.Log(255f / scaleFactor) / Mathf.Log(2f); - - // maintain maximal integrity of byte values to prevent off-by-one errors when scaling up a color one component at a time - m_Color[0] = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * m_ColorHdr[0])); - m_Color[1] = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * m_ColorHdr[1])); - m_Color[2] = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * m_ColorHdr[2])); - } + Color32 baseColor; + DecomposeHdrColor(exposureAdjustedColor, out baseColor, out m_ExposureValue); + m_Color[(int)RgbaChannel.R] = baseColor.r; + m_Color[(int)RgbaChannel.G] = baseColor.g; + m_Color[(int)RgbaChannel.B] = baseColor.b; Color.RGBToHSV( color, out m_Hsv[(int)HsvChannel.H], diff --git a/Editor/Mono/GUI/ColorPicker.cs b/Editor/Mono/GUI/ColorPicker.cs index f041d0a149..cde28eefae 100644 --- a/Editor/Mono/GUI/ColorPicker.cs +++ b/Editor/Mono/GUI/ColorPicker.cs @@ -11,6 +11,12 @@ namespace UnityEditor { internal class ColorPicker : EditorWindow { + private const string k_HeightPrefKey = "CPickerHeight"; + private const string k_ShowPresetsPrefKey = "CPPresetsShow"; + // HDR and LDR have different slider mode pref keys because they have different defaults for the sake of discoverability + private const string k_SliderModePrefKey = "CPSliderMode"; + private const string k_SliderModeHDRPrefKey = "CPSliderModeHDR"; + // the default max amount of stops to use for the intensity slider; same as in Photoshop/Affinity private const float k_DefaultExposureSliderMax = 10f; @@ -135,13 +141,8 @@ public static ColorPicker instance static void swap(ref float f1, ref float f2) { float tmp = f1; f1 = f2; f2 = tmp; } - Vector2 Slider2D(Rect rect, Vector2 value, Vector2 maxvalue, Vector2 minvalue, GUIStyle backStyle, GUIStyle thumbStyle) + Vector2 Slider2D(Rect rect, Vector2 value, Vector2 maxvalue, Vector2 minvalue, GUIStyle thumbStyle) { - if (backStyle == null) - return value; - if (thumbStyle == null) - return value; - int id = GUIUtility.GetControlID(s_Slider2Dhash, FocusType.Passive); // test max and min @@ -194,9 +195,6 @@ Vector2 Slider2D(Rect rect, Vector2 value, Vector2 maxvalue, Vector2 minvalue, G case EventType.Repaint: { - // background - backStyle.Draw(rect, GUIContent.none, id); - // thumb (set to black for light colors to prevent blending with background) var oldColor = GUI.color; GUI.color = VisionUtility.ComputePerceivedLuminance(color) > Styles.highLuminanceThreshold ? @@ -319,9 +317,9 @@ Texture2D Update1DSlider( step = new Color(0, 0, 0, 1); break; } - FillArea(xSize, 2, colors, start, step, new Color(0, 0, 0, 0)); + FillArea(xSize, 2, colors, start, step, new Color(0, 0, 0, 0), !hsvSpace && m_HDR); if (hsvSpace) - HSVToRGBArray(colors); + HSVToRGBArray(colors, m_HDR); oldConst1 = const1; oldConst2 = const2; @@ -375,7 +373,7 @@ void HSVSliders() GUILayout.Space(Styles.extraVerticalSpacing); } - static void FillArea(int xSize, int ySize, Color[] retval, Color topLeftColor, Color rightGradient, Color downGradient) + static void FillArea(int xSize, int ySize, Color[] retval, Color topLeftColor, Color rightGradient, Color downGradient, bool convertToGamma) { // Calc the deltas for stepping. Color rightDelta = new Color(0, 0, 0, 0), downDelta = new Color(0, 0, 0, 0); @@ -392,14 +390,14 @@ static void FillArea(int xSize, int ySize, Color[] retval, Color topLeftColor, C Color p2 = p; for (int x = 0; x < xSize; x++) { - retval[current++] = p2; + retval[current++] = convertToGamma ? p2.gamma : p2; p2 += rightDelta; } p += downDelta; } } - static void HSVToRGBArray(Color[] colors) + static void HSVToRGBArray(Color[] colors, bool convertToGamma) { int s = colors.Length; for (int i = 0; i < s; i++) @@ -407,7 +405,7 @@ static void HSVToRGBArray(Color[] colors) Color c = colors[i]; Color c2 = Color.HSVToRGB(c.r, c.g, c.b); c2.a = c.a; - colors[i] = c2; + colors[i] = convertToGamma ? c2.gamma : c2; } } @@ -442,8 +440,8 @@ void DrawColorSpaceBox(Rect colorBoxRect, float constantValue) int xSize = m_ColorBox.width; int ySize = m_ColorBox.height; - 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)); - HSVToRGBArray(m_Colors); + 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); + HSVToRGBArray(m_Colors, m_HDR); m_ColorBox.SetPixels(m_Colors, 0); m_ColorBox.Apply(true); @@ -474,6 +472,7 @@ static class Styles public static readonly GUIStyle currentColorSwatch = "ColorPickerCurrentColor"; public static readonly GUIStyle colorBoxThumb = "ColorPicker2DThumb"; public static readonly GUIStyle hueDialBackground = "ColorPickerHueRing"; + public static readonly GUIStyle hueDialBackgroundHDR = "ColorPickerHueRing-HDR"; public static readonly GUIStyle hueDialThumb = "ColorPickerHueRingThumb"; public static readonly GUIStyle sliderBackground = "ColorPickerSliderBackground"; public static readonly GUIStyle sliderThumb = "ColorPickerHorizThumb"; @@ -559,6 +558,11 @@ void OnClickedPresetSwatch(int clickCount, object presetObject) SetColor(color); } + private Color GetGUIColor(Color color) + { + return m_HDR ? color.gamma : color; + } + void DoColorSwatchAndEyedropper() { GUILayout.BeginHorizontal(); @@ -590,13 +594,13 @@ void DoColorSwatchAndEyedropper() if (Event.current.type == EventType.Repaint) { GUI.backgroundColor = m_Color.exposureAdjustedColor.a == 1f ? Color.clear : Color.white; - GUI.contentColor = m_Color.exposureAdjustedColor; + GUI.contentColor = GetGUIColor(m_Color.exposureAdjustedColor); Styles.currentColorSwatch.Draw(swatchRect, Styles.currentColorSwatchFill, id); } swatchRect.x -= swatchRect.width; GUI.backgroundColor = m_Color.originalColor.a == 1f ? Color.clear : Color.white; - GUI.contentColor = m_Color.originalColor; + GUI.contentColor = GetGUIColor(m_Color.originalColor); if (GUI.Button(swatchRect, Styles.originalColorSwatchFill, Styles.originalColorSwatch)) { m_Color.Reset(); @@ -612,7 +616,8 @@ void DoColorSwatchAndEyedropper() void DoColorSpaceGUI() { - var dialSize = Styles.hueDialBackground.CalcSize(GUIContent.none); + var backgroundStyle = m_HDR ? Styles.hueDialBackgroundHDR : Styles.hueDialBackground; + var dialSize = backgroundStyle.CalcSize(GUIContent.none); var dialRect = GUILayoutUtility.GetRect(dialSize.x, dialSize.y); switch (m_ColorBoxMode) { @@ -622,7 +627,7 @@ void DoColorSpaceGUI() dialRect.width = dialRect.height; var hue = m_Color.GetColorChannel(HsvChannel.H); var oldColor = GUI.contentColor; - GUI.contentColor = Color.HSVToRGB(hue, 1f, 1f); + GUI.contentColor = GetGUIColor(Color.HSVToRGB(hue, 1f, 1f)); EditorGUI.BeginChangeCheck(); @@ -631,7 +636,7 @@ void DoColorSpaceGUI() GUIContent.none, hue * 360f, ((GUIContent)Styles.hueDialThumbFill).image, - Styles.hueDialBackground, + backgroundStyle, Styles.hueDialThumb ); @@ -655,7 +660,7 @@ void DoColorSpaceGUI() EditorGUI.BeginChangeCheck(); var sv = new Vector2(m_Color.GetColorChannel(HsvChannel.S), 1f - m_Color.GetColorChannel(HsvChannel.V)); - sv = Slider2D(svRect, sv, Vector2.zero, Vector2.one, GUIStyle.none, Styles.colorBoxThumb); + sv = Slider2D(svRect, sv, Vector2.zero, Vector2.one, Styles.colorBoxThumb); if (EditorGUI.EndChangeCheck()) { @@ -810,7 +815,7 @@ void DoExposureSwatches() for (int i = 0; i < numSwatches; ++i) { var stop = i - numSwatches / 2; - var col = m_Color.exposureAdjustedColor * Mathf.Pow(2f, stop); + var col = (m_Color.exposureAdjustedColor * Mathf.Pow(2f, stop)).gamma; col.a = 1f; GUI.backgroundColor = col; GUI.contentColor = VisionUtility.ComputePerceivedLuminance(col) < Styles.highLuminanceThreshold ? @@ -845,7 +850,7 @@ void DoPresetsGUI() { var foldoutRect = GUILayoutUtility.GetRect(Styles.presetsToggle, EditorStyles.foldout); foldoutRect.xMax -= 17f; // make room for presets settings menu button - m_ShowPresets = EditorGUI.Foldout(foldoutRect, m_ShowPresets, Styles.presetsToggle); + m_ShowPresets = EditorGUI.Foldout(foldoutRect, m_ShowPresets, Styles.presetsToggle, true); if (m_ShowPresets) { @@ -871,6 +876,8 @@ void OnGUI() case EventCommandNames.EyeDropperClicked: m_ColorBoxMode = ColorBoxMode.HSV; Color col = EyeDropper.GetLastPickedColor(); + if (m_HDR) + col = col.linear; m_Color.SetColorChannelHdr(RgbaChannel.R, col.r); m_Color.SetColorChannelHdr(RgbaChannel.G, col.g); m_Color.SetColorChannelHdr(RgbaChannel.B, col.b); @@ -1105,16 +1112,18 @@ static void Show(GUIView viewToUpdate, Action colorChangedCallback, Color cp.m_ExposureSliderMax = Mathf.Max(cp.m_ExposureSliderMax, cp.m_Color.exposureValue); originalKeyboardControl = GUIUtility.keyboardControl; - // For now we enforce our Color Picker for hdr colors if (cp.m_HDR) + { cp.m_IsOSColorPicker = false; + cp.m_SliderMode = (SliderMode)EditorPrefs.GetInt(k_SliderModeHDRPrefKey, (int)SliderMode.RGB); + } if (cp.m_IsOSColorPicker) OSColorPicker.Show(showAlpha); else { cp.titleContent = hdr ? EditorGUIUtility.TrTextContent("HDR Color") : EditorGUIUtility.TrTextContent("Color"); - float height = EditorPrefs.GetInt("CPickerHeight", (int)cp.position.height); + float height = EditorPrefs.GetInt(k_HeightPrefKey, (int)cp.position.height); cp.minSize = new Vector2(Styles.fixedWindowWidth, height); cp.maxSize = new Vector2(Styles.fixedWindowWidth, height); cp.InitializePresetsLibraryIfNeeded(); // Ensure the heavy lifting of loading presets is done before window is visible @@ -1153,16 +1162,15 @@ void OnEnable() EditorApplication.update += PollOSColorPicker; EditorGUIUtility.editingTextField = true; // To fix that color values is not directly editable when tabbing (case 557510) - m_SliderMode = (SliderMode)EditorPrefs.GetInt("CPSliderMode", (int)SliderMode.RGB); - m_ShowPresets = EditorPrefs.GetInt("CPPresetsShow", 1) != 0; + m_SliderMode = (SliderMode)EditorPrefs.GetInt(k_SliderModePrefKey, (int)SliderMode.RGB); + m_ShowPresets = EditorPrefs.GetInt(k_ShowPresetsPrefKey, 1) != 0; } void OnDisable() { - EditorPrefs.SetInt("CPSliderMode", (int)m_SliderMode); - EditorPrefs.SetInt("CPColorMode", (int)m_ColorBoxMode); - EditorPrefs.SetInt("CPPresetsShow", m_ShowPresets ? 1 : 0); - EditorPrefs.SetInt("CPickerHeight", (int)position.height); + EditorPrefs.SetInt(m_HDR ? k_SliderModeHDRPrefKey : k_SliderModePrefKey, (int)m_SliderMode); + EditorPrefs.SetInt(k_ShowPresetsPrefKey, m_ShowPresets ? 1 : 0); + EditorPrefs.SetInt(k_HeightPrefKey, (int)position.height); } public void OnDestroy() @@ -1341,7 +1349,7 @@ protected override void OldOnGUI() case EventType.MouseMove: s_PickCoordinates = GUIUtility.GUIToScreenPoint(Event.current.mousePosition); StealMouseCapture(); - SendEvent("EyeDropperUpdate", true, false); + SendEvent(EventCommandNames.EyeDropperUpdate, true, false); break; case EventType.MouseDown: if (Event.current.button == 0) @@ -1353,7 +1361,7 @@ protected override void OldOnGUI() window.Close(); s_LastPickedColor = GetPickedColor(); Event.current.Use(); - SendEvent("EyeDropperClicked", true); + SendEvent(EventCommandNames.EyeDropperClicked, true); if (m_ColorPickedCallback != null) { m_ColorPickedCallback(s_LastPickedColor); @@ -1365,7 +1373,7 @@ protected override void OldOnGUI() { window.Close(); Event.current.Use(); - SendEvent("EyeDropperCancelled", true); + SendEvent(EventCommandNames.EyeDropperCancelled, true); } break; } @@ -1392,7 +1400,7 @@ void SendEvent(string eventName, bool exitGUI, bool focusOther = true) if (!m_Focused) { // Window closed before it was focused - SendEvent("EyeDropperCancelled", false); + SendEvent(EventCommandNames.EyeDropperCancelled, false); } base.OnDestroy(); diff --git a/Editor/Mono/GUIDebugger/GUIViewDebuggerWindow.cs b/Editor/Mono/GUIDebugger/GUIViewDebuggerWindow.cs index f39299d561..ea2302a265 100644 --- a/Editor/Mono/GUIDebugger/GUIViewDebuggerWindow.cs +++ b/Editor/Mono/GUIDebugger/GUIViewDebuggerWindow.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; +using UnityEditor.Experimental.UIElements.Debugger; using UnityEngine; using UnityEngine.Experimental.UIElements; using UnityEngine.Scripting; @@ -96,6 +97,7 @@ private set } else { + m_InspectedEditorWindow = null; GUIViewDebuggerHelper.StopDebugging(); } if (instructionModeView != null) @@ -139,10 +141,21 @@ public void HighlightInstruction(GUIView view, Rect instructionRect, GUIStyle st if (m_PaddingHighlighter == null) { + var borderWidth = 1f; m_PaddingHighlighter = new VisualElement(); - m_PaddingHighlighter.style.backgroundColor = Styles.paddingHighlighterColor; + m_PaddingHighlighter.style.borderColor = UIElementsDebugger.Styles.kSizePaddingSecondaryColor; + m_PaddingHighlighter.style.borderLeftWidth = borderWidth; + m_PaddingHighlighter.style.borderRightWidth = borderWidth; + m_PaddingHighlighter.style.borderTopWidth = borderWidth; + m_PaddingHighlighter.style.borderBottomWidth = borderWidth; + m_PaddingHighlighter.pickingMode = PickingMode.Ignore; m_ContentHighlighter = new VisualElement(); - m_ContentHighlighter.style.backgroundColor = Styles.contentHighlighterColor; + m_ContentHighlighter.style.borderColor = UIElementsDebugger.Styles.kSizeSecondaryColor; + m_ContentHighlighter.style.borderLeftWidth = borderWidth; + m_ContentHighlighter.style.borderRightWidth = borderWidth; + m_ContentHighlighter.style.borderTopWidth = borderWidth; + m_ContentHighlighter.style.borderBottomWidth = borderWidth; + m_ContentHighlighter.pickingMode = PickingMode.Ignore; } m_PaddingHighlighter.layout = instructionRect; view.visualTree.Add(m_PaddingHighlighter); @@ -190,8 +203,12 @@ InstructionType instructionType VisualElement m_ContentHighlighter; VisualElement m_PaddingHighlighter; + [SerializeField] bool m_ShowHighlighter = true; + [SerializeField] + private bool m_InspectOptimizedGUIBlocks = false; + [NonSerialized] bool m_QueuedPointInspection = false; @@ -216,7 +233,7 @@ static void Init() void OnEnable() { - titleContent = EditorGUIUtility.TrTextContent("GUI Inspector"); + titleContent = EditorGUIUtility.TrTextContent("IMGUI Debugger"); GUIViewDebuggerHelper.onViewInstructionsChanged += OnInspectedViewChanged; GUIView serializedInspected = m_Inspected; inspected = null; @@ -228,8 +245,7 @@ void OnEnable() void OnDisable() { GUIViewDebuggerHelper.onViewInstructionsChanged -= OnInspectedViewChanged; - GUIViewDebuggerHelper.StopDebugging(); - ClearInstructionHighlighter(); + inspected = null; } void OnBecameVisible() @@ -248,8 +264,22 @@ void OnGUI() ShowDrawInstructions(); } + private bool m_FlushingOptimizedGUIBlock; + void OnInspectedViewChanged() { + if (m_InspectOptimizedGUIBlocks && !m_FlushingOptimizedGUIBlock) + { + var inspector = m_InspectedEditorWindow as InspectorWindow; + if (inspector != null && inspector.tracker != null) + { + m_FlushingOptimizedGUIBlock = true; + foreach (var editor in inspector.tracker.activeEditors) + editor.isInspectorDirty = true; + inspector.Repaint(); + } + } + m_FlushingOptimizedGUIBlock = false; RefreshData(); Repaint(); } @@ -261,6 +291,7 @@ void DoToolbar() DoWindowPopup(); DoInspectTypePopup(); DoInstructionOverlayToggle(); + DoOptimizedGUIBlockToggle(); GUILayout.EndHorizontal(); } @@ -330,13 +361,21 @@ void DoInspectTypePopup() void DoInstructionOverlayToggle() { EditorGUI.BeginChangeCheck(); - m_ShowHighlighter = GUILayout.Toggle(m_ShowHighlighter, GUIContent.Temp("Show overlay"), EditorStyles.toolbarButton); + m_ShowHighlighter = GUILayout.Toggle(m_ShowHighlighter, GUIContent.Temp("Show Overlay"), EditorStyles.toolbarButton); if (EditorGUI.EndChangeCheck()) { OnShowOverlayChanged(); } } + void DoOptimizedGUIBlockToggle() + { + EditorGUI.BeginChangeCheck(); + m_InspectOptimizedGUIBlocks = GUILayout.Toggle(m_InspectOptimizedGUIBlocks, GUIContent.Temp("Force Inspect Optimized GUI Blocks"), EditorStyles.toolbarButton); + if (EditorGUI.EndChangeCheck()) + OnInspectedViewChanged(); + } + void OnShowOverlayChanged() { if (m_ShowHighlighter == false) diff --git a/Editor/Mono/ImportSettings/SubstanceImporterInspector.cs b/Editor/Mono/ImportSettings/SubstanceImporterInspector.cs deleted file mode 100644 index 4874c12aff..0000000000 --- a/Editor/Mono/ImportSettings/SubstanceImporterInspector.cs +++ /dev/null @@ -1,532 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -// SUBSTANCE HOOK - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - [CustomEditor(typeof(SubstanceArchive))] - internal class SubstanceImporterInspector : Editor - { - private const float kPreviewWidth = 60; - private const float kPreviewHeight = kPreviewWidth + 16; - private const int kMaxRows = 2; - - private static SubstanceArchive s_LastSelectedPackage = null; - private static string s_CachedSelectedMaterialInstanceName = null; - private string m_SelectedMaterialInstanceName = null; - private Vector2 m_ListScroll = Vector2.zero; - - private EditorCache m_EditorCache; - - [System.NonSerialized] - private string[] m_PrototypeNames = null; - - Editor m_MaterialInspector; - - // Static preview rendering - protected bool m_IsVisible = false; - public Vector2 previewDir = new Vector2(0, -20); - public int selectedMesh = 0, lightMode = 1; - private PreviewRenderUtility m_PreviewUtility; - static Mesh[] s_Meshes = { null, null, null, null }; - static GUIContent[] s_MeshIcons = { null, null, null, null }; - static GUIContent[] s_LightIcons = { null, null }; - - // Styles used in the SubstanceImporterInspector - class SubstanceStyles - { - public GUIContent iconToolbarPlus = EditorGUIUtility.TrIconContent("Toolbar Plus", "Add substance from prototype."); - public GUIContent iconToolbarMinus = EditorGUIUtility.TrIconContent("Toolbar Minus", "Remove selected substance."); - public GUIContent iconDuplicate = EditorGUIUtility.TrIconContent("TreeEditor.Duplicate", "Duplicate selected substance."); - public GUIStyle resultsGridLabel = "ObjectPickerResultsGridLabel"; - public GUIStyle resultsGrid = "ObjectPickerResultsGrid"; - public GUIStyle gridBackground = "TE NodeBackground"; - public GUIStyle background = "ObjectPickerBackground"; - public GUIStyle toolbar = "TE Toolbar"; - public GUIStyle toolbarButton = "TE toolbarbutton"; - public GUIStyle toolbarDropDown = "TE toolbarDropDown"; - } - SubstanceStyles m_SubstanceStyles; - - public void OnEnable() - { - if (target == s_LastSelectedPackage) - m_SelectedMaterialInstanceName = s_CachedSelectedMaterialInstanceName; - else - s_LastSelectedPackage = target as SubstanceArchive; - } - - public void OnDisable() - { - if (m_EditorCache != null) - m_EditorCache.Dispose(); - - if (m_MaterialInspector != null) - { - ProceduralMaterialInspector pmInsp = (ProceduralMaterialInspector)m_MaterialInspector; - pmInsp.ReimportSubstancesIfNeeded(); - DestroyImmediate(m_MaterialInspector); - } - - s_CachedSelectedMaterialInstanceName = m_SelectedMaterialInstanceName; - - if (m_PreviewUtility != null) - { - m_PreviewUtility.Cleanup(); - m_PreviewUtility = null; - } - } - - ProceduralMaterial GetSelectedMaterial() - { - SubstanceImporter importer = GetImporter(); - if (importer == null) - return null; - ProceduralMaterial[] materials = GetSortedMaterials(); - - // In some cases, m_SelectedMaterialInstanceName is not valid (for instance after ProceduralMaterial renaming). - // So we first try to find it in the materials so we know if we should return a valid material instead (case 840177). - ProceduralMaterial selectedMaterial = System.Array.Find(materials, element => element.name == m_SelectedMaterialInstanceName); - if (m_SelectedMaterialInstanceName == null || selectedMaterial == null) - { - if (materials.Length > 0) - { - selectedMaterial = materials[0]; - m_SelectedMaterialInstanceName = selectedMaterial.name; - } - } - return selectedMaterial; - } - - private void SelectNextMaterial() - { - SubstanceImporter importer = GetImporter(); - if (importer == null) - return; - string selected = null; - ProceduralMaterial[] materials = GetSortedMaterials(); - for (int i = 0; i < materials.Length; ++i) - { - if (materials[i].name == m_SelectedMaterialInstanceName) - { - int id = System.Math.Min(i + 1, materials.Length - 1); - if (id == i) --id; - if (id >= 0) selected = materials[id].name; - break; - } - } - m_SelectedMaterialInstanceName = selected; - } - - Editor GetSelectedMaterialInspector() - { - // Check if the cached editor is still valid - ProceduralMaterial material = GetSelectedMaterial(); - if (material && m_MaterialInspector != null && m_MaterialInspector.target == material) - return m_MaterialInspector; - - // In case the user was editing the name of the material, but didn't apply the changes yet, end text editing - // Case 535718 - EditorGUI.EndEditingActiveTextField(); - - // Build a new editor and return it - DestroyImmediate(m_MaterialInspector); - m_MaterialInspector = null; - - if (material) - { - m_MaterialInspector = Editor.CreateEditor(material); - - if (!(m_MaterialInspector is ProceduralMaterialInspector) && m_MaterialInspector != null) - { - if (material.shader != null) - Debug.LogError("The shader: '" + material.shader.name + "' is using a custom editor deriving from MaterialEditor, please derive from ShaderGUI instead. Only the ShaderGUI approach works with Procedural Materials. Search the docs for 'ShaderGUI'"); - - DestroyImmediate(m_MaterialInspector); - m_MaterialInspector = Editor.CreateEditor(material, typeof(ProceduralMaterialInspector)); - } - - // This should never fail, but will throw if the unexpected occurs - ProceduralMaterialInspector pmInsp = (ProceduralMaterialInspector)m_MaterialInspector; - pmInsp.DisableReimportOnDisable(); - } - - return m_MaterialInspector; - } - - public override void OnInspectorGUI() - { - // Initialize styles - if (m_SubstanceStyles == null) - m_SubstanceStyles = new SubstanceStyles(); - - EditorGUILayout.Space(); - - EditorGUILayout.BeginVertical(); - MaterialListing(); - MaterialManagement(); - EditorGUILayout.EndVertical(); - - Editor materialEditor = GetSelectedMaterialInspector(); - if (materialEditor) - { - materialEditor.DrawHeader(); - materialEditor.OnInspectorGUI(); - } - } - - SubstanceImporter GetImporter() - { - return AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(target)) as SubstanceImporter; - } - - private static int previewNoDragDropHash = "PreviewWithoutDragAndDrop".GetHashCode(); - void MaterialListing() - { - ProceduralMaterial[] materials = GetSortedMaterials(); - - foreach (ProceduralMaterial mat in materials) - { - if (mat.isProcessing) - { - Repaint(); - SceneView.RepaintAll(); - GameView.RepaintAll(); - break; - } - } - - int count = materials.Length; - - // The height of the content may change based on the selected material, - // thus an inspector vertical scrollbar may appear or disappear based on selected material. - // We don't want previews to jump around when you select them. - // So we don't calculate the width based on the available space (because it would change due to scrollbar) - // but rather based on total inspector width, with scrollbar width (16) always subtracted (plus margins and borders). - float listWidth = GUIView.current.position.width - 16 - 18 - 2; - - // If the preview list gets its own scrollbar, subtract the width of that one as well - // This won't jump around based on selection, so ok to conditionally subtract it. - if (listWidth * kMaxRows < count * kPreviewWidth) - listWidth -= 16; - - // Number of previews per row - int perRow = Mathf.Max(1, Mathf.FloorToInt(listWidth / kPreviewWidth)); - // Number of preview rows - int rows = Mathf.CeilToInt(count / (float)perRow); - // The rect for the preview list - Rect listRect = new Rect(0, 0, perRow * kPreviewWidth, rows * kPreviewHeight); - // The rect for the ScrollView the preview list in shown in - Rect listDisplayRect = GUILayoutUtility.GetRect( - listRect.width, - Mathf.Clamp(listRect.height, kPreviewHeight, kPreviewHeight * kMaxRows) + 1 // Add one for top border - ); - - // Rect without top and side borders - Rect listDisplayRectInner = new Rect(listDisplayRect.x + 1, listDisplayRect.y + 1, listDisplayRect.width - 2, listDisplayRect.height - 1); - - // Background - GUI.Box(listDisplayRect, GUIContent.none, m_SubstanceStyles.gridBackground); - GUI.Box(listDisplayRectInner, GUIContent.none, m_SubstanceStyles.background); - - m_ListScroll = GUI.BeginScrollView(listDisplayRectInner, m_ListScroll, listRect, false, false); - - if (m_EditorCache == null) - m_EditorCache = new EditorCache(EditorFeatures.PreviewGUI); - - for (int i = 0; i < materials.Length; i++) - { - ProceduralMaterial mat = materials[i]; - if (mat == null) - continue; - - float x = (i % perRow) * kPreviewWidth; - float y = (i / perRow) * kPreviewHeight; - - Rect r = new Rect(x, y, kPreviewWidth, kPreviewHeight); - bool selected = (mat.name == m_SelectedMaterialInstanceName); - Event evt = Event.current; - int id = GUIUtility.GetControlID(previewNoDragDropHash, FocusType.Passive, r); - - switch (evt.GetTypeForControl(id)) - { - case EventType.Repaint: - Rect r2 = r; - r2.y = r.yMax - 16; - r2.height = 16; - m_SubstanceStyles.resultsGridLabel.Draw(r2, EditorGUIUtility.TempContent(mat.name), false, false, selected, selected); - break; - case EventType.MouseDown: - if (evt.button != 0) - break; - if (r.Contains(evt.mousePosition)) - { - // One click selects the material - if (evt.clickCount == 1) - { - m_SelectedMaterialInstanceName = mat.name; - evt.Use(); - } - // Double click opens the SBSAR - else if (evt.clickCount == 2) - { - AssetDatabase.OpenAsset(mat); - GUIUtility.ExitGUI(); - evt.Use(); - } - } - break; - } - - r.height -= 16; - EditorWrapper p = m_EditorCache[mat]; - p.OnPreviewGUI(r, m_SubstanceStyles.background); - } - - GUI.EndScrollView(); - } - - public override bool HasPreviewGUI() - { - return (GetSelectedMaterialInspector() != null); - } - - // Show the preview of the selected substance. - public override void OnPreviewGUI(Rect position, GUIStyle style) - { - Editor editor = GetSelectedMaterialInspector(); - if (editor) - editor.OnPreviewGUI(position, style); - } - - public override string GetInfoString() - { - Editor editor = GetSelectedMaterialInspector(); - if (editor) - return editor.targetTitle + "\n" + editor.GetInfoString(); - return string.Empty; - } - - public override void OnPreviewSettings() - { - Editor editor = GetSelectedMaterialInspector(); - if (editor) - editor.OnPreviewSettings(); - } - - public void InstanciatePrototype(object prototypeName) - { - m_SelectedMaterialInstanceName = GetImporter().InstantiateMaterial(prototypeName as string); - ApplyAndRefresh(false); - } - - public class SubstanceNameComparer : IComparer - { - public int Compare(object o1, object o2) - { - Object O1 = o1 as Object; - Object O2 = o2 as Object; - return EditorUtility.NaturalCompare(O1.name, O2.name); - } - } - - private ProceduralMaterial[] GetSortedMaterials() - { - SubstanceImporter importer = GetImporter(); - ProceduralMaterial[] materials = importer.GetMaterials(); - System.Array.Sort(materials, new SubstanceNameComparer()); - return materials; - } - - void MaterialManagement() - { - // Get selected material - SubstanceImporter importer = GetImporter(); - - if (m_PrototypeNames == null) - m_PrototypeNames = importer.GetPrototypeNames(); - - ProceduralMaterial selectedMaterial = GetSelectedMaterial(); - - GUILayout.BeginHorizontal(m_SubstanceStyles.toolbar); - { - GUILayout.FlexibleSpace(); - - using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) - { - // Instantiate prototype - if (m_PrototypeNames.Length > 1) - { - Rect dropdownRect = EditorGUILayoutUtilityInternal.GetRect(m_SubstanceStyles.iconToolbarPlus, m_SubstanceStyles.toolbarDropDown); - if (EditorGUI.DropdownButton(dropdownRect, m_SubstanceStyles.iconToolbarPlus, FocusType.Passive, m_SubstanceStyles.toolbarDropDown)) - { - GenericMenu menu = new GenericMenu(); - for (int i = 0; i < m_PrototypeNames.Length; i++) - { - menu.AddItem(new GUIContent(m_PrototypeNames[i]), false, InstanciatePrototype, m_PrototypeNames[i] as object); - } - menu.DropDown(dropdownRect); - } - } - else if (m_PrototypeNames.Length == 1) - { - if (GUILayout.Button(m_SubstanceStyles.iconToolbarPlus, m_SubstanceStyles.toolbarButton)) - { - m_SelectedMaterialInstanceName = GetImporter().InstantiateMaterial(m_PrototypeNames[0]); - ApplyAndRefresh(true); - } - } - - using (new EditorGUI.DisabledScope(selectedMaterial == null)) - { - // Delete selected instance - if (GUILayout.Button(m_SubstanceStyles.iconToolbarMinus, m_SubstanceStyles.toolbarButton)) - { - if (GetSortedMaterials().Length > 1) - { - SelectNextMaterial(); - importer.DestroyMaterial(selectedMaterial); - ApplyAndRefresh(true); - } - } - - // Clone selected instance - if (GUILayout.Button(m_SubstanceStyles.iconDuplicate, m_SubstanceStyles.toolbarButton)) - { - string cloneName = importer.CloneMaterial(selectedMaterial); - if (cloneName != "") - { - m_SelectedMaterialInstanceName = cloneName; - ApplyAndRefresh(true); - } - } - } - } - } EditorGUILayout.EndHorizontal(); - } - - void ApplyAndRefresh(bool exitGUI) - { - string path = AssetDatabase.GetAssetPath(target); - AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUncompressedImport); - if (exitGUI) - EditorGUIUtility.ExitGUI(); - Repaint(); - } - - // Init used for static preview rendering - void Init() - { - if (m_PreviewUtility == null) - m_PreviewUtility = new PreviewRenderUtility(); - - if (s_Meshes[0] == null) - { - GameObject handleGo = (GameObject)EditorGUIUtility.LoadRequired("Previews/PreviewMaterials.fbx"); - // @TODO: temp workaround to make it not render in the scene - handleGo.SetActive(false); - foreach (Transform t in handleGo.transform) - { - var meshFilter = t.GetComponent(); - switch (t.name) - { - case "sphere": - s_Meshes[0] = meshFilter.sharedMesh; - break; - case "cube": - s_Meshes[1] = meshFilter.sharedMesh; - break; - case "cylinder": - s_Meshes[2] = meshFilter.sharedMesh; - break; - case "torus": - s_Meshes[3] = meshFilter.sharedMesh; - break; - default: - Debug.Log("Something is wrong, weird object found: " + t.name); - break; - } - } - - s_MeshIcons[0] = EditorGUIUtility.IconContent("PreMatSphere"); - s_MeshIcons[1] = EditorGUIUtility.IconContent("PreMatCube"); - s_MeshIcons[2] = EditorGUIUtility.IconContent("PreMatCylinder"); - s_MeshIcons[3] = EditorGUIUtility.IconContent("PreMatTorus"); - - s_LightIcons[0] = EditorGUIUtility.IconContent("PreMatLight0"); - s_LightIcons[1] = EditorGUIUtility.IconContent("PreMatLight1"); - } - } - - // Note that the static preview for the package is completely different than the dynamic preview. - // The static preview makes a single image of all the substances, while the dynamic preview - // redirects to the MaterialEditor dynamic preview for the selected substance. - public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - return null; - - Init(); - - m_PreviewUtility.BeginStaticPreview(new Rect(0, 0, width, height)); - - DoRenderPreview(subAssets); - - return m_PreviewUtility.EndStaticPreview(); - } - - // Used for static preview only. See note above. - protected void DoRenderPreview(Object[] subAssets) - { - if (m_PreviewUtility.renderTexture.width <= 0 || m_PreviewUtility.renderTexture.height <= 0) - return; - - List materials = new List(); - foreach (Object obj in subAssets) - if (obj is ProceduralMaterial) - materials.Add(obj as ProceduralMaterial); - - int rows = 1; - int cols = 1; - while (cols * cols < materials.Count) - cols++; - rows = Mathf.CeilToInt(materials.Count / (float)cols); - - m_PreviewUtility.camera.transform.position = -Vector3.forward * 5 * cols; - m_PreviewUtility.camera.transform.rotation = Quaternion.identity; - m_PreviewUtility.camera.farClipPlane = 5 * cols + 5.0f; - m_PreviewUtility.camera.nearClipPlane = 5 * cols - 3.0f; - m_PreviewUtility.ambientColor = new Color(.2f, .2f, .2f, 0); - if (lightMode == 0) - { - m_PreviewUtility.lights[0].intensity = 1.0f; - m_PreviewUtility.lights[0].transform.rotation = Quaternion.Euler(30f, 30f, 0); - m_PreviewUtility.lights[1].intensity = 0; - } - else - { - m_PreviewUtility.lights[0].intensity = 1.0f; - m_PreviewUtility.lights[0].transform.rotation = Quaternion.Euler(50f, 50f, 0); - m_PreviewUtility.lights[1].intensity = 1.0f; - } - - for (int i = 0; i < materials.Count; i++) - { - ProceduralMaterial mat = materials[i]; - Vector3 pos = new Vector3(i % cols - (cols - 1) * 0.5f, -i / cols + (rows - 1) * 0.5f, 0); - pos *= Mathf.Tan(m_PreviewUtility.camera.fieldOfView * 0.5f * Mathf.Deg2Rad) * 5 * 2; - m_PreviewUtility.DrawMesh(s_Meshes[selectedMesh], pos, Quaternion.Euler(previewDir.y, 0, 0) * Quaternion.Euler(0, previewDir.x, 0), mat, 0); - } - - m_PreviewUtility.Render(); - } - } -} diff --git a/Editor/Mono/Inspector/AddComponent/AddComponentDataSource.cs b/Editor/Mono/Inspector/AddComponent/AddComponentDataSource.cs new file mode 100644 index 0000000000..0c80858a4a --- /dev/null +++ b/Editor/Mono/Inspector/AddComponent/AddComponentDataSource.cs @@ -0,0 +1,107 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Collections.Generic; +using System.Linq; + +namespace UnityEditor +{ + internal class AddComponentDataSource : AdvancedDropdownDataSource + { + protected override AdvancedDropdownItem FetchData() + { + return RebuildTree(); + } + + protected AdvancedDropdownItem RebuildTree() + { + AdvancedDropdownItem root = new ComponentDropdownItem(); + var menuDictionary = GetMenuDictionary(); + menuDictionary.Sort(CompareItems); + for (var i = 0; i < menuDictionary.Count; i++) + { + var menu = menuDictionary[i]; + if (menu.Value == "ADD") + { + continue; + } + + var menuPath = menu.Key; + var paths = menuPath.Split('/'); + + var parent = root; + for (var j = 0; j < paths.Length; j++) + { + var path = paths[j]; + if (j == paths.Length - 1) + { + var element = new ComponentDropdownItem(LocalizationDatabase.GetLocalizedString(path), menuPath, menu.Value); + element.searchable = true; + element.SetParent(parent); + parent.AddChild(element); + continue; + } + var group = parent.children.SingleOrDefault(c => c.name == path); + if (group == null) + { + group = new ComponentDropdownItem(path, -1); + group.SetParent(parent); + parent.AddChild(group); + } + parent = group; + } + } + root = root.children.Single(); + root.SetParent(null); + var newScript = new ComponentDropdownItem("New script", -1); + newScript.AddChild(new NewScriptDropdownItem()); + newScript.SetParent(root); + root.AddChild(newScript); + return root; + } + + private static List> GetMenuDictionary() + { + var menus = Unsupported.GetSubmenus("Component"); + var commands = Unsupported.GetSubmenusCommands("Component"); + + var menuDictionary = new Dictionary(menus.Length); + for (var i = 0; i < menus.Length; i++) + { + menuDictionary.Add(menus[i], commands[i]); + } + return menuDictionary.ToList(); + } + + private int CompareItems(KeyValuePair x, KeyValuePair y) + { + var legacyString = "legacy"; + var isStr1Legacy = x.Key.ToLower().Contains(legacyString); + var isStr2Legacy = y.Key.ToLower().Contains(legacyString); + if (isStr1Legacy && isStr2Legacy) + return x.Key.CompareTo(y.Key); + if (isStr1Legacy) + return 1; + if (isStr2Legacy) + return -1; + return x.Key.CompareTo(y.Key); + } + + protected override AdvancedDropdownItem Search(string searchString) + { + var searchTree = base.Search(searchString); + if (searchTree != null) + { + var addNewScriptGroup = new ComponentDropdownItem("New script", -1); + var addNewScript = new NewScriptDropdownItem(); + addNewScript.className = searchString; + addNewScriptGroup.AddChild(addNewScript); + addNewScript.SetParent(addNewScriptGroup); + addNewScriptGroup.SetParent(searchTree); + searchTree.AddChild(addNewScriptGroup); + } + return searchTree; + } + } +} diff --git a/Editor/Mono/Inspector/AddComponent/AddComponentGUI.cs b/Editor/Mono/Inspector/AddComponent/AddComponentGUI.cs new file mode 100644 index 0000000000..e229487736 --- /dev/null +++ b/Editor/Mono/Inspector/AddComponent/AddComponentGUI.cs @@ -0,0 +1,65 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using UnityEngine; + +namespace UnityEditor +{ + internal class AddComponentGUI : AdvancedDropdownGUI + { + private Vector2 m_IconSize = new Vector2(16, 16); + public override Vector2 iconSize => m_IconSize; + + public override void DrawItem(AdvancedDropdownItem item, bool selected, bool hasSearch) + { + var nsItem = item as NewScriptDropdownItem; + if (nsItem == null) + { + base.DrawItem(item, selected, hasSearch); + return; + } + + GUILayout.Label("Name", EditorStyles.label); + + EditorGUI.FocusTextInControl("NewScriptName"); + GUI.SetNextControlName("NewScriptName"); + + nsItem.m_ClassName = EditorGUILayout.TextField(nsItem.m_ClassName); + + EditorGUILayout.Space(); + + EditorGUILayout.EnumPopup("Language", NewScriptDropdownItem.Language.CSharp); + + EditorGUILayout.Space(); + + var canCreate = nsItem.CanCreate(); + if (!canCreate && nsItem.m_ClassName != "") + GUILayout.Label(nsItem.GetError(), EditorStyles.helpBox); + + GUILayout.FlexibleSpace(); + + using (new EditorGUI.DisabledScope(!canCreate)) + { + if (GUILayout.Button("Create and Add")) + { + nsItem.Create(AddComponentWindow.s_AddComponentWindow.m_GameObjects); + } + } + + EditorGUILayout.Space(); + } + + internal override string DrawSearchFieldControl(string searchString) + { + float padding = 8f; + m_SearchRect = GUILayoutUtility.GetRect(0, 0); + m_SearchRect.x += padding; + m_SearchRect.y = 7; + m_SearchRect.width -= padding * 2; + m_SearchRect.height = 30; + var newSearch = EditorGUI.SearchField(m_SearchRect, searchString); + return newSearch; + } + } +} diff --git a/Editor/Mono/Inspector/AddComponent/AddComponentWindow.cs b/Editor/Mono/Inspector/AddComponent/AddComponentWindow.cs index 68699b519d..e7e6208cf6 100644 --- a/Editor/Mono/Inspector/AddComponent/AddComponentWindow.cs +++ b/Editor/Mono/Inspector/AddComponent/AddComponentWindow.cs @@ -3,12 +3,8 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; -using System.IO; -using System.Linq; using UnityEngine; -using UnityEditorInternal; using UnityEngine.Scripting; -using Object = UnityEngine.Object; namespace UnityEditor { @@ -37,9 +33,9 @@ protected override bool isSearchFieldDisabled { get { - var child = CurrentlyRenderedTree.GetSelectedChild(); + var child = m_CurrentlyRenderedTree.GetSelectedChild(); if (child != null) - return child is NewScriptDropdownElement; + return child is NewScriptDropdownItem; return false; } } @@ -47,8 +43,11 @@ protected override bool isSearchFieldDisabled protected override void OnEnable() { base.OnEnable(); + gui = new AddComponentGUI(); + dataSource = new AddComponentDataSource(); s_AddComponentWindow = this; m_Search = EditorPrefs.GetString(kComponentSearch, ""); + showHeader = true; } protected override void OnDisable() @@ -70,8 +69,8 @@ internal static bool Show(Rect rect, GameObject[] gos) protected override bool SpecialKeyboardHandling(Event evt) { - var createScriptMenu = CurrentlyRenderedTree.GetSelectedChild(); - if (createScriptMenu is NewScriptDropdownElement) + var createScriptMenu = m_CurrentlyRenderedTree.GetSelectedChild(); + if (createScriptMenu is NewScriptDropdownItem) { // When creating new script name we want to dedicate both left/right arrow and backspace // to editing the script name so they can't be used for navigating the menus. @@ -92,90 +91,12 @@ protected override bool SpecialKeyboardHandling(Event evt) return false; } - protected override DropdownElement RebuildTree() - { - var root = new DropdownElement("ROOT"); - var menus = Unsupported.GetSubmenus("Component"); - var commands = Unsupported.GetSubmenusCommands("Component"); - for (var i = 0; i < menus.Length; i++) - { - if (commands[i] == "ADD") - { - continue; - } - - var menuPath = menus[i]; - var paths = menuPath.Split('/'); - - var parent = root; - for (var j = 0; j < paths.Length; j++) - { - var path = paths[j]; - if (j == paths.Length - 1) - { - var element = new ComponentDropdownElement(LocalizationDatabase.GetLocalizedString(path), menuPath, commands[i]); - element.SetParent(parent); - parent.AddChild(element); - continue; - } - var group = parent.children.SingleOrDefault(c => c.name == path); - if (group == null) - { - group = new GroupDropdownElement(path); - group.SetParent(parent); - parent.AddChild(group); - } - parent = group; - } - } - root = root.children.Single(); - root.SetParent(null); - var newScript = new GroupDropdownElement("New script"); - newScript.AddChild(new NewScriptDropdownElement()); - newScript.SetParent(root); - root.AddChild(newScript); - return root; - } - - protected override DropdownElement RebuildSearch() - { - var searchTree = base.RebuildSearch(); - - if (searchTree != null) - { - var addNewScriptGroup = new GroupDropdownElement("New script"); - var addNewScript = new NewScriptDropdownElement(); - addNewScript.className = m_Search; - addNewScriptGroup.AddChild(addNewScript); - addNewScript.SetParent(addNewScriptGroup); - addNewScriptGroup.SetParent(searchTree); - searchTree.AddChild(addNewScriptGroup); - } - return searchTree; - } - internal static void SendUsabilityAnalyticsEvent(AnalyticsEventData eventData) { var openTime = s_AddComponentWindow.m_ComponentOpenTime; UsabilityAnalytics.SendEvent("executeAddComponentWindow", openTime, DateTime.UtcNow - openTime, false, eventData); } - private static void CloseAllOpenWindows() - { - var windows = Resources.FindObjectsOfTypeAll(typeof(T)); - foreach (var window in windows) - { - try - { - ((EditorWindow)window).Close(); - } - catch - { - DestroyImmediate(window); - } - } - } - [UsedByNativeCode] internal static bool ValidateAddComponentMenuItem() { diff --git a/Editor/Mono/Inspector/AddComponent/ComponentDropdownElement.cs b/Editor/Mono/Inspector/AddComponent/ComponentDropdownItem.cs similarity index 69% rename from Editor/Mono/Inspector/AddComponent/ComponentDropdownElement.cs rename to Editor/Mono/Inspector/AddComponent/ComponentDropdownItem.cs index 0459741b69..7ed47e5d00 100644 --- a/Editor/Mono/Inspector/AddComponent/ComponentDropdownElement.cs +++ b/Editor/Mono/Inspector/AddComponent/ComponentDropdownItem.cs @@ -6,21 +6,37 @@ namespace UnityEditor { - internal class ComponentDropdownElement : DropdownElement + internal class ComponentDropdownItem : AdvancedDropdownItem { private string m_MenuPath; - private string m_Command; private bool m_IsLegacy; - protected override bool isSearchable + private static class Styles + { + public static GUIStyle itemStyle = new GUIStyle("PR Label"); + + static Styles() + { + itemStyle.alignment = TextAnchor.MiddleLeft; + itemStyle.padding.left = 0; + itemStyle.fixedHeight = 20; + itemStyle.margin = new RectOffset(0, 0, 0, 0); + } + } + + public override GUIStyle lineStyle => Styles.itemStyle; + + internal ComponentDropdownItem() : base("ROOT", -1) + { + } + + public ComponentDropdownItem(string path, int menuPath) : base(path, menuPath) { - get { return true; } } - public ComponentDropdownElement(string name, string menuPath, string command) : base(name) + public ComponentDropdownItem(string name, string menuPath, string command) : base(name, -1) { m_MenuPath = menuPath; - m_Command = command; m_IsLegacy = menuPath.Contains("Legacy"); if (command.StartsWith("SCRIPT")) @@ -44,10 +60,10 @@ public ComponentDropdownElement(string name, string menuPath, string command) : public override int CompareTo(object o) { - if (o is ComponentDropdownElement) + if (o is ComponentDropdownItem) { // legacy elements should always come after non legacy elements - var componentElement = (ComponentDropdownElement)o; + var componentElement = (ComponentDropdownItem)o; if (m_IsLegacy && !componentElement.m_IsLegacy) return 1; if (!m_IsLegacy && componentElement.m_IsLegacy) @@ -72,7 +88,7 @@ public override bool OnAction() public override string ToString() { - return m_MenuPath + m_Command; + return m_MenuPath; } } } diff --git a/Editor/Mono/Inspector/AddComponent/NewScriptDropdownElement.cs b/Editor/Mono/Inspector/AddComponent/NewScriptDropdownItem.cs similarity index 76% rename from Editor/Mono/Inspector/AddComponent/NewScriptDropdownElement.cs rename to Editor/Mono/Inspector/AddComponent/NewScriptDropdownItem.cs index 2435330dac..33a9833dd7 100644 --- a/Editor/Mono/Inspector/AddComponent/NewScriptDropdownElement.cs +++ b/Editor/Mono/Inspector/AddComponent/NewScriptDropdownItem.cs @@ -10,7 +10,7 @@ namespace UnityEditor { - class NewScriptDropdownElement : DropdownElement + class NewScriptDropdownItem : AdvancedDropdownItem { private readonly char[] kInvalidPathChars = new char[] {'<', '>', ':', '"', '|', '?', '*', (char)0}; private readonly char[] kPathSepChars = new char[] {'/', '\\'}; @@ -18,7 +18,7 @@ class NewScriptDropdownElement : DropdownElement private string m_Directory = string.Empty; - private string m_ClassName = "NewBehaviourScript"; + internal string m_ClassName = "NewBehaviourScript"; public string className { @@ -26,44 +26,12 @@ public string className get { return m_ClassName; } } - private enum Language + internal enum Language { CSharp = 0 } - public NewScriptDropdownElement() : base("New Script") {} - - public override void Draw(bool selected, bool isSearching) - { - GUILayout.Label("Name", EditorStyles.label); - - EditorGUI.FocusTextInControl("NewScriptName"); - GUI.SetNextControlName("NewScriptName"); - - m_ClassName = EditorGUILayout.TextField(m_ClassName); - - EditorGUILayout.Space(); - - EditorGUILayout.EnumPopup("Language", Language.CSharp); - - EditorGUILayout.Space(); - - var canCreate = CanCreate(); - if (!canCreate && m_ClassName != "") - GUILayout.Label(GetError(), EditorStyles.helpBox); - - GUILayout.FlexibleSpace(); - - using (new EditorGUI.DisabledScope(!canCreate)) - { - if (GUILayout.Button("Create and Add")) - { - Create(AddComponentWindow.s_AddComponentWindow.m_GameObjects); - } - } - - EditorGUILayout.Space(); - } + public NewScriptDropdownItem() : base("New Script", -1) {} public override bool OnAction() { @@ -72,7 +40,7 @@ public override bool OnAction() return true; } - private bool CanCreate() + internal bool CanCreate() { return m_ClassName.Length > 0 && !File.Exists(TargetPath()) && @@ -81,7 +49,7 @@ private bool CanCreate() !InvalidTargetPath(); } - private string GetError() + public string GetError() { // Create string to tell the user what the problem is var blockReason = string.Empty; @@ -99,7 +67,7 @@ private string GetError() return blockReason; } - private void Create(GameObject[] gameObjects) + internal void Create(GameObject[] gameObjects) { if (!CanCreate()) return; diff --git a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownDataSource.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownDataSource.cs new file mode 100644 index 0000000000..76a3a39cfb --- /dev/null +++ b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownDataSource.cs @@ -0,0 +1,93 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Collections.Generic; + +namespace UnityEditor +{ + internal abstract class AdvancedDropdownDataSource + { + private const string kSearchHeader = "Search"; + + private AdvancedDropdownItem m_MainTree; + private AdvancedDropdownItem m_SearchTree; + + public AdvancedDropdownItem mainTree { get { return m_MainTree; }} + public AdvancedDropdownItem searchTree { get { return m_SearchTree; }} + + public void ReloadData() + { + m_MainTree = FetchData(); + } + + protected abstract AdvancedDropdownItem FetchData(); + + public void RebuildSearch(string search) + { + m_SearchTree = Search(search); + } + + virtual protected AdvancedDropdownItem Search(string searchString) + { + if (string.IsNullOrEmpty(searchString)) + return null; + + // Support multiple search words separated by spaces. + var searchWords = searchString.ToLower().Split(' '); + + // We keep two lists. Matches that matches the start of an item always get first priority. + var matchesStart = new List(); + var matchesWithin = new List(); + + foreach (var e in m_MainTree.GetSearchableElements()) + { + var name = e.name.ToLower().Replace(" ", ""); + + var didMatchAll = true; + var didMatchStart = false; + + // See if we match ALL the seaarch words. + for (var w = 0; w < searchWords.Length; w++) + { + var search = searchWords[w]; + if (name.Contains(search)) + { + // If the start of the item matches the first search word, make a note of that. + if (w == 0 && name.StartsWith(search)) + didMatchStart = true; + } + else + { + // As soon as any word is not matched, we disregard this item. + didMatchAll = false; + break; + } + } + // We always need to match all search words. + // If we ALSO matched the start, this item gets priority. + if (didMatchAll) + { + if (didMatchStart) + matchesStart.Add(e); + else + matchesWithin.Add(e); + } + } + + matchesStart.Sort(); + matchesWithin.Sort(); + + var searchTree = new AdvancedDropdownItem(kSearchHeader, -1); + foreach (var element in matchesStart) + { + searchTree.AddChild(element); + } + foreach (var element in matchesWithin) + { + searchTree.AddChild(element); + } + return searchTree; + } + } +} diff --git a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs new file mode 100644 index 0000000000..1939131d15 --- /dev/null +++ b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs @@ -0,0 +1,151 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine; +using Event = UnityEngine.Event; + +namespace UnityEditor +{ + internal class AdvancedDropdownGUI + { + protected static class Styles + { + public static GUIStyle header = new GUIStyle(EditorStyles.inspectorBig); + public static GUIStyle rightArrow = "AC RightArrow"; + public static GUIStyle leftArrow = "AC LeftArrow"; + public static GUIStyle lineSeparator = new GUIStyle(); + + static Styles() + { + header.font = EditorStyles.boldLabel.font; + header.margin = new RectOffset(0, 0, 0, 0); + + lineSeparator.fixedHeight = 1; + lineSeparator.margin.bottom = 2; + lineSeparator.margin.top = 2; + } + } + + protected Rect m_SearchRect; + public virtual float HeaderHeight => m_SearchRect.height; + + private const int kWindowHeight = 395 - 80; + public virtual float WindowHeight => kWindowHeight; + + //This should ideally match line height + private Vector2 s_IconSize = new Vector2(13, 13); + public virtual Vector2 iconSize => s_IconSize; + + public virtual void DrawItem(AdvancedDropdownItem item, bool selected, bool hasSearch) + { + if (item.IsSeparator()) + { + DrawLineSeparator(); + return; + } + + var content = !hasSearch ? item.content : item.contentWhenSearching; + var rect = GUILayoutUtility.GetRect(content, item.lineStyle, GUILayout.ExpandWidth(true)); + if (item.IsSeparator() || Event.current.type != EventType.Repaint) + return; + + if (content.image == null) + { + item.lineStyle.Draw(rect, GUIContent.none, false, false, selected, selected); + rect.x += iconSize.x; + rect.width -= iconSize.x; + } + item.lineStyle.Draw(rect, content, false, false, selected, selected); + if (item.drawArrow) + { + var size = Styles.rightArrow.lineHeight; + var yOffset = item.lineStyle.fixedHeight / 2 - size / 2; + Rect arrowRect = new Rect(rect.x + rect.width - size, rect.y + yOffset, size, size); + Styles.rightArrow.Draw(arrowRect, false, false, false, false); + } + } + + protected virtual void DrawLineSeparator() + { + var rect = GUILayoutUtility.GetRect(GUIContent.none, Styles.lineSeparator, GUILayout.ExpandWidth(true)); + if (Event.current.type != EventType.Repaint) + return; + EditorGUIUtility.DrawVerticalSplitter(rect); + } + + public void DrawHeader(AdvancedDropdownItem group, Action backButtonPressed) + { + var content = GUIContent.Temp(group.name); + var headerRect = GUILayoutUtility.GetRect(content, Styles.header, GUILayout.ExpandWidth(true)); + + if (Event.current.type == EventType.Repaint) + Styles.header.Draw(headerRect, content, false, false, false, false); + + // Back button + if (group.parent != null) + { + var arrowSize = 13; + var y = headerRect.y + (headerRect.height / 2 - arrowSize / 2); + var arrowRect = new Rect(headerRect.x + 4, y, arrowSize, arrowSize); + if (Event.current.type == EventType.Repaint) + Styles.leftArrow.Draw(arrowRect, false, false, false, false); + if (Event.current.type == EventType.MouseDown && headerRect.Contains(Event.current.mousePosition)) + { + backButtonPressed(); + Event.current.Use(); + } + } + } + + public void DrawSearchField(bool isSearchFieldDisabled, string searchString, Action searchChanged) + { + if (!isSearchFieldDisabled) + { + EditorGUI.FocusTextInControl("ComponentSearch"); + } + + using (new EditorGUI.DisabledScope(isSearchFieldDisabled)) + { + GUI.SetNextControlName("ComponentSearch"); + + var newSearch = DrawSearchFieldControl(searchString); + + if (newSearch != searchString) + { + searchChanged(newSearch); + } + } + } + + internal virtual string DrawSearchFieldControl(string searchString) + { + var paddingX = 8f; + var paddingY = 2f; + m_SearchRect = GUILayoutUtility.GetRect(0, 0); + m_SearchRect.x += paddingX; + m_SearchRect.y += paddingY; + m_SearchRect.height = EditorStyles.toolbarSearchField.fixedHeight + paddingY * 2; + // Adjust to the frame + m_SearchRect.y += 1; + m_SearchRect.height += 1; + m_SearchRect.width -= paddingX * 2; + var newSearch = EditorGUI.ToolbarSearchField(m_SearchRect, searchString, false); + return newSearch; + } + + public Rect GetAnimRect(Rect position, float anim) + { + // Calculate rect for animated area + var rect = new Rect(position); + rect.x = position.width * anim; + rect.y = HeaderHeight; + rect.height -= HeaderHeight; + // Adjust to the frame + rect.x += 1; + rect.width -= 2; + return rect; + } + } +} diff --git a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownItem.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownItem.cs new file mode 100644 index 0000000000..c40e5e010b --- /dev/null +++ b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownItem.cs @@ -0,0 +1,202 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Event = UnityEngine.Event; +using Object = UnityEngine.Object; + +namespace UnityEditor +{ + internal class AdvancedDropdownItem : IComparable + { + internal static AdvancedDropdownItem s_SeparatorItem = new SeparatorDropdownItem(); + + private static class Styles + { + public static GUIStyle itemStyle = new GUIStyle("PR Label"); + + static Styles() + { + itemStyle.alignment = TextAnchor.MiddleLeft; + itemStyle.padding = new RectOffset(0, 0, 2, 2); + itemStyle.margin = new RectOffset(0, 0, 0, 0); + } + } + + public virtual GUIStyle lineStyle => Styles.itemStyle; + + protected GUIContent m_Content; + public virtual GUIContent content => m_Content; + + protected GUIContent m_ContentWhenSearching; + public virtual GUIContent contentWhenSearching => m_ContentWhenSearching; + + private string m_Name; + public string name => m_Name; + + private string m_Id; + public string id => m_Id; + + private AdvancedDropdownItem m_Parent; + public virtual AdvancedDropdownItem parent => m_Parent; + + private List m_Children = new List(); + public virtual List children => m_Children; + + public bool hasChildren => children.Any(); + public virtual bool drawArrow => hasChildren; + + public virtual bool searchable { get; set; } + + internal int m_Index = -1; + internal Vector2 m_Scroll; + internal int m_SelectedItem = 0; + + public int selectedItem + { + get { return m_SelectedItem; } + set + { + if (value < 0) + { + m_SelectedItem = 0; + } + else if (value >= children.Count) + { + m_SelectedItem = children.Count - 1; + } + else + { + m_SelectedItem = value; + } + } + } + + public AdvancedDropdownItem(string name, int index) : this(name, name, index) + { + } + + public AdvancedDropdownItem(string name, string id, int index) + { + m_Content = new GUIContent(name); + m_ContentWhenSearching = new GUIContent(id); + m_Name = name; + m_Id = id; + m_Index = index; + } + + public AdvancedDropdownItem(GUIContent content, int index) : this(content, content, index) + { + } + + public AdvancedDropdownItem(GUIContent content, GUIContent contentWhenSearching, int index) + { + m_Content = content; + m_ContentWhenSearching = contentWhenSearching; + m_Name = content.text; + m_Id = contentWhenSearching.text; + m_Index = index; + } + + internal void AddChild(AdvancedDropdownItem item) + { + children.Add(item); + } + + internal void SetParent(AdvancedDropdownItem item) + { + m_Parent = item; + } + + internal void AddSeparator() + { + children.Add(s_SeparatorItem); + } + + internal virtual bool IsSeparator() + { + return false; + } + + public virtual bool OnAction() + { + return true; + } + + public AdvancedDropdownItem GetSelectedChild() + { + if (children.Count == 0 || m_SelectedItem < 0) + return null; + return children[m_SelectedItem]; + } + + public int GetSelectedChildIndex() + { + var i = children[m_SelectedItem].m_Index; + if (i >= 0) + { + return i; + } + return m_SelectedItem; + } + + public IEnumerable GetSearchableElements() + { + if (searchable) + yield return this; + foreach (var child in children) + { + foreach (var searchableChildren in child.GetSearchableElements()) + { + yield return searchableChildren; + } + } + } + + public virtual int CompareTo(object o) + { + return name.CompareTo((o as AdvancedDropdownItem).name); + } + + public void MoveDownSelection() + { + var selectedIndex = selectedItem; + do + { + ++selectedIndex; + } + while (selectedIndex < children.Count && children[selectedIndex].IsSeparator()); + + if (selectedIndex < children.Count) + selectedItem = selectedIndex; + } + + public void MoveUpSelection() + { + var selectedIndex = selectedItem; + do + { + --selectedIndex; + } + while (selectedIndex >= 0 && children[selectedIndex].IsSeparator()); + if (selectedIndex >= 0) + selectedItem = selectedIndex; + } + + class SeparatorDropdownItem : AdvancedDropdownItem + { + public SeparatorDropdownItem() : base("SEPARATOR", -1) + { + } + + internal override bool IsSeparator() + { + return true; + } + } + } +} diff --git a/Editor/Mono/Inspector/SearchableDropdown/AdvancedDropdown.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownSimpleDataSource.cs similarity index 75% rename from Editor/Mono/Inspector/SearchableDropdown/AdvancedDropdown.cs rename to Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownSimpleDataSource.cs index 6e1301a68d..bd68193e3b 100644 --- a/Editor/Mono/Inspector/SearchableDropdown/AdvancedDropdown.cs +++ b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownSimpleDataSource.cs @@ -2,13 +2,11 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License -using System.Collections.Generic; using System.Linq; -using UnityEngine; namespace UnityEditor { - class AdvancedDropdown : AdvancedDropdownWindow + internal class AdvancedDropdownSimpleDataSource : AdvancedDropdownDataSource { private string[] m_DisplayedOptions; public string[] DisplayedOptions {set { m_DisplayedOptions = value; }} @@ -19,33 +17,34 @@ class AdvancedDropdown : AdvancedDropdownWindow private static int m_SelectedIndex; public int SelectedIndex { set { m_SelectedIndex = value; } } - protected override DropdownElement RebuildTree() + protected override AdvancedDropdownItem FetchData() { - var rootGroup = new GroupDropdownElement(m_Label); + var rootGroup = new AdvancedDropdownItem(m_Label, -1); for (int i = 0; i < m_DisplayedOptions.Length; i++) { var menuPath = m_DisplayedOptions[i]; var paths = menuPath.Split('/'); - DropdownElement parent = rootGroup; + AdvancedDropdownItem parent = rootGroup; for (var j = 0; j < paths.Length; j++) { var path = paths[j]; if (j == paths.Length - 1) { - var element = new SearchableDropdownElement(path, menuPath, i); + var element = new AdvancedDropdownItem(path, menuPath, i); + element.searchable = true; element.SetParent(parent); parent.AddChild(element); if (i == m_SelectedIndex) { var tempParent = parent; - DropdownElement searchedElement = element; + AdvancedDropdownItem searchedItem = element; while (tempParent != null) { - tempParent.selectedItem = tempParent.children.IndexOf(searchedElement); - searchedElement = tempParent; + tempParent.selectedItem = tempParent.children.IndexOf(searchedItem); + searchedItem = tempParent; tempParent = tempParent.parent; } } @@ -59,7 +58,7 @@ protected override DropdownElement RebuildTree() var group = parent.children.SingleOrDefault(c => c.id == groupPathId); if (group == null) { - group = new GroupDropdownElement(path, groupPathId); + group = new AdvancedDropdownItem(path, groupPathId, -1); group.SetParent(parent); parent.AddChild(group); } diff --git a/Editor/Mono/Inspector/SearchableDropdown/AdvancedDropdownWindow.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownWindow.cs similarity index 50% rename from Editor/Mono/Inspector/SearchableDropdown/AdvancedDropdownWindow.cs rename to Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownWindow.cs index 3d0da0c614..17a10b7db7 100644 --- a/Editor/Mono/Inspector/SearchableDropdown/AdvancedDropdownWindow.cs +++ b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownWindow.cs @@ -3,41 +3,24 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; -using System.Collections.Generic; using System.Linq; +using UnityEditor.Callbacks; using UnityEngine; using Event = UnityEngine.Event; -using Object = UnityEngine.Object; namespace UnityEditor { [InitializeOnLoad] - [Serializable] - internal abstract class AdvancedDropdownWindow : EditorWindow + internal class AdvancedDropdownWindow : EditorWindow { - protected internal static Styles s_Styles; - internal class Styles + private static class Styles { - public GUIStyle header = new GUIStyle(EditorStyles.inspectorBig); - public GUIStyle componentButton = new GUIStyle("PR Label"); - public GUIStyle groupButton; - public GUIStyle background = "grey_border"; - public GUIStyle previewHeader = new GUIStyle(EditorStyles.label); - public GUIStyle previewText = new GUIStyle(EditorStyles.wordWrappedLabel); - public GUIStyle rightArrow = "AC RightArrow"; - public GUIStyle leftArrow = "AC LeftArrow"; - - public Styles() - { - header.font = EditorStyles.boldLabel.font; - - componentButton.alignment = TextAnchor.MiddleLeft; - componentButton.padding.left -= 15; - componentButton.fixedHeight = 20; - - groupButton = new GUIStyle(componentButton); - groupButton.padding.left += 17; + public static GUIStyle background = "grey_border"; + public static GUIStyle previewHeader = new GUIStyle(EditorStyles.label); + public static GUIStyle previewText = new GUIStyle(EditorStyles.wordWrappedLabel); + static Styles() + { previewText.padding.left += 3; previewText.padding.right += 3; previewHeader.padding.left += 3 - 2; @@ -47,44 +30,25 @@ public Styles() } } - private const int kHeaderHeight = 30; - private const int kWindowHeight = 400 - 80; - private const int kHelpHeight = 80 * 0; - private const string kSearchHeader = "Search"; + protected AdvancedDropdownGUI gui = new AdvancedDropdownGUI(); + public AdvancedDropdownDataSource dataSource = new AdvancedDropdownSimpleDataSource(); - private DropdownElement m_MainTree; - private DropdownElement m_SearchTree; - protected DropdownElement CurrentlyRenderedTree - { - get - { - return hasSearch ? m_SearchTree : m_MainTree; - } - set - { - if (hasSearch) - { - m_SearchTree = value; - } - else - { - m_MainTree = value; - } - } - } + protected AdvancedDropdownItem m_CurrentlyRenderedTree; - private DropdownElement m_AnimationTree; + private AdvancedDropdownItem m_AnimationTree; private float m_NewAnimTarget = 0; private long m_LastTime = 0; private bool m_ScrollToSelected = true; + + [NonSerialized] private bool m_DirtyList = true; protected string m_Search = ""; private bool hasSearch { get { return !string.IsNullOrEmpty(m_Search); } } public event Action onSelected; + public bool showHeader { get; set; } = true; - protected abstract DropdownElement RebuildTree(); protected virtual bool isSearchFieldDisabled { get; } protected virtual void OnEnable() @@ -109,8 +73,10 @@ public void Init(Rect buttonRect) buttonRect = GUIUtility.GUIToScreenRect(buttonRect); OnDirtyList(); + m_CurrentlyRenderedTree = hasSearch ? dataSource.searchTree : dataSource.mainTree; - ShowAsDropDown(buttonRect, new Vector2(buttonRect.width, kWindowHeight), null, ShowMode.PopupMenuWithKeyboardFocus); + + ShowAsDropDown(buttonRect, new Vector2(buttonRect.width, gui.WindowHeight), null, ShowMode.PopupMenuWithKeyboardFocus); Focus(); @@ -122,10 +88,7 @@ public void Init(Rect buttonRect) internal void OnGUI() { - if (s_Styles == null) - s_Styles = new Styles(); - - GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, s_Styles.background); + GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, Styles.background); if (m_DirtyList) { @@ -133,12 +96,8 @@ internal void OnGUI() } HandleKeyboard(); - - GUILayout.Space(7); - OnGUISearch(); - if (m_NewAnimTarget != 0 && Event.current.type == EventType.Layout) { long now = DateTime.Now.Ticks; @@ -160,13 +119,13 @@ internal void OnGUI() if (anim == 0) { - DrawDropdown(0, CurrentlyRenderedTree); + DrawDropdown(0, m_CurrentlyRenderedTree); } else if (anim < 0) { // Go to parent // m_NewAnimTarget goes -1 -> 0 - DrawDropdown(anim, CurrentlyRenderedTree); + DrawDropdown(anim, m_CurrentlyRenderedTree); DrawDropdown(anim + 1, m_AnimationTree); } else // > 0 @@ -174,41 +133,27 @@ internal void OnGUI() // Go to child // m_NewAnimTarget 1 -> 0 DrawDropdown(anim - 1 , m_AnimationTree); - DrawDropdown(anim, CurrentlyRenderedTree); + DrawDropdown(anim, m_CurrentlyRenderedTree); } } private void OnDirtyList() { m_DirtyList = false; - m_MainTree = RebuildTree(); + dataSource.ReloadData(); if (hasSearch) - m_SearchTree = RebuildSearch(); + dataSource.RebuildSearch(m_Search); } private void OnGUISearch() { - if (!isSearchFieldDisabled) - { - EditorGUI.FocusTextInControl("ComponentSearch"); - } - - var searchRect = GUILayoutUtility.GetRect(10, 20); - searchRect.x += 8; - searchRect.width -= 16; - - GUI.SetNextControlName("ComponentSearch"); - - using (new EditorGUI.DisabledScope(isSearchFieldDisabled)) - { - var newSearch = EditorGUI.SearchField(searchRect, m_Search); - - if (newSearch != m_Search) + gui.DrawSearchField(isSearchFieldDisabled, m_Search, (newSearch) => { + dataSource.RebuildSearch(newSearch); + m_CurrentlyRenderedTree = + string.IsNullOrEmpty(newSearch) ? dataSource.mainTree : dataSource.searchTree; m_Search = newSearch; - m_SearchTree = RebuildSearch(); - } - } + }); } private void HandleKeyboard() @@ -225,25 +170,25 @@ private void HandleKeyboard() // Always do these if (evt.keyCode == KeyCode.DownArrow) { - CurrentlyRenderedTree.selectedItem++; + m_CurrentlyRenderedTree.MoveDownSelection(); m_ScrollToSelected = true; evt.Use(); } if (evt.keyCode == KeyCode.UpArrow) { - CurrentlyRenderedTree.selectedItem--; + m_CurrentlyRenderedTree.MoveUpSelection(); m_ScrollToSelected = true; evt.Use(); } if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter) { - if (CurrentlyRenderedTree.GetSelectedChild().children.Any()) + if (m_CurrentlyRenderedTree.GetSelectedChild().children.Any()) { - GoToChild(CurrentlyRenderedTree); + GoToChild(m_CurrentlyRenderedTree); } else { - if (CurrentlyRenderedTree.GetSelectedChild().OnAction()) + if (m_CurrentlyRenderedTree.GetSelectedChild().OnAction()) { CloseWindow(); } @@ -261,8 +206,8 @@ private void HandleKeyboard() } if (evt.keyCode == KeyCode.RightArrow) { - if (CurrentlyRenderedTree.GetSelectedChild().children.Any()) - GoToChild(CurrentlyRenderedTree); + if (m_CurrentlyRenderedTree.GetSelectedChild().children.Any()) + GoToChild(m_CurrentlyRenderedTree); evt.Use(); } if (evt.keyCode == KeyCode.Escape) @@ -283,7 +228,7 @@ private void CloseWindow() internal string GetIdOfSelectedItem() { - return CurrentlyRenderedTree.GetSelectedChild().id; + return m_CurrentlyRenderedTree.GetSelectedChild().id; } protected virtual bool SpecialKeyboardHandling(Event evt) @@ -291,53 +236,32 @@ protected virtual bool SpecialKeyboardHandling(Event evt) return false; } - private void DrawDropdown(float anim, DropdownElement group) + private void DrawDropdown(float anim, AdvancedDropdownItem group) { - // Calculate rect for animated area - var animRect = new Rect(position); - animRect.x = 1 + (position.width * anim); - animRect.y = kHeaderHeight; - animRect.height -= kHeaderHeight + kHelpHeight; - animRect.width -= 2; - // Start of animated area (the part that moves left and right) - GUILayout.BeginArea(animRect); - + var areaPosition = position; + // Adjust to the frame + areaPosition.height -= 1; + GUILayout.BeginArea(gui.GetAnimRect(areaPosition, anim)); // Header - var headerRect = GUILayoutUtility.GetRect(10, 25); - var name = group.name; - GUI.Label(headerRect, name, s_Styles.header); - - // Back button - if (group.parent != null) - { - var arrowRect = new Rect(headerRect.x + 4, headerRect.y + 7, 13, 13); - if (Event.current.type == EventType.Repaint) - s_Styles.leftArrow.Draw(arrowRect, false, false, false, false); - if (Event.current.type == EventType.MouseDown && headerRect.Contains(Event.current.mousePosition)) - { - GoToParent(); - Event.current.Use(); - } - } + if (showHeader) + gui.DrawHeader(group, GoToParent); DrawList(group); - GUILayout.EndArea(); } - private void DrawList(DropdownElement element) + private void DrawList(AdvancedDropdownItem item) { // Start of scroll view list - element.m_Scroll = GUILayout.BeginScrollView(element.m_Scroll); - EditorGUIUtility.SetIconSize(new Vector2(16, 16)); - + item.m_Scroll = GUILayout.BeginScrollView(item.m_Scroll); + EditorGUIUtility.SetIconSize(gui.iconSize); Rect selectedRect = new Rect(); - for (var i = 0; i < element.children.Count; i++) + for (var i = 0; i < item.children.Count; i++) { - var child = element.children[i]; - bool selected = i == element.m_SelectedItem; - child.Draw(selected, hasSearch); + var child = item.children[i]; + bool selected = i == item.m_SelectedItem; + gui.DrawItem(child, selected, hasSearch); var r = GUILayoutUtility.GetLastRect(); if (selected) selectedRect = r; @@ -349,20 +273,20 @@ private void DrawList(DropdownElement element) //if (parent.selectedIndex != i && r.Contains(Event.current.mousePosition)) if (!selected && r.Contains(Event.current.mousePosition)) { - element.m_SelectedItem = i; + item.m_SelectedItem = i; Event.current.Use(); } } if (Event.current.type == EventType.MouseDown && r.Contains(Event.current.mousePosition)) { - element.m_SelectedItem = i; - if (CurrentlyRenderedTree.GetSelectedChild().children.Any()) + item.m_SelectedItem = i; + if (m_CurrentlyRenderedTree.GetSelectedChild().children.Any()) { - GoToChild(CurrentlyRenderedTree); + GoToChild(m_CurrentlyRenderedTree); } else { - if (CurrentlyRenderedTree.GetSelectedChild().OnAction()) + if (m_CurrentlyRenderedTree.GetSelectedChild().OnAction()) { CloseWindow(); GUIUtility.ExitGUI(); @@ -380,108 +304,68 @@ private void DrawList(DropdownElement element) { m_ScrollToSelected = false; Rect scrollRect = GUILayoutUtility.GetLastRect(); - if (selectedRect.yMax - scrollRect.height > element.m_Scroll.y) + if (selectedRect.yMax - scrollRect.height > item.m_Scroll.y) { - element.m_Scroll.y = selectedRect.yMax - scrollRect.height; + item.m_Scroll.y = selectedRect.yMax - scrollRect.height; Repaint(); } - if (selectedRect.y < element.m_Scroll.y) + if (selectedRect.y < item.m_Scroll.y) { - element.m_Scroll.y = selectedRect.y; + item.m_Scroll.y = selectedRect.y; Repaint(); } } } - protected virtual DropdownElement RebuildSearch() - { - if (string.IsNullOrEmpty(m_Search)) - return null; - - // Support multiple search words separated by spaces. - var searchWords = m_Search.ToLower().Split(' '); - - // We keep two lists. Matches that matches the start of an item always get first priority. - var matchesStart = new List(); - var matchesWithin = new List(); - - foreach (var e in m_MainTree.GetSearchableElements()) - { - var name = e.name.ToLower().Replace(" ", ""); - - var didMatchAll = true; - var didMatchStart = false; - - // See if we match ALL the seaarch words. - for (var w = 0; w < searchWords.Length; w++) - { - var search = searchWords[w]; - if (name.Contains(search)) - { - // If the start of the item matches the first search word, make a note of that. - if (w == 0 && name.StartsWith(search)) - didMatchStart = true; - } - else - { - // As soon as any word is not matched, we disregard this item. - didMatchAll = false; - break; - } - } - // We always need to match all search words. - // If we ALSO matched the start, this item gets priority. - if (didMatchAll) - { - if (didMatchStart) - matchesStart.Add(e); - else - matchesWithin.Add(e); - } - } - - matchesStart.Sort(); - matchesWithin.Sort(); - - var searchTree = new GroupDropdownElement(kSearchHeader); - foreach (var element in matchesStart) - { - searchTree.AddChild(element); - } - foreach (var element in matchesWithin) - { - searchTree.AddChild(element); - } - return searchTree; - } - protected void GoToParent() { - if (CurrentlyRenderedTree.parent == null) + if (m_CurrentlyRenderedTree.parent == null) return; m_LastTime = System.DateTime.Now.Ticks; if (m_NewAnimTarget > 0) m_NewAnimTarget = -1 + m_NewAnimTarget; else m_NewAnimTarget = -1; - m_AnimationTree = CurrentlyRenderedTree; - CurrentlyRenderedTree = CurrentlyRenderedTree.parent; + m_AnimationTree = m_CurrentlyRenderedTree; + m_CurrentlyRenderedTree = m_CurrentlyRenderedTree.parent; } - private void GoToChild(DropdownElement parent) + private void GoToChild(AdvancedDropdownItem parent) { m_LastTime = System.DateTime.Now.Ticks; if (m_NewAnimTarget < 0) m_NewAnimTarget = 1 + m_NewAnimTarget; else m_NewAnimTarget = 1; - CurrentlyRenderedTree = parent.GetSelectedChild(); + m_CurrentlyRenderedTree = parent.GetSelectedChild(); m_AnimationTree = parent; } public int GetSelectedIndex() { - return CurrentlyRenderedTree.GetSelectedChildIndex(); + return m_CurrentlyRenderedTree.GetSelectedChildIndex(); + } + + [DidReloadScripts] + private static void OnScriptReload() + { + CloseAllOpenWindows(); + } + + protected static void CloseAllOpenWindows() + { + var windows = Resources.FindObjectsOfTypeAll(typeof(T)); + foreach (var window in windows) + { + try + { + ((EditorWindow)window).Close(); + } + catch + { + DestroyImmediate(window); + } + } } } } diff --git a/Editor/Mono/Inspector/SearchableDropdown/StatefulAdvancedDropdown.cs b/Editor/Mono/Inspector/AdvancedDropdown/StatefulAdvancedDropdown.cs similarity index 71% rename from Editor/Mono/Inspector/SearchableDropdown/StatefulAdvancedDropdown.cs rename to Editor/Mono/Inspector/AdvancedDropdown/StatefulAdvancedDropdown.cs index 1e0338348a..0d91e2b983 100644 --- a/Editor/Mono/Inspector/SearchableDropdown/StatefulAdvancedDropdown.cs +++ b/Editor/Mono/Inspector/AdvancedDropdown/StatefulAdvancedDropdown.cs @@ -10,7 +10,7 @@ namespace UnityEditor internal class StatefulAdvancedDropdown { [NonSerialized] - private AdvancedDropdown s_Instance; + private AdvancedDropdownWindow s_Instance; public Action onSelected { get; set; } public string Label { get; set; } @@ -25,11 +25,15 @@ public void Show(Rect rect) s_Instance = null; } - s_Instance = ScriptableObject.CreateInstance(); + s_Instance = ScriptableObject.CreateInstance(); + + var dataSource = new AdvancedDropdownSimpleDataSource(); + dataSource.DisplayedOptions = DisplayedOptions; + dataSource.SelectedIndex = SelectedIndex; + dataSource.Label = Label; + + s_Instance.dataSource = dataSource; - s_Instance.DisplayedOptions = DisplayedOptions; - s_Instance.SelectedIndex = SelectedIndex; - s_Instance.Label = Label; s_Instance.onSelected += w => onSelected(w.GetIdOfSelectedItem()); s_Instance.Init(rect); diff --git a/Editor/Mono/Inspector/SearchableDropdown/StatelessAdvancedDropdown.cs b/Editor/Mono/Inspector/AdvancedDropdown/StatelessAdvancedDropdown.cs similarity index 85% rename from Editor/Mono/Inspector/SearchableDropdown/StatelessAdvancedDropdown.cs rename to Editor/Mono/Inspector/AdvancedDropdown/StatelessAdvancedDropdown.cs index 7441de8669..c2de7b650c 100644 --- a/Editor/Mono/Inspector/SearchableDropdown/StatelessAdvancedDropdown.cs +++ b/Editor/Mono/Inspector/AdvancedDropdown/StatelessAdvancedDropdown.cs @@ -9,13 +9,13 @@ namespace UnityEditor { internal static class StatelessAdvancedDropdown { - private static AdvancedDropdown s_Instance; + private static AdvancedDropdownWindow s_Instance; private static EditorWindow s_ParentWindow; private static bool m_WindowClosed; private static int m_Result; private static int s_CurrentControl; - private static void SearchablePopup(Rect rect, string label, int selectedIndex, string[] displayedOptions, + internal static void SearchablePopup(Rect rect, string label, int selectedIndex, string[] displayedOptions, Action onSelected) { ResetAndCreateWindow(); @@ -70,15 +70,19 @@ private static void ResetAndCreateWindow() s_Instance = null; } s_ParentWindow = EditorWindow.focusedWindow; - s_Instance = ScriptableObject.CreateInstance(); + s_Instance = ScriptableObject.CreateInstance(); m_WindowClosed = false; } private static void InitWindow(Rect rect, string label, int selectedIndex, string[] displayedOptions) { - s_Instance.DisplayedOptions = displayedOptions; - s_Instance.SelectedIndex = selectedIndex; - s_Instance.Label = label; + var dataSource = new AdvancedDropdownSimpleDataSource(); + + dataSource.DisplayedOptions = displayedOptions; + dataSource.SelectedIndex = selectedIndex; + dataSource.Label = label; + + s_Instance.dataSource = dataSource; s_Instance.onSelected += (w) => { diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index e3abb3aca3..9be9836305 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -1034,7 +1034,7 @@ private void DrawEditors(Editor[] editors) // When inspecting a material asset force visible properties (MaterialEditor can be collapsed when shown on a GameObject) if (inspectedObject is Material) { - // Find material editor. MaterialEditor is in either index 0 or 1 (ProceduralMaterialInspector is in index 0). + // Find material editor. MaterialEditor is in either index 0 or 1. for (int i = 0; i <= 1 && i < editors.Length; i++) { MaterialEditor me = editors[i] as MaterialEditor; @@ -1394,7 +1394,7 @@ internal bool ShouldCullEditor(Editor[] editors, int editorIndex) Object currentTarget = editors[editorIndex].target; // Objects that should always be hidden - if (currentTarget is SubstanceImporter || currentTarget is ParticleSystemRenderer) + if (currentTarget is ParticleSystemRenderer) return true; // Hide regular AssetImporters (but not inherited types) @@ -1629,7 +1629,9 @@ void RestoreLockStateFromSerializedData() // set the tracker to the serialized list. if it contains nulls or is empty, the tracker won't lock // this fixes case 775007 m_Tracker.SetObjectsLockedByThisTracker(m_ObjectsLockedBeforeSerialization); - m_Tracker.RebuildIfNecessary(); + // since this method likely got called during OnEnable, and rebuilding the tracker could call OnDisable on all Editors, + // some of which might not have gotten their enable yet, the rebuilding needs to happen delayed in EditorApplication.update + new DelayedCallback(tracker.RebuildIfNecessary, 0f); } } } diff --git a/Editor/Mono/Inspector/LightProbeProxyVolumeEditor.cs b/Editor/Mono/Inspector/LightProbeProxyVolumeEditor.cs index 3849cea907..dea9898f48 100644 --- a/Editor/Mono/Inspector/LightProbeProxyVolumeEditor.cs +++ b/Editor/Mono/Inspector/LightProbeProxyVolumeEditor.cs @@ -122,8 +122,9 @@ private bool noRendererWarningValue { get { - Renderer renderer = ((LightProbeProxyVolume)target).GetComponent(typeof(Renderer)) as Renderer; - return (renderer == null) && (targets.Length == 1); + var proxyVolume = (LightProbeProxyVolume)target; + Renderer renderer = proxyVolume.GetComponent(typeof(Renderer)) as Renderer; + return (renderer == null && proxyVolume.boundingBoxMode != LightProbeProxyVolume.BoundingBoxMode.Custom) && (targets.Length == 1); } } diff --git a/Editor/Mono/Inspector/MaterialEditor.cs b/Editor/Mono/Inspector/MaterialEditor.cs index cea14aad2b..c23a58cd93 100644 --- a/Editor/Mono/Inspector/MaterialEditor.cs +++ b/Editor/Mono/Inspector/MaterialEditor.cs @@ -234,7 +234,7 @@ public void SetShader(Shader newShader, bool registerUndo) } else { - // ensure e.g., ProceduralMaterialInspector correctly rebuilds textures (case 879446) + // ensure e.g., correctly rebuilt textures (case 879446) OnShaderChanged(); } } @@ -242,7 +242,6 @@ public void SetShader(Shader newShader, bool registerUndo) private void UpdateAllOpenMaterialEditors() { // copy current list contents to array in case it changes during iteration - // e.g., changing shader in ProceduralMaterialInspector will destroy/recreate editors foreach (var materialEditor in s_MaterialEditors.ToArray()) materialEditor.DetectShaderEditorNeedsUpdate(); } diff --git a/Editor/Mono/Inspector/ProceduralMaterialInspector.cs b/Editor/Mono/Inspector/ProceduralMaterialInspector.cs deleted file mode 100644 index bd8e423855..0000000000 --- a/Editor/Mono/Inspector/ProceduralMaterialInspector.cs +++ /dev/null @@ -1,1354 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -// SUBSTANCE HOOK - -using UnityEngine; -using UnityEditorInternal; -using System.Collections.Generic; -using UnityEditor.Build; - -namespace UnityEditor -{ - [CustomEditor(typeof(ProceduralMaterial))] - [CanEditMultipleObjects] - internal class ProceduralMaterialInspector : MaterialEditor - { - private static ProceduralMaterial m_Material = null; - private static SubstanceImporter m_Importer = null; - private static string[] kMaxTextureSizeStrings = { "32", "64", "128", "256", "512", "1024", "2048" }; - private static int[] kMaxTextureSizeValues = { 32, 64, 128, 256, 512, 1024, 2048 }; - private bool m_AllowTextureSizeModification = false; - private bool m_ShowTexturesSection = false; - private bool m_ShowHSLInputs = true; - private Styles m_Styles; - private static string[] kMaxLoadBehaviorStrings = { "Do nothing", "Do nothing and cache", "Build on level load", "Build on level load and cache", "Bake and keep Substance", "Bake and discard Substance" }; - private static int[] kMaxLoadBehaviorValues = { 0, 5, 1, 4, 2, 3 }; - private static string[] kTextureFormatStrings = { "Compressed", "Compressed - No Alpha", "RAW", "RAW - No Alpha" }; - private static int[] kTextureFormatValues = { 0, 2, 1, 3 }; - private bool m_MightHaveModified = false; - private static bool m_UndoWasPerformed = false; - - private static Dictionary m_GeneratingSince = new Dictionary(); - - private bool m_ReimportOnDisable = true; - - private class Styles - { - public GUIContent hslContent = EditorGUIUtility.TrTextContent("HSL Adjustment", "Hue_Shift, Saturation, Luminosity"); - public GUIContent randomSeedContent = EditorGUIUtility.TrTextContent("Random Seed", "$randomseed : the overall random aspect of the texture."); - public GUIContent randomizeButtonContent = EditorGUIUtility.TrTextContent("Randomize"); - public GUIContent generateAllOutputsContent = EditorGUIUtility.TrTextContent("Generate all outputs", "Force the generation of all Substance outputs."); - public GUIContent animatedContent = EditorGUIUtility.TrTextContent("Animation update rate", "Set the animation update rate in millisecond"); - public GUIContent defaultPlatform = EditorGUIUtility.TrTextContent("Default"); - public GUIContent targetWidth = EditorGUIUtility.TrTextContent("Target Width"); - public GUIContent targetHeight = EditorGUIUtility.TrTextContent("Target Height"); - public GUIContent textureFormat = EditorGUIUtility.TrTextContent("Format"); - public GUIContent loadBehavior = EditorGUIUtility.TrTextContent("Load Behavior"); - public GUIContent mipmapContent = EditorGUIUtility.TrTextContent("Generate Mip Maps"); - } - - // A ProceduralMaterialInspector is either created by a multi-material SubstanceImporterInspector, - // or in standalone mode. There is no way a ProceduralInspector can be moved from "parented by a - // SubstanceImporterInspector" to standalone mode in its lifetime. - // As a consequence, this is a one-way trip, no 'Enable' is needed for this. - public void DisableReimportOnDisable() - { - m_ReimportOnDisable = false; - } - - public void ReimportSubstances() - { - string[] asset_names = new string[targets.GetLength(0)]; - int i = 0; - foreach (ProceduralMaterial material in targets) - { - asset_names[i++] = AssetDatabase.GetAssetPath(material); - } - for (int j = 0; j < i; ++j) - { - SubstanceImporter importer = AssetImporter.GetAtPath(asset_names[j]) as SubstanceImporter; - if (importer && EditorUtility.IsDirty(importer.GetInstanceID())) - { - AssetDatabase.ImportAsset(asset_names[j], ImportAssetOptions.ForceUncompressedImport); - } - } - } - - public override void Awake() - { - base.Awake(); - m_ShowTexturesSection = EditorPrefs.GetBool("ProceduralShowTextures", false); - m_ReimportOnDisable = true; - // after undo, object is deselected because of reimport - // ensure all outputs are up-to-date when reselecting after an undo or redo - if (m_UndoWasPerformed) - { - m_UndoWasPerformed = false; - OnShaderChanged(); - } - m_UndoWasPerformed = false; - } - - public override void OnEnable() - { - base.OnEnable(); - Undo.undoRedoPerformed += UndoRedoPerformed; - } - - public void ReimportSubstancesIfNeeded() - { - if (m_MightHaveModified && !m_UndoWasPerformed) - { - // Reimport if required - if (!EditorApplication.isPlaying && !InternalEditorUtility.ignoreInspectorChanges) - ReimportSubstances(); - } - } - - public override void OnDisable() - { - // Warn the user if there are some unapplied import settings (output size / format / load behaviour) - // This mimics what the other asset importers do, except the ProceduralMaterialInspector does not derive - // from AssetImporter, so it's done manually here (case 707737) - ProceduralMaterial material = target as ProceduralMaterial; - if (material && m_PlatformSettings != null && HasModified()) - { - string dialogText = "Unapplied import settings for \'" + AssetDatabase.GetAssetPath(target) + "\'"; - if (EditorUtility.DisplayDialog("Unapplied import settings", dialogText, "Apply", "Revert")) - { - Apply(); - ReimportSubstances(); - } - ResetValues(); - } - - // If this inspector is a sub-inspector of a SubstanceImporterInspector, then we do not reimport the substances right now, - // but when the parent SubstanceImporterInspector is deleted instead. - if (m_ReimportOnDisable) - ReimportSubstancesIfNeeded(); - Undo.undoRedoPerformed -= UndoRedoPerformed; - base.OnDisable(); - } - - public override void UndoRedoPerformed() - { - m_UndoWasPerformed = true; - if (m_Material != null) - { - m_Material.RebuildTextures(); - } - base.UndoRedoPerformed(); - } - - protected override void OnShaderChanged() - { - // trigger reimport so that generated textures are up-to-date - foreach (ProceduralMaterial mat in targets) - { - string matPath = AssetDatabase.GetAssetPath(mat); - SubstanceImporter importer = AssetImporter.GetAtPath(matPath) as SubstanceImporter; - // some targets may be null when first selecting after reimport - if (importer != null && mat != null) - importer.OnShaderModified(mat); - } - } - - // A minimal list of settings to be shown in the Asset Store preview inspector or - // for materials extracted from asset bundles (i.e. where no importer is available) - internal void DisplayRestrictedInspector() - { - m_MightHaveModified = false; - - if (m_Styles == null) - m_Styles = new Styles(); - - // Procedural Material - ProceduralMaterial material = target as ProceduralMaterial; - // Set current material to test for changes later on - if (m_Material != material) - { - m_Material = material; - } - - ProceduralProperties(); - GUILayout.Space(15); - GeneratedTextures(); - } - - internal override void OnAssetStoreInspectorGUI() - { - DisplayRestrictedInspector(); - } - - // Don't disable the gui based on hideFlags of the targets because this editor applies changes - // back to the importer, so it's an exception. We still want to respect IsOpenForEdit() though. - internal override bool IsEnabled() { return IsOpenForEdit(); } - - internal override void OnHeaderTitleGUI(Rect titleRect, string header) - { - // Procedural Material - ProceduralMaterial material = target as ProceduralMaterial; - - // Retrieve the Substance importer - string path = AssetDatabase.GetAssetPath(target); - m_Importer = AssetImporter.GetAtPath(path) as SubstanceImporter; - - // In case the user somehow created a ProceduralMaterial manually outside of the importer - if (m_Importer == null) - return; - - string materialName = material.name; - materialName = EditorGUI.DelayedTextField(titleRect, materialName, EditorStyles.textField); - if (materialName != material.name) - { - if (m_Importer.RenameMaterial(material, materialName)) - { - AssetDatabase.ImportAsset(m_Importer.assetPath, ImportAssetOptions.ForceUncompressedImport); - GUIUtility.ExitGUI(); - } - else - { - materialName = material.name; - } - } - } - - public override void OnInspectorGUI() - { - using (new EditorGUI.DisabledScope(AnimationMode.InAnimationMode())) - { - m_MightHaveModified = true; - - if (m_Styles == null) - m_Styles = new Styles(); - - // Procedural Material - ProceduralMaterial material = target as ProceduralMaterial; - - // Retrieve the Substance importer - string path = AssetDatabase.GetAssetPath(target); - m_Importer = AssetImporter.GetAtPath(path) as SubstanceImporter; - - // In case the user somehow created a ProceduralMaterial manually outside of the importer - if (m_Importer == null) - { - DisplayRestrictedInspector(); - return; - } - - // Set current material to test for changes later on - if (m_Material != material) - { - m_Material = material; - } - - // Show Material header that also works as foldout - if (!isVisible || material.shader == null) - { - return; - } - - // Show standard GUI without substance textures - if (PropertiesGUI()) - { - OnShaderChanged(); - PropertiesChanged(); - } - - // Show input header - GUILayout.Space(5); - ProceduralProperties(); - GUILayout.Space(15); - GeneratedTextures(); - } - } - - void ProceduralProperties() - { - GUILayout.Label("Procedural Properties", EditorStyles.boldLabel, GUILayout.ExpandWidth(true)); - - // Ensure that materials are updated - foreach (ProceduralMaterial mat in targets) - { - if (mat.isProcessing) - { - Repaint(); - SceneView.RepaintAll(); - GameView.RepaintAll(); - break; - } - } - - if (targets.Length > 1) - { - GUILayout.Label("Procedural properties do not support multi-editing.", EditorStyles.wordWrappedLabel); - return; - } - - // Reset label and field widths - EditorGUIUtility.labelWidth = 0; - EditorGUIUtility.fieldWidth = 0; - - // Show inputs - - if (m_Importer != null) - { - // Display warning if substance is not supported - if (!ProceduralMaterial.isSupported) - { - GUILayout.Label("Procedural Materials are not supported on " + EditorUserBuildSettings.activeBuildTarget + ". Textures will be baked.", - EditorStyles.helpBox, GUILayout.ExpandWidth(true)); - } - - // Do not track GenerateAllOutputs/Mipmaps/AnimationUpdateRate as undo-able stuff - // Changing these actually triggers a reimport form inside the inspector, and this cannot be re-done by the Undo system - // when undo-ing a change to these properties - bool changed = GUI.changed; - using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) - { - { // Generate all outputs flag - EditorGUI.BeginChangeCheck(); - bool value = EditorGUILayout.Toggle(m_Styles.generateAllOutputsContent, m_Importer.GetGenerateAllOutputs(m_Material)); - if (EditorGUI.EndChangeCheck()) - m_Importer.SetGenerateAllOutputs(m_Material, value); - } - { // Mipmap generation flag - EditorGUI.BeginChangeCheck(); - bool value = EditorGUILayout.Toggle(m_Styles.mipmapContent, m_Importer.GetGenerateMipMaps(m_Material)); - if (EditorGUI.EndChangeCheck()) - m_Importer.SetGenerateMipMaps(m_Material, value); - } - } - if (m_Material.HasProceduralProperty("$time")) - { // Animation update rate - EditorGUI.BeginChangeCheck(); - int value = EditorGUILayout.IntField(m_Styles.animatedContent, m_Importer.GetAnimationUpdateRate(m_Material)); - if (EditorGUI.EndChangeCheck()) - m_Importer.SetAnimationUpdateRate(m_Material, value); - } - GUI.changed = changed; - } - InputOptions(m_Material); - } - - void GeneratedTextures() - { - if (targets.Length > 1) - return; - - ProceduralPropertyDescription[] inputs = m_Material.GetProceduralPropertyDescriptions(); - foreach (ProceduralPropertyDescription input in inputs) - { - if (input.name == "$outputsize") - { - m_AllowTextureSizeModification = true; - break; - } - } - - // Generated Textures foldout - string header = "Generated Textures"; - - // Ensure that textures are updated - if (ShowIsGenerating(target as ProceduralMaterial)) - header += " (Generating...)"; - - EditorGUI.BeginChangeCheck(); - m_ShowTexturesSection = EditorGUILayout.Foldout(m_ShowTexturesSection, header, true); - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetBool("ProceduralShowTextures", m_ShowTexturesSection); - - // Generated Textures section - if (m_ShowTexturesSection) - { - // Show textures - ShowProceduralTexturesGUI(m_Material); - ShowGeneratedTexturesGUI(m_Material); - - if (m_Importer != null) - { - // Show texture offset - if (HasProceduralTextureProperties(m_Material)) - OffsetScaleGUI(m_Material); - - GUILayout.Space(5f); - - // Do not allow texture modification if in play mode - using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) - { - ShowTextureSizeGUI(); - } - } - } - } - - public static bool ShowIsGenerating(ProceduralMaterial mat) - { - if (!m_GeneratingSince.ContainsKey(mat)) - m_GeneratingSince[mat] = 0; - if (mat.isProcessing) - return (Time.realtimeSinceStartup > m_GeneratingSince[mat] + 0.4f); - else - m_GeneratingSince[mat] = Time.realtimeSinceStartup; - return false; - } - - public override string GetInfoString() - { - ProceduralMaterial material = target as ProceduralMaterial; - Texture[] textures = material.GetGeneratedTextures(); - if (textures.Length == 0) - return string.Empty; - return textures[0].width + "x" + textures[0].height; - } - - public bool HasProceduralTextureProperties(Material material) - { - Shader shader = material.shader; - int count = ShaderUtil.GetPropertyCount(shader); - for (int i = 0; i < count; i++) - { - if (ShaderUtil.GetPropertyType(shader, i) != ShaderUtil.ShaderPropertyType.TexEnv) - continue; - - string name = ShaderUtil.GetPropertyName(shader, i); - Texture tex = material.GetTexture(name); - - if (SubstanceImporter.IsProceduralTextureSlot(material, tex, name)) - return true; - } - return false; - } - - protected void RecordForUndo(ProceduralMaterial material, SubstanceImporter importer, string message) - { - if (importer) - Undo.RecordObjects(new Object[] { material, importer }, message); - else - Undo.RecordObject(material, message); - } - - protected void OffsetScaleGUI(ProceduralMaterial material) - { - if (m_Importer == null || targets.Length > 1) - return; - - Vector2 scale = m_Importer.GetMaterialScale(material); - Vector2 offset = m_Importer.GetMaterialOffset(material); - Vector4 scaleAndOffset = new Vector4(scale.x, scale.y, offset.x, offset.y); - - GUILayout.BeginHorizontal(); - GUILayout.Space(10f); - Rect rect = GUILayoutUtility.GetRect(100, 10000, 2 * EditorGUI.kSingleLineHeight, 2 * EditorGUI.kSingleLineHeight); - GUILayout.EndHorizontal(); - - EditorGUI.BeginChangeCheck(); - scaleAndOffset = TextureScaleOffsetProperty(rect, scaleAndOffset); - if (EditorGUI.EndChangeCheck()) - { - RecordForUndo(material, m_Importer, "Modify " + material.name + "'s Tiling/Offset"); - m_Importer.SetMaterialScale(material, new Vector2(scaleAndOffset.x, scaleAndOffset.y)); - m_Importer.SetMaterialOffset(material, new Vector2(scaleAndOffset.z, scaleAndOffset.w)); - } - } - - protected void InputOptions(ProceduralMaterial material) - { - EditorGUI.BeginChangeCheck(); - InputsGUI(); - - if (EditorGUI.EndChangeCheck()) - { - material.RebuildTextures(); - } - } - - [MenuItem("CONTEXT/ProceduralMaterial/Reset", false, -100)] - public static void ResetSubstance(MenuCommand command) - { - // Retrieve the Substance importer - string path = AssetDatabase.GetAssetPath(command.context); - m_Importer = AssetImporter.GetAtPath(path) as SubstanceImporter; - // Reset substance - m_Importer.ResetMaterial(command.context as ProceduralMaterial); - } - - private static void ExportBitmaps(ProceduralMaterial material, bool alphaRemap) - { - // Select the output folder - string exportPath = EditorUtility.SaveFolderPanel("Set bitmap export path...", "", ""); - if (exportPath == "") - return; - - // Retrieve the Substance importer - string assetPath = AssetDatabase.GetAssetPath(material); - SubstanceImporter importer = AssetImporter.GetAtPath(assetPath) as SubstanceImporter; - // This can be null for substances that are previewed from the asset store for instance - if (importer) - { - // Export the bitmaps - importer.ExportBitmaps(material, exportPath, alphaRemap); - } - } - - [MenuItem("CONTEXT/ProceduralMaterial/Export Bitmaps (remapped alpha channels)", false)] - public static void ExportBitmapsAlphaRemap(MenuCommand command) - { - ExportBitmaps(command.context as ProceduralMaterial, true); - } - - [MenuItem("CONTEXT/ProceduralMaterial/Export Bitmaps (original alpha channels)", false)] - public static void ExportBitmapsNoAlphaRemap(MenuCommand command) - { - ExportBitmaps(command.context as ProceduralMaterial, false); - } - - [MenuItem("CONTEXT/ProceduralMaterial/Export Preset", false)] - public static void ExportPreset(MenuCommand command) - { - // Select the output folder - string exportPath = EditorUtility.SaveFolderPanel("Set preset export path...", "", ""); - if (exportPath == "") - return; - - // Retrieve the Substance importer - ProceduralMaterial material = command.context as ProceduralMaterial; - string assetPath = AssetDatabase.GetAssetPath(material); - SubstanceImporter importer = AssetImporter.GetAtPath(assetPath) as SubstanceImporter; - // This can be null for substances that are previewed from the asset store for instance - if (importer) - { - // Export the preset string - importer.ExportPreset(material, exportPath); - } - } - - protected void ShowProceduralTexturesGUI(ProceduralMaterial material) - { - if (targets.Length > 1) - return; - - EditorGUILayout.Space(); - - // Show textures - Shader shader = material.shader; - if (shader == null) - return; - EditorGUILayout.BeginHorizontal(); - - GUILayout.Space(4); - GUILayout.FlexibleSpace(); - - float spacing = 10; - bool first = true; - for (int i = 0; i < ShaderUtil.GetPropertyCount(shader); i++) - { - // Only show texture properties - if (ShaderUtil.GetPropertyType(shader, i) != ShaderUtil.ShaderPropertyType.TexEnv) - continue; - - string name = ShaderUtil.GetPropertyName(shader, i); - Texture tex = material.GetTexture(name); - - // Only show substance textures - if (!SubstanceImporter.IsProceduralTextureSlot(material, tex, name)) - continue; - - string label = ShaderUtil.GetPropertyDescription(shader, i); - - UnityEngine.Rendering.TextureDimension desiredTexdim = ShaderUtil.GetTexDim(shader, i); - System.Type t = MaterialEditor.GetTextureTypeFromDimension(desiredTexdim); - - // TODO: Move into styles class - GUIStyle styleLabel = "ObjectPickerResultsGridLabel"; - - if (first) - first = false; - else - GUILayout.Space(spacing); - - GUILayout.BeginVertical(GUILayout.Height(72 + styleLabel.fixedHeight + styleLabel.fixedHeight + 8)); - - Rect rect = EditorGUILayoutUtilityInternal.GetRect(72, 72); - - // Create object field with no "texture drop-box" - DoObjectPingField(rect, rect, EditorGUIUtility.GetControlID(12354, FocusType.Keyboard, rect), tex, t); - ShowAlphaSourceGUI(material, tex as ProceduralTexture, ref rect); - - rect.height = styleLabel.fixedHeight; - GUI.Label(rect, label, styleLabel); - - GUILayout.EndVertical(); - GUILayout.FlexibleSpace(); - } - - GUILayout.Space(4); - EditorGUILayout.EndHorizontal(); - } - - Vector2 m_ScrollPos = new Vector2(); - protected void ShowGeneratedTexturesGUI(ProceduralMaterial material) - { - if (targets.Length > 1) - return; - - if (m_Importer != null && !m_Importer.GetGenerateAllOutputs(m_Material)) - return; - - GUIStyle styleLabel = "ObjectPickerResultsGridLabel"; - EditorGUILayout.Space(); - GUILayout.FlexibleSpace(); - m_ScrollPos = EditorGUILayout.BeginScrollView(m_ScrollPos, GUILayout.Height(64 + styleLabel.fixedHeight + styleLabel.fixedHeight + 16)); - EditorGUILayout.BeginHorizontal(); - - GUILayout.FlexibleSpace(); - - float spacing = 10; - Texture[] textures = material.GetGeneratedTextures(); - foreach (Texture texture in textures) - { - ProceduralTexture procTex = texture as ProceduralTexture; - if (procTex != null) - { - // This hard space is there so that textures do not touch even when the inspector is really narrow, - // even if we are already in a FlexibleSpace-enclosed block. - GUILayout.Space(spacing); - - GUILayout.BeginVertical(GUILayout.Height(64 + styleLabel.fixedHeight + 8)); - - Rect rect = EditorGUILayoutUtilityInternal.GetRect(64, 64); - - // Create object field with no "texture drop-box" - DoObjectPingField(rect, rect, EditorGUIUtility.GetControlID(12354, FocusType.Keyboard, rect), procTex, typeof(Texture)); - ShowAlphaSourceGUI(material, procTex, ref rect); - - GUILayout.EndVertical(); - - // This hard space is there so that textures do not touch even when the inspector is really narrow, - // even if we are already in a FlexibleSpace-enclosed block. - GUILayout.Space(spacing); - - GUILayout.FlexibleSpace(); - } - } - - EditorGUILayout.EndHorizontal(); - EditorGUILayout.EndScrollView(); - } - - void ShowAlphaSourceGUI(ProceduralMaterial material, ProceduralTexture tex, ref Rect rect) - { - GUIStyle styleLabel = "ObjectPickerResultsGridLabel"; - float spacing = 10; - rect.y = rect.yMax + 2; - if (m_Importer != null) - { - using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) - { - if (tex.GetProceduralOutputType() != ProceduralOutputType.Normal && tex.hasAlpha) - { - rect.height = styleLabel.fixedHeight; - // create alpha modifier popup - string[] m_TextureSrc = - { - "Source (A)", - "Diffuse (A)", - "Normal (A)", - "Height (A)", - "Emissive (A)", - "Specular (A)", - "Opacity (A)", - "Smoothness (A)", - "Amb. Occlusion (A)", - "Detail Mask (A)", - "Metallic (A)", - "Roughness (A)" - }; - EditorGUILayout.Space(); - EditorGUILayout.Space(); - EditorGUI.BeginChangeCheck(); - int alphaSource = EditorGUI.Popup(rect, (int)m_Importer.GetTextureAlphaSource(material, tex.name), m_TextureSrc); - if (EditorGUI.EndChangeCheck()) - { - RecordForUndo(material, m_Importer, "Modify " + material.name + "'s Alpha Modifier"); - m_Importer.SetTextureAlphaSource(material, tex.name, (ProceduralOutputType)alphaSource); - } - rect.y = rect.yMax + 2; - } - } - } - rect.width += spacing; - } - - // Similar to ObjectField, but does not allow changing the object. - // It will still ping or select the object when clicked / double-clicked. - internal static void DoObjectPingField(Rect position, Rect dropRect, int id, Object obj, System.Type objType) - { - Event evt = Event.current; - EventType eventType = evt.type; - - // special case test, so we continue to ping/select objects with the object field disabled - if (!GUI.enabled && GUIClip.enabled && (Event.current.rawType == EventType.MouseDown)) - eventType = Event.current.rawType; - - bool usePreview = EditorGUIUtility.HasObjectThumbnail(objType) && position.height > EditorGUI.kSingleLineHeight; - - switch (eventType) - { - case EventType.MouseDown: - // Ignore right clicks - if (Event.current.button != 0) - break; - if (position.Contains(Event.current.mousePosition)) - { - Object actualTargetObject = obj; - Component com = actualTargetObject as Component; - if (com) - actualTargetObject = com.gameObject; - - // One click shows where the referenced object is - if (Event.current.clickCount == 1) - { - GUIUtility.keyboardControl = id; - if (actualTargetObject) - EditorGUIUtility.PingObject(actualTargetObject); - evt.Use(); - } - // Double click changes selection to referenced object - else if (Event.current.clickCount == 2) - { - if (actualTargetObject) - { - AssetDatabase.OpenAsset(actualTargetObject); - GUIUtility.ExitGUI(); - } - evt.Use(); - } - } - break; - - case EventType.Repaint: - GUIContent temp = EditorGUIUtility.ObjectContent(obj, objType); - if (usePreview) - { - GUIStyle style = EditorStyles.objectFieldThumb; - style.Draw(position, GUIContent.none, id, DragAndDrop.activeControlID == id); - - if (obj != null) - { - EditorGUI.DrawPreviewTexture(style.padding.Remove(position), temp.image); - } - else - { - GUIStyle s2 = style.name + "Overlay"; - s2.Draw(position, temp, id); - } - } - else - { - GUIStyle style = EditorStyles.objectField; - style.Draw(position, temp, id, DragAndDrop.activeControlID == id); - } - break; - } - } - - internal void ResetValues() - { - BuildTargetList(); - if (HasModified()) - Debug.LogError("Impossible"); - } - - internal void Apply() - { - foreach (ProceduralPlatformSetting ps in m_PlatformSettings) - { - ps.Apply(); - } - } - - internal bool HasModified() - { - foreach (ProceduralPlatformSetting ps in m_PlatformSettings) - { - if (ps.HasChanged()) - { - return true; - } - } - - return false; - } - - [System.Serializable] - protected class ProceduralPlatformSetting - { - Object[] targets; - public string name; - public bool m_Overridden; - public int maxTextureWidth; - public int maxTextureHeight; - public int m_TextureFormat; - public int m_LoadBehavior; - public BuildTarget target; - public Texture2D icon; - public bool isDefault { get { return name == ""; } } - - public int textureFormat - { - get { return m_TextureFormat; } - set - { - m_TextureFormat = value; - } - } - - public ProceduralPlatformSetting(Object[] objects, string _name, BuildTarget _target, Texture2D _icon) - { - targets = objects; - m_Overridden = false; - target = _target; - name = _name; - icon = _icon; - m_Overridden = false; - if (name != "") - { - foreach (ProceduralMaterial mat in targets) - { - string matPath = AssetDatabase.GetAssetPath(mat); - SubstanceImporter importer = AssetImporter.GetAtPath(matPath) as SubstanceImporter; - if (importer != null && importer.GetPlatformTextureSettings(mat.name, name, out maxTextureWidth, out maxTextureHeight, out m_TextureFormat, out m_LoadBehavior)) - { - m_Overridden = true; - break; - } - } - } - if (!m_Overridden && targets.Length > 0) - { - string matPath = AssetDatabase.GetAssetPath(targets[0]); - SubstanceImporter importer = AssetImporter.GetAtPath(matPath) as SubstanceImporter; - if (importer != null) - importer.GetPlatformTextureSettings((targets[0] as ProceduralMaterial).name, "", out maxTextureWidth, out maxTextureHeight, out m_TextureFormat, out m_LoadBehavior); - } - } - - public bool overridden - { - get - { - return m_Overridden; - } - } - - public void SetOverride(ProceduralPlatformSetting master) - { - m_Overridden = true; - } - - public void ClearOverride(ProceduralPlatformSetting master) - { - m_TextureFormat = master.textureFormat; - maxTextureWidth = master.maxTextureWidth; - maxTextureHeight = master.maxTextureHeight; - m_LoadBehavior = master.m_LoadBehavior; - m_Overridden = false; - } - - public bool HasChanged() - { - ProceduralPlatformSetting orig = new ProceduralPlatformSetting(targets, name, target, null); - return orig.m_Overridden != m_Overridden || orig.maxTextureWidth != maxTextureWidth - || orig.maxTextureHeight != maxTextureHeight || orig.textureFormat != textureFormat - || orig.m_LoadBehavior != m_LoadBehavior; - } - - public void Apply() - { - foreach (ProceduralMaterial mat in targets) - { - string matPath = AssetDatabase.GetAssetPath(mat); - SubstanceImporter importer = AssetImporter.GetAtPath(matPath) as SubstanceImporter; - - if (name != "") - { - if (m_Overridden) - { - importer.SetPlatformTextureSettings(mat, name, maxTextureWidth, maxTextureHeight, m_TextureFormat, m_LoadBehavior); - } - else - { - importer.ClearPlatformTextureSettings(mat.name, name); - } - } - else - { - importer.SetPlatformTextureSettings(mat, name, maxTextureWidth, maxTextureHeight, m_TextureFormat, m_LoadBehavior); - } - } - } - } - - protected List m_PlatformSettings; - - public void BuildTargetList() - { - List validPlatforms = BuildPlatforms.instance.GetValidPlatforms(); - - m_PlatformSettings = new List(); - m_PlatformSettings.Add(new ProceduralPlatformSetting(targets, "", BuildTarget.StandaloneWindows, null)); - - foreach (BuildPlatform bp in validPlatforms) - { - m_PlatformSettings.Add(new ProceduralPlatformSetting(targets, bp.name, bp.defaultTarget, bp.smallIcon)); - } - } - - public void ShowTextureSizeGUI() - { - if (m_PlatformSettings == null) - BuildTargetList(); - - TextureSizeGUI(); - } - - protected void TextureSizeGUI() - { - BuildPlatform[] validPlatforms = BuildPlatforms.instance.GetValidPlatforms().ToArray(); - int shownTextureFormatPage = EditorGUILayout.BeginPlatformGrouping(validPlatforms, m_Styles.defaultPlatform); - ProceduralPlatformSetting realPS = m_PlatformSettings[shownTextureFormatPage + 1]; - ProceduralPlatformSetting ps = realPS; - - bool newOverride = true; - if (realPS.name != "") - { - EditorGUI.BeginChangeCheck(); - newOverride = GUILayout.Toggle(realPS.overridden, "Override for " + realPS.name); - if (EditorGUI.EndChangeCheck()) - { - if (newOverride) - { - realPS.SetOverride(m_PlatformSettings[0]); - } - else - { - realPS.ClearOverride(m_PlatformSettings[0]); - } - } - } - - using (new EditorGUI.DisabledScope(!newOverride)) - { - // Inform the user the texture size cannot be changed (case 693959) - if (!m_AllowTextureSizeModification) - GUILayout.Label("This ProceduralMaterial was published with a fixed size.", EditorStyles.wordWrappedLabel); - - // Do not allow texture size modification if the SBSAR doesn't have an "$outputsize" input (case 693959) - using (new EditorGUI.DisabledScope(!m_AllowTextureSizeModification)) - { - EditorGUI.BeginChangeCheck(); - ps.maxTextureWidth = EditorGUILayout.IntPopup(m_Styles.targetWidth.text, ps.maxTextureWidth, kMaxTextureSizeStrings, kMaxTextureSizeValues); - ps.maxTextureHeight = EditorGUILayout.IntPopup(m_Styles.targetHeight.text, ps.maxTextureHeight, kMaxTextureSizeStrings, kMaxTextureSizeValues); - if (EditorGUI.EndChangeCheck() && ps.isDefault) - { - foreach (ProceduralPlatformSetting psToUpdate in m_PlatformSettings) - { - if (psToUpdate.isDefault || psToUpdate.overridden) continue; - psToUpdate.maxTextureWidth = ps.maxTextureWidth; - psToUpdate.maxTextureHeight = ps.maxTextureHeight; - } - } - } - - EditorGUI.BeginChangeCheck(); - int tf = (int)ps.textureFormat; - if (tf < 0 || tf >= kTextureFormatStrings.Length) - { - Debug.LogError("Invalid TextureFormat"); - } - tf = EditorGUILayout.IntPopup(m_Styles.textureFormat.text, tf, kTextureFormatStrings, kTextureFormatValues); - if (EditorGUI.EndChangeCheck()) - { - ps.textureFormat = tf; - if (ps.isDefault) - { - foreach (ProceduralPlatformSetting psToUpdate in m_PlatformSettings) - { - if (psToUpdate.isDefault || psToUpdate.overridden) continue; - psToUpdate.textureFormat = ps.textureFormat; - } - } - } - EditorGUI.BeginChangeCheck(); - ps.m_LoadBehavior = EditorGUILayout.IntPopup(m_Styles.loadBehavior.text, ps.m_LoadBehavior, kMaxLoadBehaviorStrings, kMaxLoadBehaviorValues); - if (EditorGUI.EndChangeCheck() && ps.isDefault) - { - foreach (ProceduralPlatformSetting psToUpdate in m_PlatformSettings) - { - if (psToUpdate.isDefault || psToUpdate.overridden) continue; - psToUpdate.m_LoadBehavior = ps.m_LoadBehavior; - } - } - - GUILayout.Space(5); - using (new EditorGUI.DisabledScope(!HasModified())) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Revert")) - { - ResetValues(); - } - - if (GUILayout.Button("Apply")) - { - Apply(); - ReimportSubstances(); - ResetValues(); - } - GUILayout.EndHorizontal(); - } - - GUILayout.Space(5); - EditorGUILayout.EndPlatformGrouping(); - } - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - base.OnPreviewGUI(r, background); - if (ShowIsGenerating(target as ProceduralMaterial) && r.width > 50) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 20), "Generating..."); - } - - public void InputsGUI() - { - /* Proper input listing is: - 1) Groupless non-image-type parameters - 2) For each parameter group - a) Non-image-type parameters - b) Image-type parameters - 3) Groupless image-type parameters - */ - - List groupNames = new List(); - Dictionary> nonImageInputsSortedByGroup = new Dictionary>(); - Dictionary> imageInputsSortedByGroup = new Dictionary>(); - - ProceduralPropertyDescription[] inputs = m_Material.GetProceduralPropertyDescriptions(); - - // Try to catch groupless H/S/L tweaks in order to group them later on - ProceduralPropertyDescription inputH = null; - ProceduralPropertyDescription inputS = null; - ProceduralPropertyDescription inputL = null; - - foreach (ProceduralPropertyDescription input in inputs) - { - if (input.name == "$randomseed") - { - InputSeedGUI(input); - continue; - } - - // Skip all '$'-prefixed special parameters - if (input.name.Length > 0 && input.name[0] == '$') - continue; - - // Skip all non-visible inputs - if (!m_Material.IsProceduralPropertyVisible(input.name)) - continue; - - string group = input.group; - - // Keep track of all non-empty parameter group names - if (group != string.Empty && !groupNames.Contains(group)) - groupNames.Add(group); - - // Keep track of the HSL tweaks if we need to group them later on - if (input.name == "Hue_Shift" && input.type == ProceduralPropertyType.Float && group == string.Empty) - inputH = input; - if (input.name == "Saturation" && input.type == ProceduralPropertyType.Float && group == string.Empty) - inputS = input; - if (input.name == "Luminosity" && input.type == ProceduralPropertyType.Float && group == string.Empty) - inputL = input; - - // Sort the parameters into image and non-image, in dictionaries keyed by the parameter group name - if (input.type == ProceduralPropertyType.Texture) - { - if (!imageInputsSortedByGroup.ContainsKey(group)) - imageInputsSortedByGroup.Add(group, new List()); - imageInputsSortedByGroup[group].Add(input); - } - else - { - if (!nonImageInputsSortedByGroup.ContainsKey(group)) - nonImageInputsSortedByGroup.Add(group, new List()); - nonImageInputsSortedByGroup[group].Add(input); - } - } - - bool showCustomHSLGroup = false; - if (inputH != null && inputS != null && inputL != null) - showCustomHSLGroup = true; - - // Start with non-image groupless parameters - List grouplessNonImageParameters; - if (nonImageInputsSortedByGroup.TryGetValue(string.Empty, out grouplessNonImageParameters)) - { - foreach (ProceduralPropertyDescription input in grouplessNonImageParameters) - { - // Don't draw the H/S/L right here if we already know we'll draw a special H/S/L group at the bottom of the inspector - if (showCustomHSLGroup && (input == inputH || input == inputS || input == inputL)) - continue; - - InputGUI(input); - } - } - - // For each group, draw non-image tweaks first, then image tweaks - foreach (string groupName in groupNames) - { - ProceduralMaterial material = target as ProceduralMaterial; - string materialName = material.name; - string groupCompleteName = materialName + groupName; - - GUILayout.Space(5); - bool showGroup = EditorPrefs.GetBool(groupCompleteName, true); - EditorGUI.BeginChangeCheck(); - showGroup = EditorGUILayout.Foldout(showGroup, groupName, true); - if (EditorGUI.EndChangeCheck()) - { - EditorPrefs.SetBool(groupCompleteName, showGroup); - } - - if (showGroup) - { - EditorGUI.indentLevel++; - - List nonImageParameters; - if (nonImageInputsSortedByGroup.TryGetValue(groupName, out nonImageParameters)) - foreach (ProceduralPropertyDescription input in nonImageParameters) - InputGUI(input); - - List imageParameters; - if (imageInputsSortedByGroup.TryGetValue(groupName, out imageParameters)) - { - GUILayout.Space(2); - foreach (ProceduralPropertyDescription input in imageParameters) - InputGUI(input); - } - - EditorGUI.indentLevel--; - } - } - - // Draw H/S/L special group if we need to - if (showCustomHSLGroup) - InputHSLGUI(inputH, inputS, inputL); - - // Then end the parameter list with groupless image tweaks - List grouplessImageParameters; - if (imageInputsSortedByGroup.TryGetValue(string.Empty, out grouplessImageParameters)) - { - GUILayout.Space(5); - foreach (ProceduralPropertyDescription input in grouplessImageParameters) - InputGUI(input); - } - } - - private void InputGUI(ProceduralPropertyDescription input) - { - ProceduralPropertyType type = input.type; - GUIContent content = new GUIContent(input.label, input.name); - switch (type) - { - case ProceduralPropertyType.Boolean: - { - EditorGUI.BeginChangeCheck(); - bool val = EditorGUILayout.Toggle(content, m_Material.GetProceduralBoolean(input.name)); - if (EditorGUI.EndChangeCheck()) - { - RecordForUndo(m_Material, m_Importer, "Modified property " + input.name + " for material " + m_Material.name); - m_Material.SetProceduralBoolean(input.name, val); - } - break; - } - case ProceduralPropertyType.Float: - { - float val; - EditorGUI.BeginChangeCheck(); - if (input.hasRange) - { - float min = input.minimum; - float max = input.maximum; - val = EditorGUILayout.Slider(content, m_Material.GetProceduralFloat(input.name), min, max); - } - else - { - val = EditorGUILayout.FloatField(content, m_Material.GetProceduralFloat(input.name)); - } - if (EditorGUI.EndChangeCheck()) - { - RecordForUndo(m_Material, m_Importer, "Modified property " + input.name + " for material " + m_Material.name); - m_Material.SetProceduralFloat(input.name, val); - } - break; - } - case ProceduralPropertyType.Vector2: - case ProceduralPropertyType.Vector3: - case ProceduralPropertyType.Vector4: - { - int inputCount = (type == ProceduralPropertyType.Vector2 ? 2 : (type == ProceduralPropertyType.Vector3 ? 3 : 4)); - Vector4 val = m_Material.GetProceduralVector(input.name); - - EditorGUI.BeginChangeCheck(); - if (input.hasRange) - { - float min = input.minimum; - float max = input.maximum; - EditorGUILayout.BeginVertical(); - EditorGUILayout.BeginHorizontal(); - GUILayout.Space(EditorGUI.indentLevel * 15); - GUILayout.Label(content); - EditorGUILayout.EndHorizontal(); - EditorGUI.indentLevel++; - for (int i = 0; i < inputCount; i++) - val[i] = EditorGUILayout.Slider(new GUIContent(input.componentLabels[i]), val[i], min, max); - EditorGUI.indentLevel--; - EditorGUILayout.EndVertical(); - } - else - { - switch (inputCount) - { - case 2: val = EditorGUILayout.Vector2Field(input.name, val); break; - case 3: val = EditorGUILayout.Vector3Field(input.name, val); break; - case 4: val = EditorGUILayout.Vector4Field(input.name, val); break; - } - } - if (EditorGUI.EndChangeCheck()) - { - RecordForUndo(m_Material, m_Importer, "Modified property " + input.name + " for material " + m_Material.name); - m_Material.SetProceduralVector(input.name, val); - } - break; - } - case ProceduralPropertyType.Color3: - case ProceduralPropertyType.Color4: - { - EditorGUI.BeginChangeCheck(); - Color val = EditorGUILayout.ColorField(content, m_Material.GetProceduralColor(input.name)); - if (EditorGUI.EndChangeCheck()) - { - RecordForUndo(m_Material, m_Importer, "Modified property " + input.name + " for material " + m_Material.name); - m_Material.SetProceduralColor(input.name, val); - } - break; - } - case ProceduralPropertyType.Enum: - { - GUIContent[] enumOptions = new GUIContent[input.enumOptions.Length]; - for (int i = 0; i < enumOptions.Length; ++i) - { - enumOptions[i] = new GUIContent(input.enumOptions[i]); - } - EditorGUI.BeginChangeCheck(); - int val = EditorGUILayout.Popup(content, m_Material.GetProceduralEnum(input.name), enumOptions); - if (EditorGUI.EndChangeCheck()) - { - RecordForUndo(m_Material, m_Importer, "Modified property " + input.name + " for material " + m_Material.name); - m_Material.SetProceduralEnum(input.name, val); - } - break; - } - case ProceduralPropertyType.String: - { - EditorGUI.BeginChangeCheck(); - string val = EditorGUILayout.TextField(content, m_Material.GetProceduralString(input.name)); - - if (EditorGUI.EndChangeCheck()) - { - RecordForUndo(m_Material, m_Importer, "Modified property " + input.name + " for material " + m_Material.name); - m_Material.SetProceduralString(input.name, val); - } - break; - } - case ProceduralPropertyType.Texture: - { - EditorGUILayout.BeginHorizontal(); - GUILayout.Space(EditorGUI.indentLevel * 15); - GUILayout.Label(content); - GUILayout.FlexibleSpace(); - Rect R = GUILayoutUtility.GetRect(64, 64, GUILayout.ExpandWidth(false)); - EditorGUI.BeginChangeCheck(); - Texture2D val = EditorGUI.DoObjectField(R, R, EditorGUIUtility.GetControlID(12354, FocusType.Keyboard, R), m_Material.GetProceduralTexture(input.name) as Object, typeof(Texture2D), null, null, false) as Texture2D; - EditorGUILayout.EndHorizontal(); - if (EditorGUI.EndChangeCheck()) - { - RecordForUndo(m_Material, m_Importer, "Modified property " + input.name + " for material " + m_Material.name); - m_Material.SetProceduralTexture(input.name, val); - } - break; - } - } - } - - private void InputHSLGUI(ProceduralPropertyDescription hInput, ProceduralPropertyDescription sInput, ProceduralPropertyDescription lInput) - { - GUILayout.Space(5); - m_ShowHSLInputs = EditorPrefs.GetBool("ProceduralShowHSL", true); - EditorGUI.BeginChangeCheck(); - m_ShowHSLInputs = EditorGUILayout.Foldout(m_ShowHSLInputs, m_Styles.hslContent, true); - if (EditorGUI.EndChangeCheck()) - { - EditorPrefs.SetBool("ProceduralShowHSL", m_ShowHSLInputs); - } - - if (m_ShowHSLInputs) - { - EditorGUI.indentLevel++; - InputGUI(hInput); - InputGUI(sInput); - InputGUI(lInput); - EditorGUI.indentLevel--; - } - } - - private void InputSeedGUI(ProceduralPropertyDescription input) - { - Rect r = EditorGUILayout.GetControlRect(); - EditorGUI.BeginChangeCheck(); - float val = (float)RandomIntField(r, m_Styles.randomSeedContent, (int)m_Material.GetProceduralFloat(input.name), 0, 9999); - if (EditorGUI.EndChangeCheck()) - { - RecordForUndo(m_Material, m_Importer, "Modified random seed for material " + m_Material.name); - m_Material.SetProceduralFloat(input.name, val); - } - } - - internal int RandomIntField(Rect position, GUIContent label, int val, int min, int max) - { - position = EditorGUI.PrefixLabel(position, 0, label); - return RandomIntField(position, val, min, max); - } - - internal int RandomIntField(Rect position, int val, int min, int max) - { - position.width = position.width - EditorGUIUtility.fieldWidth - EditorGUI.kSpacing; - - if (GUI.Button(position, m_Styles.randomizeButtonContent, EditorStyles.miniButton)) - { - val = Random.Range(min, max + 1); - } - - position.x += position.width + EditorGUI.kSpacing; - position.width = EditorGUIUtility.fieldWidth; - val = Mathf.Clamp(EditorGUI.IntField(position, val), min, max); - - return val; - } - } -} diff --git a/Editor/Mono/Inspector/ProceduralTextureInspector.cs b/Editor/Mono/Inspector/ProceduralTextureInspector.cs deleted file mode 100644 index aa52633307..0000000000 --- a/Editor/Mono/Inspector/ProceduralTextureInspector.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -// SUBSTANCE HOOK - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections.Generic; - -namespace UnityEditor -{ - [CustomEditor(typeof(ProceduralTexture))] - [CanEditMultipleObjects] - internal class ProceduralTextureInspector : TextureInspector - { - private bool m_MightHaveModified = false; - - protected override void OnDisable() - { - base.OnDisable(); - - if (!EditorApplication.isPlaying && !InternalEditorUtility.ignoreInspectorChanges && m_MightHaveModified) - { - m_MightHaveModified = false; - string[] asset_names = new string[targets.GetLength(0)]; - int i = 0; - foreach (ProceduralTexture tex in targets) - { - string path = AssetDatabase.GetAssetPath(tex); - SubstanceImporter importer = AssetImporter.GetAtPath(path) as SubstanceImporter; - if (importer) - importer.OnTextureInformationsChanged(tex); - path = AssetDatabase.GetAssetPath(tex.GetProceduralMaterial()); - bool exist = false; - for (int j = 0; j < i; ++j) - { - if (asset_names[j] == path) - { - exist = true; - break; - } - } - if (!exist) - asset_names[i++] = path; - } - for (int j = 0; j < i; ++j) - { - SubstanceImporter importer = AssetImporter.GetAtPath(asset_names[j]) as SubstanceImporter; - if (importer && EditorUtility.IsDirty(importer.GetInstanceID())) - AssetDatabase.ImportAsset(asset_names[j], ImportAssetOptions.ForceUncompressedImport); - } - } - } - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - - if (GUI.changed) - m_MightHaveModified = true; - - // Ensure that materials are updated - foreach (ProceduralTexture tex in targets) - { - if (tex) - { - ProceduralMaterial mat = tex.GetProceduralMaterial(); - if (mat && mat.isProcessing) - { - Repaint(); - SceneView.RepaintAll(); - GameView.RepaintAll(); - break; - } - } - } - } - - // Same as in ProceduralMaterialInspector - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - base.OnPreviewGUI(r, background); - if (target) - { - ProceduralMaterial mat = (target as ProceduralTexture).GetProceduralMaterial(); - if (mat && ProceduralMaterialInspector.ShowIsGenerating(mat) && r.width > 50) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 20), "Generating..."); - } - } - } -} diff --git a/Editor/Mono/Inspector/SearchableDropdown/DropdownElement.cs b/Editor/Mono/Inspector/SearchableDropdown/DropdownElement.cs deleted file mode 100644 index 69898a538d..0000000000 --- a/Editor/Mono/Inspector/SearchableDropdown/DropdownElement.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using Event = UnityEngine.Event; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [Serializable] - internal class DropdownElement : IComparable - { - protected GUIContent m_Content; - protected GUIContent m_ContentWhenSearching; - - protected virtual GUIStyle labelStyle - { - get { return AdvancedDropdownWindow.s_Styles.componentButton; } - } - - private string m_Name; - public string name - { - get { return m_Name; } - } - - private string m_Id; - public string id - { - get { return m_Id; } - } - - private DropdownElement m_Parent; - public DropdownElement parent - { - get { return m_Parent; } - } - - private List m_Children = new List(); - public List children - { - get { return m_Children; } - } - - protected virtual bool drawArrow { get; } - protected virtual bool isSearchable { get; } - - internal int m_Index = -1; - internal Vector2 m_Scroll; - internal int m_SelectedItem = 0; - - public int selectedItem - { - get { return m_SelectedItem; } - set - { - if (value < 0) - { - m_SelectedItem = 0; - } - else if (value >= children.Count) - { - m_SelectedItem = children.Count - 1; - } - else - { - m_SelectedItem = value; - } - } - } - - public DropdownElement(string name) : this(name, name, -1) - { - } - - public DropdownElement(string name, string id) : this(name, id, -1) - { - } - - public DropdownElement(string name, int index) : this(name, name, index) - { - } - - public DropdownElement(string name, string id, int index) - { - m_Content = new GUIContent(name); - m_ContentWhenSearching = new GUIContent(id); - m_Name = name; - m_Id = id; - m_Index = index; - } - - internal void AddChild(DropdownElement element) - { - children.Add(element); - } - - public void SetParent(DropdownElement element) - { - m_Parent = element; - } - - public virtual bool OnAction() - { - return true; - } - - public virtual void Draw(bool selected, bool isSearching) - { - var content = !isSearching ? m_Content : m_ContentWhenSearching; - - var rect = GUILayoutUtility.GetRect(content, labelStyle, GUILayout.ExpandWidth(true)); - if (Event.current.type != EventType.Repaint) - return; - - labelStyle.Draw(rect, content, false, false, selected, selected); - if (drawArrow) - { - Rect arrowRect = new Rect(rect.x + rect.width - 13, rect.y + 4, 13, 13); - AdvancedDropdownWindow.s_Styles.rightArrow.Draw(arrowRect, false, false, false, false); - } - } - - public DropdownElement GetSelectedChild() - { - if (children.Count == 0) - return null; - return children[m_SelectedItem]; - } - - public virtual int GetSelectedChildIndex() - { - var i = children[m_SelectedItem].m_Index; - if (i >= 0) - { - return i; - } - return m_SelectedItem; - } - - public IEnumerable GetSearchableElements() - { - if (isSearchable) - yield return this; - foreach (var child in children) - { - foreach (var searchableChildren in child.GetSearchableElements()) - { - yield return searchableChildren; - } - } - } - - public virtual int CompareTo(object o) - { - return name.CompareTo((o as DropdownElement).name); - } - } - - internal class SearchableDropdownElement : DropdownElement - { - protected override bool isSearchable - { - get { return true; } - } - - public SearchableDropdownElement(string name, int index) : this(name, name, index) - { - } - - public SearchableDropdownElement(string name, string id, int index) : base(name, id, index) - { - } - } -} diff --git a/Editor/Mono/Inspector/SearchableDropdown/GroupDropdownElement.cs b/Editor/Mono/Inspector/SearchableDropdown/GroupDropdownElement.cs deleted file mode 100644 index 20ea8feee7..0000000000 --- a/Editor/Mono/Inspector/SearchableDropdown/GroupDropdownElement.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [Serializable] - internal class GroupDropdownElement : DropdownElement - { - protected override GUIStyle labelStyle - { - get { return AdvancedDropdownWindow.s_Styles.groupButton; } - } - - protected override bool drawArrow - { - get { return true; } - } - - public GroupDropdownElement(string name) : this(name, name) - { - } - - public GroupDropdownElement(string name, string id) : base(name, id) - { - } - - public void SetSelectedIndex(int index) - { - selectedItem = index; - } - } -} diff --git a/Editor/Mono/Inspector/TextureInspector.cs b/Editor/Mono/Inspector/TextureInspector.cs index 66337a6e12..1dcf82cf5e 100644 --- a/Editor/Mono/Inspector/TextureInspector.cs +++ b/Editor/Mono/Inspector/TextureInspector.cs @@ -378,7 +378,7 @@ public override void OnPreviewSettings() bool hasAlpha = true; int mipCount = 1; - if (target is Texture2D || target is ProceduralTexture) + if (target is Texture2D) { alphaOnly = true; hasAlpha = false; @@ -395,11 +395,6 @@ public override void OnPreviewSettings() format = (t as Texture2D).format; checkFormat = true; } - else if (t is ProceduralTexture) - { - format = (t as ProceduralTexture).format; - checkFormat = true; - } if (checkFormat) { @@ -469,7 +464,7 @@ public override void OnPreviewGUI(Rect r, GUIStyle background) return; } - // Substances can report zero sizes in some cases just after a parameter change; + // target can report zero sizes in some cases just after a parameter change; // guard against that. int texWidth = Mathf.Max(t.width, 1); int texHeight = Mathf.Max(t.height, 1); diff --git a/Editor/Mono/Inspector/UnityEventDrawer.cs b/Editor/Mono/Inspector/UnityEventDrawer.cs index e671dcedab..e43400f725 100644 --- a/Editor/Mono/Inspector/UnityEventDrawer.cs +++ b/Editor/Mono/Inspector/UnityEventDrawer.cs @@ -77,9 +77,11 @@ private State GetState(SerializedProperty prop) State state; string key = prop.propertyPath; m_States.TryGetValue(key, out state); - if (state == null) + // ensure the cached SerializedProperty is synchronized (case 974069) + if (state == null || state.m_ReorderableList.serializedProperty.serializedObject != prop.serializedObject) { - state = new State(); + if (state == null) + state = new State(); SerializedProperty listenersArray = prop.FindPropertyRelative("m_PersistentCalls.m_Calls"); state.m_ReorderableList = new ReorderableList(prop.serializedObject, listenersArray, false, true, true, true); diff --git a/Editor/Mono/ObjectNames.cs b/Editor/Mono/ObjectNames.cs index 60d73f25a1..bbac0243ad 100644 --- a/Editor/Mono/ObjectNames.cs +++ b/Editor/Mono/ObjectNames.cs @@ -54,14 +54,6 @@ private static string GetObjectTypeName(Object o) return "Default References (" + (script ? script.name : string.Empty) + ")"; } - var substanceImporter = o as SubstanceImporter; - if (substanceImporter) - { - var assetObject = substanceImporter.GetSubstanceArchive(); - if (assetObject) - return assetObject.name + " (Substance Archive)"; - } - return o.GetType().Name; } diff --git a/Editor/Mono/PlayerSettings.deprecated.cs b/Editor/Mono/PlayerSettings.deprecated.cs index 01f57e2eda..e5d06349b9 100644 --- a/Editor/Mono/PlayerSettings.deprecated.cs +++ b/Editor/Mono/PlayerSettings.deprecated.cs @@ -68,6 +68,19 @@ public enum iOSTargetOSVersion Unknown = 999, } + // deprecated in 5.6 + [Flags] + [Obsolete("Use UnityEngine.iOS.SystemGestureDeferMode instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.iOS.SystemGestureDeferMode", true)] + public enum iOSSystemGestureDeferMode: uint + { + None = 0, + TopEdge = 1 << 0, + LeftEdge = 1 << 1, + BottomEdge = 1 << 2, + RightEdge = 1 << 3, + All = TopEdge | LeftEdge | BottomEdge | RightEdge + } + partial class PlayerSettings { // deprecated since forever diff --git a/Editor/Mono/PlayerSettingsIOS.bindings.cs b/Editor/Mono/PlayerSettingsIOS.bindings.cs index 79dec279b6..1c190e579d 100644 --- a/Editor/Mono/PlayerSettingsIOS.bindings.cs +++ b/Editor/Mono/PlayerSettingsIOS.bindings.cs @@ -98,17 +98,6 @@ public enum iOSLaunchScreenImageType iPadImage = 2, } - [Flags] - public enum iOSSystemGestureDeferMode: uint - { - None = 0, - TopEdge = 1 << 0, - LeftEdge = 1 << 1, - BottomEdge = 1 << 2, - RightEdge = 1 << 3, - All = TopEdge | LeftEdge | BottomEdge | RightEdge - } - // extern splash screen type (on iOS) public enum iOSLaunchScreenType { @@ -324,9 +313,9 @@ public static iOSStatusBarStyle statusBarStyle [NativeProperty("DeferSystemGesturesMode")] private extern static int deferSystemGesturesModeInternal { get; set; } - public static iOSSystemGestureDeferMode deferSystemGesturesMode + public static UnityEngine.iOS.SystemGestureDeferMode deferSystemGesturesMode { - get { return (iOSSystemGestureDeferMode)deferSystemGesturesModeInternal; } + get { return (UnityEngine.iOS.SystemGestureDeferMode)deferSystemGesturesModeInternal; } set { deferSystemGesturesModeInternal = (int)value; } } diff --git a/Editor/Mono/PluginImporter.bindings.cs b/Editor/Mono/PluginImporter.bindings.cs index 3cd4a0ab59..eddd97dd1d 100644 --- a/Editor/Mono/PluginImporter.bindings.cs +++ b/Editor/Mono/PluginImporter.bindings.cs @@ -155,6 +155,39 @@ private bool InvokeIncludeInBuildDelegate() return true; } + // this is implemented as a static map so that it can survive a garbage collection on the PluginImporter and not get lost + private static Dictionary> s_shouldOverridePredicateMap = new Dictionary>(); + internal void SetShouldOverridePredicate(System.Predicate shouldOverridePredicate) + { + if (shouldOverridePredicate != null) + { + s_shouldOverridePredicateMap[assetPath] = shouldOverridePredicate; + } + else + { + if (s_shouldOverridePredicateMap.ContainsKey(assetPath)) + s_shouldOverridePredicateMap.Remove(assetPath); + } + } + + [RequiredByNativeCode] + private bool InvokeShouldOverridePredicate() + { + if (s_shouldOverridePredicateMap.ContainsKey(assetPath)) + { + try + { + return s_shouldOverridePredicateMap[assetPath](assetPath); + } + catch (System.Exception) + { + UnityEngine.Debug.LogWarning("Exception occurred while invoking ShouldOverridePredicate for " + assetPath); + } + } + + return false; + } + public void SetExcludeFromAnyPlatform(BuildTarget platform, bool excludedFromAny) { SetExcludeFromAnyPlatform(BuildPipeline.GetBuildTargetName(platform), excludedFromAny); diff --git a/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs b/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs index 0b8aee5180..fe1039077d 100644 --- a/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs +++ b/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs @@ -27,7 +27,7 @@ private bool isCurrentlyNested get { return (m_PropertyDrawer != null - && ScriptAttributeUtility.s_DrawerStack.Any() + && ScriptAttributeUtility.s_DrawerStack.Count > 0 && m_PropertyDrawer == ScriptAttributeUtility.s_DrawerStack.Peek()); } } diff --git a/Editor/Mono/ShaderUtil.bindings.cs b/Editor/Mono/ShaderUtil.bindings.cs index 0ffc333691..08f080301c 100644 --- a/Editor/Mono/ShaderUtil.bindings.cs +++ b/Editor/Mono/ShaderUtil.bindings.cs @@ -6,7 +6,8 @@ using UnityEngine.Scripting; using UnityEngine; using System; - +using System.Runtime.InteropServices; +using UnityEngine.Assertions; namespace UnityEditor { @@ -39,10 +40,109 @@ public bool hasErrors } } + public class ShaderData + { + public class Subshader + { + internal ShaderData m_Data; + internal int m_SubshaderIndex; + + internal Subshader(ShaderData data, int subshaderIndex) + { + m_Data = data; + m_SubshaderIndex = subshaderIndex; + } + + internal Shader SourceShader { get { return m_Data.SourceShader; } } + + public int PassCount { get { return ShaderUtil.GetShaderTotalPassCount(m_Data.SourceShader, m_SubshaderIndex); } } + + public Pass GetPass(int passIndex) + { + if (passIndex < 0 || passIndex >= PassCount) + { + Debug.LogErrorFormat("Pass index is incorrect: {0}, shader {1} has {2} passes.", passIndex, SourceShader, PassCount); + return null; + } + + return new Pass(this, passIndex); + } + } + + public class Pass + { + Subshader m_Subshader; + int m_PassIndex; + + internal Pass(Subshader subshader, int passIndex) + { + m_Subshader = subshader; + m_PassIndex = passIndex; + } + + internal Shader SourceShader { get { return m_Subshader.m_Data.SourceShader; } } + internal int SubshaderIndex { get { return m_Subshader.m_SubshaderIndex; } } + + public string SourceCode { get { return ShaderUtil.GetShaderPassSourceCode(SourceShader, SubshaderIndex, m_PassIndex); } } + public string Name { get { return ShaderUtil.GetShaderPassName(SourceShader, SubshaderIndex, m_PassIndex); } } + } + + public int ActiveSubshaderIndex { get { return ShaderUtil.GetShaderActiveSubshaderIndex(SourceShader); } } + public int SubshaderCount { get { return ShaderUtil.GetShaderSubshaderCount(SourceShader); } } + + public Shader SourceShader { get; private set; } + + public Subshader ActiveSubshader + { + get + { + var index = ActiveSubshaderIndex; + if (index < 0 || index >= SubshaderCount) + return null; + + return new Subshader(this, index); + } + } + + internal ShaderData(Shader sourceShader) + { + Assert.IsNotNull(sourceShader); + this.SourceShader = sourceShader; + } + + public Subshader GetSubshader(int index) + { + if (index < 0 || index >= SubshaderCount) + { + Debug.LogErrorFormat("Subshader index is incorrect: {0}, shader {1} has {2} passes.", index, SourceShader, SubshaderCount); + return null; + } + + return new Subshader(this, index); + } + } + [NativeHeader("Editor/Src/ShaderMenu.h")] + [NativeHeader("Editor/Src/ShaderData.h")] public partial class ShaderUtil { [FreeFunction] public static extern ShaderInfo[] GetAllShaderInfo(); + + public static ShaderData GetShaderData(Shader shader) + { + return new ShaderData(shader); + } + + [FreeFunction] + internal static extern string GetShaderPassSourceCode([NotNull] Shader shader, int subShaderIndex, int passId); + [FreeFunction] + internal static extern string GetShaderPassName([NotNull] Shader shader, int subShaderIndex, int passId); + [FreeFunction] + internal static extern int GetShaderActiveSubshaderIndex([NotNull] Shader shader); + [FreeFunction] + internal static extern int GetShaderSubshaderCount([NotNull] Shader shader); + [FreeFunction] + internal static extern int GetShaderTotalPassCount([NotNull] Shader shader, int subShaderIndex); } } diff --git a/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs b/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs index 40a55f2d84..9b23fc331f 100644 --- a/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs +++ b/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs @@ -195,6 +195,7 @@ void OnSelectionChange() var assetPath = GetSelectionAssetPath(); var ai = AssetImporter.GetAtPath(assetPath); var dataProvider = ai as ISpriteEditorDataProvider; + bool updateModules = false; if (dataProvider == null || selectedProviderChanged) { @@ -203,6 +204,7 @@ void OnSelectionChange() ResetWindow(); RefreshPropertiesCache(); RefreshRects(); + updateModules = true; } if (m_RectsCache != null) @@ -216,7 +218,9 @@ void OnSelectionChange() } } - UpdateAvailableModules(); + // We only update modules when data provider changed + if (updateModules) + UpdateAvailableModules(); Repaint(); } diff --git a/Editor/Mono/SubstanceImporter.cs b/Editor/Mono/SubstanceImporter.cs deleted file mode 100644 index d13c69ea8f..0000000000 --- a/Editor/Mono/SubstanceImporter.cs +++ /dev/null @@ -1,160 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -// SubstanceImporter C# class description -// SUBSTANCE HOOK - -using System; -using UnityEditor; -using UnityEngine; -using Object = UnityEngine.Object; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; -using System.Collections.Generic; -using System.IO; - -namespace UnityEditor -{ - // Material informations for Procedural Material textures generation - // I have hidden this odd implementation detail from the public interface. - struct ScriptingProceduralMaterialInformation - { - // Offset and scaling - Vector2 m_TextureOffsets; - Vector2 m_TextureScales; - int m_GenerateAllOutputs; - int m_AnimationUpdateRate; - bool m_GenerateMipMaps; - - // Gets or sets the texture offsets - public Vector2 offset { get { return m_TextureOffsets; } set { m_TextureOffsets = value; } } - - // Gets or sets the texture scale factors - public Vector2 scale { get { return m_TextureScales; } set { m_TextureScales = value; } } - - // Gets or sets if all the outputs are generated independently of the current shader - public bool generateAllOutputs { get { return m_GenerateAllOutputs != 0; } set { m_GenerateAllOutputs = value ? 1 : 0; } } - - // Gets or sets the animation update rate in millisecond - public int animationUpdateRate { get { return m_AnimationUpdateRate; } set { m_AnimationUpdateRate = value; } } - - // Gets or sets the mipmap generation mode - public bool generateMipMaps { get { return m_GenerateMipMaps; } set { m_GenerateMipMaps = value; } } - } - - // Substance importer lets you access the imported Procedural Material instances. - public partial class SubstanceImporter : AssetImporter - { - // Get the material offset, which is used for all the textures that are part of this Procedural Material. - public Vector2 GetMaterialOffset(ProceduralMaterial material) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - return GetMaterialInformation(material).offset; - } - - // Set the material offset, which is used for all the textures that are part of this Procedural Material. - public void SetMaterialOffset(ProceduralMaterial material, Vector2 offset) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - ScriptingProceduralMaterialInformation information = GetMaterialInformation(material); - information.offset = offset; - SetMaterialInformation(material, information); - } - - // Get the material scale, which is used for all the textures that are part of this Procedural Material. - public Vector2 GetMaterialScale(ProceduralMaterial material) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - return GetMaterialInformation(material).scale; - } - - // Set the material scale, which is used for all the textures that are part of this Procedural Material. - public void SetMaterialScale(ProceduralMaterial material, Vector2 scale) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - ScriptingProceduralMaterialInformation information = GetMaterialInformation(material); - information.scale = scale; - SetMaterialInformation(material, information); - } - - // Checks if the Procedural Material need to force generation of all its outputs. - public bool GetGenerateAllOutputs(ProceduralMaterial material) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - return GetMaterialInformation(material).generateAllOutputs; - } - - // Specifies if the Procedural Material need to force generation of all its outputs. - public void SetGenerateAllOutputs(ProceduralMaterial material, bool generated) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - ScriptingProceduralMaterialInformation information = GetMaterialInformation(material); - information.generateAllOutputs = generated; - SetMaterialInformation(material, information); - } - - // Get the Procedural Material animation update rate in millisecond. - public int GetAnimationUpdateRate(ProceduralMaterial material) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - return GetMaterialInformation(material).animationUpdateRate; - } - - // Set the Procedural Material animation update rate in millisecond. - public void SetAnimationUpdateRate(ProceduralMaterial material, int animation_update_rate) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - ScriptingProceduralMaterialInformation information = GetMaterialInformation(material); - information.animationUpdateRate = animation_update_rate; - SetMaterialInformation(material, information); - } - - // Returns whether mipmaps are generated for the given material - public bool GetGenerateMipMaps(ProceduralMaterial material) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - return GetMaterialInformation(material).generateMipMaps; - } - - // Sets the Mipmap generation mode for the given material - public void SetGenerateMipMaps(ProceduralMaterial material, bool mode) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - ScriptingProceduralMaterialInformation information = GetMaterialInformation(material); - information.generateMipMaps = mode; - SetMaterialInformation(material, information); - } - - // Compares a texture and a property name and returns true if the texture is a ProceduralTexture locked to that property - internal static bool IsProceduralTextureSlot(Material material, Texture tex, string name) - { - return (material is ProceduralMaterial && tex is ProceduralTexture - && CanShaderPropertyHostProceduralOutput(name, ((tex as ProceduralTexture).GetProceduralOutputType())) - && SubstanceImporter.IsSubstanceParented(tex as ProceduralTexture, material as ProceduralMaterial)); - } - - public void ExportBitmaps(ProceduralMaterial material, string exportPath, bool alphaRemap) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - if (exportPath == "") throw new ArgumentException("Invalid export path specified"); - - DirectoryInfo dirInfo = Directory.CreateDirectory(exportPath); - if (!dirInfo.Exists) throw new ArgumentException("Export folder " + exportPath + " doesn't exist and cannot be created."); - - ExportBitmapsInternal(material, exportPath, alphaRemap); - } - - public void ExportPreset(ProceduralMaterial material, string exportPath) - { - if (material == null) throw new ArgumentException("Invalid ProceduralMaterial"); - if (exportPath == "") throw new ArgumentException("Invalid export path specified"); - - DirectoryInfo dirInfo = Directory.CreateDirectory(exportPath); - if (!dirInfo.Exists) throw new ArgumentException("Export folder " + exportPath + " doesn't exist and cannot be created."); - - File.WriteAllText(Path.Combine(exportPath, material.name + ".sbsprs"), material.preset); - } - } -} // namespace UnityEditor diff --git a/Modules/SpriteShape/Public/ScriptBindings/SpriteShapeUtility.bindings.cs b/Modules/SpriteShape/Public/ScriptBindings/SpriteShapeUtility.bindings.cs index 3b1cbe1ffc..979593f838 100644 --- a/Modules/SpriteShape/Public/ScriptBindings/SpriteShapeUtility.bindings.cs +++ b/Modules/SpriteShape/Public/ScriptBindings/SpriteShapeUtility.bindings.cs @@ -63,6 +63,7 @@ public sealed partial class SpriteShapeRenderer : Renderer { extern internal int GetVertexCount(); extern internal int GetIndexCount(); + extern internal Bounds GetLocalAABB(); } [NativeHeader("Modules/SpriteShape/Public/SpriteShapeUtility.h")] diff --git a/Modules/Substance/SubstanceUtility.bindings.cs b/Modules/Substance/SubstanceUtility.bindings.cs new file mode 100644 index 0000000000..4ae814f060 --- /dev/null +++ b/Modules/Substance/SubstanceUtility.bindings.cs @@ -0,0 +1,24 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +// SUBSTANCE HOOK + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Collections; + +namespace UnityEngine +{ + public partial class ProceduralMaterial : Material + { + static void FeatureRemoved() + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + //static extern void BindingsGeneratorTrigger(); + } + +} // namespace UnityEngine diff --git a/Modules/Substance/SubstanceUtility.cs b/Modules/Substance/SubstanceUtility.cs new file mode 100644 index 0000000000..fcc514752f --- /dev/null +++ b/Modules/Substance/SubstanceUtility.cs @@ -0,0 +1,334 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +/* +using scm=System.ComponentModel; +using uei=UnityEngine.Internal; +using RequiredByNativeCodeAttribute=UnityEngine.Scripting.RequiredByNativeCodeAttribute; +using UsedByNativeCodeAttribute=UnityEngine.Scripting.UsedByNativeCodeAttribute; +*/ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Collections; + +namespace UnityEngine +{ + [Obsolete("ProceduralProcessorUsage is deprecated and no longer available.", true)] + public enum ProceduralProcessorUsage + { + Unsupported = 0, + One = 1, + Half = 2, + All = 3 + } + + [Obsolete("ProceduralCacheSize is deprecated and no longer available.", true)] + public enum ProceduralCacheSize + { + Tiny = 0, + Medium = 1, + Heavy = 2, + NoLimit = 3, + None = 4 + } + + [Obsolete("ProceduralLoadingBehavior is deprecated and no longer available.", true)] + public enum ProceduralLoadingBehavior + { + DoNothing = 0, + Generate = 1, + BakeAndKeep = 2, + BakeAndDiscard = 3, + Cache = 4, + DoNothingAndCache = 5 + } + + [Obsolete("ProceduralPropertyType is deprecated and no longer available.", true)] + public enum ProceduralPropertyType + { + Boolean = 0, + Float = 1, + Vector2 = 2, + Vector3 = 3, + Vector4 = 4, + Color3 = 5, + Color4 = 6, + Enum = 7, + Texture = 8, + String = 9 + } + + [Obsolete("ProceduralOutputType is deprecated and no longer available.", true)] + public enum ProceduralOutputType + { + Unknown = 0, + Diffuse = 1, + Normal = 2, + Height = 3, + Emissive = 4, + Specular = 5, + Opacity = 6, + Smoothness = 7, + AmbientOcclusion = 8, + DetailMask = 9, + Metallic = 10, + Roughness = 11 + } + + [StructLayout(LayoutKind.Sequential)] + [Obsolete("ProceduralPropertyDescription is deprecated and no longer available.", true)] + public sealed partial class ProceduralPropertyDescription + { + public string name; + public string label; + public string group; + public ProceduralPropertyType type; + public bool hasRange; + public float minimum; + public float maximum; + public float step; + public string[] enumOptions; + public string[] componentLabels; + } + + [Obsolete("ProceduralMaterial is deprecated and no longer available.", true)] + [ExcludeFromPreset] + public sealed partial class ProceduralMaterial : Material + { + internal ProceduralMaterial() + : base((Material)null) + { + FeatureRemoved(); + } + + public ProceduralPropertyDescription[] GetProceduralPropertyDescriptions() + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public bool HasProceduralProperty(string inputName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public bool GetProceduralBoolean(string inputName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public bool IsProceduralPropertyVisible(string inputName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public void SetProceduralBoolean(string inputName, bool value) + { + FeatureRemoved(); + } + + public float GetProceduralFloat(string inputName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public void SetProceduralFloat(string inputName, float value) + { + FeatureRemoved(); + } + + public Vector4 GetProceduralVector(string inputName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public void SetProceduralVector(string inputName, Vector4 value) + { + FeatureRemoved(); + } + + public Color GetProceduralColor(string inputName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public void SetProceduralColor(string inputName, Color value) + { + FeatureRemoved(); + } + + public int GetProceduralEnum(string inputName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public void SetProceduralEnum(string inputName, int value) + { + FeatureRemoved(); + } + + public Texture2D GetProceduralTexture(string inputName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public void SetProceduralTexture(string inputName, Texture2D value) + { + FeatureRemoved(); + } + + public string GetProceduralString(string inputName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public void SetProceduralString(string inputName, string value) + { + FeatureRemoved(); + } + + public bool IsProceduralPropertyCached(string inputName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public void CacheProceduralProperty(string inputName, bool value) + { + FeatureRemoved(); + } + + public void ClearCache() + { + FeatureRemoved(); + } + + public ProceduralCacheSize cacheSize + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + set { FeatureRemoved(); } + } + + + public int animationUpdateRate + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + set { FeatureRemoved(); } + } + + public void RebuildTextures() + { + FeatureRemoved(); + } + + public void RebuildTexturesImmediately() + { + FeatureRemoved(); + } + + public bool isProcessing + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + } + + public static void StopRebuilds() + { + FeatureRemoved(); + } + + public bool isCachedDataAvailable + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + } + + public bool isLoadTimeGenerated + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + set { FeatureRemoved(); } + } + + public ProceduralLoadingBehavior loadingBehavior + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + } + + public static bool isSupported + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + } + + public static ProceduralProcessorUsage substanceProcessorUsage + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + set { FeatureRemoved(); } + } + + public string preset + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + set { FeatureRemoved(); } + } + + public Texture[] GetGeneratedTextures() + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public ProceduralTexture GetGeneratedTexture(string textureName) + { + throw new Exception("ProceduralMaterial is deprecated and no longer available."); + } + + public bool isReadable + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + set { FeatureRemoved(); } + } + + public void FreezeAndReleaseSourceData() + { + FeatureRemoved(); + } + + public bool isFrozen + { + get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + } + } + + [Obsolete("ProceduralTexture is deprecated and no longer available.", true)] + [ExcludeFromPreset] + public sealed partial class ProceduralTexture : Texture + { + private ProceduralTexture() + { + throw new Exception("ProceduralTexture is deprecated and no longer available."); + } + + public ProceduralOutputType GetProceduralOutputType() + { + throw new Exception("ProceduralTexture is deprecated and no longer available."); + } + + internal ProceduralMaterial GetProceduralMaterial() + { + throw new Exception("ProceduralTexture is deprecated and no longer available."); + } + + public bool hasAlpha + { + get { throw new Exception("ProceduralTexture is deprecated and no longer available."); } + } + + public TextureFormat format + { + get { throw new Exception("ProceduralTexture is deprecated and no longer available."); } + } + + public Color32[] GetPixels32(int x, int y, int blockWidth, int blockHeight) + { + throw new Exception("ProceduralTexture is deprecated and no longer available."); + } + } + +} diff --git a/Modules/UnityWebRequest/Public/WebRequestExtensions.cs b/Modules/UnityWebRequest/Public/WebRequestExtensions.cs index c3024797f1..8521cd5ddf 100644 --- a/Modules/UnityWebRequest/Public/WebRequestExtensions.cs +++ b/Modules/UnityWebRequest/Public/WebRequestExtensions.cs @@ -334,11 +334,6 @@ public static byte[] SerializeFormSections(List multipart string sectionName = section.sectionName; string fileName = section.fileName; - if (!string.IsNullOrEmpty(fileName)) - { - disposition = "file"; - } - string header = "Content-Disposition: " + disposition; if (!string.IsNullOrEmpty(sectionName)) diff --git a/Modules/XR/Subsystems/Camera/XRCameraInstance.bindings.cs b/Modules/XR/Subsystems/Camera/XRCameraInstance.bindings.cs new file mode 100644 index 0000000000..1f8d8dc26f --- /dev/null +++ b/Modules/XR/Subsystems/Camera/XRCameraInstance.bindings.cs @@ -0,0 +1,28 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Rendering; +using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace UnityEngine.Experimental.XR +{ + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeType(Header = "Modules/XR/Subsystems/Camera/XRCameraInstance.h")] + [UsedByNativeCode] + public class XRCameraInstance : XRInstance + { + [NativeConditional("ENABLE_XR")] + public extern void SetMaterial(Material mat); + + [NativeConditional("ENABLE_XR")] + public extern float GetAverageBrightness(); + + [NativeConditional("ENABLE_XR")] + public extern float GetAverageColorTemperature(); + } +} diff --git a/Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.bindings.cs new file mode 100644 index 0000000000..153527755c --- /dev/null +++ b/Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.bindings.cs @@ -0,0 +1,24 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace UnityEngine.Experimental.XR +{ + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeType(Header = "Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.h")] + [UsedByNativeCode] + public class XRCameraSubsystemDescriptor : XRSubsystemDescriptor + { + [NativeConditional("ENABLE_XR")] + public extern bool ProvidesAverageBrightness { get; } + + [NativeConditional("ENABLE_XR")] + public extern bool ProvidesAverageColorTemperature { get; } + } +} diff --git a/Modules/XR/Subsystems/Environment/Depth/XRDepth.bindings.cs b/Modules/XR/Subsystems/Environment/Depth/XRDepth.bindings.cs new file mode 100644 index 0000000000..46f23166a9 --- /dev/null +++ b/Modules/XR/Subsystems/Environment/Depth/XRDepth.bindings.cs @@ -0,0 +1,110 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; +using System.Collections.Generic; + +namespace UnityEngine.Experimental.XR +{ + public struct PointCloudUpdatedEventArgs + { + internal XRDepth m_Depth; + public XRDepth XRDepth { get { return m_Depth; } } + } + + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeHeader("Modules/XR/Subsystems/Environment/Depth/XRDepth.h")] + [StructLayout(LayoutKind.Sequential)] + public class XRDepth + { + private IntPtr m_Ptr; + private XREnvironment m_Environment; + + public bool Valid + { + get + { + return m_Ptr != IntPtr.Zero; + } + } + + public XREnvironment XREnvironment + { + get + { + return m_Environment; + } + } + + public event Action PointCloudUpdated; + + [NativeConditional("ENABLE_XR")] + public extern int FrameOfLastPointCloudUpdate { get; } + + [NativeConditional("ENABLE_XR")] + public extern bool TryGetPoint(TrackableId pointId, out Vector3 point); + + public void GetPointCloudPoints(List pointsOut) + { + if (pointsOut == null) + throw new ArgumentNullException("pointsOut"); + + Internal_GetPointCloudPointsAsList(pointsOut); + } + + public void GetPointCloudConfidence(List confidenceOut) + { + if (confidenceOut == null) + throw new ArgumentNullException("confidenceOut"); + + Internal_GetPointCloudConfidenceAsList(confidenceOut); + } + + internal XRDepth(IntPtr nativeEnvironment, XREnvironment managedEnvironment) + { + m_Ptr = Internal_Create(nativeEnvironment); + m_Environment = managedEnvironment; + SetHandle(this); + } + + [RequiredByNativeCode] + private void NotifyDepthDestruction() + { + m_Ptr = IntPtr.Zero; + } + + [RequiredByNativeCode] + private void InvokePointCloudUpdatedEvent() + { + if (PointCloudUpdated != null) + { + PointCloudUpdated(new PointCloudUpdatedEventArgs() + { + m_Depth = this + }); + } + } + + [NativeConditional("ENABLE_XR")] + private static extern IntPtr Internal_Create(IntPtr xrEnvironment); + + [NativeConditional("ENABLE_XR")] + private extern void SetHandle(XRDepth inst); + + [NativeConditional("ENABLE_XR")] + private extern void Internal_GetPointCloudPointsAsList(List pointsOut); + + [NativeConditional("ENABLE_XR")] + private extern void Internal_GetPointCloudConfidenceAsList(List confidenceOut); + + [NativeConditional("ENABLE_XR")] + private extern Vector3[] Internal_GetPointCloudPointsAsFixedArray(); + + [NativeConditional("ENABLE_XR")] + private extern float[] Internal_GetPointCloudConfidenceAsFixedArray(); + } +} diff --git a/Modules/XR/Subsystems/Environment/Planes/XRPlane.bindings.cs b/Modules/XR/Subsystems/Environment/Planes/XRPlane.bindings.cs new file mode 100644 index 0000000000..ad883731ac --- /dev/null +++ b/Modules/XR/Subsystems/Environment/Planes/XRPlane.bindings.cs @@ -0,0 +1,232 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; +using System.Collections.Generic; + +namespace UnityEngine.Experimental.XR +{ + [Flags] + public enum PlaneAlignment + { + Horizontal = 1 << 0, + Vertical = 1 << 1, + NonAxis = 1 << 2 + } + + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + [NativeHeader("Modules/XR/Subsystems/Environment/Planes/XRBoundedPlane.h")] + [NativeHeader("XRScriptingClasses.h")] + public struct BoundedPlane + { + private uint m_InstanceId; + + public TrackableId Id { get; set; } + public Vector3 Position { get; set; } + public Vector3 Center { get; set; } + public Quaternion Rotation { get; set; } + public Vector2 Size { get; set; } + public PlaneAlignment Alignment { get; set; } + + public float Width { get { return Size.x; } } + public float Height { get { return Size.y; } } + public Vector3 Normal { get { return Rotation * Vector3.up; } } + public Plane Plane { get { return new Plane(Normal, Center); } } + + public void GetCorners( + out Vector3 p0, + out Vector3 p1, + out Vector3 p2, + out Vector3 p3) + { + var worldHalfX = (Rotation * Vector3.right) * (Width * .5f); + var worldHalfZ = (Rotation * Vector3.forward) * (Height * .5f); + p0 = Center - worldHalfX - worldHalfZ; + p1 = Center - worldHalfX + worldHalfZ; + p2 = Center + worldHalfX + worldHalfZ; + p3 = Center + worldHalfX - worldHalfZ; + } + + public bool TryGetBoundary(List boundaryOut) + { + if (boundaryOut == null) + throw new ArgumentNullException("boundaryOut"); + + return Internal_GetBoundaryAsList(m_InstanceId, Id, boundaryOut); + } + + [NativeConditional("ENABLE_XR")] + private static extern Vector3[] Internal_GetBoundaryAsFixedArray( + uint instanceId, + TrackableId id); + + [NativeConditional("ENABLE_XR")] + private static extern bool Internal_GetBoundaryAsList( + uint instanceId, + TrackableId id, + List boundaryOut); + } + + public struct PlaneAddedEventArgs + { + internal XRPlane m_Planes; + public XRPlane XRPlane { get { return m_Planes; } } + public BoundedPlane AddedPlane { get; set; } + } + + public struct PlaneUpdatedEventArgs + { + internal XRPlane m_Planes; + public XRPlane XRPlane { get { return m_Planes; } } + public BoundedPlane UpdatedPlane { get; set; } + } + + public struct PlaneRemovedEventArgs + { + internal XRPlane m_Planes; + public XRPlane XRPlane { get { return m_Planes; } } + public BoundedPlane RemovedPlane { get; set; } + public BoundedPlane? SubsumedByPlane { get; set; } + } + + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeHeader("Modules/XR/Subsystems/Environment/Planes/XRPlane.h")] + [StructLayout(LayoutKind.Sequential)] + public class XRPlane + { + private IntPtr m_Ptr; + private XREnvironment m_Environment; + + public bool Valid + { + get + { + return m_Ptr != IntPtr.Zero; + } + } + + public XREnvironment XREnvironment + { + get + { + return m_Environment; + } + } + + public event Action PlaneAdded; + public event Action PlaneUpdated; + public event Action PlaneRemoved; + + [NativeConditional("ENABLE_XR")] + public extern int FrameOfLastPlaneUpdate { get; } + + [NativeConditional("ENABLE_XR")] + public extern bool TryGetPlane(TrackableId planeId, out BoundedPlane plane); + + public void GetAllPlanes(List planesOut) + { + if (planesOut == null) + throw new ArgumentNullException("planesOut"); + + GetAllPlanesAsList(planesOut); + } + + public bool TryGetPlaneBoundary(TrackableId planeId, List boundaryOut) + { + if (boundaryOut == null) + throw new ArgumentNullException("boundaryOut"); + + return Internal_GetBoundaryAsList(planeId, boundaryOut); + } + + internal XRPlane(IntPtr nativeEnvironment, XREnvironment managedEnvironment) + { + m_Ptr = Internal_Create(nativeEnvironment); + m_Environment = managedEnvironment; + SetHandle(this); + } + + [RequiredByNativeCode] + private void NotifyPlanesDestruction() + { + m_Ptr = IntPtr.Zero; + } + + [RequiredByNativeCode] + private void InvokePlaneAddedEvent(BoundedPlane plane) + { + if (PlaneAdded != null) + { + PlaneAdded(new PlaneAddedEventArgs() + { + m_Planes = this, + AddedPlane = plane + }); + } + } + + [RequiredByNativeCode] + private void InvokePlaneUpdatedEvent(BoundedPlane plane) + { + if (PlaneUpdated != null) + { + PlaneUpdated(new PlaneUpdatedEventArgs() + { + m_Planes = this, + UpdatedPlane = plane + }); + } + } + + [RequiredByNativeCode] + private void InvokePlaneMergedEvent(BoundedPlane removedPlane, BoundedPlane subsumedByPlane) + { + if (PlaneRemoved != null) + { + PlaneRemoved(new PlaneRemovedEventArgs() + { + m_Planes = this, + RemovedPlane = removedPlane, + SubsumedByPlane = subsumedByPlane + }); + } + } + + [RequiredByNativeCode] + private void InvokePlaneRemovedEvent(BoundedPlane removedPlane) + { + if (PlaneRemoved != null) + { + PlaneRemoved(new PlaneRemovedEventArgs() + { + m_Planes = this, + RemovedPlane = removedPlane, + SubsumedByPlane = null + }); + } + } + + [NativeConditional("ENABLE_XR")] + private extern BoundedPlane[] GetAllPlanesAsFixedArray(); + + [NativeConditional("ENABLE_XR")] + private extern void GetAllPlanesAsList(List planes); + + [NativeConditional("ENABLE_XR")] + private extern bool Internal_GetBoundaryAsList(TrackableId planeId, List boundaryOut); + + [NativeConditional("ENABLE_XR")] + private extern Vector3[] Internal_GetBoundaryAsFixedArray(TrackableId planeId); + + [NativeConditional("ENABLE_XR")] + private static extern IntPtr Internal_Create(IntPtr xrEnvironment); + + [NativeConditional("ENABLE_XR")] + private extern void SetHandle(XRPlane inst); + } +} diff --git a/Modules/XR/Subsystems/Environment/Raycast/XRRaycast.bindings.cs b/Modules/XR/Subsystems/Environment/Raycast/XRRaycast.bindings.cs new file mode 100644 index 0000000000..f370545360 --- /dev/null +++ b/Modules/XR/Subsystems/Environment/Raycast/XRRaycast.bindings.cs @@ -0,0 +1,136 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; +using System.Collections.Generic; + +namespace UnityEngine.Experimental.XR +{ + // Must match UnityXRTrackableType + [Flags] + public enum TrackableType + { + None = 0, + PlaneWithinPolygon = 1 << 0, + PlaneWithinBounds = 1 << 1, + PlaneWithinInfinity = 1 << 2, + PlaneEstimated = 1 << 3, + Planes = + PlaneWithinPolygon | + PlaneWithinBounds | + PlaneWithinInfinity | + PlaneEstimated, + FeaturePoint = 1 << 4, + All = Planes | FeaturePoint + } + + // Must match UnityXRRaycastHit + [NativeHeader("Modules/XR/Subsystems/Environment/Raycast/XRRaycast.h")] + [UsedByNativeCode] + public struct XRRaycastHit + { + public TrackableId TrackableId { get; set; } + public Vector3 Position { get; set; } + public Quaternion Rotation { get; set; } + public float Distance { get; set; } + public TrackableType HitType { get; set; } + } + + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeHeader("Modules/XR/Subsystems/Environment/Raycast/XRRaycast.h")] + [StructLayout(LayoutKind.Sequential)] + public class XRRaycast + { + private IntPtr m_Ptr; + private XREnvironment m_Environment; + + public bool Valid + { + get + { + return m_Ptr != IntPtr.Zero; + } + } + + public XREnvironment Environment + { + get + { + return m_Environment; + } + } + + [NativeConditional("ENABLE_XR")] + public extern float RaycastAngle { get; set; } + + public bool Raycast(Ray ray, List hitResults, TrackableType trackableTypeMask = TrackableType.All) + { + if (hitResults == null) + throw new ArgumentNullException("hitResults"); + + hitResults.Clear(); + + return Internal_RaycastAsList(ray.origin, ray.direction, trackableTypeMask, hitResults); + } + + public bool Raycast(Vector3 screenPoint, List hitResults, TrackableType trackableTypeMask = TrackableType.All) + { + if (hitResults == null) + throw new ArgumentNullException("hitResults"); + + float screenX = Mathf.Clamp01(screenPoint.x / Screen.width); + float screenY = Mathf.Clamp01(screenPoint.y / Screen.height); + + return Internal_ScreenRaycastAsList(screenX, screenY, trackableTypeMask, hitResults); + } + + internal XRRaycast(IntPtr nativeEnvironment, XREnvironment managedEnvironment) + { + m_Ptr = Internal_Create(nativeEnvironment); + m_Environment = managedEnvironment; + SetHandle(this); + } + + [RequiredByNativeCode] + private void NotifyRaycastDestruction() + { + m_Ptr = IntPtr.Zero; + } + + [NativeConditional("ENABLE_XR")] + private static extern IntPtr Internal_Create(IntPtr xrEnvironment); + + [NativeConditional("ENABLE_XR")] + private extern void SetHandle(XRRaycast inst); + + [NativeConditional("ENABLE_XR")] + private extern XRRaycastHit[] Internal_RaycastAsFixedArray( + Vector3 origin, + Vector3 direction, + TrackableType hitMask); + + [NativeConditional("ENABLE_XR")] + private extern bool Internal_RaycastAsList( + Vector3 origin, + Vector3 direction, + TrackableType hitMask, + List hitResultsOut); + + [NativeConditional("ENABLE_XR")] + private extern bool Internal_ScreenRaycastAsList( + float screenX, + float screenY, + TrackableType hitMask, + List hitResultsOut); + + [NativeConditional("ENABLE_XR")] + private extern XRRaycastHit[] Internal_ScreenRaycastAsFixedArray( + float screenX, + float screenY, + TrackableType hitMask); + } +} diff --git a/Modules/XR/Subsystems/Environment/ReferencePoints/XRReferencePoint.bindings.cs b/Modules/XR/Subsystems/Environment/ReferencePoints/XRReferencePoint.bindings.cs new file mode 100644 index 0000000000..60aefe00c5 --- /dev/null +++ b/Modules/XR/Subsystems/Environment/ReferencePoints/XRReferencePoint.bindings.cs @@ -0,0 +1,110 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; +using System.Collections.Generic; + +namespace UnityEngine.Experimental.XR +{ + // Must match XRManagedReferencePoint + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + [NativeHeader("Modules/XR/Subsystems/Environment/ReferencePoints/XRManagedReferencePoint.h")] + public struct ReferencePoint + { + public TrackableId Id { get; set; } + public Vector3 Position { get; set; } + public Quaternion Rotation { get; set; } + } + + public struct ReferencePointUpdatedEventArgs + { + public ReferencePoint UpdatedReferencePoint { get; set; } + } + + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeHeader("Modules/XR/Subsystems/Environment/ReferencePoints/XRReferencePoint.h")] + [StructLayout(LayoutKind.Sequential)] + public class XRReferencePoint + { + private IntPtr m_Ptr; + private XREnvironment m_Environment; + + public bool Valid + { + get + { + return m_Ptr != IntPtr.Zero; + } + } + + public XREnvironment XREnvironment + { + get + { + return m_Environment; + } + } + + public event Action ReferencePointUpdated; + + [NativeConditional("ENABLE_XR")] + public extern int FrameOfLastReferencePointUpdate { get; } + + [NativeConditional("ENABLE_XR")] + public extern bool TryAddReferencePoint(Vector3 position, Quaternion rotation, out TrackableId referencePointId); + + [NativeConditional("ENABLE_XR")] + public extern bool TryRemoveReferencePoint(TrackableId referencePointId); + + [NativeConditional("ENABLE_XR")] + public extern bool TryGetReferencePoint(TrackableId referencePointId, out ReferencePoint referencePoint); + + public void GetAllReferencePoints(List referencePointsOut) + { + if (referencePointsOut == null) + throw new ArgumentNullException("referencePointsOut"); + + Internal_GetAllReferencePointsAsList(referencePointsOut); + } + + internal XRReferencePoint(IntPtr nativeEnvironment, XREnvironment managedEnvironment) + { + m_Ptr = Internal_Create(nativeEnvironment); + m_Environment = managedEnvironment; + SetHandle(this); + } + + [RequiredByNativeCode] + private void NotifyReferencePointsDestruction() + { + m_Ptr = IntPtr.Zero; + } + + [RequiredByNativeCode] + private void InvokeReferencePointUpdatedEvent(ReferencePoint updatedReferencePoint) + { + if (ReferencePointUpdated != null) + ReferencePointUpdated(new ReferencePointUpdatedEventArgs() + { + UpdatedReferencePoint = updatedReferencePoint + }); + } + + [NativeConditional("ENABLE_XR")] + private static extern IntPtr Internal_Create(IntPtr xrEnvironment); + + [NativeConditional("ENABLE_XR")] + private extern void SetHandle(XRReferencePoint inst); + + [NativeConditional("ENABLE_XR")] + private extern void Internal_GetAllReferencePointsAsList(List referencePointsOut); + + [NativeConditional("ENABLE_XR")] + private extern ReferencePoint[] Internal_GetAllReferencePointsAsFixedArray(); + } +} diff --git a/Modules/XR/Subsystems/Environment/Session/XRSession.bindings.cs b/Modules/XR/Subsystems/Environment/Session/XRSession.bindings.cs new file mode 100644 index 0000000000..514c3d29c7 --- /dev/null +++ b/Modules/XR/Subsystems/Environment/Session/XRSession.bindings.cs @@ -0,0 +1,86 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; +using System.Collections.Generic; + +namespace UnityEngine.Experimental.XR +{ + [NativeHeader("Modules/XR/Subsystems/Environment/Session/XRSession.h")] + [UsedByNativeCode] + public struct SessionConfiguration + { + public bool EnablePlaneDetection { get; set; } + public bool EnableDepthData { get; set; } + public bool EnableCamera { get; set; } + public bool EnableLightEstimation { get; set; } + } + + // Must match UnityXRTrackingState + public enum TrackingState + { + Unknown = 0, + Initializing = 1, + Tracking = 2, + Suspended = 3, + Aborted = 4 + } + + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeHeader("Modules/XR/Subsystems/Environment/Session/XRSession.h")] + [NativeHeader("XRScriptingClasses.h")] + [StructLayout(LayoutKind.Sequential)] + public class XRSession + { + private IntPtr m_Ptr; + private XREnvironment m_Environment; + + public bool Valid + { + get + { + return m_Ptr != IntPtr.Zero; + } + } + + public XREnvironment Environment + { + get + { + return m_Environment; + } + } + + // NativeConditional can't handle enums at the moment + public extern TrackingState TrackingState { get; } + + [NativeConditional("ENABLE_XR")] + public extern int FrameOfLastTrackingStateUpdate { get; } + + [NativeConditional("ENABLE_XR")] + public extern void SetConfig(SessionConfiguration config); + + internal XRSession(IntPtr nativeEnvironment, XREnvironment managedEnvironment) + { + m_Ptr = Internal_Create(nativeEnvironment); + m_Environment = managedEnvironment; + SetHandle(this); + } + + [RequiredByNativeCode] + private void NotifySessionDestruction() + { + m_Ptr = IntPtr.Zero; + } + + [NativeConditional("ENABLE_XR")] + private static extern IntPtr Internal_Create(IntPtr xrEnvironment); + + [NativeConditional("ENABLE_XR")] + private extern void SetHandle(XRSession inst); + } +} diff --git a/Modules/XR/Subsystems/Environment/XREnvironment.bindings.cs b/Modules/XR/Subsystems/Environment/XREnvironment.bindings.cs new file mode 100644 index 0000000000..ffd48a1841 --- /dev/null +++ b/Modules/XR/Subsystems/Environment/XREnvironment.bindings.cs @@ -0,0 +1,145 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; +using System.Collections.Generic; + +namespace UnityEngine.Experimental.XR +{ + [NativeHeader("Modules/XR/Subsystems/Environment/XREnvironment.h")] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + public struct TrackableId + { + public override string ToString() + { + return string.Format("{0}-{1}", + m_SubId1.ToString("X16"), + m_SubId2.ToString("X16")); + } + + public override int GetHashCode() + { + return m_SubId1.GetHashCode() ^ m_SubId2.GetHashCode(); + } + + public override bool Equals(object obj) + { + if (obj is TrackableId) + { + var id = (TrackableId)obj; + return + (m_SubId1 == id.m_SubId1) && + (m_SubId2 == id.m_SubId2); + } + + return false; + } + + public static bool operator==(TrackableId id1, TrackableId id2) + { + return + (id1.m_SubId1 == id2.m_SubId1) && + (id1.m_SubId2 == id2.m_SubId2); + } + + public static bool operator!=(TrackableId id1, TrackableId id2) + { + return + (id1.m_SubId1 != id2.m_SubId1) || + (id1.m_SubId2 != id2.m_SubId2); + } + + private static TrackableId s_InvalidId = new TrackableId(); + public static TrackableId InvalidId { get { return s_InvalidId; } } + + private ulong m_SubId1; + private ulong m_SubId2; + } + + internal static class DotNetHelper + { + public static bool TryCopyFixedArrayToList(T[] fixedArrayIn, List listOut) + { + if (fixedArrayIn == null) + return false; + + var count = fixedArrayIn.Length; + + listOut.Clear(); + + if (listOut.Capacity < count) + listOut.Capacity = count; + + listOut.AddRange(fixedArrayIn); + return true; + } + } + + [NativeHeader("Modules/XR/Subsystems/Environment/XREnvironment.h")] + [UsedByNativeCode("xrEnvironment")] + public class XREnvironment : XRInstance + { + // internal since XREnvironment may only be created by the XRSubsystemDescriptor + internal XREnvironment() : base() {} + + public XRDepth Depth + { + get + { + return m_DepthInterface; + } + } + + public XRPlane Planes + { + get + { + return m_PlanesInterface; + } + } + + public XRRaycast Raycast + { + get + { + return m_RaycastInterface; + } + } + + public XRReferencePoint ReferencePoints + { + get + { + return m_ReferencePointsInterface; + } + } + + public XRSession Session + { + get + { + return m_SessionInterface; + } + } + + private XRDepth m_DepthInterface; + private XRPlane m_PlanesInterface; + private XRRaycast m_RaycastInterface; + private XRReferencePoint m_ReferencePointsInterface; + private XRSession m_SessionInterface; + + override internal void Initialize() + { + m_DepthInterface = new XRDepth(m_Ptr, this); + m_PlanesInterface = new XRPlane(m_Ptr, this); + m_RaycastInterface = new XRRaycast(m_Ptr, this); + m_ReferencePointsInterface = new XRReferencePoint(m_Ptr, this); + m_SessionInterface = new XRSession(m_Ptr, this); + } + } +} diff --git a/Modules/XR/Subsystems/Environment/XREnvironmentSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/Environment/XREnvironmentSubsystemDescriptor.bindings.cs new file mode 100644 index 0000000000..7784b4a96a --- /dev/null +++ b/Modules/XR/Subsystems/Environment/XREnvironmentSubsystemDescriptor.bindings.cs @@ -0,0 +1,30 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace UnityEngine.Experimental.XR +{ + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeType(Header = "Modules/XR/Subsystems/Environment/XREnvironmentSubsystemDescriptor.h")] + [UsedByNativeCode("xrEnvironmentSubsystemDescriptor")] + public class XREnvironmentSubsystemDescriptor : XRSubsystemDescriptor + { + [NativeConditional("ENABLE_XR")] + public extern bool SupportsFeaturePoints { get; } + + [NativeConditional("ENABLE_XR")] + public extern bool SupportsPlaneFinding { get; } + + [NativeConditional("ENABLE_XR")] + public extern bool SupportsReferencePoints { get; } + + [NativeConditional("ENABLE_XR")] + public extern bool SupportsLightEstimation { get; } + } +} diff --git a/Modules/XR/Subsystems/Input/XRInputInstance.bindings.cs b/Modules/XR/Subsystems/Input/XRInputInstance.bindings.cs new file mode 100644 index 0000000000..f865953544 --- /dev/null +++ b/Modules/XR/Subsystems/Input/XRInputInstance.bindings.cs @@ -0,0 +1,18 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace UnityEngine.Experimental.XR +{ + [NativeType(Header = "Modules/XR/Subsystems/Input/XRInputInstance.h")] + [UsedByNativeCode] + public class XRInputInstance : XRInstance + { + } +} diff --git a/Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.bindings.cs new file mode 100644 index 0000000000..13c8e5503a --- /dev/null +++ b/Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.bindings.cs @@ -0,0 +1,17 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace UnityEngine.Experimental.XR +{ + [NativeType(Header = "Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.h")] + [UsedByNativeCode] + public class XRInputSubsystemDescriptor : XRSubsystemDescriptor + {} +} diff --git a/Modules/XR/XRSubsystemManager.bindings.cs b/Modules/XR/XRSubsystemManager.bindings.cs index 4d7454d82b..c8ff86206b 100644 --- a/Modules/XR/XRSubsystemManager.bindings.cs +++ b/Modules/XR/XRSubsystemManager.bindings.cs @@ -62,6 +62,7 @@ internal static void Internal_InitializeManagedInstance(IntPtr ptr, XRInstance i { inst.m_Ptr = ptr; inst.SetHandle(inst); + inst.Initialize(); s_SubsystemInstances.Add(inst); } @@ -169,6 +170,7 @@ public class XRInstance internal IXRSubsystemDescriptor m_subsystemDescriptor; extern internal void SetHandle(XRInstance inst); + virtual internal void Initialize() {} extern public void Start(); extern public void Stop(); public void Destroy() diff --git a/Projects/CSharp/UnityEditor.csproj b/Projects/CSharp/UnityEditor.csproj index cee9e25fa9..8fd6256b33 100644 --- a/Projects/CSharp/UnityEditor.csproj +++ b/Projects/CSharp/UnityEditor.csproj @@ -22,13 +22,13 @@ full false bin\Debug\ - DEBUG;TRACE;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_UNLOCKED_DIAGNOSTIC_SWITCHES;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_LOCALIZATION;COMBINED_ASSEMBLIES;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_ALTERNATIVE_LISTEN_PORT;ENABLE_AUDIO_MANAGER_BASED_SCHEDULING;ENABLE_MONO;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_SUBSTANCE;ENABLE_VERSION_CONTROL_INTEGRATION;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_UNITYWEBREQUEST;ENABLE_VIDEO;PLAYERCONNECTION_LISTENS_FIXED_PORT;UNITY_EDITOR;ENABLE_HOLOLENS_MODULE_API;UNITY_PS4_API;ENABLE_VR;ENABLE_CLOUD_SERVICES_COLLAB_TESTING;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_CRUNCH_TEXTURE_COMPRESSION;UNITY_EDITOR_API;UNITY_ANDROID_API;UNITY_STANDALONE_WIN_API;UNITY_STANDALONE_OSX_API;UNITY_PSVITA_API;UNITY_XBOXONE_API;UNITY_SWITCH_API;UNITY_IPHONE_API;UNITY_TVOS_API;UNITY_STANDALONE_LINUX_API;UNITY_TIZEN_API;UNITY_WEBGL_API;UNITY_PS4_API;UNITY_METRO_API;UNITY_N3DS_API;UNITY_ASSEMBLIES_API;UNITY_ASSERTIONS + DEBUG;TRACE;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_UNLOCKED_DIAGNOSTIC_SWITCHES;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_LOCALIZATION;COMBINED_ASSEMBLIES;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_ALTERNATIVE_LISTEN_PORT;ENABLE_AUDIO_MANAGER_BASED_SCHEDULING;ENABLE_MONO;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_VERSION_CONTROL_INTEGRATION;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_UNITYWEBREQUEST;ENABLE_VIDEO;PLAYERCONNECTION_LISTENS_FIXED_PORT;UNITY_EDITOR;ENABLE_HOLOLENS_MODULE_API;UNITY_PS4_API;ENABLE_VR;ENABLE_CLOUD_SERVICES_COLLAB_TESTING;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_CRUNCH_TEXTURE_COMPRESSION;UNITY_EDITOR_API;UNITY_ANDROID_API;UNITY_STANDALONE_WIN_API;UNITY_STANDALONE_OSX_API;UNITY_PSVITA_API;UNITY_XBOXONE_API;UNITY_SWITCH_API;UNITY_IPHONE_API;UNITY_TVOS_API;UNITY_STANDALONE_LINUX_API;UNITY_TIZEN_API;UNITY_WEBGL_API;UNITY_PS4_API;UNITY_METRO_API;UNITY_N3DS_API;UNITY_ASSEMBLIES_API;UNITY_ASSERTIONS pdbonly true bin\Release\ - TRACE;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_UNLOCKED_DIAGNOSTIC_SWITCHES;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_LOCALIZATION;COMBINED_ASSEMBLIES;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_ALTERNATIVE_LISTEN_PORT;ENABLE_AUDIO_MANAGER_BASED_SCHEDULING;ENABLE_MONO;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_SUBSTANCE;ENABLE_VERSION_CONTROL_INTEGRATION;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_UNITYWEBREQUEST;ENABLE_VIDEO;PLAYERCONNECTION_LISTENS_FIXED_PORT;UNITY_EDITOR;ENABLE_HOLOLENS_MODULE_API;UNITY_PS4_API;ENABLE_VR;ENABLE_CLOUD_SERVICES_COLLAB_TESTING;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_CRUNCH_TEXTURE_COMPRESSION;UNITY_EDITOR_API;UNITY_ANDROID_API;UNITY_STANDALONE_WIN_API;UNITY_STANDALONE_OSX_API;UNITY_PSVITA_API;UNITY_XBOXONE_API;UNITY_SWITCH_API;UNITY_IPHONE_API;UNITY_TVOS_API;UNITY_STANDALONE_LINUX_API;UNITY_TIZEN_API;UNITY_WEBGL_API;UNITY_PS4_API;UNITY_METRO_API;UNITY_N3DS_API;UNITY_ASSEMBLIES_API;UNITY_ASSERTIONS + TRACE;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_UNLOCKED_DIAGNOSTIC_SWITCHES;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_LOCALIZATION;COMBINED_ASSEMBLIES;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_ALTERNATIVE_LISTEN_PORT;ENABLE_AUDIO_MANAGER_BASED_SCHEDULING;ENABLE_MONO;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_VERSION_CONTROL_INTEGRATION;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_UNITYWEBREQUEST;ENABLE_VIDEO;PLAYERCONNECTION_LISTENS_FIXED_PORT;UNITY_EDITOR;ENABLE_HOLOLENS_MODULE_API;UNITY_PS4_API;ENABLE_VR;ENABLE_CLOUD_SERVICES_COLLAB_TESTING;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_CRUNCH_TEXTURE_COMPRESSION;UNITY_EDITOR_API;UNITY_ANDROID_API;UNITY_STANDALONE_WIN_API;UNITY_STANDALONE_OSX_API;UNITY_PSVITA_API;UNITY_XBOXONE_API;UNITY_SWITCH_API;UNITY_IPHONE_API;UNITY_TVOS_API;UNITY_STANDALONE_LINUX_API;UNITY_TIZEN_API;UNITY_WEBGL_API;UNITY_PS4_API;UNITY_METRO_API;UNITY_N3DS_API;UNITY_ASSEMBLIES_API;UNITY_ASSERTIONS @@ -483,9 +483,6 @@ Editor\Mono\PlayerSettingsPS4.bindings.cs - -Editor\Mono\SubstanceImporter.cs - Editor\Mono\DrivenRectTransformUndo.cs @@ -696,9 +693,6 @@ Editor\Mono\ImportSettings\EditorPluginImporterExtension.cs - -Editor\Mono\ImportSettings\SubstanceImporterInspector.cs - Editor\Mono\ImportSettings\AssetImporterEditor.cs @@ -2481,9 +2475,6 @@ Editor\Mono\Inspector\MaterialEditor.cs - -Editor\Mono\Inspector\ProceduralMaterialInspector.cs - Editor\Mono\Inspector\TargetJoint2DEditor.cs @@ -2607,9 +2598,6 @@ Editor\Mono\Inspector\AssetStoreAssetInspector.cs - -Editor\Mono\Inspector\ProceduralTextureInspector.cs - Editor\Mono\Inspector\NavMeshAgentInspector.cs @@ -2991,32 +2979,20 @@ Editor\Mono\Inspector\TextMeshInspector.cs - -Editor\Mono\Inspector\AddComponent\AddComponentWindow.cs - - -Editor\Mono\Inspector\AddComponent\ComponentDropdownElement.cs - - -Editor\Mono\Inspector\AddComponent\NewScriptDropdownElement.cs - - -Editor\Mono\Inspector\SearchableDropdown\DropdownElement.cs - - -Editor\Mono\Inspector\SearchableDropdown\StatefulAdvancedDropdown.cs + +Editor\Mono\Inspector\AddComponent\NewScriptDropdownItem.cs - -Editor\Mono\Inspector\SearchableDropdown\AdvancedDropdown.cs + +Editor\Mono\Inspector\AddComponent\AddComponentDataSource.cs - -Editor\Mono\Inspector\SearchableDropdown\GroupDropdownElement.cs + +Editor\Mono\Inspector\AddComponent\AddComponentWindow.cs - -Editor\Mono\Inspector\SearchableDropdown\StatelessAdvancedDropdown.cs + +Editor\Mono\Inspector\AddComponent\AddComponentGUI.cs - -Editor\Mono\Inspector\SearchableDropdown\AdvancedDropdownWindow.cs + +Editor\Mono\Inspector\AddComponent\ComponentDropdownItem.cs Editor\Mono\Inspector\Enlighten\LightmapParameters.cs @@ -3066,6 +3042,27 @@ Editor\Mono\Inspector\PlayerSettingsEditor\PlayerSettingsSplashScreenEditor.bindings.cs + +Editor\Mono\Inspector\AdvancedDropdown\StatefulAdvancedDropdown.cs + + +Editor\Mono\Inspector\AdvancedDropdown\AdvancedDropdownItem.cs + + +Editor\Mono\Inspector\AdvancedDropdown\AdvancedDropdownGUI.cs + + +Editor\Mono\Inspector\AdvancedDropdown\StatelessAdvancedDropdown.cs + + +Editor\Mono\Inspector\AdvancedDropdown\AdvancedDropdownWindow.cs + + +Editor\Mono\Inspector\AdvancedDropdown\AdvancedDropdownSimpleDataSource.cs + + +Editor\Mono\Inspector\AdvancedDropdown\AdvancedDropdownDataSource.cs + Editor\Mono\SerializedProperty\SerializedPropertyTable.cs @@ -3488,9 +3485,6 @@ artifacts\generated\bindings_old\common\Editor\StateMachineBindings.gen.cs - -artifacts\generated\bindings_old\common\Editor\SubstanceEditorUtilityBindings.gen.cs - artifacts\generated\bindings_old\common\Editor\HighlighterBindings.gen.cs diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index 2d6d5938a1..c39951de0e 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -23,13 +23,13 @@ full false bin\Debug\ - DEBUG;TRACE;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_UNLOCKED_DIAGNOSTIC_SWITCHES;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_LOCALIZATION;COMBINED_ASSEMBLIES;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_ALTERNATIVE_LISTEN_PORT;ENABLE_AUDIO_MANAGER_BASED_SCHEDULING;ENABLE_MONO;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_SUBSTANCE;ENABLE_VERSION_CONTROL_INTEGRATION;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_UNITYWEBREQUEST;ENABLE_VIDEO;PLAYERCONNECTION_LISTENS_FIXED_PORT;UNITY_EDITOR;ENABLE_HOLOLENS_MODULE_API;UNITY_PS4_API;ENABLE_VR;ENABLE_CLOUD_SERVICES_COLLAB_TESTING;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_CRUNCH_TEXTURE_COMPRESSION;UNITY_EDITOR_API;UNITY_ANDROID_API;UNITY_STANDALONE_WIN_API;UNITY_STANDALONE_OSX_API;UNITY_PSVITA_API;UNITY_XBOXONE_API;UNITY_SWITCH_API;UNITY_IPHONE_API;UNITY_TVOS_API;UNITY_STANDALONE_LINUX_API;UNITY_TIZEN_API;UNITY_WEBGL_API;UNITY_PS4_API;UNITY_METRO_API;UNITY_N3DS_API;UNITY_ASSEMBLIES_API;UNITY_ASSERTIONS + DEBUG;TRACE;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_UNLOCKED_DIAGNOSTIC_SWITCHES;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_LOCALIZATION;COMBINED_ASSEMBLIES;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_ALTERNATIVE_LISTEN_PORT;ENABLE_AUDIO_MANAGER_BASED_SCHEDULING;ENABLE_MONO;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_VERSION_CONTROL_INTEGRATION;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_UNITYWEBREQUEST;ENABLE_VIDEO;PLAYERCONNECTION_LISTENS_FIXED_PORT;UNITY_EDITOR;ENABLE_HOLOLENS_MODULE_API;UNITY_PS4_API;ENABLE_VR;ENABLE_CLOUD_SERVICES_COLLAB_TESTING;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_CRUNCH_TEXTURE_COMPRESSION;UNITY_EDITOR_API;UNITY_ANDROID_API;UNITY_STANDALONE_WIN_API;UNITY_STANDALONE_OSX_API;UNITY_PSVITA_API;UNITY_XBOXONE_API;UNITY_SWITCH_API;UNITY_IPHONE_API;UNITY_TVOS_API;UNITY_STANDALONE_LINUX_API;UNITY_TIZEN_API;UNITY_WEBGL_API;UNITY_PS4_API;UNITY_METRO_API;UNITY_N3DS_API;UNITY_ASSEMBLIES_API;UNITY_ASSERTIONS pdbonly true bin\Release\ - TRACE;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_UNLOCKED_DIAGNOSTIC_SWITCHES;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_LOCALIZATION;COMBINED_ASSEMBLIES;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_ALTERNATIVE_LISTEN_PORT;ENABLE_AUDIO_MANAGER_BASED_SCHEDULING;ENABLE_MONO;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_SUBSTANCE;ENABLE_VERSION_CONTROL_INTEGRATION;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_UNITYWEBREQUEST;ENABLE_VIDEO;PLAYERCONNECTION_LISTENS_FIXED_PORT;UNITY_EDITOR;ENABLE_HOLOLENS_MODULE_API;UNITY_PS4_API;ENABLE_VR;ENABLE_CLOUD_SERVICES_COLLAB_TESTING;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_CRUNCH_TEXTURE_COMPRESSION;UNITY_EDITOR_API;UNITY_ANDROID_API;UNITY_STANDALONE_WIN_API;UNITY_STANDALONE_OSX_API;UNITY_PSVITA_API;UNITY_XBOXONE_API;UNITY_SWITCH_API;UNITY_IPHONE_API;UNITY_TVOS_API;UNITY_STANDALONE_LINUX_API;UNITY_TIZEN_API;UNITY_WEBGL_API;UNITY_PS4_API;UNITY_METRO_API;UNITY_N3DS_API;UNITY_ASSEMBLIES_API;UNITY_ASSERTIONS + TRACE;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_UNLOCKED_DIAGNOSTIC_SWITCHES;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_LOCALIZATION;COMBINED_ASSEMBLIES;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_ALTERNATIVE_LISTEN_PORT;ENABLE_AUDIO_MANAGER_BASED_SCHEDULING;ENABLE_MONO;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_VERSION_CONTROL_INTEGRATION;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_UNITYWEBREQUEST;ENABLE_VIDEO;PLAYERCONNECTION_LISTENS_FIXED_PORT;UNITY_EDITOR;ENABLE_HOLOLENS_MODULE_API;UNITY_PS4_API;ENABLE_VR;ENABLE_CLOUD_SERVICES_COLLAB_TESTING;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_CRUNCH_TEXTURE_COMPRESSION;UNITY_EDITOR_API;UNITY_ANDROID_API;UNITY_STANDALONE_WIN_API;UNITY_STANDALONE_OSX_API;UNITY_PSVITA_API;UNITY_XBOXONE_API;UNITY_SWITCH_API;UNITY_IPHONE_API;UNITY_TVOS_API;UNITY_STANDALONE_LINUX_API;UNITY_TIZEN_API;UNITY_WEBGL_API;UNITY_PS4_API;UNITY_METRO_API;UNITY_N3DS_API;UNITY_ASSEMBLIES_API;UNITY_ASSERTIONS @@ -307,6 +307,9 @@ Runtime\Export\MonoBehaviour.bindings.cs + +Runtime\Export\iOSSystemGestureDeferMode.cs + Runtime\Export\WaitForFixedUpdate.cs @@ -664,9 +667,6 @@ Runtime\Export\GI\Lightmapping.cs - -Runtime\Export\GI\ScriptBindings\Lights.bindings.cs - Runtime\Export\Unsafe\UnsafeUtility.bindings.cs @@ -895,9 +895,6 @@ artifacts\generated\bindings_old\common\Core\LineUtilityBindings.gen.cs - -artifacts\generated\bindings_old\common\Core\SubstanceUtilityBindings.gen.cs - artifacts\generated\bindings_old\common\Core\TextureBindings.gen.cs @@ -1533,6 +1530,12 @@ Modules\SpriteShape\Public\ScriptBindings\SpriteShapeUtility.bindings.cs + +Modules\Substance\SubstanceUtility.bindings.cs + + +Modules\Substance\SubstanceUtility.cs + Modules\Terrain\Public\Terrain.bindings.cs @@ -1971,11 +1974,44 @@ Modules\XR\XRSubsystemManager.bindings.cs + +Modules\XR\Subsystems\Camera\XRCameraInstance.bindings.cs + + +Modules\XR\Subsystems\Camera\XRCameraSubsystemDescriptor.bindings.cs + + +Modules\XR\Subsystems\Environment\XREnvironment.bindings.cs + + +Modules\XR\Subsystems\Environment\XREnvironmentSubsystemDescriptor.bindings.cs + + +Modules\XR\Subsystems\Environment\Depth\XRDepth.bindings.cs + + +Modules\XR\Subsystems\Environment\Planes\XRPlane.bindings.cs + + +Modules\XR\Subsystems\Environment\Raycast\XRRaycast.bindings.cs + + +Modules\XR\Subsystems\Environment\ReferencePoints\XRReferencePoint.bindings.cs + + +Modules\XR\Subsystems\Environment\Session\XRSession.bindings.cs + Modules\XR\Subsystems\Example\XRExampleInstance.bindings.cs Modules\XR\Subsystems\Example\XRExampleSubsystemDescriptor.bindings.cs + + +Modules\XR\Subsystems\Input\XRInputInstance.bindings.cs + + +Modules\XR\Subsystems\Input\XRInputSubsystemDescriptor.bindings.cs diff --git a/README.md b/README.md index 02b2c5b971..3f2f9715d7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.1.0b1 C# reference source code +## Unity 2018.1.0b2 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs b/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs index db07d45ee4..64774c158f 100644 --- a/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs +++ b/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs @@ -198,5 +198,7 @@ public static NativeArray GetDeformableVertices(this SpriteRenderer spr extern private static SpriteChannelInfo GetDeformableChannelInfo(this SpriteRenderer sprite, VertexAttribute channel); + + extern internal static void SetLocalAABB(this SpriteRenderer renderer, Bounds aabb); } } diff --git a/Runtime/Export/GI/Lightmapping.cs b/Runtime/Export/GI/Lightmapping.cs index 5e4784646d..4709ed8299 100644 --- a/Runtime/Export/GI/Lightmapping.cs +++ b/Runtime/Export/GI/Lightmapping.cs @@ -5,6 +5,8 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine.Rendering; +using Unity.Collections; +using NativeArrayUnsafeUtility = Unity.Collections.LowLevel.Unsafe.NativeArrayUnsafeUtility; namespace UnityEngine { @@ -351,21 +353,19 @@ public static void Extract(Light l, ref RectangleLight rect) public static class Lightmapping { - public delegate void RequestLightsDelegate(List requests, List lightsOutput); + public delegate void RequestLightsDelegate(Light[] requests, NativeArray lightsOutput); public static void SetDelegate(RequestLightsDelegate del) { s_RequestLightsDelegate = del != null ? del : s_DefaultDelegate; } public static void ResetDelegate() { s_RequestLightsDelegate = s_DefaultDelegate; } - public static void RequestLights() + + [UnityEngine.Scripting.UsedByNativeCode] + internal static void RequestLights(Light[] lights, System.IntPtr outLightsPtr, int outLightsCount) { - s_Requests.Clear(); - Lights.GetModified(s_Requests); - s_Storage.Clear(); - s_RequestLightsDelegate(s_Requests, s_Storage); - Lights.SetFromScript(s_Storage); + var outLights = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(outLightsPtr, outLightsCount, Allocator.None); + s_RequestLightsDelegate(lights, outLights); } - private static readonly List s_Storage = new List(); - private static readonly List s_Requests = new List(); - private static readonly RequestLightsDelegate s_DefaultDelegate = (List requests, List lightsOutput) => + + private static readonly RequestLightsDelegate s_DefaultDelegate = (Light[] requests, NativeArray lightsOutput) => { // get all lights in the scene DirectionalLight dir = new DirectionalLight(); @@ -373,8 +373,9 @@ public static void RequestLights() SpotLight spot = new SpotLight(); RectangleLight rect = new RectangleLight(); LightDataGI ld = new LightDataGI(); - foreach (var l in requests) + for (int i = 0; i < requests.Length; i++) { + Light l = requests[i]; switch (l.type) { case UnityEngine.LightType.Directional: LightmapperUtils.Extract(l, ref dir); ld.Init(ref dir); break; @@ -383,7 +384,7 @@ public static void RequestLights() case UnityEngine.LightType.Area: LightmapperUtils.Extract(l, ref rect); ld.Init(ref rect); break; default: ld.InitNoBake(l.GetInstanceID()); break; } - lightsOutput.Add(ld); + lightsOutput[i] = ld; } }; private static RequestLightsDelegate s_RequestLightsDelegate = s_DefaultDelegate; diff --git a/Runtime/Export/GI/ScriptBindings/Lights.bindings.cs b/Runtime/Export/GI/ScriptBindings/Lights.bindings.cs deleted file mode 100644 index e47155470e..0000000000 --- a/Runtime/Export/GI/ScriptBindings/Lights.bindings.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using System.Collections.Generic; - -namespace UnityEngine -{ - namespace Experimental.GlobalIllumination - { - [NativeConditional("ENABLE_RUNTIME_GI")] - [NativeHeader("Runtime/Export/GI/ScriptBindings/Lights.h")] - internal static class Lights - { - // called by the Lightmapper (C# -> C++) - public static extern void GetModified(List outLights); - - public static void SetFromScript(List lights) - { - // there's a copy here until the new binding system properly supports passing down List<...> - SetFromScript_Internal((LightDataGI[])NoAllocHelpers.ExtractArrayFromList(lights), - NoAllocHelpers.SafeLength(lights)); - } - - extern private static void SetFromScript_Internal(LightDataGI[] lights, int count); - - // called by the baking backends (C++ -> C#) - [RequiredByNativeCode] - private static void RequestLights_Internal() - { - Lightmapping.RequestLights(); - } - } - } -} diff --git a/Runtime/Export/Graphics.bindings.cs b/Runtime/Export/Graphics.bindings.cs index 3a3b39ec55..d6395e55b2 100644 --- a/Runtime/Export/Graphics.bindings.cs +++ b/Runtime/Export/Graphics.bindings.cs @@ -118,6 +118,7 @@ public static void SetResolution(int width, int height, bool fullscreen) namespace UnityEngine { + [NativeHeader("Runtime/Camera/LightProbeProxyVolume.h")] [NativeHeader("Runtime/Graphics/CopyTexture.h")] [NativeHeader("Runtime/Graphics/GraphicsScriptBindings.h")] [NativeHeader("Runtime/Shaders/ComputeShader.h")] @@ -134,42 +135,42 @@ public partial class Graphics [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, null, 0, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, null, 0, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer, Camera camera) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, 0, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, 0, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer, Camera camera, int submeshIndex) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, bool castShadows) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, bool castShadows, bool receiveShadows) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, receiveShadows, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, receiveShadows, null, LightProbeUsage.BlendProbes, null); } public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer, [uei.DefaultValue("null")] Camera camera, [uei.DefaultValue("0")] int submeshIndex, [uei.DefaultValue("null")] MaterialPropertyBlock properties, [uei.DefaultValue("true")] bool castShadows, [uei.DefaultValue("true")] bool receiveShadows, [uei.DefaultValue("true")] bool useLightProbes) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, receiveShadows, null, useLightProbes ? LightProbeUsage.BlendProbes : LightProbeUsage.Off); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, receiveShadows, null, useLightProbes ? LightProbeUsage.BlendProbes : LightProbeUsage.Off, null); } #endregion @@ -178,24 +179,24 @@ public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Ma [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, Transform probeAnchor) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, probeAnchor, LightProbeUsage.BlendProbes); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, probeAnchor, LightProbeUsage.BlendProbes, null); } public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows, [uei.DefaultValue("true")] bool receiveShadows, [uei.DefaultValue("null")] Transform probeAnchor, [uei.DefaultValue("true")] bool useLightProbes) { - DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, probeAnchor, useLightProbes ? LightProbeUsage.BlendProbes : LightProbeUsage.Off); + DrawMesh(mesh, Matrix4x4.TRS(position, rotation, Vector3.one), material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, probeAnchor, useLightProbes ? LightProbeUsage.BlendProbes : LightProbeUsage.Off, null); } #endregion @@ -204,42 +205,42 @@ public static void DrawMesh(Mesh mesh, Vector3 position, Quaternion rotation, Ma [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer) { - DrawMesh(mesh, matrix, material, layer, null, 0, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, matrix, material, layer, null, 0, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera) { - DrawMesh(mesh, matrix, material, layer, camera, 0, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, matrix, material, layer, camera, 0, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex) { - DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, null, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties) { - DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, ShadowCastingMode.On, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, bool castShadows) { - DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, bool castShadows, bool receiveShadows) { - DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, receiveShadows, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, receiveShadows, null, LightProbeUsage.BlendProbes, null); } public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, [uei.DefaultValue("null")] Camera camera, [uei.DefaultValue("0")] int submeshIndex, [uei.DefaultValue("null")] MaterialPropertyBlock properties, [uei.DefaultValue("true")] bool castShadows, [uei.DefaultValue("true")] bool receiveShadows, [uei.DefaultValue("true")] bool useLightProbes) { - DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, receiveShadows, null, useLightProbes ? LightProbeUsage.BlendProbes : LightProbeUsage.Off); + DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows ? ShadowCastingMode.On : ShadowCastingMode.Off, receiveShadows, null, useLightProbes ? LightProbeUsage.BlendProbes : LightProbeUsage.Off, null); } #endregion @@ -248,83 +249,95 @@ public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows) { - DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows, true, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows, true, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows) { - DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, null, LightProbeUsage.BlendProbes); + DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, Transform probeAnchor) { - DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, probeAnchor, LightProbeUsage.BlendProbes); + DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, probeAnchor, LightProbeUsage.BlendProbes, null); } public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows, [uei.DefaultValue("true")] bool receiveShadows, [uei.DefaultValue("null")] Transform probeAnchor, [uei.DefaultValue("true")] bool useLightProbes) { - DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, probeAnchor, useLightProbes ? LightProbeUsage.BlendProbes : LightProbeUsage.Off); + DrawMesh(mesh, matrix, material, layer, camera, submeshIndex, properties, castShadows, receiveShadows, probeAnchor, useLightProbes ? LightProbeUsage.BlendProbes : LightProbeUsage.Off, null); } + [uei.ExcludeFromDocs] public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, Transform probeAnchor, LightProbeUsage lightProbeUsage) { - if (lightProbeUsage == LightProbeUsage.UseProxyVolume) - throw new ArgumentException("lightProbeUsage", String.Format("LightProbeUsage {0} cannot be specified for DrawMesh.", lightProbeUsage.ToString())); - Internal_DrawMesh(mesh, submeshIndex, matrix, material, layer, camera, properties, castShadows, receiveShadows, probeAnchor, lightProbeUsage); + Internal_DrawMesh(mesh, submeshIndex, matrix, material, layer, camera, properties, castShadows, receiveShadows, probeAnchor, lightProbeUsage, null); + } + + public static void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int layer, Camera camera, int submeshIndex, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, Transform probeAnchor, LightProbeUsage lightProbeUsage, [uei.DefaultValue("null")] LightProbeProxyVolume lightProbeProxyVolume) + { + if (lightProbeUsage == LightProbeUsage.UseProxyVolume && lightProbeProxyVolume == null) + throw new ArgumentException("lightProbeProxyVolume", "Argument lightProbeProxyVolume must not be null if lightProbeUsage is set to UseProxyVolume."); + Internal_DrawMesh(mesh, submeshIndex, matrix, material, layer, camera, properties, castShadows, receiveShadows, probeAnchor, lightProbeUsage, lightProbeProxyVolume); } #endregion [FreeFunction("DrawMeshMatrixFromScript")] - extern internal static void Internal_DrawMesh(Mesh mesh, int submeshIndex, Matrix4x4 matrix, Material material, int layer, Camera camera, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, Transform probeAnchor, LightProbeUsage lightProbeUsage); + extern internal static void Internal_DrawMesh(Mesh mesh, int submeshIndex, Matrix4x4 matrix, Material material, int layer, Camera camera, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, Transform probeAnchor, LightProbeUsage lightProbeUsage, LightProbeProxyVolume lightProbeProxyVolume); // TODO: Migrate these dreadful overloads to default arguments. - #region public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count = matrices.Length, MaterialPropertyBlock properties = null, ShadowCastingMode castShadows = ShadowCastingMode.On, bool receiveShadows = true, int layer = 0, Camera camera = null, LightProbeUsage lightProbeUsage = LightProbeUsage.BlendProbes) + #region public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count = matrices.Length, MaterialPropertyBlock properties = null, ShadowCastingMode castShadows = ShadowCastingMode.On, bool receiveShadows = true, int layer = 0, Camera camera = null, LightProbeUsage lightProbeUsage = LightProbeUsage.BlendProbes, LightProbeProxyVolume lightProbeProxyVolume = null) [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, matrices.Length, null, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, matrices.Length, null, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, null, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, null, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count, MaterialPropertyBlock properties) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count, MaterialPropertyBlock properties, ShadowCastingMode castShadows) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, receiveShadows, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, receiveShadows, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, receiveShadows, layer, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, receiveShadows, layer, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer, Camera camera) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, receiveShadows, layer, camera, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, receiveShadows, layer, camera, LightProbeUsage.BlendProbes, null); + } + + [uei.ExcludeFromDocs] + public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer, Camera camera, LightProbeUsage lightProbeUsage) + { + DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, receiveShadows, layer, camera, lightProbeUsage, null); } - public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, [uei.DefaultValue("matrices.Length")] int count, [uei.DefaultValue("null")] MaterialPropertyBlock properties, [uei.DefaultValue("ShadowCastingMode.On")] ShadowCastingMode castShadows, [uei.DefaultValue("true")] bool receiveShadows, [uei.DefaultValue("0")] int layer, [uei.DefaultValue("null")] Camera camera, [uei.DefaultValue("LightProbeUsage.BlendProbes")] LightProbeUsage lightProbeUsage) + public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, [uei.DefaultValue("matrices.Length")] int count, [uei.DefaultValue("null")] MaterialPropertyBlock properties, [uei.DefaultValue("ShadowCastingMode.On")] ShadowCastingMode castShadows, [uei.DefaultValue("true")] bool receiveShadows, [uei.DefaultValue("0")] int layer, [uei.DefaultValue("null")] Camera camera, [uei.DefaultValue("LightProbeUsage.BlendProbes")] LightProbeUsage lightProbeUsage, [uei.DefaultValue("null")] LightProbeProxyVolume lightProbeProxyVolume) { if (!SystemInfo.supportsInstancing) throw new InvalidOperationException("Instancing is not supported."); @@ -340,110 +353,122 @@ public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material mater throw new ArgumentNullException("matrices"); else if (count < 0 || count > Mathf.Min(kMaxDrawMeshInstanceCount, matrices.Length)) throw new ArgumentOutOfRangeException("count", String.Format("Count must be in the range of 0 to {0}.", Mathf.Min(kMaxDrawMeshInstanceCount, matrices.Length))); - else if (lightProbeUsage == LightProbeUsage.UseProxyVolume) - throw new ArgumentException("lightProbeUsage", String.Format("LightProbeUsage {0} cannot be specified for DrawMeshInstanced.", lightProbeUsage.ToString())); + else if (lightProbeUsage == LightProbeUsage.UseProxyVolume && lightProbeProxyVolume == null) + throw new ArgumentException("lightProbeProxyVolume", "Argument lightProbeProxyVolume must not be null if lightProbeUsage is set to UseProxyVolume."); if (count > 0) - Internal_DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, receiveShadows, layer, camera, lightProbeUsage); + Internal_DrawMeshInstanced(mesh, submeshIndex, material, matrices, count, properties, castShadows, receiveShadows, layer, camera, lightProbeUsage, lightProbeProxyVolume); } #endregion // TODO: Migrate these dreadful overloads to default arguments. - #region public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices, MaterialPropertyBlock properties = null, ShadowCastingMode castShadows = ShadowCastingMode.On, bool receiveShadows = true, int layer = 0, Camera camera = null, LightProbeUsage lightProbeUsage = LightProbeUsage.BlendProbes) + #region public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices, MaterialPropertyBlock properties = null, ShadowCastingMode castShadows = ShadowCastingMode.On, bool receiveShadows = true, int layer = 0, Camera camera = null, LightProbeUsage lightProbeUsage = LightProbeUsage.BlendProbes, LightProbeyProxyVolume lightProbeProxyVolume = null) [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, null, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, null, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices, MaterialPropertyBlock properties) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices, MaterialPropertyBlock properties, ShadowCastingMode castShadows) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, castShadows, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, castShadows, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, castShadows, receiveShadows, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, castShadows, receiveShadows, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, castShadows, receiveShadows, layer, null, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, castShadows, receiveShadows, layer, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer, Camera camera) { - DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, castShadows, receiveShadows, layer, camera, LightProbeUsage.BlendProbes); + DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, castShadows, receiveShadows, layer, camera, LightProbeUsage.BlendProbes, null); } - public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices, [uei.DefaultValue("null")] MaterialPropertyBlock properties, [uei.DefaultValue("ShadowCastingMode.On")] ShadowCastingMode castShadows, [uei.DefaultValue("true")] bool receiveShadows, [uei.DefaultValue("0")] int layer, [uei.DefaultValue("null")] Camera camera, [uei.DefaultValue("LightProbeUsage.BlendProbes")] LightProbeUsage lightProbeUsage) + [uei.ExcludeFromDocs] + public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer, Camera camera, LightProbeUsage lightProbeUsage) + { + DrawMeshInstanced(mesh, submeshIndex, material, matrices, properties, castShadows, receiveShadows, layer, camera, lightProbeUsage, null); + } + + public static void DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, List matrices, [uei.DefaultValue("null")] MaterialPropertyBlock properties, [uei.DefaultValue("ShadowCastingMode.On")] ShadowCastingMode castShadows, [uei.DefaultValue("true")] bool receiveShadows, [uei.DefaultValue("0")] int layer, [uei.DefaultValue("null")] Camera camera, [uei.DefaultValue("LightProbeUsage.BlendProbes")] LightProbeUsage lightProbeUsage, [uei.DefaultValue("null")] LightProbeProxyVolume lightProbeProxyVolume) { if (matrices == null) throw new ArgumentNullException("matrices"); - DrawMeshInstanced(mesh, submeshIndex, material, NoAllocHelpers.ExtractArrayFromListT(matrices), matrices.Count, properties, castShadows, receiveShadows, layer, camera, lightProbeUsage); + DrawMeshInstanced(mesh, submeshIndex, material, NoAllocHelpers.ExtractArrayFromListT(matrices), matrices.Count, properties, castShadows, receiveShadows, layer, camera, lightProbeUsage, lightProbeProxyVolume); } #endregion [FreeFunction("DrawMeshInstancedFromScript")] - extern internal static void Internal_DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer, Camera camera, LightProbeUsage lightProbeUsage); + extern internal static void Internal_DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, Matrix4x4[] matrices, int count, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer, Camera camera, LightProbeUsage lightProbeUsage, LightProbeProxyVolume lightProbeProxyVolume); - #region public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset = 0, MaterialPropertyBlock properties = null, ShadowCastingMode castShadows = ShadowCastingMode.On, bool receiveShadows = true, int layer = 0, Camera camera = null, LightProbeUsage lightProbeUsage = LightProbeUsage.BlendProbes) + #region public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset = 0, MaterialPropertyBlock properties = null, ShadowCastingMode castShadows = ShadowCastingMode.On, bool receiveShadows = true, int layer = 0, Camera camera = null, LightProbeUsage lightProbeUsage = LightProbeUsage.BlendProbes, LightProbeProxyVolume lightProbeProxyVolume = null) [uei.ExcludeFromDocs] public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs) { - DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, 0, null, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, 0, null, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset) { - DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, null, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, null, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties) { - DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, ShadowCastingMode.On, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties, ShadowCastingMode castShadows) { - DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, true, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, true, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows) { - DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, receiveShadows, 0, null, LightProbeUsage.BlendProbes); + DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, receiveShadows, 0, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer) { - DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, receiveShadows, layer, null, LightProbeUsage.BlendProbes); + DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, receiveShadows, layer, null, LightProbeUsage.BlendProbes, null); } [uei.ExcludeFromDocs] public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer, Camera camera) { - DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, receiveShadows, layer, camera, LightProbeUsage.BlendProbes); + DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, receiveShadows, layer, camera, LightProbeUsage.BlendProbes, null); + } + + [uei.ExcludeFromDocs] + public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer, Camera camera, LightProbeUsage lightProbeUsage) + { + DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, receiveShadows, layer, camera, lightProbeUsage, null); } - public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, [uei.DefaultValue("0")] int argsOffset, [uei.DefaultValue("null")] MaterialPropertyBlock properties, [uei.DefaultValue("ShadowCastingMode.On")] ShadowCastingMode castShadows, [uei.DefaultValue("true")] bool receiveShadows, [uei.DefaultValue("0")] int layer, [uei.DefaultValue("null")] Camera camera, [uei.DefaultValue("LightProbeUsage.BlendProbes")] LightProbeUsage lightProbeUsage) + public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, [uei.DefaultValue("0")] int argsOffset, [uei.DefaultValue("null")] MaterialPropertyBlock properties, [uei.DefaultValue("ShadowCastingMode.On")] ShadowCastingMode castShadows, [uei.DefaultValue("true")] bool receiveShadows, [uei.DefaultValue("0")] int layer, [uei.DefaultValue("null")] Camera camera, [uei.DefaultValue("LightProbeUsage.BlendProbes")] LightProbeUsage lightProbeUsage, [uei.DefaultValue("null")] LightProbeProxyVolume lightProbeProxyVolume) { if (!SystemInfo.supportsInstancing) throw new InvalidOperationException("Instancing is not supported."); @@ -455,16 +480,16 @@ public static void DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Materi throw new ArgumentNullException("material"); else if (bufferWithArgs == null) throw new ArgumentNullException("bufferWithArgs"); - else if (lightProbeUsage == LightProbeUsage.UseProxyVolume) - throw new ArgumentException("lightProbeUsage", String.Format("LightProbeUsage {0} cannot be specified for DrawMeshInstancedIndirect.", lightProbeUsage.ToString())); + if (lightProbeUsage == LightProbeUsage.UseProxyVolume && lightProbeProxyVolume == null) + throw new ArgumentException("lightProbeProxyVolume", "Argument lightProbeProxyVolume must not be null if lightProbeUsage is set to UseProxyVolume."); - Internal_DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, receiveShadows, layer, camera, lightProbeUsage); + Internal_DrawMeshInstancedIndirect(mesh, submeshIndex, material, bounds, bufferWithArgs, argsOffset, properties, castShadows, receiveShadows, layer, camera, lightProbeUsage, lightProbeProxyVolume); } #endregion [FreeFunction("DrawMeshInstancedIndirectFromScript")] - extern internal static void Internal_DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer, Camera camera, LightProbeUsage lightProbeUsage); + extern internal static void Internal_DrawMeshInstancedIndirect(Mesh mesh, int submeshIndex, Material material, Bounds bounds, ComputeBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties, ShadowCastingMode castShadows, bool receiveShadows, int layer, Camera camera, LightProbeUsage lightProbeUsage, LightProbeProxyVolume lightProbeProxyVolume); [FreeFunction("GraphicsScripting::BlitMaterial")] extern private static void Internal_BlitMaterial(Texture source, RenderTexture dest, [NotNull] Material mat, int pass, bool setRT); diff --git a/Runtime/Export/iOS/iOSDevice.bindings.cs b/Runtime/Export/iOS/iOSDevice.bindings.cs index 5ed07618b8..51f6fb3112 100644 --- a/Runtime/Export/iOS/iOSDevice.bindings.cs +++ b/Runtime/Export/iOS/iOSDevice.bindings.cs @@ -2,6 +2,7 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; using UnityEngine.Bindings; namespace UnityEngine.iOS @@ -107,6 +108,27 @@ extern public static bool advertisingTrackingEnabled [FreeFunction("IOSScripting::IsAdvertisingTrackingEnabled")] get; } + extern public static bool hideHomeButton + { + [NativeConditional("PLATFORM_IPHONE")] + [FreeFunction("IOSScripting::GetHideHomeButton")] get; + [NativeConditional("PLATFORM_IPHONE")] + [FreeFunction("IOSScripting::SetHideHomeButton")] set; + } + + extern private static int deferSystemGesturesModeInternal + { + [NativeConditional("PLATFORM_IPHONE")] + [FreeFunction("IOSScripting::GetDeferSystemGesturesMode")] get; + [NativeConditional("PLATFORM_IPHONE")] + [FreeFunction("IOSScripting::SetDeferSystemGesturesMode")] set; + } + + public static SystemGestureDeferMode deferSystemGesturesMode + { + get { return (SystemGestureDeferMode)deferSystemGesturesModeInternal; } + set { deferSystemGesturesModeInternal = (int)value; } + } [NativeConditional("PLATFORM_IPHONE || PLATFORM_TVOS")] [NativeMethod(Name = "IOSScripting::SetNoBackupFlag", IsFreeFunction = true, IsThreadSafe = true)] diff --git a/Runtime/Export/iOSSystemGestureDeferMode.cs b/Runtime/Export/iOSSystemGestureDeferMode.cs new file mode 100644 index 0000000000..7f91a6521c --- /dev/null +++ b/Runtime/Export/iOSSystemGestureDeferMode.cs @@ -0,0 +1,19 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; + +namespace UnityEngine.iOS +{ + [Flags] + public enum SystemGestureDeferMode: uint + { + None = 0, + TopEdge = 1 << 0, + LeftEdge = 1 << 1, + BottomEdge = 1 << 2, + RightEdge = 1 << 3, + All = TopEdge | LeftEdge | BottomEdge | RightEdge + } +} diff --git a/artifacts/generated/bindings_old/common/Core/SubstanceUtilityBindings.gen.cs b/artifacts/generated/bindings_old/common/Core/SubstanceUtilityBindings.gen.cs deleted file mode 100644 index 97222bf288..0000000000 --- a/artifacts/generated/bindings_old/common/Core/SubstanceUtilityBindings.gen.cs +++ /dev/null @@ -1,405 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using scm=System.ComponentModel; -using uei=UnityEngine.Internal; -using RequiredByNativeCodeAttribute=UnityEngine.Scripting.RequiredByNativeCodeAttribute; -using UsedByNativeCodeAttribute=UnityEngine.Scripting.UsedByNativeCodeAttribute; - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; - -namespace UnityEngine -{ -public enum ProceduralProcessorUsage -{ - - Unsupported = 0, - - One = 1, - - Half = 2, - - All = 3 -} - -public enum ProceduralCacheSize -{ - - Tiny = 0, - - Medium = 1, - - Heavy = 2, - - NoLimit = 3, - - None = 4 -} - -public enum ProceduralLoadingBehavior -{ - - DoNothing = 0, - - Generate = 1, - - BakeAndKeep = 2, - - BakeAndDiscard = 3, - - Cache = 4, - - DoNothingAndCache = 5 -} - -public enum ProceduralPropertyType -{ - - Boolean = 0, - - Float = 1, - - Vector2 = 2, - - Vector3 = 3, - - Vector4 = 4, - - Color3 = 5, - - Color4 = 6, - - Enum = 7, - - Texture = 8, - - String = 9 -} - -public enum ProceduralOutputType -{ - - Unknown = 0, - - Diffuse = 1, - - Normal = 2, - - Height = 3, - - Emissive = 4, - - Specular = 5, - - Opacity = 6, - - Smoothness = 7, - - AmbientOcclusion = 8, - - DetailMask = 9, - - Metallic = 10, - - Roughness = 11 -} - -[StructLayout(LayoutKind.Sequential)] -[UsedByNativeCode] -public sealed partial class ProceduralPropertyDescription -{ - public string name; - - - public string label; - - - public string group; - - - public ProceduralPropertyType type; - - - public bool hasRange; - - - public float minimum; - - - public float maximum; - - - public float step; - - - public string[] enumOptions; - - - public string[] componentLabels; -} - -public sealed partial class ProceduralMaterial : Material -{ - internal ProceduralMaterial() : base((Material)null) {} - - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public ProceduralPropertyDescription[] GetProceduralPropertyDescriptions () ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public bool HasProceduralProperty (string inputName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public bool GetProceduralBoolean (string inputName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public bool IsProceduralPropertyVisible (string inputName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void SetProceduralBoolean (string inputName, bool value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public float GetProceduralFloat (string inputName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void SetProceduralFloat (string inputName, float value) ; - - public Vector4 GetProceduralVector (string inputName) { - Vector4 result; - INTERNAL_CALL_GetProceduralVector ( this, inputName, out result ); - return result; - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - private extern static void INTERNAL_CALL_GetProceduralVector (ProceduralMaterial self, string inputName, out Vector4 value); - public void SetProceduralVector (string inputName, Vector4 value) { - INTERNAL_CALL_SetProceduralVector ( this, inputName, ref value ); - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - private extern static void INTERNAL_CALL_SetProceduralVector (ProceduralMaterial self, string inputName, ref Vector4 value); - public Color GetProceduralColor (string inputName) { - Color result; - INTERNAL_CALL_GetProceduralColor ( this, inputName, out result ); - return result; - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - private extern static void INTERNAL_CALL_GetProceduralColor (ProceduralMaterial self, string inputName, out Color value); - public void SetProceduralColor (string inputName, Color value) { - INTERNAL_CALL_SetProceduralColor ( this, inputName, ref value ); - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - private extern static void INTERNAL_CALL_SetProceduralColor (ProceduralMaterial self, string inputName, ref Color value); - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public int GetProceduralEnum (string inputName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void SetProceduralEnum (string inputName, int value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public Texture2D GetProceduralTexture (string inputName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void SetProceduralTexture (string inputName, Texture2D value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public string GetProceduralString (string inputName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void SetProceduralString (string inputName, string value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public bool IsProceduralPropertyCached (string inputName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void CacheProceduralProperty (string inputName, bool value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void ClearCache () ; - - public extern ProceduralCacheSize cacheSize - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - set; - } - - public extern int animationUpdateRate - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - set; - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void RebuildTextures () ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void RebuildTexturesImmediately () ; - - public extern bool isProcessing - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public static void StopRebuilds () ; - - public extern bool isCachedDataAvailable - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - } - - public extern bool isLoadTimeGenerated - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - set; - } - - public extern ProceduralLoadingBehavior loadingBehavior - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - } - - public extern static bool isSupported - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - } - - public extern static ProceduralProcessorUsage substanceProcessorUsage - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - set; - } - - public extern string preset - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - set; - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public Texture[] GetGeneratedTextures () ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public ProceduralTexture GetGeneratedTexture (string textureName) ; - - public extern bool isReadable - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - set; - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void FreezeAndReleaseSourceData () ; - - public extern bool isFrozen - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - } - -} - -public sealed partial class ProceduralTexture : Texture -{ - private ProceduralTexture() {} - - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public ProceduralOutputType GetProceduralOutputType () ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal ProceduralMaterial GetProceduralMaterial () ; - - public extern bool hasAlpha - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal bool HasBeenGenerated () ; - - public extern TextureFormat format - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public Color32[] GetPixels32 (int x, int y, int blockWidth, int blockHeight) ; - -} - - -} diff --git a/artifacts/generated/bindings_old/common/Editor/BuildPipelineBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/BuildPipelineBindings.gen.cs index 0d4c56df2d..f46dad7985 100644 --- a/artifacts/generated/bindings_old/common/Editor/BuildPipelineBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/BuildPipelineBindings.gen.cs @@ -74,7 +74,9 @@ public enum BuildOptions ComputeCRC = 1 << 20, StrictMode = 1 << 21, - IncludeTestAssemblies = 1 << 22 + IncludeTestAssemblies = 1 << 22, + + NoUniqueIdentifier = 1 << 23 } [System.Flags] diff --git a/artifacts/generated/bindings_old/common/Editor/EditorGUIUtilityBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/EditorGUIUtilityBindings.gen.cs index 889dadbe07..0f12059327 100644 --- a/artifacts/generated/bindings_old/common/Editor/EditorGUIUtilityBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/EditorGUIUtilityBindings.gen.cs @@ -884,6 +884,8 @@ internal static void DrawColorSwatch(Rect position, Color color, bool showAlpha, float a = GUI.enabled ? 1 : 2; GUI.color = EditorGUI.showMixedValue ? new Color(0.82f, 0.82f, 0.82f, a) * oldColor : new Color(color.r, color.g, color.b, a); + if (hdr) + GUI.color = GUI.color.gamma; GUI.backgroundColor = Color.white; GUIStyle gs = whiteTextureStyle; @@ -891,25 +893,31 @@ internal static void DrawColorSwatch(Rect position, Color color, bool showAlpha, float maxColorComponent = GUI.color.maxColorComponent; - if (hdr && maxColorComponent > 1.0f) + if (hdr) { - float gradientWidth = position.width / 3f; - Rect leftRect = new Rect(position.x, position.y, gradientWidth, position.height); - Rect rightRect = new Rect(position.xMax - gradientWidth, position.y, gradientWidth, position.height); - - Color normalizedColor = GUI.color.RGBMultiplied(1f / maxColorComponent); - - Color orgColor = GUI.color; - GUI.color = normalizedColor; - GUIStyle basicStyle = EditorGUIUtility.GetBasicTextureStyle(EditorGUIUtility.whiteTexture); - basicStyle.Draw(leftRect, false, false, false, false); - basicStyle.Draw(rightRect, false, false, false, false); - GUI.color = orgColor; - - basicStyle = EditorGUIUtility.GetBasicTextureStyle(ColorPicker.GetGradientTextureWithAlpha0To1()); - basicStyle.Draw(leftRect, false, false, false, false); - basicStyle = EditorGUIUtility.GetBasicTextureStyle(ColorPicker.GetGradientTextureWithAlpha1To0()); - basicStyle.Draw(rightRect, false, false, false, false); + Color32 baseColor; + float exposure; + ColorMutator.DecomposeHdrColor(GUI.color.linear, out baseColor, out exposure); + + if (!Mathf.Approximately(exposure, 0f)) + { + float gradientWidth = position.width / 3f; + Rect leftRect = new Rect(position.x, position.y, gradientWidth, position.height); + Rect rightRect = new Rect(position.xMax - gradientWidth, position.y, gradientWidth, + position.height); + + Color orgColor = GUI.color; + GUI.color = ((Color)baseColor).gamma; + GUIStyle basicStyle = GetBasicTextureStyle(whiteTexture); + basicStyle.Draw(leftRect, false, false, false, false); + basicStyle.Draw(rightRect, false, false, false, false); + GUI.color = orgColor; + + basicStyle = GetBasicTextureStyle(ColorPicker.GetGradientTextureWithAlpha0To1()); + basicStyle.Draw(leftRect, false, false, false, false); + basicStyle = GetBasicTextureStyle(ColorPicker.GetGradientTextureWithAlpha1To0()); + basicStyle.Draw(rightRect, false, false, false, false); + } } if (!EditorGUI.showMixedValue) @@ -936,7 +944,7 @@ internal static void DrawColorSwatch(Rect position, Color color, bool showAlpha, GUI.color = oldColor; GUI.backgroundColor = oldBackgroundColor; - if (hdr && maxColorComponent > 1.0f) + if (hdr) { GUI.Label(new Rect(position.x, position.y, position.width - 3, position.height), "HDR", EditorStyles.centeredGreyMiniLabel); } @@ -1160,6 +1168,20 @@ internal static void DrawHorizontalSplitter(Rect dragRect) } + internal static void DrawVerticalSplitter(Rect dragRect) + { + if (Event.current.type != EventType.Repaint) + return; + + Color orgColor = GUI.color; + Color tintColor = (EditorGUIUtility.isProSkin) ? new Color(0.12f, 0.12f, 0.12f, 1.333f) : new Color(0.6f, 0.6f, 0.6f, 1.333f); + GUI.color = GUI.color * tintColor; + Rect splitterRect = new Rect(dragRect.x, dragRect.y + 1, dragRect.width, 1f); + GUI.DrawTexture(splitterRect, EditorGUIUtility.whiteTexture); + GUI.color = orgColor; + } + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern internal static void CleanCache (string text) ; diff --git a/artifacts/generated/bindings_old/common/Editor/InternalEditorUtilityBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/InternalEditorUtilityBindings.gen.cs index 94e913d0bb..063652f40d 100644 --- a/artifacts/generated/bindings_old/common/Editor/InternalEditorUtilityBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/InternalEditorUtilityBindings.gen.cs @@ -752,6 +752,10 @@ private static Bounds GetLocalBounds(GameObject gameObject) { return ((SpriteMask)renderer).GetSpriteBounds(); } + if (renderer is UnityEngine.Experimental.U2D.SpriteShapeRenderer) + { + return ((UnityEngine.Experimental.U2D.SpriteShapeRenderer)renderer).GetLocalAABB(); + } if (renderer is UnityEngine.Tilemaps.TilemapRenderer) { UnityEngine.Tilemaps.Tilemap tilemap = renderer.GetComponent(); diff --git a/artifacts/generated/bindings_old/common/Editor/PlayerSettingsAndroidBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/PlayerSettingsAndroidBindings.gen.cs index b7ac448e8c..3ef683f0dc 100644 --- a/artifacts/generated/bindings_old/common/Editor/PlayerSettingsAndroidBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/PlayerSettingsAndroidBindings.gen.cs @@ -26,7 +26,7 @@ public enum AndroidArchitecture : uint ARMv7 = 1 << 0, - + ARM64 = 1 << 1, X86 = 1 << 2, diff --git a/artifacts/generated/bindings_old/common/Editor/SubstanceEditorUtilityBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/SubstanceEditorUtilityBindings.gen.cs deleted file mode 100644 index e0382701fc..0000000000 --- a/artifacts/generated/bindings_old/common/Editor/SubstanceEditorUtilityBindings.gen.cs +++ /dev/null @@ -1,120 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using scm=System.ComponentModel; -using uei=UnityEngine.Internal; -using RequiredByNativeCodeAttribute=UnityEngine.Scripting.RequiredByNativeCodeAttribute; -using UsedByNativeCodeAttribute=UnityEngine.Scripting.UsedByNativeCodeAttribute; - -using System; -using UnityEditor; -using UnityEngine; -using Object = UnityEngine.Object; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; -using System.Collections.Generic; -using System.IO; - -namespace UnityEditor -{ - - -public sealed partial class SubstanceImporter : AssetImporter -{ - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public string[] GetPrototypeNames () ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public int GetMaterialCount () ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public ProceduralMaterial[] GetMaterials () ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public string CloneMaterial (ProceduralMaterial material) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public string InstantiateMaterial (string prototypeName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void DestroyMaterial (ProceduralMaterial material) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void ResetMaterial (ProceduralMaterial material) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public bool RenameMaterial (ProceduralMaterial material, string name) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void OnShaderModified (ProceduralMaterial material) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public ProceduralOutputType GetTextureAlphaSource (ProceduralMaterial material, string textureName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void SetTextureAlphaSource (ProceduralMaterial material, string textureName, ProceduralOutputType alphaSource) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public bool GetPlatformTextureSettings (string materialName, string platform, out int maxTextureWidth, out int maxTextureHeight, out int textureFormat, out int loadBehavior) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void SetPlatformTextureSettings (ProceduralMaterial material, string platform, int maxTextureWidth, int maxTextureHeight, int textureFormat, int loadBehavior) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private ScriptingProceduralMaterialInformation GetMaterialInformation (ProceduralMaterial material) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private void SetMaterialInformation (ProceduralMaterial material, ScriptingProceduralMaterialInformation scriptingProcMatInfo) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal static bool CanShaderPropertyHostProceduralOutput (string name, ProceduralOutputType substanceType) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal void ClearPlatformTextureSettings (string materialName, string platform) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal void OnTextureInformationsChanged (ProceduralTexture texture) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal void ExportBitmapsInternal (ProceduralMaterial material, string exportPath, bool alphaRemap) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal static bool IsSubstanceParented (ProceduralTexture texture, ProceduralMaterial material) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal MonoScript GetSubstanceArchive () ; - -} - -[NativeClass(null)] -[ExcludeFromPreset] -public sealed partial class SubstanceArchive : Object -{ - private SubstanceArchive() {} -} - - -} From 1ff77516e4c139d1bef02ee7727249c4b2d4cd41 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 17 Jan 2018 12:06:15 +0000 Subject: [PATCH 02/17] Unity 2018.1.0b3 C# reference source code --- Editor/Mono/Collab/Collab.cs | 20 ++++++ Editor/Mono/Collab/CollabHistoryWindow.cs | 7 -- .../Presenters/CollabHistoryPresenter.cs | 22 +++++-- .../Mono/Collab/Views/ICollabHistoryWindow.cs | 1 - Editor/Mono/ContainerWindow.cs | 3 +- .../PlayerSettingsEditor.cs | 55 ++++++++-------- .../ParticleSystemModules/InitialModuleUI.cs | 3 + .../ParticleSystemEditor/ParticleSystemUI.cs | 17 ++--- .../PlayerSettingsPlatformIcons.bindings.cs | 49 +++++++++++++- Editor/Mono/PlayerSettingsIOS.bindings.cs | 43 ++++++++++-- Editor/Mono/ProvisioningProfileGUI.cs | 4 +- .../ScriptCompilation/EditorBuildRules.cs | 6 ++ .../VR/Mono/Oculus/VRCustomOptionsOculus.cs | 66 +++++++++++++++++++ .../VR/ScriptBindings/VREditor.bindings.cs | 50 ++++++++++++-- Modules/GraphViewEditor/Elements/Edge.cs | 2 +- .../Manipulators/RectangleSelector.cs | 11 ++++ Modules/IMGUI/StylePainter.cs | 3 + Modules/UIElements/Panel.cs | 14 ++-- Modules/UIElements/PanelWrapper.cs | 41 ++++++++++++ Modules/UIElements/VisualElement.cs | 39 +++++++++-- Projects/CSharp/UnityEditor.csproj | 3 + Projects/CSharp/UnityEngine.csproj | 3 + README.md | 2 +- .../Managed/NetworkTransportConfig.cs | 51 +++++++++++++- .../ScriptBindings/UNETworking.bindings.cs | 9 +++ .../common/IMGUI/GUIUtilityBindings.gen.cs | 25 +++++++ .../ParticleSystemBindings.gen.cs | 7 ++ .../common/UNET/UNETworkingBindings.gen.cs | 7 ++ 28 files changed, 473 insertions(+), 90 deletions(-) create mode 100644 Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs create mode 100644 Modules/UIElements/PanelWrapper.cs diff --git a/Editor/Mono/Collab/Collab.cs b/Editor/Mono/Collab/Collab.cs index de03d64723..17adb5c452 100644 --- a/Editor/Mono/Collab/Collab.cs +++ b/Editor/Mono/Collab/Collab.cs @@ -17,6 +17,7 @@ namespace UnityEditor.Collaboration { internal delegate void StateChangedDelegate(CollabInfo info); + internal delegate void ErrorDelegate(); [Flags] internal enum CollabOperation : ulong @@ -51,6 +52,8 @@ internal partial class Collab public event StateChangedDelegate StateChanged; public event StateChangedDelegate RevisionUpdated; public event StateChangedDelegate JobsCompleted; + public event ErrorDelegate ErrorOccurred; + public event ErrorDelegate ErrorCleared; private static Collab s_Instance; private static bool s_IsFirstStateChange = true; @@ -269,6 +272,7 @@ private static void OnStateChanged() } } + [RequiredByNativeCode] private static void OnRevisionUpdated() { var handler = instance.RevisionUpdated; @@ -278,6 +282,22 @@ private static void OnRevisionUpdated() } } + [RequiredByNativeCode] + private static void SetCollabError() + { + var handler = instance.ErrorOccurred; + if (handler != null) + handler(); + } + + [RequiredByNativeCode] + private static void ClearCollabError() + { + var handler = instance.ErrorCleared; + if (handler != null) + handler(); + } + private static void OnJobsCompleted() { var handler = instance.JobsCompleted; diff --git a/Editor/Mono/Collab/CollabHistoryWindow.cs b/Editor/Mono/Collab/CollabHistoryWindow.cs index d12d8db382..64cacc2e18 100644 --- a/Editor/Mono/Collab/CollabHistoryWindow.cs +++ b/Editor/Mono/Collab/CollabHistoryWindow.cs @@ -39,7 +39,6 @@ public static bool ValidateShowHistoryWindow() VisualElement m_Container; PagedListView m_Pager; int m_ItemsPerPage = 5; - string m_ErrMessage; string m_InProgressRev; bool m_RevisionActionsEnabled; @@ -244,12 +243,6 @@ public int itemsPerPage } } - public string errMessage - { - private get { return m_ErrMessage; } - set { m_ErrMessage = value; } - } - public PageChangeAction OnPageChangeAction { set { m_Pager.OnPageChange = value; } diff --git a/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs b/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs index 12f72a637b..44f947bcbd 100644 --- a/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs +++ b/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs @@ -15,6 +15,7 @@ internal class CollabHistoryPresenter IRevisionsService m_Service; ConnectInfo m_ConnectState; CollabInfo m_CollabState; + bool m_IsCollabError; int m_TotalRevisions; int m_CurrentPage; BuildAccess m_BuildAccess; @@ -36,6 +37,8 @@ public void OnWindowEnabled() Collab.instance.StateChanged += OnCollabStateChanged; Collab.instance.RevisionUpdated += OnCollabRevisionUpdated; Collab.instance.JobsCompleted += OnCollabJobsCompleted; + Collab.instance.ErrorOccurred += OnCollabError; + Collab.instance.ErrorCleared += OnCollabErrorCleared; EditorApplication.playModeStateChanged += OnPlayModeStateChanged; if (Collab.instance.IsConnected()) @@ -133,6 +136,18 @@ private void OnCollabJobsCompleted(CollabInfo state) m_ProgressRevision = null; } + private void OnCollabError() + { + m_IsCollabError = true; + m_Window.UpdateState(RecalculateState(), false); + } + + private void OnCollabErrorCleared() + { + m_IsCollabError = false; + m_Window.UpdateState(RecalculateState(), false); + } + private void OnPlayModeStateChanged(PlayModeStateChange stateChange) { // If entering play mode, disable @@ -151,11 +166,6 @@ private void OnPlayModeStateChanged(PlayModeStateChange stateChange) private HistoryState RecalculateState() { - if (m_ConnectState.error) - { - m_Window.errMessage = m_ConnectState.lastErrorMsg; - return HistoryState.Error; - } if (!m_ConnectState.online) return HistoryState.Offline; if (m_ConnectState.maintenance || m_CollabState.maintenance) @@ -168,6 +178,8 @@ private HistoryState RecalculateState() return HistoryState.Disabled; if (!Collab.instance.IsConnected() || !m_CollabState.ready) return HistoryState.Waiting; + if (m_ConnectState.error || m_IsCollabError) + return HistoryState.Error; return HistoryState.Ready; } diff --git a/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs b/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs index 6621d2580e..9e9f4d017b 100644 --- a/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs +++ b/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs @@ -69,7 +69,6 @@ internal interface ICollabHistoryWindow bool revisionActionsEnabled { get; set; } int itemsPerPage { set; } - string errMessage { set; } string inProgressRevision { get; set; } PageChangeAction OnPageChangeAction { set; } RevisionAction OnGoBackAction { set; } diff --git a/Editor/Mono/ContainerWindow.cs b/Editor/Mono/ContainerWindow.cs index 60f78ff727..87a6b5814c 100644 --- a/Editor/Mono/ContainerWindow.cs +++ b/Editor/Mono/ContainerWindow.cs @@ -187,8 +187,7 @@ internal bool IsNotDocked() (m_ShowMode == (int)ShowMode.Utility || m_ShowMode == (int)ShowMode.AuxWindow) || - (rootView as SplitView != null && - rootView.children.Length == 1 && + (rootView is SplitView && rootView.children.Length == 1 && rootView.children[0] is DockArea && ((DockArea)rootView.children[0]).m_Panes.Count == 1) diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 4b8ddc291b..7e7183c096 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -46,7 +46,7 @@ static class Styles public static readonly GUIContent recordingInfo = EditorGUIUtility.TrTextContent("Reordering the list will switch editor to the first available platform"); public static readonly GUIContent notApplicableInfo = EditorGUIUtility.TrTextContent("Not applicable for this platform."); public static readonly GUIContent sharedBetweenPlatformsInfo = EditorGUIUtility.TrTextContent("* Shared setting between multiple platforms."); - public static readonly GUIContent VRSupportOverridenInfo = EditorGUIUtility.TrTextContent("This setting is overridden by Virtual Reality Support."); + public static readonly GUIContent vrOrientationInfo = EditorGUIUtility.TrTextContent("Virtual Reality Support is enabled. Upon entering VR mode, landscape left orientation will be the default orientation unless only landscape right is available."); public static readonly GUIContent IL2CPPAndroidExperimentalInfo = EditorGUIUtility.TrTextContent("IL2CPP on Android is experimental and unsupported"); public static readonly GUIContent cursorHotspot = EditorGUIUtility.TrTextContent("Cursor Hotspot"); @@ -847,42 +847,39 @@ public void ResolutionSectionGUI(BuildTargetGroup targetGroup, ISettingEditorExt { GUILayout.Label(Styles.orientationTitle, EditorStyles.boldLabel); - using (new EditorGUI.DisabledScope(PlayerSettings.virtualRealitySupported)) - { - EditorGUILayout.PropertyField(m_DefaultScreenOrientation, Styles.defaultScreenOrientation); + EditorGUILayout.PropertyField(m_DefaultScreenOrientation, Styles.defaultScreenOrientation); - if (PlayerSettings.virtualRealitySupported) - { - EditorGUILayout.HelpBox(Styles.VRSupportOverridenInfo.text, MessageType.Info); - } + if (PlayerSettings.virtualRealitySupported) + { + EditorGUILayout.HelpBox(Styles.vrOrientationInfo.text, MessageType.Warning); + } - if (m_DefaultScreenOrientation.enumValueIndex == 4) - { - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.Tizen) - EditorGUILayout.PropertyField(m_UseOSAutoRotation, Styles.useOSAutoRotation); + if (m_DefaultScreenOrientation.enumValueIndex == (int)UIOrientation.AutoRotation) + { + if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.Tizen) + EditorGUILayout.PropertyField(m_UseOSAutoRotation, Styles.useOSAutoRotation); - EditorGUI.indentLevel++; + EditorGUI.indentLevel++; - GUILayout.Label(Styles.allowedOrientationTitle, EditorStyles.boldLabel); + GUILayout.Label(Styles.allowedOrientationTitle, EditorStyles.boldLabel); - bool somethingAllowed = m_AllowedAutoRotateToPortrait.boolValue - || m_AllowedAutoRotateToPortraitUpsideDown.boolValue - || m_AllowedAutoRotateToLandscapeRight.boolValue - || m_AllowedAutoRotateToLandscapeLeft.boolValue; + bool somethingAllowed = m_AllowedAutoRotateToPortrait.boolValue + || m_AllowedAutoRotateToPortraitUpsideDown.boolValue + || m_AllowedAutoRotateToLandscapeRight.boolValue + || m_AllowedAutoRotateToLandscapeLeft.boolValue; - if (!somethingAllowed) - { - m_AllowedAutoRotateToPortrait.boolValue = true; - Debug.LogError("All orientations are disabled. Allowing portrait"); - } + if (!somethingAllowed) + { + m_AllowedAutoRotateToPortrait.boolValue = true; + Debug.LogError("All orientations are disabled. Allowing portrait"); + } - EditorGUILayout.PropertyField(m_AllowedAutoRotateToPortrait, Styles.allowedAutoRotateToPortrait); - EditorGUILayout.PropertyField(m_AllowedAutoRotateToPortraitUpsideDown, Styles.allowedAutoRotateToPortraitUpsideDown); - EditorGUILayout.PropertyField(m_AllowedAutoRotateToLandscapeRight, Styles.allowedAutoRotateToLandscapeRight); - EditorGUILayout.PropertyField(m_AllowedAutoRotateToLandscapeLeft, Styles.allowedAutoRotateToLandscapeLeft); + EditorGUILayout.PropertyField(m_AllowedAutoRotateToPortrait, Styles.allowedAutoRotateToPortrait); + EditorGUILayout.PropertyField(m_AllowedAutoRotateToPortraitUpsideDown, Styles.allowedAutoRotateToPortraitUpsideDown); + EditorGUILayout.PropertyField(m_AllowedAutoRotateToLandscapeRight, Styles.allowedAutoRotateToLandscapeRight); + EditorGUILayout.PropertyField(m_AllowedAutoRotateToLandscapeLeft, Styles.allowedAutoRotateToLandscapeLeft); - EditorGUI.indentLevel--; - } + EditorGUI.indentLevel--; } } diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs index 2950323a6d..3c031ce472 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs @@ -304,6 +304,9 @@ override public void UpdateCullingSupportedString(ref string text) if (m_GravityModifier.state != MinMaxCurveState.k_Scalar) text += "\nGravity modifier is not constant."; + + if (m_StopAction.intValue != 0) + text += "\nStop Action is being used."; } } } // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs index 815ba83c3d..fc359c68c5 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs @@ -21,15 +21,6 @@ internal class ParticleSystemUI private string m_SupportsCullingText; private string m_SupportsCullingTextLabel; // Cached version including bullet points - // Keep in sync with ParticleSystemEditor.h - public enum DefaultTypes - { - Root, - SubBirth, - SubCollision, - SubDeath, - }; - protected class Texts { public GUIContent addModules = new GUIContent("", "Show/Hide Modules"); @@ -64,7 +55,7 @@ public void Init(ParticleEffectUI owner, ParticleSystem[] systems) internal ModuleUI GetParticleSystemRendererModuleUI() { - return m_Modules[m_Modules.Length - 1]; + return m_Modules.Last(); } private void InitRendererUI() @@ -84,10 +75,10 @@ private void InitRendererUI() // Create RendererModuleUI if (renderers.Count > 0) { - System.Diagnostics.Debug.Assert(m_Modules[m_Modules.Length - 1] == null); // If hitting this assert we have either not cleaned up the previous renderer or hitting another module + System.Diagnostics.Debug.Assert(m_Modules.Last() == null); // If hitting this assert we have either not cleaned up the previous renderer or hitting another module m_RendererSerializedObject = new SerializedObject(renderers.ToArray()); - m_Modules[m_Modules.Length - 1] = new RendererModuleUI(this, m_RendererSerializedObject, s_ModuleNames[s_ModuleNames.Length - 1]); + m_Modules[m_Modules.Length - 1] = new RendererModuleUI(this, m_RendererSerializedObject, s_ModuleNames.Last()); } } @@ -465,7 +456,7 @@ void ResetModules() } // Default setup has a renderer - if (m_Modules[m_Modules.Length - 1] == null) + if (m_Modules.Last() == null) InitRendererUI(); // Default setup has shape, emission and renderer diff --git a/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs b/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs index 3d44011dbc..3b512404c0 100644 --- a/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs +++ b/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs @@ -252,10 +252,17 @@ public static PlatformIcon[] GetPlatformIcons(BuildTargetGroup platform, Platfor PlatformIconStruct[] serializedIcons = GetPlatformIconsInternal(platformName, kind.kind); PlatformIcon[] icons = PlatformIcon.GetRequiredPlatformIconsByType(platformIconProvider, kind); + if (serializedIcons.Length <= 0) + { + ImportLegacyIcons(platform, kind, icons); + SetPlatformIcons(platform, kind, icons); + } + if (serializedIcons.Length <= 0) { foreach (var icon in icons) - icon.SetTextures(null); + if (icon.IsEmpty()) + icon.SetTextures(null); } else { @@ -332,6 +339,13 @@ internal static int GetNonEmptyPlatformIconCount(PlatformIcon[] icons) return icons.Count(i => !i.IsEmpty()); } + internal static int GetValidPlatformIconCount(PlatformIcon[] icons) + { + return icons.Count( + i => i.GetTextures().Count(t => t != null) >= i.minLayerCount && i.layerCount <= i.maxLayerCount + ); + } + [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] [NativeMethod(Name = "SetIconsForPlatform")] extern internal static void SetPlatformIconsInternal(string platform, PlatformIconStruct[] icons, int kind); @@ -351,8 +365,6 @@ internal static void ClearSetIconsForPlatform(BuildTargetGroup target) // Old API methods, will be made obsolete when the new API is implemented for all platforms, // currently it functions as a wrapper for the new API for all platforms that support it (iOS, Android & tvOS). - - public static void SetIconsForTargetGroup(BuildTargetGroup platform, Texture2D[] icons, IconKind kind) { if (platform == BuildTargetGroup.iOS || platform == BuildTargetGroup.tvOS || platform == BuildTargetGroup.Android) @@ -402,6 +414,37 @@ public static Texture2D[] GetIconsForTargetGroup(BuildTargetGroup platform, Icon } } + internal static void ImportLegacyIcons(string platform, PlatformIconKind kind, PlatformIcon[] platformIcons) + { + if (!Enum.IsDefined(typeof(IconKind), kind.kind)) + return; + + IconKind iconKind = (IconKind)kind.kind; + + Texture2D[] legacyIcons = GetIconsForPlatform(platform, iconKind); + int[] legacyIconWidths = GetIconWidthsForPlatform(platform, iconKind); + int[] legacyIconHeights = GetIconHeightsForPlatform(platform, iconKind); + + for (var i = 0; i < legacyIcons.Length; i++) + { + List selectedIcons = new List(); + foreach (var icon in platformIcons) + { + if (icon.width == legacyIconWidths[i] && icon.height == legacyIconHeights[i]) + { + selectedIcons.Add(icon); + } + } + foreach (var selectedIcon in selectedIcons) + selectedIcon.SetTextures(legacyIcons[i]); + } + } + + internal static void ImportLegacyIcons(BuildTargetGroup platform, PlatformIconKind kind, PlatformIcon[] platformIcons) + { + ImportLegacyIcons(GetPlatformName(platform), kind, platformIcons); + } + // Returns the list of assigned icons for the specified platform. public static Texture2D[] GetIconsForTargetGroup(BuildTargetGroup platform) { diff --git a/Editor/Mono/PlayerSettingsIOS.bindings.cs b/Editor/Mono/PlayerSettingsIOS.bindings.cs index 1c190e579d..84c115c9cc 100644 --- a/Editor/Mono/PlayerSettingsIOS.bindings.cs +++ b/Editor/Mono/PlayerSettingsIOS.bindings.cs @@ -355,7 +355,7 @@ public extern static bool forceHardShadowsOnMetal public extern static bool allowHTTPDownload { get; set; } [NativeProperty("AppleDeveloperTeamID")] - public extern static string appleDeveloperTeamID + private extern static string appleDeveloperTeamIDInternal { [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] get; @@ -363,8 +363,19 @@ public extern static string appleDeveloperTeamID set; } + public static string appleDeveloperTeamID + { + get + { + return appleDeveloperTeamIDInternal.Length < 1 ? + EditorPrefs.GetString("DefaultiOSAutomaticSignTeamId") : appleDeveloperTeamIDInternal; + } + set { appleDeveloperTeamIDInternal = value; } + } + + [NativeProperty("iOSManualProvisioningProfileID")] - public extern static string iOSManualProvisioningProfileID + private extern static string iOSManualProvisioningProfileIDInternal { [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] get; @@ -372,8 +383,19 @@ public extern static string iOSManualProvisioningProfileID set; } + public static string iOSManualProvisioningProfileID + { + get + { + return String.IsNullOrEmpty(iOSManualProvisioningProfileIDInternal) ? + EditorPrefs.GetString("DefaultiOSProvisioningProfileUUID") : iOSManualProvisioningProfileIDInternal; + } + set { iOSManualProvisioningProfileIDInternal = value; } + } + + [NativeProperty("tvOSManualProvisioningProfileID")] - public extern static string tvOSManualProvisioningProfileID + private extern static string tvOSManualProvisioningProfileIDInternal { [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] get; @@ -381,6 +403,17 @@ public extern static string tvOSManualProvisioningProfileID set; } + public static string tvOSManualProvisioningProfileID + { + get + { + return String.IsNullOrEmpty(tvOSManualProvisioningProfileIDInternal) ? + EditorPrefs.GetString("DefaulttvOSProvisioningProfileUUID") : tvOSManualProvisioningProfileIDInternal; + } + set { tvOSManualProvisioningProfileIDInternal = value; } + } + + [NativeProperty("AppleEnableAutomaticSigning")] private extern static int appleEnableAutomaticSigningInternal { @@ -394,7 +427,9 @@ public static bool appleEnableAutomaticSigning { get { - return appleEnableAutomaticSigningInternal == (int)iOSAutomaticallySignValue.AutomaticallySignValueTrue; + return appleEnableAutomaticSigningInternal == (int)iOSAutomaticallySignValue.AutomaticallySignValueNotSet ? + EditorPrefs.GetBool("DefaultiOSAutomaticallySignBuild") : + (iOSAutomaticallySignValue)appleEnableAutomaticSigningInternal == iOSAutomaticallySignValue.AutomaticallySignValueTrue; } set { diff --git a/Editor/Mono/ProvisioningProfileGUI.cs b/Editor/Mono/ProvisioningProfileGUI.cs index 094df39c2c..2376fdb6d2 100644 --- a/Editor/Mono/ProvisioningProfileGUI.cs +++ b/Editor/Mono/ProvisioningProfileGUI.cs @@ -138,8 +138,8 @@ internal static void ShowUIWithDefaults(string provisioningPrefKey, SerializedPr Rect toggleRect = EditorGUILayout.GetControlRect(true, 0); EditorGUI.BeginProperty(toggleRect, automaticSigningGUI, enableAutomaticSigningProp); bool newValue = EditorGUILayout.Toggle(automaticSigningGUI, oldValue); - bool signingValueNotSet = enableAutomaticSigningProp.intValue == (int)iOSAutomaticallySignValue.AutomaticallySignValueNotSet; - if (newValue != oldValue || signingValueNotSet) + + if (newValue != oldValue) { enableAutomaticSigningProp.intValue = GetIntValueForAutomaticSigningBool(newValue); } diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs index 58df67cf05..51b605f2bb 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs @@ -225,6 +225,12 @@ public static ScriptAssembly[] GetAllScriptAssemblies(IEnumerable allSou if (!IsCompatibleWithPlatform(targetAssembly, settings)) continue; + var scriptExtension = ScriptCompilers.GetExtensionOfSourceFile(scriptFile); + var scriptLanguage = ScriptCompilers.GetLanguageFromExtension(scriptExtension); + + if (targetAssembly.Language == null && targetAssembly.Type == TargetAssemblyType.Custom) + targetAssembly.Language = scriptLanguage; + HashSet assemblySourceFiles; if (!targetAssemblyFiles.TryGetValue(targetAssembly, out assemblySourceFiles)) diff --git a/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs b/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs new file mode 100644 index 0000000000..5a949a85d7 --- /dev/null +++ b/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs @@ -0,0 +1,66 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEditor; +using UnityEngine; +using System.Linq; + +namespace UnityEditorInternal.VR +{ + internal class VRCustomOptionsOculus : VRCustomOptions + { + static GUIContent s_SharedDepthBufferLabel = EditorGUIUtility.TextContent("Shared Depth Buffer|Enable depth buffer submission to allow for overlay depth occlusion, etc."); + static GUIContent s_DashSupportLabel = EditorGUIUtility.TextContent("Dash Support|If enabled, pressing the home button brings up Dash, otherwise it brings up the older universal menu."); + + SerializedProperty m_SharedDepthBuffer; + SerializedProperty m_DashSupport; + + public override void Initialize(SerializedObject settings) + { + Initialize(settings, "oculus"); + } + + public override void Initialize(SerializedObject settings, string propertyName) + { + base.Initialize(settings, propertyName); + m_SharedDepthBuffer = FindPropertyAssert("sharedDepthBuffer"); + m_DashSupport = FindPropertyAssert("dashSupport"); + } + + public override Rect Draw(Rect rect) + { + rect.y += EditorGUIUtility.standardVerticalSpacing; + + rect.height = EditorGUIUtility.singleLineHeight; + GUIContent label = EditorGUI.BeginProperty(rect, s_SharedDepthBufferLabel, m_SharedDepthBuffer); + EditorGUI.BeginChangeCheck(); + bool boolValue = EditorGUI.Toggle(rect, label, m_SharedDepthBuffer.boolValue); + if (EditorGUI.EndChangeCheck()) + { + m_SharedDepthBuffer.boolValue = boolValue; + } + EditorGUI.EndProperty(); + rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; + + rect.height = EditorGUIUtility.singleLineHeight; + label = EditorGUI.BeginProperty(rect, s_DashSupportLabel, m_DashSupport); + EditorGUI.BeginChangeCheck(); + boolValue = EditorGUI.Toggle(rect, label, m_DashSupport.boolValue); + if (EditorGUI.EndChangeCheck()) + { + m_DashSupport.boolValue = boolValue; + } + EditorGUI.EndProperty(); + rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; + + return rect; + } + + public override float GetHeight() + { + return (EditorGUIUtility.singleLineHeight * 2.0f) + (EditorGUIUtility.standardVerticalSpacing * 3.0f); + } + } +} diff --git a/Editor/Src/VR/ScriptBindings/VREditor.bindings.cs b/Editor/Src/VR/ScriptBindings/VREditor.bindings.cs index 7cdd285e1b..7e52bbb98b 100644 --- a/Editor/Src/VR/ScriptBindings/VREditor.bindings.cs +++ b/Editor/Src/VR/ScriptBindings/VREditor.bindings.cs @@ -24,24 +24,46 @@ public partial struct VRDeviceInfoEditor [NativeHeader("Editor/Src/VR/VREditor.bindings.h")] public sealed partial class VREditor { - extern public static VRDeviceInfoEditor[] GetAllVRDeviceInfo(BuildTargetGroup targetGroup); + extern public static VRDeviceInfoEditor[] GetAllVRDeviceInfo(BuildTargetGroup targetGroup); - extern public static VRDeviceInfoEditor[] GetAllVRDeviceInfoByTarget(BuildTarget target); + extern public static VRDeviceInfoEditor[] GetAllVRDeviceInfoByTarget(BuildTarget target); - extern public static bool GetVREnabledOnTargetGroup(BuildTargetGroup targetGroup); + extern public static bool GetVREnabledOnTargetGroup(BuildTargetGroup targetGroup); - extern public static void SetVREnabledOnTargetGroup(BuildTargetGroup targetGroup, bool value); + extern public static void SetVREnabledOnTargetGroup(BuildTargetGroup targetGroup, bool value); - extern public static string[] GetVREnabledDevicesOnTargetGroup(BuildTargetGroup targetGroup); + extern public static string[] GetVREnabledDevicesOnTargetGroup(BuildTargetGroup targetGroup); - extern public static string[] GetVREnabledDevicesOnTarget(BuildTarget target); + extern public static string[] GetVREnabledDevicesOnTarget(BuildTarget target); - extern public static void SetVREnabledDevicesOnTargetGroup(BuildTargetGroup targetGroup, string[] devices); + extern public static void SetVREnabledDevicesOnTargetGroup(BuildTargetGroup targetGroup, string[] devices); } } namespace UnityEditorInternal { + [NativeHeader("Runtime/Misc/PlayerSettings.h")] + [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] + internal class PlayerSettingsOculus + { + public static extern bool sharedDepthBuffer + { + [NativeMethod("GetOculusSharedDepthBufferEnabled")] + get; + [NativeMethod("SetOculusSharedDepthBufferEnabled")] + set; + } + + public static extern bool dashSupport + { + [NativeMethod("GetOculusDashSupportEnabled")] + get; + [NativeMethod("SetOculusDashSupportEnabled")] + set; + } + } + + [NativeHeader("Runtime/Misc/PlayerSettings.h")] [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] internal class PlayerSettings360StereoCapture @@ -60,6 +82,20 @@ namespace UnityEditor { partial class PlayerSettings { + public class VROculus + { + public static bool sharedDepthBuffer + { + get { return UnityEditorInternal.PlayerSettingsOculus.sharedDepthBuffer; } + set { UnityEditorInternal.PlayerSettingsOculus.sharedDepthBuffer = value; } + } + public static bool dashSupport + { + get { return UnityEditorInternal.PlayerSettingsOculus.dashSupport; } + set { UnityEditorInternal.PlayerSettingsOculus.dashSupport = value; } + } + } + public static bool enable360StereoCapture { get { return UnityEditorInternal.PlayerSettings360StereoCapture.enable360StereoCapture; } diff --git a/Modules/GraphViewEditor/Elements/Edge.cs b/Modules/GraphViewEditor/Elements/Edge.cs index a5b7a09fd8..86af65fd52 100644 --- a/Modules/GraphViewEditor/Elements/Edge.cs +++ b/Modules/GraphViewEditor/Elements/Edge.cs @@ -129,9 +129,9 @@ public Edge() Add(edgeControl); - this.AddManipulator(new EdgeManipulator()); capabilities |= Capabilities.Selectable | Capabilities.Deletable; + this.AddManipulator(new EdgeManipulator()); this.AddManipulator(new ContextualMenuManipulator(null)); } diff --git a/Modules/GraphViewEditor/Manipulators/RectangleSelector.cs b/Modules/GraphViewEditor/Manipulators/RectangleSelector.cs index d6f7851cce..d0550af717 100644 --- a/Modules/GraphViewEditor/Manipulators/RectangleSelector.cs +++ b/Modules/GraphViewEditor/Manipulators/RectangleSelector.cs @@ -47,6 +47,7 @@ protected override void RegisterCallbacksOnTarget() target.RegisterCallback(OnMouseDown); target.RegisterCallback(OnMouseUp); target.RegisterCallback(OnMouseMove); + target.RegisterCallback(OnMouseCaptureOutEvent); } protected override void UnregisterCallbacksFromTarget() @@ -54,6 +55,16 @@ protected override void UnregisterCallbacksFromTarget() target.UnregisterCallback(OnMouseDown); target.UnregisterCallback(OnMouseUp); target.UnregisterCallback(OnMouseMove); + target.UnregisterCallback(OnMouseCaptureOutEvent); + } + + void OnMouseCaptureOutEvent(MouseCaptureOutEvent e) + { + if (m_Active) + { + m_Rectangle.RemoveFromHierarchy(); + m_Active = false; + } } private void OnMouseDown(MouseDownEvent e) diff --git a/Modules/IMGUI/StylePainter.cs b/Modules/IMGUI/StylePainter.cs index 0b3db924ac..7bc97fe2c8 100644 --- a/Modules/IMGUI/StylePainter.cs +++ b/Modules/IMGUI/StylePainter.cs @@ -181,6 +181,9 @@ public void DrawTexture(TextureStylePainterParameters painterParams) bool usePremultiplyAlpha = painterParams.usePremultiplyAlpha; Rect textureRect = screenRect; + + /// Comparing aspects ratio is error-prone because the screenRect may end up being scaled by the + /// transform and the corners will end up being pixel aligned, possibly resulting in blurriness. float srcAspect = (texture.width * sourceRect.width) / (texture.height * sourceRect.height); float destAspect = screenRect.width / screenRect.height; switch (scaleMode) diff --git a/Modules/UIElements/Panel.cs b/Modules/UIElements/Panel.cs index 1122c592d1..21a7cd8b58 100644 --- a/Modules/UIElements/Panel.cs +++ b/Modules/UIElements/Panel.cs @@ -484,12 +484,12 @@ private void PaintSubTree(Event e, VisualElement root, Matrix4x4 offset, Rect cu // validate cache texture size first var worldBound = root.worldBound; - int w = Mathf.RoundToInt(worldBound.xMax) - Mathf.RoundToInt(worldBound.xMin); - int h = Mathf.RoundToInt(worldBound.yMax) - Mathf.RoundToInt(worldBound.yMin); + int w = (int)GUIUtility.Internal_Roundf(worldBound.xMax) - (int)GUIUtility.Internal_Roundf(worldBound.xMin); + int h = (int)GUIUtility.Internal_Roundf(worldBound.yMax) - (int)GUIUtility.Internal_Roundf(worldBound.yMin); // This needs to be consistent with RoundRect() in GUITexture.cpp. Otherwise, the texture may be stretched. - int textureWidth = Mathf.RoundToInt(w * GUIUtility.pixelsPerPoint); - int textureHeight = Mathf.RoundToInt(h * GUIUtility.pixelsPerPoint); + int textureWidth = (int)GUIUtility.Internal_Roundf(w * GUIUtility.pixelsPerPoint); + int textureHeight = (int)GUIUtility.Internal_Roundf(h * GUIUtility.pixelsPerPoint); // Prevent the texture size from going empty, which may occur if the element has a sub-pixel size textureWidth = Math.Max(textureWidth, 1); @@ -546,7 +546,7 @@ private void PaintSubTree(Event e, VisualElement root, Matrix4x4 offset, Rect cu // Calculate the offset required to translate the origin of the rect to the upper left corner // of the pixel cache. We need to round because the rect will be rounded when rendered. - var childrenOffset = Matrix4x4.Translate(new Vector3(-Mathf.RoundToInt(worldBound.x), -Mathf.RoundToInt(worldBound.y), 0)); + var childrenOffset = Matrix4x4.Translate(new Vector3(-GUIUtility.Internal_Roundf(worldBound.x), -GUIUtility.Internal_Roundf(worldBound.y), 0)); Matrix4x4 offsetWorldTransform = childrenOffset * root.worldTransform; @@ -633,11 +633,11 @@ private void PaintSubTree(Event e, VisualElement root, Matrix4x4 offset, Rect cu var painterParams = new TextureStylePainterParameters { - rect = root.rect, + rect = root.alignedRect, uv = new Rect(0, 0, 1, 1), texture = root.renderData.pixelCache, color = Color.white, - scaleMode = ScaleMode.ScaleAndCrop, + scaleMode = ScaleMode.StretchToFill, usePremultiplyAlpha = true }; diff --git a/Modules/UIElements/PanelWrapper.cs b/Modules/UIElements/PanelWrapper.cs new file mode 100644 index 0000000000..ac4c959d3e --- /dev/null +++ b/Modules/UIElements/PanelWrapper.cs @@ -0,0 +1,41 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using UnityEngine.Experimental.UIElements; + +namespace UnityEngine.Internal.Experimental.UIElements +{ + /// + /// Panel being internal, this wrapper is used in Graphics Tests to perform basic operations that would + /// otherwise only be possible with reflection. We prefer to avoid using reflection because it is cumbersome and + /// only detected at runtime which would add latency to the development process. + /// + public class PanelWrapper : ScriptableObject + { + private Panel m_Panel; + + private void OnEnable() + { + m_Panel = UIElementsUtility.FindOrCreatePanel(this); + } + + private void OnDisable() + { + m_Panel = null; + } + + public VisualElement visualTree + { + get + { + return m_Panel.visualTree; + } + } + + public void Repaint(Event e) + { + m_Panel.Repaint(e); + } + } +} diff --git a/Modules/UIElements/VisualElement.cs b/Modules/UIElements/VisualElement.cs index 6bf2ddb410..056da93cf6 100644 --- a/Modules/UIElements/VisualElement.cs +++ b/Modules/UIElements/VisualElement.cs @@ -221,25 +221,34 @@ protected Rect paddingRect } } - // get the AA aligned bound + /// + /// AABB after applying the world transform to rect. + /// public Rect worldBound { get { var g = worldTransform; - var min = g.MultiplyPoint3x4(rect.min); - var max = g.MultiplyPoint3x4(rect.max); + var min = GUIUtility.Internal_MultiplyPoint(new Vector3(rect.min.x, rect.min.y, 1), g); + var max = GUIUtility.Internal_MultiplyPoint(new Vector3(rect.max.x, rect.max.y, 1), g); + + // We assume that the transform performs translation/scaling without rotation. return Rect.MinMaxRect(Math.Min(min.x, max.x), Math.Min(min.y, max.y), Math.Max(min.x, max.x), Math.Max(min.y, max.y)); } } + /// + /// AABB after applying the transform to the rect, but before applying the layout translation. + /// public Rect localBound { get { var g = transform.matrix; - var min = g.MultiplyPoint3x4(layout.min); - var max = g.MultiplyPoint3x4(layout.max); + var min = GUIUtility.Internal_MultiplyPoint(layout.min, g); + var max = GUIUtility.Internal_MultiplyPoint(layout.max, g); + + // We assume that the transform performs translation/scaling without rotation. return Rect.MinMaxRect(Math.Min(min.x, max.x), Math.Min(min.y, max.y), Math.Max(min.x, max.x), Math.Max(min.y, max.y)); } } @@ -252,6 +261,22 @@ internal Rect rect } } + /// + /// rect converted to world space, aligned to the pixel-grid, and converted back to its original space. + /// + /// + /// The offset used when rendering to a pixel cache can yield numerical errors that result in rounding + /// differences in GUITexture.cpp, causing blur. By specifying an already-aligned rect, the numerical + /// errors aren't sufficient to generate rounding differences. + /// + internal Rect alignedRect + { + get + { + return GUIUtility.Internal_AlignRectToDevice(rect, worldTransform); + } + } + public Matrix4x4 worldTransform { get @@ -1138,7 +1163,7 @@ internal static TextureStylePainterParameters GetDefaultTextureParameters(this I IStyle style = ve.style; var painterParams = new TextureStylePainterParameters { - rect = ve.rect, + rect = ve.alignedRect, uv = new Rect(0, 0, 1, 1), color = Color.white, texture = style.backgroundImage, @@ -1157,7 +1182,7 @@ internal static RectStylePainterParameters GetDefaultRectParameters(this IStyleP IStyle style = ve.style; var painterParams = new RectStylePainterParameters { - rect = ve.rect, + rect = ve.alignedRect, color = style.backgroundColor, }; painter.SetBorderFromStyle(ref painterParams.border, style); diff --git a/Projects/CSharp/UnityEditor.csproj b/Projects/CSharp/UnityEditor.csproj index 8fd6256b33..26976cea85 100644 --- a/Projects/CSharp/UnityEditor.csproj +++ b/Projects/CSharp/UnityEditor.csproj @@ -3583,6 +3583,9 @@ Editor\Src\VR\Mono\GoogleVR\VRCustomOptionsGoogleVR.cs + +Editor\Src\VR\Mono\Oculus\VRCustomOptionsOculus.cs + artifacts\generated\bindings_old\common\VREditor\HolographicEmulationBindings.gen.cs diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index c39951de0e..3dd699a998 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -1647,6 +1647,9 @@ Modules\UIElements\Panel.cs + +Modules\UIElements\PanelWrapper.cs + Modules\UIElements\RepeatButton.cs diff --git a/README.md b/README.md index 3f2f9715d7..9ef88899ea 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.1.0b2 C# reference source code +## Unity 2018.1.0b3 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Networking/Managed/NetworkTransportConfig.cs b/Runtime/Networking/Managed/NetworkTransportConfig.cs index a7d8a4077b..73255cebd3 100644 --- a/Runtime/Networking/Managed/NetworkTransportConfig.cs +++ b/Runtime/Networking/Managed/NetworkTransportConfig.cs @@ -73,14 +73,19 @@ public class ChannelQOS [SerializeField] internal QosType m_Type; + [SerializeField] + internal bool m_BelongsSharedOrderChannel; + public ChannelQOS(QosType value) { m_Type = value; + m_BelongsSharedOrderChannel = false; } public ChannelQOS() { m_Type = QosType.Unreliable; + m_BelongsSharedOrderChannel = false; } public ChannelQOS(ChannelQOS channel) @@ -88,9 +93,11 @@ public ChannelQOS(ChannelQOS channel) if (channel == null) throw new NullReferenceException("channel is not defined"); m_Type = channel.m_Type; + m_BelongsSharedOrderChannel = channel.m_BelongsSharedOrderChannel; } public QosType QOS { get { return m_Type; } } + public bool BelongsToSharedOrderChannel { get { return m_BelongsSharedOrderChannel; } } } //connection configuration proxy class @@ -155,6 +162,8 @@ public class ConnectionConfig private string m_SSLCAFilePath; [SerializeField] internal List m_Channels = new List(); + [SerializeField] + internal List> m_SharedOrderChannels = new List>(); public ConnectionConfig() { @@ -224,6 +233,10 @@ public ConnectionConfig(ConnectionConfig config) { m_Channels.Add(new ChannelQOS(channel)); } + foreach (var channelIds in config.m_SharedOrderChannels) + { + m_SharedOrderChannels.Add(channelIds); + } } public static void Validate(ConnectionConfig config) @@ -424,7 +437,10 @@ public int ChannelCount { get { return m_Channels.Count; } } - + public int SharedOrderChannelCount + { + get { return m_SharedOrderChannels.Count; } + } public byte AddChannel(QosType value) { if (m_Channels.Count > 255) @@ -438,6 +454,32 @@ public byte AddChannel(QosType value) return (byte)(m_Channels.Count - 1); } + public void MakeChannelsSharedOrder(List channelIndices) + { + if (channelIndices == null) + throw new NullReferenceException("channelIndices must not be null"); + if (channelIndices.Count == 0) + throw new ArgumentOutOfRangeException("Received empty list of shared order channel indexes"); + for (byte i = 0; i < channelIndices.Count; i++) + { + byte channelId = channelIndices[i]; + if (channelId >= m_Channels.Count) + throw new ArgumentOutOfRangeException("Shared order channel list contains wrong channel index " + channelId); + ChannelQOS channel = m_Channels[channelId]; + if (channel.BelongsToSharedOrderChannel) + throw new ArgumentException("Channel with index " + channelId + " has been already included to other shared order channel"); + if (!(channel.QOS == QosType.Reliable || channel.QOS == QosType.Unreliable)) + throw new ArgumentException("Only Reliable and Unreliable QoS are allowed for shared order channel, wrong channel is with index " + channelId); + } + for (byte i = 0; i < channelIndices.Count; i++) + { + byte channelId = channelIndices[i]; + m_Channels[channelId].m_BelongsSharedOrderChannel = true; + } + List newChannelIndices = new List(channelIndices); + m_SharedOrderChannels.Add(newChannelIndices); + } + public QosType GetChannel(byte idx) { if (idx >= m_Channels.Count) @@ -445,6 +487,13 @@ public QosType GetChannel(byte idx) return m_Channels[idx].QOS; } + public IList GetSharedOrderChannels(byte idx) + { + if (idx >= m_SharedOrderChannels.Count) + throw new ArgumentOutOfRangeException("requested index greater than maximum shared order channels count"); + return m_SharedOrderChannels[idx].AsReadOnly(); + } + public List Channels { get { return m_Channels; } } } diff --git a/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs b/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs index 3c3bc3455a..b35fbf6b55 100644 --- a/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs +++ b/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs @@ -39,6 +39,15 @@ static public void Init(GlobalConfig config) [FreeFunction("UNETManager::Get()->NotifyWhenConnectionReadyForSend")] extern public static bool NotifyWhenConnectionReadyForSend(int hostId, int connectionId, int notificationLevel, out byte error); + + [FreeFunction("UNETManager::Get()->GetHostPort")] + extern public static int GetHostPort(int hostId); + } + + internal sealed partial class ConnectionConfigInternal : IDisposable + { + [NativeMethod("MakeChannelsSharedOrder")] + private extern bool MakeChannelsSharedOrder(byte[] values); } } diff --git a/artifacts/generated/bindings_old/common/IMGUI/GUIUtilityBindings.gen.cs b/artifacts/generated/bindings_old/common/IMGUI/GUIUtilityBindings.gen.cs index 9234c52e34..0381eb405b 100644 --- a/artifacts/generated/bindings_old/common/IMGUI/GUIUtilityBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/IMGUI/GUIUtilityBindings.gen.cs @@ -166,6 +166,31 @@ internal extern static bool manualTex2SRGBEnabled [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern internal static bool HasFocusableControls () ; + [VisibleToOtherModules("UnityEngine.UIElementsModule")] + internal static Rect Internal_AlignRectToDevice (Rect rect, Matrix4x4 transform) { + Rect result; + INTERNAL_CALL_Internal_AlignRectToDevice ( ref rect, ref transform, out result ); + return result; + } + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + private extern static void INTERNAL_CALL_Internal_AlignRectToDevice (ref Rect rect, ref Matrix4x4 transform, out Rect value); + [VisibleToOtherModules("UnityEngine.UIElementsModule")] + internal static Vector3 Internal_MultiplyPoint (Vector3 point, Matrix4x4 transform) { + Vector3 result; + INTERNAL_CALL_Internal_MultiplyPoint ( ref point, ref transform, out result ); + return result; + } + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + private extern static void INTERNAL_CALL_Internal_MultiplyPoint (ref Vector3 point, ref Matrix4x4 transform, out Vector3 value); + [VisibleToOtherModules("UnityEngine.UIElementsModule")] + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern internal static float Internal_Roundf (float f) ; + } internal sealed partial class GUIClip diff --git a/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs b/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs index f5f08e4d73..8313f1edd0 100644 --- a/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs @@ -3432,6 +3432,13 @@ public extern bool useAutoRandomSeed set; } + public extern bool automaticCullingEnabled + { + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + get; + } + public MainModule main { get { return new MainModule(this); } } public EmissionModule emission { get { return new EmissionModule(this); } } public ShapeModule shape { get { return new ShapeModule(this); } } diff --git a/artifacts/generated/bindings_old/common/UNET/UNETworkingBindings.gen.cs b/artifacts/generated/bindings_old/common/UNET/UNETworkingBindings.gen.cs index b1779f814f..8b7d437792 100644 --- a/artifacts/generated/bindings_old/common/UNET/UNETworkingBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/UNET/UNETworkingBindings.gen.cs @@ -108,6 +108,13 @@ public ConnectionConfigInternal(ConnectionConfig config) { AddChannel(config.GetChannel(i)); } + for (byte i = 0; i < config.SharedOrderChannelCount; ++i) + { + IList sharedOrderChannelsList = config.GetSharedOrderChannels(i); + byte[] sharedOrderChannelsArray = new byte[sharedOrderChannelsList.Count]; + sharedOrderChannelsList.CopyTo(sharedOrderChannelsArray, 0); + MakeChannelsSharedOrder(sharedOrderChannelsArray); + } } From d64a9e06cc60047248ccf982dbe1ee14b74efb34 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Mon, 22 Jan 2018 19:10:28 +0000 Subject: [PATCH 03/17] Unity 2018.1.0b4 C# reference source code --- .../2D/SpriteAtlas/SpriteAtlasInspector.cs | 8 +- Editor/Mono/AssemblyHelper.cs | 15 ++- .../TextureGenerator.bindings.cs | 19 ++-- .../Collab/Views/CollabHistoryDropDown.cs | 17 ++-- Editor/Mono/Collab/Views/CollabHistoryItem.cs | 2 +- Editor/Mono/Inspector/AvatarPreview.cs | 4 +- Editor/Mono/Inspector/ClothInspector.cs | 11 ++- .../Mono/Inspector/MaterialPropertyDrawer.cs | 62 +++++++----- .../DefaultPlayerSettingsEditorExtension.cs | 13 --- Editor/Mono/PlayerSettingsIOS.bindings.cs | 17 +++- Editor/Mono/PlayerSettingsTVOS.bindings.cs | 6 ++ Editor/Mono/Sprites/SpriteUtilityWindow.cs | 11 +-- Modules/GraphViewEditor/Elements/GroupNode.cs | 13 ++- Modules/GraphViewEditor/Elements/MiniMap.cs | 13 +++ Modules/GraphViewEditor/Views/GraphView.cs | 96 ++++++++++++++----- .../Public/ProfilerFrameDataView.bindings.cs | 3 + Modules/UIElements/HierarchyTraversal.cs | 9 +- .../Public/WebRequestExtensions.cs | 8 +- .../UnityWebRequest/Public/WebRequestUtils.cs | 11 ++- Modules/UnityWebRequestWWW/Public/WWW.cs | 19 +--- README.md | 2 +- Runtime/Export/Pose.cs | 15 +++ .../Export/RenderPipeline/RenderPipeline.cs | 7 ++ .../RenderPipeline/RenderPipelineAsset.cs | 4 +- .../common/Core/ProfilerBindings.gen.cs | 3 + .../common/Editor/UnityConnectBindings.gen.cs | 2 + 26 files changed, 263 insertions(+), 127 deletions(-) diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs index 02c617cf5d..3c44628970 100644 --- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs +++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs @@ -643,16 +643,12 @@ public override void OnPreviewGUI(Rect r, GUIStyle background) { Texture2D t = m_PreviewTextures[m_PreviewPage]; - float oldBias = t.mipMapBias; float bias = m_MipLevel - (float)(System.Math.Log(t.width / r.width) / System.Math.Log(2)); - TextureUtil.SetMipMapBiasNoDirty(t, bias); if (m_ShowAlpha) - EditorGUI.DrawTextureAlpha(r, t, ScaleMode.ScaleToFit); + EditorGUI.DrawTextureAlpha(r, t, ScaleMode.ScaleToFit, 0, bias); else - EditorGUI.DrawTextureTransparent(r, t, ScaleMode.ScaleToFit); - - TextureUtil.SetMipMapBiasNoDirty(t, oldBias); + EditorGUI.DrawTextureTransparent(r, t, ScaleMode.ScaleToFit, 0, bias); } } diff --git a/Editor/Mono/AssemblyHelper.cs b/Editor/Mono/AssemblyHelper.cs index af3bafedcf..d75990069f 100644 --- a/Editor/Mono/AssemblyHelper.cs +++ b/Editor/Mono/AssemblyHelper.cs @@ -22,6 +22,10 @@ static public void CheckForAssemblyFileNameMismatch(string assemblyPath) { string fileName = Path.GetFileNameWithoutExtension(assemblyPath); string assemblyName = ExtractInternalAssemblyName(assemblyPath); + + if (string.IsNullOrEmpty(assemblyName)) + return; + if (fileName != assemblyName) { Debug.LogWarning("Assembly '" + assemblyName + "' has non matching file name: '" + Path.GetFileName(assemblyPath) + "'. This can cause build issues on some platforms."); @@ -66,8 +70,15 @@ public static Assembly FindLoadedAssemblyWithName(string s) static public string ExtractInternalAssemblyName(string path) { - AssemblyDefinition definition = AssemblyDefinition.ReadAssembly(path); - return definition.Name.Name; + try + { + AssemblyDefinition definition = AssemblyDefinition.ReadAssembly(path); + return definition.Name.Name; + } + catch + { + return ""; // Possible on just deleted FacebookSDK + } } static AssemblyDefinition GetAssemblyDefinitionCached(string path, Dictionary cache) diff --git a/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs b/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs index 02e9ff41e2..dc8739325c 100644 --- a/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs +++ b/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs @@ -4,12 +4,11 @@ using System; using UnityEngine; -using UnityEditor; using UnityEngine.Bindings; using System.Runtime.InteropServices; -using UnityEngine.Scripting; using System.Collections.Generic; using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; namespace UnityEditor.Experimental.AssetImporters { @@ -81,10 +80,6 @@ public struct TextureGenerationSettings { [NativeName("assetPath")] private string m_AssetPath; - [NativeName("imageData")] - private IntPtr m_ImageData; - [NativeName("imageDataSize")] - private int m_ImageDataSize; [NativeName("qualifyForSpritePacking")] private bool m_QualifyForSpritePacking; [NativeName("enablePostProcessor")] @@ -100,14 +95,13 @@ public struct TextureGenerationSettings [NativeName("spritePackingTag")] private string m_SpritePackingTag; + public TextureGenerationSettings(TextureImporterType type) { m_EnablePostProcessor = true; m_AssetPath = ""; - m_ImageDataSize = 0; m_QualifyForSpritePacking = false; m_SpritePackingTag = ""; - m_ImageData = new IntPtr(); m_SpriteImportData = null; m_SourceTextureInformation = new SourceTextureInformation(); @@ -210,8 +204,6 @@ public TextureGenerationSettings(TextureImporterType type) } public string assetPath { get { return m_AssetPath; } set { m_AssetPath = value; } } - public IntPtr imageData { get { return m_ImageData; } set { m_ImageData = value; } } - public int imageDataSize { get { return m_ImageDataSize; } set { m_ImageDataSize = value; } } public bool qualifyForSpritePacking { get { return m_QualifyForSpritePacking; } set { m_QualifyForSpritePacking = value; } } public bool enablePostProcessor { get { return m_EnablePostProcessor; } set { m_EnablePostProcessor = value; } } public TextureImporterSettings textureImporterSettings { get { return m_Settings; } set { m_Settings = value; } } @@ -228,8 +220,13 @@ public TextureGenerationSettings(TextureImporterType type) [NativeHeader("Runtime/Serialize/BuildTarget.h")] public static class TextureGenerator { + public static TextureGenerationOutput GenerateTexture(TextureGenerationSettings settings, NativeArray colorBuffer) + { + return GenerateTextureImpl(settings, colorBuffer.GetUnsafeReadOnlyPtr(), colorBuffer.Length * 4); + } + [NativeThrows] [NativeMethod("GenerateTextureScripting")] - extern public static TextureGenerationOutput GenerateTexture(TextureGenerationSettings settings); + extern static TextureGenerationOutput GenerateTextureImpl(TextureGenerationSettings settings, IntPtr colorBuffer, int colorBufferLength); } } diff --git a/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs b/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs index 0b9605103a..1a9c5ef2a2 100644 --- a/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs +++ b/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs @@ -2,7 +2,6 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License -using System.Linq; using UnityEngine; using UnityEngine.Experimental.UIElements; using System.Collections.Generic; @@ -12,14 +11,16 @@ namespace UnityEditor.Collaboration { internal class CollabHistoryDropDown : VisualElement { - private readonly VisualElement m_FilesContainer; - private readonly Label m_ToggleLabel; - private int m_ChangesTotal; + readonly VisualElement m_FilesContainer; + readonly Label m_ToggleLabel; + int m_ChangesTotal; + string m_RevisionId; - public CollabHistoryDropDown(ICollection changes, int changesTotal, bool changesTruncated) + public CollabHistoryDropDown(ICollection changes, int changesTotal, bool changesTruncated, string revisionId) { m_FilesContainer = new VisualElement(); m_ChangesTotal = changesTotal; + m_RevisionId = revisionId; m_ToggleLabel = new Label(ToggleText(false)); m_ToggleLabel.AddManipulator(new Clickable(ToggleDropdown)); @@ -62,10 +63,10 @@ private string ToggleText(bool open) private void ShowAllClick() { - var host = UnityConnect.instance.GetConfigurationURL(CloudConfigUrl.CloudCollab); - var org = UnityConnect.instance.GetOrganizationForeignKey(); + var host = UnityConnect.instance.GetConfigurationURL(CloudConfigUrl.CloudServicesDashboard); + var org = UnityConnect.instance.GetOrganizationId(); var proj = UnityConnect.instance.GetProjectGUID(); - var url = string.Format("{0}/orgs/{1}/projects/{2}/assets", host, org, proj); + var url = string.Format("{0}/collab/orgs/{1}/projects/{2}/commits?commit={3}", host, org, proj, m_RevisionId); Application.OpenURL(url); } } diff --git a/Editor/Mono/Collab/Views/CollabHistoryItem.cs b/Editor/Mono/Collab/Views/CollabHistoryItem.cs index 47ddf2c427..ab80cb316c 100644 --- a/Editor/Mono/Collab/Views/CollabHistoryItem.cs +++ b/Editor/Mono/Collab/Views/CollabHistoryItem.cs @@ -69,7 +69,7 @@ public CollabHistoryItem(RevisionData data) m_Description = new Label(m_FullDescription); } m_Description.name = "RevisionDescription"; - var dropdown = new CollabHistoryDropDown(data.changes, data.changesTotal, data.changesTruncated); + var dropdown = new CollabHistoryDropDown(data.changes, data.changesTotal, data.changesTruncated, data.id); if (data.current) { m_Button = new Button(Restore) {name = "ActionButton", text = "Restore"}; diff --git a/Editor/Mono/Inspector/AvatarPreview.cs b/Editor/Mono/Inspector/AvatarPreview.cs index 064d115c9b..ba5fe175f0 100644 --- a/Editor/Mono/Inspector/AvatarPreview.cs +++ b/Editor/Mono/Inspector/AvatarPreview.cs @@ -513,7 +513,7 @@ private RenderTexture RenderPreviewShadowmap(Light light, float scale, Vector3 c // Set ortho camera and position it var cam = previewUtility.camera; - cam.orthographic = is2D; + cam.orthographic = true; cam.orthographicSize = scale * 2.0f; cam.nearClipPlane = 1 * scale; cam.farClipPlane = 25 * scale; @@ -656,7 +656,7 @@ public void DoRenderPreview(Rect previewRect, GUIStyle background) // Render shadow map Matrix4x4 shadowMatrix; - RenderTexture shadowMap = RenderPreviewShadowmap(previewUtility.lights[0], m_BoundingVolumeScale / 2, bodyPos, floorPos, out shadowMatrix); + RenderTexture shadowMap = RenderPreviewShadowmap(previewUtility.lights[0], m_BoundingVolumeScale / 2, bodyPosition, floorPos, out shadowMatrix); float tempZoomFactor = (is2D ? 1.0f : m_ZoomFactor); // Position camera diff --git a/Editor/Mono/Inspector/ClothInspector.cs b/Editor/Mono/Inspector/ClothInspector.cs index 870789d22c..de2cb08024 100644 --- a/Editor/Mono/Inspector/ClothInspector.cs +++ b/Editor/Mono/Inspector/ClothInspector.cs @@ -532,14 +532,15 @@ void InitBrushCollider() MeshCollider oldMeshCollider = go.GetComponent(); if (oldMeshCollider != null) { - if (oldMeshCollider.hideFlags == (HideFlags.HideInHierarchy | HideFlags.HideInInspector)) + if (((oldMeshCollider.hideFlags & HideFlags.HideInHierarchy) != 0) || ((oldMeshCollider.hideFlags & HideFlags.HideInInspector) != 0)) { - DestroyImmediate(oldMeshCollider); + DestroyImmediate(oldMeshCollider, true); } } MeshCollider meshCollider = go.AddComponent(); - meshCollider.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector; + meshCollider.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector | + HideFlags.DontSaveInEditor | HideFlags.NotEditable; meshCollider.sharedMesh = m_SkinnedMeshRenderer.sharedMesh; @@ -559,9 +560,9 @@ public void OnDestroy() MeshCollider meshCollider = go.GetComponent(); if (meshCollider != null) { - if (meshCollider.hideFlags == (HideFlags.HideInHierarchy | HideFlags.HideInInspector)) + if (((meshCollider.hideFlags & HideFlags.HideInHierarchy) != 0) || ((meshCollider.hideFlags & HideFlags.HideInInspector) != 0)) { - DestroyImmediate(meshCollider); + DestroyImmediate(meshCollider, true); } } s_BrushCreated = false; diff --git a/Editor/Mono/Inspector/MaterialPropertyDrawer.cs b/Editor/Mono/Inspector/MaterialPropertyDrawer.cs index 2902631f49..b31a148ca1 100644 --- a/Editor/Mono/Inspector/MaterialPropertyDrawer.cs +++ b/Editor/Mono/Inspector/MaterialPropertyDrawer.cs @@ -251,41 +251,24 @@ public virtual void Apply(MaterialProperty prop) // syntax in shaders, e.g. [Toggle] in front of a shader property will // end up using MaterialToggleDrawer to display it as a toggle. - - internal class MaterialToggleDrawer : MaterialPropertyDrawer + // Variant of the ToggleDrawer that defines no keyword (just UI) + internal class MaterialToggleUIDrawer : MaterialPropertyDrawer { - protected readonly string keyword; - public MaterialToggleDrawer() - { - } - - public MaterialToggleDrawer(string keyword) + public MaterialToggleUIDrawer() { - this.keyword = keyword; } - static bool IsPropertyTypeSuitable(MaterialProperty prop) + public MaterialToggleUIDrawer(string keyword) { - return prop.type == MaterialProperty.PropType.Float || prop.type == MaterialProperty.PropType.Range; } protected virtual void SetKeyword(MaterialProperty prop, bool on) { - SetKeywordInternal(prop, on, "_ON"); } - protected void SetKeywordInternal(MaterialProperty prop, bool on, string defaultKeywordSuffix) + static bool IsPropertyTypeSuitable(MaterialProperty prop) { - // if no keyword is provided, use + defaultKeywordSuffix - string kw = string.IsNullOrEmpty(keyword) ? prop.name.ToUpperInvariant() + defaultKeywordSuffix : keyword; - // set or clear the keyword - foreach (Material material in prop.targets) - { - if (on) - material.EnableKeyword(kw); - else - material.DisableKeyword(kw); - } + return prop.type == MaterialProperty.PropType.Float || prop.type == MaterialProperty.PropType.Range; } public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) @@ -333,6 +316,39 @@ public override void Apply(MaterialProperty prop) } } + + internal class MaterialToggleDrawer : MaterialToggleUIDrawer + { + protected readonly string keyword; + public MaterialToggleDrawer() + { + } + + public MaterialToggleDrawer(string keyword) + { + this.keyword = keyword; + } + + protected override void SetKeyword(MaterialProperty prop, bool on) + { + SetKeywordInternal(prop, on, "_ON"); + } + + protected void SetKeywordInternal(MaterialProperty prop, bool on, string defaultKeywordSuffix) + { + // if no keyword is provided, use + defaultKeywordSuffix + string kw = string.IsNullOrEmpty(keyword) ? prop.name.ToUpperInvariant() + defaultKeywordSuffix : keyword; + // set or clear the keyword + foreach (Material material in prop.targets) + { + if (on) + material.EnableKeyword(kw); + else + material.DisableKeyword(kw); + } + } + } + // Variant of the ToggleDrawer that defines a keyword when it's not on // This is useful when adding Toggles to existing shaders while maintaining backwards compatibility internal class MaterialToggleOffDrawer : MaterialToggleDrawer diff --git a/Editor/Mono/Modules/DefaultPlayerSettingsEditorExtension.cs b/Editor/Mono/Modules/DefaultPlayerSettingsEditorExtension.cs index d6f9970567..8d2c0e9477 100644 --- a/Editor/Mono/Modules/DefaultPlayerSettingsEditorExtension.cs +++ b/Editor/Mono/Modules/DefaultPlayerSettingsEditorExtension.cs @@ -92,19 +92,6 @@ public virtual bool SupportsGfxJobModes() return false; } - public string FixTargetOSVersion(string version) - { - var decimalIndexes = Enumerable.Range(0, version.Length).Where(i => version[i] == '.').ToArray(); - - if (decimalIndexes.Length <= 0) - return (version + ".0").Trim(); - else if (decimalIndexes.Length > 1) - return (version.Substring(0, decimalIndexes[1])).Trim(); - else if (decimalIndexes.Length == 1 && decimalIndexes[0] == version.Length - 1) - return (version + "0").Trim(); - return version.Trim(); - } - public virtual bool SupportsMultithreadedRendering() { return false; diff --git a/Editor/Mono/PlayerSettingsIOS.bindings.cs b/Editor/Mono/PlayerSettingsIOS.bindings.cs index 84c115c9cc..4be67cb24d 100644 --- a/Editor/Mono/PlayerSettingsIOS.bindings.cs +++ b/Editor/Mono/PlayerSettingsIOS.bindings.cs @@ -259,6 +259,12 @@ public static iOSTargetOSVersion targetOSVersion } } + [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] + [NativeMethod("GetiOSMinimumVersionString")] + static extern string GetMinimumVersionString(); + + internal static readonly Version minimumOsVersion = new Version(GetMinimumVersionString()); + [NativeProperty("iOSTargetOSVersion")] public extern static string targetOSVersionString { @@ -544,8 +550,15 @@ internal extern static bool appleEnableProMotion internal static bool IsTargetVersionEqualOrHigher(Version requiredVersion) { - Version minimumVersion = new Version(8, 0); - Version requestedVersion = string.IsNullOrEmpty(PlayerSettings.iOS.targetOSVersionString) ? minimumVersion : new Version(PlayerSettings.iOS.targetOSVersionString); + Version requestedVersion; + try + { + requestedVersion = new Version(targetOSVersionString); + } + catch (Exception) + { + requestedVersion = minimumOsVersion; + } return requestedVersion >= requiredVersion; } diff --git a/Editor/Mono/PlayerSettingsTVOS.bindings.cs b/Editor/Mono/PlayerSettingsTVOS.bindings.cs index 6a149406ba..ac15c9101f 100644 --- a/Editor/Mono/PlayerSettingsTVOS.bindings.cs +++ b/Editor/Mono/PlayerSettingsTVOS.bindings.cs @@ -77,6 +77,12 @@ public static tvOSTargetOSVersion targetOSVersion } } + [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] + [NativeMethod("GettvOSMinimumVersionString")] + static extern string GetMinimumVersionString(); + + internal static readonly Version minimumOsVersion = new Version(GetMinimumVersionString()); + public static extern string targetOSVersionString { [NativeMethod("GettvOSTargetOSVersion")] diff --git a/Editor/Mono/Sprites/SpriteUtilityWindow.cs b/Editor/Mono/Sprites/SpriteUtilityWindow.cs index 8c88c3fd14..b67282355a 100644 --- a/Editor/Mono/Sprites/SpriteUtilityWindow.cs +++ b/Editor/Mono/Sprites/SpriteUtilityWindow.cs @@ -223,10 +223,8 @@ private float Log2(float x) protected void DrawTexture() { int texWidth = Mathf.Max(m_Texture.width, 1); - float mipLevel = Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(m_Texture) - 1); + float mipLevel = Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(m_Texture) - 1) - Log2(texWidth / m_TextureRect.width); - float oldBias = m_Texture.mipMapBias; - TextureUtil.SetMipMapBiasNoDirty(m_Texture, mipLevel - Log2(texWidth / m_TextureRect.width)); FilterMode oldFilter = m_Texture.filterMode; TextureUtil.SetFilterModeNoDirty(m_Texture, FilterMode.Point); @@ -234,15 +232,14 @@ protected void DrawTexture() { // check if we have a valid alpha texture if (m_TextureAlphaOverride != null) - EditorGUI.DrawTextureTransparent(m_TextureRect, m_TextureAlphaOverride); + EditorGUI.DrawTextureTransparent(m_TextureRect, m_TextureAlphaOverride, ScaleMode.StretchToFill, 0, mipLevel); // else use the original texture and display its alpha else - EditorGUI.DrawTextureAlpha(m_TextureRect, m_Texture); + EditorGUI.DrawTextureAlpha(m_TextureRect, m_Texture, ScaleMode.StretchToFill, 0, mipLevel); } else - EditorGUI.DrawTextureTransparent(m_TextureRect, m_Texture); + EditorGUI.DrawTextureTransparent(m_TextureRect, m_Texture, ScaleMode.StretchToFill, 0, mipLevel); - TextureUtil.SetMipMapBiasNoDirty(m_Texture, oldBias); TextureUtil.SetFilterModeNoDirty(m_Texture, oldFilter); } diff --git a/Modules/GraphViewEditor/Elements/GroupNode.cs b/Modules/GraphViewEditor/Elements/GroupNode.cs index b07e0a9269..222171911f 100644 --- a/Modules/GraphViewEditor/Elements/GroupNode.cs +++ b/Modules/GraphViewEditor/Elements/GroupNode.cs @@ -119,6 +119,7 @@ public class GroupNode : GraphElement private bool m_IsUpdatingGeometryFromContent = false; private bool m_IsMovingElements = false; bool m_Initialized = false; + bool m_FirstRepaint = true; bool m_HeaderSizeIsValid = false; bool m_EditTitleCancelled = false; Vector2 mPreviousPosInCanvasSpace = new Vector2(); @@ -187,6 +188,15 @@ public GroupNode() m_HeaderItem.RegisterCallback(OnHeaderSizeChanged); RegisterCallback(e => { MoveElements(); }); RegisterCallback(OnMouseUpEvent); + + this.schedule.Execute(e => { + if (visible && (m_Initialized == false)) + { + m_Initialized = true; + + UpdateGeometryFromContent(); + } + }); } void OnSubElementPostLayout(PostLayoutEvent e) @@ -426,8 +436,9 @@ public void OnPositionChanged(VisualElement ve) public override void DoRepaint() { - if (m_Initialized == false) + if (m_FirstRepaint) { + m_FirstRepaint = false; m_Initialized = true; UpdateGeometryFromContent(); diff --git a/Modules/GraphViewEditor/Elements/MiniMap.cs b/Modules/GraphViewEditor/Elements/MiniMap.cs index 10c286dc9a..e76d4cbb53 100644 --- a/Modules/GraphViewEditor/Elements/MiniMap.cs +++ b/Modules/GraphViewEditor/Elements/MiniMap.cs @@ -74,6 +74,7 @@ public MiniMap() Add(m_Label); RegisterCallback(OnMouseDown); + m_Label.RegisterCallback(EatMouseDown); this.AddManipulator(new ContextualMenuManipulator(BuildContextualMenu)); } @@ -387,6 +388,16 @@ void DrawRectangleOutline(Rect rect, Color color) Handles.color = currentColor; } + private void EatMouseDown(MouseDownEvent e) + { + // The minimap should not let any left mouse down go through when it's not movable. + if (e.button == (int)MouseButton.LeftMouse && + (capabilities & Capabilities.Movable) == 0) + { + e.StopPropagation(); + } + } + private void OnMouseDown(MouseDownEvent e) { var gView = graphView; @@ -412,6 +423,8 @@ private void OnMouseDown(MouseDownEvent e) e.StopPropagation(); } }); + + EatMouseDown(e); } } } diff --git a/Modules/GraphViewEditor/Views/GraphView.cs b/Modules/GraphViewEditor/Views/GraphView.cs index e0a7311380..7f01dcacae 100644 --- a/Modules/GraphViewEditor/Views/GraphView.cs +++ b/Modules/GraphViewEditor/Views/GraphView.cs @@ -713,12 +713,12 @@ public virtual void ClearSelection() public virtual void BuildContextualMenu(ContextualMenuPopulateEvent evt) { - if (evt.target is UIElements.GraphView.GraphView) + if (evt.target is UIElements.GraphView.GraphView && nodeCreationRequest != null) { evt.menu.AppendAction("Create Node", OnContextMenuNodeCreate, ContextualMenu.MenuAction.AlwaysEnabled); evt.menu.AppendSeparator(); } - if (evt.target is UIElements.GraphView.GraphView || evt.target is Node || evt.target is GroupNode || evt.target is Edge) + if (evt.target is UIElements.GraphView.GraphView || evt.target is Node || evt.target is GroupNode) { evt.menu.AppendAction("Cut", (e) => { CutSelectionCallback(); }, (e) => { return canCutSelection ? ContextualMenu.MenuAction.StatusFlags.Normal : ContextualMenu.MenuAction.StatusFlags.Disabled; }); @@ -733,6 +733,19 @@ public virtual void BuildContextualMenu(ContextualMenuPopulateEvent evt) evt.menu.AppendAction("Paste", (e) => { PasteCallback(); }, (e) => { return canPaste ? ContextualMenu.MenuAction.StatusFlags.Normal : ContextualMenu.MenuAction.StatusFlags.Disabled; }); } + if (evt.target is UIElements.GraphView.GraphView || evt.target is Node || evt.target is GroupNode || evt.target is Edge) + { + evt.menu.AppendSeparator(); + evt.menu.AppendAction("Delete", (e) => { DeleteSelectionCallback(AskUser.DontAskUser); }, + (e) => { return canDeleteSelection ? ContextualMenu.MenuAction.StatusFlags.Normal : ContextualMenu.MenuAction.StatusFlags.Disabled; }); + } + if (evt.target is UIElements.GraphView.GraphView || evt.target is Node || evt.target is GroupNode) + { + evt.menu.AppendSeparator(); + evt.menu.AppendAction("Duplicate", (e) => { DuplicateSelectionCallback(); }, + (e) => { return canDuplicateSelection ? ContextualMenu.MenuAction.StatusFlags.Normal : ContextualMenu.MenuAction.StatusFlags.Disabled; }); + evt.menu.AppendSeparator(); + } } void OnContextMenuNodeCreate(EventBase evt) @@ -942,9 +955,44 @@ protected internal virtual bool canCopySelection get { return selection.OfType().Any() || selection.OfType().Any(); } } + private void CollectElements(IEnumerable elements, HashSet collectedElementSet, Func conditionFunc) + { + foreach (var element in elements.Where(e => e != null && !collectedElementSet.Contains(e) && conditionFunc(e))) + { + var node = element as Node; + + if (node != null) + { + CollectConnectedEgdes(collectedElementSet, node); + } + else + { + var groupNode = element as GroupNode; + + // If the selected element is a group then visit its contained element + if (groupNode != null) + { + CollectElements(groupNode.containedElements, collectedElementSet, conditionFunc); + } + } + + collectedElementSet.Add(element); + } + } + + private void CollectCopyableGraphElements(IEnumerable elements, HashSet elementsToCopySet) + { + CollectElements(elements, elementsToCopySet, e => (e is Node || e is GroupNode)); + } + protected internal void CopySelectionCallback() { - string data = SerializeGraphElements(selection.OfType()); + var elementsToCopySet = new HashSet(); + + CollectCopyableGraphElements(selection.OfType(), elementsToCopySet); + + string data = SerializeGraphElements(elementsToCopySet); + if (!string.IsNullOrEmpty(data)) { clipboard = data; @@ -953,7 +1001,7 @@ protected internal void CopySelectionCallback() protected internal virtual bool canCutSelection { - get { return selection.Count > 0; } + get { return selection.OfType().Any() || selection.OfType().Any(); } } protected internal void CutSelectionCallback() @@ -979,7 +1027,12 @@ protected internal virtual bool canDuplicateSelection protected internal void DuplicateSelectionCallback() { - string serializedData = SerializeGraphElements(selection.OfType()); + var elementsToCopySet = new HashSet(); + + CollectCopyableGraphElements(selection.OfType(), elementsToCopySet); + + string serializedData = SerializeGraphElements(elementsToCopySet); + UnserializeAndPasteOperation("Duplicate", serializedData); } @@ -1176,6 +1229,21 @@ private EventPropagation DeleteSelectedPresenters() return (elementsToRemove.Count > 0) ? EventPropagation.Stop : EventPropagation.Continue; } + private void CollectConnectedEgdes(HashSet elementsToRemoveSet, Node node) + { + elementsToRemoveSet.UnionWith(node.inputContainer.Children().OfType().SelectMany(c => c.connections) + .Where(d => (d.capabilities & Capabilities.Deletable) != 0) + .Cast()); + elementsToRemoveSet.UnionWith(node.outputContainer.Children().OfType().SelectMany(c => c.connections) + .Where(d => (d.capabilities & Capabilities.Deletable) != 0) + .Cast()); + } + + private void CollectDeletableGraphElements(IEnumerable elements, HashSet elementsToRemoveSet) + { + CollectElements(elements, elementsToRemoveSet, e => (e.capabilities & Capabilities.Deletable) == Capabilities.Deletable); + } + public EventPropagation DeleteSelection() { // TODO: Remove when removing presenters. @@ -1183,24 +1251,8 @@ public EventPropagation DeleteSelection() return DeleteSelectedPresenters(); var elementsToRemoveSet = new HashSet(); - foreach (var selectedElement in selection.Cast().Where(e => e != null)) - { - if ((selectedElement.capabilities & Capabilities.Deletable) == 0) - continue; - - elementsToRemoveSet.Add(selectedElement); - var connectorColl = selectedElement as Node; - if (connectorColl == null) - continue; - - elementsToRemoveSet.UnionWith(connectorColl.inputContainer.Children().OfType().SelectMany(c => c.connections) - .Where(d => (d.capabilities & Capabilities.Deletable) != 0) - .Cast()); - elementsToRemoveSet.UnionWith(connectorColl.outputContainer.Children().OfType().SelectMany(c => c.connections) - .Where(d => (d.capabilities & Capabilities.Deletable) != 0) - .Cast()); - } + CollectDeletableGraphElements(selection.OfType(), elementsToRemoveSet); DeleteElements(elementsToRemoveSet); diff --git a/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs b/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs index eefd5dfa41..5e1b21b247 100644 --- a/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs +++ b/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs @@ -5,9 +5,11 @@ using System; using System.Collections.Generic; using UnityEngine.Bindings; +using UnityEngine.Scripting.APIUpdating; namespace UnityEditorInternal.Profiling { + [MovedFrom("UnityEditorInternal")] public enum ProfilerViewType { Hierarchy = 0, @@ -15,6 +17,7 @@ public enum ProfilerViewType RawHierarchy = 2 } + [MovedFrom("UnityEditorInternal")] public enum ProfilerColumn { DontSort = -1, diff --git a/Modules/UIElements/HierarchyTraversal.cs b/Modules/UIElements/HierarchyTraversal.cs index fe25a19bdb..d0a4d1d7ce 100644 --- a/Modules/UIElements/HierarchyTraversal.cs +++ b/Modules/UIElements/HierarchyTraversal.cs @@ -142,10 +142,17 @@ private bool MatchRightToLeft(VisualElement element, ref RuleMatcher matcher) protected virtual void Recurse(VisualElement element, int depth, List ruleMatchers) { - for (int i = 0; i < element.shadow.childCount; i++) + int i = 0; + + while (i < element.shadow.childCount) { var child = element.shadow[i]; TraverseRecursive(child, depth + 1, ruleMatchers); + + // if the child has been moved to another parent, which happens when its parent has changed, then do not increment the iterator + if (child.shadow.parent != element) + continue; + i++; } } diff --git a/Modules/UnityWebRequest/Public/WebRequestExtensions.cs b/Modules/UnityWebRequest/Public/WebRequestExtensions.cs index 8521cd5ddf..9f1a7170cc 100644 --- a/Modules/UnityWebRequest/Public/WebRequestExtensions.cs +++ b/Modules/UnityWebRequest/Public/WebRequestExtensions.cs @@ -296,7 +296,9 @@ public static string EscapeURL(string s, Encoding e) if (e == null) return null; - return WWWTranscoder.URLEncode(s, e); + var bytes = Encoding.UTF8.GetBytes(s); + var decodedBytes = WWWTranscoder.URLEncode(bytes); + return e.GetString(decodedBytes); } public static string UnEscapeURL(string s) @@ -312,7 +314,9 @@ public static string UnEscapeURL(string s, Encoding e) if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1) return s; - return WWWTranscoder.URLDecode(s, e); + var bytes = Encoding.UTF8.GetBytes(s); + var decodedBytes = WWWTranscoder.URLDecode(bytes); + return e.GetString(decodedBytes); } public static byte[] SerializeFormSections(List multipartFormSections, byte[] boundary) diff --git a/Modules/UnityWebRequest/Public/WebRequestUtils.cs b/Modules/UnityWebRequest/Public/WebRequestUtils.cs index dc7455f00b..948abb2719 100644 --- a/Modules/UnityWebRequest/Public/WebRequestUtils.cs +++ b/Modules/UnityWebRequest/Public/WebRequestUtils.cs @@ -548,7 +548,16 @@ internal static string MakeInitialUrl(string targetUrl, string localUrl) // for file://protocol pass in unescaped string so we can pass it to VFS if (targetUrl.StartsWith("file://", StringComparison.OrdinalIgnoreCase)) - return targetUrl.Contains("%") ? UnityEngine.WWWTranscoder.URLDecode(targetUrl, System.Text.Encoding.UTF8) : targetUrl; + { + if (targetUrl.Contains("%")) + { + var urlBytes = Encoding.UTF8.GetBytes(targetUrl); + var decodedBytes = UnityEngine.WWWTranscoder.URLDecode(urlBytes); + return Encoding.UTF8.GetString(decodedBytes); + } + else + return targetUrl; + } // if URL contains '%', assume it is properly escaped, otherwise '%2f' gets unescaped as '/' (which may not be correct) // otherwise escape it, i.e. replaces spaces by '%20' diff --git a/Modules/UnityWebRequestWWW/Public/WWW.cs b/Modules/UnityWebRequestWWW/Public/WWW.cs index 86d832bd28..a070973721 100644 --- a/Modules/UnityWebRequestWWW/Public/WWW.cs +++ b/Modules/UnityWebRequestWWW/Public/WWW.cs @@ -22,16 +22,7 @@ public static string EscapeURL(string s) public static string EscapeURL(string s, Encoding e) { - if (s == null) - return null; - - if (s == "") - return ""; - - if (e == null) - return null; - - return WWWTranscoder.URLEncode(s, e); + return UnityWebRequest.EscapeURL(s, e); } public static string UnEscapeURL(string s) @@ -41,13 +32,7 @@ public static string UnEscapeURL(string s) public static string UnEscapeURL(string s, Encoding e) { - if (null == s) - return null; - - if (s.IndexOf('%') == -1 && s.IndexOf('+') == -1) - return s; - - return WWWTranscoder.URLDecode(s, e); + return UnityWebRequest.UnEscapeURL(s, e); } public static WWW LoadFromCacheOrDownload(string url, int version) diff --git a/README.md b/README.md index 9ef88899ea..047c8c63dd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.1.0b3 C# reference source code +## Unity 2018.1.0b4 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Export/Pose.cs b/Runtime/Export/Pose.cs index 23074136c2..ca7f301694 100644 --- a/Runtime/Export/Pose.cs +++ b/Runtime/Export/Pose.cs @@ -44,6 +44,21 @@ public Pose GetTransformedBy(Transform lhs) }; } + public Vector3 forward + { + get { return (rotation * Vector3.forward); } + } + + public Vector3 right + { + get { return (rotation * Vector3.right); } + } + + public Vector3 up + { + get { return (rotation * Vector3.up); } + } + static readonly Pose k_Identity = new Pose(Vector3.zero, Quaternion.identity); public static Pose identity { diff --git a/Runtime/Export/RenderPipeline/RenderPipeline.cs b/Runtime/Export/RenderPipeline/RenderPipeline.cs index e13ce9ca86..0deca44bcf 100644 --- a/Runtime/Export/RenderPipeline/RenderPipeline.cs +++ b/Runtime/Export/RenderPipeline/RenderPipeline.cs @@ -8,6 +8,8 @@ namespace UnityEngine.Experimental.Rendering { public abstract class RenderPipeline : IRenderPipeline { + public static event Action beginFrameRendering; + public virtual void Render(ScriptableRenderContext renderContext, Camera[] cameras) { if (disposed) @@ -20,5 +22,10 @@ public virtual void Dispose() { disposed = true; } + + public static void BeginFrameRendering(Camera[] cameras) + { + beginFrameRendering?.Invoke(cameras); + } } } diff --git a/Runtime/Export/RenderPipeline/RenderPipelineAsset.cs b/Runtime/Export/RenderPipeline/RenderPipelineAsset.cs index 19173f2a82..a8b7c4c9fc 100644 --- a/Runtime/Export/RenderPipeline/RenderPipelineAsset.cs +++ b/Runtime/Export/RenderPipeline/RenderPipelineAsset.cs @@ -85,12 +85,12 @@ protected IEnumerable CreatedInstances() return m_CreatedPipelines; } - private void OnValidate() + protected virtual void OnValidate() { DestroyCreatedInstances(); } - private void OnDisable() + protected virtual void OnDisable() { DestroyCreatedInstances(); } diff --git a/artifacts/generated/bindings_old/common/Core/ProfilerBindings.gen.cs b/artifacts/generated/bindings_old/common/Core/ProfilerBindings.gen.cs index e5e4ffdf1f..7887924e77 100644 --- a/artifacts/generated/bindings_old/common/Core/ProfilerBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Core/ProfilerBindings.gen.cs @@ -20,7 +20,10 @@ namespace UnityEngine.Profiling { +[UsedByNativeCode] [MovedFrom("UnityEngine")] + + public sealed partial class Profiler { private Profiler() {} diff --git a/artifacts/generated/bindings_old/common/Editor/UnityConnectBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/UnityConnectBindings.gen.cs index 365dd19860..14ab7859e5 100644 --- a/artifacts/generated/bindings_old/common/Editor/UnityConnectBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/UnityConnectBindings.gen.cs @@ -30,6 +30,8 @@ internal enum CloudConfigUrl CloudIdentity = 6, CloudPortal = 7, CloudPerfEvents = 8, + CloudAdsDashboard = 9, + CloudServicesDashboard = 10 } internal enum COPPACompliance From 57f47116322e5b0a412bf95673603d85af0a1bb5 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 31 Jan 2018 12:56:51 +0000 Subject: [PATCH 04/17] Unity 2018.1.0b5 C# reference source code --- Editor/Mono/AssemblyInfo/AssemblyInfo.cs | 1 + .../TextureGenerator.bindings.cs | 6 +- .../Mono/BuildPipeline/CodeStrippingUtils.cs | 3 +- Editor/Mono/BuildPlayerWindow.cs | 8 +- .../Burst/BurstCompilerService.bindings.cs | 26 ++ Editor/Mono/Burst/BurstCompilerService.cs | 35 +++ Editor/Mono/EditorGUI.cs | 2 +- Editor/Mono/Inspector/BlendTreeInspector.cs | 5 + .../Mono/Inspector/LineRendererInspector.cs | 1 + .../Mono/Inspector/QualitySettingsEditor.cs | 7 +- .../Mono/Inspector/TrailRendererInspector.cs | 1 + .../Media/Bindings/MediaEncoder.bindings.cs | 6 +- .../Modules/DefaultPluginImporterExtension.cs | 3 +- .../ScriptCompilation/EditorBuildRules.cs | 7 +- .../ScriptCompilation/EditorCompilation.cs | 2 +- .../SettingsWindow/GraphicsSettingsEditors.cs | 31 +- .../Mono/SpriteEditor/SpriteEditorWindow.cs | 13 +- .../Troubleshooter/TroubleshooterWindow.cs | 2 +- Modules/AI/NavMesh/NavMesh.bindings.cs | 16 + Modules/AI/NavMeshExperimental.bindings.cs | 296 ++++++++++++++++++ .../ScriptBindings/AudioRenderer.bindings.cs | 8 +- .../AudioSampleProvider.bindings.cs | 4 +- Modules/Input/Private/InputModule.bindings.cs | 8 +- .../Editor/Managed/PackageManagerCommands.cs | 23 ++ .../Substance/SubstanceUtility.bindings.cs | 2 +- Modules/Substance/SubstanceUtility.cs | 76 ++--- Projects/CSharp/UnityEditor.csproj | 11 + Projects/CSharp/UnityEngine.csproj | 23 +- README.md | 2 +- .../SpriteDataAccess.bindings.cs | 31 +- .../ScriptBindings/RaycastCommand.bindings.cs | 44 +++ Runtime/Export/AsyncGPUReadback.bindings.cs | 6 +- Runtime/Export/AtomicSafetyHandle.bindings.cs | 8 - Runtime/Export/Burst/BurstDiscardAttribute.cs | 14 + .../NativeCollectionAccessPolicies.cs | 23 +- Runtime/Export/FriendAttributes.cs | 1 + Runtime/Export/GI/Lightmapping.cs | 4 +- Runtime/Export/NativeArray/NativeArray.cs | 64 ++-- Runtime/Export/NativeArray/NativeSlice.cs | 92 +++--- Runtime/Export/Ping.bindings.cs | 5 +- .../Export/Unsafe/UnsafeUtility.bindings.cs | 105 ++----- Runtime/Export/Unsafe/UnsafeUtilityPatched.cs | 73 +++++ Runtime/Jobs/Managed/BatchQueries.cs | 40 +++ Runtime/Jobs/Managed/IJob.cs | 9 +- Runtime/Jobs/Managed/IJobParallelFor.cs | 9 +- .../Jobs/Managed/IJobParallelForTransform.cs | 9 +- .../Jobs/ScriptBindings/JobHandle.bindings.cs | 22 +- Runtime/Jobs/ScriptBindings/Jobs.bindings.cs | 41 ++- .../TransformAccessArray.bindings.cs | 1 - .../common/Core/ComputeShaderBindings.gen.cs | 26 ++ .../common/Core/HandheldBindings.gen.cs | 10 + .../common/Physics/DynamicsBindings.gen.cs | 14 +- 52 files changed, 967 insertions(+), 312 deletions(-) create mode 100644 Editor/Mono/Burst/BurstCompilerService.bindings.cs create mode 100644 Editor/Mono/Burst/BurstCompilerService.cs create mode 100644 Modules/AI/NavMesh/NavMesh.bindings.cs create mode 100644 Modules/AI/NavMeshExperimental.bindings.cs create mode 100644 Modules/PackageManager/Editor/Managed/PackageManagerCommands.cs create mode 100644 Runtime/Dynamics/ScriptBindings/RaycastCommand.bindings.cs delete mode 100644 Runtime/Export/AtomicSafetyHandle.bindings.cs create mode 100644 Runtime/Export/Burst/BurstDiscardAttribute.cs create mode 100644 Runtime/Export/Unsafe/UnsafeUtilityPatched.cs create mode 100644 Runtime/Jobs/Managed/BatchQueries.cs diff --git a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs index 0b9b249956..0c432cfc16 100644 --- a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs +++ b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs @@ -8,6 +8,7 @@ // ADD_NEW_PLATFORM_HERE [assembly: InternalsVisibleTo("UnityEditor.Advertisements")] [assembly: InternalsVisibleTo("UnityEditor.UIAutomation")] +[assembly: InternalsVisibleTo("Unity.Burst")] [assembly: InternalsVisibleTo("Unity.PackageManager")] [assembly: InternalsVisibleTo("Unity.PackageManagerStandalone")] [assembly: InternalsVisibleTo("Unity.Automation")] diff --git a/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs b/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs index dc8739325c..e917a25336 100644 --- a/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs +++ b/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs @@ -218,15 +218,15 @@ public TextureGenerationSettings(TextureImporterType type) [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureImporterTypes.h")] [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureImporter.bindings.h")] [NativeHeader("Runtime/Serialize/BuildTarget.h")] - public static class TextureGenerator + public static unsafe class TextureGenerator { public static TextureGenerationOutput GenerateTexture(TextureGenerationSettings settings, NativeArray colorBuffer) { - return GenerateTextureImpl(settings, colorBuffer.GetUnsafeReadOnlyPtr(), colorBuffer.Length * 4); + return GenerateTextureImpl(settings, colorBuffer.GetUnsafeReadOnlyPtr(), colorBuffer.Length * UnsafeUtility.SizeOf()); } [NativeThrows] [NativeMethod("GenerateTextureScripting")] - extern static TextureGenerationOutput GenerateTextureImpl(TextureGenerationSettings settings, IntPtr colorBuffer, int colorBufferLength); + extern static unsafe TextureGenerationOutput GenerateTextureImpl(TextureGenerationSettings settings, void* colorBuffer, int colorBufferLength); } } diff --git a/Editor/Mono/BuildPipeline/CodeStrippingUtils.cs b/Editor/Mono/BuildPipeline/CodeStrippingUtils.cs index 66b5dc6a2d..9df34d9a2a 100644 --- a/Editor/Mono/BuildPipeline/CodeStrippingUtils.cs +++ b/Editor/Mono/BuildPipeline/CodeStrippingUtils.cs @@ -75,7 +75,8 @@ public static UnityType[] BlackListNativeClasses static readonly Dictionary s_blackListNativeClassesDependencyNames = new Dictionary { - {"ParticleSystemRenderer", "ParticleSystem"} + {"ParticleSystemRenderer", "ParticleSystem"}, + {"ParticleSystem", "ParticleSystemRenderer"} }; static Dictionary s_blackListNativeClassesDependency; diff --git a/Editor/Mono/BuildPlayerWindow.cs b/Editor/Mono/BuildPlayerWindow.cs index 5219098eb6..888ea30d4d 100644 --- a/Editor/Mono/BuildPlayerWindow.cs +++ b/Editor/Mono/BuildPlayerWindow.cs @@ -62,7 +62,7 @@ class Styles const string kShopURL = "https://store.unity3d.com/shop/"; const string kDownloadURL = "http://unity3d.com/unity/download/"; const string kMailURL = "http://unity3d.com/company/sales?type=sales"; - const string kMultiPlatformURL = "https://unity3d.com/unity/features/multiplatform"; + const string kPlatformInstallationURL = "https://unity3d.com/platform-installation"; // ADD_NEW_PLATFORM_HERE public GUIContent[,] notLicensedMessages = { @@ -71,9 +71,9 @@ class Styles { EditorGUIUtility.TextContent("Your license does not cover Apple TV Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, { EditorGUIUtility.TextContent("Your license does not cover Android Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, { EditorGUIUtility.TextContent("Your license does not cover Tizen Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, - { EditorGUIUtility.TextContent("Your license does not cover Xbox One Publishing. For more information please see 'Unity for Console' on the multiplatform site."), EditorGUIUtility.TrTextContent("Unity Multiplatform"), new GUIContent(kMultiPlatformURL) }, - { EditorGUIUtility.TextContent("Your license does not cover PS Vita Publishing. For more information please see 'Unity for Console' on the multiplatform site."), EditorGUIUtility.TrTextContent("Unity Multiplatform"), new GUIContent(kMultiPlatformURL) }, - { EditorGUIUtility.TextContent("Your license does not cover PS4 Publishing. For more information please see 'Unity for Console' on the multiplatform site."), EditorGUIUtility.TrTextContent("Unity Multiplatform"), new GUIContent(kMultiPlatformURL) }, + { EditorGUIUtility.TextContent("Your license does not cover Xbox One Publishing. Please see the Xbox One section of the Platform Module Installation documentation for more details."), EditorGUIUtility.TrTextContent("Platform Module Installation"), new GUIContent(kPlatformInstallationURL) }, + { EditorGUIUtility.TextContent("Your license does not cover PS Vita Publishing. Please see the PS Vita section of the Platform Module Installation documentation for more details."), EditorGUIUtility.TrTextContent("Platform Module Installation"), new GUIContent(kPlatformInstallationURL) }, + { EditorGUIUtility.TextContent("Your license does not cover PS4 Publishing. Please see the PS4 section of the Platform Module Installation documentation for more details."), EditorGUIUtility.TrTextContent("Platform Module Installation"), new GUIContent(kPlatformInstallationURL) }, { EditorGUIUtility.TextContent("Your license does not cover Universal Windows Platform Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, { EditorGUIUtility.TextContent("Your license does not cover Windows Phone 8 Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, { EditorGUIUtility.TextContent("Your license does not cover Nintendo 3DS Publishing"), EditorGUIUtility.TrTextContent("Contact sales"), new GUIContent(kMailURL) }, diff --git a/Editor/Mono/Burst/BurstCompilerService.bindings.cs b/Editor/Mono/Burst/BurstCompilerService.bindings.cs new file mode 100644 index 0000000000..e8ef7ca6bd --- /dev/null +++ b/Editor/Mono/Burst/BurstCompilerService.bindings.cs @@ -0,0 +1,26 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System; +using System.IO; +using UnityEngine.Bindings; +using System.Reflection; + +namespace Unity.Burst.LowLevel +{ + [NativeHeader("Runtime/Burst/Burst.h")] + [StaticAccessor("BurstCompilerService::Get()", StaticAccessorType.Arrow)] + internal static partial class BurstCompilerService + { + [NativeMethod("Initialize")] + static extern string InitializeInternal(string path, ExtractCompilerFlags extractCompilerFlags); + + public static extern string GetDisassembly(MethodInfo m, string compilerOptions); + + public static extern bool IsInitialized { get; } + } +} diff --git a/Editor/Mono/Burst/BurstCompilerService.cs b/Editor/Mono/Burst/BurstCompilerService.cs new file mode 100644 index 0000000000..32cfc698ad --- /dev/null +++ b/Editor/Mono/Burst/BurstCompilerService.cs @@ -0,0 +1,35 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System; +using System.IO; +using UnityEngine.Bindings; + +namespace Unity.Burst.LowLevel +{ + internal static partial class BurstCompilerService + { + public delegate bool ExtractCompilerFlags(Type jobType, out string flags); + + public static void Initialize(string folderRuntime, ExtractCompilerFlags extractCompilerFlags) + { + if (folderRuntime == null) throw new ArgumentNullException(nameof(folderRuntime)); + if (extractCompilerFlags == null) throw new ArgumentNullException(nameof(extractCompilerFlags)); + + if (!Directory.Exists(folderRuntime)) + { + Debug.LogError($"Unable to initialize the burst JIT compiler. The folder `{folderRuntime}` does not exist"); + return; + } + + var message = InitializeInternal(folderRuntime, extractCompilerFlags); + + if (message != null) + Debug.LogError($"Unexpected error while trying to initialize the burst JIT compiler: {message}"); + } + } +} diff --git a/Editor/Mono/EditorGUI.cs b/Editor/Mono/EditorGUI.cs index a90a1d3e47..abdd782f79 100644 --- a/Editor/Mono/EditorGUI.cs +++ b/Editor/Mono/EditorGUI.cs @@ -1706,7 +1706,7 @@ internal static double DoubleFieldInternal(Rect position, GUIContent label, doub } // Handle dragging of value - private static void DragNumberValue(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, bool isDouble, ref double doubleVal, ref long longVal, string formatString, GUIStyle style, double dragSensitivity) + internal static void DragNumberValue(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, bool isDouble, ref double doubleVal, ref long longVal, string formatString, GUIStyle style, double dragSensitivity) { Event evt = Event.current; diff --git a/Editor/Mono/Inspector/BlendTreeInspector.cs b/Editor/Mono/Inspector/BlendTreeInspector.cs index e5b26e3db8..7a89cb7a88 100644 --- a/Editor/Mono/Inspector/BlendTreeInspector.cs +++ b/Editor/Mono/Inspector/BlendTreeInspector.cs @@ -1305,6 +1305,11 @@ public void RemoveButton(UnityEditorInternal.ReorderableList list) if (list.index >= m_Childs.arraySize) list.index = m_Childs.arraySize - 1; SetMinMaxThresholds(); + + serializedObject.ApplyModifiedProperties(); + + // Layout has changed, bail out now. + EditorGUIUtility.ExitGUI(); } } diff --git a/Editor/Mono/Inspector/LineRendererInspector.cs b/Editor/Mono/Inspector/LineRendererInspector.cs index 7ff31c05c9..66f9c06cac 100644 --- a/Editor/Mono/Inspector/LineRendererInspector.cs +++ b/Editor/Mono/Inspector/LineRendererInspector.cs @@ -43,6 +43,7 @@ public override void OnEnable() excludedProperties.Add("m_MotionVectors"); if (!SupportedRenderingFeatures.active.rendererSupportsReceiveShadows) excludedProperties.Add("m_ReceiveShadows"); + excludedProperties.Add("m_RenderingLayerMask"); m_ExcludedProperties = excludedProperties.ToArray(); m_CurveEditor.OnEnable(serializedObject); diff --git a/Editor/Mono/Inspector/QualitySettingsEditor.cs b/Editor/Mono/Inspector/QualitySettingsEditor.cs index a1e082b9b3..2f85962e6e 100644 --- a/Editor/Mono/Inspector/QualitySettingsEditor.cs +++ b/Editor/Mono/Inspector/QualitySettingsEditor.cs @@ -7,6 +7,7 @@ using UnityEditor.Build; using System.Linq; using UnityEditorInternal; +using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; namespace UnityEditor @@ -534,14 +535,16 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(resolutionScalingFixedDPIFactorProperty); GUILayout.Space(10); + GUILayout.Label(EditorGUIUtility.TempContent("Shadows"), EditorStyles.boldLabel); + if (SupportedRenderingFeatures.IsMixedLightingModeSupported(MixedLightingMode.Shadowmask)) + EditorGUILayout.PropertyField(shadowMaskUsageProperty); + if (!usingSRP) { - GUILayout.Label(EditorGUIUtility.TempContent("Shadows"), EditorStyles.boldLabel); EditorGUILayout.PropertyField(shadowsProperty); EditorGUILayout.PropertyField(shadowResolutionProperty); EditorGUILayout.PropertyField(shadowProjectionProperty); EditorGUILayout.PropertyField(shadowDistanceProperty); - EditorGUILayout.PropertyField(shadowMaskUsageProperty); EditorGUILayout.PropertyField(shadowNearPlaneOffsetProperty); EditorGUILayout.PropertyField(shadowCascadesProperty); diff --git a/Editor/Mono/Inspector/TrailRendererInspector.cs b/Editor/Mono/Inspector/TrailRendererInspector.cs index dfff9d1db0..32f231e4e3 100644 --- a/Editor/Mono/Inspector/TrailRendererInspector.cs +++ b/Editor/Mono/Inspector/TrailRendererInspector.cs @@ -42,6 +42,7 @@ public override void OnEnable() excludedProperties.Add("m_ReflectionProbeUsage"); excludedProperties.Add("m_ProbeAnchor"); excludedProperties.Add("m_Parameters"); + excludedProperties.Add("m_RenderingLayerMask"); m_ExcludedProperties = excludedProperties.ToArray(); m_CurveEditor.OnEnable(serializedObject); diff --git a/Editor/Mono/Media/Bindings/MediaEncoder.bindings.cs b/Editor/Mono/Media/Bindings/MediaEncoder.bindings.cs index 06ac02abe2..00f29847ce 100644 --- a/Editor/Mono/Media/Bindings/MediaEncoder.bindings.cs +++ b/Editor/Mono/Media/Bindings/MediaEncoder.bindings.cs @@ -83,7 +83,7 @@ public bool AddFrame(Texture2D texture) return Internal_AddFrame(m_Ptr, texture); } - public bool AddSamples(ushort trackIndex, NativeArray interleavedSamples) + unsafe public bool AddSamples(ushort trackIndex, NativeArray interleavedSamples) { return Internal_AddSamples( m_Ptr, trackIndex, interleavedSamples.GetUnsafeReadOnlyPtr(), @@ -126,7 +126,7 @@ extern private static IntPtr Internal_Create( extern private static bool Internal_AddFrame(IntPtr encoder, Texture2D texture); [FreeFunction] - extern private static bool Internal_AddSamples( - IntPtr encoder, ushort trackIndex, IntPtr buffer, int sampleCount); + unsafe extern private static bool Internal_AddSamples( + IntPtr encoder, ushort trackIndex, void* buffer, int sampleCount); } } diff --git a/Editor/Mono/Modules/DefaultPluginImporterExtension.cs b/Editor/Mono/Modules/DefaultPluginImporterExtension.cs index a4cafade64..4e27dd1fb8 100644 --- a/Editor/Mono/Modules/DefaultPluginImporterExtension.cs +++ b/Editor/Mono/Modules/DefaultPluginImporterExtension.cs @@ -67,7 +67,8 @@ protected void ParseStringValue(PluginImporterInspector inspector, string valueS internal virtual void Apply(PluginImporterInspector inspector) { - inspector.importer.SetPlatformData(platformName, key, value.ToString()); + string valueString = type == typeof(bool) ? value.ToString().ToLower() : value.ToString(); + inspector.importer.SetPlatformData(platformName, key, valueString); } internal virtual void OnGUI(PluginImporterInspector inspector) diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs index 51b605f2bb..961de2583b 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs @@ -506,7 +506,7 @@ internal static void AddScriptAssemblyReferences(ref ScriptAssembly scriptAssemb precompiledAssembliesForReferences = precompiledAssembliesForReferences.Where(x => x.OptionalUnityReferences == OptionalUnityReferences.None || ((targetAssembly.OptionalUnityReferences & x.OptionalUnityReferences & settings.OptionalUnityReferences) != 0)).ToArray(); } - var precompiledReferences = GetPrecompiledReferences(scriptAssembly, settings.CompilationOptions, targetAssembly.editorCompatibility, precompiledAssembliesForReferences); + var precompiledReferences = GetPrecompiledReferences(scriptAssembly, targetAssembly.Type, settings.CompilationOptions, targetAssembly.editorCompatibility, precompiledAssembliesForReferences); references.AddRange(precompiledReferences); if (buildingForEditor && assemblies.EditorAssemblyReferences != null) @@ -625,12 +625,13 @@ public static List GetUnityReferences(ScriptAssembly scriptAssembly, Pre return references; } - public static List GetPrecompiledReferences(ScriptAssembly scriptAssembly, EditorScriptCompilationOptions options, EditorCompatibility editorCompatibility, PrecompiledAssembly[] precompiledAssemblies) + public static List GetPrecompiledReferences(ScriptAssembly scriptAssembly, TargetAssemblyType targetAssemblyType, EditorScriptCompilationOptions options, EditorCompatibility editorCompatibility, PrecompiledAssembly[] precompiledAssemblies) { var references = new List(); bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; bool assemblyEditorOnly = (scriptAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; + bool isCustomAssembly = (targetAssemblyType & TargetAssemblyType.Custom) == TargetAssemblyType.Custom; if (precompiledAssemblies != null) foreach (var precompiledAssembly in precompiledAssemblies) @@ -638,7 +639,7 @@ public static List GetPrecompiledReferences(ScriptAssembly scriptAssembl bool compiledAssemblyEditorOnly = (precompiledAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; // Add all pre-compiled runtime assemblies as references to all script assemblies. Don't add pre-compiled editor assemblies as dependencies to runtime assemblies. - if (!compiledAssemblyEditorOnly || assemblyEditorOnly || (buildingForEditor && editorCompatibility == EditorCompatibility.CompatibleWithEditor)) + if (!compiledAssemblyEditorOnly || assemblyEditorOnly || (isCustomAssembly && buildingForEditor && editorCompatibility == EditorCompatibility.CompatibleWithEditor)) { if (IsPrecompiledAssemblyCompatibleWithScriptAssembly(precompiledAssembly, scriptAssembly)) references.Add(precompiledAssembly.Path); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index d0bbe137af..8a4cecb62e 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -1087,7 +1087,7 @@ public ScriptAssembly CreateScriptAssembly(Compilation.AssemblyBuilder assemblyB var unityReferences = EditorBuildRules.GetUnityReferences(scriptAssembly, unityAssemblies, options); var customReferences = EditorBuildRules.GetCompiledCustomAssembliesReferences(scriptAssembly, customTargetAssemblies, GetCompileScriptsOutputDirectory(), assemblySuffix); - var precompiledReferences = EditorBuildRules.GetPrecompiledReferences(scriptAssembly, options, EditorBuildRules.EditorCompatibility.CompatibleWithEditor, precompiledAssemblies); + var precompiledReferences = EditorBuildRules.GetPrecompiledReferences(scriptAssembly, EditorBuildRules.TargetAssemblyType.Custom, options, EditorBuildRules.EditorCompatibility.CompatibleWithEditor, precompiledAssemblies); var additionalReferences = EditorBuildRules.GenerateAdditionalReferences(scriptAssembly.ApiCompatibilityLevel, scriptAssembly.BuildTarget, scriptAssembly.Language, buildingForEditor, scriptAssembly.Filename); string[] editorReferences = buildingForEditor ? ModuleUtils.GetAdditionalReferencesForUserScripts() : new string[0]; diff --git a/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs b/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs index 96ef0aba29..8b30e40b47 100644 --- a/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs +++ b/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs @@ -5,6 +5,7 @@ using System; using UnityEngine; using UnityEditor.Build; +using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; using EditorGraphicsSettings = UnityEditor.Rendering.EditorGraphicsSettings; using TierSettings = UnityEditor.Rendering.TierSettings; @@ -348,7 +349,9 @@ internal void OnFieldLabelsGUI(bool vertical) EditorGUILayout.LabelField(Styles.detailNormalMap); EditorGUILayout.LabelField(Styles.semitransparentShadows); } - EditorGUILayout.LabelField(Styles.enableLPPV); + + if (SupportedRenderingFeatures.active.rendererSupportsLightProbeProxyVolumes) + EditorGUILayout.LabelField(Styles.enableLPPV); if (!vertical) { @@ -361,10 +364,17 @@ internal void OnFieldLabelsGUI(bool vertical) EditorGUILayout.LabelField(Styles.cascadedShadowMaps); EditorGUILayout.LabelField(Styles.prefer32BitShadowMaps); EditorGUILayout.LabelField(Styles.useHDR); - EditorGUILayout.LabelField(Styles.hdrMode); + } + + EditorGUILayout.LabelField(Styles.hdrMode); + + if (!usingSRP) + { EditorGUILayout.LabelField(Styles.renderingPath); } - EditorGUILayout.LabelField(Styles.realtimeGICPUUsage); + + if (SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime)) + EditorGUILayout.LabelField(Styles.realtimeGICPUUsage); } // custom enum handling @@ -430,7 +440,9 @@ internal void OnTierGUI(BuildTargetGroup platform, GraphicsTier tier, bool verti ts.detailNormalMap = EditorGUILayout.Toggle(ts.detailNormalMap); ts.semitransparentShadows = EditorGUILayout.Toggle(ts.semitransparentShadows); } - ts.enableLPPV = EditorGUILayout.Toggle(ts.enableLPPV); + + if (SupportedRenderingFeatures.active.rendererSupportsLightProbeProxyVolumes) + ts.enableLPPV = EditorGUILayout.Toggle(ts.enableLPPV); if (!vertical) { @@ -443,10 +455,15 @@ internal void OnTierGUI(BuildTargetGroup platform, GraphicsTier tier, bool verti ts.cascadedShadowMaps = EditorGUILayout.Toggle(ts.cascadedShadowMaps); ts.prefer32BitShadowMaps = EditorGUILayout.Toggle(ts.prefer32BitShadowMaps); ts.hdr = EditorGUILayout.Toggle(ts.hdr); - ts.hdrMode = HDRModePopup(ts.hdrMode); - ts.renderingPath = RenderingPathPopup(ts.renderingPath); } - ts.realtimeGICPUUsage = RealtimeGICPUUsagePopup(ts.realtimeGICPUUsage); + + ts.hdrMode = HDRModePopup(ts.hdrMode); + + if (!usingSRP) + ts.renderingPath = RenderingPathPopup(ts.renderingPath); + + if (SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime)) + ts.realtimeGICPUUsage = RealtimeGICPUUsagePopup(ts.realtimeGICPUUsage); if (EditorGUI.EndChangeCheck()) { diff --git a/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs b/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs index 9b23fc331f..22667271f1 100644 --- a/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs +++ b/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs @@ -325,13 +325,13 @@ void OnGUI() if (m_ResetOnNextRepaint || selectedProviderChanged || m_RectsCache == null) { + m_ResetOnNextRepaint = false; HandleApplyRevertDialog(SpriteEditorWindowStyles.applyRevertDialogTitle.text, SpriteEditorWindowStyles.pendingChangesDialogContent.text); ResetWindow(); RefreshPropertiesCache(); RefreshRects(); UpdateAvailableModules(); SetupModule(m_CurrentModuleIndex); - m_ResetOnNextRepaint = false; } Matrix4x4 oldHandlesMatrix = Handles.matrix; @@ -629,15 +629,16 @@ void SetupModule(int newModuleIndex) if (s_Instance == null) return; - if (m_CurrentModule != null) - m_CurrentModule.OnModuleDeactivate(); - - m_CurrentModule = null; if (m_RegisteredModules.Count > newModuleIndex) { + m_CurrentModuleIndex = newModuleIndex; + if (m_CurrentModule != null) + m_CurrentModule.OnModuleDeactivate(); + + m_CurrentModule = null; + m_CurrentModule = m_RegisteredModules[newModuleIndex]; m_CurrentModule.OnModuleActivate(); - m_CurrentModuleIndex = newModuleIndex; } } diff --git a/Editor/Mono/Troubleshooter/TroubleshooterWindow.cs b/Editor/Mono/Troubleshooter/TroubleshooterWindow.cs index ddd79672c5..f3a318d0a0 100644 --- a/Editor/Mono/Troubleshooter/TroubleshooterWindow.cs +++ b/Editor/Mono/Troubleshooter/TroubleshooterWindow.cs @@ -29,7 +29,7 @@ internal override WebView webView set { m_WebView = value; } } - [MenuItem("Help/Troubleshoot Issue...")] + [MenuItem("Help/Troubleshoot Issue...", priority = 2000)] public static void RunTroubleshooter() { TroubleshooterWindow window = EditorWindow.GetWindowWithRect(new Rect(100, 100, 990, 680), true, "Troubleshooter") as TroubleshooterWindow; diff --git a/Modules/AI/NavMesh/NavMesh.bindings.cs b/Modules/AI/NavMesh/NavMesh.bindings.cs new file mode 100644 index 0000000000..0074c422aa --- /dev/null +++ b/Modules/AI/NavMesh/NavMesh.bindings.cs @@ -0,0 +1,16 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using UnityEngine.Bindings; + +namespace UnityEngine.AI +{ + [NativeHeader("Modules/AI/NavMeshManager.h")] + public static partial class NavMesh + { + [StaticAccessor("GetNavMeshManager()")] + [NativeName("Cleanup")] + public static extern void RemoveAllNavMeshData(); + } +} diff --git a/Modules/AI/NavMeshExperimental.bindings.cs b/Modules/AI/NavMeshExperimental.bindings.cs new file mode 100644 index 0000000000..b5fc25f0f4 --- /dev/null +++ b/Modules/AI/NavMeshExperimental.bindings.cs @@ -0,0 +1,296 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + + +using System; +using System.Runtime.InteropServices; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; +using Unity.Jobs; +using UnityEngine.Bindings; +using UnityEngine.AI; + +namespace UnityEngine.Experimental.AI +{ + public struct PolygonID + { + internal ulong polyRef; + + public bool IsNull() { return polyRef == 0; } + + public static bool operator==(PolygonID x, PolygonID y) { return x.polyRef == y.polyRef; } + public static bool operator!=(PolygonID x, PolygonID y) { return x.polyRef != y.polyRef; } + public override int GetHashCode() { return polyRef.GetHashCode(); } + public override bool Equals(object obj) + { + if (obj == null || !(obj is PolygonID)) + return false; + var rhs = (PolygonID)obj; + return rhs == this; + } + } + + public struct NavMeshLocation + { + public PolygonID polygon { get; } + public Vector3 position { get; } + + internal NavMeshLocation(Vector3 position, PolygonID polygon) + { + this.position = position; + this.polygon = polygon; + } + } + + //public struct NavMeshHit + //{ + // public NavMeshLocation position; + // public Vector3 normal; + // public float distance; + + // public int area; //Think if this should be a struct etc + + // public bool hit; + //} + + //public struct NavMeshPolyData + //{ + // internal unsafe fixed ulong neighbors[6]; + // internal unsafe fixed float vertices[6 * 3]; + // internal int areaType; + // internal int vertexCount; + //} + + //public struct NavMeshSegment + //{ + // public Vector3 begin; + // public Vector3 end; + //} + + // Keep in sync with the values in NavMeshTypes.h + [Flags] + public enum PathQueryStatus + { + // High level status. + Failure = 1 << 31, + Success = 1 << 30, + InProgress = 1 << 29, + + // Detail information for status. + StatusDetailMask = 0x0ffffff, + WrongMagic = 1 << 0, // Input data is not recognized. + WrongVersion = 1 << 1, // Input data is in wrong version. + OutOfMemory = 1 << 2, // Operation ran out of memory. + InvalidParam = 1 << 3, // An input parameter was invalid. + BufferTooSmall = 1 << 4, // Result buffer for the query was too small to store all results. + OutOfNodes = 1 << 5, // Query ran out of nodes during search. + PartialResult = 1 << 6 // Query did not reach the end location, returning best guess. + } + + // Flags describing polygon properties. Keep in sync with the enum declared in NavMesh.h + public enum NavMeshPolyTypes + { + Ground = 0, // Regular ground polygons. + OffMeshConnection = 1 // Off-mesh connections. + } + + [StaticAccessor("NavMeshWorldBindings", StaticAccessorType.DoubleColon)] + public struct NavMeshWorld + { + internal IntPtr world; + + public bool IsValid() + { + return world != IntPtr.Zero; + } + + public static extern NavMeshWorld GetDefaultWorld(); + + static extern void AddDependencyInternal(IntPtr navmesh, JobHandle handle); + + public void AddDependency(JobHandle job) + { + AddDependencyInternal(world, job); + } + } + + [NativeContainer] + [StructLayout(LayoutKind.Sequential)] + [NativeHeader("Modules/AI/NavMeshExperimental.bindings.h")] + [NativeHeader("Runtime/Math/Matrix4x4.h")] + [StaticAccessor("NavMeshQueryBindings", StaticAccessorType.DoubleColon)] + public struct NavMeshQuery : IDisposable + { + [NativeDisableUnsafePtrRestriction] + internal IntPtr m_NavMeshQuery; + Allocator m_Allocator; + + + public NavMeshQuery(NavMeshWorld world, Allocator allocator, int pathNodePoolSize = 0) + { + m_Allocator = allocator; + m_NavMeshQuery = Create(world, pathNodePoolSize); + + } + + public void Dispose() + { + Destroy(m_NavMeshQuery); + m_NavMeshQuery = IntPtr.Zero; + } + + static extern IntPtr Create(NavMeshWorld world, int nodePoolSize); + + static extern void Destroy(IntPtr navMeshQuery); + + + + public unsafe PathQueryStatus BeginFindPath(NavMeshLocation start, NavMeshLocation end, + int areaMask = NavMesh.AllAreas, NativeArray costs = new NativeArray()) + { + void* costsPtr = costs.Length > 0 ? costs.GetUnsafePtr() : null; + return BeginFindPath(m_NavMeshQuery, start, end, areaMask, costsPtr); + } + + public PathQueryStatus UpdateFindPath(int iterations, out int iterationsPerformed) + { + return UpdateFindPath(m_NavMeshQuery, iterations, out iterationsPerformed); + } + + public PathQueryStatus EndFindPath(out int pathSize) + { + return EndFindPath(m_NavMeshQuery, out pathSize); + } + + public unsafe int GetPathResult(NativeSlice path) + { + return GetPathResult(m_NavMeshQuery, path.GetUnsafePtr(), path.Length); + } + + [ThreadSafe] + unsafe static extern PathQueryStatus BeginFindPath(IntPtr navMeshQuery, NavMeshLocation start, NavMeshLocation end, int areaMask, void* costs); + + [ThreadSafe] + static extern PathQueryStatus UpdateFindPath(IntPtr navMeshQuery, int iterations, out int iterationsPerformed); + + [ThreadSafe] + static extern PathQueryStatus EndFindPath(IntPtr navMeshQuery, out int pathSize); + + [ThreadSafe] + unsafe static extern int GetPathResult(IntPtr navMeshQuery, void* path, int maxPath); + + // If BeginFindPath/UpdateFindPath/EndFindPath existing NativeArray become invalid... +// extern NavMeshPathStatus GetPath(out NativeArray outputPath); + + //void DidScheduleJob(JobHandle handle); + + + [ThreadSafe] + static extern bool IsValidPolygon(IntPtr navMeshQuery, PolygonID polygon); + + public bool IsValid(PolygonID polygon) + { + return polygon.polyRef != 0 && IsValidPolygon(m_NavMeshQuery, polygon); + } + + public bool IsValid(NavMeshLocation location) + { + return IsValid(location.polygon); + } + + [ThreadSafe] + static extern int GetAgentTypeIdForPolygon(IntPtr navMeshQuery, PolygonID polygon); + public int GetAgentTypeIdForPolygon(PolygonID polygon) + { + return GetAgentTypeIdForPolygon(m_NavMeshQuery, polygon); + } + + [ThreadSafe] + static extern bool IsPositionInPolygon(IntPtr navMeshQuery, Vector3 position, PolygonID polygon); + + public NavMeshLocation CreateLocation(Vector3 position, PolygonID polygon) + { + return new NavMeshLocation(position, polygon); + } + + [ThreadSafe] + static extern NavMeshLocation MapLocation(IntPtr navMeshQuery, Vector3 position, Vector3 extents, int agentTypeID, int areaMask = NavMesh.AllAreas); + public NavMeshLocation MapLocation(Vector3 position, Vector3 extents, int agentTypeID, int areaMask = NavMesh.AllAreas) + { + return MapLocation(m_NavMeshQuery, position, extents, agentTypeID, areaMask); + } + + [ThreadSafe] + static unsafe extern void MoveLocations(IntPtr navMeshQuery, void* locations, void* targets, void* areaMasks, int count); + public unsafe void MoveLocations(NativeSlice locations, NativeSlice targets, NativeSlice areaMasks) + { + MoveLocations(m_NavMeshQuery, locations.GetUnsafePtr(), targets.GetUnsafeReadOnlyPtr(), areaMasks.GetUnsafeReadOnlyPtr(), locations.Length); + } + + [ThreadSafe] + unsafe static extern void MoveLocationsInSameAreas(IntPtr navMeshQuery, void* locations, void* targets, int count, int areaMask); + unsafe public void MoveLocationsInSameAreas(NativeSlice locations, NativeSlice targets, int areaMask = NavMesh.AllAreas) + { + MoveLocationsInSameAreas(m_NavMeshQuery, locations.GetUnsafePtr(), targets.GetUnsafeReadOnlyPtr(), locations.Length, areaMask); + } + + [ThreadSafe] + static extern NavMeshLocation MoveLocation(IntPtr navMeshQuery, NavMeshLocation location, Vector3 target, int areaMask); + public NavMeshLocation MoveLocation(NavMeshLocation location, Vector3 target, int areaMask = NavMesh.AllAreas) + { + return MoveLocation(m_NavMeshQuery, location, target, areaMask); + } + + [ThreadSafe] + static extern bool GetPortalPoints(IntPtr navMeshQuery, PolygonID polygon, PolygonID neighbourPolygon, out Vector3 left, out Vector3 right); + public bool GetPortalPoints(PolygonID polygon, PolygonID neighbourPolygon, out Vector3 left, out Vector3 right) + { + return GetPortalPoints(m_NavMeshQuery, polygon, neighbourPolygon, out left, out right); + } + + [ThreadSafe] + static extern Matrix4x4 PolygonLocalToWorldMatrix(IntPtr navMeshQuery, PolygonID polygon); + public Matrix4x4 PolygonLocalToWorldMatrix(PolygonID polygon) + { + return PolygonLocalToWorldMatrix(m_NavMeshQuery, polygon); + } + + [ThreadSafe] + static extern Matrix4x4 PolygonWorldToLocalMatrix(IntPtr navMeshQuery, PolygonID polygon); + public Matrix4x4 PolygonWorldToLocalMatrix(PolygonID polygon) + { + return PolygonWorldToLocalMatrix(m_NavMeshQuery, polygon); + } + + [ThreadSafe] + static extern NavMeshPolyTypes GetPolygonType(IntPtr navMeshQuery, PolygonID polygon); + public NavMeshPolyTypes GetPolygonType(PolygonID polygon) + { + return GetPolygonType(m_NavMeshQuery, polygon); + } + + //NavMeshStatus MoveAlongSurface(NavMeshLocation location, Vector3 targetPosition, int agentTypeID, int areaMask, + // out NavMeshLocation outputLocation, NativeArray visitedBuffer, out int actualVisited); + + //// Trace a ray between two points on the NavMesh. + //extern bool Raycast(NavMeshLocation location, Vector3 targetPosition, out NavMeshHit hit, int agentTypeID, int areaMask, NativeArray costs); + + //// Polygon Queries + //public NavMeshPolyData GetPolygon(PolygonID poly); + //public void GetPolygon(NativeArray polygonIDs, NativeArray polygons); + //public void GetPolygons(MappedPosition position, float distance, NativeList polygons); + + //public static void LocalizePolygonIndices(NativeArray polygons); + + //// Segments + //public NativeArray FindBoundarySegments (MappedPosition position, float distance, Allocator allocator); + + //// Voxel rasterize + //public void Rasterize (MappedPosition position, Quaternion orientation, float cellWidth, float cellHeight, NativeArray2D grid); + + //// DetailMesh queries + //void ProjectToDetailMesh(NativeArray positions, NativeArray outputPositions); + } +} + diff --git a/Modules/Audio/Public/ScriptBindings/AudioRenderer.bindings.cs b/Modules/Audio/Public/ScriptBindings/AudioRenderer.bindings.cs index aadcca78ca..02c81a76ad 100644 --- a/Modules/Audio/Public/ScriptBindings/AudioRenderer.bindings.cs +++ b/Modules/Audio/Public/ScriptBindings/AudioRenderer.bindings.cs @@ -30,12 +30,12 @@ public static int GetSampleCountForCaptureFrame() } // We should consider making this delegate-based in order to provide information like channel count and format. Also the term "sink" is quite audio-domain specific. - internal static bool AddMixerGroupSink(AudioMixerGroup mixerGroup, NativeArray buffer, bool excludeFromMix) + unsafe internal static bool AddMixerGroupSink(AudioMixerGroup mixerGroup, NativeArray buffer, bool excludeFromMix) { return Internal_AudioRenderer_AddMixerGroupSink(mixerGroup, buffer.GetUnsafePtr(), buffer.Length, excludeFromMix); } - public static bool Render(NativeArray buffer) + unsafe public static bool Render(NativeArray buffer) { return Internal_AudioRenderer_Render(buffer.GetUnsafePtr(), buffer.Length); } @@ -43,7 +43,7 @@ public static bool Render(NativeArray buffer) internal static extern bool Internal_AudioRenderer_Start(); internal static extern bool Internal_AudioRenderer_Stop(); internal static extern int Internal_AudioRenderer_GetSampleCountForCaptureFrame(); - internal static extern bool Internal_AudioRenderer_AddMixerGroupSink(AudioMixerGroup mixerGroup, IntPtr ptr, int length, bool excludeFromMix); - internal static extern bool Internal_AudioRenderer_Render(IntPtr ptr, int length); + unsafe internal static extern bool Internal_AudioRenderer_AddMixerGroupSink(AudioMixerGroup mixerGroup, void* ptr, int length, bool excludeFromMix); + unsafe internal static extern bool Internal_AudioRenderer_Render(void* ptr, int length); } } diff --git a/Modules/Audio/Public/ScriptBindings/AudioSampleProvider.bindings.cs b/Modules/Audio/Public/ScriptBindings/AudioSampleProvider.bindings.cs index 1be0ce6bc0..e291c8f2fd 100644 --- a/Modules/Audio/Public/ScriptBindings/AudioSampleProvider.bindings.cs +++ b/Modules/Audio/Public/ScriptBindings/AudioSampleProvider.bindings.cs @@ -106,13 +106,13 @@ public bool enableSilencePadding set { InternalSetEnableSilencePadding(id, value); } } - public uint ConsumeSampleFrames(NativeArray sampleFrames) + unsafe public uint ConsumeSampleFrames(NativeArray sampleFrames) { if (channelCount == 0) return 0; return m_ConsumeSampleFramesNativeFunction( - id, sampleFrames.GetUnsafePtr(), (uint)sampleFrames.Length / channelCount); + id, (IntPtr)sampleFrames.GetUnsafePtr(), (uint)sampleFrames.Length / channelCount); } public static ConsumeSampleFramesNativeFunction consumeSampleFramesNativeFunction diff --git a/Modules/Input/Private/InputModule.bindings.cs b/Modules/Input/Private/InputModule.bindings.cs index 00e5f21f34..5b97153ba0 100644 --- a/Modules/Input/Private/InputModule.bindings.cs +++ b/Modules/Input/Private/InputModule.bindings.cs @@ -21,18 +21,18 @@ public partial class NativeInputSystem // C# doesn't allow taking the address of a value type because of pinning requirements for the heap. // And our bindings generator doesn't support overloading. So ugly code following here... - public static void SendInput(TInputEvent inputEvent) + public unsafe static void SendInput(TInputEvent inputEvent) where TInputEvent : struct { - SendInput(UnsafeUtility.AddressOf(ref inputEvent)); + SendInput((IntPtr)UnsafeUtility.AddressOf(ref inputEvent)); } public static extern void SendInput(IntPtr inputEvent); - public static bool SendOutput(int deviceId, int type, TOutputEvent outputEvent) + unsafe public static bool SendOutput(int deviceId, int type, TOutputEvent outputEvent) where TOutputEvent : struct { - return SendOutput(deviceId, type, UnsafeUtility.SizeOf(), UnsafeUtility.AddressOf(ref outputEvent)); + return SendOutput(deviceId, type, UnsafeUtility.SizeOf(), (IntPtr)UnsafeUtility.AddressOf(ref outputEvent)); } public static extern bool SendOutput(int deviceId, int type, int sizeInBytes, IntPtr data); diff --git a/Modules/PackageManager/Editor/Managed/PackageManagerCommands.cs b/Modules/PackageManager/Editor/Managed/PackageManagerCommands.cs new file mode 100644 index 0000000000..eff87310f8 --- /dev/null +++ b/Modules/PackageManager/Editor/Managed/PackageManagerCommands.cs @@ -0,0 +1,23 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using UnityEngine; +using UnityEditor.PackageManager.Requests; + +namespace UnityEditor.PackageManager +{ + static class PackageManagerCommands + { + [MenuItem("Help/Reset Packages to defaults", priority = 1000)] + public static void ResetProjectPackagesToEditorDefaults() + { + ResetToEditorDefaultsRequest request = Client.ResetToEditorDefaults(); + if (request.Status == StatusCode.Failure) + { + Debug.LogError("Resetting your project's packages to the editor's default configuration failed. Reason: " + request.Error.message); + } + } + } +} + diff --git a/Modules/Substance/SubstanceUtility.bindings.cs b/Modules/Substance/SubstanceUtility.bindings.cs index 4ae814f060..e7a719a073 100644 --- a/Modules/Substance/SubstanceUtility.bindings.cs +++ b/Modules/Substance/SubstanceUtility.bindings.cs @@ -15,7 +15,7 @@ public partial class ProceduralMaterial : Material { static void FeatureRemoved() { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } //static extern void BindingsGeneratorTrigger(); diff --git a/Modules/Substance/SubstanceUtility.cs b/Modules/Substance/SubstanceUtility.cs index fcc514752f..cafd0baa03 100644 --- a/Modules/Substance/SubstanceUtility.cs +++ b/Modules/Substance/SubstanceUtility.cs @@ -15,7 +15,7 @@ namespace UnityEngine { - [Obsolete("ProceduralProcessorUsage is deprecated and no longer available.", true)] + [Obsolete("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store.", true)] public enum ProceduralProcessorUsage { Unsupported = 0, @@ -24,7 +24,7 @@ public enum ProceduralProcessorUsage All = 3 } - [Obsolete("ProceduralCacheSize is deprecated and no longer available.", true)] + [Obsolete("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store.", true)] public enum ProceduralCacheSize { Tiny = 0, @@ -34,7 +34,7 @@ public enum ProceduralCacheSize None = 4 } - [Obsolete("ProceduralLoadingBehavior is deprecated and no longer available.", true)] + [Obsolete("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store.", true)] public enum ProceduralLoadingBehavior { DoNothing = 0, @@ -45,7 +45,7 @@ public enum ProceduralLoadingBehavior DoNothingAndCache = 5 } - [Obsolete("ProceduralPropertyType is deprecated and no longer available.", true)] + [Obsolete("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store.", true)] public enum ProceduralPropertyType { Boolean = 0, @@ -60,7 +60,7 @@ public enum ProceduralPropertyType String = 9 } - [Obsolete("ProceduralOutputType is deprecated and no longer available.", true)] + [Obsolete("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store.", true)] public enum ProceduralOutputType { Unknown = 0, @@ -78,7 +78,7 @@ public enum ProceduralOutputType } [StructLayout(LayoutKind.Sequential)] - [Obsolete("ProceduralPropertyDescription is deprecated and no longer available.", true)] + [Obsolete("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store.", true)] public sealed partial class ProceduralPropertyDescription { public string name; @@ -93,7 +93,7 @@ public sealed partial class ProceduralPropertyDescription public string[] componentLabels; } - [Obsolete("ProceduralMaterial is deprecated and no longer available.", true)] + [Obsolete("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store.", true)] [ExcludeFromPreset] public sealed partial class ProceduralMaterial : Material { @@ -105,22 +105,22 @@ internal ProceduralMaterial() public ProceduralPropertyDescription[] GetProceduralPropertyDescriptions() { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public bool HasProceduralProperty(string inputName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public bool GetProceduralBoolean(string inputName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public bool IsProceduralPropertyVisible(string inputName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public void SetProceduralBoolean(string inputName, bool value) @@ -130,7 +130,7 @@ public void SetProceduralBoolean(string inputName, bool value) public float GetProceduralFloat(string inputName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public void SetProceduralFloat(string inputName, float value) @@ -140,7 +140,7 @@ public void SetProceduralFloat(string inputName, float value) public Vector4 GetProceduralVector(string inputName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public void SetProceduralVector(string inputName, Vector4 value) @@ -150,7 +150,7 @@ public void SetProceduralVector(string inputName, Vector4 value) public Color GetProceduralColor(string inputName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public void SetProceduralColor(string inputName, Color value) @@ -160,7 +160,7 @@ public void SetProceduralColor(string inputName, Color value) public int GetProceduralEnum(string inputName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public void SetProceduralEnum(string inputName, int value) @@ -170,7 +170,7 @@ public void SetProceduralEnum(string inputName, int value) public Texture2D GetProceduralTexture(string inputName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public void SetProceduralTexture(string inputName, Texture2D value) @@ -180,7 +180,7 @@ public void SetProceduralTexture(string inputName, Texture2D value) public string GetProceduralString(string inputName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public void SetProceduralString(string inputName, string value) @@ -190,7 +190,7 @@ public void SetProceduralString(string inputName, string value) public bool IsProceduralPropertyCached(string inputName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public void CacheProceduralProperty(string inputName, bool value) @@ -205,14 +205,14 @@ public void ClearCache() public ProceduralCacheSize cacheSize { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } set { FeatureRemoved(); } } public int animationUpdateRate { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } set { FeatureRemoved(); } } @@ -228,7 +228,7 @@ public void RebuildTexturesImmediately() public bool isProcessing { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } } public static void StopRebuilds() @@ -238,50 +238,50 @@ public static void StopRebuilds() public bool isCachedDataAvailable { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } } public bool isLoadTimeGenerated { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } set { FeatureRemoved(); } } public ProceduralLoadingBehavior loadingBehavior { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } } public static bool isSupported { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } } public static ProceduralProcessorUsage substanceProcessorUsage { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } set { FeatureRemoved(); } } public string preset { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } set { FeatureRemoved(); } } public Texture[] GetGeneratedTextures() { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public ProceduralTexture GetGeneratedTexture(string textureName) { - throw new Exception("ProceduralMaterial is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public bool isReadable { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } set { FeatureRemoved(); } } @@ -292,42 +292,42 @@ public void FreezeAndReleaseSourceData() public bool isFrozen { - get { throw new Exception("ProceduralMaterial is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } } } - [Obsolete("ProceduralTexture is deprecated and no longer available.", true)] + [Obsolete("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store.", true)] [ExcludeFromPreset] public sealed partial class ProceduralTexture : Texture { private ProceduralTexture() { - throw new Exception("ProceduralTexture is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public ProceduralOutputType GetProceduralOutputType() { - throw new Exception("ProceduralTexture is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } internal ProceduralMaterial GetProceduralMaterial() { - throw new Exception("ProceduralTexture is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } public bool hasAlpha { - get { throw new Exception("ProceduralTexture is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } } public TextureFormat format { - get { throw new Exception("ProceduralTexture is deprecated and no longer available."); } + get { throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } } public Color32[] GetPixels32(int x, int y, int blockWidth, int blockHeight) { - throw new Exception("ProceduralTexture is deprecated and no longer available."); + throw new Exception("Built-in support for Substance Designer materials has been removed from Unity. To continue using Substance Designer materials, you will need to install Allegorithmic's external importer from the Asset Store."); } } diff --git a/Projects/CSharp/UnityEditor.csproj b/Projects/CSharp/UnityEditor.csproj index 26976cea85..58f73e2418 100644 --- a/Projects/CSharp/UnityEditor.csproj +++ b/Projects/CSharp/UnityEditor.csproj @@ -23,12 +23,14 @@ false bin\Debug\ DEBUG;TRACE;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_UNLOCKED_DIAGNOSTIC_SWITCHES;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_LOCALIZATION;COMBINED_ASSEMBLIES;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_ALTERNATIVE_LISTEN_PORT;ENABLE_AUDIO_MANAGER_BASED_SCHEDULING;ENABLE_MONO;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_VERSION_CONTROL_INTEGRATION;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_UNITYWEBREQUEST;ENABLE_VIDEO;PLAYERCONNECTION_LISTENS_FIXED_PORT;UNITY_EDITOR;ENABLE_HOLOLENS_MODULE_API;UNITY_PS4_API;ENABLE_VR;ENABLE_CLOUD_SERVICES_COLLAB_TESTING;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_CRUNCH_TEXTURE_COMPRESSION;UNITY_EDITOR_API;UNITY_ANDROID_API;UNITY_STANDALONE_WIN_API;UNITY_STANDALONE_OSX_API;UNITY_PSVITA_API;UNITY_XBOXONE_API;UNITY_SWITCH_API;UNITY_IPHONE_API;UNITY_TVOS_API;UNITY_STANDALONE_LINUX_API;UNITY_TIZEN_API;UNITY_WEBGL_API;UNITY_PS4_API;UNITY_METRO_API;UNITY_N3DS_API;UNITY_ASSEMBLIES_API;UNITY_ASSERTIONS + true pdbonly true bin\Release\ TRACE;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_DUCK_TYPING;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_SPRITERENDERER_FLIPPING;ENABLE_SPRITES;ENABLE_GRID;ENABLE_TILEMAP;ENABLE_TERRAIN;ENABLE_RAKNET;ENABLE_DIRECTOR;ENABLE_UNET;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_COLLAB;ENABLE_CLOUD_SERVICES_COLLAB_SOFTLOCKS;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_HUB;ENABLE_CLOUD_PROJECT_ID;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_UNET;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_TIMELINE;ENABLE_EDITOR_METRICS;ENABLE_EDITOR_METRICS_CACHING;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;INCLUDE_DYNAMIC_GI;INCLUDE_GI;ENABLE_MONO_BDWGC;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;INCLUDE_PUBNUB;ENABLE_UNLOCKED_DIAGNOSTIC_SWITCHES;ENABLE_PLAYMODE_TESTS_RUNNER;ENABLE_VIDEO;ENABLE_PACKMAN;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_LOCALIZATION;COMBINED_ASSEMBLIES;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_ALTERNATIVE_LISTEN_PORT;ENABLE_AUDIO_MANAGER_BASED_SCHEDULING;ENABLE_MONO;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_VERSION_CONTROL_INTEGRATION;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_UNITYWEBREQUEST;ENABLE_VIDEO;PLAYERCONNECTION_LISTENS_FIXED_PORT;UNITY_EDITOR;ENABLE_HOLOLENS_MODULE_API;UNITY_PS4_API;ENABLE_VR;ENABLE_CLOUD_SERVICES_COLLAB_TESTING;ENABLE_AR;ENABLE_SPATIALTRACKING;ENABLE_CRUNCH_TEXTURE_COMPRESSION;UNITY_EDITOR_API;UNITY_ANDROID_API;UNITY_STANDALONE_WIN_API;UNITY_STANDALONE_OSX_API;UNITY_PSVITA_API;UNITY_XBOXONE_API;UNITY_SWITCH_API;UNITY_IPHONE_API;UNITY_TVOS_API;UNITY_STANDALONE_LINUX_API;UNITY_TIZEN_API;UNITY_WEBGL_API;UNITY_PS4_API;UNITY_METRO_API;UNITY_N3DS_API;UNITY_ASSEMBLIES_API;UNITY_ASSERTIONS + true @@ -2163,6 +2165,12 @@ Editor\Mono\Playables\Playables.bindings.cs + +Editor\Mono\Burst\BurstCompilerService.cs + + +Editor\Mono\Burst\BurstCompilerService.bindings.cs + Editor\Mono\Accessibility\UserAccessibilitySettings.cs @@ -3886,6 +3894,9 @@ Modules\PackageManager\Editor\Managed\PackageManager.bindings.cs + +Modules\PackageManager\Editor\Managed\PackageManagerCommands.cs + Modules\PackageManager\Editor\Managed\PackageStatus.cs diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index 3dd699a998..898aec1293 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -184,9 +184,6 @@ Runtime\Export\ArrayUtils.cs - -Runtime\Export\AtomicSafetyHandle.bindings.cs - Runtime\Export\UnityEvent.cs @@ -667,9 +664,15 @@ Runtime\Export\GI\Lightmapping.cs + +Runtime\Export\Burst\BurstDiscardAttribute.cs + Runtime\Export\Unsafe\UnsafeUtility.bindings.cs + +Runtime\Export\Unsafe\UnsafeUtilityPatched.cs + Runtime\Export\iOS\iOSReplayKit.bindings.cs @@ -737,7 +740,10 @@ Runtime\Export\Assertions\Must\MustFloat.cs Runtime\Transform\ScriptBindings\TransformAccessArray.bindings.cs - + +Runtime\Jobs\Managed\BatchQueries.cs + + Runtime\Jobs\Managed\IJobParallelForTransform.cs @@ -1002,6 +1008,9 @@ Runtime\Dynamics\Managed\Dynamics.cs + +Runtime\Dynamics\ScriptBindings\RaycastCommand.bindings.cs + artifacts\generated\bindings_old\common\Physics\DynamicsBindings.gen.cs @@ -1278,6 +1287,12 @@ artifacts\generated\bindings_old\common\VR\TransformLockBindings.gen.cs + +Modules\AI\NavMeshExperimental.bindings.cs + + +Modules\AI\NavMesh\NavMesh.bindings.cs + Modules\AI\NavMesh\NavMesh.cs diff --git a/README.md b/README.md index 047c8c63dd..9cc1e7e9cb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.1.0b4 C# reference source code +## Unity 2018.1.0b5 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs b/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs index 64774c158f..abd472a38a 100644 --- a/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs +++ b/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs @@ -58,7 +58,7 @@ internal struct SpriteChannelInfo [NativeNameAttribute("stride")] int m_Stride; - public IntPtr buffer { get { return m_Buffer; } set { m_Buffer = value; } } + unsafe public void* buffer { get { return (void*)m_Buffer; } set { m_Buffer = (IntPtr)value; } } public int count { get { return m_Count; } set { m_Count = value; } } public int offset { get { return m_Offset; } set { m_Offset = value; } } public int stride { get { return m_Stride; } set { m_Stride = value; } } @@ -96,52 +96,53 @@ private static void CheckAttributeTypeMatchesAndThrow(VertexAttribute channel throw new InvalidOperationException(String.Format("The requested channel '{0}' does not match the return type {1}.", channel, typeof(T).Name)); } - public static NativeSlice GetVertexAttribute(this Sprite sprite, VertexAttribute channel) where T : struct + public unsafe static NativeSlice GetVertexAttribute(this Sprite sprite, VertexAttribute channel) where T : struct { CheckAttributeTypeMatchesAndThrow(channel); var info = GetChannelInfo(sprite, channel); - var slice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice(info.buffer, info.offset, info.count, info.stride); + var buffer = (byte*)(info.buffer) + info.offset; + var slice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice(buffer, info.stride, info.count); return slice; } - public static void SetVertexAttribute(this Sprite sprite, VertexAttribute channel, NativeArray src) where T : struct + unsafe public static void SetVertexAttribute(this Sprite sprite, VertexAttribute channel, NativeArray src) where T : struct { CheckAttributeTypeMatchesAndThrow(channel); SetChannelData(sprite, channel, src.GetUnsafeReadOnlyPtr()); } - public static NativeArray GetBindPoses(this Sprite sprite) + unsafe public static NativeArray GetBindPoses(this Sprite sprite) { var info = GetBindPoseInfo(sprite); var arr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(info.buffer, info.count, Allocator.Invalid); return arr; } - public static void SetBindPoses(this Sprite sprite, NativeArray src) + unsafe public static void SetBindPoses(this Sprite sprite, NativeArray src) { SetBindPoseData(sprite, src.GetUnsafeReadOnlyPtr(), src.Length); } - public static NativeArray GetIndices(this Sprite sprite) + unsafe public static NativeArray GetIndices(this Sprite sprite) { var info = GetIndicesInfo(sprite); var arr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(info.buffer, info.count, Allocator.Invalid); return arr; } - public static void SetIndices(this Sprite sprite, NativeArray src) + unsafe public static void SetIndices(this Sprite sprite, NativeArray src) { SetIndicesData(sprite, src.GetUnsafeReadOnlyPtr(), src.Length); } - public static NativeArray GetBoneWeights(this Sprite sprite) + unsafe public static NativeArray GetBoneWeights(this Sprite sprite) { var info = GetBoneWeightsInfo(sprite); var arr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(info.buffer, info.count, Allocator.Invalid); return arr; } - public static void SetBoneWeights(this Sprite sprite, NativeArray src) + unsafe public static void SetBoneWeights(this Sprite sprite, NativeArray src) { SetBoneWeightsData(sprite, src.GetUnsafeReadOnlyPtr(), src.Length); } @@ -165,19 +166,19 @@ public static void SetBones(this Sprite sprite, SpriteBone[] src) // This lenght is not tied to vertexCount extern private static SpriteChannelInfo GetBindPoseInfo(Sprite sprite); - extern private static void SetBindPoseData(Sprite sprite, IntPtr src, int count); + unsafe extern private static void SetBindPoseData(Sprite sprite, void* src, int count); extern private static SpriteChannelInfo GetIndicesInfo(Sprite sprite); - extern private static void SetIndicesData(Sprite sprite, IntPtr src, int count); + unsafe extern private static void SetIndicesData(Sprite sprite, void* src, int count); extern private static SpriteChannelInfo GetChannelInfo(Sprite sprite, VertexAttribute channel); - extern private static void SetChannelData(Sprite sprite, VertexAttribute channel, IntPtr src); + unsafe extern private static void SetChannelData(Sprite sprite, VertexAttribute channel, void* src); extern private static SpriteBone[] GetBoneInfo(Sprite sprite); extern private static void SetBoneData(Sprite sprite, SpriteBone[] src); extern private static SpriteChannelInfo GetBoneWeightsInfo(Sprite sprite); - extern private static void SetBoneWeightsData(Sprite sprite, IntPtr src, int count); + unsafe extern private static void SetBoneWeightsData(Sprite sprite, void* src, int count); } @@ -185,7 +186,7 @@ public static void SetBones(this Sprite sprite, SpriteBone[] src) [NativeHeader("Runtime/Graphics/Mesh/SpriteRenderer.h")] public static class SpriteRendererDataAccessExtensions { - public static NativeArray GetDeformableVertices(this SpriteRenderer spriteRenderer) + public unsafe static NativeArray GetDeformableVertices(this SpriteRenderer spriteRenderer) { var info = GetDeformableChannelInfo(spriteRenderer, VertexAttribute.Position); var arr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(info.buffer, info.count, Allocator.Invalid); diff --git a/Runtime/Dynamics/ScriptBindings/RaycastCommand.bindings.cs b/Runtime/Dynamics/ScriptBindings/RaycastCommand.bindings.cs new file mode 100644 index 0000000000..5a53022a7e --- /dev/null +++ b/Runtime/Dynamics/ScriptBindings/RaycastCommand.bindings.cs @@ -0,0 +1,44 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using Unity.Jobs; +using Unity.Jobs.LowLevel.Unsafe; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; + +namespace UnityEngine +{ + [NativeHeader("Runtime/Dynamics/BatchCommands/RaycastCommand.h")] + [NativeHeader("Runtime/Jobs/ScriptBindings/JobsBindingsTypes.h")] + public struct RaycastCommand + { + public RaycastCommand(Vector3 from, Vector3 direction, float distance = float.MaxValue, int layerMask = Physics.DefaultRaycastLayers, int maxHits = 1) + { + this.from = from; + this.direction = direction; + this.distance = distance; + this.layerMask = layerMask; + this.maxHits = maxHits; + } + + public Vector3 from; + public Vector3 direction; + public float distance { get; set; } + public int layerMask { get; set; } + public int maxHits { get; set; } + + public unsafe static JobHandle ScheduleBatch(NativeArray commands, NativeArray results, int minCommandsPerJob, JobHandle dependsOn = new JobHandle()) + { + var jobData = new BatchQueryJob(commands, results); + var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), BatchQueryJobStruct>.Initialize(), dependsOn, ScheduleMode.Batched); + + return ScheduleRaycastBatch(ref scheduleParams, commands.GetUnsafePtr(), commands.Length, results.GetUnsafePtr(), results.Length, minCommandsPerJob); + } + + [FreeFunction("ScheduleRaycastCommandBatch")] + unsafe extern private static JobHandle ScheduleRaycastBatch(ref JobsUtility.JobScheduleParameters parameters, void* commands, int commandLen, void* result, int resultLen, int minCommandsPerJob); + } +} diff --git a/Runtime/Export/AsyncGPUReadback.bindings.cs b/Runtime/Export/AsyncGPUReadback.bindings.cs index 04a2133eba..3ea5a70c8d 100644 --- a/Runtime/Export/AsyncGPUReadback.bindings.cs +++ b/Runtime/Export/AsyncGPUReadback.bindings.cs @@ -24,7 +24,7 @@ public struct AsyncGPUReadbackRequest extern public void Update(); extern public void WaitForCompletion(); - public NativeArray GetData(int layer = 0) where T : struct + public unsafe NativeArray GetData(int layer = 0) where T : struct { if (!done || hasError) throw new InvalidOperationException("Cannot access the data as it is not available"); @@ -34,7 +34,7 @@ public NativeArray GetData(int layer = 0) where T : struct int stride = UnsafeUtility.SizeOf(); - var array = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(GetDataRaw(layer), GetLayerDataSize() / stride, Allocator.None); + var array = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray((void*)GetDataRaw(layer), GetLayerDataSize() / stride, Allocator.None); return array; } @@ -47,7 +47,7 @@ public NativeArray GetData(int layer = 0) where T : struct private extern bool HasError(); private extern int GetLayerCount(); - private extern IntPtr GetDataRaw(int layer); + unsafe private extern IntPtr GetDataRaw(int layer); private extern int GetLayerDataSize(); } diff --git a/Runtime/Export/AtomicSafetyHandle.bindings.cs b/Runtime/Export/AtomicSafetyHandle.bindings.cs deleted file mode 100644 index f3b4521926..0000000000 --- a/Runtime/Export/AtomicSafetyHandle.bindings.cs +++ /dev/null @@ -1,8 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - diff --git a/Runtime/Export/Burst/BurstDiscardAttribute.cs b/Runtime/Export/Burst/BurstDiscardAttribute.cs new file mode 100644 index 0000000000..08f82e3384 --- /dev/null +++ b/Runtime/Export/Burst/BurstDiscardAttribute.cs @@ -0,0 +1,14 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; + +namespace Unity.Burst +{ + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)] + public class BurstDiscardAttribute : Attribute + { + // Attribute used to discard entirely a method/property from being compiled by the burst compiler. + } +} diff --git a/Runtime/Export/Collections/NativeCollectionAccessPolicies.cs b/Runtime/Export/Collections/NativeCollectionAccessPolicies.cs index 4ccb6bbb6a..0bf51b9371 100644 --- a/Runtime/Export/Collections/NativeCollectionAccessPolicies.cs +++ b/Runtime/Export/Collections/NativeCollectionAccessPolicies.cs @@ -8,12 +8,12 @@ namespace Unity.Collections { [RequiredByNativeCode] - [AttributeUsage(AttributeTargets.Field)] + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue)] public sealed class ReadOnlyAttribute : Attribute {} [RequiredByNativeCode] - [AttributeUsage(AttributeTargets.Field)] + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue)] public sealed class WriteOnlyAttribute : Attribute {} @@ -39,11 +39,6 @@ public sealed class NativeMatchesParallelForLengthAttribute : Attribute [AttributeUsage(AttributeTargets.Field)] public sealed class NativeDisableParallelForRestrictionAttribute : Attribute {} - - [RequiredByNativeCode] - [AttributeUsage(AttributeTargets.Field)] - public sealed class NativeDisableUnsafePtrRestrictionAttribute : Attribute - {} } namespace Unity.Collections.LowLevel.Unsafe @@ -72,4 +67,18 @@ public sealed class NativeContainerSupportsDeallocateOnJobCompletionAttribute : [AttributeUsage(AttributeTargets.Struct)] public sealed class NativeContainerNeedsThreadIndexAttribute : Attribute {} + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method)] + public class WriteAccessRequiredAttribute : Attribute + {} + + [RequiredByNativeCode] + [AttributeUsage(AttributeTargets.Field)] + public sealed class NativeDisableUnsafePtrRestrictionAttribute : Attribute + {} + + [RequiredByNativeCode] + [AttributeUsage(AttributeTargets.Field)] + public sealed class NativeSetClassTypeToNullOnScheduleAttribute : Attribute + {} } diff --git a/Runtime/Export/FriendAttributes.cs b/Runtime/Export/FriendAttributes.cs index 07eedd5df3..6a3c3466d9 100644 --- a/Runtime/Export/FriendAttributes.cs +++ b/Runtime/Export/FriendAttributes.cs @@ -25,3 +25,4 @@ // needed for UnityEngine.UnsafeUtility and Object.FindObjectFromInstanceID. [assembly: InternalsVisibleTo("UnityEngine.Physics2DModule")] +[assembly: InternalsVisibleTo("UnityEngine.PhysicsModule")] diff --git a/Runtime/Export/GI/Lightmapping.cs b/Runtime/Export/GI/Lightmapping.cs index 4709ed8299..e4572748b5 100644 --- a/Runtime/Export/GI/Lightmapping.cs +++ b/Runtime/Export/GI/Lightmapping.cs @@ -358,9 +358,9 @@ public static class Lightmapping public static void ResetDelegate() { s_RequestLightsDelegate = s_DefaultDelegate; } [UnityEngine.Scripting.UsedByNativeCode] - internal static void RequestLights(Light[] lights, System.IntPtr outLightsPtr, int outLightsCount) + internal unsafe static void RequestLights(Light[] lights, System.IntPtr outLightsPtr, int outLightsCount) { - var outLights = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(outLightsPtr, outLightsCount, Allocator.None); + var outLights = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray((void*)outLightsPtr, outLightsCount, Allocator.None); s_RequestLightsDelegate(lights, outLights); } diff --git a/Runtime/Export/NativeArray/NativeArray.cs b/Runtime/Export/NativeArray/NativeArray.cs index 9c2473f597..f6d0fec2aa 100644 --- a/Runtime/Export/NativeArray/NativeArray.cs +++ b/Runtime/Export/NativeArray/NativeArray.cs @@ -6,17 +6,16 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using Unity.Burst; using Unity.Collections.LowLevel.Unsafe; namespace Unity.Collections { - [System.Flags] public enum NativeArrayOptions { - None = 0, - ClearMemory = 1 << 0 + UninitializedMemory = 0, + ClearMemory = 1 } [StructLayout(LayoutKind.Sequential)] @@ -25,9 +24,10 @@ public enum NativeArrayOptions [NativeContainerSupportsDeallocateOnJobCompletion] [DebuggerDisplay("Length = {Length}")] [DebuggerTypeProxy(typeof(NativeArrayDebugView < >))] - public struct NativeArray : IDisposable, IEnumerable where T : struct + unsafe public struct NativeArray : IDisposable, IEnumerable where T : struct { - internal IntPtr m_Buffer; + [NativeDisableUnsafePtrRestriction] + internal void* m_Buffer; internal int m_Length; @@ -37,7 +37,7 @@ public NativeArray(int length, Allocator allocator, NativeArrayOptions options = { Allocate(length, allocator, out this); if ((options & NativeArrayOptions.ClearMemory) == NativeArrayOptions.ClearMemory) - UnsafeUtility.MemClear(m_Buffer, (ulong)Length * (ulong)UnsafeUtility.SizeOf()); + UnsafeUtility.MemClear(m_Buffer, (long)Length * (long)UnsafeUtility.SizeOf()); } public NativeArray(T[] array, Allocator allocator) @@ -58,7 +58,7 @@ private static void Allocate(int length, Allocator allocator, out NativeArray long totalSize = UnsafeUtility.SizeOf() * (long)length; - array.m_Buffer = UnsafeUtility.Malloc((ulong)totalSize, UnsafeUtility.AlignOf(), allocator); + array.m_Buffer = UnsafeUtility.Malloc(totalSize, UnsafeUtility.AlignOf(), allocator); array.m_Length = length; array.m_AllocatorLabel = allocator; @@ -66,34 +66,54 @@ private static void Allocate(int length, Allocator allocator, out NativeArray public int Length { get { return m_Length; } } + [BurstDiscard] + internal static void IsBlittableAndThrow() + { + if (!UnsafeUtility.IsBlittable()) + throw new ArgumentException(string.Format("{0} used in NativeArray<{0}> must be blittable", typeof(T))); + } + + [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] + private unsafe void CheckElementReadAccess(int index) + { + } + + [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] + private unsafe void CheckElementWriteAccess(int index) + { + } + public unsafe T this[int index] { get { + CheckElementReadAccess(index); return UnsafeUtility.ReadArrayElement(m_Buffer, index); } + [WriteAccessRequired] set { - + CheckElementWriteAccess(index); UnsafeUtility.WriteArrayElement(m_Buffer, index, value); } } public bool IsCreated { - get { return m_Buffer != IntPtr.Zero; } + get { return m_Buffer != null; } } + [WriteAccessRequired] public void Dispose() { UnsafeUtility.Free(m_Buffer, m_AllocatorLabel); - m_Buffer = IntPtr.Zero; + m_Buffer = null; m_Length = 0; } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining + [WriteAccessRequired] public void CopyFrom(T[] array) { @@ -101,13 +121,12 @@ public void CopyFrom(T[] array) UnsafeUtility.WriteArrayElement(m_Buffer, i, array[i]); } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining + [WriteAccessRequired] public void CopyFrom(NativeArray array) { array.CopyTo(this); } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining public void CopyTo(T[] array) { @@ -115,14 +134,12 @@ public void CopyTo(T[] array) array[i] = UnsafeUtility.ReadArrayElement(m_Buffer, i); } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining public void CopyTo(NativeArray array) { - UnsafeUtility.MemCpy(array.m_Buffer, m_Buffer, (ulong)Length * (ulong)UnsafeUtility.SizeOf()); + UnsafeUtility.MemCpy(array.m_Buffer, m_Buffer, (long)Length * (long)UnsafeUtility.SizeOf()); } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining public T[] ToArray() { var array = new T[Length]; @@ -206,12 +223,13 @@ namespace Unity.Collections.LowLevel.Unsafe public static class NativeArrayUnsafeUtility { - public static NativeArray ConvertExistingDataToNativeArray(IntPtr dataPointer, int length, Allocator allocator) where T : struct + /// Internal method used typically by other systems to provide a view on them. + /// The caller is still the owner of the data. + unsafe public static NativeArray ConvertExistingDataToNativeArray(void* dataPointer, int length, Allocator allocator) where T : struct { + var newArray = new NativeArray { - // Internal method used typically by other systems to provide a view on them. - // The caller is still the owner of the data. m_Buffer = dataPointer, m_Length = length, m_AllocatorLabel = allocator, @@ -221,17 +239,17 @@ public static NativeArray ConvertExistingDataToNativeArray(IntPtr dataPoin return newArray; } - public static IntPtr GetUnsafePtr(this NativeArray nativeArray) where T : struct + public unsafe static void* GetUnsafePtr(this NativeArray nativeArray) where T : struct { return nativeArray.m_Buffer; } - public static IntPtr GetUnsafeReadOnlyPtr(this NativeArray nativeArray) where T : struct + public unsafe static void* GetUnsafeReadOnlyPtr(this NativeArray nativeArray) where T : struct { return nativeArray.m_Buffer; } - public static IntPtr GetUnsafeBufferPointerWithoutChecks(this NativeArray nativeArray) where T : struct + unsafe public static void* GetUnsafeBufferPointerWithoutChecks(this NativeArray nativeArray) where T : struct { return nativeArray.m_Buffer; } diff --git a/Runtime/Export/NativeArray/NativeSlice.cs b/Runtime/Export/NativeArray/NativeSlice.cs index c276ae2f6c..12309e87d0 100644 --- a/Runtime/Export/NativeArray/NativeSlice.cs +++ b/Runtime/Export/NativeArray/NativeSlice.cs @@ -6,7 +6,6 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Unity.Collections.LowLevel.Unsafe; @@ -28,6 +27,21 @@ public static NativeSlice Slice(this NativeArray thisArray, int start, { return new NativeSlice(thisArray, start, length); } + + public static NativeSlice Slice(this NativeSlice thisSlice) where T : struct + { + return thisSlice; + } + + public static NativeSlice Slice(this NativeSlice thisSlice, int length) where T : struct + { + return new NativeSlice(thisSlice, length); + } + + public static NativeSlice Slice(this NativeSlice thisSlice, int start, int length) where T : struct + { + return new NativeSlice(thisSlice, start, length); + } } @@ -36,33 +50,44 @@ public static NativeSlice Slice(this NativeArray thisArray, int start, [NativeContainerSupportsMinMaxWriteRestriction] [DebuggerDisplay("Length = {Length}")] [DebuggerTypeProxy(typeof(NativeSliceDebugView < >))] - public struct NativeSlice : IEnumerable where T : struct + unsafe public struct NativeSlice : IEnumerable where T : struct { - internal IntPtr m_Buffer; + [NativeDisableUnsafePtrRestriction] + internal byte* m_Buffer; internal int m_Stride; internal int m_Length; - public static implicit operator NativeSlice(NativeArray array) + public NativeSlice(NativeSlice slice, int start) : this(slice, start, slice.Length - start) {} + + public unsafe NativeSlice(NativeSlice slice, int start, int length) { - return new NativeSlice(array); + + m_Stride = slice.m_Stride; + m_Buffer = slice.m_Buffer + m_Stride * start; + m_Length = length; + } public NativeSlice(NativeArray array) : this(array, 0, array.Length) {} public NativeSlice(NativeArray array, int start) : this(array, start, array.Length - start) {} + public static implicit operator NativeSlice(NativeArray array) + { + return new NativeSlice(array); + } + public unsafe NativeSlice(NativeArray array, int start, int length) { m_Stride = UnsafeUtility.SizeOf(); byte* ptr = (byte*)array.m_Buffer + m_Stride * start; - m_Buffer = (IntPtr)ptr; + m_Buffer = ptr; m_Length = length; } // Keeps stride, changes length - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining public NativeSlice SliceConvert() where U : struct { var sizeofU = UnsafeUtility.SizeOf(); @@ -76,32 +101,22 @@ public NativeSlice SliceConvert() where U : struct } // Keeps length, changes stride - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining public unsafe NativeSlice SliceWithStride(int offset) where U : struct { NativeSlice outputSlice; - byte* ptr = (byte*)m_Buffer + offset; - outputSlice.m_Buffer = (IntPtr)ptr; + outputSlice.m_Buffer = m_Buffer + offset; outputSlice.m_Stride = m_Stride; outputSlice.m_Length = m_Length; return outputSlice; } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining public NativeSlice SliceWithStride() where U : struct { return SliceWithStride(0); } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining - public NativeSlice SliceWithStride(string offsetFieldName) where U : struct - { - var offsetOf = UnsafeUtility.OffsetOf(offsetFieldName); - return SliceWithStride(offsetOf); - } - public unsafe T this[int index] { get @@ -110,6 +125,7 @@ public unsafe T this[int index] return UnsafeUtility.ReadArrayElementWithStride(m_Buffer, index, m_Stride); } + [WriteAccessRequired] set { @@ -118,15 +134,14 @@ public unsafe T this[int index] } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining + [WriteAccessRequired] public void CopyFrom(NativeSlice slice) { - for (var i = 0; i != m_Length; i++) - this[i] = slice[i]; + UnsafeUtility.MemCpyStride(this.GetUnsafePtr(), Stride, slice.GetUnsafeReadOnlyPtr(), slice.Stride, UnsafeUtility.SizeOf(), m_Length); } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining + [WriteAccessRequired] public void CopyFrom(T[] array) { @@ -134,22 +149,20 @@ public void CopyFrom(T[] array) this[i] = array[i]; } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining public void CopyTo(NativeArray array) { - for (var i = 0; i != m_Length; i++) - array[i] = this[i]; + int sizeOf = UnsafeUtility.SizeOf(); + UnsafeUtility.MemCpyStride(array.GetUnsafePtr(), sizeOf, this.GetUnsafeReadOnlyPtr(), Stride, sizeOf, m_Length); } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining public void CopyTo(T[] array) { + for (var i = 0; i != m_Length; i++) array[i] = this[i]; } - [MethodImpl((MethodImplOptions) 256)] // AggressiveInlining public T[] ToArray() { var array = new T[Length]; @@ -235,33 +248,18 @@ namespace Unity.Collections.LowLevel.Unsafe { public static class NativeSliceUnsafeUtility { - public static NativeSlice ConvertExistingDataToNativeSlice(IntPtr dataPointer, int length) where T : struct - { - var newSlice = new NativeSlice - { - m_Stride = UnsafeUtility.SizeOf(), - m_Buffer = dataPointer, - m_Length = length, - - }; - - return newSlice; - } - public static unsafe NativeSlice ConvertExistingDataToNativeSlice(IntPtr dataPointer, int start, int length, int stride) where T : struct + public static unsafe NativeSlice ConvertExistingDataToNativeSlice(void* dataPointer, int stride, int length) where T : struct { if (length < 0) throw new System.ArgumentException(String.Format("Invalid length of '{0}'. It must be greater than 0.", length)); - if (start < 0) - throw new System.ArgumentException(String.Format("Invalid start index of '{0}'. It must be greater than 0.", start)); if (stride < 0) throw new System.ArgumentException(String.Format("Invalid stride '{0}'. It must be greater than 0.", stride)); - byte* ptr = (byte*)dataPointer + start; var newSlice = new NativeSlice { m_Stride = stride, - m_Buffer = (IntPtr)ptr, + m_Buffer = (byte*)dataPointer, m_Length = length, }; @@ -269,14 +267,12 @@ public static unsafe NativeSlice ConvertExistingDataToNativeSlice(IntPtr d return newSlice; } - [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] - public static IntPtr GetUnsafePtr(this NativeSlice nativeSlice) where T : struct + unsafe public static void* GetUnsafePtr(this NativeSlice nativeSlice) where T : struct { return nativeSlice.m_Buffer; } - [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] - public static IntPtr GetUnsafeReadOnlyPtr(this NativeSlice nativeSlice) where T : struct + unsafe public static void* GetUnsafeReadOnlyPtr(this NativeSlice nativeSlice) where T : struct { return nativeSlice.m_Buffer; } diff --git a/Runtime/Export/Ping.bindings.cs b/Runtime/Export/Ping.bindings.cs index d04ad6ebde..d64412a041 100644 --- a/Runtime/Export/Ping.bindings.cs +++ b/Runtime/Export/Ping.bindings.cs @@ -25,12 +25,11 @@ public Ping(string address) [ThreadAndSerializationSafe] public void DestroyPing() { - m_Ptr = IntPtr.Zero; Internal_Destroy(m_Ptr); + m_Ptr = IntPtr.Zero; } - [ThreadAndSerializationSafe] - [FreeFunction("DestroyPing")] + [NativeMethod(Name = "DestroyPing", IsFreeFunction = true, IsThreadSafe = true)] private static extern void Internal_Destroy(IntPtr ptr); [FreeFunction("CreatePing")] private static extern IntPtr Internal_Create(string address); diff --git a/Runtime/Export/Unsafe/UnsafeUtility.bindings.cs b/Runtime/Export/Unsafe/UnsafeUtility.bindings.cs index de29396224..1a272a5e7f 100644 --- a/Runtime/Export/Unsafe/UnsafeUtility.bindings.cs +++ b/Runtime/Export/Unsafe/UnsafeUtility.bindings.cs @@ -6,83 +6,42 @@ using System.Reflection; using System.Runtime.InteropServices; using UnityEngine.Bindings; +using System.Runtime.CompilerServices; namespace Unity.Collections.LowLevel.Unsafe { [NativeHeader("Runtime/Export/Unsafe/UnsafeUtility.bindings.h")] [StaticAccessor("UnsafeUtility", StaticAccessorType.DoubleColon)] [VisibleToOtherModules] - public static class UnsafeUtility + public static partial class UnsafeUtility { - // Copies sizeof(T) bytes from ptr to output - public static void CopyPtrToStructure(IntPtr ptr, out T output) where T : struct - { - // @patched at compile time - throw new NotImplementedException("Patching this method failed"); - } - - // Copies sizeof(T) bytes from output to ptr - public static void CopyStructureToPtr(ref T input, IntPtr ptr) where T : struct - { - // @patched at compile time - throw new NotImplementedException("Patching this method failed"); - } - - public static T ReadArrayElement(IntPtr source, int index) - { - // @patched at compile time - throw new NotImplementedException("Patching this method failed"); - } - - public static T ReadArrayElementWithStride(IntPtr source, int index, int stride) - { - // @patched at compile time - throw new NotImplementedException("Patching this method failed"); - } - - public static void WriteArrayElement(IntPtr destination, int index, T value) - { - // @patched at compile time - throw new NotImplementedException("Patching this method failed"); - } - public static void WriteArrayElementWithStride(IntPtr destination, int index, int stride, T value) - { - // @patched at compile time - throw new NotImplementedException("Patching this method failed"); - } - - // The address of the memory where the struct resides in memory - public static IntPtr AddressOf(ref T output) where T : struct - { - // @patched at compile time - throw new NotImplementedException("Patching this method failed"); - } + [ThreadSafe] + extern static int GetFieldOffsetInStruct(FieldInfo field); - // The size of a struct - public static int SizeOf() where T : struct - { - // @patched at compile time - throw new NotImplementedException("Patching this method failed"); - } + [ThreadSafe] + extern static int GetFieldOffsetInClass(FieldInfo field); - // minimum alignment of a struct - public static int AlignOf() where T : struct + public static int GetFieldOffset(FieldInfo field) { - throw new NotImplementedException("Patching this method failed"); + if (field.DeclaringType.IsValueType) + return GetFieldOffsetInStruct(field); + else if (field.DeclaringType.IsClass) + return GetFieldOffsetInClass(field); + else + { + return -1; + } } - internal static unsafe int OffsetOf(string name) where T : struct - { - return (int)System.Runtime.InteropServices.Marshal.OffsetOf(typeof(T), name); - } + [ThreadSafe] + unsafe public static extern void* PinGCObjectAndGetAddress(System.Object target, out ulong gcHandle); - internal static bool IsFieldOfType(string fieldName, Type expectedFieldType) where T : struct - { - return IsFieldOfType(typeof(T), fieldName, expectedFieldType); - } + [ThreadSafe] + unsafe public static extern void ReleaseGCObject(ulong gcHandle); - static extern bool IsFieldOfType(Type type, string fieldName, Type expectedFieldType); + [ThreadSafe] + unsafe public static extern void CopyObjectAddressToPtr(object target, void* dstPtr); public static unsafe bool IsBlittable() where T : struct { @@ -90,22 +49,25 @@ public static unsafe bool IsBlittable() where T : struct } [ThreadSafe] - public static extern IntPtr Malloc(ulong size, int alignment, Allocator allocator); + unsafe public static extern void* Malloc(long size, int alignment, Allocator allocator); + + [ThreadSafe] + unsafe public static extern void Free(void* memory, Allocator allocator); [ThreadSafe] - public static extern void Free(IntPtr memory, Allocator allocator); + unsafe public static extern void MemCpy(void* destination, void* source, long size); [ThreadSafe] - public static extern void MemCpy(IntPtr destination, IntPtr source, ulong size); + unsafe public static extern void MemCpyReplicate(void* destination, void* source, int size, int count); [ThreadSafe] - public static extern void MemCpyReplicate(IntPtr destination, IntPtr source, ulong size, int count); + unsafe public static extern void MemCpyStride(void* destination, int destinationStride, void* source, int sourceStride, int elementSize, int count); [ThreadSafe] - public static extern void MemMove(IntPtr destination, IntPtr source, ulong size); + unsafe public static extern void MemMove(void* destination, void* source, long size); [ThreadSafe] - public static extern void MemClear(IntPtr destination, ulong size); + unsafe public static extern void MemClear(void* destination, long size); [ThreadSafe] public static extern int SizeOf(Type type); @@ -116,12 +78,5 @@ public static unsafe bool IsBlittable() where T : struct // @TODO : This is probably not the ideal place to have this? [ThreadSafe] internal static extern void LogError(string msg, string filename, int linenumber); - - public static unsafe void SetFieldStruct(object target, FieldInfo field, ref T value) where T : struct - { - SetFieldStructInternal(target, field, AddressOf(ref value), Marshal.SizeOf(typeof(T))); - } - - private static extern void SetFieldStructInternal(object target, FieldInfo field, IntPtr value, int size); } } diff --git a/Runtime/Export/Unsafe/UnsafeUtilityPatched.cs b/Runtime/Export/Unsafe/UnsafeUtilityPatched.cs new file mode 100644 index 0000000000..42ac5d5570 --- /dev/null +++ b/Runtime/Export/Unsafe/UnsafeUtilityPatched.cs @@ -0,0 +1,73 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using UnityEngine.Bindings; +using System.Runtime.CompilerServices; + +namespace Unity.Collections.LowLevel.Unsafe +{ + public static partial class UnsafeUtility + { + // Copies sizeof(T) bytes from ptr to output + unsafe public static void CopyPtrToStructure(void* ptr, out T output) where T : struct + { + // @patched at compile time + throw new NotImplementedException("Patching this method failed"); + } + + // Copies sizeof(T) bytes from output to ptr + unsafe public static void CopyStructureToPtr(ref T input, void* ptr) where T : struct + { + // @patched at compile time + throw new NotImplementedException("Patching this method failed"); + } + + unsafe public static T ReadArrayElement(void* source, int index) + { + // @patched at compile time + throw new NotImplementedException("Patching this method failed"); + } + + unsafe public static T ReadArrayElementWithStride(void* source, int index, int stride) + { + // @patched at compile time + throw new NotImplementedException("Patching this method failed"); + } + + unsafe public static void WriteArrayElement(void* destination, int index, T value) + { + // @patched at compile time + throw new NotImplementedException("Patching this method failed"); + } + + unsafe public static void WriteArrayElementWithStride(void* destination, int index, int stride, T value) + { + // @patched at compile time + throw new NotImplementedException("Patching this method failed"); + } + + // The address of the memory where the struct resides in memory + unsafe public static void* AddressOf(ref T output) where T : struct + { + // @patched at compile time + throw new NotImplementedException("Patching this method failed"); + } + + // The size of a struct + public static int SizeOf() where T : struct + { + // @patched at compile time + throw new NotImplementedException("Patching this method failed"); + } + + // minimum alignment of a struct + public static int AlignOf() where T : struct + { + throw new NotImplementedException("Patching this method failed"); + } + } +} diff --git a/Runtime/Jobs/Managed/BatchQueries.cs b/Runtime/Jobs/Managed/BatchQueries.cs new file mode 100644 index 0000000000..d36ff9d1dd --- /dev/null +++ b/Runtime/Jobs/Managed/BatchQueries.cs @@ -0,0 +1,40 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.InteropServices; +using UnityEngine.Bindings; +using Unity.Collections; +using Unity.Jobs; + +namespace Unity.Jobs.LowLevel.Unsafe +{ + public struct BatchQueryJob where CommandT : struct + where ResultT : struct + { + public BatchQueryJob(NativeArray commands, NativeArray results) + { + this.commands = commands; + this.results = results; + } + + [ReadOnly] + internal NativeArray commands; + internal NativeArray results; + } + public struct BatchQueryJobStruct where T : struct + { + static internal IntPtr jobReflectionData; + + public static IntPtr Initialize() + { + if (jobReflectionData == IntPtr.Zero) + jobReflectionData = JobsUtility.CreateJobReflectionData(typeof(T), JobType.ParallelFor, System.IntPtr.Zero); + return jobReflectionData; + } + } +} diff --git a/Runtime/Jobs/Managed/IJob.cs b/Runtime/Jobs/Managed/IJob.cs index 7ec30341e3..6b207b91c8 100644 --- a/Runtime/Jobs/Managed/IJob.cs +++ b/Runtime/Jobs/Managed/IJob.cs @@ -8,6 +8,7 @@ namespace Unity.Jobs { + [JobProducerType(typeof(IJobExtensions.JobStruct < >))] public interface IJob { void Execute(); @@ -15,14 +16,14 @@ public interface IJob public static class IJobExtensions { - struct JobStruct where T : struct, IJob + internal struct JobStruct where T : struct, IJob { public static IntPtr jobReflectionData; public static IntPtr Initialize() { if (jobReflectionData == IntPtr.Zero) - jobReflectionData = JobsUtility.CreateJobReflectionData(typeof(T), (ExecuteJobFunction)Execute); + jobReflectionData = JobsUtility.CreateJobReflectionData(typeof(T), JobType.Single, (ExecuteJobFunction)Execute); return jobReflectionData; } @@ -33,13 +34,13 @@ public static void Execute(ref T data, IntPtr additionalPtr, IntPtr bufferRangeP } } - public static JobHandle Schedule(this T jobData, JobHandle dependsOn = new JobHandle()) where T : struct, IJob + unsafe public static JobHandle Schedule(this T jobData, JobHandle dependsOn = new JobHandle()) where T : struct, IJob { var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), JobStruct.Initialize(), dependsOn, ScheduleMode.Batched); return JobsUtility.Schedule(ref scheduleParams); } - public static void Run(this T jobData) where T : struct, IJob + unsafe public static void Run(this T jobData) where T : struct, IJob { var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), JobStruct.Initialize(), new JobHandle(), ScheduleMode.Run); JobsUtility.Schedule(ref scheduleParams); diff --git a/Runtime/Jobs/Managed/IJobParallelFor.cs b/Runtime/Jobs/Managed/IJobParallelFor.cs index 494bec619a..2fbdd56c5a 100644 --- a/Runtime/Jobs/Managed/IJobParallelFor.cs +++ b/Runtime/Jobs/Managed/IJobParallelFor.cs @@ -8,6 +8,7 @@ namespace Unity.Jobs { + [JobProducerType(typeof(IJobParallelForExtensions.ParallelForJobStruct < >))] public interface IJobParallelFor { void Execute(int index); @@ -15,14 +16,14 @@ public interface IJobParallelFor public static class IJobParallelForExtensions { - struct ParallelForJobStruct where T : struct, IJobParallelFor + internal struct ParallelForJobStruct where T : struct, IJobParallelFor { public static IntPtr jobReflectionData; public static IntPtr Initialize() { if (jobReflectionData == IntPtr.Zero) - jobReflectionData = JobsUtility.CreateJobReflectionData(typeof(T), (ExecuteJobFunction)Execute); + jobReflectionData = JobsUtility.CreateJobReflectionData(typeof(T), JobType.ParallelFor, (ExecuteJobFunction)Execute); return jobReflectionData; } @@ -44,13 +45,13 @@ public static unsafe void Execute(ref T jobData, IntPtr additionalPtr, IntPtr bu } } - public static JobHandle Schedule(this T jobData, int arrayLength, int innerloopBatchCount, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelFor + unsafe public static JobHandle Schedule(this T jobData, int arrayLength, int innerloopBatchCount, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelFor { var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), ParallelForJobStruct.Initialize(), dependsOn, ScheduleMode.Batched); return JobsUtility.ScheduleParallelFor(ref scheduleParams, arrayLength, innerloopBatchCount); } - public static void Run(this T jobData, int arrayLength) where T : struct, IJobParallelFor + unsafe public static void Run(this T jobData, int arrayLength) where T : struct, IJobParallelFor { var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), ParallelForJobStruct.Initialize(), new JobHandle(), ScheduleMode.Run); JobsUtility.ScheduleParallelFor(ref scheduleParams, arrayLength, arrayLength); diff --git a/Runtime/Jobs/Managed/IJobParallelForTransform.cs b/Runtime/Jobs/Managed/IJobParallelForTransform.cs index 8c4fcfd4c8..936b6012a9 100644 --- a/Runtime/Jobs/Managed/IJobParallelForTransform.cs +++ b/Runtime/Jobs/Managed/IJobParallelForTransform.cs @@ -11,6 +11,7 @@ //@TODO: Move this into Runtime/Transform folder with the test of Transform component namespace UnityEngine.Jobs { + [JobProducerType(typeof(IJobParallelForTransformExtensions.TransformParallelForLoopStruct < >))] public interface IJobParallelForTransform { void Execute(int index, TransformAccess transform); @@ -18,14 +19,14 @@ public interface IJobParallelForTransform public static class IJobParallelForTransformExtensions { - struct TransformParallelForLoopStruct where T : struct, IJobParallelForTransform + internal struct TransformParallelForLoopStruct where T : struct, IJobParallelForTransform { static public IntPtr jobReflectionData; public static IntPtr Initialize() { if (jobReflectionData == IntPtr.Zero) - jobReflectionData = JobsUtility.CreateJobReflectionData(typeof(T), (ExecuteJobFunction)Execute); + jobReflectionData = JobsUtility.CreateJobReflectionData(typeof(T), JobType.ParallelFor, (ExecuteJobFunction)Execute); return jobReflectionData; } @@ -33,7 +34,7 @@ public static IntPtr Initialize() public static unsafe void Execute(ref T jobData, System.IntPtr jobData2, System.IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex) { IntPtr transformAccessArray; - UnsafeUtility.CopyPtrToStructure(jobData2, out transformAccessArray); + UnsafeUtility.CopyPtrToStructure((void*)jobData2, out transformAccessArray); int* sortedToUserIndex = (int*)TransformAccessArray.GetSortedToUserIndex(transformAccessArray); TransformAccess* sortedTransformAccess = (TransformAccess*)TransformAccessArray.GetSortedTransformAccess(transformAccessArray); @@ -51,7 +52,7 @@ public static unsafe void Execute(ref T jobData, System.IntPtr jobData2, System. } } - static public JobHandle Schedule(this T jobData, TransformAccessArray transforms, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelForTransform + unsafe static public JobHandle Schedule(this T jobData, TransformAccessArray transforms, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelForTransform { var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), TransformParallelForLoopStruct.Initialize(), dependsOn, ScheduleMode.Batched); return JobsUtility.ScheduleParallelForTransform(ref scheduleParams, transforms.GetTransformAccessArrayForSchedule()); diff --git a/Runtime/Jobs/ScriptBindings/JobHandle.bindings.cs b/Runtime/Jobs/ScriptBindings/JobHandle.bindings.cs index 3335359dbe..6c956ce4cd 100644 --- a/Runtime/Jobs/ScriptBindings/JobHandle.bindings.cs +++ b/Runtime/Jobs/ScriptBindings/JobHandle.bindings.cs @@ -28,7 +28,7 @@ unsafe public static void CompleteAll(ref JobHandle job0, ref JobHandle job1) JobHandle* jobs = stackalloc JobHandle[2]; jobs[0] = job0; jobs[1] = job1; - ScheduleBatchedJobsAndCompleteAll((IntPtr)jobs, 2); + ScheduleBatchedJobsAndCompleteAll(jobs, 2); job0 = new JobHandle(); job1 = new JobHandle(); @@ -40,7 +40,7 @@ unsafe public static void CompleteAll(ref JobHandle job0, ref JobHandle job1, re jobs[0] = job0; jobs[1] = job1; jobs[2] = job2; - ScheduleBatchedJobsAndCompleteAll((IntPtr)jobs, 3); + ScheduleBatchedJobsAndCompleteAll(jobs, 3); job0 = new JobHandle(); job1 = new JobHandle(); @@ -68,7 +68,7 @@ public unsafe static void CompleteAll(NativeArray jobs) static extern bool ScheduleBatchedJobsAndIsCompleted(ref JobHandle job); [NativeMethod(IsFreeFunction = true)] - unsafe extern static void ScheduleBatchedJobsAndCompleteAll(IntPtr jobs, int count); + unsafe extern static void ScheduleBatchedJobsAndCompleteAll(void* jobs, int count); public static JobHandle CombineDependencies(JobHandle job0, JobHandle job1) @@ -81,7 +81,7 @@ public static JobHandle CombineDependencies(JobHandle job0, JobHandle job1, JobH return CombineDependenciesInternal3(ref job0, ref job1, ref job2); } - public static JobHandle CombineDependencies(NativeArray jobs) + unsafe public static JobHandle CombineDependencies(NativeArray jobs) { return CombineDependenciesInternalPtr(jobs.GetUnsafeReadOnlyPtr(), jobs.Length); } @@ -93,9 +93,21 @@ public static JobHandle CombineDependencies(NativeArray jobs) static extern JobHandle CombineDependenciesInternal3(ref JobHandle job0, ref JobHandle job1, ref JobHandle job2); [NativeMethod(IsFreeFunction = true)] - static extern JobHandle CombineDependenciesInternalPtr(IntPtr jobs, int count); + unsafe internal static extern JobHandle CombineDependenciesInternalPtr(void* jobs, int count); [NativeMethod(IsFreeFunction = true)] public static extern bool CheckFenceIsDependencyOrDidSyncFence(JobHandle jobHandle, JobHandle dependsOn); } } + +namespace Unity.Jobs.LowLevel.Unsafe +{ + public static class JobHandleUnsafeUtility + { + unsafe public static JobHandle CombineDependencies(JobHandle* jobs, int count) + { + return JobHandle.CombineDependenciesInternalPtr(jobs, count); + } + } +} + diff --git a/Runtime/Jobs/ScriptBindings/Jobs.bindings.cs b/Runtime/Jobs/ScriptBindings/Jobs.bindings.cs index 55f7d5f161..8f6574a7e1 100644 --- a/Runtime/Jobs/ScriptBindings/Jobs.bindings.cs +++ b/Runtime/Jobs/ScriptBindings/Jobs.bindings.cs @@ -9,6 +9,17 @@ namespace Unity.Jobs.LowLevel.Unsafe { + [AttributeUsage(AttributeTargets.Interface)] + public sealed class JobProducerTypeAttribute : Attribute + { + public Type ProducerType { get; } + + public JobProducerTypeAttribute(Type producerType) + { + ProducerType = producerType; + } + } + public unsafe struct JobRanges { public int batchSize; @@ -27,6 +38,12 @@ public enum ScheduleMode Batched = 1 } + public enum JobType + { + Single = 0, + ParallelFor = 1 + } + [NativeType(Header = "Runtime/Jobs/ScriptBindings/JobsBindings.h")] public static class JobsUtility { @@ -38,10 +55,10 @@ public struct JobScheduleParameters public IntPtr reflectionData; public IntPtr jobDataPtr; - public JobScheduleParameters(IntPtr i_jobData, IntPtr i_reflectionData, JobHandle i_dependency, ScheduleMode i_scheduleMode) + unsafe public JobScheduleParameters(void* i_jobData, IntPtr i_reflectionData, JobHandle i_dependency, ScheduleMode i_scheduleMode) { dependency = i_dependency; - jobDataPtr = i_jobData; + jobDataPtr = (IntPtr)i_jobData; reflectionData = i_reflectionData; scheduleMode = (int)i_scheduleMode; } @@ -67,27 +84,25 @@ public static unsafe void GetJobRange(ref JobRanges ranges, int jobIndex, out in public static extern JobHandle ScheduleParallelForTransform(ref JobScheduleParameters parameters, IntPtr transfromAccesssArray); [NativeMethod(IsThreadSafe = true, IsFreeFunction = true)] - public static extern void PatchBufferMinMaxRanges(IntPtr bufferRangePatchData, IntPtr jobdata, int startIndex, int rangeSize); + unsafe public static extern void PatchBufferMinMaxRanges(IntPtr bufferRangePatchData, void* jobdata, int startIndex, int rangeSize); [FreeFunction] - private static extern IntPtr CreateJobReflectionData(Type wrapperJobType, Type userJobType, object managedJobFunction0, object managedJobFunction1, object managedJobFunction2); + private static extern IntPtr CreateJobReflectionData(Type wrapperJobType, Type userJobType, JobType jobType, object managedJobFunction0, object managedJobFunction1, object managedJobFunction2); - public static IntPtr CreateJobReflectionData(Type type, object managedJobFunction0, object managedJobFunction1 = null, object managedJobFunction2 = null) + public static IntPtr CreateJobReflectionData(Type type, JobType jobType, object managedJobFunction0, object managedJobFunction1 = null, object managedJobFunction2 = null) { - return CreateJobReflectionData(type, type, managedJobFunction0, managedJobFunction1, managedJobFunction2); + return CreateJobReflectionData(type, type, jobType, managedJobFunction0, managedJobFunction1, managedJobFunction2); } - public static IntPtr CreateJobReflectionData(Type wrapperJobType, Type userJobType, object managedJobFunction0) + public static IntPtr CreateJobReflectionData(Type wrapperJobType, Type userJobType, JobType jobType, object managedJobFunction0) { - return CreateJobReflectionData(wrapperJobType, userJobType, managedJobFunction0, null, null); + return CreateJobReflectionData(wrapperJobType, userJobType, jobType, managedJobFunction0, null, null); } - [FreeFunction] - public static extern void SetJobDebuggerEnabled(bool value); - - [FreeFunction] - public static extern bool GetJobDebuggerEnabled(); + public static extern bool JobDebuggerEnabled {[FreeFunction] get; [FreeFunction] set; } + public static extern bool JobCompilerEnabled {[FreeFunction] get; [FreeFunction] set; } + //@TODO: @timj Should we decrease this??? public const int MaxJobThreadCount = 128; public const int CacheLineSize = 64; } diff --git a/Runtime/Transform/ScriptBindings/TransformAccessArray.bindings.cs b/Runtime/Transform/ScriptBindings/TransformAccessArray.bindings.cs index bd6a937640..5e2edb3e9f 100644 --- a/Runtime/Transform/ScriptBindings/TransformAccessArray.bindings.cs +++ b/Runtime/Transform/ScriptBindings/TransformAccessArray.bindings.cs @@ -89,7 +89,6 @@ public static void Allocate(int capacity, int desiredJobCount, out TransformAcce } - public bool IsCreated { get { return m_TransformArray != IntPtr.Zero; } diff --git a/artifacts/generated/bindings_old/common/Core/ComputeShaderBindings.gen.cs b/artifacts/generated/bindings_old/common/Core/ComputeShaderBindings.gen.cs index e78cc4a49e..17fc6eaf68 100644 --- a/artifacts/generated/bindings_old/common/Core/ComputeShaderBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Core/ComputeShaderBindings.gen.cs @@ -13,6 +13,8 @@ using System.Diagnostics; using System.Collections; using System.Collections.Generic; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; namespace UnityEngine { @@ -322,6 +324,14 @@ public void SetData(List data) + [System.Security.SecuritySafeCritical] + unsafe public void SetData(NativeArray data) where T : struct + { + InternalSetNativeData((IntPtr)data.GetUnsafeReadOnlyPtr(), 0, 0, data.Length, UnsafeUtility.SizeOf()); + } + + + [System.Security.SecuritySafeCritical] public void SetData(System.Array data, int managedBufferStartIndex, int computeBufferStartIndex, int count) { @@ -349,6 +359,22 @@ public void SetData(List data, int managedBufferStartIndex, int computeBuf } + + [System.Security.SecuritySafeCritical] + public unsafe void SetData(NativeArray data, int nativeBufferStartIndex, int computeBufferStartIndex, int count) where T : struct + { + if (nativeBufferStartIndex < 0 || computeBufferStartIndex < 0 || count < 0 || nativeBufferStartIndex + count > data.Length) + throw new ArgumentOutOfRangeException(String.Format("Bad indices/count arguments (nativeBufferStartIndex:{0} computeBufferStartIndex:{1} count:{2})", nativeBufferStartIndex, computeBufferStartIndex, count)); + + InternalSetNativeData((IntPtr)data.GetUnsafeReadOnlyPtr(), nativeBufferStartIndex, computeBufferStartIndex, count, UnsafeUtility.SizeOf()); + } + + + [System.Security.SecurityCritical] + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private void InternalSetNativeData (IntPtr data, int nativeBufferStartIndex, int computeBufferStartIndex, int count, int elemSize) ; + [System.Security.SecurityCritical] [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] diff --git a/artifacts/generated/bindings_old/common/Core/HandheldBindings.gen.cs b/artifacts/generated/bindings_old/common/Core/HandheldBindings.gen.cs index b3eb6c1464..0060094c79 100644 --- a/artifacts/generated/bindings_old/common/Core/HandheldBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Core/HandheldBindings.gen.cs @@ -335,6 +335,16 @@ public extern Status status get; } + public extern int characterLimit + { + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + get; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + set; + } + public extern bool canGetSelection { [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration diff --git a/artifacts/generated/bindings_old/common/Physics/DynamicsBindings.gen.cs b/artifacts/generated/bindings_old/common/Physics/DynamicsBindings.gen.cs index e282265e64..cb8f6e9035 100644 --- a/artifacts/generated/bindings_old/common/Physics/DynamicsBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Physics/DynamicsBindings.gen.cs @@ -1271,19 +1271,15 @@ public partial struct ContactPoint public Vector3 normal { get { return m_Normal; } } - public Collider thisCollider { get { return ColliderFromInstanceId(m_ThisColliderInstanceID); } } + public Collider thisCollider { get { return Object.FindObjectFromInstanceID(m_ThisColliderInstanceID) as Collider; } } - public Collider otherCollider { get { return ColliderFromInstanceId(m_OtherColliderInstanceID); } } + public Collider otherCollider { get { return Object.FindObjectFromInstanceID(m_OtherColliderInstanceID) as Collider; } } public float separation { get { return m_Separation; }} - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private static Collider ColliderFromInstanceId (int instanceID) ; - } [RequireComponent(typeof(Transform))] @@ -3056,7 +3052,7 @@ public partial struct RaycastHit private int m_FaceID; private float m_Distance; private Vector2 m_UV; - private Collider m_Collider; + private int m_Collider; private static void CalculateRaycastTexCoord (out Vector2 output, Collider col, Vector2 uv, Vector3 point, int face, int index) { @@ -3108,9 +3104,7 @@ public Vector2 lightmapCoord } - public Collider collider { get { return m_Collider; } } - - + public Collider collider { get { return Object.FindObjectFromInstanceID(m_Collider) as Collider; } } public Rigidbody rigidbody { get { return collider != null ? collider.attachedRigidbody : null; } } From f6dc11befde8b30d7cc3e14a641adef2d298efae Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 7 Feb 2018 23:26:06 +0000 Subject: [PATCH 05/17] Unity 2018.1.0b6 C# reference source code --- .../Mono/Annotation/SceneRenderModeWindow.cs | 20 ++- .../Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs | 6 +- Editor/Mono/EditorGUI.cs | 2 + Editor/Mono/EditorHandles/ArcHandle.cs | 84 +++++----- .../BoundsHandle/PrimitiveBoundsHandle.cs | 13 +- Editor/Mono/Inspector/CameraEditor.cs | 9 +- Editor/Mono/Inspector/HingeJoint2DEditor.cs | 10 +- Editor/Mono/Inspector/InspectorWindow.cs | 10 -- Editor/Mono/Inspector/LightEditor.cs | 38 +++-- .../PlayerSettingsEditor.cs | 4 +- .../Mono/Inspector/ShaderImporterInspector.cs | 3 + Editor/Mono/RetainedMode.cs | 4 +- Editor/Mono/SceneView/SceneView.cs | 22 ++- .../Scripting/Compilers/MonoCSharpCompiler.cs | 10 +- .../ScriptCompilation/AssemblyBuilder.cs | 2 +- .../ScriptCompilation/CompilationTask.cs | 49 +++++- .../ScriptCompilation/EditorBuildRules.cs | 83 +--------- .../ScriptCompilation/EditorCompilation.cs | 90 ++++++++--- .../EditorCompilationInterface.cs | 18 +++ .../ScriptCompilation/MonoLibraryHelpers.cs | 129 ++++++++++++++++ Editor/Mono/SettingsWindow/LightingEditor.cs | 39 +++-- .../Mono/UIElements/Controls/ObjectField.cs | 7 +- Editor/Mono/UIElements/Controls/PopupField.cs | 132 ++++++++++++++++ .../Public/ScriptBindings/AudioExtensions.cs | 8 - Modules/GraphViewEditor/EdgeControl.cs | 62 +++++--- Modules/GraphViewEditor/Elements/Node.cs | 8 + Modules/IMGUI/GUI.cs | 6 +- Modules/Tilemap/Managed/TileBase.cs | 5 + .../ScriptBindings/Tilemap.bindings.cs | 21 +++ .../Editor/Managed/TilemapRendererEditor.cs | 14 ++ .../UIElementsDebugger.cs | 12 +- .../Events/CustomEventData.bindings.cs | 63 ++++++++ .../UnityAnalytics/Events/CustomEventData.cs | 62 +++----- Modules/UnityAnalytics/UnityAnalytics.cs | 50 +++--- .../UnityAnalyticsHandler.bindings.cs | 79 ++++++++++ .../UnityConnect/RemoteSettings.bindings.cs | 9 ++ Projects/CSharp/UnityEditor.csproj | 6 + Projects/CSharp/UnityEngine.csproj | 12 +- README.md | 2 +- .../common/Core/RectTransformBindings.gen.cs | 6 +- .../common/Editor/EditorBindings.gen.cs | 3 + .../CustomEventDataBindings.gen.cs | 88 ----------- .../UnityAnalyticsHandlerBindings.gen.cs | 143 ------------------ 43 files changed, 881 insertions(+), 562 deletions(-) create mode 100644 Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs create mode 100644 Editor/Mono/UIElements/Controls/PopupField.cs create mode 100644 Modules/UnityAnalytics/Events/CustomEventData.bindings.cs create mode 100644 Modules/UnityAnalytics/UnityAnalyticsHandler.bindings.cs delete mode 100644 artifacts/generated/bindings_old/common/UnityAnalytics/CustomEventDataBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/UnityAnalytics/UnityAnalyticsHandlerBindings.gen.cs diff --git a/Editor/Mono/Annotation/SceneRenderModeWindow.cs b/Editor/Mono/Annotation/SceneRenderModeWindow.cs index c699040d53..e607138525 100644 --- a/Editor/Mono/Annotation/SceneRenderModeWindow.cs +++ b/Editor/Mono/Annotation/SceneRenderModeWindow.cs @@ -158,9 +158,23 @@ private float windowHeight { get { - int headers = Styles.sBuiltinCameraModes.Where(mode => m_SceneView.IsCameraDrawModeEnabled(mode)).Select(mode => mode.section).Distinct().Count() + - SceneView.userDefinedModes.Where(mode => m_SceneView.IsCameraDrawModeEnabled(mode)).Select(mode => mode.section).Distinct().Count(); - int modes = Styles.sBuiltinCameraModes.Count(mode => m_SceneView.IsCameraDrawModeEnabled(mode)) + SceneView.userDefinedModes.Count(mode => m_SceneView.IsCameraDrawModeEnabled(mode)); + int headers; + int modes; + + // TODO: This needs to be fixed and we need to find a way to dif. between disabled and unsupported + if (GraphicsSettings.renderPipelineAsset != null) + { + // When using SRP, we completely hide disabled builtin modes, including headers + headers = Styles.sBuiltinCameraModes.Where(mode => m_SceneView.IsCameraDrawModeEnabled(mode)).Select(mode => mode.section).Distinct().Count() + + SceneView.userDefinedModes.Where(mode => m_SceneView.IsCameraDrawModeEnabled(mode)).Select(mode => mode.section).Distinct().Count(); + modes = Styles.sBuiltinCameraModes.Count(mode => m_SceneView.IsCameraDrawModeEnabled(mode)) + SceneView.userDefinedModes.Count(mode => m_SceneView.IsCameraDrawModeEnabled(mode)); + } + else + { + headers = Styles.sBuiltinCameraModes.Select(mode => mode.section).Distinct().Count() + SceneView.userDefinedModes.Where(mode => m_SceneView.IsCameraDrawModeEnabled(mode)).Select(mode => mode.section).Distinct().Count(); + modes = Styles.sBuiltinCameraModes.Count() + SceneView.userDefinedModes.Count(mode => m_SceneView.IsCameraDrawModeEnabled(mode)); + } + int separators = headers - 2; return ((headers + modes) * EditorGUI.kSingleLineHeight) + (kSeparatorHeight * separators) + kShowLightmapResolutionHeight; } diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs index bcabe8fe2d..31903c2287 100644 --- a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs +++ b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs @@ -104,7 +104,7 @@ internal static string ApiCompatibilityLevelToDotNetProfileArgument(ApiCompatibi return "net20"; case ApiCompatibilityLevel.NET_4_6: - return "net45"; + return "unityjit"; case ApiCompatibilityLevel.NET_Standard_2_0: return "unityaot"; @@ -195,7 +195,7 @@ public void RunCompileAndLink() arguments.Add(string.Format("--map-file-parser=\"{0}\"", GetMapFileParserPath())); arguments.Add(string.Format("--generatedcppdir=\"{0}\"", Path.GetFullPath(GetCppOutputDirectoryInStagingArea()))); if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_4_6) - arguments.Add("--dotnetprofile=\"net45\""); + arguments.Add("--dotnetprofile=\"unityjit\""); if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_Standard_2_0) arguments.Add("--dotnetprofile=\"unityaot\""); Action setupStartInfo = il2CppNativeCodeBuilder.SetupStartInfo; @@ -287,7 +287,7 @@ private void ConvertPlayerDlltoCpp(ICollection userAssemblies, string ou var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(m_PlatformProvider.target); if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_4_6) - arguments.Add("--dotnetprofile=\"net45\""); + arguments.Add("--dotnetprofile=\"unityjit\""); if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_Standard_2_0) arguments.Add("--dotnetprofile=\"unityaot\""); diff --git a/Editor/Mono/EditorGUI.cs b/Editor/Mono/EditorGUI.cs index abdd782f79..dbc47ec627 100644 --- a/Editor/Mono/EditorGUI.cs +++ b/Editor/Mono/EditorGUI.cs @@ -8111,6 +8111,8 @@ internal static Rect GetToggleRect(bool hasLabel, params GUILayoutOption[] optio public class FadeGroupScope : GUI.Scope { + // when using the FadeGroupScope, make sure to only show the content when 'visible' is set to true, + // otherwise only the hide animation will run, and then the content will be visible again. public bool visible { get; protected set; } float m_Value; diff --git a/Editor/Mono/EditorHandles/ArcHandle.cs b/Editor/Mono/EditorHandles/ArcHandle.cs index dba721a067..19d083271a 100644 --- a/Editor/Mono/EditorHandles/ArcHandle.cs +++ b/Editor/Mono/EditorHandles/ArcHandle.cs @@ -2,7 +2,7 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License -using System; +using System.Collections.Generic; using UnityEngine; namespace UnityEditor.IMGUI.Controls @@ -14,27 +14,49 @@ public class ArcHandle static readonly float s_DefaultRadiusHandleSize = 0.03f; - static float DefaultAngleHandleSizeFunction(Vector3 position) + static readonly Dictionary s_MostRecentValidAngleHandleOrientations = + new Dictionary(); + + // only used inside of DefaultAngleHandleDrawFunction to look up and store the most recent valid orientation per handle + // done so that DefaultAngleHandleDrawFunction can be a static method, which makes angleHandleDrawFunction more usable by sub-classes + static int s_CurrentlyDrawingAngleHandleHash; + + public static void DefaultAngleHandleDrawFunction( + int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType + ) { - return HandleUtility.GetHandleSize(position) * s_DefaultAngleHandleSize; + Handles.DrawLine(Vector3.zero, position); + + // draw a cylindrical "hammer head" to indicate the direction the handle will move + Vector3 worldPosition = Handles.matrix.MultiplyPoint3x4(position); + Vector3 normal = worldPosition - Handles.matrix.MultiplyPoint3x4(Vector3.zero); + Vector3 tangent = Handles.matrix.MultiplyVector(Quaternion.AngleAxis(90f, Vector3.up) * position); + Quaternion mostRecentValidOrientation; + if (!s_MostRecentValidAngleHandleOrientations.TryGetValue(s_CurrentlyDrawingAngleHandleHash, out mostRecentValidOrientation)) + mostRecentValidOrientation = Quaternion.identity; + rotation = Mathf.Approximately(tangent.sqrMagnitude, 0f) ? + mostRecentValidOrientation : Quaternion.LookRotation(tangent, normal); + s_MostRecentValidAngleHandleOrientations[s_CurrentlyDrawingAngleHandleHash] = rotation; + Matrix4x4 matrix = + Matrix4x4.TRS(worldPosition, rotation, (Vector3.one + Vector3.forward * s_DefaultAngleHandleSizeRatio)); + using (new Handles.DrawingScope(matrix)) + Handles.CylinderHandleCap(controlID, Vector3.zero, Quaternion.identity, size, eventType); + s_CurrentlyDrawingAngleHandleHash = 0; } - static float DefaultRadiusHandleSizeFunction(Vector3 position) + public static float DefaultAngleHandleSizeFunction(Vector3 position) { - return HandleUtility.GetHandleSize(position) * s_DefaultRadiusHandleSize; + return HandleUtility.GetHandleSize(position) * s_DefaultAngleHandleSize; } - static void DefaultRadiusHandleDrawFunction( - int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType - ) + public static float DefaultRadiusHandleSizeFunction(Vector3 position) { - Handles.DotHandleCap(controlID, position, rotation, size, eventType); + return HandleUtility.GetHandleSize(position) * s_DefaultRadiusHandleSize; } private bool m_ControlIDsReserved = false; private int m_AngleHandleControlID; private int[] m_RadiusHandleControlIDs = new int[4]; - private Quaternion m_MostRecentValidAngleHandleOrientation = Quaternion.identity; public float angle { get; set; } @@ -60,6 +82,15 @@ public ArcHandle() { radius = 1f; SetColorWithoutRadiusHandle(Color.white, 0.1f); + angleHandleDrawFunction = DefaultAngleHandleDrawFunction; + angleHandleSizeFunction = DefaultAngleHandleSizeFunction; + radiusHandleDrawFunction = Handles.DotHandleCap; + radiusHandleSizeFunction = DefaultRadiusHandleSizeFunction; + } + + ~ArcHandle() + { + s_MostRecentValidAngleHandleOrientations.Remove(GetHashCode()); } public void SetColorWithoutRadiusHandle(Color color, float fillColorAlpha) @@ -147,15 +178,13 @@ public void DrawHandle() Vector3 newPosition; EditorGUI.BeginChangeCheck(); { - float size = radiusHandleSizeFunction == null ? - DefaultRadiusHandleSizeFunction(radiusHandlePosition) : - radiusHandleSizeFunction(radiusHandlePosition); + var size = radiusHandleSizeFunction == null ? 0f : radiusHandleSizeFunction(radiusHandlePosition); newPosition = Handles.Slider( m_RadiusHandleControlIDs[i], radiusHandlePosition, Vector3.forward, size, - radiusHandleDrawFunction ?? DefaultRadiusHandleDrawFunction, + radiusHandleDrawFunction, SnapSettings.move.z ); } @@ -171,13 +200,12 @@ public void DrawHandle() // draw angle handle last so it will always take precedence when overlapping a radius handle using (new Handles.DrawingScope(Handles.color * angleHandleColor)) { - if (Handles.color.a > 0f) + if (Handles.color.a > 0f && angleHandleDrawFunction != null) { EditorGUI.BeginChangeCheck(); { - float size = angleHandleSizeFunction == null ? - DefaultAngleHandleSizeFunction(angleHandlePosition) : - angleHandleSizeFunction(angleHandlePosition); + var size = angleHandleSizeFunction == null ? 0f : angleHandleSizeFunction(angleHandlePosition); + s_CurrentlyDrawingAngleHandleHash = GetHashCode(); angleHandlePosition = Handles.Slider2D( m_AngleHandleControlID, angleHandlePosition, @@ -185,7 +213,7 @@ public void DrawHandle() Vector3.forward, Vector3.right, size, - angleHandleDrawFunction ?? DefaultAngleHandleDrawFunction, + angleHandleDrawFunction, Vector2.zero ); } @@ -207,23 +235,5 @@ internal void GetControlIDs() m_RadiusHandleControlIDs[i] = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); m_ControlIDsReserved = true; } - - private void DefaultAngleHandleDrawFunction( - int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType - ) - { - Handles.DrawLine(Vector3.zero, position); - - // draw a cylindrical "hammer head" to indicate the direction the handle will move - Vector3 worldPosition = Handles.matrix.MultiplyPoint3x4(position); - Vector3 normal = worldPosition - Handles.matrix.MultiplyPoint3x4(Vector3.zero); - Vector3 tangent = Handles.matrix.MultiplyVector(Quaternion.AngleAxis(90f, Vector3.up) * position); - m_MostRecentValidAngleHandleOrientation = rotation = tangent.sqrMagnitude == 0f ? - m_MostRecentValidAngleHandleOrientation : Quaternion.LookRotation(tangent, normal); - Matrix4x4 matrix = - Matrix4x4.TRS(worldPosition, rotation, (Vector3.one + Vector3.forward * s_DefaultAngleHandleSizeRatio)); - using (new Handles.DrawingScope(matrix)) - Handles.CylinderHandleCap(controlID, Vector3.zero, Quaternion.identity, size, eventType); - } } } diff --git a/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs b/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs index 74d6e2d86d..8cdac7367a 100644 --- a/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs +++ b/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs @@ -48,7 +48,7 @@ internal static GUIContent editModeButton } private static GUIContent s_EditModeButton; - private static float DefaultMidpointHandleSizeFunction(Vector3 position) + public static float DefaultMidpointHandleSizeFunction(Vector3 position) { return HandleUtility.GetHandleSize(position) * s_DefaultMidpointHandleSize; } @@ -81,6 +81,8 @@ public PrimitiveBoundsHandle() handleColor = Color.white; wireframeColor = Color.white; axes = Axes.X | Axes.Y | Axes.Z; + midpointHandleDrawFunction = Handles.DotHandleCap; + midpointHandleSizeFunction = DefaultMidpointHandleSizeFunction; } public void SetColor(Color color) @@ -272,14 +274,15 @@ private Vector3 MidpointHandle(int id, Vector3 localPos, Vector3 localTangent, V AdjustMidpointHandleColor(localPos, localTangent, localBinormal, isCameraInsideBox); - if (Handles.color.a > 0f) + if (Handles.color.a > 0f && midpointHandleDrawFunction != null) { Vector3 localDir = Vector3.Cross(localTangent, localBinormal).normalized; - var drawFunc = midpointHandleDrawFunction ?? Handles.DotHandleCap; - var sizeFunc = midpointHandleSizeFunction ?? DefaultMidpointHandleSizeFunction; + var size = midpointHandleSizeFunction == null ? 0f : midpointHandleSizeFunction(localPos); - localPos = UnityEditorInternal.Slider1D.Do(id, localPos, localDir, sizeFunc(localPos), drawFunc, SnapSettings.scale); + localPos = UnityEditorInternal.Slider1D.Do( + id, localPos, localDir, size, midpointHandleDrawFunction, SnapSettings.scale + ); } Handles.color = oldColor; diff --git a/Editor/Mono/Inspector/CameraEditor.cs b/Editor/Mono/Inspector/CameraEditor.cs index 3097c2791c..3084ffe3d5 100644 --- a/Editor/Mono/Inspector/CameraEditor.cs +++ b/Editor/Mono/Inspector/CameraEditor.cs @@ -450,8 +450,10 @@ public override void OnInspectorGUI() settings.DrawClearFlags(); - using (new EditorGUILayout.FadeGroupScope(m_ShowBGColorOptions.faded)) + if (EditorGUILayout.BeginFadeGroup(m_ShowBGColorOptions.faded)) settings.DrawBackgroundColor(); + EditorGUILayout.EndFadeGroup(); + settings.DrawCullingMask(); EditorGUILayout.Space(); @@ -480,8 +482,9 @@ public override void OnInspectorGUI() settings.DrawVR(); settings.DrawMultiDisplay(); - using (new EditorGUILayout.FadeGroupScope(m_ShowTargetEyeOption.faded)) + if (EditorGUILayout.BeginFadeGroup(m_ShowTargetEyeOption.faded)) settings.DrawTargetEye(); + EditorGUILayout.EndFadeGroup(); DepthTextureModeGUI(); CommandBufferGUI(); @@ -563,7 +566,7 @@ public virtual void OnOverlayGUI(Object target, SceneView sceneView) } var previewTexture = GetPreviewTextureWithSize((int)cameraRect.width, (int)cameraRect.height); - previewTexture.antiAliasing = QualitySettings.antiAliasing; + previewTexture.antiAliasing = Mathf.Max(1, QualitySettings.antiAliasing); previewCamera.targetTexture = previewTexture; previewCamera.pixelRect = new Rect(0, 0, cameraRect.width, cameraRect.height); diff --git a/Editor/Mono/Inspector/HingeJoint2DEditor.cs b/Editor/Mono/Inspector/HingeJoint2DEditor.cs index cc62dda4bb..521cf41002 100644 --- a/Editor/Mono/Inspector/HingeJoint2DEditor.cs +++ b/Editor/Mono/Inspector/HingeJoint2DEditor.cs @@ -66,12 +66,6 @@ internal override Bounds GetWorldBoundsOfTarget(UnityObject targetObject) return bounds; } - private void NonEditableHandleDrawFunction( - int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType - ) - { - } - private static readonly Quaternion s_RightHandedHandleOrientationOffset = Quaternion.AngleAxis(180f, Vector3.right) * Quaternion.AngleAxis(90f, Vector3.up); private static readonly Quaternion s_LeftHandedHandleOrientationOffset = @@ -96,9 +90,9 @@ private void NonEditableHandleDrawFunction( // only display control handles on manipulator if in edit mode var editMode = EditMode.editMode == EditMode.SceneViewEditMode.JointAngularLimits && EditMode.IsOwner(this); if (editMode) - m_AngularLimitHandle.angleHandleDrawFunction = null; + m_AngularLimitHandle.angleHandleDrawFunction = ArcHandle.DefaultAngleHandleDrawFunction; else - m_AngularLimitHandle.angleHandleDrawFunction = NonEditableHandleDrawFunction; + m_AngularLimitHandle.angleHandleDrawFunction = null; // to enhance usability, orient the manipulator to best illustrate its affects on the dynamic body in the system var dynamicBody = hingeJoint2D.attachedRigidbody; diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index 9be9836305..347016f3e7 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -1003,16 +1003,6 @@ protected void AssignAssetEditor(Editor[] editors) if (editors.Length > 1 && editors[0] is AssetImporterEditor) { (editors[0] as AssetImporterEditor).assetEditor = editors[1]; - // if we have an asset editor but no target, it's likely the asset was just imported and we lost the target - // get the target back from the serialized object for all editors - // (dealing with multiple editors when a GameObject is involved) - for (int i = 0; i < editors.Length; i++) - { - if (editors[i].target == null) - { - editors[i].InternalSetTargets(editors[i].serializedObject.targetObjects); - } - } } } diff --git a/Editor/Mono/Inspector/LightEditor.cs b/Editor/Mono/Inspector/LightEditor.cs index cf2472c00a..6a858c23dd 100644 --- a/Editor/Mono/Inspector/LightEditor.cs +++ b/Editor/Mono/Inspector/LightEditor.cs @@ -523,37 +523,44 @@ public override void OnInspectorGUI() //bool keepRangeHidden = m_ShowDirOptions.isAnimating && m_ShowDirOptions.target; //float fadeRange = keepRangeHidden ? 0.0f : 1.0f - m_ShowDirOptions.faded; // Light Range - using (new EditorGUILayout.FadeGroupScope(1.0f - m_AnimShowDirOptions.faded)) + if (EditorGUILayout.BeginFadeGroup(1.0f - m_AnimShowDirOptions.faded)) settings.DrawRange(m_AnimShowAreaOptions.target); + EditorGUILayout.EndFadeGroup(); - using (new EditorGUILayout.FadeGroupScope(m_AnimShowSpotOptions.faded)) + if (EditorGUILayout.BeginFadeGroup(m_AnimShowSpotOptions.faded)) settings.DrawSpotAngle(); + EditorGUILayout.EndFadeGroup(); // Area width & height - using (new EditorGUILayout.FadeGroupScope(m_AnimShowAreaOptions.faded)) + if (EditorGUILayout.BeginFadeGroup(m_AnimShowAreaOptions.faded)) settings.DrawArea(); + EditorGUILayout.EndFadeGroup(); settings.DrawColor(); EditorGUILayout.Space(); // Baking type - using (new EditorGUILayout.FadeGroupScope(1.0F - m_AnimShowAreaOptions.faded)) + if (EditorGUILayout.BeginFadeGroup(1.0F - m_AnimShowAreaOptions.faded)) settings.DrawLightmapping(); + EditorGUILayout.EndFadeGroup(); settings.DrawIntensity(); - using (new EditorGUILayout.FadeGroupScope(m_AnimShowLightBounceIntensity.faded)) + if (EditorGUILayout.BeginFadeGroup(m_AnimShowLightBounceIntensity.faded)) settings.DrawBounceIntensity(); + EditorGUILayout.EndFadeGroup(); ShadowsGUI(); - using (new EditorGUILayout.FadeGroupScope(m_AnimShowRuntimeOptions.faded)) + if (EditorGUILayout.BeginFadeGroup(m_AnimShowRuntimeOptions.faded)) settings.DrawCookie(); + EditorGUILayout.EndFadeGroup(); // Cookie size also requires directional light - using (new EditorGUILayout.FadeGroupScope(m_AnimShowRuntimeOptions.faded * m_AnimShowDirOptions.faded)) + if (EditorGUILayout.BeginFadeGroup(m_AnimShowRuntimeOptions.faded * m_AnimShowDirOptions.faded)) settings.DrawCookieSize(); + EditorGUILayout.EndFadeGroup(); settings.DrawHalo(); settings.DrawFlare(); @@ -576,20 +583,29 @@ void ShadowsGUI() // Shadows drop-down. Area lights can only be baked and always have shadows. float show = 1 - m_AnimShowAreaOptions.faded; - using (new EditorGUILayout.FadeGroupScope(show)) + + if (EditorGUILayout.BeginFadeGroup(show)) settings.DrawShadowsType(); + EditorGUILayout.EndFadeGroup(); EditorGUI.indentLevel += 1; show *= m_AnimShowShadowOptions.faded; + // Baked Shadow radius - using (new EditorGUILayout.FadeGroupScope(show * m_AnimBakedShadowRadiusOptions.faded)) + if (EditorGUILayout.BeginFadeGroup(show * m_AnimBakedShadowRadiusOptions.faded)) settings.DrawBakedShadowRadius(); + EditorGUILayout.EndFadeGroup(); + // Baked Shadow angle - using (new EditorGUILayout.FadeGroupScope(show * m_AnimBakedShadowAngleOptions.faded)) + if (EditorGUILayout.BeginFadeGroup(show * m_AnimBakedShadowAngleOptions.faded)) settings.DrawBakedShadowAngle(); + EditorGUILayout.EndFadeGroup(); + // Runtime shadows - shadow strength, resolution, bias - using (new EditorGUILayout.FadeGroupScope(show * m_AnimShowRuntimeOptions.faded)) + if (EditorGUILayout.BeginFadeGroup(show * m_AnimShowRuntimeOptions.faded)) settings.DrawRuntimeShadow(); + EditorGUILayout.EndFadeGroup(); + EditorGUI.indentLevel -= 1; EditorGUILayout.Space(); diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 7e7183c096..8488684de9 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -149,7 +149,7 @@ static class Styles public static readonly GUIContent scriptingDefineSymbols = EditorGUIUtility.TrTextContent("Scripting Define Symbols*"); public static readonly GUIContent scriptingRuntimeVersion = EditorGUIUtility.TrTextContent("Scripting Runtime Version*", "The scripting runtime version to be used. Unity uses different scripting backends based on platform, so these options are listed as equivalent expected behavior."); public static readonly GUIContent scriptingRuntimeVersionLegacy = EditorGUIUtility.TrTextContent("Stable (.NET 3.5 Equivalent)"); - public static readonly GUIContent scriptingRuntimeVersionLatest = EditorGUIUtility.TrTextContent("Experimental (.NET 4.6 Equivalent)"); + public static readonly GUIContent scriptingRuntimeVersionLatest = EditorGUIUtility.TrTextContent("Experimental (.NET 4.x Equivalent)"); public static readonly GUIContent scriptingBackend = EditorGUIUtility.TrTextContent("Scripting Backend"); public static readonly GUIContent il2cppCompilerConfiguration = EditorGUIUtility.TrTextContent("C++ Compiler Configuration"); public static readonly GUIContent scriptingMono2x = EditorGUIUtility.TrTextContent("Mono"); @@ -159,7 +159,7 @@ static class Styles public static readonly GUIContent apiCompatibilityLevel = EditorGUIUtility.TrTextContent("Api Compatibility Level*"); public static readonly GUIContent apiCompatibilityLevel_NET_2_0 = EditorGUIUtility.TrTextContent(".NET 2.0"); public static readonly GUIContent apiCompatibilityLevel_NET_2_0_Subset = EditorGUIUtility.TrTextContent(".NET 2.0 Subset"); - public static readonly GUIContent apiCompatibilityLevel_NET_4_6 = EditorGUIUtility.TrTextContent(".NET 4.6"); + public static readonly GUIContent apiCompatibilityLevel_NET_4_6 = EditorGUIUtility.TrTextContent(".NET 4.x"); public static readonly GUIContent apiCompatibilityLevel_NET_Standard_2_0 = EditorGUIUtility.TrTextContent(".NET Standard 2.0"); public static readonly GUIContent activeInputHandling = EditorGUIUtility.TrTextContent("Active Input Handling*"); public static readonly GUIContent[] activeInputHandlingOptions = new GUIContent[] { EditorGUIUtility.TrTextContent("Input Manager"), EditorGUIUtility.TrTextContent("Input System (Preview)"), EditorGUIUtility.TrTextContent("Both") }; diff --git a/Editor/Mono/Inspector/ShaderImporterInspector.cs b/Editor/Mono/Inspector/ShaderImporterInspector.cs index 84c7f94616..f44e2e258b 100644 --- a/Editor/Mono/Inspector/ShaderImporterInspector.cs +++ b/Editor/Mono/Inspector/ShaderImporterInspector.cs @@ -224,6 +224,9 @@ internal static string[] GetShaderIncludePaths() results.AddRange(result); } } + // The paths appear in the list in random order. We sort the list here so that the same paths will always + // result into the exact same list. Otherwise the shader importer will think the paths have changed. + results.Sort(); s_ShaderIncludePaths = results.ToArray(); } return s_ShaderIncludePaths; diff --git a/Editor/Mono/RetainedMode.cs b/Editor/Mono/RetainedMode.cs index 449237bd1f..d9f33038b9 100644 --- a/Editor/Mono/RetainedMode.cs +++ b/Editor/Mono/RetainedMode.cs @@ -19,7 +19,7 @@ class RetainedMode : AssetPostprocessor internal static bool UxmlLiveReloadIsEnabled { - get { return EditorPrefs.GetBool(k_UielementsUxmllivereloadPrefsKey, true); } + get { return EditorPrefs.GetBool(k_UielementsUxmllivereloadPrefsKey, false); } set { EditorPrefs.SetBool(k_UielementsUxmllivereloadPrefsKey, value); } } @@ -113,7 +113,7 @@ static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAsse // Usually called by the USS importer, which might not get called here StyleSheetCache.ClearCaches(); - if (UxmlLiveReloadIsEnabled) + if (UxmlLiveReloadIsEnabled && Unsupported.IsDeveloperMode()) { // Delay the view reloading so we do not try to reload the view that // is currently active in the current callstack (i.e. ProjectView). diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs index cb7d182f64..93a1f6ce4c 100644 --- a/Editor/Mono/SceneView/SceneView.cs +++ b/Editor/Mono/SceneView/SceneView.cs @@ -235,7 +235,15 @@ public DrawCameraMode renderMode public CameraMode cameraMode { - get { return m_CameraMode; } + get + { + // fix for case 969889 where the toolbar is empty when we havent fully initialized the value + if (string.IsNullOrEmpty(m_CameraMode.name)) + { + m_CameraMode = SceneRenderModeWindow.GetBuiltinCameraMode(m_CameraMode.drawMode); + } + return m_CameraMode; + } set { m_CameraMode = value; @@ -1717,16 +1725,16 @@ internal void OnGUI() //Ensure that the target texture is clamped [0-1] //This is needed because otherwise gizmo rendering gets all //messed up (think HDR target with value of 50 + alpha blend gizmo... gonna be white!) - var ldrSceneTargetTexture = m_SceneTargetTexture; if (!UseSceneFiltering() && evt.type == EventType.Repaint && RenderTextureEditor.IsHDRFormat(m_SceneTargetTexture.format)) { var rtDesc = m_SceneTargetTexture.descriptor; rtDesc.colorFormat = RenderTextureFormat.ARGB32; rtDesc.depthBufferBits = 0; - rtDesc.sRGB = false; - ldrSceneTargetTexture = RenderTexture.GetTemporary(rtDesc); + RenderTexture ldrSceneTargetTexture = RenderTexture.GetTemporary(rtDesc); Graphics.Blit(m_SceneTargetTexture, ldrSceneTargetTexture); - Graphics.SetRenderTarget(ldrSceneTargetTexture.colorBuffer, m_SceneTargetTexture.depthBuffer); + Graphics.Blit(ldrSceneTargetTexture, m_SceneTargetTexture); + Graphics.SetRenderTarget(m_SceneTargetTexture.colorBuffer, m_SceneTargetTexture.depthBuffer); + RenderTexture.ReleaseTemporary(ldrSceneTargetTexture); } if (!UseSceneFiltering()) @@ -1771,9 +1779,7 @@ internal void OnGUI() GUIClip.Pop(); if (evt.type == EventType.Repaint) { - Graphics.DrawTexture(guiRect, ldrSceneTargetTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, EditorGUIUtility.GUITextureBlit2SRGBMaterial); - if (RenderTextureEditor.IsHDRFormat(m_SceneTargetTexture.format)) - RenderTexture.ReleaseTemporary(ldrSceneTargetTexture); + Graphics.DrawTexture(guiRect, m_SceneTargetTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, EditorGUIUtility.GUITextureBlit2SRGBMaterial); Profiler.EndSample(); } } diff --git a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs index 667324f61a..c858966c04 100644 --- a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs @@ -9,6 +9,7 @@ using UnityEngine; using UnityEditor.Utils; using System.Text; +using UnityEditor.Scripting.ScriptCompilation; namespace UnityEditor.Scripting.Compilers { @@ -59,13 +60,10 @@ private string GetCompilerPath(List arguments) var compilerPath = Path.Combine(dir, "mcs.exe"); if (File.Exists(compilerPath)) { - var profile = _island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0 ? "2.0-api" - : BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level); + var systemAssemblyDirectory = MonoLibraryHelpers.GetSystemReferenceDirectory(_island._api_compatibility_level); - if (_island._api_compatibility_level != ApiCompatibilityLevel.NET_Standard_2_0) - { - arguments.Add("-lib:" + PrepareFileName(MonoInstallationFinder.GetProfileDirectory(profile, MonoInstallationFinder.MonoBleedingEdgeInstallation))); - } + if (!string.IsNullOrEmpty(systemAssemblyDirectory) && Directory.Exists(systemAssemblyDirectory)) + arguments.Add("-lib:" + PrepareFileName(systemAssemblyDirectory)); return compilerPath; } diff --git a/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs b/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs index 76decfdd70..cf0b7ae8b8 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs @@ -72,7 +72,7 @@ internal bool Build(EditorCompilation editorCompilation) var scriptAssembly = editorCompilation.CreateScriptAssembly(this); compilationTask = new CompilationTask(new ScriptAssembly[] { scriptAssembly }, scriptAssembly.OutputDirectory, - EditorScriptCompilationOptions.BuildingEmpty, 1); + EditorScriptCompilationOptions.BuildingEmpty, CompilationTaskOptions.StopOnFirstError, 1); compilationTask.OnCompilationStarted += (assembly, phase) => { diff --git a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs index c8f2f1fa4b..8771de7d30 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs @@ -10,6 +10,13 @@ namespace UnityEditor.Scripting.ScriptCompilation { + [Flags] + enum CompilationTaskOptions + { + None = 0, + StopOnFirstError = (1 << 0) + } + // CompilationTask represents one complete rebuild of all the ScriptAssembly's that are passed in the constructor. // The ScriptAssembly's are built in correct order according to their ScriptAssembly dependencies. class CompilationTask @@ -20,6 +27,7 @@ class CompilationTask string buildOutputDirectory; int compilePhase = 0; EditorScriptCompilationOptions options; + CompilationTaskOptions compilationTaskOptions; int maxConcurrentCompilers; public event Action OnCompilationStarted; @@ -28,12 +36,13 @@ class CompilationTask public bool Stopped { get; private set; } public bool CompileErrors { get; private set; } - public CompilationTask(ScriptAssembly[] scriptAssemblies, string buildOutputDirectory, EditorScriptCompilationOptions options, int maxConcurrentCompilers) + public CompilationTask(ScriptAssembly[] scriptAssemblies, string buildOutputDirectory, EditorScriptCompilationOptions options, CompilationTaskOptions compilationTaskOptions, int maxConcurrentCompilers) { pendingAssemblies = new HashSet(scriptAssemblies); CompileErrors = false; this.buildOutputDirectory = buildOutputDirectory; this.options = options; + this.compilationTaskOptions = compilationTaskOptions; this.maxConcurrentCompilers = maxConcurrentCompilers; } @@ -120,8 +129,10 @@ public bool Poll() compiler.Dispose(); } - // Do not queue assemblies for compilation in case of compile errors. - if (CompileErrors) + // If StopOnFirstError is set, do not queue assemblies for compilation in case of compile errors. + bool stopOnFirstError = (compilationTaskOptions & CompilationTaskOptions.StopOnFirstError) == CompilationTaskOptions.StopOnFirstError; + + if (stopOnFirstError && CompileErrors) { // Set empty compiler messages for all pending assemblies. // Makes handling of messages easier in the editor. @@ -149,6 +160,7 @@ void QueuePendingAssemblies() return; List assemblyCompileQueue = null; + List removePendingAssemblies = null; // Find assemblies that have all their references already compiled. foreach (var pendingAssembly in pendingAssemblies) @@ -157,11 +169,27 @@ void QueuePendingAssemblies() foreach (var reference in pendingAssembly.ScriptAssemblyReferences) { - if (!processedAssemblies.ContainsKey(reference)) + CompilerMessage[] messages; + + if (!processedAssemblies.TryGetValue(reference, out messages)) { compileAssembly = false; break; } + + // If reference has compile errors, do not compile the pending assembly. + bool compileErrors = messages.Any(m => m.type == CompilerMessageType.Error); + + if (compileErrors) + { + if (removePendingAssemblies == null) + removePendingAssemblies = new List(); + + removePendingAssemblies.Add(pendingAssembly); + + compileAssembly = false; + break; + } } if (compileAssembly) @@ -173,10 +201,21 @@ void QueuePendingAssemblies() } } + if (removePendingAssemblies != null) + { + foreach (var assembly in removePendingAssemblies) + pendingAssemblies.Remove(assembly); + + // All pending assemblies were removed and no assemblies + // were queued for compilation. + if (assemblyCompileQueue == null) + return; + } + // No assemblies to compile, need to wait for more references to finish compiling. if (assemblyCompileQueue == null) { - Debug.Assert(compilerTasks.Count > 0, "No pending assemblies queued for compilation and no compilers running. Compilation will never finish."); + UnityEngine.Assertions.Assert.IsTrue(compilerTasks.Count > 0, "No pending assemblies queued for compilation and no compilers running. Compilation will never finish."); return; } diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs index 961de2583b..58e462867d 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs @@ -4,11 +4,8 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using UnityEditor.Compilation; using UnityEditor.Scripting.Compilers; -using UnityEditor.Utils; using File = System.IO.File; namespace UnityEditor.Scripting.ScriptCompilation @@ -211,7 +208,7 @@ public static TargetAssembly[] CreateTargetAssemblies(IEnumerable allSourceFiles, string projectDirectory, ScriptAssemblySettings settings, CompilationAssemblies assemblies) + public static ScriptAssembly[] GetAllScriptAssemblies(IEnumerable allSourceFiles, string projectDirectory, ScriptAssemblySettings settings, CompilationAssemblies assemblies, TargetAssemblyType onlyIncludeType = TargetAssemblyType.Undefined) { if (allSourceFiles == null || allSourceFiles.Count() == 0) return new ScriptAssembly[0]; @@ -225,6 +222,10 @@ public static ScriptAssembly[] GetAllScriptAssemblies(IEnumerable allSou if (!IsCompatibleWithPlatform(targetAssembly, settings)) continue; + // Optionally only include specific TargetAssemblyType assemblies. + if (onlyIncludeType != TargetAssemblyType.Undefined && targetAssembly.Type != onlyIncludeType) + continue; + var scriptExtension = ScriptCompilers.GetExtensionOfSourceFile(scriptFile); var scriptLanguage = ScriptCompilers.GetLanguageFromExtension(scriptExtension); @@ -512,84 +513,12 @@ internal static void AddScriptAssemblyReferences(ref ScriptAssembly scriptAssemb if (buildingForEditor && assemblies.EditorAssemblyReferences != null) references.AddRange(assemblies.EditorAssemblyReferences); - references.AddRange(GenerateAdditionalReferences(scriptAssembly.ApiCompatibilityLevel, scriptAssembly.BuildTarget, scriptAssembly.Language, buildingForEditor, scriptAssembly.Filename)); + references.AddRange(MonoLibraryHelpers.GetSystemLibraryReferences(scriptAssembly.ApiCompatibilityLevel, scriptAssembly.BuildTarget, scriptAssembly.Language, buildingForEditor, scriptAssembly.Filename)); scriptAssembly.ScriptAssemblyReferences = scriptAssemblyReferences.ToArray(); scriptAssembly.References = references.ToArray(); } - public static List GenerateAdditionalReferences(ApiCompatibilityLevel apiCompatibilityLevel, BuildTarget buildTarget, SupportedLanguage supportedLanguage, - bool buildingForEditor, string assemblyName) - { - var additionalReferences = new List(); - - if (WSAHelpers.BuildingForDotNet(buildTarget, buildingForEditor, assemblyName)) - return additionalReferences; - - // The language may not be compatible with these additional references - if (supportedLanguage != null && !supportedLanguage.CompilerRequiresAdditionalReferences()) - return additionalReferences; - - // For .NET 2.0 profile, the new mcs.exe references class libraries out of 2.0-api folder (even though we run against 2.0 at runtime) - var profile = apiCompatibilityLevel == ApiCompatibilityLevel.NET_2_0 - ? "2.0-api" - : BuildPipeline.CompatibilityProfileToClassLibFolder(apiCompatibilityLevel); - - var monoAssemblyDirectory = MonoInstallationFinder.GetProfileDirectory(profile, - MonoInstallationFinder.MonoBleedingEdgeInstallation); - - if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) - { - additionalReferences.AddRange(GetNetStandardClassLibraries()); - } - else - { - additionalReferences.AddRange(GetAdditionalReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); - - // Look in the mono assembly directory for a facade folder and get a list of all the DLL's to be - // used later by the language compilers. - if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) - { - var facadesDirectory = Path.Combine(monoAssemblyDirectory, "Facades"); - additionalReferences.AddRange(Directory.GetFiles(facadesDirectory, "*.dll")); - } - } - - return additionalReferences; - } - - internal static string[] GetNetStandardClassLibraries() - { - var classLibraries = new List(); - - // Add the .NET Standard 2.0 reference assembly - classLibraries.Add(Path.Combine(NetStandardFinder.GetReferenceDirectory(), "netstandard.dll")); - - // Add the .NET Standard 2.0 compat shims - classLibraries.AddRange(Directory.GetFiles(NetStandardFinder.GetNetStandardCompatShimsDirectory(), "*.dll")); - - // Add the .NET Framework compat shims - classLibraries.AddRange(Directory.GetFiles(NetStandardFinder.GetDotNetFrameworkCompatShimsDirectory(), "*.dll")); - - return classLibraries.ToArray(); - } - - internal static string[] GetAdditionalReferences() - { - return new[] - { - "mscorlib.dll", - "System.dll", - "System.Core.dll", - "System.Runtime.Serialization.dll", - "System.Xml.dll", - "System.Xml.Linq.dll", - "UnityScript.dll", - "UnityScript.Lang.dll", - "Boo.Lang.dll", - }; - } - public static List GetUnityReferences(ScriptAssembly scriptAssembly, PrecompiledAssembly[] unityAssemblies, EditorScriptCompilationOptions options) { var references = new List(); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index 8a4cecb62e..492a737480 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -6,10 +6,8 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; -using UnityEditor.Compilation; using UnityEditor.Modules; using UnityEditor.Scripting.Compilers; -using UnityEditor.Utils; using UnityEditorInternal; using CompilerMessage = UnityEditor.Scripting.Compilers.CompilerMessage; using CompilerMessageType = UnityEditor.Scripting.Compilers.CompilerMessageType; @@ -128,6 +126,20 @@ public string[] GetExtensionsSupportedByCompiler() return languages.Select(language => language.GetExtensionICanCompile()).ToArray(); } + public void DirtyPredefinedAssemblyScripts(EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) + { + var scriptAssemblySettings = CreateScriptAssemblySettings(platformGroup, platform, options); + var scriptAssemblies = GetAllScriptAssembliesOfType(scriptAssemblySettings, EditorBuildRules.TargetAssemblyType.Predefined); + + foreach (var assembly in scriptAssemblies) + { + foreach (var script in assembly.Files) + { + dirtyScripts.Add(script); + } + } + } + public void DirtyAllScripts() { areAllScriptsDirty = true; @@ -642,22 +654,6 @@ private static EditorBuildRules.TargetAssembly[] GetCustomAssembliesNotContainin internal bool CompileScripts(ScriptAssemblySettings scriptAssemblySettings, string tempBuildDirectory, EditorScriptCompilationOptions options, ref EditorBuildRules.TargetAssembly[] notCompiledTargetAssemblies) { - StopAllCompilation(); - - // Do no start compilation if there is an setup error. - if (setupErrorFlags != CompilationSetupErrorFlags.none) - return false; - - CheckCyclicAssemblyReferences(); - - DeleteUnusedAssemblies(); - - if (!Directory.Exists(scriptAssemblySettings.OutputDirectory)) - Directory.CreateDirectory(scriptAssemblySettings.OutputDirectory); - - if (!Directory.Exists(tempBuildDirectory)) - Directory.CreateDirectory(tempBuildDirectory); - IEnumerable allDirtyScripts = areAllScriptsDirty ? allScripts.ToArray() : dirtyScripts.ToArray(); areAllScriptsDirty = false; @@ -692,9 +688,41 @@ internal bool CompileScripts(ScriptAssemblySettings scriptAssemblySettings, stri if (!scriptAssemblies.Any()) return false; - // Compile to tempBuildDirectory - compilationTask = new CompilationTask(scriptAssemblies, tempBuildDirectory, options, UnityEngine.SystemInfo.processorCount); + return CompileScriptAssemblies(scriptAssemblies, scriptAssemblySettings, tempBuildDirectory, options, CompilationTaskOptions.StopOnFirstError); + } + + internal bool CompileCustomScriptAssemblies(EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) + { + var scriptAssemblySettings = CreateScriptAssemblySettings(platformGroup, platform, options); + return CompileCustomScriptAssemblies(scriptAssemblySettings, EditorTempPath, options, platformGroup, platform); + } + internal bool CompileCustomScriptAssemblies(ScriptAssemblySettings scriptAssemblySettings, string tempBuildDirectory, EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) + { + var scriptAssemblies = GetAllScriptAssembliesOfType(scriptAssemblySettings, EditorBuildRules.TargetAssemblyType.Custom); + return CompileScriptAssemblies(scriptAssemblies, scriptAssemblySettings, tempBuildDirectory, options, CompilationTaskOptions.None); + } + + internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, ScriptAssemblySettings scriptAssemblySettings, string tempBuildDirectory, EditorScriptCompilationOptions options, CompilationTaskOptions compilationTaskOptions) + { + StopAllCompilation(); + + // Do no start compilation if there is an setup error. + if (setupErrorFlags != CompilationSetupErrorFlags.none) + return false; + + CheckCyclicAssemblyReferences(); + + DeleteUnusedAssemblies(); + + if (!Directory.Exists(scriptAssemblySettings.OutputDirectory)) + Directory.CreateDirectory(scriptAssemblySettings.OutputDirectory); + + if (!Directory.Exists(tempBuildDirectory)) + Directory.CreateDirectory(tempBuildDirectory); + + // Compile to tempBuildDirectory + compilationTask = new CompilationTask(scriptAssemblies, tempBuildDirectory, options, compilationTaskOptions, UnityEngine.SystemInfo.processorCount); compilationTask.OnCompilationStarted += (assembly, phase) => { @@ -905,6 +933,11 @@ public CompileStatus TickCompilationPipeline(EditorScriptCompilationOptions opti return CompileStatus.CompilationStarted; } + return PollCompilation(); + } + + public CompileStatus PollCompilation() + { if (IsCompilationTaskCompiling()) { if (compilationTask.Poll()) // Returns true when compilation finished. @@ -912,6 +945,7 @@ public CompileStatus TickCompilationPipeline(EditorScriptCompilationOptions opti return CompileStatus.Compiling; } + return CompileStatus.Idle; } @@ -1006,6 +1040,20 @@ ScriptAssembly[] GetAllScriptAssemblies(EditorScriptCompilationOptions options, return EditorBuildRules.GetAllScriptAssemblies(allScripts, projectDirectory, settings, assemblies); } + ScriptAssembly[] GetAllScriptAssembliesOfType(ScriptAssemblySettings settings, EditorBuildRules.TargetAssemblyType type) + { + var assemblies = new EditorBuildRules.CompilationAssemblies + { + UnityAssemblies = unityAssemblies, + PrecompiledAssemblies = precompiledAssemblies, + CustomTargetAssemblies = customTargetAssemblies, + PredefinedAssembliesCustomTargetReferences = GetCustomAssembliesNotContainingTests(customTargetAssemblies), + EditorAssemblyReferences = ModuleUtils.GetAdditionalReferencesForUserScripts() + }; + + return EditorBuildRules.GetAllScriptAssemblies(allScripts, projectDirectory, settings, assemblies, type); + } + public MonoIsland[] GetAllMonoIslands() { return GetAllMonoIslands(unityAssemblies, precompiledAssemblies, EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies); @@ -1088,7 +1136,7 @@ public ScriptAssembly CreateScriptAssembly(Compilation.AssemblyBuilder assemblyB var unityReferences = EditorBuildRules.GetUnityReferences(scriptAssembly, unityAssemblies, options); var customReferences = EditorBuildRules.GetCompiledCustomAssembliesReferences(scriptAssembly, customTargetAssemblies, GetCompileScriptsOutputDirectory(), assemblySuffix); var precompiledReferences = EditorBuildRules.GetPrecompiledReferences(scriptAssembly, EditorBuildRules.TargetAssemblyType.Custom, options, EditorBuildRules.EditorCompatibility.CompatibleWithEditor, precompiledAssemblies); - var additionalReferences = EditorBuildRules.GenerateAdditionalReferences(scriptAssembly.ApiCompatibilityLevel, scriptAssembly.BuildTarget, scriptAssembly.Language, buildingForEditor, scriptAssembly.Filename); + var additionalReferences = MonoLibraryHelpers.GetSystemLibraryReferences(scriptAssembly.ApiCompatibilityLevel, scriptAssembly.BuildTarget, scriptAssembly.Language, buildingForEditor, scriptAssembly.Filename); string[] editorReferences = buildingForEditor ? ModuleUtils.GetAdditionalReferencesForUserScripts() : new string[0]; var references = unityReferences.Concat(customReferences).Concat(precompiledReferences).Concat(editorReferences).Concat(additionalReferences); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs index 66288d6603..352158a9cf 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs @@ -109,6 +109,12 @@ public static string[] GetExtensionsSupportedByCompiler() return Instance.GetExtensionsSupportedByCompiler(); } + [RequiredByNativeCode] + public static void DirtyPredefinedAssemblyScripts(EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) + { + EmitExceptionAsError(() => Instance.DirtyPredefinedAssemblyScripts(options, platformGroup, platform)); + } + [RequiredByNativeCode] public static void DirtyAllScripts() { @@ -187,6 +193,12 @@ public static bool CompileScripts(EditorScriptCompilationOptions definesOptions, return EmitExceptionAsError(() => Instance.CompileScripts(definesOptions, platformGroup, platform), false); } + [RequiredByNativeCode] + public static bool CompileCustomScriptAssemblies(EditorScriptCompilationOptions definesOptions, BuildTargetGroup platformGroup, BuildTarget platform) + { + return EmitExceptionAsError(() => Instance.CompileCustomScriptAssemblies(definesOptions, platformGroup, platform), false); + } + [RequiredByNativeCode] public static bool DoesProjectFolderHaveAnyDirtyScripts() { @@ -229,6 +241,12 @@ public static EditorCompilation.CompileStatus TickCompilationPipeline(EditorScri return EmitExceptionAsError(() => Instance.TickCompilationPipeline(options, platformGroup, platform), EditorCompilation.CompileStatus.Idle); } + [RequiredByNativeCode] + public static EditorCompilation.CompileStatus PollCompilation() + { + return EmitExceptionAsError(() => Instance.PollCompilation(), EditorCompilation.CompileStatus.Idle); + } + [RequiredByNativeCode] public static EditorCompilation.TargetAssemblyInfo[] GetTargetAssemblies() { diff --git a/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs b/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs new file mode 100644 index 0000000000..5613714390 --- /dev/null +++ b/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs @@ -0,0 +1,129 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor.Scripting.Compilers; +using UnityEditor.Utils; + +namespace UnityEditor.Scripting.ScriptCompilation +{ + static class MonoLibraryHelpers + { + class CachedReferences + { + public ApiCompatibilityLevel ApiCompatibilityLevel; + public string[] References; + } + + static CachedReferences cachedReferences; + + public static string[] GetSystemLibraryReferences(ApiCompatibilityLevel apiCompatibilityLevel, BuildTarget buildTarget, SupportedLanguage supportedLanguage, + bool buildingForEditor, string assemblyName) + { + if (WSAHelpers.BuildingForDotNet(buildTarget, buildingForEditor, assemblyName)) + return new string[0]; + + // The language may not be compatible with these additional references + if (supportedLanguage != null && !supportedLanguage.CompilerRequiresAdditionalReferences()) + return new string[0]; + + return GetCachedSystemLibraryReferences(apiCompatibilityLevel); + } + + static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompatibilityLevel) + { + // We cache the references because they are computed by getting files in directories on disk, + // which is very slow. + if (cachedReferences != null && cachedReferences.ApiCompatibilityLevel == apiCompatibilityLevel) + { + return cachedReferences.References; + } + + var references = new List(); + var monoAssemblyDirectory = GetSystemReferenceDirectory(apiCompatibilityLevel); + + if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) + { + references.AddRange(GetNetStandardClassLibraries()); + } + else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) + { + references.AddRange(GetSystemReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); + + // Look in the mono assembly directory for a facade folder and get a list of all the DLL's to be + // used later by the language compilers. + references.AddRange(Directory.GetFiles(Path.Combine(monoAssemblyDirectory, "Facades"), "*.dll")); + + references.AddRange(GetBooAndUsReferences().Select(dll => Path.Combine(MonoInstallationFinder.GetProfileDirectory("unityscript", MonoInstallationFinder.MonoBleedingEdgeInstallation), dll))); + } + else + { + references.AddRange(GetSystemReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); + references.AddRange(GetBooAndUsReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); + } + + cachedReferences = new CachedReferences + { + ApiCompatibilityLevel = apiCompatibilityLevel, + References = references.ToArray() + }; + + + return cachedReferences.References; + } + + public static string GetSystemReferenceDirectory(ApiCompatibilityLevel apiCompatibilityLevel) + { + if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) + return ""; + else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) + return MonoInstallationFinder.GetProfileDirectory("4.7.1-api", MonoInstallationFinder.MonoBleedingEdgeInstallation); + else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_2_0) + return MonoInstallationFinder.GetProfileDirectory("2.0-api", MonoInstallationFinder.MonoBleedingEdgeInstallation); + + return MonoInstallationFinder.GetProfileDirectory(BuildPipeline.CompatibilityProfileToClassLibFolder(apiCompatibilityLevel), MonoInstallationFinder.MonoBleedingEdgeInstallation); + } + + static string[] GetNetStandardClassLibraries() + { + var classLibraries = new List(); + + // Add the .NET Standard 2.0 reference assembly + classLibraries.Add(Path.Combine(NetStandardFinder.GetReferenceDirectory(), "netstandard.dll")); + + // Add the .NET Standard 2.0 compat shims + classLibraries.AddRange(Directory.GetFiles(NetStandardFinder.GetNetStandardCompatShimsDirectory(), "*.dll")); + + // Add the .NET Framework compat shims + classLibraries.AddRange(Directory.GetFiles(NetStandardFinder.GetDotNetFrameworkCompatShimsDirectory(), "*.dll")); + + return classLibraries.ToArray(); + } + + static string[] GetSystemReferences() + { + return new[] + { + "mscorlib.dll", + "System.dll", + "System.Core.dll", + "System.Runtime.Serialization.dll", + "System.Xml.dll", + "System.Xml.Linq.dll", + }; + } + + static string[] GetBooAndUsReferences() + { + return new[] + { + "UnityScript.dll", + "UnityScript.Lang.dll", + "Boo.Lang.dll", + }; + } + } +} diff --git a/Editor/Mono/SettingsWindow/LightingEditor.cs b/Editor/Mono/SettingsWindow/LightingEditor.cs index def0b0e565..3155a3958a 100644 --- a/Editor/Mono/SettingsWindow/LightingEditor.cs +++ b/Editor/Mono/SettingsWindow/LightingEditor.cs @@ -17,7 +17,6 @@ internal enum DefaultReflectionMode Custom } - [CustomEditor(typeof(RenderSettings))] internal class LightingEditor : Editor { internal static class Styles @@ -81,25 +80,27 @@ static Styles() {} protected SerializedProperty m_CustomReflection; protected SerializedProperty m_ReflectionCompression; + protected SerializedObject m_RenderSettings; protected SerializedObject m_LightmapSettings; private bool m_bShowEnvironment; private const string kShowEnvironment = "ShowEnvironment"; - public virtual void OnEnable() + private void InitSettings() { - m_Sun = serializedObject.FindProperty("m_Sun"); - m_AmbientSource = serializedObject.FindProperty("m_AmbientMode"); - m_AmbientSkyColor = serializedObject.FindProperty("m_AmbientSkyColor"); - m_AmbientEquatorColor = serializedObject.FindProperty("m_AmbientEquatorColor"); - m_AmbientGroundColor = serializedObject.FindProperty("m_AmbientGroundColor"); - m_AmbientIntensity = serializedObject.FindProperty("m_AmbientIntensity"); - m_ReflectionIntensity = serializedObject.FindProperty("m_ReflectionIntensity"); - m_ReflectionBounces = serializedObject.FindProperty("m_ReflectionBounces"); - m_SkyboxMaterial = serializedObject.FindProperty("m_SkyboxMaterial"); - m_DefaultReflectionMode = serializedObject.FindProperty("m_DefaultReflectionMode"); - m_DefaultReflectionResolution = serializedObject.FindProperty("m_DefaultReflectionResolution"); - m_CustomReflection = serializedObject.FindProperty("m_CustomReflection"); + m_RenderSettings = new SerializedObject(RenderSettings.GetRenderSettings()); + m_Sun = m_RenderSettings.FindProperty("m_Sun"); + m_AmbientSource = m_RenderSettings.FindProperty("m_AmbientMode"); + m_AmbientSkyColor = m_RenderSettings.FindProperty("m_AmbientSkyColor"); + m_AmbientEquatorColor = m_RenderSettings.FindProperty("m_AmbientEquatorColor"); + m_AmbientGroundColor = m_RenderSettings.FindProperty("m_AmbientGroundColor"); + m_AmbientIntensity = m_RenderSettings.FindProperty("m_AmbientIntensity"); + m_ReflectionIntensity = m_RenderSettings.FindProperty("m_ReflectionIntensity"); + m_ReflectionBounces = m_RenderSettings.FindProperty("m_ReflectionBounces"); + m_SkyboxMaterial = m_RenderSettings.FindProperty("m_SkyboxMaterial"); + m_DefaultReflectionMode = m_RenderSettings.FindProperty("m_DefaultReflectionMode"); + m_DefaultReflectionResolution = m_RenderSettings.FindProperty("m_DefaultReflectionResolution"); + m_CustomReflection = m_RenderSettings.FindProperty("m_CustomReflection"); m_LightmapSettings = new SerializedObject(LightmapEditorSettings.GetLightmapSettings()); m_ReflectionCompression = m_LightmapSettings.FindProperty("m_LightmapEditorSettings.m_ReflectionCompression"); @@ -110,6 +111,11 @@ public virtual void OnEnable() m_bShowEnvironment = SessionState.GetBool(kShowEnvironment, true); } + public virtual void OnEnable() + { + InitSettings(); + } + public virtual void OnDisable() { SessionState.SetBool(kShowEnvironment, m_bShowEnvironment); @@ -117,6 +123,11 @@ public virtual void OnDisable() private void DrawGUI() { + if (m_RenderSettings == null || m_RenderSettings.targetObject != RenderSettings.GetRenderSettings()) + { + InitSettings(); + } + Material skyboxMaterial = m_SkyboxMaterial.objectReferenceValue as Material; m_bShowEnvironment = EditorGUILayout.FoldoutTitlebar(m_bShowEnvironment, Styles.env_top, true); diff --git a/Editor/Mono/UIElements/Controls/ObjectField.cs b/Editor/Mono/UIElements/Controls/ObjectField.cs index 6d7f587b4e..3e1479491c 100644 --- a/Editor/Mono/UIElements/Controls/ObjectField.cs +++ b/Editor/Mono/UIElements/Controls/ObjectField.cs @@ -70,9 +70,9 @@ public void Update() m_ObjectLabel.text = content.text; } - protected internal override void ExecuteDefaultAction(EventBase evt) + protected internal override void ExecuteDefaultActionAtTarget(EventBase evt) { - base.ExecuteDefaultAction(evt); + base.ExecuteDefaultActionAtTarget(evt); if (evt.GetEventTypeId() == MouseDownEvent.TypeId()) OnMouseDown(); @@ -133,6 +133,9 @@ private void OnIMGUI(EventBase evt) m_ObjectField.SetValueAndNotify(validatedObject); DragAndDrop.AcceptDrag(); + + evt.StopPropagation(); + RemoveFromClassList("acceptDrop"); } else diff --git a/Editor/Mono/UIElements/Controls/PopupField.cs b/Editor/Mono/UIElements/Controls/PopupField.cs new file mode 100644 index 0000000000..31b8266d99 --- /dev/null +++ b/Editor/Mono/UIElements/Controls/PopupField.cs @@ -0,0 +1,132 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Experimental.UIElements; + +namespace UnityEditor.Experimental.UIElements +{ + public class PopupField : BaseTextElement, INotifyValueChanged + { + private readonly List m_PossibleValues; + + private T m_Value; + public T value + { + get { return m_Value; } + set + { + if (EqualityComparer.Default.Equals(m_Value, value)) + return; + + if (!m_PossibleValues.Contains(value)) + throw new ArgumentException(string.Format("Value {0} is not present in the list of possible values", value)); + + m_Value = value; + m_Index = m_PossibleValues.IndexOf(m_Value); + text = m_Value.ToString(); + Dirty(ChangeType.Repaint); + } + } + + private int m_Index = -1; + public int index + { + get { return m_Index; } + set + { + if (value != m_Index) + { + if (value >= m_PossibleValues.Count || value < 0) + throw new ArgumentException(string.Format("Index {0} is beyond the scope of possible value", value)); + m_Index = value; + this.value = m_PossibleValues[m_Index]; + } + } + } + + private PopupField(List possibleValues) + { + if (possibleValues == null) + throw new ArgumentNullException("possibleValues can't be null"); + + m_PossibleValues = possibleValues; + + AddToClassList("popupField"); + } + + public PopupField(List possibleValues, T defaultValue) : + this(possibleValues) + { + if (defaultValue == null) + throw new ArgumentNullException("defaultValue can't be null"); + + if (!m_PossibleValues.Contains(defaultValue)) + throw new ArgumentException(string.Format("Default value {0} is not present in the list of possible values", defaultValue)); + + // note: idx will be set when setting value + value = defaultValue; + } + + public PopupField(List possibleValues, int defaultIndex) : + this(possibleValues) + { + if (defaultIndex >= m_PossibleValues.Count || defaultIndex < 0) + throw new ArgumentException(string.Format("Default Index {0} is beyond the scope of possible value", value)); + + // note: value will be set when setting idx + index = defaultIndex; + } + + public void SetValueAndNotify(T newValue) + { + if (!EqualityComparer.Default.Equals(newValue, value)) + { + using (ChangeEvent evt = ChangeEvent.GetPooled(value, newValue)) + { + evt.target = this; + value = newValue; + UIElementsUtility.eventDispatcher.DispatchEvent(evt, panel); + } + } + } + + public void OnValueChanged(EventCallback> callback) + { + RegisterCallback(callback); + } + + protected internal override void ExecuteDefaultAction(EventBase evt) + { + base.ExecuteDefaultAction(evt); + + if (evt.GetEventTypeId() == MouseDownEvent.TypeId()) + OnMouseDown(); + } + + private void OnMouseDown() + { + var menu = new GenericMenu(); + + foreach (T item in m_PossibleValues) + { + bool isSelected = EqualityComparer.Default.Equals(item, value); + menu.AddItem(new GUIContent(item.ToString()), isSelected, + () => ChangeValueFromMenu(item)); + } + + var menuPosition = new Vector2(0.0f, layout.height); + menuPosition = this.LocalToWorld(menuPosition); + var menuRect = new Rect(menuPosition, Vector2.zero); + menu.DropDown(menuRect); + } + + private void ChangeValueFromMenu(T menuItem) + { + SetValueAndNotify(menuItem); + } + } +} diff --git a/Modules/Audio/Public/ScriptBindings/AudioExtensions.cs b/Modules/Audio/Public/ScriptBindings/AudioExtensions.cs index d667273e8b..d84fd2c54a 100644 --- a/Modules/Audio/Public/ScriptBindings/AudioExtensions.cs +++ b/Modules/Audio/Public/ScriptBindings/AudioExtensions.cs @@ -410,14 +410,6 @@ static internal void Update() { RegisterBuiltinDefinitions(); - if (m_SpatializerName != AudioSettings.GetSpatializerPluginName()) - { - m_SpatializerName = AudioSettings.GetSpatializerPluginName(); - if (GetSourceSpatializerExtensionType() != null) - m_SpatializerExtensionName = GetSourceSpatializerExtensionType().Name; - if (GetListenerSpatializerExtensionEditorType() != null) - m_ListenerSpatializerExtensionName = GetListenerSpatializerExtensionType().Name; - } AudioListener listener = GetAudioListener() as AudioListener; if (listener != null) diff --git a/Modules/GraphViewEditor/EdgeControl.cs b/Modules/GraphViewEditor/EdgeControl.cs index 25a6d01c31..ed7809cbb9 100644 --- a/Modules/GraphViewEditor/EdgeControl.cs +++ b/Modules/GraphViewEditor/EdgeControl.cs @@ -334,6 +334,26 @@ public virtual void UpdateLayout() m_ControlPointsDirty = false; } + void RenderStraightLines(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4) + { + float safeSpan = orientation == Orientation.Horizontal + ? Mathf.Abs((p1.x + k_EdgeLengthFromPort) - (p4.x - k_EdgeLengthFromPort)) + : Mathf.Abs((p1.y + k_EdgeLengthFromPort) - (p4.y - k_EdgeLengthFromPort)); + + float safeSpan3 = safeSpan / k_EdgeStraightLineSegmentDivisor; + float nodeToP2Dist = Mathf.Min(safeSpan3, k_EdgeTurnDiameter); + nodeToP2Dist = Mathf.Max(0, nodeToP2Dist); + + var offset = orientation == Orientation.Horizontal + ? new Vector2(k_EdgeTurnDiameter - nodeToP2Dist, 0) + : new Vector2(0, k_EdgeTurnDiameter - nodeToP2Dist); + + m_RenderPoints.Add(p1); + m_RenderPoints.Add(p2 - offset); + m_RenderPoints.Add(p3 + offset); + m_RenderPoints.Add(p4); + } + protected virtual void UpdateRenderPoints() { ComputeControlPoints(); // This should have been updated before : make sure anyway. @@ -362,32 +382,23 @@ protected virtual void UpdateRenderPoints() if ((orientation == Orientation.Horizontal && Mathf.Abs(p1.y - p4.y) < 2 && p1.x + k_EdgeLengthFromPort < p4.x - k_EdgeLengthFromPort) || (orientation == Orientation.Vertical && Mathf.Abs(p1.x - p4.x) < 2 && p1.y + k_EdgeLengthFromPort < p4.y - k_EdgeLengthFromPort)) { - float safeSpan = orientation == Orientation.Horizontal - ? Mathf.Abs((p1.x + k_EdgeLengthFromPort) - (p4.x - k_EdgeLengthFromPort)) - : Mathf.Abs((p1.y + k_EdgeLengthFromPort) - (p4.y - k_EdgeLengthFromPort)); - - float safeSpan3 = safeSpan / k_EdgeStraightLineSegmentDivisor; - float nodeToP2Dist = Mathf.Min(safeSpan3, diameter); - nodeToP2Dist = Mathf.Max(0, nodeToP2Dist); - - var offset = orientation == Orientation.Horizontal - ? new Vector2(diameter - nodeToP2Dist, 0) - : new Vector2(0, diameter - nodeToP2Dist); - - m_RenderPoints.Add(p1); - m_RenderPoints.Add(p2 - offset); - m_RenderPoints.Add(p3 + offset); - m_RenderPoints.Add(p4); + RenderStraightLines(p1, p2, p3, p4); return; } - m_RenderPoints.Add(p1); EdgeCornerSweepValues corner1 = GetCornerSweepValues(p1, p2, p3, diameter, Direction.Output); EdgeCornerSweepValues corner2 = GetCornerSweepValues(p2, p3, p4, diameter, Direction.Input); - ValidateCornerSweepValues(ref corner1, ref corner2); + if (!ValidateCornerSweepValues(ref corner1, ref corner2)) + { + RenderStraightLines(p1, p2, p3, p4); + + return; + } + + m_RenderPoints.Add(p1); GetRoundedCornerPoints(m_RenderPoints, corner1, Direction.Output); GetRoundedCornerPoints(m_RenderPoints, corner2, Direction.Input); @@ -395,7 +406,7 @@ protected virtual void UpdateRenderPoints() m_RenderPoints.Add(p4); } - private void ValidateCornerSweepValues(ref EdgeCornerSweepValues corner1, ref EdgeCornerSweepValues corner2) + private bool ValidateCornerSweepValues(ref EdgeCornerSweepValues corner1, ref EdgeCornerSweepValues corner2) { // Get the midpoint between the two corner circle centers. Vector2 circlesMidpoint = (corner1.circleCenter + corner2.circleCenter) / 2; @@ -404,8 +415,15 @@ private void ValidateCornerSweepValues(ref EdgeCornerSweepValues corner1, ref Ed Vector2 p2CenterToCross1 = corner1.circleCenter - corner1.crossPoint1; Vector2 p2CenterToCirclesMid = corner1.circleCenter - circlesMidpoint; double angleToCirclesMid = orientation == Orientation.Horizontal - ? Math.Atan2(p2CenterToCross1.y, p2CenterToCross1.x) - Math.Atan2(p2CenterToCirclesMid.y, p2CenterToCirclesMid.x) - : Math.Atan2(p2CenterToCross1.x, p2CenterToCross1.y) - Math.Atan2(p2CenterToCirclesMid.x, p2CenterToCirclesMid.y); + ? Math.Atan2(p2CenterToCross1.y, p2CenterToCross1.x) - + Math.Atan2(p2CenterToCirclesMid.y, p2CenterToCirclesMid.x) + : Math.Atan2(p2CenterToCross1.x, p2CenterToCross1.y) - + Math.Atan2(p2CenterToCirclesMid.x, p2CenterToCirclesMid.y); + + if (double.IsNaN(angleToCirclesMid)) + { + return false; + } // We need the angle to the circles midpoint to match the turn direction of the first corner's sweep angle. angleToCirclesMid = Math.Sign(angleToCirclesMid) * 2 * Mathf.PI - angleToCirclesMid; @@ -424,6 +442,8 @@ private void ValidateCornerSweepValues(ref EdgeCornerSweepValues corner1, ref Ed corner1.sweepAngle = Math.Sign(corner1.sweepAngle) * Mathf.Min(maxSweepAngle, Mathf.Abs((float)corner1.sweepAngle)); corner2.sweepAngle = Math.Sign(corner2.sweepAngle) * Mathf.Min(maxSweepAngle, Mathf.Abs((float)corner2.sweepAngle)); } + + return true; } private EdgeCornerSweepValues GetCornerSweepValues( diff --git a/Modules/GraphViewEditor/Elements/Node.cs b/Modules/GraphViewEditor/Elements/Node.cs index d6df9b0803..259280c433 100644 --- a/Modules/GraphViewEditor/Elements/Node.cs +++ b/Modules/GraphViewEditor/Elements/Node.cs @@ -265,12 +265,20 @@ public bool RefreshPorts() foreach (Port input in updatedInputs) { + // Make sure we don't register these more than once. + input.OnConnect -= OnPortConnectAction; + input.OnDisconnect -= OnPortConnectAction; + input.OnConnect += OnPortConnectAction; input.OnDisconnect += OnPortConnectAction; } foreach (Port output in updatedOutputs) { + // Make sure we don't register these more than once. + output.OnConnect -= OnPortConnectAction; + output.OnDisconnect -= OnPortConnectAction; + output.OnConnect += OnPortConnectAction; output.OnDisconnect += OnPortConnectAction; } diff --git a/Modules/IMGUI/GUI.cs b/Modules/IMGUI/GUI.cs index 3815b30336..27f33906c8 100644 --- a/Modules/IMGUI/GUI.cs +++ b/Modules/IMGUI/GUI.cs @@ -16,6 +16,7 @@ public partial class GUI private static int s_HotTextField = -1; + private static readonly int s_BoxHash = "Box".GetHashCode(); private static readonly int s_RepeatButtonHash = "repeatButton".GetHashCode(); private static readonly int s_ToggleHash = "Toggle".GetHashCode(); private static readonly int s_ButtonGridHash = "ButtonGrid".GetHashCode(); @@ -340,8 +341,11 @@ public static void Box(Rect position, Texture image, GUIStyle style) public static void Box(Rect position, GUIContent content, GUIStyle style) { GUIUtility.CheckOnGUI(); + int id = GUIUtility.GetControlID(s_BoxHash, FocusType.Passive); if (Event.current.type == EventType.Repaint) - style.Draw(position, content, false, false, false, false); + { + style.Draw(position, content, id); + } } /// *listonly* diff --git a/Modules/Tilemap/Managed/TileBase.cs b/Modules/Tilemap/Managed/TileBase.cs index f5e62f233f..1bbb5c7d4e 100644 --- a/Modules/Tilemap/Managed/TileBase.cs +++ b/Modules/Tilemap/Managed/TileBase.cs @@ -10,7 +10,10 @@ namespace UnityEngine.Tilemaps [RequiredByNativeCode] public abstract class TileBase : ScriptableObject { + [RequiredByNativeCode] public virtual void RefreshTile(Vector3Int position, ITilemap tilemap) { tilemap.RefreshTile(position); } + + [RequiredByNativeCode] public virtual void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData) {} private TileData GetTileDataNoRef(Vector3Int position, ITilemap tilemap) { @@ -19,6 +22,7 @@ private TileData GetTileDataNoRef(Vector3Int position, ITilemap tilemap) return tileData; } + [RequiredByNativeCode] public virtual bool GetTileAnimationData(Vector3Int position, ITilemap tilemap, ref TileAnimationData tileAnimationData) { return false; } private TileAnimationData GetTileAnimationDataNoRef(Vector3Int position, ITilemap tilemap) { @@ -27,6 +31,7 @@ private TileAnimationData GetTileAnimationDataNoRef(Vector3Int position, ITilema return tileAnimationData; } + [RequiredByNativeCode] public virtual bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go) { return false; } } } diff --git a/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs b/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs index dcce42cfeb..9d6ad54798 100644 --- a/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs +++ b/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs @@ -263,6 +263,7 @@ public void EditorPreviewBoxFill(Vector3Int position, Object tile, int startX, i [RequireComponent(typeof(Tilemap))] [NativeHeader("Modules/Grid/Public/GridMarshalling.h")] [NativeHeader("Modules/Tilemap/TilemapRendererJobs.h")] + [NativeHeader("Modules/Tilemap/Public/TilemapMarshalling.h")] [NativeType(Header = "Modules/Tilemap/Public/TilemapRenderer.h")] public sealed partial class TilemapRenderer : Renderer { @@ -274,12 +275,26 @@ public enum SortOrder TopRight = 3, } + public enum DetectChunkCullingBounds + { + Auto = 0, + Manual = 1, + } + public extern Vector3Int chunkSize { get; set; } + public extern Vector3 chunkCullingBounds + { + [FreeFunction("TilemapRendererBindings::GetChunkCullingBounds", HasExplicitThis = true)] + get; + [FreeFunction("TilemapRendererBindings::SetChunkCullingBounds", HasExplicitThis = true)] + set; + } + public extern int maxChunkCount { get; @@ -298,6 +313,12 @@ public extern SortOrder sortOrder set; } + public extern DetectChunkCullingBounds detectChunkCullingBounds + { + get; + set; + } + public extern SpriteMaskInteraction maskInteraction { get; diff --git a/Modules/TilemapEditor/Editor/Managed/TilemapRendererEditor.cs b/Modules/TilemapEditor/Editor/Managed/TilemapRendererEditor.cs index 17d793fcc8..689deedbfc 100644 --- a/Modules/TilemapEditor/Editor/Managed/TilemapRendererEditor.cs +++ b/Modules/TilemapEditor/Editor/Managed/TilemapRendererEditor.cs @@ -15,6 +15,13 @@ internal class TilemapRendererEditor : RendererEditorBase private SerializedProperty m_Material; private SerializedProperty m_SortOrder; private SerializedProperty m_MaskInteraction; + private SerializedProperty m_ChunkCullingBounds; + private SerializedProperty m_DetectChunkCullingBounds; + + private TilemapRenderer tilemapRenderer + { + get { return target as TilemapRenderer; } + } private static class Styles { @@ -29,6 +36,8 @@ public override void OnEnable() m_Material = serializedObject.FindProperty("m_Materials.Array"); // Only allow to edit one material m_SortOrder = serializedObject.FindProperty("m_SortOrder"); m_MaskInteraction = serializedObject.FindProperty("m_MaskInteraction"); + m_ChunkCullingBounds = serializedObject.FindProperty("m_ChunkCullingBounds"); + m_DetectChunkCullingBounds = serializedObject.FindProperty("m_DetectChunkCullingBounds"); } public override void OnInspectorGUI() @@ -37,6 +46,11 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(m_Material.GetArrayElementAtIndex(0), Styles.materialLabel, true); EditorGUILayout.PropertyField(m_SortOrder); + EditorGUILayout.PropertyField(m_DetectChunkCullingBounds); + GUI.enabled = (!m_DetectChunkCullingBounds.hasMultipleDifferentValues && TilemapRenderer.DetectChunkCullingBounds.Manual == tilemapRenderer.detectChunkCullingBounds); + EditorGUILayout.PropertyField(m_ChunkCullingBounds); + GUI.enabled = true; + RenderSortingLayerFields(); EditorGUILayout.Space(); diff --git a/Modules/UIElementsDebuggerEditor/UIElementsDebugger.cs b/Modules/UIElementsDebuggerEditor/UIElementsDebugger.cs index b867a44c0c..5301600445 100644 --- a/Modules/UIElementsDebuggerEditor/UIElementsDebugger.cs +++ b/Modules/UIElementsDebuggerEditor/UIElementsDebugger.cs @@ -131,10 +131,14 @@ public void OnGUI() m_Overlay = GUILayout.Toggle(m_Overlay, Styles.overlayContent, EditorStyles.toolbarButton); - bool uxmlLiveReloadIsEnabled = RetainedMode.UxmlLiveReloadIsEnabled; - bool newUxmlLiveReloadIsEnabled = GUILayout.Toggle(uxmlLiveReloadIsEnabled, Styles.liveReloadContent, EditorStyles.toolbarButton); - if (newUxmlLiveReloadIsEnabled != uxmlLiveReloadIsEnabled) - RetainedMode.UxmlLiveReloadIsEnabled = newUxmlLiveReloadIsEnabled; + // Note for future us : the UXML reload feature isn't quite ready to be public + if (Unsupported.IsDeveloperBuild()) + { + bool uxmlLiveReloadIsEnabled = RetainedMode.UxmlLiveReloadIsEnabled; + bool newUxmlLiveReloadIsEnabled = GUILayout.Toggle(uxmlLiveReloadIsEnabled, Styles.liveReloadContent, EditorStyles.toolbarButton); + if (newUxmlLiveReloadIsEnabled != uxmlLiveReloadIsEnabled) + RetainedMode.UxmlLiveReloadIsEnabled = newUxmlLiveReloadIsEnabled; + } EditorGUILayout.EndHorizontal(); diff --git a/Modules/UnityAnalytics/Events/CustomEventData.bindings.cs b/Modules/UnityAnalytics/Events/CustomEventData.bindings.cs new file mode 100644 index 0000000000..7d84d2f93f --- /dev/null +++ b/Modules/UnityAnalytics/Events/CustomEventData.bindings.cs @@ -0,0 +1,63 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using Object = UnityEngine.Object; + +namespace UnityEngine.Analytics +{ + [StructLayout(LayoutKind.Sequential)] + [NativeHeader("Modules/UnityAnalytics/Events/UserCustomEvent.h")] + internal partial class CustomEventData : IDisposable + { + [System.NonSerialized] + internal IntPtr m_Ptr; + + private CustomEventData() {} + + public CustomEventData(string name) + { + m_Ptr = Internal_Create(this, name); + } + + ~CustomEventData() + { + Destroy(); + } + + void Destroy() + { + if (m_Ptr != IntPtr.Zero) + { + Internal_Destroy(m_Ptr); + m_Ptr = IntPtr.Zero; + } + } + + public void Dispose() + { + Destroy(); + GC.SuppressFinalize(this); + } + + internal static extern IntPtr Internal_Create(CustomEventData ced, string name); + [ThreadSafe] + internal static extern void Internal_Destroy(IntPtr ptr); + + public extern bool AddString(string key, string value); + public extern bool AddInt32(string key, Int32 value); + public extern bool AddUInt32(string key, UInt32 value); + public extern bool AddInt64(string key, Int64 value); + public extern bool AddUInt64(string key, UInt64 value); + public extern bool AddBool(string key, bool value); + public extern bool AddDouble(string key, double value); + } +} diff --git a/Modules/UnityAnalytics/Events/CustomEventData.cs b/Modules/UnityAnalytics/Events/CustomEventData.cs index 1202e47f15..4e810d5938 100644 --- a/Modules/UnityAnalytics/Events/CustomEventData.cs +++ b/Modules/UnityAnalytics/Events/CustomEventData.cs @@ -16,35 +16,7 @@ namespace UnityEngine.Analytics { internal partial class CustomEventData : IDisposable { - private CustomEventData() {} - - public CustomEventData(string name) { InternalCreate(name); } - - ~CustomEventData() { InternalDestroy(); } - - public void Dispose() - { - InternalDestroy(); - GC.SuppressFinalize(this); - } - - public bool Add(string key, string value) { return AddString(key, value); } - public bool Add(string key, bool value) { return AddBool(key, value); } - public bool Add(string key, char value) { return AddChar(key, value); } - public bool Add(string key, byte value) { return AddByte(key, value); } - public bool Add(string key, sbyte value) { return AddSByte(key, value); } - public bool Add(string key, Int16 value) { return AddInt16(key, value); } - public bool Add(string key, UInt16 value) { return AddUInt16(key, value); } - public bool Add(string key, Int32 value) { return AddInt32(key, value); } - public bool Add(string key, UInt32 value) { return AddUInt32(key, value); } - public bool Add(string key, Int64 value) { return AddInt64(key, value); } - public bool Add(string key, UInt64 value) { return AddUInt64(key, value); } - public bool Add(string key, float value) { return AddDouble(key, (double)System.Convert.ToDecimal(value)); } - public bool Add(string key, double value) { return AddDouble(key, value); } - public bool Add(string key, Decimal value) { return AddDouble(key, (double)System.Convert.ToDecimal(value)); } - - - public bool Add(IDictionary eventData) + public bool AddDictionary(IDictionary eventData) { foreach (var item in eventData) { @@ -52,40 +24,40 @@ public bool Add(IDictionary eventData) object value = item.Value; if (value == null) { - Add(key, "null"); + AddString(key, "null"); continue; } Type type = value.GetType(); if (type == typeof(System.String)) - Add(key, (string)value); + AddString(key, (string)value); else if (type == typeof(System.Char)) - Add(key, (Char)value); + AddString(key, Char.ToString((Char)value)); else if (type == typeof(System.SByte)) - Add(key, (SByte)value); + AddInt32(key, (SByte)value); else if (type == typeof(System.Byte)) - Add(key, (Byte)value); + AddInt32(key, (Byte)value); else if (type == typeof(System.Int16)) - Add(key, (Int16)value); + AddInt32(key, (Int16)value); else if (type == typeof(System.UInt16)) - Add(key, (UInt16)value); + AddUInt32(key, (UInt16)value); else if (type == typeof(System.Int32)) - Add(key, (Int32)value); + AddInt32(key, (Int32)value); else if (type == typeof(System.UInt32)) - Add(item.Key, (UInt32)value); + AddUInt32(item.Key, (UInt32)value); else if (type == typeof(System.Int64)) - Add(key, (Int64)value); + AddInt64(key, (Int64)value); else if (type == typeof(System.UInt64)) - Add(key, (UInt64)value); + AddUInt64(key, (UInt64)value); else if (type == typeof(System.Boolean)) - Add(key, (bool)value); + AddBool(key, (bool)value); else if (type == typeof(System.Single)) - Add(key, (Single)value); + AddDouble(key, (double)System.Convert.ToDecimal((Single)value)); else if (type == typeof(System.Double)) - Add(key, (double)value); + AddDouble(key, (double)value); else if (type == typeof(System.Decimal)) - Add(key, (Decimal)value); + AddDouble(key, (double)System.Convert.ToDecimal((Decimal)value)); else if (type.IsValueType) - Add(key, value.ToString()); + AddString(key, value.ToString()); else throw new ArgumentException(String.Format("Invalid type: {0} passed", type)); } diff --git a/Modules/UnityAnalytics/UnityAnalytics.cs b/Modules/UnityAnalytics/UnityAnalytics.cs index ccbe319f26..bd884d0533 100644 --- a/Modules/UnityAnalytics/UnityAnalytics.cs +++ b/Modules/UnityAnalytics/UnityAnalytics.cs @@ -7,8 +7,6 @@ using UnityEngine; -using UnityEngine.Connect; - namespace UnityEngine.Analytics { public enum Gender @@ -38,7 +36,9 @@ internal static UnityAnalyticsHandler GetUnityAnalyticsHandler() { if (s_UnityAnalyticsHandler == null) s_UnityAnalyticsHandler = new UnityAnalyticsHandler(); - return s_UnityAnalyticsHandler; + if (s_UnityAnalyticsHandler.IsInitialized()) + return s_UnityAnalyticsHandler; + return null; } public static bool limitUserTracking @@ -88,7 +88,7 @@ public static AnalyticsResult FlushEvents() if (unityAnalyticsHandler == null) return AnalyticsResult.NotInitialized; - return (AnalyticsResult)unityAnalyticsHandler.FlushEvents(); + return unityAnalyticsHandler.FlushEvents() ? AnalyticsResult.Ok : AnalyticsResult.NotInitialized; } public static AnalyticsResult SetUserId(string userId) @@ -98,7 +98,7 @@ public static AnalyticsResult SetUserId(string userId) UnityAnalyticsHandler unityAnalyticsHandler = GetUnityAnalyticsHandler(); if (unityAnalyticsHandler == null) return AnalyticsResult.NotInitialized; - return (AnalyticsResult)unityAnalyticsHandler.SetUserId(userId); + return unityAnalyticsHandler.SetUserId(userId); } public static AnalyticsResult SetUserGender(Gender gender) @@ -106,7 +106,7 @@ public static AnalyticsResult SetUserGender(Gender gender) UnityAnalyticsHandler unityAnalyticsHandler = GetUnityAnalyticsHandler(); if (unityAnalyticsHandler == null) return AnalyticsResult.NotInitialized; - return (AnalyticsResult)unityAnalyticsHandler.SetUserGender(gender); + return unityAnalyticsHandler.SetUserGender(gender); } public static AnalyticsResult SetUserBirthYear(int birthYear) @@ -114,31 +114,33 @@ public static AnalyticsResult SetUserBirthYear(int birthYear) UnityAnalyticsHandler unityAnalyticsHandler = GetUnityAnalyticsHandler(); if (s_UnityAnalyticsHandler == null) return AnalyticsResult.NotInitialized; - return (AnalyticsResult)unityAnalyticsHandler.SetUserBirthYear(birthYear); + return unityAnalyticsHandler.SetUserBirthYear(birthYear); } public static AnalyticsResult Transaction(string productId, decimal amount, string currency) { - UnityAnalyticsHandler unityAnalyticsHandler = GetUnityAnalyticsHandler(); - if (unityAnalyticsHandler == null) - return AnalyticsResult.NotInitialized; - return (AnalyticsResult)unityAnalyticsHandler.Transaction(productId, Convert.ToDouble(amount), currency, null, null); + return Transaction(productId, amount, currency, null, null, false); } public static AnalyticsResult Transaction(string productId, decimal amount, string currency, string receiptPurchaseData, string signature) { - UnityAnalyticsHandler unityAnalyticsHandler = GetUnityAnalyticsHandler(); - if (unityAnalyticsHandler == null) - return AnalyticsResult.NotInitialized; - return (AnalyticsResult)unityAnalyticsHandler.Transaction(productId, Convert.ToDouble(amount), currency, receiptPurchaseData, signature); + return Transaction(productId, amount, currency, receiptPurchaseData, signature, false); } public static AnalyticsResult Transaction(string productId, decimal amount, string currency, string receiptPurchaseData, string signature, bool usingIAPService) { + if (string.IsNullOrEmpty(productId)) + throw new ArgumentException("Cannot set productId to an empty or null string"); + if (string.IsNullOrEmpty(currency)) + throw new ArgumentException("Cannot set currency to an empty or null string"); UnityAnalyticsHandler unityAnalyticsHandler = GetUnityAnalyticsHandler(); if (unityAnalyticsHandler == null) return AnalyticsResult.NotInitialized; - return (AnalyticsResult)unityAnalyticsHandler.Transaction(productId, Convert.ToDouble(amount), currency, receiptPurchaseData, signature, usingIAPService); + if (receiptPurchaseData == null) + receiptPurchaseData = string.Empty; + if (signature == null) + signature = string.Empty; + return unityAnalyticsHandler.Transaction(productId, Convert.ToDouble(amount), currency, receiptPurchaseData, signature, usingIAPService); } public static AnalyticsResult CustomEvent(string customEventName) @@ -148,7 +150,7 @@ public static AnalyticsResult CustomEvent(string customEventName) UnityAnalyticsHandler unityAnalyticsHandler = GetUnityAnalyticsHandler(); if (unityAnalyticsHandler == null) return AnalyticsResult.NotInitialized; - return (AnalyticsResult)unityAnalyticsHandler.CustomEvent(customEventName); + return unityAnalyticsHandler.SendCustomEventName(customEventName); } public static AnalyticsResult CustomEvent(string customEventName, Vector3 position) @@ -159,10 +161,10 @@ public static AnalyticsResult CustomEvent(string customEventName, Vector3 positi if (unityAnalyticsHandler == null) return AnalyticsResult.NotInitialized; CustomEventData customEvent = new CustomEventData(customEventName); - customEvent.Add("x", (double)System.Convert.ToDecimal(position.x)); - customEvent.Add("y", (double)System.Convert.ToDecimal(position.y)); - customEvent.Add("z", (double)System.Convert.ToDecimal(position.z)); - return (AnalyticsResult)unityAnalyticsHandler.CustomEvent(customEvent); + customEvent.AddDouble("x", (double)System.Convert.ToDecimal(position.x)); + customEvent.AddDouble("y", (double)System.Convert.ToDecimal(position.y)); + customEvent.AddDouble("z", (double)System.Convert.ToDecimal(position.z)); + return unityAnalyticsHandler.SendCustomEvent(customEvent); } public static AnalyticsResult CustomEvent(string customEventName, IDictionary eventData) @@ -173,10 +175,10 @@ public static AnalyticsResult CustomEvent(string customEventName, IDictionary Completed; [RequiredByNativeCode] internal static void RemoteSettingsUpdated(bool wasLastUpdatedFromServer) @@ -37,6 +38,14 @@ internal static void RemoteSettingsBeforeFetchFromServer() handler(); } + [RequiredByNativeCode] + internal static void RemoteSettingsUpdateCompleted(bool wasLastUpdatedFromServer, bool settingsChanged, int response) + { + var handler = Completed; + if (handler != null) + handler(wasLastUpdatedFromServer, settingsChanged, response); + } + [Obsolete("Calling CallOnUpdate() is not necessary any more and should be removed. Use RemoteSettingsUpdated instead", true)] public static void CallOnUpdate() { diff --git a/Projects/CSharp/UnityEditor.csproj b/Projects/CSharp/UnityEditor.csproj index 58f73e2418..ff7bb23e5a 100644 --- a/Projects/CSharp/UnityEditor.csproj +++ b/Projects/CSharp/UnityEditor.csproj @@ -1661,6 +1661,9 @@ Editor\Mono\UIElements\Controls\GradientField.cs + +Editor\Mono\UIElements\Controls\PopupField.cs + Editor\Mono\UIElements\Controls\CompoundFields.cs @@ -1850,6 +1853,9 @@ Editor\Mono\Scripting\ScriptCompilation\AssemblyDefinitionException.cs + +Editor\Mono\Scripting\ScriptCompilation\MonoLibraryHelpers.cs + Editor\Mono\PerceptionRemoting\HolographicEmulation\HolographicEmulationWindow.cs diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index 898aec1293..8696b8763b 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -1896,14 +1896,14 @@ Modules\UnityAnalytics\UnityAnalytics.cs - -Modules\UnityAnalytics\Events\CustomEventData.cs + +Modules\UnityAnalytics\UnityAnalyticsHandler.bindings.cs - -artifacts\generated\bindings_old\common\UnityAnalytics\UnityAnalyticsHandlerBindings.gen.cs + +Modules\UnityAnalytics\Events\CustomEventData.bindings.cs - -artifacts\generated\bindings_old\common\UnityAnalytics\CustomEventDataBindings.gen.cs + +Modules\UnityAnalytics\Events\CustomEventData.cs Modules\UnityConnect\AnalyticsSessionInfo.bindings.cs diff --git a/README.md b/README.md index 9cc1e7e9cb..bd8f865d8d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.1.0b5 C# reference source code +## Unity 2018.1.0b6 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/artifacts/generated/bindings_old/common/Core/RectTransformBindings.gen.cs b/artifacts/generated/bindings_old/common/Core/RectTransformBindings.gen.cs index bb1fa7c5ef..3789267f3b 100644 --- a/artifacts/generated/bindings_old/common/Core/RectTransformBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Core/RectTransformBindings.gen.cs @@ -65,12 +65,12 @@ public void Add(Object driver, RectTransform rectTransform, DrivenTransformPrope if (m_Tracked == null) m_Tracked = new List(); - rectTransform.drivenByObject = driver; - rectTransform.drivenProperties = rectTransform.drivenProperties | drivenProperties; - if (!Application.isPlaying && CanRecordModifications()) RuntimeUndo.RecordObject(rectTransform, "Driving RectTransform"); + rectTransform.drivenByObject = driver; + rectTransform.drivenProperties = rectTransform.drivenProperties | drivenProperties; + m_Tracked.Add(rectTransform); } diff --git a/artifacts/generated/bindings_old/common/Editor/EditorBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/EditorBindings.gen.cs index aa327ac0ed..560ede9acb 100644 --- a/artifacts/generated/bindings_old/common/Editor/EditorBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/EditorBindings.gen.cs @@ -221,7 +221,10 @@ private void OnDisableINTERNAL() internal virtual void OnForceReloadInspector() { if (m_SerializedObject != null) + { m_SerializedObject.SetIsDifferentCacheDirty(); + InternalSetTargets(m_SerializedObject.targetObjects); + } } internal bool GetOptimizedGUIBlockImplementation(bool isDirty, bool isVisible, out OptimizedGUIBlock block, out float height) diff --git a/artifacts/generated/bindings_old/common/UnityAnalytics/CustomEventDataBindings.gen.cs b/artifacts/generated/bindings_old/common/UnityAnalytics/CustomEventDataBindings.gen.cs deleted file mode 100644 index bad48d531d..0000000000 --- a/artifacts/generated/bindings_old/common/UnityAnalytics/CustomEventDataBindings.gen.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using scm=System.ComponentModel; -using uei=UnityEngine.Internal; -using RequiredByNativeCodeAttribute=UnityEngine.Scripting.RequiredByNativeCodeAttribute; -using UsedByNativeCodeAttribute=UnityEngine.Scripting.UsedByNativeCodeAttribute; - - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEngine.Analytics -{ -[StructLayout(LayoutKind.Sequential)] -internal partial class CustomEventData : IDisposable -{ - [System.NonSerialized] - internal IntPtr m_Ptr; - - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public void InternalCreate (string name) ; - - [ThreadAndSerializationSafe ()] - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal void InternalDestroy () ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddString (string key, string value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddBool (string key, bool value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddChar (string key, char value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddByte (string key, byte value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddSByte (string key, sbyte value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddInt16 (string key, Int16 value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddUInt16 (string key, UInt16 value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddInt32 (string key, Int32 value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddUInt32 (string key, UInt32 value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddInt64 (string key, Int64 value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddUInt64 (string key, UInt64 value) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private bool AddDouble (string key, double value) ; - -} - - -} diff --git a/artifacts/generated/bindings_old/common/UnityAnalytics/UnityAnalyticsHandlerBindings.gen.cs b/artifacts/generated/bindings_old/common/UnityAnalytics/UnityAnalyticsHandlerBindings.gen.cs deleted file mode 100644 index 4e4be3504e..0000000000 --- a/artifacts/generated/bindings_old/common/UnityAnalytics/UnityAnalyticsHandlerBindings.gen.cs +++ /dev/null @@ -1,143 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using scm=System.ComponentModel; -using uei=UnityEngine.Internal; -using RequiredByNativeCodeAttribute=UnityEngine.Scripting.RequiredByNativeCodeAttribute; -using UsedByNativeCodeAttribute=UnityEngine.Scripting.UsedByNativeCodeAttribute; - - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEngine.Analytics -{ -[StructLayout(LayoutKind.Sequential)] -internal sealed partial class UnityAnalyticsHandler : IDisposable -{ - [System.NonSerialized] - internal IntPtr m_Ptr; - - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal void InternalCreate () ; - - [ThreadAndSerializationSafe ()] - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern internal void InternalDestroy () ; - - public UnityAnalyticsHandler() - { - InternalCreate(); - } - - - ~UnityAnalyticsHandler() - { - InternalDestroy(); - } - - - public void Dispose() - { - InternalDestroy(); - GC.SuppressFinalize(this); - } - - - public extern static bool limitUserTracking - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - set; - } - - public extern static bool deviceStatsEnabled - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - set; - } - - public extern bool enabled - { - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - get; - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - set; - } - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public AnalyticsResult FlushEvents () ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public AnalyticsResult SetUserId (string userId) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public AnalyticsResult SetUserGender (Gender gender) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public AnalyticsResult SetUserBirthYear (int birthYear) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public AnalyticsResult Transaction (string productId, double amount, string currency) ; - - public AnalyticsResult Transaction(string productId, double amount, string currency, string receiptPurchaseData, string signature) - { - return Transaction(productId, amount, currency, receiptPurchaseData, signature, false); - } - - - internal AnalyticsResult Transaction(string productId, double amount, string currency, string receiptPurchaseData, string signature, bool usingIAPService) - { - if (receiptPurchaseData == null) - receiptPurchaseData = string.Empty; - if (signature == null) - signature = string.Empty; - return InternalTransaction(productId, amount, currency, receiptPurchaseData, signature, usingIAPService); - } - - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private AnalyticsResult InternalTransaction (string productId, double amount, string currency, string receiptPurchaseData, string signature, bool usingIAPService) ; - - public AnalyticsResult CustomEvent(string customEventName) { return SendCustomEventName(customEventName); } - - - public AnalyticsResult CustomEvent(CustomEventData eventData) { return SendCustomEvent(eventData); } - - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private AnalyticsResult SendCustomEventName (string customEventName) ; - - [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration - [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern private AnalyticsResult SendCustomEvent (CustomEventData eventData) ; - -} - - -} From 170d37aa36029b2d22b5698bfbae973608d405af Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 14 Feb 2018 11:12:33 +0000 Subject: [PATCH 06/17] Unity 2018.1.0b7 C# reference source code --- .../AnimationWindow/CurveMenuManager.cs | 7 +- .../Animation/MaterialAnimationUtility.cs | 4 +- Editor/Mono/AssemblyHelper.cs | 66 ++++--------------- Editor/Mono/BuildPipeline/MonoCrossCompile.cs | 4 +- Editor/Mono/GUI/DockArea.cs | 2 + .../GUIViewDebuggerHelper.bindings.cs | 1 + Editor/Mono/GUIView.cs | 4 ++ .../ImportSettings/AssetImporterEditor.cs | 22 ++++--- .../TextureImportPlatformSettings.cs | 2 + Editor/Mono/Inspector/InspectorWindow.cs | 10 --- .../PlayerSettingsEditor.cs | 4 +- Editor/Mono/Inspector/PreviewWindow.cs | 1 - .../ScriptCompilation/CompilationTask.cs | 15 ++++- .../ScriptCompilation/CustomScriptAssembly.cs | 45 +++++++++++-- .../ScriptCompilation/EditorCompilation.cs | 28 ++++++-- .../EditorCompilationInterface.cs | 12 ++++ .../Mono/UIElements/VisualTreeAssetEditor.cs | 6 ++ .../Editor/Managed/PackageInfo.cs | 5 +- .../Profiler/Editor/ProfilerWindow/Chart.cs | 4 +- .../Editor/ProfilerWindow/ProfilerChart.cs | 1 + .../ProfilerFrameDataTreeView.cs | 33 ++++++++-- .../Editor/ProfilerWindow/ProfilerWindow.cs | 20 +++--- .../Public/ProfilerFrameDataView.bindings.cs | 14 ++++ Modules/UIElements/Events/EventBase.cs | 2 + Modules/UIElements/UIElementsUtility.cs | 5 ++ Modules/UIElements/UQuery.cs | 18 +++-- Modules/UnityAnalytics/UnityAnalytics.cs | 22 +++++++ .../UnityAnalyticsHandler.bindings.cs | 4 ++ README.md | 2 +- Runtime/Export/GI/Lightmapping.cs | 25 +++++-- Runtime/Export/UnityEngineObject.bindings.cs | 12 +++- .../common/Editor/UndoBindings.gen.cs | 16 +++-- 32 files changed, 289 insertions(+), 127 deletions(-) diff --git a/Editor/Mono/Animation/AnimationWindow/CurveMenuManager.cs b/Editor/Mono/Animation/AnimationWindow/CurveMenuManager.cs index eb1b20e5e0..1db96f0775 100644 --- a/Editor/Mono/Animation/AnimationWindow/CurveMenuManager.cs +++ b/Editor/Mono/Animation/AnimationWindow/CurveMenuManager.cs @@ -129,10 +129,12 @@ public void AddTangentMenuItems(GenericMenu menu, List keyList) menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Linear"), allLeftLinear, SetLeftLinear, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Constant"), allLeftConstant, SetLeftConstant, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Weighted"), allLeftWeighted, ToggleLeftWeighted, keyList); + menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Free"), allRightFree, SetRightEditable, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Linear"), allRightLinear, SetRightLinear, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Constant"), allRightConstant, SetRightConstant, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Free"), allRightFree && allLeftFree, SetBothEditable, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Weighted"), allRightWeighted, ToggleRightWeighted, keyList); + menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Free"), allRightFree && allLeftFree, SetBothEditable, keyList); + menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Linear"), allRightLinear && allLeftLinear, SetBothLinear, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Constant"), allRightConstant && allLeftConstant, SetBothConstant, keyList); menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Weighted"), allRightWeighted && allLeftWeighted, ToggleBothWeighted, keyList); } @@ -147,12 +149,15 @@ public void AddTangentMenuItems(GenericMenu menu, List keyList) menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Free")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Linear")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Constant")); + menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Weighted")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Free")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Linear")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Constant")); + menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Weighted")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Free")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Linear")); menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Constant")); + menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Weighted")); } } diff --git a/Editor/Mono/Animation/MaterialAnimationUtility.cs b/Editor/Mono/Animation/MaterialAnimationUtility.cs index c69f38f32d..a6702449b2 100644 --- a/Editor/Mono/Animation/MaterialAnimationUtility.cs +++ b/Editor/Mono/Animation/MaterialAnimationUtility.cs @@ -66,8 +66,8 @@ static bool ApplyMaterialModificationToAnimationRecording(PropertyModification[] undoModifications[i].previousValue = modifications[i]; } - UndoPropertyModification[] ret = Undo.postprocessModifications(undoModifications); - return (ret.Length != modifications.Length); + UndoPropertyModification[] ret = Undo.InvokePostprocessModifications(undoModifications); + return ret.Length != modifications.Length; } static public bool OverridePropertyColor(MaterialProperty materialProp, Renderer target, out Color color) diff --git a/Editor/Mono/AssemblyHelper.cs b/Editor/Mono/AssemblyHelper.cs index d75990069f..050de9db4d 100644 --- a/Editor/Mono/AssemblyHelper.cs +++ b/Editor/Mono/AssemblyHelper.cs @@ -17,6 +17,8 @@ namespace UnityEditor { internal partial class AssemblyHelper { + static readonly Type[] ExtendableScriptTypes = { typeof(MonoBehaviour), typeof(ScriptableObject), typeof(Experimental.AssetImporters.ScriptedImporter) }; + // Check if assmebly internal name doesn't match file name, and show the warning. static public void CheckForAssemblyFileNameMismatch(string assemblyPath) { @@ -50,24 +52,6 @@ static public string[] GetNamesOfAssembliesLoadedInCurrentDomain() return locations.ToArray(); } - public static Assembly FindLoadedAssemblyWithName(string s) - { - var assemblies = AppDomain.CurrentDomain.GetAssemblies(); - foreach (var a in assemblies) - { - try - { - if (s == System.IO.Path.GetFileNameWithoutExtension(a.Location)) - return a; - } - catch (NotSupportedException) - { - //we have some "dynamic" assmeblies that do not have a filename - } - } - return null; - } - static public string ExtractInternalAssemblyName(string path) { try @@ -222,55 +206,29 @@ static public bool IsUnityEngineModule(Assembly assembly) return assembly.GetCustomAttributes(typeof(UnityEngineModuleAssembly), false).Length > 0; } - private static bool IsTypeAUserExtendedScript(AssemblyDefinition assembly, TypeReference type) + private static bool IsTypeAUserExtendedScript(TypeReference type) { - if (type == null) + if (type == null || type.FullName == "System.Object") return false; - // Early out - if (type.FullName == "System.Object") - return false; - - // Look up the type in UnityEngine.dll or UnityEditor.dll - Assembly builtinAssembly = null; - if (type.Scope.Name == "UnityEngine" || type.Scope.Name == "UnityEngine.CoreModule") - builtinAssembly = typeof(MonoBehaviour).Assembly; - else if (type.Scope.Name == "UnityEditor") - builtinAssembly = typeof(EditorWindow).Assembly; - else if (type.Scope.Name == "UnityEngine.UI") - builtinAssembly = FindLoadedAssemblyWithName("UnityEngine.UI"); - - if (builtinAssembly != null) + foreach (var extendableScriptType in ExtendableScriptTypes) { - // TypeReference.FullName is cached and is preferred to use, but in case of generic types it - // includes generic arguments we can't use to get type from assembly. - var typeName = type.IsGenericInstance ? (type.Namespace + "." + type.Name) : type.FullName; - var engineType = builtinAssembly.GetType(typeName); - - // TODO: this "list of classes" should get dynamically filled by the classes them self, thus removing dependency of this class on those classes. - if (engineType != null) - { - if (engineType == typeof(MonoBehaviour) || engineType.IsSubclassOf(typeof(MonoBehaviour))) - return true; - if (engineType == typeof(ScriptableObject) || engineType.IsSubclassOf(typeof(ScriptableObject))) - return true; - if (engineType == typeof(Experimental.AssetImporters.ScriptedImporter) || engineType.IsSubclassOf(typeof(Experimental.AssetImporters.ScriptedImporter))) - return true; - } + if (type.Name == extendableScriptType.Name && type.Namespace == extendableScriptType.Namespace) + return true; } - TypeDefinition typeDefinition = null; try { - typeDefinition = type.Resolve(); + var typeDefinition = type.Resolve(); + + if (typeDefinition != null) + return IsTypeAUserExtendedScript(typeDefinition.BaseType); } catch (AssemblyResolutionException) { // just eat exception if we fail to load assembly here. // failure should be handled better in other places. } - if (typeDefinition != null) - return IsTypeAUserExtendedScript(assembly, typeDefinition.BaseType); return false; } @@ -308,7 +266,7 @@ public static void ExtractAllClassesThatAreUserExtendedScripts(string path, out try { - if (IsTypeAUserExtendedScript(assembly, baseType)) + if (IsTypeAUserExtendedScript(baseType)) { classNames.Add(type.Name); nameSpaces.Add(type.Namespace); diff --git a/Editor/Mono/BuildPipeline/MonoCrossCompile.cs b/Editor/Mono/BuildPipeline/MonoCrossCompile.cs index 033baf0939..da5a8a5144 100644 --- a/Editor/Mono/BuildPipeline/MonoCrossCompile.cs +++ b/Editor/Mono/BuildPipeline/MonoCrossCompile.cs @@ -4,6 +4,7 @@ using UnityEngine; using UnityEditor; +using UnityEditor.Scripting.ScriptCompilation; using System.Collections; using System.Collections.Generic; using System.IO; @@ -233,8 +234,7 @@ static public bool CrossCompileAOTDirectoryParallel(string crossCompilerPath, Bu static bool IsDebugableAssembly(string fname) { - fname = Path.GetFileName(fname); - return fname.StartsWith("Assembly", StringComparison.OrdinalIgnoreCase); + return EditorCompilationInterface.Instance.IsRuntimeScriptAssembly(fname); } static void CrossCompileAOT(BuildTarget target, string crossCompilerAbsolutePath, string assembliesAbsoluteDirectory, CrossCompileOptions crossCompileOptions, string input, string output, string additionalOptions) diff --git a/Editor/Mono/GUI/DockArea.cs b/Editor/Mono/GUI/DockArea.cs index e194e175d6..f2aa28b132 100644 --- a/Editor/Mono/GUI/DockArea.cs +++ b/Editor/Mono/GUI/DockArea.cs @@ -99,6 +99,8 @@ protected override void OnDestroy() UnityEngine.Object.DestroyImmediate(w, true); } + m_Panes.Clear(); + base.OnDestroy(); } diff --git a/Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.cs b/Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.cs index decf2f4cee..9b80c69e13 100644 --- a/Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.cs +++ b/Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.cs @@ -109,6 +109,7 @@ internal struct IMGUIInstruction public StackFrame[] stack; public int typeInstructionIndex; + public bool enabled; } [NativeHeader("Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.h")] diff --git a/Editor/Mono/GUIView.cs b/Editor/Mono/GUIView.cs index b6c9a1933c..685246bda2 100644 --- a/Editor/Mono/GUIView.cs +++ b/Editor/Mono/GUIView.cs @@ -179,6 +179,7 @@ protected virtual void OnDisable() if (imguiContainer.HasMouseCapture()) MouseCaptureController.ReleaseMouseCapture(); visualTree.Remove(imguiContainer); + imguiContainer = null; } protected virtual void OldOnGUI() {} @@ -212,6 +213,9 @@ protected override void SetPosition(Rect newPos) protected override void OnDestroy() { Internal_Close(); + + UIElementsUtility.RemoveCachedPanel(this.GetInstanceID()); + base.OnDestroy(); } diff --git a/Editor/Mono/ImportSettings/AssetImporterEditor.cs b/Editor/Mono/ImportSettings/AssetImporterEditor.cs index 31d320c15e..d76453f9c0 100644 --- a/Editor/Mono/ImportSettings/AssetImporterEditor.cs +++ b/Editor/Mono/ImportSettings/AssetImporterEditor.cs @@ -14,7 +14,11 @@ public abstract class AssetImporterEditor : Editor bool m_MightHaveModified = false; private Editor m_AssetEditor; - internal Editor assetEditor { private get { return m_AssetEditor; } set { m_AssetEditor = value; } } + // Called from ActiveEditorTracker.cpp to setup the target editor once created before Awake and OnEnable of the Editor. + internal void InternalSetAssetImporterTargetEditor(Object editor) + { + m_AssetEditor = editor as Editor; + } protected internal Object[] assetTargets { get { return m_AssetEditor != null ? m_AssetEditor.targets : null; } } protected internal Object assetTarget { get { return m_AssetEditor != null ? m_AssetEditor.target : null; } } @@ -24,7 +28,7 @@ internal override string targetTitle { get { - return string.Format(L10n.Tr("{0} Import Settings"), assetEditor == null ? string.Empty : assetEditor.targetTitle); + return string.Format(L10n.Tr("{0} Import Settings"), m_AssetEditor == null ? string.Empty : m_AssetEditor.targetTitle); } } @@ -34,8 +38,8 @@ internal override int referenceTargetIndex set { base.referenceTargetIndex = value; - if (assetEditor != null) - assetEditor.referenceTargetIndex = value; + if (m_AssetEditor != null) + m_AssetEditor.referenceTargetIndex = value; } } @@ -43,8 +47,8 @@ internal override IPreviewable preview { get { - if (useAssetDrawPreview && assetEditor != null) - return assetEditor; + if (useAssetDrawPreview && m_AssetEditor != null) + return m_AssetEditor; // Sometimes assetEditor has gone away because of "magical" workarounds and we need to fall back to base.Preview. // See cases 597496 and 601174 for context. return base.preview; @@ -58,8 +62,8 @@ internal override IPreviewable preview // Make the Importer use the icon of the asset internal override void OnHeaderIconGUI(Rect iconRect) { - if (assetEditor != null) - assetEditor.OnHeaderIconGUI(iconRect); + if (m_AssetEditor != null) + m_AssetEditor.OnHeaderIconGUI(iconRect); } // Let asset importers decide if the imported object should be shown as a separate editor or not @@ -241,7 +245,7 @@ protected virtual bool OnApplyRevertGUI() protected void ApplyRevertGUI() { - if (assetEditor == null || assetEditor.target == null) + if (m_AssetEditor == null || m_AssetEditor.target == null) { // always apply changes when buttons are hidden Apply(); diff --git a/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs b/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs index 0cf670f7b9..6e545dea41 100644 --- a/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs +++ b/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs @@ -353,6 +353,8 @@ public void Apply() (int)TextureImporterFormat.RGBAHalf, (int)TextureImporterFormat.BC4, (int)TextureImporterFormat.BC5, + (int)TextureImporterFormat.BC6H, + (int)TextureImporterFormat.BC7, (int)TextureImporterFormat.ASTC_RGB_4x4, (int)TextureImporterFormat.ASTC_RGB_5x5, diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index 347016f3e7..533ee228dc 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -405,7 +405,6 @@ protected virtual void OnGUI() s_CurrentInspectorWindow = this; Editor[] editors = tracker.activeEditors; - AssignAssetEditor(editors); Profiler.BeginSample("InspectorWindow.DrawEditors()"); DrawEditors(editors); Profiler.EndSample(); @@ -997,15 +996,6 @@ protected void DrawVCSShortInfoAsset(Asset asset, string tooltip, Rect rect, Tex EditorGUI.LabelField(textRect, content, styles.preToolbar2); } - protected void AssignAssetEditor(Editor[] editors) - { - // Assign asset editor to importer editor - if (editors.Length > 1 && editors[0] is AssetImporterEditor) - { - (editors[0] as AssetImporterEditor).assetEditor = editors[1]; - } - } - private void DrawEditors(Editor[] editors) { if (editors.Length == 0) diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 8488684de9..3dafc5ac64 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -2103,7 +2103,7 @@ private void OtherSectionOptimizationGUI(BuildTargetGroup targetGroup) static ApiCompatibilityLevel[] only_4_x_profiles = new ApiCompatibilityLevel[] { ApiCompatibilityLevel.NET_4_6, ApiCompatibilityLevel.NET_Standard_2_0 }; static ApiCompatibilityLevel[] only_2_0_profiles = new ApiCompatibilityLevel[] { ApiCompatibilityLevel.NET_2_0, ApiCompatibilityLevel.NET_2_0_Subset }; - static ApiCompatibilityLevel[] allProfiles = new ApiCompatibilityLevel[] { ApiCompatibilityLevel.NET_2_0, ApiCompatibilityLevel.NET_2_0_Subset, ApiCompatibilityLevel.NET_4_6, ApiCompatibilityLevel.NET_Standard_2_0 }; + static ApiCompatibilityLevel[] wsa_profiles = new ApiCompatibilityLevel[] { ApiCompatibilityLevel.NET_2_0, ApiCompatibilityLevel.NET_2_0_Subset, ApiCompatibilityLevel.NET_4_6 }; private ApiCompatibilityLevel[] GetAvailableApiCompatibilityLevels(BuildTargetGroup activeBuildTargetGroup) { @@ -2111,7 +2111,7 @@ private ApiCompatibilityLevel[] GetAvailableApiCompatibilityLevels(BuildTargetGr return only_4_x_profiles; if (activeBuildTargetGroup == BuildTargetGroup.WSA || activeBuildTargetGroup == BuildTargetGroup.XboxOne) - return allProfiles; + return wsa_profiles; return only_2_0_profiles; } diff --git a/Editor/Mono/Inspector/PreviewWindow.cs b/Editor/Mono/Inspector/PreviewWindow.cs index e10c28cd6f..2e0df95d37 100644 --- a/Editor/Mono/Inspector/PreviewWindow.cs +++ b/Editor/Mono/Inspector/PreviewWindow.cs @@ -53,7 +53,6 @@ protected override void OnGUI() Editor.m_AllowMultiObjectAccess = true; CreatePreviewables(); - AssignAssetEditor(tracker.activeEditors); // Do we have an editor that supports previews? Null if not. IPreviewable[] editorsWithPreviews = GetEditorsWithPreviews(tracker.activeEditors); diff --git a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs index 8771de7d30..6ade732b00 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs @@ -123,7 +123,7 @@ public bool Poll() processedAssemblies.Add(assembly, messagesList.ToArray()); if (!CompileErrors) - CompileErrors = messages.Any(m => m.type == CompilerMessageType.Error); + CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); compilerTasks.Remove(assembly); compiler.Dispose(); @@ -173,6 +173,16 @@ void QueuePendingAssemblies() if (!processedAssemblies.TryGetValue(reference, out messages)) { + // If a reference is not compiling and not pending + // also remove this assembly from pending. + if (!compilerTasks.ContainsKey(reference) && !pendingAssemblies.Contains(reference)) + { + if (removePendingAssemblies == null) + removePendingAssemblies = new List(); + + removePendingAssemblies.Add(pendingAssembly); + } + compileAssembly = false; break; } @@ -215,7 +225,8 @@ void QueuePendingAssemblies() // No assemblies to compile, need to wait for more references to finish compiling. if (assemblyCompileQueue == null) { - UnityEngine.Assertions.Assert.IsTrue(compilerTasks.Count > 0, "No pending assemblies queued for compilation and no compilers running. Compilation will never finish."); + if (compilerTasks.Count() == 0) + throw new Exception("No pending assemblies queued for compilation and no compilers running. Compilation will never finish."); return; } diff --git a/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs b/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs index 9c47f975d1..8d5d6bbb66 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs @@ -3,6 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.Collections.Generic; using System.Linq; using UnityEditor.Compilation; @@ -98,10 +99,13 @@ public AssemblyFlags AssemblyFlags } public static CustomScriptAssemblyPlatform[] Platforms { get; private set; } + public static CustomScriptAssemblyPlatform[] DeprecatedPlatforms { get; private set; } + public static CustomScriptOptinalUnityAssembly[] OptinalUnityAssemblies { get; private set; } static CustomScriptAssembly() { + // When removing a platform from Platforms, please add it to DeprecatedPlatforms. Platforms = new CustomScriptAssemblyPlatform[] { new CustomScriptAssemblyPlatform("Editor", "Editor", BuildTarget.NoTarget), @@ -114,8 +118,7 @@ static CustomScriptAssembly() new CustomScriptAssemblyPlatform("iOS", BuildTarget.iOS), new CustomScriptAssemblyPlatform("Android", BuildTarget.Android), new CustomScriptAssemblyPlatform("WebGL", BuildTarget.WebGL), - new CustomScriptAssemblyPlatform("WSA", "Windows Store App", BuildTarget.WSAPlayer), - new CustomScriptAssemblyPlatform("Tizen", BuildTarget.Tizen), + new CustomScriptAssemblyPlatform("WSA", "Universal Windows Platform", BuildTarget.WSAPlayer), new CustomScriptAssemblyPlatform("PSVita", BuildTarget.PSP2), new CustomScriptAssemblyPlatform("PS4", BuildTarget.PS4), new CustomScriptAssemblyPlatform("XboxOne", BuildTarget.XboxOne), @@ -124,6 +127,15 @@ static CustomScriptAssembly() new CustomScriptAssemblyPlatform("Switch", BuildTarget.Switch), }; +#pragma warning disable 0618 + DeprecatedPlatforms = new CustomScriptAssemblyPlatform[] + { + new CustomScriptAssemblyPlatform("PSMobile", BuildTarget.PSM), + new CustomScriptAssemblyPlatform("Tizen", BuildTarget.Tizen), + new CustomScriptAssemblyPlatform("WiiU", BuildTarget.WiiU), + }; +#pragma warning restore 0618 + OptinalUnityAssemblies = new[] { new CustomScriptOptinalUnityAssembly("Test Assemblies", OptionalUnityReferences.TestAssemblies, "Predefined Assemblies (Assembly-CSharp.dll etc) will not reference this assembly.\nThis assembly will only be used for tests and will not be included in player builds."), @@ -213,14 +225,39 @@ public static CustomScriptAssembly FromCustomScriptAssemblyData(string path, Cus } if (customScriptAssemblyData.includePlatforms != null && customScriptAssemblyData.includePlatforms.Length > 0) - customScriptAssembly.IncludePlatforms = customScriptAssemblyData.includePlatforms.Select(name => GetPlatformFromName(name)).ToArray(); + customScriptAssembly.IncludePlatforms = GetPlatformsFromNames(customScriptAssemblyData.includePlatforms); if (customScriptAssemblyData.excludePlatforms != null && customScriptAssemblyData.excludePlatforms.Length > 0) - customScriptAssembly.ExcludePlatforms = customScriptAssemblyData.excludePlatforms.Select(name => GetPlatformFromName(name)).ToArray(); + customScriptAssembly.ExcludePlatforms = GetPlatformsFromNames(customScriptAssemblyData.excludePlatforms); return customScriptAssembly; } + public static CustomScriptAssemblyPlatform[] GetPlatformsFromNames(string[] names) + { + var platforms = new List(); + + foreach (var name in names) + { + // Ignore deprecated platforms. + if (IsDeprecatedPlatformName(name)) + continue; + + platforms.Add(GetPlatformFromName(name)); + } + + return platforms.ToArray(); + } + + public static bool IsDeprecatedPlatformName(string name) + { + foreach (var platform in DeprecatedPlatforms) + if (string.Equals(platform.Name, name, System.StringComparison.OrdinalIgnoreCase)) + return true; + + return false; + } + public static CustomScriptAssemblyPlatform GetPlatformFromName(string name) { foreach (var platform in Platforms) diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index 492a737480..739c6039a3 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -151,6 +151,12 @@ public void DirtyScript(string path) dirtyScripts.Add(path); } + public void ClearDirtyScripts() + { + dirtyScripts.Clear(); + areAllScriptsDirty = false; + } + public void RunScriptUpdaterOnAssembly(string assemblyFilename) { runScriptUpdaterAssemblies.Add(assemblyFilename); @@ -761,7 +767,7 @@ internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, ScriptA if (!CopyAssembly(AssetPath.Combine(tempBuildDirectory, assembly.Filename), assembly.FullPath)) { messages.Add(new CompilerMessage { message = string.Format("Copying assembly from directory {0} to {1} failed", tempBuildDirectory, assembly.OutputDirectory), type = CompilerMessageType.Error, file = assembly.FullPath, line = -1, column = -1 }); - StopAllCompilation(); + StopCompilationTask(); InvokeAssemblyCompilationFinished(assemblyOutputPath, messages); return; } @@ -788,6 +794,11 @@ public void InvokeAssemblyCompilationFinished(string assemblyOutputPath, List 0) || dirtyScripts.Count > 0; @@ -898,11 +909,16 @@ public bool IsCompilationTaskCompiling() public void StopAllCompilation() { - if (compilationTask != null) - { - compilationTask.Stop(); - compilationTask = null; - } + StopCompilationTask(); + compilationTask = null; + } + + public void StopCompilationTask() + { + if (compilationTask == null) + return; + + compilationTask.Stop(); } internal static OptionalUnityReferences ToOptionalUnityReferences(EditorScriptCompilationOptions editorScriptCompilationOptions) diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs index 352158a9cf..4f0d730899 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs @@ -127,6 +127,12 @@ public static void DirtyScript(string path) Instance.DirtyScript(path); } + [RequiredByNativeCode] + public static void ClearDirtyScripts() + { + Instance.ClearDirtyScripts(); + } + [RequiredByNativeCode] public static void RunScriptUpdaterOnAssembly(string assemblyFilename) { @@ -205,6 +211,12 @@ public static bool DoesProjectFolderHaveAnyDirtyScripts() return Instance.DoesProjectFolderHaveAnyDirtyScripts(); } + [RequiredByNativeCode] + public static bool AreAllScriptsDirty() + { + return Instance.AreAllScriptsDirty(); + } + [RequiredByNativeCode] public static bool DoesProjectFolderHaveAnyScripts() { diff --git a/Editor/Mono/UIElements/VisualTreeAssetEditor.cs b/Editor/Mono/UIElements/VisualTreeAssetEditor.cs index c251f9ef18..c6f3f7842a 100644 --- a/Editor/Mono/UIElements/VisualTreeAssetEditor.cs +++ b/Editor/Mono/UIElements/VisualTreeAssetEditor.cs @@ -23,6 +23,12 @@ protected void OnEnable() m_FileTypeIcon = EditorGUIUtility.FindTexture("UxmlScript Icon"); } + protected void OnDestroy() + { + m_Panel = null; + UIElementsUtility.RemoveCachedPanel(m_LastTree.GetInstanceID()); + } + // hack to avoid null references when a scriptedImporter runs and replaces the current selection internal override string targetTitle { diff --git a/Modules/PackageManager/Editor/Managed/PackageInfo.cs b/Modules/PackageManager/Editor/Managed/PackageInfo.cs index 32cd9dbd8c..281a5676d7 100644 --- a/Modules/PackageManager/Editor/Managed/PackageInfo.cs +++ b/Modules/PackageManager/Editor/Managed/PackageInfo.cs @@ -64,7 +64,8 @@ internal PackageInfo( string tag = "", PackageStatus status = PackageStatus.Unavailable, IEnumerable errors = null, - VersionsInfo versions = null) + VersionsInfo versions = null, + string version = "") { // Set the default values m_OriginType = OriginType.Unknown; @@ -80,7 +81,7 @@ internal PackageInfo( // Populate name and version var nameAndVersion = packageId.Split('@'); m_Name = nameAndVersion[0]; - m_Version = nameAndVersion[1]; + m_Version = !string.IsNullOrEmpty(version) ? version : nameAndVersion[1]; } public string packageId { get { return m_PackageId; } } diff --git a/Modules/Profiler/Editor/ProfilerWindow/Chart.cs b/Modules/Profiler/Editor/ProfilerWindow/Chart.cs index 6b9d214f72..0fbf9bc343 100644 --- a/Modules/Profiler/Editor/ProfilerWindow/Chart.cs +++ b/Modules/Profiler/Editor/ProfilerWindow/Chart.cs @@ -66,6 +66,7 @@ static class Styles public GUIContent legendHeaderLabel { get; set; } public Vector2 labelRange { get; set; } + public Vector2 graphRange { get; set; } int m_DragItemIndex = -1; Vector2 m_DragDownPos; @@ -75,6 +76,7 @@ static class Styles public Chart() { labelRange = new Vector2(-Mathf.Infinity, Mathf.Infinity); + graphRange = new Vector2(-Mathf.Infinity, Mathf.Infinity); } private int MoveSelectedFrame(int selectedFrame, ChartViewData cdata, int direction) @@ -677,7 +679,7 @@ private void DrawChartItemLine(Rect r, ChartViewData cdata, int index) { m_LineDrawingPoints[i].Set( (series.xValues[i] - domain.x) * domainScale + r.x, - rectBottom - (series.yValues[i] - series.rangeAxis.x) * rangeScale, + rectBottom - (Mathf.Clamp(series.yValues[i], graphRange.x, graphRange.y) - series.rangeAxis.x) * rangeScale, 0f ); } diff --git a/Modules/Profiler/Editor/ProfilerWindow/ProfilerChart.cs b/Modules/Profiler/Editor/ProfilerWindow/ProfilerChart.cs index fdc71dfd03..6aaefcf91c 100644 --- a/Modules/Profiler/Editor/ProfilerWindow/ProfilerChart.cs +++ b/Modules/Profiler/Editor/ProfilerWindow/ProfilerChart.cs @@ -45,6 +45,7 @@ public bool active public ProfilerChart(ProfilerArea area, Chart.ChartType type, float dataScale, int seriesCount) : base() { labelRange = new Vector2(Mathf.Epsilon, Mathf.Infinity); + graphRange = new Vector2(Mathf.Epsilon, Mathf.Infinity); m_Area = area; m_Type = type; m_DataScale = dataScale; diff --git a/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameDataTreeView.cs b/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameDataTreeView.cs index f1821ffe27..488c41ecc1 100644 --- a/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameDataTreeView.cs +++ b/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameDataTreeView.cs @@ -144,13 +144,24 @@ void StoreExpandedState() public void SetSelectionFromLegacyPropertyPath(string selectedPropertyPath) { - if (string.IsNullOrEmpty(selectedPropertyPath)) + // if the path is the same as the current selection, don't change anything + if (m_SelectedItemMarkerIdPath != null && PropertyPathMatchesSelectedIDs(selectedPropertyPath, state.selectedIDs)) return; m_LegacySelectedItemMarkerNamePath = selectedPropertyPath; m_SelectedItemMarkerIdPath = null; } + private bool PropertyPathMatchesSelectedIDs(string legacyPropertyPath, List selectedIDs) + { + if (string.IsNullOrEmpty(legacyPropertyPath) || selectedIDs == null || selectedIDs.Count == 0) + { + return string.IsNullOrEmpty(legacyPropertyPath) && (selectedIDs == null || selectedIDs.Count == 0); + } + + return m_FrameDataView.GetItemPath(selectedIDs[0]) == legacyPropertyPath; + } + void StoreSelectedState() { if (m_SelectedItemMarkerIdPath != null || m_LegacySelectedItemMarkerNamePath != null) @@ -182,13 +193,14 @@ void MigrateExpandedState(List newExpandedIds) state.expandedIDs = newExpandedIds; } - void MigrateSelectedState() + void MigrateSelectedState(bool expandIfNecessary) { if (m_SelectedItemMarkerIdPath == null && m_LegacySelectedItemMarkerNamePath == null) return; // Find view id which corresponds to markerPath var newSelectedId = m_FrameDataView.GetRootItemID(); + bool selectedItemsPathIsExpanded = true; if (m_SelectedItemMarkerIdPath != null) { foreach (var marker in m_SelectedItemMarkerIdPath.Value.markerIds) @@ -198,6 +210,10 @@ void MigrateSelectedState() { if (marker == m_FrameDataView.GetItemMarkerID(childId)) { + // check if the parent is expanded + if (!IsExpanded(newSelectedId)) + selectedItemsPathIsExpanded = false; + newSelectedId = childId; break; } @@ -218,6 +234,10 @@ void MigrateSelectedState() { if (markerName == m_FrameDataView.GetItemFunctionName(childId)) { + // check if the parent is expanded + if (!IsExpanded(newSelectedId)) + selectedItemsPathIsExpanded = false; + newSelectedId = childId; markerIdPath.Add(m_FrameDataView.GetItemMarkerID(childId)); break; @@ -232,9 +252,12 @@ void MigrateSelectedState() m_LegacySelectedItemMarkerNamePath = null; } + var newSelection = (newSelectedId == 0) ? new List() : new List() { newSelectedId }; state.selectedIDs = newSelection; - FrameItem(newSelectedId); + + if (newSelectedId != 0 && isInitialized && (selectedItemsPathIsExpanded || expandIfNecessary)) + FrameItem(newSelectedId); } public IList GetSelectedInstanceIds() @@ -285,7 +308,7 @@ protected override IList BuildRows(TreeViewItem root) } MigrateExpandedState(newExpandedIds); - MigrateSelectedState(); + MigrateSelectedState(false); return m_Rows; } @@ -465,7 +488,7 @@ void OnSortingChanged(MultiColumnHeader header) public override void OnGUI(Rect rect) { if (m_LegacySelectedItemMarkerNamePath != null) - MigrateSelectedState(); + MigrateSelectedState(true); base.OnGUI(rect); } diff --git a/Modules/Profiler/Editor/ProfilerWindow/ProfilerWindow.cs b/Modules/Profiler/Editor/ProfilerWindow/ProfilerWindow.cs index 65939049de..d36e08a1c6 100644 --- a/Modules/Profiler/Editor/ProfilerWindow/ProfilerWindow.cs +++ b/Modules/Profiler/Editor/ProfilerWindow/ProfilerWindow.cs @@ -266,11 +266,15 @@ private static string[] ProfilerColumnNames(ProfilerColumn[] columns) const string kProfilerRecentSaveLoadProfilePath = "ProfilerRecentSaveLoadProfilePath"; const string kProfilerEnabledSessionKey = "ProfilerEnabled"; + internal delegate void SelectionChangedCallback(string selectedPropertyPath); + public event SelectionChangedCallback selectionChanged; + public void SetSelectedPropertyPath(string path) { if (ProfilerDriver.selectedPropertyPath != path) { ProfilerDriver.selectedPropertyPath = path; + selectionChanged.Invoke(path); UpdateCharts(); } } @@ -280,6 +284,7 @@ public void ClearSelectedPropertyPath() if (ProfilerDriver.selectedPropertyPath != string.Empty) { ProfilerDriver.selectedPropertyPath = string.Empty; + selectionChanged.Invoke(string.Empty); UpdateCharts(); } } @@ -372,12 +377,14 @@ void Initialize() m_CPUFrameDataHierarchyView.gpuView = false; m_CPUFrameDataHierarchyView.viewTypeChanged += CPUOrGPUViewTypeChanged; m_CPUFrameDataHierarchyView.selectionChanged += CPUOrGPUViewSelectionChanged; + selectionChanged += m_CPUFrameDataHierarchyView.SetSelectionFromLegacyPropertyPath; if (m_GPUFrameDataHierarchyView == null) m_GPUFrameDataHierarchyView = new ProfilerFrameDataHierarchyView(); m_GPUFrameDataHierarchyView.gpuView = true; m_GPUFrameDataHierarchyView.viewTypeChanged += CPUOrGPUViewTypeChanged; m_GPUFrameDataHierarchyView.selectionChanged += CPUOrGPUViewSelectionChanged; + selectionChanged += m_GPUFrameDataHierarchyView.SetSelectionFromLegacyPropertyPath; m_CPUTimelineGUI = new ProfilerTimelineGUI(this); m_CPUTimelineGUI.viewTypeChanged += CPUOrGPUViewTypeChanged; @@ -396,15 +403,7 @@ void CPUOrGPUViewSelectionChanged(int id) if (m_FrameDataView == null || !m_FrameDataView.IsValid()) return; - var ancestors = m_FrameDataView.GetItemAncestors(id); - var propertyPathBuilder = new StringBuilder(); - foreach (var ancestor in ancestors) - { - propertyPathBuilder.Append(m_FrameDataView.GetItemFunctionName(ancestor)); - propertyPathBuilder.Append('/'); - } - propertyPathBuilder.Append(m_FrameDataView.GetItemFunctionName(id)); - SetSelectedPropertyPath(propertyPathBuilder.ToString()); + SetSelectedPropertyPath(m_FrameDataView.GetItemPath(id)); } void CPUOrGPUViewTypeChanged(ProfilerViewType viewtype) @@ -412,9 +411,6 @@ void CPUOrGPUViewTypeChanged(ProfilerViewType viewtype) if (m_ViewType == viewtype) return; - if (m_ViewType == ProfilerViewType.Timeline) - m_CPUFrameDataHierarchyView.SetSelectionFromLegacyPropertyPath(ProfilerDriver.selectedPropertyPath); - m_ViewType = viewtype; } diff --git a/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs b/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs index 5e1b21b247..56f84d67e5 100644 --- a/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs +++ b/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Text; using UnityEngine.Bindings; using UnityEngine.Scripting.APIUpdating; @@ -185,6 +186,19 @@ public MarkerPath GetItemMarkerIDPath(int id) return new MarkerPath(markerIds); } + public string GetItemPath(int id) + { + var ancestors = GetItemAncestors(id); + var propertyPathBuilder = new StringBuilder(); + for (int i = ancestors.Length - 1; i >= 0; i--) + { + propertyPathBuilder.Append(GetItemFunctionName(ancestors[i])); + propertyPathBuilder.Append('/'); + } + propertyPathBuilder.Append(GetItemFunctionName(id)); + return propertyPathBuilder.ToString(); + } + public static extern UnityEngine.Color32 GetMarkerCategoryColor(int category); public bool IsValid() diff --git a/Modules/UIElements/Events/EventBase.cs b/Modules/UIElements/Events/EventBase.cs index b3b6f15038..a8f3779f6c 100644 --- a/Modules/UIElements/Events/EventBase.cs +++ b/Modules/UIElements/Events/EventBase.cs @@ -174,6 +174,8 @@ protected static void ReleasePooled(T evt) s_Pool.Release(evt); // To avoid double release from pool evt.flags &= ~EventFlags.Pooled; + // Set target to null before pooling to avoid leaking VisualElement + evt.target = null; } } diff --git a/Modules/UIElements/UIElementsUtility.cs b/Modules/UIElements/UIElementsUtility.cs index c441431131..49259ae6e6 100644 --- a/Modules/UIElements/UIElementsUtility.cs +++ b/Modules/UIElements/UIElementsUtility.cs @@ -81,6 +81,11 @@ private static bool ProcessEvent(int instanceID, IntPtr nativeEventPtr) return false; } + public static void RemoveCachedPanel(int instanceID) + { + s_UIElementsCache.Remove(instanceID); + } + private static void CleanupRoots() { // see GUI.CleanupRoots diff --git a/Modules/UIElements/UQuery.cs b/Modules/UIElements/UQuery.cs index 3c17139a8f..c122598613 100644 --- a/Modules/UIElements/UQuery.cs +++ b/Modules/UIElements/UQuery.cs @@ -80,7 +80,7 @@ public virtual void Run(VisualElement root, List matchers) private abstract class SingleQueryMatcher : UQueryMatcher { - public VisualElement match { get; protected set; } + public VisualElement match { get; set; } public override void Run(VisualElement root, List matchers) { @@ -484,14 +484,21 @@ public QueryState RebuildOn(VisualElement element) public T First() { s_First.Run(m_Element, m_Matchers); - return s_First.match as T; + + // We need to make sure we don't leak a ref to the VisualElement. + var match = s_First.match as T; + s_First.match = null; + return match; } public T Last() { s_Last.Run(m_Element, m_Matchers); - return s_Last.match as T; + // We need to make sure we don't leak a ref to the VisualElement. + var match = s_Last.match as T; + s_Last.match = null; + return match; } private class ListQueryMatcher : UQueryMatcher @@ -531,7 +538,10 @@ public T AtIndex(int index) s_Index.matchIndex = index; s_Index.Run(m_Element, m_Matchers); - return s_Index.match as T; + // We need to make sure we don't leak a ref to the VisualElement. + var match = s_Index.match as T; + s_Index.match = null; + return match; } //Convoluted trick so save on allocating memory for delegates or lambdas diff --git a/Modules/UnityAnalytics/UnityAnalytics.cs b/Modules/UnityAnalytics/UnityAnalytics.cs index bd884d0533..b509243af3 100644 --- a/Modules/UnityAnalytics/UnityAnalytics.cs +++ b/Modules/UnityAnalytics/UnityAnalytics.cs @@ -180,6 +180,28 @@ public static AnalyticsResult CustomEvent(string customEventName, IDictionary Date: Tue, 20 Feb 2018 23:19:54 +0000 Subject: [PATCH 07/17] Unity 2018.1.0b8 C# reference source code --- .../SpriteEditorModule/SpriteOutlineModule.cs | 42 +++-- .../SpritePhysicsShapeModule.cs | 15 +- Editor/Mono/AssetPostprocessor.cs | 30 ++++ Editor/Mono/Collab/Collab.bindings.cs | 26 +-- Editor/Mono/Collab/Collab.cs | 18 -- Editor/Mono/Collab/CollabHistoryWindow.cs | 63 +++---- .../Presenters/CollabHistoryPresenter.cs | 32 +++- Editor/Mono/Collab/RevisionsService.cs | 49 ++++-- Editor/Mono/EditorWindow.cs | 1 - .../TextureImporterInspector.cs | 12 +- .../AssemblyDefinitionImporterInspector.cs | 35 ++++ .../PlayerSettingsEditor.cs | 14 ++ .../Compilers/MicrosoftCSharpCompiler.cs | 4 +- .../Scripting/Compilers/MonoCSharpCompiler.cs | 8 +- .../Scripting/Compilers/ScriptCompilerBase.cs | 164 +++++++++++++++--- .../ScriptCompilation/AssemblyBuilder.cs | 2 + .../ScriptCompilation/CompilationPipeline.cs | 57 +++++- .../ScriptCompilation/CustomScriptAssembly.cs | 9 + .../ScriptCompilation/EditorBuildRules.cs | 74 +++++--- .../ScriptCompilation/EditorCompilation.cs | 30 +++- .../EditorCompilationInterface.cs | 27 ++- .../EditorScriptCompilationOptions.cs | 2 + .../ScriptCompilation/ScriptAssembly.cs | 16 +- Editor/Mono/Scripting/ScriptCompilers.cs | 7 +- Editor/Mono/SyncProject.cs | 2 +- .../SolutionSynchronizationSettings.cs | 23 ++- .../SolutionSynchronizer.cs | 79 ++++++--- .../CrashReporting/Managed/CrashReporting.cs | 6 +- .../Utils/VisualElementAttacher.cs | 45 +++-- .../GridEditor/Managed/GridEditorUtility.cs | 19 +- .../UISystem/UISystemProfilerTreeView.cs | 5 +- Modules/UIElements/EventDispatcher.cs | 34 ++-- Modules/UIElements/Events/LayoutEvents.cs | 6 +- Modules/UIElements/Panel.cs | 35 ++-- Modules/UIElements/ScrollView.cs | 13 +- Modules/UIElements/Slider.cs | 23 +-- README.md | 2 +- .../Editor/EditorUtilityBindings.gen.cs | 2 +- .../Editor/PlayerSettingsBindings.gen.cs | 10 ++ .../Editor/TextureImporterBindings.gen.cs | 8 + 40 files changed, 774 insertions(+), 275 deletions(-) diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs index 9754c7d5ae..04c1621953 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs @@ -182,7 +182,7 @@ internal class SpriteOutlineModule : SpriteEditorModuleBase { class Styles { - public GUIContent generateOutlineLabel = EditorGUIUtility.TrTextContent("Update", "Update new outline based on mesh detail value."); + public GUIContent generateOutlineLabel = EditorGUIUtility.TrTextContent("Generate", "Generate new outline based on mesh detail value."); public GUIContent outlineTolerance = EditorGUIUtility.TrTextContent("Outline Tolerance", "Sets how tight the outline should be from the sprite."); public GUIContent snapButtonLabel = EditorGUIUtility.TrTextContent("Snap", "Snap points to nearest pixel"); public GUIContent generatingOutlineDialogTitle = EditorGUIUtility.TrTextContent("Outline"); @@ -227,7 +227,7 @@ public SpriteOutlineModule(ISpriteEditor sem, IEventSystem es, IUndoSystem us, I public override string moduleName { - get { return "Edit Outline"; } + get { return "Custom Outline"; } } public override bool ApplyRevert(bool apply) @@ -614,7 +614,8 @@ public void SetupShapeEditor() if (m_Selected != null) { - SetupShapeEditorOutline(m_Selected); + if (!HasShapeOutline(m_Selected)) + SetupShapeEditorOutline(m_Selected); m_ShapeEditors = new ShapeEditor[selectedShapeOutline.Count]; for (int i = 0; i < selectedShapeOutline.Count; ++i) @@ -655,36 +656,33 @@ public void SetupShapeEditor() protected virtual bool HasShapeOutline(SpriteRect spriteRect) { var outline = m_Outline[spriteRect.spriteID]?.spriteOutlines; - return outline != null && outline.Count > 0; + return outline != null; } protected virtual void SetupShapeEditorOutline(SpriteRect spriteRect) { var outline = m_Outline[spriteRect.spriteID]; - if (outline.spriteOutlines == null || outline.spriteOutlines.Count == 0) + var outlines = GenerateSpriteRectOutline(spriteRect.rect, + Math.Abs(outline.tessellationDetail - (-1f)) < Mathf.Epsilon ? 0 : outline.tessellationDetail, + 0, m_TextureDataProvider); + if (outlines.Count == 0) { - var outlines = GenerateSpriteRectOutline(spriteRect.rect, - Math.Abs(outline.tessellationDetail - (-1f)) < Mathf.Epsilon ? 0 : outline.tessellationDetail, - 0, m_TextureDataProvider); - if (outlines.Count == 0) + Vector2 halfSize = spriteRect.rect.size * 0.5f; + outlines = new List() { - Vector2 halfSize = spriteRect.rect.size * 0.5f; - outlines = new List() + new SpriteOutline() { - new SpriteOutline() + m_Path = new List() { - m_Path = new List() - { - new Vector2(-halfSize.x, -halfSize.y), - new Vector2(-halfSize.x, halfSize.y), - new Vector2(halfSize.x, halfSize.y), - new Vector2(halfSize.x, -halfSize.y), - } + new Vector2(-halfSize.x, -halfSize.y), + new Vector2(-halfSize.x, halfSize.y), + new Vector2(halfSize.x, halfSize.y), + new Vector2(halfSize.x, -halfSize.y), } - }; - } - m_Outline[spriteRect.spriteID].spriteOutlines = outlines; + } + }; } + m_Outline[spriteRect.spriteID].spriteOutlines = outlines; } public Vector3 SnapPoint(Vector3 position) diff --git a/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs b/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs index 72b4046159..b2d6ef3ddd 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs @@ -26,7 +26,7 @@ public SpritePhysicsShapeModule(ISpriteEditor sem, IEventSystem ege, IUndoSystem public override string moduleName { - get { return "Edit Physics Shape"; } + get { return "Custom Physics Shape"; } } private ISpriteEditor spriteEditorWindow @@ -71,14 +71,11 @@ protected override void LoadOutline() protected override void SetupShapeEditorOutline(SpriteRect spriteRect) { var physicsShape = m_Outline[spriteRect.spriteID]; - if (physicsShape.spriteOutlines == null || physicsShape.spriteOutlines.Count == 0) - { - var physicsShapes = GenerateSpriteRectOutline(spriteRect.rect, - Math.Abs(physicsShape.tessellationDetail - (-1f)) < Mathf.Epsilon ? kDefaultPhysicsTessellationDetail : physicsShape.tessellationDetail, - kDefaultPhysicsAlphaTolerance, m_TextureDataProvider); - spriteEditorWindow.SetDataModified(); - m_Outline[spriteRect.spriteID].spriteOutlines = physicsShapes; - } + var physicsShapes = GenerateSpriteRectOutline(spriteRect.rect, + Math.Abs(physicsShape.tessellationDetail - (-1f)) < Mathf.Epsilon ? kDefaultPhysicsTessellationDetail : physicsShape.tessellationDetail, + kDefaultPhysicsAlphaTolerance, m_TextureDataProvider); + m_Outline[spriteRect.spriteID].spriteOutlines = physicsShapes; + spriteEditorWindow.SetDataModified(); } } } diff --git a/Editor/Mono/AssetPostprocessor.cs b/Editor/Mono/AssetPostprocessor.cs index c867f1c3c9..9597e764e4 100644 --- a/Editor/Mono/AssetPostprocessor.cs +++ b/Editor/Mono/AssetPostprocessor.cs @@ -55,6 +55,36 @@ static internal void CallOnGeneratedCSProjectFiles() } } + //This callback is used by C# code editors to modify the .sln file. + static internal string CallOnGeneratedSlnSolution(string path, string content) + { + foreach (var method in AllPostProcessorMethodsNamed("OnGeneratedSlnSolution")) + { + object[] args = { path, content }; + object returnValue = method.Invoke(null, args); + + if (method.ReturnType == typeof(string)) + content = (string)returnValue; + } + + return content; + } + + // This callback is used by C# code editors to modify the .csproj files. + static internal string CallOnGeneratedCSProject(string path, string content) + { + foreach (var method in AllPostProcessorMethodsNamed("OnGeneratedCSProject")) + { + object[] args = { path, content }; + object returnValue = method.Invoke(null, args); + + if (method.ReturnType == typeof(string)) + content = (string)returnValue; + } + + return content; + } + //This callback is used by UnityVS to take over project generation from unity static internal bool OnPreGeneratingCSProjectFiles() { diff --git a/Editor/Mono/Collab/Collab.bindings.cs b/Editor/Mono/Collab/Collab.bindings.cs index 3ce8cb4047..59a9428f6f 100644 --- a/Editor/Mono/Collab/Collab.bindings.cs +++ b/Editor/Mono/Collab/Collab.bindings.cs @@ -2,31 +2,21 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; +using UnityEngine; using UnityEngine.Bindings; +using UnityEngine.Scripting; namespace UnityEditor.Collaboration { - [NativeHeader("Editor/Src/Collab/CollabBindings.h")] + [NativeHeader("Editor/Src/Collab/Collab.h")] partial class Collab { - [NativeThrows] - [FreeFunction("GetRevisions")] - private static extern Revision[] InternalGetRevisions( - bool withChanges = false, int startIndex = 0, int numRevisions = -1); - - public Revision[] GetRevisions(bool withChanges = false, int startIndex = 0, int numRevisions = -1) - { - return InternalGetRevisions(withChanges, startIndex, numRevisions); - } - - [NativeThrows] - [FreeFunction("GetRevisionsData")] - private static extern RevisionsData InternalGetRevisionsData( + [StaticAccessor("Collab::Get()", StaticAccessorType.Arrow)] + public static extern int GetRevisionsData( bool withChanges, int startIndex, int numRevisions); - public RevisionsData GetRevisionsData(bool withChanges, int startIndex, int numRevisions) - { - return InternalGetRevisionsData(withChanges, startIndex, numRevisions); - } + [StaticAccessor("Collab::Get()", StaticAccessorType.Arrow)] + public static extern RevisionsData PopulateRevisionsData(IntPtr nativeData); } } diff --git a/Editor/Mono/Collab/Collab.cs b/Editor/Mono/Collab/Collab.cs index 17adb5c452..86c2210281 100644 --- a/Editor/Mono/Collab/Collab.cs +++ b/Editor/Mono/Collab/Collab.cs @@ -120,24 +120,6 @@ public static string GetProjectClientType() return string.IsNullOrEmpty(cvalue) ? clientType[0] : cvalue; } - [MenuItem("Window/Collab/Get Revisions", false, 1000, true)] - public static void TestGetRevisions() - { - Revision[] revisions = instance.GetRevisions(); - if (revisions.Length == 0) - { - Debug.Log("No revisions"); - return; - } - - int num = revisions.Length; - foreach (Revision revision in revisions) - { - Debug.Log("Revision #" + num + ": " + revision.revisionID); - num--; - } - } - public static Collab instance { get diff --git a/Editor/Mono/Collab/CollabHistoryWindow.cs b/Editor/Mono/Collab/CollabHistoryWindow.cs index 64cacc2e18..2ce8141e60 100644 --- a/Editor/Mono/Collab/CollabHistoryWindow.cs +++ b/Editor/Mono/Collab/CollabHistoryWindow.cs @@ -137,7 +137,7 @@ public void SetupGUI() var waitingView = new StatusView() { - message = "Connecting...", + message = "Updating...", }; var historyView = new ScrollView() { name = "HistoryContainer", showHorizontal = false}; @@ -182,38 +182,41 @@ public void UpdateRevisions(IEnumerable datas, string tip, int tot var isFullDateObtained = false; // Has everything from this date been obtained? m_HistoryItems.Clear(); - DateTime currentDate = DateTime.MinValue; - foreach (var data in datas) + if (datas != null) { - if (data.timeStamp.Date != currentDate.Date) + DateTime currentDate = DateTime.MinValue; + foreach (var data in datas) { - elements.Add(new CollabHistoryRevisionLine(data.timeStamp, isFullDateObtained)); - currentDate = data.timeStamp; + if (data.timeStamp.Date != currentDate.Date) + { + elements.Add(new CollabHistoryRevisionLine(data.timeStamp, isFullDateObtained)); + currentDate = data.timeStamp; + } + + var item = new CollabHistoryItem(data); + m_HistoryItems.Add(item); + + var container = new VisualContainer(); + container.style.flexDirection = FlexDirection.Row; + if (data.current) + { + isFullDateObtained = true; + container.AddToClassList("currentRevision"); + container.AddToClassList("obtainedRevision"); + } + else if (data.obtained) + { + container.AddToClassList("obtainedRevision"); + } + else + { + container.AddToClassList("absentRevision"); + } + // If we use the index as-is, the latest commit will become #1, but we want it to be last + container.Add(new CollabHistoryRevisionLine(data.index)); + container.Add(item); + elements.Add(container); } - - var item = new CollabHistoryItem(data); - m_HistoryItems.Add(item); - - var container = new VisualContainer(); - container.style.flexDirection = FlexDirection.Row; - if (data.current) - { - isFullDateObtained = true; - container.AddToClassList("currentRevision"); - container.AddToClassList("obtainedRevision"); - } - else if (data.obtained) - { - container.AddToClassList("obtainedRevision"); - } - else - { - container.AddToClassList("absentRevision"); - } - // If we use the index as-is, the latest commit will become #1, but we want it to be last - container.Add(new CollabHistoryRevisionLine(data.index)); - container.Add(item); - elements.Add(container); } m_Pager.totalItems = totalRevisions; diff --git a/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs b/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs index 44f947bcbd..c45321ec0c 100644 --- a/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs +++ b/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs @@ -2,6 +2,7 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System.Collections.Generic; using UnityEditor.Connect; using UnityEditor.Web; @@ -18,6 +19,8 @@ internal class CollabHistoryPresenter bool m_IsCollabError; int m_TotalRevisions; int m_CurrentPage; + bool m_FetchInProgress; + BuildAccess m_BuildAccess; string m_ProgressRevision; public bool BuildServiceEnabled {get; set; } @@ -40,12 +43,15 @@ public void OnWindowEnabled() Collab.instance.ErrorOccurred += OnCollabError; Collab.instance.ErrorCleared += OnCollabErrorCleared; EditorApplication.playModeStateChanged += OnPlayModeStateChanged; + m_Service.FetchRevisionsCallback += OnFetchRevisions; if (Collab.instance.IsConnected()) { m_ConnectState = UnityConnect.instance.GetConnectInfo(); - m_CollabState = Collab.instance.GetCollabInfo(); + // Copy the initialized fields of the collab info, even if the instance hasn't connected yet. } + // Copy the initialized fields of the collab info, even if the instance hasn't connected yet. + m_CollabState = Collab.instance.GetCollabInfo(); m_Window.revisionActionsEnabled = !EditorApplication.isPlayingOrWillChangePlaymode; @@ -176,7 +182,7 @@ private HistoryState RecalculateState() return HistoryState.NoSeat; if (!Collab.instance.IsCollabEnabledForCurrentProject()) return HistoryState.Disabled; - if (!Collab.instance.IsConnected() || !m_CollabState.ready) + if (!Collab.instance.IsConnected() || !m_CollabState.ready || m_FetchInProgress) return HistoryState.Waiting; if (m_ConnectState.error || m_IsCollabError) return HistoryState.Error; @@ -222,10 +228,24 @@ public void ShowServicePage() public void OnUpdatePage(int page) { - var revs = m_Service.GetRevisions(page * k_ItemsPerPage, k_ItemsPerPage); - m_TotalRevisions = revs.RevisionsInRepo; - var items = m_Factory.GenerateElements(revs.Revisions, m_TotalRevisions, page * k_ItemsPerPage, m_Service.tipRevision, m_Window.inProgressRevision, - m_Window.revisionActionsEnabled, BuildServiceEnabled, m_Service.currentUser); + m_FetchInProgress = true; + m_Service.GetRevisions(page * k_ItemsPerPage, k_ItemsPerPage); + m_Window.UpdateState(RecalculateState(), false); + m_CurrentPage = page; + } + + private void OnFetchRevisions(RevisionsResult data) + { + m_FetchInProgress = false; + IEnumerable items = null; + if (data != null) + { + m_TotalRevisions = data.RevisionsInRepo; + items = m_Factory.GenerateElements(data.Revisions, m_TotalRevisions, m_CurrentPage * k_ItemsPerPage, m_Service.tipRevision, m_Window.inProgressRevision, m_Window.revisionActionsEnabled, BuildServiceEnabled, m_Service.currentUser); + } + + // State must be recalculated prior to inserting items + m_Window.UpdateState(RecalculateState(), false); m_Window.UpdateRevisions(items, m_Service.tipRevision, m_TotalRevisions); } diff --git a/Editor/Mono/Collab/RevisionsService.cs b/Editor/Mono/Collab/RevisionsService.cs index 33636612f1..dcef43ec85 100644 --- a/Editor/Mono/Collab/RevisionsService.cs +++ b/Editor/Mono/Collab/RevisionsService.cs @@ -2,12 +2,16 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; using System.Collections.Generic; using UnityEditor.Collaboration; using UnityEditor.Connect; +using UnityEngine.Scripting; namespace UnityEditor.Collaboration { + delegate void RevisionsDelegate(RevisionsResult revisionsResult); + internal class RevisionsResult { public List Revisions = new List(); @@ -24,39 +28,52 @@ public void Clear() internal interface IRevisionsService { - RevisionsResult GetRevisions(int offset, int count); + event RevisionsDelegate FetchRevisionsCallback; + void GetRevisions(int offset, int count); string tipRevision { get; } string currentUser { get; } } internal class RevisionsService : IRevisionsService { + public event RevisionsDelegate FetchRevisionsCallback; protected Collab collab; protected UnityConnect connect; - protected RevisionsResult history; - protected int historyOffset = 0; + private static RevisionsService instance; + + public string tipRevision { get { return collab.collabInfo.tip; } } + public string currentUser { get { return connect.GetUserInfo().userName; } } public RevisionsService(Collab collabInstance, UnityConnect connectInstance) { collab = collabInstance; connect = connectInstance; - history = new RevisionsResult(); + instance = this; } - public RevisionsResult GetRevisions(int offset, int count) + public void GetRevisions(int offset, int count) { - // For now, clear out the local cache and just load what they ask for - history.Clear(); - // TODO: Handle exception if call fails - var data = collab.GetRevisionsData(true, offset, count); - history.Revisions.AddRange(data.Revisions); - history.RevisionsInRepo = data.RevisionsInRepo; - historyOffset = data.RevisionOffset; - - return history; + // Only send down request for the desired data. + Collab.GetRevisionsData(true, offset, count); } - public string tipRevision { get { return collab.collabInfo.tip; } } - public string currentUser { get { return connect.GetUserInfo().userName; } } + [RequiredByNativeCode] + private static void OnFetchRevisions(IntPtr nativeData) + { + RevisionsService service = instance; + if (service == null || service.FetchRevisionsCallback == null) + return; + + RevisionsResult history = null; + if (nativeData != IntPtr.Zero) + { + RevisionsData data = Collab.PopulateRevisionsData(nativeData); + history = new RevisionsResult(); + history.Revisions.AddRange(data.Revisions); + history.RevisionsInRepo = data.RevisionsInRepo; + } + + service.FetchRevisionsCallback(history); + } } } diff --git a/Editor/Mono/EditorWindow.cs b/Editor/Mono/EditorWindow.cs index f4d9893f8e..3868593e45 100644 --- a/Editor/Mono/EditorWindow.cs +++ b/Editor/Mono/EditorWindow.cs @@ -15,7 +15,6 @@ namespace UnityEditor [ExcludeFromObjectFactory] public partial class EditorWindow : ScriptableObject { - [SerializeField] [HideInInspector] bool m_AutoRepaintOnSceneChange; diff --git a/Editor/Mono/ImportSettings/TextureImporterInspector.cs b/Editor/Mono/ImportSettings/TextureImporterInspector.cs index a4d4b2d394..5637be2bb9 100644 --- a/Editor/Mono/ImportSettings/TextureImporterInspector.cs +++ b/Editor/Mono/ImportSettings/TextureImporterInspector.cs @@ -549,6 +549,7 @@ internal class Styles EditorGUIUtility.TrTextContent("Bottom Right"), EditorGUIUtility.TrTextContent("Custom"), }; + 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."); public readonly GUIContent alphaIsTransparency = EditorGUIUtility.TrTextContent("Alpha Is Transparency", "If the provided alpha channel is transparency, enable this to pre-filter the color to avoid texture filtering artifacts. This is not supported for HDR textures."); public readonly GUIContent etc1Compression = EditorGUIUtility.TrTextContent("Compress using ETC1 (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."); @@ -632,6 +633,7 @@ void EnumPopup(SerializedProperty property, System.Type type, GUIContent label) SerializedProperty m_SpriteMeshType; SerializedProperty m_Alignment; SerializedProperty m_SpritePivot; + SerializedProperty m_SpriteGenerateFallbackPhysicsShape; SerializedProperty m_AlphaIsTransparency; @@ -689,6 +691,7 @@ void CacheSerializedProperties() m_SpriteMeshType = serializedObject.FindProperty("m_SpriteMeshType"); m_Alignment = serializedObject.FindProperty("m_Alignment"); m_SpritePivot = serializedObject.FindProperty("m_SpritePivot"); + m_SpriteGenerateFallbackPhysicsShape = serializedObject.FindProperty("m_SpriteGenerateFallbackPhysicsShape"); m_AlphaIsTransparency = serializedObject.FindProperty("m_AlphaIsTransparency"); @@ -814,6 +817,7 @@ void SetSerializedPropertySettings(TextureImporterSettings settings) m_SpriteExtrude.intValue = (int)settings.spriteExtrude; m_SpriteMeshType.intValue = (int)settings.spriteMeshType; m_Alignment.intValue = settings.spriteAlignment; + m_SpriteGenerateFallbackPhysicsShape.intValue = settings.spriteGenerateFallbackPhysicsShape ? 1 : 0; m_WrapU.intValue = (int)settings.wrapMode; m_WrapV.intValue = (int)settings.wrapMode; @@ -908,6 +912,9 @@ internal TextureImporterSettings GetSerializedPropertySettings(TextureImporterSe if (!m_SpritePivot.hasMultipleDifferentValues) settings.spritePivot = m_SpritePivot.vector2Value; + if (!m_SpriteGenerateFallbackPhysicsShape.hasMultipleDifferentValues) + settings.spriteGenerateFallbackPhysicsShape = m_SpriteGenerateFallbackPhysicsShape.intValue > 0; + if (!m_WrapU.hasMultipleDifferentValues) settings.wrapModeU = (TextureWrapMode)m_WrapU.intValue; if (!m_WrapV.hasMultipleDifferentValues) @@ -1100,7 +1107,7 @@ private void SpriteGUI(TextureInspectorGUIElement guiElements) EditorGUILayout.IntSlider(m_SpriteExtrude, 0, 32, s_Styles.spriteExtrude); - if (m_SpriteMode.intValue == 1) + if (m_SpriteMode.intValue == (int)SpriteImportMode.Multiple) { EditorGUILayout.Popup(m_Alignment, s_Styles.spriteAlignmentOptions, s_Styles.spriteAlignment); @@ -1112,6 +1119,9 @@ private void SpriteGUI(TextureInspectorGUIElement guiElements) } } + if (m_SpriteMode.intValue != (int)SpriteImportMode.Polygon) + ToggleFromInt(m_SpriteGenerateFallbackPhysicsShape, s_Styles.spriteGenerateFallbackPhysicsShape); + using (new EditorGUI.DisabledScope(targets.Length != 1)) { GUILayout.BeginHorizontal(); diff --git a/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs b/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs index 9af9a83ca6..77fbe87c06 100644 --- a/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs +++ b/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs @@ -23,6 +23,8 @@ internal class Styles public static readonly GUIContent name = EditorGUIUtility.TrTextContent("Name"); public static readonly GUIContent unityReferences = EditorGUIUtility.TrTextContent("Unity References"); public static readonly GUIContent references = EditorGUIUtility.TrTextContent("References"); + public static readonly GUIContent options = EditorGUIUtility.TrTextContent("Options"); + public static readonly GUIContent allowUnsafeCode = EditorGUIUtility.TrTextContent("Allow 'unsafe' Code"); public static readonly GUIContent platforms = EditorGUIUtility.TrTextContent("Platforms"); public static readonly GUIContent anyPlatform = EditorGUIUtility.TrTextContent("Any Platform"); public static readonly GUIContent includePlatforms = EditorGUIUtility.TrTextContent("Include Platforms"); @@ -64,6 +66,7 @@ public string path public string name; public List references; public MixedBool[] optionalUnityReferences; + public MixedBool allowUnsafeCode; public MixedBool compatibleWithAnyPlatform; public MixedBool[] platformCompatibility; public bool modified; @@ -129,6 +132,12 @@ public override void OnInspectorGUI() EditorGUILayout.EndVertical(); GUILayout.Space(10f); + GUILayout.Label(Styles.options, EditorStyles.boldLabel); + EditorGUILayout.BeginVertical(GUI.skin.box); + m_State.allowUnsafeCode = ToggleWithMixedValue(Styles.allowUnsafeCode, m_State.allowUnsafeCode); + EditorGUILayout.EndVertical(); + GUILayout.Space(10f); + GUILayout.Label(Styles.platforms, EditorStyles.boldLabel); EditorGUILayout.BeginVertical(GUI.skin.box); var compatibleWithAnyPlatform = m_State.compatibleWithAnyPlatform; @@ -240,6 +249,19 @@ static void UpdatePlatformCompatibility(MixedBool compatibleWithAnyPlatform, Ass } } + static MixedBool ToMixedBool(bool value) + { + return value ? MixedBool.True : MixedBool.False; + } + + static bool ToBool(MixedBool value) + { + if (value == MixedBool.Mixed) + throw new System.ArgumentException("Cannot convert MixedBool.Mixed to bool"); + + return value == MixedBool.True; + } + static MixedBool ToggleWithMixedValue(GUIContent title, MixedBool value) { EditorGUI.showMixedValue = value == MixedBool.Mixed; @@ -312,6 +334,7 @@ void LoadAssemblyDefinitionFiles() m_State.name = m_TargetStates[0].name; m_State.references = new List(); m_State.modified = m_TargetStates[0].modified; + m_State.allowUnsafeCode = m_TargetStates[0].allowUnsafeCode; for (int i = 0; i < minReferencesCount; ++i) m_State.references.Add(m_TargetStates[0].references[i]); @@ -331,6 +354,12 @@ void LoadAssemblyDefinitionFiles() m_State.references[r].displayValue = MixedBool.Mixed; } + if (m_State.allowUnsafeCode != MixedBool.Mixed) + { + if (m_State.allowUnsafeCode != targetState.allowUnsafeCode) + m_State.allowUnsafeCode = MixedBool.Mixed; + } + m_State.modified |= targetState.modified; } @@ -409,6 +438,7 @@ static AssemblyDefintionState LoadAssemblyDefintionState(string path) state.asset = asset; state.name = data.name; state.references = new List(); + state.allowUnsafeCode = ToMixedBool(data.allowUnsafeCode); if (data.references != null) { @@ -511,6 +541,9 @@ static void SaveAndUpdateAssemblyDefinitionStates(AssemblyDefintionState combine foreach (var state in states) { + if (combinedState.allowUnsafeCode != MixedBool.Mixed) + state.allowUnsafeCode = combinedState.allowUnsafeCode; + for (int i = 0; i < combinedReferenceCount; ++i) { if (combinedState.references[i].displayValue != MixedBool.Mixed) @@ -559,6 +592,8 @@ static void SaveAssemblyDefinitionState(AssemblyDefintionState state) } data.optionalUnityReferences = optionalUnityReferences.ToArray(); + data.allowUnsafeCode = ToBool(state.allowUnsafeCode); + List dataPlatforms = new List(); for (int i = 0; i < platforms.Length; ++i) diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 3dafc5ac64..e0b2e996df 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -161,6 +161,7 @@ static class Styles public static readonly GUIContent apiCompatibilityLevel_NET_2_0_Subset = EditorGUIUtility.TrTextContent(".NET 2.0 Subset"); public static readonly GUIContent apiCompatibilityLevel_NET_4_6 = EditorGUIUtility.TrTextContent(".NET 4.x"); public static readonly GUIContent apiCompatibilityLevel_NET_Standard_2_0 = EditorGUIUtility.TrTextContent(".NET Standard 2.0"); + public static readonly GUIContent allowUnsafeCode = EditorGUIUtility.TrTextContent("Allow 'unsafe' Code", "Allow compilation of unsafe code for predefined assemblies (Assembly-CSharp.dll, etc.)"); public static readonly GUIContent activeInputHandling = EditorGUIUtility.TrTextContent("Active Input Handling*"); public static readonly GUIContent[] activeInputHandlingOptions = new GUIContent[] { EditorGUIUtility.TrTextContent("Input Manager"), EditorGUIUtility.TrTextContent("Input System (Preview)"), EditorGUIUtility.TrTextContent("Both") }; public static readonly GUIContent vrSettingsMoved = EditorGUIUtility.TrTextContent("Virtual Reality moved to XR Settings"); @@ -262,6 +263,8 @@ PlayerSettingsSplashScreenEditor splashScreenEditor SerializedProperty m_EnableInputSystem; SerializedProperty m_DisableInputManager; + SerializedProperty m_AllowUnsafeCode; + // vita SerializedProperty m_VideoMemoryForVertexBuffers; @@ -421,6 +424,8 @@ void OnEnable() m_EnableInputSystem = FindPropertyAssert("enableNativePlatformBackendsForNewInputSystem"); m_DisableInputManager = FindPropertyAssert("disableOldInputManagerSupport"); + m_AllowUnsafeCode = FindPropertyAssert("allowUnsafeCode"); + m_DefaultScreenWidth = FindPropertyAssert("defaultScreenWidth"); m_DefaultScreenHeight = FindPropertyAssert("defaultScreenHeight"); m_RunInBackground = FindPropertyAssert("runInBackground"); @@ -1998,6 +2003,15 @@ private void OtherSectionConfigurationGUI(BuildTargetGroup targetGroup, ISetting PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, scriptDefines); } + { + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(m_AllowUnsafeCode, Styles.allowUnsafeCode); + if (EditorGUI.EndChangeCheck()) + { + PlayerSettings.allowUnsafeCode = m_AllowUnsafeCode.boolValue; + } + } + // Active input handling int inputOption = (!m_EnableInputSystem.boolValue) ? 0 : m_DisableInputManager.boolValue ? 1 : 2; int oldInputOption = inputOption; diff --git a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs index 3fa7338e7d..47d137de6f 100644 --- a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs @@ -104,10 +104,12 @@ protected override Program StartCompiler() { "/target:library", "/nowarn:0169", - "/unsafe", "/out:" + outputPath }; + if (_island._allowUnsafeCode) + arguments.Add("/unsafe"); + if (!_island._development_player) { arguments.Add("/debug:pdbonly"); diff --git a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs index c858966c04..7397e9dbd3 100644 --- a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs @@ -31,9 +31,11 @@ override protected Program StartCompiler() "-langversion:" + ((EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) ? "6" : "4"), "-out:" + PrepareFileName(_island._output), "-nostdlib", - "-unsafe" }; + if (_island._allowUnsafeCode) + arguments.Add("-unsafe"); + if (!_island._development_player && !_island._editor) arguments.Add("-optimize"); @@ -75,9 +77,9 @@ protected override CompilerOutputParserBase CreateOutputParser() return new MonoCSharpCompilerOutputParser(); } - public static string[] Compile(string[] sources, string[] references, string[] defines, string outputFile) + public static string[] Compile(string[] sources, string[] references, string[] defines, string outputFile, bool allowUnsafeCode) { - var island = new MonoIsland(BuildTarget.StandaloneWindows, ApiCompatibilityLevel.NET_2_0_Subset, sources, references, defines, outputFile); + var island = new MonoIsland(BuildTarget.StandaloneWindows, ApiCompatibilityLevel.NET_2_0_Subset, allowUnsafeCode, sources, references, defines, outputFile); using (var c = new MonoCSharpCompiler(island, false)) { c.BeginCompiling(); diff --git a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs index 3ebb033cdc..a013f6ae4a 100644 --- a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs @@ -13,6 +13,28 @@ namespace UnityEditor.Scripting.Compilers { internal abstract class ScriptCompilerBase : IDisposable { + public class ResponseFileData + { + public class Reference + { + public String Alias; + public String Assembly; + } + + public string[] Defines; + public Reference[] References; + public bool Unsafe; + public string[] Errors; + } + + public class CompilerOption + { + public string Arg; + public string Value; + } + + static readonly char[] CompilerOptionArgumentSeperators = { ';', ',' }; + private Program process; private string _responseFile = null; private bool _runAPIUpdater; @@ -97,33 +119,31 @@ protected bool AddCustomResponseFileIfPresent(List arguments, string res return true; } - protected string GenerateResponseFile(List arguments) - { - _responseFile = CommandLineFormatter.GenerateResponseFile(arguments); - return _responseFile; - } - - public static string[] GetResponseFileDefinesFromFile(string responseFileName) + public static ResponseFileData ParseResponseFileFromFile(string responseFileName) { var relativeCustomResponseFilePath = Path.Combine("Assets", responseFileName); if (!File.Exists(relativeCustomResponseFilePath)) - return new string[0]; + { + var empty = new ResponseFileData + { + Defines = new string[0], + References = new ResponseFileData.Reference[0], + Unsafe = false, + Errors = new string[0] + }; + + return empty; + } var responseFileText = File.ReadAllText(relativeCustomResponseFilePath); - return GetResponseFileDefinesFromText(responseFileText); + return ParseResponseFileText(responseFileText); } - public static string[] GetResponseFileDefinesFromText(string responseFileText) + public static ResponseFileData ParseResponseFileText(string responseFileText) { - const string defineString = "-define:"; - var defineStringLength = defineString.Length; - - if (!responseFileText.Contains(defineString)) - return new string[0]; - - List result = new List(); + var compilerOptions = new List(); var textLines = responseFileText.Split(' ', '\n'); @@ -131,15 +151,115 @@ public static string[] GetResponseFileDefinesFromText(string responseFileText) { var trimmedLine = line.Trim(); - if (trimmedLine.StartsWith(defineString)) + int idx = trimmedLine.IndexOf(':'); + string arg, value; + + if (idx == -1) + { + arg = trimmedLine; + value = ""; + } + else + { + arg = trimmedLine.Substring(0, idx); + value = trimmedLine.Substring(idx + 1); + } + + if (!string.IsNullOrEmpty(arg) && arg[0] == '-') + arg = '/' + arg.Substring(1); + + compilerOptions.Add(new CompilerOption { Arg = arg, Value = value }); + } + + var defines = new List(); + var references = new List(); + bool unsafeDefined = false; + var errors = new List(); + + foreach (var option in compilerOptions) + { + var arg = option.Arg; + var value = option.Value; + + switch (arg) { - var definesSubString = trimmedLine.Substring(defineStringLength); - var defines = definesSubString.Split(',', ';'); - result.AddRange(defines); + case "/d": + case "/define": + { + if (value.Length == 0) + { + errors.Add("No value set for define"); + break; + } + + var defs = value.Split(CompilerOptionArgumentSeperators); + foreach (string define in defs) + defines.Add(define.Trim()); + } + break; + + case "/r": + case "/reference": + { + if (value.Length == 0) + { + errors.Add("No value set for reference"); + break; + } + + string[] refs = value.Split(CompilerOptionArgumentSeperators); + + if (refs.Length != 1) + { + errors.Add("Cannot specify multiple aliases using single /reference option"); + break; + } + + foreach (string reference in refs) + { + if (reference.Length == 0) + continue; + + int index = reference.IndexOf('='); + if (index > -1) + { + string alias = reference.Substring(0, index); + string assembly = reference.Substring(index + 1); + + references.Add(new ResponseFileData.Reference { Alias = alias, Assembly = assembly }); + } + else + { + references.Add(new ResponseFileData.Reference { Alias = string.Empty, Assembly = reference }); + } + } + } + break; + + case "/unsafe": + case "/unsafe+": + { + unsafeDefined = true; + } + break; + + case "/unsafe-": + { + unsafeDefined = false; + } + break; } } - return result.ToArray(); + var responseFileData = new ResponseFileData + { + Defines = defines.ToArray(), + References = references.ToArray(), + Unsafe = unsafeDefined, + Errors = errors.ToArray() + }; + + return responseFileData; } protected static string PrepareFileName(string fileName) diff --git a/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs b/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs index cf0b7ae8b8..9e045b8d63 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs @@ -33,6 +33,7 @@ public class AssemblyBuilder public string[] additionalDefines { get; set; } public string[] additionalReferences { get; set; } public string[] excludeReferences { get; set; } + public ScriptCompilerOptions compilerOptions { get; set; } public AssemblyBuilderFlags flags { get; set; } public BuildTargetGroup buildTargetGroup { get; set; } @@ -51,6 +52,7 @@ public AssemblyBuilder(string assemblyPath, params string[] scriptPaths) this.scriptPaths = scriptPaths; this.assemblyPath = assemblyPath; + compilerOptions = new ScriptCompilerOptions(); flags = AssemblyBuilderFlags.None; buildTargetGroup = EditorUserBuildSettings.activeBuildTargetGroup; buildTarget = EditorUserBuildSettings.activeBuildTarget; diff --git a/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs b/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs index f95470f3f1..b249d59b18 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs @@ -17,6 +17,16 @@ public enum AssemblyFlags EditorAssembly = (1 << 0) } + public class ScriptCompilerOptions + { + public bool AllowUnsafeCode { get; set; } + + public ScriptCompilerOptions() + { + AllowUnsafeCode = false; + } + } + public class Assembly { public string name { get; private set; } @@ -26,10 +36,36 @@ public class Assembly public Assembly[] assemblyReferences { get; private set; } public string[] compiledAssemblyReferences { get; private set; } public AssemblyFlags flags { get; private set; } + public ScriptCompilerOptions compilerOptions { get; private set; } public string[] allReferences { get { return assemblyReferences.Select(a => a.outputPath).Concat(compiledAssemblyReferences).ToArray(); } } - public Assembly(string name, string outputPath, string[] sourceFiles, string[] defines, Assembly[] assemblyReferences, string[] compiledAssemblyReferences, AssemblyFlags flags) + public Assembly(string name, + string outputPath, + string[] sourceFiles, + string[] defines, + Assembly[] assemblyReferences, + string[] compiledAssemblyReferences, + AssemblyFlags flags) + : this(name, + outputPath, + sourceFiles, + defines, + assemblyReferences, + compiledAssemblyReferences, + flags, + new ScriptCompilerOptions()) + { + } + + public Assembly(string name, + string outputPath, + string[] sourceFiles, + string[] defines, + Assembly[] assemblyReferences, + string[] compiledAssemblyReferences, + AssemblyFlags flags, + ScriptCompilerOptions compilerOptions) { this.name = name; this.outputPath = outputPath; @@ -38,6 +74,7 @@ public Assembly(string name, string outputPath, string[] sourceFiles, string[] d this.assemblyReferences = assemblyReferences; this.compiledAssemblyReferences = compiledAssemblyReferences; this.flags = flags; + this.compilerOptions = compilerOptions; } } @@ -98,7 +135,8 @@ internal static void SubscribeToEvents(EditorCompilation editorCompilation) public static Assembly[] GetAssemblies() { - return GetAssemblies(EditorCompilationInterface.Instance); + var options = EditorCompilationInterface.GetAdditionalEditorScriptCompilationOptions(); + return GetAssemblies(EditorCompilationInterface.Instance, options); } public static string GetAssemblyNameFromScriptPath(string sourceFilePath) @@ -127,9 +165,9 @@ public static AssemblyDefinitionPlatform[] GetAssemblyDefinitionPlatforms() return assemblyDefinitionPlatforms; } - internal static Assembly[] GetAssemblies(EditorCompilation editorCompilation) + internal static Assembly[] GetAssemblies(EditorCompilation editorCompilation, EditorScriptCompilationOptions additionalOptions) { - var scriptAssemblies = editorCompilation.GetAllEditorScriptAssemblies(); + var scriptAssemblies = editorCompilation.GetAllEditorScriptAssemblies(additionalOptions); var assemblies = new Assembly[scriptAssemblies.Length]; var scriptAssemblyToAssembly = new Dictionary(); @@ -153,7 +191,16 @@ internal static Assembly[] GetAssemblies(EditorCompilation editorCompilation) if ((scriptAssembly.Flags & sc.AssemblyFlags.EditorOnly) == sc.AssemblyFlags.EditorOnly) flags |= AssemblyFlags.EditorAssembly; - assemblies[i] = new Assembly(name, outputPath, sourceFiles, defines, assemblyReferences, compiledAssemblyReferences, flags); + var compilerOptions = scriptAssembly.CompilerOptions; + + assemblies[i] = new Assembly(name, + outputPath, + sourceFiles, + defines, + assemblyReferences, + compiledAssemblyReferences, + flags, + compilerOptions); } return assemblies; diff --git a/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs b/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs index 8d5d6bbb66..2f66b460fa 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs @@ -18,6 +18,7 @@ class CustomScriptAssemblyData public string[] optionalUnityReferences; public string[] includePlatforms; public string[] excludePlatforms; + public bool allowUnsafeCode; public static CustomScriptAssemblyData FromJson(string json) { @@ -86,6 +87,7 @@ class CustomScriptAssembly public CustomScriptAssemblyPlatform[] ExcludePlatforms { get; set; } public EditorCompilation.PackageAssembly? PackageAssembly { get; set; } + public ScriptCompilerOptions CompilerOptions { get; set; } public AssemblyFlags AssemblyFlags { @@ -199,6 +201,7 @@ public static CustomScriptAssembly Create(string name, string directory) customScriptAssembly.FilePath = modifiedDirectory; customScriptAssembly.PathPrefix = modifiedDirectory; customScriptAssembly.References = new string[0]; + customScriptAssembly.CompilerOptions = new ScriptCompilerOptions(); return customScriptAssembly; } @@ -230,6 +233,12 @@ public static CustomScriptAssembly FromCustomScriptAssemblyData(string path, Cus if (customScriptAssemblyData.excludePlatforms != null && customScriptAssemblyData.excludePlatforms.Length > 0) customScriptAssembly.ExcludePlatforms = GetPlatformsFromNames(customScriptAssemblyData.excludePlatforms); + var compilerOptions = new ScriptCompilerOptions(); + + compilerOptions.AllowUnsafeCode = customScriptAssemblyData.allowUnsafeCode; + + customScriptAssembly.CompilerOptions = compilerOptions; + return customScriptAssembly; } diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs index 58e462867d..c678da6663 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using UnityEditor.Compilation; using UnityEditor.Scripting.Compilers; using File = System.IO.File; @@ -37,19 +38,20 @@ internal class TargetAssembly public List References { get; private set; } public TargetAssemblyType Type { get; private set; } public OptionalUnityReferences OptionalUnityReferences { get; set; } + public ScriptCompilerOptions CompilerOptions { get; set; } public TargetAssembly() { References = new List(); } - public TargetAssembly(string name, SupportedLanguage language, AssemblyFlags flags, TargetAssemblyType type) - : this(name, language, flags, type, null, null) - { - } - - public TargetAssembly(string name, SupportedLanguage language, AssemblyFlags flags, TargetAssemblyType type, - Func pathFilter, Func compatFunc) : this() + public TargetAssembly(string name, + SupportedLanguage language, + AssemblyFlags flags, + TargetAssemblyType type, + Func pathFilter, + Func compatFunc, + ScriptCompilerOptions compilerOptions) : this() { Language = language; Filename = name; @@ -57,6 +59,7 @@ public TargetAssembly(string name, SupportedLanguage language, AssemblyFlags fla PathFilter = pathFilter; IsCompatibleFunc = compatFunc; Type = type; + CompilerOptions = compilerOptions; } public string FilenameWithSuffix(string filenameSuffix) @@ -169,9 +172,13 @@ public static TargetAssembly[] CreateTargetAssemblies(IEnumerable path.StartsWith(pathPrefixLowerCase) ? pathPrefixLowerCase.Length : -1, - (BuildTarget target, EditorScriptCompilationOptions options) => customAssembly.IsCompatibleWith(target, options)) + var targetAssembly = new TargetAssembly(customAssembly.Name + ".dll", + null, + customAssembly.AssemblyFlags, + TargetAssemblyType.Custom, + path => path.StartsWith(pathPrefixLowerCase) ? pathPrefixLowerCase.Length : -1, + (BuildTarget target, EditorScriptCompilationOptions options) => customAssembly.IsCompatibleWith(target, options), + customAssembly.CompilerOptions) { OptionalUnityReferences = customAssembly.OptionalUnityReferences, }; @@ -417,6 +424,11 @@ internal static ScriptAssembly[] ToScriptAssemblies(IDictionary(); + var scriptCompilerOptions = new ScriptCompilerOptions(); + // Initialize predefined assembly targets foreach (var language in supportedLanguages) { var languageName = language.GetLanguageName(); - var runtimeFirstPass = new TargetAssembly("Assembly-" + languageName + "-firstpass" + ".dll", language, - AssemblyFlags.FirstPass, TargetAssemblyType.Predefined, FilterAssemblyInFirstpassFolder, null); - - var runtime = new TargetAssembly("Assembly-" + languageName + ".dll", language, AssemblyFlags.None, TargetAssemblyType.Predefined); - - var editorFirstPass = new TargetAssembly("Assembly-" + languageName + "-Editor-firstpass" + ".dll", language, - AssemblyFlags.EditorOnly | AssemblyFlags.FirstPass, TargetAssemblyType.Predefined, FilterAssemblyInFirstpassEditorFolder, - IsCompatibleWithEditor) + var runtimeFirstPass = new TargetAssembly("Assembly-" + languageName + "-firstpass" + ".dll", + language, + AssemblyFlags.FirstPass, + TargetAssemblyType.Predefined, + FilterAssemblyInFirstpassFolder, + null, + scriptCompilerOptions); + + var runtime = new TargetAssembly("Assembly-" + languageName + ".dll", + language, + AssemblyFlags.None, + TargetAssemblyType.Predefined, + null, + null, + scriptCompilerOptions); + + var editorFirstPass = new TargetAssembly("Assembly-" + languageName + "-Editor-firstpass" + ".dll", + language, + AssemblyFlags.EditorOnly | AssemblyFlags.FirstPass, + TargetAssemblyType.Predefined, + FilterAssemblyInFirstpassEditorFolder, + IsCompatibleWithEditor, + scriptCompilerOptions) { OptionalUnityReferences = OptionalUnityReferences.TestAssemblies, }; - var editor = new TargetAssembly("Assembly-" + languageName + "-Editor" + ".dll", language, - AssemblyFlags.EditorOnly, TargetAssemblyType.Predefined, FilterAssemblyInEditorFolder, IsCompatibleWithEditor) + var editor = new TargetAssembly("Assembly-" + languageName + "-Editor" + ".dll", + language, + AssemblyFlags.EditorOnly, + TargetAssemblyType.Predefined, + FilterAssemblyInEditorFolder, + IsCompatibleWithEditor, + scriptCompilerOptions) { OptionalUnityReferences = OptionalUnityReferences.TestAssemblies, }; diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index 739c6039a3..aa9e6df773 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Runtime.InteropServices; using UnityEditor.Modules; +using UnityEditor.Compilation; using UnityEditor.Scripting.Compilers; using UnityEditorInternal; using CompilerMessage = UnityEditor.Scripting.Compilers.CompilerMessage; @@ -747,6 +748,14 @@ internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, ScriptA if (messages.Any(m => m.type == CompilerMessageType.Error)) { + var errorMessages = messages.Where(m => m.type == CompilerMessageType.Error); + + // error CS0227: Unsafe code requires the `unsafe' command line option to be specified + if (errorMessages.Any(em => em.message.Contains("CS0227"))) + { + messages.Add(new CompilerMessage { message = "You can allow 'unsafe' code for Assembly Definition Files in the inspector and for predefined assemblies in player settings.", type = CompilerMessageType.Warning, file = assembly.FullPath, line = -1, column = -1 }); + } + InvokeAssemblyCompilationFinished(assemblyOutputPath, messages); return; } @@ -813,6 +822,11 @@ ScriptAssemblySettings CreateScriptAssemblySettings(BuildTargetGroup buildTarget { var defines = InternalEditorUtility.GetCompilationDefines(options, buildTargetGroup, buildTarget); + var predefinedAssembliesCompilerOptions = new ScriptCompilerOptions(); + + if ((options & EditorScriptCompilationOptions.BuildingPredefinedAssembliesAllowUnsafeCode) == EditorScriptCompilationOptions.BuildingPredefinedAssembliesAllowUnsafeCode) + predefinedAssembliesCompilerOptions.AllowUnsafeCode = true; + var settings = new ScriptAssemblySettings { BuildTarget = buildTarget, @@ -821,6 +835,7 @@ ScriptAssemblySettings CreateScriptAssemblySettings(BuildTargetGroup buildTarget Defines = defines, ApiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup), CompilationOptions = options, + PredefinedAssembliesCompilerOptions = predefinedAssembliesCompilerOptions, FilenameSuffix = assemblySuffix, OptionalUnityReferences = ToOptionalUnityReferences(options), }; @@ -995,16 +1010,16 @@ public TargetAssemblyInfo[] GetTargetAssemblies() return targetAssemblyInfo; } - public ScriptAssembly[] GetAllScriptAssembliesForLanguage() where T : SupportedLanguage + public ScriptAssembly[] GetAllScriptAssembliesForLanguage(EditorScriptCompilationOptions additionalOptions) where T : SupportedLanguage { var assemblies = GetAllScriptAssemblies(EditorScriptCompilationOptions.BuildingForEditor).Where(a => a.Language.GetType() == typeof(T)).ToArray(); return assemblies; } - public ScriptAssembly GetScriptAssemblyForLanguage(string assemblyNameOrPath) where T : SupportedLanguage + public ScriptAssembly GetScriptAssemblyForLanguage(string assemblyNameOrPath, EditorScriptCompilationOptions additionalOptions) where T : SupportedLanguage { var assemblyName = AssetPath.GetAssemblyNameWithoutExtension(assemblyNameOrPath); - var scriptAssemblies = GetAllScriptAssembliesForLanguage(); + var scriptAssemblies = GetAllScriptAssembliesForLanguage(additionalOptions); return scriptAssemblies.SingleOrDefault(a => String.Compare(assemblyName, AssetPath.GetAssemblyNameWithoutExtension(a.Filename), StringComparison.OrdinalIgnoreCase) == 0); } @@ -1030,9 +1045,9 @@ public EditorBuildRules.TargetAssembly GetTargetAssemblyDetails(string scriptPat return EditorBuildRules.GetTargetAssembly(scriptPath, projectDirectory, customTargetAssemblies); } - public ScriptAssembly[] GetAllEditorScriptAssemblies() + public ScriptAssembly[] GetAllEditorScriptAssemblies(EditorScriptCompilationOptions additionalOptions) { - return GetAllScriptAssemblies(EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies); + return GetAllScriptAssemblies(EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies | additionalOptions); } ScriptAssembly[] GetAllScriptAssemblies(EditorScriptCompilationOptions options) @@ -1070,9 +1085,9 @@ ScriptAssembly[] GetAllScriptAssembliesOfType(ScriptAssemblySettings settings, E return EditorBuildRules.GetAllScriptAssemblies(allScripts, projectDirectory, settings, assemblies, type); } - public MonoIsland[] GetAllMonoIslands() + public MonoIsland[] GetAllMonoIslands(EditorScriptCompilationOptions additionalOptions) { - return GetAllMonoIslands(unityAssemblies, precompiledAssemblies, EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies); + return GetAllMonoIslands(unityAssemblies, precompiledAssemblies, EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies | additionalOptions); } public MonoIsland[] GetAllMonoIslands(PrecompiledAssembly[] unityAssembliesArg, PrecompiledAssembly[] precompiledAssembliesArg, EditorScriptCompilationOptions options) @@ -1147,6 +1162,7 @@ public ScriptAssembly CreateScriptAssembly(Compilation.AssemblyBuilder assemblyB scriptAssembly.Filename = AssetPath.GetFileName(assemblyPath); scriptAssembly.OutputDirectory = AssetPath.GetDirectoryName(assemblyPath); scriptAssembly.Defines = defines; + scriptAssembly.CompilerOptions = assemblyBuilder.compilerOptions; scriptAssembly.ScriptAssemblyReferences = new ScriptAssembly[0]; var unityReferences = EditorBuildRules.GetUnityReferences(scriptAssembly, unityAssemblies, options); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs index 4f0d730899..3f03773bc3 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs @@ -5,6 +5,7 @@ using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; using System; using UnityEditor.Compilation; +using UnityEditor.Scripting.Compilers; using UnityEditorInternal; using System.Collections.Generic; @@ -274,7 +275,31 @@ public static EditorCompilation.TargetAssemblyInfo GetTargetAssembly(string scri [RequiredByNativeCode] public static MonoIsland[] GetAllMonoIslands() { - return Instance.GetAllMonoIslands(); + var options = GetAdditionalEditorScriptCompilationOptions(); + return Instance.GetAllMonoIslands(options); + } + + public static EditorScriptCompilationOptions GetAdditionalEditorScriptCompilationOptions() + { + var options = EditorScriptCompilationOptions.BuildingEmpty; + + if (PlayerSettings.allowUnsafeCode) + options |= EditorScriptCompilationOptions.BuildingPredefinedAssembliesAllowUnsafeCode; + + return options; + } + + public static ScriptAssembly[] GetAllScriptAssembliesForLanguage() where T : SupportedLanguage + { + var additionalOptions = GetAdditionalEditorScriptCompilationOptions(); + return Instance.GetAllScriptAssembliesForLanguage(additionalOptions); + } + + public static ScriptAssembly GetScriptAssemblyForLanguage(string assemblyNameOrPath) where T : SupportedLanguage + { + var additionalOptions = GetAdditionalEditorScriptCompilationOptions(); + + return Instance.GetScriptAssemblyForLanguage(assemblyNameOrPath, additionalOptions); } } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs index 5b56e0165b..54d00b3510 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs @@ -6,6 +6,7 @@ namespace UnityEditor.Scripting.ScriptCompilation { + // Keep in sync with EditorScriptCompilationOptions in native [Flags] enum EditorScriptCompilationOptions { @@ -16,5 +17,6 @@ enum EditorScriptCompilationOptions BuildingForIl2Cpp = 1 << 3, BuildingWithAsserts = 1 << 4, BuildingIncludingTestAssemblies = 1 << 5, + BuildingPredefinedAssembliesAllowUnsafeCode = (1 << 6) }; } diff --git a/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs b/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs index d1138753c2..f0c2448551 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs @@ -4,7 +4,7 @@ using System.Linq; using UnityEditor.Scripting.Compilers; - +using UnityEditor.Compilation; namespace UnityEditor.Scripting.ScriptCompilation { @@ -17,6 +17,8 @@ class ScriptAssemblySettings public string[] Defines { get; set; } public ApiCompatibilityLevel ApiCompatibilityLevel { get; set; } public EditorScriptCompilationOptions CompilationOptions { get; set; } + public ScriptCompilerOptions PredefinedAssembliesCompilerOptions { get; set; } + public OptionalUnityReferences OptionalUnityReferences { get; set; } public string FilenameSuffix { get; set; } @@ -24,6 +26,7 @@ public ScriptAssemblySettings() { BuildTarget = BuildTarget.NoTarget; BuildTargetGroup = BuildTargetGroup.Unknown; + PredefinedAssembliesCompilerOptions = new ScriptCompilerOptions(); } public bool BuildingForEditor @@ -51,6 +54,7 @@ class ScriptAssembly public string[] Defines { get; set; } public string[] Files { get; set; } public bool RunUpdater { get; set; } + public ScriptCompilerOptions CompilerOptions { get; set; } public string FullPath { get { return AssetPath.Combine(OutputDirectory, Filename); } } @@ -70,7 +74,15 @@ public MonoIsland ToMonoIsland(EditorScriptCompilationOptions options, string bu var outputPath = AssetPath.Combine(buildOutputDirectory, Filename); - return new MonoIsland(BuildTarget, buildingForEditor, developmentBuild, ApiCompatibilityLevel, Files, referencesArray, Defines, outputPath); + return new MonoIsland(BuildTarget, + buildingForEditor, + developmentBuild, + CompilerOptions.AllowUnsafeCode, + ApiCompatibilityLevel, + Files, + referencesArray, + Defines, + outputPath); } } } diff --git a/Editor/Mono/Scripting/ScriptCompilers.cs b/Editor/Mono/Scripting/ScriptCompilers.cs index d679ed97c0..37f02f9f16 100644 --- a/Editor/Mono/Scripting/ScriptCompilers.cs +++ b/Editor/Mono/Scripting/ScriptCompilers.cs @@ -23,17 +23,19 @@ internal struct MonoIsland public readonly BuildTarget _target; public readonly bool _development_player; public readonly bool _editor; + public readonly bool _allowUnsafeCode; public readonly ApiCompatibilityLevel _api_compatibility_level; public readonly string[] _files; public readonly string[] _references; public readonly string[] _defines; public readonly string _output; - public MonoIsland(BuildTarget target, ApiCompatibilityLevel api_compatibility_level, string[] files, string[] references, string[] defines, string output) + public MonoIsland(BuildTarget target, ApiCompatibilityLevel api_compatibility_level, bool allowUnsafeCode, string[] files, string[] references, string[] defines, string output) { _target = target; _development_player = false; _editor = false; + _allowUnsafeCode = allowUnsafeCode; _api_compatibility_level = api_compatibility_level; _files = files; _references = references; @@ -41,11 +43,12 @@ public MonoIsland(BuildTarget target, ApiCompatibilityLevel api_compatibility_le _output = output; } - public MonoIsland(BuildTarget target, bool editor, bool development_player, ApiCompatibilityLevel api_compatibility_level, string[] files, string[] references, string[] defines, string output) + public MonoIsland(BuildTarget target, bool editor, bool development_player, bool allowUnsafeCode, ApiCompatibilityLevel api_compatibility_level, string[] files, string[] references, string[] defines, string output) { _target = target; _development_player = development_player; _editor = editor; + _allowUnsafeCode = allowUnsafeCode; _api_compatibility_level = api_compatibility_level; _files = files; _references = references; diff --git a/Editor/Mono/SyncProject.cs b/Editor/Mono/SyncProject.cs index 58b99263ba..005f7ea16a 100644 --- a/Editor/Mono/SyncProject.cs +++ b/Editor/Mono/SyncProject.cs @@ -77,7 +77,7 @@ public static string FindBestVisualStudio() private static readonly SolutionSynchronizer Synchronizer; internal static Dictionary InstalledVisualStudios { get; private set; } - class SolutionSynchronizationSettings : DefaultSolutionSynchronizationSettings + internal class SolutionSynchronizationSettings : DefaultSolutionSynchronizationSettings { public override int VisualStudioVersion { diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs index 2e65382cfb..4759cfb1c6 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs @@ -87,7 +87,7 @@ public virtual string SolutionProjectConfigurationTemplate public virtual string GetProjectHeaderTemplate(ScriptingLanguage language) { - return string.Join("\r\n", new[] { + var header = new[] { @"", @"", @" ", @@ -116,7 +116,7 @@ public virtual string GetProjectHeaderTemplate(ScriptingLanguage language) @" prompt", @" 4", @" 0169", - @" true", + @" {12}", @" ", @" ", @" pdbonly", @@ -125,14 +125,20 @@ public virtual string GetProjectHeaderTemplate(ScriptingLanguage language) @" prompt", @" 4", @" 0169", - @" true", + @" {12}", @" ", @" ", + }; + + var systemReferences = new string[] { @" ", @" ", @" ", @" ", @" ", + }; + + var footer = new string[] { @" ", @" {3}", @" ", @@ -142,7 +148,16 @@ public virtual string GetProjectHeaderTemplate(ScriptingLanguage language) @" ", @" ", @"" - }); + }; + + string[] text; + + if (language == ScriptingLanguage.CSharp) + text = header.Concat(footer).ToArray(); + else + text = header.Concat(systemReferences).Concat(footer).ToArray(); + + return string.Join("\r\n", text); } public virtual string GetProjectFooterTemplate(ScriptingLanguage language) diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index 8e88e41260..da5ce40aff 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -198,6 +198,7 @@ public void Sync() SetupProjectSupportedExtensions(); bool externalCodeAlreadyGeneratedProjects = AssetPostprocessingInternal.OnPreGeneratingCSProjectFiles(); + if (!externalCodeAlreadyGeneratedProjects) { var scriptEditor = ScriptEditorUtility.GetScriptEditorFromPreferences(); @@ -206,25 +207,38 @@ public void Sync() if (scriptEditor == ScriptEditorUtility.ScriptEditor.SystemDefault || scriptEditor == ScriptEditorUtility.ScriptEditor.Other) return; - // Only synchronize islands that have associated source files and ones that we actually want in the project. - // This also filters out DLLs coming from .asmdef files in packages. - IEnumerable islands = EditorCompilationInterface.GetAllMonoIslands(). - Where(i => 0 < i._files.Length && i._files.Any(f => ShouldFileBePartOfSolution(f))); + GenerateAndWriteSolutionAndProjects(scriptEditor); + } + + AssetPostprocessingInternal.CallOnGeneratedCSProjectFiles(); + } + + internal void GenerateAndWriteSolutionAndProjects(ScriptEditorUtility.ScriptEditor scriptEditor) + { + // Only synchronize islands that have associated source files and ones that we actually want in the project. + // This also filters out DLLs coming from .asmdef files in packages. + IEnumerable islands = EditorCompilationInterface.GetAllMonoIslands(). + Where(i => 0 < i._files.Length && i._files.Any(f => ShouldFileBePartOfSolution(f))); - var allAssetProjectParts = GenerateAllAssetProjectParts(); + var allAssetProjectParts = GenerateAllAssetProjectParts(); - var responseFileDefines = ScriptCompilerBase.GetResponseFileDefinesFromFile(MonoCSharpCompiler.ReponseFilename); + var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ReponseFilename); - SyncSolution(islands); - var allProjectIslands = RelevantIslandsForMode(islands, ModeForCurrentExternalEditor()).ToList(); - foreach (MonoIsland island in allProjectIslands) - SyncProject(island, allAssetProjectParts, responseFileDefines, allProjectIslands); + var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile(Path.Combine(_projectDirectory, responseFilePath)); - if (scriptEditor == ScriptEditorUtility.ScriptEditor.VisualStudioCode) - WriteVSCodeSettingsFiles(); + if (responseFileData.Errors.Length > 0) + { + foreach (var error in responseFileData.Errors) + UnityEngine.Debug.LogErrorFormat("{0} Parse Error : {1}", responseFilePath, error); } - AssetPostprocessingInternal.CallOnGeneratedCSProjectFiles(); + SyncSolution(islands); + var allProjectIslands = RelevantIslandsForMode(islands, ModeForCurrentExternalEditor()).ToList(); + foreach (MonoIsland island in allProjectIslands) + SyncProject(island, allAssetProjectParts, responseFileData, allProjectIslands); + + if (scriptEditor == ScriptEditorUtility.ScriptEditor.VisualStudioCode) + WriteVSCodeSettingsFiles(); } Dictionary GenerateAllAssetProjectParts() @@ -271,9 +285,29 @@ Dictionary GenerateAllAssetProjectParts() return result; } - void SyncProject(MonoIsland island, Dictionary allAssetsProjectParts, string[] additionalDefines, List allProjectIslands) + void SyncProject(MonoIsland island, + Dictionary allAssetsProjectParts, + ScriptCompilerBase.ResponseFileData responseFileData, + List allProjectIslands) { - SyncFileIfNotChanged(ProjectFile(island), ProjectText(island, ModeForCurrentExternalEditor(), allAssetsProjectParts, additionalDefines, allProjectIslands)); + SyncProjectFileIfNotChanged(ProjectFile(island), ProjectText(island, ModeForCurrentExternalEditor(), allAssetsProjectParts, responseFileData, allProjectIslands)); + } + + static void SyncProjectFileIfNotChanged(string path, string newContents) + { + if (Path.GetExtension(path) == ".csproj") + { + newContents = AssetPostprocessingInternal.CallOnGeneratedCSProject(path, newContents); + } + + SyncFileIfNotChanged(path, newContents); + } + + static void SyncSolutionFileIfNotChanged(string path, string newContents) + { + newContents = AssetPostprocessingInternal.CallOnGeneratedSlnSolution(path, newContents); + + SyncFileIfNotChanged(path, newContents); } private static void SyncFileIfNotChanged(string filename, string newContents) @@ -310,9 +344,13 @@ static bool IsAdditionalInternalAssemblyReference(bool isBuildingEditorProject, return false; } - string ProjectText(MonoIsland island, Mode mode, Dictionary allAssetsProjectParts, string[] additionalDefines, List allProjectIslands) + string ProjectText(MonoIsland island, + Mode mode, + Dictionary allAssetsProjectParts, + ScriptCompilerBase.ResponseFileData responseFileData, + List allProjectIslands) { - var projectBuilder = new StringBuilder(ProjectHeader(island, additionalDefines)); + var projectBuilder = new StringBuilder(ProjectHeader(island, responseFileData.Defines)); var references = new List(); var projectReferences = new List(); Match match; @@ -348,7 +386,7 @@ string ProjectText(MonoIsland island, Mode mode, Dictionary allA var allAdditionalReferenceFilenames = new List(); - foreach (string reference in references.Union(island._references)) + foreach (string reference in references.Union(island._references).Union(responseFileData.References.Select(r => r.Assembly))) { if (reference.EndsWith("/UnityEditor.dll") || reference.EndsWith("/UnityEngine.dll") || reference.EndsWith("\\UnityEditor.dll") || reference.EndsWith("\\UnityEngine.dll")) continue; @@ -463,7 +501,8 @@ private string ProjectHeader(MonoIsland island, string[] additionalDefines) EditorSettings.projectGenerationRootNamespace, targetframeworkversion, targetLanguageVersion, - baseDirectory + baseDirectory, + island._allowUnsafeCode }; try @@ -478,7 +517,7 @@ private string ProjectHeader(MonoIsland island, string[] additionalDefines) private void SyncSolution(IEnumerable islands) { - SyncFileIfNotChanged(SolutionFile(), SolutionText(islands, ModeForCurrentExternalEditor())); + SyncSolutionFileIfNotChanged(SolutionFile(), SolutionText(islands, ModeForCurrentExternalEditor())); } private static Mode ModeForCurrentExternalEditor() diff --git a/Modules/CloudServicesSettingsEditor/CrashReporting/Managed/CrashReporting.cs b/Modules/CloudServicesSettingsEditor/CrashReporting/Managed/CrashReporting.cs index bc5697c4f1..24e47f0d34 100644 --- a/Modules/CloudServicesSettingsEditor/CrashReporting/Managed/CrashReporting.cs +++ b/Modules/CloudServicesSettingsEditor/CrashReporting/Managed/CrashReporting.cs @@ -168,9 +168,9 @@ public static void UploadSymbolsInPath(string authToken, string symbolPath, stri UseShellExecute = false }; - psi.EnvironmentVariables.Add("USYM_UPLOAD_AUTH_TOKEN", authToken); - psi.EnvironmentVariables.Add("USYM_UPLOAD_URL_SOURCE", SignedUrlSourceUrl); - psi.EnvironmentVariables.Add("LZMA_PATH", platformConfig.LzmaPath); + psi.EnvironmentVariables["USYM_UPLOAD_AUTH_TOKEN"] = authToken; + psi.EnvironmentVariables["USYM_UPLOAD_URL_SOURCE"] = SignedUrlSourceUrl; + psi.EnvironmentVariables["LZMA_PATH"] = platformConfig.LzmaPath; System.Diagnostics.Process nativeProgram = new System.Diagnostics.Process(); nativeProgram.StartInfo = psi; diff --git a/Modules/GraphViewEditor/Utils/VisualElementAttacher.cs b/Modules/GraphViewEditor/Utils/VisualElementAttacher.cs index 4437d1dd6d..ca2adcd864 100644 --- a/Modules/GraphViewEditor/Utils/VisualElementAttacher.cs +++ b/Modules/GraphViewEditor/Utils/VisualElementAttacher.cs @@ -64,15 +64,15 @@ public float distance private bool isAttached { - get { return target != null && element != null && m_CommonAncestor != null; } + get { return target != null && element != null && m_WatchedObjects != null && m_WatchedObjects.Count > 0; } } private Rect m_LastTargetWorldBounds = Rect.zero; private Rect m_ElementSize = Rect.zero; + private List m_WatchedObjects; private Vector2 m_Offset; private SpriteAlignment m_Alignment; private float m_Distance; - private VisualElement m_CommonAncestor; public Attacher(VisualElement anchored, VisualElement target, SpriteAlignment alignment) { @@ -99,39 +99,60 @@ public void Reattach() private void RegisterCallbacks() { - if (m_CommonAncestor != null) + if (m_WatchedObjects != null && m_WatchedObjects.Count > 0) { UnregisterCallbacks(); } - m_CommonAncestor = target.FindCommonAncestor(element); + VisualElement commonAncestor = target.FindCommonAncestor(element); - if (m_CommonAncestor == target) + if (commonAncestor == target) { Debug.Log("Attacher: Target is already parent of anchored element."); - m_CommonAncestor = null; } - else if (m_CommonAncestor == element) + else if (commonAncestor == element) { Debug.Log("Attacher: An element can't be anchored to one of its descendants"); - m_CommonAncestor = null; } - else if (m_CommonAncestor == null) + else if (commonAncestor == null) { Debug.Log("Attacher: The element and its target must be in the same visual tree hierarchy"); } else { - m_CommonAncestor.RegisterCallback(OnTargetLayout); + if (m_WatchedObjects == null) + m_WatchedObjects = new List(); + + VisualElement v = target; + + while (v != commonAncestor) + { + m_WatchedObjects.Add(v); + v.RegisterCallback(OnTargetLayout); + v = v.shadow.parent; + } + + v = element; + + while (v != commonAncestor) + { + m_WatchedObjects.Add(v); + v.RegisterCallback(OnTargetLayout); + v = v.shadow.parent; + } } } private void UnregisterCallbacks() { - if (m_CommonAncestor != null) + foreach (VisualElement v in m_WatchedObjects) { - m_CommonAncestor.UnregisterCallback(OnTargetLayout); + { + v.UnregisterCallback(OnTargetLayout); + } } + + m_WatchedObjects.Clear(); } private void OnTargetLayout(PostLayoutEvent evt) diff --git a/Modules/GridEditor/Managed/GridEditorUtility.cs b/Modules/GridEditor/Managed/GridEditorUtility.cs index bf1f5656ce..b882cb0f5a 100644 --- a/Modules/GridEditor/Managed/GridEditorUtility.cs +++ b/Modules/GridEditor/Managed/GridEditorUtility.cs @@ -314,12 +314,12 @@ public static Mesh GenerateCachedGridMesh(GridLayout gridLayout, Color color, fl vertices[vertex + 0] = gridLayout.CellToLocal(minPosition); vertices[vertex + 1] = gridLayout.CellToLocal(maxPosition); + uvs2[vertex + 0] = Vector2.zero; + uvs2[vertex + 1] = new Vector2(0f, cellStride.y * bounds.size.y); if (topology == MeshTopology.Quads) { vertices[vertex + 2] = gridLayout.CellToLocal(maxPosition) + horizontalPixelOffset; vertices[vertex + 3] = gridLayout.CellToLocal(minPosition) + horizontalPixelOffset; - uvs2[vertex + 0] = Vector2.zero; - uvs2[vertex + 1] = new Vector2(0f, cellStride.y * bounds.size.y); uvs2[vertex + 2] = new Vector2(0f, cellStride.y * bounds.size.y); uvs2[vertex + 3] = Vector2.zero; } @@ -327,12 +327,12 @@ public static Mesh GenerateCachedGridMesh(GridLayout gridLayout, Color color, fl vertices[vertex + 0] = gridLayout.CellToLocalInterpolated(minPosition + cellGap); vertices[vertex + 1] = gridLayout.CellToLocalInterpolated(maxPosition + cellGap); + uvs2[vertex + 0] = Vector2.zero; + uvs2[vertex + 1] = new Vector2(0f, cellStride.y * bounds.size.y); if (topology == MeshTopology.Quads) { vertices[vertex + 2] = gridLayout.CellToLocalInterpolated(maxPosition + cellGap) + horizontalPixelOffset; vertices[vertex + 3] = gridLayout.CellToLocalInterpolated(minPosition + cellGap) + horizontalPixelOffset; - uvs2[vertex + 0] = Vector2.zero; - uvs2[vertex + 1] = new Vector2(0f, cellStride.y * bounds.size.y); uvs2[vertex + 2] = new Vector2(0f, cellStride.y * bounds.size.y); uvs2[vertex + 3] = Vector2.zero; } @@ -354,12 +354,12 @@ public static Mesh GenerateCachedGridMesh(GridLayout gridLayout, Color color, fl vertices[vertex + 0] = gridLayout.CellToLocal(minPosition); vertices[vertex + 1] = gridLayout.CellToLocal(maxPosition); + uvs2[vertex + 0] = Vector2.zero; + uvs2[vertex + 1] = new Vector2(cellStride.x * bounds.size.x, 0f); if (topology == MeshTopology.Quads) { vertices[vertex + 2] = gridLayout.CellToLocal(maxPosition) + verticalPixelOffset; vertices[vertex + 3] = gridLayout.CellToLocal(minPosition) + verticalPixelOffset; - uvs2[vertex + 0] = Vector2.zero; - uvs2[vertex + 1] = new Vector2(cellStride.x * bounds.size.x, 0f); uvs2[vertex + 2] = new Vector2(cellStride.x * bounds.size.x, 0f); uvs2[vertex + 3] = Vector2.zero; } @@ -367,12 +367,12 @@ public static Mesh GenerateCachedGridMesh(GridLayout gridLayout, Color color, fl vertices[vertex + 0] = gridLayout.CellToLocalInterpolated(minPosition + cellGap); vertices[vertex + 1] = gridLayout.CellToLocalInterpolated(maxPosition + cellGap); + uvs2[vertex + 0] = Vector2.zero; + uvs2[vertex + 1] = new Vector2(cellStride.x * bounds.size.x, 0f); if (topology == MeshTopology.Quads) { vertices[vertex + 2] = gridLayout.CellToLocalInterpolated(maxPosition + cellGap) + verticalPixelOffset; vertices[vertex + 3] = gridLayout.CellToLocalInterpolated(minPosition + cellGap) + verticalPixelOffset; - uvs2[vertex + 0] = Vector2.zero; - uvs2[vertex + 1] = new Vector2(cellStride.x * bounds.size.x, 0f); uvs2[vertex + 2] = new Vector2(cellStride.x * bounds.size.x, 0f); uvs2[vertex + 3] = Vector2.zero; } @@ -392,8 +392,7 @@ public static Mesh GenerateCachedGridMesh(GridLayout gridLayout, Color color, fl mesh.vertices = vertices; mesh.uv = uvs; - if (topology == MeshTopology.Quads) - mesh.uv2 = uvs2; + mesh.uv2 = uvs2; mesh.colors = colors; mesh.SetIndices(indices, topology, 0); diff --git a/Modules/Profiler/Editor/ProfilerWindow/UISystem/UISystemProfilerTreeView.cs b/Modules/Profiler/Editor/ProfilerWindow/UISystem/UISystemProfilerTreeView.cs index c6300c2b5e..6003dee5c9 100644 --- a/Modules/Profiler/Editor/ProfilerWindow/UISystem/UISystemProfilerTreeView.cs +++ b/Modules/Profiler/Editor/ProfilerWindow/UISystem/UISystemProfilerTreeView.cs @@ -19,12 +19,14 @@ internal class UISystemProfilerTreeView : TreeView public ProfilerProperty property; private RootTreeViewItem m_AllCanvasesItem; + private GUIStyle lineStyle; public UISystemProfilerTreeView(State state, MultiColumnHeader multiColumnHeader) : base(state, multiColumnHeader) { m_Comparer = new CanvasBatchComparer(); showBorder = false; showAlternatingRowBackgrounds = true; + lineStyle = null; } public State profilerState @@ -108,7 +110,8 @@ protected override void RowGUI(RowGUIArgs args) Rect rect = args.GetCellRect(i); if (column == (int)Column.Element) { - GUIStyle lineStyle = DefaultStyles.label; + if (lineStyle == null) + lineStyle = new GUIStyle(DefaultStyles.label); rect.xMin += lineStyle.margin.left + GetContentIndent(args.item); int iconRectWidth = 16; diff --git a/Modules/UIElements/EventDispatcher.cs b/Modules/UIElements/EventDispatcher.cs index 819e2355d4..2c5da7bcc8 100644 --- a/Modules/UIElements/EventDispatcher.cs +++ b/Modules/UIElements/EventDispatcher.cs @@ -362,8 +362,8 @@ public void DispatchEvent(EventBase evt, IPanel panel) else if (evt is IPropagatableEvent || evt is IFocusEvent || evt is IChangeEvent || - evt.GetEventTypeId() == PostLayoutEvent.TypeId() || - evt.GetEventTypeId() == InputEvent.TypeId()) + evt.GetEventTypeId() == InputEvent.TypeId() || + evt.GetEventTypeId() == PostLayoutEvent.TypeId()) { Debug.Assert(evt.target != null); invokedHandleEvent = true; @@ -426,11 +426,14 @@ private static void PropagateEvent(EventBase evt) return; } - using (var paths = BuildPropagationPath(evt.target as VisualElement)) + PropagationPaths.Type pathTypesRequested = (evt.capturable ? PropagationPaths.Type.Capture : PropagationPaths.Type.None); + pathTypesRequested |= (evt.bubbles ? PropagationPaths.Type.BubbleUp : PropagationPaths.Type.None); + + using (var paths = BuildPropagationPath(evt.target as VisualElement, pathTypesRequested)) { evt.dispatch = true; - if (evt.capturable && paths.capturePath.Count > 0) + if (evt.capturable && paths != null && paths.capturePath.Count > 0) { // Phase 1: Capture phase // Propagate event from root to target.parent @@ -454,7 +457,7 @@ private static void PropagateEvent(EventBase evt) // Phase 3: bubble Up phase // Propagate event from target parent up to root - if (evt.bubbles && paths.bubblePath.Count > 0) + if (evt.bubbles && paths != null && paths.bubblePath.Count > 0) { evt.propagationPhase = PropagationPhase.BubbleUp; @@ -491,10 +494,17 @@ private static void ExecuteDefaultAction(EventBase evt) } private const int k_DefaultPropagationDepth = 16; - private static readonly PropagationPaths k_EmptyPropagationPaths = new PropagationPaths(0); - struct PropagationPaths : IDisposable + class PropagationPaths : IDisposable { + [Flags] + public enum Type + { + None = 0, + Capture = 1, + BubbleUp = 2 + } + public readonly List capturePath; public readonly List bubblePath; @@ -542,18 +552,18 @@ public static void Release(PropagationPaths po) } } - private static PropagationPaths BuildPropagationPath(VisualElement elem) + private static PropagationPaths BuildPropagationPath(VisualElement elem, PropagationPaths.Type pathTypesRequested) { - if (elem == null) - return k_EmptyPropagationPaths; + if (elem == null || pathTypesRequested == PropagationPaths.Type.None) + return null; var ret = PropagationPathsPool.Acquire(); while (elem.shadow.parent != null) { if (elem.shadow.parent.enabledInHierarchy) { - if (elem.shadow.parent.HasCaptureHandlers()) + if ((pathTypesRequested & PropagationPaths.Type.Capture) == PropagationPaths.Type.Capture && elem.shadow.parent.HasCaptureHandlers()) ret.capturePath.Add(elem.shadow.parent); - if (elem.shadow.parent.HasBubbleHandlers()) + if ((pathTypesRequested & PropagationPaths.Type.BubbleUp) == PropagationPaths.Type.BubbleUp && elem.shadow.parent.HasBubbleHandlers()) ret.bubblePath.Add(elem.shadow.parent); } elem = elem.shadow.parent; diff --git a/Modules/UIElements/Events/LayoutEvents.cs b/Modules/UIElements/Events/LayoutEvents.cs index 166fbe0601..fde6e36692 100644 --- a/Modules/UIElements/Events/LayoutEvents.cs +++ b/Modules/UIElements/Events/LayoutEvents.cs @@ -6,10 +6,12 @@ namespace UnityEngine.Experimental.UIElements { public class PostLayoutEvent : EventBase, IPropagatableEvent { - public static PostLayoutEvent GetPooled(bool hasNewLayout) + public static PostLayoutEvent GetPooled(bool hasNewLayout, Rect oldRect, Rect newRect) { PostLayoutEvent e = GetPooled(); e.hasNewLayout = hasNewLayout; + e.oldRect = oldRect; + e.newRect = newRect; return e; } @@ -20,6 +22,8 @@ protected override void Init() } public bool hasNewLayout { get; private set; } + public Rect oldRect { get; private set; } + public Rect newRect { get; private set; } public PostLayoutEvent() { diff --git a/Modules/UIElements/Panel.cs b/Modules/UIElements/Panel.cs index 21a7cd8b58..d1c5bcd29d 100644 --- a/Modules/UIElements/Panel.cs +++ b/Modules/UIElements/Panel.cs @@ -386,16 +386,25 @@ public override void ValidateLayout() break; } } + Profiler.EndSample(); } - bool ValidateSubTree(VisualElement root) + void ValidateSubTree(VisualElement root) { - // if the last layout is different than this one we must dirty transform on children - if (root.renderData.lastLayout != new Rect(root.cssNode.LayoutX, root.cssNode.LayoutY, root.cssNode.LayoutWidth, root.cssNode.LayoutHeight)) + Rect cssRect = new Rect(root.cssNode.LayoutX, root.cssNode.LayoutY, root.cssNode.LayoutWidth, root.cssNode.LayoutHeight); + Rect lastRect = root.renderData.lastLayout; + + bool rectChanged = lastRect != cssRect; + + // if the last layout rect is different than the current one we must dirty transform on children + if (rectChanged) { - root.Dirty(ChangeType.Transform); - root.renderData.lastLayout = new Rect(root.cssNode.LayoutX, root.cssNode.LayoutY, root.cssNode.LayoutWidth, root.cssNode.LayoutHeight); + if (lastRect.position != cssRect.position) + { + root.Dirty(ChangeType.Transform); + } + root.renderData.lastLayout = cssRect; } // ignore clean sub trees @@ -408,17 +417,21 @@ bool ValidateSubTree(VisualElement root) } } - using (var evt = PostLayoutEvent.GetPooled(hasNewLayout)) + if (rectChanged) { - evt.target = root; - UIElementsUtility.eventDispatcher.DispatchEvent(evt, this); + using (var evt = PostLayoutEvent.GetPooled(hasNewLayout, lastRect, cssRect)) + { + evt.target = root; + UIElementsUtility.eventDispatcher.DispatchEvent(evt, this); + } } // reset both flags at the end root.ClearDirty(ChangeType.Layout); - root.cssNode.MarkLayoutSeen(); - - return hasNewLayout; + if (hasNewLayout) + { + root.cssNode.MarkLayoutSeen(); + } } // get the AA aligned bound diff --git a/Modules/UIElements/ScrollView.cs b/Modules/UIElements/ScrollView.cs index b6b9472b88..a78e979721 100644 --- a/Modules/UIElements/ScrollView.cs +++ b/Modules/UIElements/ScrollView.cs @@ -124,6 +124,7 @@ public ScrollView(Vector2 horizontalScrollerValues, Vector2 verticalScrollerValu (value) => { scrollOffset = new Vector2(value, scrollOffset.y); + UpdateContentViewTransform(); }, Slider.Direction.Horizontal) {name = "HorizontalScroller", persistenceKey = "HorizontalScroller"}; shadow.Add(horizontalScroller); @@ -132,11 +133,13 @@ public ScrollView(Vector2 horizontalScrollerValues, Vector2 verticalScrollerValu (value) => { scrollOffset = new Vector2(scrollOffset.x, value); + UpdateContentViewTransform(); }, Slider.Direction.Vertical) {name = "VerticalScroller", persistenceKey = "VerticalScroller"}; shadow.Add(verticalScroller); RegisterCallback(OnScrollWheel); + contentContainer.RegisterCallback(OnGeometryChanged); } protected internal override void ExecuteDefaultAction(EventBase evt) @@ -145,15 +148,17 @@ protected internal override void ExecuteDefaultAction(EventBase evt) if (evt.GetEventTypeId() == PostLayoutEvent.TypeId()) { - var postLayoutEvt = (PostLayoutEvent)evt; - OnPostLayout(postLayoutEvt.hasNewLayout); + OnGeometryChanged((PostLayoutEvent)evt); } } - private void OnPostLayout(bool hasNewLayout) + private void OnGeometryChanged(PostLayoutEvent evt) { - if (!hasNewLayout) + // Only affected by dimension changes + if (evt.oldRect.size == evt.newRect.size) + { return; + } if (contentContainer.layout.width > Mathf.Epsilon) horizontalScroller.Adjust(contentViewport.layout.width / contentContainer.layout.width); diff --git a/Modules/UIElements/Slider.cs b/Modules/UIElements/Slider.cs index ae2dc367f1..bec256f9c8 100644 --- a/Modules/UIElements/Slider.cs +++ b/Modules/UIElements/Slider.cs @@ -118,6 +118,7 @@ public Slider(float start, float end, System.Action valueChanged, Add(new VisualElement() { name = "TrackElement" }); dragElement = new VisualElement() { name = "DragElement" }; + dragElement.RegisterCallback(UpdateDragElementPosition); Add(dragElement); @@ -131,6 +132,17 @@ private void ClampValue() value = value; } + void UpdateDragElementPosition(PostLayoutEvent evt) + { + // Only affected by dimension changes + if (evt.oldRect.size == evt.newRect.size) + { + return; + } + + UpdateDragElementPosition(); + } + public override void OnPersistentDataReady() { base.OnPersistentDataReady(); @@ -277,17 +289,8 @@ protected internal override void ExecuteDefaultAction(EventBase evt) if (evt.GetEventTypeId() == PostLayoutEvent.TypeId()) { - var postLayoutEvt = (PostLayoutEvent)evt; - OnPostLayout(postLayoutEvt.hasNewLayout); + UpdateDragElementPosition((PostLayoutEvent)evt); } } - - private void OnPostLayout(bool hasNewLayout) - { - if (!hasNewLayout) - return; - - UpdateDragElementPosition(); - } } } diff --git a/README.md b/README.md index 292551b0f6..b4a666cb48 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.1.0b7 C# reference source code +## Unity 2018.1.0b8 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/artifacts/generated/bindings_old/common/Editor/EditorUtilityBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/EditorUtilityBindings.gen.cs index e3ee34124a..690037790e 100644 --- a/artifacts/generated/bindings_old/common/Editor/EditorUtilityBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/EditorUtilityBindings.gen.cs @@ -609,7 +609,7 @@ static public GameObject CreateGameObjectWithHideFlags(string name, HideFlags fl public static string[] CompileCSharp(string[] sources, string[] references, string[] defines, string outputFile) { - return UnityEditor.Scripting.Compilers.MonoCSharpCompiler.Compile(sources, references, defines, outputFile); + return UnityEditor.Scripting.Compilers.MonoCSharpCompiler.Compile(sources, references, defines, outputFile, PlayerSettings.allowUnsafeCode); } diff --git a/artifacts/generated/bindings_old/common/Editor/PlayerSettingsBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/PlayerSettingsBindings.gen.cs index 222412e0ba..0028c70061 100644 --- a/artifacts/generated/bindings_old/common/Editor/PlayerSettingsBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/PlayerSettingsBindings.gen.cs @@ -1038,6 +1038,16 @@ public extern static ScriptingRuntimeVersion scriptingRuntimeVersion set; } + public extern static bool allowUnsafeCode + { + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + get; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + set; + } + public extern static string keystorePass { [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration diff --git a/artifacts/generated/bindings_old/common/Editor/TextureImporterBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/TextureImporterBindings.gen.cs index 4128001b28..80a9566569 100644 --- a/artifacts/generated/bindings_old/common/Editor/TextureImporterBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/TextureImporterBindings.gen.cs @@ -1164,6 +1164,8 @@ public sealed partial class TextureImporterSettings float m_SpritePixelsToUnits; [SerializeField] Vector4 m_SpriteBorder; + [SerializeField] + int m_SpriteGenerateFallbackPhysicsShape; [SerializeField] @@ -1444,6 +1446,12 @@ public Vector4 spriteBorder set { m_SpriteBorder = value; } } + public bool spriteGenerateFallbackPhysicsShape + { + get {return m_SpriteGenerateFallbackPhysicsShape != 0; } + set { m_SpriteGenerateFallbackPhysicsShape = value ? 1 : 0; } + } + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] From 61a8d8d7d818bef17cfa023b24b0353533107491 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Tue, 27 Feb 2018 20:03:39 +0000 Subject: [PATCH 08/17] Unity 2018.1.0b9 C# reference source code --- Editor/Mono/AssemblyInfo/AssemblyInfo.cs | 1 + .../AssetPipeline/AssetImporter.bindings.cs | 2 +- .../Mixer/Bindings/AudioMixerController.cs | 3 ++ .../Mixer/GUI/AudioMixerGroupTreeView.cs | 1 + .../Mono/Audio/Mixer/GUI/AudioMixerWindow.cs | 2 +- .../DesktopStandalonePostProcessor.cs | 36 ++++++++----- Editor/Mono/BuildPlayerWindowBuildMethods.cs | 20 +++++++ .../DesktopPluginImporterExtension.cs | 26 ++++------ Editor/Mono/Inspector/AudioSourceInspector.cs | 44 ++-------------- Editor/Mono/Inspector/GameObjectInspector.cs | 4 +- Editor/Mono/Inspector/InspectorWindow.cs | 3 +- .../PlayerSettingsEditor.cs | 6 +-- Editor/Mono/Modules/PlatformSupportModule.cs | 19 +++++++ Editor/Mono/PlayerSettingsXboxOne.bindings.cs | 26 ++++++++++ .../Mono/ProjectWindow/ProjectWindowUtil.cs | 11 ++++ Editor/Mono/SettingsWindow/LightingEditor.cs | 4 ++ Editor/Mono/Sprites/SpriteUtilityWindow.cs | 3 +- Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs | 49 ++++++++++++++---- .../lib/mono/2.0/Boo.Lang.Compiler.dll | Bin 934912 -> 934912 bytes .../lib/mono/2.0/Boo.Lang.Parser.dll | Bin 414208 -> 414208 bytes .../lib/mono/2.0/Boo.Lang.dll | Bin 126976 -> 126976 bytes .../lib/mono/2.0/Mono.Posix.dll | Bin 184320 -> 184320 bytes .../lib/mono/2.0/Mono.Security.dll | Bin 294912 -> 294912 bytes .../lib/mono/2.0/System.Core.dll | Bin 297472 -> 297984 bytes .../lib/mono/2.0/System.Xml.Linq.dll | Bin 106496 -> 106496 bytes .../lib/mono/2.0/System.Xml.dll | Bin 1270272 -> 1270272 bytes .../monodistribution/lib/mono/2.0/System.dll | Bin 1679360 -> 1679360 bytes .../lib/mono/2.0/UnityScript.dll | Bin 177664 -> 177664 bytes .../Editor/Managed/PackageInfo.cs | 22 ++------ .../{OriginType.cs => PackageSource.cs} | 6 +-- .../Editor/Managed/Grid/GridBrush.cs | 5 +- Modules/UnityAnalytics/UnityAnalytics.cs | 18 ++++++- .../UnityAnalyticsHandler.bindings.cs | 2 +- .../EditorAnalytics.bindings.cs | 29 +++++++++++ .../Public/UnityWebRequest.bindings.cs | 13 +---- .../UnityWebRequest/Public/WebRequestUtils.cs | 37 +++++++++---- Projects/CSharp/UnityEditor.csproj | 9 ++-- Projects/CSharp/UnityEngine.csproj | 3 ++ README.md | 2 +- Runtime/Export/Internal/InternalInterfaces.cs | 17 ++++++ .../Audio/AudioMixerGroupBindings.gen.cs | 3 +- .../Audio/AudioMixerSnapshotBindings.gen.cs | 3 +- .../common/Core/ApplicationBindings.gen.cs | 3 +- .../Editor/BuildPipelineBindings.gen.cs | 5 +- 44 files changed, 293 insertions(+), 144 deletions(-) create mode 100644 Editor/Mono/PlayerSettingsXboxOne.bindings.cs rename Modules/PackageManager/Editor/Managed/{OriginType.cs => PackageSource.cs} (82%) create mode 100644 Runtime/Export/Internal/InternalInterfaces.cs diff --git a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs index 0c432cfc16..4f99a49772 100644 --- a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs +++ b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs @@ -42,6 +42,7 @@ [assembly: InternalsVisibleTo("UnityEditor.TreeEditor")] [assembly: InternalsVisibleTo("UnityEditor.Timeline")] [assembly: InternalsVisibleTo("UnityEditor.VR")] +[assembly: InternalsVisibleTo("Unity.RuntimeTests")] [assembly: InternalsVisibleTo("Unity.RuntimeTests.Framework")] [assembly: InternalsVisibleTo("UnityEditor.Facebook.Extensions")] [assembly: InternalsVisibleTo("Assembly-CSharp-Editor-firstpass-testable")] diff --git a/Editor/Mono/AssetPipeline/AssetImporter.bindings.cs b/Editor/Mono/AssetPipeline/AssetImporter.bindings.cs index 1ce6f36838..0175ed3162 100644 --- a/Editor/Mono/AssetPipeline/AssetImporter.bindings.cs +++ b/Editor/Mono/AssetPipeline/AssetImporter.bindings.cs @@ -91,7 +91,7 @@ public extern string assetBundleVariant [NativeName("SetAssetBundleName")] extern public void SetAssetBundleNameAndVariant(string assetBundleName, string assetBundleVariant); - [FreeFunction("FindAssetImporterAtAssetPath")] + [FreeFunction("FindAssetImporterInstanceAtAssetPath")] extern public static AssetImporter GetAtPath(string path); public void SaveAndReimport() diff --git a/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs b/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs index 8f79b96c77..30c3582fa6 100644 --- a/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs +++ b/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs @@ -622,6 +622,9 @@ public List DuplicateGroups(AudioMixerGroupController AudioMixerGroupController parent = FindParentGroup(masterGroup, source); if (parent != null && source != null) { + if (recordUndo) + Undo.RecordObject(parent, "Reparent AudioMixerGroup"); + AudioMixerGroupController copy = DuplicateGroupRecurse(source, recordUndo); var modifiedChildList = new List(parent.children); diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupTreeView.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupTreeView.cs index 9b93ba9b6e..fef6317fb6 100644 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupTreeView.cs +++ b/Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupTreeView.cs @@ -336,6 +336,7 @@ public void ReloadTree() if (m_Controller != null) { m_Controller.SanitizeGroupViews(); + m_Controller.OnSubAssetChanged(); } } diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs index 025f2095a8..1317daf679 100644 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs +++ b/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs @@ -344,9 +344,9 @@ public void UndoRedoPerformed() return; // Undo may have deleted one of the selected groups + m_Controller.OnSubAssetChanged(); m_Controller.SanitizeGroupViews(); m_Controller.OnUnitySelectionChanged(); - m_Controller.OnSubAssetChanged(); if (m_GroupTree != null) m_GroupTree.OnUndoRedoPerformed(); diff --git a/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs b/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs index 9d1c6ba137..33938cdab1 100644 --- a/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs +++ b/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs @@ -3,7 +3,9 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using UnityEditor; using UnityEditor.Build.Reporting; using UnityEditor.Modules; @@ -40,7 +42,7 @@ public override void UpdateBootConfig(BuildTarget target, BootConfigData config, config.Set("mono-codegen", "il2cpp"); } - private void CopyNativePlugins(BuildPostProcessArgs args) + private void CopyNativePlugins(BuildPostProcessArgs args, out List cppPlugins) { string buildTargetName = BuildPipeline.GetBuildTargetName(args.target); IPluginImporterExtension pluginImpExtension = new DesktopPluginImporterExtension(); @@ -52,11 +54,19 @@ private void CopyNativePlugins(BuildPostProcessArgs args) bool haveCreatedPluginsFolder = false; bool haveCreatedSubDir32Bit = false; bool haveCreatedSubDir64Bit = false; + cppPlugins = new List(); foreach (PluginImporter imp in PluginImporter.GetImporters(args.target)) { BuildTarget t = args.target; + // Skip .cpp files. They get copied to il2cpp output folder just before code compilation + if (DesktopPluginImporterExtension.IsCppPluginFile(imp.assetPath)) + { + cppPlugins.Add(imp.assetPath); + continue; + } + // Skip managed DLLs. if (!imp.isNativePlugin) continue; @@ -151,6 +161,14 @@ private void CopyNativePlugins(BuildPostProcessArgs args) } } + private void CopyCppPlugins(string cppOutputDir, IEnumerable cppPlugins) + { + foreach (var plugin in cppPlugins) + { + FileUtil.CopyFileOrDirectory(plugin, Path.Combine(cppOutputDir, Path.GetFileName(plugin))); + } + } + private void SetupStagingArea(BuildPostProcessArgs args) { if (UseIl2Cpp && GetCreateSolution()) @@ -160,7 +178,8 @@ private void SetupStagingArea(BuildPostProcessArgs args) Directory.CreateDirectory(args.stagingAreaData); - CopyNativePlugins(args); + List cppPlugins; + CopyNativePlugins(args, out cppPlugins); if (args.target == BuildTarget.StandaloneWindows || args.target == BuildTarget.StandaloneWindows64) @@ -173,7 +192,7 @@ private void SetupStagingArea(BuildPostProcessArgs args) if (UseIl2Cpp) { CopyVariationFolderIntoStagingArea(args); - IL2CPPUtils.RunIl2Cpp(args.stagingAreaData, GetPlatformProvider(args), null, args.usedClassRegistry); + IL2CPPUtils.RunIl2Cpp(args.stagingAreaData, GetPlatformProvider(args), (cppOutputDir) => CopyCppPlugins(cppOutputDir, cppPlugins), args.usedClassRegistry); // Move GameAssembly next to game executable var il2cppOutputNativeDirectory = Path.Combine(args.stagingAreaData, "Native"); @@ -427,16 +446,7 @@ protected virtual bool PlaceIL2CPPSymbolMapNextToExecutable() return true; } - internal class ScriptingImplementations : IScriptingImplementations + internal class ScriptingImplementations : DefaultScriptingImplementations { - public ScriptingImplementation[] Supported() - { - return new[] { ScriptingImplementation.Mono2x, ScriptingImplementation.IL2CPP }; - } - - public ScriptingImplementation[] Enabled() - { - return new[] { ScriptingImplementation.Mono2x, ScriptingImplementation.IL2CPP }; - } } } diff --git a/Editor/Mono/BuildPlayerWindowBuildMethods.cs b/Editor/Mono/BuildPlayerWindowBuildMethods.cs index 62ee426ca1..a40d1eb055 100644 --- a/Editor/Mono/BuildPlayerWindowBuildMethods.cs +++ b/Editor/Mono/BuildPlayerWindowBuildMethods.cs @@ -312,9 +312,29 @@ static bool PickBuildLocation(BuildTargetGroup targetGroup, BuildTarget target, // Invalidate default name, if extension mismatches the default file (for ex., when switching between folder type export to file type export, see Android) if (extension != Path.GetExtension(defaultName).Replace(".", "")) defaultName = string.Empty; + + // Hack: For Windows Standalone, we want the BuildPanel to choose a folder, + // but we don't want BuildPlayer to take a folder path because historically it took an .exe path + // and we would be breaking tons of projects! + bool isWindowsStandalone = target == BuildTarget.StandaloneWindows || target == BuildTarget.StandaloneWindows64; + string realExtension = extension; + if (isWindowsStandalone) + { + extension = string.Empty; + // Remove the filename.exe part from the path + if (!string.IsNullOrEmpty(defaultName)) + defaultName = Path.GetDirectoryName(defaultName); + } + string title = "Build " + BuildPlatforms.instance.GetBuildTargetDisplayName(targetGroup, target); string path = EditorUtility.SaveBuildPanel(target, title, defaultFolder, defaultName, extension, out updateExistingBuild); + if (isWindowsStandalone) + { + extension = realExtension; + path = Path.Combine(path, Path.GetFileName(path) + '.' + extension); + } + if (path == string.Empty) return false; diff --git a/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs b/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs index c0e811ded0..89a1aee21c 100644 --- a/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs +++ b/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs @@ -3,13 +3,10 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; -using System.IO; -using System.Text; -using System.Text.RegularExpressions; using System.Collections.Generic; -using UnityEngine; -using UnityEditor; +using System.IO; using UnityEditor.Modules; +using UnityEngine; namespace UnityEditor { @@ -113,9 +110,7 @@ private bool IsUsableOnWindows(PluginImporter imp) return true; string ext = Path.GetExtension(imp.assetPath).ToLower(); - if (ext == ".dll") - return true; - return false; + return ext == ".dll" || IsCppPluginFile(imp.assetPath); } private bool IsUsableOnOSX(PluginImporter imp) @@ -124,10 +119,7 @@ private bool IsUsableOnOSX(PluginImporter imp) return true; string ext = Path.GetExtension(imp.assetPath).ToLower(); - if (ext == ".so" || - ext == ".bundle") - return true; - return false; + return ext == ".so" || ext == ".bundle" || IsCppPluginFile(imp.assetPath); } private bool IsUsableOnLinux(PluginImporter imp) @@ -136,9 +128,7 @@ private bool IsUsableOnLinux(PluginImporter imp) return true; string ext = Path.GetExtension(imp.assetPath).ToLower(); - if (ext == ".so") - return true; - return false; + return ext == ".so" || IsCppPluginFile(imp.assetPath); } public override void OnPlatformSettingsGUI(PluginImporterInspector inspector) @@ -248,5 +238,11 @@ public override string CalculateFinalPluginPath(string platformName, PluginImpor // For files this will return filename, for directories, this will return last path component return Path.GetFileName(imp.assetPath); } + + internal static bool IsCppPluginFile(string assetPath) + { + var extension = Path.GetExtension(assetPath).ToLower(); + return extension == ".cpp" || extension == ".c" || extension == ".h"; + } } } diff --git a/Editor/Mono/Inspector/AudioSourceInspector.cs b/Editor/Mono/Inspector/AudioSourceInspector.cs index 3e7eb60831..6abc5c2ecf 100644 --- a/Editor/Mono/Inspector/AudioSourceInspector.cs +++ b/Editor/Mono/Inspector/AudioSourceInspector.cs @@ -59,7 +59,6 @@ public AudioCurveWrapper(AudioCurveType type, string legend, int id, Color color } private AudioCurveWrapper[] m_AudioCurves; - bool m_RefreshCurveEditor = false; CurveEditor m_CurveEditor = null; Vector3 m_LastSourcePosition; Vector3 m_LastListenerPosition; @@ -417,8 +416,6 @@ private void Update() private void UndoRedoPerformed() { - m_RefreshCurveEditor = true; - DestroyExtensionEditors(); UpdateSpatializerExtensionMixedValues(); @@ -461,35 +458,13 @@ private void HandleLowPassFilter() public override void OnInspectorGUI() { InitStyles(); - serializedObject.Update(); + if (m_LowpassObject != null) m_LowpassObject.Update(); HandleLowPassFilter(); - // Check if curves changed outside of the control of this editor - foreach (AudioCurveWrapper audioCurve in m_AudioCurves) - { - CurveWrapper cw = m_CurveEditor.GetCurveWrapperFromID(audioCurve.id); - if (audioCurve.curveProp != null) - { - AnimationCurve propCurve = audioCurve.curveProp.animationCurveValue; - if ((cw == null) != audioCurve.curveProp.hasMultipleDifferentValues) - { - m_RefreshCurveEditor = true; - } - else if (cw != null) - { - if (cw.curve.length == 0) - m_RefreshCurveEditor = true; - else if (propCurve.length >= 1 && propCurve.keys[0].value != cw.curve.keys[0].value) - m_RefreshCurveEditor = true; - } - } - else if (cw != null) - m_RefreshCurveEditor = true; - } UpdateWrappersAndLegend(); EditorGUILayout.PropertyField(m_AudioClip, ms_Styles.audioClipLabel); @@ -656,9 +631,6 @@ private void Audio3DGUI() { EditorGUILayout.Slider(m_DopplerLevel, 0.0f, 5.0f, ms_Styles.dopplerLevelLabel); - // If anything inside this block changes, we need to update the wrappers - EditorGUI.BeginChangeCheck(); - // Spread control AnimProp(ms_Styles.spreadLabel, m_AudioCurves[kSpreadCurveID].curveProp, 0.0f, 360.0f, true); @@ -697,10 +669,6 @@ private void Audio3DGUI() if (EditorGUI.EndChangeCheck()) m_MaxDistance.floatValue = Mathf.Min(Mathf.Max(Mathf.Max(m_MaxDistance.floatValue, 0.01f), m_MinDistance.floatValue * 1.01f), 1000000.0f); - // If anything changed, update the wrappers - if (EditorGUI.EndChangeCheck()) - m_RefreshCurveEditor = true; - Rect r = GUILayoutUtility.GetAspectRect(1.333f, GUI.skin.textField); r.xMin += EditorGUI.indent; if (Event.current.type != EventType.Layout && Event.current.type != EventType.Used) @@ -729,7 +697,6 @@ private void Audio3DGUI() } } - // Draw legend DrawLegend(); @@ -762,12 +729,8 @@ void UpdateWrappersAndLegend() if (m_CurveEditor.InLiveEdit()) return; - if (m_RefreshCurveEditor) - { - m_CurveEditor.animationCurves = GetCurveWrapperArray(); - SyncShownCurvesToLegend(GetShownAudioCurves()); - m_RefreshCurveEditor = false; - } + m_CurveEditor.animationCurves = GetCurveWrapperArray(); + SyncShownCurvesToLegend(GetShownAudioCurves()); } void DrawLegend() @@ -926,7 +889,6 @@ void OnSceneGUI() Undo.RecordObject(source, "AudioSource Distance"); source.minDistance = minDistance; source.maxDistance = maxDistance; - m_RefreshCurveEditor = true; } Handles.color = tempColor; diff --git a/Editor/Mono/Inspector/GameObjectInspector.cs b/Editor/Mono/Inspector/GameObjectInspector.cs index 093e1b3a08..6f1b2bbb0f 100644 --- a/Editor/Mono/Inspector/GameObjectInspector.cs +++ b/Editor/Mono/Inspector/GameObjectInspector.cs @@ -102,6 +102,7 @@ public void Dispose() return; renderUtility.Cleanup(); UnityObject.DestroyImmediate(gameObject); + m_GameObject = null; m_Disposed = true; } } @@ -509,7 +510,8 @@ PreviewData GetPreviewData() previewData = new PreviewData(target); m_PreviewInstances.Add(referenceTargetIndex, previewData); } - + if (!previewData.gameObject) + ReloadPreviewInstances(); return previewData; } diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index 533ee228dc..4492b2f9f5 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -202,7 +202,8 @@ void OnSelectionChange() m_Previews = null; m_SelectedPreview = null; m_TypeSelectionList = null; - m_Parent.ClearKeyboardControl(); + if (m_Parent != null) // parent may be null in some situations (case 970700, 851988) + m_Parent.ClearKeyboardControl(); ScriptAttributeUtility.ClearGlobalCache(); Repaint(); } diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index e0b2e996df..eca8aecd0e 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -148,8 +148,8 @@ static class Styles public static readonly GUIContent disableStatistics = EditorGUIUtility.TrTextContent("Disable HW Statistics*", "Disables HW Statistics (Pro Only)"); public static readonly GUIContent scriptingDefineSymbols = EditorGUIUtility.TrTextContent("Scripting Define Symbols*"); public static readonly GUIContent scriptingRuntimeVersion = EditorGUIUtility.TrTextContent("Scripting Runtime Version*", "The scripting runtime version to be used. Unity uses different scripting backends based on platform, so these options are listed as equivalent expected behavior."); - public static readonly GUIContent scriptingRuntimeVersionLegacy = EditorGUIUtility.TrTextContent("Stable (.NET 3.5 Equivalent)"); - public static readonly GUIContent scriptingRuntimeVersionLatest = EditorGUIUtility.TrTextContent("Experimental (.NET 4.x Equivalent)"); + public static readonly GUIContent scriptingRuntimeVersionLegacy = EditorGUIUtility.TrTextContent("Legacy (.NET 3.5 Equivalent)"); + public static readonly GUIContent scriptingRuntimeVersionLatest = EditorGUIUtility.TrTextContent("Stable (.NET 4.x Equivalent)"); public static readonly GUIContent scriptingBackend = EditorGUIUtility.TrTextContent("Scripting Backend"); public static readonly GUIContent il2cppCompilerConfiguration = EditorGUIUtility.TrTextContent("C++ Compiler Configuration"); public static readonly GUIContent scriptingMono2x = EditorGUIUtility.TrTextContent("Mono"); @@ -1918,7 +1918,7 @@ private void OtherSectionConfigurationGUI(BuildTargetGroup targetGroup, ISetting if (targetGroupSupportsIl2Cpp) { - using (new EditorGUI.DisabledScope(!currentBackendIsIl2Cpp)) + using (new EditorGUI.DisabledScope(!currentBackendIsIl2Cpp || !scripting.AllowIL2CPPCompilerConfigurationSelection())) { var currentConfiguration = PlayerSettings.GetIl2CppCompilerConfiguration(targetGroup); var configurations = GetIl2CppCompilerConfigurations(); diff --git a/Editor/Mono/Modules/PlatformSupportModule.cs b/Editor/Mono/Modules/PlatformSupportModule.cs index d22a032dbb..b874731cca 100644 --- a/Editor/Mono/Modules/PlatformSupportModule.cs +++ b/Editor/Mono/Modules/PlatformSupportModule.cs @@ -159,6 +159,25 @@ internal interface IScriptingImplementations // Scripting implementations exposed to the user. ScriptingImplementation[] Enabled(); + bool AllowIL2CPPCompilerConfigurationSelection(); + } + + internal class DefaultScriptingImplementations : IScriptingImplementations + { + public virtual ScriptingImplementation[] Supported() + { + return new[] { ScriptingImplementation.Mono2x, ScriptingImplementation.IL2CPP }; + } + + public virtual ScriptingImplementation[] Enabled() + { + return new[] { ScriptingImplementation.Mono2x, ScriptingImplementation.IL2CPP }; + } + + public virtual bool AllowIL2CPPCompilerConfigurationSelection() + { + return true; + } } // Extension point to add/alter the SettingsEditorWindow class diff --git a/Editor/Mono/PlayerSettingsXboxOne.bindings.cs b/Editor/Mono/PlayerSettingsXboxOne.bindings.cs new file mode 100644 index 0000000000..4748358727 --- /dev/null +++ b/Editor/Mono/PlayerSettingsXboxOne.bindings.cs @@ -0,0 +1,26 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using UnityEngine; +using UnityEngine.Bindings; +using System.Runtime.CompilerServices; + +namespace UnityEditor +{ + public sealed partial class PlayerSettings + { + [NativeHeader("Runtime/Misc/PlayerSettings.h")] + public sealed partial class XboxOne + { + [NativeProperty("XboxOneXTitleMemory", TargetType.Field)] + extern public static int XTitleMemory + { + [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] + get; + [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] + set; + } + } + } +} diff --git a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs index 4db29a8463..b1ae653853 100644 --- a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs +++ b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs @@ -12,6 +12,7 @@ using UnityEditor.SceneManagement; using UnityEditorInternal; using UnityEngine; +using UnityEngine.Internal; using Object = UnityEngine.Object; namespace UnityEditor @@ -734,6 +735,7 @@ internal static IEnumerable DuplicateAssets(IEnumerable assets) AssetDatabase.Refresh(); var copiedPaths = new List(); + Object firstDuplicatedObjectToFail = null; foreach (var asset in assets) { @@ -742,6 +744,12 @@ internal static IEnumerable DuplicateAssets(IEnumerable assets) // if duplicating a sub-asset, then create a copy next to the main asset file if (AssetDatabase.IsSubAsset(asset)) { + if (asset is ISubAssetNotDuplicatable) + { + firstDuplicatedObjectToFail = firstDuplicatedObjectToFail ? firstDuplicatedObjectToFail : asset; + continue; + } + var extension = NativeFormatImporterUtility.GetExtensionForAsset(asset); var newPath = AssetDatabase.GenerateUniqueAssetPath( Path.Combine(Path.GetDirectoryName(assetPath), string.Format("{0}.{1}", asset.name, extension)) @@ -758,6 +766,9 @@ internal static IEnumerable DuplicateAssets(IEnumerable assets) } } + if (firstDuplicatedObjectToFail != null) + Debug.LogError("Duplication error: One or more sub assets could not be duplicated directly, use the appropriate editor instead", firstDuplicatedObjectToFail); + AssetDatabase.Refresh(); return copiedPaths.Select(AssetDatabase.LoadMainAssetAtPath); diff --git a/Editor/Mono/SettingsWindow/LightingEditor.cs b/Editor/Mono/SettingsWindow/LightingEditor.cs index 3155a3958a..a232f232bf 100644 --- a/Editor/Mono/SettingsWindow/LightingEditor.cs +++ b/Editor/Mono/SettingsWindow/LightingEditor.cs @@ -128,6 +128,8 @@ private void DrawGUI() InitSettings(); } + m_RenderSettings.UpdateIfRequiredOrScript(); + Material skyboxMaterial = m_SkyboxMaterial.objectReferenceValue as Material; m_bShowEnvironment = EditorGUILayout.FoldoutTitlebar(m_bShowEnvironment, Styles.env_top, true); @@ -257,6 +259,8 @@ private void DrawGUI() EditorGUI.indentLevel--; EditorGUILayout.Space(); } + + m_RenderSettings.ApplyModifiedProperties(); } public override void OnInspectorGUI() diff --git a/Editor/Mono/Sprites/SpriteUtilityWindow.cs b/Editor/Mono/Sprites/SpriteUtilityWindow.cs index b67282355a..827e411a44 100644 --- a/Editor/Mono/Sprites/SpriteUtilityWindow.cs +++ b/Editor/Mono/Sprites/SpriteUtilityWindow.cs @@ -222,8 +222,7 @@ private float Log2(float x) protected void DrawTexture() { - int texWidth = Mathf.Max(m_Texture.width, 1); - float mipLevel = Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(m_Texture) - 1) - Log2(texWidth / m_TextureRect.width); + float mipLevel = Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(m_Texture) - 1); FilterMode oldFilter = m_Texture.filterMode; TextureUtil.SetFilterModeNoDirty(m_Texture, FilterMode.Point); diff --git a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs index 4065b45155..779fb53b4e 100644 --- a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs +++ b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs @@ -31,7 +31,7 @@ static class Styles EditorGUIUtility.TrTextContent("Single Pass Instanced (Preview)") }; - public static readonly GUIContent[] kAndroidStereoRenderingPaths = + public static readonly GUIContent[] kMultiviewStereoRenderingPaths = { EditorGUIUtility.TrTextContent("Multi Pass"), EditorGUIUtility.TrTextContent("Single Pass (Preview)"), @@ -159,7 +159,7 @@ internal void XRSectionGUI(BuildTargetGroup targetGroup, int sectionIndex) VuforiaGUI(targetGroup); - Stereo360CaptureGUI(); + Stereo360CaptureGUI(targetGroup); ErrorOnARDeviceIncompatibility(targetGroup); } @@ -234,27 +234,53 @@ private void CheckDevicesRequireInstall(BuildTargetGroup targetGroup) } } - private static bool TargetSupportsSinglePassStereoRendering(BuildTargetGroup targetGroup) + // Keep these in sync with BuildTargetPlatformSpecific.cpp + private static bool DoesBuildTargetSupportSinglePassStereoRendering(BuildTargetGroup targetGroup) { switch (targetGroup) { case BuildTargetGroup.Standalone: case BuildTargetGroup.PS4: - case BuildTargetGroup.Android: case BuildTargetGroup.WSA: + case BuildTargetGroup.Android: return true; default: return false; } } - private static bool TargetSupportsStereoInstancingRendering(BuildTargetGroup targetGroup) + // Keep these in sync with BuildTargetPlatformSpecific.cpp + private static bool DoesBuildTargetSupportStereoInstancingRendering(BuildTargetGroup targetGroup) { switch (targetGroup) { - case BuildTargetGroup.WSA: case BuildTargetGroup.Standalone: case BuildTargetGroup.PS4: + case BuildTargetGroup.WSA: + return true; + default: + return false; + } + } + + // Keep these in sync with BuildTargetPlatformSpecific.cpp + private static bool DoesBuildTargetSupportStereoMultiviewRendering(BuildTargetGroup targetGroup) + { + switch (targetGroup) + { + case BuildTargetGroup.Android: + return true; + default: + return false; + } + } + + // Keep these in sync with BuildTargetPlatformSpecific.cpp + private static bool DoesBuildTargetSupportStereo360Capture(BuildTargetGroup targetGroup) + { + switch (targetGroup) + { + case BuildTargetGroup.Standalone: return true; default: return false; @@ -263,7 +289,7 @@ private static bool TargetSupportsStereoInstancingRendering(BuildTargetGroup tar private static GUIContent[] GetStereoRenderingPaths(BuildTargetGroup targetGroup) { - return (targetGroup == BuildTargetGroup.Android) ? Styles.kAndroidStereoRenderingPaths : Styles.kDefaultStereoRenderingPaths; + return DoesBuildTargetSupportStereoMultiviewRendering(targetGroup) ? Styles.kMultiviewStereoRenderingPaths : Styles.kDefaultStereoRenderingPaths; } private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedProperty stereoRenderingPath) @@ -271,8 +297,8 @@ private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedPropert if (!PlayerSettings.virtualRealitySupported) return; - bool supportsSinglePass = TargetSupportsSinglePassStereoRendering(targetGroup); - bool supportsSinglePassInstanced = TargetSupportsStereoInstancingRendering(targetGroup); + bool supportsSinglePass = DoesBuildTargetSupportSinglePassStereoRendering(targetGroup); + bool supportsSinglePassInstanced = DoesBuildTargetSupportStereoInstancingRendering(targetGroup); // populate the dropdown with the valid options based on target platform. int validStereoRenderingOptionsCount = 1 + (supportsSinglePass ? 1 : 0) + (supportsSinglePassInstanced ? 1 : 0); @@ -324,9 +350,10 @@ private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedPropert } } - private void Stereo360CaptureGUI() + private void Stereo360CaptureGUI(BuildTargetGroup targetGroup) { - EditorGUILayout.PropertyField(m_Enable360StereoCapture, Styles.stereo360CaptureCheckbox); + if (DoesBuildTargetSupportStereo360Capture(targetGroup)) + EditorGUILayout.PropertyField(m_Enable360StereoCapture, Styles.stereo360CaptureCheckbox); } private void AddVRDeviceMenuSelected(object userData, string[] options, int selected) diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Compiler.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Compiler.dll index 47d303ae603cfbd6cd55e002713def92bc26b9f4..4d4aa1dc7b7e50da64b241da0489943200fd74a8 100644 GIT binary patch delta 216 zcmV;}04M)|h&h0WIgp407lw0zi-n5;g^L1(ivxv=1ci$Qg^LD-iwA{^2!)FYg^LP> ziwlK|426pgwTljoIe(Dn+f;3b+d_tc&yuUxxB0k;l34)O;%4QOHj delta 216 zcmV;}04M)|h&h0WIgp40a%>=hi-n5;g^L1(ivxv=1ci$Qg^LD-iwA{^2!)FYg^LP> ziwlK|426pgwTljoIe&yaG99l4$3(NQVhL7#X(n8O*aNWRt3d+whm*?xS+jgbwpm6L zHTH!ro5Kvh5y6ro7JlCN0`9e2?TIyo5_vNPddsE#vQyEf5`LHfJ;Y8RuJJqG23)ED zbcouC-DR*E_w#9FDiMQ&m%9vSLMA}ef$=cvAzREK|l^>0k;l34)O;VuwNqp diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Parser.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Parser.dll index 7ffc91cf7d0e7fbd122c4cda94697299f46c17d8..14a069e14eea1b687600f180e2dfeb7182fe83c8 100644 GIT binary patch delta 192 zcmV;x06+hLq#1yu8IXtr8isR$i-n5;g^L1(ivxv=1ci$QwTlLQNq=S&oURXv=1rKk z61C<$&D@~D=Ya)?j?{;|+EN=X0o7lqxZ<$A0u%QqYJ2K|;(>!MVA{okr~RNa(RGOs zdW+*5mR@>Mfhn>%M1?#^Z)!x!E){_eo6v=#gqjM~MAgSVS1h&P`&mIt6JD{)Y|w>r uUs-JaFc94E7DL?EO%Yl%O&DJ;^SyNSCr|EOS*FFe5l{wp0k;lJ2J!{XXjw-9 delta 192 zcmV;x06+hLq#1yu8IXtrb!;Gki-n5;g^L1(ivxv=1ci$QwTlLQNq?a2$@eE+`$)S0 zCUfqGC+`^IY(ewl3(m684A2ZPNpvBTR=xHS80-ckA@1RcjK=&YW^Q^UGi2~{sg{Dc z=4!t&2#H&sdV&L!JBcT_WlLTLCD+N}KvN872 u1G9Cz9Zzb{){xUAG7;*I?>0eis4dByNK6gzp#TH75l{wp0k;lJ2J!`|jaY2} diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.dll index f60a36853ab97fbde5690f12dccb6c9a3efe7dd1..68b72a1af24ae7ff58cd6a5bb96eafc3b4b376bd 100644 GIT binary patch delta 177 zcmV;i08ama;0J)<2at#Z5{7eui?xdZ1?7Kr?$8~|eCa@<{J$t+c(-@;+o3FBoF+W_ z=hCi!VCkl_qIFar`?st8!G@)96E?iI$L&0VujU0SpJsE%!owHrUUsIOw)PNhJDa`J z#Qh7$Nz5_|t-F$L%6j7e%M7U%rRot_gf|#MNQ;I_bPgA%10un?J6_j*McvtVvx^Ki3E|B43{AZ z6{#K%uiaeG)-^**wfCe5L&1Y~Z|(F)m|kxXPTzE9^cBnxGg!9lZ{HYMH<~x%WmJ!Z zJ{^z{6wfJb5pk&~WN<1!C#A0Bj^(rZ^KP&x`t6^{c&;dDW^k02YM_1EnVphAY0MGb fIwys0x7JS+&QAzxjc9Iew-N3E?g6(B=mGKvlp9fx diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Mono.Posix.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Mono.Posix.dll index c67f38e4747ba8ec70666371ab098884f006bdd6..06bb682aca5fd845adbb5cf04b398e4fda517f11 100644 GIT binary patch delta 179 zcmV;k08IaYpbLPY3y_EdZi91yi-n5;wTl9I$bVw`Pav3rQ%<+&YMa40CAln1bS}AD z;^}VB!ki_|(iaA7BZcnI;x)=;0`36tu1+8_z2I@Laoh1}03jfadi;{mlrl;8Bp~CZ zY{d~9UHWJ@$qyyL3sKwEsuM8?8?UP8D~=hv?;5XkwV*da)t^u^BEPaO<>g?jTX$dZ hcoFvq=;$)PW1<(h>5(`t+Jg+2QOyE+w+_kz@&z`8R!aZ? delta 179 zcmV;k08IaYpbLPY3y_Ed$Y~&fi-n5;wTl9I$bXG~Lc_4Xt3s34r#RG}!DM8ILCzQ2CAucHyDq&Nf0dzTS@1h%&hdIa(X^{HAL delta 185 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 V{H5b{&F?ni<*MeuRq{X0{{kb6-2MOn delta 107702 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

f8ggpv$`S8L5lEKAH6z}aB9VdxX+ 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 delta 179 zcmV;k08IaYzy^T829SsYd}<(pi?xdZ>6CwIQlPKiBg997(?^Nr&ut#ptDp%+%E7;`S1?OrvaP+0+BEZw+@&A@(1d_R1*LI diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/System.Xml.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/System.Xml.dll index 843baf262b0d18cb22e1f03633095a8600f5143d..71ace215f33ede95d914c47c6c4338a17d21feaa 100644 GIT binary patch delta 230 zcmV ziwlK|426pgg^Lb_iw}j15QU2og^LokixU}IfB9(IwE4XIPPw{M#3S@S6h_p>=xfiA za}{lUtjgHvLR*G067kY~eMUoK<<-&n`Me)fOvF`?szh}*t g5s)Sh%d3BSa32f#3#b_X*?gA~U=!N64qOxR1um~_&Hw-a delta 230 zcmV ziwlK|426pgg^Lb_iw}j15QU2og^LokixU}If79C}PPp+nPl!w!ZV92GT8lsUTqn@> z$7!BV{E^Y44ngB}xS5|1Ly7+8LYl#!pwjW>OjPi@u0r|25=h-)Iw!mAXvFcKOFB(0 z^pZX$92*u+Sxcd}lbxwV+W+rW=QiIEAhMiJtO5GpIi`>sBuYa!HA=wxXA7%+x8lU# g5r4>H2z64*7MH5D^xj##9X*#3U=!N64qOxR1>Co5k^lez diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/System.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/System.dll index 2004a26b95574bd0620e5cc0c482865c8e3b06df..6f4127197acc921821a9ceedd1fd113e930e915a 100644 GIT binary patch delta 248 zcmV ziwlK|426pgg^Lb_iw}j15QU2og^Ln}ixY*56orcwg^L!2ix-897`2NTJ(z#)y<}3W zQlLb)8=qlFWVoyWB6q}=Y2Dii1ydMLxra0pH{?<~u(o|CA!MZQ8xG ziwlK|426pgg^Lb_iw}j15QU2og^Ln}ixY*56orcwg^L!2ix-897`2NTJ(zz#%sql+ znQlg>?mY$9x7hw@JkvEt7)LUan=23Leoo@+Dgoql1jTC!0q(=GU7k73w(aF*ppRey z;!}A3ExK*NyOrb71n5dy<`VtIS*oTo-Zi3kG)kWMSGTH{j8yV^fUz(AMH@(EV2j>k y_}!gOLR-?q={az0&2N96AkUX4&&=QwCCtdo;1_j9ZoAZ6#sWs(%={2F zW`?qSe<0bgefm5`Lkpl70|O&ajDdj(D0cN4qgbOvNk(R|ijlb)gNllgu?di64rZBd zXO3Xv6;%gI8yi~y1#|L~6LX4HjEyZBRG`8jU0~tu=DAEaY}tewws6SGY!_Y4bd62G zhJ{V2(ScKeiBYK02FTj}dn40KMuFhIZ@qyFcpdhKF&Dm!Es&Yq$P~MsaSPLbMgXD` BPUHXp delta 279 zcmZp8!`1MHYeENeOO8Tg_ttJkO=}iG7ADT^JFFRRF$(E3F|br?0tu#SJuqpoeTgmO zBReKers*9ujB^oX7hA|dwuc>96AkTM3j+wzFDo>u7!7oafal6!9#sWs(ocs_q zW`?qSe<0bsefm5`Lkpl70|O&ajDdj(D0cN4qgbPaijlFYijlb)gGxz8W-*Xu&Y%Jm zGuh4@!Ne=7u9B0VoS0LrVr*;yRbgyw2~+_WhG^Vwp38K@mQ7Yhs9_7ocG1;L*VqIc zSlEObZ8#N}7=;=gfUNDmH!{s+6li3Md|iDa)p6g8eW#Z>ou4_mktudN;})j>i~zL^ BQ4s(D diff --git a/Modules/PackageManager/Editor/Managed/PackageInfo.cs b/Modules/PackageManager/Editor/Managed/PackageInfo.cs index 281a5676d7..b62d07fd01 100644 --- a/Modules/PackageManager/Editor/Managed/PackageInfo.cs +++ b/Modules/PackageManager/Editor/Managed/PackageInfo.cs @@ -26,8 +26,8 @@ public class PackageInfo [NativeName("version")] private string m_Version; [SerializeField] - [NativeName("originType")] - private OriginType m_OriginType; + [NativeName("source")] + private PackageSource m_Source; [SerializeField] [NativeName("resolvedPath")] private string m_ResolvedPath; @@ -65,10 +65,11 @@ internal PackageInfo( PackageStatus status = PackageStatus.Unavailable, IEnumerable errors = null, VersionsInfo versions = null, + PackageSource source = PackageSource.Registry, string version = "") { // Set the default values - m_OriginType = OriginType.Unknown; + m_Source = source; m_PackageId = packageId; m_DisplayName = displayName; m_Category = category; @@ -86,8 +87,7 @@ internal PackageInfo( public string packageId { get { return m_PackageId; } } public string version { get { return m_Version; } } - // Mocked for PAX uncomment when properly implemented - // public OriginType originType { get { return m_OriginType; } }} + public PackageSource source { get { return m_Source; } } public string resolvedPath { get { return m_ResolvedPath; } } public string name { get { return m_Name; } } public string displayName { get { return m_DisplayName; } } @@ -96,18 +96,6 @@ internal PackageInfo( public PackageStatus status { get { return m_Status; } } public Error[] errors { get { return m_Errors; } } public VersionsInfo versions { get { return m_Versions; } } - - // Mock needed by PAX - public OriginType originType - { - get - { - if (m_Name.StartsWith("com.unity.modules.")) - return OriginType.Builtin; - else - return OriginType.Registry; - } - } } } diff --git a/Modules/PackageManager/Editor/Managed/OriginType.cs b/Modules/PackageManager/Editor/Managed/PackageSource.cs similarity index 82% rename from Modules/PackageManager/Editor/Managed/OriginType.cs rename to Modules/PackageManager/Editor/Managed/PackageSource.cs index 985dc2189d..548dce7d78 100644 --- a/Modules/PackageManager/Editor/Managed/OriginType.cs +++ b/Modules/PackageManager/Editor/Managed/PackageSource.cs @@ -5,14 +5,14 @@ namespace UnityEditor.PackageManager { - public enum OriginType + public enum PackageSource { Unknown, - Builtin, Registry, + BuiltIn, Embedded, Local, - Git + Git, } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs index ac86017b8d..b5ffdea764 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs @@ -22,6 +22,9 @@ public class GridBrush : GridBrushBase [HideInInspector] private Vector3Int m_Pivot; + private static readonly Matrix4x4 s_Clockwise = new Matrix4x4(new Vector4(0f, 1f, 0f, 0f), new Vector4(-1f, 0f, 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4(0f, 0f, 0f, 1f)); + private static readonly Matrix4x4 s_CounterClockwise = new Matrix4x4(new Vector4(0f, -1f, 0f, 0f), new Vector4(1f, 0f, 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4(0f, 0f, 0f, 1f)); + public Vector3Int size { get { return m_Size; } set { m_Size = value; SizeUpdated(); } } public Vector3Int pivot { get { return m_Pivot; } set { m_Pivot = value; } } public BrushCell[] cells { get { return m_Cells; } } @@ -134,7 +137,7 @@ public override void Rotate(RotationDirection direction, Grid.CellLayout layout) int newPivotY = direction == RotationDirection.Clockwise ? pivot.x : oldSize.x - pivot.x - 1; pivot = new Vector3Int(newPivotX, newPivotY, pivot.z); - Matrix4x4 rotation = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, 0f, direction == RotationDirection.Clockwise ? 90f : -90f), Vector3.one); + Matrix4x4 rotation = direction == RotationDirection.Clockwise ? s_Clockwise : s_CounterClockwise; foreach (BrushCell cell in m_Cells) { Matrix4x4 oldMatrix = cell.matrix; diff --git a/Modules/UnityAnalytics/UnityAnalytics.cs b/Modules/UnityAnalytics/UnityAnalytics.cs index b509243af3..4c003deeb4 100644 --- a/Modules/UnityAnalytics/UnityAnalytics.cs +++ b/Modules/UnityAnalytics/UnityAnalytics.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; +using System.Reflection; +using System.Runtime.CompilerServices; using UnityEngine; @@ -181,14 +183,28 @@ public static AnalyticsResult CustomEvent(string customEventName, IDictionary= scheme.Length + 2) && targetUrl[scheme.Length + 1] != '/') + { + StringBuilder sb = new StringBuilder(scheme, targetUrl.Length); + sb.Append(':'); + sb.Append(targetUri.PathAndQuery); // for these spec URIs path also has the part of URI to right of colon + sb.Append(targetUri.Fragment); + return sb.ToString(); + } + + return targetUri.AbsoluteUri; } } } diff --git a/Projects/CSharp/UnityEditor.csproj b/Projects/CSharp/UnityEditor.csproj index ff7bb23e5a..6503599b49 100644 --- a/Projects/CSharp/UnityEditor.csproj +++ b/Projects/CSharp/UnityEditor.csproj @@ -296,6 +296,9 @@ Editor\Mono\ShaderUtil.bindings.cs + +Editor\Mono\PlayerSettingsXboxOne.bindings.cs + Editor\Mono\ExportPackageOptions.cs @@ -3888,9 +3891,6 @@ Modules\PackageManager\Editor\Managed\OperationStatus.cs - -Modules\PackageManager\Editor\Managed\OriginType.cs - Modules\PackageManager\Editor\Managed\PackageCollection.cs @@ -3903,6 +3903,9 @@ Modules\PackageManager\Editor\Managed\PackageManagerCommands.cs + +Modules\PackageManager\Editor\Managed\PackageSource.cs + Modules\PackageManager\Editor\Managed\PackageStatus.cs diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index 8696b8763b..473b66fe99 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -568,6 +568,9 @@ Runtime\Export\Director\TexturePlayableOutput.bindings.cs + +Runtime\Export\Internal\InternalInterfaces.cs + Runtime\Export\Internal\ExcludeFromDocs.cs diff --git a/README.md b/README.md index b4a666cb48..c5910e9906 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.1.0b8 C# reference source code +## Unity 2018.1.0b9 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Export/Internal/InternalInterfaces.cs b/Runtime/Export/Internal/InternalInterfaces.cs new file mode 100644 index 0000000000..f2ddc938cb --- /dev/null +++ b/Runtime/Export/Internal/InternalInterfaces.cs @@ -0,0 +1,17 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; + +namespace UnityEngine.Internal +{ + ///

+ /// Tags that it is not possible (or undefined) to duplicate/instantiate an asset of this type. + /// + [VisibleToOtherModules] + interface ISubAssetNotDuplicatable + { + } +} diff --git a/artifacts/generated/bindings_old/common/Audio/AudioMixerGroupBindings.gen.cs b/artifacts/generated/bindings_old/common/Audio/AudioMixerGroupBindings.gen.cs index f2c949f090..866c8da607 100644 --- a/artifacts/generated/bindings_old/common/Audio/AudioMixerGroupBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Audio/AudioMixerGroupBindings.gen.cs @@ -8,12 +8,13 @@ using UsedByNativeCodeAttribute=UnityEngine.Scripting.UsedByNativeCodeAttribute; using UnityEngine; +using UnityEngine.Internal; namespace UnityEngine.Audio { -public partial class AudioMixerGroup : Object +public partial class AudioMixerGroup : Object, ISubAssetNotDuplicatable { internal AudioMixerGroup() {} diff --git a/artifacts/generated/bindings_old/common/Audio/AudioMixerSnapshotBindings.gen.cs b/artifacts/generated/bindings_old/common/Audio/AudioMixerSnapshotBindings.gen.cs index d4eaaec59d..73146744bf 100644 --- a/artifacts/generated/bindings_old/common/Audio/AudioMixerSnapshotBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Audio/AudioMixerSnapshotBindings.gen.cs @@ -8,12 +8,13 @@ using UsedByNativeCodeAttribute=UnityEngine.Scripting.UsedByNativeCodeAttribute; using UnityEngine; +using UnityEngine.Internal; namespace UnityEngine.Audio { -public partial class AudioMixerSnapshot : Object +public partial class AudioMixerSnapshot : Object, ISubAssetNotDuplicatable { internal AudioMixerSnapshot() {} diff --git a/artifacts/generated/bindings_old/common/Core/ApplicationBindings.gen.cs b/artifacts/generated/bindings_old/common/Core/ApplicationBindings.gen.cs index f4264a60e0..ba514b595f 100644 --- a/artifacts/generated/bindings_old/common/Core/ApplicationBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Core/ApplicationBindings.gen.cs @@ -152,10 +152,11 @@ public static bool isMobilePlatform case RuntimePlatform.IPhonePlayer: case RuntimePlatform.Android: case RuntimePlatform.TizenPlayer: + return true; case RuntimePlatform.WSAPlayerX86: case RuntimePlatform.WSAPlayerX64: case RuntimePlatform.WSAPlayerARM: - return true; + return SystemInfo.deviceType == DeviceType.Handheld; default: return false; } diff --git a/artifacts/generated/bindings_old/common/Editor/BuildPipelineBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/BuildPipelineBindings.gen.cs index f46dad7985..8fb4317486 100644 --- a/artifacts/generated/bindings_old/common/Editor/BuildPipelineBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/BuildPipelineBindings.gen.cs @@ -59,9 +59,8 @@ public enum BuildOptions EnableHeadlessMode = 1 << 14, BuildScriptsOnly = 1 << 15, - - - Il2CPP = 1 << 16, + [Obsolete("BuildOptions.IL2CPP is deprecated and has no effect. Use PlayerSettings.SetScriptingBackend() instead.", true)] + Il2CPP = 0, ForceEnableAssertions = 1 << 17, From 723b0d3c01446c0cff514efd86034de0dd3ae0b2 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Thu, 8 Mar 2018 15:30:14 +0000 Subject: [PATCH 09/17] Unity 2018.1.0b10 C# reference source code --- .../AnimationWindow/AnimationRecording.cs | 17 +++- Editor/Mono/AssemblyInfo/AssemblyInfo.cs | 1 + .../BuildPipeline/BuildPipelineInterfaces.cs | 3 +- .../DesktopStandaloneBuildWindowExtension.cs | 10 +++ .../DesktopStandalonePostProcessor.cs | 18 +++-- .../Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs | 18 ++--- .../Burst/BurstCompilerService.bindings.cs | 6 ++ Editor/Mono/Burst/BurstCompilerService.cs | 2 +- Editor/Mono/Collab/CollabAnalytics.cs | 32 ++++++++ .../Collab/Views/CollabHistoryDropDown.cs | 3 + Editor/Mono/Collab/Views/CollabHistoryItem.cs | 7 ++ Editor/Mono/Collab/Views/PagedListView.cs | 4 + Editor/Mono/ContainerWindow.cs | 2 + Editor/Mono/GameView/GameView.cs | 2 +- Editor/Mono/Inspector/Avatar/AvatarEditor.cs | 62 ++++++++++----- .../Inspector/Avatar/AvatarMuscleEditor.cs | 5 ++ .../Scripting/Compilers/MonoCSharpCompiler.cs | 2 +- .../Compilers/MonoScriptCompilerBase.cs | 11 ++- .../Scripting/Compilers/ScriptCompilerBase.cs | 79 +++++++++++++++++-- .../Compilers/UnityScriptCompiler.cs | 21 ++++- Editor/Mono/SyncProject.cs | 2 - .../SolutionSynchronizationSettings.cs | 15 +++- .../SolutionSynchronizer.cs | 56 +++++++------ .../VisualStudioIntegration/UnityVSSupport.cs | 5 -- .../Weaver/UNetBehaviourProcessor.cs | 1 + .../EditorAnalytics.bindings.cs | 5 ++ Projects/CSharp/UnityEditor.csproj | 3 + README.md | 2 +- .../ScriptBindings/RaycastCommand.bindings.cs | 2 +- Runtime/Export/NativeArray/NativeArray.cs | 13 ++- Runtime/Export/NativeArray/NativeSlice.cs | 26 +++++- .../Export/RenderPipeline/RenderPipeline.cs | 6 ++ .../Export/Unsafe/UnsafeUtility.bindings.cs | 3 + .../PlayerSettingsSwitchBindings.gen.cs | 10 +++ .../common/Editor/UnsupportedBindings.gen.cs | 12 ++- 35 files changed, 367 insertions(+), 99 deletions(-) create mode 100644 Editor/Mono/Collab/CollabAnalytics.cs diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs b/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs index eed18e1814..1759bb7fa6 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs @@ -608,8 +608,10 @@ static private void ProcessAnimatorModifications(IAnimationRecordingState state, Animator animator = root.GetComponent(); bool isHuman = animator != null ? animator.isHuman : false; - bool hasRootMotion = animator != null ? animator.hasRootMotion : false; - bool applyRootMotion = animator != null ? animator.applyRootMotion : false; + + // timeline root motion scale revert + // bool hasRootMotion = animator != null ? animator.hasRootMotion : false; + // bool applyRootMotion = animator != null ? animator.applyRootMotion : false; // process animator positions List discardListPos = new List(); @@ -628,7 +630,10 @@ static private void ProcessAnimatorModifications(IAnimationRecordingState state, continue; bool isRootTransform = root.transform == target; - bool isRootMotion = (isHuman || hasRootMotion || applyRootMotion) && isRootTransform; + // timeline root motion scale revert + // bool isRootMotion = (isHuman || hasRootMotion || applyRootMotion) && isRootTransform; + bool isRootMotion = false; + bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target); if (isHumanBone) @@ -677,7 +682,11 @@ static private void ProcessAnimatorModifications(IAnimationRecordingState state, continue; bool isRootTransform = root.transform == target; - bool isRootMotion = (isHuman || hasRootMotion || applyRootMotion) && isRootTransform; + + // timeline root motion scale revert + // bool isRootMotion = (isHuman || hasRootMotion || applyRootMotion) && isRootTransform; + bool isRootMotion = false; + bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target); if (isHumanBone) diff --git a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs index 4f99a49772..b78bc6700c 100644 --- a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs +++ b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs @@ -9,6 +9,7 @@ [assembly: InternalsVisibleTo("UnityEditor.Advertisements")] [assembly: InternalsVisibleTo("UnityEditor.UIAutomation")] [assembly: InternalsVisibleTo("Unity.Burst")] +[assembly: InternalsVisibleTo("Unity.Burst.Editor")] [assembly: InternalsVisibleTo("Unity.PackageManager")] [assembly: InternalsVisibleTo("Unity.PackageManagerStandalone")] [assembly: InternalsVisibleTo("Unity.Automation")] diff --git a/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs b/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs index 919707b85b..81669bf01f 100644 --- a/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs +++ b/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs @@ -103,9 +103,10 @@ internal static void InitializeBuildCallbacks(BuildCallbacks findFlags) { if (findFlags == previousFlags) return; - previousFlags = findFlags; CleanupBuildCallbacks(); + previousFlags = findFlags; + bool findBuildProcessors = (findFlags & BuildCallbacks.BuildProcessors) == BuildCallbacks.BuildProcessors; bool findSceneProcessors = (findFlags & BuildCallbacks.SceneProcessors) == BuildCallbacks.SceneProcessors; bool findTargetProcessors = (findFlags & BuildCallbacks.BuildTargetProcessors) == BuildCallbacks.BuildTargetProcessors; diff --git a/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs b/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs index 8ac0d9527c..64e5db3c20 100644 --- a/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs +++ b/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs @@ -159,6 +159,7 @@ public override void ShowPlatformBuildOptions() } ShowIl2CppErrorIfNeeded(); + ShowIl2CppDebuggerWarningIfNeeded(); } private void ShowIl2CppErrorIfNeeded() @@ -173,6 +174,15 @@ private void ShowIl2CppErrorIfNeeded() EditorGUILayout.HelpBox(error, MessageType.Error); } + void ShowIl2CppDebuggerWarningIfNeeded() + { + if (PlayerSettings.GetScriptingBackend(BuildTargetGroup.Standalone) != ScriptingImplementation.IL2CPP) + return; + + if (EditorUserBuildSettings.allowDebugging && EditorApplication.scriptingRuntimeVersion != ScriptingRuntimeVersion.Latest) + EditorGUILayout.HelpBox("Script debugging is only supported with IL2CPP on the .NET 4.x scripting runtime.", MessageType.Warning); + } + public override bool EnabledBuildButton() { if (PlayerSettings.GetScriptingBackend(BuildTargetGroup.Standalone) == ScriptingImplementation.Mono2x) diff --git a/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs b/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs index 33938cdab1..eb7096a671 100644 --- a/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs +++ b/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs @@ -296,10 +296,15 @@ protected virtual void CopyVariationFolderIntoStagingArea(BuildPostProcessArgs a var playerFolder = args.playerPackage + "/Variations/" + GetVariationName(args); FileUtil.CopyDirectoryFiltered(playerFolder, args.stagingArea, true, f => CopyPlayerFilter(f, args), recursive: true); + RecordCommonFiles(args, playerFolder, args.stagingAreaData); + } + + protected static void RecordCommonFiles(BuildPostProcessArgs args, string variationSourceFolder, string monoFolderRoot) + { // Mark all the managed DLLs in Data/Managed as engine API assemblies // Data/Managed may already contain managed DLLs in the UnityEngine.*.dll naming scheme from the extensions // So we find the files in the source Variations directory and mark the corresponding files in the output - foreach (var file in Directory.GetFiles(Path.Combine(playerFolder, "Data/Managed"), "*.dll")) + foreach (var file in Directory.GetFiles(Path.Combine(variationSourceFolder, "Data/Managed"), "*.dll")) { var filename = Path.GetFileName(file); if (!filename.StartsWith("UnityEngine")) @@ -310,13 +315,16 @@ protected virtual void CopyVariationFolderIntoStagingArea(BuildPostProcessArgs a } // Mark the default resources file - args.report.RecordFileAdded(Path.Combine(args.stagingArea, "Data/Resources/unity default resources"), CommonRoles.builtInResources); + args.report.RecordFileAdded(Path.Combine(args.stagingArea, "Data/Resources/unity default resources"), + CommonRoles.builtInResources); // Mark up each mono runtime - foreach (var monoName in new[] { "Mono", "MonoBleedingEdge" }) + foreach (var monoName in new[] {"Mono", "MonoBleedingEdge"}) { - args.report.RecordFilesAddedRecursive(Path.Combine(args.stagingArea, "Data/" + monoName + "/EmbedRuntime"), CommonRoles.monoRuntime); - args.report.RecordFilesAddedRecursive(Path.Combine(args.stagingArea, "Data/" + monoName + "/etc"), CommonRoles.monoConfig); + args.report.RecordFilesAddedRecursive(Path.Combine(monoFolderRoot, monoName + "/EmbedRuntime"), + CommonRoles.monoRuntime); + args.report.RecordFilesAddedRecursive(Path.Combine(monoFolderRoot, monoName + "/etc"), + CommonRoles.monoConfig); } } diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs index 31903c2287..bfa7c42b4b 100644 --- a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs +++ b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs @@ -162,7 +162,7 @@ public void Run() if (m_ModifyOutputBeforeCompile != null) m_ModifyOutputBeforeCompile(outputDirectory); - ConvertPlayerDlltoCpp(GetUserAssembliesToConvert(managedDir), outputDirectory, managedDir); + ConvertPlayerDlltoCpp(GetUserAssembliesToConvert(managedDir), outputDirectory, managedDir, m_PlatformProvider.supportsManagedDebugging); var compiler = m_PlatformProvider.CreateNativeCompiler(); if (compiler != null && m_PlatformProvider.CreateIl2CppNativeCodeBuilder() == null) @@ -254,7 +254,7 @@ public static string GetMapFileParserPath() Application.platform == RuntimePlatform.WindowsEditor ? @"Tools\MapFileParser\MapFileParser.exe" : @"Tools/MapFileParser/MapFileParser")); } - private void ConvertPlayerDlltoCpp(ICollection userAssemblies, string outputDirectory, string workingDirectory) + private void ConvertPlayerDlltoCpp(ICollection userAssemblies, string outputDirectory, string workingDirectory, bool platformSupportsManagedDebugging) { if (userAssemblies.Count == 0) return; @@ -281,10 +281,6 @@ private void ConvertPlayerDlltoCpp(ICollection userAssemblies, string ou if (m_BuildForMonoRuntime) arguments.Add("--mono-runtime"); - //Currently In Development, Not yet ready to enable - //if (m_PlatformProvider.enableDebugger) - // arguments.Add("--enable-debugger"); - var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(m_PlatformProvider.target); if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_4_6) arguments.Add("--dotnetprofile=\"unityjit\""); @@ -292,11 +288,13 @@ private void ConvertPlayerDlltoCpp(ICollection userAssemblies, string ou if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_Standard_2_0) arguments.Add("--dotnetprofile=\"unityaot\""); + var useDebugBuild = EditorUserBuildSettings.allowDebugging; + if (useDebugBuild && platformSupportsManagedDebugging && EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) + arguments.Add("--enable-debugger"); + var il2CppNativeCodeBuilder = m_PlatformProvider.CreateIl2CppNativeCodeBuilder(); if (il2CppNativeCodeBuilder != null) { - var useDebugBuild = PlayerSettings.GetIl2CppCompilerConfiguration(buildTargetGroup) == Il2CppCompilerConfiguration.Debug; - Il2CppNativeCodeBuilderUtils.ClearAndPrepareCacheDirectory(il2CppNativeCodeBuilder); arguments.AddRange(Il2CppNativeCodeBuilderUtils.AddBuilderArguments(il2CppNativeCodeBuilder, OutputFileRelativePath(), m_PlatformProvider.includePaths, useDebugBuild)); } @@ -407,7 +405,7 @@ internal interface IIl2CppPlatformProvider bool developmentMode { get; } string moduleStrippingInformationFolder { get; } bool supportsEngineStripping { get; } - bool enableDebugger { get; } + bool supportsManagedDebugging { get; } BuildReport buildReport { get; } string[] includePaths { get; } @@ -460,7 +458,7 @@ public virtual bool supportsEngineStripping get { return false; } } - public virtual bool enableDebugger + public virtual bool supportsManagedDebugging { get { return false; } } diff --git a/Editor/Mono/Burst/BurstCompilerService.bindings.cs b/Editor/Mono/Burst/BurstCompilerService.bindings.cs index e8ef7ca6bd..33a198b7bf 100644 --- a/Editor/Mono/Burst/BurstCompilerService.bindings.cs +++ b/Editor/Mono/Burst/BurstCompilerService.bindings.cs @@ -13,6 +13,7 @@ namespace Unity.Burst.LowLevel { [NativeHeader("Runtime/Burst/Burst.h")] + [NativeHeader("Runtime/Burst/BurstDelegateCache.h")] [StaticAccessor("BurstCompilerService::Get()", StaticAccessorType.Arrow)] internal static partial class BurstCompilerService { @@ -21,6 +22,11 @@ internal static partial class BurstCompilerService public static extern string GetDisassembly(MethodInfo m, string compilerOptions); + [FreeFunction] + public static extern int CompileAsyncDelegateMethod(object delegateMethod, string compilerOptions); + [FreeFunction] + public unsafe static extern void* GetAsyncCompiledAsyncDelegateMethod(int userID); + public static extern bool IsInitialized { get; } } } diff --git a/Editor/Mono/Burst/BurstCompilerService.cs b/Editor/Mono/Burst/BurstCompilerService.cs index 32cfc698ad..298d5e6c5c 100644 --- a/Editor/Mono/Burst/BurstCompilerService.cs +++ b/Editor/Mono/Burst/BurstCompilerService.cs @@ -28,7 +28,7 @@ public static void Initialize(string folderRuntime, ExtractCompilerFlags extract var message = InitializeInternal(folderRuntime, extractCompilerFlags); - if (message != null) + if (!String.IsNullOrEmpty(message)) Debug.LogError($"Unexpected error while trying to initialize the burst JIT compiler: {message}"); } } diff --git a/Editor/Mono/Collab/CollabAnalytics.cs b/Editor/Mono/Collab/CollabAnalytics.cs new file mode 100644 index 0000000000..299ad61831 --- /dev/null +++ b/Editor/Mono/Collab/CollabAnalytics.cs @@ -0,0 +1,32 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Scripting; +using UnityEditor; +using UnityEditorInternal; + +namespace UnityEditor.Collaboration +{ + internal static class CollabAnalytics + { + [Serializable] + private struct CollabUserActionAnalyticsEvent + { + public string category; + public string action; + } + + public static void SendUserAction(string category, string action) + { + EditorAnalytics.SendCollabUserAction(new CollabUserActionAnalyticsEvent() { category = category, action = action }); + } + + public static string historyCategoryString = "History"; + }; +} diff --git a/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs b/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs index 1a9c5ef2a2..a6333b0c22 100644 --- a/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs +++ b/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs @@ -44,11 +44,13 @@ void ToggleDropdown() { if (Contains(m_FilesContainer)) { + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "CollapseAssets"); Remove(m_FilesContainer); m_ToggleLabel.text = ToggleText(false); } else { + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "ExpandAssets"); Add(m_FilesContainer); m_ToggleLabel.text = ToggleText(true); } @@ -67,6 +69,7 @@ private void ShowAllClick() var org = UnityConnect.instance.GetOrganizationId(); var proj = UnityConnect.instance.GetProjectGUID(); var url = string.Format("{0}/collab/orgs/{1}/projects/{2}/commits?commit={3}", host, org, proj, m_RevisionId); + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "ShowAllOnDashboard"); Application.OpenURL(url); } } diff --git a/Editor/Mono/Collab/Views/CollabHistoryItem.cs b/Editor/Mono/Collab/Views/CollabHistoryItem.cs index ab80cb316c..e355e1e66d 100644 --- a/Editor/Mono/Collab/Views/CollabHistoryItem.cs +++ b/Editor/Mono/Collab/Views/CollabHistoryItem.cs @@ -143,6 +143,7 @@ public void SetInProgressStatus(string revisionIdInProgress) void ShowBuildForCommit() { + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "ShowBuild"); if (s_OnShowBuild != null) { s_OnShowBuild(m_RevisionId); @@ -151,6 +152,7 @@ void ShowBuildForCommit() void ShowServicePage() { + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "ShowServices"); if (s_OnShowServices != null) { s_OnShowServices(); @@ -159,6 +161,7 @@ void ShowServicePage() void Restore() { + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "Restore"); if (s_OnRestore != null) { s_OnRestore(m_RevisionId, false); @@ -167,6 +170,7 @@ void Restore() void GoBackTo() { + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "GoBackTo"); if (s_OnGoBack != null) { s_OnGoBack(m_RevisionId, false); @@ -175,6 +179,7 @@ void GoBackTo() void UpdateTo() { + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "Update"); if (s_OnUpdate != null) { s_OnUpdate(m_RevisionId, true); @@ -206,12 +211,14 @@ void ToggleDescription() { if (m_Expanded) { + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "CollapseDescription"); m_Expanded = false; m_ExpandCollapseButton.text = "Show More"; m_Description.text = GetTruncatedDescription(m_FullDescription); } else { + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "ExpandDescription"); m_Expanded = true; m_ExpandCollapseButton.text = "Show Less"; m_Description.text = m_FullDescription; diff --git a/Editor/Mono/Collab/Views/PagedListView.cs b/Editor/Mono/Collab/Views/PagedListView.cs index 2c3a4badfb..6d0ae626be 100644 --- a/Editor/Mono/Collab/Views/PagedListView.cs +++ b/Editor/Mono/Collab/Views/PagedListView.cs @@ -60,6 +60,8 @@ private void OnPageDownClicked() if (m_CurPage <= 0) return; + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "NewerPage"); + m_CurPage--; if (OnPageChange != null) @@ -73,6 +75,8 @@ private void OnPageUpClicked() if (m_CurPage >= m_TotalPages) return; + CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "OlderPage"); + m_CurPage++; if (OnPageChange != null) diff --git a/Editor/Mono/ContainerWindow.cs b/Editor/Mono/ContainerWindow.cs index 87a6b5814c..7f6c01b585 100644 --- a/Editor/Mono/ContainerWindow.cs +++ b/Editor/Mono/ContainerWindow.cs @@ -423,6 +423,7 @@ private void DragTitleBar(Rect titleBarRect) Event.current.Use(); s_LastDragMousePos = GUIUtility.GUIToScreenPoint(evt.mousePosition); dragPosition = position; + Unsupported.SetAllowCursorLock(false, Unsupported.DisallowCursorLockReasons.SizeMove); } break; case EventType.MouseUp: @@ -430,6 +431,7 @@ private void DragTitleBar(Rect titleBarRect) { GUIUtility.hotControl = 0; Event.current.Use(); + Unsupported.SetAllowCursorLock(true, Unsupported.DisallowCursorLockReasons.SizeMove); } break; case EventType.MouseDrag: diff --git a/Editor/Mono/GameView/GameView.cs b/Editor/Mono/GameView/GameView.cs index d6a3407118..901825e588 100644 --- a/Editor/Mono/GameView/GameView.cs +++ b/Editor/Mono/GameView/GameView.cs @@ -336,7 +336,7 @@ private void UpdateZoomAreaAndParent() void AllowCursorLockAndHide(bool enable) { - Unsupported.SetAllowCursorLock(enable); + Unsupported.SetAllowCursorLock(enable, Unsupported.DisallowCursorLockReasons.Other); Unsupported.SetAllowCursorHide(enable); } diff --git a/Editor/Mono/Inspector/Avatar/AvatarEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarEditor.cs index 88d2469f0a..72a9ff4ac9 100644 --- a/Editor/Mono/Inspector/Avatar/AvatarEditor.cs +++ b/Editor/Mono/Inspector/Avatar/AvatarEditor.cs @@ -56,7 +56,7 @@ static void DoWriteAllAssets() protected GameObject prefab { get { return m_Inspector.prefab; } } protected Dictionary modelBones { get { return m_Inspector.m_ModelBones; } } protected Transform root { get { return gameObject == null ? null : gameObject.transform; } } - protected SerializedObject serializedObject { get { return m_Inspector.serializedObject; } } + protected SerializedObject serializedObject { get { return m_Inspector.serializedAssetImporter; } } protected Avatar avatarAsset { get { return m_Inspector.avatar; } } public virtual void Enable(AvatarEditor inspector) @@ -193,6 +193,22 @@ enum EditMode private SceneSetup[] sceneSetup; // These member are used when the avatar is part of an asset + // This is used as a backend by the AvatarSubEditors to serialize + // only the FBXImporter part and not mess up with the Editor's serializedObject. + internal SerializedObject m_SerializedAssetImporter = null; + public SerializedObject serializedAssetImporter + { + get + { + // TODO find a better sync for that and be in better control of the lifetime + if (m_SerializedAssetImporter == null) + { + m_SerializedAssetImporter = CreateSerializedImporterForTarget(target); + } + return m_SerializedAssetImporter; + } + } + internal Avatar avatar { get { return target as Avatar; } } protected bool m_InspectorLocked; @@ -254,14 +270,15 @@ public GameObject prefab } } - internal override SerializedObject GetSerializedObjectInternal() + static private SerializedObject CreateSerializedImporterForTarget(UnityEngine.Object target) { - if (m_SerializedObject == null) - m_SerializedObject = SerializedObject.LoadFromCache(GetInstanceID()); - // Override to make serializedObject be the model importer instead of being the avatar - if (m_SerializedObject == null) - m_SerializedObject = new SerializedObject(AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(target))); - return m_SerializedObject; + SerializedObject so = null; + AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(target)); + if (importer != null) + { + so = new SerializedObject(importer); + } + return so; } void OnEnable() @@ -291,10 +308,11 @@ void OnDisable() editor.Disable(); EditorApplication.update -= Update; - if (m_SerializedObject != null) + + if (m_SerializedAssetImporter != null) { - m_SerializedObject.Cache(GetInstanceID()); - m_SerializedObject = null; + m_SerializedAssetImporter.Cache(GetInstanceID()); + m_SerializedAssetImporter = null; } } @@ -466,12 +484,12 @@ internal void SwitchToEditMode() // Instantiate character m_GameObject = Instantiate(prefab) as GameObject; - if (serializedObject.FindProperty("m_OptimizeGameObjects").boolValue) + if (serializedAssetImporter.FindProperty("m_OptimizeGameObjects").boolValue) AnimatorUtility.DeoptimizeTransformHierarchy(m_GameObject); // First get all available modelBones Dictionary modelBones = AvatarSetupTool.GetModelBones(m_GameObject.transform, true, null); - AvatarSetupTool.BoneWrapper[] humanBones = AvatarSetupTool.GetHumanBones(serializedObject, modelBones); + AvatarSetupTool.BoneWrapper[] humanBones = AvatarSetupTool.GetHumanBones(serializedAssetImporter, modelBones); m_ModelBones = AvatarSetupTool.GetModelBones(m_GameObject.transform, false, humanBones); @@ -544,19 +562,27 @@ internal void SwitchToAssetMode() else EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); + // Make sure that we restore the "original" selection + // globally. + // This should really be done in a more controlled manner + // so that a globally important/observable state (i.e. selection) is not set + // in a "random" very granular piece of control flow and + // by an unrelated editor for which it is not the responsability to do so. + + SelectAsset(); + + if (!m_CameFromImportSettings) + m_EditMode = EditMode.NotEditing; + EditorApplication.update -= CleanUpSceneOnDestroy; }; EditorApplication.update += CleanUpSceneOnDestroy; } + // Reset back the Edit Mode specific states (they probably should be better encapsulated) m_GameObject = null; m_ModelBones = null; - - SelectAsset(); - - if (!m_CameFromImportSettings) - m_EditMode = EditMode.NotEditing; } void ChangeInspectorLock(bool locked) diff --git a/Editor/Mono/Inspector/Avatar/AvatarMuscleEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarMuscleEditor.cs index 39e82817eb..d65f91a1ec 100644 --- a/Editor/Mono/Inspector/Avatar/AvatarMuscleEditor.cs +++ b/Editor/Mono/Inspector/Avatar/AvatarMuscleEditor.cs @@ -607,6 +607,11 @@ public override void OnInspectorGUI() WritePose(); } + if (avatarAsset == null) + { + return; + } + using (new EditorGUI.DisabledScope(!avatarAsset.isHuman)) { EditorGUIUtility.labelWidth = 110; diff --git a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs index 7397e9dbd3..73d6a07ab1 100644 --- a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs @@ -53,7 +53,7 @@ override protected Program StartCompiler() else if (_island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0 && AddCustomResponseFileIfPresent(arguments, "gmcs.rsp")) Debug.LogWarning(string.Format("Using obsolete custom response file 'gmcs.rsp'. Please use '{0}' instead.", ReponseFilename)); } - return StartCompiler(_island._target, GetCompilerPath(arguments), arguments, false, MonoInstallationFinder.GetMonoInstallation(MonoInstallationFinder.MonoBleedingEdgeInstallation)); + return StartCompiler(_island._target, GetCompilerPath(arguments), arguments, BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level), false, MonoInstallationFinder.GetMonoInstallation(MonoInstallationFinder.MonoBleedingEdgeInstallation)); } private string GetCompilerPath(List arguments) diff --git a/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs index e5d00668e0..b0fee0cd32 100644 --- a/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs @@ -15,22 +15,27 @@ protected MonoScriptCompilerBase(MonoIsland island, bool runUpdater) : base(isla } protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments) + { + return StartCompiler(target, compiler, arguments, BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level)); + } + + protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments, string profileDirectory) { AddCustomResponseFileIfPresent(arguments, Path.GetFileNameWithoutExtension(compiler) + ".rsp"); var monoInstallation = (PlayerSettingsEditor.IsLatestApiCompatibility(_island._api_compatibility_level)) ? MonoInstallationFinder.GetMonoBleedingEdgeInstallation() : MonoInstallationFinder.GetMonoInstallation(); - return StartCompiler(target, compiler, arguments, true, monoInstallation); + return StartCompiler(target, compiler, arguments, profileDirectory, true, monoInstallation); } - protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments, bool setMonoEnvironmentVariables, string monodistro) + protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments, string profileDirectory, bool setMonoEnvironmentVariables, string monodistro) { var responseFile = CommandLineFormatter.GenerateResponseFile(arguments); RunAPIUpdaterIfRequired(responseFile); - var program = new ManagedProgram(monodistro, BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level), compiler, " @" + responseFile, setMonoEnvironmentVariables, null); + var program = new ManagedProgram(monodistro, profileDirectory, compiler, " @" + responseFile, setMonoEnvironmentVariables, null); program.Start(); return program; diff --git a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs index a013f6ae4a..3eaf64db76 100644 --- a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs @@ -141,28 +141,91 @@ public static ResponseFileData ParseResponseFileFromFile(string responseFileName return ParseResponseFileText(responseFileText); } - public static ResponseFileData ParseResponseFileText(string responseFileText) + // From: + // https://github.com/mono/mono/blob/c106cdc775792ceedda6da58de7471f9f5c0b86c/mcs/mcs/settings.cs + // + // settings.cs: All compiler settings + // + // Author: Miguel de Icaza (miguel@ximian.com) + // Ravi Pratap (ravi@ximian.com) + // Marek Safar (marek.safar@gmail.com) + // + // + // Dual licensed under the terms of the MIT X11 or GNU GPL + // + // Copyright 2001 Ximian, Inc (http://www.ximian.com) + // Copyright 2004-2008 Novell, Inc + // Copyright 2011 Xamarin, Inc (http://www.xamarin.com) + static string[] ResponseFileTextToStrings(string responseFileText) { - var compilerOptions = new List(); + var args = new List(); - var textLines = responseFileText.Split(' ', '\n'); + var sb = new System.Text.StringBuilder(); + + var textLines = responseFileText.Split('\n', '\r'); foreach (var line in textLines) { - var trimmedLine = line.Trim(); + int t = line.Length; + + for (int i = 0; i < t; i++) + { + char c = line[i]; + + if (c == '"' || c == '\'') + { + char end = c; + + for (i++; i < t; i++) + { + c = line[i]; + + if (c == end) + break; + sb.Append(c); + } + } + else if (c == ' ') + { + if (sb.Length > 0) + { + args.Add(sb.ToString()); + sb.Length = 0; + } + } + else + sb.Append(c); + } + if (sb.Length > 0) + { + args.Add(sb.ToString()); + sb.Length = 0; + } + } + + return args.ToArray(); + } - int idx = trimmedLine.IndexOf(':'); + public static ResponseFileData ParseResponseFileText(string responseFileText) + { + var compilerOptions = new List(); + + var responseFileStrings = ResponseFileTextToStrings(responseFileText); + + foreach (var line in responseFileStrings) + { + int idx = line.IndexOf(':'); string arg, value; if (idx == -1) { - arg = trimmedLine; + arg = line; value = ""; } else { - arg = trimmedLine.Substring(0, idx); - value = trimmedLine.Substring(idx + 1); + arg = line.Substring(0, idx); + value = line.Substring(idx + 1); } if (!string.IsNullOrEmpty(arg) && arg[0] == '-') diff --git a/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs b/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs index a3fde9d7bf..c4221efcee 100644 --- a/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs @@ -14,6 +14,7 @@ namespace UnityEditor.Scripting.Compilers class UnityScriptCompiler : MonoScriptCompilerBase { private static readonly Regex UnityEditorPattern = new Regex(@"UnityEditor\.dll$", RegexOptions.ExplicitCapture); + const string k_UnityScriptProfileDirectory = "unityscript"; public UnityScriptCompiler(MonoIsland island, bool runUpdater) : base(island, runUpdater) { @@ -58,8 +59,24 @@ override protected Program StartCompiler() foreach (string source in _island._files) arguments.Add(PrepareFileName(source)); - var compilerPath = Path.Combine(GetMonoProfileLibDirectory(), "us.exe"); - return StartCompiler(_island._target, compilerPath, arguments); + var compilerPath = Path.Combine(GetUnityScriptCompilerDirectory(), "us.exe"); + return StartCompiler(_island._target, compilerPath, arguments, GetUnityScriptProfileDirectory()); + } + + string GetUnityScriptCompilerDirectory() + { + if (PlayerSettings.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) + return GetMonoProfileLibDirectory(); + + return Path.Combine(MonoInstallationFinder.GetProfilesDirectory(MonoInstallationFinder.MonoBleedingEdgeInstallation), k_UnityScriptProfileDirectory); + } + + string GetUnityScriptProfileDirectory() + { + if (PlayerSettings.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) + return BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level); + + return k_UnityScriptProfileDirectory; } private bool StrictBuildTarget() diff --git a/Editor/Mono/SyncProject.cs b/Editor/Mono/SyncProject.cs index 005f7ea16a..e68103aa66 100644 --- a/Editor/Mono/SyncProject.cs +++ b/Editor/Mono/SyncProject.cs @@ -56,8 +56,6 @@ static SyncVS() } SetVisualStudioAsEditorIfNoEditorWasSet(); - - UnityVSSupport.Initialize(); } private static void SetVisualStudioAsEditorIfNoEditorWasSet() diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs index 4759cfb1c6..251006e60d 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs @@ -127,6 +127,17 @@ public virtual string GetProjectHeaderTemplate(ScriptingLanguage language) @" 0169", @" {12}", @" ", + }; + + var forceExplicitReferences = new string[] { + @" ", + @" true", + @" true", + @" false", + @" ", + }; + + var itemGroupStart = new[] { @" ", }; @@ -153,9 +164,9 @@ public virtual string GetProjectHeaderTemplate(ScriptingLanguage language) string[] text; if (language == ScriptingLanguage.CSharp) - text = header.Concat(footer).ToArray(); + text = header.Concat(forceExplicitReferences).Concat(itemGroupStart).Concat(footer).ToArray(); else - text = header.Concat(systemReferences).Concat(footer).ToArray(); + text = header.Concat(itemGroupStart).Concat(systemReferences).Concat(footer).ToArray(); return string.Join("\r\n", text); } diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index da5ce40aff..d78bd30bc3 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -109,11 +109,9 @@ public bool ShouldFileBePartOfSolution(string file) string extension = Path.GetExtension(file); // Exclude files coming from packages except if they are internalized. - if (AssetDatabase.IsPackagedAssetPath(file)) + if (IsNonInternalizedPackagePath(file)) { - var absolutePath = Path.GetFullPath(file).ConvertSeparatorsToUnity(); - if (!absolutePath.StartsWith(_projectDirectory)) - return false; + return false; } // Dll's are not scripts but still need to be included.. @@ -248,11 +246,9 @@ Dictionary GenerateAllAssetProjectParts() foreach (string asset in AssetDatabase.GetAllAssetPaths()) { // Exclude files coming from packages except if they are internalized. - if (AssetDatabase.IsPackagedAssetPath(asset)) + if (IsNonInternalizedPackagePath(asset)) { - var absolutePath = Path.GetFullPath(asset).ConvertSeparatorsToUnity(); - if (!absolutePath.StartsWith(_projectDirectory)) - continue; + continue; } string extension = Path.GetExtension(asset); @@ -285,6 +281,18 @@ Dictionary GenerateAllAssetProjectParts() return result; } + bool IsNonInternalizedPackagePath(string file) + { + if (AssetDatabase.IsPackagedAssetPath(file)) + { + //@TODO: After 2018.1 this should be done using AssetDatabase.GetAssetFolderInfo + var absolutePath = Path.GetFullPath(file).ConvertSeparatorsToUnity(); + return !absolutePath.StartsWith(_projectDirectory.ConvertSeparatorsToUnity()); + } + return false; + } + + void SyncProject(MonoIsland island, Dictionary allAssetsProjectParts, ScriptCompilerBase.ResponseFileData responseFileData, @@ -350,12 +358,10 @@ string ProjectText(MonoIsland island, ScriptCompilerBase.ResponseFileData responseFileData, List allProjectIslands) { - var projectBuilder = new StringBuilder(ProjectHeader(island, responseFileData.Defines)); + var projectBuilder = new StringBuilder(ProjectHeader(island, responseFileData)); var references = new List(); var projectReferences = new List(); Match match; - string extension; - string fullFile; bool isBuildingEditorProject = island._output.EndsWith("-Editor.dll"); foreach (string file in island._files) @@ -363,13 +369,12 @@ string ProjectText(MonoIsland island, if (!ShouldFileBePartOfSolution(file)) continue; - extension = Path.GetExtension(file).ToLower(); - fullFile = Path.IsPathRooted(file) ? file : Path.Combine(_projectDirectory, file); - + var extension = Path.GetExtension(file).ToLower(); + var fullFile = EscapedRelativePathFor(file); if (".dll" != extension) { var tagName = "Compile"; - projectBuilder.AppendFormat(" <{0} Include=\"{1}\" />{2}", tagName, EscapedRelativePathFor(fullFile), WindowsNewline); + projectBuilder.AppendFormat(" <{0} Include=\"{1}\" />{2}", tagName, fullFile, WindowsNewline); } else { @@ -466,7 +471,8 @@ internal string SolutionFile() return Path.Combine(_projectDirectory, string.Format("{0}.sln", _projectName)); } - private string ProjectHeader(MonoIsland island, string[] additionalDefines) + private string ProjectHeader(MonoIsland island, + ScriptCompilerBase.ResponseFileData responseFileData) { string targetframeworkversion = "v3.5"; string targetLanguageVersion = "4"; @@ -495,14 +501,14 @@ private string ProjectHeader(MonoIsland island, string[] additionalDefines) toolsversion, productversion, ProjectGuid(island._output), _settings.EngineAssemblyPath, _settings.EditorAssemblyPath, - string.Join(";", new[] { "DEBUG", "TRACE"}.Concat(_settings.Defines).Concat(island._defines).Concat(additionalDefines).Distinct().ToArray()), + string.Join(";", new[] { "DEBUG", "TRACE"}.Concat(_settings.Defines).Concat(island._defines).Concat(responseFileData.Defines).Distinct().ToArray()), MSBuildNamespaceUri, Path.GetFileNameWithoutExtension(island._output), EditorSettings.projectGenerationRootNamespace, targetframeworkversion, targetLanguageVersion, baseDirectory, - island._allowUnsafeCode + island._allowUnsafeCode | responseFileData.Unsafe }; try @@ -579,15 +585,13 @@ private string GetProjectActiveConfigurations(string projectGuid) private string EscapedRelativePathFor(string file) { + if (AssetDatabase.IsPackagedAssetPath(file.ConvertSeparatorsToUnity())) + file = Path.GetFullPath(file.ConvertSeparatorsToUnity()).ConvertSeparatorsToWindows(); + var projectDir = _projectDirectory.ConvertSeparatorsToWindows(); - file = file.ConvertSeparatorsToWindows(); - var path = Paths.SkipPathPrefix(file, projectDir); - if (AssetDatabase.IsPackagedAssetPath(path.ConvertSeparatorsToUnity())) - { - var absolutePath = Path.GetFullPath(path).ConvertSeparatorsToWindows(); - path = Paths.SkipPathPrefix(absolutePath, projectDir); - } - return SecurityElement.Escape(path); + file = Paths.SkipPathPrefix(file.ConvertSeparatorsToWindows(), projectDir); + + return SecurityElement.Escape(file); } string ProjectGuid(string assembly) diff --git a/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs b/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs index e2aadd7eea..dedc4a100e 100644 --- a/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs +++ b/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs @@ -27,11 +27,6 @@ public static void InitializeUnityVSSupport() Initialize(null); } - public static void Initialize() - { - Initialize(null); - } - public static void Initialize(string editorPath) { var externalEditor = editorPath ?? ScriptEditorUtility.GetExternalScriptEditor(); diff --git a/Extensions/Networking/Weaver/UNetBehaviourProcessor.cs b/Extensions/Networking/Weaver/UNetBehaviourProcessor.cs index 525b712890..4bcdf3b19b 100644 --- a/Extensions/Networking/Weaver/UNetBehaviourProcessor.cs +++ b/Extensions/Networking/Weaver/UNetBehaviourProcessor.cs @@ -2214,6 +2214,7 @@ void ProcessSyncVars() fieldModuleName != Weaver.m_UnityAssemblyDefinition.MainModule.Name && fieldModuleName != Weaver.m_UNetAssemblyDefinition.MainModule.Name && fieldModuleName != Weaver.corLib.Name && + fieldModuleName != "netstandard.dll" && fieldModuleName != "System.Runtime.dll" // this is only for Metro, built-in types are not in corlib on metro ) { diff --git a/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs b/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs index 82a3948cfa..365bb220f7 100644 --- a/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs +++ b/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs @@ -40,6 +40,11 @@ internal static bool SendEventSceneViewInfo(object parameters) return EditorAnalytics.SendEvent("sceneViewInfo", parameters); } + internal static bool SendCollabUserAction(object parameters) + { + return EditorAnalytics.SendEvent("collabUserAction", parameters); + } + public extern static bool enabled { get; diff --git a/Projects/CSharp/UnityEditor.csproj b/Projects/CSharp/UnityEditor.csproj index 6503599b49..72c1c527fc 100644 --- a/Projects/CSharp/UnityEditor.csproj +++ b/Projects/CSharp/UnityEditor.csproj @@ -2288,6 +2288,9 @@ Editor\Mono\Collab\AssetAccess.cs + +Editor\Mono\Collab\CollabAnalytics.cs + Editor\Mono\Collab\Collab.bindings.cs diff --git a/README.md b/README.md index c5910e9906..7db2e9f2bb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.1.0b9 C# reference source code +## Unity 2018.1.0b10 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Dynamics/ScriptBindings/RaycastCommand.bindings.cs b/Runtime/Dynamics/ScriptBindings/RaycastCommand.bindings.cs index 5a53022a7e..d226a49625 100644 --- a/Runtime/Dynamics/ScriptBindings/RaycastCommand.bindings.cs +++ b/Runtime/Dynamics/ScriptBindings/RaycastCommand.bindings.cs @@ -35,7 +35,7 @@ public RaycastCommand(Vector3 from, Vector3 direction, float distance = float.Ma var jobData = new BatchQueryJob(commands, results); var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), BatchQueryJobStruct>.Initialize(), dependsOn, ScheduleMode.Batched); - return ScheduleRaycastBatch(ref scheduleParams, commands.GetUnsafePtr(), commands.Length, results.GetUnsafePtr(), results.Length, minCommandsPerJob); + return ScheduleRaycastBatch(ref scheduleParams, NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(commands), commands.Length, NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(results), results.Length, minCommandsPerJob); } [FreeFunction("ScheduleRaycastCommandBatch")] diff --git a/Runtime/Export/NativeArray/NativeArray.cs b/Runtime/Export/NativeArray/NativeArray.cs index f6d0fec2aa..988c0477ff 100644 --- a/Runtime/Export/NativeArray/NativeArray.cs +++ b/Runtime/Export/NativeArray/NativeArray.cs @@ -9,6 +9,7 @@ using System.Runtime.InteropServices; using Unity.Burst; using Unity.Collections.LowLevel.Unsafe; +using UnityEngine.Internal; namespace Unity.Collections { @@ -148,7 +149,12 @@ public T[] ToArray() } - public IEnumerator GetEnumerator() + public Enumerator GetEnumerator() + { + return new Enumerator(ref this); + } + + IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(ref this); } @@ -158,7 +164,8 @@ IEnumerator IEnumerable.GetEnumerator() return GetEnumerator(); } - internal struct Enumerator : IEnumerator + [ExcludeFromDocs] + public struct Enumerator : IEnumerator { private NativeArray m_Array; private int m_Index; @@ -249,7 +256,7 @@ unsafe public static NativeArray ConvertExistingDataToNativeArray(void* da return nativeArray.m_Buffer; } - unsafe public static void* GetUnsafeBufferPointerWithoutChecks(this NativeArray nativeArray) where T : struct + unsafe public static void* GetUnsafeBufferPointerWithoutChecks(NativeArray nativeArray) where T : struct { return nativeArray.m_Buffer; } diff --git a/Runtime/Export/NativeArray/NativeSlice.cs b/Runtime/Export/NativeArray/NativeSlice.cs index 12309e87d0..377e43768d 100644 --- a/Runtime/Export/NativeArray/NativeSlice.cs +++ b/Runtime/Export/NativeArray/NativeSlice.cs @@ -8,6 +8,7 @@ using System.Diagnostics; using System.Runtime.InteropServices; using Unity.Collections.LowLevel.Unsafe; +using UnityEngine.Internal; namespace Unity.Collections { @@ -117,18 +118,29 @@ public NativeSlice SliceWithStride() where U : struct return SliceWithStride(0); } + // These are double-whammy excluded to we can elide bounds checks in the Burst disassembly view + [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] + private void CheckReadIndex(int index) + { + } + + [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")] + private void CheckWriteIndex(int index) + { + } + public unsafe T this[int index] { get { - + CheckReadIndex(index); return UnsafeUtility.ReadArrayElementWithStride(m_Buffer, index, m_Stride); } [WriteAccessRequired] set { - + CheckWriteIndex(index); UnsafeUtility.WriteArrayElementWithStride(m_Buffer, index, m_Stride, value); } } @@ -173,7 +185,12 @@ public T[] ToArray() public int Stride { get { return m_Stride; } } public int Length { get { return m_Length; } } - public IEnumerator GetEnumerator() + public Enumerator GetEnumerator() + { + return new Enumerator(ref this); + } + + IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(ref this); } @@ -183,7 +200,8 @@ IEnumerator IEnumerable.GetEnumerator() return GetEnumerator(); } - internal struct Enumerator : IEnumerator + [ExcludeFromDocs] + public struct Enumerator : IEnumerator { private NativeSlice m_Array; private int m_Index; diff --git a/Runtime/Export/RenderPipeline/RenderPipeline.cs b/Runtime/Export/RenderPipeline/RenderPipeline.cs index 0deca44bcf..791beaed7c 100644 --- a/Runtime/Export/RenderPipeline/RenderPipeline.cs +++ b/Runtime/Export/RenderPipeline/RenderPipeline.cs @@ -9,6 +9,7 @@ namespace UnityEngine.Experimental.Rendering public abstract class RenderPipeline : IRenderPipeline { public static event Action beginFrameRendering; + public static event Action beginCameraRendering; public virtual void Render(ScriptableRenderContext renderContext, Camera[] cameras) { @@ -27,5 +28,10 @@ public static void BeginFrameRendering(Camera[] cameras) { beginFrameRendering?.Invoke(cameras); } + + public static void BeginCameraRendering(Camera camera) + { + beginCameraRendering?.Invoke(camera); + } } } diff --git a/Runtime/Export/Unsafe/UnsafeUtility.bindings.cs b/Runtime/Export/Unsafe/UnsafeUtility.bindings.cs index 1a272a5e7f..ae1d40bbf9 100644 --- a/Runtime/Export/Unsafe/UnsafeUtility.bindings.cs +++ b/Runtime/Export/Unsafe/UnsafeUtility.bindings.cs @@ -54,6 +54,9 @@ public static unsafe bool IsBlittable() where T : struct [ThreadSafe] unsafe public static extern void Free(void* memory, Allocator allocator); + public static bool IsValidAllocator(Allocator allocator) { return allocator > Allocator.None; } + + [ThreadSafe] unsafe public static extern void MemCpy(void* destination, void* source, long size); diff --git a/artifacts/generated/bindings_old/common/Editor/PlayerSettingsSwitchBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/PlayerSettingsSwitchBindings.gen.cs index e29366035c..dd0876a656 100644 --- a/artifacts/generated/bindings_old/common/Editor/PlayerSettingsSwitchBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/PlayerSettingsSwitchBindings.gen.cs @@ -161,6 +161,16 @@ public extern static bool useSwitchCPUProfiler set; } + public extern static int queueCommandMemory + { + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + get; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + set; + } + public extern static Switch.ScreenResolutionBehavior screenResolutionBehavior { [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration diff --git a/artifacts/generated/bindings_old/common/Editor/UnsupportedBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/UnsupportedBindings.gen.cs index 1a7b3cf7b0..9d99cf2a1b 100644 --- a/artifacts/generated/bindings_old/common/Editor/UnsupportedBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/UnsupportedBindings.gen.cs @@ -103,9 +103,19 @@ public static bool IsDeveloperBuild() [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern public static void SetAllowCursorHide (bool allow) ; + internal enum DisallowCursorLockReasons + { + None = 0, + PlayPause = 1 << 0, + Other = 1 << 1, + Focus = 1 << 2, + SizeMove = 1 << 3, + }; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] - extern public static void SetAllowCursorLock (bool allow) ; + extern internal static void SetAllowCursorLock (bool allow, DisallowCursorLockReasons reasons) ; public static bool SetOverrideRenderSettings(Scene scene) { From 11bcfd801fccd2a52b09bb6fd636c1ddcc9f1705 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Fri, 16 Mar 2018 13:01:57 +0000 Subject: [PATCH 10/17] Unity 2018.1.0b11 C# reference source code --- Editor/Mono/AssemblyHelper.cs | 32 +++- .../Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs | 19 +- Editor/Mono/Collab/CollabHistoryWindow.cs | 22 ++- .../Presenters/CollabHistoryPresenter.cs | 11 +- .../Mono/Collab/Views/ICollabHistoryWindow.cs | 2 +- Editor/Mono/Collab/Views/PagedListView.cs | 175 ++++++++---------- Editor/Mono/ConsoleWindow.cs | 82 ++++---- Editor/Mono/EditorWindow.cs | 2 + Editor/Mono/GUI/ColorPicker.cs | 2 +- Editor/Mono/GUI/QuadTree.cs | 9 +- Editor/Mono/GradientPreviewCache.bindings.cs | 1 + .../ImportSettings/ModelImporterRigEditor.cs | 4 +- .../Mono/Inspector/BillboardAssetInspector.cs | 2 +- Editor/Mono/Inspector/ModelInspector.cs | 2 +- .../PlayerSettingsEditor.cs | 2 +- .../ParticleSystemModules/ShapeModuleUI.cs | 2 +- Editor/Mono/PerformanceTools/FrameDebugger.cs | 2 +- .../PreferencesWindow/PreferencesWindow.cs | 2 +- .../Mono/SceneModeWindows/LightingWindow.cs | 16 +- .../Mono/SceneModeWindows/SceneModeUtility.cs | 17 +- .../Scripting/Compilers/ScriptCompilerBase.cs | 10 + .../ScriptCompilation/EditorCompilation.cs | 61 +++++- Modules/AI/NavMeshExperimental.bindings.cs | 58 +++--- .../Managed/PlayerBuildInterface.bindings.cs | 3 + Modules/IMGUI/GUILayoutUtility.cs | 96 ++++------ .../ScriptBindings/Physics2D.bindings.cs | 11 ++ .../ProfilerWindow/ProfilerDetailedView.cs | 6 +- Modules/SharedInternals/BindingsAttributes.cs | 12 ++ .../AnalyticsSessionInfo.bindings.cs | 1 + Modules/XR/DotNetHelper.cs | 27 +++ .../Camera/XRCameraSubsystem.bindings.cs | 77 ++++++++ .../XRCameraSubsystemDescriptor.bindings.cs | 12 +- .../Depth/XRDepthSubsystem.bindings.cs | 66 +++++++ .../XRDepthSubsystemDescriptor.bindings.cs} | 16 +- .../Environment/Depth/XRDepth.bindings.cs | 110 ----------- .../XRReferencePoint.bindings.cs | 110 ----------- .../Environment/Session/XRSession.bindings.cs | 86 --------- .../Environment/XREnvironment.bindings.cs | 145 --------------- ...EnvironmentSubsystemDescriptor.bindings.cs | 30 --- ...ings.cs => XRExampleSubsystem.bindings.cs} | 4 +- .../XRExampleSubsystemDescriptor.bindings.cs | 2 +- ...ndings.cs => XRInputSubsystem.bindings.cs} | 4 +- .../XRInputSubsystemDescriptor.bindings.cs | 2 +- .../XRPlaneSubsystem.bindings.cs} | 113 +++-------- .../XRPlaneSubsystemDescriptor.bindings.cs | 19 ++ .../XRRaycastSubsystem.bindings.cs} | 100 ++++------ .../XRRaycastSubsystemDescriptor.bindings.cs | 20 ++ .../XRReferencePointSubsystem.bindings.cs | 79 ++++++++ ...erencePointSubsystemDescriptor.bindings.cs | 20 ++ .../Session/XRSessionSubsystem.bindings.cs | 56 ++++++ .../XRSessionSubsystemDescriptor.bindings.cs | 20 ++ Modules/XR/UnityXRTrackable.bindings.cs | 63 +++++++ Modules/XR/XRSubsystemManager.bindings.cs | 74 ++++---- Projects/CSharp/UnityEngine.csproj | 63 ++++--- README.md | 2 +- .../AR/ScriptBindings/ARBackgroundRenderer.cs | 16 +- .../ScriptBindings/Animator.bindings.cs | 21 ++- Runtime/Export/Graphics.cs | 4 + Runtime/Export/GraphicsComponents.bindings.cs | 2 + Runtime/Export/NativeArray/NativeSlice.cs | 8 +- .../HoloLens/ScriptBindings/GestureSource.cs | 4 +- .../common/Core/RecorderBindings.gen.cs | 11 +- .../PlayerSettingsAndroidBindings.gen.cs | 4 + 63 files changed, 1037 insertions(+), 1017 deletions(-) create mode 100644 Modules/XR/DotNetHelper.cs create mode 100644 Modules/XR/Subsystems/Camera/XRCameraSubsystem.bindings.cs create mode 100644 Modules/XR/Subsystems/Depth/XRDepthSubsystem.bindings.cs rename Modules/XR/Subsystems/{Camera/XRCameraInstance.bindings.cs => Depth/XRDepthSubsystemDescriptor.bindings.cs} (50%) delete mode 100644 Modules/XR/Subsystems/Environment/Depth/XRDepth.bindings.cs delete mode 100644 Modules/XR/Subsystems/Environment/ReferencePoints/XRReferencePoint.bindings.cs delete mode 100644 Modules/XR/Subsystems/Environment/Session/XRSession.bindings.cs delete mode 100644 Modules/XR/Subsystems/Environment/XREnvironment.bindings.cs delete mode 100644 Modules/XR/Subsystems/Environment/XREnvironmentSubsystemDescriptor.bindings.cs rename Modules/XR/Subsystems/Example/{XRExampleInstance.bindings.cs => XRExampleSubsystem.bindings.cs} (88%) rename Modules/XR/Subsystems/Input/{XRInputInstance.bindings.cs => XRInputSubsystem.bindings.cs} (76%) rename Modules/XR/Subsystems/{Environment/Planes/XRPlane.bindings.cs => Planes/XRPlaneSubsystem.bindings.cs} (57%) create mode 100644 Modules/XR/Subsystems/Planes/XRPlaneSubsystemDescriptor.bindings.cs rename Modules/XR/Subsystems/{Environment/Raycast/XRRaycast.bindings.cs => Raycast/XRRaycastSubsystem.bindings.cs} (50%) create mode 100644 Modules/XR/Subsystems/Raycast/XRRaycastSubsystemDescriptor.bindings.cs create mode 100644 Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystem.bindings.cs create mode 100644 Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystemDescriptor.bindings.cs create mode 100644 Modules/XR/Subsystems/Session/XRSessionSubsystem.bindings.cs create mode 100644 Modules/XR/Subsystems/Session/XRSessionSubsystemDescriptor.bindings.cs create mode 100644 Modules/XR/UnityXRTrackable.bindings.cs diff --git a/Editor/Mono/AssemblyHelper.cs b/Editor/Mono/AssemblyHelper.cs index 050de9db4d..094342ac49 100644 --- a/Editor/Mono/AssemblyHelper.cs +++ b/Editor/Mono/AssemblyHelper.cs @@ -75,20 +75,34 @@ static AssemblyDefinition GetAssemblyDefinitionCached(string path, Dictionary userAssemblies, string ou if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_Standard_2_0) arguments.Add("--dotnetprofile=\"unityaot\""); - var useDebugBuild = EditorUserBuildSettings.allowDebugging; - if (useDebugBuild && platformSupportsManagedDebugging && EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) + if (EditorUserBuildSettings.allowDebugging && platformSupportsManagedDebugging && EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) arguments.Add("--enable-debugger"); var il2CppNativeCodeBuilder = m_PlatformProvider.CreateIl2CppNativeCodeBuilder(); if (il2CppNativeCodeBuilder != null) { + var useDebugBuild = PlayerSettings.GetIl2CppCompilerConfiguration(buildTargetGroup) == Il2CppCompilerConfiguration.Debug; + Il2CppNativeCodeBuilderUtils.ClearAndPrepareCacheDirectory(il2CppNativeCodeBuilder); arguments.AddRange(Il2CppNativeCodeBuilderUtils.AddBuilderArguments(il2CppNativeCodeBuilder, OutputFileRelativePath(), m_PlatformProvider.includePaths, useDebugBuild)); } @@ -329,6 +331,19 @@ private void ConvertPlayerDlltoCpp(ICollection userAssemblies, string ou if (il2CppNativeCodeBuilder != null) setupStartInfo = il2CppNativeCodeBuilder.SetupStartInfo; + if (PlayerBuildInterface.ExtraTypesProvider != null) + { + var extraTypes = new HashSet(); + foreach (var extraType in PlayerBuildInterface.ExtraTypesProvider()) + { + extraTypes.Add(extraType); + } + + var tempFile = Path.GetFullPath(Path.Combine(m_TempFolder, "extra-types.txt")); + File.WriteAllLines(tempFile, extraTypes.ToArray()); + arguments.Add(string.Format("--extra-types-file=\"{0}\"", tempFile)); + } + RunIl2CppWithArguments(arguments, setupStartInfo, workingDirectory); } diff --git a/Editor/Mono/Collab/CollabHistoryWindow.cs b/Editor/Mono/Collab/CollabHistoryWindow.cs index 2ce8141e60..1066c06c29 100644 --- a/Editor/Mono/Collab/CollabHistoryWindow.cs +++ b/Editor/Mono/Collab/CollabHistoryWindow.cs @@ -38,6 +38,7 @@ public static bool ValidateShowHistoryWindow() HistoryState m_State; VisualElement m_Container; PagedListView m_Pager; + ScrollView m_HistoryView; int m_ItemsPerPage = 5; string m_InProgressRev; bool m_RevisionActionsEnabled; @@ -100,7 +101,6 @@ public void SetupGUI() m_Pager = new PagedListView() { name = "PagedElement", - PagerLoc = PagerLocation.Top, pageSize = m_ItemsPerPage }; @@ -140,9 +140,9 @@ public void SetupGUI() message = "Updating...", }; - var historyView = new ScrollView() { name = "HistoryContainer", showHorizontal = false}; - historyView.contentContainer.StretchToParentWidth(); - historyView.Add(m_Pager); + m_HistoryView = new ScrollView() { name = "HistoryContainer", showHorizontal = false}; + m_HistoryView.contentContainer.StretchToParentWidth(); + m_HistoryView.Add(m_Pager); m_Views = new Dictionary() { @@ -152,7 +152,7 @@ public void SetupGUI() {HistoryState.LoggedOut, loginView}, {HistoryState.NoSeat, noSeatView}, {HistoryState.Waiting, waitingView}, - {HistoryState.Ready, historyView} + {HistoryState.Ready, m_HistoryView} }; } @@ -176,7 +176,7 @@ public void UpdateState(HistoryState state, bool force) m_Container.Add(m_Views[m_State]); } - public void UpdateRevisions(IEnumerable datas, string tip, int totalRevisions) + public void UpdateRevisions(IEnumerable datas, string tip, int totalRevisions, int currentPage) { var elements = new List(); var isFullDateObtained = false; // Has everything from this date been obtained? @@ -219,7 +219,9 @@ public void UpdateRevisions(IEnumerable datas, string tip, int tot } } + m_HistoryView.scrollOffset = new Vector2(0, 0); m_Pager.totalItems = totalRevisions; + m_Pager.curPage = currentPage; m_Pager.items = elements; } @@ -248,7 +250,7 @@ public int itemsPerPage public PageChangeAction OnPageChangeAction { - set { m_Pager.OnPageChange = value; } + set { m_Pager.OnPageChanged = value; } } public RevisionAction OnGoBackAction @@ -276,11 +278,11 @@ public Action OnShowServicesAction set { CollabHistoryItem.s_OnShowServices = value; } } - private void UpdateHistoryView(VisualElement history) + void UpdateHistoryView(VisualElement history) { } - private void NoSeatClick() + void NoSeatClick() { var connection = UnityConnect.instance; var env = connection.GetEnvironment(); @@ -297,7 +299,7 @@ private void NoSeatClick() Application.OpenURL(url); } - private void SignInClick() + void SignInClick() { UnityConnect.instance.ShowLogin(); } diff --git a/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs b/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs index c45321ec0c..9344df8b71 100644 --- a/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs +++ b/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs @@ -19,6 +19,7 @@ internal class CollabHistoryPresenter bool m_IsCollabError; int m_TotalRevisions; int m_CurrentPage; + int m_RequestedPage; bool m_FetchInProgress; BuildAccess m_BuildAccess; @@ -134,7 +135,8 @@ string tip private void OnCollabRevisionUpdated(CollabInfo state) { - OnUpdatePage(m_CurrentPage); + if (m_CollabState.tip != state.tip) + OnUpdatePage(m_CurrentPage); } private void OnCollabJobsCompleted(CollabInfo state) @@ -151,6 +153,8 @@ private void OnCollabError() private void OnCollabErrorCleared() { m_IsCollabError = false; + m_FetchInProgress = true; + m_Service.GetRevisions(m_CurrentPage * k_ItemsPerPage, k_ItemsPerPage); m_Window.UpdateState(RecalculateState(), false); } @@ -231,7 +235,7 @@ public void OnUpdatePage(int page) m_FetchInProgress = true; m_Service.GetRevisions(page * k_ItemsPerPage, k_ItemsPerPage); m_Window.UpdateState(RecalculateState(), false); - m_CurrentPage = page; + m_RequestedPage = page; } private void OnFetchRevisions(RevisionsResult data) @@ -240,13 +244,14 @@ private void OnFetchRevisions(RevisionsResult data) IEnumerable items = null; if (data != null) { + m_CurrentPage = m_RequestedPage; m_TotalRevisions = data.RevisionsInRepo; items = m_Factory.GenerateElements(data.Revisions, m_TotalRevisions, m_CurrentPage * k_ItemsPerPage, m_Service.tipRevision, m_Window.inProgressRevision, m_Window.revisionActionsEnabled, BuildServiceEnabled, m_Service.currentUser); } // State must be recalculated prior to inserting items m_Window.UpdateState(RecalculateState(), false); - m_Window.UpdateRevisions(items, m_Service.tipRevision, m_TotalRevisions); + m_Window.UpdateRevisions(items, m_Service.tipRevision, m_TotalRevisions, m_CurrentPage); } private void OnRestore(string revisionId, bool updatetorevision) diff --git a/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs b/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs index 9e9f4d017b..df3f721b2f 100644 --- a/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs +++ b/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs @@ -65,7 +65,7 @@ internal struct ChangeData internal interface ICollabHistoryWindow { void UpdateState(HistoryState state, bool force); - void UpdateRevisions(IEnumerable items, string tip, int totalRevisions); + void UpdateRevisions(IEnumerable items, string tip, int totalRevisions, int currentPage); bool revisionActionsEnabled { get; set; } int itemsPerPage { set; } diff --git a/Editor/Mono/Collab/Views/PagedListView.cs b/Editor/Mono/Collab/Views/PagedListView.cs index 6d0ae626be..40e0a3305e 100644 --- a/Editor/Mono/Collab/Views/PagedListView.cs +++ b/Editor/Mono/Collab/Views/PagedListView.cs @@ -4,27 +4,34 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using UnityEngine.Experimental.UIElements; using UnityEngine.Experimental.UIElements.StyleEnums; namespace UnityEditor.Collaboration { - internal class PagerElement : VisualElement + internal delegate bool IsPagerVisible(PagerLocation loc); + + internal interface IPagerData { - public PageChangeAction OnPageChange; + int curPage { get; } + int totalPages { get; } + PageChangeAction OnPageChanged { get; } + } - private readonly Label m_PageText; - private readonly Button m_DownButton; - private readonly Button m_UpButton; - private int m_CurPage; - private int m_TotalPages; + internal class PagerElement : VisualElement + { + IPagerData m_Data; + readonly Label m_PageText; + readonly Button m_DownButton; + readonly Button m_UpButton; - public PagerElement(int pageCount, int startPage = 0) + public PagerElement(IPagerData dataSource) { + m_Data = dataSource; + this.style.flexDirection = FlexDirection.Row; this.style.alignSelf = Align.Center; - m_CurPage = startPage; - m_TotalPages = pageCount; Add(m_DownButton = new Button(OnPageDownClicked) {text = "\u25c5 Newer"}); m_DownButton.AddToClassList("PagerDown"); @@ -39,57 +46,31 @@ public PagerElement(int pageCount, int startPage = 0) UpdateControls(); } - public int PageCount + void OnPageDownClicked() { - get { return m_TotalPages; } - set - { - if (m_TotalPages == value) - return; - m_TotalPages = value; - if (m_CurPage > m_TotalPages) - { - m_CurPage = m_TotalPages; - } - UpdateControls(); - } - } - - private void OnPageDownClicked() - { - if (m_CurPage <= 0) - return; - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "NewerPage"); - - m_CurPage--; - - if (OnPageChange != null) - OnPageChange(m_CurPage); - - UpdateControls(); + m_Data.OnPageChanged(m_Data.curPage - 1); } - private void OnPageUpClicked() + void OnPageUpClicked() { - if (m_CurPage >= m_TotalPages) - return; - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "OlderPage"); + m_Data.OnPageChanged(m_Data.curPage + 1); + } - m_CurPage++; - - if (OnPageChange != null) - OnPageChange(m_CurPage); - + public void Refresh() + { UpdateControls(); } - private void UpdateControls() + void UpdateControls() { - m_PageText.text = (m_CurPage + 1) + " / " + m_TotalPages; - m_DownButton.SetEnabled(m_CurPage > 0); - m_UpButton.SetEnabled(m_CurPage < m_TotalPages - 1); + var curPage = m_Data.curPage; + var totalPages = m_Data.totalPages; + + m_PageText.text = (curPage + 1) + " / " + totalPages; + m_DownButton.SetEnabled(curPage > 0); + m_UpButton.SetEnabled(curPage < totalPages - 1); } } @@ -97,32 +78,18 @@ internal enum PagerLocation { Top, Bottom, - None } - internal class PagedListView : VisualElement + internal class PagedListView : VisualElement, IPagerData { public const int DefaultItemsPerPage = 10; - private readonly VisualElement m_ItemContainer; - private readonly PagerElement m_Pager; - private int m_PageSize = DefaultItemsPerPage; - private IEnumerable m_Items; - private int m_TotalItems; - private PagerLocation m_PagerLoc = PagerLocation.Bottom; - - public PagerLocation PagerLoc - { - get { return m_PagerLoc; } - set - { - if (value == m_PagerLoc) - return; - - m_PagerLoc = value; - UpdatePager(); - } - } + readonly VisualElement m_ItemContainer; + readonly PagerElement m_PagerTop, m_PagerBottom; + int m_PageSize = DefaultItemsPerPage; + IEnumerable m_Items; + int m_TotalItems; + int m_CurPage; public int pageSize { @@ -150,14 +117,11 @@ public int totalItems } } - public PageChangeAction OnPageChange - { - set { m_Pager.OnPageChange = value; } - } + public PageChangeAction OnPageChanged { get; set; } public PagedListView() { - m_Pager = new PagerElement(0); + m_PagerTop = new PagerElement(this); m_ItemContainer = new VisualElement() { @@ -165,29 +129,11 @@ public PagedListView() }; Add(m_ItemContainer); m_Items = new List(); - } - private void UpdatePager() - { - if (m_Pager.parent == this) - { - Remove(m_Pager); - } - - switch (m_PagerLoc) - { - case PagerLocation.Top: - Insert(0, m_Pager); - break; - case PagerLocation.Bottom: - Add(m_Pager); - break; - } - - m_Pager.PageCount = pageCount; + m_PagerBottom = new PagerElement(this); } - private void LayoutItems() + void LayoutItems() { m_ItemContainer.Clear(); foreach (var item in m_Items) @@ -196,6 +142,22 @@ private void LayoutItems() } } + void UpdatePager() + { + if (m_PagerTop.parent != this && totalPages > 1 && curPage > 0) + Insert(0, m_PagerTop); + if (m_PagerTop.parent == this && (totalPages <= 1 || curPage == 0)) + Remove(m_PagerTop); + + if (m_PagerBottom.parent != this && totalPages > 1) + Add(m_PagerBottom); + if (m_PagerBottom.parent == this && totalPages <= 1) + Remove(m_PagerBottom); + + m_PagerTop.Refresh(); + m_PagerBottom.Refresh(); + } + int pageCount { get @@ -207,5 +169,26 @@ int pageCount return pages; } } + + public int curPage + { + get { return m_CurPage; } + set + { + m_CurPage = value; + UpdatePager(); + } + } + + public int totalPages + { + get + { + var extraPage = 0; + if (m_TotalItems % m_PageSize > 0) + extraPage = 1; + return m_TotalItems / m_PageSize + extraPage; + } + } } } diff --git a/Editor/Mono/ConsoleWindow.cs b/Editor/Mono/ConsoleWindow.cs index 14aea73fb0..daafbecdb4 100644 --- a/Editor/Mono/ConsoleWindow.cs +++ b/Editor/Mono/ConsoleWindow.cs @@ -5,8 +5,6 @@ using System; using System.Globalization; using UnityEngine; -using UnityEditor; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -177,20 +175,16 @@ protected override void OnGUIMenu(Rect connectRect, List profile { if (additionalMenuItems == null) { - additionalMenuItems = new List(); - additionalMenuItems.Add("Player Logging"); + additionalMenuItems = new List {"Player Logging"}; if (Unsupported.IsDeveloperMode()) additionalMenuItems.Add("Full Log (Developer Mode Only)"); additionalMenuItems.Add(""); } - var names = additionalMenuItems.Concat(profilers.Select(p => p.Name)); - - var enabled = new List(); + var names = additionalMenuItems.Concat(profilers.Select(p => p.Name)).ToArray(); // "Player Logging" field is always enabled. - enabled.Add(true); - + var enabled = new List {true}; var selected = new List(); var connected = PlayerConnectionLogReceiver.instance.State != PlayerConnectionLogReceiver.ConnectionState.Disconnected; @@ -211,7 +205,7 @@ protected override void OnGUIMenu(Rect connectRect, List profile else { // everything but first menu item is disabled. - enabled.AddRange(new bool[names.Count() - 1]); + enabled.AddRange(new bool[names.Length - 1]); } int index = profilers.FindIndex(p => p.IsSelected()); @@ -220,12 +214,13 @@ protected override void OnGUIMenu(Rect connectRect, List profile var seperators = new bool[enabled.Count]; seperators[additionalMenuItems.Count - 1] = true; - EditorUtility.DisplayCustomMenuWithSeparators(connectRect, names.ToArray(), enabled.ToArray(), seperators, selected.ToArray(), SelectClick, profilers); + EditorUtility.DisplayCustomMenuWithSeparators(connectRect, names, enabled.ToArray(), seperators, selected.ToArray(), SelectClick, profilers); } } ConsoleAttachProfilerUI m_AttachProfilerUI = new ConsoleAttachProfilerUI(); + [Flags] internal enum Mode { Error = 1 << 0, @@ -618,8 +613,6 @@ void OnGUI() GUILayout.EndHorizontal(); - m_ListView.totalRows = LogEntries.StartGettingEntries(); - SplitterGUILayout.BeginVerticalSplit(spl); int rowHeight = RowHeight; EditorGUIUtility.SetIconSize(new Vector2(rowHeight, rowHeight)); @@ -627,24 +620,20 @@ void OnGUI() int id = GUIUtility.GetControlID(0); /////@TODO: Make Frame selected work with ListViewState - try + using (new GettingLogEntriesScope(m_ListView)) { - bool selected = false; + int selectedRow = -1; + bool openSelectedItem = false; bool collapsed = HasFlag(ConsoleFlags.Collapse); foreach (ListViewElement el in ListViewGUI.ListView(m_ListView, Constants.Box)) { if (e.type == EventType.MouseDown && e.button == 0 && el.position.Contains(e.mousePosition)) { + selectedRow = m_ListView.row; if (e.clickCount == 2) - { - LogEntries.RowGotDoubleClicked(m_ListView.row); - } - - selected = true; + openSelectedItem = true; } - - // Paint list view element - if (e.type == EventType.Repaint) + else if (e.type == EventType.Repaint) { int mode = 0; string text = null; @@ -663,7 +652,6 @@ void OnGUI() GUIStyle errorModeStyle = GetStyleForErrorMode(mode, false, Constants.LogStyleLineCount == 1); errorModeStyle.Draw(el.position, tempContent, id, m_ListView.row == el.row); - if (collapsed) { Rect badgeRect = el.position; @@ -677,13 +665,12 @@ void OnGUI() } } - if (selected) + if (selectedRow != -1) { if (m_ListView.scrollPos.y >= m_ListView.rowHeight * m_ListView.totalRows - ms_LVHeight) m_ListView.scrollPos.y = m_ListView.rowHeight * m_ListView.totalRows - ms_LVHeight - 1; } - // Make sure the selected entry is up to date if (m_ListView.totalRows == 0 || m_ListView.row >= m_ListView.totalRows || m_ListView.row < 0) { @@ -707,20 +694,23 @@ void OnGUI() // Open entry using return key if ((GUIUtility.keyboardControl == m_ListView.ID) && (e.type == EventType.KeyDown) && (e.keyCode == KeyCode.Return) && (m_ListView.row != 0)) { - LogEntries.RowGotDoubleClicked(m_ListView.row); - Event.current.Use(); + selectedRow = m_ListView.row; + openSelectedItem = true; } if (e.type != EventType.Layout && ListViewGUI.ilvState.rectHeight != 1) ms_LVHeight = ListViewGUI.ilvState.rectHeight; + + if (openSelectedItem) + { + LogEntries.RowGotDoubleClicked(selectedRow); + Event.current.Use(); + } } - finally - { - LogEntries.EndGettingEntries(); - EditorGUIUtility.SetIconSize(Vector2.zero); - } - // Display active text (We want wordwrapped text with a vertical scrollbar) + EditorGUIUtility.SetIconSize(Vector2.zero); + + // Display active text (We want word wrapped text with a vertical scrollbar) m_TextScroll = GUILayout.BeginScrollView(m_TextScroll, Constants.Box); float height = Constants.MessageStyle.CalcHeight(GUIContent.Temp(m_ActiveText), position.width); EditorGUILayout.SelectableLabel(m_ActiveText, Constants.MessageStyle, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true), GUILayout.MinHeight(height)); @@ -837,4 +827,28 @@ private static void SendEntryDoubleClicked(LogEntry entry) ConsoleWindow.entryWithManagedCallbackDoubleClicked(entry); } } + + internal class GettingLogEntriesScope : IDisposable + { + private bool m_Disposed; + + public GettingLogEntriesScope(ListViewState listView) + { + listView.totalRows = LogEntries.StartGettingEntries(); + } + + public void Dispose() + { + if (m_Disposed) + return; + LogEntries.EndGettingEntries(); + m_Disposed = true; + } + + ~GettingLogEntriesScope() + { + if (!m_Disposed) + Debug.LogError("Scope was not disposed! You should use the 'using' keyword or manually call Dispose."); + } + } } diff --git a/Editor/Mono/EditorWindow.cs b/Editor/Mono/EditorWindow.cs index 3868593e45..552b677ef0 100644 --- a/Editor/Mono/EditorWindow.cs +++ b/Editor/Mono/EditorWindow.cs @@ -474,6 +474,8 @@ internal void ShowWithMode(ShowMode mode) cw.rootView = host; MakeParentsSettingsMatchMe(); cw.Show(mode, true, false); + // set min/max size now that native window is not null so that it will e.g., use proper styleMask on macOS + cw.SetMinMaxSizes(minSize, maxSize); oldState.ApplyAndForget(); } diff --git a/Editor/Mono/GUI/ColorPicker.cs b/Editor/Mono/GUI/ColorPicker.cs index cde28eefae..2d04d0c030 100644 --- a/Editor/Mono/GUI/ColorPicker.cs +++ b/Editor/Mono/GUI/ColorPicker.cs @@ -1207,8 +1207,8 @@ public void OnDestroy() if (m_ColorLibraryEditor != null) m_ColorLibraryEditor.UnloadUsedLibraries(); - GUIUtility.keyboardControl = originalKeyboardControl; + originalKeyboardControl = 0; } } diff --git a/Editor/Mono/GUI/QuadTree.cs b/Editor/Mono/GUI/QuadTree.cs index e7b3450f31..de305472df 100644 --- a/Editor/Mono/GUI/QuadTree.cs +++ b/Editor/Mono/GUI/QuadTree.cs @@ -453,8 +453,13 @@ public void Remove(T item) public List GetItemsAtPosition(Vector2 pos) { - Rect r = new Rect(pos, Vector2.one); - return IntersectsWith(r); + if (m_Root.BoundingRect.Contains(pos)) + { + Rect r = new Rect(pos, Vector2.one); + return IntersectsWith(r); + } + + return new List(); } public List IntersectsWith(Rect area) diff --git a/Editor/Mono/GradientPreviewCache.bindings.cs b/Editor/Mono/GradientPreviewCache.bindings.cs index 1ef08b2117..2e5bc26057 100644 --- a/Editor/Mono/GradientPreviewCache.bindings.cs +++ b/Editor/Mono/GradientPreviewCache.bindings.cs @@ -10,6 +10,7 @@ namespace UnityEditorInternal { [NativeHeader("Editor/Src/GradientPreviewCache.h")] [NativeHeader("Runtime/Graphics/Texture2D.h")] + [NativeHeader("Runtime/Math/Gradient.h")] internal partial class GradientPreviewCache { public static extern Texture2D GenerateGradientPreview(Gradient gradient, Texture2D existingTexture); diff --git a/Editor/Mono/ImportSettings/ModelImporterRigEditor.cs b/Editor/Mono/ImportSettings/ModelImporterRigEditor.cs index bd6aa93dc2..292180ea3c 100644 --- a/Editor/Mono/ImportSettings/ModelImporterRigEditor.cs +++ b/Editor/Mono/ImportSettings/ModelImporterRigEditor.cs @@ -726,7 +726,7 @@ internal override void PostApply() { ModelImporter importer = targets[i] as ModelImporter; // Special case if the model didn't have animation before... - if (oldModelSettings[i].hasNoAnimation && assetTarget != null) + if (oldModelSettings[i].hasNoAnimation && assetTargets[i] != null) { // We have to do an extra import first, before the automapping works. // Because the model doesn't have any skinned meshes when it was last imported with @@ -739,7 +739,7 @@ internal override void PostApply() // Perform auto-setup on this model. SerializedObject so = new SerializedObject(targets[i]); - GameObject go = assetTarget as GameObject; + GameObject go = assetTargets[i] as GameObject; // The character could be optimized right now // 'm_OptimizeGameObjects' can't be used to tell if it is optimized, because the user can change this value from UI, // and the change hasn't been applied yet. diff --git a/Editor/Mono/Inspector/BillboardAssetInspector.cs b/Editor/Mono/Inspector/BillboardAssetInspector.cs index 0bae306e62..e23a5ccba4 100644 --- a/Editor/Mono/Inspector/BillboardAssetInspector.cs +++ b/Editor/Mono/Inspector/BillboardAssetInspector.cs @@ -90,7 +90,7 @@ private void InitPreview() m_GeometryMesh.hideFlags = HideFlags.HideAndDontSave; m_GeometryMesh.MarkDynamic(); m_ShadedMaterialProperties = new MaterialPropertyBlock(); - m_GeometryMaterial = EditorGUIUtility.GetBuiltinExtraResource(typeof(Material), "Default-Material.mat") as Material; + m_GeometryMaterial = Material.GetDefaultMaterial(); m_WireframeMaterial = ModelInspector.CreateWireframeMaterial(); EditorUtility.SetCameraAnimateMaterials(m_PreviewUtility.camera, true); } diff --git a/Editor/Mono/Inspector/ModelInspector.cs b/Editor/Mono/Inspector/ModelInspector.cs index 200f09196c..7ab7c105c1 100644 --- a/Editor/Mono/Inspector/ModelInspector.cs +++ b/Editor/Mono/Inspector/ModelInspector.cs @@ -41,7 +41,7 @@ void Init() { m_PreviewUtility = new PreviewRenderUtility(); m_PreviewUtility.camera.fieldOfView = 30.0f; - m_Material = EditorGUIUtility.GetBuiltinExtraResource(typeof(Material), "Default-Material.mat") as Material; + m_Material = Material.GetDefaultMaterial(); m_WireMaterial = CreateWireframeMaterial(); } } diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index eca8aecd0e..6b1e458adc 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -2124,7 +2124,7 @@ private ApiCompatibilityLevel[] GetAvailableApiCompatibilityLevels(BuildTargetGr if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) return only_4_x_profiles; - if (activeBuildTargetGroup == BuildTargetGroup.WSA || activeBuildTargetGroup == BuildTargetGroup.XboxOne) + if (activeBuildTargetGroup == BuildTargetGroup.WSA) return wsa_profiles; return only_2_0_profiles; diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ShapeModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ShapeModuleUI.cs index 89b3ff2bed..8e81c8618f 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ShapeModuleUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ShapeModuleUI.cs @@ -272,7 +272,7 @@ protected override void Init() m_Rotation = GetProperty("m_Rotation"); if (!s_Material) - s_Material = EditorGUIUtility.GetBuiltinExtraResource(typeof(Material), "Default-Material.mat") as Material; + s_Material = Material.GetDefaultMaterial(); if (!s_TextureMaterial) s_TextureMaterial = new Material((Shader)EditorGUIUtility.Load("SceneView/ParticleShapeGizmo.shader")); if (!s_SphereTextureMaterial) diff --git a/Editor/Mono/PerformanceTools/FrameDebugger.cs b/Editor/Mono/PerformanceTools/FrameDebugger.cs index 51c5df2f83..55d8a3c391 100644 --- a/Editor/Mono/PerformanceTools/FrameDebugger.cs +++ b/Editor/Mono/PerformanceTools/FrameDebugger.cs @@ -677,7 +677,7 @@ private void DrawMeshPreview(Rect previewRect, Rect meshInfoRect, Mesh mesh, int m_PreviewUtility.camera.fieldOfView = 30.0f; } if (m_Material == null) - m_Material = EditorGUIUtility.GetBuiltinExtraResource(typeof(Material), "Default-Material.mat") as Material; + m_Material = Material.GetDefaultMaterial(); if (m_WireMaterial == null) { m_WireMaterial = ModelInspector.CreateWireframeMaterial(); diff --git a/Editor/Mono/PreferencesWindow/PreferencesWindow.cs b/Editor/Mono/PreferencesWindow/PreferencesWindow.cs index 5ecdf4c901..01901c281b 100644 --- a/Editor/Mono/PreferencesWindow/PreferencesWindow.cs +++ b/Editor/Mono/PreferencesWindow/PreferencesWindow.cs @@ -64,7 +64,7 @@ internal class Styles public static readonly GUIContent autoRefreshHelpBox = EditorGUIUtility.TrTextContent("Auto Refresh must be set when using Collaboration feature.", EditorGUIUtility.GetHelpIcon(MessageType.Warning)); public static readonly GUIContent loadPreviousProjectOnStartup = EditorGUIUtility.TrTextContent("Load Previous Project on Startup"); public static readonly GUIContent compressAssetsOnImport = EditorGUIUtility.TrTextContent("Compress Assets on Import"); - public static readonly GUIContent osxColorPicker = EditorGUIUtility.TrTextContent("OS X Color Picker"); + public static readonly GUIContent osxColorPicker = EditorGUIUtility.TrTextContent("macOS Color Picker"); public static readonly GUIContent disableEditorAnalytics = EditorGUIUtility.TrTextContent("Disable Editor Analytics (Pro Only)"); public static readonly GUIContent showAssetStoreSearchHits = EditorGUIUtility.TrTextContent("Show Asset Store search hits"); public static readonly GUIContent verifySavingAssets = EditorGUIUtility.TrTextContent("Verify Saving Assets"); diff --git a/Editor/Mono/SceneModeWindows/LightingWindow.cs b/Editor/Mono/SceneModeWindows/LightingWindow.cs index b76d2bde64..250a7bf1d9 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindow.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindow.cs @@ -51,8 +51,6 @@ enum BakeMode public LightingWindowLightingTab m_LightingTab; LightingWindowLightmapPreviewTab m_LightmapPreviewTab; - Scene m_LastActiveScene; - SerializedObject m_LightmapSettings; SerializedProperty m_WorkflowMode; SerializedProperty m_EnabledBakedGI; @@ -172,20 +170,8 @@ void OnGUI() void InitLightmapSettings() { - //None of the events from EditorSceneManager worked here. - //The problems is that EditorSceneManager.NewScene will trigger a repaint of all windows, and this happens before the EditorSceneManager events gets called. - //So this window never gets a chance to rebuild its m_LightmapSettings. - //For now the workaround is to poll for active scene change during OnGUI. - var currentScene = EditorSceneManager.GetActiveScene(); - if (m_LastActiveScene != currentScene) + if (m_LightmapSettings == null || m_LightmapSettings.targetObject != LightmapEditorSettings.GetLightmapSettings()) { - if (m_LightmapSettings != null) - { - m_LightmapSettings.Dispose(); - m_EnabledBakedGI.Dispose(); - m_WorkflowMode.Dispose(); - } - m_LastActiveScene = currentScene; m_LightmapSettings = new SerializedObject(LightmapEditorSettings.GetLightmapSettings()); m_EnabledBakedGI = m_LightmapSettings.FindProperty("m_GISettings.m_EnableBakedLightmaps"); m_WorkflowMode = m_LightmapSettings.FindProperty("m_GIWorkflowMode"); diff --git a/Editor/Mono/SceneModeWindows/SceneModeUtility.cs b/Editor/Mono/SceneModeWindows/SceneModeUtility.cs index d5de470d72..8c99951717 100644 --- a/Editor/Mono/SceneModeWindows/SceneModeUtility.cs +++ b/Editor/Mono/SceneModeWindows/SceneModeUtility.cs @@ -147,9 +147,24 @@ public static bool StaticFlagField(string label, SerializedProperty property, in public static bool SetStaticFlags(Object[] targetObjects, int changedFlags, bool flagValue) { bool allFlagsAreChanged = (changedFlags == ~0); + var msgChangedFlags = changedFlags; + if (msgChangedFlags < 0 && !allFlagsAreChanged) + { + //In order to have a list of human readable list of changed flags, + //we need to filter out bits that does not correspont to any option. + int allPossibleValues = 0; + var values = Enum.GetValues(typeof(StaticEditorFlags)); + foreach (var value in values) + { + allPossibleValues |= (int)value; + } + + msgChangedFlags = msgChangedFlags & allPossibleValues; + } StaticEditorFlags flag = allFlagsAreChanged ? (StaticEditorFlags)0 : - (StaticEditorFlags)Enum.Parse(typeof(StaticEditorFlags), changedFlags.ToString()); + (StaticEditorFlags)Enum.Parse(typeof(StaticEditorFlags), msgChangedFlags.ToString()); + // Should we include child objects? GameObjectUtility.ShouldIncludeChildren includeChildren = GameObjectUtility.DisplayUpdateChildrenDialogIfNeeded(targetObjects.OfType(), "Change Static Flags", diff --git a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs index 3eaf64db76..1ab28462c1 100644 --- a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs @@ -435,5 +435,15 @@ internal struct CompilerMessage /// The normalized status. Each class deriving from ScriptCompilerBase must map errors / warning # /// if it can be mapped to a NormalizedCompilerStatusCode. public NormalizedCompilerStatus normalizedStatus; + + public CompilerMessage(CompilerMessage cm) + { + message = cm.message; + file = cm.file; + line = cm.line; + column = cm.column; + type = cm.type; + normalizedStatus = cm.normalizedStatus; + } } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index aa9e6df773..3b2417ca9e 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -613,7 +613,7 @@ public CustomScriptAssembly FindCustomScriptAssemblyFromAssemblyName(string asse if (packageCustomScriptAssemblies != null) allCustomScriptAssemblies.AddRange(packageCustomScriptAssemblies); - var customScriptAssembly = allCustomScriptAssemblies.Single(a => a.Name == AssetPath.GetAssemblyNameWithoutExtension(assemblyName)); + var customScriptAssembly = allCustomScriptAssemblies.Single(a => AssemblyNameWithSuffix(a.Name) == AssetPath.GetAssemblyNameWithoutExtension(assemblyName)); return customScriptAssembly; } @@ -748,13 +748,7 @@ internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, ScriptA if (messages.Any(m => m.type == CompilerMessageType.Error)) { - var errorMessages = messages.Where(m => m.type == CompilerMessageType.Error); - - // error CS0227: Unsafe code requires the `unsafe' command line option to be specified - if (errorMessages.Any(em => em.message.Contains("CS0227"))) - { - messages.Add(new CompilerMessage { message = "You can allow 'unsafe' code for Assembly Definition Files in the inspector and for predefined assemblies in player settings.", type = CompilerMessageType.Warning, file = assembly.FullPath, line = -1, column = -1 }); - } + AddUnitySpecificErrorMessages(assembly, messages); InvokeAssemblyCompilationFinished(assemblyOutputPath, messages); return; @@ -788,6 +782,46 @@ internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, ScriptA return true; } + void AddUnitySpecificErrorMessages(ScriptAssembly assembly, List messages) + { + // error CS0227: Unsafe code requires the `unsafe' command line option to be specified + if (!messages.Any(m => m.type == CompilerMessageType.Error && m.message.Contains("CS0227"))) + return; + + var assemblyName = AssetPath.GetAssemblyNameWithoutExtension(assembly.Filename); + + string unityUnsafeMessage; + + try + { + var customScriptAssembly = FindCustomScriptAssemblyFromAssemblyName(assemblyName); + unityUnsafeMessage = string.Format("Enable \"Allow 'unsafe' code\" in the inspector for '{0}' to fix this error.", customScriptAssembly.FilePath); + } + catch + { + unityUnsafeMessage = "Enable \"Allow 'unsafe' code\" in Player Settings to fix this error."; + } + + List newMessages = new List(); + + foreach (var message in messages) + { + if (message.type == CompilerMessageType.Error && message.message.Contains("CS0227")) + { + var newMessage = new CompilerMessage(message); + newMessage.message += ". " + unityUnsafeMessage; + newMessages.Add(newMessage); + } + else + { + newMessages.Add(message); + } + } + + messages.Clear(); + messages.AddRange(newMessages); + } + public void InvokeAssemblyCompilationStarted(string assemblyOutputPath) { if (assemblyCompilationStarted != null) @@ -991,6 +1025,17 @@ string AssemblyFilenameWithSuffix(string assemblyFilename) return assemblyFilename; } + string AssemblyNameWithSuffix(string assemblyName) + { + if (!string.IsNullOrEmpty(assemblySuffix)) + { + var basename = AssetPath.GetAssemblyNameWithoutExtension(assemblyName); + return string.Concat(basename, assemblySuffix); + } + + return assemblyName; + } + public TargetAssemblyInfo[] GetTargetAssemblies() { EditorBuildRules.TargetAssembly[] predefindTargetAssemblies = EditorBuildRules.GetPredefinedTargetAssemblies(); diff --git a/Modules/AI/NavMeshExperimental.bindings.cs b/Modules/AI/NavMeshExperimental.bindings.cs index b5fc25f0f4..f1cb82f07a 100644 --- a/Modules/AI/NavMeshExperimental.bindings.cs +++ b/Modules/AI/NavMeshExperimental.bindings.cs @@ -10,33 +10,36 @@ using Unity.Jobs; using UnityEngine.Bindings; using UnityEngine.AI; +using UnityEngine.Scripting; namespace UnityEngine.Experimental.AI { - public struct PolygonID + public struct PolygonId : IEquatable { internal ulong polyRef; public bool IsNull() { return polyRef == 0; } - public static bool operator==(PolygonID x, PolygonID y) { return x.polyRef == y.polyRef; } - public static bool operator!=(PolygonID x, PolygonID y) { return x.polyRef != y.polyRef; } + public static bool operator==(PolygonId x, PolygonId y) { return x.polyRef == y.polyRef; } + public static bool operator!=(PolygonId x, PolygonId y) { return x.polyRef != y.polyRef; } public override int GetHashCode() { return polyRef.GetHashCode(); } + public bool Equals(PolygonId rhs) { return rhs == this; } + public override bool Equals(object obj) { - if (obj == null || !(obj is PolygonID)) + if (obj == null || !(obj is PolygonId)) return false; - var rhs = (PolygonID)obj; + var rhs = (PolygonId)obj; return rhs == this; } } public struct NavMeshLocation { - public PolygonID polygon { get; } + public PolygonId polygon { get; } public Vector3 position { get; } - internal NavMeshLocation(Vector3 position, PolygonID polygon) + internal NavMeshLocation(Vector3 position, PolygonId polygon) { this.position = position; this.polygon = polygon; @@ -125,7 +128,8 @@ public struct NavMeshQuery : IDisposable [NativeDisableUnsafePtrRestriction] internal IntPtr m_NavMeshQuery; Allocator m_Allocator; - + const string k_NoBufferAllocatedErrorMessage = "This query has no buffer allocated for pathfinding operations. " + + "Create a different NavMeshQuery with an explicit node pool size."; public NavMeshQuery(NavMeshWorld world, Allocator allocator, int pathNodePoolSize = 0) { @@ -163,7 +167,7 @@ public PathQueryStatus EndFindPath(out int pathSize) return EndFindPath(m_NavMeshQuery, out pathSize); } - public unsafe int GetPathResult(NativeSlice path) + public unsafe int GetPathResult(NativeSlice path) { return GetPathResult(m_NavMeshQuery, path.GetUnsafePtr(), path.Length); } @@ -181,15 +185,15 @@ public unsafe int GetPathResult(NativeSlice path) unsafe static extern int GetPathResult(IntPtr navMeshQuery, void* path, int maxPath); // If BeginFindPath/UpdateFindPath/EndFindPath existing NativeArray become invalid... -// extern NavMeshPathStatus GetPath(out NativeArray outputPath); +// extern NavMeshPathStatus GetPath(out NativeArray outputPath); //void DidScheduleJob(JobHandle handle); [ThreadSafe] - static extern bool IsValidPolygon(IntPtr navMeshQuery, PolygonID polygon); + static extern bool IsValidPolygon(IntPtr navMeshQuery, PolygonId polygon); - public bool IsValid(PolygonID polygon) + public bool IsValid(PolygonId polygon) { return polygon.polyRef != 0 && IsValidPolygon(m_NavMeshQuery, polygon); } @@ -200,16 +204,16 @@ public bool IsValid(NavMeshLocation location) } [ThreadSafe] - static extern int GetAgentTypeIdForPolygon(IntPtr navMeshQuery, PolygonID polygon); - public int GetAgentTypeIdForPolygon(PolygonID polygon) + static extern int GetAgentTypeIdForPolygon(IntPtr navMeshQuery, PolygonId polygon); + public int GetAgentTypeIdForPolygon(PolygonId polygon) { return GetAgentTypeIdForPolygon(m_NavMeshQuery, polygon); } [ThreadSafe] - static extern bool IsPositionInPolygon(IntPtr navMeshQuery, Vector3 position, PolygonID polygon); + static extern bool IsPositionInPolygon(IntPtr navMeshQuery, Vector3 position, PolygonId polygon); - public NavMeshLocation CreateLocation(Vector3 position, PolygonID polygon) + public NavMeshLocation CreateLocation(Vector3 position, PolygonId polygon) { return new NavMeshLocation(position, polygon); } @@ -243,42 +247,42 @@ public NavMeshLocation MoveLocation(NavMeshLocation location, Vector3 target, in } [ThreadSafe] - static extern bool GetPortalPoints(IntPtr navMeshQuery, PolygonID polygon, PolygonID neighbourPolygon, out Vector3 left, out Vector3 right); - public bool GetPortalPoints(PolygonID polygon, PolygonID neighbourPolygon, out Vector3 left, out Vector3 right) + static extern bool GetPortalPoints(IntPtr navMeshQuery, PolygonId polygon, PolygonId neighbourPolygon, out Vector3 left, out Vector3 right); + public bool GetPortalPoints(PolygonId polygon, PolygonId neighbourPolygon, out Vector3 left, out Vector3 right) { return GetPortalPoints(m_NavMeshQuery, polygon, neighbourPolygon, out left, out right); } [ThreadSafe] - static extern Matrix4x4 PolygonLocalToWorldMatrix(IntPtr navMeshQuery, PolygonID polygon); - public Matrix4x4 PolygonLocalToWorldMatrix(PolygonID polygon) + static extern Matrix4x4 PolygonLocalToWorldMatrix(IntPtr navMeshQuery, PolygonId polygon); + public Matrix4x4 PolygonLocalToWorldMatrix(PolygonId polygon) { return PolygonLocalToWorldMatrix(m_NavMeshQuery, polygon); } [ThreadSafe] - static extern Matrix4x4 PolygonWorldToLocalMatrix(IntPtr navMeshQuery, PolygonID polygon); - public Matrix4x4 PolygonWorldToLocalMatrix(PolygonID polygon) + static extern Matrix4x4 PolygonWorldToLocalMatrix(IntPtr navMeshQuery, PolygonId polygon); + public Matrix4x4 PolygonWorldToLocalMatrix(PolygonId polygon) { return PolygonWorldToLocalMatrix(m_NavMeshQuery, polygon); } [ThreadSafe] - static extern NavMeshPolyTypes GetPolygonType(IntPtr navMeshQuery, PolygonID polygon); - public NavMeshPolyTypes GetPolygonType(PolygonID polygon) + static extern NavMeshPolyTypes GetPolygonType(IntPtr navMeshQuery, PolygonId polygon); + public NavMeshPolyTypes GetPolygonType(PolygonId polygon) { return GetPolygonType(m_NavMeshQuery, polygon); } //NavMeshStatus MoveAlongSurface(NavMeshLocation location, Vector3 targetPosition, int agentTypeID, int areaMask, - // out NavMeshLocation outputLocation, NativeArray visitedBuffer, out int actualVisited); + // out NavMeshLocation outputLocation, NativeArray visitedBuffer, out int actualVisited); //// Trace a ray between two points on the NavMesh. //extern bool Raycast(NavMeshLocation location, Vector3 targetPosition, out NavMeshHit hit, int agentTypeID, int areaMask, NativeArray costs); //// Polygon Queries - //public NavMeshPolyData GetPolygon(PolygonID poly); - //public void GetPolygon(NativeArray polygonIDs, NativeArray polygons); + //public NavMeshPolyData GetPolygon(PolygonId poly); + //public void GetPolygon(NativeArray polygonIDs, NativeArray polygons); //public void GetPolygons(MappedPosition position, float distance, NativeList polygons); //public static void LocalizePolygonIndices(NativeArray polygons); diff --git a/Modules/BuildPipeline/Editor/Managed/PlayerBuildInterface.bindings.cs b/Modules/BuildPipeline/Editor/Managed/PlayerBuildInterface.bindings.cs index 8105eddaee..31b1e25adc 100644 --- a/Modules/BuildPipeline/Editor/Managed/PlayerBuildInterface.bindings.cs +++ b/Modules/BuildPipeline/Editor/Managed/PlayerBuildInterface.bindings.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using UnityEngine.Bindings; using UnityEngine.Scripting; +using System.Collections.Generic; namespace UnityEditor.Experimental.Build.Player { @@ -67,6 +68,8 @@ public struct ScriptCompilationResult [NativeHeader("Modules/BuildPipeline/Editor/Public/PlayerBuildInterface.h")] public class PlayerBuildInterface { + public static Func> ExtraTypesProvider; + [FreeFunction(Name = "BuildPipeline::CompilePlayerScripts")] extern private static ScriptCompilationResult CompilePlayerScriptsNative(ScriptCompilationSettings input, string outputFolder, bool editorScripts); diff --git a/Modules/IMGUI/GUILayoutUtility.cs b/Modules/IMGUI/GUILayoutUtility.cs index eec8f5e5d7..42f347e0f0 100644 --- a/Modules/IMGUI/GUILayoutUtility.cs +++ b/Modules/IMGUI/GUILayoutUtility.cs @@ -19,15 +19,12 @@ public partial class GUILayoutUtility [VisibleToOtherModules("UnityEngine.UIElementsModule")] internal sealed class LayoutCache { - //*undocumented* [VisibleToOtherModules("UnityEngine.UIElementsModule")] internal GUILayoutGroup topLevel = new GUILayoutGroup(); - //*undocumented* + internal GenericStack layoutGroups = new GenericStack(); - //*undocumented* internal GUILayoutGroup windows = new GUILayoutGroup(); - //*undocumented* [VisibleToOtherModules("UnityEngine.UIElementsModule")] internal LayoutCache() { @@ -43,14 +40,14 @@ internal LayoutCache(LayoutCache other) } // TODO: Clean these up after a while - static Dictionary s_StoredLayouts = new Dictionary(); - static Dictionary s_StoredWindows = new Dictionary(); + static readonly Dictionary s_StoredLayouts = new Dictionary(); + static readonly Dictionary s_StoredWindows = new Dictionary(); internal static LayoutCache current = new LayoutCache(); internal static readonly Rect kDummyRect = new Rect(0, 0, 1, 1); - static internal void CleanupRoots() + internal static void CleanupRoots() { // See GUI.CleanupRoots s_SpaceStyle = null; @@ -60,7 +57,7 @@ static internal void CleanupRoots() } [VisibleToOtherModules("UnityEngine.UIElementsModule")] - static internal LayoutCache SelectIDList(int instanceID, bool isWindow) + internal static LayoutCache SelectIDList(int instanceID, bool isWindow) { Dictionary store = isWindow ? s_StoredWindows : s_StoredLayouts; LayoutCache cache; @@ -82,7 +79,7 @@ static internal LayoutCache SelectIDList(int instanceID, bool isWindow) // Set up the internal GUILayouting // Called by the main GUI class automatically (from GUI.Begin) - static internal void Begin(int instanceID) + internal static void Begin(int instanceID) { LayoutCache cache = SelectIDList(instanceID, false); // Make a vertical group to encompass the whole thing @@ -102,7 +99,7 @@ static internal void Begin(int instanceID) } [VisibleToOtherModules("UnityEngine.UIElementsModule")] - static internal void BeginContainer(LayoutCache cache) + internal static void BeginContainer(LayoutCache cache) { // Make a vertical group to encompass the whole thing if (Event.current.type == EventType.Layout) @@ -120,7 +117,7 @@ static internal void BeginContainer(LayoutCache cache) } } - static internal void BeginWindow(int windowID, GUIStyle style, GUILayoutOption[] options) + internal static void BeginWindow(int windowID, GUIStyle style, GUILayoutOption[] options) { LayoutCache cache = SelectIDList(windowID, true); // Make a vertical group to encompass the whole thing @@ -144,15 +141,13 @@ static internal void BeginWindow(int windowID, GUIStyle style, GUILayoutOption[] } // TODO: actually make these check... - // *undocumented* [Obsolete("BeginGroup has no effect and will be removed", false)] - static public void BeginGroup(string GroupName) {} - // *undocumented* - [Obsolete("EndGroup has no effect and will be removed", false)] - static public void EndGroup(string groupName) {} + public static void BeginGroup(string GroupName) {} + [Obsolete("EndGroup has no effect and will be removed", false)] + public static void EndGroup(string groupName) {} - static internal void Layout() + internal static void Layout() { if (current.topLevel.windowID == -1) { @@ -172,9 +167,8 @@ static internal void Layout() } } - // Global fayout function. Called from EditorWindows (differs from game view in that they use the full window size and try to stretch GUI - // *undocumented* - static internal void LayoutFromEditorWindow() + // Global layout function. Called from EditorWindows (differs from game view in that they use the full window size and try to stretch GUI + internal static void LayoutFromEditorWindow() { if (current.topLevel != null) { @@ -195,7 +189,7 @@ static internal void LayoutFromEditorWindow() } [VisibleToOtherModules("UnityEngine.UIElementsModule")] - static internal void LayoutFromContainer(float w, float h) + internal static void LayoutFromContainer(float w, float h) { if (current.topLevel != null) { @@ -219,8 +213,7 @@ static internal void LayoutFromContainer(float w, float h) // After this call everything has a properly calculated size // Called by Unity automatically. // Is public so we can access it from editor inspectors, but not supported by public stuff - // *undocumented* - static internal float LayoutFromInspector(float width) + internal static float LayoutFromInspector(float width) { if (current.topLevel != null && current.topLevel.windowID == -1) { @@ -237,15 +230,12 @@ static internal float LayoutFromInspector(float width) LayoutFreeGroup(current.windows); return height; } - else - { - if (current.topLevel != null) - LayoutSingleGroup(current.topLevel); - return 0; - } + if (current.topLevel != null) + LayoutSingleGroup(current.topLevel); + return 0; } - static internal void LayoutFreeGroup(GUILayoutGroup toplevel) + internal static void LayoutFreeGroup(GUILayoutGroup toplevel) { foreach (GUILayoutGroup i in toplevel.entries) { @@ -346,18 +336,15 @@ internal static void EndLayoutGroup() } if (Event.current.type != EventType.Layout && Event.current.type != EventType.Used) GUIDebugger.LogLayoutEndGroup(); - switch (Event.current.type) - { - default: - current.layoutGroups.Pop(); - current.topLevel = (0 < current.layoutGroups.Count) ? - (GUILayoutGroup)current.layoutGroups.Peek() : - null; - return; - } + + current.layoutGroups.Pop(); + if (0 < current.layoutGroups.Count) + current.topLevel = (GUILayoutGroup)current.layoutGroups.Peek(); + else + current.topLevel = new GUILayoutGroup(); } - // Generic helper - use this when creating a layoutgroup. It will make sure everything is wired up correctly. + // Generic helper - use this when creating a layout group. It will make sure everything is wired up correctly. internal static GUILayoutGroup BeginLayoutArea(GUIStyle style, Type layoutType) { GUILayoutGroup g; @@ -383,18 +370,13 @@ internal static GUILayoutGroup BeginLayoutArea(GUIStyle style, Type layoutType) } // Trampoline for Editor stuff - //*undocumented* internal static GUILayoutGroup DoBeginLayoutArea(GUIStyle style, Type layoutType) { return BeginLayoutArea(style, layoutType); } - internal static GUILayoutGroup topLevel - { - get { return current.topLevel; } - } + internal static GUILayoutGroup topLevel => current.topLevel; - /// *listonly* public static Rect GetRect(GUIContent content, GUIStyle style) { return DoGetRect(content, style, null); } // Reserve layout space for a rectangle for displaying some contents with a specific style. public static Rect GetRect(GUIContent content, GUIStyle style, params GUILayoutOption[] options) { return DoGetRect(content, style, options); } @@ -443,24 +425,19 @@ static Rect DoGetRect(GUIContent content, GUIStyle style, GUILayoutOption[] opti } } - /// *listonly* public static Rect GetRect(float width, float height) { return DoGetRect(width, width, height, height, GUIStyle.none, null); } - /// *listonly* public static Rect GetRect(float width, float height, GUIStyle style) {return DoGetRect(width, width, height, height, style, null); } - /// *listonly* public static Rect GetRect(float width, float height, params GUILayoutOption[] options) {return DoGetRect(width, width, height, height, GUIStyle.none, options); } // Reserve layout space for a rectangle with a fixed content area. public static Rect GetRect(float width, float height, GUIStyle style, params GUILayoutOption[] options) {return DoGetRect(width, width, height, height, style, options); } - - /// *listonly* public static Rect GetRect(float minWidth, float maxWidth, float minHeight, float maxHeight) { return DoGetRect(minWidth, maxWidth, minHeight, maxHeight, GUIStyle.none, null); } - /// *listonly* + public static Rect GetRect(float minWidth, float maxWidth, float minHeight, float maxHeight, GUIStyle style) { return DoGetRect(minWidth, maxWidth, minHeight, maxHeight, style, null); } - /// *listonly* + public static Rect GetRect(float minWidth, float maxWidth, float minHeight, float maxHeight, params GUILayoutOption[] options) { return DoGetRect(minWidth, maxWidth, minHeight, maxHeight, GUIStyle.none, options); } // Reserve layout space for a flexible rect. @@ -493,15 +470,12 @@ public static Rect GetLastRect() } } - /// *listonly* - public static Rect GetAspectRect(float aspect) { return DoGetAspectRect(aspect, GUIStyle.none, null); } - /// *listonly* - public static Rect GetAspectRect(float aspect, GUIStyle style) { return DoGetAspectRect(aspect, style, null); } - /// *listonly* - public static Rect GetAspectRect(float aspect, params GUILayoutOption[] options) { return DoGetAspectRect(aspect, GUIStyle.none, options); } + public static Rect GetAspectRect(float aspect) { return DoGetAspectRect(aspect, null); } + public static Rect GetAspectRect(float aspect, GUIStyle style) { return DoGetAspectRect(aspect, null); } + public static Rect GetAspectRect(float aspect, params GUILayoutOption[] options) { return DoGetAspectRect(aspect, options); } // Reserve layout space for a rectangle with a specific aspect ratio. - public static Rect GetAspectRect(float aspect, GUIStyle style, params GUILayoutOption[] options) { return DoGetAspectRect(aspect, GUIStyle.none, options); } - static Rect DoGetAspectRect(float aspect, GUIStyle style, GUILayoutOption[] options) + public static Rect GetAspectRect(float aspect, GUIStyle style, params GUILayoutOption[] options) { return DoGetAspectRect(aspect, options); } + private static Rect DoGetAspectRect(float aspect, GUILayoutOption[] options) { switch (Event.current.type) { diff --git a/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs b/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs index 9ed1c2632f..b2dc3274a0 100644 --- a/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs +++ b/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs @@ -1894,16 +1894,27 @@ public bool IsFilteringNormalAngle(float angle) return result; } + [NativeName("m_UseTriggers")] public bool useTriggers; + [NativeName("m_UseLayerMask")] public bool useLayerMask; + [NativeName("m_UseDepth")] public bool useDepth; + [NativeName("m_UseOutsideDepth")] public bool useOutsideDepth; + [NativeName("m_UseNormalAngle")] public bool useNormalAngle; + [NativeName("m_UseOutsideNormalAngle")] public bool useOutsideNormalAngle; + [NativeName("m_LayerMask")] public LayerMask layerMask; + [NativeName("m_MinDepth")] public float minDepth; + [NativeName("m_MaxDepth")] public float maxDepth; + [NativeName("m_MinNormalAngle")] public float minNormalAngle; + [NativeName("m_MaxNormalAngle")] public float maxNormalAngle; public const float NormalAngleUpperLimit = 359.9999f; diff --git a/Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedView.cs b/Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedView.cs index c7d4ec3048..4dee1f9a99 100644 --- a/Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedView.cs +++ b/Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedView.cs @@ -18,9 +18,9 @@ protected static class Styles public static GUIContent emptyText = new GUIContent(""); public static GUIContent selectLineText = EditorGUIUtility.TrTextContent("Select Line for the detailed information"); - public static readonly GUIStyle expandedArea = GUIStyle.none; - public static readonly GUIStyle callstackScroll = GUIStyle.none; - public static readonly GUIStyle callstackTextArea = EditorStyles.textArea; + public static readonly GUIStyle expandedArea = new GUIStyle(); + public static readonly GUIStyle callstackScroll = new GUIStyle(); + public static readonly GUIStyle callstackTextArea = new GUIStyle(EditorStyles.textArea); static Styles() { diff --git a/Modules/SharedInternals/BindingsAttributes.cs b/Modules/SharedInternals/BindingsAttributes.cs index 26187af894..d7cdc7e5a0 100644 --- a/Modules/SharedInternals/BindingsAttributes.cs +++ b/Modules/SharedInternals/BindingsAttributes.cs @@ -70,6 +70,7 @@ interface IBindingsWritableSelfProviderAttribute : IBindingsAttribute class NativeConditionalAttribute : Attribute, IBindingsAttribute { public string Condition { get; set; } + public string StubReturnStatement { get; set; } public bool Enabled { get; set; } public NativeConditionalAttribute() @@ -91,6 +92,16 @@ public NativeConditionalAttribute(string condition, bool enabled) : this(conditi { Enabled = enabled; } + + public NativeConditionalAttribute(string condition, string stubReturnStatement, bool enabled) : this(condition, stubReturnStatement) + { + Enabled = enabled; + } + + public NativeConditionalAttribute(string condition, string stubReturnStatement) : this(condition) + { + StubReturnStatement = stubReturnStatement; + } } @@ -383,5 +394,6 @@ public NativeThrowsAttribute(bool throwsException) [VisibleToOtherModules] class IgnoreAttribute : Attribute, IBindingsAttribute { + public bool DoesNotContributeToSize { get; set; } } } diff --git a/Modules/UnityConnect/AnalyticsSessionInfo.bindings.cs b/Modules/UnityConnect/AnalyticsSessionInfo.bindings.cs index 9767aee05e..5f22999c43 100644 --- a/Modules/UnityConnect/AnalyticsSessionInfo.bindings.cs +++ b/Modules/UnityConnect/AnalyticsSessionInfo.bindings.cs @@ -21,6 +21,7 @@ public enum AnalyticsSessionState } [RequiredByNativeCode] + [NativeHeader("UnityConnectScriptingClasses.h")] [NativeHeader("Modules/UnityConnect/UnityConnectClient.h")] public static class AnalyticsSessionInfo { diff --git a/Modules/XR/DotNetHelper.cs b/Modules/XR/DotNetHelper.cs new file mode 100644 index 0000000000..5f15fbf17b --- /dev/null +++ b/Modules/XR/DotNetHelper.cs @@ -0,0 +1,27 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Collections.Generic; + +namespace UnityEngine.Experimental.XR +{ + internal static class DotNetHelper + { + public static bool TryCopyFixedArrayToList(T[] fixedArrayIn, List listOut) + { + if (fixedArrayIn == null) + return false; + + var count = fixedArrayIn.Length; + + listOut.Clear(); + + if (listOut.Capacity < count) + listOut.Capacity = count; + + listOut.AddRange(fixedArrayIn); + return true; + } + } +} diff --git a/Modules/XR/Subsystems/Camera/XRCameraSubsystem.bindings.cs b/Modules/XR/Subsystems/Camera/XRCameraSubsystem.bindings.cs new file mode 100644 index 0000000000..e0d11da869 --- /dev/null +++ b/Modules/XR/Subsystems/Camera/XRCameraSubsystem.bindings.cs @@ -0,0 +1,77 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; + +namespace UnityEngine.Experimental.XR +{ + public struct FrameReceivedEventArgs + { + internal XRCameraSubsystem m_CameraSubsystem; + public XRCameraSubsystem CameraSubsystem { get { return m_CameraSubsystem; } } + } + + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeHeader("Runtime/Graphics/Texture2D.h")] + [NativeType(Header = "Modules/XR/Subsystems/Camera/XRCameraSubsystem.h")] + [UsedByNativeCode] + [NativeConditional("ENABLE_XR")] + public class XRCameraSubsystem : Subsystem + { + public extern int LastUpdatedFrame { get; } + + public extern bool LightEstimationRequested { get; set; } + + public extern Material Material { get; set; } + + public extern Camera Camera { get; set; } + + public extern bool TryGetAverageBrightness(ref float averageBrightness); + + public extern bool TryGetAverageColorTemperature(ref float averageColorTemperature); + + public extern bool TryGetProjectionMatrix(ref Matrix4x4 projectionMatrix); + + public extern bool TryGetDisplayMatrix(ref Matrix4x4 displayMatrix); + + public extern bool TryGetTimestamp(ref Int64 timestampNs); + + public bool TryGetShaderName(ref string shaderName) + { + return Internal_TryGetShaderName(ref shaderName); + } + + private extern bool Internal_TryGetShaderName(ref string shaderName); + + public void GetTextures(List texturesOut) + { + if (texturesOut == null) + throw new ArgumentNullException("texturesOut"); + + GetTexturesAsList(texturesOut); + } + + private extern void GetTexturesAsList(List textures); + + private extern Texture2D[] GetTexturesAsFixedArray(); + + public event Action FrameReceived; + + [RequiredByNativeCode] + private void InvokeFrameReceivedEvent() + { + if (FrameReceived != null) + { + FrameReceived(new FrameReceivedEventArgs() + { + m_CameraSubsystem = this + }); + } + } + } +} diff --git a/Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.bindings.cs index 153527755c..89dc78a5f9 100644 --- a/Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.bindings.cs +++ b/Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.bindings.cs @@ -7,18 +7,24 @@ using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using UnityEngine.Experimental; namespace UnityEngine.Experimental.XR { [NativeHeader("Modules/XR/XRPrefix.h")] [NativeType(Header = "Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.h")] [UsedByNativeCode] - public class XRCameraSubsystemDescriptor : XRSubsystemDescriptor + [NativeConditional("ENABLE_XR")] + public class XRCameraSubsystemDescriptor : SubsystemDescriptor { - [NativeConditional("ENABLE_XR")] public extern bool ProvidesAverageBrightness { get; } - [NativeConditional("ENABLE_XR")] public extern bool ProvidesAverageColorTemperature { get; } + + public extern bool ProvidesProjectionMatrix { get; } + + public extern bool ProvidesDisplayMatrix { get; } + + public extern bool ProvidesTimestamp { get; } } } diff --git a/Modules/XR/Subsystems/Depth/XRDepthSubsystem.bindings.cs b/Modules/XR/Subsystems/Depth/XRDepthSubsystem.bindings.cs new file mode 100644 index 0000000000..f70c9a53b2 --- /dev/null +++ b/Modules/XR/Subsystems/Depth/XRDepthSubsystem.bindings.cs @@ -0,0 +1,66 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using UnityEngine.Experimental; + +namespace UnityEngine.Experimental.XR +{ + public struct PointCloudUpdatedEventArgs + { + internal XRDepthSubsystem m_DepthSubsystem; + public XRDepthSubsystem DepthSubsystem { get { return m_DepthSubsystem; } } + } + + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeHeader("Modules/XR/Subsystems/Depth/XRDepthSubsystem.h")] + [UsedByNativeCode] + [NativeConditional("ENABLE_XR")] + public class XRDepthSubsystem : Subsystem + { + public event Action PointCloudUpdated; + + public extern int LastUpdatedFrame { get; } + + public void GetPoints(List pointsOut) + { + if (pointsOut == null) + throw new ArgumentNullException("pointsOut"); + + Internal_GetPointCloudPointsAsList(pointsOut); + } + + public void GetConfidence(List confidenceOut) + { + if (confidenceOut == null) + throw new ArgumentNullException("confidenceOut"); + + Internal_GetPointCloudConfidenceAsList(confidenceOut); + } + + [RequiredByNativeCode] + private void InvokePointCloudUpdatedEvent() + { + if (PointCloudUpdated != null) + { + PointCloudUpdated(new PointCloudUpdatedEventArgs() + { + m_DepthSubsystem = this + }); + } + } + + private extern void Internal_GetPointCloudPointsAsList(List pointsOut); + + private extern void Internal_GetPointCloudConfidenceAsList(List confidenceOut); + + private extern Vector3[] Internal_GetPointCloudPointsAsFixedArray(); + + private extern float[] Internal_GetPointCloudConfidenceAsFixedArray(); + } +} diff --git a/Modules/XR/Subsystems/Camera/XRCameraInstance.bindings.cs b/Modules/XR/Subsystems/Depth/XRDepthSubsystemDescriptor.bindings.cs similarity index 50% rename from Modules/XR/Subsystems/Camera/XRCameraInstance.bindings.cs rename to Modules/XR/Subsystems/Depth/XRDepthSubsystemDescriptor.bindings.cs index 1f8d8dc26f..b22773046a 100644 --- a/Modules/XR/Subsystems/Camera/XRCameraInstance.bindings.cs +++ b/Modules/XR/Subsystems/Depth/XRDepthSubsystemDescriptor.bindings.cs @@ -4,25 +4,19 @@ using System; using UnityEngine.Bindings; -using UnityEngine.Rendering; using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using UnityEngine.Experimental; namespace UnityEngine.Experimental.XR { [NativeHeader("Modules/XR/XRPrefix.h")] - [NativeType(Header = "Modules/XR/Subsystems/Camera/XRCameraInstance.h")] + [NativeType(Header = "Modules/XR/Subsystems/Depth/XRDepthSubsystemDescriptor.h")] [UsedByNativeCode] - public class XRCameraInstance : XRInstance + [NativeConditional("ENABLE_XR")] + public class XRDepthSubsystemDescriptor : SubsystemDescriptor { - [NativeConditional("ENABLE_XR")] - public extern void SetMaterial(Material mat); - - [NativeConditional("ENABLE_XR")] - public extern float GetAverageBrightness(); - - [NativeConditional("ENABLE_XR")] - public extern float GetAverageColorTemperature(); + public extern bool SupportsFeaturePoints { get; } } } diff --git a/Modules/XR/Subsystems/Environment/Depth/XRDepth.bindings.cs b/Modules/XR/Subsystems/Environment/Depth/XRDepth.bindings.cs deleted file mode 100644 index 46f23166a9..0000000000 --- a/Modules/XR/Subsystems/Environment/Depth/XRDepth.bindings.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using System.Runtime.InteropServices; -using System.Collections.Generic; - -namespace UnityEngine.Experimental.XR -{ - public struct PointCloudUpdatedEventArgs - { - internal XRDepth m_Depth; - public XRDepth XRDepth { get { return m_Depth; } } - } - - [NativeHeader("Modules/XR/XRPrefix.h")] - [NativeHeader("Modules/XR/Subsystems/Environment/Depth/XRDepth.h")] - [StructLayout(LayoutKind.Sequential)] - public class XRDepth - { - private IntPtr m_Ptr; - private XREnvironment m_Environment; - - public bool Valid - { - get - { - return m_Ptr != IntPtr.Zero; - } - } - - public XREnvironment XREnvironment - { - get - { - return m_Environment; - } - } - - public event Action PointCloudUpdated; - - [NativeConditional("ENABLE_XR")] - public extern int FrameOfLastPointCloudUpdate { get; } - - [NativeConditional("ENABLE_XR")] - public extern bool TryGetPoint(TrackableId pointId, out Vector3 point); - - public void GetPointCloudPoints(List pointsOut) - { - if (pointsOut == null) - throw new ArgumentNullException("pointsOut"); - - Internal_GetPointCloudPointsAsList(pointsOut); - } - - public void GetPointCloudConfidence(List confidenceOut) - { - if (confidenceOut == null) - throw new ArgumentNullException("confidenceOut"); - - Internal_GetPointCloudConfidenceAsList(confidenceOut); - } - - internal XRDepth(IntPtr nativeEnvironment, XREnvironment managedEnvironment) - { - m_Ptr = Internal_Create(nativeEnvironment); - m_Environment = managedEnvironment; - SetHandle(this); - } - - [RequiredByNativeCode] - private void NotifyDepthDestruction() - { - m_Ptr = IntPtr.Zero; - } - - [RequiredByNativeCode] - private void InvokePointCloudUpdatedEvent() - { - if (PointCloudUpdated != null) - { - PointCloudUpdated(new PointCloudUpdatedEventArgs() - { - m_Depth = this - }); - } - } - - [NativeConditional("ENABLE_XR")] - private static extern IntPtr Internal_Create(IntPtr xrEnvironment); - - [NativeConditional("ENABLE_XR")] - private extern void SetHandle(XRDepth inst); - - [NativeConditional("ENABLE_XR")] - private extern void Internal_GetPointCloudPointsAsList(List pointsOut); - - [NativeConditional("ENABLE_XR")] - private extern void Internal_GetPointCloudConfidenceAsList(List confidenceOut); - - [NativeConditional("ENABLE_XR")] - private extern Vector3[] Internal_GetPointCloudPointsAsFixedArray(); - - [NativeConditional("ENABLE_XR")] - private extern float[] Internal_GetPointCloudConfidenceAsFixedArray(); - } -} diff --git a/Modules/XR/Subsystems/Environment/ReferencePoints/XRReferencePoint.bindings.cs b/Modules/XR/Subsystems/Environment/ReferencePoints/XRReferencePoint.bindings.cs deleted file mode 100644 index 60aefe00c5..0000000000 --- a/Modules/XR/Subsystems/Environment/ReferencePoints/XRReferencePoint.bindings.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using System.Runtime.InteropServices; -using System.Collections.Generic; - -namespace UnityEngine.Experimental.XR -{ - // Must match XRManagedReferencePoint - [UsedByNativeCode] - [StructLayout(LayoutKind.Sequential)] - [NativeHeader("Modules/XR/Subsystems/Environment/ReferencePoints/XRManagedReferencePoint.h")] - public struct ReferencePoint - { - public TrackableId Id { get; set; } - public Vector3 Position { get; set; } - public Quaternion Rotation { get; set; } - } - - public struct ReferencePointUpdatedEventArgs - { - public ReferencePoint UpdatedReferencePoint { get; set; } - } - - [NativeHeader("Modules/XR/XRPrefix.h")] - [NativeHeader("Modules/XR/Subsystems/Environment/ReferencePoints/XRReferencePoint.h")] - [StructLayout(LayoutKind.Sequential)] - public class XRReferencePoint - { - private IntPtr m_Ptr; - private XREnvironment m_Environment; - - public bool Valid - { - get - { - return m_Ptr != IntPtr.Zero; - } - } - - public XREnvironment XREnvironment - { - get - { - return m_Environment; - } - } - - public event Action ReferencePointUpdated; - - [NativeConditional("ENABLE_XR")] - public extern int FrameOfLastReferencePointUpdate { get; } - - [NativeConditional("ENABLE_XR")] - public extern bool TryAddReferencePoint(Vector3 position, Quaternion rotation, out TrackableId referencePointId); - - [NativeConditional("ENABLE_XR")] - public extern bool TryRemoveReferencePoint(TrackableId referencePointId); - - [NativeConditional("ENABLE_XR")] - public extern bool TryGetReferencePoint(TrackableId referencePointId, out ReferencePoint referencePoint); - - public void GetAllReferencePoints(List referencePointsOut) - { - if (referencePointsOut == null) - throw new ArgumentNullException("referencePointsOut"); - - Internal_GetAllReferencePointsAsList(referencePointsOut); - } - - internal XRReferencePoint(IntPtr nativeEnvironment, XREnvironment managedEnvironment) - { - m_Ptr = Internal_Create(nativeEnvironment); - m_Environment = managedEnvironment; - SetHandle(this); - } - - [RequiredByNativeCode] - private void NotifyReferencePointsDestruction() - { - m_Ptr = IntPtr.Zero; - } - - [RequiredByNativeCode] - private void InvokeReferencePointUpdatedEvent(ReferencePoint updatedReferencePoint) - { - if (ReferencePointUpdated != null) - ReferencePointUpdated(new ReferencePointUpdatedEventArgs() - { - UpdatedReferencePoint = updatedReferencePoint - }); - } - - [NativeConditional("ENABLE_XR")] - private static extern IntPtr Internal_Create(IntPtr xrEnvironment); - - [NativeConditional("ENABLE_XR")] - private extern void SetHandle(XRReferencePoint inst); - - [NativeConditional("ENABLE_XR")] - private extern void Internal_GetAllReferencePointsAsList(List referencePointsOut); - - [NativeConditional("ENABLE_XR")] - private extern ReferencePoint[] Internal_GetAllReferencePointsAsFixedArray(); - } -} diff --git a/Modules/XR/Subsystems/Environment/Session/XRSession.bindings.cs b/Modules/XR/Subsystems/Environment/Session/XRSession.bindings.cs deleted file mode 100644 index 514c3d29c7..0000000000 --- a/Modules/XR/Subsystems/Environment/Session/XRSession.bindings.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using System.Runtime.InteropServices; -using System.Collections.Generic; - -namespace UnityEngine.Experimental.XR -{ - [NativeHeader("Modules/XR/Subsystems/Environment/Session/XRSession.h")] - [UsedByNativeCode] - public struct SessionConfiguration - { - public bool EnablePlaneDetection { get; set; } - public bool EnableDepthData { get; set; } - public bool EnableCamera { get; set; } - public bool EnableLightEstimation { get; set; } - } - - // Must match UnityXRTrackingState - public enum TrackingState - { - Unknown = 0, - Initializing = 1, - Tracking = 2, - Suspended = 3, - Aborted = 4 - } - - [NativeHeader("Modules/XR/XRPrefix.h")] - [NativeHeader("Modules/XR/Subsystems/Environment/Session/XRSession.h")] - [NativeHeader("XRScriptingClasses.h")] - [StructLayout(LayoutKind.Sequential)] - public class XRSession - { - private IntPtr m_Ptr; - private XREnvironment m_Environment; - - public bool Valid - { - get - { - return m_Ptr != IntPtr.Zero; - } - } - - public XREnvironment Environment - { - get - { - return m_Environment; - } - } - - // NativeConditional can't handle enums at the moment - public extern TrackingState TrackingState { get; } - - [NativeConditional("ENABLE_XR")] - public extern int FrameOfLastTrackingStateUpdate { get; } - - [NativeConditional("ENABLE_XR")] - public extern void SetConfig(SessionConfiguration config); - - internal XRSession(IntPtr nativeEnvironment, XREnvironment managedEnvironment) - { - m_Ptr = Internal_Create(nativeEnvironment); - m_Environment = managedEnvironment; - SetHandle(this); - } - - [RequiredByNativeCode] - private void NotifySessionDestruction() - { - m_Ptr = IntPtr.Zero; - } - - [NativeConditional("ENABLE_XR")] - private static extern IntPtr Internal_Create(IntPtr xrEnvironment); - - [NativeConditional("ENABLE_XR")] - private extern void SetHandle(XRSession inst); - } -} diff --git a/Modules/XR/Subsystems/Environment/XREnvironment.bindings.cs b/Modules/XR/Subsystems/Environment/XREnvironment.bindings.cs deleted file mode 100644 index ffd48a1841..0000000000 --- a/Modules/XR/Subsystems/Environment/XREnvironment.bindings.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using System.Runtime.InteropServices; -using System.Collections.Generic; - -namespace UnityEngine.Experimental.XR -{ - [NativeHeader("Modules/XR/Subsystems/Environment/XREnvironment.h")] - [UsedByNativeCode] - [StructLayout(LayoutKind.Sequential)] - public struct TrackableId - { - public override string ToString() - { - return string.Format("{0}-{1}", - m_SubId1.ToString("X16"), - m_SubId2.ToString("X16")); - } - - public override int GetHashCode() - { - return m_SubId1.GetHashCode() ^ m_SubId2.GetHashCode(); - } - - public override bool Equals(object obj) - { - if (obj is TrackableId) - { - var id = (TrackableId)obj; - return - (m_SubId1 == id.m_SubId1) && - (m_SubId2 == id.m_SubId2); - } - - return false; - } - - public static bool operator==(TrackableId id1, TrackableId id2) - { - return - (id1.m_SubId1 == id2.m_SubId1) && - (id1.m_SubId2 == id2.m_SubId2); - } - - public static bool operator!=(TrackableId id1, TrackableId id2) - { - return - (id1.m_SubId1 != id2.m_SubId1) || - (id1.m_SubId2 != id2.m_SubId2); - } - - private static TrackableId s_InvalidId = new TrackableId(); - public static TrackableId InvalidId { get { return s_InvalidId; } } - - private ulong m_SubId1; - private ulong m_SubId2; - } - - internal static class DotNetHelper - { - public static bool TryCopyFixedArrayToList(T[] fixedArrayIn, List listOut) - { - if (fixedArrayIn == null) - return false; - - var count = fixedArrayIn.Length; - - listOut.Clear(); - - if (listOut.Capacity < count) - listOut.Capacity = count; - - listOut.AddRange(fixedArrayIn); - return true; - } - } - - [NativeHeader("Modules/XR/Subsystems/Environment/XREnvironment.h")] - [UsedByNativeCode("xrEnvironment")] - public class XREnvironment : XRInstance - { - // internal since XREnvironment may only be created by the XRSubsystemDescriptor - internal XREnvironment() : base() {} - - public XRDepth Depth - { - get - { - return m_DepthInterface; - } - } - - public XRPlane Planes - { - get - { - return m_PlanesInterface; - } - } - - public XRRaycast Raycast - { - get - { - return m_RaycastInterface; - } - } - - public XRReferencePoint ReferencePoints - { - get - { - return m_ReferencePointsInterface; - } - } - - public XRSession Session - { - get - { - return m_SessionInterface; - } - } - - private XRDepth m_DepthInterface; - private XRPlane m_PlanesInterface; - private XRRaycast m_RaycastInterface; - private XRReferencePoint m_ReferencePointsInterface; - private XRSession m_SessionInterface; - - override internal void Initialize() - { - m_DepthInterface = new XRDepth(m_Ptr, this); - m_PlanesInterface = new XRPlane(m_Ptr, this); - m_RaycastInterface = new XRRaycast(m_Ptr, this); - m_ReferencePointsInterface = new XRReferencePoint(m_Ptr, this); - m_SessionInterface = new XRSession(m_Ptr, this); - } - } -} diff --git a/Modules/XR/Subsystems/Environment/XREnvironmentSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/Environment/XREnvironmentSubsystemDescriptor.bindings.cs deleted file mode 100644 index 7784b4a96a..0000000000 --- a/Modules/XR/Subsystems/Environment/XREnvironmentSubsystemDescriptor.bindings.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace UnityEngine.Experimental.XR -{ - [NativeHeader("Modules/XR/XRPrefix.h")] - [NativeType(Header = "Modules/XR/Subsystems/Environment/XREnvironmentSubsystemDescriptor.h")] - [UsedByNativeCode("xrEnvironmentSubsystemDescriptor")] - public class XREnvironmentSubsystemDescriptor : XRSubsystemDescriptor - { - [NativeConditional("ENABLE_XR")] - public extern bool SupportsFeaturePoints { get; } - - [NativeConditional("ENABLE_XR")] - public extern bool SupportsPlaneFinding { get; } - - [NativeConditional("ENABLE_XR")] - public extern bool SupportsReferencePoints { get; } - - [NativeConditional("ENABLE_XR")] - public extern bool SupportsLightEstimation { get; } - } -} diff --git a/Modules/XR/Subsystems/Example/XRExampleInstance.bindings.cs b/Modules/XR/Subsystems/Example/XRExampleSubsystem.bindings.cs similarity index 88% rename from Modules/XR/Subsystems/Example/XRExampleInstance.bindings.cs rename to Modules/XR/Subsystems/Example/XRExampleSubsystem.bindings.cs index 0bfb91e6a1..02d1ed1fc9 100644 --- a/Modules/XR/Subsystems/Example/XRExampleInstance.bindings.cs +++ b/Modules/XR/Subsystems/Example/XRExampleSubsystem.bindings.cs @@ -10,9 +10,9 @@ namespace UnityEngine.Experimental.XR { - [NativeType(Header = "Modules/XR/Subsystems/Example/XRExampleInstance.h")] + [NativeType(Header = "Modules/XR/Subsystems/Example/XRExampleSubsystem.h")] [UsedByNativeCode] - public class XRExampleInstance : XRInstance + public class XRExampleSubsystem : Subsystem { public extern void PrintExample(); public extern bool GetBool(); diff --git a/Modules/XR/Subsystems/Example/XRExampleSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/Example/XRExampleSubsystemDescriptor.bindings.cs index a5087cf973..720abcd0cd 100644 --- a/Modules/XR/Subsystems/Example/XRExampleSubsystemDescriptor.bindings.cs +++ b/Modules/XR/Subsystems/Example/XRExampleSubsystemDescriptor.bindings.cs @@ -12,7 +12,7 @@ namespace UnityEngine.Experimental.XR { [NativeType(Header = "Modules/XR/Subsystems/Example/XRExampleSubsystemDescriptor.h")] [UsedByNativeCode] - public class XRExampleSubsystemDescriptor : XRSubsystemDescriptor + public class XRExampleSubsystemDescriptor : SubsystemDescriptor { public extern bool supportsEditorMode { get; } public extern bool disableBackbufferMSAA { get; } diff --git a/Modules/XR/Subsystems/Input/XRInputInstance.bindings.cs b/Modules/XR/Subsystems/Input/XRInputSubsystem.bindings.cs similarity index 76% rename from Modules/XR/Subsystems/Input/XRInputInstance.bindings.cs rename to Modules/XR/Subsystems/Input/XRInputSubsystem.bindings.cs index f865953544..274e62365e 100644 --- a/Modules/XR/Subsystems/Input/XRInputInstance.bindings.cs +++ b/Modules/XR/Subsystems/Input/XRInputSubsystem.bindings.cs @@ -10,9 +10,9 @@ namespace UnityEngine.Experimental.XR { - [NativeType(Header = "Modules/XR/Subsystems/Input/XRInputInstance.h")] + [NativeType(Header = "Modules/XR/Subsystems/Input/XRInputSubsystem")] [UsedByNativeCode] - public class XRInputInstance : XRInstance + public class XRInputSubsystem : Subsystem { } } diff --git a/Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.bindings.cs index 13c8e5503a..42dc5e24eb 100644 --- a/Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.bindings.cs +++ b/Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.bindings.cs @@ -12,6 +12,6 @@ namespace UnityEngine.Experimental.XR { [NativeType(Header = "Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.h")] [UsedByNativeCode] - public class XRInputSubsystemDescriptor : XRSubsystemDescriptor + public class XRInputSubsystemDescriptor : SubsystemDescriptor {} } diff --git a/Modules/XR/Subsystems/Environment/Planes/XRPlane.bindings.cs b/Modules/XR/Subsystems/Planes/XRPlaneSubsystem.bindings.cs similarity index 57% rename from Modules/XR/Subsystems/Environment/Planes/XRPlane.bindings.cs rename to Modules/XR/Subsystems/Planes/XRPlaneSubsystem.bindings.cs index ad883731ac..5308a87299 100644 --- a/Modules/XR/Subsystems/Environment/Planes/XRPlane.bindings.cs +++ b/Modules/XR/Subsystems/Planes/XRPlaneSubsystem.bindings.cs @@ -10,6 +10,7 @@ namespace UnityEngine.Experimental.XR { + [UsedByNativeCode] [Flags] public enum PlaneAlignment { @@ -20,22 +21,24 @@ public enum PlaneAlignment [UsedByNativeCode] [StructLayout(LayoutKind.Sequential)] - [NativeHeader("Modules/XR/Subsystems/Environment/Planes/XRBoundedPlane.h")] + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeHeader("Modules/XR/Subsystems/Planes/XRBoundedPlane.h")] [NativeHeader("XRScriptingClasses.h")] + [NativeConditional("ENABLE_XR")] public struct BoundedPlane { private uint m_InstanceId; public TrackableId Id { get; set; } - public Vector3 Position { get; set; } + public TrackableId SubsumedById { get; set; } + public Pose Pose { get; set; } public Vector3 Center { get; set; } - public Quaternion Rotation { get; set; } public Vector2 Size { get; set; } public PlaneAlignment Alignment { get; set; } public float Width { get { return Size.x; } } public float Height { get { return Size.y; } } - public Vector3 Normal { get { return Rotation * Vector3.up; } } + public Vector3 Normal { get { return Pose.up; } } public Plane Plane { get { return new Plane(Normal, Center); } } public void GetCorners( @@ -44,8 +47,8 @@ public void GetCorners( out Vector3 p2, out Vector3 p3) { - var worldHalfX = (Rotation * Vector3.right) * (Width * .5f); - var worldHalfZ = (Rotation * Vector3.forward) * (Height * .5f); + var worldHalfX = (Pose.right) * (Width * .5f); + var worldHalfZ = (Pose.forward) * (Height * .5f); p0 = Center - worldHalfX - worldHalfZ; p1 = Center - worldHalfX + worldHalfZ; p2 = Center + worldHalfX + worldHalfZ; @@ -60,12 +63,10 @@ public bool TryGetBoundary(List boundaryOut) return Internal_GetBoundaryAsList(m_InstanceId, Id, boundaryOut); } - [NativeConditional("ENABLE_XR")] private static extern Vector3[] Internal_GetBoundaryAsFixedArray( uint instanceId, TrackableId id); - [NativeConditional("ENABLE_XR")] private static extern bool Internal_GetBoundaryAsList( uint instanceId, TrackableId id, @@ -74,58 +75,34 @@ private static extern bool Internal_GetBoundaryAsList( public struct PlaneAddedEventArgs { - internal XRPlane m_Planes; - public XRPlane XRPlane { get { return m_Planes; } } - public BoundedPlane AddedPlane { get; set; } + public XRPlaneSubsystem PlaneSubsystem { get; internal set; } + public BoundedPlane Plane { get; internal set; } } public struct PlaneUpdatedEventArgs { - internal XRPlane m_Planes; - public XRPlane XRPlane { get { return m_Planes; } } - public BoundedPlane UpdatedPlane { get; set; } + public XRPlaneSubsystem PlaneSubsystem { get; internal set; } + public BoundedPlane Plane { get; internal set; } } public struct PlaneRemovedEventArgs { - internal XRPlane m_Planes; - public XRPlane XRPlane { get { return m_Planes; } } - public BoundedPlane RemovedPlane { get; set; } - public BoundedPlane? SubsumedByPlane { get; set; } + public XRPlaneSubsystem PlaneSubsystem { get; internal set; } + public BoundedPlane Plane { get; internal set; } } [NativeHeader("Modules/XR/XRPrefix.h")] - [NativeHeader("Modules/XR/Subsystems/Environment/Planes/XRPlane.h")] - [StructLayout(LayoutKind.Sequential)] - public class XRPlane + [NativeHeader("Modules/XR/Subsystems/Planes/XRPlaneSubsystem.h")] + [UsedByNativeCode] + [NativeConditional("ENABLE_XR")] + public class XRPlaneSubsystem : Subsystem { - private IntPtr m_Ptr; - private XREnvironment m_Environment; - - public bool Valid - { - get - { - return m_Ptr != IntPtr.Zero; - } - } - - public XREnvironment XREnvironment - { - get - { - return m_Environment; - } - } - public event Action PlaneAdded; public event Action PlaneUpdated; public event Action PlaneRemoved; - [NativeConditional("ENABLE_XR")] - public extern int FrameOfLastPlaneUpdate { get; } + public extern int LastUpdatedFrame { get; } - [NativeConditional("ENABLE_XR")] public extern bool TryGetPlane(TrackableId planeId, out BoundedPlane plane); public void GetAllPlanes(List planesOut) @@ -144,19 +121,6 @@ public bool TryGetPlaneBoundary(TrackableId planeId, List boundaryOut) return Internal_GetBoundaryAsList(planeId, boundaryOut); } - internal XRPlane(IntPtr nativeEnvironment, XREnvironment managedEnvironment) - { - m_Ptr = Internal_Create(nativeEnvironment); - m_Environment = managedEnvironment; - SetHandle(this); - } - - [RequiredByNativeCode] - private void NotifyPlanesDestruction() - { - m_Ptr = IntPtr.Zero; - } - [RequiredByNativeCode] private void InvokePlaneAddedEvent(BoundedPlane plane) { @@ -164,8 +128,8 @@ private void InvokePlaneAddedEvent(BoundedPlane plane) { PlaneAdded(new PlaneAddedEventArgs() { - m_Planes = this, - AddedPlane = plane + PlaneSubsystem = this, + Plane = plane }); } } @@ -177,22 +141,8 @@ private void InvokePlaneUpdatedEvent(BoundedPlane plane) { PlaneUpdated(new PlaneUpdatedEventArgs() { - m_Planes = this, - UpdatedPlane = plane - }); - } - } - - [RequiredByNativeCode] - private void InvokePlaneMergedEvent(BoundedPlane removedPlane, BoundedPlane subsumedByPlane) - { - if (PlaneRemoved != null) - { - PlaneRemoved(new PlaneRemovedEventArgs() - { - m_Planes = this, - RemovedPlane = removedPlane, - SubsumedByPlane = subsumedByPlane + PlaneSubsystem = this, + Plane = plane }); } } @@ -204,29 +154,18 @@ private void InvokePlaneRemovedEvent(BoundedPlane removedPlane) { PlaneRemoved(new PlaneRemovedEventArgs() { - m_Planes = this, - RemovedPlane = removedPlane, - SubsumedByPlane = null + PlaneSubsystem = this, + Plane = removedPlane }); } } - [NativeConditional("ENABLE_XR")] private extern BoundedPlane[] GetAllPlanesAsFixedArray(); - [NativeConditional("ENABLE_XR")] private extern void GetAllPlanesAsList(List planes); - [NativeConditional("ENABLE_XR")] private extern bool Internal_GetBoundaryAsList(TrackableId planeId, List boundaryOut); - [NativeConditional("ENABLE_XR")] private extern Vector3[] Internal_GetBoundaryAsFixedArray(TrackableId planeId); - - [NativeConditional("ENABLE_XR")] - private static extern IntPtr Internal_Create(IntPtr xrEnvironment); - - [NativeConditional("ENABLE_XR")] - private extern void SetHandle(XRPlane inst); } } diff --git a/Modules/XR/Subsystems/Planes/XRPlaneSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/Planes/XRPlaneSubsystemDescriptor.bindings.cs new file mode 100644 index 0000000000..e42b955b12 --- /dev/null +++ b/Modules/XR/Subsystems/Planes/XRPlaneSubsystemDescriptor.bindings.cs @@ -0,0 +1,19 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace UnityEngine.Experimental.XR +{ + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeType(Header = "Modules/XR/Subsystems/Planes/XRPlaneSubsystemDescriptor.h")] + [UsedByNativeCode] + public class XRPlaneSubsystemDescriptor : SubsystemDescriptor + { + } +} diff --git a/Modules/XR/Subsystems/Environment/Raycast/XRRaycast.bindings.cs b/Modules/XR/Subsystems/Raycast/XRRaycastSubsystem.bindings.cs similarity index 50% rename from Modules/XR/Subsystems/Environment/Raycast/XRRaycast.bindings.cs rename to Modules/XR/Subsystems/Raycast/XRRaycastSubsystem.bindings.cs index f370545360..e65f2fb743 100644 --- a/Modules/XR/Subsystems/Environment/Raycast/XRRaycast.bindings.cs +++ b/Modules/XR/Subsystems/Raycast/XRRaycastSubsystem.bindings.cs @@ -7,10 +7,12 @@ using UnityEngine.Scripting; using System.Runtime.InteropServices; using System.Collections.Generic; +using UnityEngine.Experimental; namespace UnityEngine.Experimental.XR { // Must match UnityXRTrackableType + [UsedByNativeCode] [Flags] public enum TrackableType { @@ -29,54 +31,22 @@ public enum TrackableType } // Must match UnityXRRaycastHit - [NativeHeader("Modules/XR/Subsystems/Environment/Raycast/XRRaycast.h")] + [NativeHeader("Modules/XR/Subsystems/Raycast/XRRaycastSubsystem.h")] [UsedByNativeCode] public struct XRRaycastHit { public TrackableId TrackableId { get; set; } - public Vector3 Position { get; set; } - public Quaternion Rotation { get; set; } + public Pose Pose { get; set; } public float Distance { get; set; } public TrackableType HitType { get; set; } } [NativeHeader("Modules/XR/XRPrefix.h")] - [NativeHeader("Modules/XR/Subsystems/Environment/Raycast/XRRaycast.h")] - [StructLayout(LayoutKind.Sequential)] - public class XRRaycast + [NativeHeader("Modules/XR/Subsystems/Raycast/XRRaycastSubsystem.h")] + [UsedByNativeCode] + [NativeConditional("ENABLE_XR")] + public class XRRaycastSubsystem : Subsystem { - private IntPtr m_Ptr; - private XREnvironment m_Environment; - - public bool Valid - { - get - { - return m_Ptr != IntPtr.Zero; - } - } - - public XREnvironment Environment - { - get - { - return m_Environment; - } - } - - [NativeConditional("ENABLE_XR")] - public extern float RaycastAngle { get; set; } - - public bool Raycast(Ray ray, List hitResults, TrackableType trackableTypeMask = TrackableType.All) - { - if (hitResults == null) - throw new ArgumentNullException("hitResults"); - - hitResults.Clear(); - - return Internal_RaycastAsList(ray.origin, ray.direction, trackableTypeMask, hitResults); - } - public bool Raycast(Vector3 screenPoint, List hitResults, TrackableType trackableTypeMask = TrackableType.All) { if (hitResults == null) @@ -88,46 +58,44 @@ public bool Raycast(Vector3 screenPoint, List hitResults, Trackabl return Internal_ScreenRaycastAsList(screenX, screenY, trackableTypeMask, hitResults); } - internal XRRaycast(IntPtr nativeEnvironment, XREnvironment managedEnvironment) + static public void Raycast( + Ray ray, + XRDepthSubsystem depthSubsystem, + XRPlaneSubsystem planeSubsystem, + List hitResults, + TrackableType trackableTypeMask = TrackableType.All, + float pointCloudRaycastAngleInDegrees = 5f) { - m_Ptr = Internal_Create(nativeEnvironment); - m_Environment = managedEnvironment; - SetHandle(this); - } - - [RequiredByNativeCode] - private void NotifyRaycastDestruction() - { - m_Ptr = IntPtr.Zero; - } - - [NativeConditional("ENABLE_XR")] - private static extern IntPtr Internal_Create(IntPtr xrEnvironment); + if (hitResults == null) + throw new ArgumentNullException("hitResults"); - [NativeConditional("ENABLE_XR")] - private extern void SetHandle(XRRaycast inst); + IntPtr depthPtr = depthSubsystem == null ? IntPtr.Zero : depthSubsystem.m_Ptr; + IntPtr planePtr = planeSubsystem == null ? IntPtr.Zero : planeSubsystem.m_Ptr; - [NativeConditional("ENABLE_XR")] - private extern XRRaycastHit[] Internal_RaycastAsFixedArray( - Vector3 origin, - Vector3 direction, - TrackableType hitMask); + Internal_RaycastAsList(ray, pointCloudRaycastAngleInDegrees, depthPtr, planePtr, trackableTypeMask, hitResults); + } - [NativeConditional("ENABLE_XR")] - private extern bool Internal_RaycastAsList( - Vector3 origin, - Vector3 direction, - TrackableType hitMask, + private static extern void Internal_RaycastAsList( + Ray ray, + float pointCloudRaycastAngleInDegrees, + IntPtr depthSubsystem, + IntPtr planeSubsystem, + TrackableType trackableTypeMask, List hitResultsOut); - [NativeConditional("ENABLE_XR")] + private static extern XRRaycastHit[] Internal_RaycastAsFixedArray( + Ray ray, + float pointCloudRaycastAngleInDegrees, + IntPtr depthSubsystem, + IntPtr planeSubsystem, + TrackableType trackableTypeMask); + private extern bool Internal_ScreenRaycastAsList( float screenX, float screenY, TrackableType hitMask, List hitResultsOut); - [NativeConditional("ENABLE_XR")] private extern XRRaycastHit[] Internal_ScreenRaycastAsFixedArray( float screenX, float screenY, diff --git a/Modules/XR/Subsystems/Raycast/XRRaycastSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/Raycast/XRRaycastSubsystemDescriptor.bindings.cs new file mode 100644 index 0000000000..d9ad4832e9 --- /dev/null +++ b/Modules/XR/Subsystems/Raycast/XRRaycastSubsystemDescriptor.bindings.cs @@ -0,0 +1,20 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using UnityEngine.Experimental; + +namespace UnityEngine.Experimental.XR +{ + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeType(Header = "Modules/XR/Subsystems/Raycast/XRRaycastSubsystemDescriptor.h")] + [UsedByNativeCode] + public class XRRaycastSubsystemDescriptor : SubsystemDescriptor + { + } +} diff --git a/Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystem.bindings.cs b/Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystem.bindings.cs new file mode 100644 index 0000000000..99807e3d6e --- /dev/null +++ b/Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystem.bindings.cs @@ -0,0 +1,79 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using UnityEngine.Experimental; + +namespace UnityEngine.Experimental.XR +{ + // Must match XRManagedReferencePoint + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + [NativeHeader("Modules/XR/Subsystems/ReferencePoints/XRManagedReferencePoint.h")] + [NativeHeader("Modules/XR/Subsystems/Session/XRSessionSubsystem.h")] + public struct ReferencePoint + { + public TrackableId Id { get; internal set; } + public TrackingState TrackingState { get; internal set; } + public Pose Pose { get; internal set; } + } + + [NativeHeader("Modules/XR/Subsystems/Session/XRSessionSubsystem.h")] + public struct ReferencePointUpdatedEventArgs + { + public ReferencePoint ReferencePoint { get; internal set; } + public TrackingState PreviousTrackingState { get; internal set; } + public Pose PreviousPose { get; internal set; } + } + + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeHeader("Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystem.h")] + [UsedByNativeCode] + [NativeConditional("ENABLE_XR")] + public class XRReferencePointSubsystem : Subsystem + { + public event Action ReferencePointUpdated; + + public extern int LastUpdatedFrame { get; } + + public extern bool TryAddReferencePoint(Vector3 position, Quaternion rotation, out TrackableId referencePointId); + + public bool TryAddReferencePoint(Pose pose, out TrackableId referencePointId) + { + return TryAddReferencePoint(pose.position, pose.rotation, out referencePointId); + } + + public extern bool TryRemoveReferencePoint(TrackableId referencePointId); + + public extern bool TryGetReferencePoint(TrackableId referencePointId, out ReferencePoint referencePoint); + + public void GetAllReferencePoints(List referencePointsOut) + { + if (referencePointsOut == null) + throw new ArgumentNullException("referencePointsOut"); + + Internal_GetAllReferencePointsAsList(referencePointsOut); + } + + [RequiredByNativeCode] + private void InvokeReferencePointUpdatedEvent(ReferencePoint updatedReferencePoint, TrackingState previousTrackingState, Pose previousPose) + { + if (ReferencePointUpdated != null) + ReferencePointUpdated(new ReferencePointUpdatedEventArgs() + { + ReferencePoint = updatedReferencePoint, + PreviousTrackingState = previousTrackingState, + PreviousPose = previousPose + }); + } + + private extern void Internal_GetAllReferencePointsAsList(List referencePointsOut); + + private extern ReferencePoint[] Internal_GetAllReferencePointsAsFixedArray(); + } +} diff --git a/Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystemDescriptor.bindings.cs new file mode 100644 index 0000000000..99a1177196 --- /dev/null +++ b/Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystemDescriptor.bindings.cs @@ -0,0 +1,20 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using UnityEngine.Experimental; + +namespace UnityEngine.Experimental.XR +{ + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeType(Header = "Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystemDescriptor.h")] + [UsedByNativeCode] + public class XRReferencePointSubsystemDescriptor : SubsystemDescriptor + { + } +} diff --git a/Modules/XR/Subsystems/Session/XRSessionSubsystem.bindings.cs b/Modules/XR/Subsystems/Session/XRSessionSubsystem.bindings.cs new file mode 100644 index 0000000000..609ceff99e --- /dev/null +++ b/Modules/XR/Subsystems/Session/XRSessionSubsystem.bindings.cs @@ -0,0 +1,56 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using UnityEngine.Experimental; + +namespace UnityEngine.Experimental.XR +{ + // Must match UnityXRTrackingState + [UsedByNativeCode] + public enum TrackingState + { + Unknown = 0, + Tracking = 1, + Unavailable = 2 + } + + public struct SessionTrackingStateChangedEventArgs + { + internal XRSessionSubsystem m_Session; + public XRSessionSubsystem SessionSubsystem { get { return m_Session; } } + public TrackingState NewState { get; set; } + } + + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeHeader("Modules/XR/Subsystems/Session/XRSessionSubsystem.h")] + [UsedByNativeCode] + [NativeConditional("ENABLE_XR")] + public class XRSessionSubsystem : Subsystem + { + public event Action TrackingStateChanged; + + [NativeConditional("ENABLE_XR", StubReturnStatement = "kUnityXRTrackingStateUnknown")] + public extern TrackingState TrackingState { get; } + + public extern int LastUpdatedFrame { get; } + + [RequiredByNativeCode] + private void InvokeTrackingStateChangedEvent(TrackingState newState) + { + if (TrackingStateChanged != null) + { + TrackingStateChanged(new SessionTrackingStateChangedEventArgs() + { + m_Session = this, + NewState = newState + }); + } + } + } +} diff --git a/Modules/XR/Subsystems/Session/XRSessionSubsystemDescriptor.bindings.cs b/Modules/XR/Subsystems/Session/XRSessionSubsystemDescriptor.bindings.cs new file mode 100644 index 0000000000..faf180764e --- /dev/null +++ b/Modules/XR/Subsystems/Session/XRSessionSubsystemDescriptor.bindings.cs @@ -0,0 +1,20 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using UnityEngine.Experimental; + +namespace UnityEngine.Experimental.XR +{ + [NativeHeader("Modules/XR/XRPrefix.h")] + [NativeType(Header = "Modules/XR/Subsystems/Session/XRSessionSubsystemDescriptor.h")] + [UsedByNativeCode] + public class XRSessionSubsystemDescriptor : SubsystemDescriptor + { + } +} diff --git a/Modules/XR/UnityXRTrackable.bindings.cs b/Modules/XR/UnityXRTrackable.bindings.cs new file mode 100644 index 0000000000..598180b757 --- /dev/null +++ b/Modules/XR/UnityXRTrackable.bindings.cs @@ -0,0 +1,63 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using System.Runtime.InteropServices; +using System.Collections.Generic; + +namespace UnityEngine.Experimental.XR +{ + [NativeHeader("Modules/XR/XRManagedBindings.h")] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + public struct TrackableId + { + public override string ToString() + { + return string.Format("{0}-{1}", + m_SubId1.ToString("X16"), + m_SubId2.ToString("X16")); + } + + public override int GetHashCode() + { + return m_SubId1.GetHashCode() ^ m_SubId2.GetHashCode(); + } + + public override bool Equals(object obj) + { + if (obj is TrackableId) + { + var id = (TrackableId)obj; + return + (m_SubId1 == id.m_SubId1) && + (m_SubId2 == id.m_SubId2); + } + + return false; + } + + public static bool operator==(TrackableId id1, TrackableId id2) + { + return + (id1.m_SubId1 == id2.m_SubId1) && + (id1.m_SubId2 == id2.m_SubId2); + } + + public static bool operator!=(TrackableId id1, TrackableId id2) + { + return + (id1.m_SubId1 != id2.m_SubId1) || + (id1.m_SubId2 != id2.m_SubId2); + } + + private static TrackableId s_InvalidId = new TrackableId(); + public static TrackableId InvalidId { get { return s_InvalidId; } } + + private ulong m_SubId1; + private ulong m_SubId2; + } +} diff --git a/Modules/XR/XRSubsystemManager.bindings.cs b/Modules/XR/XRSubsystemManager.bindings.cs index c8ff86206b..a2f251fdc2 100644 --- a/Modules/XR/XRSubsystemManager.bindings.cs +++ b/Modules/XR/XRSubsystemManager.bindings.cs @@ -12,57 +12,56 @@ using intptr_t = System.Int32; -namespace UnityEngine.Experimental.XR +namespace UnityEngine.Experimental { - public interface IXRSubsystemDescriptor + public interface ISubsystemDescriptor { } - internal interface IXRSubsystemDescriptorImpl + internal interface ISubsystemDescriptorImpl { IntPtr ptr { get; set; } } [UsedByNativeCode("XRSubsystemDescriptorBase")] [StructLayout(LayoutKind.Sequential)] - public class XRSubsystemDescriptorBase : IXRSubsystemDescriptor, IXRSubsystemDescriptorImpl + public class SubsystemDescriptorBase : ISubsystemDescriptor, ISubsystemDescriptorImpl { internal IntPtr m_Ptr; public string id { - get { return Internal_XRSubsystemDescriptors.GetId(m_Ptr); } + get { return Internal_SubsystemDescriptors.GetId(m_Ptr); } } - IntPtr IXRSubsystemDescriptorImpl.ptr { get { return m_Ptr; } set { m_Ptr = value; } } + IntPtr ISubsystemDescriptorImpl.ptr { get { return m_Ptr; } set { m_Ptr = value; } } } [NativeType(Header = "Modules/XR/XRSubsystemDescriptor.h")] [UsedByNativeCode("XRSubsystemDescriptor")] [StructLayout(LayoutKind.Sequential)] - public class XRSubsystemDescriptor : XRSubsystemDescriptorBase - where TXRInstance : XRInstance + public class SubsystemDescriptor : SubsystemDescriptorBase + where TSubsystem : Subsystem { - public TXRInstance Create() + public TSubsystem Create() { - IntPtr ptr = Internal_XRSubsystemDescriptors.Create(m_Ptr); - var instance = (TXRInstance)Internal_XRSubsystemInstances.Internal_GetInstanceByPtr(ptr); + IntPtr ptr = Internal_SubsystemDescriptors.Create(m_Ptr); + var instance = (TSubsystem)Internal_SubsystemInstances.Internal_GetInstanceByPtr(ptr); instance.m_subsystemDescriptor = this; return instance; } } // Handle instance lifetime (on managed side) - internal static class Internal_XRSubsystemInstances + internal static class Internal_SubsystemInstances { - internal static List s_SubsystemInstances = new List(); + internal static List s_SubsystemInstances = new List(); [RequiredByNativeCode] - internal static void Internal_InitializeManagedInstance(IntPtr ptr, XRInstance inst) + internal static void Internal_InitializeManagedInstance(IntPtr ptr, Subsystem inst) { inst.m_Ptr = ptr; inst.SetHandle(inst); - inst.Initialize(); s_SubsystemInstances.Add(inst); } @@ -89,9 +88,9 @@ internal static void Internal_RemoveInstanceByPtr(IntPtr ptr) } } - internal static XRInstance Internal_GetInstanceByPtr(IntPtr ptr) + internal static Subsystem Internal_GetInstanceByPtr(IntPtr ptr) { - foreach (XRInstance instance in s_SubsystemInstances) + foreach (Subsystem instance in s_SubsystemInstances) { if (instance.m_Ptr == ptr) return instance; @@ -101,12 +100,12 @@ internal static XRInstance Internal_GetInstanceByPtr(IntPtr ptr) } // Handle subsystem descriptor lifetime (on managed side) - internal static class Internal_XRSubsystemDescriptors + internal static class Internal_SubsystemDescriptors { - internal static List s_SubsystemDescriptors = new List(); + internal static List s_SubsystemDescriptors = new List(); [RequiredByNativeCode] - internal static void Internal_InitializeManagedDescriptor(IntPtr ptr, IXRSubsystemDescriptorImpl desc) + internal static void Internal_InitializeManagedDescriptor(IntPtr ptr, ISubsystemDescriptorImpl desc) { desc.ptr = ptr; s_SubsystemDescriptors.Add(desc); @@ -122,24 +121,24 @@ internal static void Internal_ClearManagedDescriptors() s_SubsystemDescriptors.Clear(); } - // These are here instead of on XRSubsystemDescriptor because generic types are not supported by .bindings.cs + // These are here instead of on SubsystemDescriptor because generic types are not supported by .bindings.cs public static extern IntPtr Create(IntPtr descriptorPtr); public static extern string GetId(IntPtr descriptorPtr); } [NativeType(Header = "Modules/XR/XRSubsystemManager.h")] - public static class XRSubsystemManager + public static class SubsystemManager { - static XRSubsystemManager() + static SubsystemManager() { StaticConstructScriptingClassMap(); } public static void GetSubsystemDescriptors(List descriptors) - where T : IXRSubsystemDescriptor + where T : ISubsystemDescriptor { descriptors.Clear(); - foreach (var descriptor in Internal_XRSubsystemDescriptors.s_SubsystemDescriptors) + foreach (var descriptor in Internal_SubsystemDescriptors.s_SubsystemDescriptors) { if (descriptor is T) descriptors.Add((T)descriptor); @@ -147,10 +146,10 @@ public static void GetSubsystemDescriptors(List descriptors) } public static void GetInstances(List instances) - where T : XRInstance + where T : Subsystem { instances.Clear(); - foreach (var instance in Internal_XRSubsystemInstances.s_SubsystemInstances) + foreach (var instance in Internal_SubsystemInstances.s_SubsystemInstances) { if (instance is T) instances.Add((T)instance); @@ -161,31 +160,30 @@ public static void GetInstances(List instances) extern internal static void StaticConstructScriptingClassMap(); } - [NativeType(Header = "Modules/XR/XRInstance.h")] + [NativeType(Header = "Modules/XR/XRSubsystem.h")] [UsedByNativeCode] [StructLayout(LayoutKind.Sequential)] - public class XRInstance + public class Subsystem { internal IntPtr m_Ptr; - internal IXRSubsystemDescriptor m_subsystemDescriptor; + internal ISubsystemDescriptor m_subsystemDescriptor; - extern internal void SetHandle(XRInstance inst); - virtual internal void Initialize() {} + extern internal void SetHandle(Subsystem inst); extern public void Start(); extern public void Stop(); public void Destroy() { IntPtr removedPtr = m_Ptr; - Internal_XRSubsystemInstances.Internal_RemoveInstanceByPtr(m_Ptr); - XRSubsystemManager.DestroyInstance_Internal(removedPtr); + Internal_SubsystemInstances.Internal_RemoveInstanceByPtr(m_Ptr); + SubsystemManager.DestroyInstance_Internal(removedPtr); } } - [UsedByNativeCode("XRInstance_TXRSubsystemDescriptor")] - public class XRInstance : XRInstance where TXRSubsystemDescriptor : IXRSubsystemDescriptor + [UsedByNativeCode("XRSubsystem_TXRSubsystemDescriptor")] + public class Subsystem : Subsystem where TSubsystemDescriptor : ISubsystemDescriptor { - public TXRSubsystemDescriptor SubsystemDescriptor + public TSubsystemDescriptor SubsystemDescriptor { - get { return (TXRSubsystemDescriptor)m_subsystemDescriptor; } + get { return (TSubsystemDescriptor)m_subsystemDescriptor; } } } } diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index 473b66fe99..a6d3bdec6a 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -1992,47 +1992,62 @@ artifacts\generated\bindings_old\common\Wind\WindZoneBindings.gen.cs + +Modules\XR\DotNetHelper.cs + + +Modules\XR\UnityXRTrackable.bindings.cs + Modules\XR\XRSubsystemManager.bindings.cs - -Modules\XR\Subsystems\Camera\XRCameraInstance.bindings.cs + +Modules\XR\Subsystems\Camera\XRCameraSubsystem.bindings.cs Modules\XR\Subsystems\Camera\XRCameraSubsystemDescriptor.bindings.cs - -Modules\XR\Subsystems\Environment\XREnvironment.bindings.cs + +Modules\XR\Subsystems\Depth\XRDepthSubsystem.bindings.cs - -Modules\XR\Subsystems\Environment\XREnvironmentSubsystemDescriptor.bindings.cs + +Modules\XR\Subsystems\Depth\XRDepthSubsystemDescriptor.bindings.cs - -Modules\XR\Subsystems\Environment\Depth\XRDepth.bindings.cs + +Modules\XR\Subsystems\Example\XRExampleSubsystem.bindings.cs - -Modules\XR\Subsystems\Environment\Planes\XRPlane.bindings.cs + +Modules\XR\Subsystems\Example\XRExampleSubsystemDescriptor.bindings.cs - -Modules\XR\Subsystems\Environment\Raycast\XRRaycast.bindings.cs + +Modules\XR\Subsystems\Input\XRInputSubsystem.bindings.cs - -Modules\XR\Subsystems\Environment\ReferencePoints\XRReferencePoint.bindings.cs + +Modules\XR\Subsystems\Input\XRInputSubsystemDescriptor.bindings.cs - -Modules\XR\Subsystems\Environment\Session\XRSession.bindings.cs + +Modules\XR\Subsystems\Planes\XRPlaneSubsystem.bindings.cs - -Modules\XR\Subsystems\Example\XRExampleInstance.bindings.cs + +Modules\XR\Subsystems\Planes\XRPlaneSubsystemDescriptor.bindings.cs - -Modules\XR\Subsystems\Example\XRExampleSubsystemDescriptor.bindings.cs + +Modules\XR\Subsystems\Raycast\XRRaycastSubsystem.bindings.cs - -Modules\XR\Subsystems\Input\XRInputInstance.bindings.cs + +Modules\XR\Subsystems\Raycast\XRRaycastSubsystemDescriptor.bindings.cs - -Modules\XR\Subsystems\Input\XRInputSubsystemDescriptor.bindings.cs + +Modules\XR\Subsystems\ReferencePoints\XRReferencePointSubsystem.bindings.cs + + +Modules\XR\Subsystems\ReferencePoints\XRReferencePointSubsystemDescriptor.bindings.cs + + +Modules\XR\Subsystems\Session\XRSessionSubsystem.bindings.cs + + +Modules\XR\Subsystems\Session\XRSessionSubsystemDescriptor.bindings.cs diff --git a/README.md b/README.md index 7db2e9f2bb..bb33569334 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.1.0b10 C# reference source code +## Unity 2018.1.0b11 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/AR/ScriptBindings/ARBackgroundRenderer.cs b/Runtime/AR/ScriptBindings/ARBackgroundRenderer.cs index 049608d210..87ada89122 100644 --- a/Runtime/AR/ScriptBindings/ARBackgroundRenderer.cs +++ b/Runtime/AR/ScriptBindings/ARBackgroundRenderer.cs @@ -146,11 +146,19 @@ protected bool EnableARBackgroundRendering() // Command buffer setup m_CommandBuffer = new CommandBuffer(); - if (m_BackgroundTexture != null) - m_CommandBuffer.Blit(m_BackgroundTexture, BuiltinRenderTextureType.CameraTarget, m_BackgroundMaterial); - else - m_CommandBuffer.Blit(m_BackgroundMaterial.GetTexture("_MainTex"), BuiltinRenderTextureType.CameraTarget, m_BackgroundMaterial); + var backgroundTexture = m_BackgroundTexture; + if (backgroundTexture == null) + { + const string kMainTexName = "_MainTex"; + + // GetTexture will return null if the texture isn't found, but it also + // writes an error to the console. We check for existence to silence + // this error. + if (m_BackgroundMaterial.HasProperty(kMainTexName)) + backgroundTexture = m_BackgroundMaterial.GetTexture(kMainTexName); + } + m_CommandBuffer.Blit(backgroundTexture, BuiltinRenderTextureType.CameraTarget, m_BackgroundMaterial); camera.AddCommandBuffer(CameraEvent.BeforeForwardOpaque, m_CommandBuffer); camera.AddCommandBuffer(CameraEvent.BeforeGBuffer, m_CommandBuffer); diff --git a/Runtime/Animation/ScriptBindings/Animator.bindings.cs b/Runtime/Animation/ScriptBindings/Animator.bindings.cs index 5076843685..c1ac6932a3 100644 --- a/Runtime/Animation/ScriptBindings/Animator.bindings.cs +++ b/Runtime/Animation/ScriptBindings/Animator.bindings.cs @@ -225,15 +225,22 @@ public struct AnimatorTransitionInfo internal bool exit { get { return (m_TransitionType & (int)TransitionType.Exit) != 0; }} - - private int m_FullPath; - private int m_UserName; - private int m_Name; - private bool m_HasFixedDuration; + [NativeName("fullPathHash")] + private int m_FullPath; + [NativeName("userNameHash")] + private int m_UserName; + [NativeName("nameHash")] + private int m_Name; + [NativeName("hasFixedDuration")] + private bool m_HasFixedDuration; + [NativeName("duration")] private float m_Duration; + [NativeName("normalizedTime")] private float m_NormalizedTime; - private bool m_AnyState; - private int m_TransitionType; + [NativeName("anyState")] + private bool m_AnyState; + [NativeName("transitionType")] + private int m_TransitionType; } #pragma warning restore 649 diff --git a/Runtime/Export/Graphics.cs b/Runtime/Export/Graphics.cs index f644fd738d..9134776dc2 100644 --- a/Runtime/Export/Graphics.cs +++ b/Runtime/Export/Graphics.cs @@ -460,6 +460,10 @@ public static void Blit(Texture source, Material mat) public static void BlitMultiTap(Texture source, RenderTexture dest, Material mat, params Vector2[] offsets) { + // in case params were not passed, we will end up with empty array (not null) but our cpp code is not ready for that. + // do explicit argument exception instead of potential nullref coming from native side + if (offsets.Length == 0) + throw new ArgumentException("empty offsets list passed.", "offsets"); Internal_BlitMultiTap(source, dest, mat, offsets); } } diff --git a/Runtime/Export/GraphicsComponents.bindings.cs b/Runtime/Export/GraphicsComponents.bindings.cs index 9808ec64b2..8c76897d55 100644 --- a/Runtime/Export/GraphicsComponents.bindings.cs +++ b/Runtime/Export/GraphicsComponents.bindings.cs @@ -58,7 +58,9 @@ public struct LightBakingOutput { public int probeOcclusionLightIndex; public int occlusionMaskChannel; + [NativeName("lightmapBakeMode.lightmapBakeType")] public LightmapBakeType lightmapBakeType; + [NativeName("lightmapBakeMode.mixedLightingMode")] public MixedLightingMode mixedLightingMode; public bool isBaked; } diff --git a/Runtime/Export/NativeArray/NativeSlice.cs b/Runtime/Export/NativeArray/NativeSlice.cs index 377e43768d..eea1f282c1 100644 --- a/Runtime/Export/NativeArray/NativeSlice.cs +++ b/Runtime/Export/NativeArray/NativeSlice.cs @@ -19,9 +19,9 @@ public static NativeSlice Slice(this NativeArray thisArray) where T : s return new NativeSlice(thisArray); } - public static NativeSlice Slice(this NativeArray thisArray, int length) where T : struct + public static NativeSlice Slice(this NativeArray thisArray, int start) where T : struct { - return new NativeSlice(thisArray, length); + return new NativeSlice(thisArray, start); } public static NativeSlice Slice(this NativeArray thisArray, int start, int length) where T : struct @@ -34,9 +34,9 @@ public static NativeSlice Slice(this NativeSlice thisSlice) where T : s return thisSlice; } - public static NativeSlice Slice(this NativeSlice thisSlice, int length) where T : struct + public static NativeSlice Slice(this NativeSlice thisSlice, int start) where T : struct { - return new NativeSlice(thisSlice, length); + return new NativeSlice(thisSlice, start); } public static NativeSlice Slice(this NativeSlice thisSlice, int start, int length) where T : struct diff --git a/Runtime/VR/HoloLens/ScriptBindings/GestureSource.cs b/Runtime/VR/HoloLens/ScriptBindings/GestureSource.cs index 7bb05dffb7..abc13ce724 100644 --- a/Runtime/VR/HoloLens/ScriptBindings/GestureSource.cs +++ b/Runtime/VR/HoloLens/ScriptBindings/GestureSource.cs @@ -404,7 +404,7 @@ private enum EventType SourceReleased } - private delegate void InternalSourceEventHandler(EventType eventType, InteractionSourceState state, InteractionSourcePressType pressType); + private delegate void InternalSourceEventHandler(EventType eventType, ref InteractionSourceState state, InteractionSourcePressType pressType); private static InternalSourceEventHandler m_OnSourceEventHandler; static InteractionManager() @@ -415,7 +415,7 @@ static InteractionManager() #pragma warning disable 0618 [AOT.MonoPInvokeCallback(typeof(InternalSourceEventHandler))] - private static void OnSourceEvent(EventType eventType, InteractionSourceState state, InteractionSourcePressType pressType) + private static void OnSourceEvent(EventType eventType, ref InteractionSourceState state, InteractionSourcePressType pressType) { switch (eventType) { diff --git a/artifacts/generated/bindings_old/common/Core/RecorderBindings.gen.cs b/artifacts/generated/bindings_old/common/Core/RecorderBindings.gen.cs index 5ba47b74d8..1d6aa9e204 100644 --- a/artifacts/generated/bindings_old/common/Core/RecorderBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Core/RecorderBindings.gen.cs @@ -34,11 +34,18 @@ internal Recorder() {} public static Recorder Get(string samplerName) { - var sampler = Sampler.Get(samplerName); - return sampler.GetRecorder(); + var recorder = GetInternal(samplerName); + if (recorder == null) + return s_InvalidRecorder; + + return recorder; } + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static Recorder GetInternal (string samplerName) ; + public bool isValid { get { return m_Ptr != IntPtr.Zero; } diff --git a/artifacts/generated/bindings_old/common/Editor/PlayerSettingsAndroidBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/PlayerSettingsAndroidBindings.gen.cs index 3ef683f0dc..c3bac0a03c 100644 --- a/artifacts/generated/bindings_old/common/Editor/PlayerSettingsAndroidBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/PlayerSettingsAndroidBindings.gen.cs @@ -55,6 +55,10 @@ public enum AndroidSdkVersions AndroidApiLevel24 = 24, AndroidApiLevel25 = 25, + + AndroidApiLevel26 = 26, + + AndroidApiLevel27 = 27, } public enum AndroidPreferredInstallLocation From 83cceb769a97e24025616acc7503e9c21891f0f1 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Fri, 23 Mar 2018 08:03:45 +0000 Subject: [PATCH 11/17] Unity 2018.1.0b12 C# reference source code --- .../2D/SpriteEditorModule/SpriteEditorData.cs | 64 ++-- .../2D/SpriteEditorModule/TextureImporter.cs | 9 +- .../BuildPipeline/BuildPipelineInterfaces.cs | 173 +++++++---- .../DesktopStandalonePostProcessor.cs | 5 + Editor/Mono/GameView/GameView.cs | 51 ++- Editor/Mono/GameView/GameViewSize.cs | 35 ++- Editor/Mono/Inspector/Avatar/AvatarEditor.cs | 111 +++---- Editor/Mono/Inspector/InspectorWindow.cs | 5 +- .../Inspector/LightingSettingsInspector.cs | 16 +- Editor/Mono/PostprocessScene.cs | 2 +- .../ScriptCompilation/EditorCompilation.cs | 8 +- .../lib/mono/2.0/Boo.Lang.Compiler.dll | Bin 934912 -> 934912 bytes .../lib/mono/2.0/Boo.Lang.Parser.dll | Bin 414208 -> 414208 bytes .../lib/mono/2.0/Boo.Lang.dll | Bin 126976 -> 126976 bytes .../lib/mono/2.0/Mono.Posix.dll | Bin 184320 -> 184320 bytes .../lib/mono/2.0/Mono.Security.dll | Bin 294912 -> 294912 bytes .../lib/mono/2.0/System.Core.dll | Bin 297984 -> 297984 bytes .../lib/mono/2.0/System.Xml.Linq.dll | Bin 106496 -> 106496 bytes .../lib/mono/2.0/System.Xml.dll | Bin 1270272 -> 1270272 bytes .../monodistribution/lib/mono/2.0/System.dll | Bin 1679360 -> 1679360 bytes .../lib/mono/2.0/UnityScript.dll | Bin 177664 -> 177664 bytes .../PackageManager/Editor/Managed/Client.cs | 35 +-- .../Editor/Managed/PackageManager.bindings.cs | 7 +- .../ScriptBindings/Physics2D.bindings.cs | 72 ++++- Modules/PresetsEditor/PresetContextMenu.cs | 95 ++++-- .../ProfilerDetailedCallsView.cs | 7 +- .../ProfilerFrameDataTreeView.cs | 292 ++++++++++++------ .../ProfilerFrameHierarchyView.cs | 11 +- .../Editor/ProfilerWindow/ProfilerWindow.cs | 9 +- .../Public/ProfilerFrameDataView.bindings.cs | 5 +- .../BuildEventsHandler.cs | 2 +- README.md | 2 +- .../SupportedRenderingFeatures.cs | 110 +++++-- Runtime/Export/UnitySynchronizationContext.cs | 3 +- .../RenderingCommandBufferBindings.gen.cs | 11 + .../Editor/PlayerSettingsBindings.gen.cs | 10 + 36 files changed, 766 insertions(+), 384 deletions(-) diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs index c4260d6208..4daf77d4f1 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs @@ -14,7 +14,6 @@ namespace UnityEditor.U2D { internal class SpriteDataExt : SpriteRect { - public List spriteBone; public float tessellationDetail = 0; // The following lists are to be left un-initialized. @@ -24,9 +23,35 @@ internal class SpriteDataExt : SpriteRect public List indices; public List edges; public List spritePhysicsOutline; + public List spriteBone; - internal SpriteDataExt() + internal SpriteDataExt(SerializedObject so) { + var ti = so.targetObject as TextureImporter; + var texture = AssetDatabase.LoadAssetAtPath(ti.assetPath); + name = texture.name; + alignment = (SpriteAlignment)so.FindProperty("m_Alignment").intValue; + border = ti.spriteBorder; + pivot = SpriteEditorUtility.GetPivotValue(alignment, ti.spritePivot); + tessellationDetail = so.FindProperty("m_SpriteTessellationDetail").floatValue; + + int width = 0, height = 0; + ti.GetWidthAndHeight(ref width, ref height); + rect = new Rect(0, 0, width, height); + + var guidSP = so.FindProperty("m_SpriteSheet.m_SpriteID"); + spriteID = new GUID(guidSP.stringValue); + } + + internal SpriteDataExt(SerializedProperty sp) + { + rect = sp.FindPropertyRelative("m_Rect").rectValue; + border = sp.FindPropertyRelative("m_Border").vector4Value; + name = sp.FindPropertyRelative("m_Name").stringValue; + alignment = (SpriteAlignment)sp.FindPropertyRelative("m_Alignment").intValue; + pivot = SpriteEditorUtility.GetPivotValue(alignment, sp.FindPropertyRelative("m_Pivot").vector2Value); + tessellationDetail = sp.FindPropertyRelative("m_TessellationDetail").floatValue; + spriteID = new GUID(sp.FindPropertyRelative("m_SpriteID").stringValue); } internal SpriteDataExt(SpriteRect sr) @@ -39,6 +64,12 @@ internal SpriteDataExt(SpriteRect sr) spriteID = sr.spriteID; alignment = sr.alignment; pivot = sr.pivot; + spriteOutline = new List(); + vertices = new List(); + indices = new List(); + edges = new List(); + spritePhysicsOutline = new List(); + spriteBone = new List(); } public void Apply(SerializedObject so) @@ -80,35 +111,6 @@ public void Apply(SerializedProperty sp) SpriteMeshDataTransfer.Apply(sp, vertices, indices, edges); } - public void Load(SerializedObject so) - { - var ti = so.targetObject as TextureImporter; - var texture = AssetDatabase.LoadAssetAtPath(ti.assetPath); - name = texture.name; - alignment = (SpriteAlignment)so.FindProperty("m_Alignment").intValue; - border = ti.spriteBorder; - pivot = SpriteEditorUtility.GetPivotValue(alignment, ti.spritePivot); - tessellationDetail = so.FindProperty("m_SpriteTessellationDetail").floatValue; - - int width = 0, height = 0; - ti.GetWidthAndHeight(ref width, ref height); - rect = new Rect(0, 0, width, height); - - var guidSP = so.FindProperty("m_SpriteSheet.m_SpriteID"); - spriteID = new GUID(guidSP.stringValue); - } - - public void Load(SerializedProperty sp) - { - rect = sp.FindPropertyRelative("m_Rect").rectValue; - border = sp.FindPropertyRelative("m_Border").vector4Value; - name = sp.FindPropertyRelative("m_Name").stringValue; - alignment = (SpriteAlignment)sp.FindPropertyRelative("m_Alignment").intValue; - pivot = SpriteEditorUtility.GetPivotValue(alignment, sp.FindPropertyRelative("m_Pivot").vector2Value); - tessellationDetail = sp.FindPropertyRelative("m_TessellationDetail").floatValue; - spriteID = new GUID(sp.FindPropertyRelative("m_SpriteID").stringValue); - } - public void CopyFromSpriteRect(SpriteRect spriteRect) { alignment = spriteRect.alignment; diff --git a/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs b/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs index b12631bf6f..e3b976bbb4 100644 --- a/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs +++ b/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs @@ -40,7 +40,8 @@ void ISpriteEditorDataProvider.SetSpriteRects(SpriteRect[] spriteRects) { for (int i = m_SpritesMultiple.Count - 1; i >= 0; --i) { - if (!spriteRects.Contains(m_SpritesMultiple[i])) + var spriteID = m_SpritesMultiple[i].spriteID; + if (spriteRects.FirstOrDefault(x => x.spriteID == spriteID) == null) m_SpritesMultiple.RemoveAt(i); } for (int i = 0; i < spriteRects.Length; i++) @@ -113,14 +114,12 @@ void ISpriteEditorDataProvider.InitSpriteEditorDataProvider() var so = new SerializedObject(this); var spriteSheetSO = so.FindProperty("m_SpriteSheet.m_Sprites"); m_SpritesMultiple = new List(); - m_SpriteSingle = new SpriteDataExt(); - m_SpriteSingle.Load(so); + m_SpriteSingle = new SpriteDataExt(so); for (int i = 0; i < spriteSheetSO.arraySize; ++i) { - var data = new SpriteDataExt(); var sp = spriteSheetSO.GetArrayElementAtIndex(i); - data.Load(sp); + var data = new SpriteDataExt(sp); m_SpritesMultiple.Add(data); } } diff --git a/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs b/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs index 81669bf01f..abf284f606 100644 --- a/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs +++ b/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs @@ -16,17 +16,35 @@ public interface IOrderedCallback int callbackOrder { get; } } + [Obsolete("Use IPreprocessBuildWithReport instead")] public interface IPreprocessBuild : IOrderedCallback + { + void OnPreprocessBuild(BuildTarget target, string path); + } + + public interface IPreprocessBuildWithReport : IOrderedCallback { void OnPreprocessBuild(BuildReport report); } + [Obsolete("Use IPostprocessBuildWithReport instead")] public interface IPostprocessBuild : IOrderedCallback + { + void OnPostprocessBuild(BuildTarget target, string path); + } + + public interface IPostprocessBuildWithReport : IOrderedCallback { void OnPostprocessBuild(BuildReport report); } + [Obsolete("Use IProcessSceneWithReport instead")] public interface IProcessScene : IOrderedCallback + { + void OnProcessScene(UnityEngine.SceneManagement.Scene scene); + } + + public interface IProcessSceneWithReport : IOrderedCallback { void OnProcessScene(UnityEngine.SceneManagement.Scene scene, BuildReport report); } @@ -38,9 +56,16 @@ public interface IActiveBuildTargetChanged : IOrderedCallback internal static class BuildPipelineInterfaces { +#pragma warning disable 618 private static List buildPreprocessors; private static List buildPostprocessors; private static List sceneProcessors; +#pragma warning restore 618 + + private static List buildPreprocessorsWithReport; + private static List buildPostprocessorsWithReport; + private static List sceneProcessorsWithReport; + private static List buildTargetProcessors; [Flags] @@ -68,7 +93,17 @@ static void AddToList(object o, ref List list) where T : class list.Add(inst); } - private class AttributeCallbackWrapper : IPostprocessBuild, IProcessScene, IActiveBuildTargetChanged + static void AddToListIfTypeImplementsInterface(Type t, ref object o, ref List list) where T : class + { + if (!ValidateType(t)) + return; + + if (o == null) + o = Activator.CreateInstance(t); + AddToList(o, ref list); + } + + private class AttributeCallbackWrapper : IPostprocessBuildWithReport, IProcessSceneWithReport, IActiveBuildTargetChanged { int m_callbackOrder; MethodInfo m_method; @@ -115,45 +150,58 @@ internal static void InitializeBuildCallbacks(BuildCallbacks findFlags) { if (t.IsAbstract || t.IsInterface) continue; + + // Defer creating the instance until we actually add it to one of the lists object instance = null; + if (findBuildProcessors) { - if (ValidateType(t)) - AddToList(instance = Activator.CreateInstance(t), ref buildPreprocessors); - - if (ValidateType(t)) - AddToList(instance = instance == null ? Activator.CreateInstance(t) : instance, ref buildPostprocessors); + AddToListIfTypeImplementsInterface(t, ref instance, ref buildPreprocessors); + AddToListIfTypeImplementsInterface(t, ref instance, ref buildPreprocessorsWithReport); + AddToListIfTypeImplementsInterface(t, ref instance, ref buildPostprocessors); + AddToListIfTypeImplementsInterface(t, ref instance, ref buildPostprocessorsWithReport); } - if (findSceneProcessors && ValidateType(t)) - AddToList(instance = instance == null ? Activator.CreateInstance(t) : instance, ref sceneProcessors); + if (findSceneProcessors) + { + AddToListIfTypeImplementsInterface(t, ref instance, ref sceneProcessors); + AddToListIfTypeImplementsInterface(t, ref instance, ref sceneProcessorsWithReport); + } - if (findTargetProcessors && ValidateType(t)) - AddToList(instance = instance == null ? Activator.CreateInstance(t) : instance, ref buildTargetProcessors); + if (findTargetProcessors) + { + AddToListIfTypeImplementsInterface(t, ref instance, ref buildTargetProcessors); + } } if (findBuildProcessors) { foreach (var m in EditorAssemblies.GetAllMethodsWithAttribute()) if (ValidateMethod(m, postProcessBuildAttributeParams)) - AddToList(new AttributeCallbackWrapper(m), ref buildPostprocessors); + AddToList(new AttributeCallbackWrapper(m), ref buildPostprocessorsWithReport); } if (findSceneProcessors) { foreach (var m in EditorAssemblies.GetAllMethodsWithAttribute()) if (ValidateMethod(m, Type.EmptyTypes)) - AddToList(new AttributeCallbackWrapper(m), ref sceneProcessors); + AddToList(new AttributeCallbackWrapper(m), ref sceneProcessorsWithReport); } if (buildPreprocessors != null) buildPreprocessors.Sort(CompareICallbackOrder); + if (buildPreprocessorsWithReport != null) + buildPreprocessorsWithReport.Sort(CompareICallbackOrder); if (buildPostprocessors != null) buildPostprocessors.Sort(CompareICallbackOrder); + if (buildPostprocessorsWithReport != null) + buildPostprocessorsWithReport.Sort(CompareICallbackOrder); if (buildTargetProcessors != null) buildTargetProcessors.Sort(CompareICallbackOrder); if (sceneProcessors != null) sceneProcessors.Sort(CompareICallbackOrder); + if (sceneProcessorsWithReport != null) + sceneProcessorsWithReport.Sort(CompareICallbackOrder); } internal static bool ValidateType(Type t) @@ -217,67 +265,81 @@ static bool ValidateMethod(MethodInfo method, Type[] expectedArguments) return false; } - [RequiredByNativeCode] - internal static void OnBuildPreProcess(BuildReport report) + private static bool InvokeCallbackInterfacesPair(List oneInterfaces, Action invocationOne, List twoInterfaces, Action invocationTwo, bool exitOnFailure) where T1 : IOrderedCallback where T2 : IOrderedCallback { - if (buildPreprocessors != null) + if (oneInterfaces == null && twoInterfaces == null) + return true; + + // 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. + // So, we have to walk both lists simultaneously, calling whichever callback has the lower ordering value + IEnumerator e1 = (oneInterfaces != null) ? (IEnumerator)oneInterfaces.GetEnumerator() : null; + IEnumerator e2 = (twoInterfaces != null) ? (IEnumerator)twoInterfaces.GetEnumerator() : null; + if (e1 != null && !e1.MoveNext()) + e1 = null; + if (e2 != null && !e2.MoveNext()) + e2 = null; + + while (e1 != null || e2 != null) { - foreach (IPreprocessBuild bpp in buildPreprocessors) + try { - try + if (e1 != null && (e2 == null || e1.Current.callbackOrder < e2.Current.callbackOrder)) { - bpp.OnPreprocessBuild(report); + var callback = e1.Current; + if (!e1.MoveNext()) + e1 = null; + invocationOne(callback); } - catch (Exception e) + else if (e2 != null) { - Debug.LogException(e); - if ((report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0) - return; + var callback = e2.Current; + if (!e2.MoveNext()) + e2 = null; + invocationTwo(callback); } } + catch (Exception e) + { + Debug.LogException(e); + if (exitOnFailure) + return false; + } } + + return true; + } + + [RequiredByNativeCode] + internal static void OnBuildPreProcess(BuildReport report) + { +#pragma warning disable 618 + InvokeCallbackInterfacesPair( + buildPreprocessors, bpp => bpp.OnPreprocessBuild(report.summary.platform, report.summary.outputPath), + buildPreprocessorsWithReport, bpp => bpp.OnPreprocessBuild(report), + (report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0); +#pragma warning restore 618 } [RequiredByNativeCode] internal static void OnSceneProcess(UnityEngine.SceneManagement.Scene scene, BuildReport report) { - if (sceneProcessors != null) - { - foreach (IProcessScene spp in sceneProcessors) - { - try - { - spp.OnProcessScene(scene, report); - } - catch (Exception e) - { - Debug.LogException(e); - if ((report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0) - return; - } - } - } +#pragma warning disable 618 + InvokeCallbackInterfacesPair( + sceneProcessors, spp => spp.OnProcessScene(scene), + sceneProcessorsWithReport, spp => spp.OnProcessScene(scene, report), + report && ((report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0)); +#pragma warning restore 618 } [RequiredByNativeCode] internal static void OnBuildPostProcess(BuildReport report) { - if (buildPostprocessors != null) - { - foreach (IPostprocessBuild bpp in buildPostprocessors) - { - try - { - bpp.OnPostprocessBuild(report); - } - catch (Exception e) - { - Debug.LogException(e); - if ((report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0) - return; - } - } - } +#pragma warning disable 618 + InvokeCallbackInterfacesPair( + buildPostprocessors, bpp => bpp.OnPostprocessBuild(report.summary.platform, report.summary.outputPath), + buildPostprocessorsWithReport, bpp => bpp.OnPostprocessBuild(report), + (report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0); +#pragma warning restore 618 } [RequiredByNativeCode] @@ -306,6 +368,9 @@ internal static void CleanupBuildCallbacks() buildPreprocessors = null; buildPostprocessors = null; sceneProcessors = null; + buildPreprocessorsWithReport = null; + buildPostprocessorsWithReport = null; + sceneProcessorsWithReport = null; previousFlags = BuildCallbacks.None; } } diff --git a/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs b/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs index eb7096a671..d6094f56d6 100644 --- a/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs +++ b/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs @@ -23,6 +23,7 @@ public override void PostProcess(BuildPostProcessArgs args) { SetupStagingArea(args); CopyStagingAreaIntoDestination(args); + ProcessSymbolFiles(args); } public override bool SupportsLz4Compression() @@ -439,6 +440,10 @@ protected virtual void ProcessPlatformSpecificIL2CPPOutput(BuildPostProcessArgs { } + protected virtual void ProcessSymbolFiles(BuildPostProcessArgs args) + { + } + protected string GetIl2CppDataBackupFolderName(BuildPostProcessArgs args) { return Path.GetFileNameWithoutExtension(args.installPath) + "_BackUpThisFolder_ButDontShipItWithYourGame"; diff --git a/Editor/Mono/GameView/GameView.cs b/Editor/Mono/GameView/GameView.cs index 901825e588..4e6842e7c2 100644 --- a/Editor/Mono/GameView/GameView.cs +++ b/Editor/Mono/GameView/GameView.cs @@ -178,15 +178,23 @@ internal Vector2 targetSize // Size of render target in pixels } // Area of the render target in zoom content space (it is centered in content space) - Rect targetInContent { get { return EditorGUIUtility.PixelsToPoints(new Rect(-0.5f * targetSize, targetSize)); } } + Rect targetInContent + { + get + { + var targetSizeCached = targetSize; + return EditorGUIUtility.PixelsToPoints(new Rect(-0.5f * targetSizeCached, targetSizeCached)); + } + } Rect targetInView // Area of the render target in zoom view space { get { + var targetInContentCached = targetInContent; return new Rect( - m_ZoomArea.DrawingToViewTransformPoint(targetInContent.position), - m_ZoomArea.DrawingToViewTransformVector(targetInContent.size) + m_ZoomArea.DrawingToViewTransformPoint(targetInContentCached.position), + m_ZoomArea.DrawingToViewTransformVector(targetInContentCached.size) ); } } @@ -225,18 +233,24 @@ Rect viewInParent // The view area in parent view space Rect targetInParent // Area of the render target in parent view space { - get { return new Rect(targetInView.position + viewInParent.position, targetInView.size); } + get + { + var targetInViewCached = targetInView; + return new Rect(targetInViewCached.position + viewInParent.position, targetInViewCached.size); + } } Rect clippedTargetInParent // targetInParent, but clipped to viewInParent to discard outside mouse events { get { + var targetInParentCached = targetInParent; + var viewInParentCached = viewInParent; var clippedTargetInParent = Rect.MinMaxRect( - Mathf.Max(targetInParent.xMin, viewInParent.xMin), - Mathf.Max(targetInParent.yMin, viewInParent.yMin), - Mathf.Min(targetInParent.xMax, viewInParent.xMax), - Mathf.Min(targetInParent.yMax, viewInParent.yMax) + Mathf.Max(targetInParentCached.xMin, viewInParentCached.xMin), + Mathf.Max(targetInParentCached.yMin, viewInParentCached.yMin), + Mathf.Min(targetInParentCached.xMax, viewInParentCached.xMax), + Mathf.Min(targetInParentCached.yMax, viewInParentCached.yMax) ); return clippedTargetInParent; } @@ -639,10 +653,11 @@ private void ConfigureZoomArea() { m_ZoomArea.rect = viewInWindow; // Sliders are sized with respect to canvas - m_ZoomArea.hBaseRangeMin = targetInContent.xMin; - m_ZoomArea.vBaseRangeMin = targetInContent.yMin; - m_ZoomArea.hBaseRangeMax = targetInContent.xMax; - m_ZoomArea.vBaseRangeMax = targetInContent.yMax; + var targetInContentCached = targetInContent; + m_ZoomArea.hBaseRangeMin = targetInContentCached.xMin; + m_ZoomArea.vBaseRangeMin = targetInContentCached.yMin; + m_ZoomArea.hBaseRangeMax = targetInContentCached.xMax; + m_ZoomArea.vBaseRangeMax = targetInContentCached.yMax; // Restrict zooming m_ZoomArea.hScaleMin = m_ZoomArea.vScaleMin = minScale; m_ZoomArea.hScaleMax = m_ZoomArea.vScaleMax = maxScale; @@ -651,16 +666,17 @@ private void ConfigureZoomArea() private void EnforceZoomAreaConstraints() { var shownArea = m_ZoomArea.shownArea; + var targetInContentCached = targetInContent; // When zoomed out, we disallow panning by automatically centering the view - if (shownArea.width > targetInContent.width) + if (shownArea.width > targetInContentCached.width) { shownArea.x = -0.5f * shownArea.width; } else // When zoomed in, we prevent panning outside the render area { - shownArea.x = Mathf.Clamp(shownArea.x, targetInContent.xMin, targetInContent.xMax - shownArea.width); + shownArea.x = Mathf.Clamp(shownArea.x, targetInContentCached.xMin, targetInContentCached.xMax - shownArea.width); } // Horizontal and vertical are separated because otherwise we get weird behaviour when only one is zoomed out if (shownArea.height > targetInContent.height) @@ -669,7 +685,7 @@ private void EnforceZoomAreaConstraints() } else { - shownArea.y = Mathf.Clamp(shownArea.y, targetInContent.yMin, targetInContent.yMax - shownArea.height); + shownArea.y = Mathf.Clamp(shownArea.y, targetInContentCached.yMin, targetInContentCached.yMax - shownArea.height); } m_ZoomArea.shownArea = shownArea; @@ -707,8 +723,9 @@ private void OnGUI() // We hide sliders when playing, and also when we are zoomed out beyond canvas edges var playing = EditorApplication.isPlaying && !EditorApplication.isPaused; - m_ZoomArea.hSlider = !playing && m_ZoomArea.shownArea.width < targetInContent.width; - m_ZoomArea.vSlider = !playing && m_ZoomArea.shownArea.height < targetInContent.height; + var targetInContentCached = targetInContent; + m_ZoomArea.hSlider = !playing && m_ZoomArea.shownArea.width < targetInContentCached.width; + m_ZoomArea.vSlider = !playing && m_ZoomArea.shownArea.height < targetInContentCached.height; m_ZoomArea.enableMouseInput = !playing; ConfigureZoomArea(); diff --git a/Editor/Mono/GameView/GameViewSize.cs b/Editor/Mono/GameView/GameViewSize.cs index f8a8746496..ce5c9e3855 100644 --- a/Editor/Mono/GameView/GameViewSize.cs +++ b/Editor/Mono/GameView/GameViewSize.cs @@ -31,10 +31,12 @@ public string baseText get {return m_BaseText; } set { + var oldBaseText = m_BaseText; m_BaseText = value; if (m_BaseText.Length > kMaxBaseTextLength) m_BaseText = m_BaseText.Substring(0, kMaxBaseTextLength); - Changed(); + if (m_BaseText != oldBaseText) + Changed(); } } public GameViewSizeType sizeType @@ -42,25 +44,40 @@ public GameViewSizeType sizeType get { return m_SizeType; } set { - m_SizeType = value; Clamp(); Changed(); + var oldSizeType = m_SizeType; + m_SizeType = value; + Clamp(); + if (m_SizeType != oldSizeType) + Changed(); } } public int width { get { return m_Width; } - set { m_Width = value; Clamp(); Changed(); } + set + { + var oldWidth = m_Width; + m_Width = value; + Clamp(); + if (m_Width != oldWidth) + Changed(); + } } public int height { get { return m_Height; } - set { m_Height = value; Clamp(); Changed(); } + set + { + var oldHeight = m_Height; + m_Height = value; + Clamp(); + if (m_Height != oldHeight) + Changed(); + } } void Clamp() { - int orgWidth = m_Width; - int orgHeight = m_Height; - int minValue = 0; switch (sizeType) { @@ -77,9 +94,6 @@ void Clamp() m_Width = Mathf.Clamp(m_Width, minValue, kMaxResolutionOrAspect); m_Height = Mathf.Clamp(m_Height, minValue, kMaxResolutionOrAspect); - - if (m_Width != orgWidth || m_Height != orgHeight) - Changed(); } public GameViewSize(GameViewSizeType type, int width, int height, string baseText) @@ -101,7 +115,6 @@ public void Set(GameViewSize other) width = other.width; height = other.height; baseText = other.baseText; - Changed(); } public bool isFreeAspectRatio diff --git a/Editor/Mono/Inspector/Avatar/AvatarEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarEditor.cs index 72a9ff4ac9..ec823adc5f 100644 --- a/Editor/Mono/Inspector/Avatar/AvatarEditor.cs +++ b/Editor/Mono/Inspector/Avatar/AvatarEditor.cs @@ -125,31 +125,29 @@ protected void ApplyRevertGUI() { EditorGUILayout.Space(); - GUILayout.BeginHorizontal(); - - using (new EditorGUI.DisabledScope(!HasModified())) + using (new GUILayout.HorizontalScope()) { - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Revert")) + using (new EditorGUI.DisabledScope(!HasModified())) { - ResetValues(); - if (HasModified()) - Debug.LogError("Avatar tool reports modified values after reset."); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Revert")) + { + ResetValues(); + System.Diagnostics.Debug.Assert(!HasModified(), "Avatar settings are marked as modified after calling Reset."); + } + + if (GUILayout.Button("Apply")) + { + ApplyAndImport(); + } } - if (GUILayout.Button("Apply")) + if (GUILayout.Button("Done")) { - ApplyAndImport(); + m_Inspector.SwitchToAssetMode(); + GUIUtility.ExitGUI(); } } - - if (GUILayout.Button("Done")) - { - m_Inspector.SwitchToAssetMode(); - GUIUtility.ExitGUI(); - } - - GUILayout.EndHorizontal(); } } @@ -393,25 +391,24 @@ public override void OnInspectorGUI() { GUI.enabled = true; - EditorGUILayout.BeginVertical(EditorStyles.inspectorFullWidthMargins); - - if (m_EditMode == EditMode.Editing) + using (new EditorGUILayout.VerticalScope(EditorStyles.inspectorFullWidthMargins)) { - EditingGUI(); - } - else if (!m_CameFromImportSettings) - { - EditButtonGUI(); - } - else - { - if (m_EditMode == EditMode.NotEditing && Event.current.type == EventType.Repaint) + if (m_EditMode == EditMode.Editing) + { + EditingGUI(); + } + else if (!m_CameFromImportSettings) { - m_SwitchToEditMode = true; + EditButtonGUI(); + } + else + { + if (m_EditMode == EditMode.NotEditing && Event.current.type == EventType.Repaint) + { + m_SwitchToEditMode = true; + } } } - - EditorGUILayout.EndVertical(); } void EditButtonGUI() @@ -425,39 +422,43 @@ void EditButtonGUI() if (modelImporter == null) return; - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button(styles.editCharacter, GUILayout.Width(120)) && - EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) + using (new EditorGUILayout.HorizontalScope()) { - SwitchToEditMode(); - GUIUtility.ExitGUI(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button(styles.editCharacter, GUILayout.Width(120)) && + EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) + { + SwitchToEditMode(); + GUIUtility.ExitGUI(); + } + + GUILayout.FlexibleSpace(); } - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); } void EditingGUI() { - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); + using (new EditorGUILayout.HorizontalScope()) { - int tabIndex = m_TabIndex; - bool wasEnable = GUI.enabled; - GUI.enabled = !(avatar == null || !avatar.isHuman); - tabIndex = GUILayout.Toolbar(tabIndex, styles.tabs, "LargeButton", GUI.ToolbarButtonSize.FitToContents); - GUI.enabled = wasEnable; - if (tabIndex != m_TabIndex) + GUILayout.FlexibleSpace(); { - DestroyEditor(); - if (avatar != null && avatar.isHuman) - m_TabIndex = tabIndex; + int tabIndex = m_TabIndex; + bool wasEnable = GUI.enabled; + GUI.enabled = !(avatar == null || !avatar.isHuman); + tabIndex = GUILayout.Toolbar(tabIndex, styles.tabs, "LargeButton", + GUI.ToolbarButtonSize.FitToContents); + GUI.enabled = wasEnable; + if (tabIndex != m_TabIndex) + { + DestroyEditor(); + if (avatar != null && avatar.isHuman) + m_TabIndex = tabIndex; - CreateEditor(); + CreateEditor(); + } } + GUILayout.FlexibleSpace(); } - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); editor.OnInspectorGUI(); } diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index 4492b2f9f5..fd2e8ed44a 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -20,7 +20,7 @@ namespace UnityEditor { [EditorWindowTitle(title = "Inspector", useTypeNameAsIconName = true)] - public class InspectorWindow : EditorWindow, IHasCustomMenu, ISerializationCallbackReceiver + internal class InspectorWindow : EditorWindow, IHasCustomMenu, ISerializationCallbackReceiver { internal Vector2 m_ScrollPosition; internal InspectorMode m_InspectorMode = InspectorMode.Normal; @@ -70,7 +70,6 @@ public class InspectorWindow : EditorWindow, IHasCustomMenu, ISerializationCallb private IPreviewable m_SelectedPreview; private EditorDragging editorDragging; - static public Action OnPostHeaderGUI = null; internal class Styles { @@ -1220,8 +1219,6 @@ private void DrawEditor(Editor[] editors, int editorIndex, bool rebuildOptimized } DisplayDeprecationMessageIfNecessary(editor); - if (OnPostHeaderGUI != null) - OnPostHeaderGUI(editor); // We need to reset again after drawing the header. EditorGUIUtility.ResetGUIState(); diff --git a/Editor/Mono/Inspector/LightingSettingsInspector.cs b/Editor/Mono/Inspector/LightingSettingsInspector.cs index b78f1dae1b..72430f50c8 100644 --- a/Editor/Mono/Inspector/LightingSettingsInspector.cs +++ b/Editor/Mono/Inspector/LightingSettingsInspector.cs @@ -155,7 +155,7 @@ public bool Begin() if (s_Styles == null) s_Styles = new Styles(); - m_ShowSettings = EditorGUILayout.Foldout(m_ShowSettings, s_Styles.Lighting); + m_ShowSettings = EditorGUILayout.Foldout(m_ShowSettings, s_Styles.Lighting, true); if (!m_ShowSettings) return false; @@ -216,12 +216,12 @@ public void RenderMeshSettings(bool showLightmapSettings) if (showEnlightenSettings) { - m_ShowChartingSettings = EditorGUILayout.Foldout(m_ShowChartingSettings, s_Styles.UVCharting); + m_ShowChartingSettings = EditorGUILayout.Foldout(m_ShowChartingSettings, s_Styles.UVCharting, true); if (m_ShowChartingSettings) RendererUVSettings(); } - m_ShowLightmapSettings = EditorGUILayout.Foldout(m_ShowLightmapSettings, s_Styles.LightmapSettings); + m_ShowLightmapSettings = EditorGUILayout.Foldout(m_ShowLightmapSettings, s_Styles.LightmapSettings, true); if (m_ShowLightmapSettings) { @@ -250,11 +250,11 @@ public void RenderMeshSettings(bool showLightmapSettings) LightmapParametersGUI(m_LightmapParameters, s_Styles.LightmapParameters); - m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, s_Styles.Atlas); + m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, s_Styles.Atlas, true); if (m_ShowBakedLM) ShowAtlasGUI(m_Renderers[0].GetInstanceID()); - m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, s_Styles.RealtimeLM); + m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, s_Styles.RealtimeLM, true); if (m_ShowRealtimeLM) ShowRealtimeLMGUI(m_Renderers[0]); @@ -302,7 +302,7 @@ public void RenderTerrainSettings() if (enableSettings) { - m_ShowLightmapSettings = EditorGUILayout.Foldout(m_ShowLightmapSettings, s_Styles.LightmapSettings); + m_ShowLightmapSettings = EditorGUILayout.Foldout(m_ShowLightmapSettings, s_Styles.LightmapSettings, true); if (m_ShowLightmapSettings) { @@ -325,11 +325,11 @@ public void RenderTerrainSettings() if (GUI.enabled && m_Terrains.Length == 1 && m_Terrains[0].terrainData != null) ShowBakePerformanceWarning(m_Terrains[0]); - m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, s_Styles.Atlas); + m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, s_Styles.Atlas, true); if (m_ShowBakedLM) ShowAtlasGUI(m_Terrains[0].GetInstanceID()); - m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, s_Styles.RealtimeLM); + m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, s_Styles.RealtimeLM, true); if (m_ShowRealtimeLM) ShowRealtimeLMGUI(m_Terrains[0]); diff --git a/Editor/Mono/PostprocessScene.cs b/Editor/Mono/PostprocessScene.cs index 9cb8f6e74f..71891c4fc0 100644 --- a/Editor/Mono/PostprocessScene.cs +++ b/Editor/Mono/PostprocessScene.cs @@ -7,7 +7,7 @@ namespace UnityEditor { - internal class UnityBuildPostprocessor : IProcessScene + internal class UnityBuildPostprocessor : IProcessSceneWithReport { public int callbackOrder { get { return 0; } } public void OnProcessScene(UnityEngine.SceneManagement.Scene scene, Build.Reporting.BuildReport report) diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index 3b2417ca9e..b9a72cbf1b 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -486,14 +486,14 @@ private static CustomScriptAssembly CreatePackageCustomScriptAssembly(PackageAss // Delete all .dll's that aren't used anymore public void DeleteUnusedAssemblies() { - string fullEditorAssemblyPath = AssetPath.Combine(AssetPath.GetDirectoryName(UnityEngine.Application.dataPath), GetCompileScriptsOutputDirectory()); + string fullEditorAssemblyPath = AssetPath.Combine(projectDirectory, GetCompileScriptsOutputDirectory()); if (!Directory.Exists(fullEditorAssemblyPath)) return; var deleteFiles = Directory.GetFiles(fullEditorAssemblyPath).Select(f => AssetPath.ReplaceSeparators(f)).ToList(); string timestampPath = GetAssemblyTimestampPath(GetCompileScriptsOutputDirectory()); - deleteFiles.Remove(AssetPath.Combine(AssetPath.GetDirectoryName(UnityEngine.Application.dataPath), timestampPath)); + deleteFiles.Remove(AssetPath.Combine(projectDirectory, timestampPath)); var scriptAssemblies = GetAllScriptAssemblies(EditorScriptCompilationOptions.BuildingForEditor); @@ -514,7 +514,7 @@ public void DeleteUnusedAssemblies() public void CleanScriptAssemblies() { - string fullEditorAssemblyPath = AssetPath.Combine(AssetPath.GetDirectoryName(UnityEngine.Application.dataPath), GetCompileScriptsOutputDirectory()); + string fullEditorAssemblyPath = AssetPath.Combine(projectDirectory, GetCompileScriptsOutputDirectory()); if (!Directory.Exists(fullEditorAssemblyPath)) return; @@ -661,6 +661,8 @@ private static EditorBuildRules.TargetAssembly[] GetCustomAssembliesNotContainin internal bool CompileScripts(ScriptAssemblySettings scriptAssemblySettings, string tempBuildDirectory, EditorScriptCompilationOptions options, ref EditorBuildRules.TargetAssembly[] notCompiledTargetAssemblies) { + DeleteUnusedAssemblies(); + IEnumerable allDirtyScripts = areAllScriptsDirty ? allScripts.ToArray() : dirtyScripts.ToArray(); areAllScriptsDirty = false; diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Compiler.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Compiler.dll index 4d4aa1dc7b7e50da64b241da0489943200fd74a8..a7752ccdc678887d2230b671a529cd69505ec432 100644 GIT binary patch delta 216 zcmV;}04M)|h&h0WIgp40A1I`Oi-n5;g^L1(ivxv=1ci$Qg^LD-iwA{^2!)FYg^LP> ziwlK|426pgwTljoIe(P#Go3G#twoy=i17#zOAWWW7M=64WAXowjA=RL%49tiHXE?= zffnuCr$j(nTDVG84lVd-7K1EooM5SyRXg2^-Pn9U^-cpa&{`ak6MaiU2Ud2U|;X+;X SXQ3{)K|l^>0k;l34)O ziwlK|426pgwTljoIe(Dn+f;3b+d_tc&yuUxxB0k;l34)O;%4QOHj diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Parser.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Parser.dll index 14a069e14eea1b687600f180e2dfeb7182fe83c8..3717a39e5a3c8933411f08f5118ea34c84680036 100644 GIT binary patch delta 192 zcmV;x06+hLq#1yu8IXtrA}FMRi-n5;g^L1(ivxv=1ci$QwTlLQNq_hZ&YojLc0`~z zc(ix0WOZSZ(OKqlB6uo_w*2PkH7!MVA{okr~RNa(RGOs zdW+*5mR@>Mfhn>%M1?#^Z)!x!E){_eo6v=#gqjM~MAgSVS1h&P`&mIt6JD{)Y|w>r uUs-JaFc94E7DL?EO%Yl%O&DJ;^SyNSCr|EOS*FFe5l{wp0k;lJ2J!{XXjw-9 diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.dll index 68b72a1af24ae7ff58cd6a5bb96eafc3b4b376bd..b66b75a25ff6ddc9011fc25858023de075808b70 100644 GIT binary patch delta 177 zcmV;i08ama;0J)<2at#Z8z`iKi?xdZ1?7J^put@3Pkcv|dXw;u`})B5ypDPQ;TLqL zufC9S@)NB!=38OLxT_Dqd^yVMP@!q2_Ib8HYxKjcGWdpJ1cVvKLC#0qo8aI}{96gN zO=H!}kjEX1Qoxi)&$%Wy+isAOzv}?3RRFIvzUK(h;nCmf#d+uzY^ZCR{%*qqjr$Q} fTflXs9%=wo*}PEXmHH)Aw-N3E?g6(B=mGKvMD$+L delta 177 zcmV;i08ama;0J)<2at#Z5{7eui?xdZ1?7Kr?$8~|eCa@<{J$t+c(-@;+o3FBoF+W_ z=hCi!VCkl_qIFar`?st8!G@)96E?iI$L&0VujU0SpJsE%!owHrUUsIOw)PNhJDa`J z#Qh7$Nz5_|t-F$L%6j7e%M7U%rRot_gf|#MNQ;I_bPgA%10un?J6_j*Mcvt@cZ{8R3P|>RxL>)l3Ma|cK|O@Bv>FP#h@^DBSsDhjfI?I hei4DvV6nK@y<#a43<6-{uw=29QOyE+w+_kz@&zm(Q5OIJ delta 179 zcmV;k08IaYpbLPY3y_EdZi91yi-n5;wTl9I$bVw`Pav3rQ%<+&YMa40CAln1bS}AD z;^}VB!ki_|(iaA7BZcnI;x)=;0`36tu1+8_z2I@Laoh1}03jfadi;{mlrl;8Bp~CZ zY{d~9UHWJ@$qyyL3sKwEsuM8?8?UP8D~=hv?;5XkwV*da)t^u^BEPaO<>g?jTX$dZ hcoFvq=;$)PW1<(h>5(`t+Jg+2QOyE+w+_kz@&z`8R!aZ? diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Mono.Security.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Mono.Security.dll index 9113698278e2fe530668fec751a995f7949b3134..0f9cd4604ac15ed7b6c903b5b3342c0f7213fe44 100644 GIT binary patch delta 185 zcmV;q07n0SfD(X!5|D@kkR_yni-n5;g^L1(ivzWb1U-0vxrE6`Lt!^Vk&oxLt177u zWC8wm^vFcT?SRyEUi}N0J!g{VpKTU2)|dgUm%jnFB8~z3s)iYM>YoeS3aA~vE>NjQ(x{n n*=1@?>j~wi=X9)w3iWn1h%&hdIa(XP9s*V delta 185 zcmV;q07n0SfD(X!5|D@kbAxk%i-n5;g^L1(ivzWb1U-0vdU{B3Aac4&oXu%6N!to% zb?e}`+!3TMUqxH<0}GIElR^XO^hpuSimC${@ZUV9?d!Sw7S-|l=p%#)O8ic21z^MG zYTR)7UiQf=7ZbnBvU6@!T-JwfkDhe#DO(+zLCzQ2CAucHyDq&Nf0dzTS@1h%&hdIa(X^{HAL diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/System.Core.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/System.Core.dll index 46abef9c967771f9f8d02ca86343507061a5b524..a56e1d1e949c4b4c6d15296bbac2725ea7d4a730 100644 GIT binary patch delta 11148 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 WEmpSmR+IkEv}3HM3(9;y4*7p4i8lQJ delta 11151 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 diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/System.Xml.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/System.Xml.dll index 71ace215f33ede95d914c47c6c4338a17d21feaa..ba5a20c10ebcaad13008353e87e8029029b060a8 100644 GIT binary patch delta 230 zcmV ziwlK|426pgg^Lb_iw}j15QU2og^LokixU}If1WJH+AP=xM7v|w*_=m;^1xFBx$Pfv zB`4i@rp05Lf%dqB@AtDex}W7>+0JgH>)tYa&K( g5%$s&FM?c~EDC5hq%gwP7B!a ziwlK|426pgg^Lb_iw}j15QU2og^LokixU}IfB9(IwE4XIPPw{M#3S@S6h_p>=xfiA za}{lUtjgHvLR*G067kY~eMUoK<<-&n`Me)fOvF`?szh}*t g5s)Sh%d3BSa32f#3#b_X*?gA~U=!N64qOxR1um~_&Hw-a diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/System.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/System.dll index 6f4127197acc921821a9ceedd1fd113e930e915a..78f786694971158b62e4a1fafbbc9c3a0d06b377 100644 GIT binary patch delta 70417 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 delta 245 zcmZp8!`1MHYeEOJMq6=X_ttJkEo){@L6+@1tQns&vKuflurO8YZ(m}|_{ffliF0~K z4dWcfg6XQYjA4xV+iPkWr^#~&Gcq&yMV*n`E;X02fRQ&dKSYh0p)B7YNH%PrK9AAR z0w~77zz7s$U|<4@UA@Mr+{kUBVq|X4prT@AY`UE}f{9mDy(A;ESjE`b0w|c1pPZNj z;#e}MK!wdi_@% diff --git a/Modules/PackageManager/Editor/Managed/Client.cs b/Modules/PackageManager/Editor/Managed/Client.cs index 7651b4f5ee..ba7bc1ef4a 100644 --- a/Modules/PackageManager/Editor/Managed/Client.cs +++ b/Modules/PackageManager/Editor/Managed/Client.cs @@ -7,27 +7,15 @@ namespace UnityEditor.PackageManager { - /// - /// Entry point for all Unity Package Manager operations - /// public static class Client { - /// - /// Lists the packages the project depends on. - /// - /// A ListRequest instance - public static ListRequest List() + public static ListRequest List(bool offlineMode = false) { long operationId; - var status = NativeClient.List(out operationId); + var status = NativeClient.List(out operationId, offlineMode); return new ListRequest(operationId, status); } - /// - /// Adds a package dependency to the project. - /// - /// Id or name of the package to add - /// An AddRequest instance public static AddRequest Add(string packageIdOrName) { long operationId; @@ -35,11 +23,6 @@ public static AddRequest Add(string packageIdOrName) return new AddRequest(operationId, status); } - /// - /// Removes a previously added package from the project. - /// - /// Id or name of the package to remove - /// A RemoveRequest instance public static RemoveRequest Remove(string packageIdOrName) { long operationId; @@ -47,11 +30,6 @@ public static RemoveRequest Remove(string packageIdOrName) return new RemoveRequest(operationId, status, packageIdOrName); } - /// - /// Searches the registry for the given package. - /// - /// Id or name of the package to search for - /// A SearchRequest instance public static SearchRequest Search(string packageIdOrName) { long operationId; @@ -59,10 +37,6 @@ public static SearchRequest Search(string packageIdOrName) return new SearchRequest(operationId, status, packageIdOrName); } - /// - /// Searches the registry for all available packages. - /// - /// A SearchRequest instance public static SearchRequest SearchAll() { long operationId; @@ -70,11 +44,6 @@ public static SearchRequest SearchAll() return new SearchRequest(operationId, status, string.Empty); } - /// - /// Resets the list of packages installed for this project to the editor's default configuration. - /// This operation will clear all packages added to the project and keep only the packages set for the current editor default configuration. - /// - /// A ResetToEditorDefaultsRequest instance public static ResetToEditorDefaultsRequest ResetToEditorDefaults() { long operationId; diff --git a/Modules/PackageManager/Editor/Managed/PackageManager.bindings.cs b/Modules/PackageManager/Editor/Managed/PackageManager.bindings.cs index 57c8f5a773..a75bce0128 100644 --- a/Modules/PackageManager/Editor/Managed/PackageManager.bindings.cs +++ b/Modules/PackageManager/Editor/Managed/PackageManager.bindings.cs @@ -14,8 +14,13 @@ namespace UnityEditor.PackageManager [NativeHeader("Modules/PackageManager/Editor/Public/PackageManagerApi.h")] partial class NativeClient { + public static NativeStatusCode List(out long operationId) + { + return List(out operationId, false); + } + [StaticAccessor("PackageManager::Api::GetInstance()", StaticAccessorType.Arrow)] - extern public static NativeStatusCode List([Out] out long operationId); + extern public static NativeStatusCode List([Out] out long operationId, bool offlineMode); [StaticAccessor("PackageManager::Api::GetInstance()", StaticAccessorType.Arrow)] extern public static NativeStatusCode Add([Out] out long operationId, string packageId); diff --git a/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs b/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs index b2dc3274a0..48c1385725 100644 --- a/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs +++ b/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs @@ -1939,9 +1939,11 @@ public partial class Collision2D internal int m_OtherCollider; internal int m_Rigidbody; internal int m_OtherRigidbody; - internal ContactPoint2D[] m_Contacts; internal Vector2 m_RelativeVelocity; internal int m_Enabled; + internal int m_ContactCount; + internal IntPtr m_Contacts; + internal ContactPoint2D[] m_LegacyContactArray; // The first collider involved in the collision. public Collider2D collider { get { return Object.FindObjectFromInstanceID(m_Collider) as Collider2D; } } @@ -1961,33 +1963,73 @@ public partial class Collision2D // The game object of the rigid-body or if no rigid-body is available, the collider transform. public GameObject gameObject { get { return rigidbody != null ? rigidbody.gameObject : collider.gameObject; } } + // The relative velocity between the two bodies. + public Vector2 relativeVelocity { get { return m_RelativeVelocity; } } + + // Whether the collision is enabled or not. Effectors can temporarily disable a collision but all collisions are reported. + public bool enabled { get { return m_Enabled == 1; } } + // The contact points. - public ContactPoint2D[] contacts + public unsafe ContactPoint2D[] contacts { get { - if (m_Contacts == null) - m_Contacts = CreateCollisionContacts_Internal(collider, otherCollider, rigidbody, otherRigidbody, enabled); + if (m_LegacyContactArray == null) + { + m_LegacyContactArray = new ContactPoint2D[m_ContactCount]; + if (m_ContactCount > 0) + { + ContactPoint2D* contactPoint = (ContactPoint2D*)m_Contacts.ToPointer(); + for (var i = 0; i < m_ContactCount; ++i) + { + m_LegacyContactArray[i] = *contactPoint++; + } + } + } - return m_Contacts; + return m_LegacyContactArray; } } - [StaticAccessor("GetPhysicsManager2D()", StaticAccessorType.Arrow)] - [NativeMethod("CreateCollision2DContactsArray_Binding")] - extern private static ContactPoint2D[] CreateCollisionContacts_Internal(Collider2D collider, Collider2D otherCollider, Rigidbody2D rigidbody, Rigidbody2D otherRigidbody, bool enabled); - // Get contacts for this collision. - public int GetContacts(ContactPoint2D[] contacts) + public unsafe int GetContacts(ContactPoint2D[] contacts) { - return Physics2D.GetContacts(collider, otherCollider, new ContactFilter2D().NoFilter(), contacts); + if (contacts == null) + throw new ArgumentNullException("Cannot get contacts into a NULL array."); + + var contactCount = Mathf.Min(contacts.Length, m_ContactCount); + if (contactCount == 0) + return 0; + + // If we have an existing contact array then use that and copy it. + if (m_LegacyContactArray != null) + { + Array.Copy(m_LegacyContactArray, contacts, contactCount); + return contactCount; + } + + // Copy the cached contact points instead. + if (m_ContactCount > 0) + { + ContactPoint2D* contactPoint = (ContactPoint2D*)m_Contacts.ToPointer(); + for (var i = 0; i < contactCount; ++i) + { + contacts[i] = *contactPoint++; + } + } + return contactCount; } - // The relative velocity between the two bodies. - public Vector2 relativeVelocity { get { return m_RelativeVelocity; } } + ~Collision2D() + { + // Free any contacts. + if (m_ContactCount > 0) + FreeContacts(m_Contacts); + } - // Whether the collision is enabled or not. Effectors can temporarily disable a collision but all collisions are reported. - public bool enabled { get { return m_Enabled == 1; } } + [StaticAccessor("GetPhysicsManager2D()", StaticAccessorType.Arrow)] + [NativeMethod("FreeCachedContactPoints_Binding", IsThreadSafe = true)] + extern private static void FreeContacts(IntPtr contacts); }; // Describes a contact point where the collision occurs. diff --git a/Modules/PresetsEditor/PresetContextMenu.cs b/Modules/PresetsEditor/PresetContextMenu.cs index fd59da0679..ac1d9a7174 100644 --- a/Modules/PresetsEditor/PresetContextMenu.cs +++ b/Modules/PresetsEditor/PresetContextMenu.cs @@ -20,18 +20,44 @@ internal static void CreateAndShow(Object[] targets) var instance = CreateInstance(); if (targets[0] is AssetImporter) { - // we need to keep our own instance of the selected importer in order to handle the Apply/Reset correctly + // AssetImporterEditor never applies the AssetImporter's SerializedObject because it uses it for the Apply/Revert mechanic. + // This means we need to write/read the data directly from the SerializedObject instead of the AssetImporter itself + // And thus, we can't use Presets directly. instance.m_ImporterEditors = Resources .FindObjectsOfTypeAll() .Where(e => e.targets == targets) .ToArray(); - instance.m_Targets = new[] {Instantiate(targets[0])}; - instance.m_ImporterSerialized = new SerializedObject(targets); - var prop = instance.m_ImporterEditors[0].m_SerializedObject.GetIterator(); - while (prop.Next(true)) + // m_Targets needs to keep a dummy version of each real target to avoid overriding the real importers. + var dummyPresets = targets.Select(t => new Preset(t)); + instance.m_Targets = dummyPresets.Select(p => p.GetReferenceObject()).ToArray(); + instance.m_ImporterSerialized = new SerializedObject(instance.m_Targets); + // copy values from the first editor serializedObject, because user may have done changes we want to apply back when selecting none. + var currentEditorValues = instance.m_ImporterEditors[0].m_SerializedObject; + // Do only apply on the properties that are part of the Preset modifications list + // That will particularly avoid the AudioImporter preview data that can be a 30k+ array we don't want. + var presetProperties = dummyPresets.First().PropertyModifications; + string propertyPath = ""; + foreach (var propertyModification in presetProperties) { - instance.m_ImporterSerialized.CopyFromSerializedProperty(prop); + // We need to filter out .Array.* properties and use the parent one instead, + // because changing .Array.size from CopyFromSerializedProperty will corrupt the SerializedObject data. + if (!string.IsNullOrEmpty(propertyPath) && propertyModification.propertyPath.StartsWith(propertyPath + ".Array.")) + { + continue; + } + if (propertyModification.propertyPath.Contains(".Array.")) + { + propertyPath = propertyModification.propertyPath.Substring(0, propertyModification.propertyPath.IndexOf(".Array.")); + } + else + { + propertyPath = propertyModification.propertyPath; + } + instance.m_ImporterSerialized.CopyFromSerializedProperty(currentEditorValues.FindProperty(propertyPath)); } + instance.m_ImporterSerialized.ApplyModifiedPropertiesWithoutUndo(); + // create a list of Presets that contains the current values of each object + instance.m_Presets = instance.m_Targets.Select(t => new Preset(t)).ToArray(); } else { @@ -41,21 +67,50 @@ internal static void CreateAndShow(Object[] targets) PresetSelector.ShowSelector(targets[0], null, true, instance); } - void RevertValues() + void ApplyPresetSerializedObjectToEditorOnes() { - if (m_ImporterEditors != null) + var presetProperties = m_Presets[0].PropertyModifications; + foreach (var importerEditor in m_ImporterEditors) { - foreach (var importerEditor in m_ImporterEditors) + string propertyPath = ""; + // We need to revert the editor serializedobject first + // to make sure Apply/Revert button stay disabled if the Preset did not make any changes. + importerEditor.m_SerializedObject.SetIsDifferentCacheDirty(); + importerEditor.m_SerializedObject.Update(); + // Do only apply on the properties that are part of the Preset modifications list + // That will particularly avoid the AudioImporter preview data that can be a 30k+ array we don't want. + foreach (var propertyModification in presetProperties) { - importerEditor.m_SerializedObject.SetIsDifferentCacheDirty(); - importerEditor.m_SerializedObject.Update(); - var seria = m_ImporterSerialized.GetIterator(); - while (seria.Next(true)) + // We need to filter out .Array.* properties and use the parent one instead, + // because changing .Array.size from CopyFromSerializedProperty will corrupt the SerializedObject data. + if (!string.IsNullOrEmpty(propertyPath) && propertyModification.propertyPath.StartsWith(propertyPath + ".Array.")) + { + continue; + } + if (propertyModification.propertyPath.Contains(".Array.")) { - importerEditor.m_SerializedObject.CopyFromSerializedPropertyIfDifferent(seria); + propertyPath = propertyModification.propertyPath.Substring(0, propertyModification.propertyPath.IndexOf(".Array.")); } + else + { + propertyPath = propertyModification.propertyPath; + } + importerEditor.m_SerializedObject.CopyFromSerializedPropertyIfDifferent(m_ImporterSerialized.FindProperty(propertyPath)); } } + } + + void RevertValues() + { + if (m_ImporterEditors != null) + { + for (int i = 0; i < m_Targets.Length; i++) + { + m_Presets[i].ApplyTo(m_Targets[i]); + } + m_ImporterSerialized.Update(); + ApplyPresetSerializedObjectToEditorOnes(); + } else { Undo.RecordObjects(m_Targets, "Cancel Preset"); @@ -81,16 +136,8 @@ public override void OnSelectionChanged(Preset selection) } if (m_ImporterEditors != null) { - foreach (var importerEditor in m_ImporterEditors) - { - importerEditor.m_SerializedObject.SetIsDifferentCacheDirty(); - importerEditor.m_SerializedObject.Update(); - var seria = new SerializedObject(m_Targets).GetIterator(); - while (seria.Next(true)) - { - importerEditor.m_SerializedObject.CopyFromSerializedPropertyIfDifferent(seria); - } - } + m_ImporterSerialized.Update(); + ApplyPresetSerializedObjectToEditorOnes(); } } InspectorWindow.RepaintAllInspectors(); diff --git a/Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedCallsView.cs b/Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedCallsView.cs index 09f2373bd7..ed6de13910 100644 --- a/Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedCallsView.cs +++ b/Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedCallsView.cs @@ -446,19 +446,20 @@ void UpdateIfNeeded(FrameDataView frameDataView, int selectedId) var callers = new Dictionary(); var callees = new Dictionary(); + var childrenIds = new List(256); var stack = new Stack(); stack.Push(m_FrameDataView.GetRootItemID()); while (stack.Count > 0) { var current = stack.Pop(); + if (!m_FrameDataView.HasItemChildren(current)) continue; var markerId = m_FrameDataView.GetItemMarkerID(current); - - var childrenId = m_FrameDataView.GetItemChildren(current); - foreach (var childId in childrenId) + m_FrameDataView.GetItemChildren(current, childrenIds); + foreach (var childId in childrenIds) { var childMarkerId = m_FrameDataView.GetItemMarkerID(childId); if (childMarkerId == selectedMarkerId) diff --git a/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameDataTreeView.cs b/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameDataTreeView.cs index 488c41ecc1..eb5adc39fe 100644 --- a/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameDataTreeView.cs +++ b/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameDataTreeView.cs @@ -16,13 +16,34 @@ internal class ProfilerFrameDataTreeView : TreeView { public static readonly GUIContent kFrameTooltip = EditorGUIUtility.TextContent("|Press 'F' to frame selection"); + const int kMaxPooledRowsCount = 1000000; + readonly List m_Rows = new List(1000); ProfilerFrameDataMultiColumnHeader m_MultiColumnHeader; FrameDataView m_FrameDataView; FrameDataView.MarkerPath? m_SelectedItemMarkerIdPath; string m_LegacySelectedItemMarkerNamePath; - HashSet m_ExpandedMarkerIdPaths; + + // Tree of expanded nodes. + // Each level has a set of expanded marker ids, which are equivalent to sample name. + class ExpandedMarkerIdHierarchy + { + public Dictionary expandedMarkers; + } + [NonSerialized] + ExpandedMarkerIdHierarchy m_ExpandedMarkersHierarchy; + + [NonSerialized] + List m_RowsPool = new List(); + [NonSerialized] + Stack> m_ChildrenPool = new Stack>(); + [NonSerialized] + LinkedList m_ReusableVisitList = new LinkedList(); + [NonSerialized] + List m_ReusableChildrenIds = new List(1024); + [NonSerialized] + Stack> m_TreeTraversalStatePool = new Stack>(); public delegate void SelectionChangedCallback(int id); public event SelectionChangedCallback selectionChanged; @@ -73,7 +94,16 @@ public int samplesCount public FrameDataTreeViewItem(FrameDataView frameDataView, int id, int depth, TreeViewItem parent) : base(id, depth, parent, null) { - Assert.IsNotNull(frameDataView); + m_FrameDataView = frameDataView; + m_Initialized = false; + } + + internal void Init(FrameDataView frameDataView, int id, int depth, TreeViewItem parent) + { + this.id = id; + this.depth = depth; + this.parent = parent; + this.displayName = null; m_FrameDataView = frameDataView; m_Initialized = false; } @@ -123,23 +153,42 @@ public void SetFrameDataView(FrameDataView frameDataView) Reload(); } - void StoreExpandedState() + void AddExpandedChildrenRecursively(TreeViewItem item, ExpandedMarkerIdHierarchy expandedHierarchy) { - if (m_ExpandedMarkerIdPaths != null) + if (item.children == null) return; - if (m_FrameDataView == null || !m_FrameDataView.IsValid()) + for (var i = 0; i < item.children.Count; ++i) + { + var childItem = item.children[i]; + // Inlining !IsChildListForACollapsedParent without childList.Count == 1 check, as we only create list if we have children + if (childItem.children != null && childItem.children[0] != null) + { + var subHierarchy = new ExpandedMarkerIdHierarchy(); + if (expandedHierarchy.expandedMarkers == null) + expandedHierarchy.expandedMarkers = new Dictionary(); + try + { + expandedHierarchy.expandedMarkers.Add(m_FrameDataView.GetItemMarkerID(childItem.id), subHierarchy); + } + catch (ArgumentException) + { + } + + AddExpandedChildrenRecursively(childItem, subHierarchy); + } + } + } + + void StoreExpandedState() + { + if (m_ExpandedMarkersHierarchy != null) return; - var oldExpanded = GetExpanded(); - if (oldExpanded.Count == 0) + if (m_FrameDataView == null || !m_FrameDataView.IsValid()) return; - m_ExpandedMarkerIdPaths = new HashSet(); - foreach (var expanded in oldExpanded) - { - var markerIdPath = m_FrameDataView.GetItemMarkerIDPath(expanded); - m_ExpandedMarkerIdPaths.Add(markerIdPath); - } + m_ExpandedMarkersHierarchy = new ExpandedMarkerIdHierarchy(); + AddExpandedChildrenRecursively(rootItem, m_ExpandedMarkersHierarchy); } public void SetSelectionFromLegacyPropertyPath(string selectedPropertyPath) @@ -176,15 +225,6 @@ void StoreSelectedState() m_SelectedItemMarkerIdPath = m_FrameDataView.GetItemMarkerIDPath(oldSelection[0]); } - bool IsMigratedExpanded(int id) - { - if (m_ExpandedMarkerIdPaths == null) - return IsExpanded(id); - - var markerIdPath = m_FrameDataView.GetItemMarkerIDPath(id); - return m_ExpandedMarkerIdPaths.Contains(markerIdPath); - } - void MigrateExpandedState(List newExpandedIds) { if (newExpandedIds == null) @@ -205,17 +245,20 @@ void MigrateSelectedState(bool expandIfNecessary) { foreach (var marker in m_SelectedItemMarkerIdPath.Value.markerIds) { - var childrenId = m_FrameDataView.GetItemChildren(newSelectedId); - foreach (var childId in childrenId) + if (m_FrameDataView.HasItemChildren(newSelectedId)) { - if (marker == m_FrameDataView.GetItemMarkerID(childId)) + m_FrameDataView.GetItemChildren(newSelectedId, m_ReusableChildrenIds); + foreach (var childId in m_ReusableChildrenIds) { - // check if the parent is expanded - if (!IsExpanded(newSelectedId)) - selectedItemsPathIsExpanded = false; - - newSelectedId = childId; - break; + if (marker == m_FrameDataView.GetItemMarkerID(childId)) + { + // check if the parent is expanded + if (!IsExpanded(newSelectedId)) + selectedItemsPathIsExpanded = false; + + newSelectedId = childId; + break; + } } } @@ -229,18 +272,21 @@ void MigrateSelectedState(bool expandIfNecessary) var markerNames = m_LegacySelectedItemMarkerNamePath.Split('/'); foreach (var markerName in markerNames) { - var childrenId = m_FrameDataView.GetItemChildren(newSelectedId); - foreach (var childId in childrenId) + if (m_FrameDataView.HasItemChildren(newSelectedId)) { - if (markerName == m_FrameDataView.GetItemFunctionName(childId)) + m_FrameDataView.GetItemChildren(newSelectedId, m_ReusableChildrenIds); + foreach (var childId in m_ReusableChildrenIds) { - // check if the parent is expanded - if (!IsExpanded(newSelectedId)) - selectedItemsPathIsExpanded = false; - - newSelectedId = childId; - markerIdPath.Add(m_FrameDataView.GetItemMarkerID(childId)); - break; + if (markerName == m_FrameDataView.GetItemFunctionName(childId)) + { + // check if the parent is expanded + if (!IsExpanded(newSelectedId)) + selectedItemsPathIsExpanded = false; + + newSelectedId = childId; + markerIdPath.Add(m_FrameDataView.GetItemMarkerID(childId)); + break; + } } } @@ -252,11 +298,14 @@ void MigrateSelectedState(bool expandIfNecessary) m_LegacySelectedItemMarkerNamePath = null; } - var newSelection = (newSelectedId == 0) ? new List() : new List() { newSelectedId }; state.selectedIDs = newSelection; - if (newSelectedId != 0 && isInitialized && (selectedItemsPathIsExpanded || expandIfNecessary)) + // Framing invalidates expanded state and this is very expensive operation to perform each frame. + // Thus we auto frame selection only when we are not profiling. + var collectingSamples = ProfilerDriver.enabled && (ProfilerDriver.profileEditor || EditorApplication.isPlaying); + var isFramingAllowed = !collectingSamples; + if (newSelectedId != 0 && isInitialized && isFramingAllowed && (selectedItemsPathIsExpanded || expandIfNecessary)) FrameItem(newSelectedId); } @@ -281,6 +330,13 @@ public void Clear() m_FrameDataView.Dispose(); m_FrameDataView = null; + + m_RowsPool.Clear(); + m_ChildrenPool.Clear(); + m_ReusableVisitList.Clear(); + m_ReusableChildrenIds.Clear(); + m_TreeTraversalStatePool.Clear(); + Reload(); } @@ -292,19 +348,21 @@ protected override TreeViewItem BuildRoot() protected override IList BuildRows(TreeViewItem root) { + if (m_RowsPool.Count < kMaxPooledRowsCount) + m_RowsPool.AddRange(m_Rows); m_Rows.Clear(); if (m_FrameDataView == null || !m_FrameDataView.IsValid()) return m_Rows; - var newExpandedIds = m_ExpandedMarkerIdPaths == null ? null : new List(m_ExpandedMarkerIdPaths.Count); + var newExpandedIds = m_ExpandedMarkersHierarchy == null ? null : new List(state.expandedIDs.Count); if (!string.IsNullOrEmpty(searchString)) { Search(root, searchString, m_Rows); } else { - AddAllChildren((FrameDataTreeViewItem)root, m_Rows, newExpandedIds); + AddAllChildren((FrameDataTreeViewItem)root, m_ExpandedMarkersHierarchy, m_Rows, newExpandedIds); } MigrateExpandedState(newExpandedIds); @@ -323,12 +381,9 @@ void Search(TreeViewItem searchFromThis, string search, List resul const int kItemDepth = 0; // tree is flattened when searching var stack = new Stack(); - if (m_FrameDataView.HasItemChildren(searchFromThis.id)) - { - var childrenId = m_FrameDataView.GetItemChildren(searchFromThis.id); - foreach (var childId in childrenId) - stack.Push(childId); - } + m_FrameDataView.GetItemChildren(searchFromThis.id, m_ReusableChildrenIds); + foreach (var childId in m_ReusableChildrenIds) + stack.Push(childId); while (stack.Count > 0) { @@ -338,76 +393,139 @@ void Search(TreeViewItem searchFromThis, string search, List resul var functionName = m_FrameDataView.GetItemFunctionName(current); if (functionName.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0) { - var item = new FrameDataTreeViewItem(m_FrameDataView, current, kItemDepth, searchFromThis); + var item = AcquireFrameDataTreeViewItem(m_FrameDataView, current, kItemDepth, searchFromThis); searchFromThis.AddChild(item); result.Add(item); } - if (m_FrameDataView.HasItemChildren(current)) + m_FrameDataView.GetItemChildren(current, m_ReusableChildrenIds); + foreach (var childId in m_ReusableChildrenIds) + stack.Push(childId); + } + } + + // Hierarchy traversal state. + // Represents node to descent into and expansion state of its children. + // This way we follow samples and expansion hierarchy simultaneously avoiding expensive + // expansion lookup by a full sample path in a global table. + struct TreeTraversalState + { + public FrameDataTreeViewItem item; + public ExpandedMarkerIdHierarchy expandedHierarchy; + } + + LinkedListNode AcquireTreeTraversalStateNode(FrameDataTreeViewItem item, ExpandedMarkerIdHierarchy expandedHierarchy) + { + if (m_TreeTraversalStatePool.Count == 0) + return new LinkedListNode(new TreeTraversalState() { item = item, expandedHierarchy = expandedHierarchy }); + + var node = m_TreeTraversalStatePool.Pop(); + node.Value = new TreeTraversalState() { item = item, expandedHierarchy = expandedHierarchy }; + return node; + } + + FrameDataTreeViewItem AcquireFrameDataTreeViewItem(FrameDataView frameDataView, int id, int depth, TreeViewItem parent) + { + if (m_RowsPool.Count > 0) + { + FrameDataTreeViewItem child = (FrameDataTreeViewItem)m_RowsPool[m_RowsPool.Count - 1]; + m_RowsPool.RemoveAt(m_RowsPool.Count - 1); + child.Init(m_FrameDataView, id, depth, parent); + if (child.children != null) { - var childrenId = m_FrameDataView.GetItemChildren(current); - foreach (var childId in childrenId) - stack.Push(childId); + m_ChildrenPool.Push(child.children); + child.children = null; } + + return child; } + + return new FrameDataTreeViewItem(m_FrameDataView, id, depth, parent); } - void AddAllChildren(FrameDataTreeViewItem parent, IList newRows, List newExpandedIds) + void AddAllChildren(FrameDataTreeViewItem parent, ExpandedMarkerIdHierarchy parentExpandedHierararchy, IList newRows, List newExpandedIds) { - var toVisitList = new LinkedList(); - toVisitList.AddFirst(parent); + m_ReusableVisitList.AddFirst(AcquireTreeTraversalStateNode(parent, parentExpandedHierararchy)); - // Depth-first traversal - while (toVisitList.First != null) + // Depth-first traversal. + // Think of it as an unrolled recursion where stack state is defined by TreeTraversalState. + while (m_ReusableVisitList.First != null) { - var currentItem = toVisitList.First.Value; - toVisitList.RemoveFirst(); + var currentItem = m_ReusableVisitList.First.Value; + m_TreeTraversalStatePool.Push(m_ReusableVisitList.First); + m_ReusableVisitList.RemoveFirst(); - if (currentItem.depth != -1) - newRows.Add(currentItem); + if (currentItem.item.depth != -1) + newRows.Add(currentItem.item); - if (!m_FrameDataView.HasItemChildren(currentItem.id)) + m_FrameDataView.GetItemChildren(currentItem.item.id, m_ReusableChildrenIds); + var childrenCount = m_ReusableChildrenIds.Count; + if (childrenCount == 0) continue; - if (currentItem.depth != -1) + if (currentItem.item.depth != -1) { // Check expansion state from a previous frame view state (marker id path) or current tree view state (frame-specific id). - var needsExpansion = IsMigratedExpanded(currentItem.id); + bool needsExpansion; + if (m_ExpandedMarkersHierarchy == null) + { + // When we alter expansion state of the currently selected frame, + // we rely on TreeView's IsExpanded functionality. + needsExpansion = IsExpanded(currentItem.item.id); + } + else + { + // When we switch to another frame, we rebuild expanded state based on stored m_ExpandedMarkersHierarchy + // which represents tree of expanded nodes. + needsExpansion = currentItem.expandedHierarchy != null; + } + if (!needsExpansion) { - if (currentItem.children == null) - currentItem.children = CreateChildListForCollapsedParent(); + if (currentItem.item.children == null) + currentItem.item.children = CreateChildListForCollapsedParent(); continue; } if (newExpandedIds != null) - newExpandedIds.Add(currentItem.id); + newExpandedIds.Add(currentItem.item.id); } // Generate children based on the view data. - // TODO: Potentially we can reuse children list if it's only expansion/collapsing, but that has to be tracked separately. - var childrenId = m_FrameDataView.GetItemChildren(currentItem.id); - if (currentItem.children != null) + if (currentItem.item.children == null) { // Reuse existing list. - currentItem.children.Clear(); - currentItem.children.Capacity = childrenId.Length; - } - else - { - currentItem.children = new List(childrenId.Length); + if (m_ChildrenPool.Count > 0) + currentItem.item.children = m_ChildrenPool.Pop(); + else + currentItem.item.children = new List(); } - foreach (var childId in childrenId) + currentItem.item.children.Clear(); + currentItem.item.children.Capacity = childrenCount; + + for (var i = 0; i < childrenCount; ++i) { - var child = new FrameDataTreeViewItem(m_FrameDataView, childId, currentItem.depth + 1, currentItem); - currentItem.children.Add(child); + var child = AcquireFrameDataTreeViewItem(m_FrameDataView, m_ReusableChildrenIds[i], currentItem.item.depth + 1, currentItem.item); + currentItem.item.children.Add(child); } // Add children to the traversal list. // We add all of them in front, so it is depth search, but with preserved siblings order. - LinkedListNode prev = null; - foreach (var child in currentItem.children) - prev = prev == null ? toVisitList.AddFirst((FrameDataTreeViewItem)child) : toVisitList.AddAfter(prev, (FrameDataTreeViewItem)child); + LinkedListNode prev = null; + foreach (var child in currentItem.item.children) + { + var childMarkerId = m_FrameDataView.GetItemMarkerID(child.id); + ExpandedMarkerIdHierarchy childExpandedHierarchy = null; + if (currentItem.expandedHierarchy != null && currentItem.expandedHierarchy.expandedMarkers != null) + currentItem.expandedHierarchy.expandedMarkers.TryGetValue(childMarkerId, out childExpandedHierarchy); + + var traversalState = AcquireTreeTraversalStateNode((FrameDataTreeViewItem)child, childExpandedHierarchy); + if (prev == null) + m_ReusableVisitList.AddFirst(traversalState); + else + m_ReusableVisitList.AddAfter(prev, traversalState); + prev = traversalState; + } } if (newExpandedIds != null) @@ -439,7 +557,7 @@ protected override void SelectionChanged(IList selectedIds) protected override void ExpandedStateChanged() { // Invalidate saved expanded state if user altered current state. - m_ExpandedMarkerIdPaths = null; + m_ExpandedMarkersHierarchy = null; } protected override void DoubleClickedItem(int id) diff --git a/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameHierarchyView.cs b/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameHierarchyView.cs index 402b3b929c..123e085a28 100644 --- a/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameHierarchyView.cs +++ b/Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameHierarchyView.cs @@ -256,9 +256,12 @@ public void DoGUI(FrameDataView frameDataView) { InitIfNeeded(); - var isDataAvailable = frameDataView != null && frameDataView.IsValid(); + var collectingSamples = ProfilerDriver.enabled && (ProfilerDriver.profileEditor || EditorApplication.isPlaying); + var isSearchAllowed = string.IsNullOrEmpty(treeView.searchString) || !(collectingSamples && ProfilerDriver.deepProfiling); - m_TreeView.SetFrameDataView(frameDataView); + var isDataAvailable = frameDataView != null && frameDataView.IsValid(); + if (isDataAvailable && isSearchAllowed) + m_TreeView.SetFrameDataView(frameDataView); var showDetailedView = isDataAvailable && m_DetailedViewType != DetailedViewType.None; if (showDetailedView) @@ -273,6 +276,10 @@ public void DoGUI(FrameDataView frameDataView) { GUILayout.Label(BaseStyles.noData, BaseStyles.label); } + else if (!isSearchAllowed) + { + GUILayout.Label(BaseStyles.disabledSearchText, BaseStyles.label); + } else { var rect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true), GUILayout.ExpandHeight(true)); diff --git a/Modules/Profiler/Editor/ProfilerWindow/ProfilerWindow.cs b/Modules/Profiler/Editor/ProfilerWindow/ProfilerWindow.cs index d36e08a1c6..4c2b71d676 100644 --- a/Modules/Profiler/Editor/ProfilerWindow/ProfilerWindow.cs +++ b/Modules/Profiler/Editor/ProfilerWindow/ProfilerWindow.cs @@ -40,8 +40,11 @@ internal static class Styles public static readonly GUIContent frame = EditorGUIUtility.TrTextContent("Frame: "); public static readonly GUIContent clearOnPlay = EditorGUIUtility.TrTextContent("Clear on Play"); public static readonly GUIContent clearData = EditorGUIUtility.TrTextContent("Clear"); + public static readonly GUIContent saveWindowTitle = EditorGUIUtility.TrTextContent("Save Window"); public static readonly GUIContent saveProfilingData = EditorGUIUtility.TrTextContent("Save", "Save current profiling information to a binary file"); + public static readonly GUIContent loadWindowTitle = EditorGUIUtility.TrTextContent("Load Window"); public static readonly GUIContent loadProfilingData = EditorGUIUtility.TrTextContent("Load", "Load binary profiling information from a file. Shift click to append to the existing data"); + public static readonly string[] loadProfilingDataFileFilters = new string[] { L10n.Tr("Profiler files"), "data,raw", L10n.Tr("All files"), "*" }; public static readonly GUIContent[] reasons = GetLocalizedReasons(); public static readonly GUIContent accessibilityModeLabel = EditorGUIUtility.TrTextContent("Color Blind Mode"); @@ -1197,7 +1200,6 @@ void MemRecordModeClick(object userData, string[] options, int selected) void SaveProfilingData() { - string title = EditorGUIUtility.TempContent("Save profile").text; string recent = EditorPrefs.GetString(kProfilerRecentSaveLoadProfilePath); string directory = string.IsNullOrEmpty(recent) ? "" @@ -1206,7 +1208,7 @@ void SaveProfilingData() ? "" : System.IO.Path.GetFileName(recent); - string selected = EditorUtility.SaveFilePanel(title, directory, filename, "data"); + string selected = EditorUtility.SaveFilePanel(Styles.saveWindowTitle.text, directory, filename, "data"); if (selected.Length != 0) { EditorPrefs.SetString(kProfilerRecentSaveLoadProfilePath, selected); @@ -1219,9 +1221,8 @@ void SaveProfilingData() void LoadProfilingData(bool keepExistingData) { - string title = EditorGUIUtility.TempContent("Load profile").text; string recent = EditorPrefs.GetString(kProfilerRecentSaveLoadProfilePath); - string selected = EditorUtility.OpenFilePanel(title, recent, "data"); + string selected = EditorUtility.OpenFilePanelWithFilters(Styles.loadWindowTitle.text, recent, Styles.loadProfilingDataFileFilters); if (selected.Length != 0) { EditorPrefs.SetString(kProfilerRecentSaveLoadProfilePath, selected); diff --git a/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs b/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs index 56f84d67e5..1777c77f30 100644 --- a/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs +++ b/Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using System.Text; using UnityEngine.Bindings; using UnityEngine.Scripting.APIUpdating; @@ -159,7 +160,9 @@ private void DisposeInternal() public extern bool HasItemChildren(int id); - public extern int[] GetItemChildren(int id); + public extern int GetItemChildrenCount(int id); + + public extern void GetItemChildren(int id, List outChildren); public extern int[] GetItemAncestors(int id); diff --git a/Modules/UnityEditorAnalyticsEditor/BuildEventsHandler.cs b/Modules/UnityEditorAnalyticsEditor/BuildEventsHandler.cs index 9dd6f0e1c6..735896e658 100644 --- a/Modules/UnityEditorAnalyticsEditor/BuildEventsHandler.cs +++ b/Modules/UnityEditorAnalyticsEditor/BuildEventsHandler.cs @@ -19,7 +19,7 @@ internal struct SceneViewInfo public bool is_default_2d_mode; } - internal class BuildEventsHandlerPostProcess : IPostprocessBuild + internal class BuildEventsHandlerPostProcess : IPostprocessBuildWithReport { private static bool s_EventSent = false; private static int s_NumOfSceneViews = 0; diff --git a/README.md b/README.md index bb33569334..aaa399cd3a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.1.0b11 C# reference source code +## Unity 2018.1.0b12 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Export/RenderPipeline/SupportedRenderingFeatures.cs b/Runtime/Export/RenderPipeline/SupportedRenderingFeatures.cs index 2534a106df..43b012357a 100644 --- a/Runtime/Export/RenderPipeline/SupportedRenderingFeatures.cs +++ b/Runtime/Export/RenderPipeline/SupportedRenderingFeatures.cs @@ -2,6 +2,7 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; using UnityEngine.Scripting; namespace UnityEngine.Experimental.Rendering @@ -54,60 +55,125 @@ public enum LightmapMixedBakeMode public bool rendererSupportsReceiveShadows { get; set; } = true; public bool rendererSupportsReflectionProbes { get; set; } = true; + internal static unsafe MixedLightingMode FallbackMixedLightingMode() + { + MixedLightingMode fallbackMode; + FallbackMixedLightingModeByRef(new IntPtr(&fallbackMode)); + return fallbackMode; + } + [RequiredByNativeCode] - internal static MixedLightingMode FallbackMixedLightingMode() + internal static unsafe void FallbackMixedLightingModeByRef(IntPtr fallbackModePtr) { - // the pipline has picked a default value that is supported + var fallbackMode = (MixedLightingMode*)fallbackModePtr; + + // if the pipeline has picked a default value that is supported if ((SupportedRenderingFeatures.active.defaultMixedLightingMode != LightmapMixedBakeMode.None) && ((SupportedRenderingFeatures.active.supportedMixedLightingModes & SupportedRenderingFeatures.active.defaultMixedLightingMode) == SupportedRenderingFeatures.active.defaultMixedLightingMode)) { switch (SupportedRenderingFeatures.active.defaultMixedLightingMode) { case LightmapMixedBakeMode.Shadowmask: - return MixedLightingMode.Shadowmask; + *fallbackMode = MixedLightingMode.Shadowmask; + break; case LightmapMixedBakeMode.Subtractive: - return MixedLightingMode.Subtractive; + *fallbackMode = MixedLightingMode.Subtractive; + break; default: - return MixedLightingMode.IndirectOnly; + *fallbackMode = MixedLightingMode.IndirectOnly; + break; } + return; } + // otherwise we try to find a value that is supported if (IsMixedLightingModeSupported(MixedLightingMode.Shadowmask)) - return MixedLightingMode.Shadowmask; + { + *fallbackMode = MixedLightingMode.Shadowmask; + return; + } if (IsMixedLightingModeSupported(MixedLightingMode.Subtractive)) - return MixedLightingMode.Subtractive; + { + *fallbackMode = MixedLightingMode.Subtractive; + return; + } + + // last restort. make sure Mixed mode is even supported, otherwise the baking pipeline will treat the Mixed lights it as Realtime + *fallbackMode = MixedLightingMode.IndirectOnly; + } - return MixedLightingMode.IndirectOnly; + internal static unsafe bool IsMixedLightingModeSupported(MixedLightingMode mixedMode) + { + bool isSupported; + IsMixedLightingModeSupportedByRef(mixedMode, new IntPtr(&isSupported)); + return isSupported; } [RequiredByNativeCode] - internal static bool IsMixedLightingModeSupported(MixedLightingMode mixedMode) + internal unsafe static void IsMixedLightingModeSupportedByRef(MixedLightingMode mixedMode, IntPtr isSupportedPtr) { + // if Mixed mode hasn't been turned off completely and the Mixed lights will be treated as Realtime + bool* isSupported = (bool*)isSupportedPtr; + + if (!IsLightmapBakeTypeSupported(LightmapBakeType.Mixed)) + { + *isSupported = false; + return; + } // this is done since the original enum doesn't allow flags due to it starting at 0, not 1 - return ((mixedMode == MixedLightingMode.IndirectOnly && - ((SupportedRenderingFeatures.active.supportedMixedLightingModes & - LightmapMixedBakeMode.IndirectOnly) == LightmapMixedBakeMode.IndirectOnly)) || - (mixedMode == MixedLightingMode.Subtractive && - ((SupportedRenderingFeatures.active.supportedMixedLightingModes & - LightmapMixedBakeMode.Subtractive) == LightmapMixedBakeMode.Subtractive)) || - (mixedMode == MixedLightingMode.Shadowmask && - ((SupportedRenderingFeatures.active.supportedMixedLightingModes & - LightmapMixedBakeMode.Shadowmask) == LightmapMixedBakeMode.Shadowmask))); + *isSupported = ((mixedMode == MixedLightingMode.IndirectOnly && + ((SupportedRenderingFeatures.active.supportedMixedLightingModes & + LightmapMixedBakeMode.IndirectOnly) == LightmapMixedBakeMode.IndirectOnly)) || + (mixedMode == MixedLightingMode.Subtractive && + ((SupportedRenderingFeatures.active.supportedMixedLightingModes & + LightmapMixedBakeMode.Subtractive) == LightmapMixedBakeMode.Subtractive)) || + (mixedMode == MixedLightingMode.Shadowmask && + ((SupportedRenderingFeatures.active.supportedMixedLightingModes & + LightmapMixedBakeMode.Shadowmask) == LightmapMixedBakeMode.Shadowmask))); + } + + internal static unsafe bool IsLightmapBakeTypeSupported(LightmapBakeType bakeType) + { + bool isSupported; + IsLightmapBakeTypeSupportedByRef(bakeType, new IntPtr(&isSupported)); + return isSupported; } [RequiredByNativeCode] - internal static bool IsLightmapBakeTypeSupported(LightmapBakeType bakeType) + internal static unsafe void IsLightmapBakeTypeSupportedByRef(LightmapBakeType bakeType, IntPtr isSupportedPtr) + { + var isSupported = (bool*)isSupportedPtr; + + if (bakeType == LightmapBakeType.Mixed) + { + // we can't have Mixed without Bake + bool isBakedSupported = IsLightmapBakeTypeSupported(LightmapBakeType.Baked); + // we can't support Mixed mode and then not support any of the different modes + if (!isBakedSupported || SupportedRenderingFeatures.active.supportedMixedLightingModes == LightmapMixedBakeMode.None) + { + *isSupported = false; + return; + } + } + + *isSupported = ((SupportedRenderingFeatures.active.supportedLightmapBakeTypes & bakeType) == bakeType); + } + + internal static unsafe bool IsLightmapsModeSupported(LightmapsMode mode) { - return ((SupportedRenderingFeatures.active.supportedLightmapBakeTypes & bakeType) == bakeType); + bool isSupported; + IsLightmapsModeSupportedByRef(mode, new IntPtr(&isSupported)); + return isSupported; } [RequiredByNativeCode] - internal static bool IsLightmapsModeSupported(LightmapsMode mode) + internal static unsafe void IsLightmapsModeSupportedByRef(LightmapsMode mode, IntPtr isSupportedPtr) { - return ((SupportedRenderingFeatures.active.supportedLightmapsModes & mode) == mode); + var isSupported = (bool*)isSupportedPtr; + *isSupported = ((SupportedRenderingFeatures.active.supportedLightmapsModes & mode) == mode); } } } diff --git a/Runtime/Export/UnitySynchronizationContext.cs b/Runtime/Export/UnitySynchronizationContext.cs index a9cbc9a811..deb67e0aec 100644 --- a/Runtime/Export/UnitySynchronizationContext.cs +++ b/Runtime/Export/UnitySynchronizationContext.cs @@ -51,7 +51,8 @@ private void Exec() { lock (m_AsyncWorkQueue) { - while (m_AsyncWorkQueue.Count > 0) + var workCount = m_AsyncWorkQueue.Count; + for (int i = 0; i < workCount; i++) { var work = m_AsyncWorkQueue.Dequeue(); work.Invoke(); diff --git a/artifacts/generated/bindings_old/common/Core/RenderingCommandBufferBindings.gen.cs b/artifacts/generated/bindings_old/common/Core/RenderingCommandBufferBindings.gen.cs index 498621dd80..a35aa465a1 100644 --- a/artifacts/generated/bindings_old/common/Core/RenderingCommandBufferBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Core/RenderingCommandBufferBindings.gen.cs @@ -652,6 +652,17 @@ public void SetViewport (Rect pixelRect) { [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] private extern static void INTERNAL_CALL_SetViewport (CommandBuffer self, ref Rect pixelRect); + public void EnableScissorRect (Rect scissor) { + INTERNAL_CALL_EnableScissorRect ( this, ref scissor ); + } + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + private extern static void INTERNAL_CALL_EnableScissorRect (CommandBuffer self, ref Rect scissor); + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern public void DisableScissorRect () ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern private void CopyTexture_Internal (ref UnityEngine.Rendering.RenderTargetIdentifier src, int srcElement, int srcMip, int srcX, int srcY, int srcWidth, int srcHeight, diff --git a/artifacts/generated/bindings_old/common/Editor/PlayerSettingsBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/PlayerSettingsBindings.gen.cs index 0028c70061..2c4b91e0a3 100644 --- a/artifacts/generated/bindings_old/common/Editor/PlayerSettingsBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/PlayerSettingsBindings.gen.cs @@ -549,6 +549,16 @@ public extern static bool macRetinaSupport set; } + public extern static bool enableMetalAPIValidation + { + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + get; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + set; + } + public extern static bool runInBackground { [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration From 73f36bfe71b68d241a6802e0396dc6d6822cb520 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Tue, 11 Sep 2018 13:07:05 +0000 Subject: [PATCH 12/17] Unity 2018.3.0b1 C# reference source code --- Editor/Mono/AssetStore/AssetStoreContext.cs | 17 + .../GUI/AudioMixerExposedParameterView.cs | 4 + .../GUI/AudioMixerExposedParametersPopup.cs | 2 +- Editor/Mono/BuildPipeline/AssemblyStripper.cs | 2 +- Editor/Mono/Collab/Collab.bindings.cs | 5 + Editor/Mono/Collab/Collab.cs | 10 +- Editor/Mono/Commands/GOCreationCommands.cs | 7 +- Editor/Mono/ContainerWindow.bindings.cs | 6 +- Editor/Mono/ContainerWindow.cs | 14 +- Editor/Mono/EditorApplication.cs | 11 + Editor/Mono/EditorGUI.cs | 65 +++- .../BoundsHandle/PrimitiveBoundsHandle.cs | 4 +- .../EditorHandles/JointAngularLimitHandle.cs | 8 +- .../Mono/EditorUserBuildSettings.bindings.cs | 9 + Editor/Mono/EditorUtility.cs | 10 +- Editor/Mono/EditorWindow.cs | 22 +- .../GI/LightmapEditorSettings.bindings.cs | 7 +- Editor/Mono/GUI/ColorPicker.cs | 23 +- Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs | 4 +- Editor/Mono/GUI/Toolbar.cs | 1 + .../TreeView/GameObjectTreeViewDataSource.cs | 4 - Editor/Mono/GUI/WindowLayout.cs | 11 +- Editor/Mono/GameView/GameViewSizes.cs | 8 +- Editor/Mono/HandleUtility.cs | 11 +- Editor/Mono/Handles.cs | 4 +- .../Inspector/Avatar/AvatarMappingEditor.cs | 14 +- Editor/Mono/Inspector/CameraEditor.cs | 2 +- Editor/Mono/Inspector/LabelGUI.cs | 4 +- .../Inspector/LightingSettingsInspector.cs | 12 +- .../Inspector/MaterialEditorGUIHelpers.cs | 1 + .../PlayerSettingsEditor.cs | 42 +-- Editor/Mono/Inspector/RectTransformEditor.cs | 2 +- Editor/Mono/Inspector/TagManagerInspector.cs | 2 +- Editor/Mono/Inspector/TextureInspector.cs | 103 ++++- Editor/Mono/LookDevView/LookDevView.cs | 2 +- Editor/Mono/Prefabs/PrefabUtility.bindings.cs | 38 +- Editor/Mono/Prefabs/PrefabUtility.cs | 79 ++-- Editor/Mono/ProjectBrowser.cs | 2 +- .../Mono/ProjectWindow/ProjectWindowUtil.cs | 15 - Editor/Mono/SceneHierarchy.cs | 4 +- Editor/Mono/SceneHierarchyStageHandling.cs | 26 +- .../StageManager/PrefabStage/PrefabStage.cs | 54 ++- .../DefaultLightingExplorerExtension.cs | 14 +- .../LightingWindowBakeSettings.cs | 37 +- Editor/Mono/SceneView/SceneView.cs | 4 +- .../Mono/Scripting/Compilers/UWPReferences.cs | 10 +- .../ScriptCompilation/EditorCompilation.cs | 26 +- .../EditorScriptCompilationOptions.cs | 3 +- Editor/Mono/TooltipView/TooltipView.cs | 2 +- .../SolutionSynchronizer.cs | 6 + .../AssetImporterTabbedEditor.cs | 2 + .../Manipulators/SelectionDragger.cs | 2 + Modules/GraphViewEditor/Views/GraphView.cs | 1 + .../GridEditor/Managed/GridEditorUtility.cs | 40 +- Modules/IMGUI/GUILayout.cs | 5 + .../ImageConversion.bindings.cs | 2 +- .../MemoryProfiler/MemorySnapshot.cs | 20 +- .../ProfilerWindow/NetworkDetailStats.cs | 4 + .../ProfilerFrameHierarchyView.cs | 104 ++--- .../ProfilerWindow/ProfilerTimelineGUI.cs | 355 +++++++++--------- .../ProfilerWindow/ProfilerWindow.cs | 303 ++++++++------- .../Public/ProfilerAPI.bindings.cs | 2 +- .../ProfilerFrameDataIterator.bindings.cs | 8 + .../ShortcutController.cs | 11 + Modules/ShortcutManagerEditor/Trigger.cs | 5 + Modules/Tilemap/Managed/GridBrushBase.cs | 3 + .../Editor/Managed/Grid/GridBrush.cs | 1 + .../Managed/Grid/GridBrushEditorBase.cs | 6 + .../Managed/Grid/GridPaintPaletteClipboard.cs | 39 +- .../Managed/Grid/GridPaintPaletteWindow.cs | 80 +++- .../Editor/Managed/Grid/GridPaintingState.cs | 13 +- .../Editor/Managed/Grid/PaintableGrid.cs | 50 ++- .../Managed/Grid/PaintableSceneViewGrid.cs | 10 +- .../Editor/Managed/TilemapEditor.cs | 31 +- Modules/TreeEditor/TreeEditor.cs | 2 - .../EditorAnalytics.bindings.cs | 2 + .../Public/DownloadHandlerAudio.bindings.cs | 1 + Modules/XR/ScriptBindings/XRInput.bindings.cs | 95 +++-- README.md | 2 +- Runtime/Export/Camera.bindings.cs | 6 +- Runtime/Export/GI/DynamicGI.bindings.cs | 3 + Runtime/Export/GraphicsEnums.cs | 11 + Runtime/Export/SystemInfo.bindings.cs | 8 + Runtime/Export/Vector3Int.cs | 4 +- .../Networking/Managed/MatchMakingClient.cs | 7 +- .../Managed/NetworkTransportConfig.cs | 5 + .../UNETTransportConfig.bindings.cs | 2 + .../ScriptBindings/UNETworking.bindings.cs | 1 + .../MemoryProfiling.bindings.cs | 5 + 89 files changed, 1240 insertions(+), 784 deletions(-) diff --git a/Editor/Mono/AssetStore/AssetStoreContext.cs b/Editor/Mono/AssetStore/AssetStoreContext.cs index 068e39c522..7669651041 100644 --- a/Editor/Mono/AssetStore/AssetStoreContext.cs +++ b/Editor/Mono/AssetStore/AssetStoreContext.cs @@ -12,6 +12,7 @@ using System.Linq; using System.IO; using UnityEditor.Web; +using UnityEditor.Analytics; namespace UnityEditor { @@ -163,6 +164,15 @@ public void OpenBrowser(string url) Application.OpenURL(url); } + [Serializable] + public struct DownloadAssetInfo + { + public string package_id; + public string package_name; + public string publisher_name; + public string category_name; + } + public void Download(Package package, DownloadInfo downloadInfo) { Download( @@ -205,6 +215,13 @@ public static void Download(string package_id, string url, string key, string pa parameters["download"] = download; AssetStoreUtils.Download(package_id, url, dest, key, parameters.ToString(), resumeOK, doneCallback); + EditorAnalytics.SendAssetDownloadEvent(new DownloadAssetInfo() + { + package_id = package_id, + package_name = package_name, + publisher_name = publisher_name, + category_name = category_name + }); } /// diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs index 9832a5c637..8c86a45d7a 100644 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs +++ b/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs @@ -106,6 +106,10 @@ void DrawElement(Rect rect, int index, bool isActive, bool isFocused) public Vector2 CalcSize() { + if (m_ReorderableListWithRenameAndScrollView.list.count != m_Controller.exposedParameters.Length) + { + RecreateListControl(); + } float maxWidth = 0; for (int index = 0; index < m_ReorderableListWithRenameAndScrollView.list.count; index++) { diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs index c2935d9343..b06409045d 100644 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs +++ b/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs @@ -18,7 +18,7 @@ internal static void Popup(AudioMixerController controller, GUIStyle style, para Rect buttonRect = GUILayoutUtility.GetRect(content, style, options); if (EditorGUI.DropdownButton(buttonRect, content, FocusType.Passive, style)) { - PopupWindow.Show(buttonRect, new AudioMixerExposedParametersPopup(controller), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(buttonRect, new AudioMixerExposedParametersPopup(controller)); } } diff --git a/Editor/Mono/BuildPipeline/AssemblyStripper.cs b/Editor/Mono/BuildPipeline/AssemblyStripper.cs index 69c450511f..3f9223838c 100644 --- a/Editor/Mono/BuildPipeline/AssemblyStripper.cs +++ b/Editor/Mono/BuildPipeline/AssemblyStripper.cs @@ -77,7 +77,7 @@ private static bool StripAssembliesTo(string[] assemblies, string[] searchDirs, args.AddRange(additionalBlacklist.Select(path => "-x \"" + path + "\"")); args.AddRange(searchDirs.Select(d => "-d \"" + d + "\"")); - args.AddRange(assemblies.Select(assembly => "-a \"" + Path.GetFullPath(assembly) + "\"")); + args.AddRange(assemblies.Select(assembly => "--include-unity-root-assembly=\"" + Path.GetFullPath(assembly) + "\"")); args.Add($"--dotnetruntime={GetRuntimeArgumentValueForLinker(buildTargetGroup)}"); args.Add($"--dotnetprofile={GetProfileArgumentValueForLinker(buildTargetGroup)}"); args.Add("--use-editor-options"); diff --git a/Editor/Mono/Collab/Collab.bindings.cs b/Editor/Mono/Collab/Collab.bindings.cs index e2755d5759..253f72c7b9 100644 --- a/Editor/Mono/Collab/Collab.bindings.cs +++ b/Editor/Mono/Collab/Collab.bindings.cs @@ -206,12 +206,17 @@ public extern void TestClearSoftLockAsCollaborator(string projectGuid, string pr [NativeMethod(HasExplicitThis = true, ThrowsException = true, IsThreadSafe = true)] extern void SetChangesToPublishInternal(ChangeItem[] changes); + [NativeMethod(HasExplicitThis = true, ThrowsException = true, IsThreadSafe = true)] + extern Change[] GetSelectedChangesInternal(); + [NativeMethod(Name = "GetJobProgress", HasExplicitThis = true, ThrowsException = true)] extern bool GetJobProgressInternal([Out] ProgressInfo info, int jobId); [NativeMethod(HasExplicitThis = true, ThrowsException = true)] public extern void Publish(string comment, bool useSelectedAssets, bool confirmMatchesPrevious); + [NativeMethod(HasExplicitThis = true, ThrowsException = true, IsThreadSafe = true)] + public extern void ClearSelectedChangesToPublish(); [NativeMethod(HasExplicitThis = true, ThrowsException = true)] public extern SoftLock[] GetSoftLocks(string assetGuid); diff --git a/Editor/Mono/Collab/Collab.cs b/Editor/Mono/Collab/Collab.cs index 2ab706e9eb..80ec1bd2c5 100644 --- a/Editor/Mono/Collab/Collab.cs +++ b/Editor/Mono/Collab/Collab.cs @@ -364,11 +364,17 @@ public bool SetConflictsResolvedTheirs(string[] paths) public PublishInfo GetChangesToPublish() { - Change[] changes = GetChangesToPublishInternal(); + Change[] changes = GetSelectedChangesInternal(); + bool isFiltered = false; + if (Toolbar.isLastShowRequestPartial) + { + isFiltered = true; + } + return new PublishInfo() { changes = changes, - filter = false + filter = isFiltered }; } diff --git a/Editor/Mono/Commands/GOCreationCommands.cs b/Editor/Mono/Commands/GOCreationCommands.cs index bc37a4b193..17755458d3 100644 --- a/Editor/Mono/Commands/GOCreationCommands.cs +++ b/Editor/Mono/Commands/GOCreationCommands.cs @@ -52,7 +52,12 @@ static void CreateEmptyChild(MenuCommand menuCommand) { var parent = menuCommand.context as GameObject; if (parent == null) - parent = Selection.activeGameObject; + { + var activeGO = Selection.activeGameObject; + if (activeGO != null && !EditorUtility.IsPersistent(activeGO)) + parent = activeGO; + } + var go = ObjectFactory.CreateGameObject("GameObject"); Place(go, parent); } diff --git a/Editor/Mono/ContainerWindow.bindings.cs b/Editor/Mono/ContainerWindow.bindings.cs index 2c427c9ead..d070126ab3 100644 --- a/Editor/Mono/ContainerWindow.bindings.cs +++ b/Editor/Mono/ContainerWindow.bindings.cs @@ -12,7 +12,7 @@ internal enum ShowMode { // Show as a normal window with max, min & close buttons. NormalWindow = 0, - // Used for a popup menu and tooltip. On mac this means light shadow and no titlebar. + // Used for a popup menu. On mac this means light shadow and no titlebar. PopupMenu = 1, // Utility window - floats above the app. Disappears when app loses focus. Utility = 2, @@ -22,8 +22,8 @@ internal enum ShowMode MainWindow = 4, // Aux windows. The ones that close the moment you move the mouse out of them. AuxWindow = 5, - // Like PopupMenu, but allows keyboard focus (e.g. AddComponentWindow) - PopupMenuWithKeyboardFocus = 6 + // Like PopupMenu, but without keyboard focus + Tooltip = 6 } //[StaticAccessor("ContainerWindowBindings", StaticAccessorType.DoubleColon)] diff --git a/Editor/Mono/ContainerWindow.cs b/Editor/Mono/ContainerWindow.cs index dea9694434..248f7b566c 100644 --- a/Editor/Mono/ContainerWindow.cs +++ b/Editor/Mono/ContainerWindow.cs @@ -59,14 +59,24 @@ internal void __internalAwake() internal static bool IsPopup(ShowMode mode) { - return (ShowMode.PopupMenu == mode || ShowMode.PopupMenuWithKeyboardFocus == mode); + return (ShowMode.PopupMenu == mode); } internal bool isPopup { get { return IsPopup((ShowMode)m_ShowMode); } } internal void ShowPopup() { - m_ShowMode = (int)ShowMode.PopupMenu; + ShowPopupWithMode(ShowMode.PopupMenu); + } + + internal void ShowTooltip() + { + ShowPopupWithMode(ShowMode.Tooltip); + } + + internal void ShowPopupWithMode(ShowMode mode) + { + m_ShowMode = (int)mode; Internal_Show(m_PixelRect, m_ShowMode, m_MinSize, m_MaxSize); if (m_RootView) m_RootView.SetWindowRecurse(this); diff --git a/Editor/Mono/EditorApplication.cs b/Editor/Mono/EditorApplication.cs index ef237e355f..58680a1ff7 100644 --- a/Editor/Mono/EditorApplication.cs +++ b/Editor/Mono/EditorApplication.cs @@ -187,6 +187,9 @@ public static void DirtyHierarchyWindowSorting() // Global key up/down event that was not handled by anyone internal static CallbackFunction globalEventHandler; + // Returns true when the pressed keys are defined in the Trigger + internal static Func doPressedKeysTriggerAnyShortcut; + // Windows were reordered internal static CallbackFunction windowsReordered; @@ -313,6 +316,14 @@ static void Internal_CallWindowsReordered() windowsReordered(); } + [RequiredByNativeCode] + static bool DoPressedKeysTriggerAnyShortcutHandler() + { + if (doPressedKeysTriggerAnyShortcut != null) + return doPressedKeysTriggerAnyShortcut(); + return false; + } + [RequiredByNativeCode] static void Internal_CallGlobalEventHandler() { diff --git a/Editor/Mono/EditorGUI.cs b/Editor/Mono/EditorGUI.cs index 6b63726c98..0494d380d8 100644 --- a/Editor/Mono/EditorGUI.cs +++ b/Editor/Mono/EditorGUI.cs @@ -18,6 +18,7 @@ using UnityEditor.Build; using UnityEditor.StyleSheets; using UnityEngine.Internal; +using UnityEngine.Rendering; using DescriptionAttribute = System.ComponentModel.DescriptionAttribute; namespace UnityEditor @@ -1050,6 +1051,7 @@ internal static string DoTextField(RecycledTextEditor editor, int id, Rect posit // Note, OS X send characters for the following keys that we need to eat: // ASCII 25: "End Of Medium" on pressing shift tab // ASCII 27: "Escape" on pressing ESC + nonPrintableTab = true; } else if (editor.IsEditingControl(id)) { @@ -4337,6 +4339,14 @@ private static Color DoColorField(Rect position, int id, Color value, bool showE break; case EventType.ExecuteCommand: + + // Cancel EyeDropper if we change focus. + if (showEyedropper && Event.current.commandName == EventCommandNames.NewKeyboardFocus) + { + EyeDropper.End(); + s_ColorPickID = 0; + } + // when ColorPicker sends an event back to this control's GUIView, it someties retains keyboardControl if (GUIUtility.keyboardControl == id || ColorPicker.originalKeyboardControl == id) { @@ -5639,11 +5649,11 @@ internal static void ShowRepaints() // Draws the alpha channel of a texture within a rectangle. internal static void DrawTextureAlphaInternal(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel) { - DrawPreviewTextureInternal(position, image, alphaMaterial, scaleMode, imageAspect, mipLevel); + DrawPreviewTextureInternal(position, image, alphaMaterial, scaleMode, imageAspect, mipLevel, ColorWriteMask.All); } // Draws texture transparently using the alpha channel. - internal static void DrawTextureTransparentInternal(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel) + internal static void DrawTextureTransparentInternal(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel, ColorWriteMask colorWriteMask) { if (imageAspect == 0f && image == null) { @@ -5656,7 +5666,7 @@ internal static void DrawTextureTransparentInternal(Rect position, Texture image DrawTransparencyCheckerTexture(position, scaleMode, imageAspect); if (image != null) - DrawPreviewTexture(position, image, transparentMaterial, scaleMode, imageAspect, mipLevel); + DrawPreviewTexture(position, image, transparentMaterial, scaleMode, imageAspect, mipLevel, colorWriteMask); } internal static void DrawTransparencyCheckerTexture(Rect position, ScaleMode scaleMode, float imageAspect) @@ -5678,15 +5688,27 @@ internal static void DrawTransparencyCheckerTexture(Rect position, ScaleMode sca } // Draws the texture within a rectangle. - internal static void DrawPreviewTextureInternal(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect, float mipLevel) + internal static void DrawPreviewTextureInternal(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect, float mipLevel, ColorWriteMask colorWriteMask) { if (Event.current.type == EventType.Repaint) { if (imageAspect == 0) imageAspect = image.width / (float)image.height; + Color colorMask = new Color(1, 1, 1, 1); + + if ((colorWriteMask & ColorWriteMask.Red) == 0) + colorMask.r = 0; + if ((colorWriteMask & ColorWriteMask.Green) == 0) + colorMask.g = 0; + if ((colorWriteMask & ColorWriteMask.Blue) == 0) + colorMask.b = 0; + if ((colorWriteMask & ColorWriteMask.Alpha) == 0) + colorMask.a = 0; + if (mat == null) mat = GetMaterialForSpecialTexture(image, colorMaterial); + mat.SetColor("_ColorMask", colorMask); mat.SetFloat("_Mip", mipLevel); RenderTexture rt = image as RenderTexture; @@ -6343,9 +6365,9 @@ public static void DrawTextureAlpha(Rect position, Texture image, ScaleMode scal } // Draws texture transparently using the alpha channel. - public static void DrawTextureTransparent(Rect position, Texture image, [DefaultValue("ScaleMode.StretchToFill")] ScaleMode scaleMode, [DefaultValue("0")] float imageAspect, [DefaultValue("-1")] float mipLevel) + 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) { - DrawTextureTransparentInternal(position, image, scaleMode, imageAspect, mipLevel); + DrawTextureTransparentInternal(position, image, scaleMode, imageAspect, mipLevel, colorWriteMask); } [ExcludeFromDocs] @@ -6360,16 +6382,35 @@ public static void DrawTextureTransparent(Rect position, Texture image) DrawTextureTransparent(position, image, ScaleMode.StretchToFill, 0); } + [ExcludeFromDocs] public static void DrawTextureTransparent(Rect position, Texture image, ScaleMode scaleMode, float imageAspect) { - DrawTextureTransparentInternal(position, image, scaleMode, imageAspect, -1); + DrawTextureTransparent(position, image, scaleMode, imageAspect, -1); + } + + [ExcludeFromDocs] + public static void DrawTextureTransparent(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel) + { + DrawTextureTransparent(position, image, scaleMode, imageAspect, mipLevel, ColorWriteMask.All); } // Draws the texture within a rectangle. public static void DrawPreviewTexture(Rect position, Texture image, [DefaultValue("null")] Material mat, [DefaultValue("ScaleMode.StretchToFill")] ScaleMode scaleMode, - [DefaultValue("0")] float imageAspect, [DefaultValue("-1")] float mipLevel) + [DefaultValue("0")] float imageAspect, [DefaultValue("-1")] float mipLevel, [DefaultValue("ColorWriteMask.All")] ColorWriteMask colorWriteMask) { - DrawPreviewTextureInternal(position, image, mat, scaleMode, imageAspect, mipLevel); + DrawPreviewTextureInternal(position, image, mat, scaleMode, imageAspect, mipLevel, colorWriteMask); + } + + [ExcludeFromDocs] + public static void DrawPreviewTexture(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect, float mipLevel) + { + DrawPreviewTexture(position, image, mat, scaleMode, imageAspect, mipLevel, ColorWriteMask.All); + } + + [ExcludeFromDocs] + public static void DrawPreviewTexture(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect) + { + DrawPreviewTexture(position, image, mat, scaleMode, imageAspect, -1); } [ExcludeFromDocs] @@ -6390,12 +6431,6 @@ public static void DrawPreviewTexture(Rect position, Texture image) DrawPreviewTexture(position, image, null, ScaleMode.StretchToFill, 0); } - [ExcludeFromDocs] - public static void DrawPreviewTexture(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect) - { - DrawPreviewTextureInternal(position, image, mat, scaleMode, imageAspect, -1); - } - [ExcludeFromDocs] public static void LabelField(Rect position, string label) { diff --git a/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs b/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs index f10253d950..7f9efafb9a 100644 --- a/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs +++ b/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs @@ -122,8 +122,8 @@ public void DrawHandle() // handles int prevHotControl = GUIUtility.hotControl; - Vector3 cameraLocalPos = Handles.inverseMatrix.MultiplyPoint(Camera.current.transform.position); - bool isCameraInsideBox = m_Bounds.Contains(cameraLocalPos); + bool isCameraInsideBox = Camera.current != null + && m_Bounds.Contains(Handles.inverseMatrix.MultiplyPoint(Camera.current.transform.position)); EditorGUI.BeginChangeCheck(); using (new Handles.DrawingScope(Handles.color * handleColor)) MidpointHandles(ref minPos, ref maxPos, isCameraInsideBox); diff --git a/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs b/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs index 10c838a157..9bbe0c21c8 100644 --- a/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs +++ b/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs @@ -26,10 +26,12 @@ private static float GetSortingDistance(ArcHandle handle) Vector3 worldPosition = Handles.matrix.MultiplyPoint3x4( Quaternion.AngleAxis(handle.angle, Vector3.up) * Vector3.forward * handle.radius ); - Vector3 toHandle = worldPosition - Camera.current.transform.position; - if (Camera.current.orthographic) + Vector3 toHandle = Camera.current == null + ? worldPosition + : worldPosition - Camera.current.transform.position; + if (Camera.current == null || Camera.current.orthographic) { - Vector3 lookVector = Camera.current.transform.forward; + Vector3 lookVector = Camera.current == null ? Vector3.forward : Camera.current.transform.forward; toHandle = lookVector * Vector3.Dot(lookVector, toHandle); } return toHandle.sqrMagnitude; diff --git a/Editor/Mono/EditorUserBuildSettings.bindings.cs b/Editor/Mono/EditorUserBuildSettings.bindings.cs index 04b6e3a25a..f7bddf49a9 100644 --- a/Editor/Mono/EditorUserBuildSettings.bindings.cs +++ b/Editor/Mono/EditorUserBuildSettings.bindings.cs @@ -626,6 +626,15 @@ public static extern bool switchNVNShaderDebugging set; } + // Enable debug validation of NVN drawcalls + public static extern bool switchNVNDrawValidation + { + [NativeMethod("GetNVNDrawValidation")] + get; + [NativeMethod("SetNVNDrawValidation")] + set; + } + // Enable linkage of the Heap inspector tool for Nintendo Switch. public static extern bool switchEnableHeapInspector { diff --git a/Editor/Mono/EditorUtility.cs b/Editor/Mono/EditorUtility.cs index b197a5a8c8..5ebdd84813 100644 --- a/Editor/Mono/EditorUtility.cs +++ b/Editor/Mono/EditorUtility.cs @@ -198,25 +198,25 @@ public static Object InstantiatePrefab(Object target) return PrefabUtility.InstantiatePrefab(target); } - [Obsolete("Use PrefabUtility.ReplacePrefab", false)] + [Obsolete("Use PrefabUtility.SaveAsPrefabAsset with a path instead.", false)] public static GameObject ReplacePrefab(GameObject go, Object targetPrefab, ReplacePrefabOptions options) { return PrefabUtility.ReplacePrefab(go, targetPrefab, options); } - [Obsolete("Use PrefabUtility.ReplacePrefab", false)] + [Obsolete("Use PrefabUtility.SaveAsPrefabAsset or PrefabUtility.SaveAsPrefabAssetAndConnect with a path instead.", false)] public static GameObject ReplacePrefab(GameObject go, Object targetPrefab) { return PrefabUtility.ReplacePrefab(go, targetPrefab, ReplacePrefabOptions.Default); } - [Obsolete("Use PrefabUtility.CreateEmptyPrefab", false)] + [Obsolete("The concept of creating a completely empty Prefab has been discontinued. You can however use PrefabUtility.SaveAsPrefabAsset with an empty GameObject.", false)] public static Object CreateEmptyPrefab(string path) { return PrefabUtility.CreateEmptyPrefab(path); } - [Obsolete("Use PrefabUtility.RevertPrefabInstance", false)] + [Obsolete("Use PrefabUtility.RevertPrefabInstance.", false)] public static bool ReconnectToLastPrefab(GameObject go) { return PrefabUtility.ReconnectToLastPrefab(go); @@ -240,7 +240,7 @@ public static GameObject FindPrefabRoot(GameObject source) return PrefabUtility.FindPrefabRoot(source); } - [Obsolete("Use PrefabUtility.ResetToPrefabState", false)] + [Obsolete("Use PrefabUtility.RevertObjectOverride.", false)] public static bool ResetToPrefabState(Object source) { return PrefabUtility.ResetToPrefabState(source); diff --git a/Editor/Mono/EditorWindow.cs b/Editor/Mono/EditorWindow.cs index 1b17962e0f..00590ec4be 100644 --- a/Editor/Mono/EditorWindow.cs +++ b/Editor/Mono/EditorWindow.cs @@ -478,8 +478,18 @@ public void ShowUtility() ShowWithMode(ShowMode.Utility); } - // Used for popup style windows. + internal void ShowTooltip() + { + ShowPopupWithMode(ShowMode.Tooltip); + } + public void ShowPopup() + { + ShowPopupWithMode(ShowMode.PopupMenu); + } + + // Used for popup style windows. + internal void ShowPopupWithMode(ShowMode mode) { if (m_Parent == null) { @@ -494,7 +504,7 @@ public void ShowPopup() cw.position = r; cw.rootView = host; MakeParentsSettingsMatchMe(); - cw.ShowPopup(); + cw.ShowPopupWithMode(mode); } } @@ -531,7 +541,7 @@ public void ShowAsDropDown(Rect buttonRect, Vector2 windowSize) internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocation[] locationPriorityOrder) { - ShowAsDropDown(buttonRect, windowSize, locationPriorityOrder, ShowMode.PopupMenuWithKeyboardFocus); + ShowAsDropDown(buttonRect, windowSize, locationPriorityOrder, ShowMode.PopupMenu); } internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocation[] locationPriorityOrder, ShowMode mode) @@ -550,9 +560,9 @@ internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocation[ position = ShowAsDropDownFitToScreen(buttonRect, windowSize, locationPriorityOrder); // ShowWithMode() always grabs window focus so we use ShowPopup() for popup windows so PopupWindowWithoutFocus - // will work correctly (no focus when opened) - if (ContainerWindow.IsPopup(mode) && mode != ShowMode.PopupMenuWithKeyboardFocus) - ShowPopup(); + // will work correctly (no focus when opened). + if (ContainerWindow.IsPopup(mode)) + ShowPopupWithMode(mode); else ShowWithMode(mode); diff --git a/Editor/Mono/GI/LightmapEditorSettings.bindings.cs b/Editor/Mono/GI/LightmapEditorSettings.bindings.cs index 4f841a6632..2a28803785 100644 --- a/Editor/Mono/GI/LightmapEditorSettings.bindings.cs +++ b/Editor/Mono/GI/LightmapEditorSettings.bindings.cs @@ -29,8 +29,11 @@ public enum Lightmapper [Obsolete("Use Lightmapper.ProgressiveCPU instead. (UnityUpgradable) -> UnityEditor.LightmapEditorSettings/Lightmapper.ProgressiveCPU", true)] PathTracer = 1, - // Lightmaps are baked by the Progressive lightmapper (Wintermute + OpenRL based). - ProgressiveCPU = 1 + // Lightmaps are baked by the CPU Progressive lightmapper (Wintermute + OpenRL based). + ProgressiveCPU = 1, + + // Lightmaps are baked by the GPU Progressive lightmapper (RadeonRays + OpenCL based). + ProgressiveGPU = 2 } // Which path tracer sampling scheme is used. diff --git a/Editor/Mono/GUI/ColorPicker.cs b/Editor/Mono/GUI/ColorPicker.cs index 453514fc52..d2ef8314f7 100644 --- a/Editor/Mono/GUI/ColorPicker.cs +++ b/Editor/Mono/GUI/ColorPicker.cs @@ -570,7 +570,7 @@ void DoColorSwatchAndEyedropper() if (GUILayout.Button(Styles.eyeDropper, GUIStyle.none, GUILayout.Width(40), GUILayout.ExpandWidth(false))) { GUIUtility.keyboardControl = 0; - EyeDropper.Start(m_Parent, false); + EyeDropper.Start(m_Parent); m_ColorBoxMode = ColorBoxMode.EyeDropper; GUIUtility.ExitGUI(); } @@ -958,6 +958,15 @@ void OnGUI() } } + // Cancel EyeDropper if we change focus. + if (m_ColorBoxMode == ColorBoxMode.EyeDropper && + Event.current.type == EventType.ExecuteCommand && + Event.current.commandName == EventCommandNames.NewKeyboardFocus) + { + EyeDropper.End(); + OnEyedropperCancelled(); + } + // Remove keyfocus when clicked outside any control if ((Event.current.type == EventType.MouseDown && Event.current.button != 1) || Event.current.type == EventType.ContextClick) { @@ -1229,17 +1238,17 @@ internal class EyeDropper : GUIView private bool m_Focused = false; private Action m_ColorPickedCallback; - public static void Start(GUIView viewToUpdate, bool stealFocus = true) + public static void Start(GUIView viewToUpdate) { - Start(viewToUpdate, null, stealFocus); + Start(viewToUpdate, null); } - public static void Start(Action colorPickedCallback, bool stealFocus = true) + public static void Start(Action colorPickedCallback) { - Start(null, colorPickedCallback, stealFocus); + Start(null, colorPickedCallback); } - static void Start(GUIView viewToUpdate, Action colorPickedCallback, bool stealFocus) + static void Start(GUIView viewToUpdate, Action colorPickedCallback) { instance.m_DelegateView = viewToUpdate; instance.m_ColorPickedCallback = colorPickedCallback; @@ -1255,8 +1264,6 @@ static void Start(GUIView viewToUpdate, Action colorPickedCallback, bool win.position = new Rect(-kDummyWindowSize / 2, -kDummyWindowSize / 2, kDummyWindowSize, kDummyWindowSize); instance.wantsMouseMove = true; instance.StealMouseCapture(); - if (stealFocus) - instance.Focus(); } public static void End() diff --git a/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs b/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs index b060fcdea7..8cdfc53eb2 100644 --- a/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs +++ b/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs @@ -243,7 +243,7 @@ void CreateNewItemButton(Rect itemRect) SelectItem(newIndex); EditorApplication.RequestRepaintAllViews(); // We want to repaint the flexible menu (currently in modifyItemUI) }); - PopupWindow.Show(plusRect, m_ModifyItemUI, null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(plusRect, m_ModifyItemUI); } } @@ -261,7 +261,7 @@ void EditExistingItem(Rect itemRect, int index) m_ItemProvider.Replace(index, obj); EditorApplication.RequestRepaintAllViews(); // We want to repaint the flexible menu (currently in modifyItemUI) }); - PopupWindow.Show(itemRect, m_ModifyItemUI, null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(itemRect, m_ModifyItemUI); } void DeleteItem(int index) diff --git a/Editor/Mono/GUI/Toolbar.cs b/Editor/Mono/GUI/Toolbar.cs index 22e979d006..12cebecd4d 100644 --- a/Editor/Mono/GUI/Toolbar.cs +++ b/Editor/Mono/GUI/Toolbar.cs @@ -137,6 +137,7 @@ protected override void OnDisable() public static Toolbar get = null; public static bool requestShowCollabToolbar = false; + public static bool isLastShowRequestPartial = true; internal static string lastLoadedLayoutName { diff --git a/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs b/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs index 26f2ba9e37..1182c65d9d 100644 --- a/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs +++ b/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs @@ -208,10 +208,6 @@ void CreateRootItem(HierarchyProperty property) // All game objects m_RootItem = new GameObjectTreeViewItem(m_RootInstanceID, rootDepth, null, "RootOfAll"); } - - // Ensure root is expanded if not shown - if (!showRootItem) - SetExpanded(m_RootItem, true); } void ClearSearchFilter() diff --git a/Editor/Mono/GUI/WindowLayout.cs b/Editor/Mono/GUI/WindowLayout.cs index 7ce55f3e21..047ce599c4 100644 --- a/Editor/Mono/GUI/WindowLayout.cs +++ b/Editor/Mono/GUI/WindowLayout.cs @@ -356,10 +356,13 @@ internal static void MaximizeKeyHandler(ShortcutArguments args) var mouseOverWindow = EditorWindow.mouseOverWindow; - if (IsMaximized(mouseOverWindow)) - Unmaximize(mouseOverWindow); - else - Maximize(mouseOverWindow); + if (mouseOverWindow != null) + { + if (IsMaximized(mouseOverWindow)) + Unmaximize(mouseOverWindow); + else + Maximize(mouseOverWindow); + } } public static void AddSplitViewAndChildrenRecurse(View splitview, ArrayList list) diff --git a/Editor/Mono/GameView/GameViewSizes.cs b/Editor/Mono/GameView/GameViewSizes.cs index 6a326192d2..72b896eda3 100644 --- a/Editor/Mono/GameView/GameViewSizes.cs +++ b/Editor/Mono/GameView/GameViewSizes.cs @@ -239,9 +239,10 @@ private void InitBuiltinGroups() k_4_3_Landscape, k_4_3_Portrait, k_iPhone4_Portrait, k_iPhone4_Landscape, k_iPhone5_Portrait, k_iPhone5_Landscape, - k_iPad_768p_Landscape, k_iPad_768p_Portrait); + k_iPad_768p_Landscape, k_iPad_768p_Portrait, + m_Remote); - m_Android.AddBuiltinSizes(kFree, m_Remote, + m_Android.AddBuiltinSizes(kFree, k_800x480_Portrait, k_800x480_Landscape, k_720p_Portrait, k_720p_Landscape, k_1080p_Portrait, k_1080p_Landscape, @@ -249,7 +250,8 @@ private void InitBuiltinGroups() k_2560x1440_Portrait, k_2560x1440_Landscape, k_2960x1440_Portrait, k_2960x1440_Landscape, k_16_9_Portrait, k_16_9_Landscape, - k_18_9_Portrait, k_18_9_Landscape); + k_18_9_Portrait, k_18_9_Landscape, + m_Remote); m_HMD.AddBuiltinSizes(kFree, m_Remote); } diff --git a/Editor/Mono/HandleUtility.cs b/Editor/Mono/HandleUtility.cs index 8fc8f52881..2e87d2449c 100644 --- a/Editor/Mono/HandleUtility.cs +++ b/Editor/Mono/HandleUtility.cs @@ -26,7 +26,7 @@ public static float CalcLineTranslation(Vector2 src, Vector2 dest, Vector3 srcPo // The constrained direction is facing towards the camera, THATS BAD when the handle is close to the camera // The srcPosition goes through to the other side of the camera float invert = 1.0F; - Vector3 cameraForward = Camera.current.transform.forward; + Vector3 cameraForward = Camera.current == null ? Vector3.forward : Camera.current.transform.forward; if (Vector3.Dot(constraintDir, cameraForward) < 0.0F) invert = -1.0F; @@ -36,8 +36,13 @@ public static float CalcLineTranslation(Vector2 src, Vector2 dest, Vector3 srcPo Vector3 cd = constraintDir; cd.y = -cd.y; Camera cam = Camera.current; - Vector2 p1 = EditorGUIUtility.PixelsToPoints(cam.WorldToScreenPoint(srcPosition)); - Vector2 p2 = EditorGUIUtility.PixelsToPoints(cam.WorldToScreenPoint(srcPosition + constraintDir * invert)); + // if camera is null, then we are drawing in OnGUI, where y-coordinate goes top-to-bottom + Vector2 p1 = cam == null + ? Vector2.Scale(srcPosition, new Vector2(1f, -1f)) + : EditorGUIUtility.PixelsToPoints(cam.WorldToScreenPoint(srcPosition)); + Vector2 p2 = cam == null + ? Vector2.Scale(srcPosition + constraintDir * invert, new Vector2(1f, -1f)) + : EditorGUIUtility.PixelsToPoints(cam.WorldToScreenPoint(srcPosition + constraintDir * invert)); Vector2 p3 = dest; Vector2 p4 = src; diff --git a/Editor/Mono/Handles.cs b/Editor/Mono/Handles.cs index 4dd97995b5..db89421be6 100644 --- a/Editor/Mono/Handles.cs +++ b/Editor/Mono/Handles.cs @@ -550,8 +550,8 @@ public static void DotHandleCap(int controlID, Vector3 position, Quaternion rota // Only apply matrix to the position because DotCap is camera facing position = matrix.MultiplyPoint(position); - Vector3 sideways = Camera.current.transform.right * size; - Vector3 up = Camera.current.transform.up * size; + Vector3 sideways = (Camera.current == null ? Vector3.right : Camera.current.transform.right) * size; + Vector3 up = (Camera.current == null ? Vector3.up : Camera.current.transform.up) * size; Color col = color * new Color(1, 1, 1, 0.99f); HandleUtility.ApplyWireMaterial(Handles.zTest); diff --git a/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs index 50ceac4111..9cf9bfb61a 100644 --- a/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs +++ b/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs @@ -251,15 +251,27 @@ private void HandleBodyView(int bodyView) Vector2 m_FoldoutScroll = Vector2.zero; - public override void OnInspectorGUI() + private void SetupInternalProperties() + { + m_HumanBoneArray = serializedObject.FindProperty("m_HumanDescription.m_Human"); + m_Skeleton = serializedObject.FindProperty("m_HumanDescription.m_Skeleton"); + } + + private void HandleUndoPerformed() { if (Event.current.type == EventType.ValidateCommand && Event.current.commandName == EventCommandNames.UndoRedoPerformed) { + SetupInternalProperties(); + AvatarSetupTool.TransferPoseToDescription(m_Skeleton, root); for (int i = 0; i < m_Bones.Length; i++) m_Bones[i].Serialize(m_HumanBoneArray); } + } + public override void OnInspectorGUI() + { + HandleUndoPerformed(); UpdateSelectedBone(); // case 837655. GUI.keyboardControl is overriden when changing scene selection. diff --git a/Editor/Mono/Inspector/CameraEditor.cs b/Editor/Mono/Inspector/CameraEditor.cs index 1cd244ae15..81e164090d 100644 --- a/Editor/Mono/Inspector/CameraEditor.cs +++ b/Editor/Mono/Inspector/CameraEditor.cs @@ -213,7 +213,7 @@ public void DrawProjection() GUIContent content = EditorGUI.BeginProperty(EditorGUILayout.BeginHorizontal(), Styles.fieldOfView, fieldOfView); EditorGUI.BeginDisabled(projectionMatrixMode.hasMultipleDifferentValues || isPhysicalCamera && (focalLength.hasMultipleDifferentValues || sensorSize.hasMultipleDifferentValues)); EditorGUI.BeginChangeCheck(); - float fovNewValue = EditorGUILayout.Slider(content, fieldOfView.floatValue, 1f, 179f); + float fovNewValue = EditorGUILayout.Slider(content, fieldOfView.floatValue, 0.00001f, 179f); bool fovChanged = EditorGUI.EndChangeCheck(); EditorGUI.EndDisabled(); EditorGUILayout.EndHorizontal(); diff --git a/Editor/Mono/Inspector/LabelGUI.cs b/Editor/Mono/Inspector/LabelGUI.cs index c7b69c305f..7ef70781c2 100644 --- a/Editor/Mono/Inspector/LabelGUI.cs +++ b/Editor/Mono/Inspector/LabelGUI.cs @@ -189,7 +189,7 @@ public void OnLabelGUI(Object[] assets) r.x = widthProbeRect.xMax + labelButton.margin.left; if (EditorGUI.DropdownButton(r, GUIContent.none, FocusType.Passive, labelButton)) { - PopupWindow.Show(r, new PopupList(m_AssetLabels), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(r, new PopupList(m_AssetLabels)); } EditorGUILayout.EndHorizontal(); @@ -209,7 +209,7 @@ private void DrawLabelList(bool partiallySelected, float xMax) { evt.Use(); rt.x = xMax; - PopupWindow.Show(rt, new PopupList(m_AssetLabels, content.text), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(rt, new PopupList(m_AssetLabels, content.text)); } } } diff --git a/Editor/Mono/Inspector/LightingSettingsInspector.cs b/Editor/Mono/Inspector/LightingSettingsInspector.cs index afe116b735..0f5d45dffb 100644 --- a/Editor/Mono/Inspector/LightingSettingsInspector.cs +++ b/Editor/Mono/Inspector/LightingSettingsInspector.cs @@ -56,7 +56,6 @@ static class Styles 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."); public static readonly GUIContent ReceiveShadows = EditorGUIUtility.TrTextContent("Receive Shadows", "When enabled, any shadows cast from other objects are drawn on the geometry."); 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."); - public static readonly GUIContent LightmapInfoBox = EditorGUIUtility.TrTextContent("To enable generation of lightmaps for this Mesh Renderer, please enable the 'Lightmap Static' property."); public static readonly GUIContent TerrainLightmapInfoBox = EditorGUIUtility.TrTextContent("To enable generation of lightmaps for this Mesh Renderer, please enable the 'Lightmap Static' property."); 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."); @@ -157,13 +156,20 @@ public void RenderMeshSettings(bool showLightmapSettings) m_GameObjectsSerializedObject.Update(); m_LightmapSettings.Update(); - EditorGUILayout.PropertyField(m_CastShadows, Styles.CastShadows, true); + // TODO(RadeonRays): remove if GPU lightmapper once the feature has been implemented. + if (LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.PropertyField(m_CastShadows, Styles.CastShadows, true); + bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath(); if (SupportedRenderingFeatures.active.rendererSupportsReceiveShadows) { using (new EditorGUI.DisabledScope(isDeferredRenderingPath)) - EditorGUILayout.PropertyField(m_ReceiveShadows, Styles.ReceiveShadows, true); + { + // TODO(RadeonRays): remove if GPU lightmapper once the feature has been implemented. + if (LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.PropertyField(m_ReceiveShadows, Styles.ReceiveShadows, true); + } } if (SupportedRenderingFeatures.active.rendererSupportsMotionVectors) diff --git a/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs b/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs index 77dcd09308..f585af937f 100644 --- a/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs +++ b/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs @@ -163,6 +163,7 @@ public bool DoubleSidedGIField() } else { + // TODO(RadeonRays): change this to (lightmapper == Enlighten) once Double Sided GI works with GPU lightmapper. using (new EditorGUI.DisabledScope(LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveCPU)) EditorGUI.Toggle(r, Styles.doubleSidedGILabel, false); } diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 2c022b45dc..7d97663c9a 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -168,6 +168,7 @@ class SettingsContent public static readonly GUIContent managedStrippingLevel = EditorGUIUtility.TrTextContent("Managed Stripping Level", "If scripting backend is IL2CPP, managed stripping can't be disabled."); public static readonly GUIContent il2cppCompilerConfiguration = EditorGUIUtility.TrTextContent("C++ Compiler Configuration"); public static readonly GUIContent scriptingMono2x = EditorGUIUtility.TrTextContent("Mono"); + public static readonly GUIContent scriptingMono2xDeprecated = EditorGUIUtility.TrTextContent("Mono (Deprecated)"); public static readonly GUIContent scriptingWinRTDotNET = EditorGUIUtility.TrTextContent(".NET"); public static readonly GUIContent scriptingIL2CPP = EditorGUIUtility.TrTextContent("IL2CPP"); public static readonly GUIContent scriptingDefault = EditorGUIUtility.TrTextContent("Default"); @@ -1697,10 +1698,10 @@ private void OtherSectionRenderingGUI(BuildPlatform platform, BuildTargetGroup t EditorGUI.BeginChangeCheck(); LightmapEncodingQuality encodingQuality = PlayerSettings.GetLightmapEncodingQualityForPlatformGroup(targetGroup); LightmapEncodingQuality[] lightmapEncodingValues = {LightmapEncodingQuality.Normal, LightmapEncodingQuality.High}; - encodingQuality = BuildEnumPopup(SettingsContent.lightmapEncodingLabel, encodingQuality, lightmapEncodingValues, SettingsContent.lightmapEncodingNames); - if (EditorGUI.EndChangeCheck()) + LightmapEncodingQuality newEncodingQuality = BuildEnumPopup(SettingsContent.lightmapEncodingLabel, encodingQuality, lightmapEncodingValues, SettingsContent.lightmapEncodingNames); + if (EditorGUI.EndChangeCheck() && encodingQuality != newEncodingQuality) { - PlayerSettings.SetLightmapEncodingQualityForPlatformGroup(targetGroup, encodingQuality); + PlayerSettings.SetLightmapEncodingQualityForPlatformGroup(targetGroup, newEncodingQuality); Lightmapping.OnUpdateLightmapEncoding(targetGroup); @@ -1961,6 +1962,7 @@ private void OtherSectionConfigurationGUI(BuildTargetGroup targetGroup, ISetting ScriptingImplementation currBackend = PlayerSettings.GetScriptingBackend(targetGroup); currentBackendIsIl2Cpp = currBackend == ScriptingImplementation.IL2CPP; ScriptingImplementation newBackend; + var mono2xDeprecated = targetGroup == BuildTargetGroup.iOS; if (targetGroup == BuildTargetGroup.tvOS) { @@ -1970,11 +1972,11 @@ private void OtherSectionConfigurationGUI(BuildTargetGroup targetGroup, ISetting else if (backends.Length == 1) { newBackend = backends[0]; - BuildDisabledEnumPopup(GetNiceScriptingBackendName(backends[0]), SettingsContent.scriptingBackend); + BuildDisabledEnumPopup(GetNiceScriptingBackendName(backends[0], mono2xDeprecated), SettingsContent.scriptingBackend); } else { - newBackend = BuildEnumPopup(SettingsContent.scriptingBackend, currBackend, backends, GetNiceScriptingBackendNames(backends)); + newBackend = BuildEnumPopup(SettingsContent.scriptingBackend, currBackend, backends, GetNiceScriptingBackendNames(backends, mono2xDeprecated)); } if (targetGroup == BuildTargetGroup.iOS && newBackend == ScriptingImplementation.Mono2x) @@ -2313,7 +2315,6 @@ private void OtherSectionLegacyGUI() EditorGUILayout.Space(); } - private static Dictionary m_NiceScriptingBackendNames; private static Dictionary m_NiceApiCompatibilityLevelNames; private static Dictionary m_NiceManagedStrippingLevelNames; @@ -2331,31 +2332,26 @@ private static GUIContent[] GetGUIContentsForValues(Dictionary return names; } - private static GUIContent[] GetNiceScriptingBackendNames(ScriptingImplementation[] scriptingBackends) + static GUIContent[] GetNiceScriptingBackendNames(ScriptingImplementation[] scriptingBackends, bool mono2xDeprecated) { - InitializeNiceScriptingBackendNames(); - return GetGUIContentsForValues(m_NiceScriptingBackendNames, scriptingBackends); + return scriptingBackends.Select(s => GetNiceScriptingBackendName(s, mono2xDeprecated)).ToArray(); } - static void InitializeNiceScriptingBackendNames() + static GUIContent GetNiceScriptingBackendName(ScriptingImplementation scriptingBackend, bool mono2xDeprecated) { - if (m_NiceScriptingBackendNames == null) + switch (scriptingBackend) { - m_NiceScriptingBackendNames = new Dictionary - { - { ScriptingImplementation.Mono2x, SettingsContent.scriptingMono2x }, - { ScriptingImplementation.WinRTDotNET, SettingsContent.scriptingWinRTDotNET }, - { ScriptingImplementation.IL2CPP, SettingsContent.scriptingIL2CPP } - }; + case ScriptingImplementation.Mono2x: + return mono2xDeprecated ? SettingsContent.scriptingMono2xDeprecated : SettingsContent.scriptingMono2x; + case ScriptingImplementation.IL2CPP: + return SettingsContent.scriptingIL2CPP; + case ScriptingImplementation.WinRTDotNET: + return SettingsContent.scriptingWinRTDotNET; + default: + throw new ArgumentException($"Scripting backend value {scriptingBackend} is not supported.", nameof(scriptingBackend)); } } - private static GUIContent GetNiceScriptingBackendName(ScriptingImplementation scriptingBackend) - { - InitializeNiceScriptingBackendNames(); - return GetGUIContentsForValues(m_NiceScriptingBackendNames, new[] { scriptingBackend }).First(); - } - private static GUIContent[] GetNiceApiCompatibilityLevelNames(ApiCompatibilityLevel[] apiCompatibilityLevels) { if (m_NiceApiCompatibilityLevelNames == null) diff --git a/Editor/Mono/Inspector/RectTransformEditor.cs b/Editor/Mono/Inspector/RectTransformEditor.cs index 3ee6543a67..a98c23be5b 100644 --- a/Editor/Mono/Inspector/RectTransformEditor.cs +++ b/Editor/Mono/Inspector/RectTransformEditor.cs @@ -298,7 +298,7 @@ void LayoutDropdownButton(bool anyWithoutParent) { GUIUtility.keyboardControl = 0; m_DropdownWindow = new LayoutDropdownWindow(serializedObject); - PopupWindow.Show(dropdownPosition, m_DropdownWindow, null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(dropdownPosition, m_DropdownWindow); } GUI.color = oldColor; } diff --git a/Editor/Mono/Inspector/TagManagerInspector.cs b/Editor/Mono/Inspector/TagManagerInspector.cs index 4d6d4b4f38..b4548b6da4 100644 --- a/Editor/Mono/Inspector/TagManagerInspector.cs +++ b/Editor/Mono/Inspector/TagManagerInspector.cs @@ -175,7 +175,7 @@ void NewElement(Rect buttonRect, ReorderableList list) { buttonRect.x -= 400; buttonRect.y -= 13; - PopupWindow.Show(buttonRect, new EnterNamePopup(m_Tags, s => { InternalEditorUtility.AddTag(s); }), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(buttonRect, new EnterNamePopup(m_Tags, s => { InternalEditorUtility.AddTag(s); })); } private void RemoveFromTagsList(ReorderableList list) diff --git a/Editor/Mono/Inspector/TextureInspector.cs b/Editor/Mono/Inspector/TextureInspector.cs index 86ba109b6e..ab99053c9b 100644 --- a/Editor/Mono/Inspector/TextureInspector.cs +++ b/Editor/Mono/Inspector/TextureInspector.cs @@ -2,8 +2,10 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System.Collections.Generic; using UnityEngine; using UnityEditor; +using UnityEngine.Rendering; namespace UnityEditor @@ -48,8 +50,9 @@ internal class TextureInspector : Editor { class Styles { - public GUIContent smallZoom, largeZoom, alphaIcon, RGBIcon; + public GUIContent smallZoom, largeZoom; public GUIStyle previewButton, previewSlider, previewSliderThumb, previewLabel; + public GUIStyle previewButtonRed, previewButtonGreen, previewButtonBlue; public readonly GUIContent wrapModeLabel = EditorGUIUtility.TrTextContent("Wrap Mode"); public readonly GUIContent wrapU = EditorGUIUtility.TrTextContent("U axis"); @@ -77,9 +80,11 @@ public Styles() { smallZoom = EditorGUIUtility.IconContent("PreTextureMipMapLow"); largeZoom = EditorGUIUtility.IconContent("PreTextureMipMapHigh"); - alphaIcon = EditorGUIUtility.IconContent("PreTextureAlpha"); - RGBIcon = EditorGUIUtility.IconContent("PreTextureRGB"); + previewButton = "preButton"; + previewButtonRed = "preButtonRed"; + previewButtonGreen = "preButtonGreen"; + previewButtonBlue = "preButtonBlue"; previewSlider = "preSlider"; previewSliderThumb = "preSliderThumb"; previewLabel = "preLabelUpper"; @@ -87,8 +92,20 @@ public Styles() } static Styles s_Styles; - private bool m_ShowAlpha; - public bool showAlpha { get { return m_ShowAlpha; } } + enum PreviewMode + { + RGB, + R, + G, + B, + A, + }; + + private PreviewMode m_PreviewMode = PreviewMode.RGB; + public bool showAlpha + { + get { return m_PreviewMode == PreviewMode.A; } + } // Plain Texture protected SerializedProperty m_WrapU; @@ -410,7 +427,6 @@ public override void OnPreviewSettings() // and while it's being shown the actual texture object might disappear -- // make sure to handle null targets. Texture tex = target as Texture; - bool showMode = true; bool alphaOnly = false; bool hasAlpha = true; int mipCount = 1; @@ -448,19 +464,53 @@ public override void OnPreviewSettings() mipCount = Mathf.Max(mipCount, TextureUtil.GetMipmapCount(t)); } + + List previewCandidates = new List(5); + previewCandidates.Add(PreviewMode.RGB); + previewCandidates.Add(PreviewMode.R); + previewCandidates.Add(PreviewMode.G); + previewCandidates.Add(PreviewMode.B); + previewCandidates.Add(PreviewMode.A); + if (alphaOnly) { - m_ShowAlpha = true; - showMode = false; + previewCandidates.Clear(); + previewCandidates.Add(PreviewMode.A); + m_PreviewMode = PreviewMode.A; } else if (!hasAlpha) { - m_ShowAlpha = false; - showMode = false; + previewCandidates.Remove(PreviewMode.A); } - if (showMode && tex != null && !IsNormalMap(tex)) - m_ShowAlpha = GUILayout.Toggle(m_ShowAlpha, m_ShowAlpha ? s_Styles.alphaIcon : s_Styles.RGBIcon, s_Styles.previewButton); + + if (previewCandidates.Count > 1 && tex != null && !IsNormalMap(tex)) + { + int selectedIndex = previewCandidates.IndexOf(m_PreviewMode); + if (selectedIndex == -1) + selectedIndex = 0; + + if (previewCandidates.Contains(PreviewMode.RGB)) + m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.RGB, "RGB", s_Styles.previewButton) + ? PreviewMode.RGB + : m_PreviewMode; + if (previewCandidates.Contains(PreviewMode.R)) + m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.R, "R", s_Styles.previewButtonRed) + ? PreviewMode.R + : m_PreviewMode; + if (previewCandidates.Contains(PreviewMode.G)) + m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.G, "G", s_Styles.previewButtonGreen) + ? PreviewMode.G + : m_PreviewMode; + if (previewCandidates.Contains(PreviewMode.B)) + m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.B, "B", s_Styles.previewButtonBlue) + ? PreviewMode.B + : m_PreviewMode; + if (previewCandidates.Contains(PreviewMode.A)) + m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.A, "A", s_Styles.previewButton) + ? PreviewMode.A + : m_PreviewMode; + } if (mipCount > 1) { @@ -512,14 +562,33 @@ public override void OnPreviewGUI(Rect r, GUIStyle background) PreviewGUI.BeginScrollView(r, m_Pos, wantedRect, "PreHorizontalScrollbar", "PreHorizontalScrollbarThumb"); FilterMode oldFilter = t.filterMode; TextureUtil.SetFilterModeNoDirty(t, FilterMode.Point); - Texture2D t2d = t as Texture2D; - if (m_ShowAlpha) + ColorWriteMask colorWriteMask = ColorWriteMask.All; + + switch (m_PreviewMode) + { + case PreviewMode.R: + colorWriteMask = ColorWriteMask.Red | ColorWriteMask.Alpha; + break; + case PreviewMode.G: + colorWriteMask = ColorWriteMask.Green | ColorWriteMask.Alpha; + break; + case PreviewMode.B: + colorWriteMask = ColorWriteMask.Blue | ColorWriteMask.Alpha; + break; + } + + if (m_PreviewMode == PreviewMode.A) + { EditorGUI.DrawTextureAlpha(wantedRect, t, ScaleMode.StretchToFill, 0, mipLevel); - else if (t2d != null && t2d.alphaIsTransparency) - EditorGUI.DrawTextureTransparent(wantedRect, t, ScaleMode.StretchToFill, 0, mipLevel); + } else - EditorGUI.DrawPreviewTexture(wantedRect, t, null, ScaleMode.StretchToFill, 0, mipLevel); + { + if (t2d != null && t2d.alphaIsTransparency) + EditorGUI.DrawTextureTransparent(wantedRect, t, ScaleMode.StretchToFill, 0, mipLevel, colorWriteMask); + else + EditorGUI.DrawPreviewTexture(wantedRect, t, null, ScaleMode.StretchToFill, 0, mipLevel, colorWriteMask); + } // TODO: Less hacky way to prevent sprite rects to not appear in smaller previews like icons. if (wantedRect.width > 32 && wantedRect.height > 32) diff --git a/Editor/Mono/LookDevView/LookDevView.cs b/Editor/Mono/LookDevView/LookDevView.cs index ceadf35366..4709caf02b 100644 --- a/Editor/Mono/LookDevView/LookDevView.cs +++ b/Editor/Mono/LookDevView/LookDevView.cs @@ -1676,7 +1676,7 @@ private void HandleDragging() } GameObject go = o as GameObject; - if (go && EditorUtility.IsPersistent(go) && PrefabUtility.GetPrefabObject(go) != null) + if (go && EditorUtility.IsPersistent(go) && PrefabUtility.IsPartOfPrefabAsset(go)) { if (GameObjectInspector.HasRenderableParts(go)) { diff --git a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs index 7953e088d2..499f70164c 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs @@ -30,6 +30,7 @@ public sealed partial class PrefabUtility extern private static Object GetCorrespondingObjectFromSourceAtPath_internal([NotNull] Object obj, string prefabAssetPath); // Retrieves the prefab object representation. + [Obsolete("Use GetPrefabInstanceHandle for Prefab instances. Handles for Prefab Assets has been discontinued.")] [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] extern public static Object GetPrefabObject(Object targetObject); @@ -72,6 +73,7 @@ public sealed partial class PrefabUtility extern public static void MergeAllPrefabInstances(Object targetObject); // Disconnects the prefab instance from its parent prefab. + [Obsolete("The concept of disconnecting Prefab instances has been deprecated.")] [FreeFunction] extern public static void DisconnectPrefabInstance(Object targetObject); @@ -88,6 +90,7 @@ public sealed partial class PrefabUtility extern public static void LoadPrefabContentsIntoPreviewScene(string prefabPath, Scene scene); // Connect the source prefab to the game object, which replaces the instance content with the content of the prefab + [Obsolete("Use RevertPrefabInstance. Prefabs instances can no longer be connected to Prefab Assets they are not an instance of to begin with.")] [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] [NativeThrows] extern public static GameObject ConnectGameObjectToPrefab([NotNull] GameObject go, [NotNull] GameObject sourcePrefab); @@ -105,26 +108,35 @@ public sealed partial class PrefabUtility // Connects the game object to the prefab that it was last connected to. [FreeFunction] + [Obsolete("Use RevertPrefabInstance.")] extern public static bool ReconnectToLastPrefab(GameObject go); // Resets the properties of the component or game object to the parent prefab state + [Obsolete("Use RevertObjectOverride.")] [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] extern public static bool ResetToPrefabState(Object obj); + // Resets the properties of the component or game object to the parent prefab state + [NativeMethod("PrefabUtilityBindings::ResetToPrefabState", IsFreeFunction = true)] + extern private static bool RevertObjectOverride_Internal(Object obj); + [FreeFunction] extern public static bool IsAddedComponentOverride([NotNull] Object component); // Resets the properties of all objects in the prefab, including child game objects and components that were added to the prefab instance + [Obsolete("Use the overload that takes an InteractionMode parameter.")] [FreeFunction] extern public static bool RevertPrefabInstance([NotNull] GameObject go); + // Resets the properties of all objects in the prefab, including child game objects and components that were added to the prefab instance + [NativeMethod("RevertPrefabInstance", IsFreeFunction = true)] + extern private static bool RevertPrefabInstance_Internal([NotNull] GameObject go); + // Helper function to find the prefab root of an object [FreeFunction] [Obsolete("Use GetOutermostPrefabInstanceRoot if source is a Prefab instance or source.transform.root.gameObject if source is a Prefab Asset object.")] extern public static GameObject FindPrefabRoot([NotNull] GameObject source); -#pragma warning disable 0618 // Type or member is obsolete - internal static GameObject CreateVariant(GameObject assetRoot, string path) { if (assetRoot == null) @@ -146,11 +158,16 @@ internal static GameObject CreateVariant(GameObject assetRoot, string path) if (!Paths.IsValidAssetPath(path, ".prefab")) throw new ArgumentException("Given path is not valid: '" + path + "'"); +#pragma warning disable 0618 // Type or member is obsolete return CreateVariant_Internal(assetRoot, path, ReplacePrefabOptions.Default); +#pragma warning restore 0618 // Type or member is obsolete } + // TODO: Having an non-obsolete method that takes an obsolete enum types as parameter is no good. [NativeMethod("CreateVariant", IsFreeFunction = true)] +#pragma warning disable 0618 // Type or member is obsolete extern private static GameObject CreateVariant_Internal([NotNull] GameObject original, string path, ReplacePrefabOptions replaceOptions); +#pragma warning restore 0618 // Type or member is obsolete private enum PrefabCreationFlags { @@ -158,6 +175,8 @@ private enum PrefabCreationFlags CreateVariant = 1, } + // TODO: Having an non-obsolete method that takes an obsolete enum types as parameter is no good. +#pragma warning disable 0618 // Type or member is obsolete private static GameObject SavePrefab(GameObject inputObject, string path, ReplacePrefabOptions replaceOptions, PrefabCreationFlags creationFlags) { if (inputObject == null) @@ -175,13 +194,17 @@ private static GameObject SavePrefab(GameObject inputObject, string path, Replac throw new ArgumentException("Given path does not exist: '" + path + "'"); string prefabGUID = AssetDatabase.AssetPathToGUID(path); - if (!VerifyNestingFromScript(new GameObject[] {inputObject}, prefabGUID, PrefabUtility.GetPrefabObject(inputObject))) + if (!VerifyNestingFromScript(new GameObject[] {inputObject}, prefabGUID, PrefabUtility.GetPrefabInstanceHandle(inputObject))) throw new ArgumentException("Cyclic nesting detected"); return SavePrefab_Internal(inputObject, path, replaceOptions, creationFlags); } +#pragma warning restore 0618 // Type or member is obsolete + + // TODO: Having an non-obsolete method that takes an obsolete enum types as parameter is no good. [NativeMethod("SavePrefab", IsFreeFunction = true)] +#pragma warning disable 0618 // Type or member is obsolete extern private static GameObject SavePrefab_Internal([NotNull] GameObject root, string path, ReplacePrefabOptions replaceOptions, PrefabCreationFlags createOptions); #pragma warning restore 0618 // Type or member is obsolete @@ -201,7 +224,7 @@ internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, Object targetPrefabInstance = null; - var targetPrefabObject = PrefabUtility.GetPrefabObject(targetPrefab); + var targetPrefabObject = PrefabUtility.GetPrefabAssetHandle(targetPrefab); foreach (GameObject go in gameObjects) { @@ -232,7 +255,7 @@ internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, if (PrefabUtility.IsPartOfNonAssetPrefabInstance(go)) { var correspondingGO = PrefabUtility.GetCorrespondingObjectFromSource(go); - var correspondingGOPrefabObject = PrefabUtility.GetPrefabObject(correspondingGO); + var correspondingGOPrefabObject = PrefabUtility.GetPrefabAssetHandle(correspondingGO); if (targetPrefabObject == correspondingGOPrefabObject) throw new ArgumentException("GameObject is already part of target prefab"); } @@ -299,6 +322,11 @@ internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, [FreeFunction] extern public static bool IsPartOfVariantPrefab([NotNull] Object componentOrGameObject); + // Returns true if the object is from a Prefab Asset which is not editable, or an instance of such a Prefab + // Examples are Model Prefabs and Prefabs in read-only folders. + [FreeFunction] + extern public static bool IsPartOfImmutablePrefab([NotNull] Object componentOrGameObject); + [FreeFunction] extern public static bool IsDisconnectedFromPrefabAsset([NotNull] Object componentOrGameObject); diff --git a/Editor/Mono/Prefabs/PrefabUtility.cs b/Editor/Mono/Prefabs/PrefabUtility.cs index 8279a9f737..869694c941 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.cs @@ -296,10 +296,7 @@ public static void RevertPrefabInstance(GameObject instanceRoot, InteractionMode CheckInstanceIsNotPersistent(instanceRoot); - // The concept of disconnecting are being deprecated. For now use FindRootGameObjectWithSameParentPrefab - // to re-connect existing disconnected prefabs. - #pragma warning disable 0618 // Type or member is obsolete - GameObject prefabInstanceRoot = FindRootGameObjectWithSameParentPrefab(instanceRoot); + GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot); var actionName = "Revert Prefab Instance"; HashSet hierarchy = null; @@ -313,13 +310,13 @@ public static void RevertPrefabInstance(GameObject instanceRoot, InteractionMode if (isDisconnected) { - ReconnectToLastPrefab(prefabInstanceRoot); + RevertPrefabInstance_Internal(prefabInstanceRoot); if (action == InteractionMode.UserAction) Undo.RegisterCreatedObjectUndo(GetPrefabInstanceHandle(prefabInstanceRoot), actionName); } - RevertPrefabInstance(prefabInstanceRoot); + RevertPrefabInstance_Internal(prefabInstanceRoot); if (action == InteractionMode.UserAction) { @@ -333,10 +330,7 @@ public static void ApplyPrefabInstance(GameObject instanceRoot, InteractionMode CheckInstanceIsNotPersistent(instanceRoot); - // The concept of disconnecting are being deprecated. For now use FindRootGameObjectWithSameParentPrefab - // to re-connect existing disconnected prefabs. - #pragma warning disable 0618 // Type or member is obsolete - GameObject prefabInstanceRoot = FindRootGameObjectWithSameParentPrefab(instanceRoot); + GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot); var actionName = "Apply instance to prefab"; Object correspondingSourceObject = GetCorrespondingObjectFromSource(prefabInstanceRoot); @@ -525,7 +519,7 @@ public static void RevertObjectOverride(Object instanceComponentOrGameObject, In if (action == InteractionMode.UserAction) Undo.RegisterCompleteObjectUndo(instanceComponentOrGameObject, "Revert component property overrides"); - PrefabUtility.ResetToPrefabState(instanceComponentOrGameObject); + PrefabUtility.RevertObjectOverride_Internal(instanceComponentOrGameObject); } public static void ApplyAddedComponent(Component component, string assetPath, InteractionMode action) @@ -598,7 +592,7 @@ private static bool IsPrefabInstanceObjectOf(Object instance, Object source) return true; } - if (GetPrefabObject(o) == source) + if (GetPrefabAssetHandle(o) == source) { return true; } @@ -641,7 +635,7 @@ public static void ApplyRemovedComponent(GameObject instanceGameObject, Componen SavePrefabAsset(prefabAsset); } - var prefabInstanceObject = PrefabUtility.GetPrefabObject(instanceGameObject); + var prefabInstanceObject = PrefabUtility.GetPrefabInstanceHandle(instanceGameObject); if (action == InteractionMode.UserAction) Undo.RegisterCompleteObjectUndo(prefabInstanceObject, actionName); @@ -682,7 +676,7 @@ public static void RevertRemovedComponent(GameObject instanceGameObject, Compone CheckInstanceIsNotPersistent(instanceGameObject); var actionName = "Revert Prefab removed component"; - var prefabInstanceObject = PrefabUtility.GetPrefabObject(instanceGameObject); + var prefabInstanceObject = PrefabUtility.GetPrefabInstanceHandle(instanceGameObject); if (action == InteractionMode.UserAction) Undo.RegisterCompleteObjectUndo(instanceGameObject, actionName); @@ -928,7 +922,7 @@ public static Object GetPrefabParent(Object obj) } // Creates an empty prefab at given path. - // TODO Steen Lund 2017 11 28 This needs to be marked OBSOLETE + [Obsolete("The concept of creating a completely empty Prefab has been discontinued. You can however use SaveAsPrefabAsset with an empty GameObject.")] public static Object CreateEmptyPrefab(string path) { // This is here to simulate previous behaviour @@ -944,8 +938,6 @@ public static Object CreateEmptyPrefab(string path) return PrefabUtility.GetPrefabObject(assetObject); } -#pragma warning disable CS0618 // Type or member is obsolete - public static GameObject SavePrefabAsset(GameObject asset) { if (asset == null) @@ -966,7 +958,9 @@ public static GameObject SavePrefabAsset(GameObject asset) if (root != asset) throw new ArgumentException("GameObject to save Prefab from must be a Prefab root"); +#pragma warning disable CS0618 // Type or member is obsolete return SavePrefab(root, path, ReplacePrefabOptions.Default, PrefabCreationFlags.None); +#pragma warning restore CS0618 // Type or member is obsolete } private static void SaveAsPrefabAssetArgumentCheck(GameObject root) @@ -1002,7 +996,9 @@ public static GameObject SaveAsPrefabAsset(GameObject root, string assetPath) if (IsPrefabInstanceRoot(root)) creationFlags = PrefabCreationFlags.CreateVariant; +#pragma warning disable CS0618 // Type or member is obsolete return SavePrefab(root, assetPath, ReplacePrefabOptions.Default, creationFlags); +#pragma warning restore CS0618 // Type or member is obsolete } public static GameObject SaveAsPrefabAssetAndConnect(GameObject root, string assetPath, InteractionMode action) @@ -1020,7 +1016,9 @@ public static GameObject SaveAsPrefabAssetAndConnect(GameObject root, string ass if (IsPrefabInstanceRoot(root)) creationFlags = PrefabCreationFlags.CreateVariant; +#pragma warning disable CS0618 // Type or member is obsolete var assetRoot = SavePrefab(root, assetPath, ReplacePrefabOptions.ConnectToPrefab, creationFlags); +#pragma warning restore CS0618 // Type or member is obsolete if (action == InteractionMode.UserAction) { @@ -1049,7 +1047,7 @@ internal static void ApplyPrefabInstance(GameObject instance) { // The concept of disconnecting are being deprecated. For now use FindRootGameObjectWithSameParentPrefab // to re-connect existing disconnected prefabs. - var validRoot = PrefabUtility.FindValidUploadPrefabInstanceRoot(instance); + var validRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(instance); var ok = validRoot == instance; if (!ok && PrefabUtility.GetCorrespondingObjectFromOriginalSource(instance) != PrefabUtility.GetCorrespondingObjectFromSource(instance)) throw new ArgumentException("Can't save Prefab from an object that originates from a nested Prefab"); @@ -1063,11 +1061,17 @@ internal static void ApplyPrefabInstance(GameObject instance) var assetObject = GetCorrespondingObjectFromSource(instance); string path = AssetDatabase.GetAssetPath(assetObject); + +#pragma warning disable CS0618 // Type or member is obsolete SavePrefab(instance, path, ReplacePrefabOptions.ConnectToPrefab, PrefabCreationFlags.None); +#pragma warning restore CS0618 // Type or member is obsolete } + // TOOO: Remove entirely once regular methods handle merging + // based on both ids and names on a smarter and more granular level. internal static GameObject ReplacePrefabAssetNameBased(GameObject root, string targetPrefab, bool connectToInstance) { +#pragma warning disable CS0618 // Type or member is obsolete var options = ReplacePrefabOptions.ReplaceNameBased; if (connectToInstance) options |= ReplacePrefabOptions.ConnectToPrefab; @@ -1076,8 +1080,7 @@ internal static GameObject ReplacePrefabAssetNameBased(GameObject root, string t if (IsPartOfNonAssetPrefabInstance(root)) { - var instanceRoot = PrefabUtility.GetPrefabInstanceRootGameObject(root); - if (root != instanceRoot) + if (!IsOutermostPrefabInstanceRoot(root)) throw new ArgumentException("Can't replace with part of Prefab instance. Please specify instance root object or a non-instance object."); createOptions = PrefabCreationFlags.CreateVariant; @@ -1087,18 +1090,17 @@ internal static GameObject ReplacePrefabAssetNameBased(GameObject root, string t throw new ArgumentException("Argument connectToInstance is true but root object is an asset not an instance"); return SavePrefab(root, targetPrefab, options, createOptions); - } - #pragma warning restore CS0618 // Type or member is obsolete + } - //[Obsolete("CreatePrefab() has been deprecated. Use SavePrefab() instead (UnityUpgradable) -> SavePrefab(go, path, ReplacePrefabOptions.Default)")] + // Can't use UnityUpgradable since it doesn't currently support swapping parameter order. + [Obsolete("Use SaveAsPrefabAsset instead.")] public static GameObject CreatePrefab(string path, GameObject go) { return SaveAsPrefabAsset(go, path); } - //[Obsolete("CreatePrefab() has been deprecated. Use SavePrefab() instead (UnityUpgradable) -> SavePrefab(go, path, options)")] -#pragma warning disable CS0618 // Type or member is obsolete + [Obsolete("Use SaveAsPrefabAsset or SaveAsPrefabAssetAndConnect instead.")] public static GameObject CreatePrefab(string path, GameObject go, ReplacePrefabOptions options) { if (options == ReplacePrefabOptions.ConnectToPrefab) @@ -1119,11 +1121,13 @@ public static Object InstantiatePrefab(Object assetComponentOrGameObject, Scene return InstantiatePrefab_internal(assetComponentOrGameObject, destinationScene); } + [Obsolete("Use SaveAsPrefabAsset with a path instead.")] public static GameObject ReplacePrefab(GameObject go, Object targetPrefab) { return ReplacePrefab(go, targetPrefab, ReplacePrefabOptions.Default); } + [Obsolete("Use SaveAsPrefabAsset or SaveAsPrefabAssetAndConnect with a path instead.")] public static GameObject ReplacePrefab(GameObject go, Object targetPrefab, ReplacePrefabOptions replaceOptions) { var targetPrefabObject = PrefabUtility.GetPrefabObject(targetPrefab); @@ -1163,8 +1167,6 @@ public static GameObject ReplacePrefab(GameObject go, Object targetPrefab, Repla return SavePrefab(go, assetPath, replaceOptions, PrefabCreationFlags.None); } -#pragma warning restore CS0618 // Type or member is obsolete - // Returns the corresponding object from its immediate source, or null if it can't be found. public static TObject GetCorrespondingObjectFromSource(TObject componentOrGameObject) where TObject : Object { @@ -1211,7 +1213,6 @@ private static Object GetCorrespondingObjectFromOriginalSource_Internal(Object i } // Given an object, returns its prefab type (None, if it's not a prefab) -#pragma warning disable CS0618 // Type or member is obsolete [Obsolete("Use GetPrefabAssetType and GetPrefabInstanceStatus to get the full picture about Prefab types.")] public static PrefabType GetPrefabType(Object target) { @@ -1251,8 +1252,6 @@ public static PrefabType GetPrefabType(Object target) return PrefabType.PrefabInstance; } -#pragma warning restore CS0618 // Type or member is obsolete - // Called after prefab instances in the scene have been updated public delegate void PrefabInstanceUpdated(GameObject instance); public static PrefabInstanceUpdated prefabInstanceUpdated; @@ -1328,7 +1327,7 @@ public static void UnpackPrefabInstance(GameObject root, PrefabUnpackMode unpack if (!IsPartOfNonAssetPrefabInstance(root)) throw new ArgumentException("UnpackPrefabInstance must be called with a Prefab instance."); - if (GetPrefabInstanceRootGameObject(root) != root) + if (!IsOutermostPrefabInstanceRoot(root)) throw new ArgumentException("UnpackPrefabInstance must be called with a root Prefab instance GameObject."); if (action == InteractionMode.UserAction) @@ -1351,24 +1350,6 @@ public static void UnpackPrefabInstance(GameObject root, PrefabUnpackMode unpack } } - public static bool IsPartOfImmutablePrefab(Object gameObjectOrComponent) - { - if (IsPartOfModelPrefab(gameObjectOrComponent)) - return true; - - // If prefab instance, get the prefab asset. - if (!EditorUtility.IsPersistent(gameObjectOrComponent)) - gameObjectOrComponent = GetCorrespondingObjectFromSource(gameObjectOrComponent); - - string prefabAssetPath = AssetDatabase.GetAssetPath(gameObjectOrComponent); - bool isRootFolder, isReadonly; - bool validPath = AssetDatabase.GetAssetFolderInfo(prefabAssetPath, out isRootFolder, out isReadonly); - if (validPath && isReadonly) - return true; - - return false; - } - internal static bool HasInvalidComponent(Object gameObjectOrComponent) { if (gameObjectOrComponent == null) diff --git a/Editor/Mono/ProjectBrowser.cs b/Editor/Mono/ProjectBrowser.cs index 513ebb2d6e..fd04e054d5 100644 --- a/Editor/Mono/ProjectBrowser.cs +++ b/Editor/Mono/ProjectBrowser.cs @@ -2266,7 +2266,7 @@ void AssetLabelsDropDown() Rect r = GUILayoutUtility.GetRect(s_Styles.m_FilterByLabel, EditorStyles.toolbarButton); if (EditorGUI.DropdownButton(r, s_Styles.m_FilterByLabel, FocusType.Passive, EditorStyles.toolbarButton)) { - PopupWindow.Show(r, new PopupList(m_AssetLabels), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(r, new PopupList(m_AssetLabels)); } } diff --git a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs index f1543afe72..9277fffd56 100644 --- a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs +++ b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs @@ -107,15 +107,6 @@ public override void Action(int instanceId, string pathName, string resourceFile } } - internal class DoCreatePrefab : EndNameEditAction - { - public override void Action(int instanceId, string pathName, string resourceFile) - { - Object o = PrefabUtility.CreateEmptyPrefab(pathName); - ProjectWindowUtil.ShowCreatedAsset(o); - } - } - internal class DoCreatePrefabVariant : EndNameEditAction { public override void Action(int instanceId, string pathName, string resourceFile) @@ -257,12 +248,6 @@ public static void CreateScene() StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Scene.unity", EditorGUIUtility.FindTexture(typeof(SceneAsset)), null); } - // Create a prefab - public static void CreatePrefab() - { - StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Prefab.prefab", EditorGUIUtility.IconContent("Prefab Icon").image as Texture2D, null); - } - [MenuItem("Assets/Create/Prefab Variant", true)] static bool CreatePrefabVariantValidation() { diff --git a/Editor/Mono/SceneHierarchy.cs b/Editor/Mono/SceneHierarchy.cs index dec6f48fed..1f5e4ed5a8 100644 --- a/Editor/Mono/SceneHierarchy.cs +++ b/Editor/Mono/SceneHierarchy.cs @@ -485,8 +485,6 @@ public virtual void OnEnable() EditorSceneManager.newSceneCreated += OnSceneCreated; EditorSceneManager.sceneOpened += OnSceneOpened; - DoPingRequest(); - m_AllowAlphaNumericalSort = EditorPrefs.GetBool("AllowAlphaNumericHierarchy", false) || !InternalEditorUtility.isHumanControllingUs; // Always allow alphasorting when running automated tests so we can test alpha sorting SetUpSortMethodLists(); @@ -495,6 +493,8 @@ public virtual void OnEnable() if (m_TreeViewKeyboardControlID == 0) m_TreeViewKeyboardControlID = EditorGUIUtility.GetPermanentControlID(); + + DoPingRequest(); } public virtual void OnDisable() diff --git a/Editor/Mono/SceneHierarchyStageHandling.cs b/Editor/Mono/SceneHierarchyStageHandling.cs index a633173992..b0dffebe74 100644 --- a/Editor/Mono/SceneHierarchyStageHandling.cs +++ b/Editor/Mono/SceneHierarchyStageHandling.cs @@ -105,8 +105,30 @@ void HandleFirstTimePrefabStageIsOpened(StageNavigationItem stage) { if (stage.isPrefabStage && GetStoredHierarchyState(m_SceneHierarchyWindow, stage) == null) { - var visibleRootID = stage.prefabStage.prefabContentsRoot.GetInstanceID(); - m_SceneHierarchy.SetExpandedRecursive(visibleRootID, true); + SetDefaultExpandedStateForOpenedPrefab(stage.prefabStage.prefabContentsRoot); + } + } + + void SetDefaultExpandedStateForOpenedPrefab(GameObject root) + { + var expandedIDs = new List(); + AddParentsBelowButIgnoreNestedPrefabsRecursive(root.transform, expandedIDs); + expandedIDs.Sort(); + m_SceneHierarchy.treeViewState.expandedIDs = expandedIDs; + } + + void AddParentsBelowButIgnoreNestedPrefabsRecursive(Transform transform, List gameObjectInstanceIDs) + { + gameObjectInstanceIDs.Add(transform.gameObject.GetInstanceID()); + + int count = transform.childCount; + for (int i = 0; i < count; ++i) + { + var child = transform.GetChild(i); + if (child.childCount > 0 && !PrefabUtility.IsAnyPrefabInstanceRoot(child.gameObject)) + { + AddParentsBelowButIgnoreNestedPrefabsRecursive(child, gameObjectInstanceIDs); + } } } diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs index 3bee757397..6de9a6e44c 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs @@ -61,7 +61,7 @@ public GameObject prefabContentsRoot get { if (m_PrefabContentsRoot == null) - throw new InvalidOperationException("Requesting 'prefabContentsRoot' from Awake and OnEnable are not supported"); // The preview scene is not fully loaded when we call Awake and OnEnable on user scripts + throw new InvalidOperationException("Requesting 'prefabContentsRoot' from Awake and OnEnable are 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 return m_PrefabContentsRoot; } } @@ -261,7 +261,7 @@ bool isTextFieldCaretShowing bool readyToAutoSave { - get { return m_PrefabContentsRoot != null && HasSceneBeenModified() && GUIUtility.hotControl == 0 && !isTextFieldCaretShowing; } + get { return m_PrefabContentsRoot != null && HasSceneBeenModified() && GUIUtility.hotControl == 0 && !isTextFieldCaretShowing && !EditorApplication.isCompiling; } } void HandleAutoSave() @@ -313,11 +313,15 @@ internal void SavePrefab() if (prefabSaving != null) prefabSaving(m_PrefabContentsRoot); - ClearDirtiness(); - PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, m_PrefabAssetPath); + var prefabAssetRoot = PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, m_PrefabAssetPath); - if (prefabSaved != null) - prefabSaved(m_PrefabContentsRoot); + if (prefabAssetRoot != null) + { + ClearDirtiness(); + + if (prefabSaved != null) + prefabSaved(m_PrefabContentsRoot); + } if (SceneHierarchy.s_DebugPrefabStage) Debug.Log("SAVE PREFAB ended"); @@ -393,32 +397,26 @@ internal bool SaveAsNewPrefabWithSavePanel() // Returns true if prefab was saved. internal bool SavePrefabWithVersionControlDialogAndRenameDialog() { - Assert.IsTrue(m_PrefabContentsRoot != null, "We should have a valid m_PrefabContentsRoot when saving to prefab asset"); - bool editablePrefab = !AnimationMode.InAnimationMode(); - - //bool editablePrefab = UnityEditor.VersionControl.Provider.PromptAndCheckoutIfNeeded( - // new string[] {context.assetPath}, - // "The version control requires you to check out the prefab before applying changes."); - - if (editablePrefab) + if (m_PrefabContentsRoot == null) { - if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(m_PrefabAssetPath, PrefabUtility.SaveVerb.Save)) - { - // If user doesn't want to check out prefab asset, or it cannot be, - // it doesn't make sense to keep auto save on. - m_TemporarilyDisableAutoSave = true; - return false; - } - - bool showCancelButton = !autoSave; - if (!CheckRenamedPrefabRootWhenSaving(showCancelButton)) - return false; + Debug.LogError("We should have a valid m_PrefabContentsRoot when saving to prefab asset"); + return false; + } - SavePrefab(); - return true; + if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(m_PrefabAssetPath, PrefabUtility.SaveVerb.Save)) + { + // If user doesn't want to check out prefab asset, or it cannot be, + // it doesn't make sense to keep auto save on. + m_TemporarilyDisableAutoSave = true; + return false; } - return false; + bool showCancelButton = !autoSave; + if (!CheckRenamedPrefabRootWhenSaving(showCancelButton)) + return false; + + SavePrefab(); + return true; } // Returns true if we should continue saving diff --git a/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs b/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs index b3f4b6ffa8..c546825ccd 100644 --- a/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs +++ b/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs @@ -14,7 +14,7 @@ private static class Styles public static readonly GUIContent[] ProjectionStrings = { EditorGUIUtility.TrTextContent("Infinite"), EditorGUIUtility.TrTextContent("Box") }; public static readonly GUIContent[] LightmapEmissiveStrings = { EditorGUIUtility.TrTextContent("Realtime"), EditorGUIUtility.TrTextContent("Baked") }; public static readonly GUIContent Name = EditorGUIUtility.TrTextContent("Name"); - public static readonly GUIContent On = EditorGUIUtility.TrTextContent("On"); + public static readonly GUIContent Enabled = EditorGUIUtility.TrTextContent("Enabled"); public static readonly GUIContent Type = EditorGUIUtility.TrTextContent("Type"); public static readonly GUIContent Shape = EditorGUIUtility.TrTextContent("Shape"); public static readonly GUIContent Mode = EditorGUIUtility.TrTextContent("Mode"); @@ -69,8 +69,8 @@ protected virtual LightingExplorerTableColumn[] GetLightColumns() { return new[] { - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 0: Name - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.On, "m_Enabled", 25), // 1: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.Enabled, "m_Enabled", 50), // 0: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 1: Name new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Enum, Styles.Type, "m_Type", 120, (r, prop, dep) => { // 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 @@ -168,8 +168,8 @@ protected virtual LightingExplorerTableColumn[] GetReflectionProbeColumns() { return new[] { - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 0: Name - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.On, "m_Enabled", 25), // 1: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.Enabled, "m_Enabled", 50), // 0: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 1: Name new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Int, Styles.Mode, "m_Mode", 70, (r, prop, dep) => { EditorGUI.IntPopup(r, prop, ReflectionProbeEditor.Styles.reflectionProbeMode, ReflectionProbeEditor.Styles.reflectionProbeModeValues, GUIContent.none); @@ -195,8 +195,8 @@ protected virtual LightingExplorerTableColumn[] GetLightProbeColumns() { return new[] { - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 0: Name - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.On, "m_Enabled", 25), // 1: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.Enabled, "m_Enabled", 50), // 0: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 1: Name }; } diff --git a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs index 79ac29a750..64c5a47251 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs @@ -71,7 +71,6 @@ internal class LightingWindowBakeSettings SerializedProperty m_PVRFilteringAtrousPositionSigmaAO; SerializedProperty m_BounceScale; - SerializedProperty m_UpdateThreshold; static bool PlayerHasSM20Support() { @@ -131,7 +130,6 @@ private void InitSettings() //dev debug properties m_BounceScale = so.FindProperty("m_GISettings.m_BounceScale"); - m_UpdateThreshold = so.FindProperty("m_GISettings.m_TemporalCoherenceThreshold"); } public void OnEnable() @@ -351,7 +349,6 @@ public void DeveloperBuildSettingsGUI() Lightmapping.filterMode = (FilterMode)EditorGUILayout.EnumPopup(EditorGUIUtility.TempContent("Filter Mode"), Lightmapping.filterMode); EditorGUILayout.Slider(m_BounceScale, 0.0f, 10.0f, Styles.BounceScale); - EditorGUILayout.Slider(m_UpdateThreshold, 0.0f, 1.0f, Styles.UpdateThreshold); if (GUILayout.Button("Clear disk cache", GUILayout.Width(LightingWindow.kButtonWidth))) { @@ -371,6 +368,16 @@ public void DeveloperBuildSettingsGUI() DynamicGI.UpdateEnvironment(); } + private void ClampFilterType(SerializedProperty filter) + { + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + { + // Force unsupported A-Trous filter back to Gaussian. + if (filter.intValue == 1) + filter.intValue = 0; + } + } + void GeneralLightmapSettingsGUI() { bool bakedGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Baked); @@ -453,7 +460,16 @@ void GeneralLightmapSettingsGUI() { EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_PVRFilterTypeDirect, Styles.PVRFilterTypeDirect); + // TODO(RadeonRays): Hiding A-trous until it is implemented. + var filterOptions = new[] { EditorGUIUtility.TextContent("Gaussian"), EditorGUIUtility.TextContent("None") }; + var filterInts = new[] { 0, 2 }; + + ClampFilterType(m_PVRFilterTypeDirect); + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.IntPopup(m_PVRFilterTypeDirect, filterOptions, filterInts, Styles.PVRFilterTypeDirect); + else + EditorGUILayout.PropertyField(m_PVRFilterTypeDirect, Styles.PVRFilterTypeDirect); + DrawFilterSettingField(m_PVRFilteringGaussRadiusDirect, m_PVRFilteringAtrousPositionSigmaDirect, Styles.PVRFilteringGaussRadiusDirect, @@ -462,7 +478,11 @@ void GeneralLightmapSettingsGUI() EditorGUILayout.Space(); - EditorGUILayout.PropertyField(m_PVRFilterTypeIndirect, Styles.PVRFilterTypeIndirect); + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.IntPopup(m_PVRFilterTypeIndirect, filterOptions, filterInts, Styles.PVRFilterTypeIndirect); + else + EditorGUILayout.PropertyField(m_PVRFilterTypeIndirect, Styles.PVRFilterTypeIndirect); + ClampFilterType(m_PVRFilterTypeIndirect); DrawFilterSettingField(m_PVRFilteringGaussRadiusIndirect, m_PVRFilteringAtrousPositionSigmaIndirect, Styles.PVRFilteringGaussRadiusIndirect, @@ -472,8 +492,11 @@ void GeneralLightmapSettingsGUI() using (new EditorGUI.DisabledScope(!m_AmbientOcclusion.boolValue)) { EditorGUILayout.Space(); - - EditorGUILayout.PropertyField(m_PVRFilterTypeAO, Styles.PVRFilterTypeAO); + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.IntPopup(m_PVRFilterTypeAO, filterOptions, filterInts, Styles.PVRFilterTypeAO); + else + EditorGUILayout.PropertyField(m_PVRFilterTypeAO, Styles.PVRFilterTypeAO); + ClampFilterType(m_PVRFilterTypeAO); DrawFilterSettingField(m_PVRFilteringGaussRadiusAO, m_PVRFilteringAtrousPositionSigmaAO, Styles.PVRFilteringGaussRadiusAO, Styles.PVRFilteringAtrousPositionSigmaAO, diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs index ab9c61444e..7adc6e7d02 100644 --- a/Editor/Mono/SceneView/SceneView.cs +++ b/Editor/Mono/SceneView/SceneView.cs @@ -741,7 +741,7 @@ void ToolbarDisplayStateGUI() if (EditorGUI.DropdownButton(modeRect, modeContent, FocusType.Passive, EditorStyles.toolbarDropDown)) { Rect rect = GUILayoutUtility.topLevel.GetLast(); - PopupWindow.Show(rect, new SceneRenderModeWindow(this), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(rect, new SceneRenderModeWindow(this)); GUIUtility.ExitGUI(); } @@ -768,7 +768,7 @@ void ToolbarDisplayStateGUI() if (EditorGUI.DropdownButton(fxRightRect, GUIContent.none, FocusType.Passive, GUIStyle.none)) { Rect rect = GUILayoutUtility.topLevel.GetLast(); - PopupWindow.Show(rect, new SceneFXWindow(this), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(rect, new SceneFXWindow(this)); GUIUtility.ExitGUI(); } diff --git a/Editor/Mono/Scripting/Compilers/UWPReferences.cs b/Editor/Mono/Scripting/Compilers/UWPReferences.cs index f057f616bf..da1105c3a5 100644 --- a/Editor/Mono/Scripting/Compilers/UWPReferences.cs +++ b/Editor/Mono/Scripting/Compilers/UWPReferences.cs @@ -174,15 +174,11 @@ public static IEnumerable(); @@ -495,14 +496,14 @@ Exception[] UpdateCustomTargetAssemblies() { try { - if (m_PackageAssemblies != null && !assembly.PackageAssembly.HasValue) + if (packageAssemblies != null && !assembly.PackageAssembly.HasValue) { var pathPrefix = assembly.PathPrefix.ToLowerInvariant(); - foreach (var packageAssembly in m_PackageAssemblies) + foreach (var packageAssembly in packageAssemblies) { - var lower = AssetPath.ReplaceSeparators(packageAssembly.DirectoryPath).ToLowerInvariant(); - if (pathPrefix.StartsWith(lower)) + var lower = AssetPath.ReplaceSeparators(packageAssembly.DirectoryPath + AssetPath.Separator).ToLowerInvariant(); + if (pathPrefix.StartsWith(lower, StringComparison.Ordinal)) { assembly.PackageAssembly = packageAssembly; break; @@ -521,11 +522,22 @@ Exception[] UpdateCustomTargetAssemblies() } catch (Exception e) { - SetCompilationSetupErrorFlags(CompilationSetupErrorFlags.loadError); exceptions.Add(e); } } + return exceptions.ToArray(); + } + + Exception[] UpdateCustomTargetAssemblies() + { + var exceptions = UpdateCustomScriptAssemblies(customScriptAssemblies, m_PackageAssemblies); + + if (exceptions.Length > 0) + { + SetCompilationSetupErrorFlags(CompilationSetupErrorFlags.loadError); + } + customTargetAssemblies = EditorBuildRules.CreateTargetAssemblies(customScriptAssemblies, precompiledAssemblies); ClearCompilationSetupErrorFlags(CompilationSetupErrorFlags.cyclicReferences); @@ -533,7 +545,7 @@ Exception[] UpdateCustomTargetAssemblies() // customTargetAssemblies being updated. UpdateDirtyTargetAssemblies(); - return exceptions.ToArray(); + return exceptions; } void UpdateDirtyTargetAssemblies() diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs index 54d00b3510..c2cc1d0136 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs @@ -17,6 +17,7 @@ enum EditorScriptCompilationOptions BuildingForIl2Cpp = 1 << 3, BuildingWithAsserts = 1 << 4, BuildingIncludingTestAssemblies = 1 << 5, - BuildingPredefinedAssembliesAllowUnsafeCode = (1 << 6) + BuildingPredefinedAssembliesAllowUnsafeCode = (1 << 6), + BuildingForHeadlessPlayer = 1 << 7 }; } diff --git a/Editor/Mono/TooltipView/TooltipView.cs b/Editor/Mono/TooltipView/TooltipView.cs index 4a9b6242c8..bc3f53b210 100644 --- a/Editor/Mono/TooltipView/TooltipView.cs +++ b/Editor/Mono/TooltipView/TooltipView.cs @@ -66,7 +66,7 @@ void Setup(string tooltip, Rect rect) position = new Rect(0, 0, m_optimalSize.x, m_optimalSize.y); - window.ShowPopup(); + window.ShowTooltip(); window.SetAlpha(1.0f); s_guiView.mouseRayInvisible = true; diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index 5392398c9f..ec051304c7 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -205,6 +205,12 @@ private bool ShouldSyncOnReimportedAsset(string asset) public void Sync() { + // Do not sync solution until all Unity extensions are registered and initialized. + // Otherwise Unity might emit errors when VSTU tries to generate the solution and + // get all managed extensions, which not yet initialized. + if (!InternalEditorUtility.IsUnityExtensionsInitialized()) + return; + SetupProjectSupportedExtensions(); bool externalCodeAlreadyGeneratedProjects = AssetPostprocessingInternal.OnPreGeneratingCSProjectFiles(); diff --git a/Modules/AssetPipelineEditor/ImportSettings/AssetImporterTabbedEditor.cs b/Modules/AssetPipelineEditor/ImportSettings/AssetImporterTabbedEditor.cs index e3ec3ddce3..129af826f3 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/AssetImporterTabbedEditor.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/AssetImporterTabbedEditor.cs @@ -88,6 +88,8 @@ public override void OnInspectorGUI() // the activeTab can get destroyed when opening particular sub-editors (such as the Avatar configuration editor on the Rig tab) if (activeTab != null) { + GUILayout.Space(EditorGUI.kSpacing); + activeTab.OnInspectorGUI(); } diff --git a/Modules/GraphViewEditor/Manipulators/SelectionDragger.cs b/Modules/GraphViewEditor/Manipulators/SelectionDragger.cs index 790fb52601..56e112b8af 100644 --- a/Modules/GraphViewEditor/Manipulators/SelectionDragger.cs +++ b/Modules/GraphViewEditor/Manipulators/SelectionDragger.cs @@ -453,6 +453,8 @@ void MoveElement(GraphElement element, Rect originalPos) var graphView = target as GraphView; if (graphView != null && graphView.graphViewChanged != null) { + KeyValuePair firstPos = m_OriginalPos.First(); + m_GraphViewChange.moveDelta = firstPos.Key.GetPosition().position - firstPos.Value.pos.position; graphView.graphViewChanged(m_GraphViewChange); } } diff --git a/Modules/GraphViewEditor/Views/GraphView.cs b/Modules/GraphViewEditor/Views/GraphView.cs index e65244ab2c..a22ce0220b 100644 --- a/Modules/GraphViewEditor/Views/GraphView.cs +++ b/Modules/GraphViewEditor/Views/GraphView.cs @@ -44,6 +44,7 @@ public struct GraphViewChange // Operations Completed public List movedElements; + public Vector2 moveDelta; } public struct NodeCreationContext diff --git a/Modules/GridEditor/Managed/GridEditorUtility.cs b/Modules/GridEditor/Managed/GridEditorUtility.cs index 7516832bc6..59891615e0 100644 --- a/Modules/GridEditor/Managed/GridEditorUtility.cs +++ b/Modules/GridEditor/Managed/GridEditorUtility.cs @@ -216,10 +216,10 @@ public static void DrawGridMarquee(GridLayout gridLayout, BoundsInt area, Color Vector3[] cellLocals = { - gridLayout.CellToLocal(new Vector3Int(area.xMin, area.yMin, 0)), - gridLayout.CellToLocalInterpolated(new Vector3(area.xMax - 1 + cellGap.x, area.yMin, 0)), - gridLayout.CellToLocalInterpolated(new Vector3(area.xMax - 1 + cellGap.x, area.yMax - 1 + cellGap.y, 0)), - gridLayout.CellToLocalInterpolated(new Vector3(area.xMin, area.yMax - 1 + cellGap.y, 0)) + gridLayout.CellToLocal(new Vector3Int(area.xMin, area.yMin, area.zMin)), + gridLayout.CellToLocalInterpolated(new Vector3(area.xMax - 1 + cellGap.x, area.yMin, area.zMin)), + gridLayout.CellToLocalInterpolated(new Vector3(area.xMax - 1 + cellGap.x, area.yMax - 1 + cellGap.y, area.zMin)), + gridLayout.CellToLocalInterpolated(new Vector3(area.xMin, area.yMax - 1 + cellGap.y, area.zMin)) }; HandleUtility.ApplyWireMaterial(); @@ -252,34 +252,34 @@ public static void DrawSelectedHexGridArea(GridLayout gridLayout, BoundsInt area int right = horizontalCount; Vector3[] cellOffset = { - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(0, gridLayout.cellSize.y / 2, 0)), - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(gridLayout.cellSize.x / 2, gridLayout.cellSize.y / 4, 0)), - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(gridLayout.cellSize.x / 2, -gridLayout.cellSize.y / 4, 0)), - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(0, -gridLayout.cellSize.y / 2, 0)), - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(-gridLayout.cellSize.x / 2, -gridLayout.cellSize.y / 4, 0)), - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(-gridLayout.cellSize.x / 2, gridLayout.cellSize.y / 4, 0)) + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(0, gridLayout.cellSize.y / 2, area.zMin)), + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(gridLayout.cellSize.x / 2, gridLayout.cellSize.y / 4, area.zMin)), + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(gridLayout.cellSize.x / 2, -gridLayout.cellSize.y / 4, area.zMin)), + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(0, -gridLayout.cellSize.y / 2, area.zMin)), + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(-gridLayout.cellSize.x / 2, -gridLayout.cellSize.y / 4, area.zMin)), + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(-gridLayout.cellSize.x / 2, gridLayout.cellSize.y / 4, area.zMin)) }; // Fill Top and Bottom Vertices for (int x = area.min.x; x < area.max.x; x++) { - cellLocals[bottom++] = gridLayout.CellToLocal(new Vector3Int(x, area.min.y, 0)) + cellOffset[4]; - cellLocals[bottom++] = gridLayout.CellToLocal(new Vector3Int(x, area.min.y, 0)) + cellOffset[3]; - cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(x, area.max.y - 1, 0)) + cellOffset[0]; - cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(x, area.max.y - 1, 0)) + cellOffset[1]; + cellLocals[bottom++] = gridLayout.CellToLocal(new Vector3Int(x, area.min.y, area.zMin)) + cellOffset[4]; + cellLocals[bottom++] = gridLayout.CellToLocal(new Vector3Int(x, area.min.y, area.zMin)) + cellOffset[3]; + cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(x, area.max.y - 1, area.zMin)) + cellOffset[0]; + cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(x, area.max.y - 1, area.zMin)) + cellOffset[1]; } // Fill first Left and Right Vertices - cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, area.min.y, 0)) + cellOffset[5]; - cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, area.max.y - 1, 0)) + cellOffset[2]; + cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, area.min.y, area.zMin)) + cellOffset[5]; + cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, area.max.y - 1, area.zMin)) + cellOffset[2]; // Fill Left and Right Vertices for (int y = area.min.y + 1; y < area.max.y; y++) { - cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, y, 0)) + cellOffset[4]; - cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, y, 0)) + cellOffset[5]; + cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, y, area.zMin)) + cellOffset[4]; + cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, y, area.zMin)) + cellOffset[5]; } for (int y = area.min.y; y < (area.max.y - 1); y++) { - cellLocals[right++] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, y, 0)) + cellOffset[2]; - cellLocals[right++] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, y, 0)) + cellOffset[1]; + cellLocals[right++] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, y, area.zMin)) + cellOffset[2]; + cellLocals[right++] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, y, area.zMin)) + cellOffset[1]; } HandleUtility.ApplyWireMaterial(); GL.PushMatrix(); diff --git a/Modules/IMGUI/GUILayout.cs b/Modules/IMGUI/GUILayout.cs index 193026aef4..f204f4e28a 100644 --- a/Modules/IMGUI/GUILayout.cs +++ b/Modules/IMGUI/GUILayout.cs @@ -242,6 +242,11 @@ static public void FlexibleSpace() op.value = 10000; GUILayoutUtility.GetRect(0, 0, GUILayoutUtility.spaceStyle, op); + + if (Event.current.type == EventType.Layout) + { + GUILayoutUtility.current.topLevel.entries[GUILayoutUtility.current.topLevel.entries.Count - 1].consideredForMargin = false; + } } public static void BeginHorizontal(params GUILayoutOption[] options) { BeginHorizontal(GUIContent.none, GUIStyle.none, options); } diff --git a/Modules/ImageConversion/ScriptBindings/ImageConversion.bindings.cs b/Modules/ImageConversion/ScriptBindings/ImageConversion.bindings.cs index 86ce9a075e..d5ea21ea9c 100644 --- a/Modules/ImageConversion/ScriptBindings/ImageConversion.bindings.cs +++ b/Modules/ImageConversion/ScriptBindings/ImageConversion.bindings.cs @@ -32,7 +32,7 @@ public static byte[] EncodeToEXR(this Texture2D tex) } [NativeMethod(Name = "ImageConversionBindings::LoadImage", IsFreeFunction = true)] - extern public static bool LoadImage(this Texture2D tex, byte[] data, bool markNonReadable); + extern public static bool LoadImage([NotNull] this Texture2D tex, byte[] data, bool markNonReadable); public static bool LoadImage(this Texture2D tex, byte[] data) { return LoadImage(tex, data, false); diff --git a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs index c61d4a7ef8..3ca57653be 100644 --- a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs +++ b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs @@ -121,15 +121,21 @@ public UnityEngine.Profiling.Memory.Experimental.MetaData metadata // [opt: screenshot_width ] // [opt: screenshot_height ] // [opt: screenshot_format ] + var data = new UnityEngine.Profiling.Memory.Experimental.MetaData(); - var metaData = new UnityEngine.Profiling.Memory.Experimental.MetaData(); + if (array.Length == 0) + { + data.content = ""; + data.platform = ""; + return data; + } int offset = 0; int dataLength = 0; offset = ReadIntFromByteArray(array, offset, out dataLength); - offset = ReadStringFromByteArray(array, offset, dataLength, out metaData.content); + offset = ReadStringFromByteArray(array, offset, dataLength, out data.content); offset = ReadIntFromByteArray(array, offset, out dataLength); - offset = ReadStringFromByteArray(array, offset, dataLength, out metaData.platform); + offset = ReadStringFromByteArray(array, offset, dataLength, out data.platform); offset = ReadIntFromByteArray(array, offset, out dataLength); if (dataLength > 0) @@ -146,14 +152,14 @@ public UnityEngine.Profiling.Memory.Experimental.MetaData metadata offset = ReadIntFromByteArray(array, offset, out height); offset = ReadIntFromByteArray(array, offset, out format); - metaData.screenshot = new Texture2D(width, height, (TextureFormat)format, false); - metaData.screenshot.LoadRawTextureData(screenshot); - metaData.screenshot.Apply(); + data.screenshot = new Texture2D(width, height, (TextureFormat)format, false); + data.screenshot.LoadRawTextureData(screenshot); + data.screenshot.Apply(); } UnityEngine.Assertions.Assert.AreEqual(array.Length, offset); - return metaData; + return data; } } diff --git a/Modules/ProfilerEditor/ProfilerWindow/NetworkDetailStats.cs b/Modules/ProfilerEditor/ProfilerWindow/NetworkDetailStats.cs index 16ccf7806d..e8ba9d056b 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/NetworkDetailStats.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/NetworkDetailStats.cs @@ -119,8 +119,10 @@ public void NewProfilerTick(int tickId) { entry.NewProfilerTick(tickId); } +#pragma warning disable 618 NetworkTransport.SetPacketStat(0, MsgId, (int)totalIn, 1); NetworkTransport.SetPacketStat(1, MsgId, (int)totalOut, 1); +#pragma warning restore 618 totalIn = 0; totalOut = 0; } @@ -253,8 +255,10 @@ static public void ResetAll() { foreach (var detail in m_NetworkOperations.Values) { +#pragma warning disable 618 NetworkTransport.SetPacketStat(0, detail.MsgId, 0, 1); NetworkTransport.SetPacketStat(1, detail.MsgId, 0, 1); +#pragma warning restore 618 } m_NetworkOperations.Clear(); } diff --git a/Modules/ProfilerEditor/ProfilerWindow/ProfilerFrameHierarchyView.cs b/Modules/ProfilerEditor/ProfilerWindow/ProfilerFrameHierarchyView.cs index 4850a99fb8..f7f1f41a83 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/ProfilerFrameHierarchyView.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/ProfilerFrameHierarchyView.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using UnityEditor; using UnityEditor.IMGUI.Controls; +using Unity.Profiling; namespace UnityEditorInternal.Profiling { @@ -111,6 +112,8 @@ public bool sortedProfilerColumnAscending public delegate void SearchChangedCallback(string newSearch); public event SearchChangedCallback searchChanged; + static readonly ProfilerMarker m_DoGUIMarker = new ProfilerMarker(nameof(ProfilerFrameDataHierarchyView) + ".DoGUI"); + public ProfilerFrameDataHierarchyView() { m_Initialized = false; @@ -275,70 +278,73 @@ static string GetProfilerColumnName(ProfilerColumn column) public void DoGUI(FrameDataView frameDataView) { - InitIfNeeded(); + using (m_DoGUIMarker.Auto()) + { + InitIfNeeded(); - var collectingSamples = ProfilerDriver.enabled && (ProfilerDriver.profileEditor || EditorApplication.isPlaying); - var isSearchAllowed = string.IsNullOrEmpty(treeView.searchString) || !(collectingSamples && ProfilerDriver.deepProfiling); + var collectingSamples = ProfilerDriver.enabled && (ProfilerDriver.profileEditor || EditorApplication.isPlaying); + var isSearchAllowed = string.IsNullOrEmpty(treeView.searchString) || !(collectingSamples && ProfilerDriver.deepProfiling); - var isDataAvailable = frameDataView != null && frameDataView.IsValid(); - if (isDataAvailable && isSearchAllowed) - if (isDataAvailable) - m_TreeView.SetFrameDataView(frameDataView); + var isDataAvailable = frameDataView != null && frameDataView.IsValid(); + if (isDataAvailable && isSearchAllowed) + if (isDataAvailable) + m_TreeView.SetFrameDataView(frameDataView); - var showDetailedView = isDataAvailable && m_DetailedViewType != DetailedViewType.None; - if (showDetailedView) - SplitterGUILayout.BeginHorizontalSplit(m_DetailedViewSpliterState); + var showDetailedView = isDataAvailable && m_DetailedViewType != DetailedViewType.None; + if (showDetailedView) + SplitterGUILayout.BeginHorizontalSplit(m_DetailedViewSpliterState); - // Hierarchy view area - GUILayout.BeginVertical(); + // Hierarchy view area + GUILayout.BeginVertical(); - DrawToolbar(frameDataView, showDetailedView); + DrawToolbar(frameDataView, showDetailedView); - if (!isDataAvailable) - { - GUILayout.Label(BaseStyles.noData, BaseStyles.label); - } - else if (!isSearchAllowed) - { - GUILayout.Label(BaseStyles.disabledSearchText, BaseStyles.label); - } - else - { - var rect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true), GUILayout.ExpandHeight(true)); - m_TreeView.OnGUI(rect); - } + if (!isDataAvailable) + { + GUILayout.Label(BaseStyles.noData, BaseStyles.label); + } + else if (!isSearchAllowed) + { + GUILayout.Label(BaseStyles.disabledSearchText, BaseStyles.label); + } + else + { + var rect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true), GUILayout.ExpandHeight(true)); + m_TreeView.OnGUI(rect); + } - GUILayout.EndVertical(); + GUILayout.EndVertical(); - if (showDetailedView) - { - GUILayout.BeginVertical(); + if (showDetailedView) + { + GUILayout.BeginVertical(); - // Detailed view area - EditorGUILayout.BeginHorizontal(BaseStyles.toolbar); + // Detailed view area + EditorGUILayout.BeginHorizontal(BaseStyles.toolbar); - DrawDetailedViewPopup(); - GUILayout.FlexibleSpace(); + DrawDetailedViewPopup(); + GUILayout.FlexibleSpace(); - DrawOptionsMenuPopup(); - EditorGUILayout.EndHorizontal(); + DrawOptionsMenuPopup(); + EditorGUILayout.EndHorizontal(); - switch (m_DetailedViewType) - { - case DetailedViewType.Objects: - detailedObjectsView.DoGUI(BaseStyles.header, frameDataView, m_TreeView.GetSelection()); - break; - case DetailedViewType.CallersAndCallees: - detailedCallsView.DoGUI(BaseStyles.header, frameDataView, m_TreeView.GetSelection()); - break; - } + switch (m_DetailedViewType) + { + case DetailedViewType.Objects: + detailedObjectsView.DoGUI(BaseStyles.header, frameDataView, m_TreeView.GetSelection()); + break; + case DetailedViewType.CallersAndCallees: + detailedCallsView.DoGUI(BaseStyles.header, frameDataView, m_TreeView.GetSelection()); + break; + } - GUILayout.EndVertical(); + GUILayout.EndVertical(); - SplitterGUILayout.EndHorizontalSplit(); - } + SplitterGUILayout.EndHorizontalSplit(); + } - HandleKeyboardEvents(); + HandleKeyboardEvents(); + } } void DrawSearchBar() diff --git a/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs b/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs index 9d60438ccd..ee29b6a242 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs @@ -9,6 +9,7 @@ using UnityEditorInternal.Profiling; using Object = UnityEngine.Object; using UnityEditor.AnimatedValues; +using Unity.Profiling; namespace UnityEditorInternal { @@ -36,12 +37,13 @@ internal class ThreadInfo public int threadIndex; public string name; public bool alive; - public int maxDepth = 1; - public ThreadInfo(string name, int threadIndex, int linesToDisplay) + public int maxDepth; + public ThreadInfo(string name, int threadIndex, int maxDepth, int linesToDisplay) { this.name = name; this.threadIndex = threadIndex; this.linesToDisplay = linesToDisplay; + this.maxDepth = Mathf.Max(1, maxDepth); } } @@ -227,6 +229,8 @@ struct RangeSelectionInfo RangeSelectionInfo m_RangeSelection = new RangeSelectionInfo(); + static readonly ProfilerMarker m_DoGUIMarker = new ProfilerMarker(nameof(ProfilerTimelineGUI) + ".DoGUI"); + public ProfilerTimelineGUI(IProfilerWindowController window) { m_Window = window; @@ -265,43 +269,21 @@ private void UpdateGroupAndThreadInfo(ref ProfilerFrameDataIterator iter, int fr ThreadInfo thread = threads.Find(t => t.threadIndex == i); if (thread == null) { - thread = new ThreadInfo(iter.GetThreadName(), i, group.defaultLineCountPerThread); + // ProfilerFrameDataIterator.maxDepth includes the thread sample which is not getting displayed, so we store it at -1 for all intents and purposes + thread = new ThreadInfo(iter.GetThreadName(), i, iter.maxDepth - 1, group.defaultLineCountPerThread); // the main thread gets double the size if (i == 0) thread.linesToDisplay *= 2; group.threads.Add(thread); } - thread.alive = true; - } - - if (m_LastSelectedFrameID != frameIndex) - { - foreach (var group in m_Groups) + else if (m_LastSelectedFrameID != frameIndex) { - foreach (var thread in group.threads) - { - thread.maxDepth = GetThreadMaxDepth(thread, frameIndex); - } - } - m_LastSelectedFrameID = frameIndex; - } - } - - int GetThreadMaxDepth(ThreadInfo thread, int frame) - { - int maxDepth = 1; - using (var iter = new ProfilerFrameDataIterator()) - { - iter.SetRoot(frame, thread.threadIndex); - - while (iter.Next(true)) - { - if (iter.depth > maxDepth) - maxDepth = iter.depth; + thread.maxDepth = iter.maxDepth; } + thread.alive = true; } - return maxDepth; + m_LastSelectedFrameID = frameIndex; } private float CalculateHeightForAllBars(Rect fullRect, out float combinedHeaderHeight, out float combinedThreadHeight) @@ -1190,200 +1172,203 @@ void HandleThreadSplitterFoldoutButtons(GroupInfo group, ThreadInfo thread, Rect public void DoGUI(FrameDataView frameDataView, float width, float ypos, float height) { - if (frameDataView == null || !frameDataView.IsValid()) + using (m_DoGUIMarker.Auto()) { - GUILayout.Label(BaseStyles.noData, BaseStyles.label); - return; - } - - Rect fullRect = new Rect(0, ypos - 1, width, height + 1); - float sideWidth = Chart.kSideWidth - 1; + if (frameDataView == null || !frameDataView.IsValid()) + { + GUILayout.Label(BaseStyles.noData, BaseStyles.label); + return; + } - Rect timeRulerRect = new Rect(fullRect.x + sideWidth, fullRect.y, fullRect.width - sideWidth, k_LineHeight); + Rect fullRect = new Rect(0, ypos - 1, width, height + 1); + float sideWidth = Chart.kSideWidth - 1; - Rect timeAreaRect = new Rect(fullRect.x + sideWidth, fullRect.y + timeRulerRect.height, fullRect.width - sideWidth, fullRect.height - timeRulerRect.height); + Rect timeRulerRect = new Rect(fullRect.x + sideWidth, fullRect.y, fullRect.width - sideWidth, k_LineHeight); - bool initializing = false; - if (m_TimeArea == null) - { - initializing = true; - m_TimeArea = new ZoomableArea(); - m_TimeArea.hRangeLocked = false; - m_TimeArea.vRangeLocked = false; - m_TimeArea.hSlider = true; - m_TimeArea.vSlider = true; - m_TimeArea.vAllowExceedBaseRangeMax = false; - m_TimeArea.vAllowExceedBaseRangeMin = false; - m_TimeArea.hBaseRangeMin = 0; - m_TimeArea.vBaseRangeMin = 0; - m_TimeArea.vScaleMax = 1f; - m_TimeArea.vScaleMin = 1f; - m_TimeArea.scaleWithWindow = true; - m_TimeArea.margin = 10; - m_TimeArea.topmargin = 0; - m_TimeArea.bottommargin = 0; - m_TimeArea.upDirection = ZoomableArea.YDirection.Negative; - m_TimeArea.vZoomLockedByDefault = true; - } + Rect timeAreaRect = new Rect(fullRect.x + sideWidth, fullRect.y + timeRulerRect.height, fullRect.width - sideWidth, fullRect.height - timeRulerRect.height); - m_TimeArea.rect = timeAreaRect; + bool initializing = false; + if (m_TimeArea == null) + { + initializing = true; + m_TimeArea = new ZoomableArea(); + m_TimeArea.hRangeLocked = false; + m_TimeArea.vRangeLocked = false; + m_TimeArea.hSlider = true; + m_TimeArea.vSlider = true; + m_TimeArea.vAllowExceedBaseRangeMax = false; + m_TimeArea.vAllowExceedBaseRangeMin = false; + m_TimeArea.hBaseRangeMin = 0; + m_TimeArea.vBaseRangeMin = 0; + m_TimeArea.vScaleMax = 1f; + m_TimeArea.vScaleMin = 1f; + m_TimeArea.scaleWithWindow = true; + m_TimeArea.margin = 10; + m_TimeArea.topmargin = 0; + m_TimeArea.bottommargin = 0; + m_TimeArea.upDirection = ZoomableArea.YDirection.Negative; + m_TimeArea.vZoomLockedByDefault = true; + } - Rect bottomLeftFillRect = new Rect(0, ypos + height - m_TimeArea.vSliderWidth, sideWidth, m_TimeArea.vSliderWidth); + m_TimeArea.rect = timeAreaRect; - if (Event.current.type == EventType.Repaint) - { - styles.profilerGraphBackground.Draw(fullRect, false, false, false, false); - // The bar in the lower left side that fills the space next to the horizontal scrollbar. - EditorStyles.toolbar.Draw(bottomLeftFillRect, false, false, false, false); - } + Rect bottomLeftFillRect = new Rect(0, ypos + height - m_TimeArea.vSliderWidth, sideWidth, m_TimeArea.vSliderWidth); - if (initializing) - { - NativeProfilerTimeline_InitializeArgs args = new NativeProfilerTimeline_InitializeArgs(); - args.Reset(); - args.ghostAlpha = 0.3f; - args.nonSelectedAlpha = 0.75f; - args.guiStyle = styles.bar.m_Ptr; - args.lineHeight = k_LineHeight; - args.textFadeOutWidth = k_TextFadeOutWidth; - args.textFadeStartWidth = k_TextFadeStartWidth; - - NativeProfilerTimeline.Initialize(ref args); - } - // Prepare group and Thread Info - var iter = new ProfilerFrameDataIterator(); - int threadCount = iter.GetThreadCount(frameDataView.frameIndex); - iter.SetRoot(frameDataView.frameIndex, 0); - UpdateGroupAndThreadInfo(ref iter, frameDataView.frameIndex); - MarkDeadOrClearThread(); + if (Event.current.type == EventType.Repaint) + { + styles.profilerGraphBackground.Draw(fullRect, false, false, false, false); + // The bar in the lower left side that fills the space next to the horizontal scrollbar. + EditorStyles.toolbar.Draw(bottomLeftFillRect, false, false, false, false); + } - HandleFrameSelected(iter.frameTimeMS); + if (initializing) + { + NativeProfilerTimeline_InitializeArgs args = new NativeProfilerTimeline_InitializeArgs(); + args.Reset(); + args.ghostAlpha = 0.3f; + args.nonSelectedAlpha = 0.75f; + args.guiStyle = styles.bar.m_Ptr; + args.lineHeight = k_LineHeight; + args.textFadeOutWidth = k_TextFadeOutWidth; + args.textFadeStartWidth = k_TextFadeStartWidth; + + NativeProfilerTimeline.Initialize(ref args); + } + // Prepare group and Thread Info + var iter = new ProfilerFrameDataIterator(); + int threadCount = iter.GetThreadCount(frameDataView.frameIndex); + iter.SetRoot(frameDataView.frameIndex, 0); + UpdateGroupAndThreadInfo(ref iter, frameDataView.frameIndex); + MarkDeadOrClearThread(); - // update time area to new bounds - float combinedHeaderHeight, combinedThreadHeight; - float heightForAllBars = CalculateHeightForAllBars(fullRect, out combinedHeaderHeight, out combinedThreadHeight); - float emptySpaceBelowBars = k_LineHeight * 3f; + HandleFrameSelected(iter.frameTimeMS); - // if needed, take up more empty space below, to fill up the ZoomableArea - emptySpaceBelowBars = Mathf.Max(emptySpaceBelowBars, timeAreaRect.height - heightForAllBars); + // update time area to new bounds + float combinedHeaderHeight, combinedThreadHeight; + float heightForAllBars = CalculateHeightForAllBars(fullRect, out combinedHeaderHeight, out combinedThreadHeight); + float emptySpaceBelowBars = k_LineHeight * 3f; - heightForAllBars += emptySpaceBelowBars; + // if needed, take up more empty space below, to fill up the ZoomableArea + emptySpaceBelowBars = Mathf.Max(emptySpaceBelowBars, timeAreaRect.height - heightForAllBars); - m_TimeArea.hBaseRangeMax = iter.frameTimeMS; - m_TimeArea.vBaseRangeMax = heightForAllBars; + heightForAllBars += emptySpaceBelowBars; - if (Mathf.Abs(heightForAllBars - m_LastHeightForAllBars) >= 0.5f || Mathf.Abs(fullRect.height - m_LastFullRectHeight) >= 0.5f) - { - m_LastHeightForAllBars = heightForAllBars; - m_LastFullRectHeight = fullRect.height; + m_TimeArea.hBaseRangeMax = iter.frameTimeMS; + m_TimeArea.vBaseRangeMax = heightForAllBars; - // set V range to enforce scale of 1 and to shift the shown area up in case the drawn area shrunk down - m_TimeArea.SetShownVRange(m_TimeArea.shownArea.y, m_TimeArea.shownArea.y + m_TimeArea.drawRect.height); - } + if (Mathf.Abs(heightForAllBars - m_LastHeightForAllBars) >= 0.5f || Mathf.Abs(fullRect.height - m_LastFullRectHeight) >= 0.5f) + { + m_LastHeightForAllBars = heightForAllBars; + m_LastFullRectHeight = fullRect.height; - // frame the selection if needed and before drawing the time area - if (initializing) - PerformFrameSelected(iter.frameTimeMS); + // set V range to enforce scale of 1 and to shift the shown area up in case the drawn area shrunk down + m_TimeArea.SetShownVRange(m_TimeArea.shownArea.y, m_TimeArea.shownArea.y + m_TimeArea.drawRect.height); + } - DoTimeRulerGUI(timeRulerRect, sideWidth, iter.frameTimeMS); - DoTimeArea(); + // frame the selection if needed and before drawing the time area + if (initializing) + PerformFrameSelected(iter.frameTimeMS); - Rect fullThreadsRect = new Rect(fullRect.x, fullRect.y + timeRulerRect.height, fullRect.width - m_TimeArea.vSliderWidth, fullRect.height - timeRulerRect.height - m_TimeArea.hSliderHeight); + DoTimeRulerGUI(timeRulerRect, sideWidth, iter.frameTimeMS); + DoTimeArea(); - Rect fullThreadsRectWithoutSidebar = fullThreadsRect; - fullThreadsRectWithoutSidebar.x += sideWidth; - fullThreadsRectWithoutSidebar.width -= sideWidth; + Rect fullThreadsRect = new Rect(fullRect.x, fullRect.y + timeRulerRect.height, fullRect.width - m_TimeArea.vSliderWidth, fullRect.height - timeRulerRect.height - m_TimeArea.hSliderHeight); - // The splitters need to be handled after the time area so that they don't interfere with the input for panning/scrolling the ZoomableArea - DoThreadSplitters(fullThreadsRect, fullThreadsRectWithoutSidebar, frameDataView.frameIndex, ThreadSplitterCommand.HandleThreadSplitter); + Rect fullThreadsRectWithoutSidebar = fullThreadsRect; + fullThreadsRectWithoutSidebar.x += sideWidth; + fullThreadsRectWithoutSidebar.width -= sideWidth; - Rect barsUIRect = m_TimeArea.drawRect; + // The splitters need to be handled after the time area so that they don't interfere with the input for panning/scrolling the ZoomableArea + DoThreadSplitters(fullThreadsRect, fullThreadsRectWithoutSidebar, frameDataView.frameIndex, ThreadSplitterCommand.HandleThreadSplitter); - DrawGrid(barsUIRect, iter.frameTimeMS); + Rect barsUIRect = m_TimeArea.drawRect; - Rect barsAndSidebarUIRect = new Rect(barsUIRect.x - sideWidth, barsUIRect.y, barsUIRect.width + sideWidth, barsUIRect.height); + DrawGrid(barsUIRect, iter.frameTimeMS); - GUI.BeginClip(barsAndSidebarUIRect); + Rect barsAndSidebarUIRect = new Rect(barsUIRect.x - sideWidth, barsUIRect.y, barsUIRect.width + sideWidth, barsUIRect.height); - Rect shownBarsUIRect = barsUIRect; - shownBarsUIRect.y = scrollOffsetY; + GUI.BeginClip(barsAndSidebarUIRect); - // since the scale is not applied to the group headers, there would be some height unaccounted for - // this calculation applies that height to the threads via scaleForThreadHeight - float heightUnaccountedForDueToNotScalingHeaders = m_TimeArea.scale.y * combinedHeaderHeight - combinedHeaderHeight; - float scaleForThreadHeight = (combinedThreadHeight * m_TimeArea.scale.y + heightUnaccountedForDueToNotScalingHeaders) / combinedThreadHeight; + Rect shownBarsUIRect = barsUIRect; + shownBarsUIRect.y = scrollOffsetY; - DrawBars(shownBarsUIRect, scaleForThreadHeight); - GUI.EndClip(); + // since the scale is not applied to the group headers, there would be some height unaccounted for + // this calculation applies that height to the threads via scaleForThreadHeight + float heightUnaccountedForDueToNotScalingHeaders = m_TimeArea.scale.y * combinedHeaderHeight - combinedHeaderHeight; + float scaleForThreadHeight = (combinedThreadHeight * m_TimeArea.scale.y + heightUnaccountedForDueToNotScalingHeaders) / combinedThreadHeight; - DoRangeSelection(barsUIRect); + DrawBars(shownBarsUIRect, scaleForThreadHeight); + GUI.EndClip(); - GUI.BeginClip(barsUIRect); - shownBarsUIRect.x = 0; + DoRangeSelection(barsUIRect); - bool oldEnabled = GUI.enabled; - GUI.enabled = false; - // Walk backwards to find how many previous frames we need to show. - int maxContextFramesToShow = m_Window.IsRecording() ? 1 : 3; - int numContextFramesToShow = maxContextFramesToShow; - int currentFrame = frameDataView.frameIndex; - float currentTime = 0; - do - { - int prevFrame = ProfilerDriver.GetPreviousFrameIndex(currentFrame); - if (prevFrame == -1) - break; - iter.SetRoot(prevFrame, 0); - currentTime -= iter.frameTimeMS; - currentFrame = prevFrame; - --numContextFramesToShow; - } - while (currentTime > m_TimeArea.shownArea.x && numContextFramesToShow > 0); + GUI.BeginClip(barsUIRect); + shownBarsUIRect.x = 0; - // Draw previous frames - while (currentFrame != -1 && currentFrame != frameDataView.frameIndex) - { - iter.SetRoot(currentFrame, 0); - DoProfilerFrame(currentFrame, shownBarsUIRect, true, threadCount, currentTime, scaleForThreadHeight); - currentTime += iter.frameTimeMS; - currentFrame = ProfilerDriver.GetNextFrameIndex(currentFrame); - } + bool oldEnabled = GUI.enabled; + GUI.enabled = false; + // Walk backwards to find how many previous frames we need to show. + int maxContextFramesToShow = m_Window.IsRecording() ? 1 : 3; + int numContextFramesToShow = maxContextFramesToShow; + int currentFrame = frameDataView.frameIndex; + float currentTime = 0; + do + { + int prevFrame = ProfilerDriver.GetPreviousFrameIndex(currentFrame); + if (prevFrame == -1) + break; + iter.SetRoot(prevFrame, 0); + currentTime -= iter.frameTimeMS; + currentFrame = prevFrame; + --numContextFramesToShow; + } + while (currentTime > m_TimeArea.shownArea.x && numContextFramesToShow > 0); - // Draw next frames - numContextFramesToShow = maxContextFramesToShow; - currentFrame = frameDataView.frameIndex; - currentTime = 0; - while (currentTime < m_TimeArea.shownArea.x + m_TimeArea.shownArea.width && numContextFramesToShow >= 0) - { - if (frameDataView.frameIndex != currentFrame) + // Draw previous frames + while (currentFrame != -1 && currentFrame != frameDataView.frameIndex) + { + iter.SetRoot(currentFrame, 0); DoProfilerFrame(currentFrame, shownBarsUIRect, true, threadCount, currentTime, scaleForThreadHeight); - iter.SetRoot(currentFrame, 0); - currentFrame = ProfilerDriver.GetNextFrameIndex(currentFrame); - if (currentFrame == -1) - break; - currentTime += iter.frameTimeMS; - --numContextFramesToShow; - } + currentTime += iter.frameTimeMS; + currentFrame = ProfilerDriver.GetNextFrameIndex(currentFrame); + } + + // Draw next frames + numContextFramesToShow = maxContextFramesToShow; + currentFrame = frameDataView.frameIndex; + currentTime = 0; + while (currentTime < m_TimeArea.shownArea.x + m_TimeArea.shownArea.width && numContextFramesToShow >= 0) + { + if (frameDataView.frameIndex != currentFrame) + DoProfilerFrame(currentFrame, shownBarsUIRect, true, threadCount, currentTime, scaleForThreadHeight); + iter.SetRoot(currentFrame, 0); + currentFrame = ProfilerDriver.GetNextFrameIndex(currentFrame); + if (currentFrame == -1) + break; + currentTime += iter.frameTimeMS; + --numContextFramesToShow; + } - GUI.enabled = oldEnabled; + GUI.enabled = oldEnabled; - // Draw center frame last to get on top - threadCount = 0; - DoProfilerFrame(frameDataView.frameIndex, shownBarsUIRect, false, threadCount, 0, scaleForThreadHeight); + // Draw center frame last to get on top + threadCount = 0; + DoProfilerFrame(frameDataView.frameIndex, shownBarsUIRect, false, threadCount, 0, scaleForThreadHeight); - GUI.EndClip(); + GUI.EndClip(); - // Draw Foldout Buttons on top of natively drawn bars - DoThreadSplitters(fullThreadsRect, fullThreadsRectWithoutSidebar, frameDataView.frameIndex, ThreadSplitterCommand.HandleThreadSplitterFoldoutButtons); + // Draw Foldout Buttons on top of natively drawn bars + DoThreadSplitters(fullThreadsRect, fullThreadsRectWithoutSidebar, frameDataView.frameIndex, ThreadSplitterCommand.HandleThreadSplitterFoldoutButtons); - // Draw tooltips on top of clip to be able to extend outside of timeline area - DoSelectionTooltip(frameDataView.frameIndex, m_TimeArea.drawRect); + // Draw tooltips on top of clip to be able to extend outside of timeline area + DoSelectionTooltip(frameDataView.frameIndex, m_TimeArea.drawRect); - if (Event.current.type == EventType.Repaint) - { - // Reset all flags once Repaint finished on this view - m_LastRepaintProcessedInputs = m_CurrentlyProcessedInputs; - m_CurrentlyProcessedInputs = 0; + if (Event.current.type == EventType.Repaint) + { + // Reset all flags once Repaint finished on this view + m_LastRepaintProcessedInputs = m_CurrentlyProcessedInputs; + m_CurrentlyProcessedInputs = 0; + } } } diff --git a/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs b/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs index 1228f2fe70..127ff30dbb 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs @@ -107,7 +107,8 @@ static Styles() private Vector2 m_GraphPos = Vector2.zero; private Vector2[] m_PaneScroll = new Vector2[Profiler.areaCount]; private Vector2 m_PaneScroll_AudioChannels = Vector2.zero; - private Vector2 m_PaneScroll_AudioDSP = Vector2.zero; + private Vector2 m_PaneScroll_AudioDSPLeft = Vector2.zero; + private Vector2 m_PaneScroll_AudioDSPRight = Vector2.zero; private Vector2 m_PaneScroll_AudioClips = Vector2.zero; [SerializeField] @@ -122,7 +123,7 @@ static Styles() ProfilerArea? m_CurrentArea = ProfilerArea.CPU; ProfilerMemoryView m_ShowDetailedMemoryPane = ProfilerMemoryView.Simple; - ProfilerAudioView m_ShowDetailedAudioPane = ProfilerAudioView.Stats; + ProfilerAudioView m_ShowDetailedAudioPane = ProfilerAudioView.Channels; [SerializeField] bool m_ShowInactiveDSPChains = false; @@ -837,194 +838,192 @@ void DrawNetworkOperationsPane() } - private void AudioProfilerToggle(ProfilerCaptureFlags toggleFlag) + private enum ProfilerAudioPopupItems { - bool oldState = (AudioSettings.profilerCaptureFlags & (int)toggleFlag) != 0; - bool newState = GUILayout.Toggle(oldState, "Record", EditorStyles.toolbarButton); - if (oldState != newState) - ProfilerDriver.SetAudioCaptureFlags((AudioSettings.profilerCaptureFlags & ~(int)toggleFlag) | (newState - ? (int)toggleFlag - : 0)); + Simple = 0, + Detailed = 1 + } + + private bool AudioDeepProfileToggle() + { + int toggleFlags = (int)ProfilerCaptureFlags.Channels; + if (Unsupported.IsDeveloperMode()) + toggleFlags |= (int)ProfilerCaptureFlags.Clips | (int)ProfilerCaptureFlags.DSPNodes; + ProfilerAudioPopupItems oldShowDetailedAudioPane = (AudioSettings.profilerCaptureFlags & toggleFlags) != 0 ? ProfilerAudioPopupItems.Detailed : ProfilerAudioPopupItems.Simple; + ProfilerAudioPopupItems newShowDetailedAudioPane = (ProfilerAudioPopupItems)EditorGUILayout.EnumPopup(oldShowDetailedAudioPane, EditorStyles.toolbarDropDown, GUILayout.Width(70f)); + if (oldShowDetailedAudioPane != newShowDetailedAudioPane) + ProfilerDriver.SetAudioCaptureFlags((AudioSettings.profilerCaptureFlags & ~toggleFlags) | (newShowDetailedAudioPane == ProfilerAudioPopupItems.Detailed ? toggleFlags : 0)); + return (AudioSettings.profilerCaptureFlags & toggleFlags) != 0; + } + + private Rect DrawAudioStatsPane(ref Vector2 scrollPos) + { + var totalRect = GUILayoutUtility.GetRect(20f, 20000f, 10, 10000f); + var statsRect = new Rect(totalRect.x, totalRect.y, 230f, totalRect.height); + var rightRect = new Rect(statsRect.xMax, totalRect.y, totalRect.width - statsRect.width, totalRect.height); + + // STATS + var content = ProfilerDriver.GetOverviewText(m_CurrentArea.Value, GetActiveVisibleFrameIndex()); + var textSize = EditorStyles.wordWrappedLabel.CalcSize(GUIContent.Temp(content)); + scrollPos = GUI.BeginScrollView(statsRect, scrollPos, new Rect(0, 0, textSize.x, textSize.y)); + GUI.Label(new Rect(3, 3, textSize.x, textSize.y), content, EditorStyles.wordWrappedLabel); + GUI.EndScrollView(); + EditorGUI.DrawRect(new Rect(statsRect.xMax - 1, statsRect.y, 1, statsRect.height), Color.black); + + return rightRect; } private void DrawAudioPane() { EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); ProfilerAudioView newShowDetailedAudioPane = m_ShowDetailedAudioPane; - if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Stats, "Stats", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Stats; - if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Channels, "Channels", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Channels; - if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Groups, "Groups", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Groups; - if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.ChannelsAndGroups, "Channels and groups", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.ChannelsAndGroups; - if (Unsupported.IsDeveloperMode() && GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.DSPGraph, "DSP Graph", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.DSPGraph; - if (Unsupported.IsDeveloperMode() && GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Clips, "Clips", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Clips; - if (newShowDetailedAudioPane != m_ShowDetailedAudioPane) - { - m_ShowDetailedAudioPane = newShowDetailedAudioPane; - m_LastAudioProfilerFrame = -1; // force update - } - if (m_ShowDetailedAudioPane == ProfilerAudioView.Stats) - { - GUILayout.Space(5); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - DrawOverviewText(m_CurrentArea); - } - else if (m_ShowDetailedAudioPane == ProfilerAudioView.DSPGraph) + if (AudioDeepProfileToggle()) { - GUILayout.Space(5); - AudioProfilerToggle(ProfilerCaptureFlags.DSPNodes); - GUILayout.Space(5); - m_ShowInactiveDSPChains = GUILayout.Toggle(m_ShowInactiveDSPChains, "Show inactive", EditorStyles.toolbarButton); - if (m_ShowInactiveDSPChains) - m_HighlightAudibleDSPChains = GUILayout.Toggle(m_HighlightAudibleDSPChains, "Highlight audible", EditorStyles.toolbarButton); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); + if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Channels, "Channels", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Channels; + if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Groups, "Groups", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Groups; + if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.ChannelsAndGroups, "Channels and groups", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.ChannelsAndGroups; + if (Unsupported.IsDeveloperMode() && GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.DSPGraph, "DSP Graph", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.DSPGraph; + if (Unsupported.IsDeveloperMode() && GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Clips, "Clips", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Clips; + if (newShowDetailedAudioPane != m_ShowDetailedAudioPane) + { + m_ShowDetailedAudioPane = newShowDetailedAudioPane; + m_LastAudioProfilerFrame = -1; // force update + } + if (m_ShowDetailedAudioPane == ProfilerAudioView.DSPGraph) + { + m_ShowInactiveDSPChains = GUILayout.Toggle(m_ShowInactiveDSPChains, "Show inactive", EditorStyles.toolbarButton); + if (m_ShowInactiveDSPChains) + m_HighlightAudibleDSPChains = GUILayout.Toggle(m_HighlightAudibleDSPChains, "Highlight audible", EditorStyles.toolbarButton); + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); - var totalRect = GUILayoutUtility.GetRect(20f, 10000f, 10, 20000f); + var graphRect = DrawAudioStatsPane(ref m_PaneScroll_AudioDSPLeft); - m_PaneScroll_AudioDSP = GUI.BeginScrollView(totalRect, m_PaneScroll_AudioDSP, new Rect(0, 0, 10000, 20000)); + m_PaneScroll_AudioDSPRight = GUI.BeginScrollView(graphRect, m_PaneScroll_AudioDSPRight, new Rect(0, 0, 10000, 20000)); - var clippingRect = new Rect(m_PaneScroll_AudioDSP.x, m_PaneScroll_AudioDSP.y, totalRect.width, totalRect.height); + var clippingRect = new Rect(m_PaneScroll_AudioDSPRight.x, m_PaneScroll_AudioDSPRight.y, graphRect.width, graphRect.height); - if (m_AudioProfilerDSPView == null) - m_AudioProfilerDSPView = new AudioProfilerDSPView(); + if (m_AudioProfilerDSPView == null) + m_AudioProfilerDSPView = new AudioProfilerDSPView(); - ProfilerProperty property = CreateProperty(); - if (CheckFrameData(property)) - { - m_AudioProfilerDSPView.OnGUI(clippingRect, property, m_ShowInactiveDSPChains, m_HighlightAudibleDSPChains, ref m_DSPGraphZoomFactor, ref m_PaneScroll_AudioDSP); - } - if (property != null) - property.Dispose(); + ProfilerProperty property = CreateProperty(); + if (CheckFrameData(property)) + { + m_AudioProfilerDSPView.OnGUI(clippingRect, property, m_ShowInactiveDSPChains, m_HighlightAudibleDSPChains, ref m_DSPGraphZoomFactor, ref m_PaneScroll_AudioDSPRight); + } + if (property != null) + property.Dispose(); - GUI.EndScrollView(); + GUI.EndScrollView(); - Repaint(); - } - else if (m_ShowDetailedAudioPane == ProfilerAudioView.Clips) - { - GUILayout.Space(5); - AudioProfilerToggle(ProfilerCaptureFlags.Clips); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - - var totalRect = GUILayoutUtility.GetRect(20f, 20000f, 10, 10000f); - var statsRect = new Rect(totalRect.x, totalRect.y, 230f, totalRect.height); - var treeRect = new Rect(statsRect.xMax, totalRect.y, totalRect.width - statsRect.width, totalRect.height); + Repaint(); + } + else if (m_ShowDetailedAudioPane == ProfilerAudioView.Clips) + { + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); - // STATS - var content = ProfilerDriver.GetOverviewText(m_CurrentArea.Value, GetActiveVisibleFrameIndex()); - var textSize = EditorStyles.wordWrappedLabel.CalcSize(GUIContent.Temp(content)); - m_PaneScroll_AudioClips = GUI.BeginScrollView(statsRect, m_PaneScroll_AudioClips, new Rect(0, 0, textSize.x, textSize.y)); - GUI.Label(new Rect(3, 3, textSize.x, textSize.y), content, EditorStyles.wordWrappedLabel); - GUI.EndScrollView(); - EditorGUI.DrawRect(new Rect(statsRect.xMax - 1, statsRect.y, 1, statsRect.height), Color.black); + var treeRect = DrawAudioStatsPane(ref m_PaneScroll_AudioClips); - // TREE - if (m_AudioProfilerClipTreeViewState == null) - m_AudioProfilerClipTreeViewState = new AudioProfilerClipTreeViewState(); + // TREE + if (m_AudioProfilerClipTreeViewState == null) + m_AudioProfilerClipTreeViewState = new AudioProfilerClipTreeViewState(); - if (m_AudioProfilerClipViewBackend == null) - m_AudioProfilerClipViewBackend = new AudioProfilerClipViewBackend(m_AudioProfilerClipTreeViewState); + if (m_AudioProfilerClipViewBackend == null) + m_AudioProfilerClipViewBackend = new AudioProfilerClipViewBackend(m_AudioProfilerClipTreeViewState); - ProfilerProperty property = CreateProperty(); - if (CheckFrameData(property)) - { - if (m_CurrentFrame == -1 || m_LastAudioProfilerFrame != m_CurrentFrame) + ProfilerProperty property = CreateProperty(); + if (CheckFrameData(property)) { - m_LastAudioProfilerFrame = m_CurrentFrame; - var sourceItems = property.GetAudioProfilerClipInfo(); - if (sourceItems != null && sourceItems.Length > 0) + if (m_CurrentFrame == -1 || m_LastAudioProfilerFrame != m_CurrentFrame) { - var items = new List(); - foreach (var s in sourceItems) - { - items.Add(new AudioProfilerClipInfoWrapper(s, property.GetAudioProfilerNameByOffset(s.assetNameOffset))); - } - m_AudioProfilerClipViewBackend.SetData(items); - if (m_AudioProfilerClipView == null) + m_LastAudioProfilerFrame = m_CurrentFrame; + var sourceItems = property.GetAudioProfilerClipInfo(); + if (sourceItems != null && sourceItems.Length > 0) { - m_AudioProfilerClipView = new AudioProfilerClipView(this, m_AudioProfilerClipTreeViewState); - m_AudioProfilerClipView.Init(treeRect, m_AudioProfilerClipViewBackend); + var items = new List(); + foreach (var s in sourceItems) + { + items.Add(new AudioProfilerClipInfoWrapper(s, property.GetAudioProfilerNameByOffset(s.assetNameOffset))); + } + m_AudioProfilerClipViewBackend.SetData(items); + if (m_AudioProfilerClipView == null) + { + m_AudioProfilerClipView = new AudioProfilerClipView(this, m_AudioProfilerClipTreeViewState); + m_AudioProfilerClipView.Init(treeRect, m_AudioProfilerClipViewBackend); + } } } + if (m_AudioProfilerClipView != null) + m_AudioProfilerClipView.OnGUI(treeRect); } - if (m_AudioProfilerClipView != null) - m_AudioProfilerClipView.OnGUI(treeRect); + if (property != null) + property.Dispose(); } - if (property != null) - property.Dispose(); - } - else - { - GUILayout.Space(5); - AudioProfilerToggle(ProfilerCaptureFlags.Channels); - GUILayout.Space(5); - bool resetAllAudioClipPlayCountsOnPlay = GUILayout.Toggle(AudioUtil.resetAllAudioClipPlayCountsOnPlay, "Reset play count on play", EditorStyles.toolbarButton); - if (resetAllAudioClipPlayCountsOnPlay != AudioUtil.resetAllAudioClipPlayCountsOnPlay) - AudioUtil.resetAllAudioClipPlayCountsOnPlay = resetAllAudioClipPlayCountsOnPlay; - if (Unsupported.IsDeveloperMode()) + else { - GUILayout.Space(5); - bool showAllGroups = EditorPrefs.GetBool("AudioProfilerShowAllGroups"); - bool newShowAllGroups = GUILayout.Toggle(showAllGroups, "Show all groups (dev mode only)", EditorStyles.toolbarButton); - if (showAllGroups != newShowAllGroups) - EditorPrefs.SetBool("AudioProfilerShowAllGroups", newShowAllGroups); - } - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - - var totalRect = GUILayoutUtility.GetRect(20f, 20000f, 10, 10000f); - var statsRect = new Rect(totalRect.x, totalRect.y, 230f, totalRect.height); - var treeRect = new Rect(statsRect.xMax, totalRect.y, totalRect.width - statsRect.width, totalRect.height); + bool resetAllAudioClipPlayCountsOnPlay = GUILayout.Toggle(AudioUtil.resetAllAudioClipPlayCountsOnPlay, "Reset play count on play", EditorStyles.toolbarButton); + if (resetAllAudioClipPlayCountsOnPlay != AudioUtil.resetAllAudioClipPlayCountsOnPlay) + AudioUtil.resetAllAudioClipPlayCountsOnPlay = resetAllAudioClipPlayCountsOnPlay; + if (Unsupported.IsDeveloperMode()) + { + GUILayout.Space(5); + bool showAllGroups = EditorPrefs.GetBool("AudioProfilerShowAllGroups"); + bool newShowAllGroups = GUILayout.Toggle(showAllGroups, "Show all groups (dev mode only)", EditorStyles.toolbarButton); + if (showAllGroups != newShowAllGroups) + EditorPrefs.SetBool("AudioProfilerShowAllGroups", newShowAllGroups); + } + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); - // STATS - var content = ProfilerDriver.GetOverviewText(m_CurrentArea.Value, GetActiveVisibleFrameIndex()); - var textSize = EditorStyles.wordWrappedLabel.CalcSize(GUIContent.Temp(content)); - m_PaneScroll_AudioChannels = GUI.BeginScrollView(statsRect, m_PaneScroll_AudioChannels, new Rect(0, 0, textSize.x, textSize.y)); - GUI.Label(new Rect(3, 3, textSize.x, textSize.y), content, EditorStyles.wordWrappedLabel); - GUI.EndScrollView(); - EditorGUI.DrawRect(new Rect(statsRect.xMax - 1, statsRect.y, 1, statsRect.height), Color.black); + var treeRect = DrawAudioStatsPane(ref m_PaneScroll_AudioChannels); - // TREE - if (m_AudioProfilerGroupTreeViewState == null) - m_AudioProfilerGroupTreeViewState = new AudioProfilerGroupTreeViewState(); + // TREE + if (m_AudioProfilerGroupTreeViewState == null) + m_AudioProfilerGroupTreeViewState = new AudioProfilerGroupTreeViewState(); - if (m_AudioProfilerGroupViewBackend == null) - m_AudioProfilerGroupViewBackend = new AudioProfilerGroupViewBackend(m_AudioProfilerGroupTreeViewState); + if (m_AudioProfilerGroupViewBackend == null) + m_AudioProfilerGroupViewBackend = new AudioProfilerGroupViewBackend(m_AudioProfilerGroupTreeViewState); - ProfilerProperty property = CreateProperty(); - if (CheckFrameData(property)) - { - if (m_CurrentFrame == -1 || m_LastAudioProfilerFrame != m_CurrentFrame) + ProfilerProperty property = CreateProperty(); + if (CheckFrameData(property)) { - m_LastAudioProfilerFrame = m_CurrentFrame; - var sourceItems = property.GetAudioProfilerGroupInfo(); - if (sourceItems != null && sourceItems.Length > 0) + if (m_CurrentFrame == -1 || m_LastAudioProfilerFrame != m_CurrentFrame) { - var items = new List(); - foreach (var s in sourceItems) - { - bool isGroup = (s.flags & AudioProfilerGroupInfoHelper.AUDIOPROFILER_FLAGS_GROUP) != 0; - if (m_ShowDetailedAudioPane == ProfilerAudioView.Channels && isGroup) - continue; - if (m_ShowDetailedAudioPane == ProfilerAudioView.Groups && !isGroup) - continue; - items.Add(new AudioProfilerGroupInfoWrapper(s, property.GetAudioProfilerNameByOffset(s.assetNameOffset), property.GetAudioProfilerNameByOffset(s.objectNameOffset), m_ShowDetailedAudioPane == ProfilerAudioView.Channels)); - } - m_AudioProfilerGroupViewBackend.SetData(items); - if (m_AudioProfilerGroupView == null) + m_LastAudioProfilerFrame = m_CurrentFrame; + var sourceItems = property.GetAudioProfilerGroupInfo(); + if (sourceItems != null && sourceItems.Length > 0) { - m_AudioProfilerGroupView = new AudioProfilerGroupView(this, m_AudioProfilerGroupTreeViewState); - m_AudioProfilerGroupView.Init(treeRect, m_AudioProfilerGroupViewBackend); + var items = new List(); + foreach (var s in sourceItems) + { + bool isGroup = (s.flags & AudioProfilerGroupInfoHelper.AUDIOPROFILER_FLAGS_GROUP) != 0; + if (m_ShowDetailedAudioPane == ProfilerAudioView.Channels && isGroup) + continue; + if (m_ShowDetailedAudioPane == ProfilerAudioView.Groups && !isGroup) + continue; + items.Add(new AudioProfilerGroupInfoWrapper(s, property.GetAudioProfilerNameByOffset(s.assetNameOffset), property.GetAudioProfilerNameByOffset(s.objectNameOffset), m_ShowDetailedAudioPane == ProfilerAudioView.Channels)); + } + m_AudioProfilerGroupViewBackend.SetData(items); + if (m_AudioProfilerGroupView == null) + { + m_AudioProfilerGroupView = new AudioProfilerGroupView(this, m_AudioProfilerGroupTreeViewState); + m_AudioProfilerGroupView.Init(treeRect, m_AudioProfilerGroupViewBackend); + } } } + if (m_AudioProfilerGroupView != null) + m_AudioProfilerGroupView.OnGUI(treeRect, m_ShowDetailedAudioPane == ProfilerAudioView.Channels); } - if (m_AudioProfilerGroupView != null) - m_AudioProfilerGroupView.OnGUI(treeRect, m_ShowDetailedAudioPane == ProfilerAudioView.Channels); + if (property != null) + property.Dispose(); } - if (property != null) - property.Dispose(); + } + else + { + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); + DrawOverviewText(m_CurrentArea); } } diff --git a/Modules/ProfilerEditor/Public/ProfilerAPI.bindings.cs b/Modules/ProfilerEditor/Public/ProfilerAPI.bindings.cs index b2b687f222..75bb8169db 100644 --- a/Modules/ProfilerEditor/Public/ProfilerAPI.bindings.cs +++ b/Modules/ProfilerEditor/Public/ProfilerAPI.bindings.cs @@ -54,7 +54,7 @@ public enum ProfilerMemoryView public enum ProfilerAudioView { - Stats = 0, + [Obsolete("This has been made obsolete. Audio stats are now shown on every subpane.", true)] Stats = 0, Channels = 1, Groups = 2, ChannelsAndGroups = 3, diff --git a/Modules/ProfilerEditor/Public/ProfilerFrameDataIterator.bindings.cs b/Modules/ProfilerEditor/Public/ProfilerFrameDataIterator.bindings.cs index 19037e8a21..c2ddb37866 100644 --- a/Modules/ProfilerEditor/Public/ProfilerFrameDataIterator.bindings.cs +++ b/Modules/ProfilerEditor/Public/ProfilerFrameDataIterator.bindings.cs @@ -63,6 +63,14 @@ public extern int depth get; } + /// + /// The maximal depth of the stacked samples. This count includes the thread root as well as counters. + /// + public extern int maxDepth + { + get; + } + public extern string path { [NativeMethod("GetFunctionPath")] diff --git a/Modules/ShortcutManagerEditor/ShortcutController.cs b/Modules/ShortcutManagerEditor/ShortcutController.cs index 068fe5f33c..f551108c50 100644 --- a/Modules/ShortcutManagerEditor/ShortcutController.cs +++ b/Modules/ShortcutManagerEditor/ShortcutController.cs @@ -16,11 +16,17 @@ static ShortcutIntegration() { InitializeController(); EditorApplication.globalEventHandler += EventHandler; + EditorApplication.doPressedKeysTriggerAnyShortcut += HasAnyEntriesHandler; // Need to reinitialize after project load if we want menu items EditorApplication.projectWasLoaded += InitializeController; } + static bool HasAnyEntriesHandler() + { + return instance.HasAnyEntries(Event.current); + } + static void EventHandler() { instance.contextManager.SetFocusedWindow(EditorWindow.focusedWindow); @@ -67,6 +73,11 @@ internal void Initialize(IShortcutProfileManager sender) m_Trigger = new Trigger(directory, new ConflictResolver()); } + internal bool HasAnyEntries(Event evt) + { + return m_Trigger.HasAnyEntries(); + } + internal void HandleKeyEvent(Event evt) { m_Trigger.HandleKeyEvent(evt, contextManager); diff --git a/Modules/ShortcutManagerEditor/Trigger.cs b/Modules/ShortcutManagerEditor/Trigger.cs index 3aaf584b68..b388a2588a 100644 --- a/Modules/ShortcutManagerEditor/Trigger.cs +++ b/Modules/ShortcutManagerEditor/Trigger.cs @@ -130,6 +130,11 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) } } + public bool HasAnyEntries() + { + return m_Entries.Any(); + } + // filtered entries are expected to all be in the same context and/or null context and they all are known to share the prefix bool HasConflicts(List filteredEntries, List prefix) { diff --git a/Modules/Tilemap/Managed/GridBrushBase.cs b/Modules/Tilemap/Managed/GridBrushBase.cs index 73c38221d0..9b7bf651bb 100644 --- a/Modules/Tilemap/Managed/GridBrushBase.cs +++ b/Modules/Tilemap/Managed/GridBrushBase.cs @@ -49,5 +49,8 @@ public virtual void Pick(GridLayout gridLayout, GameObject brushTarget, BoundsIn public virtual void Move(GridLayout gridLayout, GameObject brushTarget, BoundsInt from, BoundsInt to) {} public virtual void MoveStart(GridLayout gridLayout, GameObject brushTarget, BoundsInt position) {} public virtual void MoveEnd(GridLayout gridLayout, GameObject brushTarget, BoundsInt position) {} + + public virtual void ChangeZPosition(int change) {} + public virtual void ResetZPosition() {} } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs index 9e14183cba..978133932c 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs @@ -453,6 +453,7 @@ public override int GetHashCode() { hash = tile != null ? tile.GetInstanceID() : 0; hash = hash * 33 + matrix.GetHashCode(); + hash = hash * 33 + matrix.rotation.GetHashCode(); hash = hash * 33 + color.GetHashCode(); } return hash; diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs index 80d520831b..72ceacb7d1 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs @@ -56,6 +56,12 @@ internal static void OnPaintSceneGUIInternal(GridLayout gridLayout, GameObject b } GridEditorUtility.DrawGridMarquee(gridLayout, position, color); + if (position.zMin != 0) + { + var zeroBounds = position; + zeroBounds.zMin = 0; + GridEditorUtility.DrawGridMarquee(gridLayout, zeroBounds, Color.blue); + } } } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteClipboard.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteClipboard.cs index 74278db16c..fcdb778094 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteClipboard.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteClipboard.cs @@ -353,7 +353,7 @@ protected override void OnDisable() public override void OnGUI() { - if (guiRect.width == 0f || guiRect.height == 0f) + if (Mathf.Approximately(guiRect.width, 0f) || Mathf.Approximately(guiRect.height, 0f)) return; UpdateMouseGridPosition(); @@ -389,7 +389,7 @@ public override void OnGUI() public void OnViewSizeChanged(Rect oldSize, Rect newSize) { - if (oldSize.height * oldSize.width * newSize.height * newSize.width == 0f) + if (Mathf.Approximately(oldSize.height * oldSize.width * newSize.height * newSize.width, 0f)) return; Camera cam = previewUtility.camera; @@ -625,13 +625,13 @@ private void RenderDragAndDropPreview() RectInt rect = TileDragAndDrop.GetMinMaxRect(m_HoverData.Keys.ToList()); rect.position += mouseGridPosition; DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - GridEditorUtility.DrawGridMarquee(grid, new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, 0), new Vector3Int(rect.width, rect.height, 1)), Color.white); + GridEditorUtility.DrawGridMarquee(grid, new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, zPosition), new Vector3Int(rect.width, rect.height, 1)), Color.white); } private void RenderGrid() { // MeshTopology.Lines doesn't give nice pixel perfect grid so we have to have separate codepath with MeshTopology.Quads specially for palette window here - if (m_GridMesh == null && grid.cellLayout == Grid.CellLayout.Rectangle) + if (m_GridMesh == null && grid.cellLayout == GridLayout.CellLayout.Rectangle) m_GridMesh = GridEditorUtility.GenerateCachedGridMesh(grid, k_GridColor, 1f / LocalToScreenRatio(), paddedBoundsInt, MeshTopology.Quads); GridEditorUtility.DrawGridGizmo(grid, grid.transform, k_GridColor, ref m_GridMesh, ref m_GridMaterial); @@ -750,7 +750,7 @@ public void SetEditorPreviewTile(Tilemap tilemap, Vector2Int position, TileBase public void SetTile(Tilemap tilemap, Vector2Int position, TileBase tile, Color color, Matrix4x4 matrix) { - Vector3Int pos3 = new Vector3Int(position.x, position.y, 0); + Vector3Int pos3 = new Vector3Int(position.x, position.y, zPosition); tilemap.SetTile(pos3, tile); tilemap.SetColor(pos3, color); tilemap.SetTransformMatrix(pos3, matrix); @@ -809,7 +809,7 @@ protected override void PickBrush(BoundsInt position, Vector3Int pickingStart) gridBrush.Pick(grid, brushTarget, position, pickingStart); if (!PaintableGrid.InGridEditMode()) - EditMode.ChangeEditMode(EditMode.SceneViewEditMode.GridPainting, new Bounds(), GridPaintingState.instance); + EditMode.ChangeEditMode(EditMode.SceneViewEditMode.GridPainting, GridPaintingState.instance); m_ActivePick = new RectInt(position.min.x, position.min.y, position.size.x, position.size.y); } @@ -873,7 +873,7 @@ private void PingTileAsset(RectInt rect) // Only able to ping asset if only one asset is selected if (rect.size == Vector2Int.zero && tilemap != null) { - TileBase tile = tilemap.GetTile(new Vector3Int(rect.xMin, rect.yMin, 0)); + TileBase tile = tilemap.GetTile(new Vector3Int(rect.xMin, rect.yMin, zPosition)); EditorGUIUtility.PingObject(tile); Selection.activeObject = tile; } @@ -931,29 +931,6 @@ protected void DrawSelectionGizmo(RectInt rect) private void HandleMouseEnterLeave() { - if (Event.current.type == EventType.MouseEnterWindow) - { - if (PaintableGrid.InGridEditMode()) - { - GridPaintingState.activeGrid = this; - Event.current.Use(); - } - } - else if (Event.current.type == EventType.MouseLeaveWindow) - { - if (m_PreviousMousePosition.HasValue && guiRect.Contains(m_PreviousMousePosition.Value) && GridPaintingState.activeBrushEditor != null) - { - GridPaintingState.activeBrushEditor.OnMouseLeave(); - } - m_PreviousMousePosition = null; - if (PaintableGrid.InGridEditMode()) - { - GridPaintingState.activeGrid = null; - Event.current.Use(); - Repaint(); - } - } - if (guiRect.Contains(Event.current.mousePosition)) { if (m_PreviousMousePosition.HasValue && !guiRect.Contains(m_PreviousMousePosition.Value) || !m_PreviousMousePosition.HasValue) @@ -998,7 +975,7 @@ private void CallOnPaintSceneGUI(Vector2Int position) rect = new RectInt(GridSelection.position.xMin, GridSelection.position.yMin, GridSelection.position.size.x, GridSelection.position.size.y); var gridLayout = tilemap != null ? tilemap as GridLayout : grid as GridLayout; - BoundsInt brushBounds = new BoundsInt(new Vector3Int(rect.x, rect.y, 0), new Vector3Int(rect.width, rect.height, 1)); + BoundsInt brushBounds = new BoundsInt(new Vector3Int(rect.x, rect.y, zPosition), new Vector3Int(rect.width, rect.height, 1)); if (GridPaintingState.activeBrushEditor != null) GridPaintingState.activeBrushEditor.OnPaintSceneGUI(gridLayout, brushTarget, brushBounds, EditModeToBrushTool(EditMode.editMode), m_MarqueeStart.HasValue || executing); diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs index 04dc841fa8..4cf48e9b5b 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs @@ -97,6 +97,8 @@ static class Styles public static readonly GUIContent tilePalette = EditorGUIUtility.TrTextContent("Tile Palette"); public static readonly GUIContent edit = EditorGUIUtility.TrTextContent("Edit"); public static readonly GUIContent editModified = EditorGUIUtility.TrTextContent("Edit*"); + public static readonly GUIContent zPosition = EditorGUIUtility.TrTextContent("Z Position"); + public static readonly GUIContent resetZPosition = EditorGUIUtility.TrTextContent("Reset"); public static readonly GUIStyle ToolbarTitleStyle = "Toolbar"; public static readonly GUIStyle dragHandle = "RL DragHandle"; public static readonly float dragPadding = 3f; @@ -280,6 +282,31 @@ static void FlipBrushY() FlipBrush(GridBrush.FlipAxis.Y); } + static void ChangeBrushZ(int change) + { + GridPaintingState.gridBrush.ChangeZPosition(change); + GridPaintingState.activeGrid.ChangeZPosition(change); + GridPaintingState.activeGrid.Repaint(); + foreach (var window in GridPaintPaletteWindow.instances) + { + window.Repaint(); + } + } + + [Shortcut("Grid Painting/Increase Z", typeof(ShortcutContext), "-")] + static void IncreaseBrushZ() + { + if (GridPaintingState.gridBrush != null && GridPaintingState.activeGrid != null) + ChangeBrushZ(1); + } + + [Shortcut("Grid Painting/Decrease Z", typeof(ShortcutContext), "=")] + static void DecreaseBrushZ() + { + if (GridPaintingState.gridBrush != null && GridPaintingState.activeGrid != null) + ChangeBrushZ(-1); + } + [SettingsProvider] internal static SettingsProvider CreateSettingsProvider() { @@ -556,7 +583,9 @@ public void SavePalette() GridPaintingState.savingPalette = true; SetHideFlagsRecursivelyIgnoringTilemapChildren(paletteInstance, HideFlags.HideInHierarchy); string path = AssetDatabase.GetAssetPath(palette); + #pragma warning disable CS0618 // Type or member is obsolete PrefabUtility.ReplacePrefabAssetNameBased(paletteInstance, path, true); + #pragma warning restore CS0618 // Type or member is obsolete SetHideFlagsRecursivelyIgnoringTilemapChildren(paletteInstance, HideFlags.HideAndDontSave); GridPaintingState.savingPalette = false; } @@ -688,6 +717,7 @@ public void OnEnable() GridPaintingState.brushChanged += OnBrushChanged; SceneView.onSceneGUIDelegate += OnSceneViewGUI; PrefabUtility.prefabInstanceUpdated += PrefabInstanceUpdated; + EditorApplication.projectWasLoaded += OnProjectLoaded; AssetPreview.SetPreviewTextureCacheSize(256, GetInstanceID()); wantsMouseMove = true; @@ -726,6 +756,12 @@ private void PrefabInstanceUpdated(GameObject updatedPrefab) } } + private void OnProjectLoaded() + { + // ShortcutIntegration instance is recreated after LoadLayout which wipes the OnEnable registration + ShortcutIntegration.instance.contextManager.RegisterToolContext(m_ShortcutContext); + } + private void OnBrushChanged(GridBrushBase brush) { DisableFocus(); @@ -774,6 +810,7 @@ public void OnDisable() GridPaintingState.brushChanged -= OnBrushChanged; GridPaintingState.UnregisterPainterInterest(this); PrefabUtility.prefabInstanceUpdated -= PrefabInstanceUpdated; + EditorApplication.projectWasLoaded -= OnProjectLoaded; ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_ShortcutContext); } @@ -787,7 +824,7 @@ private void OnScenePaintTargetChanged(GameObject scenePaintTarget) public void ChangeToTool(GridBrushBase.Tool tool) { - EditMode.ChangeEditMode(PaintableGrid.BrushToolToEditMode(tool), new Bounds(Vector3.zero, Vector3.positiveInfinity), GridPaintingState.instance); + EditMode.ChangeEditMode(PaintableGrid.BrushToolToEditMode(tool), GridPaintingState.instance); Repaint(); } @@ -838,12 +875,18 @@ private void CallOnToolDeactivated() } } + internal void ResetZPosition() + { + GridPaintingState.gridBrush.ResetZPosition(); + GridPaintingState.lastActiveGrid.ResetZPosition(); + } + private void OnBrushInspectorGUI() { - var brush = GridPaintingState.gridBrush; - if (brush == null) + if (GridPaintingState.gridBrush == null) return; + // Brush Inspector GUI EditorGUI.BeginChangeCheck(); if (GridPaintingState.activeBrushEditor != null) GridPaintingState.activeBrushEditor.OnPaintInspectorGUI(); @@ -853,6 +896,25 @@ private void OnBrushInspectorGUI() { GridPaletteBrushes.ActiveGridBrushAssetChanged(); } + + // Z Position Inspector + var hasLastActiveGrid = GridPaintingState.lastActiveGrid != null; + using (new EditorGUI.DisabledScope(!hasLastActiveGrid)) + { + EditorGUILayout.BeginHorizontal(); + EditorGUI.BeginChangeCheck(); + var zPosition = EditorGUILayout.DelayedIntField(Styles.zPosition, hasLastActiveGrid ? GridPaintingState.lastActiveGrid.zPosition : 0); + if (EditorGUI.EndChangeCheck()) + { + GridPaintingState.gridBrush.ChangeZPosition(zPosition - GridPaintingState.lastActiveGrid.zPosition); + GridPaintingState.lastActiveGrid.zPosition = zPosition; + } + if (GUILayout.Button(Styles.resetZPosition)) + { + ResetZPosition(); + } + EditorGUILayout.EndHorizontal(); + } } private bool IsObjectPrefabInstance(Object target) @@ -938,19 +1000,19 @@ private void SelectTarget(int i, object o) var option = EditorUtility.DisplayDialogComplex(TilePaletteProperties.targetEditModeDialogTitle , TilePaletteProperties.targetEditModeDialogMessage , TilePaletteProperties.targetEditModeDialogYes - , TilePaletteProperties.targetEditModeDialogChange - , TilePaletteProperties.targetEditModeDialogNo); + , TilePaletteProperties.targetEditModeDialogNo + , TilePaletteProperties.targetEditModeDialogChange); switch (option) { case 0: GoToPrefabMode(obj); return; case 1: - var settingsWindow = SettingsWindow.Show(SettingsScopes.User); - settingsWindow.FilterProviders(TilePaletteProperties.targetEditModeLookup); + // Do nothing here for "No" break; case 2: - // Do nothing here for "No" + var settingsWindow = SettingsWindow.Show(SettingsScopes.User); + settingsWindow.FilterProviders(TilePaletteProperties.targetEditModeLookup); break; } } @@ -1037,7 +1099,7 @@ private void OpenAddPalettePopup(Rect rect) private void OnClipboardGUI(Rect position) { - if (Event.current.type != EventType.Layout && position.Contains(Event.current.mousePosition) && GridPaintingState.activeGrid != clipboardView) + if (Event.current.type != EventType.Layout && position.Contains(Event.current.mousePosition) && GridPaintingState.activeGrid != clipboardView && clipboardView.unlocked) { GridPaintingState.activeGrid = clipboardView; SceneView.RepaintAll(); diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs index 7f25f4a305..9010374679 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs @@ -15,6 +15,7 @@ internal class GridPaintingState : ScriptableSingleton, ITool [SerializeField] private GameObject m_ScenePaintTarget; // Which GameObject in scene is considered as painting target [SerializeField] private GridBrushBase m_Brush; // Which brush will handle painting callbacks [SerializeField] private PaintableGrid m_ActiveGrid; // Grid that has painting focus (can be palette, too) + [SerializeField] private PaintableGrid m_LastActiveGrid; // Grid that last had painting focus (can be palette, too) [SerializeField] private HashSet m_InterestedPainters = new HashSet(); // A list of objects that can paint using the GridPaintingState private GameObject[] m_CachedPaintTargets = null; @@ -145,7 +146,17 @@ public static Editor fallbackEditor public static PaintableGrid activeGrid { get { return instance.m_ActiveGrid; } - set { instance.m_ActiveGrid = value; } + set + { + instance.m_ActiveGrid = value; + if (instance.m_ActiveGrid != null) + instance.m_LastActiveGrid = value; + } + } + + public static PaintableGrid lastActiveGrid + { + get { return instance.m_LastActiveGrid; } } public static bool ValidatePaintTarget(GameObject candidate) diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs index b1dced7da9..4003031a24 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs @@ -53,11 +53,13 @@ protected virtual void OnBrushPickCancelled() {} private MarqueeType m_MarqueeType = MarqueeType.None; private bool m_IsExecuting; private EditMode.SceneViewEditMode m_ModeBeforePicking; + private int m_ZPosition; public Vector2Int mouseGridPosition { get { return m_MouseGridPosition; } } public bool isPicking { get { return m_MarqueeType == MarqueeType.Pick; } } public bool isBoxing { get { return m_MarqueeType == MarqueeType.Box; } } public Grid.CellLayout cellLayout { get { return CellLayout(); } } + public int zPosition { get { return m_ZPosition; } set { m_ZPosition = value; } } protected bool executing { get { return m_IsExecuting; } set { m_IsExecuting = value && isHotControl; } } @@ -118,12 +120,17 @@ protected void UpdateMouseGridPosition() newGridPosition.y = m_MouseGridPosition.y + Math.Sign(delta.y) * k_MaxMouseCellDelta; m_PreviousMouseGridPosition = m_MouseGridPosition; m_MouseGridPosition = newGridPosition; - m_MouseGridPositionChanged = true; - m_PositionChangeRepaintDone = false; + MouseGridPositionChanged(); } } } + private void MouseGridPositionChanged() + { + m_MouseGridPositionChanged = true; + m_PositionChangeRepaintDone = false; + } + private void HandleEditModeChange() { // Handles changes in EditMode while tool is expected to be in the same mode @@ -178,7 +185,7 @@ private void HandleBrushPicking() if (evt.type == EventType.MouseDrag && isHotControl && m_MarqueeStart.HasValue && m_MarqueeType == MarqueeType.Pick && IsPickingEvent(evt)) { RectInt rect = GridEditorUtility.GetMarqueeRect(m_MarqueeStart.Value, mouseGridPosition); - OnBrushPickDragged(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, 0), new Vector3Int(rect.size.x, rect.size.y, 1))); + OnBrushPickDragged(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, zPosition), new Vector3Int(rect.size.x, rect.size.y, 1))); Event.current.Use(); GUI.changed = true; } @@ -189,7 +196,7 @@ private void HandleBrushPicking() { RectInt rect = GridEditorUtility.GetMarqueeRect(m_MarqueeStart.Value, mouseGridPosition); Vector2Int pivot = GetMarqueePivot(m_MarqueeStart.Value, mouseGridPosition); - PickBrush(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, 0), new Vector3Int(rect.size.x, rect.size.y, 1)), new Vector3Int(pivot.x, pivot.y, 0)); + PickBrush(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, zPosition), new Vector3Int(rect.size.x, rect.size.y, 1)), new Vector3Int(pivot.x, pivot.y, 0)); if (inEditMode && EditMode.editMode != m_ModeBeforePicking) { @@ -245,7 +252,7 @@ private void HandleSelectTool() if (evt.type == EventType.MouseUp && m_MarqueeType == MarqueeType.Select) { RectInt rect = GridEditorUtility.GetMarqueeRect(m_MarqueeStart.Value, mouseGridPosition); - Select(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, 0), new Vector3Int(rect.size.x, rect.size.y, 1))); + Select(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, zPosition), new Vector3Int(rect.size.x, rect.size.y, 1))); Event.current.Use(); } if (evt.control) @@ -288,7 +295,7 @@ private void HandleMoveTool() { executing = true; BoundsInt previousRect = GridSelection.position; - BoundsInt previousBounds = new BoundsInt(new Vector3Int(previousRect.xMin, previousRect.yMin, 0), new Vector3Int(previousRect.size.x, previousRect.size.y, 1)); + BoundsInt previousBounds = new BoundsInt(new Vector3Int(previousRect.xMin, previousRect.yMin, GridSelection.position.zMin), new Vector3Int(previousRect.size.x, previousRect.size.y, 1)); Vector2Int direction = mouseGridPosition - m_PreviousMove.Value; BoundsInt pos = GridSelection.position; @@ -326,13 +333,13 @@ private void HandleBrushPaintAndErase() { if (EditMode.editMode != EditMode.SceneViewEditMode.GridEraser) EditMode.ChangeEditMode(EditMode.SceneViewEditMode.GridEraser, GridPaintingState.instance); - Erase(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, 0)); + Erase(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, zPosition)); } else { if (EditMode.editMode != EditMode.SceneViewEditMode.GridPainting) EditMode.ChangeEditMode(EditMode.SceneViewEditMode.GridPainting, GridPaintingState.instance); - Paint(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, 0)); + Paint(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, zPosition)); } Event.current.Use(); @@ -350,9 +357,9 @@ private void HandleBrushPaintAndErase() for (int i = 1; i < points.Count; i++) { if (IsErasingEvent(evt)) - Erase(new Vector3Int(points[i].x, points[i].y, 0)); + Erase(new Vector3Int(points[i].x, points[i].y, zPosition)); else - Paint(new Vector3Int(points[i].x, points[i].y, 0)); + Paint(new Vector3Int(points[i].x, points[i].y, zPosition)); } Event.current.Use(); GUI.changed = true; @@ -405,7 +412,7 @@ private void HandleFloodFill() { executing = false; RegisterUndo(); - FloodFill(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, 0)); + FloodFill(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, zPosition)); GUI.changed = true; Event.current.Use(); GUIUtility.hotControl = 0; @@ -442,9 +449,9 @@ private void HandleBoxTool() RegisterUndo(); RectInt rect = GridEditorUtility.GetMarqueeRect(m_MarqueeStart.Value, mouseGridPosition); if (evt.shift) - BoxErase(new BoundsInt(rect.x, rect.y, 0, rect.size.x, rect.size.y, 1)); + BoxErase(new BoundsInt(rect.x, rect.y, zPosition, rect.size.x, rect.size.y, 1)); else - BoxFill(new BoundsInt(rect.x, rect.y, 0, rect.size.x, rect.size.y, 1)); + BoxFill(new BoundsInt(rect.x, rect.y, zPosition, rect.size.x, rect.size.y, 1)); Event.current.Use(); executing = false; GUI.changed = true; @@ -464,6 +471,23 @@ private Vector2Int GetMarqueePivot(Vector2Int start, Vector2Int end) return pivot; } + public void ChangeZPosition(int change) + { + m_ZPosition += change; + MouseGridPositionChanged(); + Repaint(); + } + + public void ResetZPosition() + { + if (m_ZPosition == 0) + return; + + m_ZPosition = 0; + MouseGridPositionChanged(); + Repaint(); + } + public static bool InGridEditMode() { return diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs index f8f53f27df..4e5f28982b 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs @@ -320,16 +320,16 @@ void CallOnPaintSceneGUI() rect = new RectInt(GridSelection.position.xMin, GridSelection.position.yMin, GridSelection.position.size.x, GridSelection.position.size.y); var layoutGrid = tilemap != null ? tilemap as GridLayout : grid as GridLayout; - + BoundsInt brushBounds = new BoundsInt(new Vector3Int(rect.x, rect.y, zPosition), new Vector3Int(rect.width, rect.height, 1)); if (GridPaintingState.activeBrushEditor != null) { - GridPaintingState.activeBrushEditor.OnPaintSceneGUI(layoutGrid, brushTarget, - new BoundsInt(new Vector3Int(rect.x, rect.y, 0), new Vector3Int(rect.width, rect.height, 1)), - EditModeToBrushTool(EditMode.editMode), m_MarqueeStart.HasValue || executing); + GridPaintingState.activeBrushEditor.OnPaintSceneGUI(layoutGrid, brushTarget, brushBounds + , EditModeToBrushTool(EditMode.editMode), m_MarqueeStart.HasValue || executing); } else // Fallback when user hasn't defined custom editor { - GridBrushEditorBase.OnPaintSceneGUIInternal(layoutGrid, brushTarget, new BoundsInt(new Vector3Int(rect.x, rect.y, 0), new Vector3Int(rect.width, rect.height, 1)), EditModeToBrushTool(EditMode.editMode), m_MarqueeStart.HasValue || executing); + GridBrushEditorBase.OnPaintSceneGUIInternal(layoutGrid, brushTarget, brushBounds + , EditModeToBrushTool(EditMode.editMode), m_MarqueeStart.HasValue || executing); } } diff --git a/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs b/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs index 36b436c627..292b2177bc 100644 --- a/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs +++ b/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs @@ -30,8 +30,10 @@ private static class Styles public static readonly GUIContent tilemapColorLabel = EditorGUIUtility.TrTextContent("Color", "Color tinting all Sprites from tiles in the tilemap"); public static readonly GUIContent tileAnchorLabel = EditorGUIUtility.TrTextContent("Tile Anchor", "Anchoring position for Sprites from tiles in the tilemap"); public static readonly GUIContent orientationLabel = EditorGUIUtility.TrTextContent("Orientation", "Orientation for tiles in the tilemap"); - public static readonly GUIContent pointTopHexagonCreateUndo = EditorGUIUtility.TrTextContent("Hexagonal Point Top Tilemap"); - public static readonly GUIContent flatTopHexagonCreateUndo = EditorGUIUtility.TrTextContent("Hexagonal Flat Top Tilemap"); + public static readonly string pointTopHexagonCreateUndo = L10n.Tr("Hexagonal Point Top Tilemap"); + public static readonly string flatTopHexagonCreateUndo = L10n.Tr("Hexagonal Flat Top Tilemap"); + public static readonly string isometricCreateUndo = L10n.Tr("Isometric Tilemap"); + public static readonly string isometricZAsYCreateUndo = L10n.Tr("Isometric Z As Y Tilemap"); } private void OnEnable() @@ -89,17 +91,28 @@ internal static void CreateRectangularTilemap() [MenuItem("GameObject/2D Object/Hexagonal Point Top Tilemap")] internal static void CreateHexagonalPointTopTilemap() { - CreateHexagonalTilemap(GridLayout.CellSwizzle.XYZ, Styles.pointTopHexagonCreateUndo.text); + CreateHexagonalTilemap(GridLayout.CellSwizzle.XYZ, Styles.pointTopHexagonCreateUndo); } [MenuItem("GameObject/2D Object/Hexagonal Flat Top Tilemap")] internal static void CreateHexagonalFlatTopTilemap() { - CreateHexagonalTilemap(GridLayout.CellSwizzle.YXZ, Styles.flatTopHexagonCreateUndo.text); + CreateHexagonalTilemap(GridLayout.CellSwizzle.YXZ, Styles.flatTopHexagonCreateUndo); } [MenuItem("GameObject/2D Object/Isometric Tilemap")] internal static void CreateIsometricTilemap() + { + CreateIsometricTilemap(GridLayout.CellLayout.Isometric, Styles.isometricCreateUndo); + } + + [MenuItem("GameObject/2D Object/Isometric Z As Y Tilemap")] + internal static void CreateIsometricZAsYTilemap() + { + CreateIsometricTilemap(GridLayout.CellLayout.IsometricZAsY, Styles.isometricZAsYCreateUndo); + } + + private static void CreateIsometricTilemap(GridLayout.CellLayout isometricLayout, string undoMessage) { var root = FindOrCreateRootGrid(); var uniqueName = GameObjectUtility.GetUniqueNameForSibling(root.transform, "Tilemap"); @@ -108,12 +121,16 @@ internal static void CreateIsometricTilemap() tilemapGO.transform.position = Vector3.zero; var grid = root.GetComponent(); - grid.cellLayout = Grid.CellLayout.Isometric; - grid.cellSize = new Vector3(1.0f, 0.5f, 0.0f); + // Case 1071703: Do not reset cell size if adding a new Tilemap to an existing Grid of the same layout + if (isometricLayout != grid.cellLayout) + { + grid.cellLayout = isometricLayout; + grid.cellSize = new Vector3(1.0f, 0.5f, 0.0f); + } var tilemapRenderer = tilemapGO.GetComponent(); tilemapRenderer.sortOrder = TilemapRenderer.SortOrder.TopRight; - Undo.RegisterCreatedObjectUndo(tilemapGO, "Create Isometric Tilemap"); + Undo.RegisterCreatedObjectUndo(tilemapGO, undoMessage); } private static void CreateHexagonalTilemap(GridLayout.CellSwizzle swizzle, string undoMessage) diff --git a/Modules/TreeEditor/TreeEditor.cs b/Modules/TreeEditor/TreeEditor.cs index 23a43f22f9..8ee5d00614 100644 --- a/Modules/TreeEditor/TreeEditor.cs +++ b/Modules/TreeEditor/TreeEditor.cs @@ -310,8 +310,6 @@ static void CreateNewTree(MenuCommand menuCommand) AssetDatabase.AddObjectToAsset(materialCutoutAsset, prefabAsset); AssetDatabase.AddObjectToAsset(data, prefabAsset); - PrefabUtility.ApplyPrefabInstance(prefabInstance); - GameObjectUtility.SetParentAndAlign(prefabInstance, menuCommand.context as GameObject); // Store Creation undo diff --git a/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs b/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs index 5bd23f2bf8..56e7db50de 100644 --- a/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs +++ b/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs @@ -83,6 +83,8 @@ internal static bool SendCollabOperation(object parameters) return EditorAnalytics.SendEvent("collabOperation", parameters); } + internal extern static bool SendAssetDownloadEvent(object parameters); + public extern static bool enabled { get; diff --git a/Modules/UnityWebRequestAudio/Public/DownloadHandlerAudio.bindings.cs b/Modules/UnityWebRequestAudio/Public/DownloadHandlerAudio.bindings.cs index dbc8c4accb..75c3447496 100644 --- a/Modules/UnityWebRequestAudio/Public/DownloadHandlerAudio.bindings.cs +++ b/Modules/UnityWebRequestAudio/Public/DownloadHandlerAudio.bindings.cs @@ -40,6 +40,7 @@ protected override string GetText() throw new System.NotSupportedException("String access is not supported for audio clips"); } + [NativeThrows] public extern AudioClip audioClip { get; } public extern bool streamAudio { get; set; } diff --git a/Modules/XR/ScriptBindings/XRInput.bindings.cs b/Modules/XR/ScriptBindings/XRInput.bindings.cs index 461c5f7a68..b836986d97 100644 --- a/Modules/XR/ScriptBindings/XRInput.bindings.cs +++ b/Modules/XR/ScriptBindings/XRInput.bindings.cs @@ -20,13 +20,11 @@ public struct HapticCapabilities : IEquatable bool m_SupportsImpulse; bool m_SupportsBuffer; uint m_BufferFrequencyHz; - uint m_BufferMaxSize; public uint numChannels { get { return m_NumChannels; } internal set { m_NumChannels = value; } } public bool supportsImpulse { get { return m_SupportsImpulse; } internal set { m_SupportsImpulse = value; } } public bool supportsBuffer { get { return m_SupportsBuffer; } internal set { m_SupportsBuffer = value; } } public uint bufferFrequencyHz { get { return m_BufferFrequencyHz; } internal set { m_BufferFrequencyHz = value; } } - public uint bufferMaxSize { get { return m_BufferMaxSize; } internal set { m_BufferMaxSize = value; } } public override bool Equals(object obj) { @@ -41,8 +39,7 @@ public bool Equals(HapticCapabilities other) return numChannels == other.numChannels && supportsImpulse == other.supportsImpulse && supportsBuffer == other.supportsBuffer && - bufferFrequencyHz == other.bufferFrequencyHz && - bufferMaxSize == other.bufferMaxSize; + bufferFrequencyHz == other.bufferFrequencyHz; } public override int GetHashCode() @@ -50,68 +47,78 @@ public override int GetHashCode() return numChannels.GetHashCode() ^ (supportsImpulse.GetHashCode() << 1) ^ (supportsBuffer.GetHashCode() >> 1) ^ - (bufferFrequencyHz.GetHashCode() << 2) ^ - (bufferMaxSize.GetHashCode() >> 2); + (bufferFrequencyHz.GetHashCode() << 2); + } + + public static bool operator==(HapticCapabilities a, HapticCapabilities b) + { + return a.Equals(b); + } + + public static bool operator!=(HapticCapabilities a, HapticCapabilities b) + { + return !(a == b); } } + [UsedByNativeCode] [StructLayout(LayoutKind.Sequential)] [NativeConditional("ENABLE_VR")] - public struct HapticState : IEquatable + [NativeHeader("Modules/XR/Subsystems/Input/Public/XRInputTrackingFacade.h")] + public struct InputDevice : IEquatable { - uint m_SamplesQueued; - uint m_SamplesAvailable; + private UInt64 m_DeviceId; - public uint samplesQueued { get { return m_SamplesQueued; } internal set { m_SamplesQueued = value; } } - public uint samplesAvailable { get { return m_SamplesAvailable; } internal set { m_SamplesAvailable = value; } } + internal InputDevice(UInt64 deviceId) { m_DeviceId = deviceId; } + + public bool IsValid { get { return InputTracking.IsDeviceValid(m_DeviceId); } } + + // Haptics + public bool SendHapticImpulse(uint channel, float amplitude, float duration = 1.0f) { return InputTracking.SendHapticImpulse(m_DeviceId, channel, amplitude, duration); } + public bool SendHapticBuffer(uint channel, byte[] buffer) { return InputTracking.SendHapticBuffer(m_DeviceId, channel, buffer); } + public bool TryGetHapticCapabilities(out HapticCapabilities capabilities) { return InputTracking.TryGetHapticCapabilities(m_DeviceId, out capabilities); } + public void StopHaptics() { InputTracking.StopHaptics(m_DeviceId); } public override bool Equals(object obj) { - if (!(obj is HapticState)) + if (!(obj is InputDevice)) return false; - return Equals((HapticState)obj); + return Equals((InputDevice)obj); } - public bool Equals(HapticState other) + public bool Equals(InputDevice other) { - return samplesQueued == other.samplesQueued && - samplesAvailable == other.samplesAvailable; + return m_DeviceId == other.m_DeviceId; } public override int GetHashCode() { - return samplesQueued.GetHashCode() ^ (samplesAvailable.GetHashCode() << 2); + return m_DeviceId.GetHashCode(); + } + + public static bool operator==(InputDevice a, InputDevice b) + { + return a.Equals(b); + } + + public static bool operator!=(InputDevice a, InputDevice b) + { + return !(a == b); } } [NativeHeader("Modules/XR/Subsystems/Input/Public/XRInputTrackingFacade.h")] [NativeConditional("ENABLE_VR")] [StaticAccessor("XRInputTrackingFacade::Get()", StaticAccessorType.Dot)] - public partial class InputHaptic + public partial class InputDevices { - [NativeConditional("ENABLE_VR")] - bool SendImpulse(XRNode node, uint channel, float amplitude) { return SendImpulse(node, channel, amplitude, 1.0f); } - - [NativeConditional("ENABLE_VR")] - [NativeMethod("SendHapticImpulse")] - extern public static bool SendImpulse(XRNode node, uint channel, float amplitude, [UnityEngine.Internal.DefaultValue("1.0f")] float frequency); - - [NativeConditional("ENABLE_VR")] - [NativeMethod("SendHapticBuffer")] - extern public static bool SendBuffer(XRNode node, uint channel, byte[] buffer); - - [NativeConditional("ENABLE_VR", "false")] - [NativeMethod("TryGetHapticCapabilities")] - extern public static bool TryGetCapabilities(XRNode node, out HapticCapabilities capabilities); - - [NativeConditional("ENABLE_VR", "false")] - [NativeMethod("TryGetHapticState")] - extern public static bool TryGetState(XRNode node, out HapticState state); - - [NativeConditional("ENABLE_VR")] - [NativeMethod("StopHaptics")] - extern public static void Stop(XRNode node); + [NativeConditional("ENABLE_VR", "InputDevice::Identity")] + public static InputDevice GetDeviceAtXRNode(XRNode node) + { + UInt64 deviceId = InputTracking.GetDeviceIdAtXRNode(node); + return new InputDevice(deviceId); + } } [NativeHeader("Modules/XR/Subsystems/Input/Public/XRInputTrackingFacade.h")] @@ -156,5 +163,13 @@ extern public static bool disablePositionalTracking [NativeName("SetPositionalTrackingDisabled")] set; } + + internal static extern bool SendHapticImpulse(UInt64 deviceId, uint channel, float amplitude, float duration); + internal static extern bool SendHapticBuffer(UInt64 deviceId, uint channel, byte[] buffer); + internal static extern bool TryGetHapticCapabilities(UInt64 deviceId, out HapticCapabilities capabilities); + internal static extern void StopHaptics(UInt64 deviceId); + + internal static extern bool IsDeviceValid(UInt64 deviceId); + internal static extern UInt64 GetDeviceIdAtXRNode(XRNode node); } } diff --git a/README.md b/README.md index b8559e74df..f414498bbd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0a11 C# reference source code +## Unity 2018.3.0b1 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Export/Camera.bindings.cs b/Runtime/Export/Camera.bindings.cs index a34e8b2ccf..c27dd8219c 100644 --- a/Runtime/Export/Camera.bindings.cs +++ b/Runtime/Export/Camera.bindings.cs @@ -274,7 +274,7 @@ public bool RenderToCubemap(RenderTexture cubemap, int faceMask, MonoOrStereosco public void AddCommandBuffer(CameraEvent evt, CommandBuffer buffer) { - if (!Enum.IsDefined(typeof(CameraEvent), evt)) + if (!Rendering.CameraEventUtils.IsValid(evt)) throw new ArgumentException(string.Format(@"Invalid CameraEvent value ""{0}"".", (int)evt), "evt"); if (buffer == null) throw new NullReferenceException("buffer is null"); AddCommandBufferImpl(evt, buffer); @@ -282,7 +282,7 @@ public void AddCommandBuffer(CameraEvent evt, CommandBuffer buffer) public void AddCommandBufferAsync(CameraEvent evt, CommandBuffer buffer, ComputeQueueType queueType) { - if (!Enum.IsDefined(typeof(CameraEvent), evt)) + if (!Rendering.CameraEventUtils.IsValid(evt)) throw new ArgumentException(string.Format(@"Invalid CameraEvent value ""{0}"".", (int)evt), "evt"); if (buffer == null) throw new NullReferenceException("buffer is null"); AddCommandBufferAsyncImpl(evt, buffer, queueType); @@ -290,7 +290,7 @@ public void AddCommandBufferAsync(CameraEvent evt, CommandBuffer buffer, Compute public void RemoveCommandBuffer(CameraEvent evt, CommandBuffer buffer) { - if (!Enum.IsDefined(typeof(CameraEvent), evt)) + if (!Rendering.CameraEventUtils.IsValid(evt)) throw new ArgumentException(string.Format(@"Invalid CameraEvent value ""{0}"".", (int)evt), "evt"); if (buffer == null) throw new NullReferenceException("buffer is null"); RemoveCommandBufferImpl(evt, buffer); diff --git a/Runtime/Export/GI/DynamicGI.bindings.cs b/Runtime/Export/GI/DynamicGI.bindings.cs index 04a31065e6..b4e134a2a3 100644 --- a/Runtime/Export/GI/DynamicGI.bindings.cs +++ b/Runtime/Export/GI/DynamicGI.bindings.cs @@ -12,10 +12,13 @@ public sealed partial class DynamicGI { public static float indirectScale { get { return 0.0f; } set {} } public static float updateThreshold { get { return 0.0f; } set {} } + public static int materialUpdateTimeSlice { get { return 0; } set {} } public static void SetEmissive(Renderer renderer, Color color) {} public static void SetEnvironmentData(float[] input) {} public static bool synchronousMode { get { return false; } set {} } public static bool isConverged { get { return false; } } + + internal static int scheduledMaterialUpdatesCount { get { return 0; } } public static extern void UpdateEnvironment(); [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] diff --git a/Runtime/Export/GraphicsEnums.cs b/Runtime/Export/GraphicsEnums.cs index 1546184f20..b1ac63f5e6 100644 --- a/Runtime/Export/GraphicsEnums.cs +++ b/Runtime/Export/GraphicsEnums.cs @@ -961,6 +961,17 @@ public enum CameraEvent AfterHaloAndLensFlares } + internal static class CameraEventUtils + { + const CameraEvent k_MinimumValue = CameraEvent.BeforeDepthTexture; + const CameraEvent k_MaximumValue = CameraEvent.AfterHaloAndLensFlares; + + public static bool IsValid(CameraEvent value) + { + return value >= k_MinimumValue && value <= k_MaximumValue; + } + } + // Keep in sync with RenderLightEventType in Runtime/Graphics/CommandBuffer/RenderingEvents.h public enum LightEvent { diff --git a/Runtime/Export/SystemInfo.bindings.cs b/Runtime/Export/SystemInfo.bindings.cs index 6125bb74a1..23fa6dc4ed 100644 --- a/Runtime/Export/SystemInfo.bindings.cs +++ b/Runtime/Export/SystemInfo.bindings.cs @@ -214,6 +214,11 @@ public static bool graphicsMultiThreaded get { return GetGraphicsMultiThreaded(); } } + public static bool hasHiddenSurfaceRemovalOnGPU + { + get { return HasHiddenSurfaceRemovalOnGPU(); } + } + // Are built-in shadows supported? (RO) public static bool supportsShadows { @@ -527,6 +532,9 @@ public static int graphicsPixelFillrate [FreeFunction("ScriptingGraphicsCaps::GetGraphicsMultiThreaded")] static extern bool GetGraphicsMultiThreaded(); + [FreeFunction("ScriptingGraphicsCaps::HasHiddenSurfaceRemovalOnGPU")] + static extern bool HasHiddenSurfaceRemovalOnGPU(); + [FreeFunction("ScriptingGraphicsCaps::SupportsShadows")] static extern bool SupportsShadows(); diff --git a/Runtime/Export/Vector3Int.cs b/Runtime/Export/Vector3Int.cs index d7871a42a8..15e21aa1f8 100644 --- a/Runtime/Export/Vector3Int.cs +++ b/Runtime/Export/Vector3Int.cs @@ -177,7 +177,9 @@ public bool Equals(Vector3Int other) public override int GetHashCode() { - return x.GetHashCode() ^ (y.GetHashCode() << 2) ^ (z.GetHashCode() >> 2); + var yHash = y.GetHashCode(); + var zHash = z.GetHashCode(); + return x.GetHashCode() ^ (yHash << 4) ^ (yHash >> 28) ^ (zHash >> 4) ^ (zHash << 28); } public override string ToString() diff --git a/Runtime/Networking/Managed/MatchMakingClient.cs b/Runtime/Networking/Managed/MatchMakingClient.cs index 79df91f44d..4725689b0a 100644 --- a/Runtime/Networking/Managed/MatchMakingClient.cs +++ b/Runtime/Networking/Managed/MatchMakingClient.cs @@ -12,6 +12,7 @@ namespace UnityEngine.Networking.Match { // returned when you create or join a match (private info) //[Serializable] //TODO: enabled this when 64 bit enum issue is resolved + [Obsolete("The matchmaker and relay feature will be removed in the future, minimal support will continue until this can be safely done.")] public class MatchInfo { public string address { get; private set; } @@ -53,6 +54,7 @@ public override string ToString() } } + [Obsolete("The matchmaker and relay feature will be removed in the future, minimal support will continue until this can be safely done.")] public class MatchInfoSnapshot { public NetworkID networkId { get; private set; } @@ -109,6 +111,7 @@ internal MatchInfoSnapshot(MatchDesc matchDesc) } } + [Obsolete("The matchmaker and relay feature will be removed in the future, minimal support will continue until this can be safely done.")] public class NetworkMatch : MonoBehaviour { public delegate void BasicResponseDelegate(bool success, string extendedInfo); @@ -137,11 +140,9 @@ public Coroutine CreateMatch(string matchName, uint matchSize, bool matchAdverti Debug.LogError("Matchmaking is not supported on WebGL player."); return null; } - else - return CreateMatch(new CreateMatchRequest { name = matchName, size = matchSize, advertise = matchAdvertise, password = matchPassword, publicAddress = publicClientAddress, privateAddress = privateClientAddress, eloScore = eloScoreForMatch, domain = requestDomain }, callback); + return CreateMatch(new CreateMatchRequest { name = matchName, size = matchSize, advertise = matchAdvertise, password = matchPassword, publicAddress = publicClientAddress, privateAddress = privateClientAddress, eloScore = eloScoreForMatch, domain = requestDomain }, callback); } - // Begin Create a match internal Coroutine CreateMatch(CreateMatchRequest req, DataResponseDelegate callback) { if (callback == null) diff --git a/Runtime/Networking/Managed/NetworkTransportConfig.cs b/Runtime/Networking/Managed/NetworkTransportConfig.cs index 9bdf9f3b57..84450263db 100644 --- a/Runtime/Networking/Managed/NetworkTransportConfig.cs +++ b/Runtime/Networking/Managed/NetworkTransportConfig.cs @@ -68,6 +68,7 @@ public enum ConnectionAcksType }; [Serializable] + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public class ChannelQOS { [SerializeField] @@ -105,6 +106,7 @@ public ChannelQOS(ChannelQOS channel) //to allow user manipulate channel info via property with parameter (using array interface) //all fields are defined for direct access from HLAPI (it it needed) [Serializable] + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public class ConnectionConfig { private const int g_MinPacketSize = 128; @@ -502,6 +504,7 @@ public IList GetSharedOrderChannels(byte idx) //and array of special connection (with special configuration) //AddSpecialConnection will return connection id which user should use when he call connect to identify special configuration for this connection [Serializable] + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public class HostTopology { [SerializeField] @@ -589,6 +592,7 @@ public int AddSpecialConnectionConfig(ConnectionConfig config) } [Serializable] + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public class GlobalConfig { private const uint g_MaxTimerTimeout = 12000; //before changing check UNETConfiguration.h file @@ -753,6 +757,7 @@ public Action ConnectionReadyForSend } } + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public class ConnectionSimulatorConfig : IDisposable { internal int m_OutMinDelay; diff --git a/Runtime/Networking/ScriptBindings/UNETTransportConfig.bindings.cs b/Runtime/Networking/ScriptBindings/UNETTransportConfig.bindings.cs index a170c1b9ed..10e043cef8 100644 --- a/Runtime/Networking/ScriptBindings/UNETTransportConfig.bindings.cs +++ b/Runtime/Networking/ScriptBindings/UNETTransportConfig.bindings.cs @@ -13,6 +13,7 @@ namespace UnityEngine.Networking { +#pragma warning disable 618 [NativeHeader("Runtime/Networking/UNETManager.h")] [NativeHeader("Runtime/Networking/UNetTypes.h")] @@ -308,4 +309,5 @@ public void Dispose() [NativeProperty("m_MaxNetSimulatorTimeout", TargetType.Field)] private extern uint MaxNetSimulatorTimeout { set; } } +#pragma warning restore 618 } diff --git a/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs b/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs index c5eafd5400..0d8523ddf3 100644 --- a/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs +++ b/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs @@ -19,6 +19,7 @@ namespace UnityEngine.Networking [NativeHeader("Runtime/Networking/UNetTypes.h")] [NativeHeader("Runtime/Networking/UNETConfiguration.h")] [NativeConditional("ENABLE_NETWORK && ENABLE_UNET", true)] + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public sealed partial class NetworkTransport { private NetworkTransport() {} diff --git a/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs b/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs index dc9144cefa..38177b0d47 100644 --- a/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs +++ b/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs @@ -61,6 +61,7 @@ public static void TakeTempSnapshot(Action finishCallback, Captur TakeSnapshot(path, finishCallback, captureFlags); } + [RequiredByNativeCode] static byte[] PrepareMetadata() { if (createMetaData == null) @@ -71,6 +72,9 @@ static byte[] PrepareMetadata() MetaData data = new MetaData(); createMetaData(data); + if (data.content == null) data.content = ""; + if (data.platform == null) data.platform = ""; + int contentLength = sizeof(char) * data.content.Length; int platformLength = sizeof(char) * data.platform.Length; @@ -164,6 +168,7 @@ private static int WriteStringToByteArray(byte[] array, int offset, string value return offset; } + [RequiredByNativeCode] static void FinalizeSnapshot(string path, bool result) { if (snapshotFinished != null) From 198807ef34ab2add31864ce43a1b84ba79b57762 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 26 Sep 2018 13:21:30 +0000 Subject: [PATCH 13/17] Unity 2018.3.0b3 C# reference source code --- .../Mono/Animation/AnimationMode.bindings.cs | 3 + .../Animation/AnimationUtility.bindings.cs | 6 + .../AnimationWindow/AddCurvesPopup.cs | 23 +- .../AddCurvesPopupHierarchy.cs | 13 +- .../AddCurvesPopupHierarchyDataSource.cs | 1 + .../AddCurvesPopupHierarchyGUI.cs | 84 ++++++- Editor/Mono/Animation/ZoomableArea.cs | 17 +- .../AssetPipeline/TextureImporter.bindings.cs | 30 ++- Editor/Mono/AssetPostprocessor.cs | 14 +- Editor/Mono/BuildPipeline/AssemblyStripper.cs | 10 - Editor/Mono/ContainerWindow.cs | 4 +- Editor/Mono/EditorWindow.cs | 15 +- Editor/Mono/GUI/ColorPicker.cs | 2 +- Editor/Mono/GUI/DockArea.cs | 48 ++-- Editor/Mono/GUI/MainView.cs | 2 +- Editor/Mono/GUI/PaneDragTab.cs | 4 +- Editor/Mono/GUI/SplitView.cs | 4 +- Editor/Mono/GUI/WindowLayout.cs | 4 +- Editor/Mono/HostView.cs | 75 +++--- .../ImportSettings/AssetImporterEditor.cs | 4 +- .../DesktopPluginImporterExtension.cs | 2 +- Editor/Mono/Inspector/AnimationClipEditor.cs | 8 +- Editor/Mono/Inspector/GameObjectInspector.cs | 105 ++++---- Editor/Mono/Inspector/InspectorWindow.cs | 2 +- .../Inspector/LightingSettingsInspector.cs | 19 +- Editor/Mono/Inspector/MaterialEditor.cs | 1 + .../Inspector/MaterialEditorGUIHelpers.cs | 4 + Editor/Mono/Menu.bindings.cs | 3 + Editor/Mono/PackageUtility.bindings.cs | 3 + .../ParticleSystemModules/InitialModuleUI.cs | 12 + .../ParticleSystemEditor/ParticleSystemUI.cs | 2 +- Editor/Mono/Prefabs/PrefabImporterEditor.cs | 13 + .../PrefabOverrides/PrefabOverridesWindow.cs | 227 ++++++++++++----- Editor/Mono/Prefabs/PrefabUtility.bindings.cs | 14 +- Editor/Mono/Prefabs/PrefabUtility.cs | 231 ++++++++++++------ Editor/Mono/ProjectBrowser.cs | 7 + .../StageManager/PrefabStage/PrefabStage.cs | 40 ++- .../LightingWindowBakeSettings.cs | 26 +- .../Mono/SceneView/SceneViewStageHandling.cs | 25 +- .../Compilers/MicrosoftCSharpCompiler.cs | 3 +- .../ScriptCompilation/EditorCompilation.cs | 4 +- .../Providers/AssetSettingsProvider.cs | 12 + Editor/Mono/Settings/SettingsService.cs | 27 +- .../Mono/SpriteEditor/SpriteEditorWindow.cs | 25 +- Editor/Mono/UIElements/Controls/CurveField.cs | 5 +- Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs | 10 + Modules/AI/NavMesh/NavMesh.bindings.cs | 2 +- .../ImportSettings/ModelImporterEditor.cs | 13 + Modules/IMGUI/GUIStyle.cs | 5 + Modules/PresetsEditor/PresetManagerEditor.cs | 1 + .../ShortcutManagerEditor/ConflictResolver.cs | 2 +- .../ShortcutManagerEditor/ContextManager.cs | 15 +- Modules/ShortcutManagerEditor/Directory.cs | 6 + .../IConflictResolver.cs | 2 +- Modules/ShortcutManagerEditor/Trigger.cs | 24 +- Modules/UIElements/ImmediateStylePainter.cs | 14 +- Modules/UIElements/StylePainter.cs | 4 +- Projects/CSharp/UnityEngine.csproj | 3 + README.md | 2 +- .../SpriteDataAccess.bindings.cs | 2 +- Runtime/Export/AnimationCurve.bindings.cs | 12 + .../Scripting/GarbageCollector.bindings.cs | 46 ++++ Runtime/Export/Texture.cs | 1 + .../Managed/ParticleSystem.deprecated.cs | 45 ++-- .../Managed/ParticleSystemEnums.cs | 9 + .../ScriptBindings/ParticleSystem.bindings.cs | 2 +- .../Editor/ModuleMetadataBindings.gen.cs | 8 + .../ParticleSystemBindings.gen.cs | 9 + 68 files changed, 1034 insertions(+), 386 deletions(-) create mode 100644 Runtime/Export/Scripting/GarbageCollector.bindings.cs diff --git a/Editor/Mono/Animation/AnimationMode.bindings.cs b/Editor/Mono/Animation/AnimationMode.bindings.cs index c3b411f482..2b30484c29 100644 --- a/Editor/Mono/Animation/AnimationMode.bindings.cs +++ b/Editor/Mono/Animation/AnimationMode.bindings.cs @@ -146,6 +146,9 @@ internal static void StartAnimationRecording() [NativeThrows] extern public static void AddPropertyModification(EditorCurveBinding binding, PropertyModification modification, bool keepPrefabOverride); + [NativeThrows] + extern public static void AddEditorCurveBinding([NotNull] GameObject gameObject, EditorCurveBinding binding); + [NativeThrows] extern internal static void AddTransformTR([NotNull] GameObject root, string path); diff --git a/Editor/Mono/Animation/AnimationUtility.bindings.cs b/Editor/Mono/Animation/AnimationUtility.bindings.cs index dd22c87e44..b2ede18a80 100644 --- a/Editor/Mono/Animation/AnimationUtility.bindings.cs +++ b/Editor/Mono/Animation/AnimationUtility.bindings.cs @@ -143,8 +143,14 @@ internal static EditorCurveBinding[] GetAnimatableBindings(ScriptableObject scri return Internal_GetScriptableObjectAnimatableBindings(scriptableObject); } + internal static EditorCurveBinding[] GetAdditionalAnimatorBindings(GameObject targetObject) + { + return Internal_GetAdditionalAnimatorBindings(targetObject); + } + extern private static EditorCurveBinding[] Internal_GetGameObjectAnimatableBindings([NotNull] GameObject targetObject, [NotNull] GameObject root); extern private static EditorCurveBinding[] Internal_GetScriptableObjectAnimatableBindings([NotNull] ScriptableObject scriptableObject); + extern private static EditorCurveBinding[] Internal_GetAdditionalAnimatorBindings([NotNull] GameObject targetObject); // 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) // null if it can't be bound. diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs index 84e4b40e80..7bece927e0 100644 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs +++ b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs @@ -13,6 +13,11 @@ namespace UnityEditorInternal internal class AddCurvesPopup : EditorWindow { const float k_WindowPadding = 3; + const float k_SpaceForSlider = 16; + + const float k_WindowMaxWidth = 450; + const float k_WindowMinWidth = 240; + const float k_WindowFixedHeight = 250; internal static AnimationWindowState s_State; @@ -20,16 +25,25 @@ internal class AddCurvesPopup : EditorWindow private static long s_LastClosedTime; private static AddCurvesPopupHierarchy s_Hierarchy; - private static Vector2 windowSize = new Vector2(240, 250); - public delegate void OnNewCurveAdded(AddCurvesPopupPropertyNode node); private static OnNewCurveAdded NewCurveAddedCallback; + Vector2 GetWindowSize() + { + float contentWidth = s_Hierarchy.GetContentWidth(); + float width = Mathf.Clamp(contentWidth + k_SpaceForSlider + k_WindowPadding, k_WindowMinWidth, k_WindowMaxWidth); + return new Vector2(width, k_WindowFixedHeight); + } + void Init(Rect buttonRect) { + s_Hierarchy = new AddCurvesPopupHierarchy(); + s_Hierarchy.InitIfNeeded(this, new Rect(0, 0, k_WindowMinWidth, k_WindowFixedHeight)); + buttonRect = GUIUtility.GUIToScreenRect(buttonRect); - ShowAsDropDown(buttonRect, windowSize, new[] { PopupLocation.Right }); + + ShowAsDropDown(buttonRect, GetWindowSize(), new[] { PopupLocation.Right }); } void OnEnable() @@ -77,8 +91,7 @@ internal void OnGUI() if (Event.current.type == EventType.Layout) return; - if (s_Hierarchy == null) - s_Hierarchy = new AddCurvesPopupHierarchy(); + Vector2 windowSize = GetWindowSize(); Rect rect = new Rect(1, 1, windowSize.x - k_WindowPadding, windowSize.y - k_WindowPadding); GUI.Box(new Rect(0, 0, windowSize.x, windowSize.y), GUIContent.none, "grey_border"); diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs index 3f69454e6f..4adb9ff208 100644 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs +++ b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs @@ -14,9 +14,16 @@ internal class AddCurvesPopupHierarchy private TreeViewState m_TreeViewState; private AddCurvesPopupHierarchyDataSource m_TreeViewDataSource; + private float m_ContentWidth = 0f; + + public float GetContentWidth() + { + return m_ContentWidth; + } + public void OnGUI(Rect position, EditorWindow owner) { - InitIfNeeded(owner, position); + m_TreeView.SetTotalRect(position); m_TreeView.OnEvent(); m_TreeView.OnGUI(position, GUIUtility.GetControlID(FocusType.Keyboard)); } @@ -33,7 +40,7 @@ public void InitIfNeeded(EditorWindow owner, Rect rect) m_TreeView.deselectOnUnhandledMouseDown = true; m_TreeViewDataSource = new AddCurvesPopupHierarchyDataSource(m_TreeView); - TreeViewGUI gui = new AddCurvesPopupHierarchyGUI(m_TreeView, owner); + AddCurvesPopupHierarchyGUI gui = new AddCurvesPopupHierarchyGUI(m_TreeView, owner); m_TreeView.Init(rect, m_TreeViewDataSource, @@ -42,6 +49,8 @@ public void InitIfNeeded(EditorWindow owner, Rect rect) ); m_TreeViewDataSource.UpdateData(); + + m_ContentWidth = gui.GetContentWidth(); } internal virtual bool IsRenamingNodeAllowed(TreeViewItem node) diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs index b944bfb74b..5bea4058b3 100644 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs +++ b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs @@ -31,6 +31,7 @@ private void SetupRootNodeSettings() public override void FetchData() { + m_RootItem = null; if (AddCurvesPopup.s_State.selection.canAddCurves) { GameObject rootGameObject = AddCurvesPopup.s_State.activeRootGameObject; diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs index 37a14c36a6..939b21cf85 100644 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs +++ b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs @@ -5,6 +5,7 @@ using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; +using System.Collections.Generic; namespace UnityEditorInternal { @@ -14,6 +15,7 @@ internal class AddCurvesPopupHierarchyGUI : TreeViewGUI public bool showPlusButton { get; set; } private GUIStyle plusButtonStyle = "OL Plus"; private GUIStyle plusButtonBackgroundStyle = "Tag MenuItem"; + private GUIContent addPropertiesContent = EditorGUIUtility.TrTextContent("Add Properties"); private const float plusButtonWidth = 17; public AddCurvesPopupHierarchyGUI(TreeViewController treeView, EditorWindow owner) @@ -25,7 +27,12 @@ public AddCurvesPopupHierarchyGUI(TreeViewController treeView, EditorWindow owne public override void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool selected, bool focused) { base.OnRowGUI(rowRect, node, row, selected, focused); + DoAddCurveButton(rowRect, node); + HandleContextMenu(rowRect, node); + } + private void DoAddCurveButton(Rect rowRect, TreeViewItem node) + { // Is it propertynode. If not, then we don't need plusButton so quit here AddCurvesPopupPropertyNode hierarchyNode = node as AddCurvesPopupPropertyNode; if (hierarchyNode == null || hierarchyNode.curveBindings == null || hierarchyNode.curveBindings.Length == 0) @@ -41,10 +48,85 @@ public override void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool sel if (GUI.Button(buttonRect, GUIContent.none, plusButtonStyle)) { AddCurvesPopup.AddNewCurve(hierarchyNode); - owner.Close(); + + // Hold shift key to add new curves and keep window opened. + if (Event.current.shift) + m_TreeView.ReloadData(); + else + owner.Close(); } } + private void HandleContextMenu(Rect rowRect, TreeViewItem node) + { + if (Event.current.type != EventType.ContextClick) + return; + + if (rowRect.Contains(Event.current.mousePosition)) + { + // Add current node to selection + var ids = new List(m_TreeView.GetSelection()); + ids.Add(node.id); + m_TreeView.SetSelection(ids.ToArray(), false, false); + + GenerateMenu().ShowAsContext(); + Event.current.Use(); + } + } + + private GenericMenu GenerateMenu() + { + GenericMenu menu = new GenericMenu(); + menu.AddItem(addPropertiesContent, false, AddPropertiesFromSelectedNodes); + + return menu; + } + + private void AddPropertiesFromSelectedNodes() + { + int[] ids = m_TreeView.GetSelection(); + for (int i = 0; i < ids.Length; ++i) + { + var node = m_TreeView.FindItem(ids[i]); + var propertyNode = node as AddCurvesPopupPropertyNode; + + if (propertyNode != null) + { + AddCurvesPopup.AddNewCurve(propertyNode); + } + else if (node.hasChildren) + { + foreach (var childNode in node.children) + { + var childPropertyNode = childNode as AddCurvesPopupPropertyNode; + if (childPropertyNode != null) + { + AddCurvesPopup.AddNewCurve(childPropertyNode); + } + } + } + } + + m_TreeView.ReloadData(); + } + + public float GetContentWidth() + { + IList rows = m_TreeView.data.GetRows(); + List allRows = new List(); + allRows.AddRange(rows); + + for (int i = 0; i < allRows.Count; ++i) + { + var row = allRows[i]; + if (row.hasChildren) + allRows.AddRange(row.children); + } + + float rowWidth = GetMaxWidth(allRows); + return rowWidth + plusButtonWidth; + } + override protected void SyncFakeItem() { //base.SyncFakeItem(); diff --git a/Editor/Mono/Animation/ZoomableArea.cs b/Editor/Mono/Animation/ZoomableArea.cs index 80017a2a7e..2bc23ff956 100644 --- a/Editor/Mono/Animation/ZoomableArea.cs +++ b/Editor/Mono/Animation/ZoomableArea.cs @@ -377,14 +377,20 @@ public void SetShownHRange(float min, float max) public void SetShownVRangeInsideMargins(float min, float max) { + float heightInsideMargins = drawRect.height - topmargin - bottommargin; + if (heightInsideMargins < kMinHeight) heightInsideMargins = kMinHeight; + + float denum = max - min; + if (denum < kMinHeight) denum = kMinHeight; + if (m_UpDirection == YDirection.Positive) { - m_Scale.y = -(drawRect.height - topmargin - bottommargin) / (max - min); + m_Scale.y = -heightInsideMargins / denum; m_Translation.y = drawRect.height - min * m_Scale.y - topmargin; } else { - m_Scale.y = (drawRect.height - topmargin - bottommargin) / (max - min); + m_Scale.y = heightInsideMargins / denum; m_Translation.y = -min * m_Scale.y - bottommargin; } EnforceScaleAndRange(); @@ -392,14 +398,17 @@ public void SetShownVRangeInsideMargins(float min, float max) public void SetShownVRange(float min, float max) { + float denum = max - min; + if (denum < kMinHeight) denum = kMinHeight; + if (m_UpDirection == YDirection.Positive) { - m_Scale.y = -drawRect.height / (max - min); + m_Scale.y = -drawRect.height / denum; m_Translation.y = drawRect.height - min * m_Scale.y; } else { - m_Scale.y = drawRect.height / (max - min); + m_Scale.y = drawRect.height / denum; m_Translation.y = -min * m_Scale.y; } EnforceScaleAndRange(); diff --git a/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs b/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs index 001ec95022..90bdb7af92 100644 --- a/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs +++ b/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs @@ -20,6 +20,14 @@ namespace UnityEditor [NativeHeader("Editor/Src/EditorUserBuildSettings.h")] public sealed partial class TextureImporter : AssetImporter, ISpriteEditorDataProvider { + private string GetFixedPlatformName(string platform) + { + var targetGroup = BuildPipeline.GetBuildTargetGroupByName(platform); + if (targetGroup != BuildTargetGroup.Unknown) + return BuildPipeline.GetBuildTargetGroupName(targetGroup); + return platform; + } + [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.")] public extern TextureImporterFormat textureFormat { @@ -96,6 +104,9 @@ public bool GetPlatformTextureSettings(string platform, out int maxTextureSize, // public API will always return a valid TextureImporterPlatformSettings, creating it based on the default one if it did not exist. public TextureImporterPlatformSettings GetPlatformTextureSettings(string platform) { + // make sure we are converting the settings to use the proper BuildTargetGroupName to get them (the way it works on other importers) + platform = GetFixedPlatformName(platform); + TextureImporterPlatformSettings dest = GetPlatformTextureSetting_Internal(platform); if (platform != dest.name) { @@ -112,6 +123,7 @@ public TextureImporterPlatformSettings GetDefaultPlatformTextureSettings() public TextureImporterFormat GetAutomaticFormat(string platform) { + platform = GetFixedPlatformName(platform); TextureImporterSettings settings = new TextureImporterSettings(); ReadTextureSettings(settings); TextureImporterPlatformSettings platformSettings = GetPlatformTextureSettings(platform); @@ -161,11 +173,25 @@ public void SetPlatformTextureSettings(string platform, int maxTextureSize, Text SetPlatformTextureSettings(dest); } + [NativeName("SetPlatformTextureSettings")] + private extern void SetPlatformTextureSettings_Internal(TextureImporterPlatformSettings platformSettings); + // Set specific target platform settings - public extern void SetPlatformTextureSettings(TextureImporterPlatformSettings platformSettings); + public void SetPlatformTextureSettings(TextureImporterPlatformSettings platformSettings) + { + // we need to fix the name in case the user changed it to some mismatching value + platformSettings.name = GetFixedPlatformName(platformSettings.name); + SetPlatformTextureSettings_Internal(platformSettings); + } // Clear specific target platform settings - public extern void ClearPlatformTextureSettings(string platform); + [NativeName("ClearPlatformTextureSettings")] + private extern void ClearPlatformTextureSettings_Internal(string platform); + + public void ClearPlatformTextureSettings(string platform) + { + ClearPlatformTextureSettings_Internal(GetFixedPlatformName(platform)); + } [FreeFunction] internal static extern TextureImporterFormat DefaultFormatFromTextureParameters([NotNull] TextureImporterSettings settings, TextureImporterPlatformSettings platformSettings, bool doesTextureContainAlpha, bool sourceWasHDR, BuildTarget destinationPlatform); diff --git a/Editor/Mono/AssetPostprocessor.cs b/Editor/Mono/AssetPostprocessor.cs index 798978522f..00ba6ae26f 100644 --- a/Editor/Mono/AssetPostprocessor.cs +++ b/Editor/Mono/AssetPostprocessor.cs @@ -263,10 +263,10 @@ static string GetMeshProcessorsHashString() var inst = Activator.CreateInstance(assetPostprocessorClass) as AssetPostprocessor; var type = inst.GetType(); bool hasPreProcessMethod = type.GetMethod("OnPreprocessModel", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; - bool hasProcessMeshAssignMethod = type.GetMethod("OnProcessMeshAssingModel", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; + bool hasPostprocessMeshHierarchy = type.GetMethod("OnPostprocessMeshHierarchy", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; bool hasPostProcessMethod = type.GetMethod("OnPostprocessModel", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; uint version = inst.GetVersion(); - if (version != 0 && (hasPreProcessMethod || hasProcessMeshAssignMethod || hasPostProcessMethod)) + if (version != 0 && (hasPreProcessMethod || hasPostprocessMeshHierarchy || hasPostProcessMethod)) { versionsByType.Add(type.FullName, version); } @@ -356,6 +356,16 @@ static bool ProcessMeshHasAssignMaterial() return false; } + [RequiredByNativeCode] + static void PostprocessMeshHierarchy(GameObject root) + { + foreach (AssetPostprocessor inst in m_ImportProcessors) + { + object[] args = { root }; + AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessMeshHierarchy", args); + } + } + static void PostprocessMesh(GameObject gameObject) { foreach (AssetPostprocessor inst in m_ImportProcessors) diff --git a/Editor/Mono/BuildPipeline/AssemblyStripper.cs b/Editor/Mono/BuildPipeline/AssemblyStripper.cs index 3f9223838c..94da574fe4 100644 --- a/Editor/Mono/BuildPipeline/AssemblyStripper.cs +++ b/Editor/Mono/BuildPipeline/AssemblyStripper.cs @@ -270,7 +270,6 @@ private static void RunAssemblyStripper(IEnumerable assemblies, string managedAs blacklists = blacklists.Concat(new[] { WriteMethodsToPreserveBlackList(rcr, platformProvider.target), - WriteUnityEngineBlackList(), MonoAssemblyStripping.GenerateLinkXmlToPreserveDerivedTypes(managedAssemblyFolderPath, rcr) }); } @@ -377,15 +376,6 @@ private static string WriteMethodsToPreserveBlackList(RuntimeClassRegistry rcr, return methodPerserveBlackList; } - private static string WriteUnityEngineBlackList() - { - // UnityEngine.dll would be stripped, as it contains no referenced symbols, only type forwarders. - // Since we need those type forwarders, we generate blacklist to preserve the assembly (but no members). - var unityEngineBlackList = Path.GetTempFileName(); - File.WriteAllText(unityEngineBlackList, ""); - return unityEngineBlackList; - } - private static string GetMethodPreserveBlacklistContents(RuntimeClassRegistry rcr, BuildTarget target) { if (rcr.GetMethodsToPreserve().Count == 0) diff --git a/Editor/Mono/ContainerWindow.cs b/Editor/Mono/ContainerWindow.cs index 248f7b566c..638f8c1b8a 100644 --- a/Editor/Mono/ContainerWindow.cs +++ b/Editor/Mono/ContainerWindow.cs @@ -94,7 +94,7 @@ static Color skinBackgroundColor } // Show the editor window. - public void Show(ShowMode showMode, bool loadPosition, bool displayImmediately) + public void Show(ShowMode showMode, bool loadPosition, bool displayImmediately, bool setFocus) { if (showMode == ShowMode.AuxWindow) showMode = ShowMode.Utility; @@ -117,7 +117,7 @@ public void Show(ShowMode showMode, bool loadPosition, bool displayImmediately) SetBackgroundColor(skinBackgroundColor); - Internal_BringLiveAfterCreation(displayImmediately, true); + Internal_BringLiveAfterCreation(displayImmediately, setFocus); // Window could be killed by now in user callbacks... if (!this) diff --git a/Editor/Mono/EditorWindow.cs b/Editor/Mono/EditorWindow.cs index 00590ec4be..ba8446b436 100644 --- a/Editor/Mono/EditorWindow.cs +++ b/Editor/Mono/EditorWindow.cs @@ -525,7 +525,7 @@ internal void ShowWithMode(ShowMode mode) cw.position = r; cw.rootView = host; MakeParentsSettingsMatchMe(); - cw.Show(mode, true, false); + cw.Show(mode, loadPosition: true, displayImmediately: false, setFocus: true); // set min/max size now that native window is not null so that it will e.g., use proper styleMask on macOS cw.SetMinMaxSizes(minSize, maxSize); @@ -1068,24 +1068,19 @@ private void OnDisableINTERNAL() // Internal stuff: // Helper to show this EditorWindow - internal static void CreateNewWindowForEditorWindow(EditorWindow window, bool loadPosition, bool showImmediately) - { - CreateNewWindowForEditorWindow(window, new Vector2(window.position.x, window.position.y), loadPosition, showImmediately); - } - - internal static void CreateNewWindowForEditorWindow(EditorWindow window, Vector2 screenPosition, bool loadPosition, bool showImmediately) + internal static void CreateNewWindowForEditorWindow(EditorWindow window, bool loadPosition, bool showImmediately, bool setFocus = true) { ContainerWindow cw = ScriptableObject.CreateInstance(); SplitView sw = ScriptableObject.CreateInstance(); cw.rootView = sw; DockArea da = ScriptableObject.CreateInstance(); - da.AddTab(window); + da.AddTab(window, setFocus); sw.AddChild(da); - Rect r = window.m_Parent.borderSize.Add(new Rect(screenPosition.x, screenPosition.y, window.position.width, window.position.height)); + Rect r = window.m_Parent.borderSize.Add(window.position); cw.position = r; sw.position = new Rect(0, 0, r.width, r.height); window.MakeParentsSettingsMatchMe(); - cw.Show(ShowMode.NormalWindow, loadPosition, showImmediately); + cw.Show(ShowMode.NormalWindow, loadPosition, showImmediately, setFocus: true); //Need this, as show my change the size of the window, due to screen constraints cw.OnResize(); } diff --git a/Editor/Mono/GUI/ColorPicker.cs b/Editor/Mono/GUI/ColorPicker.cs index d2ef8314f7..58d0173fd8 100644 --- a/Editor/Mono/GUI/ColorPicker.cs +++ b/Editor/Mono/GUI/ColorPicker.cs @@ -1257,7 +1257,7 @@ static void Start(GUIView viewToUpdate, Action colorPickedCallback) win.title = "EyeDropper"; win.hideFlags = HideFlags.DontSave; win.rootView = instance; - win.Show(ShowMode.PopupMenu, true, false); + win.Show(ShowMode.PopupMenu, loadPosition: true, displayImmediately: false, setFocus: true); instance.AddToAuxWindowList(); win.SetInvisible(); instance.SetMinMaxSizes(new Vector2(0, 0), new Vector2(kDummyWindowSize, kDummyWindowSize)); diff --git a/Editor/Mono/GUI/DockArea.cs b/Editor/Mono/GUI/DockArea.cs index e64688792e..fad669b4b6 100644 --- a/Editor/Mono/GUI/DockArea.cs +++ b/Editor/Mono/GUI/DockArea.cs @@ -82,14 +82,16 @@ private static class Styles public int selected { get { return m_Selected; } - set - { - if (m_Selected != value) - m_LastSelected = m_Selected; - m_Selected = value; - if (m_Selected >= 0 && m_Selected < m_Panes.Count) - actualView = m_Panes[m_Selected]; - } + set { SetSelectedPrivate(value, sendEvents: true); } + } + + private void SetSelectedPrivate(int value, bool sendEvents) + { + if (m_Selected != value) + m_LastSelected = m_Selected; + m_Selected = value; + if (m_Selected >= 0 && m_Selected < m_Panes.Count) + SetActualViewInternal(m_Panes[m_Selected], sendEvents); } public DockArea() @@ -173,16 +175,16 @@ protected override void UpdateViewMargins(EditorWindow view) style.positionType = PositionType.Absolute; } - public void AddTab(EditorWindow pane) + public void AddTab(EditorWindow pane, bool sendPaneEvents = true) { - AddTab(m_Panes.Count, pane); + AddTab(m_Panes.Count, pane, sendPaneEvents); } - public void AddTab(int idx, EditorWindow pane) + public void AddTab(int idx, EditorWindow pane, bool sendPaneEvents = true) { - DeregisterSelectedPane(true); + DeregisterSelectedPane(clearActualView: true, sendEvents: true); m_Panes.Insert(idx, pane); - selected = idx; + SetSelectedPrivate(idx, sendPaneEvents); s_GUIContents.Clear(); var sp = parent as SplitView; @@ -192,11 +194,11 @@ public void AddTab(int idx, EditorWindow pane) Repaint(); } - public void RemoveTab(EditorWindow pane) { RemoveTab(pane, true); } - public void RemoveTab(EditorWindow pane, bool killIfEmpty) + public void RemoveTab(EditorWindow pane) { RemoveTab(pane, killIfEmpty: true); } + public void RemoveTab(EditorWindow pane, bool killIfEmpty, bool sendEvents = true) { if (actualView == pane) - DeregisterSelectedPane(true); + DeregisterSelectedPane(clearActualView: true, sendEvents: sendEvents); int idx = m_Panes.IndexOf(pane); if (idx == -1) return; // Pane is not in the window @@ -222,7 +224,7 @@ public void RemoveTab(EditorWindow pane, bool killIfEmpty) pane.m_Parent = null; if (killIfEmpty) KillIfEmpty(); - RegisterSelectedPane(); + RegisterSelectedPane(sendEvents: true); } private void KillIfEmpty() @@ -279,9 +281,10 @@ public DropInfo DragOver(EditorWindow window, Vector2 mouseScreenPosition) public bool PerformDrop(EditorWindow w, DropInfo info, Vector2 screenPos) { - s_OriginalDragSource.RemoveTab(w, s_OriginalDragSource != this); + // Don't send focus events to the tab being moved + s_OriginalDragSource.RemoveTab(w, killIfEmpty: s_OriginalDragSource != this, sendEvents: false); int tabInsertIndex = s_PlaceholderPos == -1 || s_PlaceholderPos > m_Panes.Count ? m_Panes.Count : s_PlaceholderPos; - AddTab(tabInsertIndex, w); + AddTab(tabInsertIndex, w, sendPaneEvents: false); selected = tabInsertIndex; return true; } @@ -891,7 +894,9 @@ private float DragTab(Rect tabAreaRect, float scrollOffset, GUIStyle tabStyle) ResetDragVars(); - RemoveTab(w); + // The active tab that we're moving to the new window stays focused at all times. + // Do not remove focus from the tab being detached. + RemoveTab(w, killIfEmpty: true, sendEvents: false); Rect wPos = w.position; wPos.x = screenMousePos.x - wPos.width * .5f; wPos.y = screenMousePos.y - wPos.height * .5f; @@ -900,7 +905,8 @@ private float DragTab(Rect tabAreaRect, float scrollOffset, GUIStyle tabStyle) if (Application.platform == RuntimePlatform.WindowsEditor) wPos.y = Mathf.Max(InternalEditorUtility.GetBoundsOfDesktopAtPoint(screenMousePos).y, wPos.y); - EditorWindow.CreateNewWindowForEditorWindow(w, false, false); + // Don't call OnFocus on the tab when it is moved to the new window + EditorWindow.CreateNewWindowForEditorWindow(w, loadPosition: false, showImmediately: false, setFocus: false); w.position = w.m_Parent.window.FitWindowRectToScreen(wPos, true, true); diff --git a/Editor/Mono/GUI/MainView.cs b/Editor/Mono/GUI/MainView.cs index 24f90a0854..1f41368a2a 100644 --- a/Editor/Mono/GUI/MainView.cs +++ b/Editor/Mono/GUI/MainView.cs @@ -56,7 +56,7 @@ public static void MakeMain() int height = Mathf.Clamp(res.height * 3 / 4, 600, 950); cw.position = new Rect(60, 20, width, height); - cw.Show(ShowMode.MainWindow, true, true); + cw.Show(ShowMode.MainWindow, loadPosition: true, displayImmediately: true, setFocus: true); cw.DisplayAllViews(); } diff --git a/Editor/Mono/GUI/PaneDragTab.cs b/Editor/Mono/GUI/PaneDragTab.cs index 935cdd2932..ce5ca74804 100644 --- a/Editor/Mono/GUI/PaneDragTab.cs +++ b/Editor/Mono/GUI/PaneDragTab.cs @@ -131,7 +131,9 @@ public void Show(Rect pixelPos, GUIContent content, Vector2 viewSize, Vector2 mo { SetWindowPos(pixelPos); } - m_Window.Show(ShowMode.NoShadow, true, false); + + // Do not steal focus from the pane + m_Window.Show(ShowMode.NoShadow, loadPosition: true, displayImmediately: false, setFocus: false); m_TargetRect = pixelPos; } diff --git a/Editor/Mono/GUI/SplitView.cs b/Editor/Mono/GUI/SplitView.cs index 2c3682beb7..f0fc43a7ff 100644 --- a/Editor/Mono/GUI/SplitView.cs +++ b/Editor/Mono/GUI/SplitView.cs @@ -445,9 +445,9 @@ public bool PerformDrop(EditorWindow dropWindow, DropInfo dropInfo, Vector2 scre parentForDrop.MakeRoomForRect(dropRect); parentForDrop.AddChild(newDockArea, dropIndex); newDockArea.position = dropRect; - DockArea.s_OriginalDragSource.RemoveTab(dropWindow); + DockArea.s_OriginalDragSource.RemoveTab(dropWindow, killIfEmpty: true, sendEvents: false); dropWindow.m_Parent = newDockArea; - newDockArea.AddTab(dropWindow); + newDockArea.AddTab(dropWindow, sendPaneEvents: false); Reflow(); RecalcMinMaxAndReflowAll(this); newDockArea.MakeVistaDWMHappyDance(); diff --git a/Editor/Mono/GUI/WindowLayout.cs b/Editor/Mono/GUI/WindowLayout.cs index 047ce599c4..0b3d4ea174 100644 --- a/Editor/Mono/GUI/WindowLayout.cs +++ b/Editor/Mono/GUI/WindowLayout.cs @@ -600,7 +600,7 @@ public static bool LoadWindowLayout(string path, bool newProjectLayoutWasCreated throw new System.Exception(); } - mainWindow.Show(mainWindow.showMode, true, true); + mainWindow.Show(mainWindow.showMode, loadPosition: true, displayImmediately: true, setFocus: true); // Show other windows for (int i = 0; i < newWindows.Count; i++) @@ -611,7 +611,7 @@ public static bool LoadWindowLayout(string path, bool newProjectLayoutWasCreated ContainerWindow containerWindow = newWindows[i] as ContainerWindow; if (containerWindow && containerWindow != mainWindow) - containerWindow.Show(containerWindow.showMode, true, true); + containerWindow.Show(containerWindow.showMode, loadPosition: true, displayImmediately: true, setFocus: true); } // Unmaximize maximized GameView if maximize on play is enabled diff --git a/Editor/Mono/HostView.cs b/Editor/Mono/HostView.cs index ceccdc8cc7..bcd640d654 100644 --- a/Editor/Mono/HostView.cs +++ b/Editor/Mono/HostView.cs @@ -32,22 +32,24 @@ internal class HostView : GUIView internal EditorWindow actualView { get { return m_ActualView; } - set - { - if (m_ActualView == value) - return; - DeregisterSelectedPane(true); - m_ActualView = value; - m_IsGameView = m_ActualView is GameView; - RegisterSelectedPane(); - actualViewChanged?.Invoke(this); - } + set { SetActualViewInternal(value, sendEvents: true); } + } + + internal void SetActualViewInternal(EditorWindow value, bool sendEvents) + { + if (m_ActualView == value) + return; + DeregisterSelectedPane(clearActualView: true, sendEvents: true); + m_ActualView = value; + m_IsGameView = m_ActualView is GameView; + RegisterSelectedPane(sendEvents); + actualViewChanged?.Invoke(this); } internal void ResetActiveView() { - DeregisterSelectedPane(false); - RegisterSelectedPane(); + DeregisterSelectedPane(clearActualView: false, sendEvents: true); + RegisterSelectedPane(sendEvents: true); if (actualViewChanged != null) actualViewChanged(this); } @@ -94,7 +96,7 @@ protected override void OnEnable() EditorPrefs.onValueWasUpdated += PlayModeTintColorChangedCallback; base.OnEnable(); background = null; - RegisterSelectedPane(); + RegisterSelectedPane(sendEvents: true); } protected override void OnDisable() @@ -102,7 +104,7 @@ protected override void OnDisable() EditorApplication.playModeStateChanged -= PlayModeStateChangedCallback; EditorPrefs.onValueWasUpdated -= PlayModeTintColorChangedCallback; base.OnDisable(); - DeregisterSelectedPane(false); + DeregisterSelectedPane(clearActualView: false, sendEvents: true); } protected override void OldOnGUI() @@ -159,6 +161,11 @@ internal void OnLostFocus() { EditorGUI.EndEditingActiveTextField(); Invoke("OnLostFocus"); + + // Callback could have killed us + if (!this) + return; + Repaint(); } @@ -339,7 +346,7 @@ protected void Invoke(string methodName, object obj) mi?.Invoke(obj, null); } - protected void RegisterSelectedPane() + protected void RegisterSelectedPane(bool sendEvents) { if (!m_ActualView) return; @@ -368,24 +375,27 @@ protected void RegisterSelectedPane() EditorApplication.update += m_ActualView.CheckForWindowRepaint; } - try - { - Invoke("OnBecameVisible"); - EditorModes.OnBecameVisible(m_ActualView); - Invoke("OnFocus"); - EditorModes.OnFocus(m_ActualView); - } - catch (TargetInvocationException ex) + if (sendEvents) { - // We need to catch these so the window initialization doesn't get screwed - if (ex.InnerException != null) - Debug.LogError(ex.InnerException.GetType().Name + ":" + ex.InnerException.Message); + try + { + Invoke("OnBecameVisible"); + EditorModes.OnBecameVisible(m_ActualView); + Invoke("OnFocus"); + EditorModes.OnFocus(m_ActualView); + } + catch (TargetInvocationException ex) + { + // We need to catch these so the window initialization doesn't get screwed + if (ex.InnerException != null) + Debug.LogError(ex.InnerException.GetType().Name + ":" + ex.InnerException.Message); + } } UpdateViewMargins(m_ActualView); } - protected void DeregisterSelectedPane(bool clearActualView) + protected void DeregisterSelectedPane(bool clearActualView, bool sendEvents) { if (!m_ActualView) return; @@ -417,10 +427,13 @@ protected void DeregisterSelectedPane(bool clearActualView) { EditorWindow oldActualView = m_ActualView; m_ActualView = null; - Invoke("OnLostFocus", oldActualView); - EditorModes.OnLostFocus(m_ActualView); - Invoke("OnBecameInvisible", oldActualView); - EditorModes.OnBecameInvisible(oldActualView); + if (sendEvents) + { + Invoke("OnLostFocus", oldActualView); + EditorModes.OnLostFocus(m_ActualView); + Invoke("OnBecameInvisible", oldActualView); + EditorModes.OnBecameInvisible(oldActualView); + } } } diff --git a/Editor/Mono/ImportSettings/AssetImporterEditor.cs b/Editor/Mono/ImportSettings/AssetImporterEditor.cs index d2e0537a7b..f981e73479 100644 --- a/Editor/Mono/ImportSettings/AssetImporterEditor.cs +++ b/Editor/Mono/ImportSettings/AssetImporterEditor.cs @@ -22,11 +22,13 @@ internal void InternalSetAssetImporterTargetEditor(Object editor) protected internal Object assetTarget { get { return m_AssetEditor != null ? m_AssetEditor.target : null; } } protected internal SerializedObject assetSerializedObject { get { return m_AssetEditor != null ? m_AssetEditor.serializedObject : null; } } + static string s_LocalizedTitleString = L10n.Tr("{0} Import Settings"); + internal override string targetTitle { get { - return string.Format(L10n.Tr("{0} Import Settings"), m_AssetEditor == null ? string.Empty : m_AssetEditor.targetTitle); + return string.Format(s_LocalizedTitleString, m_AssetEditor == null ? string.Empty : m_AssetEditor.targetTitle); } } diff --git a/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs b/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs index b2e66d701a..2264c4dac2 100644 --- a/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs +++ b/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs @@ -49,7 +49,7 @@ internal override void OnGUI(PluginImporterInspector inspector) // This toggle controls two things: // * Is platform enabled/disabled? // * Platform CPU value - bool isTargetEnabled = EditorGUILayout.Toggle(name, IsTargetEnabled(inspector)); + bool isTargetEnabled = EditorGUILayout.Toggle(name, IsTargetEnabled(inspector) && value.ToString() == defaultValue.ToString()); if (EditorGUI.EndChangeCheck()) { value = isTargetEnabled ? defaultValue : DesktopPluginCPUArchitecture.None; diff --git a/Editor/Mono/Inspector/AnimationClipEditor.cs b/Editor/Mono/Inspector/AnimationClipEditor.cs index 23fc6cffb2..93bbbb54b9 100644 --- a/Editor/Mono/Inspector/AnimationClipEditor.cs +++ b/Editor/Mono/Inspector/AnimationClipEditor.cs @@ -217,6 +217,7 @@ public bool needsToGenerateClipInfo const int kPosition = 3; Vector2[][][] m_QualityCurves = new Vector2[4][][]; bool m_DirtyQualityCurves = false; + bool m_FirstInitialization = true; private void InitController() { @@ -269,7 +270,12 @@ private void InitController() { m_AvatarPreview.Animator.Play(0, 0, 0); m_AvatarPreview.Animator.Update(0); - m_AvatarPreview.ResetPreviewFocus(); + + if (m_FirstInitialization) + { + m_AvatarPreview.ResetPreviewFocus(); + m_FirstInitialization = false; + } } } } diff --git a/Editor/Mono/Inspector/GameObjectInspector.cs b/Editor/Mono/Inspector/GameObjectInspector.cs index bb5d9782ce..ef7ccf6d4f 100644 --- a/Editor/Mono/Inspector/GameObjectInspector.cs +++ b/Editor/Mono/Inspector/GameObjectInspector.cs @@ -131,11 +131,14 @@ public void Dispose() Dictionary m_PreviewInstances = new Dictionary(); + bool m_PlayModeObjects; bool m_IsAsset; bool m_ImmutableSelf; bool m_ImmutableSourceAsset; - bool m_IsPrefabInstanceAnyRoot = false; - bool m_IsPrefabInstanceOutermostRoot = false; + bool m_IsDisconnected; + bool m_IsMissing; + bool m_IsPrefabInstanceAnyRoot; + bool m_IsPrefabInstanceOutermostRoot; bool m_AllOfSamePrefabType = true; public void OnEnable() @@ -157,8 +160,14 @@ public void OnEnable() void CalculatePrefabStatus() { - m_IsPrefabInstanceAnyRoot = false; + m_PlayModeObjects = false; m_IsAsset = false; + m_ImmutableSelf = false; + m_ImmutableSourceAsset = false; + m_IsDisconnected = false; + m_IsMissing = false; + m_IsPrefabInstanceAnyRoot = true; + m_IsPrefabInstanceOutermostRoot = true; m_AllOfSamePrefabType = true; PrefabAssetType firstType = PrefabUtility.GetPrefabAssetType(targets[0]); PrefabInstanceStatus firstStatus = PrefabUtility.GetPrefabInstanceStatus(targets[0]); @@ -170,17 +179,23 @@ void CalculatePrefabStatus() if (type != firstType || status != firstStatus) m_AllOfSamePrefabType = false; - if (PrefabUtility.IsAnyPrefabInstanceRoot(go)) - m_IsPrefabInstanceAnyRoot = true; - if (m_IsPrefabInstanceAnyRoot) - m_IsPrefabInstanceOutermostRoot = PrefabUtility.IsOutermostPrefabInstanceRoot(go); + if (Application.IsPlaying(go)) + m_PlayModeObjects = true; + if (!PrefabUtility.IsAnyPrefabInstanceRoot(go)) + m_IsPrefabInstanceAnyRoot = false; // Conservative is false if any is false + if (!m_IsPrefabInstanceAnyRoot || !PrefabUtility.IsOutermostPrefabInstanceRoot(go)) + m_IsPrefabInstanceOutermostRoot = false; // Conservative is false if any is false if (PrefabUtility.IsPartOfPrefabAsset(go)) - m_IsAsset = true; + m_IsAsset = true; // Conservative is true if any is true if (m_IsAsset && PrefabUtility.IsPartOfImmutablePrefab(go)) - m_ImmutableSelf = true; + m_ImmutableSelf = true; // Conservative is true if any is true GameObject originalSourceOrVariant = PrefabUtility.GetOriginalSourceOrVariantRoot(go); if (originalSourceOrVariant != null && PrefabUtility.IsPartOfImmutablePrefab(originalSourceOrVariant)) - m_ImmutableSourceAsset = true; + m_ImmutableSourceAsset = true; // Conservative is true if any is true + if (PrefabUtility.IsDisconnectedFromPrefabAsset(go)) + m_IsDisconnected = true; + if (PrefabUtility.IsPrefabAssetMissing(go)) + m_IsMissing = true; } } @@ -298,7 +313,7 @@ internal bool DrawInspector() // Prefab Toolbar if (EditorGUIUtility.comparisonViewMode == EditorGUIUtility.ComparisonViewMode.None) { - DoPrefabButtons(go); + DoPrefabButtons(); } serializedObject.ApplyModifiedProperties(); @@ -306,19 +321,18 @@ internal bool DrawInspector() return true; } - private void DoPrefabButtons(GameObject go) + private void DoPrefabButtons() { - // @TODO: If/when we support multi-editing of prefab/model instances, - // handle it here. Only show prefab bar if all are same type? - if (!m_IsPrefabInstanceAnyRoot) return; + if (!m_IsPrefabInstanceAnyRoot) + return; - using (new EditorGUI.DisabledScope(EditorApplication.isPlayingOrWillChangePlaymode && PrefabStageUtility.GetPrefabStage(go) == null)) + using (new EditorGUI.DisabledScope(m_PlayModeObjects)) { EditorGUILayout.BeginHorizontal(s_Styles.prefabButtonsHorizontalLayout); // Prefab information - PrefabAssetType prefabType = PrefabUtility.GetPrefabAssetType(go); - PrefabInstanceStatus instanceStatus = PrefabUtility.GetPrefabInstanceStatus(go); + PrefabAssetType singlePrefabType = PrefabUtility.GetPrefabAssetType(target); + PrefabInstanceStatus singleInstanceStatus = PrefabUtility.GetPrefabInstanceStatus(target); GUIContent prefixLabel; if (targets.Length > 1) { @@ -326,14 +340,14 @@ private void DoPrefabButtons(GameObject go) } else { - prefixLabel = s_Styles.goTypeLabel[(int)prefabType, (int)instanceStatus]; + prefixLabel = s_Styles.goTypeLabel[(int)singlePrefabType, (int)singleInstanceStatus]; } if (prefixLabel != null) { EditorGUILayout.BeginHorizontal(GUILayout.Width(kIconSize + s_Styles.tagFieldWidth)); GUILayout.FlexibleSpace(); - if (PrefabUtility.IsDisconnectedFromPrefabAsset(go) || PrefabUtility.IsPrefabAssetMissing(go)) + if (m_IsDisconnected || m_IsMissing) { GUI.contentColor = GUI.skin.GetStyle("CN StatusWarn").normal.textColor; GUILayout.Label(prefixLabel, EditorStyles.whiteLabel, GUILayout.ExpandWidth(false)); @@ -344,13 +358,11 @@ private void DoPrefabButtons(GameObject go) EditorGUILayout.EndHorizontal(); } - if (targets.Length > 1) - GUILayout.Label("Instance Management Disabled", s_Styles.instanceManagementInfo); - else + if (!m_IsMissing) { - if (!PrefabUtility.IsPrefabAssetMissing(go)) + using (new EditorGUI.DisabledScope(targets.Length > 1)) { - if (prefabType == PrefabAssetType.Model) + if (singlePrefabType == PrefabAssetType.Model) { // Open Model Prefab if (GUILayout.Button("Open", "MiniButtonLeft")) @@ -373,11 +385,15 @@ private void DoPrefabButtons(GameObject go) } } } + } - // Select prefab - if (GUILayout.Button("Select", "MiniButtonRight")) + // Select prefab + if (GUILayout.Button("Select", "MiniButtonRight")) + { + HashSet selectedAssets = new HashSet(); + for (int i = 0; i < targets.Length; i++) { - Selection.activeObject = PrefabUtility.GetOriginalSourceOrVariantRoot(target); + GameObject prefabGo = PrefabUtility.GetOriginalSourceOrVariantRoot(targets[i]); // Because of legacy prefab references we have to have this extra step // to make sure we ping the prefab asset correctly. @@ -385,25 +401,30 @@ private void DoPrefabButtons(GameObject go) // will reference prefabs as if they are serialized assets. Those references // works fine but we are not able to ping objects loaded directly from the asset // file, so we have to make sure we ping the metadata version of the prefab. - var assetPath = AssetDatabase.GetAssetPath(Selection.activeObject); - Selection.activeObject = AssetDatabase.LoadMainAssetAtPath(assetPath); + var assetPath = AssetDatabase.GetAssetPath(prefabGo); + selectedAssets.Add((GameObject)AssetDatabase.LoadMainAssetAtPath(assetPath)); + } + Selection.objects = selectedAssets.ToArray(); + if (Selection.gameObjects.Length == 1) EditorGUIUtility.PingObject(Selection.activeObject); - } + } - // Should be EditorGUILayout.Space, except it does not have ExpandWidth set to false. - // Maybe we can change that? - GUILayoutUtility.GetRect(6, 6, GUILayout.ExpandWidth(false)); + // Should be EditorGUILayout.Space, except it does not have ExpandWidth set to false. + // Maybe we can change that? + GUILayoutUtility.GetRect(6, 6, GUILayout.ExpandWidth(false)); - // Reserve space regardless of whether the button is there or not to avoid jumps in button sizes. - Rect rect = GUILayoutUtility.GetRect(s_Styles.overridesContent, s_Styles.overridesDropdown); - if (m_IsPrefabInstanceOutermostRoot) + // Reserve space regardless of whether the button is there or not to avoid jumps in button sizes. + Rect rect = GUILayoutUtility.GetRect(s_Styles.overridesContent, s_Styles.overridesDropdown); + if (m_IsPrefabInstanceOutermostRoot) + { + if (EditorGUI.DropdownButton(rect, s_Styles.overridesContent, FocusType.Passive)) { - if (EditorGUI.DropdownButton(rect, s_Styles.overridesContent, FocusType.Passive)) - { - PopupWindow.Show(rect, new PrefabOverridesWindow(go)); - GUIUtility.ExitGUI(); - } + if (targets.Length > 1) + PopupWindow.Show(rect, new PrefabOverridesWindow(targets.Select(e => (GameObject)e).ToArray())); + else + PopupWindow.Show(rect, new PrefabOverridesWindow((GameObject)target)); + GUIUtility.ExitGUI(); } } } diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index 9c685ac9ae..1464161d4b 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -1241,7 +1241,7 @@ private void DrawEditor(Editor[] editors, int editorIndex, bool rebuildOptimized Rect contentRect = new Rect(); bool excludedClass = ModuleMetadata.GetModuleIncludeSettingForObject(target) == ModuleIncludeSetting.ForceExclude; if (excludedClass) - EditorGUILayout.HelpBox("The built-in package 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.", MessageType.Warning); + EditorGUILayout.HelpBox("The built-in package '" + ModuleMetadata.GetExcludingModuleForObject(target) + "', which is required this component type has been disabled in Package Manager. This object will be removed in play mode and from any builds you make.", MessageType.Warning); using (new EditorGUI.DisabledScope(!editor.IsEnabled() || excludedClass)) { diff --git a/Editor/Mono/Inspector/LightingSettingsInspector.cs b/Editor/Mono/Inspector/LightingSettingsInspector.cs index 0f5d45dffb..ae164fd643 100644 --- a/Editor/Mono/Inspector/LightingSettingsInspector.cs +++ b/Editor/Mono/Inspector/LightingSettingsInspector.cs @@ -61,6 +61,8 @@ static class Styles 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."); 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."); public static readonly GUIContent GINotEnabledInfo = EditorGUIUtility.TrTextContent("Lightmapping settings are currently disabled. Enable Baked Global Illumination or Realtime Global Illumination to display these settings."); + public static readonly GUIContent CastShadowsProgressiveGPUWarning = EditorGUIUtility.TrTextContent("Cast Shadows is forced to 'On' when using the GPU lightmapper (Preview), it will be supported in a later version. Use the CPU lightmapper instead if you need this functionality."); + public static readonly GUIContent ReceiveShadowsProgressiveGPUWarning = EditorGUIUtility.TrTextContent("Receive Shadows is forced to 'On' when using the GPU lightmapper (Preview), it will be supported in a later version. Use the CPU lightmapper instead if you need this functionality."); } bool m_ShowChartingSettings = true; @@ -156,20 +158,25 @@ public void RenderMeshSettings(bool showLightmapSettings) m_GameObjectsSerializedObject.Update(); m_LightmapSettings.Update(); - // TODO(RadeonRays): remove if GPU lightmapper once the feature has been implemented. - if (LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveGPU) + // TODO(RadeonRays): remove scope for GPU lightmapper once the feature has been implemented. + using (new EditorGUI.DisabledScope(LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU)) + { EditorGUILayout.PropertyField(m_CastShadows, Styles.CastShadows, true); + } + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.HelpBox(Styles.CastShadowsProgressiveGPUWarning.text, MessageType.Info); bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath(); if (SupportedRenderingFeatures.active.rendererSupportsReceiveShadows) { - using (new EditorGUI.DisabledScope(isDeferredRenderingPath)) + // TODO(RadeonRays): remove scope for GPU lightmapper once the feature has been implemented. + using (new EditorGUI.DisabledScope(isDeferredRenderingPath || LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU)) { - // TODO(RadeonRays): remove if GPU lightmapper once the feature has been implemented. - if (LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveGPU) - EditorGUILayout.PropertyField(m_ReceiveShadows, Styles.ReceiveShadows, true); + EditorGUILayout.PropertyField(m_ReceiveShadows, Styles.ReceiveShadows, true); } + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.HelpBox(Styles.ReceiveShadowsProgressiveGPUWarning.text, MessageType.Info); } if (SupportedRenderingFeatures.active.rendererSupportsMotionVectors) diff --git a/Editor/Mono/Inspector/MaterialEditor.cs b/Editor/Mono/Inspector/MaterialEditor.cs index ad6c71cf1f..30628d6d4f 100644 --- a/Editor/Mono/Inspector/MaterialEditor.cs +++ b/Editor/Mono/Inspector/MaterialEditor.cs @@ -60,6 +60,7 @@ private static class Styles public static readonly GUIContent enableInstancingLabel = EditorGUIUtility.TrTextContent("Enable GPU Instancing"); 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."); public static readonly GUIContent emissionLabel = EditorGUIUtility.TrTextContent("Emission"); + public static readonly GUIContent ProgressiveGPUWarning = EditorGUIUtility.TrTextContent("The Double Sided Global Illumination feature is not implemented in the Progressive GPU lightmapper yet. Use the CPU lightmapper instead if you need this functionality."); } private static readonly List s_MaterialEditors = new List(4); diff --git a/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs b/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs index f585af937f..6ff78840fe 100644 --- a/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs +++ b/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs @@ -166,6 +166,10 @@ public bool DoubleSidedGIField() // TODO(RadeonRays): change this to (lightmapper == Enlighten) once Double Sided GI works with GPU lightmapper. using (new EditorGUI.DisabledScope(LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveCPU)) EditorGUI.Toggle(r, Styles.doubleSidedGILabel, false); + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + { + EditorGUILayout.HelpBox(Styles.ProgressiveGPUWarning.text, MessageType.Info); + } } return false; } diff --git a/Editor/Mono/Menu.bindings.cs b/Editor/Mono/Menu.bindings.cs index aaa3b83298..cf50afc6d6 100644 --- a/Editor/Mono/Menu.bindings.cs +++ b/Editor/Mono/Menu.bindings.cs @@ -21,5 +21,8 @@ public sealed class Menu [FreeFunction("MenuController::SetMenuItemHotkey")] internal static extern void SetHotkey(string menuPath, string hotkey); + + [FreeFunction("MenuController::ExtractSubmenus")] + internal static extern string[] ExtractSubmenus(string menuPath); } } diff --git a/Editor/Mono/PackageUtility.bindings.cs b/Editor/Mono/PackageUtility.bindings.cs index ddc81d4910..c548a47068 100644 --- a/Editor/Mono/PackageUtility.bindings.cs +++ b/Editor/Mono/PackageUtility.bindings.cs @@ -68,5 +68,8 @@ internal class PackageUtility public static extern void ImportPackageAssets(string packageName, ImportPackageItem[] items, bool performReInstall); [FreeFunction("ImportPackageAssets")] public static extern void ImportPackageAssetsImmediately(string packageName, ImportPackageItem[] items, bool performReInstall); + + [FreeFunction("TickPackageImport")] + public static extern void TickPackageImport(); } } diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs index 0f20879f08..87217b8985 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs @@ -38,6 +38,7 @@ internal class InitialModuleUI : ModuleUI public SerializedProperty m_AutoRandomSeed; public SerializedProperty m_RandomSeed; public SerializedProperty m_StopAction; + public SerializedProperty m_CullingMode; public SerializedProperty m_RingBufferMode; public SerializedProperty m_RingBufferLoopRange; @@ -68,6 +69,7 @@ class Texts public GUIContent randomSeed = EditorGUIUtility.TrTextContent("Random Seed", "Randomize the look of the Particle System. Using the same seed will make the Particle System play identically each time. After changing this value, restart the Particle System to see the changes, or check the Resimulate box."); public GUIContent emitterVelocity = EditorGUIUtility.TrTextContent("Emitter Velocity", "When the Particle System is moving, should we use its Transform, or Rigidbody Component, to calculate its velocity?"); public GUIContent stopAction = EditorGUIUtility.TrTextContent("Stop Action", "When the Particle System is stopped and all particles have died, should the GameObject automatically disable/destroy itself?"); + public GUIContent cullingMode = EditorGUIUtility.TrTextContent("Culling Mode", "Choose whether to continue simulating the Particle System when offscreen. Catch-up mode pauses offscreen simulations, but performs a large simulation step when they become visible, giving the appearance that they were never paused. Automatic uses Pause mode for looping systems, and AlwaysSimulate if not looping."); public GUIContent ringBufferMode = EditorGUIUtility.TrTextContent("Ring Buffer Mode", "Rather than dying when their lifetime has elapsed, particles will remain alive until the Max Particles buffer is full, at which point new particles will replace the oldest."); public GUIContent ringBufferLoopRange = EditorGUIUtility.TrTextContent("Loop Range", "Particle lifetimes may loop between a fade-in and fade-out time, in order to use curves for the entire time they are alive. Values are in the 0-1 range."); public GUIContent x = EditorGUIUtility.TextContent("X"); @@ -96,6 +98,14 @@ class Texts EditorGUIUtility.TrTextContent("Callback") }; + public GUIContent[] cullingModes = new GUIContent[] + { + EditorGUIUtility.TrTextContent("Automatic"), + EditorGUIUtility.TrTextContent("Pause and Catch-up"), + EditorGUIUtility.TrTextContent("Pause"), + EditorGUIUtility.TrTextContent("Always Simulate") + }; + public GUIContent[] ringBufferModes = new GUIContent[] { EditorGUIUtility.TrTextContent("Disabled"), @@ -146,6 +156,7 @@ protected override void Init() m_AutoRandomSeed = GetProperty0("autoRandomSeed"); m_RandomSeed = GetProperty0("randomSeed"); m_StopAction = GetProperty0("stopAction"); + m_CullingMode = GetProperty0("cullingMode"); m_RingBufferMode = GetProperty0("ringBufferMode"); m_RingBufferLoopRange = GetProperty0("ringBufferLoopRange"); @@ -307,6 +318,7 @@ override public void OnInspectorGUI(InitialModuleUI initial) } GUIPopup(s_Texts.stopAction, m_StopAction, s_Texts.stopActions); + GUIPopup(s_Texts.cullingMode, m_CullingMode, s_Texts.cullingModes); ParticleSystemRingBufferMode ringBufferMode = (ParticleSystemRingBufferMode)GUIPopup(s_Texts.ringBufferMode, m_RingBufferMode, s_Texts.ringBufferModes); if (!m_RingBufferMode.hasMultipleDifferentValues && ringBufferMode == ParticleSystemRingBufferMode.LoopUntilReplaced) diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs index 8fa5a25abb..6311362d91 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs @@ -427,7 +427,7 @@ void UpdateParticleSystemInfoString() if (supportsCullingText != m_SupportsCullingText || m_SupportsCullingTextLabel == null) { m_SupportsCullingText = supportsCullingText; - m_SupportsCullingTextLabel = "Automatic culling is disabled because: " + supportsCullingText.Replace("\n", "\n" + s_Texts.bulletPoint); + m_SupportsCullingTextLabel = "Procedural simulation is not supported because: " + supportsCullingText.Replace("\n", "\n" + s_Texts.bulletPoint); } } else diff --git a/Editor/Mono/Prefabs/PrefabImporterEditor.cs b/Editor/Mono/Prefabs/PrefabImporterEditor.cs index b5cc37005b..d95d7175aa 100644 --- a/Editor/Mono/Prefabs/PrefabImporterEditor.cs +++ b/Editor/Mono/Prefabs/PrefabImporterEditor.cs @@ -15,6 +15,8 @@ internal class PrefabImporterEditor : AssetImporterEditor { static GUIContent s_OpenContent = EditorGUIUtility.TrTextContent("Open Prefab"); static GUIContent s_BaseContent = EditorGUIUtility.TrTextContent("Base"); + static string s_LocalizedTitleMultiplePrefabs = L10n.Tr("Prefab Assets"); + static string s_LocalizedTitleSinglePrefab = L10n.Tr("Prefab Asset"); int m_HasMixedBaseVariants = -1; @@ -41,6 +43,17 @@ void CacheHasMixedBaseVariants() public override bool showImportedObject { get { return false; } } + internal override string targetTitle + { + get + { + if (assetTargets == null || assetTargets.Length == 1 || !m_AllowMultiObjectAccess) + return assetTarget != null ? assetTarget.name : s_LocalizedTitleSinglePrefab; + else + return assetTargets.Length + " " + s_LocalizedTitleMultiplePrefabs; + } + } + internal override void OnHeaderControlsGUI() { var variantBase = PrefabUtility.GetCorrespondingObjectFromSource(assetTarget); diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs index e14e7d536a..1d23d08821 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs @@ -17,19 +17,28 @@ internal class PrefabOverridesWindow : PopupWindowContent const float k_HeaderHeight = 32f; const float k_ButtonWidth = 120; const float k_HeaderLeftMargin = 6; + const float k_NoOverridesLabelHeight = 26f; + const float k_ApplyButtonHeight = 32f; + const float k_HelpBoxHeight = 40f; + GameObject[] m_SelectedGameObjects = null; + + // TreeView not used when there are multiple Prefabs. TreeViewState m_TreeViewState; PrefabOverridesTreeView m_TreeView; - GameObject m_SelectedGameObject; GUIContent m_StageContent = new GUIContent(); GUIContent m_InstanceContent = new GUIContent(); GUIContent m_RevertAllContent = new GUIContent(); GUIContent m_ApplyAllContent = new GUIContent(); - bool m_Immutable; + bool m_AnyOverrides; + bool m_Disconnected; bool m_InvalidComponentOnInstance; + bool m_ModelPrefab; + bool m_Immutable; bool m_InvalidComponentOnAsset; + static class Styles { public static GUIContent revertAllContent = EditorGUIUtility.TrTextContent("Revert All", "Revert all overrides."); @@ -49,46 +58,76 @@ static Styles() internal PrefabOverridesWindow(GameObject selectedGameObject) { - m_SelectedGameObject = selectedGameObject; + m_SelectedGameObjects = new GameObject[] { selectedGameObject }; m_TreeViewState = new TreeViewState(); m_TreeView = new PrefabOverridesTreeView(selectedGameObject, m_TreeViewState); - GameObject prefabAssetRoot = PrefabUtility.GetCorrespondingObjectFromSource(m_SelectedGameObject); + GameObject prefabAssetRoot = PrefabUtility.GetCorrespondingObjectFromSource(selectedGameObject); - m_TreeView.SetApplyTarget(m_SelectedGameObject, prefabAssetRoot, AssetDatabase.GetAssetPath(prefabAssetRoot)); + m_TreeView.SetApplyTarget(selectedGameObject, prefabAssetRoot, AssetDatabase.GetAssetPath(prefabAssetRoot)); - UpdateText(prefabAssetRoot); + UpdateTextSingle(prefabAssetRoot); + UpdateStatusChecks(selectedGameObject); + } - m_Immutable = PrefabUtility.IsPartOfImmutablePrefab(prefabAssetRoot); - m_InvalidComponentOnInstance = PrefabUtility.HasInvalidComponent(m_SelectedGameObject); - m_InvalidComponentOnAsset = PrefabUtility.HasInvalidComponent(prefabAssetRoot); + internal PrefabOverridesWindow(GameObject[] selectedGameObjects) + { + m_SelectedGameObjects = selectedGameObjects; + UpdateTextMultiple(); + for (int i = 0; i < m_SelectedGameObjects.Length; i++) + UpdateStatusChecks(m_SelectedGameObjects[i]); } - bool IsDisconnected() + void UpdateStatusChecks(GameObject prefabInstanceRoot) { - return PrefabUtility.IsDisconnectedFromPrefabAsset(m_SelectedGameObject); + if (PrefabUtility.HasPrefabInstanceAnyOverrides(prefabInstanceRoot, false)) + m_AnyOverrides = true; + if (PrefabUtility.IsDisconnectedFromPrefabAsset(prefabInstanceRoot)) + m_Disconnected = true; + if (PrefabUtility.HasInvalidComponent(prefabInstanceRoot)) + m_InvalidComponentOnInstance = true; + + GameObject prefabAssetRoot = PrefabUtility.GetCorrespondingObjectFromSource(prefabInstanceRoot); + + if (PrefabUtility.IsPartOfModelPrefab(prefabAssetRoot)) + m_ModelPrefab = true; + if (PrefabUtility.IsPartOfImmutablePrefab(prefabAssetRoot)) + m_Immutable = true; + if (PrefabUtility.HasInvalidComponent(prefabAssetRoot)) + m_InvalidComponentOnAsset = true; } bool IsShowingActionButton() { - if (m_TreeView.hasModifications || IsDisconnected()) - return true; + return m_AnyOverrides || m_Disconnected; + } - return false; + bool HasMultiSelection() + { + return m_SelectedGameObjects.Length > 1; + } + + bool DisplayingTreeView() + { + return m_AnyOverrides && !HasMultiSelection(); } public override Vector2 GetWindowSize() { var height = k_HeaderHeight; - if (!IsDisconnected()) - height += k_TreeViewPadding.top + m_TreeView.totalHeight + k_TreeViewPadding.bottom; + if (!IsShowingActionButton()) + { + height += k_NoOverridesLabelHeight; + } + else + { + if (DisplayingTreeView()) + height += k_TreeViewPadding.top + m_TreeView.totalHeight + k_TreeViewPadding.bottom; - const float applyButtonHeight = 32f; - if (IsShowingActionButton()) - height += applyButtonHeight; - if (m_TreeView.hasModifications || IsDisconnected()) - height += 40; + if (IsShowingActionButton()) + height += k_ApplyButtonHeight + k_HelpBoxHeight; + } // Width should be no smaller than minimum width, but we could potentially improve // width handling by making it expand if needed based on tree view content. @@ -99,6 +138,13 @@ public override Vector2 GetWindowSize() public override void OnGUI(Rect rect) { + // Escape closes the window + if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) + { + editorWindow.Close(); + GUIUtility.ExitGUI(); + } + Rect headerRect = GUILayoutUtility.GetRect(20, 10000, k_HeaderHeight, k_HeaderHeight); EditorGUI.DrawRect(headerRect, headerBgColor); @@ -120,20 +166,36 @@ public override void OnGUI(Rect rect) GUILayout.Space(k_TreeViewPadding.top); - if (!IsDisconnected()) + // If we know there are no overrides and thus no meaningful actions we just show that and nothing more. + if (!IsShowingActionButton()) { - Rect treeViewRect = GUILayoutUtility.GetRect(100, 1000, 0, 1000); - m_TreeView.OnGUI(treeViewRect); + EditorGUILayout.LabelField("No Overrides"); + return; } - if (IsShowingActionButton()) + // Display tree view and/or instructions related to it. + if (HasMultiSelection()) { - if (IsDisconnected()) + if (m_InvalidComponentOnAsset || m_InvalidComponentOnInstance || m_ModelPrefab || m_Immutable) + EditorGUILayout.HelpBox( + "Multiple Prefabs selected. Cannot show overrides.\nApplying is not possible for one or more Prefabs. Select individual Prefabs for details.", + MessageType.Info); + else + EditorGUILayout.HelpBox( + "Multiple Prefabs selected. Cannot show overrides.", + MessageType.Info); + } + else + { + if (m_Disconnected) { EditorGUILayout.HelpBox("Disconnected. Cannot show overrides.", MessageType.Warning); } - else if (m_TreeView.hasModifications) + else if (m_AnyOverrides) { + Rect treeViewRect = GUILayoutUtility.GetRect(100, 1000, 0, 1000); + m_TreeView.OnGUI(treeViewRect); + if (m_InvalidComponentOnAsset) EditorGUILayout.HelpBox( "Click on individual items to review and revert.\nThe Prefab file contains an invalid script. Applying is not possible. Enter Prefab Mode and remove the script.", @@ -142,7 +204,7 @@ public override void OnGUI(Rect rect) EditorGUILayout.HelpBox( "Click on individual items to review and revert.\nThe Prefab instance contains an invalid script. Applying is not possible. Remove the script.", MessageType.Info); - else if (PrefabUtility.IsPartOfModelPrefab(m_SelectedGameObject)) + else if (m_ModelPrefab) EditorGUILayout.HelpBox( "Click on individual items to review and revert.\nApplying to a model Prefab is not possible.", MessageType.Info); @@ -154,54 +216,93 @@ public override void OnGUI(Rect rect) EditorGUILayout.HelpBox("Click on individual items to review, revert and apply.", MessageType.Info); } + } - GUILayout.BeginHorizontal(); - - GUILayout.FlexibleSpace(); - - using (new EditorGUI.DisabledScope(m_InvalidComponentOnAsset)) + // Display action buttons (Revert All and Apply All) + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + using (new EditorGUI.DisabledScope(m_InvalidComponentOnAsset)) + { + if (GUILayout.Button(m_RevertAllContent, GUILayout.Width(k_ButtonWidth))) { - if (GUILayout.Button(m_RevertAllContent, GUILayout.Width(k_ButtonWidth))) + if (RevertAll() && editorWindow != null) { - PrefabUtility.RevertPrefabInstance(m_SelectedGameObject, InteractionMode.UserAction); - - if (editorWindow != null) - { - editorWindow.Close(); - GUIUtility.ExitGUI(); - } + editorWindow.Close(); + GUIUtility.ExitGUI(); } + } - using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance)) + using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance)) + { + if (GUILayout.Button(m_ApplyAllContent, GUILayout.Width(k_ButtonWidth))) { - if (GUILayout.Button(m_ApplyAllContent, GUILayout.Width(k_ButtonWidth))) + if (ApplyAll() && editorWindow != null) { - string assetPath = - PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(m_SelectedGameObject); - if (PrefabUtility.PromptAndCheckoutPrefabIfNeeded(assetPath, PrefabUtility.SaveVerb.Apply)) - { - PrefabUtility.ApplyPrefabInstance(m_SelectedGameObject, InteractionMode.UserAction); - - if (editorWindow != null) - { - editorWindow.Close(); - GUIUtility.ExitGUI(); - } - } + editorWindow.Close(); + GUIUtility.ExitGUI(); } } } } + GUILayout.EndHorizontal(); + } - // Escape closes the window - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) + bool ApplyAll() + { + // Collect Prefab Asset paths and also check if there's more than one of the same. + HashSet prefabAssetPaths = new HashSet(); + bool multipleOfSame = false; + for (int i = 0; i < m_SelectedGameObjects.Length; i++) { - editorWindow.Close(); - GUIUtility.ExitGUI(); + string prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(m_SelectedGameObjects[i]); + if (prefabAssetPaths.Contains(prefabAssetPath)) + multipleOfSame = true; + else + prefabAssetPaths.Add(prefabAssetPath); } + + // If more than one instance of the same Prefab Asset, show dialog to user. + if (multipleOfSame && !EditorUtility.DisplayDialog( + "Multiple instances of same Prefab Asset", + "Multiple instances of the same Prefab Asset were detected. Potentially conflicting overrides will be applied sequentially and will overwrite each other.", + "OK", + "Cancel")) + return false; + + // Make sure assets are checked out in version control. + if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(prefabAssetPaths.ToArray(), PrefabUtility.SaveVerb.Apply)) + return false; + + // Apply sequentially. + for (int i = 0; i < m_SelectedGameObjects.Length; i++) + PrefabUtility.ApplyPrefabInstance(m_SelectedGameObjects[i], InteractionMode.UserAction); + + return true; + } + + bool RevertAll() + { + for (int i = 0; i < m_SelectedGameObjects.Length; i++) + PrefabUtility.RevertPrefabInstance(m_SelectedGameObjects[i], InteractionMode.UserAction); + + return true; + } + + void UpdateTextSingle(GameObject prefabAsset) + { + Texture2D icon = (Texture2D)AssetDatabase.GetCachedIcon(AssetDatabase.GetAssetPath(prefabAsset)); + string name = prefabAsset.name; + UpdateText(icon, name); + } + + void UpdateTextMultiple() + { + Texture icon = EditorGUIUtility.IconContent("Prefab Icon").image; + string name = "(Multiple Prefabs)"; + UpdateText(icon, name); } - void UpdateText(GameObject prefabAsset) + void UpdateText(Texture assetIcon, string assetName) { var stage = SceneManagement.StageNavigationManager.instance.currentItem; if (stage.isMainStage) @@ -215,8 +316,8 @@ void UpdateText(GameObject prefabAsset) m_StageContent.text = stage.displayName; } - m_InstanceContent.image = (Texture2D)AssetDatabase.GetCachedIcon(AssetDatabase.GetAssetPath(prefabAsset)); - m_InstanceContent.text = prefabAsset.name; + m_InstanceContent.image = assetIcon; + m_InstanceContent.text = assetName; m_RevertAllContent.text = Styles.revertAllContent.text; m_RevertAllContent.tooltip = Styles.revertAllContent.tooltip; @@ -226,7 +327,7 @@ void UpdateText(GameObject prefabAsset) applyAllContent = Styles.applyAllToBaseContent; m_ApplyAllContent.text = applyAllContent.text; - m_ApplyAllContent.tooltip = string.Format(applyAllContent.tooltip, prefabAsset.name); + m_ApplyAllContent.tooltip = string.Format(applyAllContent.tooltip, assetName); } } } diff --git a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs index 499f70164c..728dd0a803 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs @@ -57,6 +57,9 @@ public sealed partial class PrefabUtility [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] extern public static void SetPropertyModifications(Object targetPrefab, PropertyModification[] modifications); + [FreeFunction] + extern public static bool HasPrefabInstanceAnyOverrides(GameObject instanceRoot, bool includeDefaultOverrides); + // Instantiate an asset that is referenced by a prefab and use it on the prefab instance. [FreeFunction] [NativeHeader("Editor/Src/Prefabs/AttachedPrefabAsset.h")] @@ -79,7 +82,7 @@ public sealed partial class PrefabUtility [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] [NativeThrows] - extern public static GameObject[] UnpackPrefabInstanceAndReturnNewOutermostRoots(GameObject root, PrefabUnpackMode unpackMode); + extern public static GameObject[] UnpackPrefabInstanceAndReturnNewOutermostRoots(GameObject instanceRoot, PrefabUnpackMode unpackMode); [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] [NativeThrows] @@ -158,16 +161,11 @@ internal static GameObject CreateVariant(GameObject assetRoot, string path) if (!Paths.IsValidAssetPath(path, ".prefab")) throw new ArgumentException("Given path is not valid: '" + path + "'"); -#pragma warning disable 0618 // Type or member is obsolete - return CreateVariant_Internal(assetRoot, path, ReplacePrefabOptions.Default); -#pragma warning restore 0618 // Type or member is obsolete + return CreateVariant_Internal(assetRoot, path); } - // TODO: Having an non-obsolete method that takes an obsolete enum types as parameter is no good. [NativeMethod("CreateVariant", IsFreeFunction = true)] -#pragma warning disable 0618 // Type or member is obsolete - extern private static GameObject CreateVariant_Internal([NotNull] GameObject original, string path, ReplacePrefabOptions replaceOptions); -#pragma warning restore 0618 // Type or member is obsolete + extern private static GameObject CreateVariant_Internal([NotNull] GameObject original, string path); private enum PrefabCreationFlags { diff --git a/Editor/Mono/Prefabs/PrefabUtility.cs b/Editor/Mono/Prefabs/PrefabUtility.cs index 869694c941..695db44170 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.cs @@ -385,21 +385,91 @@ private static void MapObjectReferencePropertyToSourceIfApplicable(SerializedPro } public static void ApplyPropertyOverride(SerializedProperty instanceProperty, string assetPath, InteractionMode action) - { - ApplyPropertyOverride(instanceProperty, assetPath, action, true); - } - - static void ApplyPropertyOverride(SerializedProperty instanceProperty, string assetPath, InteractionMode action, bool singlePropertyOnly) { DateTime startTime = DateTime.UtcNow; Object prefabInstanceObject = instanceProperty.serializedObject.targetObject; + CheckInstanceIsNotPersistent(prefabInstanceObject); + + ApplyPropertyOverrides(prefabInstanceObject, instanceProperty, assetPath, action); + + Analytics.SendApplyEvent( + Analytics.ApplyScope.PropertyOverride, + prefabInstanceObject, + assetPath, + action, + startTime, + IsPropertyOverrideDefaultOverrideComparedToAnySource(instanceProperty) + ); + } + + // This method is called both from ApplyPropertyOverride (one time) and ApplyObjectOverride (many times). + // In the former case, optionalSingleInstanceProperty is passed along as is the only property that should be processed. + // In the latter, all properties in the prefabInstanceObject are iterated. + // An alternative approach was considered where the method takes an array of SerializedProperties, + // but since there can be thousands of those in a component, and they would each have to be copied from the iterator, + // it's better to handle properties inline as the iterator iterates over them. + // This does mean that we need to cache the SerializedObjects that end up being touched. + // Those are that of the prefabInstanceObject itself, and the chain of corresponding object + // all the way to the Prefab at the specified assetPath. + // Since calling ApplyModifiedProperties on a SerializedObject can trigger a whole chain of imports, + // we don't want to create and call ApplyModifiedProperties more than once for each SerializedObject, hence the caching. + // We also can't swap the inner and outer loop, iterating the chain of corresponding objects in the outer loop + // and the SerializedProperties in the inner loop, since we only process overridden properties, so it would + // again require storing information about that for each property in some kind of list, which we want to avoid. + static void ApplyPropertyOverrides(Object prefabInstanceObject, SerializedProperty optionalSingleInstanceProperty, string assetPath, InteractionMode action) + { + bool singleProperty = optionalSingleInstanceProperty != null; Object prefabSourceObject = GetCorrespondingObjectFromSourceAtPath(prefabInstanceObject, assetPath); if (prefabSourceObject == null) return; - if (IsPropertyOverrideDefaultOverrideComparedToAnySource(instanceProperty) && IsObjectOnRootInAsset(prefabInstanceObject, assetPath)) + SerializedObject prefabSourceSerializedObject = new SerializedObject(prefabSourceObject); + + // Cache SerializedObjects used. + List serializedObjects = new List(); + + bool isObjectOnRootInAsset = IsObjectOnRootInAsset(prefabInstanceObject, assetPath); + if (singleProperty) + { + if (optionalSingleInstanceProperty.prefabOverride) + ApplySingleProperty(optionalSingleInstanceProperty, prefabSourceSerializedObject, assetPath, isObjectOnRootInAsset, true, serializedObjects, action); + } + else + { + SerializedObject so = new SerializedObject(prefabInstanceObject); + SerializedProperty property = so.GetIterator(); + while (property.Next(property.hasChildren)) + { + if (property.prefabOverride) + ApplySingleProperty(property, prefabSourceSerializedObject, assetPath, isObjectOnRootInAsset, false, serializedObjects, action); + } + } + + // Write modified value to prefab source object. + for (int i = 0; i < serializedObjects.Count; i++) + { + serializedObjects[i].ApplyModifiedProperties(); + if (action == InteractionMode.UserAction) + Undo.FlushUndoRecordObjects(); // flush'es ensure that SavePrefab() on undo/redo on the source happens in the right order + } + } + + // Since method is called for each overridden property in a component. + // That may be thousands of times if a component has lots of array data. + // We provide as much information as possible to the method as parameters + // so we don't have to recalculate it for each call. + static void ApplySingleProperty( + SerializedProperty instanceProperty, + SerializedObject prefabSourceSerializedObject, + string assetPath, + bool isObjectOnRootInAsset, + bool singlePropertyOnly, + List serializedObjects, + InteractionMode action) + { + if (isObjectOnRootInAsset && IsPropertyOverrideDefaultOverrideComparedToAnySource(instanceProperty)) { if (singlePropertyOnly) { @@ -408,12 +478,14 @@ static void ApplyPropertyOverride(SerializedProperty instanceProperty, string as if (action == InteractionMode.AutomatedAction) Debug.LogWarning("Cannot apply default-override property, since it is protected from being applied or reverted."); else - EditorUtility.DisplayDialog("Cannot apply default-override property", "Default-override properties are protected from being applied or reverted.", "OK"); + EditorUtility.DisplayDialog( + "Cannot apply default-override property", + "Default-override properties are protected from being applied or reverted.", + "OK"); } return; } - SerializedObject prefabSourceSerializedObject = new SerializedObject(prefabSourceObject); prefabSourceSerializedObject.CopyFromSerializedProperty(instanceProperty); SerializedProperty sourceProperty = prefabSourceSerializedObject.FindProperty(instanceProperty.propertyPath); @@ -432,47 +504,46 @@ static void ApplyPropertyOverride(SerializedProperty instanceProperty, string as if (action == InteractionMode.AutomatedAction) Debug.LogWarning("Cannot apply reference to scene object that is not part of apply target prefab."); else - EditorUtility.DisplayDialog("Cannot apply reference to object in scene", "A reference to an object in the scene cannot be applied to the Prefab asset.", "OK"); + EditorUtility.DisplayDialog( + "Cannot apply reference to object in scene", + "A reference to an object in the scene cannot be applied to the Prefab asset.", + "OK"); } return; } } - // Write modified value to prefab source object. - prefabSourceSerializedObject.ApplyModifiedProperties(); + // Apply target SerializedObject should get ApplyModifiedProperties called first. + if (serializedObjects.Count == 0) + serializedObjects.Add(prefabSourceSerializedObject); - if (action == InteractionMode.UserAction) - Undo.FlushUndoRecordObjects(); // flush'es ensure that SavePrefab() on undo/redo on the source happens in the right order - - // Clear overrides for property in prefab instance and outer prefabs that are using(nesting) the prefab source. + // Clear overrides for property in Prefab instance and outer Prefabs that are using(nesting) the Prefab source. // Otherwise applied modification would appear to jump back to the value it had before applying. + Object prefabInstanceObject = instanceProperty.serializedObject.targetObject; + Object prefabSourceObject = prefabSourceSerializedObject.targetObject; Object outerPrefabObject = prefabInstanceObject; + int sourceIndex = 1; while (outerPrefabObject != prefabSourceObject) { - SerializedObject outerPrefabSerializedObject = new SerializedObject(outerPrefabObject); + SerializedObject outerPrefabSerializedObject; + if (sourceIndex >= serializedObjects.Count) + { + outerPrefabSerializedObject = new SerializedObject(outerPrefabObject); + serializedObjects.Add(outerPrefabSerializedObject); + } + else + { + outerPrefabSerializedObject = serializedObjects[sourceIndex]; + } + SerializedProperty outerPrefabProp = outerPrefabSerializedObject.FindProperty(instanceProperty.propertyPath); if (outerPrefabProp.prefabOverride) { outerPrefabProp.prefabOverride = false; - outerPrefabSerializedObject.ApplyModifiedProperties(); - - if (action == InteractionMode.UserAction) - Undo.FlushUndoRecordObjects(); } - outerPrefabObject = PrefabUtility.GetCorrespondingObjectFromSource(outerPrefabObject); - } - // If this method is called as part of ApplyObjectOverride, we don't want to send analytics here too. - if (singlePropertyOnly) - { - Analytics.SendApplyEvent( - Analytics.ApplyScope.PropertyOverride, - prefabInstanceObject, - assetPath, - action, - startTime, - IsPropertyOverrideDefaultOverrideComparedToAnySource(instanceProperty) - ); + outerPrefabObject = PrefabUtility.GetCorrespondingObjectFromSource(outerPrefabObject); + sourceIndex++; } } @@ -492,13 +563,7 @@ public static void ApplyObjectOverride(Object instanceComponentOrGameObject, str CheckInstanceIsNotPersistent(instanceComponentOrGameObject); - SerializedObject so = new SerializedObject(instanceComponentOrGameObject); - SerializedProperty property = so.GetIterator(); - while (property.Next(property.hasChildren)) - { - if (property.prefabOverride) - ApplyPropertyOverride(property, assetPath, action, false); - } + ApplyPropertyOverrides(instanceComponentOrGameObject, null, assetPath, action); Analytics.SendApplyEvent( Analytics.ApplyScope.ObjectOverride, @@ -963,21 +1028,21 @@ public static GameObject SavePrefabAsset(GameObject asset) #pragma warning restore CS0618 // Type or member is obsolete } - private static void SaveAsPrefabAssetArgumentCheck(GameObject root) + private static void SaveAsPrefabAssetArgumentCheck(GameObject instanceRoot) { - if (root == null) + if (instanceRoot == null) throw new ArgumentNullException("Parameter root is null"); - if (EditorUtility.IsPersistent(root)) + if (EditorUtility.IsPersistent(instanceRoot)) throw new ArgumentException("Can't save persistent object as a Prefab asset"); - if (IsPrefabAssetMissing(root)) + if (IsPrefabAssetMissing(instanceRoot)) throw new ArgumentException("Can't save Prefab instance with missing asset as a Prefab. You may unpack the instance and save the unpacked GameObjects as a Prefab."); - var instanceRoot = GetOutermostPrefabInstanceRoot(root); - if (instanceRoot) + var actualInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot); + if (actualInstanceRoot) { - if (instanceRoot != root) + if (actualInstanceRoot != instanceRoot) throw new ArgumentException("Can't save part of a Prefab instance as a Prefab"); } } @@ -988,41 +1053,41 @@ private static bool IsPrefabInstanceRoot(GameObject gameObject) return instanceRoot != null && instanceRoot == gameObject; } - public static GameObject SaveAsPrefabAsset(GameObject root, string assetPath) + public static GameObject SaveAsPrefabAsset(GameObject instanceRoot, string assetPath) { - SaveAsPrefabAssetArgumentCheck(root); + SaveAsPrefabAssetArgumentCheck(instanceRoot); PrefabCreationFlags creationFlags = PrefabCreationFlags.None; - if (IsPrefabInstanceRoot(root)) + if (IsPrefabInstanceRoot(instanceRoot)) creationFlags = PrefabCreationFlags.CreateVariant; #pragma warning disable CS0618 // Type or member is obsolete - return SavePrefab(root, assetPath, ReplacePrefabOptions.Default, creationFlags); + return SavePrefab(instanceRoot, assetPath, ReplacePrefabOptions.Default, creationFlags); #pragma warning restore CS0618 // Type or member is obsolete } - public static GameObject SaveAsPrefabAssetAndConnect(GameObject root, string assetPath, InteractionMode action) + public static GameObject SaveAsPrefabAssetAndConnect(GameObject instanceRoot, string assetPath, InteractionMode action) { - SaveAsPrefabAssetArgumentCheck(root); + SaveAsPrefabAssetArgumentCheck(instanceRoot); var actionName = "Connect to Prefab"; if (action == InteractionMode.UserAction) { - Undo.RegisterFullObjectHierarchyUndo(root, actionName); + Undo.RegisterFullObjectHierarchyUndo(instanceRoot, actionName); } PrefabCreationFlags creationFlags = PrefabCreationFlags.None; - if (IsPrefabInstanceRoot(root)) + if (IsPrefabInstanceRoot(instanceRoot)) creationFlags = PrefabCreationFlags.CreateVariant; #pragma warning disable CS0618 // Type or member is obsolete - var assetRoot = SavePrefab(root, assetPath, ReplacePrefabOptions.ConnectToPrefab, creationFlags); + var assetRoot = SavePrefab(instanceRoot, assetPath, ReplacePrefabOptions.ConnectToPrefab, creationFlags); #pragma warning restore CS0618 // Type or member is obsolete if (action == InteractionMode.UserAction) { - Undo.RegisterCreatedObjectUndo(GetPrefabInstanceHandle(root), actionName); + Undo.RegisterCreatedObjectUndo(GetPrefabInstanceHandle(instanceRoot), actionName); } return assetRoot; @@ -1105,6 +1170,11 @@ public static GameObject CreatePrefab(string path, GameObject go, ReplacePrefabO { if (options == ReplacePrefabOptions.ConnectToPrefab) return SaveAsPrefabAssetAndConnect(go, path, InteractionMode.AutomatedAction); + else if ((options & ReplacePrefabOptions.ReplaceNameBased) != 0) + { + bool connectToPrefab = (options & ReplacePrefabOptions.ConnectToPrefab) != 0; + return ReplacePrefabAssetNameBased(go, path, connectToPrefab); + } else return SaveAsPrefabAsset(go, path); } @@ -1300,44 +1370,55 @@ internal enum SaveVerb Save, Apply } + internal static bool PromptAndCheckoutPrefabIfNeeded(string assetPath, SaveVerb saveVerb) { + return PromptAndCheckoutPrefabIfNeeded(new string[] { assetPath }, saveVerb); + } + + internal static bool PromptAndCheckoutPrefabIfNeeded(string[] assetPaths, SaveVerb saveVerb) + { + string prefabNoun = assetPaths.Length > 1 ? "Prefabs" : "Prefab"; bool result = Provider.PromptAndCheckoutIfNeeded( - new string[] { assetPath }, + assetPaths, String.Format( - "The version control requires you to check out the Prefab before {0} changes.", - saveVerb == SaveVerb.Save ? "saving" : "applying") + "The version control requires you to check out the {1} before {0} changes.", + saveVerb == SaveVerb.Save ? "saving" : "applying", + prefabNoun + ) ); if (!result) EditorUtility.DisplayDialog( String.Format( - "Could not {0} Prefab", - saveVerb == SaveVerb.Save ? "save" : "apply to"), + "Could not {0} {1}", + saveVerb == SaveVerb.Save ? "save" : "apply to", + prefabNoun), String.Format( - "It was not possible to check out the Prefab so the {0} operation has been canceled.", - saveVerb == SaveVerb.Save ? "save" : "apply"), + "It was not possible to check out the {1} so the {0} operation has been canceled.", + saveVerb == SaveVerb.Save ? "save" : "apply", + prefabNoun), "OK"); return result; } - public static void UnpackPrefabInstance(GameObject root, PrefabUnpackMode unpackMode, InteractionMode action) + public static void UnpackPrefabInstance(GameObject instanceRoot, PrefabUnpackMode unpackMode, InteractionMode action) { - if (!IsPartOfNonAssetPrefabInstance(root)) + if (!IsPartOfNonAssetPrefabInstance(instanceRoot)) throw new ArgumentException("UnpackPrefabInstance must be called with a Prefab instance."); - if (!IsOutermostPrefabInstanceRoot(root)) + if (!IsOutermostPrefabInstanceRoot(instanceRoot)) throw new ArgumentException("UnpackPrefabInstance must be called with a root Prefab instance GameObject."); if (action == InteractionMode.UserAction) { var undoActionName = "Unpack Prefab instance"; - Undo.RegisterFullObjectHierarchyUndo(root, undoActionName); - var instanceRoots = UnpackPrefabInstanceAndReturnNewOutermostRoots(root, unpackMode); - foreach (var instanceRoot in instanceRoots) + Undo.RegisterFullObjectHierarchyUndo(instanceRoot, undoActionName); + var newInstanceRoots = UnpackPrefabInstanceAndReturnNewOutermostRoots(instanceRoot, unpackMode); + foreach (var newInstanceRoot in newInstanceRoots) { - var prefabInstance = PrefabUtility.GetPrefabInstanceHandle(instanceRoot); + var prefabInstance = PrefabUtility.GetPrefabInstanceHandle(newInstanceRoot); if (prefabInstance) { Undo.RegisterCreatedObjectUndo(prefabInstance, undoActionName); @@ -1346,7 +1427,7 @@ public static void UnpackPrefabInstance(GameObject root, PrefabUnpackMode unpack } else { - UnpackPrefabInstanceAndReturnNewOutermostRoots(root, unpackMode); + UnpackPrefabInstanceAndReturnNewOutermostRoots(instanceRoot, unpackMode); } } @@ -1428,13 +1509,13 @@ public static GameObject LoadPrefabContents(string assetPath) return roots[0]; } - public static void UnloadPrefabContents(GameObject root) + public static void UnloadPrefabContents(GameObject contentsRoot) { - if (!EditorSceneManager.IsPreviewSceneObject(root)) + if (!EditorSceneManager.IsPreviewSceneObject(contentsRoot)) { throw new ArgumentException("Specified object is not part of Prefab contents"); } - var scene = root.scene; + var scene = contentsRoot.scene; EditorSceneManager.ClosePreviewScene(scene); } diff --git a/Editor/Mono/ProjectBrowser.cs b/Editor/Mono/ProjectBrowser.cs index fd04e054d5..6229ff1dda 100644 --- a/Editor/Mono/ProjectBrowser.cs +++ b/Editor/Mono/ProjectBrowser.cs @@ -1277,6 +1277,13 @@ void AssetTreeKeyboardInputCallback() OpenAssetSelection(Selection.instanceIDs); } break; + case KeyCode.Delete: + if (Event.current.shift) + { + DeleteSelectedAssets(false); + Event.current.Use(); + } + break; } } } diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs index 6de9a6e44c..0b3f63498a 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs @@ -38,6 +38,8 @@ public class PrefabStage HideFlagUtility m_HideFlagUtility; Texture2D m_PrefabFileIcon; bool m_TemporarilyDisableAutoSave; + float m_LastSavingDuration = 0f; + const float kDurationBeforeShowingSavingBadge = 1.0f; bool m_AnalyticsDidUserModify; bool m_AnalyticsDidUserSave; @@ -91,6 +93,12 @@ public string prefabAssetPath get { return m_PrefabAssetPath; } } + internal bool showingSavingLabel + { + get; + private set; + } + internal Texture2D prefabFileIcon { get { return m_PrefabFileIcon; } @@ -268,7 +276,7 @@ void HandleAutoSave() { if (autoSave && readyToAutoSave) { - SavePrefabWithVersionControlDialogAndRenameDialog(); + AutoSave(); } } @@ -298,7 +306,7 @@ public void ClearDirtiness() m_InitialSceneDirtyID = m_PreviewScene.dirtyID; } - // Not private so we use it in Tests + // Is internal so we can use it in Tests internal void SavePrefab() { if (!initialized) @@ -313,7 +321,9 @@ internal void SavePrefab() if (prefabSaving != null) prefabSaving(m_PrefabContentsRoot); + var startTime = EditorApplication.timeSinceStartup; var prefabAssetRoot = PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, m_PrefabAssetPath); + m_LastSavingDuration = (float)(EditorApplication.timeSinceStartup - startTime); if (prefabAssetRoot != null) { @@ -325,6 +335,8 @@ internal void SavePrefab() if (SceneHierarchy.s_DebugPrefabStage) Debug.Log("SAVE PREFAB ended"); + + showingSavingLabel = false; } internal bool SaveAsNewPrefab(string newPath, bool asCopy) @@ -394,6 +406,30 @@ internal bool SaveAsNewPrefabWithSavePanel() return SaveAsNewPrefab(relativePath, false); } + void PerformDelayedAutoSave() + { + EditorApplication.update -= PerformDelayedAutoSave; + SavePrefabWithVersionControlDialogAndRenameDialog(); + } + + void AutoSave() + { + showingSavingLabel = m_LastSavingDuration > kDurationBeforeShowingSavingBadge; + if (showingSavingLabel) + { + // Save delayed if we want to show the save badge while saving. + foreach (SceneView sceneView in SceneView.sceneViews) + sceneView.Repaint(); + + EditorApplication.update += PerformDelayedAutoSave; + } + else + { + // Save directly if we don't want to show the saving badge + SavePrefabWithVersionControlDialogAndRenameDialog(); + } + } + // Returns true if prefab was saved. internal bool SavePrefabWithVersionControlDialogAndRenameDialog() { diff --git a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs index 64c5a47251..3479ab3321 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs @@ -373,8 +373,8 @@ private void ClampFilterType(SerializedProperty filter) if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) { // Force unsupported A-Trous filter back to Gaussian. - if (filter.intValue == 1) - filter.intValue = 0; + if (filter.intValue == (int)LightmapEditorSettings.FilterType.ATrous) + filter.intValue = (int)LightmapEditorSettings.FilterType.Gaussian; } } @@ -397,11 +397,10 @@ void GeneralLightmapSettingsGUI() { EditorGUI.BeginChangeCheck(); - //TODO(RadeonRays) Remove this when GPU lightmapper is public. - - if (Unsupported.IsDeveloperMode() && (Application.platform == RuntimePlatform.WindowsEditor)) + //TODO(RadeonRays): Remove this when GPU lightmapper works on macOS and Linux. + if (Application.platform != RuntimePlatform.WindowsEditor) { - var backendOptions = new[] { "Enlighten", "Progressive CPU", "Progressive GPU (Preview)" }; + var backendOptions = new[] { "Enlighten", "Progressive CPU" }; m_BakeBackend.intValue = EditorGUILayout.Popup(Styles.BakeBackend, m_BakeBackend.intValue, backendOptions); } else @@ -460,13 +459,12 @@ void GeneralLightmapSettingsGUI() { EditorGUI.indentLevel++; - // TODO(RadeonRays): Hiding A-trous until it is implemented. - var filterOptions = new[] { EditorGUIUtility.TextContent("Gaussian"), EditorGUIUtility.TextContent("None") }; - var filterInts = new[] { 0, 2 }; + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.HelpBox(Styles.ProgressiveGPUWarning.text, MessageType.Info); ClampFilterType(m_PVRFilterTypeDirect); if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) - EditorGUILayout.IntPopup(m_PVRFilterTypeDirect, filterOptions, filterInts, Styles.PVRFilterTypeDirect); + EditorGUILayout.IntPopup(m_PVRFilterTypeDirect, Styles.GPUFilterOptions, Styles.GPUFilterInts, Styles.PVRFilterTypeDirect); else EditorGUILayout.PropertyField(m_PVRFilterTypeDirect, Styles.PVRFilterTypeDirect); @@ -479,7 +477,7 @@ void GeneralLightmapSettingsGUI() EditorGUILayout.Space(); if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) - EditorGUILayout.IntPopup(m_PVRFilterTypeIndirect, filterOptions, filterInts, Styles.PVRFilterTypeIndirect); + EditorGUILayout.IntPopup(m_PVRFilterTypeIndirect, Styles.GPUFilterOptions, Styles.GPUFilterInts, Styles.PVRFilterTypeIndirect); else EditorGUILayout.PropertyField(m_PVRFilterTypeIndirect, Styles.PVRFilterTypeIndirect); ClampFilterType(m_PVRFilterTypeIndirect); @@ -493,7 +491,7 @@ void GeneralLightmapSettingsGUI() { EditorGUILayout.Space(); if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) - EditorGUILayout.IntPopup(m_PVRFilterTypeAO, filterOptions, filterInts, Styles.PVRFilterTypeAO); + EditorGUILayout.IntPopup(m_PVRFilterTypeAO, Styles.GPUFilterOptions, Styles.GPUFilterInts, Styles.PVRFilterTypeAO); else EditorGUILayout.PropertyField(m_PVRFilterTypeAO, Styles.PVRFilterTypeAO); ClampFilterType(m_PVRFilterTypeAO); @@ -711,6 +709,10 @@ static class Styles public static readonly GUIContent PVRFilteringAtrousPositionSigmaIndirect = EditorGUIUtility.TrTextContent("Indirect Sigma", "Controls the threshold of the filter for indirect light stored in the lightmap. A higher value will increase the threshold, reducing noise in the indirect layer of the lightmap. Too high of a value can cause a loss of detail in the lightmap."); public static readonly GUIContent PVRFilteringAtrousPositionSigmaAO = EditorGUIUtility.TrTextContent("Ambient Occlusion Sigma", "Controls the threshold of the filter for ambient occlusion stored in the lightmap. A higher value will increase the threshold, reducing noise in the ambient occlusion layer of the lightmap. Too high of a value can cause a loss of detail in the lightmap."); public static readonly GUIContent PVRCulling = EditorGUIUtility.TrTextContent("Prioritize View", "Specifies whether the lightmapper should prioritize baking texels within the scene view. When disabled, objects outside the scene view will have the same priority as those in the scene view."); + // TODO(RadeonRays): Used for hiding A-trous filtering option until it is implemented. + public static readonly GUIContent[] GPUFilterOptions = new[] { EditorGUIUtility.TrTextContent("Gaussian"), EditorGUIUtility.TrTextContent("None") }; + public static readonly int[] GPUFilterInts = new[] { (int)LightmapEditorSettings.FilterType.Gaussian, (int)LightmapEditorSettings.FilterType.None }; + public static readonly GUIContent ProgressiveGPUWarning = EditorGUIUtility.TrTextContent("A-Trous filtering is not implemented in the Progressive GPU lightmapper yet. Use the CPU lightmapper instead if you need this functionality."); } } } // namespace diff --git a/Editor/Mono/SceneView/SceneViewStageHandling.cs b/Editor/Mono/SceneView/SceneViewStageHandling.cs index 9f45d1315c..4173497993 100644 --- a/Editor/Mono/SceneView/SceneViewStageHandling.cs +++ b/Editor/Mono/SceneView/SceneViewStageHandling.cs @@ -36,11 +36,13 @@ static bool autoSave static class Styles { - public static GUIContent autoSaveGUIContent = EditorGUIUtility.TrTextContent("Auto Save"); + 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."); public static GUIContent saveButtonContent = EditorGUIUtility.TrTextContent("Save"); public static GUIContent checkoutButtonContent = EditorGUIUtility.TrTextContent("Check Out"); + public static GUIContent autoSavingBadgeContent = EditorGUIUtility.TrTextContent("Auto Saving..."); public static GUIStyle saveToggle; public static GUIStyle button; + public static GUIStyle savingBadge = "Badge"; static Styles() { @@ -232,16 +234,14 @@ void AutoSaveButtons() { StatusQueryOptions opts = EditorUserSettings.allowAsyncStatusUpdate ? StatusQueryOptions.UseCachedAsync : StatusQueryOptions.UseCachedIfPossible; bool openForEdit = AssetDatabase.IsOpenForEdit(item.prefabAssetPath, opts); - if (!openForEdit) + + PrefabStage stage = item.prefabStage; + if (stage.showingSavingLabel) { - if (GUILayout.Button(Styles.checkoutButtonContent, Styles.button)) - { - Task task = Provider.Checkout(AssetDatabase.LoadAssetAtPath(item.prefabAssetPath), CheckoutMode.Both); - task.Wait(); - } + GUILayout.Label(Styles.autoSavingBadgeContent, Styles.savingBadge); + GUILayout.Space(4); } - PrefabStage stage = item.prefabStage; if (!stage.autoSave) { using (new EditorGUI.DisabledScope(!openForEdit || !PrefabStageUtility.GetCurrentPrefabStage().HasSceneBeenModified())) @@ -259,6 +259,15 @@ void AutoSaveButtons() if (EditorGUI.EndChangeCheck()) stage.autoSave = autoSaveForScene; } + + if (!openForEdit) + { + if (GUILayout.Button(Styles.checkoutButtonContent, Styles.button)) + { + Task task = Provider.Checkout(AssetDatabase.LoadAssetAtPath(item.prefabAssetPath), CheckoutMode.Both); + task.Wait(); + } + } } } diff --git a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs index 19a5762ed3..fb95d0cfa4 100644 --- a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs @@ -183,7 +183,8 @@ protected override Program StartCompiler() arguments.Add("/unsafe"); var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); - if (!_island._development_player) + var disableOptimizations = _island._development_player || (_island._editor && EditorPrefs.GetBool("AllowAttachedDebuggingOfEditor", true)); + if (!disableOptimizations) { if (PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.WinRTDotNET) arguments.Add("/debug:pdbonly"); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index d9ea366d92..6cab818501 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -148,7 +148,9 @@ public override void PostprocessMessage(ref CompilerMessage message) var index = message.message.IndexOf(EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest ? "Consider adding a reference to that assembly." : "Consider adding a reference to assembly"); if (index != -1) message.message = message.message.Substring(0, index); - var moduleName = GetNiceDisplayNameForModule(match.Groups[1].Value); + var moduleName = match.Groups[1].Value; + moduleName = ModuleMetadata.GetExcludingModule(moduleName); + moduleName = GetNiceDisplayNameForModule(moduleName); message.message += string.Format("Enable the built in package '{0}' in the Package Manager window to fix this error.", moduleName); } diff --git a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs index c00bc409b7..7063a34d06 100644 --- a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs +++ b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs @@ -8,6 +8,7 @@ using UnityEngine.Experimental.UIElements; using UnityEngine.Internal; using UnityEditor.StyleSheets; +using UnityEditorInternal; namespace UnityEditor { @@ -68,9 +69,20 @@ public override void OnDeactivate() public override void OnGUI(string searchContext) { if (m_SettingsEditor != null) + { using (new SettingsWindow.GUIScope()) m_SettingsEditor.OnInspectorGUI(); + // Emulate the Inspector by handling DnD at the native level. + var remainingRect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true)); + if ((Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) && remainingRect.Contains(Event.current.mousePosition)) + { + DragAndDrop.visualMode = InternalEditorUtility.InspectorWindowDrag(new[] { m_SettingsEditor.target }, Event.current.type == EventType.DragPerform); + if (Event.current.type == EventType.DragPerform) + DragAndDrop.AcceptDrag(); + } + } + base.OnGUI(searchContext); } diff --git a/Editor/Mono/Settings/SettingsService.cs b/Editor/Mono/Settings/SettingsService.cs index 61c625bdeb..8ca28cfcb2 100644 --- a/Editor/Mono/Settings/SettingsService.cs +++ b/Editor/Mono/Settings/SettingsService.cs @@ -6,14 +6,23 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Text; using UnityEngine; using UnityEngine.Internal; namespace UnityEditor { [ExcludeFromDocs] + [InitializeOnLoad] public class SettingsService { + const string k_ProjectSettings = "Edit/Project Settings"; + static SettingsService() + { + EditorApplication.update -= CheckProjectSettings; + EditorApplication.update += CheckProjectSettings; + } + public static event Action settingsProviderChanged; public static SettingsProvider[] FetchSettingsProviders() @@ -31,6 +40,22 @@ public static void NotifySettingsProviderChanged() settingsProviderChanged?.Invoke(); } + private static void CheckProjectSettings() + { + EditorApplication.update -= CheckProjectSettings; + + var deprecatedMenuItems = Menu.ExtractSubmenus(k_ProjectSettings); + if (deprecatedMenuItems.Length > 0) + { + var sb = new StringBuilder(); + sb.Append("There are menu items registered under Edit/Project Settings: "); + sb.Append(string.Join(", ", deprecatedMenuItems.Select(item => item.Replace(k_ProjectSettings + "/", "")).ToArray())); + sb.Append("\n"); + sb.AppendLine("Consider using [SettingsProvider] attribute to register in the Unified Settings Window."); + Debug.LogWarning(sb); + } + } + private static IEnumerable FetchPreferenceItems() { var methods = AttributeHelper.GetMethodsWithAttribute(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); @@ -39,8 +64,8 @@ private static IEnumerable FetchPreferenceItems() var callback = Delegate.CreateDelegate(typeof(Action), method.info) as Action; if (callback != null) { - Debug.LogWarning("PreferenceItem is deprecated. Use [SettingsProvider] instead"); var attributeName = (method.attribute as PreferenceItem).name; + Debug.LogWarning($"Trying to register preference item: \"{attributeName}\". [PreferenceItem] attribute is deprecated. Use [SettingsProvider] attribute instead."); return new SettingsProvider("Preferences/" + attributeName) { guiHandler = searchContext => callback(), scopes = SettingsScopes.User }; } diff --git a/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs b/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs index e62e1ea2e5..d507ba77b3 100644 --- a/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs +++ b/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs @@ -103,8 +103,8 @@ private void OnFocus() public void RefreshPropertiesCache() { - m_SpriteDataProvider = AssetImporter.GetAtPath(m_SelectedAssetPath) as ISpriteEditorDataProvider; - if (m_SpriteDataProvider == null) + m_SpriteDataProvider = AssetImporter.GetAtPath(m_SelectedAssetPath) as ISpriteEditorDataProvider; + if (!IsSpriteDataProviderValid()) { m_SelectedAssetPath = ""; return; @@ -156,7 +156,7 @@ private Rect warningMessageRect public SpriteImportMode spriteImportMode { - get { return m_SpriteDataProvider == null ? SpriteImportMode.None : m_SpriteDataProvider.spriteImportMode; } + get { return !IsSpriteDataProviderValid() ? SpriteImportMode.None : m_SpriteDataProvider.spriteImportMode; } } bool activeDataProviderSelected @@ -352,7 +352,7 @@ void OnEditorApplicationQuit() void HandleApplyRevertDialog(string dialogTitle, string dialogContent) { - if (textureIsDirty && m_SpriteDataProvider != null) + if (textureIsDirty && IsSpriteDataProviderValid()) { if (EditorUtility.DisplayDialog(dialogTitle, dialogContent, SpriteEditorWindowStyles.applyButtonLabel.text, SpriteEditorWindowStyles.revertButtonLabel.text)) @@ -364,10 +364,15 @@ void HandleApplyRevertDialog(string dialogTitle, string dialogContent) } } + bool IsSpriteDataProviderValid() + { + return m_SpriteDataProvider != null && !m_SpriteDataProvider.Equals(null); + } + void RefreshRects() { m_RectsCache = null; - if (m_SpriteDataProvider != null) + if (IsSpriteDataProviderValid()) { m_RectsCache = m_SpriteDataProvider.GetSpriteRects().ToList(); } @@ -379,7 +384,7 @@ private void Update() { if (m_ResetOnNextRepaint || selectedProviderChanged) { - if (selectedProviderChanged || m_SpriteDataProvider == null) + if (selectedProviderChanged || !IsSpriteDataProviderValid()) m_SelectedAssetPath = GetSelectionAssetPath(); RebuildCache(); } @@ -393,7 +398,6 @@ private void RebuildCache() RefreshPropertiesCache(); RefreshRects(); UpdateAvailableModules(); - SetupModule(m_CurrentModuleIndex); } private void DoTextureAndModulesGUI() @@ -735,7 +739,7 @@ void UpdateAvailableModules() } m_RegisteredModuleNames = new GUIContent[m_RegisteredModules.Count]; - int lastUsedModuleIndex = -1; + int lastUsedModuleIndex = 0; for (int i = 0; i < m_RegisteredModules.Count; i++) { m_RegisteredModuleNames[i] = new GUIContent(m_RegisteredModules[i].moduleName); @@ -745,10 +749,7 @@ void UpdateAvailableModules() } } - if (lastUsedModuleIndex >= 0) - SetupModule(lastUsedModuleIndex); - else - SetupModule(0); + SetupModule(lastUsedModuleIndex); } void InitModules() diff --git a/Editor/Mono/UIElements/Controls/CurveField.cs b/Editor/Mono/UIElements/Controls/CurveField.cs index a6c6f02794..e6a2f58051 100644 --- a/Editor/Mono/UIElements/Controls/CurveField.cs +++ b/Editor/Mono/UIElements/Controls/CurveField.cs @@ -149,6 +149,7 @@ public override void SetValueWithoutNotify(AnimationCurve newValue) m_Value.postWrapMode = WrapMode.Once; } m_TextureDirty = true; + CurveEditorWindow.curve = m_Value; IncrementVersion(VersionChangeType.Repaint); @@ -237,8 +238,8 @@ void FillCurveData() normals = new Vector3[k_HorizontalCurveResolution * 2]; } - float startTime = 0; - float endTime = curve.keys.Length > 0 ? curve.keys[curve.keys.Length - 1].time : 1.0f; + float startTime = curve.keys[0].time; + float endTime = curve.keys[curve.keys.Length - 1].time; float duration = endTime - startTime; float minValue = Mathf.Infinity; diff --git a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs index 69162be0eb..2cb70ecd12 100644 --- a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs +++ b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs @@ -101,6 +101,7 @@ private void RefreshVRDeviceList(BuildTargetGroup targetGroup) customOptions = new VRCustomOptionsNone(); } customOptions.Initialize(m_Settings.serializedObject); + customOptions.IsExpanded = true; m_CustomOptions.Add(deviceInfo.deviceNameKey, customOptions); } } @@ -390,7 +391,16 @@ private void AddVRDeviceElement(BuildTargetGroup target, Rect rect, ReorderableL private void RemoveVRDeviceElement(BuildTargetGroup target, ReorderableList list) { var devices = VREditor.GetVREnabledDevicesOnTargetGroup(target).ToList(); + var device = devices[list.index]; devices.RemoveAt(list.index); + + VRCustomOptions customOptions; + if (m_CustomOptions.TryGetValue(device, out customOptions)) + { + customOptions.IsExpanded = true; + } + + ApplyChangedVRDeviceList(target, devices.ToArray()); } diff --git a/Modules/AI/NavMesh/NavMesh.bindings.cs b/Modules/AI/NavMesh/NavMesh.bindings.cs index 0074c422aa..86023f6ec2 100644 --- a/Modules/AI/NavMesh/NavMesh.bindings.cs +++ b/Modules/AI/NavMesh/NavMesh.bindings.cs @@ -10,7 +10,7 @@ namespace UnityEngine.AI public static partial class NavMesh { [StaticAccessor("GetNavMeshManager()")] - [NativeName("Cleanup")] + [NativeName("CleanupAfterCarving")] public static extern void RemoveAllNavMeshData(); } } diff --git a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterEditor.cs b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterEditor.cs index f11f5c3c8d..af951453d3 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterEditor.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterEditor.cs @@ -11,6 +11,8 @@ namespace UnityEditor [CanEditMultipleObjects] internal class ModelImporterEditor : AssetImporterTabbedEditor { + static string s_LocalizedTitle = L10n.Tr("Model Import Settings"); + public override void OnEnable() { if (tabs == null) @@ -47,5 +49,16 @@ public override GUIContent GetPreviewTitle() // Only show the imported GameObject when the Model tab is active; not when the Animation tab is active public override bool showImportedObject { get { return activeTab is ModelImporterModelEditor; } } + + internal override string targetTitle + { + get + { + if (assetTargets == null || assetTargets.Length == 1 || !m_AllowMultiObjectAccess) + return base.targetTitle; + else + return assetTargets.Length + " " + s_LocalizedTitle; + } + } } } diff --git a/Modules/IMGUI/GUIStyle.cs b/Modules/IMGUI/GUIStyle.cs index 074efdb66a..7e90f54d74 100644 --- a/Modules/IMGUI/GUIStyle.cs +++ b/Modules/IMGUI/GUIStyle.cs @@ -80,6 +80,11 @@ public GUIStyle() // Constructs GUIStyle identical to given other GUIStyle. public GUIStyle(GUIStyle other) { + if (other == null) + { + Debug.LogError("Copied style is null. Using StyleNotFound instead."); + other = GUISkin.error; + } m_Ptr = Internal_Copy(this, other); } diff --git a/Modules/PresetsEditor/PresetManagerEditor.cs b/Modules/PresetsEditor/PresetManagerEditor.cs index 7a91f1785f..31d983ae32 100644 --- a/Modules/PresetsEditor/PresetManagerEditor.cs +++ b/Modules/PresetsEditor/PresetManagerEditor.cs @@ -147,6 +147,7 @@ void DrawElementCallback(Rect rect, int index, bool isActive, bool isFocused) case EventType.MouseDown: if (buttonRect.Contains(Event.current.mousePosition)) { + RefreshAddList(); var menu = new GenericMenu(); if (m_DiscoveredPresets.ContainsKey(keyType)) { diff --git a/Modules/ShortcutManagerEditor/ConflictResolver.cs b/Modules/ShortcutManagerEditor/ConflictResolver.cs index e54fc6df84..0a6cde0f5a 100644 --- a/Modules/ShortcutManagerEditor/ConflictResolver.cs +++ b/Modules/ShortcutManagerEditor/ConflictResolver.cs @@ -12,7 +12,7 @@ namespace UnityEditor.ShortcutManagement { class ConflictResolver : IConflictResolver { - public void ResolveConflict(List keyCombinationSequence, List entries) + public void ResolveConflict(IEnumerable keyCombinationSequence, IEnumerable entries) { var builder = new StringBuilder(); diff --git a/Modules/ShortcutManagerEditor/ContextManager.cs b/Modules/ShortcutManagerEditor/ContextManager.cs index 9a0de4c520..c6709cd1f7 100644 --- a/Modules/ShortcutManagerEditor/ContextManager.cs +++ b/Modules/ShortcutManagerEditor/ContextManager.cs @@ -16,6 +16,7 @@ interface IContextManager bool HasAnyPriorityContext(); bool HasPriorityContextOfType(Type type); bool HasActiveContextOfType(Type type); + bool playModeContextIsActive { get; } object GetContextInstanceOfType(Type type); } @@ -32,7 +33,19 @@ internal class GlobalContext {} List m_ToolContexts = new List(); - public int activeContextCount => 1 + ((m_FocusedWindow != null && m_FocusedWindow.IsAlive && m_FocusedWindow.Target != null) ? 1 : 0) + m_PriorityContexts.Count(c => c.active) + m_ToolContexts.Count(c => c.active); + public int activeContextCount => 1 + ((focusedWindow != null) ? 1 : 0) + m_PriorityContexts.Count(c => c.active) + m_ToolContexts.Count(c => c.active); + + public bool playModeContextIsActive => focusedWindow is GameView && EditorApplication.isPlaying; + + private EditorWindow focusedWindow + { + get + { + if (m_FocusedWindow != null && m_FocusedWindow.IsAlive && m_FocusedWindow.Target != null) + return m_FocusedWindow.Target as EditorWindow; + return null; + } + } public void SetFocusedWindow(EditorWindow window) { diff --git a/Modules/ShortcutManagerEditor/Directory.cs b/Modules/ShortcutManagerEditor/Directory.cs index e718465fd2..05f04b2292 100644 --- a/Modules/ShortcutManagerEditor/Directory.cs +++ b/Modules/ShortcutManagerEditor/Directory.cs @@ -56,6 +56,12 @@ public void FindShortcutEntries(List combinationSequence, IConte { if (!contextManager.HasActiveContextOfType(shortcutEntry.context)) continue; + if (shortcutEntry.type != ShortcutType.Menu && contextManager.playModeContextIsActive) + // Emulate old play mode shortcut behavior + // * Menu shortcuts are always active + // * Non-menu shortcuts only apply when the game view does not have focus + continue; + outputShortcuts.Add(shortcutEntry); } } diff --git a/Modules/ShortcutManagerEditor/IConflictResolver.cs b/Modules/ShortcutManagerEditor/IConflictResolver.cs index 06f79d4fdf..845e86f5e0 100644 --- a/Modules/ShortcutManagerEditor/IConflictResolver.cs +++ b/Modules/ShortcutManagerEditor/IConflictResolver.cs @@ -8,5 +8,5 @@ interface IConflictResolver { - void ResolveConflict(List keyCombinationSequence, List entries); + void ResolveConflict(IEnumerable keyCombinationSequence, IEnumerable entries); } diff --git a/Modules/ShortcutManagerEditor/Trigger.cs b/Modules/ShortcutManagerEditor/Trigger.cs index b388a2588a..e6ccda2c44 100644 --- a/Modules/ShortcutManagerEditor/Trigger.cs +++ b/Modules/ShortcutManagerEditor/Trigger.cs @@ -64,26 +64,24 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) return; m_Directory.FindShortcutEntries(m_KeyCombinationSequence, contextManager, m_Entries); + IEnumerable entries = m_Entries; // Deal ONLY with prioritycontext - if (m_Entries.Count > 1 && contextManager.HasAnyPriorityContext()) + if (entries.Count() > 1 && contextManager.HasAnyPriorityContext()) { - var entry = m_Entries.FindAll(a => contextManager.HasPriorityContextOfType(a.context)); - if (entry.Any()) - { - m_Entries.Clear(); - m_Entries.AddRange(entry); - } + entries = m_Entries.FindAll(a => contextManager.HasPriorityContextOfType(a.context)); + if (!entries.Any()) + entries = m_Entries; } - switch (m_Entries.Count) + switch (entries.Count()) { case 0: Reset(); break; case 1: - var shortcutEntry = m_Entries.Single(); + var shortcutEntry = entries.Single(); if (ShortcutFullyMatchesKeyCombination(shortcutEntry)) { if (evt.keyCode != m_KeyCombinationSequence.Last().keyCode) @@ -121,9 +119,9 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) break; default: - if (HasConflicts(m_Entries, m_KeyCombinationSequence)) + if (HasConflicts(entries, m_KeyCombinationSequence)) { - m_ConflictResolver.ResolveConflict(m_KeyCombinationSequence, m_Entries); + m_ConflictResolver.ResolveConflict(m_KeyCombinationSequence, entries); Reset(); } break; @@ -136,10 +134,10 @@ public bool HasAnyEntries() } // filtered entries are expected to all be in the same context and/or null context and they all are known to share the prefix - bool HasConflicts(List filteredEntries, List prefix) + bool HasConflicts(IEnumerable filteredEntries, List prefix) { if (filteredEntries.Any(e => e.FullyMatches(prefix))) - return filteredEntries.Count > 1; + return filteredEntries.Count() > 1; return false; } diff --git a/Modules/UIElements/ImmediateStylePainter.cs b/Modules/UIElements/ImmediateStylePainter.cs index 56e15fffdf..e6b037476e 100644 --- a/Modules/UIElements/ImmediateStylePainter.cs +++ b/Modules/UIElements/ImmediateStylePainter.cs @@ -119,18 +119,18 @@ public void DrawBackground() { IStyle style = currentElement.style; - // The background color is embedded in the texture/background image - if (style.backgroundImage.value != null) + if (style.backgroundColor != Color.clear) { - var painterParams = TextureStylePainterParameters.GetDefault(currentElement); + var painterParams = RectStylePainterParameters.GetDefault(currentElement); painterParams.border.SetWidth(0.0f); - DrawTexture(painterParams); + DrawRect(painterParams); } - else if (style.backgroundColor != Color.clear) + + if (style.backgroundImage.value != null) { - var painterParams = RectStylePainterParameters.GetDefault(currentElement); + var painterParams = TextureStylePainterParameters.GetDefault(currentElement); painterParams.border.SetWidth(0.0f); - DrawRect(painterParams); + DrawTexture(painterParams); } } diff --git a/Modules/UIElements/StylePainter.cs b/Modules/UIElements/StylePainter.cs index 29c4cc0fe4..0bca9f788a 100644 --- a/Modules/UIElements/StylePainter.cs +++ b/Modules/UIElements/StylePainter.cs @@ -114,9 +114,7 @@ public static TextureStylePainterParameters GetDefault(VisualElement ve) { rect = GUIUtility.AlignRectToDevice(ve.rect), uv = new Rect(0, 0, 1, 1), - // When the background color is not clear, we have to embed it into the texture... - // whereas if the color is clear, the white color is used... - color = (style.backgroundColor != Color.clear) ? (Color)style.backgroundColor : (Color)Color.white, + color = (Color)Color.white, texture = style.backgroundImage, scaleMode = style.backgroundScaleMode, sliceLeft = style.sliceLeft, diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index b285e968a3..baadafe1cf 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -792,6 +792,9 @@ Runtime\Export\Scripting\ExtensionOfNativeClassAttribute.cs + + Runtime\Export\Scripting\GarbageCollector.bindings.cs + Runtime\Export\Scripting\PreserveAttribute.cs diff --git a/README.md b/README.md index f414498bbd..c330049458 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b1 C# reference source code +## Unity 2018.3.0b3 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs b/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs index feea57170f..7db928fc8d 100644 --- a/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs +++ b/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs @@ -185,7 +185,7 @@ public static void SetBones(this Sprite sprite, SpriteBone[] src) extern private static SpriteChannelInfo GetBoneWeightsInfo(Sprite sprite); unsafe extern private static void SetBoneWeightsData(Sprite sprite, void* src, int count); - extern private static AtomicSafetyHandle GetSafetyHandle(this Sprite sprite); + extern internal static AtomicSafetyHandle GetSafetyHandle(this Sprite sprite); } [NativeHeader("Runtime/2D/Common/SpriteDataAccess.h")] diff --git a/Runtime/Export/AnimationCurve.bindings.cs b/Runtime/Export/AnimationCurve.bindings.cs index e8f0051e65..9262cff54b 100644 --- a/Runtime/Export/AnimationCurve.bindings.cs +++ b/Runtime/Export/AnimationCurve.bindings.cs @@ -227,6 +227,12 @@ public static AnimationCurve Constant(float timeStart, float timeEnd, float valu // A straight Line starting at /timeStart/, /valueStart/ and ending at /timeEnd/, /valueEnd/ public static AnimationCurve Linear(float timeStart, float valueStart, float timeEnd, float valueEnd) { + if (timeStart == timeEnd) + { + Keyframe key = new Keyframe(timeStart, valueStart); + return new AnimationCurve(new Keyframe[] {key}); + } + float tangent = (valueEnd - valueStart) / (timeEnd - timeStart); Keyframe[] keys = { new Keyframe(timeStart, valueStart, 0.0F, tangent), new Keyframe(timeEnd, valueEnd, tangent, 0.0F) }; return new AnimationCurve(keys); @@ -235,6 +241,12 @@ public static AnimationCurve Linear(float timeStart, float valueStart, float tim // An ease-in and out curve starting at /timeStart/, /valueStart/ and ending at /timeEnd/, /valueEnd/. public static AnimationCurve EaseInOut(float timeStart, float valueStart, float timeEnd, float valueEnd) { + if (timeStart == timeEnd) + { + Keyframe key = new Keyframe(timeStart, valueStart); + return new AnimationCurve(new Keyframe[] {key}); + } + Keyframe[] keys = { new Keyframe(timeStart, valueStart, 0.0F, 0.0F), new Keyframe(timeEnd, valueEnd, 0.0F, 0.0F) }; return new AnimationCurve(keys); } diff --git a/Runtime/Export/Scripting/GarbageCollector.bindings.cs b/Runtime/Export/Scripting/GarbageCollector.bindings.cs new file mode 100644 index 0000000000..3ed1d0271e --- /dev/null +++ b/Runtime/Export/Scripting/GarbageCollector.bindings.cs @@ -0,0 +1,46 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; + +namespace UnityEngine.Scripting +{ + [NativeHeader("Runtime/Scripting/GarbageCollector.h")] + [VisibleToOtherModules] + public static class GarbageCollector + { + public enum Mode + { + Disabled = 0, + Enabled = 1, + } + + public static Action GCModeChanged; + + public static Mode GCMode + { + get + { + return GetMode(); + } + + set + { + if (value == GetMode()) + return; + + SetMode(value); + + if (GCModeChanged != null) + GCModeChanged(value); + } + } + + [NativeThrows] + extern static void SetMode(Mode mode); + [NativeThrows] + extern static Mode GetMode(); + } +} diff --git a/Runtime/Export/Texture.cs b/Runtime/Export/Texture.cs index 06d0730b91..972e0c25ee 100644 --- a/Runtime/Export/Texture.cs +++ b/Runtime/Export/Texture.cs @@ -739,6 +739,7 @@ public void Apply([uei.DefaultValue("true")] bool updateMipmaps, [uei.DefaultVal public sealed partial class CubemapArray : Texture { + [RequiredByNativeCode] public CubemapArray(int width, int cubemapCount, GraphicsFormat format, TextureCreationFlags flags) { if (ValidateFormat(format, FormatUsage.Sample)) diff --git a/Runtime/ParticleSystem/Managed/ParticleSystem.deprecated.cs b/Runtime/ParticleSystem/Managed/ParticleSystem.deprecated.cs index 462a1bf79b..a0611e5bc6 100644 --- a/Runtime/ParticleSystem/Managed/ParticleSystem.deprecated.cs +++ b/Runtime/ParticleSystem/Managed/ParticleSystem.deprecated.cs @@ -44,7 +44,7 @@ public partial struct ShapeModule // Scale. (Meshes) [Obsolete("meshScale property is deprecated.Please use scale instead.", false)] public float meshScale { get { return scale.x; } set { scale = new Vector3(value, value, value); } } - [Obsolete("randomDirection property is deprecated.Use randomDirectionAmount instead.", false)] + [Obsolete("randomDirection property is deprecated. Use randomDirectionAmount instead.", false)] public bool randomDirection { get { return (randomDirectionAmount >= 0.5f); } set { randomDirectionAmount = value ? 1.0f : 0.0f; } } } @@ -82,11 +82,11 @@ public partial struct Particle { [Obsolete("Please use Particle.remainingLifetime instead. (UnityUpgradable) -> UnityEngine.ParticleSystem/Particle.remainingLifetime", false)] public float lifetime { get { return remainingLifetime; } set { remainingLifetime = value; } } - [Obsolete("randomValue property is deprecated.Use randomSeed instead to control random behavior of particles.", false)] + [Obsolete("randomValue property is deprecated. Use randomSeed instead to control random behavior of particles.", false)] public float randomValue { get { return BitConverter.ToSingle(BitConverter.GetBytes(m_RandomSeed), 0); } set { m_RandomSeed = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0); } } - [Obsolete("size property is deprecated.Use startSize or GetCurrentSize() instead.", false)] + [Obsolete("size property is deprecated. Use startSize or GetCurrentSize() instead.", false)] public float size { get { return startSize; } set { startSize = value; } } - [Obsolete("color property is deprecated.Use startColor or GetCurrentColor() instead.", false)] + [Obsolete("color property is deprecated. Use startColor or GetCurrentColor() instead.", false)] public Color32 color { get { return startColor; } set { startColor = value; } } } @@ -125,56 +125,59 @@ public void Emit(ParticleSystem.Particle particle) Internal_EmitOld(ref particle); } - [Obsolete("startDelay property is deprecated.Use main.startDelay or main.startDelayMultiplier instead.", false)] + [Obsolete("startDelay property is deprecated. Use main.startDelay or main.startDelayMultiplier instead.", false)] public float startDelay { get { return main.startDelayMultiplier; } set { var m = main; m.startDelayMultiplier = value; } } - [Obsolete("loop property is deprecated.Use main.loop instead.", false)] + [Obsolete("loop property is deprecated. Use main.loop instead.", false)] public bool loop { get { return main.loop; } set { var m = main; m.loop = value; } } - [Obsolete("playOnAwake property is deprecated.Use main.playOnAwake instead.", false)] + [Obsolete("playOnAwake property is deprecated. Use main.playOnAwake instead.", false)] public bool playOnAwake { get { return main.playOnAwake; } set { var m = main; m.playOnAwake = value; } } - [Obsolete("duration property is deprecated.Use main.duration instead.", false)] + [Obsolete("duration property is deprecated. Use main.duration instead.", false)] public float duration { get { return main.duration; } } - [Obsolete("playbackSpeed property is deprecated.Use main.simulationSpeed instead.", false)] + [Obsolete("playbackSpeed property is deprecated. Use main.simulationSpeed instead.", false)] public float playbackSpeed { get { return main.simulationSpeed; } set { var m = main; m.simulationSpeed = value; } } - [Obsolete("enableEmission property is deprecated.Use emission.enabled instead.", false)] + [Obsolete("enableEmission property is deprecated. Use emission.enabled instead.", false)] public bool enableEmission { get { return emission.enabled; } set { var em = emission; em.enabled = value; } } - [Obsolete("emissionRate property is deprecated.Use emission.rateOverTime, emission.rateOverDistance, emission.rateOverTimeMultiplier or emission.rateOverDistanceMultiplier instead.", false)] + [Obsolete("emissionRate property is deprecated. Use emission.rateOverTime, emission.rateOverDistance, emission.rateOverTimeMultiplier or emission.rateOverDistanceMultiplier instead.", false)] public float emissionRate { get { return emission.rateOverTimeMultiplier; } set { var em = emission; em.rateOverTime = value; } } - [Obsolete("startSpeed property is deprecated.Use main.startSpeed or main.startSpeedMultiplier instead.", false)] + [Obsolete("startSpeed property is deprecated. Use main.startSpeed or main.startSpeedMultiplier instead.", false)] public float startSpeed { get { return main.startSpeedMultiplier; } set { var m = main; m.startSpeedMultiplier = value; } } - [Obsolete("startSize property is deprecated.Use main.startSize or main.startSizeMultiplier instead.", false)] + [Obsolete("startSize property is deprecated. Use main.startSize or main.startSizeMultiplier instead.", false)] public float startSize { get { return main.startSizeMultiplier; } set { var m = main; m.startSizeMultiplier = value; } } - [Obsolete("startColor property is deprecated.Use main.startColor instead.", false)] + [Obsolete("startColor property is deprecated. Use main.startColor instead.", false)] public Color startColor { get { return main.startColor.color; } set { var m = main; m.startColor = value; } } - [Obsolete("startRotation property is deprecated.Use main.startRotation or main.startRotationMultiplier instead.", false)] + [Obsolete("startRotation property is deprecated. Use main.startRotation or main.startRotationMultiplier instead.", false)] public float startRotation { get { return main.startRotationMultiplier; } set { var m = main; m.startRotationMultiplier = value; } } - [Obsolete("startRotation3D property is deprecated.Use main.startRotationX, main.startRotationY and main.startRotationZ instead. (Or main.startRotationXMultiplier, main.startRotationYMultiplier and main.startRotationZMultiplier).", false)] + [Obsolete("startRotation3D property is deprecated. Use main.startRotationX, main.startRotationY and main.startRotationZ instead. (Or main.startRotationXMultiplier, main.startRotationYMultiplier and main.startRotationZMultiplier).", false)] public Vector3 startRotation3D { get { return new Vector3(main.startRotationXMultiplier, main.startRotationYMultiplier, main.startRotationZMultiplier); } set { var m = main; m.startRotationXMultiplier = value.x; m.startRotationYMultiplier = value.y; m.startRotationZMultiplier = value.z; } } - [Obsolete("startLifetime property is deprecated.Use main.startLifetime or main.startLifetimeMultiplier instead.", false)] + [Obsolete("startLifetime property is deprecated. Use main.startLifetime or main.startLifetimeMultiplier instead.", false)] public float startLifetime { get { return main.startLifetimeMultiplier; } set { var m = main; m.startLifetimeMultiplier = value; } } - [Obsolete("gravityModifier property is deprecated.Use main.gravityModifier or main.gravityModifierMultiplier instead.", false)] + [Obsolete("gravityModifier property is deprecated. Use main.gravityModifier or main.gravityModifierMultiplier instead.", false)] public float gravityModifier { get { return main.gravityModifierMultiplier; } set { var m = main; m.gravityModifierMultiplier = value; } } - [Obsolete("maxParticles property is deprecated.Use main.maxParticles instead.", false)] + [Obsolete("maxParticles property is deprecated. Use main.maxParticles instead.", false)] public int maxParticles { get { return main.maxParticles; } set { var m = main; m.maxParticles = value; } } - [Obsolete("simulationSpace property is deprecated.Use main.simulationSpace instead.", false)] + [Obsolete("simulationSpace property is deprecated. Use main.simulationSpace instead.", false)] public ParticleSystemSimulationSpace simulationSpace { get { return main.simulationSpace; } set { var m = main; m.simulationSpace = value; } } - [Obsolete("scalingMode property is deprecated.Use main.scalingMode instead.", false)] + [Obsolete("scalingMode property is deprecated. Use main.scalingMode instead.", false)] public ParticleSystemScalingMode scalingMode { get { return main.scalingMode; } set { var m = main; m.scalingMode = value; } } + + [Obsolete("automaticCullingEnabled property is deprecated. Use proceduralSimulationSupported instead (UnityUpgradable) -> proceduralSimulationSupported", true)] + public bool automaticCullingEnabled { get { return proceduralSimulationSupported; } } } public static partial class ParticlePhysicsExtensions diff --git a/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs b/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs index c1a37bb876..432ca9b435 100644 --- a/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs +++ b/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs @@ -188,6 +188,15 @@ public enum ParticleSystemStopAction Callback = 3 // Calls OnParticleSystemStopped. } + // The action to perform when a particle system is offscreen + public enum ParticleSystemCullingMode + { + Automatic = 0, + PauseAndCatchup = 1, + Pause = 2, + AlwaysSimulate = 3 + } + // The emitter velocity mode for particle systems public enum ParticleSystemEmitterVelocityMode { diff --git a/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs b/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs index cde478662b..591e257949 100644 --- a/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs +++ b/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs @@ -64,7 +64,7 @@ extern public bool useAutoRandomSeed set; } - extern public bool automaticCullingEnabled + extern public bool proceduralSimulationSupported { get; } diff --git a/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs index 91ff96bb6b..51484d3ada 100644 --- a/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs @@ -54,6 +54,14 @@ public static UnityType[] GetModuleTypes(string moduleName) [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern internal static ModuleIncludeSetting GetModuleIncludeSettingForObject (Object o) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern internal static string GetExcludingModuleForObject (Object o) ; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern internal static string GetExcludingModule (string module) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern internal static uint[] GetModuleTypeIndices (string moduleName) ; diff --git a/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs b/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs index a95bdccce4..dfa7f7c180 100644 --- a/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs @@ -63,6 +63,7 @@ public partial struct MainModule public int maxParticles { get { return GetMaxParticles(m_ParticleSystem); } set { SetMaxParticles(m_ParticleSystem, value); } } public ParticleSystemEmitterVelocityMode emitterVelocityMode { get { return GetUseRigidbodyForVelocity(m_ParticleSystem) ? ParticleSystemEmitterVelocityMode.Rigidbody : ParticleSystemEmitterVelocityMode.Transform; } set { SetUseRigidbodyForVelocity(m_ParticleSystem, value == ParticleSystemEmitterVelocityMode.Rigidbody); } } public ParticleSystemStopAction stopAction { get { return GetStopAction(m_ParticleSystem); } set { SetStopAction(m_ParticleSystem, value); } } + public ParticleSystemCullingMode cullingMode { get { return GetCullingMode(m_ParticleSystem); } set { SetCullingMode(m_ParticleSystem, value); } } public ParticleSystemRingBufferMode ringBufferMode { get { return GetRingBufferMode(m_ParticleSystem); } set { SetRingBufferMode(m_ParticleSystem, value); } } public Vector2 ringBufferLoopRange { get { return GetRingBufferLoopRange(m_ParticleSystem); } set { SetRingBufferLoopRange(m_ParticleSystem, value); } } @@ -363,6 +364,14 @@ public partial struct MainModule [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern private static ParticleSystemStopAction GetStopAction (ParticleSystem system) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static void SetCullingMode (ParticleSystem system, ParticleSystemCullingMode value) ; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static ParticleSystemCullingMode GetCullingMode (ParticleSystem system) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern private static void SetRingBufferMode (ParticleSystem system, ParticleSystemRingBufferMode value) ; From 86ce57f70f76576207924c1757dca4d310fcfca7 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 10 Oct 2018 08:17:14 +0000 Subject: [PATCH 14/17] Unity 2018.3.0b5 C# reference source code --- .../2D/SpriteAtlas/SpriteAtlasInspector.cs | 8 +- .../Animation/GameObjectRecorder.bindings.cs | 12 +- Editor/Mono/BuildPipeline.bindings.cs | 2 + .../BuiltinBakedReflectionSystem.bindings.cs | 9 + .../IScriptableBakedReflectionSystem.cs | 1 + .../Camera/ScriptableBakedReflectionSystem.cs | 1 + ...leBakedReflectionSystemWrapper.bindings.cs | 12 + Editor/Mono/EditorApplication.cs | 8 + Editor/Mono/EditorGUI.cs | 2 +- .../Mono/GI/LightmapVisualization.bindings.cs | 3 + Editor/Mono/GUI/ColorPicker.cs | 2 +- Editor/Mono/GUIView.cs | 1 - Editor/Mono/Inspector/AudioClipInspector.cs | 64 +- .../Inspector/LightingSettingsInspector.cs | 184 ++--- .../PlayerSettingsEditor.cs | 6 +- Editor/Mono/Inspector/PreviewRenderUtility.cs | 2 +- .../Mono/Inspector/QualitySettingsEditor.cs | 2 + .../Inspector/StandardParticlesShaderGUI.cs | 20 +- Editor/Mono/Menu.bindings.cs | 4 +- .../ParticleSystemModules/RendererModuleUI.cs | 9 +- .../ParticleSystemModules/TrailModuleUI.cs | 4 + Editor/Mono/PerformanceTools/FrameDebugger.cs | 2 +- Editor/Mono/PlayerSettings.bindings.cs | 6 + Editor/Mono/PlayerSettingsAndroid.bindings.cs | 3 + Editor/Mono/PlayerSettingsSwitch.bindings.cs | 6 +- .../PreferencesSettingsProviders.cs | 13 +- Editor/Mono/SceneHierarchy.cs | 2 - .../LightingWindowLightmapPreviewTab.cs | 30 +- .../SceneModeWindows/LightmapPreviewWindow.cs | 61 +- Editor/Mono/SceneView/SceneView.cs | 100 ++- .../Mono/Scripting/Compilers/UWPReferences.cs | 88 ++- .../CSharpNamespaceParser.cs | 42 +- Editor/Mono/UIElements/UXMLEditorFactories.cs | 3 +- .../Mono/UIElements/VisualTreeAssetEditor.cs | 1 - .../SolutionSynchronizer.cs | 2 +- .../Mono/GoogleVR/VRCustomOptionsGoogleVR.cs | 10 +- .../VR/Mono/Oculus/VRCustomOptionsOculus.cs | 57 +- Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs | 30 +- Editor/Src/VR/Mono/VRCustomOptions.cs | 4 +- .../VRCustomOptionsWindowsHolographic.cs | 2 +- .../Public/PluginImporter.bindings.cs | 3 + .../MemoryProfiler/MemorySnapshot.cs | 47 +- .../ProfilerWindow/MemorySnapshot.cs | 21 +- .../ShortcutAttributeDiscoveryProvider.cs | 12 +- .../ShortcutController.cs | 15 + .../ShortcutManagerEditor/ShortcutEntry.cs | 4 +- Modules/ShortcutManagerEditor/Trigger.cs | 30 +- Modules/TextCore/Managed/AssemblyInfo.cs | 2 + Modules/TextCore/Managed/FaceInfo.cs | 261 +++++++ Modules/TextCore/Managed/Glyph.cs | 404 +++++++---- .../ScriptBindings/FontEngine.bindings.cs | 636 +++++++++++++++++- .../ScriptBindings/GlyphMarshallingStruct.cs | 74 ++ .../TextRendering/TextRendering.bindings.cs | 9 +- .../Managed/Grid/GridPaintPaletteWindow.cs | 12 +- .../Managed/Grid/GridPaletteAddPopup.cs | 4 + .../Editor/Managed/Grid/PaintableGrid.cs | 22 +- .../Managed/Grid/PaintableSceneViewGrid.cs | 10 +- .../ScriptBindings/VFXEnums.bindings.cs | 7 +- .../ScriptBindings/VisualEffect.bindings.cs | 26 +- .../VFXMemorySerializer.bindings.cs | 19 +- .../VisualEffectResource.bindings.cs | 1 + Projects/CSharp/UnityEngine.csproj | 6 + README.md | 2 +- Runtime/Export/Camera.bindings.cs | 3 + Runtime/Export/GraphicsManagers.bindings.cs | 2 + .../ScriptBindings/ParticleSystem.bindings.cs | 18 +- .../ScriptBindings/Transform.bindings.cs | 5 +- .../ParticleSystemBindings.gen.cs | 18 + 68 files changed, 2002 insertions(+), 489 deletions(-) create mode 100644 Modules/TextCore/Managed/FaceInfo.cs create mode 100644 Modules/TextCore/ScriptBindings/GlyphMarshallingStruct.cs diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs index 3ff20a742e..90218d3f3e 100644 --- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs +++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs @@ -61,7 +61,8 @@ class Styles public readonly GUIContent variantMultiplierLabel = EditorGUIUtility.TrTextContent("Scale", "Down scale ratio."); public readonly GUIContent copyMasterButton = EditorGUIUtility.TrTextContent("Copy Master's Settings", "Copy all master's settings into this variant."); public readonly GUIContent packButton = EditorGUIUtility.TrTextContent("Pack Preview", "Pack this atlas."); - public readonly GUIContent disabledPackLabel = EditorGUIUtility.TrTextContent("Sprite Atlas packing is disabled. Enable it in Edit > Project Settings > Editor."); + + public readonly GUIContent disabledPackLabel = EditorGUIUtility.TrTextContent("Sprite Atlas packing is disabled. Enable it in Edit > Settings > Editor.", null, EditorGUIUtility.GetHelpIcon(MessageType.Info)); public readonly GUIContent packableListLabel = EditorGUIUtility.TrTextContent("Objects for Packing", "Only accept Folder, Sprite Sheet(Texture) and Sprite."); public readonly GUIContent notPowerOfTwoWarning = EditorGUIUtility.TrTextContent("This scale will produce a Sprite Atlas variant with a packed texture that is NPOT (non - power of two). This may cause visual artifacts in certain compression/texture formats."); @@ -310,7 +311,10 @@ public override void OnInspectorGUI() } else { - EditorGUILayout.HelpBox(s_Styles.disabledPackLabel.text, MessageType.Info); + if (GUILayout.Button(s_Styles.disabledPackLabel, EditorStyles.helpBox)) + { + SettingsWindow.OpenProjectSettings("Project/Editor"); + } } serializedObject.ApplyModifiedProperties(); diff --git a/Editor/Mono/Animation/GameObjectRecorder.bindings.cs b/Editor/Mono/Animation/GameObjectRecorder.bindings.cs index c5ee0ddd49..de7c75bede 100644 --- a/Editor/Mono/Animation/GameObjectRecorder.bindings.cs +++ b/Editor/Mono/Animation/GameObjectRecorder.bindings.cs @@ -46,7 +46,17 @@ public void BindComponentsOfType(GameObject target, Type componentType, bool rec extern public GameObject root { get; } // Bindings. - extern public void Bind(EditorCurveBinding binding); + public void Bind(EditorCurveBinding binding) + { + if (!binding.type.IsSubclassOf(typeof(UnityEngine.Object))) + throw new InvalidCastException("Binding type should derive from Unity type."); + + BindInternal(binding); + } + + [NativeMethod("Bind")] + extern private void BindInternal(EditorCurveBinding binding); + extern public void BindAll(GameObject target, bool recursive); extern public void BindComponent([NotNull] Component component); diff --git a/Editor/Mono/BuildPipeline.bindings.cs b/Editor/Mono/BuildPipeline.bindings.cs index 87dd7ed3cc..64e3257ace 100644 --- a/Editor/Mono/BuildPipeline.bindings.cs +++ b/Editor/Mono/BuildPipeline.bindings.cs @@ -9,6 +9,7 @@ using UnityEngine.Bindings; using UnityEditor.Build.Reporting; using Mono.Cecil; +using UnityEditor.Scripting.ScriptCompilation; namespace UnityEditor { @@ -179,6 +180,7 @@ public class BuildPipeline internal static extern BuildTargetGroup GetBuildTargetGroupByName(string platform); internal static extern BuildTarget GetBuildTargetByName(string platform); + internal static extern EditorScriptCompilationOptions GetScriptCompileFlags(BuildOptions buildOptions, BuildTarget buildTarget); [FreeFunction] internal static extern string GetBuildTargetGroupDisplayName(BuildTargetGroup targetPlatformGroup); diff --git a/Editor/Mono/Camera/BuiltinBakedReflectionSystem.bindings.cs b/Editor/Mono/Camera/BuiltinBakedReflectionSystem.bindings.cs index 7928108d9b..c2e20ef94f 100644 --- a/Editor/Mono/Camera/BuiltinBakedReflectionSystem.bindings.cs +++ b/Editor/Mono/Camera/BuiltinBakedReflectionSystem.bindings.cs @@ -64,6 +64,14 @@ public void Clear() Internal_Clear(); } + public bool BakeAllReflectionProbes() + { + if (disposed) + throw new ObjectDisposedException("BuiltinBakedReflectionSystem"); + + return Internal_BakeAllReflectionProbes(); + } + public void Cancel() { // Cancel is empty on purpose @@ -120,5 +128,6 @@ void Internal_BuiltinBakedReflectionSystem_SetIsDone(bool isDone) extern void Internal_SynchronizeReflectionProbes(); extern void Internal_Clear(); extern void Internal_SetPtr(BuiltinBakedReflectionSystem ptr); + extern bool Internal_BakeAllReflectionProbes(); } } diff --git a/Editor/Mono/Camera/IScriptableBakedReflectionSystem.cs b/Editor/Mono/Camera/IScriptableBakedReflectionSystem.cs index bcb1c439d4..2557f60973 100644 --- a/Editor/Mono/Camera/IScriptableBakedReflectionSystem.cs +++ b/Editor/Mono/Camera/IScriptableBakedReflectionSystem.cs @@ -16,5 +16,6 @@ public interface IScriptableBakedReflectionSystem : IDisposable void SynchronizeReflectionProbes(); void Clear(); void Cancel(); + bool BakeAllReflectionProbes(); } } diff --git a/Editor/Mono/Camera/ScriptableBakedReflectionSystem.cs b/Editor/Mono/Camera/ScriptableBakedReflectionSystem.cs index 45f1f55623..416f7574a1 100644 --- a/Editor/Mono/Camera/ScriptableBakedReflectionSystem.cs +++ b/Editor/Mono/Camera/ScriptableBakedReflectionSystem.cs @@ -21,6 +21,7 @@ public virtual void Tick(SceneStateHash sceneStateHash, IScriptableBakedReflecti public virtual void SynchronizeReflectionProbes() {} public virtual void Clear() {} public virtual void Cancel() {} + public virtual bool BakeAllReflectionProbes() { return false; } protected virtual void Dispose(bool disposing) {} diff --git a/Editor/Mono/Camera/ScriptableBakedReflectionSystemWrapper.bindings.cs b/Editor/Mono/Camera/ScriptableBakedReflectionSystemWrapper.bindings.cs index e2c26a0746..96d7c7cdcc 100644 --- a/Editor/Mono/Camera/ScriptableBakedReflectionSystemWrapper.bindings.cs +++ b/Editor/Mono/Camera/ScriptableBakedReflectionSystemWrapper.bindings.cs @@ -118,6 +118,18 @@ void Internal_ScriptableBakedReflectionSystemWrapper_Cancel() implementation.Cancel(); } + [RequiredByNativeCode] + bool Internal_ScriptableBakedReflectionSystemWrapper_BakeAllReflectionProbes() + { + if (Disposed) + throw new ObjectDisposedException("ScriptableBakedReflectionSystemWrapper"); + + if (implementation != null) + return implementation.BakeAllReflectionProbes(); + + return false; + } + [StaticAccessor("ScriptableBakedReflectionSystem", StaticAccessorType.DoubleColon)] static extern void ScriptingEnterStage(IntPtr objPtr, int stage, string progressMessage, float progress); diff --git a/Editor/Mono/EditorApplication.cs b/Editor/Mono/EditorApplication.cs index 58680a1ff7..9d941b3959 100644 --- a/Editor/Mono/EditorApplication.cs +++ b/Editor/Mono/EditorApplication.cs @@ -190,6 +190,8 @@ public static void DirtyHierarchyWindowSorting() // Returns true when the pressed keys are defined in the Trigger internal static Func doPressedKeysTriggerAnyShortcut; + internal static event Action focusChanged; + // Windows were reordered internal static CallbackFunction windowsReordered; @@ -335,5 +337,11 @@ static void Internal_CallGlobalEventHandler() Event.current = null; } + + [RequiredByNativeCode] + static void Internal_FocusChanged(bool isFocused) + { + focusChanged?.Invoke(isFocused); + } } } diff --git a/Editor/Mono/EditorGUI.cs b/Editor/Mono/EditorGUI.cs index 0494d380d8..8fad8a4c1f 100644 --- a/Editor/Mono/EditorGUI.cs +++ b/Editor/Mono/EditorGUI.cs @@ -2536,7 +2536,7 @@ private static float DoSlider( if (sliderBackground != null && Event.current.type == EventType.Repaint) { var bgRect = sliderStyle.overflow.Add(sliderStyle.padding.Remove(sliderRect)); - Graphics.DrawTexture(bgRect, sliderBackground, new Rect(.5f / sliderBackground.width, .5f / sliderBackground.height, 1 - 1f / sliderBackground.width, 1 - 1f / sliderBackground.height), 0, 0, 0, 0, Color.grey); + 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)); } newSliderValue = GUI.Slider(sliderRect, newSliderValue, 0, remapLeft, remapRight, sliderStyle, showMixedValue ? "SliderMixed" : thumbStyle, true, sliderId); diff --git a/Editor/Mono/GI/LightmapVisualization.bindings.cs b/Editor/Mono/GI/LightmapVisualization.bindings.cs index 95cdebbaf8..435a75b001 100644 --- a/Editor/Mono/GI/LightmapVisualization.bindings.cs +++ b/Editor/Mono/GI/LightmapVisualization.bindings.cs @@ -31,6 +31,9 @@ internal sealed partial class LightmapVisualizationUtility [StaticAccessor("VisualisationManager::Get()", StaticAccessorType.Arrow)] internal extern static bool IsBakedTextureType(GITextureType textureType); + [StaticAccessor("VisualisationManager::Get()", StaticAccessorType.Arrow)] + internal extern static bool IsAtlasTextureType(GITextureType textureType); + [StaticAccessor("VisualisationManager::Get()", StaticAccessorType.Arrow)] public extern static VisualisationGITexture[] GetRealtimeGITextures(GITextureType textureType); diff --git a/Editor/Mono/GUI/ColorPicker.cs b/Editor/Mono/GUI/ColorPicker.cs index 58d0173fd8..670789bce6 100644 --- a/Editor/Mono/GUI/ColorPicker.cs +++ b/Editor/Mono/GUI/ColorPicker.cs @@ -448,7 +448,7 @@ void DrawColorSpaceBox(Rect colorBoxRect, float constantValue) m_LastConstant = constantValue; m_TextureColorBoxMode = (int)m_ColorBoxMode; } - 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, Color.grey); + 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)); } static class Styles diff --git a/Editor/Mono/GUIView.cs b/Editor/Mono/GUIView.cs index 2398aec6e2..a86b7dd95c 100644 --- a/Editor/Mono/GUIView.cs +++ b/Editor/Mono/GUIView.cs @@ -36,7 +36,6 @@ protected Panel panel { if (m_Panel == null) { - UXMLEditorFactories.RegisterAll(); m_Panel = UIElementsUtility.FindOrCreatePanel(this, ContextType.Editor, DataWatchService.sharedInstance); m_Panel.cursorManager = m_CursorManager; m_Panel.contextualMenuManager = s_ContextualMenuManager; diff --git a/Editor/Mono/Inspector/AudioClipInspector.cs b/Editor/Mono/Inspector/AudioClipInspector.cs index 1ac6c24213..d4304d9698 100644 --- a/Editor/Mono/Inspector/AudioClipInspector.cs +++ b/Editor/Mono/Inspector/AudioClipInspector.cs @@ -120,29 +120,26 @@ public override void OnPreviewSettings() AudioClip clip = target as AudioClip; + bool isEditingMultipleObjects = targets.Length > 1; + using (new EditorGUI.DisabledScope(AudioUtil.IsMovieAudio(clip))) { - bool isEditingMultipleObjects = targets.Length > 1; - - using (new EditorGUI.DisabledScope(isEditingMultipleObjects)) + bool oldAutoPlay = m_bAutoPlay; + bool newAutoPlay = PreviewGUI.CycleButton(oldAutoPlay ? 1 : 0, s_AutoPlayIcons) != 0; + if (oldAutoPlay != newAutoPlay) { - bool oldAutoPlay = isEditingMultipleObjects ? false : m_bAutoPlay; - bool newAutoPlay = PreviewGUI.CycleButton(oldAutoPlay ? 1 : 0, s_AutoPlayIcons) != 0; - if (oldAutoPlay != newAutoPlay) - { - m_bAutoPlay = newAutoPlay; - InspectorWindow.RepaintAllInspectors(); - } + m_bAutoPlay = newAutoPlay; + InspectorWindow.RepaintAllInspectors(); + } - bool oldLoop = isEditingMultipleObjects ? false : m_bLoop; - bool newLoop = PreviewGUI.CycleButton(oldLoop ? 1 : 0, s_LoopIcons) != 0; - if (oldLoop != newLoop) - { - m_bLoop = newLoop; - if (playing) - AudioUtil.LoopClip(clip, newLoop); - InspectorWindow.RepaintAllInspectors(); - } + bool oldLoop = m_bLoop; + bool newLoop = PreviewGUI.CycleButton(oldLoop ? 1 : 0, s_LoopIcons) != 0; + if (oldLoop != newLoop) + { + m_bLoop = newLoop; + if (playing) + AudioUtil.LoopClip(clip, newLoop); + InspectorWindow.RepaintAllInspectors(); } using (new EditorGUI.DisabledScope(isEditingMultipleObjects && !playing && m_PlayingInspector != this)) @@ -153,8 +150,10 @@ public override void OnPreviewSettings() if (newPlaying != curPlaying) { AudioUtil.StopAllClips(); + m_PlayingClip = null; + m_PlayingInspector = null; - if (newPlaying) + if (newPlaying && !isEditingMultipleObjects) { AudioUtil.PlayClip(clip, 0, m_bLoop); m_PlayingClip = clip; @@ -163,6 +162,21 @@ public override void OnPreviewSettings() } } } + + // autoplay start? + if (m_bAutoPlay && m_PlayingClip != clip && m_PlayingInspector == this && !isEditingMultipleObjects) + { + AudioUtil.StopAllClips(); + m_PlayingClip = null; + m_PlayingInspector = null; + + if (!isEditingMultipleObjects) + { + AudioUtil.PlayClip(clip, 0, m_bLoop); + m_PlayingClip = clip; + m_PlayingInspector = this; + } + } } // 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. @@ -314,16 +328,6 @@ public override void OnPreviewGUI(Rect r, GUIStyle background) PreviewGUI.EndScrollView(); } - - // autoplay start? - if (m_bAutoPlay && m_PlayingClip != clip && m_PlayingInspector == this) - { - AudioUtil.StopAllClips(); - AudioUtil.PlayClip(clip, 0, m_bLoop); - m_PlayingClip = clip; - m_PlayingInspector = this; - } - // force update GUI if (playing) GUIView.current.Repaint(); diff --git a/Editor/Mono/Inspector/LightingSettingsInspector.cs b/Editor/Mono/Inspector/LightingSettingsInspector.cs index ae164fd643..0f27dbf8aa 100644 --- a/Editor/Mono/Inspector/LightingSettingsInspector.cs +++ b/Editor/Mono/Inspector/LightingSettingsInspector.cs @@ -63,12 +63,18 @@ static class Styles public static readonly GUIContent GINotEnabledInfo = EditorGUIUtility.TrTextContent("Lightmapping settings are currently disabled. Enable Baked Global Illumination or Realtime Global Illumination to display these settings."); public static readonly GUIContent CastShadowsProgressiveGPUWarning = EditorGUIUtility.TrTextContent("Cast Shadows is forced to 'On' when using the GPU lightmapper (Preview), it will be supported in a later version. Use the CPU lightmapper instead if you need this functionality."); public static readonly GUIContent ReceiveShadowsProgressiveGPUWarning = EditorGUIUtility.TrTextContent("Receive Shadows is forced to 'On' when using the GPU lightmapper (Preview), it will be supported in a later version. Use the CPU lightmapper instead if you need this functionality."); + public static readonly GUIContent OpenPreview = EditorGUIUtility.TrTextContent("Open Preview"); + + public static readonly GUIStyle OpenPreviewStyle = EditorStyles.objectFieldThumb.name + "LightmapPreviewOverlay"; + + public static readonly int PreviewPadding = 30; + public static readonly int PreviewWidth = 104; } bool m_ShowChartingSettings = true; bool m_ShowLightmapSettings = true; - bool m_ShowBakedLM = false; - bool m_ShowRealtimeLM = false; + bool m_ShowBakedLM = true; + bool m_ShowRealtimeLM = true; SerializedObject m_SerializedObject; SerializedObject m_GameObjectsSerializedObject; @@ -240,13 +246,8 @@ public void RenderMeshSettings(bool showLightmapSettings) { EditorGUI.indentLevel += 1; - m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, Styles.Atlas, true); - if (m_ShowBakedLM) - ShowAtlasGUI(m_Renderers[0].GetInstanceID()); - - m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, Styles.RealtimeLM, true); - if (m_ShowRealtimeLM) - ShowRealtimeLMGUI(m_Renderers[0]); + ShowAtlasGUI(m_Renderers[0].GetInstanceID()); + ShowRealtimeLMGUI(m_Renderers[0]); EditorGUI.indentLevel -= 1; } @@ -312,13 +313,8 @@ public void RenderTerrainSettings() if (GUI.enabled && m_Terrains.Length == 1 && m_Terrains[0].terrainData != null) ShowBakePerformanceWarning(m_Terrains[0]); - m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, Styles.Atlas, true); - if (m_ShowBakedLM) - ShowAtlasGUI(m_Terrains[0].GetInstanceID()); - - m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, Styles.RealtimeLM, true); - if (m_ShowRealtimeLM) - ShowRealtimeLMGUI(m_Terrains[0]); + ShowAtlasGUI(m_Terrains[0].GetInstanceID()); + ShowRealtimeLMGUI(m_Terrains[0]); m_SerializedObject.ApplyModifiedProperties(); } @@ -413,44 +409,29 @@ void ShowAtlasGUI(int instanceID) if (m_CachedBakedTexture.texture == null) return; - EditorGUI.indentLevel += 1; + m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, Styles.Atlas, true); - GUILayout.BeginHorizontal(); - GUILayout.Space(30); - - Rect rect = GUILayoutUtility.GetRect(100, 100, EditorStyles.objectField); + if (!m_ShowBakedLM) + return; - EditorGUI.Toggle(rect, false, EditorStyles.objectFieldThumb); + EditorGUI.indentLevel += 1; - if (rect.Contains(Event.current.mousePosition)) - { - Object actualTargetObject = m_CachedBakedTexture.texture; - Component com = actualTargetObject as Component; + GUILayout.BeginHorizontal(); - if (com) - actualTargetObject = com.gameObject; + DrawLightmapPreview(m_CachedBakedTexture.texture, false, instanceID); - if (Event.current.clickCount == 2) - LightmapPreviewWindow.CreateLightmapPreviewWindow(m_Renderers[0].GetInstanceID(), false, false); - else if (Event.current.clickCount == 1) - EditorGUI.PingObjectOrShowPreviewOnClick(actualTargetObject, GUILayoutUtility.GetLastRect()); - } + GUILayout.BeginVertical(); - if (Event.current.type == EventType.Repaint) - { - rect = EditorStyles.objectFieldThumb.padding.Remove(rect); - EditorGUI.DrawPreviewTexture(rect, m_CachedBakedTexture.texture); - } + GUILayout.Label(Styles.AtlasIndex.text + ": " + m_LightmapIndex.intValue.ToString()); + GUILayout.Label(Styles.AtlasTilingX.text + ": " + m_LightmapTilingOffsetX.floatValue.ToString()); + GUILayout.Label(Styles.AtlasTilingY.text + ": " + m_LightmapTilingOffsetY.floatValue.ToString()); + GUILayout.Label(Styles.AtlasOffsetX.text + ": " + m_LightmapTilingOffsetZ.floatValue.ToString()); + GUILayout.Label(Styles.AtlasOffsetY.text + ": " + m_LightmapTilingOffsetW.floatValue.ToString()); + GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); - EditorGUILayout.LabelField(Styles.AtlasIndex, GUIContent.Temp(m_LightmapIndex.intValue.ToString())); - EditorGUILayout.LabelField(Styles.AtlasTilingX, GUIContent.Temp(m_LightmapTilingOffsetX.floatValue.ToString())); - EditorGUILayout.LabelField(Styles.AtlasTilingY, GUIContent.Temp(m_LightmapTilingOffsetY.floatValue.ToString())); - EditorGUILayout.LabelField(Styles.AtlasOffsetX, GUIContent.Temp(m_LightmapTilingOffsetZ.floatValue.ToString())); - EditorGUILayout.LabelField(Styles.AtlasOffsetY, GUIContent.Temp(m_LightmapTilingOffsetW.floatValue.ToString())); - bool showProgressiveInfo = isPrefabAsset || (m_EnabledBakedGI.boolValue && LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.Enlighten); if (showProgressiveInfo && Unsupported.IsDeveloperMode()) @@ -467,19 +448,32 @@ void ShowAtlasGUI(int instanceID) LightmapEditorSettings.GetPVRAtlasInstanceOffset(instanceID, out atlasInstanceOffset); EditorGUILayout.LabelField(Styles.PVRAtlasInstanceOffset, GUIContent.Temp(atlasInstanceOffset.ToString())); } - EditorGUI.indentLevel -= 1; + + GUILayout.Space(5); } void ShowRealtimeLMGUI(Terrain terrain) { + Hash128 inputSystemHash; + if (terrain == null || !LightmapEditorSettings.GetInputSystemHash(terrain.GetInstanceID(), out inputSystemHash) || inputSystemHash == new Hash128()) + return; // early return since we don't have any lightmaps for it + + if (!UpdateRealtimeTexture(inputSystemHash, terrain.GetInstanceID())) + return; + + m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, Styles.RealtimeLM, true); + + if (!m_ShowRealtimeLM) + return; + EditorGUI.indentLevel += 1; - Hash128 inputSystemHash; - if (terrain != null && LightmapEditorSettings.GetInputSystemHash(terrain.GetInstanceID(), out inputSystemHash)) - { - ShowRealtimeLightmapPreview(inputSystemHash); - } + GUILayout.BeginHorizontal(); + + DrawLightmapPreview(m_CachedRealtimeTexture.texture, true, terrain.GetInstanceID()); + + GUILayout.BeginVertical(); // Resolution of the system. int width, height; @@ -489,34 +483,56 @@ void ShowRealtimeLMGUI(Terrain terrain) var str = width.ToString() + "x" + height.ToString(); if (numChunksInX > 1 || numChunksInY > 1) str += string.Format(" ({0}x{1} chunks)", numChunksInX, numChunksInY); - EditorGUILayout.LabelField(Styles.RealtimeLMResolution, GUIContent.Temp(str)); + GUILayout.Label(Styles.RealtimeLMResolution.text + ": " + str); } + GUILayout.EndVertical(); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + EditorGUI.indentLevel -= 1; + + GUILayout.Space(5); } void ShowRealtimeLMGUI(Renderer renderer) { + Hash128 inputSystemHash; + if (renderer == null || !LightmapEditorSettings.GetInputSystemHash(renderer.GetInstanceID(), out inputSystemHash) || inputSystemHash == new Hash128()) + return; // early return since we don't have any lightmaps for it + + if (!UpdateRealtimeTexture(inputSystemHash, renderer.GetInstanceID())) + return; + + m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, Styles.RealtimeLM, true); + + if (!m_ShowRealtimeLM) + return; + EditorGUI.indentLevel += 1; - Hash128 inputSystemHash = new Hash128(); - if (renderer != null && LightmapEditorSettings.GetInputSystemHash(renderer.GetInstanceID(), out inputSystemHash)) - { - ShowRealtimeLightmapPreview(inputSystemHash); - } + GUILayout.BeginHorizontal(); + + DrawLightmapPreview(m_CachedRealtimeTexture.texture, true, renderer.GetInstanceID()); + + GUILayout.BeginVertical(); int instWidth, instHeight; if (LightmapEditorSettings.GetInstanceResolution(renderer, out instWidth, out instHeight)) { - EditorGUILayout.LabelField(Styles.RealtimeLMInstanceResolution, GUIContent.Temp(instWidth.ToString() + "x" + instHeight.ToString())); + GUILayout.Label(Styles.RealtimeLMInstanceResolution.text + ": " + instWidth.ToString() + "x" + instHeight.ToString()); } int width, height; if (LightmapEditorSettings.GetSystemResolution(renderer, out width, out height)) { - EditorGUILayout.LabelField(Styles.RealtimeLMResolution, GUIContent.Temp(width.ToString() + "x" + height.ToString())); + GUILayout.Label(Styles.RealtimeLMResolution.text + ": " + width.ToString() + "x" + height.ToString()); } + GUILayout.EndVertical(); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + if (Unsupported.IsDeveloperMode()) { Hash128 instanceHash; @@ -535,12 +551,14 @@ void ShowRealtimeLMGUI(Renderer renderer) } EditorGUI.indentLevel -= 1; + + GUILayout.Space(5); } - void ShowRealtimeLightmapPreview(Hash128 inputSystemHash) + bool UpdateRealtimeTexture(Hash128 inputSystemHash, int instanceId) { if (inputSystemHash == new Hash128()) - return; + return false; Hash128 contentHash = LightmapVisualizationUtility.GetRealtimeGITextureHash(inputSystemHash, GITextureType.Irradiance); @@ -549,35 +567,51 @@ void ShowRealtimeLightmapPreview(Hash128 inputSystemHash) m_CachedRealtimeTexture = LightmapVisualizationUtility.GetRealtimeGITexture(inputSystemHash, GITextureType.Irradiance); if (m_CachedRealtimeTexture.texture == null) - return; + return false; - GUILayout.BeginHorizontal(); - GUILayout.Space(30); + return true; + } - Rect rect = GUILayoutUtility.GetRect(100, 100, EditorStyles.objectField); + private void DrawLightmapPreview(Texture2D texture, bool realtimeLightmap, int instanceId) + { + GUILayout.Space(Styles.PreviewPadding); - EditorGUI.Toggle(rect, false, EditorStyles.objectFieldThumb); + int previewWidth = Styles.PreviewWidth - 4; // padding - if (rect.Contains(Event.current.mousePosition)) + Rect rect = GUILayoutUtility.GetRect(previewWidth, previewWidth, EditorStyles.objectField); + Rect buttonRect = new Rect(rect.xMax - 70, rect.yMax - 14, 70, 14); + + if (Event.current.type == EventType.MouseDown) { - Object actualTargetObject = m_CachedRealtimeTexture.texture; - Component com = actualTargetObject as Component; + if ((buttonRect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1) || + (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 2)) + { + LightmapPreviewWindow.CreateLightmapPreviewWindow(instanceId, realtimeLightmap, false); + } + else if (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1) + { + Object actualTargetObject = texture; + Component com = actualTargetObject as Component; - if (com) - actualTargetObject = com.gameObject; + if (com) + actualTargetObject = com.gameObject; - if (Event.current.clickCount == 2) - LightmapPreviewWindow.CreateLightmapPreviewWindow(m_Renderers[0].GetInstanceID(), true, false); + EditorGUI.PingObjectOrShowPreviewOnClick(actualTargetObject, rect); + } } + EditorGUI.Toggle(rect, false, EditorStyles.objectFieldThumb); + if (Event.current.type == EventType.Repaint) { rect = EditorStyles.objectFieldThumb.padding.Remove(rect); - EditorGUI.DrawPreviewTexture(rect, m_CachedRealtimeTexture.texture); + EditorGUI.DrawPreviewTexture(rect, texture); + + Styles.OpenPreviewStyle.Draw(rect, Styles.OpenPreview, false, false, false, false); } - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); + float spacing = Mathf.Max(5.0f, EditorGUIUtility.labelWidth - Styles.PreviewPadding - Styles.PreviewWidth); + GUILayout.Space(spacing); } static bool HasNormals(Renderer renderer) diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 7d97663c9a..6b8786ffff 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -142,9 +142,9 @@ class SettingsContent 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."); public static readonly GUIContent useOnDemandResources = EditorGUIUtility.TrTextContent("Use on demand resources*"); public static readonly GUIContent accelerometerFrequency = EditorGUIUtility.TrTextContent("Accelerometer Frequency*"); - public static readonly GUIContent cameraUsageDescription = EditorGUIUtility.TrTextContent("Camera Usage Description*"); - public static readonly GUIContent locationUsageDescription = EditorGUIUtility.TrTextContent("Location Usage Description*"); - public static readonly GUIContent microphoneUsageDescription = EditorGUIUtility.TrTextContent("Microphone Usage Description*"); + 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"); + 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."); + 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"); public static readonly GUIContent muteOtherAudioSources = EditorGUIUtility.TrTextContent("Mute Other Audio Sources*"); public static readonly GUIContent prepareIOSForRecording = EditorGUIUtility.TrTextContent("Prepare iOS for Recording"); public static readonly GUIContent forceIOSSpeakersWhenRecording = EditorGUIUtility.TrTextContent("Force iOS Speakers when Recording"); diff --git a/Editor/Mono/Inspector/PreviewRenderUtility.cs b/Editor/Mono/Inspector/PreviewRenderUtility.cs index 783603be1a..0417154154 100644 --- a/Editor/Mono/Inspector/PreviewRenderUtility.cs +++ b/Editor/Mono/Inspector/PreviewRenderUtility.cs @@ -229,7 +229,7 @@ public void BeginPreview(Rect r, GUIStyle previewBackground) new Rect(0, 0, 1, 1), previewBackground.border.left, previewBackground.border.right, previewBackground.border.top, previewBackground.border.bottom, - new Color(.5f, .5f, .5f, 1), + new Color(.5f, .5f, .5f, 0.5f), null ); diff --git a/Editor/Mono/Inspector/QualitySettingsEditor.cs b/Editor/Mono/Inspector/QualitySettingsEditor.cs index d079c972d7..495fd0a4a9 100644 --- a/Editor/Mono/Inspector/QualitySettingsEditor.cs +++ b/Editor/Mono/Inspector/QualitySettingsEditor.cs @@ -503,6 +503,7 @@ public override void OnInspectorGUI() var particleRaycastBudgetProperty = currentSettings.FindPropertyRelative("particleRaycastBudget"); var asyncUploadTimeSliceProperty = currentSettings.FindPropertyRelative("asyncUploadTimeSlice"); var asyncUploadBufferSizeProperty = currentSettings.FindPropertyRelative("asyncUploadBufferSize"); + var asyncUploadPersistentBufferProperty = currentSettings.FindPropertyRelative("asyncUploadPersistentBuffer"); var resolutionScalingFixedDPIFactorProperty = currentSettings.FindPropertyRelative("resolutionScalingFixedDPIFactor"); bool usingSRP = GraphicsSettings.renderPipelineAsset != null; @@ -586,6 +587,7 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(particleRaycastBudgetProperty); EditorGUILayout.PropertyField(asyncUploadTimeSliceProperty); EditorGUILayout.PropertyField(asyncUploadBufferSizeProperty); + EditorGUILayout.PropertyField(asyncUploadPersistentBufferProperty); asyncUploadTimeSliceProperty.intValue = Mathf.Clamp(asyncUploadTimeSliceProperty.intValue, kMinAsyncUploadTimeSlice, kMaxAsyncUploadTimeSlice); asyncUploadBufferSizeProperty.intValue = Mathf.Clamp(asyncUploadBufferSizeProperty.intValue, kMinAsyncRingBufferSize, kMaxAsyncRingBufferSize); diff --git a/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs b/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs index 656b97c002..760f41840b 100644 --- a/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs +++ b/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs @@ -54,20 +54,18 @@ private static class Styles public static GUIContent colorMode = EditorGUIUtility.TrTextContent("Color Mode", "Determines the blending mode between the particle color and the texture albedo."); public static GUIContent[] colorNames = Array.ConvertAll(Enum.GetNames(typeof(ColorMode)), item => new GUIContent(item)); - public static GUIContent flipbookMode = EditorGUIUtility.TrTextContent("Flip-Book Mode", "Determines the blending mode used for animated texture sheets."); - public static GUIContent[] flipbookNames = Array.ConvertAll(Enum.GetNames(typeof(FlipbookMode)), item => new GUIContent(item)); - + public static GUIContent flipbookBlending = EditorGUIUtility.TrTextContent("Flip-Book Frame Blending", "Enables blending between the frames of animated texture sheets."); public static GUIContent twoSidedEnabled = EditorGUIUtility.TrTextContent("Two Sided", "Render both front and back faces of the particle geometry."); - public static GUIContent distortionEnabled = EditorGUIUtility.TrTextContent("Enable Distortion", "Use a grab pass and normal map to simulate refraction."); + public static GUIContent distortionEnabled = EditorGUIUtility.TrTextContent("Distortion", "Use a grab pass and normal map to simulate refraction."); public static GUIContent distortionStrengthText = EditorGUIUtility.TrTextContent("Strength", "Distortion Strength."); public static GUIContent distortionBlendText = EditorGUIUtility.TrTextContent("Blend", "Weighting between albedo and grab pass."); - public static GUIContent softParticlesEnabled = EditorGUIUtility.TrTextContent("Enable Soft Particles", "Fade out particle geometry when it gets close to the surface of objects written into the depth buffer."); + 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."); public static GUIContent softParticlesNearFadeDistanceText = EditorGUIUtility.TrTextContent("Near fade", "Soft Particles near fade distance."); public static GUIContent softParticlesFarFadeDistanceText = EditorGUIUtility.TrTextContent("Far fade", "Soft Particles far fade distance."); - public static GUIContent cameraFadingEnabled = EditorGUIUtility.TrTextContent("Enable Camera Fading", "Fade out particle geometry when it gets close to the camera."); + public static GUIContent cameraFadingEnabled = EditorGUIUtility.TrTextContent("Camera Fading", "Fade out particle geometry when it gets close to the camera."); public static GUIContent cameraNearFadeDistanceText = EditorGUIUtility.TrTextContent("Near fade", "Camera near fade distance."); public static GUIContent cameraFarFadeDistanceText = EditorGUIUtility.TrTextContent("Far fade", "Camera far fade distance."); @@ -184,7 +182,7 @@ public void ShaderPropertiesGUI(Material material) EditorGUILayout.Space(); GUILayout.Label(Styles.mainOptionsText, EditorStyles.boldLabel); - FlipbookModePopup(); + FlipbookBlendingPopup(); TwoSidedPopup(material); FadingPopup(material); DistortionPopup(material); @@ -296,17 +294,17 @@ void ColorModePopup() } } - void FlipbookModePopup() + void FlipbookBlendingPopup() { EditorGUI.showMixedValue = flipbookMode.hasMixedValue; - var mode = (FlipbookMode)flipbookMode.floatValue; + var enabled = (flipbookMode.floatValue == (float)FlipbookMode.Blended); EditorGUI.BeginChangeCheck(); - mode = (FlipbookMode)EditorGUILayout.Popup(Styles.flipbookMode, (int)mode, Styles.flipbookNames); + enabled = EditorGUILayout.Toggle(Styles.flipbookBlending, enabled); if (EditorGUI.EndChangeCheck()) { m_MaterialEditor.RegisterPropertyChangeUndo("Flip-Book Mode"); - flipbookMode.floatValue = (float)mode; + flipbookMode.floatValue = enabled ? (float)FlipbookMode.Blended : (float)FlipbookMode.Simple; } EditorGUI.showMixedValue = false; diff --git a/Editor/Mono/Menu.bindings.cs b/Editor/Mono/Menu.bindings.cs index cf50afc6d6..c8cbee328f 100644 --- a/Editor/Mono/Menu.bindings.cs +++ b/Editor/Mono/Menu.bindings.cs @@ -16,8 +16,8 @@ public sealed class Menu [NativeMethod("MenuController::GetChecked", true)] public static extern bool GetChecked(string menuPath); - [FreeFunction("MenuController::GetMenuItemShortcuts")] - internal static extern void GetMenuItemShortcuts(List outItemNames, List outItemShortcuts); + [FreeFunction("MenuController::GetMenuItemDefaultShortcuts")] + internal static extern void GetMenuItemDefaultShortcuts(List outItemNames, List outItemDefaultShortcuts); [FreeFunction("MenuController::SetMenuItemHotkey")] internal static extern void SetHotkey(string menuPath, string hotkey); diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs index ff4c3926cd..35f83e7f67 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs @@ -274,12 +274,15 @@ override public void OnInspectorGUI(InitialModuleUI initial) { if (renderMode != RenderMode.Mesh) GUIFloat(s_Texts.normalDirection, m_NormalDirection); - - if (m_Material != null) // The renderer's material list could be empty - GUIObject(s_Texts.material, m_Material); } } + if (renderMode != RenderMode.None) + { + if (m_Material != null) // The renderer's material list could be empty + GUIObject(s_Texts.material, m_Material); + } + if (m_TrailMaterial != null) // The renderer's material list could be empty GUIObject(s_Texts.trailMaterial, m_TrailMaterial); diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs index d0db6cc3c1..bdb29270c0 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs @@ -28,6 +28,7 @@ class Texts public 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."); public GUIContent ribbonCount = EditorGUIUtility.TrTextContent("Ribbon Count", "Select how many ribbons to render throughout the Particle System."); public GUIContent splitSubEmitterRibbons = EditorGUIUtility.TrTextContent("Split Sub Emitter Ribbons", "When used on a sub emitter, ribbons will connect particles from each parent particle independently."); + public GUIContent attachRibbonsToTransform = EditorGUIUtility.TrTextContent("Attach Ribbons to Transform", "Connect each ribbon to the position of the Transform Component."); public GUIContent[] trailModeOptions = { @@ -62,6 +63,7 @@ class Texts SerializedProperty m_ShadowBias; SerializedProperty m_RibbonCount; SerializedProperty m_SplitSubEmitterRibbons; + SerializedProperty m_AttachRibbonsToTransform; public TrailModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) : base(owner, o, "TrailModule", displayName) @@ -94,6 +96,7 @@ protected override void Init() m_ShadowBias = GetProperty("shadowBias"); m_RibbonCount = GetProperty("ribbonCount"); m_SplitSubEmitterRibbons = GetProperty("splitSubEmitterRibbons"); + m_AttachRibbonsToTransform = GetProperty("attachRibbonsToTransform"); } override public void OnInspectorGUI(InitialModuleUI initial) @@ -113,6 +116,7 @@ override public void OnInspectorGUI(InitialModuleUI initial) { GUIInt(s_Texts.ribbonCount, m_RibbonCount); GUIToggle(s_Texts.splitSubEmitterRibbons, m_SplitSubEmitterRibbons); + GUIToggle(s_Texts.attachRibbonsToTransform, m_AttachRibbonsToTransform); } } diff --git a/Editor/Mono/PerformanceTools/FrameDebugger.cs b/Editor/Mono/PerformanceTools/FrameDebugger.cs index e7501eb423..2cca28353c 100644 --- a/Editor/Mono/PerformanceTools/FrameDebugger.cs +++ b/Editor/Mono/PerformanceTools/FrameDebugger.cs @@ -127,7 +127,7 @@ internal struct FrameDebuggerEventData public int subShaderIndex; public int shaderPassIndex; public string shaderKeywords; - public int rendererInstanceID; + public int componentInstanceID; public Mesh mesh; public int meshInstanceID; public int meshSubset; diff --git a/Editor/Mono/PlayerSettings.bindings.cs b/Editor/Mono/PlayerSettings.bindings.cs index 9f9d15dda8..fb1edb4611 100644 --- a/Editor/Mono/PlayerSettings.bindings.cs +++ b/Editor/Mono/PlayerSettings.bindings.cs @@ -1098,5 +1098,11 @@ public static extern bool enableMetalAPIValidation [StaticAccessor("GetPlayerSettings().GetEditorOnly()")] internal static extern bool RelaunchProjectIfScriptRuntimeVersionHasChanged(); + + [StaticAccessor("GetPlayerSettings()")] + public static extern bool GetWsaHolographicRemotingEnabled(); + + [StaticAccessor("GetPlayerSettings()")] + public static extern void SetWsaHolographicRemotingEnabled(bool enabled); } } diff --git a/Editor/Mono/PlayerSettingsAndroid.bindings.cs b/Editor/Mono/PlayerSettingsAndroid.bindings.cs index dc0c0acbec..6685deca5b 100644 --- a/Editor/Mono/PlayerSettingsAndroid.bindings.cs +++ b/Editor/Mono/PlayerSettingsAndroid.bindings.cs @@ -67,6 +67,9 @@ public enum AndroidSdkVersions // Android 8.1, "Oreo", API level 27 AndroidApiLevel27 = 27, + + // Android 9.0, "Pie", API level 28 + AndroidApiLevel28 = 28, } // Preferred application install location diff --git a/Editor/Mono/PlayerSettingsSwitch.bindings.cs b/Editor/Mono/PlayerSettingsSwitch.bindings.cs index f435d72098..076266ecd8 100644 --- a/Editor/Mono/PlayerSettingsSwitch.bindings.cs +++ b/Editor/Mono/PlayerSettingsSwitch.bindings.cs @@ -49,7 +49,8 @@ public enum Languages Korean, } - public enum StartupUserAccount + public enum + StartupUserAccount { None = 0, Required = 1, @@ -367,6 +368,9 @@ extern public static string[] localCommunicationIds [NativeProperty("switchDataLossConfirmation", TargetType.Field)] extern public static bool isDataLossConfirmationEnabled { get; set; } + [NativeProperty("switchUserAccountLockEnabled", TargetType.Field)] + extern public static bool isUserAccountLockEnabled { get; set; } + [Obsolete("isDataLossConfirmation was renamed to isDataLossConfirmationEnabled")] [NativeProperty("switchDataLossConfirmation", TargetType.Field)] extern public static bool isDataLossConfirmation { get; set; } diff --git a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs index b99d96e3a3..a17eef3271 100644 --- a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs +++ b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs @@ -37,6 +37,12 @@ internal static class Constants internal class Styles { public static readonly GUIContent browse = EditorGUIUtility.TrTextContent("Browse..."); + public static readonly GUIStyle clearBindingButton = new GUIStyle(GUI.skin.button); + + static Styles() + { + clearBindingButton.margin.top = 0; + } } internal class GeneralProperties @@ -711,6 +717,9 @@ private void ShowShortcutConfiguration(int controlID, ShortcutEntry selectedShor { GUILayout.Label("Key:"); e = EditorGUILayout.KeyEventField(e); + + if (GUILayout.Button("Clear", Styles.clearBindingButton)) + e.keyCode = KeyCode.None; } using (new GUILayout.HorizontalScope()) @@ -732,7 +741,9 @@ private void ShowShortcutConfiguration(int controlID, ShortcutEntry selectedShor if (m_ValidKeyChange) { // TODO: Don't clobber secondary+ combinations - var newCombination = new List { new KeyCombination(e) }; + var newCombination = new List(); + if (e.keyCode != KeyCode.None) + newCombination.Add(new KeyCombination(e)); shortcutController.profileManager.ModifyShortcutEntry(selectedShortcut.identifier, newCombination); shortcutController.profileManager.PersistChanges(); } diff --git a/Editor/Mono/SceneHierarchy.cs b/Editor/Mono/SceneHierarchy.cs index 1f5e4ed5a8..3534c68484 100644 --- a/Editor/Mono/SceneHierarchy.cs +++ b/Editor/Mono/SceneHierarchy.cs @@ -493,8 +493,6 @@ public virtual void OnEnable() if (m_TreeViewKeyboardControlID == 0) m_TreeViewKeyboardControlID = EditorGUIUtility.GetPermanentControlID(); - - DoPingRequest(); } public virtual void OnDisable() diff --git a/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs b/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs index c07d539564..c80cb9ee41 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs @@ -31,10 +31,13 @@ internal class LightingWindowLightmapPreviewTab SerializedProperty m_LightingDataAsset; SerializedProperty m_TextureCompression; - class Styles + static class Styles { public static readonly GUIStyle SelectedLightmapHighlight = "LightmapEditorSelectedHighlight"; 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."); + public static readonly GUIContent OpenPreview = EditorGUIUtility.TrTextContent("Open Preview"); + + public static readonly GUIStyle OpenPreviewStyle = EditorStyles.objectFieldThumb.name + "LightmapPreviewOverlay"; } public LightingWindowLightmapPreviewTab(LightmapType type) @@ -171,28 +174,27 @@ private void LightmapListGUI(LightmapData[] lightmaps, VisualisationGITexture[] private void LightmapField(Texture2D lightmap, int index, Hash128 hash) { Rect rect = GUILayoutUtility.GetRect(100, 100, EditorStyles.objectField); + Rect buttonRect = new Rect(rect.xMax - 70, rect.yMax - 14, 70, 14); if (EditorGUI.Toggle(rect, index == m_SelectedLightmapIndex, EditorStyles.objectFieldThumb)) { m_SelectedLightmapIndex = index; - if (rect.Contains(Event.current.mousePosition)) + if ((buttonRect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1) || + (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 2)) + { + if (isRealtimeLightmap) + LightmapPreviewWindow.CreateLightmapPreviewWindow(m_SelectedLightmapIndex, true, true); + else + LightmapPreviewWindow.CreateLightmapPreviewWindow(m_SelectedLightmapIndex, false, true); + } + else if (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1) { Object actualTargetObject = lightmap; Component com = actualTargetObject as Component; if (com) actualTargetObject = com.gameObject; - - if (Event.current.clickCount == 1) - EditorGUI.PingObjectOrShowPreviewOnClick(actualTargetObject, GUILayoutUtility.GetLastRect()); - - if (Event.current.clickCount == 2) - { - if (isRealtimeLightmap) - LightmapPreviewWindow.CreateLightmapPreviewWindow(m_SelectedLightmapIndex, true, true); - else - LightmapPreviewWindow.CreateLightmapPreviewWindow(m_SelectedLightmapIndex, false, true); - } + EditorGUI.PingObjectOrShowPreviewOnClick(actualTargetObject, GUILayoutUtility.GetLastRect()); } } @@ -201,6 +203,8 @@ private void LightmapField(Texture2D lightmap, int index, Hash128 hash) rect = EditorStyles.objectFieldThumb.padding.Remove(rect); EditorGUI.DrawPreviewTexture(rect, lightmap); + Styles.OpenPreviewStyle.Draw(rect, Styles.OpenPreview, false, false, false, false); + if ((!isRealtimeLightmap && index == m_ActiveGameObjectLightmapIndex) || (isRealtimeLightmap && hash == m_ActiveGameObjectTextureHash)) { Styles.SelectedLightmapHighlight.Draw(rect, false, false, false, false); diff --git a/Editor/Mono/SceneModeWindows/LightmapPreviewWindow.cs b/Editor/Mono/SceneModeWindows/LightmapPreviewWindow.cs index 79645fd7f9..1bc8fb7a3a 100644 --- a/Editor/Mono/SceneModeWindows/LightmapPreviewWindow.cs +++ b/Editor/Mono/SceneModeWindows/LightmapPreviewWindow.cs @@ -37,7 +37,9 @@ internal class LightmapPreviewWindow : EditorWindow Hash128 m_RealtimeTextureHash = new Hash128(); VisualisationGITexture m_CachedTexture; GameObject[] m_CachedTextureObjects; + int m_ActiveGameObjectLightmapIndex = -1; // the object the user selects in the scene + int m_ActiveGameObjectInstanceId = -1; // for instance based non-atlas textures such as baked emissive for Progressive Hash128 m_ActiveGameObjectTextureHash = new Hash128(); // the object the user selects in the scene private float m_ExposureSliderMax = 10f; @@ -93,19 +95,18 @@ static class Styles public static readonly GUIContent TextureNotAvailableRealtime = EditorGUIUtility.TrTextContent("The texture is not available at the moment."); public static readonly GUIContent TextureNotAvailableBaked = EditorGUIUtility.TrTextContent("The texture is not available at the moment.\nPlease try to rebake the current scene or turn on Auto, and make sure that this object is set to Lightmap Static if it's meant to be baked."); 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 Lightmap Static."); + public static readonly GUIContent TextureNotAvailableBakedAlbedoEmissive = EditorGUIUtility.TrTextContent("The texture is not an index based texture and is not available when using Progressive.\nPlease go to the instance you wish to debug, and select the lightmap on the Mesh Renderer."); public static readonly GUIContent TextureLoading = EditorGUIUtility.TrTextContent("Loading..."); public static readonly GUIContent ExposureIcon = EditorGUIUtility.TrIconContent("SceneViewLighting", "Controls the number of stops to over or under expose the lightmap."); } public int lightmapIndex { - get { return m_LightmapIndex; } set { m_LightmapIndex = value; } } public int instanceID { - get { return m_InstanceID; } set { m_InstanceID = value; } } @@ -115,17 +116,24 @@ public bool isRealtimeLightmap set { m_IsRealtimeLightmap = value; } } + // 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) private bool isIndexBased { - get { return m_LightmapIndex != -1; } + get { return m_InstanceID == -1; } } private string lightmapTitle { get { - return isIndexBased ? ((isRealtimeLightmap ? "Realtime Lightmap Index " : "Lightmap Index ") + lightmapIndex) : - (isRealtimeLightmap ? "Realtime Lightmap" : "Lightmap"); + if (isIndexBased) return ((isRealtimeLightmap ? "Realtime Lightmap Index " : "Lightmap Index ") + m_LightmapIndex); + + var obj = EditorUtility.InstanceIDToObject(m_InstanceID); + + if (obj) + return (isRealtimeLightmap ? "Realtime" : "") + " Lightmap for '" + obj.name + "'"; + + return (isRealtimeLightmap ? "Realtime" : "") + " Lightmap"; } } @@ -199,6 +207,7 @@ private void UpdateActiveGameObjectSelection() (terrain = Selection.activeGameObject.GetComponent()) == null)) { m_ActiveGameObjectLightmapIndex = -1; + m_ActiveGameObjectInstanceId = -1; m_ActiveGameObjectTextureHash = new Hash128(); return; } @@ -214,7 +223,10 @@ private void UpdateActiveGameObjectSelection() m_ActiveGameObjectTextureHash = new Hash128(); } else + { m_ActiveGameObjectLightmapIndex = renderer != null ? renderer.lightmapIndex : terrain.lightmapIndex; + m_ActiveGameObjectInstanceId = renderer != null ? renderer.GetInstanceID() : terrain.GetInstanceID(); + } } private void PreviewSettings() @@ -297,9 +309,11 @@ private void DrawPreview(Rect r) if (m_CachedTexture.textureAvailability == GITextureAvailability.GITextureNotAvailable || m_CachedTexture.textureAvailability == GITextureAvailability.GITextureUnknown) { - if (LightmapVisualizationUtility.IsBakedTextureType(textureType)) + if (!isRealtimeLightmap) { - if (textureType == GITextureType.BakedShadowMask) + if (!LightmapVisualizationUtility.IsAtlasTextureType(textureType) && isIndexBased) + GUI.Label(drawableArea, Styles.TextureNotAvailableBakedAlbedoEmissive, Styles.PreviewLabel); + else if (textureType == GITextureType.BakedShadowMask) GUI.Label(drawableArea, Styles.TextureNotAvailableBakedShadowmask, Styles.PreviewLabel); else GUI.Label(drawableArea, Styles.TextureNotAvailableBaked, Styles.PreviewLabel); @@ -324,8 +338,12 @@ private void DrawPreview(Rect r) case EventType.ValidateCommand: case EventType.ExecuteCommand: - if (Event.current.commandName == EventCommandNames.FrameSelected && (isRealtimeLightmap ? m_RealtimeTextureHash == m_ActiveGameObjectTextureHash : m_LightmapIndex == m_ActiveGameObjectLightmapIndex)) + if (Event.current.commandName == EventCommandNames.FrameSelected && IsSelectedObjectInLightmap(textureType)) { + // There are instance based baked textures where we don't get any STs and can't do the framing + if (!isRealtimeLightmap && !LightmapVisualizationUtility.IsAtlasTextureType(textureType)) + break; + Vector4 lightmapTilingOffset = LightmapVisualizationUtility.GetLightmapTilingOffset(lightmapType); Vector2 min = new Vector2(lightmapTilingOffset.z, lightmapTilingOffset.w); @@ -349,7 +367,7 @@ private void DrawPreview(Rect r) Rect rect = new Rect(min.x, min.y, max.x - min.x, max.y - min.y); rect.width = rect.height = Mathf.Max(rect.width, rect.height); rect.x -= (offsetX * min.x); - rect.y += (offsetY * (1 - max.y)); + rect.y += (offsetY * (1 - max.y)); m_ZoomablePreview.shownArea = rect; Event.current.Use(); @@ -377,7 +395,7 @@ private void DrawPreview(Rect r) texture.filterMode = FilterMode.Point; LightmapVisualizationUtility.DrawTextureWithUVOverlay(texture, - (m_ShowUVOverlay && (isRealtimeLightmap ? m_RealtimeTextureHash == m_ActiveGameObjectTextureHash : m_LightmapIndex == m_ActiveGameObjectLightmapIndex)) ? Selection.activeGameObject : null, + (m_ShowUVOverlay && IsSelectedObjectInLightmap(textureType)) ? Selection.activeGameObject : null, m_ShowUVOverlay ? m_CachedTextureObjects : new GameObject[] {}, drawableArea, textureRect, textureType, exposure); texture.filterMode = prevMode; } @@ -395,6 +413,17 @@ private void SelectPreviewTextureIndex(object textureOption) m_SelectedPreviewTextureOptionIndex = Array.IndexOf(options, textureOption); } + private bool IsSelectedObjectInLightmap(GITextureType textureType) + { + if (isRealtimeLightmap) + return (m_ActiveGameObjectTextureHash == m_RealtimeTextureHash); + + if (LightmapVisualizationUtility.IsAtlasTextureType(textureType)) + return (m_ActiveGameObjectLightmapIndex == m_LightmapIndex); + + return (m_ActiveGameObjectInstanceId == m_InstanceID); + } + private GITextureType GetSelectedTextureType() { GUIContent[] options = isRealtimeLightmap ? Styles.RealtimePreviewTextureOptions : Styles.BakedPreviewTextureOptions; @@ -437,7 +466,7 @@ private void UpdateCachedTexture(GITextureType textureType) { Hash128 systemHash; - if (!LightmapEditorSettings.GetInputSystemHash(instanceID, out systemHash)) + if (!LightmapEditorSettings.GetInputSystemHash(m_InstanceID, out systemHash)) return; m_RealtimeTextureHash = systemHash; @@ -446,7 +475,7 @@ private void UpdateCachedTexture(GITextureType textureType) { int lightmapIndex; - if (!LightmapEditorSettings.GetLightmapIndex(instanceID, out lightmapIndex)) + if (!LightmapEditorSettings.GetLightmapIndex(m_InstanceID, out lightmapIndex)) return; m_LightmapIndex = lightmapIndex; @@ -454,14 +483,14 @@ private void UpdateCachedTexture(GITextureType textureType) } Hash128 contentHash = isRealtimeLightmap ? LightmapVisualizationUtility.GetRealtimeGITextureHash(m_RealtimeTextureHash, textureType) : - LightmapVisualizationUtility.GetBakedGITextureHash(m_LightmapIndex, 0, textureType); + LightmapVisualizationUtility.GetBakedGITextureHash(m_LightmapIndex, m_InstanceID, textureType); // if we need to fetch a new texture if (m_CachedTexture.texture == null || m_CachedTexture.type != textureType || m_CachedTexture.contentHash != contentHash || m_CachedTexture.contentHash == new Hash128()) { m_CachedTexture = isRealtimeLightmap ? LightmapVisualizationUtility.GetRealtimeGITexture(m_RealtimeTextureHash, textureType) : - LightmapVisualizationUtility.GetBakedGITexture(m_LightmapIndex, 0, textureType); + LightmapVisualizationUtility.GetBakedGITexture(m_LightmapIndex, m_InstanceID, textureType); } if (!m_ShowUVOverlay) @@ -474,8 +503,10 @@ private void UpdateCachedTexture(GITextureType textureType) if (isRealtimeLightmap) m_CachedTextureObjects = LightmapVisualizationUtility.GetRealtimeGITextureRenderers(m_RealtimeTextureHash); - else + else if (LightmapVisualizationUtility.IsAtlasTextureType(textureType)) m_CachedTextureObjects = LightmapVisualizationUtility.GetBakedGITextureRenderers(m_LightmapIndex); + else // if it's an instance based baked lightmap, we only have 1 object in it + m_CachedTextureObjects = new GameObject[] {}; } private Rect ResizeRectToFit(Rect rect, Rect to) diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs index 7adc6e7d02..2cf27b4719 100644 --- a/Editor/Mono/SceneView/SceneView.cs +++ b/Editor/Mono/SceneView/SceneView.cs @@ -412,6 +412,9 @@ public float cameraDistance static Shader s_ShowMipsShader; static Shader s_ShowTextureStreamingShader; static Shader s_AuraShader; + static Shader s_BuildFilterShader; + static Material s_FadeMaterial; + static Material s_ApplyFilterMaterial; static Texture2D s_MipColorsTexture; // Handle Dragging of stuff over scene view @@ -1317,31 +1320,7 @@ private void DoDrawCamera(Rect windowSpaceCameraRect, Rect groupSpaceCameraRect, if (UseSceneFiltering()) { if (evt.type == EventType.Repaint) - { - // First pass: Draw objects which do not meet the search filter with grayscale image effect. - Handles.EnableCameraFx(m_Camera, true); - - Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowRest); - - float fade = Mathf.Clamp01((float)(EditorApplication.timeSinceStartup - m_StartSearchFilterTime)); - Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); - Handles.DrawCameraFade(m_Camera, fade); - - // Second pass: Draw aura for objects which do meet search filter, but are occluded. - Handles.EnableCameraFx(m_Camera, false); - Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowFiltered); - if (!s_AuraShader) - s_AuraShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewAura.shader") as Shader; - m_Camera.SetReplacementShader(s_AuraShader, ""); - Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); - - // Third pass: Draw objects which do meet filter normally - m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString); - Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode, gridParam); - - if (fade < 1) - Repaint(); - } + RenderFilteredScene(groupSpaceCameraRect); if (evt.type == EventType.Repaint) RenderTexture.active = null; @@ -1368,6 +1347,73 @@ private void DoDrawCamera(Rect windowSpaceCameraRect, Rect groupSpaceCameraRect, } } + void RenderFilteredScene(Rect groupSpaceCameraRect) + { + var oldTargetTexture = m_Camera.targetTexture; + var oldDepthTextureMode = m_Camera.depthTextureMode; + var oldRenderingPath = m_Camera.renderingPath; + + // First pass: Draw the scene normally in destination render textsure + DoClearCamera(groupSpaceCameraRect); + Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); + + // Second pass: Blit the scene faded out in a different render texture + var fadedDesc = m_SceneTargetTexture.descriptor; + var fadedRT = RenderTexture.GetTemporary(fadedDesc); + fadedRT.name = "FadedRT"; + + float fade = Mathf.Clamp01((float)(EditorApplication.timeSinceStartup - m_StartSearchFilterTime)); + if (!s_FadeMaterial) + s_FadeMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewGrayscaleEffectFade.mat") as Material; + s_FadeMaterial.SetFloat("_Fade", fade); + Graphics.Blit(m_SceneTargetTexture, fadedRT, s_FadeMaterial); + + // Third pass: Draw aura for objects which meet the search filter, but are occluded. + m_Camera.renderingPath = RenderingPath.Forward; + if (!s_AuraShader) + s_AuraShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewAura.shader") as Shader; + m_Camera.SetReplacementShader(s_AuraShader, ""); + m_Camera.SetTargetBuffers(fadedRT.colorBuffer, m_SceneTargetTexture.depthBuffer); + m_Camera.depthTextureMode = DepthTextureMode.None; + Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowFiltered); + Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); + + // Fourth pass: Draw objects which do meet filter in a mask + var maskDesc = m_SceneTargetTexture.descriptor; + maskDesc.colorFormat = RenderTextureFormat.R8; + maskDesc.depthBufferBits = 0; + var maskRT = RenderTexture.GetTemporary(maskDesc); + maskRT.name = "MaskRT"; + + RenderTexture.active = maskRT; + GL.Clear(false, true, Color.clear); + + if (!s_BuildFilterShader) + s_BuildFilterShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewBuildFilter.shader") as Shader; + m_Camera.SetReplacementShader(s_BuildFilterShader, ""); + m_Camera.SetTargetBuffers(maskRT.colorBuffer, m_SceneTargetTexture.depthBuffer); + m_Camera.depthTextureMode = DepthTextureMode.None; + Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); + + // Final pass: Blit the faded scene where the mask isn't set + if (!s_ApplyFilterMaterial) + s_ApplyFilterMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewApplyFilter.mat") as Material; + s_ApplyFilterMaterial.SetTexture("_MaskTex", maskRT); + Graphics.Blit(fadedRT, m_SceneTargetTexture, s_ApplyFilterMaterial); + + RenderTexture.ReleaseTemporary(maskRT); + RenderTexture.ReleaseTemporary(fadedRT); + + // Reset camera + m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString); + m_Camera.renderingPath = oldRenderingPath; + m_Camera.targetTexture = oldTargetTexture; + m_Camera.depthTextureMode = oldDepthTextureMode; + + if (fade < 1) + Repaint(); + } + void SetupPBRValidation() { DrawCameraMode renderMode = m_CameraMode.drawMode; @@ -2222,9 +2268,7 @@ void SetupCamera() if (Event.current.type == EventType.Repaint) { - bool enableImageEffects = false; - if (!UseSceneFiltering()) - enableImageEffects = m_CameraMode.drawMode == DrawCameraMode.Textured && sceneViewState.showImageEffects; + bool enableImageEffects = m_CameraMode.drawMode == DrawCameraMode.Textured && sceneViewState.showImageEffects; UpdateImageEffects(enableImageEffects); } diff --git a/Editor/Mono/Scripting/Compilers/UWPReferences.cs b/Editor/Mono/Scripting/Compilers/UWPReferences.cs index da1105c3a5..d2c2861e13 100644 --- a/Editor/Mono/Scripting/Compilers/UWPReferences.cs +++ b/Editor/Mono/Scripting/Compilers/UWPReferences.cs @@ -31,20 +31,22 @@ internal class UWPSDK { public readonly Version Version; public readonly Version MinVSVersion; + public readonly IEnumerable PreviousSDKs; - public UWPSDK(Version version, Version minVSVersion) + public UWPSDK(Version version, Version minVSVersion, IEnumerable previousSDKs) { Version = version; MinVSVersion = minVSVersion; + PreviousSDKs = previousSDKs; } } - internal class PreviousSDKVersion + internal class PreviousUWPSDK { - public readonly string Version; + public readonly Version Version; public readonly bool DefaultFallback; - public PreviousSDKVersion(string version, bool defaultFallback) + public PreviousUWPSDK(Version version, bool defaultFallback) { Version = version; DefaultFallback = defaultFallback; @@ -71,13 +73,19 @@ public UWPExtension(string manifest, string windowsKitsFolder, string sdkVersion } } - public static string[] GetReferences(Version sdkVersion) + private static readonly Version kMinimumSupportedUWPVersion = new Version(10, 0, 10240, 0); + private static readonly PreviousUWPSDK kMinimumSupportedPreviousUWPSDK = new PreviousUWPSDK(kMinimumSupportedUWPVersion, true); + private static readonly UWPSDK kMinimumSupportedUWPSDK = new UWPSDK(kMinimumSupportedUWPVersion, new Version(14, 0), new[] { kMinimumSupportedPreviousUWPSDK }); + + public static UWPSDK MinimumSupportedUWPSDK { get { return kMinimumSupportedUWPSDK; } } + + public static string[] GetReferences(UWPSDK sdk) { var folder = GetWindowsKit10(); if (string.IsNullOrEmpty(folder)) return new string[0]; - var version = SdkVersionToString(sdkVersion); + var version = SdkVersionToString(sdk.Version); var references = new HashSet(StringComparer.InvariantCultureIgnoreCase); var windowsWinMd = CombinePaths(folder, "UnionMetadata", version, "Facade", "Windows.winmd"); @@ -102,13 +110,13 @@ public static string[] GetReferences(Version sdkVersion) return references.ToArray(); } - public static IEnumerable GetExtensionSDKs(Version sdkVersion) + public static IEnumerable GetExtensionSDKs(UWPSDK sdk) { var windowsKit10Directory = GetWindowsKit10(); if (string.IsNullOrEmpty(windowsKit10Directory)) return new UWPExtensionSDK[0]; - return GetExtensionSDKs(windowsKit10Directory, SdkVersionToString(sdkVersion)); + return GetExtensionSDKs(windowsKit10Directory, SdkVersionToString(sdk.Version)); } static string SdkVersionToString(Version version) @@ -125,17 +133,17 @@ static string SdkVersionToString(Version version) return sdkVersion; } - public static IEnumerable>>> GetInstalledSDKs() + public static IEnumerable GetInstalledSDKs() { var windowsKit10Directory = GetWindowsKit10(); if (string.IsNullOrEmpty(windowsKit10Directory)) - return Enumerable.Empty>>>(); + return Enumerable.Empty(); var platformsUAP = CombinePaths(windowsKit10Directory, "Platforms", "UAP"); if (!Directory.Exists(platformsUAP)) - return Enumerable.Empty>>>(); + return Enumerable.Empty(); - var allSDKs = new Dictionary>>(); + var allSDKs = new List(); var filesUnderPlatformsUAP = Directory.GetFiles(platformsUAP, "*", SearchOption.AllDirectories); var allPlatformXmlFiles = filesUnderPlatformsUAP.Where(f => string.Equals("Platform.xml", Path.GetFileName(f), StringComparison.OrdinalIgnoreCase)); @@ -158,46 +166,64 @@ public static IEnumerable e.Value).FirstOrDefault(); // Get supported previous versionss var previousVersionPath = Path.Combine(Path.GetDirectoryName(platformXmlFile), "PreviousPlatforms.xml"); - var previousVersions = new SortedList(); + var previousVersions = new List(); if (File.Exists(previousVersionPath)) { + XNamespace xn = "http://microsoft.com/schemas/Windows/SDK/PreviousPlatforms"; + XDocument previousPlatformsDocument = null; + try { - XNamespace xn = "http://microsoft.com/schemas/Windows/SDK/PreviousPlatforms"; - var previousPlatformsDocument = XDocument.Load(previousVersionPath); + previousPlatformsDocument = XDocument.Load(previousVersionPath); + } + catch + { + } - foreach (XElement previousPlatformElement in previousPlatformsDocument.Element(xn + "PreviousPlatforms").Elements(xn + "ApplicationPlatform")) + if (previousPlatformsDocument != null) + { + var previousPlatformsElement = previousPlatformsDocument.Element(xn + "PreviousPlatforms"); + if (previousPlatformsElement != null) { - var previousVersion = previousPlatformElement.Attribute("version").Value; - bool isDefault; - - if (!bool.TryParse(previousPlatformElement.Attribute("IsDefaultFallback").Value, out isDefault)) + foreach (XElement previousPlatformElement in previousPlatformsElement.Elements(xn + "ApplicationPlatform")) { - isDefault = false; + var versionAttribute = previousPlatformElement.Attribute("version"); + if (versionAttribute != null) + { + var previousVersionString = versionAttribute.Value; + bool isDefault = false; + + var isDefaultFallbackAttribute = previousPlatformElement.Attribute("IsDefaultFallback"); + if (isDefaultFallbackAttribute != null) + bool.TryParse(isDefaultFallbackAttribute.Value, out isDefault); + + var previousVersion = TryParseVersion(previousVersionString); + if (previousVersion != null && previousVersion >= kMinimumSupportedUWPVersion) + previousVersions.Add(new PreviousUWPSDK(previousVersion, isDefault)); + } } - - previousVersions.Add(previousVersion, new PreviousSDKVersion(previousVersion, isDefault)); } } - catch - { - // Ignore exception. We'll just use the default below. - } } if (previousVersions.Count == 0) { - // For previous versions, only support the current version if no PreviousVersions.xml was found. - previousVersions.Add(version.ToString(), new PreviousSDKVersion(version.ToString(), true)); + // For previous versions, only support the current version and our minimum supported version if no PreviousVersions.xml was found. + previousVersions.Add(new PreviousUWPSDK(version, true)); + + if (version > kMinimumSupportedUWPVersion) + previousVersions.Add(new PreviousUWPSDK(kMinimumSupportedUWPVersion, false)); } - previousVersions.Reverse(); - allSDKs.Add(new UWPSDK(version, TryParseVersion(minVSVersionString)), previousVersions); + allSDKs.Add(new UWPSDK(version, TryParseVersion(minVSVersionString), previousVersions)); } } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs b/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs index 55e0c6d088..a8a63432fa 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs @@ -11,6 +11,14 @@ namespace UnityEditor.Scripting.ScriptCompilation { + internal class IllegalNamespaceParsing : Exception + { + public IllegalNamespaceParsing(string className, Exception cause) + : base($"Searching for classname: '{className}' caused error in CSharpNameParser", cause) + { + } + } + internal static class CSharpNamespaceParser { static readonly Regex k_ReDefineExpr = new Regex(@"r'\s+|([=!]=)\s*(true|false)|([_a-zA-Z][_a-zA-Z0-9]*)|([()!]|&&|\|\|)", RegexOptions.Compiled); @@ -20,6 +28,7 @@ internal static class CSharpNamespaceParser static readonly Regex k_VerbatimStrings = new Regex(@"@(""[^""]*"")+", RegexOptions.Compiled); static readonly Regex k_NewlineRegex = new Regex("\r\n?", RegexOptions.Compiled); static readonly Regex k_SingleQuote = new Regex(@"((? defines) var split = source.Split(new[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (var s in split) { - if (s.Contains("#define")) + var match = k_ConditionalCompilation.Match(s); + var directive = match.Groups[1].Value; + var arg = match.Groups[2].Value; + if (directive == "define") { - if (stack.Count == 0 || stack.Peek().Item1) defines.Add(s.Split(new[] { "#define" }, StringSplitOptions.None)[1].Trim()); + if (stack.Count == 0 || stack.Peek().Item1) defines.Add(arg.Trim()); } - else if (s.Contains("#undefine")) + else if (directive == "undefine") { - if (stack.Count == 0 || stack.Peek().Item1) defines.Add(s.Split(new[] { "#define" }, StringSplitOptions.None)[1].Trim()); + if (stack.Count == 0 || stack.Peek().Item1) defines.Add(arg.Trim()); } - else if (s.Contains("#if")) + else if (directive == "if") { - var evalResult = EvaluateDefine(s.Split(new[] { "#if" }, StringSplitOptions.None)[1].Trim(), defines); + var evalResult = EvaluateDefine(arg.Trim(), defines); var isEmitting = stack.Count == 0 || stack.Peek().Item1; stack.Push(new Tuple(isEmitting && evalResult, isEmitting && !evalResult)); } - else if (s.Contains("#elif")) + else if (directive == "elif") { + var evalResult = EvaluateDefine(arg, defines); var elseEmitting = stack.Peek().Item2; - var evalResult = EvaluateDefine(s.Split(new[] { "#elif" }, StringSplitOptions.None)[1], defines); - stack.Pop(); - stack.Push(new Tuple(elseEmitting && evalResult, elseEmitting && !evalResult)); + stack.Pop(); stack.Push(new Tuple(elseEmitting && evalResult, elseEmitting && !evalResult)); } - else if (s.Contains("#else")) + else if (directive == "else") { var elseEmitting = stack.Peek().Item2; - stack.Pop(); - stack.Push(new Tuple(elseEmitting, false)); + stack.Pop(); stack.Push(new Tuple(elseEmitting, false)); } - else if (s.Contains("#endif")) + else if (directive == "endif") { stack.Pop(); } diff --git a/Editor/Mono/UIElements/UXMLEditorFactories.cs b/Editor/Mono/UIElements/UXMLEditorFactories.cs index e08c7e366c..db9c6cd070 100644 --- a/Editor/Mono/UIElements/UXMLEditorFactories.cs +++ b/Editor/Mono/UIElements/UXMLEditorFactories.cs @@ -6,11 +6,12 @@ namespace UnityEditor.Experimental.UIElements { + [InitializeOnLoad] internal class UXMLEditorFactories { private static bool s_Registered; - internal static void RegisterAll() + static UXMLEditorFactories() { if (s_Registered) return; diff --git a/Editor/Mono/UIElements/VisualTreeAssetEditor.cs b/Editor/Mono/UIElements/VisualTreeAssetEditor.cs index 230c2b81b2..dd9f1f6885 100644 --- a/Editor/Mono/UIElements/VisualTreeAssetEditor.cs +++ b/Editor/Mono/UIElements/VisualTreeAssetEditor.cs @@ -59,7 +59,6 @@ public void Render(VisualTreeAsset vta, Rect r, GUIStyle background) if (m_Panel == null) { - UXMLEditorFactories.RegisterAll(); m_Panel = UIElementsUtility.FindOrCreatePanel(m_LastTree, ContextType.Editor, new DataWatchService()); if (m_Panel.visualTree.styleSheets == null) { diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index ec051304c7..f7ab82ff33 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -504,7 +504,7 @@ private string ProjectHeader(MonoIsland island, { targetframeworkversion = "v4.7.1"; } - targetLanguageVersion = "7.2"; + targetLanguageVersion = "7.3"; } else if (_settings.VisualStudioVersion == 9) { diff --git a/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs b/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs index 9f52de4a7e..3eb316accf 100644 --- a/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs +++ b/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs @@ -47,7 +47,7 @@ public override Rect Draw(BuildTargetGroup target, Rect rect) return rect; } - public override float GetHeight() + public override float GetHeight(BuildTargetGroup target) { return EditorGUIUtility.singleLineHeight + (EditorGUIUtility.standardVerticalSpacing * 2.0f); } @@ -87,9 +87,9 @@ public override Rect Draw(BuildTargetGroup target, Rect rect) return rect; } - public override float GetHeight() + public override float GetHeight(BuildTargetGroup target) { - return base.GetHeight() + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + return base.GetHeight(target) + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; } } @@ -266,7 +266,7 @@ public override Rect Draw(BuildTargetGroup target, Rect rect) return rect; } - public override float GetHeight() + public override float GetHeight(BuildTargetGroup target) { float singleLineCount = 5.0f; float thumbnailCount = 2.0f; @@ -278,7 +278,7 @@ public override float GetHeight() verticalSpacingCount += 1.0f; } - return base.GetHeight() + (EditorGUIUtility.singleLineHeight * singleLineCount) + + return base.GetHeight(target) + (EditorGUIUtility.singleLineHeight * singleLineCount) + (EditorGUI.kObjectFieldThumbnailHeight * thumbnailCount) + (EditorGUIUtility.standardVerticalSpacing * verticalSpacingCount); } diff --git a/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs b/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs index 162bf65800..a76b51cb62 100644 --- a/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs +++ b/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs @@ -13,6 +13,7 @@ internal class VRCustomOptionsOculus : VRCustomOptions { static GUIContent s_SharedDepthBufferLabel = EditorGUIUtility.TextContent("Shared Depth Buffer|Enable depth buffer submission to allow for overlay depth occlusion, etc."); static GUIContent s_DashSupportLabel = EditorGUIUtility.TextContent("Dash Support|If enabled, pressing the home button brings up Dash, otherwise it brings up the older universal menu."); + static GUIContent s_SharedDepthAndroidInfo = EditorGUIUtility.TrTextContent("Shared Depth Buffer and Dash Support aren't available when targeting mobile."); SerializedProperty m_SharedDepthBuffer; SerializedProperty m_DashSupport; @@ -33,39 +34,51 @@ public override Rect Draw(BuildTargetGroup target, Rect rect) { rect.y += EditorGUIUtility.standardVerticalSpacing; - EditorGUI.BeginDisabled(target == BuildTargetGroup.Android); - - rect.height = EditorGUIUtility.singleLineHeight; - GUIContent label = EditorGUI.BeginProperty(rect, s_SharedDepthBufferLabel, m_SharedDepthBuffer); - EditorGUI.BeginChangeCheck(); - bool boolValue = EditorGUI.Toggle(rect, label, m_SharedDepthBuffer.boolValue); - if (EditorGUI.EndChangeCheck()) + if (target != BuildTargetGroup.Android) { - m_SharedDepthBuffer.boolValue = boolValue; - } - EditorGUI.EndProperty(); - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; + rect.height = EditorGUIUtility.singleLineHeight; + GUIContent label = EditorGUI.BeginProperty(rect, s_SharedDepthBufferLabel, m_SharedDepthBuffer); + EditorGUI.BeginChangeCheck(); + bool boolValue = EditorGUI.Toggle(rect, label, m_SharedDepthBuffer.boolValue); + if (EditorGUI.EndChangeCheck()) + { + m_SharedDepthBuffer.boolValue = boolValue; + } + EditorGUI.EndProperty(); + rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - rect.height = EditorGUIUtility.singleLineHeight; - label = EditorGUI.BeginProperty(rect, s_DashSupportLabel, m_DashSupport); - EditorGUI.BeginChangeCheck(); - boolValue = EditorGUI.Toggle(rect, label, m_DashSupport.boolValue); - if (EditorGUI.EndChangeCheck()) + rect.height = EditorGUIUtility.singleLineHeight; + label = EditorGUI.BeginProperty(rect, s_DashSupportLabel, m_DashSupport); + EditorGUI.BeginChangeCheck(); + boolValue = EditorGUI.Toggle(rect, label, m_DashSupport.boolValue); + if (EditorGUI.EndChangeCheck()) + { + m_DashSupport.boolValue = boolValue; + } + EditorGUI.EndProperty(); + } + else { - m_DashSupport.boolValue = boolValue; + EditorGUI.BeginDisabled(true); + EditorGUI.LabelField(rect, s_SharedDepthAndroidInfo.text, EditorStyles.wordWrappedMiniLabel); + EditorGUI.EndDisabled(); } - EditorGUI.EndProperty(); - - EditorGUI.EndDisabled(); rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; return rect; } - public override float GetHeight() + public override float GetHeight(BuildTargetGroup target) { - return (EditorGUIUtility.singleLineHeight * 2.0f) + (EditorGUIUtility.standardVerticalSpacing * 3.0f); + if (target != BuildTargetGroup.Android) + { + return (EditorGUIUtility.singleLineHeight * 2.0f) + (EditorGUIUtility.standardVerticalSpacing * 3.0f); + } + else + { + return (EditorGUIUtility.singleLineHeight * 1.0f) + (EditorGUIUtility.standardVerticalSpacing * 2.0f); + } } } } diff --git a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs index 2cb70ecd12..eec3acf2ce 100644 --- a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs +++ b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs @@ -160,6 +160,8 @@ internal void XRSectionGUI(BuildTargetGroup targetGroup, int sectionIndex) VuforiaGUI(targetGroup); + RemotingWSAHolographicGUI(targetGroup); + Stereo360CaptureGUI(targetGroup); ErrorOnARDeviceIncompatibility(targetGroup); @@ -170,6 +172,11 @@ internal void XRSectionGUI(BuildTargetGroup targetGroup, int sectionIndex) m_Settings.EndSettingsBox(); } + internal bool TargetGroupSupportsWSAHolographicRemoting(BuildTargetGroup targetGroup) + { + return targetGroup == BuildTargetGroup.WSA; + } + private void DevicesGUI(BuildTargetGroup targetGroup) { if (!TargetGroupSupportsVirtualReality(targetGroup)) @@ -474,7 +481,7 @@ private float GetVRDeviceElementHeight(BuildTargetGroup target, int index) VRCustomOptions customOptions; if (m_CustomOptions.TryGetValue(name, out customOptions)) { - customOptionsHeight = customOptions.IsExpanded ? customOptions.GetHeight() + EditorGUI.kControlVerticalSpacing : 0.0f; + customOptionsHeight = customOptions.IsExpanded ? customOptions.GetHeight(target) + EditorGUI.kControlVerticalSpacing : 0.0f; } return list.elementHeight + customOptionsHeight; @@ -612,5 +619,26 @@ internal void VuforiaGUI(BuildTargetGroup targetGroup) EditorGUILayout.HelpBox("Vuforia Augmented Reality is required when using the Vuforia Virtual Reality SDK.", MessageType.Info); } } + + internal void RemotingWSAHolographicGUI(BuildTargetGroup targetGroup) + { + if (!TargetGroupSupportsWSAHolographicRemoting(targetGroup)) + return; + var shouldEnableScope = VREditor.GetVREnabledOnTargetGroup(targetGroup) && GetVRDeviceElementIsInList(targetGroup, "WindowsMR"); + using (new EditorGUI.DisabledScope(!shouldEnableScope)) + { + var remotingEnabled = PlayerSettings.GetWsaHolographicRemotingEnabled(); + EditorGUI.BeginChangeCheck(); + remotingEnabled = EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("WSA Holographic Remoting Supported"), remotingEnabled); + if (EditorGUI.EndChangeCheck()) + { + PlayerSettings.SetWsaHolographicRemotingEnabled(remotingEnabled); + } + } + if (shouldEnableScope) + { + EditorGUILayout.HelpBox("WindowsMR is required when using WSA Holographic Remoting.", MessageType.Info); + } + } } } diff --git a/Editor/Src/VR/Mono/VRCustomOptions.cs b/Editor/Src/VR/Mono/VRCustomOptions.cs index 4f2987cfd7..e6b810c3bb 100644 --- a/Editor/Src/VR/Mono/VRCustomOptions.cs +++ b/Editor/Src/VR/Mono/VRCustomOptions.cs @@ -65,12 +65,12 @@ public virtual void Initialize(SerializedObject settings, string propertyName) } abstract public Rect Draw(BuildTargetGroup target, Rect rect); - abstract public float GetHeight(); + abstract public float GetHeight(BuildTargetGroup target); } internal class VRCustomOptionsNone : VRCustomOptions { public override Rect Draw(BuildTargetGroup target, Rect rect) { return rect; } - public override float GetHeight() { return 0.0f; } + public override float GetHeight(BuildTargetGroup target) { return 0.0f; } } } diff --git a/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs b/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs index 23cacc5175..0dec8b4b95 100644 --- a/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs +++ b/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs @@ -61,7 +61,7 @@ public override Rect Draw(BuildTargetGroup target, Rect rect) return rect; } - public override float GetHeight() + public override float GetHeight(BuildTargetGroup target) { return EditorGUIUtility.singleLineHeight * 2.0f; } diff --git a/Modules/AssetPipelineEditor/Public/PluginImporter.bindings.cs b/Modules/AssetPipelineEditor/Public/PluginImporter.bindings.cs index 4ec47ccaa8..fd4083cfae 100644 --- a/Modules/AssetPipelineEditor/Public/PluginImporter.bindings.cs +++ b/Modules/AssetPipelineEditor/Public/PluginImporter.bindings.cs @@ -213,6 +213,9 @@ public bool GetExcludeFromAnyPlatform(BuildTarget platform) [NativeMethod("SetCompatibleWithEditor")] extern internal void SetCompatibleWithEditorWithBuildTargetsInternal(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, bool enable); + [NativeMethod("IsCompatibleWithDefines")] + extern internal bool IsCompatibleWithDefines(string[] defines); + internal void SetCompatibleWithEditor(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, bool enable) { SetCompatibleWithEditorWithBuildTargetsInternal(buildTargetGroup, buildTarget, enable); diff --git a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs index 3ca57653be..0ad5078c77 100644 --- a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs +++ b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs @@ -10,12 +10,10 @@ namespace UnityEditor.Profiling.Memory.Experimental { - // Note: this snapshot is completely serializable by unity's serializer. // !!!!! NOTE: Keep in sync with Runtime\Profiler\MemorySnapshots.cpp - public class PackedMemorySnapshot : ISerializationCallbackReceiver + public class PackedMemorySnapshot : IDisposable { - private static readonly UInt64 kMinSupportedVersion = 7; - + static readonly UInt64 kMinSupportedVersion = 7; public static PackedMemorySnapshot Load(string path) { MemorySnapshotFileReader reader = new MemorySnapshotFileReader(path); @@ -42,7 +40,6 @@ public static void Save(PackedMemorySnapshot snapshot, string writePath) FileUtil.CopyFileIfExists(path, writePath, true); } - [SerializeField] MemorySnapshotFileReader m_Reader = null; public ConnectionEntries connections { get; internal set; } @@ -84,15 +81,6 @@ internal void BuildEntries() typeDescriptions = new TypeDescriptionEntries(m_Reader); } - public void OnBeforeSerialize() - { - } - - public void OnAfterDeserialize() - { - BuildEntries(); - } - internal MemorySnapshotFileReader GetReader() { return m_Reader; @@ -106,11 +94,11 @@ public UInt32 version } } - public UnityEngine.Profiling.Memory.Experimental.MetaData metadata + public MetaData metadata { get { - byte[] array = m_Reader.GetDataSingle(EntryType.Metadata_UserMetadata, ConversionFunctions.ToByteArray); + byte[] array = m_Reader.GetDataSingle(EntryType.Metadata_UserMetadata, ConversionFunctions.ToByteArray); // decoded as // content_data_length // content_data @@ -228,7 +216,7 @@ public DateTime recordDate } } - public UnityEngine.Profiling.Memory.Experimental.CaptureFlags captureFlags + public CaptureFlags captureFlags { get { @@ -243,6 +231,31 @@ public VirtualMachineInformation virtualMachineInformation return m_Reader.GetDataSingle(EntryType.Metadata_VirtualMachineInformation, ConversionFunctions.ToVirtualMachineInformation); } } + + ~PackedMemorySnapshot() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + if (m_Reader == null) + { + return; + } + + m_Reader.Dispose(); + m_Reader = null; + } + } } [Flags] diff --git a/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs b/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs index 5ff7053662..5a6c077a9e 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs @@ -3,6 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.IO; using UnityEngine; namespace UnityEditor.MemoryProfiler @@ -15,23 +16,33 @@ private static void SnapshotFinished(string path, bool result) { if (result) { - UnityEditor.Profiling.Memory.Experimental.PackedMemorySnapshot snapshot = UnityEditor.Profiling.Memory.Experimental.PackedMemorySnapshot.Load(path); + Profiling.Memory.Experimental.PackedMemorySnapshot snapshot = Profiling.Memory.Experimental.PackedMemorySnapshot.Load(path); - OnSnapshotReceived(new PackedMemorySnapshot(snapshot)); + var oldSnapshot = new PackedMemorySnapshot(snapshot); + snapshot.Dispose(); + File.Delete(path); + + OnSnapshotReceived(oldSnapshot); } else { + if (File.Exists(path)) + File.Delete(path); + OnSnapshotReceived(null); } } - public static void RequestNewSnapshot() + internal static string GetTemporarySnapshotPath() { string[] s = Application.dataPath.Split('/'); string projectName = s[s.Length - 2]; - string path = Application.temporaryCachePath + "/" + projectName + ".snap"; + return Path.Combine(Application.temporaryCachePath, projectName + ".snap"); + } - UnityEngine.Profiling.Memory.Experimental.MemoryProfiler.TakeSnapshot(path, SnapshotFinished, UnityEngine.Profiling.Memory.Experimental.CaptureFlags.NativeObjects | UnityEngine.Profiling.Memory.Experimental.CaptureFlags.ManagedObjects); + public static void RequestNewSnapshot() + { + UnityEngine.Profiling.Memory.Experimental.MemoryProfiler.TakeSnapshot(GetTemporarySnapshotPath(), SnapshotFinished, UnityEngine.Profiling.Memory.Experimental.CaptureFlags.NativeObjects | UnityEngine.Profiling.Memory.Experimental.CaptureFlags.ManagedObjects); } } diff --git a/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs b/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs index 196892e6dd..ed6c0ee843 100644 --- a/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs +++ b/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs @@ -2,6 +2,7 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -39,15 +40,15 @@ public IEnumerable GetDefinedShortcuts() { var entries = new List(); var names = new List(); - var shortcuts = new List(); - Menu.GetMenuItemShortcuts(names, shortcuts); + var defaultShortcuts = new List(); + Menu.GetMenuItemDefaultShortcuts(names, defaultShortcuts); entries.Capacity += names.Count; for (int index = 0; index < names.Count; ++index) { var keys = new List(); - if (!string.IsNullOrEmpty(shortcuts[index])) - keys.Add(new KeyCombination(Event.KeyboardEvent(shortcuts[index]))); + if (!string.IsNullOrEmpty(defaultShortcuts[index])) + keys.Add(new KeyCombination(Event.KeyboardEvent(defaultShortcuts[index]))); entries.Add(new MenuItemEntryDiscoveryInfo(names[index], keys)); } @@ -139,7 +140,8 @@ public MenuItemEntryDiscoveryInfo(string menuItemPath, List keys m_KeyCombinations = keys; m_MenuItemPath = menuItemPath; - m_ShortcutEntry = new ShortcutEntry(new Identifier(m_MenuItemPath), m_KeyCombinations, null, null, ShortcutType.Menu); + Action menuAction = (args) => { EditorApplication.ExecuteMenuItem(m_MenuItemPath); }; + m_ShortcutEntry = new ShortcutEntry(new Identifier(m_MenuItemPath), m_KeyCombinations, menuAction, null, ShortcutType.Menu); } public ShortcutEntry GetShortcutEntry() diff --git a/Modules/ShortcutManagerEditor/ShortcutController.cs b/Modules/ShortcutManagerEditor/ShortcutController.cs index f551108c50..34f3303ddc 100644 --- a/Modules/ShortcutManagerEditor/ShortcutController.cs +++ b/Modules/ShortcutManagerEditor/ShortcutController.cs @@ -20,6 +20,8 @@ static ShortcutIntegration() // Need to reinitialize after project load if we want menu items EditorApplication.projectWasLoaded += InitializeController; + + EditorApplication.focusChanged += OnFocusChanged; } static bool HasAnyEntriesHandler() @@ -33,6 +35,17 @@ static void EventHandler() instance.HandleKeyEvent(Event.current); } + static void OnInvokingAction(ShortcutEntry shortcutEntry, ShortcutArguments shortcutArguments) + { + // Separate shortcut actions into different undo groups + Undo.IncrementCurrentGroup(); + } + + static void OnFocusChanged(bool isFocused) + { + instance.trigger.ResetActiveClutches(); + } + static void InitializeController() { var shortcutProviders = new IDiscoveryShortcutProvider[] @@ -45,6 +58,7 @@ static void InitializeController() var discovery = new Discovery(shortcutProviders, identifierConflictHandler, invalidContextReporter); instance = new ShortcutController(discovery); instance.Initialize(instance.profileManager); + instance.trigger.invokingAction += OnInvokingAction; } } @@ -55,6 +69,7 @@ class ShortcutController public IShortcutProfileManager profileManager { get; } public IDirectory directory => m_Directory; + public Trigger trigger => m_Trigger; ContextManager m_ContextManager = new ContextManager(); diff --git a/Modules/ShortcutManagerEditor/ShortcutEntry.cs b/Modules/ShortcutManagerEditor/ShortcutEntry.cs index 298751209b..06f605f018 100644 --- a/Modules/ShortcutManagerEditor/ShortcutEntry.cs +++ b/Modules/ShortcutManagerEditor/ShortcutEntry.cs @@ -74,10 +74,10 @@ class ShortcutEntry public Type context => m_Context; public ShortcutType type => m_Type; - internal ShortcutEntry(Identifier id, List defaultCombination, Action action, Type context, ShortcutType type) + internal ShortcutEntry(Identifier id, IEnumerable defaultCombination, Action action, Type context, ShortcutType type) { m_Identifier = id; - m_DefaultCombinations = new List(defaultCombination); + m_DefaultCombinations = defaultCombination.ToList(); m_Context = context ?? ContextManager.globalContextType; m_Action = action; m_Type = type; diff --git a/Modules/ShortcutManagerEditor/Trigger.cs b/Modules/ShortcutManagerEditor/Trigger.cs index e6ccda2c44..28201c667a 100644 --- a/Modules/ShortcutManagerEditor/Trigger.cs +++ b/Modules/ShortcutManagerEditor/Trigger.cs @@ -17,7 +17,8 @@ class Trigger List m_KeyCombinationSequence = new List(); List m_Entries = new List(); Dictionary> m_ActiveClutches = new Dictionary>(); - HashSet m_KeysDown = new HashSet(); + + public event Action invokingAction; public Trigger(IDirectory directory, IConflictResolver conflictResolver) { @@ -32,7 +33,6 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) if (evt.type == EventType.KeyUp) { - m_KeysDown.Remove(evt.keyCode); Tuple clutchTuple; if (m_ActiveClutches.TryGetValue(evt.keyCode, out clutchTuple)) { @@ -44,17 +44,18 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) context = clutchContext, state = ShortcutState.End }; + invokingAction?.Invoke(clutchTuple.Item1, args); clutchTuple.Item1.action(args); } return; } - if (m_KeysDown.Contains(evt.keyCode)) + // Use the event and return if the key is currently used in an active clutch + if (m_ActiveClutches.ContainsKey(evt.keyCode)) { evt.Use(); return; } - m_KeysDown.Add(evt.keyCode); var keyCodeCombination = new KeyCombination(evt); m_KeyCombinationSequence.Add(keyCodeCombination); @@ -93,6 +94,7 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) { case ShortcutType.Action: args.state = ShortcutState.End; + invokingAction?.Invoke(shortcutEntry, args); shortcutEntry.action(args); evt.Use(); Reset(); @@ -103,6 +105,7 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) { m_ActiveClutches.Add(evt.keyCode, new Tuple(shortcutEntry, args.context)); args.state = ShortcutState.Begin; + invokingAction?.Invoke(shortcutEntry, args); shortcutEntry.action(args); evt.Use(); Reset(); @@ -110,7 +113,8 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) break; case ShortcutType.Menu: args.state = ShortcutState.End; - EditorApplication.ExecuteMenuItem(shortcutEntry.identifier.path); + invokingAction?.Invoke(shortcutEntry, args); + shortcutEntry.action(args); evt.Use(); Reset(); break; @@ -128,6 +132,22 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) } } + public void ResetActiveClutches() + { + foreach (var clutchTuple in m_ActiveClutches.Values) + { + var args = new ShortcutArguments + { + context = clutchTuple.Item2, + state = ShortcutState.End, + }; + invokingAction?.Invoke(clutchTuple.Item1, args); + clutchTuple.Item1.action(args); + } + + m_ActiveClutches.Clear(); + } + public bool HasAnyEntries() { return m_Entries.Any(); diff --git a/Modules/TextCore/Managed/AssemblyInfo.cs b/Modules/TextCore/Managed/AssemblyInfo.cs index 6e1c470b4e..8400fd720c 100644 --- a/Modules/TextCore/Managed/AssemblyInfo.cs +++ b/Modules/TextCore/Managed/AssemblyInfo.cs @@ -9,3 +9,5 @@ [assembly: InternalsVisibleTo("Unity.TextCore.Editor")] [assembly: InternalsVisibleTo("Unity.TextMeshPro")] [assembly: InternalsVisibleTo("Unity.TextMeshPro.Editor")] +[assembly: InternalsVisibleTo("Unity.FontEngine.Tests")] +[assembly: InternalsVisibleTo("Unity.FontEngine.Editor.Tests")] diff --git a/Modules/TextCore/Managed/FaceInfo.cs b/Modules/TextCore/Managed/FaceInfo.cs new file mode 100644 index 0000000000..fe1b8fadb9 --- /dev/null +++ b/Modules/TextCore/Managed/FaceInfo.cs @@ -0,0 +1,261 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Runtime.InteropServices; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using UnityEngine.TextCore.LowLevel; + + +namespace UnityEngine.TextCore +{ + /// + /// A structure that contains information about a given typeface and for a specific point size. + /// + [Serializable] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + public struct FaceInfo + { + /// + /// The name of the font typeface also known as family name. + /// + public string familyName { get { return m_FamilyName; } set { m_FamilyName = value; } } + + /// + /// The style name of the typeface which defines both the visual style and weight of the typeface. + /// + public string styleName { get { return m_StyleName; } set { m_StyleName = value; } } + + /// + /// The point size used for sampling the typeface. This is also referenced as sampling point size. + /// + public int pointSize { get { return m_PointSize; } set { m_PointSize = value; } } + + /// + /// The relative scale of the typeface. + /// Default value is 1.0f. + /// + public float scale { get { return m_Scale; } set { m_Scale = value; } } + + // Key metrics for the typeface + + /// + /// The line height represents the distance between consecutive lines of text. + /// This is the distance from baseline to baseline. It is usually computed as line height = ascent - descent + line gap. + /// + public float lineHeight { get { return m_LineHeight; } set { m_LineHeight = value; } } + + /// + /// The Ascent line is typically located at the top of the tallest glyph in the typeface. This represents the distance between the baseline and the tallest ascender. This value is usually positive. + /// + public float ascentLine { get { return m_AscentLine; } set { m_AscentLine = value; } } + + /// + /// The Cap line is typically located at the top of capital letters. This value represents the distance between the baseline and the top of capital letters. + /// + public float capLine { get { return m_CapLine; } set { m_CapLine = value; } } + + /// + /// The Mean line is typically located at the top of lowercase letters. This value represents the distance between the baseline and the top of lowercase letters. + /// + public float meanLine { get { return m_MeanLine; } set { m_MeanLine = value; } } + + /// + /// The Baseline is an imaginary line upon which all glyphs appear to rest on. This value is typically zero. + /// + public float baseline { get { return m_Baseline; } set { m_Baseline = value; } } + + /// + /// The Descent line is typically located at the bottom of the glyph with the lowest descender in the typeface. This represents the distance between the baseline and the lowest descender. This value is usually negative. + /// + public float descentLine { get { return m_DescentLine; } set { m_DescentLine = value; } } + + /// + /// The position of characters using superscript. + /// + public float superscriptOffset { get { return m_SuperscriptOffset; } set { m_SuperscriptOffset = value; } } + + /// + /// The relative size / scale of superscript characters. + /// + public float superscriptSize { get { return m_SuperscriptSize; } set { m_SuperscriptSize = value; } } + + /// + /// The position of characters using subscript. + /// + public float subscriptOffset { get { return m_SubscriptOffset; } set { m_SubscriptOffset = value; } } + + /// + /// The relative size / scale of subscript characters. + /// + public float subscriptSize { get { return m_SubscriptSize; } set { m_SubscriptSize = value; } } + + /// + /// The position of the underline. + /// + public float underlineOffset { get { return m_UnderlineOffset; } set { m_UnderlineOffset = value; } } + + /// + /// The thickness of the underline. + /// + public float underlineThickness { get { return m_UnderlineThickness; } set { m_UnderlineThickness = value; } } + + /// + /// The position of the strikethrough. + /// + public float strikethroughOffset { get { return m_StrikethroughOffset; } set { m_StrikethroughOffset = value; } } + + /// + /// The thickness of the strikethrough. + /// + public float strikethroughThickness { get { return m_StrikethroughThickness; } set { m_StrikethroughThickness = value; } } + + /// + /// The width of the tab character. This width is typically the same as the space character. + /// + public float tabWidth { get { return m_TabWidth; } set { m_TabWidth = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("familyName")] + private string m_FamilyName; + + [SerializeField] + [NativeName("styleName")] + private string m_StyleName; + + [SerializeField] + [NativeName("pointSize")] + private int m_PointSize; + + [SerializeField] + [NativeName("scale")] + private float m_Scale; + + [SerializeField] + [NativeName("lineHeight")] + private float m_LineHeight; + + [SerializeField] + [NativeName("ascentLine")] + private float m_AscentLine; + + [SerializeField] + [NativeName("capLine")] + private float m_CapLine; + + [SerializeField] + [NativeName("meanLine")] + private float m_MeanLine; + + [SerializeField] + [NativeName("baseline")] + private float m_Baseline; + + [SerializeField] + [NativeName("descentLine")] + private float m_DescentLine; + + [SerializeField] + [NativeName("superscriptOffset")] + private float m_SuperscriptOffset; + + [SerializeField] + [NativeName("superscriptSize")] + private float m_SuperscriptSize; + + [SerializeField] + [NativeName("subscriptOffset")] + private float m_SubscriptOffset; + + [SerializeField] + [NativeName("subscriptSize")] + private float m_SubscriptSize; + + [SerializeField] + [NativeName("underlineOffset")] + private float m_UnderlineOffset; + + [SerializeField] + [NativeName("underlineThickness")] + private float m_UnderlineThickness; + + [SerializeField] + [NativeName("strikethroughOffset")] + private float m_StrikethroughOffset; + + [SerializeField] + [NativeName("strikethroughThickness")] + private float m_StrikethroughThickness; + + [SerializeField] + [NativeName("tabWidth")] + private float m_TabWidth; + + /// + /// Constructor used for testing + /// + internal FaceInfo(string familyName, string styleName, int pointSize, float scale, float lineHeight, float ascentLine, float capLine, float meanLine, float baseline, float descentLine, float superscriptOffset, float superscriptSize, float subscriptOffset, float subscriptSize, float underlineOffset, float underlineThickness, float strikethroughOffset, float strikethroughThickness, float tabWidth) + { + m_FamilyName = familyName; + m_StyleName = styleName; + + m_PointSize = pointSize; + m_Scale = scale; + + m_LineHeight = lineHeight; + m_AscentLine = ascentLine; + m_CapLine = capLine; + m_MeanLine = meanLine; + m_Baseline = baseline; + m_DescentLine = descentLine; + + m_SuperscriptOffset = superscriptOffset; + m_SuperscriptSize = superscriptSize; + m_SubscriptOffset = subscriptOffset; + m_SubscriptSize = subscriptSize; + + m_UnderlineOffset = underlineOffset; + m_UnderlineThickness = underlineThickness; + + m_StrikethroughOffset = strikethroughOffset; + m_StrikethroughThickness = strikethroughThickness; + + m_TabWidth = tabWidth; + } + + /// + /// Compares the information in this FaceInfo structure with the information in the given FaceInfo structure to determine whether they have the same values. + /// + /// The FaceInfo structure to compare this FaceInfo structure with. + /// Returns true if the FaceInfo structures have the same values. False if not. + public bool Compare(FaceInfo other) + { + return familyName == other.familyName && + styleName == other.styleName && + pointSize == other.pointSize && + FontEngineUtilities.Approximately(scale, other.scale) && + FontEngineUtilities.Approximately(lineHeight, other.lineHeight) && + FontEngineUtilities.Approximately(ascentLine, other.ascentLine) && + FontEngineUtilities.Approximately(capLine, other.capLine) && + FontEngineUtilities.Approximately(meanLine, other.meanLine) && + FontEngineUtilities.Approximately(baseline, other.baseline) && + FontEngineUtilities.Approximately(descentLine, other.descentLine) && + FontEngineUtilities.Approximately(superscriptOffset, other.superscriptOffset) && + FontEngineUtilities.Approximately(superscriptSize, other.superscriptSize) && + FontEngineUtilities.Approximately(subscriptOffset, other.subscriptOffset) && + FontEngineUtilities.Approximately(subscriptSize, other.subscriptSize) && + FontEngineUtilities.Approximately(underlineOffset, other.underlineOffset) && + FontEngineUtilities.Approximately(underlineThickness, other.underlineThickness) && + FontEngineUtilities.Approximately(strikethroughOffset, other.strikethroughOffset) && + FontEngineUtilities.Approximately(strikethroughThickness, other.strikethroughThickness) && + FontEngineUtilities.Approximately(tabWidth, other.tabWidth); + } + } +} diff --git a/Modules/TextCore/Managed/Glyph.cs b/Modules/TextCore/Managed/Glyph.cs index 0499ff254c..0aa3275e2d 100644 --- a/Modules/TextCore/Managed/Glyph.cs +++ b/Modules/TextCore/Managed/Glyph.cs @@ -6,211 +6,367 @@ using System.Runtime.InteropServices; using UnityEngine.Bindings; using UnityEngine.Scripting; +using UnityEngine.TextCore.LowLevel; namespace UnityEngine.TextCore { /// - /// A Glyph is the visual representation of a text element / character. + /// A rectangle that defines the position of a glyph within an atlas texture. /// [Serializable] - [NativeAsStruct] [UsedByNativeCode] [StructLayout(LayoutKind.Sequential)] - public class Glyph + public struct GlyphRect : IEquatable { /// - /// Constructor for a new glyph. + /// The x position of the glyph in the font atlas texture. /// - public Glyph() - { - this.index = 0; - this.x = 0; - this.y = 0; - this.width = 0; - this.height = 0; - this.bearingX = 0; - this.bearingY = 0; - this.advanceX = 0; - this.scale = 1; - this.atlasIndex = 0; - } + public int x { get { return m_X; } set { m_X = value; } } /// - /// Constructor for a new glyph + /// The y position of the glyph in the font atlas texture. /// - /// Glyph whose values are copied to the new glyph. - public Glyph(Glyph glyph) - { - this.index = glyph.index; - this.x = glyph.x; - this.y = glyph.y; - this.width = glyph.width; - this.height = glyph.height; - this.bearingX = glyph.bearingX; - this.bearingY = glyph.bearingY; - this.advanceX = glyph.advanceX; - this.scale = glyph.scale; - this.atlasIndex = glyph.atlasIndex; - } + public int y { get { return m_Y; } set { m_Y = value; } } /// - /// Constructor for a new glyph + /// The width of the glyph. /// - /// Index of the glyph. - /// The bearingX of the glyph. - /// The bearingY of the glyph. - /// The width of the glyph. - /// The height of the glyph. - /// The advanceX of the glyph. - /// The relative scale of the glyph. - public Glyph(uint index, int bearingX, int bearingY, int width, int height, int advanceX, float scale, int atlasIndex) - { - this.index = index; - this.x = 0; - this.y = 0; - this.width = width; - this.height = height; - this.bearingX = bearingX; - this.bearingY = bearingY; - this.advanceX = advanceX; - this.scale = scale; - this.atlasIndex = atlasIndex; - } + public int width { get { return m_Width; } set { m_Width = value; } } /// - /// The index of the glyph in the source font file. + /// The height of the glyph. /// - public uint index; + public int height { get { return m_Height; } set { m_Height = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("x")] + private int m_X; + + [SerializeField] + [NativeName("y")] + private int m_Y; + + [SerializeField] + [NativeName("width")] + private int m_Width; + + [SerializeField] + [NativeName("height")] + private int m_Height; + + static readonly GlyphRect s_ZeroGlyphRect = new GlyphRect(0, 0, 0, 0); /// - /// The point size at which this glyph was rastered. + /// A GlyphRect with all values set to zero. Shorthand for writing GlyphRect(0, 0, 0, 0). /// - //public int pointSize; + public static GlyphRect zero { get { return s_ZeroGlyphRect; } } /// - /// The x position of the glyph in the font atlas texture + /// Constructor for new GlyphRect. /// - public int x { get { return m_XMin; } set { m_XMin = value; } } - [SerializeField] - [NativeName("x")] - private int m_XMin; + /// The x position of the glyph in the atlas texture. + /// The y position of the glyph in the atlas texture. + /// The width of the glyph. + /// The height of the glyph. + public GlyphRect(int x, int y, int width, int height) + { + m_X = x; + m_Y = y; + m_Width = width; + m_Height = height; + } /// - /// The y position of the glyph in the font atlas texture. + /// Construct new GlyphRect from a Rect. /// - public int y { get { return m_YMin; } set { m_YMin = value; } } - [SerializeField] - [NativeName("y")] - private int m_YMin; + /// The Rect used to construct the new GlyphRect. + public GlyphRect(Rect rect) + { + m_X = (int)rect.x; + m_Y = (int)rect.y; + m_Width = (int)rect.width; + m_Height = (int)rect.height; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + public bool Equals(GlyphRect other) + { + return base.Equals(other); + } + public static bool operator==(GlyphRect lhs, GlyphRect rhs) + { + return lhs.x == rhs.x && + lhs.y == rhs.y && + lhs.width == rhs.width && + lhs.height == rhs.height; + } - // ======================= - // Glyph Metrics - // ======================= + public static bool operator!=(GlyphRect lhs, GlyphRect rhs) + { + return !(lhs == rhs); + } + } + /// + /// A set of values that define the size, position and spacing of a glyph when performing text layout. + /// + [Serializable] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + public struct GlyphMetrics : IEquatable + { /// /// The width of the glyph. /// - public int width { get { return m_Width; } set { m_Width = value; } } - [SerializeField] - [NativeName("width")] - private int m_Width; + public float width { get { return m_Width; } set { m_Width = value; } } /// /// The height of the glyph. /// - public int height { get { return m_Height; } set { m_Height = value; } } - [SerializeField] - [NativeName("height")] - private int m_Height; + public float height { get { return m_Height; } set { m_Height = value; } } /// - /// The horizontal distance from the current drawing position (origin) relative to the elements' left bounding box edge (bbox). + /// The horizontal distance from the current drawing position (origin) relative to the element's left bounding box edge (bbox). /// - public int bearingX; + public float horizontalBearingX { get { return m_HorizontalBearingX; } set { m_HorizontalBearingX = value; } } /// - /// The vertical distance from the current baseline relative to the elements' top bounding box edge (bbox). + /// The vertical distance from the current baseline relative to the element's top bounding box edge (bbox). /// - public int bearingY; + public float horizontalBearingY { get { return m_HorizontalBearingY; } set { m_HorizontalBearingY = value; } } /// /// The horizontal distance to increase (left to right) or decrease (right to left) the drawing position relative to the origin of the text element. - /// This determines the origin position of the next element. + /// This determines the origin position of the next text element. /// - public int advanceX; + public float horizontalAdvance { get { return m_HorizontalAdvance; } set { m_HorizontalAdvance = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("width")] + private float m_Width; + + [SerializeField] + [NativeName("height")] + private float m_Height; + + [SerializeField] + [NativeName("horizontalBearingX")] + private float m_HorizontalBearingX; + + [SerializeField] + [NativeName("horizontalBearingy")] + private float m_HorizontalBearingY; + + [SerializeField] + [NativeName("horizontalAdvance")] + private float m_HorizontalAdvance; /// - /// The relative scale of the text element. The default value is 1.0. + /// Constructor for new glyph metrics. /// - public float scale; + /// The width of the glyph. + /// The height of the glyph. + /// The horizontal bearingX. + /// The horizontal bearingY. + /// The horizontal advance. + public GlyphMetrics(float width, float height, float bearingX, float bearingY, float advance) + { + m_Width = width; + m_Height = height; + m_HorizontalBearingX = bearingX; + m_HorizontalBearingY = bearingY; + m_HorizontalAdvance = advance; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + public bool Equals(GlyphMetrics other) + { + return base.Equals(other); + } + public static bool operator==(GlyphMetrics lhs, GlyphMetrics rhs) + { + return lhs.width == rhs.width && + lhs.height == rhs.height && + lhs.horizontalBearingX == rhs.horizontalBearingX && + lhs.horizontalBearingY == rhs.horizontalBearingY && + lhs.horizontalAdvance == rhs.horizontalAdvance; + } - // ======================= - // Font Atlas Information - // ======================= + public static bool operator!=(GlyphMetrics lhs, GlyphMetrics rhs) + { + return !(lhs == rhs); + } + } + /// + /// A Glyph is the visual representation of a text element or character. + /// + [Serializable] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + public class Glyph + { /// - /// The index of the atlas texture that contains this glyph. + /// The index of the glyph in the source font file. /// - public int atlasIndex; + public uint index { get { return m_Index; } set { m_Index = value; } } /// - /// The x position of the glyph in the font atlas texture + /// The metrics that define the size, position and spacing of a glyph when performing text layout. /// - //public int x { get { return m_XMin; } set { m_XMin = value; } } - //[SerializeField] - //[NativeName("x")] - //private int m_XMin; + public GlyphMetrics metrics { get { return m_Metrics; } set { m_Metrics = value; } } /// - /// The y position of the glyph in the font atlas texture. + /// A rectangle that defines the position of a glyph within an atlas texture. /// - //public int y { get { return m_YMin; } set { m_YMin = value; } } - //[SerializeField] - //[NativeName("y")] - //private int m_YMin; + public GlyphRect glyphRect { get { return m_GlyphRect; } set { m_GlyphRect = value; } } /// - /// A Rect that contains the uv coordinates of the glyph in the atlas texture. These values correspond to the xMin, yMin, xMax, yMax positions. + /// The relative scale of the glyph. The default value is 1.0. /// - //public Vector4 uv; + public float scale { get { return m_Scale; } set { m_Scale = value; } } /// - /// The UV coordinate corresponding to the bottom left of the glyph in texture space. + /// The index of the atlas texture that contains this glyph. /// - //public Vector2 uv0 { get { return new Vector2(uv.xMin, uv.yMin); } } + public int atlasIndex { get { return m_AtlasIndex; } set { m_AtlasIndex = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("index")] + private uint m_Index; + + [SerializeField] + [NativeName("metrics")] + private GlyphMetrics m_Metrics; + + [SerializeField] + [NativeName("glyphRect")] + private GlyphRect m_GlyphRect; + + [SerializeField] + [NativeName("scale")] + private float m_Scale; + + [SerializeField] + [NativeName("atlasIndex")] + private int m_AtlasIndex; /// - /// The UV coordinate corresponding to the top left of the glyph in texture space. + /// Constructor for a new glyph. /// - //public Vector2 uv1 { get { return new Vector2(uv.xMin, uv.yMax); } } + public Glyph() + { + m_Index = 0; + m_Metrics = new GlyphMetrics(); + m_GlyphRect = new GlyphRect(); + m_Scale = 1; + m_AtlasIndex = 0; + } /// - /// The UV coordinate corresponding to the top right of the glyph in texture space. + /// Constructor for a new glyph /// - //public Vector2 uv2 { get { return new Vector2(uv.xMax, uv.yMax); } } + /// Glyph whose values are copied to the new glyph. + public Glyph(Glyph glyph) + { + m_Index = glyph.index; + m_Metrics = glyph.metrics; + m_GlyphRect = glyph.glyphRect; + m_Scale = glyph.scale; + m_AtlasIndex = glyph.atlasIndex; + } /// - /// The UV coordinate corresponding to the bottom right of the glyph in texture space. + /// Constructor for a new glyph /// - //public Vector2 uv3 { get { return new Vector2(uv.xMax, uv.yMin); } } + /// Glyph whose values are copied to the new glyph. + internal Glyph(GlyphMarshallingStruct glyphStruct) + { + m_Index = glyphStruct.index; + m_Metrics = glyphStruct.metrics; + m_GlyphRect = glyphStruct.glyphRect; + m_Scale = glyphStruct.scale; + m_AtlasIndex = glyphStruct.atlasIndex; + } /// - /// Set the uv coordinates of the glyph in the atlas texture. + /// Constructor for new glyph. + /// The scale will be set to a value of 1.0 and atlas index to 0. /// - /// The x position of the glyph in the atlas texture. - /// The y position of the glyph in the atlas texture. - /// The width of the atlas texture. - /// The height of the atlas texture. - //public void SetUV(int x, int y, int texWidth, int texHeight) - //{ - // uv.xMin = x / texWidth; - // uv.xMax = uv.xMin + m_Width / texWidth; - - // uv.xMin = y / texHeight; - // uv.yMax = uv.yMin + m_Height / texHeight; - //} + /// The index of the glyph in the font file. + /// The metrics of the glyph. + /// The GlyphRect defining the position of the glyph in the atlas texture. + public Glyph(uint index, GlyphMetrics metrics, GlyphRect glyphRect) + { + m_Index = index; + m_Metrics = metrics; + m_GlyphRect = glyphRect; + m_Scale = 1; + m_AtlasIndex = 0; + } + + /// + /// Constructor for new glyph. + /// + /// The index of the glyph in the font file. + /// The metrics of the glyph. + /// The GlyphRect defining the position of the glyph in the atlas texture. + /// The relative scale of the glyph. + /// The index of the atlas texture that contains the glyph. + public Glyph(uint index, GlyphMetrics metrics, GlyphRect glyphRect, float scale, int atlasIndex) + { + m_Index = index; + m_Metrics = metrics; + m_GlyphRect = glyphRect; + m_Scale = scale; + m_AtlasIndex = atlasIndex; + } + + /// + /// Compares two glyphs to determine if they have the same values. + /// + /// The glyph to compare with. + /// Returns true if the glyphs have the same values. False if not. + public bool Compare(Glyph other) + { + return index == other.index && + metrics == other.metrics && + glyphRect == other.glyphRect && + scale == other.scale && + atlasIndex == other.atlasIndex; + } } } diff --git a/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs b/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs index b0b99f22f0..d886798a11 100644 --- a/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs +++ b/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs @@ -2,6 +2,7 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine.Scripting; using UnityEngine.Bindings; @@ -27,12 +28,11 @@ public enum GlyphLoadFlags //LOAD_LINEAR_DESIGN = 1 << 13, LOAD_NO_AUTOHINT = 1 << 15, /* Bits 16-19 are used by `LOAD_TARGET_' */ - LOAD_COLOR = 1 << 20, + //LOAD_COLOR = 1 << 20, LOAD_COMPUTE_METRICS = 1 << 21, LOAD_BITMAP_METRICS_ONLY = 1 << 22 } - /// /// Rasterizing modes used by the Font Engine to raster glyphs. /// @@ -71,21 +71,33 @@ public enum FontEngineError Invalid_File_Path = 0x1, Invalid_File_Format = 0x2, Invalid_File_Structure = 0x3, + Invalid_File = 0x4, // Glyph related errors. Invalid_Glyph_Index = 0x10, Invalid_Character_Code = 0x11, Invalid_Pixel_Size = 0x17, + // + Invalid_Library = 0x21, + + // Font face related errors. + Invalid_Face = 0x23, + + Invalid_Library_or_Face = 0x29, + + // Font atlas generation and glyph rendering related errors. + Atlas_Generation_Cancelled = 0x64, + Invalid_SharedTextureData = 0x65, + // Additional errors codes will be added as necessary to cover new FontEngine features and functionality. } - /// /// Rendering modes used by the Font Engine to render glyphs. /// [UsedByNativeCode] - public enum GlyphRenderModes + public enum GlyphRenderMode { SMOOTH_HINTED = GlyphRasterModes.RASTER_MODE_HINTED | GlyphRasterModes.RASTER_MODE_8BIT | GlyphRasterModes.RASTER_MODE_BITMAP | GlyphRasterModes.RASTER_MODE_1X, SMOOTH = GlyphRasterModes.RASTER_MODE_NO_HINTING | GlyphRasterModes.RASTER_MODE_8BIT | GlyphRasterModes.RASTER_MODE_BITMAP | GlyphRasterModes.RASTER_MODE_1X, @@ -98,17 +110,38 @@ public enum GlyphRenderModes SDF16 = GlyphRasterModes.RASTER_MODE_HINTED | GlyphRasterModes.RASTER_MODE_MONO | GlyphRasterModes.RASTER_MODE_SDF | GlyphRasterModes.RASTER_MODE_16X, SDF32 = GlyphRasterModes.RASTER_MODE_HINTED | GlyphRasterModes.RASTER_MODE_MONO | GlyphRasterModes.RASTER_MODE_SDF | GlyphRasterModes.RASTER_MODE_32X, - SDFAA = GlyphRasterModes.RASTER_MODE_HINTED | GlyphRasterModes.RASTER_MODE_8BIT | GlyphRasterModes.RASTER_MODE_SDFAA | GlyphRasterModes.RASTER_MODE_1X, + SDFAA_HINTED = GlyphRasterModes.RASTER_MODE_HINTED | GlyphRasterModes.RASTER_MODE_8BIT | GlyphRasterModes.RASTER_MODE_SDFAA | GlyphRasterModes.RASTER_MODE_1X, + SDFAA = GlyphRasterModes.RASTER_MODE_NO_HINTING | GlyphRasterModes.RASTER_MODE_8BIT | GlyphRasterModes.RASTER_MODE_SDFAA | GlyphRasterModes.RASTER_MODE_1X, //MSDF = RasterModes.RASTER_MODE_HINTED | RasterModes.RASTER_MODE_8BIT | RasterModes.RASTER_MODE_MSDF | RasterModes.RASTER_MODE_1X, //MSDFA = RasterModes.RASTER_MODE_HINTED | RasterModes.RASTER_MODE_8BIT | RasterModes.RASTER_MODE_MSDFA | RasterModes.RASTER_MODE_1X, } + /// + /// The modes available when packing glyphs into an atlas texture. + /// + [UsedByNativeCode] + public enum GlyphPackingMode + { + BestShortSideFit = 0x0, + BestLongSideFit = 0x1, + BestAreaFit = 0x2, + BottomLeftRule = 0x3, + ContactPointRule = 0x4, + } - [NativeHeader("Modules/TextCore/Native/FontEngine.h")] + [NativeHeader("Modules/TextCore/Native/FontEngine/FontEngine.h")] public sealed class FontEngine { private static readonly FontEngine s_Instance = new FontEngine(); + private static GlyphMarshallingStruct[] s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[16]; + private static GlyphMarshallingStruct[] s_GlyphMarshallingStruct_OUT = new GlyphMarshallingStruct[16]; + + private static GlyphRect[] s_FreeGlyphRects = new GlyphRect[16]; + private static GlyphRect[] s_UsedGlyphRects = new GlyphRect[16]; + + private static Dictionary s_GlyphLookupDictionary = new Dictionary(); + internal FontEngine() {} /// @@ -144,6 +177,38 @@ public static FontEngineError DestroyFontEngine() [NativeMethod(Name = "TextCore::FontEngine::DestroyFontEngine", IsFreeFunction = true)] static extern int DestroyFontEngine_Internal(); + /// + /// Force the cancellation of any atlas or glyph rendering process. + /// Used primarily by the Font Asset Creator. + /// + internal static void SendCancellationRequest() + { + SendCancellationRequest_Internal(); + } + + [NativeMethod(Name = "TextCore::FontEngine::SendCancellationRequest", IsFreeFunction = true)] + static extern void SendCancellationRequest_Internal(); + + /// + /// Determines if the font engine is currently in the process of rendering and adding glyphs into an atlas texture. + /// Used primarily by the Font Asset Creator. + /// + internal static extern bool isProcessingDone + { + [NativeMethod(Name = "TextCore::FontEngine::GetIsProcessingDone", IsFreeFunction = true)] + get; + } + + /// + /// Returns the generation progress on glyph packing and rendering. + /// Used primarily by the Font Asset Creator. + /// + internal static extern float generationProgress + { + [NativeMethod(Name = "TextCore::FontEngine::GetGenerationProgress", IsFreeFunction = true)] + get; + } + /// /// Load the source font file at the given file path. /// @@ -180,6 +245,9 @@ public static FontEngineError LoadFontFace(string filePath, int pointSize) /// Returns a value of zero if the font face was loaded successfully. public static FontEngineError LoadFontFace(byte[] sourceFontFile) { + if (sourceFontFile.Length == 0) + return FontEngineError.Invalid_File; + return (FontEngineError)LoadFontFace_FromSourceFontFile_Internal(sourceFontFile); } @@ -195,6 +263,9 @@ public static FontEngineError LoadFontFace(byte[] sourceFontFile) /// Returns a value of zero if the font face was loaded successfully. public static FontEngineError LoadFontFace(byte[] sourceFontFile, int pointSize) { + if (sourceFontFile.Length == 0) + return FontEngineError.Invalid_File; + return (FontEngineError)LoadFontFace_With_Size_FromSourceFontFile_Internal(sourceFontFile, pointSize); } @@ -202,6 +273,35 @@ public static FontEngineError LoadFontFace(byte[] sourceFontFile, int pointSize) static extern int LoadFontFace_With_Size_FromSourceFontFile_Internal(byte[] sourceFontFile, int pointSize); + /// + /// Load the font file from the Unity font's internal font data. Note the Unity font must be set to Dynamic with Include Font Data enabled. + /// + /// The font from which to load the data. + /// Returns a value of zero if the font face was loaded successfully. + public static FontEngineError LoadFontFace(Font font) + { + return (FontEngineError)LoadFontFace_FromFont_Internal(font); + } + + [NativeMethod(Name = "TextCore::FontEngine::LoadFontFace", IsFreeFunction = true)] + static extern int LoadFontFace_FromFont_Internal(Font font); + + + /// + /// Load the font file from the Unity font's internal font data. Note the Unity font must be set to Dynamic with Include Font Data enabled. + /// + /// The font from which to load the data. + /// The point size used to scale the font face. + /// Returns a value of zero if the font face was loaded successfully. + public static FontEngineError LoadFontFace(Font font, int pointSize) + { + return (FontEngineError)LoadFontFace_With_Size_FromFont_Internal(font, pointSize); + } + + [NativeMethod(Name = "TextCore::FontEngine::LoadFontFace", IsFreeFunction = true)] + static extern int LoadFontFace_With_Size_FromFont_Internal(Font font, int pointSize); + + /// /// Set the size of the currently loaded font face. /// @@ -212,17 +312,44 @@ public static FontEngineError SetFaceSize(int pointSize) return (FontEngineError)SetFaceSize_Internal(pointSize); } - [NativeMethod(Name = "TextCore::FontEngine::SetFaceSize", IsFreeFunction = true)] + [NativeMethod(Name = "TextCore::FontEngine::SetFaceSize", IsThreadSafe = true, IsFreeFunction = true)] static extern int SetFaceSize_Internal(int pointSize); + /// + /// Get information about the currently loaded and sized font face. + /// + /// Returns the FaceInfo of the currently loaded font face. + public static FaceInfo GetFaceInfo() + { + FaceInfo faceInfo = new FaceInfo(); + + GetFaceInfo_Internal(ref faceInfo); + + return faceInfo; + } + + [NativeMethod(Name = "TextCore::FontEngine::GetFaceInfo", IsThreadSafe = true, IsFreeFunction = true)] + static extern int GetFaceInfo_Internal(ref FaceInfo faceInfo); + + /// /// Get the index of the glyph for the character mapped at Unicode value. /// /// The Unicode value of the character for which to lookup the glyph index. /// Returns the index of the glyph used by the character using the Unicode value. Returns zero if no glyph exists for the given Unicode value. - [NativeMethod(Name = "TextCore::FontEngine::GetGlyphIndex", IsFreeFunction = true)] - public static extern int GetGlyphIndex(uint unicode); + [NativeMethod(Name = "TextCore::FontEngine::GetGlyphIndex", IsThreadSafe = true, IsFreeFunction = true)] + internal static extern uint GetGlyphIndex(uint unicode); + + + /// + /// Try to get the glyph index for the character at the given Unicode value. + /// + /// The unicode value of the character for which to lookup the glyph index. + /// The index of the glyph for the given unicode character or the .notdef glyph (index 0) if no glyph is available for the given Unicode value. + /// Returns true if the given unicode has a glyph index. + [NativeMethod(Name = "TextCore::FontEngine::TryGetGlyphIndex", IsThreadSafe = true, IsFreeFunction = true)] + public static extern bool TryGetGlyphIndex(uint unicode, out uint glyphIndex); /// @@ -236,7 +363,7 @@ internal static FontEngineError LoadGlyph(uint unicode, GlyphLoadFlags flags) return (FontEngineError)LoadGlyph_Internal(unicode, flags); } - [NativeMethod(Name = "TextCore::FontEngine::LoadGlyph", IsFreeFunction = true)] + [NativeMethod(Name = "TextCore::FontEngine::LoadGlyph", IsThreadSafe = true, IsFreeFunction = true)] static extern int LoadGlyph_Internal(uint unicode, GlyphLoadFlags loadFlags); @@ -249,13 +376,23 @@ internal static FontEngineError LoadGlyph(uint unicode, GlyphLoadFlags flags) /// Returns true if a glyph exists for the given unicode value. Otherwise returns false. public static bool TryGetGlyphWithUnicodeValue(uint unicode, GlyphLoadFlags flags, out Glyph glyph) { - glyph = new Glyph(); + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(); + + if (TryGetGlyphWithUnicodeValue_Internal(unicode, flags, ref glyphStruct)) + { + glyph = new Glyph(glyphStruct); + + return true; + } + + // Set glyph to null if no glyph exists for the given unicode value. + glyph = null; - return TryGetGlyphWithUnicodeValue_Internal(unicode, flags, glyph); + return false; } - [NativeMethod(Name = "TextCore::FontEngine::TryGetGlyphWithUnicodeValue", IsFreeFunction = true)] - static extern bool TryGetGlyphWithUnicodeValue_Internal(uint unicode, GlyphLoadFlags loadFlags, [Out] Glyph glyph); + [NativeMethod(Name = "TextCore::FontEngine::TryGetGlyphWithUnicodeValue", IsThreadSafe = true, IsFreeFunction = true)] + static extern bool TryGetGlyphWithUnicodeValue_Internal(uint unicode, GlyphLoadFlags loadFlags, ref GlyphMarshallingStruct glyphStruct); /// @@ -267,46 +404,485 @@ public static bool TryGetGlyphWithUnicodeValue(uint unicode, GlyphLoadFlags flag /// Returns true if a glyph exists at the given index. Otherwise returns false. public static bool TryGetGlyphWithIndexValue(uint glyphIndex, GlyphLoadFlags flags, out Glyph glyph) { - glyph = new Glyph(); + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(); + + if (TryGetGlyphWithIndexValue_Internal(glyphIndex, flags, ref glyphStruct)) + { + glyph = new Glyph(glyphStruct); + + return true; + } + + // Set glyph to null if no glyph exists for the given unicode value. + glyph = null; + + return false; + } - return TryGetGlyphWithIndexValue_Internal(glyphIndex, flags, glyph); + [NativeMethod(Name = "TextCore::FontEngine::TryGetGlyphWithIndexValue", IsThreadSafe = true, IsFreeFunction = true)] + static extern bool TryGetGlyphWithIndexValue_Internal(uint glyphIndex, GlyphLoadFlags loadFlags, ref GlyphMarshallingStruct glyphStruct); + + + /// + /// Try to pack the given glyph into the given texture width and height. + /// + /// The glyph to try to pack. + /// The padding between this glyph and other glyphs. + /// The packing algorithm used to pack the glyphs. + /// The glyph rendering mode. + /// The width of the target atlas texture. + /// The height of the target atlas texture. + /// List of GlyphRects representing the available space in the atlas. + /// List of GlyphRects representing the occupied space in the atlas. + /// + internal static bool TryPackGlyphInAtlas(Glyph glyph, int padding, GlyphPackingMode packingMode, GlyphRenderMode renderMode, int width, int height, List freeGlyphRects, List usedGlyphRects) + { + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(glyph); + + int freeGlyphRectCount = freeGlyphRects.Count; + int usedGlyphRectCount = usedGlyphRects.Count; + int totalGlyphRects = freeGlyphRectCount + usedGlyphRectCount; + + // Make sure marshalling arrays allocations are appropriate. + if (s_FreeGlyphRects.Length < totalGlyphRects || s_UsedGlyphRects.Length < totalGlyphRects) + { + int newSize = Mathf.NextPowerOfTwo(totalGlyphRects + 1); + s_FreeGlyphRects = new GlyphRect[newSize]; + s_UsedGlyphRects = new GlyphRect[newSize]; + } + + // Copy glyph rect data to marshalling arrays. + int glyphRectCount = Mathf.Max(freeGlyphRectCount, usedGlyphRectCount); + for (int i = 0; i < glyphRectCount; i++) + { + if (i < freeGlyphRectCount) + s_FreeGlyphRects[i] = freeGlyphRects[i]; + + if (i < usedGlyphRectCount) + s_UsedGlyphRects[i] = usedGlyphRects[i]; + } + + if (TryPackGlyphInAtlas_Internal(ref glyphStruct, padding, packingMode, renderMode, width, height, s_FreeGlyphRects, ref freeGlyphRectCount, s_UsedGlyphRects, ref usedGlyphRectCount)) + { + // Copy new glyph position to source glyph. + glyph.glyphRect = glyphStruct.glyphRect; + + freeGlyphRects.Clear(); + usedGlyphRects.Clear(); + + // Copy marshalled glyph rect data + glyphRectCount = Mathf.Max(freeGlyphRectCount, usedGlyphRectCount); + for (int i = 0; i < glyphRectCount; i++) + { + if (i < freeGlyphRectCount) + freeGlyphRects.Add(s_FreeGlyphRects[i]); + + if (i < usedGlyphRectCount) + usedGlyphRects.Add(s_UsedGlyphRects[i]); + } + + return true; + } + + return false; } - [NativeMethod(Name = "TextCore::FontEngine::TryGetGlyphWithIndexValue", IsFreeFunction = true)] - static extern bool TryGetGlyphWithIndexValue_Internal(uint glyphIndex, GlyphLoadFlags loadFlags, [Out] Glyph glyph); + [NativeMethod(Name = "TextCore::FontEngine::TryPackGlyph", IsThreadSafe = true, IsFreeFunction = true)] + extern static bool TryPackGlyphInAtlas_Internal(ref GlyphMarshallingStruct glyph, int padding, GlyphPackingMode packingMode, GlyphRenderMode renderMode, int width, int height, + [Out] GlyphRect[] freeGlyphRects, ref int freeGlyphRectCount, [Out] GlyphRect[] usedGlyphRects, ref int usedGlyphRectCount); /// - /// Try rasterizing and adding the given glyph to the provided texture. + /// Pack glyphs in the given atlas size. + /// + /// Glyphs to pack in atlas. + /// Glyphs packed in atlas. + /// The padding between glyphs. + /// The packing algorithm used to pack the glyphs. + /// The glyph rendering mode. + /// The width of the target atlas texture. + /// The height of the target atlas texture. + /// List of GlyphRects representing the available space in the atlas. + /// List of GlyphRects representing the occupied space in the atlas. + /// + internal static bool TryPackGlyphsInAtlas(List glyphsToAdd, List glyphsAdded, int padding, GlyphPackingMode packingMode, GlyphRenderMode renderMode, int width, int height, List freeGlyphRects, List usedGlyphRects) + { + // Determine potential total allocations required for glyphs and glyph rectangles. + int glyphsToAddCount = glyphsToAdd.Count; + int glyphsAddedCount = glyphsAdded.Count; + int freeGlyphRectCount = freeGlyphRects.Count; + int usedGlyphRectCount = usedGlyphRects.Count; + int totalCount = glyphsToAddCount + glyphsAddedCount + freeGlyphRectCount + usedGlyphRectCount; + + // Make sure marshaling arrays allocations are appropriate. + if (s_GlyphMarshallingStruct_IN.Length < totalCount || s_GlyphMarshallingStruct_OUT.Length < totalCount || s_FreeGlyphRects.Length < totalCount || s_UsedGlyphRects.Length < totalCount) + { + int newSize = Mathf.NextPowerOfTwo(totalCount + 1); + s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[newSize]; + s_GlyphMarshallingStruct_OUT = new GlyphMarshallingStruct[newSize]; + s_FreeGlyphRects = new GlyphRect[newSize]; + s_UsedGlyphRects = new GlyphRect[newSize]; + } + + s_GlyphLookupDictionary.Clear(); + + // Copy glyph data into appropriate marshaling array. + for (int i = 0; i < totalCount; i++) + { + if (i < glyphsToAddCount) + { + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(glyphsToAdd[i]); + + s_GlyphMarshallingStruct_IN[i] = glyphStruct; + + // Add reference to glyph in lookup dictionary + if (s_GlyphLookupDictionary.ContainsKey(glyphStruct.index) == false) + s_GlyphLookupDictionary.Add(glyphStruct.index, glyphsToAdd[i]); + } + + if (i < glyphsAddedCount) + { + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(glyphsAdded[i]); + + s_GlyphMarshallingStruct_OUT[i] = glyphStruct; + + // Add reference to glyph in lookup dictionary + if (s_GlyphLookupDictionary.ContainsKey(glyphStruct.index) == false) + s_GlyphLookupDictionary.Add(glyphStruct.index, glyphsAdded[i]); + } + + if (i < freeGlyphRectCount) + s_FreeGlyphRects[i] = freeGlyphRects[i]; + + if (i < usedGlyphRectCount) + s_UsedGlyphRects[i] = usedGlyphRects[i]; + } + + bool allGlyphsIncluded = TryPackGlyphsInAtlas_Internal(s_GlyphMarshallingStruct_IN, ref glyphsToAddCount, s_GlyphMarshallingStruct_OUT, ref glyphsAddedCount, + padding, packingMode, renderMode, width, height, + s_FreeGlyphRects, ref freeGlyphRectCount, s_UsedGlyphRects, ref usedGlyphRectCount); + + // Clear lists and / or re-allocate arrays. + glyphsToAdd.Clear(); + glyphsAdded.Clear(); + freeGlyphRects.Clear(); + usedGlyphRects.Clear(); + + // Copy marshaled glyph data back into the appropriate lists. + for (int i = 0; i < totalCount; i++) + { + if (i < glyphsToAddCount) + { + GlyphMarshallingStruct glyphStruct = s_GlyphMarshallingStruct_IN[i]; + Glyph glyph = s_GlyphLookupDictionary[glyphStruct.index]; + + // Note: In theory, only new glyphRect x and y need to be copied. + glyph.metrics = glyphStruct.metrics; + glyph.glyphRect = glyphStruct.glyphRect; + glyph.scale = glyphStruct.scale; + glyph.atlasIndex = glyphStruct.atlasIndex; + + glyphsToAdd.Add(glyph); + } + + if (i < glyphsAddedCount) + { + GlyphMarshallingStruct glyphStruct = s_GlyphMarshallingStruct_OUT[i]; + Glyph glyph = s_GlyphLookupDictionary[glyphStruct.index]; + + glyph.metrics = glyphStruct.metrics; + glyph.glyphRect = glyphStruct.glyphRect; + glyph.scale = glyphStruct.scale; + glyph.atlasIndex = glyphStruct.atlasIndex; + + glyphsAdded.Add(glyph); + } + + if (i < freeGlyphRectCount) + { + freeGlyphRects.Add(s_FreeGlyphRects[i]); + } + + if (i < usedGlyphRectCount) + { + usedGlyphRects.Add(s_UsedGlyphRects[i]); + } + } + + return allGlyphsIncluded; + } + + [NativeMethod(Name = "TextCore::FontEngine::TryPackGlyphs", IsThreadSafe = true, IsFreeFunction = true)] + extern static bool TryPackGlyphsInAtlas_Internal([Out] GlyphMarshallingStruct[] glyphsToAdd, ref int glyphsToAddCount, [Out] GlyphMarshallingStruct[] glyphsAdded, ref int glyphsAddedCount, + int padding, GlyphPackingMode packingMode, GlyphRenderMode renderMode, int width, int height, + [Out] GlyphRect[] freeGlyphRects, ref int freeGlyphRectCount, [Out] GlyphRect[] usedGlyphRects, ref int usedGlyphRectCount); + + + /// + /// Render and add glyph to the provided texture. /// /// The Glyph that should be added into the provided texture. /// The padding value around the glyph. /// The Rendering Mode for the Glyph. /// The Texture to which the glyph should be added. /// Returns a value of zero if the glyph was successfully added to the texture. - public static FontEngineError AddGlyphToTexture(Glyph glyph, int padding, GlyphRenderModes renderMode, Texture2D texture) + internal static FontEngineError RenderGlyphToTexture(Glyph glyph, int padding, GlyphRenderMode renderMode, Texture2D texture) { - return (FontEngineError)AddGlyphToTexture_Internal(glyph, padding, renderMode, texture); + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(glyph); + + return (FontEngineError)RenderGlyphToTexture_Internal(glyphStruct, padding, renderMode, texture); } - [NativeMethod(Name = "TextCore::FontEngine::AddGlyphToTexture", IsFreeFunction = true)] - extern static int AddGlyphToTexture_Internal(Glyph glyph, int padding, GlyphRenderModes renderMode, Texture2D texture); + [NativeMethod(Name = "TextCore::FontEngine::RenderGlyphToTexture", IsFreeFunction = true)] + extern static int RenderGlyphToTexture_Internal(GlyphMarshallingStruct glyphStruct, int padding, GlyphRenderMode renderMode, Texture2D texture); /// - /// Try rasterizing and adding the given list of glyphs to the provided texture. + /// Render and add the glyphs in the provided list to the texture. /// - /// The list of glyphs to be added into the provided texture. + /// The list of glyphs to be rendered and added to the provided texture. /// The padding value around the glyphs. - /// The rendering mode used rasterize the glyphs. + /// The rendering mode used to rasterize the glyphs. /// Returns a value of zero if the glyphs were successfully added to the texture. /// - public static FontEngineError AddGlyphsToTexture(Glyph[] glyphs, int padding, GlyphRenderModes renderMode, Texture2D texture) + internal static FontEngineError RenderGlyphsToTexture(List glyphs, int padding, GlyphRenderMode renderMode, Texture2D texture) { - return (FontEngineError)AddGlyphsToTextureFromArray_Internal(glyphs, padding, renderMode, texture); + int glyphCount = glyphs.Count; + + // Make sure marshaling arrays allocations are appropriate. + if (s_GlyphMarshallingStruct_IN.Length < glyphCount) + { + int newSize = Mathf.NextPowerOfTwo(glyphCount + 1); + s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[newSize]; + } + + // Copy data to marshalling buffers + for (int i = 0; i < glyphCount; i++) + s_GlyphMarshallingStruct_IN[i] = new GlyphMarshallingStruct(glyphs[i]); + + // Call extern function to render and add glyphs to texture. + int error = RenderGlyphsToTexture_Internal(s_GlyphMarshallingStruct_IN, glyphCount, padding, renderMode, texture); + + return (FontEngineError)error; } - [NativeMethod(Name = "TextCore::FontEngine::AddGlyphsToTexture", IsFreeFunction = true)] - extern static int AddGlyphsToTextureFromArray_Internal(Glyph[] glyphs, int padding, GlyphRenderModes renderMode, Texture2D texture); + [NativeMethod(Name = "TextCore::FontEngine::RenderGlyphsToTexture", IsFreeFunction = true)] + extern static int RenderGlyphsToTexture_Internal(GlyphMarshallingStruct[] glyphs, int glyphCount, int padding, GlyphRenderMode renderMode, Texture2D texture); + + + internal static FontEngineError RenderGlyphsToTexture(List glyphs, int padding, GlyphRenderMode renderMode, byte[] texBuffer, int texWidth, int texHeight) + { + int glyphCount = glyphs.Count; + + // Make sure marshaling arrays allocations are appropriate. + if (s_GlyphMarshallingStruct_IN.Length < glyphCount) + { + int newSize = Mathf.NextPowerOfTwo(glyphCount + 1); + s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[newSize]; + } + + // Copy data to marshalling buffers + for (int i = 0; i < glyphCount; i++) + s_GlyphMarshallingStruct_IN[i] = new GlyphMarshallingStruct(glyphs[i]); + + int error = RenderGlyphsToTextureBuffer_Internal(s_GlyphMarshallingStruct_IN, glyphCount, padding, renderMode, texBuffer, texWidth, texHeight); + + return (FontEngineError)error; + } + + [NativeMethod(Name = "TextCore::FontEngine::RenderGlyphsToTextureBuffer", IsThreadSafe = true, IsFreeFunction = true)] + extern static int RenderGlyphsToTextureBuffer_Internal(GlyphMarshallingStruct[] glyphs, int glyphCount, int padding, GlyphRenderMode renderMode, [Out] byte[] texBuffer, int texWidth, int texHeight); + + + /// + /// Internal function used to render and add glyphs to the cached shared texture data from outside the main thread. + /// It is necessary to use SetSharedTextureData(texture) prior to calling this function. + /// + /// The list of glyphs to be added into the provided texture. + /// The padding value around the glyphs. + /// The rendering mode used to rasterize the glyphs. + /// + internal static FontEngineError RenderGlyphsToSharedTexture(List glyphs, int padding, GlyphRenderMode renderMode) + { + int glyphCount = glyphs.Count; + + // Make sure marshaling arrays allocations are appropriate. + if (s_GlyphMarshallingStruct_IN.Length < glyphCount) + { + int newSize = Mathf.NextPowerOfTwo(glyphCount + 1); + s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[newSize]; + } + + // Copy data to marshalling buffers + for (int i = 0; i < glyphCount; i++) + s_GlyphMarshallingStruct_IN[i] = new GlyphMarshallingStruct(glyphs[i]); + + int error = RenderGlyphsToSharedTexture_Internal(s_GlyphMarshallingStruct_IN, glyphCount, padding, renderMode); + + return (FontEngineError)error; + } + + [NativeMethod(Name = "TextCore::FontEngine::RenderGlyphsToSharedTexture", IsThreadSafe = true, IsFreeFunction = true)] + extern static int RenderGlyphsToSharedTexture_Internal(GlyphMarshallingStruct[] glyphs, int glyphCount, int padding, GlyphRenderMode renderMode); + + + /// + /// Internal function used to get a reference to the shared texture data which is required for accessing the texture data outside of the main thread. + /// + [NativeMethod(Name = "TextCore::FontEngine::SetSharedTextureData", IsFreeFunction = true)] + internal extern static void SetSharedTexture(Texture2D texture); + + + /// + /// Internal function used to release the shared texture data. + /// + [NativeMethod(Name = "TextCore::FontEngine::ReleaseSharedTextureData", IsThreadSafe = true, IsFreeFunction = true)] + internal extern static void ReleaseSharedTexture(); + + + internal static bool TryAddGlyphToTexture(uint glyphIndex, int padding, GlyphPackingMode packingMode, List freeGlyphRects, List usedGlyphRects, GlyphRenderMode renderMode, Texture2D texture, out Glyph glyph) + { + // Determine potential total allocations required for glyphs and glyph rectangles. + int freeGlyphRectCount = freeGlyphRects.Count; + int usedGlyphRectCount = usedGlyphRects.Count; + int totalGlyphRects = freeGlyphRectCount + usedGlyphRectCount; + + // Make sure marshalling arrays allocations are appropriate. + if (s_FreeGlyphRects.Length < totalGlyphRects || s_UsedGlyphRects.Length < totalGlyphRects) + { + int newSize = Mathf.NextPowerOfTwo(totalGlyphRects + 1); + s_FreeGlyphRects = new GlyphRect[newSize]; + s_UsedGlyphRects = new GlyphRect[newSize]; + } + + // Copy glyph rect data to marshalling arrays. + int glyphRectCount = Mathf.Max(freeGlyphRectCount, usedGlyphRectCount); + for (int i = 0; i < glyphRectCount; i++) + { + if (i < freeGlyphRectCount) + s_FreeGlyphRects[i] = freeGlyphRects[i]; + + if (i < usedGlyphRectCount) + s_UsedGlyphRects[i] = usedGlyphRects[i]; + } + + GlyphMarshallingStruct glyphStruct; + + // Marshall data over to the native side. + if (TryAddGlyphToTexture_Internal(glyphIndex, padding, packingMode, s_FreeGlyphRects, ref freeGlyphRectCount, s_UsedGlyphRects, ref usedGlyphRectCount, renderMode, texture, out glyphStruct)) + { + // Copy marshalled data over to new glyph. + glyph = new Glyph(glyphStruct); + + freeGlyphRects.Clear(); + usedGlyphRects.Clear(); + + // Copy marshalled free and used GlyphRect data over. + glyphRectCount = Mathf.Max(freeGlyphRectCount, usedGlyphRectCount); + for (int i = 0; i < glyphRectCount; i++) + { + if (i < freeGlyphRectCount) + freeGlyphRects.Add(s_FreeGlyphRects[i]); + + if (i < usedGlyphRectCount) + usedGlyphRects.Add(s_UsedGlyphRects[i]); + } + + return true; + } + + glyph = null; + + return false; + } + + [NativeMethod(Name = "TextCore::FontEngine::TryAddGlyphToTexture", IsThreadSafe = true, IsFreeFunction = true)] + extern static bool TryAddGlyphToTexture_Internal(uint glyphIndex, int padding, + GlyphPackingMode packingMode, [Out] GlyphRect[] freeGlyphRects, ref int freeGlyphRectCount, [Out] GlyphRect[] usedGlyphRects, ref int usedGlyphRectCount, + GlyphRenderMode renderMode, Texture2D texture, out GlyphMarshallingStruct glyph); + + + /// + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::GetGlyphPairAdjustmentTable", IsFreeFunction = true)] + internal extern static void GetGlyphPairAdjustmentTable(); + + // ================================================ + // Experimental / Testing / Benchmarking Functions + // ================================================ + + /// + /// Internal function used for testing rasterizing of shapes and glyphs. + /// + /// Texture containing the source shape to raster. + /// Padding value. + /// The rendering mode. + /// Texture containing the rastered shape. + [NativeMethod(Name = "TextCore::FontEngine::RenderToTexture", IsFreeFunction = true)] + internal extern static void RenderBufferToTexture(Texture2D srcTexture, int padding, GlyphRenderMode renderMode, Texture2D dstTexture); + + /* + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyph", IsFreeFunction = true)] + extern public static void ModifyGlyph([Out] Glyph glyph); + + /// + /// + /// + /// + public static void ModifyGlyphStruct(Glyph glyph) + { + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(glyph); + + ModifyGlyph_Internal(ref glyphStruct); + + glyph.metrics = glyphStruct.metrics; + glyph.glyphRect = glyphStruct.glyphRect; + glyph.scale = glyphStruct.scale; + glyph.atlasIndex = glyphStruct.atlasIndex; + } + + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyph", IsThreadSafe = true, IsFreeFunction = true)] + extern static void ModifyGlyph_Internal(ref GlyphMarshallingStruct glyphs); + + /// + /// + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyphMarshallingStruct", IsFreeFunction = true)] + extern public static void ModifyGlyphMarshallingStruct(GlyphMarshallingStruct[] glyph); + + /// + /// + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyphMarshallingStruct", IsFreeFunction = true)] + extern public static void ModifyGlyphMarshallingStructArray(GlyphMarshallingStruct[] glyph); + + /// + /// + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyphs", IsFreeFunction = true)] + extern public static void ModifyGlyphStructArray([Out] GlyphMarshallingStruct[] glyph); + + /// + /// + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyphs", IsFreeFunction = true)] + extern public static void ModifyGlyphArray([Out] Glyph[] glyph); + + [NativeMethod(Name = "TextCore::FontEngine::AccessFont", IsFreeFunction = true)] + extern public static void AccessFont(Font font); + */ + } + + internal struct FontEngineUtilities + { + internal static bool Approximately(float a, float b) + { + return Mathf.Abs(a - b) < 0.001f; + } } } diff --git a/Modules/TextCore/ScriptBindings/GlyphMarshallingStruct.cs b/Modules/TextCore/ScriptBindings/GlyphMarshallingStruct.cs new file mode 100644 index 0000000000..f293121789 --- /dev/null +++ b/Modules/TextCore/ScriptBindings/GlyphMarshallingStruct.cs @@ -0,0 +1,74 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Runtime.InteropServices; +using UnityEngine.Bindings; +using UnityEngine.Scripting; + + +namespace UnityEngine.TextCore.LowLevel +{ + /// + /// Structure used for marshalling glyphs between managed and native code. + /// + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + internal struct GlyphMarshallingStruct + { + /// + /// The index of the glyph in the source font file. + /// + public uint index; + + /// + /// Metrics defining the size, positioning and spacing of a glyph when doing text layout. + /// + public GlyphMetrics metrics; + + /// + /// A rectangle that defines the position of a glyph within an atlas texture. + /// + public GlyphRect glyphRect; + + /// + /// The relative scale of the text element. The default value is 1.0. + /// + public float scale; + + /// + /// The index of the atlas texture that contains this glyph. + /// + public int atlasIndex; + + /// + /// Constructor for a new glyph + /// + /// Glyph whose values are copied to the new glyph. + public GlyphMarshallingStruct(Glyph glyph) + { + this.index = glyph.index; + this.metrics = glyph.metrics; + this.glyphRect = glyph.glyphRect; + this.scale = glyph.scale; + this.atlasIndex = glyph.atlasIndex; + } + + /// + /// Constructor for new glyph + /// + /// The index of the glyph in the font file. + /// The metrics of the glyph. + /// A rectangle defining the position of the glyph in the atlas texture. + /// The relative scale of the glyph. + /// The index of the atlas texture that contains the glyph. + public GlyphMarshallingStruct(uint index, GlyphMetrics metrics, GlyphRect glyphRect, float scale, int atlasIndex) + { + this.index = index; + this.metrics = metrics; + this.glyphRect = glyphRect; + this.scale = scale; + this.atlasIndex = atlasIndex; + } + } +} diff --git a/Modules/TextRendering/TextRendering.bindings.cs b/Modules/TextRendering/TextRendering.bindings.cs index 63d1ff0d0b..d2d1875ef8 100644 --- a/Modules/TextRendering/TextRendering.bindings.cs +++ b/Modules/TextRendering/TextRendering.bindings.cs @@ -365,7 +365,14 @@ public static int GetMaxVertsForString(string str) } internal static extern Font GetDefault(); - public extern bool HasCharacter(char c); + + public bool HasCharacter(char c) + { + return HasCharacter((int)c); + } + + private extern bool HasCharacter(int c); + public static extern string[] GetOSInstalledFontNames(); private static extern void Internal_CreateFont([Writable] Font self, string name); diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs index 4cf48e9b5b..17081082fc 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs @@ -1244,7 +1244,18 @@ private static void OnPostprocessAllAssets(string[] importedAssets, string[] del public class PaletteAssetModificationProcessor : AssetModificationProcessor { + static void OnWillCreateAsset(string assetName) + { + SavePalettesIfRequired(); + } + static string[] OnWillSaveAssets(string[] paths) + { + SavePalettesIfRequired(); + return paths; + } + + static void SavePalettesIfRequired() { if (!GridPaintingState.savingPalette) { @@ -1257,7 +1268,6 @@ static string[] OnWillSaveAssets(string[] paths) } } } - return paths; } } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs index 952df16b08..6509d90f1d 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs @@ -104,6 +104,9 @@ internal void OnGUI() { if (GUILayout.Button(Styles.ok)) { + // case 1077362: Close window to prevent overlap with OS folder window when saving new palette asset + Close(); + var swizzle = Grid.CellSwizzle.XYZ; if (m_Layout == GridLayout.CellLayout.Hexagon) swizzle = Styles.hexagonSwizzleTypeValue[m_HexagonLayout]; @@ -114,6 +117,7 @@ internal void OnGUI() m_Owner.palette = go; m_Owner.Repaint(); } + GUIUtility.ExitGUI(); } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs index 4003031a24..72dfeac3c6 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs @@ -103,12 +103,20 @@ public virtual void OnGUI() } } - protected void UpdateMouseGridPosition() + protected void ResetPreviousMousePositionToCurrentPosition() { - if (Event.current.type == EventType.MouseDrag || Event.current.type == EventType.MouseMove || Event.current.type == EventType.DragUpdated) - { - m_MouseGridPositionChanged = false; + m_PreviousMouseGridPosition = m_MouseGridPosition; + } + protected void UpdateMouseGridPosition(bool forceUpdate = false) + { + if (Event.current.type == EventType.MouseDrag + || Event.current.type == EventType.MouseMove + // Case 1075857: Mouse Down when window is not in focus needs to update mouse grid position + || Event.current.type == EventType.MouseDown + || Event.current.type == EventType.DragUpdated + || forceUpdate) + { Vector2Int newGridPosition = ScreenToGrid(Event.current.mousePosition); if (newGridPosition != m_MouseGridPosition) { @@ -118,10 +126,14 @@ protected void UpdateMouseGridPosition() newGridPosition.x = m_MouseGridPosition.x + Math.Sign(delta.x) * k_MaxMouseCellDelta; if (Mathf.Abs(delta.y) > k_MaxMouseCellDelta) newGridPosition.y = m_MouseGridPosition.y + Math.Sign(delta.y) * k_MaxMouseCellDelta; - m_PreviousMouseGridPosition = m_MouseGridPosition; + ResetPreviousMousePositionToCurrentPosition(); m_MouseGridPosition = newGridPosition; MouseGridPositionChanged(); } + else if (!forceUpdate) + { + m_MouseGridPositionChanged = false; + } } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs index 4e5f28982b..a538cc4e38 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs @@ -18,6 +18,7 @@ internal class PaintableSceneViewGrid : PaintableGrid private Grid grid { get { return brushTarget != null ? brushTarget.GetComponentInParent() : (Selection.activeGameObject != null ? Selection.activeGameObject.GetComponentInParent() : null); } } private GridBrushBase gridBrush { get { return GridPaintingState.gridBrush; } } private SceneView activeSceneView = null; + private int sceneViewTransformHash; GameObject brushTarget { @@ -64,7 +65,12 @@ private Rect GetSceneViewPositionRect(SceneView sceneView) public void OnSceneGUI(SceneView sceneView) { - UpdateMouseGridPosition(); + HandleMouseEnterLeave(sceneView); + + // Case 1077400: SceneView camera transform changes may update the mouse grid position even though the mouse position has not changed + var currentSceneViewTransformHash = sceneView.camera.transform.localToWorldMatrix.GetHashCode(); + UpdateMouseGridPosition(currentSceneViewTransformHash == sceneViewTransformHash); + sceneViewTransformHash = currentSceneViewTransformHash; var dot = 1.0f; var gridView = GetGridView(); @@ -88,7 +94,6 @@ public void OnSceneGUI(SceneView sceneView) EditorGUIUtility.AddCursorRect(GetSceneViewPositionRect(sceneView), MouseCursor.CustomCursor); } } - HandleMouseEnterLeave(sceneView); } private void HandleMouseEnterLeave(SceneView sceneView) @@ -132,6 +137,7 @@ private void OnMouseEnter(SceneView sceneView) GridPaintingState.activeBrushEditor.OnMouseEnter(); GridPaintingState.activeGrid = this; activeSceneView = sceneView; + ResetPreviousMousePositionToCurrentPosition(); } private void OnMouseLeave(SceneView sceneView) diff --git a/Modules/VFX/Public/ScriptBindings/VFXEnums.bindings.cs b/Modules/VFX/Public/ScriptBindings/VFXEnums.bindings.cs index 998ba30d89..c1dc69eb80 100644 --- a/Modules/VFX/Public/ScriptBindings/VFXEnums.bindings.cs +++ b/Modules/VFX/Public/ScriptBindings/VFXEnums.bindings.cs @@ -63,7 +63,7 @@ internal enum VFXExpressionOperation // matrix operations TRSToMatrix, - InverseTRS, + InverseMatrix, ExtractPositionFromMatrix, ExtractAnglesFromMatrix, ExtractScaleFromMatrix, @@ -123,7 +123,10 @@ internal enum VFXExpressionOperation // Logical operations LogicalAnd, LogicalOr, - LogicalNot + LogicalNot, + + // This allows backward compatibility + InverseTRS = InverseMatrix, } internal enum VFXValueType diff --git a/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs b/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs index 2d107d7a9c..2401ade069 100644 --- a/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs +++ b/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs @@ -43,9 +43,29 @@ public VFXEventAttribute CreateVFXEventAttribute() return vfxEventAttribute; } - extern public void Play(VFXEventAttribute eventAttribute = null); - extern public void Stop(VFXEventAttribute eventAttribute = null); - extern public void SendEvent(string eventName, VFXEventAttribute eventAttribute = null); + extern public void Play(VFXEventAttribute eventAttribute); + + public void Play() + { + Play(null); + } + + extern public void Stop(VFXEventAttribute eventAttribute); + public void Stop() + { + Stop(null); + } + + extern public void SendEvent(int eventNameID, VFXEventAttribute eventAttribute); + public void SendEvent(string eventName) + { + SendEvent(Shader.PropertyToID(eventName), null); + } + + public void SendEvent(string eventName, VFXEventAttribute eventAttribute) + { + SendEvent(Shader.PropertyToID(eventName), null); + } extern public void Reinit(); extern public void AdvanceOneFrame(); diff --git a/Modules/VFXEditor/Public/ScriptBindings/VFXMemorySerializer.bindings.cs b/Modules/VFXEditor/Public/ScriptBindings/VFXMemorySerializer.bindings.cs index a5d4a5cf31..4773276ced 100644 --- a/Modules/VFXEditor/Public/ScriptBindings/VFXMemorySerializer.bindings.cs +++ b/Modules/VFXEditor/Public/ScriptBindings/VFXMemorySerializer.bindings.cs @@ -19,8 +19,23 @@ internal static class VFXMemorySerializer { extern public static string StoreObjects(ScriptableObject[] objects); - [FreeFunction(Name = "VFXMemorySerializerBindings::Internal_ExtractObjects")] - extern public static ScriptableObject[] ExtractObjects(string data, bool asACopy); + extern public static byte[] StoreObjectsToByteArray(ScriptableObject[] objects, CompressionLevel compressionLevel = CompressionLevel.None); + + [FreeFunction(Name = "VFXMemorySerializerBindings::Internal_ExtractObjects_FromString")] + extern private static ScriptableObject[] ExtractObjects_FromString(string data, bool asACopy); + + [FreeFunction(Name = "VFXMemorySerializerBindings::Internal_ExtractObjects_FromByteArray")] + extern private static ScriptableObject[] ExtractObjects_FromByteArray(byte[] data, bool asACopy); + + public static ScriptableObject[] ExtractObjects(string data, bool asACopy) + { + return ExtractObjects_FromString(data, asACopy); + } + + public static ScriptableObject[] ExtractObjects(byte[] data, bool asACopy) + { + return ExtractObjects_FromByteArray(data, asACopy); + } [FreeFunction(Name = "VFXMemorySerializerBindings::Internal_DuplicateObjects")] extern public static ScriptableObject[] DuplicateObjects(ScriptableObject[] objects); diff --git a/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs b/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs index 8b16ca9b96..10b9a80910 100644 --- a/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs +++ b/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs @@ -35,6 +35,7 @@ internal struct VFXRendererSettings public bool receiveShadows; public ReflectionProbeUsage reflectionProbeUsage; public LightProbeUsage lightProbeUsage; + public int transparencyPriority; } [UsedByNativeCode] diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index baadafe1cf..9eb5fc83be 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -1506,12 +1506,18 @@ Modules\TextCore\Managed\AssemblyInfo.cs + + Modules\TextCore\Managed\FaceInfo.cs + Modules\TextCore\Managed\Glyph.cs Modules\TextCore\ScriptBindings\FontEngine.bindings.cs + + Modules\TextCore\ScriptBindings\GlyphMarshallingStruct.cs + Modules\TextRendering\FontStyle.cs diff --git a/README.md b/README.md index c330049458..8700f0282d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b3 C# reference source code +## Unity 2018.3.0b5 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Export/Camera.bindings.cs b/Runtime/Export/Camera.bindings.cs index c27dd8219c..9620d45454 100644 --- a/Runtime/Export/Camera.bindings.cs +++ b/Runtime/Export/Camera.bindings.cs @@ -232,6 +232,9 @@ public static Camera[] allCameras } public static int GetAllCameras(Camera[] cameras) { + if (cameras == null) + throw new NullReferenceException(); + if (cameras.Length < allCamerasCount) throw new ArgumentException("Passed in array to fill with cameras is to small to hold the number of cameras. Use Camera.allCamerasCount to get the needed size."); return GetAllCamerasImpl(cameras); diff --git a/Runtime/Export/GraphicsManagers.bindings.cs b/Runtime/Export/GraphicsManagers.bindings.cs index d5315d7c90..0e85526478 100644 --- a/Runtime/Export/GraphicsManagers.bindings.cs +++ b/Runtime/Export/GraphicsManagers.bindings.cs @@ -84,6 +84,8 @@ private QualitySettings() {} extern public static int antiAliasing { get; set; } extern public static int asyncUploadTimeSlice { get; set; } extern public static int asyncUploadBufferSize { get; set; } + extern public static bool asyncUploadPersistentBuffer { get; set; } + extern public static bool realtimeReflectionProbes { get; set; } extern public static bool billboardsFaceCameraPosition { get; set; } diff --git a/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs b/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs index 591e257949..532b49ce9f 100644 --- a/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs +++ b/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs @@ -21,30 +21,30 @@ public partial class ParticleSystem : Component // Properties extern public bool isPlaying { - [NativeName("SyncJobs()->IsPlaying")] get; + [NativeName("SyncJobs(false)->IsPlaying")] get; } extern public bool isEmitting { - [NativeName("SyncJobs()->IsEmitting")] get; + [NativeName("SyncJobs(false)->IsEmitting")] get; } extern public bool isStopped { - [NativeName("SyncJobs()->IsStopped")] get; + [NativeName("SyncJobs(false)->IsStopped")] get; } extern public bool isPaused { - [NativeName("SyncJobs()->IsPaused")] get; + [NativeName("SyncJobs(false)->IsPaused")] get; } extern public int particleCount { - [NativeName("SyncJobs()->GetParticleCount")] get; + [NativeName("SyncJobs(false)->GetParticleCount")] get; } extern public float time { - [NativeName("SyncJobs()->GetSecPosition")] + [NativeName("SyncJobs(false)->GetSecPosition")] get; - [NativeName("SyncJobs()->SetSecPosition")] + [NativeName("SyncJobs(false)->SetSecPosition")] set; } @@ -52,7 +52,7 @@ extern public UInt32 randomSeed { [NativeName("GetRandomSeed")] get; - [NativeName("SyncJobs()->SetRandomSeed")] + [NativeName("SyncJobs(false)->SetRandomSeed")] set; } @@ -60,7 +60,7 @@ extern public bool useAutoRandomSeed { [NativeName("GetAutoRandomSeed")] get; - [NativeName("SyncJobs()->SetAutoRandomSeed")] + [NativeName("SyncJobs(false)->SetAutoRandomSeed")] set; } diff --git a/Runtime/Transform/ScriptBindings/Transform.bindings.cs b/Runtime/Transform/ScriptBindings/Transform.bindings.cs index 79877fee02..3e3e121490 100644 --- a/Runtime/Transform/ScriptBindings/Transform.bindings.cs +++ b/Runtime/Transform/ScriptBindings/Transform.bindings.cs @@ -382,7 +382,10 @@ public int hierarchyCapacity [FreeFunction("SetHierarchyCapacity", HasExplicitThis = true)] private extern void internal_setHierarchyCapacity(int value); - public int hierarchyCount { get; } + public int hierarchyCount { get { return internal_getHierarchyCount(); } } + + [FreeFunction("GetHierarchyCount", HasExplicitThis = true)] + private extern int internal_getHierarchyCount(); [NativeConditional("UNITY_EDITOR")] [FreeFunction("IsNonUniformScaleTransform", HasExplicitThis = true)] diff --git a/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs b/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs index dfa7f7c180..8e66c9141b 100644 --- a/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs @@ -2971,6 +2971,8 @@ public partial struct TrailModule public bool generateLightingData { set { SetGenerateLightingData(m_ParticleSystem, value); } get { return GetGenerateLightingData(m_ParticleSystem); } } public int ribbonCount { get { return GetRibbonCount(m_ParticleSystem); } set { SetRibbonCount(m_ParticleSystem, value); } } public float shadowBias { set { SetShadowBias(m_ParticleSystem, value); } get { return GetShadowBias(m_ParticleSystem); } } + public bool splitSubEmitterRibbons { set { SetSplitSubEmitterRibbons(m_ParticleSystem, value); } get { return GetSplitSubEmitterRibbons(m_ParticleSystem); } } + public bool attachRibbonsToTransform { set { SetAttachRibbonsToTransform(m_ParticleSystem, value); } get { return GetAttachRibbonsToTransform(m_ParticleSystem); } } [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration @@ -3125,6 +3127,22 @@ public partial struct TrailModule [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern private static float GetShadowBias (ParticleSystem system) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static void SetSplitSubEmitterRibbons (ParticleSystem system, bool value) ; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static bool GetSplitSubEmitterRibbons (ParticleSystem system) ; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static void SetAttachRibbonsToTransform (ParticleSystem system, bool value) ; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static bool GetAttachRibbonsToTransform (ParticleSystem system) ; + } [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.LayoutKind.Sequential)] From 42361760bb0461e70c6b3a4e9b794e8abe7cf334 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Thu, 18 Oct 2018 07:28:58 +0000 Subject: [PATCH 15/17] Unity 2018.3.0b6 C# reference source code --- Editor/Mono/Animation/ZoomableArea.cs | 15 + Editor/Mono/Collab/Collab.cs | 11 +- Editor/Mono/ConsoleWindow.cs | 10 +- Editor/Mono/ContainerWindow.cs | 3 +- Editor/Mono/GameView/GameView.cs | 3 + Editor/Mono/Inspector/InspectorWindow.cs | 19 +- .../PlayerSettingsEditor.cs | 188 ++--- Editor/Mono/PlayerSettingsAndroid.bindings.cs | 8 - .../StageManager/StageNavigationManager.cs | 8 +- Editor/Mono/SceneView/SceneView.cs | 47 +- .../Mono/Scripting/Compilers/BooCompiler.cs | 17 +- .../Scripting/Compilers/CSharpLanguage.cs | 59 +- .../Compilers/MicrosoftCSharpCompiler.cs | 40 +- .../Scripting/Compilers/MonoCSharpCompiler.cs | 53 +- .../Compilers/MonoScriptCompilerBase.cs | 4 +- .../Scripting/Compilers/ScriptCompilerBase.cs | 138 +++- .../Compilers/UnityScriptCompiler.cs | 27 +- .../ScriptCompilation/EditorBuildRules.cs | 11 + .../ScriptCompilation/EditorCompilation.cs | 24 +- .../EditorCompilationInterface.cs | 10 +- .../ScriptCompilation/MonoLibraryHelpers.cs | 58 +- .../Providers/AssetSettingsProvider.cs | 6 + Editor/Mono/Settings/SettingsProvider.cs | 6 + Editor/Mono/Settings/SettingsWindow.cs | 16 +- Editor/Mono/Utils/DirectoryExtensions.cs | 2 +- .../SolutionSynchronizer.cs | 69 +- Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs | 102 ++- Modules/ShortcutManagerEditor/Trigger.cs | 1 + Modules/Terrain/Public/BrushTransform.cs | 80 ++ Modules/Terrain/Public/PaintContext.cs | 632 ++++++++++++++++ Modules/Terrain/Public/TerrainPaintUtility.cs | 688 +++--------------- Modules/TerrainEditor/Brush/Brush.cs | 2 +- Modules/TerrainEditor/Brush/BrushList.cs | 5 + .../PaintTools/PaintHeightTool.cs | 55 +- .../PaintTools/PaintTextureTool.cs | 22 +- .../TerrainEditor/PaintTools/SetHeightTool.cs | 56 +- .../PaintTools/SmoothHeightTool.cs | 39 +- Modules/TerrainEditor/PaintTools/StampTool.cs | 69 +- .../PaintTools/TerrainPaintTool.cs | 36 +- Modules/TerrainEditor/TerrainInspector.cs | 136 +++- .../Utilities/TerrainPaintUtilityEditor.cs | 193 +++-- Modules/UIElements/VisualElement.cs | 22 +- Projects/CSharp/UnityEngine.csproj | 6 + README.md | 2 +- .../AR/Tango/ScriptBindings/Tango.bindings.cs | 64 +- 45 files changed, 1892 insertions(+), 1170 deletions(-) create mode 100644 Modules/Terrain/Public/BrushTransform.cs create mode 100644 Modules/Terrain/Public/PaintContext.cs diff --git a/Editor/Mono/Animation/ZoomableArea.cs b/Editor/Mono/Animation/ZoomableArea.cs index 2bc23ff956..8ab4fd6020 100644 --- a/Editor/Mono/Animation/ZoomableArea.cs +++ b/Editor/Mono/Animation/ZoomableArea.cs @@ -992,5 +992,20 @@ public float PixelDeltaToTime(Rect rect) { return shownArea.width / rect.width; } + + public void UpdateZoomScale(float fMaxScaleValue, float fMinScaleValue) + { + // 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 + + if (m_Scale.y > fMaxScaleValue || m_Scale.y < fMinScaleValue) + { + m_Scale.y = m_Scale.y > fMaxScaleValue ? fMaxScaleValue : fMinScaleValue; + } + + if (m_Scale.x > fMaxScaleValue || m_Scale.x < fMinScaleValue) + { + m_Scale.x = m_Scale.x > fMaxScaleValue ? fMaxScaleValue : fMinScaleValue; + } + } } } // namespace diff --git a/Editor/Mono/Collab/Collab.cs b/Editor/Mono/Collab/Collab.cs index 80ec1bd2c5..5a3a96c851 100644 --- a/Editor/Mono/Collab/Collab.cs +++ b/Editor/Mono/Collab/Collab.cs @@ -364,11 +364,16 @@ public bool SetConflictsResolvedTheirs(string[] paths) public PublishInfo GetChangesToPublish() { - Change[] changes = GetSelectedChangesInternal(); + Change[] changes = GetChangesToPublishInternal(); bool isFiltered = false; - if (Toolbar.isLastShowRequestPartial) + + if (SupportsAsyncChanges()) { - isFiltered = true; + changes = GetSelectedChangesInternal(); + if (Toolbar.isLastShowRequestPartial) + { + isFiltered = true; + } } return new PublishInfo() diff --git a/Editor/Mono/ConsoleWindow.cs b/Editor/Mono/ConsoleWindow.cs index 12d7ac5db0..4cb9501d5d 100644 --- a/Editor/Mono/ConsoleWindow.cs +++ b/Editor/Mono/ConsoleWindow.cs @@ -627,6 +627,7 @@ void OnGUI() EditorGUIUtility.SetIconSize(new Vector2(rowHeight, rowHeight)); GUIContent tempContent = new GUIContent(); int id = GUIUtility.GetControlID(0); + int rowDoubleClicked = -1; /////@TODO: Make Frame selected work with ListViewState using (new GettingLogEntriesScope(m_ListView)) @@ -712,11 +713,16 @@ void OnGUI() if (openSelectedItem) { - LogEntries.RowGotDoubleClicked(selectedRow); - Event.current.Use(); + rowDoubleClicked = selectedRow; + e.Use(); } } + // Prevent dead locking in EditorMonoConsole by delaying callbacks (which can log to the console) until after LogEntries.EndGettingEntries() has been + // called (this releases the mutex in EditorMonoConsole so logging again is allowed). Fix for case 1081060. + if (rowDoubleClicked != -1) + LogEntries.RowGotDoubleClicked(rowDoubleClicked); + EditorGUIUtility.SetIconSize(Vector2.zero); // Display active text (We want word wrapped text with a vertical scrollbar) diff --git a/Editor/Mono/ContainerWindow.cs b/Editor/Mono/ContainerWindow.cs index 638f8c1b8a..c1a379d446 100644 --- a/Editor/Mono/ContainerWindow.cs +++ b/Editor/Mono/ContainerWindow.cs @@ -82,7 +82,8 @@ internal void ShowPopupWithMode(ShowMode mode) m_RootView.SetWindowRecurse(this); Internal_SetTitle(m_Title); Save(); - Internal_BringLiveAfterCreation(false, false); + // only set focus iff mode is a popupMenu. + Internal_BringLiveAfterCreation(false, mode == ShowMode.PopupMenu); } static Color skinBackgroundColor diff --git a/Editor/Mono/GameView/GameView.cs b/Editor/Mono/GameView/GameView.cs index 628b539d89..8f0c17b335 100644 --- a/Editor/Mono/GameView/GameView.cs +++ b/Editor/Mono/GameView/GameView.cs @@ -385,6 +385,9 @@ private void UpdateZoomAreaAndParent() CopyDimensionsToParentView(); m_LastWindowPixelSize = position.size * EditorGUIUtility.pixelsPerPoint; EditorApplication.SetSceneRepaintDirty(); + + // update the scale according to new resolution + m_ZoomArea.UpdateZoomScale(maxScale, minScale); } void AllowCursorLockAndHide(bool enable) diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index 1464161d4b..ba33875f25 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -511,7 +511,8 @@ protected virtual void OnGUI() if (tracker.activeEditors.Length > 0) { - DrawVCSShortInfo(); + Editor assetEditor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(tracker.activeEditors); + DrawVCSShortInfo(this, assetEditor); } } @@ -904,14 +905,13 @@ private void DetachPreview() GUIUtility.ExitGUI(); } - protected virtual void DrawVCSSticky(float offset) + private static void DrawVCSSticky(EditorWindow hostWindow, Editor assetEditor, float offset) { string message = ""; - Editor assetEditor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(tracker.activeEditors); bool hasRemovedSticky = EditorPrefs.GetBool("vcssticky"); if (!hasRemovedSticky && !Editor.IsAppropriateFileOpenForEdit(assetEditor.target, out message)) { - var rect = new Rect(10, position.height - 94, position.width - 20, 80); + var rect = new Rect(10, hostWindow.position.height - 94, hostWindow.position.width - 20, 80); rect.y -= offset; if (Event.current.type == EventType.Repaint) { @@ -932,14 +932,13 @@ protected virtual void DrawVCSSticky(float offset) } } - private void DrawVCSShortInfo() + internal static void DrawVCSShortInfo(EditorWindow hostWindow, Editor assetEditor) { if (Provider.enabled && EditorSettings.externalVersionControl != ExternalVersionControl.Disabled && EditorSettings.externalVersionControl != ExternalVersionControl.AutoDetect && EditorSettings.externalVersionControl != ExternalVersionControl.Generic) { - Editor assetEditor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(tracker.activeEditors); string assetPath = AssetDatabase.GetAssetPath(assetEditor.target); Asset asset = Provider.GetAssetByPath(assetPath); if (asset == null || !(asset.path.StartsWith("Assets") || asset.path.StartsWith("ProjectSettings"))) @@ -1005,15 +1004,15 @@ private void DrawVCSShortInfo() // TODO: Retrieve default CheckoutMode from VC settings (depends on asset type; native vs. imported) Task task = Provider.Checkout(assetEditor.targets, CheckoutMode.Both); task.Wait(); - Repaint(); + hostWindow.Repaint(); } } - DrawVCSSticky(rect.height / 2); + DrawVCSSticky(hostWindow, assetEditor, rect.height / 2); } } } - protected string BuildTooltip(Asset asset, Asset metaAsset) + protected static string BuildTooltip(Asset asset, Asset metaAsset) { var sb = new StringBuilder(); if (asset != null) @@ -1029,7 +1028,7 @@ protected string BuildTooltip(Asset asset, Asset metaAsset) return sb.ToString(); } - protected void DrawVCSShortInfoAsset(Asset asset, string tooltip, Rect rect, Texture2D icon, string currentState) + protected static void DrawVCSShortInfoAsset(Asset asset, string tooltip, Rect rect, Texture2D icon, string currentState) { Rect overlayRect = new Rect(rect.x, rect.y, 28, 16); Rect iconRect = overlayRect; diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 6b8786ffff..370285f953 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -1137,6 +1137,14 @@ void OpenGLES31OptionsGUI(BuildTargetGroup targetGroup, BuildTarget targetPlatfo void GraphicsAPIsGUIOnePlatform(BuildTargetGroup targetGroup, BuildTarget targetPlatform, string platformTitle) { + // Facebook on windows must be always DX11 + // TODO: Remove this when Facebook platform support contract is over + if (targetGroup == BuildTargetGroup.Facebook && + (targetPlatform == BuildTarget.StandaloneWindows || targetPlatform == BuildTarget.StandaloneWindows64)) + { + return; + } + GraphicsDeviceType[] availableDevices = PlayerSettings.GetSupportedGraphicsAPIs(targetPlatform); // if no devices (e.g. no platform module), or we only have one possible choice, then no // point in having any UI @@ -1891,124 +1899,128 @@ private void OtherSectionConfigurationGUI(BuildTargetGroup targetGroup, ISetting // Configuration GUILayout.Label(SettingsContent.configurationTitle, EditorStyles.boldLabel); - // Scripting Runtime Version - var scriptingRuntimeVersions = new[] {ScriptingRuntimeVersion.Legacy, ScriptingRuntimeVersion.Latest}; - var scriptingRuntimeVersionNames = new[] {SettingsContent.scriptingRuntimeVersionLegacy, SettingsContent.scriptingRuntimeVersionLatest}; - var newScriptingRuntimeVersions = PlayerSettings.scriptingRuntimeVersion; - - if (EditorApplication.isPlaying) - { - var current = PlayerSettings.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy ? SettingsContent.scriptingRuntimeVersionLegacy : SettingsContent.scriptingRuntimeVersionLatest; - BuildDisabledEnumPopup(current, SettingsContent.scriptingRuntimeVersion); - } - else - { - newScriptingRuntimeVersions = BuildEnumPopup(SettingsContent.scriptingRuntimeVersion, PlayerSettings.scriptingRuntimeVersion, scriptingRuntimeVersions, scriptingRuntimeVersionNames); - } - - if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - { - EditorGUILayout.HelpBox(SettingsContent.scriptingRuntimeVersionDeprecationWarning.text, MessageType.Warning); - } - - if (PlayerSettings.scriptingRuntimeVersion != EditorApplication.scriptingRuntimeVersion) + // scripting runtime settings in play mode are not supported + using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) { - var activeScriptingRuntime = EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy ? SettingsContent.scriptingRuntimeVersionLegacy : SettingsContent.scriptingRuntimeVersionLatest; - BuildDisabledEnumPopup(activeScriptingRuntime, SettingsContent.scriptingRuntimeVersionActive); - - EditorGUILayout.HelpBox(SettingsContent.scriptingRuntimeVersionActiveWarning.text, MessageType.Warning); - } + // Scripting Runtime Version + var scriptingRuntimeVersions = new[] {ScriptingRuntimeVersion.Legacy, ScriptingRuntimeVersion.Latest}; + var scriptingRuntimeVersionNames = new[] {SettingsContent.scriptingRuntimeVersionLegacy, SettingsContent.scriptingRuntimeVersionLatest}; + var newScriptingRuntimeVersions = PlayerSettings.scriptingRuntimeVersion; - if (newScriptingRuntimeVersions != PlayerSettings.scriptingRuntimeVersion) - { - if (newScriptingRuntimeVersions == EditorApplication.scriptingRuntimeVersion) + if (EditorApplication.isPlaying) { - PlayerSettings.scriptingRuntimeVersion = newScriptingRuntimeVersions; + var current = PlayerSettings.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy ? SettingsContent.scriptingRuntimeVersionLegacy : SettingsContent.scriptingRuntimeVersionLatest; + BuildDisabledEnumPopup(current, SettingsContent.scriptingRuntimeVersion); } else { - var currentScriptingRuntimeVersions = PlayerSettings.scriptingRuntimeVersion; - PlayerSettings.scriptingRuntimeVersion = newScriptingRuntimeVersions; + newScriptingRuntimeVersions = BuildEnumPopup(SettingsContent.scriptingRuntimeVersion, PlayerSettings.scriptingRuntimeVersion, scriptingRuntimeVersions, scriptingRuntimeVersionNames); + } - if (!PlayerSettings.RelaunchProjectIfScriptRuntimeVersionHasChanged()) - { - PlayerSettings.scriptingRuntimeVersion = currentScriptingRuntimeVersions; - } + if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) + { + EditorGUILayout.HelpBox(SettingsContent.scriptingRuntimeVersionDeprecationWarning.text, MessageType.Warning); } - } - // Scripting back-end - IScriptingImplementations scripting = ModuleManager.GetScriptingImplementations(targetGroup); - bool targetGroupSupportsIl2Cpp = false; - bool currentBackendIsIl2Cpp = false; + if (PlayerSettings.scriptingRuntimeVersion != EditorApplication.scriptingRuntimeVersion) + { + var activeScriptingRuntime = EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy ? SettingsContent.scriptingRuntimeVersionLegacy : SettingsContent.scriptingRuntimeVersionLatest; + BuildDisabledEnumPopup(activeScriptingRuntime, SettingsContent.scriptingRuntimeVersionActive); - if (scripting == null) - { - BuildDisabledEnumPopup(SettingsContent.scriptingDefault, SettingsContent.scriptingBackend); - } - else - { - var backends = scripting.Enabled(); + EditorGUILayout.HelpBox(SettingsContent.scriptingRuntimeVersionActiveWarning.text, MessageType.Warning); + } - foreach (var backend in backends) + if (newScriptingRuntimeVersions != PlayerSettings.scriptingRuntimeVersion) { - if (backend == ScriptingImplementation.IL2CPP) + if (newScriptingRuntimeVersions == EditorApplication.scriptingRuntimeVersion) { - targetGroupSupportsIl2Cpp = true; - break; + PlayerSettings.scriptingRuntimeVersion = newScriptingRuntimeVersions; + } + else + { + var currentScriptingRuntimeVersions = PlayerSettings.scriptingRuntimeVersion; + PlayerSettings.scriptingRuntimeVersion = newScriptingRuntimeVersions; + + if (!PlayerSettings.RelaunchProjectIfScriptRuntimeVersionHasChanged()) + { + PlayerSettings.scriptingRuntimeVersion = currentScriptingRuntimeVersions; + } } } - ScriptingImplementation currBackend = PlayerSettings.GetScriptingBackend(targetGroup); - currentBackendIsIl2Cpp = currBackend == ScriptingImplementation.IL2CPP; - ScriptingImplementation newBackend; - var mono2xDeprecated = targetGroup == BuildTargetGroup.iOS; + // Scripting back-end + IScriptingImplementations scripting = ModuleManager.GetScriptingImplementations(targetGroup); + bool targetGroupSupportsIl2Cpp = false; + bool currentBackendIsIl2Cpp = false; - if (targetGroup == BuildTargetGroup.tvOS) - { - newBackend = ScriptingImplementation.IL2CPP; - PlayerSettingsEditor.BuildDisabledEnumPopup(SettingsContent.scriptingIL2CPP, SettingsContent.scriptingBackend); - } - else if (backends.Length == 1) + if (scripting == null) { - newBackend = backends[0]; - BuildDisabledEnumPopup(GetNiceScriptingBackendName(backends[0], mono2xDeprecated), SettingsContent.scriptingBackend); + BuildDisabledEnumPopup(SettingsContent.scriptingDefault, SettingsContent.scriptingBackend); } else { - newBackend = BuildEnumPopup(SettingsContent.scriptingBackend, currBackend, backends, GetNiceScriptingBackendNames(backends, mono2xDeprecated)); - } + var backends = scripting.Enabled(); - if (targetGroup == BuildTargetGroup.iOS && newBackend == ScriptingImplementation.Mono2x) - { - EditorGUILayout.HelpBox(SettingsContent.monoNotSupportediOS11WarningGUIContent.text, MessageType.Warning); - } + foreach (var backend in backends) + { + if (backend == ScriptingImplementation.IL2CPP) + { + targetGroupSupportsIl2Cpp = true; + break; + } + } - if (newBackend != currBackend) - PlayerSettings.SetScriptingBackend(targetGroup, newBackend); - } + ScriptingImplementation currBackend = PlayerSettings.GetScriptingBackend(targetGroup); + currentBackendIsIl2Cpp = currBackend == ScriptingImplementation.IL2CPP; + ScriptingImplementation newBackend; + var mono2xDeprecated = targetGroup == BuildTargetGroup.iOS; + + if (targetGroup == BuildTargetGroup.tvOS) + { + newBackend = ScriptingImplementation.IL2CPP; + PlayerSettingsEditor.BuildDisabledEnumPopup(SettingsContent.scriptingIL2CPP, SettingsContent.scriptingBackend); + } + else if (backends.Length == 1) + { + newBackend = backends[0]; + BuildDisabledEnumPopup(GetNiceScriptingBackendName(backends[0], mono2xDeprecated), SettingsContent.scriptingBackend); + } + else + { + newBackend = BuildEnumPopup(SettingsContent.scriptingBackend, currBackend, backends, GetNiceScriptingBackendNames(backends, mono2xDeprecated)); + } - // Api Compatibility Level - var currentCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(targetGroup); - var availableCompatibilityLevels = GetAvailableApiCompatibilityLevels(targetGroup); + if (targetGroup == BuildTargetGroup.iOS && newBackend == ScriptingImplementation.Mono2x) + { + EditorGUILayout.HelpBox(SettingsContent.monoNotSupportediOS11WarningGUIContent.text, MessageType.Warning); + } + + if (newBackend != currBackend) + PlayerSettings.SetScriptingBackend(targetGroup, newBackend); + } - var newCompatibilityLevel = BuildEnumPopup(SettingsContent.apiCompatibilityLevel, currentCompatibilityLevel, availableCompatibilityLevels, GetNiceApiCompatibilityLevelNames(availableCompatibilityLevels)); + // Api Compatibility Level + var currentCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(targetGroup); + var availableCompatibilityLevels = GetAvailableApiCompatibilityLevels(targetGroup); - if (currentCompatibilityLevel != newCompatibilityLevel) - PlayerSettings.SetApiCompatibilityLevel(targetGroup, newCompatibilityLevel); + var newCompatibilityLevel = BuildEnumPopup(SettingsContent.apiCompatibilityLevel, currentCompatibilityLevel, availableCompatibilityLevels, GetNiceApiCompatibilityLevelNames(availableCompatibilityLevels)); - if (targetGroupSupportsIl2Cpp) - { - using (new EditorGUI.DisabledScope(!currentBackendIsIl2Cpp || !scripting.AllowIL2CPPCompilerConfigurationSelection())) + if (currentCompatibilityLevel != newCompatibilityLevel) + PlayerSettings.SetApiCompatibilityLevel(targetGroup, newCompatibilityLevel); + + if (targetGroupSupportsIl2Cpp) { - var currentConfiguration = PlayerSettings.GetIl2CppCompilerConfiguration(targetGroup); - var configurations = GetIl2CppCompilerConfigurations(); - var configurationNames = GetIl2CppCompilerConfigurationNames(); + using (new EditorGUI.DisabledScope(!currentBackendIsIl2Cpp || !scripting.AllowIL2CPPCompilerConfigurationSelection())) + { + var currentConfiguration = PlayerSettings.GetIl2CppCompilerConfiguration(targetGroup); + var configurations = GetIl2CppCompilerConfigurations(); + var configurationNames = GetIl2CppCompilerConfigurationNames(); - var newConfiguration = BuildEnumPopup(SettingsContent.il2cppCompilerConfiguration, currentConfiguration, configurations, configurationNames); + var newConfiguration = BuildEnumPopup(SettingsContent.il2cppCompilerConfiguration, currentConfiguration, configurations, configurationNames); - if (currentConfiguration != newConfiguration) - PlayerSettings.SetIl2CppCompilerConfiguration(targetGroup, newConfiguration); + if (currentConfiguration != newConfiguration) + PlayerSettings.SetIl2CppCompilerConfiguration(targetGroup, newConfiguration); + } } } diff --git a/Editor/Mono/PlayerSettingsAndroid.bindings.cs b/Editor/Mono/PlayerSettingsAndroid.bindings.cs index 6685deca5b..e904f27cff 100644 --- a/Editor/Mono/PlayerSettingsAndroid.bindings.cs +++ b/Editor/Mono/PlayerSettingsAndroid.bindings.cs @@ -399,14 +399,6 @@ public static extern bool startInFullscreen [NativeMethod("SetAndroidStartInFullscreen")] set; } - - public static extern int jvmMaxHeapSize - { - [NativeMethod("GetAndroidJvmMaxHeapSize")] - get; - [NativeMethod("SetAndroidJvmMaxHeapSize")] - set; - } } } } diff --git a/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs b/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs index e23f0caa92..e13f91687a 100644 --- a/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs +++ b/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs @@ -265,10 +265,6 @@ internal void NavigateBack(Analytics.ChangeType stageChangeAnalytics) var previousStage = m_NavigationHistory.GetPrevious(); SwitchToStage(previousStage, false, true, stageChangeAnalytics); } - else - { - Debug.LogError("Cannot navigate back"); - } } internal void GoToMainStage(bool setPreviousSelection, Analytics.ChangeType stageChangeAnalytics) @@ -469,8 +465,8 @@ static bool OnOpenAsset(int instanceID, int line) if (assetPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase)) { - // The 'line' parameter is used for passing an instance if entered from the Hierarchy or SceneView, otherwise it is -1 - GameObject instanceRoot = line == -1 ? null : (GameObject)EditorUtility.InstanceIDToObject(line); + // The 'line' parameter can be used for passing an instanceID of a prefab instance + GameObject instanceRoot = line == -1 ? null : EditorUtility.InstanceIDToObject(line) as GameObject; PrefabStageUtility.OpenPrefab(assetPath, instanceRoot, Analytics.ChangeType.EnterViaAssetOpened); return true; diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs index 2cf27b4719..9702700750 100644 --- a/Editor/Mono/SceneView/SceneView.cs +++ b/Editor/Mono/SceneView/SceneView.cs @@ -84,7 +84,7 @@ public static SceneView lastActiveSceneView public static SceneView currentDrawingSceneView { get { return s_CurrentDrawingSceneView; } } static readonly PrefColor kSceneViewBackground = new PrefColor("Scene/Background", 0.278431f, 0.278431f, 0.278431f, 0); - static readonly PrefColor kSceneViewPrefabBackground = new PrefColor("Scene/Background for Prefabs", 0.132f, 0.231f, 0.330f, 0); + internal static readonly PrefColor kSceneViewPrefabBackground = new PrefColor("Scene/Background for Prefabs", 0.132f, 0.231f, 0.330f, 0); static readonly PrefColor kSceneViewWire = new PrefColor("Scene/Wireframe", 0.0f, 0.0f, 0.0f, 0.5f); static readonly PrefColor kSceneViewWireOverlay = new PrefColor("Scene/Wireframe Overlay", 0.0f, 0.0f, 0.0f, 0.25f); 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); @@ -1349,66 +1349,61 @@ private void DoDrawCamera(Rect windowSpaceCameraRect, Rect groupSpaceCameraRect, void RenderFilteredScene(Rect groupSpaceCameraRect) { - var oldTargetTexture = m_Camera.targetTexture; - var oldDepthTextureMode = m_Camera.depthTextureMode; var oldRenderingPath = m_Camera.renderingPath; - // First pass: Draw the scene normally in destination render textsure + // First pass: Draw the scene normally in destination render texture, save color buffer for later DoClearCamera(groupSpaceCameraRect); Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); - // Second pass: Blit the scene faded out in a different render texture - var fadedDesc = m_SceneTargetTexture.descriptor; - var fadedRT = RenderTexture.GetTemporary(fadedDesc); - fadedRT.name = "FadedRT"; + var colorDesc = m_SceneTargetTexture.descriptor; + colorDesc.depthBufferBits = 0; + var colorRT = RenderTexture.GetTemporary(colorDesc); + colorRT.name = "SavedColorRT"; + Graphics.Blit(m_SceneTargetTexture, colorRT); + // Second pass: Blit the scene faded out in the scene target texture float fade = Mathf.Clamp01((float)(EditorApplication.timeSinceStartup - m_StartSearchFilterTime)); if (!s_FadeMaterial) s_FadeMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewGrayscaleEffectFade.mat") as Material; s_FadeMaterial.SetFloat("_Fade", fade); - Graphics.Blit(m_SceneTargetTexture, fadedRT, s_FadeMaterial); + Graphics.Blit(colorRT, m_SceneTargetTexture, s_FadeMaterial); - // Third pass: Draw aura for objects which meet the search filter, but are occluded. + // Third pass: Draw aura for objects which meet the search filter, but are occluded. Save color buffer for later. m_Camera.renderingPath = RenderingPath.Forward; if (!s_AuraShader) s_AuraShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewAura.shader") as Shader; m_Camera.SetReplacementShader(s_AuraShader, ""); - m_Camera.SetTargetBuffers(fadedRT.colorBuffer, m_SceneTargetTexture.depthBuffer); - m_Camera.depthTextureMode = DepthTextureMode.None; Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowFiltered); Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); - // Fourth pass: Draw objects which do meet filter in a mask - var maskDesc = m_SceneTargetTexture.descriptor; - maskDesc.colorFormat = RenderTextureFormat.R8; - maskDesc.depthBufferBits = 0; - var maskRT = RenderTexture.GetTemporary(maskDesc); - maskRT.name = "MaskRT"; + var fadedDesc = m_SceneTargetTexture.descriptor; + colorDesc.depthBufferBits = 0; + var fadedRT = RenderTexture.GetTemporary(fadedDesc); + fadedRT.name = "FadedColorRT"; + Graphics.Blit(m_SceneTargetTexture, fadedRT); - RenderTexture.active = maskRT; + // Fourth pass: Draw objects which do meet filter in a mask + RenderTexture.active = m_SceneTargetTexture; GL.Clear(false, true, Color.clear); if (!s_BuildFilterShader) s_BuildFilterShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewBuildFilter.shader") as Shader; m_Camera.SetReplacementShader(s_BuildFilterShader, ""); - m_Camera.SetTargetBuffers(maskRT.colorBuffer, m_SceneTargetTexture.depthBuffer); - m_Camera.depthTextureMode = DepthTextureMode.None; Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); // Final pass: Blit the faded scene where the mask isn't set if (!s_ApplyFilterMaterial) s_ApplyFilterMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewApplyFilter.mat") as Material; - s_ApplyFilterMaterial.SetTexture("_MaskTex", maskRT); - Graphics.Blit(fadedRT, m_SceneTargetTexture, s_ApplyFilterMaterial); + s_ApplyFilterMaterial.SetTexture("_MaskTex", m_SceneTargetTexture); + Graphics.Blit(fadedRT, colorRT, s_ApplyFilterMaterial); + Graphics.Blit(colorRT, m_SceneTargetTexture); - RenderTexture.ReleaseTemporary(maskRT); + RenderTexture.ReleaseTemporary(colorRT); RenderTexture.ReleaseTemporary(fadedRT); // Reset camera m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString); m_Camera.renderingPath = oldRenderingPath; - m_Camera.targetTexture = oldTargetTexture; - m_Camera.depthTextureMode = oldDepthTextureMode; if (fade < 1) Repaint(); diff --git a/Editor/Mono/Scripting/Compilers/BooCompiler.cs b/Editor/Mono/Scripting/Compilers/BooCompiler.cs index 91bc774c92..8cbb470b10 100644 --- a/Editor/Mono/Scripting/Compilers/BooCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/BooCompiler.cs @@ -23,19 +23,19 @@ override protected Program StartCompiler() { "-debug", "-target:library", - "-out:" + _island._output, + "-out:" + m_Island._output, "-x-type-inference-rule-attribute:" + typeof(UnityEngineInternal.TypeInferenceRuleAttribute) }; - foreach (string dll in _island._references) + foreach (string dll in m_Island._references) arguments.Add("-r:" + PrepareFileName(dll)); - foreach (string define in _island._defines.Distinct()) + foreach (string define in m_Island._defines.Distinct()) arguments.Add("-define:" + define); - foreach (string source in _island._files) + foreach (string source in m_Island._files) arguments.Add(PrepareFileName(source)); string compilerPath = Path.Combine(GetBooCompilerDirectory(), "booc.exe"); - return StartCompiler(_island._target, compilerPath, arguments, GetBooProfileDirectory()); + return StartCompiler(m_Island._target, compilerPath, arguments, GetBooProfileDirectory()); } protected override CompilerOutputParserBase CreateOutputParser() @@ -43,6 +43,11 @@ protected override CompilerOutputParserBase CreateOutputParser() return new BooCompilerOutputParser(); } + protected override string[] GetSystemReferenceDirectories() + { + return new[] { GetBooCompilerDirectory() }; + } + string GetBooCompilerDirectory() { if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) @@ -54,7 +59,7 @@ string GetBooCompilerDirectory() string GetBooProfileDirectory() { if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - return BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level); + return BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level); return k_UnityScriptProfileDirectory; } diff --git a/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs b/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs index 8d83e543ee..a3481ab119 100644 --- a/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs +++ b/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs @@ -56,45 +56,25 @@ public override bool CompilerRequiresAdditionalReferences() return true; } - public string GetNamespaceNewRuntime(string filePath, string definedSymbols) + static string[] GetSystemReferenceDirectories(ApiCompatibilityLevel apiCompatibilityLevel) { - var definedSymbolSplit = definedSymbols.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - string[] defines = null; - var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ReponseFilename); - try - { - var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile(responseFilePath); - defines = new string[responseFileData.Defines.Length + definedSymbolSplit.Length]; - Array.Copy(definedSymbolSplit, defines, definedSymbolSplit.Length); - Array.Copy(responseFileData.Defines, 0, defines, definedSymbolSplit.Length, responseFileData.Defines.Length); - } - catch (Exception e) - { - Debug.LogException(e); - } - - var uniqueSymbols = new HashSet(defines ?? definedSymbolSplit); - return CSharpNamespaceParser.GetNamespace(ReadAndConverteNewLines(filePath).ReadToEnd(), Path.GetFileNameWithoutExtension(filePath), uniqueSymbols.ToArray()); + return MonoLibraryHelpers.GetSystemReferenceDirectories(apiCompatibilityLevel); } - public string GetNamespaceOldRuntime(string filePath, string definedSymbols) + public string GetNamespaceNewRuntime(string filePath, string definedSymbols, string[] defines) { var definedSymbolSplit = definedSymbols.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - string[] defines = null; - var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ReponseFilename); - try - { - var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile(responseFilePath); - defines = new string[responseFileData.Defines.Length + definedSymbolSplit.Length]; - Array.Copy(definedSymbolSplit, defines, definedSymbolSplit.Length); - Array.Copy(responseFileData.Defines, 0, defines, definedSymbolSplit.Length, responseFileData.Defines.Length); - } - catch (Exception e) - { - Debug.LogException(e); - } + var uniqueSymbols = defines.Union(definedSymbolSplit).Distinct().ToArray(); + return CSharpNamespaceParser.GetNamespace( + ReadAndConverteNewLines(filePath).ReadToEnd(), + Path.GetFileNameWithoutExtension(filePath), + uniqueSymbols); + } - var uniqueSymbols = new HashSet(defines ?? definedSymbolSplit); + public string GetNamespaceOldRuntime(string filePath, string definedSymbols, string[] defines) + { + var definedSymbolSplit = definedSymbols.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var uniqueSymbols = defines.Union(definedSymbolSplit).Distinct().ToArray(); using (var parser = ParserFactory.CreateParser(ICSharpCode.NRefactory.SupportedLanguage.CSharp, ReadAndConverteNewLines(filePath))) { foreach (var symbol in uniqueSymbols) @@ -121,13 +101,22 @@ public string GetNamespaceOldRuntime(string filePath, string definedSymbols) public override string GetNamespace(string filePath, string definedSymbols) { + var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ResponseFilename); if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) { - return GetNamespaceNewRuntime(filePath, definedSymbols); + var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile( + responseFilePath, + Application.dataPath, + GetSystemReferenceDirectories(ApiCompatibilityLevel.NET_4_6)); + return GetNamespaceNewRuntime(filePath, definedSymbols, responseFileData.Defines); } else { - return GetNamespaceOldRuntime(filePath, definedSymbols); + var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile( + responseFilePath, + Application.dataPath, + GetSystemReferenceDirectories(ApiCompatibilityLevel.NET_2_0)); + return GetNamespaceOldRuntime(filePath, definedSymbols, responseFileData.Defines); } } diff --git a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs index fb95d0cfa4..5a19930cbc 100644 --- a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using UnityEditor.Modules; +using UnityEditor.Scripting.ScriptCompilation; using UnityEditor.Utils; using UnityEngine; @@ -21,18 +22,18 @@ public MicrosoftCSharpCompiler(MonoIsland island, bool runUpdater) : base(island { } - private BuildTarget BuildTarget { get { return _island._target; } } + BuildTarget BuildTarget => m_Island._target; - private string[] GetClassLibraries() + public static string[] GetClassLibraries(BuildTarget buildTarget) { - var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); + var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget); if (PlayerSettings.GetScriptingBackend(buildTargetGroup) != ScriptingImplementation.WinRTDotNET) { return new string[] {}; } - if (BuildTarget != BuildTarget.WSAPlayer) - throw new InvalidOperationException(string.Format("MicrosoftCSharpCompiler cannot build for .NET Scripting backend for BuildTarget.{0}.", BuildTarget)); + if (buildTarget != BuildTarget.WSAPlayer) + throw new InvalidOperationException($"MicrosoftCSharpCompiler cannot build for .NET Scripting backend for BuildTarget. {buildTarget}."); var resolver = new NuGetPackageResolver { ProjectLockFile = @"UWP\project.lock.json" }; return resolver.Resolve(); @@ -54,7 +55,7 @@ private void FillCompilerOptions(List arguments, out string argsPrefix) { var compilationExtension = platformSupportModule.CreateCompilationExtension(); - arguments.AddRange(GetClassLibraries().Select(r => "/reference:\"" + r + "\"")); + arguments.AddRange(GetClassLibraries(BuildTarget).Select(r => "/reference:\"" + r + "\"")); arguments.AddRange(compilationExtension.GetAdditionalAssemblyReferences().Select(r => "/reference:\"" + r + "\"")); arguments.AddRange(compilationExtension.GetWindowsMetadataReferences().Select(r => "/reference:\"" + r + "\"")); arguments.AddRange(compilationExtension.GetAdditionalDefines().Select(d => "/define:" + d)); @@ -69,14 +70,14 @@ private static void ThrowCompilerNotFoundException(string path) private Program StartCompilerImpl(List arguments, string argsPrefix) { - foreach (string dll in _island._references) + foreach (string dll in m_Island._references) arguments.Add("/reference:" + PrepareFileName(dll)); - foreach (string define in _island._defines.Distinct()) + foreach (string define in m_Island._defines.Distinct()) arguments.Add("/define:" + define); - var filePathMappings = new List(_island._files.Length); - foreach (var source in _island._files) + var filePathMappings = new List(m_Island._files.Length); + foreach (var source in m_Island._files) { var f = PrepareFileName(source); if (Application.platform == RuntimePlatform.WindowsEditor) @@ -117,7 +118,7 @@ private Program StartCompilerImpl(List arguments, string argsPrefix) if (!AddCustomResponseFileIfPresent(arguments, ReponseFilename) && PlayerSettings.GetScriptingBackend(buildTargetGroup) != ScriptingImplementation.WinRTDotNET) { if (AddCustomResponseFileIfPresent(arguments, "mcs.rsp")) - UnityEngine.Debug.LogWarning(string.Format("Using obsolete custom response file 'mcs.rsp'. Please use '{0}' instead.", ReponseFilename)); + UnityEngine.Debug.LogWarning($"Using obsolete custom response file 'mcs.rsp'. Please use '{ReponseFilename}' instead."); } var responseFile = CommandLineFormatter.GenerateResponseFile(arguments); @@ -168,7 +169,7 @@ static bool UseNetCoreCompiler() protected override Program StartCompiler() { - var outputPath = PrepareFileName(_island._output); + var outputPath = PrepareFileName(m_Island._output); // Always build with "/debug:pdbonly", "/optimize+", because even if the assembly is optimized // it seems you can still succesfully debug C# scripts in Visual Studio @@ -179,11 +180,11 @@ protected override Program StartCompiler() "/out:" + outputPath }; - if (_island._allowUnsafeCode) + if (m_Island._allowUnsafeCode) arguments.Add("/unsafe"); var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); - var disableOptimizations = _island._development_player || (_island._editor && EditorPrefs.GetBool("AllowAttachedDebuggingOfEditor", true)); + var disableOptimizations = m_Island._development_player || (m_Island._editor && EditorPrefs.GetBool("AllowAttachedDebuggingOfEditor", true)); if (!disableOptimizations) { if (PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.WinRTDotNET) @@ -206,6 +207,17 @@ protected override Program StartCompiler() return StartCompilerImpl(arguments, argsPrefix); } + protected override string[] GetSystemReferenceDirectories() + { + var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); + if (BuildTarget == BuildTarget.WSAPlayer && PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.WinRTDotNET) + { + return GetClassLibraries(BuildTarget).Select(library => Directory.GetParent(library).FullName).Distinct().ToArray(); + } + + return MonoLibraryHelpers.GetSystemReferenceDirectories(m_Island._api_compatibility_level); + } + protected override string[] GetStreamContainingCompilerMessages() { return GetStandardOutput(); diff --git a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs index 6572173376..f442a9f7b4 100644 --- a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs @@ -14,13 +14,13 @@ namespace UnityEditor.Scripting.Compilers { class MonoCSharpCompiler : MonoScriptCompilerBase { - public static readonly string ReponseFilename = "mcs.rsp"; + public static readonly string ResponseFilename = "mcs.rsp"; public MonoCSharpCompiler(MonoIsland island, bool runUpdater) : base(island, runUpdater) { } - override protected Program StartCompiler() + protected override Program StartCompiler() { var arguments = new List { @@ -28,23 +28,23 @@ override protected Program StartCompiler() "-target:library", "-nowarn:0169", "-langversion:" + ((EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) ? "6" : "4"), - "-out:" + PrepareFileName(_island._output), + "-out:" + PrepareFileName(m_Island._output), "-nostdlib", }; - if (_island._allowUnsafeCode) + if (m_Island._allowUnsafeCode) arguments.Add("-unsafe"); - if (!_island._development_player && !_island._editor) + if (!m_Island._development_player && !m_Island._editor) arguments.Add("-optimize"); - foreach (string dll in _island._references) + foreach (string dll in m_Island._references) arguments.Add("-r:" + PrepareFileName(dll)); - foreach (string define in _island._defines.Distinct()) + foreach (string define in m_Island._defines.Distinct()) arguments.Add("-define:" + define); - var pathMappings = new List(_island._files.Length); - foreach (string source in _island._files) + var pathMappings = new List(m_Island._files.Length); + foreach (string source in m_Island._files) { var preparedFileName = PrepareFileName(source); if (preparedFileName != source) @@ -53,35 +53,39 @@ override protected Program StartCompiler() arguments.Add(preparedFileName); } - if (!AddCustomResponseFileIfPresent(arguments, ReponseFilename)) + if (!AddCustomResponseFileIfPresent(arguments, ResponseFilename)) { - if (_island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0_Subset && AddCustomResponseFileIfPresent(arguments, "smcs.rsp")) - Debug.LogWarning(string.Format("Using obsolete custom response file 'smcs.rsp'. Please use '{0}' instead.", ReponseFilename)); - else if (_island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0 && AddCustomResponseFileIfPresent(arguments, "gmcs.rsp")) - Debug.LogWarning(string.Format("Using obsolete custom response file 'gmcs.rsp'. Please use '{0}' instead.", ReponseFilename)); + if (m_Island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0_Subset + && AddCustomResponseFileIfPresent(arguments, "smcs.rsp")) + { + Debug.LogWarning("Using obsolete custom response file \'smcs.rsp\'. " + + $"Please use '{ResponseFilename}' instead."); + } + else if (m_Island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0 + && AddCustomResponseFileIfPresent(arguments, "gmcs.rsp")) + { + Debug.LogWarning("Using obsolete custom response file \'gmcs.rsp\'. " + + $"Please use '{ResponseFilename}' instead."); + } } return StartCompiler( - _island._target, - GetCompilerPath(arguments), + m_Island._target, + GetCompilerPath(), arguments, - BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level), + BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level), false, MonoInstallationFinder.GetMonoInstallation(MonoInstallationFinder.MonoBleedingEdgeInstallation), pathMappings ); } - private string GetCompilerPath(List arguments) + static string GetCompilerPath() { string dir = MonoInstallationFinder.GetProfileDirectory("4.5", MonoInstallationFinder.MonoBleedingEdgeInstallation); var compilerPath = Path.Combine(dir, "mcs.exe"); if (File.Exists(compilerPath)) { - var systemAssemblyDirectory = MonoLibraryHelpers.GetSystemReferenceDirectory(_island._api_compatibility_level); - - if (!string.IsNullOrEmpty(systemAssemblyDirectory) && Directory.Exists(systemAssemblyDirectory)) - arguments.Add("-lib:" + PrepareFileName(systemAssemblyDirectory)); return compilerPath; } @@ -93,6 +97,11 @@ protected override CompilerOutputParserBase CreateOutputParser() return new MonoCSharpCompilerOutputParser(); } + protected override string[] GetSystemReferenceDirectories() + { + return MonoLibraryHelpers.GetSystemReferenceDirectories(m_Island._api_compatibility_level); + } + public static string[] Compile(string[] sources, string[] references, string[] defines, string outputFile, bool allowUnsafeCode) { var island = new MonoIsland(BuildTarget.StandaloneWindows, ApiCompatibilityLevel.NET_2_0_Subset, allowUnsafeCode, sources, references, defines, outputFile); diff --git a/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs index 52122f5232..6d919acd25 100644 --- a/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs @@ -16,14 +16,14 @@ protected MonoScriptCompilerBase(MonoIsland island, bool runUpdater) : base(isla protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments) { - return StartCompiler(target, compiler, arguments, BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level)); + return StartCompiler(target, compiler, arguments, BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level)); } protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments, string profileDirectory) { AddCustomResponseFileIfPresent(arguments, Path.GetFileNameWithoutExtension(compiler) + ".rsp"); - var monoInstallation = (PlayerSettingsEditor.IsLatestApiCompatibility(_island._api_compatibility_level)) + var monoInstallation = PlayerSettingsEditor.IsLatestApiCompatibility(m_Island._api_compatibility_level) ? MonoInstallationFinder.GetMonoBleedingEdgeInstallation() : MonoInstallationFinder.GetMonoInstallation(); return StartCompiler(target, compiler, arguments, profileDirectory, true, monoInstallation); diff --git a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs index fd3072da16..d140999018 100644 --- a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using UnityEditor.Scripting.ScriptCompilation; using UnityEngine; using UnityEditor.Utils; @@ -22,9 +23,10 @@ public class Reference } public string[] Defines; - public Reference[] References; + public Reference[] FullPathReferences; public bool Unsafe; public string[] Errors; + public string[] OtherArguments; } public class CompilerOption @@ -38,9 +40,10 @@ public class CompilerOption private Program process; private string _responseFile = null; private bool _runAPIUpdater; + string m_ProjectDirectory; // ToDo: would be nice to move MonoIsland to MonoScriptCompilerBase - protected MonoIsland _island; + protected MonoIsland m_Island; protected abstract Program StartCompiler(); @@ -48,8 +51,9 @@ public class CompilerOption protected ScriptCompilerBase(MonoIsland island, bool runAPIUpdater) { - _island = island; + m_Island = island; _runAPIUpdater = runAPIUpdater; + m_ProjectDirectory = Directory.GetParent(Application.dataPath).FullName.ConvertSeparatorsToUnity(); } protected string[] GetErrorOutput() @@ -98,15 +102,17 @@ public void WaitForCompilationToFinish() protected string GetMonoProfileLibDirectory() { - var profile = BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level); + var profile = BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level); - var monoInstall = (PlayerSettingsEditor.IsLatestApiCompatibility(_island._api_compatibility_level)) + var monoInstall = PlayerSettingsEditor.IsLatestApiCompatibility(m_Island._api_compatibility_level) ? MonoInstallationFinder.MonoBleedingEdgeInstallation : MonoInstallationFinder.MonoInstallation; return MonoInstallationFinder.GetProfileDirectory(profile, monoInstall); } + protected abstract string[] GetSystemReferenceDirectories(); + protected bool AddCustomResponseFileIfPresent(List arguments, string responseFileName) { var relativeCustomResponseFilePath = Path.Combine("Assets", responseFileName); @@ -114,19 +120,36 @@ protected bool AddCustomResponseFileIfPresent(List arguments, string res if (!File.Exists(relativeCustomResponseFilePath)) return false; - arguments.Add("@" + relativeCustomResponseFilePath); + var responseFileData = ParseResponseFileFromFile( + Path.Combine(m_ProjectDirectory, relativeCustomResponseFilePath), + Application.dataPath, + GetSystemReferenceDirectories()); + foreach (var error in responseFileData.Errors) + { + Debug.LogError($"{relativeCustomResponseFilePath} Parse Error : {error}"); + } + + arguments.AddRange(responseFileData.Defines.Distinct().Select(define => "/define:" + define)); + arguments.AddRange(responseFileData.FullPathReferences.Select(reference => + "/reference:" + PrepareFileName(reference.Assembly))); + + if (responseFileData.Unsafe) arguments.Add("/unsafe"); + arguments.AddRange(responseFileData.OtherArguments); return true; } - public static ResponseFileData ParseResponseFileFromFile(string responseFilePath) + public static ResponseFileData ParseResponseFileFromFile( + string responseFilePath, + string projectDirectory, + string[] systemReferenceDirectories) { if (!File.Exists(responseFilePath)) { var empty = new ResponseFileData { Defines = new string[0], - References = new ResponseFileData.Reference[0], + FullPathReferences = new ResponseFileData.Reference[0], Unsafe = false, Errors = new string[0] }; @@ -136,7 +159,11 @@ public static ResponseFileData ParseResponseFileFromFile(string responseFilePath var responseFileText = File.ReadAllText(responseFilePath); - return ParseResponseFileText(responseFileText); + return ParseResponseFileText( + responseFileText, + responseFilePath, + projectDirectory, + systemReferenceDirectories); } // From: @@ -204,7 +231,11 @@ static string[] ResponseFileTextToStrings(string responseFileText) return args.ToArray(); } - public static ResponseFileData ParseResponseFileText(string responseFileText) + static ResponseFileData ParseResponseFileText( + string responseFileText, + string responseFileName, + string projectDirectory, + string[] systemReferenceDirectories) { var compilerOptions = new List(); @@ -232,6 +263,7 @@ public static ResponseFileData ParseResponseFileText(string responseFileText) compilerOptions.Add(new CompilerOption { Arg = arg, Value = value }); } + var responseArguments = new List(); var defines = new List(); var references = new List(); bool unsafeDefined = false; @@ -276,24 +308,61 @@ public static ResponseFileData ParseResponseFileText(string responseFileText) break; } - foreach (string reference in refs) + var reference = refs[0]; + if (reference.Length == 0) { - if (reference.Length == 0) - continue; + continue; + } - int index = reference.IndexOf('='); - if (index > -1) - { - string alias = reference.Substring(0, index); - string assembly = reference.Substring(index + 1); + ResponseFileData.Reference responseReference; + + int index = reference.IndexOf('='); + if (index > -1) + { + string alias = reference.Substring(0, index); + string assembly = reference.Substring(index + 1); + + responseReference = new ResponseFileData.Reference { Alias = alias, Assembly = assembly }; + } + else + { + responseReference = new ResponseFileData.Reference { Alias = string.Empty, Assembly = reference }; + } - references.Add(new ResponseFileData.Reference { Alias = alias, Assembly = assembly }); + string fullPathReference = ""; + var referencePath = responseReference.Assembly; + if (Path.IsPathRooted(referencePath)) + { + fullPathReference = referencePath; + } + else + { + foreach (var directory in systemReferenceDirectories) + { + var systemReferencePath = Paths.Combine(directory, referencePath); + if (File.Exists(systemReferencePath)) + { + fullPathReference = systemReferencePath; + break; + } } - else + + var userPath = Paths.Combine(projectDirectory, referencePath); + if (File.Exists(userPath)) { - references.Add(new ResponseFileData.Reference { Alias = string.Empty, Assembly = reference }); + fullPathReference = userPath; } } + + if (fullPathReference == "") + { + errors.Add($"{responseFileName}: not parsed correctly: {responseReference.Assembly} could not be found as a system library.\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."); + continue; + } + + responseReference.Assembly = fullPathReference.Replace('\\', '/'); + references.Add(responseReference); } break; @@ -309,15 +378,20 @@ public static ResponseFileData ParseResponseFileText(string responseFileText) unsafeDefined = false; } break; + default: + var valueWithColon = value.Length == 0 ? "" : ":" + value; + responseArguments.Add(arg + valueWithColon); + break; } } var responseFileData = new ResponseFileData { Defines = defines.ToArray(), - References = references.ToArray(), + FullPathReferences = references.ToArray(), Unsafe = unsafeDefined, - Errors = errors.ToArray() + Errors = errors.ToArray(), + OtherArguments = responseArguments.ToArray(), }; return responseFileData; @@ -336,7 +410,11 @@ public virtual CompilerMessage[] GetCompilerMessages() DumpStreamOutputToLog(); - return CreateOutputParser().Parse(GetStreamContainingCompilerMessages(), CompilationHadFailure(), Path.GetFileName(_island._output)).ToArray(); + return CreateOutputParser().Parse( + GetStreamContainingCompilerMessages(), + CompilationHadFailure(), + Path.GetFileName(m_Island._output) + ).ToArray(); } protected bool CompilationHadFailure() @@ -367,7 +445,11 @@ private void DumpStreamOutputToLog() string[] stdOutput = GetStandardOutput(); - Console.WriteLine("-----CompilerOutput:-stdout--exitcode: " + process.ExitCode + "--compilationhadfailure: " + hadCompilationFailure + "--outfile: " + _island._output); + Console.WriteLine( + "-----CompilerOutput:-stdout--exitcode: " + process.ExitCode + + "--compilationhadfailure: " + hadCompilationFailure + + "--outfile: " + m_Island._output + ); foreach (string line in stdOutput) Console.WriteLine(line); @@ -386,7 +468,11 @@ protected void RunAPIUpdaterIfRequired(string responseFile, IList pathMa var pathMappingsFilePath = Path.GetTempFileName(); File.WriteAllLines(pathMappingsFilePath, pathMappings.ToArray()); - APIUpdaterHelper.UpdateScripts(responseFile, _island.GetExtensionOfSourceFiles(), PrepareFileName(pathMappingsFilePath)); + APIUpdaterHelper.UpdateScripts( + responseFile, + m_Island.GetExtensionOfSourceFiles(), + PrepareFileName(pathMappingsFilePath) + ); } } diff --git a/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs b/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs index 48b4ab118e..7b4c4c5809 100644 --- a/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs @@ -25,7 +25,7 @@ protected override CompilerOutputParserBase CreateOutputParser() return new UnityScriptCompilerOutputParser(); } - override protected Program StartCompiler() + protected override Program StartCompiler() { var arguments = new List { @@ -37,30 +37,30 @@ override protected Program StartCompiler() "-nowarn:BCW0016", "-nowarn:BCW0003", "-method:Main", - "-out:" + _island._output, + "-out:" + m_Island._output, "-x-type-inference-rule-attribute:" + typeof(UnityEngineInternal.TypeInferenceRuleAttribute) }; if (StrictBuildTarget()) arguments.Add("-pragmas:strict,downcast"); - foreach (var define in _island._defines.Distinct()) + foreach (var define in m_Island._defines.Distinct()) arguments.Add("-define:" + define); - foreach (var dll in _island._references) + foreach (var dll in m_Island._references) arguments.Add("-r:" + PrepareFileName(dll)); - var compilingEditorScripts = Array.Exists(_island._references, UnityEditorPattern.IsMatch); + var compilingEditorScripts = Array.Exists(m_Island._references, UnityEditorPattern.IsMatch); if (compilingEditorScripts) arguments.Add("-i:UnityEditor"); - else if (!BuildPipeline.IsUnityScriptEvalSupported(_island._target)) - arguments.Add(string.Format("-disable-eval:eval is not supported on the current build target ({0}).", _island._target)); + else if (!BuildPipeline.IsUnityScriptEvalSupported(m_Island._target)) + arguments.Add($"-disable-eval:eval is not supported on the current build target ({m_Island._target})."); - foreach (string source in _island._files) + foreach (string source in m_Island._files) arguments.Add(PrepareFileName(source)); var compilerPath = Path.Combine(GetUnityScriptCompilerDirectory(), "us.exe"); - return StartCompiler(_island._target, compilerPath, arguments, GetUnityScriptProfileDirectory()); + return StartCompiler(m_Island._target, compilerPath, arguments, GetUnityScriptProfileDirectory()); } string GetUnityScriptCompilerDirectory() @@ -74,14 +74,19 @@ string GetUnityScriptCompilerDirectory() string GetUnityScriptProfileDirectory() { if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - return BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level); + return BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level); return k_UnityScriptProfileDirectory; } private bool StrictBuildTarget() { - return Array.IndexOf(_island._defines, "ENABLE_DUCK_TYPING") == -1; + return Array.IndexOf(m_Island._defines, "ENABLE_DUCK_TYPING") == -1; + } + + protected override string[] GetSystemReferenceDirectories() + { + return new[] { GetUnityScriptCompilerDirectory() }; } protected override string[] GetStreamContainingCompilerMessages() diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs index f784520a09..1eccdccda8 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs @@ -769,6 +769,17 @@ static bool IsCompatibleWithPlatformAndDefines(TargetAssembly assembly, ScriptAs return assembly.IsCompatibleFunc == null || assembly.IsCompatibleFunc(settings, assembly.Defines); } + public static bool IsCompatibleWithPlatformAndDefines(TargetAssembly assembly, BuildTarget buildTarget, EditorScriptCompilationOptions options) + { + var settings = new ScriptAssemblySettings + { + BuildTarget = buildTarget, + CompilationOptions = options + }; + + return IsCompatibleWithPlatformAndDefines(assembly, settings); + } + internal static TargetAssembly[] CreatePredefinedTargetAssemblies() { var runtimeFirstPassAssemblies = new List(); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index 6cab818501..5f5e896a54 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -240,6 +240,23 @@ public void DirtyScript(string path) dirtyScripts.Add(path); } + public void DirtyMovedScript(string oldPath, string newPath) + { + DirtyScript(newPath); + + var targetAssembly = EditorBuildRules.GetTargetAssembly(oldPath, projectDirectory, customTargetAssemblies); + + // The target assembly might not exist any more. + if (targetAssembly == null) + { + areAllScriptsDirty = true; + } + else + { + dirtyTargetAssemblies.Add(targetAssembly); + } + } + public void DirtyRemovedScript(string path) { allScripts.Remove(path); @@ -354,7 +371,7 @@ public PrecompiledAssembly[] GetAllPrecompiledAssemblies() return this.precompiledAssemblies; } - public TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies(out CustomScriptAssemblyAndReference[] assembliesWithMissingReference) + public TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies(EditorScriptCompilationOptions options, BuildTarget buildTarget, out CustomScriptAssemblyAndReference[] assembliesWithMissingReference) { if (customTargetAssemblies == null) { @@ -393,6 +410,11 @@ public TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies(out // of compiled assemblies. foreach (var reference in assembly.References) { + // Don't check references that are not compatible with the current build target, + // as those assemblies have not been compiled. + if (!EditorBuildRules.IsCompatibleWithPlatformAndDefines(reference, buildTarget, options)) + continue; + if (!customTargetAssemblyCompiledPaths.ContainsKey(reference)) { customTargetAssemblyCompiledPaths.Remove(assembly); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs index c30ab10805..e51ed2fc6c 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs @@ -155,6 +155,12 @@ public static void DirtyRemovedScript(string path) Instance.DirtyRemovedScript(path); } + [RequiredByNativeCode] + public static void DirtyMovedScript(string oldPath, string newPath) + { + Instance.DirtyMovedScript(oldPath, newPath); + } + [RequiredByNativeCode] public static void DirtyPrecompiledAssembly(string path) { @@ -210,11 +216,11 @@ public static void SetAllPackageAssemblies(EditorCompilation.PackageAssembly[] p } [RequiredByNativeCode] - public static EditorCompilation.TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies() + public static EditorCompilation.TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies(EditorScriptCompilationOptions options, BuildTarget buildTarget) { EditorCompilation.CustomScriptAssemblyAndReference[] assembliesWithMissingReference = null; - var result = EmitExceptionAsError(() => Instance.GetAllCompiledAndResolvedCustomTargetAssemblies(out assembliesWithMissingReference), new EditorCompilation.TargetAssemblyInfo[0]); + var result = EmitExceptionAsError(() => Instance.GetAllCompiledAndResolvedCustomTargetAssemblies(options, buildTarget, out assembliesWithMissingReference), new EditorCompilation.TargetAssemblyInfo[0]); if (assembliesWithMissingReference.Length > 0) { diff --git a/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs b/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs index f5578f113f..ecf78af84d 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs @@ -33,6 +33,16 @@ public static string[] GetSystemLibraryReferences(ApiCompatibilityLevel apiCompa return GetCachedSystemLibraryReferences(apiCompatibilityLevel); } + static string[] FindReferencesInDirectories(this string[] references, string[] directories) + { + return ( + from reference in references + from directory in directories + where File.Exists(Path.Combine(directory, reference)) + select Path.Combine(directory, reference) + ).ToArray(); + } + static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompatibilityLevel) { // We cache the references because they are computed by getting files in directories on disk, @@ -43,7 +53,7 @@ static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompat } var references = new List(); - var monoAssemblyDirectory = GetSystemReferenceDirectory(apiCompatibilityLevel); + var monoAssemblyDirectories = GetSystemReferenceDirectories(apiCompatibilityLevel); if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) { @@ -51,19 +61,20 @@ static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompat } else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) { - references.AddRange(GetSystemReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); - references.AddRange(GetNet46SystemReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); + references.AddRange(GetSystemReferences().FindReferencesInDirectories(monoAssemblyDirectories)); + references.AddRange(GetNet46SystemReferences().FindReferencesInDirectories(monoAssemblyDirectories)); // Look in the mono assembly directory for a facade folder and get a list of all the DLL's to be // used later by the language compilers. + var monoAssemblyDirectory = MonoInstallationFinder.GetProfileDirectory("4.7.1-api", MonoInstallationFinder.MonoBleedingEdgeInstallation); references.AddRange(Directory.GetFiles(Path.Combine(monoAssemblyDirectory, "Facades"), "*.dll")); references.AddRange(GetBooAndUsReferences().Select(dll => Path.Combine(MonoInstallationFinder.GetProfileDirectory("unityscript", MonoInstallationFinder.MonoBleedingEdgeInstallation), dll))); } else { - references.AddRange(GetSystemReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); - references.AddRange(GetBooAndUsReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); + references.AddRange(GetSystemReferences().FindReferencesInDirectories(monoAssemblyDirectories)); + references.AddRange(GetBooAndUsReferences().FindReferencesInDirectories(monoAssemblyDirectories)); } cachedReferences = new CachedReferences @@ -76,18 +87,40 @@ static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompat return cachedReferences.References; } - public static string GetSystemReferenceDirectory(ApiCompatibilityLevel apiCompatibilityLevel) + static string GetSystemReference(ApiCompatibilityLevel apiCompatibilityLevel) { - if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) - return ""; - else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) + if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) return MonoInstallationFinder.GetProfileDirectory("4.7.1-api", MonoInstallationFinder.MonoBleedingEdgeInstallation); - else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_2_0) + if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_2_0) return MonoInstallationFinder.GetProfileDirectory("2.0-api", MonoInstallationFinder.MonoBleedingEdgeInstallation); return MonoInstallationFinder.GetProfileDirectory(BuildPipeline.CompatibilityProfileToClassLibFolder(apiCompatibilityLevel), MonoInstallationFinder.MonoBleedingEdgeInstallation); } + public static string[] GetSystemReferenceDirectories(ApiCompatibilityLevel apiCompatibilityLevel) + { + if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) + { + var systemReferenceDirectories = new List(); + systemReferenceDirectories.Add(NetStandardFinder.GetReferenceDirectory()); + systemReferenceDirectories.Add(NetStandardFinder.GetNetStandardCompatShimsDirectory()); + systemReferenceDirectories.Add(NetStandardFinder.GetNetStandardExtensionsDirectory()); + systemReferenceDirectories.Add(NetStandardFinder.GetDotNetFrameworkCompatShimsDirectory()); + return systemReferenceDirectories.ToArray(); + } + + if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) + { + var systemReferenceDirectories = new List(); + var frameworkDirectory = GetSystemReference(apiCompatibilityLevel); + systemReferenceDirectories.Add(frameworkDirectory); + systemReferenceDirectories.Add(Path.Combine(frameworkDirectory, "Facades")); + return systemReferenceDirectories.ToArray(); + } + + return new[] { GetSystemReference(apiCompatibilityLevel) }; + } + static string[] GetNetStandardClassLibraries() { var classLibraries = new List(); @@ -125,7 +158,10 @@ static string[] GetNet46SystemReferences() return new[] { "System.Numerics.dll", - "System.Numerics.Vectors.dll" + "System.Numerics.Vectors.dll", + "System.Net.Http.dll", + "Microsoft.CSharp.dll", + "System.Data.dll", }; } diff --git a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs index 7063a34d06..c1c276d9e1 100644 --- a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs +++ b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs @@ -102,5 +102,11 @@ public override void OnTitleBarGUI() } } } + + public override void OnFooterBarGUI() + { + if (m_SettingsEditor != null) + InspectorWindow.DrawVCSShortInfo(settingsWindow, m_SettingsEditor); + } } } diff --git a/Editor/Mono/Settings/SettingsProvider.cs b/Editor/Mono/Settings/SettingsProvider.cs index 622bdcdb43..c41f58ca89 100644 --- a/Editor/Mono/Settings/SettingsProvider.cs +++ b/Editor/Mono/Settings/SettingsProvider.cs @@ -69,6 +69,7 @@ public string label public Action guiHandler { get; set; } public Action titleBarGuiHandler { get; set; } + public Action footerBarGuiHandler { get; set; } public Action activateHandler { get; set; } public Action deactivateHandler { get; set; } public Func hasSearchInterestHandler { get; set; } @@ -119,6 +120,11 @@ public virtual void OnTitleBarGUI() titleBarGuiHandler?.Invoke(); } + public virtual void OnFooterBarGUI() + { + footerBarGuiHandler?.Invoke(); + } + public void PopulateSearchKeywordsFromGUIContentProperties() { GetSearchKeywordsFromGUIContentProperties(keywords); diff --git a/Editor/Mono/Settings/SettingsWindow.cs b/Editor/Mono/Settings/SettingsWindow.cs index e69757227e..cf6b61a8ba 100644 --- a/Editor/Mono/Settings/SettingsWindow.cs +++ b/Editor/Mono/Settings/SettingsWindow.cs @@ -275,19 +275,22 @@ private void DrawToolbar() private void DrawSettingsPanel() { + if (m_TreeView.currentProvider == null) + return; + + DrawTitleBar(); + using (var scrollViewScope = new EditorGUILayout.ScrollViewScope(m_PosRight, GUILayout.ExpandWidth(true))) { m_PosRight = scrollViewScope.scrollPosition; DrawControls(); } + + DrawFooterBar(); } private void DrawControls() { - if (m_TreeView.currentProvider == null) - return; - - DrawTitleBar(); using (new EditorGUI.LabelHighlightScope(m_SearchText, Styles.settingsPanel.GetColor("-unity-search-highlight-selection-color"), Styles.settingsPanel.GetColor("-unity-search-highlight-color"))) m_TreeView.currentProvider.OnGUI(m_SearchText); } @@ -303,6 +306,11 @@ private void DrawTitleBar() GUILayout.EndHorizontal(); } + private void DrawFooterBar() + { + m_TreeView.currentProvider.OnFooterBarGUI(); + } + private void DrawTreeView() { var splitterRect = m_Splitter.GetSplitterRect(m_Splitter.Children().First()); diff --git a/Editor/Mono/Utils/DirectoryExtensions.cs b/Editor/Mono/Utils/DirectoryExtensions.cs index 7079909df6..609bbae427 100644 --- a/Editor/Mono/Utils/DirectoryExtensions.cs +++ b/Editor/Mono/Utils/DirectoryExtensions.cs @@ -6,7 +6,7 @@ namespace UnityEditor.Utils { - internal static class DirectoryExtensions + static class DirectoryExtensions { public static void DeleteRecursive(this string directoryPath) { diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index f7ab82ff33..998704dfca 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -18,8 +18,8 @@ using UnityEditorInternal; using UnityEditor.Scripting.Compilers; -using Mono.Cecil; using UnityEditor.Compilation; +using UnityEditor.Modules; namespace UnityEditor.VisualStudioIntegration { @@ -233,25 +233,44 @@ internal void GenerateAndWriteSolutionAndProjects(ScriptEditorUtility.ScriptEdit var allAssetProjectParts = GenerateAllAssetProjectParts(); - var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ReponseFilename); + var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ResponseFilename); - var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile(Path.Combine(_projectDirectory, responseFilePath)); + var monoIslands = islands.ToList(); - if (responseFileData.Errors.Length > 0) - { - foreach (var error in responseFileData.Errors) - UnityEngine.Debug.LogErrorFormat("{0} Parse Error : {1}", responseFilePath, error); - } - SyncSolution(islands); - var allProjectIslands = RelevantIslandsForMode(islands, ModeForCurrentExternalEditor()).ToList(); + SyncSolution(monoIslands); + var allProjectIslands = RelevantIslandsForMode(monoIslands, ModeForCurrentExternalEditor()).ToList(); foreach (MonoIsland island in allProjectIslands) + { + var responseFileData = parseResponseFileData(island, responseFilePath); SyncProject(island, allAssetProjectParts, responseFileData, allProjectIslands); + } if (scriptEditor == ScriptEditorUtility.ScriptEditor.VisualStudioCode) WriteVSCodeSettingsFiles(); } + ScriptCompilerBase.ResponseFileData parseResponseFileData(MonoIsland island, string responseFilePath) + { + var systemReferenceDirectories = CSharpLanguage.GetCSharpCompiler(island._target, true, "Assembly-CSharp") == CSharpCompiler.Microsoft + && PlayerSettings.GetScriptingBackend(BuildPipeline.GetBuildTargetGroup(island._target)) == ScriptingImplementation.WinRTDotNET + ? MicrosoftCSharpCompiler.GetClassLibraries(island._target) + : MonoLibraryHelpers.GetSystemReferenceDirectories(island._api_compatibility_level); + + ScriptCompilerBase.ResponseFileData responseFileData = ScriptCompilerBase.ParseResponseFileFromFile( + Path.Combine(_projectDirectory, responseFilePath), + _projectDirectory, + systemReferenceDirectories); + + if (responseFileData.Errors.Length > 0) + { + foreach (var error in responseFileData.Errors) + UnityEngine.Debug.LogErrorFormat("{0} Parse Error : {1}", responseFilePath, error); + } + + return responseFileData; + } + Dictionary GenerateAllAssetProjectParts() { Dictionary stringBuilders = new Dictionary(); @@ -401,8 +420,9 @@ string ProjectText(MonoIsland island, projectBuilder.Append(additionalAssetsForProject); var allAdditionalReferenceFilenames = new List(); + var islandRefs = references.Union(island._references); - foreach (string reference in references.Union(island._references).Union(responseFileData.References.Select(r => r.Assembly))) + foreach (string reference in islandRefs) { if (reference.EndsWith("/UnityEditor.dll") || reference.EndsWith("/UnityEngine.dll") || reference.EndsWith("\\UnityEditor.dll") || reference.EndsWith("\\UnityEngine.dll")) continue; @@ -439,13 +459,13 @@ string ProjectText(MonoIsland island, allAdditionalReferenceFilenames.Add(referenceName); } - //replace \ with / and \\ with / - var escapedFullPath = SecurityElement.Escape(fullReference); - escapedFullPath = escapedFullPath.Replace("\\", "/"); - escapedFullPath = escapedFullPath.Replace("\\\\", "/"); - projectBuilder.AppendFormat(" {1}", Path.GetFileNameWithoutExtension(escapedFullPath), WindowsNewline); - projectBuilder.AppendFormat(" {0}{1}", escapedFullPath, WindowsNewline); - projectBuilder.AppendFormat(" {0}", WindowsNewline); + AppendReference(fullReference, projectBuilder); + } + + var responseRefs = responseFileData.FullPathReferences.Select(r => r.Assembly); + foreach (var reference in responseRefs) + { + AppendReference(reference, projectBuilder); } if (0 < projectReferences.Count) @@ -472,6 +492,17 @@ string ProjectText(MonoIsland island, return projectBuilder.ToString(); } + static void AppendReference(string fullReference, StringBuilder projectBuilder) + { + //replace \ with / and \\ with / + var escapedFullPath = SecurityElement.Escape(fullReference); + escapedFullPath = escapedFullPath.Replace("\\", "/"); + escapedFullPath = escapedFullPath.Replace("\\\\", "/"); + projectBuilder.AppendFormat(" {1}", Path.GetFileNameWithoutExtension(escapedFullPath), WindowsNewline); + projectBuilder.AppendFormat(" {0}{1}", escapedFullPath, WindowsNewline); + projectBuilder.AppendFormat(" {0}", WindowsNewline); + } + public string ProjectFile(MonoIsland island) { ScriptingLanguage language = ScriptingLanguageFor(island); @@ -504,7 +535,7 @@ private string ProjectHeader(MonoIsland island, { targetframeworkversion = "v4.7.1"; } - targetLanguageVersion = "7.3"; + targetLanguageVersion = "latest"; } else if (_settings.VisualStudioVersion == 9) { diff --git a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs index eec3acf2ce..82b85d1157 100644 --- a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs +++ b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs @@ -22,19 +22,21 @@ static class Styles { public static readonly GUIContent singlepassAndroidWarning = EditorGUIUtility.TrTextContent("Single Pass stereo rendering requires OpenGL ES 3. Please make sure that it's the first one listed under Graphics APIs."); public static readonly GUIContent singlepassAndroidWarning2 = EditorGUIUtility.TrTextContent("Multi Pass will be used on Android devices that don't support Single Pass."); + public static readonly GUIContent singlepassAndroidWarning3 = EditorGUIUtility.TrTextContent("When using a Scriptable Render Pipeline, Single Pass Double Wide will be used on Android devices that don't support Single Pass Instancing or Multi-view."); public static readonly GUIContent singlePassInstancedWarning = EditorGUIUtility.TrTextContent("Single Pass Instanced is only supported on Windows. Multi Pass will be used on other platforms."); + public static readonly GUIContent multiPassNotSupportedWithSRP = EditorGUIUtility.TrTextContent("Multi Pass is only supported using the legacy render pipelies. Stereo Rendering Mode is set to the fallback mode of Single Pass."); public static readonly GUIContent[] kDefaultStereoRenderingPaths = { EditorGUIUtility.TrTextContent("Multi Pass"), EditorGUIUtility.TrTextContent("Single Pass"), - EditorGUIUtility.TrTextContent("Single Pass Instanced (Preview)") + EditorGUIUtility.TrTextContent("Single Pass Instanced") }; public static readonly GUIContent[] kMultiviewStereoRenderingPaths = { EditorGUIUtility.TrTextContent("Multi Pass"), - EditorGUIUtility.TrTextContent("Single Pass Multiview or Instanced (Preview)") + EditorGUIUtility.TrTextContent("Single Pass") }; public static readonly GUIContent xrSettingsTitle = EditorGUIUtility.TrTextContent("XR Settings"); @@ -60,6 +62,7 @@ static class Styles private bool m_InstallsRequired = false; private bool m_VuforiaInstalled = false; + private bool m_ShowMultiPassSRPInfoBox = false; internal int GUISectionIndex { get; set; } @@ -305,16 +308,44 @@ private static GUIContent[] GetStereoRenderingPaths(BuildTargetGroup targetGroup return DoesBuildTargetSupportStereoMultiviewRendering(targetGroup) ? Styles.kMultiviewStereoRenderingPaths : Styles.kDefaultStereoRenderingPaths; } + private bool IsStereoRenderingModeSupported(BuildTargetGroup targetGroup, StereoRenderingPath stereoRenderingPath) + { + switch (stereoRenderingPath) + { + case StereoRenderingPath.MultiPass: + return (UnityEngine.Rendering.GraphicsSettings.renderPipelineAsset == null); + + case StereoRenderingPath.SinglePass: + return DoesBuildTargetSupportSinglePassStereoRendering(targetGroup); + + case StereoRenderingPath.Instancing: + return DoesBuildTargetSupportStereoInstancingRendering(targetGroup); + } + ; + + return false; + } + + void OnStereoModeSelected(SerializedProperty stereoRenderingPath, object userData) + { + stereoRenderingPath.intValue = (int)userData; + m_ShowMultiPassSRPInfoBox = false; + + m_Settings.serializedObject.ApplyModifiedProperties(); + } + private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedProperty stereoRenderingPath) { if (!PlayerSettings.virtualRealitySupported) return; - bool supportsSinglePass = DoesBuildTargetSupportSinglePassStereoRendering(targetGroup); - bool supportsSinglePassInstanced = DoesBuildTargetSupportStereoInstancingRendering(targetGroup); + bool supportsMultiPass = IsStereoRenderingModeSupported(targetGroup, StereoRenderingPath.MultiPass); + bool supportsSinglePass = IsStereoRenderingModeSupported(targetGroup, StereoRenderingPath.SinglePass); + bool supportsSinglePassInstanced = IsStereoRenderingModeSupported(targetGroup, StereoRenderingPath.Instancing); // populate the dropdown with the valid options based on target platform. - int validStereoRenderingOptionsCount = 1 + (supportsSinglePass ? 1 : 0) + (supportsSinglePassInstanced ? 1 : 0); + int multiPassAndSinglePass = 2; + int validStereoRenderingOptionsCount = multiPassAndSinglePass + (supportsSinglePassInstanced ? 1 : 0); var validStereoRenderingPaths = new GUIContent[validStereoRenderingOptionsCount]; var validStereoRenderingValues = new int[validStereoRenderingOptionsCount]; @@ -324,11 +355,8 @@ private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedPropert validStereoRenderingPaths[addedStereoRenderingOptionsCount] = stereoRenderingPaths[(int)StereoRenderingPath.MultiPass]; validStereoRenderingValues[addedStereoRenderingOptionsCount++] = (int)StereoRenderingPath.MultiPass; - if (supportsSinglePass) - { - validStereoRenderingPaths[addedStereoRenderingOptionsCount] = stereoRenderingPaths[(int)StereoRenderingPath.SinglePass]; - validStereoRenderingValues[addedStereoRenderingOptionsCount++] = (int)StereoRenderingPath.SinglePass; - } + validStereoRenderingPaths[addedStereoRenderingOptionsCount] = stereoRenderingPaths[(int)StereoRenderingPath.SinglePass]; + validStereoRenderingValues[addedStereoRenderingOptionsCount++] = (int)StereoRenderingPath.SinglePass; if (supportsSinglePassInstanced) { @@ -337,20 +365,56 @@ private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedPropert } // setup fallbacks + if (!supportsMultiPass && (stereoRenderingPath.intValue == (int)StereoRenderingPath.MultiPass)) + { + stereoRenderingPath.intValue = (int)StereoRenderingPath.SinglePass; + m_ShowMultiPassSRPInfoBox = true; + } + if (!supportsSinglePassInstanced && (stereoRenderingPath.intValue == (int)StereoRenderingPath.Instancing)) stereoRenderingPath.intValue = (int)StereoRenderingPath.SinglePass; if (!supportsSinglePass && (stereoRenderingPath.intValue == (int)StereoRenderingPath.SinglePass)) stereoRenderingPath.intValue = (int)StereoRenderingPath.MultiPass; - EditorGUILayout.IntPopup(stereoRenderingPath, validStereoRenderingPaths, validStereoRenderingValues, EditorGUIUtility.TrTextContent("Stereo Rendering Mode*")); + if (m_ShowMultiPassSRPInfoBox) + EditorGUILayout.HelpBox(Styles.multiPassNotSupportedWithSRP.text, MessageType.Info); + + var rect = EditorGUILayout.GetControlRect(); + EditorGUI.BeginProperty(rect, EditorGUIUtility.TrTextContent("Stereo Rendering Mode*"), stereoRenderingPath); + rect = EditorGUI.PrefixLabel(rect, EditorGUIUtility.TrTextContent("Stereo Rendering Mode*")); + + int index = Math.Max(0, Array.IndexOf(validStereoRenderingValues, stereoRenderingPath.intValue)); + if (EditorGUI.DropdownButton(rect, validStereoRenderingPaths[index], FocusType.Passive)) + { + var menu = new GenericMenu(); + for (int i = 0; i < validStereoRenderingValues.Length; i++) + { + int value = validStereoRenderingValues[i]; + bool selected = (value == stereoRenderingPath.intValue); + + if (!IsStereoRenderingModeSupported(targetGroup, (StereoRenderingPath)value)) + menu.AddDisabledItem(validStereoRenderingPaths[i], selected); + else + menu.AddItem(validStereoRenderingPaths[i], selected, (object userData) => { OnStereoModeSelected(stereoRenderingPath, userData); }, value); + } + menu.DropDown(rect); + } + EditorGUI.EndProperty(); if ((stereoRenderingPath.intValue == (int)StereoRenderingPath.SinglePass) && (targetGroup == BuildTargetGroup.Android)) { var apisAndroid = PlayerSettings.GetGraphicsAPIs(BuildTarget.Android); if ((apisAndroid.Length > 0) && (apisAndroid[0] == GraphicsDeviceType.OpenGLES3)) { - EditorGUILayout.HelpBox(Styles.singlepassAndroidWarning2.text, MessageType.Info); + if (supportsMultiPass) + { + EditorGUILayout.HelpBox(Styles.singlepassAndroidWarning2.text, MessageType.Info); + } + else + { + EditorGUILayout.HelpBox(Styles.singlepassAndroidWarning3.text, MessageType.Info); + } } else { @@ -361,6 +425,8 @@ private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedPropert { EditorGUILayout.HelpBox(Styles.singlePassInstancedWarning.text, MessageType.Warning); } + + m_Settings.serializedObject.ApplyModifiedProperties(); } private void Stereo360CaptureGUI(BuildTargetGroup targetGroup) @@ -577,18 +643,6 @@ internal void TangoGUI(BuildTargetGroup targetGroup) // Google Tango settings EditorGUILayout.PropertyField(m_AndroidEnableTango, EditorGUIUtility.TrTextContent("ARCore Supported")); - - if (PlayerSettings.Android.ARCoreEnabled) - { - EditorGUI.indentLevel++; - - if ((int)PlayerSettings.Android.minSdkVersion < 24) - { - GUIContent tangoAndroidWarning = EditorGUIUtility.TrTextContent("ARCore requires 'Minimum API Level' to be at least Android 7.0"); - EditorGUILayout.HelpBox(tangoAndroidWarning.text, MessageType.Warning); - } - EditorGUI.indentLevel--; - } } internal void VuforiaGUI(BuildTargetGroup targetGroup) diff --git a/Modules/ShortcutManagerEditor/Trigger.cs b/Modules/ShortcutManagerEditor/Trigger.cs index 28201c667a..87358087be 100644 --- a/Modules/ShortcutManagerEditor/Trigger.cs +++ b/Modules/ShortcutManagerEditor/Trigger.cs @@ -126,6 +126,7 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) if (HasConflicts(entries, m_KeyCombinationSequence)) { m_ConflictResolver.ResolveConflict(m_KeyCombinationSequence, entries); + evt.Use(); Reset(); } break; diff --git a/Modules/Terrain/Public/BrushTransform.cs b/Modules/Terrain/Public/BrushTransform.cs new file mode 100644 index 0000000000..229d3b07ea --- /dev/null +++ b/Modules/Terrain/Public/BrushTransform.cs @@ -0,0 +1,80 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using UnityEngine.Rendering; + +namespace UnityEngine.Experimental.TerrainAPI +{ + // represents a linear 2D transform between brush UV space and some other target XY space + // xy = u * brushU + v * brushV + brushOrigin + // uv = x * targetX + y * targetY + targetOrigin + public struct BrushTransform + { + public Vector2 brushOrigin { get; } // brush UV origin, in XY space + public Vector2 brushU { get; } // brush U vector, in XY space + public Vector2 brushV { get; } // brush V vector, in XY space + + public Vector2 targetOrigin { get; } // XY origin, in brush UV space + public Vector2 targetX { get; } // X vector, in brush UV space + public Vector2 targetY { get; } // Y vector, in brush UV space + + public BrushTransform(Vector2 brushOrigin, Vector2 brushU, Vector2 brushV) + { + // invert the rotation matrix [BrushU, BrushV] + // this gives us [X, Y] vectors in brush UV space + // note we run the true inverse, to support non-orthogonal brush axes + float det = brushU.x * brushV.y - brushU.y * brushV.x; + float invDet = Mathf.Approximately(det, 0.0f) ? 1.0f : 1.0f / det; // for non-invert-able matrices, we do 'something' + Vector2 targetX = new Vector2(brushV.y, -brushU.y) * invDet; + Vector2 targetY = new Vector2(-brushV.x, brushU.x) * invDet; + + // calculate XY origin in brush UV space + Vector2 targetOrigin = -brushOrigin.x * targetX - brushOrigin.y * targetY; + + this.brushOrigin = brushOrigin; + this.brushU = brushU; + this.brushV = brushV; + this.targetOrigin = targetOrigin; + this.targetX = targetX; + this.targetY = targetY; + } + + public Rect GetBrushXYBounds() // get the XY bounding rectangle around the Brush [0,1] UV space + { + // compute all four corners of the brush [0,1] UV space + Vector2 pU = brushOrigin + brushU; + Vector2 pV = brushOrigin + brushV; + Vector2 pUV = brushOrigin + brushU + brushV; + + // compute min and max XY coordinates + float minX = Mathf.Min(Mathf.Min(brushOrigin.x, pU.x), Mathf.Min(pV.x, pUV.x)); + float maxX = Mathf.Max(Mathf.Max(brushOrigin.x, pU.x), Mathf.Max(pV.x, pUV.x)); + float minY = Mathf.Min(Mathf.Min(brushOrigin.y, pU.y), Mathf.Min(pV.y, pUV.y)); + float maxY = Mathf.Max(Mathf.Max(brushOrigin.y, pU.y), Mathf.Max(pV.y, pUV.y)); + + // return the XY bounding rectangle + return Rect.MinMaxRect(minX, minY, maxX, maxY); + } + + public static BrushTransform FromRect(Rect brushRect) + { + Vector2 brushOrigin = brushRect.min; + Vector2 brushU = new Vector2(brushRect.width, 0.0f); + Vector2 brushV = new Vector2(0.0f, brushRect.height); + return new BrushTransform(brushOrigin, brushU, brushV); + } + + public Vector2 ToBrushUV(Vector2 targetXY) + { + return targetXY.x * targetX + targetXY.y * targetY + targetOrigin; + } + + public Vector2 FromBrushUV(Vector2 brushUV) + { + return brushUV.x * brushU + brushUV.y * brushV + brushOrigin; + } + } +} diff --git a/Modules/Terrain/Public/PaintContext.cs b/Modules/Terrain/Public/PaintContext.cs new file mode 100644 index 0000000000..f85775e442 --- /dev/null +++ b/Modules/Terrain/Public/PaintContext.cs @@ -0,0 +1,632 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using UnityEngine.Rendering; + +namespace UnityEngine.Experimental.TerrainAPI +{ + public class PaintContext + { + // initialized by constructor + public Terrain originTerrain { get; } // the terrain that defines the coordinate system and world space position of this PaintContext + public RectInt pixelRect { get; } // the rectangle, in target texture pixels on the originTerrain, that this paint context represents + public int targetTextureWidth { get; } // the size of the target texture, per terrain tile + public int targetTextureHeight { get; } // the size of the target texture, per terrain tile + public Vector2 pixelSize { get; } // size of a paint context pixel in object/terrain/world space + + // initialized by CreateRenderTargets() + public RenderTexture sourceRenderTexture { get { return m_SourceRenderTexture; } } // the original data + public RenderTexture destinationRenderTexture { get { return m_DestinationRenderTexture; } } // the modified data (you render to this) + public RenderTexture oldRenderTexture { get { return m_OldRenderTexture; } } // active render texture at the time CreateRenderTargets() is called, restored on Cleanup() + + public int terrainCount { get { return m_TerrainTiles.Count; } } + public Terrain GetTerrain(int terrainIndex) + { + return m_TerrainTiles[terrainIndex].terrain; + } + + public RectInt GetClippedPixelRectInTerrainPixels(int terrainIndex) + { + return m_TerrainTiles[terrainIndex].clippedLocal; + } + + public RectInt GetClippedPixelRectInRenderTexturePixels(int terrainIndex) + { + Rect vp = m_TerrainTiles[terrainIndex].validPaintRect; + return new RectInt( + Mathf.RoundToInt(vp.xMin), + Mathf.RoundToInt(vp.yMin), + Mathf.RoundToInt(vp.width), + Mathf.RoundToInt(vp.height)); + } + + // initialized by constructor + private List m_TerrainTiles; // all terrain tiles touched by this paint context + + // initialized by CreateRenderTargets() + private RenderTexture m_SourceRenderTexture; + private RenderTexture m_DestinationRenderTexture; + private RenderTexture m_OldRenderTexture; + + internal class TerrainTile + { + public TerrainTile() {} + public TerrainTile(Terrain newTerrain, RectInt newRegion) { rect = newRegion; terrain = newTerrain; } + + public Terrain terrain; // the terrain object + public RectInt rect; // coordinates of this terrain tile in paint context pixels (essentially originTerrain target texture pixels) + public RectInt clippedLocal; // pixelRect in local pixel coordinates (for target texture), clipped to the local tile + public Rect validPaintRect; // the area per tile where the source texture was able to read from (in paint context pixels) + public int mapIndex; // + public int channelIndex; // + + // offsets used for gather / scatter + public Vector2Int readOffset; // offsets used when reading from the terrain heightmap + public Vector2Int writeOffset; // offsets used when copying from PaintContext clipped heightmap back to the terrain heightmap + } + + [Flags] + internal enum ToolAction + { + None = 0, + PaintHeightmap = 1 << 0, + PaintTexture = 1 << 1, + } + + // TerrainPaintUtilityEditor hooks to this event to do automatic undo + internal static event Action onTerrainTileBeforePaint; + + public PaintContext(Terrain terrain, RectInt pixelRect, int targetTextureWidth, int targetTextureHeight) + { + this.originTerrain = terrain; + this.pixelRect = pixelRect; + this.targetTextureWidth = targetTextureWidth; + this.targetTextureHeight = targetTextureHeight; + TerrainData terrainData = terrain.terrainData; + this.pixelSize = new Vector2( + terrainData.size.x / (targetTextureWidth - 1.0f), + terrainData.size.z / (targetTextureHeight - 1.0f)); + + FindTerrainTiles(); + ClipTerrainTiles(); + } + + public static PaintContext CreateFromBounds(Terrain terrain, Rect boundsInTerrainSpace, int inputTextureWidth, int inputTextureHeight, int extraBorderPixels = 0) + { + return new PaintContext( + terrain, + TerrainPaintUtility.CalcPixelRectFromBounds(terrain, boundsInTerrainSpace, inputTextureWidth, inputTextureHeight, extraBorderPixels), + inputTextureWidth, inputTextureHeight); + } + + internal void FindTerrainTiles() + { + m_TerrainTiles = new List(); + + Terrain left = originTerrain.leftNeighbor; + Terrain right = originTerrain.rightNeighbor; + Terrain top = originTerrain.topNeighbor; + Terrain bottom = originTerrain.bottomNeighbor; + + bool wantLeft = (pixelRect.x < 0); + bool wantRight = (pixelRect.xMax > (targetTextureWidth - 1)); + bool wantTop = (pixelRect.yMax > (targetTextureHeight - 1)); + bool wantBottom = (pixelRect.y < 0); + + if (wantLeft && wantRight) + { + Debug.LogWarning("PaintContext pixelRect is too large! It should touch a maximum of 2 Terrains horizontally."); + wantRight = false; + } + + if (wantTop && wantBottom) + { + Debug.LogWarning("PaintContext pixelRect is too large! It should touch a maximum of 2 Terrains vertically."); + wantBottom = false; + } + + // add center tile + TerrainTile tile = new TerrainTile(originTerrain, new RectInt(0, 0, targetTextureWidth, targetTextureHeight)); + tile.readOffset = Vector2Int.zero; + tile.writeOffset = Vector2Int.zero; + m_TerrainTiles.Add(tile); + + // add horizontal and vertical neighbors + Terrain horiz = null; + Terrain vert = null; + Terrain cornerTerrain = null; + + int xBias = 0; + int yBias = 0; + int xReadBias = 0; + int yReadBias = 0; + int xWriteBias = 0; + int yWriteBias = 0; + + if (wantLeft) + { + xBias = -1; + xReadBias = -1; + xWriteBias = 1; + horiz = left; + } + else if (wantRight) + { + xBias = 1; + xReadBias = 1; + xWriteBias = -1; + horiz = right; + } + + if (wantTop) + { + yBias = 1; + yReadBias = 1; + yWriteBias = -1; + vert = top; + } + else if (wantBottom) + { + yBias = -1; + yReadBias = -1; + yWriteBias = 1; + vert = bottom; + } + + if (horiz) + { + tile = new TerrainTile(horiz, new RectInt(xBias * targetTextureWidth, 0, targetTextureWidth, targetTextureHeight)); + tile.readOffset = new Vector2Int(xReadBias, 0); + tile.writeOffset = new Vector2Int(xWriteBias, 0); + m_TerrainTiles.Add(tile); + + // add corner, if we have a link + if (wantTop && horiz.topNeighbor) + cornerTerrain = horiz.topNeighbor; + else if (wantBottom && horiz.bottomNeighbor) + cornerTerrain = horiz.bottomNeighbor; + } + + if (vert) + { + tile = new PaintContext.TerrainTile(vert, new RectInt(0, yBias * targetTextureHeight, targetTextureWidth, targetTextureHeight)); + tile.readOffset = new Vector2Int(0, yReadBias); + tile.writeOffset = new Vector2Int(0, yWriteBias); + m_TerrainTiles.Add(tile); + + // add corner, if we have a link + if (wantLeft && vert.leftNeighbor) + cornerTerrain = vert.leftNeighbor; + else if (wantRight && vert.rightNeighbor) + cornerTerrain = vert.rightNeighbor; + } + + if (cornerTerrain != null) + { + tile = new TerrainTile(cornerTerrain, new RectInt(xBias * targetTextureWidth, yBias * targetTextureHeight, targetTextureWidth, targetTextureHeight)); + tile.readOffset = new Vector2Int(xReadBias, yReadBias); + tile.writeOffset = new Vector2Int(xWriteBias, yWriteBias); + m_TerrainTiles.Add(tile); + } + } + + internal void ClipTerrainTiles() + { + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile tile = m_TerrainTiles[i]; + tile.clippedLocal = new RectInt(); + tile.clippedLocal.x = Mathf.Max(0, pixelRect.x - tile.rect.x); + tile.clippedLocal.y = Mathf.Max(0, pixelRect.y - tile.rect.y); + tile.clippedLocal.xMax = Mathf.Min(tile.rect.width, pixelRect.xMax - tile.rect.x); + tile.clippedLocal.yMax = Mathf.Min(tile.rect.height, pixelRect.yMax - tile.rect.y); + + tile.validPaintRect = new Rect( + tile.clippedLocal.x + tile.rect.x - pixelRect.x, + tile.clippedLocal.y + tile.rect.y - pixelRect.y, + tile.clippedLocal.width, + tile.clippedLocal.height); + } + } + + public void CreateRenderTargets(RenderTextureFormat colorFormat) + { + m_SourceRenderTexture = RenderTexture.GetTemporary(pixelRect.width, pixelRect.height, 0, colorFormat, RenderTextureReadWrite.Linear); + m_DestinationRenderTexture = RenderTexture.GetTemporary(pixelRect.width, pixelRect.height, 0, colorFormat, RenderTextureReadWrite.Linear); + m_SourceRenderTexture.wrapMode = TextureWrapMode.Clamp; + m_SourceRenderTexture.filterMode = FilterMode.Point; + m_OldRenderTexture = RenderTexture.active; + } + + public void Cleanup(bool restoreRenderTexture = true) + { + if (restoreRenderTexture) + { + RenderTexture.active = m_OldRenderTexture; + } + RenderTexture.ReleaseTemporary(m_SourceRenderTexture); + RenderTexture.ReleaseTemporary(m_DestinationRenderTexture); + m_SourceRenderTexture = null; + m_DestinationRenderTexture = null; + m_OldRenderTexture = null; + } + + public void GatherHeightmap() + { + Material blitMaterial = TerrainPaintUtility.GetBlitMaterial(); + + RenderTexture.active = sourceRenderTexture; + GL.Clear(false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f)); + + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile terrainTile = m_TerrainTiles[i]; + if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + continue; + + Texture sourceTexture = terrainTile.terrain.terrainData.heightmapTexture; + if ((sourceTexture.width != targetTextureWidth) || (sourceTexture.height != targetTextureHeight)) + { + Debug.LogWarning("PaintContext heightmap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + continue; + } + + Rect readRect = new Rect( + (terrainTile.clippedLocal.x + terrainTile.readOffset.x) / (float)targetTextureWidth, + (terrainTile.clippedLocal.y + terrainTile.readOffset.y) / (float)targetTextureHeight, + (terrainTile.clippedLocal.width) / (float)targetTextureWidth, + (terrainTile.clippedLocal.height) / (float)targetTextureHeight); + + FilterMode oldFilterMode = sourceTexture.filterMode; + + sourceTexture.filterMode = FilterMode.Point; + + blitMaterial.SetTexture("_MainTex", sourceTexture); + blitMaterial.SetPass(0); + + TerrainPaintUtility.DrawQuad(pixelRect.width, pixelRect.height, readRect, terrainTile.validPaintRect); + + sourceTexture.filterMode = oldFilterMode; + } + + RenderTexture.active = oldRenderTexture; + } + + public void ScatterHeightmap(string editorUndoName) + { + Material blitMaterial = TerrainPaintUtility.GetBlitMaterial(); + + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile terrainTile = m_TerrainTiles[i]; + if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + continue; + + RenderTexture heightmap = terrainTile.terrain.terrainData.heightmapTexture; + if ((heightmap.width != targetTextureWidth) || (heightmap.height != targetTextureHeight)) + { + Debug.LogWarning("PaintContext heightmap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + continue; + } + + if (onTerrainTileBeforePaint != null) + onTerrainTileBeforePaint(terrainTile, ToolAction.PaintHeightmap, editorUndoName); + + RenderTexture.active = heightmap; + + Rect readRect = new Rect( + (terrainTile.clippedLocal.x + terrainTile.rect.x - pixelRect.x + terrainTile.writeOffset.x) / (float)pixelRect.width, + (terrainTile.clippedLocal.y + terrainTile.rect.y - pixelRect.y + terrainTile.writeOffset.y) / (float)pixelRect.height, + (terrainTile.clippedLocal.width) / (float)pixelRect.width, + (terrainTile.clippedLocal.height) / (float)pixelRect.height); + + Rect writeRect = new Rect( + terrainTile.clippedLocal.x, + terrainTile.clippedLocal.y, + terrainTile.clippedLocal.width, + terrainTile.clippedLocal.height); + + destinationRenderTexture.filterMode = FilterMode.Point; + + blitMaterial.SetTexture("_MainTex", destinationRenderTexture); + blitMaterial.SetPass(0); + + TerrainPaintUtility.DrawQuad(heightmap.width, heightmap.height, readRect, writeRect); + + terrainTile.terrain.terrainData.UpdateDirtyRegion(terrainTile.clippedLocal.x, terrainTile.clippedLocal.y, terrainTile.clippedLocal.width, terrainTile.clippedLocal.height, !terrainTile.terrain.drawInstanced); + OnTerrainPainted(terrainTile, ToolAction.PaintHeightmap); + } + } + + public void GatherNormals() + { + RenderTexture rt = originTerrain.normalmapTexture; + + Material blitMaterial = TerrainPaintUtility.GetBlitMaterial(); + + RenderTexture.active = sourceRenderTexture; + GL.Clear(false, true, new Color(0.5f, 0.5f, 0.5f, 0.5f)); + + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile terrainTile = m_TerrainTiles[i]; + if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + continue; + + Texture sourceTexture = terrainTile.terrain.normalmapTexture; + if ((sourceTexture.width != targetTextureWidth) || (sourceTexture.height != targetTextureHeight)) + { + Debug.LogWarning("PaintContext normalmap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + continue; + } + + Rect readRect = new Rect( + (terrainTile.clippedLocal.x + terrainTile.readOffset.x) / (float)targetTextureWidth, + (terrainTile.clippedLocal.y + terrainTile.readOffset.y) / (float)targetTextureHeight, + (terrainTile.clippedLocal.width) / (float)targetTextureWidth, + (terrainTile.clippedLocal.height) / (float)targetTextureHeight); + + FilterMode oldFilterMode = sourceTexture.filterMode; + + sourceTexture.filterMode = FilterMode.Point; + + blitMaterial.SetTexture("_MainTex", sourceTexture); + blitMaterial.SetPass(0); + + TerrainPaintUtility.DrawQuad(pixelRect.width, pixelRect.height, readRect, terrainTile.validPaintRect); + + sourceTexture.filterMode = oldFilterMode; + } + + RenderTexture.active = oldRenderTexture; + } + + public void GatherAlphamap(TerrainLayer inputLayer, bool addLayerIfDoesntExist = true) + { + if (inputLayer == null) + return; + + int terrainLayerIndex = TerrainPaintUtility.FindTerrainLayerIndex(originTerrain, inputLayer); + if (terrainLayerIndex == -1 && addLayerIfDoesntExist) + terrainLayerIndex = TerrainPaintUtility.AddTerrainLayer(originTerrain, inputLayer); + + RenderTexture.active = sourceRenderTexture; + GL.Clear(false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f)); + + Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) }; + + Material copyTerrainLayerMaterial = TerrainPaintUtility.GetCopyTerrainLayerMaterial(); + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile terrainTile = m_TerrainTiles[i]; + if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + continue; + + Rect readRect = new Rect( + (terrainTile.clippedLocal.x + terrainTile.readOffset.x) / (float)targetTextureWidth, + (terrainTile.clippedLocal.y + terrainTile.readOffset.y) / (float)targetTextureHeight, + (terrainTile.clippedLocal.width) / (float)targetTextureWidth, + (terrainTile.clippedLocal.height) / (float)targetTextureHeight); + + int tileLayerIndex = TerrainPaintUtility.FindTerrainLayerIndex(terrainTile.terrain, inputLayer); + if (tileLayerIndex == -1) + { + if (!addLayerIfDoesntExist) + { + // setting these to zero will prevent them from being used later + terrainTile.clippedLocal.width = 0; + terrainTile.clippedLocal.height = 0; + terrainTile.validPaintRect.width = 0; + terrainTile.validPaintRect.height = 0; + continue; + } + tileLayerIndex = TerrainPaintUtility.AddTerrainLayer(terrainTile.terrain, inputLayer); + } + + terrainTile.mapIndex = tileLayerIndex >> 2; + terrainTile.channelIndex = tileLayerIndex & 0x3; + + Texture sourceTexture = TerrainPaintUtility.GetTerrainAlphaMapChecked(terrainTile.terrain, terrainTile.mapIndex); + if ((sourceTexture.width != targetTextureWidth) || (sourceTexture.height != targetTextureHeight)) + { + Debug.LogWarning("PaintContext alphamap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + continue; + } + + FilterMode oldFilterMode = sourceTexture.filterMode; + sourceTexture.filterMode = FilterMode.Point; + + copyTerrainLayerMaterial.SetVector("_LayerMask", layerMasks[terrainTile.channelIndex]); + copyTerrainLayerMaterial.SetTexture("_MainTex", sourceTexture); + copyTerrainLayerMaterial.SetPass(0); + + TerrainPaintUtility.DrawQuad(pixelRect.width, pixelRect.height, readRect, terrainTile.validPaintRect); + + sourceTexture.filterMode = oldFilterMode; + } + + RenderTexture.active = oldRenderTexture; + } + + public void ScatterAlphamap(string editorUndoName) + { + Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) }; + + Material copyTerrainLayerMaterial = TerrainPaintUtility.GetCopyTerrainLayerMaterial(); + + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile terrainTile = m_TerrainTiles[i]; + if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + continue; + + if (onTerrainTileBeforePaint != null) + onTerrainTileBeforePaint(terrainTile, ToolAction.PaintTexture, editorUndoName); + + var rtdesc = new RenderTextureDescriptor(destinationRenderTexture.width, destinationRenderTexture.height, RenderTextureFormat.ARGB32); + rtdesc.sRGB = false; + rtdesc.useMipMap = false; + rtdesc.autoGenerateMips = false; + RenderTexture destTarget = RenderTexture.GetTemporary(rtdesc); + RenderTexture.active = destTarget; + + var writeRect = new RectInt( + terrainTile.clippedLocal.x + terrainTile.rect.x - pixelRect.x + terrainTile.writeOffset.x, + terrainTile.clippedLocal.y + terrainTile.rect.y - pixelRect.y + terrainTile.writeOffset.y, + terrainTile.clippedLocal.width, + terrainTile.clippedLocal.height); + + var readRect = new Rect( + writeRect.x / (float)pixelRect.width, + writeRect.y / (float)pixelRect.height, + writeRect.width / (float)pixelRect.width, + writeRect.height / (float)pixelRect.height); + + destinationRenderTexture.filterMode = FilterMode.Point; + + for (int j = 0; j < terrainTile.terrain.terrainData.alphamapTextureCount; j++) + { + Texture2D sourceTex = terrainTile.terrain.terrainData.alphamapTextures[j]; + if ((sourceTex.width != targetTextureWidth) || (sourceTex.height != targetTextureHeight)) + { + Debug.LogWarning("PaintContext alphamap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + continue; + } + + int mapIndex = terrainTile.mapIndex; + int channelIndex = terrainTile.channelIndex; + + Rect combineRect = new Rect( + terrainTile.clippedLocal.x / (float)sourceTex.width, + terrainTile.clippedLocal.y / (float)sourceTex.height, + terrainTile.clippedLocal.width / (float)sourceTex.width, + terrainTile.clippedLocal.height / (float)sourceTex.height); + + copyTerrainLayerMaterial.SetTexture("_MainTex", destinationRenderTexture); + copyTerrainLayerMaterial.SetTexture("_OldAlphaMapTexture", sourceRenderTexture); + copyTerrainLayerMaterial.SetTexture("_AlphaMapTexture", sourceTex); + copyTerrainLayerMaterial.SetVector("_LayerMask", j == mapIndex ? layerMasks[channelIndex] : Vector4.zero); + copyTerrainLayerMaterial.SetPass(1); + + GL.PushMatrix(); + GL.LoadOrtho(); + GL.LoadPixelMatrix(0, destTarget.width, 0, destTarget.height); + + GL.Begin(GL.QUADS); + GL.Color(new Color(1.0f, 1.0f, 1.0f, 1.0f)); + + GL.MultiTexCoord2(0, readRect.x, readRect.y); + GL.MultiTexCoord2(1, combineRect.x, combineRect.y); + GL.Vertex3(writeRect.x, writeRect.y, 0.0f); + GL.MultiTexCoord2(0, readRect.x, readRect.yMax); + GL.MultiTexCoord2(1, combineRect.x, combineRect.yMax); + GL.Vertex3(writeRect.x, writeRect.yMax, 0.0f); + GL.MultiTexCoord2(0, readRect.xMax, readRect.yMax); + GL.MultiTexCoord2(1, combineRect.xMax, combineRect.yMax); + GL.Vertex3(writeRect.xMax, writeRect.yMax, 0.0f); + GL.MultiTexCoord2(0, readRect.xMax, readRect.y); + GL.MultiTexCoord2(1, combineRect.xMax, combineRect.y); + GL.Vertex3(writeRect.xMax, writeRect.y, 0.0f); + + GL.End(); + GL.PopMatrix(); + + if (TerrainPaintUtility.paintTextureUsesCopyTexture) + { + var rtdesc2 = new RenderTextureDescriptor(sourceTex.width, sourceTex.height, RenderTextureFormat.ARGB32); + rtdesc2.sRGB = false; + rtdesc2.useMipMap = true; + rtdesc2.autoGenerateMips = false; + var mips = RenderTexture.GetTemporary(rtdesc2); + if (!mips.IsCreated()) + mips.Create(); + + // Composes mip0 in a RT with full mipchain. + Graphics.CopyTexture(sourceTex, 0, 0, mips, 0, 0); + Graphics.CopyTexture(destTarget, 0, 0, writeRect.x, writeRect.y, writeRect.width, writeRect.height, mips, 0, 0, terrainTile.clippedLocal.x, terrainTile.clippedLocal.y); + mips.GenerateMips(); + + // Copy them into sourceTex. + Graphics.CopyTexture(mips, sourceTex); + + RenderTexture.ReleaseTemporary(mips); + } + else + { + GraphicsDeviceType deviceType = SystemInfo.graphicsDeviceType; + if (deviceType == GraphicsDeviceType.Metal || deviceType == GraphicsDeviceType.OpenGLCore) + sourceTex.ReadPixels(new Rect(writeRect.x, writeRect.y, writeRect.width, writeRect.height), terrainTile.clippedLocal.x, terrainTile.clippedLocal.y); + else + sourceTex.ReadPixels(new Rect(writeRect.x, destTarget.height - writeRect.y - writeRect.height, writeRect.width, writeRect.height), terrainTile.clippedLocal.x, terrainTile.clippedLocal.y); + sourceTex.Apply(); + } + } + + RenderTexture.active = null; + RenderTexture.ReleaseTemporary(destTarget); + + OnTerrainPainted(terrainTile, ToolAction.PaintTexture); + } + } + + // Collects modified terrain so that we can update some deferred operations at the mouse up event + private class PaintedTerrain + { + public Terrain terrain; + public ToolAction action; + }; + private static List s_PaintedTerrain = new List(); + + private static void OnTerrainPainted(PaintContext.TerrainTile tile, ToolAction action) + { + for (int i = 0; i < s_PaintedTerrain.Count; ++i) + { + if (tile.terrain == s_PaintedTerrain[i].terrain) + { + s_PaintedTerrain[i].action |= action; + return; + } + } + s_PaintedTerrain.Add(new PaintedTerrain { terrain = tile.terrain, action = action }); + } + + public static void ApplyDelayedActions() + { + for (int i = 0; i < s_PaintedTerrain.Count; ++i) + { + var pt = s_PaintedTerrain[i]; + if ((pt.action & ToolAction.PaintHeightmap) != 0) + { + pt.terrain.ApplyDelayedHeightmapModification(); + } + if ((pt.action & ToolAction.PaintTexture) != 0) + { + var terrainData = pt.terrain.terrainData; + if (terrainData == null) + continue; + terrainData.SetBaseMapDirty(); + if (TerrainPaintUtility.paintTextureUsesCopyTexture) + { + // pull the data from GPU to CPU + var rtdesc = new RenderTextureDescriptor(terrainData.alphamapResolution, terrainData.alphamapResolution, RenderTextureFormat.ARGB32); + rtdesc.sRGB = false; + rtdesc.useMipMap = false; + rtdesc.autoGenerateMips = false; + RenderTexture tmp = RenderTexture.GetTemporary(rtdesc); + for (int c = 0; c < terrainData.alphamapTextureCount; ++c) + { + Graphics.Blit(terrainData.alphamapTextures[c], tmp); + terrainData.alphamapTextures[c].ReadPixels(new Rect(0, 0, rtdesc.width, rtdesc.height), 0, 0, true); + } + RenderTexture.ReleaseTemporary(tmp); + } + } + } + + s_PaintedTerrain.Clear(); + } + } +} diff --git a/Modules/Terrain/Public/TerrainPaintUtility.cs b/Modules/Terrain/Public/TerrainPaintUtility.cs index 2089699697..a2d752a116 100644 --- a/Modules/Terrain/Public/TerrainPaintUtility.cs +++ b/Modules/Terrain/Public/TerrainPaintUtility.cs @@ -27,390 +27,96 @@ public static Material GetBuiltinPaintMaterial() return s_BuiltinPaintMaterial; } - public class TerrainTile + // returns a transform from terrain space to brush UV + public static BrushTransform CalculateBrushTransform( + Terrain terrain, Vector2 brushCenterTerrainUV, float brushSize, float brushRotationDegrees) { - public TerrainTile() { terrain = null; } - public TerrainTile(Terrain newTerrain, RectInt newRegion) { rect = newRegion; terrain = newTerrain; } - public Terrain terrain; - public RectInt rect; // pixel coordinates of this terrain tile in the paint context (a locally built space relative to the active 'center' tile) + float rotationRadians = brushRotationDegrees * Mathf.Deg2Rad; + float cos = Mathf.Cos(rotationRadians); + float sin = Mathf.Sin(rotationRadians); + Vector2 brushU = new Vector2(cos, -sin) * brushSize; + Vector2 brushV = new Vector2(sin, cos) * brushSize; - public int mapIndex; - public int channelIndex; + // calculate brush origin + Vector3 terrainSize = terrain.terrainData.size; + Vector2 brushCenterTerrainSpace = brushCenterTerrainUV * new Vector2(terrainSize.x, terrainSize.z); + Vector2 brushOrigin = brushCenterTerrainSpace - 0.5f * brushU - 0.5f * brushV; - // offsets used for gather / scatter - public Vector2Int readOffset; // offsets used when reading from the terrain heightmap - public Vector2Int writeOffset; // offsets used when copying from PaintContext clipped heightmap back to the terrain heightmap + BrushTransform xform = new BrushTransform(brushOrigin, brushU, brushV); + return xform; } - public class PaintContext + public static void BuildTransformPaintContextUVToPaintContextUV(PaintContext src, PaintContext dst, out Vector4 scaleOffset) { - public RectInt brushRect; // the rectangle represented by this paint context, in target texture pixels (for the active terrain tile) - public TerrainTile[] terrainTiles; // all terrain tiles touched by this paint context - public RectInt[] clippedTiles; // the intersection of brushRect with each of the terrain tiles above, clipped into local tile pixels - public Rect[] validPaintRects; // the area per tile where the source texture was able to read from - - public RenderTexture sourceRenderTexture; - public RenderTexture destinationRenderTexture; - - public RenderTexture oldRenderTexture; // active render texture before PaintContext was initialized - - - public void CalculateBrushRect(Terrain terrain, Rect bounds, int inputTextureWidth, int inputTextureHeight) - { - brushRect = CalcBrushRectInPixels(terrain, bounds, inputTextureWidth, inputTextureHeight); - } - - public void CreateTerrainTiles(Terrain terrain, int inputTextureWidth, int inputTextureHeight) - { - terrainTiles = FindTerrainTiles(terrain, inputTextureWidth, inputTextureHeight, brushRect); - clippedTiles = ClipTerrainTiles(terrainTiles, brushRect); - validPaintRects = new Rect[terrainTiles.Length]; - - for (int i = 0; i < terrainTiles.Length; ++i) - { - TerrainTile terrainTile = terrainTiles[i]; - validPaintRects[i] = new Rect( - clippedTiles[i].x + terrainTile.rect.x - brushRect.x, - clippedTiles[i].y + terrainTile.rect.y - brushRect.y, - clippedTiles[i].width, - clippedTiles[i].height); - } - } - - public void CreateRenderTargets(RenderTextureFormat colorFormat) - { - sourceRenderTexture = RenderTexture.GetTemporary(brushRect.width, brushRect.height, 0, colorFormat, RenderTextureReadWrite.Linear); - destinationRenderTexture = RenderTexture.GetTemporary(brushRect.width, brushRect.height, 0, colorFormat, RenderTextureReadWrite.Linear); - sourceRenderTexture.wrapMode = TextureWrapMode.Clamp; - sourceRenderTexture.filterMode = FilterMode.Point; - oldRenderTexture = RenderTexture.active; - } - - public void Cleanup() - { - RenderTexture.active = oldRenderTexture; - RenderTexture.ReleaseTemporary(sourceRenderTexture); - RenderTexture.ReleaseTemporary(destinationRenderTexture); - sourceRenderTexture = null; - destinationRenderTexture = null; - oldRenderTexture = null; - } - - public void GatherHeightmap(Terrain terrain) - { - RenderTexture rt = terrain.terrainData.heightmapTexture; - int heightmapWidth = rt.width; - int heightmapHeight = rt.height; - - Material blitMaterial = GetBlitMaterial(); - - RenderTexture.active = sourceRenderTexture; - - for (int i = 0; i < terrainTiles.Length; i++) - { - if (clippedTiles[i].width == 0 || clippedTiles[i].height == 0) - continue; - - TerrainTile terrainTile = terrainTiles[i]; - - Rect readRect = new Rect( - (clippedTiles[i].x + terrainTile.readOffset.x) / (float)heightmapWidth, - (clippedTiles[i].y + terrainTile.readOffset.y) / (float)heightmapHeight, - (clippedTiles[i].width) / (float)heightmapWidth, - (clippedTiles[i].height) / (float)heightmapHeight); - - Texture sourceTexture = terrainTile.terrain.terrainData.heightmapTexture; - FilterMode oldFilterMode = sourceTexture.filterMode; - - sourceTexture.filterMode = FilterMode.Point; - - blitMaterial.SetTexture("_MainTex", sourceTexture); - blitMaterial.SetPass(0); - - DrawQuad(brushRect.width, brushRect.height, readRect, validPaintRects[i]); - - sourceTexture.filterMode = oldFilterMode; - } - - RenderTexture.active = oldRenderTexture; - } - - public void ScatterHeightmap(string editorUndoName) - { - Material blitMaterial = GetBlitMaterial(); - - for (int i = 0; i < terrainTiles.Length; i++) - { - if (clippedTiles[i].width == 0 || clippedTiles[i].height == 0) - continue; - - TerrainTile terrainTile = terrainTiles[i]; - - if (onTerrainTileBeforePaint != null) - onTerrainTileBeforePaint(terrainTile, ToolAction.PaintHeightmap, editorUndoName); - - RenderTexture heightmap = terrainTile.terrain.terrainData.heightmapTexture; - RenderTexture.active = heightmap; - - Rect readRect = new Rect( - (clippedTiles[i].x + terrainTile.rect.x - brushRect.x + terrainTile.writeOffset.x) / (float)brushRect.width, - (clippedTiles[i].y + terrainTile.rect.y - brushRect.y + terrainTile.writeOffset.y) / (float)brushRect.height, - (clippedTiles[i].width) / (float)brushRect.width, - (clippedTiles[i].height) / (float)brushRect.height); - - Rect writeRect = new Rect( - clippedTiles[i].x, - clippedTiles[i].y, - clippedTiles[i].width, - clippedTiles[i].height); - - destinationRenderTexture.filterMode = FilterMode.Point; - - blitMaterial.SetTexture("_MainTex", destinationRenderTexture); - blitMaterial.SetPass(0); - - DrawQuad(heightmap.width, heightmap.height, readRect, writeRect); - - terrainTile.terrain.terrainData.UpdateDirtyRegion(clippedTiles[i].x, clippedTiles[i].y, clippedTiles[i].width, clippedTiles[i].height, !terrainTile.terrain.drawInstanced); - OnTerrainPainted(terrainTile, ToolAction.PaintHeightmap); - } - } - - public void GatherNormals(Terrain terrain) - { - RenderTexture rt = terrain.normalmapTexture; - - RenderTextureFormat colorFormat = rt.format; - int heightmapWidth = rt.width; - int heightmapHeight = rt.height; - - Material blitMaterial = GetBlitMaterial(); - - RenderTexture.active = sourceRenderTexture; - - for (int i = 0; i < terrainTiles.Length; i++) - { - if (clippedTiles[i].width == 0 || clippedTiles[i].height == 0) - continue; - - TerrainTile terrainTile = terrainTiles[i]; - - Rect readRect = new Rect( - (clippedTiles[i].x + terrainTile.readOffset.x) / (float)heightmapWidth, - (clippedTiles[i].y + terrainTile.readOffset.y) / (float)heightmapHeight, - (clippedTiles[i].width) / (float)heightmapWidth, - (clippedTiles[i].height) / (float)heightmapHeight); - - Texture sourceTexture = terrainTile.terrain.normalmapTexture; - FilterMode oldFilterMode = sourceTexture.filterMode; - - sourceTexture.filterMode = FilterMode.Point; - - blitMaterial.SetTexture("_MainTex", sourceTexture); - blitMaterial.SetPass(0); - - DrawQuad(brushRect.width, brushRect.height, readRect, validPaintRects[i]); - - sourceTexture.filterMode = oldFilterMode; - } - - RenderTexture.active = oldRenderTexture; - } - - public void GatherAlphamap(Terrain terrain, TerrainLayer inputLayer, bool addLayerIfDoesntExist = true) - { - if (inputLayer == null) - return; - - int terrainLayerIndex = FindTerrainLayerIndex(terrain, inputLayer); - if (terrainLayerIndex == -1 && addLayerIfDoesntExist) - terrainLayerIndex = AddTerrainLayer(terrain, inputLayer); - - Texture2D inputTexture = GetTerrainAlphaMapChecked(terrain, terrainLayerIndex >> 2); - - int inputTextureWidth = inputTexture.width; - int inputTextureHeight = inputTexture.height; - - RenderTexture.active = sourceRenderTexture; - - Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) }; - - Material copyTerrainLayerMaterial = GetCopyTerrainLayerMaterial(); - for (int i = 0; i < terrainTiles.Length; i++) - { - if (clippedTiles[i].width == 0 || clippedTiles[i].height == 0) - continue; - - TerrainTile terrainTile = terrainTiles[i]; - - Rect readRect = new Rect( - (clippedTiles[i].x + terrainTile.readOffset.x) / (float)inputTextureWidth, - (clippedTiles[i].y + terrainTile.readOffset.y) / (float)inputTextureHeight, - (clippedTiles[i].width) / (float)inputTextureWidth, - (clippedTiles[i].height) / (float)inputTextureHeight); - - int tileLayerIndex = FindTerrainLayerIndex(terrainTile.terrain, inputLayer); - if (tileLayerIndex == -1) - { - if (!addLayerIfDoesntExist) - { - // setting these to zero will prevent them from being used later - clippedTiles[i].width = 0; - clippedTiles[i].height = 0; - validPaintRects[i].width = 0; - validPaintRects[i].height = 0; - continue; - } - tileLayerIndex = AddTerrainLayer(terrainTile.terrain, inputLayer); - } - - terrainTile.mapIndex = tileLayerIndex >> 2; - terrainTile.channelIndex = tileLayerIndex & 0x3; - - Texture sourceTexture = GetTerrainAlphaMapChecked(terrainTile.terrain, terrainTile.mapIndex); - - FilterMode oldFilterMode = sourceTexture.filterMode; - sourceTexture.filterMode = FilterMode.Point; - - copyTerrainLayerMaterial.SetVector("_LayerMask", layerMasks[terrainTile.channelIndex]); - copyTerrainLayerMaterial.SetTexture("_MainTex", sourceTexture); - copyTerrainLayerMaterial.SetPass(0); - - DrawQuad(brushRect.width, brushRect.height, readRect, validPaintRects[i]); - - sourceTexture.filterMode = oldFilterMode; - } - - RenderTexture.active = oldRenderTexture; - } - - public void ScatterAlphamap(string editorUndoName) - { - Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) }; - - Material copyTerrainLayerMaterial = GetCopyTerrainLayerMaterial(); - - for (int i = 0; i < terrainTiles.Length; i++) - { - if (clippedTiles[i].width == 0 || clippedTiles[i].height == 0) - continue; - - TerrainTile terrainTile = terrainTiles[i]; - - if (onTerrainTileBeforePaint != null) - onTerrainTileBeforePaint(terrainTile, ToolAction.PaintTexture, editorUndoName); - - var rtdesc = new RenderTextureDescriptor(destinationRenderTexture.width, destinationRenderTexture.height, RenderTextureFormat.ARGB32); - rtdesc.sRGB = false; - rtdesc.useMipMap = false; - rtdesc.autoGenerateMips = false; - RenderTexture destTarget = RenderTexture.GetTemporary(rtdesc); - RenderTexture.active = destTarget; - - var writeRect = new RectInt( - clippedTiles[i].x + terrainTile.rect.x - brushRect.x + terrainTile.writeOffset.x, - clippedTiles[i].y + terrainTile.rect.y - brushRect.y + terrainTile.writeOffset.y, - clippedTiles[i].width, - clippedTiles[i].height); - - var readRect = new Rect( - writeRect.x / (float)brushRect.width, - writeRect.y / (float)brushRect.height, - writeRect.width / (float)brushRect.width, - writeRect.height / (float)brushRect.height); - - destinationRenderTexture.filterMode = FilterMode.Point; - - for (int j = 0; j < terrainTile.terrain.terrainData.alphamapTextureCount; j++) - { - Texture2D sourceTex = terrainTile.terrain.terrainData.alphamapTextures[j]; - - int mapIndex = terrainTile.mapIndex; - int channelIndex = terrainTile.channelIndex; - - Rect combineRect = new Rect( - clippedTiles[i].x / (float)sourceTex.width, - clippedTiles[i].y / (float)sourceTex.height, - clippedTiles[i].width / (float)sourceTex.width, - clippedTiles[i].height / (float)sourceTex.height); - - copyTerrainLayerMaterial.SetTexture("_MainTex", destinationRenderTexture); - copyTerrainLayerMaterial.SetTexture("_OldAlphaMapTexture", sourceRenderTexture); - copyTerrainLayerMaterial.SetTexture("_AlphaMapTexture", sourceTex); - copyTerrainLayerMaterial.SetVector("_LayerMask", j == mapIndex ? layerMasks[channelIndex] : Vector4.zero); - copyTerrainLayerMaterial.SetPass(1); - - GL.PushMatrix(); - GL.LoadOrtho(); - GL.LoadPixelMatrix(0, destTarget.width, 0, destTarget.height); - - GL.Begin(GL.QUADS); - GL.Color(new Color(1.0f, 1.0f, 1.0f, 1.0f)); - - GL.MultiTexCoord2(0, readRect.x, readRect.y); - GL.MultiTexCoord2(1, combineRect.x, combineRect.y); - GL.Vertex3(writeRect.x, writeRect.y, 0.0f); - GL.MultiTexCoord2(0, readRect.x, readRect.yMax); - GL.MultiTexCoord2(1, combineRect.x, combineRect.yMax); - GL.Vertex3(writeRect.x, writeRect.yMax, 0.0f); - GL.MultiTexCoord2(0, readRect.xMax, readRect.yMax); - GL.MultiTexCoord2(1, combineRect.xMax, combineRect.yMax); - GL.Vertex3(writeRect.xMax, writeRect.yMax, 0.0f); - GL.MultiTexCoord2(0, readRect.xMax, readRect.y); - GL.MultiTexCoord2(1, combineRect.xMax, combineRect.y); - GL.Vertex3(writeRect.xMax, writeRect.y, 0.0f); - - GL.End(); - GL.PopMatrix(); - - if (paintTextureUsesCopyTexture) - { - var rtdesc2 = new RenderTextureDescriptor(sourceTex.width, sourceTex.height, RenderTextureFormat.ARGB32); - rtdesc2.sRGB = false; - rtdesc2.useMipMap = true; - rtdesc2.autoGenerateMips = false; - var mips = RenderTexture.GetTemporary(rtdesc2); - if (!mips.IsCreated()) - mips.Create(); - - // Composes mip0 in a RT with full mipchain. - Graphics.CopyTexture(sourceTex, 0, 0, mips, 0, 0); - Graphics.CopyTexture(destTarget, 0, 0, writeRect.x, writeRect.y, writeRect.width, writeRect.height, mips, 0, 0, clippedTiles[i].x, clippedTiles[i].y); - mips.GenerateMips(); - - // Copy them into sourceTex. - Graphics.CopyTexture(mips, sourceTex); - - RenderTexture.ReleaseTemporary(mips); - } - else - { - GraphicsDeviceType deviceType = SystemInfo.graphicsDeviceType; - if (deviceType == GraphicsDeviceType.Metal || deviceType == GraphicsDeviceType.OpenGLCore) - sourceTex.ReadPixels(new Rect(writeRect.x, writeRect.y, writeRect.width, writeRect.height), clippedTiles[i].x, clippedTiles[i].y); - else - sourceTex.ReadPixels(new Rect(writeRect.x, destTarget.height - writeRect.y - writeRect.height, writeRect.width, writeRect.height), clippedTiles[i].x, clippedTiles[i].y); - sourceTex.Apply(); - } - } - - RenderTexture.active = null; - RenderTexture.ReleaseTemporary(destTarget); - - OnTerrainPainted(terrainTile, ToolAction.PaintTexture); - } - } + // for example: + // src = alphaUV + // dst = normalUV + // dst.uv = src.u * scales.xy + src.v * scales.zw + offset + // terrainspace.xz = srcOrigin + src.uv * srcSize + // terrainspace.xz = dstOrigin + dst.uv * dstSize + // dstOrigin + dst.uv * dstSize = srcOrigin + src.uv * srcSize + // dst.uv * dstSize = src.uv * srcSize + srcOrigin - dstOrigin + // dst.uv = (src.uv * srcSize + srcOrigin - dstOrigin) / dstSize + // dst.uv = (src.uv * srcSize) / dstSize + (srcOrigin - dstOrigin) / dstSize + // scales.x = srcSize.x / dstSize.x + // scales.yz = 0.0f; + // scales.w = srcSize.y / dstSize.y + // offset.xy = (srcOrigin.xy - dstOrigin.xy) / dstSize.xy + + // paint context origin in terrain space + // (note this is the UV space origin and size, not the mesh origin & size) + float srcOriginX = (src.pixelRect.xMin - 0.5f) * src.pixelSize.x; + float srcOriginZ = (src.pixelRect.yMin - 0.5f) * src.pixelSize.y; + float srcSizeX = (src.pixelRect.width) * src.pixelSize.x; + float srcSizeZ = (src.pixelRect.height) * src.pixelSize.y; + + // paint context origin in terrain space + // (note this is the UV space origin and size, not the mesh origin & size) + float dstOriginX = (dst.pixelRect.xMin - 0.5f) * dst.pixelSize.x; + float dstOriginZ = (dst.pixelRect.yMin - 0.5f) * dst.pixelSize.y; + float dstSizeX = (dst.pixelRect.width) * dst.pixelSize.x; + float dstSizeZ = (dst.pixelRect.height) * dst.pixelSize.y; + + scaleOffset = new Vector4( + srcSizeX / dstSizeX, + srcSizeZ / dstSizeZ, + (srcOriginX - dstOriginX) / dstSizeX, + (srcOriginZ - dstOriginZ) / dstSizeZ + ); } - [Flags] - public enum ToolAction + // this function sets up material properties used by functions provided in TerrainTool.cginc + public static void SetupTerrainToolMaterialProperties( + PaintContext paintContext, + BrushTransform brushXform, // the brush transform to terrain space (of paintContext.originTerrain) + Material material) { - None = 0, - PaintHeightmap = 1 << 0, - PaintTexture = 1 << 1, + // BrushUV = f(terrainSpace.xz) = f(g(pc.uv)) + // f(ts.xy) = ts.x * brushXform.X + ts.y * brushXform.Y + brushXform.Origin + // g(pc.uv) = ts.xz = pcOrigin + pc.uv * pcSize + // f(g(pc.uv)) == (pcOrigin + pc.uv * pcSize).x * brushXform.X + (pcOrigin + pc.uv * pcSize).y * brushXform.Y + brushXform.Origin + // f(g(pc.uv)) == (pcOrigin.x + pc.u * pcSize.x) * brushXform.X + (pcOrigin.y + pc.v * pcSize.y) * brushXform.Y + brushXform.Origin + // f(g(pc.uv)) == (pcOrigin.x * brushXform.X) + (pc.u * pcSize.x) * brushXform.X + (pcOrigin.y * brushXform.Y) + (pc.v * pcSize.y) * brushXform.Y + brushXform.Origin + // f(g(pc.uv)) == pc.u * (pcSize.x * brushXform.X) + pc.v * (pcSize.y * brushXform.Y) + (brushXform.Origin + (pcOrigin.x * brushXform.X) + (pcOrigin.y * brushXform.Y)) + + // pcOrigin = (pc.pixelRect.xyMin - 0.5) * pc.pixelSize.xy + // pcSize = (pc.pixelRect.wh) * pc.pixelSize.xy + + // paint context origin in terrain space + // (note this is the UV space origin and size, not the mesh origin & size) + float pcOriginX = (paintContext.pixelRect.xMin - 0.5f) * paintContext.pixelSize.x; + float pcOriginZ = (paintContext.pixelRect.yMin - 0.5f) * paintContext.pixelSize.y; + float pcSizeX = (paintContext.pixelRect.width) * paintContext.pixelSize.x; + float pcSizeZ = (paintContext.pixelRect.height) * paintContext.pixelSize.y; + + Vector2 scaleU = pcSizeX * brushXform.targetX; + Vector2 scaleV = pcSizeZ * brushXform.targetY; + Vector2 offset = brushXform.targetOrigin + pcOriginX * brushXform.targetX + pcOriginZ * brushXform.targetY; + material.SetVector("_PCUVToBrushUVScales", new Vector4(scaleU.x, scaleU.y, scaleV.x, scaleV.y)); + material.SetVector("_PCUVToBrushUVOffset", new Vector4(offset.x, offset.y, 0.0f, 0.0f)); } - private static bool paintTextureUsesCopyTexture + internal static bool paintTextureUsesCopyTexture { get { @@ -419,12 +125,10 @@ private static bool paintTextureUsesCopyTexture } } - static PaintContext InitializePaintContext(Terrain terrain, Rect bounds, int inputTextureWidth, int inputTextureHeight, RenderTextureFormat colorFormat) + static PaintContext InitializePaintContext(Terrain terrain, Texture target, RenderTextureFormat pcFormat, Rect boundsInTerrainSpace, int extraBorderPixels = 0) { - PaintContext ctx = new PaintContext(); - ctx.CalculateBrushRect(terrain, bounds, inputTextureWidth, inputTextureHeight); - ctx.CreateTerrainTiles(terrain, inputTextureWidth, inputTextureHeight); - ctx.CreateRenderTargets(colorFormat); + PaintContext ctx = PaintContext.CreateFromBounds(terrain, boundsInTerrainSpace, target.width, target.height, extraBorderPixels); + ctx.CreateRenderTargets(pcFormat); return ctx; } @@ -433,77 +137,11 @@ public static void ReleaseContextResources(PaintContext ctx) ctx.Cleanup(); } - public static Rect CalculateBrushRectInTerrainUnits(Terrain terrain, Vector2 uv, float brushSize) - { - Vector3 terrainSize = terrain.terrainData.size; - return new Rect(uv * new Vector2(terrainSize.x, terrainSize.z) - Vector2.one * brushSize * 0.5f, Vector2.one * brushSize); - } - - // Collects modified terrain so that we can update some deferred operations at the mouse up event - private class PaintedTerrain - { - public Terrain terrain; - public ToolAction action; - }; - private static List s_PaintedTerrain = new List(); - - private static void OnTerrainPainted(TerrainTile tile, ToolAction action) - { - for (int i = 0; i < s_PaintedTerrain.Count; ++i) - { - if (tile.terrain == s_PaintedTerrain[i].terrain) - { - s_PaintedTerrain[i].action |= action; - return; - } - } - s_PaintedTerrain.Add(new PaintedTerrain { terrain = tile.terrain, action = action }); - } - - public static void FlushAllPaints() - { - for (int i = 0; i < s_PaintedTerrain.Count; ++i) - { - var pt = s_PaintedTerrain[i]; - if ((pt.action & ToolAction.PaintHeightmap) != 0) - { - pt.terrain.ApplyDelayedHeightmapModification(); - } - if ((pt.action & ToolAction.PaintTexture) != 0) - { - var terrainData = pt.terrain.terrainData; - if (terrainData == null) - continue; - terrainData.SetBaseMapDirty(); - if (paintTextureUsesCopyTexture) - { - // pull the data from GPU to CPU - var rtdesc = new RenderTextureDescriptor(terrainData.alphamapResolution, terrainData.alphamapResolution, RenderTextureFormat.ARGB32); - rtdesc.sRGB = false; - rtdesc.useMipMap = false; - rtdesc.autoGenerateMips = false; - RenderTexture tmp = RenderTexture.GetTemporary(rtdesc); - for (int c = 0; c < terrainData.alphamapTextureCount; ++c) - { - Graphics.Blit(terrainData.alphamapTextures[c], tmp); - terrainData.alphamapTextures[c].ReadPixels(new Rect(0, 0, rtdesc.width, rtdesc.height), 0, 0, true); - } - RenderTexture.ReleaseTemporary(tmp); - } - } - } - - s_PaintedTerrain.Clear(); - } - - // TerrainPaintUtilityEditor hooks to this event to do automatic undo - internal static event Action onTerrainTileBeforePaint; - - public static PaintContext BeginPaintHeightmap(Terrain terrain, Rect bounds) // bounds in terrain space units + public static PaintContext BeginPaintHeightmap(Terrain terrain, Rect boundsInTerrainSpace, int extraBorderPixels = 0) { RenderTexture rt = terrain.terrainData.heightmapTexture; - PaintContext ctx = InitializePaintContext(terrain, bounds, rt.width, rt.height, rt.format); - ctx.GatherHeightmap(terrain); + PaintContext ctx = InitializePaintContext(terrain, rt, rt.format, boundsInTerrainSpace, extraBorderPixels); + ctx.GatherHeightmap(); return ctx; } @@ -513,15 +151,15 @@ public static void EndPaintHeightmap(PaintContext ctx, string editorUndoName) ctx.Cleanup(); } - public static PaintContext CollectNormals(Terrain terrain, Rect bounds) + public static PaintContext CollectNormals(Terrain terrain, Rect boundsInTerrainSpace, int extraBorderPixels = 0) { RenderTexture rt = terrain.normalmapTexture; - PaintContext ctx = InitializePaintContext(terrain, bounds, rt.width, rt.height, rt.format); - ctx.GatherNormals(terrain); + PaintContext ctx = InitializePaintContext(terrain, rt, rt.format, boundsInTerrainSpace, extraBorderPixels); + ctx.GatherNormals(); return ctx; } - public static PaintContext BeginPaintTexture(Terrain terrain, Rect bounds, TerrainLayer inputLayer) + public static PaintContext BeginPaintTexture(Terrain terrain, Rect boundsInTerrainSpace, TerrainLayer inputLayer, int extraBorderPixels = 0) { if (inputLayer == null) return null; @@ -532,8 +170,8 @@ public static PaintContext BeginPaintTexture(Terrain terrain, Rect bounds, Terra Texture2D inputTexture = GetTerrainAlphaMapChecked(terrain, terrainLayerIndex >> 2); - PaintContext ctx = InitializePaintContext(terrain, bounds, inputTexture.width, inputTexture.height, RenderTextureFormat.R8); - ctx.GatherAlphamap(terrain, inputLayer); + PaintContext ctx = InitializePaintContext(terrain, inputTexture, RenderTextureFormat.R8, boundsInTerrainSpace, extraBorderPixels); + ctx.GatherAlphamap(inputLayer); return ctx; } @@ -560,7 +198,7 @@ public static Material GetCopyTerrainLayerMaterial() return m_CopyTerrainLayerMaterial; } - static void DrawQuad(int width, int height, Rect source, Rect destination) + internal static void DrawQuad(int width, int height, Rect source, Rect destination) { GL.PushMatrix(); GL.LoadOrtho(); @@ -582,139 +220,15 @@ static void DrawQuad(int width, int height, Rect source, Rect destination) GL.PopMatrix(); } - public static RectInt CalcBrushRectInPixels(Terrain terrain, Rect brushRect, int textureWidth, int textureHeight) - { - int xMin = Mathf.FloorToInt(((float)textureWidth) * brushRect.xMin / terrain.terrainData.size.x); - int yMin = Mathf.FloorToInt(((float)textureHeight) * brushRect.yMin / terrain.terrainData.size.z); - int xMax = Mathf.CeilToInt(((float)textureWidth) * brushRect.xMax / terrain.terrainData.size.x); - int yMax = Mathf.CeilToInt(((float)textureHeight) * brushRect.yMax / terrain.terrainData.size.z); - return new RectInt(xMin, yMin, xMax - xMin, yMax - yMin); - } - - public static TerrainTile[] FindTerrainTiles(Terrain terrain, int width, int height, RectInt brushRect) + internal static RectInt CalcPixelRectFromBounds(Terrain terrain, Rect boundsInTerrainSpace, int textureWidth, int textureHeight, int extraBorderPixels) { - List terrainTiles = new List(); - - Terrain left = terrain.leftNeighbor; - Terrain right = terrain.rightNeighbor; - Terrain top = terrain.topNeighbor; - Terrain bottom = terrain.bottomNeighbor; - - bool wantLeft = (brushRect.x < 0); - bool wantRight = (brushRect.xMax > (width - 1)); - bool wantTop = (brushRect.yMax > (height - 1)); - bool wantBottom = (brushRect.y < 0); - - if (wantLeft && wantRight) - { - Debug.Log("FindTerrainTiles query rectangle too large!"); - wantRight = false; - } - - if (wantTop && wantBottom) - { - Debug.Log("FindTerrainTiles query rectangle too large!"); - wantBottom = false; - } - - // add center tile - TerrainTile tile = new TerrainTile(terrain, new RectInt(0, 0, width, height)); - tile.readOffset = Vector2Int.zero; - tile.writeOffset = Vector2Int.zero; - terrainTiles.Add(tile); - - // add horizontal and vertical neighbors - Terrain horiz = null; - Terrain vert = null; - Terrain cornerTerrain = null; - - int xBias = 0; - int yBias = 0; - int xReadBias = 0; - int yReadBias = 0; - int xWriteBias = 0; - int yWriteBias = 0; - - if (wantLeft) - { - xBias = -1; - xReadBias = -1; - xWriteBias = 1; - horiz = left; - } - else if (wantRight) - { - xBias = 1; - xReadBias = 1; - xWriteBias = -1; - horiz = right; - } - - if (wantTop) - { - yBias = 1; - yReadBias = 1; - yWriteBias = -1; - vert = top; - } - else if (wantBottom) - { - yBias = -1; - yReadBias = -1; - yWriteBias = 1; - vert = bottom; - } - - if (horiz) - { - tile = new TerrainTile(horiz, new RectInt(xBias * width, 0, width, height)); - tile.readOffset = new Vector2Int(xReadBias, 0); - tile.writeOffset = new Vector2Int(xWriteBias, 0); - terrainTiles.Add(tile); - - // add corner, if we have a link - if (wantTop && horiz.topNeighbor) - cornerTerrain = horiz.topNeighbor; - else if (wantBottom && horiz.bottomNeighbor) - cornerTerrain = horiz.bottomNeighbor; - } - - if (vert) - { - tile = new TerrainTile(vert, new RectInt(0, yBias * height, width, height)); - tile.readOffset = new Vector2Int(0, yReadBias); - tile.writeOffset = new Vector2Int(0, yWriteBias); - terrainTiles.Add(tile); - - // add corner, if we have a link - if (wantLeft && vert.leftNeighbor) - cornerTerrain = vert.leftNeighbor; - else if (wantRight && vert.rightNeighbor) - cornerTerrain = vert.rightNeighbor; - } - - if (cornerTerrain != null) - { - tile = new TerrainTile(cornerTerrain, new RectInt(xBias * width, yBias * height, width, height)); - tile.readOffset = new Vector2Int(xReadBias, yReadBias); - tile.writeOffset = new Vector2Int(xWriteBias, yWriteBias); - terrainTiles.Add(tile); - } - - return terrainTiles.ToArray(); - } - - public static RectInt[] ClipTerrainTiles(TerrainTile[] terrainTiles, RectInt brushRect) - { - RectInt[] clippedTiles = new RectInt[terrainTiles.Length]; - for (int i = 0; i < terrainTiles.Length; i++) - { - clippedTiles[i].x = Mathf.Max(0, brushRect.x - terrainTiles[i].rect.x); - clippedTiles[i].y = Mathf.Max(0, brushRect.y - terrainTiles[i].rect.y); - clippedTiles[i].xMax = Mathf.Min(terrainTiles[i].rect.width, brushRect.xMax - terrainTiles[i].rect.x); - clippedTiles[i].yMax = Mathf.Min(terrainTiles[i].rect.height, brushRect.yMax - terrainTiles[i].rect.y); - } - return clippedTiles; + float scaleX = (textureWidth - 1.0f) / terrain.terrainData.size.x; + float scaleY = (textureHeight - 1.0f) / terrain.terrainData.size.z; + int xMin = Mathf.FloorToInt(boundsInTerrainSpace.xMin * scaleX) - extraBorderPixels; + int yMin = Mathf.FloorToInt(boundsInTerrainSpace.yMin * scaleY) - extraBorderPixels; + int xMax = Mathf.CeilToInt(boundsInTerrainSpace.xMax * scaleX) + extraBorderPixels; + int yMax = Mathf.CeilToInt(boundsInTerrainSpace.yMax * scaleY) + extraBorderPixels; + return new RectInt(xMin, yMin, xMax - xMin + 1, yMax - yMin + 1); } // Alphamap utilities @@ -736,7 +250,7 @@ static public int FindTerrainLayerIndex(Terrain terrain, TerrainLayer inputLayer return -1; } - static int AddTerrainLayer(Terrain terrain, TerrainLayer inputLayer) + internal static int AddTerrainLayer(Terrain terrain, TerrainLayer inputLayer) { int newIndex = terrain.terrainData.terrainLayers.Length; var newarray = new TerrainLayer[newIndex + 1]; diff --git a/Modules/TerrainEditor/Brush/Brush.cs b/Modules/TerrainEditor/Brush/Brush.cs index 8453538495..a300ec29ac 100644 --- a/Modules/TerrainEditor/Brush/Brush.cs +++ b/Modules/TerrainEditor/Brush/Brush.cs @@ -99,7 +99,7 @@ internal static Texture2D GenerateBrushTexture(Texture2D mask, AnimationCurve fa s_CreateBrushMaterial = new Material(EditorGUIUtility.LoadRequired("Brushes/CreateBrush.shader") as Shader); int sampleCount = Mathf.Max(width, 1024); - Texture2D falloffTex = new Texture2D(sampleCount, 1, TextureFormat.R8, false); + Texture2D falloffTex = new Texture2D(sampleCount, 1, TextureFormat.R16, false); Color[] falloffPix = new Color[sampleCount]; for (int i = 0; i < sampleCount; i++) { diff --git a/Modules/TerrainEditor/Brush/BrushList.cs b/Modules/TerrainEditor/Brush/BrushList.cs index 7e199ba0ed..553ef2891d 100644 --- a/Modules/TerrainEditor/Brush/BrushList.cs +++ b/Modules/TerrainEditor/Brush/BrushList.cs @@ -97,6 +97,11 @@ public void UpdateSelection(int newSelectedBrush) m_BrushEditor = Editor.CreateEditor(GetActiveBrush()); } + public Brush GetCircleBrush() + { + return m_BrushList[0]; + } + public Brush GetActiveBrush() { if (m_SelectedBrush >= m_BrushList.Length) diff --git a/Modules/TerrainEditor/PaintTools/PaintHeightTool.cs b/Modules/TerrainEditor/PaintTools/PaintHeightTool.cs index eef201b7d3..3770163db0 100644 --- a/Modules/TerrainEditor/PaintTools/PaintHeightTool.cs +++ b/Modules/TerrainEditor/PaintTools/PaintHeightTool.cs @@ -25,25 +25,56 @@ public override void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext editContext.ShowBrushesGUI(5); } - public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) + private void ApplyBrushInternal(PaintContext paintContext, float brushStrength, Texture brushTexture, BrushTransform brushXform) { - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, editContext.brushTexture, editContext.brushStrength * 0.01f, editContext.brushSize, editContext.brushStrength * 0.01f); + Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); + + brushStrength = Event.current.shift ? -brushStrength : brushStrength; + Vector4 brushParams = new Vector4(0.01f * brushStrength, 0.0f, 0.0f, 0.0f); + mat.SetTexture("_BrushTex", brushTexture); + mat.SetVector("_BrushParams", brushParams); + + TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); + + Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.RaiseLowerHeight); } - public override bool OnPaint(Terrain terrain, IOnPaint editContext) + public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { - float brushStrength = Event.current.shift ? -editContext.brushStrength : editContext.brushStrength; + // We're only doing painting operations, early out if it's not a repaint + if (Event.current.type != EventType.Repaint) + return; - Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); - TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushRect); + if (editContext.hitValidTerrain) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); - // apply brush - Vector4 brushParams = new Vector4(brushStrength * 0.01f, 0.0f, 0.0f, 0.0f); - mat.SetTexture("_BrushTex", editContext.brushTexture); - mat.SetVector("_BrushParams", brushParams); - Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.RaiseLowerHeight); + Material material = TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(); + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, editContext.brushTexture, brushXform, material, 0); + + // draw result preview + { + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); + + // restore old render target + RenderTexture.active = paintContext.oldRenderTexture; + + material.SetTexture("_HeightmapOrig", paintContext.sourceRenderTexture); + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.DestinationRenderTexture, editContext.brushTexture, brushXform, material, 1); + } + TerrainPaintUtility.ReleaseContextResources(paintContext); + } + } + + public override bool OnPaint(Terrain terrain, IOnPaint editContext) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds()); + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Raise or Lower Height"); return true; } diff --git a/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs b/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs index 827487c55e..0fae39fd1a 100644 --- a/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs +++ b/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs @@ -24,6 +24,7 @@ public class PaintTextureTool : TerrainPaintTool [SerializeField] float m_SplatAlpha = 1.0f; + public override string GetName() { return "Paint Texture"; @@ -36,17 +37,20 @@ public override string GetDesc() public override bool OnPaint(Terrain terrain, IOnPaint editContext) { - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); - - TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintTexture(terrain, brushRect, m_SelectedTerrainLayer); + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintTexture(terrain, brushXform.GetBrushXYBounds(), m_SelectedTerrainLayer); if (paintContext == null) return false; Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); + // apply brush Vector4 brushParams = new Vector4(editContext.brushStrength, m_SplatAlpha, 0.0f, 0.0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); + + TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); + Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.PaintTexture); TerrainPaintUtility.EndPaintTexture(paintContext, "Terrain Paint - Texture"); @@ -55,7 +59,17 @@ public override bool OnPaint(Terrain terrain, IOnPaint editContext) public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, editContext.brushTexture, editContext.brushStrength, editContext.brushSize, 0.0f); + // We're only doing painting operations, early out if it's not a repaint + if (Event.current.type != EventType.Repaint) + return; + + if (editContext.hitValidTerrain) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); + PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); + TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, editContext.brushTexture, brushXform, TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(), 0); + TerrainPaintUtility.ReleaseContextResources(ctx); + } } private void DrawFoldoutEditor(Editor editor, int controlId, ref bool visible) diff --git a/Modules/TerrainEditor/PaintTools/SetHeightTool.cs b/Modules/TerrainEditor/PaintTools/SetHeightTool.cs index a2d3999f35..2d3087b176 100644 --- a/Modules/TerrainEditor/PaintTools/SetHeightTool.cs +++ b/Modules/TerrainEditor/PaintTools/SetHeightTool.cs @@ -29,7 +29,48 @@ public override string GetDesc() public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, editContext.brushTexture, editContext.brushStrength * 0.01f, editContext.brushSize, 0); + // We're only doing painting operations, early out if it's not a repaint + if (Event.current.type != EventType.Repaint) + return; + + if (editContext.hitValidTerrain) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); + + Material material = TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(); + + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, editContext.brushTexture, brushXform, material, 0); + + // draw result preview + { + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); + + // restore old render target + RenderTexture.active = paintContext.oldRenderTexture; + + material.SetTexture("_HeightmapOrig", paintContext.sourceRenderTexture); + + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.DestinationRenderTexture, editContext.brushTexture, brushXform, material, 1); + } + + TerrainPaintUtility.ReleaseContextResources(paintContext); + } + } + + private void ApplyBrushInternal(PaintContext paintContext, float brushStrength, Texture brushTexture, BrushTransform brushXform) + { + Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); + + Vector4 brushParams = new Vector4(brushStrength * 0.01f, 0.5f * m_Height, 0.0f, 0.0f); + mat.SetTexture("_BrushTex", brushTexture); + mat.SetVector("_BrushParams", brushParams); + + TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); + + Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.SetHeights); } public override bool OnPaint(Terrain terrain, IOnPaint editContext) @@ -40,17 +81,10 @@ public override bool OnPaint(Terrain terrain, IOnPaint editContext) editContext.RepaintAllInspectors(); return true; } - Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); - - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); - TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushRect); - - Vector4 brushParams = new Vector4(editContext.brushStrength * 0.01f, 0.5f * m_Height, 0.0f, 0.0f); - mat.SetTexture("_BrushTex", editContext.brushTexture); - mat.SetVector("_BrushParams", brushParams); - - Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.SetHeights); + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds()); + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Set Height"); return true; } diff --git a/Modules/TerrainEditor/PaintTools/SmoothHeightTool.cs b/Modules/TerrainEditor/PaintTools/SmoothHeightTool.cs index d345368f35..ed607efb85 100644 --- a/Modules/TerrainEditor/PaintTools/SmoothHeightTool.cs +++ b/Modules/TerrainEditor/PaintTools/SmoothHeightTool.cs @@ -25,22 +25,41 @@ public override void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext editContext.ShowBrushesGUI(5); } - public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) + private void ApplyBrushInternal(PaintContext paintContext, float brushStrength, Texture brushTexture, BrushTransform brushXform) { - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, editContext.brushTexture, editContext.brushStrength, editContext.brushSize, 0.0f); - } + Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); - public override bool OnPaint(Terrain terrain, IOnPaint editContext) - { - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); - TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushRect); + brushStrength = Event.current.shift ? -brushStrength : brushStrength; - Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); - Vector4 brushParams = new Vector4(editContext.brushStrength, 0.0f, 0.0f, 0.0f); - mat.SetTexture("_BrushTex", editContext.brushTexture); + Vector4 brushParams = new Vector4(brushStrength, 0.0f, 0.0f, 0.0f); + mat.SetTexture("_BrushTex", brushTexture); mat.SetVector("_BrushParams", brushParams); + + TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); + Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.SmoothHeights); + } + + public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) + { + // We're only doing painting operations, early out if it's not a repaint + if (Event.current.type != EventType.Repaint) + return; + if (editContext.hitValidTerrain) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); + PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); + TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, editContext.brushTexture, brushXform, TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(), 0); + TerrainPaintUtility.ReleaseContextResources(ctx); + } + } + + public override bool OnPaint(Terrain terrain, IOnPaint editContext) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds()); + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Smooth Height"); return true; } diff --git a/Modules/TerrainEditor/PaintTools/StampTool.cs b/Modules/TerrainEditor/PaintTools/StampTool.cs index f4f4eafa62..d6d59e57da 100644 --- a/Modules/TerrainEditor/PaintTools/StampTool.cs +++ b/Modules/TerrainEditor/PaintTools/StampTool.cs @@ -21,45 +21,84 @@ public override string GetName() public override string GetDesc() { - return "Left click to stamp the brush onto the terrain.\n\nHold shift and left click to stamp negative."; + return "Left click to stamp the brush onto the terrain.\n\nHold shift and mousewheel to adjust height."; } - public override bool OnPaint(Terrain terrain, IOnPaint editContext) + private void ApplyBrushInternal(PaintContext paintContext, float brushStrength, Texture brushTexture, BrushTransform brushXform) { - if (Event.current.type == EventType.MouseDrag) - return true; - Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); - TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushRect); - - Vector4 brushParams = new Vector4(editContext.brushStrength * 0.01f, 0.0f, m_StampHeight, 0.0f); + Vector4 brushParams = new Vector4(0.01f * brushStrength, 0.0f, m_StampHeight, 0.0f); + mat.SetTexture("_BrushTex", brushTexture); + mat.SetVector("_BrushParams", brushParams); - if (Event.current.shift) - brushParams.x = -brushParams.x; + TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); - mat.SetTexture("_BrushTex", editContext.brushTexture); - mat.SetVector("_BrushParams", brushParams); Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.StampHeight); + } + + public override bool OnPaint(Terrain terrain, IOnPaint editContext) + { + // ignore mouse drags + if (Event.current.type == EventType.MouseDrag) + return true; + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds()); + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Stamp"); return true; } public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, editContext.brushTexture, editContext.brushStrength * 0.01f, editContext.brushSize, m_StampHeight); + Event evt = Event.current; + if (evt.shift && (evt.type == EventType.ScrollWheel)) + { + m_StampHeight += Event.current.delta.y * -0.0000007f * editContext.raycastHit.distance; + evt.Use(); + } + + // We're only doing painting operations, early out if it's not a repaint + if (evt.type != EventType.Repaint) + return; + + if (editContext.hitValidTerrain) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); + + Material material = TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(); + + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, editContext.brushTexture, brushXform, material, 0); + + // draw result preview + { + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); + + // restore old render target + RenderTexture.active = paintContext.oldRenderTexture; + + material.SetTexture("_HeightmapOrig", paintContext.sourceRenderTexture); + + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.DestinationRenderTexture, editContext.brushTexture, brushXform, material, 1); + } + + TerrainPaintUtility.ReleaseContextResources(paintContext); + } } public override void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext) { EditorGUI.BeginChangeCheck(); - m_StampHeight = EditorGUILayout.Slider(new GUIContent("Stamp Height", "You can set the Stamp Height property manually or you can shift-click on the terrain to sample the height at the mouse position (rather like the “eyedropper” tool in an image editor)."), m_StampHeight * terrain.terrainData.size.y, 0, terrain.terrainData.size.y) / terrain.terrainData.size.y; + m_StampHeight = EditorGUILayout.Slider(new GUIContent("Stamp Height", "You can set the Stamp Height manually or you can hold shift and mouse wheel on the terrain to adjust it."), m_StampHeight * terrain.terrainData.size.y, 0, terrain.terrainData.size.y) / terrain.terrainData.size.y; if (EditorGUI.EndChangeCheck()) Save(true); // show built-in brushes + editContext.ShowBrushesGUI(5); base.OnInspectorGUI(terrain, editContext); } } diff --git a/Modules/TerrainEditor/PaintTools/TerrainPaintTool.cs b/Modules/TerrainEditor/PaintTools/TerrainPaintTool.cs index 65eb147cdc..9f1de28910 100644 --- a/Modules/TerrainEditor/PaintTools/TerrainPaintTool.cs +++ b/Modules/TerrainEditor/PaintTools/TerrainPaintTool.cs @@ -15,7 +15,6 @@ public interface IOnPaint Texture brushTexture { get; } Vector2 uv { get; } float brushStrength { get; } - float brushRotation { get; } float brushSize { get; } void RepaintAllInspectors(); @@ -25,8 +24,9 @@ public interface IOnSceneGUI SceneView sceneView { get; } Texture brushTexture { get; } float brushStrength { get; } - float brushRotation { get; } float brushSize { get; } + bool hitValidTerrain { get; } + RaycastHit raycastHit { get; } } public interface IOnInspectorGUI @@ -40,6 +40,8 @@ internal interface ITerrainPaintTool string GetDesc(); void OnEnable(); void OnDisable(); + void OnEnterToolMode(); + void OnExitToolMode(); void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext); void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext); bool OnPaint(Terrain terrain, IOnPaint editContext); @@ -51,6 +53,8 @@ public abstract class TerrainPaintTool : ScriptableSingleton, ITerrainPain public abstract string GetDesc(); public virtual void OnEnable() {} public virtual void OnDisable() {} + public virtual void OnEnterToolMode() {} + public virtual void OnExitToolMode() {} public virtual void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) {} public virtual void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext) {} public virtual bool OnPaint(Terrain terrain, IOnPaint editContext) { return false; } @@ -62,27 +66,28 @@ internal class OnPaintContext : IOnPaint internal Vector2 m_UV = Vector2.zero; internal float m_BrushStrength = 0.0f; internal float m_BrushSize = 0; - internal float m_BrushRotation = 0.0f; + internal bool m_HitValidTerrain = false; + internal RaycastHit m_RaycastHit; - public OnPaintContext(Texture brushTexture, Vector2 uv, float brushStrength, float brushRotation, float brushSize) + public OnPaintContext(RaycastHit raycastHit, Texture brushTexture, Vector2 uv, float brushStrength, float brushSize) { - Set(brushTexture, uv, brushStrength, brushRotation, brushSize); + Set(false, raycastHit, brushTexture, uv, brushStrength, brushSize); } - public OnPaintContext Set(Texture brushTexture, Vector2 uv, float brushStrength, float brushRotation, float brushSize) + public OnPaintContext Set(bool hitValidTerrain, RaycastHit raycastHit, Texture brushTexture, Vector2 uv, float brushStrength, float brushSize) { m_BrushTexture = brushTexture; m_UV = uv; m_BrushStrength = brushStrength; m_BrushSize = brushSize; - m_BrushRotation = brushRotation; + m_HitValidTerrain = hitValidTerrain; + m_RaycastHit = raycastHit; return this; } public Texture brushTexture { get { return m_BrushTexture; } } public Vector2 uv { get { return m_UV; } } public float brushStrength { get { return m_BrushStrength; } } - public float brushRotation { get { return m_BrushRotation; } } public float brushSize { get { return m_BrushSize; } } public void RepaintAllInspectors() { InspectorWindow.RepaintAllInspectors(); } @@ -94,28 +99,31 @@ internal class OnSceneGUIContext : IOnSceneGUI internal Texture m_BrushTexture = null; internal float m_BrushStrength = 0.0f; internal float m_BrushSize = 0; - internal float m_BrushRotation = 0.0f; + internal bool m_HitValidTerrain = false; + internal RaycastHit m_RaycastHit; - public OnSceneGUIContext(SceneView sceneView, Texture brushTexture, float brushStrength, float brushRotation, float brushSize) + public OnSceneGUIContext(SceneView sceneView, RaycastHit raycastHit, Texture brushTexture, float brushStrength, float brushSize) { - Set(sceneView, brushTexture, brushStrength, brushSize, brushRotation); + Set(sceneView, false, raycastHit, brushTexture, brushStrength, brushSize); } - public OnSceneGUIContext Set(SceneView sceneView, Texture brushTexture, float brushStrength, float brushRotation, float brushSize) + public OnSceneGUIContext Set(SceneView sceneView, bool hitValidTerrain, RaycastHit raycastHit, Texture brushTexture, float brushStrength, float brushSize) { m_SceneView = sceneView; m_BrushTexture = brushTexture; m_BrushStrength = brushStrength; m_BrushSize = brushSize; - m_BrushRotation = brushRotation; + m_HitValidTerrain = hitValidTerrain; + m_RaycastHit = raycastHit; return this; } public SceneView sceneView { get { return m_SceneView; } } public Texture brushTexture { get { return m_BrushTexture; } } public float brushStrength { get { return m_BrushStrength; } } - public float brushRotation { get { return m_BrushRotation; } } public float brushSize { get { return m_BrushSize; } } + public bool hitValidTerrain { get { return m_HitValidTerrain; } } + public RaycastHit raycastHit { get { return m_RaycastHit; } } } internal class OnInspectorGUIContext : IOnInspectorGUI diff --git a/Modules/TerrainEditor/TerrainInspector.cs b/Modules/TerrainEditor/TerrainInspector.cs index fcc226c9cb..de381c2fe1 100644 --- a/Modules/TerrainEditor/TerrainInspector.cs +++ b/Modules/TerrainEditor/TerrainInspector.cs @@ -635,9 +635,9 @@ public bool active static internal ITerrainPaintTool[] m_Tools = null; static internal string[] m_ToolNames = null; - static OnPaintContext onPaintEditContext = new OnPaintContext(null, Vector2.zero, 0.0f, 0.0f, 0.0f); + static OnPaintContext onPaintEditContext = new OnPaintContext(new RaycastHit(), null, Vector2.zero, 0.0f, 0.0f); static OnInspectorGUIContext onInspectorGUIEditContext = new OnInspectorGUIContext(); - static OnSceneGUIContext onSceneGUIEditContext = new OnSceneGUIContext(null, null, 0.0f, 0.0f, 0.0f); + static OnSceneGUIContext onSceneGUIEditContext = new OnSceneGUIContext(null, new RaycastHit(), null, 0.0f, 0.0f); ITerrainPaintTool GetActiveTool() { @@ -813,6 +813,7 @@ void ResetPaintTools() void Initialize() { m_Terrain = target as Terrain; + CheckToolActivation(); } void LoadInspectorSettings() @@ -826,7 +827,7 @@ void LoadInspectorSettings() int selected = EditorPrefs.GetInt("TerrainSelectedBrush", 0); s_DetailPainter.selectedDetail = EditorPrefs.GetInt("TerrainSelectedDetail", 0); - m_ActivePaintToolIndex = EditorPrefs.GetInt("TerraiActivePaintToolIndex", 0); + m_ActivePaintToolIndex = EditorPrefs.GetInt("TerrainActivePaintToolIndex", 0); // TODO: this should be stored by name if (m_ActivePaintToolIndex > m_Tools.Length) m_ActivePaintToolIndex = 0; @@ -844,7 +845,7 @@ void SaveInspectorSettings() EditorPrefs.SetFloat("TerrainBrushSize", m_Size); EditorPrefs.SetFloat("TerrainBrushStrength", m_Strength); - EditorPrefs.SetInt("TerraiActivePaintToolIndex", m_ActivePaintToolIndex); + EditorPrefs.SetInt("TerrainActivePaintToolIndex", m_ActivePaintToolIndex); } public void OnEnable() @@ -874,6 +875,9 @@ public void OnEnable() LoadInspectorSettings(); + // now that tool selection has been loaded from inspector, activate the selected tool + CheckToolActivation(); + InitializeLightingFields(); m_TerrainToolContext = new TerrainToolContext(this); @@ -886,9 +890,11 @@ public void OnEnable() public void OnDisable() { ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_TerrainToolContext); - TerrainPaintUtility.FlushAllPaints(); + PaintContext.ApplyDelayedActions(); SceneView.onSceneGUIDelegate -= OnSceneGUICallback; + SetCurrentPaintToolInactive(); + SaveInspectorSettings(); m_ShowReflectionProbesGUI.valueChanged.RemoveListener(Repaint); @@ -922,6 +928,55 @@ TerrainTool selectedTool Tools.current = Tool.None; m_SelectedTool.value = (int)value; s_activeTerrainInspector = GetInstanceID(); + CheckToolActivation(); + } + } + + // this is a bunch of tracking to ensure we don't mess up the tool mode callbacks + private bool m_PaintToolActive = false; + private void SetCurrentPaintToolActive() + { + if (!m_PaintToolActive) + { + ITerrainPaintTool paintTool = GetActiveTool(); + if (paintTool != null) + { + paintTool.OnEnterToolMode(); + m_PaintToolActive = true; + } + } + } + + private void SetCurrentPaintToolInactive() + { + if (m_PaintToolActive) + { + ITerrainPaintTool paintTool = GetActiveTool(); + if (paintTool != null) + { + paintTool.OnExitToolMode(); + m_PaintToolActive = false; + } + } + } + + // Ideally we would be notified when the active tool changes, but I can see no way to do that + // So instead we will call this function everywhere, which checks for it changing and does the proper notification callbacks + private TerrainTool m_PreviousSelectedTool = TerrainTool.None; + private void CheckToolActivation() + { + TerrainTool currentTool = selectedTool; + if (currentTool != m_PreviousSelectedTool) + { + // inactivate previous tool, if necessary + if (m_PreviousSelectedTool == TerrainTool.Paint) + SetCurrentPaintToolInactive(); + + m_PreviousSelectedTool = currentTool; + + // activate new tool, if necessary + if (currentTool == TerrainTool.Paint) + SetCurrentPaintToolActive(); } } @@ -1390,9 +1445,14 @@ public void ShowPaint() if (m_Tools != null && m_Tools.Length > 1 && m_ToolNames != null) { EditorGUI.BeginChangeCheck(); - m_ActivePaintToolIndex = EditorGUILayout.Popup(m_ActivePaintToolIndex, m_ToolNames); - if (EditorGUI.EndChangeCheck()) + int newPaintToolIndex = EditorGUILayout.Popup(m_ActivePaintToolIndex, m_ToolNames); + if (EditorGUI.EndChangeCheck() && (newPaintToolIndex != m_ActivePaintToolIndex)) + { + SetCurrentPaintToolInactive(); + m_ActivePaintToolIndex = newPaintToolIndex; + SetCurrentPaintToolActive(); Repaint(); + } ITerrainPaintTool activeTool = GetActiveTool(); GUILayout.BeginVertical(EditorStyles.helpBox); @@ -1408,7 +1468,8 @@ public void ShowBrushes(int spacing) GUILayout.Space(spacing); bool repaint = brushList.ShowGUI(); - m_Size = EditorGUILayout.Slider(styles.brushSize, m_Size, 1.0f, Mathf.Min(m_Terrain.terrainData.size.x - 1.0f, m_Terrain.terrainData.size.z - 1.0f)); + float safetyFactorHack = 0.9375f; + m_Size = EditorGUILayout.Slider(styles.brushSize, m_Size, 0.1f, Mathf.Round(Mathf.Min(m_Terrain.terrainData.size.x, m_Terrain.terrainData.size.z) * safetyFactorHack)); m_Strength = PercentSlider(styles.opacity, m_Strength, kMinBrushStrength, 1); // former string formatting: "0.0%" brushList.ShowEditGUI(); @@ -1866,23 +1927,21 @@ private bool IsModificationToolActive() return true; } - bool IsBrushPreviewVisible() + bool IsBrushPreviewVisible(Terrain overTerrain) { if (!IsModificationToolActive()) return false; - Vector3 pos; - Vector2 uv; - return Raycast(out uv, out pos); + return (overTerrain != null); } - private bool RaycastAllTerrains(out Terrain hitTerrain, out Vector2 hitUV) + private bool RaycastAllTerrains(out Terrain hitTerrain, out RaycastHit raycastHit) { Ray mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); float minDist = float.MaxValue; hitTerrain = null; - hitUV = Vector2.zero; + raycastHit = new RaycastHit(); foreach (Terrain terrain in Terrain.activeTerrains) { RaycastHit hit; @@ -1892,11 +1951,11 @@ private bool RaycastAllTerrains(out Terrain hitTerrain, out Vector2 hitUV) { minDist = hit.distance; hitTerrain = terrain; - hitUV = hit.textureCoord; + raycastHit = hit; } } } - return hitTerrain; + return (hitTerrain != null); } public void OnSceneGUICallback(SceneView sceneView) @@ -1905,47 +1964,52 @@ public void OnSceneGUICallback(SceneView sceneView) Event e = Event.current; - Terrain terrain = null; - Vector2 uv = Vector2.zero; + Terrain hitTerrain = null; + RaycastHit raycastHit = new RaycastHit(); if (selectedTool == TerrainTool.Paint || selectedTool == TerrainTool.PaintDetail || selectedTool == TerrainTool.PlaceTree) { - if (RaycastAllTerrains(out terrain, out uv)) + if (RaycastAllTerrains(out hitTerrain, out raycastHit)) { if (e.type == EventType.MouseDown || e.type == EventType.MouseUp) { if (e.button == 0 && !Event.current.alt) - Selection.activeObject = terrain; + Selection.activeObject = hitTerrain; } } } + Vector2 uv = raycastHit.textureCoord; - bool isTerrainValid = (terrain != null && terrain.terrainData != null); + bool hitValidTerrain = (hitTerrain != null && hitTerrain.terrainData != null); + if (!hitValidTerrain) + { + raycastHit = new RaycastHit(); + } if (selectedTool == TerrainTool.Paint) { - Terrain lastActiveTerrain = isTerrainValid ? terrain : s_LastActiveTerrain; + Terrain lastActiveTerrain = hitValidTerrain ? hitTerrain : s_LastActiveTerrain; if (lastActiveTerrain) { ITerrainPaintTool activeTool = GetActiveTool(); - activeTool.OnSceneGUI(lastActiveTerrain, onSceneGUIEditContext.Set(sceneView, brushList.GetActiveBrush().texture, m_Strength, 0.0f, m_Size)); + activeTool.OnSceneGUI(lastActiveTerrain, onSceneGUIEditContext.Set(sceneView, hitValidTerrain, raycastHit, brushList.GetActiveBrush().texture, m_Strength, m_Size)); } } else if (selectedTool == TerrainTool.PaintDetail || selectedTool == TerrainTool.PlaceTree) { - if (isTerrainValid) + if (hitValidTerrain) { float brushSize = selectedTool == TerrainTool.PlaceTree ? TreePainter.brushSize : m_Size; - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, brushList.GetActiveBrush().texture, m_Strength, brushSize, 0.0f); + TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(hitTerrain, brushList.GetCircleBrush().texture, brushSize); } } - if (!isTerrainValid) + if (!hitValidTerrain) return; - s_LastActiveTerrain = terrain; + s_LastActiveTerrain = hitTerrain; int id = GUIUtility.GetControlID(s_TerrainEditorHash, FocusType.Passive); switch (e.GetTypeForControl(id)) @@ -1957,7 +2021,7 @@ public void OnSceneGUICallback(SceneView sceneView) break; case EventType.MouseMove: - if (IsBrushPreviewVisible()) + if (IsBrushPreviewVisible(hitTerrain)) HandleUtility.Repaint(); break; @@ -2000,12 +2064,12 @@ public void OnSceneGUICallback(SceneView sceneView) TreePainter.BeginPlaceTrees(m_Terrain); } - TreePainter.PlaceTrees(terrain, uv.x, uv.y); + TreePainter.PlaceTrees(hitTerrain, uv.x, uv.y); } } else { - TreePainter.RemoveTrees(terrain, uv.x, uv.y, Event.current.control); + TreePainter.RemoveTrees(hitTerrain, uv.x, uv.y, Event.current.control); } } else if (selectedTool == TerrainTool.PaintDetail) @@ -2016,13 +2080,13 @@ public void OnSceneGUICallback(SceneView sceneView) } DetailPaintOperation paintOp = new DetailPaintOperation(); - paintOp.size = (int)Mathf.Max(1.0f, ((float)m_Size * ((float)terrain.terrainData.detailResolution / terrain.terrainData.size.x))); + paintOp.size = (int)Mathf.Max(1.0f, ((float)m_Size * ((float)hitTerrain.terrainData.detailResolution / hitTerrain.terrainData.size.x))); paintOp.targetStrength = m_DetailStrength * 16F; if (Event.current.shift || Event.current.control) paintOp.targetStrength *= -1; paintOp.opacity = m_DetailOpacity; paintOp.clearSelectedOnly = Event.current.control; - paintOp.terrainData = terrain.terrainData; + paintOp.terrainData = hitTerrain.terrainData; paintOp.brush = brushList.GetActiveBrush(); paintOp.tool = selectedTool; paintOp.randomizeDetails = true; @@ -2034,10 +2098,10 @@ public void OnSceneGUICallback(SceneView sceneView) else { ITerrainPaintTool activeTool = GetActiveTool(); - if (activeTool.OnPaint(terrain, onPaintEditContext.Set(brushList.GetActiveBrush().texture, uv, m_Strength, 0.0f, m_Size))) + if (activeTool.OnPaint(hitTerrain, onPaintEditContext.Set(hitValidTerrain, raycastHit, brushList.GetActiveBrush().texture, uv, m_Strength, m_Size))) { // height map modification modes - terrain.editorRenderFlags = TerrainRenderFlags.Heightmap; + hitTerrain.editorRenderFlags = TerrainRenderFlags.Heightmap; } } @@ -2067,8 +2131,8 @@ public void OnSceneGUICallback(SceneView sceneView) s_DetailPainter.EndPaintDetails(); } - terrain.editorRenderFlags = TerrainRenderFlags.All; - TerrainPaintUtility.FlushAllPaints(); + hitTerrain.editorRenderFlags = TerrainRenderFlags.All; + PaintContext.ApplyDelayedActions(); e.Use(); } diff --git a/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs b/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs index 39ccf3c7f7..22743c45f5 100644 --- a/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs +++ b/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs @@ -14,12 +14,6 @@ namespace UnityEditor.Experimental.TerrainAPI { public static class TerrainPaintUtilityEditor { - internal enum BrushPreviewMeshType - { - QuadOutline = 0, - QuadPatch - } - // This maintains the list of terrains we have touched in the current operation (and the current operation identifier, as an undo group) // We track this to have good cross-tile undo support: each modified tile should be added, at most, ONCE within a single operation private static int s_CurrentOperationUndoGroup = -1; @@ -27,7 +21,7 @@ internal enum BrushPreviewMeshType static TerrainPaintUtilityEditor() { - TerrainPaintUtility.onTerrainTileBeforePaint += (tile, action, editorUndoName) => + PaintContext.onTerrainTileBeforePaint += (tile, action, editorUndoName) => { // if we are in a new undo group (new operation) then start with an empty list if (Undo.GetCurrentGroup() != s_CurrentOperationUndoGroup) @@ -44,7 +38,7 @@ static TerrainPaintUtilityEditor() s_CurrentOperationUndoStack.Add(tile.terrain); var undoObjects = new List(); undoObjects.Add(tile.terrain.terrainData); - if (0 != (action & TerrainPaintUtility.ToolAction.PaintTexture)) + if (0 != (action & PaintContext.ToolAction.PaintTexture)) undoObjects.AddRange(tile.terrain.terrainData.alphamapTextures); Undo.RegisterCompleteObjectUndo(undoObjects.ToArray(), editorUndoName); } @@ -67,31 +61,15 @@ internal static void UpdateTerrainDataUndo(TerrainData terrainData, string undoN } } - public static void ShowDefaultPreviewBrush(Terrain terrain, Texture brushTexture, float brushStrength, float brushSize, float futurePreviewScale) + public static void ShowDefaultPreviewBrush(Terrain terrain, Texture brushTexture, float brushSize) { Ray mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); RaycastHit hit; if (terrain.GetComponent().Raycast(mouseRay, out hit, Mathf.Infinity)) { - if (Event.current.shift) - brushStrength = -brushStrength; - - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, hit.textureCoord, brushSize); - TerrainPaintUtility.PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushRect); - - ctx.sourceRenderTexture.filterMode = FilterMode.Bilinear; - brushTexture.filterMode = FilterMode.Bilinear; - - Vector2 topLeft = ctx.brushRect.min; - float xfrac = ((topLeft.x - (int)topLeft.x) / (float)ctx.sourceRenderTexture.width); - float yfrac = ((topLeft.y - (int)topLeft.y) / (float)ctx.sourceRenderTexture.height); - - Vector4 texScaleOffset = new Vector4(0.5f, 0.5f, 0.5f + xfrac + 0.5f / (float)ctx.sourceRenderTexture.width, 0.5f + yfrac + 0.5f / (float)ctx.sourceRenderTexture.height); - - DrawDefaultBrushPreviewMesh(terrain, hit, ctx.sourceRenderTexture, brushTexture, brushStrength * 0.01f, brushSize, defaultPreviewPatchMesh, false, texScaleOffset); - if ((futurePreviewScale > Mathf.Epsilon) && Event.current.control) - DrawDefaultBrushPreviewMesh(terrain, hit, ctx.sourceRenderTexture, brushTexture, futurePreviewScale, brushSize, defaultPreviewPatchMesh, true, texScaleOffset); - + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, hit.textureCoord, brushSize, 0.0f); + PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); + DrawBrushPreview(ctx, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, brushTexture, brushXform, GetDefaultBrushPreviewMaterial(), 0); TerrainPaintUtility.ReleaseContextResources(ctx); } } @@ -103,83 +81,96 @@ public static Material GetDefaultBrushPreviewMaterial() return m_BrushPreviewMaterial; } - // drawing utilities - - internal static Mesh GenerateDefaultBrushPreviewMesh(int tesselationLevel) + public enum BrushPreview { - if (tesselationLevel < 1) - { - Debug.LogWarning("Invalid tessellation level passed to GenerateBrushPreviewMesh."); - return null; - } - - var verts = new List(); - var indices = new List(); - - Mesh m = new Mesh(); - - float incr = 2.0f / (float)tesselationLevel; - - Vector3 v = new Vector3(-1.0f, 0, -1.0f); - - for (int i = 0; i <= tesselationLevel; i++) - { - v.x = -1.0f; - for (int j = 0; j <= tesselationLevel; j++) - { - verts.Add(v); - v.x += incr; - - if (i != tesselationLevel && j != tesselationLevel) - { - int index = i * (tesselationLevel + 1) + j; - - indices.Add(index); - indices.Add(index + tesselationLevel + 1); - indices.Add(index + 1); - - indices.Add(index + 1); - indices.Add(index + tesselationLevel + 1); - indices.Add(index + tesselationLevel + 2); - } - } - v.z += incr; - } - - m.vertices = verts.ToArray(); - m.triangles = indices.ToArray(); - - return m; - } - - public static void DrawDefaultBrushPreviewMesh(Terrain terrain, RaycastHit hit, Texture heightmapTexture, Texture brushTexture, float brushStrength, float brushSize, Mesh mesh, bool showPreviewPostBrush, Vector4 texScaleOffset) + SourceRenderTexture, + DestinationRenderTexture + }; + + public static void DrawBrushPreview( + PaintContext heightmapPC, + BrushPreview previewTexture, + Texture brushTexture, // brush texture to apply + BrushTransform brushXform, // brush transform that defines the brush UV space + Material proceduralMaterial, // the material to render with (must support procedural quad-mesh generation) + int materialPassIndex) // the pass to use within the material { - Vector4 brushParams = new Vector4(brushStrength, 2.0f * terrain.terrainData.heightmapScale.y, 0.0f, 0.0f); - - Material mat = GetDefaultBrushPreviewMaterial(); - mat.SetTexture("_MainTex", heightmapTexture); - mat.SetTexture("_BrushTex", brushTexture); - mat.SetVector("_BrushParams", brushParams); - mat.SetVector("_TexScaleOffet", texScaleOffset); - mat.SetPass(showPreviewPostBrush ? 1 : 0); - - Matrix4x4 matrix = Matrix4x4.identity; - matrix.SetTRS(new Vector3(hit.point.x, terrain.GetPosition().y, hit.point.z), Quaternion.identity, new Vector3(brushSize / 2.0f, 1, brushSize / 2.0f)); - - Graphics.DrawMeshNow(mesh, matrix); + // we want to build a quad mesh, with one vertex for each pixel in the heightmap + // i.e. a 3x3 heightmap would create a mesh that looks like this: + // + // +-+-+ + // |\|\| + // +-+-+ + // |\|\| + // +-+-+ + // + int quadsX = heightmapPC.pixelRect.width - 1; + int quadsY = heightmapPC.pixelRect.height - 1; + int vertexCount = quadsX * quadsY * (2 * 3); // two triangles (2 * 3 vertices) per quad + + // this is used to tessellate the quad mesh (from within the vertex shader) + proceduralMaterial.SetVector("_QuadRez", new Vector4(quadsX, quadsY, vertexCount, 0.0f)); + + // paint context pixels to heightmap uv: uv = (pixels + 0.5) / width + Texture heightmapTexture = (previewTexture == BrushPreview.SourceRenderTexture) ? heightmapPC.sourceRenderTexture : heightmapPC.destinationRenderTexture; + float invWidth = 1.0f / heightmapTexture.width; + float invHeight = 1.0f / heightmapTexture.height; + proceduralMaterial.SetVector("_HeightmapUV_PCPixelsX", new Vector4(invWidth, 0.0f, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_HeightmapUV_PCPixelsY", new Vector4(0.0f, invHeight, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_HeightmapUV_Offset", new Vector4(0.5f * invWidth, 0.5f * invHeight, 0.0f, 0.0f)); + + // make sure we point filter the heightmap + FilterMode oldFilter = heightmapTexture.filterMode; + heightmapTexture.filterMode = FilterMode.Point; + proceduralMaterial.SetTexture("_Heightmap", heightmapTexture); + + // paint context pixels to object (terrain) position + // objectPos.x = scaleX * pcPixels.x + heightmapRect.xMin * scaleX + // objectPos.y = scaleY * H + // objectPos.z = scaleZ * pcPixels.y + heightmapRect.yMin * scaleZ + float scaleX = heightmapPC.pixelSize.x; + float scaleY = 2.0f * heightmapPC.originTerrain.terrainData.heightmapScale.y; + float scaleZ = heightmapPC.pixelSize.y; + proceduralMaterial.SetVector("_ObjectPos_PCPixelsX", new Vector4(scaleX, 0.0f, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_ObjectPos_HeightMapSample", new Vector4(0.0f, scaleY, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_ObjectPos_PCPixelsY", new Vector4(0.0f, 0.0f, scaleZ, 0.0f)); + proceduralMaterial.SetVector("_ObjectPos_Offset", new Vector4(heightmapPC.pixelRect.xMin * scaleX, 0.0f, heightmapPC.pixelRect.yMin * scaleZ, 1.0f)); + + // heightmap paint context pixels to brush UV + // derivation: + + // BrushUV = f(terrainSpace.xz) = f(g(pcPixels.xy)) + // f(ts.xy) = ts.x * brushXform.X + ts.y * brushXform.Y + brushXform.Origin + // g(pcPixels.xy) = ts.xz = pcOrigin + pcPixels.xy * pcSize + // f(g(pcPixels.uv)) == (pcOrigin + pcPixels.uv * pcSize).x * brushXform.X + (pcOrigin + pcPixels.uv * pcSize).y * brushXform.Y + brushXform.Origin + // f(g(pcPixels.uv)) == (pcOrigin.x + pcPixels.u * pcSize.x) * brushXform.X + (pcOrigin.y + pcPixels.v * pcSize.y) * brushXform.Y + brushXform.Origin + // f(g(pcPixels.uv)) == (pcOrigin.x * brushXform.X) + (pcPixels.u * pcSize.x) * brushXform.X + (pcOrigin.y * brushXform.Y) + (pcPixels.v * pcSize.y) * brushXform.Y + brushXform.Origin + // f(g(pcPixels.uv)) == pcPixels.u * (pcSize.x * brushXform.X) + pcPixels.v * (pcSize.y * brushXform.Y) + (brushXform.Origin + (pcOrigin.x * brushXform.X) + (pcOrigin.y * brushXform.Y)) + + // paint context origin in terrain space + // (note this is the UV space origin and size, not the mesh origin & size) + float pcOriginX = heightmapPC.pixelRect.xMin * heightmapPC.pixelSize.x; + float pcOriginZ = heightmapPC.pixelRect.yMin * heightmapPC.pixelSize.y; + float pcSizeX = heightmapPC.pixelSize.x; + float pcSizeZ = heightmapPC.pixelSize.y; + + Vector2 scaleU = pcSizeX * brushXform.targetX; + Vector2 scaleV = pcSizeZ * brushXform.targetY; + Vector2 offset = brushXform.targetOrigin + pcOriginX * brushXform.targetX + pcOriginZ * brushXform.targetY; + proceduralMaterial.SetVector("_BrushUV_PCPixelsX", new Vector4(scaleU.x, scaleU.y, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_BrushUV_PCPixelsY", new Vector4(scaleV.x, scaleV.y, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_BrushUV_Offset", new Vector4(offset.x, offset.y, 0.0f, 1.0f)); + proceduralMaterial.SetTexture("_BrushTex", brushTexture); + + Vector3 terrainPos = heightmapPC.originTerrain.GetPosition(); + proceduralMaterial.SetVector("_TerrainObjectToWorldOffset", terrainPos); + + proceduralMaterial.SetPass(materialPassIndex); + Graphics.DrawProcedural(MeshTopology.Triangles, vertexCount); + + heightmapTexture.filterMode = oldFilter; } - static Mesh m_DefaultPreviewPatchMesh = null; static Material m_BrushPreviewMaterial = null; - - public static Mesh defaultPreviewPatchMesh - { - get - { - if (m_DefaultPreviewPatchMesh == null) - m_DefaultPreviewPatchMesh = GenerateDefaultBrushPreviewMesh(100); - return m_DefaultPreviewPatchMesh; - } - } } } diff --git a/Modules/UIElements/VisualElement.cs b/Modules/UIElements/VisualElement.cs index 43ab959327..ccd739578f 100644 --- a/Modules/UIElements/VisualElement.cs +++ b/Modules/UIElements/VisualElement.cs @@ -620,9 +620,25 @@ internal void SetPanel(BaseVisualElementPanel p) elements.Add(this); GatherAllChildren(elements); - foreach (var e in elements) + EventDispatcher.Gate? pDispatcherGate = null; + if (p?.dispatcher != null) { - e.ChangePanel(p); + pDispatcherGate = new EventDispatcher.Gate(p.dispatcher); + } + + EventDispatcher.Gate? panelDispatcherGate = null; + if (panel?.dispatcher != null && panel.dispatcher != p?.dispatcher) + { + panelDispatcherGate = new EventDispatcher.Gate(panel.dispatcher); + } + + using (pDispatcherGate) + using (panelDispatcherGate) + { + foreach (var e in elements) + { + e.ChangePanel(p); + } } } finally @@ -655,7 +671,7 @@ void ChangePanel(BaseVisualElementPanel p) using (var e = AttachToPanelEvent.GetPooled(prevPanel, p)) { e.target = this; - elementPanel.SendEvent(e, DispatchMode.Immediate); + elementPanel.SendEvent(e, DispatchMode.Default); } } diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index 9eb5fc83be..953308b49b 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -1488,6 +1488,12 @@ Modules\Substance\SubstanceUtility.cs + + Modules\Terrain\Public\BrushTransform.cs + + + Modules\Terrain\Public\PaintContext.cs + Modules\Terrain\Public\Terrain.bindings.cs diff --git a/README.md b/README.md index 8700f0282d..9d239fc5b0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b5 C# reference source code +## Unity 2018.3.0b6 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/AR/Tango/ScriptBindings/Tango.bindings.cs b/Runtime/AR/Tango/ScriptBindings/Tango.bindings.cs index d075d899e2..9a40d7718b 100644 --- a/Runtime/AR/Tango/ScriptBindings/Tango.bindings.cs +++ b/Runtime/AR/Tango/ScriptBindings/Tango.bindings.cs @@ -13,24 +13,6 @@ namespace UnityEngine.XR.Tango { - // This must correspond to Tango::CoordinateFrame in TangoTypes.h - internal enum CoordinateFrame - { - GlobalWGS84 = 0, - AreaDescription, - StartOfService, - PreviousDevicePose, - Device, - IMU, - Display, - CameraColor, - CameraDepth, - CameraFisheye, - UUID, - Invalid, - MaxCoordinateFrameType - } - internal enum PoseStatus { Initializing = 0, @@ -41,31 +23,16 @@ internal enum PoseStatus [UsedByNativeCode] [NativeHeader("ARScriptingClasses.h")] - [StructLayout(LayoutKind.Explicit, Size = 8)] - internal struct CoordinateFramePair - { - [FieldOffset(0)] public CoordinateFrame baseFrame; - [FieldOffset(4)] public CoordinateFrame targetFrame; - } - - [UsedByNativeCode] - [NativeHeader("ARScriptingClasses.h")] - [StructLayout(LayoutKind.Explicit, Size = 92)] internal struct PoseData { - [FieldOffset(0)] public uint version; - [FieldOffset(8)] public double timestamp; - [FieldOffset(16)] public double orientation_x; - [FieldOffset(24)] public double orientation_y; - [FieldOffset(32)] public double orientation_z; - [FieldOffset(40)] public double orientation_w; - [FieldOffset(48)] public double translation_x; - [FieldOffset(56)] public double translation_y; - [FieldOffset(64)] public double translation_z; - [FieldOffset(72)] public PoseStatus statusCode; - [FieldOffset(76)] public CoordinateFramePair frame; - [FieldOffset(84)] public uint confidence; - [FieldOffset(88)] public float accuracy; + public double orientation_x; + public double orientation_y; + public double orientation_z; + public double orientation_w; + public double translation_x; + public double translation_y; + public double translation_z; + public PoseStatus statusCode; public Quaternion rotation { @@ -78,24 +45,15 @@ public Vector3 position } } - [NativeHeader("Runtime/AR/Tango/TangoScriptApi.h")] [NativeConditional("PLATFORM_ANDROID")] internal static partial class TangoInputTracking { - extern private static bool Internal_TryGetPoseAtTime(double time, ScreenOrientation screenOrientation, - CoordinateFrame baseFrame, CoordinateFrame targetFrame, out PoseData pose); - - internal static bool TryGetPoseAtTime(out PoseData pose, CoordinateFrame baseFrame, CoordinateFrame targetFrame, - double time, ScreenOrientation screenOrientation) - { - return Internal_TryGetPoseAtTime(time, screenOrientation, baseFrame, targetFrame, out pose); - } + extern private static bool Internal_TryGetPoseAtTime(out PoseData pose); - internal static bool TryGetPoseAtTime(out PoseData pose, CoordinateFrame baseFrame, CoordinateFrame targetFrame, - double time = 0.0) + internal static bool TryGetPoseAtTime(out PoseData pose) { - return Internal_TryGetPoseAtTime(time, Screen.orientation, baseFrame, targetFrame, out pose); + return Internal_TryGetPoseAtTime(out pose); } } } From 94dfaf4e9dea0bab6989dd1a1d9650a206b7d465 Mon Sep 17 00:00:00 2001 From: LosingLin <764837522@qq.com> Date: Tue, 23 Oct 2018 15:24:47 +0800 Subject: [PATCH 16/17] delete all Files --- .../SpriteEditorExtension.bindings.cs | 22 - .../TexturePlatformSettingsController.cs | 191 - .../TexturePlatformSettingsFormatHelper.cs | 57 - .../2D/Common/TexturePlatformSettingsView.cs | 137 - Editor/Mono/2D/Interface/IAssetDatabase.cs | 28 - Editor/Mono/2D/Interface/IEvent.cs | 105 - Editor/Mono/2D/Interface/IGL.cs | 70 - Editor/Mono/2D/Interface/IGUIUtility.cs | 51 - Editor/Mono/2D/Interface/IHandles.cs | 79 - .../2D/Interface/ISpriteEditorDataProvider.cs | 456 - Editor/Mono/2D/Interface/ITexture.cs | 146 - .../2D/Interface/ITexturePlatformSetting.cs | 34 - Editor/Mono/2D/Interface/IUndoSystem.cs | 45 - .../2D/SpriteAtlas/SpriteAtlasInspector.cs | 671 -- .../SpriteEditorModule/ISpriteEditorModule.cs | 60 - .../2D/SpriteEditorModule/SpriteEditorData.cs | 124 - .../SpriteFrameModule/SpriteFrameModule.cs | 321 - .../SpriteFrameModuleBase.cs | 336 - .../SpriteFrameModuleBaseView.cs | 522 - .../SpriteFrameModuleView.cs | 221 - .../SpritePolygonModeModule.cs | 95 - .../SpritePolygonModeModuleView.cs | 164 - .../SpriteEditorModule/SpriteOutlineModule.cs | 821 -- .../SpritePhysicsShapeModule.cs | 81 - .../2D/SpriteEditorModule/TextureImporter.cs | 167 - .../UserAccessibilitySettings.cs | 46 - .../AnimationClipSettings.bindings.cs | 41 - .../Animation/AnimationClipStats.bindings.cs | 63 - .../Mono/Animation/AnimationMode.bindings.cs | 165 - .../Animation/AnimationUtility.bindings.cs | 338 - .../AnimationWindow/AddCurvesPopup.cs | 88 - .../AddCurvesPopupHierarchy.cs | 52 - .../AddCurvesPopupHierarchyDataSource.cs | 259 - .../AddCurvesPopupHierarchyGUI.cs | 76 - .../Animation/AnimationWindow/AnimEditor.cs | 1248 --- .../AnimationWindow/AnimEditorOverlay.cs | 132 - .../AnimationClipSelectionItem.cs | 35 - .../AnimationContextualPropertyMenu.cs | 181 - .../AnimationWindow/AnimationKeyTime.cs | 75 - .../AnimationWindow/AnimationRecording.cs | 825 -- .../AnimationWindow/AnimationWindow.cs | 289 - .../AnimationWindowClipPopup.cs | 119 - .../AnimationWindow/AnimationWindowControl.cs | 848 -- .../AnimationWindow/AnimationWindowCurve.cs | 325 - .../AnimationWindow/AnimationWindowEvent.cs | 103 - .../AnimationWindowEventInspector.cs | 506 - .../AnimationWindowHierarchy.cs | 105 - .../AnimationWindowHierarchyDataSource.cs | 163 - .../AnimationWindowHierarchyGUI.cs | 894 -- .../AnimationWindowHierarchyNode.cs | 74 - .../AnimationWindowKeySelection.cs | 42 - .../AnimationWindowKeyframe.cs | 174 - .../AnimationWindowManipulator.cs | 192 - .../AnimationWindowSelectionItem.cs | 361 - .../AnimationWindow/AnimationWindowState.cs | 1650 ---- .../AnimationWindow/AnimationWindowStyles.cs | 65 - .../AnimationWindow/AnimationWindowUtility.cs | 1202 --- .../AnimationWindow/ControlPointRenderer.cs | 179 - .../AnimationWindow/CurveBindingUtility.cs | 48 - .../Animation/AnimationWindow/CurveEditor.cs | 4002 -------- .../CurveEditorRectangleTool.cs | 850 -- .../AnimationWindow/CurveEditorSelection.cs | 82 - .../AnimationWindow/CurveEditorSettings.cs | 77 - .../AnimationWindow/CurveEditorWindow.cs | 602 -- .../AnimationWindow/CurveMenuManager.cs | 364 - .../CurveRenderer/BoolCurveRenderer.cs | 30 - .../CurveRenderer/CurveRenderer.cs | 28 - .../EulerCurveCombinedRenderer.cs | 308 - .../CurveRenderer/EulerCurveRenderer.cs | 79 - .../CurveRenderer/IntCurveRenderer.cs | 55 - .../CurveRenderer/NormalCurveRenderer.cs | 651 -- .../Deprecated/AnimationEventTimeline.cs | 452 - .../Deprecated/EditorGUIExt.cs | 853 -- .../Deprecated/UtilityClasses.cs | 466 - .../Animation/AnimationWindow/DopeLine.cs | 122 - .../AnimationWindow/DopeSheetEditor.cs | 1489 --- .../DopeSheetEditorRectangleTool.cs | 364 - .../GameObjectSelectionItem.cs | 68 - .../IAnimationContextualResponder.cs | 37 - .../IAnimationRecordingState.cs | 28 - .../IAnimationWindowControl.cs | 56 - .../AnimationWindow/RectangleTool.cs | 251 - .../RotationCurveInterpolation.cs | 286 - Editor/Mono/Animation/AnimatorController.cs | 289 - Editor/Mono/Animation/BlendTree.cs | 95 - .../Animation/EditorCurveBinding.bindings.cs | 110 - .../Animation/GameObjectRecorder.bindings.cs | 54 - .../Animation/MaterialAnimationUtility.cs | 193 - Editor/Mono/Animation/MecanimUtilities.cs | 49 - .../Mono/Animation/SerializedStringTable.cs | 71 - Editor/Mono/Animation/StateMachine.cs | 721 -- Editor/Mono/Animation/TickHandler.cs | 214 - Editor/Mono/Animation/TickStyle.cs | 21 - Editor/Mono/Animation/TimeArea.cs | 547 -- Editor/Mono/Animation/TransitionPreview.cs | 758 -- Editor/Mono/Animation/ZoomableArea.cs | 884 -- .../AnimationCurvePreviewCache.bindings.cs | 119 - Editor/Mono/AnimatorController.bindings.cs | 138 - .../Mono/AnimatorControllerLayer.bindings.cs | 126 - Editor/Mono/Annotation/AnnotationWindow.cs | 675 -- .../Mono/Annotation/LayerVisibilityWindow.cs | 323 - Editor/Mono/Annotation/SceneFXWindow.cs | 103 - .../Mono/Annotation/SceneRenderModeWindow.cs | 339 - Editor/Mono/AssembleEditorSkin.cs | 34 - Editor/Mono/AssemblyHelper.cs | 419 - Editor/Mono/AssemblyInfo/AssemblyInfo.cs | 90 - Editor/Mono/AssemblyReloadEvents.cs | 29 - .../AssetDatabase/AssetDatabase.bindings.cs | 96 - Editor/Mono/AssetDatabase/AssetDatabase.cs | 57 - .../AssetDatabase/AssetDatabase.deprecated.cs | 52 - .../AssetDatabase/AssetDatabaseSearching.cs | 76 - .../AssetImportInProgressProxy.bindings.cs | 41 - Editor/Mono/AssetModificationProcessor.cs | 317 - .../AssemblyDefinitionImporter.cs | 20 - .../AssetImportContext.bindings.cs | 82 - .../AssetPipeline/AssetImporter.bindings.cs | 135 - Editor/Mono/AssetPipeline/LocalCacheServer.cs | 230 - .../AssetPipeline/ModelImporter.bindings.cs | 866 -- .../AssetPipeline/MonoImporter.bindings.cs | 33 - .../NativeFormatImporterUtility.bindings.cs | 138 - Editor/Mono/AssetPipeline/ScriptedImporter.cs | 128 - .../TextureGenerator.bindings.cs | 232 - Editor/Mono/AssetPostprocessor.cs | 478 - Editor/Mono/AssetPreviewUpdater.cs | 52 - Editor/Mono/AssetStore/AssetStoreAsset.cs | 146 - .../AssetStore/AssetStoreAssetSelection.cs | 296 - Editor/Mono/AssetStore/AssetStoreClient.cs | 860 -- Editor/Mono/AssetStore/AssetStoreContext.cs | 435 - .../AssetStore/AssetStoreInstaBuyWindow.cs | 521 - .../Mono/AssetStore/AssetStoreLoginWIndow.cs | 234 - .../AssetStore/AssetStorePreviewManager.cs | 380 - Editor/Mono/AssetStore/AssetStoreWindow.cs | 363 - Editor/Mono/AssetStore/Json.cs | 676 -- Editor/Mono/AssetStoreToolUtils.cs | 35 - Editor/Mono/AsyncHTTPClient.bindings.cs | 30 - Editor/Mono/AsyncHTTPClient.cs | 231 - Editor/Mono/AsyncProgressBar.bindings.cs | 25 - Editor/Mono/AttributeHelper.cs | 303 - .../Mono/Audio/Effects/AudioCurveRendering.cs | 294 - .../Audio/Effects/AudioMixerEffectPlugin.cs | 67 - Editor/Mono/Audio/Effects/Complex.cs | 148 - Editor/Mono/Audio/Effects/DuckVolumeGUI.cs | 338 - .../Mono/Audio/Effects/IAudioEffectPlugin.cs | 23 - .../Audio/Effects/IAudioEffectPluginGUI.cs | 21 - Editor/Mono/Audio/Effects/ParamEQGUI.cs | 197 - .../Mono/Audio/Mixer/AudioMixerDescription.cs | 156 - .../Mixer/Bindings/AudioMixerController.cs | 1085 --- .../Audio/Mixer/Bindings/AudioMixerGroup.cs | 72 - .../Mixer/GUI/AudioMixerChannelStripView.cs | 1730 ---- .../Audio/Mixer/GUI/AudioMixerColorCodes.cs | 98 - .../Audio/Mixer/GUI/AudioMixerDrawUtils.cs | 369 - .../Audio/Mixer/GUI/AudioMixerEffectGUI.cs | 167 - .../Audio/Mixer/GUI/AudioMixerEffectView.cs | 593 -- .../GUI/AudioMixerExposedParameterView.cs | 174 - .../GUI/AudioMixerExposedParametersPopup.cs | 61 - .../Mixer/GUI/AudioMixerGroupTreeView.cs | 680 -- .../Mixer/GUI/AudioMixerGroupViewList.cs | 248 - .../Audio/Mixer/GUI/AudioMixerSelection.cs | 82 - .../Mixer/GUI/AudioMixerSnapshotPopup.cs | 42 - .../Audio/Mixer/GUI/AudioMixerSnapshotView.cs | 299 - .../Mono/Audio/Mixer/GUI/AudioMixerUtility.cs | 38 - .../Mono/Audio/Mixer/GUI/AudioMixerWindow.cs | 809 -- .../Audio/Mixer/GUI/AudioMixersTreeView.cs | 730 -- .../Audio/Mixer/GUI/ObjectTreeSelector.cs | 378 - .../ReorderableListWithRenameAndScrollView.cs | 330 - .../Mixer/GUI/TreeViewForAudioMixerGroups.cs | 297 - Editor/Mono/Audio/StreamedAudioClipPreview.cs | 466 - Editor/Mono/Audio/WaveformPreview.cs | 273 - Editor/Mono/Audio/WaveformPreviewFactory.cs | 20 - .../Mono/Audio/WaveformStreamer.bindings.cs | 64 - Editor/Mono/AvatarUtility.bindings.cs | 19 - Editor/Mono/BlendTree.bindings.cs | 131 - .../Mono/BlendTreePreviewUtility.bindings.cs | 28 - Editor/Mono/BuildPipeline/AssemblyStripper.cs | 314 - .../AssemblyTypeInfoGenerator.cs | 429 - .../Mono/BuildPipeline/AssemblyValidation.cs | 160 - .../BuildPipeline/BuildFailedException.cs | 29 - .../BuildPipeline/BuildPipelineInterfaces.cs | 377 - Editor/Mono/BuildPipeline/BuildPlatform.cs | 190 - Editor/Mono/BuildPipeline/BuildUtils.cs | 147 - Editor/Mono/BuildPipeline/BuildVerifier.cs | 81 - .../Mono/BuildPipeline/CodeStrippingUtils.cs | 713 -- .../DesktopStandaloneBuildWindowExtension.cs | 212 - .../DesktopStandalonePostProcessor.cs | 465 - .../DesktopStandaloneUserBuildSettings.cs | 23 - .../GendarmeAssemblyValidation.cs | 108 - .../BuildPipeline/Il2Cpp/FileMirroring.cs | 158 - .../BuildPipeline/Il2Cpp/ICompilerSettings.cs | 11 - .../Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs | 603 -- .../BuildPipeline/Il2Cpp/INativeCompiler.cs | 10 - .../Il2Cpp/Il2CppNativeCodeBuilder.cs | 125 - .../Il2Cpp/Il2CppNativeCodeBuilderUtils.cs | 103 - .../BuildPipeline/Il2Cpp/NativeCompiler.cs | 116 - .../BuildPipeline/MonoAssemblyStripping.cs | 333 - Editor/Mono/BuildPipeline/MonoCrossCompile.cs | 335 - .../MonoInternalCallGenerator.cs | 390 - .../PostProcessStandalonePlayer.cs | 14 - .../BuildPipeline/PostprocessBuildPlayer.cs | 334 - .../BuildPipeline/RuntimeClassMetadata.cs | 173 - Editor/Mono/BuildPipeline/WinRT/WinRTUtils.cs | 25 - Editor/Mono/BuildPlayerSceneTreeView.cs | 322 - Editor/Mono/BuildPlayerWindow.cs | 886 -- Editor/Mono/BuildPlayerWindowBuildMethods.cs | 392 - Editor/Mono/BuildPlayerWindowPublish.cs | 308 - Editor/Mono/BuildTarget.cs | 128 - Editor/Mono/BuildTargetGroup.cs | 92 - .../Burst/BurstCompilerService.bindings.cs | 32 - Editor/Mono/Burst/BurstCompilerService.cs | 35 - Editor/Mono/CSPreProcess.cs | 90 - Editor/Mono/Callbacks.cs | 81 - Editor/Mono/ChangeTrackerHandle.bindings.cs | 60 - Editor/Mono/CloudBuild/CloudBuild.cs | 182 - Editor/Mono/Collab/AssetAccess.cs | 128 - Editor/Mono/Collab/CloudBuildStatus.cs | 26 - Editor/Mono/Collab/Collab.bindings.cs | 22 - Editor/Mono/Collab/Collab.cs | 370 - Editor/Mono/Collab/CollabAnalytics.cs | 32 - Editor/Mono/Collab/CollabChange.cs | 67 - Editor/Mono/Collab/CollabChangeAction.cs | 24 - Editor/Mono/Collab/CollabDialogs.cs | 146 - Editor/Mono/Collab/CollabEditorHooks.cs | 194 - Editor/Mono/Collab/CollabFilters.cs | 168 - Editor/Mono/Collab/CollabHistoryWindow.cs | 307 - Editor/Mono/Collab/CollabProgressInfo.cs | 70 - Editor/Mono/Collab/CollabRevision.cs | 40 - Editor/Mono/Collab/CollabRevisionsData.cs | 27 - Editor/Mono/Collab/CollabTesting.cs | 91 - Editor/Mono/Collab/CollabToolbarWindow.cs | 139 - .../Presenters/CollabHistoryPresenter.cs | 276 - Editor/Mono/Collab/RevisionsService.cs | 79 - .../Mono/Collab/Softlocks/CollabSoftLocks.cs | 31 - Editor/Mono/Collab/Softlocks/SoftlockData.cs | 192 - .../Mono/Collab/Softlocks/SoftlockFilter.cs | 38 - .../Mono/Collab/Softlocks/SoftlockUIData.cs | 207 - .../Softlocks/SoftlockViewController.cs | 531 -- Editor/Mono/Collab/Views/BuildStatusButton.cs | 52 - .../Collab/Views/CollabHistoryDropDown.cs | 76 - .../Collab/Views/CollabHistoryDropDownItem.cs | 51 - Editor/Mono/Collab/Views/CollabHistoryItem.cs | 228 - .../Collab/Views/CollabHistoryItemFactory.cs | 119 - .../Collab/Views/CollabHistoryRevisionLine.cs | 93 - .../Collab/Views/HistoryProgressSpinner.cs | 68 - .../Collab/Views/ICollabHistoryItemFactory.cs | 16 - .../Mono/Collab/Views/ICollabHistoryWindow.cs | 80 - Editor/Mono/Collab/Views/PagedListView.cs | 194 - Editor/Mono/Collab/Views/StatusView.cs | 87 - Editor/Mono/Commands/GOCreationCommands.cs | 270 - Editor/Mono/CompilationPipeline.bindings.cs | 17 - Editor/Mono/ComponentUtility.cs | 74 - Editor/Mono/ConsoleWindow.cs | 854 -- Editor/Mono/ContainerWindow.cs | 454 - Editor/Mono/CustomEditorAttributes.cs | 183 - Editor/Mono/DataWatchService.cs | 252 - Editor/Mono/DefaultAsset.bindings.cs | 34 - .../DefaultDeploymentTargetsExtension.cs | 47 - .../DeploymentTargetManager.cs | 87 - .../IDeploymentTargetsExtension.cs | 141 - Editor/Mono/DisplayUtility.cs | 44 - .../DrivenPropertyManagerInternal.bindings.cs | 23 - Editor/Mono/DrivenRectTransformUndo.cs | 25 - Editor/Mono/DropInfo.cs | 38 - Editor/Mono/EditorApplication.cs | 316 - Editor/Mono/EditorApplication.deprecated.cs | 124 - Editor/Mono/EditorAssemblies.bindings.cs | 54 - Editor/Mono/EditorAssemblies.cs | 144 - Editor/Mono/EditorBuildSettings.bindings.cs | 123 - .../EditorGUI.EnumMaskField.deprecated.cs | 424 - Editor/Mono/EditorGUI.bindings.cs | 18 - Editor/Mono/EditorGUI.cs | 8378 ----------------- Editor/Mono/EditorGUIUtility.bindings.cs | 162 - Editor/Mono/EditorGUIUtility.cs | 347 - Editor/Mono/EditorGraphicsSettings.cs | 122 - Editor/Mono/EditorHandles.cs | 575 -- Editor/Mono/EditorHandles/ArcHandle.cs | 239 - Editor/Mono/EditorHandles/BoneHandle.cs | 234 - .../BoundsHandle/BoxBoundsHandle.cs | 24 - .../BoundsHandle/CapsuleBoundsHandle.cs | 203 - .../BoundsHandle/PrimitiveBoundsHandle.cs | 319 - .../BoundsHandle/SphereBoundsHandle.cs | 81 - Editor/Mono/EditorHandles/Button.cs | 107 - .../Mono/EditorHandles/ConeFrustrumHandle.cs | 71 - Editor/Mono/EditorHandles/ConeHandle.cs | 69 - Editor/Mono/EditorHandles/Disc.cs | 207 - Editor/Mono/EditorHandles/FreeMove.cs | 300 - Editor/Mono/EditorHandles/FreeRotate.cs | 138 - .../EditorHandles/JointAngularLimitHandle.cs | 529 -- Editor/Mono/EditorHandles/PositionHandle.cs | 452 - Editor/Mono/EditorHandles/RadiusHandle.cs | 142 - Editor/Mono/EditorHandles/RectHandle.cs | 53 - Editor/Mono/EditorHandles/RotationHandle.cs | 191 - Editor/Mono/EditorHandles/ScaleHandle.cs | 229 - .../Mono/EditorHandles/SimpleRadiusHandle.cs | 89 - Editor/Mono/EditorHandles/Slider1D.cs | 185 - Editor/Mono/EditorHandles/Slider2D.cs | 433 - Editor/Mono/EditorHandles/SliderScale.cs | 256 - Editor/Mono/EditorHandles/TransformHandle.cs | 342 - Editor/Mono/EditorHandles/VertexSnapping.cs | 159 - Editor/Mono/EditorHeaderItemAttribute.cs | 26 - .../Mono/EditorResourcesUtility.bindings.cs | 33 - .../Mono/EditorUserBuildSettings.bindings.cs | 617 -- .../EditorUserBuildSettings.deprecated.cs | 35 - Editor/Mono/EditorUserBuildSettingsUtils.cs | 30 - Editor/Mono/EditorUtility.bindings.cs | 35 - Editor/Mono/EditorWindow.cs | 994 -- Editor/Mono/ExportPackageOptions.cs | 27 - Editor/Mono/FileUtil.bindings.cs | 144 - Editor/Mono/FileUtil.cs | 318 - Editor/Mono/FlagSet.cs | 36 - .../GI/LightmapEditorSettingsDeprecated.cs | 197 - Editor/Mono/GI/LightmapSnapshot.deprecated.cs | 16 - Editor/Mono/GI/Lightmapping.deprecated.cs | 33 - Editor/Mono/GUI/AboutWindow.cs | 258 - Editor/Mono/GUI/AboutWindowNames.cs | 157 - Editor/Mono/GUI/AngularDial.cs | 121 - Editor/Mono/GUI/AnimatedValues.cs | 259 - Editor/Mono/GUI/AppStatusBar.cs | 136 - Editor/Mono/GUI/AssetPopupBackend.cs | 123 - Editor/Mono/GUI/AssetSaveDialog.cs | 242 - .../Mono/GUI/BumpMapSettingsFixingWindow.cs | 93 - Editor/Mono/GUI/ButtonWithAnimatedIcon.cs | 81 - Editor/Mono/GUI/CallbackController.cs | 49 - Editor/Mono/GUI/ColorClipboard.cs | 49 - Editor/Mono/GUI/ColorMutator.cs | 219 - Editor/Mono/GUI/ColorPicker.cs | 1415 --- Editor/Mono/GUI/ColorPicker.deprecated.cs | 28 - Editor/Mono/GUI/ColumnView.cs | 329 - Editor/Mono/GUI/CreateAssetUtility.cs | 125 - Editor/Mono/GUI/DockArea.cs | 850 -- Editor/Mono/GUI/DragRect.cs | 66 - Editor/Mono/GUI/EditorApplicationLayout.cs | 93 - Editor/Mono/GUI/EditorCache.cs | 173 - Editor/Mono/GUI/EditorGUIContents.cs | 58 - Editor/Mono/GUI/EditorGUIInternal.cs | 90 - Editor/Mono/GUI/EditorStyles.cs | 418 - Editor/Mono/GUI/EditorUpdateWindow.cs | 148 - Editor/Mono/GUI/ExposablePopupMenu.cs | 165 - Editor/Mono/GUI/FallbackEditorWindow.cs | 38 - Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs | 312 - .../FlexibleMenu/FlexibleMenuModifyItemUI.cs | 47 - .../FlexibleMenu/IFlexibleMenuItemProvider.cs | 20 - Editor/Mono/GUI/FlowLayout.cs | 327 - Editor/Mono/GUI/GenericMenu.cs | 120 - Editor/Mono/GUI/GradientEditor.cs | 605 -- Editor/Mono/GUI/GradientField.cs | 172 - Editor/Mono/GUI/GradientPicker.cs | 260 - Editor/Mono/GUI/HexColorTextField.cs | 59 - Editor/Mono/GUI/InternalEditorGUI.cs | 322 - Editor/Mono/GUI/InternalEditorGUILayout.cs | 34 - Editor/Mono/GUI/Knob.cs | 378 - Editor/Mono/GUI/ListViewElement.cs | 15 - Editor/Mono/GUI/ListViewGUI.cs | 124 - Editor/Mono/GUI/ListViewGUILayout.cs | 215 - Editor/Mono/GUI/ListViewOptions.cs | 8 - Editor/Mono/GUI/ListViewShared.cs | 694 -- Editor/Mono/GUI/ListViewState.cs | 47 - Editor/Mono/GUI/MainView.cs | 76 - Editor/Mono/GUI/MaskFieldGUI.cs | 246 - Editor/Mono/GUI/ObjectField.cs | 502 - Editor/Mono/GUI/PackageExport.cs | 273 - Editor/Mono/GUI/PackageExportTreeView.cs | 483 - Editor/Mono/GUI/PackageImport.cs | 392 - Editor/Mono/GUI/PackageImportTreeView.cs | 662 -- Editor/Mono/GUI/PaneDragTab.cs | 167 - Editor/Mono/GUI/PingData.cs | 83 - Editor/Mono/GUI/PopupLocationHelper.cs | 172 - Editor/Mono/GUI/PopupWindow.cs | 131 - Editor/Mono/GUI/PopupWindowWithoutFocus.cs | 134 - Editor/Mono/GUI/PragmaFixingWindow.cs | 98 - Editor/Mono/GUI/PreviewResizer.cs | 205 - Editor/Mono/GUI/QuadTree.cs | 487 - Editor/Mono/GUI/RenameOverlay.cs | 415 - Editor/Mono/GUI/ReorderableList.cs | 855 -- Editor/Mono/GUI/ScalableGUIContent.cs | 65 - Editor/Mono/GUI/ScreenShotting.cs | 179 - Editor/Mono/GUI/SearchField.cs | 133 - Editor/Mono/GUI/SliderWithTexture.cs | 113 - Editor/Mono/GUI/SplitView.cs | 749 -- Editor/Mono/GUI/Splitter.cs | 485 - Editor/Mono/GUI/StructPropertyGUI.cs | 67 - Editor/Mono/GUI/TargetChoiceHandler.cs | 132 - Editor/Mono/GUI/TextFieldDropDown.cs | 44 - Editor/Mono/GUI/Toolbar.cs | 656 -- Editor/Mono/GUI/Tools/BuiltinTools.cs | 978 -- Editor/Mono/GUI/Tools/SnapSettings.cs | 154 - Editor/Mono/GUI/Tools/Tools.cs | 546 -- Editor/Mono/GUI/Tools/TransformManipulator.cs | 396 - .../AssetOrGameObjectTreeViewDragging.cs | 280 - .../GUI/TreeView/AssetsTreeViewDataSource.cs | 318 - Editor/Mono/GUI/TreeView/AssetsTreeViewGUI.cs | 202 - .../TreeView/GameObjectTreeViewDataSource.cs | 575 -- .../GUI/TreeView/GameObjectTreeViewGUI.cs | 429 - .../GUI/TreeView/GameObjectTreeViewItem.cs | 50 - .../Mono/GUI/TreeView/ITreeViewDataSource.cs | 76 - Editor/Mono/GUI/TreeView/ITreeViewDragging.cs | 30 - Editor/Mono/GUI/TreeView/ITreeViewGUI.cs | 54 - .../GUI/TreeView/LazyTreeViewDataSource.cs | 126 - Editor/Mono/GUI/TreeView/MultiColumnHeader.cs | 497 - .../GUI/TreeView/MultiColumnHeaderDefaults.cs | 58 - .../GUI/TreeView/MultiColumnHeaderState.cs | 156 - .../TreeViewControl/TreeViewControl.cs | 825 -- .../TreeViewControlDataSource.cs | 133 - .../TreeViewControlDefaults.cs | 85 - .../TreeViewControlDragging.cs | 63 - .../TreeViewControl/TreeViewControlGUI.cs | 362 - .../Mono/GUI/TreeView/TreeViewController.cs | 1265 --- .../Mono/GUI/TreeView/TreeViewDataSource.cs | 359 - Editor/Mono/GUI/TreeView/TreeViewDragging.cs | 396 - .../GUI/TreeView/TreeViewExpandAnimator.cs | 320 - Editor/Mono/GUI/TreeView/TreeViewGUI.cs | 502 - .../TreeViewGUIWithCustomItemHeights.cs | 196 - Editor/Mono/GUI/TreeView/TreeViewItem.cs | 88 - .../TreeView/TreeViewTests/TreeViewTest.cs | 143 - .../TreeViewTests/TreeViewTestBackEnd.cs | 243 - .../TreeViewTests/TreeViewTestDataSource.cs | 50 - .../TreeViewTests/TreeViewTestDragging.cs | 82 - .../TreeView/TreeViewTests/TreeViewTestGUI.cs | 87 - .../TreeViewTests/TreeViewTestGUICustom.cs | 130 - .../TreeViewTestLazyDataSource.cs | 85 - .../TreeViewTests/TreeViewTestWindow.cs | 95 - .../TreeViewTestWithCustomHeight.cs | 37 - Editor/Mono/GUI/TreeView/TreeViewUtililty.cs | 223 - Editor/Mono/GUI/TypeSelectionList.cs | 66 - Editor/Mono/GUI/VUMeter.cs | 153 - Editor/Mono/GUI/VerticalGrid.cs | 270 - Editor/Mono/GUI/WindowLayout.cs | 998 -- Editor/Mono/GUID.bindings.cs | 131 - Editor/Mono/GUIDebugger/BaseInspectView.cs | 271 - Editor/Mono/GUIDebugger/GUIClipInspectView.cs | 130 - .../Mono/GUIDebugger/GUILayoutInspectView.cs | 163 - .../GUIDebugger/GUINamedControlInspectView.cs | 84 - .../GUIDebugger/GUIPropertyInspectView.cs | 92 - .../GUIViewDebuggerHelper.bindings.cs | 147 - .../Mono/GUIDebugger/GUIViewDebuggerWindow.cs | 479 - .../Mono/GUIDebugger/StyleDrawInspectView.cs | 263 - Editor/Mono/GUIDebugger/UnifiedInspectView.cs | 164 - Editor/Mono/GUIView.cs | 237 - Editor/Mono/GameObjectUtility.bindings.cs | 132 - Editor/Mono/GameView/GameView.cs | 856 -- Editor/Mono/GameView/GameViewSize.cs | 171 - Editor/Mono/GameView/GameViewSizeGroup.cs | 118 - Editor/Mono/GameView/GameViewSizeMenu.cs | 58 - Editor/Mono/GameView/GameViewSizes.cs | 510 - .../GameView/GameViewSizesMenuItemProvider.cs | 114 - .../GameView/GameViewSizesMenuModifyItemUI.cs | 152 - Editor/Mono/GameView/IGameViewSizeMenuUser.cs | 14 - Editor/Mono/GameviewGUI.cs | 169 - Editor/Mono/GenerateIconsWithMipLevels.cs | 442 - Editor/Mono/GradientPreviewCache.bindings.cs | 18 - Editor/Mono/Grid/GridSnapping.cs | 27 - Editor/Mono/Help.bindings.cs | 55 - Editor/Mono/HomeWindow.bindings.cs | 28 - Editor/Mono/HostView.cs | 480 - Editor/Mono/ICleanuppable.cs | 11 - Editor/Mono/IDropArea.cs | 21 - Editor/Mono/IHasCustomMenu.cs | 13 - Editor/Mono/IconSelector.cs | 351 - .../AnimationClipInfoProperties.cs | 453 - .../ImportSettings/AssetImporterEditor.cs | 284 - .../ImportSettings/AudioImporterInspector.cs | 656 -- .../ImportSettings/BaseAssetImporterTabUI.cs | 95 - .../DesktopPluginImporterExtension.cs | 248 - .../EditorPluginImporterExtension.cs | 64 - .../ImportSettings/ExposeTransformEditor.cs | 76 - .../IHVImageFormatImporterInspector.cs | 97 - .../ImportSettings/ModelImporterClipEditor.cs | 1018 -- .../ImportSettings/ModelImporterEditor.cs | 51 - .../ModelImporterMaterialEditor.cs | 504 - .../ModelImporterModelEditor.cs | 367 - .../ImportSettings/ModelImporterRigEditor.cs | 770 -- .../ImportSettings/MovieImporterInspector.cs | 83 - .../PatchImportSettingsRecycleID.cs | 38 - .../ImportSettings/PluginImporterInspector.cs | 592 -- Editor/Mono/ImportSettings/PrefabUtility.cs | 224 - .../ImportSettings/ScriptedImporterEditor.cs | 44 - .../SpeedTreeImporterInspector.cs | 415 - .../TextureImportPlatformSettings.cs | 520 - .../TextureImporterInspector.cs | 1635 ---- .../TrueTypeFontImporterInspector.cs | 310 - .../VideoClipImporterInspector.cs | 897 -- .../AddComponent/AddComponentDataSource.cs | 107 - .../Inspector/AddComponent/AddComponentGUI.cs | 65 - .../AddComponent/AddComponentWindow.cs | 124 - .../AddComponent/ComponentDropdownItem.cs | 94 - .../AddComponent/NewScriptDropdownItem.cs | 139 - .../AdvancedDropdownDataSource.cs | 93 - .../AdvancedDropdown/AdvancedDropdownGUI.cs | 151 - .../AdvancedDropdown/AdvancedDropdownItem.cs | 202 - .../AdvancedDropdownSimpleDataSource.cs | 71 - .../AdvancedDropdownWindow.cs | 371 - .../StatefulAdvancedDropdown.cs | 42 - .../StatelessAdvancedDropdown.cs | 96 - Editor/Mono/Inspector/AimConstraintEditor.cs | 142 - .../Mono/Inspector/AnchoredJoint2DEditor.cs | 73 - Editor/Mono/Inspector/AnimationClipEditor.cs | 1791 ---- Editor/Mono/Inspector/AnimationEditor.cs | 61 - Editor/Mono/Inspector/AnimatorInspector.cs | 154 - .../AnimatorOverrideControllerInspector.cs | 213 - Editor/Mono/Inspector/AreaEffector2DEditor.cs | 86 - .../AssemblyDefinitionImporterInspector.cs | 677 -- Editor/Mono/Inspector/AssetBundleNameGUI.cs | 225 - .../Inspector/AssetStoreAssetInspector.cs | 547 -- .../Mono/Inspector/AudioChorusFilterEditor.cs | 14 - Editor/Mono/Inspector/AudioClipInspector.cs | 348 - .../AudioDistortionFilterInspector.cs | 14 - .../Inspector/AudioEchoFilterInspector.cs | 14 - Editor/Mono/Inspector/AudioExtensionEditor.cs | 130 - Editor/Mono/Inspector/AudioFilterGUI.cs | 50 - .../Inspector/AudioHighPassFIlterInspector.cs | 14 - .../Inspector/AudioListenerExtensionEditor.cs | 22 - .../Mono/Inspector/AudioListenerInspector.cs | 206 - .../Inspector/AudioLowPassFilterInspector.cs | 37 - .../Mono/Inspector/AudioManagerInspector.cs | 133 - .../AudioMixerControllerInspector.cs | 65 - .../Mono/Inspector/AudioMixerGroupEditor.cs | 93 - .../Mono/Inspector/AudioReverbFilterEditor.cs | 81 - .../Mono/Inspector/AudioReverbZoneEditor.cs | 112 - .../Inspector/AudioSourceExtensionEditor.cs | 24 - Editor/Mono/Inspector/AudioSourceInspector.cs | 900 -- .../Mono/Inspector/Avatar/AvatarAutoMapper.cs | 917 -- .../Inspector/Avatar/AvatarBipedMapper.cs | 282 - .../Inspector/Avatar/AvatarColliderEditor.cs | 243 - Editor/Mono/Inspector/Avatar/AvatarControl.cs | 283 - Editor/Mono/Inspector/Avatar/AvatarEditor.cs | 660 -- .../Inspector/Avatar/AvatarHandleEditor.cs | 466 - .../Inspector/Avatar/AvatarMappingEditor.cs | 872 -- .../Inspector/Avatar/AvatarMuscleEditor.cs | 1130 --- .../Mono/Inspector/Avatar/AvatarSetupTool.cs | 1340 --- .../Inspector/Avatar/AvatarSkeletonDrawer.cs | 169 - Editor/Mono/Inspector/AvatarMaskInspector.cs | 764 -- Editor/Mono/Inspector/AvatarMaskUtility.cs | 163 - Editor/Mono/Inspector/AvatarPreview.cs | 1081 --- .../Mono/Inspector/AvatarPreviewSelection.cs | 45 - .../Mono/Inspector/BillboardAssetInspector.cs | 265 - .../Inspector/BillboardRendererInspector.cs | 44 - Editor/Mono/Inspector/BlendTreeInspector.cs | 2208 ----- Editor/Mono/Inspector/BoxCollider2DEditor.cs | 120 - Editor/Mono/Inspector/BoxColliderEditor.cs | 61 - .../Inspector/BuoyancyEffector2DEditor.cs | 143 - Editor/Mono/Inspector/CameraEditor.cs | 748 -- Editor/Mono/Inspector/CanvasEditor.cs | 267 - .../Mono/Inspector/CapsuleCollider2DEditor.cs | 111 - .../Mono/Inspector/CapsuleColliderEditor.cs | 129 - .../Inspector/CharacterControllerEditor.cs | 165 - Editor/Mono/Inspector/CharacterJointEditor.cs | 64 - .../Mono/Inspector/CircleCollider2DEditor.cs | 66 - Editor/Mono/Inspector/ClothInspector.cs | 1719 ---- Editor/Mono/Inspector/Collider2DEditorBase.cs | 259 - Editor/Mono/Inspector/Collider3DEditorBase.cs | 34 - Editor/Mono/Inspector/ColliderEditorBase.cs | 66 - .../Mono/Inspector/ColliderEditorUtility.cs | 47 - .../Inspector/ColorPresetLibraryInspector.cs | 42 - .../Inspector/CompositeCollider2DEditor.cs | 78 - .../Mono/Inspector/ComputeShaderInspector.cs | 108 - .../Mono/Inspector/ConfigurableJointEditor.cs | 79 - Editor/Mono/Inspector/ConstraintEditorBase.cs | 239 - Editor/Mono/Inspector/CubemapInspector.cs | 163 - Editor/Mono/Inspector/CubemapPreview.cs | 208 - .../Inspector/CurvePresetLibraryInspector.cs | 99 - .../Mono/Inspector/CustomPreviewAttribute.cs | 21 - .../Inspector/CustomRenderTextureEditor.cs | 503 - Editor/Mono/Inspector/DirectorEditor.cs | 299 - .../Mono/Inspector/DistanceJoint2DEditor.cs | 35 - .../DoubleCurvePresetLibraryInspector.cs | 40 - Editor/Mono/Inspector/EdgeCollider2DEditor.cs | 65 - Editor/Mono/Inspector/EditMode.cs | 354 - Editor/Mono/Inspector/Editor.cs | 752 -- Editor/Mono/Inspector/EditorDragging.cs | 274 - .../Mono/Inspector/EditorSettingsInspector.cs | 715 -- Editor/Mono/Inspector/Effector2DEditor.cs | 101 - .../Inspector/Enlighten/LightmapParameters.cs | 127 - Editor/Mono/Inspector/FontInspector.cs | 30 - Editor/Mono/Inspector/GameObjectInspector.cs | 848 -- Editor/Mono/Inspector/GenericInspector.cs | 92 - .../GenericPresetLibraryInspector.cs | 172 - .../GradientPresetLibraryInspector.cs | 42 - .../Inspector/GraphicsSettingsInspector.cs | 176 - Editor/Mono/Inspector/HingeJoint2DEditor.cs | 160 - Editor/Mono/Inspector/HingeJointEditor.cs | 84 - Editor/Mono/Inspector/InspectorWindow.cs | 1615 ---- Editor/Mono/Inspector/Joint2DEditor.cs | 179 - Editor/Mono/Inspector/JointEditor.cs | 137 - Editor/Mono/Inspector/LODGroupEditor.cs | 1245 --- Editor/Mono/Inspector/LODGroupGUI.cs | 272 - Editor/Mono/Inspector/LabelGUI.cs | 239 - Editor/Mono/Inspector/LayoutDropdownWindow.cs | 564 -- .../Mono/Inspector/LegacyIlluminShaderGUI.cs | 23 - Editor/Mono/Inspector/LightEditor.cs | 668 -- .../Inspector/LightProbeGroupInspector.cs | 755 -- .../Inspector/LightProbeProxyVolumeEditor.cs | 384 - Editor/Mono/Inspector/LightProbesInspector.cs | 23 - .../Inspector/LightingSettingsInspector.cs | 620 -- .../Mono/Inspector/LineRendererCurveEditor.cs | 157 - .../Mono/Inspector/LineRendererInspector.cs | 91 - Editor/Mono/Inspector/MaterialEditor.cs | 2062 ---- .../Inspector/MaterialEditorGUIHelpers.cs | 368 - .../Mono/Inspector/MaterialPropertyDrawer.cs | 647 -- Editor/Mono/Inspector/MeshColliderEditor.cs | 83 - Editor/Mono/Inspector/MeshRendererEditor.cs | 112 - Editor/Mono/Inspector/ModelInspector.cs | 221 - Editor/Mono/Inspector/MonoScriptInspector.cs | 230 - .../Mono/Inspector/MovieTextureInspector.cs | 110 - .../Mono/Inspector/NavMeshAgentInspector.cs | 176 - Editor/Mono/Inspector/NavMeshEditorHelpers.cs | 139 - .../Inspector/NavMeshObstacleInspector.cs | 85 - Editor/Mono/Inspector/OcclusionAreaEditor.cs | 98 - .../Mono/Inspector/OcclusionPortalEditor.cs | 89 - Editor/Mono/Inspector/OffMeshLinkInspector.cs | 78 - .../Mono/Inspector/ParentConstraintEditor.cs | 218 - .../Inspector/Physics2DSettingsInspector.cs | 93 - .../Mono/Inspector/PhysicsManagerInspector.cs | 164 - .../Inspector/PlatformEffector2DEditor.cs | 187 - .../PlayerSettingsEditor.cs | 2440 ----- ...ayerSettingsSplashScreenEditor.bindings.cs | 32 - .../PlayerSettingsSplashScreenEditor.cs | 399 - .../PlayerSettingsEditor/WebTemplate.cs | 43 - .../WebTemplateManagerBase.cs | 290 - .../Mono/Inspector/PointEffector2DEditor.cs | 89 - .../Mono/Inspector/PolygonCollider2DEditor.cs | 124 - Editor/Mono/Inspector/PolygonEditorUtility.cs | 364 - .../Inspector/PositionConstraintEditor.cs | 82 - Editor/Mono/Inspector/PrefabInspector.cs | 63 - Editor/Mono/Inspector/PreviewRenderUtility.cs | 485 - Editor/Mono/Inspector/PreviewWindow.cs | 106 - .../Inspector/PrimitiveCollider2DEditor.cs | 87 - .../Inspector/PrimitiveCollider3DEditor.cs | 63 - .../Inspector/ProjectSettingsBaseEditor.cs | 30 - Editor/Mono/Inspector/PropertyDrawerCache.cs | 48 - .../Mono/Inspector/QualitySettingsEditor.cs | 585 -- Editor/Mono/Inspector/RectHandles.cs | 296 - Editor/Mono/Inspector/RectTransformEditor.cs | 1386 --- .../Mono/Inspector/RectTransformSnapping.cs | 387 - .../Mono/Inspector/ReflectionProbeEditor.cs | 816 -- .../Mono/Inspector/RelativeJoint2DEditor.cs | 45 - .../Mono/Inspector/RenderSettingsInspector.cs | 47 - Editor/Mono/Inspector/RenderTextureEditor.cs | 203 - Editor/Mono/Inspector/RendererEditorBase.cs | 416 - Editor/Mono/Inspector/Rigidbody2DEditor.cs | 291 - Editor/Mono/Inspector/RigidbodyEditor.cs | 75 - .../Inspector/RotationConstraintEditor.cs | 81 - .../Mono/Inspector/ScaleConstraintEditor.cs | 81 - .../ScriptExecutionOrderInspector.cs | 829 -- Editor/Mono/Inspector/ShaderGUI.cs | 90 - .../Mono/Inspector/ShaderImporterInspector.cs | 235 - .../Inspector/ShaderIncludePathAttribute.cs | 15 - Editor/Mono/Inspector/ShaderInspector.cs | 604 -- .../ShaderVariantCollectionInspector.cs | 402 - .../Mono/Inspector/ShadowCascadeSplitGUI.cs | 216 - .../Inspector/SkinnedMeshRendererEditor.cs | 197 - .../Inspector/SkyboxPanoramicShaderGUI.cs | 78 - .../Inspector/SkyboxProceduralShaderGUI.cs | 42 - Editor/Mono/Inspector/SliderJoint2DEditor.cs | 55 - Editor/Mono/Inspector/SortingGroupEditor.cs | 31 - .../Inspector/SortingLayerEditorUtility.cs | 32 - .../Inspector/SpeedTreeMaterialInspector.cs | 187 - Editor/Mono/Inspector/SphereColliderEditor.cs | 68 - Editor/Mono/Inspector/SpringJoint2DEditor.cs | 35 - Editor/Mono/Inspector/SpriteFrameInspector.cs | 374 - Editor/Mono/Inspector/SpriteRendererEditor.cs | 289 - .../Inspector/StandardParticlesShaderGUI.cs | 794 -- .../Inspector/StandardRoughnessShaderGUI.cs | 332 - Editor/Mono/Inspector/StandardShaderGUI.cs | 429 - .../Mono/Inspector/SurfaceEffector2DEditor.cs | 84 - Editor/Mono/Inspector/TabbedEditor.cs | 200 - Editor/Mono/Inspector/TagManagerInspector.cs | 341 - Editor/Mono/Inspector/TargetJoint2DEditor.cs | 50 - .../Mono/Inspector/TerrainColliderEditor.cs | 38 - Editor/Mono/Inspector/TextMeshInspector.cs | 38 - Editor/Mono/Inspector/Texture3DInspector.cs | 103 - Editor/Mono/Inspector/TextureInspector.cs | 804 -- Editor/Mono/Inspector/TimeControl.cs | 230 - Editor/Mono/Inspector/TimeManagerInspector.cs | 50 - Editor/Mono/Inspector/TimelineControl.cs | 787 -- .../Mono/Inspector/TrailRendererInspector.cs | 97 - Editor/Mono/Inspector/TransformInspector.cs | 66 - Editor/Mono/Inspector/TransformRotationGUI.cs | 118 - Editor/Mono/Inspector/TransformUtils.cs | 22 - .../Mono/Inspector/UNetBehaviourInspector.cs | 5 - Editor/Mono/Inspector/UnityEventDrawer.cs | 713 -- Editor/Mono/Inspector/VideoClipInspector.cs | 199 - Editor/Mono/Inspector/VideoPlayerEditor.cs | 683 -- .../Mono/Inspector/WebCamTextureInspector.cs | 107 - Editor/Mono/Inspector/WheelColliderEditor.cs | 58 - Editor/Mono/Inspector/WheelJoint2DEditor.cs | 40 - Editor/Mono/Inspector/WindInspector.cs | 73 - Editor/Mono/Internal/MonoScripts.cs | 22 - Editor/Mono/InternalEditorUtility.cs | 426 - Editor/Mono/JSProxy/ClipboardAccess.cs | 40 - Editor/Mono/JSProxy/JSProxyMgr.cs | 652 -- Editor/Mono/JSProxy/PreviewGenerator.cs | 50 - Editor/Mono/JSProxy/TroubleshooterAccess.cs | 61 - Editor/Mono/JSProxy/WebScriptObject.cs | 52 - Editor/Mono/LicenseManagementWindow.cs | 101 - .../LocalizationDatabase.bindings.cs | 43 - .../Mono/Localization/LocalizationDatabase.cs | 51 - .../LocalizedEditorFontManager.cs | 162 - Editor/Mono/LogEntries.bindings.cs | 16 - Editor/Mono/LookDevView/CameraController.cs | 18 - .../LookDevView/CameraControllerStandard.cs | 274 - Editor/Mono/LookDevView/CameraState.cs | 75 - Editor/Mono/LookDevView/LookDevConfig.cs | 500 - Editor/Mono/LookDevView/LookDevContext.cs | 80 - .../LookDevView/LookDevEnvironmentLibrary.cs | 227 - .../LookDevView/LookDevEnvironmentWindow.cs | 860 -- Editor/Mono/LookDevView/LookDevInc.cs | 428 - .../Mono/LookDevView/LookDevSettingsWindow.cs | 278 - Editor/Mono/LookDevView/LookDevView.cs | 2116 ----- Editor/Mono/LookDevView/LookDevViewsWindow.cs | 284 - Editor/Mono/Macros/MacroEvaluator.cs | 72 - Editor/Mono/Macros/MethodEvaluator.cs | 114 - Editor/Mono/MaterialProperty.cs | 229 - .../Media/Bindings/MediaEncoder.bindings.cs | 132 - Editor/Mono/Menu.bindings.cs | 18 - Editor/Mono/MenuCommand.cs | 29 - Editor/Mono/MenuItem.cs | 43 - .../Mono/Modules/DefaultBuildPostprocessor.cs | 80 - .../Modules/DefaultBuildWindowExtension.cs | 30 - .../Modules/DefaultCompilationExtension.cs | 49 - .../Modules/DefaultPlatformSupportModule.cs | 67 - .../DefaultPlayerSettingsEditorExtension.cs | 125 - .../Modules/DefaultPluginImporterExtension.cs | 218 - .../DefaultProjectGeneratorExtension.cs | 16 - .../DefaultTextureImportSettingsExtension.cs | 297 - Editor/Mono/Modules/ModuleManager.cs | 850 -- Editor/Mono/Modules/PlatformSupportModule.cs | 429 - Editor/Mono/MonoScript.bindings.cs | 53 - Editor/Mono/MuscleClipUtility.bindings.cs | 58 - .../PlayerConnection/EditorConnection.cs | 185 - Editor/Mono/NumericFieldDraggerUtility.cs | 53 - Editor/Mono/ObjectFactory.bindings.cs | 129 - Editor/Mono/ObjectListArea.cs | 1735 ---- Editor/Mono/ObjectListAssetStoreGroup.cs | 353 - Editor/Mono/ObjectListGroup.cs | 283 - Editor/Mono/ObjectListLocalGroup.cs | 1411 --- Editor/Mono/ObjectNames.cs | 80 - Editor/Mono/ObjectSelector.cs | 816 -- Editor/Mono/ObjectTreeForSelector.cs | 375 - Editor/Mono/PackageUtility.bindings.cs | 70 - .../ParticleSystemEditor/ParticleEffectUI.cs | 1083 --- .../ParticleRendererEditor.cs | 50 - .../ParticleSystemClipboard.cs | 202 - .../ParticleSystemCurveEditor.cs | 839 -- .../ParticleSystemEditor.cs | 255 - .../ClampVelocityModuleUI.cs | 120 - .../CollisionModuleUI.cs | 665 -- .../ColorByVelocityModuleUI.cs | 48 - .../ParticleSystemModules/ColorModuleUI.cs | 43 - .../CustomDataModuleUI.cs | 89 - .../ParticleSystemModules/EmissionModuleUI.cs | 233 - .../ExternalForcesModuleUI.cs | 47 - .../ParticleSystemModules/ForceModuleUI.cs | 84 - .../InheritVelocityModuleUI.cs | 63 - .../ParticleSystemModules/InitialModuleUI.cs | 312 - .../ParticleSystemModules/LightsModuleUI.cs | 85 - .../ParticleSystemModules/ModuleUI.cs | 225 - .../ParticleSystemModules/ModuleUIHelpers.cs | 1168 --- .../ParticleSystemModules/NoiseModuleUI.cs | 255 - .../ParticleSystemModules/RendererModuleUI.cs | 624 -- .../RotationByVelocityModuleUI.cs | 97 - .../ParticleSystemModules/RotationModuleUI.cs | 101 - .../SerializedModuleUI.cs | 72 - .../ParticleSystemModules/ShapeModuleUI.cs | 777 -- .../SizeByVelocityModuleUI.cs | 94 - .../ParticleSystemModules/SizeModuleUI.cs | 83 - .../ParticleSystemModules/SubModuleUI.cs | 326 - .../ParticleSystemModules/TrailModuleUI.cs | 156 - .../ParticleSystemModules/TriggerModuleUI.cs | 231 - .../ParticleSystemModules/UVModuleUI.cs | 215 - .../ParticleSystemModules/VelocityModuleUI.cs | 113 - .../ParticleSystemStyles.cs | 124 - .../ParticleSystemEditor/ParticleSystemUI.cs | 647 -- .../ParticleSystemWindow.cs | 312 - .../ParticleSystemEditor.bindings.cs | 55 - .../SerializedMinMaxColor.cs | 32 - .../SerializedMinMaxCurve.cs | 316 - .../SerializedMinMaxGradient.cs | 95 - .../HolographicEmulationWindow.cs | 418 - Editor/Mono/PerformanceTools/FrameDebugger.cs | 1534 --- .../PerformanceTools/FrameDebuggerTreeView.cs | 272 - .../Mono/PlatformSupport/PlatformIconField.cs | 270 - .../PlayerSettingsPlatformIcons.bindings.cs | 478 - .../PlatformSupport/ReorderableTextureList.cs | 159 - Editor/Mono/Playables/Playables.bindings.cs | 34 - Editor/Mono/PlayerConnectionLogReceiver.cs | 92 - Editor/Mono/PlayerSettings.deprecated.cs | 171 - Editor/Mono/PlayerSettingsIOS.bindings.cs | 571 -- Editor/Mono/PlayerSettingsMacOS.bindings.cs | 27 - Editor/Mono/PlayerSettingsPS4.bindings.cs | 190 - Editor/Mono/PlayerSettingsPSVita.bindings.cs | 102 - Editor/Mono/PlayerSettingsSplashScreen.cs | 31 - Editor/Mono/PlayerSettingsTVOS.bindings.cs | 206 - Editor/Mono/PlayerSettingsTizen.bindings.cs | 135 - Editor/Mono/PlayerSettingsWSA.cs | 699 -- Editor/Mono/PlayerSettingsXboxOne.bindings.cs | 26 - Editor/Mono/PluginDesc.cs | 22 - Editor/Mono/PluginImporter.bindings.cs | 295 - Editor/Mono/Plugins/PluginsHelper.cs | 35 - Editor/Mono/PointEditor.cs | 289 - Editor/Mono/PostprocessScene.cs | 23 - .../CacheServerPreferences.cs | 298 - .../DiagnosticsSwitchPreferences.cs | 191 - .../PreferencesWindow/PreferencesWindow.cs | 1281 --- .../PresetLibraries/ColorPresetLibrary.cs | 241 - .../PresetLibraries/CurvePresetLibrary.cs | 128 - .../CurvePresetsContentsForPopupWindow.cs | 147 - .../DoubleCurvePresetLibrary.cs | 178 - ...oubleCurvePresetsContentsForPopupWindow.cs | 163 - .../PresetLibraries/GradientPresetLibrary.cs | 146 - .../PopupWindowContentForNewLibrary.cs | 133 - Editor/Mono/PresetLibraries/PresetLibrary.cs | 49 - .../PresetLibraries/PresetLibraryEditor.cs | 969 -- .../PresetLibraryEditorMenu.cs | 130 - .../PresetLibraries/PresetLibraryManager.cs | 289 - .../ScriptableObjectSaveLoadHelper.cs | 88 - Editor/Mono/ProjectBrowser.cs | 2726 ------ .../Mono/ProjectBrowser/SavedSearchFilter.cs | 547 -- Editor/Mono/ProjectBrowserColumnOne.cs | 416 - Editor/Mono/ProjectBrowserPopups.cs | 532 -- Editor/Mono/ProjectTemplateWindow.cs | 50 - .../ProjectWindow/CachedFilteredHierachy.cs | 500 - .../Mono/ProjectWindow/ProjectWindowUtil.cs | 793 -- Editor/Mono/ProjectWindow/SearchFilter.cs | 295 - .../ProjectWindow/SearchableEditorWindow.cs | 241 - Editor/Mono/ProvisioningProfile.cs | 67 - Editor/Mono/ProvisioningProfileGUI.cs | 194 - Editor/Mono/RagdollBuilder.cs | 531 -- Editor/Mono/RetainedMode.cs | 178 - ...RuntimeInitializeOnLoadManager.bindings.cs | 50 - Editor/Mono/SceneHierarchySortingWindow.cs | 150 - Editor/Mono/SceneHierarchyWindow.cs | 1359 --- .../SceneManagement/EditorSceneManager.cs | 79 - Editor/Mono/SceneManagement/SceneSetup.cs | 42 - Editor/Mono/SceneModeWindows/LightTable.cs | 513 - .../LightingExplorerWindow.cs | 181 - .../LightingExplorerWindowTableTab.cs | 78 - .../Mono/SceneModeWindows/LightingWindow.cs | 553 -- .../LightingWindowBakeSettings.cs | 643 -- .../LightingWindowLightingTab.cs | 189 - .../LightingWindowLightmapPreviewTab.cs | 568 -- .../LightingWindowObjectTab.cs | 299 - .../Mono/SceneModeWindows/NavigationWindow.cs | 1045 -- .../OcclusionCullingWindow.cs | 521 - .../SceneModeWindows/PhysicsDebugWindow.cs | 343 - .../Mono/SceneModeWindows/SceneModeUtility.cs | 219 - .../SceneModeWindows/TierSettingsWindow.cs | 64 - Editor/Mono/SceneView/RectSelection.cs | 237 - Editor/Mono/SceneView/SceneView.cs | 2784 ------ Editor/Mono/SceneView/SceneViewGrid.cs | 73 - Editor/Mono/SceneView/SceneViewMotion.cs | 1143 --- Editor/Mono/SceneView/SceneViewOverlay.cs | 188 - Editor/Mono/SceneView/SceneViewPicking.cs | 169 - .../CustomPropertyDrawerAttribute.cs | 29 - .../ScriptAttributeGUI/DecoratorDrawer.cs | 33 - Editor/Mono/ScriptAttributeGUI/GUIDrawer.cs | 9 - .../Implementations/DecoratorDrawers.cs | 35 - .../Implementations/ExposedReferenceDrawer.cs | 279 - .../Implementations/PropertyDrawers.cs | 136 - .../Mono/ScriptAttributeGUI/PropertyDrawer.cs | 64 - .../ScriptAttributeGUI/PropertyHandler.cs | 293 - .../ScriptAttributeUtility.cs | 284 - Editor/Mono/ScriptEditorUtility.cs | 144 - Editor/Mono/ScriptableSingleton.cs | 128 - Editor/Mono/ScriptableSingletonDictionary.cs | 147 - Editor/Mono/Scripting/APIUpdaterHelper.cs | 365 - Editor/Mono/Scripting/APIUpdaterLogger.cs | 27 - Editor/Mono/Scripting/Compilers/APIUpdater.cs | 105 - .../Mono/Scripting/Compilers/BooCompiler.cs | 44 - .../Compilers/BooCompilerOutputParser.cs | 34 - .../Mono/Scripting/Compilers/BooLanguage.cs | 39 - .../Scripting/Compilers/CSharpLanguage.cs | 141 - .../Scripting/Compilers/Cil2AsOutputParser.cs | 43 - .../Compilers/CommandLineFormatter.cs | 63 - .../Compilers/CompilerOutputParserBase.cs | 138 - .../Compilers/GendarmeOutputParser.cs | 132 - .../Scripting/Compilers/Il2CppOutputParser.cs | 71 - .../Compilers/MicrosoftCSharpCompiler.cs | 139 - .../MicrosoftCSharpCompilerOutputParser.cs | 23 - .../Scripting/Compilers/MonoCSharpCompiler.cs | 92 - .../MonoCSharpCompilerOutputParser.cs | 49 - .../Compilers/MonoScriptCompilerBase.cs | 44 - .../Compilers/NuGetPackageResolver.cs | 117 - .../Scripting/Compilers/ScriptCompilerBase.cs | 449 - .../Scripting/Compilers/SupportedLanguage.cs | 22 - .../Mono/Scripting/Compilers/UWPReferences.cs | 308 - .../Compilers/UnityScriptCompiler.cs | 92 - .../UnityScriptCompilerOutputParser.cs | 34 - .../Compilers/UnityScriptLanguage.cs | 24 - Editor/Mono/Scripting/PragmaFixing30.cs | 148 - .../ScriptCompilation/AssemblyBuilder.cs | 144 - .../AssemblyDefinitionException.cs | 18 - .../ScriptCompilation/AssemblyFlags.cs | 20 - .../Scripting/ScriptCompilation/AssetPath.cs | 57 - .../ScriptCompilation/CompilationPipeline.cs | 253 - .../ScriptCompilation/CompilationTask.cs | 257 - .../ScriptCompilation/CompilerMessage.cs | 21 - .../ScriptCompilation/CustomScriptAssembly.cs | 293 - .../ScriptCompilation/EditorBuildRules.cs | 817 -- .../ScriptCompilation/EditorCompilation.cs | 1270 --- .../EditorCompilationInterface.cs | 305 - .../EditorScriptCompilationOptions.cs | 22 - .../ScriptCompilation/MonoLibraryHelpers.cs | 129 - .../OptionalUnityReferences.cs | 16 - .../ScriptCompilation/PrecompiledAssembly.cs | 17 - .../ScriptCompilation/ScriptAssembly.cs | 88 - .../Scripting/ScriptCompilation/WSAHelpers.cs | 51 - Editor/Mono/Scripting/ScriptCompilers.cs | 153 - .../ScriptUpdatingManager.bindings.cs | 21 - Editor/Mono/Scripting/Serialization/Weaver.cs | 84 - Editor/Mono/SearchUtility.cs | 203 - Editor/Mono/Selection.bindings.cs | 129 - Editor/Mono/Selection.cs | 73 - Editor/Mono/SerializedObject.cs | 58 - Editor/Mono/SerializedProperty.cs | 204 - .../SerializedPropertyFilters.cs | 74 - .../SerializedPropertyTable.cs | 191 - .../SerializedPropertyTreeView.cs | 637 -- Editor/Mono/Settings.cs | 451 - Editor/Mono/SettingsWindow/FogEditor.cs | 73 - .../SettingsWindow/GraphicsSettingsEditors.cs | 595 -- Editor/Mono/SettingsWindow/LightingEditor.cs | 277 - .../SettingsWindow/OtherRenderingEditor.cs | 53 - Editor/Mono/ShaderUtil.bindings.cs | 148 - Editor/Mono/ShapeEditor/ShapeEditor.cs | 1114 --- .../ShapeEditor/ShapeEditorRectSelection.cs | 232 - Editor/Mono/SplashScreenLogo.cs | 41 - .../Mono/SpriteEditor/SpriteEditorHandles.cs | 370 - Editor/Mono/SpriteEditor/SpriteEditorMenu.cs | 405 - .../Mono/SpriteEditor/SpriteEditorUtility.cs | 188 - .../Mono/SpriteEditor/SpriteEditorWindow.cs | 885 -- Editor/Mono/SpriteEditor/SpriteRect.cs | 174 - Editor/Mono/SpritePacker.bindings.cs | 93 - .../Mono/Sprites/DefaultSpritePackerPolicy.cs | 152 - Editor/Mono/Sprites/SpritePacker.cs | 162 - Editor/Mono/Sprites/SpritePackerWindow.cs | 390 - Editor/Mono/Sprites/SpriteUtility.cs | 633 -- Editor/Mono/Sprites/SpriteUtilityWindow.cs | 388 - .../TightRotateEnabledSpritePackerPolicy.cs | 19 - .../Mono/Sprites/TightSpritePackerPolicy.cs | 19 - Editor/Mono/StateMachine.bindings.cs | 323 - .../StateMachineBehaviourContext.bindings.cs | 27 - Editor/Mono/StaticEditorFlags.cs | 27 - Editor/Mono/StyleSheets/CSSSpec.cs | 120 - .../StyleSheetAssetPostProcessor.cs | 65 - Editor/Mono/StyleSheets/StyleSheetBuilder.cs | 183 - Editor/Mono/StyleSheets/StyleSheetEditor.cs | 44 - .../StyleSheets/StyleSheetImportErrors.cs | 88 - Editor/Mono/StyleSheets/StyleSheetImporter.cs | 47 - .../StyleSheets/StyleSheetImporterImpl.cs | 341 - .../StyleSheets/StyleSheetResourceUtil.cs | 77 - Editor/Mono/SyncProject.cs | 452 - Editor/Mono/TerrainEditor/Brush.cs | 135 - Editor/Mono/TerrainEditor/HeightmapFilters.cs | 98 - .../TerrainEditor/TerrainEditorUtility.cs | 101 - Editor/Mono/TerrainEditor/TerrainInspector.cs | 2008 ---- Editor/Mono/TerrainEditor/TerrainMenus.cs | 267 - .../Mono/TerrainEditor/TerrainSplatEditor.cs | 323 - Editor/Mono/TerrainEditor/TerrainWizards.cs | 772 -- Editor/Mono/TerrainEditor/TreeAOImporter.cs | 218 - Editor/Mono/TooltipView/TooltipView.cs | 108 - .../Troubleshooter/TroubleshooterWindow.cs | 41 - Editor/Mono/Tutorial/Highlighter.cs | 278 - Editor/Mono/TypeSystem/UnityType.bindings.cs | 30 - Editor/Mono/TypeSystem/UnityType.cs | 130 - .../UIElements/Controls/BaseCompositeField.cs | 92 - .../UIElements/Controls/BaseValueField.cs | 48 - .../Mono/UIElements/Controls/BoundsField.cs | 55 - Editor/Mono/UIElements/Controls/ColorField.cs | 82 - .../UIElements/Controls/CompoundFields.cs | 62 - Editor/Mono/UIElements/Controls/CurveField.cs | 233 - .../Mono/UIElements/Controls/DoubleField.cs | 49 - Editor/Mono/UIElements/Controls/EnumField.cs | 85 - .../Mono/UIElements/Controls/GradientField.cs | 146 - .../Mono/UIElements/Controls/IntegerField.cs | 51 - .../Mono/UIElements/Controls/ObjectField.cs | 231 - Editor/Mono/UIElements/Controls/PopupField.cs | 132 - .../UIElements/Controls/TextValueField.cs | 102 - .../Controls/UXMLEditorFactories.cs | 36 - .../UIElements/EditorContextualMenuManager.cs | 80 - Editor/Mono/UIElements/EditorCursor.cs | 29 - .../EditorWindowPersistentViewData.cs | 26 - Editor/Mono/UIElements/Events/TooltipEvent.cs | 15 - Editor/Mono/UIElements/FieldMouseDragger.cs | 108 - .../UIElements/SerializableJsonDictionary.cs | 114 - Editor/Mono/UIElements/Tooltip.cs | 91 - .../UIElements/UIElementsEditorUtility.cs | 64 - .../Mono/UIElements/UIElementsViewImporter.cs | 527 -- .../Mono/UIElements/VisualTreeAssetEditor.cs | 126 - Editor/Mono/Undo/UndoWindow.cs | 91 - .../Mono/UnityConnect/CloudProjectSettings.cs | 67 - .../Mono/UnityConnect/Services/AdsAccess.cs | 118 - .../UnityConnect/Services/AnalyticsAccess.cs | 70 - .../Mono/UnityConnect/Services/BuildAccess.cs | 43 - .../Services/CloudServiceAccess.cs | 60 - .../UnityConnect/Services/CollabAccess.cs | 63 - .../Services/CrashReportingAccess.cs | 63 - .../Services/EditorProjectAccess.bindings.cs | 22 - .../Services/EditorProjectAccess.cs | 162 - .../UnityConnect/Services/ErrorHubAccess.cs | 32 - .../Mono/UnityConnect/Services/HubAccess.cs | 65 - .../UnityConnect/Services/PurchasingAccess.cs | 142 - .../Mono/UnityConnect/Services/UnetAccess.cs | 50 - Editor/Mono/UnityConnect/UnityConnect.cs | 269 - .../UnityConnect/UnityConnectConsentView.cs | 93 - .../UnityConnect/UnityConnectEditorWindow.cs | 110 - Editor/Mono/UnityConnect/UnityConnectPrefs.cs | 175 - .../UnityConnectServiceCollection.cs | 266 - .../UnityConnect/UnityConnectServiceData.cs | 66 - Editor/Mono/Utils/AssemblyReferenceChecker.cs | 309 - Editor/Mono/Utils/EditorExtensionMethods.cs | 84 - Editor/Mono/Utils/ExpressionEvaluator.cs | 434 - Editor/Mono/Utils/IDeviceUtils.cs | 42 - Editor/Mono/Utils/LightProbeGroupSelection.cs | 14 - Editor/Mono/Utils/ManagedProgram.cs | 63 - Editor/Mono/Utils/MathUtils.cs | 498 - Editor/Mono/Utils/MenuUtils.cs | 71 - .../Utils/MetroCertificatePasswordWindow.cs | 129 - .../Utils/MetroCreateTestCertificateWindow.cs | 231 - Editor/Mono/Utils/MonoInstallationFinder.cs | 65 - Editor/Mono/Utils/NetCoreProgram.cs | 114 - Editor/Mono/Utils/NetStandardFinder.cs | 42 - Editor/Mono/Utils/Paths.cs | 269 - Editor/Mono/Utils/PerformanceChecks.cs | 114 - .../Mono/Utils/ProcessOutputStreamReader.cs | 73 - Editor/Mono/Utils/Program.cs | 187 - Editor/Mono/Utils/ProgressBarUtils.cs | 109 - Editor/Mono/Utils/SimpleProfiler.cs | 64 - Editor/Mono/Utils/TickTimerHelper.cs | 32 - Editor/Mono/Utils/TimeAgo.cs | 53 - Editor/Mono/Utils/TimeHelper.cs | 25 - Editor/Mono/Utils/UnityEventTools.cs | 171 - Editor/Mono/VersionControl/Common/VCAsset.cs | 162 - .../Mono/VersionControl/Common/VCAssetList.cs | 85 - .../Common/VCAssetModificationHooks.cs | 129 - .../Mono/VersionControl/Common/VCChangeSet.cs | 36 - .../VersionControl/Common/VCChangeSets.cs | 12 - .../Mono/VersionControl/Common/VCMessage.cs | 22 - .../Mono/VersionControl/Common/VCProvider.cs | 374 - Editor/Mono/VersionControl/Common/VCTask.cs | 39 - .../Mono/VersionControl/UI/VCListControl.cs | 1343 --- Editor/Mono/VersionControl/UI/VCListItem.cs | 454 - Editor/Mono/VersionControl/UI/VCMenuChange.cs | 149 - .../Mono/VersionControl/UI/VCMenuPending.cs | 146 - .../Mono/VersionControl/UI/VCMenuProject.cs | 213 - Editor/Mono/VersionControl/UI/VCOverlay.cs | 284 - .../Mono/VersionControl/UI/VCProjectHooks.cs | 33 - .../Mono/VersionControl/UI/VCWindowChange.cs | 449 - .../UI/VCWindowCheckoutFailure.cs | 156 - .../Mono/VersionControl/UI/VCWindowPending.cs | 649 -- .../Mono/VersionControl/UI/VCWindowResolve.cs | 204 - .../Mono/VersionControl/UI/VCWindowRevert.cs | 138 - .../VersionControl/VCProvider.bindings.cs | 284 - Editor/Mono/View.cs | 249 - .../SolutionSynchronizationSettings.cs | 277 - .../SolutionSynchronizer.cs | 837 -- .../VisualStudioIntegration/UnityVSSupport.cs | 356 - Editor/Mono/VisualStudioUtil.bindings.cs | 51 - .../WebViewEditorStaticWindow.cs | 47 - .../WebViewEditorWindow.cs | 446 - .../WebViewEditorWindowsTabs.cs | 197 - .../WebViewTestFunctions.cs | 138 - .../TextRendering/TextRenderingCommands.cs | 26 - .../Mono/GoogleVR/VRCustomOptionsGoogleVR.cs | 286 - Editor/Src/VR/Mono/HolographicEmulation.cs | 169 - .../VR/Mono/Oculus/VRCustomOptionsOculus.cs | 66 - Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs | 601 -- Editor/Src/VR/Mono/VRCustomOptions.cs | 76 - Editor/Src/VR/Mono/VREditor.cs | 119 - Editor/Src/VR/Mono/VRModule.cs | 50 - .../VRCustomOptionsWindowsHolographic.cs | 69 - .../VR/ScriptBindings/VREditor.bindings.cs | 105 - Extensions/Networking/Weaver/AssemblyInfo.cs | 32 - Extensions/Networking/Weaver/Helpers.cs | 231 - .../Weaver/MessageClassProcessor.cs | 156 - .../Weaver/MonoBehaviourProcessor.cs | 99 - Extensions/Networking/Weaver/Program.cs | 65 - .../Weaver/SyncListStructProcessor.cs | 357 - .../Weaver/UNetBehaviourProcessor.cs | 2341 ----- Extensions/Networking/Weaver/UNetWeaver.cs | 1907 ---- .../Networking/Weaver/UNetWeaver.csproj | 59 - .../csharp/Facebook.CSSLayout/CSSAlign.cs | 23 - .../csharp/Facebook.CSSLayout/CSSConstants.cs | 24 - .../csharp/Facebook.CSSLayout/CSSDIrection.cs | 25 - .../csharp/Facebook.CSSLayout/CSSDimension.cs | 20 - .../csharp/Facebook.CSSLayout/CSSEdge.cs | 27 - .../CSSExperimentalFeature.cs | 20 - .../Facebook.CSSLayout/CSSFlexDirection.cs | 22 - .../csharp/Facebook.CSSLayout/CSSJustify.cs | 23 - .../csharp/Facebook.CSSLayout/CSSLogLevel.cs | 23 - .../csharp/Facebook.CSSLayout/CSSLogger.cs | 50 - .../Facebook.CSSLayout/CSSMeasureFunc.cs | 25 - .../Facebook.CSSLayout/CSSMeasureMode.cs | 21 - .../Facebook.CSSLayout/CSSNode.Create.cs | 23 - .../csharp/Facebook.CSSLayout/CSSNode.cs | 598 -- .../csharp/Facebook.CSSLayout/CSSOverflow.cs | 21 - .../Facebook.CSSLayout/CSSPositionType.cs | 20 - .../Facebook.CSSLayout/CSSPrintOptions.cs | 21 - .../csharp/Facebook.CSSLayout/CSSSize.cs | 23 - .../csharp/Facebook.CSSLayout/CSSWrap.cs | 20 - .../ConcurrentDictionary.cs | 57 - .../Facebook.CSSLayout/MeasureFunction.cs | 24 - .../Facebook.CSSLayout/MeasureOutput.cs | 37 - .../Facebook.CSSLayout/Native.bindings.cs | 329 - .../csharp/Facebook.CSSLayout/Spacing.cs | 15 - .../builds/builds/lib/net35/ExCSS.Unity.dll | Bin 90624 -> 0 bytes External/JsonParsers/MiniJson/MiniJSON.cs | 638 -- External/JsonParsers/SimpleJson/SimpleJson.cs | 1664 ---- .../lib/mono/2.0/Boo.Lang.Compiler.dll | Bin 934912 -> 0 bytes .../lib/mono/2.0/Boo.Lang.Parser.dll | Bin 414208 -> 0 bytes .../lib/mono/2.0/Boo.Lang.dll | Bin 126976 -> 0 bytes .../lib/mono/2.0/Mono.Posix.dll | Bin 184320 -> 0 bytes .../lib/mono/2.0/Mono.Security.dll | Bin 294912 -> 0 bytes .../lib/mono/2.0/System.Core.dll | Bin 297984 -> 0 bytes .../lib/mono/2.0/System.Xml.Linq.dll | Bin 106496 -> 0 bytes .../lib/mono/2.0/System.Xml.dll | Bin 1270272 -> 0 bytes .../monodistribution/lib/mono/2.0/System.dll | Bin 1679360 -> 0 bytes .../lib/mono/2.0/UnityScript.dll | Bin 177664 -> 0 bytes .../3.2.1/net35/Unity.Legacy.NRefactory.dll | Bin 520704 -> 0 bytes .../builds/lib/net35/Unity.Cecil.Mdb.dll | Bin 44544 -> 0 bytes .../builds/lib/net35/Unity.Cecil.Pdb.dll | Bin 87552 -> 0 bytes .../builds/lib/net35/Unity.Cecil.dll | Bin 347136 -> 0 bytes Modules/AI/NavMesh/NavMesh.bindings.cs | 16 - Modules/AI/NavMesh/NavMesh.cs | 22 - Modules/AI/NavMeshExperimental.bindings.cs | 300 - Modules/Accessibility/VisionUtility.cs | 76 - Modules/AssetBundle/Managed/AssemblyInfo.cs | 8 - .../Managed/AssetBundle.deprecated.cs | 22 - .../Managed/AssetBundleUtility.bindings.cs | 19 - .../Audio/Public/Managed/Audio.deprecated.cs | 46 - .../AudioClipPlayable.bindings.cs | 189 - .../Public/ScriptBindings/AudioExtensions.cs | 526 -- .../AudioMixerPlayable.bindings.cs | 85 - .../AudioPlayableGraphExtensions.bindings.cs | 21 - .../AudioPlayableOutput.bindings.cs | 80 - .../ScriptBindings/AudioRenderer.bindings.cs | 49 - .../AudioSampleProvider.bindings.cs | 231 - .../AssetBundleBuildInterface.bindings.cs | 103 - .../Editor/Managed/BuildCommandSet.cs | 161 - .../Editor/Managed/BuildDefines.cs | 30 - .../Editor/Managed/BuildInput.cs | 69 - .../Editor/Managed/BuildOutput.cs | 87 - .../Editor/Managed/BuildSettings.cs | 43 - .../Editor/Managed/BuildUsage.cs | 36 - .../Managed/BuildUsageTagSet.bindings.cs | 83 - .../Editor/Managed/ObjectIdentifier.cs | 98 - .../Managed/PlayerBuildInterface.bindings.cs | 89 - .../Editor/Managed/ResourceFile.cs | 29 - .../Editor/Managed/SceneLoadInfo.cs | 38 - .../Editor/Managed/TypeDB.bindings.cs | 79 - .../BuildReportingEditor/Managed/BuildFile.cs | 25 - .../Managed/BuildReport.bindings.cs | 72 - .../Managed/BuildReportHelper.cs | 45 - .../Managed/BuildReportViewerWindow.cs | 15 - .../Managed/BuildResult.cs | 16 - .../BuildReportingEditor/Managed/BuildStep.cs | 28 - .../Managed/BuildStepMessage.cs | 18 - .../Managed/BuildSummary.cs | 39 - .../BuildReportingEditor/Managed/BuildType.cs | 15 - .../Managed/CommonRoles.bindings.cs | 81 - .../Managed/ScopedBuildStep.cs | 33 - .../Managed/StrippingInfo.cs | 154 - .../Managed/StrippingInfoWithSizeAnalysis.cs | 178 - .../AdvertisementSettings.bindings.cs | 49 - .../AnalyticsSettings.bindings.cs | 25 - .../CrashReporting/Managed/CrashReporting.cs | 186 - .../CrashReportingSettings.bindings.cs | 28 - .../Managed/CoreStats.cs | 33 - .../PerformanceReportingSettings.bindings.cs | 19 - .../PurchasingSettings.bindings.cs | 25 - .../CrashReportHandler.bindings.cs | 18 - .../PlayableDirector.bindings.cs | 141 - .../GameCenter/Managed/GameCenterServices.cs | 12 - Modules/GameCenter/Managed/LocalService.cs | 682 -- Modules/GameCenter/Managed/NetworkServices.cs | 233 - .../Public/GameCenterServices.bindings.cs | 9 - Modules/GraphViewEditor/BaseTypeFactory.cs | 88 - Modules/GraphViewEditor/Capabilities.cs | 20 - Modules/GraphViewEditor/DataWatchContainer.cs | 76 - .../Decorators/GridBackground.cs | 229 - Modules/GraphViewEditor/Direction.cs | 12 - Modules/GraphViewEditor/EdgeControl.cs | 812 -- Modules/GraphViewEditor/Elements/Edge.cs | 324 - .../Elements/FallbackGraphElement.cs | 27 - .../GraphViewEditor/Elements/GraphElement.cs | 304 - .../GraphElementGroupNodeExtensions.cs | 32 - Modules/GraphViewEditor/Elements/GroupNode.cs | 541 -- Modules/GraphViewEditor/Elements/MiniMap.cs | 430 - Modules/GraphViewEditor/Elements/Node.cs | 521 - Modules/GraphViewEditor/Elements/Port.cs | 571 -- .../Elements/Presenters/EdgePresenter.cs | 61 - .../Presenters/GraphElementPresenter.cs | 79 - .../Elements/Presenters/InputPortPresenter.cs | 17 - .../Elements/Presenters/MiniMapPresenter.cs | 38 - .../Elements/Presenters/NodePresenter.cs | 78 - .../Presenters/OutputPortPresenter.cs | 17 - .../Elements/Presenters/PortPresenter.cs | 117 - .../Presenters/SimpleElementPresenter.cs | 30 - .../GraphViewEditor/Elements/SimpleElement.cs | 26 - .../GraphViewEditor/GraphViewEditorWindow.cs | 86 - .../GraphViewEditor/GraphViewTypeFactory.cs | 23 - Modules/GraphViewEditor/IDroppable.cs | 24 - Modules/GraphViewEditor/ISelectable.cs | 19 - Modules/GraphViewEditor/ISelection.cs | 17 - Modules/GraphViewEditor/IconBadge.cs | 377 - .../Manipulators/ClickSelector.cs | 65 - .../Manipulators/ContentDragger.cs | 134 - .../GraphViewEditor/Manipulators/Dragger.cs | 134 - .../Manipulators/EdgeConnector.cs | 132 - .../Manipulators/EdgeDragHelper.cs | 371 - .../Manipulators/EdgeManipulator.cs | 245 - .../Manipulators/FreehandSelector.cs | 205 - .../Manipulators/RectangleSelector.cs | 228 - .../GraphViewEditor/Manipulators/Resizer.cs | 182 - .../Manipulators/SelectionDragger.cs | 389 - .../Manipulators/SelectionDropper.cs | 277 - .../Manipulators/ShortcutHandler.cs | 51 - .../GraphViewEditor/Manipulators/Zoomer.cs | 195 - Modules/GraphViewEditor/NodeAdapter.cs | 153 - .../GraphViewEditor/NodeSearch/SearchTree.cs | 47 - .../NodeSearch/SearchWindow.cs | 638 -- Modules/GraphViewEditor/Orientation.cs | 12 - Modules/GraphViewEditor/Utils/RectUtils.cs | 92 - .../Utils/VisualElementAttacher.cs | 260 - Modules/GraphViewEditor/Views/GraphView.cs | 1474 --- .../Views/Presenters/GraphViewPresenter.cs | 94 - Modules/Grid/Managed/Grid.cs | 12 - Modules/Grid/ScriptBindings/Grid.bindings.cs | 48 - .../ScriptBindings/GridLayout.bindings.cs | 82 - Modules/GridEditor/Managed/GridEditor.cs | 37 - .../GridEditor/Managed/GridEditorUtility.cs | 402 - .../Managed/SceneViewGridManager.cs | 170 - Modules/IMGUI/Event.cs | 356 - Modules/IMGUI/EventCommandNames.cs | 48 - Modules/IMGUI/EventEnums.cs | 114 - Modules/IMGUI/EventInterests.cs | 29 - Modules/IMGUI/FriendAttributes.cs | 8 - Modules/IMGUI/GUI.cs | 1714 ---- Modules/IMGUI/GUIBindings.cs | 132 - Modules/IMGUI/GUIContent.cs | 174 - Modules/IMGUI/GUIDebugger.bindings.cs | 37 - Modules/IMGUI/GUIEnums.cs | 30 - Modules/IMGUI/GUILayout.cs | 545 -- Modules/IMGUI/GUILayoutBindings.cs | 167 - Modules/IMGUI/GUILayoutOption.cs | 29 - Modules/IMGUI/GUILayoutUtility.cs | 504 - Modules/IMGUI/GUISkin.cs | 359 - Modules/IMGUI/GUIStateObjects.cs | 43 - Modules/IMGUI/GUIStyle.cs | 587 -- Modules/IMGUI/GUITargetAttribute.cs | 59 - Modules/IMGUI/GUIUtility.bindings.cs | 23 - Modules/IMGUI/GUIUtility.cs | 446 - Modules/IMGUI/LayoutEntry.cs | 323 - Modules/IMGUI/LayoutGroup.cs | 819 -- Modules/IMGUI/ObjectGUIState.bindings.cs | 46 - Modules/IMGUI/ScrollViewState.cs | 94 - Modules/IMGUI/SliderHandler.cs | 325 - Modules/IMGUI/StylePainter.cs | 313 - Modules/IMGUI/TextEditor.cs | 1456 --- Modules/Input/Private/Input.cs | 329 - Modules/Input/Private/InputModule.bindings.cs | 64 - .../Editor/Managed/BuildUtilities.cs | 38 - .../PackageManager/Editor/Managed/Client.cs | 55 - .../PackageManager/Editor/Managed/Error.cs | 39 - .../Editor/Managed/ErrorCode.cs | 19 - .../Managed/IShouldIncludeInBuildCallback.cs | 12 - .../Editor/Managed/NativeStatusCode.cs | 19 - .../Editor/Managed/OperationStatus.cs | 51 - .../Editor/Managed/PackageCollection.cs | 53 - .../Editor/Managed/PackageInfo.cs | 101 - .../Editor/Managed/PackageManager.bindings.cs | 54 - .../Editor/Managed/PackageManagerCommands.cs | 23 - .../Editor/Managed/PackageSource.cs | 18 - .../Editor/Managed/PackageStatus.cs | 17 - .../Editor/Managed/Requests/AddRequest.cs | 32 - .../Editor/Managed/Requests/ListRequest.cs | 35 - .../Editor/Managed/Requests/RemoveRequest.cs | 42 - .../Editor/Managed/Requests/Request.cs | 172 - .../Requests/ResetToEditorDefaultsRequest.cs | 26 - .../Editor/Managed/Requests/SearchRequest.cs | 48 - .../Editor/Managed/StatusCode.cs | 15 - .../Editor/Managed/VersionsInfo.cs | 64 - .../ParticlesLegacy.deprecated.cs | 43 - .../ScriptBindings/Physics2D.bindings.cs | 3385 ------- .../ScriptBindings/Physics2D.deprecated.cs | 64 - Modules/PresetsEditor/Preset.bindings.cs | 74 - Modules/PresetsEditor/PresetContextMenu.cs | 152 - Modules/PresetsEditor/PresetEditor.cs | 253 - .../PresetsEditor/PresetManager.bindings.cs | 16 - Modules/PresetsEditor/PresetManagerEditor.cs | 223 - .../PresetManagerPostProcessor.cs | 26 - Modules/PresetsEditor/PresetSelector.cs | 397 - .../Editor/ProfilerWindow/AttachProfilerUI.cs | 286 - .../ProfilerWindow/AudioProfilerView.cs | 1134 --- .../Profiler/Editor/ProfilerWindow/Chart.cs | 1022 -- .../IProfilerWindowController.cs | 24 - .../Editor/ProfilerWindow/MemoryElement.cs | 260 - .../MemoryElementDataManager.cs | 137 - .../Editor/ProfilerWindow/MemorySnapshot.cs | 282 - .../Editor/ProfilerWindow/MemoryTreeList.cs | 401 - .../ProfilerWindow/NetworkDetailStats.cs | 262 - .../Editor/ProfilerWindow/ProfilerChart.cs | 148 - .../Editor/ProfilerWindow/ProfilerColors.cs | 55 - .../ProfilerDetailedCallsView.cs | 544 -- .../ProfilerDetailedObjectsView.cs | 298 - .../ProfilerWindow/ProfilerDetailedView.cs | 63 - .../ProfilerFrameDataTreeView.cs | 715 -- .../ProfilerFrameHierarchyView.cs | 420 - .../ProfilerWindow/ProfilerFrameViewBase.cs | 147 - .../ProfilerInstrumentationPopup.cs | 253 - .../ProfilerWindow/ProfilerTimelineGUI.cs | 995 -- .../Editor/ProfilerWindow/ProfilerWindow.cs | 1521 --- .../UISystem/UISystemProfiler.cs | 417 - .../UISystem/UISystemProfilerChart.cs | 97 - .../UISystemProfilerThumbnailService.cs | 141 - .../UISystem/UISystemProfilerTreeView.cs | 443 - .../Public/ProfilerFrameDataView.bindings.cs | 236 - Modules/RestService/AssetRestHandler.cs | 119 - Modules/RestService/Handler.cs | 115 - Modules/RestService/HttpStatusCode.cs | 20 - Modules/RestService/Logger.cs | 22 - .../RestService/OpenDocumentsRestHandler.cs | 36 - Modules/RestService/PairingRestHandler.cs | 78 - Modules/RestService/PlayModeRestHandler.cs | 57 - .../RestService/ProjectStateRestHandler.cs | 171 - Modules/RestService/RestRequest.cs | 74 - Modules/RestService/RestRequestException.cs | 30 - Modules/RestService/RestServiceExtension.cs | 19 - Modules/RestService/ScriptEditorSettings.cs | 80 - .../ScriptBindings/ScreenCapture.bindings.cs | 20 - Modules/SharedInternals/Attributes.cs | 135 - Modules/SharedInternals/BindingsAttributes.cs | 399 - Modules/SharedInternals/UnityString.cs | 24 - .../ScriptBindings/SpriteMask.bindings.cs | 27 - .../Editor/Managed/SpriteMaskEditor.cs | 113 - .../SpriteShapeUtility.bindings.cs | 79 - .../Managed/SpriteShapeRendererEditor.cs | 107 - .../Substance/SubstanceUtility.bindings.cs | 24 - Modules/Substance/SubstanceUtility.cs | 334 - Modules/Terrain/Public/Terrain.bindings.cs | 213 - .../Terrain/Public/TerrainData.bindings.cs | 613 -- Modules/TextRendering/FontStyle.cs | 24 - Modules/TextRendering/TextGenerator.cs | 292 - .../Managed/CustomGridBrushAttribute.cs | 53 - Modules/Tilemap/Managed/GridBrushBase.cs | 53 - Modules/Tilemap/Managed/ITilemap.cs | 79 - Modules/Tilemap/Managed/Tile.cs | 49 - Modules/Tilemap/Managed/TileBase.cs | 37 - .../ScriptBindings/Tilemap.bindings.cs | 368 - .../Editor/Managed/EditorPreviewTilemap.cs | 78 - .../Editor/Managed/Grid/GridBrush.cs | 376 - .../Editor/Managed/Grid/GridBrushEditor.cs | 397 - .../Managed/Grid/GridBrushEditorBase.cs | 61 - .../Managed/Grid/GridBrushesDropdown.cs | 70 - .../Managed/Grid/GridPaintPaletteClipboard.cs | 1088 --- .../Managed/Grid/GridPaintPaletteWindow.cs | 1009 -- .../Managed/Grid/GridPaintTargetsDropdown.cs | 70 - .../Editor/Managed/Grid/GridPaintingState.cs | 220 - .../Editor/Managed/Grid/GridPalette.cs | 15 - .../Managed/Grid/GridPaletteAddPopup.cs | 119 - .../Editor/Managed/Grid/GridPaletteBrushes.cs | 237 - .../Editor/Managed/Grid/GridPaletteUtility.cs | 115 - .../Editor/Managed/Grid/GridPalettes.cs | 76 - .../Managed/Grid/GridPalettesDropdown.cs | 78 - .../Editor/Managed/Grid/GridSelection.cs | 59 - .../Managed/Grid/GridSelectionEditor.cs | 62 - .../Editor/Managed/Grid/PaintableGrid.cs | 508 - .../Managed/Grid/PaintableSceneViewGrid.cs | 320 - .../Editor/Managed/Grid/TileDragAndDrop.cs | 370 - .../Managed/Grid/TileDragAndDropManager.cs | 164 - .../Editor/Managed/TileEditor.cs | 121 - .../Editor/Managed/TileUtility.cs | 26 - .../Editor/Managed/TilemapCollider2DEditor.cs | 24 - .../Editor/Managed/TilemapEditor.cs | 131 - .../Editor/Managed/TilemapRendererEditor.cs | 62 - .../ScriptBindings/TilemapEditor.bindings.cs | 37 - Modules/UIElements/Button.cs | 18 - Modules/UIElements/ClampedDragger.cs | 91 - Modules/UIElements/Clickable.cs | 136 - Modules/UIElements/ContextualMenu.cs | 114 - Modules/UIElements/ContextualMenuManager.cs | 30 - .../UIElements/ContextualMenuManipulator.cs | 68 - Modules/UIElements/Cursor.cs | 62 - Modules/UIElements/EventArgs.cs | 68 - Modules/UIElements/EventDispatcher.cs | 574 -- Modules/UIElements/Events/CaptureEvents.cs | 39 - Modules/UIElements/Events/ChangeEvent.cs | 37 - Modules/UIElements/Events/EventBase.cs | 197 - Modules/UIElements/Events/EventCallback.cs | 108 - .../Events/EventCallbackRegistry.cs | 323 - Modules/UIElements/Events/EventHandler.cs | 96 - Modules/UIElements/Events/EventPool.cs | 26 - Modules/UIElements/Events/FocusEvents.cs | 78 - Modules/UIElements/Events/InputEvents.cs | 33 - Modules/UIElements/Events/KeyboardEvents.cs | 90 - Modules/UIElements/Events/LayoutEvents.cs | 33 - Modules/UIElements/Events/MouseEvents.cs | 255 - Modules/UIElements/Events/PanelEvents.cs | 14 - Modules/UIElements/Events/UIEvent.cs | 29 - Modules/UIElements/FocusController.cs | 222 - Modules/UIElements/HierarchyTraversal.cs | 250 - Modules/UIElements/IDataWatchService.cs | 21 - Modules/UIElements/IMGUIContainer.cs | 487 - Modules/UIElements/INotifyValueChanged.cs | 15 - .../UIElements/ISerializableJsonDictionary.cs | 29 - Modules/UIElements/IStyle.cs | 74 - Modules/UIElements/ITransform.cs | 14 - Modules/UIElements/Image.cs | 159 - Modules/UIElements/KeyboardTextEditor.cs | 384 - Modules/UIElements/Label.cs | 17 - .../UIElements/ManipulatorActivationFilter.cs | 45 - Modules/UIElements/Manipulators.cs | 37 - Modules/UIElements/MouseButton.cs | 13 - Modules/UIElements/MouseCaptureController.cs | 63 - Modules/UIElements/MouseManipulator.cs | 41 - Modules/UIElements/Panel.cs | 738 -- Modules/UIElements/PanelWrapper.cs | 41 - Modules/UIElements/RepeatButton.cs | 14 - Modules/UIElements/Scheduler.cs | 320 - Modules/UIElements/ScrollView.cs | 244 - Modules/UIElements/Scroller.cs | 108 - Modules/UIElements/Slider.cs | 296 - Modules/UIElements/Spacing.cs | 53 - Modules/UIElements/StyleEnums.cs | 61 - .../StyleComplexSelectorExtensions.cs | 77 - .../UIElements/StyleSheets/StyleContext.cs | 171 - .../StyleSheets/StyleSheetApplicator.cs | 210 - .../UIElements/StyleSheets/StyleSheetCache.cs | 167 - .../StyleSheets/StyleSheetExtensions.cs | 66 - Modules/UIElements/StyleSheets/StyleValue.cs | 242 - .../StyleSheets/VisualElementStylesData.cs | 551 -- Modules/UIElements/TemplateContainer.cs | 30 - Modules/UIElements/TextEditor.cs | 35 - Modules/UIElements/TextEditorEngine.cs | 39 - Modules/UIElements/TextElement.cs | 90 - Modules/UIElements/TextField.cs | 148 - Modules/UIElements/TextInputFieldBase.cs | 391 - Modules/UIElements/Toggle.cs | 52 - Modules/UIElements/TouchScreenTextEditor.cs | 53 - Modules/UIElements/UIElementsUtility.cs | 260 - Modules/UIElements/UQuery.cs | 665 -- Modules/UIElements/UXML/IUxmlAttributes.cs | 19 - Modules/UIElements/UXML/TemplateAsset.cs | 46 - Modules/UIElements/UXML/VisualElementAsset.cs | 229 - .../UIElements/UXML/VisualElementFactory.cs | 169 - Modules/UIElements/UXML/VisualTreeAsset.cs | 338 - Modules/UIElements/VisualContainer.cs | 53 - Modules/UIElements/VisualElement.cs | 1272 --- Modules/UIElements/VisualElementDataWatch.cs | 98 - Modules/UIElements/VisualElementFocusRing.cs | 272 - Modules/UIElements/VisualElementHierarchy.cs | 600 -- Modules/UIElements/VisualElementScheduler.cs | 306 - .../UIElements/VisualElementStyleAccess.cs | 905 -- Modules/UIElements/VisualElementUtils.cs | 26 - .../UIElementsDebuggerEditor/PanelDebug.cs | 66 - .../PanelPickerWindow.cs | 42 - .../UIElementsDebuggerEditor/PickingData.cs | 165 - .../UIElementsDebugger.cs | 850 -- .../UIElementsDebuggerEditor/UxmlExporter.cs | 126 - .../VisualTreeTreeView.cs | 69 - .../Events/CustomEventData.bindings.cs | 63 - .../UnityAnalytics/Events/CustomEventData.cs | 68 - Modules/UnityAnalytics/UnityAnalytics.cs | 223 - .../UnityAnalyticsHandler.bindings.cs | 83 - .../AnalyticsSessionInfo.bindings.cs | 63 - .../UnityConnect/RemoteSettings.bindings.cs | 186 - .../BuildEventsHandler.cs | 51 - .../EditorAnalytics.bindings.cs | 121 - .../UsabilityAnalytics.bindings.cs | 56 - Modules/UnityWebRequest/FriendAttributes.cs | 13 - .../CertificateHandler.bindings.cs | 55 - .../DownloadHandler.bindings.cs | 234 - .../Public/MultipartFormHelper.cs | 157 - .../Public/UnityWebRequest.bindings.cs | 571 -- .../UploadHandler/UploadHandler.bindings.cs | 129 - .../Public/WebRequest.deprecated.cs | 16 - .../Public/WebRequestExtensions.cs | 401 - .../UnityWebRequest/Public/WebRequestUtils.cs | 584 -- .../DownloadHandlerAssetBundle.bindings.cs | 66 - .../UnityWebRequestAssetBundle.cs | 118 - .../Public/DownloadHandlerAudio.bindings.cs | 87 - .../UnityWebRequestMultimedia.cs | 33 - .../Public/DownloadHandlerTexture.bindings.cs | 77 - .../UnityWebRequestTexture.cs | 32 - .../UnityWebRequestWWW/Public/WWW.bindings.cs | 21 - Modules/UnityWebRequestWWW/Public/WWW.cs | 470 - .../VideoClipPlayable.bindings.cs | 186 - .../VideoPlayerExtensions.bindings.cs | 55 - Modules/Web/FriendAttributes.cs | 8 - Modules/XR/DotNetHelper.cs | 27 - .../Camera/XRCameraSubsystem.bindings.cs | 77 - .../XRCameraSubsystemDescriptor.bindings.cs | 30 - .../Depth/XRDepthSubsystem.bindings.cs | 66 - .../XRDepthSubsystemDescriptor.bindings.cs | 22 - .../Example/XRExampleSubsystem.bindings.cs | 20 - .../XRExampleSubsystemDescriptor.bindings.cs | 22 - .../Input/XRInputSubsystem.bindings.cs | 18 - .../XRInputSubsystemDescriptor.bindings.cs | 17 - .../Planes/XRPlaneSubsystem.bindings.cs | 171 - .../XRPlaneSubsystemDescriptor.bindings.cs | 19 - .../Raycast/XRRaycastSubsystem.bindings.cs | 104 - .../XRRaycastSubsystemDescriptor.bindings.cs | 20 - .../XRReferencePointSubsystem.bindings.cs | 79 - ...erencePointSubsystemDescriptor.bindings.cs | 20 - .../Session/XRSessionSubsystem.bindings.cs | 56 - .../XRSessionSubsystemDescriptor.bindings.cs | 20 - Modules/XR/UnityXRTrackable.bindings.cs | 63 - Modules/XR/XRSubsystemManager.bindings.cs | 189 - Projects/CSharp/UnityEditor.csproj | 4207 --------- Projects/CSharp/UnityEngine.csproj | 2068 ---- Projects/CSharp/UnityReferenceSource.sln | 52 - README.md | 26 - .../SpriteDataAccess.bindings.cs | 205 - .../Common/ScriptBindings/Sprites.bindings.cs | 80 - .../ScriptBindings/SortingGroup.bindings.cs | 24 - .../AR/ScriptBindings/ARBackgroundRenderer.cs | 208 - .../AR/Tango/ScriptBindings/Tango.bindings.cs | 361 - .../AR/Tango/ScriptBindings/TangoConfig.cs | 115 - .../AR/Tango/ScriptBindings/TangoDevice.cs | 95 - .../ScriptBindings/TangoInputTracking.cs | 46 - .../TangoMeshReconstructionServer.cs | 187 - .../Animation/Managed/Animation.deprecated.cs | 132 - .../Managed/AnimationPlayableUtilities.cs | 70 - .../Animation/Managed/Animator.deprecated.cs | 31 - .../Managed/StateMachineBehaviour.cs | 90 - .../ScriptBindings/AimConstraint.bindings.cs | 134 - .../ScriptBindings/AnimationClip.bindings.cs | 107 - .../AnimationClipPlayable.bindings.cs | 111 - .../AnimationLayerMixerPlayable.bindings.cs | 105 - .../AnimationMixerPlayable.bindings.cs | 72 - ...nimationMotionXToDeltaPlayable.bindings.cs | 69 - .../AnimationOffsetPlayable.bindings.cs | 99 - .../AnimationPlayableExtensions.bindings.cs | 27 - ...imationPlayableGraphExtensions.bindings.cs | 36 - .../AnimationPlayableOutput.bindings.cs | 80 - .../ScriptBindings/Animator.bindings.cs | 1229 --- .../AnimatorControllerParameter.bindings.cs | 55 - .../AnimatorControllerPlayable.bindings.cs | 467 - .../AnimatorOverrideController.bindings.cs | 157 - .../AnimatorUtility.bindings.cs | 20 - .../ScriptBindings/Avatar.bindings.cs | 315 - .../ScriptBindings/AvatarBuilder.bindings.cs | 122 - .../ScriptBindings/AvatarMask.bindings.cs | 92 - .../ScriptBindings/Constraint.bindings.cs | 388 - .../HumanPoseHandler.bindings.cs | 105 - .../ScriptBindings/HumanTrait.bindings.cs | 103 - .../ScriptBindings/Motion.bindings.cs | 45 - .../ParentConstraint.bindings.cs | 157 - .../RuntimeAnimatorController.bindings.cs | 20 - Runtime/Cloth/Cloth.bindings.cs | 62 - Runtime/Cloth/Cloth.cs | 76 - Runtime/Dynamics/Managed/Dynamics.cs | 400 - .../ScriptBindings/RaycastCommand.bindings.cs | 44 - Runtime/Export/AndroidJNISafe.cs | 519 - Runtime/Export/AndroidJavaImpl.cs | 1291 --- Runtime/Export/Application.cs | 143 - Runtime/Export/ArrayUtils.cs | 13 - Runtime/Export/AssemblyInfo.cs | 87 - .../Export/Assertions/Assert/AssertBase.cs | 49 - .../Export/Assertions/Assert/AssertBool.cs | 39 - .../Export/Assertions/Assert/AssertFloat.cs | 62 - .../Export/Assertions/Assert/AssertGeneric.cs | 76 - .../Export/Assertions/Assert/AssertNull.cs | 65 - .../Assertions/Assert/AssertionException.cs | 31 - .../Assertions/Assert/AssertionMessageUtil.cs | 44 - .../Assert/Comparers/FloatComparer.cs | 66 - Runtime/Export/Assertions/Must/MustBool.cs | 41 - Runtime/Export/Assertions/Must/MustFloat.cs | 69 - Runtime/Export/Assertions/Must/MustGeneric.cs | 43 - Runtime/Export/Assertions/Must/MustNull.cs | 41 - Runtime/Export/AsyncGPUReadback.bindings.cs | 124 - Runtime/Export/AttributeHelperEngine.cs | 132 - Runtime/Export/Attributes.cs | 137 - Runtime/Export/AudioType.cs | 57 - Runtime/Export/BaseClass.cs | 242 - Runtime/Export/BeforeRenderHelper.cs | 102 - Runtime/Export/BootConfig.bindings.cs | 51 - Runtime/Export/Bounds.cs | 126 - Runtime/Export/BoundsInt.cs | 165 - Runtime/Export/Burst/BurstDiscardAttribute.cs | 14 - Runtime/Export/Cache.bindings.cs | 105 - Runtime/Export/Caching.bindings.cs | 295 - Runtime/Export/Caching.deprecated.cs | 18 - Runtime/Export/Camera.bindings.cs | 230 - Runtime/Export/Camera.deprecated.cs | 86 - Runtime/Export/CastHelper.cs | 17 - Runtime/Export/ClassLibraryInitializer.cs | 17 - .../NativeCollectionAccessPolicies.cs | 84 - .../NativeCollectionEnums.bindings.cs | 22 - Runtime/Export/Color.cs | 379 - Runtime/Export/Color32.cs | 84 - Runtime/Export/ColorUtility.cs | 43 - Runtime/Export/Component.bindings.cs | 235 - Runtime/Export/Component.deprecated.cs | 113 - Runtime/Export/Coroutine.bindings.cs | 29 - Runtime/Export/Coroutines.cs | 48 - Runtime/Export/CustomYieldInstruction.cs | 26 - Runtime/Export/Debug.bindings.cs | 220 - Runtime/Export/Debug.deprecated.cs | 25 - Runtime/Export/DiagnosticSwitch.cs | 50 - .../Director/CameraPlayable.bindings.cs | 87 - Runtime/Export/Director/FrameData.cs | 51 - Runtime/Export/Director/IPlayable.cs | 14 - Runtime/Export/Director/IPlayableBehaviour.cs | 27 - Runtime/Export/Director/IPlayableOutput.cs | 14 - .../MaterialEffectPlayable.bindings.cs | 99 - Runtime/Export/Director/Playable.cs | 55 - Runtime/Export/Director/PlayableAsset.cs | 77 - Runtime/Export/Director/PlayableBehaviour.cs | 38 - Runtime/Export/Director/PlayableExtensions.cs | 260 - .../Export/Director/PlayableGraph.bindings.cs | 141 - .../Director/PlayableHandle.bindings.cs | 201 - .../Director/PlayableOutput.bindings.cs | 73 - Runtime/Export/Director/PlayableOutput.cs | 48 - .../Director/PlayableOutputExtensions.cs | 69 - Runtime/Export/Director/ScriptPlayable.cs | 146 - .../Export/Director/ScriptPlayableOutput.cs | 57 - .../Director/TextureMixerPlayable.bindings.cs | 72 - ...TexturePlayableGraphExtensions.bindings.cs | 21 - .../TexturePlayableOutput.bindings.cs | 80 - .../Export/DrivenPropertyManager.bindings.cs | 46 - Runtime/Export/EnumInfo.cs | 29 - .../ExcludeFromObjectFactoryAttribute.cs | 13 - .../Export/ExposedPropertyTable.bindings.cs | 29 - Runtime/Export/ExposedReference.cs | 35 - Runtime/Export/FailedToLoadScriptObject.cs | 24 - Runtime/Export/FriendAttributes.cs | 28 - Runtime/Export/GI/Lightmapping.cs | 410 - Runtime/Export/GPUFence.bindings.cs | 87 - Runtime/Export/GameObject.deprecated.cs | 137 - Runtime/Export/GeometryUtility.cs | 89 - Runtime/Export/Graphics.bindings.cs | 683 -- Runtime/Export/Graphics.cs | 523 - Runtime/Export/Graphics.deprecated.cs | 267 - Runtime/Export/GraphicsComponents.bindings.cs | 113 - Runtime/Export/GraphicsEnums.cs | 1237 --- Runtime/Export/GraphicsManagers.bindings.cs | 128 - Runtime/Export/GraphicsRenderers.bindings.cs | 262 - Runtime/Export/Handheld.cs | 24 - Runtime/Export/Hash128.bindings.cs | 80 - Runtime/Export/IExposedPropertyTable.cs | 17 - .../Export/Internal/DefaultValueAttribute.cs | 47 - Runtime/Export/Internal/ExcludeFromDocs.cs | 19 - Runtime/Export/Internal/InternalInterfaces.cs | 17 - Runtime/Export/JetBrains.Annotations.cs | 468 - Runtime/Export/KeyCode.cs | 682 -- Runtime/Export/Light.deprecated.cs | 52 - Runtime/Export/LineUtility.cs | 52 - Runtime/Export/Logger/DebugLogHandler.cs | 21 - Runtime/Export/Logger/ILogHandler.cs | 15 - Runtime/Export/Logger/ILogger.cs | 45 - Runtime/Export/Logger/Logger.cs | 138 - Runtime/Export/ManagedStreamHelpers.cs | 49 - Runtime/Export/Math.bindings.cs | 138 - Runtime/Export/Mathf.cs | 441 - Runtime/Export/Matrix4x4.cs | 392 - Runtime/Export/Mesh.bindings.cs | 160 - Runtime/Export/Mesh.cs | 633 -- Runtime/Export/Metro.cs | 24 - Runtime/Export/MonoBehaviour.bindings.cs | 175 - Runtime/Export/MouseEvents.cs | 217 - Runtime/Export/NativeArray/DisposeSentinel.cs | 27 - Runtime/Export/NativeArray/NativeArray.cs | 264 - Runtime/Export/NativeArray/NativeSlice.cs | 298 - .../PlayerConnection/ConnectionApi.cs | 32 - .../PlayerConnection/PlayerConnection.cs | 163 - .../PlayerEditorConnectionEvents.cs | 107 - Runtime/Export/Ping.bindings.cs | 60 - Runtime/Export/Plane.cs | 128 - Runtime/Export/PlayerLoop.bindings.cs | 370 - Runtime/Export/Pose.cs | 71 - Runtime/Export/PropertyAttribute.cs | 165 - Runtime/Export/PropertyName.bindings.cs | 24 - Runtime/Export/PropertyName.cs | 89 - Runtime/Export/Quaternion.cs | 254 - Runtime/Export/Random.bindings.cs | 105 - Runtime/Export/Random.cs | 39 - Runtime/Export/RangeInt.cs | 20 - Runtime/Export/Ray.cs | 50 - Runtime/Export/Ray2D.cs | 46 - Runtime/Export/Rect.cs | 211 - Runtime/Export/RectInt.cs | 149 - Runtime/Export/RectOffset.cs | 59 - Runtime/Export/RenderPipeline/BlendState.cs | 107 - .../RenderPipeline/CullingParameters.cs | 266 - Runtime/Export/RenderPipeline/DepthState.cs | 44 - .../RenderPipeline/DrawRendererFlags.cs | 16 - .../DrawRendererSortSettings.cs | 26 - .../RenderPipeline/DrawShadowsSettings.cs | 34 - .../RenderPipeline/FilterRenderersSettings.cs | 45 - .../Export/RenderPipeline/FilterResults.cs | 17 - .../Export/RenderPipeline/IRenderPipeline.cs | 15 - .../RenderPipeline/IRenderPipelineAsset.cs | 15 - .../Export/RenderPipeline/LODParameters.cs | 50 - Runtime/Export/RenderPipeline/RasterState.cs | 59 - .../ReflectionProbeSortOptions.cs | 14 - .../Export/RenderPipeline/RenderPipeline.cs | 37 - .../RenderPipeline/RenderPipelineAsset.cs | 98 - .../RenderPipeline/RenderPipelineManager.cs | 58 - .../Export/RenderPipeline/RenderQueueRange.cs | 30 - .../Export/RenderPipeline/RenderStateBlock.cs | 67 - .../RenderPipeline/RenderStateMapping.cs | 36 - .../Export/RenderPipeline/RenderStateMask.cs | 22 - .../RenderPipeline/RenderTargetBlendState.cs | 90 - .../RenderPipeline/RendererConfiguration.cs | 25 - .../RenderPipeline/ScriptableRenderContext.cs | 112 - .../Export/RenderPipeline/ShadowSplitData.cs | 42 - Runtime/Export/RenderPipeline/SortFlags.cs | 24 - Runtime/Export/RenderPipeline/StencilState.cs | 173 - .../SupportedRenderingFeatures.cs | 179 - .../RenderPipeline/VisibleLightFlags.cs | 16 - .../Export/RenderingCommandBuffer.bindings.cs | 27 - Runtime/Export/Resources.deprecated.cs | 21 - .../RuntimeInitializeOnLoadAttribute.cs | 23 - Runtime/Export/ScriptableObject.bindings.cs | 55 - .../ScriptableRenderContext.bindings.cs | 23 - .../Export/ScriptableRenderLoop/RenderPass.cs | 58 - .../RenderPassAttachment.bindings.cs | 89 - .../APIUpdating/UpdatedFromAttribute.cs | 25 - Runtime/Export/Scripting/PreserveAttribute.cs | 13 - .../Scripting/ScriptingRuntime.bindings.cs | 15 - Runtime/Export/ScrollWaitDefinitions.cs | 12 - Runtime/Export/Security.cs | 66 - Runtime/Export/SelectionBaseAttribute.cs | 13 - Runtime/Export/Serialization.cs | 39 - .../FormerlySerializedAsAttribute.cs | 22 - Runtime/Export/Serialization/IPPtrRemapper.cs | 7 - .../ISerializedNamedStateReader.cs | 10 - .../ISerializedNamedStateWriter.cs | 10 - .../Serialization/ISerializedStateReader.cs | 9 - .../Serialization/ISerializedStateWriter.cs | 9 - .../Serialization/IUnitySerializable.cs | 11 - .../Serialization/SerializedStateReader.cs | 9 - .../Serialization/SerializedStateWriter.cs | 9 - .../Serialization/UnitySurrogateSelector.cs | 117 - Runtime/Export/Shader.bindings.cs | 279 - Runtime/Export/Shader.cs | 588 -- Runtime/Export/StackTrace.cs | 400 - .../CombineForStaticBatching.cs | 265 - .../MeshSubsetCombineUtility.cs | 38 - Runtime/Export/SystemClock.cs | 30 - Runtime/Export/SystemInfo.bindings.cs | 575 -- Runtime/Export/Texture.bindings.cs | 225 - Runtime/Export/Texture.cs | 474 - Runtime/Export/Texture.deprecated.cs | 19 - Runtime/Export/Time.bindings.cs | 77 - Runtime/Export/Tizen/Tizen.bindings.cs | 26 - Runtime/Export/TouchScreenKeyboardType.cs | 34 - Runtime/Export/TrackedReference.cs | 44 - .../UnityAPICompatibilityVersionAttribute.cs | 20 - .../APIUpdaterRuntimeServices.cs | 70 - .../TypeInferenceRuleAttribute.cs | 56 - .../UnityEngineInternal/WrappedTypes.cs | 15 - Runtime/Export/UnityEngineObject.bindings.cs | 366 - Runtime/Export/UnityEvent.cs | 1057 --- .../Export/UnityEventQueueSystem.bindings.cs | 28 - Runtime/Export/UnityEvent_0.cs | 105 - Runtime/Export/UnityEvent_1.cs | 105 - Runtime/Export/UnityEvent_2.cs | 105 - Runtime/Export/UnityEvent_3.cs | 105 - Runtime/Export/UnityEvent_4.cs | 105 - Runtime/Export/UnityLogWriter.bindings.cs | 51 - Runtime/Export/UnitySynchronizationContext.cs | 103 - .../Export/Unsafe/UnsafeUtility.bindings.cs | 85 - Runtime/Export/Unsafe/UnsafeUtilityPatched.cs | 73 - Runtime/Export/Vector2.cs | 303 - Runtime/Export/Vector2Int.cs | 183 - Runtime/Export/Vector3.cs | 342 - Runtime/Export/Vector3Int.cs | 197 - Runtime/Export/Vector4.cs | 272 - Runtime/Export/WaitForEndOfFrame.cs | 14 - Runtime/Export/WaitForFixedUpdate.cs | 14 - Runtime/Export/WaitForSeconds.cs | 20 - Runtime/Export/WaitForSecondsRealtime.cs | 21 - Runtime/Export/WaitUntil.cs | 17 - Runtime/Export/WaitWhile.cs | 17 - Runtime/Export/WinRT/NetFxCoreExtensions.cs | 23 - Runtime/Export/Windows/Speech.cs | 392 - Runtime/Export/YieldOperation.cs | 16 - .../Export/iOS/OnDemandResources.bindings.cs | 54 - Runtime/Export/iOS/TV.bindings.cs | 55 - Runtime/Export/iOS/iOS.deprecated.cs | 583 -- Runtime/Export/iOS/iOSDevice.bindings.cs | 145 - .../Export/iOS/iOSNotifications.bindings.cs | 217 - Runtime/Export/iOS/iOSReplayKit.bindings.cs | 159 - Runtime/Export/iOSSystemGestureDeferMode.cs | 19 - Runtime/Jobs/Managed/BatchQueries.cs | 40 - Runtime/Jobs/Managed/IJob.cs | 49 - Runtime/Jobs/Managed/IJobParallelFor.cs | 60 - .../Jobs/Managed/IJobParallelForTransform.cs | 63 - .../Jobs/ScriptBindings/JobHandle.bindings.cs | 113 - Runtime/Jobs/ScriptBindings/Jobs.bindings.cs | 109 - .../Networking/Managed/MatchMakingClient.cs | 444 - .../Networking/Managed/NetworkTransport.cs | 121 - .../Managed/NetworkTransportConfig.cs | 755 -- Runtime/Networking/Managed/UNETInterface.cs | 714 -- Runtime/Networking/Managed/UNETTypes.cs | 134 - .../Networking/Managed/UNETWebSocketLib.cs | 15 - .../ScriptBindings/UNETworking.bindings.cs | 53 - .../Managed/ParticleSystem.deprecated.cs | 192 - .../Managed/ParticleSystemEnums.cs | 337 - .../ParticleSystemRenderer.deprecated.cs | 111 - .../ParticleSystemRenderer.bindings.cs | 38 - .../Test/MarshallingTests.bindings.cs | 8 - .../Test/MarshallingTests2.bindings.cs | 8 - .../ScriptedObjectTests.Resources.cs | 14 - .../StyleSheets/Managed/FriendAttributes.cs | 8 - .../Managed/StyleComplexSelector.cs | 68 - Runtime/StyleSheets/Managed/StyleProperty.cs | 44 - Runtime/StyleSheets/Managed/StyleRule.cs | 32 - Runtime/StyleSheets/Managed/StyleSelector.cs | 59 - .../StyleSheets/Managed/StyleSelectorPart.cs | 95 - .../Managed/StyleSelectorRelationship.cs | 16 - .../StyleSheets/Managed/StyleSelectorType.cs | 21 - Runtime/StyleSheets/Managed/StyleSheet.cs | 169 - .../StyleSheets/Managed/StyleValueHandle.cs | 40 - .../StyleSheets/Managed/StyleValueKeyword.cs | 19 - Runtime/StyleSheets/Managed/StyleValueType.cs | 19 - .../TerrainPhysics/TerrainPhysics.bindings.cs | 17 - .../TransformAccessArray.bindings.cs | 201 - .../UI/ScriptBindings/RectTransformUtility.cs | 171 - .../ScriptBindings/GestureRecognizer.cs | 680 -- .../GestureRecognizer.deprecated.cs | 81 - .../HoloLens/ScriptBindings/GestureSource.cs | 489 - .../GestureSource.deprecated.cs | 89 - .../HolographicSettings.bindings.cs | 29 - .../HolographicSettings.deprecated.cs | 25 - .../HoloLens/ScriptBindings/SpatialMapping.cs | 184 - .../HoloLens/ScriptBindings/TransformLock.cs | 241 - Runtime/VR/HoloLens/ScriptBindings/WebCam.cs | 749 -- .../ScriptBindings/WorldManager.deprecated.cs | 26 - Runtime/VR/ScriptBindings/InputTracking.cs | 61 - Runtime/VR/ScriptBindings/VR.deprecated.cs | 304 - Runtime/VR/ScriptBindings/VRNode.cs | 20 - .../VR/ScriptBindings/VRNode.deprecated.cs | 21 - Runtime/VR/ScriptBindings/VRNodeState.cs | 178 - .../ScriptBindings/VRNodeState.deprecated.cs | 137 - Runtime/VR/ScriptBindings/XR.bindings.cs | 11 - Runtime/Vehicles/Vehicles.bindings.cs | 60 - .../DataContract/DataContract.csproj | 61 - .../DataContract/IEditorModule.cs | 36 - .../DataContract/PackageInfo.cs | 106 - .../DataContract/PackageVersion.cs | 265 - .../DataContract/Properties/AssemblyInfo.cs | 29 - Tools/Unity.CecilTools/CecilUtils.cs | 65 - Tools/Unity.CecilTools/ElementType.cs | 21 - .../Extensions/MethodDefinitionExtensions.cs | 50 - .../Extensions/ResolutionExtensions.cs | 36 - .../Extensions/TypeDefinitionExtensions.cs | 30 - .../Extensions/TypeReferenceExtensions.cs | 53 - .../Properties/AssemblyInfo.cs | 40 - .../Unity.CecilTools/Unity.CecilTools.csproj | 59 - .../Properties/AssemblyInfo.cs | 40 - .../Unity.SerializationLogic.csproj | 58 - .../UnityEngineTypePredicates.cs | 137 - .../UnitySerializationLogic.cs | 564 -- .../common/AI/NavMeshAgentBindings.gen.cs | 486 - .../common/AI/NavMeshBindings.gen.cs | 538 -- .../common/AI/NavMeshObstacleBindings.gen.cs | 150 - .../common/AI/NavMeshPathBindings.gen.cs | 93 - .../common/AI/OffMeshLinkBindings.gen.cs | 164 - .../AI/RuntimeNavMeshBuilderBindings.gen.cs | 234 - .../AIEditor/NavMeshBuilderBindings.gen.cs | 112 - ...avMeshVisualizationSettingsBindings.gen.cs | 190 - .../Animation/AnimationsBindings.gen.cs | 675 -- .../AssetBundle/AssetBundleBindings.gen.cs | 476 - .../AssetBundleManifestBindings.gen.cs | 54 - .../common/Audio/AudioBindings.gen.cs | 1851 ---- .../common/Audio/AudioMixerBindings.gen.cs | 90 - .../Audio/AudioMixerGroupBindings.gen.cs | 32 - .../Audio/AudioMixerSnapshotBindings.gen.cs | 37 - .../common/Audio/MovieTextureBindings.gen.cs | 91 - .../UnityEngineWebCamTextureBindings.gen.cs | 218 - .../common/Cloth/ClothBindings.gen.cs | 182 - .../common/Core/AndroidInputBindings.gen.cs | 60 - .../common/Core/AndroidJNIBindings.gen.cs | 1119 --- .../common/Core/AndroidJavaBindings.gen.cs | 103 - .../common/Core/AppTrialBindings.gen.cs | 19 - .../common/Core/ApplicationBindings.gen.cs | 684 -- .../common/Core/AsyncOperationBindings.gen.cs | 106 - .../common/Core/BehaviourBindings.gen.cs | 43 - .../Core/BillboardRendererBindings.gen.cs | 210 - .../common/Core/CachingBindings.gen.cs | 41 - .../common/Core/CameraBindings.gen.cs | 187 - .../common/Core/ColorUtilityBindings.gen.cs | 24 - .../common/Core/ComputeShaderBindings.gen.cs | 454 - .../common/Core/CrashReporterBindings.gen.cs | 176 - .../common/Core/CullingGroupBindings.gen.cs | 211 - .../common/Core/CursorBindings.gen.cs | 71 - .../common/Core/DisplayBindings.gen.cs | 205 - .../common/Core/DynamicGIBindings.gen.cs | 92 - .../common/Core/EventProviderBindings.gen.cs | 28 - .../common/Core/FlareLayerBindings.gen.cs | 28 - .../Core/GIDebugVisualisationBindings.gen.cs | 85 - .../common/Core/GUIElementBindings.gen.cs | 208 - .../common/Core/GameObjectBindings.gen.cs | 414 - .../common/Core/GizmoBindings.gen.cs | 252 - .../common/Core/GradientBindings.gen.cs | 151 - .../Core/GradientUtilityBindings.gen.cs | 21 - .../common/Core/GraphicsBindings.gen.cs | 524 -- .../common/Core/HandheldBindings.gen.cs | 422 - .../common/Core/InputBindings.gen.cs | 759 -- .../common/Core/LODBindings.gen.cs | 139 - .../common/Core/LayerMaskBindings.gen.cs | 58 - .../common/Core/LightBindings.gen.cs | 222 - .../common/Core/LightProbeBindings.gen.cs | 29 - .../Core/LightProbeProxyVolumeBindings.gen.cs | 148 - .../common/Core/LineUtilityBindings.gen.cs | 45 - .../common/Core/MathBindings.gen.cs | 289 - .../common/Core/NetworkingBindings.gen.cs | 1115 --- .../common/Core/PPtrRemapperBindings.gen.cs | 20 - .../Core/PlayerConnectionBindings.gen.cs | 34 - .../PlayerConnectionInternalBindings.gen.cs | 107 - .../common/Core/PlayerPrefsBindings.gen.cs | 100 - .../common/Core/ProfilerBindings.gen.cs | 213 - .../common/Core/RecorderBindings.gen.cs | 89 - .../common/Core/RectTransformBindings.gen.cs | 369 - .../Core/ReflectionProbeBindings.gen.cs | 315 - .../Core/RenderingClassesBindings.gen.cs | 136 - .../RenderingCommandBufferBindings.gen.cs | 1180 --- .../common/Core/ResourcesBindings.gen.cs | 130 - .../common/Core/RuntimeUndoBindings.gen.cs | 34 - .../common/Core/SamplerBindings.gen.cs | 126 - .../common/Core/SceneBindings.gen.cs | 133 - .../common/Core/SceneManagerBindings.gen.cs | 281 - .../common/Core/SceneUtilityBindings.gen.cs | 28 - .../Core/ScriptableRenderLoopBindings.gen.cs | 418 - .../common/Core/SecurityPublicBindings.gen.cs | 32 - .../common/Core/ShaderBindings.gen.cs | 79 - .../common/Core/SortingLayerBindings.gen.cs | 73 - .../common/Core/SpeechBindings.gen.cs | 138 - .../Core/SphericalHarmonicsL2Bindings.gen.cs | 337 - .../common/Core/SplashScreenBindings.gen.cs | 38 - .../common/Core/SpriteAtlasBindings.gen.cs | 88 - .../common/Core/SpritesBindings.gen.cs | 424 - .../common/Core/TextAssetBindings.gen.cs | 58 - .../common/Core/TextureBindings.gen.cs | 806 -- .../common/Core/TransformBindings.gen.cs | 560 -- .../common/Core/WSAApplicationBindings.gen.cs | 132 - .../common/Core/WSACursorBindings.gen.cs | 23 - .../common/Core/WSALauncherBindings.gen.cs | 64 - .../common/Core/WSATilesBindings.gen.cs | 672 -- .../Core/WindowsCrashReportingBindings.gen.cs | 27 - .../common/Core/WindowsCryptoBindings.gen.cs | 18 - .../Core/WindowsDirectoryBindings.gen.cs | 18 - .../common/Core/WindowsFileBindings.gen.cs | 18 - .../Editor/ActiveEditorTrackerBindings.gen.cs | 169 - .../Editor/AnimationUtilityBindings.gen.cs | 38 - .../Editor/AnnotationUtilityBindings.gen.cs | 125 - .../Editor/AssetDatabaseBindings.gen.cs | 679 -- .../AssetModificationProcessorBindings.gen.cs | 23 - .../Editor/AssetPostprocessorBindings.gen.cs | 64 - .../common/Editor/AssetPreviewBindings.gen.cs | 129 - .../common/Editor/AssetStoreBindings.gen.cs | 36 - .../Editor/AssetStoreContextBindings.gen.cs | 44 - .../Editor/AssetStoreToolUtilsBindings.gen.cs | 36 - .../Editor/AssetStoreUtilsBindings.gen.cs | 86 - .../Editor/AudioImporterBindings.gen.cs | 409 - .../AudioMixerControllerBindings.gen.cs | 204 - .../AudioMixerDescriptionBindings.gen.cs | 58 - .../AudioMixerEffectControllerBindings.gen.cs | 155 - .../AudioMixerGroupControllerBindings.gen.cs | 142 - ...udioMixerSnapshotControllerBindings.gen.cs | 88 - .../common/Editor/AudioUtilBindings.gen.cs | 215 - .../Editor/BuildPipelineBindings.gen.cs | 578 -- .../common/Editor/CollabBindings.gen.cs | 388 - .../Editor/ComponentUtilityBindings.gen.cs | 110 - .../Editor/ContainerWindowBindings.gen.cs | 162 - .../common/Editor/DragAndDropBindings.gen.cs | 180 - .../common/Editor/DrawGizmoBindings.gen.cs | 64 - .../Editor/EditorApplicationBindings.gen.cs | 216 - .../common/Editor/EditorBindings.gen.cs | 411 - .../EditorConnectionInternalBindings.gen.cs | 97 - .../common/Editor/EditorGUIBindings.gen.cs | 1072 --- .../Editor/EditorGUIUtilityBindings.gen.cs | 1554 --- .../EditorGraphicsSettingsBindings.gen.cs | 90 - .../Editor/EditorHandlesBindings.gen.cs | 1083 --- .../EditorHandlesUtilityBindings.gen.cs | 893 -- .../Editor/EditorJsonUtilityBindings.gen.cs | 34 - .../EditorMaterialUtilityBindings.gen.cs | 39 - .../common/Editor/EditorPrefsBindings.gen.cs | 129 - .../Editor/EditorSceneManagerBindings.gen.cs | 271 - .../Editor/EditorSettingsBindings.gen.cs | 312 - .../Editor/EditorSpriteAtlasBindings.gen.cs | 151 - .../Editor/EditorUserSettingsBindings.gen.cs | 122 - .../Editor/EditorUtilityBindings.gen.cs | 763 -- .../common/Editor/EditorWindowBindings.gen.cs | 83 - .../Editor/FrameDebuggerBindings.gen.cs | 117 - .../common/Editor/GUIViewBindings.gen.cs | 183 - .../common/Editor/HardwareBindings.gen.cs | 154 - .../common/Editor/HighlighterBindings.gen.cs | 89 - .../InternalEditorUtilityBindings.gen.cs | 969 -- .../Editor/InternalUtilityBindings.gen.cs | 971 -- .../common/Editor/LODUtilityBindings.gen.cs | 69 - .../LicenseManagementWindowBindings.gen.cs | 37 - .../Editor/LightmapParametersBindings.gen.cs | 194 - .../common/Editor/LightmappingBindings.gen.cs | 921 -- .../common/Editor/LogEntriesBindings.gen.cs | 104 - .../common/Editor/MeshUtilityBindings.gen.cs | 28 - .../Editor/ModuleMetadataBindings.gen.cs | 67 - .../Editor/MovieImporterBindings.gen.cs | 48 - .../Editor/OSColorPickerBindings.gen.cs | 53 - .../common/Editor/ObjectNamesBindings.gen.cs | 77 - .../PlayerSettingsAndroidBindings.gen.cs | 409 - .../Editor/PlayerSettingsBindings.gen.cs | 1606 ---- .../PlayerSettingsFacebookBindings.gen.cs | 38 - .../Editor/PlayerSettingsIOSBindings.gen.cs | 28 - .../Editor/PlayerSettingsN3DSBindings.gen.cs | 215 - .../PlayerSettingsSplashScreenBindings.gen.cs | 191 - .../PlayerSettingsSwitchBindings.gen.cs | 702 -- .../PlayerSettingsVRGoogleBindings.gen.cs | 125 - .../Editor/PlayerSettingsWSABindings.gen.cs | 448 - .../Editor/PlayerSettingsWebGLBindings.gen.cs | 184 - .../PlayerSettingsXboxOneBindings.gen.cs | 358 - .../Editor/PolygonEditorBindings.gen.cs | 84 - .../common/Editor/PrefabsBindings.gen.cs | 219 - .../Editor/PreferencesWindowBindings.gen.cs | 27 - .../common/Editor/ProfilerAPIBindings.gen.cs | 957 -- .../common/Editor/RegistryUtilBindings.gen.cs | 40 - .../common/Editor/RenderDocBindings.gen.cs | 42 - .../Editor/SavedGUIStateBindings.gen.cs | 75 - .../ScriptReloadPropertiesBindings.gen.cs | 125 - .../Editor/ScriptableWizardBindings.gen.cs | 231 - .../Editor/SerializedPropertyBindings.gen.cs | 845 -- .../Editor/ShaderImporterBindings.gen.cs | 41 - .../common/Editor/ShaderUtilBindings.gen.cs | 392 - .../Editor/SpeedTreeImporterBindings.gen.cs | 244 - .../Editor/SpritesEditorBindings.gen.cs | 111 - .../common/Editor/StateMachineBindings.gen.cs | 56 - .../Editor/TextureImporterBindings.gen.cs | 1653 ---- .../common/Editor/UndoBindings.gen.cs | 251 - .../common/Editor/UnityConnectBindings.gen.cs | 338 - .../common/Editor/UnityStatsBindings.gen.cs | 276 - .../common/Editor/UnsupportedBindings.gen.cs | 285 - .../common/Editor/VCAssetBindings.gen.cs | 155 - .../common/Editor/VCChangeSetBindings.gen.cs | 73 - .../Editor/VCConflictItemBindings.gen.cs | 20 - .../Editor/VCCustomCommandBindings.gen.cs | 70 - .../Editor/VCMergeResultBindings.gen.cs | 20 - .../common/Editor/VCMessageBindings.gen.cs | 66 - .../common/Editor/VCPluginBindings.gen.cs | 116 - .../common/Editor/VCTaskBindings.gen.cs | 151 - ...rtexChannelCompressionFlagsBindings.gen.cs | 45 - .../Editor/VideoImporterBindings.gen.cs | 341 - .../common/Editor/WebURLsBindings.gen.cs | 74 - .../common/Editor/WebViewBindings.gen.cs | 159 - .../common/IMGUI/EventBindings.gen.cs | 190 - .../common/IMGUI/GUIBindings.gen.cs | 228 - .../IMGUI/GUILayoutUtilityBindings.gen.cs | 51 - .../common/IMGUI/GUISkinBindings.gen.cs | 29 - .../common/IMGUI/GUIStyleBindings.gen.cs | 398 - .../common/IMGUI/GUIUtilityBindings.gen.cs | 352 - .../common/IMGUI/StylePainterBindings.gen.cs | 66 - .../ImageConversionBindings.gen.cs | 60 - .../JSONSerialize/JsonUtilityBindings.gen.cs | 44 - .../ParticleSystemBindings.gen.cs | 3834 -------- .../PerformanceReportingBindings.gen.cs | 37 - .../common/Physics/DynamicsBindings.gen.cs | 3361 ------- .../PhysicsEditor/ColliderUtilBindings.gen.cs | 39 - .../PhysicsEditor/PhysicsDebugBindings.gen.cs | 401 - .../RestServiceRequestBindings.gen.cs | 147 - .../TextRenderingBindings.gen.cs | 865 -- .../TrueTypeFontImporterBindings.gen.cs | 212 - .../common/UI/CanvasGroupBindings.gen.cs | 78 - .../common/UI/CanvasRendererBindings.gen.cs | 299 - .../UI/RectTransformUtilBindings.gen.cs | 48 - .../common/UI/UICanvasBindings.gen.cs | 271 - .../CSSLayoutCallbacksBindings.gen.cs | 29 - .../common/UNET/UNETworkingBindings.gen.cs | 861 -- .../UnityAdsSettingsBindings.gen.cs | 73 - .../UnityConnectSettingsBindings.gen.cs | 75 - .../common/VR/GestureBindings.gen.cs | 69 - .../common/VR/GestureSourceBindings.gen.cs | 38 - .../VR/HolographicSettingsBindings.gen.cs | 74 - .../common/VR/SpatialMappingBindings.gen.cs | 91 - .../common/VR/TransformLockBindings.gen.cs | 89 - .../bindings_old/common/VR/VRBindings.gen.cs | 421 - .../common/VR/VRTestBindings.gen.cs | 90 - .../common/VR/WebCamBindings.gen.cs | 136 - .../common/VR/WorldManagerBindings.gen.cs | 69 - .../HolographicEmulationBindings.gen.cs | 120 - .../common/Video/VideoClipBindings.gen.cs | 104 - .../common/Video/VideoPlayerBindings.gen.cs | 589 -- .../common/Wind/WindZoneBindings.gen.cs | 88 - third-party-notices.txt | 95 - 2082 files changed, 481371 deletions(-) delete mode 100644 Editor/Mono/2D/Common/ScriptBindings/SpriteEditorExtension.bindings.cs delete mode 100644 Editor/Mono/2D/Common/TexturePlatformSettingsController.cs delete mode 100644 Editor/Mono/2D/Common/TexturePlatformSettingsFormatHelper.cs delete mode 100644 Editor/Mono/2D/Common/TexturePlatformSettingsView.cs delete mode 100644 Editor/Mono/2D/Interface/IAssetDatabase.cs delete mode 100644 Editor/Mono/2D/Interface/IEvent.cs delete mode 100644 Editor/Mono/2D/Interface/IGL.cs delete mode 100644 Editor/Mono/2D/Interface/IGUIUtility.cs delete mode 100644 Editor/Mono/2D/Interface/IHandles.cs delete mode 100644 Editor/Mono/2D/Interface/ISpriteEditorDataProvider.cs delete mode 100644 Editor/Mono/2D/Interface/ITexture.cs delete mode 100644 Editor/Mono/2D/Interface/ITexturePlatformSetting.cs delete mode 100644 Editor/Mono/2D/Interface/IUndoSystem.cs delete mode 100644 Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/ISpriteEditorModule.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModule.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleView.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpritePolygonModeModule.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpritePolygonModeModuleView.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs delete mode 100644 Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs delete mode 100644 Editor/Mono/Accessibility/UserAccessibilitySettings.cs delete mode 100644 Editor/Mono/Animation/AnimationClipSettings.bindings.cs delete mode 100644 Editor/Mono/Animation/AnimationClipStats.bindings.cs delete mode 100644 Editor/Mono/Animation/AnimationMode.bindings.cs delete mode 100644 Editor/Mono/Animation/AnimationUtility.bindings.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimEditor.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimEditorOverlay.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationClipSelectionItem.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationContextualPropertyMenu.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationKeyTime.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowClipPopup.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowCurve.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowEvent.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowEventInspector.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchy.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyDataSource.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyNode.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowKeySelection.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowKeyframe.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowManipulator.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowSelectionItem.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowStyles.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/ControlPointRenderer.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveBindingUtility.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveEditor.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveEditorRectangleTool.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveEditorSelection.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveEditorWindow.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveMenuManager.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveRenderer/BoolCurveRenderer.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveRenderer/CurveRenderer.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveRenderer/EulerCurveCombinedRenderer.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveRenderer/EulerCurveRenderer.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveRenderer/IntCurveRenderer.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/CurveRenderer/NormalCurveRenderer.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/Deprecated/AnimationEventTimeline.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/Deprecated/EditorGUIExt.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/Deprecated/UtilityClasses.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/DopeLine.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/DopeSheetEditor.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/DopeSheetEditorRectangleTool.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/GameObjectSelectionItem.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/IAnimationContextualResponder.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/IAnimationRecordingState.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/IAnimationWindowControl.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/RectangleTool.cs delete mode 100644 Editor/Mono/Animation/AnimationWindow/RotationCurveInterpolation.cs delete mode 100644 Editor/Mono/Animation/AnimatorController.cs delete mode 100644 Editor/Mono/Animation/BlendTree.cs delete mode 100644 Editor/Mono/Animation/EditorCurveBinding.bindings.cs delete mode 100644 Editor/Mono/Animation/GameObjectRecorder.bindings.cs delete mode 100644 Editor/Mono/Animation/MaterialAnimationUtility.cs delete mode 100644 Editor/Mono/Animation/MecanimUtilities.cs delete mode 100644 Editor/Mono/Animation/SerializedStringTable.cs delete mode 100644 Editor/Mono/Animation/StateMachine.cs delete mode 100644 Editor/Mono/Animation/TickHandler.cs delete mode 100644 Editor/Mono/Animation/TickStyle.cs delete mode 100644 Editor/Mono/Animation/TimeArea.cs delete mode 100644 Editor/Mono/Animation/TransitionPreview.cs delete mode 100644 Editor/Mono/Animation/ZoomableArea.cs delete mode 100644 Editor/Mono/AnimationCurvePreviewCache.bindings.cs delete mode 100644 Editor/Mono/AnimatorController.bindings.cs delete mode 100644 Editor/Mono/AnimatorControllerLayer.bindings.cs delete mode 100644 Editor/Mono/Annotation/AnnotationWindow.cs delete mode 100644 Editor/Mono/Annotation/LayerVisibilityWindow.cs delete mode 100644 Editor/Mono/Annotation/SceneFXWindow.cs delete mode 100644 Editor/Mono/Annotation/SceneRenderModeWindow.cs delete mode 100644 Editor/Mono/AssembleEditorSkin.cs delete mode 100644 Editor/Mono/AssemblyHelper.cs delete mode 100644 Editor/Mono/AssemblyInfo/AssemblyInfo.cs delete mode 100644 Editor/Mono/AssemblyReloadEvents.cs delete mode 100644 Editor/Mono/AssetDatabase/AssetDatabase.bindings.cs delete mode 100644 Editor/Mono/AssetDatabase/AssetDatabase.cs delete mode 100644 Editor/Mono/AssetDatabase/AssetDatabase.deprecated.cs delete mode 100644 Editor/Mono/AssetDatabase/AssetDatabaseSearching.cs delete mode 100644 Editor/Mono/AssetDatabase/AssetImportInProgressProxy.bindings.cs delete mode 100644 Editor/Mono/AssetModificationProcessor.cs delete mode 100644 Editor/Mono/AssetPipeline/AssemblyDefinitionImporter.cs delete mode 100644 Editor/Mono/AssetPipeline/AssetImportContext.bindings.cs delete mode 100644 Editor/Mono/AssetPipeline/AssetImporter.bindings.cs delete mode 100644 Editor/Mono/AssetPipeline/LocalCacheServer.cs delete mode 100644 Editor/Mono/AssetPipeline/ModelImporter.bindings.cs delete mode 100644 Editor/Mono/AssetPipeline/MonoImporter.bindings.cs delete mode 100644 Editor/Mono/AssetPipeline/NativeFormatImporterUtility.bindings.cs delete mode 100644 Editor/Mono/AssetPipeline/ScriptedImporter.cs delete mode 100644 Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs delete mode 100644 Editor/Mono/AssetPostprocessor.cs delete mode 100644 Editor/Mono/AssetPreviewUpdater.cs delete mode 100644 Editor/Mono/AssetStore/AssetStoreAsset.cs delete mode 100644 Editor/Mono/AssetStore/AssetStoreAssetSelection.cs delete mode 100644 Editor/Mono/AssetStore/AssetStoreClient.cs delete mode 100644 Editor/Mono/AssetStore/AssetStoreContext.cs delete mode 100644 Editor/Mono/AssetStore/AssetStoreInstaBuyWindow.cs delete mode 100644 Editor/Mono/AssetStore/AssetStoreLoginWIndow.cs delete mode 100644 Editor/Mono/AssetStore/AssetStorePreviewManager.cs delete mode 100644 Editor/Mono/AssetStore/AssetStoreWindow.cs delete mode 100644 Editor/Mono/AssetStore/Json.cs delete mode 100644 Editor/Mono/AssetStoreToolUtils.cs delete mode 100644 Editor/Mono/AsyncHTTPClient.bindings.cs delete mode 100644 Editor/Mono/AsyncHTTPClient.cs delete mode 100644 Editor/Mono/AsyncProgressBar.bindings.cs delete mode 100644 Editor/Mono/AttributeHelper.cs delete mode 100644 Editor/Mono/Audio/Effects/AudioCurveRendering.cs delete mode 100644 Editor/Mono/Audio/Effects/AudioMixerEffectPlugin.cs delete mode 100644 Editor/Mono/Audio/Effects/Complex.cs delete mode 100644 Editor/Mono/Audio/Effects/DuckVolumeGUI.cs delete mode 100644 Editor/Mono/Audio/Effects/IAudioEffectPlugin.cs delete mode 100644 Editor/Mono/Audio/Effects/IAudioEffectPluginGUI.cs delete mode 100644 Editor/Mono/Audio/Effects/ParamEQGUI.cs delete mode 100644 Editor/Mono/Audio/Mixer/AudioMixerDescription.cs delete mode 100644 Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs delete mode 100644 Editor/Mono/Audio/Mixer/Bindings/AudioMixerGroup.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerChannelStripView.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerColorCodes.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerDrawUtils.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerEffectGUI.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerEffectView.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupTreeView.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupViewList.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerSelection.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerSnapshotPopup.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerSnapshotView.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerUtility.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/AudioMixersTreeView.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/ObjectTreeSelector.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/ReorderableListWithRenameAndScrollView.cs delete mode 100644 Editor/Mono/Audio/Mixer/GUI/TreeViewForAudioMixerGroups.cs delete mode 100644 Editor/Mono/Audio/StreamedAudioClipPreview.cs delete mode 100644 Editor/Mono/Audio/WaveformPreview.cs delete mode 100644 Editor/Mono/Audio/WaveformPreviewFactory.cs delete mode 100644 Editor/Mono/Audio/WaveformStreamer.bindings.cs delete mode 100644 Editor/Mono/AvatarUtility.bindings.cs delete mode 100644 Editor/Mono/BlendTree.bindings.cs delete mode 100644 Editor/Mono/BlendTreePreviewUtility.bindings.cs delete mode 100644 Editor/Mono/BuildPipeline/AssemblyStripper.cs delete mode 100644 Editor/Mono/BuildPipeline/AssemblyTypeInfoGenerator.cs delete mode 100644 Editor/Mono/BuildPipeline/AssemblyValidation.cs delete mode 100644 Editor/Mono/BuildPipeline/BuildFailedException.cs delete mode 100644 Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs delete mode 100644 Editor/Mono/BuildPipeline/BuildPlatform.cs delete mode 100644 Editor/Mono/BuildPipeline/BuildUtils.cs delete mode 100644 Editor/Mono/BuildPipeline/BuildVerifier.cs delete mode 100644 Editor/Mono/BuildPipeline/CodeStrippingUtils.cs delete mode 100644 Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs delete mode 100644 Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs delete mode 100644 Editor/Mono/BuildPipeline/DesktopStandaloneUserBuildSettings.cs delete mode 100644 Editor/Mono/BuildPipeline/GendarmeAssemblyValidation.cs delete mode 100644 Editor/Mono/BuildPipeline/Il2Cpp/FileMirroring.cs delete mode 100644 Editor/Mono/BuildPipeline/Il2Cpp/ICompilerSettings.cs delete mode 100644 Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs delete mode 100644 Editor/Mono/BuildPipeline/Il2Cpp/INativeCompiler.cs delete mode 100644 Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs delete mode 100644 Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilderUtils.cs delete mode 100644 Editor/Mono/BuildPipeline/Il2Cpp/NativeCompiler.cs delete mode 100644 Editor/Mono/BuildPipeline/MonoAssemblyStripping.cs delete mode 100644 Editor/Mono/BuildPipeline/MonoCrossCompile.cs delete mode 100644 Editor/Mono/BuildPipeline/MonoInternalCallGenerator.cs delete mode 100644 Editor/Mono/BuildPipeline/PostProcessStandalonePlayer.cs delete mode 100644 Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs delete mode 100644 Editor/Mono/BuildPipeline/RuntimeClassMetadata.cs delete mode 100644 Editor/Mono/BuildPipeline/WinRT/WinRTUtils.cs delete mode 100644 Editor/Mono/BuildPlayerSceneTreeView.cs delete mode 100644 Editor/Mono/BuildPlayerWindow.cs delete mode 100644 Editor/Mono/BuildPlayerWindowBuildMethods.cs delete mode 100644 Editor/Mono/BuildPlayerWindowPublish.cs delete mode 100644 Editor/Mono/BuildTarget.cs delete mode 100644 Editor/Mono/BuildTargetGroup.cs delete mode 100644 Editor/Mono/Burst/BurstCompilerService.bindings.cs delete mode 100644 Editor/Mono/Burst/BurstCompilerService.cs delete mode 100644 Editor/Mono/CSPreProcess.cs delete mode 100644 Editor/Mono/Callbacks.cs delete mode 100644 Editor/Mono/ChangeTrackerHandle.bindings.cs delete mode 100644 Editor/Mono/CloudBuild/CloudBuild.cs delete mode 100644 Editor/Mono/Collab/AssetAccess.cs delete mode 100644 Editor/Mono/Collab/CloudBuildStatus.cs delete mode 100644 Editor/Mono/Collab/Collab.bindings.cs delete mode 100644 Editor/Mono/Collab/Collab.cs delete mode 100644 Editor/Mono/Collab/CollabAnalytics.cs delete mode 100644 Editor/Mono/Collab/CollabChange.cs delete mode 100644 Editor/Mono/Collab/CollabChangeAction.cs delete mode 100644 Editor/Mono/Collab/CollabDialogs.cs delete mode 100644 Editor/Mono/Collab/CollabEditorHooks.cs delete mode 100644 Editor/Mono/Collab/CollabFilters.cs delete mode 100644 Editor/Mono/Collab/CollabHistoryWindow.cs delete mode 100644 Editor/Mono/Collab/CollabProgressInfo.cs delete mode 100644 Editor/Mono/Collab/CollabRevision.cs delete mode 100644 Editor/Mono/Collab/CollabRevisionsData.cs delete mode 100644 Editor/Mono/Collab/CollabTesting.cs delete mode 100644 Editor/Mono/Collab/CollabToolbarWindow.cs delete mode 100644 Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs delete mode 100644 Editor/Mono/Collab/RevisionsService.cs delete mode 100644 Editor/Mono/Collab/Softlocks/CollabSoftLocks.cs delete mode 100644 Editor/Mono/Collab/Softlocks/SoftlockData.cs delete mode 100644 Editor/Mono/Collab/Softlocks/SoftlockFilter.cs delete mode 100644 Editor/Mono/Collab/Softlocks/SoftlockUIData.cs delete mode 100644 Editor/Mono/Collab/Softlocks/SoftlockViewController.cs delete mode 100644 Editor/Mono/Collab/Views/BuildStatusButton.cs delete mode 100644 Editor/Mono/Collab/Views/CollabHistoryDropDown.cs delete mode 100644 Editor/Mono/Collab/Views/CollabHistoryDropDownItem.cs delete mode 100644 Editor/Mono/Collab/Views/CollabHistoryItem.cs delete mode 100644 Editor/Mono/Collab/Views/CollabHistoryItemFactory.cs delete mode 100644 Editor/Mono/Collab/Views/CollabHistoryRevisionLine.cs delete mode 100644 Editor/Mono/Collab/Views/HistoryProgressSpinner.cs delete mode 100644 Editor/Mono/Collab/Views/ICollabHistoryItemFactory.cs delete mode 100644 Editor/Mono/Collab/Views/ICollabHistoryWindow.cs delete mode 100644 Editor/Mono/Collab/Views/PagedListView.cs delete mode 100644 Editor/Mono/Collab/Views/StatusView.cs delete mode 100644 Editor/Mono/Commands/GOCreationCommands.cs delete mode 100644 Editor/Mono/CompilationPipeline.bindings.cs delete mode 100644 Editor/Mono/ComponentUtility.cs delete mode 100644 Editor/Mono/ConsoleWindow.cs delete mode 100644 Editor/Mono/ContainerWindow.cs delete mode 100644 Editor/Mono/CustomEditorAttributes.cs delete mode 100644 Editor/Mono/DataWatchService.cs delete mode 100644 Editor/Mono/DefaultAsset.bindings.cs delete mode 100644 Editor/Mono/DeploymentTargets/DefaultDeploymentTargetsExtension.cs delete mode 100644 Editor/Mono/DeploymentTargets/DeploymentTargetManager.cs delete mode 100644 Editor/Mono/DeploymentTargets/IDeploymentTargetsExtension.cs delete mode 100644 Editor/Mono/DisplayUtility.cs delete mode 100644 Editor/Mono/DrivenPropertyManagerInternal.bindings.cs delete mode 100644 Editor/Mono/DrivenRectTransformUndo.cs delete mode 100644 Editor/Mono/DropInfo.cs delete mode 100644 Editor/Mono/EditorApplication.cs delete mode 100644 Editor/Mono/EditorApplication.deprecated.cs delete mode 100644 Editor/Mono/EditorAssemblies.bindings.cs delete mode 100644 Editor/Mono/EditorAssemblies.cs delete mode 100644 Editor/Mono/EditorBuildSettings.bindings.cs delete mode 100644 Editor/Mono/EditorGUI.EnumMaskField.deprecated.cs delete mode 100644 Editor/Mono/EditorGUI.bindings.cs delete mode 100644 Editor/Mono/EditorGUI.cs delete mode 100644 Editor/Mono/EditorGUIUtility.bindings.cs delete mode 100644 Editor/Mono/EditorGUIUtility.cs delete mode 100644 Editor/Mono/EditorGraphicsSettings.cs delete mode 100644 Editor/Mono/EditorHandles.cs delete mode 100644 Editor/Mono/EditorHandles/ArcHandle.cs delete mode 100644 Editor/Mono/EditorHandles/BoneHandle.cs delete mode 100644 Editor/Mono/EditorHandles/BoundsHandle/BoxBoundsHandle.cs delete mode 100644 Editor/Mono/EditorHandles/BoundsHandle/CapsuleBoundsHandle.cs delete mode 100644 Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs delete mode 100644 Editor/Mono/EditorHandles/BoundsHandle/SphereBoundsHandle.cs delete mode 100644 Editor/Mono/EditorHandles/Button.cs delete mode 100644 Editor/Mono/EditorHandles/ConeFrustrumHandle.cs delete mode 100644 Editor/Mono/EditorHandles/ConeHandle.cs delete mode 100644 Editor/Mono/EditorHandles/Disc.cs delete mode 100644 Editor/Mono/EditorHandles/FreeMove.cs delete mode 100644 Editor/Mono/EditorHandles/FreeRotate.cs delete mode 100644 Editor/Mono/EditorHandles/JointAngularLimitHandle.cs delete mode 100644 Editor/Mono/EditorHandles/PositionHandle.cs delete mode 100644 Editor/Mono/EditorHandles/RadiusHandle.cs delete mode 100644 Editor/Mono/EditorHandles/RectHandle.cs delete mode 100644 Editor/Mono/EditorHandles/RotationHandle.cs delete mode 100644 Editor/Mono/EditorHandles/ScaleHandle.cs delete mode 100644 Editor/Mono/EditorHandles/SimpleRadiusHandle.cs delete mode 100644 Editor/Mono/EditorHandles/Slider1D.cs delete mode 100644 Editor/Mono/EditorHandles/Slider2D.cs delete mode 100644 Editor/Mono/EditorHandles/SliderScale.cs delete mode 100644 Editor/Mono/EditorHandles/TransformHandle.cs delete mode 100644 Editor/Mono/EditorHandles/VertexSnapping.cs delete mode 100644 Editor/Mono/EditorHeaderItemAttribute.cs delete mode 100644 Editor/Mono/EditorResourcesUtility.bindings.cs delete mode 100644 Editor/Mono/EditorUserBuildSettings.bindings.cs delete mode 100644 Editor/Mono/EditorUserBuildSettings.deprecated.cs delete mode 100644 Editor/Mono/EditorUserBuildSettingsUtils.cs delete mode 100644 Editor/Mono/EditorUtility.bindings.cs delete mode 100644 Editor/Mono/EditorWindow.cs delete mode 100644 Editor/Mono/ExportPackageOptions.cs delete mode 100644 Editor/Mono/FileUtil.bindings.cs delete mode 100644 Editor/Mono/FileUtil.cs delete mode 100644 Editor/Mono/FlagSet.cs delete mode 100644 Editor/Mono/GI/LightmapEditorSettingsDeprecated.cs delete mode 100644 Editor/Mono/GI/LightmapSnapshot.deprecated.cs delete mode 100644 Editor/Mono/GI/Lightmapping.deprecated.cs delete mode 100644 Editor/Mono/GUI/AboutWindow.cs delete mode 100644 Editor/Mono/GUI/AboutWindowNames.cs delete mode 100644 Editor/Mono/GUI/AngularDial.cs delete mode 100644 Editor/Mono/GUI/AnimatedValues.cs delete mode 100644 Editor/Mono/GUI/AppStatusBar.cs delete mode 100644 Editor/Mono/GUI/AssetPopupBackend.cs delete mode 100644 Editor/Mono/GUI/AssetSaveDialog.cs delete mode 100644 Editor/Mono/GUI/BumpMapSettingsFixingWindow.cs delete mode 100644 Editor/Mono/GUI/ButtonWithAnimatedIcon.cs delete mode 100644 Editor/Mono/GUI/CallbackController.cs delete mode 100644 Editor/Mono/GUI/ColorClipboard.cs delete mode 100644 Editor/Mono/GUI/ColorMutator.cs delete mode 100644 Editor/Mono/GUI/ColorPicker.cs delete mode 100644 Editor/Mono/GUI/ColorPicker.deprecated.cs delete mode 100644 Editor/Mono/GUI/ColumnView.cs delete mode 100644 Editor/Mono/GUI/CreateAssetUtility.cs delete mode 100644 Editor/Mono/GUI/DockArea.cs delete mode 100644 Editor/Mono/GUI/DragRect.cs delete mode 100644 Editor/Mono/GUI/EditorApplicationLayout.cs delete mode 100644 Editor/Mono/GUI/EditorCache.cs delete mode 100644 Editor/Mono/GUI/EditorGUIContents.cs delete mode 100644 Editor/Mono/GUI/EditorGUIInternal.cs delete mode 100644 Editor/Mono/GUI/EditorStyles.cs delete mode 100644 Editor/Mono/GUI/EditorUpdateWindow.cs delete mode 100644 Editor/Mono/GUI/ExposablePopupMenu.cs delete mode 100644 Editor/Mono/GUI/FallbackEditorWindow.cs delete mode 100644 Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs delete mode 100644 Editor/Mono/GUI/FlexibleMenu/FlexibleMenuModifyItemUI.cs delete mode 100644 Editor/Mono/GUI/FlexibleMenu/IFlexibleMenuItemProvider.cs delete mode 100644 Editor/Mono/GUI/FlowLayout.cs delete mode 100644 Editor/Mono/GUI/GenericMenu.cs delete mode 100644 Editor/Mono/GUI/GradientEditor.cs delete mode 100644 Editor/Mono/GUI/GradientField.cs delete mode 100644 Editor/Mono/GUI/GradientPicker.cs delete mode 100644 Editor/Mono/GUI/HexColorTextField.cs delete mode 100644 Editor/Mono/GUI/InternalEditorGUI.cs delete mode 100644 Editor/Mono/GUI/InternalEditorGUILayout.cs delete mode 100644 Editor/Mono/GUI/Knob.cs delete mode 100644 Editor/Mono/GUI/ListViewElement.cs delete mode 100644 Editor/Mono/GUI/ListViewGUI.cs delete mode 100644 Editor/Mono/GUI/ListViewGUILayout.cs delete mode 100644 Editor/Mono/GUI/ListViewOptions.cs delete mode 100644 Editor/Mono/GUI/ListViewShared.cs delete mode 100644 Editor/Mono/GUI/ListViewState.cs delete mode 100644 Editor/Mono/GUI/MainView.cs delete mode 100644 Editor/Mono/GUI/MaskFieldGUI.cs delete mode 100644 Editor/Mono/GUI/ObjectField.cs delete mode 100644 Editor/Mono/GUI/PackageExport.cs delete mode 100644 Editor/Mono/GUI/PackageExportTreeView.cs delete mode 100644 Editor/Mono/GUI/PackageImport.cs delete mode 100644 Editor/Mono/GUI/PackageImportTreeView.cs delete mode 100644 Editor/Mono/GUI/PaneDragTab.cs delete mode 100644 Editor/Mono/GUI/PingData.cs delete mode 100644 Editor/Mono/GUI/PopupLocationHelper.cs delete mode 100644 Editor/Mono/GUI/PopupWindow.cs delete mode 100644 Editor/Mono/GUI/PopupWindowWithoutFocus.cs delete mode 100644 Editor/Mono/GUI/PragmaFixingWindow.cs delete mode 100644 Editor/Mono/GUI/PreviewResizer.cs delete mode 100644 Editor/Mono/GUI/QuadTree.cs delete mode 100644 Editor/Mono/GUI/RenameOverlay.cs delete mode 100644 Editor/Mono/GUI/ReorderableList.cs delete mode 100644 Editor/Mono/GUI/ScalableGUIContent.cs delete mode 100644 Editor/Mono/GUI/ScreenShotting.cs delete mode 100644 Editor/Mono/GUI/SearchField.cs delete mode 100644 Editor/Mono/GUI/SliderWithTexture.cs delete mode 100644 Editor/Mono/GUI/SplitView.cs delete mode 100644 Editor/Mono/GUI/Splitter.cs delete mode 100644 Editor/Mono/GUI/StructPropertyGUI.cs delete mode 100644 Editor/Mono/GUI/TargetChoiceHandler.cs delete mode 100644 Editor/Mono/GUI/TextFieldDropDown.cs delete mode 100644 Editor/Mono/GUI/Toolbar.cs delete mode 100644 Editor/Mono/GUI/Tools/BuiltinTools.cs delete mode 100644 Editor/Mono/GUI/Tools/SnapSettings.cs delete mode 100644 Editor/Mono/GUI/Tools/Tools.cs delete mode 100644 Editor/Mono/GUI/Tools/TransformManipulator.cs delete mode 100644 Editor/Mono/GUI/TreeView/AssetOrGameObjectTreeViewDragging.cs delete mode 100644 Editor/Mono/GUI/TreeView/AssetsTreeViewDataSource.cs delete mode 100644 Editor/Mono/GUI/TreeView/AssetsTreeViewGUI.cs delete mode 100644 Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs delete mode 100644 Editor/Mono/GUI/TreeView/GameObjectTreeViewGUI.cs delete mode 100644 Editor/Mono/GUI/TreeView/GameObjectTreeViewItem.cs delete mode 100644 Editor/Mono/GUI/TreeView/ITreeViewDataSource.cs delete mode 100644 Editor/Mono/GUI/TreeView/ITreeViewDragging.cs delete mode 100644 Editor/Mono/GUI/TreeView/ITreeViewGUI.cs delete mode 100644 Editor/Mono/GUI/TreeView/LazyTreeViewDataSource.cs delete mode 100644 Editor/Mono/GUI/TreeView/MultiColumnHeader.cs delete mode 100644 Editor/Mono/GUI/TreeView/MultiColumnHeaderDefaults.cs delete mode 100644 Editor/Mono/GUI/TreeView/MultiColumnHeaderState.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControl.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDataSource.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDefaults.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDragging.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlGUI.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewController.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewDataSource.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewDragging.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewExpandAnimator.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewGUI.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewGUIWithCustomItemHeights.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewItem.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTest.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestBackEnd.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestDataSource.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestDragging.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestGUI.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestGUICustom.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestLazyDataSource.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestWindow.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestWithCustomHeight.cs delete mode 100644 Editor/Mono/GUI/TreeView/TreeViewUtililty.cs delete mode 100644 Editor/Mono/GUI/TypeSelectionList.cs delete mode 100644 Editor/Mono/GUI/VUMeter.cs delete mode 100644 Editor/Mono/GUI/VerticalGrid.cs delete mode 100644 Editor/Mono/GUI/WindowLayout.cs delete mode 100644 Editor/Mono/GUID.bindings.cs delete mode 100644 Editor/Mono/GUIDebugger/BaseInspectView.cs delete mode 100644 Editor/Mono/GUIDebugger/GUIClipInspectView.cs delete mode 100644 Editor/Mono/GUIDebugger/GUILayoutInspectView.cs delete mode 100644 Editor/Mono/GUIDebugger/GUINamedControlInspectView.cs delete mode 100644 Editor/Mono/GUIDebugger/GUIPropertyInspectView.cs delete mode 100644 Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.cs delete mode 100644 Editor/Mono/GUIDebugger/GUIViewDebuggerWindow.cs delete mode 100644 Editor/Mono/GUIDebugger/StyleDrawInspectView.cs delete mode 100644 Editor/Mono/GUIDebugger/UnifiedInspectView.cs delete mode 100644 Editor/Mono/GUIView.cs delete mode 100644 Editor/Mono/GameObjectUtility.bindings.cs delete mode 100644 Editor/Mono/GameView/GameView.cs delete mode 100644 Editor/Mono/GameView/GameViewSize.cs delete mode 100644 Editor/Mono/GameView/GameViewSizeGroup.cs delete mode 100644 Editor/Mono/GameView/GameViewSizeMenu.cs delete mode 100644 Editor/Mono/GameView/GameViewSizes.cs delete mode 100644 Editor/Mono/GameView/GameViewSizesMenuItemProvider.cs delete mode 100644 Editor/Mono/GameView/GameViewSizesMenuModifyItemUI.cs delete mode 100644 Editor/Mono/GameView/IGameViewSizeMenuUser.cs delete mode 100644 Editor/Mono/GameviewGUI.cs delete mode 100644 Editor/Mono/GenerateIconsWithMipLevels.cs delete mode 100644 Editor/Mono/GradientPreviewCache.bindings.cs delete mode 100644 Editor/Mono/Grid/GridSnapping.cs delete mode 100644 Editor/Mono/Help.bindings.cs delete mode 100644 Editor/Mono/HomeWindow.bindings.cs delete mode 100644 Editor/Mono/HostView.cs delete mode 100644 Editor/Mono/ICleanuppable.cs delete mode 100644 Editor/Mono/IDropArea.cs delete mode 100644 Editor/Mono/IHasCustomMenu.cs delete mode 100644 Editor/Mono/IconSelector.cs delete mode 100644 Editor/Mono/ImportSettings/AnimationClipInfoProperties.cs delete mode 100644 Editor/Mono/ImportSettings/AssetImporterEditor.cs delete mode 100644 Editor/Mono/ImportSettings/AudioImporterInspector.cs delete mode 100644 Editor/Mono/ImportSettings/BaseAssetImporterTabUI.cs delete mode 100644 Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs delete mode 100644 Editor/Mono/ImportSettings/EditorPluginImporterExtension.cs delete mode 100644 Editor/Mono/ImportSettings/ExposeTransformEditor.cs delete mode 100644 Editor/Mono/ImportSettings/IHVImageFormatImporterInspector.cs delete mode 100644 Editor/Mono/ImportSettings/ModelImporterClipEditor.cs delete mode 100644 Editor/Mono/ImportSettings/ModelImporterEditor.cs delete mode 100644 Editor/Mono/ImportSettings/ModelImporterMaterialEditor.cs delete mode 100644 Editor/Mono/ImportSettings/ModelImporterModelEditor.cs delete mode 100644 Editor/Mono/ImportSettings/ModelImporterRigEditor.cs delete mode 100644 Editor/Mono/ImportSettings/MovieImporterInspector.cs delete mode 100644 Editor/Mono/ImportSettings/PatchImportSettingsRecycleID.cs delete mode 100644 Editor/Mono/ImportSettings/PluginImporterInspector.cs delete mode 100644 Editor/Mono/ImportSettings/PrefabUtility.cs delete mode 100644 Editor/Mono/ImportSettings/ScriptedImporterEditor.cs delete mode 100644 Editor/Mono/ImportSettings/SpeedTreeImporterInspector.cs delete mode 100644 Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs delete mode 100644 Editor/Mono/ImportSettings/TextureImporterInspector.cs delete mode 100644 Editor/Mono/ImportSettings/TrueTypeFontImporterInspector.cs delete mode 100644 Editor/Mono/ImportSettings/VideoClipImporterInspector.cs delete mode 100644 Editor/Mono/Inspector/AddComponent/AddComponentDataSource.cs delete mode 100644 Editor/Mono/Inspector/AddComponent/AddComponentGUI.cs delete mode 100644 Editor/Mono/Inspector/AddComponent/AddComponentWindow.cs delete mode 100644 Editor/Mono/Inspector/AddComponent/ComponentDropdownItem.cs delete mode 100644 Editor/Mono/Inspector/AddComponent/NewScriptDropdownItem.cs delete mode 100644 Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownDataSource.cs delete mode 100644 Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs delete mode 100644 Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownItem.cs delete mode 100644 Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownSimpleDataSource.cs delete mode 100644 Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownWindow.cs delete mode 100644 Editor/Mono/Inspector/AdvancedDropdown/StatefulAdvancedDropdown.cs delete mode 100644 Editor/Mono/Inspector/AdvancedDropdown/StatelessAdvancedDropdown.cs delete mode 100644 Editor/Mono/Inspector/AimConstraintEditor.cs delete mode 100644 Editor/Mono/Inspector/AnchoredJoint2DEditor.cs delete mode 100644 Editor/Mono/Inspector/AnimationClipEditor.cs delete mode 100644 Editor/Mono/Inspector/AnimationEditor.cs delete mode 100644 Editor/Mono/Inspector/AnimatorInspector.cs delete mode 100644 Editor/Mono/Inspector/AnimatorOverrideControllerInspector.cs delete mode 100644 Editor/Mono/Inspector/AreaEffector2DEditor.cs delete mode 100644 Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs delete mode 100644 Editor/Mono/Inspector/AssetBundleNameGUI.cs delete mode 100644 Editor/Mono/Inspector/AssetStoreAssetInspector.cs delete mode 100644 Editor/Mono/Inspector/AudioChorusFilterEditor.cs delete mode 100644 Editor/Mono/Inspector/AudioClipInspector.cs delete mode 100644 Editor/Mono/Inspector/AudioDistortionFilterInspector.cs delete mode 100644 Editor/Mono/Inspector/AudioEchoFilterInspector.cs delete mode 100644 Editor/Mono/Inspector/AudioExtensionEditor.cs delete mode 100644 Editor/Mono/Inspector/AudioFilterGUI.cs delete mode 100644 Editor/Mono/Inspector/AudioHighPassFIlterInspector.cs delete mode 100644 Editor/Mono/Inspector/AudioListenerExtensionEditor.cs delete mode 100644 Editor/Mono/Inspector/AudioListenerInspector.cs delete mode 100644 Editor/Mono/Inspector/AudioLowPassFilterInspector.cs delete mode 100644 Editor/Mono/Inspector/AudioManagerInspector.cs delete mode 100644 Editor/Mono/Inspector/AudioMixerControllerInspector.cs delete mode 100644 Editor/Mono/Inspector/AudioMixerGroupEditor.cs delete mode 100644 Editor/Mono/Inspector/AudioReverbFilterEditor.cs delete mode 100644 Editor/Mono/Inspector/AudioReverbZoneEditor.cs delete mode 100644 Editor/Mono/Inspector/AudioSourceExtensionEditor.cs delete mode 100644 Editor/Mono/Inspector/AudioSourceInspector.cs delete mode 100644 Editor/Mono/Inspector/Avatar/AvatarAutoMapper.cs delete mode 100644 Editor/Mono/Inspector/Avatar/AvatarBipedMapper.cs delete mode 100644 Editor/Mono/Inspector/Avatar/AvatarColliderEditor.cs delete mode 100644 Editor/Mono/Inspector/Avatar/AvatarControl.cs delete mode 100644 Editor/Mono/Inspector/Avatar/AvatarEditor.cs delete mode 100644 Editor/Mono/Inspector/Avatar/AvatarHandleEditor.cs delete mode 100644 Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs delete mode 100644 Editor/Mono/Inspector/Avatar/AvatarMuscleEditor.cs delete mode 100644 Editor/Mono/Inspector/Avatar/AvatarSetupTool.cs delete mode 100644 Editor/Mono/Inspector/Avatar/AvatarSkeletonDrawer.cs delete mode 100644 Editor/Mono/Inspector/AvatarMaskInspector.cs delete mode 100644 Editor/Mono/Inspector/AvatarMaskUtility.cs delete mode 100644 Editor/Mono/Inspector/AvatarPreview.cs delete mode 100644 Editor/Mono/Inspector/AvatarPreviewSelection.cs delete mode 100644 Editor/Mono/Inspector/BillboardAssetInspector.cs delete mode 100644 Editor/Mono/Inspector/BillboardRendererInspector.cs delete mode 100644 Editor/Mono/Inspector/BlendTreeInspector.cs delete mode 100644 Editor/Mono/Inspector/BoxCollider2DEditor.cs delete mode 100644 Editor/Mono/Inspector/BoxColliderEditor.cs delete mode 100644 Editor/Mono/Inspector/BuoyancyEffector2DEditor.cs delete mode 100644 Editor/Mono/Inspector/CameraEditor.cs delete mode 100644 Editor/Mono/Inspector/CanvasEditor.cs delete mode 100644 Editor/Mono/Inspector/CapsuleCollider2DEditor.cs delete mode 100644 Editor/Mono/Inspector/CapsuleColliderEditor.cs delete mode 100644 Editor/Mono/Inspector/CharacterControllerEditor.cs delete mode 100644 Editor/Mono/Inspector/CharacterJointEditor.cs delete mode 100644 Editor/Mono/Inspector/CircleCollider2DEditor.cs delete mode 100644 Editor/Mono/Inspector/ClothInspector.cs delete mode 100644 Editor/Mono/Inspector/Collider2DEditorBase.cs delete mode 100644 Editor/Mono/Inspector/Collider3DEditorBase.cs delete mode 100644 Editor/Mono/Inspector/ColliderEditorBase.cs delete mode 100644 Editor/Mono/Inspector/ColliderEditorUtility.cs delete mode 100644 Editor/Mono/Inspector/ColorPresetLibraryInspector.cs delete mode 100644 Editor/Mono/Inspector/CompositeCollider2DEditor.cs delete mode 100644 Editor/Mono/Inspector/ComputeShaderInspector.cs delete mode 100644 Editor/Mono/Inspector/ConfigurableJointEditor.cs delete mode 100644 Editor/Mono/Inspector/ConstraintEditorBase.cs delete mode 100644 Editor/Mono/Inspector/CubemapInspector.cs delete mode 100644 Editor/Mono/Inspector/CubemapPreview.cs delete mode 100644 Editor/Mono/Inspector/CurvePresetLibraryInspector.cs delete mode 100644 Editor/Mono/Inspector/CustomPreviewAttribute.cs delete mode 100644 Editor/Mono/Inspector/CustomRenderTextureEditor.cs delete mode 100644 Editor/Mono/Inspector/DirectorEditor.cs delete mode 100644 Editor/Mono/Inspector/DistanceJoint2DEditor.cs delete mode 100644 Editor/Mono/Inspector/DoubleCurvePresetLibraryInspector.cs delete mode 100644 Editor/Mono/Inspector/EdgeCollider2DEditor.cs delete mode 100644 Editor/Mono/Inspector/EditMode.cs delete mode 100644 Editor/Mono/Inspector/Editor.cs delete mode 100644 Editor/Mono/Inspector/EditorDragging.cs delete mode 100644 Editor/Mono/Inspector/EditorSettingsInspector.cs delete mode 100644 Editor/Mono/Inspector/Effector2DEditor.cs delete mode 100644 Editor/Mono/Inspector/Enlighten/LightmapParameters.cs delete mode 100644 Editor/Mono/Inspector/FontInspector.cs delete mode 100644 Editor/Mono/Inspector/GameObjectInspector.cs delete mode 100644 Editor/Mono/Inspector/GenericInspector.cs delete mode 100644 Editor/Mono/Inspector/GenericPresetLibraryInspector.cs delete mode 100644 Editor/Mono/Inspector/GradientPresetLibraryInspector.cs delete mode 100644 Editor/Mono/Inspector/GraphicsSettingsInspector.cs delete mode 100644 Editor/Mono/Inspector/HingeJoint2DEditor.cs delete mode 100644 Editor/Mono/Inspector/HingeJointEditor.cs delete mode 100644 Editor/Mono/Inspector/InspectorWindow.cs delete mode 100644 Editor/Mono/Inspector/Joint2DEditor.cs delete mode 100644 Editor/Mono/Inspector/JointEditor.cs delete mode 100644 Editor/Mono/Inspector/LODGroupEditor.cs delete mode 100644 Editor/Mono/Inspector/LODGroupGUI.cs delete mode 100644 Editor/Mono/Inspector/LabelGUI.cs delete mode 100644 Editor/Mono/Inspector/LayoutDropdownWindow.cs delete mode 100644 Editor/Mono/Inspector/LegacyIlluminShaderGUI.cs delete mode 100644 Editor/Mono/Inspector/LightEditor.cs delete mode 100644 Editor/Mono/Inspector/LightProbeGroupInspector.cs delete mode 100644 Editor/Mono/Inspector/LightProbeProxyVolumeEditor.cs delete mode 100644 Editor/Mono/Inspector/LightProbesInspector.cs delete mode 100644 Editor/Mono/Inspector/LightingSettingsInspector.cs delete mode 100644 Editor/Mono/Inspector/LineRendererCurveEditor.cs delete mode 100644 Editor/Mono/Inspector/LineRendererInspector.cs delete mode 100644 Editor/Mono/Inspector/MaterialEditor.cs delete mode 100644 Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs delete mode 100644 Editor/Mono/Inspector/MaterialPropertyDrawer.cs delete mode 100644 Editor/Mono/Inspector/MeshColliderEditor.cs delete mode 100644 Editor/Mono/Inspector/MeshRendererEditor.cs delete mode 100644 Editor/Mono/Inspector/ModelInspector.cs delete mode 100644 Editor/Mono/Inspector/MonoScriptInspector.cs delete mode 100644 Editor/Mono/Inspector/MovieTextureInspector.cs delete mode 100644 Editor/Mono/Inspector/NavMeshAgentInspector.cs delete mode 100644 Editor/Mono/Inspector/NavMeshEditorHelpers.cs delete mode 100644 Editor/Mono/Inspector/NavMeshObstacleInspector.cs delete mode 100644 Editor/Mono/Inspector/OcclusionAreaEditor.cs delete mode 100644 Editor/Mono/Inspector/OcclusionPortalEditor.cs delete mode 100644 Editor/Mono/Inspector/OffMeshLinkInspector.cs delete mode 100644 Editor/Mono/Inspector/ParentConstraintEditor.cs delete mode 100644 Editor/Mono/Inspector/Physics2DSettingsInspector.cs delete mode 100644 Editor/Mono/Inspector/PhysicsManagerInspector.cs delete mode 100644 Editor/Mono/Inspector/PlatformEffector2DEditor.cs delete mode 100644 Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs delete mode 100644 Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.bindings.cs delete mode 100644 Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.cs delete mode 100644 Editor/Mono/Inspector/PlayerSettingsEditor/WebTemplate.cs delete mode 100644 Editor/Mono/Inspector/PlayerSettingsEditor/WebTemplateManagerBase.cs delete mode 100644 Editor/Mono/Inspector/PointEffector2DEditor.cs delete mode 100644 Editor/Mono/Inspector/PolygonCollider2DEditor.cs delete mode 100644 Editor/Mono/Inspector/PolygonEditorUtility.cs delete mode 100644 Editor/Mono/Inspector/PositionConstraintEditor.cs delete mode 100644 Editor/Mono/Inspector/PrefabInspector.cs delete mode 100644 Editor/Mono/Inspector/PreviewRenderUtility.cs delete mode 100644 Editor/Mono/Inspector/PreviewWindow.cs delete mode 100644 Editor/Mono/Inspector/PrimitiveCollider2DEditor.cs delete mode 100644 Editor/Mono/Inspector/PrimitiveCollider3DEditor.cs delete mode 100644 Editor/Mono/Inspector/ProjectSettingsBaseEditor.cs delete mode 100644 Editor/Mono/Inspector/PropertyDrawerCache.cs delete mode 100644 Editor/Mono/Inspector/QualitySettingsEditor.cs delete mode 100644 Editor/Mono/Inspector/RectHandles.cs delete mode 100644 Editor/Mono/Inspector/RectTransformEditor.cs delete mode 100644 Editor/Mono/Inspector/RectTransformSnapping.cs delete mode 100644 Editor/Mono/Inspector/ReflectionProbeEditor.cs delete mode 100644 Editor/Mono/Inspector/RelativeJoint2DEditor.cs delete mode 100644 Editor/Mono/Inspector/RenderSettingsInspector.cs delete mode 100644 Editor/Mono/Inspector/RenderTextureEditor.cs delete mode 100644 Editor/Mono/Inspector/RendererEditorBase.cs delete mode 100644 Editor/Mono/Inspector/Rigidbody2DEditor.cs delete mode 100644 Editor/Mono/Inspector/RigidbodyEditor.cs delete mode 100644 Editor/Mono/Inspector/RotationConstraintEditor.cs delete mode 100644 Editor/Mono/Inspector/ScaleConstraintEditor.cs delete mode 100644 Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs delete mode 100644 Editor/Mono/Inspector/ShaderGUI.cs delete mode 100644 Editor/Mono/Inspector/ShaderImporterInspector.cs delete mode 100644 Editor/Mono/Inspector/ShaderIncludePathAttribute.cs delete mode 100644 Editor/Mono/Inspector/ShaderInspector.cs delete mode 100644 Editor/Mono/Inspector/ShaderVariantCollectionInspector.cs delete mode 100644 Editor/Mono/Inspector/ShadowCascadeSplitGUI.cs delete mode 100644 Editor/Mono/Inspector/SkinnedMeshRendererEditor.cs delete mode 100644 Editor/Mono/Inspector/SkyboxPanoramicShaderGUI.cs delete mode 100644 Editor/Mono/Inspector/SkyboxProceduralShaderGUI.cs delete mode 100644 Editor/Mono/Inspector/SliderJoint2DEditor.cs delete mode 100644 Editor/Mono/Inspector/SortingGroupEditor.cs delete mode 100644 Editor/Mono/Inspector/SortingLayerEditorUtility.cs delete mode 100644 Editor/Mono/Inspector/SpeedTreeMaterialInspector.cs delete mode 100644 Editor/Mono/Inspector/SphereColliderEditor.cs delete mode 100644 Editor/Mono/Inspector/SpringJoint2DEditor.cs delete mode 100644 Editor/Mono/Inspector/SpriteFrameInspector.cs delete mode 100644 Editor/Mono/Inspector/SpriteRendererEditor.cs delete mode 100644 Editor/Mono/Inspector/StandardParticlesShaderGUI.cs delete mode 100644 Editor/Mono/Inspector/StandardRoughnessShaderGUI.cs delete mode 100644 Editor/Mono/Inspector/StandardShaderGUI.cs delete mode 100644 Editor/Mono/Inspector/SurfaceEffector2DEditor.cs delete mode 100644 Editor/Mono/Inspector/TabbedEditor.cs delete mode 100644 Editor/Mono/Inspector/TagManagerInspector.cs delete mode 100644 Editor/Mono/Inspector/TargetJoint2DEditor.cs delete mode 100644 Editor/Mono/Inspector/TerrainColliderEditor.cs delete mode 100644 Editor/Mono/Inspector/TextMeshInspector.cs delete mode 100644 Editor/Mono/Inspector/Texture3DInspector.cs delete mode 100644 Editor/Mono/Inspector/TextureInspector.cs delete mode 100644 Editor/Mono/Inspector/TimeControl.cs delete mode 100644 Editor/Mono/Inspector/TimeManagerInspector.cs delete mode 100644 Editor/Mono/Inspector/TimelineControl.cs delete mode 100644 Editor/Mono/Inspector/TrailRendererInspector.cs delete mode 100644 Editor/Mono/Inspector/TransformInspector.cs delete mode 100644 Editor/Mono/Inspector/TransformRotationGUI.cs delete mode 100644 Editor/Mono/Inspector/TransformUtils.cs delete mode 100644 Editor/Mono/Inspector/UNetBehaviourInspector.cs delete mode 100644 Editor/Mono/Inspector/UnityEventDrawer.cs delete mode 100644 Editor/Mono/Inspector/VideoClipInspector.cs delete mode 100644 Editor/Mono/Inspector/VideoPlayerEditor.cs delete mode 100644 Editor/Mono/Inspector/WebCamTextureInspector.cs delete mode 100644 Editor/Mono/Inspector/WheelColliderEditor.cs delete mode 100644 Editor/Mono/Inspector/WheelJoint2DEditor.cs delete mode 100644 Editor/Mono/Inspector/WindInspector.cs delete mode 100644 Editor/Mono/Internal/MonoScripts.cs delete mode 100644 Editor/Mono/InternalEditorUtility.cs delete mode 100644 Editor/Mono/JSProxy/ClipboardAccess.cs delete mode 100644 Editor/Mono/JSProxy/JSProxyMgr.cs delete mode 100644 Editor/Mono/JSProxy/PreviewGenerator.cs delete mode 100644 Editor/Mono/JSProxy/TroubleshooterAccess.cs delete mode 100644 Editor/Mono/JSProxy/WebScriptObject.cs delete mode 100644 Editor/Mono/LicenseManagementWindow.cs delete mode 100644 Editor/Mono/Localization/LocalizationDatabase.bindings.cs delete mode 100644 Editor/Mono/Localization/LocalizationDatabase.cs delete mode 100644 Editor/Mono/Localization/LocalizedEditorFontManager.cs delete mode 100644 Editor/Mono/LogEntries.bindings.cs delete mode 100644 Editor/Mono/LookDevView/CameraController.cs delete mode 100644 Editor/Mono/LookDevView/CameraControllerStandard.cs delete mode 100644 Editor/Mono/LookDevView/CameraState.cs delete mode 100644 Editor/Mono/LookDevView/LookDevConfig.cs delete mode 100644 Editor/Mono/LookDevView/LookDevContext.cs delete mode 100644 Editor/Mono/LookDevView/LookDevEnvironmentLibrary.cs delete mode 100644 Editor/Mono/LookDevView/LookDevEnvironmentWindow.cs delete mode 100644 Editor/Mono/LookDevView/LookDevInc.cs delete mode 100644 Editor/Mono/LookDevView/LookDevSettingsWindow.cs delete mode 100644 Editor/Mono/LookDevView/LookDevView.cs delete mode 100644 Editor/Mono/LookDevView/LookDevViewsWindow.cs delete mode 100644 Editor/Mono/Macros/MacroEvaluator.cs delete mode 100644 Editor/Mono/Macros/MethodEvaluator.cs delete mode 100644 Editor/Mono/MaterialProperty.cs delete mode 100644 Editor/Mono/Media/Bindings/MediaEncoder.bindings.cs delete mode 100644 Editor/Mono/Menu.bindings.cs delete mode 100644 Editor/Mono/MenuCommand.cs delete mode 100644 Editor/Mono/MenuItem.cs delete mode 100644 Editor/Mono/Modules/DefaultBuildPostprocessor.cs delete mode 100644 Editor/Mono/Modules/DefaultBuildWindowExtension.cs delete mode 100644 Editor/Mono/Modules/DefaultCompilationExtension.cs delete mode 100644 Editor/Mono/Modules/DefaultPlatformSupportModule.cs delete mode 100644 Editor/Mono/Modules/DefaultPlayerSettingsEditorExtension.cs delete mode 100644 Editor/Mono/Modules/DefaultPluginImporterExtension.cs delete mode 100644 Editor/Mono/Modules/DefaultProjectGeneratorExtension.cs delete mode 100644 Editor/Mono/Modules/DefaultTextureImportSettingsExtension.cs delete mode 100644 Editor/Mono/Modules/ModuleManager.cs delete mode 100644 Editor/Mono/Modules/PlatformSupportModule.cs delete mode 100644 Editor/Mono/MonoScript.bindings.cs delete mode 100644 Editor/Mono/MuscleClipUtility.bindings.cs delete mode 100644 Editor/Mono/Networking/PlayerConnection/EditorConnection.cs delete mode 100644 Editor/Mono/NumericFieldDraggerUtility.cs delete mode 100644 Editor/Mono/ObjectFactory.bindings.cs delete mode 100644 Editor/Mono/ObjectListArea.cs delete mode 100644 Editor/Mono/ObjectListAssetStoreGroup.cs delete mode 100644 Editor/Mono/ObjectListGroup.cs delete mode 100644 Editor/Mono/ObjectListLocalGroup.cs delete mode 100644 Editor/Mono/ObjectNames.cs delete mode 100644 Editor/Mono/ObjectSelector.cs delete mode 100644 Editor/Mono/ObjectTreeForSelector.cs delete mode 100644 Editor/Mono/PackageUtility.bindings.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleEffectUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleRendererEditor.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemClipboard.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemCurveEditor.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemEditor.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ClampVelocityModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/CollisionModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ColorByVelocityModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ColorModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/CustomDataModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/EmissionModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ExternalForcesModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ForceModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InheritVelocityModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/LightsModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ModuleUIHelpers.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/NoiseModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RotationByVelocityModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RotationModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SerializedModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ShapeModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SizeByVelocityModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SizeModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SubModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TriggerModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/UVModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemModules/VelocityModuleUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemStyles.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ParticleSystemWindow.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/ScriptBindings/ParticleSystemEditor.bindings.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/SerializedMinMaxColor.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/SerializedMinMaxCurve.cs delete mode 100644 Editor/Mono/ParticleSystemEditor/SerializedMinMaxGradient.cs delete mode 100644 Editor/Mono/PerceptionRemoting/HolographicEmulation/HolographicEmulationWindow.cs delete mode 100644 Editor/Mono/PerformanceTools/FrameDebugger.cs delete mode 100644 Editor/Mono/PerformanceTools/FrameDebuggerTreeView.cs delete mode 100644 Editor/Mono/PlatformSupport/PlatformIconField.cs delete mode 100644 Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs delete mode 100644 Editor/Mono/PlatformSupport/ReorderableTextureList.cs delete mode 100644 Editor/Mono/Playables/Playables.bindings.cs delete mode 100644 Editor/Mono/PlayerConnectionLogReceiver.cs delete mode 100644 Editor/Mono/PlayerSettings.deprecated.cs delete mode 100644 Editor/Mono/PlayerSettingsIOS.bindings.cs delete mode 100644 Editor/Mono/PlayerSettingsMacOS.bindings.cs delete mode 100644 Editor/Mono/PlayerSettingsPS4.bindings.cs delete mode 100644 Editor/Mono/PlayerSettingsPSVita.bindings.cs delete mode 100644 Editor/Mono/PlayerSettingsSplashScreen.cs delete mode 100644 Editor/Mono/PlayerSettingsTVOS.bindings.cs delete mode 100644 Editor/Mono/PlayerSettingsTizen.bindings.cs delete mode 100644 Editor/Mono/PlayerSettingsWSA.cs delete mode 100644 Editor/Mono/PlayerSettingsXboxOne.bindings.cs delete mode 100644 Editor/Mono/PluginDesc.cs delete mode 100644 Editor/Mono/PluginImporter.bindings.cs delete mode 100644 Editor/Mono/Plugins/PluginsHelper.cs delete mode 100644 Editor/Mono/PointEditor.cs delete mode 100644 Editor/Mono/PostprocessScene.cs delete mode 100644 Editor/Mono/PreferencesWindow/CacheServerPreferences.cs delete mode 100644 Editor/Mono/PreferencesWindow/DiagnosticsSwitchPreferences.cs delete mode 100644 Editor/Mono/PreferencesWindow/PreferencesWindow.cs delete mode 100644 Editor/Mono/PresetLibraries/ColorPresetLibrary.cs delete mode 100644 Editor/Mono/PresetLibraries/CurvePresetLibrary.cs delete mode 100644 Editor/Mono/PresetLibraries/CurvePresetsContentsForPopupWindow.cs delete mode 100644 Editor/Mono/PresetLibraries/DoubleCurvePresetLibrary.cs delete mode 100644 Editor/Mono/PresetLibraries/DoubleCurvePresetsContentsForPopupWindow.cs delete mode 100644 Editor/Mono/PresetLibraries/GradientPresetLibrary.cs delete mode 100644 Editor/Mono/PresetLibraries/PopupWindowContentForNewLibrary.cs delete mode 100644 Editor/Mono/PresetLibraries/PresetLibrary.cs delete mode 100644 Editor/Mono/PresetLibraries/PresetLibraryEditor.cs delete mode 100644 Editor/Mono/PresetLibraries/PresetLibraryEditorMenu.cs delete mode 100644 Editor/Mono/PresetLibraries/PresetLibraryManager.cs delete mode 100644 Editor/Mono/PresetLibraries/ScriptableObjectSaveLoadHelper.cs delete mode 100644 Editor/Mono/ProjectBrowser.cs delete mode 100644 Editor/Mono/ProjectBrowser/SavedSearchFilter.cs delete mode 100644 Editor/Mono/ProjectBrowserColumnOne.cs delete mode 100644 Editor/Mono/ProjectBrowserPopups.cs delete mode 100644 Editor/Mono/ProjectTemplateWindow.cs delete mode 100644 Editor/Mono/ProjectWindow/CachedFilteredHierachy.cs delete mode 100644 Editor/Mono/ProjectWindow/ProjectWindowUtil.cs delete mode 100644 Editor/Mono/ProjectWindow/SearchFilter.cs delete mode 100644 Editor/Mono/ProjectWindow/SearchableEditorWindow.cs delete mode 100644 Editor/Mono/ProvisioningProfile.cs delete mode 100644 Editor/Mono/ProvisioningProfileGUI.cs delete mode 100644 Editor/Mono/RagdollBuilder.cs delete mode 100644 Editor/Mono/RetainedMode.cs delete mode 100644 Editor/Mono/RuntimeInitializeOnLoadManager.bindings.cs delete mode 100644 Editor/Mono/SceneHierarchySortingWindow.cs delete mode 100644 Editor/Mono/SceneHierarchyWindow.cs delete mode 100644 Editor/Mono/SceneManagement/EditorSceneManager.cs delete mode 100644 Editor/Mono/SceneManagement/SceneSetup.cs delete mode 100644 Editor/Mono/SceneModeWindows/LightTable.cs delete mode 100644 Editor/Mono/SceneModeWindows/LightingExplorerWindow.cs delete mode 100644 Editor/Mono/SceneModeWindows/LightingExplorerWindowTableTab.cs delete mode 100644 Editor/Mono/SceneModeWindows/LightingWindow.cs delete mode 100644 Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs delete mode 100644 Editor/Mono/SceneModeWindows/LightingWindowLightingTab.cs delete mode 100644 Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs delete mode 100644 Editor/Mono/SceneModeWindows/LightingWindowObjectTab.cs delete mode 100644 Editor/Mono/SceneModeWindows/NavigationWindow.cs delete mode 100644 Editor/Mono/SceneModeWindows/OcclusionCullingWindow.cs delete mode 100644 Editor/Mono/SceneModeWindows/PhysicsDebugWindow.cs delete mode 100644 Editor/Mono/SceneModeWindows/SceneModeUtility.cs delete mode 100644 Editor/Mono/SceneModeWindows/TierSettingsWindow.cs delete mode 100644 Editor/Mono/SceneView/RectSelection.cs delete mode 100644 Editor/Mono/SceneView/SceneView.cs delete mode 100644 Editor/Mono/SceneView/SceneViewGrid.cs delete mode 100644 Editor/Mono/SceneView/SceneViewMotion.cs delete mode 100644 Editor/Mono/SceneView/SceneViewOverlay.cs delete mode 100644 Editor/Mono/SceneView/SceneViewPicking.cs delete mode 100644 Editor/Mono/ScriptAttributeGUI/CustomPropertyDrawerAttribute.cs delete mode 100644 Editor/Mono/ScriptAttributeGUI/DecoratorDrawer.cs delete mode 100644 Editor/Mono/ScriptAttributeGUI/GUIDrawer.cs delete mode 100644 Editor/Mono/ScriptAttributeGUI/Implementations/DecoratorDrawers.cs delete mode 100644 Editor/Mono/ScriptAttributeGUI/Implementations/ExposedReferenceDrawer.cs delete mode 100644 Editor/Mono/ScriptAttributeGUI/Implementations/PropertyDrawers.cs delete mode 100644 Editor/Mono/ScriptAttributeGUI/PropertyDrawer.cs delete mode 100644 Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs delete mode 100644 Editor/Mono/ScriptAttributeGUI/ScriptAttributeUtility.cs delete mode 100644 Editor/Mono/ScriptEditorUtility.cs delete mode 100644 Editor/Mono/ScriptableSingleton.cs delete mode 100644 Editor/Mono/ScriptableSingletonDictionary.cs delete mode 100644 Editor/Mono/Scripting/APIUpdaterHelper.cs delete mode 100644 Editor/Mono/Scripting/APIUpdaterLogger.cs delete mode 100644 Editor/Mono/Scripting/Compilers/APIUpdater.cs delete mode 100644 Editor/Mono/Scripting/Compilers/BooCompiler.cs delete mode 100644 Editor/Mono/Scripting/Compilers/BooCompilerOutputParser.cs delete mode 100644 Editor/Mono/Scripting/Compilers/BooLanguage.cs delete mode 100644 Editor/Mono/Scripting/Compilers/CSharpLanguage.cs delete mode 100644 Editor/Mono/Scripting/Compilers/Cil2AsOutputParser.cs delete mode 100644 Editor/Mono/Scripting/Compilers/CommandLineFormatter.cs delete mode 100644 Editor/Mono/Scripting/Compilers/CompilerOutputParserBase.cs delete mode 100644 Editor/Mono/Scripting/Compilers/GendarmeOutputParser.cs delete mode 100644 Editor/Mono/Scripting/Compilers/Il2CppOutputParser.cs delete mode 100644 Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs delete mode 100644 Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompilerOutputParser.cs delete mode 100644 Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs delete mode 100644 Editor/Mono/Scripting/Compilers/MonoCSharpCompilerOutputParser.cs delete mode 100644 Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs delete mode 100644 Editor/Mono/Scripting/Compilers/NuGetPackageResolver.cs delete mode 100644 Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs delete mode 100644 Editor/Mono/Scripting/Compilers/SupportedLanguage.cs delete mode 100644 Editor/Mono/Scripting/Compilers/UWPReferences.cs delete mode 100644 Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs delete mode 100644 Editor/Mono/Scripting/Compilers/UnityScriptCompilerOutputParser.cs delete mode 100644 Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs delete mode 100644 Editor/Mono/Scripting/PragmaFixing30.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/AssemblyDefinitionException.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/AssemblyFlags.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/AssetPath.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/CompilerMessage.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/OptionalUnityReferences.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/PrecompiledAssembly.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs delete mode 100644 Editor/Mono/Scripting/ScriptCompilers.cs delete mode 100644 Editor/Mono/Scripting/ScriptUpdatingManager.bindings.cs delete mode 100644 Editor/Mono/Scripting/Serialization/Weaver.cs delete mode 100644 Editor/Mono/SearchUtility.cs delete mode 100644 Editor/Mono/Selection.bindings.cs delete mode 100644 Editor/Mono/Selection.cs delete mode 100644 Editor/Mono/SerializedObject.cs delete mode 100644 Editor/Mono/SerializedProperty.cs delete mode 100644 Editor/Mono/SerializedProperty/SerializedPropertyFilters.cs delete mode 100644 Editor/Mono/SerializedProperty/SerializedPropertyTable.cs delete mode 100644 Editor/Mono/SerializedProperty/SerializedPropertyTreeView.cs delete mode 100644 Editor/Mono/Settings.cs delete mode 100644 Editor/Mono/SettingsWindow/FogEditor.cs delete mode 100644 Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs delete mode 100644 Editor/Mono/SettingsWindow/LightingEditor.cs delete mode 100644 Editor/Mono/SettingsWindow/OtherRenderingEditor.cs delete mode 100644 Editor/Mono/ShaderUtil.bindings.cs delete mode 100644 Editor/Mono/ShapeEditor/ShapeEditor.cs delete mode 100644 Editor/Mono/ShapeEditor/ShapeEditorRectSelection.cs delete mode 100644 Editor/Mono/SplashScreenLogo.cs delete mode 100644 Editor/Mono/SpriteEditor/SpriteEditorHandles.cs delete mode 100644 Editor/Mono/SpriteEditor/SpriteEditorMenu.cs delete mode 100644 Editor/Mono/SpriteEditor/SpriteEditorUtility.cs delete mode 100644 Editor/Mono/SpriteEditor/SpriteEditorWindow.cs delete mode 100644 Editor/Mono/SpriteEditor/SpriteRect.cs delete mode 100644 Editor/Mono/SpritePacker.bindings.cs delete mode 100644 Editor/Mono/Sprites/DefaultSpritePackerPolicy.cs delete mode 100644 Editor/Mono/Sprites/SpritePacker.cs delete mode 100644 Editor/Mono/Sprites/SpritePackerWindow.cs delete mode 100644 Editor/Mono/Sprites/SpriteUtility.cs delete mode 100644 Editor/Mono/Sprites/SpriteUtilityWindow.cs delete mode 100644 Editor/Mono/Sprites/TightRotateEnabledSpritePackerPolicy.cs delete mode 100644 Editor/Mono/Sprites/TightSpritePackerPolicy.cs delete mode 100644 Editor/Mono/StateMachine.bindings.cs delete mode 100644 Editor/Mono/StateMachineBehaviourContext.bindings.cs delete mode 100644 Editor/Mono/StaticEditorFlags.cs delete mode 100644 Editor/Mono/StyleSheets/CSSSpec.cs delete mode 100644 Editor/Mono/StyleSheets/StyleSheetAssetPostProcessor.cs delete mode 100644 Editor/Mono/StyleSheets/StyleSheetBuilder.cs delete mode 100644 Editor/Mono/StyleSheets/StyleSheetEditor.cs delete mode 100644 Editor/Mono/StyleSheets/StyleSheetImportErrors.cs delete mode 100644 Editor/Mono/StyleSheets/StyleSheetImporter.cs delete mode 100644 Editor/Mono/StyleSheets/StyleSheetImporterImpl.cs delete mode 100644 Editor/Mono/StyleSheets/StyleSheetResourceUtil.cs delete mode 100644 Editor/Mono/SyncProject.cs delete mode 100644 Editor/Mono/TerrainEditor/Brush.cs delete mode 100644 Editor/Mono/TerrainEditor/HeightmapFilters.cs delete mode 100644 Editor/Mono/TerrainEditor/TerrainEditorUtility.cs delete mode 100644 Editor/Mono/TerrainEditor/TerrainInspector.cs delete mode 100644 Editor/Mono/TerrainEditor/TerrainMenus.cs delete mode 100644 Editor/Mono/TerrainEditor/TerrainSplatEditor.cs delete mode 100644 Editor/Mono/TerrainEditor/TerrainWizards.cs delete mode 100644 Editor/Mono/TerrainEditor/TreeAOImporter.cs delete mode 100644 Editor/Mono/TooltipView/TooltipView.cs delete mode 100644 Editor/Mono/Troubleshooter/TroubleshooterWindow.cs delete mode 100644 Editor/Mono/Tutorial/Highlighter.cs delete mode 100644 Editor/Mono/TypeSystem/UnityType.bindings.cs delete mode 100644 Editor/Mono/TypeSystem/UnityType.cs delete mode 100644 Editor/Mono/UIElements/Controls/BaseCompositeField.cs delete mode 100644 Editor/Mono/UIElements/Controls/BaseValueField.cs delete mode 100644 Editor/Mono/UIElements/Controls/BoundsField.cs delete mode 100644 Editor/Mono/UIElements/Controls/ColorField.cs delete mode 100644 Editor/Mono/UIElements/Controls/CompoundFields.cs delete mode 100644 Editor/Mono/UIElements/Controls/CurveField.cs delete mode 100644 Editor/Mono/UIElements/Controls/DoubleField.cs delete mode 100644 Editor/Mono/UIElements/Controls/EnumField.cs delete mode 100644 Editor/Mono/UIElements/Controls/GradientField.cs delete mode 100644 Editor/Mono/UIElements/Controls/IntegerField.cs delete mode 100644 Editor/Mono/UIElements/Controls/ObjectField.cs delete mode 100644 Editor/Mono/UIElements/Controls/PopupField.cs delete mode 100644 Editor/Mono/UIElements/Controls/TextValueField.cs delete mode 100644 Editor/Mono/UIElements/Controls/UXMLEditorFactories.cs delete mode 100644 Editor/Mono/UIElements/EditorContextualMenuManager.cs delete mode 100644 Editor/Mono/UIElements/EditorCursor.cs delete mode 100644 Editor/Mono/UIElements/EditorWindowPersistentViewData.cs delete mode 100644 Editor/Mono/UIElements/Events/TooltipEvent.cs delete mode 100644 Editor/Mono/UIElements/FieldMouseDragger.cs delete mode 100644 Editor/Mono/UIElements/SerializableJsonDictionary.cs delete mode 100644 Editor/Mono/UIElements/Tooltip.cs delete mode 100644 Editor/Mono/UIElements/UIElementsEditorUtility.cs delete mode 100644 Editor/Mono/UIElements/UIElementsViewImporter.cs delete mode 100644 Editor/Mono/UIElements/VisualTreeAssetEditor.cs delete mode 100644 Editor/Mono/Undo/UndoWindow.cs delete mode 100644 Editor/Mono/UnityConnect/CloudProjectSettings.cs delete mode 100644 Editor/Mono/UnityConnect/Services/AdsAccess.cs delete mode 100644 Editor/Mono/UnityConnect/Services/AnalyticsAccess.cs delete mode 100644 Editor/Mono/UnityConnect/Services/BuildAccess.cs delete mode 100644 Editor/Mono/UnityConnect/Services/CloudServiceAccess.cs delete mode 100644 Editor/Mono/UnityConnect/Services/CollabAccess.cs delete mode 100644 Editor/Mono/UnityConnect/Services/CrashReportingAccess.cs delete mode 100644 Editor/Mono/UnityConnect/Services/EditorProjectAccess.bindings.cs delete mode 100644 Editor/Mono/UnityConnect/Services/EditorProjectAccess.cs delete mode 100644 Editor/Mono/UnityConnect/Services/ErrorHubAccess.cs delete mode 100644 Editor/Mono/UnityConnect/Services/HubAccess.cs delete mode 100644 Editor/Mono/UnityConnect/Services/PurchasingAccess.cs delete mode 100644 Editor/Mono/UnityConnect/Services/UnetAccess.cs delete mode 100644 Editor/Mono/UnityConnect/UnityConnect.cs delete mode 100644 Editor/Mono/UnityConnect/UnityConnectConsentView.cs delete mode 100644 Editor/Mono/UnityConnect/UnityConnectEditorWindow.cs delete mode 100644 Editor/Mono/UnityConnect/UnityConnectPrefs.cs delete mode 100644 Editor/Mono/UnityConnect/UnityConnectServiceCollection.cs delete mode 100644 Editor/Mono/UnityConnect/UnityConnectServiceData.cs delete mode 100644 Editor/Mono/Utils/AssemblyReferenceChecker.cs delete mode 100644 Editor/Mono/Utils/EditorExtensionMethods.cs delete mode 100644 Editor/Mono/Utils/ExpressionEvaluator.cs delete mode 100644 Editor/Mono/Utils/IDeviceUtils.cs delete mode 100644 Editor/Mono/Utils/LightProbeGroupSelection.cs delete mode 100644 Editor/Mono/Utils/ManagedProgram.cs delete mode 100644 Editor/Mono/Utils/MathUtils.cs delete mode 100644 Editor/Mono/Utils/MenuUtils.cs delete mode 100644 Editor/Mono/Utils/MetroCertificatePasswordWindow.cs delete mode 100644 Editor/Mono/Utils/MetroCreateTestCertificateWindow.cs delete mode 100644 Editor/Mono/Utils/MonoInstallationFinder.cs delete mode 100644 Editor/Mono/Utils/NetCoreProgram.cs delete mode 100644 Editor/Mono/Utils/NetStandardFinder.cs delete mode 100644 Editor/Mono/Utils/Paths.cs delete mode 100644 Editor/Mono/Utils/PerformanceChecks.cs delete mode 100644 Editor/Mono/Utils/ProcessOutputStreamReader.cs delete mode 100644 Editor/Mono/Utils/Program.cs delete mode 100644 Editor/Mono/Utils/ProgressBarUtils.cs delete mode 100644 Editor/Mono/Utils/SimpleProfiler.cs delete mode 100644 Editor/Mono/Utils/TickTimerHelper.cs delete mode 100644 Editor/Mono/Utils/TimeAgo.cs delete mode 100644 Editor/Mono/Utils/TimeHelper.cs delete mode 100644 Editor/Mono/Utils/UnityEventTools.cs delete mode 100644 Editor/Mono/VersionControl/Common/VCAsset.cs delete mode 100644 Editor/Mono/VersionControl/Common/VCAssetList.cs delete mode 100644 Editor/Mono/VersionControl/Common/VCAssetModificationHooks.cs delete mode 100644 Editor/Mono/VersionControl/Common/VCChangeSet.cs delete mode 100644 Editor/Mono/VersionControl/Common/VCChangeSets.cs delete mode 100644 Editor/Mono/VersionControl/Common/VCMessage.cs delete mode 100644 Editor/Mono/VersionControl/Common/VCProvider.cs delete mode 100644 Editor/Mono/VersionControl/Common/VCTask.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCListControl.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCListItem.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCMenuChange.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCMenuPending.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCMenuProject.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCOverlay.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCProjectHooks.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCWindowChange.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCWindowCheckoutFailure.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCWindowPending.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCWindowResolve.cs delete mode 100644 Editor/Mono/VersionControl/UI/VCWindowRevert.cs delete mode 100644 Editor/Mono/VersionControl/VCProvider.bindings.cs delete mode 100644 Editor/Mono/View.cs delete mode 100644 Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs delete mode 100644 Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs delete mode 100644 Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs delete mode 100644 Editor/Mono/VisualStudioUtil.bindings.cs delete mode 100644 Editor/Mono/WebViewEditorWindow/WebViewEditorStaticWindow.cs delete mode 100644 Editor/Mono/WebViewEditorWindow/WebViewEditorWindow.cs delete mode 100644 Editor/Mono/WebViewEditorWindow/WebViewEditorWindowsTabs.cs delete mode 100644 Editor/Mono/WebViewEditorWindow/WebViewTestFunctions.cs delete mode 100644 Editor/Src/TextRendering/TextRenderingCommands.cs delete mode 100644 Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs delete mode 100644 Editor/Src/VR/Mono/HolographicEmulation.cs delete mode 100644 Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs delete mode 100644 Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs delete mode 100644 Editor/Src/VR/Mono/VRCustomOptions.cs delete mode 100644 Editor/Src/VR/Mono/VREditor.cs delete mode 100644 Editor/Src/VR/Mono/VRModule.cs delete mode 100644 Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs delete mode 100644 Editor/Src/VR/ScriptBindings/VREditor.bindings.cs delete mode 100644 Extensions/Networking/Weaver/AssemblyInfo.cs delete mode 100644 Extensions/Networking/Weaver/Helpers.cs delete mode 100644 Extensions/Networking/Weaver/MessageClassProcessor.cs delete mode 100644 Extensions/Networking/Weaver/MonoBehaviourProcessor.cs delete mode 100644 Extensions/Networking/Weaver/Program.cs delete mode 100644 Extensions/Networking/Weaver/SyncListStructProcessor.cs delete mode 100644 Extensions/Networking/Weaver/UNetBehaviourProcessor.cs delete mode 100644 Extensions/Networking/Weaver/UNetWeaver.cs delete mode 100644 Extensions/Networking/Weaver/UNetWeaver.csproj delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSAlign.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSConstants.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSDIrection.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSDimension.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSEdge.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSExperimentalFeature.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSFlexDirection.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSJustify.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSLogLevel.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSLogger.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSMeasureFunc.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSMeasureMode.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSNode.Create.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSNode.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSOverflow.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSPositionType.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSPrintOptions.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSSize.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/CSSWrap.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/ConcurrentDictionary.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/MeasureFunction.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/MeasureOutput.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/Native.bindings.cs delete mode 100644 External/CSSLayout/csharp/Facebook.CSSLayout/Spacing.cs delete mode 100644 External/ExCSS/builds/builds/lib/net35/ExCSS.Unity.dll delete mode 100644 External/JsonParsers/MiniJson/MiniJSON.cs delete mode 100644 External/JsonParsers/SimpleJson/SimpleJson.cs delete mode 100644 External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Compiler.dll delete mode 100644 External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Parser.dll delete mode 100644 External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.dll delete mode 100644 External/Mono/builds/monodistribution/lib/mono/2.0/Mono.Posix.dll delete mode 100644 External/Mono/builds/monodistribution/lib/mono/2.0/Mono.Security.dll delete mode 100644 External/Mono/builds/monodistribution/lib/mono/2.0/System.Core.dll delete mode 100644 External/Mono/builds/monodistribution/lib/mono/2.0/System.Xml.Linq.dll delete mode 100644 External/Mono/builds/monodistribution/lib/mono/2.0/System.Xml.dll delete mode 100644 External/Mono/builds/monodistribution/lib/mono/2.0/System.dll delete mode 100644 External/Mono/builds/monodistribution/lib/mono/2.0/UnityScript.dll delete mode 100644 External/NRefactory/builds/3.2.1/net35/Unity.Legacy.NRefactory.dll delete mode 100644 External/Unity.Cecil/builds/lib/net35/Unity.Cecil.Mdb.dll delete mode 100644 External/Unity.Cecil/builds/lib/net35/Unity.Cecil.Pdb.dll delete mode 100644 External/Unity.Cecil/builds/lib/net35/Unity.Cecil.dll delete mode 100644 Modules/AI/NavMesh/NavMesh.bindings.cs delete mode 100644 Modules/AI/NavMesh/NavMesh.cs delete mode 100644 Modules/AI/NavMeshExperimental.bindings.cs delete mode 100644 Modules/Accessibility/VisionUtility.cs delete mode 100644 Modules/AssetBundle/Managed/AssemblyInfo.cs delete mode 100644 Modules/AssetBundle/Managed/AssetBundle.deprecated.cs delete mode 100644 Modules/AssetBundle/Managed/AssetBundleUtility.bindings.cs delete mode 100644 Modules/Audio/Public/Managed/Audio.deprecated.cs delete mode 100644 Modules/Audio/Public/ScriptBindings/AudioClipPlayable.bindings.cs delete mode 100644 Modules/Audio/Public/ScriptBindings/AudioExtensions.cs delete mode 100644 Modules/Audio/Public/ScriptBindings/AudioMixerPlayable.bindings.cs delete mode 100644 Modules/Audio/Public/ScriptBindings/AudioPlayableGraphExtensions.bindings.cs delete mode 100644 Modules/Audio/Public/ScriptBindings/AudioPlayableOutput.bindings.cs delete mode 100644 Modules/Audio/Public/ScriptBindings/AudioRenderer.bindings.cs delete mode 100644 Modules/Audio/Public/ScriptBindings/AudioSampleProvider.bindings.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/AssetBundleBuildInterface.bindings.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/BuildCommandSet.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/BuildDefines.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/BuildInput.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/BuildOutput.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/BuildSettings.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/BuildUsage.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/BuildUsageTagSet.bindings.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/ObjectIdentifier.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/PlayerBuildInterface.bindings.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/ResourceFile.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/SceneLoadInfo.cs delete mode 100644 Modules/BuildPipeline/Editor/Managed/TypeDB.bindings.cs delete mode 100644 Modules/BuildReportingEditor/Managed/BuildFile.cs delete mode 100644 Modules/BuildReportingEditor/Managed/BuildReport.bindings.cs delete mode 100644 Modules/BuildReportingEditor/Managed/BuildReportHelper.cs delete mode 100644 Modules/BuildReportingEditor/Managed/BuildReportViewerWindow.cs delete mode 100644 Modules/BuildReportingEditor/Managed/BuildResult.cs delete mode 100644 Modules/BuildReportingEditor/Managed/BuildStep.cs delete mode 100644 Modules/BuildReportingEditor/Managed/BuildStepMessage.cs delete mode 100644 Modules/BuildReportingEditor/Managed/BuildSummary.cs delete mode 100644 Modules/BuildReportingEditor/Managed/BuildType.cs delete mode 100644 Modules/BuildReportingEditor/Managed/CommonRoles.bindings.cs delete mode 100644 Modules/BuildReportingEditor/Managed/ScopedBuildStep.cs delete mode 100644 Modules/BuildReportingEditor/Managed/StrippingInfo.cs delete mode 100644 Modules/BuildReportingEditor/Managed/StrippingInfoWithSizeAnalysis.cs delete mode 100644 Modules/CloudServicesSettingsEditor/Ads/ScriptBindings/AdvertisementSettings.bindings.cs delete mode 100644 Modules/CloudServicesSettingsEditor/Analytics/ScriptBindings/AnalyticsSettings.bindings.cs delete mode 100644 Modules/CloudServicesSettingsEditor/CrashReporting/Managed/CrashReporting.cs delete mode 100644 Modules/CloudServicesSettingsEditor/CrashReporting/ScriptBindings/CrashReportingSettings.bindings.cs delete mode 100644 Modules/CloudServicesSettingsEditor/Managed/CoreStats.cs delete mode 100644 Modules/CloudServicesSettingsEditor/PerformanceReporting/ScriptBindings/PerformanceReportingSettings.bindings.cs delete mode 100644 Modules/CloudServicesSettingsEditor/Purchasing/ScriptBindings/PurchasingSettings.bindings.cs delete mode 100644 Modules/CrashReporting/CrashReportHandler.bindings.cs delete mode 100644 Modules/Director/ScriptBindings/PlayableDirector.bindings.cs delete mode 100644 Modules/GameCenter/Managed/GameCenterServices.cs delete mode 100644 Modules/GameCenter/Managed/LocalService.cs delete mode 100644 Modules/GameCenter/Managed/NetworkServices.cs delete mode 100644 Modules/GameCenter/Public/GameCenterServices.bindings.cs delete mode 100644 Modules/GraphViewEditor/BaseTypeFactory.cs delete mode 100644 Modules/GraphViewEditor/Capabilities.cs delete mode 100644 Modules/GraphViewEditor/DataWatchContainer.cs delete mode 100644 Modules/GraphViewEditor/Decorators/GridBackground.cs delete mode 100644 Modules/GraphViewEditor/Direction.cs delete mode 100644 Modules/GraphViewEditor/EdgeControl.cs delete mode 100644 Modules/GraphViewEditor/Elements/Edge.cs delete mode 100644 Modules/GraphViewEditor/Elements/FallbackGraphElement.cs delete mode 100644 Modules/GraphViewEditor/Elements/GraphElement.cs delete mode 100644 Modules/GraphViewEditor/Elements/GraphElementGroupNodeExtensions.cs delete mode 100644 Modules/GraphViewEditor/Elements/GroupNode.cs delete mode 100644 Modules/GraphViewEditor/Elements/MiniMap.cs delete mode 100644 Modules/GraphViewEditor/Elements/Node.cs delete mode 100644 Modules/GraphViewEditor/Elements/Port.cs delete mode 100644 Modules/GraphViewEditor/Elements/Presenters/EdgePresenter.cs delete mode 100644 Modules/GraphViewEditor/Elements/Presenters/GraphElementPresenter.cs delete mode 100644 Modules/GraphViewEditor/Elements/Presenters/InputPortPresenter.cs delete mode 100644 Modules/GraphViewEditor/Elements/Presenters/MiniMapPresenter.cs delete mode 100644 Modules/GraphViewEditor/Elements/Presenters/NodePresenter.cs delete mode 100644 Modules/GraphViewEditor/Elements/Presenters/OutputPortPresenter.cs delete mode 100644 Modules/GraphViewEditor/Elements/Presenters/PortPresenter.cs delete mode 100644 Modules/GraphViewEditor/Elements/Presenters/SimpleElementPresenter.cs delete mode 100644 Modules/GraphViewEditor/Elements/SimpleElement.cs delete mode 100644 Modules/GraphViewEditor/GraphViewEditorWindow.cs delete mode 100644 Modules/GraphViewEditor/GraphViewTypeFactory.cs delete mode 100644 Modules/GraphViewEditor/IDroppable.cs delete mode 100644 Modules/GraphViewEditor/ISelectable.cs delete mode 100644 Modules/GraphViewEditor/ISelection.cs delete mode 100644 Modules/GraphViewEditor/IconBadge.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/ClickSelector.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/ContentDragger.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/Dragger.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/EdgeConnector.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/EdgeDragHelper.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/EdgeManipulator.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/FreehandSelector.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/RectangleSelector.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/Resizer.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/SelectionDragger.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/SelectionDropper.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/ShortcutHandler.cs delete mode 100644 Modules/GraphViewEditor/Manipulators/Zoomer.cs delete mode 100644 Modules/GraphViewEditor/NodeAdapter.cs delete mode 100644 Modules/GraphViewEditor/NodeSearch/SearchTree.cs delete mode 100644 Modules/GraphViewEditor/NodeSearch/SearchWindow.cs delete mode 100644 Modules/GraphViewEditor/Orientation.cs delete mode 100644 Modules/GraphViewEditor/Utils/RectUtils.cs delete mode 100644 Modules/GraphViewEditor/Utils/VisualElementAttacher.cs delete mode 100644 Modules/GraphViewEditor/Views/GraphView.cs delete mode 100644 Modules/GraphViewEditor/Views/Presenters/GraphViewPresenter.cs delete mode 100644 Modules/Grid/Managed/Grid.cs delete mode 100644 Modules/Grid/ScriptBindings/Grid.bindings.cs delete mode 100644 Modules/Grid/ScriptBindings/GridLayout.bindings.cs delete mode 100644 Modules/GridEditor/Managed/GridEditor.cs delete mode 100644 Modules/GridEditor/Managed/GridEditorUtility.cs delete mode 100644 Modules/GridEditor/Managed/SceneViewGridManager.cs delete mode 100644 Modules/IMGUI/Event.cs delete mode 100644 Modules/IMGUI/EventCommandNames.cs delete mode 100644 Modules/IMGUI/EventEnums.cs delete mode 100644 Modules/IMGUI/EventInterests.cs delete mode 100644 Modules/IMGUI/FriendAttributes.cs delete mode 100644 Modules/IMGUI/GUI.cs delete mode 100644 Modules/IMGUI/GUIBindings.cs delete mode 100644 Modules/IMGUI/GUIContent.cs delete mode 100644 Modules/IMGUI/GUIDebugger.bindings.cs delete mode 100644 Modules/IMGUI/GUIEnums.cs delete mode 100644 Modules/IMGUI/GUILayout.cs delete mode 100644 Modules/IMGUI/GUILayoutBindings.cs delete mode 100644 Modules/IMGUI/GUILayoutOption.cs delete mode 100644 Modules/IMGUI/GUILayoutUtility.cs delete mode 100644 Modules/IMGUI/GUISkin.cs delete mode 100644 Modules/IMGUI/GUIStateObjects.cs delete mode 100644 Modules/IMGUI/GUIStyle.cs delete mode 100644 Modules/IMGUI/GUITargetAttribute.cs delete mode 100644 Modules/IMGUI/GUIUtility.bindings.cs delete mode 100644 Modules/IMGUI/GUIUtility.cs delete mode 100644 Modules/IMGUI/LayoutEntry.cs delete mode 100644 Modules/IMGUI/LayoutGroup.cs delete mode 100644 Modules/IMGUI/ObjectGUIState.bindings.cs delete mode 100644 Modules/IMGUI/ScrollViewState.cs delete mode 100644 Modules/IMGUI/SliderHandler.cs delete mode 100644 Modules/IMGUI/StylePainter.cs delete mode 100644 Modules/IMGUI/TextEditor.cs delete mode 100644 Modules/Input/Private/Input.cs delete mode 100644 Modules/Input/Private/InputModule.bindings.cs delete mode 100644 Modules/PackageManager/Editor/Managed/BuildUtilities.cs delete mode 100644 Modules/PackageManager/Editor/Managed/Client.cs delete mode 100644 Modules/PackageManager/Editor/Managed/Error.cs delete mode 100644 Modules/PackageManager/Editor/Managed/ErrorCode.cs delete mode 100644 Modules/PackageManager/Editor/Managed/IShouldIncludeInBuildCallback.cs delete mode 100644 Modules/PackageManager/Editor/Managed/NativeStatusCode.cs delete mode 100644 Modules/PackageManager/Editor/Managed/OperationStatus.cs delete mode 100644 Modules/PackageManager/Editor/Managed/PackageCollection.cs delete mode 100644 Modules/PackageManager/Editor/Managed/PackageInfo.cs delete mode 100644 Modules/PackageManager/Editor/Managed/PackageManager.bindings.cs delete mode 100644 Modules/PackageManager/Editor/Managed/PackageManagerCommands.cs delete mode 100644 Modules/PackageManager/Editor/Managed/PackageSource.cs delete mode 100644 Modules/PackageManager/Editor/Managed/PackageStatus.cs delete mode 100644 Modules/PackageManager/Editor/Managed/Requests/AddRequest.cs delete mode 100644 Modules/PackageManager/Editor/Managed/Requests/ListRequest.cs delete mode 100644 Modules/PackageManager/Editor/Managed/Requests/RemoveRequest.cs delete mode 100644 Modules/PackageManager/Editor/Managed/Requests/Request.cs delete mode 100644 Modules/PackageManager/Editor/Managed/Requests/ResetToEditorDefaultsRequest.cs delete mode 100644 Modules/PackageManager/Editor/Managed/Requests/SearchRequest.cs delete mode 100644 Modules/PackageManager/Editor/Managed/StatusCode.cs delete mode 100644 Modules/PackageManager/Editor/Managed/VersionsInfo.cs delete mode 100644 Modules/ParticlesLegacy/Private/ScriptBindings/ParticlesLegacy.deprecated.cs delete mode 100644 Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs delete mode 100644 Modules/Physics2D/ScriptBindings/Physics2D.deprecated.cs delete mode 100644 Modules/PresetsEditor/Preset.bindings.cs delete mode 100644 Modules/PresetsEditor/PresetContextMenu.cs delete mode 100644 Modules/PresetsEditor/PresetEditor.cs delete mode 100644 Modules/PresetsEditor/PresetManager.bindings.cs delete mode 100644 Modules/PresetsEditor/PresetManagerEditor.cs delete mode 100644 Modules/PresetsEditor/PresetManagerPostProcessor.cs delete mode 100644 Modules/PresetsEditor/PresetSelector.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/AttachProfilerUI.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/AudioProfilerView.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/Chart.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/IProfilerWindowController.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/MemoryElement.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/MemoryElementDataManager.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/MemorySnapshot.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/MemoryTreeList.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/NetworkDetailStats.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerChart.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerColors.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedCallsView.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedObjectsView.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerDetailedView.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameDataTreeView.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameHierarchyView.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerFrameViewBase.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerInstrumentationPopup.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerTimelineGUI.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/ProfilerWindow.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/UISystem/UISystemProfiler.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/UISystem/UISystemProfilerChart.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/UISystem/UISystemProfilerThumbnailService.cs delete mode 100644 Modules/Profiler/Editor/ProfilerWindow/UISystem/UISystemProfilerTreeView.cs delete mode 100644 Modules/Profiler/Editor/Public/ProfilerFrameDataView.bindings.cs delete mode 100644 Modules/RestService/AssetRestHandler.cs delete mode 100644 Modules/RestService/Handler.cs delete mode 100644 Modules/RestService/HttpStatusCode.cs delete mode 100644 Modules/RestService/Logger.cs delete mode 100644 Modules/RestService/OpenDocumentsRestHandler.cs delete mode 100644 Modules/RestService/PairingRestHandler.cs delete mode 100644 Modules/RestService/PlayModeRestHandler.cs delete mode 100644 Modules/RestService/ProjectStateRestHandler.cs delete mode 100644 Modules/RestService/RestRequest.cs delete mode 100644 Modules/RestService/RestRequestException.cs delete mode 100644 Modules/RestService/RestServiceExtension.cs delete mode 100644 Modules/RestService/ScriptEditorSettings.cs delete mode 100644 Modules/ScreenCapture/ScriptBindings/ScreenCapture.bindings.cs delete mode 100644 Modules/SharedInternals/Attributes.cs delete mode 100644 Modules/SharedInternals/BindingsAttributes.cs delete mode 100644 Modules/SharedInternals/UnityString.cs delete mode 100644 Modules/SpriteMask/Public/ScriptBindings/SpriteMask.bindings.cs delete mode 100644 Modules/SpriteMaskEditor/Editor/Managed/SpriteMaskEditor.cs delete mode 100644 Modules/SpriteShape/Public/ScriptBindings/SpriteShapeUtility.bindings.cs delete mode 100644 Modules/SpriteShapeEditor/Managed/SpriteShapeRendererEditor.cs delete mode 100644 Modules/Substance/SubstanceUtility.bindings.cs delete mode 100644 Modules/Substance/SubstanceUtility.cs delete mode 100644 Modules/Terrain/Public/Terrain.bindings.cs delete mode 100644 Modules/Terrain/Public/TerrainData.bindings.cs delete mode 100644 Modules/TextRendering/FontStyle.cs delete mode 100644 Modules/TextRendering/TextGenerator.cs delete mode 100644 Modules/Tilemap/Managed/CustomGridBrushAttribute.cs delete mode 100644 Modules/Tilemap/Managed/GridBrushBase.cs delete mode 100644 Modules/Tilemap/Managed/ITilemap.cs delete mode 100644 Modules/Tilemap/Managed/Tile.cs delete mode 100644 Modules/Tilemap/Managed/TileBase.cs delete mode 100644 Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/EditorPreviewTilemap.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridBrushesDropdown.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteClipboard.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridPaintTargetsDropdown.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridPalette.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteBrushes.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteUtility.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridPalettes.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridPalettesDropdown.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridSelection.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/GridSelectionEditor.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/TileDragAndDrop.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/Grid/TileDragAndDropManager.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/TileEditor.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/TileUtility.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/TilemapCollider2DEditor.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs delete mode 100644 Modules/TilemapEditor/Editor/Managed/TilemapRendererEditor.cs delete mode 100644 Modules/TilemapEditor/Editor/ScriptBindings/TilemapEditor.bindings.cs delete mode 100644 Modules/UIElements/Button.cs delete mode 100644 Modules/UIElements/ClampedDragger.cs delete mode 100644 Modules/UIElements/Clickable.cs delete mode 100644 Modules/UIElements/ContextualMenu.cs delete mode 100644 Modules/UIElements/ContextualMenuManager.cs delete mode 100644 Modules/UIElements/ContextualMenuManipulator.cs delete mode 100644 Modules/UIElements/Cursor.cs delete mode 100644 Modules/UIElements/EventArgs.cs delete mode 100644 Modules/UIElements/EventDispatcher.cs delete mode 100644 Modules/UIElements/Events/CaptureEvents.cs delete mode 100644 Modules/UIElements/Events/ChangeEvent.cs delete mode 100644 Modules/UIElements/Events/EventBase.cs delete mode 100644 Modules/UIElements/Events/EventCallback.cs delete mode 100644 Modules/UIElements/Events/EventCallbackRegistry.cs delete mode 100644 Modules/UIElements/Events/EventHandler.cs delete mode 100644 Modules/UIElements/Events/EventPool.cs delete mode 100644 Modules/UIElements/Events/FocusEvents.cs delete mode 100644 Modules/UIElements/Events/InputEvents.cs delete mode 100644 Modules/UIElements/Events/KeyboardEvents.cs delete mode 100644 Modules/UIElements/Events/LayoutEvents.cs delete mode 100644 Modules/UIElements/Events/MouseEvents.cs delete mode 100644 Modules/UIElements/Events/PanelEvents.cs delete mode 100644 Modules/UIElements/Events/UIEvent.cs delete mode 100644 Modules/UIElements/FocusController.cs delete mode 100644 Modules/UIElements/HierarchyTraversal.cs delete mode 100644 Modules/UIElements/IDataWatchService.cs delete mode 100644 Modules/UIElements/IMGUIContainer.cs delete mode 100644 Modules/UIElements/INotifyValueChanged.cs delete mode 100644 Modules/UIElements/ISerializableJsonDictionary.cs delete mode 100644 Modules/UIElements/IStyle.cs delete mode 100644 Modules/UIElements/ITransform.cs delete mode 100644 Modules/UIElements/Image.cs delete mode 100644 Modules/UIElements/KeyboardTextEditor.cs delete mode 100644 Modules/UIElements/Label.cs delete mode 100644 Modules/UIElements/ManipulatorActivationFilter.cs delete mode 100644 Modules/UIElements/Manipulators.cs delete mode 100644 Modules/UIElements/MouseButton.cs delete mode 100644 Modules/UIElements/MouseCaptureController.cs delete mode 100644 Modules/UIElements/MouseManipulator.cs delete mode 100644 Modules/UIElements/Panel.cs delete mode 100644 Modules/UIElements/PanelWrapper.cs delete mode 100644 Modules/UIElements/RepeatButton.cs delete mode 100644 Modules/UIElements/Scheduler.cs delete mode 100644 Modules/UIElements/ScrollView.cs delete mode 100644 Modules/UIElements/Scroller.cs delete mode 100644 Modules/UIElements/Slider.cs delete mode 100644 Modules/UIElements/Spacing.cs delete mode 100644 Modules/UIElements/StyleEnums.cs delete mode 100644 Modules/UIElements/StyleSheets/StyleComplexSelectorExtensions.cs delete mode 100644 Modules/UIElements/StyleSheets/StyleContext.cs delete mode 100644 Modules/UIElements/StyleSheets/StyleSheetApplicator.cs delete mode 100644 Modules/UIElements/StyleSheets/StyleSheetCache.cs delete mode 100644 Modules/UIElements/StyleSheets/StyleSheetExtensions.cs delete mode 100644 Modules/UIElements/StyleSheets/StyleValue.cs delete mode 100644 Modules/UIElements/StyleSheets/VisualElementStylesData.cs delete mode 100644 Modules/UIElements/TemplateContainer.cs delete mode 100644 Modules/UIElements/TextEditor.cs delete mode 100644 Modules/UIElements/TextEditorEngine.cs delete mode 100644 Modules/UIElements/TextElement.cs delete mode 100644 Modules/UIElements/TextField.cs delete mode 100644 Modules/UIElements/TextInputFieldBase.cs delete mode 100644 Modules/UIElements/Toggle.cs delete mode 100644 Modules/UIElements/TouchScreenTextEditor.cs delete mode 100644 Modules/UIElements/UIElementsUtility.cs delete mode 100644 Modules/UIElements/UQuery.cs delete mode 100644 Modules/UIElements/UXML/IUxmlAttributes.cs delete mode 100644 Modules/UIElements/UXML/TemplateAsset.cs delete mode 100644 Modules/UIElements/UXML/VisualElementAsset.cs delete mode 100644 Modules/UIElements/UXML/VisualElementFactory.cs delete mode 100644 Modules/UIElements/UXML/VisualTreeAsset.cs delete mode 100644 Modules/UIElements/VisualContainer.cs delete mode 100644 Modules/UIElements/VisualElement.cs delete mode 100644 Modules/UIElements/VisualElementDataWatch.cs delete mode 100644 Modules/UIElements/VisualElementFocusRing.cs delete mode 100644 Modules/UIElements/VisualElementHierarchy.cs delete mode 100644 Modules/UIElements/VisualElementScheduler.cs delete mode 100644 Modules/UIElements/VisualElementStyleAccess.cs delete mode 100644 Modules/UIElements/VisualElementUtils.cs delete mode 100644 Modules/UIElementsDebuggerEditor/PanelDebug.cs delete mode 100644 Modules/UIElementsDebuggerEditor/PanelPickerWindow.cs delete mode 100644 Modules/UIElementsDebuggerEditor/PickingData.cs delete mode 100644 Modules/UIElementsDebuggerEditor/UIElementsDebugger.cs delete mode 100644 Modules/UIElementsDebuggerEditor/UxmlExporter.cs delete mode 100644 Modules/UIElementsDebuggerEditor/VisualTreeTreeView.cs delete mode 100644 Modules/UnityAnalytics/Events/CustomEventData.bindings.cs delete mode 100644 Modules/UnityAnalytics/Events/CustomEventData.cs delete mode 100644 Modules/UnityAnalytics/UnityAnalytics.cs delete mode 100644 Modules/UnityAnalytics/UnityAnalyticsHandler.bindings.cs delete mode 100644 Modules/UnityConnect/AnalyticsSessionInfo.bindings.cs delete mode 100644 Modules/UnityConnect/RemoteSettings.bindings.cs delete mode 100644 Modules/UnityEditorAnalyticsEditor/BuildEventsHandler.cs delete mode 100644 Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs delete mode 100644 Modules/UnityEditorAnalyticsEditor/UsabilityAnalytics.bindings.cs delete mode 100644 Modules/UnityWebRequest/FriendAttributes.cs delete mode 100644 Modules/UnityWebRequest/Public/CertificateHandler/CertificateHandler.bindings.cs delete mode 100644 Modules/UnityWebRequest/Public/DownloadHandler/DownloadHandler.bindings.cs delete mode 100644 Modules/UnityWebRequest/Public/MultipartFormHelper.cs delete mode 100644 Modules/UnityWebRequest/Public/UnityWebRequest.bindings.cs delete mode 100644 Modules/UnityWebRequest/Public/UploadHandler/UploadHandler.bindings.cs delete mode 100644 Modules/UnityWebRequest/Public/WebRequest.deprecated.cs delete mode 100644 Modules/UnityWebRequest/Public/WebRequestExtensions.cs delete mode 100644 Modules/UnityWebRequest/Public/WebRequestUtils.cs delete mode 100644 Modules/UnityWebRequestAssetBundle/Public/DownloadHandlerAssetBundle.bindings.cs delete mode 100644 Modules/UnityWebRequestAssetBundle/UnityWebRequestAssetBundle.cs delete mode 100644 Modules/UnityWebRequestAudio/Public/DownloadHandlerAudio.bindings.cs delete mode 100644 Modules/UnityWebRequestAudio/UnityWebRequestMultimedia.cs delete mode 100644 Modules/UnityWebRequestTexture/Public/DownloadHandlerTexture.bindings.cs delete mode 100644 Modules/UnityWebRequestTexture/UnityWebRequestTexture.cs delete mode 100644 Modules/UnityWebRequestWWW/Public/WWW.bindings.cs delete mode 100644 Modules/UnityWebRequestWWW/Public/WWW.cs delete mode 100644 Modules/Video/Public/ScriptBindings/VideoClipPlayable.bindings.cs delete mode 100644 Modules/Video/Public/ScriptBindings/VideoPlayerExtensions.bindings.cs delete mode 100644 Modules/Web/FriendAttributes.cs delete mode 100644 Modules/XR/DotNetHelper.cs delete mode 100644 Modules/XR/Subsystems/Camera/XRCameraSubsystem.bindings.cs delete mode 100644 Modules/XR/Subsystems/Camera/XRCameraSubsystemDescriptor.bindings.cs delete mode 100644 Modules/XR/Subsystems/Depth/XRDepthSubsystem.bindings.cs delete mode 100644 Modules/XR/Subsystems/Depth/XRDepthSubsystemDescriptor.bindings.cs delete mode 100644 Modules/XR/Subsystems/Example/XRExampleSubsystem.bindings.cs delete mode 100644 Modules/XR/Subsystems/Example/XRExampleSubsystemDescriptor.bindings.cs delete mode 100644 Modules/XR/Subsystems/Input/XRInputSubsystem.bindings.cs delete mode 100644 Modules/XR/Subsystems/Input/XRInputSubsystemDescriptor.bindings.cs delete mode 100644 Modules/XR/Subsystems/Planes/XRPlaneSubsystem.bindings.cs delete mode 100644 Modules/XR/Subsystems/Planes/XRPlaneSubsystemDescriptor.bindings.cs delete mode 100644 Modules/XR/Subsystems/Raycast/XRRaycastSubsystem.bindings.cs delete mode 100644 Modules/XR/Subsystems/Raycast/XRRaycastSubsystemDescriptor.bindings.cs delete mode 100644 Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystem.bindings.cs delete mode 100644 Modules/XR/Subsystems/ReferencePoints/XRReferencePointSubsystemDescriptor.bindings.cs delete mode 100644 Modules/XR/Subsystems/Session/XRSessionSubsystem.bindings.cs delete mode 100644 Modules/XR/Subsystems/Session/XRSessionSubsystemDescriptor.bindings.cs delete mode 100644 Modules/XR/UnityXRTrackable.bindings.cs delete mode 100644 Modules/XR/XRSubsystemManager.bindings.cs delete mode 100644 Projects/CSharp/UnityEditor.csproj delete mode 100644 Projects/CSharp/UnityEngine.csproj delete mode 100644 Projects/CSharp/UnityReferenceSource.sln delete mode 100644 README.md delete mode 100644 Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs delete mode 100644 Runtime/2D/Common/ScriptBindings/Sprites.bindings.cs delete mode 100644 Runtime/2D/Sorting/ScriptBindings/SortingGroup.bindings.cs delete mode 100644 Runtime/AR/ScriptBindings/ARBackgroundRenderer.cs delete mode 100644 Runtime/AR/Tango/ScriptBindings/Tango.bindings.cs delete mode 100644 Runtime/AR/Tango/ScriptBindings/TangoConfig.cs delete mode 100644 Runtime/AR/Tango/ScriptBindings/TangoDevice.cs delete mode 100644 Runtime/AR/Tango/ScriptBindings/TangoInputTracking.cs delete mode 100644 Runtime/AR/Tango/ScriptBindings/TangoMeshReconstructionServer.cs delete mode 100644 Runtime/Animation/Managed/Animation.deprecated.cs delete mode 100644 Runtime/Animation/Managed/AnimationPlayableUtilities.cs delete mode 100644 Runtime/Animation/Managed/Animator.deprecated.cs delete mode 100644 Runtime/Animation/Managed/StateMachineBehaviour.cs delete mode 100644 Runtime/Animation/ScriptBindings/AimConstraint.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimationClip.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimationClipPlayable.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimationLayerMixerPlayable.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimationMixerPlayable.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimationMotionXToDeltaPlayable.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimationOffsetPlayable.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimationPlayableExtensions.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimationPlayableGraphExtensions.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimationPlayableOutput.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/Animator.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimatorControllerParameter.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimatorControllerPlayable.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimatorOverrideController.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AnimatorUtility.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/Avatar.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AvatarBuilder.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/AvatarMask.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/Constraint.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/HumanPoseHandler.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/HumanTrait.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/Motion.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/ParentConstraint.bindings.cs delete mode 100644 Runtime/Animation/ScriptBindings/RuntimeAnimatorController.bindings.cs delete mode 100644 Runtime/Cloth/Cloth.bindings.cs delete mode 100644 Runtime/Cloth/Cloth.cs delete mode 100644 Runtime/Dynamics/Managed/Dynamics.cs delete mode 100644 Runtime/Dynamics/ScriptBindings/RaycastCommand.bindings.cs delete mode 100644 Runtime/Export/AndroidJNISafe.cs delete mode 100644 Runtime/Export/AndroidJavaImpl.cs delete mode 100644 Runtime/Export/Application.cs delete mode 100644 Runtime/Export/ArrayUtils.cs delete mode 100644 Runtime/Export/AssemblyInfo.cs delete mode 100644 Runtime/Export/Assertions/Assert/AssertBase.cs delete mode 100644 Runtime/Export/Assertions/Assert/AssertBool.cs delete mode 100644 Runtime/Export/Assertions/Assert/AssertFloat.cs delete mode 100644 Runtime/Export/Assertions/Assert/AssertGeneric.cs delete mode 100644 Runtime/Export/Assertions/Assert/AssertNull.cs delete mode 100644 Runtime/Export/Assertions/Assert/AssertionException.cs delete mode 100644 Runtime/Export/Assertions/Assert/AssertionMessageUtil.cs delete mode 100644 Runtime/Export/Assertions/Assert/Comparers/FloatComparer.cs delete mode 100644 Runtime/Export/Assertions/Must/MustBool.cs delete mode 100644 Runtime/Export/Assertions/Must/MustFloat.cs delete mode 100644 Runtime/Export/Assertions/Must/MustGeneric.cs delete mode 100644 Runtime/Export/Assertions/Must/MustNull.cs delete mode 100644 Runtime/Export/AsyncGPUReadback.bindings.cs delete mode 100644 Runtime/Export/AttributeHelperEngine.cs delete mode 100644 Runtime/Export/Attributes.cs delete mode 100644 Runtime/Export/AudioType.cs delete mode 100644 Runtime/Export/BaseClass.cs delete mode 100644 Runtime/Export/BeforeRenderHelper.cs delete mode 100644 Runtime/Export/BootConfig.bindings.cs delete mode 100644 Runtime/Export/Bounds.cs delete mode 100644 Runtime/Export/BoundsInt.cs delete mode 100644 Runtime/Export/Burst/BurstDiscardAttribute.cs delete mode 100644 Runtime/Export/Cache.bindings.cs delete mode 100644 Runtime/Export/Caching.bindings.cs delete mode 100644 Runtime/Export/Caching.deprecated.cs delete mode 100644 Runtime/Export/Camera.bindings.cs delete mode 100644 Runtime/Export/Camera.deprecated.cs delete mode 100644 Runtime/Export/CastHelper.cs delete mode 100644 Runtime/Export/ClassLibraryInitializer.cs delete mode 100644 Runtime/Export/Collections/NativeCollectionAccessPolicies.cs delete mode 100644 Runtime/Export/Collections/NativeCollectionEnums.bindings.cs delete mode 100644 Runtime/Export/Color.cs delete mode 100644 Runtime/Export/Color32.cs delete mode 100644 Runtime/Export/ColorUtility.cs delete mode 100644 Runtime/Export/Component.bindings.cs delete mode 100644 Runtime/Export/Component.deprecated.cs delete mode 100644 Runtime/Export/Coroutine.bindings.cs delete mode 100644 Runtime/Export/Coroutines.cs delete mode 100644 Runtime/Export/CustomYieldInstruction.cs delete mode 100644 Runtime/Export/Debug.bindings.cs delete mode 100644 Runtime/Export/Debug.deprecated.cs delete mode 100644 Runtime/Export/DiagnosticSwitch.cs delete mode 100644 Runtime/Export/Director/CameraPlayable.bindings.cs delete mode 100644 Runtime/Export/Director/FrameData.cs delete mode 100644 Runtime/Export/Director/IPlayable.cs delete mode 100644 Runtime/Export/Director/IPlayableBehaviour.cs delete mode 100644 Runtime/Export/Director/IPlayableOutput.cs delete mode 100644 Runtime/Export/Director/MaterialEffectPlayable.bindings.cs delete mode 100644 Runtime/Export/Director/Playable.cs delete mode 100644 Runtime/Export/Director/PlayableAsset.cs delete mode 100644 Runtime/Export/Director/PlayableBehaviour.cs delete mode 100644 Runtime/Export/Director/PlayableExtensions.cs delete mode 100644 Runtime/Export/Director/PlayableGraph.bindings.cs delete mode 100644 Runtime/Export/Director/PlayableHandle.bindings.cs delete mode 100644 Runtime/Export/Director/PlayableOutput.bindings.cs delete mode 100644 Runtime/Export/Director/PlayableOutput.cs delete mode 100644 Runtime/Export/Director/PlayableOutputExtensions.cs delete mode 100644 Runtime/Export/Director/ScriptPlayable.cs delete mode 100644 Runtime/Export/Director/ScriptPlayableOutput.cs delete mode 100644 Runtime/Export/Director/TextureMixerPlayable.bindings.cs delete mode 100644 Runtime/Export/Director/TexturePlayableGraphExtensions.bindings.cs delete mode 100644 Runtime/Export/Director/TexturePlayableOutput.bindings.cs delete mode 100644 Runtime/Export/DrivenPropertyManager.bindings.cs delete mode 100644 Runtime/Export/EnumInfo.cs delete mode 100644 Runtime/Export/ExcludeFromObjectFactoryAttribute.cs delete mode 100644 Runtime/Export/ExposedPropertyTable.bindings.cs delete mode 100644 Runtime/Export/ExposedReference.cs delete mode 100644 Runtime/Export/FailedToLoadScriptObject.cs delete mode 100644 Runtime/Export/FriendAttributes.cs delete mode 100644 Runtime/Export/GI/Lightmapping.cs delete mode 100644 Runtime/Export/GPUFence.bindings.cs delete mode 100644 Runtime/Export/GameObject.deprecated.cs delete mode 100644 Runtime/Export/GeometryUtility.cs delete mode 100644 Runtime/Export/Graphics.bindings.cs delete mode 100644 Runtime/Export/Graphics.cs delete mode 100644 Runtime/Export/Graphics.deprecated.cs delete mode 100644 Runtime/Export/GraphicsComponents.bindings.cs delete mode 100644 Runtime/Export/GraphicsEnums.cs delete mode 100644 Runtime/Export/GraphicsManagers.bindings.cs delete mode 100644 Runtime/Export/GraphicsRenderers.bindings.cs delete mode 100644 Runtime/Export/Handheld.cs delete mode 100644 Runtime/Export/Hash128.bindings.cs delete mode 100644 Runtime/Export/IExposedPropertyTable.cs delete mode 100644 Runtime/Export/Internal/DefaultValueAttribute.cs delete mode 100644 Runtime/Export/Internal/ExcludeFromDocs.cs delete mode 100644 Runtime/Export/Internal/InternalInterfaces.cs delete mode 100644 Runtime/Export/JetBrains.Annotations.cs delete mode 100644 Runtime/Export/KeyCode.cs delete mode 100644 Runtime/Export/Light.deprecated.cs delete mode 100644 Runtime/Export/LineUtility.cs delete mode 100644 Runtime/Export/Logger/DebugLogHandler.cs delete mode 100644 Runtime/Export/Logger/ILogHandler.cs delete mode 100644 Runtime/Export/Logger/ILogger.cs delete mode 100644 Runtime/Export/Logger/Logger.cs delete mode 100644 Runtime/Export/ManagedStreamHelpers.cs delete mode 100644 Runtime/Export/Math.bindings.cs delete mode 100644 Runtime/Export/Mathf.cs delete mode 100644 Runtime/Export/Matrix4x4.cs delete mode 100644 Runtime/Export/Mesh.bindings.cs delete mode 100644 Runtime/Export/Mesh.cs delete mode 100644 Runtime/Export/Metro.cs delete mode 100644 Runtime/Export/MonoBehaviour.bindings.cs delete mode 100644 Runtime/Export/MouseEvents.cs delete mode 100644 Runtime/Export/NativeArray/DisposeSentinel.cs delete mode 100644 Runtime/Export/NativeArray/NativeArray.cs delete mode 100644 Runtime/Export/NativeArray/NativeSlice.cs delete mode 100644 Runtime/Export/Networking/PlayerConnection/ConnectionApi.cs delete mode 100644 Runtime/Export/Networking/PlayerConnection/PlayerConnection.cs delete mode 100644 Runtime/Export/Networking/PlayerConnection/PlayerEditorConnectionEvents.cs delete mode 100644 Runtime/Export/Ping.bindings.cs delete mode 100644 Runtime/Export/Plane.cs delete mode 100644 Runtime/Export/PlayerLoop.bindings.cs delete mode 100644 Runtime/Export/Pose.cs delete mode 100644 Runtime/Export/PropertyAttribute.cs delete mode 100644 Runtime/Export/PropertyName.bindings.cs delete mode 100644 Runtime/Export/PropertyName.cs delete mode 100644 Runtime/Export/Quaternion.cs delete mode 100644 Runtime/Export/Random.bindings.cs delete mode 100644 Runtime/Export/Random.cs delete mode 100644 Runtime/Export/RangeInt.cs delete mode 100644 Runtime/Export/Ray.cs delete mode 100644 Runtime/Export/Ray2D.cs delete mode 100644 Runtime/Export/Rect.cs delete mode 100644 Runtime/Export/RectInt.cs delete mode 100644 Runtime/Export/RectOffset.cs delete mode 100644 Runtime/Export/RenderPipeline/BlendState.cs delete mode 100644 Runtime/Export/RenderPipeline/CullingParameters.cs delete mode 100644 Runtime/Export/RenderPipeline/DepthState.cs delete mode 100644 Runtime/Export/RenderPipeline/DrawRendererFlags.cs delete mode 100644 Runtime/Export/RenderPipeline/DrawRendererSortSettings.cs delete mode 100644 Runtime/Export/RenderPipeline/DrawShadowsSettings.cs delete mode 100644 Runtime/Export/RenderPipeline/FilterRenderersSettings.cs delete mode 100644 Runtime/Export/RenderPipeline/FilterResults.cs delete mode 100644 Runtime/Export/RenderPipeline/IRenderPipeline.cs delete mode 100644 Runtime/Export/RenderPipeline/IRenderPipelineAsset.cs delete mode 100644 Runtime/Export/RenderPipeline/LODParameters.cs delete mode 100644 Runtime/Export/RenderPipeline/RasterState.cs delete mode 100644 Runtime/Export/RenderPipeline/ReflectionProbeSortOptions.cs delete mode 100644 Runtime/Export/RenderPipeline/RenderPipeline.cs delete mode 100644 Runtime/Export/RenderPipeline/RenderPipelineAsset.cs delete mode 100644 Runtime/Export/RenderPipeline/RenderPipelineManager.cs delete mode 100644 Runtime/Export/RenderPipeline/RenderQueueRange.cs delete mode 100644 Runtime/Export/RenderPipeline/RenderStateBlock.cs delete mode 100644 Runtime/Export/RenderPipeline/RenderStateMapping.cs delete mode 100644 Runtime/Export/RenderPipeline/RenderStateMask.cs delete mode 100644 Runtime/Export/RenderPipeline/RenderTargetBlendState.cs delete mode 100644 Runtime/Export/RenderPipeline/RendererConfiguration.cs delete mode 100644 Runtime/Export/RenderPipeline/ScriptableRenderContext.cs delete mode 100644 Runtime/Export/RenderPipeline/ShadowSplitData.cs delete mode 100644 Runtime/Export/RenderPipeline/SortFlags.cs delete mode 100644 Runtime/Export/RenderPipeline/StencilState.cs delete mode 100644 Runtime/Export/RenderPipeline/SupportedRenderingFeatures.cs delete mode 100644 Runtime/Export/RenderPipeline/VisibleLightFlags.cs delete mode 100644 Runtime/Export/RenderingCommandBuffer.bindings.cs delete mode 100644 Runtime/Export/Resources.deprecated.cs delete mode 100644 Runtime/Export/RuntimeInitializeOnLoadAttribute.cs delete mode 100644 Runtime/Export/ScriptableObject.bindings.cs delete mode 100644 Runtime/Export/ScriptableRenderContext.bindings.cs delete mode 100644 Runtime/Export/ScriptableRenderLoop/RenderPass.cs delete mode 100644 Runtime/Export/ScriptableRenderLoop/RenderPassAttachment.bindings.cs delete mode 100644 Runtime/Export/Scripting/APIUpdating/UpdatedFromAttribute.cs delete mode 100644 Runtime/Export/Scripting/PreserveAttribute.cs delete mode 100644 Runtime/Export/Scripting/ScriptingRuntime.bindings.cs delete mode 100644 Runtime/Export/ScrollWaitDefinitions.cs delete mode 100644 Runtime/Export/Security.cs delete mode 100644 Runtime/Export/SelectionBaseAttribute.cs delete mode 100644 Runtime/Export/Serialization.cs delete mode 100644 Runtime/Export/Serialization/FormerlySerializedAsAttribute.cs delete mode 100644 Runtime/Export/Serialization/IPPtrRemapper.cs delete mode 100644 Runtime/Export/Serialization/ISerializedNamedStateReader.cs delete mode 100644 Runtime/Export/Serialization/ISerializedNamedStateWriter.cs delete mode 100644 Runtime/Export/Serialization/ISerializedStateReader.cs delete mode 100644 Runtime/Export/Serialization/ISerializedStateWriter.cs delete mode 100644 Runtime/Export/Serialization/IUnitySerializable.cs delete mode 100644 Runtime/Export/Serialization/SerializedStateReader.cs delete mode 100644 Runtime/Export/Serialization/SerializedStateWriter.cs delete mode 100644 Runtime/Export/Serialization/UnitySurrogateSelector.cs delete mode 100644 Runtime/Export/Shader.bindings.cs delete mode 100644 Runtime/Export/Shader.cs delete mode 100644 Runtime/Export/StackTrace.cs delete mode 100644 Runtime/Export/StaticBatching/CombineForStaticBatching.cs delete mode 100644 Runtime/Export/StaticBatching/MeshSubsetCombineUtility.cs delete mode 100644 Runtime/Export/SystemClock.cs delete mode 100644 Runtime/Export/SystemInfo.bindings.cs delete mode 100644 Runtime/Export/Texture.bindings.cs delete mode 100644 Runtime/Export/Texture.cs delete mode 100644 Runtime/Export/Texture.deprecated.cs delete mode 100644 Runtime/Export/Time.bindings.cs delete mode 100644 Runtime/Export/Tizen/Tizen.bindings.cs delete mode 100644 Runtime/Export/TouchScreenKeyboardType.cs delete mode 100644 Runtime/Export/TrackedReference.cs delete mode 100644 Runtime/Export/UnityAPICompatibilityVersionAttribute.cs delete mode 100644 Runtime/Export/UnityEngineInternal/APIUpdaterRuntimeServices.cs delete mode 100644 Runtime/Export/UnityEngineInternal/TypeInferenceRuleAttribute.cs delete mode 100644 Runtime/Export/UnityEngineInternal/WrappedTypes.cs delete mode 100644 Runtime/Export/UnityEngineObject.bindings.cs delete mode 100644 Runtime/Export/UnityEvent.cs delete mode 100644 Runtime/Export/UnityEventQueueSystem.bindings.cs delete mode 100644 Runtime/Export/UnityEvent_0.cs delete mode 100644 Runtime/Export/UnityEvent_1.cs delete mode 100644 Runtime/Export/UnityEvent_2.cs delete mode 100644 Runtime/Export/UnityEvent_3.cs delete mode 100644 Runtime/Export/UnityEvent_4.cs delete mode 100644 Runtime/Export/UnityLogWriter.bindings.cs delete mode 100644 Runtime/Export/UnitySynchronizationContext.cs delete mode 100644 Runtime/Export/Unsafe/UnsafeUtility.bindings.cs delete mode 100644 Runtime/Export/Unsafe/UnsafeUtilityPatched.cs delete mode 100644 Runtime/Export/Vector2.cs delete mode 100644 Runtime/Export/Vector2Int.cs delete mode 100644 Runtime/Export/Vector3.cs delete mode 100644 Runtime/Export/Vector3Int.cs delete mode 100644 Runtime/Export/Vector4.cs delete mode 100644 Runtime/Export/WaitForEndOfFrame.cs delete mode 100644 Runtime/Export/WaitForFixedUpdate.cs delete mode 100644 Runtime/Export/WaitForSeconds.cs delete mode 100644 Runtime/Export/WaitForSecondsRealtime.cs delete mode 100644 Runtime/Export/WaitUntil.cs delete mode 100644 Runtime/Export/WaitWhile.cs delete mode 100644 Runtime/Export/WinRT/NetFxCoreExtensions.cs delete mode 100644 Runtime/Export/Windows/Speech.cs delete mode 100644 Runtime/Export/YieldOperation.cs delete mode 100644 Runtime/Export/iOS/OnDemandResources.bindings.cs delete mode 100644 Runtime/Export/iOS/TV.bindings.cs delete mode 100644 Runtime/Export/iOS/iOS.deprecated.cs delete mode 100644 Runtime/Export/iOS/iOSDevice.bindings.cs delete mode 100644 Runtime/Export/iOS/iOSNotifications.bindings.cs delete mode 100644 Runtime/Export/iOS/iOSReplayKit.bindings.cs delete mode 100644 Runtime/Export/iOSSystemGestureDeferMode.cs delete mode 100644 Runtime/Jobs/Managed/BatchQueries.cs delete mode 100644 Runtime/Jobs/Managed/IJob.cs delete mode 100644 Runtime/Jobs/Managed/IJobParallelFor.cs delete mode 100644 Runtime/Jobs/Managed/IJobParallelForTransform.cs delete mode 100644 Runtime/Jobs/ScriptBindings/JobHandle.bindings.cs delete mode 100644 Runtime/Jobs/ScriptBindings/Jobs.bindings.cs delete mode 100644 Runtime/Networking/Managed/MatchMakingClient.cs delete mode 100644 Runtime/Networking/Managed/NetworkTransport.cs delete mode 100644 Runtime/Networking/Managed/NetworkTransportConfig.cs delete mode 100644 Runtime/Networking/Managed/UNETInterface.cs delete mode 100644 Runtime/Networking/Managed/UNETTypes.cs delete mode 100644 Runtime/Networking/Managed/UNETWebSocketLib.cs delete mode 100644 Runtime/Networking/ScriptBindings/UNETworking.bindings.cs delete mode 100644 Runtime/ParticleSystem/Managed/ParticleSystem.deprecated.cs delete mode 100644 Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs delete mode 100644 Runtime/ParticleSystem/Managed/ParticleSystemRenderer.deprecated.cs delete mode 100644 Runtime/ParticleSystem/ScriptBindings/ParticleSystemRenderer.bindings.cs delete mode 100644 Runtime/Scripting/Marshalling/Test/MarshallingTests.bindings.cs delete mode 100644 Runtime/Scripting/Marshalling/Test/MarshallingTests2.bindings.cs delete mode 100644 Runtime/Scripting/ScriptedObjectTests.Resources.cs delete mode 100644 Runtime/StyleSheets/Managed/FriendAttributes.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleComplexSelector.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleProperty.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleRule.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleSelector.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleSelectorPart.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleSelectorRelationship.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleSelectorType.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleSheet.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleValueHandle.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleValueKeyword.cs delete mode 100644 Runtime/StyleSheets/Managed/StyleValueType.cs delete mode 100644 Runtime/TerrainPhysics/TerrainPhysics.bindings.cs delete mode 100644 Runtime/Transform/ScriptBindings/TransformAccessArray.bindings.cs delete mode 100644 Runtime/UI/ScriptBindings/RectTransformUtility.cs delete mode 100644 Runtime/VR/HoloLens/ScriptBindings/GestureRecognizer.cs delete mode 100644 Runtime/VR/HoloLens/ScriptBindings/GestureRecognizer.deprecated.cs delete mode 100644 Runtime/VR/HoloLens/ScriptBindings/GestureSource.cs delete mode 100644 Runtime/VR/HoloLens/ScriptBindings/GestureSource.deprecated.cs delete mode 100644 Runtime/VR/HoloLens/ScriptBindings/HolographicSettings.bindings.cs delete mode 100644 Runtime/VR/HoloLens/ScriptBindings/HolographicSettings.deprecated.cs delete mode 100644 Runtime/VR/HoloLens/ScriptBindings/SpatialMapping.cs delete mode 100644 Runtime/VR/HoloLens/ScriptBindings/TransformLock.cs delete mode 100644 Runtime/VR/HoloLens/ScriptBindings/WebCam.cs delete mode 100644 Runtime/VR/HoloLens/ScriptBindings/WorldManager.deprecated.cs delete mode 100644 Runtime/VR/ScriptBindings/InputTracking.cs delete mode 100644 Runtime/VR/ScriptBindings/VR.deprecated.cs delete mode 100644 Runtime/VR/ScriptBindings/VRNode.cs delete mode 100644 Runtime/VR/ScriptBindings/VRNode.deprecated.cs delete mode 100644 Runtime/VR/ScriptBindings/VRNodeState.cs delete mode 100644 Runtime/VR/ScriptBindings/VRNodeState.deprecated.cs delete mode 100644 Runtime/VR/ScriptBindings/XR.bindings.cs delete mode 100644 Runtime/Vehicles/Vehicles.bindings.cs delete mode 100644 Tools/PackageManager/DataContract/DataContract.csproj delete mode 100644 Tools/PackageManager/DataContract/IEditorModule.cs delete mode 100644 Tools/PackageManager/DataContract/PackageInfo.cs delete mode 100644 Tools/PackageManager/DataContract/PackageVersion.cs delete mode 100644 Tools/PackageManager/DataContract/Properties/AssemblyInfo.cs delete mode 100644 Tools/Unity.CecilTools/CecilUtils.cs delete mode 100644 Tools/Unity.CecilTools/ElementType.cs delete mode 100644 Tools/Unity.CecilTools/Extensions/MethodDefinitionExtensions.cs delete mode 100644 Tools/Unity.CecilTools/Extensions/ResolutionExtensions.cs delete mode 100644 Tools/Unity.CecilTools/Extensions/TypeDefinitionExtensions.cs delete mode 100644 Tools/Unity.CecilTools/Extensions/TypeReferenceExtensions.cs delete mode 100644 Tools/Unity.CecilTools/Properties/AssemblyInfo.cs delete mode 100644 Tools/Unity.CecilTools/Unity.CecilTools.csproj delete mode 100644 Tools/Unity.SerializationLogic/Properties/AssemblyInfo.cs delete mode 100644 Tools/Unity.SerializationLogic/Unity.SerializationLogic.csproj delete mode 100644 Tools/Unity.SerializationLogic/UnityEngineTypePredicates.cs delete mode 100644 Tools/Unity.SerializationLogic/UnitySerializationLogic.cs delete mode 100644 artifacts/generated/bindings_old/common/AI/NavMeshBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/AI/NavMeshObstacleBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/AI/NavMeshPathBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/AI/OffMeshLinkBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/AI/RuntimeNavMeshBuilderBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/AIEditor/NavMeshBuilderBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/AIEditor/NavMeshVisualizationSettingsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Animation/AnimationsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/AssetBundle/AssetBundleBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/AssetBundle/AssetBundleManifestBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Audio/AudioBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Audio/AudioMixerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Audio/AudioMixerGroupBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Audio/AudioMixerSnapshotBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Audio/MovieTextureBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Audio/UnityEngineWebCamTextureBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Cloth/ClothBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/AndroidInputBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/AndroidJNIBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/AndroidJavaBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/AppTrialBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/ApplicationBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/AsyncOperationBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/BehaviourBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/BillboardRendererBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/CachingBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/CameraBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/ColorUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/ComputeShaderBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/CrashReporterBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/CullingGroupBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/CursorBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/DisplayBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/DynamicGIBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/EventProviderBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/FlareLayerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/GIDebugVisualisationBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/GUIElementBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/GameObjectBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/GizmoBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/GradientBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/GradientUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/GraphicsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/HandheldBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/InputBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/LODBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/LayerMaskBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/LightBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/LightProbeBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/LightProbeProxyVolumeBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/LineUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/MathBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/NetworkingBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/PPtrRemapperBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/PlayerConnectionBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/PlayerConnectionInternalBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/PlayerPrefsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/ProfilerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/RecorderBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/RectTransformBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/ReflectionProbeBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/RenderingClassesBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/RenderingCommandBufferBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/ResourcesBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/RuntimeUndoBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SamplerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SceneBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SceneManagerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SceneUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/ScriptableRenderLoopBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SecurityPublicBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/ShaderBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SortingLayerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SpeechBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SphericalHarmonicsL2Bindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SplashScreenBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SpriteAtlasBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/SpritesBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/TextAssetBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/TextureBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/TransformBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/WSAApplicationBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/WSACursorBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/WSALauncherBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/WSATilesBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/WindowsCrashReportingBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/WindowsCryptoBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/WindowsDirectoryBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Core/WindowsFileBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/ActiveEditorTrackerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AnimationUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AnnotationUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AssetDatabaseBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AssetModificationProcessorBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AssetPostprocessorBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AssetPreviewBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AssetStoreBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AssetStoreContextBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AssetStoreToolUtilsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AssetStoreUtilsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AudioImporterBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AudioMixerControllerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AudioMixerDescriptionBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AudioMixerEffectControllerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AudioMixerGroupControllerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AudioMixerSnapshotControllerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/AudioUtilBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/BuildPipelineBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/CollabBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/ComponentUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/ContainerWindowBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/DragAndDropBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/DrawGizmoBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorApplicationBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorConnectionInternalBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorGUIBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorGUIUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorGraphicsSettingsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorHandlesBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorHandlesUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorJsonUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorMaterialUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorPrefsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorSceneManagerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorSettingsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorSpriteAtlasBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorUserSettingsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/EditorWindowBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/FrameDebuggerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/GUIViewBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/HardwareBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/HighlighterBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/InternalEditorUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/InternalUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/LODUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/LicenseManagementWindowBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/LightmapParametersBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/LightmappingBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/LogEntriesBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/MeshUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/MovieImporterBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/OSColorPickerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/ObjectNamesBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsAndroidBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsFacebookBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsIOSBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsN3DSBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsSplashScreenBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsSwitchBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsVRGoogleBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsWSABindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsWebGLBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PlayerSettingsXboxOneBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PolygonEditorBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PrefabsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/PreferencesWindowBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/ProfilerAPIBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/RegistryUtilBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/RenderDocBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/SavedGUIStateBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/ScriptReloadPropertiesBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/ScriptableWizardBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/SerializedPropertyBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/ShaderImporterBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/ShaderUtilBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/SpeedTreeImporterBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/SpritesEditorBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/StateMachineBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/TextureImporterBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/UndoBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/UnityConnectBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/UnityStatsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/UnsupportedBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/VCAssetBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/VCChangeSetBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/VCConflictItemBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/VCCustomCommandBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/VCMergeResultBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/VCMessageBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/VCPluginBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/VCTaskBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/VertexChannelCompressionFlagsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/VideoImporterBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/WebURLsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Editor/WebViewBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/IMGUI/EventBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/IMGUI/GUIBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/IMGUI/GUILayoutUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/IMGUI/GUISkinBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/IMGUI/GUIStyleBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/IMGUI/GUIUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/IMGUI/StylePainterBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/ImageConversion/ImageConversionBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/JSONSerialize/JsonUtilityBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/PerformanceReporting/PerformanceReportingBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Physics/DynamicsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/PhysicsEditor/ColliderUtilBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/PhysicsEditor/PhysicsDebugBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/RestService/RestServiceRequestBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/TextRendering/TextRenderingBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/TextRenderingEditor/TrueTypeFontImporterBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/UI/CanvasGroupBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/UI/CanvasRendererBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/UI/RectTransformUtilBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/UI/UICanvasBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/UIElements/CSSLayoutCallbacksBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/UNET/UNETworkingBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/UnityConnect/UnityAdsSettingsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/UnityConnect/UnityConnectSettingsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/VR/GestureBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/VR/GestureSourceBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/VR/HolographicSettingsBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/VR/SpatialMappingBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/VR/TransformLockBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/VR/VRBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/VR/VRTestBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/VR/WebCamBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/VR/WorldManagerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/VREditor/HolographicEmulationBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Video/VideoClipBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Video/VideoPlayerBindings.gen.cs delete mode 100644 artifacts/generated/bindings_old/common/Wind/WindZoneBindings.gen.cs delete mode 100644 third-party-notices.txt diff --git a/Editor/Mono/2D/Common/ScriptBindings/SpriteEditorExtension.bindings.cs b/Editor/Mono/2D/Common/ScriptBindings/SpriteEditorExtension.bindings.cs deleted file mode 100644 index d9f863d56a..0000000000 --- a/Editor/Mono/2D/Common/ScriptBindings/SpriteEditorExtension.bindings.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEngine.Bindings; - -namespace UnityEditor.Experimental.U2D -{ - [NativeHeader("Editor/Src/2D/SpriteEditorExtension.h")] - public static class SpriteEditorExtension - { - public static GUID GetSpriteID(this Sprite sprite) - { - return new GUID(GetSpriteIDScripting(sprite)); - } - - [FreeFunction("SpriteEditorExtension::GetSpriteIDScripting")] - private static extern string GetSpriteIDScripting(Sprite sprite); - } -} diff --git a/Editor/Mono/2D/Common/TexturePlatformSettingsController.cs b/Editor/Mono/2D/Common/TexturePlatformSettingsController.cs deleted file mode 100644 index df4aef1641..0000000000 --- a/Editor/Mono/2D/Common/TexturePlatformSettingsController.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEditor.U2D.Interface; -using UnityEngine; -using UnityEngine.Assertions; - -namespace UnityEditor.U2D.Common -{ - internal class TexturePlatformSettingsViewController : ITexturePlatformSettingsController - { - public bool HandleDefaultSettings(List platformSettings, ITexturePlatformSettingsView view) - { - Assert.IsTrue(platformSettings.Count > 0, "At least 1 platform setting is needed to display the texture platform setting UI."); - - int allSize = platformSettings[0].maxTextureSize; - TextureImporterCompression allCompression = platformSettings[0].textureCompression; - bool allUseCrunchedCompression = platformSettings[0].crunchedCompression; - int allCompressionQuality = platformSettings[0].compressionQuality; - - var newSize = allSize; - var newCompression = allCompression; - var newUseCrunchedCompression = allUseCrunchedCompression; - var newCompressionQuality = allCompressionQuality; - - bool mixedSize = false; - bool mixedCompression = false; - bool mixedUseCrunchedCompression = false; - bool mixedCompressionQuality = false; - - bool sizeChanged = false; - bool compressionChanged = false; - bool useCrunchedCompressionChanged = false; - bool compressionQualityChanged = false; - - for (var i = 1; i < platformSettings.Count; ++i) - { - var settings = platformSettings[i]; - if (settings.maxTextureSize != allSize) - mixedSize = true; - if (settings.textureCompression != allCompression) - mixedCompression = true; - if (settings.crunchedCompression != allUseCrunchedCompression) - mixedUseCrunchedCompression = true; - if (settings.compressionQuality != allCompressionQuality) - mixedCompressionQuality = true; - } - - newSize = view.DrawMaxSize(allSize, mixedSize, out sizeChanged); - newCompression = view.DrawCompression(allCompression, mixedCompression, out compressionChanged); - if (!mixedCompression && allCompression != TextureImporterCompression.Uncompressed) - { - newUseCrunchedCompression = view.DrawUseCrunchedCompression(allUseCrunchedCompression, mixedUseCrunchedCompression, out useCrunchedCompressionChanged); - - if (!mixedUseCrunchedCompression && allUseCrunchedCompression) - { - newCompressionQuality = view.DrawCompressionQualitySlider(allCompressionQuality, mixedCompressionQuality, out compressionQualityChanged); - } - } - - if (sizeChanged || compressionChanged || useCrunchedCompressionChanged || compressionQualityChanged) - { - for (var i = 0; i < platformSettings.Count; ++i) - { - if (sizeChanged) - platformSettings[i].maxTextureSize = newSize; - if (compressionChanged) - platformSettings[i].textureCompression = newCompression; - if (useCrunchedCompressionChanged) - platformSettings[i].crunchedCompression = newUseCrunchedCompression; - if (compressionQualityChanged) - platformSettings[i].compressionQuality = newCompressionQuality; - } - return true; - } - else - return false; - } - - public bool HandlePlatformSettings(BuildTarget buildTarget, List platformSettings, ITexturePlatformSettingsView view, ITexturePlatformSettingsFormatHelper formatHelper) - { - Assert.IsTrue(platformSettings.Count > 0, "At least 1 platform setting is needed to display the texture platform setting UI."); - - bool allOverride = platformSettings[0].overridden; - int allSize = platformSettings[0].maxTextureSize; - TextureImporterFormat allFormat = platformSettings[0].format; - int allCompressionQuality = platformSettings[0].compressionQuality; - - var newOverride = allOverride; - var newSize = allSize; - var newFormat = allFormat; - var newCompressionQuality = allCompressionQuality; - - bool mixedOverride = false; - bool mixedSize = false; - bool mixedFormat = false; - bool mixedCompression = false; - - bool overrideChanged = false; - bool sizeChanged = false; - bool formatChanged = false; - bool compressionChanged = false; - - for (var i = 1; i < platformSettings.Count; ++i) - { - var settings = platformSettings[i]; - if (settings.overridden != allOverride) - mixedOverride = true; - if (settings.maxTextureSize != allSize) - mixedSize = true; - if (settings.format != allFormat) - mixedFormat = true; - if (settings.compressionQuality != allCompressionQuality) - mixedCompression = true; - } - - newOverride = view.DrawOverride(allOverride, mixedOverride, out overrideChanged); - - if (!mixedOverride && allOverride) - { - newSize = view.DrawMaxSize(allSize, mixedSize, out sizeChanged); - } - - int[] formatValues = null; - string[] formatStrings = null; - formatHelper.AcquireTextureFormatValuesAndStrings(buildTarget, out formatValues, out formatStrings); - - newFormat = view.DrawFormat(allFormat, formatValues, formatStrings, mixedFormat, mixedOverride || !allOverride, out formatChanged); - - if (!mixedFormat && !mixedOverride && allOverride && formatHelper.TextureFormatRequireCompressionQualityInput(allFormat)) - { - bool showAsEnum = - buildTarget == BuildTarget.iOS || - buildTarget == BuildTarget.tvOS || - buildTarget == BuildTarget.Android || - buildTarget == BuildTarget.Tizen - ; - - if (showAsEnum) - { - int compressionMode = 1; - if (allCompressionQuality == (int)TextureCompressionQuality.Fast) - compressionMode = 0; - else if (allCompressionQuality == (int)TextureCompressionQuality.Best) - compressionMode = 2; - - var returnValue = view.DrawCompressionQualityPopup(compressionMode, mixedCompression, out compressionChanged); - - if (compressionChanged) - { - switch (returnValue) - { - case 0: newCompressionQuality = (int)TextureCompressionQuality.Fast; break; - case 1: newCompressionQuality = (int)TextureCompressionQuality.Normal; break; - case 2: newCompressionQuality = (int)TextureCompressionQuality.Best; break; - - default: - Assert.IsTrue(false, "ITexturePlatformSettingsView.DrawCompressionQualityPopup should never return compression option value that's not 0, 1 or 2."); - break; - } - } - } - else - { - newCompressionQuality = view.DrawCompressionQualitySlider(allCompressionQuality, mixedCompression, out compressionChanged); - } - } - - if (overrideChanged || sizeChanged || formatChanged || compressionChanged) - { - for (var i = 0; i < platformSettings.Count; ++i) - { - if (overrideChanged) - platformSettings[i].overridden = newOverride; - if (sizeChanged) - platformSettings[i].maxTextureSize = newSize; - if (formatChanged) - platformSettings[i].format = newFormat; - if (compressionChanged) - platformSettings[i].compressionQuality = newCompressionQuality; - } - - return true; - } - else - return false; - } - } -} diff --git a/Editor/Mono/2D/Common/TexturePlatformSettingsFormatHelper.cs b/Editor/Mono/2D/Common/TexturePlatformSettingsFormatHelper.cs deleted file mode 100644 index 4ab2e10277..0000000000 --- a/Editor/Mono/2D/Common/TexturePlatformSettingsFormatHelper.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.U2D.Interface; - -namespace UnityEditor.U2D.Common -{ - internal class TexturePlatformSettingsFormatHelper : ITexturePlatformSettingsFormatHelper - { - public void AcquireTextureFormatValuesAndStrings(BuildTarget buildTarget, out int[] formatValues, out string[] formatStrings) - { - if (TextureImporterInspector.IsGLESMobileTargetPlatform(buildTarget)) - { - if (buildTarget == BuildTarget.iOS || buildTarget == BuildTarget.tvOS) - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueApplePVR; - formatStrings = TextureImporterInspector.s_TextureFormatStringsApplePVR; - } - else - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueAndroid; - formatStrings = TextureImporterInspector.s_TextureFormatStringsAndroid; - } - } - else - { - if (buildTarget == BuildTarget.WebGL) - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueWebGL; - formatStrings = TextureImporterInspector.s_TextureFormatStringsWebGL; - } - else if (buildTarget == BuildTarget.PSP2) - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValuePSP2; - formatStrings = TextureImporterInspector.s_TextureFormatStringsPSP2; - } - else if (buildTarget == BuildTarget.Switch) - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueSwitch; - formatStrings = TextureImporterInspector.s_TextureFormatStringsSwitch; - } - else - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueDefault; - formatStrings = TextureImporterInspector.s_TextureFormatStringsDefault; - } - } - } - - public bool TextureFormatRequireCompressionQualityInput(TextureImporterFormat format) - { - return TextureImporterInspector.IsFormatRequireCompressionSetting(format); - } - } -} diff --git a/Editor/Mono/2D/Common/TexturePlatformSettingsView.cs b/Editor/Mono/2D/Common/TexturePlatformSettingsView.cs deleted file mode 100644 index 0c06650e20..0000000000 --- a/Editor/Mono/2D/Common/TexturePlatformSettingsView.cs +++ /dev/null @@ -1,137 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.U2D.Interface; - -namespace UnityEditor.U2D.Common -{ - internal class TexturePlatformSettingsView : ITexturePlatformSettingsView - { - class Styles - { - public readonly GUIContent textureFormatLabel = EditorGUIUtility.TrTextContent("Format"); - public readonly GUIContent maxTextureSizeLabel = EditorGUIUtility.TrTextContent("Max Texture Size", "Maximum size of the packed texture."); - public readonly GUIContent compressionLabel = EditorGUIUtility.TrTextContent("Compression", "How will this texture be compressed?"); - public readonly GUIContent useCrunchedCompressionLabel = EditorGUIUtility.TrTextContent("Use Crunch Compression", "Texture is crunch-compressed to save space on disk when applicable."); - public readonly GUIContent compressionQualityLabel = EditorGUIUtility.TrTextContent("Compressor Quality"); - public readonly GUIContent compressionQualitySliderLabel = EditorGUIUtility.TrTextContent("Compressor Quality", "Use the slider to adjust compression quality from 0 (Fastest) to 100 (Best)"); - - public readonly int[] kMaxTextureSizeValues = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; - public readonly GUIContent[] kMaxTextureSizeStrings; - - public readonly GUIContent[] kTextureCompressionOptions = - { - EditorGUIUtility.TrTextContent("None", "Texture is not compressed."), - EditorGUIUtility.TrTextContent("Low Quality", "Texture compressed with low quality but high performance, high compression format."), - EditorGUIUtility.TrTextContent("Normal Quality", "Texture is compressed with a standard format."), - EditorGUIUtility.TrTextContent("High Quality", "Texture compressed with a high quality format."), - }; - - public readonly int[] kTextureCompressionValues = - { - (int)TextureImporterCompression.Uncompressed, - (int)TextureImporterCompression.CompressedLQ, - (int)TextureImporterCompression.Compressed, - (int)TextureImporterCompression.CompressedHQ - }; - - public readonly GUIContent[] kMobileCompressionQualityOptions = - { - EditorGUIUtility.TrTextContent("Fast"), - EditorGUIUtility.TrTextContent("Normal"), - EditorGUIUtility.TrTextContent("Best") - }; - - public Styles() - { - kMaxTextureSizeStrings = new GUIContent[kMaxTextureSizeValues.Length]; - for (var i = 0; i < kMaxTextureSizeValues.Length; ++i) - kMaxTextureSizeStrings[i] = EditorGUIUtility.TextContent(string.Format("{0}", kMaxTextureSizeValues[i])); - } - } - - private static Styles s_Styles; - - public string buildPlatformTitle { get; set; } - - internal TexturePlatformSettingsView() - { - s_Styles = s_Styles ?? new Styles(); - } - - public virtual TextureImporterCompression DrawCompression(TextureImporterCompression defaultValue, bool isMixedValue, out bool changed) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = isMixedValue; - defaultValue = (TextureImporterCompression)EditorGUILayout.IntPopup(s_Styles.compressionLabel, (int)defaultValue, s_Styles.kTextureCompressionOptions, s_Styles.kTextureCompressionValues); - EditorGUI.showMixedValue = false; - changed = EditorGUI.EndChangeCheck(); - return defaultValue; - } - - public virtual bool DrawUseCrunchedCompression(bool defaultValue, bool isMixedValue, out bool changed) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = isMixedValue; - defaultValue = EditorGUILayout.Toggle(s_Styles.useCrunchedCompressionLabel, defaultValue); - EditorGUI.showMixedValue = false; - changed = EditorGUI.EndChangeCheck(); - return defaultValue; - } - - public virtual bool DrawOverride(bool defaultValue, bool isMixedValue, out bool changed) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = isMixedValue; - defaultValue = EditorGUILayout.ToggleLeft(EditorGUIUtility.TempContent("Override for " + buildPlatformTitle), defaultValue); - EditorGUI.showMixedValue = false; - changed = EditorGUI.EndChangeCheck(); - return defaultValue; - } - - public virtual int DrawMaxSize(int defaultValue, bool isMixedValue, out bool changed) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = isMixedValue; - defaultValue = EditorGUILayout.IntPopup(s_Styles.maxTextureSizeLabel, defaultValue, s_Styles.kMaxTextureSizeStrings, s_Styles.kMaxTextureSizeValues); - EditorGUI.showMixedValue = false; - changed = EditorGUI.EndChangeCheck(); - return defaultValue; - } - - public virtual TextureImporterFormat DrawFormat(TextureImporterFormat defaultValue, int[] displayValues, string[] displayStrings, bool isMixedValue, bool isDisabled, out bool changed) - { - using (new EditorGUI.DisabledScope(isDisabled)) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = isMixedValue; - defaultValue = (TextureImporterFormat)EditorGUILayout.IntPopup(s_Styles.textureFormatLabel, (int)defaultValue, EditorGUIUtility.TempContent(displayStrings), displayValues); - EditorGUI.showMixedValue = false; - changed = EditorGUI.EndChangeCheck(); - return defaultValue; - } - } - - public virtual int DrawCompressionQualityPopup(int defaultValue, bool isMixedValue, out bool changed) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = isMixedValue; - defaultValue = EditorGUILayout.Popup(s_Styles.compressionQualityLabel, defaultValue, s_Styles.kMobileCompressionQualityOptions); - EditorGUI.showMixedValue = false; - changed = EditorGUI.EndChangeCheck(); - return defaultValue; - } - - public virtual int DrawCompressionQualitySlider(int defaultValue, bool isMixedValue, out bool changed) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = isMixedValue; - defaultValue = EditorGUILayout.IntSlider(s_Styles.compressionQualitySliderLabel, defaultValue, 0, 100); - EditorGUI.showMixedValue = false; - changed = EditorGUI.EndChangeCheck(); - return defaultValue; - } - } -} diff --git a/Editor/Mono/2D/Interface/IAssetDatabase.cs b/Editor/Mono/2D/Interface/IAssetDatabase.cs deleted file mode 100644 index 60b0d4ec7f..0000000000 --- a/Editor/Mono/2D/Interface/IAssetDatabase.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor.U2D.Interface -{ - internal interface IAssetDatabase - { - string GetAssetPath(Object o); - AssetImporter GetAssetImporterFromPath(string path); - } - - internal class AssetDatabaseSystem : IAssetDatabase - { - public string GetAssetPath(Object o) - { - return UnityEditor.AssetDatabase.GetAssetPath(o); - } - - public AssetImporter GetAssetImporterFromPath(string path) - { - return UnityEditor.AssetImporter.GetAtPath(path); - } - } -} diff --git a/Editor/Mono/2D/Interface/IEvent.cs b/Editor/Mono/2D/Interface/IEvent.cs deleted file mode 100644 index 6db0d4c449..0000000000 --- a/Editor/Mono/2D/Interface/IEvent.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEvent = UnityEngine.Event; - -// We are putting this in the Editor folder for now since on SpriteEditorWindow et al. are using it -namespace UnityEngine.U2D.Interface -{ - internal interface IEvent - { - EventType type { get; } - string commandName { get; } - bool control { get; } - bool alt { get; } - bool shift { get; } - KeyCode keyCode { get; } - Vector2 mousePosition { get; } - int button { get; } - EventModifiers modifiers { get; } - EventType GetTypeForControl(int id); - - void Use(); - } - - internal class Event : IEvent - { - UnityEvent m_Event; - - public Event() - { - m_Event = UnityEvent.current; - } - - public EventType type - { - get { return m_Event.type; } - } - - public string commandName - { - get { return m_Event.commandName; } - } - - public bool control - { - get { return m_Event.control; } - } - - public bool alt - { - get { return m_Event.alt; } - } - - public bool shift - { - get { return m_Event.shift; } - } - - public KeyCode keyCode - { - get { return m_Event.keyCode; } - } - - public Vector2 mousePosition - { - get { return m_Event.mousePosition; } - } - - public int button - { - get { return m_Event.button; } - } - - public void Use() - { - m_Event.Use(); - } - - public EventModifiers modifiers - { - get { return m_Event.modifiers; } - } - - public EventType GetTypeForControl(int id) - { - return m_Event.GetTypeForControl(id); - } - } - - internal interface IEventSystem - { - IEvent current { get; } - } - - internal class EventSystem : IEventSystem - { - public IEvent current - { - get { return new Event(); } - } - } -} diff --git a/Editor/Mono/2D/Interface/IGL.cs b/Editor/Mono/2D/Interface/IGL.cs deleted file mode 100644 index a6e8726b8e..0000000000 --- a/Editor/Mono/2D/Interface/IGL.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEngine.U2D.Interface -{ - internal interface IGL - { - void PushMatrix(); - void PopMatrix(); - void MultMatrix(Matrix4x4 m); - void Begin(int mode); - void End(); - void Color(Color c); - void Vertex(Vector3 v); - } - - internal class GLSystem : IGL - { - static IGL m_GLSystem; - internal static void SetSystem(IGL system) - { - m_GLSystem = system; - } - - internal static IGL GetSystem() - { - if (m_GLSystem == null) - m_GLSystem = new GLSystem(); - return m_GLSystem; - } - - public void PushMatrix() - { - GL.PushMatrix(); - } - - public void PopMatrix() - { - GL.PopMatrix(); - } - - public void MultMatrix(Matrix4x4 m) - { - GL.MultMatrix(m); - } - - public void Begin(int mode) - { - GL.Begin(mode); - } - - public void End() - { - GL.End(); - } - - public void Color(Color c) - { - GL.Color(c); - } - - public void Vertex(Vector3 v) - { - GL.Vertex(v); - } - } -} diff --git a/Editor/Mono/2D/Interface/IGUIUtility.cs b/Editor/Mono/2D/Interface/IGUIUtility.cs deleted file mode 100644 index c5c0ee6eae..0000000000 --- a/Editor/Mono/2D/Interface/IGUIUtility.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEngine -{ - internal interface IGUIUtility - { - int GetPermanentControlID(); - int hotControl { get; set; } - int keyboardControl { get; set; } - int GetControlID(int hint, FocusType focus); - } - - internal class GUIUtilitySystem : IGUIUtility - { - public int GetPermanentControlID() - { - return GUIUtility.GetPermanentControlID(); - } - - public int hotControl - { - get - { - return GUIUtility.hotControl; - } - set - { - GUIUtility.hotControl = value; - } - } - - public int keyboardControl - { - get - { - return GUIUtility.keyboardControl; - } - set - { - GUIUtility.keyboardControl = value; - } - } - - public int GetControlID(int hint, FocusType focus) - { - return GUIUtility.GetControlID(hint, focus); - } - } -} diff --git a/Editor/Mono/2D/Interface/IHandles.cs b/Editor/Mono/2D/Interface/IHandles.cs deleted file mode 100644 index bb0cec37c1..0000000000 --- a/Editor/Mono/2D/Interface/IHandles.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityHandles = UnityEditor.Handles; -using UnityTexture2D = UnityEngine.Texture2D; -using UnityEngine.U2D.Interface; - -namespace UnityEditor.U2D.Interface -{ - internal interface IHandles - { - Color color { get; set; } - Matrix4x4 matrix { get; set; } - - Vector3[] MakeBezierPoints(Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent, int division); - - void DrawAAPolyLine(ITexture2D lineTex, float width, params Vector3[] points); - void DrawAAPolyLine(ITexture2D lineTex, params Vector3[] points); - - void DrawLine(Vector3 p1, Vector3 p2); - - void SetDiscSectionPoints(Vector3[] dest, Vector3 center, Vector3 normal, Vector3 from, float angle, float radius); - } - - internal class HandlesSystem : IHandles - { - static IHandles m_System; - - static public void SetSystem(IHandles system) - { - m_System = system; - } - - static public IHandles GetSystem() - { - if (m_System == null) - m_System = new HandlesSystem(); - return m_System; - } - - public Color color - { - get { return UnityHandles.color; } - set { UnityHandles.color = value; } - } - public Matrix4x4 matrix - { - get { return UnityHandles.matrix; } - set { UnityHandles.matrix = value; } - } - - public Vector3[] MakeBezierPoints(Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent, int division) - { - return UnityHandles.MakeBezierPoints(startPosition, endPosition, startTangent, endTangent, division); - } - - public void DrawAAPolyLine(ITexture2D lineTex, float width, params Vector3[] points) - { - UnityHandles.DrawAAPolyLine((UnityTexture2D)lineTex, width, points); - } - - public void DrawAAPolyLine(ITexture2D lineTex, params Vector3[] points) - { - UnityHandles.DrawAAPolyLine((UnityTexture2D)lineTex, points); - } - - public void DrawLine(Vector3 p1, Vector3 p2) - { - UnityHandles.DrawLine(p1, p2); - } - - public void SetDiscSectionPoints(Vector3[] dest, Vector3 center, Vector3 normal, Vector3 from, float angle, float radius) - { - UnityHandles.SetDiscSectionPoints(dest, center, normal, from, angle, radius); - } - } -} diff --git a/Editor/Mono/2D/Interface/ISpriteEditorDataProvider.cs b/Editor/Mono/2D/Interface/ISpriteEditorDataProvider.cs deleted file mode 100644 index 45f7f8acab..0000000000 --- a/Editor/Mono/2D/Interface/ISpriteEditorDataProvider.cs +++ /dev/null @@ -1,456 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; -using UnityEditor.U2D; -using UnityEngine.Experimental.U2D; -using UnityObject = UnityEngine.Object; - -namespace UnityEditor.Experimental.U2D -{ - public interface ISpriteEditorDataProvider - { - SpriteImportMode spriteImportMode { get; } - float pixelsPerUnit { get; } - UnityObject targetObject { get; } - - SpriteRect[] GetSpriteRects(); - void SetSpriteRects(SpriteRect[] spriteRects); - void Apply(); - void InitSpriteEditorDataProvider(); - - T GetDataProvider() where T : class; - bool HasDataProvider(Type type); - } - - public interface ISpriteBoneDataProvider - { - List GetBones(GUID guid); - void SetBones(GUID guid, List bones); - } - - public interface ISpriteOutlineDataProvider - { - List GetOutlines(GUID guid); - void SetOutlines(GUID guid, List data); - float GetTessellationDetail(GUID guid); - void SetTessellationDetail(GUID guid, float value); - } - - public interface ISpritePhysicsOutlineDataProvider - { - List GetOutlines(GUID guid); - void SetOutlines(GUID guid, List data); - float GetTessellationDetail(GUID guid); - void SetTessellationDetail(GUID guid, float value); - } - - public interface ITextureDataProvider - { - Texture2D texture { get; } - void GetTextureActualWidthAndHeight(out int width , out int height); - Texture2D GetReadableTexture2D(); - } - - internal class SpriteDataProviderBase - { - public SpriteDataProviderBase(TextureImporter dp) - { - dataProvider = dp; - } - - protected TextureImporter dataProvider { get; private set; } - } - - [Serializable] - public struct Vertex2DMetaData - { - public Vector2 position; - public BoneWeight boneWeight; - } - - public interface ISpriteMeshDataProvider - { - Vertex2DMetaData[] GetVertices(GUID guid); - void SetVertices(GUID guid, Vertex2DMetaData[] vertices); - int[] GetIndices(GUID guid); - void SetIndices(GUID guid, int[] indices); - Vector2Int[] GetEdges(GUID guid); - void SetEdges(GUID guid, Vector2Int[] edges); - } - - internal class SpriteBoneDataTransfer : SpriteDataProviderBase, ISpriteBoneDataProvider - { - public SpriteBoneDataTransfer(TextureImporter dp) : base(dp) - {} - - public List GetBones(GUID guid) - { - var index = dataProvider.GetSpriteDataIndex(guid); - return Load(new SerializedObject(dataProvider), dataProvider.spriteImportMode, index); - } - - public void SetBones(GUID guid, List bones) - { - ((SpriteDataExt)dataProvider.GetSpriteData(guid)).spriteBone = bones; - } - - private static List Load(SerializedObject importer, SpriteImportMode mode, int index) - { - var sp = mode == SpriteImportMode.Multiple ? - importer.FindProperty("m_SpriteSheet.m_Sprites").GetArrayElementAtIndex(index).FindPropertyRelative("m_Bones") : - importer.FindProperty("m_SpriteSheet.m_Bones"); - - var spriteBone = new List(sp.arraySize); - for (int i = 0; i < sp.arraySize; ++i) - { - var boneSO = sp.GetArrayElementAtIndex(i); - var sb = new SpriteBone(); - sb.length = boneSO.FindPropertyRelative("length").floatValue; - sb.position = boneSO.FindPropertyRelative("position").vector3Value; - sb.rotation = boneSO.FindPropertyRelative("rotation").quaternionValue; - sb.parentId = boneSO.FindPropertyRelative("parentId").intValue; - sb.name = boneSO.FindPropertyRelative("name").stringValue; - spriteBone.Add(sb); - } - return spriteBone; - } - - public static void Apply(SerializedProperty rectSP, List spriteBone) - { - var sp = rectSP.FindPropertyRelative("m_Bones"); - sp.arraySize = spriteBone.Count; - for (int i = 0; i < sp.arraySize; ++i) - { - var boneSO = sp.GetArrayElementAtIndex(i); - var sb = spriteBone[i]; - boneSO.FindPropertyRelative("length").floatValue = sb.length; - boneSO.FindPropertyRelative("position").vector3Value = sb.position; - boneSO.FindPropertyRelative("rotation").quaternionValue = sb.rotation; - boneSO.FindPropertyRelative("parentId").intValue = sb.parentId; - boneSO.FindPropertyRelative("name").stringValue = sb.name; - } - } - } - - internal class SpriteOutlineDataTransfer : SpriteDataProviderBase, ISpriteOutlineDataProvider - { - public SpriteOutlineDataTransfer(TextureImporter dp) : base(dp) - {} - - public List GetOutlines(GUID guid) - { - var index = dataProvider.GetSpriteDataIndex(guid); - return Load(new SerializedObject(dataProvider), dataProvider.spriteImportMode, index); - } - - public void SetOutlines(GUID guid, List data) - { - ((SpriteDataExt)dataProvider.GetSpriteData(guid)).spriteOutline = data; - } - - public float GetTessellationDetail(GUID guid) - { - return ((SpriteDataExt)dataProvider.GetSpriteData(guid)).tessellationDetail; - } - - public void SetTessellationDetail(GUID guid, float value) - { - ((SpriteDataExt)dataProvider.GetSpriteData(guid)).tessellationDetail = value; - } - - private static List Load(SerializedObject importer, SpriteImportMode mode, int index) - { - var outlineSP = mode == SpriteImportMode.Multiple ? - importer.FindProperty("m_SpriteSheet.m_Sprites").GetArrayElementAtIndex(index).FindPropertyRelative("m_Outline") : - importer.FindProperty("m_SpriteSheet.m_Outline"); - - var outline = new List(); - for (int j = 0; j < outlineSP.arraySize; ++j) - { - SerializedProperty outlinePathSP = outlineSP.GetArrayElementAtIndex(j); - var o = new Vector2[outlinePathSP.arraySize]; - for (int k = 0; k < outlinePathSP.arraySize; ++k) - { - o[k] = outlinePathSP.GetArrayElementAtIndex(k).vector2Value; - } - outline.Add(o); - } - return outline; - } - - public static void Apply(SerializedProperty rectSP, List outline) - { - var outlineSP = rectSP.FindPropertyRelative("m_Outline"); - outlineSP.ClearArray(); - for (int j = 0; j < outline.Count; ++j) - { - outlineSP.InsertArrayElementAtIndex(j); - var o = outline[j]; - SerializedProperty outlinePathSP = outlineSP.GetArrayElementAtIndex(j); - outlinePathSP.ClearArray(); - for (int k = 0; k < o.Length; ++k) - { - outlinePathSP.InsertArrayElementAtIndex(k); - outlinePathSP.GetArrayElementAtIndex(k).vector2Value = o[k]; - } - } - } - } - - internal class SpriteMeshDataTransfer : SpriteDataProviderBase, ISpriteMeshDataProvider - { - public SpriteMeshDataTransfer(TextureImporter dp) : base(dp) - {} - - public Vertex2DMetaData[] GetVertices(GUID guid) - { - var index = dataProvider.GetSpriteDataIndex(guid); - return LoadVertex2DMetaData(new SerializedObject(dataProvider), dataProvider.spriteImportMode, index); - } - - public void SetVertices(GUID guid, Vertex2DMetaData[] data) - { - ((SpriteDataExt)dataProvider.GetSpriteData(guid)).vertices = new List(data); - } - - public int[] GetIndices(GUID guid) - { - var index = dataProvider.GetSpriteDataIndex(guid); - return LoadIndices(new SerializedObject(dataProvider), dataProvider.spriteImportMode, index); - } - - public void SetIndices(GUID guid, int[] indices) - { - ((SpriteDataExt)dataProvider.GetSpriteData(guid)).indices = new List(indices); - } - - public Vector2Int[] GetEdges(GUID guid) - { - var index = dataProvider.GetSpriteDataIndex(guid); - return LoadEdges(new SerializedObject(dataProvider), dataProvider.spriteImportMode, index); - } - - public void SetEdges(GUID guid, Vector2Int[] edges) - { - ((SpriteDataExt)dataProvider.GetSpriteData(guid)).edges = new List(edges); - } - - private Vertex2DMetaData[] LoadVertex2DMetaData(SerializedObject importer, SpriteImportMode mode, int index) - { - var so = mode == SpriteImportMode.Multiple ? - importer.FindProperty("m_SpriteSheet.m_Sprites").GetArrayElementAtIndex(index) : - importer.FindProperty("m_SpriteSheet"); - - var verticesSP = so.FindPropertyRelative("m_Vertices"); - var weightsSP = so.FindPropertyRelative("m_Weights"); - - var vertices = new Vertex2DMetaData[verticesSP.arraySize]; - for (int i = 0; i < verticesSP.arraySize; ++i) - { - var vsp = verticesSP.GetArrayElementAtIndex(i); - var wsp = weightsSP.GetArrayElementAtIndex(i); - - vertices[i] = new Vertex2DMetaData - { - position = vsp.vector2Value, - boneWeight = new BoneWeight - { - weight0 = wsp.FindPropertyRelative("weight[0]").floatValue, - weight1 = wsp.FindPropertyRelative("weight[1]").floatValue, - weight2 = wsp.FindPropertyRelative("weight[2]").floatValue, - weight3 = wsp.FindPropertyRelative("weight[3]").floatValue, - boneIndex0 = wsp.FindPropertyRelative("boneIndex[0]").intValue, - boneIndex1 = wsp.FindPropertyRelative("boneIndex[1]").intValue, - boneIndex2 = wsp.FindPropertyRelative("boneIndex[2]").intValue, - boneIndex3 = wsp.FindPropertyRelative("boneIndex[3]").intValue - } - }; - } - - return vertices; - } - - private int[] LoadIndices(SerializedObject importer, SpriteImportMode mode, int index) - { - var so = mode == SpriteImportMode.Multiple ? - importer.FindProperty("m_SpriteSheet.m_Sprites").GetArrayElementAtIndex(index) : - importer.FindProperty("m_SpriteSheet"); - - var indicesSP = so.FindPropertyRelative("m_Indices"); - - var indices = new int[indicesSP.arraySize]; - for (int i = 0; i < indicesSP.arraySize; ++i) - { - indices[i] = indicesSP.GetArrayElementAtIndex(i).intValue; - } - - return indices; - } - - private Vector2Int[] LoadEdges(SerializedObject importer, SpriteImportMode mode, int index) - { - var so = mode == SpriteImportMode.Multiple ? - importer.FindProperty("m_SpriteSheet.m_Sprites").GetArrayElementAtIndex(index) : - importer.FindProperty("m_SpriteSheet"); - - var edgesSP = so.FindPropertyRelative("m_Edges"); - - var edges = new Vector2Int[edgesSP.arraySize]; - for (int i = 0; i < edgesSP.arraySize; ++i) - { - edges[i] = edgesSP.GetArrayElementAtIndex(i).vector2IntValue; - } - - return edges; - } - - public static void Apply(SerializedProperty rectSP, List vertices, List indices, List edges) - { - var verticesSP = rectSP.FindPropertyRelative("m_Vertices"); - var weightsSP = rectSP.FindPropertyRelative("m_Weights"); - var indicesSP = rectSP.FindPropertyRelative("m_Indices"); - var edgesSP = rectSP.FindPropertyRelative("m_Edges"); - - verticesSP.arraySize = vertices.Count; - weightsSP.arraySize = vertices.Count; - - for (int i = 0; i < vertices.Count; ++i) - { - var vsp = verticesSP.GetArrayElementAtIndex(i); - var wsp = weightsSP.GetArrayElementAtIndex(i); - - vsp.vector2Value = vertices[i].position; - wsp.FindPropertyRelative("weight[0]").floatValue = vertices[i].boneWeight.weight0; - wsp.FindPropertyRelative("weight[1]").floatValue = vertices[i].boneWeight.weight1; - wsp.FindPropertyRelative("weight[2]").floatValue = vertices[i].boneWeight.weight2; - wsp.FindPropertyRelative("weight[3]").floatValue = vertices[i].boneWeight.weight3; - wsp.FindPropertyRelative("boneIndex[0]").intValue = vertices[i].boneWeight.boneIndex0; - wsp.FindPropertyRelative("boneIndex[1]").intValue = vertices[i].boneWeight.boneIndex1; - wsp.FindPropertyRelative("boneIndex[2]").intValue = vertices[i].boneWeight.boneIndex2; - wsp.FindPropertyRelative("boneIndex[3]").intValue = vertices[i].boneWeight.boneIndex3; - } - - indicesSP.arraySize = indices.Count; - - for (int i = 0; i < indices.Count; ++i) - { - indicesSP.GetArrayElementAtIndex(i).intValue = indices[i]; - } - - edgesSP.arraySize = edges.Count; - - for (int i = 0; i < edges.Count; ++i) - { - edgesSP.GetArrayElementAtIndex(i).vector2IntValue = edges[i]; - } - } - } - - internal class SpritePhysicsOutlineDataTransfer : SpriteDataProviderBase, ISpritePhysicsOutlineDataProvider - { - public SpritePhysicsOutlineDataTransfer(TextureImporter dp) : base(dp) - {} - - public List GetOutlines(GUID guid) - { - var index = dataProvider.GetSpriteDataIndex(guid); - return Load(new SerializedObject(dataProvider), dataProvider.spriteImportMode, index); - } - - public void SetOutlines(GUID guid, List data) - { - ((SpriteDataExt)dataProvider.GetSpriteData(guid)).spritePhysicsOutline = data; - } - - public float GetTessellationDetail(GUID guid) - { - return ((SpriteDataExt)dataProvider.GetSpriteData(guid)).tessellationDetail; - } - - public void SetTessellationDetail(GUID guid, float value) - { - ((SpriteDataExt)dataProvider.GetSpriteData(guid)).tessellationDetail = value; - } - - private static List Load(SerializedObject importer, SpriteImportMode mode, int index) - { - var outlineSP = mode == SpriteImportMode.Multiple ? - importer.FindProperty("m_SpriteSheet.m_Sprites").GetArrayElementAtIndex(index).FindPropertyRelative("m_PhysicsShape") : - importer.FindProperty("m_SpriteSheet.m_PhysicsShape"); - - var outline = new List(); - for (int j = 0; j < outlineSP.arraySize; ++j) - { - SerializedProperty outlinePathSP = outlineSP.GetArrayElementAtIndex(j); - var o = new Vector2[outlinePathSP.arraySize]; - for (int k = 0; k < outlinePathSP.arraySize; ++k) - { - o[k] = outlinePathSP.GetArrayElementAtIndex(k).vector2Value; - } - outline.Add(o); - } - return outline; - } - - public static void Apply(SerializedProperty rectSP, List value) - { - var outlineSP = rectSP.FindPropertyRelative("m_PhysicsShape"); - outlineSP.ClearArray(); - for (int j = 0; j < value.Count; ++j) - { - outlineSP.InsertArrayElementAtIndex(j); - var o = value[j]; - SerializedProperty outlinePathSP = outlineSP.GetArrayElementAtIndex(j); - outlinePathSP.ClearArray(); - for (int k = 0; k < o.Length; ++k) - { - outlinePathSP.InsertArrayElementAtIndex(k); - outlinePathSP.GetArrayElementAtIndex(k).vector2Value = o[k]; - } - } - } - } - - internal class SpriteTextureDataTransfer : SpriteDataProviderBase, ITextureDataProvider - { - public SpriteTextureDataTransfer(TextureImporter dp) : base(dp) - {} - - Texture2D m_ReadableTexture; - Texture2D m_OriginalTexture; - - public Texture2D texture - { - get - { - if (m_OriginalTexture == null) - m_OriginalTexture = AssetDatabase.LoadAssetAtPath(dataProvider.assetPath); - return m_OriginalTexture; - } - } - - public void GetTextureActualWidthAndHeight(out int width, out int height) - { - width = height = 0; - dataProvider.GetWidthAndHeight(ref width, ref height); - } - - public Texture2D GetReadableTexture2D() - { - if (m_ReadableTexture == null) - { - int width = 0, height = 0; - GetTextureActualWidthAndHeight(out width, out height); - m_ReadableTexture = UnityEditor.SpriteUtility.CreateTemporaryDuplicate(texture, width, height); - if (m_ReadableTexture != null) - m_ReadableTexture.filterMode = texture.filterMode; - } - return m_ReadableTexture; - } - } -} diff --git a/Editor/Mono/2D/Interface/ITexture.cs b/Editor/Mono/2D/Interface/ITexture.cs deleted file mode 100644 index 41f09c6733..0000000000 --- a/Editor/Mono/2D/Interface/ITexture.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityTexture2D = UnityEngine.Texture2D; -using System; - -// We are putting this in the Editor folder for now since on SpriteEditorWindow et al. are using it -namespace UnityEngine.U2D.Interface -{ - internal abstract class ITexture2D - { - abstract public int width { get; } - abstract public int height { get; } - abstract public TextureFormat format { get; } - abstract public Color32[] GetPixels32(); - abstract public FilterMode filterMode { get; set; } - abstract public string name { get; } - abstract public void SetPixels(Color[] c); - abstract public void Apply(); - abstract public float mipMapBias { get; } - - public static bool operator==(ITexture2D t1, ITexture2D t2) - { - if (object.ReferenceEquals(t1, null)) - { - return object.ReferenceEquals(t2, null) || t2 == null; - } - - return t1.Equals(t2); - } - - public static bool operator!=(ITexture2D t1, ITexture2D t2) - { - if (object.ReferenceEquals(t1, null)) - { - return !object.ReferenceEquals(t2, null) && t2 != null; - } - - return !t1.Equals(t2); - } - - override public bool Equals(object other) - { - throw new NotImplementedException(); - } - - override public int GetHashCode() - { - throw new NotImplementedException(); - } - - public static implicit operator UnityEngine.Object(ITexture2D t) - { - return object.ReferenceEquals(t, null) ? null : t.ToUnityObject(); - } - - public static implicit operator UnityEngine.Texture2D(ITexture2D t) - { - return object.ReferenceEquals(t, null) ? null : t.ToUnityTexture(); - } - - abstract protected UnityEngine.Object ToUnityObject(); - abstract protected UnityEngine.Texture2D ToUnityTexture(); - } - - internal class Texture2D : ITexture2D - { - UnityTexture2D m_Texture; - - public Texture2D(UnityTexture2D texture) - { - m_Texture = texture; - } - - override public int width - { - get { return m_Texture.width; } - } - - override public int height - { - get { return m_Texture.height; } - } - - override public TextureFormat format - { - get { return m_Texture.format; } - } - - override public Color32[] GetPixels32() - { - return m_Texture.GetPixels32(); - } - - override public FilterMode filterMode - { - get { return m_Texture.filterMode; } - set { m_Texture.filterMode = value; } - } - - override public float mipMapBias - { - get { return m_Texture.mipMapBias; } - } - - override public string name - { - get { return m_Texture.name; } - } - - public override bool Equals(object other) - { - Texture2D t = other as Texture2D; - if (object.ReferenceEquals(t, null)) - return m_Texture == null; - return m_Texture == t.m_Texture; - } - - public override int GetHashCode() - { - return m_Texture.GetHashCode(); - } - - public override void SetPixels(Color[] c) - { - m_Texture.SetPixels(c); - } - - public override void Apply() - { - m_Texture.Apply(); - } - - override protected UnityEngine.Object ToUnityObject() - { - return m_Texture; - } - - override protected UnityEngine.Texture2D ToUnityTexture() - { - return m_Texture; - } - } -} diff --git a/Editor/Mono/2D/Interface/ITexturePlatformSetting.cs b/Editor/Mono/2D/Interface/ITexturePlatformSetting.cs deleted file mode 100644 index 5b3a6fb72e..0000000000 --- a/Editor/Mono/2D/Interface/ITexturePlatformSetting.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor.U2D.Interface -{ - internal interface ITexturePlatformSettingsView - { - string buildPlatformTitle { get; set; } - TextureImporterCompression DrawCompression(TextureImporterCompression defaultValue, bool isMixedValue, out bool changed); - bool DrawUseCrunchedCompression(bool defaultValue, bool isMixedValue, out bool changed); - bool DrawOverride(bool defaultValue, bool isMixedValue, out bool changed); - int DrawMaxSize(int defaultValue, bool isMixedValue, out bool changed); - TextureImporterFormat DrawFormat(TextureImporterFormat defaultValue, int[] displayValues, string[] displayStrings, bool isMixedValue, bool isDisabled, out bool changed); - int DrawCompressionQualityPopup(int defaultValue, bool isMixedValue, out bool changed); - int DrawCompressionQualitySlider(int defaultValue, bool isMixedValue, out bool changed); - } - - internal interface ITexturePlatformSettingsFormatHelper - { - void AcquireTextureFormatValuesAndStrings(BuildTarget buildTarget, out int[] displayValues, out string[] displayStrings); - - bool TextureFormatRequireCompressionQualityInput(TextureImporterFormat format); - } - - internal interface ITexturePlatformSettingsController - { - bool HandleDefaultSettings(List platformSettings, ITexturePlatformSettingsView view); - bool HandlePlatformSettings(BuildTarget buildTarget, List platformSettings, ITexturePlatformSettingsView view, ITexturePlatformSettingsFormatHelper formatHelper); - } -} diff --git a/Editor/Mono/2D/Interface/IUndoSystem.cs b/Editor/Mono/2D/Interface/IUndoSystem.cs deleted file mode 100644 index 1cc598e095..0000000000 --- a/Editor/Mono/2D/Interface/IUndoSystem.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor.U2D.Interface -{ - internal interface IUndoSystem - { - void RegisterUndoCallback(Undo.UndoRedoCallback undoCallback); - void UnregisterUndoCallback(Undo.UndoRedoCallback undoCallback); - void RegisterCompleteObjectUndo(ScriptableObject obj, string undoText); - void ClearUndo(ScriptableObject obj); - } - - internal class UndoSystem : IUndoSystem - { - public void RegisterUndoCallback(Undo.UndoRedoCallback undoCallback) - { - Undo.undoRedoPerformed += undoCallback; - } - - public void UnregisterUndoCallback(Undo.UndoRedoCallback undoCallback) - { - Undo.undoRedoPerformed -= undoCallback; - } - - public void RegisterCompleteObjectUndo(ScriptableObject so, string undoText) - { - if (so != null) - { - Undo.RegisterCompleteObjectUndo(so, undoText); - } - } - - public void ClearUndo(ScriptableObject so) - { - if (so != null) - { - Undo.ClearUndo(so); - } - } - } -} diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs deleted file mode 100644 index 3c44628970..0000000000 --- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs +++ /dev/null @@ -1,671 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.U2D; -using UnityEditor.Build; -using UnityEditor.U2D.Common; -using UnityEditor.U2D.Interface; -using UnityEditorInternal; - -namespace UnityEditor.U2D -{ - [CustomEditor(typeof(SpriteAtlas))] - [CanEditMultipleObjects] - internal class SpriteAtlasInspector : Editor - { - class SpriteAtlasInspectorPlatformSettingView : TexturePlatformSettingsView - { - private bool m_ShowMaxSizeOption; - - public SpriteAtlasInspectorPlatformSettingView(bool showMaxSizeOption) - { - m_ShowMaxSizeOption = showMaxSizeOption; - } - - public override int DrawMaxSize(int defaultValue, bool isMixedValue, out bool changed) - { - if (m_ShowMaxSizeOption) - return base.DrawMaxSize(defaultValue, isMixedValue, out changed); - else - changed = false; - return defaultValue; - } - } - - class Styles - { - public readonly GUIStyle dropzoneStyle = new GUIStyle("BoldLabel"); - public readonly GUIStyle preDropDown = "preDropDown"; - public readonly GUIStyle previewButton = "preButton"; - public readonly GUIStyle previewSlider = "preSlider"; - public readonly GUIStyle previewSliderThumb = "preSliderThumb"; - public readonly GUIStyle previewLabel = new GUIStyle("preLabel"); - - public readonly GUIContent textureSettingLabel = EditorGUIUtility.TrTextContent("Texture"); - public readonly GUIContent variantSettingLabel = EditorGUIUtility.TrTextContent("Variant"); - public readonly GUIContent packingParametersLabel = EditorGUIUtility.TrTextContent("Packing"); - public readonly GUIContent atlasTypeLabel = EditorGUIUtility.TrTextContent("Type"); - public readonly GUIContent defaultPlatformLabel = EditorGUIUtility.TrTextContent("Default"); - public readonly GUIContent masterAtlasLabel = EditorGUIUtility.TrTextContent("Master Atlas", "Assigning another Sprite Atlas asset will make this atlas a variant of it."); - public readonly GUIContent bindAsDefaultLabel = EditorGUIUtility.TrTextContent("Include in Build", "Packed textures will be included in the build by default."); - public readonly GUIContent enableRotationLabel = EditorGUIUtility.TrTextContent("Allow Rotation", "Try rotating the sprite to fit better during packing."); - public readonly GUIContent enableTightPackingLabel = EditorGUIUtility.TrTextContent("Tight Packing", "Use the mesh outline to fit instead of the whole texture rect during packing."); - public readonly GUIContent paddingLabel = EditorGUIUtility.TrTextContent("Padding", "The amount of extra padding between packed sprites."); - - public readonly GUIContent generateMipMapLabel = EditorGUIUtility.TrTextContent("Generate Mip Maps"); - public readonly GUIContent sRGBLabel = EditorGUIUtility.TrTextContent("sRGB", "Texture content is stored in gamma space."); - public readonly GUIContent readWrite = EditorGUIUtility.TrTextContent("Read/Write Enabled", "Enable to be able to access the raw pixel data from code."); - public readonly GUIContent variantMultiplierLabel = EditorGUIUtility.TrTextContent("Scale", "Down scale ratio."); - public readonly GUIContent copyMasterButton = EditorGUIUtility.TrTextContent("Copy Master's Settings", "Copy all master's settings into this variant."); - public readonly GUIContent packButton = EditorGUIUtility.TrTextContent("Pack Preview", "Pack this atlas."); - public readonly GUIContent disabledPackLabel = EditorGUIUtility.TrTextContent("Sprite Atlas packing is disabled. Enable it in Edit > Project Settings > Editor."); - public readonly GUIContent packableListLabel = EditorGUIUtility.TrTextContent("Objects for Packing", "Only accept Folder, Sprite Sheet(Texture) and Sprite."); - - public readonly GUIContent notPowerOfTwoWarning = EditorGUIUtility.TrTextContent("This scale will produce a Sprite Atlas variant with a packed texture that is NPOT (non - power of two). This may cause visual artifacts in certain compression/texture formats."); - - public readonly GUIContent smallZoom = EditorGUIUtility.IconContent("PreTextureMipMapLow"); - public readonly GUIContent largeZoom = EditorGUIUtility.IconContent("PreTextureMipMapHigh"); - public readonly GUIContent alphaIcon = EditorGUIUtility.IconContent("PreTextureAlpha"); - public readonly GUIContent RGBIcon = EditorGUIUtility.IconContent("PreTextureRGB"); - - public readonly int packableElementHash = "PackableElement".GetHashCode(); - public readonly int packableSelectorHash = "PackableSelector".GetHashCode(); - - public readonly int[] atlasTypeValues = { 0, 1 }; - public readonly GUIContent[] atlasTypeOptions = - { - EditorGUIUtility.TrTextContent("Master"), - EditorGUIUtility.TrTextContent("Variant"), - }; - - public readonly int[] paddingValues = { 2, 4, 8 }; - public readonly GUIContent[] paddingOptions; - - public Styles() - { - dropzoneStyle.alignment = TextAnchor.MiddleCenter; - dropzoneStyle.border = new RectOffset(10, 10, 10, 10); - - paddingOptions = new GUIContent[paddingValues.Length]; - for (var i = 0; i < paddingValues.Length; ++i) - paddingOptions[i] = EditorGUIUtility.TextContent(paddingValues[i].ToString()); - } - } - - private static Styles s_Styles; - - private readonly string kDefaultPlatformName = "default"; - - private enum AtlasType { Undefined = -1, Master = 0, Variant = 1 } - - private SerializedProperty m_MaxTextureSize; - private SerializedProperty m_TextureCompression; - private SerializedProperty m_UseCrunchedCompression; - private SerializedProperty m_CompressionQuality; - private SerializedProperty m_FilterMode; - private SerializedProperty m_AnisoLevel; - private SerializedProperty m_GenerateMipMaps; - private SerializedProperty m_Readable; - private SerializedProperty m_UseSRGB; - private SerializedProperty m_EnableTightPacking; - private SerializedProperty m_EnableRotation; - private SerializedProperty m_Padding; - private SerializedProperty m_BindAsDefault; - private SerializedProperty m_Packables; - - private SerializedProperty m_MasterAtlas; - private SerializedProperty m_VariantMultiplier; - - private string m_Hash; - private int m_PreviewPage = 0; - private int m_TotalPages = 0; - private int[] m_OptionValues = null; - private string[] m_OptionDisplays = null; - private Texture2D[] m_PreviewTextures = null; - - private bool m_PackableListExpanded = true; - private ReorderableList m_PackableList; - - private float m_MipLevel = 0; - private bool m_ShowAlpha; - - private List m_ValidPlatforms; - private Dictionary> m_TempPlatformSettings; - - private ITexturePlatformSettingsView m_TexturePlatformSettingsView; - private ITexturePlatformSettingsFormatHelper m_TexturePlatformSettingTextureHelper; - private ITexturePlatformSettingsController m_TexturePlatformSettingsController; - - private SpriteAtlas spriteAtlas { get { return target as SpriteAtlas; } } - - static bool IsPackable(Object o) - { - return o != null && (o.GetType() == typeof(Sprite) || o.GetType() == typeof(Texture2D) || (o.GetType() == typeof(DefaultAsset) && ProjectWindowUtil.IsFolder(o.GetInstanceID()))); - } - - static Object ValidateObjectForPackableFieldAssignment(Object[] references, System.Type objType, SerializedProperty property, EditorGUI.ObjectFieldValidatorOptions options) - { - // We only validate and care about the first one as this is a object field assignment. - if (references.Length > 0 && IsPackable(references[0])) - return references[0]; - return null; - } - - bool AllTargetsAreVariant() - { - foreach (SpriteAtlas sa in targets) - { - if (!sa.isVariant) - return false; - } - return true; - } - - bool AllTargetsAreMaster() - { - foreach (SpriteAtlas sa in targets) - { - if (sa.isVariant) - return false; - } - return true; - } - - void OnEnable() - { - m_MaxTextureSize = serializedObject.FindProperty("m_EditorData.textureSettings.maxTextureSize"); - m_TextureCompression = serializedObject.FindProperty("m_EditorData.textureSettings.textureCompression"); - m_UseCrunchedCompression = serializedObject.FindProperty("m_EditorData.textureSettings.crunchedCompression"); - m_CompressionQuality = serializedObject.FindProperty("m_EditorData.textureSettings.compressionQuality"); - m_FilterMode = serializedObject.FindProperty("m_EditorData.textureSettings.filterMode"); - m_AnisoLevel = serializedObject.FindProperty("m_EditorData.textureSettings.anisoLevel"); - m_GenerateMipMaps = serializedObject.FindProperty("m_EditorData.textureSettings.generateMipMaps"); - m_Readable = serializedObject.FindProperty("m_EditorData.textureSettings.readable"); - m_UseSRGB = serializedObject.FindProperty("m_EditorData.textureSettings.sRGB"); - - m_EnableTightPacking = serializedObject.FindProperty("m_EditorData.packingParameters.enableTightPacking"); - m_EnableRotation = serializedObject.FindProperty("m_EditorData.packingParameters.enableRotation"); - m_Padding = serializedObject.FindProperty("m_EditorData.packingParameters.padding"); - - m_MasterAtlas = serializedObject.FindProperty("m_MasterAtlas"); - m_BindAsDefault = serializedObject.FindProperty("m_EditorData.bindAsDefault"); - m_VariantMultiplier = serializedObject.FindProperty("m_EditorData.variantMultiplier"); - - m_Packables = serializedObject.FindProperty("m_EditorData.packables"); - m_PackableList = new ReorderableList(serializedObject, m_Packables, true, true, true, true); - m_PackableList.onAddCallback = AddPackable; - m_PackableList.onRemoveCallback = RemovePackable; - m_PackableList.drawElementCallback = DrawPackableElement; - m_PackableList.elementHeight = EditorGUIUtility.singleLineHeight; - m_PackableList.headerHeight = 0f; - - SyncPlatformSettings(); - - // Initialise texture importer's texture format strings - TextureImporterInspector.InitializeTextureFormatStrings(); - - m_TexturePlatformSettingsView = new SpriteAtlasInspectorPlatformSettingView(AllTargetsAreMaster()); - m_TexturePlatformSettingTextureHelper = new TexturePlatformSettingsFormatHelper(); - m_TexturePlatformSettingsController = new TexturePlatformSettingsViewController(); - } - - void SyncPlatformSettings() - { - m_TempPlatformSettings = new Dictionary>(); - - // Default platform - var defaultSettings = new List(); - m_TempPlatformSettings.Add(kDefaultPlatformName, defaultSettings); - foreach (var t in targets) - { - TextureImporterPlatformSettings settings = new TextureImporterPlatformSettings(); - settings.name = kDefaultPlatformName; - - SerializedObject targetSerializedObject = new SerializedObject(t); - settings.maxTextureSize = targetSerializedObject.FindProperty("m_EditorData.textureSettings.maxTextureSize").intValue; - settings.textureCompression = (TextureImporterCompression)targetSerializedObject.FindProperty("m_EditorData.textureSettings.textureCompression").enumValueIndex; - settings.crunchedCompression = targetSerializedObject.FindProperty("m_EditorData.textureSettings.crunchedCompression").boolValue; - settings.compressionQuality = targetSerializedObject.FindProperty("m_EditorData.textureSettings.compressionQuality").intValue; - - defaultSettings.Add(settings); - } - - m_ValidPlatforms = BuildPlatforms.instance.GetValidPlatforms(); - foreach (var platform in m_ValidPlatforms) - { - var platformSettings = new List(); - m_TempPlatformSettings.Add(platform.name, platformSettings); - foreach (SpriteAtlas sa in targets) - { - TextureImporterPlatformSettings settings = new TextureImporterPlatformSettings(); - settings.name = platform.name; - sa.CopyPlatformSettingsIfAvailable(platform.name, settings); - - // setting will be in default state if copy failed - platformSettings.Add(settings); - } - } - } - - void AddPackable(ReorderableList list) - { - ObjectSelector.get.Show(null, typeof(Object), null, false); - ObjectSelector.get.searchFilter = "t:sprite t:texture2d t:folder"; - ObjectSelector.get.objectSelectorID = s_Styles.packableSelectorHash; - } - - void RemovePackable(ReorderableList list) - { - var index = list.index; - if (index != -1) - spriteAtlas.RemoveAt(index); - } - - void DrawPackableElement(Rect rect, int index, bool selected, bool focused) - { - var property = m_Packables.GetArrayElementAtIndex(index); - var controlID = EditorGUIUtility.GetControlID(s_Styles.packableElementHash, FocusType.Passive); - var previousObject = property.objectReferenceValue; - - EditorGUI.BeginChangeCheck(); - var changedObject = EditorGUI.DoObjectField(rect, rect, controlID, previousObject, typeof(Object), null, ValidateObjectForPackableFieldAssignment, false); - if (EditorGUI.EndChangeCheck()) - { - // Always call Remove() on the previous object if we swapping the object field item. - // This ensure the Sprites was pack in this atlas will be refreshed of it unbound. - if (previousObject != null) - spriteAtlas.Remove(new Object[] { previousObject }); - property.objectReferenceValue = changedObject; - } - - if (GUIUtility.keyboardControl == controlID && !selected) - m_PackableList.index = index; - } - - public override void OnInspectorGUI() - { - s_Styles = s_Styles ?? new Styles(); - - serializedObject.Update(); - - HandleCommonSettingUI(); - - GUILayout.Space(EditorGUI.kSpacing); - - if (AllTargetsAreVariant()) - HandleVariantSettingUI(); - else if (AllTargetsAreMaster()) - HandleMasterSettingUI(); - - GUILayout.Space(EditorGUI.kSpacing); - - HandleTextureSettingUI(); - - GUILayout.Space(EditorGUI.kSpacing); - - // Only show the packable object list when: - // - This is a master atlas. - // - It is not currently selecting multiple atlases. - if (targets.Length == 1 && AllTargetsAreMaster()) - HandlePackableListUI(); - - bool spriteAtlasPackignEnabled = (EditorSettings.spritePackerMode == SpritePackerMode.BuildTimeOnlyAtlas - || EditorSettings.spritePackerMode == SpritePackerMode.AlwaysOnAtlas); - if (spriteAtlasPackignEnabled) - { - if (GUILayout.Button(s_Styles.packButton, GUILayout.ExpandWidth(false))) - { - SpriteAtlas[] spriteAtlases = new SpriteAtlas[targets.Length]; - for (int i = 0; i < spriteAtlases.Length; ++i) - spriteAtlases[i] = (SpriteAtlas)targets[i]; - - SpriteAtlasUtility.PackAtlases(spriteAtlases, EditorUserBuildSettings.activeBuildTarget); - - // Packing an atlas might change platform settings in the process, reinitialize - SyncPlatformSettings(); - - GUIUtility.ExitGUI(); - } - } - else - { - EditorGUILayout.HelpBox(s_Styles.disabledPackLabel.text, MessageType.Info); - } - - serializedObject.ApplyModifiedProperties(); - } - - private void HandleCommonSettingUI() - { - var atlasType = AtlasType.Undefined; - if (AllTargetsAreMaster()) - atlasType = AtlasType.Master; - else if (AllTargetsAreVariant()) - atlasType = AtlasType.Variant; - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = atlasType == AtlasType.Undefined; - atlasType = (AtlasType)EditorGUILayout.IntPopup(s_Styles.atlasTypeLabel, (int)atlasType, s_Styles.atlasTypeOptions, s_Styles.atlasTypeValues); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - bool setToVariant = atlasType == AtlasType.Variant; - foreach (SpriteAtlas sa in targets) - sa.SetIsVariant(setToVariant); - - // Reinit the platform setting view - m_TexturePlatformSettingsView = new SpriteAtlasInspectorPlatformSettingView(AllTargetsAreMaster()); - } - - if (atlasType == AtlasType.Variant) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_MasterAtlas, s_Styles.masterAtlasLabel); - if (EditorGUI.EndChangeCheck()) - { - // Apply modified properties here to have latest master atlas reflected in native codes. - serializedObject.ApplyModifiedProperties(); - - foreach (SpriteAtlas sa in targets) - { - sa.CopyMasterAtlasSettings(); - SyncPlatformSettings(); - } - } - } - - EditorGUILayout.PropertyField(m_BindAsDefault, s_Styles.bindAsDefaultLabel); - } - - private void HandleVariantSettingUI() - { - EditorGUILayout.LabelField(s_Styles.variantSettingLabel, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_VariantMultiplier, s_Styles.variantMultiplierLabel); - - // Test if the multiplier scale a power of two size (1024) into another power of 2 size. - if (!Mathf.IsPowerOfTwo((int)(m_VariantMultiplier.floatValue * 1024))) - EditorGUILayout.HelpBox(s_Styles.notPowerOfTwoWarning.text, MessageType.Warning, true); - } - - private void HandleBoolToIntPropertyField(SerializedProperty prop, GUIContent content) - { - Rect rect = EditorGUILayout.GetControlRect(); - EditorGUI.BeginProperty(rect, content, prop); - EditorGUI.BeginChangeCheck(); - var boolValue = EditorGUI.Toggle(rect, content, prop.boolValue); - if (EditorGUI.EndChangeCheck()) - prop.boolValue = boolValue; - EditorGUI.EndProperty(); - } - - private void HandleMasterSettingUI() - { - EditorGUILayout.LabelField(s_Styles.packingParametersLabel, EditorStyles.boldLabel); - - HandleBoolToIntPropertyField(m_EnableRotation, s_Styles.enableRotationLabel); - HandleBoolToIntPropertyField(m_EnableTightPacking, s_Styles.enableTightPackingLabel); - EditorGUILayout.IntPopup(m_Padding, s_Styles.paddingOptions, s_Styles.paddingValues, s_Styles.paddingLabel); - - GUILayout.Space(EditorGUI.kSpacing); - } - - private void HandleTextureSettingUI() - { - EditorGUILayout.LabelField(s_Styles.textureSettingLabel, EditorStyles.boldLabel); - - HandleBoolToIntPropertyField(m_Readable, s_Styles.readWrite); - HandleBoolToIntPropertyField(m_GenerateMipMaps, s_Styles.generateMipMapLabel); - HandleBoolToIntPropertyField(m_UseSRGB, s_Styles.sRGBLabel); - EditorGUILayout.PropertyField(m_FilterMode); - - var showAniso = !m_FilterMode.hasMultipleDifferentValues && !m_GenerateMipMaps.hasMultipleDifferentValues - && (FilterMode)m_FilterMode.intValue != FilterMode.Point && m_GenerateMipMaps.boolValue; - if (showAniso) - EditorGUILayout.IntSlider(m_AnisoLevel, 0, 16); - - GUILayout.Space(EditorGUI.kSpacing); - - HandlePlatformSettingUI(); - } - - private void HandlePlatformSettingUI() - { - int shownTextureFormatPage = EditorGUILayout.BeginPlatformGrouping(m_ValidPlatforms.ToArray(), s_Styles.defaultPlatformLabel); - if (shownTextureFormatPage == -1) - { - List platformSettings = m_TempPlatformSettings[kDefaultPlatformName]; - List newSettings = new List(platformSettings.Count); - for (var i = 0; i < platformSettings.Count; ++i) - { - TextureImporterPlatformSettings settings = new TextureImporterPlatformSettings(); - platformSettings[i].CopyTo(settings); - newSettings.Add(settings); - } - - if (m_TexturePlatformSettingsController.HandleDefaultSettings(newSettings, m_TexturePlatformSettingsView)) - { - for (var i = 0; i < newSettings.Count; ++i) - { - if (platformSettings[i].maxTextureSize != newSettings[i].maxTextureSize) - m_MaxTextureSize.intValue = newSettings[i].maxTextureSize; - if (platformSettings[i].textureCompression != newSettings[i].textureCompression) - m_TextureCompression.enumValueIndex = (int)newSettings[i].textureCompression; - if (platformSettings[i].crunchedCompression != newSettings[i].crunchedCompression) - m_UseCrunchedCompression.boolValue = newSettings[i].crunchedCompression; - if (platformSettings[i].compressionQuality != newSettings[i].compressionQuality) - m_CompressionQuality.intValue = newSettings[i].compressionQuality; - - newSettings[i].CopyTo(platformSettings[i]); - } - } - } - else - { - BuildPlatform buildPlatform = m_ValidPlatforms[shownTextureFormatPage]; - List platformSettings = m_TempPlatformSettings[buildPlatform.name]; - - // Predetermine format if overridden is unchecked - for (var i = 0; i < platformSettings.Count; ++i) - { - var settings = platformSettings[i]; - if (!settings.overridden) - { - SpriteAtlas sa = (SpriteAtlas)targets[i]; - settings.format = sa.FormatDetermineByAtlasSettings(buildPlatform.defaultTarget); - } - } - - m_TexturePlatformSettingsView.buildPlatformTitle = buildPlatform.title.text; - if (m_TexturePlatformSettingsController.HandlePlatformSettings(buildPlatform.defaultTarget, platformSettings, m_TexturePlatformSettingsView, m_TexturePlatformSettingTextureHelper)) - { - for (var i = 0; i < platformSettings.Count; ++i) - { - SpriteAtlas sa = (SpriteAtlas)targets[i]; - sa.SetPlatformSettings(platformSettings[i]); - } - } - } - - EditorGUILayout.EndPlatformGrouping(); - } - - private void HandlePackableListUI() - { - var currentEvent = Event.current; - var usedEvent = false; - - Rect rect = EditorGUILayout.GetControlRect(); - - var controlID = EditorGUIUtility.s_LastControlID; - switch (currentEvent.type) - { - case EventType.DragExited: - if (GUI.enabled) - HandleUtility.Repaint(); - break; - - case EventType.DragUpdated: - case EventType.DragPerform: - if (rect.Contains(currentEvent.mousePosition) && GUI.enabled) - { - // Check each single object, so we can add multiple objects in a single drag. - var didAcceptDrag = false; - var references = DragAndDrop.objectReferences; - foreach (var obj in references) - { - if (IsPackable(obj)) - { - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - if (currentEvent.type == EventType.DragPerform) - { - m_Packables.AppendFoldoutPPtrValue(obj); - didAcceptDrag = true; - DragAndDrop.activeControlID = 0; - } - else - DragAndDrop.activeControlID = controlID; - } - } - if (didAcceptDrag) - { - GUI.changed = true; - DragAndDrop.AcceptDrag(); - usedEvent = true; - } - } - break; - case EventType.ValidateCommand: - if (currentEvent.commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == s_Styles.packableSelectorHash) - usedEvent = true; - break; - case EventType.ExecuteCommand: - if (currentEvent.commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == s_Styles.packableSelectorHash) - { - var obj = ObjectSelector.GetCurrentObject(); - if (IsPackable(obj)) - { - m_Packables.AppendFoldoutPPtrValue(obj); - m_PackableList.index = m_Packables.arraySize - 1; - } - - usedEvent = true; - } - break; - } - - // Handle Foldout after we handle the current event because Foldout might process the drag and drop event and used it. - m_PackableListExpanded = EditorGUI.Foldout(rect, m_PackableListExpanded, s_Styles.packableListLabel, true); - - if (usedEvent) - currentEvent.Use(); - - if (m_PackableListExpanded) - { - EditorGUI.indentLevel++; - m_PackableList.DoLayoutList(); - EditorGUI.indentLevel--; - } - } - - void CachePreviewTexture() - { - if (m_PreviewTextures == null || m_Hash != spriteAtlas.GetHashString()) - { - m_PreviewTextures = spriteAtlas.GetPreviewTextures(); - m_Hash = spriteAtlas.GetHashString(); - - if (m_PreviewTextures != null - && m_PreviewTextures.Length > 0 - && m_TotalPages != m_PreviewTextures.Length) - { - m_TotalPages = m_PreviewTextures.Length; - m_OptionDisplays = new string[m_TotalPages]; - m_OptionValues = new int[m_TotalPages]; - for (int i = 0; i < m_TotalPages; ++i) - { - m_OptionDisplays[i] = string.Format("# {0}", i + 1); - m_OptionValues[i] = i; - } - } - } - } - - public override string GetInfoString() - { - if (m_PreviewTextures != null && m_PreviewPage < m_PreviewTextures.Length) - { - Texture2D t = m_PreviewTextures[m_PreviewPage]; - TextureFormat format = TextureUtil.GetTextureFormat(t); - - return string.Format("{0}x{1} {2}\n{3}", t.width, t.height, TextureUtil.GetTextureFormatString(format), EditorUtility.FormatBytes(TextureUtil.GetStorageMemorySizeLong(t))); - } - return ""; - } - - public override bool HasPreviewGUI() - { - CachePreviewTexture(); - return (m_PreviewTextures != null && m_PreviewTextures.Length > 0); - } - - public override void OnPreviewSettings() - { - // Do not allow changing of pages when multiple atlases is selected. - if (targets.Length == 1 && m_OptionDisplays != null && m_OptionValues != null && m_TotalPages > 1) - m_PreviewPage = EditorGUILayout.IntPopup(m_PreviewPage, m_OptionDisplays, m_OptionValues, s_Styles.preDropDown, GUILayout.MaxWidth(50)); - else - m_PreviewPage = 0; - - if (m_PreviewTextures != null) - { - Texture2D t = m_PreviewTextures[m_PreviewPage]; - - if (TextureUtil.HasAlphaTextureFormat(t.format)) - m_ShowAlpha = GUILayout.Toggle(m_ShowAlpha, m_ShowAlpha ? s_Styles.alphaIcon : s_Styles.RGBIcon, s_Styles.previewButton); - - int mipCount = Mathf.Max(1, TextureUtil.GetMipmapCount(t)); - if (mipCount > 1) - { - GUILayout.Box(s_Styles.smallZoom, s_Styles.previewLabel); - m_MipLevel = Mathf.Round(GUILayout.HorizontalSlider(m_MipLevel, mipCount - 1, 0, s_Styles.previewSlider, s_Styles.previewSliderThumb, GUILayout.MaxWidth(64))); - GUILayout.Box(s_Styles.largeZoom, s_Styles.previewLabel); - } - } - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - CachePreviewTexture(); - if (m_PreviewTextures != null && m_PreviewPage < m_PreviewTextures.Length) - { - Texture2D t = m_PreviewTextures[m_PreviewPage]; - - float bias = m_MipLevel - (float)(System.Math.Log(t.width / r.width) / System.Math.Log(2)); - - if (m_ShowAlpha) - EditorGUI.DrawTextureAlpha(r, t, ScaleMode.ScaleToFit, 0, bias); - else - EditorGUI.DrawTextureTransparent(r, t, ScaleMode.ScaleToFit, 0, bias); - } - } - - public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) - { - var spriteAtlas = AssetDatabase.LoadMainAssetAtPath(assetPath) as SpriteAtlas; - if (spriteAtlas == null) - return null; - - var previewTextures = spriteAtlas.GetPreviewTextures(); - if (previewTextures == null || previewTextures.Length == 0) - return null; - - var texture = previewTextures[0]; - PreviewHelpers.AdjustWidthAndHeightForStaticPreview(texture.width, texture.height, ref width, ref height); - - return SpriteUtility.CreateTemporaryDuplicate(texture, width, height); - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/ISpriteEditorModule.cs b/Editor/Mono/2D/SpriteEditorModule/ISpriteEditorModule.cs deleted file mode 100644 index ae47305db1..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/ISpriteEditorModule.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor.Experimental.U2D -{ - public abstract class SpriteEditorModuleBase - { - public ISpriteEditor spriteEditor { get; internal set; } - - public abstract string moduleName { get; } - - public abstract bool CanBeActivated(); - public abstract void DoMainGUI(); - public abstract void DoToolbarGUI(Rect drawArea); - public abstract void OnModuleActivate(); - public abstract void OnModuleDeactivate(); - public abstract void DoPostGUI(); - public abstract bool ApplyRevert(bool apply); - } - - public interface ISpriteEditor - { - List spriteRects { set; } - SpriteRect selectedSpriteRect { get; set; } - bool enableMouseMoveEvent { set; } - bool editingDisabled { get; } - Rect windowDimension { get; } - T GetDataProvider() where T : class; - - bool HandleSpriteSelection(); - void RequestRepaint(); - void SetDataModified(); - void ApplyOrRevertModification(bool apply); - } - - [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] - public class RequireSpriteDataProviderAttribute : Attribute - { - Type[] m_Types; - - public RequireSpriteDataProviderAttribute(params Type[] types) - { - m_Types = types; - } - - internal bool ContainsAllType(ISpriteEditorDataProvider provider) - { - return provider == null ? false : m_Types.Where(x => - { - return provider.HasDataProvider(x); - }).Count() == m_Types.Length; - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs deleted file mode 100644 index 4daf77d4f1..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteEditorData.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEditor.Experimental.U2D; -using UnityEngine.Experimental.U2D; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor.U2D -{ - internal class SpriteDataExt : SpriteRect - { - public float tessellationDetail = 0; - - // The following lists are to be left un-initialized. - // If they never loaded or assign explicitly, we avoid writing empty list to metadata. - public List spriteOutline; - public List vertices; - public List indices; - public List edges; - public List spritePhysicsOutline; - public List spriteBone; - - internal SpriteDataExt(SerializedObject so) - { - var ti = so.targetObject as TextureImporter; - var texture = AssetDatabase.LoadAssetAtPath(ti.assetPath); - name = texture.name; - alignment = (SpriteAlignment)so.FindProperty("m_Alignment").intValue; - border = ti.spriteBorder; - pivot = SpriteEditorUtility.GetPivotValue(alignment, ti.spritePivot); - tessellationDetail = so.FindProperty("m_SpriteTessellationDetail").floatValue; - - int width = 0, height = 0; - ti.GetWidthAndHeight(ref width, ref height); - rect = new Rect(0, 0, width, height); - - var guidSP = so.FindProperty("m_SpriteSheet.m_SpriteID"); - spriteID = new GUID(guidSP.stringValue); - } - - internal SpriteDataExt(SerializedProperty sp) - { - rect = sp.FindPropertyRelative("m_Rect").rectValue; - border = sp.FindPropertyRelative("m_Border").vector4Value; - name = sp.FindPropertyRelative("m_Name").stringValue; - alignment = (SpriteAlignment)sp.FindPropertyRelative("m_Alignment").intValue; - pivot = SpriteEditorUtility.GetPivotValue(alignment, sp.FindPropertyRelative("m_Pivot").vector2Value); - tessellationDetail = sp.FindPropertyRelative("m_TessellationDetail").floatValue; - spriteID = new GUID(sp.FindPropertyRelative("m_SpriteID").stringValue); - } - - internal SpriteDataExt(SpriteRect sr) - { - originalName = sr.originalName; - name = sr.name; - border = sr.border; - tessellationDetail = 0; - rect = sr.rect; - spriteID = sr.spriteID; - alignment = sr.alignment; - pivot = sr.pivot; - spriteOutline = new List(); - vertices = new List(); - indices = new List(); - edges = new List(); - spritePhysicsOutline = new List(); - spriteBone = new List(); - } - - public void Apply(SerializedObject so) - { - so.FindProperty("m_Alignment").intValue = (int)alignment; - so.FindProperty("m_SpriteBorder").vector4Value = border; - so.FindProperty("m_SpritePivot").vector2Value = pivot; - so.FindProperty("m_SpriteTessellationDetail").floatValue = tessellationDetail; - so.FindProperty("m_SpriteSheet.m_SpriteID").stringValue = spriteID.ToString(); - - var sp = so.FindProperty("m_SpriteSheet"); - if (spriteBone != null) - SpriteBoneDataTransfer.Apply(sp, spriteBone); - if (spriteOutline != null) - SpriteOutlineDataTransfer.Apply(sp, spriteOutline); - if (spritePhysicsOutline != null) - SpritePhysicsOutlineDataTransfer.Apply(sp, spritePhysicsOutline); - if (vertices != null) - SpriteMeshDataTransfer.Apply(sp, vertices, indices, edges); - } - - public void Apply(SerializedProperty sp) - { - sp.FindPropertyRelative("m_Rect").rectValue = rect; - sp.FindPropertyRelative("m_Name").stringValue = name; - sp.FindPropertyRelative("m_Border").vector4Value = border; - sp.FindPropertyRelative("m_Alignment").intValue = (int)alignment; - sp.FindPropertyRelative("m_Pivot").vector2Value = pivot; - sp.FindPropertyRelative("m_TessellationDetail").floatValue = tessellationDetail; - sp.FindPropertyRelative("m_SpriteID").stringValue = spriteID.ToString(); - - if (spriteBone != null) - SpriteBoneDataTransfer.Apply(sp, spriteBone); - if (spriteOutline != null) - SpriteOutlineDataTransfer.Apply(sp, spriteOutline); - if (spritePhysicsOutline != null) - SpritePhysicsOutlineDataTransfer.Apply(sp, spritePhysicsOutline); - if (vertices != null) - SpriteMeshDataTransfer.Apply(sp, vertices, indices, edges); - } - - public void CopyFromSpriteRect(SpriteRect spriteRect) - { - alignment = spriteRect.alignment; - border = spriteRect.border; - name = spriteRect.name; - pivot = spriteRect.pivot; - rect = spriteRect.rect; - spriteID = spriteRect.spriteID; - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModule.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModule.cs deleted file mode 100644 index 0258ba3ad5..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModule.cs +++ /dev/null @@ -1,321 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using UnityEngine; -using UnityEditorInternal; -using System.Collections.Generic; -using UnityEditor.U2D.Interface; -using UnityEngine.U2D.Interface; -using UnityTexture2D = UnityEngine.Texture2D; -using UnityEditor.Experimental.U2D; - -namespace UnityEditor -{ - [RequireSpriteDataProvider(typeof(ITextureDataProvider))] - internal partial class SpriteFrameModule : SpriteFrameModuleBase - { - public enum AutoSlicingMethod - { - DeleteAll = 0, - Smart = 1, - Safe = 2 - } - - private bool[] m_AlphaPixelCache; - private const int kDefaultColliderAlphaCutoff = 254; - private const float kDefaultColliderDetail = 0.25f; - - public SpriteFrameModule(ISpriteEditor sw, IEventSystem es, IUndoSystem us, IAssetDatabase ad) : - base("Sprite Editor", sw, es, us, ad) - {} - - public override void OnModuleActivate() - { - base.OnModuleActivate(); - spriteEditor.enableMouseMoveEvent = true; - } - - public override bool CanBeActivated() - { - return SpriteUtility.GetSpriteImportMode(spriteEditor.GetDataProvider()) != SpriteImportMode.Polygon; - } - - private string GetUniqueName(string prefix, int startIndex) - { - while (true) - { - var name = prefix + "_" + startIndex++; - - var nameUsed = false; - for (int i = 0; i < m_RectsCache.spriteRects.Count; ++i) - { - if (m_RectsCache.spriteRects[i].name == name) - { - nameUsed = true; - break; - } - } - - if (!nameUsed) - return name; - } - } - - // Aurajoki-Sweep Rect Sorting(tm) - // 1. Find top-most rectangle - // 2. Sweep it vertically to find out all rects from that "row" - // 3. goto 1. - // This will give us nicely sorted left->right top->down list of rectangles - // Works for most sprite sheets pretty nicely - private List SortRects(List rects) - { - List result = new List(); - - while (rects.Count > 0) - { - // Because the slicing algorithm works from bottom-up, the topmost rect is the last one in the array - Rect r = rects[rects.Count - 1]; - Rect sweepRect = new Rect(0, r.yMin, textureActualWidth, r.height); - - List rowRects = RectSweep(rects, sweepRect); - - if (rowRects.Count > 0) - result.AddRange(rowRects); - else - { - // We didn't find any rects, just dump the remaining rects and continue - result.AddRange(rects); - break; - } - } - return result; - } - - private List RectSweep(List rects, Rect sweepRect) - { - if (rects == null || rects.Count == 0) - return new List(); - - List containedRects = new List(); - - foreach (Rect rect in rects) - { - if (rect.Overlaps(sweepRect)) - containedRects.Add(rect); - } - - // Remove found rects from original list - foreach (Rect rect in containedRects) - rects.Remove(rect); - - // Sort found rects by x position - containedRects.Sort((a, b) => a.x.CompareTo(b.x)); - - return containedRects; - } - - private void AddSprite(Rect frame, int alignment, Vector2 pivot, AutoSlicingMethod slicingMethod, ref int index) - { - if (slicingMethod != AutoSlicingMethod.DeleteAll) - { - // Smart: Whenever we overlap, we just modify the existing rect and keep its other properties - // Safe: We only add new rect if it doesn't overlap existing one - - SpriteRect existingSprite = GetExistingOverlappingSprite(frame); - if (existingSprite != null) - { - if (slicingMethod == AutoSlicingMethod.Smart) - { - existingSprite.rect = frame; - existingSprite.alignment = (SpriteAlignment)alignment; - existingSprite.pivot = pivot; - } - } - else - AddSpriteWithUniqueName(frame, alignment, pivot, kDefaultColliderAlphaCutoff, kDefaultColliderDetail, index++); - } - else - AddSprite(frame, alignment, pivot, kDefaultColliderAlphaCutoff, kDefaultColliderDetail, GetSpriteNamePrefix() + "_" + index++); - } - - private SpriteRect GetExistingOverlappingSprite(Rect rect) - { - for (int i = 0; i < m_RectsCache.spriteRects.Count; i++) - { - Rect existingRect = m_RectsCache.spriteRects[i].rect; - if (existingRect.Overlaps(rect)) - return m_RectsCache.spriteRects[i]; - } - return null; - } - - private bool PixelHasAlpha(int x, int y, UnityTexture2D texture) - { - if (m_AlphaPixelCache == null) - { - m_AlphaPixelCache = new bool[texture.width * texture.height]; - Color32[] pixels = texture.GetPixels32(); - - for (int i = 0; i < pixels.Length; i++) - m_AlphaPixelCache[i] = pixels[i].a != 0; - } - int index = y * (int)texture.width + x; - return m_AlphaPixelCache[index]; - } - - private SpriteRect AddSprite(Rect rect, int alignment, Vector2 pivot, int colliderAlphaCutoff, float colliderDetail, string name) - { - SpriteRect spriteRect = new SpriteRect(); - - spriteRect.rect = rect; - spriteRect.alignment = (SpriteAlignment)alignment; - spriteRect.pivot = pivot; - - spriteRect.name = name; - spriteRect.originalName = spriteRect.name; - spriteRect.border = Vector4.zero; - spriteEditor.SetDataModified(); - - m_RectsCache.spriteRects.Add(spriteRect); - spriteEditor.SetDataModified(); - - return spriteRect; - } - - public SpriteRect AddSpriteWithUniqueName(Rect rect, int alignment, Vector2 pivot, int colliderAlphaCutoff, float colliderDetail, int nameIndexingHint) - { - string name = GetUniqueName(GetSpriteNamePrefix(), nameIndexingHint); - return AddSprite(rect, alignment, pivot, colliderAlphaCutoff, colliderDetail, name); - } - - private string GetSpriteNamePrefix() - { - return Path.GetFileNameWithoutExtension(spriteAssetPath); - } - - public void DoAutomaticSlicing(int minimumSpriteSize, int alignment, Vector2 pivot, AutoSlicingMethod slicingMethod) - { - undoSystem.RegisterCompleteObjectUndo(m_RectsCache, "Automatic Slicing"); - - if (slicingMethod == AutoSlicingMethod.DeleteAll) - m_RectsCache.spriteRects.Clear(); - - var textureToUse = m_TextureDataProvider.GetReadableTexture2D(); - List frames = new List(InternalSpriteUtility.GenerateAutomaticSpriteRectangles((UnityTexture2D)textureToUse, minimumSpriteSize, 0)); - frames = SortRects(frames); - int index = 0; - - foreach (Rect frame in frames) - AddSprite(frame, alignment, pivot, slicingMethod, ref index); - - selected = null; - spriteEditor.SetDataModified(); - Repaint(); - } - - public void DoGridSlicing(Vector2 size, Vector2 offset, Vector2 padding, int alignment, Vector2 pivot) - { - var textureToUse = m_TextureDataProvider.GetReadableTexture2D(); - Rect[] frames = InternalSpriteUtility.GenerateGridSpriteRectangles((UnityTexture2D)textureToUse, offset, size, padding); - - int index = 0; - undoSystem.RegisterCompleteObjectUndo(m_RectsCache, "Grid Slicing"); - m_RectsCache.spriteRects.Clear(); - - foreach (Rect frame in frames) - AddSprite(frame, alignment, pivot, kDefaultColliderAlphaCutoff, kDefaultColliderDetail, GetSpriteNamePrefix() + "_" + index++); - - selected = null; - spriteEditor.SetDataModified(); - Repaint(); - } - - public void ScaleSpriteRect(Rect r) - { - if (selected != null) - { - undoSystem.RegisterCompleteObjectUndo(m_RectsCache, "Scale sprite"); - selected.rect = ClampSpriteRect(r, textureActualWidth, textureActualHeight); - selected.border = ClampSpriteBorderToRect(selected.border, selected.rect); - spriteEditor.SetDataModified(); - } - } - - public void TrimAlpha() - { - var texture = m_TextureDataProvider.GetReadableTexture2D(); - if (texture == null) - return; - - Rect rect = selected.rect; - - int xMin = (int)rect.xMax; - int xMax = (int)rect.xMin; - int yMin = (int)rect.yMax; - int yMax = (int)rect.yMin; - - for (int y = (int)rect.yMin; y < (int)rect.yMax; y++) - { - for (int x = (int)rect.xMin; x < (int)rect.xMax; x++) - { - if (PixelHasAlpha(x, y, texture)) - { - xMin = Mathf.Min(xMin, x); - xMax = Mathf.Max(xMax, x); - yMin = Mathf.Min(yMin, y); - yMax = Mathf.Max(yMax, y); - } - } - } - // Case 582309: Return an empty rectangle if no pixel has an alpha - if (xMin > xMax || yMin > yMax) - rect = new Rect(0, 0, 0, 0); - else - rect = new Rect(xMin, yMin, xMax - xMin + 1, yMax - yMin + 1); - - if (rect.width <= 0 && rect.height <= 0) - { - m_RectsCache.spriteRects.Remove(selected); - spriteEditor.SetDataModified(); - selected = null; - } - else - { - rect = ClampSpriteRect(rect, texture.width, texture.height); - if (selected.rect != rect) - spriteEditor.SetDataModified(); - - selected.rect = rect; - } - } - - public void DuplicateSprite() - { - if (selected != null) - { - undoSystem.RegisterCompleteObjectUndo(m_RectsCache, "Duplicate sprite"); - selected = AddSpriteWithUniqueName(selected.rect, (int)selected.alignment, selected.pivot, kDefaultColliderAlphaCutoff, kDefaultColliderDetail, 0); - } - } - - public void CreateSprite(Rect rect) - { - rect = ClampSpriteRect(rect, textureActualWidth, textureActualHeight); - undoSystem.RegisterCompleteObjectUndo(m_RectsCache, "Create sprite"); - selected = AddSpriteWithUniqueName(rect, 0, Vector2.zero, kDefaultColliderAlphaCutoff, kDefaultColliderDetail, 0); - } - - public void DeleteSprite() - { - if (selected != null) - { - undoSystem.RegisterCompleteObjectUndo(m_RectsCache, "Delete sprite"); - m_RectsCache.spriteRects.Remove(selected); - selected = null; - spriteEditor.SetDataModified(); - } - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs deleted file mode 100644 index 5f9ebae02e..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs +++ /dev/null @@ -1,336 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using UnityEditor.Experimental.U2D; -using UnityEngine; -using UnityEditorInternal; -using UnityEditor.U2D.Interface; -using UnityEngine.U2D.Interface; - -namespace UnityEditor -{ - internal class SpriteRectModel : ScriptableObject - { - public List spriteRects; - - private SpriteRectModel() - {} - } - - internal abstract partial class SpriteFrameModuleBase : SpriteEditorModuleBase - { - protected SpriteRectModel m_RectsCache; - protected ITextureDataProvider m_TextureDataProvider; - protected ISpriteEditorDataProvider m_SpriteDataProvider; - string m_ModuleName; - - protected SpriteFrameModuleBase(string name, ISpriteEditor sw, IEventSystem es, IUndoSystem us, IAssetDatabase ad) - { - spriteEditor = sw; - eventSystem = es; - undoSystem = us; - assetDatabase = ad; - m_ModuleName = name; - } - - // implements ISpriteEditorModule - - public override void OnModuleActivate() - { - spriteImportMode = SpriteUtility.GetSpriteImportMode(spriteEditor.GetDataProvider()); - m_TextureDataProvider = spriteEditor.GetDataProvider(); - m_SpriteDataProvider = spriteEditor.GetDataProvider(); - int width, height; - m_TextureDataProvider.GetTextureActualWidthAndHeight(out width, out height); - textureActualWidth = width; - textureActualHeight = height; - m_RectsCache = ScriptableObject.CreateInstance(); - m_RectsCache.spriteRects = m_SpriteDataProvider.GetSpriteRects().ToList(); - spriteEditor.spriteRects = m_RectsCache.spriteRects; - if (spriteEditor.selectedSpriteRect != null) - spriteEditor.selectedSpriteRect = m_RectsCache.spriteRects.FirstOrDefault(x => x.spriteID == spriteEditor.selectedSpriteRect.spriteID); - } - - public override void OnModuleDeactivate() - { - if (m_RectsCache != null) - { - undoSystem.ClearUndo(m_RectsCache); - ScriptableObject.DestroyImmediate(m_RectsCache); - m_RectsCache = null; - } - } - - public override bool ApplyRevert(bool apply) - { - if (apply) - { - if (containsMultipleSprites) - { - var oldNames = new List(); - var newNames = new List(); - - for (int i = 0; i < m_RectsCache.spriteRects.Count; i++) - { - SpriteRect spriteRect = (SpriteRect)m_RectsCache.spriteRects[i]; - - if (string.IsNullOrEmpty(spriteRect.name)) - spriteRect.name = "Empty"; - - if (!string.IsNullOrEmpty(spriteRect.originalName)) - { - oldNames.Add(spriteRect.originalName); - newNames.Add(spriteRect.name); - } - } - var so = new SerializedObject(m_SpriteDataProvider.targetObject); - if (oldNames.Count > 0) - PatchImportSettingRecycleID.PatchMultiple(so, 213, oldNames.ToArray(), newNames.ToArray()); - so.ApplyModifiedPropertiesWithoutUndo(); - } - m_SpriteDataProvider.SetSpriteRects(m_RectsCache?.spriteRects.ToArray()); - if (m_RectsCache != null) - undoSystem.ClearUndo(m_RectsCache); - } - else - { - if (m_RectsCache != null) - { - undoSystem.ClearUndo(m_RectsCache); - m_RectsCache.spriteRects = m_SpriteDataProvider.GetSpriteRects().ToList(); - spriteEditor.spriteRects = m_RectsCache.spriteRects; - if (spriteEditor.selectedSpriteRect != null) - spriteEditor.selectedSpriteRect = m_RectsCache.spriteRects.FirstOrDefault(x => x.spriteID == spriteEditor.selectedSpriteRect.spriteID); - } - } - - return true; - } - - public override string moduleName - { - get { return m_ModuleName; } - } - - // injected interfaces - protected IEventSystem eventSystem - { - get; - private set; - } - - protected IUndoSystem undoSystem - { - get; - private set; - } - - protected IAssetDatabase assetDatabase - { - get; - private set; - } - - protected SpriteRect selected - { - get { return spriteEditor.selectedSpriteRect; } - set { spriteEditor.selectedSpriteRect = value; } - } - - protected SpriteImportMode spriteImportMode - { - get; private set; - } - - protected string spriteAssetPath - { - get { return assetDatabase.GetAssetPath(m_TextureDataProvider.texture); } - } - - public bool hasSelected - { - get { return spriteEditor.selectedSpriteRect != null; } - } - - public SpriteAlignment selectedSpriteAlignment - { - get { return selected.alignment; } - } - - public Vector2 selectedSpritePivot - { - get { return selected.pivot; } - } - - public int CurrentSelectedSpriteIndex() - { - if (m_RectsCache != null && selected != null) - return m_RectsCache.spriteRects.FindIndex(x => x.spriteID == selected.spriteID); - return -1; - } - - public Vector4 selectedSpriteBorder - { - get { return ClampSpriteBorderToRect(selected.border, selected.rect); } - set - { - undoSystem.RegisterCompleteObjectUndo(m_RectsCache, "Change Sprite Border"); - spriteEditor.SetDataModified(); - selected.border = ClampSpriteBorderToRect(value, selected.rect); - } - } - - public Rect selectedSpriteRect - { - get { return selected.rect; } - set - { - undoSystem.RegisterCompleteObjectUndo(m_RectsCache, "Change Sprite rect"); - spriteEditor.SetDataModified(); - selected.rect = ClampSpriteRect(value, textureActualWidth, textureActualHeight); - } - } - - public string selectedSpriteName - { - get { return selected.name; } - set - { - undoSystem.RegisterCompleteObjectUndo(m_RectsCache, "Change Sprite Name"); - spriteEditor.SetDataModified(); - - string oldName = selected.name; - string newName = InternalEditorUtility.RemoveInvalidCharsFromFileName(value, true); - - // These can only be changed in sprite multiple mode - if (string.IsNullOrEmpty(selected.originalName) && (newName != oldName)) - selected.originalName = oldName; - - // Is the name empty? - if (string.IsNullOrEmpty(newName)) - newName = oldName; - - // newName have to be unique. Multiple sprite assets sharing the same name will create problems with animations etc. - for (int i = 0; i < m_RectsCache.spriteRects.Count; ++i) - { - if (m_RectsCache.spriteRects[i].name == newName) - { - newName = selected.originalName; - break; - } - } - selected.name = newName; - } - } - - public int spriteCount - { - get { return m_RectsCache.spriteRects.Count; } - } - - public Vector4 GetSpriteBorderAt(int i) - { - return m_RectsCache.spriteRects[i].border; - } - - public Rect GetSpriteRectAt(int i) - { - return m_RectsCache.spriteRects[i].rect; - } - - public int textureActualWidth { get; private set; } - public int textureActualHeight { get; private set; } - - public void SetSpritePivotAndAlignment(Vector2 pivot, SpriteAlignment alignment) - { - undoSystem.RegisterCompleteObjectUndo(m_RectsCache, "Change Sprite Pivot"); - spriteEditor.SetDataModified(); - selected.alignment = alignment; - selected.pivot = SpriteEditorUtility.GetPivotValue(alignment, pivot); - } - - public bool containsMultipleSprites - { - get { return spriteImportMode == SpriteImportMode.Multiple; } - } - - protected void SnapPivot(Vector2 pivot, out Vector2 outPivot, out SpriteAlignment outAlignment) - { - Rect rect = selectedSpriteRect; - - // Convert from normalized space to texture space - Vector2 texturePos = new Vector2(rect.xMin + rect.width * pivot.x, rect.yMin + rect.height * pivot.y); - - Vector2[] snapPoints = GetSnapPointsArray(rect); - - // Snapping is now a firm action, it will always snap to one of the snapping points. - SpriteAlignment snappedAlignment = SpriteAlignment.Custom; - float nearestDistance = float.MaxValue; - for (int alignment = 0; alignment < snapPoints.Length; alignment++) - { - float distance = (texturePos - snapPoints[alignment]).magnitude * m_Zoom; - if (distance < nearestDistance) - { - snappedAlignment = (SpriteAlignment)alignment; - nearestDistance = distance; - } - } - - outAlignment = snappedAlignment; - outPivot = ConvertFromTextureToNormalizedSpace(snapPoints[(int)snappedAlignment], rect); - } - - protected static Rect ClampSpriteRect(Rect rect, float maxX, float maxY) - { - // Clamp rect to width height - Rect newRect = new Rect(); - - newRect.xMin = Mathf.Clamp(rect.xMin, 0, maxX - 1); - newRect.yMin = Mathf.Clamp(rect.yMin, 0, maxY - 1); - newRect.xMax = Mathf.Clamp(rect.xMax, 1, maxX); - newRect.yMax = Mathf.Clamp(rect.yMax, 1, maxY); - - // Prevent width and height to be 0 value after clamping. - if (Mathf.RoundToInt(newRect.width) == 0) - newRect.width = 1; - if (Mathf.RoundToInt(newRect.height) == 0) - newRect.height = 1; - - return SpriteEditorUtility.RoundedRect(newRect); - } - - protected static Rect FlipNegativeRect(Rect rect) - { - Rect newRect = new Rect(); - - newRect.xMin = Mathf.Min(rect.xMin, rect.xMax); - newRect.yMin = Mathf.Min(rect.yMin, rect.yMax); - newRect.xMax = Mathf.Max(rect.xMin, rect.xMax); - newRect.yMax = Mathf.Max(rect.yMin, rect.yMax); - - return newRect; - } - - protected static Vector4 ClampSpriteBorderToRect(Vector4 border, Rect rect) - { - Rect flipRect = FlipNegativeRect(rect); - float w = flipRect.width; - float h = flipRect.height; - - Vector4 newBorder = new Vector4(); - - // Make sure borders are within the width/height and left < right and top < bottom - newBorder.x = Mathf.RoundToInt(Mathf.Clamp(border.x, 0, Mathf.Min(Mathf.Abs(w - border.z), w))); // Left - newBorder.z = Mathf.RoundToInt(Mathf.Clamp(border.z, 0, Mathf.Min(Mathf.Abs(w - newBorder.x), w))); // Right - - newBorder.y = Mathf.RoundToInt(Mathf.Clamp(border.y, 0, Mathf.Min(Mathf.Abs(h - border.w), h))); // Bottom - newBorder.w = Mathf.RoundToInt(Mathf.Clamp(border.w, 0, Mathf.Min(Mathf.Abs(h - newBorder.y), h))); // Top - - return newBorder; - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs deleted file mode 100644 index 0fc12e3249..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs +++ /dev/null @@ -1,522 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Experimental.U2D; -using UnityEngine; -using UnityEditorInternal; -using UnityEngine.U2D.Interface; - -namespace UnityEditor -{ - internal abstract partial class SpriteFrameModuleBase : SpriteEditorModuleBase - { - protected enum GizmoMode - { - BorderEditing, - RectEditing - } - - protected class Styles - { - public readonly GUIStyle dragdot = "U2D.dragDot"; - public readonly GUIStyle dragdotactive = "U2D.dragDotActive"; - public readonly GUIStyle createRect = "U2D.createRect"; - public readonly GUIStyle pivotdotactive = "U2D.pivotDotActive"; - public readonly GUIStyle pivotdot = "U2D.pivotDot"; - - public readonly GUIStyle dragBorderdot = new GUIStyle(); - public readonly GUIStyle dragBorderDotActive = new GUIStyle(); - - public readonly GUIStyle toolbar; - - public readonly GUIContent[] spriteAlignmentOptions = - { - EditorGUIUtility.TrTextContent("Center"), - EditorGUIUtility.TrTextContent("Top Left"), - EditorGUIUtility.TrTextContent("Top"), - EditorGUIUtility.TrTextContent("Top Right"), - EditorGUIUtility.TrTextContent("Left"), - EditorGUIUtility.TrTextContent("Right"), - EditorGUIUtility.TrTextContent("Bottom Left"), - EditorGUIUtility.TrTextContent("Bottom"), - EditorGUIUtility.TrTextContent("Bottom Right"), - EditorGUIUtility.TrTextContent("Custom"), - }; - - public readonly GUIContent pivotLabel = EditorGUIUtility.TrTextContent("Pivot"); - - public readonly GUIContent spriteLabel = EditorGUIUtility.TrTextContent("Sprite"); - public readonly GUIContent customPivotLabel = EditorGUIUtility.TrTextContent("Custom Pivot"); - - public readonly GUIContent borderLabel = EditorGUIUtility.TrTextContent("Border"); - public readonly GUIContent lLabel = EditorGUIUtility.TextContent("L"); - public readonly GUIContent tLabel = EditorGUIUtility.TextContent("T"); - public readonly GUIContent rLabel = EditorGUIUtility.TextContent("R"); - public readonly GUIContent bLabel = EditorGUIUtility.TextContent("B"); - - public readonly GUIContent positionLabel = EditorGUIUtility.TrTextContent("Position"); - public readonly GUIContent xLabel = EditorGUIUtility.TextContent("X"); - public readonly GUIContent yLabel = EditorGUIUtility.TextContent("Y"); - public readonly GUIContent wLabel = EditorGUIUtility.TextContent("W"); - public readonly GUIContent hLabel = EditorGUIUtility.TextContent("H"); - - public readonly GUIContent nameLabel = EditorGUIUtility.TrTextContent("Name"); - - public Styles() - { - toolbar = new GUIStyle(EditorStyles.inspectorBig); - toolbar.margin.top = 0; - toolbar.margin.bottom = 0; - createRect.border = new RectOffset(3, 3, 3, 3); - - dragBorderdot.fixedHeight = 5f; - dragBorderdot.fixedWidth = 5f; - dragBorderdot.normal.background = EditorGUIUtility.whiteTexture; - - dragBorderDotActive.fixedHeight = dragBorderdot.fixedHeight; - dragBorderDotActive.fixedWidth = dragBorderdot.fixedWidth; - dragBorderDotActive.normal.background = EditorGUIUtility.whiteTexture; - } - } - - private static Styles s_Styles; - - protected static Styles styles - { - get - { - if (s_Styles == null) - s_Styles = new Styles(); - return s_Styles; - } - } - - private const float kScrollbarMargin = 16f; - private const float kInspectorWindowMargin = 8f; - private const float kInspectorWidth = 330f; - private const float kInspectorHeight = 160f; - - private float m_Zoom = 1.0f; - private GizmoMode m_GizmoMode; - - private bool ShouldShowRectScaling() - { - return hasSelected && m_GizmoMode == GizmoMode.RectEditing; - } - - private void DoPivotFields() - { - EditorGUI.BeginChangeCheck(); - - SpriteAlignment alignment = selectedSpriteAlignment; - alignment = (SpriteAlignment)EditorGUILayout.Popup(styles.pivotLabel, (int)alignment, styles.spriteAlignmentOptions); - - Vector2 oldPivot = selectedSpritePivot; - Vector2 newPivot = oldPivot; - - using (new EditorGUI.DisabledScope(alignment != SpriteAlignment.Custom)) - { - Rect pivotRect = GUILayoutUtility.GetRect(kInspectorWidth - kInspectorWindowMargin, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector2, styles.customPivotLabel)); - GUI.SetNextControlName("PivotField"); - newPivot = EditorGUI.Vector2Field(pivotRect, styles.customPivotLabel, oldPivot); - } - - if (EditorGUI.EndChangeCheck()) - SetSpritePivotAndAlignment(newPivot, alignment); - } - - private void DoBorderFields() - { - EditorGUI.BeginChangeCheck(); - - Vector4 oldBorder = selectedSpriteBorder; - int x = Mathf.RoundToInt(oldBorder.x); - int y = Mathf.RoundToInt(oldBorder.y); - int z = Mathf.RoundToInt(oldBorder.z); - int w = Mathf.RoundToInt(oldBorder.w); - - SpriteEditorUtility.FourIntFields(new Vector2(kInspectorWidth - kInspectorWindowMargin, EditorGUI.kSingleLineHeight * 2f + EditorGUI.kVerticalSpacingMultiField), - styles.borderLabel, - styles.lLabel, - styles.tLabel, - styles.rLabel, - styles.bLabel, - ref x, ref w, ref z, ref y); - - Vector4 newBorder = new Vector4(x, y, z, w); - - if (EditorGUI.EndChangeCheck()) - selectedSpriteBorder = newBorder; - } - - private void DoPositionField() - { - EditorGUI.BeginChangeCheck(); - - Rect oldRect = selectedSpriteRect; - int x = Mathf.RoundToInt(oldRect.x); - int y = Mathf.RoundToInt(oldRect.y); - int w = Mathf.RoundToInt(oldRect.width); - int h = Mathf.RoundToInt(oldRect.height); - - SpriteEditorUtility.FourIntFields(new Vector2(kInspectorWidth - kInspectorWindowMargin, EditorGUI.kSingleLineHeight * 2f + EditorGUI.kVerticalSpacingMultiField), - styles.positionLabel, - styles.xLabel, - styles.yLabel, - styles.wLabel, - styles.hLabel, - ref x, ref y, ref w, ref h); - - if (EditorGUI.EndChangeCheck()) - selectedSpriteRect = new Rect(x, y, w, h); - } - - private void DoNameField() - { - EditorGUI.BeginChangeCheck(); - - string oldName = selectedSpriteName; - GUI.SetNextControlName("SpriteName"); - string newName = EditorGUILayout.TextField(styles.nameLabel, oldName); - - if (EditorGUI.EndChangeCheck()) - selectedSpriteName = newName; - } - - private Rect inspectorRect - { - get - { - Rect position = spriteEditor.windowDimension; - return new Rect( - position.width - kInspectorWidth - kInspectorWindowMargin, - position.height - kInspectorHeight - kInspectorWindowMargin, - kInspectorWidth, - kInspectorHeight); - } - } - - private void DoSelectedFrameInspector() - { - if (!hasSelected) - return; - - EditorGUIUtility.wideMode = true; - float oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 135f; - - GUILayout.BeginArea(inspectorRect); - GUILayout.BeginVertical(styles.spriteLabel, GUI.skin.window); - - // Name and Position is set by importer in Single import mode - using (new EditorGUI.DisabledScope(!containsMultipleSprites)) - { - DoNameField(); - DoPositionField(); - } - - DoBorderFields(); - DoPivotFields(); - - GUILayout.EndVertical(); - GUILayout.EndArea(); - - EditorGUIUtility.labelWidth = oldLabelWidth; - } - - private static Vector2 ApplySpriteAlignmentToPivot(Vector2 pivot, Rect rect, SpriteAlignment alignment) - { - if (alignment != SpriteAlignment.Custom) - { - Vector2[] snapPoints = GetSnapPointsArray(rect); - Vector2 texturePos = snapPoints[(int)alignment]; - return ConvertFromTextureToNormalizedSpace(texturePos, rect); - } - return pivot; - } - - private static Vector2 ConvertFromTextureToNormalizedSpace(Vector2 texturePos, Rect rect) - { - return new Vector2((texturePos.x - rect.xMin) / rect.width, (texturePos.y - rect.yMin) / rect.height); - } - - private static Vector2[] GetSnapPointsArray(Rect rect) - { - Vector2[] snapPoints = new Vector2[9]; - snapPoints[(int)SpriteAlignment.TopLeft] = new Vector2(rect.xMin, rect.yMax); - snapPoints[(int)SpriteAlignment.TopCenter] = new Vector2(rect.center.x, rect.yMax); - snapPoints[(int)SpriteAlignment.TopRight] = new Vector2(rect.xMax, rect.yMax); - snapPoints[(int)SpriteAlignment.LeftCenter] = new Vector2(rect.xMin, rect.center.y); - snapPoints[(int)SpriteAlignment.Center] = new Vector2(rect.center.x, rect.center.y); - snapPoints[(int)SpriteAlignment.RightCenter] = new Vector2(rect.xMax, rect.center.y); - snapPoints[(int)SpriteAlignment.BottomLeft] = new Vector2(rect.xMin, rect.yMin); - snapPoints[(int)SpriteAlignment.BottomCenter] = new Vector2(rect.center.x, rect.yMin); - snapPoints[(int)SpriteAlignment.BottomRight] = new Vector2(rect.xMax, rect.yMin); - return snapPoints; - } - - protected void Repaint() - { - spriteEditor.RequestRepaint(); - } - - protected void HandleGizmoMode() - { - GizmoMode oldGizmoMode = m_GizmoMode; - IEvent evt = eventSystem.current; - if (evt.control) - m_GizmoMode = GizmoMode.BorderEditing; - else - m_GizmoMode = GizmoMode.RectEditing; - - if (oldGizmoMode != m_GizmoMode && (evt.type == EventType.KeyDown || evt.type == EventType.KeyUp) && (evt.keyCode == KeyCode.LeftControl || evt.keyCode == KeyCode.RightControl || evt.keyCode == KeyCode.LeftAlt || evt.keyCode == KeyCode.RightAlt)) - Repaint(); - } - - protected bool MouseOnTopOfInspector() - { - if (hasSelected == false) - return false; - - // GUIClip.Unclip sets the mouse position to include the windows tab. - Vector2 mousePosition = GUIClip.Unclip(eventSystem.current.mousePosition) - (GUIClip.topmostRect.position - GUIClip.GetTopRect().position); - return inspectorRect.Contains(mousePosition); - } - - protected void HandlePivotHandle() - { - if (!hasSelected) - return; - - EditorGUI.BeginChangeCheck(); - - SpriteAlignment alignment = selectedSpriteAlignment; - Vector2 pivot = selectedSpritePivot; - Rect rect = selectedSpriteRect; - pivot = ApplySpriteAlignmentToPivot(pivot, rect, alignment); - Vector2 pivotHandlePosition = SpriteEditorHandles.PivotSlider(rect, pivot, styles.pivotdot, styles.pivotdotactive); - - if (EditorGUI.EndChangeCheck()) - { - // Pivot snapping only happen when ctrl is press. Same as scene view snapping move - if (eventSystem.current.control) - SnapPivot(pivotHandlePosition, out pivot, out alignment); - else - { - pivot = pivotHandlePosition; - alignment = SpriteAlignment.Custom; - } - SetSpritePivotAndAlignment(pivot, alignment); - } - } - - protected void HandleBorderSidePointScalingSliders() - { - if (!hasSelected) - return; - - GUIStyle dragDot = styles.dragBorderdot; - GUIStyle dragDotActive = styles.dragBorderDotActive; - var color = new Color(0f, 1f, 0f); - - Rect rect = selectedSpriteRect; - Vector4 border = selectedSpriteBorder; - - float left = rect.xMin + border.x; - float right = rect.xMax - border.z; - float top = rect.yMax - border.w; - float bottom = rect.yMin + border.y; - - EditorGUI.BeginChangeCheck(); - - float horizontal = bottom - (bottom - top) / 2; - float vertical = left - (left - right) / 2; - - float center = horizontal; - HandleBorderPointSlider(ref left, ref center, MouseCursor.ResizeHorizontal, false, dragDot, dragDotActive, color); - - center = horizontal; - HandleBorderPointSlider(ref right, ref center, MouseCursor.ResizeHorizontal, false, dragDot, dragDotActive, color); - - center = vertical; - HandleBorderPointSlider(ref center, ref top, MouseCursor.ResizeVertical, false, dragDot, dragDotActive, color); - - center = vertical; - HandleBorderPointSlider(ref center, ref bottom, MouseCursor.ResizeVertical, false, dragDot, dragDotActive, color); - - if (EditorGUI.EndChangeCheck()) - { - border.x = left - rect.xMin; - border.z = rect.xMax - right; - border.w = rect.yMax - top; - border.y = bottom - rect.yMin; - selectedSpriteBorder = border; - } - } - - protected void HandleBorderCornerScalingHandles() - { - if (!hasSelected) - return; - - GUIStyle dragDot = styles.dragBorderdot; - GUIStyle dragDotActive = styles.dragBorderDotActive; - var color = new Color(0f, 1f, 0f); - - Rect rect = selectedSpriteRect; - Vector4 border = selectedSpriteBorder; - - float left = rect.xMin + border.x; - float right = rect.xMax - border.z; - float top = rect.yMax - border.w; - float bottom = rect.yMin + border.y; - - EditorGUI.BeginChangeCheck(); - - // Handle corner points, but hide them if border values are below 1 - HandleBorderPointSlider(ref left, ref top, MouseCursor.ResizeUpLeft, border.x < 1 && border.w < 1, dragDot, dragDotActive, color); - HandleBorderPointSlider(ref right, ref top, MouseCursor.ResizeUpRight, border.z < 1 && border.w < 1, dragDot, dragDotActive, color); - HandleBorderPointSlider(ref left, ref bottom, MouseCursor.ResizeUpRight, border.x < 1 && border.y < 1, dragDot, dragDotActive, color); - HandleBorderPointSlider(ref right, ref bottom, MouseCursor.ResizeUpLeft, border.z < 1 && border.y < 1, dragDot, dragDotActive, color); - - if (EditorGUI.EndChangeCheck()) - { - border.x = left - rect.xMin; - border.z = rect.xMax - right; - border.w = rect.yMax - top; - border.y = bottom - rect.yMin; - selectedSpriteBorder = border; - } - } - - protected void HandleBorderSideScalingHandles() - { - if (hasSelected == false) - return; - - Rect rect = new Rect(selectedSpriteRect); - Vector4 border = selectedSpriteBorder; - - float left = rect.xMin + border.x; - float right = rect.xMax - border.z; - float top = rect.yMax - border.w; - float bottom = rect.yMin + border.y; - - Vector2 screenRectTopLeft = Handles.matrix.MultiplyPoint(new Vector3(rect.xMin, rect.yMin)); - Vector2 screenRectBottomRight = Handles.matrix.MultiplyPoint(new Vector3(rect.xMax, rect.yMax)); - - float screenRectWidth = Mathf.Abs(screenRectBottomRight.x - screenRectTopLeft.x); - float screenRectHeight = Mathf.Abs(screenRectBottomRight.y - screenRectTopLeft.y); - - EditorGUI.BeginChangeCheck(); - - left = HandleBorderScaleSlider(left, rect.yMax, screenRectWidth, screenRectHeight, true); - right = HandleBorderScaleSlider(right, rect.yMax, screenRectWidth, screenRectHeight, true); - - top = HandleBorderScaleSlider(rect.xMin, top, screenRectWidth, screenRectHeight, false); - bottom = HandleBorderScaleSlider(rect.xMin, bottom, screenRectWidth, screenRectHeight, false); - - if (EditorGUI.EndChangeCheck()) - { - border.x = left - rect.xMin; - border.z = rect.xMax - right; - border.w = rect.yMax - top; - border.y = bottom - rect.yMin; - - selectedSpriteBorder = border; - } - } - - protected void HandleBorderPointSlider(ref float x, ref float y, MouseCursor mouseCursor, bool isHidden, GUIStyle dragDot, GUIStyle dragDotActive, Color color) - { - var originalColor = GUI.color; - - if (isHidden) - GUI.color = new Color(0, 0, 0, 0); - else - GUI.color = color; - - Vector2 point = SpriteEditorHandles.PointSlider(new Vector2(x, y), mouseCursor, dragDot, dragDotActive); - x = point.x; - y = point.y; - - GUI.color = originalColor; - } - - protected float HandleBorderScaleSlider(float x, float y, float width, float height, bool isHorizontal) - { - float handleSize = styles.dragBorderdot.fixedWidth; - Vector2 point = Handles.matrix.MultiplyPoint(new Vector2(x, y)); - float result; - - EditorGUI.BeginChangeCheck(); - - if (isHorizontal) - { - Rect newRect = new Rect(point.x - handleSize * .5f, point.y, handleSize, height); - result = SpriteEditorHandles.ScaleSlider(point, MouseCursor.ResizeHorizontal, newRect).x; - } - else - { - Rect newRect = new Rect(point.x, point.y - handleSize * .5f, width, handleSize); - result = SpriteEditorHandles.ScaleSlider(point, MouseCursor.ResizeVertical, newRect).y; - } - - if (EditorGUI.EndChangeCheck()) - return result; - - return isHorizontal ? x : y; - } - - protected void DrawSpriteRectGizmos() - { - if (eventSystem.current.type != EventType.Repaint) - return; - - SpriteEditorUtility.BeginLines(new Color(0f, 1f, 0f, 0.7f)); - int currentSelectedSpriteIndex = CurrentSelectedSpriteIndex(); - for (int i = 0; i < spriteCount; i++) - { - Vector4 border = GetSpriteBorderAt(i); - if (currentSelectedSpriteIndex != i && m_GizmoMode != GizmoMode.BorderEditing) - { - if (Mathf.Approximately(border.sqrMagnitude, 0)) - continue; - } - - - var rect = GetSpriteRectAt(i); - SpriteEditorUtility.DrawLine(new Vector3(rect.xMin + border.x, rect.yMin), new Vector3(rect.xMin + border.x, rect.yMax)); - SpriteEditorUtility.DrawLine(new Vector3(rect.xMax - border.z, rect.yMin), new Vector3(rect.xMax - border.z, rect.yMax)); - - SpriteEditorUtility.DrawLine(new Vector3(rect.xMin, rect.yMin + border.y), new Vector3(rect.xMax, rect.yMin + border.y)); - SpriteEditorUtility.DrawLine(new Vector3(rect.xMin, rect.yMax - border.w), new Vector3(rect.xMax, rect.yMax - border.w)); - } - SpriteEditorUtility.EndLines(); - - if (ShouldShowRectScaling()) - { - Rect r = selectedSpriteRect; - SpriteEditorUtility.BeginLines(new Color(0f, 0.1f, 0.3f, 0.25f)); - SpriteEditorUtility.DrawBox(new Rect(r.xMin + 1f / m_Zoom, r.yMin + 1f / m_Zoom, r.width, r.height)); - SpriteEditorUtility.EndLines(); - SpriteEditorUtility.BeginLines(new Color(0.25f, 0.5f, 1f, 0.75f)); - SpriteEditorUtility.DrawBox(r); - SpriteEditorUtility.EndLines(); - } - } - - // implements ISpriteEditorModule - - public override void DoMainGUI() - { - m_Zoom = Handles.matrix.GetColumn(0).magnitude; - } - - public override void DoPostGUI() - { - DoSelectedFrameInspector(); - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleView.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleView.cs deleted file mode 100644 index 34f498a681..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleView.cs +++ /dev/null @@ -1,221 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using UnityEngine.U2D.Interface; - -namespace UnityEditor -{ - internal partial class SpriteFrameModule : SpriteFrameModuleBase - { - private static class SpriteFrameModuleStyles - { - public static readonly GUIContent sliceButtonLabel = EditorGUIUtility.TrTextContent("Slice"); - public static readonly GUIContent trimButtonLabel = EditorGUIUtility.TrTextContent("Trim", "Trims selected rectangle (T)"); - public static readonly GUIContent okButtonLabel = EditorGUIUtility.TrTextContent("Ok"); - public static readonly GUIContent cancelButtonLabel = EditorGUIUtility.TrTextContent("Cancel"); - } - - internal static PrefKey k_SpriteEditorTrim = new PrefKey("Sprite Editor/Trim", "#t"); - - - // overrides for SpriteFrameModuleBase - public override void DoMainGUI() - { - base.DoMainGUI(); - DrawSpriteRectGizmos(); - - HandleGizmoMode(); - - if (containsMultipleSprites) - HandleRectCornerScalingHandles(); - - HandleBorderCornerScalingHandles(); - HandleBorderSidePointScalingSliders(); - - if (containsMultipleSprites) - HandleRectSideScalingHandles(); - - HandleBorderSideScalingHandles(); - HandlePivotHandle(); - - if (containsMultipleSprites) - HandleDragging(); - - if (!MouseOnTopOfInspector()) - spriteEditor.HandleSpriteSelection(); - - if (containsMultipleSprites) - { - HandleCreate(); - HandleDelete(); - HandleDuplicate(); - } - spriteEditor.spriteRects = m_RectsCache.spriteRects; - } - - public override void DoToolbarGUI(Rect toolbarRect) - { - using (new EditorGUI.DisabledScope(!containsMultipleSprites || spriteEditor.editingDisabled)) - { - GUIStyle skin = EditorStyles.toolbarPopup; - - Rect drawArea = toolbarRect; - - drawArea.width = skin.CalcSize(SpriteFrameModuleStyles.sliceButtonLabel).x; - SpriteUtilityWindow.DrawToolBarWidget(ref drawArea, ref toolbarRect, (adjustedDrawArea) => - { - if (GUI.Button(adjustedDrawArea, SpriteFrameModuleStyles.sliceButtonLabel, skin)) - { - if (SpriteEditorMenu.ShowAtPosition(adjustedDrawArea, this, m_TextureDataProvider)) - GUIUtility.ExitGUI(); - } - }); - - using (new EditorGUI.DisabledScope(!hasSelected)) - { - drawArea.x += drawArea.width; - drawArea.width = skin.CalcSize(SpriteFrameModuleStyles.trimButtonLabel).x; - SpriteUtilityWindow.DrawToolBarWidget(ref drawArea, ref toolbarRect, (adjustedDrawArea) => - { - if (GUI.Button(adjustedDrawArea, SpriteFrameModuleStyles.trimButtonLabel, EditorStyles.toolbarButton) || - (string.IsNullOrEmpty(GUI.GetNameOfFocusedControl()) && k_SpriteEditorTrim.activated)) - { - TrimAlpha(); - Repaint(); - } - }); - } - } - } - - private void HandleRectCornerScalingHandles() - { - if (!hasSelected) - return; - - GUIStyle dragDot = styles.dragdot; - GUIStyle dragDotActive = styles.dragdotactive; - var color = Color.white; - - Rect rect = new Rect(selectedSpriteRect); - - float left = rect.xMin; - float right = rect.xMax; - float top = rect.yMax; - float bottom = rect.yMin; - - EditorGUI.BeginChangeCheck(); - - HandleBorderPointSlider(ref left, ref top, MouseCursor.ResizeUpLeft, false, dragDot, dragDotActive, color); - HandleBorderPointSlider(ref right, ref top, MouseCursor.ResizeUpRight, false, dragDot, dragDotActive, color); - HandleBorderPointSlider(ref left, ref bottom, MouseCursor.ResizeUpRight, false, dragDot, dragDotActive, color); - HandleBorderPointSlider(ref right, ref bottom, MouseCursor.ResizeUpLeft, false, dragDot, dragDotActive, color); - - if (EditorGUI.EndChangeCheck()) - { - rect.xMin = left; - rect.xMax = right; - rect.yMax = top; - rect.yMin = bottom; - ScaleSpriteRect(rect); - } - } - - private void HandleRectSideScalingHandles() - { - if (!hasSelected) - return; - - Rect rect = new Rect(selectedSpriteRect); - - float left = rect.xMin; - float right = rect.xMax; - float top = rect.yMax; - float bottom = rect.yMin; - - Vector2 screenRectTopLeft = Handles.matrix.MultiplyPoint(new Vector3(rect.xMin, rect.yMin)); - Vector2 screenRectBottomRight = Handles.matrix.MultiplyPoint(new Vector3(rect.xMax, rect.yMax)); - - float screenRectWidth = Mathf.Abs(screenRectBottomRight.x - screenRectTopLeft.x); - float screenRectHeight = Mathf.Abs(screenRectBottomRight.y - screenRectTopLeft.y); - - EditorGUI.BeginChangeCheck(); - - left = HandleBorderScaleSlider(left, rect.yMax, screenRectWidth, screenRectHeight, true); - right = HandleBorderScaleSlider(right, rect.yMax, screenRectWidth, screenRectHeight, true); - - top = HandleBorderScaleSlider(rect.xMin, top, screenRectWidth, screenRectHeight, false); - bottom = HandleBorderScaleSlider(rect.xMin, bottom, screenRectWidth, screenRectHeight, false); - - if (EditorGUI.EndChangeCheck()) - { - rect.xMin = left; - rect.xMax = right; - rect.yMax = top; - rect.yMin = bottom; - - ScaleSpriteRect(rect); - } - } - - private void HandleDragging() - { - if (hasSelected && !MouseOnTopOfInspector()) - { - Rect textureBounds = new Rect(0, 0, textureActualWidth, textureActualHeight); - EditorGUI.BeginChangeCheck(); - - Rect oldRect = selectedSpriteRect; - Rect newRect = SpriteEditorUtility.ClampedRect(SpriteEditorUtility.RoundedRect(SpriteEditorHandles.SliderRect(oldRect)), textureBounds, true); - - if (EditorGUI.EndChangeCheck()) - selectedSpriteRect = newRect; - } - } - - private void HandleCreate() - { - if (!MouseOnTopOfInspector() && !eventSystem.current.alt) - { - // Create new rects via dragging in empty space - EditorGUI.BeginChangeCheck(); - Rect newRect = SpriteEditorHandles.RectCreator(textureActualWidth, textureActualHeight, styles.createRect); - if (EditorGUI.EndChangeCheck() && newRect.width > 0f && newRect.height > 0f) - { - CreateSprite(newRect); - GUIUtility.keyboardControl = 0; - } - } - } - - private void HandleDuplicate() - { - IEvent evt = eventSystem.current; - if ((evt.type == EventType.ValidateCommand || evt.type == EventType.ExecuteCommand) - && evt.commandName == EventCommandNames.Duplicate) - { - if (evt.type == EventType.ExecuteCommand) - DuplicateSprite(); - - evt.Use(); - } - } - - private void HandleDelete() - { - IEvent evt = eventSystem.current; - - if ((evt.type == EventType.ValidateCommand || evt.type == EventType.ExecuteCommand) - && (evt.commandName == EventCommandNames.SoftDelete || evt.commandName == EventCommandNames.Delete)) - { - if (evt.type == EventType.ExecuteCommand && hasSelected) - DeleteSprite(); - - evt.Use(); - } - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpritePolygonModeModule.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpritePolygonModeModule.cs deleted file mode 100644 index 7706e2b1d3..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpritePolygonModeModule.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Experimental.U2D; -using UnityEditor.U2D.Interface; -using UnityEngine.U2D.Interface; -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - [RequireSpriteDataProvider(typeof(ISpriteOutlineDataProvider), typeof(ITextureDataProvider))] - internal partial class SpritePolygonModeModule : SpriteFrameModuleBase - { - List> m_Outline; - - public SpritePolygonModeModule(ISpriteEditor sw, IEventSystem es, IUndoSystem us, IAssetDatabase ad) : - base("Sprite Polygon Mode Editor", sw, es, us, ad) - {} - - // ISpriteEditorModule implemenation - public override void OnModuleActivate() - { - base.OnModuleActivate(); - m_Outline = new List>(); - - for (int i = 0; i < m_RectsCache.spriteRects.Count; ++i) - { - var rect = m_RectsCache.spriteRects[i]; - m_Outline.Add(spriteEditor.GetDataProvider().GetOutlines(rect.spriteID)); - } - - showChangeShapeWindow = polygonSprite; - if (polygonSprite) - DeterminePolygonSides(); - } - - public override bool CanBeActivated() - { - return SpriteUtility.GetSpriteImportMode(spriteEditor.GetDataProvider()) == SpriteImportMode.Polygon; - } - - private bool polygonSprite - { - get { return spriteImportMode == SpriteImportMode.Polygon; } - } - - private void DeterminePolygonSides() - { - if (polygonSprite && m_RectsCache.spriteRects.Count == 1 && m_Outline.Count == 1 && m_Outline[0].Count == 1) - { - polygonSides = m_Outline[0][0].Length; - } - else - // If for reasons we cannot determine the sides of the polygon, fall back to 0 (Square) - polygonSides = 0; - } - - public int GetPolygonSideCount() - { - DeterminePolygonSides(); - return polygonSides; - } - - public int polygonSides - { - get; - set; - } - - public List GetSpriteOutlineAt(int i) - { - return m_Outline[i]; - } - - public void GeneratePolygonOutline() - { - for (int i = 0; i < m_RectsCache.spriteRects.Count; i++) - { - SpriteRect currentRect = m_RectsCache.spriteRects[i]; - - var result = UnityEditor.Sprites.SpriteUtility.GeneratePolygonOutlineVerticesOfSize(polygonSides, (int)currentRect.rect.width, (int)currentRect.rect.height); - - m_Outline.Clear(); - var newOutlineList = new List(); - newOutlineList.Add(result); - m_Outline.Add(newOutlineList); - - spriteEditor.SetDataModified(); - } - Repaint(); - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpritePolygonModeModuleView.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpritePolygonModeModuleView.cs deleted file mode 100644 index 0a10a97f09..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpritePolygonModeModuleView.cs +++ /dev/null @@ -1,164 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEditorInternal; -using UnityEngine.U2D.Interface; -using UnityEditor.Experimental.U2D; - -namespace UnityEditor -{ - internal partial class SpritePolygonModeModule : SpriteFrameModuleBase - { - private static class SpritePolygonModeStyles - { - public static readonly GUIContent changeShapeLabel = EditorGUIUtility.TrTextContent("Change Shape"); - public static readonly GUIContent sidesLabel = EditorGUIUtility.TrTextContent("Sides"); - public static readonly GUIContent polygonChangeShapeHelpBoxContent = EditorGUIUtility.TrTextContent("Sides can only be either 0 or anything between 3 and 128"); - public static readonly GUIContent changeButtonLabel = EditorGUIUtility.TrTextContent("Change", "Change to the new number of sides"); - } - - private const int k_PolygonChangeShapeWindowMargin = EditorGUI.kWindowToolbarHeight; - private const int k_PolygonChangeShapeWindowWidth = 150; - private const int k_PolygonChangeShapeWindowHeight = 45; - private const int k_PolygonChangeShapeWindowWarningHeight = k_PolygonChangeShapeWindowHeight + 20; - - private Rect m_PolygonChangeShapeWindowRect = new Rect(0, k_PolygonChangeShapeWindowMargin, k_PolygonChangeShapeWindowWidth, k_PolygonChangeShapeWindowHeight); - - // overrides for SpriteFrameModuleViewBase - public override void DoPostGUI() - { - // Polygon change shape window - DoPolygonChangeShapeWindow(); - base.DoPostGUI(); - } - - public override void DoMainGUI() - { - base.DoMainGUI(); - DrawGizmos(); - - HandleGizmoMode(); - - HandleBorderCornerScalingHandles(); - HandleBorderSidePointScalingSliders(); - - HandleBorderSideScalingHandles(); - HandlePivotHandle(); - - if (!MouseOnTopOfInspector()) - spriteEditor.HandleSpriteSelection(); - } - - public override void DoToolbarGUI(Rect toolbarRect) - { - using (new EditorGUI.DisabledScope(spriteEditor.editingDisabled)) - { - GUIStyle skin = EditorStyles.toolbarPopup; - Rect drawArea = toolbarRect; - drawArea.width = skin.CalcSize(SpritePolygonModeStyles.changeShapeLabel).x; - SpriteUtilityWindow.DrawToolBarWidget(ref drawArea, ref toolbarRect, (adjustedDrawArea) => - { - showChangeShapeWindow = GUI.Toggle(adjustedDrawArea, showChangeShapeWindow, SpritePolygonModeStyles.changeShapeLabel, EditorStyles.toolbarButton); - }); - } - } - - private void DrawGizmos() - { - if (eventSystem.current.type != EventType.Repaint) - return; - for (int i = 0; i < spriteCount; i++) - { - List outline = GetSpriteOutlineAt(i); - Vector2 offset = GetSpriteRectAt(i).size * 0.5f; - if (outline.Count > 0) - { - SpriteEditorUtility.BeginLines(new Color(0.75f, 0.75f, 0.75f, 0.75f)); - for (int j = 0; j < outline.Count; ++j) - { - for (int k = 0, last = outline[j].Length - 1; k < outline[j].Length; last = k, ++k) - SpriteEditorUtility.DrawLine(outline[j][last] + offset, outline[j][k] + offset); - } - SpriteEditorUtility.EndLines(); - } - } - DrawSpriteRectGizmos(); - } - - private void DoPolygonChangeShapeWindow() - { - if (showChangeShapeWindow && !spriteEditor.editingDisabled) - { - bool createAndClose = false; - - float oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 45f; - - GUILayout.BeginArea(m_PolygonChangeShapeWindowRect); - GUILayout.BeginVertical(GUI.skin.box); - - // Catch "return" key before text box - IEvent evt = eventSystem.current; - if (isSidesValid && - evt.type == EventType.KeyDown && - evt.keyCode == KeyCode.Return) - { - createAndClose = true; - evt.Use(); - } - - EditorGUI.BeginChangeCheck(); - polygonSides = EditorGUILayout.IntField(SpritePolygonModeStyles.sidesLabel, polygonSides); - if (EditorGUI.EndChangeCheck()) - m_PolygonChangeShapeWindowRect.height = isSidesValid ? k_PolygonChangeShapeWindowHeight : k_PolygonChangeShapeWindowWarningHeight; - - GUILayout.FlexibleSpace(); - - if (!isSidesValid) - EditorGUILayout.HelpBox(SpritePolygonModeStyles.polygonChangeShapeHelpBoxContent.text, MessageType.Warning, true); - else - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - EditorGUI.BeginDisabledGroup(!isSidesValid); - if (GUILayout.Button(SpritePolygonModeStyles.changeButtonLabel)) - createAndClose = true; - EditorGUI.EndDisabledGroup(); - - GUILayout.EndHorizontal(); - } - GUILayout.EndVertical(); - - if (createAndClose) - { - if (isSidesValid) - GeneratePolygonOutline(); - showChangeShapeWindow = false; - GUIUtility.hotControl = 0; - GUIUtility.keyboardControl = 0; - } - - EditorGUIUtility.labelWidth = oldLabelWidth; - GUILayout.EndArea(); - } - } - - private bool isSidesValid - { - get - { - return polygonSides == 0 || (polygonSides >= 3 && polygonSides <= 128); - } - } - - public bool showChangeShapeWindow - { - get; - set; - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs deleted file mode 100644 index 04c1621953..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs +++ /dev/null @@ -1,821 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.Experimental.U2D; -using UnityEditorInternal; -using UnityEngine.U2D.Interface; -using UnityEditor.U2D.Interface; -using System; -using System.Linq; - -namespace UnityEditor.U2D -{ - // We need this so that undo/redo works - [Serializable] - internal class SpriteOutline - { - [SerializeField] - public List m_Path = new List(); - - public void Add(Vector2 point) - { - m_Path.Add(point); - } - - public void Insert(int index, Vector2 point) - { - m_Path.Insert(index, point); - } - - public void RemoveAt(int index) - { - m_Path.RemoveAt(index); - } - - public Vector2 this[int index] - { - get { return m_Path[index]; } - set { m_Path[index] = value; } - } - - public int Count - { - get { return m_Path.Count; } - } - - public void AddRange(IEnumerable addRange) - { - m_Path.AddRange(addRange); - } - } - - // Collection of outlines for a single Sprite - [Serializable] - internal class SpriteOutlineList - { - [SerializeField] - List m_SpriteOutlines = new List(); - [SerializeField] - float m_TessellationDetail = 0; - - public List spriteOutlines { get { return m_SpriteOutlines; } set { m_SpriteOutlines = value; } } - public GUID spriteID { get; private set; } - - public float tessellationDetail - { - get { return m_TessellationDetail; } - set - { - m_TessellationDetail = value; - m_TessellationDetail = Mathf.Min(1, m_TessellationDetail); - m_TessellationDetail = Mathf.Max(0, m_TessellationDetail); - } - } - - public SpriteOutlineList(GUID guid) - { - this.spriteID = guid; - m_SpriteOutlines = new List(); - } - - public SpriteOutlineList(GUID guid, List list) - { - this.spriteID = guid; - - m_SpriteOutlines = new List(list.Count); - for (int i = 0; i < list.Count; ++i) - { - var newList = new SpriteOutline(); - newList.m_Path.AddRange(list[i]); - m_SpriteOutlines.Add(newList); - } - } - - public SpriteOutlineList(GUID guid, List list) - { - this.spriteID = guid; - - m_SpriteOutlines = list; - } - - public List ToListVector() - { - var value = new List(m_SpriteOutlines.Count); - foreach (var s in m_SpriteOutlines) - { - value.Add(s.m_Path.ToArray()); - } - return value; - } - - public SpriteOutline this[int index] - { - get { return IsValidIndex(index) ? m_SpriteOutlines[index] : null; } - set - { - if (IsValidIndex(index)) - m_SpriteOutlines[index] = value; - } - } - - public static implicit operator List(SpriteOutlineList list) - { - return list != null ? list.m_SpriteOutlines : null; - } - - public int Count { get { return m_SpriteOutlines.Count; } } - - bool IsValidIndex(int index) - { - return index >= 0 && index < Count; - } - } - - // Collection of Sprites' outlines - internal class SpriteOutlineModel : ScriptableObject - { - [SerializeField] - List m_SpriteOutlineList = new List(); - - private SpriteOutlineModel() - {} - - public SpriteOutlineList this[int index] - { - get { return IsValidIndex(index) ? m_SpriteOutlineList[index] : null; } - set - { - if (IsValidIndex(index)) - m_SpriteOutlineList[index] = value; - } - } - - public SpriteOutlineList this[GUID guid] - { - get { return m_SpriteOutlineList.FirstOrDefault(x => x.spriteID == guid); } - set - { - var index = m_SpriteOutlineList.FindIndex(x => x.spriteID == guid); - if (index != -1) - m_SpriteOutlineList[index] = value; - } - } - - public void AddListVector2(GUID guid, List outline) - { - m_SpriteOutlineList.Add(new SpriteOutlineList(guid, outline)); - } - - public int Count { get { return m_SpriteOutlineList.Count; } } - - bool IsValidIndex(int index) - { - return index >= 0 && index < Count; - } - } - - [RequireSpriteDataProvider(typeof(ISpriteOutlineDataProvider), typeof(ITextureDataProvider))] - internal class SpriteOutlineModule : SpriteEditorModuleBase - { - class Styles - { - public GUIContent generateOutlineLabel = EditorGUIUtility.TrTextContent("Generate", "Generate new outline based on mesh detail value."); - public GUIContent outlineTolerance = EditorGUIUtility.TrTextContent("Outline Tolerance", "Sets how tight the outline should be from the sprite."); - public GUIContent snapButtonLabel = EditorGUIUtility.TrTextContent("Snap", "Snap points to nearest pixel"); - public GUIContent generatingOutlineDialogTitle = EditorGUIUtility.TrTextContent("Outline"); - public GUIContent generatingOutlineDialogContent = EditorGUIUtility.TrTextContent("Generating outline {0}/{1}"); - public Color spriteBorderColor = new Color(0.25f, 0.5f, 1f, 0.75f); - } - - protected SpriteRect m_Selected; - - private const float k_HandleSize = 5f; - private readonly string k_DeleteCommandName = EventCommandNames.Delete; - private readonly string k_SoftDeleteCommandName = EventCommandNames.SoftDelete; - - private ShapeEditor[] m_ShapeEditors; - private bool m_RequestRepaint; - private Matrix4x4 m_HandleMatrix; - private Vector2 m_MousePosition; - private bool m_Snap = true; - private ShapeEditorRectSelectionTool m_ShapeSelectionUI; - private bool m_WasRectSelecting = false; - private Rect? m_SelectionRect; - private ITexture2D m_OutlineTexture; - private Styles m_Styles; - protected SpriteOutlineModel m_Outline; - protected ITextureDataProvider m_TextureDataProvider; - - public SpriteOutlineModule(ISpriteEditor sem, IEventSystem es, IUndoSystem us, IAssetDatabase ad, IGUIUtility gu, IShapeEditorFactory sef, ITexture2D outlineTexture) - { - spriteEditorWindow = sem; - undoSystem = us; - eventSystem = es; - assetDatabase = ad; - guiUtility = gu; - shapeEditorFactory = sef; - m_OutlineTexture = outlineTexture; - - m_ShapeSelectionUI = new ShapeEditorRectSelectionTool(gu); - - m_ShapeSelectionUI.RectSelect += RectSelect; - m_ShapeSelectionUI.ClearSelection += ClearSelection; - } - - public override string moduleName - { - get { return "Custom Outline"; } - } - - public override bool ApplyRevert(bool apply) - { - if (m_Outline != null) - { - if (apply) - { - var outlineDataProvider = spriteEditorWindow.GetDataProvider(); - for (int i = 0; i < m_Outline.Count; ++i) - { - outlineDataProvider.SetOutlines(m_Outline[i].spriteID, m_Outline[i].ToListVector()); - outlineDataProvider.SetTessellationDetail(m_Outline[i].spriteID, m_Outline[i].tessellationDetail); - } - } - - ScriptableObject.DestroyImmediate(m_Outline); - m_Outline = null; - } - - return true; - } - - private Styles styles - { - get - { - if (m_Styles == null) - m_Styles = new Styles(); - return m_Styles; - } - } - - protected virtual List selectedShapeOutline - { - get - { - return m_Outline[m_Selected.spriteID].spriteOutlines; - } - set - { - m_Outline[m_Selected.spriteID].spriteOutlines = value; - } - } - - private bool shapeEditorDirty - { - get; set; - } - - private bool editingDisabled - { - get { return spriteEditorWindow.editingDisabled; } - } - - private ISpriteEditor spriteEditorWindow - { - get; set; - } - - private IUndoSystem undoSystem - { - get; set; - } - - private IEventSystem eventSystem - { - get; set; - } - - private IAssetDatabase assetDatabase - { - get; set; - } - - private IGUIUtility guiUtility - { - get; set; - } - - private IShapeEditorFactory shapeEditorFactory - { - get; set; - } - - private void RectSelect(Rect r, ShapeEditor.SelectionType selectionType) - { - var localRect = EditorGUIExt.FromToRect(ScreenToLocal(r.min), ScreenToLocal(r.max)); - m_SelectionRect = localRect; - } - - private void ClearSelection() - { - m_RequestRepaint = true; - } - - protected virtual void LoadOutline() - { - m_Outline = ScriptableObject.CreateInstance(); - var spriteDataProvider = spriteEditorWindow.GetDataProvider(); - var outlineDataProvider = spriteEditorWindow.GetDataProvider(); - foreach (var rect in spriteDataProvider.GetSpriteRects()) - { - var outlines = outlineDataProvider.GetOutlines(rect.spriteID); - m_Outline.AddListVector2(rect.spriteID, outlines); - m_Outline[m_Outline.Count - 1].tessellationDetail = outlineDataProvider.GetTessellationDetail(rect.spriteID); - } - } - - public override void OnModuleActivate() - { - m_TextureDataProvider = spriteEditorWindow.GetDataProvider(); - LoadOutline(); - GenerateOutlineIfNotExist(); - undoSystem.RegisterUndoCallback(UndoRedoPerformed); - shapeEditorDirty = true; - SetupShapeEditor(); - spriteEditorWindow.enableMouseMoveEvent = true; - } - - void GenerateOutlineIfNotExist() - { - var rectCache = spriteEditorWindow.GetDataProvider().GetSpriteRects(); - if (rectCache != null) - { - bool needApply = false; - for (int i = 0; i < rectCache.Length; ++i) - { - var rect = rectCache[i]; - if (!HasShapeOutline(rect)) - { - EditorUtility.DisplayProgressBar(styles.generatingOutlineDialogTitle.text, - string.Format(styles.generatingOutlineDialogContent.text, i + 1 , rectCache.Length), - (float)(i) / rectCache.Length); - - SetupShapeEditorOutline(rect); - needApply = true; - } - } - if (needApply) - { - EditorUtility.ClearProgressBar(); - spriteEditorWindow.ApplyOrRevertModification(true); - LoadOutline(); - } - } - } - - public override void OnModuleDeactivate() - { - undoSystem.UnregisterUndoCallback(UndoRedoPerformed); - CleanupShapeEditors(); - m_Selected = null; - spriteEditorWindow.enableMouseMoveEvent = false; - if (m_Outline != null) - { - undoSystem.ClearUndo(m_Outline); - ScriptableObject.DestroyImmediate(m_Outline); - m_Outline = null; - } - } - - public override void DoMainGUI() - { - IEvent evt = eventSystem.current; - - m_RequestRepaint = false; - m_HandleMatrix = Handles.matrix; - - m_MousePosition = Handles.inverseMatrix.MultiplyPoint(eventSystem.current.mousePosition); - if (m_Selected == null || !m_Selected.rect.Contains(m_MousePosition) && !IsMouseOverOutlinePoints() && evt.shift == false) - spriteEditorWindow.HandleSpriteSelection(); - - HandleCreateNewOutline(); - - m_WasRectSelecting = m_ShapeSelectionUI.isSelecting; - - UpdateShapeEditors(); - - m_ShapeSelectionUI.OnGUI(); - - DrawGizmos(); - - if (m_RequestRepaint || evt.type == EventType.MouseMove) - spriteEditorWindow.RequestRepaint(); - } - - public override void DoToolbarGUI(Rect drawArea) - { - var style = styles; - - Rect snapDrawArea = new Rect(drawArea.x, drawArea.y, EditorStyles.toolbarButton.CalcSize(style.snapButtonLabel).x, drawArea.height); - m_Snap = GUI.Toggle(snapDrawArea, m_Snap, style.snapButtonLabel, EditorStyles.toolbarButton); - - using (new EditorGUI.DisabledScope(editingDisabled || m_Selected == null)) - { - float totalWidth = drawArea.width - snapDrawArea.width; - drawArea.x = snapDrawArea.xMax; - drawArea.width = EditorStyles.toolbarButton.CalcSize(style.outlineTolerance).x; - totalWidth -= drawArea.width; - if (totalWidth < 0) - drawArea.width += totalWidth; - if (drawArea.width > 0) - GUI.Label(drawArea, style.outlineTolerance, EditorStyles.miniLabel); - drawArea.x += drawArea.width; - - drawArea.width = 100; - totalWidth -= drawArea.width; - if (totalWidth < 0) - drawArea.width += totalWidth; - - if (drawArea.width > 0) - { - float tesselationValue = m_Selected != null ? m_Outline[m_Selected.spriteID].tessellationDetail : 0; - EditorGUI.BeginChangeCheck(); - float oldFieldWidth = EditorGUIUtility.fieldWidth; - float oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.fieldWidth = 30; - EditorGUIUtility.labelWidth = 1; - tesselationValue = EditorGUI.Slider(drawArea, Mathf.Clamp01(tesselationValue), 0, 1); - if (EditorGUI.EndChangeCheck()) - { - RecordUndo(); - m_Outline[m_Selected.spriteID].tessellationDetail = tesselationValue; - } - EditorGUIUtility.fieldWidth = oldFieldWidth; - EditorGUIUtility.labelWidth = oldLabelWidth; - } - - drawArea.x += drawArea.width; - drawArea.width = EditorStyles.toolbarButton.CalcSize(style.generateOutlineLabel).x; - totalWidth -= drawArea.width; - if (totalWidth < 0) - drawArea.width += totalWidth; - - if (drawArea.width > 0 && GUI.Button(drawArea, style.generateOutlineLabel, EditorStyles.toolbarButton)) - { - RecordUndo(); - selectedShapeOutline.Clear(); - SetupShapeEditorOutline(m_Selected); - spriteEditorWindow.SetDataModified(); - shapeEditorDirty = true; - } - } - } - - public override void DoPostGUI() - {} - - public override bool CanBeActivated() - { - return SpriteUtility.GetSpriteImportMode(spriteEditorWindow.GetDataProvider()) != SpriteImportMode.None; - } - - private void RecordUndo() - { - undoSystem.RegisterCompleteObjectUndo(m_Outline, "Outline changed"); - } - - public void CreateNewOutline(Rect rectOutline) - { - Rect rect = m_Selected.rect; - if (rect.Contains(rectOutline.min) && rect.Contains(rectOutline.max)) - { - RecordUndo(); - SpriteOutline so = new SpriteOutline(); - Vector2 outlineOffset = new Vector2(0.5f * rect.width + rect.x, 0.5f * rect.height + rect.y); - Rect selectionRect = new Rect(rectOutline); - selectionRect.min = SnapPoint(rectOutline.min); - selectionRect.max = SnapPoint(rectOutline.max); - so.Add(CapPointToRect(new Vector2(selectionRect.xMin, selectionRect.yMin), rect) - outlineOffset); - so.Add(CapPointToRect(new Vector2(selectionRect.xMin, selectionRect.yMax), rect) - outlineOffset); - so.Add(CapPointToRect(new Vector2(selectionRect.xMax, selectionRect.yMax), rect) - outlineOffset); - so.Add(CapPointToRect(new Vector2(selectionRect.xMax, selectionRect.yMin), rect) - outlineOffset); - selectedShapeOutline.Add(so); - spriteEditorWindow.SetDataModified(); - shapeEditorDirty = true; - } - } - - private void HandleCreateNewOutline() - { - if (m_WasRectSelecting && m_ShapeSelectionUI.isSelecting == false && m_SelectionRect != null && m_Selected != null) - { - bool createNewOutline = true; - foreach (var se in m_ShapeEditors) - { - if (se.selectedPoints.Count != 0) - { - createNewOutline = false; - break; - } - } - - if (createNewOutline) - CreateNewOutline(m_SelectionRect.Value); - } - m_SelectionRect = null; - } - - public void UpdateShapeEditors() - { - SetupShapeEditor(); - - if (m_Selected != null) - { - IEvent currentEvent = eventSystem.current; - var wantsDelete = currentEvent.type == EventType.ExecuteCommand && (currentEvent.commandName == k_SoftDeleteCommandName || currentEvent.commandName == k_DeleteCommandName); - - for (int i = 0; i < m_ShapeEditors.Length; ++i) - { - if (m_ShapeEditors[i].GetPointsCount() == 0) - continue; - - m_ShapeEditors[i].inEditMode = true; - m_ShapeEditors[i].OnGUI(); - if (shapeEditorDirty) - break; - } - - if (wantsDelete) - { - // remove outline which have lesser than 3 points - for (int i = selectedShapeOutline.Count - 1; i >= 0; --i) - { - if (selectedShapeOutline[i].Count < 3) - { - selectedShapeOutline.RemoveAt(i); - shapeEditorDirty = true; - } - } - } - } - } - - private bool IsMouseOverOutlinePoints() - { - if (m_Selected == null) - return false; - Vector2 outlineOffset = new Vector2(0.5f * m_Selected.rect.width + m_Selected.rect.x, 0.5f * m_Selected.rect.height + m_Selected.rect.y); - float handleSize = GetHandleSize(); - Rect r = new Rect(0, 0, handleSize * 2, handleSize * 2); - for (int i = 0; i < selectedShapeOutline.Count; ++i) - { - var outline = selectedShapeOutline[i]; - for (int j = 0; j < outline.Count; ++j) - { - r.center = outline[j] + outlineOffset; - if (r.Contains(m_MousePosition)) - return true; - } - } - return false; - } - - private float GetHandleSize() - { - return k_HandleSize / m_HandleMatrix.m00; - } - - private void CleanupShapeEditors() - { - if (m_ShapeEditors != null) - { - for (int i = 0; i < m_ShapeEditors.Length; ++i) - { - for (int j = 0; j < m_ShapeEditors.Length; ++j) - { - if (i != j) - m_ShapeEditors[j].UnregisterFromShapeEditor(m_ShapeEditors[i]); - } - m_ShapeEditors[i].OnDisable(); - } - } - m_ShapeEditors = null; - } - - public void SetupShapeEditor() - { - if (shapeEditorDirty || m_Selected != spriteEditorWindow.selectedSpriteRect) - { - m_Selected = spriteEditorWindow.selectedSpriteRect; - CleanupShapeEditors(); - - if (m_Selected != null) - { - if (!HasShapeOutline(m_Selected)) - SetupShapeEditorOutline(m_Selected); - m_ShapeEditors = new ShapeEditor[selectedShapeOutline.Count]; - - for (int i = 0; i < selectedShapeOutline.Count; ++i) - { - int outlineIndex = i; - m_ShapeEditors[i] = shapeEditorFactory.CreateShapeEditor(); - m_ShapeEditors[i].SetRectSelectionTool(m_ShapeSelectionUI); - m_ShapeEditors[i].LocalToWorldMatrix = () => m_HandleMatrix; - m_ShapeEditors[i].LocalToScreen = (point) => Handles.matrix.MultiplyPoint(point); - m_ShapeEditors[i].ScreenToLocal = ScreenToLocal; - m_ShapeEditors[i].RecordUndo = RecordUndo; - m_ShapeEditors[i].GetHandleSize = GetHandleSize; - m_ShapeEditors[i].lineTexture = m_OutlineTexture; - m_ShapeEditors[i].Snap = SnapPoint; - m_ShapeEditors[i].GetPointPosition = (index) => GetPointPosition(outlineIndex, index); - m_ShapeEditors[i].SetPointPosition = (index, position) => SetPointPosition(outlineIndex, index, position); - m_ShapeEditors[i].InsertPointAt = (index, position) => InsertPointAt(outlineIndex, index, position); - m_ShapeEditors[i].RemovePointAt = (index) => RemovePointAt(outlineIndex, index); - m_ShapeEditors[i].GetPointsCount = () => GetPointsCount(outlineIndex); - } - for (int i = 0; i < selectedShapeOutline.Count; ++i) - { - for (int j = 0; j < selectedShapeOutline.Count; ++j) - { - if (i != j) - m_ShapeEditors[j].RegisterToShapeEditor(m_ShapeEditors[i]); - } - } - } - else - { - m_ShapeEditors = new ShapeEditor[0]; - } - } - shapeEditorDirty = false; - } - - protected virtual bool HasShapeOutline(SpriteRect spriteRect) - { - var outline = m_Outline[spriteRect.spriteID]?.spriteOutlines; - return outline != null; - } - - protected virtual void SetupShapeEditorOutline(SpriteRect spriteRect) - { - var outline = m_Outline[spriteRect.spriteID]; - var outlines = GenerateSpriteRectOutline(spriteRect.rect, - Math.Abs(outline.tessellationDetail - (-1f)) < Mathf.Epsilon ? 0 : outline.tessellationDetail, - 0, m_TextureDataProvider); - if (outlines.Count == 0) - { - Vector2 halfSize = spriteRect.rect.size * 0.5f; - outlines = new List() - { - new SpriteOutline() - { - m_Path = new List() - { - new Vector2(-halfSize.x, -halfSize.y), - new Vector2(-halfSize.x, halfSize.y), - new Vector2(halfSize.x, halfSize.y), - new Vector2(halfSize.x, -halfSize.y), - } - } - }; - } - m_Outline[spriteRect.spriteID].spriteOutlines = outlines; - } - - public Vector3 SnapPoint(Vector3 position) - { - if (m_Snap) - { - position.x = Mathf.RoundToInt(position.x); - position.y = Mathf.RoundToInt(position.y); - } - return position; - } - - public Vector3 GetPointPosition(int outlineIndex, int pointIndex) - { - if (outlineIndex >= 0 && outlineIndex < selectedShapeOutline.Count) - { - var outline = selectedShapeOutline[outlineIndex]; - if (pointIndex >= 0 && pointIndex < outline.Count) - { - return ConvertSpriteRectSpaceToTextureSpace(outline[pointIndex]); - } - } - return new Vector3(float.NaN, float.NaN, float.NaN); - } - - public void SetPointPosition(int outlineIndex, int pointIndex, Vector3 position) - { - selectedShapeOutline[outlineIndex][pointIndex] = ConvertTextureSpaceToSpriteRectSpace(CapPointToRect(position, m_Selected.rect)); - spriteEditorWindow.SetDataModified(); - } - - public void InsertPointAt(int outlineIndex, int pointIndex, Vector3 position) - { - selectedShapeOutline[outlineIndex].Insert(pointIndex, ConvertTextureSpaceToSpriteRectSpace(CapPointToRect(position, m_Selected.rect))); - spriteEditorWindow.SetDataModified(); - } - - public void RemovePointAt(int outlineIndex, int i) - { - selectedShapeOutline[outlineIndex].RemoveAt(i); - spriteEditorWindow.SetDataModified(); - } - - public int GetPointsCount(int outlineIndex) - { - return selectedShapeOutline[outlineIndex].Count; - } - - private Vector2 ConvertSpriteRectSpaceToTextureSpace(Vector2 value) - { - Vector2 outlineOffset = new Vector2(0.5f * m_Selected.rect.width + m_Selected.rect.x, 0.5f * m_Selected.rect.height + m_Selected.rect.y); - value += outlineOffset; - return value; - } - - private Vector2 ConvertTextureSpaceToSpriteRectSpace(Vector2 value) - { - Vector2 outlineOffset = new Vector2(0.5f * m_Selected.rect.width + m_Selected.rect.x, 0.5f * m_Selected.rect.height + m_Selected.rect.y); - value -= outlineOffset; - return value; - } - - private Vector3 ScreenToLocal(Vector2 point) - { - return Handles.inverseMatrix.MultiplyPoint(point); - } - - private void UndoRedoPerformed() - { - shapeEditorDirty = true; - } - - private void DrawGizmos() - { - if (eventSystem.current.type == EventType.Repaint) - { - var selected = spriteEditorWindow.selectedSpriteRect; - if (selected != null) - { - SpriteEditorUtility.BeginLines(styles.spriteBorderColor); - SpriteEditorUtility.DrawBox(selected.rect); - SpriteEditorUtility.EndLines(); - } - } - } - - protected static List GenerateSpriteRectOutline(Rect rect, float detail, byte alphaTolerance, ITextureDataProvider textureProvider) - { - List outline = new List(); - var texture = textureProvider.texture; - if (texture != null) - { - Vector2[][] paths; - - // we might have a texture that is capped because of max size or NPOT. - // in that case, we need to convert values from capped space to actual texture space and back. - int actualWidth = 0, actualHeight = 0; - int cappedWidth, cappedHeight; - textureProvider.GetTextureActualWidthAndHeight(out actualWidth, out actualHeight); - cappedWidth = texture.width; - cappedHeight = texture.height; - - Vector2 scale = new Vector2(cappedWidth / (float)actualWidth, cappedHeight / (float)actualHeight); - Rect spriteRect = rect; - spriteRect.xMin *= scale.x; - spriteRect.xMax *= scale.x; - spriteRect.yMin *= scale.y; - spriteRect.yMax *= scale.y; - - Sprites.SpriteUtility.GenerateOutline(texture, spriteRect, detail, alphaTolerance, true, out paths); - - Rect capRect = new Rect(); - capRect.size = rect.size; - capRect.center = Vector2.zero; - for (int j = 0; j < paths.Length; ++j) - { - SpriteOutline points = new SpriteOutline(); - foreach (Vector2 v in paths[j]) - points.Add(CapPointToRect(new Vector2(v.x / scale.x, v.y / scale.y), capRect)); - - outline.Add(points); - } - } - return outline; - } - - private static Vector2 CapPointToRect(Vector2 so, Rect r) - { - so.x = Mathf.Min(r.xMax, so.x); - so.x = Mathf.Max(r.xMin, so.x); - so.y = Mathf.Min(r.yMax, so.y); - so.y = Mathf.Max(r.yMin, so.y); - return so; - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs b/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs deleted file mode 100644 index b2d6ef3ddd..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.Experimental.U2D; -using UnityEditorInternal; -using UnityEngine.U2D.Interface; -using UnityEditor.U2D.Interface; - -namespace UnityEditor.U2D -{ - [RequireSpriteDataProvider(typeof(ISpritePhysicsOutlineDataProvider), typeof(ITextureDataProvider))] - internal class SpritePhysicsShapeModule : SpriteOutlineModule - { - private readonly float kDefaultPhysicsTessellationDetail = 0.25f; - private readonly byte kDefaultPhysicsAlphaTolerance = 200; - - public SpritePhysicsShapeModule(ISpriteEditor sem, IEventSystem ege, IUndoSystem us, IAssetDatabase ad, IGUIUtility gu, IShapeEditorFactory sef, ITexture2D outlineTexture) - : base(sem, ege, us, ad, gu, sef, outlineTexture) - { - spriteEditorWindow = sem; - } - - public override string moduleName - { - get { return "Custom Physics Shape"; } - } - - private ISpriteEditor spriteEditorWindow - { - get; set; - } - - public override bool ApplyRevert(bool apply) - { - if (m_Outline != null) - { - if (apply) - { - var dp = spriteEditorWindow.GetDataProvider(); - for (int i = 0; i < m_Outline.Count; ++i) - { - dp.SetOutlines(m_Outline[i].spriteID, m_Outline[i].ToListVector()); - dp.SetTessellationDetail(m_Outline[i].spriteID, m_Outline[i].tessellationDetail); - } - } - - ScriptableObject.DestroyImmediate(m_Outline); - m_Outline = null; - } - - return true; - } - - protected override void LoadOutline() - { - m_Outline = ScriptableObject.CreateInstance(); - var spriteDataProvider = spriteEditorWindow.GetDataProvider(); - var outlineDataProvider = spriteEditorWindow.GetDataProvider(); - foreach (var rect in spriteDataProvider.GetSpriteRects()) - { - var outlines = outlineDataProvider.GetOutlines(rect.spriteID); - m_Outline.AddListVector2(rect.spriteID, outlines); - m_Outline[m_Outline.Count - 1].tessellationDetail = outlineDataProvider.GetTessellationDetail(rect.spriteID); - } - } - - protected override void SetupShapeEditorOutline(SpriteRect spriteRect) - { - var physicsShape = m_Outline[spriteRect.spriteID]; - var physicsShapes = GenerateSpriteRectOutline(spriteRect.rect, - Math.Abs(physicsShape.tessellationDetail - (-1f)) < Mathf.Epsilon ? kDefaultPhysicsTessellationDetail : physicsShape.tessellationDetail, - kDefaultPhysicsAlphaTolerance, m_TextureDataProvider); - m_Outline[spriteRect.spriteID].spriteOutlines = physicsShapes; - spriteEditorWindow.SetDataModified(); - } - } -} diff --git a/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs b/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs deleted file mode 100644 index e3b976bbb4..0000000000 --- a/Editor/Mono/2D/SpriteEditorModule/TextureImporter.cs +++ /dev/null @@ -1,167 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEditor.Experimental.U2D; -using UnityEditor.U2D; -using System.Collections.Generic; - -namespace UnityEditor -{ - public sealed partial class TextureImporter : AssetImporter, ISpriteEditorDataProvider - { - List m_SpritesMultiple; - SpriteDataExt m_SpriteSingle; - - float ISpriteEditorDataProvider.pixelsPerUnit - { - get { return spritePixelsPerUnit; } - } - - UnityEngine.Object ISpriteEditorDataProvider.targetObject - { - get { return this; } - } - - SpriteRect[] ISpriteEditorDataProvider.GetSpriteRects() - { - return spriteImportMode == SpriteImportMode.Multiple ? m_SpritesMultiple.Select(x => new SpriteDataExt(x) as SpriteRect).ToArray() : new[] { new SpriteDataExt(m_SpriteSingle) }; - } - - void ISpriteEditorDataProvider.SetSpriteRects(SpriteRect[] spriteRects) - { - if (spriteImportMode != SpriteImportMode.Multiple && spriteImportMode != SpriteImportMode.None && spriteRects.Length == 1) - { - m_SpriteSingle.CopyFromSpriteRect(spriteRects[0]); - } - else if (spriteImportMode == SpriteImportMode.Multiple) - { - for (int i = m_SpritesMultiple.Count - 1; i >= 0; --i) - { - var spriteID = m_SpritesMultiple[i].spriteID; - if (spriteRects.FirstOrDefault(x => x.spriteID == spriteID) == null) - m_SpritesMultiple.RemoveAt(i); - } - for (int i = 0; i < spriteRects.Length; i++) - { - var spriteRect = spriteRects[i]; - var index = m_SpritesMultiple.FindIndex(x => x.spriteID == spriteRect.spriteID); - if (-1 == index) - m_SpritesMultiple.Add(new SpriteDataExt(spriteRect)); - else - m_SpritesMultiple[index].CopyFromSpriteRect(spriteRects[i]); - } - } - } - - internal SpriteRect GetSpriteData(GUID guid) - { - return spriteImportMode == SpriteImportMode.Multiple ? m_SpritesMultiple.FirstOrDefault(x => x.spriteID == guid) : m_SpriteSingle; - } - - internal int GetSpriteDataIndex(GUID guid) - { - switch (spriteImportMode) - { - case SpriteImportMode.Single: - case SpriteImportMode.Polygon: - return 0; - case SpriteImportMode.Multiple: - { - return m_SpritesMultiple.FindIndex(x => x.spriteID == guid); - } - default: - throw new InvalidOperationException(string.Format("Sprite with GUID {0} not found", guid)); - } - } - - void ISpriteEditorDataProvider.Apply() - { - var so = new SerializedObject(this); - m_SpriteSingle.Apply(so); - var spriteSheetSO = so.FindProperty("m_SpriteSheet.m_Sprites"); - GUID[] guids = new GUID[spriteSheetSO.arraySize]; - for (int i = 0; i < spriteSheetSO.arraySize; ++i) - { - var element = spriteSheetSO.GetArrayElementAtIndex(i); - guids[i] = SpriteRect.GetSpriteIDFromSerializedProperty(element); - // find the GUID in our sprite list and apply to it; - var smd = m_SpritesMultiple.Find(x => x.spriteID == guids[i]); - if (smd == null) // we can't find it, it is already deleted - { - spriteSheetSO.DeleteArrayElementAtIndex(i); - --i; - } - else - smd.Apply(element); - } - - // Add new ones - var newSprites = m_SpritesMultiple.Where(x => !guids.Contains(x.spriteID)); - foreach (var newSprite in newSprites) - { - spriteSheetSO.InsertArrayElementAtIndex(spriteSheetSO.arraySize); - var element = spriteSheetSO.GetArrayElementAtIndex(spriteSheetSO.arraySize - 1); - newSprite.Apply(element); - } - so.ApplyModifiedPropertiesWithoutUndo(); - } - - void ISpriteEditorDataProvider.InitSpriteEditorDataProvider() - { - var so = new SerializedObject(this); - var spriteSheetSO = so.FindProperty("m_SpriteSheet.m_Sprites"); - m_SpritesMultiple = new List(); - m_SpriteSingle = new SpriteDataExt(so); - - for (int i = 0; i < spriteSheetSO.arraySize; ++i) - { - var sp = spriteSheetSO.GetArrayElementAtIndex(i); - var data = new SpriteDataExt(sp); - m_SpritesMultiple.Add(data); - } - } - - T ISpriteEditorDataProvider.GetDataProvider() - { - if (typeof(T) == typeof(ISpriteBoneDataProvider)) - { - return new SpriteBoneDataTransfer(this) as T; - } - if (typeof(T) == typeof(ISpriteMeshDataProvider)) - { - return new SpriteMeshDataTransfer(this) as T; - } - if (typeof(T) == typeof(ISpriteOutlineDataProvider)) - { - return new SpriteOutlineDataTransfer(this) as T; - } - if (typeof(T) == typeof(ISpritePhysicsOutlineDataProvider)) - { - return new SpritePhysicsOutlineDataTransfer(this) as T; - } - if (typeof(T) == typeof(ITextureDataProvider)) - { - return new SpriteTextureDataTransfer(this) as T; - } - else - return this as T; - } - - bool ISpriteEditorDataProvider.HasDataProvider(Type type) - { - if (type == typeof(ISpriteBoneDataProvider) || - type == typeof(ISpriteMeshDataProvider) || - type == typeof(ISpriteOutlineDataProvider) || - type == typeof(ISpritePhysicsOutlineDataProvider) || - type == typeof(ITextureDataProvider)) - { - return true; - } - else - return type.IsAssignableFrom(GetType()); - } - } -} diff --git a/Editor/Mono/Accessibility/UserAccessibilitySettings.cs b/Editor/Mono/Accessibility/UserAccessibilitySettings.cs deleted file mode 100644 index 9489dfa555..0000000000 --- a/Editor/Mono/Accessibility/UserAccessibilitySettings.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor.Accessibility -{ - internal enum ColorBlindCondition - { - Default, - Deuteranopia, - Protanopia, - Tritanopia, - } - - // NOTE: The preferences in this class are currently only exposed via a context menu in the ProfilerWindow - // these toggles need to instead be moved to e.g., the Preferences menu before they are used elsewhere - internal static class UserAccessiblitySettings - { - static UserAccessiblitySettings() - { - s_ColorBlindCondition = (ColorBlindCondition)EditorPrefs.GetInt(k_ColorBlindConditionPrefKey, (int)ColorBlindCondition.Default); - } - - private const string k_ColorBlindConditionPrefKey = "AccessibilityColorBlindCondition"; - - public static ColorBlindCondition colorBlindCondition - { - get { return s_ColorBlindCondition; } - set - { - if (s_ColorBlindCondition != value) - { - s_ColorBlindCondition = value; - EditorPrefs.SetInt(k_ColorBlindConditionPrefKey, (int)value); - if (colorBlindConditionChanged != null) - colorBlindConditionChanged(); - } - } - } - private static ColorBlindCondition s_ColorBlindCondition; - - public static Action colorBlindConditionChanged; - } -} diff --git a/Editor/Mono/Animation/AnimationClipSettings.bindings.cs b/Editor/Mono/Animation/AnimationClipSettings.bindings.cs deleted file mode 100644 index 3f31322e69..0000000000 --- a/Editor/Mono/Animation/AnimationClipSettings.bindings.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Runtime.InteropServices; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEngine.Playables; -using UnityEngine.Scripting.APIUpdating; -using UnityEngine.Internal; - -namespace UnityEditor -{ - [NativeType(CodegenOptions.Custom, "MonoAnimationClipSettings")] - [NativeAsStruct] - [StructLayout(LayoutKind.Sequential)] - [RequiredByNativeCode] - public class AnimationClipSettings - { - public AnimationClip additiveReferencePoseClip; - public float additiveReferencePoseTime; - public float startTime; - public float stopTime; - public float orientationOffsetY; - public float level; - public float cycleOffset; - public bool hasAdditiveReferencePose; - public bool loopTime; - public bool loopBlend; - public bool loopBlendOrientation; - public bool loopBlendPositionY; - public bool loopBlendPositionXZ; - public bool keepOriginalOrientation; - public bool keepOriginalPositionY; - public bool keepOriginalPositionXZ; - public bool heightFromFeet; - public bool mirror; - } -} diff --git a/Editor/Mono/Animation/AnimationClipStats.bindings.cs b/Editor/Mono/Animation/AnimationClipStats.bindings.cs deleted file mode 100644 index ffe13b88f3..0000000000 --- a/Editor/Mono/Animation/AnimationClipStats.bindings.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEngine.Playables; -using UnityEngine.Scripting.APIUpdating; -using UnityEngine.Internal; - -namespace UnityEditor -{ - // Must be kept in sync with AnimationClipStats in AnimationClipStats - internal struct AnimationClipStats - { - public int size; - public int positionCurves; - public int quaternionCurves; - public int eulerCurves; - public int scaleCurves; - public int muscleCurves; - public int genericCurves; - public int pptrCurves; - public int totalCurves; - public int constantCurves; - public int denseCurves; - public int streamCurves; - - public void Reset() - { - size = 0; - positionCurves = 0; - quaternionCurves = 0; - eulerCurves = 0; - scaleCurves = 0; - muscleCurves = 0; - genericCurves = 0; - pptrCurves = 0; - totalCurves = 0; - constantCurves = 0; - denseCurves = 0; - streamCurves = 0; - } - - public void Combine(AnimationClipStats other) - { - size += other.size; - positionCurves += other.positionCurves; - quaternionCurves += other.quaternionCurves; - eulerCurves += other.eulerCurves; - scaleCurves += other.scaleCurves; - muscleCurves += other.muscleCurves; - genericCurves += other.genericCurves; - pptrCurves += other.pptrCurves; - totalCurves += other.totalCurves; - constantCurves += other.constantCurves; - denseCurves += other.denseCurves; - streamCurves += other.streamCurves; - } - } -} diff --git a/Editor/Mono/Animation/AnimationMode.bindings.cs b/Editor/Mono/Animation/AnimationMode.bindings.cs deleted file mode 100644 index bc96ddf0b0..0000000000 --- a/Editor/Mono/Animation/AnimationMode.bindings.cs +++ /dev/null @@ -1,165 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEngine.Scripting.APIUpdating; -using UnityEngine; - -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AnimationModeDriver : ScriptableObject - { - internal delegate bool IsKeyCallback(Object target, string propertyPath); - - internal IsKeyCallback isKeyCallback; - - [UsedByNativeCode] - internal bool InvokeIsKeyCallback_Internal(Object target, string propertyPath) - { - if (isKeyCallback == null) - return false; - - return isKeyCallback(target, propertyPath); - } - } - - [NativeHeader("Editor/Src/Animation/AnimationMode.bindings.h")] - [NativeHeader("Editor/Src/Animation/EditorCurveBinding.bindings.h")] - [NativeHeader("Editor/Src/Prefabs/PropertyModification.h")] - public class AnimationMode - { - static private bool s_InAnimationPlaybackMode = false; - static private bool s_InAnimationRecordMode = false; - - 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); - 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); - 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); - - static public Color animatedPropertyColor { get { return s_AnimatedPropertyColor; } } - static public Color recordedPropertyColor { get { return s_RecordedPropertyColor; } } - static public Color candidatePropertyColor { get { return s_CandidatePropertyColor; } } - - static private AnimationModeDriver s_DummyDriver; - static private AnimationModeDriver DummyDriver() - { - if (s_DummyDriver == null) - { - s_DummyDriver = ScriptableObject.CreateInstance(); - s_DummyDriver.name = "DummyDriver"; - } - return s_DummyDriver; - } - - extern public static bool IsPropertyAnimated(Object target, string propertyPath); - extern internal static bool IsPropertyCandidate(Object target, string propertyPath); - - // Stops animation mode, as used by the animation editor. - public static void StopAnimationMode() - { - StopAnimationMode(DummyDriver()); - } - - // Stops animation mode, as used by the animation editor. - extern internal static void StopAnimationMode(Object driver); - - // Returns true if the editor is currently in animation mode. - public static bool InAnimationMode() - { - return Internal_InAnimationModeNoDriver(); - } - - // Returns true if the editor is currently in animation mode. - internal static bool InAnimationMode(Object driver) - { - return Internal_InAnimationMode(driver); - } - - // Starts animation mode, as used by the animation editor. - public static void StartAnimationMode() - { - StartAnimationMode(DummyDriver()); - } - - // Starts animation mode, as used by the animation editor. - extern internal static void StartAnimationMode(Object driver); - - // Stops animation playback mode, as used by the animation editor. - internal static void StopAnimationPlaybackMode() - { - s_InAnimationPlaybackMode = false; - } - - // Returns true if the editor is currently in animation playback mode. - internal static bool InAnimationPlaybackMode() - { - return s_InAnimationPlaybackMode; - } - - // Starts animation mode, as used by the animation editor playback mode. - internal static void StartAnimationPlaybackMode() - { - s_InAnimationPlaybackMode = true; - } - - internal static void StopAnimationRecording() - { - s_InAnimationRecordMode = false; - } - - internal static bool InAnimationRecording() - { - return s_InAnimationRecordMode; - } - - internal static void StartAnimationRecording() - { - s_InAnimationRecordMode = true; - } - - [NativeThrows] - extern internal static void StartCandidateRecording(Object driver); - - [NativeThrows] - extern internal static void AddCandidate(EditorCurveBinding binding, PropertyModification modification, bool keepPrefabOverride); - - extern internal static void StopCandidateRecording(); - - extern internal static bool IsRecordingCandidates(); - - [NativeThrows] - extern public static void BeginSampling(); - - [NativeThrows] - extern public static void EndSampling(); - - [NativeThrows] - extern public static void SampleAnimationClip(GameObject gameObject, AnimationClip clip, float time); - - [NativeThrows] - extern internal static void SampleCandidateClip(GameObject gameObject, AnimationClip clip, float time); - - [NativeThrows] - extern public static void AddPropertyModification(EditorCurveBinding binding, PropertyModification modification, bool keepPrefabOverride); - - [NativeThrows] - extern internal static void InitializePropertyModificationForGameObject(GameObject gameObject, AnimationClip clip); - - [NativeThrows] - extern internal static void InitializePropertyModificationForObject(Object target, AnimationClip clip); - - [NativeThrows] - extern internal static void RevertPropertyModificationsForGameObject(GameObject gameObject); - - [NativeThrows] - extern internal static void RevertPropertyModificationsForObject(Object target); - - extern private static bool Internal_InAnimationMode(Object driver); - - extern private static bool Internal_InAnimationModeNoDriver(); - } -} diff --git a/Editor/Mono/Animation/AnimationUtility.bindings.cs b/Editor/Mono/Animation/AnimationUtility.bindings.cs deleted file mode 100644 index fe42cf7063..0000000000 --- a/Editor/Mono/Animation/AnimationUtility.bindings.cs +++ /dev/null @@ -1,338 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEngine.Scripting.APIUpdating; -using UnityEngine; -using UnityEngine.Internal; - -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - public struct ObjectReferenceKeyframe - { - public float time; - public UnityEngine.Object value; - } - - // 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. - public class AnimationClipCurveData - { - // The path of the game object / bone being animated. - public string path; - // The type of the component / material being animated. - public Type type; - // The name of the property being animated. - public string propertyName; - // The actual animation curve. - public AnimationCurve curve; - - // This is only used internally for deleting curves - internal int classID; - internal int scriptInstanceID; - - public AnimationClipCurveData() - { - } - - public AnimationClipCurveData(EditorCurveBinding binding) - { - path = binding.path; - type = binding.type; - propertyName = binding.propertyName; - curve = null; - classID = binding.m_ClassID; - scriptInstanceID = binding.m_ScriptInstanceID; - } - } - - [NativeHeader("Editor/Src/Animation/AnimationUtility.bindings.h")] - public partial class AnimationUtility - { - public enum CurveModifiedType - { - CurveDeleted = 0, - CurveModified = 1, - ClipModified = 2 - } - - public enum TangentMode - { - Free = 0, - Auto = 1, - Linear = 2, - Constant = 3, - ClampedAuto = 4 - } - - internal enum PolynomialValid - { - Valid = 0, - InvalidPreWrapMode = 1, - InvalidPostWrapMode = 2, - TooManySegments = 3 - } - - public delegate void OnCurveWasModified(AnimationClip clip, EditorCurveBinding binding, CurveModifiedType type); - public static OnCurveWasModified onCurveWasModified; - - [RequiredByNativeCode] - private static void Internal_CallOnCurveWasModified(AnimationClip clip, EditorCurveBinding binding, CurveModifiedType type) - { - if (onCurveWasModified != null) - onCurveWasModified(clip, binding, type); - } - - [RequiredByNativeCode] - private static void Internal_CallAnimationClipAwake(AnimationClip clip) - { - if (onCurveWasModified != null) - onCurveWasModified(clip, new EditorCurveBinding(), CurveModifiedType.ClipModified); - } - - [Obsolete("GetAnimationClips(Animation) is deprecated. Use GetAnimationClips(GameObject) instead.")] - public static AnimationClip[] GetAnimationClips(Animation component) - { - return GetAnimationClips(component.gameObject); - } - - // Returns the array of AnimationClips that are referenced in the Animation component - extern public static AnimationClip[] GetAnimationClips([NotNull] GameObject gameObject); - - - // Sets the array of AnimationClips to be referenced in the Animation component - extern public static void SetAnimationClips([NotNull] Animation animation, AnimationClip[] clips); - - public static EditorCurveBinding[] GetAnimatableBindings(GameObject targetObject, GameObject root) - { - return Internal_GetGameObjectAnimatableBindings(targetObject, root); - } - - internal static EditorCurveBinding[] GetAnimatableBindings(ScriptableObject scriptableObject) - { - return Internal_GetScriptableObjectAnimatableBindings(scriptableObject); - } - - extern private static EditorCurveBinding[] Internal_GetGameObjectAnimatableBindings([NotNull] GameObject targetObject, [NotNull] GameObject root); - extern private static EditorCurveBinding[] Internal_GetScriptableObjectAnimatableBindings([NotNull] ScriptableObject scriptableObject); - - // 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) - // null if it can't be bound. - public static System.Type GetEditorCurveValueType(GameObject root, EditorCurveBinding binding) - { - return Internal_GetGameObjectEditorCurveValueType(root, binding); - } - - internal static System.Type GetEditorCurveValueType(ScriptableObject scriptableObject, EditorCurveBinding binding) - { - return Internal_GetScriptableObjectEditorCurveValueType(scriptableObject, binding); - } - - extern private static System.Type Internal_GetGameObjectEditorCurveValueType([NotNull] GameObject root, EditorCurveBinding binding); - extern private static System.Type Internal_GetScriptableObjectEditorCurveValueType([NotNull] ScriptableObject scriptableObject, EditorCurveBinding binding); - - extern public static bool GetFloatValue([NotNull] GameObject root, EditorCurveBinding binding, out float data); - //extern public static bool GetObjectReferenceValue([NotNull]GameObject root, [NotNull]EditorCurveBinding binding, out Object data); - - extern public static Object GetAnimatedObject([NotNull] GameObject root, EditorCurveBinding binding); - - //extern public static Type PropertyModificationToEditorCurveBinding(PropertyModification modification, [NotNull]GameObject gameObject, out EditorCurveBinding binding); - extern internal static PropertyModification EditorCurveBindingToPropertyModification(EditorCurveBinding binding, [NotNull] GameObject gameObject); - - extern public static EditorCurveBinding[] GetCurveBindings([NotNull] AnimationClip clip); - extern public static EditorCurveBinding[] GetObjectReferenceCurveBindings([NotNull] AnimationClip clip); - - extern public static ObjectReferenceKeyframe[] GetObjectReferenceCurve([NotNull] AnimationClip clip, EditorCurveBinding binding); - extern public static void SetObjectReferenceCurve([NotNull] AnimationClip clip, EditorCurveBinding binding, ObjectReferenceKeyframe[] keyframes); - - extern public static AnimationCurve GetEditorCurve([NotNull] AnimationClip clip, EditorCurveBinding binding); - extern public static void SetEditorCurve([NotNull] AnimationClip clip, EditorCurveBinding binding, AnimationCurve curve); - - // Todo. Should be converted to c++. - internal static void SetEditorCurves(AnimationClip clip, EditorCurveBinding[] bindings, AnimationCurve[] curves) - { - if (clip == null) - throw new ArgumentNullException("clip"); - if (curves == null) - throw new ArgumentNullException("curves"); - if (bindings == null) - throw new ArgumentNullException("bindings"); - - if (bindings.Length != curves.Length) - throw new ArgumentException("bindings and curves array sizes do not match"); - - for (int i = 0; i < bindings.Length; ++i) - { - Internal_SetEditorCurve(clip, bindings[i], curves[i], false); - - if (onCurveWasModified != null) - onCurveWasModified(clip, bindings[i], curves[i] != null ? CurveModifiedType.CurveModified : CurveModifiedType.CurveDeleted); - } - - Internal_SyncEditorCurves(clip); - } - - extern private static void Internal_SetEditorCurve(AnimationClip clip, EditorCurveBinding binding, AnimationCurve curve, bool syncEditorCurve); - extern private static void Internal_SyncEditorCurves(AnimationClip clip); - - [NativeThrows] - extern internal static void UpdateTangentsFromModeSurrounding([NotNull] AnimationCurve curve, int index); - - extern internal static void UpdateTangentsFromMode([NotNull] AnimationCurve curve); - - [NativeThrows] - extern public static TangentMode GetKeyLeftTangentMode([NotNull] AnimationCurve curve, int index); - - [NativeThrows] - extern public static TangentMode GetKeyRightTangentMode([NotNull] AnimationCurve curve, int index); - - [NativeThrows] - extern public static bool GetKeyBroken([NotNull] AnimationCurve curve, int index); - - [NativeThrows] - extern public static void SetKeyLeftTangentMode([NotNull] AnimationCurve curve, int index, TangentMode tangentMode); - - [NativeThrows] - extern public static void SetKeyRightTangentMode([NotNull] AnimationCurve curve, int index, TangentMode tangentMode); - - [NativeThrows] - extern public static void SetKeyBroken([NotNull] AnimationCurve curve, int index, bool broken); - - internal static TangentMode GetKeyLeftTangentMode(Keyframe key) - { - return Internal_GetKeyLeftTangentMode(key); - } - - internal static TangentMode GetKeyRightTangentMode(Keyframe key) - { - return Internal_GetKeyRightTangentMode(key); - } - - internal static bool GetKeyBroken(Keyframe key) - { - return Internal_GetKeyBroken(key); - } - - extern private static TangentMode Internal_GetKeyLeftTangentMode(Keyframe key); - extern private static TangentMode Internal_GetKeyRightTangentMode(Keyframe key); - extern private static bool Internal_GetKeyBroken(Keyframe key); - - internal static void SetKeyLeftTangentMode(ref Keyframe key, TangentMode tangentMode) - { - Internal_SetKeyLeftTangentMode(ref key, tangentMode); - } - - internal static void SetKeyRightTangentMode(ref Keyframe key, TangentMode tangentMode) - { - Internal_SetKeyRightTangentMode(ref key, tangentMode); - } - - internal static void SetKeyBroken(ref Keyframe key, bool broken) - { - Internal_SetKeyBroken(ref key, broken); - } - - extern private static void Internal_SetKeyLeftTangentMode(ref Keyframe key, TangentMode tangentMode); - extern private static void Internal_SetKeyRightTangentMode(ref Keyframe key, TangentMode tangentMode); - extern private static void Internal_SetKeyBroken(ref Keyframe key, bool broken); - - extern internal static int AddInbetweenKey(AnimationCurve curve, float time); - - [Obsolete("GetAllCurves is deprecated. Use GetCurveBindings and GetObjectReferenceCurveBindings instead.")] - public static AnimationClipCurveData[] GetAllCurves(AnimationClip clip) - { - bool includeCurveData = true; - return GetAllCurves(clip, includeCurveData); - } - - [Obsolete("GetAllCurves is deprecated. Use GetCurveBindings and GetObjectReferenceCurveBindings instead.")] - public static AnimationClipCurveData[] GetAllCurves(AnimationClip clip, [DefaultValue("true")] bool includeCurveData) - { - EditorCurveBinding[] bindings = GetCurveBindings(clip); - - AnimationClipCurveData[] curves = new AnimationClipCurveData[bindings.Length]; - for (int i = 0; i < curves.Length; i++) - { - curves[i] = new AnimationClipCurveData(bindings[i]); - - if (includeCurveData) - curves[i].curve = GetEditorCurve(clip, bindings[i]); - } - - return curves; - } - - [Obsolete("This overload is deprecated. Use the one with EditorCurveBinding instead.")] - public static bool GetFloatValue(GameObject root, string relativePath, Type type, string propertyName, out float data) - { - return GetFloatValue(root, EditorCurveBinding.FloatCurve(relativePath, type, propertyName), out data); - } - - [Obsolete("This overload is deprecated. Use the one with EditorCurveBinding instead.")] - public static void SetEditorCurve(AnimationClip clip, string relativePath, Type type, string propertyName, AnimationCurve curve) - { - SetEditorCurve(clip, EditorCurveBinding.FloatCurve(relativePath, type, propertyName), curve); - } - - [Obsolete("This overload is deprecated. Use the one with EditorCurveBinding instead.")] - public static AnimationCurve GetEditorCurve(AnimationClip clip, string relativePath, Type type, string propertyName) - { - return GetEditorCurve(clip, EditorCurveBinding.FloatCurve(relativePath, type, propertyName)); - } - - extern public static AnimationEvent[] GetAnimationEvents([NotNull] AnimationClip clip); - extern public static void SetAnimationEvents([NotNull] AnimationClip clip, [NotNull] AnimationEvent[] events); - - extern public static string CalculateTransformPath([NotNull] Transform targetTransform, Transform root); - - extern public static AnimationClipSettings GetAnimationClipSettings([NotNull] AnimationClip clip); - extern public static void SetAnimationClipSettings([NotNull] AnimationClip clip, AnimationClipSettings srcClipInfo); - extern internal static void SetAnimationClipSettingsNoDirty([NotNull] AnimationClip clip, AnimationClipSettings srcClipInfo); - - extern public static void SetAdditiveReferencePose(AnimationClip clip, AnimationClip referenceClip, float time); - - extern internal static bool IsValidOptimizedPolynomialCurve(AnimationCurve curve); - extern public static void ConstrainToPolynomialCurve(AnimationCurve curve); - extern internal static int GetMaxNumPolynomialSegmentsSupported(); - extern internal static PolynomialValid IsValidPolynomialCurve(AnimationCurve curve); - - extern internal static AnimationClipStats GetAnimationClipStats(AnimationClip clip); - - extern public static bool GetGenerateMotionCurves(AnimationClip clip); - extern public static void SetGenerateMotionCurves(AnimationClip clip, bool value); - extern internal static bool HasGenericRootTransform(AnimationClip clip); - extern internal static bool HasMotionFloatCurves(AnimationClip clip); - extern internal static bool HasMotionCurves(AnimationClip clip); - extern internal static bool HasRootCurves(AnimationClip clip); - - extern internal static bool AmbiguousBinding(string path, int classID, Transform root); - - extern internal static Vector3 GetClosestEuler(Quaternion q, Vector3 eulerHint, RotationOrder rotationOrder); - - [Obsolete("Use AnimationMode.InAnimationMode instead.")] - static public bool InAnimationMode() - { - return AnimationMode.InAnimationMode(); - } - - [Obsolete("Use AnimationMode.StartAnimationmode instead.")] - public static void StartAnimationMode(Object[] objects) - { - 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"); - AnimationMode.StartAnimationMode(); - } - - [Obsolete("Use AnimationMode.StopAnimationMode instead.")] - public static void StopAnimationMode() - { - AnimationMode.StopAnimationMode(); - } - - [Obsolete("SetAnimationType is no longer supported.")] - public static void SetAnimationType(AnimationClip clip, ModelImporterAnimationType type) {} - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs deleted file mode 100644 index e0c480b1d0..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using System; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal class AddCurvesPopup : EditorWindow - { - const float k_WindowPadding = 3; - - internal static AnimationWindowState s_State; - - private static AddCurvesPopup s_AddCurvesPopup; - private static long s_LastClosedTime; - private static AddCurvesPopupHierarchy s_Hierarchy; - - private static Vector2 windowSize = new Vector2(240, 250); - - public delegate void OnNewCurveAdded(AddCurvesPopupPropertyNode node); - - private static OnNewCurveAdded NewCurveAddedCallback; - - void Init(Rect buttonRect) - { - buttonRect = GUIUtility.GUIToScreenRect(buttonRect); - ShowAsDropDown(buttonRect, windowSize, new[] { PopupLocationHelper.PopupLocation.Right }); - } - - void OnEnable() - { - AssemblyReloadEvents.beforeAssemblyReload += Close; - } - - void OnDisable() - { - AssemblyReloadEvents.beforeAssemblyReload -= Close; - s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - s_AddCurvesPopup = null; - s_Hierarchy = null; - } - - internal static void AddNewCurve(AddCurvesPopupPropertyNode node) - { - AnimationWindowUtility.CreateDefaultCurves(s_State, node.curveBindings); - if (NewCurveAddedCallback != null) - NewCurveAddedCallback(node); - } - - internal static bool ShowAtPosition(Rect buttonRect, AnimationWindowState state, OnNewCurveAdded newCurveCallback) - { - // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time. - long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - bool justClosed = nowMilliSeconds < s_LastClosedTime + 50; - if (!justClosed) - { - Event.current.Use(); - if (s_AddCurvesPopup == null) - s_AddCurvesPopup = ScriptableObject.CreateInstance(); - - NewCurveAddedCallback = newCurveCallback; - s_State = state; - s_AddCurvesPopup.Init(buttonRect); - return true; - } - return false; - } - - internal void OnGUI() - { - // We do not use the layout event - if (Event.current.type == EventType.Layout) - return; - - if (s_Hierarchy == null) - s_Hierarchy = new AddCurvesPopupHierarchy(); - - Rect rect = new Rect(1, 1, windowSize.x - k_WindowPadding, windowSize.y - k_WindowPadding); - GUI.Box(new Rect(0, 0, windowSize.x, windowSize.y), GUIContent.none, new GUIStyle("grey_border")); - s_Hierarchy.OnGUI(rect, this); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs deleted file mode 100644 index 8a40d82b1b..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditorInternal -{ - internal class AddCurvesPopupHierarchy - { - private TreeViewController m_TreeView; - private TreeViewState m_TreeViewState; - private AddCurvesPopupHierarchyDataSource m_TreeViewDataSource; - - public void OnGUI(Rect position, EditorWindow owner) - { - InitIfNeeded(owner, position); - m_TreeView.OnEvent(); - m_TreeView.OnGUI(position, GUIUtility.GetControlID(FocusType.Keyboard)); - } - - public void InitIfNeeded(EditorWindow owner, Rect rect) - { - if (m_TreeViewState == null) - m_TreeViewState = new TreeViewState(); - else - return; - - m_TreeView = new TreeViewController(owner, m_TreeViewState); - - m_TreeView.deselectOnUnhandledMouseDown = true; - - m_TreeViewDataSource = new AddCurvesPopupHierarchyDataSource(m_TreeView); - TreeViewGUI gui = new AddCurvesPopupHierarchyGUI(m_TreeView, owner); - - m_TreeView.Init(rect, - m_TreeViewDataSource, - gui, - null - ); - - m_TreeViewDataSource.UpdateData(); - } - - internal virtual bool IsRenamingNodeAllowed(TreeViewItem node) - { - return false; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs deleted file mode 100644 index b944bfb74b..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs +++ /dev/null @@ -1,259 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using System; -using System.Linq; -using UnityEditor.IMGUI.Controls; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal class AddCurvesPopupHierarchyDataSource : TreeViewDataSource - { - public static bool showEntireHierarchy { get; set; } - - public AddCurvesPopupHierarchyDataSource(TreeViewController treeView) - : base(treeView) - { - showRootItem = false; - rootIsCollapsable = false; - } - - private void SetupRootNodeSettings() - { - showRootItem = false; - SetExpanded(root, true); - } - - public override void FetchData() - { - if (AddCurvesPopup.s_State.selection.canAddCurves) - { - GameObject rootGameObject = AddCurvesPopup.s_State.activeRootGameObject; - ScriptableObject scriptableObject = AddCurvesPopup.s_State.activeScriptableObject; - - if (rootGameObject != null) - { - AddGameObjectToHierarchy(rootGameObject, rootGameObject, AddCurvesPopup.s_State.activeAnimationClip, m_RootItem); - } - else if (scriptableObject != null) - { - AddScriptableObjectToHierarchy(scriptableObject, AddCurvesPopup.s_State.activeAnimationClip, m_RootItem); - } - } - - SetupRootNodeSettings(); - m_NeedRefreshRows = true; - } - - private TreeViewItem AddGameObjectToHierarchy(GameObject gameObject, GameObject rootGameObject, AnimationClip animationClip, TreeViewItem parent) - { - string path = AnimationUtility.CalculateTransformPath(gameObject.transform, rootGameObject.transform); - TreeViewItem node = new AddCurvesPopupGameObjectNode(gameObject, parent, gameObject.name); - List childNodes = new List(); - - if (m_RootItem == null) - m_RootItem = node; - - // Iterate over all animatable objects - EditorCurveBinding[] allCurveBindings = AnimationUtility.GetAnimatableBindings(gameObject, rootGameObject); - List singleObjectBindings = new List(); - for (int i = 0; i < allCurveBindings.Length; i++) - { - EditorCurveBinding curveBinding = allCurveBindings[i]; - - singleObjectBindings.Add(curveBinding); - - // Don't create group for GameObject.m_IsActive. It looks messy - if (curveBinding.propertyName == "m_IsActive") - { - // Don't show for the root go - if (curveBinding.path != "") - { - TreeViewItem newNode = CreateNode(singleObjectBindings.ToArray(), node); - if (newNode != null) - childNodes.Add(newNode); - singleObjectBindings.Clear(); - } - else - { - singleObjectBindings.Clear(); - } - } - else - { - // We expect allCurveBindings to come sorted by type - - bool isLastItemOverall = (i == allCurveBindings.Length - 1); - bool isLastItemOnThisGroup = false; - - if (!isLastItemOverall) - isLastItemOnThisGroup = (allCurveBindings[i + 1].type != curveBinding.type); - - // Let's not add those that already have a existing curve. - if (AnimationWindowUtility.IsCurveCreated(animationClip, curveBinding)) - singleObjectBindings.Remove(curveBinding); - - // Remove animator enabled property which shouldn't be animated. - if (curveBinding.type == typeof(Animator) && curveBinding.propertyName == "m_Enabled") - singleObjectBindings.Remove(curveBinding); - - if ((isLastItemOverall || isLastItemOnThisGroup) && singleObjectBindings.Count > 0) - { - childNodes.Add(AddAnimatableObjectToHierarchy(singleObjectBindings.ToArray(), node, path)); - singleObjectBindings.Clear(); - } - } - } - - if (showEntireHierarchy) - { - // Iterate over all child GOs - for (int i = 0; i < gameObject.transform.childCount; i++) - { - Transform childTransform = gameObject.transform.GetChild(i); - TreeViewItem childNode = AddGameObjectToHierarchy(childTransform.gameObject, rootGameObject, animationClip, node); - if (childNode != null) - childNodes.Add(childNode); - } - } - - TreeViewUtility.SetChildParentReferences(childNodes, node); - return node; - } - - private TreeViewItem AddScriptableObjectToHierarchy(ScriptableObject scriptableObject, AnimationClip clip, TreeViewItem parent) - { - EditorCurveBinding[] allCurveBindings = AnimationUtility.GetAnimatableBindings(scriptableObject); - EditorCurveBinding[] availableBindings = allCurveBindings.Where(c => !AnimationWindowUtility.IsCurveCreated(clip, c)).ToArray(); - - TreeViewItem node = null; - if (availableBindings.Length > 0) - node = AddAnimatableObjectToHierarchy(availableBindings, parent, ""); - else - node = new AddCurvesPopupObjectNode(parent, "", scriptableObject.name); - - if (m_RootItem == null) - m_RootItem = node; - - return node; - } - - static string GetClassName(EditorCurveBinding binding) - { - if (AddCurvesPopup.s_State.activeRootGameObject != null) - { - Object target = AnimationUtility.GetAnimatedObject(AddCurvesPopup.s_State.activeRootGameObject, binding); - if (target) - return ObjectNames.GetInspectorTitle(target); - } - - return binding.type.Name; - } - - static Texture2D GetIcon(EditorCurveBinding binding) - { - if (AddCurvesPopup.s_State.activeRootGameObject != null) - { - return AssetPreview.GetMiniThumbnail(AnimationUtility.GetAnimatedObject(AddCurvesPopup.s_State.activeRootGameObject, binding)); - } - else if (AddCurvesPopup.s_State.activeScriptableObject != null) - { - return AssetPreview.GetMiniThumbnail(AddCurvesPopup.s_State.activeScriptableObject); - } - - return null; - } - - private TreeViewItem AddAnimatableObjectToHierarchy(EditorCurveBinding[] curveBindings, TreeViewItem parentNode, string path) - { - TreeViewItem node = new AddCurvesPopupObjectNode(parentNode, path, GetClassName(curveBindings[0])); - node.icon = GetIcon(curveBindings[0]); - - List childNodes = new List(); - List singlePropertyBindings = new List(); - - for (int i = 0; i < curveBindings.Length; i++) - { - EditorCurveBinding curveBinding = curveBindings[i]; - - singlePropertyBindings.Add(curveBinding); - - // We expect curveBindings to come sorted by propertyname - if (i == curveBindings.Length - 1 || AnimationWindowUtility.GetPropertyGroupName(curveBindings[i + 1].propertyName) != AnimationWindowUtility.GetPropertyGroupName(curveBinding.propertyName)) - { - TreeViewItem newNode = CreateNode(singlePropertyBindings.ToArray(), node); - if (newNode != null) - childNodes.Add(newNode); - singlePropertyBindings.Clear(); - } - } - - childNodes.Sort(); - - TreeViewUtility.SetChildParentReferences(childNodes, node); - return node; - } - - private TreeViewItem CreateNode(EditorCurveBinding[] curveBindings, TreeViewItem parentNode) - { - var node = new AddCurvesPopupPropertyNode(parentNode, curveBindings); - - // For RectTransform.position we only want .z - if (AnimationWindowUtility.IsRectTransformPosition(node.curveBindings[0])) - node.curveBindings = new EditorCurveBinding[] {node.curveBindings[2]}; - - node.icon = parentNode.icon; - return node; - } - - public void UpdateData() - { - m_TreeView.ReloadData(); - } - } - - internal class AddCurvesPopupGameObjectNode : TreeViewItem - { - public AddCurvesPopupGameObjectNode(GameObject gameObject, TreeViewItem parent, string displayName) - : base(gameObject.GetInstanceID(), parent != null ? parent.depth + 1 : -1, parent, displayName) - { - } - } - - internal class AddCurvesPopupObjectNode : TreeViewItem - { - public AddCurvesPopupObjectNode(TreeViewItem parent, string path, string className) - : base((path + className).GetHashCode(), parent != null ? parent.depth + 1 : -1, parent, className) - { - } - } - - internal class AddCurvesPopupPropertyNode : TreeViewItem - { - public EditorCurveBinding[] curveBindings; - - public AddCurvesPopupPropertyNode(TreeViewItem parent, EditorCurveBinding[] curveBindings) - : base(curveBindings[0].GetHashCode(), parent.depth + 1, parent, AnimationWindowUtility.NicifyPropertyGroupName(curveBindings[0].type, AnimationWindowUtility.GetPropertyGroupName(curveBindings[0].propertyName))) - { - this.curveBindings = curveBindings; - } - - public override int CompareTo(TreeViewItem other) - { - AddCurvesPopupPropertyNode otherNode = other as AddCurvesPopupPropertyNode; - if (otherNode != null) - { - if (displayName.Contains("Rotation") && otherNode.displayName.Contains("Position")) - return 1; - if (displayName.Contains("Position") && otherNode.displayName.Contains("Rotation")) - return -1; - } - return base.CompareTo(other); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs deleted file mode 100644 index 96a9629b41..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditorInternal -{ - internal class AddCurvesPopupHierarchyGUI : TreeViewGUI - { - public EditorWindow owner; - public bool showPlusButton { get; set; } - private GUIStyle plusButtonStyle = new GUIStyle("OL Plus"); - private GUIStyle plusButtonBackgroundStyle = new GUIStyle("Tag MenuItem"); - private const float plusButtonWidth = 17; - - public AddCurvesPopupHierarchyGUI(TreeViewController treeView, EditorWindow owner) - : base(treeView, true) - { - this.owner = owner; - } - - public override void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool selected, bool focused) - { - base.OnRowGUI(rowRect, node, row, selected, focused); - - // Is it propertynode. If not, then we don't need plusButton so quit here - AddCurvesPopupPropertyNode hierarchyNode = node as AddCurvesPopupPropertyNode; - if (hierarchyNode == null || hierarchyNode.curveBindings == null || hierarchyNode.curveBindings.Length == 0) - return; - - Rect buttonRect = new Rect(rowRect.width - plusButtonWidth, rowRect.yMin, plusButtonWidth, plusButtonStyle.fixedHeight); - - // TODO Make a style for add curves popup - // Draw background behind plus button to prevent text overlapping - GUI.Box(buttonRect, GUIContent.none, plusButtonBackgroundStyle); - - // Check if the curve already exists and remove plus button - if (GUI.Button(buttonRect, GUIContent.none, plusButtonStyle)) - { - AddCurvesPopup.AddNewCurve(hierarchyNode); - owner.Close(); - } - } - - override protected void SyncFakeItem() - { - //base.SyncFakeItem(); - } - - override protected void RenameEnded() - { - //base.RenameEnded(); - } - - override protected bool IsRenaming(int id) - { - return false; - } - - public override bool BeginRename(TreeViewItem item, float delay) - { - return false; - } - - override protected Texture GetIconForItem(TreeViewItem item) - { - if (item != null) - return item.icon; - - return null; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs b/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs deleted file mode 100644 index e02cdb66f7..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs +++ /dev/null @@ -1,1248 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal enum WrapModeFixed - { - Default = (int)WrapMode.Default, - Once = (int)WrapMode.Once, - Loop = (int)WrapMode.Loop, - ClampForever = (int)WrapMode.ClampForever, - PingPong = (int)WrapMode.PingPong - } - - internal class AnimEditor : ScriptableObject - { - // Active Animation windows - private static List s_AnimationWindows = new List(); - public static List GetAllAnimationWindows() { return s_AnimationWindows; } - public bool stateDisabled { get { return m_State.disabled; } } - - [SerializeField] private SplitterState m_HorizontalSplitter; - [SerializeField] private AnimationWindowState m_State; - [SerializeField] private DopeSheetEditor m_DopeSheet; - [SerializeField] private AnimationWindowHierarchy m_Hierarchy; - [SerializeField] private AnimationWindowClipPopup m_ClipPopup; - [SerializeField] private AnimationEventTimeLine m_Events; - [SerializeField] private CurveEditor m_CurveEditor; - [SerializeField] private AnimEditorOverlay m_Overlay; - [SerializeField] private EditorWindow m_OwnerWindow; - - [System.NonSerialized] private Rect m_Position; - [System.NonSerialized] private bool m_TriggerFraming; - [System.NonSerialized] private bool m_Initialized; - - private float hierarchyWidth { get { return m_HorizontalSplitter.realSizes[0]; } } - private float contentWidth { get { return m_HorizontalSplitter.realSizes[1]; } } - - internal static PrefColor kEulerXColor = new PrefColor("Animation/EulerX", 1.0f, 0.0f, 1.0f, 1.0f); - internal static PrefColor kEulerYColor = new PrefColor("Animation/EulerY", 1.0f, 1.0f, 0.0f, 1.0f); - internal static PrefColor kEulerZColor = new PrefColor("Animation/EulerZ", 0.0f, 1.0f, 1.0f, 1.0f); - - static private Color s_SelectionRangeColorLight = new Color32(255, 255, 255, 90); - static private Color s_SelectionRangeColorDark = new Color32(200, 200, 200, 40); - - static private Color selectionRangeColor - { - get - { - return EditorGUIUtility.isProSkin ? s_SelectionRangeColorDark : s_SelectionRangeColorLight; - } - } - - static private Color s_OutOfRangeColorLight = new Color32(160, 160, 160, 127); - static private Color s_OutOfRangeColorDark = new Color32(40, 40, 40, 127); - - static private Color outOfRangeColor - { - get - { - return EditorGUIUtility.isProSkin ? s_OutOfRangeColorDark : s_OutOfRangeColorLight; - } - } - - static private Color s_InRangeColorLight = new Color32(211, 211, 211, 255); - static private Color s_InRangeColorDark = new Color32(75, 75, 75, 255); - - static private Color inRangeColor - { - get - { - return EditorGUIUtility.isProSkin ? s_InRangeColorDark : s_InRangeColorLight; - } - } - - internal static PrefKey kAnimationPlayToggle = new PrefKey("Animation/Play Animation", " "); - internal static PrefKey kAnimationPrevFrame = new PrefKey("Animation/Previous Frame", ","); - internal static PrefKey kAnimationNextFrame = new PrefKey("Animation/Next Frame", "."); - internal static PrefKey kAnimationPrevKeyframe = new PrefKey("Animation/Previous Keyframe", "&,"); - internal static PrefKey kAnimationNextKeyframe = new PrefKey("Animation/Next Keyframe", "&."); - internal static PrefKey kAnimationFirstKey = new PrefKey("Animation/First Keyframe", "#,"); - internal static PrefKey kAnimationLastKey = new PrefKey("Animation/Last Keyframe", "#."); - internal static PrefKey kAnimationRecordKeyframeSelected = new PrefKey("Animation/Key Selected", "k"); - internal static PrefKey kAnimationRecordKeyframeModified = new PrefKey("Animation/Key Modified", "#k"); - internal static PrefKey kAnimationShowCurvesToggle = new PrefKey("Animation/Show Curves", "c"); - - internal const int kSliderThickness = 15; - internal const int kLayoutRowHeight = EditorGUI.kWindowToolbarHeight + 1; - internal const int kIntFieldWidth = 35; - internal const int kHierarchyMinWidth = 300; - internal const int kToggleButtonWidth = 80; - internal const float kDisabledRulerAlpha = 0.12f; - - public AnimationWindowState state { get { return m_State; } } - - public AnimationWindowSelectionItem selection - { - get - { - return m_State.selection; - } - - set - { - m_State.selection = value; - } - } - - public IAnimationWindowControl controlInterface - { - get - { - return state.controlInterface; - } - } - - public IAnimationWindowControl overrideControlInterface - { - get - { - return state.overrideControlInterface; - } - - set - { - state.overrideControlInterface = value; - } - } - - private bool triggerFraming - { - set - { - m_TriggerFraming = value; - } - - get - { - return m_TriggerFraming; - } - } - - internal CurveEditor curveEditor { get { return m_CurveEditor; } } - internal DopeSheetEditor dopeSheetEditor { get { return m_DopeSheet; } } - - public void OnAnimEditorGUI(EditorWindow parent, Rect position) - { - m_DopeSheet.m_Owner = parent; - m_OwnerWindow = parent; - m_Position = position; - - if (!m_Initialized) - Initialize(); - - m_State.OnGUI(); - - if (m_State.disabled && controlInterface.recording) - m_State.StopRecording(); - - SynchronizeLayout(); - - using (new EditorGUI.DisabledScope(m_State.disabled || m_State.animatorIsOptimized)) - { - OverlayEventOnGUI(); - - GUILayout.BeginHorizontal(); - SplitterGUILayout.BeginHorizontalSplit(m_HorizontalSplitter); - - // Left side - GUILayout.BeginVertical(); - - // First row of controls - GUILayout.BeginHorizontal(EditorStyles.toolbarButton); - PlayControlsOnGUI(); - GUILayout.EndHorizontal(); - - // Second row of controls - GUILayout.BeginHorizontal(EditorStyles.toolbarButton); - LinkOptionsOnGUI(); - ClipSelectionDropDownOnGUI(); - GUILayout.FlexibleSpace(); - FrameRateInputFieldOnGUI(); - AddKeyframeButtonOnGUI(); - AddEventButtonOnGUI(); - GUILayout.EndHorizontal(); - - HierarchyOnGUI(); - - // Bottom row of controls - GUILayout.BeginHorizontal(AnimationWindowStyles.miniToolbar); - TabSelectionOnGUI(); - GUILayout.EndHorizontal(); - - GUILayout.EndVertical(); - - // Right side - GUILayout.BeginVertical(); - - // Acquire Rects - Rect timerulerRect = GUILayoutUtility.GetRect(contentWidth, kLayoutRowHeight); - Rect eventsRect = GUILayoutUtility.GetRect(contentWidth, kLayoutRowHeight); - Rect contentLayoutRect = GUILayoutUtility.GetRect(contentWidth, contentWidth, 0f, float.MaxValue, GUILayout.ExpandHeight(true)); - - // MainContent must be done first since it resizes the Zoomable area. - MainContentOnGUI(contentLayoutRect); - TimeRulerOnGUI(timerulerRect); - EventLineOnGUI(eventsRect); - GUILayout.EndVertical(); - - SplitterGUILayout.EndHorizontalSplit(); - GUILayout.EndHorizontal(); - - // Overlay - OverlayOnGUI(contentLayoutRect); - - RenderEventTooltip(); - - HandleHotKeys(); - } - } - - private void MainContentOnGUI(Rect contentLayoutRect) - { - // Bail out if the hierarchy in animator is optimized. - if (m_State.animatorIsOptimized) - { - Vector2 textSize = GUI.skin.label.CalcSize(AnimationWindowStyles.animatorOptimizedText); - Rect labelRect = new Rect(contentLayoutRect.x + contentLayoutRect.width * .5f - textSize.x * .5f, contentLayoutRect.y + contentLayoutRect.height * .5f - textSize.y * .5f, textSize.x, textSize.y); - GUI.Label(labelRect, AnimationWindowStyles.animatorOptimizedText); - return; - } - - - if (m_State.disabled) - { - SetupWizardOnGUI(contentLayoutRect); - } - else - { - Event evt = Event.current; - if (evt.type == EventType.MouseDown && contentLayoutRect.Contains(evt.mousePosition)) - m_Events.ClearSelection(); - - if (triggerFraming && evt.type == EventType.Repaint) - { - m_DopeSheet.FrameClip(); - m_CurveEditor.FrameClip(true, true); - - triggerFraming = false; - } - - if (m_State.showCurveEditor) - { - CurveEditorOnGUI(contentLayoutRect); - } - else - { - DopeSheetOnGUI(contentLayoutRect); - } - } - - HandleCopyPaste(); - } - - private void OverlayEventOnGUI() - { - if (m_State.animatorIsOptimized) - return; - - if (m_State.disabled) - return; - - Rect overlayRect = new Rect(hierarchyWidth - 1, 0f, contentWidth - kSliderThickness, m_Position.height - kSliderThickness); - - GUI.BeginGroup(overlayRect); - m_Overlay.HandleEvents(); - GUI.EndGroup(); - } - - private void OverlayOnGUI(Rect contentRect) - { - if (m_State.animatorIsOptimized) - return; - - if (m_State.disabled) - return; - - if (Event.current.type != EventType.Repaint) - return; - - Rect contentRectNoSliders = new Rect(contentRect.xMin, contentRect.yMin, contentRect.width - kSliderThickness, contentRect.height - kSliderThickness); - Rect overlayRectNoSliders = new Rect(hierarchyWidth - 1, 0f, contentWidth - kSliderThickness, m_Position.height - kSliderThickness); - - GUI.BeginGroup(overlayRectNoSliders); - - Rect localRect = new Rect(0, 0, overlayRectNoSliders.width, overlayRectNoSliders.height); - - Rect localContentRect = contentRectNoSliders; - localContentRect.position -= overlayRectNoSliders.min; - - m_Overlay.OnGUI(localRect, localContentRect); - - GUI.EndGroup(); - } - - public void Update() - { - if (m_State == null) - return; - - PlaybackUpdate(); - } - - public void OnEnable() - { - hideFlags = HideFlags.HideAndDontSave; - s_AnimationWindows.Add(this); - - if (m_State == null) - { - m_State = CreateInstance(typeof(AnimationWindowState)) as AnimationWindowState; - m_State.hideFlags = HideFlags.HideAndDontSave; - m_State.animEditor = this; - InitializeHorizontalSplitter(); - InitializeClipSelection(); - InitializeDopeSheet(); - InitializeEvents(); - InitializeCurveEditor(); - InitializeOverlay(); - } - - InitializeNonserializedValues(); - - m_State.timeArea = m_State.showCurveEditor ? (TimeArea)m_CurveEditor : m_DopeSheet; - m_DopeSheet.state = m_State; - m_ClipPopup.state = m_State; - m_Overlay.state = m_State; - - m_CurveEditor.curvesUpdated += SaveChangedCurvesFromCurveEditor; - m_CurveEditor.OnEnable(); - - EditorApplication.globalEventHandler += HandleGlobalHotkeys; - } - - public void OnDisable() - { - s_AnimationWindows.Remove(this); - - if (m_CurveEditor != null) - { - m_CurveEditor.curvesUpdated -= SaveChangedCurvesFromCurveEditor; - m_CurveEditor.OnDisable(); - } - - if (m_DopeSheet != null) - m_DopeSheet.OnDisable(); - - m_State.OnDisable(); - - EditorApplication.globalEventHandler -= HandleGlobalHotkeys; - } - - public void OnDestroy() - { - if (m_CurveEditor != null) - m_CurveEditor.OnDestroy(); - - DestroyImmediate(m_State); - } - - public void OnSelectionChanged() - { - triggerFraming = true; // Framing of clip can only be done after Layout. Here we just order it to happen later on. - Repaint(); - } - - public void OnStartLiveEdit() - { - SaveCurveEditorKeySelection(); - } - - public void OnEndLiveEdit() - { - UpdateSelectedKeysToCurveEditor(); - controlInterface.ResampleAnimation(); - } - - public void OnLostFocus() - { - // RenameOverlay might still be active, close before switching to another window. - if (m_Hierarchy != null) - m_Hierarchy.EndNameEditing(true); - - // Stop text editing. FrameRate ui or Frame ui may still be in edition mode. - EditorGUI.EndEditingActiveTextField(); - } - - private void PlaybackUpdate() - { - if (m_State.disabled && controlInterface.playing) - controlInterface.StopPlayback(); - - if (controlInterface.PlaybackUpdate()) - Repaint(); - } - - private void SetupWizardOnGUI(Rect position) - { - GUI.Label(position, GUIContent.none, AnimationWindowStyles.dopeSheetBackground); - - Rect positionWithoutScrollBar = new Rect(position.x, position.y, position.width - kSliderThickness, position.height - kSliderThickness); - GUI.BeginClip(positionWithoutScrollBar); - GUI.enabled = true; - - m_State.showCurveEditor = false; - m_State.timeArea = m_DopeSheet; - m_State.timeArea.SetShownHRangeInsideMargins(0f, 1f); - - bool animatableObject = m_State.activeGameObject && !EditorUtility.IsPersistent(m_State.activeGameObject); - - if (animatableObject) - { - var missingObjects = (!m_State.activeRootGameObject && !m_State.activeAnimationClip) ? AnimationWindowStyles.animatorAndAnimationClip.text : AnimationWindowStyles.animationClip.text; - - string txt = String.Format(AnimationWindowStyles.formatIsMissing.text, m_State.activeGameObject.name, missingObjects); - - const float buttonWidth = 70f; - const float buttonHeight = 20f; - const float buttonPadding = 3f; - - GUIContent textContent = GUIContent.Temp(txt); - Vector2 textSize = GUI.skin.label.CalcSize(textContent); - Rect labelRect = new Rect(positionWithoutScrollBar.width * .5f - textSize.x * .5f, positionWithoutScrollBar.height * .5f - textSize.y * .5f, textSize.x, textSize.y); - GUI.Label(labelRect, textContent); - - Rect buttonRect = new Rect(positionWithoutScrollBar.width * .5f - buttonWidth * .5f, labelRect.yMax + buttonPadding, buttonWidth, buttonHeight); - - if (GUI.Button(buttonRect, AnimationWindowStyles.create)) - { - if (AnimationWindowUtility.InitializeGameobjectForAnimation(m_State.activeGameObject)) - { - Component animationPlayer = AnimationWindowUtility.GetClosestAnimationPlayerComponentInParents(m_State.activeGameObject.transform); - m_State.activeAnimationClip = AnimationUtility.GetAnimationClips(animationPlayer.gameObject)[0]; - } - - // Layout has changed, bail out now. - EditorGUIUtility.ExitGUI(); - } - } - else - { - Color oldColor = GUI.color; - GUI.color = Color.gray; - Vector2 textSize = GUI.skin.label.CalcSize(AnimationWindowStyles.noAnimatableObjectSelectedText); - Rect labelRect = new Rect(positionWithoutScrollBar.width * .5f - textSize.x * .5f, positionWithoutScrollBar.height * .5f - textSize.y * .5f, textSize.x, textSize.y); - GUI.Label(labelRect, AnimationWindowStyles.noAnimatableObjectSelectedText); - GUI.color = oldColor; - } - GUI.EndClip(); - GUI.enabled = false; // Reset state to false. It's always false originally for SetupWizardOnGUI. - } - - private void EventLineOnGUI(Rect eventsRect) - { - eventsRect.width -= kSliderThickness; - GUI.Label(eventsRect, GUIContent.none, AnimationWindowStyles.eventBackground); - - using (new EditorGUI.DisabledScope(!selection.animationIsEditable)) - { - m_Events.EventLineGUI(eventsRect, m_State); - } - } - - private void RenderEventTooltip() - { - m_Events.DrawInstantTooltip(m_Position); - } - - private void TabSelectionOnGUI() - { - GUILayout.FlexibleSpace(); - EditorGUI.BeginChangeCheck(); - GUILayout.Toggle(!m_State.showCurveEditor, AnimationWindowStyles.dopesheet, AnimationWindowStyles.miniToolbarButton, GUILayout.Width(kToggleButtonWidth)); - GUILayout.Toggle(m_State.showCurveEditor, AnimationWindowStyles.curves, AnimationWindowStyles.miniToolbarButton, GUILayout.Width(kToggleButtonWidth)); - if (EditorGUI.EndChangeCheck()) - { - SwitchBetweenCurvesAndDopesheet(); - } - else if (kAnimationShowCurvesToggle.activated) - { - SwitchBetweenCurvesAndDopesheet(); - Event.current.Use(); - } - } - - private void HierarchyOnGUI() - { - Rect r = GUILayoutUtility.GetRect(hierarchyWidth, hierarchyWidth, 0f, float.MaxValue, GUILayout.ExpandHeight(true)); - - if (!m_State.disabled) - m_Hierarchy.OnGUI(r); - } - - private void FrameRateInputFieldOnGUI() - { - using (new EditorGUI.DisabledScope(!selection.animationIsEditable)) - { - GUILayout.Label(AnimationWindowStyles.samples, AnimationWindowStyles.toolbarLabel); - - EditorGUI.BeginChangeCheck(); - int clipFrameRate = EditorGUILayout.DelayedIntField((int)m_State.clipFrameRate, EditorStyles.toolbarTextField, GUILayout.Width(kIntFieldWidth)); - if (EditorGUI.EndChangeCheck()) - { - m_State.clipFrameRate = clipFrameRate; - UpdateSelectedKeysToCurveEditor(); - } - } - } - - private void ClipSelectionDropDownOnGUI() - { - m_ClipPopup.OnGUI(); - } - - private void DopeSheetOnGUI(Rect position) - { - Rect noVerticalSliderRect = new Rect(position.xMin, position.yMin, position.width - kSliderThickness, position.height); - - if (Event.current.type == EventType.Repaint) - { - m_DopeSheet.rect = noVerticalSliderRect; - m_DopeSheet.SetTickMarkerRanges(); - m_DopeSheet.RecalculateBounds(); - } - - if (m_State.showCurveEditor) - return; - - Rect noSlidersRect = new Rect(position.xMin, position.yMin, position.width - kSliderThickness, position.height - kSliderThickness); - - m_DopeSheet.BeginViewGUI(); - - GUI.Label(position, GUIContent.none, AnimationWindowStyles.dopeSheetBackground); - - if (!m_State.disabled) - { - m_DopeSheet.TimeRuler(noSlidersRect, m_State.frameRate, false, true, kDisabledRulerAlpha, m_State.timeFormat); // grid - } - m_DopeSheet.OnGUI(noSlidersRect, m_State.hierarchyState.scrollPos * -1); - - m_DopeSheet.EndViewGUI(); - - Rect verticalScrollBarPosition = new Rect(noVerticalSliderRect.xMax, noVerticalSliderRect.yMin, kSliderThickness, noSlidersRect.height); - - float visibleHeight = m_Hierarchy.GetTotalRect().height; - float contentHeight = Mathf.Max(visibleHeight, m_Hierarchy.GetContentSize().y); - - m_State.hierarchyState.scrollPos.y = GUI.VerticalScrollbar(verticalScrollBarPosition, m_State.hierarchyState.scrollPos.y, visibleHeight, 0f, contentHeight); - - if (m_DopeSheet.spritePreviewLoading == true) - Repaint(); - } - - private void CurveEditorOnGUI(Rect position) - { - if (Event.current.type == EventType.Repaint) - { - m_CurveEditor.rect = position; - m_CurveEditor.SetTickMarkerRanges(); - } - - Rect noSlidersRect = new Rect(position.xMin, position.yMin, position.width - kSliderThickness, position.height - kSliderThickness); - - m_CurveEditor.vSlider = m_State.showCurveEditor; - m_CurveEditor.hSlider = m_State.showCurveEditor; - - // Sync animation curves in curve editor. Do it only once per frame. - if (Event.current.type == EventType.Layout) - UpdateCurveEditorData(); - - m_CurveEditor.BeginViewGUI(); - - if (!m_State.disabled) - { - GUI.Box(noSlidersRect, GUIContent.none, AnimationWindowStyles.curveEditorBackground); - m_CurveEditor.GridGUI(); - } - - EditorGUI.BeginChangeCheck(); - m_CurveEditor.CurveGUI(); - if (EditorGUI.EndChangeCheck()) - { - SaveChangedCurvesFromCurveEditor(); - } - m_CurveEditor.EndViewGUI(); - } - - private void TimeRulerOnGUI(Rect timeRulerRect) - { - Rect timeRulerRectNoScrollbar = new Rect(timeRulerRect.xMin, timeRulerRect.yMin, timeRulerRect.width - kSliderThickness, timeRulerRect.height); - - GUI.Box(timeRulerRect, GUIContent.none, EditorStyles.toolbarButton); - - if (!m_State.disabled) - { - RenderInRangeOverlay(timeRulerRectNoScrollbar); - RenderSelectionOverlay(timeRulerRectNoScrollbar); - } - - m_State.timeArea.TimeRuler(timeRulerRectNoScrollbar, m_State.frameRate, true, false, 1f, m_State.timeFormat); - - if (!m_State.disabled) - RenderOutOfRangeOverlay(timeRulerRectNoScrollbar); - } - - private void AddEventButtonOnGUI() - { - using (new EditorGUI.DisabledScope(!selection.animationIsEditable)) - { - if (GUILayout.Button(AnimationWindowStyles.addEventContent, EditorStyles.toolbarButton)) - m_Events.AddEvent(m_State.currentTime, selection.rootGameObject, selection.animationClip); - } - } - - private void AddKeyframeButtonOnGUI() - { - using (new EditorGUI.DisabledScope(!selection.animationIsEditable)) - { - if (GUILayout.Button(AnimationWindowStyles.addKeyframeContent, EditorStyles.toolbarButton)) - { - SaveCurveEditorKeySelection(); - var keyTime = AnimationKeyTime.Time(m_State.currentTime, m_State.frameRate); - AnimationWindowUtility.AddSelectedKeyframes(m_State, keyTime); - UpdateSelectedKeysToCurveEditor(); - - // data is scheduled for an update, bail out now to avoid using out of date data. - EditorGUIUtility.ExitGUI(); - } - } - } - - private void PlayControlsOnGUI() - { - using (new EditorGUI.DisabledScope(!controlInterface.canPreview)) - { - PreviewButtonOnGUI(); - } - - using (new EditorGUI.DisabledScope(!controlInterface.canRecord)) - { - RecordButtonOnGUI(); - } - - if (GUILayout.Button(AnimationWindowStyles.firstKeyContent, EditorStyles.toolbarButton)) - { - controlInterface.GoToFirstKeyframe(); - - // Stop text editing. User may be editing frame navigation ui which will not update until we exit text editing. - EditorGUI.EndEditingActiveTextField(); - } - - if (GUILayout.Button(AnimationWindowStyles.prevKeyContent, EditorStyles.toolbarButton)) - { - controlInterface.GoToPreviousKeyframe(); - - // Stop text editing. User may be editing frame navigation ui which will not update until we exit text editing. - EditorGUI.EndEditingActiveTextField(); - } - - using (new EditorGUI.DisabledScope(!controlInterface.canPlay)) - { - PlayButtonOnGUI(); - } - - if (GUILayout.Button(AnimationWindowStyles.nextKeyContent, EditorStyles.toolbarButton)) - { - controlInterface.GoToNextKeyframe(); - - // Stop text editing. User may be editing frame navigation ui which will not update until we exit text editing. - EditorGUI.EndEditingActiveTextField(); - } - - if (GUILayout.Button(AnimationWindowStyles.lastKeyContent, EditorStyles.toolbarButton)) - { - controlInterface.GoToLastKeyframe(); - - // Stop text editing. User may be editing frame navigation ui which will not update until we exit text editing. - EditorGUI.EndEditingActiveTextField(); - } - - GUILayout.FlexibleSpace(); - - EditorGUI.BeginChangeCheck(); - int newFrame = EditorGUILayout.DelayedIntField(m_State.currentFrame, EditorStyles.toolbarTextField, GUILayout.Width(kIntFieldWidth)); - if (EditorGUI.EndChangeCheck()) - { - controlInterface.GoToFrame(newFrame); - } - } - - private void LinkOptionsOnGUI() - { - if (m_State.linkedWithSequencer) - { - if (GUILayout.Toggle(true, AnimationWindowStyles.sequencerLinkContent, EditorStyles.toolbarButton) == false) - { - m_State.linkedWithSequencer = false; - m_State.selection = null; - - // Layout has changed, bail out now. - EditorGUIUtility.ExitGUI(); - } - } - } - - private void HandleHotKeys() - { - if (!GUI.enabled || m_State.disabled) - return; - - bool keyChanged = false; - - if (kAnimationPrevKeyframe.activated) - { - controlInterface.GoToPreviousKeyframe(); - keyChanged = true; - } - - if (kAnimationNextKeyframe.activated) - { - controlInterface.GoToNextKeyframe(); - keyChanged = true; - } - - if (kAnimationNextFrame.activated) - { - controlInterface.GoToNextFrame(); - keyChanged = true; - } - - if (kAnimationPrevFrame.activated) - { - controlInterface.GoToPreviousFrame(); - keyChanged = true; - } - - if (kAnimationFirstKey.activated) - { - controlInterface.GoToFirstKeyframe(); - keyChanged = true; - } - - if (kAnimationLastKey.activated) - { - controlInterface.GoToLastKeyframe(); - keyChanged = true; - } - - if (keyChanged) - { - Event.current.Use(); - Repaint(); - } - - if (kAnimationPlayToggle.activated) - { - if (controlInterface.playing) - controlInterface.StopPlayback(); - else - controlInterface.StartPlayback(); - - Event.current.Use(); - } - - if (kAnimationRecordKeyframeSelected.activated) - { - SaveCurveEditorKeySelection(); - AnimationWindowUtility.AddSelectedKeyframes(m_State, controlInterface.time); - UpdateSelectedKeysToCurveEditor(); - - Event.current.Use(); - } - - if (kAnimationRecordKeyframeModified.activated) - { - SaveCurveEditorKeySelection(); - controlInterface.ProcessCandidates(); - UpdateSelectedKeysToCurveEditor(); - - Event.current.Use(); - } - } - - public void HandleGlobalHotkeys() - { - if (!m_State.previewing) - return; - - if (!GUI.enabled || m_State.disabled) - return; - - if (kAnimationRecordKeyframeSelected.activated) - { - SaveCurveEditorKeySelection(); - AnimationWindowUtility.AddSelectedKeyframes(m_State, controlInterface.time); - controlInterface.ClearCandidates(); - UpdateSelectedKeysToCurveEditor(); - - Event.current.Use(); - } - - if (kAnimationRecordKeyframeModified.activated) - { - SaveCurveEditorKeySelection(); - controlInterface.ProcessCandidates(); - UpdateSelectedKeysToCurveEditor(); - - Event.current.Use(); - } - } - - private void PlayButtonOnGUI() - { - EditorGUI.BeginChangeCheck(); - bool playbackEnabled = GUILayout.Toggle(controlInterface.playing, AnimationWindowStyles.playContent, EditorStyles.toolbarButton); - if (EditorGUI.EndChangeCheck()) - { - if (playbackEnabled) - controlInterface.StartPlayback(); - else - controlInterface.StopPlayback(); - - // Stop text editing. User may be editing frame navigation ui which will not update until we exit text editing. - EditorGUI.EndEditingActiveTextField(); - } - } - - private void PreviewButtonOnGUI() - { - EditorGUI.BeginChangeCheck(); - - bool recordingEnabled = GUILayout.Toggle(controlInterface.previewing, AnimationWindowStyles.previewContent, EditorStyles.toolbarButton); - if (EditorGUI.EndChangeCheck()) - { - if (recordingEnabled) - m_State.StartPreview(); - else - m_State.StopPreview(); - } - } - - private void RecordButtonOnGUI() - { - EditorGUI.BeginChangeCheck(); - - Color backupColor = GUI.color; - if (controlInterface.recording) - { - Color recordedColor = AnimationMode.recordedPropertyColor; - recordedColor.a *= GUI.color.a; - GUI.color = recordedColor; - } - - bool recordingEnabled = GUILayout.Toggle(controlInterface.recording, AnimationWindowStyles.recordContent, EditorStyles.toolbarButton); - if (EditorGUI.EndChangeCheck()) - { - if (recordingEnabled) - m_State.StartRecording(); - else - { - m_State.StopRecording(); - - // Force refresh in inspector as stopping recording does not invalidate any data. - InspectorWindow.RepaintAllInspectors(); - } - } - - GUI.color = backupColor; - } - - private void SwitchBetweenCurvesAndDopesheet() - { - if (!m_State.showCurveEditor) - { - SwitchToCurveEditor(); - } - else - { - SwitchToDopeSheetEditor(); - } - } - - internal void SwitchToCurveEditor() - { - m_State.showCurveEditor = true; - - UpdateSelectedKeysToCurveEditor(); - AnimationWindowUtility.SyncTimeArea(m_DopeSheet, m_CurveEditor); - m_State.timeArea = m_CurveEditor; - } - - internal void SwitchToDopeSheetEditor() - { - m_State.showCurveEditor = false; - - UpdateSelectedKeysFromCurveEditor(); - AnimationWindowUtility.SyncTimeArea(m_CurveEditor, m_DopeSheet); - m_State.timeArea = m_DopeSheet; - } - - private void RenderSelectionOverlay(Rect rect) - { - if (m_State.showCurveEditor && !m_CurveEditor.hasSelection) - return; - - if (!m_State.showCurveEditor && m_State.selectedKeys.Count == 0) - return; - - const int kOverlayMinWidth = 14; - - Bounds bounds = m_State.showCurveEditor ? m_CurveEditor.selectionBounds : m_State.selectionBounds; - - float startPixel = m_State.TimeToPixel(bounds.min.x) + rect.xMin; - float endPixel = m_State.TimeToPixel(bounds.max.x) + rect.xMin; - - if ((endPixel - startPixel) < kOverlayMinWidth) - { - float centerPixel = (startPixel + endPixel) * 0.5f; - - startPixel = centerPixel - kOverlayMinWidth * 0.5f; - endPixel = centerPixel + kOverlayMinWidth * 0.5f; - } - - AnimationWindowUtility.DrawSelectionOverlay(rect, selectionRangeColor, startPixel, endPixel); - } - - private void RenderInRangeOverlay(Rect rect) - { - Color color = inRangeColor; - - if (controlInterface.recording) - color *= AnimationMode.recordedPropertyColor; - else if (controlInterface.previewing) - color *= AnimationMode.animatedPropertyColor; - else - color = Color.clear; - - Vector2 timeRange = m_State.timeRange; - AnimationWindowUtility.DrawInRangeOverlay(rect, color, m_State.TimeToPixel(timeRange.x) + rect.xMin, m_State.TimeToPixel(timeRange.y) + rect.xMin); - } - - private void RenderOutOfRangeOverlay(Rect rect) - { - Color color = outOfRangeColor; - - if (controlInterface.recording) - color *= AnimationMode.recordedPropertyColor; - else if (controlInterface.previewing) - color *= AnimationMode.animatedPropertyColor; - - Vector2 timeRange = m_State.timeRange; - AnimationWindowUtility.DrawOutOfRangeOverlay(rect, color, m_State.TimeToPixel(timeRange.x) + rect.xMin, m_State.TimeToPixel(timeRange.y) + rect.xMin); - } - - private void SynchronizeLayout() - { - m_HorizontalSplitter.realSizes[1] = (int)Mathf.Min(m_Position.width - m_HorizontalSplitter.realSizes[0], m_HorizontalSplitter.realSizes[1]); - - // Synchronize frame rate - if (selection.animationClip != null) - { - m_State.frameRate = selection.animationClip.frameRate; - } - else - { - m_State.frameRate = AnimationWindowState.kDefaultFrameRate; - } - } - - struct ChangedCurvesPerClip - { - public List bindings; - public List curves; - } - - // Curve editor changes curves, but we are in charge of saving them into the clip - private void SaveChangedCurvesFromCurveEditor() - { - m_State.SaveKeySelection(AnimationWindowState.kEditCurveUndoLabel); - - var curvesToUpdate = new Dictionary(); - var changedCurves = new ChangedCurvesPerClip(); - - for (int i = 0; i < m_CurveEditor.animationCurves.Length; ++i) - { - CurveWrapper curveWrapper = m_CurveEditor.animationCurves[i]; - if (curveWrapper.changed) - { - if (!curveWrapper.animationIsEditable) - Debug.LogError("Curve is not editable and shouldn't be saved."); - - if (curveWrapper.animationClip != null) - { - if (curvesToUpdate.TryGetValue(curveWrapper.animationClip, out changedCurves)) - { - changedCurves.bindings.Add(curveWrapper.binding); - changedCurves.curves.Add(curveWrapper.curve.length > 0 ? curveWrapper.curve : null); - } - else - { - changedCurves.bindings = new List(); - changedCurves.curves = new List(); - - changedCurves.bindings.Add(curveWrapper.binding); - changedCurves.curves.Add(curveWrapper.curve.length > 0 ? curveWrapper.curve : null); - - curvesToUpdate.Add(curveWrapper.animationClip, changedCurves); - } - } - - curveWrapper.changed = false; - } - } - - if (curvesToUpdate.Count > 0) - { - foreach (var kvp in curvesToUpdate) - { - Undo.RegisterCompleteObjectUndo(kvp.Key, AnimationWindowState.kEditCurveUndoLabel); - AnimationUtility.SetEditorCurves(kvp.Key, kvp.Value.bindings.ToArray(), kvp.Value.curves.ToArray()); - } - - m_State.ResampleAnimation(); - } - } - - // We sync keyframe selection from curve editor to AnimationWindowState - private void UpdateSelectedKeysFromCurveEditor() - { - m_State.ClearKeySelections(); - foreach (CurveSelection curveSelection in m_CurveEditor.selectedCurves) - { - AnimationWindowKeyframe keyFrame = AnimationWindowUtility.CurveSelectionToAnimationWindowKeyframe(curveSelection, m_State.allCurves); - if (keyFrame != null) - m_State.SelectKey(keyFrame); - } - } - - // We sync keyframe selection from AnimationWindowState to curve editor - private void UpdateSelectedKeysToCurveEditor() - { - UpdateCurveEditorData(); - - m_CurveEditor.ClearSelection(); - m_CurveEditor.BeginRangeSelection(); - foreach (AnimationWindowKeyframe keyframe in m_State.selectedKeys) - { - CurveSelection curveSelection = AnimationWindowUtility.AnimationWindowKeyframeToCurveSelection(keyframe, m_CurveEditor); - if (curveSelection != null) - m_CurveEditor.AddSelection(curveSelection); - } - m_CurveEditor.EndRangeSelection(); - } - - private void SaveCurveEditorKeySelection() - { - // Synchronize current selection in curve editor and save selection snapshot in undo redo. - if (m_State.showCurveEditor) - UpdateSelectedKeysFromCurveEditor(); - else - UpdateSelectedKeysToCurveEditor(); - - m_CurveEditor.SaveKeySelection(AnimationWindowState.kEditCurveUndoLabel); - } - - public void BeginKeyModification() - { - SaveCurveEditorKeySelection(); - - m_State.SaveKeySelection(AnimationWindowState.kEditCurveUndoLabel); - m_State.ClearKeySelections(); - } - - public void EndKeyModification() - { - UpdateSelectedKeysToCurveEditor(); - } - - private void HandleCopyPaste() - { - if (Event.current.type == EventType.ValidateCommand || Event.current.type == EventType.ExecuteCommand) - { - switch (Event.current.commandName) - { - case EventCommandNames.Copy: - if (Event.current.type == EventType.ExecuteCommand) - { - if (m_State.showCurveEditor) - UpdateSelectedKeysFromCurveEditor(); - m_State.CopyKeys(); - } - Event.current.Use(); - break; - case EventCommandNames.Paste: - if (Event.current.type == EventType.ExecuteCommand) - { - SaveCurveEditorKeySelection(); - m_State.PasteKeys(); - UpdateSelectedKeysToCurveEditor(); - - // data is scheduled for an update, bail out now to avoid using out of date data. - EditorGUIUtility.ExitGUI(); - } - Event.current.Use(); - break; - } - } - } - - internal void UpdateCurveEditorData() - { - m_CurveEditor.animationCurves = m_State.activeCurveWrappers; - } - - public void Repaint() - { - if (m_OwnerWindow != null) - m_OwnerWindow.Repaint(); - } - - // Called just-in-time by OnGUI - private void Initialize() - { - AnimationWindowStyles.Initialize(); - InitializeHierarchy(); - - m_CurveEditor.state = m_State; - - // The rect here is only for initialization and will be overriden at layout - m_HorizontalSplitter.realSizes[0] = kHierarchyMinWidth; - m_HorizontalSplitter.realSizes[1] = (int)Mathf.Max(m_Position.width - kHierarchyMinWidth, kHierarchyMinWidth); - m_DopeSheet.rect = new Rect(0, 0, contentWidth, 100); - - m_Initialized = true; - } - - // Called once during initialization of m_State - private void InitializeClipSelection() - { - m_ClipPopup = new AnimationWindowClipPopup(); - } - - // Called once during initialization of m_State - private void InitializeHierarchy() - { - // The rect here is only for initialization and will be overriden at layout - m_Hierarchy = new AnimationWindowHierarchy(m_State, m_OwnerWindow, new Rect(0, 0, hierarchyWidth, 100)); - } - - // Called once during initialization of m_State - private void InitializeDopeSheet() - { - m_DopeSheet = new DopeSheetEditor(m_OwnerWindow); - m_DopeSheet.SetTickMarkerRanges(); - m_DopeSheet.hSlider = true; - m_DopeSheet.shownArea = new Rect(1, 1, 1, 1); - // The rect here is only for initialization and will be overriden at layout - m_DopeSheet.rect = new Rect(0, 0, contentWidth, 100); - m_DopeSheet.hTicks.SetTickModulosForFrameRate(m_State.frameRate); - } - - // Called once during initialization of m_State - private void InitializeEvents() - { - m_Events = new AnimationEventTimeLine(m_OwnerWindow); - } - - // Called once during initialization of m_State - private void InitializeCurveEditor() - { - // The rect here is only for initialization and will be overriden at layout - m_CurveEditor = new CurveEditor(new Rect(0, 0, contentWidth, 100), new CurveWrapper[0], false); - - CurveEditorSettings settings = new CurveEditorSettings(); - settings.hTickStyle.distMin = 30; // min distance between vertical lines before they disappear completely - settings.hTickStyle.distFull = 80; // distance between vertical lines where they gain full strength - settings.hTickStyle.distLabel = 0; // min distance between vertical lines labels - if (EditorGUIUtility.isProSkin) - { - settings.vTickStyle.tickColor.color = new Color(1, 1, 1, settings.vTickStyle.tickColor.color.a); // color and opacity of horizontal lines - settings.vTickStyle.labelColor.color = new Color(1, 1, 1, settings.vTickStyle.labelColor.color.a); // color and opacity of horizontal line labels - } - settings.vTickStyle.distMin = 15; // min distance between horizontal lines before they disappear completely - settings.vTickStyle.distFull = 40; // distance between horizontal lines where they gain full strength - settings.vTickStyle.distLabel = 30; // min distance between horizontal lines labels - settings.vTickStyle.stubs = true; - settings.hRangeMin = 0; - settings.hRangeLocked = false; - settings.vRangeLocked = false; - settings.hSlider = true; - settings.vSlider = true; - settings.allowDeleteLastKeyInCurve = true; - settings.rectangleToolFlags = CurveEditorSettings.RectangleToolFlags.FullRectangleTool; - settings.undoRedoSelection = true; - - m_CurveEditor.shownArea = new Rect(1, 1, 1, 1); - m_CurveEditor.settings = settings; - m_CurveEditor.state = m_State; - } - - // Called once during initialization of m_State - private void InitializeHorizontalSplitter() - { - m_HorizontalSplitter = new SplitterState(new float[] { kHierarchyMinWidth, kHierarchyMinWidth * 3 }, new int[] { kHierarchyMinWidth, kHierarchyMinWidth }, null); - m_HorizontalSplitter.realSizes[0] = kHierarchyMinWidth; - m_HorizontalSplitter.realSizes[1] = kHierarchyMinWidth; - } - - // Called once during initialization of m_State - private void InitializeOverlay() - { - m_Overlay = new AnimEditorOverlay(); - } - - // Called during initialization, even when m_State already exists - private void InitializeNonserializedValues() - { - // Since CurveEditor doesn't know about AnimationWindowState, a delegate allows it to reflect frame rate changes - m_State.onFrameRateChange += delegate(float newFrameRate) - { - m_CurveEditor.invSnap = newFrameRate; - m_CurveEditor.hTicks.SetTickModulosForFrameRate(newFrameRate); - }; - - m_State.onStartLiveEdit += OnStartLiveEdit; - m_State.onEndLiveEdit += OnEndLiveEdit; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimEditorOverlay.cs b/Editor/Mono/Animation/AnimationWindow/AnimEditorOverlay.cs deleted file mode 100644 index 7b6dd22f15..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimEditorOverlay.cs +++ /dev/null @@ -1,132 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - [System.Serializable] - internal class AnimEditorOverlay - { - public AnimationWindowState state; - - private TimeCursorManipulator m_PlayHeadCursor; - - private Rect m_Rect; - private Rect m_ContentRect; - - public Rect rect { get { return m_Rect; } } - public Rect contentRect { get { return m_ContentRect; } } - - public void Initialize() - { - if (m_PlayHeadCursor == null) - { - m_PlayHeadCursor = new TimeCursorManipulator(AnimationWindowStyles.playHead); - - m_PlayHeadCursor.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (evt.mousePosition.y <= (m_Rect.yMin + 20)) - return OnStartDragPlayHead(evt); - - return false; - }; - m_PlayHeadCursor.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - return OnDragPlayHead(evt); - }; - m_PlayHeadCursor.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - return OnEndDragPlayHead(evt); - }; - } - } - - public void OnGUI(Rect rect, Rect contentRect) - { - if (Event.current.type != EventType.Repaint) - return; - - m_Rect = rect; - m_ContentRect = contentRect; - - Initialize(); - - m_PlayHeadCursor.OnGUI(m_Rect, m_Rect.xMin + TimeToPixel(state.currentTime)); - } - - public void HandleEvents() - { - Initialize(); - - m_PlayHeadCursor.HandleEvents(); - } - - private bool OnStartDragPlayHead(Event evt) - { - state.controlInterface.StopPlayback(); - state.controlInterface.StartScrubTime(); - state.controlInterface.ScrubTime(MousePositionToTime(evt)); - return true; - } - - private bool OnDragPlayHead(Event evt) - { - state.controlInterface.ScrubTime(MousePositionToTime(evt)); - return true; - } - - private bool OnEndDragPlayHead(Event evt) - { - state.controlInterface.EndScrubTime(); - return true; - } - - public float MousePositionToTime(Event evt) - { - float width = m_ContentRect.width; - float time = Mathf.Max(((evt.mousePosition.x / width) * state.visibleTimeSpan + state.minVisibleTime), 0); - time = state.SnapToFrame(time, AnimationWindowState.SnapMode.SnapToFrame); - return time; - } - - public float MousePositionToValue(Event evt) - { - float height = m_ContentRect.height; - float valuePixel = height - evt.mousePosition.y; - - TimeArea timeArea = state.timeArea; - - float pixelPerValue = timeArea.m_Scale.y * -1f; - float zeroValuePixel = timeArea.shownArea.yMin * pixelPerValue * -1f; - - float value = (valuePixel - zeroValuePixel) / pixelPerValue; - - return value; - } - - public float TimeToPixel(float time) - { - return state.TimeToPixel(time); - } - - public float ValueToPixel(float value) - { - TimeArea timeArea = state.timeArea; - - float pixelPerValue = timeArea.m_Scale.y * -1f; - float zeroValuePixel = timeArea.shownArea.yMin * pixelPerValue * -1f; - - float pixelValue = value * pixelPerValue + zeroValuePixel; - - return pixelValue; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationClipSelectionItem.cs b/Editor/Mono/Animation/AnimationWindow/AnimationClipSelectionItem.cs deleted file mode 100644 index c6942190d7..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationClipSelectionItem.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; - -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal class AnimationClipSelectionItem : AnimationWindowSelectionItem - { - public static AnimationClipSelectionItem Create(AnimationClip animationClip, Object sourceObject) - { - AnimationClipSelectionItem selectionItem = CreateInstance(typeof(AnimationClipSelectionItem)) as AnimationClipSelectionItem; - - selectionItem.gameObject = sourceObject as GameObject; - selectionItem.scriptableObject = sourceObject as ScriptableObject; - selectionItem.animationClip = animationClip; - selectionItem.id = 0; // no need for id since there's only one item in selection. - - return selectionItem; - } - - public override bool canPreview { get { return false; } } - - public override bool canRecord { get { return false; } } - - public override bool canChangeAnimationClip { get { return false; } } - - public override bool canSyncSceneSelection { get { return false; } } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationContextualPropertyMenu.cs b/Editor/Mono/Animation/AnimationWindow/AnimationContextualPropertyMenu.cs deleted file mode 100644 index 0d730d3f08..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationContextualPropertyMenu.cs +++ /dev/null @@ -1,181 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Reflection; -using UnityEngine; -using UnityEditor; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal class AnimationPropertyContextualMenu - { - public static AnimationPropertyContextualMenu Instance = new AnimationPropertyContextualMenu(); - - IAnimationContextualResponder m_Responder; - - private static GUIContent addKeyContent = EditorGUIUtility.TrTextContent("Add Key"); - private static GUIContent updateKeyContent = EditorGUIUtility.TrTextContent("Update Key"); - private static GUIContent removeKeyContent = EditorGUIUtility.TrTextContent("Remove Key"); - private static GUIContent removeCurveContent = EditorGUIUtility.TrTextContent("Remove All Keys"); - private static GUIContent goToPreviousKeyContent = EditorGUIUtility.TrTextContent("Go to Previous Key"); - private static GUIContent goToNextKeyContent = EditorGUIUtility.TrTextContent("Go to Next Key"); - private static GUIContent addCandidatesContent = EditorGUIUtility.TrTextContent("Key All Modified"); - private static GUIContent addAnimatedContent = EditorGUIUtility.TrTextContent("Key All Animated"); - - public AnimationPropertyContextualMenu() - { - EditorApplication.contextualPropertyMenu += OnPropertyContextMenu; - MaterialEditor.contextualPropertyMenu += OnPropertyContextMenu; - } - - public void SetResponder(IAnimationContextualResponder responder) - { - m_Responder = responder; - } - - public bool IsResponder(IAnimationContextualResponder responder) - { - return responder == m_Responder; - } - - void OnPropertyContextMenu(GenericMenu menu, SerializedProperty property) - { - if (m_Responder == null) - return; - - PropertyModification[] modifications = AnimationWindowUtility.SerializedPropertyToPropertyModifications(property); - - bool isPropertyAnimatable = m_Responder.IsAnimatable(modifications); - if (isPropertyAnimatable) - { - var targetObject = property.serializedObject.targetObject; - if (m_Responder.IsEditable(targetObject)) - OnPropertyContextMenu(menu, modifications); - else - OnDisabledPropertyContextMenu(menu); - } - } - - void OnPropertyContextMenu(GenericMenu menu, MaterialProperty property, Renderer[] renderers) - { - if (m_Responder == null) - return; - - if (property.targets == null || property.targets.Length == 0) - return; - - if (renderers == null || renderers.Length == 0) - return; - - var modifications = new List(); - foreach (Renderer renderer in renderers) - { - modifications.AddRange(MaterialAnimationUtility.MaterialPropertyToPropertyModifications(property, renderer)); - } - - if (m_Responder.IsEditable(renderers[0])) - OnPropertyContextMenu(menu, modifications.ToArray()); - else - OnDisabledPropertyContextMenu(menu); - } - - void OnPropertyContextMenu(GenericMenu menu, PropertyModification[] modifications) - { - bool hasKey = m_Responder.KeyExists(modifications); - bool hasCandidate = m_Responder.CandidateExists(modifications); - bool hasCurve = (hasKey || m_Responder.CurveExists(modifications)); - - bool hasAnyCandidate = m_Responder.HasAnyCandidates(); - bool hasAnyCurve = m_Responder.HasAnyCurves(); - - menu.AddItem(((hasKey && hasCandidate) ? updateKeyContent : addKeyContent), false, () => - { - m_Responder.AddKey(modifications); - }); - - if (hasKey) - { - menu.AddItem(removeKeyContent, false, () => - { - m_Responder.RemoveKey(modifications); - }); - } - else - { - menu.AddDisabledItem(removeKeyContent); - } - - if (hasCurve) - { - menu.AddItem(removeCurveContent, false, () => - { - m_Responder.RemoveCurve(modifications); - }); - } - else - { - menu.AddDisabledItem(removeCurveContent); - } - - menu.AddSeparator(string.Empty); - if (hasAnyCandidate) - { - menu.AddItem(addCandidatesContent, false, () => - { - m_Responder.AddCandidateKeys(); - }); - } - else - { - menu.AddDisabledItem(addCandidatesContent); - } - - if (hasAnyCurve) - { - menu.AddItem(addAnimatedContent, false, () => - { - m_Responder.AddAnimatedKeys(); - }); - } - else - { - menu.AddDisabledItem(addAnimatedContent); - } - - menu.AddSeparator(string.Empty); - if (hasCurve) - { - menu.AddItem(goToPreviousKeyContent, false, () => - { - m_Responder.GoToPreviousKeyframe(modifications); - }); - menu.AddItem(goToNextKeyContent, false, () => - { - m_Responder.GoToNextKeyframe(modifications); - }); - } - else - { - menu.AddDisabledItem(goToPreviousKeyContent); - menu.AddDisabledItem(goToNextKeyContent); - } - } - - void OnDisabledPropertyContextMenu(GenericMenu menu) - { - menu.AddDisabledItem(addKeyContent); - menu.AddDisabledItem(removeKeyContent); - menu.AddDisabledItem(removeCurveContent); - menu.AddSeparator(string.Empty); - menu.AddDisabledItem(addCandidatesContent); - menu.AddDisabledItem(addAnimatedContent); - menu.AddSeparator(string.Empty); - menu.AddDisabledItem(goToPreviousKeyContent); - menu.AddDisabledItem(goToNextKeyContent); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationKeyTime.cs b/Editor/Mono/Animation/AnimationWindow/AnimationKeyTime.cs deleted file mode 100644 index 753e324ff1..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationKeyTime.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; - -namespace UnityEditorInternal -{ - [System.Serializable] - struct AnimationKeyTime - { - [SerializeField] private float m_FrameRate; - [SerializeField] private int m_Frame; - [SerializeField] private float m_Time; - - public float time { get { return m_Time; } } - public int frame { get { return m_Frame; } } - public float frameRate { get { return m_FrameRate; } } - - /// - /// A frame has a range of time. This is the beginning of the frame. - /// - public float frameFloor - { - get - { - return ((float)frame - 0.5f) / frameRate; - } - } - - /// - /// A frame has a range of time. This is the end of the frame. - /// - public float frameCeiling - { - get - { - return ((float)frame + 0.5f) / frameRate; - } - } - - public static AnimationKeyTime Time(float time, float frameRate) - { - AnimationKeyTime key = new AnimationKeyTime(); - key.m_Time = Mathf.Max(time, 0f); - key.m_FrameRate = frameRate; - key.m_Frame = UnityEngine.Mathf.RoundToInt(key.m_Time * frameRate); - return key; - } - - public static AnimationKeyTime Frame(int frame, float frameRate) - { - AnimationKeyTime key = new AnimationKeyTime(); - key.m_Frame = (frame < 0) ? 0 : frame; - key.m_Time = key.m_Frame / frameRate; - key.m_FrameRate = frameRate; - return key; - } - - // Check if a time in seconds overlaps with the frame - public bool ContainsTime(float time) - { - return time >= frameFloor && time < frameCeiling; - } - - public bool Equals(AnimationKeyTime key) - { - return m_Frame == key.m_Frame && - m_FrameRate == key.m_FrameRate && - Mathf.Approximately(m_Time, key.m_Time); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs b/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs deleted file mode 100644 index 1759bb7fa6..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs +++ /dev/null @@ -1,825 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Reflection; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal class AnimationRecording - { - const string kLocalPosition = "m_LocalPosition"; - const string kLocalRotation = "m_LocalRotation"; - const string kLocalScale = "m_LocalScale"; - const string kLocalEulerAnglesHint = "m_LocalEulerAnglesHint"; - - static bool HasAnyRecordableModifications(GameObject root, UndoPropertyModification[] modifications) - { - for (int i = 0; i < modifications.Length; i++) - { - EditorCurveBinding tempBinding; - if (AnimationUtility.PropertyModificationToEditorCurveBinding(modifications[i].previousValue, root, out tempBinding) != null) - return true; - } - return false; - } - - static private UndoPropertyModification[] FilterModifications(IAnimationRecordingState state, ref UndoPropertyModification[] modifications) - { - AnimationClip clip = state.activeAnimationClip; - GameObject rootGameObject = state.activeRootGameObject; - - List discardedModifications = new List(); - List outModifications = new List(); - for (int i = 0; i < modifications.Length; ++i) - { - UndoPropertyModification modification = modifications[i]; - PropertyModification prop = modification.previousValue; - - if (state.DiscardModification(prop)) - { - discardedModifications.Add(modification); - continue; - } - - var binding = new EditorCurveBinding(); - if (AnimationUtility.PropertyModificationToEditorCurveBinding(prop, rootGameObject, out binding) != null) - outModifications.Add(modification); - else - discardedModifications.Add(modification); - } - - if (discardedModifications.Count > 0) - modifications = outModifications.ToArray(); - - return discardedModifications.ToArray(); - } - - internal class RotationModification - { - public UndoPropertyModification x; - public UndoPropertyModification y; - public UndoPropertyModification z; - public UndoPropertyModification w; - - public UndoPropertyModification lastQuatModification; - - public bool useEuler = false; - public UndoPropertyModification eulerX; - public UndoPropertyModification eulerY; - public UndoPropertyModification eulerZ; - } - - static private void CollectRotationModifications(IAnimationRecordingState state, ref UndoPropertyModification[] modifications, - ref System.Collections.Generic.Dictionary rotationModifications) - { - List outModifs = new List(); - foreach (var modification in modifications) - { - PropertyModification prop = modification.previousValue; - if (!(prop.target is Transform)) - { - outModifs.Add(modification); - continue; - } - - EditorCurveBinding binding = new EditorCurveBinding(); - AnimationUtility.PropertyModificationToEditorCurveBinding(prop, state.activeRootGameObject, out binding); - if (binding.propertyName.StartsWith(kLocalRotation)) - { - RotationModification rotationModification; - - if (!rotationModifications.TryGetValue(prop.target, out rotationModification)) - { - rotationModification = new RotationModification(); - rotationModifications[prop.target] = rotationModification; - } - - if (binding.propertyName.EndsWith("x")) - rotationModification.x = modification; - else if (binding.propertyName.EndsWith("y")) - rotationModification.y = modification; - else if (binding.propertyName.EndsWith("z")) - rotationModification.z = modification; - else if (binding.propertyName.EndsWith("w")) - rotationModification.w = modification; - - rotationModification.lastQuatModification = modification; - } - else if (prop.propertyPath.StartsWith(kLocalEulerAnglesHint)) - { - RotationModification rotationModification; - - if (!rotationModifications.TryGetValue(prop.target, out rotationModification)) - { - rotationModification = new RotationModification(); - rotationModifications[prop.target] = rotationModification; - } - - rotationModification.useEuler = true; - - if (prop.propertyPath.EndsWith("x")) - rotationModification.eulerX = modification; - else if (prop.propertyPath.EndsWith("y")) - rotationModification.eulerY = modification; - else if (prop.propertyPath.EndsWith("z")) - rotationModification.eulerZ = modification; - } - else - { - outModifs.Add(modification); - } - } - - if (rotationModifications.Count > 0) - { - modifications = outModifs.ToArray(); - } - } - - static private void DiscardRotationModification(RotationModification rotationModification, ref List discardedModifications) - { - if (rotationModification.x.currentValue != null) - discardedModifications.Add(rotationModification.x); - if (rotationModification.y.currentValue != null) - discardedModifications.Add(rotationModification.y); - if (rotationModification.z.currentValue != null) - discardedModifications.Add(rotationModification.z); - if (rotationModification.w.currentValue != null) - discardedModifications.Add(rotationModification.w); - - if (rotationModification.eulerX.currentValue != null) - discardedModifications.Add(rotationModification.eulerX); - if (rotationModification.eulerY.currentValue != null) - discardedModifications.Add(rotationModification.eulerY); - if (rotationModification.eulerZ.currentValue != null) - discardedModifications.Add(rotationModification.eulerZ); - } - - static private UndoPropertyModification[] FilterRotationModifications(IAnimationRecordingState state, ref Dictionary rotationModifications) - { - AnimationClip clip = state.activeAnimationClip; - GameObject rootGameObject = state.activeRootGameObject; - - List itemsToRemove = new List(); - - List discardedModifications = new List(); - foreach (KeyValuePair item in rotationModifications) - { - RotationModification m = item.Value; - - if (state.DiscardModification(m.lastQuatModification.currentValue)) - { - DiscardRotationModification(m, ref discardedModifications); - itemsToRemove.Add(item.Key); - continue; - } - - EditorCurveBinding binding = new EditorCurveBinding(); - Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.lastQuatModification.currentValue, rootGameObject, out binding); - if (type == null) - { - DiscardRotationModification(m, ref discardedModifications); - itemsToRemove.Add(item.Key); - } - } - - foreach (var key in itemsToRemove) - { - rotationModifications.Remove(key); - } - - return discardedModifications.ToArray(); - } - - static private void AddRotationPropertyModification(IAnimationRecordingState state, EditorCurveBinding baseBinding, UndoPropertyModification modification) - { - if (modification.previousValue == null) - return; - - // case 817356. Reuse baseBinding as basis for rotation binding. - // This is needed to register valid bindings for m_LocalEulerAnglesHint - // that cannot be converted to EditorCurveBinding otherwise. - EditorCurveBinding binding = baseBinding; - binding.propertyName = modification.previousValue.propertyPath; - - state.AddPropertyModification(binding, modification.previousValue, modification.keepPrefabOverride); - } - - static private void ProcessRotationModifications(IAnimationRecordingState state, ref System.Collections.Generic.Dictionary rotationModifications) - { - AnimationClip clip = state.activeAnimationClip; - GameObject root = state.activeRootGameObject; - - foreach (KeyValuePair item in rotationModifications) - { - RotationModification m = item.Value; - Transform target = item.Key as Transform; - - if (target == null) - continue; - - EditorCurveBinding binding = new EditorCurveBinding(); - Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.lastQuatModification.currentValue, state.activeRootGameObject, out binding); - if (type == null) - continue; - - AddRotationPropertyModification(state, binding, m.x); - AddRotationPropertyModification(state, binding, m.y); - AddRotationPropertyModification(state, binding, m.z); - AddRotationPropertyModification(state, binding, m.w); - - Quaternion previousValue = target.localRotation; - Quaternion currentValue = target.localRotation; - - object x, y, z, w; - if (ValueFromPropertyModification(m.x.previousValue, binding, out x)) - previousValue.x = (float)x; - if (ValueFromPropertyModification(m.y.previousValue, binding, out y)) - previousValue.y = (float)y; - if (ValueFromPropertyModification(m.z.previousValue, binding, out z)) - previousValue.z = (float)z; - if (ValueFromPropertyModification(m.w.previousValue, binding, out w)) - previousValue.w = (float)w; - - if (ValueFromPropertyModification(m.x.currentValue, binding, out x)) - currentValue.x = (float)x; - if (ValueFromPropertyModification(m.y.currentValue, binding, out y)) - currentValue.y = (float)y; - if (ValueFromPropertyModification(m.z.currentValue, binding, out z)) - currentValue.z = (float)z; - if (ValueFromPropertyModification(m.w.currentValue, binding, out w)) - currentValue.w = (float)w; - - // Favour euler hints if one or more exist on any axis. - if (m.useEuler) - { - AddRotationPropertyModification(state, binding, m.eulerX); - AddRotationPropertyModification(state, binding, m.eulerY); - AddRotationPropertyModification(state, binding, m.eulerZ); - - Vector3 previousEulerAngles = target.GetLocalEulerAngles(RotationOrder.OrderZXY); - Vector3 currentEulerAngles = previousEulerAngles; - - object eulerX, eulerY, eulerZ; - if (ValueFromPropertyModification(m.eulerX.previousValue, binding, out eulerX)) - previousEulerAngles.x = (float)eulerX; - if (ValueFromPropertyModification(m.eulerY.previousValue, binding, out eulerY)) - previousEulerAngles.y = (float)eulerY; - if (ValueFromPropertyModification(m.eulerZ.previousValue, binding, out eulerZ)) - previousEulerAngles.z = (float)eulerZ; - - if (ValueFromPropertyModification(m.eulerX.currentValue, binding, out eulerX)) - currentEulerAngles.x = (float)eulerX; - if (ValueFromPropertyModification(m.eulerY.currentValue, binding, out eulerY)) - currentEulerAngles.y = (float)eulerY; - if (ValueFromPropertyModification(m.eulerZ.currentValue, binding, out eulerZ)) - currentEulerAngles.z = (float)eulerZ; - - // Fallback to quaternion euler values if euler hint and quaternion are out of sync. - previousEulerAngles = AnimationUtility.GetClosestEuler(previousValue, previousEulerAngles, RotationOrder.OrderZXY); - currentEulerAngles = AnimationUtility.GetClosestEuler(currentValue, currentEulerAngles, RotationOrder.OrderZXY); - - AddRotationKey(state, binding, type, previousEulerAngles, currentEulerAngles); - } - else - { - Vector3 eulerAngles = target.GetLocalEulerAngles(RotationOrder.OrderZXY); - - Vector3 previousEulerAngles = AnimationUtility.GetClosestEuler(previousValue, eulerAngles, RotationOrder.OrderZXY); - Vector3 currentEulerAngles = AnimationUtility.GetClosestEuler(currentValue, eulerAngles, RotationOrder.OrderZXY); - - AddRotationKey(state, binding, type, previousEulerAngles, currentEulerAngles); - } - } - } - - internal class Vector3Modification - { - public UndoPropertyModification x; - public UndoPropertyModification y; - public UndoPropertyModification z; - - public UndoPropertyModification last; - } - - static private void CollectVector3Modifications(IAnimationRecordingState state, ref UndoPropertyModification[] modifications, - ref System.Collections.Generic.Dictionary vector3Modifications, string propertyName) - { - List outModifs = new List(); - foreach (var modification in modifications) - { - PropertyModification prop = modification.previousValue; - if (!(prop.target is Transform)) - { - outModifs.Add(modification); - continue; - } - - EditorCurveBinding binding = new EditorCurveBinding(); - AnimationUtility.PropertyModificationToEditorCurveBinding(prop, state.activeRootGameObject, out binding); - if (binding.propertyName.StartsWith(propertyName)) - { - Vector3Modification vector3Modification; - - if (!vector3Modifications.TryGetValue(prop.target, out vector3Modification)) - { - vector3Modification = new Vector3Modification(); - vector3Modifications[prop.target] = vector3Modification; - } - - if (binding.propertyName.EndsWith("x")) - vector3Modification.x = modification; - else if (binding.propertyName.EndsWith("y")) - vector3Modification.y = modification; - else if (binding.propertyName.EndsWith("z")) - vector3Modification.z = modification; - - vector3Modification.last = modification; - } - else - { - outModifs.Add(modification); - } - } - - if (vector3Modifications.Count > 0) - { - modifications = outModifs.ToArray(); - } - } - - static private void ProcessVector3Modification(IAnimationRecordingState state, EditorCurveBinding baseBinding, UndoPropertyModification modification, Transform target, string axis) - { - var binding = baseBinding; - var property = modification.previousValue; - - binding.propertyName = binding.propertyName.Remove(binding.propertyName.Length - 1, 1) + axis; - - if (property == null) - { - // create dummy - property = new PropertyModification(); - property.target = target; - property.propertyPath = binding.propertyName; - object currentValue = CurveBindingUtility.GetCurrentValue(state.activeRootGameObject, binding); - property.value = ((float)currentValue).ToString(); - } - - state.AddPropertyModification(binding, property, modification.keepPrefabOverride); - AddKey(state, binding, typeof(float), property); - } - - static public void ProcessVector3Modifications(IAnimationRecordingState state, ref System.Collections.Generic.Dictionary vector3Modifications) - { - AnimationClip clip = state.activeAnimationClip; - GameObject root = state.activeRootGameObject; - - foreach (KeyValuePair item in vector3Modifications) - { - Vector3Modification m = item.Value; - Transform target = item.Key as Transform; - - if (target == null) - continue; - - EditorCurveBinding binding = new EditorCurveBinding(); - Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.last.currentValue, state.activeRootGameObject, out binding); - if (type == null) - continue; - - ProcessVector3Modification(state, binding, m.x, target, "x"); - ProcessVector3Modification(state, binding, m.y, target, "y"); - ProcessVector3Modification(state, binding, m.z, target, "z"); - } - } - - static public void ProcessModifications(IAnimationRecordingState state, UndoPropertyModification[] modifications) - { - AnimationClip clip = state.activeAnimationClip; - GameObject root = state.activeRootGameObject; - - // Record modified properties - for (int i = 0; i < modifications.Length; i++) - { - EditorCurveBinding binding = new EditorCurveBinding(); - - PropertyModification prop = modifications[i].previousValue; - Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(prop, root, out binding); - if (type != null) - { - state.AddPropertyModification(binding, prop, modifications[i].keepPrefabOverride); - AddKey(state, binding, type, prop); - } - } - } - - static public UndoPropertyModification[] Process(IAnimationRecordingState state, UndoPropertyModification[] modifications) - { - GameObject root = state.activeRootGameObject; - if (root == null) - return modifications; - - // Fast path detect that nothing recordable has changed. - if (!HasAnyRecordableModifications(root, modifications)) - return modifications; - - System.Collections.Generic.Dictionary rotationModifications = new Dictionary(); - System.Collections.Generic.Dictionary scaleModifications = new Dictionary(); - System.Collections.Generic.Dictionary positionModifications = new Dictionary(); - - //Strip out the rotation modifications from the rest - CollectRotationModifications(state, ref modifications, ref rotationModifications); - UndoPropertyModification[] discardedRotationModifications = FilterRotationModifications(state, ref rotationModifications); - UndoPropertyModification[] discardedModifications = FilterModifications(state, ref modifications); - CollectVector3Modifications(state, ref modifications, ref positionModifications, kLocalPosition); - CollectVector3Modifications(state, ref modifications, ref scaleModifications, kLocalScale); - - // Process Animator Modifications. - ProcessAnimatorModifications(state, ref positionModifications, ref rotationModifications, ref scaleModifications); - // Process position modifications. - ProcessVector3Modifications(state, ref positionModifications); - // Process rotation modifications. - ProcessRotationModifications(state, ref rotationModifications); - // Process scale modifications. - ProcessVector3Modifications(state, ref scaleModifications); - // Process what's remaining. - ProcessModifications(state, modifications); - - discardedModifications.Concat(discardedRotationModifications); - return discardedModifications.ToArray(); - } - - static bool ValueFromPropertyModification(PropertyModification modification, EditorCurveBinding binding, out object outObject) - { - if (modification == null) - { - outObject = null; - return false; - } - else if (binding.isPPtrCurve) - { - outObject = modification.objectReference; - return true; - } - else - { - float temp; - if (float.TryParse(modification.value, out temp)) - { - outObject = temp; - return true; - } - else - { - outObject = null; - return false; - } - } - } - - static void AddKey(IAnimationRecordingState state, EditorCurveBinding binding, Type type, PropertyModification modification) - { - GameObject root = state.activeRootGameObject; - AnimationClip clip = state.activeAnimationClip; - - if ((clip.hideFlags & HideFlags.NotEditable) != 0) - return; - - AnimationWindowCurve curve = new AnimationWindowCurve(clip, binding, type); - - // Add key at current frame - object currentValue = CurveBindingUtility.GetCurrentValue(root, binding); - - if (state.addZeroFrame) - { - // Is it a new curve? - if (curve.length == 0) - { - object oldValue = null; - if (!ValueFromPropertyModification(modification, binding, out oldValue)) - oldValue = currentValue; - - if (state.currentFrame != 0) - AnimationWindowUtility.AddKeyframeToCurve(curve, oldValue, type, AnimationKeyTime.Frame(0, clip.frameRate)); - } - } - - AnimationWindowUtility.AddKeyframeToCurve(curve, currentValue, type, AnimationKeyTime.Frame(state.currentFrame, clip.frameRate)); - - state.SaveCurve(curve); - } - - static void AddRotationKey(IAnimationRecordingState state, EditorCurveBinding binding, Type type, Vector3 previousEulerAngles, Vector3 currentEulerAngles) - { - AnimationClip clip = state.activeAnimationClip; - - if ((clip.hideFlags & HideFlags.NotEditable) != 0) - return; - - EditorCurveBinding[] additionalBindings = RotationCurveInterpolation.RemapAnimationBindingForRotationAddKey(binding, clip); - - // Add key at current frame - for (int i = 0; i < 3; i++) - { - AnimationWindowCurve curve = new AnimationWindowCurve(clip, additionalBindings[i], type); - - if (state.addZeroFrame) - { - // Is it a new curve? - if (curve.length == 0) - { - if (state.currentFrame != 0) - { - AnimationWindowUtility.AddKeyframeToCurve(curve, previousEulerAngles[i], type, AnimationKeyTime.Frame(0, clip.frameRate)); - } - } - } - - AnimationWindowUtility.AddKeyframeToCurve(curve, currentEulerAngles[i], type, AnimationKeyTime.Frame(state.currentFrame, clip.frameRate)); - state.SaveCurve(curve); - } - } - - internal class RootMotionModification - { - public UndoPropertyModification px; - public UndoPropertyModification py; - public UndoPropertyModification pz; - public UndoPropertyModification lastP; - - public UndoPropertyModification rx; - public UndoPropertyModification ry; - public UndoPropertyModification rz; - public UndoPropertyModification rw; - public UndoPropertyModification lastR; - } - - static private void ProcessRootMotionModifications(IAnimationRecordingState state, - ref System.Collections.Generic.Dictionary rootMotionModifications) - { - AnimationClip clip = state.activeAnimationClip; - GameObject root = state.activeRootGameObject; - Animator animator = root.GetComponent(); - - bool isHuman = animator != null ? animator.isHuman : false; - - foreach (KeyValuePair item in rootMotionModifications) - { - RootMotionModification m = item.Value; - Transform target = item.Key as Transform; - - Vector3 scale = target.localScale * (isHuman ? animator.humanScale : 1); - Vector3 position = target.localPosition; - Quaternion rotation = target.localRotation; - - if (m.lastP.previousValue != null) - { - ProcessAnimatorModification(state, animator, m.px, "MotionT.x", position.x, scale.x); - ProcessAnimatorModification(state, animator, m.py, "MotionT.y", position.y, scale.y); - ProcessAnimatorModification(state, animator, m.pz, "MotionT.z", position.z, scale.z); - } - - if (m.lastR.previousValue != null) - { - ProcessAnimatorModification(state, animator, m.rx, "MotionQ.x", rotation.x, 1); - ProcessAnimatorModification(state, animator, m.ry, "MotionQ.y", rotation.y, 1); - ProcessAnimatorModification(state, animator, m.rz, "MotionQ.z", rotation.z, 1); - ProcessAnimatorModification(state, animator, m.rw, "MotionQ.w", rotation.w, 1); - } - } - } - - static private void ProcessAnimatorModifications(IAnimationRecordingState state, - ref System.Collections.Generic.Dictionary positionModifications, - ref System.Collections.Generic.Dictionary rotationModifications, - ref System.Collections.Generic.Dictionary scaleModifications) - { - System.Collections.Generic.Dictionary rootMotionModifications = new Dictionary(); - - AnimationClip clip = state.activeAnimationClip; - GameObject root = state.activeRootGameObject; - Animator animator = root.GetComponent(); - - bool isHuman = animator != null ? animator.isHuman : false; - - // timeline root motion scale revert - // bool hasRootMotion = animator != null ? animator.hasRootMotion : false; - // bool applyRootMotion = animator != null ? animator.applyRootMotion : false; - - // process animator positions - List discardListPos = new List(); - - foreach (KeyValuePair item in positionModifications) - { - Vector3Modification m = item.Value; - Transform target = item.Key as Transform; - - if (target == null) - continue; - - EditorCurveBinding binding = new EditorCurveBinding(); - Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.last.currentValue, state.activeRootGameObject, out binding); - if (type == null) - continue; - - bool isRootTransform = root.transform == target; - // timeline root motion scale revert - // bool isRootMotion = (isHuman || hasRootMotion || applyRootMotion) && isRootTransform; - bool isRootMotion = false; - - bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target); - - if (isHumanBone) - { - Debug.LogWarning("Keyframing translation on humanoid rig is not supported!", target as Transform); - discardListPos.Add(item.Key); - } - else if (isRootMotion) - { - RootMotionModification rootMotionModification; - - if (!rootMotionModifications.TryGetValue(target, out rootMotionModification)) - { - rootMotionModification = new RootMotionModification(); - rootMotionModifications[target] = rootMotionModification; - } - - rootMotionModification.lastP = m.last; - rootMotionModification.px = m.x; - rootMotionModification.py = m.y; - rootMotionModification.pz = m.z; - - discardListPos.Add(item.Key); - } - } - - foreach (object key in discardListPos) - { - positionModifications.Remove(key); - } - - // process animator rotation - List discardListRot = new List(); - - foreach (KeyValuePair item in rotationModifications) - { - RotationModification m = item.Value; - Transform target = item.Key as Transform; - - if (target == null) - continue; - - EditorCurveBinding binding = new EditorCurveBinding(); - Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.lastQuatModification.currentValue, state.activeRootGameObject, out binding); - if (type == null) - continue; - - bool isRootTransform = root.transform == target; - - // timeline root motion scale revert - // bool isRootMotion = (isHuman || hasRootMotion || applyRootMotion) && isRootTransform; - bool isRootMotion = false; - - bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target); - - if (isHumanBone) - { - Debug.LogWarning("Keyframing rotation on humanoid rig is not supported!", target as Transform); - discardListRot.Add(item.Key); - } - else if (isRootMotion) - { - RootMotionModification rootMotionModification; - - if (!rootMotionModifications.TryGetValue(target, out rootMotionModification)) - { - rootMotionModification = new RootMotionModification(); - rootMotionModifications[target] = rootMotionModification; - } - - rootMotionModification.lastR = m.lastQuatModification; - rootMotionModification.rx = m.x; - rootMotionModification.ry = m.y; - rootMotionModification.rz = m.z; - rootMotionModification.rw = m.w; - - discardListRot.Add(item.Key); - } - } - - foreach (object key in discardListRot) - { - rotationModifications.Remove(key); - } - - // process animator scales - List discardListScale = new List(); - - foreach (KeyValuePair item in scaleModifications) - { - Vector3Modification m = item.Value; - Transform target = item.Key as Transform; - - if (target == null) - continue; - - EditorCurveBinding binding = new EditorCurveBinding(); - Type type = AnimationUtility.PropertyModificationToEditorCurveBinding(m.last.currentValue, state.activeRootGameObject, out binding); - if (type == null) - continue; - - bool isRootTransform = root.transform == target; - bool isHumanBone = isHuman && !isRootTransform && animator.IsBoneTransform(target); - if (isHumanBone) - { - Debug.LogWarning("Keyframing scale on humanoid rig is not supported!", target as Transform); - discardListScale.Add(item.Key); - } - } - - foreach (object key in discardListScale) - { - scaleModifications.Remove(key); - } - - ProcessRootMotionModifications(state, ref rootMotionModifications); - } - - static void ProcessAnimatorModification(IAnimationRecordingState state, Animator animator, UndoPropertyModification modification, string name, float value, float scale) - { - AnimationClip clip = state.activeAnimationClip; - - if ((clip.hideFlags & HideFlags.NotEditable) != 0) - return; - - float prevValue = value; - - object oValue; - - if (ValueFromPropertyModification(modification.currentValue, new EditorCurveBinding(), out oValue)) - value = (float)oValue; - - if (ValueFromPropertyModification(modification.previousValue, new EditorCurveBinding(), out oValue)) - prevValue = (float)oValue; - - value = Mathf.Abs(scale) > Mathf.Epsilon ? value / scale : value; - prevValue = Mathf.Abs(scale) > Mathf.Epsilon ? prevValue / scale : prevValue; - - var binding = new EditorCurveBinding(); - binding.propertyName = name; - binding.path = ""; - binding.type = typeof(Animator); - - var prop = new PropertyModification(); - prop.target = animator; - prop.propertyPath = binding.propertyName; - prop.value = value.ToString(); - - state.AddPropertyModification(binding, prop, modification.keepPrefabOverride); - - AnimationWindowCurve curve = new AnimationWindowCurve(clip, binding, typeof(float)); - - if (state.addZeroFrame && state.currentFrame != 0 && curve.length == 0) - { - AnimationWindowUtility.AddKeyframeToCurve(curve, prevValue, typeof(float), AnimationKeyTime.Frame(0, clip.frameRate)); - } - - AnimationWindowUtility.AddKeyframeToCurve(curve, value, typeof(float), AnimationKeyTime.Frame(state.currentFrame, clip.frameRate)); - - state.SaveCurve(curve); - } - - static public void SaveModifiedCurve(AnimationWindowCurve curve, AnimationClip clip) - { - curve.m_Keyframes.Sort((a, b) => a.time.CompareTo(b.time)); - - if (curve.isPPtrCurve) - { - ObjectReferenceKeyframe[] objectCurve = curve.ToObjectCurve(); - - if (objectCurve.Length == 0) - objectCurve = null; - - AnimationUtility.SetObjectReferenceCurve(clip, curve.binding, objectCurve); - } - else - { - AnimationCurve animationCurve = curve.ToAnimationCurve(); - - if (animationCurve.keys.Length == 0) - animationCurve = null; - else - QuaternionCurveTangentCalculation.UpdateTangentsFromMode(animationCurve, clip, curve.binding); - - AnimationUtility.SetEditorCurve(clip, curve.binding, animationCurve); - } - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs deleted file mode 100644 index 7a4818db55..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs +++ /dev/null @@ -1,289 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Profiling; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Animation", useTypeNameAsIconName = true)] - internal class AnimationWindow : EditorWindow, IHasCustomMenu - { - // Active Animation windows - private static List s_AnimationWindows = new List(); - public static List GetAllAnimationWindows() { return s_AnimationWindows; } - - [SerializeField] private AnimEditor m_AnimEditor; - - [SerializeField] - EditorGUIUtility.EditorLockTracker m_LockTracker = new EditorGUIUtility.EditorLockTracker(); - - [SerializeField] private int m_LastSelectedObjectID; - - private GUIStyle m_LockButtonStyle; - private GUIContent m_DefaultTitleContent; - private GUIContent m_RecordTitleContent; - - internal AnimationWindowState state - { - get - { - if (m_AnimEditor != null) - { - return m_AnimEditor.state; - } - return null; - } - } - - public void ForceRefresh() - { - if (m_AnimEditor != null) - { - m_AnimEditor.state.ForceRefresh(); - } - } - - public void OnEnable() - { - if (m_AnimEditor == null) - { - m_AnimEditor = CreateInstance(typeof(AnimEditor)) as AnimEditor; - m_AnimEditor.hideFlags = HideFlags.HideAndDontSave; - } - - s_AnimationWindows.Add(this); - titleContent = GetLocalizedTitleContent(); - - m_DefaultTitleContent = titleContent; - m_RecordTitleContent = EditorGUIUtility.TextContentWithIcon(titleContent.text, "Animation.Record"); - - OnSelectionChange(); - - Undo.undoRedoPerformed += UndoRedoPerformed; - } - - public void OnDisable() - { - s_AnimationWindows.Remove(this); - m_AnimEditor.OnDisable(); - - Undo.undoRedoPerformed -= UndoRedoPerformed; - } - - public void OnDestroy() - { - DestroyImmediate(m_AnimEditor); - } - - public void Update() - { - m_AnimEditor.Update(); - } - - public void OnGUI() - { - Profiler.BeginSample("AnimationWindow.OnGUI"); - titleContent = m_AnimEditor.state.recording ? m_RecordTitleContent : m_DefaultTitleContent; - m_AnimEditor.OnAnimEditorGUI(this, position); - Profiler.EndSample(); - } - - public void OnSelectionChange() - { - if (m_AnimEditor == null) - return; - - Object activeObject = Selection.activeObject; - - bool restoringLockedSelection = false; - if (m_LockTracker.isLocked && m_AnimEditor.stateDisabled) - { - activeObject = EditorUtility.InstanceIDToObject(m_LastSelectedObjectID); - restoringLockedSelection = true; - m_LockTracker.isLocked = false; - } - - GameObject activeGameObject = activeObject as GameObject; - if (activeGameObject != null) - { - EditGameObject(activeGameObject); - } - else - { - AnimationClip activeAnimationClip = activeObject as AnimationClip; - if (activeAnimationClip != null) - EditAnimationClip(activeAnimationClip); - } - - if (restoringLockedSelection && !m_AnimEditor.stateDisabled) - { - m_LockTracker.isLocked = true; - } - } - - public void OnFocus() - { - OnSelectionChange(); - } - - public void OnControllerChange() - { - // Refresh selectedItem to update selected clips. - OnSelectionChange(); - } - - public void OnLostFocus() - { - if (m_AnimEditor != null) - m_AnimEditor.OnLostFocus(); - } - - public bool EditGameObject(GameObject gameObject) - { - if (state.linkedWithSequencer == true) - return false; - - return EditGameObjectInternal(gameObject, (IAnimationWindowControl)null); - } - - public bool EditAnimationClip(AnimationClip animationClip) - { - if (state.linkedWithSequencer == true) - return false; - - return EditAnimationClipInternal(animationClip, (Object)null, (IAnimationWindowControl)null); - } - - public bool EditSequencerClip(AnimationClip animationClip, Object sourceObject, IAnimationWindowControl controlInterface) - { - if (EditAnimationClipInternal(animationClip, sourceObject, controlInterface)) - { - state.linkedWithSequencer = true; - return true; - } - - return false; - } - - public void UnlinkSequencer() - { - if (state.linkedWithSequencer) - { - state.linkedWithSequencer = false; - - // Selected object could have been changed when unlocking the animation window - EditAnimationClip(null); - OnSelectionChange(); - } - } - - private bool EditGameObjectInternal(GameObject gameObject, IAnimationWindowControl controlInterface) - { - if (EditorUtility.IsPersistent(gameObject)) - return false; - - if ((gameObject.hideFlags & HideFlags.NotEditable) != 0) - return false; - - var newSelection = GameObjectSelectionItem.Create(gameObject); - if (ShouldUpdateGameObjectSelection(newSelection)) - { - m_AnimEditor.selection = newSelection; - m_AnimEditor.overrideControlInterface = controlInterface; - - m_LastSelectedObjectID = gameObject != null ? gameObject.GetInstanceID() : 0; - } - else - return false; - - return true; - } - - private bool EditAnimationClipInternal(AnimationClip animationClip, Object sourceObject, IAnimationWindowControl controlInterface) - { - var newSelection = AnimationClipSelectionItem.Create(animationClip, sourceObject); - if (ShouldUpdateSelection(newSelection)) - { - m_AnimEditor.selection = newSelection; - m_AnimEditor.overrideControlInterface = controlInterface; - - m_LastSelectedObjectID = animationClip != null ? animationClip.GetInstanceID() : 0; - } - else - return false; - - return true; - } - - protected virtual void ShowButton(Rect r) - { - if (m_LockButtonStyle == null) - m_LockButtonStyle = "IN LockButton"; - - EditorGUI.BeginChangeCheck(); - - m_LockTracker.ShowButton(r, m_LockButtonStyle, m_AnimEditor.stateDisabled); - - // Selected object could have been changed when unlocking the animation window - if (EditorGUI.EndChangeCheck()) - OnSelectionChange(); - } - - private bool ShouldUpdateGameObjectSelection(GameObjectSelectionItem selectedItem) - { - if (m_LockTracker.isLocked) - return false; - - // Selected game object with no animation player. - if (selectedItem.rootGameObject == null) - return true; - - AnimationWindowSelectionItem currentSelection = m_AnimEditor.selection; - - // Game object holding animation player has changed. Update selection. - if (selectedItem.rootGameObject != currentSelection.rootGameObject) - return true; - - // No clip in current selection, favour new selection. - if (currentSelection.animationClip == null) - return true; - - // Make sure that animation clip is still referenced in animation player. - if (currentSelection.rootGameObject != null) - { - AnimationClip[] allClips = AnimationUtility.GetAnimationClips(currentSelection.rootGameObject); - if (!Array.Exists(allClips, x => x == currentSelection.animationClip)) - return true; - } - - return false; - } - - private bool ShouldUpdateSelection(AnimationWindowSelectionItem selectedItem) - { - if (m_LockTracker.isLocked) - return false; - - AnimationWindowSelectionItem currentSelection = m_AnimEditor.selection; - return (selectedItem.GetRefreshHash() != currentSelection.GetRefreshHash()); - } - - private void UndoRedoPerformed() - { - Repaint(); - } - - public virtual void AddItemsToMenu(GenericMenu menu) - { - m_LockTracker.AddItemsToMenu(menu, m_AnimEditor.stateDisabled); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowClipPopup.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowClipPopup.cs deleted file mode 100644 index 218dde0f47..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowClipPopup.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - [System.Serializable] - class AnimationWindowClipPopup - { - [SerializeField] public AnimationWindowState state; - [SerializeField] private int selectedIndex; - - public void OnGUI() - { - if (state.selection.canChangeAnimationClip) - { - string[] menuContent = GetClipMenuContent(); - EditorGUI.BeginChangeCheck(); - // TODO: Make this more robust - selectedIndex = EditorGUILayout.Popup(ClipToIndex(state.activeAnimationClip), menuContent, EditorStyles.toolbarPopup); - if (EditorGUI.EndChangeCheck()) - { - if (menuContent[selectedIndex] == AnimationWindowStyles.createNewClip.text) - { - AnimationClip newClip = AnimationWindowUtility.CreateNewClip(state.selection.rootGameObject.name); - if (newClip) - { - AnimationWindowUtility.AddClipToAnimationPlayerComponent(state.activeAnimationPlayer, newClip); - state.activeAnimationClip = newClip; - } - - // Layout has changed, bail out now. - EditorGUIUtility.ExitGUI(); - } - else - { - state.activeAnimationClip = IndexToClip(selectedIndex); - } - } - } - else if (state.activeAnimationClip != null) - { - Rect r = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight, AnimationWindowStyles.toolbarLabel); - EditorGUI.LabelField(r, CurveUtility.GetClipName(state.activeAnimationClip), AnimationWindowStyles.toolbarLabel); - } - } - - private string[] GetClipMenuContent() - { - List content = new List(); - content.AddRange(GetClipNames()); - - if (state.selection.rootGameObject != null) - { - content.Add(""); - content.Add(AnimationWindowStyles.createNewClip.text); - } - - return content.ToArray(); - } - - private AnimationClip[] GetOrderedClipList() - { - AnimationClip[] clips = new AnimationClip[0]; - if (state.activeRootGameObject != null) - clips = AnimationUtility.GetAnimationClips(state.activeRootGameObject); - - Array.Sort(clips, (AnimationClip clip1, AnimationClip clip2) => CurveUtility.GetClipName(clip1).CompareTo(CurveUtility.GetClipName(clip2))); - - return clips; - } - - private string[] GetClipNames() - { - AnimationClip[] clips = GetOrderedClipList(); - string[] clipNames = new string[clips.Length]; - - for (int i = 0; i < clips.Length; i++) - clipNames[i] = CurveUtility.GetClipName(clips[i]); - - return clipNames; - } - - // TODO: Make this more robust - private AnimationClip IndexToClip(int index) - { - if (state.activeRootGameObject != null) - { - AnimationClip[] clips = GetOrderedClipList(); - if (index >= 0 && index < clips.Length) - return clips[index]; - } - - return null; - } - - // TODO: Make this more robust - private int ClipToIndex(AnimationClip clip) - { - if (state.activeRootGameObject != null) - { - int index = 0; - AnimationClip[] clips = GetOrderedClipList(); - foreach (AnimationClip other in clips) - { - if (clip == other) - return index; - index++; - } - } - return 0; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs deleted file mode 100644 index 423aaff44c..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs +++ /dev/null @@ -1,848 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using System.Collections; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal class AnimationWindowControl : IAnimationWindowControl, IAnimationContextualResponder - { - class CandidateRecordingState : IAnimationRecordingState - { - public GameObject activeGameObject { get; private set; } - public GameObject activeRootGameObject { get; private set; } - public AnimationClip activeAnimationClip { get; private set; } - public int currentFrame { get { return 0; } } - - public bool addZeroFrame { get { return false; } } - - public CandidateRecordingState(AnimationWindowState state, AnimationClip candidateClip) - { - activeGameObject = state.activeGameObject; - activeRootGameObject = state.activeRootGameObject; - activeAnimationClip = candidateClip; - } - - public bool DiscardModification(PropertyModification modification) - { - return !AnimationMode.IsPropertyAnimated(modification.target, modification.propertyPath); - } - - public void SaveCurve(AnimationWindowCurve curve) - { - Undo.RegisterCompleteObjectUndo(curve.clip, "Edit Candidate Curve"); - AnimationRecording.SaveModifiedCurve(curve, curve.clip); - } - - public void AddPropertyModification(EditorCurveBinding binding, PropertyModification propertyModification, bool keepPrefabOverride) - { - AnimationMode.AddCandidate(binding, propertyModification, keepPrefabOverride); - } - } - - enum RecordingStateMode - { - ManualKey, - AutoKey - }; - - class RecordingState : IAnimationRecordingState - { - private AnimationWindowState m_State; - private RecordingStateMode m_Mode; - - public GameObject activeGameObject { get { return m_State.activeGameObject; } } - public GameObject activeRootGameObject { get { return m_State.activeRootGameObject; } } - public AnimationClip activeAnimationClip { get { return m_State.activeAnimationClip; } } - public int currentFrame { get { return m_State.currentFrame; } } - - public bool addZeroFrame { get { return (m_Mode == RecordingStateMode.AutoKey); } } - public bool addPropertyModification { get { return m_State.previewing; } } - - public RecordingState(AnimationWindowState state, RecordingStateMode mode) - { - m_State = state; - m_Mode = mode; - } - - public bool DiscardModification(PropertyModification modification) - { - return false; - } - - public void SaveCurve(AnimationWindowCurve curve) - { - m_State.SaveCurve(curve); - } - - public void AddPropertyModification(EditorCurveBinding binding, PropertyModification propertyModification, bool keepPrefabOverride) - { - AnimationMode.AddPropertyModification(binding, propertyModification, keepPrefabOverride); - } - } - - [SerializeField] private AnimationKeyTime m_Time; - - [NonSerialized] private float m_PreviousUpdateTime; - - [NonSerialized] public AnimationWindowState state; - public AnimEditor animEditor { get { return state.animEditor; } } - - [SerializeField] private AnimationClip m_CandidateClip; - - [SerializeField] private AnimationModeDriver m_Driver; - [SerializeField] private AnimationModeDriver m_CandidateDriver; - - public override void OnEnable() - { - base.OnEnable(); - } - - public void OnDisable() - { - StopPreview(); - StopPlayback(); - } - - public override void OnSelectionChanged() - { - // Set back time at beginning and stop recording. - if (state != null) - m_Time = AnimationKeyTime.Time(0f, state.frameRate); - - StopPreview(); - StopPlayback(); - } - - public override AnimationKeyTime time - { - get - { - return m_Time; - } - } - - public override void GoToTime(float time) - { - SetCurrentTime(time); - } - - public override void GoToFrame(int frame) - { - SetCurrentFrame(frame); - } - - public override void StartScrubTime() - { - // nothing to do... - } - - public override void ScrubTime(float time) - { - SetCurrentTime(time); - } - - public override void EndScrubTime() - { - // nothing to do... - } - - public override void GoToPreviousFrame() - { - SetCurrentFrame(time.frame - 1); - } - - public override void GoToNextFrame() - { - SetCurrentFrame(time.frame + 1); - } - - public override void GoToPreviousKeyframe() - { - List curves = (state.showCurveEditor && state.activeCurves.Count > 0) ? state.activeCurves : state.allCurves; - - float newTime = AnimationWindowUtility.GetPreviousKeyframeTime(curves.ToArray(), time.time, state.clipFrameRate); - SetCurrentTime(state.SnapToFrame(newTime, AnimationWindowState.SnapMode.SnapToClipFrame)); - } - - public void GoToPreviousKeyframe(PropertyModification[] modifications) - { - EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip); - if (bindings.Length == 0) - return; - - List curves = new List(); - for (int i = 0; i < state.allCurves.Count; ++i) - { - AnimationWindowCurve curve = state.allCurves[i]; - if (Array.Exists(bindings, binding => curve.binding.Equals(binding))) - curves.Add(curve); - } - - float newTime = AnimationWindowUtility.GetPreviousKeyframeTime(curves.ToArray(), time.time, state.clipFrameRate); - SetCurrentTime(state.SnapToFrame(newTime, AnimationWindowState.SnapMode.SnapToClipFrame)); - - state.Repaint(); - } - - public override void GoToNextKeyframe() - { - List curves = (state.showCurveEditor && state.activeCurves.Count > 0) ? state.activeCurves : state.allCurves; - - float newTime = AnimationWindowUtility.GetNextKeyframeTime(curves.ToArray(), time.time, state.clipFrameRate); - SetCurrentTime(state.SnapToFrame(newTime, AnimationWindowState.SnapMode.SnapToClipFrame)); - } - - public void GoToNextKeyframe(PropertyModification[] modifications) - { - EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip); - if (bindings.Length == 0) - return; - - List curves = new List(); - for (int i = 0; i < state.allCurves.Count; ++i) - { - AnimationWindowCurve curve = state.allCurves[i]; - if (Array.Exists(bindings, binding => curve.binding.Equals(binding))) - curves.Add(curve); - } - - float newTime = AnimationWindowUtility.GetNextKeyframeTime(curves.ToArray(), time.time, state.clipFrameRate); - SetCurrentTime(state.SnapToFrame(newTime, AnimationWindowState.SnapMode.SnapToClipFrame)); - - state.Repaint(); - } - - public override void GoToFirstKeyframe() - { - if (state.activeAnimationClip) - SetCurrentTime(state.activeAnimationClip.startTime); - } - - public override void GoToLastKeyframe() - { - if (state.activeAnimationClip) - SetCurrentTime(state.activeAnimationClip.stopTime); - } - - private void SnapTimeToFrame() - { - float newTime = state.FrameToTime(time.frame); - SetCurrentTime(newTime); - } - - private void SetCurrentTime(float value) - { - if (!Mathf.Approximately(value, time.time)) - { - m_Time = AnimationKeyTime.Time(value, state.frameRate); - StartPreview(); - ClearCandidates(); - ResampleAnimation(); - } - } - - private void SetCurrentFrame(int value) - { - if (value != time.frame) - { - m_Time = AnimationKeyTime.Frame(value, state.frameRate); - StartPreview(); - ClearCandidates(); - ResampleAnimation(); - } - } - - public override bool canPlay - { - get - { - return canPreview; - } - } - - public override bool playing - { - get - { - return AnimationMode.InAnimationPlaybackMode() && previewing; - } - } - - public override bool StartPlayback() - { - if (!canPlay) - return false; - - if (!playing) - { - AnimationMode.StartAnimationPlaybackMode(); - - m_PreviousUpdateTime = Time.realtimeSinceStartup; - - // Auto-Preview when start playing - StartPreview(); - ClearCandidates(); - } - - return true; - } - - public override void StopPlayback() - { - if (AnimationMode.InAnimationPlaybackMode()) - { - AnimationMode.StopAnimationPlaybackMode(); - - // Snap to frame when playing stops - SnapTimeToFrame(); - } - } - - public override bool PlaybackUpdate() - { - if (!playing) - return false; - - float deltaTime = Time.realtimeSinceStartup - m_PreviousUpdateTime; - m_PreviousUpdateTime = Time.realtimeSinceStartup; - - float newTime = time.time + deltaTime; - - // looping - if (newTime > state.maxTime) - newTime = state.minTime; - - m_Time = AnimationKeyTime.Time(Mathf.Clamp(newTime, state.minTime, state.maxTime), state.frameRate); - - ResampleAnimation(); - - return true; - } - - public override bool canPreview - { - get - { - if (!state.selection.canPreview) - return false; - - return AnimationMode.InAnimationMode(GetAnimationModeDriver()) || !AnimationMode.InAnimationMode(); - } - } - - public override bool previewing - { - get - { - return AnimationMode.InAnimationMode(GetAnimationModeDriver()); - } - } - - public override bool StartPreview() - { - if (previewing) - return true; - - if (!canPreview) - return false; - - AnimationMode.StartAnimationMode(GetAnimationModeDriver()); - AnimationPropertyContextualMenu.Instance.SetResponder(this); - Undo.postprocessModifications += PostprocessAnimationRecordingModifications; - return true; - } - - public override void StopPreview() - { - StopPlayback(); - StopRecording(); - ClearCandidates(); - - AnimationMode.StopAnimationMode(GetAnimationModeDriver()); - - // reset responder only if we have set it - if (AnimationPropertyContextualMenu.Instance.IsResponder(this)) - { - AnimationPropertyContextualMenu.Instance.SetResponder(null); - } - - Undo.postprocessModifications -= PostprocessAnimationRecordingModifications; - } - - public override bool canRecord - { - get - { - if (!state.selection.canRecord) - return false; - - return canPreview; - } - } - - public override bool recording - { - get - { - if (previewing) - return AnimationMode.InAnimationRecording(); - return false; - } - } - - public override bool StartRecording(Object targetObject) - { - return StartRecording(); - } - - private bool StartRecording() - { - if (recording) - return true; - - if (!canRecord) - return false; - - if (StartPreview()) - { - AnimationMode.StartAnimationRecording(); - ClearCandidates(); - return true; - } - - return false; - } - - public override void StopRecording() - { - if (recording) - { - AnimationMode.StopAnimationRecording(); - } - } - - private void StartCandidateRecording() - { - AnimationMode.StartCandidateRecording(GetCandidateDriver()); - } - - private void StopCandidateRecording() - { - AnimationMode.StopCandidateRecording(); - } - - public override void ResampleAnimation() - { - if (state.disabled) - return; - - if (previewing == false) - return; - if (canPreview == false) - return; - - if (state.activeAnimationClip != null) - { - AnimationMode.BeginSampling(); - - Undo.FlushUndoRecordObjects(); - - AnimationMode.SampleAnimationClip(state.activeRootGameObject, state.activeAnimationClip, time.time); - if (m_CandidateClip != null) - AnimationMode.SampleCandidateClip(state.activeRootGameObject, m_CandidateClip, 0f); - - AnimationMode.EndSampling(); - - SceneView.RepaintAll(); - InspectorWindow.RepaintAllInspectors(); - - // Particle editor needs to be manually repainted to refresh the animated properties - var particleSystemWindow = ParticleSystemWindow.GetInstance(); - if (particleSystemWindow) - particleSystemWindow.Repaint(); - } - } - - private AnimationModeDriver GetAnimationModeDriver() - { - if (m_Driver == null) - { - m_Driver = CreateInstance(); - m_Driver.name = "AnimationWindowDriver"; - m_Driver.isKeyCallback += (Object target, string propertyPath) => - { - if (AnimationMode.IsPropertyAnimated(target, propertyPath)) - { - var modification = new PropertyModification(); - modification.target = target; - modification.propertyPath = propertyPath; - - return KeyExists(new PropertyModification[] {modification}); - } - - return false; - }; - } - - return m_Driver; - } - - private AnimationModeDriver GetCandidateDriver() - { - if (m_CandidateDriver == null) - { - m_CandidateDriver = CreateInstance(); - m_CandidateDriver.name = "AnimationWindowCandidateDriver"; - } - - return m_CandidateDriver; - } - - private UndoPropertyModification[] PostprocessAnimationRecordingModifications(UndoPropertyModification[] modifications) - { - //Fix for case 751009: The animationMode can be changed outside the AnimationWindow, and this callback needs to be unregistered. - if (!AnimationMode.InAnimationMode(GetAnimationModeDriver())) - { - Undo.postprocessModifications -= PostprocessAnimationRecordingModifications; - return modifications; - } - - if (recording) - return ProcessAutoKey(modifications); - else if (previewing) - return RegisterCandidates(modifications); - - return modifications; - } - - private UndoPropertyModification[] ProcessAutoKey(UndoPropertyModification[] modifications) - { - BeginKeyModification(); - - RecordingState recordingState = new RecordingState(state, RecordingStateMode.AutoKey); - UndoPropertyModification[] discardedModifications = AnimationRecording.Process(recordingState, modifications); - - EndKeyModification(); - - return discardedModifications; - } - - private UndoPropertyModification[] RegisterCandidates(UndoPropertyModification[] modifications) - { - bool createNewClip = (m_CandidateClip == null); - if (createNewClip) - { - m_CandidateClip = new AnimationClip(); - m_CandidateClip.legacy = state.activeAnimationClip.legacy; - m_CandidateClip.name = "CandidateClip"; - - StartCandidateRecording(); - } - - CandidateRecordingState recordingState = new CandidateRecordingState(state, m_CandidateClip); - UndoPropertyModification[] discardedModifications = AnimationRecording.Process(recordingState, modifications); - - // No modifications were added to the candidate clip, discard. - if (createNewClip && discardedModifications.Length == modifications.Length) - { - ClearCandidates(); - } - - // Make sure inspector is repainted after adding new candidates to get appropriate feedback. - InspectorWindow.RepaintAllInspectors(); - - return discardedModifications; - } - - private void RemoveFromCandidates(PropertyModification[] modifications) - { - if (m_CandidateClip == null) - return; - - EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, m_CandidateClip); - if (bindings.Length == 0) - return; - - // Remove entry from candidate clip. - Undo.RegisterCompleteObjectUndo(m_CandidateClip, "Edit Candidate Curve"); - - for (int i = 0; i < bindings.Length; ++i) - { - EditorCurveBinding binding = bindings[i]; - if (binding.isPPtrCurve) - AnimationUtility.SetObjectReferenceCurve(m_CandidateClip, binding, null); - else - AnimationUtility.SetEditorCurve(m_CandidateClip, binding, null); - } - - // Clear out candidate clip if it's empty. - if (AnimationUtility.GetCurveBindings(m_CandidateClip).Length == 0 && AnimationUtility.GetObjectReferenceCurveBindings(m_CandidateClip).Length == 0) - ClearCandidates(); - } - - public override void ClearCandidates() - { - m_CandidateClip = null; - StopCandidateRecording(); - } - - public override void ProcessCandidates() - { - if (m_CandidateClip == null) - return; - - BeginKeyModification(); - - EditorCurveBinding[] bindings = AnimationUtility.GetCurveBindings(m_CandidateClip); - EditorCurveBinding[] objectCurveBindings = AnimationUtility.GetObjectReferenceCurveBindings(m_CandidateClip); - - List curves = new List(); - - for (int i = 0; i < state.allCurves.Count; ++i) - { - AnimationWindowCurve curve = state.allCurves[i]; - EditorCurveBinding remappedBinding = RotationCurveInterpolation.RemapAnimationBindingForRotationCurves(curve.binding, m_CandidateClip); - if (Array.Exists(bindings, binding => remappedBinding.Equals(binding)) || Array.Exists(objectCurveBindings, binding => remappedBinding.Equals(binding))) - curves.Add(curve); - } - - AnimationWindowUtility.AddKeyframes(state, curves.ToArray(), time); - - EndKeyModification(); - - ClearCandidates(); - } - - private List GetKeys(PropertyModification[] modifications) - { - var keys = new List(); - - EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip); - if (bindings.Length == 0) - return keys; - - for (int i = 0; i < state.allCurves.Count; ++i) - { - AnimationWindowCurve curve = state.allCurves[i]; - if (Array.Exists(bindings, binding => curve.binding.Equals(binding))) - { - int keyIndex = curve.GetKeyframeIndex(state.time); - if (keyIndex >= 0) - { - keys.Add(curve.m_Keyframes[keyIndex]); - } - } - } - - return keys; - } - - public bool IsAnimatable(PropertyModification[] modifications) - { - for (int i = 0; i < modifications.Length; ++i) - { - var modification = modifications[i]; - if (AnimationWindowUtility.PropertyIsAnimatable(modification.target, modification.propertyPath, state.activeRootGameObject)) - return true; - } - - return false; - } - - public bool IsEditable(Object targetObject) - { - if (state.selection.disabled) - return false; - - if (previewing == false) - return false; - - GameObject gameObject = null; - if (targetObject is Component) - gameObject = ((Component)targetObject).gameObject; - else if (targetObject is GameObject) - gameObject = (GameObject)targetObject; - - if (gameObject != null) - { - Component animationPlayer = AnimationWindowUtility.GetClosestAnimationPlayerComponentInParents(gameObject.transform); - if (state.selection.animationPlayer == animationPlayer) - { - return state.selection.animationIsEditable; - } - } - - return false; - } - - public bool KeyExists(PropertyModification[] modifications) - { - return (GetKeys(modifications).Count > 0); - } - - public bool CandidateExists(PropertyModification[] modifications) - { - if (!HasAnyCandidates()) - return false; - - for (int i = 0; i < modifications.Length; ++i) - { - var modification = modifications[i]; - if (AnimationMode.IsPropertyCandidate(modification.target, modification.propertyPath)) - return true; - } - - return false; - } - - public bool CurveExists(PropertyModification[] modifications) - { - EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip); - if (bindings.Length == 0) - return false; - - EditorCurveBinding[] clipBindings = AnimationUtility.GetCurveBindings(state.activeAnimationClip); - if (clipBindings.Length == 0) - return false; - - if (Array.Exists(bindings, binding => Array.Exists(clipBindings, clipBinding => clipBinding.Equals(binding)))) - return true; - - EditorCurveBinding[] objectCurveBindings = AnimationUtility.GetObjectReferenceCurveBindings(state.activeAnimationClip); - if (objectCurveBindings.Length == 0) - return false; - - return Array.Exists(objectCurveBindings, binding => Array.Exists(clipBindings, clipBinding => clipBinding.Equals(binding))); - } - - public bool HasAnyCandidates() - { - return (m_CandidateClip != null); - } - - public bool HasAnyCurves() - { - return (state.allCurves.Count > 0); - } - - public void AddKey(SerializedProperty property) - { - AddKey(AnimationWindowUtility.SerializedPropertyToPropertyModifications(property)); - } - - public void AddKey(PropertyModification[] modifications) - { - var undoModifications = new UndoPropertyModification[modifications.Length]; - for (int i = 0; i < modifications.Length; ++i) - { - var modification = modifications[i]; - undoModifications[i].previousValue = modification; - undoModifications[i].currentValue = modification; - } - - BeginKeyModification(); - - var recordingState = new RecordingState(state, RecordingStateMode.ManualKey); - AnimationRecording.Process(recordingState, undoModifications); - - EndKeyModification(); - - RemoveFromCandidates(modifications); - - ResampleAnimation(); - state.Repaint(); - } - - public void RemoveKey(SerializedProperty property) - { - RemoveKey(AnimationWindowUtility.SerializedPropertyToPropertyModifications(property)); - } - - public void RemoveKey(PropertyModification[] modifications) - { - BeginKeyModification(); - - List keys = GetKeys(modifications); - state.DeleteKeys(keys); - - RemoveFromCandidates(modifications); - - EndKeyModification(); - - ResampleAnimation(); - state.Repaint(); - } - - public void RemoveCurve(SerializedProperty property) - { - RemoveCurve(AnimationWindowUtility.SerializedPropertyToPropertyModifications(property)); - } - - public void RemoveCurve(PropertyModification[] modifications) - { - EditorCurveBinding[] bindings = AnimationWindowUtility.PropertyModificationsToEditorCurveBindings(modifications, state.activeRootGameObject, state.activeAnimationClip); - if (bindings.Length == 0) - return; - - BeginKeyModification(); - - Undo.RegisterCompleteObjectUndo(state.activeAnimationClip, "Remove Curve"); - - for (int i = 0; i < bindings.Length; ++i) - { - EditorCurveBinding binding = bindings[i]; - if (binding.isPPtrCurve) - AnimationUtility.SetObjectReferenceCurve(state.activeAnimationClip, binding, null); - else - AnimationUtility.SetEditorCurve(state.activeAnimationClip, binding, null); - } - - EndKeyModification(); - - RemoveFromCandidates(modifications); - - ResampleAnimation(); - state.Repaint(); - } - - public void AddCandidateKeys() - { - ProcessCandidates(); - - ResampleAnimation(); - state.Repaint(); - } - - public void AddAnimatedKeys() - { - BeginKeyModification(); - - AnimationWindowUtility.AddKeyframes(state, state.allCurves.ToArray(), time); - ClearCandidates(); - - EndKeyModification(); - - ResampleAnimation(); - state.Repaint(); - } - - private void BeginKeyModification() - { - if (animEditor != null) - animEditor.BeginKeyModification(); - } - - private void EndKeyModification() - { - if (animEditor != null) - animEditor.EndKeyModification(); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowCurve.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowCurve.cs deleted file mode 100644 index f866b167e1..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowCurve.cs +++ /dev/null @@ -1,325 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal class AnimationWindowCurve : IComparable - { - public const float timeEpsilon = 0.00001f; - - public List m_Keyframes; - - private EditorCurveBinding m_Binding; - private int m_BindingHashCode; - - private AnimationClip m_Clip; - private AnimationWindowSelectionItem m_SelectionBinding; - - private System.Type m_ValueType; - - public EditorCurveBinding binding { get { return m_Binding; } } - public bool isPPtrCurve { get { return m_Binding.isPPtrCurve; } } - public bool isDiscreteCurve { get { return m_Binding.isDiscreteCurve; } } - public bool isPhantom { get { return m_Binding.isPhantom; } } - public string propertyName { get { return m_Binding.propertyName; } } - public string path { get { return m_Binding.path; } } - public System.Type type { get { return m_Binding.type; } } - public System.Type valueType { get { return m_ValueType; } } - public int length { get { return m_Keyframes.Count; } } - - public int depth { get { return path.Length > 0 ? path.Split('/').Length : 0; } } - - public AnimationClip clip { get { return m_Clip; } } - - public GameObject rootGameObject { get { return m_SelectionBinding != null ? m_SelectionBinding.rootGameObject : null; } } - public ScriptableObject scriptableObject { get { return m_SelectionBinding != null ? m_SelectionBinding.scriptableObject : null; } } - public bool clipIsEditable { get { return m_SelectionBinding != null ? m_SelectionBinding.clipIsEditable : true; } } - public bool animationIsEditable { get { return m_SelectionBinding != null ? m_SelectionBinding.animationIsEditable : true; } } - public int selectionID { get { return m_SelectionBinding != null ? m_SelectionBinding.id : 0; } } - - public AnimationWindowSelectionItem selectionBinding { get { return m_SelectionBinding; } set { m_SelectionBinding = value; } } - - public AnimationWindowCurve(AnimationClip clip, EditorCurveBinding binding, System.Type valueType) - { - binding = RotationCurveInterpolation.RemapAnimationBindingForRotationCurves(binding, clip); - - m_Binding = binding; - m_BindingHashCode = binding.GetHashCode(); - m_ValueType = valueType; - m_Clip = clip; - - LoadKeyframes(clip); - } - - public void LoadKeyframes(AnimationCurve curve) - { - if (curve == null) - return; - - for (int i = 0; i < curve.length; i++) - m_Keyframes.Add(new AnimationWindowKeyframe(this, curve[i])); - } - - public void LoadKeyframes(AnimationClip clip) - { - m_Keyframes = new List(); - - if (!m_Binding.isPPtrCurve) - { - AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, binding); - LoadKeyframes(curve); - } - else - { - ObjectReferenceKeyframe[] curve = AnimationUtility.GetObjectReferenceCurve(clip, binding); - if (curve != null) - { - for (int i = 0; i < curve.Length; i++) - m_Keyframes.Add(new AnimationWindowKeyframe(this, curve[i])); - } - } - } - - public override int GetHashCode() - { - int clipID = (clip == null ? 0 : clip.GetInstanceID()); - return unchecked(selectionID * 92821 ^ clipID * 19603 ^ GetBindingHashCode()); - } - - public int GetBindingHashCode() - { - return m_BindingHashCode; - } - - public int CompareTo(AnimationWindowCurve obj) - { - bool pathEquals = path.Equals(obj.path); - bool typeEquals = obj.type == type; - - if (!pathEquals && depth != obj.depth) - { - int minLength = Math.Min(path.Length, obj.path.Length); - int commonLength = 0; - int index = 0; - for (; index < minLength; ++index) - { - if (path[index] != obj.path[index]) - break; - - if (path[index] == '/') - commonLength = index + 1; - } - - if (index == minLength) - commonLength = minLength; - - string subPath1 = path.Substring(commonLength); - string subPath2 = obj.path.Substring(commonLength); - - if (String.IsNullOrEmpty(subPath1)) - return -1; - else if (String.IsNullOrEmpty(subPath2)) - return 1; - - Regex r = new Regex(@"^[^\/]*\/"); - - Match match1 = r.Match(subPath1); - string next1 = match1.Success ? match1.Value.Substring(0, match1.Value.Length - 1) : subPath1; - - Match match2 = r.Match(subPath2); - string next2 = match2.Success ? match2.Value.Substring(0, match2.Value.Length - 1) : subPath2; - - return next1.CompareTo(next2); - } - - bool sameTransformComponent = type == typeof(Transform) && obj.type == typeof(Transform) && pathEquals; - bool oneIsTransformComponent = (type == typeof(Transform) || obj.type == typeof(Transform)) && pathEquals; - - // We want to sort position before rotation - if (sameTransformComponent) - { - string propertyGroupA = AnimationWindowUtility.GetNicePropertyGroupDisplayName(typeof(Transform), AnimationWindowUtility.GetPropertyGroupName(propertyName)); - string propertyGroupB = AnimationWindowUtility.GetNicePropertyGroupDisplayName(typeof(Transform), AnimationWindowUtility.GetPropertyGroupName(obj.propertyName)); - - if (propertyGroupA.Contains("Position") && propertyGroupB.Contains("Rotation")) - return -1; - if (propertyGroupA.Contains("Rotation") && propertyGroupB.Contains("Position")) - return 1; - } - // Transform component should always come first. - else if (oneIsTransformComponent) - { - if (type == typeof(Transform)) - return -1; - else - return 1; - } - - // Sort (.r, .g, .b, .a) and (.x, .y, .z, .w) - if (pathEquals && typeEquals) - { - int lhsIndex = AnimationWindowUtility.GetComponentIndex(obj.propertyName); - int rhsIndex = AnimationWindowUtility.GetComponentIndex(propertyName); - if (lhsIndex != -1 && rhsIndex != -1 && propertyName.Substring(0, propertyName.Length - 2) == obj.propertyName.Substring(0, obj.propertyName.Length - 2)) - return rhsIndex - lhsIndex; - } - - return (path + type + propertyName).CompareTo(obj.path + obj.type + obj.propertyName); - } - - public AnimationCurve ToAnimationCurve() - { - int length = m_Keyframes.Count; - AnimationCurve animationCurve = new AnimationCurve(); - List keys = new List(); - - float lastFrameTime = float.MinValue; - - for (int i = 0; i < length; i++) - { - // Make sure we don't get two keyframes in an exactly the same time. We just ignore those. - if (Mathf.Abs(m_Keyframes[i].time - lastFrameTime) > AnimationWindowCurve.timeEpsilon) - { - Keyframe newKeyframe = m_Keyframes[i].ToKeyframe(); - keys.Add(newKeyframe); - lastFrameTime = m_Keyframes[i].time; - } - } - - animationCurve.keys = keys.ToArray(); - return animationCurve; - } - - public ObjectReferenceKeyframe[] ToObjectCurve() - { - int length = m_Keyframes.Count; - List keys = new List(); - - float lastFrameTime = float.MinValue; - - for (int i = 0; i < length; i++) - { - // Make sure we don't get two keyframes in an exactly the same time. We just ignore those. - if (Mathf.Abs(m_Keyframes[i].time - lastFrameTime) > AnimationWindowCurve.timeEpsilon) - { - ObjectReferenceKeyframe newKeyframe = m_Keyframes[i].ToObjectReferenceKeyframe(); - lastFrameTime = newKeyframe.time; - keys.Add(newKeyframe); - } - } - - return keys.ToArray(); - } - - public AnimationWindowKeyframe FindKeyAtTime(AnimationKeyTime keyTime) - { - int index = GetKeyframeIndex(keyTime); - if (index == -1) - return null; - - return m_Keyframes[index]; - } - - public object Evaluate(float time) - { - if (m_Keyframes.Count == 0) - return isPPtrCurve ? null : (object)0f; - - AnimationWindowKeyframe firstKey = m_Keyframes[0]; - if (time <= firstKey.time) - return firstKey.value; - - AnimationWindowKeyframe lastKey = m_Keyframes[m_Keyframes.Count - 1]; - if (time >= lastKey.time) - return lastKey.value; - - AnimationWindowKeyframe key = firstKey; - for (int i = 1; i < m_Keyframes.Count; ++i) - { - AnimationWindowKeyframe nextKey = m_Keyframes[i]; - - if (key.time < time && nextKey.time >= time) - { - if (isPPtrCurve) - { - return key.value; - } - else - { - // Create an animation curve stub and evaluate. - Keyframe keyframe = key.ToKeyframe(); - Keyframe nextKeyframe = nextKey.ToKeyframe(); - - AnimationCurve animationCurve = new AnimationCurve(); - animationCurve.keys = new Keyframe[2] { keyframe, nextKeyframe }; - - return animationCurve.Evaluate(time); - } - } - - key = nextKey; - } - - // Shouldn't happen... - return isPPtrCurve ? null : (object)0f; - } - - public void AddKeyframe(AnimationWindowKeyframe key, AnimationKeyTime keyTime) - { - // If there is already key in this time, we always want to remove it - RemoveKeyframe(keyTime); - - m_Keyframes.Add(key); - m_Keyframes.Sort((a, b) => a.time.CompareTo(b.time)); - } - - public void RemoveKeyframe(AnimationKeyTime time) - { - // Loop backwards so key removals don't mess up order - for (int i = m_Keyframes.Count - 1; i >= 0; i--) - { - if (time.ContainsTime(m_Keyframes[i].time)) - m_Keyframes.RemoveAt(i); - } - } - - public bool HasKeyframe(AnimationKeyTime time) - { - return GetKeyframeIndex(time) != -1; - } - - public int GetKeyframeIndex(AnimationKeyTime time) - { - for (int i = 0; i < m_Keyframes.Count; i++) - { - if (time.ContainsTime(m_Keyframes[i].time)) - return i; - } - return -1; - } - - // Remove keys at range. Start time is exclusive and end time inclusive. - public void RemoveKeysAtRange(float startTime, float endTime) - { - for (int i = m_Keyframes.Count - 1; i >= 0; i--) - { - if (Mathf.Approximately(endTime, m_Keyframes[i].time) || - m_Keyframes[i].time > startTime && m_Keyframes[i].time < endTime) - m_Keyframes.RemoveAt(i); - } - } - - public void Clear() - { - m_Keyframes.Clear(); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowEvent.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowEvent.cs deleted file mode 100644 index 613cfa17ff..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowEvent.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal struct AnimationWindowEventMethod - { - public string name; - public Type parameterType; - } - - internal class AnimationWindowEvent : ScriptableObject - { - public GameObject root; - public AnimationClip clip; - public AnimationClipInfoProperties clipInfo; - public int eventIndex; - - static public AnimationWindowEvent CreateAndEdit(GameObject root, AnimationClip clip, float time) - { - AnimationEvent animationEvent = new AnimationEvent(); - animationEvent.time = time; - - // Or add a new one - AnimationEvent[] events = AnimationUtility.GetAnimationEvents(clip); - int eventIndex = InsertAnimationEvent(ref events, clip, animationEvent); - - AnimationWindowEvent animationWindowEvent = CreateInstance(); - animationWindowEvent.hideFlags = HideFlags.HideInHierarchy; - animationWindowEvent.name = "Animation Event"; - - animationWindowEvent.root = root; - animationWindowEvent.clip = clip; - animationWindowEvent.clipInfo = null; - animationWindowEvent.eventIndex = eventIndex; - - return animationWindowEvent; - } - - static public AnimationWindowEvent Edit(GameObject root, AnimationClip clip, int eventIndex) - { - AnimationWindowEvent animationWindowEvent = CreateInstance(); - animationWindowEvent.hideFlags = HideFlags.HideInHierarchy; - animationWindowEvent.name = "Animation Event"; - - animationWindowEvent.root = root; - animationWindowEvent.clip = clip; - animationWindowEvent.clipInfo = null; - animationWindowEvent.eventIndex = eventIndex; - - return animationWindowEvent; - } - - static public AnimationWindowEvent Edit(AnimationClipInfoProperties clipInfo, int eventIndex) - { - AnimationWindowEvent animationWindowEvent = CreateInstance(); - animationWindowEvent.hideFlags = HideFlags.HideInHierarchy; - animationWindowEvent.name = "Animation Event"; - - animationWindowEvent.root = null; - animationWindowEvent.clip = null; - animationWindowEvent.clipInfo = clipInfo; - animationWindowEvent.eventIndex = eventIndex; - - return animationWindowEvent; - } - - static private int InsertAnimationEvent(ref AnimationEvent[] events, AnimationClip clip, AnimationEvent evt) - { - Undo.RegisterCompleteObjectUndo(clip, "Add Event"); - - // Or add a new one - int insertIndex = events.Length; - for (int i = 0; i < events.Length; i++) - { - if (events[i].time > evt.time) - { - insertIndex = i; - break; - } - } - - ArrayUtility.Insert(ref events, insertIndex, evt); - AnimationUtility.SetAnimationEvents(clip, events); - - events = AnimationUtility.GetAnimationEvents(clip); - if (events[insertIndex].time != evt.time || events[insertIndex].functionName != evt.functionName) - Debug.LogError("Failed insertion"); - - return insertIndex; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowEventInspector.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowEventInspector.cs deleted file mode 100644 index b3bccc8a70..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowEventInspector.cs +++ /dev/null @@ -1,506 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [CustomEditor(typeof(AnimationWindowEvent))] - [CanEditMultipleObjects] - internal class AnimationWindowEventInspector : Editor - { - const string kNotSupportedPostFix = " (Function Not Supported)"; - const string kNoneSelected = "(No Function Selected)"; - - public override void OnInspectorGUI() - { - var awes = targets.Select(o => o as AnimationWindowEvent).ToArray(); - OnEditAnimationEvents(awes); - } - - protected override void OnHeaderGUI() - { - string targetTitle = (targets.Length == 1) ? "Animation Event" : targets.Length + " Animation Events"; - DrawHeaderGUI(this, targetTitle); - } - - public static void OnEditAnimationEvent(AnimationWindowEvent awe) - { - OnEditAnimationEvents(new AnimationWindowEvent[] {awe}); - } - - public static void OnEditAnimationEvents(AnimationWindowEvent[] awEvents) - { - AnimationWindowEventData data = GetData(awEvents); - if (data.events == null || data.selectedEvents == null || data.selectedEvents.Length == 0) - return; - - AnimationEvent firstEvent = data.selectedEvents[0]; - - bool singleFunctionName = Array.TrueForAll(data.selectedEvents, evt => evt.functionName == firstEvent.functionName); - - GUI.changed = false; - - if (data.root != null) - { - List methods = CollectSupportedMethods(data.root); - - var methodsFormatted = new List(methods.Count); - - for (int i = 0; i < methods.Count; ++i) - { - AnimationWindowEventMethod method = methods[i]; - - string postFix = " ( )"; - if (method.parameterType != null) - { - if (method.parameterType == typeof(float)) - postFix = " ( float )"; - else if (method.parameterType == typeof(int)) - postFix = " ( int )"; - else - postFix = string.Format(" ( {0} )", method.parameterType.Name); - } - - methodsFormatted.Add(method.name + postFix); - } - - int notSupportedIndex = methods.Count; - int selected = methods.FindIndex(method => method.name == firstEvent.functionName); - if (selected == -1) - { - selected = methods.Count; - - AnimationWindowEventMethod newMethod = new AnimationWindowEventMethod(); - newMethod.name = firstEvent.functionName; - newMethod.parameterType = null; - - methods.Add(newMethod); - - if (string.IsNullOrEmpty(firstEvent.functionName)) - methodsFormatted.Add(kNoneSelected); - else - methodsFormatted.Add(firstEvent.functionName + kNotSupportedPostFix); - } - - EditorGUIUtility.labelWidth = 130; - - EditorGUI.showMixedValue = !singleFunctionName; - int wasSelected = singleFunctionName ? selected : -1; - selected = EditorGUILayout.Popup("Function: ", selected, methodsFormatted.ToArray()); - if (wasSelected != selected && selected != -1 && selected != notSupportedIndex) - { - foreach (var evt in data.selectedEvents) - { - evt.functionName = methods[selected].name; - evt.stringParameter = string.Empty; - } - } - EditorGUI.showMixedValue = false; - - var selectedParameter = methods[selected].parameterType; - - if (singleFunctionName && selectedParameter != null) - { - EditorGUILayout.Space(); - if (selectedParameter == typeof(AnimationEvent)) - EditorGUILayout.PrefixLabel("Event Data"); - else - EditorGUILayout.PrefixLabel("Parameters"); - - DoEditRegularParameters(data.selectedEvents, selectedParameter); - } - } - else - { - EditorGUI.showMixedValue = !singleFunctionName; - string oldFunctionName = singleFunctionName ? firstEvent.functionName : ""; - string functionName = EditorGUILayout.TextField(EditorGUIUtility.TrTextContent("Function"), oldFunctionName); - if (functionName != oldFunctionName) - { - foreach (var evt in data.selectedEvents) - { - evt.functionName = functionName; - evt.stringParameter = string.Empty; - } - } - EditorGUI.showMixedValue = false; - - if (singleFunctionName) - { - DoEditRegularParameters(data.selectedEvents, typeof(AnimationEvent)); - } - else - { - using (new EditorGUI.DisabledScope(true)) - { - AnimationEvent dummyEvent = new AnimationEvent(); - DoEditRegularParameters(new AnimationEvent[] {dummyEvent}, typeof(AnimationEvent)); - } - } - } - - if (GUI.changed) - SetData(awEvents, data); - } - - public static void OnDisabledAnimationEvent() - { - AnimationEvent dummyEvent = new AnimationEvent(); - - using (new EditorGUI.DisabledScope(true)) - { - dummyEvent.functionName = EditorGUILayout.TextField(EditorGUIUtility.TrTextContent("Function"), dummyEvent.functionName); - DoEditRegularParameters(new AnimationEvent[] {dummyEvent}, typeof(AnimationEvent)); - } - } - - public static List CollectSupportedMethods(GameObject gameObject) - { - List supportedMethods = new List(); - - if (gameObject == null) - return supportedMethods; - - MonoBehaviour[] behaviours = gameObject.GetComponents(); - HashSet ambiguousMethods = new HashSet(); - - foreach (MonoBehaviour behaviour in behaviours) - { - if (behaviour == null) - continue; - - Type type = behaviour.GetType(); - while (type != typeof(MonoBehaviour) && type != null) - { - MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - for (int i = 0; i < methods.Length; i++) - { - MethodInfo method = methods[i]; - string name = method.Name; - - if (!IsSupportedMethodName(name)) - continue; - - ParameterInfo[] parameters = method.GetParameters(); - if (parameters.Length > 1) - continue; - - Type parameterType = null; - - if (parameters.Length == 1) - { - parameterType = parameters[0].ParameterType; - if (!(parameterType == typeof(string) || - parameterType == typeof(float) || - parameterType == typeof(int) || - parameterType == typeof(AnimationEvent) || - parameterType == typeof(UnityEngine.Object) || - parameterType.IsSubclassOf(typeof(UnityEngine.Object)) || - parameterType.IsEnum)) - continue; - } - - AnimationWindowEventMethod newMethod = new AnimationWindowEventMethod(); - newMethod.name = method.Name; - newMethod.parameterType = parameterType; - - int existingMethodIndex = supportedMethods.FindIndex(m => m.name == name); - if (existingMethodIndex != -1) - { - // The method is only ambiguous if it has a different signature to the one we saw before - if (supportedMethods[existingMethodIndex].parameterType != parameterType) - ambiguousMethods.Add(name); - } - - supportedMethods.Add(newMethod); - } - type = type.BaseType; - } - } - - // Since AnimationEvents only stores method name, it can't handle functions with multiple overloads - // So we remove all the ambiguous methods (overloads) from the list - foreach (string ambiguousMethod in ambiguousMethods) - { - for (int i = supportedMethods.Count - 1; i >= 0; --i) - { - if (supportedMethods[i].name.Equals(ambiguousMethod)) - supportedMethods.RemoveAt(i); - } - } - - return supportedMethods; - } - - public static string FormatEvent(GameObject root, AnimationEvent evt) - { - if (string.IsNullOrEmpty(evt.functionName)) - return kNoneSelected; - - if (!IsSupportedMethodName(evt.functionName)) - return evt.functionName + kNotSupportedPostFix; - - if (root == null) - return evt.functionName + kNotSupportedPostFix; - - foreach (var behaviour in root.GetComponents()) - { - if (behaviour == null) continue; - - var type = behaviour.GetType(); - if (type == typeof(MonoBehaviour) || - (type.BaseType != null && type.BaseType.Name == "GraphBehaviour")) - continue; - - MethodInfo method = null; - try - { - method = type.GetMethod(evt.functionName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - } - catch (AmbiguousMatchException) - { - } - - if (method == null) - continue; - - var parameterTypes = method.GetParameters().Select(p => p.ParameterType); - return evt.functionName + FormatEventArguments(parameterTypes, evt); - } - - return evt.functionName + kNotSupportedPostFix; - } - - private static void DoEditRegularParameters(AnimationEvent[] events, Type selectedParameter) - { - AnimationEvent firstEvent = events[0]; - - if (selectedParameter == typeof(AnimationEvent) || selectedParameter == typeof(float)) - { - bool singleParamValue = Array.TrueForAll(events, evt => evt.floatParameter == firstEvent.floatParameter); - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = !singleParamValue; - float newValue = EditorGUILayout.FloatField("Float", firstEvent.floatParameter); - EditorGUI.showMixedValue = false; - - if (EditorGUI.EndChangeCheck()) - { - foreach (var evt in events) - evt.floatParameter = newValue; - } - } - - if (selectedParameter == typeof(AnimationEvent) || selectedParameter == typeof(int) || selectedParameter.IsEnum) - { - bool singleParamValue = Array.TrueForAll(events, evt => evt.intParameter == firstEvent.intParameter); - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = !singleParamValue; - int newValue = 0; - if (selectedParameter.IsEnum) - newValue = EnumPopup("Enum", selectedParameter, firstEvent.intParameter); - else - newValue = EditorGUILayout.IntField("Int", firstEvent.intParameter); - EditorGUI.showMixedValue = false; - - if (EditorGUI.EndChangeCheck()) - { - foreach (var evt in events) - evt.intParameter = newValue; - } - } - - if (selectedParameter == typeof(AnimationEvent) || selectedParameter == typeof(string)) - { - bool singleParamValue = Array.TrueForAll(events, evt => evt.stringParameter == firstEvent.stringParameter); - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = !singleParamValue; - string newValue = EditorGUILayout.TextField("String", firstEvent.stringParameter); - EditorGUI.showMixedValue = false; - - if (EditorGUI.EndChangeCheck()) - { - foreach (var evt in events) - evt.stringParameter = newValue; - } - } - - if (selectedParameter == typeof(AnimationEvent) || selectedParameter.IsSubclassOf(typeof(UnityEngine.Object)) || selectedParameter == typeof(UnityEngine.Object)) - { - bool singleParamValue = Array.TrueForAll(events, evt => evt.objectReferenceParameter == firstEvent.objectReferenceParameter); - - EditorGUI.BeginChangeCheck(); - Type type = typeof(UnityEngine.Object); - if (selectedParameter != typeof(AnimationEvent)) - type = selectedParameter; - - EditorGUI.showMixedValue = !singleParamValue; - bool allowSceneObjects = false; - Object newValue = EditorGUILayout.ObjectField(ObjectNames.NicifyVariableName(type.Name), firstEvent.objectReferenceParameter, type, allowSceneObjects); - EditorGUI.showMixedValue = false; - - if (EditorGUI.EndChangeCheck()) - { - foreach (var evt in events) - evt.objectReferenceParameter = newValue; - } - } - } - - private static int EnumPopup(string label, Type enumType, int selected) - { - if (!enumType.IsEnum) - throw new Exception("parameter _enum must be of type System.Enum"); - - string[] enumStrings = System.Enum.GetNames(enumType); - int i = System.Array.IndexOf(enumStrings, Enum.GetName(enumType, selected)); - - i = EditorGUILayout.Popup(label, i, enumStrings, EditorStyles.popup); - - if (i == -1) - return selected; - else - { - System.Enum res = (System.Enum)Enum.Parse(enumType, enumStrings[i]); - return Convert.ToInt32(res); - } - } - - private static bool IsSupportedMethodName(string name) - { - if (name == "Main" || name == "Start" || name == "Awake" || name == "Update") - return false; - - return true; - } - - private static string FormatEventArguments(IEnumerable paramTypes, AnimationEvent evt) - { - if (!paramTypes.Any()) - return " ( )"; - - if (paramTypes.Count() > 1) - return kNotSupportedPostFix; - - var paramType = paramTypes.First(); - - if (paramType == typeof(string)) - return " ( \"" + evt.stringParameter + "\" )"; - - if (paramType == typeof(float)) - return " ( " + evt.floatParameter + " )"; - - if (paramType == typeof(int)) - return " ( " + evt.intParameter + " )"; - - if (paramType.IsEnum) - return " ( " + paramType.Name + "." + Enum.GetName(paramType, evt.intParameter) + " )"; - - if (paramType == typeof(AnimationEvent)) - return " ( " - + evt.floatParameter + " / " - + evt.intParameter + " / \"" - + evt.stringParameter + "\" / " - + (evt.objectReferenceParameter == null ? "null" : evt.objectReferenceParameter.name) + " )"; - - if (paramType.IsSubclassOf(typeof(UnityEngine.Object)) || paramType == typeof(UnityEngine.Object)) - return " ( " + (evt.objectReferenceParameter == null ? "null" : evt.objectReferenceParameter.name) + " )"; - - return kNotSupportedPostFix; - } - - private struct AnimationWindowEventData - { - public GameObject root; - public AnimationClip clip; - public AnimationClipInfoProperties clipInfo; - - public AnimationEvent[] events; - public AnimationEvent[] selectedEvents; - } - - private static AnimationWindowEventData GetData(AnimationWindowEvent[] awEvents) - { - var data = new AnimationWindowEventData(); - if (awEvents.Length == 0) - return data; - - AnimationWindowEvent firstAwEvent = awEvents[0]; - data.root = firstAwEvent.root; - data.clip = firstAwEvent.clip; - data.clipInfo = firstAwEvent.clipInfo; - - if (data.clip != null) - data.events = AnimationUtility.GetAnimationEvents(data.clip); - else if (data.clipInfo != null) - data.events = data.clipInfo.GetEvents(); - - if (data.events != null) - { - List selectedEvents = new List(); - foreach (var awEvent in awEvents) - { - if (awEvent.eventIndex >= 0 && awEvent.eventIndex < data.events.Length) - selectedEvents.Add(data.events[awEvent.eventIndex]); - } - - data.selectedEvents = selectedEvents.ToArray(); - } - - return data; - } - - private static void SetData(AnimationWindowEvent[] awEvents, AnimationWindowEventData data) - { - if (data.events == null) - return; - - if (data.clip != null) - { - Undo.RegisterCompleteObjectUndo(data.clip, "Animation Event Change"); - AnimationUtility.SetAnimationEvents(data.clip, data.events); - } - else if (data.clipInfo != null) - { - foreach (var awEvent in awEvents) - { - if (awEvent.eventIndex >= 0 && awEvent.eventIndex < data.events.Length) - data.clipInfo.SetEvent(awEvent.eventIndex, data.events[awEvent.eventIndex]); - } - } - } - - [MenuItem("CONTEXT/AnimationWindowEvent/Reset")] - static void ResetValues(MenuCommand command) - { - AnimationWindowEvent awEvent = command.context as AnimationWindowEvent; - AnimationWindowEvent[] awEvents = new AnimationWindowEvent[] {awEvent}; - - AnimationWindowEventData data = GetData(awEvents); - if (data.events == null || data.selectedEvents == null || data.selectedEvents.Length == 0) - return; - - foreach (var evt in data.selectedEvents) - { - evt.functionName = ""; - evt.stringParameter = string.Empty; - evt.floatParameter = 0f; - evt.intParameter = 0; - evt.objectReferenceParameter = null; - } - - SetData(awEvents, data); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchy.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchy.cs deleted file mode 100644 index ccfd4088f9..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchy.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using UnityEditor.IMGUI.Controls; - -namespace UnityEditorInternal -{ - [System.Serializable] - internal class AnimationWindowHierarchyState : TreeViewState - { - private List m_TallInstanceIDs = new List(); - - public bool GetTallMode(AnimationWindowHierarchyNode node) - { - return m_TallInstanceIDs.Contains(node.id); - } - - public void SetTallMode(AnimationWindowHierarchyNode node, bool tallMode) - { - if (tallMode) - m_TallInstanceIDs.Add(node.id); - else - m_TallInstanceIDs.Remove(node.id); - } - - public int GetTallInstancesCount() - { - return m_TallInstanceIDs.Count; - } - - public void AddTallInstance(int id) - { - if (!m_TallInstanceIDs.Contains(id)) - m_TallInstanceIDs.Add(id); - } - } - - internal class AnimationWindowHierarchy - { - // Animation window shared state - private AnimationWindowState m_State; - private TreeViewController m_TreeView; - - public Vector2 GetContentSize() - { - return m_TreeView.GetContentSize(); - } - - public Rect GetTotalRect() - { - return m_TreeView.GetTotalRect(); - } - - public AnimationWindowHierarchy(AnimationWindowState state, EditorWindow owner, Rect position) - { - m_State = state; - Init(owner, position); - } - - public void OnGUI(Rect position) - { - m_TreeView.OnEvent(); - m_TreeView.OnGUI(position, GUIUtility.GetControlID(FocusType.Keyboard)); - } - - public void Init(EditorWindow owner, Rect rect) - { - if (m_State.hierarchyState == null) - m_State.hierarchyState = new AnimationWindowHierarchyState(); - - m_TreeView = new TreeViewController(owner, m_State.hierarchyState); - m_State.hierarchyData = new AnimationWindowHierarchyDataSource(m_TreeView, m_State); - m_TreeView.Init(rect, - m_State.hierarchyData, - new AnimationWindowHierarchyGUI(m_TreeView, m_State), - null - ); - - m_TreeView.deselectOnUnhandledMouseDown = true; - m_TreeView.selectionChangedCallback += m_State.OnHierarchySelectionChanged; - - m_TreeView.ReloadData(); - } - - virtual internal bool IsRenamingNodeAllowed(TreeViewItem node) { return true; } - - public bool IsIDVisible(int id) - { - if (m_TreeView == null) - return false; - - var rows = m_TreeView.data.GetRows(); - return TreeViewController.GetIndexOfID(rows, id) >= 0; - } - - public void EndNameEditing(bool acceptChanges) - { - m_TreeView.EndNameEditing(acceptChanges); - } - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyDataSource.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyDataSource.cs deleted file mode 100644 index 2dd490c0bf..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyDataSource.cs +++ /dev/null @@ -1,163 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using System.Collections.Generic; -using UnityEditor.IMGUI.Controls; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal class AnimationWindowHierarchyDataSource : TreeViewDataSource - { - // Animation window shared state - private AnimationWindowState state { get; set; } - public bool showAll { get; set; } - - public AnimationWindowHierarchyDataSource(TreeViewController treeView, AnimationWindowState animationWindowState) - : base(treeView) - { - state = animationWindowState; - } - - private void SetupRootNodeSettings() - { - showRootItem = false; - rootIsCollapsable = false; - SetExpanded(m_RootItem, true); - } - - private AnimationWindowHierarchyNode GetEmptyRootNode() - { - return new AnimationWindowHierarchyNode(0, -1, null, null, "", "", "root"); - } - - public override void FetchData() - { - m_RootItem = GetEmptyRootNode(); - SetupRootNodeSettings(); - m_NeedRefreshRows = true; - - if (state.selection.disabled) - { - root.children = null; - return; - } - - List childNodes = new List(); - - if (state.allCurves.Count > 0) - { - AnimationWindowHierarchyMasterNode masterNode = new AnimationWindowHierarchyMasterNode(); - masterNode.curves = state.allCurves.ToArray(); - - childNodes.Add(masterNode); - } - - childNodes.AddRange(CreateTreeFromCurves()); - childNodes.Add(new AnimationWindowHierarchyAddButtonNode()); - - TreeViewUtility.SetChildParentReferences(new List(childNodes.ToArray()), root); - } - - public override bool IsRenamingItemAllowed(TreeViewItem item) - { - if (item is AnimationWindowHierarchyAddButtonNode || item is AnimationWindowHierarchyMasterNode || item is AnimationWindowHierarchyClipNode) - return false; - - if ((item as AnimationWindowHierarchyNode).path.Length == 0) - return false; - - return true; - } - - public List CreateTreeFromCurves() - { - List nodes = new List(); - List singlePropertyCurves = new List(); - - AnimationWindowCurve[] curves = state.allCurves.ToArray(); - AnimationWindowHierarchyNode parentNode = (AnimationWindowHierarchyNode)m_RootItem; - - for (int i = 0; i < curves.Length; i++) - { - AnimationWindowCurve curve = curves[i]; - AnimationWindowCurve nextCurve = i < curves.Length - 1 ? curves[i + 1] : null; - - singlePropertyCurves.Add(curve); - - bool areSameGroup = nextCurve != null && AnimationWindowUtility.GetPropertyGroupName(nextCurve.propertyName) == AnimationWindowUtility.GetPropertyGroupName(curve.propertyName); - bool areSamePathAndType = nextCurve != null && curve.path.Equals(nextCurve.path) && curve.type == nextCurve.type; - - // We expect curveBindings to come sorted by propertyname - // 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. - if (i == curves.Length - 1 || !areSameGroup || !areSamePathAndType) - { - if (singlePropertyCurves.Count > 1) - nodes.Add(AddPropertyGroupToHierarchy(singlePropertyCurves.ToArray(), parentNode)); - else - nodes.Add(AddPropertyToHierarchy(singlePropertyCurves[0], parentNode)); - singlePropertyCurves.Clear(); - } - } - - return nodes; - } - - private AnimationWindowHierarchyPropertyGroupNode AddPropertyGroupToHierarchy(AnimationWindowCurve[] curves, AnimationWindowHierarchyNode parentNode) - { - List childNodes = new List(); - - System.Type animatableObjectType = curves[0].type; - AnimationWindowHierarchyPropertyGroupNode node = new AnimationWindowHierarchyPropertyGroupNode(animatableObjectType, 0, AnimationWindowUtility.GetPropertyGroupName(curves[0].propertyName), curves[0].path, parentNode); - - node.icon = GetIcon(curves[0].binding); - - node.indent = curves[0].depth; - node.curves = curves; - - foreach (AnimationWindowCurve curve in curves) - { - AnimationWindowHierarchyPropertyNode childNode = AddPropertyToHierarchy(curve, node); - // For child nodes we do not want to display the type in front (It is already shown by the group node) - childNode.displayName = AnimationWindowUtility.GetPropertyDisplayName(childNode.propertyName); - childNodes.Add(childNode); - } - - TreeViewUtility.SetChildParentReferences(new List(childNodes.ToArray()), node); - return node; - } - - private AnimationWindowHierarchyPropertyNode AddPropertyToHierarchy(AnimationWindowCurve curve, AnimationWindowHierarchyNode parentNode) - { - AnimationWindowHierarchyPropertyNode node = new AnimationWindowHierarchyPropertyNode(curve.type, 0, curve.propertyName, curve.path, parentNode, curve.binding, curve.isPPtrCurve); - - if (parentNode.icon != null) - node.icon = parentNode.icon; - else - node.icon = GetIcon(curve.binding); - - node.indent = curve.depth; - node.curves = new[] { curve }; - return node; - } - - public Texture2D GetIcon(EditorCurveBinding curveBinding) - { - if (state.activeRootGameObject != null) - { - Object animatedObject = AnimationUtility.GetAnimatedObject(state.activeRootGameObject, curveBinding); - if (animatedObject != null) - return AssetPreview.GetMiniThumbnail(animatedObject); - } - return AssetPreview.GetMiniTypeThumbnail(curveBinding.type); - } - - public void UpdateData() - { - m_TreeView.ReloadData(); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs deleted file mode 100644 index bd2c74c32b..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs +++ /dev/null @@ -1,894 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.IMGUI.Controls; - -namespace UnityEditorInternal -{ - internal class AnimationWindowHierarchyGUI : TreeViewGUI - { - public AnimationWindowState state { get; set; } - - readonly GUIContent k_AnimatePropertyLabel = EditorGUIUtility.TrTextContent("Add Property"); - - private GUIStyle m_AnimationRowEvenStyle; - private GUIStyle m_AnimationRowOddStyle; - private GUIStyle m_AnimationSelectionTextField; - private GUIStyle m_AnimationLineStyle; - private GUIStyle m_AnimationCurveDropdown; - private AnimationWindowHierarchyNode m_RenamedNode; - private Color m_LightSkinPropertyTextColor = new Color(.35f, .35f, .35f); - private Color m_PhantomCurveColor = new Color(0f, 153f / 255f, 153f / 255f); - - private int[] m_HierarchyItemFoldControlIDs; - private int[] m_HierarchyItemValueControlIDs; - private int[] m_HierarchyItemButtonControlIDs; - - private const float k_RowRightOffset = 10; - private const float k_ValueFieldDragWidth = 15; - private const float k_ValueFieldWidth = 50; - private const float k_ValueFieldOffsetFromRightSide = 75; - private const float k_ColorIndicatorTopMargin = 3; - public const float k_DopeSheetRowHeight = EditorGUI.kSingleLineHeight; - public const float k_DopeSheetRowHeightTall = k_DopeSheetRowHeight * 2f; - public const float k_AddCurveButtonNodeHeight = 40f; - public const float k_RowBackgroundColorBrightness = 0.28f; - private const float k_SelectedPhantomCurveColorMultiplier = 1.4f; - - private readonly static Color k_KeyColorInDopesheetMode = new Color(0.7f, 0.7f, 0.7f, 1); - private readonly static Color k_KeyColorForNonCurves = new Color(0.7f, 0.7f, 0.7f, 0.5f); - private readonly static Color k_LeftoverCurveColor = Color.yellow; - - internal static int s_WasInsideValueRectFrame = -1; - - public AnimationWindowHierarchyGUI(TreeViewController treeView, AnimationWindowState state) - : base(treeView) - { - this.state = state; - InitStyles(); - } - - protected void InitStyles() - { - if (m_AnimationRowEvenStyle == null) - m_AnimationRowEvenStyle = new GUIStyle("AnimationRowEven"); - if (m_AnimationRowOddStyle == null) - m_AnimationRowOddStyle = new GUIStyle("AnimationRowOdd"); - if (m_AnimationSelectionTextField == null) - m_AnimationSelectionTextField = new GUIStyle("AnimationSelectionTextField"); - if (m_AnimationLineStyle == null) - { - m_AnimationLineStyle = new GUIStyle(Styles.lineStyle); - m_AnimationLineStyle.padding.left = 0; - } - if (m_AnimationCurveDropdown == null) - m_AnimationCurveDropdown = new GUIStyle("AnimPropDropdown"); - } - - protected void DoNodeGUI(Rect rect, AnimationWindowHierarchyNode node, bool selected, bool focused, int row) - { - InitStyles(); - - if (node is AnimationWindowHierarchyMasterNode) - return; - - float indent = k_BaseIndent + (node.depth + node.indent) * k_IndentWidth; - - if (node is AnimationWindowHierarchyAddButtonNode) - { - if (Event.current.type == EventType.MouseMove && s_WasInsideValueRectFrame >= 0) - { - if (s_WasInsideValueRectFrame >= Time.frameCount - 1) - Event.current.Use(); - else - s_WasInsideValueRectFrame = -1; - } - - using (new EditorGUI.DisabledScope(!state.selection.canAddCurves)) - { - DoAddCurveButton(rect, node, row); - } - } - else - { - DoRowBackground(rect, row); - DoIconAndName(rect, node, selected, focused, indent); - DoFoldout(node, rect, indent, row); - - bool enabled = false; - if (node.curves != null) - { - enabled = !Array.Exists(node.curves, curve => curve.animationIsEditable == false); - } - - using (new EditorGUI.DisabledScope(!enabled)) - { - DoValueField(rect, node, row); - } - DoCurveDropdown(rect, node, row, enabled); - HandleContextMenu(rect, node, enabled); - DoCurveColorIndicator(rect, node); - } - EditorGUIUtility.SetIconSize(Vector2.zero); - } - - public override void BeginRowGUI() - { - base.BeginRowGUI(); - HandleDelete(); - - // Reserve unique control ids. - // This is required to avoid changing control ids mapping as we scroll in the tree view - // and change items visibility. Hopefully, we should be able to remove it entirely if we - // isolate the animation window layouts in separate IMGUIContainers... - int rowCount = m_TreeView.data.rowCount; - m_HierarchyItemFoldControlIDs = new int[rowCount]; - m_HierarchyItemValueControlIDs = new int[rowCount]; - m_HierarchyItemButtonControlIDs = new int[rowCount]; - for (int i = 0; i < rowCount; ++i) - { - var propertyNode = m_TreeView.data.GetItem(i) as AnimationWindowHierarchyPropertyNode; - if (propertyNode != null && !propertyNode.isPptrNode) - m_HierarchyItemValueControlIDs[i] = GUIUtility.GetControlID(FocusType.Keyboard); - else - m_HierarchyItemValueControlIDs[i] = 0; // not needed. - - m_HierarchyItemFoldControlIDs[i] = GUIUtility.GetControlID(FocusType.Passive); - m_HierarchyItemButtonControlIDs[i] = GUIUtility.GetControlID(FocusType.Passive); - } - } - - private void DoAddCurveButton(Rect rect, AnimationWindowHierarchyNode node, int row) - { - const int k_ButtonWidth = 230; - float xMargin = (rect.width - k_ButtonWidth) / 2f; - float yMargin = 10f; - - Rect rectWithMargin = new Rect(rect.xMin + xMargin, rect.yMin + yMargin, rect.width - xMargin * 2f, rect.height - yMargin * 2f); - - // case 767863. - // This control id is unique to the hierarchy node it refers to. - // The tree view only renders the elements that are visible, and will cause - // the control id counter to shift when scrolling through the view. - if (DoTreeViewButton(m_HierarchyItemButtonControlIDs[row], rectWithMargin, k_AnimatePropertyLabel, GUI.skin.button)) - { - AddCurvesPopupHierarchyDataSource.showEntireHierarchy = true; - - if (AddCurvesPopup.ShowAtPosition(rectWithMargin, state, OnNewCurveAdded)) - { - GUIUtility.ExitGUI(); - } - } - } - - private void OnNewCurveAdded(AddCurvesPopupPropertyNode node) - { - } - - private void DoRowBackground(Rect rect, int row) - { - if (Event.current.type != EventType.Repaint) - return; - - // Different background for even rows - if (row % 2 == 0) - m_AnimationRowEvenStyle.Draw(rect, false, false, false, false); - else - m_AnimationRowOddStyle.Draw(rect, false, false, false, false); - } - - // Draw foldout (after text content above to ensure drop down icon is rendered above selection highlight) - private void DoFoldout(AnimationWindowHierarchyNode node, Rect rect, float indent, int row) - { - if (m_TreeView.data.IsExpandable(node)) - { - Rect toggleRect = rect; - toggleRect.x = indent; - toggleRect.width = Styles.foldoutWidth; - EditorGUI.BeginChangeCheck(); - bool newExpandedValue = GUI.Toggle(toggleRect, m_HierarchyItemFoldControlIDs[row], m_TreeView.data.IsExpanded(node), GUIContent.none, Styles.foldout); - if (EditorGUI.EndChangeCheck()) - { - if (Event.current.alt) - m_TreeView.data.SetExpandedWithChildren(node, newExpandedValue); - else - m_TreeView.data.SetExpanded(node, newExpandedValue); - } - } - else - { - AnimationWindowHierarchyPropertyNode hierarchyPropertyNode = node as AnimationWindowHierarchyPropertyNode; - AnimationWindowHierarchyState hierarchyState = m_TreeView.state as AnimationWindowHierarchyState; - - if (hierarchyPropertyNode != null && hierarchyPropertyNode.isPptrNode) - { - Rect toggleRect = rect; - toggleRect.x = indent; - toggleRect.width = Styles.foldoutWidth; - - EditorGUI.BeginChangeCheck(); - bool tallMode = hierarchyState.GetTallMode(hierarchyPropertyNode); - tallMode = GUI.Toggle(toggleRect, m_HierarchyItemFoldControlIDs[row], tallMode, GUIContent.none, Styles.foldout); - if (EditorGUI.EndChangeCheck()) - hierarchyState.SetTallMode(hierarchyPropertyNode, tallMode); - } - } - } - - private void DoIconAndName(Rect rect, AnimationWindowHierarchyNode node, bool selected, bool focused, float indent) - { - EditorGUIUtility.SetIconSize(new Vector2(13, 13)); // If not set we see icons scaling down if text is being cropped - - // TODO: All this is horrible. SHAME FIX! - if (Event.current.type == EventType.Repaint) - { - if (selected) - Styles.selectionStyle.Draw(rect, false, false, true, focused); - - // Leave some space for the value field that comes after. - if (node is AnimationWindowHierarchyPropertyNode) - rect.width -= k_ValueFieldOffsetFromRightSide + 2; - - bool isLeftOverCurve = AnimationWindowUtility.IsNodeLeftOverCurve(node); - bool isAmbiguous = AnimationWindowUtility.IsNodeAmbiguous(node); - bool isPhantom = AnimationWindowUtility.IsNodePhantom(node); - - string warningText = ""; - string tooltipText = ""; - if (isPhantom) - { - warningText = " (Default Value)"; - tooltipText = "Transform position, rotation and scale can't be partially animated. This value will be animated to the default value"; - } - if (isLeftOverCurve) - { - warningText = " (Missing!)"; - tooltipText = "The GameObject or Component is missing (" + node.path + ")"; - } - if (isAmbiguous) - { - warningText = " (Duplicate GameObject name!)"; - tooltipText = "Target for curve is ambiguous since there are multiple GameObjects with same name (" + node.path + ")"; - } - - Color oldColor = m_AnimationLineStyle.normal.textColor; - Color textColor = oldColor; - if (node.depth == 0) - { - string nodePrefix = ""; - if (node.curves.Length > 0) - { - AnimationWindowSelectionItem selectionBinding = node.curves[0].selectionBinding; - if (selectionBinding != null) - { - if (selectionBinding.rootGameObject != null) - { - Transform transform = selectionBinding.rootGameObject.transform.Find(node.path); - if (transform == null) - isLeftOverCurve = true; - } - } - - string gameObjectName = GetGameObjectName(selectionBinding != null ? selectionBinding.rootGameObject : null, node.path); - nodePrefix = string.IsNullOrEmpty(gameObjectName) ? "" : gameObjectName + " : "; - } - - Styles.content = new GUIContent(nodePrefix + node.displayName + warningText, GetIconForItem(node), tooltipText); - - textColor = EditorGUIUtility.isProSkin ? Color.gray * 1.35f : Color.black; - } - else - { - Styles.content = new GUIContent(node.displayName + warningText, GetIconForItem(node), tooltipText); - - textColor = EditorGUIUtility.isProSkin ? Color.gray : m_LightSkinPropertyTextColor; - - var phantomColor = selected ? m_PhantomCurveColor * k_SelectedPhantomCurveColorMultiplier : m_PhantomCurveColor; - textColor = isPhantom ? phantomColor : textColor; - } - textColor = isLeftOverCurve || isAmbiguous ? k_LeftoverCurveColor : textColor; - SetStyleTextColor(m_AnimationLineStyle, textColor); - - rect.xMin += (int)(indent + Styles.foldoutWidth + m_AnimationLineStyle.margin.left); - GUI.Label(rect, Styles.content, m_AnimationLineStyle); - - SetStyleTextColor(m_AnimationLineStyle, oldColor); - } - - if (IsRenaming(node.id) && Event.current.type != EventType.Layout) - GetRenameOverlay().editFieldRect = new Rect(rect.x + k_IndentWidth, rect.y, rect.width - k_IndentWidth - 1, rect.height); - } - - private string GetGameObjectName(GameObject rootGameObject, string path) - { - if (string.IsNullOrEmpty(path)) - return rootGameObject != null ? rootGameObject.name : ""; - - string[] splits = path.Split('/'); - return splits[splits.Length - 1]; - } - - private string GetPathWithoutChildmostGameObject(string path) - { - if (string.IsNullOrEmpty(path)) - return ""; - - int lastIndex = path.LastIndexOf('/'); - return path.Substring(0, lastIndex + 1); - } - - private void DoValueField(Rect rect, AnimationWindowHierarchyNode node, int row) - { - bool curvesChanged = false; - - if (node is AnimationWindowHierarchyPropertyNode) - { - AnimationWindowCurve[] curves = node.curves; - if (curves == null || curves.Length == 0) - return; - - // We do valuefields for dopelines that only have single curve - AnimationWindowCurve curve = curves[0]; - object objectValue = CurveBindingUtility.GetCurrentValue(state, curve); - - if (objectValue is float) - { - float value = (float)objectValue; - - Rect valueFieldDragRect = new Rect(rect.xMax - k_ValueFieldOffsetFromRightSide - k_ValueFieldDragWidth, rect.y, k_ValueFieldDragWidth, rect.height); - Rect valueFieldRect = new Rect(rect.xMax - k_ValueFieldOffsetFromRightSide, rect.y, k_ValueFieldWidth, rect.height); - - if (Event.current.type == EventType.MouseMove && valueFieldRect.Contains(Event.current.mousePosition)) - s_WasInsideValueRectFrame = Time.frameCount; - - EditorGUI.BeginChangeCheck(); - - if (curve.valueType == typeof(bool)) - { - value = GUI.Toggle(valueFieldRect, m_HierarchyItemValueControlIDs[row], value != 0, GUIContent.none, EditorStyles.toggle) ? 1 : 0; - } - else - { - int id = m_HierarchyItemValueControlIDs[row]; - bool enterInTextField = (EditorGUIUtility.keyboardControl == id - && EditorGUIUtility.editingTextField - && Event.current.type == EventType.KeyDown - && (Event.current.character == '\n' || (int)Event.current.character == 3)); - - // Force back keyboard focus to float field editor when editing it. - // TreeView forces keyboard focus on itself at mouse down and we lose focus here. - if (EditorGUI.s_RecycledEditor.controlID == id && Event.current.type == EventType.MouseDown && valueFieldRect.Contains(Event.current.mousePosition)) - { - GUIUtility.keyboardControl = id; - } - - value = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, - valueFieldRect, - valueFieldDragRect, - id, - value, - EditorGUI.kFloatFieldFormatString, - m_AnimationSelectionTextField, - true); - if (enterInTextField) - { - GUI.changed = true; - Event.current.Use(); - } - } - - if (float.IsInfinity(value) || float.IsNaN(value)) - value = 0; - - if (EditorGUI.EndChangeCheck()) - { - string undoLabel = "Edit Key"; - - AnimationKeyTime newAnimationKeyTime = AnimationKeyTime.Time(state.currentTime, curve.clip.frameRate); - - AnimationWindowKeyframe existingKeyframe = null; - foreach (AnimationWindowKeyframe keyframe in curve.m_Keyframes) - { - if (Mathf.Approximately(keyframe.time, state.currentTime)) - existingKeyframe = keyframe; - } - - if (existingKeyframe == null) - AnimationWindowUtility.AddKeyframeToCurve(curve, value, curve.valueType, newAnimationKeyTime); - else - existingKeyframe.value = value; - - state.SaveCurve(curve, undoLabel); - curvesChanged = true; - } - } - } - - if (curvesChanged) - state.ResampleAnimation(); - } - - private bool DoTreeViewButton(int id, Rect position, GUIContent content, GUIStyle style) - { - Event evt = Event.current; - EventType type = evt.GetTypeForControl(id); - switch (type) - { - case EventType.Repaint: - style.Draw(position, content, id, false); - break; - case EventType.MouseDown: - if (position.Contains(evt.mousePosition) && evt.button == 0) - { - GUIUtility.hotControl = id; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - evt.Use(); - - if (position.Contains(evt.mousePosition)) - { - return true; - } - } - break; - } - return false; - } - - private void DoCurveDropdown(Rect rect, AnimationWindowHierarchyNode node, int row, bool enabled) - { - rect = new Rect( - rect.xMax - k_RowRightOffset - 12, - rect.yMin + 2, - 22, 12); - - // case 767863. - // This control id is unique to the hierarchy node it refers to. - // The tree view only renders the elements that are visible, and will cause - // the control id counter to shift when scrolling through the view. - if (DoTreeViewButton(m_HierarchyItemButtonControlIDs[row], rect, GUIContent.none, m_AnimationCurveDropdown)) - { - state.SelectHierarchyItem(node.id, false, false); - GenericMenu menu = GenerateMenu(new AnimationWindowHierarchyNode[] { node }.ToList(), enabled); - menu.DropDown(rect); - Event.current.Use(); - } - } - - private void DoCurveColorIndicator(Rect rect, AnimationWindowHierarchyNode node) - { - if (Event.current.type != EventType.Repaint) - return; - - Color originalColor = GUI.color; - - if (!state.showCurveEditor) - GUI.color = k_KeyColorInDopesheetMode; - else if (node.curves.Length == 1 && !node.curves[0].isPPtrCurve) - GUI.color = CurveUtility.GetPropertyColor(node.curves[0].binding.propertyName); - else - GUI.color = k_KeyColorForNonCurves; - - bool hasKey = false; - if (state.previewing) - { - foreach (var curve in node.curves) - { - if (curve.m_Keyframes.Any(key => state.time.ContainsTime(key.time))) - { - hasKey = true; - } - } - } - - Texture icon = hasKey ? CurveUtility.GetIconKey() : CurveUtility.GetIconCurve(); - rect = new Rect(rect.xMax - k_RowRightOffset - (icon.width / 2) - 5, rect.yMin + k_ColorIndicatorTopMargin, icon.width, icon.height); - GUI.DrawTexture(rect, icon, ScaleMode.ScaleToFit, true, 1); - - GUI.color = originalColor; - } - - private void HandleDelete() - { - if (m_TreeView.HasFocus()) - { - switch (Event.current.type) - { - case EventType.ExecuteCommand: - if ((Event.current.commandName == EventCommandNames.SoftDelete || Event.current.commandName == EventCommandNames.Delete)) - { - if (Event.current.type == EventType.ExecuteCommand) - RemoveCurvesFromSelectedNodes(); - Event.current.Use(); - } - break; - - case EventType.KeyDown: - if (Event.current.keyCode == KeyCode.Backspace || Event.current.keyCode == KeyCode.Delete) - { - RemoveCurvesFromSelectedNodes(); - Event.current.Use(); - } - break; - } - } - } - - private void HandleContextMenu(Rect rect, AnimationWindowHierarchyNode node, bool enabled) - { - if (Event.current.type != EventType.ContextClick) - return; - - if (rect.Contains(Event.current.mousePosition)) - { - state.SelectHierarchyItem(node.id, true, true); - //state.animationWindow.RefreshShownCurves (true); - GenerateMenu(state.selectedHierarchyNodes, enabled).ShowAsContext(); - Event.current.Use(); - } - } - - private GenericMenu GenerateMenu(List interactedNodes, bool enabled) - { - List curves = GetCurvesAffectedByNodes(interactedNodes, false); - // Linked curves are like regular affected curves but always include transform siblings - List linkedCurves = GetCurvesAffectedByNodes(interactedNodes, true); - - bool forceGroupRemove = curves.Count == 1 ? AnimationWindowUtility.ForceGrouping(curves[0].binding) : false; - - GenericMenu menu = new GenericMenu(); - - // Remove curves - GUIContent removePropertyContent = new GUIContent(curves.Count > 1 || forceGroupRemove ? "Remove Properties" : "Remove Property"); - if (!enabled) - menu.AddDisabledItem(removePropertyContent); - else - menu.AddItem(removePropertyContent, false, RemoveCurvesFromSelectedNodes); - - // Change rotation interpolation - bool showInterpolation = true; - EditorCurveBinding[] curveBindings = new EditorCurveBinding[linkedCurves.Count]; - for (int i = 0; i < linkedCurves.Count; i++) - curveBindings[i] = linkedCurves[i].binding; - RotationCurveInterpolation.Mode rotationInterpolation = GetRotationInterpolationMode(curveBindings); - if (rotationInterpolation == RotationCurveInterpolation.Mode.Undefined) - { - showInterpolation = false; - } - else - { - foreach (var node in interactedNodes) - { - if (!(node is AnimationWindowHierarchyPropertyGroupNode)) - showInterpolation = false; - } - } - if (showInterpolation) - { - string legacyWarning = state.activeAnimationClip.legacy ? " (Not fully supported in Legacy)" : ""; - GenericMenu.MenuFunction2 nullMenuFunction2 = null; - menu.AddItem(EditorGUIUtility.TrTextContent("Interpolation/Euler Angles" + legacyWarning), rotationInterpolation == RotationCurveInterpolation.Mode.RawEuler, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.RawEuler); - menu.AddItem(EditorGUIUtility.TrTextContent("Interpolation/Euler Angles (Quaternion)"), rotationInterpolation == RotationCurveInterpolation.Mode.Baked, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.Baked); - menu.AddItem(EditorGUIUtility.TrTextContent("Interpolation/Quaternion"), rotationInterpolation == RotationCurveInterpolation.Mode.NonBaked, enabled ? ChangeRotationInterpolation : nullMenuFunction2, RotationCurveInterpolation.Mode.NonBaked); - } - - // Menu items that are only applicaple when in animation mode: - if (state.previewing) - { - menu.AddSeparator(""); - - bool allHaveKeys = true; - bool noneHaveKeys = true; - foreach (AnimationWindowCurve curve in curves) - { - bool curveHasKey = curve.HasKeyframe(state.time); - if (!curveHasKey) - allHaveKeys = false; - else - noneHaveKeys = false; - } - - string str; - - str = "Add Key"; - if (allHaveKeys || !enabled) - menu.AddDisabledItem(new GUIContent(str)); - else - menu.AddItem(new GUIContent(str), false, AddKeysAtCurrentTime, curves); - - str = "Delete Key"; - if (noneHaveKeys || !enabled) - menu.AddDisabledItem(new GUIContent(str)); - else - menu.AddItem(new GUIContent(str), false, DeleteKeysAtCurrentTime, curves); - } - - return menu; - } - - private void AddKeysAtCurrentTime(object obj) { AddKeysAtCurrentTime((List)obj); } - private void AddKeysAtCurrentTime(List curves) - { - AnimationWindowUtility.AddKeyframes(state, curves.ToArray(), state.time); - } - - private void DeleteKeysAtCurrentTime(object obj) { DeleteKeysAtCurrentTime((List)obj); } - private void DeleteKeysAtCurrentTime(List curves) - { - AnimationWindowUtility.RemoveKeyframes(state, curves.ToArray(), state.time); - } - - private void ChangeRotationInterpolation(System.Object interpolationMode) - { - RotationCurveInterpolation.Mode mode = (RotationCurveInterpolation.Mode)interpolationMode; - - AnimationWindowCurve[] activeCurves = state.activeCurves.ToArray(); - EditorCurveBinding[] curveBindings = new EditorCurveBinding[activeCurves.Length]; - - for (int i = 0; i < activeCurves.Length; i++) - { - curveBindings[i] = activeCurves[i].binding; - } - - RotationCurveInterpolation.SetInterpolation(state.activeAnimationClip, curveBindings, mode); - MaintainTreeviewStateAfterRotationInterpolation(mode); - state.hierarchyData.ReloadData(); - } - - private void RemoveCurvesFromSelectedNodes() - { - RemoveCurvesFromNodes(state.selectedHierarchyNodes); - } - - private void RemoveCurvesFromNodes(List nodes) - { - string undoLabel = "Remove Curve"; - state.SaveKeySelection(undoLabel); - - foreach (var node in nodes) - { - AnimationWindowHierarchyNode hierarchyNode = (AnimationWindowHierarchyNode)node; - - if (hierarchyNode.parent is AnimationWindowHierarchyPropertyGroupNode && hierarchyNode.binding != null && AnimationWindowUtility.ForceGrouping((EditorCurveBinding)hierarchyNode.binding)) - hierarchyNode = (AnimationWindowHierarchyNode)hierarchyNode.parent; - - if (hierarchyNode.curves == null) - continue; - - List curves = null; - - // Property or propertygroup - if (hierarchyNode is AnimationWindowHierarchyPropertyGroupNode || hierarchyNode is AnimationWindowHierarchyPropertyNode) - curves = AnimationWindowUtility.FilterCurves(hierarchyNode.curves.ToArray(), hierarchyNode.path, hierarchyNode.animatableObjectType, hierarchyNode.propertyName); - else - curves = AnimationWindowUtility.FilterCurves(hierarchyNode.curves.ToArray(), hierarchyNode.path, hierarchyNode.animatableObjectType); - - foreach (AnimationWindowCurve animationWindowCurve in curves) - state.RemoveCurve(animationWindowCurve, undoLabel); - } - - m_TreeView.ReloadData(); - - state.controlInterface.ResampleAnimation(); - } - - private List GetCurvesAffectedByNodes(List nodes, bool includeLinkedCurves) - { - List curves = new List(); - foreach (var node in nodes) - { - AnimationWindowHierarchyNode hierarchyNode = node; - - if (hierarchyNode.parent is AnimationWindowHierarchyPropertyGroupNode && includeLinkedCurves) - hierarchyNode = (AnimationWindowHierarchyNode)hierarchyNode.parent; - - if (hierarchyNode.curves == null) - continue; - - if (hierarchyNode.curves.Length > 0) - { - // Property or propertygroup - if (hierarchyNode is AnimationWindowHierarchyPropertyGroupNode || hierarchyNode is AnimationWindowHierarchyPropertyNode) - curves.AddRange(AnimationWindowUtility.FilterCurves(hierarchyNode.curves, hierarchyNode.path, hierarchyNode.animatableObjectType, hierarchyNode.propertyName)); - else - curves.AddRange(AnimationWindowUtility.FilterCurves(hierarchyNode.curves, hierarchyNode.path, hierarchyNode.animatableObjectType)); - } - } - return curves.Distinct().ToList(); - } - - // Changing rotation interpolation will change the propertynames of the curves - // Propertynames are used in treeview node IDs, so we need to anticipate the new IDs by injecting them into treeview state - // This way treeview state (selection and expanding) will be preserved once the curve data is eventually reloaded - private void MaintainTreeviewStateAfterRotationInterpolation(RotationCurveInterpolation.Mode newMode) - { - List selectedInstaceIDs = state.hierarchyState.selectedIDs; - List expandedInstaceIDs = state.hierarchyState.expandedIDs; - - List oldIDs = new List(); - List newIds = new List(); - - for (int i = 0; i < selectedInstaceIDs.Count; i++) - { - AnimationWindowHierarchyNode node = state.hierarchyData.FindItem(selectedInstaceIDs[i]) as AnimationWindowHierarchyNode; - - if (node != null && !node.propertyName.Equals(RotationCurveInterpolation.GetPrefixForInterpolation(newMode))) - { - string oldPrefix = node.propertyName.Split('.')[0]; - string newPropertyName = node.propertyName.Replace(oldPrefix, RotationCurveInterpolation.GetPrefixForInterpolation(newMode)); - - // old treeview node id - oldIDs.Add(selectedInstaceIDs[i]); - // and its new replacement - newIds.Add((node.path + node.animatableObjectType.Name + newPropertyName).GetHashCode()); - } - } - - // Replace old IDs with new ones - for (int i = 0; i < oldIDs.Count; i++) - { - if (selectedInstaceIDs.Contains(oldIDs[i])) - { - int index = selectedInstaceIDs.IndexOf(oldIDs[i]); - selectedInstaceIDs[index] = newIds[i]; - } - if (expandedInstaceIDs.Contains(oldIDs[i])) - { - int index = expandedInstaceIDs.IndexOf(oldIDs[i]); - expandedInstaceIDs[index] = newIds[i]; - } - if (state.hierarchyState.lastClickedID == oldIDs[i]) - state.hierarchyState.lastClickedID = newIds[i]; - } - - state.hierarchyState.selectedIDs = new List(selectedInstaceIDs); - state.hierarchyState.expandedIDs = new List(expandedInstaceIDs); - } - - private RotationCurveInterpolation.Mode GetRotationInterpolationMode(EditorCurveBinding[] curves) - { - if (curves == null || curves.Length == 0) - return RotationCurveInterpolation.Mode.Undefined; - - RotationCurveInterpolation.Mode mode = RotationCurveInterpolation.GetModeFromCurveData(curves[0]); - for (int i = 1; i < curves.Length; i++) - { - RotationCurveInterpolation.Mode nextMode = RotationCurveInterpolation.GetModeFromCurveData(curves[i]); - if (mode != nextMode) - return RotationCurveInterpolation.Mode.Undefined; - } - - return mode; - } - - // TODO: Make real styles, not this - private void SetStyleTextColor(GUIStyle style, Color color) - { - style.normal.textColor = color; - style.focused.textColor = color; - style.active.textColor = color; - style.hover.textColor = color; - } - - public override void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible) - { - firstRowVisible = 0; - lastRowVisible = m_TreeView.data.rowCount - 1; - } - - public float GetNodeHeight(AnimationWindowHierarchyNode node) - { - if (node is AnimationWindowHierarchyAddButtonNode) - return k_AddCurveButtonNodeHeight; - - AnimationWindowHierarchyState hierarchyState = m_TreeView.state as AnimationWindowHierarchyState; - return hierarchyState.GetTallMode(node) ? k_DopeSheetRowHeightTall : k_DopeSheetRowHeight; - } - - public override Vector2 GetTotalSize() - { - var rows = m_TreeView.data.GetRows(); - float height = 0f; - for (int i = 0; i < rows.Count; i++) - { - AnimationWindowHierarchyNode node = rows[i] as AnimationWindowHierarchyNode; - height += GetNodeHeight(node); - } - - return new Vector2(1, height); - } - - float GetTopPixelOfRow(int row, IList rows) - { - float top = 0f; - for (int i = 0; i < row && i < rows.Count; i++) - { - AnimationWindowHierarchyNode node = rows[i] as AnimationWindowHierarchyNode; - top += GetNodeHeight(node); - } - return top; - } - - public override Rect GetRowRect(int row, float rowWidth) - { - var rows = m_TreeView.data.GetRows(); - AnimationWindowHierarchyNode hierarchyNode = rows[row] as AnimationWindowHierarchyNode; - if (hierarchyNode.topPixel == null) - hierarchyNode.topPixel = GetTopPixelOfRow(row, rows); - - float rowHeight = GetNodeHeight(hierarchyNode); - return new Rect(0, (float)hierarchyNode.topPixel, rowWidth, rowHeight); - } - - public override void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool selected, bool focused) - { - AnimationWindowHierarchyNode hierarchyNode = node as AnimationWindowHierarchyNode; - DoNodeGUI(rowRect, hierarchyNode, selected, focused, row); - } - - override public bool BeginRename(TreeViewItem item, float delay) - { - m_RenamedNode = item as AnimationWindowHierarchyNode; - - GameObject rootGameObject = null; - if (m_RenamedNode.curves.Length > 0) - { - AnimationWindowSelectionItem selectionBinding = m_RenamedNode.curves[0].selectionBinding; - if (selectionBinding != null) - rootGameObject = selectionBinding.rootGameObject; - } - - return GetRenameOverlay().BeginRename(m_RenamedNode.path, item.id, delay); - } - - override protected void SyncFakeItem() - { - //base.SyncFakeItem(); - } - - override protected void RenameEnded() - { - string newName = GetRenameOverlay().name; - string oldName = GetRenameOverlay().originalName; - - if (newName != oldName) - { - Undo.RecordObject(state.activeAnimationClip, "Rename Curve"); - - foreach (AnimationWindowCurve curve in m_RenamedNode.curves) - { - EditorCurveBinding newBinding = AnimationWindowUtility.GetRenamedBinding(curve.binding, newName); - - if (AnimationWindowUtility.CurveExists(newBinding, state.allCurves.ToArray())) - { - Debug.LogWarning("Curve already exists, renaming cancelled."); - continue; - } - - AnimationWindowUtility.RenameCurvePath(curve, newBinding, curve.clip); - } - } - - m_RenamedNode = null; - } - - override protected Texture GetIconForItem(TreeViewItem item) - { - if (item != null) - return item.icon; - - return null; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyNode.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyNode.cs deleted file mode 100644 index 7ed4ca36a9..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyNode.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.IMGUI.Controls; - -namespace UnityEditorInternal -{ - internal class AnimationWindowHierarchyNode : TreeViewItem - { - public string path; - public System.Type animatableObjectType; - public string propertyName; - - public EditorCurveBinding? binding; - public AnimationWindowCurve[] curves; - - public float? topPixel = null; - public int indent = 0; - - public AnimationWindowHierarchyNode(int instanceID, int depth, TreeViewItem parent, System.Type animatableObjectType, string propertyName, string path, string displayName) - : base(instanceID, depth, parent, displayName) - { - this.displayName = displayName; - this.animatableObjectType = animatableObjectType; - this.propertyName = propertyName; - this.path = path; - } - } - - internal class AnimationWindowHierarchyPropertyGroupNode : AnimationWindowHierarchyNode - { - public AnimationWindowHierarchyPropertyGroupNode(System.Type animatableObjectType, int setId, string propertyName, string path, TreeViewItem parent) - : base(AnimationWindowUtility.GetPropertyNodeID(setId, path, animatableObjectType, propertyName), parent != null ? parent.depth + 1 : -1, parent, animatableObjectType, AnimationWindowUtility.GetPropertyGroupName(propertyName), path, AnimationWindowUtility.GetNicePropertyGroupDisplayName(animatableObjectType, propertyName)) - {} - } - - internal class AnimationWindowHierarchyPropertyNode : AnimationWindowHierarchyNode - { - public bool isPptrNode; - - public AnimationWindowHierarchyPropertyNode(System.Type animatableObjectType, int setId, string propertyName, string path, TreeViewItem parent, EditorCurveBinding binding, bool isPptrNode) - : base(AnimationWindowUtility.GetPropertyNodeID(setId, path, animatableObjectType, propertyName), parent != null ? parent.depth + 1 : -1, parent, animatableObjectType, propertyName, path, AnimationWindowUtility.GetNicePropertyDisplayName(animatableObjectType, propertyName)) - { - this.binding = binding; - this.isPptrNode = isPptrNode; - } - } - - internal class AnimationWindowHierarchyClipNode : AnimationWindowHierarchyNode - { - public AnimationWindowHierarchyClipNode(TreeViewItem parent, int setId, string name) - : base(setId, parent != null ? parent.depth + 1 : -1, parent, null, null, null, name) - {} - } - - internal class AnimationWindowHierarchyMasterNode : AnimationWindowHierarchyNode - { - public AnimationWindowHierarchyMasterNode() - : base(0, -1, null, null, null, null, "") - {} - } - - // A special node to put "Add Curve" button in bottom of the tree - internal class AnimationWindowHierarchyAddButtonNode : AnimationWindowHierarchyNode - { - public AnimationWindowHierarchyAddButtonNode() - : base(0, -1, null, null, null, null, "") - {} - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowKeySelection.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowKeySelection.cs deleted file mode 100644 index 80cffd1205..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowKeySelection.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using System.Collections; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - [System.Serializable] - internal class AnimationWindowKeySelection : ScriptableObject, ISerializationCallbackReceiver - { - private HashSet m_SelectedKeyHashes; - [SerializeField] private List m_SelectedKeyHashesSerialized; - - public HashSet selectedKeyHashes - { - get { return m_SelectedKeyHashes ?? (m_SelectedKeyHashes = new HashSet()); } - set { m_SelectedKeyHashes = value; } - } - - public void SaveSelection(string undoLabel) - { - Undo.RegisterCompleteObjectUndo(this, undoLabel); - } - - public void OnBeforeSerialize() - { - m_SelectedKeyHashesSerialized = m_SelectedKeyHashes.ToList(); - } - - public void OnAfterDeserialize() - { - m_SelectedKeyHashes = new HashSet(m_SelectedKeyHashesSerialized); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowKeyframe.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowKeyframe.cs deleted file mode 100644 index 2a310b8c35..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowKeyframe.cs +++ /dev/null @@ -1,174 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditorInternal -{ - internal class AnimationWindowKeyframe - { - public float m_InTangent; - public float m_OutTangent; - public float m_InWeight; - public float m_OutWeight; - public WeightedMode m_WeightedMode; - public int m_TangentMode; - public int m_TimeHash; - int m_Hash; - - float m_time; - - object m_value; - - AnimationWindowCurve m_curve; - public float time - { - get { return m_time; } - set - { - m_time = value; - m_Hash = 0; - m_TimeHash = value.GetHashCode(); - } - } - - public object value - { - get { return m_value; } - set { m_value = value; } - } - - public float inTangent - { - get { return m_InTangent; } - set { m_InTangent = value; } - } - - public float outTangent - { - get { return m_OutTangent; } - set { m_OutTangent = value; } - } - - public float inWeight - { - get { return m_InWeight; } - set { m_InWeight = value; } - } - - public float outWeight - { - get { return m_OutWeight; } - set { m_OutWeight = value; } - } - - public WeightedMode weightedMode - { - get { return m_WeightedMode; } - set { m_WeightedMode = value; } - } - - public AnimationWindowCurve curve - { - get { return m_curve; } - set - { - m_curve = value; - m_Hash = 0; - } - } - - public bool isPPtrCurve { get { return curve.isPPtrCurve; } } - public bool isDiscreteCurve { get { return curve.isDiscreteCurve; } } - - public AnimationWindowKeyframe() - { - } - - public AnimationWindowKeyframe(AnimationWindowKeyframe key) - { - this.time = key.time; - this.value = key.value; - this.curve = key.curve; - this.m_InTangent = key.m_InTangent; - this.m_OutTangent = key.m_OutTangent; - this.m_InWeight = key.inWeight; - this.m_OutWeight = key.outWeight; - this.m_WeightedMode = key.weightedMode; - this.m_TangentMode = key.m_TangentMode; - this.m_curve = key.m_curve; - } - - public AnimationWindowKeyframe(AnimationWindowCurve curve, Keyframe key) - { - this.time = key.time; - this.value = key.value; - this.curve = curve; - this.m_InTangent = key.inTangent; - this.m_OutTangent = key.outTangent; - this.m_InWeight = key.inWeight; - this.m_OutWeight = key.outWeight; - this.m_WeightedMode = key.weightedMode; - this.m_TangentMode = key.tangentModeInternal; - this.m_curve = curve; - } - - public AnimationWindowKeyframe(AnimationWindowCurve curve, ObjectReferenceKeyframe key) - { - this.time = key.time; - this.value = key.value; - this.curve = curve; - } - - public int GetHash() - { - if (m_Hash == 0) - { - // Berstein hash - unchecked - { - m_Hash = curve.GetHashCode(); - m_Hash = 33 * m_Hash + time.GetHashCode(); - } - } - - return m_Hash; - } - - public int GetIndex() - { - for (int i = 0; i < curve.m_Keyframes.Count; i++) - { - if (curve.m_Keyframes[i] == this) - { - return i; - } - } - return -1; - } - - public Keyframe ToKeyframe() - { - var keyframe = new Keyframe(time, (float)value, inTangent, outTangent); - - keyframe.tangentModeInternal = m_TangentMode; - keyframe.weightedMode = weightedMode; - keyframe.inWeight = inWeight; - keyframe.outWeight = outWeight; - - return keyframe; - } - - public ObjectReferenceKeyframe ToObjectReferenceKeyframe() - { - var keyframe = new ObjectReferenceKeyframe(); - - keyframe.time = time; - keyframe.value = (UnityEngine.Object)value; - - return keyframe; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowManipulator.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowManipulator.cs deleted file mode 100644 index 76fc50980b..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowManipulator.cs +++ /dev/null @@ -1,192 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AnimationWindowManipulator - { - public delegate bool OnStartDragDelegate(AnimationWindowManipulator manipulator, Event evt); - public delegate bool OnDragDelegate(AnimationWindowManipulator manipulator, Event evt); - public delegate bool OnEndDragDelegate(AnimationWindowManipulator manipulator, Event evt); - - public OnStartDragDelegate onStartDrag; - public OnDragDelegate onDrag; - public OnEndDragDelegate onEndDrag; - - public Rect rect; - public int controlID; - - public AnimationWindowManipulator() - { - // NoOps... - onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => { return false; }; - onDrag += (AnimationWindowManipulator manipulator, Event evt) => { return false; }; - onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => { return false; }; - } - - public virtual void HandleEvents() - { - controlID = GUIUtility.GetControlID(FocusType.Passive); - - Event evt = Event.current; - EventType eventType = evt.GetTypeForControl(controlID); - - bool handled = false; - switch (eventType) - { - case EventType.MouseDown: - if (evt.button == 0) - { - handled = onStartDrag(this, evt); - - if (handled) - GUIUtility.hotControl = controlID; - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == controlID) - { - handled = onDrag(this, evt); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == controlID) - { - handled = onEndDrag(this, evt); - GUIUtility.hotControl = 0; - } - break; - } - - if (handled) - evt.Use(); - } - - public virtual void IgnoreEvents() - { - GUIUtility.GetControlID(FocusType.Passive); - } - } - - internal class AreaManipulator : AnimationWindowManipulator - { - private GUIStyle m_Style; - private MouseCursor m_Cursor; - - public AreaManipulator(GUIStyle style, MouseCursor cursor) - { - m_Style = style; - m_Cursor = cursor; - } - - public AreaManipulator(GUIStyle style) - { - m_Style = style; - m_Cursor = MouseCursor.Arrow; - } - - public void OnGUI(Rect widgetRect) - { - if (m_Style == null) - return; - - rect = widgetRect; - - if (Mathf.Approximately(widgetRect.width * widgetRect.height, 0f)) - return; - - GUI.Label(widgetRect, GUIContent.none, m_Style); - - if (GUIUtility.hotControl == 0 && m_Cursor != MouseCursor.Arrow) - { - EditorGUIUtility.AddCursorRect(widgetRect, m_Cursor); - } - else if (GUIUtility.hotControl == controlID) - { - Vector2 mousePosition = Event.current.mousePosition; - EditorGUIUtility.AddCursorRect(new Rect(mousePosition.x - 10, mousePosition.y - 10, 20, 20), m_Cursor); - } - } - } - - internal class TimeCursorManipulator : AnimationWindowManipulator - { - public enum Alignment - { - Center, - Left, - Right - }; - - public Alignment alignment; - public Color headColor; - public Color lineColor; - public bool dottedLine; - public bool drawLine; - public bool drawHead; - public string tooltip; - - private GUIStyle m_Style; - - public TimeCursorManipulator(GUIStyle style) - { - m_Style = style; - dottedLine = false; - headColor = Color.white; - lineColor = style.normal.textColor; - drawLine = true; - drawHead = true; - tooltip = string.Empty; - alignment = Alignment.Center; - } - - public void OnGUI(Rect windowRect, float pixelTime) - { - float widgetWidth = m_Style.fixedWidth; - float widgetHeight = m_Style.fixedHeight; - - Vector2 windowCoordinate = new Vector2(pixelTime, windowRect.yMin); - - switch (alignment) - { - case Alignment.Center: - rect = new Rect((windowCoordinate.x - widgetWidth / 2.0f), windowCoordinate.y, widgetWidth, widgetHeight); - break; - case Alignment.Left: - rect = new Rect(windowCoordinate.x - widgetWidth, windowCoordinate.y, widgetWidth, widgetHeight); - break; - case Alignment.Right: - rect = new Rect(windowCoordinate.x, windowCoordinate.y, widgetWidth, widgetHeight); - break; - } - - Vector3 p1 = new Vector3(windowCoordinate.x, windowCoordinate.y + widgetHeight, 0.0f); - Vector3 p2 = new Vector3(windowCoordinate.x, windowRect.height, 0.0f); - - if (drawLine) - { - Handles.color = lineColor; - if (dottedLine) - Handles.DrawDottedLine(p1, p2, 5.0f); - else - Handles.DrawLine(p1, p2); - } - - if (drawHead) - { - Color c = GUI.color; - GUI.color = headColor; - GUI.Box(rect, GUIContent.none, m_Style); - GUI.color = c; - } - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowSelectionItem.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowSelectionItem.cs deleted file mode 100644 index f104cd5c42..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowSelectionItem.cs +++ /dev/null @@ -1,361 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using System.Collections; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal class AnimationWindowSelectionItem : ScriptableObject, System.IEquatable, ISelectionBinding - { - [SerializeField] private int m_Id; - [SerializeField] private GameObject m_GameObject; - [SerializeField] private ScriptableObject m_ScriptableObject; - [SerializeField] private AnimationClip m_AnimationClip; - - private List m_CurvesCache = null; - - public virtual int id { get { return m_Id; } set { m_Id = value; } } - - public virtual GameObject gameObject { get { return m_GameObject; } set { m_GameObject = value; } } - - public virtual ScriptableObject scriptableObject { get { return m_ScriptableObject; } set { m_ScriptableObject = value; } } - - public virtual Object sourceObject { get { return (gameObject != null) ? (Object)gameObject : (Object)scriptableObject; } } - - public virtual AnimationClip animationClip { get { return m_AnimationClip; } set { m_AnimationClip = value; } } - - public virtual GameObject rootGameObject - { - get - { - Component animationPlayer = this.animationPlayer; - if (animationPlayer != null) - { - return animationPlayer.gameObject; - } - return null; - } - } - - public virtual Component animationPlayer - { - get - { - if (gameObject != null) - return AnimationWindowUtility.GetClosestAnimationPlayerComponentInParents(gameObject.transform); - return null; - } - } - - public bool disabled - { - get - { - // To be editable, a selection must at least contain an animation clip. - return (animationClip == null); - } - } - - public virtual bool animationIsEditable - { - get - { - // Clip is imported and shouldn't be edited - if (animationClip && (animationClip.hideFlags & HideFlags.NotEditable) != 0) - return false; - - // Object is a prefab - shouldn't be edited - if (objectIsPrefab) - return false; - - return true; - } - } - - public virtual bool clipIsEditable - { - get - { - if (!animationClip) - return false; - // Clip is imported and shouldn't be edited - if ((animationClip.hideFlags & HideFlags.NotEditable) != 0) - return false; - if (!AssetDatabase.IsOpenForEdit(animationClip, StatusQueryOptions.UseCachedIfPossible)) - return false; - - return true; - } - } - - public virtual bool objectIsPrefab - { - get - { - // No gameObject selected - if (!gameObject) - return false; - - if (EditorUtility.IsPersistent(gameObject)) - return true; - - if ((gameObject.hideFlags & HideFlags.NotEditable) != 0) - return true; - - return false; - } - } - - public virtual bool objectIsOptimized - { - get - { - Animator animator = animationPlayer as Animator; - if (animator == null) - return false; - - return animator.isOptimizable && !animator.hasTransformHierarchy; - } - } - - public virtual bool canPreview - { - get - { - if (rootGameObject != null) - { - return !objectIsOptimized; - } - - return false; - } - } - - public virtual bool canRecord - { - get - { - if (!animationIsEditable) - return false; - - return canPreview; - } - } - - public virtual bool canChangeAnimationClip - { - get - { - return rootGameObject != null; - } - } - - public virtual bool canAddCurves - { - get - { - if (gameObject != null) - { - return !objectIsPrefab && clipIsEditable; - } - else if (scriptableObject != null) - { - return true; - } - - return false; - } - } - - public virtual bool canSyncSceneSelection { get { return true; } } - - public List curves - { - get - { - if (m_CurvesCache == null) - { - m_CurvesCache = new List(); - - if (animationClip != null) - { - EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(animationClip); - EditorCurveBinding[] objectCurveBindings = AnimationUtility.GetObjectReferenceCurveBindings(animationClip); - - List transformCurves = new List(); - - foreach (EditorCurveBinding curveBinding in curveBindings) - { - if (AnimationWindowUtility.ShouldShowAnimationWindowCurve(curveBinding)) - { - AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, curveBinding, GetEditorCurveValueType(curveBinding)); - curve.selectionBinding = this; - - m_CurvesCache.Add(curve); - - if (AnimationWindowUtility.IsTransformType(curveBinding.type)) - { - transformCurves.Add(curve); - } - } - } - - foreach (EditorCurveBinding curveBinding in objectCurveBindings) - { - AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, curveBinding, GetEditorCurveValueType(curveBinding)); - curve.selectionBinding = this; - - m_CurvesCache.Add(curve); - } - - transformCurves.Sort(); - if (transformCurves.Count > 0) - { - FillInMissingTransformCurves(transformCurves, ref m_CurvesCache); - } - } - // Curves need to be sorted with path/type/property name so it's possible to construct hierarchy from them - // Sorting logic in AnimationWindowCurve.CompareTo() - m_CurvesCache.Sort(); - } - - return m_CurvesCache; - } - } - - private void FillInMissingTransformCurves(List transformCurves, ref List curvesCache) - { - EditorCurveBinding lastBinding = transformCurves[0].binding; - var propertyGroup = new EditorCurveBinding ? [3]; - string propertyGroupName; - foreach (var transformCurve in transformCurves) - { - var transformBinding = transformCurve.binding; - //if it's a new property group - if (transformBinding.path != lastBinding.path - || AnimationWindowUtility.GetPropertyGroupName(transformBinding.propertyName) != AnimationWindowUtility.GetPropertyGroupName(lastBinding.propertyName)) - { - propertyGroupName = AnimationWindowUtility.GetPropertyGroupName(lastBinding.propertyName); - - FillPropertyGroup(ref propertyGroup, lastBinding, propertyGroupName, ref curvesCache); - - lastBinding = transformBinding; - - propertyGroup = new EditorCurveBinding ? [3]; - } - - AssignBindingToRightSlot(transformBinding, ref propertyGroup); - } - FillPropertyGroup(ref propertyGroup, lastBinding, AnimationWindowUtility.GetPropertyGroupName(lastBinding.propertyName), ref curvesCache); - } - - private void FillPropertyGroup(ref EditorCurveBinding?[] propertyGroup, EditorCurveBinding lastBinding, string propertyGroupName, ref List curvesCache) - { - var newBinding = lastBinding; - newBinding.isPhantom = true; - if (!propertyGroup[0].HasValue) - { - newBinding.propertyName = propertyGroupName + ".x"; - AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, newBinding, GetEditorCurveValueType(newBinding)); - curve.selectionBinding = this; - curvesCache.Add(curve); - } - - if (!propertyGroup[1].HasValue) - { - newBinding.propertyName = propertyGroupName + ".y"; - AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, newBinding, GetEditorCurveValueType(newBinding)); - curve.selectionBinding = this; - curvesCache.Add(curve); - } - - if (!propertyGroup[2].HasValue) - { - newBinding.propertyName = propertyGroupName + ".z"; - AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, newBinding, GetEditorCurveValueType(newBinding)); - curve.selectionBinding = this; - curvesCache.Add(curve); - } - } - - private void AssignBindingToRightSlot(EditorCurveBinding transformBinding, ref EditorCurveBinding?[] propertyGroup) - { - if (transformBinding.propertyName.EndsWith(".x")) - { - propertyGroup[0] = transformBinding; - } - else if (transformBinding.propertyName.EndsWith(".y")) - { - propertyGroup[1] = transformBinding; - } - else if (transformBinding.propertyName.EndsWith(".z")) - { - propertyGroup[2] = transformBinding; - } - } - - public static AnimationWindowSelectionItem Create() - { - AnimationWindowSelectionItem selectionItem = CreateInstance(typeof(AnimationWindowSelectionItem)) as AnimationWindowSelectionItem; - return selectionItem; - } - - public int GetRefreshHash() - { - return unchecked (id * 19603 ^ - (animationClip != null ? 729 * animationClip.GetHashCode() : 0) ^ - (rootGameObject != null ? 27 * rootGameObject.GetHashCode() : 0) ^ - (scriptableObject != null ? scriptableObject.GetHashCode() : 0)); - } - - public void ClearCache() - { - m_CurvesCache = null; - } - - virtual public void Synchronize() - { - // nothing to do. - } - - public bool Equals(AnimationWindowSelectionItem other) - { - return id == other.id && - animationClip == other.animationClip && - gameObject == other.gameObject && - scriptableObject == other.scriptableObject; - } - - public Type GetEditorCurveValueType(EditorCurveBinding curveBinding) - { - if (rootGameObject != null) - { - return AnimationUtility.GetEditorCurveValueType(rootGameObject, curveBinding); - } - else if (scriptableObject != null) - { - return AnimationUtility.GetEditorCurveValueType(scriptableObject, curveBinding); - } - else - { - if (curveBinding.isPPtrCurve) - { - // Cannot extract type of PPtrCurve. - return null; - } - else - { - // Cannot extract type of AnimationCurve. Default to float. - return typeof(float); - } - } - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs deleted file mode 100644 index c92e3ed241..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs +++ /dev/null @@ -1,1650 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Reflection; -using System.Linq; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using System.Collections; -using UnityEditor.IMGUI.Controls; -using Object = UnityEngine.Object; -using Random = UnityEngine.Random; - -namespace UnityEditorInternal -{ - [System.Serializable] - internal class AnimationWindowState : ScriptableObject, ICurveEditorState - { - public enum RefreshType - { - None = 0, - CurvesOnly = 1, - Everything = 2 - }; - - public enum SnapMode - { - Disabled = 0, - SnapToFrame = 1, - SnapToClipFrame = 2 - }; - - [SerializeField] public AnimationWindowHierarchyState hierarchyState; // Persistent state of treeview on the left side of window - [SerializeField] public AnimEditor animEditor; // Reference to owner of this state. Used to trigger repaints. - [SerializeField] public bool showCurveEditor; // Do we show dopesheet or curves - [SerializeField] public bool linkedWithSequencer; // Toggle Sequencer selection mode. - [SerializeField] private TimeArea m_TimeArea; // Either curveeditor or dopesheet depending on which is selected - [SerializeField] private AnimationWindowSelectionItem m_EmptySelection; - [SerializeField] private AnimationWindowSelectionItem m_Selection; // Internal selection - [SerializeField] private AnimationWindowKeySelection m_KeySelection; // What is selected. Hashes persist cache reload, because they are from keyframe time+value - [SerializeField] private int m_ActiveKeyframeHash; // Which keyframe is active (selected key that user previously interacted with) - [SerializeField] private float m_FrameRate = kDefaultFrameRate; - [SerializeField] private TimeArea.TimeFormat m_TimeFormat = TimeArea.TimeFormat.TimeFrame; - [SerializeField] private AnimationWindowControl m_ControlInterface; - [SerializeField] private IAnimationWindowControl m_OverrideControlInterface; - - [NonSerialized] public Action onStartLiveEdit; - [NonSerialized] public Action onEndLiveEdit; - [NonSerialized] public Action onFrameRateChange; - - private static List s_KeyframeClipboard; // For copy-pasting keyframes - - [NonSerialized] public AnimationWindowHierarchyDataSource hierarchyData; - - private List m_ActiveCurvesCache; - private List m_dopelinesCache; - private List m_SelectedKeysCache; - private Bounds? m_SelectionBoundsCache; - private CurveWrapper[] m_ActiveCurveWrappersCache; - private AnimationWindowKeyframe m_ActiveKeyframeCache; - private HashSet m_ModifiedCurves = new HashSet(); - private EditorCurveBinding? m_lastAddedCurveBinding; - - // Hash of all the things that require animationWindow to refresh if they change - private int m_PreviousRefreshHash; - - // Changing m_Refresh means you are ordering a refresh at the next OnGUI(). - // CurvesOnly means that there is no need to refresh the hierarchy, since only the keyframe data changed. - private RefreshType m_Refresh = RefreshType.None; - - private struct LiveEditKeyframe - { - public AnimationWindowKeyframe keySnapshot; - public AnimationWindowKeyframe key; - } - - private class LiveEditCurve - { - public AnimationWindowCurve curve; - public List selectedKeys = new List(); - public List unselectedKeys = new List(); - } - - private List m_LiveEditSnapshot; - - public const float kDefaultFrameRate = 60.0f; - public const string kEditCurveUndoLabel = "Edit Curve"; - - public AnimationWindowSelectionItem selection - { - get - { - if (m_Selection != null) - return m_Selection; - - if (m_EmptySelection == null) - { - m_EmptySelection = AnimationClipSelectionItem.Create(null, null); - m_EmptySelection.hideFlags = HideFlags.HideAndDontSave; - } - - return m_EmptySelection; - } - - set - { - if (m_Selection != null) - Object.DestroyImmediate(m_Selection); - - // Make a copy and take ownership - if (value != null) - { - m_Selection = Object.Instantiate(value); - m_Selection.hideFlags = HideFlags.HideAndDontSave; - } - else - { - m_Selection = null; - } - - OnSelectionChanged(); - } - } - - // AnimationClip we are currently editing - public AnimationClip activeAnimationClip - { - get - { - return selection.animationClip; - } - set - { - if (selection.canChangeAnimationClip) - { - selection.animationClip = value; - OnSelectionChanged(); - } - } - } - - - // Previously or currently selected gameobject is considered as the active gameobject - public GameObject activeGameObject - { - get - { - return selection.gameObject; - } - } - - // Closes parent to activeGameObject that has Animator component - public GameObject activeRootGameObject - { - get - { - return selection.rootGameObject; - } - } - - public Component activeAnimationPlayer - { - get - { - return selection.animationPlayer; - } - } - - public ScriptableObject activeScriptableObject - { - get - { - return selection.scriptableObject; - } - } - - // Is the hierarchy in animator optimized - public bool animatorIsOptimized - { - get - { - return selection.objectIsOptimized; - } - } - - public bool disabled - { - get - { - return selection.disabled; - } - } - - public IAnimationWindowControl controlInterface - { - get - { - if (m_OverrideControlInterface != null) - return m_OverrideControlInterface; - - return m_ControlInterface; - } - } - - public IAnimationWindowControl overrideControlInterface - { - get - { - return m_OverrideControlInterface; - } - - set - { - if (m_OverrideControlInterface != null) - Object.DestroyImmediate(m_OverrideControlInterface); - - m_OverrideControlInterface = value; - } - } - - public void OnGUI() - { - RefreshHashCheck(); - Refresh(); - } - - private void RefreshHashCheck() - { - int newRefreshHash = GetRefreshHash(); - if (m_PreviousRefreshHash != newRefreshHash) - { - refresh = RefreshType.Everything; - m_PreviousRefreshHash = newRefreshHash; - } - } - - private void Refresh() - { - selection.Synchronize(); - - if (refresh == RefreshType.Everything) - { - selection.ClearCache(); - - m_ActiveKeyframeCache = null; - m_ActiveCurvesCache = null; - m_dopelinesCache = null; - m_SelectedKeysCache = null; - m_SelectionBoundsCache = null; - - ClearCurveWrapperCache(); - - if (hierarchyData != null) - hierarchyData.UpdateData(); - - // If there was new curve added, set it as active selection - if (m_lastAddedCurveBinding != null) - OnNewCurveAdded((EditorCurveBinding)m_lastAddedCurveBinding); - - // select top dopeline if there is no selection available - if (activeCurves.Count == 0 && dopelines.Count > 0) - SelectHierarchyItem(dopelines[0], false, false); - - m_Refresh = RefreshType.None; - } - else if (refresh == RefreshType.CurvesOnly) - { - m_ActiveKeyframeCache = null; - m_SelectedKeysCache = null; - m_SelectionBoundsCache = null; - - ReloadModifiedAnimationCurveCache(); - ReloadModifiedDopelineCache(); - ReloadModifiedCurveWrapperCache(); - - m_Refresh = RefreshType.None; - m_ModifiedCurves.Clear(); - } - } - - // Hash for checking if any of these things is changed - private int GetRefreshHash() - { - return - selection.GetRefreshHash() ^ - (hierarchyState != null ? hierarchyState.expandedIDs.Count : 0) ^ - (hierarchyState != null ? hierarchyState.GetTallInstancesCount() : 0) ^ - (showCurveEditor ? 1 : 0); - } - - public void ForceRefresh() - { - refresh = RefreshType.Everything; - } - - public void OnEnable() - { - hideFlags = HideFlags.HideAndDontSave; - AnimationUtility.onCurveWasModified += CurveWasModified; - Undo.undoRedoPerformed += UndoRedoPerformed; - - // NoOps... - onStartLiveEdit += () => {}; - onEndLiveEdit += () => {}; - - if (m_ControlInterface == null) - m_ControlInterface = CreateInstance(typeof(AnimationWindowControl)) as AnimationWindowControl; - - m_ControlInterface.state = this; - } - - public void OnDisable() - { - AnimationUtility.onCurveWasModified -= CurveWasModified; - Undo.undoRedoPerformed -= UndoRedoPerformed; - - m_ControlInterface.OnDisable(); - } - - public void OnDestroy() - { - Object.DestroyImmediate(m_EmptySelection); - Object.DestroyImmediate(m_Selection); - Object.DestroyImmediate(m_KeySelection); - Object.DestroyImmediate(m_ControlInterface); - Object.DestroyImmediate(m_OverrideControlInterface); - } - - public void OnSelectionChanged() - { - if (onFrameRateChange != null) - onFrameRateChange(frameRate); - - // reset back time at 0 upon selection change. - controlInterface.OnSelectionChanged(); - - if (animEditor != null) - animEditor.OnSelectionChanged(); - } - - // Set this property to ask for refresh at the next OnGUI. - public RefreshType refresh - { - get { return m_Refresh; } - // Make sure that if full refresh is already ordered, nobody gets to f*** with it - set - { - if ((int)m_Refresh < (int)value) - m_Refresh = value; - } - } - - public void UndoRedoPerformed() - { - refresh = RefreshType.Everything; - controlInterface.ResampleAnimation(); - } - - // When curve is modified, we never trigger refresh right away. We order a refresh at later time by setting refresh to appropriate value. - void CurveWasModified(AnimationClip clip, EditorCurveBinding binding, AnimationUtility.CurveModifiedType type) - { - // AnimationWindow doesn't care if some other clip somewhere changed - if (activeAnimationClip != clip) - return; - - // Refresh curves that already exist. - if (type == AnimationUtility.CurveModifiedType.CurveModified) - { - bool didFind = false; - bool hadPhantom = false; - int hashCode = binding.GetHashCode(); - - List curves = selection.curves; - for (int j = 0; j < curves.Count; ++j) - { - AnimationWindowCurve curve = curves[j]; - int curveHash = curve.GetBindingHashCode(); - if (curveHash == hashCode) - { - m_ModifiedCurves.Add(curve.GetHashCode()); - didFind = true; - hadPhantom |= curve.binding.isPhantom; - } - } - - if (didFind && !hadPhantom) - refresh = RefreshType.CurvesOnly; - else - { - // New curve was added, so let's save binding and make it active selection when Refresh is called next time - m_lastAddedCurveBinding = binding; - refresh = RefreshType.Everything; - } - } - else - { - // Otherwise do a full reload - refresh = RefreshType.Everything; - } - } - - public void SaveKeySelection(string undoLabel) - { - if (m_KeySelection != null) - Undo.RegisterCompleteObjectUndo(m_KeySelection, undoLabel); - } - - public void SaveCurve(AnimationWindowCurve curve) - { - SaveCurve(curve, kEditCurveUndoLabel); - } - - public void SaveCurve(AnimationWindowCurve curve, string undoLabel) - { - if (!curve.animationIsEditable) - Debug.LogError("Curve is not editable and shouldn't be saved."); - - Undo.RegisterCompleteObjectUndo(curve.clip, undoLabel); - AnimationRecording.SaveModifiedCurve(curve, curve.clip); - Repaint(); - } - - private void SaveSelectedKeys(string undoLabel) - { - List saveCurves = new List(); - - // Find all curves that need saving - foreach (LiveEditCurve snapshot in m_LiveEditSnapshot) - { - if (!snapshot.curve.animationIsEditable) - continue; - - if (!saveCurves.Contains(snapshot.curve)) - saveCurves.Add(snapshot.curve); - - List toBeDeleted = new List(); - - // If selected keys are dragged over non-selected keyframe at exact same time, then delete the unselected ones underneath - foreach (AnimationWindowKeyframe other in snapshot.curve.m_Keyframes) - { - // Keyframe is in selection, skip. - if (snapshot.selectedKeys.Exists(liveEditKey => liveEditKey.key == other)) - continue; - - // There is already a selected keyframe at that time, delete non-selected keyframe. - if (!snapshot.selectedKeys.Exists(liveEditKey => AnimationKeyTime.Time(liveEditKey.key.time, frameRate).frame == AnimationKeyTime.Time(other.time, frameRate).frame)) - continue; - - toBeDeleted.Add(other); - } - - foreach (AnimationWindowKeyframe deletedKey in toBeDeleted) - { - snapshot.curve.m_Keyframes.Remove(deletedKey); - } - } - - foreach (AnimationWindowCurve curve in saveCurves) - SaveCurve(curve, undoLabel); - } - - public void RemoveCurve(AnimationWindowCurve curve, string undoLabel) - { - if (!curve.animationIsEditable) - return; - - Undo.RegisterCompleteObjectUndo(curve.clip, undoLabel); - - if (curve.isPPtrCurve) - AnimationUtility.SetObjectReferenceCurve(curve.clip, curve.binding, null); - else - AnimationUtility.SetEditorCurve(curve.clip, curve.binding, null); - } - - public bool previewing { get { return controlInterface.previewing; } } - - public bool canPreview { get { return controlInterface.canPreview; } } - - public void StartPreview() - { - controlInterface.StartPreview(); - controlInterface.ResampleAnimation(); - } - - public void StopPreview() - { - controlInterface.StopPreview(); - } - - public bool recording { get { return controlInterface.recording; } } - - public bool canRecord { get { return controlInterface.canRecord; } } - - public void StartRecording() - { - controlInterface.StartRecording(selection.sourceObject); - controlInterface.ResampleAnimation(); - } - - public void StopRecording() - { - controlInterface.StopRecording(); - } - - public bool playing { get { return controlInterface.playing; } } - - public void StartPlayback() - { - controlInterface.StartPlayback(); - } - - public void StopPlayback() - { - controlInterface.StopPlayback(); - } - - public void ResampleAnimation() - { - controlInterface.ResampleAnimation(); - } - - public List allCurves - { - get { return selection.curves; } - } - - public List activeCurves - { - get - { - if (m_ActiveCurvesCache == null) - { - m_ActiveCurvesCache = new List(); - if (hierarchyState != null && hierarchyData != null) - { - foreach (int id in hierarchyState.selectedIDs) - { - TreeViewItem node = hierarchyData.FindItem(id); - AnimationWindowHierarchyNode hierarchyNode = node as AnimationWindowHierarchyNode; - - if (hierarchyNode == null) - continue; - - AnimationWindowCurve[] curves = hierarchyNode.curves; - if (curves == null) - continue; - - foreach (AnimationWindowCurve curve in curves) - if (!m_ActiveCurvesCache.Contains(curve)) - m_ActiveCurvesCache.Add(curve); - } - - m_ActiveCurvesCache.Sort(); - } - } - - return m_ActiveCurvesCache; - } - } - - public CurveWrapper[] activeCurveWrappers - { - get - { - if (m_ActiveCurveWrappersCache == null || m_ActiveCurvesCache == null) - { - List activeCurveWrappers = new List(); - foreach (AnimationWindowCurve curve in activeCurves) - if (!curve.isDiscreteCurve) - activeCurveWrappers.Add(AnimationWindowUtility.GetCurveWrapper(curve, curve.clip)); - - // If there are no active curves, we would end up with empty curve editor so we just give all curves insteads - if (!activeCurveWrappers.Any()) - foreach (AnimationWindowCurve curve in allCurves) - if (!curve.isDiscreteCurve) - activeCurveWrappers.Add(AnimationWindowUtility.GetCurveWrapper(curve, curve.clip)); - - m_ActiveCurveWrappersCache = activeCurveWrappers.ToArray(); - } - - return m_ActiveCurveWrappersCache; - } - } - - public List dopelines - { - get - { - if (m_dopelinesCache == null) - { - m_dopelinesCache = new List(); - - if (hierarchyData != null) - { - foreach (TreeViewItem node in hierarchyData.GetRows()) - { - AnimationWindowHierarchyNode hierarchyNode = node as AnimationWindowHierarchyNode; - - if (hierarchyNode == null || hierarchyNode is AnimationWindowHierarchyAddButtonNode) - continue; - - AnimationWindowCurve[] curves = hierarchyNode.curves; - if (curves == null) - continue; - - DopeLine dopeLine = new DopeLine(node.id, curves); - dopeLine.tallMode = hierarchyState.GetTallMode(hierarchyNode); - dopeLine.objectType = hierarchyNode.animatableObjectType; - dopeLine.hasChildren = !(hierarchyNode is AnimationWindowHierarchyPropertyNode); - dopeLine.isMasterDopeline = node is AnimationWindowHierarchyMasterNode; - m_dopelinesCache.Add(dopeLine); - } - } - } - return m_dopelinesCache; - } - } - - public List selectedHierarchyNodes - { - get - { - List selectedHierarchyNodes = new List(); - - if (activeAnimationClip != null && hierarchyData != null) - { - foreach (int id in hierarchyState.selectedIDs) - { - AnimationWindowHierarchyNode hierarchyNode = (AnimationWindowHierarchyNode)hierarchyData.FindItem(id); - - if (hierarchyNode == null || hierarchyNode is AnimationWindowHierarchyAddButtonNode) - continue; - - selectedHierarchyNodes.Add(hierarchyNode); - } - } - - return selectedHierarchyNodes; - } - } - - public AnimationWindowKeyframe activeKeyframe - { - get - { - if (m_ActiveKeyframeCache == null) - { - foreach (AnimationWindowCurve curve in allCurves) - { - foreach (AnimationWindowKeyframe keyframe in curve.m_Keyframes) - { - if (keyframe.GetHash() == m_ActiveKeyframeHash) - m_ActiveKeyframeCache = keyframe; - } - } - } - return m_ActiveKeyframeCache; - } - set - { - m_ActiveKeyframeCache = null; - m_ActiveKeyframeHash = value != null ? value.GetHash() : 0; - } - } - - public List selectedKeys - { - get - { - if (m_SelectedKeysCache == null) - { - m_SelectedKeysCache = new List(); - foreach (AnimationWindowCurve curve in allCurves) - { - foreach (AnimationWindowKeyframe keyframe in curve.m_Keyframes) - { - if (KeyIsSelected(keyframe)) - { - m_SelectedKeysCache.Add(keyframe); - } - } - } - } - return m_SelectedKeysCache; - } - } - - public Bounds selectionBounds - { - get - { - if (m_SelectionBoundsCache == null) - { - List keys = selectedKeys; - if (keys.Count > 0) - { - AnimationWindowKeyframe key = keys[0]; - float time = key.time; - float val = key.isPPtrCurve ? 0.0f : (float)key.value; - - Bounds bounds = new Bounds(new Vector2(time, val), Vector2.zero); - - for (int i = 1; i < keys.Count; ++i) - { - key = keys[i]; - - time = key.time; - val = key.isPPtrCurve ? 0.0f : (float)key.value; - - bounds.Encapsulate(new Vector2(time, val)); - } - - m_SelectionBoundsCache = bounds; - } - else - { - m_SelectionBoundsCache = new Bounds(Vector2.zero, Vector2.zero); - } - } - - return m_SelectionBoundsCache.Value; - } - } - - private HashSet selectedKeyHashes - { - get - { - if (m_KeySelection == null) - { - m_KeySelection = CreateInstance(); - m_KeySelection.hideFlags = HideFlags.HideAndDontSave; - } - - return m_KeySelection.selectedKeyHashes; - } - set - { - if (m_KeySelection == null) - { - m_KeySelection = CreateInstance(); - m_KeySelection.hideFlags = HideFlags.HideAndDontSave; - } - - m_KeySelection.selectedKeyHashes = value; - } - } - - public bool AnyKeyIsSelected(DopeLine dopeline) - { - foreach (AnimationWindowKeyframe keyframe in dopeline.keys) - if (KeyIsSelected(keyframe)) - return true; - - return false; - } - - public bool KeyIsSelected(AnimationWindowKeyframe keyframe) - { - return selectedKeyHashes.Contains(keyframe.GetHash()); - } - - public void SelectKey(AnimationWindowKeyframe keyframe) - { - int hash = keyframe.GetHash(); - if (!selectedKeyHashes.Contains(hash)) - selectedKeyHashes.Add(hash); - - m_SelectedKeysCache = null; - m_SelectionBoundsCache = null; - } - - public void SelectKeysFromDopeline(DopeLine dopeline) - { - if (dopeline == null) - return; - - foreach (var key in dopeline.keys) - SelectKey(key); - } - - public void UnselectKey(AnimationWindowKeyframe keyframe) - { - int hash = keyframe.GetHash(); - if (selectedKeyHashes.Contains(hash)) - selectedKeyHashes.Remove(hash); - - m_SelectedKeysCache = null; - m_SelectionBoundsCache = null; - } - - public void UnselectKeysFromDopeline(DopeLine dopeline) - { - if (dopeline == null) - return; - - foreach (var key in dopeline.keys) - UnselectKey(key); - } - - public void DeleteSelectedKeys() - { - if (selectedKeys.Count == 0) - return; - - DeleteKeys(selectedKeys); - } - - public void DeleteKeys(List keys) - { - SaveKeySelection(kEditCurveUndoLabel); - - foreach (AnimationWindowKeyframe keyframe in keys) - { - if (!keyframe.curve.animationIsEditable) - continue; - - UnselectKey(keyframe); - keyframe.curve.m_Keyframes.Remove(keyframe); - - // TODO: optimize by not saving curve for each keyframe - SaveCurve(keyframe.curve, kEditCurveUndoLabel); - } - - ResampleAnimation(); - } - - public void StartLiveEdit() - { - if (onStartLiveEdit != null) - onStartLiveEdit(); - - m_LiveEditSnapshot = new List(); - - SaveKeySelection(kEditCurveUndoLabel); - - foreach (AnimationWindowKeyframe selectedKey in selectedKeys) - { - if (!m_LiveEditSnapshot.Exists(snapshot => snapshot.curve == selectedKey.curve)) - { - LiveEditCurve snapshot = new LiveEditCurve(); - snapshot.curve = selectedKey.curve; - foreach (AnimationWindowKeyframe key in selectedKey.curve.m_Keyframes) - { - LiveEditKeyframe liveEditKey = new LiveEditKeyframe(); - liveEditKey.keySnapshot = new AnimationWindowKeyframe(key); - liveEditKey.key = key; - - if (KeyIsSelected(key)) - snapshot.selectedKeys.Add(liveEditKey); - else - snapshot.unselectedKeys.Add(liveEditKey); - } - - m_LiveEditSnapshot.Add(snapshot); - } - } - } - - public void EndLiveEdit() - { - SaveSelectedKeys(kEditCurveUndoLabel); - - m_LiveEditSnapshot = null; - - if (onEndLiveEdit != null) - onEndLiveEdit(); - } - - public bool InLiveEdit() - { - return m_LiveEditSnapshot != null; - } - - public void MoveSelectedKeys(float deltaTime, bool snapToFrame) - { - bool inLiveEdit = InLiveEdit(); - if (!inLiveEdit) - StartLiveEdit(); - - // Clear selections since all hashes are now different - ClearKeySelections(); - - foreach (LiveEditCurve snapshot in m_LiveEditSnapshot) - { - foreach (LiveEditKeyframe liveEditKey in snapshot.selectedKeys) - { - if (snapshot.curve.animationIsEditable) - { - liveEditKey.key.time = Mathf.Max(liveEditKey.keySnapshot.time + deltaTime, 0f); - - if (snapToFrame) - liveEditKey.key.time = SnapToFrame(liveEditKey.key.time, snapshot.curve.clip.frameRate); - } - - SelectKey(liveEditKey.key); - } - } - - if (!inLiveEdit) - EndLiveEdit(); - } - - public void TransformSelectedKeys(Matrix4x4 matrix, bool flipX, bool flipY, bool snapToFrame) - { - bool inLiveEdit = InLiveEdit(); - if (!inLiveEdit) - StartLiveEdit(); - - // Clear selections since all hashes are now different - ClearKeySelections(); - - foreach (LiveEditCurve snapshot in m_LiveEditSnapshot) - { - foreach (LiveEditKeyframe liveEditKey in snapshot.selectedKeys) - { - if (snapshot.curve.animationIsEditable) - { - // Transform time value. - Vector3 v = new Vector3(liveEditKey.keySnapshot.time, liveEditKey.keySnapshot.isPPtrCurve ? 0f : (float)liveEditKey.keySnapshot.value, 0f); - v = matrix.MultiplyPoint3x4(v); - - liveEditKey.key.time = Mathf.Max((snapToFrame) ? SnapToFrame(v.x, snapshot.curve.clip.frameRate) : v.x, 0f); - - if (flipX) - { - liveEditKey.key.inTangent = (liveEditKey.keySnapshot.outTangent != Mathf.Infinity) ? -liveEditKey.keySnapshot.outTangent : Mathf.Infinity; - liveEditKey.key.outTangent = (liveEditKey.keySnapshot.inTangent != Mathf.Infinity) ? -liveEditKey.keySnapshot.inTangent : Mathf.Infinity; - } - - if (!liveEditKey.key.isPPtrCurve) - { - liveEditKey.key.value = v.y; - - if (flipY) - { - liveEditKey.key.inTangent = (liveEditKey.key.inTangent != Mathf.Infinity) ? -liveEditKey.key.inTangent : Mathf.Infinity; - liveEditKey.key.outTangent = (liveEditKey.key.outTangent != Mathf.Infinity) ? -liveEditKey.key.outTangent : Mathf.Infinity; - } - } - } - - SelectKey(liveEditKey.key); - } - } - - if (!inLiveEdit) - EndLiveEdit(); - } - - public void TransformRippleKeys(Matrix4x4 matrix, float t1, float t2, bool flipX, bool snapToFrame) - { - bool inLiveEdit = InLiveEdit(); - if (!inLiveEdit) - StartLiveEdit(); - - // Clear selections since all hashes are now different - ClearKeySelections(); - - foreach (LiveEditCurve snapshot in m_LiveEditSnapshot) - { - foreach (LiveEditKeyframe liveEditKey in snapshot.selectedKeys) - { - if (snapshot.curve.animationIsEditable) - { - Vector3 v = new Vector3(liveEditKey.keySnapshot.time, 0f, 0f); - v = matrix.MultiplyPoint3x4(v); - - liveEditKey.key.time = Mathf.Max((snapToFrame) ? SnapToFrame(v.x, snapshot.curve.clip.frameRate) : v.x, 0f); - - if (flipX) - { - liveEditKey.key.inTangent = (liveEditKey.keySnapshot.outTangent != Mathf.Infinity) ? -liveEditKey.keySnapshot.outTangent : Mathf.Infinity; - liveEditKey.key.outTangent = (liveEditKey.keySnapshot.inTangent != Mathf.Infinity) ? -liveEditKey.keySnapshot.inTangent : Mathf.Infinity; - } - } - - SelectKey(liveEditKey.key); - } - - if (!snapshot.curve.animationIsEditable) - continue; - - foreach (LiveEditKeyframe liveEditKey in snapshot.unselectedKeys) - { - if (liveEditKey.keySnapshot.time > t2) - { - Vector3 v = new Vector3(flipX ? t1 : t2, 0f, 0f); - v = matrix.MultiplyPoint3x4(v); - - float dt = v.x - t2; - if (dt > 0f) - { - float newTime = liveEditKey.keySnapshot.time + dt; - liveEditKey.key.time = Mathf.Max((snapToFrame) ? SnapToFrame(newTime, snapshot.curve.clip.frameRate) : newTime, 0f); - } - else - { - liveEditKey.key.time = liveEditKey.keySnapshot.time; - } - } - else if (liveEditKey.keySnapshot.time < t1) - { - Vector3 v = new Vector3(flipX ? t2 : t1, 0f, 0f); - v = matrix.MultiplyPoint3x4(v); - - float dt = v.x - t1; - if (dt < 0f) - { - float newTime = liveEditKey.keySnapshot.time + dt; - liveEditKey.key.time = Mathf.Max((snapToFrame) ? SnapToFrame(newTime, snapshot.curve.clip.frameRate) : newTime, 0f); - } - else - { - liveEditKey.key.time = liveEditKey.keySnapshot.time; - } - } - } - } - - if (!inLiveEdit) - EndLiveEdit(); - } - - public void CopyKeys() - { - if (s_KeyframeClipboard == null) - s_KeyframeClipboard = new List(); - - float smallestTime = float.MaxValue; - s_KeyframeClipboard.Clear(); - foreach (AnimationWindowKeyframe keyframe in selectedKeys) - { - s_KeyframeClipboard.Add(new AnimationWindowKeyframe(keyframe)); - if (keyframe.time < smallestTime) - smallestTime = keyframe.time; - } - if (s_KeyframeClipboard.Count > 0) // copying selected keys - { - foreach (AnimationWindowKeyframe keyframe in s_KeyframeClipboard) - { - keyframe.time -= smallestTime; - } - } - else // No selected keys, lets copy entire curves - { - CopyAllActiveCurves(); - } - } - - public void CopyAllActiveCurves() - { - foreach (AnimationWindowCurve curve in activeCurves) - { - foreach (AnimationWindowKeyframe keyframe in curve.m_Keyframes) - { - s_KeyframeClipboard.Add(new AnimationWindowKeyframe(keyframe)); - } - } - } - - public void PasteKeys() - { - if (s_KeyframeClipboard == null) - s_KeyframeClipboard = new List(); - - SaveKeySelection(kEditCurveUndoLabel); - - HashSet oldSelection = new HashSet(selectedKeyHashes); - ClearKeySelections(); - - AnimationWindowCurve lastTargetCurve = null; - AnimationWindowCurve lastSourceCurve = null; - float lastTime = 0f; - - List clipboardCurves = new List(); - foreach (AnimationWindowKeyframe keyframe in s_KeyframeClipboard) - if (!clipboardCurves.Any() || clipboardCurves.Last() != keyframe.curve) - clipboardCurves.Add(keyframe.curve); - - // If we have equal number of target and source curves, then match by index. If not, then try to match with AnimationWindowUtility.BestMatchForPaste. - bool matchCurveByIndex = clipboardCurves.Count() == activeCurves.Count(); - int targetIndex = 0; - - foreach (AnimationWindowKeyframe keyframe in s_KeyframeClipboard) - { - if (lastSourceCurve != null && keyframe.curve != lastSourceCurve) - targetIndex++; - - AnimationWindowKeyframe newKeyframe = new AnimationWindowKeyframe(keyframe); - - if (matchCurveByIndex) - newKeyframe.curve = activeCurves[targetIndex]; - else - newKeyframe.curve = AnimationWindowUtility.BestMatchForPaste(newKeyframe.curve.binding, clipboardCurves, activeCurves); - - if (newKeyframe.curve == null) // Paste as new curve - { - // Curves are selected in the animation window hierarchy. Since we couldn't find a proper match, - // create a new curve in first selected clip in active curves. - if (activeCurves.Count > 0) - { - AnimationWindowCurve firstCurve = activeCurves[0]; - if (firstCurve.animationIsEditable) - { - newKeyframe.curve = new AnimationWindowCurve(firstCurve.clip, keyframe.curve.binding, keyframe.curve.valueType); - newKeyframe.curve.selectionBinding = firstCurve.selectionBinding; - newKeyframe.time = keyframe.time; - } - } - // If nothing is selected, create a new curve in first selected clip. - else - { - if (selection.animationIsEditable) - { - newKeyframe.curve = new AnimationWindowCurve(selection.animationClip, keyframe.curve.binding, keyframe.curve.valueType); - newKeyframe.curve.selectionBinding = selection; - newKeyframe.time = keyframe.time; - } - } - } - - if (newKeyframe.curve == null || !newKeyframe.curve.animationIsEditable) - continue; - - newKeyframe.time += time.time; - - // Only allow pasting of key frame from numerical curves to numerical curves or from pptr curves to pptr curves. - if ((newKeyframe.time >= 0.0f) && (newKeyframe.curve != null) && (newKeyframe.curve.isPPtrCurve == keyframe.curve.isPPtrCurve)) - { - if (newKeyframe.curve.HasKeyframe(AnimationKeyTime.Time(newKeyframe.time, newKeyframe.curve.clip.frameRate))) - newKeyframe.curve.RemoveKeyframe(AnimationKeyTime.Time(newKeyframe.time, newKeyframe.curve.clip.frameRate)); - - // When copy-pasting multiple keyframes (curve), its a continous thing. This is why we delete the existing keyframes in the pasted range. - if (lastTargetCurve == newKeyframe.curve) - newKeyframe.curve.RemoveKeysAtRange(lastTime, newKeyframe.time); - - newKeyframe.curve.m_Keyframes.Add(newKeyframe); - SelectKey(newKeyframe); - // TODO: Optimize to only save curve once instead once per keyframe - SaveCurve(newKeyframe.curve, kEditCurveUndoLabel); - - lastTargetCurve = newKeyframe.curve; - lastTime = newKeyframe.time; - } - - lastSourceCurve = keyframe.curve; - } - - // If nothing is pasted, then we revert to old selection - if (selectedKeyHashes.Count == 0) - selectedKeyHashes = oldSelection; - else - ResampleAnimation(); - } - - public void ClearSelections() - { - ClearKeySelections(); - ClearHierarchySelection(); - } - - public void ClearKeySelections() - { - selectedKeyHashes.Clear(); - m_SelectedKeysCache = null; - m_SelectionBoundsCache = null; - } - - public void ClearHierarchySelection() - { - hierarchyState.selectedIDs.Clear(); - m_ActiveCurvesCache = null; - } - - private void ClearCurveWrapperCache() - { - if (m_ActiveCurveWrappersCache == null) - return; - - for (int i = 0; i < m_ActiveCurveWrappersCache.Length; ++i) - { - CurveWrapper curveWrapper = m_ActiveCurveWrappersCache[i]; - if (curveWrapper.renderer != null) - curveWrapper.renderer.FlushCache(); - } - - m_ActiveCurveWrappersCache = null; - } - - private void ReloadModifiedDopelineCache() - { - if (m_dopelinesCache == null) - return; - - for (int i = 0; i < m_dopelinesCache.Count; ++i) - { - DopeLine dopeLine = m_dopelinesCache[i]; - AnimationWindowCurve[] curves = dopeLine.curves; - for (int j = 0; j < curves.Length; ++j) - { - if (m_ModifiedCurves.Contains(curves[j].GetHashCode())) - { - dopeLine.InvalidateKeyframes(); - break; - } - } - } - } - - private void ReloadModifiedCurveWrapperCache() - { - if (m_ActiveCurveWrappersCache == null) - return; - - Dictionary updateList = new Dictionary(); - - for (int i = 0; i < m_ActiveCurveWrappersCache.Length; ++i) - { - CurveWrapper curveWrapper = m_ActiveCurveWrappersCache[i]; - - if (m_ModifiedCurves.Contains(curveWrapper.id)) - { - AnimationWindowCurve curve = allCurves.Find(c => c.GetHashCode() == curveWrapper.id); - if (curve != null) - { - // Boundaries have changed, invalidate all curves - if (curve.clip.startTime != curveWrapper.renderer.RangeStart() || - curve.clip.stopTime != curveWrapper.renderer.RangeEnd()) - { - ClearCurveWrapperCache(); - return; - } - else - { - updateList[i] = curve; - } - } - } - } - - // Only update curve wrappers that were modified. - for (int i = 0; i < updateList.Count; ++i) - { - var entry = updateList.ElementAt(i); - - CurveWrapper curveWrapper = m_ActiveCurveWrappersCache[entry.Key]; - if (curveWrapper.renderer != null) - curveWrapper.renderer.FlushCache(); - - // Recreate curve wrapper only if curve has been modified. - m_ActiveCurveWrappersCache[entry.Key] = AnimationWindowUtility.GetCurveWrapper(entry.Value, entry.Value.clip); - } - } - - private void ReloadModifiedAnimationCurveCache() - { - for (int i = 0; i < allCurves.Count; ++i) - { - AnimationWindowCurve curve = allCurves[i]; - if (m_ModifiedCurves.Contains(curve.GetHashCode())) - curve.LoadKeyframes(curve.clip); - } - } - - // This is called when there is a new curve, but after the data refresh. - // This means that hierarchynodes and dopeline(s) for new curve are already available. - private void OnNewCurveAdded(EditorCurveBinding newCurve) - { - // Retrieve group property name. - // For example if we got "position.z" as our newCurve, - // the property will be "position" with three child child nodes x,y,z - string propertyName = newCurve.propertyName; - string groupPropertyName = AnimationWindowUtility.GetPropertyGroupName(newCurve.propertyName); - - if (hierarchyData == null) - return; - - if (HasHierarchySelection()) - { - // Update hierarchy selection with newly created curve. - foreach (AnimationWindowHierarchyNode node in hierarchyData.GetRows()) - { - if (node.path != newCurve.path || - node.animatableObjectType != newCurve.type || - (node.propertyName != propertyName && node.propertyName != groupPropertyName)) - continue; - - SelectHierarchyItem(node.id, true, false); - - // We want the pptr curves to be in tall mode by default - if (newCurve.isPPtrCurve) - hierarchyState.AddTallInstance(node.id); - } - } - - // Values do not change whenever a new curve is added, so we force an inspector update here. - controlInterface.ResampleAnimation(); - - m_lastAddedCurveBinding = null; - } - - public void Repaint() - { - if (animEditor != null) - animEditor.Repaint(); - } - - public List GetAggregateKeys(AnimationWindowHierarchyNode hierarchyNode) - { - DopeLine dopeline = dopelines.FirstOrDefault(e => e.hierarchyNodeID == hierarchyNode.id); - if (dopeline == null) - return null; - return dopeline.keys; - } - - public void OnHierarchySelectionChanged(int[] selectedInstanceIDs) - { - HandleHierarchySelectionChanged(selectedInstanceIDs, true); - } - - public void HandleHierarchySelectionChanged(int[] selectedInstanceIDs, bool triggerSceneSelectionSync) - { - m_ActiveCurvesCache = null; - - if (triggerSceneSelectionSync) - SyncSceneSelection(selectedInstanceIDs); - } - - public void SelectHierarchyItem(DopeLine dopeline, bool additive) - { - SelectHierarchyItem(dopeline.hierarchyNodeID, additive, true); - } - - public void SelectHierarchyItem(DopeLine dopeline, bool additive, bool triggerSceneSelectionSync) - { - SelectHierarchyItem(dopeline.hierarchyNodeID, additive, triggerSceneSelectionSync); - } - - public void SelectHierarchyItem(int hierarchyNodeID, bool additive, bool triggerSceneSelectionSync) - { - if (!additive) - ClearHierarchySelection(); - - hierarchyState.selectedIDs.Add(hierarchyNodeID); - - int[] selectedInstanceIDs = hierarchyState.selectedIDs.ToArray(); - - // We need to manually trigger this event, because injecting data to m_SelectedInstanceIDs directly doesn't trigger one via TreeView - HandleHierarchySelectionChanged(selectedInstanceIDs, triggerSceneSelectionSync); - } - - public void UnSelectHierarchyItem(DopeLine dopeline) - { - UnSelectHierarchyItem(dopeline.hierarchyNodeID); - } - - public void UnSelectHierarchyItem(int hierarchyNodeID) - { - hierarchyState.selectedIDs.Remove(hierarchyNodeID); - } - - public bool HasHierarchySelection() - { - if (hierarchyState.selectedIDs.Count == 0) - return false; - - if (hierarchyState.selectedIDs.Count == 1) - return (hierarchyState.selectedIDs[0] != 0); - - return true; - } - - public List GetAffectedHierarchyIDs(List keyframes) - { - List hierarchyIDs = new List(); - - foreach (DopeLine dopeline in GetAffectedDopelines(keyframes)) - if (!hierarchyIDs.Contains(dopeline.hierarchyNodeID)) - hierarchyIDs.Add(dopeline.hierarchyNodeID); - - return hierarchyIDs; - } - - public List GetAffectedDopelines(List keyframes) - { - List affectedDopelines = new List(); - - foreach (AnimationWindowCurve curve in GetAffectedCurves(keyframes)) - foreach (DopeLine dopeline in dopelines) - if (!affectedDopelines.Contains(dopeline) && dopeline.curves.Contains(curve)) - affectedDopelines.Add(dopeline); - - return affectedDopelines; - } - - public List GetAffectedCurves(List keyframes) - { - List affectedCurves = new List(); - - foreach (AnimationWindowKeyframe keyframe in keyframes) - if (!affectedCurves.Contains(keyframe.curve)) - affectedCurves.Add(keyframe.curve); - - return affectedCurves; - } - - public DopeLine GetDopeline(int selectedInstanceID) - { - foreach (var dopeline in dopelines) - { - if (dopeline.hierarchyNodeID == selectedInstanceID) - return dopeline; - } - - return null; - } - - // Set scene active go to be the same as the one selected from hierarchy - private void SyncSceneSelection(int[] selectedNodeIDs) - { - if (!selection.canSyncSceneSelection) - return; - - GameObject rootGameObject = selection.rootGameObject; - if (rootGameObject == null) - return; - - List selectedGameObjectIDs = new List(); - foreach (var selectedNodeID in selectedNodeIDs) - { - AnimationWindowHierarchyNode node = hierarchyData.FindItem(selectedNodeID) as AnimationWindowHierarchyNode; - - if (node == null) - continue; - - if (node is AnimationWindowHierarchyMasterNode) - continue; - - Transform t = rootGameObject.transform.Find(node.path); - - // In the case of nested animation component, we don't want to sync the scene selection (case 569506) - // When selection changes, animation window will always pick nearest animator component in terms of hierarchy depth - // 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 - - if (t != null && rootGameObject != null && activeAnimationPlayer == AnimationWindowUtility.GetClosestAnimationPlayerComponentInParents(t)) - selectedGameObjectIDs.Add(t.gameObject.GetInstanceID()); - } - - if (selectedGameObjectIDs.Count > 0) - UnityEditor.Selection.instanceIDs = selectedGameObjectIDs.ToArray(); - else - UnityEditor.Selection.activeGameObject = rootGameObject; - } - - public float clipFrameRate - { - get - { - if (activeAnimationClip == null) - return 60.0f; - return activeAnimationClip.frameRate; - } - set - { - // @TODO: Changing the clip in AnimationWindowState.frame rate feels a bit intrusive - // Should probably be done explicitly from the UI and not go through AnimationWindowState... - if (activeAnimationClip != null && value > 0 && value <= 10000) - { - // Clear selection and save empty selection snapshot for undo consistency. - ClearKeySelections(); - SaveKeySelection(kEditCurveUndoLabel); - - // Reposition all keyframes to match the new sampling rate - foreach (var curve in allCurves) - { - foreach (var key in curve.m_Keyframes) - { - int frame = AnimationKeyTime.Time(key.time, clipFrameRate).frame; - key.time = AnimationKeyTime.Frame(frame, value).time; - } - SaveCurve(curve, kEditCurveUndoLabel); - } - - AnimationEvent[] events = AnimationUtility.GetAnimationEvents(activeAnimationClip); - foreach (AnimationEvent ev in events) - { - int frame = AnimationKeyTime.Time(ev.time, clipFrameRate).frame; - ev.time = AnimationKeyTime.Frame(frame, value).time; - } - AnimationUtility.SetAnimationEvents(activeAnimationClip, events); - - activeAnimationClip.frameRate = value; - } - } - } - - public float frameRate - { - get - { - return m_FrameRate; - } - set - { - if (m_FrameRate != value) - { - m_FrameRate = value; - if (onFrameRateChange != null) - onFrameRateChange(m_FrameRate); - } - } - } - - public AnimationKeyTime time { get { return controlInterface.time; } } - public int currentFrame { get { return time.frame; } set { controlInterface.GoToFrame(value); } } - public float currentTime { get { return time.time; } set { controlInterface.GoToTime(value); } } - - public TimeArea.TimeFormat timeFormat { get { return m_TimeFormat; } set { m_TimeFormat = value; } } - - public TimeArea timeArea - { - get { return m_TimeArea; } - set { m_TimeArea = value; } - } - - // Pixel to time ratio (used for time-pixel conversions) - public float pixelPerSecond - { - get { return timeArea.m_Scale.x; } - } - - // The GUI x-coordinate, where time==0 (used for time-pixel conversions) - public float zeroTimePixel - { - get { return timeArea.shownArea.xMin * timeArea.m_Scale.x * -1f; } - } - - public float PixelToTime(float pixel) - { - return PixelToTime(pixel, SnapMode.Disabled); - } - - public float PixelToTime(float pixel, SnapMode snap) - { - float time = pixel - zeroTimePixel; - return SnapToFrame(time / pixelPerSecond, snap); - } - - public float TimeToPixel(float time) - { - return TimeToPixel(time, SnapMode.Disabled); - } - - public float TimeToPixel(float time, SnapMode snap) - { - return SnapToFrame(time, snap) * pixelPerSecond + zeroTimePixel; - } - - //@TODO: Move to animatkeytime?? - public float SnapToFrame(float time, SnapMode snap) - { - if (snap == SnapMode.Disabled) - return time; - - float fps = (snap == SnapMode.SnapToFrame) ? frameRate : clipFrameRate; - return SnapToFrame(time, fps); - } - - public float SnapToFrame(float time, float fps) - { - float snapTime = Mathf.Round(time * fps) / fps; - return snapTime; - } - - public float minVisibleTime { get { return m_TimeArea.shownArea.xMin; } } - public float maxVisibleTime { get { return m_TimeArea.shownArea.xMax; } } - public float visibleTimeSpan { get { return maxVisibleTime - minVisibleTime; } } - public float minVisibleFrame { get { return minVisibleTime * frameRate; } } - public float maxVisibleFrame { get { return maxVisibleTime * frameRate; } } - public float visibleFrameSpan { get { return visibleTimeSpan * frameRate; } } - public float minTime { get { return timeRange.x; } } - public float maxTime { get { return timeRange.y; } } - - public Vector2 timeRange - { - get - { - if (activeAnimationClip != null) - return new Vector2(activeAnimationClip.startTime, activeAnimationClip.stopTime); - - return Vector2.zero; - } - } - - public string FormatFrame(int frame, int frameDigits) - { - return (frame / (int)frameRate).ToString() + ":" + (frame % frameRate).ToString().PadLeft(frameDigits, '0'); - } - - //@TODO: Remove. Replace with animationkeytime - public float TimeToFrame(float time) - { - return time * frameRate; - } - - //@TODO: Remove. Replace with animationkeytime - public float FrameToTime(float frame) - { - return frame / frameRate; - } - - public int TimeToFrameFloor(float time) - { - return Mathf.FloorToInt(TimeToFrame(time)); - } - - public int TimeToFrameRound(float time) - { - return Mathf.RoundToInt(TimeToFrame(time)); - } - - public float FrameToPixel(float i, Rect rect) - { - return (i - minVisibleFrame) * rect.width / visibleFrameSpan; - } - - public float FrameDeltaToPixel(Rect rect) - { - return rect.width / visibleFrameSpan; - } - - public float TimeToPixel(float time, Rect rect) - { - return FrameToPixel(time * frameRate, rect); - } - - public float PixelToTime(float pixelX, Rect rect) - { - return (pixelX * visibleTimeSpan / rect.width + minVisibleTime); - } - - public float PixelDeltaToTime(Rect rect) - { - return visibleTimeSpan / rect.width; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowStyles.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowStyles.cs deleted file mode 100644 index 71d7d600d3..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowStyles.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class AnimationWindowStyles - { - public static Texture2D pointIcon = EditorGUIUtility.LoadIcon("animationkeyframe"); - - public static GUIContent playContent = EditorGUIUtility.TrIconContent("Animation.Play", "Play the animation clip."); - public static GUIContent recordContent = EditorGUIUtility.TrIconContent("Animation.Record", "Enable/disable keyframe recording mode."); - public static GUIContent previewContent = EditorGUIUtility.TrTextContent("Preview", "Enable/disable scene preview mode."); - public static GUIContent prevKeyContent = EditorGUIUtility.TrIconContent("Animation.PrevKey", "Go to previous keyframe."); - public static GUIContent nextKeyContent = EditorGUIUtility.TrIconContent("Animation.NextKey", "Go to next keyframe."); - public static GUIContent firstKeyContent = EditorGUIUtility.TrIconContent("Animation.FirstKey", "Go to the beginning of the animation clip."); - public static GUIContent lastKeyContent = EditorGUIUtility.TrIconContent("Animation.LastKey", "Go to the end of the animation clip."); - public static GUIContent addKeyframeContent = EditorGUIUtility.TrIconContent("Animation.AddKeyframe", "Add keyframe."); - public static GUIContent addEventContent = EditorGUIUtility.TrIconContent("Animation.AddEvent", "Add event."); - public static GUIContent sequencerLinkContent = EditorGUIUtility.TrIconContent("Animation.SequencerLink", "Animation Window is linked to Sequence Editor. Press to Unlink."); - - public static GUIContent noAnimatableObjectSelectedText = EditorGUIUtility.TrTextContent("No animatable object selected."); - public static GUIContent formatIsMissing = EditorGUIUtility.TrTextContent("To begin animating {0}, create {1}."); - public static GUIContent animatorAndAnimationClip = EditorGUIUtility.TrTextContent("an Animator and an Animation Clip"); - public static GUIContent animationClip = EditorGUIUtility.TrTextContent("an Animation Clip"); - public static GUIContent create = EditorGUIUtility.TrTextContent("Create"); - public static GUIContent dopesheet = EditorGUIUtility.TrTextContent("Dopesheet"); - public static GUIContent curves = EditorGUIUtility.TrTextContent("Curves"); - public static GUIContent samples = EditorGUIUtility.TrTextContent("Samples"); - public static GUIContent createNewClip = EditorGUIUtility.TrTextContent("Create New Clip..."); - - 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."); - - public static GUIStyle playHead = "AnimationPlayHead"; - - public static GUIStyle curveEditorBackground = "CurveEditorBackground"; - public static GUIStyle curveEditorLabelTickmarks = "CurveEditorLabelTickmarks"; - public static GUIStyle eventBackground = "AnimationEventBackground"; - public static GUIStyle eventTooltip = "AnimationEventTooltip"; - public static GUIStyle eventTooltipArrow = "AnimationEventTooltipArrow"; - public static GUIStyle keyframeBackground = "AnimationKeyframeBackground"; - public static GUIStyle timelineTick = "AnimationTimelineTick"; - public static GUIStyle dopeSheetKeyframe = "Dopesheetkeyframe"; - public static GUIStyle dopeSheetBackground = "DopesheetBackground"; - public static GUIStyle popupCurveDropdown = "PopupCurveDropdown"; - public static GUIStyle popupCurveEditorBackground = "PopupCurveEditorBackground"; - public static GUIStyle popupCurveEditorSwatch = "PopupCurveEditorSwatch"; - public static GUIStyle popupCurveSwatchBackground = "PopupCurveSwatchBackground"; - - public static GUIStyle miniToolbar = new GUIStyle(EditorStyles.toolbar); - public static GUIStyle miniToolbarButton = new GUIStyle(EditorStyles.toolbarButton); - public static GUIStyle toolbarLabel = new GUIStyle(EditorStyles.toolbarPopup); - - public static void Initialize() - { - toolbarLabel.normal.background = null; - miniToolbarButton.padding.top = 0; - miniToolbarButton.padding.bottom = 3; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs deleted file mode 100644 index 85a36c806c..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs +++ /dev/null @@ -1,1202 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.IO; -using System.Collections.Generic; -using UnityEditor; -using UnityEditor.Animations; -using UnityEngine; -using Object = UnityEngine.Object; - -using TangentMode = UnityEditor.AnimationUtility.TangentMode; - -namespace UnityEditorInternal -{ - static internal class AnimationWindowUtility - { - public static void CreateDefaultCurves(AnimationWindowState state, EditorCurveBinding[] properties) - { - properties = RotationCurveInterpolation.ConvertRotationPropertiesToDefaultInterpolation(state.activeAnimationClip, properties); - foreach (EditorCurveBinding prop in properties) - state.SaveCurve(CreateDefaultCurve(state, prop)); - } - - public static AnimationWindowCurve CreateDefaultCurve(AnimationWindowState state, EditorCurveBinding binding) - { - AnimationClip animationClip = state.activeAnimationClip; - Type type = state.selection.GetEditorCurveValueType(binding); - - AnimationWindowCurve curve = new AnimationWindowCurve(animationClip, binding, type); - - object currentValue = CurveBindingUtility.GetCurrentValue(state.activeRootGameObject, binding); - if (animationClip.length == 0.0F) - { - AddKeyframeToCurve(curve, currentValue, type, AnimationKeyTime.Time(0.0F, animationClip.frameRate)); - } - else - { - AddKeyframeToCurve(curve, currentValue, type, AnimationKeyTime.Time(0.0F, animationClip.frameRate)); - AddKeyframeToCurve(curve, currentValue, type, AnimationKeyTime.Time(animationClip.length, animationClip.frameRate)); - } - - return curve; - } - - public static bool ShouldShowAnimationWindowCurve(EditorCurveBinding curveBinding) - { - // We don't want to convert the w component of rotation curves to be shown in animation window - if (IsTransformType(curveBinding.type)) - return !curveBinding.propertyName.EndsWith(".w"); - - return true; - } - - public static bool IsNodeLeftOverCurve(AnimationWindowHierarchyNode node) - { - if (node.binding != null) - { - if (node.curves.Length > 0) - { - AnimationWindowSelectionItem selectionBinding = node.curves[0].selectionBinding; - if (selectionBinding != null) - { - if (selectionBinding.rootGameObject == null && selectionBinding.scriptableObject == null) - return false; - - return selectionBinding.GetEditorCurveValueType((EditorCurveBinding)node.binding) == null; - } - } - } - - // Go through all child nodes recursively - if (node.hasChildren) - { - foreach (var child in node.children) - return IsNodeLeftOverCurve(child as AnimationWindowHierarchyNode); - } - - return false; - } - - public static bool IsNodeAmbiguous(AnimationWindowHierarchyNode node) - { - if (node.binding != null) - { - if (node.curves.Length > 0) - { - AnimationWindowSelectionItem selectionBinding = node.curves[0].selectionBinding; - if (selectionBinding != null) - { - if (selectionBinding.rootGameObject != null) - return AnimationUtility.AmbiguousBinding(node.binding.Value.path, node.binding.Value.m_ClassID, selectionBinding.rootGameObject.transform); - } - } - } - - // Go through all child nodes recursively - if (node.hasChildren) - { - foreach (var child in node.children) - return IsNodeAmbiguous(child as AnimationWindowHierarchyNode); - } - - return false; - } - - public static bool IsNodePhantom(AnimationWindowHierarchyNode node) - { - if (node.binding != null) - return node.binding.Value.isPhantom; - - return false; - } - - public static void AddSelectedKeyframes(AnimationWindowState state, AnimationKeyTime time) - { - List curves = state.activeCurves.Count > 0 ? state.activeCurves : state.allCurves; - AddKeyframes(state, curves.ToArray(), time); - } - - public static void AddKeyframes(AnimationWindowState state, AnimationWindowCurve[] curves, AnimationKeyTime time) - { - string undoLabel = "Add Key"; - state.SaveKeySelection(undoLabel); - - state.ClearKeySelections(); - - foreach (AnimationWindowCurve curve in curves) - { - if (!curve.animationIsEditable) - continue; - - AnimationKeyTime shiftedMouseKeyTime = AnimationKeyTime.Time(time.time, time.frameRate); - - object value = CurveBindingUtility.GetCurrentValue(state, curve); - AnimationWindowKeyframe keyframe = AnimationWindowUtility.AddKeyframeToCurve(curve, value, curve.valueType, shiftedMouseKeyTime); - - if (keyframe != null) - { - state.SaveCurve(curve, undoLabel); - state.SelectKey(keyframe); - } - } - } - - public static void RemoveKeyframes(AnimationWindowState state, AnimationWindowCurve[] curves, AnimationKeyTime time) - { - string undoLabel = "Remove Key"; - state.SaveKeySelection(undoLabel); - - foreach (AnimationWindowCurve curve in curves) - { - if (!curve.animationIsEditable) - continue; - - curve.RemoveKeyframe(time); - - state.SaveCurve(curve, undoLabel); - } - } - - public static AnimationWindowKeyframe AddKeyframeToCurve(AnimationWindowCurve curve, object value, Type type, AnimationKeyTime time) - { - // When there is already a key a this time - // Make sure that only value is updated but tangents are maintained. - AnimationWindowKeyframe previousKey = curve.FindKeyAtTime(time); - if (previousKey != null) - { - previousKey.value = value; - return previousKey; - } - - AnimationWindowKeyframe keyframe = null; - - if (curve.isPPtrCurve) - { - keyframe = new AnimationWindowKeyframe(); - - keyframe.time = time.time; - keyframe.value = value; - keyframe.curve = curve; - curve.AddKeyframe(keyframe, time); - } - else if (type == typeof(bool) || type == typeof(float) || type == typeof(int)) - { - Keyframe tempKey = new Keyframe(time.time, (float)value); - if (type == typeof(bool) || type == typeof(int)) - { - if (type == typeof(int) && !curve.isDiscreteCurve) - { - AnimationUtility.SetKeyLeftTangentMode(ref tempKey, TangentMode.Linear); - AnimationUtility.SetKeyRightTangentMode(ref tempKey, TangentMode.Linear); - } - else - { - AnimationUtility.SetKeyLeftTangentMode(ref tempKey, TangentMode.Constant); - AnimationUtility.SetKeyRightTangentMode(ref tempKey, TangentMode.Constant); - } - - AnimationUtility.SetKeyBroken(ref tempKey, true); - } - else - { - // Create temporary curve for getting proper tangents - AnimationCurve animationCurve = curve.ToAnimationCurve(); - - int keyIndex = animationCurve.AddKey(tempKey); - if (keyIndex != -1) - { - // Make sure tangent slopes default to ClampedAuto. Tangent mode will be modified afterwards. - AnimationUtility.SetKeyLeftTangentMode(animationCurve, keyIndex, TangentMode.ClampedAuto); - AnimationUtility.SetKeyRightTangentMode(animationCurve, keyIndex, TangentMode.ClampedAuto); - AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyIndex); - - CurveUtility.SetKeyModeFromContext(animationCurve, keyIndex); - - tempKey = animationCurve[keyIndex]; - } - } - - keyframe = new AnimationWindowKeyframe(curve, tempKey); - curve.AddKeyframe(keyframe, time); - } - - return keyframe; - } - - public static List FilterCurves(AnimationWindowCurve[] curves, string path, bool entireHierarchy) - { - List results = new List(); - - if (curves != null) - { - foreach (AnimationWindowCurve curve in curves) - if (curve.path.Equals(path) || (entireHierarchy && curve.path.Contains(path))) - results.Add(curve); - } - - return results; - } - - public static List FilterCurves(AnimationWindowCurve[] curves, string path, Type animatableObjectType) - { - List results = new List(); - - if (curves != null) - { - foreach (AnimationWindowCurve curve in curves) - if (curve.path.Equals(path) && curve.type == animatableObjectType) - results.Add(curve); - } - - return results; - } - - public static bool IsCurveCreated(AnimationClip clip, EditorCurveBinding binding) - { - if (binding.isPPtrCurve) - { - return AnimationUtility.GetObjectReferenceCurve(clip, binding) != null; - } - else - { - // For RectTransform.position we only want .z - if (IsRectTransformPosition(binding)) - binding.propertyName = binding.propertyName.Replace(".x", ".z").Replace(".y", ".z"); - if (IsRotationCurve(binding)) - { - return AnimationUtility.GetEditorCurve(clip, binding) != null || HasOtherRotationCurve(clip, binding); - } - - return AnimationUtility.GetEditorCurve(clip, binding) != null; - } - } - - internal static bool HasOtherRotationCurve(AnimationClip clip, EditorCurveBinding rotationBinding) - { - if (rotationBinding.propertyName.StartsWith("m_LocalRotation")) - { - EditorCurveBinding x = rotationBinding; - EditorCurveBinding y = rotationBinding; - EditorCurveBinding z = rotationBinding; - x.propertyName = "localEulerAnglesRaw.x"; - y.propertyName = "localEulerAnglesRaw.y"; - z.propertyName = "localEulerAnglesRaw.z"; - - return AnimationUtility.GetEditorCurve(clip, x) != null || - AnimationUtility.GetEditorCurve(clip, y) != null || - AnimationUtility.GetEditorCurve(clip, z) != null; - } - else - { - EditorCurveBinding x = rotationBinding; - EditorCurveBinding y = rotationBinding; - EditorCurveBinding z = rotationBinding; - EditorCurveBinding w = rotationBinding; - - x.propertyName = "m_LocalRotation.x"; - y.propertyName = "m_LocalRotation.y"; - z.propertyName = "m_LocalRotation.z"; - w.propertyName = "m_LocalRotation.w"; - - return AnimationUtility.GetEditorCurve(clip, x) != null || - AnimationUtility.GetEditorCurve(clip, y) != null || - AnimationUtility.GetEditorCurve(clip, z) != null || - AnimationUtility.GetEditorCurve(clip, w) != null; - } - } - - internal static bool IsRotationCurve(EditorCurveBinding curveBinding) - { - string propertyName = GetPropertyGroupName(curveBinding.propertyName); - return propertyName == "m_LocalRotation" || propertyName == "localEulerAnglesRaw"; - } - - public static bool IsRectTransformPosition(EditorCurveBinding curveBinding) - { - return curveBinding.type == typeof(RectTransform) && GetPropertyGroupName(curveBinding.propertyName) == "m_LocalPosition"; - } - - public static bool ContainsFloatKeyframes(List keyframes) - { - if (keyframes == null || keyframes.Count == 0) - return false; - - foreach (var key in keyframes) - { - if (!key.isPPtrCurve) - return true; - } - - return false; - } - - // Get curves for property or propertygroup (example: x,y,z) - public static List FilterCurves(AnimationWindowCurve[] curves, string path, Type animatableObjectType, string propertyName) - { - List results = new List(); - - if (curves != null) - { - string propertyGroupName = GetPropertyGroupName(propertyName); - bool isPropertyGroup = propertyGroupName == propertyName; - - foreach (AnimationWindowCurve curve in curves) - { - bool propertyNameMatches = isPropertyGroup ? GetPropertyGroupName(curve.propertyName).Equals(propertyGroupName) : curve.propertyName.Equals(propertyName); - if (curve.path.Equals(path) && curve.type == animatableObjectType && propertyNameMatches) - results.Add(curve); - } - } - - return results; - } - - // Current value of the property that rootGO + curveBinding is pointing to - public static object GetCurrentValue(GameObject rootGameObject, EditorCurveBinding curveBinding) - { - if (curveBinding.isPPtrCurve) - { - Object value; - AnimationUtility.GetObjectReferenceValue(rootGameObject, curveBinding, out value); - return value; - } - else - { - float value; - AnimationUtility.GetFloatValue(rootGameObject, curveBinding, out value); - return value; - } - } - - public static List GetAnimatableProperties(GameObject gameObject, GameObject root, Type valueType) - { - EditorCurveBinding[] animatable = AnimationUtility.GetAnimatableBindings(gameObject, root); - - List result = new List(); - foreach (EditorCurveBinding binding in animatable) - if (AnimationUtility.GetEditorCurveValueType(root, binding) == valueType) - result.Add(binding); - - return result; - } - - public static List GetAnimatableProperties(GameObject gameObject, GameObject root, Type objectType, Type valueType) - { - EditorCurveBinding[] animatable = AnimationUtility.GetAnimatableBindings(gameObject, root); - - List result = new List(); - foreach (EditorCurveBinding binding in animatable) - if (binding.type == objectType && AnimationUtility.GetEditorCurveValueType(root, binding) == valueType) - result.Add(binding); - - return result; - } - - public static List GetAnimatableProperties(ScriptableObject scriptableObject, Type valueType) - { - EditorCurveBinding[] animatable = AnimationUtility.GetAnimatableBindings(scriptableObject); - - List result = new List(); - foreach (EditorCurveBinding binding in animatable) - if (AnimationUtility.GetEditorCurveValueType(scriptableObject, binding) == valueType) - result.Add(binding); - - return result; - } - - public static bool PropertyIsAnimatable(Object targetObject, string propertyPath, Object rootObject) - { - if (targetObject is ScriptableObject) - { - ScriptableObject scriptableObject = (ScriptableObject)targetObject; - EditorCurveBinding[] allCurveBindings = AnimationUtility.GetAnimatableBindings(scriptableObject); - return Array.Exists(allCurveBindings, binding => binding.propertyName == propertyPath); - } - else - { - GameObject gameObject = targetObject as GameObject; - if (targetObject is Component) - gameObject = ((Component)targetObject).gameObject; - - if (gameObject != null) - { - var dummyModification = new PropertyModification(); - dummyModification.propertyPath = propertyPath; - dummyModification.target = targetObject; - - EditorCurveBinding binding = new EditorCurveBinding(); - return AnimationUtility.PropertyModificationToEditorCurveBinding(dummyModification, rootObject == null ? gameObject : (GameObject)rootObject, out binding) != null; - } - } - - return false; - } - - // Given a serialized property, gathers all animateable properties - public static PropertyModification[] SerializedPropertyToPropertyModifications(SerializedProperty property) - { - List properties = new List(); - - properties.Add(property); - - // handles child properties (Vector3 is 3 recordable properties) - if (property.hasChildren) - { - var iter = property.Copy(); - var end = property.GetEndProperty(false); - - // recurse over all children properties - while (iter.Next(true) && !SerializedProperty.EqualContents(iter, end) && iter.propertyPath.StartsWith(property.propertyPath)) - { - properties.Add(iter.Copy()); - } - } - - // Special case for m_LocalRotation... - if (property.propertyPath.StartsWith("m_LocalRotation")) - { - var serializedObject = property.serializedObject; - if (serializedObject.targetObject is Transform) - { - SerializedProperty eulerHintProperty = serializedObject.FindProperty("m_LocalEulerAnglesHint"); - if (eulerHintProperty != null && eulerHintProperty.hasChildren) - { - var iter = eulerHintProperty.Copy(); - var end = eulerHintProperty.GetEndProperty(false); - - // recurse over all children properties - while (iter.Next(true) && !SerializedProperty.EqualContents(iter, end) && iter.propertyPath.StartsWith(eulerHintProperty.propertyPath)) - { - properties.Add(iter.Copy()); - } - } - } - } - - List modifications = new List(); - - for (int i = 0; i < properties.Count; ++i) - { - var propertyIter = properties[i]; - var isObject = propertyIter.propertyType == SerializedPropertyType.ObjectReference; - var isFloat = propertyIter.propertyType == SerializedPropertyType.Float; - var isBool = propertyIter.propertyType == SerializedPropertyType.Boolean; - var isInt = propertyIter.propertyType == SerializedPropertyType.Integer; - var isEnum = propertyIter.propertyType == SerializedPropertyType.Enum; - - if (isObject || isFloat || isBool || isInt || isEnum) - { - var serializedObject = propertyIter.serializedObject; - var targetObjects = serializedObject.targetObjects; - - if (propertyIter.hasMultipleDifferentValues) - { - for (int j = 0; j < targetObjects.Length; ++j) - { - var singleObject = new SerializedObject(targetObjects[j]); - SerializedProperty singleProperty = singleObject.FindProperty(propertyIter.propertyPath); - - string value = string.Empty; - Object objectReference = null; - - if (isObject) - objectReference = singleProperty.objectReferenceValue; - else if (isFloat) - value = singleProperty.floatValue.ToString(); - else if (isInt) - value = singleProperty.intValue.ToString(); - else if (isEnum) - value = singleProperty.enumValueIndex.ToString(); - else // if (isBool) - value = singleProperty.boolValue ? "1" : "0"; - - var modification = new PropertyModification(); - - modification.target = targetObjects[j]; - modification.propertyPath = singleProperty.propertyPath; - modification.value = value; - modification.objectReference = objectReference; - modifications.Add(modification); - } - } - // fast path - else - { - string value = string.Empty; - Object objectReference = null; - - if (isObject) - objectReference = propertyIter.objectReferenceValue; - else if (isFloat) - value = propertyIter.floatValue.ToString(); - else if (isInt) - value = propertyIter.intValue.ToString(); - else // if (isBool) - value = propertyIter.boolValue ? "1" : "0"; - - for (int j = 0; j < targetObjects.Length; ++j) - { - var modification = new PropertyModification(); - - modification.target = targetObjects[j]; - modification.propertyPath = propertyIter.propertyPath; - modification.value = value; - modification.objectReference = objectReference; - modifications.Add(modification); - } - } - } - } - - return modifications.ToArray(); - } - - public static EditorCurveBinding[] PropertyModificationsToEditorCurveBindings(PropertyModification[] modifications, GameObject rootGameObject, AnimationClip animationClip) - { - if (modifications == null) - return new EditorCurveBinding[] {}; - - var bindings = new HashSet(); - - for (int i = 0; i < modifications.Length; ++i) - { - var binding = new EditorCurveBinding(); - if (AnimationUtility.PropertyModificationToEditorCurveBinding(modifications[i], rootGameObject, out binding) != null) - { - EditorCurveBinding[] additionalBindings = RotationCurveInterpolation.RemapAnimationBindingForAddKey(binding, animationClip); - if (additionalBindings != null) - { - for (int j = 0; j < additionalBindings.Length; ++j) - { - bindings.Add(additionalBindings[j]); - } - } - else - { - bindings.Add(binding); - } - } - } - - return bindings.ToArray(); - } - - public static EditorCurveBinding[] SerializedPropertyToEditorCurveBindings(SerializedProperty property, GameObject rootGameObject, AnimationClip animationClip) - { - PropertyModification[] modifications = AnimationWindowUtility.SerializedPropertyToPropertyModifications(property); - return PropertyModificationsToEditorCurveBindings(modifications, rootGameObject, animationClip); - } - - public static bool CurveExists(EditorCurveBinding binding, AnimationWindowCurve[] curves) - { - foreach (var animationWindowCurve in curves) - { - if (binding.propertyName == animationWindowCurve.binding.propertyName && - binding.type == animationWindowCurve.binding.type && - binding.path == animationWindowCurve.binding.path) - return true; - } - return false; - } - - public static EditorCurveBinding GetRenamedBinding(EditorCurveBinding binding, string newPath) - { - EditorCurveBinding newBinding = new EditorCurveBinding(); - newBinding.path = newPath; - newBinding.propertyName = binding.propertyName; - newBinding.type = binding.type; - return newBinding; - } - - public static void RenameCurvePath(AnimationWindowCurve curve, EditorCurveBinding newBinding, AnimationClip clip) - { - if (curve.isPPtrCurve) - { - // Delete old curve - AnimationUtility.SetObjectReferenceCurve(clip, curve.binding, null); - - // Add new curve - AnimationUtility.SetObjectReferenceCurve(clip, newBinding, curve.ToObjectCurve()); - } - else - { - // Delete old curve - AnimationUtility.SetEditorCurve(clip, curve.binding, null); - - // Add new curve - AnimationUtility.SetEditorCurve(clip, newBinding, curve.ToAnimationCurve()); - } - } - - // Takes raw animation curve propertyname and makes it pretty - public static string GetPropertyDisplayName(string propertyName) - { - propertyName = propertyName.Replace("m_LocalPosition", "Position"); - propertyName = propertyName.Replace("m_LocalScale", "Scale"); - propertyName = propertyName.Replace("m_LocalRotation", "Rotation"); - propertyName = propertyName.Replace("localEulerAnglesBaked", "Rotation"); - propertyName = propertyName.Replace("localEulerAnglesRaw", "Rotation"); - propertyName = propertyName.Replace("localEulerAngles", "Rotation"); - propertyName = propertyName.Replace("m_Materials.Array.data", "Material Reference"); - - propertyName = ObjectNames.NicifyVariableName(propertyName); - propertyName = propertyName.Replace("m_", ""); - - return propertyName; - } - - // Transform and Sprite: just show Position / Rotation / Scale / Sprite - public static bool ShouldPrefixWithTypeName(Type animatableObjectType, string propertyName) - { - if (animatableObjectType == typeof(Transform) || animatableObjectType == typeof(RectTransform)) - return false; - - if (animatableObjectType == typeof(SpriteRenderer) && propertyName == "m_Sprite") - return false; - - return true; - } - - public static string GetNicePropertyDisplayName(Type animatableObjectType, string propertyName) - { - if (ShouldPrefixWithTypeName(animatableObjectType, propertyName)) - return ObjectNames.NicifyVariableName(animatableObjectType.Name) + "." + GetPropertyDisplayName(propertyName); - else - return GetPropertyDisplayName(propertyName); - } - - public static string GetNicePropertyGroupDisplayName(Type animatableObjectType, string propertyGroupName) - { - if (ShouldPrefixWithTypeName(animatableObjectType, propertyGroupName)) - return ObjectNames.NicifyVariableName(animatableObjectType.Name) + "." + NicifyPropertyGroupName(animatableObjectType, propertyGroupName); - else - return NicifyPropertyGroupName(animatableObjectType, propertyGroupName); - } - - // Takes raw animation curve propertyname and returns a pretty groupname - public static string NicifyPropertyGroupName(Type animatableObjectType, string propertyGroupName) - { - string result = GetPropertyGroupName(GetPropertyDisplayName(propertyGroupName)); - - // Workaround for uGUI RectTransform which only animates position.z - if (animatableObjectType == typeof(RectTransform) & result.Equals("Position")) - result = "Position (Z)"; - - return result; - } - - // We automatically group Vector4, Vector3 and Color - static public int GetComponentIndex(string name) - { - if (name == null || name.Length < 3 || name[name.Length - 2] != '.') - return -1; - char lastCharacter = name[name.Length - 1]; - switch (lastCharacter) - { - case 'r': - return 0; - case 'g': - return 1; - case 'b': - return 2; - case 'a': - return 3; - case 'x': - return 0; - case 'y': - return 1; - case 'z': - return 2; - case 'w': - return 3; - default: - return -1; - } - } - - // If Vector4, Vector3 or Color, return group name instead of full name - public static string GetPropertyGroupName(string propertyName) - { - if (GetComponentIndex(propertyName) != -1) - return propertyName.Substring(0, propertyName.Length - 2); - - return propertyName; - } - - public static float GetNextKeyframeTime(AnimationWindowCurve[] curves, float currentTime, float frameRate) - { - float candidate = float.MaxValue; - AnimationKeyTime time = AnimationKeyTime.Time(currentTime, frameRate); - AnimationKeyTime nextTime = AnimationKeyTime.Frame(time.frame + 1, frameRate); - - bool found = false; - - foreach (AnimationWindowCurve curve in curves) - { - foreach (AnimationWindowKeyframe keyframe in curve.m_Keyframes) - { - if (keyframe.time < candidate && keyframe.time >= nextTime.time) - { - candidate = keyframe.time; - found = true; - } - } - } - return found ? candidate : time.time; - } - - public static float GetPreviousKeyframeTime(AnimationWindowCurve[] curves, float currentTime, float frameRate) - { - float candidate = float.MinValue; - AnimationKeyTime time = AnimationKeyTime.Time(currentTime, frameRate); - AnimationKeyTime previousTime = AnimationKeyTime.Frame(time.frame - 1, frameRate); - - bool found = false; - - foreach (AnimationWindowCurve curve in curves) - { - foreach (AnimationWindowKeyframe keyframe in curve.m_Keyframes) - { - if (keyframe.time > candidate && keyframe.time <= previousTime.time) - { - candidate = keyframe.time; - found = true; - } - } - } - return found ? candidate : time.time; - } - - // Add animator, controller and clip to gameobject if they are missing to make this gameobject animatable - public static bool InitializeGameobjectForAnimation(GameObject animatedObject) - { - Component animationPlayer = GetClosestAnimationPlayerComponentInParents(animatedObject.transform); - if (animationPlayer == null) - { - var newClip = CreateNewClip(animatedObject.name); - - if (newClip == null) - return false; - - animationPlayer = EnsureActiveAnimationPlayer(animatedObject); - bool success = AddClipToAnimationPlayerComponent(animationPlayer, newClip); - - if (!success) - Object.DestroyImmediate(animationPlayer); - - return success; - } - - return EnsureAnimationPlayerHasClip(animationPlayer); - } - - // Ensures that the gameobject or it's parents have an animation player component. If not try to create one. - public static Component EnsureActiveAnimationPlayer(GameObject animatedObject) - { - Component closestAnimator = GetClosestAnimationPlayerComponentInParents(animatedObject.transform); - if (closestAnimator == null) - { - return Undo.AddComponent(animatedObject); - } - return closestAnimator; - } - - // Ensures that animator has atleast one clip and controller to go with it - private static bool EnsureAnimationPlayerHasClip(Component animationPlayer) - { - if (animationPlayer == null) - return false; - - if (AnimationUtility.GetAnimationClips(animationPlayer.gameObject).Length > 0) - return true; - - // At this point we know that we can create a clip - var newClip = CreateNewClip(animationPlayer.gameObject.name); - - if (newClip == null) - return false; - - // End animation mode before adding or changing animation component to object - AnimationMode.StopAnimationMode(); - - // By default add it the animation to the Animator component. - return AddClipToAnimationPlayerComponent(animationPlayer, newClip); - } - - public static bool AddClipToAnimationPlayerComponent(Component animationPlayer, AnimationClip newClip) - { - if (animationPlayer is Animator) - return AddClipToAnimatorComponent(animationPlayer as Animator, newClip); - else if (animationPlayer is Animation) - return AddClipToAnimationComponent(animationPlayer as Animation, newClip); - return false; - } - - public static bool AddClipToAnimatorComponent(Animator animator, AnimationClip newClip) - { - UnityEditor.Animations.AnimatorController controller = UnityEditor.Animations.AnimatorController.GetEffectiveAnimatorController(animator); - if (controller == null) - { - controller = UnityEditor.Animations.AnimatorController.CreateAnimatorControllerForClip(newClip, animator.gameObject); - UnityEditor.Animations.AnimatorController.SetAnimatorController(animator, controller); - - if (controller != null) - return true; - } - else - { - // Do we already have a state with the clips name? - ChildAnimatorState childAnimatorState = controller.layers[0].stateMachine.FindState(newClip.name); - - if (childAnimatorState.Equals(default(ChildAnimatorState))) - controller.AddMotion(newClip); - - // Assign clip if state already present, but without a motion - else if (childAnimatorState.state && childAnimatorState.state.motion == null) - childAnimatorState.state.motion = newClip; - - // State present, but with some other clip - else if (childAnimatorState.state && childAnimatorState.state.motion != newClip) - controller.AddMotion(newClip); - - return true; - } - return false; - } - - public static bool AddClipToAnimationComponent(Animation animation, AnimationClip newClip) - { - SetClipAsLegacy(newClip); - animation.AddClip(newClip, newClip.name); - return true; - } - - internal static string s_LastPathUsedForNewClip; - internal static AnimationClip CreateNewClip(string gameObjectName) - { - // Go forward with presenting user a save clip dialog - string message = string.Format("Create a new animation for the game object '{0}':", gameObjectName); - string newClipDirectory = ProjectWindowUtil.GetActiveFolderPath(); - if (s_LastPathUsedForNewClip != null) - { - string directoryPath = Path.GetDirectoryName(s_LastPathUsedForNewClip); - if (directoryPath != null && Directory.Exists(directoryPath)) - { - newClipDirectory = directoryPath; - } - } - string newClipPath = EditorUtility.SaveFilePanelInProject("Create New Animation", "New Animation", "anim", message, newClipDirectory); - - // If user canceled or save path is invalid, we can't create a clip - if (newClipPath == "") - return null; - - return CreateNewClipAtPath(newClipPath); - } - - // Create a new animation clip asset for gameObject at a certain asset path. - // The clipPath parameter must be a full asset path ending with '.anim'. e.g. "Assets/Animations/New Clip.anim" - // This function will overwrite existing .anim files. - internal static AnimationClip CreateNewClipAtPath(string clipPath) - { - s_LastPathUsedForNewClip = clipPath; - - var newClip = new AnimationClip(); - - var info = AnimationUtility.GetAnimationClipSettings(newClip); - info.loopTime = true; - AnimationUtility.SetAnimationClipSettingsNoDirty(newClip, info); - - AnimationClip asset = AssetDatabase.LoadMainAssetAtPath(clipPath) as AnimationClip; - - if (asset) - { - EditorUtility.CopySerialized(newClip, asset); - AssetDatabase.SaveAssets(); - Object.DestroyImmediate(newClip); - return asset; - } - - AssetDatabase.CreateAsset(newClip, clipPath); - return newClip; - } - - private static void SetClipAsLegacy(AnimationClip clip) - { - SerializedObject s = new SerializedObject(clip); - s.FindProperty("m_Legacy").boolValue = true; - s.ApplyModifiedProperties(); - } - - internal static AnimationClip AllocateAndSetupClip(bool useAnimator) - { - // At this point we know that we can create a clip - AnimationClip newClip = new AnimationClip(); - if (useAnimator) - { - AnimationClipSettings info = AnimationUtility.GetAnimationClipSettings(newClip); - info.loopTime = true; - AnimationUtility.SetAnimationClipSettingsNoDirty(newClip, info); - } - return newClip; - } - - public static int GetPropertyNodeID(int setId, string path, System.Type type, string propertyName) - { - return (setId.ToString() + path + type.Name + propertyName).GetHashCode(); - } - - // What is the first animation player component (Animator or Animation) when recursing parent tree toward root - public static Component GetClosestAnimationPlayerComponentInParents(Transform tr) - { - Animator animator = GetClosestAnimatorInParents(tr); - if (animator != null) - return animator; - Animation animation = GetClosestAnimationInParents(tr); - if (animation != null) - return animation; - return null; - } - - // What is the first animator component when recursing parent tree toward root - public static Animator GetClosestAnimatorInParents(Transform tr) - { - while (true) - { - if (tr.GetComponent() != null) return tr.GetComponent(); - if (tr == tr.root) break; - tr = tr.parent; - } - return null; - } - - // What is the first animation component when recursing parent tree toward root - public static Animation GetClosestAnimationInParents(Transform tr) - { - while (true) - { - if (tr.GetComponent() != null) return tr.GetComponent(); - if (tr == tr.root) break; - tr = tr.parent; - } - return null; - } - - public static void SyncTimeArea(TimeArea from, TimeArea to) - { - to.SetDrawRectHack(from.drawRect); - to.m_Scale = new Vector2(from.m_Scale.x, to.m_Scale.y); - to.m_Translation = new Vector2(from.m_Translation.x, to.m_Translation.y); - to.EnforceScaleAndRange(); - } - - public static void DrawInRangeOverlay(Rect rect, Color color, float startOfClipPixel, float endOfClipPixel) - { - // Rect shaded shape drawn inside range - if (endOfClipPixel >= rect.xMin) - { - if (color.a > 0f) - { - Rect inRect = Rect.MinMaxRect(Mathf.Max(startOfClipPixel, rect.xMin), rect.yMin, Mathf.Min(endOfClipPixel, rect.xMax), rect.yMax); - DrawRect(inRect, color); - } - } - } - - public static void DrawOutOfRangeOverlay(Rect rect, Color color, float startOfClipPixel, float endOfClipPixel) - { - Color lineColor = Color.white.RGBMultiplied(0.4f); - - // Rect shaded shape drawn before range - if (startOfClipPixel > rect.xMin) - { - Rect startRect = Rect.MinMaxRect(rect.xMin, rect.yMin, Mathf.Min(startOfClipPixel, rect.xMax), rect.yMax); - DrawRect(startRect, color); - TimeArea.DrawVerticalLine(startRect.xMax, startRect.yMin, startRect.yMax, lineColor); - } - - // Rect shaded shape drawn after range - Rect endRect = Rect.MinMaxRect(Mathf.Max(endOfClipPixel, rect.xMin), rect.yMin, rect.xMax, rect.yMax); - DrawRect(endRect, color); - TimeArea.DrawVerticalLine(endRect.xMin, endRect.yMin, endRect.yMax, lineColor); - } - - public static void DrawSelectionOverlay(Rect rect, Color color, float startPixel, float endPixel) - { - startPixel = Mathf.Max(startPixel, rect.xMin); - endPixel = Mathf.Max(endPixel, rect.xMin); - - Rect labelRect = Rect.MinMaxRect(startPixel, rect.yMin, endPixel, rect.yMax); - DrawRect(labelRect, color); - } - - public static void DrawRect(Rect rect, Color color) - { - if (Event.current.type != EventType.Repaint) - return; - - HandleUtility.ApplyWireMaterial(); - GL.PushMatrix(); - GL.MultMatrix(Handles.matrix); - GL.Begin(GL.QUADS); - GL.Color(color); - GL.Vertex(rect.min); - GL.Vertex(new Vector2(rect.xMax, rect.yMin)); - GL.Vertex(rect.max); - GL.Vertex(new Vector2(rect.xMin, rect.yMax)); - GL.End(); - GL.PopMatrix(); - } - - private static CurveRenderer CreateRendererForCurve(AnimationWindowCurve curve) - { - CurveRenderer renderer; - switch (System.Type.GetTypeCode(curve.valueType)) - { - case TypeCode.Int32: - renderer = new IntCurveRenderer(curve.ToAnimationCurve()); - break; - case TypeCode.Boolean: - renderer = new BoolCurveRenderer(curve.ToAnimationCurve()); - break; - default: - renderer = new NormalCurveRenderer(curve.ToAnimationCurve()); - break; - } - return renderer; - } - - private static CurveWrapper.PreProcessKeyMovement CreateKeyPreprocessorForCurve(AnimationWindowCurve curve) - { - CurveWrapper.PreProcessKeyMovement method; - switch (System.Type.GetTypeCode(curve.valueType)) - { - case TypeCode.Int32: - method = (ref Keyframe key) => { key.value = Mathf.Floor(key.value + 0.5f); }; - break; - case TypeCode.Boolean: - method = (ref Keyframe key) => { key.value = key.value > 0.5f ? 1.0f : 0.0f; }; - break; - default: - method = null; - break; - } - return method; - } - - public static CurveWrapper GetCurveWrapper(AnimationWindowCurve curve, AnimationClip clip) - { - CurveWrapper curveWrapper = new CurveWrapper(); - curveWrapper.renderer = CreateRendererForCurve(curve); - curveWrapper.preProcessKeyMovementDelegate = CreateKeyPreprocessorForCurve(curve); - curveWrapper.renderer.SetWrap(WrapMode.Clamp, clip.isLooping ? WrapMode.Loop : WrapMode.Clamp); - curveWrapper.renderer.SetCustomRange(clip.startTime, clip.stopTime); - curveWrapper.binding = curve.binding; - curveWrapper.id = curve.GetHashCode(); - curveWrapper.color = CurveUtility.GetPropertyColor(curve.propertyName); - curveWrapper.hidden = false; - curveWrapper.selectionBindingInterface = curve.selectionBinding; - return curveWrapper; - } - - // Convert keyframe from curve editor representation (CurveSelection) to animation window representation (AnimationWindowKeyframe) - public static AnimationWindowKeyframe CurveSelectionToAnimationWindowKeyframe(CurveSelection curveSelection, List allCurves) - { - foreach (AnimationWindowCurve curve in allCurves) - { - int curveID = curve.GetHashCode(); - if (curveID == curveSelection.curveID) - if (curve.m_Keyframes.Count > curveSelection.key) - return curve.m_Keyframes[curveSelection.key]; - } - - return null; - } - - // Convert keyframe from animation window representation (AnimationWindowKeyframe) to curve editor representation (CurveSelection) to animation window representation (AnimationWindowKeyframe) - public static CurveSelection AnimationWindowKeyframeToCurveSelection(AnimationWindowKeyframe keyframe, CurveEditor curveEditor) - { - int curveID = keyframe.curve.GetHashCode(); - foreach (CurveWrapper curveWrapper in curveEditor.animationCurves) - if (curveWrapper.id == curveID && keyframe.GetIndex() >= 0) - return new CurveSelection(curveWrapper.id, keyframe.GetIndex()); - - return null; - } - - public static AnimationWindowCurve BestMatchForPaste(EditorCurveBinding binding, List clipboardCurves, List targetCurves) - { - // Exact match - foreach (AnimationWindowCurve targetCurve in targetCurves) - if (targetCurve.binding == binding) - return targetCurve; - - // Matching propertyname - foreach (AnimationWindowCurve targetCurve in targetCurves) - { - if (targetCurve.binding.propertyName == binding.propertyName) - { - // Only match if key in binding is not already being pasted itself in clipboardCurves. - if (!clipboardCurves.Exists(clipboardCurve => clipboardCurve.binding == targetCurve.binding)) - { - return targetCurve; - } - } - } - - // No good match found. - return null; - } - - // Make a rect from MinMax values and make sure they're positive sizes - internal static Rect FromToRect(Vector2 start, Vector2 end) - { - Rect r = new Rect(start.x, start.y, end.x - start.x, end.y - start.y); - if (r.width < 0) - { - r.x += r.width; - r.width = -r.width; - } - if (r.height < 0) - { - r.y += r.height; - r.height = -r.height; - } - return r; - } - - public static bool IsTransformType(Type type) - { - return type == typeof(Transform) || type == typeof(RectTransform); - } - - public static bool ForceGrouping(EditorCurveBinding binding) - { - if (binding.type == typeof(Transform)) - return true; - - if (binding.type == typeof(RectTransform)) - { - string group = GetPropertyGroupName(binding.propertyName); - return group == "m_LocalPosition" || group == "m_LocalScale" || group == "m_LocalRotation" || group == "localEulerAnglesBaked" || group == "localEulerAngles" || group == "localEulerAnglesRaw"; - } - - if (typeof(Renderer).IsAssignableFrom(binding.type)) - { - string group = GetPropertyGroupName(binding.propertyName); - return group == "material._Color"; - } - return false; - } - - public static void ControllerChanged() - { - foreach (AnimationWindow animationWindow in AnimationWindow.GetAllAnimationWindows()) - animationWindow.OnControllerChange(); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/ControlPointRenderer.cs b/Editor/Mono/Animation/AnimationWindow/ControlPointRenderer.cs deleted file mode 100644 index f786cccf46..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/ControlPointRenderer.cs +++ /dev/null @@ -1,179 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - // Control point renderer - internal class ControlPointRenderer - { - private class RenderChunk - { - public Mesh mesh; - - public List vertices; - public List colors; - public List uvs; - public List indices; - - public bool isDirty = true; - } - - private List m_RenderChunks = new List(); - - private Texture2D m_Icon; - - // Can hold a maximum of 16250 control points. - const int kMaxVertices = 65000; - const string kControlPointRendererMeshName = "ControlPointRendererMesh"; - - private static Material s_Material; - public static Material material - { - get - { - if (!s_Material) - { - Shader shader = (Shader)EditorGUIUtility.LoadRequired("Editors/AnimationWindow/ControlPoint.shader"); - s_Material = new Material(shader); - } - - return s_Material; - } - } - - public ControlPointRenderer(Texture2D icon) - { - m_Icon = icon; - } - - public void FlushCache() - { - for (int i = 0; i < m_RenderChunks.Count; ++i) - { - Object.DestroyImmediate(m_RenderChunks[i].mesh); - } - - m_RenderChunks.Clear(); - } - - public void Clear() - { - for (int i = 0; i < m_RenderChunks.Count; ++i) - { - RenderChunk renderChunk = m_RenderChunks[i]; - - renderChunk.mesh.Clear(); - - renderChunk.vertices.Clear(); - renderChunk.colors.Clear(); - renderChunk.uvs.Clear(); - - renderChunk.indices.Clear(); - - renderChunk.isDirty = true; - } - } - - public void Render() - { - Material mat = material; - mat.SetTexture("_MainTex", m_Icon); - mat.SetPass(0); - - for (int i = 0; i < m_RenderChunks.Count; ++i) - { - RenderChunk renderChunk = m_RenderChunks[i]; - - if (renderChunk.isDirty) - { - renderChunk.mesh.vertices = renderChunk.vertices.ToArray(); - renderChunk.mesh.colors32 = renderChunk.colors.ToArray(); - renderChunk.mesh.uv = renderChunk.uvs.ToArray(); - - renderChunk.mesh.SetIndices(renderChunk.indices.ToArray(), MeshTopology.Triangles, 0); - - renderChunk.isDirty = false; - } - - Graphics.DrawMeshNow(renderChunk.mesh, Handles.matrix); - } - } - - public void AddPoint(Rect rect, Color color) - { - RenderChunk renderChunk = GetRenderChunk(); - - int baseIndex = renderChunk.vertices.Count; - - renderChunk.vertices.Add(new Vector3(rect.xMin, rect.yMin, 0.0f)); - renderChunk.vertices.Add(new Vector3(rect.xMax, rect.yMin, 0.0f)); - renderChunk.vertices.Add(new Vector3(rect.xMax, rect.yMax, 0.0f)); - renderChunk.vertices.Add(new Vector3(rect.xMin, rect.yMax, 0.0f)); - - renderChunk.colors.Add(color); - renderChunk.colors.Add(color); - renderChunk.colors.Add(color); - renderChunk.colors.Add(color); - - renderChunk.uvs.Add(new Vector2(0.0f, 0.0f)); - renderChunk.uvs.Add(new Vector2(1.0f, 0.0f)); - renderChunk.uvs.Add(new Vector2(1.0f, 1.0f)); - renderChunk.uvs.Add(new Vector2(0.0f, 1.0f)); - - renderChunk.indices.Add(baseIndex); - renderChunk.indices.Add(baseIndex + 1); - renderChunk.indices.Add(baseIndex + 2); - - renderChunk.indices.Add(baseIndex); - renderChunk.indices.Add(baseIndex + 2); - renderChunk.indices.Add(baseIndex + 3); - - renderChunk.isDirty = true; - } - - private RenderChunk GetRenderChunk() - { - RenderChunk renderChunk; - if (m_RenderChunks.Count > 0) - { - renderChunk = m_RenderChunks.Last(); - // Dynamically create new render chunks when needed. - if ((renderChunk.vertices.Count + 4) > kMaxVertices) - { - renderChunk = CreateRenderChunk(); - } - } - else - { - renderChunk = CreateRenderChunk(); - } - - return renderChunk; - } - - private RenderChunk CreateRenderChunk() - { - RenderChunk renderChunk = new RenderChunk(); - - renderChunk.mesh = new Mesh(); - renderChunk.mesh.name = kControlPointRendererMeshName; - renderChunk.mesh.hideFlags |= HideFlags.DontSave; - - renderChunk.vertices = new List(); - renderChunk.colors = new List(); - renderChunk.uvs = new List(); - renderChunk.indices = new List(); - - m_RenderChunks.Add(renderChunk); - - return renderChunk; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/CurveBindingUtility.cs b/Editor/Mono/Animation/AnimationWindow/CurveBindingUtility.cs deleted file mode 100644 index 21ee380a73..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveBindingUtility.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - static internal class CurveBindingUtility - { - // Retrieve current value. If bindings are available and value is animated, use bindings to get value. - // Otherwise, evaluate AnimationWindowCurve at current time. - public static object GetCurrentValue(AnimationWindowState state, AnimationWindowCurve curve) - { - if (state.previewing && curve.rootGameObject != null) - { - return AnimationWindowUtility.GetCurrentValue(curve.rootGameObject, curve.binding); - } - else - { - return curve.Evaluate(state.currentTime); - } - } - - // Retrieve Current Value. Use specified bindings to do so. - public static object GetCurrentValue(GameObject rootGameObject, EditorCurveBinding curveBinding) - { - if (rootGameObject != null) - { - return AnimationWindowUtility.GetCurrentValue(rootGameObject, curveBinding); - } - else - { - if (curveBinding.isPPtrCurve) - { - // Cannot extract type of PPtrCurve. - return null; - } - else - { - // Cannot extract type of AnimationCurve. Default to float. - return 0.0f; - } - } - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs deleted file mode 100644 index a5a23a2fef..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs +++ /dev/null @@ -1,4002 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - -using Object = UnityEngine.Object; -using TangentMode = UnityEditor.AnimationUtility.TangentMode; -using RectangleToolFlags = UnityEditor.CurveEditorSettings.RectangleToolFlags; - -namespace UnityEditor -{ - // External selection interface - internal interface ISelectionBinding - { - GameObject rootGameObject { get; } - AnimationClip animationClip { get; } - - bool clipIsEditable { get; } - bool animationIsEditable { get; } - - int id { get; } - } - - // External state interface - internal interface ICurveEditorState - { - TimeArea.TimeFormat timeFormat { get; } - } - - internal class CurveWrapper - { - public delegate Vector2 GetAxisScalarsCallback(); - public delegate void SetAxisScalarsCallback(Vector2 newAxisScalars); - public delegate void PreProcessKeyMovement(ref Keyframe key); - - public CurveWrapper() - { - id = 0; - groupId = -1; - regionId = -1; - hidden = false; - readOnly = false; - listIndex = -1; - getAxisUiScalarsCallback = null; - setAxisUiScalarsCallback = null; - } - - internal enum SelectionMode - { - None = 0, - Selected = 1, - SemiSelected = 2 - } - - // Curve management - private CurveRenderer m_Renderer; - private ISelectionBinding m_SelectionBinding; - - public CurveRenderer renderer { get { return m_Renderer; } set { m_Renderer = value; } } - public AnimationCurve curve { get { return renderer.GetCurve(); } } - - public GameObject rootGameObjet { get { return m_SelectionBinding != null ? m_SelectionBinding.rootGameObject : null; } } - public AnimationClip animationClip { get { return m_SelectionBinding != null ? m_SelectionBinding.animationClip : null; } } - public bool clipIsEditable { get { return m_SelectionBinding != null ? m_SelectionBinding.clipIsEditable : true; } } - public bool animationIsEditable { get { return m_SelectionBinding != null ? m_SelectionBinding.animationIsEditable : true; } } - public int selectionID { get { return m_SelectionBinding != null ? m_SelectionBinding.id : 0; } } - - public ISelectionBinding selectionBindingInterface { get { return m_SelectionBinding; } set { m_SelectionBinding = value; } } - - public Bounds bounds { get { return renderer.GetBounds(); } } - - // Input - should not be changed by curve editor - public int id; - public EditorCurveBinding binding; - public int groupId; - public int regionId; // Regions are defined by two curves added after each other with the same regionId. - public Color color; - public Color wrapColorMultiplier = Color.white; - public bool readOnly; - public bool hidden; - public GetAxisScalarsCallback getAxisUiScalarsCallback; // Delegate used to fetch values that are multiplied on x and y axis ui values - public SetAxisScalarsCallback setAxisUiScalarsCallback; // Delegate used to set values back that has been changed by this curve editor - - public PreProcessKeyMovement preProcessKeyMovementDelegate; // Delegate used limit key manipulation to fit curve constraints - - // Should be updated by curve editor as appropriate - public SelectionMode selected; - public int listIndex; // Index into m_AnimationCurves list - - private bool m_Changed; - public bool changed - { - get - { - return m_Changed; - } - - set - { - m_Changed = value; - - if (value && renderer != null) - renderer.FlushCache(); - } - } - - public int AddKey(Keyframe key) - { - PreProcessKey(ref key); - return curve.AddKey(key); - } - - public void PreProcessKey(ref Keyframe key) - { - if (preProcessKeyMovementDelegate != null) - preProcessKeyMovementDelegate(ref key); - } - - public int MoveKey(int index, ref Keyframe key) - { - PreProcessKey(ref key); - return curve.MoveKey(index, key); - } - - // An additional vertical min / max range clamp when editing multiple curves with different ranges - public float vRangeMin = -Mathf.Infinity; - public float vRangeMax = Mathf.Infinity; - } - - // Control point collection renderer - class CurveControlPointRenderer - { - // Control point mesh renderers. - private ControlPointRenderer m_UnselectedPointRenderer; - private ControlPointRenderer m_SelectedPointRenderer; - private ControlPointRenderer m_SelectedPointOverlayRenderer; - private ControlPointRenderer m_SemiSelectedPointOverlayRenderer; - private ControlPointRenderer m_WeightedPointRenderer; - - public CurveControlPointRenderer() - { - m_UnselectedPointRenderer = new ControlPointRenderer(CurveEditor.Styles.pointIcon); - m_SelectedPointRenderer = new ControlPointRenderer(CurveEditor.Styles.pointIconSelected); - m_SelectedPointOverlayRenderer = new ControlPointRenderer(CurveEditor.Styles.pointIconSelectedOverlay); - m_SemiSelectedPointOverlayRenderer = new ControlPointRenderer(CurveEditor.Styles.pointIconSemiSelectedOverlay); - m_WeightedPointRenderer = new ControlPointRenderer(CurveEditor.Styles.pointIconWeighted); - } - - public void FlushCache() - { - m_UnselectedPointRenderer.FlushCache(); - m_SelectedPointRenderer.FlushCache(); - m_SelectedPointOverlayRenderer.FlushCache(); - m_SemiSelectedPointOverlayRenderer.FlushCache(); - m_WeightedPointRenderer.FlushCache(); - } - - public void Clear() - { - m_UnselectedPointRenderer.Clear(); - m_SelectedPointRenderer.Clear(); - m_SelectedPointOverlayRenderer.Clear(); - m_SemiSelectedPointOverlayRenderer.Clear(); - m_WeightedPointRenderer.Clear(); - } - - public void Render() - { - m_UnselectedPointRenderer.Render(); - m_SelectedPointRenderer.Render(); - m_SelectedPointOverlayRenderer.Render(); - m_SemiSelectedPointOverlayRenderer.Render(); - m_WeightedPointRenderer.Render(); - } - - public void AddPoint(Rect rect, Color color) - { - m_UnselectedPointRenderer.AddPoint(rect, color); - } - - public void AddSelectedPoint(Rect rect, Color color) - { - m_SelectedPointRenderer.AddPoint(rect, color); - m_SelectedPointOverlayRenderer.AddPoint(rect, Color.white); - } - - public void AddSemiSelectedPoint(Rect rect, Color color) - { - m_SelectedPointRenderer.AddPoint(rect, color); - m_SemiSelectedPointOverlayRenderer.AddPoint(rect, Color.white); - } - - public void AddWeightedPoint(Rect rect, Color color) - { - m_WeightedPointRenderer.AddPoint(rect, color); - } - } - - [System.Serializable] - internal class CurveEditor : TimeArea, CurveUpdater - { - CurveWrapper[] m_AnimationCurves; - - static int s_SelectKeyHash = "SelectKeys".GetHashCode(); - - public delegate void CallbackFunction(); - - public CallbackFunction curvesUpdated; - - public CurveWrapper[] animationCurves - { - get - { - if (m_AnimationCurves == null) - m_AnimationCurves = new CurveWrapper[0]; - - return m_AnimationCurves; - } - set - { - m_AnimationCurves = value; - - curveIDToIndexMap.Clear(); - m_EnableCurveGroups = false; - for (int i = 0; i < m_AnimationCurves.Length; ++i) - { - m_AnimationCurves[i].listIndex = i; - curveIDToIndexMap.Add(m_AnimationCurves[i].id, i); - m_EnableCurveGroups = m_EnableCurveGroups || (m_AnimationCurves[i].groupId != -1); - } - SyncDrawOrder(); - SyncSelection(); - ValidateCurveList(); - } - } - - public bool GetTopMostCurveID(out int curveID) - { - if (m_DrawOrder.Count > 0) - { - curveID = m_DrawOrder[m_DrawOrder.Count - 1]; - return true; - } - - curveID = -1; - return false; - } - - private List m_DrawOrder = new List(); // contains curveIds (last element topmost) - void SyncDrawOrder() - { - // Init - if (m_DrawOrder.Count == 0) - { - m_DrawOrder = m_AnimationCurves.Select(cw => cw.id).ToList(); - return; - } - - List newDrawOrder = new List(m_AnimationCurves.Length); - // First add known curveIds (same order as before) - for (int i = 0; i < m_DrawOrder.Count; ++i) - { - int curveID = m_DrawOrder[i]; - for (int j = 0; j < m_AnimationCurves.Length; ++j) - { - if (m_AnimationCurves[j].id == curveID) - { - newDrawOrder.Add(curveID); - break; - } - } - } - m_DrawOrder = newDrawOrder; - - // Found them all - if (m_DrawOrder.Count == m_AnimationCurves.Length) - return; - - // Add nonexisting curveIds (new curves are top most) - for (int i = 0; i < m_AnimationCurves.Length; ++i) - { - int curveID = m_AnimationCurves[i].id; - bool found = false; - for (int j = 0; j < m_DrawOrder.Count; ++j) - { - if (m_DrawOrder[j] == curveID) - { - found = true; - break; - } - } - if (!found) - m_DrawOrder.Add(curveID); - } - - // Fallback if invalid setup with multiple curves with same curveID (see case 482048) - if (m_DrawOrder.Count != m_AnimationCurves.Length) - { - // Ordering can fail if we have a hierarchy like: - // - // Piston - // Cylinder - // InnerCyl - // Cylinder - // InnerCyl - // Since we cannot generate unique curve ids for identical paths like Cylinder and InnerCyl. - m_DrawOrder = m_AnimationCurves.Select(cw => cw.id).ToList(); - } - } - - public ICurveEditorState state; - - public TimeArea.TimeFormat timeFormat - { - get - { - if (state != null) - return state.timeFormat; - - return TimeArea.TimeFormat.None; - } - } - - internal Bounds m_DefaultBounds = new Bounds(new Vector3(0.5f, 0.5f, 0), new Vector3(1, 1, 0)); - - private CurveEditorSettings m_Settings = new CurveEditorSettings(); - public CurveEditorSettings settings { get { return m_Settings; } set { if (value != null) { m_Settings = value; ApplySettings(); } } } - - protected void ApplySettings() - { - hRangeLocked = settings.hRangeLocked; - vRangeLocked = settings.vRangeLocked; - hRangeMin = settings.hRangeMin; - hRangeMax = settings.hRangeMax; - vRangeMin = settings.vRangeMin; - vRangeMax = settings.vRangeMax; - scaleWithWindow = settings.scaleWithWindow; - hSlider = settings.hSlider; - vSlider = settings.vSlider; - - RecalculateBounds(); - } - - // Other style settings - private Color m_TangentColor = new Color(1, 1, 1, 0.5f); - private Color m_WeightedTangentColor = new Color(1, 1, 1, 1f); - - /// 1/time to snap all keyframes to while dragging. Set to 0 for no snap (default) - public float invSnap = 0; - - private CurveMenuManager m_MenuManager; - - static int s_TangentControlIDHash = "s_TangentControlIDHash".GetHashCode(); - - [SerializeField] CurveEditorSelection m_Selection; - - internal CurveEditorSelection selection - { - get - { - if (m_Selection == null) - { - m_Selection = ScriptableObject.CreateInstance(); - m_Selection.hideFlags = HideFlags.HideAndDontSave; - } - - return m_Selection; - } - } - - internal List selectedCurves - { - get - { - return selection.selectedCurves; - } - set - { - selection.selectedCurves = value; - InvalidateSelectionBounds(); - } - } - - List preCurveDragSelection = null; - - public bool hasSelection { get { return selectedCurves.Count != 0; } } - - bool m_InRangeSelection = false; - - internal void BeginRangeSelection() - { - m_InRangeSelection = true; - } - - internal void EndRangeSelection() - { - m_InRangeSelection = false; - selectedCurves.Sort(); - } - - internal void AddSelection(CurveSelection curveSelection) - { - selectedCurves.Add(curveSelection); - - if (!m_InRangeSelection) - selectedCurves.Sort(); - - InvalidateSelectionBounds(); - } - - internal void RemoveSelection(CurveSelection curveSelection) - { - selectedCurves.Remove(curveSelection); - InvalidateSelectionBounds(); - } - - internal void ClearSelection() - { - selectedCurves.Clear(); - InvalidateSelectionBounds(); - } - - internal CurveWrapper GetCurveWrapperFromID(int curveID) - { - if (m_AnimationCurves == null) - return null; - - int index; - if (curveIDToIndexMap.TryGetValue(curveID, out index)) - return m_AnimationCurves[index]; - - return null; - } - - internal CurveWrapper GetCurveWrapperFromSelection(CurveSelection curveSelection) - { - return GetCurveWrapperFromID(curveSelection.curveID); - } - - internal AnimationCurve GetCurveFromSelection(CurveSelection curveSelection) - { - CurveWrapper curveWrapper = GetCurveWrapperFromSelection(curveSelection); - return (curveWrapper != null) ? curveWrapper.curve : null; - } - - internal Keyframe GetKeyframeFromSelection(CurveSelection curveSelection) - { - AnimationCurve curve = GetCurveFromSelection(curveSelection); - if (curve != null) - { - if (curveSelection.key >= 0 && curveSelection.key < curve.length) - { - return curve[curveSelection.key]; - } - } - - return new Keyframe(); - } - - // Array of tangent points that have been revealed - CurveSelection m_SelectedTangentPoint; - - // Selection tracking: - // What the selection was at the start of a drag - List s_SelectionBackup; - // Time range selection, is it active and what was the mousedown time (start) and the current end time. - float s_TimeRangeSelectionStart, s_TimeRangeSelectionEnd; - bool s_TimeRangeSelectionActive = false; - - private bool m_BoundsAreDirty = true; - private bool m_SelectionBoundsAreDirty = true; - - private bool m_EnableCurveGroups = false; - - Bounds m_SelectionBounds = new Bounds(Vector3.zero, Vector3.zero); - public Bounds selectionBounds - { - get - { - RecalculateSelectionBounds(); - return m_SelectionBounds; - } - } - - Bounds m_CurveBounds = new Bounds(Vector3.zero, Vector3.zero); - public Bounds curveBounds - { - get - { - RecalculateBounds(); - return m_CurveBounds; - } - } - - Bounds m_DrawingBounds = new Bounds(Vector3.zero, Vector3.zero); - public override Bounds drawingBounds - { - get - { - RecalculateBounds(); - return m_DrawingBounds; - } - } - - // Helpers for temporarily saving a bunch of keys. - class SavedCurve - { - public class SavedKeyFrame - { - public Keyframe key; - public CurveWrapper.SelectionMode selected; - - public SavedKeyFrame(Keyframe key, CurveWrapper.SelectionMode selected) - { - this.key = key; - this.selected = selected; - } - - public SavedKeyFrame Clone() - { - SavedKeyFrame duplicate = new SavedKeyFrame(key, selected); - return duplicate; - } - } - - public class SavedKeyFrameComparer : IComparer - { - public static SavedKeyFrameComparer Instance = new SavedKeyFrameComparer(); - - public int Compare(float time1, float time2) - { - float cmp = time1 - time2; - return cmp < -kCurveTimeEpsilon ? -1 : (cmp >= kCurveTimeEpsilon ? 1 : 0); - } - } - - - public int curveId; - public List keys; - - public delegate SavedKeyFrame KeyFrameOperation(SavedKeyFrame keyframe, SavedCurve curve); - } - List m_CurveBackups; - - CurveWrapper m_DraggingKey = null; - Vector2 m_DraggedCoord; - Vector2 m_MoveCoord; - - private enum AxisLock { None, X, Y } - private AxisLock m_AxisLock; - - CurveControlPointRenderer m_PointRenderer; - CurveEditorRectangleTool m_RectangleTool; - - // The square of the maximum pick distance in pixels. - // The mouse will select a key if it's within this distance from the key point. - const float kMaxPickDistSqr = 10 * 10; - const float kExactPickDistSqr = 4 * 4; - - const float kCurveTimeEpsilon = 0.00001f; - - public CurveEditor(Rect rect, CurveWrapper[] curves, bool minimalGUI) : base(minimalGUI) - { - this.rect = rect; - animationCurves = curves; - - float[] modulos = new float[] { - 0.0000001f, 0.0000005f, 0.000001f, 0.000005f, 0.00001f, 0.00005f, 0.0001f, 0.0005f, - 0.001f, 0.005f, 0.01f, 0.05f, 0.1f, 0.5f, 1, 5, 10, 50, 100, 500, - 1000, 5000, 10000, 50000, 100000, 500000, 1000000, 5000000, 10000000 - }; - hTicks = new TickHandler(); - hTicks.SetTickModulos(modulos); - vTicks = new TickHandler(); - vTicks.SetTickModulos(modulos); - margin = 40.0f; - - OnEnable(); - } - - public void OnEnable() - { - // Only add callback once. - Undo.undoRedoPerformed -= UndoRedoPerformed; - Undo.undoRedoPerformed += UndoRedoPerformed; - } - - public void OnDisable() - { - Undo.undoRedoPerformed -= UndoRedoPerformed; - - if (m_PointRenderer != null) - m_PointRenderer.FlushCache(); - } - - public void OnDestroy() - { - if (m_Selection != null) - ScriptableObject.DestroyImmediate(m_Selection); - } - - void UndoRedoPerformed() - { - if (settings.undoRedoSelection) - InvalidateSelectionBounds(); - else - SelectNone(); - } - - private void ValidateCurveList() - { - // Validate that regions are valid (they should consist of two curves after each other with same regionId) - for (int i = 0; i < m_AnimationCurves.Length; ++i) - { - CurveWrapper cw = m_AnimationCurves[i]; - int regId1 = cw.regionId; - if (regId1 >= 0) - { - if (i == m_AnimationCurves.Length - 1) - { - Debug.LogError("Region has only one curve last! Regions should be added as two curves after each other with same regionId"); - return; - } - - CurveWrapper cw2 = m_AnimationCurves[++i]; - int regId2 = cw2.regionId; - if (regId1 != regId2) - { - Debug.LogError("Regions should be added as two curves after each other with same regionId: " + regId1 + " != " + regId2); - return; - } - } - } - - if (m_DrawOrder.Count != m_AnimationCurves.Length) - { - Debug.LogError("DrawOrder and AnimationCurves mismatch: DrawOrder " + m_DrawOrder.Count + ", AnimationCurves: " + m_AnimationCurves.Length); - return; - } - - // Validate draw order regions - int numCurves = m_DrawOrder.Count; - for (int i = 0; i < numCurves; ++i) - { - int curveID = m_DrawOrder[i]; - // If curve is part of a region then find other curve - int regionId = GetCurveWrapperFromID(curveID).regionId; - if (regionId >= 0) - { - if (i == numCurves - 1) - { - Debug.LogError("Region has only one curve last! Regions should be added as two curves after each other with same regionId"); - return; - } - - // Ensure next curve has a matching regionId - int curveId2 = m_DrawOrder[++i]; - int regionId2 = GetCurveWrapperFromID(curveId2).regionId; - if (regionId != regionId2) - { - Debug.LogError("DrawOrder: Regions not added correctly after each other. RegionIds: " + regionId + " , " + regionId2); - return; - } - } - } - - // Debug.Log all curves and their state (outcomment if needed) - /* - string info = "Count: " + m_AnimationCurves.Length + " (Click me for more info)\n"; - foreach (CurveWrapper cw in m_AnimationCurves) - info += ("Curve: id " + cw.id + ", regionId " + cw.regionId + ", hidden " + cw.hidden + "\n"); - Debug.Log(info); - */ - } - - Dictionary m_CurveIDToIndexMap; - private Dictionary curveIDToIndexMap - { - get - { - if (m_CurveIDToIndexMap == null) - m_CurveIDToIndexMap = new Dictionary(); - - return m_CurveIDToIndexMap; - } - } - - private void SyncSelection() - { - Init(); - - List newSelection = new List(selectedCurves.Count); - - foreach (CurveSelection cs in selectedCurves) - { - CurveWrapper cw = GetCurveWrapperFromSelection(cs); - if (cw != null && (!cw.hidden || cw.groupId != -1)) - { - cw.selected = CurveWrapper.SelectionMode.Selected; - newSelection.Add(cs); - } - } - if (newSelection.Count != selectedCurves.Count) - { - selectedCurves = newSelection; - } - - InvalidateBounds(); - } - - public void InvalidateBounds() - { - m_BoundsAreDirty = true; - } - - private void RecalculateBounds() - { - if (InLiveEdit()) - return; - - if (!m_BoundsAreDirty) - return; - - const float kMinRange = 0.1F; - - m_DrawingBounds = m_DefaultBounds; - m_CurveBounds = m_DefaultBounds; - - if (animationCurves != null) - { - bool assigned = false; - for (int i = 0; i < animationCurves.Length; ++i) - { - CurveWrapper wrapper = animationCurves[i]; - - if (wrapper.hidden) - continue; - - if (wrapper.curve.length == 0) - continue; - - if (!assigned) - { - m_CurveBounds = wrapper.bounds; - assigned = true; - } - else - { - m_CurveBounds.Encapsulate(wrapper.bounds); - } - } - } - - // Calculate bounds based on curve bounds if bound is not set by hRangeMin/hRangeMax vRangeMin/vRangeMax. - float minx = hRangeMin != Mathf.NegativeInfinity ? hRangeMin : m_CurveBounds.min.x; - float miny = vRangeMin != Mathf.NegativeInfinity ? vRangeMin : m_CurveBounds.min.y; - float maxx = hRangeMax != Mathf.Infinity ? hRangeMax : m_CurveBounds.max.x; - float maxy = vRangeMax != Mathf.Infinity ? vRangeMax : m_CurveBounds.max.y; - - m_DrawingBounds.SetMinMax(new Vector3(minx, miny, m_CurveBounds.min.z), new Vector3(maxx, maxy, m_CurveBounds.max.z)); - - // Enforce minimum size of bounds - m_DrawingBounds.size = new Vector3(Mathf.Max(m_DrawingBounds.size.x, kMinRange), Mathf.Max(m_DrawingBounds.size.y, kMinRange), 0); - m_CurveBounds.size = new Vector3(Mathf.Max(m_CurveBounds.size.x, kMinRange), Mathf.Max(m_CurveBounds.size.y, kMinRange), 0); - - m_BoundsAreDirty = false; - } - - public void InvalidateSelectionBounds() - { - m_SelectionBoundsAreDirty = true; - } - - private void RecalculateSelectionBounds() - { - if (!m_SelectionBoundsAreDirty) - return; - - if (hasSelection) - { - List selected = selectedCurves; - - Keyframe keyframe = GetKeyframeFromSelection(selected[0]); - m_SelectionBounds = new Bounds(new Vector2(keyframe.time, keyframe.value), Vector2.zero); - - for (int i = 1; i < selected.Count; ++i) - { - keyframe = GetKeyframeFromSelection(selected[i]); - m_SelectionBounds.Encapsulate(new Vector2(keyframe.time, keyframe.value)); - } - } - else - { - m_SelectionBounds = new Bounds(Vector3.zero, Vector3.zero); - } - - m_SelectionBoundsAreDirty = false; - } - - // Frame all curves to be visible. - public void FrameClip(bool horizontally, bool vertically) - { - Bounds frameBounds = curveBounds; - if (frameBounds.size == Vector3.zero) - return; - - if (horizontally) - SetShownHRangeInsideMargins(frameBounds.min.x, frameBounds.max.x); - if (vertically) - SetShownVRangeInsideMargins(frameBounds.min.y, frameBounds.max.y); - } - - // Frame selected keys to be visible. - public void FrameSelected(bool horizontally, bool vertically) - { - if (!hasSelection) - { - FrameClip(horizontally, vertically); - return; - } - - Bounds frameBounds = new Bounds(); - - // Add neighboring keys in bounds if only a single key is selected. - if (selectedCurves.Count == 1) - { - CurveSelection cs = selectedCurves[0]; - CurveWrapper cw = GetCurveWrapperFromSelection(cs); - - // Encapsulate key in bounds - frameBounds = new Bounds(new Vector2(cw.curve[cs.key].time, cw.curve[cs.key].value), Vector2.zero); - - // Include neighboring keys in bounds - if (cs.key - 1 >= 0) - frameBounds.Encapsulate(new Vector2(cw.curve[cs.key - 1].time, cw.curve[cs.key - 1].value)); - if (cs.key + 1 < cw.curve.length) - frameBounds.Encapsulate(new Vector2(cw.curve[cs.key + 1].time, cw.curve[cs.key + 1].value)); - } - else - { - frameBounds = selectionBounds; - } - - // Enforce minimum size of bounds - frameBounds.size = new Vector3(Mathf.Max(frameBounds.size.x, 0.1F), Mathf.Max(frameBounds.size.y, 0.1F), 0); - - if (horizontally) - SetShownHRangeInsideMargins(frameBounds.min.x, frameBounds.max.x); - if (vertically) - SetShownVRangeInsideMargins(frameBounds.min.y, frameBounds.max.y); - } - - public void UpdateCurves(List curveIds, string undoText) - { - foreach (int id in curveIds) - { - CurveWrapper cw = GetCurveWrapperFromID(id); - cw.changed = true; - } - if (curvesUpdated != null) - curvesUpdated(); - } - - public void UpdateCurves(List changedCurves, string undoText) - { - UpdateCurves(new List(changedCurves.Select(curve => curve.curveId)), undoText); - } - - public void StartLiveEdit() - { - MakeCurveBackups(); - } - - public void EndLiveEdit() - { - m_CurveBackups = null; - } - - public bool InLiveEdit() - { - return m_CurveBackups != null; - } - - void Init() - { - } - - public void OnGUI() - { - BeginViewGUI(); - GridGUI(); - DrawWrapperPopups(); - CurveGUI(); - EndViewGUI(); - } - - public void CurveGUI() - { - if (m_PointRenderer == null) - m_PointRenderer = new CurveControlPointRenderer(); - - if (m_RectangleTool == null) - { - m_RectangleTool = new CurveEditorRectangleTool(); - m_RectangleTool.Initialize(this); - } - - GUI.BeginGroup(drawRect); - - Init(); - GUIUtility.GetControlID(s_SelectKeyHash, FocusType.Passive); - GUI.contentColor = GUI.backgroundColor = Color.white; - - Color oldColor = GUI.color; - - Event evt = Event.current; - - //Because this uses a keyboard input field, it must be allowed to handle events first - if (evt.type != EventType.Repaint) - { - EditSelectedPoints(); - } - - switch (evt.type) - { - case EventType.ValidateCommand: - case EventType.ExecuteCommand: - bool execute = evt.type == EventType.ExecuteCommand; - switch (evt.commandName) - { - case EventCommandNames.Delete: - if (hasSelection) - { - if (execute) - { - DeleteSelectedKeys(); - } - evt.Use(); - } - break; - case EventCommandNames.FrameSelected: - if (execute) - FrameSelected(true, true); - evt.Use(); - break; - case EventCommandNames.SelectAll: - if (execute) - SelectAll(); - evt.Use(); - break; - } - break; - case EventType.KeyDown: - if ((evt.keyCode == KeyCode.Backspace || evt.keyCode == KeyCode.Delete) && hasSelection) - { - DeleteSelectedKeys(); - evt.Use(); - } - - // Frame All. - // Manually handle hotkey unless we decide to add it to default Unity hotkeys like - // we did for FrameSelected. - if (evt.keyCode == KeyCode.A) - { - FrameClip(true, true); - evt.Use(); - } - break; - - case EventType.ContextClick: - CurveSelection mouseKey = FindNearest(); - if (mouseKey != null) - { - List keyList = new List(); - - // Find out if key under mouse is part of selected keys - bool inSelected = false; - foreach (CurveSelection sel in selectedCurves) - { - keyList.Add(new KeyIdentifier(GetCurveFromSelection(sel), sel.curveID, sel.key)); - if (sel.curveID == mouseKey.curveID && sel.key == mouseKey.key) - inSelected = true; - } - if (!inSelected) - { - keyList.Clear(); - keyList.Add(new KeyIdentifier(GetCurveFromSelection(mouseKey), mouseKey.curveID, mouseKey.key)); - ClearSelection(); - AddSelection(mouseKey); - } - - bool isEditable = !selectedCurves.Exists(sel => !GetCurveWrapperFromSelection(sel).animationIsEditable); - - m_MenuManager = new CurveMenuManager(this); - GenericMenu menu = new GenericMenu(); - - string deleteKeyLabel = keyList.Count > 1 ? "Delete Keys" : "Delete Key"; - string editKeyLabel = keyList.Count > 1 ? "Edit Keys..." : "Edit Key..."; - - if (isEditable) - { - menu.AddItem(new GUIContent(deleteKeyLabel), false, DeleteKeys, keyList); - menu.AddItem(new GUIContent(editKeyLabel), false, StartEditingSelectedPointsContext, mousePositionInDrawing); - } - else - { - menu.AddDisabledItem(new GUIContent(deleteKeyLabel)); - menu.AddDisabledItem(new GUIContent(editKeyLabel)); - } - - if (isEditable) - { - menu.AddSeparator(""); - m_MenuManager.AddTangentMenuItems(menu, keyList); - } - - menu.ShowAsContext(); - Event.current.Use(); - } - break; - } - - GUI.color = oldColor; - - m_RectangleTool.HandleOverlayEvents(); - - DragTangents(); - - m_RectangleTool.HandleEvents(); - - EditAxisLabels(); - SelectPoints(); - - EditorGUI.BeginChangeCheck(); - Vector2 move = MovePoints(); - if (EditorGUI.EndChangeCheck() && m_DraggingKey != null) - { - m_MoveCoord = move; - } - - if (evt.type == EventType.Repaint) - { - DrawCurves(); - - m_RectangleTool.OnGUI(); - - DrawCurvesTangents(); - DrawCurvesOverlay(); - - m_RectangleTool.OverlayOnGUI(); - - EditSelectedPoints(); - } - - GUI.color = oldColor; - - GUI.EndGroup(); - } - - // Recalculate curve.selected from selected curves - void RecalcCurveSelection() - { - // Reset selection state of all curves - foreach (CurveWrapper cw in m_AnimationCurves) - cw.selected = CurveWrapper.SelectionMode.None; - - // Now sync with selected curves - foreach (CurveSelection cs in selectedCurves) - { - CurveWrapper cw = GetCurveWrapperFromSelection(cs); - if (cw != null) - cw.selected = cs.semiSelected ? CurveWrapper.SelectionMode.SemiSelected : CurveWrapper.SelectionMode.Selected; - } - } - - void RecalcSecondarySelection() - { - // No need to recalculate secondary selection if there are no curves with a valid groupId. - if (!m_EnableCurveGroups) - return; - - // The new list of secondary selections - List newSelection = new List(selectedCurves.Count); - - // Go through selection, find curveselections that need syncing, add those for the sync points. - foreach (CurveSelection cs in selectedCurves) - { - CurveWrapper cw = GetCurveWrapperFromSelection(cs); - if (cw == null) - continue; - - int groupId = cw.groupId; - if (groupId != -1 && !cs.semiSelected) - { - newSelection.Add(cs); - foreach (CurveWrapper cw2 in m_AnimationCurves) - { - if (cw2.groupId == groupId && cw2 != cw) - { - CurveSelection newCS = new CurveSelection(cw2.id, cs.key); - newCS.semiSelected = true; - newSelection.Add(newCS); - } - } - } - else - { - newSelection.Add(cs); - } - } - newSelection.Sort(); - - // the selection can contain duplicate keys. We go through the selection and remove any duplicates we find. - // Since the selection is already sorted, the duplicates are next to each other. - for (int i = 0; i < newSelection.Count - 1;) - { - CurveSelection cs1 = newSelection[i]; - CurveSelection cs2 = newSelection[i + 1]; - if (cs1.curveID == cs2.curveID && cs1.key == cs2.key) - { - // 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. - if (!cs1.semiSelected || !cs2.semiSelected) - cs1.semiSelected = false; - newSelection.RemoveAt(i + 1); - } - else - { - i++; - } - } - - // Assign back - selectedCurves = newSelection; - } - - void DragTangents() - { - Event evt = Event.current; - int tangentId = GUIUtility.GetControlID(s_TangentControlIDHash, FocusType.Passive); - switch (evt.GetTypeForControl(tangentId)) - { - case EventType.MouseDown: - if (evt.button == 0 && !evt.alt) - { - m_SelectedTangentPoint = null; - float nearestDist = kMaxPickDistSqr; - Vector2 mousePos = Event.current.mousePosition; - foreach (CurveSelection cs in selectedCurves) - { - AnimationCurve curve = GetCurveFromSelection(cs); - if (curve == null) - continue; - - if (cs.key < 0 || cs.key >= curve.length) - continue; - - if (IsLeftTangentEditable(cs)) - { - CurveSelection tangent = new CurveSelection(cs.curveID, cs.key, CurveSelection.SelectionType.InTangent); - float d = (DrawingToViewTransformPoint(GetPosition(tangent)) - mousePos).sqrMagnitude; - if (d <= nearestDist) - { - m_SelectedTangentPoint = tangent; - nearestDist = d; - } - } - - if (IsRightTangentEditable(cs)) - { - CurveSelection tangent = new CurveSelection(cs.curveID, cs.key, CurveSelection.SelectionType.OutTangent); - float d = (DrawingToViewTransformPoint(GetPosition(tangent)) - mousePos).sqrMagnitude; - if (d <= nearestDist) - { - m_SelectedTangentPoint = tangent; - nearestDist = d; - } - } - } - - if (m_SelectedTangentPoint != null) - { - SaveKeySelection("Edit Curve"); - - GUIUtility.hotControl = tangentId; - evt.Use(); - } - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == tangentId) - { - CurveSelection dragged = m_SelectedTangentPoint; - CurveWrapper curveWrapper = GetCurveWrapperFromSelection(dragged); - - if ((curveWrapper != null) && curveWrapper.animationIsEditable) - { - Vector2 newPosition = mousePositionInDrawing; - Keyframe key = curveWrapper.curve[dragged.key]; - - if (dragged.type == CurveSelection.SelectionType.InTangent) - { - Keyframe prevKey = curveWrapper.curve[dragged.key - 1]; - float dx = key.time - prevKey.time; - - Vector2 tangentDirection = newPosition - new Vector2(key.time, key.value); - if (tangentDirection.x < -0.0001F) - { - key.inTangent = tangentDirection.y / tangentDirection.x; - key.inWeight = Mathf.Clamp(Mathf.Abs(tangentDirection.x / dx), 0f, 1f); - } - else - { - key.inTangent = Mathf.Infinity; - key.inWeight = 0f; - } - AnimationUtility.SetKeyLeftTangentMode(ref key, TangentMode.Free); - - if (!AnimationUtility.GetKeyBroken(key)) - { - key.outTangent = key.inTangent; - AnimationUtility.SetKeyRightTangentMode(ref key, TangentMode.Free); - } - } - else if (dragged.type == CurveSelection.SelectionType.OutTangent) - { - Keyframe nextKey = curveWrapper.curve[dragged.key + 1]; - float dx = nextKey.time - key.time; - - Vector2 tangentDirection = newPosition - new Vector2(key.time, key.value); - if (tangentDirection.x > 0.0001F) - { - key.outTangent = tangentDirection.y / tangentDirection.x; - key.outWeight = Mathf.Clamp(Mathf.Abs(tangentDirection.x / dx), 0f, 1f); - } - else - { - key.outTangent = Mathf.Infinity; - key.outWeight = 0f; - } - AnimationUtility.SetKeyRightTangentMode(ref key, TangentMode.Free); - - if (!AnimationUtility.GetKeyBroken(key)) - { - key.inTangent = key.outTangent; - AnimationUtility.SetKeyLeftTangentMode(ref key, TangentMode.Free); - } - } - - dragged.key = curveWrapper.MoveKey(dragged.key, ref key); - AnimationUtility.UpdateTangentsFromModeSurrounding(curveWrapper.curve, dragged.key); - - curveWrapper.changed = true; - GUI.changed = true; - } - Event.current.Use(); - } - - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == tangentId) - { - GUIUtility.hotControl = 0; - evt.Use(); - } - break; - case EventType.Repaint: - if (GUIUtility.hotControl == tangentId) - { - Rect mouseRect = new Rect(evt.mousePosition.x - 10, evt.mousePosition.y - 10, 20, 20); - EditorGUIUtility.AddCursorRect(mouseRect, MouseCursor.MoveArrow); - } - break; - } - } - - struct KeyFrameCopy - { - public float time, value, inTangent, outTangent; - public int idx, selectionIdx; - public KeyFrameCopy(int idx, int selectionIdx, Keyframe source) - { - this.idx = idx; - this.selectionIdx = selectionIdx; - time = source.time; - value = source.value; - inTangent = source.inTangent; - outTangent = source.outTangent; - } - } - - internal void DeleteSelectedKeys() - { - string undoLabel; - if (selectedCurves.Count > 1) - undoLabel = "Delete Keys"; - else - undoLabel = "Delete Key"; - - SaveKeySelection(undoLabel); - - // Go over selection backwards and delete (avoids wrecking indices) - for (int i = selectedCurves.Count - 1; i >= 0; i--) - { - CurveSelection k = selectedCurves[i]; - CurveWrapper cw = GetCurveWrapperFromSelection(k); - if (cw == null) - continue; - - if (!cw.animationIsEditable) - continue; - - if (!settings.allowDeleteLastKeyInCurve) - if (cw.curve.keys.Length == 1) - continue; - - cw.curve.RemoveKey(k.key); - AnimationUtility.UpdateTangentsFromMode(cw.curve); - cw.changed = true; - GUI.changed = true; - } - SelectNone(); - } - - private void DeleteKeys(object obj) - { - List keyList = (List)obj; - - string undoLabel; - if (keyList.Count > 1) - undoLabel = "Delete Keys"; - else - undoLabel = "Delete Key"; - - SaveKeySelection(undoLabel); - - // Go over selection backwards and delete (avoids wrecking indices) - List curveIds = new List(); - for (int i = keyList.Count - 1; i >= 0; i--) - { - if (!settings.allowDeleteLastKeyInCurve) - if (keyList[i].curve.keys.Length == 1) - continue; - - if (!GetCurveWrapperFromID(keyList[i].curveId).animationIsEditable) - continue; - - keyList[i].curve.RemoveKey(keyList[i].key); - AnimationUtility.UpdateTangentsFromMode(keyList[i].curve); - curveIds.Add(keyList[i].curveId); - } - - UpdateCurves(curveIds, undoLabel); - SelectNone(); - } - - float ClampVerticalValue(float value, int curveID) - { - // Clamp by global value - value = Mathf.Clamp(value, vRangeMin, vRangeMax); - - // Clamp with per curve settings. - CurveWrapper cw = GetCurveWrapperFromID(curveID); - if (cw != null) - value = Mathf.Clamp(value, cw.vRangeMin, cw.vRangeMax); - - return value; - } - - internal void TranslateSelectedKeys(Vector2 movement) - { - bool inLiveEdit = InLiveEdit(); - if (!inLiveEdit) - StartLiveEdit(); - - UpdateCurvesFromPoints( - delegate(SavedCurve.SavedKeyFrame keyframe, SavedCurve curve) - { - if (keyframe.selected != CurveWrapper.SelectionMode.None) - { - // Duplicate it - so we don't modify the backup copy - var duplicateKeyframe = keyframe.Clone(); - - // Slide in time. Clamp key. - duplicateKeyframe.key.time = Mathf.Clamp(duplicateKeyframe.key.time + movement.x, hRangeMin, hRangeMax); - - // if it's fully selected, also move on Y - if (duplicateKeyframe.selected == CurveWrapper.SelectionMode.Selected) - duplicateKeyframe.key.value = ClampVerticalValue(duplicateKeyframe.key.value + movement.y, curve.curveId); - - return duplicateKeyframe; - } - - return keyframe; - } - ); - - if (!inLiveEdit) - EndLiveEdit(); - } - - internal void SetSelectedKeyPositions(float newTime, float newValue, bool updateTime, bool updateValue) - { - if (!updateTime && !updateValue) - return; - - bool inLiveEdit = InLiveEdit(); - if (!inLiveEdit) - StartLiveEdit(); - - UpdateCurvesFromPoints( - delegate(SavedCurve.SavedKeyFrame keyframe, SavedCurve curve) - { - if (keyframe.selected != CurveWrapper.SelectionMode.None) - { - // Duplicate it - so we don't modify the backup copy - var duplicateKeyframe = keyframe.Clone(); - - if (updateTime) - { - duplicateKeyframe.key.time = Mathf.Clamp(newTime, hRangeMin, hRangeMax); - } - if (updateValue) - { - duplicateKeyframe.key.value = ClampVerticalValue(newValue, curve.curveId); - } - - return duplicateKeyframe; - } - - return keyframe; - } - ); - - if (!inLiveEdit) - EndLiveEdit(); - } - - internal void TransformSelectedKeys(Matrix4x4 matrix, bool flipX, bool flipY) - { - bool inLiveEdit = InLiveEdit(); - if (!inLiveEdit) - StartLiveEdit(); - - UpdateCurvesFromPoints( - - delegate(SavedCurve.SavedKeyFrame keyframe, SavedCurve curve) - { - if (keyframe.selected != CurveWrapper.SelectionMode.None) - { - // Duplicate it - so we don't modify the backup copy - var duplicateKeyframe = keyframe.Clone(); - - Vector3 v = new Vector3(duplicateKeyframe.key.time, duplicateKeyframe.key.value, 0f); - v = matrix.MultiplyPoint3x4(v); - - v.x = SnapTime(v.x); - - duplicateKeyframe.key.time = Mathf.Clamp(v.x, hRangeMin, hRangeMax); - - if (flipX) - { - duplicateKeyframe.key.inTangent = (keyframe.key.outTangent != Mathf.Infinity) ? -keyframe.key.outTangent : Mathf.Infinity; - duplicateKeyframe.key.outTangent = (keyframe.key.inTangent != Mathf.Infinity) ? -keyframe.key.inTangent : Mathf.Infinity; - } - - // if it's fully selected, also move on Y - if (duplicateKeyframe.selected == CurveWrapper.SelectionMode.Selected) - { - duplicateKeyframe.key.value = ClampVerticalValue(v.y, curve.curveId); - - if (flipY) - { - duplicateKeyframe.key.inTangent = (duplicateKeyframe.key.inTangent != Mathf.Infinity) ? -duplicateKeyframe.key.inTangent : Mathf.Infinity; - duplicateKeyframe.key.outTangent = (duplicateKeyframe.key.outTangent != Mathf.Infinity) ? -duplicateKeyframe.key.outTangent : Mathf.Infinity; - } - } - - return duplicateKeyframe; - } - return keyframe; - } - ); - - if (!inLiveEdit) - EndLiveEdit(); - } - - internal void TransformRippleKeys(Matrix4x4 matrix, float t1, float t2, bool flipX) - { - bool inLiveEdit = InLiveEdit(); - if (!inLiveEdit) - StartLiveEdit(); - - UpdateCurvesFromPoints( - - delegate(SavedCurve.SavedKeyFrame keyframe, SavedCurve curve) - { - float newTime = keyframe.key.time; - - if (keyframe.selected != CurveWrapper.SelectionMode.None) - { - Vector3 v = new Vector3(keyframe.key.time, 0f, 0f); - v = matrix.MultiplyPoint3x4(v); - - newTime = v.x; - - // Duplicate it - so we don't modify the backup copy - var duplicateKeyframe = keyframe.Clone(); - - duplicateKeyframe.key.time = SnapTime(Mathf.Clamp(newTime, hRangeMin, hRangeMax)); - - if (flipX) - { - duplicateKeyframe.key.inTangent = (keyframe.key.outTangent != Mathf.Infinity) ? -keyframe.key.outTangent : Mathf.Infinity; - duplicateKeyframe.key.outTangent = (keyframe.key.inTangent != Mathf.Infinity) ? -keyframe.key.inTangent : Mathf.Infinity; - } - - return duplicateKeyframe; - } - else - { - if (keyframe.key.time > t2) - { - Vector3 v = new Vector3(flipX ? t1 : t2, 0f, 0f); - v = matrix.MultiplyPoint3x4(v); - - float dt = v.x - t2; - if (dt > 0f) - newTime = keyframe.key.time + dt; - } - else if (keyframe.key.time < t1) - { - Vector3 v = new Vector3(flipX ? t2 : t1, 0f, 0f); - v = matrix.MultiplyPoint3x4(v); - - float dt = v.x - t1; - if (dt < 0f) - newTime = keyframe.key.time + dt; - } - - if (!Mathf.Approximately(newTime, keyframe.key.time)) - { - // Duplicate it - so we don't modify the backup copy - var duplicateKeyframe = keyframe.Clone(); - duplicateKeyframe.key.time = SnapTime(Mathf.Clamp(newTime, hRangeMin, hRangeMax)); - return duplicateKeyframe; - } - } - - return keyframe; - } - ); - - if (!inLiveEdit) - EndLiveEdit(); - } - - void UpdateCurvesFromPoints(SavedCurve.KeyFrameOperation action) - { - if (m_CurveBackups == null) - return; - - // Starting up: - var dragSelection = new List(); - // Go over all saved curves - each of these has at least one selected point. - foreach (SavedCurve sc in m_CurveBackups) - { - CurveWrapper cw = GetCurveWrapperFromID(sc.curveId); - if (!cw.animationIsEditable) - continue; - - // Go through each curve and build a new working set of points. - var working = new SortedList(SavedCurve.SavedKeyFrameComparer.Instance); - - // Add all unselected key frames to the working collection first. - foreach (SavedCurve.SavedKeyFrame keyframe in sc.keys) - { - if (keyframe.selected == CurveWrapper.SelectionMode.None) - { - var newKeyframe = action(keyframe, sc); - cw.PreProcessKey(ref newKeyframe.key); - - // We might have moved keys around, let's add new key or replace existing key. - working[newKeyframe.key.time] = newKeyframe; - } - } - - // Add all modified key frames to the working collection and remove duplicates. - foreach (SavedCurve.SavedKeyFrame keyframe in sc.keys) - { - if (keyframe.selected != CurveWrapper.SelectionMode.None) - { - var newKeyframe = action(keyframe, sc); - cw.PreProcessKey(ref newKeyframe.key); - // We might have moved keys around, let's add new key or replace existing key. - working[newKeyframe.key.time] = newKeyframe; - } - } - - // Working now contains a set of points with everything set up correctly. - // Each point has it's selection set, but m_DisplayCurves has a more traditional key array. - // Go through the working points and sort those for display. - int idx = 0; - Keyframe[] keysToAssign = new Keyframe[working.Count]; - foreach (KeyValuePair kvp in working) - { - SavedCurve.SavedKeyFrame sk = kvp.Value; - keysToAssign[idx] = sk.key; - if (sk.selected != CurveWrapper.SelectionMode.None) - { - CurveSelection cs = new CurveSelection(sc.curveId, idx); - if (sk.selected == CurveWrapper.SelectionMode.SemiSelected) - cs.semiSelected = true; - dragSelection.Add(cs); - } - - ++idx; - } - - // We now have the list of keys to assign - let's get them back into the animation clip - cw.curve.keys = keysToAssign; - AnimationUtility.UpdateTangentsFromMode(cw.curve); - cw.changed = true; - } - - selectedCurves = dragSelection; - } - - float SnapTime(float t) - { - if (EditorGUI.actionKey) - { - int snapLevel = hTicks.GetLevelWithMinSeparation(5); - float snap = hTicks.GetPeriodOfLevel(snapLevel); - t = Mathf.Round(t / snap) * snap; - } - else - { - if (invSnap != 0.0f) - t = Mathf.Round(t * invSnap) / invSnap; - } - return t; - } - - float SnapValue(float v) - { - if (EditorGUI.actionKey) - { - int snapLevel = vTicks.GetLevelWithMinSeparation(5); - float snap = vTicks.GetPeriodOfLevel(snapLevel); - v = Mathf.Round(v / snap) * snap; - } - return v; - } - - /*string DebugSelection () - { - string s = ""; - foreach (int i in m_PointSelection) - s += i + ", "; - s += "\n"; - foreach (CurveSelection k in selectedCurves) - s += "[" + k.curveID + ", " + k.key+ "], "; - return s; - }*/ - - new internal static class Styles - { - public static Texture2D pointIcon = EditorGUIUtility.LoadIcon("curvekeyframe"); - public static Texture2D pointIconWeighted = EditorGUIUtility.LoadIcon("curvekeyframeweighted"); - public static Texture2D pointIconSelected = EditorGUIUtility.LoadIcon("curvekeyframeselected"); - public static Texture2D pointIconSelectedOverlay = EditorGUIUtility.LoadIcon("curvekeyframeselectedoverlay"); - public static Texture2D pointIconSemiSelectedOverlay = EditorGUIUtility.LoadIcon("curvekeyframesemiselectedoverlay"); - public static GUIContent wrapModeMenuIcon = EditorGUIUtility.IconContent("AnimationWrapModeMenu"); - - public static GUIStyle none = new GUIStyle(); - public static GUIStyle labelTickMarksY = "CurveEditorLabelTickMarks"; - public static GUIStyle labelTickMarksX; - public static GUIStyle selectionRect = "SelectionRect"; - - public static GUIStyle dragLabel = "ProfilerBadge"; - public static GUIStyle axisLabelNumberField = new GUIStyle(EditorStyles.miniTextField); - public static GUIStyle rightAlignedLabel = new GUIStyle(EditorStyles.label); - - static Styles() - { - axisLabelNumberField.alignment = TextAnchor.UpperRight; - labelTickMarksY.contentOffset = Vector2.zero; // TODO: Fix this in style when Editor has been merged to Trunk (31/8/2011) - labelTickMarksX = new GUIStyle(labelTickMarksY); - labelTickMarksX.clipping = TextClipping.Overflow; - rightAlignedLabel.alignment = TextAnchor.UpperRight; - } - } - - Vector2 GetGUIPoint(CurveWrapper cw, Vector3 point) - { - return HandleUtility.WorldToGUIPoint(DrawingToViewTransformPoint(point)); - } - - Rect GetWorldRect(CurveWrapper cw, Rect rect) - { - Vector2 min = GetWorldPoint(cw, rect.min); - Vector2 max = GetWorldPoint(cw, rect.max); - - // Invert y world coordinates. - return Rect.MinMaxRect(min.x, max.y, max.x, min.y); - } - - Vector2 GetWorldPoint(CurveWrapper cw, Vector2 point) - { - return ViewToDrawingTransformPoint(point); - } - - Rect GetCurveRect(CurveWrapper cw) - { - Bounds bounds = cw.bounds; - return Rect.MinMaxRect(bounds.min.x, bounds.min.y, bounds.max.x, bounds.max.y); - } - - Vector2 s_StartMouseDragPosition, s_EndMouseDragPosition, s_StartKeyDragPosition; - PickMode s_PickMode; - - int OnlyOneEditableCurve() - { - int index = -1; - int curves = 0; - for (int i = 0; i < m_AnimationCurves.Length; i++) - { - CurveWrapper wrapper = m_AnimationCurves[i]; - if (wrapper.hidden || wrapper.readOnly) - continue; - curves++; - index = i; - } - if (curves == 1) - return index; - else - return -1; - } - - // Returns an index into m_AnimationCurves - int GetCurveAtPosition(Vector2 viewPos, out Vector2 closestPointOnCurve) - { - Vector2 localPos = ViewToDrawingTransformPoint(viewPos); - - // Find the closest curve at the time corresponding to the position - int maxPixelDist = (int)Mathf.Sqrt(kMaxPickDistSqr); - float smallestDist = kMaxPickDistSqr; - int closest = -1; - closestPointOnCurve = Vector3.zero; - - // Use drawOrder to ensure we pick the topmost curve - for (int i = m_DrawOrder.Count - 1; i >= 0; --i) - { - CurveWrapper wrapper = GetCurveWrapperFromID(m_DrawOrder[i]); - - if (wrapper.hidden || wrapper.readOnly) - continue; - - // Sample the curves at pixel intervals in the area around the desired time, - // corresponding to the max cursor distance allowed. - Vector2 valL; - valL.x = localPos.x - maxPixelDist / scale.x; - valL.y = wrapper.renderer.EvaluateCurveSlow(valL.x); - valL = DrawingToViewTransformPoint(valL); - for (int x = -maxPixelDist; x < maxPixelDist; x++) - { - Vector2 valR; - valR.x = localPos.x + (x + 1) / scale.x; - valR.y = wrapper.renderer.EvaluateCurveSlow(valR.x); - valR = DrawingToViewTransformPoint(valR); - - float dist = HandleUtility.DistancePointLine(viewPos, valL, valR); - dist = dist * dist; - if (dist < smallestDist) - { - smallestDist = dist; - closest = wrapper.listIndex; - closestPointOnCurve = HandleUtility.ProjectPointLine(viewPos, valL, valR); - } - - valL = valR; - } - } - - if (closest >= 0) - closestPointOnCurve = ViewToDrawingTransformPoint(closestPointOnCurve); - return closest; - } - - void CreateKeyFromClick(object obj) - { - string undoLabel = "Add Key"; - SaveKeySelection(undoLabel); - - List ids = CreateKeyFromClick((Vector2)obj); - if (ids.Count > 0) - UpdateCurves(ids, undoLabel); - } - - List CreateKeyFromClick(Vector2 viewPos) - { - List curveIds = new List(); - - // Check if there is only one curve to edit - int singleCurveIndex = OnlyOneEditableCurve(); - if (singleCurveIndex >= 0) - { - // If there is only one curve, allow creating keys on it by double/right-clicking anywhere - // if the click is to the left or right of the existing keys, or if there are no existing keys. - CurveWrapper cw = m_AnimationCurves[singleCurveIndex]; - Vector2 localPos = ViewToDrawingTransformPoint(viewPos); - float time = localPos.x; - if (cw.curve.keys.Length == 0 || time < cw.curve.keys[0].time || time > cw.curve.keys[cw.curve.keys.Length - 1].time) - { - if (CreateKeyFromClick(singleCurveIndex, localPos)) - curveIds.Add(cw.id); - return curveIds; - } - } - - // If we didn't create a key above, only allow creating keys - // when double/right-clicking on an existing curve - Vector2 closestPointOnCurve; - int curveIndex = GetCurveAtPosition(viewPos, out closestPointOnCurve); - if (CreateKeyFromClick(curveIndex, closestPointOnCurve.x)) - { - if (curveIndex >= 0) - curveIds.Add(m_AnimationCurves[curveIndex].id); - } - return curveIds; - } - - bool CreateKeyFromClick(int curveIndex, float time) - { - time = Mathf.Clamp(time, settings.hRangeMin, settings.hRangeMax); - - // Add a key on a curve at a specified time - if (curveIndex >= 0) - { - CurveSelection selectedPoint = null; - CurveWrapper cw = m_AnimationCurves[curveIndex]; - - if (cw.animationIsEditable) - { - if (cw.groupId == -1) - { - selectedPoint = AddKeyAtTime(cw, time); - } - else - { - foreach (CurveWrapper cw2 in m_AnimationCurves) - { - if (cw2.groupId == cw.groupId) - { - CurveSelection cs = AddKeyAtTime(cw2, time); - if (cw2.id == cw.id) - selectedPoint = cs; - } - } - } - if (selectedPoint != null) - { - ClearSelection(); - AddSelection(selectedPoint); - RecalcSecondarySelection(); - } - else - { - SelectNone(); - } - - return true; - } - } - - return false; - } - - bool CreateKeyFromClick(int curveIndex, Vector2 localPos) - { - localPos.x = Mathf.Clamp(localPos.x, settings.hRangeMin, settings.hRangeMax); - - // Add a key on a curve at a specified time - if (curveIndex >= 0) - { - CurveSelection selectedPoint = null; - CurveWrapper cw = m_AnimationCurves[curveIndex]; - - if (cw.animationIsEditable) - { - if (cw.groupId == -1) - { - selectedPoint = AddKeyAtPosition(cw, localPos); - } - else - { - foreach (CurveWrapper cw2 in m_AnimationCurves) - { - if (cw2.groupId == cw.groupId) - { - if (cw2.id == cw.id) - selectedPoint = AddKeyAtPosition(cw2, localPos); - else - AddKeyAtTime(cw2, localPos.x); - } - } - } - if (selectedPoint != null) - { - ClearSelection(); - AddSelection(selectedPoint); - RecalcSecondarySelection(); - } - else - { - SelectNone(); - } - - return true; - } - } - - return false; - } - - public void AddKey(CurveWrapper cw, Keyframe key) - { - CurveSelection selectedPoint = AddKeyframeAndSelect(key, cw); - - if (selectedPoint != null) - { - ClearSelection(); - AddSelection(selectedPoint); - RecalcSecondarySelection(); - } - else - { - SelectNone(); - } - } - - // Add a key to cw at time. - // Returns the inserted key as a curveSelection - CurveSelection AddKeyAtTime(CurveWrapper cw, float time) - { - // Find out if there's already a key there - time = SnapTime(time); - float halfFrame; - if (invSnap != 0.0f) - halfFrame = 0.5f / invSnap; - else - halfFrame = 0.0001f; - if (CurveUtility.HaveKeysInRange(cw.curve, time - halfFrame, time + halfFrame)) - return null; - - // Add the key - int keyIndex = AnimationUtility.AddInbetweenKey(cw.curve, time); - if (keyIndex >= 0) - { - // Select the key - CurveSelection selectedPoint = new CurveSelection(cw.id, keyIndex); - cw.selected = CurveWrapper.SelectionMode.Selected; - cw.changed = true; - - return selectedPoint; - } - - return null; - } - - // Add a key to cw at time. - // Returns the inserted key as a curveSelection - CurveSelection AddKeyAtPosition(CurveWrapper cw, Vector2 position) - { - // Find out if there's already a key there - position.x = SnapTime(position.x); - float halfFrame; - if (invSnap != 0.0f) - halfFrame = 0.5f / invSnap; - else - halfFrame = 0.0001f; - if (CurveUtility.HaveKeysInRange(cw.curve, position.x - halfFrame, position.x + halfFrame)) - return null; - - // Add the key - float slope = 0; - Keyframe key = new Keyframe(position.x, SnapValue(position.y), slope, slope); - return AddKeyframeAndSelect(key, cw); - } - - CurveSelection AddKeyframeAndSelect(Keyframe key, CurveWrapper cw) - { - if (!cw.animationIsEditable) - return null; - - int keyIndex = cw.AddKey(key); - CurveUtility.SetKeyModeFromContext(cw.curve, keyIndex); - AnimationUtility.UpdateTangentsFromModeSurrounding(cw.curve, keyIndex); - - // Select the key - CurveSelection selectedPoint = new CurveSelection(cw.id, keyIndex); - cw.selected = CurveWrapper.SelectionMode.Selected; - cw.changed = true; - - return selectedPoint; - } - - // Find keyframe nearest to the mouse. We use the draw order to ensure to return the - // key that is topmost rendered if several keys are overlapping. The user can - // click on another curve to bring it to front and hereby be able to better select its keys. - // Returns null if nothing is within Sqrt(kMaxPickDistSqr) pixels. - CurveSelection FindNearest() - { - Vector2 mousePos = Event.current.mousePosition; - - bool foundCurve = false; - int bestCurveID = -1; - int bestKey = -1; - float nearestDist = kMaxPickDistSqr; - - // Last element in draw order list is topmost so reverse traverse list - for (int index = m_DrawOrder.Count - 1; index >= 0; --index) - { - CurveWrapper cw = GetCurveWrapperFromID(m_DrawOrder[index]); - if (cw.readOnly || cw.hidden) - continue; - - for (int i = 0; i < cw.curve.keys.Length; ++i) - { - Keyframe k = cw.curve.keys[i]; - float d = (GetGUIPoint(cw, new Vector2(k.time, k.value)) - mousePos).sqrMagnitude; - // If we have an exact hit we just return that key - if (d <= kExactPickDistSqr) - return new CurveSelection(cw.id, i); - - // Otherwise find closest - if (d < nearestDist) - { - foundCurve = true; - bestCurveID = cw.id; - bestKey = i; - nearestDist = d; - } - } - // If top curve has key within range make it harder for keys below to get selected - if (index == m_DrawOrder.Count - 1 && bestCurveID >= 0) - nearestDist = kExactPickDistSqr; - } - - if (foundCurve) - return new CurveSelection(bestCurveID, bestKey); - - return null; - } - - public void SelectNone() - { - ClearSelection(); - foreach (CurveWrapper cw in m_AnimationCurves) - cw.selected = CurveWrapper.SelectionMode.None; - } - - public void SelectAll() - { - int totalLength = 0; - foreach (CurveWrapper cw in m_AnimationCurves) - { - if (cw.hidden) - continue; - totalLength += cw.curve.length; - } - var newSelection = new List(totalLength); - - foreach (CurveWrapper cw in m_AnimationCurves) - { - cw.selected = CurveWrapper.SelectionMode.Selected; - for (int j = 0; j < cw.curve.length; j++) - newSelection.Add(new CurveSelection(cw.id, j)); - } - selectedCurves = newSelection; - } - - public bool IsDraggingKey() - { - return m_DraggingKey != null; - } - - public bool IsDraggingCurveOrRegion() - { - return m_DraggingCurveOrRegion != null; - } - - public bool IsDraggingCurve(CurveWrapper cw) - { - return (m_DraggingCurveOrRegion != null && m_DraggingCurveOrRegion.Length == 1 && m_DraggingCurveOrRegion[0] == cw); - } - - public bool IsDraggingRegion(CurveWrapper cw1, CurveWrapper cw2) - { - return (m_DraggingCurveOrRegion != null && m_DraggingCurveOrRegion.Length == 2 && (m_DraggingCurveOrRegion[0] == cw1 || m_DraggingCurveOrRegion[0] == cw2)); - } - - bool HandleCurveAndRegionMoveToFrontOnMouseDown(ref Vector2 timeValue, ref CurveWrapper[] curves) - { - // Did we click on a curve - Vector2 closestPointOnCurve; - int clickedCurveIndex = GetCurveAtPosition(Event.current.mousePosition, out closestPointOnCurve); - if (clickedCurveIndex >= 0) - { - MoveCurveToFront(m_AnimationCurves[clickedCurveIndex].id); - timeValue = mousePositionInDrawing; - curves = new[] { m_AnimationCurves[clickedCurveIndex] }; - return true; - } - - // Did we click in a region - for (int i = m_DrawOrder.Count - 1; i >= 0; --i) - { - CurveWrapper cw = GetCurveWrapperFromID(m_DrawOrder[i]); - - if (cw == null) - continue; - if (cw.hidden) - continue; - if (cw.curve.length == 0) - continue; - - CurveWrapper cw2 = null; - if (i > 0) - cw2 = GetCurveWrapperFromID(m_DrawOrder[i - 1]); - - if (IsRegion(cw, cw2)) - { - float mouseY = mousePositionInDrawing.y; - float time = mousePositionInDrawing.x; - float v1 = cw.renderer.EvaluateCurveSlow(time); - float v2 = cw2.renderer.EvaluateCurveSlow(time); - if (v1 > v2) - { - float tmp = v1; - v1 = v2; v2 = tmp; - } - if (mouseY >= v1 && mouseY <= v2) - { - timeValue = mousePositionInDrawing; - curves = new[] {cw, cw2}; - MoveCurveToFront(cw.id); - return true; - } - i--; // we handled two curves - } - } - return false; // No curves or regions hit - } - - void SelectPoints() - { - int id = GUIUtility.GetControlID(897560, FocusType.Passive); - Event evt = Event.current; - bool addToSelection = evt.shift; - bool toggleSelection = EditorGUI.actionKey; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - HandleUtility.AddDefaultControl(id); - break; - - case EventType.ContextClick: - Rect drawRectAtOrigin = drawRect; - drawRectAtOrigin.x = drawRectAtOrigin.y = 0f; - if (drawRectAtOrigin.Contains(Event.current.mousePosition)) - { - Vector2 closestPositionOnCurve; - int curveIndex = GetCurveAtPosition(Event.current.mousePosition, out closestPositionOnCurve); - if (curveIndex >= 0) - { - GenericMenu menu = new GenericMenu(); - if (m_AnimationCurves[curveIndex].animationIsEditable) - menu.AddItem(EditorGUIUtility.TrTextContent("Add Key"), false, CreateKeyFromClick, Event.current.mousePosition); - else - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Add Key")); - - menu.ShowAsContext(); - Event.current.Use(); - } - } - break; - - case EventType.MouseDown: - if (evt.clickCount == 2 && evt.button == 0) - { - CurveSelection selectedPoint = FindNearest(); - - if (selectedPoint != null) - { - if (!addToSelection) - { - ClearSelection(); - } - - AnimationCurve curve = GetCurveFromSelection(selectedPoint); - if (curve != null) - { - BeginRangeSelection(); - for (int keyIndex = 0; keyIndex < curve.keys.Length; ++keyIndex) - { - if (!selectedCurves.Any(x => x.curveID == selectedPoint.curveID && x.key == keyIndex)) - { - var keySelection = new CurveSelection(selectedPoint.curveID, keyIndex); - AddSelection(keySelection); - } - } - EndRangeSelection(); - } - } - else - { - SaveKeySelection("Add Key"); - - List curveIds = CreateKeyFromClick(Event.current.mousePosition); - if (curveIds.Count > 0) - { - foreach (int curveId in curveIds) - { - CurveWrapper cw = GetCurveWrapperFromID(curveId); - cw.changed = true; - } - GUI.changed = true; - } - } - evt.Use(); - } - else if (evt.button == 0) - { - CurveSelection selectedPoint = FindNearest(); - if (selectedPoint == null || selectedPoint.semiSelected) - { - // If we did not hit a key then check if a curve or region was clicked - Vector2 timeValue = Vector2.zero; - CurveWrapper[] curves = null; - var curveOrRegionClicked = HandleCurveAndRegionMoveToFrontOnMouseDown(ref timeValue, ref curves); - - if (!addToSelection && !toggleSelection && !curveOrRegionClicked) - { - SelectNone(); - } - - GUIUtility.hotControl = id; - s_EndMouseDragPosition = s_StartMouseDragPosition = evt.mousePosition; - s_PickMode = PickMode.Click; - - // case 845553 event will be processed afterwards when dragging curve. - if (!curveOrRegionClicked) - evt.Use(); - } - else - { - MoveCurveToFront(selectedPoint.curveID); - - Keyframe selectedKeyframe = GetKeyframeFromSelection(selectedPoint); - s_StartKeyDragPosition = new Vector2(selectedKeyframe.time, selectedKeyframe.value); - - if (addToSelection) - { - // Isolate range key indices in current selection. - bool addRangeToSelection = false; - int keyMin = selectedPoint.key; - int keyMax = selectedPoint.key; - for (int i = 0; i < selectedCurves.Count; ++i) - { - CurveSelection cs = selectedCurves[i]; - if (cs.curveID == selectedPoint.curveID) - { - addRangeToSelection = true; - keyMin = Mathf.Min(keyMin, cs.key); - keyMax = Mathf.Max(keyMax, cs.key); - } - } - - if (!addRangeToSelection) - { - if (!selectedCurves.Contains(selectedPoint)) - { - AddSelection(selectedPoint); - } - } - else - { - // Try and add all keys on the same curve in the range [keyMin, keyMax] - BeginRangeSelection(); - for (var keyIndex = keyMin; keyIndex <= keyMax; ++keyIndex) - { - if (!selectedCurves.Any(x => x.curveID == selectedPoint.curveID && x.key == keyIndex)) - { - var rangeSelection = new CurveSelection(selectedPoint.curveID, keyIndex); - AddSelection(rangeSelection); - } - } - EndRangeSelection(); - } - Event.current.Use(); - } - else if (toggleSelection) - { - if (!selectedCurves.Contains(selectedPoint)) - { - AddSelection(selectedPoint); - } - else - { - RemoveSelection(selectedPoint); - } - Event.current.Use(); - } - else if (!selectedCurves.Contains(selectedPoint)) - { - ClearSelection(); - AddSelection(selectedPoint); - } - - RecalcSecondarySelection(); - RecalcCurveSelection(); - } - HandleUtility.Repaint(); - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_EndMouseDragPosition = evt.mousePosition; - if (s_PickMode == PickMode.Click) - { - s_PickMode = PickMode.Marquee; - if (addToSelection || toggleSelection) - s_SelectionBackup = new List(selectedCurves); - else - s_SelectionBackup = new List(); - } - else - { - Rect r = EditorGUIExt.FromToRect(s_StartMouseDragPosition, evt.mousePosition); - - List newSelection = new List(s_SelectionBackup); - for (int i = 0; i < m_AnimationCurves.Length; ++i) - { - CurveWrapper cw = m_AnimationCurves[i]; - if (cw.readOnly || cw.hidden) - continue; - - Rect worldRect = GetWorldRect(cw, r); - if (!GetCurveRect(cw).Overlaps(worldRect)) - continue; - - int keyIndex = 0; - foreach (Keyframe k in cw.curve.keys) - { - if (worldRect.Contains(new Vector2(k.time, k.value))) - newSelection.Add(new CurveSelection(cw.id, keyIndex)); - ++keyIndex; - } - } - selectedCurves = newSelection; - - // We need to sort selection since we're mixing existing selection with new selection. - if (s_SelectionBackup.Count > 0) - selectedCurves.Sort(); - - RecalcSecondarySelection(); - RecalcCurveSelection(); - } - evt.Use(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - if (s_PickMode != PickMode.Click) - { - // Move selected curves to front. - var processedCurves = new HashSet(); - for (int i = 0; i < selectedCurves.Count; ++i) - { - CurveWrapper cw = GetCurveWrapperFromSelection(selectedCurves[i]); - if (!processedCurves.Contains(cw.id)) - { - MoveCurveToFront(cw.id); - processedCurves.Add(cw.id); - } - } - } - - GUIUtility.hotControl = 0; - s_PickMode = PickMode.None; - - Event.current.Use(); - } - break; - } - - if (s_PickMode == PickMode.Marquee) - { - GUI.Label(EditorGUIExt.FromToRect(s_StartMouseDragPosition, s_EndMouseDragPosition), GUIContent.none, Styles.selectionRect); - } - } - - string m_AxisLabelFormat = "n1"; - - private void EditAxisLabels() - { - int id = GUIUtility.GetControlID(18975602, FocusType.Keyboard); - - List curvesInSameSpace = new List(); - Vector2 axisUiScalars = GetAxisUiScalars(curvesInSameSpace); - bool isEditable = axisUiScalars.y >= 0 && curvesInSameSpace.Count > 0 && curvesInSameSpace[0].setAxisUiScalarsCallback != null; - if (!isEditable) - return; - - - Rect editRect = new Rect(0, topmargin - 8, leftmargin - 4, 16); - Rect dragRect = editRect; - dragRect.y -= editRect.height; - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Repaint: - if (GUIUtility.hotControl == 0) - EditorGUIUtility.AddCursorRect(dragRect, MouseCursor.SlideArrow); - break; - - case EventType.MouseDown: - if (evt.button == 0) - { - if (dragRect.Contains(Event.current.mousePosition)) - { - if (GUIUtility.hotControl == 0) - { - GUIUtility.keyboardControl = 0; - GUIUtility.hotControl = id; - GUI.changed = true; - evt.Use(); - } - } - if (!editRect.Contains(Event.current.mousePosition)) - GUIUtility.keyboardControl = 0; // If not hitting our FloatField ensure it loses focus - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - float dragSensitity = Mathf.Clamp01(Mathf.Max(axisUiScalars.y, Mathf.Pow(Mathf.Abs(axisUiScalars.y), 0.5f)) * .01f); - axisUiScalars.y += HandleUtility.niceMouseDelta * dragSensitity; - if (axisUiScalars.y < 0.001f) - axisUiScalars.y = 0.001f; // Since the scalar is a magnitude we do not want to drag to 0 and below.. find nicer solution - SetAxisUiScalars(axisUiScalars, curvesInSameSpace); - evt.Use(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - // Reset dragging - GUIUtility.hotControl = 0; - } - break; - } - - // Show input text field - string orgFormat = EditorGUI.kFloatFieldFormatString; - EditorGUI.kFloatFieldFormatString = m_AxisLabelFormat; - float newValue = EditorGUI.FloatField(editRect, axisUiScalars.y, Styles.axisLabelNumberField); - if (axisUiScalars.y != newValue) - SetAxisUiScalars(new Vector2(axisUiScalars.x, newValue), curvesInSameSpace); - EditorGUI.kFloatFieldFormatString = orgFormat; - } - - public void BeginTimeRangeSelection(float time, bool addToSelection) - { - if (s_TimeRangeSelectionActive) - { - Debug.LogError("BeginTimeRangeSelection can only be called once"); - return; - } - - s_TimeRangeSelectionActive = true; - s_TimeRangeSelectionStart = s_TimeRangeSelectionEnd = time; - if (addToSelection) - s_SelectionBackup = new List(selectedCurves); - else - s_SelectionBackup = new List(); - } - - public void TimeRangeSelectTo(float time) - { - if (!s_TimeRangeSelectionActive) - { - Debug.LogError("TimeRangeSelectTo can only be called after BeginTimeRangeSelection"); - return; - } - - s_TimeRangeSelectionEnd = time; - - var newSelection = new List(s_SelectionBackup); - float minTime = Mathf.Min(s_TimeRangeSelectionStart, s_TimeRangeSelectionEnd); - float maxTime = Mathf.Max(s_TimeRangeSelectionStart, s_TimeRangeSelectionEnd); - foreach (CurveWrapper cw in m_AnimationCurves) - { - if (cw.readOnly || cw.hidden) - continue; - int i = 0; - foreach (Keyframe k in cw.curve.keys) - { - if (k.time >= minTime && k.time < maxTime) - { - newSelection.Add(new CurveSelection(cw.id, i)); - } - i++; - } - } - selectedCurves = newSelection; - RecalcSecondarySelection(); - RecalcCurveSelection(); - } - - public void EndTimeRangeSelection() - { - if (!s_TimeRangeSelectionActive) - { - Debug.LogError("EndTimeRangeSelection can only be called after BeginTimeRangeSelection"); - return; - } - - s_TimeRangeSelectionStart = s_TimeRangeSelectionEnd = 0; - s_TimeRangeSelectionActive = false; - } - - public void CancelTimeRangeSelection() - { - if (!s_TimeRangeSelectionActive) - { - Debug.LogError("CancelTimeRangeSelection can only be called after BeginTimeRangeSelection"); - return; - } - - selectedCurves = s_SelectionBackup; - s_TimeRangeSelectionActive = false; - } - - bool m_EditingPoints; - bool m_TimeWasEdited; - bool m_ValueWasEdited; - float m_NewTime; - float m_NewValue; - - const string kPointValueFieldName = "pointValueField"; - const string kPointTimeFieldName = "pointTimeField"; - string m_FocusedPointField = null; - Vector2 m_PointEditingFieldPosition; - - Vector2 GetPointEditionFieldPosition() - { - var minTime = selectedCurves.Min(x => GetKeyframeFromSelection(x).time); - var maxTime = selectedCurves.Max(x => GetKeyframeFromSelection(x).time); - var minValue = selectedCurves.Min(x => GetKeyframeFromSelection(x).value); - var maxValue = selectedCurves.Max(x => GetKeyframeFromSelection(x).value); - return new Vector2(minTime + maxTime, minValue + maxValue) * 0.5f; - } - - void StartEditingSelectedPointsContext(object fieldPosition) - { - StartEditingSelectedPoints((Vector2)fieldPosition); - } - - void StartEditingSelectedPoints() - { - Vector2 centre = GetPointEditionFieldPosition(); - StartEditingSelectedPoints(centre); - } - - void StartEditingSelectedPoints(Vector2 fieldPosition) - { - m_PointEditingFieldPosition = fieldPosition; - m_FocusedPointField = kPointValueFieldName; - m_TimeWasEdited = false; - m_ValueWasEdited = false; - - // Initialize new values to current selection. - m_NewTime = 0.0f; - m_NewValue = 0.0f; - Keyframe keyframe = GetKeyframeFromSelection(selectedCurves[0]); - if (selectedCurves.All(x => GetKeyframeFromSelection(x).time == keyframe.time)) - m_NewTime = keyframe.time; - if (selectedCurves.All(x => GetKeyframeFromSelection(x).value == keyframe.value)) - m_NewValue = keyframe.value; - - m_EditingPoints = true; - } - - void FinishEditingPoints() - { - m_EditingPoints = false; - } - - void EditSelectedPoints() - { - var evt = Event.current; - - if (m_EditingPoints && !hasSelection) - { - m_EditingPoints = false; - } - - bool gotEscape = false; - if (evt.type == EventType.KeyDown) - { - if (evt.keyCode == KeyCode.KeypadEnter || evt.keyCode == KeyCode.Return) - { - if (hasSelection && !m_EditingPoints) - { - StartEditingSelectedPoints(); - evt.Use(); - } - else if (m_EditingPoints) - { - SetSelectedKeyPositions(m_NewTime, m_NewValue, m_TimeWasEdited, m_ValueWasEdited); - FinishEditingPoints(); - GUI.changed = true; - evt.Use(); - } - } - else if (evt.keyCode == KeyCode.Escape) - { - gotEscape = true; - } - } - - if (!m_EditingPoints) - { - return; - } - - var fieldPosition = DrawingToViewTransformPoint(m_PointEditingFieldPosition); - - const float kFieldHeight = 18f; - const float kFieldWidth = 80f; - - // Keep fields in the drawing margins - var drawAreaInMargins = Rect.MinMaxRect(leftmargin, topmargin, rect.width - rightmargin, rect.height - bottommargin); - fieldPosition.x = Mathf.Clamp(fieldPosition.x, drawAreaInMargins.xMin, drawAreaInMargins.xMax - kFieldWidth); - fieldPosition.y = Mathf.Clamp(fieldPosition.y, drawAreaInMargins.yMin, drawAreaInMargins.yMax - kFieldHeight * 2); - - EditorGUI.BeginChangeCheck(); - GUI.SetNextControlName(kPointTimeFieldName); - m_NewTime = PointFieldForSelection( - new Rect(fieldPosition.x, fieldPosition.y, kFieldWidth, kFieldHeight), - 1, - m_NewTime, - x => GetKeyframeFromSelection(x).time, - (r, id, time) => TimeField(r, id, time, invSnap, timeFormat), - "time"); - if (EditorGUI.EndChangeCheck()) - { - m_TimeWasEdited = true; - } - - EditorGUI.BeginChangeCheck(); - GUI.SetNextControlName(kPointValueFieldName); - m_NewValue = PointFieldForSelection( - new Rect(fieldPosition.x, fieldPosition.y + kFieldHeight, kFieldWidth, kFieldHeight), - 2, - m_NewValue, - x => GetKeyframeFromSelection(x).value, - (r, id, value) => ValueField(r, id, value), - "value"); - if (EditorGUI.EndChangeCheck()) - { - m_ValueWasEdited = true; - } - - if (gotEscape) - { - FinishEditingPoints(); - } - - // Delay focusing these controls until they've been named - if (m_FocusedPointField != null) - { - EditorGUI.FocusTextInControl(m_FocusedPointField); - if (evt.type == EventType.Repaint) - { - m_FocusedPointField = null; - } - } - - if (evt.type == EventType.KeyDown) - { - const char tabCharacter = '\t'; - const char endOfMediumCharacter = (char)25; // ASCII 25: "End Of Medium" on pressing shift tab - - // Override Unity's Tab and Shift+Tab handling. - if (evt.character == tabCharacter || evt.character == endOfMediumCharacter) - { - if (m_TimeWasEdited || m_ValueWasEdited) - { - SetSelectedKeyPositions(m_NewTime, m_NewValue, m_TimeWasEdited, m_ValueWasEdited); - m_PointEditingFieldPosition = GetPointEditionFieldPosition(); - } - - m_FocusedPointField = GUI.GetNameOfFocusedControl() == kPointValueFieldName ? kPointTimeFieldName : kPointValueFieldName; - evt.Use(); - } - } - - // Stop editing if there's an unused click - if (evt.type == EventType.MouseDown) - { - FinishEditingPoints(); - } - } - - // Float editing field for members of selected points - float PointFieldForSelection( - Rect rect, - int customID, - float value, System.Func memberGetter, - System.Func fieldCreator, - string label) - { - float firstSelectedValue = memberGetter(selectedCurves[0]); - bool sameValues = selectedCurves.All(x => memberGetter(x) == firstSelectedValue); - if (!sameValues) - EditorGUI.showMixedValue = true; - - var labelRect = rect; - labelRect.x -= labelRect.width; - - // Use custom IDs to separate event handling from drawing - int id = GUIUtility.GetControlID(customID, FocusType.Keyboard, rect); - var oldColor = GUI.color; - GUI.color = Color.white; - GUI.Label(labelRect, label, Styles.rightAlignedLabel); - - value = fieldCreator(rect, id, value); - - GUI.color = oldColor; - EditorGUI.showMixedValue = false; - - return value; - } - - // 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 - CurveWrapper[] m_DraggingCurveOrRegion = null; - - void SetupKeyOrCurveDragging(Vector2 timeValue, CurveWrapper cw, int id, Vector2 mousePos) - { - m_DraggedCoord = timeValue; - m_DraggingKey = cw; - GUIUtility.hotControl = id; - - s_StartMouseDragPosition = mousePos; - } - - public Vector2 MovePoints() - { - int id = GUIUtility.GetControlID(FocusType.Passive); - - if (!hasSelection && !settings.allowDraggingCurvesAndRegions) - return Vector2.zero; - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (evt.button == 0) - { - // Key dragging - foreach (CurveSelection cs in selectedCurves) - { - CurveWrapper curveWrapper = GetCurveWrapperFromSelection(cs); - if ((curveWrapper == null) || curveWrapper.hidden) - continue; - - if ((DrawingToViewTransformPoint(GetPosition(cs)) - evt.mousePosition).sqrMagnitude <= kMaxPickDistSqr) - { - Keyframe keyframe = GetKeyframeFromSelection(cs); - SetupKeyOrCurveDragging(new Vector2(keyframe.time, keyframe.value), curveWrapper, id, evt.mousePosition); - m_RectangleTool.OnStartMove(s_StartMouseDragPosition, m_RectangleTool.rippleTimeClutch); - evt.Use(); - break; - } - } - - // Curve dragging. Moving keys has highest priority, therefore we check curve/region dragging AFTER key dragging above - if (settings.allowDraggingCurvesAndRegions && m_DraggingKey == null) - { - // We use the logic as for moving keys when we drag entire curves or regions: We just - // select all keyFrames in a curve or region before dragging and ensure to hide tangents when drawing. - Vector2 timeValue = Vector2.zero; - CurveWrapper[] curves = null; - if (HandleCurveAndRegionMoveToFrontOnMouseDown(ref timeValue, ref curves)) - { - var newSelection = new List(); - // Add all keys of curves to selection to reuse code of key dragging - foreach (CurveWrapper cw in curves) - { - for (int i = 0; i < cw.curve.keys.Length; ++i) - newSelection.Add(new CurveSelection(cw.id, i)); - MoveCurveToFront(cw.id); - } - preCurveDragSelection = selectedCurves; - selectedCurves = newSelection; - - // Call after selection above - SetupKeyOrCurveDragging(timeValue, curves[0], id, evt.mousePosition); - m_DraggingCurveOrRegion = curves; - m_RectangleTool.OnStartMove(s_StartMouseDragPosition, false); - evt.Use(); - } - } - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - Vector2 delta = evt.mousePosition - s_StartMouseDragPosition; - Vector2 motion = Vector2.zero; - - // Only drag along x OR y when shift is held down - if (evt.shift && m_AxisLock == AxisLock.None) - m_AxisLock = Mathf.Abs(delta.x) > Mathf.Abs(delta.y) ? AxisLock.X : AxisLock.Y; - - if (m_DraggingCurveOrRegion != null) - { - // Curve/Region dragging only in y axis direction (for now) - delta.x = 0; - motion = ViewToDrawingTransformVector(delta); - motion.y = SnapValue(motion.y + s_StartKeyDragPosition.y) - s_StartKeyDragPosition.y; - } - else - { - switch (m_AxisLock) - { - case AxisLock.None: - motion = ViewToDrawingTransformVector(delta); - motion.x = SnapTime(motion.x + s_StartKeyDragPosition.x) - s_StartKeyDragPosition.x; - motion.y = SnapValue(motion.y + s_StartKeyDragPosition.y) - s_StartKeyDragPosition.y; - break; - case AxisLock.X: - delta.y = 0; - motion = ViewToDrawingTransformVector(delta); - motion.x = SnapTime(motion.x + s_StartKeyDragPosition.x) - s_StartKeyDragPosition.x; - break; - case AxisLock.Y: - delta.x = 0; - motion = ViewToDrawingTransformVector(delta); - motion.y = SnapValue(motion.y + s_StartKeyDragPosition.y) - s_StartKeyDragPosition.y; - break; - } - } - - m_RectangleTool.OnMove(s_StartMouseDragPosition + motion); - - GUI.changed = true; - evt.Use(); - return motion; - } - break; - case EventType.KeyDown: - if (GUIUtility.hotControl == id && evt.keyCode == KeyCode.Escape) - { - TranslateSelectedKeys(Vector2.zero); - ResetDragging(); - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - m_RectangleTool.OnEndMove(); - ResetDragging(); - - GUI.changed = true; - evt.Use(); - } - break; - case EventType.Repaint: - Rect mouseRect = new Rect(evt.mousePosition.x - 10, evt.mousePosition.y - 10, 20, 20); - if (m_DraggingCurveOrRegion != null) - EditorGUIUtility.AddCursorRect(mouseRect, MouseCursor.ResizeVertical); - else if (m_DraggingKey != null) - EditorGUIUtility.AddCursorRect(mouseRect, MouseCursor.MoveArrow); - break; - } - - return Vector2.zero; - } - - void ResetDragging() - { - // If we are dragging entire curve we have selected all keys we therefore ensure to deselect them again... - if (m_DraggingCurveOrRegion != null) - { - selectedCurves = preCurveDragSelection; - preCurveDragSelection = null; - } - - // Cleanup - GUIUtility.hotControl = 0; - m_DraggingKey = null; - m_DraggingCurveOrRegion = null; - m_MoveCoord = Vector2.zero; - - m_AxisLock = AxisLock.None; - } - - void MakeCurveBackups() - { - SaveKeySelection("Edit Curve"); - - m_CurveBackups = new List(); - int lastCurveID = -1; - SavedCurve sc = null; - for (int i = 0; i < selectedCurves.Count; i++) - { - CurveSelection cs = selectedCurves[i]; - // if it's a different curve than last point, we need to back up this curve. - if (cs.curveID != lastCurveID) - { - AnimationCurve curve = GetCurveFromSelection(cs); - if (curve != null) - { - // Make a new saved curve with copy of all keyframes. No need to mark them as selected - sc = new SavedCurve(); - lastCurveID = sc.curveId = cs.curveID; - Keyframe[] keys = curve.keys; - sc.keys = new List(keys.Length); - foreach (Keyframe k in keys) - sc.keys.Add(new SavedCurve.SavedKeyFrame(k, CurveWrapper.SelectionMode.None)); - m_CurveBackups.Add(sc); - } - } - - // Mark them as selected - sc.keys[cs.key].selected = cs.semiSelected ? CurveWrapper.SelectionMode.SemiSelected : CurveWrapper.SelectionMode.Selected; - } - } - - public void SaveKeySelection(string undoLabel) - { - if (settings.undoRedoSelection) - Undo.RegisterCompleteObjectUndo(selection, undoLabel); - } - - // Get the position of a CurveSelection. This will correctly offset tangent handles - Vector2 GetPosition(CurveSelection selection) - { - AnimationCurve curve = GetCurveFromSelection(selection); - Keyframe key = curve[selection.key]; - - Vector2 position = new Vector2(key.time, key.value); - - float tangentLength = 50F; - - if (selection.type == CurveSelection.SelectionType.InTangent) - { - Vector2 dir = new Vector2(1.0F, key.inTangent); - if (key.inTangent == Mathf.Infinity) dir = new Vector2(0, -1); - - Vector2 viewDir = NormalizeInViewSpace(dir); - - if ((key.weightedMode & WeightedMode.In) == WeightedMode.In) - { - Keyframe prevKey = (selection.key >= 1 && selection.key < curve.length) ? curve[selection.key - 1] : key; - float dx = key.time - prevKey.time; - - Vector2 bezierDir = dir * dx * key.inWeight; - if (viewDir.magnitude * 10F < bezierDir.magnitude) - return position - bezierDir; - else - return position - viewDir * 10F; - } - else - { - return position - viewDir * tangentLength; - } - } - else if (selection.type == CurveSelection.SelectionType.OutTangent) - { - Vector2 dir = new Vector2(1.0F, key.outTangent); - if (key.outTangent == Mathf.Infinity) dir = new Vector2(0, -1); - - Vector2 viewDir = NormalizeInViewSpace(dir); - - if ((key.weightedMode & WeightedMode.Out) == WeightedMode.Out) - { - Keyframe nextKey = (selection.key >= 0 && selection.key < (curve.length - 1)) ? curve[selection.key + 1] : key; - float dx = nextKey.time - key.time; - - Vector2 bezierDir = dir * dx * key.outWeight; - if (viewDir.magnitude * 10F < bezierDir.magnitude) - return position + bezierDir; - else - return position + viewDir * 10F; - } - else - { - return position + viewDir * tangentLength; - } - } - else - return position; - } - - void MoveCurveToFront(int curveID) - { - int numCurves = m_DrawOrder.Count; - for (int i = 0; i < numCurves; ++i) - { - // Find curveID in draw order list - if (m_DrawOrder[i] == curveID) - { - // If curve is part of a region then find other curve - int regionId = GetCurveWrapperFromID(curveID).regionId; - if (regionId >= 0) - { - // The other region curve can be on either side of current - int indexOffset = 0; - int curveID2 = -1; - - if (i - 1 >= 0) - { - int id = m_DrawOrder[i - 1]; - if (regionId == GetCurveWrapperFromID(id).regionId) - { - curveID2 = id; - indexOffset = -1; - } - } - if (i + 1 < numCurves && curveID2 < 0) - { - int id = m_DrawOrder[i + 1]; - if (regionId == GetCurveWrapperFromID(id).regionId) - { - curveID2 = id; - indexOffset = 0; - } - } - - if (curveID2 >= 0) - { - m_DrawOrder.RemoveRange(i + indexOffset, 2); - m_DrawOrder.Add(curveID2); - m_DrawOrder.Add(curveID); // ensure curveID is topMost (last) - ValidateCurveList(); - return; - } - - Debug.LogError("Unhandled region"); - } - else // Single curve - { - if (i == numCurves - 1) - return; // curve already last (topmost) - - m_DrawOrder.RemoveAt(i); - m_DrawOrder.Add(curveID); - ValidateCurveList(); - return; - } - } - } - } - - bool IsCurveSelected(CurveWrapper cw) - { - if (cw != null) - return cw.selected != CurveWrapper.SelectionMode.None; - return false; - } - - bool IsRegionCurveSelected(CurveWrapper cw1, CurveWrapper cw2) - { - return IsCurveSelected(cw1) || - IsCurveSelected(cw2); - } - - bool IsRegion(CurveWrapper cw1, CurveWrapper cw2) - { - if (cw1 != null && cw2 != null) - if (cw1.regionId >= 0) - return cw1.regionId == cw2.regionId; - return false; - } - - bool IsLeftTangentEditable(CurveSelection selection) - { - AnimationCurve curve = GetCurveFromSelection(selection); - if (curve == null) - return false; - - if (selection.key < 1 || selection.key >= curve.length) - return false; - - Keyframe keyframe = curve[selection.key]; - TangentMode mode = AnimationUtility.GetKeyLeftTangentMode(keyframe); - - // Tangent is already set to Free. - if (mode == TangentMode.Free) - return true; - - // If tangent is modified, it will be converted to Free. - if (mode == TangentMode.ClampedAuto || mode == TangentMode.Auto) - return true; - - return false; - } - - bool IsRightTangentEditable(CurveSelection selection) - { - AnimationCurve curve = GetCurveFromSelection(selection); - if (curve == null) - return false; - - if (selection.key < 0 || selection.key >= (curve.length - 1)) - return false; - - Keyframe keyframe = curve[selection.key]; - TangentMode mode = AnimationUtility.GetKeyRightTangentMode(keyframe); - - // Tangent is already set to Free. - if (mode == TangentMode.Free) - return true; - - // If tangent is modified, it will be converted to Free. - if (mode == TangentMode.ClampedAuto || mode == TangentMode.Auto) - return true; - - return false; - } - - void DrawCurvesAndRegion(CurveWrapper cw1, CurveWrapper cw2, List selection, bool hasFocus) - { - DrawRegion(cw1, cw2, hasFocus); - DrawCurveAndPoints(cw1, IsCurveSelected(cw1) ? selection : null, hasFocus); - DrawCurveAndPoints(cw2, IsCurveSelected(cw2) ? selection : null, hasFocus); - } - - void DrawCurveAndPoints(CurveWrapper cw, List selection, bool hasFocus) - { - DrawCurve(cw, hasFocus); - DrawPointsOnCurve(cw, selection, hasFocus); - } - - bool ShouldCurveHaveFocus(int indexIntoDrawOrder, CurveWrapper cw1, CurveWrapper cw2) - { - bool focus = false; - if (indexIntoDrawOrder == m_DrawOrder.Count - 1) - focus = true; - else if (hasSelection) - focus = IsCurveSelected(cw1) || IsCurveSelected(cw2); - return focus; - } - - void DrawCurves() - { - if (Event.current.type != EventType.Repaint) - return; - - m_PointRenderer.Clear(); - - // Draw all curves - for (int i = 0; i < m_DrawOrder.Count; ++i) - { - CurveWrapper cw = GetCurveWrapperFromID(m_DrawOrder[i]); - - if (cw == null) - continue; - if (cw.hidden) - continue; - if (cw.curve.length == 0) - continue; - - - CurveWrapper cw2 = null; - if (i < m_DrawOrder.Count - 1) - cw2 = GetCurveWrapperFromID(m_DrawOrder[i + 1]); - - if (IsRegion(cw, cw2)) - { - i++; // we handle two curves - - bool focus = ShouldCurveHaveFocus(i, cw, cw2); - DrawCurvesAndRegion(cw, cw2, IsRegionCurveSelected(cw, cw2) ? selectedCurves : null, focus); - } - else - { - bool focus = ShouldCurveHaveFocus(i, cw, null); - DrawCurveAndPoints(cw, IsCurveSelected(cw) ? selectedCurves : null, focus); - } - } - - m_PointRenderer.Render(); - } - - void DrawCurvesTangents() - { - if (m_DraggingCurveOrRegion != null) - return; - - // Draw left and right tangents lines - HandleUtility.ApplyWireMaterial(); - GL.Begin(GL.LINES); - GL.Color(m_TangentColor * new Color(1, 1, 1, 0.75f)); - for (int i = 0; i < selectedCurves.Count; ++i) - { - CurveSelection sel = selectedCurves[i]; - - if (sel.semiSelected) - continue; - - CurveWrapper curveWrapper = GetCurveWrapperFromSelection(sel); - if (curveWrapper == null) - continue; - - AnimationCurve curve = curveWrapper.curve; - if (curve == null) - continue; - - if (curve.length == 0) - continue; - - if (sel.key < 0 || sel.key >= curve.length) - continue; - - Vector2 keyPoint = GetPosition(sel); - - if (IsLeftTangentEditable(sel) && GetKeyframeFromSelection(sel).time != curve.keys[0].time) - { - Vector2 leftTangent = GetPosition(new CurveSelection(sel.curveID, sel.key, CurveSelection.SelectionType.InTangent)); - DrawLine(leftTangent, keyPoint); - } - - if (IsRightTangentEditable(sel) && GetKeyframeFromSelection(sel).time != curve.keys[curve.keys.Length - 1].time) - { - Vector2 rightTangent = GetPosition(new CurveSelection(sel.curveID, sel.key, CurveSelection.SelectionType.OutTangent)); - DrawLine(keyPoint, rightTangent); - } - } - GL.End(); - - m_PointRenderer.Clear(); - - // Draw left and right tangents handles - for (int i = 0; i < selectedCurves.Count; ++i) - { - CurveSelection sel = selectedCurves[i]; - - if (sel.semiSelected) - continue; - - CurveWrapper curveWrapper = GetCurveWrapperFromSelection(sel); - if (curveWrapper == null) - continue; - - AnimationCurve curve = curveWrapper.curve; - if (curve == null) - continue; - - if (curve.length == 0) - continue; - - if (IsLeftTangentEditable(sel) && GetKeyframeFromSelection(sel).time != curve.keys[0].time) - { - Vector2 leftTangent = DrawingToViewTransformPoint(GetPosition(new CurveSelection(sel.curveID, sel.key, CurveSelection.SelectionType.InTangent))); - DrawTangentPoint(leftTangent, (GetKeyframeFromSelection(sel).weightedMode & WeightedMode.In) == WeightedMode.In); - } - - if (IsRightTangentEditable(sel) && GetKeyframeFromSelection(sel).time != curve.keys[curve.keys.Length - 1].time) - { - Vector2 rightTangent = DrawingToViewTransformPoint(GetPosition(new CurveSelection(sel.curveID, sel.key, CurveSelection.SelectionType.OutTangent))); - DrawTangentPoint(rightTangent, (GetKeyframeFromSelection(sel).weightedMode & WeightedMode.Out) == WeightedMode.Out); - } - } - - m_PointRenderer.Render(); - } - - void DrawCurvesOverlay() - { - if (m_DraggingCurveOrRegion != null) - return; - - // Draw label with values while dragging - if (m_DraggingKey != null && settings.rectangleToolFlags == RectangleToolFlags.NoRectangleTool) - { - GUI.color = Color.white; - - // Clamp only using the currently dragged curve (we could have more selected but we only show the coord info for this one). - float smallestVRangeMin = vRangeMin; - float smallestVRangeMax = vRangeMax; - smallestVRangeMin = Mathf.Max(smallestVRangeMin, m_DraggingKey.vRangeMin); - smallestVRangeMax = Mathf.Min(smallestVRangeMax, m_DraggingKey.vRangeMax); - - Vector2 newPoint = m_DraggedCoord + m_MoveCoord; - newPoint.x = Mathf.Clamp(newPoint.x, hRangeMin, hRangeMax); - newPoint.y = Mathf.Clamp(newPoint.y, smallestVRangeMin, smallestVRangeMax); - Vector2 p = DrawingToViewTransformPoint(newPoint); - - Vector2 axisUiScalars = m_DraggingKey.getAxisUiScalarsCallback != null ? m_DraggingKey.getAxisUiScalarsCallback() : Vector2.one; - if (axisUiScalars.x >= 0f) - newPoint.x *= axisUiScalars.x; - if (axisUiScalars.y >= 0f) - newPoint.y *= axisUiScalars.y; - GUIContent content = new GUIContent(string.Format("{0}, {1}", FormatTime(newPoint.x, invSnap, timeFormat), FormatValue(newPoint.y))); - Vector2 size = Styles.dragLabel.CalcSize(content); - EditorGUI.DoDropShadowLabel( - new Rect(p.x, p.y - size.y, size.x, size.y), content, Styles.dragLabel, 0.3f - ); - } - } - - List CreateRegion(CurveWrapper minCurve, CurveWrapper maxCurve, float deltaTime) - { - // Create list of triangle points - List region = new List(); - - List sampleTimes = new List(); - float sampleTime = deltaTime; - for (; sampleTime <= 1.0f; sampleTime += deltaTime) - sampleTimes.Add(sampleTime); - - if (sampleTime != 1.0f) - sampleTimes.Add(1.0f); - - // To handle constant curves (high gradient) we add key time samples on both side of the keys as well - // the key time itself. - - Keyframe[] maxKeys = maxCurve.curve.keys; - for (int i = 0; i < maxKeys.Length; ++i) - { - Keyframe key = maxKeys[i]; - if (key.time > 0f && key.time < 1.0f) - { - sampleTimes.Add(key.time - 0.0001f); - sampleTimes.Add(key.time); - sampleTimes.Add(key.time + 0.0001f); - } - } - Keyframe[] minKeys = minCurve.curve.keys; - for (int i = 0; i < minKeys.Length; ++i) - { - Keyframe key = minKeys[i]; - if (key.time > 0f && key.time < 1.0f) - { - sampleTimes.Add(key.time - 0.0001f); - sampleTimes.Add(key.time); - sampleTimes.Add(key.time + 0.0001f); - } - } - - sampleTimes.Sort(); - - Vector3 prevA = new Vector3(0.0f, maxCurve.renderer.EvaluateCurveSlow(0.0f), 0.0f); - Vector3 prevB = new Vector3(0.0f, minCurve.renderer.EvaluateCurveSlow(0.0f), 0.0f); - - Vector3 screenPrevA = drawingToViewMatrix.MultiplyPoint(prevA); - Vector3 screenPrevB = drawingToViewMatrix.MultiplyPoint(prevB); - - for (int i = 0; i < sampleTimes.Count; ++i) - { - float time = sampleTimes[i]; - Vector3 valueA = new Vector3(time, maxCurve.renderer.EvaluateCurveSlow(time), 0.0f); - Vector3 valueB = new Vector3(time, minCurve.renderer.EvaluateCurveSlow(time), 0.0f); - - Vector3 screenValueA = drawingToViewMatrix.MultiplyPoint(valueA); - Vector3 screenValueB = drawingToViewMatrix.MultiplyPoint(valueB); - - // Add triangles - if (prevA.y >= prevB.y && valueA.y >= valueB.y) - { - // max is top - region.Add(screenPrevA); - region.Add(screenValueB); - region.Add(screenPrevB); - - region.Add(screenPrevA); - region.Add(screenValueA); - region.Add(screenValueB); - } - else if (prevA.y <= prevB.y && valueA.y <= valueB.y) - { - // min is top - region.Add(screenPrevB); - region.Add(screenValueA); - region.Add(screenPrevA); - - region.Add(screenPrevB); - region.Add(screenValueB); - region.Add(screenValueA); - } - else - { - // Find intersection - Vector2 intersection = Vector2.zero; - if (Mathf.LineIntersection(screenPrevA, screenValueA, screenPrevB, screenValueB, ref intersection)) - { - region.Add(screenPrevA); - region.Add(intersection); - region.Add(screenPrevB); - - region.Add(screenValueA); - region.Add(intersection); - region.Add(screenValueB); - } - else - { - Debug.Log("Error: No intersection found! There should be one..."); - } - } - - prevA = valueA; - prevB = valueB; - - screenPrevA = screenValueA; - screenPrevB = screenValueB; - } - - return region; - } - - public void DrawRegion(CurveWrapper curve1, CurveWrapper curve2, bool hasFocus) - { - if (Event.current.type != EventType.Repaint) - return; - - float deltaTime = 1.0f / (rect.width / 10.0f); - List points = CreateRegion(curve1, curve2, deltaTime); - Color color = curve1.color; - - if (IsDraggingRegion(curve1, curve2)) - { - color = Color.Lerp(color, Color.black, 0.1f); - color.a = 0.4f; - } - else if (settings.useFocusColors && !hasFocus) - { - color *= 0.4f; - color.a = 0.1f; - } - else - { - color *= 1.0f; - color.a = 0.4f; - } - - Shader.SetGlobalColor("_HandleColor", color); - HandleUtility.ApplyWireMaterial(); - GL.Begin(GL.TRIANGLES); - int numTriangles = points.Count / 3; - for (int i = 0; i < numTriangles; i++) - { - GL.Color(color); - GL.Vertex(points[i * 3]); - GL.Vertex(points[i * 3 + 1]); - GL.Vertex(points[i * 3 + 2]); - } - GL.End(); - } - - void DrawCurve(CurveWrapper cw, bool hasFocus) - { - CurveRenderer renderer = cw.renderer; - Color color = cw.color; - - if (IsDraggingCurve(cw) || cw.selected == CurveWrapper.SelectionMode.Selected) - { - color = Color.Lerp(color, Color.white, 0.3f); - } - else if (settings.useFocusColors && !hasFocus) - { - color *= 0.5f; - color.a = 0.8f; - } - - Rect framed = shownArea; - renderer.DrawCurve(framed.xMin, framed.xMax, color, drawingToViewMatrix, settings.wrapColor * cw.wrapColorMultiplier); - } - - void DrawPointsOnCurve(CurveWrapper cw, List selected, bool hasFocus) - { - if (selected == null) - { - Color color = cw.color; - if (settings.useFocusColors && !hasFocus) - color *= 0.5f; - GUI.color = color; - - Keyframe[] keys = cw.curve.keys; - for (int i = 0; i < keys.Length; ++i) - { - Keyframe k = keys[i]; - DrawPoint(DrawingToViewTransformPoint(new Vector2(k.time, k.value)), CurveWrapper.SelectionMode.None); - } - } - else - { - Color keyColor = Color.Lerp(cw.color, Color.white, .2f); - GUI.color = keyColor; - - int selectionIdx = 0; - // Find the point in selected curves that matches the curve we're about to draw. - while (selectionIdx < selected.Count && selected[selectionIdx].curveID != cw.id) - selectionIdx++; - // we're now at the right point in the selection. - int pointIdx = 0; - Keyframe[] keys = cw.curve.keys; - for (int i = 0; i < keys.Length; ++i) - { - Keyframe k = keys[i]; - if (selectionIdx < selected.Count && selected[selectionIdx].key == pointIdx && selected[selectionIdx].curveID == cw.id) - { - if (selected[selectionIdx].semiSelected) - DrawPoint(DrawingToViewTransformPoint(new Vector2(k.time, k.value)), CurveWrapper.SelectionMode.SemiSelected); - else - DrawPoint(DrawingToViewTransformPoint(new Vector2(k.time, k.value)), CurveWrapper.SelectionMode.Selected, settings.rectangleToolFlags == RectangleToolFlags.NoRectangleTool ? MouseCursor.MoveArrow : MouseCursor.Arrow); - selectionIdx++; - } - else - DrawPoint(DrawingToViewTransformPoint(new Vector2(k.time, k.value)), CurveWrapper.SelectionMode.None); - pointIdx++; - } - GUI.color = Color.white; - } - } - - void DrawPoint(Vector2 viewPos, CurveWrapper.SelectionMode selected) - { - DrawPoint(viewPos, selected, MouseCursor.Arrow); - } - - void DrawPoint(Vector2 viewPos, CurveWrapper.SelectionMode selected, MouseCursor mouseCursor) - { - // Important to take floor of positions of GUI stuff to get pixel correct alignment of - // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time. - var rect = new Rect(Mathf.Floor(viewPos.x) - 4, Mathf.Floor(viewPos.y) - 4, Styles.pointIcon.width, Styles.pointIcon.height); - - if (selected == CurveWrapper.SelectionMode.None) - { - m_PointRenderer.AddPoint(rect, GUI.color); - } - else - { - if (selected == CurveWrapper.SelectionMode.Selected) - m_PointRenderer.AddSelectedPoint(rect, GUI.color); - else - m_PointRenderer.AddSemiSelectedPoint(rect, GUI.color); - } - - // Changing the cursor for every point in the selection can be awfully costly. - if (mouseCursor != MouseCursor.Arrow) - { - if (GUIUtility.hotControl == 0) - EditorGUIUtility.AddCursorRect(rect, mouseCursor); - } - } - - void DrawTangentPoint(Vector2 viewPos, bool weighted) - { - // Important to take floor of positions of GUI stuff to get pixel correct alignment of - // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time. - var rect = new Rect(Mathf.Floor(viewPos.x) - 4, Mathf.Floor(viewPos.y) - 4, Styles.pointIcon.width, Styles.pointIcon.height); - - if (weighted) - { - m_PointRenderer.AddWeightedPoint(rect, m_WeightedTangentColor); - } - else - { - m_PointRenderer.AddPoint(rect, m_TangentColor); - } - } - - // FIXME remove when grid drawing function has been properly rewritten - void DrawLine(Vector2 lhs, Vector2 rhs) - { - GL.Vertex(DrawingToViewTransformPoint(new Vector3(lhs.x, lhs.y, 0))); - GL.Vertex(DrawingToViewTransformPoint(new Vector3(rhs.x, rhs.y, 0))); - } - - void DrawWrapperPopups() - { - if (!settings.showWrapperPopups) - return; - - int curveId; - GetTopMostCurveID(out curveId); - - if (curveId == -1) - return; - - CurveWrapper wrapper = GetCurveWrapperFromID(curveId); - AnimationCurve curve = wrapper.curve; - - if (curve != null && curve.length >= 2 && curve.preWrapMode != WrapMode.Default) - { - GUI.BeginGroup(drawRect); - Color oldText = GUI.contentColor; - - var preKey = curve.keys[0]; - var preWrap = curve.preWrapMode; - preWrap = WrapModeIconPopup(preKey, preWrap, -1.5f); - if (preWrap != curve.preWrapMode) - { - curve.preWrapMode = preWrap; - wrapper.changed = true; - } - - var postKey = curve.keys[curve.length - 1]; - var postWrap = curve.postWrapMode; - postWrap = WrapModeIconPopup(postKey, postWrap, 0.5f); - if (postWrap != curve.postWrapMode) - { - curve.postWrapMode = postWrap; - wrapper.changed = true; - } - - if (wrapper.changed) - { - wrapper.renderer.SetWrap(curve.preWrapMode, curve.postWrapMode); - if (curvesUpdated != null) - curvesUpdated(); - } - - GUI.contentColor = oldText; - GUI.EndGroup(); - } - } - - WrapMode WrapModeIconPopup(Keyframe key, WrapMode oldWrap, float hOffset) - { - float buttonSize = Styles.wrapModeMenuIcon.image.width; - var keyPosition = new Vector3(key.time, key.value); - keyPosition = DrawingToViewTransformPoint(keyPosition); - var r = new Rect(keyPosition.x + buttonSize * hOffset, keyPosition.y, buttonSize, buttonSize); - - var selectedValue = (WrapModeFixedCurve)oldWrap; - - // EnumPopupInternal begins - - // sa and values are sorted in the same order - Enum[] enumValues = Enum.GetValues(typeof(WrapModeFixedCurve)).Cast().ToArray(); - var stringNames = Enum.GetNames(typeof(WrapModeFixedCurve)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray(); - - int i = Array.IndexOf(enumValues, selectedValue); - - // PopupInternal begins - - int controlID = GUIUtility.GetControlID("WrapModeIconPopup".GetHashCode(), FocusType.Keyboard, r); - - // DoPopup begins - - var selectedPopupIndex = EditorGUI.PopupCallbackInfo.GetSelectedValueForControl(controlID, i); - - var popupStrings = EditorGUIUtility.TempContent(stringNames); - - Event evt = Event.current; - switch (evt.type) - { - case EventType.Repaint: - GUIStyle.none.Draw(r, Styles.wrapModeMenuIcon, controlID, false); - break; - case EventType.MouseDown: - if (evt.button == 0 && r.Contains(evt.mousePosition)) - { - if (Application.platform == RuntimePlatform.OSXEditor) - { - r.y = r.y - selectedPopupIndex * 16 - 19; - } - - EditorGUI.PopupCallbackInfo.instance = new EditorGUI.PopupCallbackInfo(controlID); - EditorUtility.DisplayCustomMenu(r, popupStrings, selectedPopupIndex, EditorGUI.PopupCallbackInfo.instance.SetEnumValueDelegate, null); - GUIUtility.keyboardControl = controlID; - evt.Use(); - } - break; - case EventType.KeyDown: - if (evt.MainActionKeyForControl(controlID)) - { - if (Application.platform == RuntimePlatform.OSXEditor) - { - r.y = r.y - selectedPopupIndex * 16 - 19; - } - - EditorGUI.PopupCallbackInfo.instance = new EditorGUI.PopupCallbackInfo(controlID); - EditorUtility.DisplayCustomMenu(r, popupStrings, selectedPopupIndex, EditorGUI.PopupCallbackInfo.instance.SetEnumValueDelegate, null); - evt.Use(); - } - break; - } - - return (WrapMode)enumValues[selectedPopupIndex]; - } - - // The return value for each axis can be -1, if so then we do not have any proper value - // to use. - private Vector2 GetAxisUiScalars(List curvesWithSameParameterSpace) - { - // If none or just one selected curve then use top most rendered curve value - if (selectedCurves.Count <= 1) - { - if (m_DrawOrder.Count > 0) - { - CurveWrapper cw = GetCurveWrapperFromID(m_DrawOrder[m_DrawOrder.Count - 1]); - if (cw != null && cw.getAxisUiScalarsCallback != null) - { - // Save list - if (curvesWithSameParameterSpace != null) - curvesWithSameParameterSpace.Add(cw); - return cw.getAxisUiScalarsCallback(); - } - } - return Vector2.one; - } - - // If multiple curves selected we have to check if they are in the same value space - Vector2 axisUiScalars = new Vector2(-1, -1); - if (selectedCurves.Count > 1) - { - // Find common axis scalars if more than one key selected - bool xAllSame = true; - bool yAllSame = true; - Vector2 scalars = Vector2.one; - for (int i = 0; i < selectedCurves.Count; ++i) - { - CurveWrapper cw = GetCurveWrapperFromSelection(selectedCurves[i]); - if (cw == null) - continue; - - if (cw.getAxisUiScalarsCallback != null) - { - Vector2 temp = cw.getAxisUiScalarsCallback(); - if (i == 0) - { - scalars = temp; // init scalars - } - else - { - if (Mathf.Abs(temp.x - scalars.x) > 0.00001f) - xAllSame = false; - if (Mathf.Abs(temp.y - scalars.y) > 0.00001f) - yAllSame = false; - scalars = temp; - } - - // Save list - if (curvesWithSameParameterSpace != null) - curvesWithSameParameterSpace.Add(cw); - } - } - if (xAllSame) - axisUiScalars.x = scalars.x; - if (yAllSame) - axisUiScalars.y = scalars.y; - } - - return axisUiScalars; - } - - private void SetAxisUiScalars(Vector2 newScalars, List curvesInSameSpace) - { - foreach (CurveWrapper cw in curvesInSameSpace) - { - // Only set valid values (-1 indicate invalid value, if so use original value) - Vector2 scalar = cw.getAxisUiScalarsCallback(); - if (newScalars.x >= 0) - scalar.x = newScalars.x; - if (newScalars.y >= 0) - scalar.y = newScalars.y; - - if (cw.setAxisUiScalarsCallback != null) - cw.setAxisUiScalarsCallback(scalar); - } - } - - internal enum PickMode { None, Click, Marquee }; - - public void GridGUI() - { - if (Event.current.type != EventType.Repaint) - return; - - GUI.BeginClip(drawRect); - - Color tempCol = GUI.color; - - // Get axis scalars - Vector2 axisUiScalars = GetAxisUiScalars(null); - - // Cache framed area rect as fetching the property takes some calculations - Rect shownRect = shownArea; - - hTicks.SetRanges(shownRect.xMin * axisUiScalars.x, shownRect.xMax * axisUiScalars.x, drawRect.xMin, drawRect.xMax); - vTicks.SetRanges(shownRect.yMin * axisUiScalars.y, shownRect.yMax * axisUiScalars.y, drawRect.yMin, drawRect.yMax); - - // Draw time markers of various strengths - HandleUtility.ApplyWireMaterial(); - GL.Begin(GL.LINES); - - float lineStart, lineEnd; - - hTicks.SetTickStrengths(settings.hTickStyle.distMin, settings.hTickStyle.distFull, false); - if (settings.hTickStyle.stubs) - { - lineStart = shownRect.yMin; - lineEnd = shownRect.yMin - 40 / scale.y; - } - else - { - lineStart = Mathf.Max(shownRect.yMin, vRangeMin); - lineEnd = Mathf.Min(shownRect.yMax, vRangeMax); - } - - for (int l = 0; l < hTicks.tickLevels; l++) - { - float strength = hTicks.GetStrengthOfLevel(l); - if (strength > 0f) - { - GL.Color(settings.hTickStyle.tickColor * new Color(1, 1, 1, strength) * new Color(1, 1, 1, 0.75f)); - float[] ticks = hTicks.GetTicksAtLevel(l, true); - for (int j = 0; j < ticks.Length; j++) - { - ticks[j] /= axisUiScalars.x; - if (ticks[j] > hRangeMin && ticks[j] < hRangeMax) - DrawLine(new Vector2(ticks[j], lineStart), new Vector2(ticks[j], lineEnd)); - } - } - } - - // Draw bounds of allowed range - GL.Color(settings.hTickStyle.tickColor * new Color(1, 1, 1, 1) * new Color(1, 1, 1, 0.75f)); - if (hRangeMin != Mathf.NegativeInfinity) - DrawLine(new Vector2(hRangeMin, lineStart), new Vector2(hRangeMin, lineEnd)); - if (hRangeMax != Mathf.Infinity) - DrawLine(new Vector2(hRangeMax, lineStart), new Vector2(hRangeMax, lineEnd)); - - vTicks.SetTickStrengths(settings.vTickStyle.distMin, settings.vTickStyle.distFull, false); - if (settings.vTickStyle.stubs) - { - lineStart = shownRect.xMin; - lineEnd = shownRect.xMin + 40 / scale.x; - } - else - { - lineStart = Mathf.Max(shownRect.xMin, hRangeMin); - lineEnd = Mathf.Min(shownRect.xMax, hRangeMax); - } - - // Draw value markers of various strengths - for (int l = 0; l < vTicks.tickLevels; l++) - { - float strength = vTicks.GetStrengthOfLevel(l); - if (strength > 0f) - { - GL.Color(settings.vTickStyle.tickColor * new Color(1, 1, 1, strength) * new Color(1, 1, 1, 0.75f)); - float[] ticks = vTicks.GetTicksAtLevel(l, true); - for (int j = 0; j < ticks.Length; j++) - { - ticks[j] /= axisUiScalars.y; - if (ticks[j] > vRangeMin && ticks[j] < vRangeMax) - DrawLine(new Vector2(lineStart, ticks[j]), new Vector2(lineEnd, ticks[j])); - } - } - } - // Draw bounds of allowed range - GL.Color(settings.vTickStyle.tickColor * new Color(1, 1, 1, 1) * new Color(1, 1, 1, 0.75f)); - if (vRangeMin != Mathf.NegativeInfinity) - DrawLine(new Vector2(lineStart, vRangeMin), new Vector2(lineEnd, vRangeMin)); - if (vRangeMax != Mathf.Infinity) - DrawLine(new Vector2(lineStart, vRangeMax), new Vector2(lineEnd, vRangeMax)); - - GL.End(); - - - if (settings.showAxisLabels) - { - // X Axis labels - if (settings.hTickStyle.distLabel > 0 && axisUiScalars.x > 0f) - { - GUI.color = settings.hTickStyle.labelColor; - int labelLevel = hTicks.GetLevelWithMinSeparation(settings.hTickStyle.distLabel); - - // Calculate how many decimals are needed to show the differences between the labeled ticks - int decimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(hTicks.GetPeriodOfLevel(labelLevel)); - - // now draw - float[] ticks = hTicks.GetTicksAtLevel(labelLevel, false); - float[] ticksPos = (float[])ticks.Clone(); - float vpos = Mathf.Floor(drawRect.height); - for (int i = 0; i < ticks.Length; i++) - { - ticksPos[i] /= axisUiScalars.x; - if (ticksPos[i] < hRangeMin || ticksPos[i] > hRangeMax) - continue; - Vector2 pos = DrawingToViewTransformPoint(new Vector2(ticksPos[i], 0)); - // Important to take floor of positions of GUI stuff to get pixel correct alignment of - // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time. - pos = new Vector2(Mathf.Floor(pos.x), vpos); - - float uiValue = ticks[i]; - Rect labelRect; - TextAnchor wantedAlignment; - if (settings.hTickStyle.centerLabel) - { - wantedAlignment = TextAnchor.UpperCenter; - labelRect = new Rect(pos.x, pos.y - 16 - settings.hTickLabelOffset, 1, 16); - } - else - { - wantedAlignment = TextAnchor.UpperLeft; - labelRect = new Rect(pos.x, pos.y - 16 - settings.hTickLabelOffset, 50, 16); - } - - if (Styles.labelTickMarksX.alignment != wantedAlignment) - Styles.labelTickMarksX.alignment = wantedAlignment; - - GUI.Label(labelRect, uiValue.ToString("n" + decimals) + settings.hTickStyle.unit, Styles.labelTickMarksX); - } - } - - // Y Axis labels - if (settings.vTickStyle.distLabel > 0 && axisUiScalars.y > 0f) - { - // Draw value labels - GUI.color = settings.vTickStyle.labelColor; - int labelLevel = vTicks.GetLevelWithMinSeparation(settings.vTickStyle.distLabel); - - float[] ticks = vTicks.GetTicksAtLevel(labelLevel, false); - float[] ticksPos = (float[])ticks.Clone(); - - // Calculate how many decimals are needed to show the differences between the labeled ticks - int decimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(vTicks.GetPeriodOfLevel(labelLevel)); - string format = "n" + decimals; - m_AxisLabelFormat = format; - - // Calculate the size of the biggest shown label - float labelSize = 35; - if (!settings.vTickStyle.stubs && ticks.Length > 1) - { - float min = ticks[1]; - float max = ticks[ticks.Length - 1]; - string minNumber = min.ToString(format) + settings.vTickStyle.unit; - string maxNumber = max.ToString(format) + settings.vTickStyle.unit; - labelSize = Mathf.Max( - Styles.labelTickMarksY.CalcSize(new GUIContent(minNumber)).x, - Styles.labelTickMarksY.CalcSize(new GUIContent(maxNumber)).x - ) + 6; - } - - // Now draw - for (int i = 0; i < ticks.Length; i++) - { - ticksPos[i] /= axisUiScalars.y; - if (ticksPos[i] < vRangeMin || ticksPos[i] > vRangeMax) - continue; - Vector2 pos = DrawingToViewTransformPoint(new Vector2(0, ticksPos[i])); - // Important to take floor of positions of GUI stuff to get pixel correct alignment of - // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time. - pos = new Vector2(pos.x, Mathf.Floor(pos.y)); - - float uiValue = ticks[i]; - Rect labelRect; - if (settings.vTickStyle.centerLabel) - 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) - else - labelRect = new Rect(0, pos.y - 13, labelSize, 16); // text expands to the right starting from left side of window - - - GUI.Label(labelRect, uiValue.ToString(format) + settings.vTickStyle.unit, Styles.labelTickMarksY); - } - } - } - // Cleanup - GUI.color = tempCol; - - GUI.EndClip(); - } - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditorRectangleTool.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditorRectangleTool.cs deleted file mode 100644 index ab54656e8b..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveEditorRectangleTool.cs +++ /dev/null @@ -1,850 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - -using RectangleToolFlags = UnityEditor.CurveEditorSettings.RectangleToolFlags; - -namespace UnityEditor -{ - internal class CurveEditorRectangleTool : RectangleTool - { - const int kHBarMinWidth = 14; - const int kHBarHeight = 13; - - const int kHBarLeftWidth = 15; - const int kHBarLeftHeight = 13; - const int kHBarRightWidth = 15; - const int kHBarRightHeight = 13; - - const int kHLabelMarginHorizontal = 3; - const int kHLabelMarginVertical = 1; - - const int kVBarMinHeight = 15; - const int kVBarWidth = 13; - - const int kVBarBottomWidth = 13; - const int kVBarBottomHeight = 15; - const int kVBarTopWidth = 13; - const int kVBarTopHeight = 15; - - const int kVLabelMarginHorizontal = 1; - const int kVLabelMarginVertical = 2; - - const int kScaleLeftWidth = 17; - const int kScaleLeftMarginHorizontal = 0; - const float kScaleLeftRatio = 0.80f; - - const int kScaleRightWidth = 17; - const int kScaleRightMarginHorizontal = 0; - const float kScaleRightRatio = 0.80f; - - const int kScaleBottomHeight = 17; - const int kScaleBottomMarginVertical = 0; - const float kScaleBottomRatio = 0.80f; - - const int kScaleTopHeight = 17; - const int kScaleTopMarginVertical = 0; - const float kScaleTopRatio = 0.80f; - - static Rect g_EmptyRect = new Rect(0f, 0f, 0f, 0f); - - struct ToolLayout - { - public Rect selectionRect; - - public Rect hBarRect; - public Rect hBarLeftRect; - public Rect hBarRightRect; - - public bool displayHScale; - - public Rect vBarRect; - public Rect vBarBottomRect; - public Rect vBarTopRect; - - public bool displayVScale; - - public Rect selectionLeftRect; - public Rect selectionTopRect; - - public Rect underlayTopRect; - public Rect underlayLeftRect; - - public Rect scaleLeftRect; - public Rect scaleRightRect; - public Rect scaleTopRect; - public Rect scaleBottomRect; - - public Vector2 leftLabelAnchor; - public Vector2 rightLabelAnchor; - public Vector2 bottomLabelAnchor; - public Vector2 topLabelAnchor; - } - - private CurveEditor m_CurveEditor; - - private ToolLayout m_Layout; - - private Vector2 m_Pivot; - private Vector2 m_Previous; - private Vector2 m_MouseOffset; - - enum DragMode - { - None = 0, - MoveHorizontal = 1 << 0, - MoveVertical = 1 << 1, - MoveBothAxis = MoveHorizontal | MoveVertical, - ScaleHorizontal = 1 << 2, - ScaleVertical = 1 << 3, - ScaleBothAxis = ScaleHorizontal | ScaleVertical, - MoveScaleHorizontal = MoveHorizontal | ScaleHorizontal, - MoveScaleVertical = MoveVertical | ScaleVertical - } - - private DragMode m_DragMode; - private bool m_RippleTime; - private float m_RippleTimeStart; - private float m_RippleTimeEnd; - - private AreaManipulator m_HBarLeft; - private AreaManipulator m_HBarRight; - private AreaManipulator m_HBar; - - private AreaManipulator m_VBarBottom; - private AreaManipulator m_VBarTop; - private AreaManipulator m_VBar; - - private AreaManipulator m_SelectionBox; - - private AreaManipulator m_SelectionScaleLeft; - private AreaManipulator m_SelectionScaleRight; - private AreaManipulator m_SelectionScaleBottom; - private AreaManipulator m_SelectionScaleTop; - - private bool hasSelection { get { return m_CurveEditor.hasSelection && !m_CurveEditor.IsDraggingCurveOrRegion(); } } - private Bounds selectionBounds { get { return m_CurveEditor.selectionBounds; } } - - private float frameRate { get { return m_CurveEditor.invSnap; } } - - private DragMode dragMode - { - get - { - if (m_DragMode != DragMode.None) - return m_DragMode; - - if (m_CurveEditor.IsDraggingKey()) - return DragMode.MoveBothAxis; - - return DragMode.None; - } - } - - public override void Initialize(TimeArea timeArea) - { - base.Initialize(timeArea); - m_CurveEditor = timeArea as CurveEditor; - - if (m_HBarLeft == null) - { - m_HBarLeft = new AreaManipulator(styles.rectangleToolHBarLeft, MouseCursor.ResizeHorizontal); - - m_HBarLeft.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartScale(ToolCoord.Right, ToolCoord.Left, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.ScaleHorizontal, rippleTimeClutch); - return true; - } - - return false; - }; - m_HBarLeft.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate)); - return true; - }; - m_HBarLeft.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndScale(); - return true; - }; - } - - if (m_HBarRight == null) - { - m_HBarRight = new AreaManipulator(styles.rectangleToolHBarRight, MouseCursor.ResizeHorizontal); - - m_HBarRight.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartScale(ToolCoord.Left, ToolCoord.Right, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.ScaleHorizontal, rippleTimeClutch); - return true; - } - - return false; - }; - m_HBarRight.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate)); - return true; - }; - m_HBarRight.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndScale(); - return true; - }; - } - - if (m_HBar == null) - { - m_HBar = new AreaManipulator(styles.rectangleToolHBar, MouseCursor.MoveArrow); - - m_HBar.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartMove(new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.MoveHorizontal, rippleTimeClutch); - return true; - } - - return false; - }; - m_HBar.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnMove(new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f)); - return true; - }; - m_HBar.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndMove(); - return true; - }; - } - - if (m_VBarBottom == null) - { - m_VBarBottom = new AreaManipulator(styles.rectangleToolVBarBottom, MouseCursor.ResizeVertical); - - m_VBarBottom.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartScale(ToolCoord.Top, ToolCoord.Bottom, new Vector2(0f, PixelToValue(evt.mousePosition.y)), DragMode.ScaleVertical, false); - return true; - } - - return false; - }; - m_VBarBottom.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnScaleValue(PixelToValue(evt.mousePosition.y)); - return true; - }; - m_VBarBottom.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndScale(); - return true; - }; - } - - if (m_VBarTop == null) - { - m_VBarTop = new AreaManipulator(styles.rectangleToolVBarTop, MouseCursor.ResizeVertical); - - m_VBarTop.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartScale(ToolCoord.Bottom, ToolCoord.Top, new Vector2(0f, PixelToValue(evt.mousePosition.y)), DragMode.ScaleVertical, false); - return true; - } - - return false; - }; - m_VBarTop.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnScaleValue(PixelToValue(evt.mousePosition.y)); - return true; - }; - m_VBarTop.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndScale(); - return true; - }; - } - - if (m_VBar == null) - { - m_VBar = new AreaManipulator(styles.rectangleToolVBar, MouseCursor.MoveArrow); - - m_VBar.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartMove(new Vector2(0f, PixelToValue(evt.mousePosition.y)), DragMode.MoveVertical, false); - return true; - } - - return false; - }; - m_VBar.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnMove(new Vector2(0f, PixelToValue(evt.mousePosition.y))); - return true; - }; - m_VBar.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndMove(); - return true; - }; - } - - if (m_SelectionBox == null) - { - m_SelectionBox = new AreaManipulator(styles.rectangleToolSelection, MouseCursor.MoveArrow); - - m_SelectionBox.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - bool curveEditorOverride = evt.shift || EditorGUI.actionKey; - if (!curveEditorOverride && hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartMove(new Vector2(PixelToTime(evt.mousePosition.x, frameRate), PixelToValue(evt.mousePosition.y)), rippleTimeClutch ? DragMode.MoveHorizontal : DragMode.MoveBothAxis, rippleTimeClutch); - return true; - } - - return false; - }; - m_SelectionBox.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - // Only drag along x OR y when shift is held down - if (evt.shift && m_DragMode == DragMode.MoveBothAxis) - { - float deltaX = evt.mousePosition.x - TimeToPixel(m_Previous.x); - float deltaY = evt.mousePosition.y - ValueToPixel(m_Previous.y); - m_DragMode = Mathf.Abs(deltaX) > Mathf.Abs(deltaY) ? DragMode.MoveHorizontal : DragMode.MoveVertical; - } - - float posX = ((m_DragMode & DragMode.MoveHorizontal) != 0) ? PixelToTime(evt.mousePosition.x, frameRate) : m_Previous.x; - float posY = ((m_DragMode & DragMode.MoveVertical) != 0) ? PixelToValue(evt.mousePosition.y) : m_Previous.y; - - OnMove(new Vector2(posX, posY)); - return true; - }; - m_SelectionBox.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndMove(); - return true; - }; - } - - if (m_SelectionScaleLeft == null) - { - m_SelectionScaleLeft = new AreaManipulator(styles.rectangleToolScaleLeft, MouseCursor.ResizeHorizontal); - - m_SelectionScaleLeft.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartScale(ToolCoord.Right, ToolCoord.Left, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.ScaleHorizontal, rippleTimeClutch); - return true; - } - - return false; - }; - m_SelectionScaleLeft.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate)); - return true; - }; - m_SelectionScaleLeft.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndScale(); - return true; - }; - } - - if (m_SelectionScaleRight == null) - { - m_SelectionScaleRight = new AreaManipulator(styles.rectangleToolScaleRight, MouseCursor.ResizeHorizontal); - - m_SelectionScaleRight.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartScale(ToolCoord.Left, ToolCoord.Right, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), DragMode.ScaleHorizontal, rippleTimeClutch); - return true; - } - - return false; - }; - m_SelectionScaleRight.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate)); - return true; - }; - m_SelectionScaleRight.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndScale(); - return true; - }; - } - - if (m_SelectionScaleBottom == null) - { - m_SelectionScaleBottom = new AreaManipulator(styles.rectangleToolScaleBottom, MouseCursor.ResizeVertical); - - m_SelectionScaleBottom.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartScale(ToolCoord.Top, ToolCoord.Bottom, new Vector2(0f, PixelToValue(evt.mousePosition.y)), DragMode.ScaleVertical, false); - return true; - } - - return false; - }; - m_SelectionScaleBottom.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnScaleValue(PixelToValue(evt.mousePosition.y)); - return true; - }; - m_SelectionScaleBottom.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndScale(); - return true; - }; - } - - if (m_SelectionScaleTop == null) - { - m_SelectionScaleTop = new AreaManipulator(styles.rectangleToolScaleTop, MouseCursor.ResizeVertical); - - m_SelectionScaleTop.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartScale(ToolCoord.Bottom, ToolCoord.Top, new Vector2(0f, PixelToValue(evt.mousePosition.y)), DragMode.ScaleVertical, false); - return true; - } - - return false; - }; - m_SelectionScaleTop.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnScaleValue(PixelToValue(evt.mousePosition.y)); - return true; - }; - m_SelectionScaleTop.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndScale(); - return true; - }; - } - } - - public void OnGUI() - { - if (!hasSelection) - return; - - if (Event.current.type != EventType.Repaint) - return; - - RectangleToolFlags flags = m_CurveEditor.settings.rectangleToolFlags; - if (flags == RectangleToolFlags.NoRectangleTool) - return; - - Color oldColor = GUI.color; - GUI.color = Color.white; - - m_Layout = CalculateLayout(); - - if (flags == RectangleToolFlags.FullRectangleTool) - { - GUI.Label(m_Layout.selectionLeftRect, GUIContent.none, styles.rectangleToolHighlight); - GUI.Label(m_Layout.selectionTopRect, GUIContent.none, styles.rectangleToolHighlight); - GUI.Label(m_Layout.underlayLeftRect, GUIContent.none, styles.rectangleToolHighlight); - GUI.Label(m_Layout.underlayTopRect, GUIContent.none, styles.rectangleToolHighlight); - } - - m_SelectionBox.OnGUI(m_Layout.selectionRect); - - m_SelectionScaleTop.OnGUI(m_Layout.scaleTopRect); - m_SelectionScaleBottom.OnGUI(m_Layout.scaleBottomRect); - m_SelectionScaleLeft.OnGUI(m_Layout.scaleLeftRect); - m_SelectionScaleRight.OnGUI(m_Layout.scaleRightRect); - - GUI.color = oldColor; - } - - public void OverlayOnGUI() - { - if (!hasSelection) - return; - - if (Event.current.type != EventType.Repaint) - return; - - Color oldColor = GUI.color; - - RectangleToolFlags flags = m_CurveEditor.settings.rectangleToolFlags; - if (flags == RectangleToolFlags.FullRectangleTool) - { - GUI.color = Color.white; - - m_HBar.OnGUI(m_Layout.hBarRect); - m_HBarLeft.OnGUI(m_Layout.hBarLeftRect); - m_HBarRight.OnGUI(m_Layout.hBarRightRect); - - m_VBar.OnGUI(m_Layout.vBarRect); - m_VBarBottom.OnGUI(m_Layout.vBarBottomRect); - m_VBarTop.OnGUI(m_Layout.vBarTopRect); - } - - DrawLabels(); - - GUI.color = oldColor; - } - - public void HandleEvents() - { - RectangleToolFlags flags = m_CurveEditor.settings.rectangleToolFlags; - if (flags == RectangleToolFlags.NoRectangleTool) - return; - - m_SelectionScaleTop.HandleEvents(); - m_SelectionScaleBottom.HandleEvents(); - m_SelectionScaleLeft.HandleEvents(); - m_SelectionScaleRight.HandleEvents(); - - m_SelectionBox.HandleEvents(); - } - - public void HandleOverlayEvents() - { - HandleClutchKeys(); - - RectangleToolFlags flags = m_CurveEditor.settings.rectangleToolFlags; - if (flags == RectangleToolFlags.NoRectangleTool) - return; - - if (flags == RectangleToolFlags.FullRectangleTool) - { - m_VBarBottom.HandleEvents(); - m_VBarTop.HandleEvents(); - m_VBar.HandleEvents(); - - m_HBarLeft.HandleEvents(); - m_HBarRight.HandleEvents(); - m_HBar.HandleEvents(); - } - } - - private ToolLayout CalculateLayout() - { - ToolLayout layout = new ToolLayout(); - - bool canScaleX = !Mathf.Approximately(selectionBounds.size.x, 0f); - bool canScaleY = !Mathf.Approximately(selectionBounds.size.y, 0f); - - float xMin = TimeToPixel(selectionBounds.min.x); - float xMax = TimeToPixel(selectionBounds.max.x); - - float yMin = ValueToPixel(selectionBounds.max.y); - float yMax = ValueToPixel(selectionBounds.min.y); - - layout.selectionRect = new Rect(xMin, yMin, xMax - xMin, yMax - yMin); - - // Horizontal layout - layout.displayHScale = true; - float dragHorizWidth = layout.selectionRect.width - kHBarLeftWidth - kHBarRightWidth; - - if (dragHorizWidth < kHBarMinWidth) - { - layout.displayHScale = false; - - dragHorizWidth = layout.selectionRect.width; - if (dragHorizWidth < kHBarMinWidth) - { - layout.selectionRect.x = layout.selectionRect.center.x - kHBarMinWidth * 0.5f; - layout.selectionRect.width = kHBarMinWidth; - - dragHorizWidth = kHBarMinWidth; - } - } - - if (layout.displayHScale) - { - layout.hBarLeftRect = new Rect(layout.selectionRect.xMin, contentRect.yMin, kHBarLeftWidth, kHBarLeftHeight); - layout.hBarRect = new Rect(layout.hBarLeftRect.xMax, contentRect.yMin, dragHorizWidth, kHBarHeight); - layout.hBarRightRect = new Rect(layout.hBarRect.xMax, contentRect.yMin, kHBarLeftWidth, kHBarRightHeight); - } - else - { - layout.hBarRect = new Rect(layout.selectionRect.xMin, contentRect.yMin, dragHorizWidth, kHBarHeight); - - layout.hBarLeftRect = new Rect(0f, 0f, 0f, 0f); - layout.hBarRightRect = new Rect(0f, 0f, 0f, 0f); - } - - // Vertical layout - layout.displayVScale = true; - float dragVertHeight = layout.selectionRect.height - kVBarBottomHeight - kVBarTopHeight; - - if (dragVertHeight < kVBarMinHeight) - { - layout.displayVScale = false; - - dragVertHeight = layout.selectionRect.height; - if (dragVertHeight < kVBarMinHeight) - { - layout.selectionRect.y = layout.selectionRect.center.y - kVBarMinHeight * 0.5f; - layout.selectionRect.height = kVBarMinHeight; - - dragVertHeight = kVBarMinHeight; - } - } - - if (layout.displayVScale) - { - layout.vBarTopRect = new Rect(contentRect.xMin, layout.selectionRect.yMin, kVBarTopWidth, kVBarTopHeight); - layout.vBarRect = new Rect(contentRect.xMin, layout.vBarTopRect.yMax, kVBarWidth, dragVertHeight); - layout.vBarBottomRect = new Rect(contentRect.xMin, layout.vBarRect.yMax, kVBarBottomWidth, kVBarBottomHeight); - } - else - { - layout.vBarRect = new Rect(contentRect.xMin, layout.selectionRect.yMin, kVBarWidth, dragVertHeight); - - layout.vBarTopRect = g_EmptyRect; - layout.vBarBottomRect = g_EmptyRect; - } - - // Scale handles. - if (canScaleX) - { - float leftRatio = (1.0f - kScaleLeftRatio) * 0.5f; - float rightRatio = (1.0f - kScaleRightRatio) * 0.5f; - - layout.scaleLeftRect = new Rect(layout.selectionRect.xMin - kScaleLeftMarginHorizontal - kScaleLeftWidth, layout.selectionRect.yMin + layout.selectionRect.height * leftRatio, kScaleLeftWidth, layout.selectionRect.height * kScaleLeftRatio); - layout.scaleRightRect = new Rect(layout.selectionRect.xMax + kScaleRightMarginHorizontal, layout.selectionRect.yMin + layout.selectionRect.height * rightRatio, kScaleRightWidth, layout.selectionRect.height * kScaleRightRatio); - } - else - { - layout.scaleLeftRect = g_EmptyRect; - layout.scaleRightRect = g_EmptyRect; - } - - if (canScaleY) - { - float bottomRatio = (1.0f - kScaleBottomRatio) * 0.5f; - float topRatio = (1.0f - kScaleTopRatio) * 0.5f; - - layout.scaleTopRect = new Rect(layout.selectionRect.xMin + layout.selectionRect.width * topRatio, layout.selectionRect.yMin - kScaleTopMarginVertical - kScaleTopHeight, layout.selectionRect.width * kScaleTopRatio, kScaleTopHeight); - layout.scaleBottomRect = new Rect(layout.selectionRect.xMin + layout.selectionRect.width * bottomRatio, layout.selectionRect.yMax + kScaleBottomMarginVertical, layout.selectionRect.width * kScaleBottomRatio, kScaleBottomHeight); - } - else - { - layout.scaleTopRect = g_EmptyRect; - layout.scaleBottomRect = g_EmptyRect; - } - - // Labels. - if (canScaleX) - { - layout.leftLabelAnchor = new Vector2(layout.selectionRect.xMin - kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical); - layout.rightLabelAnchor = new Vector2(layout.selectionRect.xMax + kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical); - } - else - { - layout.leftLabelAnchor = layout.rightLabelAnchor = new Vector2(layout.selectionRect.xMax + kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical); - } - - if (canScaleY) - { - layout.bottomLabelAnchor = new Vector2(contentRect.xMin + kVLabelMarginHorizontal, layout.selectionRect.yMax + kVLabelMarginVertical); - layout.topLabelAnchor = new Vector2(contentRect.xMin + kVLabelMarginHorizontal, layout.selectionRect.yMin - kVLabelMarginVertical); - } - else - { - layout.bottomLabelAnchor = layout.topLabelAnchor = new Vector2(contentRect.xMin + kVLabelMarginHorizontal, layout.selectionRect.yMin - kVLabelMarginVertical); - } - - // Extra ui. - layout.selectionLeftRect = new Rect(contentRect.xMin + kVBarWidth, layout.selectionRect.yMin, layout.selectionRect.xMin - kVBarWidth, layout.selectionRect.height); - layout.selectionTopRect = new Rect(layout.selectionRect.xMin, contentRect.yMin + kHBarHeight, layout.selectionRect.width, layout.selectionRect.yMin - kHBarHeight); - - layout.underlayTopRect = new Rect(contentRect.xMin, contentRect.yMin, contentRect.width, kHBarHeight); - layout.underlayLeftRect = new Rect(contentRect.xMin, contentRect.yMin + kHBarHeight, kVBarWidth, contentRect.height - kHBarHeight); - - return layout; - } - - private void DrawLabels() - { - if (dragMode == DragMode.None) - return; - - RectangleToolFlags flags = m_CurveEditor.settings.rectangleToolFlags; - - bool canScaleX = !Mathf.Approximately(selectionBounds.size.x, 0f); - bool canScaleY = !Mathf.Approximately(selectionBounds.size.y, 0f); - - if (flags == RectangleToolFlags.FullRectangleTool) - { - // Horizontal labels - if ((dragMode & DragMode.MoveScaleHorizontal) != 0) - { - if (canScaleX) - { - GUIContent leftLabelContent = new GUIContent(string.Format("{0}", m_CurveEditor.FormatTime(selectionBounds.min.x, m_CurveEditor.invSnap, m_CurveEditor.timeFormat))); - GUIContent rightLabelContent = new GUIContent(string.Format("{0}", m_CurveEditor.FormatTime(selectionBounds.max.x, m_CurveEditor.invSnap, m_CurveEditor.timeFormat))); - - Vector2 leftLabelSize = styles.dragLabel.CalcSize(leftLabelContent); - Vector2 rightLabelSize = styles.dragLabel.CalcSize(rightLabelContent); - - EditorGUI.DoDropShadowLabel(new Rect(m_Layout.leftLabelAnchor.x - leftLabelSize.x, m_Layout.leftLabelAnchor.y, leftLabelSize.x, leftLabelSize.y), leftLabelContent, styles.dragLabel, 0.3f); - EditorGUI.DoDropShadowLabel(new Rect(m_Layout.rightLabelAnchor.x, m_Layout.rightLabelAnchor.y, rightLabelSize.x, rightLabelSize.y), rightLabelContent, styles.dragLabel, 0.3f); - } - else - { - GUIContent labelContent = new GUIContent(string.Format("{0}", m_CurveEditor.FormatTime(selectionBounds.center.x, m_CurveEditor.invSnap, m_CurveEditor.timeFormat))); - Vector2 labelSize = styles.dragLabel.CalcSize(labelContent); - - EditorGUI.DoDropShadowLabel(new Rect(m_Layout.leftLabelAnchor.x, m_Layout.leftLabelAnchor.y, labelSize.x, labelSize.y), labelContent, styles.dragLabel, 0.3f); - } - } - - // Vertical labels - if ((dragMode & DragMode.MoveScaleVertical) != 0) - { - if (canScaleY) - { - GUIContent bottomLabelContent = new GUIContent(string.Format("{0}", m_CurveEditor.FormatValue(selectionBounds.min.y))); - GUIContent topLabelContent = new GUIContent(string.Format("{0}", m_CurveEditor.FormatValue(selectionBounds.max.y))); - - Vector2 bottomLabelSize = styles.dragLabel.CalcSize(bottomLabelContent); - Vector2 topLabelSize = styles.dragLabel.CalcSize(topLabelContent); - - EditorGUI.DoDropShadowLabel(new Rect(m_Layout.bottomLabelAnchor.x, m_Layout.bottomLabelAnchor.y, bottomLabelSize.x, bottomLabelSize.y), bottomLabelContent, styles.dragLabel, 0.3f); - EditorGUI.DoDropShadowLabel(new Rect(m_Layout.topLabelAnchor.x, m_Layout.topLabelAnchor.y - topLabelSize.y, topLabelSize.x, topLabelSize.y), topLabelContent, styles.dragLabel, 0.3f); - } - else - { - GUIContent labelContent = new GUIContent(string.Format("{0}", m_CurveEditor.FormatValue(selectionBounds.center.y))); - Vector2 labelSize = styles.dragLabel.CalcSize(labelContent); - - EditorGUI.DoDropShadowLabel(new Rect(m_Layout.topLabelAnchor.x, m_Layout.topLabelAnchor.y - labelSize.y, labelSize.x, labelSize.y), labelContent, styles.dragLabel, 0.3f); - } - } - } - else if (flags == RectangleToolFlags.MiniRectangleTool) - { - if ((dragMode & DragMode.MoveBothAxis) != 0) - { - Vector2 localPosition = (canScaleX || canScaleY) ? new Vector2(PixelToTime(Event.current.mousePosition.x, frameRate), PixelToValue(Event.current.mousePosition.y)) : (Vector2)selectionBounds.center; - Vector2 labelPosition = new Vector2(TimeToPixel(localPosition.x), ValueToPixel(localPosition.y)); - - GUIContent labelContent = new GUIContent(string.Format("{0}, {1}", m_CurveEditor.FormatTime(localPosition.x, m_CurveEditor.invSnap, m_CurveEditor.timeFormat), m_CurveEditor.FormatValue(localPosition.y))); - Vector2 labelSize = styles.dragLabel.CalcSize(labelContent); - - EditorGUI.DoDropShadowLabel(new Rect(labelPosition.x, labelPosition.y - labelSize.y, labelSize.x, labelSize.y), labelContent, styles.dragLabel, 0.3f); - } - } - } - - private void OnStartScale(ToolCoord pivotCoord, ToolCoord pickedCoord, Vector2 mousePos, DragMode dragMode, bool rippleTime) - { - Bounds bounds = selectionBounds; - m_DragMode = dragMode; - m_Pivot = ToolCoordToPosition(pivotCoord, bounds); - m_Previous = ToolCoordToPosition(pickedCoord, bounds); - m_MouseOffset = mousePos - m_Previous; - m_RippleTime = rippleTime; - m_RippleTimeStart = bounds.min.x; - m_RippleTimeEnd = bounds.max.x; - - m_CurveEditor.StartLiveEdit(); - } - - private void OnScaleTime(float time) - { - Matrix4x4 transform; - bool flipX; - if (CalculateScaleTimeMatrix(m_Previous.x, time, m_MouseOffset.x, m_Pivot.x, frameRate, out transform, out flipX)) - TransformKeys(transform, flipX, false); - } - - private void OnScaleValue(float val) - { - Matrix4x4 transform; - bool flipY; - if (CalculateScaleValueMatrix(m_Previous.y, val, m_MouseOffset.y, m_Pivot.y, out transform, out flipY)) - TransformKeys(transform, false, flipY); - } - - private void OnEndScale() - { - m_CurveEditor.EndLiveEdit(); - m_DragMode = DragMode.None; - GUI.changed = true; - } - - internal void OnStartMove(Vector2 position, bool rippleTime) - { - OnStartMove(position, DragMode.None, rippleTime); - } - - private void OnStartMove(Vector2 position, DragMode dragMode, bool rippleTime) - { - Bounds bounds = selectionBounds; - - m_DragMode = dragMode; - m_Previous = position; - m_RippleTime = rippleTime; - m_RippleTimeStart = bounds.min.x; - m_RippleTimeEnd = bounds.max.x; - - m_CurveEditor.StartLiveEdit(); - } - - internal void OnMove(Vector2 position) - { - Vector2 dv = position - m_Previous; - - Matrix4x4 transform = Matrix4x4.identity; - transform.SetTRS(new Vector3(dv.x, dv.y, 0f), Quaternion.identity, Vector3.one); - - TransformKeys(transform, false, false); - } - - internal void OnEndMove() - { - m_CurveEditor.EndLiveEdit(); - m_DragMode = DragMode.None; - GUI.changed = true; - } - - private void TransformKeys(Matrix4x4 matrix, bool flipX, bool flipY) - { - if (m_RippleTime) - { - m_CurveEditor.TransformRippleKeys(matrix, m_RippleTimeStart, m_RippleTimeEnd, flipX); - GUI.changed = true; - } - else - { - m_CurveEditor.TransformSelectedKeys(matrix, flipX, flipY); - GUI.changed = true; - } - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditorSelection.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditorSelection.cs deleted file mode 100644 index b6c3381dba..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveEditorSelection.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using System.Collections; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [System.Serializable] - internal class CurveEditorSelection : ScriptableObject - { - [SerializeField] private List m_SelectedCurves; - - public List selectedCurves - { - get { return m_SelectedCurves ?? (m_SelectedCurves = new List()); } - set { m_SelectedCurves = value; } - } - } - - [System.Serializable] - internal class CurveSelection : System.IComparable - { - internal enum SelectionType - { - Key = 0, - InTangent = 1, - OutTangent = 2, - Count = 3, - } - - [SerializeField] public int curveID = 0; - [SerializeField] public int key = -1; - [SerializeField] public bool semiSelected = false; - [SerializeField] public SelectionType type; - - internal CurveSelection(int curveID, int key) - { - this.curveID = curveID; - this.key = key; - this.type = SelectionType.Key; - } - - internal CurveSelection(int curveID, int key, SelectionType type) - { - this.curveID = curveID; - this.key = key; - this.type = type; - } - - public int CompareTo(object _other) - { - CurveSelection other = (CurveSelection)_other; - int cmp = curveID - other.curveID; - if (cmp != 0) - return cmp; - - cmp = key - other.key; - if (cmp != 0) - return cmp; - - return (int)type - (int)other.type; - } - - public override bool Equals(object _other) - { - CurveSelection other = (CurveSelection)_other; - return other.curveID == curveID && other.key == key && other.type == type; - } - - public override int GetHashCode() - { - return curveID * 729 + key * 27 + (int)type; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs deleted file mode 100644 index 7ad4ba2c6c..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [System.Serializable] - internal class CurveEditorSettings - { - // Label settings - private TickStyle m_HTickStyle = new TickStyle(); - private TickStyle m_VTickStyle = new TickStyle(); - - internal TickStyle hTickStyle { get { return m_HTickStyle; } set { m_HTickStyle = value; } } - internal TickStyle vTickStyle { get { return m_VTickStyle; } set { m_VTickStyle = value; } } - - // Range lock settings - private bool m_HRangeLocked; - private bool m_VRangeLocked; - internal bool hRangeLocked { get { return m_HRangeLocked; } set { m_HRangeLocked = value; } } - internal bool vRangeLocked { get { return m_VRangeLocked; } set { m_VRangeLocked = value; } } - - // Range settings - private float m_HRangeMin = Mathf.NegativeInfinity; - private float m_HRangeMax = Mathf.Infinity; - private float m_VRangeMin = Mathf.NegativeInfinity; - private float m_VRangeMax = Mathf.Infinity; - public float hRangeMin { get { return m_HRangeMin; } set { m_HRangeMin = value; } } - public float hRangeMax { get { return m_HRangeMax; } set { m_HRangeMax = value; } } - public float vRangeMin { get { return m_VRangeMin; } set { m_VRangeMin = value; } } - public float vRangeMax { get { return m_VRangeMax; } set { m_VRangeMax = value; } } - public bool hasUnboundedRanges - { - get - { - return - m_HRangeMin == Mathf.NegativeInfinity || - m_HRangeMax == Mathf.Infinity || - m_VRangeMin == Mathf.NegativeInfinity || - m_VRangeMax == Mathf.Infinity; - } - } - - // Offset to move the labels along the horizontal axis to make room for the overlaid scrollbar in the - // curve editor popup. - public float hTickLabelOffset = 0; - public EditorGUIUtility.SkinnedColor wrapColor = new EditorGUIUtility.SkinnedColor(new Color(1.0f, 1.0f, 1.0f, 0.5f), new Color(.65f, .65f, .65f, 0.5f)); - public bool useFocusColors = false; - public bool showAxisLabels = true; - public bool showWrapperPopups = false; - public bool allowDraggingCurvesAndRegions = true; - public bool allowDeleteLastKeyInCurve = false; - public bool undoRedoSelection = false; - - // Display options - internal enum RectangleToolFlags - { - NoRectangleTool, - MiniRectangleTool, - FullRectangleTool - } - - internal RectangleToolFlags rectangleToolFlags = RectangleToolFlags.NoRectangleTool; - - // Window resize settings - private bool m_ScaleWithWindow = true; - internal bool scaleWithWindow { get { return m_ScaleWithWindow; } set { m_ScaleWithWindow = value; } } - - // Slider settings - private bool m_HSlider = true; - private bool m_VSlider = true; - public bool hSlider { get { return m_HSlider; } set { m_HSlider = value; } } - public bool vSlider { get { return m_VSlider; } set { m_VSlider = value; } } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditorWindow.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditorWindow.cs deleted file mode 100644 index 43645f630a..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveEditorWindow.cs +++ /dev/null @@ -1,602 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Linq; - -using TangentMode = UnityEditor.AnimationUtility.TangentMode; - -namespace UnityEditor -{ - internal enum WrapModeFixedCurve - { - Clamp = (int)WrapMode.ClampForever, - Loop = (int)WrapMode.Loop, - PingPong = (int)WrapMode.PingPong - } - - [Serializable] - internal class CurveEditorWindow : EditorWindow - { - enum NormalizationMode - { - None = 0, - Normalize = 1, - Denormalize = 2, - } - - //const int kToolbarHeight = 17; - const int kPresetsHeight = 46; - - static CurveEditorWindow s_SharedCurveEditor; - - CurveEditor m_CurveEditor; - - AnimationCurve m_Curve; - Color m_Color; - - CurvePresetsContentsForPopupWindow m_CurvePresets; - GUIContent m_GUIContent = new GUIContent(); - - [SerializeField] - GUIView delegateView; - - public const string CurveChangedCommand = "CurveChanged"; - public const string CurveChangeCompletedCommand = "CurveChangeCompleted"; - - public static CurveEditorWindow instance - { - get - { - if (!s_SharedCurveEditor) - s_SharedCurveEditor = ScriptableObject.CreateInstance(); - return s_SharedCurveEditor; - } - } - - public string currentPresetLibrary - { - get - { - InitCurvePresets(); - return m_CurvePresets.currentPresetLibrary; - } - set - { - InitCurvePresets(); - m_CurvePresets.currentPresetLibrary = value; - } - } - - public static AnimationCurve curve - { - get { return visible ? CurveEditorWindow.instance.m_Curve : null; } - set - { - if (value == null) - { - CurveEditorWindow.instance.m_Curve = null; - } - else - { - CurveEditorWindow.instance.m_Curve = value; - CurveEditorWindow.instance.RefreshShownCurves(); - } - } - } - - public static Color color - { - get { return CurveEditorWindow.instance.m_Color; } - set - { - CurveEditorWindow.instance.m_Color = value; - CurveEditorWindow.instance.RefreshShownCurves(); - } - } - - public static bool visible - { - get { return s_SharedCurveEditor != null; } - } - - void OnEnable() - { - s_SharedCurveEditor = this; - Init(null); - } - - // Called by OnEnable to make sure the CurveEditor is not null, - // and by Show so we get a fresh CurveEditor when the user clicks a new curve. - void Init(CurveEditorSettings settings) - { - m_CurveEditor = new CurveEditor(GetCurveEditorRect(), GetCurveWrapperArray(), true); - m_CurveEditor.curvesUpdated = UpdateCurve; - m_CurveEditor.scaleWithWindow = true; - m_CurveEditor.margin = 40; - if (settings != null) - m_CurveEditor.settings = settings; - m_CurveEditor.settings.hTickLabelOffset = 10; - m_CurveEditor.settings.rectangleToolFlags = CurveEditorSettings.RectangleToolFlags.MiniRectangleTool; - - // As there is no guarantee animation curve changes are recorded in undo redo, we can't really - // handle curve selection in undo redo either. - m_CurveEditor.settings.undoRedoSelection = false; - m_CurveEditor.settings.showWrapperPopups = true; - - // For each of horizontal and vertical axis, if we have a finite range for that axis, use that range, - // otherwise use framing logic to determine shown range for that axis. - bool frameH = true; - bool frameV = true; - if (m_CurveEditor.settings.hRangeMin != Mathf.NegativeInfinity && m_CurveEditor.settings.hRangeMax != Mathf.Infinity) - { - m_CurveEditor.SetShownHRangeInsideMargins(m_CurveEditor.settings.hRangeMin, m_CurveEditor.settings.hRangeMax); - frameH = false; - } - if (m_CurveEditor.settings.vRangeMin != Mathf.NegativeInfinity && m_CurveEditor.settings.vRangeMax != Mathf.Infinity) - { - m_CurveEditor.SetShownVRangeInsideMargins(m_CurveEditor.settings.vRangeMin, m_CurveEditor.settings.vRangeMax); - frameV = false; - } - - m_CurveEditor.FrameSelected(frameH, frameV); - - titleContent = EditorGUIUtility.TrTextContent("Curve"); - - // deal with window size - minSize = new Vector2(240, 240 + kPresetsHeight); - maxSize = new Vector2(10000, 10000); - } - - CurveLibraryType curveLibraryType - { - get - { - if (m_CurveEditor.settings.hasUnboundedRanges) - return CurveLibraryType.Unbounded; - return CurveLibraryType.NormalizedZeroToOne; - } - } - - // Returns true if a valid normalizationRect is returned (ranges are bounded) - bool GetNormalizationRect(out Rect normalizationRect) - { - normalizationRect = new Rect(); - if (m_CurveEditor.settings.hasUnboundedRanges) - return false; - - normalizationRect = new Rect( - m_CurveEditor.settings.hRangeMin, - m_CurveEditor.settings.vRangeMin, - m_CurveEditor.settings.hRangeMax - m_CurveEditor.settings.hRangeMin, - m_CurveEditor.settings.vRangeMax - m_CurveEditor.settings.vRangeMin); - return true; - } - - static Keyframe[] CopyAndScaleCurveKeys(Keyframe[] orgKeys, Rect rect, NormalizationMode normalization) - { - Keyframe[] scaledKeys = new Keyframe[orgKeys.Length]; - orgKeys.CopyTo(scaledKeys, 0); - if (normalization == NormalizationMode.None) - return scaledKeys; - - if (rect.width == 0f || rect.height == 0f || Single.IsInfinity(rect.width) || Single.IsInfinity(rect.height)) - { - Debug.LogError("CopyAndScaleCurve: Invalid scale: " + rect); - return scaledKeys; - } - - float tangentMultiplier = rect.height / rect.width; - switch (normalization) - { - case NormalizationMode.Normalize: - for (int i = 0; i < scaledKeys.Length; ++i) - { - scaledKeys[i].time = (orgKeys[i].time - rect.xMin) / rect.width; - scaledKeys[i].value = (orgKeys[i].value - rect.yMin) / rect.height; - if (!Single.IsInfinity(orgKeys[i].inTangent)) - scaledKeys[i].inTangent = orgKeys[i].inTangent / tangentMultiplier; - if (!Single.IsInfinity(orgKeys[i].outTangent)) - scaledKeys[i].outTangent = orgKeys[i].outTangent / tangentMultiplier; - } - break; - case NormalizationMode.Denormalize: - // From normalized to real - for (int i = 0; i < scaledKeys.Length; ++i) - { - scaledKeys[i].time = orgKeys[i].time * rect.width + rect.xMin; - scaledKeys[i].value = orgKeys[i].value * rect.height + rect.yMin; - if (!Single.IsInfinity(orgKeys[i].inTangent)) - scaledKeys[i].inTangent = orgKeys[i].inTangent * tangentMultiplier; - if (!Single.IsInfinity(orgKeys[i].outTangent)) - scaledKeys[i].outTangent = orgKeys[i].outTangent * tangentMultiplier; - } - break; - } - - return scaledKeys; - } - - void InitCurvePresets() - { - if (m_CurvePresets == null) - { - // Selection callback for library window - Action presetSelectedCallback = delegate(AnimationCurve presetCurve) - { - ValidateCurveLibraryTypeAndScale(); - - // Scale curve up using ranges - m_Curve.keys = GetDenormalizedKeys(presetCurve.keys); - m_Curve.postWrapMode = presetCurve.postWrapMode; - m_Curve.preWrapMode = presetCurve.preWrapMode; - - m_CurveEditor.SelectNone(); - RefreshShownCurves(); - SendEvent(CurveChangedCommand, true); - }; - - // We set the curve to save when showing the popup to ensure to scale the current state of the curve - AnimationCurve curveToSaveAsPreset = null; - m_CurvePresets = new CurvePresetsContentsForPopupWindow(curveToSaveAsPreset, curveLibraryType, presetSelectedCallback); - m_CurvePresets.InitIfNeeded(); - } - } - - void OnDestroy() - { - if (m_CurvePresets != null) - m_CurvePresets.GetPresetLibraryEditor().UnloadUsedLibraries(); - } - - void OnDisable() - { - m_CurveEditor.OnDisable(); - if (s_SharedCurveEditor == this) - s_SharedCurveEditor = null; - else if (!this.Equals(s_SharedCurveEditor)) - throw new ApplicationException("s_SharedCurveEditor does not equal this"); - } - - private void RefreshShownCurves() - { - m_CurveEditor.animationCurves = GetCurveWrapperArray(); - } - - public void Show(GUIView viewToUpdate, CurveEditorSettings settings) - { - delegateView = viewToUpdate; - m_OnCurveChanged = null; - - Init(settings); - ShowAuxWindow(); - } - - Action m_OnCurveChanged; - - public void Show(Action onCurveChanged, CurveEditorSettings settings) - { - m_OnCurveChanged = onCurveChanged; - delegateView = null; - - Init(settings); - ShowAuxWindow(); - } - - internal class Styles - { - public GUIStyle curveEditorBackground = "PopupCurveEditorBackground"; - public GUIStyle miniToolbarPopup = "MiniToolbarPopup"; - public GUIStyle miniToolbarButton = "MiniToolbarButtonLeft"; - public GUIStyle curveSwatch = "PopupCurveEditorSwatch"; - public GUIStyle curveSwatchArea = "PopupCurveSwatchBackground"; - public GUIStyle curveWrapPopup = "PopupCurveDropdown"; - } - internal static Styles ms_Styles; - - CurveWrapper[] GetCurveWrapperArray() - { - if (m_Curve == null) - return new CurveWrapper[] {}; - CurveWrapper cw = new CurveWrapper(); - cw.id = "Curve".GetHashCode(); - cw.groupId = -1; - cw.color = m_Color; - cw.hidden = false; - cw.readOnly = false; - cw.renderer = new NormalCurveRenderer(m_Curve); - cw.renderer.SetWrap(m_Curve.preWrapMode, m_Curve.postWrapMode); - return new CurveWrapper[] { cw }; - } - - Rect GetCurveEditorRect() - { - //return new Rect(0, kToolbarHeight, position.width, position.height-kToolbarHeight); - return new Rect(0, 0, position.width, position.height - kPresetsHeight); - } - - static internal Keyframe[] GetLinearKeys() - { - Keyframe[] keys = new Keyframe[2]; - keys[0] = new Keyframe(0, 0, 1, 1); - keys[1] = new Keyframe(1, 1, 1, 1); - SetSmoothEditable(ref keys); - return keys; - } - - static internal Keyframe[] GetLinearMirrorKeys() - { - Keyframe[] keys = new Keyframe[2]; - keys[0] = new Keyframe(0, 1, -1, -1); - keys[1] = new Keyframe(1, 0, -1, -1); - SetSmoothEditable(ref keys); - return keys; - } - - static internal Keyframe[] GetEaseInKeys() - { - Keyframe[] keys = new Keyframe[2]; - keys[0] = new Keyframe(0, 0, 0, 0); - keys[1] = new Keyframe(1, 1, 2, 2); - SetSmoothEditable(ref keys); - return keys; - } - - static internal Keyframe[] GetEaseInMirrorKeys() - { - Keyframe[] keys = new Keyframe[2]; - keys[0] = new Keyframe(0, 1, -2, -2); - keys[1] = new Keyframe(1, 0, 0, 0); - SetSmoothEditable(ref keys); - return keys; - } - - static internal Keyframe[] GetEaseOutKeys() - { - Keyframe[] keys = new Keyframe[2]; - keys[0] = new Keyframe(0, 0, 2, 2); - keys[1] = new Keyframe(1, 1, 0, 0); - SetSmoothEditable(ref keys); - return keys; - } - - static internal Keyframe[] GetEaseOutMirrorKeys() - { - Keyframe[] keys = new Keyframe[2]; - keys[0] = new Keyframe(0, 1, 0, 0); - keys[1] = new Keyframe(1, 0, -2, -2); - SetSmoothEditable(ref keys); - return keys; - } - - static internal Keyframe[] GetEaseInOutKeys() - { - Keyframe[] keys = new Keyframe[2]; - keys[0] = new Keyframe(0, 0, 0, 0); - keys[1] = new Keyframe(1, 1, 0, 0); - SetSmoothEditable(ref keys); - return keys; - } - - static internal Keyframe[] GetEaseInOutMirrorKeys() - { - Keyframe[] keys = new Keyframe[2]; - keys[0] = new Keyframe(0, 1, 0, 0); - keys[1] = new Keyframe(1, 0, 0, 0); - SetSmoothEditable(ref keys); - return keys; - } - - static internal Keyframe[] GetConstantKeys(float value) - { - Keyframe[] keys = new Keyframe[2]; - keys[0] = new Keyframe(0, value, 0, 0); - keys[1] = new Keyframe(1, value, 0, 0); - SetSmoothEditable(ref keys); - return keys; - } - - static internal void SetSmoothEditable(ref Keyframe[] keys) - { - for (int i = 0; i < keys.Length; i++) - { - AnimationUtility.SetKeyBroken(ref keys[i], false); - AnimationUtility.SetKeyLeftTangentMode(ref keys[i], TangentMode.Free); - AnimationUtility.SetKeyRightTangentMode(ref keys[i], TangentMode.Free); - } - } - - Keyframe[] NormalizeKeys(Keyframe[] sourceKeys, NormalizationMode normalization) - { - Rect normalizationRect; - if (!GetNormalizationRect(out normalizationRect)) - // No normalization rect, just return a copy of the source keyframes - normalization = NormalizationMode.None; - return CopyAndScaleCurveKeys(sourceKeys, normalizationRect, normalization); - } - - Keyframe[] GetDenormalizedKeys(Keyframe[] sourceKeys) - { - return NormalizeKeys(sourceKeys, NormalizationMode.Denormalize); - } - - Keyframe[] GetNormalizedKeys(Keyframe[] sourceKeys) - { - return NormalizeKeys(sourceKeys, NormalizationMode.Normalize); - } - - void OnGUI() - { - bool gotMouseUp = (Event.current.type == EventType.MouseUp); - - if (delegateView == null && m_OnCurveChanged == null) - m_Curve = null; - - if (ms_Styles == null) - ms_Styles = new Styles(); - - // Curve Editor - m_CurveEditor.rect = GetCurveEditorRect(); - m_CurveEditor.hRangeLocked = Event.current.shift; - m_CurveEditor.vRangeLocked = EditorGUI.actionKey; - - GUI.changed = false; - - GUI.Label(m_CurveEditor.drawRect, GUIContent.none, ms_Styles.curveEditorBackground); - m_CurveEditor.OnGUI(); - - // Preset swatch area - GUI.Box(new Rect(0, position.height - kPresetsHeight, position.width, kPresetsHeight), "", ms_Styles.curveSwatchArea); - Color curveColor = m_Color; - curveColor.a *= 0.6f; - const float margin = 45f; - const float width = 40f; - const float height = 25f; - float yPos = position.height - kPresetsHeight + (kPresetsHeight - height) * 0.5f; - InitCurvePresets(); - CurvePresetLibrary curveLibrary = m_CurvePresets.GetPresetLibraryEditor().GetCurrentLib(); - if (curveLibrary != null) - { - for (int i = 0; i < curveLibrary.Count(); i++) - { - Rect swatchRect = new Rect(margin + (width + 5f) * i, yPos, width, height); - m_GUIContent.tooltip = curveLibrary.GetName(i); - if (GUI.Button(swatchRect, m_GUIContent, ms_Styles.curveSwatch)) - { - AnimationCurve animCurve = curveLibrary.GetPreset(i) as AnimationCurve; - m_Curve.keys = GetDenormalizedKeys(animCurve.keys); - m_Curve.postWrapMode = animCurve.postWrapMode; - m_Curve.preWrapMode = animCurve.preWrapMode; - m_CurveEditor.SelectNone(); - SendEvent(CurveChangedCommand, true); - } - if (Event.current.type == EventType.Repaint) - curveLibrary.Draw(swatchRect, i); - - if (swatchRect.xMax > position.width - 2 * margin) - break; - } - } - - Rect presetDropDownButtonRect = new Rect(margin - 20f, yPos + 5f, 20, 20); - PresetDropDown(presetDropDownButtonRect); - - // For adding default preset curves - //if (EditorGUI.DropdownButton(new Rect (position.width -26, yPos, 20, 20), GUIContent.none, FocusType.Passive, "OL Plus")) - // AddDefaultPresetsToCurrentLib (); - - if (Event.current.type == EventType.Used && gotMouseUp) - { - DoUpdateCurve(false); - SendEvent(CurveChangeCompletedCommand, true); - } - else if (Event.current.type != EventType.Layout && Event.current.type != EventType.Repaint) - { - DoUpdateCurve(true); - } - } - - void PresetDropDown(Rect rect) - { - if (EditorGUI.DropdownButton(rect, EditorGUI.GUIContents.titleSettingsIcon, FocusType.Passive, EditorStyles.inspectorTitlebarText)) - { - if (m_Curve != null) - { - if (m_CurvePresets == null) - { - Debug.LogError("Curve presets error"); - return; - } - - ValidateCurveLibraryTypeAndScale(); - - AnimationCurve copy = new AnimationCurve(GetNormalizedKeys(m_Curve.keys)); - copy.postWrapMode = m_Curve.postWrapMode; - copy.preWrapMode = m_Curve.preWrapMode; - - m_CurvePresets.curveToSaveAsPreset = copy; - PopupWindow.Show(rect, m_CurvePresets); - } - } - } - - void ValidateCurveLibraryTypeAndScale() - { - Rect normalizationRect; - if (GetNormalizationRect(out normalizationRect)) - { - if (curveLibraryType != CurveLibraryType.NormalizedZeroToOne) - Debug.LogError("When having a normalize rect we should be using curve library type: NormalizedZeroToOne (normalizationRect: " + normalizationRect + ")"); - } - else - { - if (curveLibraryType != CurveLibraryType.Unbounded) - Debug.LogError("When NOT having a normalize rect we should be using library type: Unbounded"); - } - } - - // Polynomial curves have limitations on how they have to be authored. - // Since we don't enforce the layout, we have a button that enforces the curve layout instead. - /* - void OptimizePolynomialCurve (Rect rect) - { - ///@TODO: only show this when editing shuriken curves.... - - bool wasEnabled = GUI.enabled; - - bool isValidPolynomialCurve = true; - for (int i=0;i 0 - && m_CurveEditor.animationCurves[0] != null - && m_CurveEditor.animationCurves[0].changed) - { - m_CurveEditor.animationCurves[0].changed = false; - RefreshShownCurves(); - SendEvent(CurveChangedCommand, exitGUI); - } - } - - void SendEvent(string eventName, bool exitGUI) - { - if (delegateView) - { - Event e = EditorGUIUtility.CommandEvent(eventName); - Repaint(); - delegateView.SendEvent(e); - if (exitGUI) - GUIUtility.ExitGUI(); - } - - if (m_OnCurveChanged != null) - { - m_OnCurveChanged(curve); - } - GUI.changed = true; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/CurveMenuManager.cs b/Editor/Mono/Animation/AnimationWindow/CurveMenuManager.cs deleted file mode 100644 index 1db96f0775..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveMenuManager.cs +++ /dev/null @@ -1,364 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -using TangentMode = UnityEditor.AnimationUtility.TangentMode; - -namespace UnityEditor -{ - internal class ChangedCurve - { - public AnimationCurve curve; - public int curveId; - public EditorCurveBinding binding; - - public ChangedCurve(AnimationCurve curve, int curveId, EditorCurveBinding binding) - { - this.curve = curve; - this.curveId = curveId; - this.binding = binding; - } - - public override int GetHashCode() - { - int hash = 0; - unchecked - { - hash = curve.GetHashCode(); - hash = 33 * hash + binding.GetHashCode(); - } - return hash; - } - } - - internal class KeyIdentifier - { - public AnimationCurve curve; - public int curveId; - public int key; - - // Used by dopesheet - public EditorCurveBinding binding; - - public KeyIdentifier(AnimationCurve _curve, int _curveId, int _keyIndex) - { - curve = _curve; - curveId = _curveId; - key = _keyIndex; - } - - public KeyIdentifier(AnimationCurve _curve, int _curveId, int _keyIndex, EditorCurveBinding _binding) - { - curve = _curve; - curveId = _curveId; - key = _keyIndex; - binding = _binding; - } - - public Keyframe keyframe { get { return curve[key]; } } - } - - internal interface CurveUpdater - { - void UpdateCurves(List curve, string undoText); - } - - internal class CurveMenuManager - { - CurveUpdater updater; - - public CurveMenuManager(CurveUpdater updater) - { - this.updater = updater; - } - - public void AddTangentMenuItems(GenericMenu menu, List keyList) - { - bool anyKeys = (keyList.Count > 0); - // Find out which qualities apply to all the keys - bool allClampedAuto = anyKeys; - bool allAuto = anyKeys; - bool allFreeSmooth = anyKeys; - bool allFlat = anyKeys; - bool allBroken = anyKeys; - bool allLeftWeighted = anyKeys; - bool allLeftFree = anyKeys; - bool allLeftLinear = anyKeys; - bool allLeftConstant = anyKeys; - bool allRightWeighted = anyKeys; - bool allRightFree = anyKeys; - bool allRightLinear = anyKeys; - bool allRightConstant = anyKeys; - foreach (KeyIdentifier sel in keyList) - { - Keyframe key = sel.keyframe; - TangentMode leftMode = AnimationUtility.GetKeyLeftTangentMode(key); - TangentMode rightMode = AnimationUtility.GetKeyRightTangentMode(key); - bool broken = AnimationUtility.GetKeyBroken(key); - if (leftMode != TangentMode.ClampedAuto || rightMode != TangentMode.ClampedAuto) allClampedAuto = false; - if (leftMode != TangentMode.Auto || rightMode != TangentMode.Auto) allAuto = false; - if (broken || leftMode != TangentMode.Free || rightMode != TangentMode.Free) allFreeSmooth = false; - if (broken || leftMode != TangentMode.Free || key.inTangent != 0 || rightMode != TangentMode.Free || key.outTangent != 0) allFlat = false; - if (!broken) allBroken = false; - if (!broken || leftMode != TangentMode.Free) allLeftFree = false; - if (!broken || leftMode != TangentMode.Linear) allLeftLinear = false; - if (!broken || leftMode != TangentMode.Constant) allLeftConstant = false; - if (!broken || rightMode != TangentMode.Free) allRightFree = false; - if (!broken || rightMode != TangentMode.Linear) allRightLinear = false; - if (!broken || rightMode != TangentMode.Constant) allRightConstant = false; - - - if ((key.weightedMode & WeightedMode.In) == WeightedMode.None) allLeftWeighted = false; - if ((key.weightedMode & WeightedMode.Out) == WeightedMode.None) allRightWeighted = false; - } - if (anyKeys) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Clamped Auto"), allClampedAuto, SetClampedAuto, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Auto"), allAuto, SetAuto, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Free Smooth"), allFreeSmooth, SetEditable, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Flat"), allFlat, SetFlat, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Broken"), allBroken, SetBroken, keyList); - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Free"), allLeftFree, SetLeftEditable, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Linear"), allLeftLinear, SetLeftLinear, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Constant"), allLeftConstant, SetLeftConstant, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Left Tangent/Weighted"), allLeftWeighted, ToggleLeftWeighted, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Free"), allRightFree, SetRightEditable, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Linear"), allRightLinear, SetRightLinear, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Constant"), allRightConstant, SetRightConstant, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Right Tangent/Weighted"), allRightWeighted, ToggleRightWeighted, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Free"), allRightFree && allLeftFree, SetBothEditable, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Linear"), allRightLinear && allLeftLinear, SetBothLinear, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Constant"), allRightConstant && allLeftConstant, SetBothConstant, keyList); - menu.AddItem(EditorGUIUtility.TrTextContent("Both Tangents/Weighted"), allRightWeighted && allLeftWeighted, ToggleBothWeighted, keyList); - } - else - { - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Weighted")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Auto")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Free Smooth")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Flat")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Broken")); - menu.AddSeparator(""); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Free")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Linear")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Constant")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Left Tangent/Weighted")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Free")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Linear")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Constant")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Right Tangent/Weighted")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Free")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Linear")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Constant")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Both Tangents/Weighted")); - } - } - - public void ToggleLeftWeighted(object keysToSet) { ToggleWeighted(WeightedMode.In, (List)keysToSet); } - public void ToggleRightWeighted(object keysToSet) { ToggleWeighted(WeightedMode.Out, (List)keysToSet); } - public void ToggleBothWeighted(object keysToSet) { ToggleWeighted(WeightedMode.Both, (List)keysToSet); } - public void ToggleWeighted(WeightedMode weightedMode, List keysToSet) - { - bool allWeighted = keysToSet.TrueForAll(key => (key.keyframe.weightedMode & weightedMode) == weightedMode); - - List changedCurves = new List(); - foreach (KeyIdentifier keyToSet in keysToSet) - { - AnimationCurve animationCurve = keyToSet.curve; - Keyframe key = keyToSet.keyframe; - - bool weighted = (key.weightedMode & weightedMode) == weightedMode; - if (weighted == allWeighted) - { - WeightedMode lastWeightedMode = key.weightedMode; - key.weightedMode = weighted ? key.weightedMode & ~weightedMode : key.weightedMode | weightedMode; - - if (key.weightedMode != WeightedMode.None) - { - TangentMode rightTangentMode = AnimationUtility.GetKeyRightTangentMode(key); - TangentMode leftTangentMode = AnimationUtility.GetKeyLeftTangentMode(key); - - if ((lastWeightedMode & WeightedMode.Out) == WeightedMode.None && (key.weightedMode & WeightedMode.Out) == WeightedMode.Out) - { - if (rightTangentMode == TangentMode.Linear || rightTangentMode == TangentMode.Constant) - AnimationUtility.SetKeyRightTangentMode(ref key, TangentMode.Free); - if (keyToSet.key < (animationCurve.length - 1)) - key.outWeight = 1 / 3.0f; - } - - if ((lastWeightedMode & WeightedMode.In) == WeightedMode.None && (key.weightedMode & WeightedMode.In) == WeightedMode.In) - { - if (leftTangentMode == TangentMode.Linear || leftTangentMode == TangentMode.Constant) - AnimationUtility.SetKeyLeftTangentMode(ref key, TangentMode.Free); - if (keyToSet.key > 0) - key.inWeight = 1 / 3.0f; - } - } - - animationCurve.MoveKey(keyToSet.key, key); - AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyToSet.key); - - ChangedCurve changedCurve = new ChangedCurve(animationCurve, keyToSet.curveId, keyToSet.binding); - if (!changedCurves.Contains(changedCurve)) - changedCurves.Add(changedCurve); - } - } - - updater.UpdateCurves(changedCurves, "Toggle Weighted"); - } - - public void SetClampedAuto(object keysToSet) { SetBoth(TangentMode.ClampedAuto, (List)keysToSet); } - public void SetAuto(object keysToSet) { SetBoth(TangentMode.Auto, (List)keysToSet); } - public void SetEditable(object keysToSet) { SetBoth(TangentMode.Free, (List)keysToSet); } - public void SetFlat(object keysToSet) { SetBoth(TangentMode.Free, (List)keysToSet); Flatten((List)keysToSet); } - public void SetBoth(TangentMode mode, List keysToSet) - { - List changedCurves = new List(); - foreach (KeyIdentifier keyToSet in keysToSet) - { - AnimationCurve animationCurve = keyToSet.curve; - Keyframe key = keyToSet.keyframe; - AnimationUtility.SetKeyBroken(ref key, false); - AnimationUtility.SetKeyRightTangentMode(ref key, mode); - AnimationUtility.SetKeyLeftTangentMode(ref key, mode); - - // Smooth Tangents based on neighboring nodes - // Note: not needed since the UpdateTangentsFromModeSurrounding call below will handle it - //if (mode == TangentMode.ClampedAuto) animationCurve.SmoothTangents(keyToSet.key, 0.0F); - // Smooth tangents based on existing tangents - if (mode == TangentMode.Free) - { - float slope = CurveUtility.CalculateSmoothTangent(key); - key.inTangent = slope; - key.outTangent = slope; - } - animationCurve.MoveKey(keyToSet.key, key); - AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyToSet.key); - - ChangedCurve changedCurve = new ChangedCurve(animationCurve, keyToSet.curveId, keyToSet.binding); - if (!changedCurves.Contains(changedCurve)) - changedCurves.Add(changedCurve); - } - - updater.UpdateCurves(changedCurves, "Set Tangents"); - } - - public void Flatten(List keysToSet) - { - List changedCurves = new List(); - foreach (KeyIdentifier keyToSet in keysToSet) - { - AnimationCurve animationCurve = keyToSet.curve; - Keyframe key = keyToSet.keyframe; - key.inTangent = 0; - key.outTangent = 0; - animationCurve.MoveKey(keyToSet.key, key); - AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyToSet.key); - - ChangedCurve changedCurve = new ChangedCurve(animationCurve, keyToSet.curveId, keyToSet.binding); - if (!changedCurves.Contains(changedCurve)) - changedCurves.Add(changedCurve); - } - - updater.UpdateCurves(changedCurves, "Set Tangents"); - } - - public void SetBroken(object _keysToSet) - { - List changedCurves = new List(); - List keysToSet = (List)_keysToSet; - foreach (KeyIdentifier keyToSet in keysToSet) - { - AnimationCurve animationCurve = keyToSet.curve; - Keyframe key = keyToSet.keyframe; - AnimationUtility.SetKeyBroken(ref key, true); - if (AnimationUtility.GetKeyRightTangentMode(key) == TangentMode.ClampedAuto || AnimationUtility.GetKeyRightTangentMode(key) == TangentMode.Auto) - AnimationUtility.SetKeyRightTangentMode(ref key, TangentMode.Free); - if (AnimationUtility.GetKeyLeftTangentMode(key) == TangentMode.ClampedAuto || AnimationUtility.GetKeyLeftTangentMode(key) == TangentMode.Auto) - AnimationUtility.SetKeyLeftTangentMode(ref key, TangentMode.Free); - - animationCurve.MoveKey(keyToSet.key, key); - AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyToSet.key); - - ChangedCurve changedCurve = new ChangedCurve(animationCurve, keyToSet.curveId, keyToSet.binding); - if (!changedCurves.Contains(changedCurve)) - changedCurves.Add(changedCurve); - } - - updater.UpdateCurves(changedCurves, "Set Tangents"); - } - - public void SetLeftEditable(object keysToSet) { SetTangent(0, TangentMode.Free, (List)keysToSet); } - public void SetLeftLinear(object keysToSet) { SetTangent(0, TangentMode.Linear, (List)keysToSet); } - public void SetLeftConstant(object keysToSet) { SetTangent(0, TangentMode.Constant, (List)keysToSet); } - public void SetRightEditable(object keysToSet) { SetTangent(1, TangentMode.Free, (List)keysToSet); } - public void SetRightLinear(object keysToSet) { SetTangent(1, TangentMode.Linear, (List)keysToSet); } - public void SetRightConstant(object keysToSet) { SetTangent(1, TangentMode.Constant, (List)keysToSet); } - public void SetBothEditable(object keysToSet) { SetTangent(2, TangentMode.Free, (List)keysToSet); } - public void SetBothLinear(object keysToSet) { SetTangent(2, TangentMode.Linear, (List)keysToSet); } - public void SetBothConstant(object keysToSet) { SetTangent(2, TangentMode.Constant, (List)keysToSet); } - public void SetTangent(int leftRight, TangentMode mode, List keysToSet) - { - List changedCurves = new List(); - - foreach (KeyIdentifier keyToSet in keysToSet) - { - AnimationCurve animationCurve = keyToSet.curve; - Keyframe key = keyToSet.keyframe; - AnimationUtility.SetKeyBroken(ref key, true); - if (leftRight == 2) - { - AnimationUtility.SetKeyLeftTangentMode(ref key, mode); - AnimationUtility.SetKeyRightTangentMode(ref key, mode); - } - else - { - if (leftRight == 0) - { - AnimationUtility.SetKeyLeftTangentMode(ref key, mode); - - // Make sure other tangent is handled correctly - if (AnimationUtility.GetKeyRightTangentMode(key) == TangentMode.ClampedAuto || AnimationUtility.GetKeyRightTangentMode(key) == TangentMode.Auto) - AnimationUtility.SetKeyRightTangentMode(ref key, TangentMode.Free); - } - else //if (leftRight == 1) - { - AnimationUtility.SetKeyRightTangentMode(ref key, mode); - - // Make sure other tangent is handled correctly - if (AnimationUtility.GetKeyLeftTangentMode(key) == TangentMode.ClampedAuto || AnimationUtility.GetKeyLeftTangentMode(key) == TangentMode.Auto) - AnimationUtility.SetKeyLeftTangentMode(ref key, TangentMode.Free); - } - } - - if (mode == TangentMode.Constant && (leftRight == 0 || leftRight == 2)) - key.inTangent = Mathf.Infinity; - if (mode == TangentMode.Constant && (leftRight == 1 || leftRight == 2)) - key.outTangent = Mathf.Infinity; - - animationCurve.MoveKey(keyToSet.key, key); - AnimationUtility.UpdateTangentsFromModeSurrounding(animationCurve, keyToSet.key); - // Debug.Log ("Before " + DebKey (key) + " after: " + DebKey (animationCurve[keyToSet.key])); - - ChangedCurve changedCurve = new ChangedCurve(animationCurve, keyToSet.curveId, keyToSet.binding); - if (!changedCurves.Contains(changedCurve)) - changedCurves.Add(changedCurve); - } - - updater.UpdateCurves(changedCurves, "Set Tangents"); - } - - /* - string DebKey (Keyframe key) { - return System.String.Format ("time:{0} value:{1} inTangent:{2} outTangent{3}", key.time, key.value, key.inTangent, key.outTangent); - } - */ - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/BoolCurveRenderer.cs b/Editor/Mono/Animation/AnimationWindow/CurveRenderer/BoolCurveRenderer.cs deleted file mode 100644 index a3d514be15..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/BoolCurveRenderer.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class BoolCurveRenderer : NormalCurveRenderer - { - public BoolCurveRenderer(AnimationCurve curve) - : base(curve) - { - } - - public override float ClampedValue(float value) - { - return value != 0.0f ? 1.0f : 0.0f; - } - - public override float EvaluateCurveSlow(float time) - { - return ClampedValue(GetCurve().Evaluate(time)); - } - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/CurveRenderer.cs b/Editor/Mono/Animation/AnimationWindow/CurveRenderer/CurveRenderer.cs deleted file mode 100644 index 1873db588b..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/CurveRenderer.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal interface CurveRenderer - { - void DrawCurve(float minTime, float maxTime, Color color, Matrix4x4 transform, Color wrapColor); - AnimationCurve GetCurve(); - float RangeStart(); - float RangeEnd(); - void SetWrap(WrapMode wrap); - void SetWrap(WrapMode preWrap, WrapMode postWrap); - void SetCustomRange(float start, float end); - float EvaluateCurveSlow(float time); - float EvaluateCurveDeltaSlow(float time); - Bounds GetBounds(); - Bounds GetBounds(float minTime, float maxTime); - float ClampedValue(float value); - void FlushCache(); - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/EulerCurveCombinedRenderer.cs b/Editor/Mono/Animation/AnimationWindow/CurveRenderer/EulerCurveCombinedRenderer.cs deleted file mode 100644 index 0166849557..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/EulerCurveCombinedRenderer.cs +++ /dev/null @@ -1,308 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class EulerCurveCombinedRenderer - { - const int kSegmentResolution = 40; - const float epsilon = 0.001f; - - private AnimationCurve quaternionX; - private AnimationCurve quaternionY; - private AnimationCurve quaternionZ; - private AnimationCurve quaternionW; - private AnimationCurve eulerX; - private AnimationCurve eulerY; - private AnimationCurve eulerZ; - - private SortedDictionary points; - - private float cachedEvaluationTime = Mathf.Infinity; - private Vector3 cachedEvaluationValue; - - private float cachedRangeStart = Mathf.Infinity; - private float cachedRangeEnd = Mathf.NegativeInfinity; - - private Vector3 refEuler; - - private float m_CustomRangeStart = 0; - private float m_CustomRangeEnd = 0; - private float rangeStart { get { return (m_CustomRangeStart == 0 && m_CustomRangeEnd == 0 && eulerX.length > 0 ? eulerX.keys[0].time : m_CustomRangeStart); } } - private float rangeEnd { get { return (m_CustomRangeStart == 0 && m_CustomRangeEnd == 0 && eulerX.length > 0 ? eulerX.keys[eulerX.length - 1].time : m_CustomRangeEnd); } } - private WrapMode preWrapMode = WrapMode.Once; - private WrapMode postWrapMode = WrapMode.Once; - - public EulerCurveCombinedRenderer( - AnimationCurve quaternionX, - AnimationCurve quaternionY, - AnimationCurve quaternionZ, - AnimationCurve quaternionW, - AnimationCurve eulerX, - AnimationCurve eulerY, - AnimationCurve eulerZ - ) - { - this.quaternionX = (quaternionX == null ? new AnimationCurve() : quaternionX); - this.quaternionY = (quaternionY == null ? new AnimationCurve() : quaternionY); - this.quaternionZ = (quaternionZ == null ? new AnimationCurve() : quaternionZ); - this.quaternionW = (quaternionW == null ? new AnimationCurve() : quaternionW); - this.eulerX = (eulerX == null ? new AnimationCurve() : eulerX); - this.eulerY = (eulerY == null ? new AnimationCurve() : eulerY); - this.eulerZ = (eulerZ == null ? new AnimationCurve() : eulerZ); - } - - public AnimationCurve GetCurveOfComponent(int component) - { - switch (component) - { - case 0: return eulerX; - case 1: return eulerY; - case 2: return eulerZ; - default: return null; - } - } - - public float RangeStart() { return rangeStart; } - public float RangeEnd() { return rangeEnd; } - public WrapMode PreWrapMode() { return preWrapMode; } - public WrapMode PostWrapMode() { return postWrapMode; } - public void SetWrap(WrapMode wrap) - { - preWrapMode = wrap; - postWrapMode = wrap; - } - - public void SetWrap(WrapMode preWrap, WrapMode postWrap) - { - preWrapMode = preWrap; - postWrapMode = postWrap; - } - - public void SetCustomRange(float start, float end) - { - m_CustomRangeStart = start; - m_CustomRangeEnd = end; - } - - private Vector3 GetValues(float time, bool keyReference) - { - if (quaternionX == null) Debug.LogError("X curve is null!"); - if (quaternionY == null) Debug.LogError("Y curve is null!"); - if (quaternionZ == null) Debug.LogError("Z curve is null!"); - if (quaternionW == null) Debug.LogError("W curve is null!"); - - Quaternion q; - - if (quaternionX.length != 0 && - quaternionY.length != 0 && - quaternionZ.length != 0 && - quaternionW.length != 0) - { - q = EvaluateQuaternionCurvesDirectly(time); - if (keyReference) - refEuler = EvaluateEulerCurvesDirectly(time); - refEuler = QuaternionCurveTangentCalculation.GetEulerFromQuaternion(q, refEuler); - } - else //euler curves only - { - refEuler = EvaluateEulerCurvesDirectly(time); - } - - return refEuler; - } - - private Quaternion EvaluateQuaternionCurvesDirectly(float time) - { - return new Quaternion( - quaternionX.Evaluate(time), - quaternionY.Evaluate(time), - quaternionZ.Evaluate(time), - quaternionW.Evaluate(time)); - } - - private Vector3 EvaluateEulerCurvesDirectly(float time) - { - return new Vector3( - eulerX.Evaluate(time), - eulerY.Evaluate(time), - eulerZ.Evaluate(time)); - } - - private void CalculateCurves(float minTime, float maxTime) - { - points = new SortedDictionary(); - - float[,] ranges = NormalCurveRenderer.CalculateRanges(minTime, maxTime, rangeStart, rangeEnd, preWrapMode, postWrapMode); - for (int i = 0; i < ranges.GetLength(0); i++) - AddPoints(ranges[i, 0], ranges[i, 1]); - } - - private void AddPoints(float minTime, float maxTime) - { - AnimationCurve refCurve = quaternionX; - if (refCurve.length == 0) - { - refCurve = eulerX; - } - - if (refCurve.length == 0) - return; - - if (refCurve[0].time >= minTime) - { - Vector3 val = GetValues(refCurve[0].time, true); - points[rangeStart] = val; - points[refCurve[0].time] = val; - } - if (refCurve[refCurve.length - 1].time <= maxTime) - { - Vector3 val = GetValues(refCurve[refCurve.length - 1].time, true); - points[refCurve[refCurve.length - 1].time] = val; - points[rangeEnd] = val; - } - - for (int i = 0; i < refCurve.length - 1; i++) - { - // Ignore segments that are outside of the range from minTime to maxTime - if (refCurve[i + 1].time maxTime) - continue; - - // Get first value from euler curve and move forwards - float newTime = refCurve[i].time; - points[newTime] = GetValues(newTime, true); - - // Iterate forwards through curve segments - for (float j = 1; j <= kSegmentResolution / 2; j++) - { - newTime = Mathf.Lerp(refCurve[i].time, refCurve[i + 1].time, (j - 0.001f) / kSegmentResolution); - points[newTime] = GetValues(newTime, false); - } - - // Get last value from euler curve and move backwards - newTime = refCurve[i + 1].time; - points[newTime] = GetValues(newTime, true); - - // Iterate backwards through curve segment - for (float j = 1; j <= kSegmentResolution / 2; j++) - { - newTime = Mathf.Lerp(refCurve[i].time, refCurve[i + 1].time, 1 - (j - 0.001f) / kSegmentResolution); - points[newTime] = GetValues(newTime, false); - } - } - } - - public float EvaluateCurveDeltaSlow(float time, int component) - { - if (quaternionX == null) - return 0; - return (EvaluateCurveSlow(time + epsilon, component) - EvaluateCurveSlow(time - epsilon, component)) / (epsilon * 2); - } - - public float EvaluateCurveSlow(float time, int component) - { - if (GetCurveOfComponent(component).length == 1) - { - return GetCurveOfComponent(component)[0].value; - } - - if (time == cachedEvaluationTime) - return cachedEvaluationValue[component]; - - if (time < cachedRangeStart || time > cachedRangeEnd) - { - // if an evaluate call is outside of cached range we might as well calculate whole range - CalculateCurves(rangeStart, rangeEnd); - cachedRangeStart = Mathf.NegativeInfinity; - cachedRangeEnd = Mathf.Infinity; - } - - float[] times = new float[points.Count]; - Vector3[] values = new Vector3[points.Count]; - int c = 0; - foreach (KeyValuePair kvp in points) - { - times[c] = kvp.Key; - values[c] = kvp.Value; - c++; - } - - for (int i = 0; i < times.Length - 1; i++) - { - if (time < times[i + 1]) - { - float lerp = Mathf.InverseLerp(times[i], times[i + 1], time); - cachedEvaluationValue = Vector3.Lerp(values[i], values[i + 1], lerp); - cachedEvaluationTime = time; - return cachedEvaluationValue[component]; - } - } - - if (values.Length > 0) - return values[values.Length - 1][component]; - - Debug.LogError("List of euler curve points is empty, probably caused by lack of euler curve key synching"); - return 0; - } - - public void DrawCurve(float minTime, float maxTime, Color color, Matrix4x4 transform, int component, Color wrapColor) - { - if (minTime < cachedRangeStart || maxTime > cachedRangeEnd) - { - CalculateCurves(minTime, maxTime); - if (minTime <= rangeStart && maxTime >= rangeEnd) - { - // if we are covering whole range - cachedRangeStart = Mathf.NegativeInfinity; - cachedRangeEnd = Mathf.Infinity; - } - else - { - cachedRangeStart = minTime; - cachedRangeEnd = maxTime; - } - } - - List polyLine = new List(); - - foreach (KeyValuePair kvp in points) - { - polyLine.Add(new Vector3(kvp.Key, kvp.Value[component])); - } - - NormalCurveRenderer.DrawCurveWrapped(minTime, maxTime, rangeStart, rangeEnd, preWrapMode, postWrapMode, color, transform, polyLine.ToArray(), wrapColor); - } - - public Bounds GetBounds(float minTime, float maxTime, int component) - { - //if (alreadyDrawn[component]) - //{ - CalculateCurves(minTime, maxTime); - // for (int i=0; i kvp in points) - { - if (kvp.Value[component] > max) - max = kvp.Value[component]; - if (kvp.Value[component] < min) - min = kvp.Value[component]; - } - if (min == Mathf.Infinity) - { - min = 0; - max = 0; - } - return new Bounds(new Vector3((maxTime + minTime) * 0.5f, (max + min) * 0.5f, 0), new Vector3(maxTime - minTime, max - min, 0)); - } - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/EulerCurveRenderer.cs b/Editor/Mono/Animation/AnimationWindow/CurveRenderer/EulerCurveRenderer.cs deleted file mode 100644 index b1eda17f54..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/EulerCurveRenderer.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class EulerCurveRenderer : CurveRenderer - { - private int component; - private EulerCurveCombinedRenderer renderer; - - public EulerCurveRenderer(int component, EulerCurveCombinedRenderer renderer) - { - this.component = component; - this.renderer = renderer; - } - - public AnimationCurve GetCurve() - { - return renderer.GetCurveOfComponent(component); - } - - public float ClampedValue(float value) - { - return value; - } - - public float RangeStart() { return renderer.RangeStart(); } - public float RangeEnd() { return renderer.RangeEnd(); } - public void SetWrap(WrapMode wrap) - { - renderer.SetWrap(wrap); - } - - public void SetWrap(WrapMode preWrapMode, WrapMode postWrapMode) - { - renderer.SetWrap(preWrapMode, postWrapMode); - } - - public void SetCustomRange(float start, float end) - { - renderer.SetCustomRange(start, end); - } - - public float EvaluateCurveSlow(float time) - { - return renderer.EvaluateCurveSlow(time, component); - } - - public float EvaluateCurveDeltaSlow(float time) - { - return renderer.EvaluateCurveDeltaSlow(time, component); - } - - public void DrawCurve(float minTime, float maxTime, Color color, Matrix4x4 transform, Color wrapColor) - { - renderer.DrawCurve(minTime, maxTime, color, transform, component, wrapColor); - } - - public Bounds GetBounds() - { - return GetBounds(renderer.RangeStart(), renderer.RangeEnd()); - } - - public Bounds GetBounds(float minTime, float maxTime) - { - return renderer.GetBounds(minTime, maxTime, component); - } - - public void FlushCache() - { - } - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/IntCurveRenderer.cs b/Editor/Mono/Animation/AnimationWindow/CurveRenderer/IntCurveRenderer.cs deleted file mode 100644 index 68145127af..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/IntCurveRenderer.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class IntCurveRenderer : NormalCurveRenderer - { - const float kSegmentWindowResolution = 1000; - const int kMaximumSampleCount = 1000; - const float kStepHelperOffset = 0.000001f; - - - public IntCurveRenderer(AnimationCurve curve) - : base(curve) - { - } - - public override float ClampedValue(float value) - { - return Mathf.Floor(value + 0.5f); - } - - public override float EvaluateCurveSlow(float time) - { - return ClampedValue(GetCurve().Evaluate(time)); - } - - protected override int GetSegmentResolution(float minTime, float maxTime, float keyTime, float nextKeyTime) - { - float fullTimeRange = maxTime - minTime; - float keyTimeRange = nextKeyTime - keyTime; - int count = Mathf.RoundToInt(kSegmentWindowResolution * (keyTimeRange / fullTimeRange)); - return Mathf.Clamp(count, 1, kMaximumSampleCount); - } - - protected override void AddPoint(ref List points, ref float lastTime, float sampleTime, ref float lastValue, float sampleValue) - { - if (lastValue != sampleValue) - { - points.Add(new Vector3(lastTime + kStepHelperOffset, sampleValue)); - } - - points.Add(new Vector3(sampleTime, sampleValue)); - lastTime = sampleTime; - lastValue = sampleValue; - } - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/NormalCurveRenderer.cs b/Editor/Mono/Animation/AnimationWindow/CurveRenderer/NormalCurveRenderer.cs deleted file mode 100644 index ff5151cb57..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/CurveRenderer/NormalCurveRenderer.cs +++ /dev/null @@ -1,651 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class NormalCurveRenderer : CurveRenderer - { - const float kSegmentWindowResolution = 1000; - const int kMaximumSampleCount = 50; - const int kMaximumLoops = 100; - const string kCurveRendererMeshName = "NormalCurveRendererMesh"; - - private AnimationCurve m_Curve; - private float m_CustomRangeStart = 0; - private float m_CustomRangeEnd = 0; - private float rangeStart { get { return (m_CustomRangeStart == 0 && m_CustomRangeEnd == 0 && m_Curve.length > 0 ? m_Curve.keys[0].time : m_CustomRangeStart); } } - private float rangeEnd { get { return (m_CustomRangeStart == 0 && m_CustomRangeEnd == 0 && m_Curve.length > 0 ? m_Curve.keys[m_Curve.length - 1].time : m_CustomRangeEnd); } } - private WrapMode preWrapMode = WrapMode.Once; - private WrapMode postWrapMode = WrapMode.Once; - - private Bounds? m_Bounds; - private Mesh m_CurveMesh; - - private static Material s_CurveMaterial; - public static Material curveMaterial - { - get - { - if (!s_CurveMaterial) - { - Shader shader = (Shader)EditorGUIUtility.LoadRequired("Editors/AnimationWindow/Curve.shader"); - s_CurveMaterial = new Material(shader); - } - - return s_CurveMaterial; - } - } - - public NormalCurveRenderer(AnimationCurve curve) - { - m_Curve = curve; - if (m_Curve == null) - m_Curve = new AnimationCurve(); - } - - public AnimationCurve GetCurve() - { - return m_Curve; - } - - public float RangeStart() { return rangeStart; } - public float RangeEnd() { return rangeEnd; } - public void SetWrap(WrapMode wrap) - { - this.preWrapMode = wrap; - this.postWrapMode = wrap; - } - - public void SetWrap(WrapMode preWrap, WrapMode postWrap) - { - this.preWrapMode = preWrap; - this.postWrapMode = postWrap; - } - - public void SetCustomRange(float start, float end) - { - m_CustomRangeStart = start; - m_CustomRangeEnd = end; - } - - public virtual float ClampedValue(float value) - { - return value; - } - - public virtual float EvaluateCurveSlow(float time) - { - return m_Curve.Evaluate(time); - } - - // TODO: Implement proper analytic evaluation of curve delta instead of this numeric hack - public float EvaluateCurveDeltaSlow(float time) - { - float epsilon = 0.0001f; - return (EvaluateCurveSlow(time + epsilon) - EvaluateCurveSlow(time - epsilon)) / (epsilon * 2); - } - - private Vector3[] GetPoints() - { - return GetPoints(rangeStart, rangeEnd); - } - - private Vector3[] GetPoints(float minTime, float maxTime) - { - List points = new List(); - - if (m_Curve.length == 0) - return points.ToArray(); - points.Capacity = 1000 + m_Curve.length; - - float[,] ranges = CalculateRanges(minTime, maxTime, rangeStart, rangeEnd, preWrapMode, postWrapMode); - for (int i = 0; i < ranges.GetLength(0); i++) - AddPoints(ref points, ranges[i, 0], ranges[i, 1], minTime, maxTime); - - // Remove points that don't go in ascending time order - if (points.Count > 0) - { - for (int i = 1; i < points.Count; i++) - { - if (points[i].x < points[i - 1].x) - { - points.RemoveAt(i); - i--; - } - } - } - - return points.ToArray(); - } - - public static float[,] CalculateRanges(float minTime, float maxTime, float rangeStart, float rangeEnd, WrapMode preWrapMode, WrapMode postWrapMode) - { - // Don't want to deal with optimizing for different pre and post wrap mode for now - WrapMode wrap = preWrapMode; - if (postWrapMode != wrap) - return new float[1, 2] {{rangeStart, rangeEnd}}; - - if (wrap == WrapMode.Loop) - { - // If we are covering a range longer than a full loop, just add all points: - if (maxTime - minTime > rangeEnd - rangeStart) - { - return new float[1, 2] {{rangeStart, rangeEnd}}; - } - // Else, only add the needed range(s) - else - { - // Find the start and end of needed shown range repeated into the range of the curve - minTime = Mathf.Repeat(minTime - rangeStart, rangeEnd - rangeStart) + rangeStart; - maxTime = Mathf.Repeat(maxTime - rangeStart, rangeEnd - rangeStart) + rangeStart; - if (minTime < maxTime) - return new float[1, 2] {{minTime, maxTime}}; - else - return new float[2, 2] {{rangeStart, maxTime}, {minTime, rangeEnd}}; - } - } - else if (wrap == WrapMode.PingPong) - { - // TODO: Maybe optimize so not whole range is calculated if not needed - return new float[1, 2] {{rangeStart, rangeEnd}}; - } - else - return new float[1, 2] {{minTime, maxTime}}; - } - - protected virtual int GetSegmentResolution(float minTime, float maxTime, float keyTime, float nextKeyTime) - { - float fullTimeRange = maxTime - minTime; - float keyTimeRange = nextKeyTime - keyTime; - int count = Mathf.RoundToInt(kSegmentWindowResolution * (keyTimeRange / fullTimeRange)); - return Mathf.Clamp(count, 1, kMaximumSampleCount); - } - - protected virtual void AddPoint(ref List points, ref float lastTime, float sampleTime, ref float lastValue, float sampleValue) - { - points.Add(new Vector3(sampleTime, sampleValue)); - lastTime = sampleTime; - lastValue = sampleValue; - } - - private void AddPoints(ref List points, float minTime, float maxTime, float visibleMinTime, float visibleMaxTime) - { - if (m_Curve[0].time >= minTime) - { - points.Add(new Vector3(rangeStart, ClampedValue(m_Curve[0].value))); - points.Add(new Vector3(m_Curve[0].time, ClampedValue(m_Curve[0].value))); - } - - for (int i = 0; i < m_Curve.length - 1; i++) - { - Keyframe key = m_Curve[i]; - Keyframe nextKey = m_Curve[i + 1]; - - // Ignore segments that are outside of the range from minTime to maxTime - if (nextKey.time < minTime || key.time > maxTime) - continue; - - // Get first value from actual key rather than evaluating curve (to correctly handle stepped interpolation) - points.Add(new Vector3(key.time, key.value)); - - // Place second sample very close to first one (to correctly handle stepped interpolation) - int segmentResolution = GetSegmentResolution(visibleMinTime, visibleMaxTime, key.time, nextKey.time); - float newTime = Mathf.Lerp(key.time, nextKey.time, 0.001f / segmentResolution); - float lastTime = key.time; - float lastValue = ClampedValue(key.value); - float value = EvaluateCurveSlow(newTime); - AddPoint(ref points, ref lastTime, newTime, ref lastValue, value); - - // Iterate through curve segment - for (float j = 1; j < segmentResolution; j++) - { - newTime = Mathf.Lerp(key.time, nextKey.time, j / segmentResolution); - value = EvaluateCurveSlow(newTime); - AddPoint(ref points, ref lastTime, newTime, ref lastValue, value); - } - - // Place second last sample very close to last one (to correctly handle stepped interpolation) - newTime = Mathf.Lerp(key.time, nextKey.time, 1 - 0.001f / segmentResolution); - value = EvaluateCurveSlow(newTime); - AddPoint(ref points, ref lastTime, newTime, ref lastValue, value); - - // Get last value from actual key rather than evaluating curve (to correctly handle stepped interpolation) - newTime = nextKey.time; - AddPoint(ref points, ref lastTime, newTime, ref lastValue, value); - } - - if (m_Curve[m_Curve.length - 1].time <= maxTime) - { - float clampedValue = ClampedValue(m_Curve[m_Curve.length - 1].value); - points.Add(new Vector3(m_Curve[m_Curve.length - 1].time, clampedValue)); - points.Add(new Vector3(rangeEnd, clampedValue)); - } - } - - private void BuildCurveMesh() - { - if (m_CurveMesh != null) - return; - - Vector3[] vertices = GetPoints(); - - m_CurveMesh = new Mesh(); - m_CurveMesh.name = kCurveRendererMeshName; - m_CurveMesh.hideFlags |= HideFlags.DontSave; - m_CurveMesh.vertices = vertices; - - if (vertices.Length > 0) - { - int nIndices = vertices.Length - 1; - int index = 0; - - List indices = new List(nIndices * 2); - while (index < nIndices) - { - indices.Add(index); - indices.Add(++index); - } - - m_CurveMesh.SetIndices(indices.ToArray(), MeshTopology.Lines, 0); - } - } - - public void DrawCurve(float minTime, float maxTime, Color color, Matrix4x4 transform, Color wrapColor) - { - BuildCurveMesh(); - - Keyframe[] keys = m_Curve.keys; - if (keys.Length > 0) - { - Vector3 firstPoint = new Vector3(rangeStart, keys.First().value); - Vector3 lastPoint = new Vector3(rangeEnd, keys.Last().value); - DrawCurveWrapped(minTime, maxTime, rangeStart, rangeEnd, preWrapMode, postWrapMode, m_CurveMesh, firstPoint, lastPoint, transform, color, wrapColor); - } - } - - public static void DrawPolyLine(Matrix4x4 transform, float minDistance, params Vector3[] points) - { - if (Event.current.type != EventType.Repaint) - return; - - Color col = Handles.color * new Color(1, 1, 1, 0.75f); - - HandleUtility.ApplyWireMaterial(); - GL.PushMatrix(); - GL.MultMatrix(Handles.matrix); - GL.Begin(GL.LINES); - GL.Color(col); - - Vector3 previous = transform.MultiplyPoint(points[0]); - for (int i = 1; i < points.Length; i++) - { - Vector3 current = transform.MultiplyPoint(points[i]); - - if ((previous - current).magnitude > minDistance) - { - GL.Vertex(previous); - GL.Vertex(current); - - previous = current; - } - } - GL.End(); - GL.PopMatrix(); - } - - public static void DrawCurveWrapped(float minTime, float maxTime, float rangeStart, float rangeEnd, - WrapMode preWrap, WrapMode postWrap, Mesh mesh, Vector3 firstPoint, Vector3 lastPoint, - Matrix4x4 transform, Color color, Color wrapColor) - { - if (mesh.vertexCount == 0) - return; - - if (Event.current.type != EventType.Repaint) - return; - - int minRep; - int maxRep; - if (rangeEnd - rangeStart != 0) - { - minRep = Mathf.FloorToInt((minTime - rangeStart) / (rangeEnd - rangeStart)); - maxRep = Mathf.CeilToInt((maxTime - rangeEnd) / (rangeEnd - rangeStart)); - - // Prevent too many loops from being rendered at one time. - if (minRep < -kMaximumLoops) - preWrap = WrapMode.Clamp; - if (maxRep > kMaximumLoops) - postWrap = WrapMode.Clamp; - } - else - { - preWrap = WrapMode.Clamp; - postWrap = WrapMode.Clamp; - minRep = (minTime < rangeStart ? -1 : 0); - maxRep = (maxTime > rangeEnd ? 1 : 0); - } - - // Draw curve itself - Material mat = curveMaterial; - mat.SetColor("_Color", color); - Handles.color = color; - - mat.SetPass(0); - Graphics.DrawMeshNow(mesh, Handles.matrix * transform); - - // Draw wrapping - mat.SetColor("_Color", new Color(wrapColor.r, wrapColor.g, wrapColor.b, wrapColor.a * color.a)); - Handles.color = new Color(wrapColor.r, wrapColor.g, wrapColor.b, wrapColor.a * color.a); - - // Draw pre wrapping - if (preWrap == WrapMode.Loop) - { - Matrix4x4 firstTransform = Handles.matrix * transform * Matrix4x4.TRS(new Vector3(minRep * (rangeEnd - rangeStart), 0.0f, 0.0f), Quaternion.identity, Vector3.one); - Matrix4x4 iterTransform = Matrix4x4.TRS(new Vector3(rangeEnd - rangeStart, 0.0f, 0.0f), Quaternion.identity, Vector3.one); - - // Render loop curve itself. - mat.SetPass(0); - Matrix4x4 curTransform = firstTransform; - for (int r = minRep; r < 0; ++r) - { - Graphics.DrawMeshNow(mesh, curTransform); - curTransform = curTransform * iterTransform; - } - - // Render straight lines connecting one loop to another. - curTransform = firstTransform; - for (int r = minRep; r < 0; ++r) - { - Matrix4x4 nextTransform = curTransform * iterTransform; - - Handles.DrawLine( - curTransform.MultiplyPoint(lastPoint), - nextTransform.MultiplyPoint(firstPoint) - ); - - curTransform = nextTransform; - } - } - else if (preWrap == WrapMode.PingPong) - { - mat.SetPass(0); - for (int r = minRep; r < 0; ++r) - { - // Even loop - if (r % 2 == 0) - { - Matrix4x4 shiftTransform = Matrix4x4.TRS(new Vector3(r * (rangeEnd - rangeStart), 0.0f, 0.0f), Quaternion.identity, Vector3.one); - Graphics.DrawMeshNow(mesh, Handles.matrix * transform * shiftTransform); - } - // Odd loop - else - { - 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)); - Graphics.DrawMeshNow(mesh, Handles.matrix * transform * shiftTransform); - } - } - } - else - { - if (minRep < 0) - { - Handles.DrawLine( - transform.MultiplyPoint(new Vector3(minTime, firstPoint.y, 0)), - transform.MultiplyPoint(new Vector3(Mathf.Min(maxTime, firstPoint.x), firstPoint.y, 0)) - ); - } - } - - // Draw post wrapping - if (postWrap == WrapMode.Loop) - { - Matrix4x4 firstTransform = Handles.matrix * transform; - Matrix4x4 iterTransform = Matrix4x4.TRS(new Vector3(rangeEnd - rangeStart, 0.0f, 0.0f), Quaternion.identity, Vector3.one); - - // Render straight lines connecting one loop to another. - Matrix4x4 prevTransform = firstTransform; - for (int r = 1; r <= maxRep; ++r) - { - Matrix4x4 curTransform = prevTransform * iterTransform; - - Handles.DrawLine( - prevTransform.MultiplyPoint(lastPoint), - curTransform.MultiplyPoint(firstPoint) - ); - - prevTransform = curTransform; - } - - // Render loop curve itself. - mat.SetPass(0); - prevTransform = firstTransform; - for (int r = 1; r <= maxRep; ++r) - { - Matrix4x4 curTransform = prevTransform * iterTransform; - Graphics.DrawMeshNow(mesh, curTransform); - prevTransform = curTransform; - } - } - else if (postWrap == WrapMode.PingPong) - { - mat.SetPass(0); - for (int r = 1; r <= maxRep; ++r) - { - // Even loop - if (r % 2 == 0) - { - Matrix4x4 shiftTransform = Matrix4x4.TRS(new Vector3(r * (rangeEnd - rangeStart), 0.0f, 0.0f), Quaternion.identity, Vector3.one); - Graphics.DrawMeshNow(mesh, Handles.matrix * transform * shiftTransform); - } - // Odd loop - else - { - 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)); - Graphics.DrawMeshNow(mesh, Handles.matrix * transform * shiftTransform); - } - } - } - else - { - if (maxRep > 0) - { - Handles.DrawLine( - transform.MultiplyPoint(new Vector3(Mathf.Max(minTime, lastPoint.x), lastPoint.y, 0)), - transform.MultiplyPoint(new Vector3(maxTime, lastPoint.y, 0)) - ); - } - } - } - - public static void DrawCurveWrapped(float minTime, float maxTime, float rangeStart, float rangeEnd, - WrapMode preWrap, WrapMode postWrap, Color color, Matrix4x4 transform, Vector3[] points, Color wrapColor) - { - if (points.Length == 0) - return; - - int minRep; - int maxRep; - if (rangeEnd - rangeStart != 0) - { - minRep = Mathf.FloorToInt((minTime - rangeStart) / (rangeEnd - rangeStart)); - maxRep = Mathf.CeilToInt((maxTime - rangeEnd) / (rangeEnd - rangeStart)); - - // Prevent too many loops from being rendered at one time. - if (minRep < -kMaximumLoops) - preWrap = WrapMode.Clamp; - if (maxRep > kMaximumLoops) - postWrap = WrapMode.Clamp; - } - else - { - preWrap = WrapMode.Clamp; - postWrap = WrapMode.Clamp; - minRep = (minTime < rangeStart ? -1 : 0); - maxRep = (maxTime > rangeEnd ? 1 : 0); - } - int last = points.Length - 1; - - // Draw curve itself - Handles.color = color; - List line = new List(); - - if (minRep <= 0 && maxRep >= 0) - { - // Use line drawing with minimum segment length. Faster for large data sets - DrawPolyLine(transform, 2, points); - } - else - Handles.DrawPolyLine(points); - - // Draw wrapping - Handles.color = new Color(wrapColor.r, wrapColor.g, wrapColor.b, wrapColor.a * color.a); - - // Draw pre wrapping - if (preWrap == WrapMode.Loop) - { - line = new List(); - for (int r = minRep; r < 0; r++) - { - for (int i = 0; i < points.Length; i++) - { - Vector3 point = points[i]; - point.x += r * (rangeEnd - rangeStart); - point = transform.MultiplyPoint(point); - line.Add(point); - } - } - line.Add(transform.MultiplyPoint(points[0])); - Handles.DrawPolyLine(line.ToArray()); - } - else if (preWrap == WrapMode.PingPong) - { - line = new List(); - for (int r = minRep; r < 0; r++) - { - for (int i = 0; i < points.Length; i++) - { - if (r / 2 == r / 2f) - { - Vector3 point = points[i]; - point.x += r * (rangeEnd - rangeStart); - point = transform.MultiplyPoint(point); - line.Add(point); - } - else - { - Vector3 point = points[last - i]; - point.x = -point.x + (r + 1) * (rangeEnd - rangeStart) + rangeStart * 2; - point = transform.MultiplyPoint(point); - line.Add(point); - } - } - } - Handles.DrawPolyLine(line.ToArray()); - } - else - { - if (minRep < 0) - { - Handles.DrawPolyLine(new Vector3[] { - transform.MultiplyPoint(new Vector3(minTime, points[0].y, 0)), - transform.MultiplyPoint(new Vector3(Mathf.Min(maxTime, points[0].x), points[0].y, 0)) - }); - } - } - - // Draw post wrapping - if (postWrap == WrapMode.Loop) - { - line = new List(); - line.Add(transform.MultiplyPoint(points[last])); - for (int r = 1; r <= maxRep; r++) - { - for (int i = 0; i < points.Length; i++) - { - Vector3 point = points[i]; - point.x += r * (rangeEnd - rangeStart); - point = transform.MultiplyPoint(point); - line.Add(point); - } - } - Handles.DrawPolyLine(line.ToArray()); - } - else if (postWrap == WrapMode.PingPong) - { - line = new List(); - for (int r = 1; r <= maxRep; r++) - { - for (int i = 0; i < points.Length; i++) - { - if (r / 2 == r / 2f) - { - Vector3 point = points[i]; - point.x += r * (rangeEnd - rangeStart); - point = transform.MultiplyPoint(point); - line.Add(point); - } - else - { - Vector3 point = points[last - i]; - point.x = -point.x + (r + 1) * (rangeEnd - rangeStart) + rangeStart * 2; - point = transform.MultiplyPoint(point); - line.Add(point); - } - } - } - Handles.DrawPolyLine(line.ToArray()); - } - else - { - if (maxRep > 0) - { - Handles.DrawPolyLine(new Vector3[] { - transform.MultiplyPoint(new Vector3(Mathf.Max(minTime, points[last].x), points[last].y, 0)), - transform.MultiplyPoint(new Vector3(maxTime, points[last].y, 0)) - }); - } - } - } - - public Bounds GetBounds() - { - BuildCurveMesh(); - if (m_Bounds == null) - m_Bounds = m_CurveMesh.bounds; - - return m_Bounds.Value; - } - - public Bounds GetBounds(float minTime, float maxTime) - { - Vector3[] points = GetPoints(minTime, maxTime); - float min = Mathf.Infinity; - float max = Mathf.NegativeInfinity; - for (int i = 0; i < points.Length; ++i) - { - Vector3 point = points[i]; - if (point.y > max) - max = point.y; - if (point.y < min) - min = point.y; - } - if (min == Mathf.Infinity) - { - min = 0; - max = 0; - } - return new Bounds(new Vector3((maxTime + minTime) * 0.5f, (max + min) * 0.5f, 0), new Vector3(maxTime - minTime, max - min, 0)); - } - - public void FlushCache() - { - Object.DestroyImmediate(m_CurveMesh); - } - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/Deprecated/AnimationEventTimeline.cs b/Editor/Mono/Animation/AnimationWindow/Deprecated/AnimationEventTimeline.cs deleted file mode 100644 index 71412cdcf8..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/Deprecated/AnimationEventTimeline.cs +++ /dev/null @@ -1,452 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Reflection; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; -using System.Linq; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [System.Serializable] - internal class AnimationEventTimeLine - { - [System.NonSerialized] - private AnimationEvent[] m_EventsAtMouseDown; - [System.NonSerialized] - private float[] m_EventTimes; - - private bool m_DirtyTooltip = false; - private int m_HoverEvent = -1; - // Rects used for checking mouse-move state changes - private string m_InstantTooltipText = null; - private Vector2 m_InstantTooltipPoint = Vector2.zero; - - public AnimationEventTimeLine(EditorWindow owner) - { - } - - public class EventComparer : IComparer - { - int IComparer.Compare(System.Object objX, System.Object objY) - { - AnimationEvent x = (AnimationEvent)objX; - AnimationEvent y = (AnimationEvent)objY; - float timeX = x.time; - float timeY = y.time; - if (timeX != timeY) - return ((int)Mathf.Sign(timeX - timeY)); - - int valueX = x.GetHashCode(); - int valueY = y.GetHashCode(); - return valueX - valueY; - } - } - - private class EventLineContextMenuObject - { - public GameObject m_Animated; - public AnimationClip m_Clip; - public float m_Time; - public int m_Index; - public bool[] m_Selected; - - public EventLineContextMenuObject(GameObject animated, AnimationClip clip, float time, int index, bool[] selected) - { - m_Animated = animated; - m_Clip = clip; - m_Time = time; - m_Index = index; - m_Selected = selected; - } - } - - public void AddEvent(float time, GameObject gameObject, AnimationClip animationClip) - { - AnimationWindowEvent awEvent = AnimationWindowEvent.CreateAndEdit(gameObject, animationClip, time); - Selection.activeObject = awEvent; - } - - public void EditEvents(GameObject gameObject, AnimationClip clip, bool[] selectedIndices) - { - List awEvents = new List(); - - for (int index = 0; index < selectedIndices.Length; ++index) - { - if (selectedIndices[index]) - awEvents.Add(AnimationWindowEvent.Edit(gameObject, clip, index)); - } - - if (awEvents.Count > 0) - { - Selection.objects = awEvents.ToArray(); - } - else - { - ClearSelection(); - } - } - - public void EditEvent(GameObject gameObject, AnimationClip clip, int index) - { - AnimationWindowEvent awEvent = AnimationWindowEvent.Edit(gameObject, clip, index); - Selection.activeObject = awEvent; - } - - public void ClearSelection() - { - // Do not unecessarily clear selection. Only clear if selection already is animation window event. - if (Selection.activeObject is AnimationWindowEvent) - Selection.activeObject = null; - } - - public void DeleteEvents(AnimationClip clip, bool[] deleteIndices) - { - bool deletedAny = false; - - List eventList = new List(AnimationUtility.GetAnimationEvents(clip)); - for (int i = eventList.Count - 1; i >= 0; i--) - { - if (deleteIndices[i]) - { - eventList.RemoveAt(i); - deletedAny = true; - } - } - - if (deletedAny) - { - Undo.RegisterCompleteObjectUndo(clip, "Delete Event"); - - AnimationUtility.SetAnimationEvents(clip, eventList.ToArray()); - Selection.objects = new AnimationWindowEvent[] {}; - - m_DirtyTooltip = true; - } - } - - public void EventLineGUI(Rect rect, AnimationWindowState state) - { - // We only display and manipulate animation events from the main - // game object in selection. If we ever want to update to handle - // a multiple selection, a single timeline might not be sufficient... - AnimationClip clip = state.activeAnimationClip; - GameObject animated = state.activeRootGameObject; - - GUI.BeginGroup(rect); - Color backupCol = GUI.color; - - Rect eventLineRect = new Rect(0, 0, rect.width, rect.height); - - float mousePosTime = Mathf.Max(Mathf.RoundToInt(state.PixelToTime(Event.current.mousePosition.x, rect) * state.frameRate) / state.frameRate, 0.0f); - - // Draw events - if (clip != null) - { - AnimationEvent[] events = AnimationUtility.GetAnimationEvents(clip); - Texture eventMarker = EditorGUIUtility.IconContent("Animation.EventMarker").image; - - // Calculate rects - Rect[] hitRects = new Rect[events.Length]; - Rect[] drawRects = new Rect[events.Length]; - int shared = 1; - int sharedLeft = 0; - for (int i = 0; i < events.Length; i++) - { - AnimationEvent evt = events[i]; - - if (sharedLeft == 0) - { - shared = 1; - while (i + shared < events.Length && events[i + shared].time == evt.time) - shared++; - sharedLeft = shared; - } - sharedLeft--; - - // Important to take floor of positions of GUI stuff to get pixel correct alignment of - // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time. - float keypos = Mathf.Floor(state.FrameToPixel(evt.time * clip.frameRate, rect)); - int sharedOffset = 0; - if (shared > 1) - { - float spread = Mathf.Min((shared - 1) * (eventMarker.width - 1), (int)(state.FrameDeltaToPixel(rect) - eventMarker.width * 2)); - sharedOffset = Mathf.FloorToInt(Mathf.Max(0, spread - (eventMarker.width - 1) * (sharedLeft))); - } - - Rect r = new Rect( - keypos + sharedOffset - eventMarker.width / 2, - (rect.height - 10) * (float)(sharedLeft - shared + 1) / Mathf.Max(1, shared - 1), - eventMarker.width, - eventMarker.height); - - hitRects[i] = r; - drawRects[i] = r; - } - - // Store tooptip info - if (m_DirtyTooltip) - { - if (m_HoverEvent >= 0 && m_HoverEvent < hitRects.Length) - { - m_InstantTooltipText = AnimationWindowEventInspector.FormatEvent(animated, events[m_HoverEvent]); - m_InstantTooltipPoint = new Vector2(hitRects[m_HoverEvent].xMin + (int)(hitRects[m_HoverEvent].width / 2) + rect.x - 30, rect.yMax); - } - m_DirtyTooltip = false; - } - - bool[] selectedEvents = new bool[events.Length]; - - Object[] selectedObjects = Selection.objects; - foreach (Object selectedObject in selectedObjects) - { - AnimationWindowEvent awe = selectedObject as AnimationWindowEvent; - if (awe != null) - { - if (awe.eventIndex >= 0 && awe.eventIndex < selectedEvents.Length) - { - selectedEvents[awe.eventIndex] = true; - } - } - } - - Vector2 offset = Vector2.zero; - int clickedIndex; - float startSelection, endSelection; - - // TODO: GUIStyle.none has hopping margins that need to be fixed - HighLevelEvent hEvent = EditorGUIExt.MultiSelection( - rect, - drawRects, - new GUIContent(eventMarker), - hitRects, - ref selectedEvents, - null, - out clickedIndex, - out offset, - out startSelection, - out endSelection, - GUIStyle.none - ); - - if (hEvent != HighLevelEvent.None) - { - switch (hEvent) - { - case HighLevelEvent.BeginDrag: - m_EventsAtMouseDown = events; - m_EventTimes = new float[events.Length]; - for (int i = 0; i < events.Length; i++) - m_EventTimes[i] = events[i].time; - break; - case HighLevelEvent.SelectionChanged: - state.ClearKeySelections(); - EditEvents(animated, clip, selectedEvents); - break; - case HighLevelEvent.Delete: - DeleteEvents(clip, selectedEvents); - break; - - case HighLevelEvent.DoubleClick: - - if (clickedIndex != -1) - EditEvents(animated, clip, selectedEvents); - else - EventLineContextMenuAdd(new EventLineContextMenuObject(animated, clip, mousePosTime, -1, selectedEvents)); - break; - case HighLevelEvent.Drag: - for (int i = events.Length - 1; i >= 0; i--) - { - if (selectedEvents[i]) - { - AnimationEvent evt = m_EventsAtMouseDown[i]; - evt.time = m_EventTimes[i] + offset.x * state.PixelDeltaToTime(rect); - evt.time = Mathf.Max(0.0F, evt.time); - evt.time = Mathf.RoundToInt(evt.time * clip.frameRate) / clip.frameRate; - } - } - int[] order = new int[selectedEvents.Length]; - for (int i = 0; i < order.Length; i++) - { - order[i] = i; - } - System.Array.Sort(m_EventsAtMouseDown, order, new EventComparer()); - bool[] selectedOld = (bool[])selectedEvents.Clone(); - float[] timesOld = (float[])m_EventTimes.Clone(); - for (int i = 0; i < order.Length; i++) - { - selectedEvents[i] = selectedOld[order[i]]; - m_EventTimes[i] = timesOld[order[i]]; - } - - // Update selection to reflect new order. - EditEvents(animated, clip, selectedEvents); - - Undo.RegisterCompleteObjectUndo(clip, "Move Event"); - AnimationUtility.SetAnimationEvents(clip, m_EventsAtMouseDown); - m_DirtyTooltip = true; - break; - case HighLevelEvent.ContextClick: - GenericMenu menu = new GenericMenu(); - var contextData = new EventLineContextMenuObject(animated, clip, events[clickedIndex].time, clickedIndex, selectedEvents); - int selectedEventsCount = selectedEvents.Count(selected => selected); - - menu.AddItem( - EditorGUIUtility.TrTextContent("Add Animation Event"), - false, - EventLineContextMenuAdd, - contextData); - menu.AddItem( - new GUIContent(selectedEventsCount > 1 ? "Delete Animation Events" : "Delete Animation Event"), - false, - EventLineContextMenuDelete, - contextData); - menu.ShowAsContext(); - - // Mouse may move while context menu is open - make sure instant tooltip is handled - m_InstantTooltipText = null; - m_DirtyTooltip = true; - state.Repaint(); - break; - } - } - - CheckRectsOnMouseMove(rect, events, hitRects); - - // Create context menu on context click - if (Event.current.type == EventType.ContextClick && eventLineRect.Contains(Event.current.mousePosition)) - { - Event.current.Use(); - // Create menu - GenericMenu menu = new GenericMenu(); - var contextData = new EventLineContextMenuObject(animated, clip, mousePosTime, -1, selectedEvents); - int selectedEventsCount = selectedEvents.Count(selected => selected); - - menu.AddItem( - EditorGUIUtility.TrTextContent("Add Animation Event"), - false, - EventLineContextMenuAdd, - contextData); - - if (selectedEventsCount > 0) - { - menu.AddItem( - new GUIContent(selectedEventsCount > 1 ? "Delete Animation Events" : "Delete Animation Event"), - false, - EventLineContextMenuDelete, - contextData); - } - - menu.ShowAsContext(); - } - } - - GUI.color = backupCol; - GUI.EndGroup(); - } - - public void DrawInstantTooltip(Rect position) - { - if (m_InstantTooltipText != null && m_InstantTooltipText != "") - { - // Draw body of tooltip - GUIStyle style = (GUIStyle)"AnimationEventTooltip"; - - // TODO: Move to editor_resources - style.contentOffset = new Vector2(0f, 0f); - style.overflow = new RectOffset(10, 10, 0, 0); - - Vector2 size = style.CalcSize(new GUIContent(m_InstantTooltipText)); - Rect rect = new Rect(m_InstantTooltipPoint.x - size.x * .5f, m_InstantTooltipPoint.y + 24, size.x, size.y); - - // Right align tooltip rect if it would otherwise exceed the bounds of the window - if (rect.xMax > position.width) - rect.x = position.width - rect.width; - - GUI.Label(rect, m_InstantTooltipText, style); - - // Draw arrow of tooltip - rect = new Rect(m_InstantTooltipPoint.x - 33, m_InstantTooltipPoint.y, 7, 25); - GUI.Label(rect, "", "AnimationEventTooltipArrow"); - } - } - - public void EventLineContextMenuAdd(object obj) - { - EventLineContextMenuObject eventObj = (EventLineContextMenuObject)obj; - AddEvent(eventObj.m_Time, eventObj.m_Animated, eventObj.m_Clip); - } - - public void EventLineContextMenuEdit(object obj) - { - EventLineContextMenuObject eventObj = (EventLineContextMenuObject)obj; - - if (Array.Exists(eventObj.m_Selected, selected => selected)) - { - EditEvents(eventObj.m_Animated, eventObj.m_Clip, eventObj.m_Selected); - } - else if (eventObj.m_Index >= 0) - { - EditEvent(eventObj.m_Animated, eventObj.m_Clip, eventObj.m_Index); - } - } - - public void EventLineContextMenuDelete(object obj) - { - EventLineContextMenuObject eventObj = (EventLineContextMenuObject)obj; - AnimationClip clip = eventObj.m_Clip; - if (clip == null) - return; - - int clickedIndex = eventObj.m_Index; - - // If a selection already exists, delete selection instead of clicked index - if (Array.Exists(eventObj.m_Selected, selected => selected)) - { - DeleteEvents(clip, eventObj.m_Selected); - } - // Else, only delete the clicked animation event - else if (clickedIndex >= 0) - { - bool[] deleteIndices = new bool[eventObj.m_Selected.Length]; - deleteIndices[clickedIndex] = true; - DeleteEvents(clip, deleteIndices); - } - } - - private void CheckRectsOnMouseMove(Rect eventLineRect, AnimationEvent[] events, Rect[] hitRects) - { - Vector2 mouse = Event.current.mousePosition; - bool hasFound = false; - - if (events.Length == hitRects.Length) - { - for (int i = hitRects.Length - 1; i >= 0; i--) - { - if (hitRects[i].Contains(mouse)) - { - hasFound = true; - if (m_HoverEvent != i) - { - m_HoverEvent = i; - m_InstantTooltipText = events[m_HoverEvent].functionName; - m_InstantTooltipPoint = new Vector2(hitRects[m_HoverEvent].xMin + (int)(hitRects[m_HoverEvent].width / 2) + eventLineRect.x, eventLineRect.yMax); - m_DirtyTooltip = true; - } - } - } - } - if (!hasFound) - { - m_HoverEvent = -1; - m_InstantTooltipText = ""; - } - } - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/Deprecated/EditorGUIExt.cs b/Editor/Mono/Animation/AnimationWindow/Deprecated/EditorGUIExt.cs deleted file mode 100644 index efe26cd040..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/Deprecated/EditorGUIExt.cs +++ /dev/null @@ -1,853 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class EditorGUIExt - { - class Styles - { - public GUIStyle selectionRect = "SelectionRect"; - } - static Styles ms_Styles = new Styles(); - - // Copied from GUI class and modified slightly to not require - // calls to methods that are internal to the GUI class - static bool DoRepeatButton(Rect position, GUIContent content, GUIStyle style, FocusType focusType) - { - //GUIUtility.CheckOnGUI (); - int id = GUIUtility.GetControlID(repeatButtonHash, focusType, position); - switch (Event.current.GetTypeForControl(id)) - { - case EventType.MouseDown: - // If the mouse is inside the button, we say that we're the hot control - if (position.Contains(Event.current.mousePosition)) - { - GUIUtility.hotControl = id; - Event.current.Use(); - } - return false; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - - // If we got the mousedown, the mouseup is ours as well - // (no matter if the click was in the button or not) - Event.current.Use(); - - // But we only return true if the button was actually clicked - return position.Contains(Event.current.mousePosition); - } - return false; - case EventType.Repaint: - style.Draw(position, content, id); - // Handles.Repaint (); - return id == GUIUtility.hotControl && position.Contains(Event.current.mousePosition); - } - return false; - } - - static int repeatButtonHash = "repeatButton".GetHashCode(); - - static float nextScrollStepTime = 0; - static int firstScrollWait = 250; // ms - static int scrollWait = 30; // ms - - /// *undocumented* - // Copied from GUI class and modified slightly to not require - // calls to methods that are internal to the GUI class - static bool ScrollerRepeatButton(int scrollerID, Rect rect, GUIStyle style) - { - bool changed = false; - - if (DoRepeatButton(rect, GUIContent.none, style, FocusType.Passive)) - { - bool firstClick = scrollControlID != scrollerID; - scrollControlID = scrollerID; - - if (firstClick) - { - changed = true; - nextScrollStepTime = Time.realtimeSinceStartup + 0.001f * firstScrollWait; - } - else - { - if (Time.realtimeSinceStartup >= nextScrollStepTime) - { - changed = true; - nextScrollStepTime = Time.realtimeSinceStartup + 0.001f * scrollWait; - } - } - - if (Event.current.type == EventType.Repaint) - // GUI.InternalRepaintEditorWindow(); - HandleUtility.Repaint(); - } - - return changed; - } - - static int scrollControlID; - 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) - { - //GUIUtility.CheckOnGUI (); - - float scrollStepSize; - if (horiz) - scrollStepSize = size * 10 / position.width; - else - scrollStepSize = size * 10 / position.height; - - // - - Rect sliderRect, minRect, maxRect; - - if (horiz) - { - sliderRect = new Rect( - position.x + leftButton.fixedWidth, position.y, - position.width - leftButton.fixedWidth - rightButton.fixedWidth, position.height - ); - minRect = new Rect(position.x, position.y, leftButton.fixedWidth, position.height); - maxRect = new Rect(position.xMax - rightButton.fixedWidth, position.y, rightButton.fixedWidth, position.height); - } - else - { - sliderRect = new Rect( - position.x, position.y + leftButton.fixedHeight, - position.width, position.height - leftButton.fixedHeight - rightButton.fixedHeight - ); - minRect = new Rect(position.x, position.y, position.width, leftButton.fixedHeight); - maxRect = new Rect(position.x, position.yMax - rightButton.fixedHeight, position.width, rightButton.fixedHeight); - } - - float newVisualStart = Mathf.Min(visualStart, value); - float newVisualEnd = Mathf.Max(visualEnd , value + size); - - MinMaxSlider(sliderRect, ref value, ref size, newVisualStart, newVisualEnd, newVisualStart, newVisualEnd, slider, thumb, horiz); - - bool wasMouseUpEvent = false; - if (Event.current.type == EventType.MouseUp) - wasMouseUpEvent = true; - - if (ScrollerRepeatButton(id, minRect, leftButton)) - value -= scrollStepSize * (visualStart < visualEnd ? 1f : -1f); - - if (ScrollerRepeatButton(id, maxRect, rightButton)) - value += scrollStepSize * (visualStart < visualEnd ? 1f : -1f); - - if (wasMouseUpEvent && Event.current.type == EventType.Used) // repeat buttons ate mouse up event - release scrolling - scrollControlID = 0; - - if (startLimit < endLimit) - value = Mathf.Clamp(value, startLimit, endLimit - size); - else - value = Mathf.Clamp(value, endLimit, startLimit - size); - } - - // State for when we're dragging a MinMax slider. - class MinMaxSliderState - { - public float dragStartPos = 0; // Start of the drag (mousePosition) - public float dragStartValue = 0; // Value at start of drag. - public float dragStartSize = 0; // Size at start of drag. - public float dragStartValuesPerPixel = 0; - public float dragStartLimit = 0; // start limit at start of drag - public float dragEndLimit = 0; // end limit at start of drag - public int whereWeDrag = -1; // which part are we dragging? 0 = middle, 1 = min, 2 = max, 3 = min trough, 4 = max trough - } - - static MinMaxSliderState s_MinMaxSliderState; - static int kFirstScrollWait = 250; // ms - static int kScrollWait = 30; // ms - static System.DateTime s_NextScrollStepTime = System.DateTime.Now; // whatever but null - - // Mouse down position for - private static Vector2 s_MouseDownPos = Vector2.zero; - // Are we doing a drag selection (as opposed to when the mousedown was over a selection rect) - enum DragSelectionState - { - None, DragSelecting, Dragging - } - static DragSelectionState s_MultiSelectDragSelection = DragSelectionState.None; - static Vector2 s_StartSelectPos = Vector2.zero; - static List s_SelectionBackup = null; - static List s_LastFrameSelections = null; - internal static int s_MinMaxSliderHash = "MinMaxSlider".GetHashCode(); - /// Make a double-draggable slider that will let you specify a range of values. - /// @param position where to draw it - /// @param value the current start position - /// @param size the size of the covered range - /// @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. - /// @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. - /// @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 - /// @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 - 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) - { - DoMinMaxSlider(position, GUIUtility.GetControlID(s_MinMaxSliderHash, FocusType.Passive), ref value, ref size, visualStart, visualEnd, startLimit, endLimit, slider, thumb, horiz); - } - - 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) - { - Event evt = Event.current; - bool usePageScrollbars = size == 0; - - float minVisual = Mathf.Min(visualStart, visualEnd); - float maxVisual = Mathf.Max(visualStart, visualEnd); - float minLimit = Mathf.Min(startLimit, endLimit); - float maxLimit = Mathf.Max(startLimit, endLimit); - - MinMaxSliderState state = s_MinMaxSliderState; - - if (GUIUtility.hotControl == id && state != null) - { - minVisual = state.dragStartLimit; - minLimit = state.dragStartLimit; - maxVisual = state.dragEndLimit; - maxLimit = state.dragEndLimit; - } - - float minSize = 0; - - float displayValue = Mathf.Clamp(value, minVisual, maxVisual); - float displaySize = Mathf.Clamp(value + size, minVisual, maxVisual) - displayValue; - - float sign = visualStart > visualEnd ? -1 : 1; - - - if (slider == null || thumb == null) - return; - - // Figure out the rects - float pixelsPerValue; - float mousePosition; - Rect thumbRect; - Rect thumbMinRect, thumbMaxRect; - if (horiz) - { - float thumbSize = thumb.fixedWidth != 0 ? thumb.fixedWidth : thumb.padding.horizontal; - pixelsPerValue = (position.width - slider.padding.horizontal - thumbSize) / (maxVisual - minVisual); - thumbRect = new Rect( - (displayValue - minVisual) * pixelsPerValue + position.x + slider.padding.left, - position.y + slider.padding.top, - displaySize * pixelsPerValue + thumbSize, - position.height - slider.padding.vertical); - thumbMinRect = new Rect(thumbRect.x, thumbRect.y, thumb.padding.left, thumbRect.height); - thumbMaxRect = new Rect(thumbRect.xMax - thumb.padding.right, thumbRect.y, thumb.padding.right, thumbRect.height); - mousePosition = evt.mousePosition.x - position.x; - } - else - { - float thumbSize = thumb.fixedHeight != 0 ? thumb.fixedHeight : thumb.padding.vertical; - pixelsPerValue = (position.height - slider.padding.vertical - thumbSize) / (maxVisual - minVisual); - thumbRect = new Rect( - position.x + slider.padding.left, - (displayValue - minVisual) * pixelsPerValue + position.y + slider.padding.top, - position.width - slider.padding.horizontal, - displaySize * pixelsPerValue + thumbSize); - thumbMinRect = new Rect(thumbRect.x, thumbRect.y, thumbRect.width, thumb.padding.top); - thumbMaxRect = new Rect(thumbRect.x, thumbRect.yMax - thumb.padding.bottom, thumbRect.width, thumb.padding.bottom); - mousePosition = evt.mousePosition.y - position.y; - } - - float mousePos; - float thumbPos; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - // if the click is outside this control, just bail out... - if (!position.Contains(evt.mousePosition) || minVisual - maxVisual == 0) - return; - if (state == null) - state = s_MinMaxSliderState = new MinMaxSliderState(); - - // These are required to be set whenever we grab hotcontrol, regardless of if we actually drag or not. (case 585577) - state.dragStartLimit = startLimit; - state.dragEndLimit = endLimit; - - if (thumbRect.Contains(evt.mousePosition)) - { - // We have a mousedown on the thumb - // Record where we're draging from, so the user can get back. - state.dragStartPos = mousePosition; - state.dragStartValue = value; - state.dragStartSize = size; - state.dragStartValuesPerPixel = pixelsPerValue; - if (thumbMinRect.Contains(evt.mousePosition)) - state.whereWeDrag = 1; - else if (thumbMaxRect.Contains(evt.mousePosition)) - state.whereWeDrag = 2; - else - state.whereWeDrag = 0; - - GUIUtility.hotControl = id; - evt.Use(); - return; - } - else - { - // We're outside the thumb, but inside the trough. - // If we have no background, we just bail out. - if (slider == GUIStyle.none) - return; - - // If we have a scrollSize, we do pgup/pgdn style movements - // if not, we just snap to the current position and begin tracking - if (size != 0 && usePageScrollbars) - { - if (horiz) - { - if (mousePosition > thumbRect.xMax - position.x) - value += size * sign * .9f; - else - value -= size * sign * .9f; - } - else - { - if (mousePosition > thumbRect.yMax - position.y) - value += size * sign * .9f; - else - value -= size * sign * .9f; - } - state.whereWeDrag = 0; - GUI.changed = true; - s_NextScrollStepTime = System.DateTime.Now.AddMilliseconds(kFirstScrollWait); - - mousePos = horiz ? evt.mousePosition.x : evt.mousePosition.y; - thumbPos = horiz ? thumbRect.x : thumbRect.y; - - state.whereWeDrag = mousePos > thumbPos ? 4 : 3; - } - else - { - if (horiz) - value = ((float)mousePosition - thumbRect.width * .5f) / pixelsPerValue + minVisual - size * .5f; - else - value = ((float)mousePosition - thumbRect.height * .5f) / pixelsPerValue + minVisual - size * .5f; - state.dragStartPos = mousePosition; - state.dragStartValue = value; - state.dragStartSize = size; - state.dragStartValuesPerPixel = pixelsPerValue; - state.whereWeDrag = 0; - GUI.changed = true; - } - GUIUtility.hotControl = id; - value = Mathf.Clamp(value, minLimit, maxLimit - size); - evt.Use(); - return; - } - case EventType.MouseDrag: - if (GUIUtility.hotControl != id) - return; - - // Recalculate the value from the mouse position. this has the side effect that values are relative to the - // click point - no matter where inside the trough the original value was. Also means user can get back original value - // if he drags back to start position. - float deltaVal = (mousePosition - state.dragStartPos) / state.dragStartValuesPerPixel; - switch (state.whereWeDrag) - { - case 0: // normal drag - value = Mathf.Clamp(state.dragStartValue + deltaVal, minLimit, maxLimit - size); - break; - case 1:// min size drag - value = state.dragStartValue + deltaVal; - size = state.dragStartSize - deltaVal; - if (value < minLimit) - { - size -= minLimit - value; - value = minLimit; - } - if (size < minSize) - { - value -= minSize - size; - size = minSize; - } - break; - case 2:// max size drag - size = state.dragStartSize + deltaVal; - if (value + size > maxLimit) - size = maxLimit - value; - if (size < minSize) - size = minSize; - break; - } - GUI.changed = true; - evt.Use(); - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - evt.Use(); - GUIUtility.hotControl = 0; - } - break; - case EventType.Repaint: - slider.Draw(position, GUIContent.none, id); - thumb.Draw(thumbRect, GUIContent.none, id); - - // if the mouse is outside this control, just bail out... - if (GUIUtility.hotControl != id || - !position.Contains(evt.mousePosition) || minVisual - maxVisual == 0) - { - return; - } - - if (thumbRect.Contains(evt.mousePosition)) - { - if (state != null && (state.whereWeDrag == 3 || state.whereWeDrag == 4)) // if was scrolling with "through" and the thumb reached mouse - sliding action over - GUIUtility.hotControl = 0; - return; - } - - - if (System.DateTime.Now < s_NextScrollStepTime) - return; - - mousePos = horiz ? evt.mousePosition.x : evt.mousePosition.y; - thumbPos = horiz ? thumbRect.x : thumbRect.y; - - int currentSide = mousePos > thumbPos ? 4 : 3; - if (currentSide != state.whereWeDrag) - return; - - // If we have a scrollSize, we do pgup/pgdn style movements - if (size != 0 && usePageScrollbars) - { - if (horiz) - { - if (mousePosition > thumbRect.xMax - position.x) - value += size * sign * .9f; - else - value -= size * sign * .9f; - } - else - { - if (mousePosition > thumbRect.yMax - position.y) - value += size * sign * .9f; - else - value -= size * sign * .9f; - } - state.whereWeDrag = -1; - GUI.changed = true; - } - value = Mathf.Clamp(value, minLimit, maxLimit - size); - - s_NextScrollStepTime = System.DateTime.Now.AddMilliseconds(kScrollWait); - break; - } - } - - private static bool adding = false; - private static bool[] initSelections; - private static int initIndex = 0; - - // Used for selecting multiple rows on the left in the animation window. - public static bool DragSelection(Rect[] positions, ref bool[] selections, GUIStyle style) - { - int id = GUIUtility.GetControlID(34553287, FocusType.Keyboard); - Event evt = Event.current; - int selectedIndex = -1; - for (int i = positions.Length - 1; i >= 0; i--) - if (positions[i].Contains(evt.mousePosition)) - { - selectedIndex = i; - break; - } - - EventType type = evt.GetTypeForControl(id); - switch (type) - { - case EventType.Repaint: - for (int i = 0; i < positions.Length; i++) - style.Draw(positions[i], GUIContent.none, id, selections[i]); - break; - case EventType.MouseDown: - if (evt.button == 0 && selectedIndex >= 0) - { - GUIUtility.keyboardControl = 0; - - bool deselecting = false; - // If clicking on an already selected item - if (selections[selectedIndex]) - { - int counter = 0; - foreach (bool sel in selections) - { - if (sel) - { - counter++; - if (counter > 1) - break; - } - } - // ...and it's the only one selected, then deselect it - if (counter == 1) - deselecting = true; - } - - // Shift click to add to current selection - if (!evt.shift && !EditorGUI.actionKey) - for (int i = 0; i < positions.Length; i++) - selections[i] = false; - - initIndex = selectedIndex; - initSelections = (bool[])selections.Clone(); - - // Command click to toggle - adding = true; - if ((evt.shift || EditorGUI.actionKey) && selections[selectedIndex] == true) - adding = false; - - selections[selectedIndex] = (deselecting ? false : adding); - GUIUtility.hotControl = id; - evt.Use(); - - return true; - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - if (evt.button == 0) - { - if (selectedIndex < 0) - { - // Clamp index to nearest positions if outside of range - // (so that less precision is required for hitting the last rect) - Rect dummyRect = new Rect(positions[0].x, positions[0].y - 200, positions[0].width, 200); - if (dummyRect.Contains(evt.mousePosition)) - selectedIndex = 0; - dummyRect.y = positions[positions.Length - 1].yMax; - if (dummyRect.Contains(evt.mousePosition)) - selectedIndex = selections.Length - 1; - } - if (selectedIndex < 0) - return false; - - int min = Mathf.Min(initIndex, selectedIndex); - int max = Mathf.Max(initIndex, selectedIndex); - for (int i = 0; i < selections.Length; i++) - { - if (i >= min && i <= max) - selections[i] = adding; - else - selections[i] = initSelections[i]; - } - evt.Use(); - return true; - } - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - GUIUtility.hotControl = 0; - break; - } - - return false; - } - - static bool Any(bool[] selections) - { - for (int i = 0; i < selections.Length; i++) - { - if (selections[i]) - return true; - } - return false; - } - - public static HighLevelEvent MultiSelection( - Rect rect, - Rect[] positions, - GUIContent content, - Rect[] hitPositions, - ref bool[] selections, - bool[] readOnly, - out int clickedIndex, - out Vector2 offset, - out float startSelect, - out float endSelect, - GUIStyle style - ) - { - int id = GUIUtility.GetControlID(41623453, FocusType.Keyboard); - Event evt = Event.current; - - offset = Vector2.zero; - clickedIndex = -1; - startSelect = endSelect = 0f; - - if (evt.type == EventType.Used) - return HighLevelEvent.None; - - bool selected = false; - if (Event.current.type != EventType.Layout) - { - if (GUIUtility.keyboardControl == id) - selected = true; - } - - int selectedIndex; - - EventType type = evt.GetTypeForControl(id); - switch (type) - { - case EventType.Repaint: - // Draw selection rect - if (GUIUtility.hotControl == id && s_MultiSelectDragSelection == DragSelectionState.DragSelecting) - { - float min = Mathf.Min(s_StartSelectPos.x, evt.mousePosition.x); - float max = Mathf.Max(s_StartSelectPos.x, evt.mousePosition.x); - Rect selRect = new Rect(0, 0, rect.width, rect.height); - selRect.x = min; - selRect.width = max - min; - // Display if bigger than 1 pixel. - if (selRect.width > 1) - GUI.Box(selRect, "", ms_Styles.selectionRect); - } - - // Draw controls - Color tempCol = GUI.color; - for (int i = 0; i < positions.Length; i++) - { - if (readOnly != null && readOnly[i]) - GUI.color = tempCol * new Color(0.90f, 0.90f, 0.90f, 0.5f); - else if (selections[i]) - GUI.color = tempCol * new Color(0.30f, 0.55f, 0.95f, 1); - else - GUI.color = tempCol * new Color(0.90f, 0.90f, 0.90f, 1); - style.Draw(positions[i], content, id, selections[i]); - } - GUI.color = tempCol; - break; - case EventType.MouseDown: - if (evt.button == 0) - { - GUIUtility.hotControl = id; - GUIUtility.keyboardControl = id; - s_StartSelectPos = evt.mousePosition; - selectedIndex = GetIndexUnderMouse(hitPositions, readOnly); - - if (Event.current.clickCount == 2) - { - if (selectedIndex >= 0) - { - for (int i = 0; i < selections.Length; i++) - selections[i] = false; - - selections[selectedIndex] = true; - - evt.Use(); - clickedIndex = selectedIndex; - return HighLevelEvent.DoubleClick; - } - } - - if (selectedIndex >= 0) - { - // Shift click to add to current selection - if (!evt.shift && !EditorGUI.actionKey && !selections[selectedIndex]) - for (int i = 0; i < hitPositions.Length; i++) - selections[i] = false; - - if (evt.shift || EditorGUI.actionKey) - selections[selectedIndex] = !selections[selectedIndex]; - else - selections[selectedIndex] = true; - - s_MouseDownPos = evt.mousePosition; - s_MultiSelectDragSelection = DragSelectionState.None; - evt.Use(); - clickedIndex = selectedIndex; - return HighLevelEvent.SelectionChanged; - } - else - { - // Shift click to add to current selection - bool changed = false; - if (!evt.shift && !EditorGUI.actionKey) - { - for (int i = 0; i < hitPositions.Length; i++) - selections[i] = false; - changed = true; - } - else - changed = false; - - s_SelectionBackup = new List(selections); - s_LastFrameSelections = new List(selections); - - s_MultiSelectDragSelection = DragSelectionState.DragSelecting; - evt.Use(); - return changed ? HighLevelEvent.SelectionChanged : HighLevelEvent.None; - } - } - - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - if (s_MultiSelectDragSelection == DragSelectionState.DragSelecting) - { - float min = Mathf.Min(s_StartSelectPos.x, evt.mousePosition.x); - float max = Mathf.Max(s_StartSelectPos.x, evt.mousePosition.x); - s_SelectionBackup.CopyTo(selections); - for (int i = 0; i < hitPositions.Length; i++) - { - if (selections[i]) - continue; - - float center = hitPositions[i].x + hitPositions[i].width * .5f; - if (center >= min && center <= max) - selections[i] = true; - } - evt.Use(); - startSelect = min; - endSelect = max; - - // Check if the selections _actually_ changed from last call - bool changed = false; - for (int i = 0; i < selections.Length; i++) - { - if (selections[i] != s_LastFrameSelections[i]) - { - changed = true; - s_LastFrameSelections[i] = selections[i]; - } - } - return changed ? HighLevelEvent.SelectionChanged : HighLevelEvent.None; - } - else - { - offset = evt.mousePosition - s_MouseDownPos; - evt.Use(); - if (s_MultiSelectDragSelection == DragSelectionState.None) - { - s_MultiSelectDragSelection = DragSelectionState.Dragging; - return HighLevelEvent.BeginDrag; - } - else - { - return HighLevelEvent.Drag; - } - } - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - - if (s_StartSelectPos != evt.mousePosition) - evt.Use(); - - // TODO fix magic number for max dragging distance to be ignored - if (s_MultiSelectDragSelection == DragSelectionState.None) - { - clickedIndex = GetIndexUnderMouse(hitPositions, readOnly); - if (evt.clickCount == 1) - return HighLevelEvent.Click; - } - else - { - s_MultiSelectDragSelection = DragSelectionState.None; - s_SelectionBackup = null; - s_LastFrameSelections = null; - return HighLevelEvent.EndDrag; - } - } - break; - case EventType.ValidateCommand: - case EventType.ExecuteCommand: - - if (selected) - { - bool execute = evt.type == EventType.ExecuteCommand; - switch (evt.commandName) - { - case EventCommandNames.Delete: - evt.Use(); - if (execute) - { - return HighLevelEvent.Delete; - } - break; - } - } - break; - case EventType.KeyDown: - if (selected) - { - if (evt.keyCode == KeyCode.Backspace || evt.keyCode == KeyCode.Delete) - { - evt.Use(); - return HighLevelEvent.Delete; - } - } - break; - case EventType.ContextClick: - selectedIndex = GetIndexUnderMouse(hitPositions, readOnly); - if (selectedIndex >= 0) - { - clickedIndex = selectedIndex; - GUIUtility.keyboardControl = id; - evt.Use(); - return HighLevelEvent.ContextClick; - } - break; - } - - return HighLevelEvent.None; - } - - // Helper for MultiSelection above. - static int GetIndexUnderMouse(Rect[] hitPositions, bool[] readOnly) - { - Vector2 mousePos = Event.current.mousePosition; - - for (int i = hitPositions.Length - 1; i >= 0; i--) - if ((readOnly == null || !readOnly[i]) && hitPositions[i].Contains(mousePos)) - return i; - - return -1; - } - - // Small helper: Make a rect from MinMax values and make sure they're positive sizes - internal static Rect FromToRect(Vector2 start, Vector2 end) - { - Rect r = new Rect(start.x, start.y, end.x - start.x, end.y - start.y); - if (r.width < 0) - { - r.x += r.width; - r.width = -r.width; - } - if (r.height < 0) - { - r.y += r.height; - r.height = -r.height; - } - return r; - } - } - - internal enum HighLevelEvent - { - None, - Click, - DoubleClick, - ContextClick, - BeginDrag, - Drag, - EndDrag, - Delete, - SelectionChanged, - } -} //namespace diff --git a/Editor/Mono/Animation/AnimationWindow/Deprecated/UtilityClasses.cs b/Editor/Mono/Animation/AnimationWindow/Deprecated/UtilityClasses.cs deleted file mode 100644 index 5ef86395fa..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/Deprecated/UtilityClasses.cs +++ /dev/null @@ -1,466 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -using TangentMode = UnityEditor.AnimationUtility.TangentMode; - -namespace UnityEditor -{ - internal static class CurveUtility - { - private static Texture2D iconKey; - private static Texture2D iconCurve; - - - public static int GetPathAndTypeID(string path, Type type) - { - return path.GetHashCode() * 27 ^ type.GetHashCode(); - } - - public static Texture2D GetIconCurve() - { - if (iconCurve == null) - iconCurve = EditorGUIUtility.LoadIcon("animationanimated"); - return iconCurve; - } - - public static Texture2D GetIconKey() - { - if (iconKey == null) - iconKey = EditorGUIUtility.LoadIcon("animationkeyframe"); - return iconKey; - } - - public static bool HaveKeysInRange(AnimationCurve curve, float beginTime, float endTime) - { - // Loop backwards - for (int i = curve.length - 1; i >= 0; i--) - { - if (curve[i].time >= beginTime && curve[i].time < endTime) - { - return true; - } - } - return false; - } - - public static void RemoveKeysInRange(AnimationCurve curve, float beginTime, float endTime) - { - // Loop backwards so key removals don't mess up order - for (int i = curve.length - 1; i >= 0; i--) - { - if (curve[i].time >= beginTime && curve[i].time < endTime) - { - curve.RemoveKey(i); - } - } - } - - public static float CalculateSmoothTangent(Keyframe key) - { - if (key.inTangent == Mathf.Infinity) key.inTangent = 0; - if (key.outTangent == Mathf.Infinity) key.outTangent = 0; - return (key.outTangent + key.inTangent) * 0.5f; - } - - // Move me to CurveEditor.cs - public static void SetKeyModeFromContext(AnimationCurve curve, int keyIndex) - { - Keyframe key = curve[keyIndex]; - bool broken = false; - bool smoothTangent = false; - - if (keyIndex > 0) - { - if (AnimationUtility.GetKeyBroken(curve[keyIndex - 1])) - broken = true; - TangentMode prevTangentMode = AnimationUtility.GetKeyRightTangentMode(curve[keyIndex - 1]); - if (prevTangentMode == TangentMode.ClampedAuto || prevTangentMode == TangentMode.Auto) - smoothTangent = true; - } - if (keyIndex < curve.length - 1) - { - if (AnimationUtility.GetKeyBroken(curve[keyIndex + 1])) - broken = true; - TangentMode nextTangentMode = AnimationUtility.GetKeyLeftTangentMode(curve[keyIndex + 1]); - if (nextTangentMode == TangentMode.ClampedAuto || nextTangentMode == TangentMode.Auto) - smoothTangent = true; - } - - AnimationUtility.SetKeyBroken(ref key, broken); - - if (broken && !smoothTangent) - { - if (keyIndex > 0) AnimationUtility.SetKeyLeftTangentMode(ref key, AnimationUtility.GetKeyRightTangentMode(curve[keyIndex - 1])); - if (keyIndex < curve.length - 1) AnimationUtility.SetKeyRightTangentMode(ref key, AnimationUtility.GetKeyLeftTangentMode(curve[keyIndex + 1])); - - // Keys at boundaries. Make sure left and right tangent modes are the same. - if (keyIndex == 0) AnimationUtility.SetKeyLeftTangentMode(ref key, AnimationUtility.GetKeyRightTangentMode(key)); - if (keyIndex == curve.length - 1) AnimationUtility.SetKeyRightTangentMode(ref key, AnimationUtility.GetKeyLeftTangentMode(key)); - } - else - { - // If both neighbors or only neighbor are set to TangentMode.Auto or TangentMode.ClampedAuto, set new key to this mode as well. - // If there are no neighbors, set new key to TangentMode.ClampedAuto. - // Otherwise, fall back to TangentMode.Free. - TangentMode mode = TangentMode.Free; - if ((keyIndex == 0 || AnimationUtility.GetKeyRightTangentMode(curve[keyIndex - 1]) == TangentMode.ClampedAuto) && - (keyIndex == curve.length - 1 || AnimationUtility.GetKeyLeftTangentMode(curve[keyIndex + 1]) == TangentMode.ClampedAuto)) - { - mode = TangentMode.ClampedAuto; - } - else if ((keyIndex == 0 || AnimationUtility.GetKeyRightTangentMode(curve[keyIndex - 1]) == TangentMode.Auto) && - (keyIndex == curve.length - 1 || AnimationUtility.GetKeyLeftTangentMode(curve[keyIndex + 1]) == TangentMode.Auto)) - { - mode = TangentMode.Auto; - } - - AnimationUtility.SetKeyLeftTangentMode(ref key, mode); - AnimationUtility.SetKeyRightTangentMode(ref key, mode); - } - - curve.MoveKey(keyIndex, key); - } - - static public string GetClipName(AnimationClip clip) - { - if (clip == null) - return "[No Clip]"; - - string name = clip.name; - - if ((clip.hideFlags & HideFlags.NotEditable) != 0) - name += " (Read-Only)"; - - return name; - } - - public static Color GetBalancedColor(Color c) - { - return new Color( - 0.15f + 0.75f * c.r, - 0.20f + 0.60f * c.g, - 0.10f + 0.90f * c.b - ); - } - - public static Color GetPropertyColor(string name) - { - Color col = Color.white; - - int type = 0; - if (name.StartsWith("m_LocalPosition")) type = 1; - if (name.StartsWith("localEulerAngles")) type = 2; - if (name.StartsWith("m_LocalScale")) type = 3; - - if (type == 1) - { - if (name.EndsWith(".x")) col = Handles.xAxisColor; - else if (name.EndsWith(".y")) col = Handles.yAxisColor; - else if (name.EndsWith(".z")) col = Handles.zAxisColor; - } - else if (type == 2) - { - if (name.EndsWith(".x")) col = AnimEditor.kEulerXColor; - else if (name.EndsWith(".y")) col = AnimEditor.kEulerYColor; - else if (name.EndsWith(".z")) col = AnimEditor.kEulerZColor; - } - else if (type == 3) - { - if (name.EndsWith(".x")) col = GetBalancedColor(new Color(0.7f, 0.4f, 0.4f)); - else if (name.EndsWith(".y")) col = GetBalancedColor(new Color(0.4f, 0.7f, 0.4f)); - else if (name.EndsWith(".z")) col = GetBalancedColor(new Color(0.4f, 0.4f, 0.7f)); - } - else if (name.EndsWith(".x")) col = Handles.xAxisColor; - else if (name.EndsWith(".y")) col = Handles.yAxisColor; - else if (name.EndsWith(".z")) col = Handles.zAxisColor; - else if (name.EndsWith(".w")) col = new Color(1.0f, 0.5f, 0.0f); - else if (name.EndsWith(".r")) col = GetBalancedColor(Color.red); - else if (name.EndsWith(".g")) col = GetBalancedColor(Color.green); - else if (name.EndsWith(".b")) col = GetBalancedColor(Color.blue); - else if (name.EndsWith(".a")) col = GetBalancedColor(Color.yellow); - else if (name.EndsWith(".width")) col = GetBalancedColor(Color.blue); - else if (name.EndsWith(".height")) col = GetBalancedColor(Color.yellow); - else - { - float rand = Mathf.PI * 2 * (name.GetHashCode() % 1000); - rand = rand - Mathf.Floor(rand); - col = GetBalancedColor(Color.HSVToRGB(rand, 1, 1)); - } - col.a = 1; // Some preference colors do not have full alpha - return col; - } - } - - struct QuaternionCurveTangentCalculation - { - AnimationCurve eulerX; - AnimationCurve eulerY; - AnimationCurve eulerZ; - - public AnimationCurve GetCurve(int index) - { - if (index == 0) - return eulerX; - else if (index == 1) - return eulerY; - else - return eulerZ; - } - - public void SetCurve(int index, AnimationCurve curve) - { - if (index == 0) - eulerX = curve; - else if (index == 1) - eulerY = curve; - else - eulerZ = curve; - } - - private Vector3 EvaluateEulerCurvesDirectly(float time) - { - return new Vector3( - eulerX.Evaluate(time), - eulerY.Evaluate(time), - eulerZ.Evaluate(time)); - } - - public float CalculateLinearTangent(int fromIndex, int toIndex, int componentIndex) - { - AnimationCurve curve = GetCurve(componentIndex); - return CalculateLinearTangent(curve[fromIndex], curve[toIndex], componentIndex); - } - - public float CalculateLinearTangent(Keyframe from, Keyframe to, int component) - { - float epsilon = 0.01f; - Vector3 fromEuler = EvaluateEulerCurvesDirectly(to.time); - Vector3 toEuler = EvaluateEulerCurvesDirectly(from.time); - Quaternion fromQ = Quaternion.Euler(fromEuler); - Quaternion toQ = Quaternion.Euler(toEuler); - Quaternion slerped = Quaternion.Slerp(fromQ, toQ, epsilon); - Vector3 euler = GetEulerFromQuaternion(slerped, fromEuler); - switch (component) - { - case 0: return (euler.x - fromEuler.x) / epsilon / -(to.time - from.time); - case 1: return (euler.y - fromEuler.y) / epsilon / -(to.time - from.time); - case 2: return (euler.z - fromEuler.z) / epsilon / -(to.time - from.time); - default: return 0; - } - } - - public float CalculateSmoothTangent(int index, int component) - { - AnimationCurve curve = GetCurve(component); - if (curve.length < 2) - return 0; - - // First keyframe - // slope are set to be the linear slerped slope from this to the right key - if (index <= 0) - return CalculateLinearTangent(curve[0], curve[1], component); - - // last keyframe - // slope is set to be the linear slerped slope from this to the left key - if (index >= curve.length - 1) - return CalculateLinearTangent(curve[curve.length - 1], curve[curve.length - 2], component); - - // Keys are on the left and right - // Calculates the slopes from this key to the left key and the right key. - float prevTime = curve[index - 1].time; - float thisTime = curve[index].time; - float nextTime = curve[index + 1].time; - Vector3 prevEuler = EvaluateEulerCurvesDirectly(prevTime); - Vector3 thisEuler = EvaluateEulerCurvesDirectly(thisTime); - Vector3 nextEuler = EvaluateEulerCurvesDirectly(nextTime); - Quaternion prevQ = Quaternion.Euler(prevEuler); - Quaternion thisQ = Quaternion.Euler(thisEuler); - Quaternion nextQ = Quaternion.Euler(nextEuler); - if (prevQ.x * thisQ.x + prevQ.y * thisQ.y + prevQ.z * thisQ.z + prevQ.w * thisQ.w < 0) - prevQ = new Quaternion(-prevQ.x, -prevQ.y, -prevQ.z, -prevQ.w); - if (nextQ.x * thisQ.x + nextQ.y * thisQ.y + nextQ.z * thisQ.z + nextQ.w * thisQ.w < 0) - nextQ = new Quaternion(-nextQ.x, -nextQ.y, -nextQ.z, -nextQ.w); - - Quaternion tangent = new Quaternion(); - float dx1 = thisTime - prevTime; - float dx2 = nextTime - thisTime; - for (int c = 0; c < 4; c++) - { - /* - float dx1 = curve.GetKey (key).time - curve.GetKey (key-1).time; - T dy1 = curve.GetKey (key).value - curve.GetKey (key-1).value; - - float dx2 = curve.GetKey (key+1).time - curve.GetKey (key).time; - T dy2 = curve.GetKey (key+1).value - curve.GetKey (key).value; - - T m1 = SafeDeltaDivide(dy1, dx1); - T m2 = SafeDeltaDivide(dy2, dx2); - - T m = (1.0F + b) * 0.5F * m1 + (1.0F - b) * 0.5F * m2; - curve.GetKey (key).inSlope = m; curve.GetKey (key).outSlope = m; - */ - - float dy1 = thisQ[c] - prevQ[c]; - float dy2 = nextQ[c] - thisQ[c]; - float m1 = SafeDeltaDivide(dy1, dx1); - float m2 = SafeDeltaDivide(dy2, dx2); - tangent[c] = 0.5F * m1 + 0.5F * m2; - } - - float small = Mathf.Abs(nextTime - prevTime) * 0.01f; - Quaternion epsilonBeforeQ = new Quaternion(thisQ.x - tangent.x * small, - thisQ.y - tangent.y * small, - thisQ.z - tangent.z * small, - thisQ.w - tangent.w * small); - Quaternion epsilonAfterQ = new Quaternion(thisQ.x + tangent.x * small, - thisQ.y + tangent.y * small, - thisQ.z + tangent.z * small, - thisQ.w + tangent.w * small); - Vector3 epsilonBeforeEuler = GetEulerFromQuaternion(epsilonBeforeQ, thisEuler); - Vector3 epsilonAfterEuler = GetEulerFromQuaternion(epsilonAfterQ, thisEuler); - Vector3 tangentEuler = (epsilonAfterEuler - epsilonBeforeEuler) / (small * 2); - return tangentEuler[component]; - } - - public static Vector3[] GetEquivalentEulerAngles(Quaternion quat) - { - Vector3 euler = quat.eulerAngles; - Vector3[] eulers = new Vector3[2]; - eulers[0] = euler; - eulers[1] = new Vector3(180 - euler.x, euler.y + 180, euler.z + 180); - return eulers; - } - - public static Vector3 GetEulerFromQuaternion(Quaternion q, Vector3 refEuler) - { - Vector3[] eulers = GetEquivalentEulerAngles(q); - for (int i = 0; i < eulers.Length; i++) - { - eulers[i] = new Vector3( - Mathf.Repeat(eulers[i].x - refEuler.x + 180, 360) + refEuler.x - 180, - Mathf.Repeat(eulers[i].y - refEuler.y + 180, 360) + refEuler.y - 180, - Mathf.Repeat(eulers[i].z - refEuler.z + 180, 360) + refEuler.z - 180 - ); - - float xRot = Mathf.Repeat(eulers[i].x, 360); - if (Mathf.Abs(xRot - 90) < 1.0f) - { - float newCombiAngle = eulers[i].z - eulers[i].y; - float refCombiAngle = refEuler.z - refEuler.y; - float angleDiff = newCombiAngle - refCombiAngle; - eulers[i].z = refEuler.z + angleDiff * 0.5f; - eulers[i].y = refEuler.y - angleDiff * 0.5f; - } - if (Mathf.Abs(xRot - 270) < 1.0f) - { - float newCombiAngle = eulers[i].z + eulers[i].y; - float refCombiAngle = refEuler.z + refEuler.y; - float angleDiff = newCombiAngle - refCombiAngle; - eulers[i].z = refEuler.z + angleDiff * 0.5f; - eulers[i].y = refEuler.y + angleDiff * 0.5f; - } - } - - //for (int i=0; i= curve.length) - return; - - Keyframe key = curve[index]; - // Adjust linear tangent - if (AnimationUtility.GetKeyLeftTangentMode(key) == TangentMode.Linear && index >= 1) - { - key.inTangent = CalculateLinearTangent(index, index - 1, componentIndex); - curve.MoveKey(index, key); - } - if (AnimationUtility.GetKeyRightTangentMode(key) == TangentMode.Linear && index + 1 < curve.length) - { - key.outTangent = CalculateLinearTangent(index, index + 1, componentIndex); - curve.MoveKey(index, key); - } - - // Adjust smooth tangents - if (AnimationUtility.GetKeyLeftTangentMode(key) == TangentMode.ClampedAuto || AnimationUtility.GetKeyRightTangentMode(key) == TangentMode.ClampedAuto) - { - key.inTangent = key.outTangent = CalculateSmoothTangent(index, componentIndex); - curve.MoveKey(index, key); - } - } - - public static void UpdateTangentsFromMode(AnimationCurve curve, AnimationClip clip, EditorCurveBinding curveBinding) - { - // if (RotationCurveInterpolation.GetModeFromCurveData(curveBinding) == RotationCurveInterpolation.Mode.NonBaked) - // { - // QuaternionCurveTangentCalculation tangentCalculator = new QuaternionCurveTangentCalculation(); - // - // int index = RotationCurveInterpolation.GetCurveIndexFromName (curveBinding.propertyName); - // - // for (int i=0;i<3;i++) - // { - // if (i == index) - // tangentCalculator.SetCurve(i, curve); - // else - // { - // EditorCurveBinding tempBinding = curveBinding; - // tempBinding.propertyName = "localEulerAngles." + RotationCurveInterpolation.kPostFix[i]; - // - // AnimationCurve clipCurve = AnimationUtility.GetEditorCurve (clip, tempBinding); - // - // // We need all curves to do quaternion tangent smoothing - // if (clipCurve == null) - // return; - // tangentCalculator.SetCurve(i, clipCurve); - // } - // } - // - // tangentCalculator.UpdateTangentsFromMode(index); - // } - // else - { - AnimationUtility.UpdateTangentsFromMode(curve); - } - } - } -} // namespace diff --git a/Editor/Mono/Animation/AnimationWindow/DopeLine.cs b/Editor/Mono/Animation/AnimationWindow/DopeLine.cs deleted file mode 100644 index c576b1cf2c..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/DopeLine.cs +++ /dev/null @@ -1,122 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using System.Linq; -using System; - -namespace UnityEditorInternal -{ - internal class DopeLine - { - private int m_HierarchyNodeID; - private AnimationWindowCurve[] m_Curves; - private List m_Keys; - - public static GUIStyle dopekeyStyle = "Dopesheetkeyframe"; - - public Rect position; - public System.Type objectType; - public bool tallMode; - public bool hasChildren; - public bool isMasterDopeline; - - public System.Type valueType - { - get - { - if (m_Curves.Length > 0) - { - System.Type type = m_Curves[0].valueType; - for (int i = 1; i < m_Curves.Length; i++) - { - if (m_Curves[i].valueType != type) - return null; - } - return type; - } - - return null; - } - } - - public bool isPptrDopeline - { - get - { - if (m_Curves.Length > 0) - { - for (int i = 0; i < m_Curves.Length; i++) - { - if (!m_Curves[i].isPPtrCurve) - return false; - } - return true; - } - return false; - } - } - - public bool isEditable - { - get - { - if (m_Curves.Length > 0) - { - bool isReadOnly = Array.Exists(m_Curves, curve => !curve.animationIsEditable); - return !isReadOnly; - } - - return false; - } - } - - public int hierarchyNodeID - { - get - { - return m_HierarchyNodeID; - } - } - - public AnimationWindowCurve[] curves - { - get - { - return m_Curves; - } - } - - public List keys - { - get - { - if (m_Keys == null) - { - m_Keys = new List(); - foreach (AnimationWindowCurve curve in m_Curves) - foreach (AnimationWindowKeyframe key in curve.m_Keyframes) - m_Keys.Add(key); - - m_Keys.Sort((a, b) => a.time.CompareTo(b.time)); - } - - return m_Keys; - } - } - - public void InvalidateKeyframes() - { - m_Keys = null; - } - - public DopeLine(int hierarchyNodeID, AnimationWindowCurve[] curves) - { - m_HierarchyNodeID = hierarchyNodeID; - m_Curves = curves; - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/DopeSheetEditor.cs b/Editor/Mono/Animation/AnimationWindow/DopeSheetEditor.cs deleted file mode 100644 index 74cc937c70..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/DopeSheetEditor.cs +++ /dev/null @@ -1,1489 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using Boo.Lang.Compiler.Ast; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Event = UnityEngine.Event; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - [System.Serializable] - internal class DopeSheetEditor : TimeArea, CurveUpdater - { - public AnimationWindowState state; - - // How much rendered keyframe left edge is visually offset when compared to the time it represents. - // A diamond shape left edge isn't representing the time, the middle part is. - private const float k_KeyframeOffset = -6.5f; - // Pptr keyframe preview also needs 1px offset so it sits more tightly in the grid - private const float k_PptrKeyframeOffset = -1; - - const int kLabelMarginHorizontal = 8; - const int kLabelMarginVertical = 2; - - struct DrawElement - { - public Rect position; - public Color color; - public Texture2D texture; - - public DrawElement(Rect position, Color color, Texture2D texture) - { - this.position = position; - this.color = color; - this.texture = texture; - } - } - - // Control point collection renderer - class DopeSheetControlPointRenderer - { - // Unoptimized control point list. Rendered through GUI.Label calls. - private List m_UnselectedKeysDrawBuffer = new List(); - private List m_SelectedKeysDrawBuffer = new List(); - private List m_DragDropKeysDrawBuffer = new List(); - - // Control point mesh renderers. - private ControlPointRenderer m_UnselectedKeysRenderer; - private ControlPointRenderer m_SelectedKeysRenderer; - private ControlPointRenderer m_DragDropKeysRenderer; - - private Texture2D m_DefaultDopeKeyIcon; - - public void FlushCache() - { - m_UnselectedKeysRenderer.FlushCache(); - m_SelectedKeysRenderer.FlushCache(); - m_DragDropKeysRenderer.FlushCache(); - } - - private void DrawElements(List elements) - { - if (elements.Count == 0) - return; - - Color oldColor = GUI.color; - - Color color = Color.white; - GUI.color = color; - Texture icon = m_DefaultDopeKeyIcon; - - for (int i = 0; i < elements.Count; ++i) - { - DrawElement element = elements[i]; - - // Change color - if (element.color != color) - { - color = GUI.enabled ? element.color : element.color * 0.8f; - GUI.color = color; - } - - // Element with specific texture (sprite). - if (element.texture != null) - { - GUI.Label(element.position, element.texture, GUIStyle.none); - } - // Ordinary control point. - else - { - Rect rect = new Rect((element.position.center.x - icon.width / 2), - (element.position.center.y - icon.height / 2), - icon.width, - icon.height); - GUI.Label(rect, icon, GUIStyle.none); - } - } - - GUI.color = oldColor; - } - - public DopeSheetControlPointRenderer() - { - m_DefaultDopeKeyIcon = EditorGUIUtility.LoadIcon("blendKey"); - - m_UnselectedKeysRenderer = new ControlPointRenderer(m_DefaultDopeKeyIcon); - m_SelectedKeysRenderer = new ControlPointRenderer(m_DefaultDopeKeyIcon); - m_DragDropKeysRenderer = new ControlPointRenderer(m_DefaultDopeKeyIcon); - } - - public void Clear() - { - m_UnselectedKeysDrawBuffer.Clear(); - m_SelectedKeysDrawBuffer.Clear(); - m_DragDropKeysDrawBuffer.Clear(); - - m_UnselectedKeysRenderer.Clear(); - m_SelectedKeysRenderer.Clear(); - m_DragDropKeysRenderer.Clear(); - } - - public void Render() - { - DrawElements(m_UnselectedKeysDrawBuffer); - m_UnselectedKeysRenderer.Render(); - - DrawElements(m_SelectedKeysDrawBuffer); - m_SelectedKeysRenderer.Render(); - - DrawElements(m_DragDropKeysDrawBuffer); - m_DragDropKeysRenderer.Render(); - } - - public void AddUnselectedKey(DrawElement element) - { - // Control point has a specific texture (sprite image). - // This will not be batched rendered and must be handled separately. - if (element.texture != null) - { - m_UnselectedKeysDrawBuffer.Add(element); - } - else - { - Rect rect = element.position; - rect.size = new Vector2(m_DefaultDopeKeyIcon.width, m_DefaultDopeKeyIcon.height); - m_UnselectedKeysRenderer.AddPoint(rect, element.color); - } - } - - public void AddSelectedKey(DrawElement element) - { - // Control point has a specific texture (sprite image). - // This will not be batched rendered and must be handled separately. - if (element.texture != null) - { - m_SelectedKeysDrawBuffer.Add(element); - } - else - { - Rect rect = element.position; - rect.size = new Vector2(m_DefaultDopeKeyIcon.width, m_DefaultDopeKeyIcon.height); - m_SelectedKeysRenderer.AddPoint(rect, element.color); - } - } - - public void AddDragDropKey(DrawElement element) - { - // Control point has a specific texture (sprite image). - // This will not be batched rendered and must be handled separately. - if (element.texture != null) - { - m_DragDropKeysDrawBuffer.Add(element); - } - else - { - Rect rect = element.position; - rect.size = new Vector2(m_DefaultDopeKeyIcon.width, m_DefaultDopeKeyIcon.height); - m_DragDropKeysRenderer.AddPoint(rect, element.color); - } - } - } - - public float contentHeight - { - get - { - float height = 0f; - - foreach (DopeLine dopeline in state.dopelines) - height += dopeline.tallMode ? AnimationWindowHierarchyGUI.k_DopeSheetRowHeightTall : AnimationWindowHierarchyGUI.k_DopeSheetRowHeight; - - height += AnimationWindowHierarchyGUI.k_AddCurveButtonNodeHeight; - return height; - } - } - - [SerializeField] public EditorWindow m_Owner; - - DopeSheetSelectionRect m_SelectionRect; - - float m_DragStartTime; - bool m_MousedownOnKeyframe; - bool m_IsDragging; - bool m_IsDraggingPlayheadStarted; - bool m_IsDraggingPlayhead; - - bool m_Initialized; - - bool m_SpritePreviewLoading; - int m_SpritePreviewCacheSize; - - public Bounds m_Bounds = new Bounds(Vector3.zero, Vector3.zero); - public override Bounds drawingBounds { get { return m_Bounds; } } - - public bool isDragging { get { return m_IsDragging; } } - - DopeSheetControlPointRenderer m_PointRenderer; - - DopeSheetEditorRectangleTool m_RectangleTool; - - internal int assetPreviewManagerID - { - get { return m_Owner != null ? m_Owner.GetInstanceID() : 0; } - } - - public bool spritePreviewLoading { get { return m_SpritePreviewLoading; } } - - public DopeSheetEditor(EditorWindow owner) : base(false) - { - m_Owner = owner; - } - - public void OnDisable() - { - if (m_PointRenderer != null) - m_PointRenderer.FlushCache(); - } - - internal void OnDestroy() - { - AssetPreview.DeletePreviewTextureManagerByID(assetPreviewManagerID); - } - - public void OnGUI(Rect position, Vector2 scrollPosition) - { - Init(); - - // drag'n'drops outside any dopelines - HandleDragAndDropToEmptyArea(); - - GUIClip.Push(position, scrollPosition, Vector2.zero, false); - - HandleRectangleToolEvents(); - - Rect localRect = new Rect(0, 0, position.width, position.height); - Rect dopesheetRect = DopelinesGUI(localRect, scrollPosition); - - HandleKeyboard(); - HandleDragging(); - HandleSelectionRect(dopesheetRect); - HandleDelete(); - - RectangleToolGUI(); - - GUIClip.Pop(); - } - - public void Init() - { - if (!m_Initialized) - { - // Set TimeArea constrains - hSlider = true; - vSlider = false; - hRangeLocked = false; - vRangeLocked = true; - hRangeMin = 0; - margin = 40; - scaleWithWindow = true; - ignoreScrollWheelUntilClicked = false; - } - m_Initialized = true; - - if (m_PointRenderer == null) - m_PointRenderer = new DopeSheetControlPointRenderer(); - - if (m_RectangleTool == null) - { - m_RectangleTool = new DopeSheetEditorRectangleTool(); - m_RectangleTool.Initialize(this); - } - } - - public void RecalculateBounds() - { - if (!state.disabled) - { - Vector2 timeRange = state.timeRange; - m_Bounds.SetMinMax(new Vector3(timeRange.x, 0, 0), new Vector3(timeRange.y, 0, 0)); - } - } - - private Rect DopelinesGUI(Rect position, Vector2 scrollPosition) - { - Color oldColor = GUI.color; - Rect linePosition = position; - - m_PointRenderer.Clear(); - - if (Event.current.type == EventType.Repaint) - m_SpritePreviewLoading = false; - - // Workaround for cases when mouseup happens outside the window. Apparently the mouseup event is lost (not true on OSX, though). - if (Event.current.type == EventType.MouseDown) - m_IsDragging = false; - - // Find out how large preview pool is needed for sprite previews - UpdateSpritePreviewCacheSize(); - - List dopelines = state.dopelines; - for (int i = 0; i < dopelines.Count; ++i) - { - DopeLine dopeLine = dopelines[i]; - - dopeLine.position = linePosition; - dopeLine.position.height = (dopeLine.tallMode ? AnimationWindowHierarchyGUI.k_DopeSheetRowHeightTall : AnimationWindowHierarchyGUI.k_DopeSheetRowHeight); - - // Cull out dopelines that are not visible - if (dopeLine.position.yMin + scrollPosition.y >= position.yMin && dopeLine.position.yMin + scrollPosition.y <= position.yMax || - dopeLine.position.yMax + scrollPosition.y >= position.yMin && dopeLine.position.yMax + scrollPosition.y <= position.yMax) - { - Event evt = Event.current; - - switch (evt.type) - { - case EventType.DragUpdated: - case EventType.DragPerform: - { - HandleDragAndDrop(dopeLine); - break; - } - case EventType.ContextClick: - { - if (!m_IsDraggingPlayhead) - { - HandleContextMenu(dopeLine); - } - - break; - } - case EventType.MouseDown: - { - if (evt.button == 0) - { - HandleMouseDown(dopeLine); - } - break; - } - case EventType.Repaint: - { - DopeLineRepaint(dopeLine); - break; - } - } - } - - linePosition.y += dopeLine.position.height; - } - - if (Event.current.type == EventType.MouseUp) - { - m_IsDraggingPlayheadStarted = false; - m_IsDraggingPlayhead = false; - } - - Rect dopelinesRect = new Rect(position.xMin, position.yMin, position.width, linePosition.yMax - position.yMin); - - m_PointRenderer.Render(); - - GUI.color = oldColor; - - return dopelinesRect; - } - - private void RectangleToolGUI() - { - m_RectangleTool.OnGUI(); - } - - private void DrawGrid(Rect position) - { - TimeRuler(position, state.frameRate, false, true, 0.2f); - } - - public void DrawMasterDopelineBackground(Rect position) - { - if (Event.current.type != EventType.Repaint) - return; - - AnimationWindowStyles.eventBackground.Draw(position, false, false, false, false); - } - - void UpdateSpritePreviewCacheSize() - { - int newPreviewCacheSize = 1; - - // Add all expanded sprite dopelines - foreach (DopeLine dopeLine in state.dopelines) - { - if (dopeLine.tallMode && dopeLine.isPptrDopeline) - { - newPreviewCacheSize += dopeLine.keys.Count; - } - } - - // Add all drag'n'drop objects - newPreviewCacheSize += DragAndDrop.objectReferences.Length; - - if (newPreviewCacheSize > m_SpritePreviewCacheSize) - { - AssetPreview.SetPreviewTextureCacheSize(newPreviewCacheSize, assetPreviewManagerID); - m_SpritePreviewCacheSize = newPreviewCacheSize; - } - } - - private void DopeLineRepaint(DopeLine dopeline) - { - Color oldColor = GUI.color; - - AnimationWindowHierarchyNode node = (AnimationWindowHierarchyNode)state.hierarchyData.FindItem(dopeline.hierarchyNodeID); - bool isChild = node != null && node.depth > 0; - Color color = isChild ? Color.gray.AlphaMultiplied(0.05f) : Color.gray.AlphaMultiplied(0.16f); - - // Draw background - if (dopeline.isMasterDopeline) - DrawMasterDopelineBackground(dopeline.position); - else - DrawBox(dopeline.position, color); - - // Draw keys - int? previousTimeHash = null; - int length = dopeline.keys.Count; - - for (int i = 0; i < length; i++) - { - AnimationWindowKeyframe keyframe = dopeline.keys[i]; - // Hash optimizations - if (previousTimeHash == keyframe.m_TimeHash) - continue; - - previousTimeHash = keyframe.m_TimeHash; - - // Default values - Rect rect = GetKeyframeRect(dopeline, keyframe); - color = dopeline.isMasterDopeline ? Color.gray.RGBMultiplied(0.85f) : Color.gray.RGBMultiplied(1.2f); - Texture2D texture = null; - - if (keyframe.isPPtrCurve && dopeline.tallMode) - texture = keyframe.value == null ? null : AssetPreview.GetAssetPreview(((Object)keyframe.value).GetInstanceID(), assetPreviewManagerID); - - if (texture != null) - { - rect = GetPreviewRectFromKeyFrameRect(rect); - color = Color.white.AlphaMultiplied(0.5f); - } - else if (keyframe.value != null && keyframe.isPPtrCurve && dopeline.tallMode) - { - m_SpritePreviewLoading = true; - } - - // TODO: Find out why zero time, and only zero time, is offset from grid - if (Mathf.Approximately(keyframe.time, 0f)) - rect.xMin -= 0.01f; - - if (AnyKeyIsSelectedAtTime(dopeline, i)) - { - color = dopeline.tallMode && dopeline.isPptrDopeline ? Color.white : new Color(0.34f, 0.52f, 0.85f, 1f); - if (dopeline.isMasterDopeline) - color = color.RGBMultiplied(0.85f); - - m_PointRenderer.AddSelectedKey(new DrawElement(rect, color, texture)); - } - else - { - m_PointRenderer.AddUnselectedKey(new DrawElement(rect, color, texture)); - } - } - - if (DoDragAndDrop(dopeline, dopeline.position, false)) - { - float time = Mathf.Max(state.PixelToTime(Event.current.mousePosition.x, AnimationWindowState.SnapMode.SnapToClipFrame), 0f); - - Color keyColor = Color.gray.RGBMultiplied(1.2f); - Texture2D texture = null; - - foreach (Object obj in GetSortedDragAndDropObjectReferences()) - { - Rect rect = GetDragAndDropRect(dopeline, time); - - if (dopeline.isPptrDopeline && dopeline.tallMode) - texture = AssetPreview.GetAssetPreview(obj.GetInstanceID(), assetPreviewManagerID); - - if (texture != null) - { - rect = GetPreviewRectFromKeyFrameRect(rect); - keyColor = Color.white.AlphaMultiplied(0.5f); - } - - m_PointRenderer.AddDragDropKey(new DrawElement(rect, keyColor, texture)); - - time += 1f / state.frameRate; - } - } - - GUI.color = oldColor; - } - - private Rect GetPreviewRectFromKeyFrameRect(Rect keyframeRect) - { - keyframeRect.width -= 2; - keyframeRect.height -= 2; - keyframeRect.xMin += 2; - keyframeRect.yMin += 2; - - return keyframeRect; - } - - private Rect GetDragAndDropRect(DopeLine dopeline, float time) - { - Rect rect = GetKeyframeRect(dopeline, null); - float offsetX = GetKeyframeOffset(dopeline, null); - rect.center = new Vector2(state.TimeToPixel(time) + rect.width * .5f + offsetX, rect.center.y); - return rect; - } - - // TODO: This is just temporary until real styles - private static void DrawBox(Rect position, Color color) - { - Color oldColor = GUI.color; - GUI.color = color; - DopeLine.dopekeyStyle.Draw(position, GUIContent.none, 0, false); - GUI.color = oldColor; - } - - private GenericMenu GenerateMenu(DopeLine dopeline) - { - GenericMenu menu = new GenericMenu(); - - // Collect hovering keys. - List hoveringKeys = new List(); - foreach (var key in dopeline.keys) - { - Rect rect = GetKeyframeRect(dopeline, key); - - if (rect.Contains(Event.current.mousePosition)) - hoveringKeys.Add(key); - } - - AnimationKeyTime mouseKeyTime = AnimationKeyTime.Time(state.PixelToTime(Event.current.mousePosition.x, AnimationWindowState.SnapMode.SnapToClipFrame), state.frameRate); - - string str = "Add Key"; - if (dopeline.isEditable && hoveringKeys.Count == 0) - menu.AddItem(new GUIContent(str), false, AddKeyToDopeline, new AddKeyToDopelineContext {dopeline = dopeline, time = mouseKeyTime}); - else - menu.AddDisabledItem(new GUIContent(str)); - - str = state.selectedKeys.Count > 1 ? "Delete Keys" : "Delete Key"; - if (dopeline.isEditable && (state.selectedKeys.Count > 0 || hoveringKeys.Count > 0)) - menu.AddItem(new GUIContent(str), false, DeleteKeys, state.selectedKeys.Count > 0 ? state.selectedKeys : hoveringKeys); - else - menu.AddDisabledItem(new GUIContent(str)); - - // Float curve tangents - if (dopeline.isEditable && AnimationWindowUtility.ContainsFloatKeyframes(state.selectedKeys)) - { - menu.AddSeparator(string.Empty); - - List keyList = new List(); - Hashtable editorCurves = new Hashtable(); - foreach (AnimationWindowKeyframe key in state.selectedKeys) - { - if (key.isDiscreteCurve) - continue; - - int index = key.curve.GetKeyframeIndex(AnimationKeyTime.Time(key.time, state.frameRate)); - if (index == -1) - continue; - - int id = key.curve.GetHashCode(); - - AnimationCurve curve = (AnimationCurve)editorCurves[id]; - if (curve == null) - { - curve = AnimationUtility.GetEditorCurve(key.curve.clip, key.curve.binding); - if (curve == null) - curve = new AnimationCurve(); - - editorCurves.Add(id, curve); - } - - keyList.Add(new KeyIdentifier(curve, id, index, key.curve.binding)); - } - - CurveMenuManager menuManager = new CurveMenuManager(this); - menuManager.AddTangentMenuItems(menu, keyList); - } - - return menu; - } - - private void HandleDragging() - { - int id = EditorGUIUtility.GetControlID("dopesheetdrag".GetHashCode(), FocusType.Passive, new Rect()); - EventType eventType = Event.current.GetTypeForControl(id); - - if ((eventType == EventType.MouseDrag || eventType == EventType.MouseUp) && m_MousedownOnKeyframe) - { - if (eventType == EventType.MouseDrag && !EditorGUI.actionKey && !Event.current.shift) - { - if (!m_IsDragging && state.selectedKeys.Count > 0) - { - m_IsDragging = true; - m_IsDraggingPlayheadStarted = true; - GUIUtility.hotControl = id; - m_DragStartTime = state.PixelToTime(Event.current.mousePosition.x); - m_RectangleTool.OnStartMove(new Vector2(m_DragStartTime, 0f), m_RectangleTool.rippleTimeClutch); - Event.current.Use(); - } - } - - // 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. - float firstSelectedKeyTime = float.MaxValue; - foreach (AnimationWindowKeyframe selectedKey in state.selectedKeys) - firstSelectedKeyTime = Mathf.Min(selectedKey.time, firstSelectedKeyTime); - - float currentTime = state.SnapToFrame(state.PixelToTime(Event.current.mousePosition.x), AnimationWindowState.SnapMode.SnapToClipFrame); - - if (m_IsDragging) - { - if (!Mathf.Approximately(currentTime, m_DragStartTime)) - { - m_RectangleTool.OnMove(new Vector2(currentTime, 0f)); - Event.current.Use(); - } - } - - if (eventType == EventType.MouseUp) - { - if (m_IsDragging && GUIUtility.hotControl == id) - { - m_RectangleTool.OnEndMove(); - Event.current.Use(); - m_IsDragging = false; - } - m_MousedownOnKeyframe = false; - GUIUtility.hotControl = 0; - } - } - - if (m_IsDraggingPlayheadStarted && eventType == EventType.MouseDrag && Event.current.button == 1) - { - m_IsDraggingPlayhead = true; - - //int frame = state.m_Frame; - //if (!m_IsDragging) - // frame = state.TimeToFrameFloor(state.SnapToFrame (state.PixelToTime (Event.current.mousePosition.x))); - - //state.animationWindow.PreviewFrame (frame); - Event.current.Use(); - } - - if (m_IsDragging) - { - Vector2 mousePosition = Event.current.mousePosition; - Rect mouseRect = new Rect(mousePosition.x - 10, mousePosition.y - 10, 20, 20); - - EditorGUIUtility.AddCursorRect(mouseRect, MouseCursor.MoveArrow); - } - } - - private void HandleKeyboard() - { - if (Event.current.type == EventType.ValidateCommand || Event.current.type == EventType.ExecuteCommand) - { - switch (Event.current.commandName) - { - case EventCommandNames.SelectAll: - if (Event.current.type == EventType.ExecuteCommand) - HandleSelectAll(); - Event.current.Use(); - break; - case EventCommandNames.FrameSelected: - if (Event.current.type == EventType.ExecuteCommand) - FrameSelected(); - Event.current.Use(); - break; - } - } - - // Frame All. - // Manually handle hotkey unless we decide to add it to default Unity hotkeys like - // we did for FrameSelected. - if (Event.current.type == EventType.KeyDown) - { - if (Event.current.keyCode == KeyCode.A) - { - FrameClip(); - Event.current.Use(); - } - } - } - - private void HandleSelectAll() - { - foreach (DopeLine dopeline in state.dopelines) - { - foreach (AnimationWindowKeyframe keyframe in dopeline.keys) - { - state.SelectKey(keyframe); - } - state.SelectHierarchyItem(dopeline, true, false); - } - } - - private void HandleDelete() - { - if (state.selectedKeys.Count == 0) - return; - - switch (Event.current.type) - { - case EventType.ValidateCommand: - case EventType.ExecuteCommand: - if ((Event.current.commandName == EventCommandNames.SoftDelete || Event.current.commandName == EventCommandNames.Delete)) - { - if (Event.current.type == EventType.ExecuteCommand) - state.DeleteSelectedKeys(); - Event.current.Use(); - } - break; - - case EventType.KeyDown: - if (Event.current.keyCode == KeyCode.Backspace || Event.current.keyCode == KeyCode.Delete) - { - state.DeleteSelectedKeys(); - Event.current.Use(); - } - break; - } - } - - private void HandleSelectionRect(Rect rect) - { - if (m_SelectionRect == null) - m_SelectionRect = new DopeSheetSelectionRect(this); - - if (!m_MousedownOnKeyframe) - m_SelectionRect.OnGUI(rect); - } - - // Handles drag and drop into empty area outside dopelines - private void HandleDragAndDropToEmptyArea() - { - Event evt = Event.current; - - if (evt.type != EventType.DragPerform && evt.type != EventType.DragUpdated) - return; - - if (!ValidateDragAndDropObjects()) - return; - - // TODO: handle multidropping of other types than sprites/textures - if (DragAndDrop.objectReferences[0].GetType() == typeof(Sprite) || DragAndDrop.objectReferences[0].GetType() == typeof(Texture2D)) - { - if (state.selection.clipIsEditable && state.selection.canAddCurves) - { - if (!DopelineForValueTypeExists(typeof(Sprite))) - { - if (evt.type == EventType.DragPerform) - { - EditorCurveBinding? spriteBinding = CreateNewPptrDopeline(state.selection, typeof(Sprite)); - if (spriteBinding != null) - { - DoSpriteDropAfterGeneratingNewDopeline(state.activeAnimationClip, spriteBinding); - } - } - - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - evt.Use(); - return; - } - } - } - DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; - } - - private void DoSpriteDropAfterGeneratingNewDopeline(AnimationClip animationClip, EditorCurveBinding? spriteBinding) - { - if (DragAndDrop.objectReferences.Length == 1) - { - UsabilityAnalytics.Event("Sprite Drag and Drop", "Drop single sprite into empty dopesheet", "null", 1); - } - else - { - UsabilityAnalytics.Event("Sprite Drag and Drop", "Drop multiple sprites into empty dopesheet", "null", 1); - } - - // Create the new curve for our sprites - AnimationWindowCurve newCurve = new AnimationWindowCurve(animationClip, (EditorCurveBinding)spriteBinding, typeof(Sprite)); - - // And finally perform the drop onto the curve - PerformDragAndDrop(newCurve, 0f); - } - - private void HandleRectangleToolEvents() - { - m_RectangleTool.HandleEvents(); - } - - private bool DopelineForValueTypeExists(Type valueType) - { - return state.allCurves.Exists(curve => curve.valueType == valueType); - } - - private EditorCurveBinding? CreateNewPptrDopeline(AnimationWindowSelectionItem selectedItem, Type valueType) - { - List potentialBindings = null; - if (selectedItem.rootGameObject != null) - { - potentialBindings = AnimationWindowUtility.GetAnimatableProperties(selectedItem.rootGameObject, selectedItem.rootGameObject, valueType); - if (potentialBindings.Count == 0 && valueType == typeof(Sprite)) // No animatable properties for Sprite available. Default as SpriteRenderer. - { - return CreateNewSpriteRendererDopeline(selectedItem.rootGameObject, selectedItem.rootGameObject); - } - } - else if (selectedItem.scriptableObject != null) - { - potentialBindings = AnimationWindowUtility.GetAnimatableProperties(selectedItem.scriptableObject, valueType); - } - - if (potentialBindings == null || potentialBindings.Count == 0) - return null; - - if (potentialBindings.Count == 1) // Single property for this valuetype, return it - { - return potentialBindings[0]; - } - else // Multiple properties, dropdown selection - { - List menuItems = new List(); - foreach (EditorCurveBinding binding in potentialBindings) - menuItems.Add(binding.type.Name); - - List userDataList = new List(); - userDataList.Add(selectedItem.animationClip); - userDataList.Add(potentialBindings); - - Rect r = new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 1, 1); - EditorUtility.DisplayCustomMenu(r, EditorGUIUtility.TempContent(menuItems.ToArray()), -1, SelectTypeForCreatingNewPptrDopeline, userDataList); - return null; // We return null, but creation is handled via dropdown callback code - } - } - - private void SelectTypeForCreatingNewPptrDopeline(object userData, string[] options, int selected) - { - List userDataList = userData as List; - AnimationClip animationClip = userDataList[0] as AnimationClip; - List bindings = userDataList[1] as List; - - if (bindings.Count > selected) - DoSpriteDropAfterGeneratingNewDopeline(animationClip, bindings[selected]); - } - - private EditorCurveBinding? CreateNewSpriteRendererDopeline(GameObject targetGameObject, GameObject rootGameObject) - { - // Let's make sure there is spriterenderer to animate - if (!targetGameObject.GetComponent()) - targetGameObject.AddComponent(); - - // Now we should always find an animatable binding for it - List curveBindings = AnimationWindowUtility.GetAnimatableProperties(targetGameObject, rootGameObject, typeof(SpriteRenderer), typeof(Sprite)); - if (curveBindings.Count == 1) - return curveBindings[0]; - - // Something went wrong - Debug.LogError("Unable to create animatable SpriteRenderer component"); - return null; - } - - private void HandleDragAndDrop(DopeLine dopeline) - { - Event evt = Event.current; - - if (evt.type != EventType.DragPerform && evt.type != EventType.DragUpdated) - return; - - if (DoDragAndDrop(dopeline, dopeline.position, evt.type == EventType.DragPerform)) - { - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - evt.Use(); - } - else - { - DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; - } - } - - private void HandleMouseDown(DopeLine dopeline) - { - Event evt = Event.current; - if (!dopeline.position.Contains(evt.mousePosition)) - return; - - bool keysAreSelected = false; - foreach (AnimationWindowKeyframe keyframe in dopeline.keys) - { - Rect r = GetKeyframeRect(dopeline, keyframe); - if (r.Contains(evt.mousePosition) && state.KeyIsSelected(keyframe)) - { - keysAreSelected = true; - break; - } - } - - // For ctrl selecting, we unselect keys if we clicked a selected key frame. - bool canUnselectKeys = (keysAreSelected && EditorGUI.actionKey); - - // Only allow new selected keys if current clicked key frame is unselected. - bool canSelectKeys = !keysAreSelected; - - // If there are no selected keyframe in click without shift or EditorGUI.actionKey, then clear all other selections - if (!keysAreSelected && !EditorGUI.actionKey && !evt.shift) - state.ClearSelections(); - - float startTime = state.PixelToTime(Event.current.mousePosition.x); - float endTime = startTime; - - // For shift selecting we need to have time range we choose between - if (Event.current.shift) - { - foreach (AnimationWindowKeyframe key in dopeline.keys) - { - if (state.KeyIsSelected(key)) - { - if (key.time < startTime) - startTime = key.time; - if (key.time > endTime) - endTime = key.time; - } - } - } - - bool clickedOnKeyframe = false; - foreach (AnimationWindowKeyframe keyframe in dopeline.keys) - { - Rect r = GetKeyframeRect(dopeline, keyframe); - if (r.Contains(evt.mousePosition)) - { - clickedOnKeyframe = true; - - if (canUnselectKeys) - { - if (state.KeyIsSelected(keyframe)) - { - state.UnselectKey(keyframe); - - if (!state.AnyKeyIsSelected(dopeline)) - state.UnSelectHierarchyItem(dopeline); - } - } - else if (canSelectKeys) - { - if (!state.KeyIsSelected(keyframe)) - { - if (Event.current.shift) - { - foreach (AnimationWindowKeyframe key in dopeline.keys) - if (key == keyframe || key.time > startTime && key.time < endTime) - state.SelectKey(key); - } - else - { - state.SelectKey(keyframe); - } - - if (!dopeline.isMasterDopeline) - state.SelectHierarchyItem(dopeline, EditorGUI.actionKey || evt.shift); - } - } - - state.activeKeyframe = keyframe; - m_MousedownOnKeyframe = true; - evt.Use(); - } - } - - if (dopeline.isMasterDopeline) - { - state.ClearHierarchySelection(); - - List hierarchyIDs = state.GetAffectedHierarchyIDs(state.selectedKeys); - foreach (int id in hierarchyIDs) - state.SelectHierarchyItem(id, true, true); - } - - if (evt.clickCount == 2 && evt.button == 0 && !Event.current.shift && !EditorGUI.actionKey) - HandleDopelineDoubleclick(dopeline); - - // Move playhead when clicked with right mouse button - if (evt.button == 1 && !state.controlInterface.playing) - { - // Clear keyframe selection if right clicked empty space - if (!clickedOnKeyframe) - { - state.ClearSelections(); - m_IsDraggingPlayheadStarted = true; - HandleUtility.Repaint(); - evt.Use(); - } - } - } - - private void HandleDopelineDoubleclick(DopeLine dopeline) - { - float timeAtMousePosition = state.PixelToTime(Event.current.mousePosition.x, AnimationWindowState.SnapMode.SnapToClipFrame); - AnimationKeyTime mouseKeyTime = AnimationKeyTime.Time(timeAtMousePosition, state.frameRate); - AnimationWindowUtility.AddKeyframes(state, dopeline.curves.ToArray(), mouseKeyTime); - - Event.current.Use(); - } - - private void HandleContextMenu(DopeLine dopeline) - { - if (!dopeline.position.Contains(Event.current.mousePosition)) - return; - - // Actual context menu - GenerateMenu(dopeline).ShowAsContext(); - } - - private Rect GetKeyframeRect(DopeLine dopeline, AnimationWindowKeyframe keyframe) - { - float time = keyframe != null ? keyframe.time : 0f; - - float width = 10f; - if (dopeline.isPptrDopeline && dopeline.tallMode && (keyframe == null || keyframe.value != null)) - width = dopeline.position.height; - - return new Rect(state.TimeToPixel(state.SnapToFrame(time, AnimationWindowState.SnapMode.SnapToClipFrame)) + GetKeyframeOffset(dopeline, keyframe), dopeline.position.yMin, width, dopeline.position.height); - } - - // This means "how much is the rendered keyframe offset in pixels for x-axis". - // 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 - // However for pptr keyframes, the time is represented by left edge - private float GetKeyframeOffset(DopeLine dopeline, AnimationWindowKeyframe keyframe) - { - if (dopeline.isPptrDopeline && dopeline.tallMode && (keyframe == null || keyframe.value != null)) - return k_PptrKeyframeOffset; - else - return k_KeyframeOffset; - } - - // Frame the selected keyframes or selected dopelines - public void FrameClip() - { - if (state.disabled) - return; - - Vector2 timeRange = state.timeRange; - timeRange.y = Mathf.Max(timeRange.x + 0.1f, timeRange.y); - SetShownHRangeInsideMargins(timeRange.x, timeRange.y); - } - - public void FrameSelected() - { - Bounds frameBounds = new Bounds(); - bool firstKey = true; - - bool keyframesSelected = state.selectedKeys.Count > 0; - - if (keyframesSelected) - { - foreach (AnimationWindowKeyframe key in state.selectedKeys) - { - Vector2 pt = new Vector2(key.time, 0.0f); - if (firstKey) - { - frameBounds.SetMinMax(pt, pt); - firstKey = false; - } - else - { - frameBounds.Encapsulate(pt); - } - } - } - - // No keyframes selected. Frame to selected dopelines - bool frameToClip = !keyframesSelected; - if (!keyframesSelected) - { - bool dopelinesSelected = state.hierarchyState.selectedIDs.Count > 0; - if (dopelinesSelected) - { - foreach (AnimationWindowCurve curve in state.activeCurves) - { - int keyCount = curve.m_Keyframes.Count; - - if (keyCount > 1) - { - Vector2 pt1 = new Vector2(curve.m_Keyframes[0].time, 0.0f); - Vector2 pt2 = new Vector2(curve.m_Keyframes[keyCount - 1].time, 0.0f); - - if (firstKey) - { - frameBounds.SetMinMax(pt1, pt2); - firstKey = false; - } - else - { - frameBounds.Encapsulate(pt1); - frameBounds.Encapsulate(pt2); - } - - frameToClip = false; - } - } - } - } - - - if (frameToClip) - FrameClip(); - else - { - // Let's make sure we don't zoom too close. - frameBounds.size = new Vector3(Mathf.Max(frameBounds.size.x, 0.1f), Mathf.Max(frameBounds.size.y, 0.1f), 0); - SetShownHRangeInsideMargins(frameBounds.min.x, frameBounds.max.x); - } - } - - private bool DoDragAndDrop(DopeLine dopeLine, Rect position, bool perform) - { - if (position.Contains(Event.current.mousePosition) == false) - return false; - - if (!ValidateDragAndDropObjects()) - return false; - - System.Type targetType = DragAndDrop.objectReferences[0].GetType(); - AnimationWindowCurve curve = null; - if (dopeLine.valueType == targetType) - { - curve = dopeLine.curves[0]; - } - else - { - // dopeline ValueType wasn't exact match. We can still look for a curve that accepts our drop object type - foreach (AnimationWindowCurve dopelineCurve in dopeLine.curves) - { - if (dopelineCurve.isPPtrCurve) - { - if (dopelineCurve.valueType == targetType) - curve = dopelineCurve; - - List sprites = SpriteUtility.GetSpriteFromPathsOrObjects(DragAndDrop.objectReferences, DragAndDrop.paths, Event.current.type); - if (dopelineCurve.valueType == typeof(Sprite) && sprites.Count > 0) - { - curve = dopelineCurve; - targetType = typeof(Sprite); - } - } - } - } - - if (curve == null) - return false; - - if (!curve.clipIsEditable) - return false; - - if (perform) - { - if (DragAndDrop.objectReferences.Length == 1) - UsabilityAnalytics.Event("Sprite Drag and Drop", "Drop single sprite into existing dopeline", "null", 1); - else - UsabilityAnalytics.Event("Sprite Drag and Drop", "Drop multiple sprites into existing dopeline", "null", 1); - - float time = Mathf.Max(state.PixelToTime(Event.current.mousePosition.x, AnimationWindowState.SnapMode.SnapToClipFrame), 0f); - AnimationWindowCurve targetCurve = GetCurveOfType(dopeLine, targetType); - PerformDragAndDrop(targetCurve, time); - } - - return true; - } - - private void PerformDragAndDrop(AnimationWindowCurve targetCurve, float time) - { - if (DragAndDrop.objectReferences.Length == 0 || targetCurve == null) - return; - - string undoLabel = "Drop Key"; - state.SaveKeySelection(undoLabel); - - state.ClearSelections(); - Object[] objectReferences = GetSortedDragAndDropObjectReferences(); - - foreach (var obj in objectReferences) - { - Object value = obj; - - if (value is Texture2D) - value = SpriteUtility.TextureToSprite(obj as Texture2D); - - CreateNewPPtrKeyframe(time, value, targetCurve); - time += 1f / targetCurve.clip.frameRate; - } - - state.SaveCurve(targetCurve, undoLabel); - DragAndDrop.AcceptDrag(); - } - - private Object[] GetSortedDragAndDropObjectReferences() - { - Object[] objectReferences = DragAndDrop.objectReferences; - - // Use same name compare as when we sort in the backend: See AssetDatabase.cpp: SortChildren - System.Array.Sort(objectReferences, (a, b) => EditorUtility.NaturalCompare(a.name, b.name)); - - return objectReferences; - } - - private void CreateNewPPtrKeyframe(float time, Object value, AnimationWindowCurve targetCurve) - { - ObjectReferenceKeyframe referenceKeyframe = new ObjectReferenceKeyframe(); - - referenceKeyframe.time = time; - referenceKeyframe.value = value; - - AnimationWindowKeyframe keyframe = new AnimationWindowKeyframe(targetCurve, referenceKeyframe); - AnimationKeyTime newTime = AnimationKeyTime.Time(keyframe.time, state.frameRate); - targetCurve.AddKeyframe(keyframe, newTime); - state.SelectKey(keyframe); - } - - // if targetType == null, it means that all types are fine (as long as they are all of the same type) - private static bool ValidateDragAndDropObjects() - { - if (DragAndDrop.objectReferences.Length == 0) - return false; - - // 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) - for (int i = 0; i < DragAndDrop.objectReferences.Length; i++) - { - Object obj = DragAndDrop.objectReferences[i]; - if (obj == null) - { - return false; - } - - if (i < DragAndDrop.objectReferences.Length - 1) - { - Object nextObj = DragAndDrop.objectReferences[i + 1]; - bool bothAreSpritesOrTextures = (obj is Texture2D || obj is Sprite) && (nextObj is Texture2D || nextObj is Sprite); - - if (obj.GetType() != nextObj.GetType() && !bothAreSpritesOrTextures) - { - return false; - } - } - } - return true; - } - - private AnimationWindowCurve GetCurveOfType(DopeLine dopeLine, System.Type type) - { - foreach (AnimationWindowCurve curve in dopeLine.curves) - { - if (curve.valueType == type) - return curve; - } - return null; - } - - // For optimizing. Starting from keyIndex, we check through any key with same time and see if any are selected - private bool AnyKeyIsSelectedAtTime(DopeLine dopeLine, int keyIndex) - { - AnimationWindowKeyframe keyframe = dopeLine.keys[keyIndex]; - int firstTimeHash = keyframe.m_TimeHash; - - int length = dopeLine.keys.Count; - for (int i = keyIndex; i < length; i++) - { - keyframe = dopeLine.keys[i]; - int timeHash = keyframe.m_TimeHash; - - if (timeHash != firstTimeHash) - return false; - - if (state.KeyIsSelected(keyframe)) - return true; - } - - return false; - } - - private struct AddKeyToDopelineContext - { - public DopeLine dopeline; - public AnimationKeyTime time; - } - - private void AddKeyToDopeline(object obj) { AddKeyToDopeline((AddKeyToDopelineContext)obj); } - private void AddKeyToDopeline(AddKeyToDopelineContext context) - { - AnimationWindowUtility.AddKeyframes(state, context.dopeline.curves.ToArray(), context.time); - } - - private void DeleteKeys(object obj) { DeleteKeys((List)obj); } - private void DeleteKeys(List keys) - { - state.DeleteKeys(keys); - } - - internal class DopeSheetSelectionRect - { - Vector2 m_SelectStartPoint; - Vector2 m_SelectMousePoint; - bool m_ValidRect; - private DopeSheetEditor owner; - - enum SelectionType { Normal, Additive, Subtractive } - public readonly GUIStyle createRect = "U2D.createRect"; - - static int s_RectSelectionID = GUIUtility.GetPermanentControlID(); - - public DopeSheetSelectionRect(DopeSheetEditor owner) - { - this.owner = owner; - } - - public void OnGUI(Rect position) - { - Event evt = Event.current; - Vector2 mousePos = evt.mousePosition; - int id = s_RectSelectionID; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (evt.button == 0 && position.Contains(mousePos)) - { - GUIUtility.hotControl = id; - m_SelectStartPoint = mousePos; - m_ValidRect = false; - evt.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - m_ValidRect = Mathf.Abs((mousePos - m_SelectStartPoint).x) > 1f; - - if (m_ValidRect) - m_SelectMousePoint = new Vector2(mousePos.x, mousePos.y); - - evt.Use(); - } - break; - - case EventType.Repaint: - if (GUIUtility.hotControl == id && m_ValidRect) - EditorStyles.selectionRect.Draw(GetCurrentPixelRect(), GUIContent.none, false, false, false, false); - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == id && evt.button == 0) - { - if (m_ValidRect) - { - if (!evt.shift && !EditorGUI.actionKey) - owner.state.ClearSelections(); - - float frameRate = owner.state.frameRate; - - Rect timeRect = GetCurrentTimeRect(); - GUI.changed = true; - - owner.state.ClearHierarchySelection(); - - List toBeUnselected = new List(); - List toBeSelected = new List(); - - foreach (DopeLine dopeline in owner.state.dopelines) - { - if (dopeline.position.yMin >= timeRect.yMin && dopeline.position.yMax <= timeRect.yMax) - { - foreach (AnimationWindowKeyframe keyframe in dopeline.keys) - { - AnimationKeyTime startTime = AnimationKeyTime.Time(timeRect.xMin, frameRate); - AnimationKeyTime endTime = AnimationKeyTime.Time(timeRect.xMax, frameRate); - - AnimationKeyTime keyTime = AnimationKeyTime.Time(keyframe.time, frameRate); - // for dopeline tallmode, we don't want to select the sprite at the end. It just feels wrong. - if (!dopeline.tallMode && keyTime.frame >= startTime.frame && keyTime.frame <= endTime.frame || - dopeline.tallMode && keyTime.frame >= startTime.frame && keyTime.frame < endTime.frame) - { - if (!toBeSelected.Contains(keyframe) && !toBeUnselected.Contains(keyframe)) - { - if (!owner.state.KeyIsSelected(keyframe)) - toBeSelected.Add(keyframe); - else if (owner.state.KeyIsSelected(keyframe)) - toBeUnselected.Add(keyframe); - } - } - } - } - } - - // Only if all the keys inside rect are selected, we want to unselect them. - if (toBeSelected.Count == 0) - foreach (AnimationWindowKeyframe keyframe in toBeUnselected) - owner.state.UnselectKey(keyframe); - - foreach (AnimationWindowKeyframe keyframe in toBeSelected) - owner.state.SelectKey(keyframe); - - // Update hierarchy selection based on newly selected keys - foreach (DopeLine dopeline in owner.state.dopelines) - if (owner.state.AnyKeyIsSelected(dopeline)) - owner.state.SelectHierarchyItem(dopeline, true, false); - } - else - { - owner.state.ClearSelections(); - } - evt.Use(); - GUIUtility.hotControl = 0; - } - break; - } - } - - public Rect GetCurrentPixelRect() - { - float height = AnimationWindowHierarchyGUI.k_DopeSheetRowHeight; - Rect r = AnimationWindowUtility.FromToRect(m_SelectStartPoint, m_SelectMousePoint); - r.xMin = owner.state.TimeToPixel(owner.state.PixelToTime(r.xMin, AnimationWindowState.SnapMode.SnapToClipFrame), AnimationWindowState.SnapMode.SnapToClipFrame); - r.xMax = owner.state.TimeToPixel(owner.state.PixelToTime(r.xMax, AnimationWindowState.SnapMode.SnapToClipFrame), AnimationWindowState.SnapMode.SnapToClipFrame); - r.yMin = Mathf.Floor(r.yMin / height) * height; - r.yMax = (Mathf.Floor(r.yMax / height) + 1) * height; - return r; - } - - public Rect GetCurrentTimeRect() - { - float height = AnimationWindowHierarchyGUI.k_DopeSheetRowHeight; - Rect r = AnimationWindowUtility.FromToRect(m_SelectStartPoint, m_SelectMousePoint); - r.xMin = owner.state.PixelToTime(r.xMin, AnimationWindowState.SnapMode.SnapToClipFrame); - r.xMax = owner.state.PixelToTime(r.xMax, AnimationWindowState.SnapMode.SnapToClipFrame); - r.yMin = Mathf.Floor(r.yMin / height) * height; - r.yMax = (Mathf.Floor(r.yMax / height) + 1) * height; - return r; - } - } - - public void UpdateCurves(List changedCurves, string undoText) - { - Undo.RegisterCompleteObjectUndo(state.activeAnimationClip, undoText); - foreach (ChangedCurve changedCurve in changedCurves) - { - AnimationWindowCurve curve = state.allCurves.Find(c => changedCurve.curveId == c.GetHashCode()); - if (curve != null) - { - AnimationUtility.SetEditorCurve(curve.clip, changedCurve.binding, changedCurve.curve); - } - else - { - Debug.LogError("Could not match ChangedCurve data to destination curves."); - } - } - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/DopeSheetEditorRectangleTool.cs b/Editor/Mono/Animation/AnimationWindow/DopeSheetEditorRectangleTool.cs deleted file mode 100644 index 401c1e77b6..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/DopeSheetEditorRectangleTool.cs +++ /dev/null @@ -1,364 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - internal class DopeSheetEditorRectangleTool : RectangleTool - { - const float kDefaultFrameRate = 60f; - - const int kScaleLeftWidth = 17; - const int kScaleLeftMarginHorizontal = 0; - const float kScaleLeftMarginVertical = 4; - - const int kScaleRightWidth = 17; - const int kScaleRightMarginHorizontal = 0; - const float kScaleRightMarginVertical = 4; - - const int kHLabelMarginHorizontal = 8; - const int kHLabelMarginVertical = 1; - - static Rect g_EmptyRect = new Rect(0f, 0f, 0f, 0f); - - struct ToolLayout - { - public Rect summaryRect; - public Rect selectionRect; - - public Rect scaleLeftRect; - public Rect scaleRightRect; - - public Vector2 leftLabelAnchor; - public Vector2 rightLabelAnchor; - } - - private DopeSheetEditor m_DopeSheetEditor; - private AnimationWindowState m_State; - - private ToolLayout m_Layout; - - private Vector2 m_Pivot; - private Vector2 m_Previous; - private Vector2 m_MouseOffset; - - private bool m_IsDragging; - private bool m_RippleTime; - private float m_RippleTimeStart; - private float m_RippleTimeEnd; - - private AreaManipulator[] m_SelectionBoxes; - - private AreaManipulator m_SelectionScaleLeft; - private AreaManipulator m_SelectionScaleRight; - - private bool hasSelection { get { return (m_State.selectedKeys.Count > 0); } } - private Bounds selectionBounds { get { return m_State.selectionBounds; } } - private float frameRate { get { return m_State.frameRate; } } - - private bool isDragging { get { return m_IsDragging || m_DopeSheetEditor.isDragging; } } - - public override void Initialize(TimeArea timeArea) - { - base.Initialize(timeArea); - m_DopeSheetEditor = timeArea as DopeSheetEditor; - m_State = m_DopeSheetEditor.state; - - if (m_SelectionBoxes == null) - { - m_SelectionBoxes = new AreaManipulator[2]; - - for (int i = 0; i < 2; ++i) - { - m_SelectionBoxes[i] = new AreaManipulator(styles.rectangleToolSelection, MouseCursor.MoveArrow); - - m_SelectionBoxes[i].onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - bool curveEditorOverride = evt.shift || EditorGUI.actionKey; - if (!curveEditorOverride && hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartMove(new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0.0f), rippleTimeClutch); - return true; - } - - return false; - }; - m_SelectionBoxes[i].onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnMove(new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0.0f)); - return true; - }; - m_SelectionBoxes[i].onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndMove(); - return true; - }; - } - } - - if (m_SelectionScaleLeft == null) - { - m_SelectionScaleLeft = new AreaManipulator(styles.dopesheetScaleLeft, MouseCursor.ResizeHorizontal); - - m_SelectionScaleLeft.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartScale(ToolCoord.Right, ToolCoord.Left, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), rippleTimeClutch); - return true; - } - - return false; - }; - m_SelectionScaleLeft.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate)); - return true; - }; - m_SelectionScaleLeft.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndScale(); - return true; - }; - } - - if (m_SelectionScaleRight == null) - { - m_SelectionScaleRight = new AreaManipulator(styles.dopesheetScaleRight, MouseCursor.ResizeHorizontal); - - m_SelectionScaleRight.onStartDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - if (hasSelection && manipulator.rect.Contains(evt.mousePosition)) - { - OnStartScale(ToolCoord.Left, ToolCoord.Right, new Vector2(PixelToTime(evt.mousePosition.x, frameRate), 0f), rippleTimeClutch); - return true; - } - - return false; - }; - m_SelectionScaleRight.onDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnScaleTime(PixelToTime(evt.mousePosition.x, frameRate)); - return true; - }; - m_SelectionScaleRight.onEndDrag += (AnimationWindowManipulator manipulator, Event evt) => - { - OnEndScale(); - return true; - }; - } - } - - public void OnGUI() - { - if (!hasSelection) - return; - - if (Event.current.type != EventType.Repaint) - return; - - m_Layout = CalculateLayout(); - - m_SelectionBoxes[0].OnGUI(m_Layout.summaryRect); - m_SelectionBoxes[1].OnGUI(m_Layout.selectionRect); - - m_SelectionScaleLeft.OnGUI(m_Layout.scaleLeftRect); - m_SelectionScaleRight.OnGUI(m_Layout.scaleRightRect); - - DrawLabels(); - } - - public void HandleEvents() - { - HandleClutchKeys(); - - m_SelectionScaleLeft.HandleEvents(); - m_SelectionScaleRight.HandleEvents(); - - m_SelectionBoxes[0].HandleEvents(); - m_SelectionBoxes[1].HandleEvents(); - } - - private ToolLayout CalculateLayout() - { - ToolLayout layout = new ToolLayout(); - - Bounds bounds = selectionBounds; - - bool canScaleX = !Mathf.Approximately(bounds.size.x, 0f); - - float xMin = TimeToPixel(bounds.min.x); - float xMax = TimeToPixel(bounds.max.x); - - float yMin = 0f, yMax = 0f; - bool firstKey = true; - - float heightCumul = 0f; - - List dopelines = m_State.dopelines; - for (int i = 0; i < dopelines.Count; ++i) - { - DopeLine dopeline = dopelines[i]; - - float dopelineHeight = (dopeline.tallMode ? AnimationWindowHierarchyGUI.k_DopeSheetRowHeightTall : AnimationWindowHierarchyGUI.k_DopeSheetRowHeight); - - if (!dopeline.isMasterDopeline) - { - int length = dopeline.keys.Count; - for (int j = 0; j < length; j++) - { - AnimationWindowKeyframe keyframe = dopeline.keys[j]; - if (m_State.KeyIsSelected(keyframe)) - { - if (firstKey) - { - yMin = heightCumul; - firstKey = false; - } - - yMax = heightCumul + dopelineHeight; - break; - } - } - } - - heightCumul += dopelineHeight; - } - - layout.summaryRect = new Rect(xMin, 0f, xMax - xMin, AnimationWindowHierarchyGUI.k_DopeSheetRowHeight); - layout.selectionRect = new Rect(xMin, yMin, xMax - xMin, yMax - yMin); - - // Scale handles. - if (canScaleX) - { - layout.scaleLeftRect = new Rect(layout.selectionRect.xMin - kScaleLeftMarginHorizontal - kScaleLeftWidth, layout.selectionRect.yMin + kScaleLeftMarginVertical, kScaleLeftWidth, layout.selectionRect.height - kScaleLeftMarginVertical * 2); - layout.scaleRightRect = new Rect(layout.selectionRect.xMax + kScaleRightMarginHorizontal, layout.selectionRect.yMin + kScaleRightMarginVertical, kScaleRightWidth, layout.selectionRect.height - kScaleRightMarginVertical * 2); - } - else - { - layout.scaleLeftRect = g_EmptyRect; - layout.scaleRightRect = g_EmptyRect; - } - - if (canScaleX) - { - layout.leftLabelAnchor = new Vector2(layout.summaryRect.xMin - kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical); - layout.rightLabelAnchor = new Vector2(layout.summaryRect.xMax + kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical); - } - else - { - layout.leftLabelAnchor = layout.rightLabelAnchor = new Vector2(layout.summaryRect.center.x + kHLabelMarginHorizontal, contentRect.yMin + kHLabelMarginVertical); - } - - return layout; - } - - private void DrawLabels() - { - if (isDragging == false) - return; - - bool canScaleX = !Mathf.Approximately(selectionBounds.size.x, 0f); - - if (canScaleX) - { - GUIContent leftLabelContent = new GUIContent(string.Format("{0}", m_DopeSheetEditor.FormatTime(selectionBounds.min.x, m_State.frameRate, m_State.timeFormat))); - GUIContent rightLabelContent = new GUIContent(string.Format("{0}", m_DopeSheetEditor.FormatTime(selectionBounds.max.x, m_State.frameRate, m_State.timeFormat))); - - Vector2 leftLabelSize = styles.dragLabel.CalcSize(leftLabelContent); - Vector2 rightLabelSize = styles.dragLabel.CalcSize(rightLabelContent); - - EditorGUI.DoDropShadowLabel(new Rect(m_Layout.leftLabelAnchor.x - leftLabelSize.x, m_Layout.leftLabelAnchor.y, leftLabelSize.x, leftLabelSize.y), leftLabelContent, styles.dragLabel, 0.3f); - EditorGUI.DoDropShadowLabel(new Rect(m_Layout.rightLabelAnchor.x, m_Layout.rightLabelAnchor.y, rightLabelSize.x, rightLabelSize.y), rightLabelContent, styles.dragLabel, 0.3f); - } - else - { - GUIContent labelContent = new GUIContent(string.Format("{0}", m_DopeSheetEditor.FormatTime(selectionBounds.center.x, m_State.frameRate, m_State.timeFormat))); - Vector2 labelSize = styles.dragLabel.CalcSize(labelContent); - - EditorGUI.DoDropShadowLabel(new Rect(m_Layout.leftLabelAnchor.x, m_Layout.leftLabelAnchor.y, labelSize.x, labelSize.y), labelContent, styles.dragLabel, 0.3f); - } - } - - private void OnStartScale(ToolCoord pivotCoord, ToolCoord pickedCoord, Vector2 mousePos, bool rippleTime) - { - Bounds bounds = selectionBounds; - - m_IsDragging = true; - m_Pivot = ToolCoordToPosition(pivotCoord, bounds); - m_Previous = ToolCoordToPosition(pickedCoord, bounds); - m_MouseOffset = mousePos - m_Previous; - m_RippleTime = rippleTime; - m_RippleTimeStart = bounds.min.x; - m_RippleTimeEnd = bounds.max.x; - - m_State.StartLiveEdit(); - } - - private void OnScaleTime(float time) - { - Matrix4x4 transform; - bool flipX; - if (CalculateScaleTimeMatrix(m_Previous.x, time, m_MouseOffset.x, m_Pivot.x, frameRate, out transform, out flipX)) - TransformKeys(transform, flipX, false); - } - - private void OnScaleValue(float val) - { - Matrix4x4 transform; - bool flipY; - if (CalculateScaleValueMatrix(m_Previous.y, val, m_MouseOffset.y, m_Pivot.y, out transform, out flipY)) - TransformKeys(transform, false, flipY); - } - - private void OnEndScale() - { - m_State.EndLiveEdit(); - m_IsDragging = false; - } - - internal void OnStartMove(Vector2 position, bool rippleTime) - { - Bounds bounds = selectionBounds; - - m_IsDragging = true; - m_Previous = position; - m_RippleTime = rippleTime; - m_RippleTimeStart = bounds.min.x; - m_RippleTimeEnd = bounds.max.x; - - m_State.StartLiveEdit(); - } - - internal void OnMove(Vector2 position) - { - Vector2 dv = position - m_Previous; - - Matrix4x4 transform = Matrix4x4.identity; - transform.SetTRS(new Vector3(dv.x, dv.y, 0f), Quaternion.identity, Vector3.one); - - TransformKeys(transform, false, false); - } - - internal void OnEndMove() - { - m_State.EndLiveEdit(); - m_IsDragging = false; - } - - private void TransformKeys(Matrix4x4 matrix, bool flipX, bool flipY) - { - if (m_RippleTime) - m_State.TransformRippleKeys(matrix, m_RippleTimeStart, m_RippleTimeEnd, flipX, true); - else - m_State.TransformSelectedKeys(matrix, flipX, flipY, true); - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/GameObjectSelectionItem.cs b/Editor/Mono/Animation/AnimationWindow/GameObjectSelectionItem.cs deleted file mode 100644 index f1d1aa5e68..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/GameObjectSelectionItem.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; - -namespace UnityEditorInternal -{ - internal class GameObjectSelectionItem : AnimationWindowSelectionItem - { - public static GameObjectSelectionItem Create(GameObject gameObject) - { - GameObjectSelectionItem selectionItem = CreateInstance(typeof(GameObjectSelectionItem)) as GameObjectSelectionItem; - - selectionItem.gameObject = gameObject; - selectionItem.animationClip = null; - selectionItem.id = 0; // no need for id since there's only one item in selection. - - if (selectionItem.rootGameObject != null) - { - AnimationClip[] allClips = AnimationUtility.GetAnimationClips(selectionItem.rootGameObject); - - if (selectionItem.animationClip == null && selectionItem.gameObject != null) // there is activeGO but clip is still null - selectionItem.animationClip = allClips.Length > 0 ? allClips[0] : null; - else if (!Array.Exists(allClips, x => x == selectionItem.animationClip)) // clip doesn't belong to the currently active GO - selectionItem.animationClip = allClips.Length > 0 ? allClips[0] : null; - } - - return selectionItem; - } - - public override AnimationClip animationClip - { - set - { - base.animationClip = value; - } - get - { - if (animationPlayer == null) - return null; - - return base.animationClip; - } - } - - public override void Synchronize() - { - if (rootGameObject != null) - { - AnimationClip[] allClips = AnimationUtility.GetAnimationClips(rootGameObject); - if (allClips.Length > 0) - { - if (!Array.Exists(allClips, x => x == animationClip)) - { - animationClip = allClips[0]; - } - } - else - { - animationClip = null; - } - } - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/IAnimationContextualResponder.cs b/Editor/Mono/Animation/AnimationWindow/IAnimationContextualResponder.cs deleted file mode 100644 index 9070b0ecf8..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/IAnimationContextualResponder.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - // Required information for animation recording. - internal interface IAnimationContextualResponder - { - bool IsAnimatable(PropertyModification[] modifications); - bool IsEditable(Object targetObject); - - bool KeyExists(PropertyModification[] modifications); - bool CandidateExists(PropertyModification[] modifications); - - bool CurveExists(PropertyModification[] modifications); - - bool HasAnyCandidates(); - bool HasAnyCurves(); - - void AddKey(PropertyModification[] modifications); - void RemoveKey(PropertyModification[] modifications); - - void RemoveCurve(PropertyModification[] modifications); - - void AddCandidateKeys(); - void AddAnimatedKeys(); - - void GoToNextKeyframe(PropertyModification[] modifications); - void GoToPreviousKeyframe(PropertyModification[] modifications); - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/IAnimationRecordingState.cs b/Editor/Mono/Animation/AnimationWindow/IAnimationRecordingState.cs deleted file mode 100644 index 8458aab6dd..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/IAnimationRecordingState.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using UnityEditor; - -namespace UnityEditorInternal -{ - // Required information for animation recording. - internal interface IAnimationRecordingState - { - GameObject activeGameObject { get; } - GameObject activeRootGameObject { get; } - AnimationClip activeAnimationClip { get; } - int currentFrame { get; } - - bool addZeroFrame { get; } - - bool DiscardModification(PropertyModification modification); - void SaveCurve(AnimationWindowCurve curve); - void AddPropertyModification(EditorCurveBinding binding, PropertyModification propertyModification, bool keepPrefabOverride); - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowControl.cs b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowControl.cs deleted file mode 100644 index 356bc4fb30..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowControl.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal abstract class IAnimationWindowControl : ScriptableObject - { - public virtual void OnEnable() { hideFlags = HideFlags.HideAndDontSave; } - public abstract void OnSelectionChanged(); - - public abstract AnimationKeyTime time { get; } - - public abstract void GoToTime(float time); - public abstract void GoToFrame(int frame); - - public abstract void StartScrubTime(); - public abstract void ScrubTime(float time); - public abstract void EndScrubTime(); - - public abstract void GoToPreviousFrame(); - public abstract void GoToNextFrame(); - public abstract void GoToPreviousKeyframe(); - public abstract void GoToNextKeyframe(); - public abstract void GoToFirstKeyframe(); - public abstract void GoToLastKeyframe(); - - public abstract bool canPlay { get; } - public abstract bool playing { get; } - - public abstract bool StartPlayback(); - public abstract void StopPlayback(); - public abstract bool PlaybackUpdate(); - - public abstract bool canPreview { get; } - public abstract bool previewing { get; } - - public abstract bool StartPreview(); - public abstract void StopPreview(); - - public abstract bool canRecord { get; } - public abstract bool recording { get; } - - public abstract bool StartRecording(Object targetObject); - public abstract void StopRecording(); - public abstract void ResampleAnimation(); - - public abstract void ProcessCandidates(); - public abstract void ClearCandidates(); - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/RectangleTool.cs b/Editor/Mono/Animation/AnimationWindow/RectangleTool.cs deleted file mode 100644 index fe380d9205..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/RectangleTool.cs +++ /dev/null @@ -1,251 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - internal class RectangleTool - { - private TimeArea m_TimeArea; - private Styles m_Styles; - private bool m_RippleTimeClutch; - - internal enum ToolCoord - { - BottomLeft, - Bottom, - BottomRight, - - Left, - Center, - Right, - - TopLeft, - Top, - TopRight - } - - internal class Styles - { - public GUIStyle rectangleToolHBarLeft = "RectangleToolHBarLeft"; - public GUIStyle rectangleToolHBarRight = "RectangleToolHBarRight"; - public GUIStyle rectangleToolHBar = "RectangleToolHBar"; - - public GUIStyle rectangleToolVBarBottom = "RectangleToolVBarBottom"; - public GUIStyle rectangleToolVBarTop = "RectangleToolVBarTop"; - public GUIStyle rectangleToolVBar = "RectangleToolVBar"; - - public GUIStyle rectangleToolSelection = "RectangleToolSelection"; - public GUIStyle rectangleToolHighlight = "RectangleToolHighlight"; - - public GUIStyle rectangleToolScaleLeft = "RectangleToolScaleLeft"; - public GUIStyle rectangleToolScaleRight = "RectangleToolScaleRight"; - public GUIStyle rectangleToolScaleBottom = "RectangleToolScaleBottom"; - public GUIStyle rectangleToolScaleTop = "RectangleToolScaleTop"; - - public GUIStyle dopesheetScaleLeft = "DopesheetScaleLeft"; - public GUIStyle dopesheetScaleRight = "DopesheetScaleRight"; - - public GUIStyle dragLabel = "ProfilerBadge"; - } - - public TimeArea timeArea { get { return m_TimeArea; } } - - public Styles styles { get { return m_Styles; } } - - public bool rippleTimeClutch { get { return m_RippleTimeClutch; } } - - public Rect contentRect - { - get - { - return new Rect(0, 0, m_TimeArea.drawRect.width, m_TimeArea.drawRect.height); - } - } - - public virtual void Initialize(TimeArea timeArea) - { - m_TimeArea = timeArea; - - if (m_Styles == null) - m_Styles = new Styles(); - } - - public Vector2 ToolCoordToPosition(ToolCoord coord, Bounds bounds) - { - switch (coord) - { - case ToolCoord.BottomLeft: - return bounds.min; - case ToolCoord.Bottom: - return new Vector2(bounds.center.x, bounds.min.y); - case ToolCoord.BottomRight: - return new Vector2(bounds.max.x, bounds.min.y); - - case ToolCoord.Left: - return new Vector2(bounds.min.x, bounds.center.y); - case ToolCoord.Center: - return bounds.center; - case ToolCoord.Right: - return new Vector2(bounds.max.x, bounds.center.y); - - case ToolCoord.TopLeft: - return new Vector2(bounds.min.x, bounds.max.y); - case ToolCoord.Top: - return new Vector2(bounds.center.x, bounds.max.y); - case ToolCoord.TopRight: - return bounds.max; - } - - return Vector2.zero; - } - - public bool CalculateScaleTimeMatrix(float fromTime, float toTime, float offsetTime, float pivotTime, float frameRate, out Matrix4x4 transform, out bool flipKeys) - { - transform = Matrix4x4.identity; - flipKeys = false; - - float thresholdTime = (Mathf.Approximately(frameRate, 0f)) ? 0.001f : 1f / frameRate; - - float dtNum = toTime - pivotTime; - float dtDenum = fromTime - pivotTime; - - // Scale handle overlaps pivot, discard operation. - if ((Mathf.Abs(dtNum) - offsetTime) < 0f) - return false; - - dtNum = (Mathf.Sign(dtNum) == Mathf.Sign(dtDenum)) ? dtNum - offsetTime : dtNum + offsetTime; - - if (Mathf.Approximately(dtDenum, 0f)) - { - transform.SetTRS(new Vector3(dtNum, 0f, 0f), Quaternion.identity, Vector3.one); - flipKeys = false; - - return true; - } - - if (Mathf.Abs(dtNum) < thresholdTime) - dtNum = (dtNum < 0f) ? -thresholdTime : thresholdTime; - - float scaleTime = dtNum / dtDenum; - - transform.SetTRS(new Vector3(pivotTime, 0f, 0f), Quaternion.identity, Vector3.one); - transform = transform * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(scaleTime, 1f, 1f)); - transform = transform * Matrix4x4.TRS(new Vector3(-pivotTime, 0f), Quaternion.identity, Vector3.one); - - flipKeys = scaleTime < 0f; - - return true; - } - - public bool CalculateScaleValueMatrix(float fromValue, float toValue, float offsetValue, float pivotValue, out Matrix4x4 transform, out bool flipKeys) - { - transform = Matrix4x4.identity; - flipKeys = false; - - float thresholdValue = 0.001f; - - float dvNum = toValue - pivotValue; - float dvDenum = fromValue - pivotValue; - - // Scale handle overlaps pivot, discard operation. - if ((Mathf.Abs(dvNum) - offsetValue) < 0f) - return false; - - dvNum = (Mathf.Sign(dvNum) == Mathf.Sign(dvDenum)) ? dvNum - offsetValue : dvNum + offsetValue; - - if (Mathf.Approximately(dvDenum, 0f)) - { - transform.SetTRS(new Vector3(0f, dvNum, 0f), Quaternion.identity, Vector3.one); - flipKeys = false; - - return true; - } - - if (Mathf.Abs(dvNum) < thresholdValue) - dvNum = (dvNum < 0f) ? -thresholdValue : thresholdValue; - - float scaleValue = dvNum / dvDenum; - - transform.SetTRS(new Vector3(0f, pivotValue, 0f), Quaternion.identity, Vector3.one); - transform = transform * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1f, scaleValue, 1f)); - transform = transform * Matrix4x4.TRS(new Vector3(0f, -pivotValue, 0f), Quaternion.identity, Vector3.one); - - flipKeys = scaleValue < 0f; - - return true; - } - - public float PixelToTime(float pixelTime, float frameRate) - { - float width = contentRect.width; - float visibleTimeSpan = m_TimeArea.shownArea.xMax - m_TimeArea.shownArea.xMin; - float minVisibleTime = m_TimeArea.shownArea.xMin; - - float time = ((pixelTime / width) * visibleTimeSpan + minVisibleTime); - if (frameRate != 0f) - time = Mathf.Round(time * frameRate) / frameRate; - - return time; - } - - public float PixelToValue(float pixelValue) - { - float height = contentRect.height; - - float pixelPerValue = m_TimeArea.m_Scale.y * -1f; - float zeroValuePixel = m_TimeArea.shownArea.yMin * pixelPerValue * -1f; - - float value = (height - pixelValue - zeroValuePixel) / pixelPerValue; - - return value; - } - - public float TimeToPixel(float time) - { - float width = contentRect.width; - float visibleTimeSpan = m_TimeArea.shownArea.xMax - m_TimeArea.shownArea.xMin; - float minVisibleTime = m_TimeArea.shownArea.xMin; - - float pixelTime = (time - minVisibleTime) * width / visibleTimeSpan; - - return pixelTime; - } - - public float ValueToPixel(float value) - { - float height = contentRect.height; - - float pixelPerValue = m_TimeArea.m_Scale.y * -1f; - float zeroValuePixel = m_TimeArea.shownArea.yMin * pixelPerValue * -1f; - - float pixelValue = height - (value * pixelPerValue + zeroValuePixel); - - return pixelValue; - } - - public void HandleClutchKeys() - { - Event evt = Event.current; - switch (evt.type) - { - case EventType.KeyDown: - if (evt.keyCode == KeyCode.R) - { - m_RippleTimeClutch = true; - } - break; - - case EventType.KeyUp: - if (evt.keyCode == KeyCode.R) - { - m_RippleTimeClutch = false; - } - break; - } - } - } -} diff --git a/Editor/Mono/Animation/AnimationWindow/RotationCurveInterpolation.cs b/Editor/Mono/Animation/AnimationWindow/RotationCurveInterpolation.cs deleted file mode 100644 index 6405421094..0000000000 --- a/Editor/Mono/Animation/AnimationWindow/RotationCurveInterpolation.cs +++ /dev/null @@ -1,286 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditorInternal; -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class RotationCurveInterpolation - { - public struct State - { - public bool allAreNonBaked; - public bool allAreBaked; - public bool allAreRaw; - public bool allAreRotations; - } - - public static char[] kPostFix = { 'x', 'y', 'z', 'w' }; - - public enum Mode { Baked, NonBaked, RawQuaternions, RawEuler, Undefined } - - public static Mode GetModeFromCurveData(EditorCurveBinding data) - { - if (AnimationWindowUtility.IsTransformType(data.type) && data.propertyName.StartsWith("localEulerAngles")) - { - if (data.propertyName.StartsWith("localEulerAnglesBaked")) - return Mode.Baked; - else if (data.propertyName.StartsWith("localEulerAnglesRaw")) - return Mode.RawEuler; - else - return Mode.NonBaked; - } - else if (AnimationWindowUtility.IsTransformType(data.type) && data.propertyName.StartsWith("m_LocalRotation")) - return Mode.RawQuaternions; - - return Mode.Undefined; - } - - // Extracts the interpolation state for the selection from the clip - public static State GetCurveState(AnimationClip clip, EditorCurveBinding[] selection) - { - State state; - state.allAreRaw = true; - state.allAreNonBaked = true; - state.allAreBaked = true; - state.allAreRotations = true; - - foreach (EditorCurveBinding data in selection) - { - Mode mode = GetModeFromCurveData(data); - state.allAreBaked &= (mode == Mode.Baked); - state.allAreNonBaked &= (mode == Mode.NonBaked); - state.allAreRaw &= mode == (Mode.RawEuler); - state.allAreRotations &= mode != (Mode.Undefined); - } - - return state; - } - - public static int GetCurveIndexFromName(string name) - { - return ExtractComponentCharacter(name) - 'x'; - } - - public static char ExtractComponentCharacter(string name) - { - return name[name.Length - 1]; - } - - public static string GetPrefixForInterpolation(Mode newInterpolationMode) - { - if (newInterpolationMode == Mode.Baked) - return "localEulerAnglesBaked"; - else if (newInterpolationMode == Mode.NonBaked) - return "localEulerAngles"; - else if (newInterpolationMode == Mode.RawEuler) - return "localEulerAnglesRaw"; - else if (newInterpolationMode == Mode.RawQuaternions) - return "m_LocalRotation"; - else - return null; - } - - internal static EditorCurveBinding[] ConvertRotationPropertiesToDefaultInterpolation(AnimationClip clip, EditorCurveBinding[] selection) - { - var mode = clip.legacy ? Mode.Baked : Mode.RawEuler; - return ConvertRotationPropertiesToInterpolationType(selection, mode); - } - - internal static EditorCurveBinding[] ConvertRotationPropertiesToInterpolationType(EditorCurveBinding[] selection, Mode newInterpolationMode) - { - if (selection.Length != 4) - return selection; - - if (GetModeFromCurveData(selection[0]) == Mode.RawQuaternions) - { - EditorCurveBinding[] newCurves = new EditorCurveBinding[3]; - newCurves[0] = selection[0]; - newCurves[1] = selection[1]; - newCurves[2] = selection[2]; - - string prefix = GetPrefixForInterpolation(newInterpolationMode); - newCurves[0].propertyName = prefix + ".x"; - newCurves[1].propertyName = prefix + ".y"; - newCurves[2].propertyName = prefix + ".z"; - - return newCurves; - } - else - return selection; - } - - static EditorCurveBinding[] GenerateTransformCurveBindingArray(string path, string property, Type type, int count) - { - EditorCurveBinding[] bindings = new EditorCurveBinding[count]; - for (int i = 0; i < count; i++) - bindings[i] = EditorCurveBinding.FloatCurve(path, type, property + kPostFix[i]); - return bindings; - } - - static public EditorCurveBinding[] RemapAnimationBindingForAddKey(EditorCurveBinding binding, AnimationClip clip) - { - if (!AnimationWindowUtility.IsTransformType(binding.type)) - { - return null; - } - else if (binding.propertyName.StartsWith("m_LocalPosition.")) - { - if (binding.type == typeof(Transform)) - return GenerateTransformCurveBindingArray(binding.path, "m_LocalPosition.", binding.type, 3); - else - return null; - } - else if (binding.propertyName.StartsWith("m_LocalScale.")) - return GenerateTransformCurveBindingArray(binding.path, "m_LocalScale.", binding.type, 3); - else if (binding.propertyName.StartsWith("m_LocalRotation")) - { - return SelectRotationBindingForAddKey(binding, clip); - } - else - return null; - } - - static public EditorCurveBinding[] RemapAnimationBindingForRotationAddKey(EditorCurveBinding binding, AnimationClip clip) - { - if (!AnimationWindowUtility.IsTransformType(binding.type)) - { - return null; - } - else if (binding.propertyName.StartsWith("m_LocalRotation")) - { - return SelectRotationBindingForAddKey(binding, clip); - } - else - return null; - } - - static private EditorCurveBinding[] SelectRotationBindingForAddKey(EditorCurveBinding binding, AnimationClip clip) - { - EditorCurveBinding testBinding = binding; - testBinding.propertyName = "localEulerAnglesBaked.x"; - if (AnimationUtility.GetEditorCurve(clip, testBinding) != null) - return GenerateTransformCurveBindingArray(binding.path, "localEulerAnglesBaked.", binding.type, 3); - else - { - testBinding.propertyName = "localEulerAngles.x"; - if (AnimationUtility.GetEditorCurve(clip, testBinding) != null) - { - return GenerateTransformCurveBindingArray(binding.path, "localEulerAngles.", binding.type, 3); - } - else - { - testBinding.propertyName = "localEulerAnglesRaw.x"; - if (clip.legacy && AnimationUtility.GetEditorCurve(clip, testBinding) == null) - return GenerateTransformCurveBindingArray(binding.path, "localEulerAnglesBaked.", binding.type, 3); - - return GenerateTransformCurveBindingArray(binding.path, "localEulerAnglesRaw.", binding.type, 3); - } - } - } - - static public EditorCurveBinding RemapAnimationBindingForRotationCurves(EditorCurveBinding curveBinding, AnimationClip clip) - { - if (!AnimationWindowUtility.IsTransformType(curveBinding.type)) - return curveBinding; - - // Convert rotation binding to valid editor curve binding. - // Only a single rotation binding (RawEuler, Baked or NonBaked) should be allowed in one clip. - // RawQuaternions should be converted to appropriate euler bindings if available. - Mode mode = GetModeFromCurveData(curveBinding); - if (mode != Mode.Undefined) - { - string suffix = curveBinding.propertyName.Split('.')[1]; - - EditorCurveBinding newBinding = curveBinding; - - if (mode != Mode.NonBaked) - { - newBinding.propertyName = GetPrefixForInterpolation(Mode.NonBaked) + "." + suffix; - AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, newBinding); - if (curve != null) - return newBinding; - } - - if (mode != Mode.Baked) - { - newBinding.propertyName = GetPrefixForInterpolation(Mode.Baked) + "." + suffix; - AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, newBinding); - if (curve != null) - return newBinding; - } - - if (mode != Mode.RawEuler) - { - newBinding.propertyName = GetPrefixForInterpolation(Mode.RawEuler) + "." + suffix; - AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, newBinding); - if (curve != null) - return newBinding; - } - - return curveBinding; - } - else - return curveBinding; - } - - internal static void SetInterpolation(AnimationClip clip, EditorCurveBinding[] curveBindings, Mode newInterpolationMode) - { - Undo.RegisterCompleteObjectUndo(clip, "Rotation Interpolation"); - - if (clip.legacy && newInterpolationMode == Mode.RawEuler) - { - 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); - } - List newCurvesBindings = new List(); - List newCurveDatas = new List(); - List oldCurvesBindings = new List(); - - foreach (EditorCurveBinding curveBinding in curveBindings) - { - Mode currentMode = GetModeFromCurveData(curveBinding); - - if (currentMode == Mode.Undefined) - continue; - - if (currentMode == Mode.RawQuaternions) - { - Debug.LogWarning("Can't convert quaternion curve: " + curveBinding.propertyName); - continue; - } - - AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, curveBinding); - - if (curve == null) - continue; - - string newPropertyPath = GetPrefixForInterpolation(newInterpolationMode) + '.' + ExtractComponentCharacter(curveBinding.propertyName); - - EditorCurveBinding newBinding = new EditorCurveBinding(); - newBinding.propertyName = newPropertyPath; - newBinding.type = curveBinding.type; - newBinding.path = curveBinding.path; - newCurvesBindings.Add(newBinding); - newCurveDatas.Add(curve); - - EditorCurveBinding removeCurve = new EditorCurveBinding(); - removeCurve.propertyName = curveBinding.propertyName; - removeCurve.type = curveBinding.type; - removeCurve.path = curveBinding.path; - oldCurvesBindings.Add(removeCurve); - } - - Undo.RegisterCompleteObjectUndo(clip, "Rotation Interpolation"); - - foreach (EditorCurveBinding binding in oldCurvesBindings) - AnimationUtility.SetEditorCurve(clip, binding, null); - - foreach (EditorCurveBinding binding in newCurvesBindings) - AnimationUtility.SetEditorCurve(clip, binding, newCurveDatas[newCurvesBindings.IndexOf(binding)]); - } - } -} diff --git a/Editor/Mono/Animation/AnimatorController.cs b/Editor/Mono/Animation/AnimatorController.cs deleted file mode 100644 index eb883602e1..0000000000 --- a/Editor/Mono/Animation/AnimatorController.cs +++ /dev/null @@ -1,289 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.IO; -using System.Collections.Generic; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; - -namespace UnityEditor.Animations -{ - [NativeClass(null)] - public sealed partial class AnimatorController : RuntimeAnimatorController - { - internal System.Action OnAnimatorControllerDirty; - - internal static AnimatorController lastActiveController = null; - internal static int lastActiveLayerIndex = 0; - private const string kControllerExtension = "controller"; - - internal PushUndoIfNeeded undoHandler = new PushUndoIfNeeded(true); - internal bool pushUndo { set { undoHandler.pushUndo = value; } } - - internal string GetDefaultBlendTreeParameter() - { - for (int i = 0; i < parameters.Length; i++) - { - if (parameters[i].type == AnimatorControllerParameterType.Float) - return parameters[i].name; - } - AddParameter("Blend", AnimatorControllerParameterType.Float); - return "Blend"; - } - - [RequiredByNativeCode] - internal static void OnInvalidateAnimatorController(AnimatorController controller) - { - if (controller.OnAnimatorControllerDirty != null) - controller.OnAnimatorControllerDirty(); - } - - internal AnimatorStateMachine FindEffectiveRootStateMachine(int layerIndex) - { - AnimatorControllerLayer currentLayer = layers[layerIndex]; - while (currentLayer.syncedLayerIndex != -1) - { - currentLayer = layers[currentLayer.syncedLayerIndex]; - } - return currentLayer.stateMachine; - } - - public void AddLayer(string name) - { - AnimatorControllerLayer newLayer = new AnimatorControllerLayer(); - newLayer.name = MakeUniqueLayerName(name); - newLayer.stateMachine = new AnimatorStateMachine(); - newLayer.stateMachine.name = newLayer.name; - newLayer.stateMachine.hideFlags = HideFlags.HideInHierarchy; - - if (AssetDatabase.GetAssetPath(this) != "") - AssetDatabase.AddObjectToAsset(newLayer.stateMachine, AssetDatabase.GetAssetPath(this)); - - AddLayer(newLayer); - } - - public void AddLayer(AnimatorControllerLayer layer) - { - undoHandler.DoUndo(this, "Layer added"); - - AnimatorControllerLayer[] layerVector = layers; - ArrayUtility.Add(ref layerVector, layer); - layers = layerVector; - } - - internal void RemoveLayers(List layerIndexes) - { - undoHandler.DoUndo(this, "Layers removed"); - - AnimatorControllerLayer[] layerVector = this.layers; - foreach (var layerIndex in layerIndexes) - { - RemoveLayerInternal(layerIndex, ref layerVector); - } - this.layers = layerVector; - } - - private void RemoveLayerInternal(int index, ref AnimatorControllerLayer[] layerVector) - { - if (layerVector[index].syncedLayerIndex == -1 && layerVector[index].stateMachine != null) - { - undoHandler.DoUndo(layerVector[index].stateMachine, "Layer removed"); - layerVector[index].stateMachine.Clear(); - if (MecanimUtilities.AreSameAsset(this, layerVector[index].stateMachine)) - Undo.DestroyObjectImmediate(layerVector[index].stateMachine); - } - - ArrayUtility.Remove(ref layerVector, layerVector[index]); - } - - public void RemoveLayer(int index) - { - undoHandler.DoUndo(this, "Layer removed"); - - AnimatorControllerLayer[] layerVector = layers; - RemoveLayerInternal(index, ref layerVector); - layers = layerVector; - } - - public void AddParameter(string name, AnimatorControllerParameterType type) - { - AnimatorControllerParameter newParameter = new AnimatorControllerParameter(); - newParameter.name = MakeUniqueParameterName(name); - newParameter.type = type; - - AddParameter(newParameter); - } - - public void AddParameter(AnimatorControllerParameter paramater) - { - undoHandler.DoUndo(this, "Parameter added"); - AnimatorControllerParameter[] parameterVector = parameters; - ArrayUtility.Add(ref parameterVector, paramater); - parameters = parameterVector; - } - - public void RemoveParameter(int index) - { - undoHandler.DoUndo(this, "Parameter removed"); - AnimatorControllerParameter[] parameterVector = parameters; - ArrayUtility.Remove(ref parameterVector, parameterVector[index]); - parameters = parameterVector; - } - - public void RemoveParameter(AnimatorControllerParameter parameter) - { - undoHandler.DoUndo(this, "Parameter removed"); - AnimatorControllerParameter[] parameterVector = parameters; - ArrayUtility.Remove(ref parameterVector, parameter); - parameters = parameterVector; - } - - [RequiredByNativeCode] - public AnimatorState AddMotion(Motion motion) - { - return AddMotion(motion, 0); - } - - public AnimatorState AddMotion(Motion motion, int layerIndex) - { - AnimatorState state = layers[layerIndex].stateMachine.AddState(motion.name); - state.motion = motion; - return state; - } - - public AnimatorState CreateBlendTreeInController(string name, out BlendTree tree) - { - return CreateBlendTreeInController(name, out tree, 0); - } - - public AnimatorState CreateBlendTreeInController(string name, out BlendTree tree, int layerIndex) - { - tree = new BlendTree(); - tree.name = name; - tree.blendParameter = tree.blendParameterY = GetDefaultBlendTreeParameter(); - - if (AssetDatabase.GetAssetPath(this) != "") - AssetDatabase.AddObjectToAsset(tree, AssetDatabase.GetAssetPath(this)); - - AnimatorState state = layers[layerIndex].stateMachine.AddState(tree.name); - state.motion = tree; - return state; - } - - public static AnimatorController CreateAnimatorControllerAtPath(string path) - { - AnimatorController controller = new AnimatorController(); - - controller.name = Path.GetFileName(path); - AssetDatabase.CreateAsset(controller, path); - - controller.pushUndo = false; - controller.AddLayer("Base Layer"); - controller.pushUndo = true; - - return controller; - } - - public static AnimationClip AllocateAnimatorClip(string name) - { - var clip = UnityEditorInternal.AnimationWindowUtility.AllocateAndSetupClip(true); - clip.name = name; - return clip; - } - - [RequiredByNativeCode] - internal static AnimatorController CreateAnimatorControllerForClip(AnimationClip clip, GameObject animatedObject) - { - string path = AssetDatabase.GetAssetPath(clip); - - if (string.IsNullOrEmpty(path)) - return null; - - path = Path.Combine(FileUtil.DeleteLastPathNameComponent(path), animatedObject.name + "." + kControllerExtension); - path = AssetDatabase.GenerateUniqueAssetPath(path); - - if (string.IsNullOrEmpty(path)) - return null; - - - return CreateAnimatorControllerAtPathWithClip(path, clip); - } - - public static AnimatorController CreateAnimatorControllerAtPathWithClip(string path, AnimationClip clip) - { - AnimatorController controller = CreateAnimatorControllerAtPath(path); - controller.AddMotion(clip); - return controller; - } - - public void SetStateEffectiveMotion(AnimatorState state, Motion motion) - { - SetStateEffectiveMotion(state, motion, 0); - } - - public void SetStateEffectiveMotion(AnimatorState state, Motion motion, int layerIndex) - { - if (layers[layerIndex].syncedLayerIndex == -1) - { - undoHandler.DoUndo(state, "Set Motion"); - state.motion = motion; - } - else - { - undoHandler.DoUndo(this, "Set Motion"); - AnimatorControllerLayer[] layerArray = layers; - layerArray[layerIndex].SetOverrideMotion(state, motion); - layers = layerArray; - } - } - - public Motion GetStateEffectiveMotion(AnimatorState state) - { - return GetStateEffectiveMotion(state, 0); - } - - public Motion GetStateEffectiveMotion(AnimatorState state, int layerIndex) - { - if (layers[layerIndex].syncedLayerIndex == -1) - { - return state.motion; - } - else - { - return layers[layerIndex].GetOverrideMotion(state); - } - } - - public void SetStateEffectiveBehaviours(AnimatorState state, int layerIndex, StateMachineBehaviour[] behaviours) - { - if (layers[layerIndex].syncedLayerIndex == -1) - { - undoHandler.DoUndo(state, "Set Behaviours"); - state.behaviours = behaviours; - } - else - { - undoHandler.DoUndo(this, "Set Behaviours"); - Internal_SetEffectiveBehaviours(state, layerIndex, behaviours); - } - } - - public StateMachineBehaviour[] GetStateEffectiveBehaviours(AnimatorState state, int layerIndex) - { - return Internal_GetEffectiveBehaviours(state, layerIndex) as StateMachineBehaviour[]; - } - - [System.Obsolete("parameterCount is obsolete. Use parameters.Length instead.", true)] - int parameterCount - { - get { return 0; } - } - - [System.Obsolete("layerCount is obsolete. Use layers.Length instead.", true)] - int layerCount - { - get { return 0; } - } - } -} diff --git a/Editor/Mono/Animation/BlendTree.cs b/Editor/Mono/Animation/BlendTree.cs deleted file mode 100644 index 70ba96bbf2..0000000000 --- a/Editor/Mono/Animation/BlendTree.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEditor; -using UnityEditor.Animations; -using System.Linq; - -namespace UnityEditor.Animations -{ - [ExcludeFromPreset] - public partial class BlendTree : Motion - { - public void AddChild(Motion motion) - { - AddChild(motion, Vector2.zero, 0); - } - - public void AddChild(Motion motion, Vector2 position) - { - AddChild(motion, position, 0); - } - - public void AddChild(Motion motion, float threshold) - { - AddChild(motion, Vector2.zero, threshold); - } - - public void RemoveChild(int index) - { - Undo.RecordObject(this, "Remove Child"); - ChildMotion[] childMotions = children; - ArrayUtility.RemoveAt(ref childMotions, index); - children = childMotions; - } - - internal void AddChild(Motion motion, Vector2 position, float threshold) - { - Undo.RecordObject(this, "Added BlendTree Child"); - ChildMotion[] childMotions = children; - ChildMotion newMotion = new ChildMotion(); - newMotion.timeScale = 1; - newMotion.motion = motion; - newMotion.position = position; - newMotion.threshold = threshold; - newMotion.directBlendParameter = "Blend"; - ArrayUtility.Add(ref childMotions, newMotion); - children = childMotions; - } - - public BlendTree CreateBlendTreeChild(float threshold) - { - return CreateBlendTreeChild(Vector2.zero, threshold); - } - - public BlendTree CreateBlendTreeChild(Vector2 position) - { - return CreateBlendTreeChild(position, 0); - } - - internal bool HasChild(BlendTree childTree, bool recursive) - { - foreach (ChildMotion child in children) - { - if (child.motion == childTree) - { - return true; - } - - if (recursive && child.motion is BlendTree && (child.motion as BlendTree).HasChild(childTree, true)) - { - return true; - } - } - - return false; - } - - internal BlendTree CreateBlendTreeChild(Vector2 position, float threshold) - { - Undo.RecordObject(this, "Created BlendTree Child"); - - BlendTree tree = new BlendTree(); - tree.name = "BlendTree"; - tree.hideFlags = HideFlags.HideInHierarchy; - if (AssetDatabase.GetAssetPath(this) != "") - AssetDatabase.AddObjectToAsset(tree, AssetDatabase.GetAssetPath(this)); - - AddChild(tree, position, threshold); - return tree; - } - } -} diff --git a/Editor/Mono/Animation/EditorCurveBinding.bindings.cs b/Editor/Mono/Animation/EditorCurveBinding.bindings.cs deleted file mode 100644 index c89b1f9ba1..0000000000 --- a/Editor/Mono/Animation/EditorCurveBinding.bindings.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEngine.Playables; -using UnityEngine.Scripting.APIUpdating; -using UnityEngine.Internal; - -namespace UnityEditor -{ - [NativeType(CodegenOptions.Custom, "MonoEditorCurveBinding")] - public struct EditorCurveBinding - { - // The path of the game object / bone being animated. - public string path; - - // The type of the component / material being animated. - private Type m_type; - - // The name of the property being animated. - public string propertyName; - - // is it a PPtr curve - private int m_isPPtrCurve; - - //is it a discrete curve - private int m_isDiscreteCurve; - - //is it placeholder curve - private int m_isPhantom; - - // This is only used internally for deleting curves - internal int m_ClassID; - internal int m_ScriptInstanceID; - - public bool isPPtrCurve { get { return m_isPPtrCurve != 0; } } - public bool isDiscreteCurve { get { return m_isDiscreteCurve != 0; } } - internal bool isPhantom { get { return m_isPhantom != 0; } set { m_isPhantom = value == true ? 1 : 0; } } - - public static bool operator==(EditorCurveBinding lhs, EditorCurveBinding rhs) - { - // Only if classID actually has been setup do we compare it (It might only be type) - if (lhs.m_ClassID != 0 && rhs.m_ClassID != 0) - { - if (lhs.m_ClassID != rhs.m_ClassID || lhs.m_ScriptInstanceID != rhs.m_ScriptInstanceID) - return false; - } - - return lhs.m_isPPtrCurve == rhs.m_isPPtrCurve && lhs.m_isDiscreteCurve == rhs.m_isDiscreteCurve && lhs.path == rhs.path && lhs.type == rhs.type && lhs.propertyName == rhs.propertyName; - } - - public static bool operator!=(EditorCurveBinding lhs, EditorCurveBinding rhs) - { - return !(lhs == rhs); - } - - public override int GetHashCode() - { - return String.Format("{0}:{1}:{2}", path, type.Name, propertyName).GetHashCode(); - } - - public override bool Equals(object other) - { - if (!(other is EditorCurveBinding)) return false; - - EditorCurveBinding rhs = (EditorCurveBinding)other; - return this == rhs; - } - - public Type type - { - get { return m_type; } - set { m_type = value; m_ClassID = 0; m_ScriptInstanceID = 0; } - } - - static public EditorCurveBinding FloatCurve(string inPath, System.Type inType, string inPropertyName) - { - EditorCurveBinding binding = new EditorCurveBinding(); - - binding.path = inPath; - binding.type = inType; - binding.propertyName = inPropertyName; - binding.m_isPPtrCurve = 0; - binding.m_isDiscreteCurve = 0; - binding.m_isPhantom = 0; - - - return binding; - //TODO: We should generate classID & scriptInstanceID here??? - } - - static public EditorCurveBinding PPtrCurve(string inPath, System.Type inType, string inPropertyName) - { - EditorCurveBinding binding = new EditorCurveBinding(); - - binding.path = inPath; - binding.type = inType; - binding.propertyName = inPropertyName; - binding.m_isPPtrCurve = 1; - binding.m_isDiscreteCurve = 1; - binding.m_isPhantom = 0; - return binding; - - //TODO: We should generate classID & scriptInstanceID here??? - } - } -} diff --git a/Editor/Mono/Animation/GameObjectRecorder.bindings.cs b/Editor/Mono/Animation/GameObjectRecorder.bindings.cs deleted file mode 100644 index d61f80e48c..0000000000 --- a/Editor/Mono/Animation/GameObjectRecorder.bindings.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEditor; -using Object = UnityEngine.Object; - -namespace UnityEditor.Experimental.Animations -{ - [NativeHeader("Editor/Src/Animation/EditorCurveBinding.bindings.h")] - [NativeHeader("Editor/Src/Animation/GameObjectRecorder.h")] - [NativeHeader("Runtime/Animation/AnimationClip.h")] - [NativeType] - public class GameObjectRecorder : Object - { - [Obsolete("The GameObjectRecorder constructor now takes a root GameObject", true)] - public GameObjectRecorder() - { - } - - public GameObjectRecorder(GameObject root) - { - Internal_Create(this, root); - } - - extern private static void Internal_Create([Writable] GameObjectRecorder notSelf, [NotNull] GameObject root); - - // Root. - extern public GameObject root { get; } - - // Bindings. - extern public void Bind(EditorCurveBinding binding); - extern public void BindAll(GameObject target, bool recursive); - extern public void BindComponent(GameObject target, Type componentType, bool recursive); - - public void BindComponent(GameObject target, bool recursive) where T : Component - { - BindComponent(target, typeof(T), recursive); - } - - extern public EditorCurveBinding[] GetBindings(); - - // Recording. - extern public void TakeSnapshot(float dt); - extern public float currentTime { get; } - extern public bool isRecording { get; } - - extern public void SaveToClip(AnimationClip clip); - extern public void ResetRecording(); - } -} diff --git a/Editor/Mono/Animation/MaterialAnimationUtility.cs b/Editor/Mono/Animation/MaterialAnimationUtility.cs deleted file mode 100644 index a6702449b2..0000000000 --- a/Editor/Mono/Animation/MaterialAnimationUtility.cs +++ /dev/null @@ -1,193 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - static internal class MaterialAnimationUtility - { - const string kMaterialPrefix = "material."; - - static PropertyModification[] CreatePropertyModifications(int count, Object target) - { - PropertyModification[] modifications = new PropertyModification[count]; - for (int i = 0; i < modifications.Length; i++) - { - modifications[i] = new PropertyModification(); - modifications[i].target = target; - } - return modifications; - } - - static void SetupPropertyModification(string name, float value, PropertyModification prop) - { - prop.propertyPath = kMaterialPrefix + name; - prop.value = value.ToString(); - } - - static PropertyModification[] MaterialPropertyToPropertyModifications(MaterialProperty materialProp, Object target, float value) - { - PropertyModification[] modifications = CreatePropertyModifications(1, target); - SetupPropertyModification(materialProp.name, value, modifications[0]); - return modifications; - } - - static PropertyModification[] MaterialPropertyToPropertyModifications(MaterialProperty materialProp, Object target, Color color) - { - PropertyModification[] modifications = CreatePropertyModifications(4, target); - SetupPropertyModification(materialProp.name + ".r", color.r, modifications[0]); - SetupPropertyModification(materialProp.name + ".g", color.g, modifications[1]); - SetupPropertyModification(materialProp.name + ".b", color.b, modifications[2]); - SetupPropertyModification(materialProp.name + ".a", color.a, modifications[3]); - return modifications; - } - - static PropertyModification[] MaterialPropertyToPropertyModifications(string name, Object target, Vector4 vec) - { - PropertyModification[] modifications = CreatePropertyModifications(4, target); - SetupPropertyModification(name + ".x", vec.x, modifications[0]); - SetupPropertyModification(name + ".y", vec.y, modifications[1]); - SetupPropertyModification(name + ".z", vec.z, modifications[2]); - SetupPropertyModification(name + ".w", vec.w, modifications[3]); - return modifications; - } - - static bool ApplyMaterialModificationToAnimationRecording(PropertyModification[] modifications) - { - UndoPropertyModification[] undoModifications = new UndoPropertyModification[modifications.Length]; - for (int i = 0; i < undoModifications.Length; ++i) - { - undoModifications[i].previousValue = modifications[i]; - } - - UndoPropertyModification[] ret = Undo.InvokePostprocessModifications(undoModifications); - return ret.Length != modifications.Length; - } - - static public bool OverridePropertyColor(MaterialProperty materialProp, Renderer target, out Color color) - { - var propertyPaths = new List(); - string basePropertyPath = kMaterialPrefix + materialProp.name; - - if (materialProp.type == MaterialProperty.PropType.Texture) - { - propertyPaths.Add(basePropertyPath + "_ST.x"); - propertyPaths.Add(basePropertyPath + "_ST.y"); - propertyPaths.Add(basePropertyPath + "_ST.z"); - propertyPaths.Add(basePropertyPath + "_ST.w"); - } - else if (materialProp.type == MaterialProperty.PropType.Color) - { - propertyPaths.Add(basePropertyPath + ".r"); - propertyPaths.Add(basePropertyPath + ".g"); - propertyPaths.Add(basePropertyPath + ".b"); - propertyPaths.Add(basePropertyPath + ".a"); - } - else - { - propertyPaths.Add(basePropertyPath); - } - - if (propertyPaths.Exists(path => AnimationMode.IsPropertyAnimated(target, path))) - { - color = AnimationMode.animatedPropertyColor; - if (AnimationMode.InAnimationRecording()) - color = AnimationMode.recordedPropertyColor; - else if (propertyPaths.Exists(path => AnimationMode.IsPropertyCandidate(target, path))) - color = AnimationMode.candidatePropertyColor; - - return true; - } - - color = Color.white; - return false; - } - - static public void SetupMaterialPropertyBlock(MaterialProperty materialProp, int changedMask, Renderer target) - { - MaterialPropertyBlock block = new MaterialPropertyBlock(); - target.GetPropertyBlock(block); - materialProp.WriteToMaterialPropertyBlock(block, changedMask); - target.SetPropertyBlock(block); - } - - static public void TearDownMaterialPropertyBlock(Renderer target) - { - target.SetPropertyBlock(null); - } - - static public bool ApplyMaterialModificationToAnimationRecording(MaterialProperty materialProp, int changedMask, Renderer target, object oldValue) - { - bool applied = false; - switch (materialProp.type) - { - case MaterialProperty.PropType.Color: - SetupMaterialPropertyBlock(materialProp, changedMask, target); - applied = ApplyMaterialModificationToAnimationRecording(MaterialPropertyToPropertyModifications(materialProp, target, (Color)oldValue)); - if (!applied) - TearDownMaterialPropertyBlock(target); - return applied; - - case MaterialProperty.PropType.Vector: - SetupMaterialPropertyBlock(materialProp, changedMask, target); - applied = ApplyMaterialModificationToAnimationRecording(MaterialPropertyToPropertyModifications(materialProp, target, (Vector4)oldValue)); - if (!applied) - TearDownMaterialPropertyBlock(target); - return applied; - - case MaterialProperty.PropType.Float: - case MaterialProperty.PropType.Range: - SetupMaterialPropertyBlock(materialProp, changedMask, target); - applied = ApplyMaterialModificationToAnimationRecording(MaterialPropertyToPropertyModifications(materialProp, target, (float)oldValue)); - if (!applied) - TearDownMaterialPropertyBlock(target); - return applied; - - case MaterialProperty.PropType.Texture: - { - if (MaterialProperty.IsTextureOffsetAndScaleChangedMask(changedMask)) - { - string name = materialProp.name + "_ST"; - SetupMaterialPropertyBlock(materialProp, changedMask, target); - applied = ApplyMaterialModificationToAnimationRecording(MaterialPropertyToPropertyModifications(name, target, (Vector4)oldValue)); - if (!applied) - TearDownMaterialPropertyBlock(target); - return applied; - } - else - return false; - } - } - - return false; - } - - static public PropertyModification[] MaterialPropertyToPropertyModifications(MaterialProperty materialProp, Renderer target) - { - switch (materialProp.type) - { - case MaterialProperty.PropType.Color: - return MaterialPropertyToPropertyModifications(materialProp, target, materialProp.colorValue); - case MaterialProperty.PropType.Vector: - return MaterialPropertyToPropertyModifications(materialProp, target, materialProp.vectorValue); - case MaterialProperty.PropType.Float: - case MaterialProperty.PropType.Range: - return MaterialPropertyToPropertyModifications(materialProp, target, materialProp.floatValue); - - case MaterialProperty.PropType.Texture: - { - string name = materialProp.name + "_ST"; - return MaterialPropertyToPropertyModifications(name, target, materialProp.vectorValue); - } - } - - return null; - } - } -} diff --git a/Editor/Mono/Animation/MecanimUtilities.cs b/Editor/Mono/Animation/MecanimUtilities.cs deleted file mode 100644 index c4ec2ef7cc..0000000000 --- a/Editor/Mono/Animation/MecanimUtilities.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections; -using UnityEditor; -using System.Collections.Generic; -using System.Linq; - - -namespace UnityEditor.Animations -{ - internal class MecanimUtilities - { - public static bool StateMachineRelativePath(AnimatorStateMachine parent, AnimatorStateMachine toFind, - ref List hierarchy) - { - hierarchy.Add(parent); - if (parent == toFind) - return true; - var childStateMachines = AnimatorStateMachine.StateMachineCache.GetChildStateMachines(parent); - for (int i = 0; i < childStateMachines.Length; i++) - { - if (StateMachineRelativePath(childStateMachines[i].stateMachine, toFind, ref hierarchy)) - return true; - } - hierarchy.Remove(parent); - return false; - } - - internal static bool AreSameAsset(Object obj1, Object obj2) - { - return AssetDatabase.GetAssetPath(obj1) == AssetDatabase.GetAssetPath(obj2); - } - - internal static void DestroyBlendTreeRecursive(BlendTree blendTree) - { - for (int i = 0; i < blendTree.children.Length; i++) - { - BlendTree childBlendTree = blendTree.children[i].motion as BlendTree; - if (childBlendTree != null && AreSameAsset(blendTree, childBlendTree)) - DestroyBlendTreeRecursive(childBlendTree); - } - - Undo.DestroyObjectImmediate(blendTree); - } - } -} diff --git a/Editor/Mono/Animation/SerializedStringTable.cs b/Editor/Mono/Animation/SerializedStringTable.cs deleted file mode 100644 index 9e6117d278..0000000000 --- a/Editor/Mono/Animation/SerializedStringTable.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections; - -[System.Serializable] -internal class SerializedStringTable -{ - [SerializeField] private string[] keys; - [SerializeField] private int[] values; - private Hashtable table; - public Hashtable hashtable { get { SanityCheck(); return table; } } - - public int Length { get { SanityCheck(); return keys.Length; } } - - private void SanityCheck() - { - if (keys == null) - { - keys = new string[0]; - values = new int[0]; - } - if (table == null) - { - table = new Hashtable(); - for (int i = 0; i < keys.Length; i++) table[keys[i]] = values[i]; - } - } - - private void SynchArrays() - { - keys = new string[table.Count]; - values = new int[table.Count]; - table.Keys.CopyTo(keys, 0); - table.Values.CopyTo(values, 0); - } - - public void Set(string key, int value) - { - SanityCheck(); - table[key] = value; - SynchArrays(); - } - - public void Set(string key) - { - Set(key, 0); - } - - public bool Contains(string key) - { - SanityCheck(); - return table.Contains(key); - } - - public int Get(string key) - { - SanityCheck(); - if (!table.Contains(key)) return -1; - return (int)table[key]; - } - - public void Remove(string key) - { - SanityCheck(); - if (table.Contains(key)) table.Remove(key); - SynchArrays(); - } -} diff --git a/Editor/Mono/Animation/StateMachine.cs b/Editor/Mono/Animation/StateMachine.cs deleted file mode 100644 index 7fadf37c91..0000000000 --- a/Editor/Mono/Animation/StateMachine.cs +++ /dev/null @@ -1,721 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEditor; -using System.Linq; - -namespace UnityEditor.Animations -{ - internal struct PushUndoIfNeeded - { - public bool pushUndo - { - get { return impl.m_PushUndo; } - set { impl.m_PushUndo = value; } - } - - public PushUndoIfNeeded(bool pushUndo) - { - m_Impl = new PushUndoIfNeededImpl(pushUndo); - } - - public void DoUndo(Object target, string undoOperation) - { - impl.DoUndo(target, undoOperation); - } - - PushUndoIfNeededImpl impl - { - get - { - if (m_Impl == null) - m_Impl = new PushUndoIfNeededImpl(true); - return m_Impl; - } - } - - PushUndoIfNeededImpl m_Impl; - - private class PushUndoIfNeededImpl - { - public PushUndoIfNeededImpl(bool pushUndo) - { - m_PushUndo = pushUndo; - } - - public void DoUndo(Object target, string undoOperation) - { - if (m_PushUndo) - { - Undo.RegisterCompleteObjectUndo(target, undoOperation); - } - } - - public bool m_PushUndo; - }; - } - - - public partial class AnimatorTransitionBase : Object - { - private PushUndoIfNeeded undoHandler = new PushUndoIfNeeded(true); - internal bool pushUndo { set { undoHandler.pushUndo = value; } } - - public void AddCondition(AnimatorConditionMode mode, float threshold, string parameter) - { - undoHandler.DoUndo(this, "Condition added"); - - AnimatorCondition[] conditionVector = conditions; - AnimatorCondition newCondition = new AnimatorCondition(); - newCondition.mode = mode; - newCondition.parameter = parameter; - newCondition.threshold = threshold; - - ArrayUtility.Add(ref conditionVector, newCondition); - conditions = conditionVector; - } - - public void RemoveCondition(AnimatorCondition condition) - { - undoHandler.DoUndo(this, "Condition removed"); - AnimatorCondition[] conditionVector = conditions; - ArrayUtility.Remove(ref conditionVector, condition); - conditions = conditionVector; - } - } - - - internal class AnimatorDefaultTransition : ScriptableObject - { - } - - public partial class AnimatorState : Object - { - private PushUndoIfNeeded undoHandler = new PushUndoIfNeeded(true); - internal bool pushUndo { set { undoHandler.pushUndo = value; } } - - - public void AddTransition(AnimatorStateTransition transition) - { - undoHandler.DoUndo(this, "Transition added"); - - AnimatorStateTransition[] transitionsVector = transitions; - ArrayUtility.Add(ref transitionsVector, transition); - transitions = transitionsVector; - } - - public void RemoveTransition(AnimatorStateTransition transition) - { - undoHandler.DoUndo(this, "Transition removed"); - - AnimatorStateTransition[] transitionsVector = transitions; - ArrayUtility.Remove(ref transitionsVector, transition); - transitions = transitionsVector; - - if (MecanimUtilities.AreSameAsset(this, transition)) - Undo.DestroyObjectImmediate(transition); - } - - private AnimatorStateTransition CreateTransition(bool setDefaultExitTime) - { - AnimatorStateTransition newTransition = new AnimatorStateTransition(); - newTransition.hasExitTime = false; - newTransition.hasFixedDuration = true; - if (AssetDatabase.GetAssetPath(this) != "") - AssetDatabase.AddObjectToAsset(newTransition, AssetDatabase.GetAssetPath(this)); - newTransition.hideFlags = HideFlags.HideInHierarchy; - - if (setDefaultExitTime) - SetDefaultTransitionExitTime(ref newTransition); - - return newTransition; - } - - private void SetDefaultTransitionExitTime(ref AnimatorStateTransition newTransition) - { - newTransition.hasExitTime = true; - - if (motion != null && motion.averageDuration > 0.0f) - { - const float transitionDefaultDuration = 0.25f; - float transitionDurationNormalized = transitionDefaultDuration / motion.averageDuration; - newTransition.duration = transitionDefaultDuration; - newTransition.exitTime = 1.0f - transitionDurationNormalized; - } - else - { - newTransition.duration = 0.25f; - newTransition.exitTime = 0.75f; - } - } - - public AnimatorStateTransition AddTransition(AnimatorState destinationState) - { - AnimatorStateTransition newTransition = CreateTransition(false); - newTransition.destinationState = destinationState; - AddTransition(newTransition); - return newTransition; - } - - public AnimatorStateTransition AddTransition(AnimatorStateMachine destinationStateMachine) - { - AnimatorStateTransition newTransition = CreateTransition(false); - newTransition.destinationStateMachine = destinationStateMachine; - AddTransition(newTransition); - return newTransition; - } - - public AnimatorStateTransition AddTransition(AnimatorState destinationState, bool defaultExitTime) - { - AnimatorStateTransition newTransition = CreateTransition(defaultExitTime); - newTransition.destinationState = destinationState; - AddTransition(newTransition); - return newTransition; - } - - public AnimatorStateTransition AddTransition(AnimatorStateMachine destinationStateMachine, bool defaultExitTime) - { - AnimatorStateTransition newTransition = CreateTransition(defaultExitTime); - newTransition.destinationStateMachine = destinationStateMachine; - AddTransition(newTransition); - return newTransition; - } - - public AnimatorStateTransition AddExitTransition() - { - return AddExitTransition(false); - } - - public AnimatorStateTransition AddExitTransition(bool defaultExitTime) - { - AnimatorStateTransition newTransition = CreateTransition(defaultExitTime); - newTransition.isExit = true; - AddTransition(newTransition); - return newTransition; - } - - internal AnimatorStateMachine FindParent(AnimatorStateMachine root) - { - if (root.HasState(this, false)) return root; - else return root.stateMachinesRecursive.Find(sm => sm.stateMachine.HasState(this, false)).stateMachine; - } - - internal AnimatorStateTransition FindTransition(AnimatorState destinationState) // pp todo return a list? - { - return (new List(transitions)).Find(t => t.destinationState == destinationState); - } - - [System.Obsolete("uniqueName does not exist anymore. Consider using .name instead.", true)] - public string uniqueName - { - get { return ""; } - } - - [System.Obsolete("GetMotion() is obsolete. Use motion", true)] - public Motion GetMotion() - { - return null; - } - - [System.Obsolete("uniqueNameHash does not exist anymore.", true)] - public int uniqueNameHash - { - get { return -1; } - } - } - - public partial class AnimatorStateMachine : Object - { - private PushUndoIfNeeded undoHandler = new PushUndoIfNeeded(true); - internal bool pushUndo { set { undoHandler.pushUndo = value; } } - - internal class StateMachineCache - { - static Dictionary m_ChildStateMachines; - static bool m_Initialized; - - static void Init() - { - if (!m_Initialized) - { - m_ChildStateMachines = new Dictionary(); - m_Initialized = true; - } - } - - static public void Clear() - { - Init(); - m_ChildStateMachines.Clear(); - } - - static public ChildAnimatorStateMachine[] GetChildStateMachines(AnimatorStateMachine parent) - { - Init(); - - ChildAnimatorStateMachine[] children; - if (m_ChildStateMachines.TryGetValue(parent, out children) == false) - { - children = parent.stateMachines; - m_ChildStateMachines.Add(parent, children); - } - return children; - } - } - internal List statesRecursive - { - get - { - List ret = new List(); - ret.AddRange(states); - - for (int j = 0; j < stateMachines.Length; j++) - { - ret.AddRange(stateMachines[j].stateMachine.statesRecursive); - } - return ret; - } - } - - internal List stateMachinesRecursive - { - get - { - List ret = new List(); - var childStateMachines = AnimatorStateMachine.StateMachineCache.GetChildStateMachines(this); - ret.AddRange(childStateMachines); - - for (int j = 0; j < childStateMachines.Length; j++) - { - ret.AddRange(childStateMachines[j].stateMachine.stateMachinesRecursive); - } - return ret; - } - } - - internal List anyStateTransitionsRecursive - { - get - { - List childTransitions = new List(); - childTransitions.AddRange(anyStateTransitions); - - foreach (ChildAnimatorStateMachine stateMachine in stateMachines) - { - childTransitions.AddRange(stateMachine.stateMachine.anyStateTransitionsRecursive); - } - - return childTransitions; - } - } - - internal Vector3 GetStatePosition(AnimatorState state) - { - ChildAnimatorState[] animatorStates = states; - for (int i = 0; i < animatorStates.Length; i++) - if (state == animatorStates[i].state) - return animatorStates[i].position; - - System.Diagnostics.Debug.Fail("Can't find state (" + state.name + ") in parent state machine (" + name + ")."); - return Vector3.zero; - } - - internal void SetStatePosition(AnimatorState state, Vector3 position) - { - ChildAnimatorState[] childStates = states; - for (int i = 0; i < childStates.Length; i++) - if (state == childStates[i].state) - { - childStates[i].position = position; - states = childStates; - return; - } - - System.Diagnostics.Debug.Fail("Can't find state (" + state.name + ") in parent state machine (" + name + ")."); - } - - internal Vector3 GetStateMachinePosition(AnimatorStateMachine stateMachine) - { - ChildAnimatorStateMachine[] childSM = stateMachines; - for (int i = 0; i < childSM.Length; i++) - if (stateMachine == childSM[i].stateMachine) - return childSM[i].position; - - System.Diagnostics.Debug.Fail("Can't find state machine (" + stateMachine.name + ") in parent state machine (" + name + ")."); - - return Vector3.zero; - } - - internal void SetStateMachinePosition(AnimatorStateMachine stateMachine, Vector3 position) - { - ChildAnimatorStateMachine[] childSM = stateMachines; - for (int i = 0; i < childSM.Length; i++) - if (stateMachine == childSM[i].stateMachine) - { - childSM[i].position = position; - stateMachines = childSM; - return; - } - - System.Diagnostics.Debug.Fail("Can't find state machine (" + stateMachine.name + ") in parent state machine (" + name + ")."); - } - - public AnimatorState AddState(string name) - { - return AddState(name, states.Length > 0 ? states[states.Length - 1].position + new Vector3(35, 65) : new Vector3(200, 0, 0)); - } - - public AnimatorState AddState(string name, Vector3 position) - { - AnimatorState state = new AnimatorState(); - state.hideFlags = HideFlags.HideInHierarchy; - state.name = MakeUniqueStateName(name); - - if (AssetDatabase.GetAssetPath(this) != "") - AssetDatabase.AddObjectToAsset(state, AssetDatabase.GetAssetPath(this)); - - AddState(state, position); - - return state; - } - - public void AddState(AnimatorState state, Vector3 position) - { - ChildAnimatorState[] childStates = states; - if (System.Array.Exists(childStates, childState => childState.state == state)) - { - Debug.LogWarning(System.String.Format("State '{0}' already exists in state machine '{1}', discarding new state.", state.name, name)); - return; - } - - undoHandler.DoUndo(this, "State added"); - ChildAnimatorState newState = new ChildAnimatorState(); - newState.state = state; - newState.position = position; - - ArrayUtility.Add(ref childStates, newState); - states = childStates; - } - - public void RemoveState(AnimatorState state) - { - undoHandler.DoUndo(this, "State removed"); - undoHandler.DoUndo(state, "State removed"); - RemoveStateInternal(state); - } - - public AnimatorStateMachine AddStateMachine(string name) - { - return AddStateMachine(name, Vector3.zero); - } - - public AnimatorStateMachine AddStateMachine(string name, Vector3 position) - { - AnimatorStateMachine stateMachine = new AnimatorStateMachine(); - stateMachine.hideFlags = HideFlags.HideInHierarchy; - stateMachine.name = MakeUniqueStateMachineName(name); - - AddStateMachine(stateMachine, position); - - if (AssetDatabase.GetAssetPath(this) != "") - AssetDatabase.AddObjectToAsset(stateMachine, AssetDatabase.GetAssetPath(this)); - - return stateMachine; - } - - public void AddStateMachine(AnimatorStateMachine stateMachine, Vector3 position) - { - ChildAnimatorStateMachine[] childStateMachines = stateMachines; - if (System.Array.Exists(childStateMachines, childStateMachine => childStateMachine.stateMachine == stateMachine)) - { - Debug.LogWarning(System.String.Format("Sub state machine '{0}' already exists in state machine '{1}', discarding new state machine.", stateMachine.name, name)); - return; - } - - undoHandler.DoUndo(this, "StateMachine " + stateMachine.name + " added"); - ChildAnimatorStateMachine newStateMachine = new ChildAnimatorStateMachine(); - newStateMachine.stateMachine = stateMachine; - newStateMachine.position = position; - - ArrayUtility.Add(ref childStateMachines, newStateMachine); - stateMachines = childStateMachines; - } - - public void RemoveStateMachine(AnimatorStateMachine stateMachine) - { - undoHandler.DoUndo(this, "StateMachine removed"); - undoHandler.DoUndo(stateMachine, "StateMachine removed"); - RemoveStateMachineInternal(stateMachine); - } - - private AnimatorStateTransition AddAnyStateTransition() - { - undoHandler.DoUndo(this, "AnyState Transition Added"); - - AnimatorStateTransition[] transitionsVector = anyStateTransitions; - AnimatorStateTransition newTransition = new AnimatorStateTransition(); - newTransition.hasExitTime = false; - newTransition.hasFixedDuration = true; - newTransition.duration = 0.25f; - newTransition.exitTime = 0.75f; - - if (AssetDatabase.GetAssetPath(this) != "") - AssetDatabase.AddObjectToAsset(newTransition, AssetDatabase.GetAssetPath(this)); - - newTransition.hideFlags = HideFlags.HideInHierarchy; - ArrayUtility.Add(ref transitionsVector, newTransition); - anyStateTransitions = transitionsVector; - - - return newTransition; - } - - public AnimatorStateTransition AddAnyStateTransition(AnimatorState destinationState) - { - AnimatorStateTransition newTransition = AddAnyStateTransition(); - newTransition.destinationState = destinationState; - return newTransition; - } - - public AnimatorStateTransition AddAnyStateTransition(AnimatorStateMachine destinationStateMachine) - { - AnimatorStateTransition newTransition = AddAnyStateTransition(); - newTransition.destinationStateMachine = destinationStateMachine; - return newTransition; - } - - public bool RemoveAnyStateTransition(AnimatorStateTransition transition) - { - if ((new List(anyStateTransitions)).Any(t => t == transition)) - { - undoHandler.DoUndo(this, "AnyState Transition Removed"); - - AnimatorStateTransition[] transitionsVector = anyStateTransitions; - ArrayUtility.Remove(ref transitionsVector, transition); - anyStateTransitions = transitionsVector; - - if (MecanimUtilities.AreSameAsset(this, transition)) - Undo.DestroyObjectImmediate(transition); - - return true; - } - - return false; - } - - internal void RemoveAnyStateTransitionRecursive(AnimatorStateTransition transition) - { - if (RemoveAnyStateTransition(transition)) - return; - - List childStateMachines = stateMachinesRecursive; - foreach (ChildAnimatorStateMachine sm in childStateMachines) - { - if (sm.stateMachine.RemoveAnyStateTransition(transition)) - return; - } - } - - public AnimatorTransition AddStateMachineTransition(AnimatorStateMachine sourceStateMachine) - { - AnimatorStateMachine sm = null; - return AddStateMachineTransition(sourceStateMachine, sm); - } - - public AnimatorTransition AddStateMachineTransition(AnimatorStateMachine sourceStateMachine, AnimatorStateMachine destinationStateMachine) - { - undoHandler.DoUndo(this, "StateMachine Transition Added"); - - AnimatorTransition[] transitionsVector = GetStateMachineTransitions(sourceStateMachine); - AnimatorTransition newTransition = new AnimatorTransition(); - if (destinationStateMachine) - { - newTransition.destinationStateMachine = destinationStateMachine; - } - - if (AssetDatabase.GetAssetPath(this) != "") - AssetDatabase.AddObjectToAsset(newTransition, AssetDatabase.GetAssetPath(this)); - - newTransition.hideFlags = HideFlags.HideInHierarchy; - ArrayUtility.Add(ref transitionsVector, newTransition); - SetStateMachineTransitions(sourceStateMachine, transitionsVector); - - return newTransition; - } - - public AnimatorTransition AddStateMachineTransition(AnimatorStateMachine sourceStateMachine, AnimatorState destinationState) - { - AnimatorTransition newTransition = AddStateMachineTransition(sourceStateMachine); - newTransition.destinationState = destinationState; - return newTransition; - } - - public AnimatorTransition AddStateMachineExitTransition(AnimatorStateMachine sourceStateMachine) - { - AnimatorTransition newTransition = AddStateMachineTransition(sourceStateMachine); - newTransition.isExit = true; - return newTransition; - } - - public bool RemoveStateMachineTransition(AnimatorStateMachine sourceStateMachine, AnimatorTransition transition) - { - undoHandler.DoUndo(this, "StateMachine Transition Removed"); - - AnimatorTransition[] transitionsVector = GetStateMachineTransitions(sourceStateMachine); - int baseSize = transitionsVector.Length; - ArrayUtility.Remove(ref transitionsVector, transition); - SetStateMachineTransitions(sourceStateMachine, transitionsVector); - - if (MecanimUtilities.AreSameAsset(this, transition)) - Undo.DestroyObjectImmediate(transition); - - return baseSize != transitionsVector.Length; - } - - private AnimatorTransition AddEntryTransition() - { - undoHandler.DoUndo(this, "Entry Transition Added"); - AnimatorTransition[] transitionsVector = entryTransitions; - AnimatorTransition newTransition = new AnimatorTransition(); - - if (AssetDatabase.GetAssetPath(this) != "") - AssetDatabase.AddObjectToAsset(newTransition, AssetDatabase.GetAssetPath(this)); - - newTransition.hideFlags = HideFlags.HideInHierarchy; - ArrayUtility.Add(ref transitionsVector, newTransition); - entryTransitions = transitionsVector; - - return newTransition; - } - - public AnimatorTransition AddEntryTransition(AnimatorState destinationState) - { - AnimatorTransition newTransition = AddEntryTransition(); - newTransition.destinationState = destinationState; - return newTransition; - } - - public AnimatorTransition AddEntryTransition(AnimatorStateMachine destinationStateMachine) - { - AnimatorTransition newTransition = AddEntryTransition(); - newTransition.destinationStateMachine = destinationStateMachine; - return newTransition; - } - - public bool RemoveEntryTransition(AnimatorTransition transition) - { - if ((new List(entryTransitions)).Any(t => t == transition)) - { - undoHandler.DoUndo(this, "Entry Transition Removed"); - AnimatorTransition[] transitionsVector = entryTransitions; - ArrayUtility.Remove(ref transitionsVector, transition); - entryTransitions = transitionsVector; - - if (MecanimUtilities.AreSameAsset(this, transition)) - Undo.DestroyObjectImmediate(transition); - - return true; - } - - return false; - } - - internal ChildAnimatorState FindState(int nameHash) - { - return (new List(states)).Find(s => s.state.nameHash == nameHash); - } - - internal ChildAnimatorState FindState(string name) - { - return (new List(states)).Find(s => s.state.name == name); - } - - internal bool HasState(AnimatorState state) - { - return statesRecursive.Any(s => s.state == state); - } - - internal bool IsDirectParent(AnimatorStateMachine stateMachine) - { - return stateMachines.Any(sm => sm.stateMachine == stateMachine); - } - - internal bool HasStateMachine(AnimatorStateMachine child) - { - return stateMachinesRecursive.Any(sm => sm.stateMachine == child); - } - - internal bool HasTransition(AnimatorState stateA, AnimatorState stateB) - { - return stateA.transitions.Any(t => t.destinationState == stateB) || - stateB.transitions.Any(t => t.destinationState == stateA); - } - - internal AnimatorStateMachine FindParent(AnimatorStateMachine stateMachine) - { - if (stateMachines.Any(childSM => childSM.stateMachine == stateMachine)) - return this; - else - return stateMachinesRecursive.Find(sm => sm.stateMachine.stateMachines.Any(childSM => childSM.stateMachine == stateMachine)).stateMachine; - } - - internal AnimatorStateMachine FindStateMachine(string path) - { - string[] smNames = path.Split('.'); - - // first element is always Root statemachine 'this' - AnimatorStateMachine currentSM = this; - // last element is state name, we don't care - for (int i = 1; i < smNames.Length - 1 && currentSM != null; ++i) - { - var childStateMachines = AnimatorStateMachine.StateMachineCache.GetChildStateMachines(currentSM); - int index = System.Array.FindIndex(childStateMachines, t => t.stateMachine.name == smNames[i]); - currentSM = index >= 0 ? childStateMachines[index].stateMachine : null; - } - - return (currentSM == null) ? this : currentSM; - } - - internal AnimatorStateMachine FindStateMachine(AnimatorState state) - { - if (HasState(state, false)) - return this; - - List childStateMachines = stateMachinesRecursive; - int index = childStateMachines.FindIndex(sm => sm.stateMachine.HasState(state, false)); - return index >= 0 ? childStateMachines[index].stateMachine : null; - } - - internal AnimatorStateTransition FindTransition(AnimatorState destinationState) - { - return (new List(anyStateTransitions)).Find(t => t.destinationState == destinationState); - } - - [System.Obsolete("stateCount is obsolete. Use .states.Length instead.", true)] - int stateCount - { - get { return 0; } - } - - [System.Obsolete("stateMachineCount is obsolete. Use .stateMachines.Length instead.", true)] - int stateMachineCount - { - get { return 0; } - } - - [System.Obsolete("GetTransitionsFromState is obsolete. Use AnimatorState.transitions instead.", true)] - AnimatorState GetTransitionsFromState(AnimatorState state) - { - return null; - } - - [System.Obsolete("uniqueNameHash does not exist anymore.", true)] - int uniqueNameHash - { - get { return -1; } - } - } -} diff --git a/Editor/Mono/Animation/TickHandler.cs b/Editor/Mono/Animation/TickHandler.cs deleted file mode 100644 index f0ccffc3c3..0000000000 --- a/Editor/Mono/Animation/TickHandler.cs +++ /dev/null @@ -1,214 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - [System.Serializable] - internal class TickHandler - { - // Variables related to drawing tick markers - [SerializeField] private float[] m_TickModulos = new float[] {}; // array with possible modulo numbers to choose from - [SerializeField] private float[] m_TickStrengths = new float[] {}; // array with current strength of each modulo number - [SerializeField] private int m_SmallestTick = 0; // index of the currently smallest modulo number used to draw ticks - [SerializeField] private int m_BiggestTick = -1; // index of the currently biggest modulo number used to draw ticks - [SerializeField] private float m_MinValue = 0; // shownArea min (in curve space) - [SerializeField] private float m_MaxValue = 1; // shownArea max (in curve space) - [SerializeField] private float m_PixelRange = 1; // total width/height of curveeditor - - public int tickLevels { get { return m_BiggestTick - m_SmallestTick + 1; } } - - public void SetTickModulos(float[] tickModulos) - { - m_TickModulos = tickModulos; - } - - public List GetTickModulosForFrameRate(float frameRate) - { - List modulos; - - // Make frames multiples of 5 and 10, if frameRate is too high (avoid overflow) or not an even number - if (frameRate > int.MaxValue / 2.0f || frameRate != Mathf.Round(frameRate)) - { - modulos = new List - { - 1f / frameRate, - 5f / frameRate, - 10f / frameRate, - 50f / frameRate, - 100f / frameRate, - 500f / frameRate, - 1000f / frameRate, - 5000f / frameRate, - 10000f / frameRate, - 50000f / frameRate, - 100000f / frameRate, - 500000f / frameRate - }; - - return modulos; - } - - List dividers = new List(); - int divisor = 1; - while (divisor < frameRate) - { - if (Math.Abs(divisor - frameRate) < 1e-5) - break; - int multiple = Mathf.RoundToInt(frameRate / divisor); - if (multiple % 60 == 0) - { - divisor *= 2; - dividers.Add(divisor); - } - else if (multiple % 30 == 0) - { - divisor *= 3; - dividers.Add(divisor); - } - else if (multiple % 20 == 0) - { - divisor *= 2; - dividers.Add(divisor); - } - else if (multiple % 10 == 0) - { - divisor *= 2; - dividers.Add(divisor); - } - else if (multiple % 5 == 0) - { - divisor *= 5; - dividers.Add(divisor); - } - else if (multiple % 2 == 0) - { - divisor *= 2; - dividers.Add(divisor); - } - else if (multiple % 3 == 0) - { - divisor *= 3; - dividers.Add(divisor); - } - else - divisor = Mathf.RoundToInt(frameRate); - } - modulos = new List(13 + dividers.Count); - - for (int i = 0; i < dividers.Count; i++) - modulos.Add(1f / dividers[dividers.Count - i - 1]); - - // Ticks based on seconds - modulos.Add(1); - modulos.Add(5); - modulos.Add(10); - modulos.Add(30); - modulos.Add(60); - modulos.Add(60 * 5); - modulos.Add(60 * 10); - modulos.Add(60 * 30); - modulos.Add(3600); - modulos.Add(3600 * 6); - modulos.Add(3600 * 24); - modulos.Add(3600 * 24 * 7); - modulos.Add(3600 * 24 * 14); - return modulos; - } - - public void SetTickModulosForFrameRate(float frameRate) - { - var modulos = GetTickModulosForFrameRate(frameRate); - SetTickModulos(modulos.ToArray()); - } - - public void SetRanges(float minValue, float maxValue, float minPixel, float maxPixel) - { - m_MinValue = minValue; - m_MaxValue = maxValue; - m_PixelRange = maxPixel - minPixel; - } - - public float[] GetTicksAtLevel(int level, bool excludeTicksFromHigherlevels) - { - if (level < 0) - return new float[0] {}; - - int l = Mathf.Clamp(m_SmallestTick + level, 0, m_TickModulos.Length - 1); - List ticks = new List(); - int startTick = Mathf.FloorToInt(m_MinValue / m_TickModulos[l]); - int endTick = Mathf.CeilToInt(m_MaxValue / m_TickModulos[l]); - for (int i = startTick; i <= endTick; i++) - { - // Return if tick mark is at same time as larger tick mark - if (excludeTicksFromHigherlevels - && l < m_BiggestTick - && (i % Mathf.RoundToInt(m_TickModulos[l + 1] / m_TickModulos[l]) == 0)) - continue; - ticks.Add(i * m_TickModulos[l]); - } - return ticks.ToArray(); - } - - public float GetStrengthOfLevel(int level) - { - return m_TickStrengths[m_SmallestTick + level]; - } - - public float GetPeriodOfLevel(int level) - { - return m_TickModulos[Mathf.Clamp(m_SmallestTick + level, 0, m_TickModulos.Length - 1)]; - } - - public int GetLevelWithMinSeparation(float pixelSeparation) - { - for (int i = 0; i < m_TickModulos.Length; i++) - { - // How far apart (in pixels) these modulo ticks are spaced: - float tickSpacing = m_TickModulos[i] * m_PixelRange / (m_MaxValue - m_MinValue); - if (tickSpacing >= pixelSeparation) - return i - m_SmallestTick; - } - return -1; - } - - public void SetTickStrengths(float tickMinSpacing, float tickMaxSpacing, bool sqrt) - { - m_TickStrengths = new float[m_TickModulos.Length]; - m_SmallestTick = 0; - m_BiggestTick = m_TickModulos.Length - 1; - - // Find the strength for each modulo number tick marker - for (int i = m_TickModulos.Length - 1; i >= 0; i--) - { - // How far apart (in pixels) these modulo ticks are spaced: - float tickSpacing = m_TickModulos[i] * m_PixelRange / (m_MaxValue - m_MinValue); - - // Calculate the strength of the tick markers based on the spacing: - m_TickStrengths[i] = - (tickSpacing - tickMinSpacing) / (tickMaxSpacing - tickMinSpacing); - - // Beyond kTickHeightFatThreshold the ticks don't get any bigger or fatter, - // so ignore them, since they are already covered by smalle modulo ticks anyway: - if (m_TickStrengths[i] >= 1) m_BiggestTick = i; - - // Do not show tick markers less than 3 pixels apart: - if (tickSpacing <= tickMinSpacing) { m_SmallestTick = i; break; } - } - - // Use sqrt on actively used modulo number tick markers - for (int i = m_SmallestTick; i <= m_BiggestTick; i++) - { - m_TickStrengths[i] = Mathf.Clamp01(m_TickStrengths[i]); - if (sqrt) - m_TickStrengths[i] = Mathf.Sqrt(m_TickStrengths[i]); - } - } - } -} // namespace diff --git a/Editor/Mono/Animation/TickStyle.cs b/Editor/Mono/Animation/TickStyle.cs deleted file mode 100644 index cc9e3680e0..0000000000 --- a/Editor/Mono/Animation/TickStyle.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [System.Serializable] - internal class TickStyle - { - 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 - 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 - public int distMin = 10; // min distance between ticks before they disappear completely - public int distFull = 80; // distance between ticks where they gain full strength - public int distLabel = 50; // min distance between tick labels - public bool stubs = false; // draw ticks as stubs or as full lines? - public bool centerLabel = false; // center label on tick lines - public string unit = ""; // unit to write after the number - } -} diff --git a/Editor/Mono/Animation/TimeArea.cs b/Editor/Mono/Animation/TimeArea.cs deleted file mode 100644 index 647c5770ac..0000000000 --- a/Editor/Mono/Animation/TimeArea.cs +++ /dev/null @@ -1,547 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [System.Serializable] - class TimeArea : ZoomableArea - { - [SerializeField] private TickHandler m_HTicks; - - public TickHandler hTicks - { - get { return m_HTicks; } - set { m_HTicks = value; } - } - - [SerializeField] private TickHandler m_VTicks; - - public TickHandler vTicks - { - get { return m_VTicks; } - set { m_VTicks = value; } - } - - internal const int kTickRulerDistMin = 3 - ; // min distance between ruler tick marks before they disappear completely - - internal const int kTickRulerDistFull = 80; // distance between ruler tick marks where they gain full strength - internal const int kTickRulerDistLabel = 40; // min distance between ruler tick mark labels - internal const float kTickRulerHeightMax = 0.7f; // height of the ruler tick marks when they are highest - - internal const float kTickRulerFatThreshold = 0.5f - ; // size of ruler tick marks at which they begin getting fatter - - public enum TimeFormat - { - None, // Unformatted time - TimeFrame, // Time:Frame - Frame // Integer frame - }; - - class Styles2 - { - public GUIStyle timelineTick = "AnimationTimelineTick"; - public GUIStyle labelTickMarks = "CurveEditorLabelTickMarks"; - public GUIStyle playhead = "AnimationPlayHead"; - } - - static Styles2 timeAreaStyles; - - static void InitStyles() - { - if (timeAreaStyles == null) - timeAreaStyles = new Styles2(); - } - - public TimeArea(bool minimalGUI) : base(minimalGUI) - { - float[] modulos = new float[] - { - 0.0000001f, 0.0000005f, 0.000001f, 0.000005f, 0.00001f, 0.00005f, 0.0001f, 0.0005f, - 0.001f, 0.005f, 0.01f, 0.05f, 0.1f, 0.5f, 1, 5, 10, 50, 100, 500, - 1000, 5000, 10000, 50000, 100000, 500000, 1000000, 5000000, 10000000 - }; - hTicks = new TickHandler(); - hTicks.SetTickModulos(modulos); - vTicks = new TickHandler(); - vTicks.SetTickModulos(modulos); - } - - public void SetTickMarkerRanges() - { - hTicks.SetRanges(shownArea.xMin, shownArea.xMax, drawRect.xMin, drawRect.xMax); - vTicks.SetRanges(shownArea.yMin, shownArea.yMax, drawRect.yMin, drawRect.yMax); - } - - public void DrawMajorTicks(Rect position, float frameRate) - { - GUI.BeginGroup(position); - if (Event.current.type != EventType.Repaint) - { - GUI.EndGroup(); - return; - } - InitStyles(); - - HandleUtility.ApplyWireMaterial(); - - SetTickMarkerRanges(); - hTicks.SetTickStrengths(kTickRulerDistMin, kTickRulerDistFull, true); - - Color tickColor = timeAreaStyles.timelineTick.normal.textColor; - tickColor.a = 0.1f; - - if (Application.platform == RuntimePlatform.WindowsEditor) - GL.Begin(GL.QUADS); - else - GL.Begin(GL.LINES); - - // Draw tick markers of various sizes - Rect theShowArea = shownArea; - for (int l = 0; l < hTicks.tickLevels; l++) - { - float strength = hTicks.GetStrengthOfLevel(l) * .9f; - if (strength > kTickRulerFatThreshold) - { - float[] ticks = hTicks.GetTicksAtLevel(l, true); - for (int i = 0; i < ticks.Length; i++) - { - if (ticks[i] < 0) continue; - int frame = Mathf.RoundToInt(ticks[i] * frameRate); - float x = FrameToPixel(frame, frameRate, position, theShowArea); - // Draw line - DrawVerticalLineFast(x, 0.0f, position.height, tickColor); - } - } - } - - GL.End(); - GUI.EndGroup(); - } - - public void TimeRuler(Rect position, float frameRate) - { - TimeRuler(position, frameRate, true, false, 1f, TimeFormat.TimeFrame); - } - - public void TimeRuler(Rect position, float frameRate, bool labels, bool useEntireHeight, float alpha) - { - TimeRuler(position, frameRate, labels, useEntireHeight, alpha, TimeFormat.TimeFrame); - } - - public void TimeRuler(Rect position, float frameRate, bool labels, bool useEntireHeight, float alpha, - TimeFormat timeFormat) - { - Color backupCol = GUI.color; - GUI.BeginGroup(position); - InitStyles(); - - HandleUtility.ApplyWireMaterial(); - - Color tempBackgroundColor = GUI.backgroundColor; - - SetTickMarkerRanges(); - hTicks.SetTickStrengths(kTickRulerDistMin, kTickRulerDistFull, true); - - Color baseColor = timeAreaStyles.timelineTick.normal.textColor; - baseColor.a = 0.75f * alpha; - - if (Event.current.type == EventType.Repaint) - { - if (Application.platform == RuntimePlatform.WindowsEditor) - GL.Begin(GL.QUADS); - else - GL.Begin(GL.LINES); - - // Draw tick markers of various sizes - - Rect cachedShowArea = shownArea; - for (int l = 0; l < hTicks.tickLevels; l++) - { - float strength = hTicks.GetStrengthOfLevel(l) * .9f; - float[] ticks = hTicks.GetTicksAtLevel(l, true); - for (int i = 0; i < ticks.Length; i++) - { - if (ticks[i] < hRangeMin || ticks[i] > hRangeMax) - continue; - int frame = Mathf.RoundToInt(ticks[i] * frameRate); - - float height = useEntireHeight - ? position.height - : position.height * Mathf.Min(1, strength) * kTickRulerHeightMax; - float x = FrameToPixel(frame, frameRate, position, cachedShowArea); - - // Draw line - DrawVerticalLineFast(x, position.height - height + 0.5f, position.height - 0.5f, - new Color(1, 1, 1, strength / kTickRulerFatThreshold) * baseColor); - } - } - - GL.End(); - } - - if (labels) - { - // Draw tick labels - int labelLevel = hTicks.GetLevelWithMinSeparation(kTickRulerDistLabel); - float[] labelTicks = hTicks.GetTicksAtLevel(labelLevel, false); - for (int i = 0; i < labelTicks.Length; i++) - { - if (labelTicks[i] < hRangeMin || labelTicks[i] > hRangeMax) - continue; - - int frame = Mathf.RoundToInt(labelTicks[i] * frameRate); - // Important to take floor of positions of GUI stuff to get pixel correct alignment of - // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time. - - float labelpos = Mathf.Floor(FrameToPixel(frame, frameRate, position)); - string label = FormatTime(labelTicks[i], frameRate, timeFormat); - GUI.Label(new Rect(labelpos + 3, -3, 40, 20), label, timeAreaStyles.timelineTick); - } - } - GUI.EndGroup(); - - GUI.backgroundColor = tempBackgroundColor; - GUI.color = backupCol; - } - - public static void DrawPlayhead(float x, float yMin, float yMax, float thickness, float alpha) - { - if (Event.current.type != EventType.Repaint) - return; - InitStyles(); - float halfThickness = thickness * 0.5f; - Color lineColor = timeAreaStyles.playhead.normal.textColor.AlphaMultiplied(alpha); - if (thickness > 1f) - { - Rect labelRect = Rect.MinMaxRect(x - halfThickness, yMin, x + halfThickness, yMax); - EditorGUI.DrawRect(labelRect, lineColor); - } - else - { - DrawVerticalLine(x, yMin, yMax, lineColor); - } - } - - public static void DrawVerticalLine(float x, float minY, float maxY, Color color) - { - if (Event.current.type != EventType.Repaint) - return; - - Color backupCol = Handles.color; - - HandleUtility.ApplyWireMaterial(); - if (Application.platform == RuntimePlatform.WindowsEditor) - GL.Begin(GL.QUADS); - else - GL.Begin(GL.LINES); - DrawVerticalLineFast(x, minY, maxY, color); - GL.End(); - - Handles.color = backupCol; - } - - public static void DrawVerticalLineFast(float x, float minY, float maxY, Color color) - { - if (Application.platform == RuntimePlatform.WindowsEditor) - { - GL.Color(color); - GL.Vertex(new Vector3(x - 0.5f, minY, 0)); - GL.Vertex(new Vector3(x + 0.5f, minY, 0)); - GL.Vertex(new Vector3(x + 0.5f, maxY, 0)); - GL.Vertex(new Vector3(x - 0.5f, maxY, 0)); - } - else - { - GL.Color(color); - GL.Vertex(new Vector3(x, minY, 0)); - GL.Vertex(new Vector3(x, maxY, 0)); - } - } - - public enum TimeRulerDragMode - { - None, - Start, - End, - Dragging, - Cancel - } - - static float s_OriginalTime; - static float s_PickOffset; - - public TimeRulerDragMode BrowseRuler(Rect position, ref float time, float frameRate, bool pickAnywhere, - GUIStyle thumbStyle) - { - int id = GUIUtility.GetControlID(3126789, FocusType.Passive); - return BrowseRuler(position, id, ref time, frameRate, pickAnywhere, thumbStyle); - } - - public TimeRulerDragMode BrowseRuler(Rect position, int id, ref float time, float frameRate, bool pickAnywhere, - GUIStyle thumbStyle) - { - Event evt = Event.current; - Rect pickRect = position; - if (time != -1) - { - pickRect.x = Mathf.Round(TimeToPixel(time, position)) - thumbStyle.overflow.left; - pickRect.width = thumbStyle.fixedWidth + thumbStyle.overflow.horizontal; - } - - switch (evt.GetTypeForControl(id)) - { - case EventType.Repaint: - if (time != -1) - { - bool hover = position.Contains(evt.mousePosition); - pickRect.x += thumbStyle.overflow.left; - thumbStyle.Draw(pickRect, id == GUIUtility.hotControl, hover || id == GUIUtility.hotControl, - false, false); - } - break; - case EventType.MouseDown: - if (pickRect.Contains(evt.mousePosition)) - { - GUIUtility.hotControl = id; - s_PickOffset = evt.mousePosition.x - TimeToPixel(time, position); - evt.Use(); - return TimeRulerDragMode.Start; - } - else if (pickAnywhere && position.Contains(evt.mousePosition)) - { - GUIUtility.hotControl = id; - - float newT = SnapTimeToWholeFPS(PixelToTime(evt.mousePosition.x, position), frameRate); - s_OriginalTime = time; - if (newT != time) - GUI.changed = true; - time = newT; - s_PickOffset = 0; - evt.Use(); - return TimeRulerDragMode.Start; - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - float newT = SnapTimeToWholeFPS(PixelToTime(evt.mousePosition.x - s_PickOffset, position), - frameRate); - if (newT != time) - GUI.changed = true; - time = newT; - - evt.Use(); - return TimeRulerDragMode.Dragging; - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - evt.Use(); - return TimeRulerDragMode.End; - } - break; - case EventType.KeyDown: - if (GUIUtility.hotControl == id && evt.keyCode == KeyCode.Escape) - { - if (time != s_OriginalTime) - GUI.changed = true; - time = s_OriginalTime; - - GUIUtility.hotControl = 0; - evt.Use(); - return TimeRulerDragMode.Cancel; - } - break; - } - return TimeRulerDragMode.None; - } - - private float FrameToPixel(float i, float frameRate, Rect rect, Rect theShownArea) - { - return (i - theShownArea.xMin * frameRate) * rect.width / (theShownArea.width * frameRate); - } - - public float FrameToPixel(float i, float frameRate, Rect rect) - { - return FrameToPixel(i, frameRate, rect, shownArea); - } - - public float TimeField(Rect rect, int id, float time, float frameRate, TimeFormat timeFormat) - { - if (timeFormat == TimeFormat.None) - { - float newTime = EditorGUI.DoFloatField( - EditorGUI.s_RecycledEditor, - rect, - new Rect(0, 0, 0, 0), - id, - time, - EditorGUI.kFloatFieldFormatString, - EditorStyles.numberField, - false); - - return SnapTimeToWholeFPS(newTime, frameRate); - } - - if (timeFormat == TimeFormat.Frame) - { - int frame = Mathf.RoundToInt(time * frameRate); - - int newFrame = EditorGUI.DoIntField( - EditorGUI.s_RecycledEditor, - rect, - new Rect(0, 0, 0, 0), - id, - frame, - EditorGUI.kIntFieldFormatString, - EditorStyles.numberField, - false, - 0f); - - return (float)newFrame / frameRate; - } - else // if (timeFormat == TimeFormat.TimeFrame) - { - string str = FormatTime(time, frameRate, TimeFormat.TimeFrame); - - string allowedCharacters = "0123456789.,:"; - - bool changed; - str = EditorGUI.DoTextField(EditorGUI.s_RecycledEditor, id, rect, str, EditorStyles.numberField, - allowedCharacters, out changed, false, false, false); - - if (changed) - { - if (GUIUtility.keyboardControl == id) - { - GUI.changed = true; - - // Make sure that comma & period are interchangable. - str = str.Replace(',', '.'); - - // format is time:frame - int index = str.IndexOf(':'); - if (index >= 0) - { - string timeStr = str.Substring(0, index); - string frameStr = str.Substring(index + 1); - - int timeValue, frameValue; - if (int.TryParse(timeStr, out timeValue) && int.TryParse(frameStr, out frameValue)) - { - float newTime = (float)timeValue + (float)frameValue / frameRate; - return newTime; - } - } - // format is floating time value. - else - { - float newTime; - if (float.TryParse(str, out newTime)) - { - return SnapTimeToWholeFPS(newTime, frameRate); - } - } - } - } - } - - return time; - } - - public float ValueField(Rect rect, int id, float value) - { - float newValue = EditorGUI.DoFloatField( - EditorGUI.s_RecycledEditor, - rect, - new Rect(0, 0, 0, 0), - id, - value, - EditorGUI.kFloatFieldFormatString, - EditorStyles.numberField, - false); - - return newValue; - } - - public string FormatTime(float time, float frameRate, TimeFormat timeFormat) - { - if (timeFormat == TimeFormat.None) - { - int hDecimals; - if (frameRate != 0) - hDecimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(1 / frameRate); - else - hDecimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(shownArea.width / drawRect.width); - - return time.ToString("N" + hDecimals); - } - - int frame = Mathf.RoundToInt(time * frameRate); - - if (timeFormat == TimeFormat.TimeFrame) - { - int frameDigits = frameRate != 0 ? ((int)frameRate - 1).ToString().Length : 1; - string sign = string.Empty; - if (frame < 0) - { - sign = "-"; - frame = -frame; - } - return sign + (frame / (int)frameRate).ToString() + ":" + - (frame % frameRate).ToString().PadLeft(frameDigits, '0'); - } - else - { - return frame.ToString(); - } - } - - public string FormatValue(float value) - { - int vDecimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(shownArea.height / drawRect.height); - return value.ToString("N" + vDecimals); - } - - public float SnapTimeToWholeFPS(float time, float frameRate) - { - if (frameRate == 0) - return time; - return Mathf.Round(time * frameRate) / frameRate; - } - - public void DrawTimeOnSlider(float time, Color c, float maxTime, float leftSidePadding = 0, float rightSidePadding = 0) - { - const float maxTimeFudgeFactor = 3; - if (!hSlider) - return; - - if (styles.horizontalScrollbar == null) - styles.InitGUIStyles(false, true); - - var inMin = TimeToPixel(0, rect); // Assume 0 minTime - var inMax = TimeToPixel(maxTime, rect); - var outMin = TimeToPixel(shownAreaInsideMargins.xMin, rect) + styles.horizontalScrollbarLeftButton.fixedWidth + leftSidePadding; - var outMax = TimeToPixel(shownAreaInsideMargins.xMax, rect) - (styles.horizontalScrollbarRightButton.fixedWidth + rightSidePadding); - var x = (TimeToPixel(time, rect) - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; - if (x > rect.xMax - (styles.horizontalScrollbarLeftButton.fixedWidth + leftSidePadding + maxTimeFudgeFactor)) - return; - var inset = styles.sliderWidth - styles.visualSliderWidth; - var otherInset = (vSlider && hSlider) ? inset : 0; - var hRangeSliderRect = new Rect(drawRect.x + 1, drawRect.yMax - inset, drawRect.width - otherInset, styles.sliderWidth); - - var p1 = new Vector2(x, hRangeSliderRect.yMin); - var p2 = new Vector2(x, hRangeSliderRect.yMax); - - var lineRect = Rect.MinMaxRect(p1.x - 0.5f, p1.y, p2.x + 0.5f, p2.y); - EditorGUI.DrawRect(lineRect, c); - } - } -} diff --git a/Editor/Mono/Animation/TransitionPreview.cs b/Editor/Mono/Animation/TransitionPreview.cs deleted file mode 100644 index e361cdd21b..0000000000 --- a/Editor/Mono/Animation/TransitionPreview.cs +++ /dev/null @@ -1,758 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections; -using UnityEditor; -using System.Collections.Generic; -using UnityEditor.Animations; - -namespace UnityEditor -{ - internal class TransitionPreview - { - private AvatarPreview m_AvatarPreview; - private TimelineControl m_Timeline; - - private AnimatorController m_Controller; - private AnimatorStateMachine m_StateMachine; - private List m_ParameterMinMax = new List(); - private List m_ParameterInfoList; - - private AnimatorStateTransition m_RefTransition; - private TransitionInfo m_RefTransitionInfo = new TransitionInfo(); - private AnimatorStateTransition m_Transition; - private AnimatorState m_SrcState; - private AnimatorState m_DstState; - private AnimatorState m_RefSrcState; - private AnimatorState m_RefDstState; - - - private Motion m_SrcMotion; - private Motion m_DstMotion; - - private bool m_ShowBlendValue = false; - - private bool m_MustResample = true; - private bool m_MustSampleMotions = false; - public bool mustResample { set { m_MustResample = value; } get { return m_MustResample; } } - private float m_LastEvalTime = -1.0f; - private bool m_IsResampling = false; - - private AvatarMask m_LayerMask; - private int m_LayerIndex; - - private bool m_ValidTransition = true; - - class ParameterInfo - { - public string m_Name; - public float m_Value; - } - - int FindParameterInfo(List parameterInfoList, string name) - { - int ret = -1; - - for (int i = 0; i < parameterInfoList.Count && ret == -1; i++) - { - if (parameterInfoList[i].m_Name == name) - { - ret = i; - } - } - - return ret; - } - - void SetMotion(AnimatorState state, int layerIndex, Motion motion) - { - AnimatorControllerLayer[] layers = m_Controller.layers; - state.motion = motion; - m_Controller.layers = layers; - } - - class TransitionInfo - { - AnimatorState m_SrcState; - AnimatorState m_DstState; - float m_TransitionDuration; - float m_TransitionOffset; - float m_ExitTime; - - public bool IsEqual(TransitionInfo info) - { - return m_SrcState == info.m_SrcState && - m_DstState == info.m_DstState && - Mathf.Approximately(m_TransitionDuration, info.m_TransitionDuration) && - Mathf.Approximately(m_TransitionOffset, info.m_TransitionOffset) && - Mathf.Approximately(m_ExitTime, info.m_ExitTime); - } - - public TransitionInfo() - { - Init(); - } - - void Init() - { - m_SrcState = null; - m_DstState = null; - m_TransitionDuration = 0.0f; - m_TransitionOffset = 0.0f; - m_ExitTime = 0.5f; - } - - public void Set(AnimatorStateTransition transition, AnimatorState srcState, AnimatorState dstState) - { - if (transition != null) - { - m_SrcState = srcState; - m_DstState = dstState; - m_TransitionDuration = transition.duration; - m_TransitionOffset = transition.offset; - m_ExitTime = transition.exitTime; - } - else - { - Init(); - } - } - }; - - - private void CopyStateForPreview(AnimatorState src, ref AnimatorState dst) - { - dst.iKOnFeet = src.iKOnFeet; - dst.speed = src.speed; - dst.mirror = src.mirror; - - dst.motion = src.motion; - } - - private void CopyTransitionForPreview(AnimatorStateTransition src, ref AnimatorStateTransition dst) - { - if (src != null) - { - dst.duration = src.duration; - dst.offset = src.offset; - dst.exitTime = src.exitTime; - dst.hasFixedDuration = src.hasFixedDuration; - } - } - - float m_LeftStateWeightA = 0; - float m_LeftStateWeightB = 1; - float m_LeftStateTimeA = 0; - float m_LeftStateTimeB = 1; - - float m_RightStateWeightA = 0; - float m_RightStateWeightB = 1; - float m_RightStateTimeA = 0; - float m_RightStateTimeB = 1; - - List m_SrcPivotList = new List(); - List m_DstPivotList = new List(); - - private bool MustResample(TransitionInfo info) - { - bool isInPlayback = m_AvatarPreview != null && m_AvatarPreview.Animator != null && m_AvatarPreview.Animator.recorderMode == AnimatorRecorderMode.Playback; - return mustResample || !info.IsEqual(m_RefTransitionInfo) || !isInPlayback; - } - - private void WriteParametersInController() - { - if (m_Controller) - { - int parameterCount = m_Controller.parameters.Length; - - for (int i = 0; i < parameterCount; i++) - { - string parameterName = m_Controller.parameters[i].name; - - int parameterInfoIndex = FindParameterInfo(m_ParameterInfoList, parameterName); - - if (parameterInfoIndex != -1) - { - m_AvatarPreview.Animator.SetFloat(parameterName, m_ParameterInfoList[parameterInfoIndex].m_Value); - } - } - } - } - - private void ResampleTransition(AnimatorStateTransition transition, AvatarMask layerMask, TransitionInfo info, Animator previewObject) - { - m_IsResampling = true; - m_MustResample = false; - m_ValidTransition = true; - - bool resetTimeSettings = m_RefTransition != transition; - - m_RefTransition = transition; - m_RefTransitionInfo = info; - - m_LayerMask = layerMask; - - if (m_AvatarPreview != null) - { - m_AvatarPreview.OnDestroy(); - m_AvatarPreview = null; - } - - ClearController(); - - - Motion sourceStateMotion = m_RefSrcState.motion; - Init(previewObject, sourceStateMotion != null ? sourceStateMotion : m_RefDstState.motion); - - if (m_Controller == null) // did not create controller - { - m_IsResampling = false; - return; - } - - - // since transform might change during sampling, and could alter the default valuesarray, and break recording - m_AvatarPreview.Animator.allowConstantClipSamplingOptimization = false; - - /// sample all frames - - m_StateMachine.defaultState = m_DstState; - m_Transition.mute = true; - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller); - m_AvatarPreview.Animator.Update(0.00001f); - WriteParametersInController(); - m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1); - - float nextStateDuration = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex).length; - - m_StateMachine.defaultState = m_SrcState; - m_Transition.mute = false; - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller); - m_AvatarPreview.Animator.Update(0.00001f); - WriteParametersInController(); - m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1); - - float currentStateDuration = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex).length; - - if (m_LayerIndex > 0) m_AvatarPreview.Animator.stabilizeFeet = false; - float maxDuration = (currentStateDuration * m_RefTransition.exitTime) + (m_Transition.duration * (m_RefTransition.hasFixedDuration ? 1.0f : currentStateDuration)) + nextStateDuration; - - // 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. - // in some case we got a m_Transition.duration == Infinity, bail out before unity hang. - if (maxDuration > 2000.0f) - { - Debug.LogWarning("Transition duration is longer than 2000 second, Disabling previewer."); - m_ValidTransition = false; - m_IsResampling = false; - return; - } - - float effectiveCurrentStatetime = m_RefTransition.exitTime > 0 ? currentStateDuration * m_RefTransition.exitTime : currentStateDuration; - // 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 - float currentStateStepTime = effectiveCurrentStatetime > 0 ? Mathf.Min(Mathf.Max(effectiveCurrentStatetime / 300.0f, 1.0f / 30.0f), effectiveCurrentStatetime / 5.0f) : 1.0f / 30.0f; - float nextStateStepTime = nextStateDuration > 0 ? Mathf.Min(Mathf.Max(nextStateDuration / 300.0f, 1.0f / 30.0f), nextStateDuration / 5.0f) : 1.0f / 30.0f; - - currentStateStepTime = Mathf.Max(currentStateStepTime, maxDuration / 600.0f); - nextStateStepTime = Mathf.Max(nextStateStepTime, maxDuration / 600.0f); - - float stepTime = currentStateStepTime; - - float currentTime = 0.0f; - - bool hasStarted = false; - bool hasTransitioned = false; - bool hasFinished = false; - - //For transitions with exit time == 0, skip to end of clip so transition happens on first frame - if (m_RefTransition.exitTime == 0) - { - m_AvatarPreview.Animator.CrossFade(0, 0f, 0, 0.9999f); - } - m_AvatarPreview.Animator.StartRecording(-1); - - m_LeftStateWeightA = 0; - m_LeftStateTimeA = 0; - - m_AvatarPreview.Animator.Update(0.0f); - - - while (!hasFinished && currentTime < maxDuration) - { - m_AvatarPreview.Animator.Update(stepTime); - - AnimatorStateInfo currentState = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(m_LayerIndex); - currentTime += stepTime; - - if (!hasStarted) - { - m_LeftStateWeightA = m_LeftStateWeightB = currentState.normalizedTime; - m_LeftStateTimeA = m_LeftStateTimeB = currentTime; - - hasStarted = true; - } - - if (hasTransitioned && currentTime >= maxDuration) - { - hasFinished = true; - } - - if (!hasTransitioned && currentState.IsName(m_DstState.name)) - { - m_RightStateWeightA = currentState.normalizedTime; - m_RightStateTimeA = currentTime; - - hasTransitioned = true; - } - - if (!hasTransitioned) - { - m_LeftStateWeightB = currentState.normalizedTime; - m_LeftStateTimeB = currentTime; - } - - if (hasTransitioned) - { - m_RightStateWeightB = currentState.normalizedTime; - m_RightStateTimeB = currentTime; - } - - - if (m_AvatarPreview.Animator.IsInTransition(m_LayerIndex)) - { - stepTime = nextStateStepTime; - } - } - - float endTime = currentTime; - m_AvatarPreview.Animator.StopRecording(); - - if (Mathf.Approximately(m_LeftStateWeightB, m_LeftStateWeightA) || Mathf.Approximately(m_RightStateWeightB, m_RightStateWeightA)) - { - Debug.LogWarning("Difference in effective length between states is too big. Transition preview will be disabled."); - m_ValidTransition = false; - m_IsResampling = false; - return; - } - - float leftDuration = (m_LeftStateTimeB - m_LeftStateTimeA) / (m_LeftStateWeightB - m_LeftStateWeightA); - float rightDuration = (m_RightStateTimeB - m_RightStateTimeA) / (m_RightStateWeightB - m_RightStateWeightA); - - if (m_MustSampleMotions) - { - // Do this as infrequently as possible - m_MustSampleMotions = false; - m_SrcPivotList.Clear(); - m_DstPivotList.Clear(); - - - stepTime = nextStateStepTime; - m_StateMachine.defaultState = m_DstState; - m_Transition.mute = true; - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller); - m_AvatarPreview.Animator.Update(0.0f); - m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1); - m_AvatarPreview.Animator.Update(0.0000001f); - WriteParametersInController(); - currentTime = 0.0f; - while (currentTime <= rightDuration) - { - TimelineControl.PivotSample sample = new TimelineControl.PivotSample(); - sample.m_Time = currentTime; - sample.m_Weight = m_AvatarPreview.Animator.pivotWeight; - m_DstPivotList.Add(sample); - m_AvatarPreview.Animator.Update(stepTime * 2); - currentTime += stepTime * 2; - } - - stepTime = currentStateStepTime; - m_StateMachine.defaultState = m_SrcState; - m_Transition.mute = true; - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller); - m_AvatarPreview.Animator.Update(0.0000001f); - WriteParametersInController(); - m_AvatarPreview.Animator.SetLayerWeight(m_LayerIndex, 1); - currentTime = 0.0f; - while (currentTime <= leftDuration) - { - TimelineControl.PivotSample sample = new TimelineControl.PivotSample(); - sample.m_Time = currentTime; - sample.m_Weight = m_AvatarPreview.Animator.pivotWeight; - m_SrcPivotList.Add(sample); - m_AvatarPreview.Animator.Update(stepTime * 2); - currentTime += stepTime * 2; - } - - - m_Transition.mute = false; - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller); - m_AvatarPreview.Animator.Update(0.0000001f); - WriteParametersInController(); - } - - - m_Timeline.StopTime = m_AvatarPreview.timeControl.stopTime = endTime; - m_AvatarPreview.timeControl.currentTime = m_Timeline.Time; - if (resetTimeSettings) - { - m_Timeline.Time = m_Timeline.StartTime = m_AvatarPreview.timeControl.currentTime = m_AvatarPreview.timeControl.startTime = 0; - m_Timeline.ResetRange(); - } - - m_AvatarPreview.Animator.StartPlayback(); - - m_AvatarPreview.Animator.playbackTime = 0f; - m_AvatarPreview.Animator.Update(0f); - m_AvatarPreview.ResetPreviewFocus(); - - m_IsResampling = false; - } - - public void SetTransition(AnimatorStateTransition transition, AnimatorState sourceState, AnimatorState destinationState, AnimatorControllerLayer srcLayer, Animator previewObject) - { - m_RefSrcState = sourceState; - m_RefDstState = destinationState; - TransitionInfo info = new TransitionInfo(); - info.Set(transition, sourceState, destinationState); - - if (MustResample(info)) - { - ResampleTransition(transition, srcLayer.avatarMask, info, previewObject); - } - } - - private void OnPreviewAvatarChanged() - { - m_RefTransitionInfo = new TransitionInfo(); - ClearController(); - CreateController(); - CreateParameterInfoList(); - } - - void ClearController() - { - if (m_AvatarPreview != null && m_AvatarPreview.Animator != null) - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, null); - - Object.DestroyImmediate(m_Controller); - Object.DestroyImmediate(m_SrcState); - Object.DestroyImmediate(m_DstState); - Object.DestroyImmediate(m_Transition); - - m_StateMachine = null; - m_Controller = null; - m_SrcState = null; - m_DstState = null; - m_Transition = null; - } - - void CreateParameterInfoList() - { - m_ParameterInfoList = new List(); - if (m_Controller && m_Controller.parameters != null) - { - int parameterCount = m_Controller.parameters.Length; - for (int i = 0; i < parameterCount; i++) - { - ParameterInfo parameterInfo = new ParameterInfo(); - parameterInfo.m_Name = m_Controller.parameters[i].name; - m_ParameterInfoList.Add(parameterInfo); - } - } - } - - void CreateController() - { - if (m_Controller == null && m_AvatarPreview != null && m_AvatarPreview.Animator != null && m_RefTransition != null) - { - // controller - m_LayerIndex = 0; - m_Controller = new AnimatorController(); - m_Controller.pushUndo = false; - m_Controller.hideFlags = HideFlags.HideAndDontSave; - m_Controller.AddLayer("preview"); - - bool isDefaultMask = true; - - if (m_LayerMask != null) - { - for (AvatarMaskBodyPart i = 0; i < AvatarMaskBodyPart.LastBodyPart && isDefaultMask; i++) - if (!m_LayerMask.GetHumanoidBodyPartActive(i)) isDefaultMask = false; - - if (!isDefaultMask) - { - m_Controller.AddLayer("Additionnal"); - m_LayerIndex++; - AnimatorControllerLayer[] layers = m_Controller.layers; - layers[m_LayerIndex].avatarMask = m_LayerMask; - m_Controller.layers = layers; - } - } - m_StateMachine = m_Controller.layers[m_LayerIndex].stateMachine; - m_StateMachine.pushUndo = false; - m_StateMachine.hideFlags = HideFlags.HideAndDontSave; - - m_SrcMotion = m_RefSrcState.motion; - m_DstMotion = m_RefDstState.motion; - - /// Add parameters - m_ParameterMinMax.Clear(); - - if (m_SrcMotion && m_SrcMotion is BlendTree) - { - BlendTree leftBlendTree = m_SrcMotion as BlendTree; - - for (int i = 0; i < leftBlendTree.recursiveBlendParameterCount; i++) - { - string blendValueName = leftBlendTree.GetRecursiveBlendParameter(i); - if (m_Controller.IndexOfParameter(blendValueName) == -1) - { - m_Controller.AddParameter(blendValueName, AnimatorControllerParameterType.Float); - m_ParameterMinMax.Add(new Vector2(leftBlendTree.GetRecursiveBlendParameterMin(i), leftBlendTree.GetRecursiveBlendParameterMax(i))); - } - } - } - - if (m_DstMotion && m_DstMotion is BlendTree) - { - BlendTree rightBlendTree = m_DstMotion as BlendTree; - - for (int i = 0; i < rightBlendTree.recursiveBlendParameterCount; i++) - { - string blendValueName = rightBlendTree.GetRecursiveBlendParameter(i); - int parameterIndex = m_Controller.IndexOfParameter(blendValueName); - if (parameterIndex == -1) - { - m_Controller.AddParameter(blendValueName, AnimatorControllerParameterType.Float); - m_ParameterMinMax.Add(new Vector2(rightBlendTree.GetRecursiveBlendParameterMin(i), rightBlendTree.GetRecursiveBlendParameterMax(i))); - } - else - { - m_ParameterMinMax[parameterIndex] = - new Vector2(Mathf.Min(rightBlendTree.GetRecursiveBlendParameterMin(i), m_ParameterMinMax[parameterIndex][0]), - Mathf.Max(rightBlendTree.GetRecursiveBlendParameterMax(i), m_ParameterMinMax[parameterIndex][1])); - } - } - } - - - // states - m_SrcState = m_StateMachine.AddState(m_RefSrcState.name); - m_SrcState.pushUndo = false; - m_SrcState.hideFlags = HideFlags.HideAndDontSave; - m_DstState = m_StateMachine.AddState(m_RefDstState.name); - m_DstState.pushUndo = false; - m_DstState.hideFlags = HideFlags.HideAndDontSave; - - CopyStateForPreview(m_RefSrcState, ref m_SrcState); - CopyStateForPreview(m_RefDstState, ref m_DstState); - - // transition - m_Transition = m_SrcState.AddTransition(m_DstState, true); - m_Transition.pushUndo = false; - m_Transition.hideFlags = HideFlags.DontSave; - CopyTransitionForPreview(m_RefTransition, ref m_Transition); - - DisableIKOnFeetIfNeeded(); - - - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller); - - m_Controller.OnAnimatorControllerDirty += ControllerDirty; - } - } - - private void ControllerDirty() - { - if (!m_IsResampling) - m_MustResample = true; - } - - private void DisableIKOnFeetIfNeeded() - { - bool disable = false; - if (m_SrcMotion == null || m_DstMotion == null) - { - disable = true; - } - - if (m_LayerIndex > 0) - { - disable = !m_LayerMask.hasFeetIK; - } - - if (disable) - { - m_SrcState.iKOnFeet = false; - m_DstState.iKOnFeet = false; - } - } - - private void Init(Animator scenePreviewObject, Motion motion) - { - if (m_AvatarPreview == null) - { - m_AvatarPreview = new AvatarPreview(scenePreviewObject, motion); - m_AvatarPreview.OnAvatarChangeFunc = OnPreviewAvatarChanged; - m_AvatarPreview.ShowIKOnFeetButton = false; - m_AvatarPreview.ResetPreviewFocus(); - } - - if (m_Timeline == null) - { - m_Timeline = new TimelineControl(); - m_MustSampleMotions = true; - } - - CreateController(); - - if (m_ParameterInfoList == null) - { - CreateParameterInfoList(); - } - } - - public void DoTransitionPreview() - { - if (m_Controller == null) - return; - - if (Event.current.type == EventType.Repaint) - m_AvatarPreview.timeControl.Update(); - - DoTimeline(); - - // Draw the blend values - - AnimatorControllerParameter[] parameters = m_Controller.parameters; - if (parameters.Length > 0) - { - m_ShowBlendValue = EditorGUILayout.Foldout(m_ShowBlendValue, "BlendTree Parameters", true); - - if (m_ShowBlendValue) - { - for (int i = 0; i < parameters.Length; i++) - { - AnimatorControllerParameter parameter = m_Controller.parameters[i]; - float value = m_ParameterInfoList[i].m_Value; - float newValue = EditorGUILayout.Slider(parameter.name, value, m_ParameterMinMax[i][0], m_ParameterMinMax[i][1]); - if (newValue != value) - { - m_ParameterInfoList[i].m_Value = newValue; - mustResample = true; - m_MustSampleMotions = true; - } - } - } - } - } - - private void DoTimeline() - { - if (!m_ValidTransition) - { - return; - } - // get local durations - float srcStateDuration = (m_LeftStateTimeB - m_LeftStateTimeA) / (m_LeftStateWeightB - m_LeftStateWeightA); - float dstStateDuration = (m_RightStateTimeB - m_RightStateTimeA) / (m_RightStateWeightB - m_RightStateWeightA); - float transitionDuration = m_Transition.duration * (m_RefTransition.hasFixedDuration ? 1.0f : srcStateDuration); - - // Set the timeline values - m_Timeline.SrcStartTime = 0f; - m_Timeline.SrcStopTime = srcStateDuration; - m_Timeline.SrcName = m_RefSrcState.name; - m_Timeline.HasExitTime = m_RefTransition.hasExitTime; - - m_Timeline.srcLoop = m_SrcMotion ? m_SrcMotion.isLooping : false; - m_Timeline.dstLoop = m_DstMotion ? m_DstMotion.isLooping : false; - - m_Timeline.TransitionStartTime = m_RefTransition.exitTime * srcStateDuration; - m_Timeline.TransitionStopTime = m_Timeline.TransitionStartTime + transitionDuration; - - m_Timeline.Time = m_AvatarPreview.timeControl.currentTime; - - m_Timeline.DstStartTime = m_Timeline.TransitionStartTime - m_RefTransition.offset * dstStateDuration; - m_Timeline.DstStopTime = m_Timeline.DstStartTime + dstStateDuration; - - m_Timeline.SampleStopTime = m_AvatarPreview.timeControl.stopTime; - - if (m_Timeline.TransitionStopTime == Mathf.Infinity) - m_Timeline.TransitionStopTime = Mathf.Min(m_Timeline.DstStopTime, m_Timeline.SrcStopTime); - - - m_Timeline.DstName = m_RefDstState.name; - - m_Timeline.SrcPivotList = m_SrcPivotList; - m_Timeline.DstPivotList = m_DstPivotList; - - // Do the timeline - Rect previewRect = EditorGUILayout.GetControlRect(false, 150, EditorStyles.label); - - EditorGUI.BeginChangeCheck(); - - bool changedData = m_Timeline.DoTimeline(previewRect); - - if (EditorGUI.EndChangeCheck()) - { - if (changedData) - { - Undo.RegisterCompleteObjectUndo(m_RefTransition, "Edit Transition"); - m_RefTransition.exitTime = m_Timeline.TransitionStartTime / m_Timeline.SrcDuration; - m_RefTransition.duration = m_Timeline.TransitionDuration / (m_RefTransition.hasFixedDuration ? 1.0f : m_Timeline.SrcDuration); - m_RefTransition.offset = (m_Timeline.TransitionStartTime - m_Timeline.DstStartTime) / m_Timeline.DstDuration; - } - - m_AvatarPreview.timeControl.nextCurrentTime = Mathf.Clamp(m_Timeline.Time, 0, m_AvatarPreview.timeControl.stopTime); - } - } - - public void OnDisable() - { - ClearController(); - } - - public void OnDestroy() - { - ClearController(); - - if (m_Timeline != null) - { - m_Timeline = null; - } - - if (m_AvatarPreview != null) - { - m_AvatarPreview.OnDestroy(); - m_AvatarPreview = null; - } - } - - public bool HasPreviewGUI() - { - return true; - } - - public void OnPreviewSettings() - { - if (m_AvatarPreview != null) - m_AvatarPreview.DoPreviewSettings(); - } - - public void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - if (m_AvatarPreview != null && m_Controller != null) - { - if (m_LastEvalTime != m_AvatarPreview.timeControl.currentTime && Event.current.type == EventType.Repaint) - { - m_AvatarPreview.Animator.playbackTime = m_AvatarPreview.timeControl.currentTime; - m_AvatarPreview.Animator.Update(0); - m_LastEvalTime = m_AvatarPreview.timeControl.currentTime; - } - - m_AvatarPreview.DoAvatarPreview(r, background); - } - } - } -}//namespace UnityEditor diff --git a/Editor/Mono/Animation/ZoomableArea.cs b/Editor/Mono/Animation/ZoomableArea.cs deleted file mode 100644 index e73ebadf28..0000000000 --- a/Editor/Mono/Animation/ZoomableArea.cs +++ /dev/null @@ -1,884 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; - -namespace UnityEditor -{ - // NOTE: do _not_ use GUILayout to get the rectangle for zoomable area, - // will not work and will start failing miserably (mouse events not hitting it, etc.). - // That's because ZoomableArea is using GUILayout itself, and needs an actual - // physical rectangle. - - [System.Serializable] - internal class ZoomableArea - { - // Global state - private static Vector2 m_MouseDownPosition = new Vector2(-1000000, -1000000); // in transformed space - private static int zoomableAreaHash = "ZoomableArea".GetHashCode(); - - // Range lock settings - [SerializeField] private bool m_HRangeLocked; - [SerializeField] private bool m_VRangeLocked; - public bool hRangeLocked { get { return m_HRangeLocked; } set { m_HRangeLocked = value; } } - public bool vRangeLocked { get { return m_VRangeLocked; } set { m_VRangeLocked = value; } } - - - [SerializeField] private float m_HBaseRangeMin = 0; - [SerializeField] private float m_HBaseRangeMax = 1; - [SerializeField] private float m_VBaseRangeMin = 0; - [SerializeField] private float m_VBaseRangeMax = 1; - public float hBaseRangeMin { get { return m_HBaseRangeMin; } set { m_HBaseRangeMin = value; } } - public float hBaseRangeMax { get { return m_HBaseRangeMax; } set { m_HBaseRangeMax = value; } } - public float vBaseRangeMin { get { return m_VBaseRangeMin; } set { m_VBaseRangeMin = value; } } - public float vBaseRangeMax { get { return m_VBaseRangeMax; } set { m_VBaseRangeMax = value; } } - [SerializeField] private bool m_HAllowExceedBaseRangeMin = true; - [SerializeField] private bool m_HAllowExceedBaseRangeMax = true; - [SerializeField] private bool m_VAllowExceedBaseRangeMin = true; - [SerializeField] private bool m_VAllowExceedBaseRangeMax = true; - public bool hAllowExceedBaseRangeMin { get { return m_HAllowExceedBaseRangeMin; } set { m_HAllowExceedBaseRangeMin = value; } } - public bool hAllowExceedBaseRangeMax { get { return m_HAllowExceedBaseRangeMax; } set { m_HAllowExceedBaseRangeMax = value; } } - public bool vAllowExceedBaseRangeMin { get { return m_VAllowExceedBaseRangeMin; } set { m_VAllowExceedBaseRangeMin = value; } } - public bool vAllowExceedBaseRangeMax { get { return m_VAllowExceedBaseRangeMax; } set { m_VAllowExceedBaseRangeMax = value; } } - public float hRangeMin - { - get { return (hAllowExceedBaseRangeMin ? Mathf.NegativeInfinity : hBaseRangeMin); } - set { SetAllowExceed(ref m_HBaseRangeMin, ref m_HAllowExceedBaseRangeMin, value); } - } - public float hRangeMax - { - get { return (hAllowExceedBaseRangeMax ? Mathf.Infinity : hBaseRangeMax); } - set { SetAllowExceed(ref m_HBaseRangeMax, ref m_HAllowExceedBaseRangeMax, value); } - } - public float vRangeMin - { - get { return (vAllowExceedBaseRangeMin ? Mathf.NegativeInfinity : vBaseRangeMin); } - set { SetAllowExceed(ref m_VBaseRangeMin, ref m_VAllowExceedBaseRangeMin, value); } - } - public float vRangeMax - { - get { return (vAllowExceedBaseRangeMax ? Mathf.Infinity : vBaseRangeMax); } - set { SetAllowExceed(ref m_VBaseRangeMax, ref m_VAllowExceedBaseRangeMax, value); } - } - private void SetAllowExceed(ref float rangeEnd, ref bool allowExceed, float value) - { - if (value == Mathf.NegativeInfinity || value == Mathf.Infinity) - { - rangeEnd = (value == Mathf.NegativeInfinity ? 0 : 1); - allowExceed = true; - } - else - { - rangeEnd = value; - allowExceed = false; - } - } - - private const float kMinScale = 0.00001f; - private const float kMaxScale = 100000.0f; - private float m_HScaleMin = kMinScale; - private float m_HScaleMax = kMaxScale; - private float m_VScaleMin = kMinScale; - private float m_VScaleMax = kMaxScale; - - private const float kMinWidth = 0.05f; - private const float kMinHeight = 0.05f; - - public float hScaleMin - { - get { return m_HScaleMin; } - set { m_HScaleMin = Mathf.Clamp(value, kMinScale, kMaxScale); } - } - public float hScaleMax - { - get { return m_HScaleMax; } - set { m_HScaleMax = Mathf.Clamp(value, kMinScale, kMaxScale); } - } - public float vScaleMin - { - get { return m_VScaleMin; } - set { m_VScaleMin = Mathf.Clamp(value, kMinScale, kMaxScale); } - } - public float vScaleMax - { - get { return m_VScaleMax; } - set { m_VScaleMax = Mathf.Clamp(value, kMinScale, kMaxScale); } - } - - // Window resize settings - [SerializeField] private bool m_ScaleWithWindow = false; - public bool scaleWithWindow { get { return m_ScaleWithWindow; } set { m_ScaleWithWindow = value; } } - - // Slider settings - [SerializeField] private bool m_HSlider = true; - [SerializeField] private bool m_VSlider = true; - public bool hSlider { get { return m_HSlider; } set { Rect r = rect; m_HSlider = value; rect = r; } } - public bool vSlider { get { return m_VSlider; } set { Rect r = rect; m_VSlider = value; rect = r; } } - - [SerializeField] private bool m_IgnoreScrollWheelUntilClicked = false; - public bool ignoreScrollWheelUntilClicked { get { return m_IgnoreScrollWheelUntilClicked; } set { m_IgnoreScrollWheelUntilClicked = value; } } - - [SerializeField] private bool m_EnableMouseInput = true; - public bool enableMouseInput { get { return m_EnableMouseInput; } set { m_EnableMouseInput = value; } } - - [SerializeField] private bool m_EnableSliderZoom = true; - - public bool m_UniformScale; - public bool uniformScale { get { return m_UniformScale; } set { m_UniformScale = value; } } - - // This is optional now, but used to be default behaviour because ZoomableAreas are mostly graphs with +Y being up - public enum YDirection - { - Positive, - Negative - } - [SerializeField] private YDirection m_UpDirection = YDirection.Positive; - public YDirection upDirection - { - get - { - return m_UpDirection; - } - set - { - if (m_UpDirection != value) - { - m_UpDirection = value; - m_Scale.y = -m_Scale.y; - } - } - } - - // View and drawing settings - [SerializeField] private Rect m_DrawArea = new Rect(0, 0, 100, 100); - internal void SetDrawRectHack(Rect r) { m_DrawArea = r; } - [SerializeField] internal Vector2 m_Scale = new Vector2(1, -1); - [SerializeField] internal Vector2 m_Translation = new Vector2(0, 0); - [SerializeField] private float m_MarginLeft, m_MarginRight, m_MarginTop, m_MarginBottom; - [SerializeField] private Rect m_LastShownAreaInsideMargins = new Rect(0, 0, 100, 100); - - public Vector2 scale { get { return m_Scale; } } - public Vector2 translation { get { return m_Translation; } } - public float margin { set { m_MarginLeft = m_MarginRight = m_MarginTop = m_MarginBottom = value; } } - public float leftmargin { get { return m_MarginLeft; } set { m_MarginLeft = value; } } - public float rightmargin { get { return m_MarginRight; } set { m_MarginRight = value; } } - public float topmargin { get { return m_MarginTop; } set { m_MarginTop = value; } } - public float bottommargin { get { return m_MarginBottom; } set { m_MarginBottom = value; } } - - // IDs for scrollbars - int verticalScrollbarID, horizontalScrollbarID; - - [SerializeField] bool m_MinimalGUI; - - public class Styles - { - public GUIStyle horizontalScrollbar; - public GUIStyle horizontalMinMaxScrollbarThumb; - public GUIStyle horizontalScrollbarLeftButton; - public GUIStyle horizontalScrollbarRightButton; - public GUIStyle verticalScrollbar; - public GUIStyle verticalMinMaxScrollbarThumb; - public GUIStyle verticalScrollbarUpButton; - public GUIStyle verticalScrollbarDownButton; - - public float sliderWidth; - public float visualSliderWidth; - public Styles(bool minimalGUI) - { - if (minimalGUI) - { - visualSliderWidth = 0; - sliderWidth = 15; - } - else - { - visualSliderWidth = 15; - sliderWidth = 15; - } - } - - public void InitGUIStyles(bool minimalGUI, bool enableSliderZoom) - { - if (minimalGUI) - { - horizontalMinMaxScrollbarThumb = enableSliderZoom ? "MiniMinMaxSliderHorizontal" : "MiniSliderhorizontal"; - horizontalScrollbarLeftButton = GUIStyle.none; - horizontalScrollbarRightButton = GUIStyle.none; - horizontalScrollbar = GUIStyle.none; - verticalMinMaxScrollbarThumb = enableSliderZoom ? "MiniMinMaxSlidervertical" : "MiniSliderVertical"; - verticalScrollbarUpButton = GUIStyle.none; - verticalScrollbarDownButton = GUIStyle.none; - verticalScrollbar = GUIStyle.none; - } - else - { - horizontalMinMaxScrollbarThumb = enableSliderZoom ? "horizontalMinMaxScrollbarThumb" : "horizontalscrollbarthumb"; - horizontalScrollbarLeftButton = "horizontalScrollbarLeftbutton"; - horizontalScrollbarRightButton = "horizontalScrollbarRightbutton"; - horizontalScrollbar = GUI.skin.horizontalScrollbar; - verticalMinMaxScrollbarThumb = enableSliderZoom ? "verticalMinMaxScrollbarThumb" : "verticalscrollbarthumb"; - verticalScrollbarUpButton = "verticalScrollbarUpbutton"; - verticalScrollbarDownButton = "verticalScrollbarDownbutton"; - verticalScrollbar = GUI.skin.verticalScrollbar; - } - } - } - - private Styles m_Styles; - protected Styles styles - { - get - { - if (m_Styles == null) - m_Styles = new Styles(m_MinimalGUI); - return m_Styles; - } - } - - public Rect rect - { - get { return new Rect(drawRect.x, drawRect.y, drawRect.width + (m_VSlider ? styles.visualSliderWidth : 0), drawRect.height + (m_HSlider ? styles.visualSliderWidth : 0)); } - set - { - Rect newDrawArea = new Rect(value.x, value.y, value.width - (m_VSlider ? styles.visualSliderWidth : 0), value.height - (m_HSlider ? styles.visualSliderWidth : 0)); - if (newDrawArea != m_DrawArea) - { - if (m_ScaleWithWindow) - { - m_DrawArea = newDrawArea; - shownAreaInsideMargins = m_LastShownAreaInsideMargins; - } - else - { - m_Translation += new Vector2((newDrawArea.width - m_DrawArea.width) / 2, (newDrawArea.height - m_DrawArea.height) / 2); - m_DrawArea = newDrawArea; - } - } - EnforceScaleAndRange(); - } - } - public Rect drawRect { get { return m_DrawArea; } } - - public void SetShownHRangeInsideMargins(float min, float max) - { - float widthInsideMargins = drawRect.width - leftmargin - rightmargin; - if (widthInsideMargins < kMinWidth) widthInsideMargins = kMinWidth; - - float denum = max - min; - if (denum < kMinWidth) denum = kMinWidth; - - m_Scale.x = widthInsideMargins / denum; - - m_Translation.x = -min * m_Scale.x + leftmargin; - EnforceScaleAndRange(); - } - - public void SetShownHRange(float min, float max) - { - float denum = max - min; - if (denum < kMinWidth) denum = kMinWidth; - - m_Scale.x = drawRect.width / denum; - - m_Translation.x = -min * m_Scale.x; - EnforceScaleAndRange(); - } - - public void SetShownVRangeInsideMargins(float min, float max) - { - if (m_UpDirection == YDirection.Positive) - { - m_Scale.y = -(drawRect.height - topmargin - bottommargin) / (max - min); - m_Translation.y = drawRect.height - min * m_Scale.y - topmargin; - } - else - { - m_Scale.y = (drawRect.height - topmargin - bottommargin) / (max - min); - m_Translation.y = -min * m_Scale.y - bottommargin; - } - EnforceScaleAndRange(); - } - - public void SetShownVRange(float min, float max) - { - if (m_UpDirection == YDirection.Positive) - { - m_Scale.y = -drawRect.height / (max - min); - m_Translation.y = drawRect.height - min * m_Scale.y; - } - else - { - m_Scale.y = drawRect.height / (max - min); - m_Translation.y = -min * m_Scale.y; - } - EnforceScaleAndRange(); - } - - // ShownArea is in curve space - public Rect shownArea - { - set - { - float width = (value.width < kMinWidth) ? kMinWidth : value.width; - float height = (value.height < kMinHeight) ? kMinHeight : value.height; - - if (m_UpDirection == YDirection.Positive) - { - m_Scale.x = drawRect.width / width; - m_Scale.y = -drawRect.height / height; - m_Translation.x = -value.x * m_Scale.x; - m_Translation.y = drawRect.height - value.y * m_Scale.y; - } - else - { - m_Scale.x = drawRect.width / width; - m_Scale.y = drawRect.height / height; - m_Translation.x = -value.x * m_Scale.x; - m_Translation.y = -value.y * m_Scale.y; - } - EnforceScaleAndRange(); - } - get - { - if (m_UpDirection == YDirection.Positive) - { - return new Rect( - -m_Translation.x / m_Scale.x, - -(m_Translation.y - drawRect.height) / m_Scale.y, - drawRect.width / m_Scale.x, - drawRect.height / -m_Scale.y - ); - } - else - { - return new Rect( - -m_Translation.x / m_Scale.x, - -m_Translation.y / m_Scale.y, - drawRect.width / m_Scale.x, - drawRect.height / m_Scale.y - ); - } - } - } - - public Rect shownAreaInsideMargins - { - set - { - shownAreaInsideMarginsInternal = value; - EnforceScaleAndRange(); - } - get - { - return shownAreaInsideMarginsInternal; - } - } - - private Rect shownAreaInsideMarginsInternal - { - set - { - float width = (value.width < kMinWidth) ? kMinWidth : value.width; - float height = (value.height < kMinHeight) ? kMinHeight : value.height; - - float widthInsideMargins = drawRect.width - leftmargin - rightmargin; - if (widthInsideMargins < kMinWidth) widthInsideMargins = kMinWidth; - - float heightInsideMargins = drawRect.height - topmargin - bottommargin; - if (heightInsideMargins < kMinHeight) heightInsideMargins = kMinHeight; - - if (m_UpDirection == YDirection.Positive) - { - m_Scale.x = widthInsideMargins / width; - m_Scale.y = -heightInsideMargins / height; - m_Translation.x = -value.x * m_Scale.x + leftmargin; - m_Translation.y = drawRect.height - value.y * m_Scale.y - topmargin; - } - else - { - m_Scale.x = widthInsideMargins / width; - m_Scale.y = heightInsideMargins / height; - m_Translation.x = -value.x * m_Scale.x + leftmargin; - m_Translation.y = -value.y * m_Scale.y + topmargin; - } - } - get - { - float leftmarginRel = leftmargin / m_Scale.x; - float rightmarginRel = rightmargin / m_Scale.x; - float topmarginRel = topmargin / m_Scale.y; - float bottommarginRel = bottommargin / m_Scale.y; - - Rect area = shownArea; - area.x += leftmarginRel; - area.y -= topmarginRel; - area.width -= leftmarginRel + rightmarginRel; - area.height += topmarginRel + bottommarginRel; - return area; - } - } - - public virtual Bounds drawingBounds - { - get - { - return new Bounds( - new Vector3((hBaseRangeMin + hBaseRangeMax) * 0.5f, (vBaseRangeMin + vBaseRangeMax) * 0.5f, 0), - new Vector3(hBaseRangeMax - hBaseRangeMin, vBaseRangeMax - vBaseRangeMin, 1) - ); - } - } - - - // Utility transform functions - - public Matrix4x4 drawingToViewMatrix - { - get - { - return Matrix4x4.TRS(m_Translation, Quaternion.identity, new Vector3(m_Scale.x, m_Scale.y, 1)); - } - } - - public Vector2 DrawingToViewTransformPoint(Vector2 lhs) - { return new Vector2(lhs.x * m_Scale.x + m_Translation.x, lhs.y * m_Scale.y + m_Translation.y); } - public Vector3 DrawingToViewTransformPoint(Vector3 lhs) - { return new Vector3(lhs.x * m_Scale.x + m_Translation.x, lhs.y * m_Scale.y + m_Translation.y, 0); } - - public Vector2 ViewToDrawingTransformPoint(Vector2 lhs) - { return new Vector2((lhs.x - m_Translation.x) / m_Scale.x , (lhs.y - m_Translation.y) / m_Scale.y); } - public Vector3 ViewToDrawingTransformPoint(Vector3 lhs) - { return new Vector3((lhs.x - m_Translation.x) / m_Scale.x , (lhs.y - m_Translation.y) / m_Scale.y, 0); } - - public Vector2 DrawingToViewTransformVector(Vector2 lhs) - { return new Vector2(lhs.x * m_Scale.x, lhs.y * m_Scale.y); } - public Vector3 DrawingToViewTransformVector(Vector3 lhs) - { return new Vector3(lhs.x * m_Scale.x, lhs.y * m_Scale.y, 0); } - - public Vector2 ViewToDrawingTransformVector(Vector2 lhs) - { return new Vector2(lhs.x / m_Scale.x, lhs.y / m_Scale.y); } - public Vector3 ViewToDrawingTransformVector(Vector3 lhs) - { return new Vector3(lhs.x / m_Scale.x, lhs.y / m_Scale.y, 0); } - - public Vector2 mousePositionInDrawing - { - get { return ViewToDrawingTransformPoint(Event.current.mousePosition); } - } - - public Vector2 NormalizeInViewSpace(Vector2 vec) - { - vec = Vector2.Scale(vec, m_Scale); - vec /= vec.magnitude; - return Vector2.Scale(vec, new Vector2(1 / m_Scale.x, 1 / m_Scale.y)); - } - - // Utility mouse event functions - - private bool IsZoomEvent() - { - return ( - (Event.current.button == 1 && Event.current.alt) // right+alt drag - //|| (Event.current.button == 0 && Event.current.command) // left+commend drag - //|| (Event.current.button == 2 && Event.current.command) // middle+command drag - - ); - } - - private bool IsPanEvent() - { - return ( - (Event.current.button == 0 && Event.current.alt) // left+alt drag - || (Event.current.button == 2 && !Event.current.command) // middle drag - ); - } - - public ZoomableArea() - { - m_MinimalGUI = false; - } - - public ZoomableArea(bool minimalGUI) - { - m_MinimalGUI = minimalGUI; - } - - public ZoomableArea(bool minimalGUI, bool enableSliderZoom) - { - m_MinimalGUI = minimalGUI; - m_EnableSliderZoom = enableSliderZoom; - } - - public void BeginViewGUI() - { - if (styles.horizontalScrollbar == null) - styles.InitGUIStyles(m_MinimalGUI, m_EnableSliderZoom); - - if (enableMouseInput) - HandleZoomAndPanEvents(m_DrawArea); - - horizontalScrollbarID = GUIUtility.GetControlID(EditorGUIExt.s_MinMaxSliderHash, FocusType.Passive); - verticalScrollbarID = GUIUtility.GetControlID(EditorGUIExt.s_MinMaxSliderHash, FocusType.Passive); - - if (!m_MinimalGUI || Event.current.type != EventType.Repaint) - SliderGUI(); - } - - public void HandleZoomAndPanEvents(Rect area) - { - GUILayout.BeginArea(area); - - area.x = 0; - area.y = 0; - int id = GUIUtility.GetControlID(zoomableAreaHash, FocusType.Passive, area); - - switch (Event.current.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (area.Contains(Event.current.mousePosition)) - { - // Catch keyboard control when clicked inside zoomable area - // (used to restrict scrollwheel) - GUIUtility.keyboardControl = id; - - if (IsZoomEvent() || IsPanEvent()) - { - GUIUtility.hotControl = id; - m_MouseDownPosition = mousePositionInDrawing; - - Event.current.Use(); - } - } - break; - case EventType.MouseUp: - //Debug.Log("mouse-up!"); - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - - // If we got the mousedown, the mouseup is ours as well - // (no matter if the click was in the area or not) - m_MouseDownPosition = new Vector2(-1000000, -1000000); - //Event.current.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl != id) break; - - if (IsZoomEvent()) - { - // Zoom in around mouse down position - HandleZoomEvent(m_MouseDownPosition, false); - Event.current.Use(); - } - else if (IsPanEvent()) - { - // Pan view - Pan(); - Event.current.Use(); - } - break; - case EventType.ScrollWheel: - if (!area.Contains(Event.current.mousePosition)) - break; - if (m_IgnoreScrollWheelUntilClicked && GUIUtility.keyboardControl != id) - break; - - // Zoom in around cursor position - HandleZoomEvent(mousePositionInDrawing, true); - Event.current.Use(); - break; - } - - GUILayout.EndArea(); - } - - public void EndViewGUI() - { - if (m_MinimalGUI && Event.current.type == EventType.Repaint) - SliderGUI(); - } - - void SliderGUI() - { - if (!m_HSlider && !m_VSlider) - return; - - using (new EditorGUI.DisabledScope(!enableMouseInput)) - { - Bounds editorBounds = drawingBounds; - Rect area = shownAreaInsideMargins; - float min, max; - float inset = styles.sliderWidth - styles.visualSliderWidth; - float otherInset = (vSlider && hSlider) ? inset : 0; - - Vector2 scaleDelta = m_Scale; - // Horizontal range slider - if (m_HSlider) - { - Rect hRangeSliderRect = new Rect(drawRect.x + 1, drawRect.yMax - inset, drawRect.width - otherInset, styles.sliderWidth); - float shownXRange = area.width; - float shownXMin = area.xMin; - if (m_EnableSliderZoom) - { - EditorGUIExt.MinMaxScroller(hRangeSliderRect, horizontalScrollbarID, - ref shownXMin, ref shownXRange, - editorBounds.min.x, editorBounds.max.x, - Mathf.NegativeInfinity, Mathf.Infinity, - styles.horizontalScrollbar, styles.horizontalMinMaxScrollbarThumb, - styles.horizontalScrollbarLeftButton, styles.horizontalScrollbarRightButton, true); - } - else - { - shownXMin = GUI.Scroller(hRangeSliderRect, - shownXMin, shownXRange, editorBounds.min.x, editorBounds.max.x, - styles.horizontalScrollbar, styles.horizontalMinMaxScrollbarThumb, - styles.horizontalScrollbarLeftButton, styles.horizontalScrollbarRightButton, true); - } - min = shownXMin; - max = shownXMin + shownXRange; - if (min > area.xMin) - min = Mathf.Min(min, max - rect.width / m_HScaleMax); - if (max < area.xMax) - max = Mathf.Max(max, min + rect.width / m_HScaleMax); - SetShownHRangeInsideMargins(min, max); - } - - // Vertical range slider - // Reverse y values since y increses upwards for the draw area but downwards for the slider - if (m_VSlider) - { - if (m_UpDirection == YDirection.Positive) - { - Rect vRangeSliderRect = new Rect(drawRect.xMax - inset, drawRect.y, styles.sliderWidth, drawRect.height - otherInset); - float shownYRange = area.height; - float shownYMin = -area.yMax; - if (m_EnableSliderZoom) - { - EditorGUIExt.MinMaxScroller(vRangeSliderRect, verticalScrollbarID, - ref shownYMin, ref shownYRange, - -editorBounds.max.y, -editorBounds.min.y, - Mathf.NegativeInfinity, Mathf.Infinity, - styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb, - styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false); - } - else - { - shownYMin = GUI.Scroller(vRangeSliderRect, - shownYMin, shownYRange, -editorBounds.max.y, -editorBounds.min.y, - styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb, - styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false); - } - min = -(shownYMin + shownYRange); - max = -shownYMin; - if (min > area.yMin) - min = Mathf.Min(min, max - rect.height / m_VScaleMax); - if (max < area.yMax) - max = Mathf.Max(max, min + rect.height / m_VScaleMax); - SetShownVRangeInsideMargins(min, max); - } - else - { - Rect vRangeSliderRect = new Rect(drawRect.xMax - inset, drawRect.y, styles.sliderWidth, drawRect.height - otherInset); - float shownYRange = area.height; - float shownYMin = area.yMin; - if (m_EnableSliderZoom) - { - EditorGUIExt.MinMaxScroller(vRangeSliderRect, verticalScrollbarID, - ref shownYMin, ref shownYRange, - editorBounds.min.y, editorBounds.max.y, - Mathf.NegativeInfinity, Mathf.Infinity, - styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb, - styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false); - } - else - { - shownYMin = GUI.Scroller(vRangeSliderRect, - shownYMin, shownYRange, editorBounds.min.y, editorBounds.max.y, - styles.verticalScrollbar, styles.verticalMinMaxScrollbarThumb, - styles.verticalScrollbarUpButton, styles.verticalScrollbarDownButton, false); - } - min = shownYMin; - max = shownYMin + shownYRange; - if (min > area.yMin) - min = Mathf.Min(min, max - rect.height / m_VScaleMax); - if (max < area.yMax) - max = Mathf.Max(max, min + rect.height / m_VScaleMax); - SetShownVRangeInsideMargins(min, max); - } - } - - if (uniformScale) - { - float aspect = drawRect.width / drawRect.height; - scaleDelta -= m_Scale; - var delta = new Vector2(-scaleDelta.y * aspect, -scaleDelta.x / aspect); - - m_Scale -= delta; - m_Translation.x -= scaleDelta.y / 2; - m_Translation.y -= scaleDelta.x / 2; - EnforceScaleAndRange(); - } - } - } - - private void Pan() - { - if (!m_HRangeLocked) - m_Translation.x += Event.current.delta.x; - if (!m_VRangeLocked) - m_Translation.y += Event.current.delta.y; - - EnforceScaleAndRange(); - } - - private void HandleZoomEvent(Vector2 zoomAround, bool scrollwhell) - { - // Get delta (from scroll wheel or mouse pad) - // Add x and y delta to cover all cases - // (scrool view has only y or only x when shift is pressed, - // while mouse pad has both x and y at all times) - float delta = Event.current.delta.x + Event.current.delta.y; - - if (scrollwhell) - delta = -delta; - - // Scale multiplier. Don't allow scale of zero or below! - float scale = Mathf.Max(0.01F, 1 + delta * 0.01F); - - // Cap scale when at min width to not "glide" away when zooming closer - float width = shownAreaInsideMargins.width; - if (width / scale <= kMinWidth) - return; - - SetScaleFocused(zoomAround, scale * m_Scale, Event.current.shift, EditorGUI.actionKey); - } - - // Sets a new scale, keeping focalPoint in the same relative position - public void SetScaleFocused(Vector2 focalPoint, Vector2 newScale) - { - SetScaleFocused(focalPoint, newScale, false, false); - } - - public void SetScaleFocused(Vector2 focalPoint, Vector2 newScale, bool lockHorizontal, bool lockVertical) - { - if (uniformScale) - lockHorizontal = lockVertical = false; - - if (!m_HRangeLocked && !lockHorizontal) - { - // Offset to make zoom centered around cursor position - m_Translation.x -= focalPoint.x * (newScale.x - m_Scale.x); - - // Apply zooming - m_Scale.x = newScale.x; - } - if (!m_VRangeLocked && !lockVertical) - { - // Offset to make zoom centered around cursor position - m_Translation.y -= focalPoint.y * (newScale.y - m_Scale.y); - - // Apply zooming - m_Scale.y = newScale.y; - } - - EnforceScaleAndRange(); - } - - public void SetTransform(Vector2 newTranslation, Vector2 newScale) - { - m_Scale = newScale; - m_Translation = newTranslation; - EnforceScaleAndRange(); - } - - public void EnforceScaleAndRange() - { - // Minimum scale might also be constrained by maximum range - float constrainedHScaleMin = rect.width / m_HScaleMin; - float constrainedVScaleMin = rect.height / m_VScaleMin; - if (hRangeMax != Mathf.Infinity && hRangeMin != Mathf.NegativeInfinity) - constrainedHScaleMin = Mathf.Min(constrainedHScaleMin, hRangeMax - hRangeMin); - if (vRangeMax != Mathf.Infinity && vRangeMin != Mathf.NegativeInfinity) - constrainedVScaleMin = Mathf.Min(constrainedVScaleMin, vRangeMax - vRangeMin); - - Rect oldArea = m_LastShownAreaInsideMargins; - Rect newArea = shownAreaInsideMargins; - if (newArea == oldArea) - return; - - float epsilon = 0.00001f; - - if (newArea.width < oldArea.width - epsilon) - { - float xLerp = Mathf.InverseLerp(oldArea.width, newArea.width, rect.width / m_HScaleMax); - newArea = new Rect( - Mathf.Lerp(oldArea.x, newArea.x, xLerp), - newArea.y, - Mathf.Lerp(oldArea.width, newArea.width, xLerp), - newArea.height - ); - } - if (newArea.height < oldArea.height - epsilon) - { - float yLerp = Mathf.InverseLerp(oldArea.height, newArea.height, rect.height / m_VScaleMax); - newArea = new Rect( - newArea.x, - Mathf.Lerp(oldArea.y, newArea.y, yLerp), - newArea.width, - Mathf.Lerp(oldArea.height, newArea.height, yLerp) - ); - } - if (newArea.width > oldArea.width + epsilon) - { - float xLerp = Mathf.InverseLerp(oldArea.width, newArea.width, constrainedHScaleMin); - newArea = new Rect( - Mathf.Lerp(oldArea.x, newArea.x, xLerp), - newArea.y, - Mathf.Lerp(oldArea.width, newArea.width, xLerp), - newArea.height - ); - } - if (newArea.height > oldArea.height + epsilon) - { - float yLerp = Mathf.InverseLerp(oldArea.height, newArea.height, constrainedVScaleMin); - newArea = new Rect( - newArea.x, - Mathf.Lerp(oldArea.y, newArea.y, yLerp), - newArea.width, - Mathf.Lerp(oldArea.height, newArea.height, yLerp) - ); - } - - // Enforce ranges - if (newArea.xMin < hRangeMin) - newArea.x = hRangeMin; - if (newArea.xMax > hRangeMax) - newArea.x = hRangeMax - newArea.width; - if (newArea.yMin < vRangeMin) - newArea.y = vRangeMin; - if (newArea.yMax > vRangeMax) - newArea.y = vRangeMax - newArea.height; - - shownAreaInsideMarginsInternal = newArea; - m_LastShownAreaInsideMargins = newArea; - } - - public float PixelToTime(float pixelX, Rect rect) - { - return ((pixelX - rect.x) * shownArea.width / rect.width + shownArea.x); - } - - public float TimeToPixel(float time, Rect rect) - { - return (time - shownArea.x) / shownArea.width * rect.width + rect.x; - } - - public float PixelDeltaToTime(Rect rect) - { - return shownArea.width / rect.width; - } - } -} // namespace diff --git a/Editor/Mono/AnimationCurvePreviewCache.bindings.cs b/Editor/Mono/AnimationCurvePreviewCache.bindings.cs deleted file mode 100644 index c81f80566e..0000000000 --- a/Editor/Mono/AnimationCurvePreviewCache.bindings.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEditor; - -namespace UnityEditorInternal -{ - [NativeHeader("Editor/Src/AnimationCurvePreviewCache.bindings.h")] - [NativeHeader("Editor/Src/Utility/SerializedProperty.h")] - [NativeHeader("Runtime/Graphics/Texture2D.h")] - [StaticAccessor("AnimationCurvePreviewCacheBindings", StaticAccessorType.DoubleColon)] - internal class AnimationCurvePreviewCache - { - // Regions as SerializedProperty - public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, SerializedProperty property2, Color color, Rect curveRanges) - { - return GetPreview(previewWidth, previewHeight, property, property2, color, Color.clear, Color.clear); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, SerializedProperty property2, Color color, Color topFillColor, Color bottomFillColor, Rect curveRanges) - { - if (property2 == null) - return GetPropertyPreviewFilled(previewWidth, previewHeight, true, curveRanges, property, color, topFillColor, bottomFillColor); - else - return GetPropertyPreviewRegionFilled(previewWidth, previewHeight, true, curveRanges, property, property2, color, topFillColor, bottomFillColor); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, SerializedProperty property2, Color color) - { - return GetPreview(previewWidth, previewHeight, property, property2, color, Color.clear, Color.clear); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, SerializedProperty property2, Color color, Color topFillColor, Color bottomFillColor) - { - if (property2 == null) - return GetPropertyPreviewFilled(previewWidth, previewHeight, false, new Rect(), property, color, topFillColor, bottomFillColor); - else - return GetPropertyPreviewRegionFilled(previewWidth, previewHeight, false, new Rect(), property, property2, color, topFillColor, bottomFillColor); - } - - // Regions as AnimationCurves - public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, AnimationCurve curve2, Color color, Color topFillColor, Color bottomFillColor, Rect curveRanges) - { - return GetCurvePreviewRegionFilled(previewWidth, previewHeight, true, curveRanges, curve, curve2, color, topFillColor, bottomFillColor); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, AnimationCurve curve2, Color color, Rect curveRanges) - { - return GetPreview(previewWidth, previewHeight, curve, curve2, color, Color.clear, Color.clear, curveRanges); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, AnimationCurve curve2, Color color, Color topFillColor, Color bottomFillColor) - { - return GetCurvePreviewRegionFilled(previewWidth, previewHeight, false, new Rect(), curve, curve2, color, topFillColor, bottomFillColor); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, AnimationCurve curve2, Color color) - { - return GetPreview(previewWidth, previewHeight, curve, curve2, color, Color.clear, Color.clear, new Rect()); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, Color color, Color topFillColor, Color bottomFillColor, Rect curveRanges) - { - return GetPropertyPreviewFilled(previewWidth, previewHeight, true, curveRanges, property, color, topFillColor, bottomFillColor); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, Color color, Rect curveRanges) - { - return GetPreview(previewWidth, previewHeight, property, color, Color.clear, Color.clear, curveRanges); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, Color color, Color topFillColor, Color bottomFillColor) - { - return GetPropertyPreviewFilled(previewWidth, previewHeight, false, new Rect(), property, color, topFillColor, bottomFillColor); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, SerializedProperty property, Color color) - { - return GetPreview(previewWidth, previewHeight, property, color, Color.clear, Color.clear, new Rect()); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, Color color, Color topFillColor, Color bottomFillColor, Rect curveRanges) - { - return GetCurvePreviewFilled(previewWidth, previewHeight, true, curveRanges, curve, color, topFillColor, bottomFillColor); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, Color color, Rect curveRanges) - { - return GetPreview(previewWidth, previewHeight, curve, color, Color.clear, Color.clear, curveRanges); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, Color color, Color topFillColor, Color bottomFillColor) - { - return GetCurvePreviewFilled(previewWidth, previewHeight, false, new Rect(), curve, color, topFillColor, bottomFillColor); - } - - public static Texture2D GetPreview(int previewWidth, int previewHeight, AnimationCurve curve, Color color) - { - return GetPreview(previewWidth, previewHeight, curve, color, Color.clear, Color.clear, new Rect()); - } - - public static extern Texture2D GenerateCurvePreview(int previewWidth, int previewHeight, Rect curveRanges, AnimationCurve curve, Color color, Texture2D existingTexture); - - internal extern static void ClearCache(); - - private extern static Texture2D GetPropertyPreview(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, SerializedProperty property, Color color); - private extern static Texture2D GetPropertyPreviewFilled(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, SerializedProperty property, Color color, Color topFillColor, Color bottomFillColor); - private extern static Texture2D GetPropertyPreviewRegion(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, SerializedProperty property, SerializedProperty property2, Color color); - private extern static Texture2D GetPropertyPreviewRegionFilled(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, SerializedProperty property, SerializedProperty property2, Color color, Color topFillColor, Color bottomFillColor); - private extern static Texture2D GetCurvePreview(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, AnimationCurve curve, Color color); - private extern static Texture2D GetCurvePreviewFilled(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, AnimationCurve curve, Color color, Color topFillColor, Color bottomFillColor); - private extern static Texture2D GetCurvePreviewRegion(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, AnimationCurve curve, AnimationCurve curve2, Color color); - private extern static Texture2D GetCurvePreviewRegionFilled(int previewWidth, int previewHeight, bool useCurveRanges, Rect curveRanges, AnimationCurve curve, AnimationCurve curve2, Color color, Color topFillColor, Color bottomFillColor); - } -} diff --git a/Editor/Mono/AnimatorController.bindings.cs b/Editor/Mono/AnimatorController.bindings.cs deleted file mode 100644 index 6c36bcf3e0..0000000000 --- a/Editor/Mono/AnimatorController.bindings.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Playables; -using UnityEngine.Animations; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEngineInternal; -using UnityEditor; -using System.Runtime.InteropServices; - -namespace UnityEditor.Animations -{ - [NativeHeader("Runtime/Animation/Animator.h")] - [NativeHeader("Editor/Src/Animation/StateMachineBehaviourScripting.h")] - [NativeHeader("Editor/Src/Animation/AnimatorController.bindings.h")] - [NativeHeader("Runtime/Animation/AnimatorController.h")] - public partial class AnimatorController : RuntimeAnimatorController - { - public AnimatorController() - { - Internal_Create(this); - } - - [FreeFunction("AnimatorControllerBindings::Internal_Create")] - extern private static void Internal_Create([Writable] AnimatorController self); - - extern public AnimatorControllerLayer[] layers - { - [FreeFunction(Name = "AnimatorControllerBindings::GetLayers", HasExplicitThis = true)] - get; - [FreeFunction(Name = "AnimatorControllerBindings::SetLayers", HasExplicitThis = true)] - set; - } - - extern public AnimatorControllerParameter[] parameters - { - [FreeFunction(Name = "AnimatorControllerBindings::GetParameters", HasExplicitThis = true)] - get; - [FreeFunction(Name = "AnimatorControllerBindings::SetParameters", HasExplicitThis = true)] - set; - } - - [FreeFunction(Name = "AnimatorControllerBindings::GetEffectiveAnimatorController")] - extern internal static AnimatorController GetEffectiveAnimatorController(Animator animator); - - - internal static AnimatorControllerPlayable FindAnimatorControllerPlayable(Animator animator, AnimatorController controller) - { - PlayableHandle handle = new PlayableHandle(); - Internal_FindAnimatorControllerPlayable(ref handle, animator, controller); - if (!handle.IsValid()) - return AnimatorControllerPlayable.Null; - return new AnimatorControllerPlayable(handle); - } - - [FreeFunction(Name = "AnimatorControllerBindings::Internal_FindAnimatorControllerPlayable")] - extern internal static void Internal_FindAnimatorControllerPlayable(ref PlayableHandle ret, Animator animator, AnimatorController controller); - - public static void SetAnimatorController(Animator animator, AnimatorController controller) - { - animator.runtimeAnimatorController = controller; - } - - extern internal int IndexOfParameter(string name); - extern internal void RenameParameter(string prevName, string newName); - extern public string MakeUniqueParameterName(string name); - extern public string MakeUniqueLayerName(string name); - - static public StateMachineBehaviourContext[] FindStateMachineBehaviourContext(StateMachineBehaviour behaviour) - { - return Internal_FindStateMachineBehaviourContext(behaviour); - } - - [FreeFunction("FindStateMachineBehaviourContext")] - extern internal static StateMachineBehaviourContext[] Internal_FindStateMachineBehaviourContext(ScriptableObject behaviour); - - [FreeFunction("AnimatorControllerBindings::Internal_CreateStateMachineBehaviour")] - extern public static int CreateStateMachineBehaviour(MonoScript script); - - [FreeFunction("AnimatorControllerBindings::CanAddStateMachineBehaviours")] - extern internal static bool CanAddStateMachineBehaviours(); - - extern internal MonoScript GetBehaviourMonoScript(AnimatorState state, int layerIndex, int behaviourIndex); - - [FreeFunction] - extern private static ScriptableObject ScriptingAddStateMachineBehaviourWithType(Type stateMachineBehaviourType, AnimatorController controller, AnimatorState state, int layerIndex); - - - [TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)] - public StateMachineBehaviour AddEffectiveStateMachineBehaviour(Type stateMachineBehaviourType, AnimatorState state, int layerIndex) - { - return (StateMachineBehaviour)ScriptingAddStateMachineBehaviourWithType(stateMachineBehaviourType, this, state, layerIndex); - } - - public T AddEffectiveStateMachineBehaviour(AnimatorState state, int layerIndex) where T : StateMachineBehaviour - { - return AddEffectiveStateMachineBehaviour(typeof(T), state, layerIndex) as T; - } - - public T[] GetBehaviours() where T : StateMachineBehaviour - { - return ConvertStateMachineBehaviour(InternalGetBehaviours(typeof(T))); - } - - [FreeFunction(Name = "AnimatorControllerBindings::Internal_GetBehaviours", HasExplicitThis = true)] - extern internal ScriptableObject[] InternalGetBehaviours([NotNull] Type type); - - internal static T[] ConvertStateMachineBehaviour(ScriptableObject[] rawObjects) where T : StateMachineBehaviour - { - if (rawObjects == null) return null; - T[] typedObjects = new T[rawObjects.Length]; - for (int i = 0; i < typedObjects.Length; i++) - typedObjects[i] = (T)rawObjects[i]; - return typedObjects; - } - - extern internal UnityEngine.Object[] CollectObjectsUsingParameter(string parameterName); - - internal extern bool isAssetBundled - { - [NativeName("IsAssetBundled")] - get; - } - - extern internal void AddStateEffectiveBehaviour([NotNull] AnimatorState state, int layerIndex, int instanceID); - extern internal void RemoveStateEffectiveBehaviour([NotNull] AnimatorState state, int layerIndex, int behaviourIndex); - - [FreeFunction(Name = "AnimatorControllerBindings::Internal_GetEffectiveBehaviours", HasExplicitThis = true)] - extern internal ScriptableObject[] Internal_GetEffectiveBehaviours([NotNull] AnimatorState state, int layerIndex); - - [FreeFunction(Name = "AnimatorControllerBindings::Internal_SetEffectiveBehaviours", HasExplicitThis = true)] - extern internal void Internal_SetEffectiveBehaviours([NotNull] AnimatorState state, int layerIndex, ScriptableObject[] behaviours); - } -} diff --git a/Editor/Mono/AnimatorControllerLayer.bindings.cs b/Editor/Mono/AnimatorControllerLayer.bindings.cs deleted file mode 100644 index 383ea6cfa0..0000000000 --- a/Editor/Mono/AnimatorControllerLayer.bindings.cs +++ /dev/null @@ -1,126 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEditor; -using System.Runtime.InteropServices; - -namespace UnityEditor.Animations -{ - public enum AnimatorLayerBlendingMode - { - Override = 0, - Additive = 1, - } - - [NativeHeader("Editor/Src/Animation/AnimatorControllerLayer.h")] - [NativeHeader("Editor/Src/Animation/AnimatorControllerLayer.bindings.h")] - [StructLayout(LayoutKind.Sequential)] - [NativeType(CodegenOptions.Custom, "MonoStateMotionPair")] - internal struct StateMotionPair - { - public AnimatorState m_State; - public Motion m_Motion; - } - - [NativeHeader("Editor/Src/Animation/AnimatorControllerLayer.h")] - [NativeHeader("Editor/Src/Animation/AnimatorControllerLayer.bindings.h")] - [StructLayout(LayoutKind.Sequential)] - [NativeType(CodegenOptions.Custom, "MonoStateBehavioursPair")] - internal struct StateBehavioursPair - { - public AnimatorState m_State; - public ScriptableObject[] m_Behaviours; - } - - [NativeHeader("Editor/Src/Animation/AnimatorControllerLayer.h")] - [NativeHeader("Editor/Src/Animation/AnimatorControllerLayer.bindings.h")] - [StructLayout(LayoutKind.Sequential)] - [NativeAsStruct] - [NativeType(CodegenOptions.Custom, "MonoAnimatorControllerLayer")] - public partial class AnimatorControllerLayer - { - public string name { get { return m_Name; } set { m_Name = value; } } - public AnimatorStateMachine stateMachine { get { return m_StateMachine; } set { m_StateMachine = value; } } - public AvatarMask avatarMask { get { return m_AvatarMask; } set { m_AvatarMask = value; } } - public AnimatorLayerBlendingMode blendingMode { get { return m_BlendingMode; } set { m_BlendingMode = value; } } - public int syncedLayerIndex { get { return m_SyncedLayerIndex; } set { m_SyncedLayerIndex = value; } } - public bool iKPass { get { return m_IKPass; } set { m_IKPass = value; } } - public float defaultWeight { get { return m_DefaultWeight; } set { m_DefaultWeight = value; } } - public bool syncedLayerAffectsTiming { get { return m_SyncedLayerAffectsTiming; } set { m_SyncedLayerAffectsTiming = value; }} - - public Motion GetOverrideMotion(AnimatorState state) - { - if (m_Motions != null) - foreach (StateMotionPair pair in m_Motions) - if (pair.m_State == state) - return pair.m_Motion; - - return null; - } - - public void SetOverrideMotion(AnimatorState state, Motion motion) - { - if (m_Motions == null) m_Motions = new StateMotionPair[] {}; - for (int i = 0; i < m_Motions.Length; ++i) - { - if (m_Motions[i].m_State == state) - { - m_Motions[i].m_Motion = motion; - return; - } - } - - StateMotionPair newPair; - newPair.m_State = state; - newPair.m_Motion = motion; - ArrayUtility.Add(ref m_Motions, newPair); - } - - public StateMachineBehaviour[] GetOverrideBehaviours(AnimatorState state) - { - if (m_Behaviours != null) - { - foreach (StateBehavioursPair pair in m_Behaviours) - { - if (pair.m_State == state) - return pair.m_Behaviours as StateMachineBehaviour[]; - } - } - return new StateMachineBehaviour[0]; - } - - public void SetOverrideBehaviours(AnimatorState state, StateMachineBehaviour[] behaviours) - { - if (m_Behaviours == null) m_Behaviours = new StateBehavioursPair[] {}; - for (int i = 0; i < m_Behaviours.Length; ++i) - { - if (m_Behaviours[i].m_State == state) - { - m_Behaviours[i].m_Behaviours = behaviours; - return; - } - } - - StateBehavioursPair newPair; - newPair.m_State = state; - newPair.m_Behaviours = behaviours; - ArrayUtility.Add(ref m_Behaviours, newPair); - } - - string m_Name; - AnimatorStateMachine m_StateMachine; - AvatarMask m_AvatarMask; - StateMotionPair[] m_Motions; - StateBehavioursPair[] m_Behaviours; - AnimatorLayerBlendingMode m_BlendingMode; - int m_SyncedLayerIndex = -1; - bool m_IKPass; - float m_DefaultWeight; - bool m_SyncedLayerAffectsTiming; - } -} diff --git a/Editor/Mono/Annotation/AnnotationWindow.cs b/Editor/Mono/Annotation/AnnotationWindow.cs deleted file mode 100644 index abe8b858d5..0000000000 --- a/Editor/Mono/Annotation/AnnotationWindow.cs +++ /dev/null @@ -1,675 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class AnnotationWindow : EditorWindow - { - class Styles - { - public GUIStyle toggle = "OL Toggle"; - public GUIStyle listEvenBg = "ObjectPickerResultsOdd";//"ObjectPickerResultsEven";// - public GUIStyle listOddBg = "ObjectPickerResultsEven";//"ObjectPickerResultsEven";// - public GUIStyle background = "grey_border"; - public GUIStyle seperator = "sv_iconselector_sep"; - public GUIStyle iconDropDown = "IN dropdown"; - public GUIStyle listTextStyle; - public GUIStyle listHeaderStyle; - public GUIStyle texelWorldSizeStyle; - public GUIStyle columnHeaderStyle; - public Styles() - { - listTextStyle = new GUIStyle(EditorStyles.label); - listTextStyle.alignment = TextAnchor.MiddleLeft; - listTextStyle.padding.left = 10; - - listHeaderStyle = new GUIStyle(EditorStyles.boldLabel); - listHeaderStyle.padding.left = 5; - - texelWorldSizeStyle = new GUIStyle(EditorStyles.label); - texelWorldSizeStyle.alignment = TextAnchor.UpperRight; - texelWorldSizeStyle.font = EditorStyles.miniLabel.font; - texelWorldSizeStyle.fontSize = EditorStyles.miniLabel.fontSize; - texelWorldSizeStyle.padding.right = 0; - - columnHeaderStyle = new GUIStyle(EditorStyles.miniLabel); - } - } - const float kWindowWidth = 270; - const float scrollBarWidth = 14; - const float listElementHeight = 18; - const float gizmoRightAlign = 23; - const float iconRightAlign = 64; - const float frameWidth = 1f; - - static bool s_Debug = false; - static AnnotationWindow s_AnnotationWindow = null; - static long s_LastClosedTime; - static Styles m_Styles; - List m_RecentAnnotations; - List m_BuiltinAnnotations; - List m_ScriptAnnotations; - Vector2 m_ScrollPosition; - bool m_SyncWithState; - string m_LastScriptThatHasShownTheIconSelector; - List m_MonoScriptIconsChanged; - - const int maxShowRecent = 5; - const string textGizmoVisible = "Show/Hide Gizmo"; - GUIContent iconToggleContent = new GUIContent("", "Show/Hide Icon"); - GUIContent iconSelectContent = new GUIContent("", "Select Icon"); - - GUIContent icon3dGizmoContent = EditorGUIUtility.TrTextContent("3D Icons"); - GUIContent showGridContent = EditorGUIUtility.TrTextContent("Show Grid"); - GUIContent showOutlineContent = EditorGUIUtility.TrTextContent("Selection Outline"); - GUIContent showWireframeContent = EditorGUIUtility.TrTextContent("Selection Wire"); - private bool m_IsGameView; - - const float exponentStart = -3.0f; - const float exponentRange = 3.0f; - const string kAlwaysFullSizeText = "Always Full Size"; - const string kHideAllIconsText = "Hide All Icons"; - - static float ConvertTexelWorldSizeTo01(float texelWorldSize) - { - if (texelWorldSize == -1.0f) - return 1.0f; - if (texelWorldSize == 0.0f) - return 0.0f; - return (Mathf.Log10(texelWorldSize) - exponentStart) / exponentRange; - } - - static float Convert01ToTexelWorldSize(float value01) - { - if (value01 <= 0.0f) - return 0.0f; // always hidden - 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) - } - - static string ConvertTexelWorldSizeToString(float texelWorldSize) - { - if (texelWorldSize == -1.0f) - { - return kAlwaysFullSizeText; - } - if (texelWorldSize == 0.0f) - { - return kHideAllIconsText; - } - - float displaySize = texelWorldSize * 32.0f; // The 32 is default icon size, so we show worldsize for 32 pixel icons. - int numDecimals = MathUtils.GetNumberOfDecimalsForMinimumDifference(displaySize * 0.1f); - return displaySize.ToString("N" + numDecimals); - } - - public void MonoScriptIconChanged(MonoScript monoScript) - { - if (monoScript == null) - return; - - bool add = true; - foreach (MonoScript m in m_MonoScriptIconsChanged) - if (m.GetInstanceID() == monoScript.GetInstanceID()) - add = false; - - if (add) - m_MonoScriptIconsChanged.Add(monoScript); - } - - static public void IconChanged() - { - if (s_AnnotationWindow != null) - s_AnnotationWindow.IconHasChanged(); - } - - float GetTopSectionHeight() - { - const int numberOfControls = 5; - return EditorGUI.kSingleLineHeight * numberOfControls + EditorGUI.kControlVerticalSpacing * numberOfControls; - } - - void OnEnable() - { - AssemblyReloadEvents.beforeAssemblyReload += Close; - hideFlags = HideFlags.DontSave; - } - - void OnDisable() - { - AssemblyReloadEvents.beforeAssemblyReload -= Close; - // When window closes we copy all changes to monoimporters (reimport monoScripts) - foreach (MonoScript monoScript in m_MonoScriptIconsChanged) - MonoImporter.CopyMonoScriptIconToImporters(monoScript); - - s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - s_AnnotationWindow = null; - } - - internal static bool ShowAtPosition(Rect buttonRect, bool isGameView) - { - // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time. - long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - bool justClosed = nowMilliSeconds < s_LastClosedTime + 50; - if (!justClosed) - { - Event.current.Use(); - if (s_AnnotationWindow == null) - s_AnnotationWindow = ScriptableObject.CreateInstance(); - s_AnnotationWindow.Init(buttonRect, isGameView); - return true; - } - return false; - } - - void Init(Rect buttonRect, bool isGameView) - { - // Has to be done before calling Show / ShowWithMode - buttonRect = GUIUtility.GUIToScreenRect(buttonRect); - - m_MonoScriptIconsChanged = new List(); - - m_SyncWithState = true; - - m_IsGameView = isGameView; - - SyncToState(); - - float windowHeight = 2 * frameWidth + GetTopSectionHeight() + DrawNormalList(false, 100, 0, 10000); - windowHeight = Mathf.Min(windowHeight, 900); - Vector2 windowSize = new Vector2(kWindowWidth, windowHeight); - - ShowAsDropDown(buttonRect, windowSize, null, ShowMode.PopupMenuWithKeyboardFocus); - } - - private void IconHasChanged() - { - if (string.IsNullOrEmpty(m_LastScriptThatHasShownTheIconSelector)) - return; - - foreach (AInfo t in m_ScriptAnnotations) - { - if (t.m_ScriptClass == m_LastScriptThatHasShownTheIconSelector) - { - if (t.m_IconEnabled == false) - { - t.m_IconEnabled = true; - SetIconState(t); - break; - } - } - } - - Repaint(); - } - - void Cancel() - { - // Undo changes we have done. - // PerformTemporaryUndoStack must be called before Close() below - // to ensure that we properly undo changes before closing window. - //Undo.PerformTemporaryUndoStack(); - - Close(); - GUI.changed = true; - GUIUtility.ExitGUI(); - } - - AInfo GetAInfo(int classID, string scriptClass) - { - if (scriptClass != "") - return m_ScriptAnnotations.Find(delegate(AInfo o) { return o.m_ScriptClass == scriptClass; }); - - return m_BuiltinAnnotations.Find(delegate(AInfo o) { return o.m_ClassID == classID; }); - } - - private void SyncToState() - { - // Sync annotations - Annotation[] a = AnnotationUtility.GetAnnotations(); - - string debuginfo = ""; - if (s_Debug) - debuginfo += "AnnotationWindow: SyncToState\n"; - - m_BuiltinAnnotations = new List(); - m_ScriptAnnotations = new List(); - for (int i = 0; i < a.Length; ++i) - { - if (s_Debug) - debuginfo += " same as below: icon " + a[i].iconEnabled + " gizmo " + a[i].gizmoEnabled + "\n"; - - bool ge = (a[i].gizmoEnabled == 1) ? true : false; - bool ie = (a[i].iconEnabled == 1) ? true : false; - AInfo anno = new AInfo(ge, ie, a[i].flags, a[i].classID, a[i].scriptClass); - - if (anno.m_ScriptClass == "") - { - m_BuiltinAnnotations.Add(anno); - if (s_Debug) - debuginfo += " " + UnityType.FindTypeByPersistentTypeID(anno.m_ClassID).name + ": icon " + anno.m_IconEnabled + " gizmo " + anno.m_GizmoEnabled + "\n"; - } - else - { - m_ScriptAnnotations.Add(anno); - if (s_Debug) - debuginfo += " " + a[i].scriptClass + ": icon " + anno.m_IconEnabled + " gizmo " + anno.m_GizmoEnabled + "\n"; - } - } - - m_BuiltinAnnotations.Sort(); - m_ScriptAnnotations.Sort(); - - // Sync recently changed annotations - m_RecentAnnotations = new List(); - Annotation[] recent = AnnotationUtility.GetRecentlyChangedAnnotations(); - for (int i = 0; i < recent.Length && i < maxShowRecent; ++i) - { - // Note: ainfo can be null if script has been renamed. - AInfo ainfo = GetAInfo(recent[i].classID, recent[i].scriptClass); - if (ainfo != null) - m_RecentAnnotations.Add(ainfo); - } - - m_SyncWithState = false; - - if (s_Debug) - Debug.Log(debuginfo); - } - - internal void OnGUI() - { - if (m_Styles == null) - m_Styles = new Styles(); - - if (m_SyncWithState) - SyncToState(); - - // Content - float topSectionHeight = GetTopSectionHeight(); - DrawTopSection(topSectionHeight); - DrawAnnotationList(topSectionHeight, position.height - topSectionHeight); - - // Background with 1 pixel border - if (Event.current.type == EventType.Repaint) - m_Styles.background.Draw(new Rect(0, 0, position.width, position.height), GUIContent.none, false, false, false, false); - - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - Cancel(); - } - - // ------------------------------------ - // TOP SECTION - // ------------------------------------ - void DrawTopSection(float topSectionHeight) - { - // Bg - GUI.Label(new Rect(frameWidth, 0, position.width - 2 * frameWidth, topSectionHeight), "", EditorStyles.inspectorBig); - - float topmargin = 7; - float margin = 11; - float curY = topmargin; - float labelWidth = 120; - //Extra spacing looks good here - float rowHeight = EditorGUI.kSingleLineHeight + 2 * EditorGUI.kControlVerticalSpacing; - - // Toggle 3D gizmos - Rect toggleRect = new Rect(margin, curY, labelWidth, rowHeight); - AnnotationUtility.use3dGizmos = GUI.Toggle(toggleRect, AnnotationUtility.use3dGizmos, icon3dGizmoContent); - - // Texel world size - float texelWorldSize = AnnotationUtility.iconSize; - if (s_Debug) - { - Rect texelSizeRect = new Rect(0, curY + 10, position.width - margin, rowHeight); - GUI.Label(texelSizeRect, ConvertTexelWorldSizeToString(texelWorldSize), m_Styles.texelWorldSizeStyle); - } - - using (new EditorGUI.DisabledScope(!AnnotationUtility.use3dGizmos)) - { - // Slider - float sliderWidth = position.width - margin - labelWidth; - float iconSize01 = ConvertTexelWorldSizeTo01(texelWorldSize); - Rect sliderRect = new Rect(labelWidth + margin, curY, sliderWidth - margin, rowHeight); - iconSize01 = GUI.HorizontalSlider(sliderRect, iconSize01, 0.0f, 1.0f); - if (GUI.changed) - { - AnnotationUtility.iconSize = Convert01ToTexelWorldSize(iconSize01); - SceneView.RepaintAll(); - } - } - - curY += rowHeight; - - // Show Grid - using (new EditorGUI.DisabledScope(m_IsGameView)) - { - toggleRect = new Rect(margin, curY, labelWidth, rowHeight); - AnnotationUtility.showGrid = GUI.Toggle(toggleRect, AnnotationUtility.showGrid, showGridContent); - - toggleRect.y += rowHeight; - AnnotationUtility.showSelectionOutline = GUI.Toggle(toggleRect, AnnotationUtility.showSelectionOutline, showOutlineContent); - - toggleRect.y += rowHeight; - AnnotationUtility.showSelectionWire = GUI.Toggle(toggleRect, AnnotationUtility.showSelectionWire, showWireframeContent); - } - } - - // ------------------------------------ - // ANNOTATION SECTION - // ------------------------------------ - - // Returns height used - void DrawAnnotationList(float startY, float height) - { - // Calc sizes - const float barHeight = 1; - Rect scrollViewRect = new Rect(frameWidth, - startY + barHeight, - position.width - 2 * frameWidth, - height - barHeight - frameWidth); - float totalContentHeight = DrawNormalList(false, 0, 0, 100000); - Rect contentRect = new Rect(0, 0, 1, totalContentHeight); - bool isScrollbarVisible = totalContentHeight > scrollViewRect.height; - float listElementWidth = scrollViewRect.width; - if (isScrollbarVisible) - listElementWidth -= scrollBarWidth; - - // Scrollview - m_ScrollPosition = GUI.BeginScrollView(scrollViewRect, m_ScrollPosition, contentRect); - { - DrawNormalList(true, listElementWidth, m_ScrollPosition.y - listElementHeight, m_ScrollPosition.y + totalContentHeight); - } - GUI.EndScrollView(); - } - - void Flip(ref bool even) - { - even = !even; - } - - float DrawNormalList(bool doDraw, float listElementWidth, float startY, float endY) - { - bool even = true; - float curY = 0; - bool headerDrawn = false; - - curY = DrawListSection(curY, L10n.Tr("Recently Changed"), m_RecentAnnotations, doDraw, listElementWidth, startY, endY, ref even, true, ref headerDrawn); - curY = DrawListSection(curY, L10n.Tr("Scripts"), m_ScriptAnnotations, doDraw, listElementWidth, startY, endY, ref even, false, ref headerDrawn); - curY = DrawListSection(curY, L10n.Tr("Built-in Components"), m_BuiltinAnnotations, doDraw, listElementWidth, startY, endY, ref even, false, ref headerDrawn); - - return curY; - } - - float DrawListSection(float y, string sectionHeader, List listElements, bool doDraw, float listElementWidth, float startY, float endY, ref bool even, bool useSeperator, ref bool headerDrawn) - { - float curY = y; - const float extraHeader = 10; - const float headerHeight = 20; - - if (listElements.Count > 0) - { - if (doDraw) - { - // Header background - Rect rect = new Rect(1, curY, listElementWidth - 2, extraHeader + headerHeight); - Flip(ref even); - GUIStyle backgroundStyle = even ? m_Styles.listEvenBg : m_Styles.listOddBg; // m_Styles.listSectionHeaderBg;// - GUI.Label(rect, GUIContent.Temp(""), backgroundStyle); - } - curY += extraHeader; - if (doDraw) - { - // Header text - DrawListHeader(sectionHeader, new Rect(3, curY, listElementWidth, headerHeight), ref headerDrawn); - } - curY += headerHeight; - - // List elements - for (int i = 0; i < listElements.Count; ++i) - { - Flip(ref even); - if (curY > startY && curY < endY) - { - Rect rect = new Rect(1, curY, listElementWidth - 2, listElementHeight); - if (doDraw) - DrawListElement(rect, even, listElements[i]); - } - curY += listElementHeight; - } - - if (useSeperator) - { - float height = 6; - if (doDraw) - { - GUIStyle backgroundStyle = even ? m_Styles.listEvenBg : m_Styles.listOddBg; - GUI.Label(new Rect(1, curY, listElementWidth - 2, height), GUIContent.Temp(""), backgroundStyle); - GUI.Label(new Rect(10, curY + 3, listElementWidth - 15, 3), GUIContent.Temp(""), m_Styles.seperator); - } - curY += height; - } - } - - return curY; - } - - void DrawListHeader(string header, Rect rect, ref bool headerDrawn) - { - GUI.Label(rect, GUIContent.Temp(header), m_Styles.listHeaderStyle); - - - if (headerDrawn == false) - { - headerDrawn = true; - GUI.color = new Color(1, 1, 1, 0.65f); - - // Column headers - Rect columnRect = rect; - columnRect.y += -10; - columnRect.x = rect.width - 32; - GUI.Label(columnRect, "gizmo", m_Styles.columnHeaderStyle); - - columnRect.x = rect.width - iconRightAlign; - GUI.Label(columnRect, "icon", m_Styles.columnHeaderStyle); - - GUI.color = Color.white; - } - } - - void DrawListElement(Rect rect, bool even, AInfo ainfo) - { - if (ainfo == null) - { - Debug.LogError("DrawListElement: AInfo not valid!"); - return; - } - - string tooltip; - float togglerSize = 17; - float disabledAlpha = 0.3f; - - // We maintain our own gui.changed - bool orgGUIChanged = GUI.changed; - bool orgGUIEnabled = GUI.enabled; - Color orgColor = GUI.color; - GUI.changed = false; - GUI.enabled = true; - - // Bg - GUIStyle backgroundStyle = even ? m_Styles.listEvenBg : m_Styles.listOddBg; - GUI.Label(rect, GUIContent.Temp(""), backgroundStyle); - - - // Text - Rect textRect = rect; - //textRect.x += 22; - textRect.width = rect.width - iconRightAlign - 22; // ensure text doesnt flow behind toggles - GUI.Label(textRect, ainfo.m_DisplayText, m_Styles.listTextStyle); - - - // Icon toggle - float iconSize = 16; - Rect iconRect = new Rect(rect.width - iconRightAlign, rect.y + (rect.height - iconSize) * 0.5f, iconSize, iconSize); - Texture thumb = null; - if (ainfo.m_ScriptClass != "") - { - // Icon for scripts - thumb = EditorGUIUtility.GetIconForObject(EditorGUIUtility.GetScript(ainfo.m_ScriptClass)); - - Rect div = iconRect; - div.x += 18; - div.y += 1; - div.width = 1; - div.height = 12; - - if (!EditorGUIUtility.isProSkin) - GUI.color = new Color(0, 0, 0, 0.33f); - else - GUI.color = new Color(1, 1, 1, 0.13f); - - GUI.DrawTexture(div, EditorGUIUtility.whiteTexture, ScaleMode.StretchToFill); - GUI.color = Color.white; - - Rect arrowRect = iconRect; - arrowRect.x += 18; - arrowRect.y += 0; - arrowRect.width = 9; - - if (GUI.Button(arrowRect, iconSelectContent, m_Styles.iconDropDown)) - { - Object script = EditorGUIUtility.GetScript(ainfo.m_ScriptClass); - if (script != null) - { - m_LastScriptThatHasShownTheIconSelector = ainfo.m_ScriptClass; - if (IconSelector.ShowAtPosition(script, arrowRect, true)) - { - IconSelector.SetMonoScriptIconChangedCallback(MonoScriptIconChanged); - GUIUtility.ExitGUI(); - } - } - } - } - else - { - // Icon for builtin components - if (ainfo.HasIcon()) - thumb = AssetPreview.GetMiniTypeThumbnailFromClassID(ainfo.m_ClassID); - } - - if (thumb != null) - { - if (!ainfo.m_IconEnabled) - { - GUI.color = new Color(GUI.color.r, GUI.color.g, GUI.color.b, disabledAlpha); - tooltip = ""; - } - - iconToggleContent.image = thumb; - if (GUI.Button(iconRect, iconToggleContent, GUIStyle.none)) - { - ainfo.m_IconEnabled = !ainfo.m_IconEnabled; - SetIconState(ainfo); - } - - GUI.color = orgColor; - } - - if (GUI.changed) - { - SetIconState(ainfo); - GUI.changed = false; - } - - GUI.enabled = true; - GUI.color = orgColor; - - // Gizmo toggle - if (ainfo.HasGizmo()) - { - tooltip = textGizmoVisible; - - Rect togglerRect = new Rect(rect.width - gizmoRightAlign, rect.y + (rect.height - togglerSize) * 0.5f, togglerSize, togglerSize); - ainfo.m_GizmoEnabled = GUI.Toggle(togglerRect, ainfo.m_GizmoEnabled, new GUIContent("", tooltip), m_Styles.toggle); - if (GUI.changed) - { - SetGizmoState(ainfo); - } - } - - GUI.enabled = orgGUIEnabled; - GUI.changed = orgGUIChanged; - GUI.color = orgColor; - } - - void SetIconState(AInfo ainfo) - { - AnnotationUtility.SetIconEnabled(ainfo.m_ClassID, ainfo.m_ScriptClass, ainfo.m_IconEnabled ? 1 : 0); - SceneView.RepaintAll(); - } - - void SetGizmoState(AInfo ainfo) - { - AnnotationUtility.SetGizmoEnabled(ainfo.m_ClassID, ainfo.m_ScriptClass, ainfo.m_GizmoEnabled ? 1 : 0); - SceneView.RepaintAll(); - } - } - - internal class AInfo : System.IComparable, System.IEquatable - { - // Similar values as in Annotation (in AnnotationManager.h) - public enum Flags { kHasIcon = 1, kHasGizmo = 2 }; - - public AInfo(bool gizmoEnabled, bool iconEnabled, int flags, int classID, string scriptClass) - { - m_GizmoEnabled = gizmoEnabled; - m_IconEnabled = iconEnabled; - m_ClassID = classID; - m_ScriptClass = scriptClass; - m_Flags = flags; - if (m_ScriptClass == "") - m_DisplayText = UnityType.FindTypeByPersistentTypeID(m_ClassID).name; - else - m_DisplayText = m_ScriptClass; - } - - public bool m_IconEnabled; - public bool m_GizmoEnabled; - public int m_ClassID; - public string m_ScriptClass; - public string m_DisplayText; - public int m_Flags; - - bool IsBitSet(byte b, int pos) - { - return (b & (1 << pos)) != 0; - } - - public bool HasGizmo() - { - return (m_Flags & (int)Flags.kHasGizmo) > 0; - } - - public bool HasIcon() - { - return (m_Flags & (int)Flags.kHasIcon) > 0; - } - - public int CompareTo(object obj) - { - AInfo other = obj as AInfo; - if (other != null) - return this.m_DisplayText.CompareTo(other.m_DisplayText); - else - throw new System.ArgumentException("Object is not an AInfo"); - } - - public bool Equals(AInfo other) - { - return (m_ClassID == other.m_ClassID && m_ScriptClass == other.m_ScriptClass); - } - } -} diff --git a/Editor/Mono/Annotation/LayerVisibilityWindow.cs b/Editor/Mono/Annotation/LayerVisibilityWindow.cs deleted file mode 100644 index a4bc296f54..0000000000 --- a/Editor/Mono/Annotation/LayerVisibilityWindow.cs +++ /dev/null @@ -1,323 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class LayerVisibilityWindow : EditorWindow - { - private class Styles - { - public readonly GUIStyle background = "grey_border"; - public readonly GUIStyle menuItem = "MenuItem"; - public readonly GUIStyle listEvenBg = "ObjectPickerResultsOdd"; - public readonly GUIStyle listOddBg = "ObjectPickerResultsEven"; - public readonly GUIStyle separator = "sv_iconselector_sep"; - public readonly GUIStyle lockButton = "IN LockButton"; - public readonly GUIStyle listTextStyle; - public readonly GUIStyle listHeaderStyle; - public readonly Texture2D visibleOn = EditorGUIUtility.LoadIcon("animationvisibilitytoggleon"); - public readonly Texture2D visibleOff = EditorGUIUtility.LoadIcon("animationvisibilitytoggleoff"); - public Styles() - { - listTextStyle = new GUIStyle(EditorStyles.label); - listTextStyle.alignment = TextAnchor.MiddleLeft; - listTextStyle.padding.left = 10; - - listHeaderStyle = new GUIStyle(EditorStyles.boldLabel); - listHeaderStyle.padding.left = 5; - } - } - - const float kScrollBarWidth = 14; - const float kFrameWidth = 1f; - const float kToggleSize = 17; - const float kSeparatorHeight = 6; - const string kLayerVisible = "Show/Hide Layer"; - const string kLayerLocked = "Lock Layer for Picking"; - - private static LayerVisibilityWindow s_LayerVisibilityWindow; - private static long s_LastClosedTime; - private static Styles s_Styles; - - private List s_LayerNames; - private List s_LayerMasks; - private int m_AllLayersMask; - - private float m_ContentHeight; - private Vector2 m_ScrollPosition; - - private void CalcValidLayers() - { - s_LayerNames = new List(); - s_LayerMasks = new List(); - m_AllLayersMask = 0; - - for (var i = 0; i < 32; i++) - { - var s = InternalEditorUtility.GetLayerName(i); - if (s == string.Empty) - continue; - s_LayerNames.Add(string.Format("{0}: {1}", i, s)); - s_LayerMasks.Add(i); - m_AllLayersMask |= (1 << i); - } - } - - internal void OnEnable() - { - hideFlags = HideFlags.DontSave; - wantsMouseMove = true; - } - - internal void OnDisable() - { - s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - s_LayerVisibilityWindow = null; - } - - internal static bool ShowAtPosition(Rect buttonRect) - { - // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time. - long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - bool justClosed = nowMilliSeconds < s_LastClosedTime + 50; - if (!justClosed) - { - Event.current.Use(); - if (s_LayerVisibilityWindow == null) - s_LayerVisibilityWindow = CreateInstance(); - s_LayerVisibilityWindow.Init(buttonRect); - return true; - } - return false; - } - - private void Init(Rect buttonRect) - { - // Has to be done before calling Show / ShowWithMode - buttonRect = GUIUtility.GUIToScreenRect(buttonRect); - - CalcValidLayers(); - - var rowCount = (s_LayerNames.Count + 2 + 1 + 1); - - var windowHeight = rowCount * EditorGUI.kSingleLineHeight + kSeparatorHeight; - - int sortingLayerCount = InternalEditorUtility.GetSortingLayerCount(); - if (sortingLayerCount > 1) - { - windowHeight += kSeparatorHeight + EditorGUI.kSingleLineHeight; - windowHeight += sortingLayerCount * EditorGUI.kSingleLineHeight; - } - m_ContentHeight = windowHeight; - windowHeight += 2 * kFrameWidth; - windowHeight = Mathf.Min(windowHeight, 600); - - var windowSize = new Vector2(180, windowHeight); - ShowAsDropDown(buttonRect, windowSize); - } - - internal void OnGUI() - { - // We do not use the layout event - if (Event.current.type == EventType.Layout) - return; - - if (s_Styles == null) - s_Styles = new Styles(); - - var scrollViewRect = new Rect(kFrameWidth, kFrameWidth, position.width - 2 * kFrameWidth, position.height - 2 * kFrameWidth); - var contentRect = new Rect(0, 0, 1, m_ContentHeight); - bool isScrollbarVisible = m_ContentHeight > scrollViewRect.height; - float listElementWidth = scrollViewRect.width; - if (isScrollbarVisible) - listElementWidth -= kScrollBarWidth; - - m_ScrollPosition = GUI.BeginScrollView(scrollViewRect, m_ScrollPosition, contentRect); - Draw(listElementWidth); - GUI.EndScrollView(); - - // Background with 1 pixel border - GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, s_Styles.background); - - // Use mouse move so we get hover state correctly in the menu item rows - if (Event.current.type == EventType.MouseMove) - Event.current.Use(); - - // Escape closes the window - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - { - Close(); - GUIUtility.ExitGUI(); - } - } - - private void DrawListBackground(Rect rect, bool even) - { - GUIStyle backgroundStyle = even ? s_Styles.listEvenBg : s_Styles.listOddBg; - GUI.Label(rect, GUIContent.none, backgroundStyle); - } - - private void DrawHeader(ref Rect rect, string text, ref bool even) - { - DrawListBackground(rect, even); - GUI.Label(rect, GUIContent.Temp(text), s_Styles.listHeaderStyle); - rect.y += EditorGUI.kSingleLineHeight; - even = !even; - } - - private void DrawSeparator(ref Rect rect, bool even) - { - DrawListBackground(new Rect(rect.x + 1, rect.y, rect.width - 2, kSeparatorHeight), even); - GUI.Label(new Rect(rect.x + 5, rect.y + 3, rect.width - 10, 3), GUIContent.none, s_Styles.separator); - rect.y += kSeparatorHeight; - } - - private void Draw(float listElementWidth) - { - var drawPos = new Rect(0, 0, listElementWidth, EditorGUI.kSingleLineHeight); - - bool even = false; - - DrawHeader(ref drawPos, "Layers", ref even); - - // Everything & nothing entries - DoSpecialLayer(drawPos, true, ref even); - drawPos.y += EditorGUI.kSingleLineHeight; - DoSpecialLayer(drawPos, false, ref even); - drawPos.y += EditorGUI.kSingleLineHeight; - - // Layers - for (var i = 0; i < s_LayerNames.Count; ++i) - { - DoOneLayer(drawPos, i, ref even); - drawPos.y += EditorGUI.kSingleLineHeight; - } - - // Sorting layers, if anything else than the single default one is present - int sortingLayerCount = InternalEditorUtility.GetSortingLayerCount(); - if (sortingLayerCount > 1) - { - DrawSeparator(ref drawPos, even); - DrawHeader(ref drawPos, "Sorting Layers", ref even); - for (var i = 0; i < sortingLayerCount; ++i) - { - DoOneSortingLayer(drawPos, i, ref even); - drawPos.y += EditorGUI.kSingleLineHeight; - } - } - - // Edit Layers entry - DrawSeparator(ref drawPos, even); - DrawListBackground(drawPos, even); - if (GUI.Button(drawPos, EditorGUIUtility.TempContent("Edit Layers..."), s_Styles.menuItem)) - { - Close(); - Selection.activeObject = EditorApplication.tagManager; - GUIUtility.ExitGUI(); - } - } - - void DoSpecialLayer(Rect rect, bool all, ref bool even) - { - int visibleMask = Tools.visibleLayers; - int expectedMask = all ? m_AllLayersMask : 0; - bool visible = (visibleMask & m_AllLayersMask) == expectedMask; - bool visibleChanged, lockedChanged; - DoLayerEntry(rect, all ? "Everything" : "Nothing", even, true, false, visible, false, out visibleChanged, out lockedChanged); - if (visibleChanged) - { - Tools.visibleLayers = all ? ~0 : 0; - RepaintAllSceneViews(); - } - even = !even; - } - - void DoOneLayer(Rect rect, int index, ref bool even) - { - int visibleMask = Tools.visibleLayers; - int lockedMask = Tools.lockedLayers; - int layerMask = 1 << (s_LayerMasks[index]); - bool visible = (visibleMask & layerMask) != 0; - bool locked = (lockedMask & layerMask) != 0; - bool visibleChanged, lockedChanged; - DoLayerEntry(rect, s_LayerNames[index], even, true, true, visible, locked, out visibleChanged, out lockedChanged); - if (visibleChanged) - { - Tools.visibleLayers ^= layerMask; - RepaintAllSceneViews(); - } - if (lockedChanged) - { - Tools.lockedLayers ^= layerMask; - } - even = !even; - } - - void DoOneSortingLayer(Rect rect, int index, ref bool even) - { - bool locked = InternalEditorUtility.GetSortingLayerLocked(index); - bool visibleChanged, lockedChanged; - DoLayerEntry(rect, InternalEditorUtility.GetSortingLayerName(index), even, false, true, true, locked, out visibleChanged, out lockedChanged); - if (lockedChanged) - { - InternalEditorUtility.SetSortingLayerLocked(index, !locked); - } - even = !even; - } - - private void DoLayerEntry(Rect rect, string layerName, bool even, bool showVisible, bool showLock, bool visible, bool locked, out bool visibleChanged, out bool lockedChanged) - { - DrawListBackground(rect, even); - - EditorGUI.BeginChangeCheck(); - // text (works as visibility toggle as well) - Rect textRect = rect; - textRect.width -= kToggleSize * 2; - visible = GUI.Toggle(textRect, visible, EditorGUIUtility.TempContent(layerName), s_Styles.listTextStyle); - - // visible checkbox - var toggleRect = new Rect(rect.width - kToggleSize * 2, rect.y + (rect.height - kToggleSize) * 0.5f, kToggleSize, kToggleSize); - visibleChanged = false; - if (showVisible) - { - var oldColor = GUI.color; - var newColor = oldColor; - newColor.a = visible ? 0.6f : 0.4f; - GUI.color = newColor; - var iconRect = toggleRect; - iconRect.y += 3; - var gc = new GUIContent(string.Empty, visible ? s_Styles.visibleOn : s_Styles.visibleOff, kLayerVisible); - GUI.Toggle(iconRect, visible, gc, GUIStyle.none); - GUI.color = oldColor; - visibleChanged = EditorGUI.EndChangeCheck(); - } - - // locked checkbox - lockedChanged = false; - if (showLock) - { - toggleRect.x += kToggleSize; - EditorGUI.BeginChangeCheck(); - var oldColor = GUI.backgroundColor; - var newColor = oldColor; - if (!locked) - newColor.a *= 0.4f; - GUI.backgroundColor = newColor; - GUI.Toggle(toggleRect, locked, new GUIContent(string.Empty, kLayerLocked), s_Styles.lockButton); - GUI.backgroundColor = oldColor; - lockedChanged = EditorGUI.EndChangeCheck(); - } - } - - static void RepaintAllSceneViews() - { - foreach (SceneView sv in Resources.FindObjectsOfTypeAll(typeof(SceneView))) - sv.Repaint(); - } - } -} diff --git a/Editor/Mono/Annotation/SceneFXWindow.cs b/Editor/Mono/Annotation/SceneFXWindow.cs deleted file mode 100644 index 990bfdb82e..0000000000 --- a/Editor/Mono/Annotation/SceneFXWindow.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal class SceneFXWindow : PopupWindowContent - { - private class Styles - { - public readonly GUIStyle menuItem = "MenuItem"; - } - - private static Styles s_Styles; - private readonly SceneView m_SceneView; - - const float kFrameWidth = 1f; - - public override Vector2 GetWindowSize() - { - var windowHeight = 2f * kFrameWidth + EditorGUI.kSingleLineHeight * 6; - var windowSize = new Vector2(160, windowHeight); - return windowSize; - } - - public SceneFXWindow(SceneView sceneView) - { - m_SceneView = sceneView; - } - - public override void OnGUI(Rect rect) - { - if (m_SceneView == null || m_SceneView.sceneViewState == null) - return; - - // We do not use the layout event - if (Event.current.type == EventType.Layout) - return; - - if (s_Styles == null) - s_Styles = new Styles(); - - // Content - Draw(rect); - - // Use mouse move so we get hover state correctly in the menu item rows - if (Event.current.type == EventType.MouseMove) - Event.current.Use(); - - // Escape closes the window - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - { - editorWindow.Close(); - GUIUtility.ExitGUI(); - } - } - - private void Draw(Rect rect) - { - if (m_SceneView == null || m_SceneView.sceneViewState == null) - return; - - var drawPos = new Rect(kFrameWidth, kFrameWidth, rect.width - 2 * kFrameWidth, EditorGUI.kSingleLineHeight); - - var state = m_SceneView.sceneViewState; - - // - // scene view effect options - - DrawListElement(drawPos, "Skybox", state.showSkybox, value => state.showSkybox = value); - drawPos.y += EditorGUI.kSingleLineHeight; - - DrawListElement(drawPos, "Fog", state.showFog, value => state.showFog = value); - drawPos.y += EditorGUI.kSingleLineHeight; - - DrawListElement(drawPos, "Flares", state.showFlares, value => state.showFlares = value); - drawPos.y += EditorGUI.kSingleLineHeight; - - DrawListElement(drawPos, "Animated Materials", state.showMaterialUpdate, value => state.showMaterialUpdate = value); - drawPos.y += EditorGUI.kSingleLineHeight; - - DrawListElement(drawPos, "Image Effects", state.showImageEffects, value => state.showImageEffects = value); - drawPos.y += EditorGUI.kSingleLineHeight; - - DrawListElement(drawPos, "Particle Systems", state.showParticleSystems, value => state.showParticleSystems = value); - drawPos.y += EditorGUI.kSingleLineHeight; - } - - void DrawListElement(Rect rect, string toggleName, bool value, Action setValue) - { - EditorGUI.BeginChangeCheck(); - bool result = GUI.Toggle(rect, value, EditorGUIUtility.TempContent(toggleName), s_Styles.menuItem); - if (EditorGUI.EndChangeCheck()) - { - setValue(result); - m_SceneView.Repaint(); - } - } - } -} diff --git a/Editor/Mono/Annotation/SceneRenderModeWindow.cs b/Editor/Mono/Annotation/SceneRenderModeWindow.cs deleted file mode 100644 index e607138525..0000000000 --- a/Editor/Mono/Annotation/SceneRenderModeWindow.cs +++ /dev/null @@ -1,339 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using UnityEngine.Rendering; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - // Match EditorDrawingMode order in C++ code! - public enum DrawCameraMode - { - UserDefined = int.MinValue, - Normal = -1, - Textured = 0, - Wireframe = 1, - TexturedWire = 2, - ShadowCascades = 3, - RenderPaths = 4, - AlphaChannel = 5, - Overdraw = 6, - Mipmaps = 7, - DeferredDiffuse = 8, - DeferredSpecular = 9, - DeferredSmoothness = 10, - DeferredNormal = 11, - - [Obsolete("Renamed to better distinguish this mode from new Progressive baked modes. Please use RealtimeCharting instead. (UnityUpgradable) -> RealtimeCharting", true)] - Charting = -12, - RealtimeCharting = 12, - - Systems = 13, - - [Obsolete("Renamed to better distinguish this mode from new Progressive baked modes. Please use RealtimeAlbedo instead. (UnityUpgradable) -> RealtimeAlbedo", true)] - Albedo = -14, - RealtimeAlbedo = 14, - - [Obsolete("Renamed to better distinguish this mode from new Progressive baked modes. Please use RealtimeEmissive instead. (UnityUpgradable) -> RealtimeEmissive", true)] - Emissive = -15, - RealtimeEmissive = 15, - - [Obsolete("Renamed to better distinguish this mode from new Progressive baked modes. Please use RealtimeIndirect instead. (UnityUpgradable) -> RealtimeIndirect", true)] - Irradiance = -16, - RealtimeIndirect = 16, - - [Obsolete("Renamed to better distinguish this mode from new Progressive baked modes. Please use RealtimeDirectionality instead. (UnityUpgradable) -> RealtimeDirectionality", true)] - Directionality = -17, - RealtimeDirectionality = 17, - - [Obsolete("Renamed to better distinguish this mode from new Progressive baked modes. Please use BakedLightmap instead. (UnityUpgradable) -> BakedLightmap", true)] - Baked = -18, - BakedLightmap = 18, - - Clustering = 19, - LitClustering = 20, - ValidateAlbedo = 21, - ValidateMetalSpecular = 22, - ShadowMasks = 23, - LightOverlap = 24, - BakedAlbedo = 25, - BakedEmissive = 26, - BakedDirectionality = 27, - BakedTexelValidity = 28, - BakedIndices = 29, - BakedCharting = 30, - SpriteMask = 31, - BakedUVOverlap = 32, - } - - internal class SceneRenderModeWindow : PopupWindowContent - { - class Styles - { - public static GUIStyle s_MenuItem; - public static GUIStyle s_Separator; - - public static GUIStyle sMenuItem - { - get - { - if (s_MenuItem == null) - s_MenuItem = "MenuItem"; - return s_MenuItem; - } - } - - public static GUIStyle sSeparator - { - get - { - if (s_Separator == null) - s_Separator = "sv_iconselector_sep"; - return s_Separator; - } - } - - public static readonly string kShadingMode = "Shading Mode"; - public static readonly string kMiscellaneous = "Miscellaneous"; - public static readonly string kDeferred = "Deferred"; - public static readonly string kGlobalIllumination = "Global Illumination"; - public static readonly string kRealtimeGI = "Realtime Global Illumination"; - public static readonly string kBakedGI = "Baked Global Illumination"; - public static readonly string kMaterialValidation = "Material Validation"; - - public static readonly GUIContent sResolutionToggle = - EditorGUIUtility.TextContent("Show Lightmap Resolution"); - - // Map all builtin DrawCameraMode entries - // This defines the order in which the entries appear in the dropdown menu! - public static readonly SceneView.CameraMode[] sBuiltinCameraModes = - { - new SceneView.CameraMode(DrawCameraMode.Textured, "Shaded", kShadingMode), - new SceneView.CameraMode(DrawCameraMode.Wireframe, "Wireframe", kShadingMode), - new SceneView.CameraMode(DrawCameraMode.TexturedWire, "Shaded Wireframe", kShadingMode), - - new SceneView.CameraMode(DrawCameraMode.ShadowCascades, "Shadow Cascades", kMiscellaneous), - new SceneView.CameraMode(DrawCameraMode.RenderPaths, "Render Paths", kMiscellaneous), - new SceneView.CameraMode(DrawCameraMode.AlphaChannel, "Alpha Channel", kMiscellaneous), - new SceneView.CameraMode(DrawCameraMode.Overdraw, "Overdraw", kMiscellaneous), - new SceneView.CameraMode(DrawCameraMode.Mipmaps, "Mipmaps", kMiscellaneous), - new SceneView.CameraMode(DrawCameraMode.SpriteMask, "Sprite Mask", kMiscellaneous), - - new SceneView.CameraMode(DrawCameraMode.DeferredDiffuse, "Albedo", kDeferred), - new SceneView.CameraMode(DrawCameraMode.DeferredSpecular, "Specular", kDeferred), - new SceneView.CameraMode(DrawCameraMode.DeferredSmoothness, "Smoothness", kDeferred), - new SceneView.CameraMode(DrawCameraMode.DeferredNormal, "Normal", kDeferred), - - new SceneView.CameraMode(DrawCameraMode.Systems, "Systems", kGlobalIllumination), - new SceneView.CameraMode(DrawCameraMode.Clustering, "Clustering", kGlobalIllumination), - new SceneView.CameraMode(DrawCameraMode.LitClustering, "Lit Clustering", kGlobalIllumination), - new SceneView.CameraMode(DrawCameraMode.RealtimeCharting, "UV Charts", kGlobalIllumination), - - new SceneView.CameraMode(DrawCameraMode.RealtimeAlbedo, "Albedo", kRealtimeGI), - new SceneView.CameraMode(DrawCameraMode.RealtimeEmissive, "Emissive", kRealtimeGI), - new SceneView.CameraMode(DrawCameraMode.RealtimeIndirect, "Indirect", kRealtimeGI), - new SceneView.CameraMode(DrawCameraMode.RealtimeDirectionality, "Directionality", kRealtimeGI), - - new SceneView.CameraMode(DrawCameraMode.BakedLightmap, "Baked Lightmap", kBakedGI), - new SceneView.CameraMode(DrawCameraMode.BakedDirectionality, "Directionality", kBakedGI), - new SceneView.CameraMode(DrawCameraMode.ShadowMasks, "Shadowmask", kBakedGI), - new SceneView.CameraMode(DrawCameraMode.BakedAlbedo, "Albedo", kBakedGI), - new SceneView.CameraMode(DrawCameraMode.BakedEmissive, "Emissive", kBakedGI), - new SceneView.CameraMode(DrawCameraMode.BakedCharting, "UV Charts", kBakedGI), - new SceneView.CameraMode(DrawCameraMode.BakedTexelValidity, "Texel Validity", kBakedGI), - new SceneView.CameraMode(DrawCameraMode.BakedUVOverlap, "UV Overlap", kBakedGI), - new SceneView.CameraMode(DrawCameraMode.BakedIndices, "Lightmap Indices", kBakedGI), - new SceneView.CameraMode(DrawCameraMode.LightOverlap, "Light Overlap", kBakedGI), - - new SceneView.CameraMode(DrawCameraMode.ValidateAlbedo, "Validate Albedo", kMaterialValidation), - new SceneView.CameraMode(DrawCameraMode.ValidateMetalSpecular, "Validate Metal Specular", kMaterialValidation), - }; - } - - private float windowHeight - { - get - { - int headers; - int modes; - - // TODO: This needs to be fixed and we need to find a way to dif. between disabled and unsupported - if (GraphicsSettings.renderPipelineAsset != null) - { - // When using SRP, we completely hide disabled builtin modes, including headers - headers = Styles.sBuiltinCameraModes.Where(mode => m_SceneView.IsCameraDrawModeEnabled(mode)).Select(mode => mode.section).Distinct().Count() + - SceneView.userDefinedModes.Where(mode => m_SceneView.IsCameraDrawModeEnabled(mode)).Select(mode => mode.section).Distinct().Count(); - modes = Styles.sBuiltinCameraModes.Count(mode => m_SceneView.IsCameraDrawModeEnabled(mode)) + SceneView.userDefinedModes.Count(mode => m_SceneView.IsCameraDrawModeEnabled(mode)); - } - else - { - headers = Styles.sBuiltinCameraModes.Select(mode => mode.section).Distinct().Count() + SceneView.userDefinedModes.Where(mode => m_SceneView.IsCameraDrawModeEnabled(mode)).Select(mode => mode.section).Distinct().Count(); - modes = Styles.sBuiltinCameraModes.Count() + SceneView.userDefinedModes.Count(mode => m_SceneView.IsCameraDrawModeEnabled(mode)); - } - - int separators = headers - 2; - return ((headers + modes) * EditorGUI.kSingleLineHeight) + (kSeparatorHeight * separators) + kShowLightmapResolutionHeight; - } - } - - float windowWidth { get { return 205; } } - - const float kSeparatorHeight = 3; - const float kFrameWidth = 1f; - const float kHeaderHorizontalPadding = 5f; - const float kHeaderVerticalPadding = 1f; - const float kShowLightmapResolutionHeight = EditorGUI.kSingleLineHeight + kSeparatorHeight * 2; - const float kTogglePadding = 7f; - - readonly SceneView m_SceneView; - - public SceneRenderModeWindow(SceneView sceneView) - { - m_SceneView = sceneView; - } - - public override Vector2 GetWindowSize() - { - return new Vector2(windowWidth, windowHeight); - } - - public override void OnGUI(Rect rect) - { - if (m_SceneView == null || m_SceneView.sceneViewState == null) - return; - - // We do not use the layout event - if (Event.current.type == EventType.Layout) - return; - - Draw(editorWindow, rect.width); - - // Use mouse move so we get hover state correctly in the menu item rows - if (Event.current.type == EventType.MouseMove) - Event.current.Use(); - - // Escape closes the window - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - { - editorWindow.Close(); - GUIUtility.ExitGUI(); - } - } - - private void DrawSeparator(ref Rect rect) - { - var labelRect = rect; - labelRect.x += kHeaderHorizontalPadding; - labelRect.y += kSeparatorHeight; - labelRect.width -= kHeaderHorizontalPadding * 2; - labelRect.height = kSeparatorHeight; - - GUI.Label(labelRect, GUIContent.none, Styles.sSeparator); - rect.y += kSeparatorHeight; - } - - private void DrawHeader(ref Rect rect, GUIContent label) - { - var labelRect = rect; - labelRect.y += kHeaderVerticalPadding; - labelRect.x += kHeaderHorizontalPadding; - labelRect.width = EditorStyles.miniLabel.CalcSize(label).x; - labelRect.height = EditorStyles.miniLabel.CalcSize(label).y; - GUI.Label(labelRect, label, EditorStyles.miniLabel); - rect.y += EditorGUI.kSingleLineHeight; - } - - private void Draw(EditorWindow caller, float listElementWidth) - { - var drawPos = new Rect(0, 0, listElementWidth, EditorGUI.kSingleLineHeight); - bool usingScriptableRenderPipeline = (GraphicsSettings.renderPipelineAsset != null); - string lastSection = null; - - foreach (SceneView.CameraMode mode in SceneView.userDefinedModes.OrderBy(mode => mode.section).Concat(Styles.sBuiltinCameraModes)) - { - // Draw separators and headers - if (usingScriptableRenderPipeline && mode.drawMode != DrawCameraMode.UserDefined && !m_SceneView.IsCameraDrawModeEnabled(mode)) - // When using SRP, we completely hide disabled builtin modes, including headers - continue; - - if (lastSection != mode.section) - { - // Draw header for new section - if (lastSection != null) - // Don't draw separator before first section - DrawSeparator(ref drawPos); - DrawHeader(ref drawPos, EditorGUIUtility.TextContent(mode.section)); - lastSection = mode.section; - } - - using (new EditorGUI.DisabledScope(!m_SceneView.IsCameraDrawModeEnabled(mode))) - { - DoBuiltinMode(caller, ref drawPos, mode); - } - } - - bool disabled = (m_SceneView.cameraMode.drawMode < DrawCameraMode.RealtimeCharting) || - !IsModeEnabled(m_SceneView.cameraMode.drawMode); - DoResolutionToggle(drawPos, disabled); - } - - bool IsModeEnabled(DrawCameraMode mode) - { - return m_SceneView.IsCameraDrawModeEnabled(GetBuiltinCameraMode(mode)); - } - - void DoResolutionToggle(Rect rect, bool disabled) - { - // Bg - GUI.Label(new Rect(kFrameWidth, rect.y, windowWidth - kFrameWidth * 2, kShowLightmapResolutionHeight), "", EditorStyles.inspectorBig); - - rect.y += kSeparatorHeight; - rect.x += kTogglePadding; - - using (new EditorGUI.DisabledScope(disabled)) - { - EditorGUI.BeginChangeCheck(); - bool showResolution = GUI.Toggle(rect, LightmapVisualization.showResolution, Styles.sResolutionToggle); - if (EditorGUI.EndChangeCheck()) - { - LightmapVisualization.showResolution = showResolution; - SceneView.RepaintAll(); - } - } - } - - void DoBuiltinMode(EditorWindow caller, ref Rect rect, SceneView.CameraMode mode) - { - using (new EditorGUI.DisabledScope(!m_SceneView.CheckDrawModeForRenderingPath(mode.drawMode))) - { - EditorGUI.BeginChangeCheck(); - - GUI.Toggle(rect, m_SceneView.cameraMode == mode, EditorGUIUtility.TextContent(mode.name), Styles.sMenuItem); - if (EditorGUI.EndChangeCheck()) - { - m_SceneView.cameraMode = mode; - m_SceneView.Repaint(); - GUIUtility.ExitGUI(); - } - - rect.y += EditorGUI.kSingleLineHeight; - } - } - - public static GUIContent GetGUIContent(DrawCameraMode drawCameraMode) - { - if (drawCameraMode == DrawCameraMode.UserDefined) - return GUIContent.none; - return EditorGUIUtility.TextContent(Styles.sBuiltinCameraModes.Single(mode => mode.drawMode == drawCameraMode).name); - } - - internal static SceneView.CameraMode GetBuiltinCameraMode(DrawCameraMode drawMode) - { - return Styles.sBuiltinCameraModes.Single(mode => mode.drawMode == drawMode); - } - } -} diff --git a/Editor/Mono/AssembleEditorSkin.cs b/Editor/Mono/AssembleEditorSkin.cs deleted file mode 100644 index 02f6dfa4e9..0000000000 --- a/Editor/Mono/AssembleEditorSkin.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Reflection; -using UnityEditorInternal; - -namespace UnityEditor -{ - // Class used by Tools/build_resources to assemble the skins from all images and source skins. - // Main entry point is DoIt, but there's also some UI that's part of developer builds. That UI is mainly for tweaking, etc. - // If you find values using the UI, you need to enter them into the constants below (as build_resources just uses those). - class AssembleEditorSkin : EditorWindow - { - // Called from c++ - public static void DoIt() - { - // This menu item is created by a script in the editor_resources project - EditorApplication.ExecuteMenuItem("Tools/Regenerate Editor Skins Now"); - } - - // Called from c++ - static void RegenerateAllIconsWithMipLevels() - { - GenerateIconsWithMipLevels.GenerateAllIconsWithMipLevels(); - } - - // Called from c++ - static void RegenerateSelectedIconsWithMipLevels() - { - GenerateIconsWithMipLevels.GenerateSelectedIconsWithMips(); - } - } -} diff --git a/Editor/Mono/AssemblyHelper.cs b/Editor/Mono/AssemblyHelper.cs deleted file mode 100644 index 094342ac49..0000000000 --- a/Editor/Mono/AssemblyHelper.cs +++ /dev/null @@ -1,419 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Collections.Generic; - -using Mono.Cecil; -using UnityEditor.Modules; -using UnityEditor.Scripting.Compilers; -using UnityEngine; - -namespace UnityEditor -{ - internal partial class AssemblyHelper - { - static readonly Type[] ExtendableScriptTypes = { typeof(MonoBehaviour), typeof(ScriptableObject), typeof(Experimental.AssetImporters.ScriptedImporter) }; - - // Check if assmebly internal name doesn't match file name, and show the warning. - static public void CheckForAssemblyFileNameMismatch(string assemblyPath) - { - string fileName = Path.GetFileNameWithoutExtension(assemblyPath); - string assemblyName = ExtractInternalAssemblyName(assemblyPath); - - if (string.IsNullOrEmpty(assemblyName)) - return; - - if (fileName != assemblyName) - { - Debug.LogWarning("Assembly '" + assemblyName + "' has non matching file name: '" + Path.GetFileName(assemblyPath) + "'. This can cause build issues on some platforms."); - } - } - - static public string[] GetNamesOfAssembliesLoadedInCurrentDomain() - { - var assemblies = AppDomain.CurrentDomain.GetAssemblies(); - var locations = new List(); - foreach (var a in assemblies) - { - try - { - locations.Add(a.Location); - } - catch (NotSupportedException) - { - //we have some "dynamic" assmeblies that do not have a filename - } - } - return locations.ToArray(); - } - - static public string ExtractInternalAssemblyName(string path) - { - try - { - AssemblyDefinition definition = AssemblyDefinition.ReadAssembly(path); - return definition.Name.Name; - } - catch - { - return ""; // Possible on just deleted FacebookSDK - } - } - - static AssemblyDefinition GetAssemblyDefinitionCached(string path, Dictionary cache) - { - if (cache.ContainsKey(path)) - return cache[path]; - - AssemblyDefinition definition = AssemblyDefinition.ReadAssembly(path); - cache[path] = definition; - return definition; - } - - static private bool CouldBelongToDotNetOrWindowsRuntime(string assemblyPath) - { - return assemblyPath.IndexOf("mscorlib.dll") != -1 || - assemblyPath.IndexOf("System.") != -1 || - assemblyPath.IndexOf("Windows.dll") != -1 || - assemblyPath.IndexOf("Microsoft.") != -1 || - assemblyPath.IndexOf("Windows.") != -1 || - assemblyPath.IndexOf("WinRTLegacy.dll") != -1 || - assemblyPath.IndexOf("platform.dll") != -1; - } - - static private bool IgnoreAssembly(string assemblyPath, BuildTarget target) - { - if (target == BuildTarget.WSAPlayer) - { - if (CouldBelongToDotNetOrWindowsRuntime(assemblyPath)) - return true; - } - else if (target == BuildTarget.XboxOne) - { - var profile = PlayerSettings.GetApiCompatibilityLevel(BuildTargetGroup.XboxOne); - if (profile == ApiCompatibilityLevel.NET_4_6 || profile == ApiCompatibilityLevel.NET_Standard_2_0) - { - if (CouldBelongToDotNetOrWindowsRuntime(assemblyPath)) - return true; - } - } - - return IsInternalAssembly(assemblyPath); - } - - static private void AddReferencedAssembliesRecurse(string assemblyPath, List alreadyFoundAssemblies, string[] allAssemblyPaths, string[] foldersToSearch, Dictionary cache, BuildTarget target) - { - if (IgnoreAssembly(assemblyPath, target)) - return; - - if (!File.Exists(assemblyPath)) - return; - - AssemblyDefinition assembly = GetAssemblyDefinitionCached(assemblyPath, cache); - if (assembly == null) - throw new System.ArgumentException("Referenced Assembly " + Path.GetFileName(assemblyPath) + " could not be found!"); - - // Ignore it if we already added the assembly - if (alreadyFoundAssemblies.IndexOf(assemblyPath) != -1) - return; - - alreadyFoundAssemblies.Add(assemblyPath); - - var architectureSpecificPlugins = PluginImporter.GetImporters(target).Where(i => - { - var cpu = i.GetPlatformData(target, "CPU"); - return !string.IsNullOrEmpty(cpu) && !string.Equals(cpu, "AnyCPU", StringComparison.InvariantCultureIgnoreCase); - }).Select(i => Path.GetFileName(i.assetPath)).Distinct(); - - // Go through all referenced assemblies - foreach (AssemblyNameReference referencedAssembly in assembly.MainModule.AssemblyReferences) - { - // Special cases for Metro - if (referencedAssembly.Name == "BridgeInterface") continue; - if (referencedAssembly.Name == "WinRTBridge") continue; - if (referencedAssembly.Name == "UnityEngineProxy") continue; - if (IgnoreAssembly(referencedAssembly.Name + ".dll", target)) continue; - - string foundPath = FindAssemblyName(referencedAssembly.FullName, referencedAssembly.Name, allAssemblyPaths, foldersToSearch, cache); - - if (foundPath == "") - { - // Ignore architecture specific plugin references - var found = false; - foreach (var extension in new[] { ".dll", ".winmd" }) - { - if (architectureSpecificPlugins.Any(p => string.Equals(p, referencedAssembly.Name + extension, StringComparison.InvariantCultureIgnoreCase))) - { - found = true; - break; - } - } - if (found) - continue; - throw new System.ArgumentException(string.Format("The Assembly {0} is referenced by {1} ('{2}'). But the dll is not allowed to be included or could not be found.", - referencedAssembly.Name, - assembly.MainModule.Assembly.Name.Name, - assemblyPath)); - } - - AddReferencedAssembliesRecurse(foundPath, alreadyFoundAssemblies, allAssemblyPaths, foldersToSearch, cache, target); - } - } - - static string FindAssemblyName(string fullName, string name, string[] allAssemblyPaths, string[] foldersToSearch, Dictionary cache) - { - // Search in provided assemblies - for (int i = 0; i < allAssemblyPaths.Length; i++) - { - if (!File.Exists(allAssemblyPaths[i])) - continue; - - AssemblyDefinition definition = GetAssemblyDefinitionCached(allAssemblyPaths[i], cache); - if (definition.MainModule.Assembly.Name.Name == name) - return allAssemblyPaths[i]; - } - - // Search in GAC - foreach (string folder in foldersToSearch) - { - string pathInGacFolder = Path.Combine(folder, name + ".dll"); - if (File.Exists(pathInGacFolder)) - return pathInGacFolder; - } - return ""; - } - - static public string[] FindAssembliesReferencedBy(string[] paths, string[] foldersToSearch, BuildTarget target) - { - List unique = new List(); - string[] allAssemblyPaths = paths; - - var cache = new Dictionary(); - for (int i = 0; i < paths.Length; i++) - AddReferencedAssembliesRecurse(paths[i], unique, allAssemblyPaths, foldersToSearch, cache, target); - - for (int i = 0; i < paths.Length; i++) - unique.Remove(paths[i]); - - return unique.ToArray(); - } - - static public string[] FindAssembliesReferencedBy(string path, string[] foldersToSearch, BuildTarget target) - { - string[] tmp = new string[1]; - tmp[0] = path; - return FindAssembliesReferencedBy(tmp, foldersToSearch, target); - } - - static public bool IsUnityEngineModule(AssemblyDefinition assembly) - { - return assembly.CustomAttributes.Any(a => a.AttributeType.FullName == typeof(UnityEngineModuleAssembly).FullName); - } - - static public bool IsUnityEngineModule(Assembly assembly) - { - return assembly.GetCustomAttributes(typeof(UnityEngineModuleAssembly), false).Length > 0; - } - - private static bool IsTypeAUserExtendedScript(TypeReference type) - { - if (type == null || type.FullName == "System.Object") - return false; - - foreach (var extendableScriptType in ExtendableScriptTypes) - { - if (type.Name == extendableScriptType.Name && type.Namespace == extendableScriptType.Namespace) - return true; - } - - try - { - var typeDefinition = type.Resolve(); - - if (typeDefinition != null) - return IsTypeAUserExtendedScript(typeDefinition.BaseType); - } - catch (AssemblyResolutionException) - { - // just eat exception if we fail to load assembly here. - // failure should be handled better in other places. - } - - return false; - } - - public static void ExtractAllClassesThatAreUserExtendedScripts(string path, out string[] classNamesArray, out string[] classNameSpacesArray, out string[] originalClassNameSpacesArray) - { - List classNames = new List(); - List nameSpaces = new List(); - List originalNamespaces = new List(); - var readerParameters = new ReaderParameters(); - - // this will resolve any types in assemblies within the same directory as the type's assembly - // or any folder which contains a currently available precompiled dll - var assemblyResolver = new DefaultAssemblyResolver(); - assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(path)); - - // Add the path to all available precompiled assemblies - var group = EditorUserBuildSettings.activeBuildTargetGroup; - var target = EditorUserBuildSettings.activeBuildTarget; - var precompiledAssemblies = UnityEditorInternal.InternalEditorUtility.GetPrecompiledAssemblies(true, group, target); - HashSet searchPaths = new HashSet(); - foreach (var asm in precompiledAssemblies) - searchPaths.Add(Path.GetDirectoryName(asm.Path)); - foreach (var asmpath in searchPaths) - assemblyResolver.AddSearchDirectory(asmpath); - - readerParameters.AssemblyResolver = assemblyResolver; - - AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(path, readerParameters); - foreach (ModuleDefinition module in assembly.Modules) - { - foreach (TypeDefinition type in module.Types) - { - TypeReference baseType = type.BaseType; - - try - { - if (IsTypeAUserExtendedScript(baseType)) - { - classNames.Add(type.Name); - nameSpaces.Add(type.Namespace); - - var originalNamespace = string.Empty; - var attribute = type.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == typeof(UnityEngine.Scripting.APIUpdating.MovedFromAttribute).FullName); - - if (attribute != null) - { - originalNamespace = (string)attribute.ConstructorArguments[0].Value; - } - - originalNamespaces.Add(originalNamespace); - } - } - catch (Exception) - { - Debug.LogError("Failed to extract " + type.FullName + " class of base type " + baseType.FullName + " when inspecting " + path); - } - } - } - - classNamesArray = classNames.ToArray(); - classNameSpacesArray = nameSpaces.ToArray(); - originalClassNameSpacesArray = originalNamespaces.ToArray(); - } - - /// Extract information about all types in the specified assembly, searchDirs might be used to resolve dependencies. - static public AssemblyTypeInfoGenerator.ClassInfo[] ExtractAssemblyTypeInfo(BuildTarget targetPlatform, bool isEditor, string assemblyPathName, string[] searchDirs) - { - try - { - var target = ModuleManager.GetTargetStringFromBuildTarget(targetPlatform); - var extension = ModuleManager.GetCompilationExtension(target); - var extraPaths = extension.GetCompilerExtraAssemblyPaths(isEditor, assemblyPathName); - if (extraPaths != null && extraPaths.Length > 0) - { - var dirs = new List(searchDirs); - dirs.AddRange(extraPaths); - searchDirs = dirs.ToArray(); - } - var assemblyResolver = extension.GetAssemblyResolver(isEditor, assemblyPathName, searchDirs); - - AssemblyTypeInfoGenerator gen; - if (assemblyResolver == null) - { - gen = new AssemblyTypeInfoGenerator(assemblyPathName, searchDirs); - } - else - { - gen = new AssemblyTypeInfoGenerator(assemblyPathName, assemblyResolver); - } - - return gen.GatherClassInfo(); - } - catch (System.Exception ex) - { - throw new Exception("ExtractAssemblyTypeInfo: Failed to process " + assemblyPathName + ", " + ex); - } - } - - internal static Type[] GetTypesFromAssembly(Assembly assembly) - { - if (assembly == null) - return new Type[] {}; - try - { - return assembly.GetTypes(); - } - catch (ReflectionTypeLoadException) - { - return new Type[] {}; - } - } - - internal static IEnumerable FindImplementors(Assembly assembly) where T : class - { - Type interfaze = typeof(T); - foreach (Type type in AssemblyHelper.GetTypesFromAssembly(assembly)) - { - if (/*type.IsNotPublic - future! ||*/ type.IsInterface || type.IsAbstract || !interfaze.IsAssignableFrom(type)) - continue; - T module = null; - - if (typeof(ScriptableObject).IsAssignableFrom(type)) - module = ScriptableObject.CreateInstance(type) as T; - else - module = Activator.CreateInstance(type) as T; - if (module != null) - yield return module; - } - } - - public static bool IsManagedAssembly(string file) - { - UnityEditorInternal.DllType type = UnityEditorInternal.InternalEditorUtility.DetectDotNetDll(file); - return type != UnityEditorInternal.DllType.Unknown && type != UnityEditorInternal.DllType.Native; - } - - public static bool IsInternalAssembly(string file) - { - return UnityEditor.Modules.ModuleManager.IsRegisteredModule(file) || - ModuleUtils.GetAdditionalReferencesForUserScripts().Any(p => p.Equals(file)); - } - - const int kDefaultDepth = 10; - internal static ICollection FindAssemblies(string basePath) - { - return FindAssemblies(basePath, kDefaultDepth); - } - - internal static ICollection FindAssemblies(string basePath, int maxDepth) - { - var assemblies = new List(); - - if (0 == maxDepth) - return assemblies; - - try - { - DirectoryInfo directory = new DirectoryInfo(basePath); - assemblies.AddRange(directory.GetFiles() - .Where(file => IsManagedAssembly(file.FullName)) - .Select(file => file.FullName)); - foreach (DirectoryInfo subdirectory in directory.GetDirectories()) - assemblies.AddRange(FindAssemblies(subdirectory.FullName, maxDepth - 1)); - } - catch (Exception) - { - // Return what we have now - } - - return assemblies; - } - } -} diff --git a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs deleted file mode 100644 index b78bc6700c..0000000000 --- a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Runtime.CompilerServices; -using UnityEngine; - -// ADD_NEW_PLATFORM_HERE -[assembly: InternalsVisibleTo("UnityEditor.Advertisements")] -[assembly: InternalsVisibleTo("UnityEditor.UIAutomation")] -[assembly: InternalsVisibleTo("Unity.Burst")] -[assembly: InternalsVisibleTo("Unity.Burst.Editor")] -[assembly: InternalsVisibleTo("Unity.PackageManager")] -[assembly: InternalsVisibleTo("Unity.PackageManagerStandalone")] -[assembly: InternalsVisibleTo("Unity.Automation")] -[assembly: InternalsVisibleTo("Unity.PureCSharpTests")] -[assembly: InternalsVisibleTo("Unity.IntegrationTests")] -[assembly: InternalsVisibleTo("Unity.DeploymentTests.Services")] -[assembly: InternalsVisibleTo("Unity.IntegrationTests.UnityAnalytics")] -[assembly: InternalsVisibleTo("UnityEditor.Graphs")] -[assembly: InternalsVisibleTo("UnityEditor.WSA.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.iOS.Extensions.Common")] -[assembly: InternalsVisibleTo("UnityEditor.iOS.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.AppleTV.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.Android.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.Tizen.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.XboxOne.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.PSP2.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.PS4.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.WebGL.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.LinuxStandalone.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.WindowsStandalone.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.OSXStandalone.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.Networking")] -[assembly: InternalsVisibleTo("UnityEngine.Networking")] -[assembly: InternalsVisibleTo("UnityEditor.Analytics")] -[assembly: InternalsVisibleTo("UnityEditor.Purchasing")] -[assembly: InternalsVisibleTo("UnityEditor.N3DS.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.Switch.Extensions")] -[assembly: InternalsVisibleTo("UnityEditor.EditorTestsRunner")] -[assembly: InternalsVisibleTo("UnityEditor.TestRunner")] -[assembly: InternalsVisibleTo("UnityEngine.TestRunner")] -[assembly: InternalsVisibleTo("UnityEditor.TreeEditor")] -[assembly: InternalsVisibleTo("UnityEditor.Timeline")] -[assembly: InternalsVisibleTo("UnityEditor.VR")] -[assembly: InternalsVisibleTo("Unity.RuntimeTests")] -[assembly: InternalsVisibleTo("Unity.RuntimeTests.Framework")] -[assembly: InternalsVisibleTo("UnityEditor.Facebook.Extensions")] -[assembly: InternalsVisibleTo("Assembly-CSharp-Editor-firstpass-testable")] -[assembly: InternalsVisibleTo("Assembly-CSharp-Editor-testable")] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] -[assembly: InternalsVisibleTo("UnityEditor.InteractiveTutorialsFramework")] -[assembly: InternalsVisibleTo("UnityEditor.GoogleAudioSpatializer")] -[assembly: InternalsVisibleTo("UnityEditor.Networking")] -[assembly: InternalsVisibleTo("UnityEditor.UI")] -[assembly: InternalsVisibleTo("UnityEditor.AR")] -[assembly: InternalsVisibleTo("UnityEditor.SpatialTracking")] -[assembly: InternalsVisibleTo("UnityEditor.HoloLens")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.001")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.002")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.003")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.004")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.005")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.006")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.007")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.008")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.009")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.010")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.011")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.012")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.013")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.014")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.015")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.016")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.017")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.018")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.019")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.020")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.021")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.022")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.023")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridge.024")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridgeDev.001")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridgeDev.002")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridgeDev.003")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridgeDev.004")] -[assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridgeDev.005")] - - -[assembly: AssemblyIsEditorAssembly] diff --git a/Editor/Mono/AssemblyReloadEvents.cs b/Editor/Mono/AssemblyReloadEvents.cs deleted file mode 100644 index 9a908f5235..0000000000 --- a/Editor/Mono/AssemblyReloadEvents.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Scripting; - -namespace UnityEditor -{ - public static class AssemblyReloadEvents - { - public delegate void AssemblyReloadCallback(); - public static event AssemblyReloadCallback beforeAssemblyReload; - public static event AssemblyReloadCallback afterAssemblyReload; - - [RequiredByNativeCode] - static void OnBeforeAssemblyReload() - { - if (beforeAssemblyReload != null) - beforeAssemblyReload(); - } - - [RequiredByNativeCode] - static void OnAfterAssemblyReload() - { - if (afterAssemblyReload != null) - afterAssemblyReload(); - } - } -} diff --git a/Editor/Mono/AssetDatabase/AssetDatabase.bindings.cs b/Editor/Mono/AssetDatabase/AssetDatabase.bindings.cs deleted file mode 100644 index 019c904982..0000000000 --- a/Editor/Mono/AssetDatabase/AssetDatabase.bindings.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - public enum ForceReserializeAssetsOptions - { - ReserializeAssets = 1 << 0, - ReserializeMetadata = 1 << 1, - ReserializeAssetsAndMetadata = ReserializeAssets | ReserializeMetadata - } - - [NativeHeader("Modules/AssetDatabase/Editor/Public/AssetDatabaseUtility.h")] - public partial class AssetDatabase - { - [FreeFunction("AssetDatabase::ReSerializeAssetsForced")] - extern private static void ReSerializeAssetsForced(GUID[] guids, ForceReserializeAssetsOptions options); - - public static void ForceReserializeAssets(IEnumerable assetPaths, ForceReserializeAssetsOptions options = ForceReserializeAssetsOptions.ReserializeAssetsAndMetadata) - { - if (EditorApplication.isPlaying) - throw new Exception("AssetDatabase.ForceReserializeAssets cannot be used when in play mode"); - - HashSet guidList = new HashSet(); - - foreach (string path in assetPaths) - { - if (path == "") - continue; - - if (path.Equals("Assets") || path.Equals("Packages")) - continue; - - if (AssetDatabase.IsPackagedAssetPath(path)) - continue; - - if (InternalEditorUtility.IsUnityExtensionRegistered(path)) - continue; - - GUID guid = new GUID(AssetPathToGUID(path)); - - if (!guid.Empty()) - { - guidList.Add(guid); - } - else - { - if (File.Exists(path)) - { - Debug.LogWarningFormat("Cannot reserialize file \"{0}\": the file is not in the AssetDatabase. Skipping.", path); - } - else - { - Debug.LogWarningFormat("Cannot reserialize file \"{0}\": the file does not exist. Skipping.", path); - } - } - } - - GUID[] guids = new GUID[guidList.Count]; - guidList.CopyTo(guids); - ReSerializeAssetsForced(guids, options); - } - - [FreeFunction("AssetDatabase::GetGUIDAndLocalIdentifierInFile")] - extern private static bool GetGUIDAndLocalIdentifierInFile(int instanceID, out GUID outGuid, out long outLocalId); - - public static bool TryGetGUIDAndLocalFileIdentifier(UnityEngine.Object obj, out string guid, out int localId) - { - return TryGetGUIDAndLocalFileIdentifier(obj.GetInstanceID(), out guid, out localId); - } - - public static bool TryGetGUIDAndLocalFileIdentifier(int instanceID, out string guid, out int localId) - { - GUID uguid; - long fileid; - bool res = GetGUIDAndLocalIdentifierInFile(instanceID, out uguid, out fileid); - guid = uguid.ToString(); - localId = (int)fileid; - return res; - } - - public static void ForceReserializeAssets() - { - ForceReserializeAssets(GetAllAssetPaths()); - } - } -} diff --git a/Editor/Mono/AssetDatabase/AssetDatabase.cs b/Editor/Mono/AssetDatabase/AssetDatabase.cs deleted file mode 100644 index ebe376d4ee..0000000000 --- a/Editor/Mono/AssetDatabase/AssetDatabase.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Scripting; - -namespace UnityEditor -{ - public sealed partial class AssetDatabase - { - // Delegate to be called from [[AssetDatabase.ImportPackage]] callbacks - public delegate void ImportPackageCallback(string packageName); - - // Delegate to be called from [[AssetDatabase.ImportPackage]] callbacks in the event of failure - public delegate void ImportPackageFailedCallback(string packageName, string errorMessage); - - // Delegate to be called when package import begins - public static event ImportPackageCallback importPackageStarted; - - // Delegate to be called when package import completes - public static event ImportPackageCallback importPackageCompleted; - - // Delegate to be called when package import is cancelled - public static event ImportPackageCallback importPackageCancelled; - - // Delegate to be called when package import fails - public static event ImportPackageFailedCallback importPackageFailed; - - [RequiredByNativeCode] - private static void Internal_CallImportPackageStarted(string packageName) - { - if (importPackageStarted != null) - importPackageStarted(packageName); - } - - [RequiredByNativeCode] - private static void Internal_CallImportPackageCompleted(string packageName) - { - if (importPackageCompleted != null) - importPackageCompleted(packageName); - } - - [RequiredByNativeCode] - private static void Internal_CallImportPackageCancelled(string packageName) - { - if (importPackageCancelled != null) - importPackageCancelled(packageName); - } - - [RequiredByNativeCode] - private static void Internal_CallImportPackageFailed(string packageName, string errorMessage) - { - if (importPackageFailed != null) - importPackageFailed(packageName, errorMessage); - } - } -} diff --git a/Editor/Mono/AssetDatabase/AssetDatabase.deprecated.cs b/Editor/Mono/AssetDatabase/AssetDatabase.deprecated.cs deleted file mode 100644 index 80ce597ddd..0000000000 --- a/Editor/Mono/AssetDatabase/AssetDatabase.deprecated.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Runtime.InteropServices; - -namespace UnityEditor -{ - partial class AssetDatabase - { - // Gets the path to the text .meta file associated with an asset - [Obsolete("GetTextMetaDataPathFromAssetPath has been renamed to GetTextMetaFilePathFromAssetPath (UnityUpgradable) -> GetTextMetaFilePathFromAssetPath(*)")] - public static string GetTextMetaDataPathFromAssetPath(string path) { return null; } - } - - // Used to be part of Asset Server, and public API for some reason. - [Obsolete("AssetStatus enum is not used anymore (Asset Server has been removed)")] - public enum AssetStatus - { - Calculating = -1, - ClientOnly = 0, - ServerOnly = 1, - Unchanged = 2, - Conflict = 3, - Same = 4, - NewVersionAvailable = 5, - NewLocalVersion = 6, - RestoredFromTrash = 7, - Ignored = 8, - BadState = 9 - } - - // Used to be part of Asset Server, and public API for some reason. - [Obsolete("AssetsItem class is not used anymore (Asset Server has been removed)")] - [StructLayout(LayoutKind.Sequential)] - [System.Serializable] - public sealed class AssetsItem - { - public string guid; - public string pathName; - public string message; - public string exportedAssetPath; - public string guidFolder; - public int enabled; - public int assetIsDir; - public int changeFlags; - public string previewPath; - public int exists; - } -} - diff --git a/Editor/Mono/AssetDatabase/AssetDatabaseSearching.cs b/Editor/Mono/AssetDatabase/AssetDatabaseSearching.cs deleted file mode 100644 index b552adeb68..0000000000 --- a/Editor/Mono/AssetDatabase/AssetDatabaseSearching.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - - -namespace UnityEditor -{ - public sealed partial class AssetDatabase - { - public static string[] FindAssets(string filter) - { - return FindAssets(filter, null); - } - - public static string[] FindAssets(string filter, string[] searchInFolders) - { - SearchFilter searchFilter = new SearchFilter(); - SearchUtility.ParseSearchString(filter, searchFilter); - if (searchInFolders != null) - searchFilter.folders = searchInFolders; - - return FindAssets(searchFilter); - } - - private static string[] FindAssets(SearchFilter searchFilter) - { - if (searchFilter.folders != null && searchFilter.folders.Length > 0) - return SearchInFolders(searchFilter); - return SearchAllAssets(searchFilter); - } - - private static string[] SearchAllAssets(SearchFilter searchFilter) - { - var property = new HierarchyProperty(HierarchyType.Assets); - property.SetSearchFilter(searchFilter); - property.Reset(); - var guids = new List(); - while (property.Next(null)) - { - guids.Add(property.guid); - } - return guids.ToArray(); - } - - private static string[] SearchInFolders(SearchFilter searchFilter) - { - var property = new HierarchyProperty(HierarchyType.Assets); - var guids = new List(); - foreach (string folderPath in searchFilter.folders) - { - // Set empty filter to ensure we search all assets to find folder - property.SetSearchFilter(new SearchFilter()); - int folderInstanceID = GetMainAssetInstanceID(folderPath); - if (property.Find(folderInstanceID, null)) - { - // Set filter after we found the folder - property.SetSearchFilter(searchFilter); - int folderDepth = property.depth; - int[] expanded = null; // enter all children of folder - while (property.NextWithDepthCheck(expanded, folderDepth + 1)) - { - guids.Add(property.guid); - } - } - else - { - Debug.LogWarning("AssetDatabase.FindAssets: Folder not found: '" + folderPath + "'"); - } - } - return guids.ToArray(); - } - } -} diff --git a/Editor/Mono/AssetDatabase/AssetImportInProgressProxy.bindings.cs b/Editor/Mono/AssetDatabase/AssetImportInProgressProxy.bindings.cs deleted file mode 100644 index ede1d22e40..0000000000 --- a/Editor/Mono/AssetDatabase/AssetImportInProgressProxy.bindings.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; -using UnityEngine; - -namespace UnityEditor -{ - [NativeType(Header = "Modules/AssetDatabase/Editor/Public/AssetImportInProgressProxy.h")] - class AssetImportInProgressProxy : UnityEngine.Object - { - public extern GUID asset - { - [NativeMethod("GetAsset")] - get; - [NativeMethod("SetAsset")] - set; - } - - [NativeMethod] - public extern static bool IsProxyAsset(int instanceID); - } - - [CustomEditor(typeof(AssetImportInProgressProxy))] - class AssetImportInProgressProxyEditor : Editor - { - public override void OnInspectorGUI() - { - var proxy = (AssetImportInProgressProxy)target; - - if (GUILayout.Button("Import")) - { - var mainAsset = AssetDatabase.LoadMainAssetAtGUID(proxy.asset); - Selection.activeObject = mainAsset; - //@TODO: Properly call this from C++ when asset import completes... - //EditorApplication.projectWindowChanged(); - } - } - } -} diff --git a/Editor/Mono/AssetModificationProcessor.cs b/Editor/Mono/AssetModificationProcessor.cs deleted file mode 100644 index cadf553c0a..0000000000 --- a/Editor/Mono/AssetModificationProcessor.cs +++ /dev/null @@ -1,317 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEditor.VersionControl; -using UnityEditorInternal; -using UnityEditorInternal.VersionControl; -using System.Reflection; - -namespace UnityEditor -{ - internal class AssetModificationProcessorInternal - { - enum FileMode - { - Binary, - Text - } - - static bool CheckArgumentTypes(Type[] types, MethodInfo method) - { - ParameterInfo[] parameters = method.GetParameters(); - - if (types.Length != parameters.Length) - { - Debug.LogWarning("Parameter count did not match. Expected: " + types.Length.ToString() + " Got: " + parameters.Length.ToString() + " in " + method.DeclaringType.ToString() + "." + method.Name); - return false; - } - - int i = 0; - foreach (Type type in types) - { - ParameterInfo pInfo = parameters[i]; - if (type != pInfo.ParameterType) - { - Debug.LogWarning("Parameter type mismatch at parameter " + i + ". Expected: " + type.ToString() + " Got: " + pInfo.ParameterType.ToString() + " in " + method.DeclaringType.ToString() + "." + method.Name); - return false; - } - ++i; - } - - return true; - } - - static bool CheckArgumentTypesAndReturnType(Type[] types, MethodInfo method, System.Type returnType) - { - if (returnType != method.ReturnType) - { - Debug.LogWarning("Return type mismatch. Expected: " + returnType.ToString() + " Got: " + method.ReturnType.ToString() + " in " + method.DeclaringType.ToString() + "." + method.Name); - return false; - } - - return CheckArgumentTypes(types, method); - } - - static bool CheckArguments(object[] args, MethodInfo method) - { - Type[] types = new Type[args.Length]; - - for (int i = 0; i < args.Length; i++) - types[i] = args[i].GetType(); - - return CheckArgumentTypes(types, method); - } - - static bool CheckArgumentsAndReturnType(object[] args, MethodInfo method, System.Type returnType) - { - Type[] types = new Type[args.Length]; - - for (int i = 0; i < args.Length; i++) - types[i] = args[i].GetType(); - - return CheckArgumentTypesAndReturnType(types, method, returnType); - } - -#pragma warning disable 0618 - static System.Collections.Generic.IEnumerable assetModificationProcessors = null; - static System.Collections.Generic.IEnumerable AssetModificationProcessors - { - get - { - if (assetModificationProcessors == null) - { - List processors = new List(); - processors.AddRange(EditorAssemblies.SubclassesOf(typeof(UnityEditor.AssetModificationProcessor))); - processors.AddRange(EditorAssemblies.SubclassesOf(typeof(global::AssetModificationProcessor))); - assetModificationProcessors = processors.ToArray(); - } - return assetModificationProcessors; - } - } -#pragma warning restore 0618 - - static void OnWillCreateAsset(string path) - { - foreach (var assetModificationProcessorClass in AssetModificationProcessors) - { - MethodInfo method = assetModificationProcessorClass.GetMethod("OnWillCreateAsset", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - if (method != null) - { - object[] args = { path }; - if (!CheckArguments(args, method)) - continue; - - method.Invoke(null, args); - } - } - } - - static void FileModeChanged(string[] assets, UnityEditor.VersionControl.FileMode mode) - { - // Make sure that all assets are checked out in version control and - // that we have the most recent status - if (Provider.enabled) - { - if (Provider.PromptAndCheckoutIfNeeded(assets, "")) - Provider.SetFileMode(assets, mode); - } - } - - // Postprocess on all assets once an automatic import has completed - static void OnWillSaveAssets(string[] assets, out string[] assetsThatShouldBeSaved, out string[] assetsThatShouldBeReverted, int explicitlySaveAsset) - { - assetsThatShouldBeReverted = new string[0]; - assetsThatShouldBeSaved = assets; - - bool showSaveDialog = assets.Length > 0 && EditorPrefs.GetBool("VerifySavingAssets", false) && InternalEditorUtility.isHumanControllingUs; - - // If we are only saving a single scene or prefab and the user explicitly said we should, skip the dialog. We don't need - // to verify this twice. - if (explicitlySaveAsset != 0 && assets.Length == 1 && (assets[0].EndsWith(".unity") || assets[0].EndsWith(".prefab"))) - showSaveDialog = false; - - if (showSaveDialog) - AssetSaveDialog.ShowWindow(assets, out assetsThatShouldBeSaved); - else - assetsThatShouldBeSaved = assets; - - foreach (var assetModificationProcessorClass in AssetModificationProcessors) - { - MethodInfo method = assetModificationProcessorClass.GetMethod("OnWillSaveAssets", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - if (method != null) - { - object[] args = { assetsThatShouldBeSaved }; - if (!CheckArguments(args, method)) - continue; - - string[] result = (string[])method.Invoke(null, args); - - if (result != null) - assetsThatShouldBeSaved = result; - } - } - - if (assetsThatShouldBeSaved == null) - { - return; - } - - var assetsNotOpened = new List(); - foreach (string asset in assetsThatShouldBeSaved) - { - if (!AssetDatabase.IsOpenForEdit(asset, StatusQueryOptions.ForceUpdate)) - assetsNotOpened.Add(asset); - } - assets = assetsNotOpened.ToArray(); - - // Try to checkout if needed. This may fail but is catched below. - if (assets.Length != 0 && !Provider.PromptAndCheckoutIfNeeded(assets, "")) - { - Debug.LogError("Could not check out the following files in version control before saving: " + - string.Join(", ", assets)); - assetsThatShouldBeSaved = new string[0]; - return; - } - } - - static void RequireTeamLicense() - { - if (!InternalEditorUtility.HasTeamLicense()) - throw new MethodAccessException("Requires team license"); - } - - static AssetMoveResult OnWillMoveAsset(string fromPath, string toPath, string[] newPaths, string[] NewMetaPaths) - { - AssetMoveResult finalResult = AssetMoveResult.DidNotMove; - if (!InternalEditorUtility.HasTeamLicense()) - return finalResult; - - finalResult = AssetModificationHook.OnWillMoveAsset(fromPath, toPath); - - foreach (var assetModificationProcessorClass in AssetModificationProcessors) - { - MethodInfo method = assetModificationProcessorClass.GetMethod("OnWillMoveAsset", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - if (method != null) - { - RequireTeamLicense(); - - object[] args = { fromPath, toPath }; - if (!CheckArgumentsAndReturnType(args, method, finalResult.GetType())) - continue; - - finalResult |= (AssetMoveResult)method.Invoke(null, args); - } - } - - return finalResult; - } - - static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions options) - { - AssetDeleteResult finalResult = AssetDeleteResult.DidNotDelete; - if (!InternalEditorUtility.HasTeamLicense()) - return finalResult; - - foreach (var assetModificationProcessorClass in AssetModificationProcessors) - { - MethodInfo method = assetModificationProcessorClass.GetMethod("OnWillDeleteAsset", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - if (method != null) - { - RequireTeamLicense(); - - object[] args = { assetPath, options }; - if (!CheckArgumentsAndReturnType(args, method, finalResult.GetType())) - continue; - - finalResult |= (AssetDeleteResult)method.Invoke(null, args); - } - } - - if (finalResult != AssetDeleteResult.DidNotDelete) - return finalResult; - - finalResult = AssetModificationHook.OnWillDeleteAsset(assetPath, options); - - return finalResult; - } - - internal static MethodInfo[] isOpenForEditMethods = null; - internal static MethodInfo[] GetIsOpenForEditMethods() - { - if (isOpenForEditMethods == null) - { - List mArray = new List(); - foreach (var assetModificationProcessorClass in AssetModificationProcessors) - { - MethodInfo method = assetModificationProcessorClass.GetMethod("IsOpenForEdit", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - if (method != null) - { - RequireTeamLicense(); - - string dummy = ""; - bool bool_dummy = false; - Type[] types = { dummy.GetType(), dummy.GetType().MakeByRefType() }; - if (!CheckArgumentTypesAndReturnType(types, method, bool_dummy.GetType())) - continue; - - mArray.Add(method); - } - } - - isOpenForEditMethods = mArray.ToArray(); - } - - return isOpenForEditMethods; - } - - internal static bool IsOpenForEdit(string assetPath, out string message, StatusQueryOptions statusOptions) - { - message = ""; - if (String.IsNullOrEmpty(assetPath)) - return true; // assetPath can be empty in some cases where Unity is checking for stuff in Library folder - - if (AssetDatabase.IsPackagedAssetPath(assetPath)) - { - return false; - } - - bool finalResult = AssetModificationHook.IsOpenForEdit(assetPath, out message, statusOptions); - - foreach (var method in GetIsOpenForEditMethods()) - { - object[] args = {assetPath, message}; - if (!((bool)method.Invoke(null, args))) - { - message = args[1] as string; - return false; - } - } - - return finalResult; - } - - internal static void OnStatusUpdated() - { - WindowPending.OnStatusUpdated(); - - foreach (var assetModificationProcessorClass in AssetModificationProcessors) - { - MethodInfo method = assetModificationProcessorClass.GetMethod("OnStatusUpdated", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - if (method != null) - { - RequireTeamLicense(); - - object[] args = {}; - if (!CheckArgumentsAndReturnType(args, method, typeof(void))) - continue; - - method.Invoke(null, args); - } - } - } - } -} diff --git a/Editor/Mono/AssetPipeline/AssemblyDefinitionImporter.cs b/Editor/Mono/AssetPipeline/AssemblyDefinitionImporter.cs deleted file mode 100644 index 850f67d5e6..0000000000 --- a/Editor/Mono/AssetPipeline/AssemblyDefinitionImporter.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - public sealed partial class AssemblyDefinitionImporter : AssetImporter - { - } - - public sealed partial class AssemblyDefinitionAsset : TextAsset - { - private AssemblyDefinitionAsset() {} - - private AssemblyDefinitionAsset(string text) {} - } -} diff --git a/Editor/Mono/AssetPipeline/AssetImportContext.bindings.cs b/Editor/Mono/AssetPipeline/AssetImportContext.bindings.cs deleted file mode 100644 index 36ba0794c2..0000000000 --- a/Editor/Mono/AssetPipeline/AssetImportContext.bindings.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Diagnostics; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using Debug = UnityEngine.Debug; -using Object = UnityEngine.Object; - - -namespace UnityEditor.Experimental.AssetImporters -{ - /// 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. - /// - /// 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 - /// 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 - /// 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 - [RequiredByNativeCode] - [NativeHeader("Editor/Src/AssetPipeline/AssetImportContext.h")] - public class AssetImportContext - { - // The bindings generator is setting the instance pointer in this field - internal IntPtr m_Self; - - // the context can only be instantiated in native code - AssetImportContext() {} - - public extern string assetPath { get; internal set; } - public extern BuildTarget selectedBuildTarget { get; } - - extern void LogMessage(string msg, string file, int line, UnityEngine.Object obj, bool isAnError); - - [NativeThrows] - public extern void SetMainObject(Object obj); - - public void AddObjectToAsset(string identifier, Object obj) - { - AddObjectToAsset(identifier, obj, null); - } - - [NativeThrows] - public extern void AddObjectToAsset(string identifier, Object obj, Texture2D thumbnail); - - // Create a dependency against the contents of the source asset at the provided path - // * if the asset at the path changes, it will trigger an import - // * if the asset at the path moves, it will trigger an import - internal void DependOnHashOfSourceFile(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException("path", "Cannot add a null path"); - } - - DependOnHashOfSourceFileInternal(path); - } - - [NativeName("DependOnHashOfSourceFile")] - private extern void DependOnHashOfSourceFileInternal(string path); - - // Internal for now, will be made public once UI/UX for persistent importer logs is implemented. - public void LogImportError(string msg, UnityEngine.Object obj = null) - { - AddToLog(msg, true, obj); - } - - // Internal for now, will be made public once UI/UX for persistent importer logs is implemented. - public void LogImportWarning(string msg, UnityEngine.Object obj = null) - { - AddToLog(msg, false, obj); - } - - void AddToLog(string msg, bool isAnError, UnityEngine.Object obj) - { - var st = new StackTrace(2, true); - var sf = st.GetFrame(0); - LogMessage(msg, sf.GetFileName(), sf.GetFileLineNumber(), obj, isAnError); - } - } -} diff --git a/Editor/Mono/AssetPipeline/AssetImporter.bindings.cs b/Editor/Mono/AssetPipeline/AssetImporter.bindings.cs deleted file mode 100644 index 0175ed3162..0000000000 --- a/Editor/Mono/AssetPipeline/AssetImporter.bindings.cs +++ /dev/null @@ -1,135 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using Object = UnityEngine.Object; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/AssetPipeline/AssetImporter.h")] - [NativeHeader("Editor/Src/AssetPipeline/AssetImporter.bindings.h")] - [ExcludeFromObjectFactory] - public partial class AssetImporter : Object - { - [NativeType(CodegenOptions.Custom, "MonoSourceAssetIdentifier")] - public struct SourceAssetIdentifier - { - public SourceAssetIdentifier(Object asset) - { - if (asset == null) - { - throw new ArgumentNullException("asset"); - } - - this.type = asset.GetType(); - this.name = asset.name; - } - - public SourceAssetIdentifier(Type type, string name) - { - if (type == null) - { - throw new ArgumentNullException("type"); - } - - if (name == null) - { - throw new ArgumentNullException("name"); - } - - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentException("The name is empty", "name"); - } - - this.type = type; - this.name = name; - } - - public Type type; - public string name; - } - - [NativeName("AssetPathName")] - public extern string assetPath - { - get; - } - - public extern bool importSettingsMissing - { - get; - } - - public extern ulong assetTimeStamp - { - get; - } - - public extern string userData - { - get; - set; - } - - public extern string assetBundleName - { - get; - set; - } - - public extern string assetBundleVariant - { - get; - set; - } - - [NativeName("SetAssetBundleName")] - extern public void SetAssetBundleNameAndVariant(string assetBundleName, string assetBundleVariant); - - [FreeFunction("FindAssetImporterInstanceAtAssetPath")] - extern public static AssetImporter GetAtPath(string path); - - public void SaveAndReimport() - { - AssetDatabase.ImportAsset(assetPath); - } - - [FreeFunction("AssetImporterBindings::LocalFileIDToClassID")] - extern internal static int LocalFileIDToClassID(long fileId); - - extern public void AddRemap(SourceAssetIdentifier identifier, Object externalObject); - - extern public bool RemoveRemap(SourceAssetIdentifier identifier); - - [FreeFunction("AssetImporterBindings::GetIdentifiers")] - extern private static SourceAssetIdentifier[] GetIdentifiers(AssetImporter self); - [FreeFunction("AssetImporterBindings::GetExternalObjects")] - extern private static Object[] GetExternalObjects(AssetImporter self); - - public Dictionary GetExternalObjectMap() - { - // bogdanc: this is not optimal - we should have only one call to get both the identifiers and the external objects. - // However, the new bindings do not support well output array parameters. - // FIXME: change this to a single call when the bindings are fixed - SourceAssetIdentifier[] identifiers = GetIdentifiers(this); - Object[] externalObjects = GetExternalObjects(this); - - Dictionary map = new Dictionary(); - - for (int i = 0; i < identifiers.Length; ++i) - { - map.Add(identifiers[i], externalObjects[i]); - } - - return map; - } - - [FreeFunction("AssetImporterBindings::RegisterImporter")] - extern internal static void RegisterImporter(Type importer, int importerVersion, int queuePos, string fileExt, bool supportsImportDependencyHinting); - } -} diff --git a/Editor/Mono/AssetPipeline/LocalCacheServer.cs b/Editor/Mono/AssetPipeline/LocalCacheServer.cs deleted file mode 100644 index 8dababbb4d..0000000000 --- a/Editor/Mono/AssetPipeline/LocalCacheServer.cs +++ /dev/null @@ -1,230 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Diagnostics; -using System.IO; -using System; -using System.Net; -using System.Net.Sockets; -using UnityEditor.Scripting; -using UnityEditor.Utils; -using UnityEngine; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - internal class LocalCacheServer : ScriptableSingleton - { - [SerializeField] public string path; - [SerializeField] public int port; - [SerializeField] public ulong size; - [SerializeField] public int pid = -1; - [SerializeField] public string time; - - public const string SizeKey = "LocalCacheServerSize"; - public const string PathKey = "LocalCacheServerPath"; - public const string CustomPathKey = "LocalCacheServerCustomPath"; - - public static string GetCacheLocation() - { - var cachePath = EditorPrefs.GetString(PathKey); - var enableCustomPath = EditorPrefs.GetBool(CustomPathKey); - var result = cachePath; - if (!enableCustomPath || string.IsNullOrEmpty(cachePath)) - result = Paths.Combine(OSUtil.GetDefaultCachePath(), "CacheServer"); - return result; - } - - public static void CreateCacheDirectory() - { - string cacheDirectoryPath = GetCacheLocation(); - if (Directory.Exists(cacheDirectoryPath) == false) - Directory.CreateDirectory(cacheDirectoryPath); - } - - void Create(int _port, ulong _size) - { - var nodeExecutable = Paths.Combine(EditorApplication.applicationContentsPath, "Tools", "nodejs"); - if (Application.platform == RuntimePlatform.WindowsEditor) - nodeExecutable = Paths.Combine(nodeExecutable, "node.exe"); - else - nodeExecutable = Paths.Combine(nodeExecutable, "bin", "node"); - - CreateCacheDirectory(); - path = GetCacheLocation(); - var cacheServerJs = Paths.Combine(EditorApplication.applicationContentsPath, "Tools", "CacheServer", "main.js"); - var processStartInfo = new ProcessStartInfo(nodeExecutable) - { - Arguments = "\"" + cacheServerJs + "\"" - + " --port " + _port - + " --path \"" + path - + "\" --nolegacy" - + " --monitor-parent-process " + Process.GetCurrentProcess().Id - // node.js has issues running on windows with stdout not redirected. - // so we silence logging to avoid that. And also to avoid CacheServer - // spamming the editor logs on OS X. - + " --silent" - + " --size " + _size, - UseShellExecute = false, - CreateNoWindow = true - }; - - var p = new Process(); - p.StartInfo = processStartInfo; - p.Start(); - - port = _port; - pid = p.Id; - size = _size; - time = p.StartTime.ToString(); - Save(true); - } - - public static int GetRandomUnusedPort() - { - var listener = new TcpListener(IPAddress.Any, 0); - listener.Start(); - var port = ((IPEndPoint)listener.LocalEndpoint).Port; - listener.Stop(); - return port; - } - - public static bool PingHost(string host, int port, int timeout) - { - try - { - using (var client = new TcpClient()) - { - var result = client.BeginConnect(host, port, null, null); - result.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(timeout)); - return client.Connected; - } - } - catch - { - return false; - } - } - - public static bool WaitForServerToComeAlive(int port) - { - DateTime start = DateTime.Now; - DateTime maximum = start.AddSeconds(5); - while (DateTime.Now < maximum) - { - if (PingHost("localhost", port, 10)) - { - System.Console.WriteLine("Server Came alive after {0} ms", (DateTime.Now - start).TotalMilliseconds); - return true; - } - } - return false; - } - - public static void Kill() - { - if (instance.pid == -1) - return; - - Process p = null; - try - { - p = Process.GetProcessById(instance.pid); - p.Kill(); - instance.pid = -1; - } - catch - { - // if we could not get a process, there is non alive. continue. - } - } - - public static void CreateIfNeeded() - { - // See if we can get an existing process with the PID we remembered. - Process p = null; - try - { - p = Process.GetProcessById(instance.pid); - } - catch - { - // if we could not get a process, there is non alive. continue. - } - - ulong size = (ulong)EditorPrefs.GetInt(SizeKey, 10) * 1024 * 1024 * 1024; - // Check if this process is really the one we used (and not another one reusing the PID). - if (p != null && p.StartTime.ToString() == instance.time) - { - if (instance.size == size && instance.path == GetCacheLocation()) - { - // We have a server running for this setup, which we can reuse, but make sure that the cache server directory exists in case it was cleaned earlier - CreateCacheDirectory(); - return; - } - else - { - // This server does not match our setup. Kill it, so we can start a new one. - Kill(); - } - } - - // No existing server we can use. Start a new one. - instance.Create(GetRandomUnusedPort(), size); - WaitForServerToComeAlive(instance.port); - } - - public static void Setup() - { - var mode = (CacheServerPreferences.CacheServerMode)EditorPrefs.GetInt("CacheServerMode"); - - if (mode == CacheServerPreferences.CacheServerMode.Local) - CreateIfNeeded(); - else - Kill(); - } - - [UsedByNativeCode] - public static int GetLocalCacheServerPort() - { - Setup(); - return instance.port; - } - - public static void Clear() - { - Kill(); - string cacheDirectoryPath = GetCacheLocation(); - if (Directory.Exists(cacheDirectoryPath)) - Directory.Delete(cacheDirectoryPath, true); - } - - public static bool CheckCacheLocationExists() - { - return Directory.Exists(GetCacheLocation()); - } - - public static bool CheckValidCacheLocation(string path) - { - if (Directory.Exists(path)) - { - var contents = Directory.GetFileSystemEntries(path); - foreach (var dir in contents) - { - var name = Path.GetFileName(dir).ToLower(); - if (name.Length == 2) - continue; - if (name == "temp") - continue; - if (name == ".ds_store") - continue; - if (name == "desktop.ini") - continue; - return false; - } - } - return true; - } - } -} diff --git a/Editor/Mono/AssetPipeline/ModelImporter.bindings.cs b/Editor/Mono/AssetPipeline/ModelImporter.bindings.cs deleted file mode 100644 index 3a718379db..0000000000 --- a/Editor/Mono/AssetPipeline/ModelImporter.bindings.cs +++ /dev/null @@ -1,866 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using scm = System.ComponentModel; -using uei = UnityEngine.Internal; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; -using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; - -using UnityEngine; -using Object = UnityEngine.Object; -using UnityEditor.Animations; -using System.Runtime.InteropServices; -using System; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - public enum ClipAnimationMaskType - { - CreateFromThisModel = 0, - - CopyFromOther = 1, - None = 3 - } - - [UsedByNativeCode] - [NativeType(CodegenOptions = CodegenOptions.Custom, Header = "Runtime/Animation/AvatarMask.h", IntermediateScriptingStructName = "MonoTransformMaskElement")] - [NativeHeader("Editor/Src/AssetPipeline/ModelImporting/ModelImporter.bindings.h")] - internal partial struct TransformMaskElement - { - public string path; - public float weight; - } - - [UsedByNativeCode] - [NativeType(CodegenOptions = CodegenOptions.Custom, IntermediateScriptingStructName = "MonoClipAnimationInfoCurve")] - [NativeHeader("Editor/Src/AssetPipeline/ModelImporting/ModelImporter.bindings.h")] - [StructLayout(LayoutKind.Sequential)] - public partial struct ClipAnimationInfoCurve - { - public string name; - public AnimationCurve curve; - } - - [UsedByNativeCode] - [System.Serializable] - [StructLayout(LayoutKind.Sequential)] - [NativeType(CodegenOptions = CodegenOptions.Custom, IntermediateScriptingStructName = "MonoClipAnimationInfo")] - [NativeHeader("Editor/Src/AssetPipeline/ModelImporting/ModelImporter.bindings.h")] - public sealed partial class ModelImporterClipAnimation - { - string m_TakeName; - string m_Name; - float m_FirstFrame; - float m_LastFrame; - WrapMode m_WrapMode; - int m_Loop; - - float m_OrientationOffsetY; - float m_Level; - float m_CycleOffset; - float m_AdditiveReferencePoseFrame; - - int m_HasAdditiveReferencePose; - int m_LoopTime; - int m_LoopBlend; - int m_LoopBlendOrientation; - int m_LoopBlendPositionY; - int m_LoopBlendPositionXZ; - int m_KeepOriginalOrientation; - int m_KeepOriginalPositionY; - int m_KeepOriginalPositionXZ; - int m_HeightFromFeet; - int m_Mirror; - int m_MaskType = 3; - AvatarMask m_MaskSource; - - int[] m_BodyMask; - AnimationEvent[] m_AnimationEvents; - ClipAnimationInfoCurve[] m_AdditionnalCurves; - TransformMaskElement[] m_TransformMask; - - bool m_MaskNeedsUpdating; - - public string takeName { get { return m_TakeName; } set { m_TakeName = value; } } - public string name { get { return m_Name; } set { m_Name = value; } } - public float firstFrame { get { return m_FirstFrame; } set { m_FirstFrame = value; } } - public float lastFrame { get { return m_LastFrame; } set { m_LastFrame = value; } } - - public WrapMode wrapMode { get { return m_WrapMode; } set { m_WrapMode = value; } } - - public bool loop { get { return m_Loop != 0; } set { m_Loop = value ? 1 : 0; } } - - public float rotationOffset { get { return m_OrientationOffsetY; } set { m_OrientationOffsetY = value; } } - - public float heightOffset { get { return m_Level; } set { m_Level = value; } } - - public float cycleOffset { get { return m_CycleOffset; } set { m_CycleOffset = value; } } - - public bool loopTime { get { return m_LoopTime != 0; } set { m_LoopTime = value ? 1 : 0; } } - - public bool loopPose { get { return m_LoopBlend != 0; } set { m_LoopBlend = value ? 1 : 0; } } - - public bool lockRootRotation { get { return m_LoopBlendOrientation != 0; } set { m_LoopBlendOrientation = value ? 1 : 0; } } - - public bool lockRootHeightY { get { return m_LoopBlendPositionY != 0; } set { m_LoopBlendPositionY = value ? 1 : 0; } } - - public bool lockRootPositionXZ { get { return m_LoopBlendPositionXZ != 0; } set { m_LoopBlendPositionXZ = value ? 1 : 0; } } - - public bool keepOriginalOrientation { get { return m_KeepOriginalOrientation != 0; } set { m_KeepOriginalOrientation = value ? 1 : 0; } } - - public bool keepOriginalPositionY { get { return m_KeepOriginalPositionY != 0; } set { m_KeepOriginalPositionY = value ? 1 : 0; } } - - public bool keepOriginalPositionXZ { get { return m_KeepOriginalPositionXZ != 0; } set { m_KeepOriginalPositionXZ = value ? 1 : 0; } } - - public bool heightFromFeet { get { return m_HeightFromFeet != 0; } set { m_HeightFromFeet = value ? 1 : 0; } } - - public bool mirror { get { return m_Mirror != 0; } set { m_Mirror = value ? 1 : 0; } } - - public ClipAnimationMaskType maskType { get { return (ClipAnimationMaskType)m_MaskType; } set { m_MaskType = (int)value; } } - - public AvatarMask maskSource { get { return m_MaskSource; } set { m_MaskSource = value; } } - - public AnimationEvent[] events { get { return m_AnimationEvents; } set { m_AnimationEvents = value; } } - public ClipAnimationInfoCurve[] curves { get { return m_AdditionnalCurves; } set { m_AdditionnalCurves = value; } } - - public bool maskNeedsUpdating { get { return m_MaskNeedsUpdating; } } - - public float additiveReferencePoseFrame { get { return m_AdditiveReferencePoseFrame; } set { m_AdditiveReferencePoseFrame = value; } } - public bool hasAdditiveReferencePose { get { return m_HasAdditiveReferencePose != 0; } set { m_HasAdditiveReferencePose = value ? 1 : 0; } } - - public void ConfigureMaskFromClip(ref AvatarMask mask) - { - mask.transformCount = this.m_TransformMask.Length; - for (int i = 0; i < mask.transformCount; i++) - { - mask.SetTransformPath(i, this.m_TransformMask[i].path); - mask.SetTransformActive(i, this.m_TransformMask[i].weight > 0f); - } - for (int i = 0; i < this.m_BodyMask.Length; i++) - { - mask.SetHumanoidBodyPartActive((AvatarMaskBodyPart)i, m_BodyMask[i] != 0); - } - } - - public void ConfigureClipFromMask(AvatarMask mask) - { - this.m_TransformMask = new TransformMaskElement[mask.transformCount]; - for (int i = 0; i < mask.transformCount; i++) - { - m_TransformMask[i].path = mask.GetTransformPath(i); - m_TransformMask[i].weight = mask.GetTransformActive(i) ? 1f : 0f; - } - m_BodyMask = new int[(int)AvatarMaskBodyPart.LastBodyPart]; - - for (int i = 0; i < (int)AvatarMaskBodyPart.LastBodyPart; i++) - { - m_BodyMask[i] = mask.GetHumanoidBodyPartActive((AvatarMaskBodyPart)i) ? 1 : 0; - } - } - - public override bool Equals(object o) - { - ModelImporterClipAnimation other = o as ModelImporterClipAnimation; - return other != null && takeName == other.takeName && name == other.name && firstFrame == other.firstFrame && lastFrame == other.lastFrame && m_WrapMode == other.m_WrapMode && m_Loop == other.m_Loop && - loopPose == other.loopPose && lockRootRotation == other.lockRootRotation && lockRootHeightY == other.lockRootHeightY && lockRootPositionXZ == other.lockRootPositionXZ && - mirror == other.mirror && maskType == other.maskType && maskSource == other.maskSource && additiveReferencePoseFrame == other.additiveReferencePoseFrame && hasAdditiveReferencePose == other.hasAdditiveReferencePose; - } - - public override int GetHashCode() - { - return name.GetHashCode(); - } - } - - [System.Obsolete("Use ModelImporterMaterialName, ModelImporter.materialName and ModelImporter.importMaterials instead")] - public enum ModelImporterGenerateMaterials - { - [System.Obsolete("Use ModelImporter.importMaterials=false instead")] - None = 0, - - [System.Obsolete("Use ModelImporter.importMaterials=true and ModelImporter.materialName=ModelImporterMaterialName.BasedOnTextureName instead")] - PerTexture = 1, - - [System.Obsolete("Use ModelImporter.importMaterials=true and ModelImporter.materialName=ModelImporterMaterialName.BasedOnModelNameAndMaterialName instead")] - PerSourceMaterial = 2, - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ModelImporter.h")] - public enum ModelImporterMaterialName - { - BasedOnTextureName = 0, - - BasedOnMaterialName = 1, - - BasedOnModelNameAndMaterialName = 2, - - [System.Obsolete("You should use ModelImporterMaterialName.BasedOnTextureName instead, because it it less complicated and behaves in more consistent way.")] - BasedOnTextureName_Or_ModelNameAndMaterialName = 3, - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ModelImporter.h")] - public enum ModelImporterMaterialSearch - { - Local = 0, - - RecursiveUp = 1, - - Everywhere = 2, - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ModelImporter.h")] - public enum ModelImporterMaterialLocation - { - External = 0, - InPrefab = 1 - }; - - public enum ModelImporterTangentSpaceMode - { - [System.Obsolete("Use ModelImporterNormals.Import instead")] - Import = 0, - [System.Obsolete("Use ModelImporterNormals.Calculate instead")] - Calculate = 1, - [System.Obsolete("Use ModelImporterNormals.None instead")] - None = 2, - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ImportMesh.h")] - public enum ModelImporterNormals - { - Import = 0, - - Calculate = 1, - - None = 2, - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ImportMesh.h")] - public enum ModelImporterNormalCalculationMode - { - Unweighted_Legacy, - - Unweighted, - AreaWeighted, - AngleWeighted, - AreaAndAngleWeighted - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ImportMesh.h")] - public enum ModelImporterTangents - { - Import = 0, - - CalculateLegacy = 1, - - CalculateLegacyWithSplitTangents = 4, - CalculateMikk = 3, - - None = 2, - } - - public enum ModelImporterMeshCompression - { - Off = 0, - - Low = 1, - - Medium = 2, - - High = 3, - } - - public enum ModelImporterIndexFormat - { - Auto = 0, - UInt16 = 1, - UInt32 = 2, - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ModelImporter.h")] - public enum ModelImporterAnimationCompression - { - Off = 0, - - KeyframeReduction = 1, - - KeyframeReductionAndCompression = 2, - - Optimal = 3 - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ModelImporter.h")] - public enum ModelImporterGenerateAnimations - { - None = 0, - - GenerateAnimations = 4, - - InRoot = 3, - - InOriginalRoots = 1, - - InNodes = 2 - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ModelImporter.h")] - public enum ModelImporterAnimationType - { - None = 0, - - Legacy = 1, - - Generic = 2, - - Human = 3 - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ModelImporter.h")] - public enum ModelImporterHumanoidOversampling - { - X1 = 1, - - X2 = 2, - - X4 = 4, - - X8 = 8 - } - - [UsedByNativeCode] - [NativeType(Header = "Editor/Src/Animation/HumanTemplate.h")] - public sealed partial class HumanTemplate : Object - { - public HumanTemplate() - { - Internal_Create(this); - } - - extern private static void Internal_Create([Writable] HumanTemplate self); - - extern public void Insert(string name, string templateName); - - extern public string Find(string name); - - extern public void ClearTemplate(); - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ModelImporter.h")] - [StructLayoutAttribute(LayoutKind.Sequential)] - [UsedByNativeCode] - public partial struct TakeInfo - { - public string name; - public string defaultClipName; - public float startTime; - public float stopTime; - public float bakeStartTime; - public float bakeStopTime; - public float sampleRate; - } - - [NativeType(Header = "Editor/Src/AssetPipeline/ModelImporting/ModelImporter.h")] - [NativeHeader("Editor/Src/AssetPipeline/ModelImporting/ModelImporter.bindings.h")] - [NativeHeader("Runtime/Animation/ScriptBindings/AvatarBuilder.bindings.h")] - public partial class ModelImporter : AssetImporter - { - [System.Obsolete("Use importMaterials, materialName and materialSearch instead")] - public extern ModelImporterGenerateMaterials generateMaterials - { - get; - set; - } - - public extern bool importMaterials - { - get; - set; - } - - public extern ModelImporterMaterialName materialName - { - get; - set; - } - - public extern ModelImporterMaterialSearch materialSearch - { - get; - set; - } - - public extern ModelImporterMaterialLocation materialLocation { get; set; } - - internal extern SourceAssetIdentifier[] sourceMaterials - { - [FreeFunction(Name = "ModelImporterBindings::GetSourceMaterials", HasExplicitThis = true)] - get; - } - - public extern float globalScale - { - get; - set; - } - - public extern bool isUseFileUnitsSupported - { - [NativeMethod("IsUseFileUnitsSupported")] - get; - } - - public extern bool importVisibility - { - get; - set; - } - - public extern bool useFileUnits - { - get; - set; - } - - public extern bool useFileScale - { - get; - set; - } - - [System.Obsolete("Use useFileScale instead")] - public bool isFileScaleUsed - { - get { return useFileScale; } - } - - public extern bool importBlendShapes - { - get; - set; - } - - public extern bool importCameras - { - get; - set; - } - - public extern bool importLights - { - get; - set; - } - - public extern bool addCollider - { - [NativeMethod("GetAddColliders")] - get; - [NativeMethod("SetAddColliders")] - set; - } - - public extern float normalSmoothingAngle - { - get; - set; - } - - [System.Obsolete("Please use tangentImportMode instead")] - public bool splitTangentsAcrossSeams - { - get - { - return importTangents == ModelImporterTangents.CalculateLegacyWithSplitTangents; - } - set - { - if (importTangents == ModelImporterTangents.CalculateLegacyWithSplitTangents && !value) - importTangents = ModelImporterTangents.CalculateLegacy; - else if (importTangents == ModelImporterTangents.CalculateLegacy && value) - importTangents = ModelImporterTangents.CalculateLegacyWithSplitTangents; - } - } - - public extern bool swapUVChannels - { - get; - set; - } - - public extern bool weldVertices - { - get; - set; - } - - public extern bool keepQuads - { - get; - set; - } - - public extern ModelImporterIndexFormat indexFormat - { - get; - set; - } - - public extern bool preserveHierarchy - { - get; - set; - } - - public extern bool generateSecondaryUV - { - get; - set; - } - - public extern float secondaryUVAngleDistortion - { - get; - set; - } - - public extern float secondaryUVAreaDistortion - { - get; - set; - } - - public extern float secondaryUVHardAngle - { - get; - set; - } - - public extern float secondaryUVPackMargin - { - get; - set; - } - - public extern ModelImporterGenerateAnimations generateAnimations - { - [NativeMethod("GetLegacyGenerateAnimations")] - get; - [NativeMethod("SetLegacyGenerateAnimations")] - set; - } - - public extern TakeInfo[] importedTakeInfos - { - get; - } - - public extern string[] transformPaths - { - get; - } - - public string[] referencedClips - { - get { return INTERNAL_GetReferencedClips(this); } - } - [FreeFunction("ModelImporterBindings::GetReferencedClips")] - private extern static string[] INTERNAL_GetReferencedClips(ModelImporter self); - - public extern bool isReadable - { - get; - set; - } - - public extern bool optimizeMesh - { - get; - set; - } - - [System.Obsolete("normalImportMode is deprecated. Use importNormals instead")] - public ModelImporterTangentSpaceMode normalImportMode - { - get { return (ModelImporterTangentSpaceMode)importNormals; } - set { importNormals = (ModelImporterNormals)value; } - } - - [System.Obsolete("tangentImportMode is deprecated. Use importTangents instead")] - public ModelImporterTangentSpaceMode tangentImportMode - { - get { return (ModelImporterTangentSpaceMode)importTangents; } - set { importTangents = (ModelImporterTangents)value; } - } - - public extern ModelImporterNormals importNormals - { - [NativeMethod("GetNormalImportMode")] - get; - [NativeMethod("SetNormalImportMode")] - set; - } - - public extern ModelImporterNormalCalculationMode normalCalculationMode - { - get; - set; - } - - public extern ModelImporterTangents importTangents - { - [NativeMethod("GetTangentImportMode")] - get; - [NativeMethod("SetTangentImportMode")] - set; - } - - public extern bool bakeIK - { - get; - set; - } - - public extern bool isBakeIKSupported - { - [NativeMethod("IsBakeIKSupported")] - get; - } - - [System.Obsolete("use resampleCurves instead.")] - public extern bool resampleRotations - { - [NativeMethod("GetResampleCurves")] - get; - [NativeMethod("SetResampleCurves")] - set; - } - - public extern bool resampleCurves - { - get; - set; - } - - public extern bool isTangentImportSupported - { - [NativeMethod("IsTangentImportSupported")] - get; - } - - [System.Obsolete("Use animationCompression instead", true)] - private bool reduceKeyframes { get { return false; } set {} } - - public ModelImporterMeshCompression meshCompression - { - get { return (ModelImporterMeshCompression)internal_meshCompression; } - set { internal_meshCompression = (int)value; } - } - - private extern int internal_meshCompression - { - [NativeMethod("GetMeshCompression")] - get; - [NativeMethod("SetMeshCompression")] - set; - } - - public extern bool importAnimation - { - get; - set; - } - - public extern bool optimizeGameObjects - { - get; - set; - } - - public string[] extraExposedTransformPaths - { - get { return GetExtraExposedTransformPaths(); } - set { INTERNAL_set_extraExposedTransformPaths(this, value); } - } - - private extern string[] GetExtraExposedTransformPaths(); - - [FreeFunction("ModelImporterBindings::SetExtraExposedTransformPaths")] - private extern static void INTERNAL_set_extraExposedTransformPaths([Writable] ModelImporter self, string[] value); - - public string[] extraUserProperties - { - get { return GetExtraUserProperties(); } - set { INTERNAL_set_extraUserProperties(this, value); } - } - - private extern string[] GetExtraUserProperties(); - - [FreeFunction("ModelImporterBindings::SetExtraUserProperties")] - private extern static void INTERNAL_set_extraUserProperties([Writable] ModelImporter self, string[] value); - - public extern ModelImporterAnimationCompression animationCompression - { - get; - set; - } - - public extern bool importAnimatedCustomProperties - { - get; - set; - } - - public extern bool importConstraints - { - get; - set; - } - - public extern float animationRotationError - { - get; - set; - } - - public extern float animationPositionError - { - get; - set; - } - - public extern float animationScaleError - { - get; - set; - } - - public extern WrapMode animationWrapMode - { - get; - set; - } - - public extern ModelImporterAnimationType animationType - { - get; - set; - } - - public extern ModelImporterHumanoidOversampling humanoidOversampling - { - get; - set; - } - - public extern string motionNodeName - { - get; - set; - } - - public Avatar sourceAvatar - { - get - { - return GetSourceAvatar(); - } - set - { - Avatar avatar = value; - if (value != null) - { - ModelImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(value)) as ModelImporter; - - if (importer != null) - { - humanDescription = importer.humanDescription; - } - else - { - Debug.LogError("Avatar must be from a ModelImporter, otherwise use ModelImporter.humanDescription"); - avatar = null; - } - } - - SetSourceAvatarInternal(this, avatar); - } - } - - extern public HumanDescription humanDescription - { - get; - set; - } - - private extern Avatar GetSourceAvatar(); - [FreeFunction("ModelImporterBindings::SetSourceAvatarInternal")] - private extern static void SetSourceAvatarInternal(ModelImporter self, Avatar value); - - [System.Obsolete("splitAnimations has been deprecated please use clipAnimations instead.", true)] - public bool splitAnimations - { - get { return clipAnimations.Length != 0; } - set {} - } - - public ModelImporterClipAnimation[] clipAnimations - { - get { return GetClipAnimations(this); } - set { SetClipAnimations(this, value); } - } - [FreeFunction("ModelImporterBindings::GetClipAnimations")] - private extern static ModelImporterClipAnimation[] GetClipAnimations(ModelImporter self); - [FreeFunction("ModelImporterBindings::SetClipAnimations")] - private extern static void SetClipAnimations([Writable] ModelImporter self, ModelImporterClipAnimation[] value); - - public ModelImporterClipAnimation[] defaultClipAnimations - { - get { return GetDefaultClipAnimations(this); } - } - [FreeFunction("ModelImporterBindings::GetDefaultClipAnimations")] - private extern static ModelImporterClipAnimation[] GetDefaultClipAnimations(ModelImporter self); - - internal extern bool isAssetOlderOr42 - { - [NativeMethod("IsAssetOlderOr42")] - get; - } - - [FreeFunction("ModelImporterBindings::UpdateTransformMask")] - extern internal static void UpdateTransformMask(AvatarMask mask, SerializedProperty serializedProperty); - - [FreeFunction("ModelImporterBindings::UpdateSkeletonPose")] - extern internal static void UpdateSkeletonPose(SkeletonBone[] skeletonBones, [NotNull] SerializedProperty serializedProperty); - extern internal AnimationClip GetPreviewAnimationClipForTake(string takeName); - - extern internal string CalculateBestFittingPreviewGameObject(); - - public void CreateDefaultMaskForClip(ModelImporterClipAnimation clip) - { - if (this.defaultClipAnimations.Length > 0) - { - var mask = new AvatarMask(); - this.defaultClipAnimations[0].ConfigureMaskFromClip(ref mask); - clip.ConfigureClipFromMask(mask); - DestroyImmediate(mask); - } - else - Debug.LogError("Cannot create default mask because the current importer doesn't have any animation information"); - } - - [NativeName("ExtractTextures")] - private extern bool ExtractTexturesInternal(string folderPath); - - public bool ExtractTextures(string folderPath) - { - if (string.IsNullOrEmpty(folderPath)) - throw new ArgumentException("The path cannot be empty", folderPath); - - return ExtractTexturesInternal(folderPath); - } - - public extern bool SearchAndRemapMaterials(ModelImporterMaterialName nameOption, ModelImporterMaterialSearch searchOption); - } -} diff --git a/Editor/Mono/AssetPipeline/MonoImporter.bindings.cs b/Editor/Mono/AssetPipeline/MonoImporter.bindings.cs deleted file mode 100644 index f069de66b1..0000000000 --- a/Editor/Mono/AssetPipeline/MonoImporter.bindings.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeHeader("Editor/Mono/AssetPipeline/MonoImporter.bindings.h")] - public class MonoImporter : AssetImporter - { - public extern void SetDefaultReferences(string[] name, Object[] target); - - [FreeFunction] - public static extern MonoScript[] GetAllRuntimeMonoScripts(); - - [FreeFunction("SetMonoScriptExecutionOrder")] - public static extern void SetExecutionOrder(MonoScript script, int order); - - // Call when icon set by SetIconForObject should be copied to monoImporter for persistance across project reloads - // This function will reimport the asset and is therefore slow. - [FreeFunction] - internal static extern void CopyMonoScriptIconToImporters(MonoScript script); - - [FreeFunction] - public static extern int GetExecutionOrder(MonoScript script); - - public extern MonoScript GetScript(); - - public extern Object GetDefaultReference(string name); - } -} diff --git a/Editor/Mono/AssetPipeline/NativeFormatImporterUtility.bindings.cs b/Editor/Mono/AssetPipeline/NativeFormatImporterUtility.bindings.cs deleted file mode 100644 index 81e1bdf2df..0000000000 --- a/Editor/Mono/AssetPipeline/NativeFormatImporterUtility.bindings.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.Bindings; -using UnityObject = UnityEngine.Object; - -namespace UnityEditor -{ - [InitializeOnLoad] - [NativeHeader("Editor/Src/AssetPipeline/NativeFormatImporter.h")] - internal static class NativeFormatImporterUtility - { - static NativeFormatImporterUtility() - { - foreach (var type in EditorAssemblies.GetAllTypesWithAttribute()) - { - var attr = type.GetCustomAttributes(typeof(AssetFileNameExtensionAttribute), false)[0] - as AssetFileNameExtensionAttribute; - try - { - RegisterExtensionForType(type, attr.preferredExtension, attr.otherExtensions.ToArray()); - } - catch (ArgumentException e) - { - Debug.LogException(e); - } - catch (NotSupportedException e) - { - Debug.LogException(e); - } - } - } - - private const string k_DefaultExtension = "asset"; - - static readonly Dictionary s_RegisteredExtensionsByType = new Dictionary(); - - internal static void RegisterExtensionForType( - Type type, string preferredExtension, params string[] otherExtensions - ) - { - if (!type.IsSubclassOf(typeof(ScriptableObject))) - { - throw new NotSupportedException( - string.Format( - "{0} may only be added to {1} types.", - typeof(AssetFileNameExtensionAttribute), typeof(ScriptableObject) - ) - ); - } - - if (s_RegisteredExtensionsByType.ContainsKey(type)) - throw new ArgumentException(string.Format("Extension already registered for type {0}.", type), "type"); - - var extensions = new string[otherExtensions.Length + 1]; - - extensions[0] = ValidateExtension(preferredExtension, type); - for (int i = 0, count = otherExtensions.Length; i < count; ++i) - extensions[i + 1] = ValidateExtension(otherExtensions[i], type); - - s_RegisteredExtensionsByType[type] = extensions; - } - - static string ValidateExtension(string extension, Type requestingType) - { - if (string.Equals(extension, k_DefaultExtension, StringComparison.OrdinalIgnoreCase)) - return extension; - var registered = s_RegisteredExtensionsByType.FirstOrDefault( - kv => kv.Value.Count(ext => string.Equals(ext, extension, StringComparison.OrdinalIgnoreCase)) > 0 - ); - if (registered.Key != null) - { - throw new ArgumentException( - string.Format( - "Extension \"{0}\" is already registered for type {1}. It cannot also be used for {2}.", - extension, registered.Key, requestingType - ), - "extension" - ); - } - bool nativeExtensionRegistered; - var registeredType = Internal_GetNativeTypeForExtension(extension, out nativeExtensionRegistered); - if (!nativeExtensionRegistered) - { - throw new ArgumentException( - string.Format( - "Extension \"{0}\" must also be registered in NativeFormatImporterExtensions.h with identical capitalization.", - extension - ), - "extension" - ); - } - if (registeredType != null && registeredType != requestingType) - { - throw new ArgumentException( - string.Format( - "Extension \"{0}\" is registered for type {1}. It cannot also be used for {2}.", - extension, registeredType, requestingType - ), - "extension" - ); - } - return extension; - } - - // TODO: swap bool and Type when bindings support `out Type` - [FreeFunction(Name = "NativeFormatImporter::Internal_GetNativeTypeForExtension", IsThreadSafe = true)] - static extern Type Internal_GetNativeTypeForExtension(string extension, out bool registered); - - internal static string GetExtensionForAsset(UnityObject asset) - { - var assetType = asset.GetType(); - - if (!typeof(ScriptableObject).IsAssignableFrom(assetType)) - return Internal_GetExtensionForNativeAsset(asset); - - // prefer the most specific type that matches (matches native implementation) - while (assetType != typeof(UnityObject)) - { - foreach (var kv in s_RegisteredExtensionsByType) - { - if (kv.Key == assetType) - return kv.Value[0]; - } - assetType = assetType.BaseType; - } - return k_DefaultExtension; - } - - [FreeFunction(Name = "NativeFormatImporter::Internal_GetExtensionForNativeAsset", IsThreadSafe = true)] - static extern string Internal_GetExtensionForNativeAsset(UnityObject asset); - } -} diff --git a/Editor/Mono/AssetPipeline/ScriptedImporter.cs b/Editor/Mono/AssetPipeline/ScriptedImporter.cs deleted file mode 100644 index 74676ca631..0000000000 --- a/Editor/Mono/AssetPipeline/ScriptedImporter.cs +++ /dev/null @@ -1,128 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEngine; -using UnityEngine.Scripting; -using Object = UnityEngine.Object; - -namespace UnityEditor.Experimental.AssetImporters -{ - // Class Concept: Root, abstract class for all Asset importers implemented in C#. - public abstract class ScriptedImporter : AssetImporter - { - // Called by native code to invoke the import handling code of the specialized scripted importer class. - // Marshals the data between the two models (native / managed) - [RequiredByNativeCode] - void GenerateAssetData(AssetImportContext ctx) - { - OnImportAsset(ctx); - } - - public abstract void OnImportAsset(AssetImportContext ctx); - - [RequiredByNativeCode] - internal static void RegisterScriptedImporters() - { - var importers = EditorAssemblies.GetAllTypesWithAttribute(); - foreach (var importer in importers) - { - var importerType = importer as Type; - var attribute = Attribute.GetCustomAttribute(importerType, typeof(ScriptedImporterAttribute)) as ScriptedImporterAttribute; - var handledExts = GetHandledExtensionsByImporter(attribute); - - // Prevent duplicates between importers! When duplicates found: all are rejected - foreach (var imp in importers) - { - if (imp == importer) - continue; - - var attribute2 = Attribute.GetCustomAttribute(imp as Type, typeof(ScriptedImporterAttribute)) as ScriptedImporterAttribute; - var handledExts2 = GetHandledExtensionsByImporter(attribute2); - - // Remove intersection? - foreach (var x1 in handledExts2) - { - if (handledExts.ContainsKey(x1.Key)) - { - // Log error message and remove from handledExts - Debug.LogError(String.Format("Scripted importers {0} and {1} are targeting the {2} extension, rejecting both.", importerType.FullName, (imp as Type).FullName, x1.Key)); - handledExts.Remove(x1.Key); - } - } - } - - MethodInfo getImportDependencyHintMethod = importerType.GetMethod("GetHashOfImportedAssetDependencyHintsForTesting", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - - // Register the importer - foreach (var ext in handledExts) - AssetImporter.RegisterImporter(importerType, attribute.version, attribute.importQueuePriority, ext.Key, getImportDependencyHintMethod != null); - } - } - - static SortedDictionary GetHandledExtensionsByImporter(ScriptedImporterAttribute attribute) - { - var handledExts = new SortedDictionary(); - if (attribute.fileExtensions != null) - { - foreach (var ext in attribute.fileExtensions) - { - var cleanExt = ext; - if (cleanExt.StartsWith(".")) - cleanExt = cleanExt.Substring(1); - - handledExts.Add(cleanExt, true); - } - } - - return handledExts; - } - } - - // Class Concept: Class attribute that describes Scriptable importers and their static characteristics. - [AttributeUsage(AttributeTargets.Class, Inherited = false)] - public class ScriptedImporterAttribute : Attribute - { - public int version { get; private set; } - - // Gives control over when the asset is imported with regards to assets of other types. - // Positive values delay the processing of source asset files while Negative values place them earlier in the import process. - public int importQueuePriority { get; private set; } - - public string[] fileExtensions { get; private set; } - - public ScriptedImporterAttribute(int version, string[] exts) - { - Init(version, exts, 0); - } - - public ScriptedImporterAttribute(int version, string ext) - { - Init(version, new[] { ext }, 0); - } - - public ScriptedImporterAttribute(int version, string[] exts, int importQueueOffset) - { - Init(version, exts, importQueueOffset); - } - - public ScriptedImporterAttribute(int version, string ext, int importQueueOffset) - { - Init(version, new[] { ext }, importQueueOffset); - } - - private void Init(int version, string[] exts, int importQueueOffset) - { - if (exts == null || exts.Any(string.IsNullOrEmpty)) - throw new ArgumentException("Must provide valid, none null, file extension strings."); - - this.version = version; - this.importQueuePriority = importQueueOffset; - fileExtensions = exts; - } - } -} diff --git a/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs b/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs deleted file mode 100644 index e917a25336..0000000000 --- a/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs +++ /dev/null @@ -1,232 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using System.Runtime.InteropServices; -using System.Collections.Generic; -using Unity.Collections; -using Unity.Collections.LowLevel.Unsafe; - -namespace UnityEditor.Experimental.AssetImporters -{ - [StructLayout(LayoutKind.Sequential)] - public struct SpriteImportData - { - private string m_Name; - private Rect m_Rect; - private SpriteAlignment m_Alignment; - private Vector2 m_Pivot; - private Vector4 m_Border; - private float m_TessellationDetail; - private string m_SpriteID; - private List m_Outline; - - public string name { get { return m_Name; } set { m_Name = value; } } - public Rect rect { get { return m_Rect; } set { m_Rect = value; } } - public SpriteAlignment alignment { get { return m_Alignment; } set { m_Alignment = value; } } - public Vector2 pivot { get { return m_Pivot; } set { m_Pivot = value; } } - public Vector4 border { get { return m_Border; } set { m_Border = value; } } - public List outline { get { return m_Outline; } set { m_Outline = value; } } - public float tessellationDetail {get { return m_TessellationDetail; } set { m_TessellationDetail = value; } } - public string spriteID {get { return m_SpriteID; } set { m_SpriteID = value; } } - } - - [StructLayout(LayoutKind.Sequential)] - public struct TextureGenerationOutput - { - [NativeName("texture")] - private Texture2D m_Texture; - [NativeName("importInspectorWarnings")] - private string m_ImportInspectorWarnings; - [NativeName("importWarnings")] - private string[] m_ImportWarnings; - [NativeName("thumbNail")] - private Texture2D m_ThumbNail; - [NativeName("sprites")] - private Sprite[] m_Sprites; - - public Texture2D texture { get { return m_Texture; } } - public string importInspectorWarnings { get { return m_ImportInspectorWarnings; } } - public string[] importWarnings { get { return m_ImportWarnings; } } - public Texture2D thumbNail { get { return m_ThumbNail; } } - public Sprite[] sprites { get { return m_Sprites; } } - }; - - - [StructLayout(LayoutKind.Sequential)] - [NativeAsStruct] - public class SourceTextureInformation - { - [NativeName("width")] - private int m_Width; - [NativeName("height")] - private int m_Height; - [NativeName("sourceContainsAlpha")] - private bool m_SourceContainsAlpha; - [NativeName("sourceWasHDR")] - private bool m_SourceWasHDR; - - public int width { get { return m_Width; } set {m_Width = value; } } - public int height { get { return m_Height; } set {m_Height = value; } } - public bool containsAlpha { get { return m_SourceContainsAlpha; } set {m_SourceContainsAlpha = value; } } - public bool hdr { get { return m_SourceWasHDR; } set {m_SourceWasHDR = value; } } - }; - - [StructLayout(LayoutKind.Sequential)] - public struct TextureGenerationSettings - { - [NativeName("assetPath")] - private string m_AssetPath; - [NativeName("qualifyForSpritePacking")] - private bool m_QualifyForSpritePacking; - [NativeName("enablePostProcessor")] - private bool m_EnablePostProcessor; - [NativeName("tiSettings")] - private TextureImporterSettings m_Settings; - [NativeName("platformSettings")] - private TextureImporterPlatformSettings m_PlatformSettings; - [NativeName("sourceTextureInformation")] - private SourceTextureInformation m_SourceTextureInformation; - [NativeName("spriteSheetData")] - private SpriteImportData[] m_SpriteImportData; - [NativeName("spritePackingTag")] - private string m_SpritePackingTag; - - - public TextureGenerationSettings(TextureImporterType type) - { - m_EnablePostProcessor = true; - m_AssetPath = ""; - m_QualifyForSpritePacking = false; - m_SpritePackingTag = ""; - m_SpriteImportData = null; - - m_SourceTextureInformation = new SourceTextureInformation(); - m_SourceTextureInformation.width = m_SourceTextureInformation.height = 0; - m_SourceTextureInformation.containsAlpha = false; - m_SourceTextureInformation.hdr = false; - - m_PlatformSettings = new TextureImporterPlatformSettings(); - m_PlatformSettings.overridden = false; - m_PlatformSettings.format = TextureImporterFormat.Automatic; - m_PlatformSettings.maxTextureSize = 2048; - m_PlatformSettings.allowsAlphaSplitting = false; - m_PlatformSettings.resizeAlgorithm = TextureResizeAlgorithm.Mitchell; - m_PlatformSettings.compressionQuality = (int)TextureCompressionQuality.Normal; - m_PlatformSettings.crunchedCompression = false; - m_PlatformSettings.name = TextureImporter.defaultPlatformName; - - // Values from TextureImporterSettings native constructor - m_Settings = new TextureImporterSettings(); - m_Settings.textureType = type; - m_Settings.textureShape = TextureImporterShape.Texture2D; - m_Settings.convertToNormalMap = false; - m_Settings.mipmapEnabled = true; - m_Settings.mipmapFilter = TextureImporterMipFilter.BoxFilter; - m_Settings.sRGBTexture = true; - m_Settings.borderMipmap = false; - m_Settings.mipMapsPreserveCoverage = false; - m_Settings.alphaTestReferenceValue = 0.5f; - m_Settings.readable = false; - m_Settings.fadeOut = false; - m_Settings.mipmapFadeDistanceStart = 1; - m_Settings.mipmapFadeDistanceEnd = 3; - m_Settings.heightmapScale = 0.25f; - m_Settings.normalMapFilter = TextureImporterNormalFilter.Standard; - m_Settings.cubemapConvolution = 0; - m_Settings.generateCubemap = TextureImporterGenerateCubemap.AutoCubemap; - m_Settings.seamlessCubemap = false; - m_Settings.npotScale = TextureImporterNPOTScale.ToNearest; - m_Settings.spriteMode = (int)SpriteImportMode.Single; - m_Settings.spriteExtrude = 1; - m_Settings.spriteMeshType = SpriteMeshType.Tight; - m_Settings.spriteAlignment = (int)SpriteAlignment.Center; - m_Settings.spritePivot = Vector2.one * 0.5f; - m_Settings.spritePixelsPerUnit = 100; - m_Settings.spriteBorder = Vector4.zero; - m_Settings.alphaSource = TextureImporterAlphaSource.FromInput; - m_Settings.alphaIsTransparency = false; - m_Settings.spriteTessellationDetail = -1; - m_Settings.wrapMode = m_Settings.wrapModeU = m_Settings.wrapModeV = m_Settings.wrapModeW = TextureWrapMode.Repeat; - - // From TextureImporterSettings::ApplyTextureType - switch (type) - { - case TextureImporterType.Default: - m_Settings.sRGBTexture = true; - m_Settings.mipmapEnabled = true; - break; - case TextureImporterType.NormalMap: - m_Settings.sRGBTexture = false; - break; - case TextureImporterType.GUI: - m_Settings.sRGBTexture = false; - m_Settings.mipmapEnabled = false; - m_Settings.alphaIsTransparency = true; - m_Settings.npotScale = TextureImporterNPOTScale.None; - m_Settings.aniso = 1; - m_Settings.wrapMode = m_Settings.wrapModeU = m_Settings.wrapModeV = m_Settings.wrapModeW = TextureWrapMode.Clamp; - break; - case TextureImporterType.Sprite: - m_Settings.npotScale = TextureImporterNPOTScale.None; - m_Settings.alphaIsTransparency = true; - m_Settings.mipmapEnabled = false; - m_Settings.sRGBTexture = true; - m_Settings.wrapMode = m_Settings.wrapModeU = m_Settings.wrapModeV = m_Settings.wrapModeW = TextureWrapMode.Clamp; - m_Settings.alphaSource = TextureImporterAlphaSource.FromInput; - break; - case TextureImporterType.Cursor: - m_Settings.readable = true; - m_Settings.alphaIsTransparency = true; - m_Settings.mipmapEnabled = false; - m_Settings.npotScale = TextureImporterNPOTScale.None; - m_Settings.aniso = 1; - m_Settings.wrapMode = m_Settings.wrapModeU = m_Settings.wrapModeV = m_Settings.wrapModeW = TextureWrapMode.Clamp; - break; - case TextureImporterType.Cookie: - m_Settings.borderMipmap = true; - m_Settings.wrapMode = m_Settings.wrapModeU = m_Settings.wrapModeV = m_Settings.wrapModeW = TextureWrapMode.Clamp; - m_Settings.aniso = 0; - break; - case TextureImporterType.Lightmap: - m_Settings.sRGBTexture = true; - m_Settings.npotScale = TextureImporterNPOTScale.ToNearest; - m_Settings.alphaIsTransparency = false; - m_Settings.alphaSource = TextureImporterAlphaSource.None; - break; - case TextureImporterType.SingleChannel: - m_Settings.sRGBTexture = false; - break; - } - } - - public string assetPath { get { return m_AssetPath; } set { m_AssetPath = value; } } - public bool qualifyForSpritePacking { get { return m_QualifyForSpritePacking; } set { m_QualifyForSpritePacking = value; } } - public bool enablePostProcessor { get { return m_EnablePostProcessor; } set { m_EnablePostProcessor = value; } } - public TextureImporterSettings textureImporterSettings { get { return m_Settings; } set { m_Settings = value; } } - public TextureImporterPlatformSettings platformSettings { get { return m_PlatformSettings; } set { m_PlatformSettings = value; } } - public SourceTextureInformation sourceTextureInformation { get { return m_SourceTextureInformation; } set { m_SourceTextureInformation = value; } } - public SpriteImportData[] spriteImportData { get { return m_SpriteImportData; } set { m_SpriteImportData = value; } } - public string spritePackingTag { get { return m_SpritePackingTag; } set { m_SpritePackingTag = value; } } - }; - - - [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureGenerator.h")] - [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureImporterTypes.h")] - [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureImporter.bindings.h")] - [NativeHeader("Runtime/Serialize/BuildTarget.h")] - public static unsafe class TextureGenerator - { - public static TextureGenerationOutput GenerateTexture(TextureGenerationSettings settings, NativeArray colorBuffer) - { - return GenerateTextureImpl(settings, colorBuffer.GetUnsafeReadOnlyPtr(), colorBuffer.Length * UnsafeUtility.SizeOf()); - } - - [NativeThrows] - [NativeMethod("GenerateTextureScripting")] - extern static unsafe TextureGenerationOutput GenerateTextureImpl(TextureGenerationSettings settings, void* colorBuffer, int colorBufferLength); - } -} diff --git a/Editor/Mono/AssetPostprocessor.cs b/Editor/Mono/AssetPostprocessor.cs deleted file mode 100644 index 9597e764e4..0000000000 --- a/Editor/Mono/AssetPostprocessor.cs +++ /dev/null @@ -1,478 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Scripting; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace UnityEditor -{ - internal class AssetPostprocessingInternal - { - static void LogPostProcessorMissingDefaultConstructor(Type type) - { - Debug.LogErrorFormat("{0} requires a default constructor to be used as an asset post processor", type); - } - - [RequiredByNativeCode] - // Postprocess on all assets once an automatic import has completed - static void PostprocessAllAssets(string[] importedAssets, string[] addedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPathAssets) - { - object[] args = { importedAssets, deletedAssets, movedAssets, movedFromPathAssets }; - foreach (var assetPostprocessorClass in EditorAssemblies.SubclassesOf(typeof(AssetPostprocessor))) - { - MethodInfo method = assetPostprocessorClass.GetMethod("OnPostprocessAllAssets", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - if (method != null) - method.Invoke(null, args); - } - - ///@TODO: we need addedAssets for SyncVS. Make this into a proper API and write tests - SyncVS.PostprocessSyncProject(importedAssets, addedAssets, deletedAssets, movedAssets, movedFromPathAssets); - } - - [RequiredByNativeCode] - static void PreprocessAssembly(string pathName) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPreprocessAssembly", new[] { pathName }); - } - } - - //This is undocumented, and a "safeguard" for when visualstudio gets a new release that is incompatible with ours, so that users can postprocess our csproj to fix it. - //(or just completely replace them). Hopefully we'll never need this. - static internal void CallOnGeneratedCSProjectFiles() - { - object[] args = {}; - foreach (var method in AllPostProcessorMethodsNamed("OnGeneratedCSProjectFiles")) - { - method.Invoke(null, args); - } - } - - //This callback is used by C# code editors to modify the .sln file. - static internal string CallOnGeneratedSlnSolution(string path, string content) - { - foreach (var method in AllPostProcessorMethodsNamed("OnGeneratedSlnSolution")) - { - object[] args = { path, content }; - object returnValue = method.Invoke(null, args); - - if (method.ReturnType == typeof(string)) - content = (string)returnValue; - } - - return content; - } - - // This callback is used by C# code editors to modify the .csproj files. - static internal string CallOnGeneratedCSProject(string path, string content) - { - foreach (var method in AllPostProcessorMethodsNamed("OnGeneratedCSProject")) - { - object[] args = { path, content }; - object returnValue = method.Invoke(null, args); - - if (method.ReturnType == typeof(string)) - content = (string)returnValue; - } - - return content; - } - - //This callback is used by UnityVS to take over project generation from unity - static internal bool OnPreGeneratingCSProjectFiles() - { - object[] args = {}; - bool result = false; - foreach (var method in AllPostProcessorMethodsNamed("OnPreGeneratingCSProjectFiles")) - { - object returnValue = method.Invoke(null, args); - - if (method.ReturnType == typeof(bool)) - result = result | (bool)returnValue; - } - return result; - } - - private static IEnumerable AllPostProcessorMethodsNamed(string callbackName) - { - return EditorAssemblies.SubclassesOf(typeof(AssetPostprocessor)).Select(assetPostprocessorClass => assetPostprocessorClass.GetMethod(callbackName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)).Where(method => method != null); - } - - internal class CompareAssetImportPriority : IComparer - { - int IComparer.Compare(System.Object xo, System.Object yo) - { - int x = ((AssetPostprocessor)xo).GetPostprocessOrder(); - int y = ((AssetPostprocessor)yo).GetPostprocessOrder(); - return x.CompareTo(y); - } - } - - internal class PostprocessStack - { - internal ArrayList m_ImportProcessors = null; - } - - static ArrayList m_PostprocessStack = null; - static ArrayList m_ImportProcessors = null; - static ArrayList m_PostprocessorClasses = null; - - static ArrayList GetCachedAssetPostprocessorClasses() - { - if (m_PostprocessorClasses == null) - { - m_PostprocessorClasses = new ArrayList(); - foreach (var type in EditorAssemblies.SubclassesOf(typeof(AssetPostprocessor))) - { - m_PostprocessorClasses.Add(type); - } - } - return m_PostprocessorClasses; - } - - [RequiredByNativeCode] - static void InitPostprocessors(string pathName) - { - m_ImportProcessors = new ArrayList(); - - // @TODO: This is just a temporary workaround for the import settings. - // We should add importers to the asset, persist them and show an inspector for them. - foreach (Type assetPostprocessorClass in GetCachedAssetPostprocessorClasses()) - { - try - { - var assetPostprocessor = Activator.CreateInstance(assetPostprocessorClass) as AssetPostprocessor; - assetPostprocessor.assetPath = pathName; - m_ImportProcessors.Add(assetPostprocessor); - } - catch (MissingMethodException) - { - LogPostProcessorMissingDefaultConstructor(assetPostprocessorClass); - } - catch (Exception e) - { - Debug.LogException(e); - } - } - - m_ImportProcessors.Sort(new CompareAssetImportPriority()); - - // Setup postprocessing stack to support rentrancy (Import asset immediate) - PostprocessStack postStack = new PostprocessStack(); - postStack.m_ImportProcessors = m_ImportProcessors; - if (m_PostprocessStack == null) - m_PostprocessStack = new ArrayList(); - m_PostprocessStack.Add(postStack); - } - - [RequiredByNativeCode] - static void CleanupPostprocessors() - { - if (m_PostprocessStack != null) - { - m_PostprocessStack.RemoveAt(m_PostprocessStack.Count - 1); - if (m_PostprocessStack.Count != 0) - { - PostprocessStack postStack = (PostprocessStack)m_PostprocessStack[m_PostprocessStack.Count - 1]; - m_ImportProcessors = postStack.m_ImportProcessors; - } - } - } - - [RequiredByNativeCode] - static uint[] GetMeshProcessorVersions() - { - List versions = new List(); - - foreach (var assetPostprocessorClass in EditorAssemblies.SubclassesOf(typeof(AssetPostprocessor))) - { - try - { - var inst = Activator.CreateInstance(assetPostprocessorClass) as AssetPostprocessor; - var type = inst.GetType(); - bool hasPreProcessMethod = type.GetMethod("OnPreprocessModel", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; - bool hasProcessMeshAssignMethod = type.GetMethod("OnProcessMeshAssingModel", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; - bool hasPostProcessMethod = type.GetMethod("OnPostprocessModel", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; - uint version = inst.GetVersion(); - if (version != 0 && (hasPreProcessMethod || hasProcessMeshAssignMethod || hasPostProcessMethod)) - { - versions.Add(version); - } - } - catch (MissingMethodException) - { - LogPostProcessorMissingDefaultConstructor(assetPostprocessorClass); - } - catch (Exception e) - { - Debug.LogException(e); - } - } - - return versions.ToArray(); - } - - [RequiredByNativeCode] - static void PreprocessAsset() - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPreprocessAsset", null); - } - } - - [RequiredByNativeCode] - static void PreprocessMesh(string pathName) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPreprocessModel", null); - } - } - - [RequiredByNativeCode] - static void PreprocessSpeedTree(string pathName) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPreprocessSpeedTree", null); - } - } - - [RequiredByNativeCode] - static void PreprocessAnimation(string pathName) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPreprocessAnimation", null); - } - } - - [RequiredByNativeCode] - static void PostprocessAnimation(GameObject root, AnimationClip clip) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { root, clip }; - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessAnimation", args); - } - } - - [RequiredByNativeCode] - static Material ProcessMeshAssignMaterial(Renderer renderer, Material material) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { material, renderer }; - object assignedMaterial = AttributeHelper.InvokeMemberIfAvailable(inst, "OnAssignMaterialModel", args); - if (assignedMaterial as Material) - return assignedMaterial as Material; - } - - return null; - } - - [RequiredByNativeCode] - static bool ProcessMeshHasAssignMaterial() - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - if (inst.GetType().GetMethod("OnAssignMaterialModel", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null) - return true; - } - - return false; - } - - static void PostprocessMesh(GameObject gameObject) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { gameObject }; - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessModel", args); - } - } - - static void PostprocessSpeedTree(GameObject gameObject) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { gameObject }; - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessSpeedTree", args); - } - } - - [RequiredByNativeCode] - static void PostprocessMaterial(Material material) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { material }; - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessMaterial", args); - } - } - - [RequiredByNativeCode] - static void PostprocessGameObjectWithUserProperties(GameObject go, string[] prop_names, object[] prop_values) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { go, prop_names, prop_values }; - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessGameObjectWithUserProperties", args); - } - } - - [RequiredByNativeCode] - static EditorCurveBinding[] PostprocessGameObjectWithAnimatedUserProperties(GameObject go, EditorCurveBinding[] bindings) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { go, bindings }; - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessGameObjectWithAnimatedUserProperties", args); - } - return bindings; - } - - [RequiredByNativeCode] - static uint[] GetTextureProcessorVersions() - { - List versions = new List(); - - foreach (var assetPostprocessorClass in EditorAssemblies.SubclassesOf(typeof(AssetPostprocessor))) - { - try - { - var inst = Activator.CreateInstance(assetPostprocessorClass) as AssetPostprocessor; - var type = inst.GetType(); - bool hasPreProcessMethod = type.GetMethod("OnPreprocessTexture", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; - bool hasPostProcessMethod = (type.GetMethod("OnPostprocessTexture", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null) || - (type.GetMethod("OnPostprocessCubemap", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null); - uint version = inst.GetVersion(); - if (version != 0 && (hasPreProcessMethod || hasPostProcessMethod)) - { - versions.Add(version); - } - } - catch (MissingMethodException) - { - LogPostProcessorMissingDefaultConstructor(assetPostprocessorClass); - } - catch (Exception e) - { - Debug.LogException(e); - } - } - - return versions.ToArray(); - } - - [RequiredByNativeCode] - static void PreprocessTexture(string pathName) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPreprocessTexture", null); - } - } - - [RequiredByNativeCode] - static void PostprocessTexture(Texture2D tex, string pathName) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { tex }; - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessTexture", args); - } - } - - [RequiredByNativeCode] - static void PostprocessCubemap(Cubemap tex, string pathName) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { tex }; - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessCubemap", args); - } - } - - [RequiredByNativeCode] - static void PostprocessSprites(Texture2D tex, string pathName, Sprite[] sprites) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { tex, sprites }; - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessSprites", args); - } - } - - [RequiredByNativeCode] - static uint[] GetAudioProcessorVersions() - { - List versions = new List(); - - foreach (var assetPostprocessorClass in EditorAssemblies.SubclassesOf(typeof(AssetPostprocessor))) - { - try - { - var inst = Activator.CreateInstance(assetPostprocessorClass) as AssetPostprocessor; - var type = inst.GetType(); - bool hasPreProcessMethod = type.GetMethod("OnPreprocessAudio", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; - bool hasPostProcessMethod = type.GetMethod("OnPostprocessAudio", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; - uint version = inst.GetVersion(); - if (version != 0 && (hasPreProcessMethod || hasPostProcessMethod)) - { - versions.Add(version); - } - } - catch (MissingMethodException) - { - LogPostProcessorMissingDefaultConstructor(assetPostprocessorClass); - } - catch (Exception e) - { - Debug.LogException(e); - } - } - - return versions.ToArray(); - } - - [RequiredByNativeCode] - static void PreprocessAudio(string pathName) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPreprocessAudio", null); - } - } - - [RequiredByNativeCode] - static void PostprocessAudio(AudioClip tex, string pathName) - { - foreach (AssetPostprocessor inst in m_ImportProcessors) - { - object[] args = { tex }; - AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessAudio", args); - } - } - - [RequiredByNativeCode] - static void PostprocessAssetbundleNameChanged(string assetPAth, string prevoiusAssetBundleName, string newAssetBundleName) - { - object[] args = { assetPAth, prevoiusAssetBundleName, newAssetBundleName }; - - foreach (var assetPostprocessorClass in EditorAssemblies.SubclassesOf(typeof(AssetPostprocessor))) - { - var assetPostprocessor = Activator.CreateInstance(assetPostprocessorClass) as AssetPostprocessor; - AttributeHelper.InvokeMemberIfAvailable(assetPostprocessor, "OnPostprocessAssetbundleNameChanged", args); - } - } - } -} diff --git a/Editor/Mono/AssetPreviewUpdater.cs b/Editor/Mono/AssetPreviewUpdater.cs deleted file mode 100644 index 3d310838d5..0000000000 --- a/Editor/Mono/AssetPreviewUpdater.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal static class AssetPreviewUpdater - { - // Generate a preview texture for an asset - public static Texture2D CreatePreviewForAsset(Object obj, Object[] subAssets, string assetPath) - { - if (obj == null) - return null; - - System.Type type = CustomEditorAttributes.FindCustomEditorType(obj, false); - if (type == null) - return null; - - System.Reflection.MethodInfo info = type.GetMethod("RenderStaticPreview"); - if (info == null) - { - Debug.LogError("Fail to find RenderStaticPreview base method"); - return null; - } - - if (info.DeclaringType == typeof(Editor)) - return null; - - - Editor editor = Editor.CreateEditor(obj); - - if (editor == null) - return null; - - Texture2D tex = editor.RenderStaticPreview(assetPath, subAssets, 128, 128); - - // For debugging we write the preview to a file (keep) - //{ - // var bytes = tex.EncodeToPNG(); - // string previewFilePath = string.Format ("{0}/../SavedPreview{1}.png", Application.dataPath, (int)(EditorApplication.timeSinceStartup*1000)); - // System.IO.File.WriteAllBytes(previewFilePath, bytes); - // Debug.Log ("Wrote preview file to: " +previewFilePath); - //} - - Object.DestroyImmediate(editor); - - return tex; - } - } -} diff --git a/Editor/Mono/AssetStore/AssetStoreAsset.cs b/Editor/Mono/AssetStore/AssetStoreAsset.cs deleted file mode 100644 index 395a34021b..0000000000 --- a/Editor/Mono/AssetStore/AssetStoreAsset.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; - -namespace UnityEditor -{ - /** - * An asset store asset. - */ - public sealed class AssetStoreAsset - { - /* Search result data - * - * This is returned when searching for assets - */ - public int id; - public string name; - public string displayName; // name without extension, we cache it to prevent string operations when rendering - public string staticPreviewURL; - public string dynamicPreviewURL; - public string className; - public string price; - public int packageID; - - /* Preview data - * - * This is returned when clicking on an assets for preview - */ - internal class PreviewInfo - { - public string packageName; - public string packageShortUrl; - public int packageSize; - public string packageVersion; - public int packageRating; - public int packageAssetCount; - public bool isPurchased; - public bool isDownloadable; - public string publisherName; - public string encryptionKey; - public string packageUrl; - public float buildProgress; // -1 when not building - public float downloadProgress; // -1 when not downloading - public string categoryName; - } - - internal PreviewInfo previewInfo; - - // - public Texture2D previewImage; - internal AssetBundleCreateRequest previewBundleRequest; - internal AssetBundle previewBundle; - internal Object previewAsset; - internal bool disposed; - - // public AssetStoreAssetsInfo assetsInfo; - public AssetStoreAsset() - { - disposed = false; - } - - public void Dispose() - { - if (previewImage != null) - { - Object.DestroyImmediate(previewImage); - previewImage = null; - } - if (previewBundle != null) - { - previewBundle.Unload(true); - previewBundle = null; - previewAsset = null; - } - disposed = true; - } - - public Object Preview - { - get - { - if (previewAsset != null) - return previewAsset; - - return previewImage; - } - } - - public bool HasLivePreview - { - get - { - return previewAsset != null; - } - } - - internal string DebugString - { - get - { - string r = string.Format("id: {0}\nname: {1}\nstaticPreviewURL: {2}\ndynamicPreviewURL: {3}\n" + - "className: {4}\nprice: {5}\npackageID: {6}", - id, name ?? "N/A", staticPreviewURL ?? "N/A", dynamicPreviewURL ?? "N/A", className ?? "N/A", price, packageID); - if (previewInfo != null) - { - r += string.Format("previewInfo {{\n" + - " packageName: {0}\n" + - " packageShortUrl: {1}\n" + - " packageSize: {2}\n" + - " packageVersion: {3}\n" + - " packageRating: {4}\n" + - " packageAssetCount: {5}\n" + - " isPurchased: {6}\n" + - " isDownloadable: {7}\n" + - " publisherName: {8}\n" + - " encryptionKey: {9}\n" + - " packageUrl: {10}\n" + - " buildProgress: {11}\n" + - " downloadProgress: {12}\n" + - " categoryName: {13}\n" + - "}}", - previewInfo.packageName ?? "N/A", - previewInfo.packageShortUrl ?? "N/A", - previewInfo.packageSize, - previewInfo.packageVersion ?? "N/A", - previewInfo.packageRating, - previewInfo.packageAssetCount, - previewInfo.isPurchased, - previewInfo.isDownloadable, - previewInfo.publisherName ?? "N/A", - previewInfo.encryptionKey ?? "N/A", - previewInfo.packageUrl ?? "N/A", - previewInfo.buildProgress, - previewInfo.downloadProgress, - previewInfo.categoryName ?? "N/A"); - } - return r; - } - } - } -} // UnityEditor namespace diff --git a/Editor/Mono/AssetStore/AssetStoreAssetSelection.cs b/Editor/Mono/AssetStore/AssetStoreAssetSelection.cs deleted file mode 100644 index 2f255c4d36..0000000000 --- a/Editor/Mono/AssetStore/AssetStoreAssetSelection.cs +++ /dev/null @@ -1,296 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; - -namespace UnityEditor -{ - /** - * An asset store asset selection. - * - * This class works as a singleton for keeping the list of selected - * asset store assets. This is not handled by the normal select framework - * because an asset store asset does not have an instanceID since it is not - * actually an asset in the local project. - * - * Currently there is only support for handling a single selected asset store - * asset at a time. This class is somewhat prepared for multiple asset store asset - * selections though. - */ - internal static class AssetStoreAssetSelection - { - public delegate void AssetsRefreshed(); - - static internal Dictionary s_SelectedAssets; - - public static void AddAsset(AssetStoreAsset searchResult, Texture2D placeholderPreviewImage) - { - if (placeholderPreviewImage != null) - searchResult.previewImage = ScaleImage(placeholderPreviewImage, 256, 256); - - searchResult.previewInfo = null; - searchResult.previewBundleRequest = null; - - // Dynamic previews is asset bundles to be displayed in - // the inspector. Static previews are images. - if (!string.IsNullOrEmpty(searchResult.dynamicPreviewURL) && searchResult.previewBundle == null) - { - // Debug.Log("dyn url " + searchResult.disposed.ToString() + " " + searchResult.dynamicPreviewURL); - searchResult.disposed = false; - // searchResult.previewBundle = AssetBundle.CreateFromFile("/users/jonasd/test.unity3d"); - // searchResult.previewAsset = searchResult.previewBundle.mainAsset; - - // Request the asset bundle data from the url and register a callback - AsyncHTTPClient client = new AsyncHTTPClient(searchResult.dynamicPreviewURL); - client.doneCallback = delegate(AsyncHTTPClient c) { - if (!client.IsSuccess()) - { - System.Console.WriteLine("Error downloading dynamic preview: " + client.text); - // Try the static preview instead - searchResult.dynamicPreviewURL = null; - DownloadStaticPreview(searchResult); - return; - } - - // We only suppport one asset so grab the first one - AssetStoreAsset sel = GetFirstAsset(); - - // Make sure that the selection hasn't changed meanwhile - if (searchResult.disposed || sel == null || searchResult.id != sel.id) - { - //Debug.Log("dyn disposed " + searchResult.disposed.ToString() + " " + (sel == null ? "null" : sel.id.ToString()) + " " + searchResult.id.ToString()); - return; - } - - // Go create the asset bundle in memory from the binary blob asynchronously - try - { - AssetBundleCreateRequest cr = AssetBundle.LoadFromMemoryAsync(c.bytes); - - // Workaround: Don't subject the bundle to the usual compatibility checks. We want - // to stay compatible with previews created in prior versions of Unity and with the - // stuff we put into previews, we should generally be able to still load the content - // in the editor. - cr.DisableCompatibilityChecks(); - - searchResult.previewBundleRequest = cr; - EditorApplication.CallbackFunction callback = null; - - // The callback will be called each tick and check if the asset bundle is ready - double startTime = EditorApplication.timeSinceStartup; - callback = () => { - AssetStoreUtils.UpdatePreloading(); - - if (!cr.isDone) - { - double nowTime = EditorApplication.timeSinceStartup; - if (nowTime - startTime > 10.0) - { - // Timeout. Stop polling - EditorApplication.update -= callback; - System.Console.WriteLine("Timed out fetch live preview bundle " + - (searchResult.dynamicPreviewURL ?? "")); - // Debug.Log("Not done Timed out" + cr.progress.ToString() ); - } - else - { - // Debug.Log("Not done " + cr.progress.ToString() ); - } - return; - } - - // Done cooking. Stop polling. - EditorApplication.update -= callback; - - // Make sure that the selection hasn't changed meanwhile - AssetStoreAsset sel2 = GetFirstAsset(); - if (searchResult.disposed || sel2 == null || searchResult.id != sel2.id) - { - // No problem. Just ignore. - // Debug.Log("dyn late disposed " + searchResult.disposed.ToString() + " " + (sel2 == null ? "null" : sel2.id.ToString()) + " " + searchResult.id.ToString()); - } - else - { - searchResult.previewBundle = cr.assetBundle; - if (cr.assetBundle == null || cr.assetBundle.mainAsset == null) - { - // Failed downloading live preview. Fallback to static - searchResult.dynamicPreviewURL = null; - DownloadStaticPreview(searchResult); - } - else - searchResult.previewAsset = searchResult.previewBundle.mainAsset; - } - }; - - EditorApplication.update += callback; - } - catch (System.Exception e) - { - System.Console.Write(e.Message); - Debug.Log(e.Message); - } - }; - client.Begin(); - } - else if (!string.IsNullOrEmpty(searchResult.staticPreviewURL)) - { - DownloadStaticPreview(searchResult); - } - - // searchResult.previewBundle = null; - AddAssetInternal(searchResult); - - RefreshFromServer(null); - } - - // Also used by AssetStoreToolUtils - internal static void AddAssetInternal(AssetStoreAsset searchResult) - { - if (s_SelectedAssets == null) - s_SelectedAssets = new Dictionary(); - s_SelectedAssets[searchResult.id] = searchResult; - } - - static void DownloadStaticPreview(AssetStoreAsset searchResult) - { - AsyncHTTPClient client = new AsyncHTTPClient(searchResult.staticPreviewURL); - client.doneCallback = delegate(AsyncHTTPClient c) { - if (!client.IsSuccess()) - { - System.Console.WriteLine("Error downloading static preview: " + client.text); - // Debug.LogError("Error downloading static preview: " + client.text); - return; - } - - // Need to put the texture through some scaling magic in order for the - // TextureInspector to be able to show it. - // TODO: This is a workaround and should be fixed. - Texture2D srcTex = c.texture; - Texture2D tex = new Texture2D(srcTex.width, srcTex.height, TextureFormat.RGB24, false, true); - AssetStorePreviewManager.ScaleImage(tex.width, tex.height, srcTex, tex, null); - // tex.Compress(true); - searchResult.previewImage = tex; - - Object.DestroyImmediate(srcTex); - AssetStoreAssetInspector.Instance.Repaint(); - }; - client.Begin(); - } - - // Refresh information about displayed asset by quering the - // asset store server. This is typically after the user has - // logged in because we need to know if he already owns the - // displayed asset. - public static void RefreshFromServer(AssetsRefreshed callback) - { - if (s_SelectedAssets.Count == 0) - return; - - // Refetch assetInfo - // Query the asset store for more info - List queryAssets = new List(); - foreach (KeyValuePair qasset in s_SelectedAssets) - queryAssets.Add(qasset.Value); - - // This will fill the queryAssets with extra preview data - AssetStoreClient.AssetsInfo(queryAssets, - delegate(AssetStoreAssetsInfo results) { - AssetStoreAssetInspector.paymentAvailability = AssetStoreAssetInspector.PaymentAvailability.ServiceDisabled; - if (results.error != null && results.error != "") - { - System.Console.WriteLine("Error performing Asset Store Info search: " + results.error); - AssetStoreAssetInspector.OfflineNoticeEnabled = true; - //Debug.LogError("Error performing Asset Store Info search: " + results.error); - if (callback != null) callback(); - return; - } - AssetStoreAssetInspector.OfflineNoticeEnabled = false; - - if (results.status == AssetStoreAssetsInfo.Status.Ok) - AssetStoreAssetInspector.paymentAvailability = AssetStoreAssetInspector.PaymentAvailability.Ok; - else if (results.status == AssetStoreAssetsInfo.Status.BasketNotEmpty) - AssetStoreAssetInspector.paymentAvailability = AssetStoreAssetInspector.PaymentAvailability.BasketNotEmpty; - else if (results.status == AssetStoreAssetsInfo.Status.AnonymousUser) - AssetStoreAssetInspector.paymentAvailability = AssetStoreAssetInspector.PaymentAvailability.AnonymousUser; - - AssetStoreAssetInspector.s_PurchaseMessage = results.message; - AssetStoreAssetInspector.s_PaymentMethodCard = results.paymentMethodCard; - AssetStoreAssetInspector.s_PaymentMethodExpire = results.paymentMethodExpire; - AssetStoreAssetInspector.s_PriceText = results.priceText; - - AssetStoreAssetInspector.Instance.Repaint(); - if (callback != null) callback(); - }); - } - - private static Texture2D ScaleImage(Texture2D source, int w, int h) - { - // Bug: When scaling down things look weird unless the source size is - // == 0 when mod 4. Therefore we just return null if that's the case. - if (source.width % 4 != 0) - return null; - - Texture2D result = new Texture2D(w, h, TextureFormat.RGB24, false, true); - Color[] rpixels = result.GetPixels(0); - - double dx = 1.0 / (double)w; - double dy = 1.0 / (double)h; - double x = 0; - double y = 0; - int idx = 0; - for (int j = 0; j < h; j++) - { - for (int i = 0; i < w; i++, idx++) - { - rpixels[idx] = source.GetPixelBilinear((float)x, (float)y); - x += dx; - } - x = 0; - y += dy; - } - result.SetPixels(rpixels, 0); - result.Apply(); - return result; - } - - public static bool ContainsAsset(int id) - { - return s_SelectedAssets != null && s_SelectedAssets.ContainsKey(id); - } - - public static void Clear() - { - if (s_SelectedAssets == null) - return; - foreach (var kv in s_SelectedAssets) - kv.Value.Dispose(); - - s_SelectedAssets.Clear(); - } - - public static int Count - { - get { return s_SelectedAssets == null ? 0 : s_SelectedAssets.Count; } - } - - public static bool Empty - { - get { return s_SelectedAssets == null ? true : s_SelectedAssets.Count == 0; } - } - - public static AssetStoreAsset GetFirstAsset() - { - if (s_SelectedAssets == null) - return null; - var i = s_SelectedAssets.GetEnumerator(); - if (!i.MoveNext()) - return null; - return i.Current.Value; - } - } -} // UnityEditor namespace diff --git a/Editor/Mono/AssetStore/AssetStoreClient.cs b/Editor/Mono/AssetStore/AssetStoreClient.cs deleted file mode 100644 index 35c26b544b..0000000000 --- a/Editor/Mono/AssetStore/AssetStoreClient.cs +++ /dev/null @@ -1,860 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -/* - * Server class handling communication with the server backend - * - * Jonas Drewsen - (C) Unity3d.com - 2011 - * - */ -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Text.RegularExpressions; -using System.IO; -using System.Collections.Generic; -using System; -using System.Net; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; - - -namespace UnityEditor -{ - /** - * The raw response from the asset store before being parsed into - * specific result class (see below). - */ - class AssetStoreResponse - { - internal AsyncHTTPClient job; - public Dictionary dict; - public bool ok; - public bool failed { get { return !ok; } } - public string message - { - get - { - if (dict == null || !dict.ContainsKey("message")) return null; - return dict["message"].AsString(true); - } - } - // Encode a string into a json string - private static string EncodeString(string str) - { - str = str.Replace("\"", "\\\""); - str = str.Replace("\\", "\\\\"); - str = str.Replace("\b", "\\b"); - str = str.Replace("\f", "\\f"); - str = str.Replace("\n", "\\n"); - str = str.Replace("\r", "\\r"); - str = str.Replace("\t", "\\t"); - // We do not use \uXXXX specifier but direct unicode in the string. - return str; - } - - public override string ToString() - { - string res = "{"; - string delim = ""; - foreach (KeyValuePair kv in dict) - { - res += delim + '"' + EncodeString(kv.Key) + "\" : " + kv.Value.ToString(); - delim = ", "; - } - return res + "}"; - } - } - - /** - * All results derive from this class. - */ - abstract class AssetStoreResultBase where Derived : class - { - public delegate void Callback(Derived res); - private Callback callback; - public string error; - public string warnings; - - public AssetStoreResultBase(Callback cb) - { - callback = cb; - warnings = ""; - } - - public void Parse(AssetStoreResponse response) - { - if (response.job.IsSuccess()) - { - if (response.job.responseCode >= 300) - error = string.Format("HTTP status code {0}", response.job.responseCode); - else if (response.dict.ContainsKey("error")) - error = response.dict["error"].AsString(true); - else - Parse(response.dict); - } - else - { - string url = response.job == null ? "nulljob" : (response.job.url == null ? "null" : response.job.url); - error = "Error receiving response from server on url '" + url + "': " + (response.job.text ?? "n/a"); - } - callback(this as Derived); - } - - abstract protected void Parse(Dictionary dict); - } - - - /** - * Result that contains the list of asset matching a search criteria. - */ - class AssetStoreSearchResults : AssetStoreResultBase - { - internal struct Group - { - public static Group Create() - { - Group g = new Group(); - g.assets = new List(); - g.label = ""; - g.name = ""; - g.offset = 0; - g.limit = -1; // no limit - return g; - } - - public List assets; - public int totalFound; - public string label; - public string name; - public int offset; - public int limit; - }; - - internal List groups = new List(); - - public AssetStoreSearchResults(Callback c) : base(c) {} - - protected override void Parse(Dictionary dict) - { - foreach (JSONValue v in dict["groups"].AsList(true)) - { - Group group = Group.Create(); - ParseList(v, ref group); - groups.Add(group); - } - JSONValue offsets = dict["query"]["offsets"]; - List limits = dict["query"]["limits"].AsList(true); - int idx = 0; - foreach (JSONValue v in offsets.AsList(true)) - { - Group g = groups[idx]; - g.offset = (int)v.AsFloat(true); - g.limit = (int)limits[idx].AsFloat(true); - groups[idx] = g; - idx++; - } - } - - static string StripExtension(string path) - { - if (path == null) return null; - - int i = path.LastIndexOf("."); - return i < 0 ? path : path.Substring(0, i); - } - - private void ParseList(JSONValue matches, ref Group group) - { - List assets = group.assets; - - if (matches.ContainsKey("error")) - error = matches["error"].AsString(true); - if (matches.ContainsKey("warnings")) - warnings = matches["warnings"].AsString(true); - - if (matches.ContainsKey("name")) - group.name = matches["name"].AsString(true); - if (matches.ContainsKey("label")) - group.label = matches["label"].AsString(true); - group.label = group.label ?? group.name; // fallback - if (matches.ContainsKey("total_found")) - group.totalFound = (int)matches["total_found"].AsFloat(true); - - if (matches.ContainsKey("matches")) - { - foreach (JSONValue asset in matches["matches"].AsList(true)) - { - AssetStoreAsset res = new AssetStoreAsset(); - if (!asset.ContainsKey("id") || !asset.ContainsKey("name") || !asset.ContainsKey("package_id")) - continue; - - res.id = (int)asset["id"].AsFloat(); - res.name = asset["name"].AsString(); - res.displayName = StripExtension(res.name); - res.packageID = (int)asset["package_id"].AsFloat(); - - if (asset.ContainsKey("static_preview_url")) - res.staticPreviewURL = asset["static_preview_url"].AsString(); - if (asset.ContainsKey("dynamic_preview_url")) - res.dynamicPreviewURL = asset["dynamic_preview_url"].AsString(); - - res.className = asset.ContainsKey("class_name") ? asset["class_name"].AsString() : ""; - if (asset.ContainsKey("price")) - res.price = asset["price"].AsString(); - assets.Add(res); - } - } - } - } - - /** - * Result that will flesh out the specified AssetStoreAssets with - * info to be displayed in an inspector. - */ - class AssetStoreAssetsInfo : AssetStoreResultBase - { - internal enum Status - { - BasketNotEmpty, - ServiceDisabled, - AnonymousUser, - Ok - } - internal Status status; - - internal Dictionary assets = new Dictionary(); - internal bool paymentTokenAvailable; - internal string paymentMethodCard; - internal string paymentMethodExpire; - internal float price; - internal float vat; - internal string currency; - internal string priceText; - internal string vatText; - internal string message; - - internal AssetStoreAssetsInfo(Callback c, List assets) : base(c) - { - foreach (AssetStoreAsset a in assets) - this.assets[a.id] = a; - } - - protected override void Parse(Dictionary dict) - { - Dictionary purchaseInfo = dict["purchase_info"].AsDict(true); - string statusStr = purchaseInfo["status"].AsString(true); - if (statusStr == "basket-not-empty") - status = Status.BasketNotEmpty; - else if (statusStr == "service-disabled") - status = Status.ServiceDisabled; - else if (statusStr == "user-anonymous") - status = Status.AnonymousUser; - else if (statusStr == "ok") - status = Status.Ok; - - paymentTokenAvailable = purchaseInfo["payment_token_available"].AsBool(); - if (purchaseInfo.ContainsKey("payment_method_card")) - paymentMethodCard = purchaseInfo["payment_method_card"].AsString(true); - if (purchaseInfo.ContainsKey("payment_method_expire")) - paymentMethodExpire = purchaseInfo["payment_method_expire"].AsString(true); - price = purchaseInfo["price"].AsFloat(true); - vat = purchaseInfo["vat"].AsFloat(true); - priceText = purchaseInfo["price_text"].AsString(true); - vatText = purchaseInfo["vat_text"].AsString(true); - currency = purchaseInfo["currency"].AsString(true); - message = purchaseInfo.ContainsKey("message") ? purchaseInfo["message"].AsString(true) : null; - - List assetsIn = dict["results"].AsList(true); - - foreach (JSONValue val in assetsIn) - { - AssetStoreAsset asset; - int aid = 0; - if (val["id"].IsString()) - aid = int.Parse(val["id"].AsString()); - else - aid = (int)val["id"].AsFloat(); - - if (!assets.TryGetValue(aid, out asset)) - continue; - - if (asset.previewInfo == null) - asset.previewInfo = new AssetStoreAsset.PreviewInfo(); - - AssetStoreAsset.PreviewInfo a = asset.previewInfo; - asset.className = val["class_names"].AsString(true).Trim(); - a.packageName = val["package_name"].AsString(true).Trim(); - a.packageShortUrl = val["short_url"].AsString(true).Trim(); - // a.packagePrice = val.ContainsKey("price_text") ? val["price_text"].AsString(true).Trim() : null; - asset.price = val.ContainsKey("price_text") ? val["price_text"].AsString(true).Trim() : null; - a.packageSize = int.Parse(val.Get("package_size").IsNull() ? "-1" : val["package_size"].AsString(true)); - asset.packageID = int.Parse(val["package_id"].AsString()); - a.packageVersion = val["package_version"].AsString(); - a.packageRating = int.Parse(val.Get("rating").IsNull() || val["rating"].AsString(true).Length == 0 ? "-1" : val["rating"].AsString(true)); - a.packageAssetCount = int.Parse(val["package_asset_count"].IsNull() ? "-1" : val["package_asset_count"].AsString(true)); - a.isPurchased = val.ContainsKey("purchased") ? val["purchased"].AsBool(true) : false; - a.isDownloadable = a.isPurchased || asset.price == null; - a.publisherName = val["publisher_name"].AsString(true).Trim(); - // a.previewBundle = (!val.ContainsKey("preview_bundle") || val["preview_bundle"].IsNull()) ? "" : val["preview_bundle"].AsString(true); - a.packageUrl = val.Get("package_url").IsNull() ? "" : val["package_url"].AsString(true); - a.encryptionKey = val.Get("encryption_key").IsNull() ? "" : val["encryption_key"].AsString(true); - a.categoryName = val.Get("category_name").IsNull() ? "" : val["category_name"].AsString(true); - a.buildProgress = -1f; - a.downloadProgress = -1f; - } - } - } - - /** - * Success of purchasing a package - */ - class PurchaseResult : AssetStoreResultBase - { - public enum Status - { - BasketNotEmpty, - ServiceDisabled, - AnonymousUser, - PasswordMissing, - PasswordWrong, - PurchaseDeclined, - Ok - } - public Status status; - public int packageID; - public string message; - - public PurchaseResult(Callback c) : base(c) - { - } - - protected override void Parse(Dictionary dict) - { - packageID = int.Parse(dict["package_id"].AsString()); - message = dict.ContainsKey("message") ? dict["message"].AsString(true) : null; - - string statusStr = dict["status"].AsString(true); - if (statusStr == "basket-not-empty") - status = Status.BasketNotEmpty; - else if (statusStr == "service-disabled") - status = Status.ServiceDisabled; - else if (statusStr == "user-anonymous") - status = Status.AnonymousUser; - else if (statusStr == "password-missing") - status = Status.PasswordMissing; - else if (statusStr == "password-wrong") - status = Status.PasswordWrong; - else if (statusStr == "purchase-declined") - status = Status.PurchaseDeclined; - else if (statusStr == "ok") - status = Status.Ok; - } - } - - /** - * Status of building a package on the asset store server. - */ - class BuildPackageResult : AssetStoreResultBase - { - internal AssetStoreAsset asset; - internal int packageID; - - internal BuildPackageResult(AssetStoreAsset asset, Callback c) : base(c) - { - this.asset = asset; - packageID = -1; - } - - protected override void Parse(Dictionary dict) - { - dict = dict["download"].AsDict(); - - packageID = int.Parse(dict["id"].AsString()); - if (packageID != asset.packageID) - { - Debug.LogError("Got asset store server build result from mismatching package"); - return; - } - asset.previewInfo.packageUrl = dict.ContainsKey("url") ? dict["url"].AsString(true) : ""; - asset.previewInfo.encryptionKey = dict.ContainsKey("key") ? dict["key"].AsString(true) : ""; - - // 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". - asset.previewInfo.buildProgress = (dict["progress"].IsFloat() ? dict["progress"].AsFloat(true) : float.Parse(dict["progress"].AsString(true), System.Globalization.CultureInfo.InvariantCulture)) / 100.0f; - } - } - - - /** - * The main API class for communication with the asset store server. - * Most interesting methods are the static ones specified in the - * bottom of this class. - */ - class AssetStoreClient - { - const string kUnauthSessionID = "26c4202eb475d02864b40827dfff11a14657aa41"; - - internal enum LoginState - { - LOGGED_OUT, - IN_PROGRESS, - LOGGED_IN, - LOGIN_ERROR - }; - - static string s_AssetStoreUrl = null; - static string s_AssetStoreSearchUrl = null; - static LoginState sLoginState = AssetStoreClient.LoginState.LOGGED_OUT; - static string sLoginErrorMessage = null; - public static string LoginErrorMessage { get { return sLoginErrorMessage; } } - public delegate void DoneCallback(AssetStoreResponse response); - public delegate void DoneLoginCallback(string errorMessage); - - // Version parameters expected by the server - static string VersionParams - { - get - { - return "unityversion=" + System.Uri.EscapeDataString(Application.unityVersion) + "&skip_terms=1"; - } - } - - // The base asset store url as parsed from the loader.html file - static string AssetStoreUrl - { - get - { - if (s_AssetStoreUrl == null) - s_AssetStoreUrl = AssetStoreUtils.GetAssetStoreUrl(); - // s_AssetStoreUrl = "https://kharma-test.unity3d.com"; - return s_AssetStoreUrl; - } - } - - // The base asset store url as parsed from the loader.html file - static string AssetStoreSearchUrl - { - get - { - if (s_AssetStoreSearchUrl == null) - s_AssetStoreSearchUrl = AssetStoreUtils.GetAssetStoreSearchUrl(); - // s_AssetStoreSearchUrl = "http://shawarma-test.unity3d.com"; - return s_AssetStoreSearchUrl; - } - } - - static AssetStoreClient() - { - ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; - } - - // The base server API url. This is used for all the normal request towards the server API. - static string APIUrl(string path) - { - return String.Format("{0}/api{2}.json?{1}" , AssetStoreUrl, VersionParams, path); - } - - static string APISearchUrl(string path) - { - return String.Format("{0}/public-api{2}.json?{1}" , AssetStoreSearchUrl, VersionParams, path); - } - - // The saved session ID if the user has allowed remembering it. - static string SavedSessionID - { - get - { - if (RememberSession) - return EditorPrefs.GetString("kharma.sessionid", ""); - return ""; - } - set { EditorPrefs.SetString("kharma.sessionid", value); } - } - - public static bool HasSavedSessionID - { - get { return !string.IsNullOrEmpty(SavedSessionID); } - } - - internal static string ActiveSessionID - { - get - { - if (AssetStoreContext.SessionHasString("kharma.active_sessionid")) - return AssetStoreContext.SessionGetString("kharma.active_sessionid"); - return ""; - } - set { AssetStoreContext.SessionSetString("kharma.active_sessionid", value); } - } - - public static bool HasActiveSessionID - { - get { return !string.IsNullOrEmpty(ActiveSessionID); } - } - - static string ActiveOrUnauthSessionID - { - get - { - string s = ActiveSessionID; - if (s == "") - return kUnauthSessionID; - return s; - } - } - - static public bool RememberSession - { - get { return EditorPrefs.GetString("kharma.remember_session") == "1"; } - set { EditorPrefs.SetString("kharma.remember_session", value ? "1" : "0"); } - } - - // The authentication token - static string GetToken() - { - return InternalEditorUtility.GetAuthToken(); - } - - // Login status - public static bool LoggedIn() { return !string.IsNullOrEmpty(ActiveSessionID); } - public static bool LoggedOut() { return string.IsNullOrEmpty(ActiveSessionID); } - public static bool LoginError() { return sLoginState == LoginState.LOGIN_ERROR; } - public static bool LoginInProgress() { return sLoginState == LoginState.IN_PROGRESS; } - - internal static void LoginWithCredentials(string username, string password, bool rememberMe, DoneLoginCallback callback) - { - if (sLoginState == LoginState.IN_PROGRESS) - { - Debug.LogError("Tried to login with credentials while already in progress of logging in"); - return; - } - sLoginState = LoginState.IN_PROGRESS; - RememberSession = rememberMe; - string url = AssetStoreUrl + "/login?skip_terms=1"; - - AssetStoreClient.sLoginErrorMessage = null; - AsyncHTTPClient client = new AsyncHTTPClient(url.Replace("http://", "https://")); - client.postData = "user=" + username + "&pass=" + password; - client.header["X-Unity-Session"] = kUnauthSessionID + GetToken(); - client.doneCallback = WrapLoginCallback(callback); - client.Begin(); - } - - /* - * Tries to login using a remembered session - */ - internal static void LoginWithRememberedSession(DoneLoginCallback callback) - { - if (sLoginState == LoginState.IN_PROGRESS) - { - Debug.LogError("Tried to login with remembered session while already in progress of logging in"); - return; - } - sLoginState = LoginState.IN_PROGRESS; - - // Make sure the session is not present if we're not allowed to use it - if (!RememberSession) - SavedSessionID = ""; - - string url = AssetStoreUrl + "/login?skip_terms=1&reuse_session=" + SavedSessionID; - AssetStoreClient.sLoginErrorMessage = null; - AsyncHTTPClient client = new AsyncHTTPClient(url); - client.header["X-Unity-Session"] = kUnauthSessionID + GetToken(); - client.doneCallback = WrapLoginCallback(callback); - client.Begin(); - } - - // Helper function for login callbacks - static AsyncHTTPClient.DoneCallback WrapLoginCallback(DoneLoginCallback callback) - { - return delegate(AsyncHTTPClient job) { - // We're logging in - string msg = job.text; - if (!job.IsSuccess()) - { - AssetStoreClient.sLoginState = LoginState.LOGIN_ERROR; - AssetStoreClient.sLoginErrorMessage = job.responseCode >= 200 && job.responseCode < 300 ? msg : "Failed to login - please retry"; - } - else if (msg.StartsWith(" param, - DoneCallback callback) - { - AsyncHTTPClient client = new AsyncHTTPClient(url); - - client.header["X-Unity-Session"] = ActiveOrUnauthSessionID + GetToken(); - client.postDictionary = param; - - client.doneCallback = WrapJsonCallback(callback); - client.Begin(); - return client; - } - - // Create a pending HTTP POST request to the server - static AsyncHTTPClient CreateJSONRequestPost(string url, string postData, - DoneCallback callback) - { - AsyncHTTPClient client = new AsyncHTTPClient(url); - - client.header["X-Unity-Session"] = ActiveOrUnauthSessionID + GetToken(); - client.postData = postData; - - client.doneCallback = WrapJsonCallback(callback); - client.Begin(); - return client; - } - - /* TODO: Implement PUT from a filepath in back end curl code - // Create a pending HTTP PUT request to the server - static void CreateJSONRequestPut(string url, string filepath, - DoneCallback callback) { - AsyncHTTPClient job = new AsyncHTTPClient(url, "PUT"); - client.SetUploadFilePath(filepath); - client.header["X-Unity-Session"] = ActiveOrUnauthSessionID + GetToken(); - client.doneCallback = WrapJsonCallback(callback); - client.Begin(); - } - */ - - // Create a pending HTTP DELETE request to the server - static AsyncHTTPClient CreateJSONRequestDelete(string url, DoneCallback callback) - { - AsyncHTTPClient client = new AsyncHTTPClient(url, "DELETE"); - client.header["X-Unity-Session"] = ActiveOrUnauthSessionID + GetToken(); - client.doneCallback = WrapJsonCallback(callback); - client.Begin(); - return client; - } - - /* Handle HTTP results and forward them to the original callback. - * - * This will callback any handler registered for requests that has finished. - */ - private static AsyncHTTPClient.DoneCallback WrapJsonCallback(DoneCallback callback) - { - return delegate(AsyncHTTPClient job) { - if (job.IsDone()) - { - try - { - AssetStoreResponse c = ParseContent(job); - callback(c); - } - catch (Exception ex) - { - Debug.Log("Uncaught exception in async net callback: " + ex.Message); - Debug.Log(ex.StackTrace); - } - } - }; - } - - /* - * Parse the HTTP response as a JSON string and into a AssetStoreResponse object. - */ - static AssetStoreResponse ParseContent(AsyncHTTPClient job) - { - AssetStoreResponse resp = new AssetStoreResponse(); - resp.job = job; - resp.dict = null; - resp.ok = false; - AsyncHTTPClient.State state = job.state; - string content = job.text; - if (!AsyncHTTPClient.IsSuccess(state)) - { - Console.WriteLine(content); - // Debug.Log("Request error: " + content); - return resp; // abort - } - - string status; - string message; - resp.dict = ParseJSON(content, out status, out message); - if (status == "error") - { - Debug.LogError("Request error (" + status + "): " + message); - return resp; - } - resp.ok = true; - return resp; - } - - /* - * Parse the HTTP response as a JSON string into a string/JSONValue dictionary - */ - static Dictionary ParseJSON(string content, out string status, out string message) - { - // extract ids etc. from json message - message = null; - status = null; - JSONValue jval; - try - { - JSONParser parser = new JSONParser(content); - jval = parser.Parse(); - } - catch (JSONParseException ex) - { - Debug.Log("Error parsing server reply: " + content); - Debug.Log(ex.Message); - return null; - } - Dictionary dict; - try - { - dict = jval.AsDict(true); - if (dict == null) - { - Debug.Log("Error parsing server message: " + content); - return null; - } - // Old backend encapsulated all replies in a "result" dict. Just unwrap that here. - if (dict.ContainsKey("result") && dict["result"].IsDict()) - { - dict = dict["result"].AsDict(true); - } - - if (dict.ContainsKey("message")) - message = dict["message"].AsString(true); - if (dict.ContainsKey("status")) - status = dict["status"].AsString(true); - else if (dict.ContainsKey("error")) - { - status = dict["error"].AsString(true); - if (status == "") - status = "ok"; - } - else - status = "ok"; - } - catch (JSONTypeException ex) - { - Debug.Log("Error parsing server reply. " + content); - Debug.Log(ex.Message); - return null; - } - return dict; - } - - internal struct SearchCount - { - public string name; - public int offset; - public int limit; - } - - - /* - * Searches the asset store for assets and passes the results to DoneCallback - */ - internal static AsyncHTTPClient SearchAssets(string searchString, string[] requiredClassNames, string[] assetLabels, - List counts, - AssetStoreSearchResults.Callback callback) - { - string offsets = ""; - string limits = ""; - string groupNames = ""; - string delim = ""; - foreach (SearchCount v in counts) - { - offsets += delim + v.offset; - limits += delim + v.limit; - groupNames += delim + v.name; - delim = ","; - } - - // If one af the class names is "MonoScript" then also include "Script" since - // that is what asset store expects - if (Array.Exists(requiredClassNames, (string a) => { return a.Equals("MonoScript", StringComparison.OrdinalIgnoreCase); })) - { - Array.Resize(ref requiredClassNames, requiredClassNames.Length + 1); - requiredClassNames[requiredClassNames.Length - 1] = "Script"; - } - - string url = string.Format("{0}&q={1}&c={2}&l={3}&O={4}&N={5}&G={6}", - APISearchUrl("/search/assets"), - System.Uri.EscapeDataString(searchString), - System.Uri.EscapeDataString(string.Join(",", requiredClassNames)), - System.Uri.EscapeDataString(string.Join(",", assetLabels)), - offsets, limits, groupNames); - - //Debug.Log(url); - //Debug.Log("session key " + ActiveOrUnauthSessionID + GetToken()); - AssetStoreSearchResults r = new AssetStoreSearchResults(callback); - return CreateJSONRequest(url, delegate(AssetStoreResponse ar) { r.Parse(ar); }); - } - - /* - * Looks up assets by ID in the asset store and passes the results to DoneCallback - */ - internal static AsyncHTTPClient AssetsInfo(List assets, AssetStoreAssetsInfo.Callback callback) - { - string url = APIUrl("/assets/list"); - foreach (AssetStoreAsset asset in assets) - url += "&id=" + asset.id.ToString(); - // Debug.Log(url); - AssetStoreAssetsInfo r = new AssetStoreAssetsInfo(callback, assets); - return CreateJSONRequest(url, delegate(AssetStoreResponse ar) { r.Parse(ar); }); - } - - /* - * Returns purchase info for the package that has assetID as part of it. - */ - internal static AsyncHTTPClient DirectPurchase(int packageID, string password, PurchaseResult.Callback callback) - { - string url = APIUrl(string.Format("/purchase/direct/{0}", packageID.ToString())); - // Debug.Log(url); - PurchaseResult r = new PurchaseResult(callback); - Dictionary d = new Dictionary(); - d["password"] = password; - return CreateJSONRequestPost(url, d, delegate(AssetStoreResponse ar) { r.Parse(ar); }); - } - - internal static AsyncHTTPClient BuildPackage(AssetStoreAsset asset, BuildPackageResult.Callback callback) - { - string url = APIUrl("/content/download/" + asset.packageID.ToString()); - // Debug.Log(url); - BuildPackageResult r = new BuildPackageResult(asset, callback); - return CreateJSONRequest(url, delegate(AssetStoreResponse ar) { r.Parse(ar); }); - } - } -} diff --git a/Editor/Mono/AssetStore/AssetStoreContext.cs b/Editor/Mono/AssetStore/AssetStoreContext.cs deleted file mode 100644 index 67dad2e51f..0000000000 --- a/Editor/Mono/AssetStore/AssetStoreContext.cs +++ /dev/null @@ -1,435 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.Linq; -using System.IO; -using UnityEditor.Web; - -namespace UnityEditor -{ - /// - /// The interface of this class is mirrored into the browser's JavaScript world as - /// "window.context". - /// - /// - /// The WebView will expose the methods of this class as functions on the JavaScript - /// object created by AssetStoreWindow.SetContextObject(). Return values and arguments - /// of these methods can be any primitive type, arrays of any other valid type, and - /// classes with public fields of any other valid type. In the last case, objects of - /// these classes will be translate to and from JavaScript objects with C# fields mapping - /// to JavaScript properties. - /// - [InitializeOnLoad] - internal partial class AssetStoreContext - { - static AssetStoreContext() - { - AssetStoreContext.GetInstance(); - } - - public static AssetStoreContext GetInstance() - { - if (s_Instance == null) - { - s_Instance = new AssetStoreContext(); - JSProxyMgr.GetInstance().AddGlobalObject("AssetStoreContext", s_Instance); - } - - return s_Instance; - } - - public string GetInitialOpenURL() - { - if (initialOpenURL != null) - { - string tmp = initialOpenURL; - initialOpenURL = null; - return tmp; - } - else - { - return ""; - } - } - - public string GetAuthToken() - { - return UnityEditorInternal.InternalEditorUtility.GetAuthToken(); - } - - public int[] GetLicenseFlags() - { - return UnityEditorInternal.InternalEditorUtility.GetLicenseFlags(); - } - - public string GetString(string key) - { - return EditorPrefs.GetString(key); - } - - public int GetInt(string key) - { - return EditorPrefs.GetInt(key); - } - - public float GetFloat(string key) - { - return EditorPrefs.GetFloat(key); - } - - public void SetString(string key, string value) - { - EditorPrefs.SetString(key, value); - } - - public void SetInt(string key, int value) - { - EditorPrefs.SetInt(key, value); - } - - public void SetFloat(string key, float value) - { - EditorPrefs.SetFloat(key, value); - } - - public bool HasKey(string key) - { - return EditorPrefs.HasKey(key); - } - - public void DeleteKey(string key) - { - EditorPrefs.DeleteKey(key); - } - - public int GetSkinIndex() - { - return EditorGUIUtility.skinIndex; - } - - public bool GetDockedStatus() - { - return docked; - } - - public bool OpenPackage(string id) - { - return OpenPackage(id, "default"); - } - - public bool OpenPackage(string id, string action) - { - return OpenPackageInternal(id); - } - - public static bool OpenPackageInternal(string id) - { - Match match = s_GeneratedIDRegExp.Match(id); - if (match.Success && File.Exists(match.Groups[1].Value)) // If id looks like a path name, just try to open that - { - AssetDatabase.ImportPackage(match.Groups[1].Value, true); - return true; - } - else - { - foreach (PackageInfo package in PackageInfo.GetPackageList()) - { - if (package.jsonInfo != "") - { - JSONValue item = JSONParser.SimpleParse(package.jsonInfo); - string itemID = item.Get("id").IsNull() ? null : item["id"].AsString(true); - if (itemID != null && itemID == id && File.Exists(package.packagePath)) - { - AssetDatabase.ImportPackage(package.packagePath, true); - return true; - } - } - } - } - Debug.LogError("Unknown package ID " + id); - return false; - } - - public void OpenBrowser(string url) - { - Application.OpenURL(url); - } - - public void Download(Package package, DownloadInfo downloadInfo) - { - Download( - downloadInfo.id, - downloadInfo.url, - downloadInfo.key, - package.title, - package.publisher.label, - package.category.label, - null - ); - } - - public static void Download(string package_id, string url, string key, string package_name, - string publisher_name, string category_name, AssetStoreUtils.DownloadDoneCallback doneCallback) - { - string[] dest = PackageStorePath(publisher_name, category_name, - package_name, package_id, url); - - JSONValue existing = JSONParser.SimpleParse(AssetStoreUtils.CheckDownload(package_id, url, dest, key)); - - // If the package is actively being downloaded right now just return - if (existing.Get("in_progress").AsBool(true)) - { - Debug.Log("Will not download " + package_name + ". Download is already in progress."); - return; - } - - // The package is not being downloaded. - // If the package has previously been partially downloaded then - // resume that download. - string existingUrl = existing.Get("download.url").AsString(true); - string existingKey = existing.Get("download.key").AsString(true); - bool resumeOK = (existingUrl == url && existingKey == key); - - JSONValue download = new JSONValue(); - download["url"] = url; - download["key"] = key; - JSONValue parameters = new JSONValue(); - parameters["download"] = download; - - AssetStoreUtils.Download(package_id, url, dest, key, parameters.ToString(), resumeOK, doneCallback); - } - - /// - /// Create an array consisting of publisherName, categoryName and packageName - /// This is to be used by AssetStoreUtils.*Download functions - /// - public static string[] PackageStorePath(string publisher_name, - string category_name, - string package_name, - string package_id, - string url) - { - string[] dest = { publisher_name, category_name, package_name }; - - for (int i = 0; i < 3; i++) - dest[i] = s_InvalidPathCharsRegExp.Replace(dest[i], ""); - - // If package name cannot be stored as a valid file name, use the package id - if (dest[2] == "") - dest[2] = s_InvalidPathCharsRegExp.Replace(package_id, ""); - - // If still no valid chars use a mangled url as the file name - if (dest[2] == "") - dest[2] = s_InvalidPathCharsRegExp.Replace(url, ""); - - return dest; - } - - public PackageList GetPackageList() - { - var packages = new Dictionary(); - var packageInfos = PackageInfo.GetPackageList(); - - foreach (PackageInfo info in packageInfos) - { - Package package = new Package(); - if (info.jsonInfo == "") - { - package.title = System.IO.Path.GetFileNameWithoutExtension(info.packagePath); - package.id = info.packagePath; - - if (IsBuiltinStandardAsset(info.packagePath)) - { - package.publisher = new LabelAndId { label = "Unity Technologies", id = "1" }; - package.category = new LabelAndId { label = "Prefab Packages", id = "4" }; - package.version = "3.5.0.0"; - } - } - else - { - var jsonData = JSONParser.SimpleParse(info.jsonInfo); - if (jsonData.IsNull()) - continue; - - package.Initialize(jsonData); - - if (package.id == null) - { - var linkId = jsonData.Get("link.id"); - if (!linkId.IsNull()) - package.id = linkId.AsString(); - else - package.id = info.packagePath; - } - } - - package.local_icon = info.iconURL; - package.local_path = info.packagePath; - - // If no package with the same ID is in the dictionary yet or if the current package - // is newer than what we currently have in the dictionary, add the package to the - // dictionary. - if (!packages.ContainsKey(package.id) || - packages[package.id].version_id == null || - packages[package.id].version_id == "-1" || - (package.version_id != null && package.version_id != "-1" && Int32.Parse(packages[package.id].version_id) <= Int32.Parse(package.version_id))) - { - packages[package.id] = package; - } - } - - var results = packages.Values.ToArray(); - return new PackageList { results = results }; - } - - private bool IsBuiltinStandardAsset(string path) - { - return s_StandardPackageRegExp.IsMatch(path); - } - - 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); - private static Regex s_GeneratedIDRegExp = new Regex(@"^\{(.*)\}$"); - private static Regex s_InvalidPathCharsRegExp = new Regex(@"[^a-zA-Z0-9() _-]"); - - internal bool docked; - internal string initialOpenURL; - - private static AssetStoreContext s_Instance; - - // Some data is created through reflection in C++ and then - // passed on to us. Shut up warning about fields that are - // never assigned to. - #pragma warning disable 0649 - - // The following classes are used for data interchange with JavaScript. - // Public fields in them directly translate to respective properties on - // JavaScript objects. - - public class DownloadInfo - { - public string url; - public string key; - public string id; - } - - public class LabelAndId - { - public string label; - public string id; - - public void Initialize(JSONValue json) - { - if (json.ContainsKey("label")) - label = json["label"].AsString(); - - if (json.ContainsKey("id")) - id = json["id"].AsString(); - } - - public override string ToString() - { - return string.Format("{{label={0}, id={1}}}", label, id); - } - } - - public class Link - { - public string type; - public string id; - - public void Initialize(JSONValue json) - { - if (json.ContainsKey("type")) - type = json["type"].AsString(); - - if (json.ContainsKey("id")) - id = json["id"].AsString(); - } - - public override string ToString() - { - return string.Format("{{type={0}, id={1}}}", type, id); - } - } - - public class Package - { - public string title; - public string id; - public string version; - public string version_id; - public string local_icon; - public string local_path; - public string pubdate; - public string description; - public LabelAndId publisher; - public LabelAndId category; - public Link link; - - public void Initialize(JSONValue json) - { - if (json.ContainsKey("title")) - title = json["title"].AsString(); - - if (json.ContainsKey("id")) - id = json["id"].AsString(); - - if (json.ContainsKey("version")) - version = json["version"].AsString(); - - if (json.ContainsKey("version_id")) - version_id = json["version_id"].AsString(); - - if (json.ContainsKey("local_icon")) - local_icon = json["local_icon"].AsString(); - - if (json.ContainsKey("local_path")) - local_path = json["local_path"].AsString(); - - if (json.ContainsKey("pubdate")) - pubdate = json["pubdate"].AsString(); - - if (json.ContainsKey("description")) - description = json["description"].AsString(); - - if (json.ContainsKey("publisher")) - { - publisher = new LabelAndId(); - publisher.Initialize(json["publisher"]); - } - - if (json.ContainsKey("category")) - { - category = new LabelAndId(); - category.Initialize(json["category"]); - } - - if (json.ContainsKey("link")) - { - link = new Link(); - link.Initialize(json["link"]); - } - } - - public override string ToString() - { - return string.Format - ("{{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}}}", - title, id, publisher, category, version, version_id, local_icon, local_path, pubdate, description, link); - } - } - - public class PackageList - { - public Package[] results; - } - } -} diff --git a/Editor/Mono/AssetStore/AssetStoreInstaBuyWindow.cs b/Editor/Mono/AssetStore/AssetStoreInstaBuyWindow.cs deleted file mode 100644 index 51e4988cd8..0000000000 --- a/Editor/Mono/AssetStore/AssetStoreInstaBuyWindow.cs +++ /dev/null @@ -1,521 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.Collections; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor -{ - /** - * A dialog that lists packages to purchase and - * a password in order to acknowledge purchase. - * Will should purchase success or failure and - * the option to import package on successful purchase. - */ - internal class AssetStoreInstaBuyWindow : EditorWindow - { - const int kStandardHeight = 160; - - enum PurchaseStatus - { - Init, - InProgress, - Declined, - Complete, - StartBuild, - Building, - Downloading - }; - - // Open the dialog to allow the user to purchase the asset - static public AssetStoreInstaBuyWindow ShowAssetStoreInstaBuyWindow(AssetStoreAsset asset, string purchaseMessage, string paymentMethodCard, string paymentMethodExpire, string priceText) - { - AssetStoreInstaBuyWindow w = EditorWindow.GetWindowWithRect(new Rect(100, 100, 400, kStandardHeight), true, "Buy package from Asset Store"); - if (w.m_Purchasing != PurchaseStatus.Init) - { - EditorUtility.DisplayDialog("Download in progress", "There is already a package download in progress. You can only have one download running at a time", "Close"); - return w; - } - - w.position = new Rect(100, 100, 400, kStandardHeight); - w.m_Parent.window.m_DontSaveToLayout = true; - w.m_Asset = asset; - w.m_Password = ""; - w.m_Message = ""; - w.m_Purchasing = PurchaseStatus.Init; - w.m_NextAllowedBuildRequestTime = 0.0; - w.m_BuildAttempts = 0; - - w.m_PurchaseMessage = purchaseMessage; - w.m_PaymentMethodCard = paymentMethodCard; - w.m_PaymentMethodExpire = paymentMethodExpire; - w.m_PriceText = priceText; - UsabilityAnalytics.Track(string.Format("/AssetStore/ShowInstaBuy/{0}/{1}", w.m_Asset.packageID, w.m_Asset.id)); - return w; - } - - // For free or already purchased packages this will open the dialog - // and just import the package. - static public void ShowAssetStoreInstaBuyWindowBuilding(AssetStoreAsset asset) - { - AssetStoreInstaBuyWindow w = ShowAssetStoreInstaBuyWindow(asset, "", "", "", ""); - if (w.m_Purchasing != PurchaseStatus.Init) - { - EditorUtility.DisplayDialog("Download in progress", "There is already a package download in progress. You can only have one download running at a time", "Close"); - return; - } - w.m_Purchasing = PurchaseStatus.StartBuild; - w.m_BuildAttempts = 1; - asset.previewInfo.buildProgress = 0f; - UsabilityAnalytics.Track(string.Format("/AssetStore/ShowInstaFree/{0}/{1}", w.m_Asset.packageID, w.m_Asset.id)); - } - - private static GUIContent s_AssetStoreLogo; - - private static void LoadLogos() - { - if (s_AssetStoreLogo != null) - return; - s_AssetStoreLogo = EditorGUIUtility.IconContent("WelcomeScreen.AssetStoreLogo"); - } - - private string m_Password = ""; - private AssetStoreAsset m_Asset = null; - private string m_Message = ""; - PurchaseStatus m_Purchasing = PurchaseStatus.Init; - private double m_NextAllowedBuildRequestTime = 0.0; - private const double kBuildPollInterval = 2.0; - private const int kMaxPolls = 5 * 30; - private int m_BuildAttempts = 0; // 5 minutes - - private string m_PurchaseMessage = null; - private string m_PaymentMethodCard = null; - private string m_PaymentMethodExpire = null; - private string m_PriceText = null; - - public void OnInspectorUpdate() - { - if (m_Purchasing == PurchaseStatus.StartBuild && - m_NextAllowedBuildRequestTime <= EditorApplication.timeSinceStartup) - { - m_NextAllowedBuildRequestTime = EditorApplication.timeSinceStartup + kBuildPollInterval; - BuildPackage(); - } - } - - void OnEnable() - { - AssetStoreUtils.RegisterDownloadDelegate(this); - } - - public void OnDisable() - { - AssetStoreAsset.PreviewInfo info = m_Asset == null ? null : m_Asset.previewInfo; - if (info != null) - { - info.downloadProgress = -1f; - info.buildProgress = -1; - } - AssetStoreUtils.UnRegisterDownloadDelegate(this); - m_Purchasing = PurchaseStatus.Init; - } - - // Callback handler for internal curl - public void OnDownloadProgress(string id, string message, int bytes, int total) - { - AssetStoreAsset.PreviewInfo info = m_Asset == null ? null : m_Asset.previewInfo; - if (info == null || m_Asset.packageID.ToString() != id) - return; - - if (message == "downloading" || message == "connecting") - { - info.downloadProgress = (float)bytes / (float)total; - } - else - { - info.downloadProgress = -1f; - } - Repaint(); - } - - public void OnGUI() - { - LoadLogos(); - if (m_Asset == null) - return; - - // Currently we only support selling a single asset at a time. - GUILayout.BeginVertical(); - GUILayout.Space(10); - - switch (m_Purchasing) - { - case PurchaseStatus.Init: - PasswordGUI(); - break; - case PurchaseStatus.InProgress: - if (m_Purchasing == PurchaseStatus.InProgress) - GUI.enabled = false; - PasswordGUI(); - break; - case PurchaseStatus.Declined: - PurchaseDeclinedGUI(); - break; - case PurchaseStatus.Complete: - PurchaseSuccessGUI(); - break; - case PurchaseStatus.StartBuild: - case PurchaseStatus.Building: - case PurchaseStatus.Downloading: - DownloadingGUI(); - break; - } - - GUILayout.EndVertical(); - } - - void PasswordGUI() - { - AssetStoreAsset.PreviewInfo item = m_Asset.previewInfo; - GUILayout.BeginHorizontal(); - GUILayout.Space(5); - GUILayout.Label(s_AssetStoreLogo, GUIStyle.none, GUILayout.ExpandWidth(false)); - GUILayout.BeginVertical(); - GUILayout.Label("Complete purchase by entering your AssetStore password", EditorStyles.boldLabel); - bool hasMessage = m_PurchaseMessage != null && m_PurchaseMessage != ""; - bool hasErrorMessage = m_Message != null && m_Message != ""; - float newHeight = kStandardHeight + (hasMessage ? 20 : 0) + (hasErrorMessage ? 20 : 0); - if (newHeight != position.height) - position = new Rect(position.x, position.y, position.width, newHeight); - - if (hasMessage) - GUILayout.Label(m_PurchaseMessage, EditorStyles.wordWrappedLabel); - if (hasErrorMessage) - { - Color oldColor = GUI.color; - GUI.color = Color.red; - GUILayout.Label(m_Message, EditorStyles.wordWrappedLabel); - GUI.color = oldColor; - } - GUILayout.Label("Package: " + item.packageName, EditorStyles.wordWrappedLabel); - string cardInfo = string.Format("Credit card: {0} (expires {1})", m_PaymentMethodCard, m_PaymentMethodExpire); - GUILayout.Label(cardInfo, EditorStyles.wordWrappedLabel); - GUILayout.Space(8); - EditorGUILayout.LabelField("Amount", m_PriceText); - m_Password = EditorGUILayout.PasswordField("Password", m_Password); - GUILayout.EndVertical(); - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.FlexibleSpace(); - - GUILayout.BeginHorizontal(); - GUILayout.Space(8); - if (GUILayout.Button("Just put to basket...")) - { - AssetStore.Open(string.Format("content/{0}/basketpurchase", m_Asset.packageID)); - UsabilityAnalytics.Track(string.Format("/AssetStore/PutToBasket/{0}/{1}", m_Asset.packageID, m_Asset.id)); - m_Asset = null; - this.Close(); - GUIUtility.ExitGUI(); - } - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Cancel")) - { - UsabilityAnalytics.Track(string.Format("/AssetStore/CancelInstaBuy/{0}/{1}", m_Asset.packageID, m_Asset.id)); - m_Asset = null; - this.Close(); - GUIUtility.ExitGUI(); - } - GUILayout.Space(5); - if (GUILayout.Button("Complete purchase")) - CompletePurchase(); - - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.Space(5); - } - - void PurchaseSuccessGUI() - { - AssetStoreAsset.PreviewInfo item = m_Asset.previewInfo; - GUILayout.BeginHorizontal(); - GUILayout.Space(5); - GUILayout.Label(s_AssetStoreLogo, GUIStyle.none, GUILayout.ExpandWidth(false)); - GUILayout.BeginVertical(); - GUILayout.Label("Purchase completed succesfully", EditorStyles.boldLabel); - GUILayout.Label("You will receive a receipt in your email soon."); - - bool hasMessage = m_Message != null && m_Message != ""; - float newHeight = kStandardHeight + (hasMessage ? 20 : 0); - if (newHeight != position.height) - position = new Rect(position.x, position.y, position.width, newHeight); - - if (hasMessage) - GUILayout.Label(m_Message, EditorStyles.wordWrappedLabel); - - GUILayout.Label("Package: " + item.packageName, EditorStyles.wordWrappedLabel); - - GUILayout.EndVertical(); - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.FlexibleSpace(); - - GUILayout.BeginHorizontal(); - GUILayout.Space(8); - - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Close")) - { - UsabilityAnalytics.Track(string.Format("/AssetStore/PurchaseOk/{0}/{1}", m_Asset.packageID, m_Asset.id)); - m_Asset = null; - this.Close(); - } - GUILayout.Space(5); - if (GUILayout.Button("Import package")) - { - UsabilityAnalytics.Track(string.Format("/AssetStore/PurchaseOkImport/{0}/{1}", m_Asset.packageID, m_Asset.id)); - m_BuildAttempts = 1; - m_Asset.previewInfo.buildProgress = 0f; - m_Purchasing = PurchaseStatus.StartBuild; - } - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.Space(5); - } - - void DownloadingGUI() - { - AssetStoreAsset.PreviewInfo item = m_Asset.previewInfo; - GUILayout.BeginHorizontal(); - GUILayout.Space(5); - GUILayout.Label(s_AssetStoreLogo, GUIStyle.none, GUILayout.ExpandWidth(false)); - GUILayout.BeginVertical(); - string label = "Importing"; // m_Purchasing == PurchaseStatus.Downloading ? "Downloading" : "Building"; - GUILayout.Label(label, EditorStyles.boldLabel); - GUILayout.Label("Package: " + item.packageName, EditorStyles.wordWrappedLabel); - // TODO: show progress when multiple progress delegates works - GUILayout.Label(" "); - if (Event.current.type == EventType.Repaint) - { - Rect r = GUILayoutUtility.GetLastRect(); - r.height += 1; - bool downloading = item.downloadProgress >= 0; - EditorGUI.ProgressBar(r, - downloading ? item.downloadProgress : item.buildProgress, - downloading ? "Downloading" : "Building"); - } - - GUILayout.EndVertical(); - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.FlexibleSpace(); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Abort")) - this.Close(); - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.Space(5); - } - - void PurchaseDeclinedGUI() - { - AssetStoreAsset.PreviewInfo item = m_Asset.previewInfo; - GUILayout.BeginHorizontal(); - GUILayout.Space(5); - GUILayout.Label(s_AssetStoreLogo, GUIStyle.none, GUILayout.ExpandWidth(false)); - GUILayout.BeginVertical(); - GUILayout.Label("Purchase declined", EditorStyles.boldLabel); - GUILayout.Label("No money has been drawn from you credit card"); - - bool hasMessage = m_Message != null && m_Message != ""; - float newHeight = kStandardHeight + (hasMessage ? 20 : 0); - if (newHeight != position.height) - position = new Rect(position.x, position.y, position.width, newHeight); - - if (hasMessage) - GUILayout.Label(m_Message, EditorStyles.wordWrappedLabel); - - GUILayout.Label("Package: " + item.packageName, EditorStyles.wordWrappedLabel); - - GUILayout.EndVertical(); - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.FlexibleSpace(); - - GUILayout.BeginHorizontal(); - GUILayout.Space(8); - - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Close")) - { - UsabilityAnalytics.Track(string.Format("/AssetStore/DeclinedAbort/{0}/{1}", m_Asset.packageID, m_Asset.id)); - m_Asset = null; - Close(); - } - GUILayout.Space(5); - if (GUILayout.Button("Put to basket")) - { - AssetStore.Open(string.Format("content/{0}/basketpurchase", m_Asset.packageID)); - UsabilityAnalytics.Track(string.Format("/AssetStore/DeclinedPutToBasket/{0}/{1}", m_Asset.packageID, m_Asset.id)); - m_Asset = null; - Close(); - } - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.Space(5); - } - - void CompletePurchase() - { - m_Message = ""; - string pw = m_Password; - m_Password = ""; - m_Purchasing = PurchaseStatus.InProgress; - AssetStoreClient.DirectPurchase(m_Asset.packageID, pw, delegate(PurchaseResult result) { - m_Purchasing = PurchaseStatus.Init; - if (result.error != null) - { - m_Purchasing = PurchaseStatus.Declined; - m_Message = "An error occurred while completing you purhase."; - Close(); - } - - string msg = null; - switch (result.status) - { - case PurchaseResult.Status.BasketNotEmpty: - m_Message = "Something else has been put in our Asset Store basket while doing this purchase."; - m_Purchasing = PurchaseStatus.Declined; - break; - case PurchaseResult.Status.ServiceDisabled: - m_Message = "Single click purchase has been disabled while doing this purchase."; - m_Purchasing = PurchaseStatus.Declined; - break; - case PurchaseResult.Status.AnonymousUser: - m_Message = "You have been logged out from somewhere else while doing this purchase."; - m_Purchasing = PurchaseStatus.Declined; - break; - case PurchaseResult.Status.PasswordMissing: - m_Message = result.message; - Repaint(); - break; - case PurchaseResult.Status.PasswordWrong: - m_Message = result.message; - Repaint(); - break; - case PurchaseResult.Status.PurchaseDeclined: - m_Purchasing = PurchaseStatus.Declined; - if (result.message != null) - m_Message = result.message; - Repaint(); - break; - case PurchaseResult.Status.Ok: - m_Purchasing = PurchaseStatus.Complete; - if (result.message != null) - m_Message = result.message; - Repaint(); - break; - } - if (msg != null) - EditorUtility.DisplayDialog("Purchase failed", msg + " This purchase has been cancelled.", - "Add this item to basket", "Cancel"); - }); - UsabilityAnalytics.Track(string.Format("/AssetStore/InstaBuy/{0}/{1}", m_Asset.packageID, m_Asset.id)); - } - - void BuildPackage() - { - AssetStoreAsset.PreviewInfo item = m_Asset.previewInfo; - if (item == null) - return; - - if (m_BuildAttempts++ > kMaxPolls) - { - EditorUtility.DisplayDialog("Building timed out", "Timed out during building of package", "Close"); - Close(); - return; - } - - item.downloadProgress = -1f; - m_Purchasing = PurchaseStatus.Building; - - AssetStoreClient.BuildPackage(m_Asset, delegate(BuildPackageResult result) { - if (this == null) return; // aborted - if (result.error != null) - { - Debug.Log(result.error); - if (EditorUtility.DisplayDialog("Error building package", - "The server was unable to build the package. Please re-import.", - "Ok")) - Close(); - return; - } - - if (m_Asset == null || m_Purchasing != PurchaseStatus.Building || result.packageID != m_Asset.packageID) - { - // Aborted - Close(); - } - - string url = result.asset.previewInfo.packageUrl; - if (url != null && url != "") - { - DownloadPackage(); - } - else - { - // Retry since package is not done building on server - m_Purchasing = PurchaseStatus.StartBuild; - } - Repaint(); - }); - } - - void DownloadPackage() - { - AssetStoreAsset.PreviewInfo item = m_Asset.previewInfo; - m_Purchasing = PurchaseStatus.Downloading; - item.downloadProgress = 0; - item.buildProgress = -1f; - - AssetStoreContext.Download(m_Asset.packageID.ToString(), item.packageUrl, item.encryptionKey, item.packageName, - item.publisherName, item.categoryName, delegate(string id, string status, int bytes, int total) { - if (this == null) return; // aborted - item.downloadProgress = -1f; - if (status != "ok") - { - Debug.LogErrorFormat("Error downloading package {0} ({1})", item.packageName, id); - Debug.LogError(status); - Close(); - return; - } - - if (m_Asset == null || m_Purchasing != PurchaseStatus.Downloading || id != m_Asset.packageID.ToString()) - { - // Aborted - Close(); - } - - if (!AssetStoreContext.OpenPackageInternal(id)) - { - Debug.LogErrorFormat("Error importing package {0} ({1})", item.packageName, id); - } - Close(); - }); - } - } -} // namespace diff --git a/Editor/Mono/AssetStore/AssetStoreLoginWIndow.cs b/Editor/Mono/AssetStore/AssetStoreLoginWIndow.cs deleted file mode 100644 index 4cd7b29f0f..0000000000 --- a/Editor/Mono/AssetStore/AssetStoreLoginWIndow.cs +++ /dev/null @@ -1,234 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.Collections; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor -{ - /** - * Login dialog for the asset store. - * This login session is shared with the asset store window ie. - * login/logout here will do the same in the asset store window - * and vice versa. - */ - internal class AssetStoreLoginWindow : EditorWindow - { - class Styles - { - public GUIStyle link = new GUIStyle(EditorStyles.miniLabel); - public Styles() - { - link.normal.textColor = new Color(.26f, .51f, .75f, 1f); - } - } - static Styles styles; - - // errorMessage is null on success - public delegate void LoginCallback(string errorMessage); - - /** Make a best effort login to the asset store by trying on order: - * 1, reuse previously saved session - * 2, show login window - */ - static public void Login(string loginReason, LoginCallback callback) - { - if (AssetStoreClient.HasActiveSessionID) - AssetStoreClient.Logout(); - - // Show login window if we cannot use saved session ID - if (!AssetStoreClient.RememberSession || !AssetStoreClient.HasSavedSessionID) - { - ShowAssetStoreLoginWindow(loginReason, callback); - return; - } - - AssetStoreClient.LoginWithRememberedSession(delegate(string errorMessage) { - if (string.IsNullOrEmpty(errorMessage)) - callback(errorMessage); - else - ShowAssetStoreLoginWindow(loginReason, callback); - }); - } - - /** Logout of the asset store - */ - static public void Logout() - { - AssetStoreClient.Logout(); - } - - // Logout of the asset store - static public bool IsLoggedIn - { - get { return AssetStoreClient.HasActiveSessionID; } - } - - /** Show the login window */ - static public void ShowAssetStoreLoginWindow(string loginReason, LoginCallback callback) - { - AssetStoreLoginWindow w = EditorWindow.GetWindowWithRect(new Rect(100, 100, 360, 140), true, "Login to Asset Store"); - w.position = new Rect(100, 100, w.position.width, w.position.height); - w.m_Parent.window.m_DontSaveToLayout = true; - w.m_Password = ""; - w.m_LoginCallback = callback; - w.m_LoginReason = loginReason; - w.m_LoginRemoteMessage = null; - UsabilityAnalytics.Track("/AssetStore/Login"); - } - - static GUIContent s_AssetStoreLogo; - - static void LoadLogos() - { - if (s_AssetStoreLogo != null) - return; - // s_AssetStoreLogo = EditorGUIUtility.IconContent ("WelcomeScreen.AssetStoreLogo"); - s_AssetStoreLogo = new GUIContent(""); // TODO: need to have logo created - } - - const float kBaseHeight = 110.0f; - string m_LoginReason; - string m_LoginRemoteMessage = null; - string m_Username = ""; - string m_Password = ""; - - LoginCallback m_LoginCallback; - - public void OnDisable() - { - if (m_LoginCallback != null) - m_LoginCallback(m_LoginRemoteMessage); - m_LoginCallback = null; - m_Password = null; - } - - public void OnGUI() - { - if (styles == null) - styles = new Styles(); - - LoadLogos(); - - if (AssetStoreClient.LoginInProgress() || AssetStoreClient.LoggedIn()) - GUI.enabled = false; - - GUILayout.BeginVertical(); - GUILayout.Space(10); - GUILayout.BeginHorizontal(); - GUILayout.Space(5); - GUILayout.Label(s_AssetStoreLogo, GUIStyle.none, GUILayout.ExpandWidth(false)); - GUILayout.BeginVertical(); - GUILayout.BeginHorizontal(); - GUILayout.Space(6); - GUILayout.Label(m_LoginReason, EditorStyles.wordWrappedLabel); - Rect lastReasonRect = GUILayoutUtility.GetLastRect(); - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); - GUILayout.Space(6); - Rect lastMessageRect = new Rect(0f, 0f, 0f, 0f); - if (m_LoginRemoteMessage != null) - { - Color oldColor = GUI.color; - GUI.color = Color.red; - GUILayout.Label(m_LoginRemoteMessage, EditorStyles.wordWrappedLabel); - GUI.color = oldColor; - lastMessageRect = GUILayoutUtility.GetLastRect(); - } - float newHeight = lastReasonRect.height + lastMessageRect.height + kBaseHeight; - if (Event.current.type == EventType.Repaint && newHeight != position.height) - { - // Debug.Log(newHeight.ToString() + " " + position.height + " " + lastReasonRect.height.ToString() + " " + lastMessageRect.height.ToString()); - position = new Rect(position.x, position.y, position.width, newHeight); - Repaint(); - } - GUILayout.EndHorizontal(); - - GUILayout.FlexibleSpace(); - GUILayout.BeginHorizontal(); - GUI.SetNextControlName("username"); - m_Username = EditorGUILayout.TextField("Username", m_Username); - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); - m_Password = EditorGUILayout.PasswordField("Password", m_Password, GUILayout.ExpandWidth(true)); - if (GUILayout.Button(EditorGUIUtility.TrTextContent("Forgot?", "Reset your password"), styles.link, GUILayout.ExpandWidth(false))) - { - Application.OpenURL("https://accounts.unity3d.com/password/new"); - } - - EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link); - GUILayout.EndHorizontal(); - - bool oldRememberMe = AssetStoreClient.RememberSession; - bool newRememberMe = EditorGUILayout.Toggle("Remember me", oldRememberMe); - if (newRememberMe != oldRememberMe) - AssetStoreClient.RememberSession = newRememberMe; - - GUILayout.EndVertical(); - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.Space(8); - - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Create account")) - { - AssetStore.Open("createuser/"); - m_LoginRemoteMessage = "Cancelled - create user"; - Close(); - } - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Cancel")) - { - m_LoginRemoteMessage = "Cancelled"; - Close(); - } - GUILayout.Space(5); - if (GUILayout.Button("Login")) - { - DoLogin(); - Repaint(); - } - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.Space(5); - - GUILayout.EndVertical(); - - if (Event.current.Equals(Event.KeyboardEvent("return"))) - { - DoLogin(); - Repaint(); - } - - if (m_Username == "") - EditorGUI.FocusTextInControl("username"); - } - - void DoLogin() - { - m_LoginRemoteMessage = null; - - if (AssetStoreClient.HasActiveSessionID) - AssetStoreClient.Logout(); - - AssetStoreClient.LoginWithCredentials(m_Username, m_Password, AssetStoreClient.RememberSession, - delegate(string errorMessage) { - m_LoginRemoteMessage = errorMessage; - if (errorMessage == null) - { - Close(); - } - else - { - Repaint(); - } - }); - } - } // class AssetStoreLoginWindow -} // namespace UnityEditor diff --git a/Editor/Mono/AssetStore/AssetStorePreviewManager.cs b/Editor/Mono/AssetStore/AssetStorePreviewManager.cs deleted file mode 100644 index a6d77e2cf5..0000000000 --- a/Editor/Mono/AssetStore/AssetStorePreviewManager.cs +++ /dev/null @@ -1,380 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - /** - * Fetching and caches preview images of asset store assets from the - * asset store server - */ - internal sealed class AssetStorePreviewManager - { - private AssetStorePreviewManager() {} // disallow instantiation - - static AssetStorePreviewManager s_SharedAssetStorePreviewManager = null; - static RenderTexture s_RenderTexture = null; - - static internal AssetStorePreviewManager Instance - { - get - { - if (s_SharedAssetStorePreviewManager == null) - { - s_SharedAssetStorePreviewManager = new AssetStorePreviewManager(); - s_SharedAssetStorePreviewManager.m_DummyItem.lastUsed = -1; - } - return s_SharedAssetStorePreviewManager; - } - } - - public class CachedAssetStoreImage - { - private const double kFadeTime = 0.5; - - public Texture2D image; - public double lastUsed; // time since app start - public double lastFetched; // time since app start - public int requestedWidth; // - public string label; // - internal AsyncHTTPClient client; // null if not in progress of fetching preview - public Color color - { - get - { - return Color.Lerp(new Color(1, 1, 1, 0), new Color(1, 1, 1, 1), - Mathf.Min(1f, (float)((EditorApplication.timeSinceStartup - lastFetched) / kFadeTime))); - } - } - } - - - // @TODO: MAKE handling of incoming images span several repaints in order to - // not have the jumpy behaviour. Just put the in a queue an handle them from there. - // - - - Dictionary m_CachedAssetStoreImages; - const double kQueryDelay = 0.2; - const int kMaxConcurrentDownloads = 15; - const int kMaxConvertionsPerTick = 1; - int m_MaxCachedAssetStoreImages = 10; - int m_Aborted = 0; - int m_Success = 0; - internal int Requested = 0; - internal int CacheHit = 0; - int m_CacheRemove = 0; - int m_ConvertedThisTick = 0; - CachedAssetStoreImage m_DummyItem = new CachedAssetStoreImage(); - - static bool s_NeedsRepaint = false; - - static Dictionary CachedAssetStoreImages - { - get - { - if (Instance.m_CachedAssetStoreImages == null) - { - Instance.m_CachedAssetStoreImages = new Dictionary(); - } - return Instance.m_CachedAssetStoreImages; - } - } - - public static int MaxCachedImages - { - get { return Instance.m_MaxCachedAssetStoreImages; } - set { Instance.m_MaxCachedAssetStoreImages = value; } - } - - public static bool CacheFull - { - get { return CachedAssetStoreImages.Count >= MaxCachedImages; } - } - - public static int Downloading - { - get - { - int c = 0; - foreach (KeyValuePair kv in CachedAssetStoreImages) - if (kv.Value.client != null) c++; - return c; - } - } - - public static string StatsString() - { - return string.Format("Reqs: {0}, Ok: {1}, Abort: {2}, CacheDel: {3}, Cache: {4}/{5}, CacheHit: {6}", - Instance.Requested, Instance.m_Success, Instance.m_Aborted, Instance.m_CacheRemove, - AssetStorePreviewManager.CachedAssetStoreImages.Count, - Instance.m_MaxCachedAssetStoreImages, - Instance.CacheHit); - } - - /** - * Return a texture from a url that points to an image resource - * - * This method does not block but queues a request to fetch the image and return null. - * When the image has been fetched this method will return the image texture downloaded. - */ - public static CachedAssetStoreImage TextureFromUrl(string url, string label, int textureSize, GUIStyle labelStyle, GUIStyle iconStyle, bool onlyCached) - { - if (string.IsNullOrEmpty(url)) - return Instance.m_DummyItem; - - CachedAssetStoreImage cached; - bool newentry = true; - - if (CachedAssetStoreImages.TryGetValue(url, out cached)) - { - cached.lastUsed = EditorApplication.timeSinceStartup; - - // Refetch the image if the size has changed and is not in the progress of being fetched - bool refetchInitiated = cached.requestedWidth == textureSize; - bool correctSize = cached.image != null && cached.image.width == textureSize; - - bool cacheRequestAborted = cached.requestedWidth == -1; - - if ((correctSize || refetchInitiated || onlyCached) && !cacheRequestAborted) - { - Instance.CacheHit++; - - // Use cached image (that may be null) if we're in progress of fetching the image - // or if we have rendered the images correctly - //return cached; - bool fetchingImage = cached.client != null; - bool labelDrawn = cached.label == null; - bool valid = fetchingImage || labelDrawn; - bool convPerTickExceeded = Instance.m_ConvertedThisTick > kMaxConvertionsPerTick; - s_NeedsRepaint = s_NeedsRepaint || convPerTickExceeded; - return (valid || convPerTickExceeded) ? - cached : - RenderEntry(cached, labelStyle, iconStyle); - } - //Debug.Log(string.Format("Found {0} {1} {2} {3}", correctSize, refetchInitiated, onlyCached, cacheRequestAborted)); - newentry = false; - if (Downloading >= kMaxConcurrentDownloads) return cached.image == null ? Instance.m_DummyItem : cached; - } - else - { - if (onlyCached || Downloading >= kMaxConcurrentDownloads) return Instance.m_DummyItem; - cached = new CachedAssetStoreImage(); - cached.image = null; - cached.lastUsed = EditorApplication.timeSinceStartup; - //Debug.Log("url is " + textureSize.ToString() + " " + url); - } - - // Only set fetch time when there is not image in order to use it for - // fading in the image when it becomes available - if (cached.image == null) - cached.lastFetched = EditorApplication.timeSinceStartup; - - cached.requestedWidth = textureSize; - cached.label = label; - - AsyncHTTPClient client = null; - client = SetupTextureDownload(cached, url, "previewSize-" + textureSize); - - ExpireCacheEntries(); - - if (newentry) - CachedAssetStoreImages.Add(url, cached); - - client.Begin(); - - Instance.Requested++; - return cached; - } - - private static AsyncHTTPClient SetupTextureDownload(CachedAssetStoreImage cached, string url, string tag) - { - AsyncHTTPClient client = new AsyncHTTPClient(url); - cached.client = client; - client.tag = tag; - client.doneCallback = delegate(AsyncHTTPClient c) { - // Debug.Log("Got image " + EditorApplication.timeSinceStartup.ToString()); - cached.client = null; - if (!client.IsSuccess()) - { - if (client.state != AsyncHTTPClient.State.ABORTED) - { - string err = "error " + client.text + " " + client.state.ToString() + " '" + url + "'"; - if (ObjectListArea.s_Debug) - Debug.LogError(err); - else - System.Console.Write(err); - } - else - { - Instance.m_Aborted++; - } - return; - } - - // In the case of refetch because of resize first destroy the current image - if (cached.image != null) - Object.DestroyImmediate(cached.image); - - cached.image = c.texture; - - s_NeedsRepaint = true; - Instance.m_Success++; - }; - return client; - } - - // Make room for image if needed (because of cache limits) - private static void ExpireCacheEntries() - { - while (CacheFull) - { - string oldestUrl = null; - CachedAssetStoreImage oldestEntry = null; - foreach (KeyValuePair kv in CachedAssetStoreImages) - { - if (oldestEntry == null || oldestEntry.lastUsed > kv.Value.lastUsed) - { - oldestEntry = kv.Value; - oldestUrl = kv.Key; - } - } - CachedAssetStoreImages.Remove(oldestUrl); - Instance.m_CacheRemove++; - if (oldestEntry == null) - { - Debug.LogError("Null entry found while removing cache entry"); - break; - } - if (oldestEntry.client != null) - { - oldestEntry.client.Abort(); - oldestEntry.client = null; - } - if (oldestEntry.image != null) - Object.DestroyImmediate(oldestEntry.image); - } - } - - /* - * When the new GUI system is is place this should render the label to the cached icon - * to speed up rendering. For now we just scale the incoming image and render the label - * separately - */ - private static CachedAssetStoreImage RenderEntry(CachedAssetStoreImage cached, GUIStyle labelStyle, GUIStyle iconStyle) - { - if (cached.label == null || cached.image == null) return cached; - Texture2D tmp = cached.image; - cached.image = new Texture2D(cached.requestedWidth, cached.requestedWidth, TextureFormat.RGB24, false, true); - ScaleImage(cached.requestedWidth, cached.requestedWidth, tmp, cached.image, iconStyle); - // Compressing creates artifacts on the images - // cached.image.Compress(true); - Object.DestroyImmediate(tmp); - cached.label = null; - Instance.m_ConvertedThisTick++; - return cached; - } - - /** Slow version of scaling an image but i doesn't - * matter since it is not performance critical - */ - internal static void ScaleImage(int w, int h, Texture2D inimage, Texture2D outimage, GUIStyle bgStyle) - { - SavedRenderTargetState saved = new SavedRenderTargetState(); - - if (s_RenderTexture != null && (s_RenderTexture.width != w || s_RenderTexture.height != h)) - { - Object.DestroyImmediate(s_RenderTexture); - s_RenderTexture = null; - } - - if (s_RenderTexture == null) - { - s_RenderTexture = RenderTexture.GetTemporary(w, h, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); - s_RenderTexture.hideFlags = HideFlags.HideAndDontSave; - } - - RenderTexture r = s_RenderTexture; - RenderTexture.active = r; - Rect rect = new Rect(0, 0, w, h); - - EditorGUIUtility.SetRenderTextureNoViewport(r); - GL.LoadOrtho(); - GL.LoadPixelMatrix(0, w, h, 0); - ShaderUtil.rawViewportRect = new Rect(0, 0, w, h); - ShaderUtil.rawScissorRect = new Rect(0 , 0, w, h); - GL.Clear(true, true, new Color(0, 0, 0, 0)); - - Rect blitRect = rect; - if (inimage.width > inimage.height) - { - float newHeight = (float)blitRect.height * ((float)inimage.height / (float)inimage.width); - blitRect.height = (int)newHeight; - blitRect.y += (int)(newHeight * 0.5f); - } - else if (inimage.width < inimage.height) - { - float newWidth = (float)blitRect.width * ((float)inimage.width / (float)inimage.height); - blitRect.width = (int)newWidth; - blitRect.x += (int)(newWidth * 0.5f); - } - if (bgStyle != null && bgStyle.normal != null && bgStyle.normal.background != null) - Graphics.DrawTexture(rect, bgStyle.normal.background); - - Graphics.DrawTexture(blitRect, inimage); - outimage.ReadPixels(rect, 0, 0, false); - outimage.Apply(); - outimage.hideFlags = HideFlags.HideAndDontSave; - saved.Restore(); - } - - /* - * Check if textures queued for download has finished downloading. - * This call will reset the flag for finished downloads. - */ - public static bool CheckRepaint() - { - bool needsRepaint = s_NeedsRepaint; - s_NeedsRepaint = false; - return needsRepaint; - } - - // Abort fetching all previews with the specified size - public static void AbortSize(int size) - { - AsyncHTTPClient.AbortByTag("previewSize-" + size.ToString()); - - // Mark any pending requests for that width in the cases as invalid - // now that requests has been aborted. - foreach (KeyValuePair kv in AssetStorePreviewManager.CachedAssetStoreImages) - { - if (kv.Value.requestedWidth != size) - continue; - kv.Value.requestedWidth = -1; - kv.Value.client = null; - } - } - - // Abort fetching all reviews that haven't been used since timestamp - public static void AbortOlderThan(double timestamp) - { - foreach (KeyValuePair kv in AssetStorePreviewManager.CachedAssetStoreImages) - { - CachedAssetStoreImage entry = kv.Value; - if (entry.lastUsed >= timestamp || entry.client == null) - continue; - entry.requestedWidth = -1; - entry.client.Abort(); - entry.client = null; - } - - // @TODO: Currently we know that AbortOlderThan is called exactly once each repaint. - // Therefore this counter can be reset here. Should probably be moved to a - // more intuitive location. - Instance.m_ConvertedThisTick = 0; - } - } -} // UnityEditor namespace diff --git a/Editor/Mono/AssetStore/AssetStoreWindow.cs b/Editor/Mono/AssetStore/AssetStoreWindow.cs deleted file mode 100644 index 46c4c8b118..0000000000 --- a/Editor/Mono/AssetStore/AssetStoreWindow.cs +++ /dev/null @@ -1,363 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using System.Text; -using System.Threading; -using UnityEditor.Web; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Asset Store", icon = "Asset Store")] - internal class AssetStoreWindow : EditorWindow , IHasCustomMenu - { - public bool initialized { get { return (null != webView); } } - - public static void OpenURL(string url) - { - AssetStoreWindow window = Init(); - bool shouldDefer = !window.initialized; - - window.InvokeJSMethod("document.AssetStore", "openURL", url); - AssetStoreContext.GetInstance().initialOpenURL = url; - if (shouldDefer) - // Ugly hack - help, asset store team! - window.ScheduleOpenURL(TimeSpan.FromSeconds(3)); - } - - // Use this for initialization - public static AssetStoreWindow Init() - { - AssetStoreWindow window = EditorWindow.GetWindow(typeof(SceneView)); - window.SetMinMaxSizes(); - window.Show(); - return window; - } - - private void SetMinMaxSizes() - { - this.minSize = new Vector2(400, 100); - this.maxSize = new Vector2(2048, 2048); - } - - public virtual void AddItemsToMenu(GenericMenu menu) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Reload"), false, Reload); - } - - // Forces user logout - public void Logout() - { - InvokeJSMethod("document.AssetStore.login", "logout"); - } - - // Reloads the web view - public void Reload() - { - m_CurrentSkin = EditorGUIUtility.skinIndex; - m_IsDocked = docked; - webView.Reload(); - } - - public void OnLoadError(string url) - { - if (!webView) - return; - - if (m_IsOffline) - { - Debug.LogErrorFormat("Unexpected error: Failed to load offline Asset Store page (url={0})", url); - return; - } - - m_IsOffline = true; - webView.LoadFile(AssetStoreUtils.GetOfflinePath()); - } - - /// - /// This is called by WebView right after the script execution environment - /// of a page has been initialized but before any of its code is actually - /// executed. This allows us to inject our own "windows.context" object for - /// the A$ scripts. - /// - public void OnInitScripting() - { - SetScriptObject(); - } - - /// - /// This is called by WebView when a link is to be opened in a new window. - /// Opens the link in the system browser. - /// - /// URL of the link. - public void OnOpenExternalLink(string url) - { - if (url.StartsWith("http://") || - url.StartsWith("https://")) - Application.OpenURL(url); - } - - public void OnEnable() - { - SetMinMaxSizes(); - titleContent = GetLocalizedTitleContent(); - AssetStoreUtils.RegisterDownloadDelegate(this); - } - - public void OnDisable() - { - AssetStoreUtils.UnRegisterDownloadDelegate(this); - } - - public void OnDownloadProgress(string id, string message, ulong bytes, ulong total) - { - InvokeJSMethod("document.AssetStore.pkgs", "OnDownloadProgress", id, message, bytes, total); - } - - public void OnGUI() - { - var webViewRect = GUIClip.Unclip(new Rect(0, 0, position.width, position.height)); - - // If we haven't initialize our embedded webview yet, - // do so now. - if (!webView) - InitWebView(webViewRect); - - // TODO workaround for Mac - if (m_RepeatedShow-- > 0) - { - Refresh(); - } - - // If there's been a layout change, update our - if (Event.current.type == EventType.Repaint) - { - webView.SetHostView(m_Parent); - webView.SetSizeAndPosition((int)webViewRect.x, (int)webViewRect.y, (int)webViewRect.width, (int)webViewRect.height); - - // Sync skin. - if (m_CurrentSkin != EditorGUIUtility.skinIndex) - { - m_CurrentSkin = EditorGUIUtility.skinIndex; - InvokeJSMethod("document.AssetStore", "refreshSkinIndex"); - } - - UpdateDockStatusIfNeeded(); - } - } - - void Update() - { - if (!m_ShouldRetryInitialURL) - return; - - m_ShouldRetryInitialURL = false; - string url = AssetStoreContext.GetInstance().initialOpenURL; - if (!string.IsNullOrEmpty(url)) - OpenURL(url); - } - - public void UpdateDockStatusIfNeeded() - { - if (m_IsDocked != docked) - { - m_IsDocked = docked; - - if (scriptObject != null) - { - AssetStoreContext.GetInstance().docked = docked; - InvokeJSMethod("document.AssetStore", "updateDockStatus"); - } - } - } - - public void ToggleMaximize() - { - maximized = !maximized; - Refresh(); - SetFocus(true); - } - - public void Refresh() - { - webView.Hide(); - webView.Show(); - } - - public void OnFocus() - { - SetFocus(true); - } - - public void OnLostFocus() - { - SetFocus(false); - } - - public void OnBecameInvisible() - { - if (!webView) - return; - - // Either our tab put into the background or we've been removed from our - // dock and are about to be moved to some other dock. Whatever the case, - // unparent our WebView native window from the current dock's native window. - // This will implicitly hide the window. - webView.SetHostView(null); - } - - public void OnDestroy() - { - DestroyImmediate(webView); - } - - private void InitWebView(Rect webViewRect) - { - m_CurrentSkin = EditorGUIUtility.skinIndex; - m_IsDocked = docked; - m_IsOffline = false; - - if (!webView) - { - var x = (int)webViewRect.x; - var y = (int)webViewRect.y; - int width = (int)webViewRect.width; - int height = (int)webViewRect.height; - - // Create WebView. - webView = ScriptableObject.CreateInstance(); - webView.InitWebView(m_Parent, x, y, width, height, false); - webView.hideFlags = HideFlags.HideAndDontSave; - webView.AllowRightClickMenu(true); - - // Sync focus. - if (hasFocus) - SetFocus(true); - } - - // Direct WebView event callbacks to us. - webView.SetDelegateObject(this); - - // Load the A$ startup file. - webView.LoadFile(AssetStoreUtils.GetLoaderPath()); - } - - private void CreateScriptObject() - { - if (scriptObject != null) - return; - - scriptObject = ScriptableObject.CreateInstance(); - scriptObject.hideFlags = HideFlags.HideAndDontSave; - scriptObject.webView = webView; - } - - private void SetScriptObject() - { - if (!webView) - return; - - CreateScriptObject(); - - //We need to leave unityScriptObject name instead of webScriptObject because it's - //been deployed on the asset store servers. - webView.DefineScriptObject("window.unityScriptObject", scriptObject); - } - - private void InvokeJSMethod(string objectName, string name, params object[] args) - { - if (!webView) - return; - - var scriptCodeBuffer = new StringBuilder(); - scriptCodeBuffer.Append(objectName); - scriptCodeBuffer.Append('.'); - scriptCodeBuffer.Append(name); - scriptCodeBuffer.Append('('); - - var isFirst = true; - foreach (var arg in args) - { - if (!isFirst) - scriptCodeBuffer.Append(','); - - // Quote strings. This is pretty simple-minded as we don't escape - // things within the string. - var isString = arg is string; - if (isString) - scriptCodeBuffer.Append('"'); - - scriptCodeBuffer.Append(arg); - - if (isString) - scriptCodeBuffer.Append('"'); - - isFirst = false; - } - - scriptCodeBuffer.Append(");"); - - webView.ExecuteJavascript(scriptCodeBuffer.ToString()); - } - - private void SetFocus(bool value) - { - // Giving the focus to the browser's native window will cause our GuiView's - // native window to lose focus. If we blindly pass on our focus state to - // the browser, we will end up making it lose focus while we try to make it - // have focus. However, we generally *do* want to pass on focus. - // - // So, what we do is to simply prevent recursion here. Allows us to just - // hand the focus over. - - if (m_SyncingFocus) - return; - - m_SyncingFocus = true; - - if (webView) - { - // If we're being focused, sync up our current native parent window and force - // the browser window to be visible. We're doing this here rather than in - // OnBecameVisible since this way it will also work when maximizing our - // EditorWindow(which goes through some really whacky logic). We'll be - // setting this state more often than otherwise, but that doesn't really - // hurt. - if (value) - { - webView.SetHostView(m_Parent); - webView.Show(); - if (RuntimePlatform.OSXEditor == Application.platform) - // TODO investigate why a Show() so close to a reparenting causes issues on Mac - m_RepeatedShow = 5; - } - - webView.SetFocus(value); - } - - m_SyncingFocus = false; - } - - void ScheduleOpenURL(TimeSpan timeout) - { - ThreadPool.QueueUserWorkItem(delegate { - Thread.Sleep(timeout); - m_ShouldRetryInitialURL = true; - }); - } - - internal WebView webView; - internal WebScriptObject scriptObject; - - private int m_CurrentSkin; - private bool m_IsDocked; - private bool m_IsOffline; - private bool m_SyncingFocus; - private int m_RepeatedShow; - private bool m_ShouldRetryInitialURL; - } -} diff --git a/Editor/Mono/AssetStore/Json.cs b/Editor/Mono/AssetStore/Json.cs deleted file mode 100644 index 9f3431c893..0000000000 --- a/Editor/Mono/AssetStore/Json.cs +++ /dev/null @@ -1,676 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -/* - * Simple recursive descending JSON parser and - * JSON string builder. - * - * Jonas Drewsen - (C) Unity3d.com - 2010 - * - * JSONParser parser = new JSONParser(" { \"hello\" : 42.3 } "); - * JSONValue value = parser.Parse(); - * - * bool is_it_float = value.isFloat(); - * float the_float = value.asFloat(); - * - */ - -using System.Collections.Generic; -using System; -using UnityEngine; - -namespace UnityEditorInternal -{ - /* - * JSON value structure - * - * Example: - * JSONValue v = JSONValue.NewDict(); - * v["hello"] = JSONValue.NewString("world"); - * asset(v["hello"].AsString() == "world"); - * - */ - internal struct JSONValue - { - public JSONValue(object o) - { - data = o; - } - - public bool IsString() { return data is string; } - public bool IsFloat() { return data is float; } - public bool IsList() { return data is List; } - public bool IsDict() { return data is Dictionary; } - public bool IsBool() { return data is bool; } - public bool IsNull() { return data == null; } - - public static implicit operator JSONValue(string s) - { - return new JSONValue(s); - } - - public static implicit operator JSONValue(float s) - { - return new JSONValue(s); - } - - public static implicit operator JSONValue(bool s) - { - return new JSONValue(s); - } - - public static implicit operator JSONValue(int s) - { - return new JSONValue((float)s); - } - - public object AsObject() - { - return data; - } - - public string AsString(bool nothrow) - { - if (data is string) - return (string)data; - if (!nothrow) - throw new JSONTypeException("Tried to read non-string json value as string"); - return ""; - } - - public string AsString() - { - return AsString(false); - } - - public float AsFloat(bool nothrow) - { - if (data is float) - return (float)data; - if (!nothrow) - throw new JSONTypeException("Tried to read non-float json value as float"); - return 0.0f; - } - - public float AsFloat() - { - return AsFloat(false); - } - - public bool AsBool(bool nothrow) - { - if (data is bool) - return (bool)data; - if (!nothrow) - throw new JSONTypeException("Tried to read non-bool json value as bool"); - return false; - } - - public bool AsBool() - { - return AsBool(false); - } - - public List AsList(bool nothrow) - { - if (data is List) - return (List)data; - if (!nothrow) - throw new JSONTypeException("Tried to read " + data.GetType().Name + " json value as list"); - return null; - } - - public List AsList() - { - return AsList(false); - } - - public Dictionary AsDict(bool nothrow) - { - if (data is Dictionary) - return (Dictionary)data; - if (!nothrow) - throw new JSONTypeException("Tried to read non-dictionary json value as dictionary"); - return null; - } - - public Dictionary AsDict() - { - return AsDict(false); - } - - public static JSONValue NewString(string val) - { - return new JSONValue(val); - } - - public static JSONValue NewFloat(float val) - { - return new JSONValue(val); - } - - public static JSONValue NewDict() - { - return new JSONValue(new Dictionary()); - } - - public static JSONValue NewList() - { - return new JSONValue(new List()); - } - - public static JSONValue NewBool(bool val) - { - return new JSONValue(val); - } - - public static JSONValue NewNull() - { - return new JSONValue(null); - } - - public JSONValue this[string index] - { - get - { - Dictionary dict = AsDict(); - return dict[index]; - } - set - { - if (data == null) - data = new Dictionary(); - Dictionary dict = AsDict(); - dict[index] = value; - } - } - - public bool ContainsKey(string index) - { - if (!IsDict()) - return false; - return AsDict().ContainsKey(index); - } - - // Get the specified field in a dict or null json value if - // no such field exists. The key can point to a nested structure - // e.g. key1.key2 in { key1 : { key2 : 32 } } - public JSONValue Get(string key) - { - if (!IsDict()) - return new JSONValue(null); - JSONValue value = this; - foreach (string part in key.Split('.')) - { - if (!value.ContainsKey(part)) - return new JSONValue(null); - value = value[part]; - } - return value; - } - - // Convenience dict value setting - public void Set(string key, string value) - { - if (value == null) - { - this[key] = NewNull(); - return; - } - this[key] = NewString(value); - } - - // Convenience dict value setting - public void Set(string key, float value) - { - this[key] = NewFloat(value); - } - - // Convenience dict value setting - public void Set(string key, bool value) - { - this[key] = NewBool(value); - } - - // Convenience list value add - public void Add(string value) - { - List list = AsList(); - if (value == null) - { - list.Add(NewNull()); - return; - } - list.Add(NewString(value)); - } - - // Convenience list value add - public void Add(float value) - { - List list = AsList(); - list.Add(NewFloat(value)); - } - - // Convenience list value add - public void Add(bool value) - { - List list = AsList(); - list.Add(NewBool(value)); - } - - /* - * Serialize a JSON value to string. - * This will recurse down through dicts and list type JSONValues. - */ - public override string ToString() - { - if (IsString()) - { - return "\"" + EncodeString(AsString()) + "\""; - } - else if (IsFloat()) - { - return AsFloat().ToString(); - } - else if (IsList()) - { - string res = "["; - string delim = ""; - foreach (JSONValue i in AsList()) - { - res += delim + i.ToString(); - delim = ", "; - } - return res + "]"; - } - else if (IsDict()) - { - string res = "{"; - string delim = ""; - foreach (KeyValuePair kv in AsDict()) - { - res += delim + '"' + EncodeString(kv.Key) + "\" : " + kv.Value.ToString(); - delim = ", "; - } - return res + "}"; - } - else if (IsBool()) - { - return AsBool() ? "true" : "false"; - } - else if (IsNull()) - { - return "null"; - } - else - { - throw new JSONTypeException("Cannot serialize json value of unknown type"); - } - } - - // Encode a string into a json string - private static string EncodeString(string str) - { - str = str.Replace("\"", "\\\""); - str = str.Replace("\\", "\\\\"); - str = str.Replace("\b", "\\b"); - str = str.Replace("\f", "\\f"); - str = str.Replace("\n", "\\n"); - str = str.Replace("\r", "\\r"); - str = str.Replace("\t", "\\t"); - // We do not use \uXXXX specifier but direct unicode in the string. - return str; - } - - object data; - } - - class JSONParseException : Exception - { - public JSONParseException(string msg) : base(msg) - { - } - } - - class JSONTypeException : Exception - { - public JSONTypeException(string msg) : base(msg) - { - } - } - - /* - * Top down recursive JSON parser - * - * Example: - * string json = "{ \"hello\" : \"world\", \"age\" : 100000, "sister" : null }"; - * JSONValue val = JSONParser.SimpleParse(json); - * asset( val["hello"].AsString() == "world" ); - * - */ - class JSONParser - { - private string json; - private int line; - private int linechar; - private int len; - private int idx; - private int pctParsed; - private char cur; - - public static JSONValue SimpleParse(string jsondata) - { - var parser = new JSONParser(jsondata); - try - { - return parser.Parse(); - } - catch (JSONParseException ex) - { - Debug.LogError(ex.Message); - } - return new JSONValue(null); - } - - /* - * Setup a parse to be ready for parsing the given string - */ - public JSONParser(string jsondata) - { - // TODO: fix that parser needs trailing spaces; - json = jsondata + " "; - line = 1; - linechar = 1; - len = json.Length; - idx = 0; - pctParsed = 0; - } - - /* - * Parse the entire json data string into a JSONValue structure hierarchy - */ - public JSONValue Parse() - { - cur = json[idx]; - return ParseValue(); - } - - private char Next() - { - if (cur == '\n') - { - line++; - linechar = 0; - } - idx++; - if (idx >= len) - throw new JSONParseException("End of json while parsing at " + PosMsg()); - - linechar++; - - int newPct = (int)((float)idx * 100f / (float)len); - if (newPct != pctParsed) - { - pctParsed = newPct; - } - cur = json[idx]; - return cur; - } - - private void SkipWs() - { - string ws = " \n\t\r"; - while (ws.IndexOf(cur) != -1) Next(); - } - - private string PosMsg() - { - return "line " + line.ToString() + ", column " + linechar.ToString(); - } - - private JSONValue ParseValue() - { - // Skip spaces - SkipWs(); - - switch (cur) - { - case '[': - return ParseArray(); - case '{': - return ParseDict(); - case '"': - return ParseString(); - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return ParseNumber(); - case 't': - case 'f': - case 'n': - return ParseConstant(); - default: - throw new JSONParseException("Cannot parse json value starting with '" + json.Substring(idx, 5) + "' at " + PosMsg()); - } - } - - private JSONValue ParseArray() - { - Next(); - SkipWs(); - List arr = new List(); - while (cur != ']') - { - arr.Add(ParseValue()); - SkipWs(); - if (cur == ',') - { - Next(); - SkipWs(); - } - } - Next(); - return new JSONValue(arr); - } - - private JSONValue ParseDict() - { - Next(); - SkipWs(); - Dictionary dict = new Dictionary(); - while (cur != '}') - { - JSONValue key = ParseValue(); - if (!key.IsString()) - throw new JSONParseException("Key not string type at " + PosMsg()); - SkipWs(); - if (cur != ':') - throw new JSONParseException("Missing dict entry delimiter ':' at " + PosMsg()); - Next(); - dict.Add(key.AsString(), ParseValue()); - SkipWs(); - if (cur == ',') - { - Next(); - SkipWs(); - } - } - Next(); - return new JSONValue(dict); - } - - static char[] endcodes = new char[] { '\\', '"' }; - - private JSONValue ParseString() - { - string res = ""; - - Next(); - - while (idx < len) - { - int endidx = json.IndexOfAny(endcodes, idx); - if (endidx < 0) - throw new JSONParseException("missing '\"' to end string at " + PosMsg()); - - res += json.Substring(idx, endidx - idx); - - if (json[endidx] == '"') - { - cur = json[endidx]; - idx = endidx; - break; - } - - endidx++; // get escape code - if (endidx >= len) - throw new JSONParseException("End of json while parsing while parsing string at " + PosMsg()); - - // char at endidx is \ - char ncur = json[endidx]; - switch (ncur) - { - case '"': - goto case '/'; - case '\\': - goto case '/'; - case '/': - res += ncur; - break; - case 'b': - res += '\b'; - break; - case 'f': - res += '\f'; - break; - case 'n': - res += '\n'; - break; - case 'r': - res += '\r'; - break; - case 't': - res += '\t'; - break; - case 'u': - // Unicode char specified by 4 hex digits - string digit = ""; - if (endidx + 4 >= len) - throw new JSONParseException("End of json while parsing while parsing unicode char near " + PosMsg()); - digit += json[endidx + 1]; - digit += json[endidx + 2]; - digit += json[endidx + 3]; - digit += json[endidx + 4]; - try - { - int d = System.Int32.Parse(digit, System.Globalization.NumberStyles.AllowHexSpecifier); - res += (char)d; - } - catch (FormatException) - { - throw new JSONParseException("Invalid unicode escape char near " + PosMsg()); - } - endidx += 4; - break; - default: - throw new JSONParseException("Invalid escape char '" + ncur + "' near " + PosMsg()); - } - idx = endidx + 1; - } - if (idx >= len) - throw new JSONParseException("End of json while parsing while parsing string near " + PosMsg()); - - cur = json[idx]; - - Next(); - return new JSONValue(res); - } - - private JSONValue ParseNumber() - { - string resstr = ""; - - if (cur == '-') - { - resstr = "-"; - Next(); - } - - while (cur >= '0' && cur <= '9') - { - resstr += cur; - Next(); - } - if (cur == '.') - { - Next(); - resstr += '.'; - while (cur >= '0' && cur <= '9') - { - resstr += cur; - Next(); - } - } - - if (cur == 'e' || cur == 'E') - { - resstr += "e"; - Next(); - if (cur != '-' && cur != '+') - { - // throw new JSONParseException("Missing - or + in 'e' potent specifier at " + PosMsg()); - resstr += cur; - Next(); - } - while (cur >= '0' && cur <= '9') - { - resstr += cur; - Next(); - } - } - - try - { - float f = System.Convert.ToSingle(resstr); - return new JSONValue(f); - } - catch (Exception) - { - throw new JSONParseException("Cannot convert string to float : '" + resstr + "' at " + PosMsg()); - } - } - - private JSONValue ParseConstant() - { - string c = ""; - c = "" + cur + Next() + Next() + Next(); - Next(); - if (c == "true") - { - return new JSONValue(true); - } - else if (c == "fals") - { - if (cur == 'e') - { - Next(); - return new JSONValue(false); - } - } - else if (c == "null") - { - return new JSONValue(null); - } - throw new JSONParseException("Invalid token at " + PosMsg()); - } - } -} diff --git a/Editor/Mono/AssetStoreToolUtils.cs b/Editor/Mono/AssetStoreToolUtils.cs deleted file mode 100644 index 2658f3af44..0000000000 --- a/Editor/Mono/AssetStoreToolUtils.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; - -namespace UnityEditorInternal -{ - /** - * Utilities for the Asset Store upload tool - */ - public partial class AssetStoreToolUtils - { - public static bool PreviewAssetStoreAssetBundleInInspector(AssetBundle bundle, AssetStoreAsset info) - { - info.id = 0; // make sure the id is zero when previewing - info.previewAsset = bundle.mainAsset; - AssetStoreAssetSelection.Clear(); - AssetStoreAssetSelection.AddAssetInternal(info); - - // Make the inspector show the asset - Selection.activeObject = AssetStoreAssetInspector.Instance; - AssetStoreAssetInspector.Instance.Repaint(); - return true; - } - - public static void UpdatePreloadingInternal() - { - AssetStoreUtils.UpdatePreloading(); - } - } -} // UnityEditor namespace diff --git a/Editor/Mono/AsyncHTTPClient.bindings.cs b/Editor/Mono/AsyncHTTPClient.bindings.cs deleted file mode 100644 index 896fb806a7..0000000000 --- a/Editor/Mono/AsyncHTTPClient.bindings.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeHeader("Editor/Mono/AsyncHTTPClient.bindings.h")] - internal partial class AsyncHTTPClient - { - private delegate void RequestProgressCallback(AsyncHTTPClient.State status, int downloaded, int totalSize); - private delegate void RequestDoneCallback(AsyncHTTPClient.State status, int httpStatus); - - private static extern IntPtr SubmitClientRequest(string tag, string url, string[] headers, string method, string data, RequestDoneCallback doneDelegate, RequestProgressCallback progressDelegate = null); - - private static extern byte[] GetBytesByHandle(IntPtr handle); - - private static extern Texture2D GetTextureByHandle(IntPtr handle); - - public static extern void AbortByTag(string tag); - - private static extern void AbortByHandle(IntPtr handle); - - [FreeFunction] - public static extern void CurlRequestCheck(); - } -} diff --git a/Editor/Mono/AsyncHTTPClient.cs b/Editor/Mono/AsyncHTTPClient.cs deleted file mode 100644 index 573ac6cccd..0000000000 --- a/Editor/Mono/AsyncHTTPClient.cs +++ /dev/null @@ -1,231 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Net; -using System.IO; -using System.Text; -using System.Threading; -using System.Collections.Generic; -using UnityEngine; -using System.Linq; - -namespace UnityEditor -{ - /* - * A HTTP job for performing HTTP requests in a thread - * This class is primarily used by the Server class. - */ - internal partial class AsyncHTTPClient - { - internal enum State - { - INIT, - CONNECTING, - CONNECTED, - UPLOADING, - DOWNLOADING, - CONFIRMING, - DONE_OK, - DONE_FAILED, - ABORTED, - TIMEOUT - } - private IntPtr m_Handle; - public delegate void DoneCallback(AsyncHTTPClient client); - public delegate void StatusCallback(State status, int bytesDone, int bytesTotal); - - public StatusCallback statusCallback; - public DoneCallback doneCallback; - - string m_ToUrl; - string m_FromData; - string m_Method; - - public string url - { - get { return m_ToUrl; } - } - - public string text - { - get - { - System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); - byte[] b = bytes; - if (b == null) return null; - return encoding.GetString(b); - } - } - - public byte[] bytes - { - get - { - return GetBytesByHandle(m_Handle); - } - } - public Texture2D texture - { - get - { - return GetTextureByHandle(m_Handle); - } - } - public State state { get; private set; } - public int responseCode { get; private set; } - public string tag { get; set; } - - public Dictionary header; - - /* GET request - * - */ - public AsyncHTTPClient(string _toUrl) - { - m_ToUrl = _toUrl; - m_FromData = null; - m_Method = ""; - state = State.INIT; - header = new Dictionary(StringComparer.OrdinalIgnoreCase); - m_Handle = (IntPtr)0; - tag = ""; - statusCallback = null; - } - - /* Any method request - * - */ - public AsyncHTTPClient(string _toUrl, string _method) - { - m_ToUrl = _toUrl; - m_FromData = null; - m_Method = _method; - state = State.INIT; - header = new Dictionary(StringComparer.OrdinalIgnoreCase); - m_Handle = (IntPtr)0; - tag = ""; - statusCallback = null; - } - - /* If this job has been set as a POST job this will overwrite the - * data to be posted. The job must not have been started yet - * ie. Begin() should not have been called. - */ - public string postData - { - set - { - m_FromData = value; - if (m_Method == "") - m_Method = "POST"; - if (!header.ContainsKey("Content-Type")) - header["Content-Type"] = "application/x-www-form-urlencoded"; - } - } - - /* - * POST request for uploading url application/x-www-form-urlencoded dictionary. - * The encoding normally allows for duplicate keys, but this method is restricted - * to unique keys. - */ - public Dictionary postDictionary - { - set - { - postData = string.Join("&", value.Select(kv => EscapeLong(kv.Key) + "=" + EscapeLong(kv.Value)).ToArray()); - } - } - - /* - * - */ - public void Abort() - { - state = State.ABORTED; - - AbortByHandle(m_Handle); - } - - public bool IsAborted() - { - return state == State.ABORTED; - } - - public bool IsDone() - { - return IsDone(state); - } - - public static bool IsDone(State state) - { - switch (state) - { - case State.DONE_OK: - case State.DONE_FAILED: - case State.ABORTED: - case State.TIMEOUT: - return true; - default: return false; - } - } - - public bool IsSuccess() - { - return state == State.DONE_OK; - } - - public static bool IsSuccess(State state) - { - return state == State.DONE_OK; - } - - public void Begin() - { - if (IsAborted()) - { - state = State.ABORTED; - return; - } - if (m_Method == "") - m_Method = "GET"; - - string[] headerFlattened = header.Select(kv => string.Format("{0}: {1}", kv.Key, kv.Value)).ToArray(); - - m_Handle = SubmitClientRequest(tag, m_ToUrl, headerFlattened, m_Method, m_FromData, Done, Progress); - } - - private void Done(State status, int i_ResponseCode) - { - state = status; - responseCode = i_ResponseCode; - - if (doneCallback != null) - doneCallback(this); - - m_Handle = (IntPtr)0; // The CurlRequestMessage will be deallocated after this callback returns - } - - private void Progress(State status, int bytesDone, int bytesTotal) - { - state = status; - if (statusCallback != null) - statusCallback(status, bytesDone, bytesTotal); - } - - /* - * The normal escape function does not support strings longer than 32766 characters - */ - private string EscapeLong(string v) - { - StringBuilder q = new StringBuilder(); - const int c_ChunkLength = 32766; - for (int i = 0; i < v.Length; i += c_ChunkLength) - { - q.Append(System.Uri.EscapeDataString(v.Substring(i, v.Length - i > c_ChunkLength ? c_ChunkLength : v.Length - i))); - } - return q.ToString(); - } - } -} diff --git a/Editor/Mono/AsyncProgressBar.bindings.cs b/Editor/Mono/AsyncProgressBar.bindings.cs deleted file mode 100644 index d1715ba480..0000000000 --- a/Editor/Mono/AsyncProgressBar.bindings.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace UnityEditor -{ - // Progress bar located in the status bar. A non blocking way of showing progress of tasks, e.g. lightmapping. - // Currently can properly show progress only for one task at a time. - [StaticAccessor("GetAsyncProgressBar()", StaticAccessorType.Dot)] - [NativeHeader("Editor/Src/AsyncProgressBar.h")] - internal partial class AsyncProgressBar - { - public static extern float progress { get; } - public static extern string progressInfo { get; } - public static extern bool isShowing {[NativeName("IsShowing")] get; } - - public static extern void Display(string progressInfo, float progress); - public static extern void Clear(); - } -} diff --git a/Editor/Mono/AttributeHelper.cs b/Editor/Mono/AttributeHelper.cs deleted file mode 100644 index aad307e82e..0000000000 --- a/Editor/Mono/AttributeHelper.cs +++ /dev/null @@ -1,303 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.Scripting; -using System; -using System.Collections; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace UnityEditor -{ - [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] - internal sealed partial class RequiredSignatureAttribute : Attribute {} - - internal class AttributeHelper - { - [StructLayout(LayoutKind.Sequential)] - struct MonoGizmoMethod - { - public MethodInfo drawGizmo; - public Type drawnType; - public int options; - } - - [RequiredByNativeCode] - static MonoGizmoMethod[] ExtractGizmos(Assembly assembly) - { - var commands = new List(); - - foreach (var mi in EditorAssemblies.GetAllMethodsWithAttribute(BindingFlags.Static).Where(m => m.DeclaringType.Assembly == assembly)) - { - var attrs = mi.GetCustomAttributes(typeof(DrawGizmo), false).Cast(); - foreach (var gizmoAttr in attrs) - { - var parameters = mi.GetParameters(); - if (parameters.Length != 2) - { - Debug.LogWarningFormat( - "Method {0}.{1} is marked with the DrawGizmo attribute but does not take parameters (ComponentType, GizmoType) so will be ignored.", - mi.DeclaringType.FullName, mi.Name - ); - continue; - } - if (mi.DeclaringType != null && mi.DeclaringType.IsGenericTypeDefinition) - { - Debug.LogWarningFormat( - "Method {0}.{1} is marked with the DrawGizmo attribute but is defined on a generic type definition, so will be ignored.", - mi.DeclaringType.FullName, mi.Name - ); - continue; - } - - var item = new MonoGizmoMethod(); - - if (gizmoAttr.drawnType == null) - item.drawnType = parameters[0].ParameterType; - else if (parameters[0].ParameterType.IsAssignableFrom(gizmoAttr.drawnType)) - item.drawnType = gizmoAttr.drawnType; - else - { - Debug.LogWarningFormat( - "Method {0}.{1} is marked with the DrawGizmo attribute but the component type it applies to could not be determined.", - mi.DeclaringType.FullName, mi.Name - ); - continue; - } - - if (parameters[1].ParameterType != typeof(GizmoType) && - parameters[1].ParameterType != typeof(int)) - { - Debug.LogWarningFormat( - "Method {0}.{1} is marked with the DrawGizmo attribute but does not take a second parameter of type GizmoType so will be ignored.", - mi.DeclaringType.FullName, mi.Name - ); - continue; - } - - item.drawGizmo = mi; - item.options = (int)gizmoAttr.drawOptions; - - commands.Add(item); - } - } - return commands.ToArray(); - } - - [RequiredByNativeCode] - static string GetComponentMenuName(Type type) - { - var attrs = type.GetCustomAttributes(typeof(AddComponentMenu), false); - if (attrs.Length > 0) - { - var menu = (AddComponentMenu)attrs[0]; - return menu.componentMenu; - } - return null; - } - - [RequiredByNativeCode] - static int GetComponentMenuOrdering(Type type) - { - var attrs = type.GetCustomAttributes(typeof(AddComponentMenu), false); - if (attrs.Length > 0) - { - var menu = (AddComponentMenu)attrs[0]; - return menu.componentOrder; - } - return 0; - } - - [StructLayout(LayoutKind.Sequential)] - struct MonoCreateAssetItem - { - public string menuItem; - public string fileName; - public int order; - public Type type; - } - - [RequiredByNativeCode] - static MonoCreateAssetItem[] ExtractCreateAssetMenuItems(Assembly assembly) - { - var result = new List(); - - foreach (var type in EditorAssemblies.GetAllTypesWithAttribute()) - { - var attr = type.GetCustomAttributes(typeof(CreateAssetMenuAttribute), false).FirstOrDefault() as CreateAssetMenuAttribute; - if (attr == null) - continue; - - if (!type.IsSubclassOf(typeof(ScriptableObject))) - { - Debug.LogWarningFormat("CreateAssetMenu attribute on {0} will be ignored as {0} is not derived from ScriptableObject.", type.FullName); - continue; - } - - string menuItemName = (string.IsNullOrEmpty(attr.menuName)) ? ObjectNames.NicifyVariableName(type.Name) : attr.menuName; - string fileName = (string.IsNullOrEmpty(attr.fileName)) ? ("New " + ObjectNames.NicifyVariableName(type.Name) + ".asset") : attr.fileName; - if (!System.IO.Path.HasExtension(fileName)) - fileName = fileName + ".asset"; - - var item = new MonoCreateAssetItem - { - menuItem = menuItemName, - fileName = fileName, - order = attr.order, - type = type - }; - result.Add(item); - } - - return result.ToArray(); - } - - static internal object InvokeMemberIfAvailable(object target, string methodName, object[] args) - { - MethodInfo method = target.GetType().GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - if (method != null) - { - return method.Invoke(target, args); - } - else - { - return null; - } - } - - internal static bool GameObjectContainsAttribute(GameObject go) where T : Attribute - { - var behaviours = go.GetComponents(typeof(Component)); - for (var index = 0; index < behaviours.Length; index++) - { - var behaviour = behaviours[index]; - if (behaviour == null) - continue; - - var behaviourType = behaviour.GetType(); - if (behaviourType.GetCustomAttributes(typeof(T), true).Length > 0) - return true; - } - return false; - } - - internal static IEnumerable CallMethodsWithAttribute(params object[] arguments) - where TAttr : Attribute - { - foreach (var method in EditorAssemblies.GetAllMethodsWithAttribute(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) - yield return (TReturnValue)method.Invoke(null, arguments); - } - - private static bool AreSignaturesMatching(MethodInfo left, MethodInfo right) - { - if (left.IsStatic != right.IsStatic) - return false; - if (left.ReturnType != right.ReturnType) - return false; - - - ParameterInfo[] leftParams = left.GetParameters(); - ParameterInfo[] rightParams = right.GetParameters(); - if (leftParams.Length != rightParams.Length) - return false; - for (int i = 0; i < leftParams.Length; i++) - { - if (leftParams[i].ParameterType != rightParams[i].ParameterType) - return false; - } - - return true; - } - - internal static string MethodToString(MethodInfo method) - { - return string.Format("{0}{1}", method.IsStatic ? "static " : "", method); - } - - internal static bool MethodMatchesAnyRequiredSignatureOfAttribute(MethodInfo method, Type attributeType) - { - List validSignatures = new List(); - foreach (var signature in attributeType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly)) - { - var requiredSignatureAttributes = signature.GetCustomAttributes(typeof(RequiredSignatureAttribute), false); - if (requiredSignatureAttributes.Length > 0) - { - if (AreSignaturesMatching(method, signature)) - { - return true; - } - validSignatures.Add(signature); - } - } - if (validSignatures.Count == 0) - Debug.LogError(MethodToString(method) + " has an invalid attribute : " + attributeType + ". " + attributeType + " must have at least one required signature declaration"); - else if (validSignatures.Count == 1) - Debug.LogError(MethodToString(method) + " does not match " + attributeType + " expected signature.\n Use " + MethodToString(validSignatures[0])); - else - Debug.LogError(MethodToString(method) + " does not match any of " + attributeType + " expected signatures.\n Valid signatures are: " + string.Join(" , ", validSignatures.Select((a) => MethodToString(a)).ToArray())); - return false; - } - - internal struct MethodWithAttribute - { - public MethodInfo info; - public Attribute attribute; - } - - internal class MethodInfoSorter - { - internal MethodInfoSorter(List methodsWithAttributes) - { - this.methodsWithAttributes = methodsWithAttributes; - } - - public IEnumerable FilterAndSortOnAttribute(Func filter, Func sorter) where T : Attribute - { - return methodsWithAttributes.Where(a => filter((T)a.attribute)).OrderBy(c => sorter((T)c.attribute)).Select(o => o.info); - } - - public IEnumerable methodsWithAttributes { get; } - } - - static Dictionary s_DecoratedMethodsByAttrTypeCache = new Dictionary(); - private const BindingFlags kAllStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; - - internal static MethodInfoSorter GetMethodsWithAttribute(BindingFlags bindingFlags = kAllStatic) where T : Attribute - { - MethodInfoSorter result; - if (!s_DecoratedMethodsByAttrTypeCache.TryGetValue(typeof(T), out result)) - { - var tmp = new List(); - foreach (var method in EditorAssemblies.GetAllMethodsWithAttribute(bindingFlags)) - { - if (method.IsGenericMethod) - { - Debug.LogErrorFormat( - "{0} is a generic method. {1} cannot be applied to it.", MethodToString(method), typeof(T) - ); - } - else - { - foreach (var attr in method.GetCustomAttributes(typeof(T), false)) - { - if (MethodMatchesAnyRequiredSignatureOfAttribute(method, typeof(T))) - { - var methodWithAttribute = new MethodWithAttribute { info = method, attribute = (T)attr }; - tmp.Add(methodWithAttribute); - } - } - } - } - - result = new MethodInfoSorter(tmp); - s_DecoratedMethodsByAttrTypeCache[typeof(T)] = result; - } - return result; - } - } -} diff --git a/Editor/Mono/Audio/Effects/AudioCurveRendering.cs b/Editor/Mono/Audio/Effects/AudioCurveRendering.cs deleted file mode 100644 index 5857c3305d..0000000000 --- a/Editor/Mono/Audio/Effects/AudioCurveRendering.cs +++ /dev/null @@ -1,294 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - public class AudioCurveRendering - { - // 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) - private static float pixelEpsilon = 0.005f; - - public delegate float AudioCurveEvaluator(float x); - public delegate float AudioCurveAndColorEvaluator(float x, out Color col); - public delegate void AudioMinMaxCurveAndColorEvaluator(float x, out Color col, out float minValue, out float maxValue); - public static readonly Color kAudioOrange = new Color(255 / 255f, 168 / 255f, 7 / 255f); - - // ------------- - // Frame, background and clipping utils - // ------------- - - // Returns the content rect (clipped) - public static Rect BeginCurveFrame(Rect r) - { - DrawCurveBackground(r); - - // Frame is subtracted from rect - r = DrawCurveFrame(r); - - // Content is clipped with group - GUI.BeginGroup(r); - return new Rect(0, 0, r.width, r.height); - } - - public static void EndCurveFrame() - { - GUI.EndGroup(); - } - - // Returns content rect - public static Rect DrawCurveFrame(Rect r) - { - if (Event.current.type != EventType.Repaint) - return r; - - EditorStyles.colorPickerBox.Draw(r, false, false, false, false); - - // Adjust rect for frame: colorPickerBox style has 1 px border - r.x += 1f; - r.y += 1f; - r.width -= 2f; - r.height -= 2f; - return r; - } - - public static void DrawCurveBackground(Rect r) - { - EditorGUI.DrawRect(r, new Color(0.3f, 0.3f, 0.3f)); - } - - // ------------- - // Curve rendering -- do not remove any of these, as they may be used by custom GUIs of native audio plugins - // ------------- - - public static void DrawFilledCurve(Rect r, AudioCurveEvaluator eval, Color curveColor) - { - DrawFilledCurve( - r, - delegate(float x, out Color color) - { - color = curveColor; - return eval(x); - } - ); - } - - public static void DrawFilledCurve(Rect r, AudioCurveAndColorEvaluator eval) - { - if (Event.current.type != EventType.Repaint) - return; - - HandleUtility.ApplyWireMaterial(); - - GL.Begin(GL.LINES); - - // Adjust by a half pixel to each side so that the transition covers a full pixel. - // This is needed for very slowly rising edges. - float pixelScale = (float)EditorGUIUtility.pixelsPerPoint; - float pixelSize = 1.0f / pixelScale; - float pixelHalfSize = 0.5f * pixelSize; - float pixelWidth = Mathf.Ceil(r.width) * pixelScale; - float startx = Mathf.Floor(r.x) + pixelEpsilon; - float wx = 1.0f / (float)(pixelWidth - 1); - float cy = r.height * 0.5f; - float my = r.y + 0.5f * r.height; - float y1 = r.y + r.height; - Color color; - - float py = Mathf.Clamp(cy * eval(0.0f, out color), -cy, cy); - for (int x = 0; x < pixelWidth; x++) - { - float nx = startx + x * pixelSize; - float ny = Mathf.Clamp(cy * eval(x * wx, out color), -cy, cy); - float e1 = Mathf.Min(ny, py) - pixelHalfSize; - float e2 = Mathf.Max(ny, py) + pixelHalfSize; - GL.Color(new Color(color.r, color.g, color.b, 0.0f)); - AudioMixerDrawUtils.Vertex(nx, my - e2); - GL.Color(color); - AudioMixerDrawUtils.Vertex(nx, my - e1); - AudioMixerDrawUtils.Vertex(nx, my - e1); - AudioMixerDrawUtils.Vertex(nx, y1); - py = ny; - } - - GL.End(); - } - - // Enforces minValue <= maxValue - private static void Sort2(ref float minValue, ref float maxValue) - { - if (minValue > maxValue) - { - float tmp = minValue; - minValue = maxValue; - maxValue = tmp; - } - } - - public static void DrawMinMaxFilledCurve(Rect r, AudioMinMaxCurveAndColorEvaluator eval) - { - HandleUtility.ApplyWireMaterial(); - - GL.Begin(GL.LINES); - - // Adjust by a half pixel to each side so that the transition covers a full pixel. - // This is needed for very slowly rising edges. - float pixelScale = (float)EditorGUIUtility.pixelsPerPoint; - float pixelSize = 1.0f / pixelScale; - float pixelHalfSize = 0.5f * pixelSize; - float pixelWidth = Mathf.Ceil(r.width) * pixelScale; - float startx = Mathf.Floor(r.x) + pixelEpsilon; - float wx = 1.0f / (float)(pixelWidth - 1); - float cy = r.height * 0.5f; - float my = r.y + 0.5f * r.height; - float minValue, maxValue; - Color color; - eval(0.0001f, out color, out minValue, out maxValue); Sort2(ref minValue, ref maxValue); - float pyMax = my - cy * Mathf.Clamp(maxValue, -1.0f, 1.0f); - float pyMin = my - cy * Mathf.Clamp(minValue, -1.0f, 1.0f); - float y1 = r.y, y2 = r.y + r.height; - for (int x = 0; x < pixelWidth; x++) - { - float nx = startx + x * pixelSize; - eval(x * wx, out color, out minValue, out maxValue); Sort2(ref minValue, ref maxValue); - Color edgeColor = new Color(color.r, color.g, color.b, 0.0f); - float nyMax = my - cy * Mathf.Clamp(maxValue, -1.0f, 1.0f); - float nyMin = my - cy * Mathf.Clamp(minValue, -1.0f, 1.0f); - float a = Mathf.Clamp(Mathf.Min(nyMax, pyMax) - pixelHalfSize, y1, y2); - float b = Mathf.Clamp(Mathf.Max(nyMax, pyMax) + pixelHalfSize, y1, y2); - float c = Mathf.Clamp(Mathf.Min(nyMin, pyMin) - pixelHalfSize, y1, y2); - float d = Mathf.Clamp(Mathf.Max(nyMin, pyMin) + pixelHalfSize, y1, y2); - 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); - GL.Color(edgeColor); - AudioMixerDrawUtils.Vertex(nx, a); - GL.Color(color); - AudioMixerDrawUtils.Vertex(nx, b); - AudioMixerDrawUtils.Vertex(nx, b); - AudioMixerDrawUtils.Vertex(nx, c); - AudioMixerDrawUtils.Vertex(nx, c); - GL.Color(edgeColor); - AudioMixerDrawUtils.Vertex(nx, d); - pyMin = nyMin; - pyMax = nyMax; - } - - GL.End(); - } - - public static void DrawSymmetricFilledCurve(Rect r, AudioCurveAndColorEvaluator eval) - { - if (Event.current.type != EventType.Repaint) - return; - - HandleUtility.ApplyWireMaterial(); - - GL.Begin(GL.LINES); - - // Adjust by a half pixel to each side so that the transition covers a full pixel. - // This is needed for very slowly rising edges. - float pixelScale = (float)EditorGUIUtility.pixelsPerPoint; - float pixelSize = 1.0f / pixelScale; - float pixelHalfSize = 0.5f * pixelSize; - float pixelWidth = Mathf.Ceil(r.width) * pixelScale; - float startx = Mathf.Floor(r.x) + pixelEpsilon; - float wx = 1.0f / (float)(pixelWidth - 1); - float cy = r.height * 0.5f; - float my = r.y + 0.5f * r.height; - Color color; - - float py = Mathf.Clamp(cy * eval(0.0001f, out color), 0.0f, cy); - for (int x = 0; x < pixelWidth; x++) - { - float nx = startx + x * pixelSize; - float ny = Mathf.Clamp(cy * eval(x * wx, out color), 0.0f, cy); - float e1 = Mathf.Max(Mathf.Min(ny, py) - pixelHalfSize, 0.0f); // Avoid self-intersection - float e2 = Mathf.Min(Mathf.Max(ny, py) + pixelHalfSize, cy); - Color edgeColor = new Color(color.r, color.g, color.b, 0.0f); - GL.Color(edgeColor); - AudioMixerDrawUtils.Vertex(nx, my - e2); - GL.Color(color); - AudioMixerDrawUtils.Vertex(nx, my - e1); - AudioMixerDrawUtils.Vertex(nx, my - e1); - AudioMixerDrawUtils.Vertex(nx, my + e1); - AudioMixerDrawUtils.Vertex(nx, my + e1); - GL.Color(edgeColor); - AudioMixerDrawUtils.Vertex(nx, my + e2); - py = ny; - } - - GL.End(); - } - - public static void DrawCurve(Rect r, AudioCurveEvaluator eval, Color curveColor) - { - if (Event.current.type != EventType.Repaint) - return; - - HandleUtility.ApplyWireMaterial(); - - int numpoints = (int)Mathf.Ceil(r.width); - float cy = r.height * 0.5f; - float ws = 1.0f / (numpoints - 1); - var line = GetPointCache(numpoints); - for (int n = 0; n < numpoints; n++) - { - line[n].x = (int)n + r.x; - line[n].y = cy - cy * eval(n * ws) + r.y; - line[n].z = 0.0f; - } - - GUI.BeginClip(r); - Handles.color = curveColor; - Handles.DrawAAPolyLine(3.0f, numpoints, line); - GUI.EndClip(); - } - - static Vector3[] s_PointCache; - static Vector3[] GetPointCache(int numPoints) - { - if (s_PointCache == null || s_PointCache.Length != numPoints) - { - s_PointCache = new Vector3[numPoints]; - } - return s_PointCache; - } - - // ------------- - // Curve gradient rect - // ------------- - - public static void DrawGradientRect(Rect r, Color c1, Color c2, float blend, bool horizontal) - { - if (Event.current.type != EventType.Repaint) - return; - HandleUtility.ApplyWireMaterial(); - GL.Begin(GL.QUADS); - if (horizontal) - { - GL.Color(new Color(c1.r, c1.g, c1.b, c1.a * blend)); - GL.Vertex3(r.x, r.y, 0); - GL.Vertex3(r.x + r.width, r.y, 0); - GL.Color(new Color(c2.r, c2.g, c2.b, c2.a * blend)); - GL.Vertex3(r.x + r.width, r.y + r.height, 0); - GL.Vertex3(r.x, r.y + r.height, 0); - } - else - { - GL.Color(new Color(c1.r, c1.g, c1.b, c1.a * blend)); - GL.Vertex3(r.x, r.y + r.height, 0); - GL.Vertex3(r.x, r.y, 0); - GL.Color(new Color(c2.r, c2.g, c2.b, c2.a * blend)); - GL.Vertex3(r.x + r.width, r.y, 0); - GL.Vertex3(r.x + r.width, r.y + r.height, 0); - } - GL.End(); - } - } -} diff --git a/Editor/Mono/Audio/Effects/AudioMixerEffectPlugin.cs b/Editor/Mono/Audio/Effects/AudioMixerEffectPlugin.cs deleted file mode 100644 index c2d159ed8b..0000000000 --- a/Editor/Mono/Audio/Effects/AudioMixerEffectPlugin.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using UnityEditor; -using UnityEditor.Audio; - -namespace UnityEditor.Audio -{ - public class AudioMixerEffectPlugin : IAudioEffectPlugin - { - public override bool SetFloatParameter(string name, float value) - { - m_Effect.SetValueForParameter(m_Controller, m_Controller.TargetSnapshot, name, value); - return true; - } - - public override bool GetFloatParameter(string name, out float value) - { - value = m_Effect.GetValueForParameter(m_Controller, m_Controller.TargetSnapshot, name); - return true; - } - - public override bool GetFloatParameterInfo(string name, out float minRange, out float maxRange, out float defaultValue) - { - foreach (var p in m_ParamDefs) - { - if (p.name == name) - { - minRange = p.minRange; - maxRange = p.maxRange; - defaultValue = p.defaultValue; - return true; - } - } - minRange = 0.0f; - maxRange = 1.0f; - defaultValue = 0.5f; - return false; - } - - public override bool GetFloatBuffer(string name, out float[] data, int numsamples) - { - m_Effect.GetFloatBuffer(m_Controller, name, out data, numsamples); - return true; - } - - public override int GetSampleRate() - { - return AudioSettings.outputSampleRate; - } - - public override bool IsPluginEditableAndEnabled() - { - return AudioMixerController.EditingTargetSnapshot() && !m_Effect.bypass; - } - - internal AudioMixerController m_Controller; - internal AudioMixerEffectController m_Effect; - internal MixerParameterDefinition[] m_ParamDefs; - } -} diff --git a/Editor/Mono/Audio/Effects/Complex.cs b/Editor/Mono/Audio/Effects/Complex.cs deleted file mode 100644 index 229d9daa1b..0000000000 --- a/Editor/Mono/Audio/Effects/Complex.cs +++ /dev/null @@ -1,148 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - // System.Numerics is not available - internal class ComplexD - { - public double real; - public double imag; - - public ComplexD(double real, double imag) - { - this.real = real; - this.imag = imag; - } - - static public ComplexD Add(ComplexD a, ComplexD b) - { - return new ComplexD( - a.real + b.real, - a.imag + b.imag); - } - - static public ComplexD Add(ComplexD a, double b) - { - return new ComplexD( - a.real + b, - a.imag); - } - - static public ComplexD Add(double a, ComplexD b) - { - return new ComplexD( - a + b.real, - b.imag); - } - - static public ComplexD Sub(ComplexD a, ComplexD b) - { - return new ComplexD( - a.real - b.real, - a.imag - b.imag); - } - - static public ComplexD Sub(ComplexD a, double b) - { - return new ComplexD( - a.real - b, - a.imag); - } - - static public ComplexD Sub(double a, ComplexD b) - { - return new ComplexD( - a - b.real, - -b.imag); - } - - static public ComplexD Mul(ComplexD a, ComplexD b) - { - return new ComplexD( - a.real * b.real - a.imag * b.imag, - a.real * b.imag + a.imag * b.real); - } - - static public ComplexD Mul(ComplexD a, double b) - { - return new ComplexD( - a.real * b, - a.imag * b); - } - - static public ComplexD Mul(double a, ComplexD b) - { - return new ComplexD( - a * b.real, - a * b.imag); - } - - static public ComplexD Div(ComplexD a, ComplexD b) - { - double d = b.real * b.real + b.imag * b.imag; - double s = 1.0 / d; - return new ComplexD( - (a.real * b.real + a.imag * b.imag) * s, - (a.imag * b.real - a.real * b.imag) * s); - } - - static public ComplexD Div(double a, ComplexD b) - { - double d = b.real * b.real + b.imag * b.imag; - double s = a / d; - return new ComplexD( - s * b.real, - -s * b.imag); - } - - static public ComplexD Div(ComplexD a, double b) - { - double s = 1.0 / b; - return new ComplexD( - a.real * s, - a.imag * s); - } - - static public ComplexD Exp(double omega) - { - return new ComplexD( - Math.Cos(omega), - Math.Sin(omega)); - } - - static public ComplexD Pow(ComplexD a, double b) - { - double p = Math.Atan2(a.imag, a.real); - double m = Math.Pow(a.Mag2(), b * 0.5f); - return new ComplexD( - m * Math.Cos(p * b), - m * Math.Sin(p * b) - ); - } - - public double Mag2() { return real * real + imag * imag; } - public double Mag() { return Math.Sqrt(Mag2()); } - - public static ComplexD operator+(ComplexD a, ComplexD b) { return Add(a, b); } - public static ComplexD operator-(ComplexD a, ComplexD b) { return Sub(a, b); } - public static ComplexD operator*(ComplexD a, ComplexD b) { return Mul(a, b); } - public static ComplexD operator/(ComplexD a, ComplexD b) { return Div(a, b); } - public static ComplexD operator+(ComplexD a, double b) { return Add(a, b); } - public static ComplexD operator-(ComplexD a, double b) { return Sub(a, b); } - public static ComplexD operator*(ComplexD a, double b) { return Mul(a, b); } - public static ComplexD operator/(ComplexD a, double b) { return Div(a, b); } - public static ComplexD operator+(double a, ComplexD b) { return Add(a, b); } - public static ComplexD operator-(double a, ComplexD b) { return Sub(a, b); } - public static ComplexD operator*(double a, ComplexD b) { return Mul(a, b); } - public static ComplexD operator/(double a, ComplexD b) { return Div(a, b); } - } -} diff --git a/Editor/Mono/Audio/Effects/DuckVolumeGUI.cs b/Editor/Mono/Audio/Effects/DuckVolumeGUI.cs deleted file mode 100644 index 33e7eb8bc4..0000000000 --- a/Editor/Mono/Audio/Effects/DuckVolumeGUI.cs +++ /dev/null @@ -1,338 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -//#define DEBUG_PLOT_GAIN - -using UnityEngine; - -namespace UnityEditor -{ - internal class DuckVolumeGUI : IAudioEffectPluginGUI - { - public static string kThresholdName = "Threshold"; - public static string kRatioName = "Ratio"; - public static string kMakeupGainName = "Make-up Gain"; - public static string kAttackTimeName = "Attack Time"; - public static string kReleaseTimeName = "Release Time"; - public static string kKneeName = "Knee"; - - public override string Name - { - get { return "Duck Volume"; } - } - - public override string Description - { - get { return "Volume Ducking"; } - } - - public override string Vendor - { - get { return "Unity Technologies"; } - } - - public static GUIStyle BuildGUIStyleForLabel(Color color, int fontSize, bool wrapText, FontStyle fontstyle, TextAnchor anchor) - { - GUIStyle style = new GUIStyle(); - style.focused.background = style.onNormal.background; - style.focused.textColor = color; - style.alignment = anchor; - style.fontSize = fontSize; - style.fontStyle = fontstyle; - style.wordWrap = wrapText; - style.clipping = TextClipping.Overflow; - style.normal.textColor = color; - return style; - } - - public static GUIStyle textStyle10 = BuildGUIStyleForLabel(Color.grey, 10, false, FontStyle.Normal, TextAnchor.MiddleLeft); - - public static void DrawText(float x, float y, string text) - { - GUI.Label(new Rect(x, y - 5, 200, 10), new GUIContent(text, ""), textStyle10); - } - - public static void DrawLine(float x1, float y1, float x2, float y2, Color col) - { - Handles.color = col; - Handles.DrawLine(new Vector3(x1, y1, 0), new Vector3(x2, y2, 0)); - } - - public enum DragType - { - None, - ThresholdAndKnee, - Ratio, - MakeupGain, - }; - - private static DragType dragtype = DragType.None; - - protected static Color ScaleAlpha(Color col, float blend) - { - return new Color(col.r, col.g, col.b, col.a * blend); - } - - protected static void DrawVU(Rect r, float level, float blend, bool topdown) - { - level = 1.0f - level; - const float border = 1; - 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)); - AudioMixerDrawUtils.DrawRect(r, new Color(0.1f, 0.1f, 0.1f)); - AudioMixerDrawUtils.DrawRect(r2, new Color(0.6f, 0.2f, 0.2f)); - } - - // Input: normalized x value [0;1]. Returns: normalized y value [-1;-1] - static float EvaluateDuckingVolume(float x, float ratio, float threshold, float makeupGain, float knee, float dbRange, float dbMin) - { - float duckGradient = 1.0f / ratio; - float duckThreshold = threshold; - float duckMakeupGain = makeupGain; - float duckKnee = knee; - float duckKneeC1 = (knee > 0.0f) ? ((duckGradient - 1.0f) / (4.0f * knee)) : 0.0f; - float duckKneeC2 = duckThreshold - knee; - - float level = x * dbRange + dbMin; - float gain = level; - float t = level - duckThreshold; - if (t > -duckKnee && t < duckKnee) - { - t += duckKnee; - gain = t * (duckKneeC1 * t + 1.0f) + duckKneeC2; - } - else if (t > 0.0f) - gain = duckThreshold + duckGradient * t; - return (2.0f * (gain + duckMakeupGain - dbMin) / dbRange) - 1.0f; - } - - 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) - { - Event evt = Event.current; - int controlID = GUIUtility.GetControlID(FocusType.Passive); - - Rect r = AudioCurveRendering.BeginCurveFrame(r0); - - const float thresholdActiveWidth = 10f; - float vuWidth = 10f; - - float minThreshold, maxThreshold, defThreshold; plugin.GetFloatParameterInfo(kThresholdName, out minThreshold, out maxThreshold, out defThreshold); - float minRatio, maxRatio, defRatio; plugin.GetFloatParameterInfo(kRatioName, out minRatio, out maxRatio, out defRatio); - float minMakeupGain, maxMakeupGain, defMakeupGain; plugin.GetFloatParameterInfo(kMakeupGainName, out minMakeupGain, out maxMakeupGain, out defMakeupGain); - float minKnee, maxKnee, defKnee; plugin.GetFloatParameterInfo(kKneeName, out minKnee, out maxKnee, out defKnee); - - float dbRange = 100.0f, dbMin = -80.0f; - float thresholdPosX = r.width * (threshold - dbMin) / dbRange; - - bool modifiedValue = false; - switch (evt.GetTypeForControl(controlID)) - { - case EventType.MouseDown: - if (r.Contains(Event.current.mousePosition) && evt.button == 0) - { - dragtype = DragType.None; - GUIUtility.hotControl = controlID; - EditorGUIUtility.SetWantsMouseJumping(1); - evt.Use(); - - // Ensure visible state change on mousedown to make it clear that interaction is possible - if ((Mathf.Abs(r.x + thresholdPosX - evt.mousePosition.x) >= thresholdActiveWidth)) - dragtype = (evt.mousePosition.x < r.x + thresholdPosX) ? DragType.MakeupGain : DragType.Ratio; - else - dragtype = DragType.ThresholdAndKnee; - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == controlID && evt.button == 0) - { - dragtype = DragType.None; - GUIUtility.hotControl = 0; - EditorGUIUtility.SetWantsMouseJumping(0); - evt.Use(); - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == controlID) - { - float dragAcceleration = evt.alt ? .25f : 1f; - if (dragtype == DragType.ThresholdAndKnee) - { - bool dragKnee = Mathf.Abs(evt.delta.x) < Mathf.Abs(evt.delta.y); - if (dragKnee) - knee = Mathf.Clamp(knee + evt.delta.y * 0.5f * dragAcceleration, minKnee, maxKnee); - else - threshold = Mathf.Clamp(threshold + evt.delta.x * 0.1f * dragAcceleration, minThreshold, maxThreshold); - } - else if (dragtype == DragType.Ratio) - ratio = Mathf.Clamp(ratio + evt.delta.y * (ratio > 1.0f ? 0.05f : 0.003f) * dragAcceleration, minRatio, maxRatio); - else if (dragtype == DragType.MakeupGain) - makeupGain = Mathf.Clamp(makeupGain - evt.delta.y * 0.5f * dragAcceleration, minMakeupGain, maxMakeupGain); - else - { - Debug.LogError("Drag: Unhandled enum"); - } - - modifiedValue = true; - evt.Use(); - } - break; - } - - if (evt.type == EventType.Repaint) - { - // Curve - HandleUtility.ApplyWireMaterial(); - - //float sidechainPosX = r.width * (sidechainLevel - dbMin) / dbRange; - float thresholdPosY = r.height * (1.0f - ((threshold - dbMin + makeupGain) / dbRange)); - Color thresholdColor = new Color(0.7f, 0.7f, 0.7f); - Color sidechainColor = Color.black; - - - float duckGradient = 1.0f / ratio; - float duckThreshold = threshold; - float duckSidechainLevel = sidechainLevel; - float duckMakeupGain = makeupGain; - float duckKnee = knee; - float duckKneeC1 = (knee > 0.0f) ? ((duckGradient - 1.0f) / (4.0f * knee)) : 0.0f; - float duckKneeC2 = duckThreshold - knee; - - // Main filled curve - AudioCurveRendering.DrawFilledCurve( - r, - delegate(float x, out Color col) - { - float level = x * dbRange + dbMin; - float gain = level; - float t = level - duckThreshold; - col = ScaleAlpha(duckSidechainLevel > level ? AudioCurveRendering.kAudioOrange : Color.grey, blend); - if (t > -duckKnee && t < duckKnee) - { - t += duckKnee; - gain = t * (duckKneeC1 * t + 1.0f) + duckKneeC2; - - if (dragtype == DragType.ThresholdAndKnee) - { - const float mult = 1.2f; - col = new Color(col.r * mult, col.g * mult, col.b * mult); - } - } - else if (t > 0.0f) - gain = duckThreshold + duckGradient * t; - return (2.0f * (gain + duckMakeupGain - dbMin) / dbRange) - 1.0f; - } - ); - - // Curve shown when modifying MakeupGain - if (dragtype == DragType.MakeupGain) - { - AudioCurveRendering.DrawCurve( - r, - delegate(float x) - { - float level = x * dbRange + dbMin; - float gain = level; - float t = level - duckThreshold; - if (t > -duckKnee && t < duckKnee) - { - t += duckKnee; - gain = t * (duckKneeC1 * t + 1.0f) + duckKneeC2; - } - else if (t > 0.0f) - gain = duckThreshold + duckGradient * t; - return (2.0f * (gain + duckMakeupGain - dbMin) / dbRange) - 1.0f; - }, - Color.white - ); - } - - - // Threshold text and line - textStyle10.normal.textColor = ScaleAlpha(thresholdColor, blend); - EditorGUI.DrawRect(new Rect(r.x + thresholdPosX, r.y, 1, r.height), textStyle10.normal.textColor); - DrawText(r.x + thresholdPosX + 4, r.y + 6, string.Format("Threshold: {0:F1} dB", threshold)); - - // Sidechain text and line - textStyle10.normal.textColor = ScaleAlpha(sidechainColor, blend); - DrawText(r.x + 4, r.y + r.height - 10, sidechainLevel < -80 ? "Input: None" : string.Format("Input: {0:F1} dB", sidechainLevel)); - - if (dragtype == DragType.Ratio) - { - float aspect = (float)r.height / (float)r.width; - Handles.DrawAAPolyLine(2.0f, - new Color[] { Color.black, Color.black }, - new Vector3[] - { - new Vector3(r.x + thresholdPosX + r.width, r.y + thresholdPosY - aspect * r.width, 0.0f), - new Vector3(r.x + thresholdPosX - r.width, r.y + thresholdPosY + aspect * r.width, 0.0f) - }); - Handles.DrawAAPolyLine(3.0f, - new Color[] { Color.white, Color.white }, - new Vector3[] - { - new Vector3(r.x + thresholdPosX + r.width, r.y + thresholdPosY - aspect * duckGradient * r.width, 0.0f), - new Vector3(r.x + thresholdPosX - r.width, r.y + thresholdPosY + aspect * duckGradient * r.width, 0.0f) - }); - } - else if (dragtype == DragType.ThresholdAndKnee) - { - // Knee min and max lines - float normalizedKnee1 = (threshold - knee - dbMin) / dbRange; - float normalizedKnee2 = (threshold + knee - dbMin) / dbRange; - float y1 = EvaluateDuckingVolume(normalizedKnee1, ratio, threshold, makeupGain, knee, dbRange, dbMin); - float y2 = EvaluateDuckingVolume(normalizedKnee2, ratio, threshold, makeupGain, knee, dbRange, dbMin); - float knee1PosY = r.yMax - (y1 + 1f) * 0.5f * r.height; - float knee2PosY = r.yMax - (y2 + 1f) * 0.5f * r.height; - EditorGUI.DrawRect(new Rect(r.x + normalizedKnee1 * r.width, knee1PosY, 1, r.height - knee1PosY), new Color(0, 0, 0, 0.5f)); - EditorGUI.DrawRect(new Rect(r.x + normalizedKnee2 * r.width - 1, knee2PosY, 1, r.height - knee2PosY), new Color(0, 0, 0, 0.5f)); - - // Enhanced threshold - EditorGUI.DrawRect(new Rect(r.x + thresholdPosX - 1, r.y, 3, r.height), Color.white); - } - - outputLevel = (Mathf.Clamp(outputLevel - makeupGain, dbMin, dbMin + dbRange) - dbMin) / dbRange; - if (EditorApplication.isPlaying) - { - const int margin = 2; - Rect vuRect = new Rect(r.x + r.width - vuWidth + margin, r.y + margin, vuWidth - 2 * margin, r.height - 2 * margin); - DrawVU(vuRect, outputLevel, blend, true); - } - } - - AudioCurveRendering.EndCurveFrame(); - - return modifiedValue; - } - - public override bool OnGUI(IAudioEffectPlugin plugin) - { - float blend = plugin.IsPluginEditableAndEnabled() ? 1.0f : 0.5f; - - float threshold, ratio, makeupGain, attackTime, releaseTime, knee; - plugin.GetFloatParameter(kThresholdName, out threshold); - plugin.GetFloatParameter(kRatioName, out ratio); - plugin.GetFloatParameter(kMakeupGainName, out makeupGain); - plugin.GetFloatParameter(kAttackTimeName, out attackTime); - plugin.GetFloatParameter(kReleaseTimeName, out releaseTime); - plugin.GetFloatParameter(kKneeName, out knee); - - float[] metering; plugin.GetFloatBuffer("Metering", out metering, 2); - - GUILayout.Space(5f); - Rect r = GUILayoutUtility.GetRect(200, 160, GUILayout.ExpandWidth(true)); - if (CurveDisplay(plugin, r, ref threshold, ref ratio, ref makeupGain, ref attackTime, ref releaseTime, ref knee, metering[0], metering[1], blend)) - { - plugin.SetFloatParameter(kThresholdName, threshold); - plugin.SetFloatParameter(kRatioName, ratio); - plugin.SetFloatParameter(kMakeupGainName, makeupGain); - plugin.SetFloatParameter(kAttackTimeName, attackTime); - plugin.SetFloatParameter(kReleaseTimeName, releaseTime); - plugin.SetFloatParameter(kKneeName, knee); - } - - return true; - } - } -} diff --git a/Editor/Mono/Audio/Effects/IAudioEffectPlugin.cs b/Editor/Mono/Audio/Effects/IAudioEffectPlugin.cs deleted file mode 100644 index 68a0256bdd..0000000000 --- a/Editor/Mono/Audio/Effects/IAudioEffectPlugin.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - public abstract class IAudioEffectPlugin - { - public abstract bool SetFloatParameter(string name, float value); - public abstract bool GetFloatParameter(string name, out float value); - public abstract bool GetFloatParameterInfo(string name, out float minRange, out float maxRange, out float defaultValue); - public abstract bool GetFloatBuffer(string name, out float[] data, int numsamples); - public abstract int GetSampleRate(); - public abstract bool IsPluginEditableAndEnabled(); - } -} diff --git a/Editor/Mono/Audio/Effects/IAudioEffectPluginGUI.cs b/Editor/Mono/Audio/Effects/IAudioEffectPluginGUI.cs deleted file mode 100644 index f22f756a0f..0000000000 --- a/Editor/Mono/Audio/Effects/IAudioEffectPluginGUI.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - public abstract class IAudioEffectPluginGUI - { - public abstract string Name { get; } - public abstract string Description { get; } - public abstract string Vendor { get; } - public abstract bool OnGUI(IAudioEffectPlugin plugin); - } -} diff --git a/Editor/Mono/Audio/Effects/ParamEQGUI.cs b/Editor/Mono/Audio/Effects/ParamEQGUI.cs deleted file mode 100644 index 8788016f1d..0000000000 --- a/Editor/Mono/Audio/Effects/ParamEQGUI.cs +++ /dev/null @@ -1,197 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; - -namespace UnityEditor -{ - internal class ParamEqGUI : IAudioEffectPluginGUI - { - public static string kCenterFreqName = "Center freq"; - public static string kOctaveRangeName = "Octave range"; - public static string kFrequencyGainName = "Frequency gain"; - - public override string Name - { - get { return "ParamEQ"; } - } - - public override string Description - { - get { return "Parametric equalizer"; } - } - - public override string Vendor - { - get { return "Firelight Technologies"; } - } - - const bool useLogScale = true; - - public static GUIStyle BuildGUIStyleForLabel(Color color, int fontSize, bool wrapText, FontStyle fontstyle, TextAnchor anchor) - { - GUIStyle style = new GUIStyle(); - style.focused.background = style.onNormal.background; - style.focused.textColor = color; - style.alignment = anchor; - style.fontSize = fontSize; - style.fontStyle = fontstyle; - style.wordWrap = wrapText; - style.clipping = TextClipping.Overflow; - style.normal.textColor = color; - return style; - } - - public static GUIStyle textStyle10 = BuildGUIStyleForLabel(Color.grey, 10, false, FontStyle.Normal, TextAnchor.MiddleCenter); - - private static void DrawFrequencyTickMarks(Rect r, float samplerate, bool logScale, Color col) - { - textStyle10.normal.textColor = col; - float px = r.x, w = 60.0f; - for (float normFreq = 0; normFreq < 1.0f; normFreq += 0.01f) - { - float f = (float)MapNormalizedFrequency(normFreq, samplerate, logScale, true); - float x = r.x + normFreq * r.width; - if (x - px > w) - { - EditorGUI.DrawRect(new Rect(x, r.yMax - 5f, 1f, 5f), col); - GUI.Label(new Rect(x, r.yMax - 22f, 1, 15f), (f < 1000.0f) ? string.Format("{0:F0} Hz", f) : string.Format("{0:F0} kHz", f * 0.001f), textStyle10); - px = x; - } - } - } - - protected static Color ScaleAlpha(Color col, float blend) - { - return new Color(col.r, col.g, col.b, col.a * blend); - } - - // Maps from normalized frequency to real frequency - private static double MapNormalizedFrequency(double f, double sr, bool useLogScale, bool forward) - { - double maxFreq = 0.5 * sr; - if (useLogScale) - { - const double lowestFreq = 10.0; - if (forward) - return lowestFreq * Math.Pow(maxFreq / lowestFreq, f); - return Math.Log(f / lowestFreq) / Math.Log(maxFreq / lowestFreq); - } - return (forward) ? (f * maxFreq) : (f / maxFreq); - } - - static bool ParamEqualizerCurveEditor(IAudioEffectPlugin plugin, Rect r, ref float centerFreq, ref float bandwidth, ref float gain, float blend) - { - Event evt = Event.current; - int controlID = GUIUtility.GetControlID(FocusType.Passive); - - r = AudioCurveRendering.BeginCurveFrame(r); - - float minCenterFreq, maxCenterFreq, defCenterFreq; plugin.GetFloatParameterInfo(kCenterFreqName, out minCenterFreq, out maxCenterFreq, out defCenterFreq); - float minOctaveRange, maxOctaveRange, defOctaveRange; plugin.GetFloatParameterInfo(kOctaveRangeName, out minOctaveRange, out maxOctaveRange, out defOctaveRange); - float minGain, maxGain, defGain; plugin.GetFloatParameterInfo(kFrequencyGainName, out minGain, out maxGain, out defGain); - - bool modifiedValue = false; - switch (evt.GetTypeForControl(controlID)) - { - case EventType.MouseDown: - if (r.Contains(Event.current.mousePosition) && evt.button == 0) - { - GUIUtility.hotControl = controlID; - EditorGUIUtility.SetWantsMouseJumping(1); - evt.Use(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == controlID && evt.button == 0) - { - GUIUtility.hotControl = 0; - EditorGUIUtility.SetWantsMouseJumping(0); - evt.Use(); - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == controlID) - { - float dragAcceleration = Event.current.alt ? .25f : 1f; - centerFreq = Mathf.Clamp((float)MapNormalizedFrequency(MapNormalizedFrequency(centerFreq, plugin.GetSampleRate(), useLogScale, false) + evt.delta.x / r.width, plugin.GetSampleRate(), useLogScale, true), minCenterFreq, maxCenterFreq); - if (Event.current.shift) - bandwidth = Mathf.Clamp(bandwidth - evt.delta.y * 0.02f * dragAcceleration, minOctaveRange, maxOctaveRange); - else - gain = Mathf.Clamp(gain - evt.delta.y * 0.01f * dragAcceleration, minGain, maxGain); - modifiedValue = true; - evt.Use(); - } - break; - } - - if (Event.current.type == EventType.Repaint) - { - // Mark CenterFreq with a vertical line - float c = (float)MapNormalizedFrequency(centerFreq, plugin.GetSampleRate(), useLogScale, false); - 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)); - - // Curve - HandleUtility.ApplyWireMaterial(); - double kPI = 3.1415926; - double wm = -2.0f * kPI / plugin.GetSampleRate(); - double w0 = 2.0 * kPI * centerFreq / plugin.GetSampleRate(); - double Q = 1.0 / bandwidth; - double A = gain; - double alpha = Math.Sin(w0) / (2.0 * Q); - double b0 = 1.0 + alpha * A; - double b1 = -2.0 * Math.Cos(w0); - double b2 = 1.0 - alpha * A; - double a0 = 1.0 + alpha / A; - double a1 = -2.0 * Math.Cos(w0); - double a2 = 1.0 - alpha / A; - AudioCurveRendering.DrawCurve( - r, - delegate(float x) - { - double f = MapNormalizedFrequency((double)x, plugin.GetSampleRate(), useLogScale, true); - ComplexD w = ComplexD.Exp(wm * f); - ComplexD n = w * (w * b2 + b1) + b0; - ComplexD d = w * (w * a2 + a1) + a0; - ComplexD h = n / d; - double mag = Math.Log10(h.Mag2()); - return (float)(0.5 * mag); // 20 dB range - }, - ScaleAlpha(AudioCurveRendering.kAudioOrange, blend) - ); - } - - DrawFrequencyTickMarks(r, plugin.GetSampleRate(), useLogScale, new Color(1.0f, 1.0f, 1.0f, 0.3f * blend)); - - AudioCurveRendering.EndCurveFrame(); - - return modifiedValue; - } - - public override bool OnGUI(IAudioEffectPlugin plugin) - { - float blend = plugin.IsPluginEditableAndEnabled() ? 1.0f : 0.5f; - - float centerFreq, octaveRange, frequencyGain; - plugin.GetFloatParameter(kCenterFreqName, out centerFreq); - plugin.GetFloatParameter(kOctaveRangeName, out octaveRange); - plugin.GetFloatParameter(kFrequencyGainName, out frequencyGain); - - GUILayout.Space(5f); - Rect r = GUILayoutUtility.GetRect(200, 100, GUILayout.ExpandWidth(true)); - if (ParamEqualizerCurveEditor(plugin, r, ref centerFreq, ref octaveRange, ref frequencyGain, blend)) - { - plugin.SetFloatParameter(kCenterFreqName, centerFreq); - plugin.SetFloatParameter(kOctaveRangeName, octaveRange); - plugin.SetFloatParameter(kFrequencyGainName, frequencyGain); - } - - return true; - } - } -} diff --git a/Editor/Mono/Audio/Mixer/AudioMixerDescription.cs b/Editor/Mono/Audio/Mixer/AudioMixerDescription.cs deleted file mode 100644 index c85637695e..0000000000 --- a/Editor/Mono/Audio/Mixer/AudioMixerDescription.cs +++ /dev/null @@ -1,156 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections.Generic; - -//FIXME: change this to nested namespaces when we merge in trunk -namespace UnityEditor.Audio -{ - internal class MixerEffectDefinition - { - public MixerEffectDefinition(string name, MixerParameterDefinition[] parameters) - { - this.m_EffectName = name; - this.m_Parameters = new MixerParameterDefinition[parameters.Length]; - Array.Copy(parameters, this.m_Parameters, parameters.Length); - } - - public string name - { - get { return this.m_EffectName; } - } - - public MixerParameterDefinition[] parameters - { - get { return this.m_Parameters; } - } - - private readonly string m_EffectName; - //TODO: GUI callback - private readonly MixerParameterDefinition[] m_Parameters; - } - - - [InitializeOnLoad] - static class MixerEffectDefinitionReloader - { - // We use this class with InitializeOnLoad attribute for ensuring MixerEffectDefinitions are refreshed - // when needed: 1) At startup, 2) after script recompile and 3) when project changes (new effects can have been added) - static MixerEffectDefinitionReloader() - { - MixerEffectDefinitions.Refresh(); - - EditorApplication.projectChanged += OnProjectChanged; - } - - static void OnProjectChanged() - { - MixerEffectDefinitions.Refresh(); - } - } - - - internal sealed partial class MixerEffectDefinitions - { - public static void Refresh() - { - ClearDefinitions(); - - RegisterAudioMixerEffect("Attenuation", new MixerParameterDefinition[0]); - RegisterAudioMixerEffect("Send", new MixerParameterDefinition[0]); - RegisterAudioMixerEffect("Receive", new MixerParameterDefinition[0]); - - var duckVolDef = new MixerParameterDefinition[7]; - 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" }; - 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" }; - 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" }; - 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" }; - 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" }; - 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" }; - 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." }; - RegisterAudioMixerEffect("Duck Volume", duckVolDef); - AddDefinitionRuntime("Duck Volume", duckVolDef); - - string[] effectNames = GetAudioEffectNames(); - foreach (var effectName in effectNames) - { - MixerParameterDefinition[] paramDesc = GetAudioEffectParameterDesc(effectName); - RegisterAudioMixerEffect(effectName, paramDesc); - } - } - - public static bool EffectExists(string name) - { - foreach (MixerEffectDefinition definition in s_MixerEffectDefinitions) - { - if (definition.name == name) - { - return true; - } - } - - return false; - } - - public static string[] GetEffectList() - { - string[] effectNames = new string[s_MixerEffectDefinitions.Count]; - for (int i = 0; i < s_MixerEffectDefinitions.Count; i++) - { - effectNames[i] = s_MixerEffectDefinitions[i].name; - } - - return effectNames; - } - - public static void ClearDefinitions() - { - s_MixerEffectDefinitions.Clear(); - ClearDefinitionsRuntime(); - } - - public static MixerParameterDefinition[] GetEffectParameters(string effect) - { - foreach (MixerEffectDefinition definition in s_MixerEffectDefinitions) - { - if (definition.name == effect) - { - return definition.parameters; - } - } - - return new MixerParameterDefinition[0]; - } - - public static bool RegisterAudioMixerEffect(string name, MixerParameterDefinition[] definitions) - { - foreach (MixerEffectDefinition definition in s_MixerEffectDefinitions) - { - if (definition.name == name) - { - //Cannot add this type, already exists in the system. - return false; - } - } - - MixerEffectDefinition newDefinition = new MixerEffectDefinition(name, definitions); - s_MixerEffectDefinitions.Add(newDefinition); - - //Wasteful - Clears the runtime representation each time a new effect is added and rebuilds all runtime - //representations. - ClearDefinitionsRuntime(); - foreach (MixerEffectDefinition definition in s_MixerEffectDefinitions) - { - AddDefinitionRuntime(definition.name, definition.parameters); - } - - return true; - } - - private static readonly List s_MixerEffectDefinitions = new List(); - } -} diff --git a/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs b/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs deleted file mode 100644 index 30c3582fa6..0000000000 --- a/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs +++ /dev/null @@ -1,1085 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Audio; -using UnityEditor; -using UnityEditor.Audio; -using System.IO; -using System; -using System.Linq; - -using Object = UnityEngine.Object; - -namespace UnityEditor.Audio -{ - internal abstract class AudioParameterPath - { - public GUID parameter; - - public abstract string ResolveStringPath(bool getOnlyBasePath); - } - - internal class AudioGroupParameterPath : AudioParameterPath - { - public AudioMixerGroupController group; - - public AudioGroupParameterPath(AudioMixerGroupController group, GUID parameter) - { - this.group = group; - this.parameter = parameter; - } - - public override string ResolveStringPath(bool getOnlyBasePath) - { - if (getOnlyBasePath) - return GetBasePath(group.GetDisplayString(), null); - - if (group.GetGUIDForVolume() == parameter) - { - return "Volume" + GetBasePath(group.GetDisplayString(), null); - } - else if (group.GetGUIDForPitch() == parameter) - { - return "Pitch" + GetBasePath(group.GetDisplayString(), null); - } - else - { - return "Error finding Parameter path."; - } - } - - protected string GetBasePath(string group, string effect) - { - string result = " (of " + group; - if (!string.IsNullOrEmpty(effect)) - result += "\u2794" + effect; //u2794 is a right arrow character - result += ")"; - return result; - } - } - - internal sealed class AudioEffectParameterPath : AudioGroupParameterPath - { - public AudioMixerEffectController effect; - - public AudioEffectParameterPath(AudioMixerGroupController group, AudioMixerEffectController effect, GUID parameter) - : base(group, parameter) - { - this.effect = effect; - } - - public override string ResolveStringPath(bool getOnlyBasePath) - { - if (getOnlyBasePath) - return GetBasePath(group.GetDisplayString(), effect.effectName); - - if (effect.GetGUIDForMixLevel() == parameter) - { - return "Mix Level" + GetBasePath(group.GetDisplayString(), effect.effectName); - } - else - { - MixerParameterDefinition[] paramDefs = MixerEffectDefinitions.GetEffectParameters(effect.effectName); - for (int i = 0; i < paramDefs.Length; i++) - { - GUID guid = effect.GetGUIDForParameter(paramDefs[i].name); - if (guid == parameter) - { - return paramDefs[i].name + GetBasePath(group.GetDisplayString(), effect.effectName); - } - } - - return "Error finding Parameter path."; - } - } - } - - internal delegate void ChangedExposedParameterHandler(); - - [ExcludeFromPreset] - internal sealed partial class AudioMixerController : AudioMixer - { - public static float kMinVolume = -80.0f; // The minimum volume is the level at which sends and effects can be bypassed - public static float kMaxEffect = 0.0f; - public static float kVolumeWarp = 1.7f; - public static string s_GroupEffectDisplaySeperator = "\\"; // Use backslash instead of forward slash to prevent OS menus from splitting path and creating submenus - - public event ChangedExposedParameterHandler ChangedExposedParameter; - public void OnChangedExposedParameter() - { - if (ChangedExposedParameter != null) - ChangedExposedParameter(); - } - - public void ClearEventHandlers() - { - if (ChangedExposedParameter != null) - { - foreach (Delegate d in ChangedExposedParameter.GetInvocationList()) - { - ChangedExposedParameter -= (ChangedExposedParameterHandler)d; - } - } - } - - [System.NonSerialized] - private Dictionary m_ExposedParamPathCache; - private Dictionary exposedParamCache - { - get - { - if (m_ExposedParamPathCache == null) - m_ExposedParamPathCache = new Dictionary(); - - return m_ExposedParamPathCache; - } - } - - private string FindUniqueParameterName(string template, ExposedAudioParameter[] parameters) - { - string unique = template; - int counter = 1; - for (int i = 0; i < parameters.Length; i++) - { - if (unique == parameters[i].name) - { - unique = template + " " + counter++; - i = -1; - } - } - - return unique; - } - - int SortFuncForExposedParameters(ExposedAudioParameter p1, ExposedAudioParameter p2) - { - return string.CompareOrdinal(ResolveExposedParameterPath(p1.guid, true), ResolveExposedParameterPath(p2.guid, true)); - } - - public void AddExposedParameter(AudioParameterPath path) - { - if (!ContainsExposedParameter(path.parameter)) - { - List parameters = new List(exposedParameters); - ExposedAudioParameter newParam = new ExposedAudioParameter(); - newParam.name = FindUniqueParameterName("MyExposedParam", exposedParameters); - newParam.guid = path.parameter; - parameters.Add(newParam); - - // We sort the exposed params by path - parameters.Sort(SortFuncForExposedParameters); - - exposedParameters = parameters.ToArray(); - OnChangedExposedParameter(); - - //Cache the path! - exposedParamCache[path.parameter] = path; - - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - else - { - Debug.LogError("Cannot expose the same parameter more than once!"); - } - } - - public bool ContainsExposedParameter(GUID parameter) - { - return exposedParameters.Where(val => val.guid == parameter).ToArray().Length > 0; - } - - public void RemoveExposedParameter(GUID parameter) - { - exposedParameters = exposedParameters.Where(val => val.guid != parameter).ToArray(); - OnChangedExposedParameter(); - - //Tidy up the cache.. - if (exposedParamCache.ContainsKey(parameter)) - exposedParamCache.Remove(parameter); - - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - - public string ResolveExposedParameterPath(GUID parameter, bool getOnlyBasePath) - { - //consult the cache of parameters first. - if (exposedParamCache.ContainsKey(parameter)) - { - AudioParameterPath path = exposedParamCache[parameter]; - - return path.ResolveStringPath(getOnlyBasePath); - } - - //Search through the whole mixer! - List groups = GetAllAudioGroupsSlow(); - foreach (AudioMixerGroupController group in groups) - { - if (group.GetGUIDForVolume() == parameter || - group.GetGUIDForPitch() == parameter) - { - AudioGroupParameterPath newPath = new AudioGroupParameterPath(group, parameter); - exposedParamCache[parameter] = newPath; - return newPath.ResolveStringPath(getOnlyBasePath); - } - else - { - for (int i = 0; i < group.effects.Length; i++) - { - AudioMixerEffectController effect = group.effects[i]; - MixerParameterDefinition[] paramDefs = MixerEffectDefinitions.GetEffectParameters(effect.effectName); - - for (int j = 0; j < paramDefs.Length; j++) - { - GUID guid = effect.GetGUIDForParameter(paramDefs[j].name); - if (guid == parameter) - { - AudioEffectParameterPath newPath = new AudioEffectParameterPath(group, effect, parameter); - exposedParamCache[parameter] = newPath; - return newPath.ResolveStringPath(getOnlyBasePath); - } - } - } - } - } - return "Error finding Parameter path"; - } - - public static AudioMixerController CreateMixerControllerAtPath(string path) - { - var controller = new AudioMixerController(); - controller.CreateDefaultAsset(path); - return controller; - } - - public void CreateDefaultAsset(string path) - { - masterGroup = new AudioMixerGroupController(this); - masterGroup.name = "Master"; - masterGroup.PreallocateGUIDs(); - - var attenuation = new AudioMixerEffectController("Attenuation"); - attenuation.PreallocateGUIDs(); - masterGroup.InsertEffect(attenuation, 0); - - AudioMixerSnapshotController snapshot = new AudioMixerSnapshotController(this); - snapshot.name = "Snapshot"; - this.snapshots = new AudioMixerSnapshotController[] { snapshot }; - - this.startSnapshot = snapshot; - - Object[] objectArray = { this, masterGroup, attenuation, snapshot }; - AssetDatabase.CreateAssetFromObjects(objectArray, path); - } - - private void BuildTestSetup(System.Random r, AudioMixerGroupController parent, int minSpan, int maxSpan, int maxGroups, string prefix, ref int numGroups) - { - int span = (numGroups == 0) ? maxSpan : r.Next(minSpan, maxSpan + 1); - for (int i = 0; i < span; i++) - { - var name = prefix + i; - var g = CreateNewGroup(name, false); - AddChildToParent(g, parent); - if (++numGroups >= maxGroups) - return; - BuildTestSetup(r, g, minSpan, (maxSpan > minSpan) ? (maxSpan - 1) : minSpan, maxGroups, name, ref numGroups); - } - } - - public void BuildTestSetup(int minSpan, int maxSpan, int maxGroups) - { - int numGroups = 0; - DeleteGroups(masterGroup.children); - BuildTestSetup(new System.Random(), masterGroup, minSpan, maxSpan, maxGroups, "G", ref numGroups); - } - - public List GetAllAudioGroupsSlow() - { - List groups = new List(); - if (masterGroup != null) - GetAllAudioGroupsSlowRecurse(masterGroup, ref groups); - return groups; - } - - private void GetAllAudioGroupsSlowRecurse(AudioMixerGroupController g, ref List groups) - { - groups.Add(g); - foreach (var c in g.children) - GetAllAudioGroupsSlowRecurse(c, ref groups); - } - - public bool HasMoreThanOneGroup() - { - return masterGroup.children.Length > 0; - } - - // Returns true if there is an ancestor of child in the groups list - private bool IsChildOf(AudioMixerGroupController child, List groups) - { - while (child != null) - { - child = FindParentGroup(masterGroup, child); - if (groups.Contains(child)) - return true; - } - return false; - } - - // 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 - // ancestor path from items in the list to any other items in the list. - public bool AreAnyOfTheGroupsInTheListAncestors(List groups) - { - return groups.Any(g => IsChildOf(g, groups)); - } - - // 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 - // child-parent relationship. By working on a cleaned list, duplication/removal is simplified a lot and just becomes a matter or recursively traversing - // each of the items in the selection without the need to watch out for sub-items that already got deleted during the recursive traversal. - private void RemoveAncestorGroups(List groups) - { - groups.RemoveAll(g => IsChildOf(g, groups)); - Debug.Equals(AreAnyOfTheGroupsInTheListAncestors(groups), false); - } - - private void DestroyExposedParametersContainedInEffect(AudioMixerEffectController effect) - { - Undo.RecordObject(this, "Changed Exposed Parameters"); - //Cleanup exposed parameters that were in the effect - var exposedParams = exposedParameters; - foreach (var param in exposedParams) - { - if (effect.ContainsParameterGUID(param.guid)) - RemoveExposedParameter(param.guid); - } - } - - private void DestroyExposedParametersContainedInGroup(AudioMixerGroupController group) - { - Undo.RecordObject(this, "Remove Exposed Parameter"); - //Clean up the exposed parameters that were in the group. - var exposedParams = exposedParameters; - foreach (var param in exposedParams) - { - if (group.GetGUIDForVolume() == param.guid || group.GetGUIDForPitch() == param.guid) - RemoveExposedParameter(param.guid); - } - } - - private void DeleteSubGroupRecursive(AudioMixerGroupController group) - { - foreach (var child in group.children) - DeleteSubGroupRecursive(child); - - foreach (var effect in group.effects) - { - DestroyExposedParametersContainedInEffect(effect); - Undo.DestroyObjectImmediate(effect); - } - - DestroyExposedParametersContainedInGroup(group); - Undo.DestroyObjectImmediate(group); - } - - private void DeleteGroupsInternal(List groupsToDelete, List allGroups) - { - foreach (var potentialParent in allGroups) - { - var deletedInParent = groupsToDelete.Intersect(potentialParent.children); - if (deletedInParent.Count() > 0) - { - Undo.RegisterCompleteObjectUndo(potentialParent, "Delete Group(s)"); - potentialParent.children = potentialParent.children.Except(deletedInParent).ToArray(); - } - } - - foreach (var group in groupsToDelete) - DeleteSubGroupRecursive(group); - } - - public void DeleteGroups(AudioMixerGroupController[] groups) - { - List filteredGroups = groups.ToList(); - RemoveAncestorGroups(filteredGroups); - - DeleteGroupsInternal(filteredGroups, GetAllAudioGroupsSlow()); - - OnUnitySelectionChanged(); - } - - public void RemoveEffect(AudioMixerEffectController effect, AudioMixerGroupController group) - { - Undo.RecordObject(group, "Delete Effect"); - - var modifiedEffectsList = new List(group.effects); - modifiedEffectsList.Remove(effect); - group.effects = modifiedEffectsList.ToArray(); - - DestroyExposedParametersContainedInEffect(effect); - Undo.DestroyObjectImmediate(effect); - } - - public void OnSubAssetChanged() - { - AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(this)); - } - - public void CloneNewSnapshotFromTarget(bool storeUndoState) - { - var snapshotList = new List(snapshots); - var ob = Instantiate(TargetSnapshot); - var newSnapshot = ob as AudioMixerSnapshotController; - newSnapshot.name = TargetSnapshot.name + " - Copy"; - snapshotList.Add(newSnapshot); - snapshots = snapshotList.ToArray(); - TargetSnapshot = snapshotList[snapshotList.Count - 1]; - - AssetDatabase.AddObjectToAsset(newSnapshot, this); - if (storeUndoState) - Undo.RegisterCreatedObjectUndo(newSnapshot, ""); - - OnSubAssetChanged(); - } - - public void RemoveTargetSnapshot() - { - if (snapshots.Length < 2) - return; - - var deletedSnapshot = TargetSnapshot; - - Undo.RecordObject(this, "Remove Snapshot"); - - var snapshotList = new List(snapshots); - snapshotList.Remove(deletedSnapshot); - snapshots = snapshotList.ToArray(); - - Undo.DestroyObjectImmediate(deletedSnapshot); - - OnSubAssetChanged(); - } - - public void RemoveSnapshot(AudioMixerSnapshotController snapshot) - { - if (snapshots.Length < 2) - return; - - var deletedSnapshot = snapshot; - - Undo.RecordObject(this, "Remove Snapshot"); - - var snapshotList = new List(snapshots); - snapshotList.Remove(deletedSnapshot); - snapshots = snapshotList.ToArray(); - - Undo.DestroyObjectImmediate(deletedSnapshot); - - OnSubAssetChanged(); - } - - public AudioMixerGroupController CreateNewGroup(string name, bool storeUndoState) - { - var group = new AudioMixerGroupController(this); - group.name = name; - group.PreallocateGUIDs(); - - var effect = new AudioMixerEffectController("Attenuation"); - AddNewSubAsset(effect, storeUndoState); - effect.PreallocateGUIDs(); - - group.InsertEffect(effect, 0); - AddNewSubAsset(group, storeUndoState); - - return group; - } - - public void AddChildToParent(AudioMixerGroupController child, AudioMixerGroupController parent) - { - RemoveGroupsFromParent(new AudioMixerGroupController[] { child }, false); - var modifiedChildList = new List(parent.children); - modifiedChildList.Add(child); - parent.children = modifiedChildList.ToArray(); - } - - void AddNewSubAsset(Object obj, bool storeUndoState) - { - AssetDatabase.AddObjectToAsset(obj, this); - if (storeUndoState) - Undo.RegisterCreatedObjectUndo(obj, ""); - } - - public void RemoveGroupsFromParent(AudioMixerGroupController[] groups, bool storeUndoState) - { - List filteredGroups = groups.ToList(); - RemoveAncestorGroups(filteredGroups); - - if (storeUndoState) - Undo.RecordObject(this, "Remove group"); - foreach (var g in filteredGroups) - { - List allGroups = GetAllAudioGroupsSlow(); - foreach (var parent in allGroups) - { - List modifiedChildList = new List(parent.children); - if (modifiedChildList.Contains(g)) - modifiedChildList.Remove(g); - if (parent.children.Length != modifiedChildList.Count) - parent.children = modifiedChildList.ToArray(); - } - } - } - - public AudioMixerGroupController FindParentGroup(AudioMixerGroupController node, AudioMixerGroupController group) - { - for (int n = 0; n < node.children.Length; n++) - { - if (node.children[n] == group) - return node; - var g = FindParentGroup(node.children[n], group); - if (g != null) - return g; - } - return null; - } - - public AudioMixerEffectController CopyEffect(AudioMixerEffectController sourceEffect) - { - var copiedEffect = new AudioMixerEffectController(sourceEffect.effectName); - copiedEffect.name = sourceEffect.name; - copiedEffect.PreallocateGUIDs(); - MixerParameterDefinition[] paramDefs = MixerEffectDefinitions.GetEffectParameters(sourceEffect.effectName); - float value; - foreach (var s in snapshots) - { - if (s.GetValue(sourceEffect.GetGUIDForMixLevel(), out value)) - s.SetValue(copiedEffect.GetGUIDForMixLevel(), value); - foreach (var p in paramDefs) - { - if (s.GetValue(sourceEffect.GetGUIDForParameter(p.name), out value)) - s.SetValue(copiedEffect.GetGUIDForParameter(p.name), value); - } - } - - AssetDatabase.AddObjectToAsset(copiedEffect, this); - return copiedEffect; - } - - private AudioMixerGroupController DuplicateGroupRecurse(AudioMixerGroupController sourceGroup, bool recordUndo) - { - var targetGroup = new AudioMixerGroupController(this); - - // Copy effects - var targetEffectsList = new List(); - foreach (var sourceEffect in sourceGroup.effects) - { - targetEffectsList.Add(CopyEffect(sourceEffect)); - } - - // Copy child groups - var targetChildren = new List(); - foreach (var childGroup in sourceGroup.children) - targetChildren.Add(DuplicateGroupRecurse(childGroup, recordUndo)); - - targetGroup.name = sourceGroup.name + " - Copy"; - targetGroup.PreallocateGUIDs(); - targetGroup.effects = targetEffectsList.ToArray(); - targetGroup.children = targetChildren.ToArray(); - targetGroup.solo = sourceGroup.solo; - targetGroup.mute = sourceGroup.mute; - targetGroup.bypassEffects = sourceGroup.bypassEffects; - float value; - foreach (var s in snapshots) - { - if (s.GetValue(sourceGroup.GetGUIDForVolume(), out value)) - s.SetValue(targetGroup.GetGUIDForVolume(), value); - if (s.GetValue(sourceGroup.GetGUIDForPitch(), out value)) - s.SetValue(targetGroup.GetGUIDForPitch(), value); - } - - AssetDatabase.AddObjectToAsset(targetGroup, this); - - if (recordUndo) - Undo.RegisterCreatedObjectUndo(targetGroup, targetGroup.name); - - // Add to view if source is shown (so it's visible in the channelstrip) - if (CurrentViewContainsGroup(sourceGroup.groupID)) - targetGroup.controller.AddGroupToCurrentView(targetGroup); - - return targetGroup; - } - - // Returns duplicated root groups (traverse group.children to get all groups duplicated) - public List DuplicateGroups(AudioMixerGroupController[] sourceGroups, bool recordUndo) - { - List filteredGroups = sourceGroups.ToList(); - RemoveAncestorGroups(filteredGroups); - - var allRoots = new List(); - - foreach (var source in filteredGroups) - { - AudioMixerGroupController parent = FindParentGroup(masterGroup, source); - if (parent != null && source != null) - { - if (recordUndo) - Undo.RecordObject(parent, "Reparent AudioMixerGroup"); - - AudioMixerGroupController copy = DuplicateGroupRecurse(source, recordUndo); - - var modifiedChildList = new List(parent.children); - modifiedChildList.Add(copy); - parent.children = modifiedChildList.ToArray(); - - allRoots.Add(copy); - } - } - - return allRoots; - } - - public void CopyEffectSettingsToAllSnapshots(AudioMixerGroupController group, int effectIndex, AudioMixerSnapshotController snapshot, bool includeWetParam) - { - AudioMixerSnapshotController[] snaps = snapshots; - for (int n = 0; n < snaps.Length; n++) - { - if (snaps[n] == snapshot) - continue; - var effect = group.effects[effectIndex]; - MixerParameterDefinition[] paramDefs = MixerEffectDefinitions.GetEffectParameters(effect.effectName); - float value; - if (includeWetParam) - { - var guid = effect.GetGUIDForMixLevel(); - if (snapshot.GetValue(guid, out value)) - snaps[n].SetValue(guid, value); - } - foreach (var p in paramDefs) - { - var guid = effect.GetGUIDForParameter(p.name); - if (snapshot.GetValue(guid, out value)) - snaps[n].SetValue(guid, value); - } - } - } - - public void CopyAllSettingsToAllSnapshots(AudioMixerGroupController group, AudioMixerSnapshotController snapshot) - { - for (int n = 0; n < group.effects.Length; n++) - CopyEffectSettingsToAllSnapshots(group, n, snapshot, true); - - AudioMixerSnapshotController[] snaps = snapshots; - for (int n = 0; n < snaps.Length; n++) - { - if (snaps[n] == snapshot) - continue; - var dst = snaps[n]; - group.SetValueForVolume(this, dst, group.GetValueForVolume(this, snapshot)); - group.SetValueForPitch(this, dst, group.GetValueForPitch(this, snapshot)); - } - } - - public void CopyAttenuationToAllSnapshots(AudioMixerGroupController group, AudioMixerSnapshotController snapshot) - { - AudioMixerSnapshotController[] snaps = snapshots; - for (int n = 0; n < snaps.Length; n++) - { - if (snaps[n] == snapshot) - continue; - var dst = snaps[n]; - group.SetValueForVolume(this, dst, group.GetValueForVolume(this, snapshot)); - } - } - - public void ReparentSelection(AudioMixerGroupController newParent, int insertionIndex, List selection) - { - // We are moving items so we adjust the insertion index to accomodate that any items above the insertion index is removed before inserting - if (insertionIndex >= 0) - insertionIndex -= newParent.children.ToList().GetRange(0, insertionIndex).Count(selection.Contains); - - Undo.RecordObject(newParent, "Change Audio Mixer Group Parent"); - List groups = GetAllAudioGroupsSlow(); - foreach (var g in groups) - { - // Check if any groups in the selection is part of current groups child list - if (g.children.Intersect(selection).Any()) - { - Undo.RecordObject(g, string.Empty); // empty string will use undo name above - var modifiedChildList = new List(g.children); - foreach (var c in selection) - modifiedChildList.Remove(c); - g.children = modifiedChildList.ToArray(); - } - } - - // When dragging upon we insert as first child - if (insertionIndex == -1) - insertionIndex = 0; - - var newChildList = new List(newParent.children); - newChildList.InsertRange(insertionIndex, selection); - newParent.children = newChildList.ToArray(); - } - - public static bool InsertEffect(AudioMixerEffectController effect, ref List targetEffects, int targetIndex) - { - if (targetIndex < 0 || targetIndex > targetEffects.Count) - { - Debug.LogError("Inserting effect failed! size: " + targetEffects.Count + " at index: " + targetIndex); - return false; - } - - targetEffects.Insert(targetIndex, effect); - return true; - } - - public static bool MoveEffect(ref List sourceEffects, int sourceIndex, ref List targetEffects, int targetIndex) - { - if (sourceEffects == targetEffects) - { - if (targetIndex > sourceIndex) - targetIndex--; - if (sourceIndex == targetIndex) - return false; - } - if (sourceIndex < 0 || sourceIndex >= sourceEffects.Count) - return false; - if (targetIndex < 0 || targetIndex > targetEffects.Count) - return false; - AudioMixerEffectController effect = sourceEffects[sourceIndex]; - sourceEffects.RemoveAt(sourceIndex); - targetEffects.Insert(targetIndex, effect); - return true; - } - - // Todo: Remove this function (we should ensure that effect names are valid for popup menus) - static public string FixNameForPopupMenu(string s) - { - return s; - } - - public void ClearSendConnectionsTo(AudioMixerEffectController sendTarget) - { - var allGroups = GetAllAudioGroupsSlow(); - foreach (var g in allGroups) - foreach (var e in g.effects) - if (e.IsSend() && e.sendTarget == sendTarget) - { - Undo.RecordObject(e, "Clear Send target"); - e.sendTarget = null; - } - } - - public class ConnectionNode - { - public bool visited = false; - public object groupTail = null; - public List targets = new List(); - public AudioMixerGroupController group = null; - public AudioMixerEffectController effect = null; - public string GetDisplayString() - { - string s = group.GetDisplayString(); - if (effect != null) - s += s_GroupEffectDisplaySeperator + FixNameForPopupMenu(effect.effectName); - return s; - } - }; - - // Builds a graph over all connections going out of a group (the parent counts as one). - // While building the map, the existing routing of effectSlotUnderTest are ignored and pretended it is connected to targetToTest instead. - // Then checks are performed whether this setup would cause any loops in the graph. - static private Dictionary BuildTemporaryGraph( - List allGroups, - AudioMixerGroupController groupWhoseEffectIsChanged, AudioMixerEffectController effectWhoseTargetIsChanged, AudioMixerEffectController targetToTest, - AudioMixerGroupController modifiedGroup1, List modifiedGroupEffects1, - AudioMixerGroupController modifiedGroup2, List modifiedGroupEffects2 - ) - { - // First build the chains of groups and their contained effects - var graph = new Dictionary(); - foreach (var group in allGroups) - { - var groupNode = new ConnectionNode(); - groupNode.group = group; - groupNode.effect = null; - graph[group] = groupNode; - object groupTail = group; - var reorderedEffects = (group == modifiedGroup1) ? modifiedGroupEffects1 : (group == modifiedGroup2) ? modifiedGroupEffects2 : group.effects.ToList(); - foreach (var effect in reorderedEffects) - { - if (!graph.ContainsKey(effect)) - graph[effect] = new ConnectionNode(); - graph[effect].group = group; - graph[effect].effect = effect; - if (!graph[groupTail].targets.Contains(effect)) - graph[groupTail].targets.Add(effect); - AudioMixerEffectController target = (group == groupWhoseEffectIsChanged && effectWhoseTargetIsChanged == effect) ? targetToTest : effect.sendTarget; - if (target != null) - { - if (!graph.ContainsKey(target)) - { - graph[target] = new ConnectionNode(); - graph[target].group = group; - graph[target].effect = target; - } - if (!graph[effect].targets.Contains(target)) - graph[effect].targets.Add(target); - } - groupTail = effect; - } - graph[group].groupTail = groupTail; - } - return graph; - } - - static private void ListTemporaryGraph(Dictionary graph) - { - Debug.Log("Listing temporary graph:"); - int nodeIndex = 0; - foreach (var node in graph) - { - Debug.Log(string.Format("Node {0}: {1}", nodeIndex++, node.Value.GetDisplayString())); - int targetIndex = 0; - foreach (var t in node.Value.targets) - Debug.Log(string.Format(" Target {0}: {1}", targetIndex++, graph[t].GetDisplayString())); - } - } - - static private bool CheckForCycle(object curr, Dictionary graph, List identifiedLoop) - { - var node = graph[curr]; - if (node.visited) - { - if (identifiedLoop != null) - { - identifiedLoop.Clear(); - identifiedLoop.Add(node); - } - return true; - } - node.visited = true; - foreach (var s in node.targets) - { - if (CheckForCycle(s, graph, identifiedLoop)) - { - node.visited = false; - if (identifiedLoop != null) - identifiedLoop.Add(node); - return true; - } - } - node.visited = false; - return false; - } - - static public bool DoesTheTemporaryGraphHaveAnyCycles(List allGroups, List identifiedLoop, Dictionary graph) - { - foreach (var g in allGroups) - { - if (CheckForCycle(g, graph, identifiedLoop)) - { - // Clean up identified loop so that we only show the looping part and not what lead to it - if (identifiedLoop != null) - { - var start = identifiedLoop[0]; - int i; - for (i = 1; i < identifiedLoop.Count;) - if (identifiedLoop[i++] == start) - break; - identifiedLoop.RemoveRange(i, identifiedLoop.Count - i); - identifiedLoop.Reverse(); - } - return true; - } - } - return false; - } - - static public bool WillChangeOfEffectTargetCauseFeedback(List allGroups, AudioMixerGroupController groupWhoseEffectIsChanged, int effectWhoseTargetIsChanged, AudioMixerEffectController targetToTest, List identifiedLoop) - { - var graph = BuildTemporaryGraph(allGroups, groupWhoseEffectIsChanged, groupWhoseEffectIsChanged.effects[effectWhoseTargetIsChanged], targetToTest, null, null, null, null); - - // Connect the chains up using the group hierarchy - foreach (var group in allGroups) - { - foreach (var childGroup in group.children) - { - var tailOfChildGroup = graph[childGroup].groupTail; - if (!graph[tailOfChildGroup].targets.Contains(group)) - graph[tailOfChildGroup].targets.Add(group); - } - } - - //ListTemporaryGraph(graph); - - return DoesTheTemporaryGraphHaveAnyCycles(allGroups, identifiedLoop, graph); - } - - static public bool WillModificationOfTopologyCauseFeedback(List allGroups, List groupsToBeMoved, AudioMixerGroupController newParentForMovedGroups, List identifiedLoop) - { - var graph = BuildTemporaryGraph(allGroups, null, null, null, null, null, null, null); - - // Connect the chains up using the group hierarchy, pretending that the groups in the list groupsToBeMoved belong to newParentForMovedGroups - foreach (var group in allGroups) - { - foreach (var childGroup in group.children) - { - var parentGroup = (groupsToBeMoved.Contains(childGroup)) ? newParentForMovedGroups : group; - var tailOfChildGroup = graph[childGroup].groupTail; - if (!graph[tailOfChildGroup].targets.Contains(parentGroup)) - graph[tailOfChildGroup].targets.Add(parentGroup); - } - } - - //ListTemporaryGraph(graph); - - return DoesTheTemporaryGraphHaveAnyCycles(allGroups, identifiedLoop, graph); - } - - static public bool WillMovingEffectCauseFeedback(List allGroups, AudioMixerGroupController sourceGroup, int sourceIndex, AudioMixerGroupController targetGroup, int targetIndex, List identifiedLoop) - { - Dictionary graph; - - if (sourceGroup == targetGroup) - { - var modifiedEffects = sourceGroup.effects.ToList(); - if (!MoveEffect(ref modifiedEffects, sourceIndex, ref modifiedEffects, targetIndex)) - return false; - graph = BuildTemporaryGraph(allGroups, null, null, null, sourceGroup, modifiedEffects, null, null); - } - else - { - var modifiedSourceEffects = sourceGroup.effects.ToList(); - var modifiedTargetEffects = targetGroup.effects.ToList(); - if (!MoveEffect(ref modifiedSourceEffects, sourceIndex, ref modifiedTargetEffects, targetIndex)) - return false; - graph = BuildTemporaryGraph(allGroups, null, null, null, sourceGroup, modifiedSourceEffects, targetGroup, modifiedTargetEffects); - } - - // Connect the chains up using the group hierarchy - foreach (var group in allGroups) - { - foreach (var childGroup in group.children) - { - var tailOfChildGroup = graph[childGroup].groupTail; - if (!graph[tailOfChildGroup].targets.Contains(group)) - graph[tailOfChildGroup].targets.Add(group); - } - } - - //ListTemporaryGraph(graph); - - return DoesTheTemporaryGraphHaveAnyCycles(allGroups, identifiedLoop, graph); - } - - static public float DbToLin(float x) - { - // 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. - if (x < kMinVolume) - return 0.0f; - - return Mathf.Pow(10.0f, x * 0.05f); - } - - public void CloneViewFromCurrent() - { - Undo.RecordObject(this, "Create view"); - - var viewList = new List(views); - MixerGroupView view = new MixerGroupView(); - view.name = views[currentViewIndex].name + " - Copy"; - view.guids = views[currentViewIndex].guids; - viewList.Add(view); - views = viewList.ToArray(); - - currentViewIndex = viewList.Count - 1; - } - - public void DeleteView(int index) - { - Undo.RecordObject(this, "Delete view"); - - var viewList = new List(views); - viewList.RemoveAt(index); - views = viewList.ToArray(); - - int newIndex = Mathf.Clamp(currentViewIndex, 0, viewList.Count - 1); - ForceSetView(newIndex); - } - - public void SetView(int index) - { - if (currentViewIndex != index) - ForceSetView(index); - } - - public void SanitizeGroupViews() - { - List allGroups = GetAllAudioGroupsSlow(); - var viewList = views; - - for (int i = 0; i < viewList.Length; i++) - { - viewList[i].guids = - (from x in viewList[i].guids - from y in allGroups - where y.groupID == x - select x).ToArray(); - } - - views = viewList.ToArray(); - } - - public void ForceSetView(int index) - { - currentViewIndex = index; - SanitizeGroupViews(); - } - - public void AddGroupToCurrentView(AudioMixerGroupController group) - { - var viewList = views; - List guidList = viewList[currentViewIndex].guids.ToList(); - guidList.Add(group.groupID); - viewList[currentViewIndex].guids = guidList.ToArray(); - views = viewList.ToArray(); - } - - public void SetCurrentViewVisibility(GUID[] guids) - { - var viewList = views; - viewList[currentViewIndex].guids = guids; - views = viewList.ToArray(); - SanitizeGroupViews(); - } - - public AudioMixerGroupController[] GetCurrentViewGroupList() - { - List allGroups = GetAllAudioGroupsSlow(); - MixerGroupView view = views[currentViewIndex]; - - return (from g in allGroups - where view.guids.Contains(g.groupID) - select g).ToArray(); - } - - public static float VolumeToScreenMapping(float value, float screenRange, bool forward) - { - float screenRange1 = GetVolumeSplitPoint() * screenRange; - float screenRange2 = screenRange - screenRange1; - if (forward) - return (value > 0.0f) ? (screenRange1 - Mathf.Pow(value / GetMaxVolume(), 1.0f / kVolumeWarp) * screenRange1) : ((Mathf.Pow(value / kMinVolume, 1.0f / kVolumeWarp) * screenRange2) + screenRange1); - else - return (value < screenRange1) ? (Mathf.Pow(1.0f - (value / screenRange1), kVolumeWarp) * GetMaxVolume()) : (Mathf.Pow((value - screenRange1) / screenRange2, kVolumeWarp) * kMinVolume); - } - - public void OnUnitySelectionChanged() - { - List allGroups = GetAllAudioGroupsSlow(); - - var selected = Selection.GetFiltered(typeof(AudioMixerGroupController), SelectionMode.Deep); - m_CachedSelection = allGroups.Intersect(selected.Select(g => (AudioMixerGroupController)g)).ToList(); - } - } -} diff --git a/Editor/Mono/Audio/Mixer/Bindings/AudioMixerGroup.cs b/Editor/Mono/Audio/Mixer/Bindings/AudioMixerGroup.cs deleted file mode 100644 index fa92fd4ebc..0000000000 --- a/Editor/Mono/Audio/Mixer/Bindings/AudioMixerGroup.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditor.Audio; -using System.IO; -using System.Collections.Generic; -using System; - -namespace UnityEditor.Audio -{ - [ExcludeFromPreset] - internal partial class AudioMixerGroupController - { - public void InsertEffect(AudioMixerEffectController effect, int index) - { - var modifiedEffectsList = new List(effects); - modifiedEffectsList.Add(null); - for (int i = modifiedEffectsList.Count - 1; i > index; i--) - modifiedEffectsList[i] = modifiedEffectsList[i - 1]; - modifiedEffectsList[index] = effect; - effects = modifiedEffectsList.ToArray(); - } - - public bool HasAttenuation() - { - foreach (var e in effects) - if (e.IsAttenuation()) - return true; - return false; - } - - public void DumpHierarchy(string title, int level) - { - if (title != "") - Console.WriteLine(title); - - string prefix = ""; - int l = level; - while (l-- > 0) - prefix += " "; - Console.WriteLine(prefix + "name=" + name); - - prefix += " "; - foreach (var f in effects) - Console.WriteLine(prefix + "effect=" + f.ToString()); - - foreach (var g in children) - g.DumpHierarchy("", level + 1); - } - - public string GetDisplayString() - { - return name; // AudioMixerController.FixNameForPopupMenu(name); - } - - public override string ToString() - { - return name; - } - } - - internal class MixerGroupControllerCompareByName : IComparer - { - public int Compare(AudioMixerGroupController x, AudioMixerGroupController y) - { - return StringComparer.InvariantCultureIgnoreCase.Compare(x.GetDisplayString(), y.GetDisplayString()); - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerChannelStripView.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerChannelStripView.cs deleted file mode 100644 index 7e160d1f42..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerChannelStripView.cs +++ /dev/null @@ -1,1730 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using System; -using UnityEditorInternal; -using UnityEditor.Audio; - -namespace UnityEditor -{ - internal class AudioMixerChannelStripView - { - [Serializable] - public class State - { - public int m_LastClickedInstanceID = 0; - public Vector2 m_ScrollPos = new Vector2(0, 0); - } - - public static float kVolumeScaleMouseDrag = 1.0f; - public static float kEffectScaleMouseDrag = 0.3f; // higher precision for effect slot editing - - private static Color kMoveColorHighlight = new Color(0.3f, 0.6f, 1.0f, 0.4f); - private static Color kMoveSlotColHiAllowed = new Color(1f, 1f, 1f, 0.7f); //new Color(59 / 255f, 162 / 255f, 216 / 255f, 0.7f); - private static Color kMoveSlotColLoAllowed = new Color(1f, 1f, 1f, 0.0f); - private static Color kMoveSlotColBorderAllowed = new Color(1f, 1f, 1f, 1.0f); - private static Color kMoveSlotColHiDisallowed = new Color(1.0f, 0.0f, 0.0f, 0.7f); - private static Color kMoveSlotColLoDisallowed = new Color(0.8f, 0.0f, 0.0f, 0.0f); - private static Color kMoveSlotColBorderDisallowed = new Color(1.0f, 0.0f, 0.0f, 1.0f); - private static int kRectSelectionHashCode = "RectSelection".GetHashCode(); - private static int kEffectDraggingHashCode = "EffectDragging".GetHashCode(); - private static int kVerticalFaderHash = "VerticalFader".GetHashCode(); - - public int m_FocusIndex = -1; - public int m_IndexCounter = 0; - public int m_EffectInteractionControlID; - public int m_RectSelectionControlID; - public float m_MouseDragStartX = 0.0f; - public float m_MouseDragStartY = 0.0f; - public float m_MouseDragStartValue = 0.0f; - public Vector2 m_RectSelectionStartPos = new Vector2(0, 0); - public Rect m_RectSelectionRect = new Rect(0, 0, 0, 0); - - State m_State; - private AudioMixerController m_Controller; - private MixerGroupControllerCompareByName m_GroupComparer = new MixerGroupControllerCompareByName(); - private bool m_WaitingForDragEvent = false; - private int m_ChangingWetMixIndex = -1; - private int m_MovingEffectSrcIndex = -1; - private int m_MovingEffectDstIndex = -1; - private Rect m_MovingSrcRect = new Rect(-1, -1, 0, 0); - private Rect m_MovingDstRect = new Rect(-1, -1, 0, 0); - private bool m_MovingEffectAllowed = false; - private AudioMixerGroupController m_MovingSrcGroup = null; - private AudioMixerGroupController m_MovingDstGroup = null; - private const float k_MinVULevel = -80f; - private List m_LastNumChannels = new List(); - - private bool m_RequiresRepaint = false; - public bool requiresRepaint - { - get - { - if (m_RequiresRepaint) - { - m_RequiresRepaint = false; - return true; - } - return false; - } - } - - const float headerHeight = 22f; - const float vuHeight = 170f; - const float dbHeight = 17f; - const float soloMuteBypassHeight = 30f; - const float effectHeight = 16f; - const float spaceBetween = 0; - const int channelStripSpacing = 4; - const float channelStripBaseWidth = 90f; - const float spaceBetweenMainGroupsAndReferenced = 50f; - readonly Vector2 channelStripsOffset = new Vector2(15, 10); - - // For background ui - static Texture2D m_GridTexture; - private const float kGridTileWidth = 12.0f; - private static readonly Color kGridColorDark = new Color(0f, 0f, 0f, 0.18f); - private static readonly Color kGridColorLight = new Color(0f, 0f, 0f, 0.10f); - private static Color gridColor - { - get - { - if (EditorGUIUtility.isProSkin) - return kGridColorDark; - else - return kGridColorLight; - } - } - - private AudioMixerDrawUtils.Styles styles - { - get { return AudioMixerDrawUtils.styles; } - } - - public AudioMixerChannelStripView(AudioMixerChannelStripView.State state) - { - m_State = state; - } - - static Texture2D CreateTilableGridTexture(int width, int height, Color backgroundColor, Color lineColor) - { - Color[] pixels = new Color[width * height]; - - // background - for (int i = 0; i < height * width; i++) - pixels[i] = backgroundColor; - - // right edge - for (int i = 0; i < height; i++) - pixels[i * width + (width - 1)] = lineColor; - - // bottom edge - for (int i = 0; i < width; i++) - pixels[(height - 1) * width + i] = lineColor; - - Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false); - texture.hideFlags = HideFlags.HideAndDontSave; - texture.SetPixels(pixels); - texture.Apply(); - return texture; - } - - Texture2D gridTextureTilable - { - get - { - if (m_GridTexture == null) - m_GridTexture = CreateTilableGridTexture((int)kGridTileWidth, (int)kGridTileWidth, new Color(0, 0, 0, 0), gridColor); - return m_GridTexture; - } - } - - void DrawAreaBackground(Rect rect) - { - if (Event.current.type == EventType.Repaint) - { - // Draw background - Color prevColor = GUI.color; - GUI.color = new Color(1, 1, 1, EditorGUIUtility.isProSkin ? 0.6f : 0.2f); - AudioMixerDrawUtils.styles.channelStripAreaBackground.Draw(rect, false, false, false, false); - GUI.color = prevColor; - // Draw grid - //GUI.DrawTextureWithTexCoords (rect, gridTextureTilable, new Rect(0, 0, rect.width / gridTextureTilable.width, rect.height / gridTextureTilable.height), true); - } - } - - private void SetFocus() { m_FocusIndex = m_IndexCounter; } - private void ClearFocus() { m_FocusIndex = -1; } - private bool HasFocus() { return m_FocusIndex == m_IndexCounter; } - private bool IsFocusActive() { return m_FocusIndex != -1; } - - public class EffectContext - { - public EffectContext(AudioMixerController controller, AudioMixerGroupController[] groups, int index, string name) - { - this.controller = controller; - this.groups = groups; - this.index = index; - this.name = name; - } - - public AudioMixerController controller; - public AudioMixerGroupController[] groups; - public int index; - public string name; - } - - public static void InsertEffectPopupCallback(object obj) - { - EffectContext context = (EffectContext)obj; - - foreach (AudioMixerGroupController group in context.groups) - { - Undo.RecordObject(group, "Add effect"); - AudioMixerEffectController newEffect = new AudioMixerEffectController(context.name); - - int index = (context.index == -1 || context.index > group.effects.Length) ? group.effects.Length : context.index; - group.InsertEffect(newEffect, index); - AssetDatabase.AddObjectToAsset(newEffect, context.controller); - newEffect.PreallocateGUIDs(); - } - - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - - public void RemoveEffectPopupCallback(object obj) - { - EffectContext context = (EffectContext)obj; - - foreach (AudioMixerGroupController group in context.groups) - { - if (context.index >= group.effects.Length) - continue; - AudioMixerEffectController effect = group.effects[context.index]; - context.controller.ClearSendConnectionsTo(effect); - context.controller.RemoveEffect(effect, group); - } - - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - - public class ConnectSendContext - { - public ConnectSendContext(AudioMixerEffectController sendEffect, AudioMixerEffectController targetEffect) - { - this.sendEffect = sendEffect; - this.targetEffect = targetEffect; - } - - public AudioMixerEffectController sendEffect; - public AudioMixerEffectController targetEffect; - } - - public static void ConnectSendPopupCallback(object obj) - { - ConnectSendContext context = (ConnectSendContext)obj; - Undo.RecordObject(context.sendEffect, "Change Send Target"); - context.sendEffect.sendTarget = context.targetEffect; - } - - private bool ClipRect(Rect r, Rect clipRect, ref Rect overlap) - { - overlap.x = Mathf.Max(r.x, clipRect.x); - overlap.y = Mathf.Max(r.y, clipRect.y); - overlap.width = Mathf.Min(r.x + r.width, clipRect.x + clipRect.width) - overlap.x; - overlap.height = Mathf.Min(r.y + r.height, clipRect.y + clipRect.height) - overlap.y; - return overlap.width > 0.0f && overlap.height > 0.0f; - } - - public float VerticalFader(Rect r, float value, int direction, float dragScale, bool drawScaleValues, bool drawMarkerValue, string tooltip, float maxValue, GUIStyle style) - { - Event evt = Event.current; - int handleHeight = (int)style.fixedHeight; - int faderScreenRange = (int)r.height - handleHeight; - float valueScreenPos = AudioMixerController.VolumeToScreenMapping(Mathf.Clamp(value, AudioMixerController.kMinVolume, maxValue), faderScreenRange, true); - Rect handleRect = new Rect(r.x, r.y + (int)valueScreenPos, r.width, handleHeight); - - int controlID = GUIUtility.GetControlID(kVerticalFaderHash, FocusType.Passive); - - switch (evt.GetTypeForControl(controlID)) - { - case EventType.MouseDown: - if (r.Contains(evt.mousePosition) && GUIUtility.hotControl == 0) - { - m_MouseDragStartY = evt.mousePosition.y; - m_MouseDragStartValue = valueScreenPos; - GUIUtility.hotControl = controlID; - evt.Use(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == controlID) - { - GUIUtility.hotControl = 0; - evt.Use(); - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == controlID) - { - valueScreenPos = Mathf.Clamp(m_MouseDragStartValue + dragScale * (evt.mousePosition.y - m_MouseDragStartY), 0.0f, faderScreenRange); - value = Mathf.Clamp(AudioMixerController.VolumeToScreenMapping(valueScreenPos, faderScreenRange, false), AudioMixerController.kMinVolume, maxValue); - evt.Use(); - } - break; - - case EventType.Repaint: - - // Ticks and Numbers - if (drawScaleValues) - { - float tickStartY = r.y + handleHeight / 2f; - float level = maxValue; - using (new EditorGUI.DisabledScope(true)) - { - while (level >= AudioMixerController.kMinVolume) - { - float y = AudioMixerController.VolumeToScreenMapping(level, faderScreenRange, true); - - if (level / 10 % 2 == 0) - GUI.Label(new Rect(r.x, tickStartY + y - 7, r.width, 14), GUIContent.Temp(Mathf.RoundToInt(level).ToString()), styles.vuValue); - EditorGUI.DrawRect(new Rect(r.x, tickStartY + y - 1, 5f, 1), new Color(0, 0, 0, 0.5f)); - level -= 10.0f; - } - } - } - - // Drag handle - if (drawMarkerValue) - style.Draw(handleRect, GUIContent.Temp(Mathf.RoundToInt(value).ToString()), false, false, false, false); - else - style.Draw(handleRect, false, false, false, false); - AudioMixerDrawUtils.AddTooltipOverlay(handleRect, tooltip); - break; - } - - return value; - } - - private static Color hfaderCol1 = new Color(0.2f, 0.2f, 0.2f, 1.0f); - private static Color hfaderCol2 = new Color(0.4f, 0.4f, 0.4f, 1.0f); - - public float HorizontalFader(Rect r, float value, float minValue, float maxValue, int direction, float dragScale) - { - m_IndexCounter++; - Rect r2 = new Rect(r); - float handleWidth = r.width * 0.2f, faderScreenRange = r2.width - handleWidth; - AudioMixerDrawUtils.DrawGradientRect(r2, hfaderCol1, hfaderCol2); - Event evt = Event.current; - if (evt.type == EventType.MouseDown && r2.Contains(evt.mousePosition)) - { - m_MouseDragStartX = evt.mousePosition.x; - m_MouseDragStartValue = value; - SetFocus(); - } - if (HasFocus()) - { - if (evt.type == EventType.MouseDrag) - { - value = m_MouseDragStartValue + (dragScale * (maxValue - minValue) * (evt.mousePosition.x - m_MouseDragStartX) / faderScreenRange); - Event.current.Use(); - } - else if (evt.type == EventType.MouseUp) - { - ClearFocus(); - Event.current.Use(); - } - } - value = Mathf.Clamp(value, minValue, maxValue); - r2.x = r.x; - r2.width = r.width; - r2.x = r.x + faderScreenRange * ((value - minValue) / (maxValue - minValue)); - r2.width = handleWidth; - AudioMixerDrawUtils.DrawGradientRect(r2, hfaderCol2, hfaderCol1); - return value; - } - - public GUIStyle sharedGuiStyle = new GUIStyle(); - - public GUIStyle GetEffectBarStyle(AudioMixerEffectController effect) - { - if (effect.IsSend() || effect.IsReceive() || effect.IsDuckVolume()) - return styles.sendReturnBar; - if (effect.IsAttenuation()) - return styles.attenuationBar; - - return styles.effectBar; - } - - class PatchSlot - { - public AudioMixerGroupController group; - public float x, y; - }; - - GUIContent bypassButtonContent = new GUIContent("", "Toggle bypass on this effect"); - void EffectSlot(Rect effectRect, AudioMixerSnapshotController snapshot, AudioMixerEffectController effect, int effectIndex, ref int highlightEffectIndex, ChannelStripParams p, ref Dictionary patchslots) - { - if (effect == null) - return; - - Rect r = effectRect; - - Event evt = Event.current; - if (evt.type == EventType.Repaint && patchslots != null && (effect.IsSend() || MixerEffectDefinitions.EffectCanBeSidechainTarget(effect))) - { - var c = new PatchSlot(); - c.group = p.group; - c.x = r.xMax - (r.yMax - r.yMin) * 0.5f; - c.y = (r.yMin + r.yMax) * 0.5f; - patchslots[effect] = c; - } - - // Bypass button - const float bypassWidth = 10.0f; - bool isBypassable = !effect.DisallowsBypass(); - Rect bypassRect = r; bypassRect.width = bypassWidth; - r.xMin += bypassWidth; - if (isBypassable) - { - // Handle mouse input is first, rendering is further down (to render on top). - if (GUI.Button(bypassRect, bypassButtonContent, GUIStyle.none)) - { - Undo.RecordObject(effect, "Bypass Effect"); - effect.bypass = !effect.bypass; - m_Controller.UpdateBypass(); - InspectorWindow.RepaintAllInspectors(); - } - } - - // Effect - m_IndexCounter++; - - // Repaint - // We are using the following GUIStyle backgrounds for: - // Normal: Disabled by bypass or group bypass - // Hover: Enabled, not draggable - // Active: Enabled, background for draggable bar - // Focused: Enabled, foreground for draggable bar - - float level = (effect != null) ? Mathf.Clamp(effect.GetValueForMixLevel(m_Controller, snapshot), AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect) : AudioMixerController.kMinVolume; - bool showLevel = (effect != null) && ((effect.IsSend() && effect.sendTarget != null) || effect.enableWetMix); - if (evt.type == EventType.Repaint) - { - GUIStyle style = GetEffectBarStyle(effect); - - float drawLevel = (showLevel) ? ((level - AudioMixerController.kMinVolume) / (AudioMixerController.kMaxEffect - AudioMixerController.kMinVolume)) : 1.0f; - bool enabled = (!p.group.bypassEffects && (effect == null || !effect.bypass)) || (effect != null && effect.DisallowsBypass()); - Color col1 = (effect != null) ? AudioMixerDrawUtils.GetEffectColor(effect) : new Color(0.0f, 0.0f, 0.0f, 0.5f); - if (!enabled) - col1 = new Color(col1.r * 0.5f, col1.g * 0.5f, col1.b * 0.5f); - - if (enabled) - { - if (drawLevel < 1.0f) - { - // Bar forground (we need special for small widths because style rendering with borders have a min width to work) - float forgroundWidth = r.width * drawLevel; - const float minimumWidthForBorderSetup = 4f; - if (forgroundWidth < minimumWidthForBorderSetup) - { - // Forground less than minimumWidthForBorderSetup (Always show marker to indicate the slot is draggable) - const float markerWidth = 2f; - forgroundWidth = Mathf.Max(forgroundWidth, markerWidth); - float frac = 1f - forgroundWidth / minimumWidthForBorderSetup; - - Color orgColor = GUI.color; - if (!GUI.enabled) - GUI.color = new Color(1, 1, 1, 0.5f); - GUI.DrawTextureWithTexCoords(new Rect(r.x, r.y, forgroundWidth, r.height), style.focused.background, new Rect(frac, 0f, 1f - frac, 1f)); - GUI.color = orgColor; - } - else - { - // Forground larger than minimumWidthForBorderSetup (uses border setup) - style.Draw(new Rect(r.x, r.y, forgroundWidth, r.height), false, false, false, true); - } - - // Bar background - GUI.DrawTexture(new Rect(r.x + forgroundWidth, r.y, r.width - forgroundWidth, r.height), style.onFocused.background, ScaleMode.StretchToFill); - } - else - { - //GUI.DrawTexture(r, showLevel ? style.focused.background : style.hover.background, ScaleMode.StretchToFill); - style.Draw(r, !showLevel, false, false, showLevel); - } - - // Cursor icon needs to proper work with dragging: TODO use hotcontrol - //if (showLevel) - // EditorGUIUtility.AddCursorRect(r, MouseCursor.SlideArrow); - } - else - { - // Disabled - style.Draw(r, false, false, false, false); - } - - // Bypass toggle - if (isBypassable) - styles.circularToggle.Draw(new Rect(bypassRect.x + 2, bypassRect.y + 5f, bypassRect.width - 2, bypassRect.width - 2f), false, false, !effect.bypass, false); - - if (effect.IsSend() && effect.sendTarget != null) - { - bypassRect.y -= 1; - GUI.Label(bypassRect, styles.sendString, EditorStyles.miniLabel); - } - - using (new EditorGUI.DisabledScope(!enabled)) - { - string name = GetEffectSlotName(effect, showLevel, snapshot, p); - string tooltip = GetEffectSlotTooltip(effect, r, p); - GUI.Label(new Rect(r.x, r.y, r.width - bypassWidth, r.height), GUIContent.Temp(name, tooltip), styles.effectName); - } - } - else - { - EffectSlotDragging(effectRect, snapshot, effect, showLevel, level, effectIndex, ref highlightEffectIndex, p); - } - } - - string GetEffectSlotName(AudioMixerEffectController effect, bool showLevel, AudioMixerSnapshotController snapshot, ChannelStripParams p) - { - if (m_ChangingWetMixIndex == m_IndexCounter && showLevel) - { - return string.Format("{0:F1} dB", effect.GetValueForMixLevel(m_Controller, snapshot)); - } - - if (effect.IsSend() && effect.sendTarget != null) - { - return effect.GetSendTargetDisplayString(p.effectMap); - } - - return effect.effectName; - } - - string GetEffectSlotTooltip(AudioMixerEffectController effect, Rect effectRect, ChannelStripParams p) - { - // Only fetch a tooltip if the cursor is inside the rect - if (!effectRect.Contains(Event.current.mousePosition)) - return string.Empty; - - if (effect.IsSend()) - { - if (effect.sendTarget != null) - { - string sendTarget = effect.GetSendTargetDisplayString(p.effectMap); - return "Send to: " + sendTarget; // We add the tooltip here because we rarely - } - else - { - return styles.emptySendSlotGUIContent.tooltip; - } - } - if (effect.IsReceive()) - { - return styles.returnSlotGUIContent.tooltip; - } - if (effect.IsDuckVolume()) - { - return styles.duckVolumeSlotGUIContent.tooltip; - } - if (effect.IsAttenuation()) - { - return styles.attenuationSlotGUIContent.tooltip; - } - - // Tooltip for all other effects - return styles.effectSlotGUIContent.tooltip; - } - - private void EffectSlotDragging(Rect r, AudioMixerSnapshotController snapshot, AudioMixerEffectController effect, bool showLevel, float level, int effectIndex, ref int highlightEffectIndex, ChannelStripParams p) - { - Event evt = Event.current; - - switch (evt.GetTypeForControl(m_EffectInteractionControlID)) - { - case EventType.MouseDown: - if (r.Contains(evt.mousePosition) && evt.button == 0 && GUIUtility.hotControl == 0) - { - GUIUtility.hotControl = m_EffectInteractionControlID; - m_MouseDragStartX = evt.mousePosition.x; - m_MouseDragStartValue = level; - highlightEffectIndex = effectIndex; - m_MovingEffectSrcIndex = -1; - m_MovingEffectDstIndex = -1; - m_WaitingForDragEvent = true; - m_MovingSrcRect = r; - m_MovingDstRect = r; - m_MovingSrcGroup = p.group; - m_MovingDstGroup = p.group; - m_MovingEffectAllowed = true; - SetFocus(); - Event.current.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - InspectorWindow.RepaintAllInspectors(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == m_EffectInteractionControlID && evt.button == 0 && p.stripRect.Contains(evt.mousePosition)) - { - if (m_MovingEffectDstIndex != -1 && m_MovingEffectAllowed) - { - if (IsDuplicateKeyPressed() && CanDuplicateDraggedEffect()) - { - // Duplicate effect - AudioMixerEffectController sourceEffect = m_MovingSrcGroup.effects[m_MovingEffectSrcIndex]; - AudioMixerEffectController copiedEffect = m_MovingSrcGroup.controller.CopyEffect(sourceEffect); - var targetEffects = m_MovingDstGroup.effects.ToList(); - if (AudioMixerController.InsertEffect(copiedEffect, ref targetEffects, m_MovingEffectDstIndex)) - { - m_MovingDstGroup.effects = targetEffects.ToArray(); - } - } - else - { - // Move effect - if (m_MovingSrcGroup == m_MovingDstGroup) - { - var effects = m_MovingSrcGroup.effects.ToList(); - if (AudioMixerController.MoveEffect(ref effects, m_MovingEffectSrcIndex, ref effects, m_MovingEffectDstIndex)) - { - m_MovingSrcGroup.effects = effects.ToArray(); - } - } - else if (!m_MovingSrcGroup.effects[m_MovingEffectSrcIndex].IsAttenuation()) - { - var sourceEffects = m_MovingSrcGroup.effects.ToList(); - var targetEffects = m_MovingDstGroup.effects.ToList(); - if (AudioMixerController.MoveEffect(ref sourceEffects, m_MovingEffectSrcIndex, ref targetEffects, m_MovingEffectDstIndex)) - { - m_MovingSrcGroup.effects = sourceEffects.ToArray(); - m_MovingDstGroup.effects = targetEffects.ToArray(); - } - } - } - } - - ClearEffectDragging(ref highlightEffectIndex); - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - GUIUtility.ExitGUI(); // We changed order of effects so stop iterating effects - } - break; - - case EventType.MouseDrag: - - if (GUIUtility.hotControl == m_EffectInteractionControlID) - { - // Detect direction of drag to decide if we want to adjust value or move effect - if (HasFocus() && m_WaitingForDragEvent) - { - m_ChangingWetMixIndex = -1; - if (effectIndex < p.group.effects.Length) - { - if (Mathf.Abs(evt.delta.y) > Mathf.Abs(evt.delta.x)) - { - // Move effect - m_MovingEffectSrcIndex = effectIndex; - ClearFocus(); - } - else - { - // Change wet mix value - m_ChangingWetMixIndex = m_IndexCounter; - } - } - m_WaitingForDragEvent = false; - } - - // Moving effect so detect effect insertion on this strip - if (IsMovingEffect() && p.stripRect.Contains(evt.mousePosition)) - { - float h2 = r.height * 0.5f; - float min = effectIndex == 0 ? -h2 : 0; - float max = effectIndex == p.group.effects.Length - 1 ? r.height + h2 : r.height; - float dy = evt.mousePosition.y - r.y; - if (dy >= min && dy <= max && effectIndex < p.group.effects.Length) - { - int newMovingEffectDstIndex = (dy < h2) ? effectIndex : (effectIndex + 1); - if (newMovingEffectDstIndex != m_MovingEffectDstIndex || m_MovingDstGroup != p.group) - { - m_MovingDstRect.x = r.x; - m_MovingDstRect.width = r.width; - m_MovingDstRect.y = ((dy < h2) ? r.y : (r.y + r.height)) - 1; - m_MovingEffectDstIndex = newMovingEffectDstIndex; - m_MovingDstGroup = p.group; - m_MovingEffectAllowed = - !(m_MovingSrcGroup.effects[m_MovingEffectSrcIndex].IsAttenuation() && m_MovingSrcGroup != m_MovingDstGroup) && - !AudioMixerController.WillMovingEffectCauseFeedback(p.allGroups, m_MovingSrcGroup, m_MovingEffectSrcIndex, m_MovingDstGroup, newMovingEffectDstIndex, null) && - (!IsDuplicateKeyPressed() || CanDuplicateDraggedEffect()); - } - 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 - } - } - - // Changing wetmix level - if (IsAdjustingWetMix() && HasFocus()) - { - if (showLevel) - { - m_WaitingForDragEvent = false; - - float tmp = kEffectScaleMouseDrag * HandleUtility.niceMouseDelta + level; - float deltaLevel = Mathf.Clamp(tmp, AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect) - level; - if (deltaLevel != 0.0f) - { - Undo.RecordObject(m_Controller.TargetSnapshot, "Change effect level"); - if (effect.IsSend() && m_Controller.CachedSelection.Count > 1 && m_Controller.CachedSelection.Contains(p.group)) - { - List changeEffects = new List(); - foreach (var g in m_Controller.CachedSelection) - foreach (var e in g.effects) - if (e.effectName == effect.effectName && e.sendTarget == effect.sendTarget) - changeEffects.Add(e); - foreach (var e in changeEffects) - if (!e.IsSend() || e.sendTarget != null) - e.SetValueForMixLevel( - m_Controller, - snapshot, - Mathf.Clamp(e.GetValueForMixLevel(m_Controller, snapshot) + deltaLevel, AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect)); - } - else - { - if (!effect.IsSend() || effect.sendTarget != null) - effect.SetValueForMixLevel( - m_Controller, - snapshot, - Mathf.Clamp(level + deltaLevel, AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect)); - } - InspectorWindow.RepaintAllInspectors(); - } - evt.Use(); - } - } - } - break; - } - } - - void ClearEffectDragging(ref int highlightEffectIndex) - { - if (GUIUtility.hotControl == m_EffectInteractionControlID) - GUIUtility.hotControl = 0; - m_MovingEffectSrcIndex = -1; - m_MovingEffectDstIndex = -1; - m_MovingSrcRect = new Rect(-1, -1, 0, 0); - m_MovingDstRect = new Rect(-1, -1, 0, 0); - m_MovingSrcGroup = null; - m_MovingDstGroup = null; - m_ChangingWetMixIndex = -1; - highlightEffectIndex = -1; - ClearFocus(); - InspectorWindow.RepaintAllInspectors(); - } - - void UnhandledEffectDraggingEvents(ref int highlightEffectIndex) - { - Event evt = Event.current; - - switch (evt.GetTypeForControl(m_EffectInteractionControlID)) - { - case EventType.MouseUp: - if (GUIUtility.hotControl == m_EffectInteractionControlID && evt.button == 0) - { - ClearEffectDragging(ref highlightEffectIndex); - evt.Use(); - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == m_EffectInteractionControlID) - { - // Clear dst group when dragging outside the strips - m_MovingEffectDstIndex = -1; - m_MovingDstRect = new Rect(-1, -1, 0, 0); - m_MovingDstGroup = null; - evt.Use(); - } - break; - case EventType.Repaint: - - if (IsMovingEffect()) - { - // Mark the effect being dragged - if (evt.type == EventType.Repaint) - { - EditorGUI.DrawRect(m_MovingSrcRect, kMoveColorHighlight); - - // Set + cursor when duplicating dragged effect - var cursor = (IsDuplicateKeyPressed() && m_MovingEffectAllowed) ? MouseCursor.ArrowPlus : MouseCursor.ResizeVertical; - EditorGUIUtility.AddCursorRect(new Rect(evt.mousePosition.x - 10, evt.mousePosition.y - 10, 20, 20), cursor, m_EffectInteractionControlID); - } - } - - if (m_MovingEffectDstIndex != -1 && m_MovingDstRect.y >= 0.0f)// && m_MovingEffectDstIndex != m_MovingEffectSrcIndex && m_MovingEffectDstIndex != m_MovingEffectSrcIndex +1) - { - float kMoveRange = 2; - Color moveSlotColLo = (m_MovingEffectAllowed) ? kMoveSlotColLoAllowed : kMoveSlotColLoDisallowed; - Color moveSlotColHi = (m_MovingEffectAllowed) ? kMoveSlotColHiAllowed : kMoveSlotColHiDisallowed; - Color moveSlotColBorder = (m_MovingEffectAllowed) ? kMoveSlotColBorderAllowed : kMoveSlotColBorderDisallowed; - AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingDstRect.x, m_MovingDstRect.y - kMoveRange, m_MovingDstRect.width, kMoveRange), moveSlotColLo, moveSlotColHi); - AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingDstRect.x, m_MovingDstRect.y, m_MovingDstRect.width, kMoveRange), moveSlotColHi, moveSlotColLo); - AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingDstRect.x, m_MovingDstRect.y - 1, m_MovingDstRect.width, 1), moveSlotColBorder, moveSlotColBorder); - } - - break; - } - } - - bool IsDuplicateKeyPressed() - { - return Event.current.alt; - } - - bool CanDuplicateDraggedEffect() - { - if (IsMovingEffect() && m_MovingSrcGroup != null) - return !m_MovingSrcGroup.effects[m_MovingEffectSrcIndex].IsAttenuation(); - return false; - } - - private class BusConnection - { - public BusConnection(float srcX, float srcY, AudioMixerEffectController targetEffect, float mixLevel, Color col, bool isSend, bool isSelected) - { - this.srcX = srcX; - this.srcY = srcY; - this.targetEffect = targetEffect; - this.mixLevel = mixLevel; - this.color = col; - this.isSend = isSend; - this.isSelected = isSelected; - } - - public AudioMixerEffectController targetEffect; - public float srcX; - public float srcY; - public float mixLevel; - public Color color; - public bool isSend; - public bool isSelected; - } - - private bool DoSoloButton(Rect r, AudioMixerGroupController group, List allGroups, List selection) - { - Event evt = Event.current; - - // Right click toggle - if (evt.type == EventType.MouseUp && evt.button == 1 && r.Contains(evt.mousePosition) && allGroups.Any(g => g.solo)) - { - Undo.RecordObject(group, "Change solo state"); - foreach (var g in allGroups) - g.solo = false; - evt.Use(); - return true; - } - - bool newState = GUI.Toggle(r, group.solo, styles.soloGUIContent, AudioMixerDrawUtils.styles.soloToggle); - if (newState != group.solo) - { - Undo.RecordObject(group, "Change solo state"); - group.solo = !group.solo; - foreach (var g in selection) - g.solo = group.solo; - return true; - } - - - return false; - } - - private bool DoMuteButton(Rect r, AudioMixerGroupController group, List allGroups, bool anySoloActive, List selection) - { - Event evt = Event.current; - // Right click toggle - if (evt.type == EventType.MouseUp && evt.button == 1 && r.Contains(evt.mousePosition) && allGroups.Any(g => g.mute)) - { - Undo.RecordObject(group, "Change mute state"); - if (allGroups.Any(g => g.solo)) - return false; - foreach (var g in allGroups) - g.mute = false; - evt.Use(); - return true; - } - Color orgColor = GUI.color; - bool dimColor = anySoloActive && group.mute; - if (dimColor) - GUI.color = new Color(GUI.color.r, GUI.color.g, GUI.color.b, 0.5f); - bool newState = GUI.Toggle(r, group.mute, styles.muteGUIContent, AudioMixerDrawUtils.styles.muteToggle); - if (dimColor) - GUI.color = orgColor; - - if (newState != group.mute) - { - Undo.RecordObject(group, "Change mute state"); - group.mute = !group.mute; - foreach (var g in selection) - g.mute = group.mute; - return true; - } - - return false; - } - - private bool DoBypassEffectsButton(Rect r, AudioMixerGroupController group, List allGroups, List selection) - { - Event evt = Event.current; - // Right click toggle - if (evt.type == EventType.MouseUp && evt.button == 1 && r.Contains(evt.mousePosition) && allGroups.Any(g => g.bypassEffects)) - { - Undo.RecordObject(group, "Change bypass effects state"); - foreach (var g in allGroups) - g.bypassEffects = false; - evt.Use(); - return true; - } - - bool newState = GUI.Toggle(r, group.bypassEffects, styles.bypassGUIContent, AudioMixerDrawUtils.styles.bypassToggle); - if (newState != group.bypassEffects) - { - Undo.RecordObject(group, "Change bypass effects state"); - group.bypassEffects = !group.bypassEffects; - foreach (var g in selection) - g.bypassEffects = group.bypassEffects; - return true; - } - - return false; - } - - private static bool RectOverlaps(Rect r1, Rect r2) - { - Rect overlap = new Rect(); - overlap.x = Mathf.Max(r1.x, r2.x); - overlap.y = Mathf.Max(r1.y, r2.y); - overlap.width = Mathf.Min(r1.x + r1.width, r2.x + r2.width) - overlap.x; - overlap.height = Mathf.Min(r1.y + r1.height, r2.y + r2.height) - overlap.y; - return overlap.width > 0.0f && overlap.height > 0.0f; - } - - bool IsRectSelectionActive() - { - return GUIUtility.hotControl == m_RectSelectionControlID; - } - - // Handles multiselection (using shift + ctrl/cmd) - void GroupClicked(AudioMixerGroupController clickedGroup, ChannelStripParams p, bool clickedControlInGroup) - { - // Get ids from items - List allIDs = new List(); - foreach (var group in p.shownGroups) - allIDs.Add(group.GetInstanceID()); - - List selectedIDs = new List(); - foreach (var group in m_Controller.CachedSelection) - selectedIDs.Add(group.GetInstanceID()); - - int lastClickedID = m_State.m_LastClickedInstanceID; - bool allowMultiselection = true; - bool keepMultiSelection = Event.current.shift || clickedControlInGroup; - bool useShiftAsActionKey = false; - - List newSelection = InternalEditorUtility.GetNewSelection(clickedGroup.GetInstanceID(), allIDs, selectedIDs, lastClickedID, keepMultiSelection, useShiftAsActionKey, allowMultiselection); - List groups = (from x in p.allGroups where newSelection.Contains(x.GetInstanceID()) select x).ToList(); - - Selection.objects = groups.ToArray(); - m_Controller.OnUnitySelectionChanged(); - - InspectorWindow.RepaintAllInspectors(); - } - - private void DoAttenuationFader(Rect r, AudioMixerGroupController group, List selection, GUIStyle style) - { - float volume = Mathf.Clamp(group.GetValueForVolume(m_Controller, m_Controller.TargetSnapshot), AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()); - float newVolume = VerticalFader(r, volume, 1, kVolumeScaleMouseDrag, true, true, styles.attenuationFader.tooltip, AudioMixerController.GetMaxVolume(), style); - if (volume != newVolume) - { - float deltaVolume = newVolume - volume; - Undo.RecordObject(m_Controller.TargetSnapshot, "Change volume fader"); - foreach (var g in selection) - { - float vol = Mathf.Clamp(g.GetValueForVolume(m_Controller, m_Controller.TargetSnapshot), AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()); - g.SetValueForVolume( - m_Controller, - m_Controller.TargetSnapshot, - Mathf.Clamp(vol + deltaVolume, AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume())); - } - InspectorWindow.RepaintAllInspectors(); - } - } - - static internal void AddEffectItemsToMenu(AudioMixerController controller, AudioMixerGroupController[] groups, int insertIndex, string prefix, GenericMenu pm) - { - string[] effectNames = MixerEffectDefinitions.GetEffectList(); - for (int t = 0; t < effectNames.Length; t++) - { - if (effectNames[t] != "Attenuation") - pm.AddItem(new GUIContent(prefix + AudioMixerController.FixNameForPopupMenu(effectNames[t])), - false, - InsertEffectPopupCallback, - new EffectContext(controller, groups, insertIndex, effectNames[t])); - } - } - - private void DoEffectSlotInsertEffectPopup(Rect buttonRect, AudioMixerGroupController group, List allGroups, - int effectSlotIndex, ref Dictionary effectMap) - { - GenericMenu pm = new GenericMenu(); - - AudioMixerGroupController[] groups = new AudioMixerGroupController[] { group }; - - if (effectSlotIndex < group.effects.Length) - { - var effect = group.effects[effectSlotIndex]; - if (!effect.IsAttenuation() && !effect.IsSend() && !effect.IsReceive() && !effect.IsDuckVolume()) - { - pm.AddItem(EditorGUIUtility.TrTextContent("Allow Wet Mixing (causes higher memory usage)"), effect.enableWetMix, delegate { effect.enableWetMix = !effect.enableWetMix; }); - pm.AddItem(EditorGUIUtility.TrTextContent("Bypass"), effect.bypass, delegate { effect.bypass = !effect.bypass; m_Controller.UpdateBypass(); InspectorWindow.RepaintAllInspectors(); }); - pm.AddSeparator(""); - } - - AddEffectItemsToMenu(group.controller, groups, effectSlotIndex, "Add effect before/", pm); - AddEffectItemsToMenu(group.controller, groups, effectSlotIndex + 1, "Add effect after/", pm); - } - else - { - // Add effect at the end of the list - AddEffectItemsToMenu(group.controller, groups, effectSlotIndex, "", pm); - } - - if (effectSlotIndex < group.effects.Length) - { - var effect = group.effects[effectSlotIndex]; - if (!effect.IsAttenuation()) - { - pm.AddSeparator(""); - pm.AddItem(EditorGUIUtility.TrTextContent("Remove"), false, RemoveEffectPopupCallback, new EffectContext(m_Controller, groups, effectSlotIndex, "")); - bool insertedSeparator = false; - if (effect.IsSend()) - { - if (effect.sendTarget != null) - { - if (!insertedSeparator) - { - insertedSeparator = true; - pm.AddSeparator(""); - } - pm.AddItem(EditorGUIUtility.TrTextContent("Disconnect from '" + effect.GetSendTargetDisplayString(effectMap) + "'") , false, ConnectSendPopupCallback, new ConnectSendContext(effect, null)); - } - - if (!insertedSeparator) - AddSeperatorIfAnyReturns(pm, allGroups); - AddMenuItemsForReturns(pm, "Connect to ", effectSlotIndex, group, allGroups, effectMap, effect, false); - } - } - } - pm.DropDown(buttonRect); - Event.current.Use(); - } - - void AddSeperatorIfAnyReturns(GenericMenu pm, List allGroups) - { - foreach (var g in allGroups) - { - foreach (var ge in g.effects) - { - if (ge.IsReceive() || ge.IsDuckVolume()) - { - pm.AddSeparator(""); - return; - } - } - } - } - - public static void AddMenuItemsForReturns(GenericMenu pm, string prefix, int effectIndex, AudioMixerGroupController group, List allGroups, - Dictionary effectMap, AudioMixerEffectController effect, bool showCurrent) - { - foreach (var g in allGroups) - { - foreach (var ge in g.effects) - { - if (MixerEffectDefinitions.EffectCanBeSidechainTarget(ge)) - { - var identifiedLoop = new List(); - - //TODO: In the future, consider allowing feedback loops, as the send code now allows for this, though give a warning to the user - // that they may be doing something stupid - if (!AudioMixerController.WillChangeOfEffectTargetCauseFeedback(allGroups, group, effectIndex, ge, identifiedLoop)) - { - if (showCurrent || effect.sendTarget != ge) - pm.AddItem(new GUIContent(prefix + "'" + ge.GetDisplayString(effectMap) + "'"), effect.sendTarget == ge, ConnectSendPopupCallback, new ConnectSendContext(effect, ge)); - } - else - { - string baseString = "A connection to '" + AudioMixerController.FixNameForPopupMenu(ge.GetDisplayString(effectMap)) + "' would result in a feedback loop/"; - pm.AddDisabledItem(new GUIContent(baseString + "Loop: ")); - int loopIndex = 1; - foreach (var s in identifiedLoop) - { - pm.AddDisabledItem(new GUIContent(baseString + loopIndex + ": " + s.GetDisplayString() + "->")); - loopIndex++; - } - pm.AddDisabledItem(new GUIContent(baseString + loopIndex + ": ...")); - } - } - } - } - } - - public void VUMeter(AudioMixerGroupController group, Rect r, float level, float peak) - { - EditorGUI.VUMeter.VerticalMeter(r, level, peak, EditorGUI.VUMeter.verticalVUTexture, Color.grey); - } - - private GUIContent headerGUIContent = new GUIContent(); - - class ChannelStripParams - { - public int index; - public Rect stripRect; - public Rect visibleRect; - public bool visible; - public AudioMixerGroupController group; - public int maxEffects; - public bool drawingBuses; - public bool anySoloActive; - public List busConnections = new List(); - public List rectSelectionGroups = new List(); - public List allGroups; - public List shownGroups; - - public int numChannels = 0; - public float[] vuinfo_level = new float[9]; - public float[] vuinfo_peak = new float[9]; - - //public int highlightEffectIndex; - public Dictionary effectMap; - - const float kAddEffectButtonHeight = 16f; - - public List bgRects; - public readonly int kHeaderIndex = 0; - public readonly int kVUMeterFaderIndex = 1; - public readonly int kTotalVULevelIndex = 2; - public readonly int kSoloMuteBypassIndex = 3; - public readonly int kEffectStartIndex = 4; - - public void Init(AudioMixerController controller, Rect channelStripRect, int maxNumEffects) - { - numChannels = controller.GetGroupVUInfo(group.groupID, false, ref vuinfo_level, ref vuinfo_peak); - //numChannels = 8; // debugging - - maxEffects = maxNumEffects; - bgRects = GetBackgroundRects(channelStripRect, group, maxEffects); - stripRect = channelStripRect; - - - stripRect.yMax = bgRects[bgRects.Count - 1].yMax; // Ensure full height - } - - List GetBackgroundRects(Rect r, AudioMixerGroupController group, int maxNumGroups) - { - List heights = new List(); - heights.AddRange(Enumerable.Repeat(0f, kEffectStartIndex)); - heights[kHeaderIndex] = headerHeight; - heights[kVUMeterFaderIndex] = vuHeight; - heights[kTotalVULevelIndex] = dbHeight; - heights[kSoloMuteBypassIndex] = soloMuteBypassHeight; - int maxNumEffectSlots = maxNumGroups; // maxNumGroups includes an empty slot used as button for adding new effect - for (int i = 0; i < maxNumEffectSlots; ++i) - heights.Add(effectHeight); - heights.Add(10f); - - List rects = new List(); - float curY = r.y; - foreach (int height in heights) - { - if (rects.Count > 0) - curY += spaceBetween; - - rects.Add(new Rect(r.x, curY, r.width, height)); - curY += height; - } - - curY += 10f; // space between last effect and add button - - rects.Add(new Rect(r.x, curY, r.width, kAddEffectButtonHeight)); - - return rects; - } - } - - void DrawBackgrounds(ChannelStripParams p, bool selected) - { - if (Event.current.type == EventType.Repaint) - { - // Bg - styles.channelStripBg.Draw(p.stripRect, false, false, selected, false); - - // Line over effects (todo: move to texture) - float lightColor = 119f / 255f; - float darkColor = 58f / 255f; - Color lineColor = EditorGUIUtility.isProSkin ? new Color(darkColor, darkColor, darkColor) : new Color(lightColor, lightColor, lightColor); - Rect lineRect = p.bgRects[p.kEffectStartIndex]; - lineRect.y -= 1; - lineRect.height = 1; - EditorGUI.DrawRect(lineRect, lineColor); - - // Optimize by rendering vu numbers and lines in one texture - //Rect vuNumbersRect = p.bgRects[1]; - //vuNumbersRect.x = p.stripRect.xMax - 90f; - //vuNumbersRect.x = vuNumbersRect.xMax - AudioMixerDrawUtils.styles.channelStripVUMeterBg.normal.background.width; // right align - //AudioMixerDrawUtils.styles.channelStripVUMeterBg.Draw(vuNumbersRect, false, false, false, false); // 0 -80 dB numbers overlay - } - - // User color - Rect colorRect = p.bgRects[p.kVUMeterFaderIndex]; - colorRect.height = EditorGUIUtility.isProSkin ? 1 : 2; - colorRect.y -= colorRect.height; - - int colorIndex = p.group.userColorIndex; - if (colorIndex != 0) - EditorGUI.DrawRect(colorRect, AudioMixerColorCodes.GetColor(colorIndex)); - } - - void OpenGroupContextMenu(AudioMixerGroupController[] groups) - { - GenericMenu pm = new GenericMenu(); - - AddEffectItemsToMenu(groups[0].controller, groups, 0, "Add effect at top/", pm); - AddEffectItemsToMenu(groups[0].controller, groups, -1, "Add effect at bottom/", pm); - - pm.AddSeparator(string.Empty); - AudioMixerColorCodes.AddColorItemsToGenericMenu(pm, groups); - pm.AddSeparator(string.Empty); - - pm.ShowAsContext(); - } - - private void DrawChannelStrip(ChannelStripParams p, ref int highlightEffectIndex, ref Dictionary patchslots, bool showBusConnectionsOfSelection) - { - Event evt = Event.current; - - bool mouseDownInsideStrip = evt.type == EventType.MouseDown && p.stripRect.Contains(evt.mousePosition); - - // Selection rendering state - bool selected = m_Controller.CachedSelection.Contains(p.group); - if (IsRectSelectionActive()) - { - if (RectOverlaps(p.stripRect, m_RectSelectionRect)) - { - p.rectSelectionGroups.Add(p.group); - selected = true; - } - } - - // Draw all background rects - DrawBackgrounds(p, selected); - - // Header area - headerGUIContent.text = headerGUIContent.tooltip = p.group.GetDisplayString(); - GUI.Label(p.bgRects[p.kHeaderIndex], headerGUIContent, AudioMixerDrawUtils.styles.channelStripHeaderStyle); - - // VU Meter and attenuation area - Rect innerRect = new RectOffset(-6, 0, 0, -4).Add(p.bgRects[p.kVUMeterFaderIndex]); - - float spaceBetweenColumns = 1f; - float column1Width = 54f; - float column2Width = innerRect.width - column1Width - spaceBetweenColumns; - Rect column1Rect = new Rect(innerRect.x, innerRect.y, column1Width, innerRect.height); - Rect column2Rect = new Rect(column1Rect.xMax + spaceBetweenColumns, innerRect.y, column2Width, innerRect.height); - - float faderWidth = 29f; - Rect faderRect = new Rect(column2Rect.x, column2Rect.y, faderWidth, column2Rect.height); - Rect tripleButtonRect = p.bgRects[p.kSoloMuteBypassIndex]; - GUIStyle attenuationMarkerStyle = AudioMixerDrawUtils.styles.channelStripAttenuationMarkerSquare; - using (new EditorGUI.DisabledScope(!AudioMixerController.EditingTargetSnapshot())) - { - DoVUMeters(column1Rect, attenuationMarkerStyle.fixedHeight, p); - DoAttenuationFader(faderRect, p.group, m_Controller.CachedSelection, attenuationMarkerStyle); - DoTotaldB(p); - DoEffectList(p, selected, ref highlightEffectIndex, ref patchslots, showBusConnectionsOfSelection); - } - - // We want to be able to set mute, solo and bypass even when EditingTargetSnapshot is false for testing during gameplay - DoSoloMuteBypassButtons(tripleButtonRect, p.group, p.allGroups, m_Controller.CachedSelection, p.anySoloActive); - - // Handle group click after all controls so we can detect if a control was clicked by checking if the event was used here - if (mouseDownInsideStrip && evt.button == 0) - GroupClicked(p.group, p, evt.type == EventType.Used); - - // Check context click after all UI controls (only show if we did not interact with any controls) - if (evt.type == EventType.ContextClick && p.stripRect.Contains(evt.mousePosition)) - { - evt.Use(); - - //If its part of an existing selection, then pass all, otherwise pretend its a new selection - if (selected) - OpenGroupContextMenu(m_Controller.CachedSelection.ToArray()); - else - OpenGroupContextMenu(new AudioMixerGroupController[] { p.group }); - } - } - - void DoTotaldB(ChannelStripParams p) - { - // Right align db but shown centered (prevents 'db' from jumping around) - float textWidth = 50f; - styles.totalVULevel.padding.right = (int)((p.stripRect.width - textWidth) * 0.5f); - float vu_level = Mathf.Max(p.vuinfo_level[8], k_MinVULevel); - Rect rect = p.bgRects[p.kTotalVULevelIndex]; - GUI.Label(rect, string.Format("{0:F1} dB", vu_level), styles.totalVULevel); - } - - GUIContent addText = EditorGUIUtility.TrTextContent("Add.."); - void DoEffectList(ChannelStripParams p, bool selected, ref int highlightEffectIndex, ref Dictionary patchslots, bool showBusConnectionsOfSelection) - { - Event evt = Event.current; - for (int i = 0; i < p.maxEffects; i++) - { - Rect effectRect = p.bgRects[p.kEffectStartIndex + i]; - if (i < p.group.effects.Length) - { - AudioMixerEffectController effect = p.group.effects[i]; - if (p.visible) - { - // Use right click event first - if (evt.type == EventType.ContextClick && effectRect.Contains(Event.current.mousePosition)) - { - ClearFocus(); - DoEffectSlotInsertEffectPopup(effectRect, p.group, p.allGroups, i, ref p.effectMap); - evt.Use(); - } - - // Then do effect button - EffectSlot(effectRect, m_Controller.TargetSnapshot, effect, i, ref highlightEffectIndex, p, ref patchslots); - } - } - } - - // Empty slot below effects - if (p.visible) - { - Rect effectRect = p.bgRects[p.bgRects.Count - 1]; - if (evt.type == EventType.Repaint) - { - 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)); - GUI.Label(effectRect, addText, styles.effectName); - } - if (evt.type == EventType.MouseDown && effectRect.Contains(Event.current.mousePosition)) - { - ClearFocus(); - int insertEffectAtIndex = p.group.effects.Length; - DoEffectSlotInsertEffectPopup(effectRect, p.group, p.allGroups, insertEffectAtIndex, ref p.effectMap); - evt.Use(); - } - } - } - - float DoVUMeters(Rect vuRect, float attenuationMarkerHeight, ChannelStripParams p) - { - float spaceBetweenMeters = 1f; - - // When the audiomixer has been rebuild we might have some frames where numChannels is not initialized. - // To prevent flickering we use last valid num channels used at current index - int numChannels = p.numChannels; - if (numChannels == 0) - { - if (p.index >= 0 && p.index < m_LastNumChannels.Count) - numChannels = m_LastNumChannels[p.index]; - } - else - { - // Cache valid numChannels for current index - while (p.index >= m_LastNumChannels.Count) - m_LastNumChannels.Add(0); - m_LastNumChannels[p.index] = numChannels; - } - - // Adjust rect based on how many channels we have - if (numChannels <= 2) - { - const float twoChannelWidth = 25f; - vuRect.x = vuRect.xMax - twoChannelWidth; // right align - vuRect.width = twoChannelWidth; - } - - // This can happen when simulating player builds, i.e. not calculating VU-info for most of the channels. - if (numChannels == 0) - return vuRect.x; - - float vuOffsetY = Mathf.Floor(attenuationMarkerHeight / 2); - vuRect.y += vuOffsetY; - vuRect.height -= 2 * vuOffsetY; - float vuWidth = Mathf.Round((vuRect.width - numChannels * spaceBetweenMeters) / numChannels); - Rect vuSubRect = new Rect(vuRect.xMax - vuWidth, vuRect.y, vuWidth, vuRect.height); - // Draw from right to left to ensure perfect right side pixel position (we are rounding widths above) - for (int i = numChannels - 1; i >= 0; i--) - { - if (i != numChannels - 1) - vuSubRect.x -= vuSubRect.width + spaceBetweenMeters; - - float warpedLevel = 1f - AudioMixerController.VolumeToScreenMapping(Mathf.Clamp(p.vuinfo_level[i], AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()), 1f, true); - float warpedPeak = 1f - AudioMixerController.VolumeToScreenMapping(Mathf.Clamp(p.vuinfo_peak[i], AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()), 1f, true); - VUMeter(p.group, vuSubRect, warpedLevel, warpedPeak); - } - AudioMixerDrawUtils.AddTooltipOverlay(vuRect, styles.vuMeterGUIContent.tooltip); - - return vuSubRect.x; - } - - void DoSoloMuteBypassButtons(Rect rect, AudioMixerGroupController group, List allGroups, List selection, bool anySoloActive) - { - float buttonSize = 21f; - float spaceBetween = 2f; - float startX = rect.x + (rect.width - (buttonSize * 3 + spaceBetween * 2)) * 0.5f; - Rect buttonRect = new Rect(startX, rect.y, buttonSize, buttonSize); - bool needMixerUpdate = false; - needMixerUpdate |= DoSoloButton(buttonRect, group, allGroups, selection); - buttonRect.x += buttonSize + spaceBetween; - needMixerUpdate |= DoMuteButton(buttonRect, group, allGroups, anySoloActive, selection); - if (needMixerUpdate) - m_Controller.UpdateMuteSolo(); - buttonRect.x += buttonSize + spaceBetween; - if (DoBypassEffectsButton(buttonRect, group, allGroups, selection)) - m_Controller.UpdateBypass(); - } - - public void OnMixerControllerChanged(AudioMixerController controller) - { - m_Controller = controller; - } - - [System.NonSerialized] - private int FrameCounter = 0; - - [System.NonSerialized] - private GUIStyle developerInfoStyle = AudioMixerDrawUtils.BuildGUIStyleForLabel(new Color(1.0f, 0.0f, 0.0f, 0.5f), 20, false, FontStyle.Bold, TextAnchor.MiddleLeft); - - public void ShowDeveloperOverlays(Rect rect, Event evt, bool show) - { - if (show && Unsupported.IsDeveloperMode() && evt.type == EventType.Repaint) - { - AudioMixerDrawUtils.ReadOnlyLabel(new Rect(rect.x + 5, rect.y + 5, rect.width - 10, 20), "Current snapshot: " + m_Controller.TargetSnapshot.name, developerInfoStyle); - AudioMixerDrawUtils.ReadOnlyLabel(new Rect(rect.x + 5, rect.y + 25, rect.width - 10, 20), "Frame count: " + FrameCounter++, developerInfoStyle); - } - } - - public static float Lerp(float x1, float x2, float t) - { - return x1 + (x2 - x1) * t; - } - - public static void GetCableVertex(float x1, float y1, float x2, float y2, float x3, float y3, float t, out float x, out float y) - { - x = Lerp(Lerp(x1, x2, t), Lerp(x2, x3, t), t); - y = Lerp(Lerp(y1, y2, t), Lerp(y2, y3, t), t); - } - - [System.NonSerialized] - private Vector3[] cablepoints = new Vector3[20]; - - public void OnGUI(Rect rect, bool showReferencedBuses, bool showBusConnections, bool showBusConnectionsOfSelection, List allGroups, Dictionary effectMap, bool sortGroupsAlphabetically, bool showDeveloperOverlays, AudioMixerGroupController scrollToItem) - { - if (m_Controller == null) - { - DrawAreaBackground(rect); - return; - } - - if (Event.current.type == EventType.Layout) - return; - - m_RectSelectionControlID = GUIUtility.GetControlID(kRectSelectionHashCode, FocusType.Passive); - m_EffectInteractionControlID = GUIUtility.GetControlID(kEffectDraggingHashCode, FocusType.Passive); - - m_IndexCounter = 0; - - Event evt = Event.current; - var sortedGroups = m_Controller.GetCurrentViewGroupList().ToList(); - if (sortGroupsAlphabetically) - sortedGroups.Sort(m_GroupComparer); - - Rect baseChannelStripRect = new Rect(channelStripsOffset.x, channelStripsOffset.y, channelStripBaseWidth, 300); - if (scrollToItem != null) - { - int index = sortedGroups.IndexOf(scrollToItem); - if (index >= 0) - { - float x = (baseChannelStripRect.width + channelStripSpacing) * index - m_State.m_ScrollPos.x; - if (x < -20 || x > rect.width) - m_State.m_ScrollPos.x += x; - } - } - - var unsortedBuses = new List(); - foreach (var c in sortedGroups) - { - foreach (var e in c.effects) - { - if (e.sendTarget != null) - { - var targetGroup = effectMap[e.sendTarget]; - if (!unsortedBuses.Contains(targetGroup) && !sortedGroups.Contains(targetGroup)) - unsortedBuses.Add(targetGroup); - } - } - } - List buses = unsortedBuses.ToList(); - buses.Sort(m_GroupComparer); - - // Show referenced buses after all sorted groups - int numMainGroups = sortedGroups.Count; - if (showReferencedBuses && buses.Count > 0) - sortedGroups.AddRange(buses); - - int maxEffects = 1; - foreach (var c in sortedGroups) - maxEffects = Mathf.Max(maxEffects, c.effects.Length); - - bool isShowingReferencedGroups = sortedGroups.Count != numMainGroups; - Rect contentRect = GetContentRect(sortedGroups, isShowingReferencedGroups, maxEffects); - m_State.m_ScrollPos = GUI.BeginScrollView(rect, m_State.m_ScrollPos, contentRect); - DrawAreaBackground(new Rect(0, 0, 10000, 10000)); - - // Setup shared AudioGroup data - var channelStripParams = new ChannelStripParams - { - effectMap = effectMap, - allGroups = allGroups, - shownGroups = sortedGroups, - anySoloActive = allGroups.Any(g => g.solo), - visibleRect = new Rect(m_State.m_ScrollPos.x, m_State.m_ScrollPos.y, rect.width, rect.height) - }; - - var patchslots = showBusConnections ? new Dictionary() : null; - for (int i = 0; i < sortedGroups.Count; ++i) - { - var group = sortedGroups[i]; - // Specific parameter data for current AudioGroup - channelStripParams.index = i; - channelStripParams.group = group; - channelStripParams.drawingBuses = false; - channelStripParams.visible = RectOverlaps(channelStripParams.visibleRect, baseChannelStripRect); - channelStripParams.Init(m_Controller, baseChannelStripRect, maxEffects); - - DrawChannelStrip(channelStripParams, ref m_Controller.m_HighlightEffectIndex, ref patchslots, showBusConnectionsOfSelection); - - // If we click inside the the strip rect we use the event to ensure the mousedown is not caught by rectangle selection - if (evt.type == EventType.MouseDown && evt.button == 0 && channelStripParams.stripRect.Contains(evt.mousePosition)) - evt.Use(); - // If we are dragging effects we reset destination index when dragging outside effects - if (IsMovingEffect() && evt.type == EventType.MouseDrag && channelStripParams.stripRect.Contains(evt.mousePosition) && GUIUtility.hotControl == m_EffectInteractionControlID) - { - m_MovingEffectDstIndex = -1; - evt.Use(); - } - baseChannelStripRect.x += channelStripParams.stripRect.width + channelStripSpacing; - - // Add extra space to referenced groups - if (showReferencedBuses && i == numMainGroups - 1 && sortedGroups.Count > numMainGroups) - { - baseChannelStripRect.x += 50f; - - using (new EditorGUI.DisabledScope(true)) - { - GUI.Label(new Rect(baseChannelStripRect.x, channelStripParams.stripRect.yMax, 130, 22), styles.referencedGroups, styles.channelStripHeaderStyle); - } - } - } - UnhandledEffectDraggingEvents(ref m_Controller.m_HighlightEffectIndex); - - if (evt.type == EventType.Repaint && patchslots != null) - { - foreach (var c in patchslots) - { - var slot = c.Value; - bool active = !showBusConnectionsOfSelection || m_Controller.CachedSelection.Contains(slot.group); - if (active) - styles.circularToggle.Draw(new Rect(slot.x - 3, slot.y - 3, 6, 6), false, false, active, false); - } - float moveamp = Mathf.Exp(-0.03f * Time.time * Time.time) * 0.1f; - var trCol1 = new Color(0.0f, 0.0f, 0.0f, AudioMixerController.EditingTargetSnapshot() ? 0.1f : 0.05f); - var trCol2 = new Color(0.0f, 0.0f, 0.0f, AudioMixerController.EditingTargetSnapshot() ? 1.0f : 0.5f); - foreach (var c in patchslots) - { - var sourceEffect = c.Key; - var targetEffect = sourceEffect.sendTarget; - if (targetEffect == null) - continue; - var sourceSlot = c.Value; - if (!patchslots.ContainsKey(targetEffect)) - continue; - var targetSlot = patchslots[targetEffect]; - int color = sourceEffect.GetInstanceID() ^ targetEffect.GetInstanceID(); - float phase = (color & 63) * 0.1f; - float mx1 = Mathf.Abs(targetSlot.x - sourceSlot.x) * Mathf.Sin(Time.time * 5.0f + phase) * moveamp + (sourceSlot.x + targetSlot.x) * 0.5f; - 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); - for (int i = 0; i < cablepoints.Length; i++) - GetCableVertex( - sourceSlot.x, sourceSlot.y, - mx1, my1, - targetSlot.x, targetSlot.y, - (float)i / (float)(cablepoints.Length - 1), - out cablepoints[i].x, out cablepoints[i].y); - bool skip = showBusConnectionsOfSelection && !m_Controller.CachedSelection.Contains(sourceSlot.group) && !m_Controller.CachedSelection.Contains(targetSlot.group); - Handles.color = skip ? trCol1 : trCol2; - Handles.DrawAAPolyLine(7.0f, cablepoints.Length, cablepoints); - if (skip) - continue; - color ^= (color >> 6) ^ (color >> 12) ^ (color >> 18); - Handles.color = - new Color( - (color & 3) * 0.15f + 0.55f, - ((color >> 2) & 3) * 0.15f + 0.55f, - ((color >> 4) & 3) * 0.15f + 0.55f, - AudioMixerController.EditingTargetSnapshot() ? 1.0f : 0.5f); - Handles.DrawAAPolyLine(4.0f, cablepoints.Length, cablepoints); - Handles.color = new Color(1.0f, 1.0f, 1.0f, AudioMixerController.EditingTargetSnapshot() ? 0.5f : 0.25f); - Handles.DrawAAPolyLine(3.0f, cablepoints.Length, cablepoints); - } - } - - RectSelection(channelStripParams); - - GUI.EndScrollView(true); - AudioMixerDrawUtils.DrawScrollDropShadow(rect, m_State.m_ScrollPos.y, contentRect.height); - WarningOverlay(allGroups, rect, contentRect); - ShowDeveloperOverlays(rect, evt, showDeveloperOverlays); - - if (!EditorApplication.isPlaying && !m_Controller.isSuspended) - m_RequiresRepaint = true; - } - - bool IsMovingEffect() - { - return m_MovingEffectSrcIndex != -1; - } - - bool IsAdjustingWetMix() - { - return m_ChangingWetMixIndex != -1; - } - - void RectSelection(ChannelStripParams channelStripParams) - { - Event evt = Event.current; - - if (evt.type == EventType.MouseDown && evt.button == 0 && GUIUtility.hotControl == 0) - { - if (!evt.shift) - { - Selection.objects = new UnityEngine.Object[0]; - m_Controller.OnUnitySelectionChanged(); - } - GUIUtility.hotControl = m_RectSelectionControlID; - - m_RectSelectionStartPos = evt.mousePosition; - m_RectSelectionRect = new Rect(m_RectSelectionStartPos.x, m_RectSelectionStartPos.y, 0, 0); - Event.current.Use(); - InspectorWindow.RepaintAllInspectors(); - } - - if (evt.type == EventType.MouseDrag) - { - if (IsRectSelectionActive()) - { - m_RectSelectionRect.x = Mathf.Min(m_RectSelectionStartPos.x, evt.mousePosition.x); - m_RectSelectionRect.y = Mathf.Min(m_RectSelectionStartPos.y, evt.mousePosition.y); - m_RectSelectionRect.width = Mathf.Max(m_RectSelectionStartPos.x, evt.mousePosition.x) - m_RectSelectionRect.x; - m_RectSelectionRect.height = Mathf.Max(m_RectSelectionStartPos.y, evt.mousePosition.y) - m_RectSelectionRect.y; - Event.current.Use(); - } - - if (m_MovingSrcRect.y >= 0.0f) - Event.current.Use(); - } - - if (IsRectSelectionActive() && evt.GetTypeForControl(m_RectSelectionControlID) == EventType.MouseUp) - { - var newChannelStripSelection = (evt.shift) ? m_Controller.CachedSelection : new List(); - foreach (var g in channelStripParams.rectSelectionGroups) - if (!newChannelStripSelection.Contains(g)) - newChannelStripSelection.Add(g); - Selection.objects = newChannelStripSelection.ToArray(); - m_Controller.OnUnitySelectionChanged(); - - GUIUtility.hotControl = 0; - Event.current.Use(); - //InspectorWindow.RepaintAllInspectors(); - } - - if (evt.type == EventType.Repaint) - { - if (IsRectSelectionActive()) - { - Color rectSelCol = new Color(1, 1, 1, 0.3f); - AudioMixerDrawUtils.DrawGradientRectHorizontal(m_RectSelectionRect, rectSelCol, rectSelCol); - } - } - } - - void WarningOverlay(List allGroups, Rect rect, Rect contentRect) - { - int numSoloed = 0, numMuted = 0, numBypassEffects = 0; - foreach (var g in allGroups) - { - if (g.solo) - numSoloed++; - if (g.mute) - numMuted++; - if (g.bypassEffects) - numBypassEffects += g.effects.Length - 1; // one of the effects is "Attenuation" - else - numBypassEffects += g.effects.Count(e => e.bypass); - } - - Event evt = Event.current; - - // Warning overlay - if (evt.type == EventType.Repaint && numSoloed > 0 || numMuted > 0 || numBypassEffects > 0) - { - string warningStr = "Warning: " + ( - (numSoloed > 0) ? (numSoloed + (numSoloed > 1 ? " groups" : " group") + " currently soloed") : - (numMuted > 0) ? (numMuted + (numMuted > 1 ? " groups" : " group") + " currently muted") : - (numBypassEffects + (numBypassEffects > 1 ? " effects" : " effect") + " currently bypassed") - ); - - //bool verticalScrollbar = contentRect.height > rect.height; - bool horizontalScrollbar = contentRect.width > rect.width; - const float margin = 5f; - float textwidth = styles.warningOverlay.CalcSize(GUIContent.Temp(warningStr)).x; - Rect warningRect = - new Rect(rect.x + margin + Mathf.Max((rect.width - 2 * margin - textwidth) * 0.5f, 0f), - rect.yMax - styles.warningOverlay.fixedHeight - margin - (horizontalScrollbar ? 17f : 0f), - textwidth, - styles.warningOverlay.fixedHeight); - - GUI.Label(warningRect, GUIContent.Temp(warningStr), styles.warningOverlay); - } - } - - Rect GetContentRect(List sortedGroups, bool isShowingReferencedGroups, int maxEffects) - { - float fixedHeight = headerHeight + vuHeight + dbHeight + soloMuteBypassHeight; - float maxHeight = channelStripsOffset.y + fixedHeight + (maxEffects * effectHeight) + 10 + effectHeight + 10; - - float maxWidth = channelStripsOffset.x * 2 + (channelStripBaseWidth + channelStripSpacing) * sortedGroups.Count + (isShowingReferencedGroups ? spaceBetweenMainGroupsAndReferenced : 0f); - return new Rect(0, 0, maxWidth, maxHeight); - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerColorCodes.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerColorCodes.cs deleted file mode 100644 index 0d89f5b0b2..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerColorCodes.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.Audio; - -namespace UnityEditor -{ - internal static class AudioMixerColorCodes - { - // Must match 'colorNames' array - static Color[] darkSkinColors = new[] { - new Color(0.5f, 0.5f, 0.5f, 0.2f), - new Color(255 / 255f, 208 / 255f, 0 / 255f), - new Color(245 / 255f, 156 / 255f, 4 / 255f), - new Color(255 / 255f, 75 / 255f, 58 / 255f), - new Color(255 / 255f, 97 / 255f, 156 / 255f), - new Color(168 / 255f, 114 / 255f, 183 / 255f), - new Color(13 / 255f, 156 / 255f, 210 / 255f), - new Color(0 / 255f, 190 / 255f, 200 / 255f), - new Color(138 / 255f, 192 / 255f, 1 / 255f) - }; - - // Must match 'colorNames' array - static Color[] lightSkinColors = new[] { - new Color(0.5f, 0.5f, 0.5f, 0.2f), - new Color(255 / 255f, 214 / 255f, 22 / 255f), - new Color(247 / 255f, 147 / 255f, 0 / 255f), - new Color(255 / 255f, 75 / 255f, 58 / 255f), - new Color(255 / 255f, 97 / 255f, 156 / 255f), - new Color(168 / 255f, 114 / 255f, 183 / 255f), - new Color(13 / 255f, 156 / 255f, 210 / 255f), - new Color(0 / 255f, 181 / 255f, 185 / 255f), - new Color(114 / 255f, 169 / 255f, 24 / 255f) - }; - - static string[] colorNames = new[] { "No Color", - "Yellow", - "Orange", - "Red", - "Magenta", - "Violet", - "Blue", - "Cyan", - "Green" }; - - static string[] GetColorNames() - { - return colorNames; - } - - static Color[] GetColors() - { - if (EditorGUIUtility.isProSkin) - return darkSkinColors; - else - return lightSkinColors; - } - - public static void AddColorItemsToGenericMenu(GenericMenu menu, AudioMixerGroupController[] groups) - { - var colors = GetColors(); - var names = GetColorNames(); - - for (int i = 0; i < colors.Length; i++) - { - bool selected = (groups.Length == 1) && (i == groups[0].userColorIndex); - menu.AddItem(new GUIContent(names[i]), selected, ItemCallback, new ItemData { groups = groups, index = i }); - } - } - - struct ItemData - { - public AudioMixerGroupController[] groups; - public int index; - } - static void ItemCallback(object data) - { - ItemData d = (ItemData)data; - - Undo.RecordObjects(d.groups, "Change Group(s) Color"); - - foreach (AudioMixerGroupController group in d.groups) - group.userColorIndex = d.index; - } - - public static Color GetColor(int index) - { - var colors = GetColors(); - if (index >= 0 && index < colors.Length) - return colors[index]; - - Debug.LogError("Invalid color code index: " + index); - return Color.white; - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerDrawUtils.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerDrawUtils.cs deleted file mode 100644 index bcaf0c086a..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerDrawUtils.cs +++ /dev/null @@ -1,369 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.Audio; - -namespace UnityEditor -{ - internal class AudioMixerDrawUtils - { - // OpenGL and D3D<11 use different ways of specifying the rasterization grid, so in order to draw exactly we need to account for this. - private static float vertexOffset = -1.0f; - private static void DetectVertexOffset() - { - //string driver = SystemInfo.graphicsDeviceVersion; - //vertexOffset = 0.5f; //(driver.StartsWith("OpenGL") || driver.StartsWith("Direct3D 11")) ? 0.0f : 0.5f; - //vertexOffset /= EditorGUIUtility.pixelsPerPoint; - vertexOffset = 0.0f; - //Debug.Log("Detected vertex offset as " + vertexOffset + " driver=" + driver); - } - - static readonly Color kAttenuationColor = AudioCurveRendering.kAudioOrange; - static readonly Color kEffectColor = new Color(103 / 255f, 160 / 255f, 0 / 255f); - static readonly Color kSendColor = new Color(0 / 255f, 147 / 255f, 170 / 255f); - static readonly Color kReceiveColor = kSendColor; - static readonly Color kDuckVolumeColor = kSendColor; - - public static Color GetEffectColor(AudioMixerEffectController effect) - { - if (effect.IsSend()) - return (effect.sendTarget != null) ? kSendColor : Color.gray; - if (effect.IsReceive()) - return kReceiveColor; - if (effect.IsDuckVolume()) - return kDuckVolumeColor; - if (effect.IsAttenuation()) - return kAttenuationColor; - - return kEffectColor; - } - - public static Color kBackgroundHi = new Color(0.5f, 0.5f, 0.5f); - public static Color kBackgroundLo = new Color(0.3f, 0.3f, 0.3f); - public static Color kBackgroundHiHighlight = new Color(0.6f, 0.6f, 0.6f); - public static Color kBackgroundLoHighlight = new Color(0.4f, 0.4f, 0.4f); - - public class Styles - { - public GUIStyle headerStyle = new GUIStyle(EditorStyles.boldLabel); - public GUIStyle reorderableListLabel = new GUIStyle("PR Label"); - public GUIStyle regionBg = GetStyle("RegionBg"); - public GUIStyle channelStripVUMeterBg = GetStyle("ChannelStripVUMeterBg"); - public GUIStyle channelStripAreaBackground = "CurveEditorBackground"; //"flow background"; - public GUIStyle channelStripBg = GetStyle("ChannelStripBg"); - public GUIStyle duckingMarker = GetStyle("ChannelStripDuckingMarker"); - public GUIStyle channelStripAttenuationMarkerSquare = GetStyle("ChannelStripAttenuationMarkerSquare"); - public GUIStyle channelStripHeaderStyle; - public GUIStyle soloToggle = GetStyle("SoloToggle"); - public GUIStyle muteToggle = GetStyle("MuteToggle"); - public GUIStyle bypassToggle = GetStyle("BypassToggle"); - public GUIStyle circularToggle = GetStyle("CircularToggle"); - public GUIStyle totalVULevel = new GUIStyle(EditorStyles.label); - public GUIStyle attenuationBar = "ChannelStripAttenuationBar"; - public GUIStyle effectBar = "ChannelStripEffectBar"; - public GUIStyle sendReturnBar = "ChannelStripSendReturnBar"; - public GUIStyle effectName = new GUIStyle(EditorStyles.miniLabel); - public GUIStyle vuValue = new GUIStyle(EditorStyles.miniLabel); - public GUIStyle mixerHeader = new GUIStyle(EditorStyles.largeLabel); - public GUIStyle warningOverlay = GetStyle("WarningOverlay"); - public Texture2D scrollShadowTexture = EditorGUIUtility.FindTexture("ScrollShadow"); - public Texture2D leftToRightShadowTexture = EditorGUIUtility.FindTexture("LeftToRightShadow"); - public GUIContent soloGUIContent = new GUIContent("", "Adds this group to set of soloed groups"); - public GUIContent muteGUIContent = new GUIContent("", "Mutes this group"); - public GUIContent bypassGUIContent = new GUIContent("", "Bypasses the effects on this group"); - public GUIContent effectSlotGUIContent = new GUIContent("", "Drag horizontally to change wet mix levels or vertically to change order of effects. Note: Enable wet mixing in the context menu."); - public GUIContent attenuationSlotGUIContent = new GUIContent("", "Place the attenuation slot in the effect stack where attenuation should take effect"); - public GUIContent emptySendSlotGUIContent = new GUIContent("", "Connect to a Receive in the context menu or in the inspector"); - public GUIContent returnSlotGUIContent = new GUIContent("", "Connect a Send to this Receive"); - public GUIContent duckVolumeSlotGUIContent = new GUIContent("", "Connect a Send to this Duck Volume"); - public GUIContent duckingFaderGUIContent = new GUIContent("", "Ducking Fader"); - public GUIContent attenuationFader = new GUIContent("", "Attenuation fader"); - public GUIContent vuMeterGUIContent = new GUIContent("", "The VU meter shows the current level of the mix of all sounds and subgroups."); - 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"); - public GUIContent sendString = new GUIContent("s"); - - - static GUIStyle GetStyle(string styleName) - { - return styleName; // Implicit construction of GUIStyle - } - - public Styles() - { - headerStyle.alignment = TextAnchor.MiddleLeft; - - Texture2D transparent = reorderableListLabel.hover.background; - reorderableListLabel.normal.background = transparent; - reorderableListLabel.active.background = transparent; - reorderableListLabel.focused.background = transparent; - reorderableListLabel.onNormal.background = transparent; - reorderableListLabel.onHover.background = transparent; - reorderableListLabel.onActive.background = transparent; - reorderableListLabel.onFocused.background = transparent; - reorderableListLabel.padding.left = reorderableListLabel.padding.right = 0; - reorderableListLabel.alignment = TextAnchor.MiddleLeft; - - scrollShadowTexture = EditorGUIUtility.FindTexture("ScrollShadow"); - - channelStripHeaderStyle = new GUIStyle(EditorStyles.boldLabel); - channelStripHeaderStyle.alignment = TextAnchor.MiddleLeft; - channelStripHeaderStyle.fontSize = 11; - channelStripHeaderStyle.fontStyle = FontStyle.Bold; - channelStripHeaderStyle.wordWrap = false; - channelStripHeaderStyle.clipping = TextClipping.Clip; - channelStripHeaderStyle.padding = new RectOffset(4, 4, 4, 4); - - totalVULevel.alignment = TextAnchor.MiddleRight; - totalVULevel.padding.right = 20; - - effectName.padding.left = 4; - effectName.padding.top = 2; - - vuValue.padding.left = 4; - vuValue.padding.right = 4; - vuValue.padding.top = 0; - vuValue.alignment = TextAnchor.MiddleRight; - vuValue.clipping = TextClipping.Overflow; - - warningOverlay.alignment = TextAnchor.MiddleCenter; - - mixerHeader.fontStyle = FontStyle.Bold; - mixerHeader.fontSize = 17; - mixerHeader.margin = new RectOffset(); - mixerHeader.padding = new RectOffset(); - mixerHeader.alignment = TextAnchor.UpperLeft; - if (EditorGUIUtility.isProSkin) - mixerHeader.normal.textColor = new Color(0.7f, 0.7f, 0.7f, 1.0f); - else - mixerHeader.normal.textColor = new Color(0.2f, 0.2f, 0.2f, 1.0f); - } - } - static Styles s_Styles; - public static Styles styles { get { return s_Styles; }} - public static void InitStyles() - { - if (s_Styles == null) - { - s_Styles = new Styles(); - DetectVertexOffset(); - } - } - - public static float GetAlpha() - { - return GUI.enabled ? 1.0f : 0.7f; - } - - public static void DrawSplitter() - { - Rect r = GUILayoutUtility.GetRect(1, 1); - if (Event.current.type == EventType.Repaint) - { - 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 - EditorGUI.DrawRect(r, color); - } - } - - public static void Vertex(float x, float y) - { - GL.Vertex3(x + vertexOffset, y + vertexOffset, 0); - } - - public static void DrawLine(float x1, float y1, float x2, float y2, Color c) - { - if (Event.current.type != EventType.Repaint) - return; - - HandleUtility.ApplyWireMaterial(); - GL.Begin(GL.LINES); - GL.Color(new Color(c.r, c.g, c.b, c.a * GetAlpha())); - Vertex(x1, y1); - Vertex(x2, y2); - GL.End(); - } - - //todo: 339 draw calls in our test case. Reduce it to fewer calls into this function. - public static void DrawGradientRect(Rect r, Color c1, Color c2) - { - if (Event.current.type != EventType.Repaint) - return; - //Profiler.BeginSample ("DrawGradientRect"); - HandleUtility.ApplyWireMaterial(); - GL.Begin(GL.QUADS); - GL.Color(new Color(c1.r, c1.g, c1.b, c1.a * GetAlpha())); - Vertex(r.x, r.y); - Vertex(r.x + r.width, r.y); - GL.Color(new Color(c2.r, c2.g, c2.b, c2.a * GetAlpha())); - Vertex(r.x + r.width, r.y + r.height); - Vertex(r.x, r.y + r.height); - GL.End(); - //Profiler.EndSample (); - } - - public static void DrawGradientRectHorizontal(Rect r, Color c1, Color c2) - { - if (Event.current.type != EventType.Repaint) - return; - //Profiler.BeginSample ("DrawGradientRectHorizontal"); - HandleUtility.ApplyWireMaterial(); - GL.Begin(GL.QUADS); - GL.Color(new Color(c1.r, c1.g, c1.b, c1.a * GetAlpha())); - Vertex(r.x + r.width, r.y); - Vertex(r.x + r.width, r.y + r.height); - GL.Color(new Color(c2.r, c2.g, c2.b, c2.a * GetAlpha())); - Vertex(r.x, r.y + r.height); - Vertex(r.x, r.y); - GL.End(); - //Profiler.EndSample (); - } - - internal const float kSectionHeaderHeight = 22f; - internal const float kSpaceBetweenSections = 10f; - - public static void DrawRegionBg(Rect rect, out Rect headerRect, out Rect contentRect) - { - const float headerIndent = 2f; - headerRect = new Rect(rect.x + headerIndent, rect.y, rect.width - headerIndent, kSectionHeaderHeight); - contentRect = new Rect(rect.x, headerRect.yMax, rect.width, rect.height - kSectionHeaderHeight); - GUI.Label(new RectOffset(1, 1, 1, 1).Add(contentRect), GUIContent.none, EditorStyles.helpBox); - } - - public static void HeaderLabel(Rect r, GUIContent text, Texture2D icon) - { - if (icon != null) - { - EditorGUIUtility.SetIconSize(new Vector2(16, 16)); - GUI.Label(r, icon, styles.headerStyle); - EditorGUIUtility.SetIconSize(Vector2.zero); - r.xMin += 20f; - } - GUI.Label(r, text, styles.headerStyle); - } - - public static GUIStyle BuildGUIStyleForLabel(Color color, int fontSize, bool wrapText, FontStyle fontstyle, TextAnchor anchor) - { - GUIStyle style = new GUIStyle(); - style.focused.background = style.onNormal.background; - style.focused.textColor = color; - style.alignment = anchor; - style.fontSize = fontSize; - style.fontStyle = fontstyle; - style.wordWrap = wrapText; - style.clipping = TextClipping.Clip; - style.normal.textColor = color; - style.padding = new RectOffset(4, 4, 4, 4); - return style; - } - - public static void ReadOnlyLabel(Rect r, GUIContent content, GUIStyle style) - { - GUI.Label(r, content, style); - } - - public static void ReadOnlyLabel(Rect r, string text, GUIStyle style) - { - GUI.Label(r, GUIContent.Temp(text), style); - } - - public static void ReadOnlyLabel(Rect r, string text, GUIStyle style, string tooltipText) - { - GUI.Label(r, GUIContent.Temp(text, tooltipText), style); - } - - public static void AddTooltipOverlay(Rect r, string tooltip) - { - GUI.Label(r, GUIContent.Temp(string.Empty, tooltip), s_Styles.headerStyle); - } - - public static void DrawConnection(Color col, float mixLevel, float srcX, float srcY, float dstX, float dstY, float width) - { - if (Event.current.type != EventType.Repaint) - return; - - //Profiler.BeginSample ("DrawConnection"); - HandleUtility.ApplyWireMaterial(); - - var dirX = dstX - srcX; - var dirY = dstY - srcY; - var scale = width / Mathf.Sqrt(dirX * dirX + dirY * dirY); - dirX *= scale; - dirY *= scale; - - float a = 2.0f, b = 1.2f; - var arrowPoints = new Vector3[4]; - arrowPoints[0] = new Vector3(dstX, dstY); - arrowPoints[1] = new Vector3(dstX - a * dirX + b * dirY, dstY - a * dirY - b * dirX); - arrowPoints[2] = new Vector3(dstX - a * dirX - b * dirY, dstY - a * dirY + b * dirX); - arrowPoints[3] = arrowPoints[0]; - - Color triColor = new Color(col.r, col.g, col.b, mixLevel * 0.3f + 0.3f); - Shader.SetGlobalColor("_HandleColor", triColor); - GL.Begin(GL.TRIANGLES); - GL.Color(triColor); - GL.Vertex(arrowPoints[0]); - GL.Vertex(arrowPoints[1]); - GL.Vertex(arrowPoints[2]); - GL.End(); - - Handles.DrawAAPolyLine(width, new[] { triColor, triColor, triColor, triColor }, arrowPoints); - - Handles.DrawAAPolyLine( - width, - new[] { new Color(col.r, col.g, col.b, mixLevel), new Color(col.r, col.g, col.b, mixLevel) }, - new[] { new Vector3(srcX, srcY, 0.0f), new Vector3(dstX, dstY, 0.0f) } - ); - //Profiler.EndSample (); - } - - public static void DrawVerticalShow(Rect rect, bool fadeToTheRight) - { - Rect textureCoordRect = fadeToTheRight ? new Rect(0, 0, 1, 1) : new Rect(1, 1, -1, -1); // flip over X - GUI.DrawTextureWithTexCoords(rect, styles.leftToRightShadowTexture, textureCoordRect); - } - - public static void DrawScrollDropShadow(Rect scrollViewRect, float scrollY, float contentHeight) - { - if (Event.current.type == EventType.Repaint) - { - bool isShowingScrollBar = contentHeight > scrollViewRect.height; - if (!isShowingScrollBar) - return; - - const float shadowHeightTop = 20f; - const float shadowHeightBottom = 10f; - const float fadeDist = 10f; - - Color orgColor = GUI.color; - - // Top shadow is faded in over the first 'fadeDist' - float alpha = scrollY > fadeDist ? 1f : (scrollY / fadeDist); - if (alpha < 1f) - GUI.color = new Color(1, 1, 1, alpha); - if (alpha > 0f) - GUI.DrawTexture(new Rect(scrollViewRect.x, scrollViewRect.y, scrollViewRect.width, shadowHeightTop), styles.scrollShadowTexture); - if (alpha < 1f) - GUI.color = orgColor; - - // Bottom shadow is shown if the scroll bar is visible - float scrollAvailable = Mathf.Max(contentHeight - scrollViewRect.height, 0f); - float alphaBottom = (scrollAvailable - scrollY) > fadeDist ? 1f : (scrollAvailable - scrollY) / fadeDist; - if (alphaBottom < 1f) - GUI.color = new Color(1, 1, 1, alphaBottom); - if (alphaBottom > 0f) - GUI.DrawTextureWithTexCoords(new Rect(scrollViewRect.x, scrollViewRect.yMax - shadowHeightBottom, scrollViewRect.width, shadowHeightBottom), styles.scrollShadowTexture, new Rect(1, 1, -1, -1)); // flip over Y - if (alphaBottom < 1f) - GUI.color = orgColor; - } - } - - public static void DrawRect(Rect rect, Color color) - { - Color orgColor = GUI.color; - GUI.color = color; - GUI.Label(rect, GUIContent.Temp(string.Empty), EditorGUIUtility.whiteTextureStyle); // Using style rendering so that disabled state is reflected in rendering - GUI.color = orgColor; - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerEffectGUI.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerEffectGUI.cs deleted file mode 100644 index de2802e4d2..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerEffectGUI.cs +++ /dev/null @@ -1,167 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.Audio; - -namespace UnityEditor -{ - internal static class AudioMixerEffectGUI - { - const string kAudioSliderFloatFormat = "F2"; - const string kExposedParameterUnicodeChar = " \u2794"; - - public static void EffectHeader(string text) - { - GUILayout.Label(text, styles.headerStyle); - } - - 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) - { - EditorGUI.BeginChangeCheck(); - - float oldNumberWidth = EditorGUIUtility.fieldWidth; - string origFormat = EditorGUI.kFloatFieldFormatString; - - bool exposed = controller.ContainsExposedParameter(path.parameter); - - EditorGUIUtility.fieldWidth = 70f; // do not go over 70 because then sliders will not be shown when inspector has minimal width - EditorGUI.kFloatFieldFormatString = kAudioSliderFloatFormat; - EditorGUI.s_UnitString = unit; - GUIContent content = label; - if (exposed) - content = GUIContent.Temp(label.text + kExposedParameterUnicodeChar, label.tooltip); - - float displayValue = value * displayScale; - displayValue = EditorGUILayout.PowerSlider(content, displayValue, leftValue * displayScale, rightValue * displayScale, displayExponent, options); - - EditorGUI.s_UnitString = null; - EditorGUI.kFloatFieldFormatString = origFormat; - EditorGUIUtility.fieldWidth = oldNumberWidth; - - if (Event.current.type == EventType.ContextClick) - { - Rect wholeSlider = GUILayoutUtility.topLevel.GetLast(); - if (wholeSlider.Contains(Event.current.mousePosition)) - { - Event.current.Use(); - - GenericMenu pm = new GenericMenu(); - if (!exposed) - pm.AddItem(EditorGUIUtility.TrTextContent("Expose '" + path.ResolveStringPath(false) + "' to script"), false, ExposePopupCallback, new ExposedParamContext(controller, path)); - else - pm.AddItem(EditorGUIUtility.TrTextContent("Unexpose"), false, UnexposePopupCallback, new ExposedParamContext(controller, path)); - - ParameterTransitionType existingType; - bool overrideExists = controller.TargetSnapshot.GetTransitionTypeOverride(path.parameter, out existingType); - System.Diagnostics.Debug.Assert(!overrideExists || existingType == ParameterTransitionType.Lerp); - - pm.AddSeparator(string.Empty); - pm.AddItem(EditorGUIUtility.TrTextContent("Linear Snapshot Transition"), existingType == ParameterTransitionType.Lerp, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.Lerp)); - pm.AddItem(EditorGUIUtility.TrTextContent("Smoothstep Snapshot Transition"), existingType == ParameterTransitionType.Smoothstep, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.Smoothstep)); - pm.AddItem(EditorGUIUtility.TrTextContent("Squared Snapshot Transition"), existingType == ParameterTransitionType.Squared, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.Squared)); - pm.AddItem(EditorGUIUtility.TrTextContent("SquareRoot Snapshot Transition"), existingType == ParameterTransitionType.SquareRoot, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.SquareRoot)); - pm.AddItem(EditorGUIUtility.TrTextContent("BrickwallStart Snapshot Transition"), existingType == ParameterTransitionType.BrickwallStart, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.BrickwallStart)); - pm.AddItem(EditorGUIUtility.TrTextContent("BrickwallEnd Snapshot Transition"), existingType == ParameterTransitionType.BrickwallEnd, ParameterTransitionOverrideCallback, new ParameterTransitionOverrideContext(controller, path.parameter, ParameterTransitionType.BrickwallEnd)); - pm.AddSeparator(string.Empty); - - pm.ShowAsContext(); - } - } - - if (EditorGUI.EndChangeCheck()) - { - value = displayValue / displayScale; - return true; - } - return false; - } - - private class ExposedParamContext - { - public ExposedParamContext(AudioMixerController controller, AudioParameterPath path) - { - this.controller = controller; - this.path = path; - } - - public AudioMixerController controller; - public AudioParameterPath path; - } - - - public static void ExposePopupCallback(object obj) - { - ExposedParamContext context = (ExposedParamContext)obj; - Undo.RecordObject(context.controller, "Expose Mixer Parameter"); - context.controller.AddExposedParameter(context.path); - - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - - public static void UnexposePopupCallback(object obj) - { - ExposedParamContext context = (ExposedParamContext)obj; - Undo.RecordObject(context.controller, "Unexpose Mixer Parameter"); - context.controller.RemoveExposedParameter(context.path.parameter); - - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - - private class ParameterTransitionOverrideContext - { - public ParameterTransitionOverrideContext(AudioMixerController controller, GUID parameter, ParameterTransitionType type) - { - this.controller = controller; - this.parameter = parameter; - this.type = type; - } - - public AudioMixerController controller; - public GUID parameter; - public ParameterTransitionType type; - } - - private class ParameterTransitionOverrideRemoveContext - { - public ParameterTransitionOverrideRemoveContext(AudioMixerController controller, GUID parameter) - { - this.controller = controller; - this.parameter = parameter; - } - - public AudioMixerController controller; - public GUID parameter; - } - - public static void ParameterTransitionOverrideCallback(object obj) - { - ParameterTransitionOverrideContext context = (ParameterTransitionOverrideContext)obj; - Undo.RecordObject(context.controller, "Change Parameter Transition Type"); - if (context.type == ParameterTransitionType.Lerp) - context.controller.TargetSnapshot.ClearTransitionTypeOverride(context.parameter); - else - context.controller.TargetSnapshot.SetTransitionTypeOverride(context.parameter, context.type); - } - - public static bool PopupButton(GUIContent label, GUIContent buttonContent, GUIStyle style, out Rect buttonRect, params GUILayoutOption[] options) - { - if (label != null) - { - Rect r = EditorGUILayout.s_LastRect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - int id = EditorGUIUtility.GetControlID("EditorPopup".GetHashCode(), FocusType.Keyboard, r); - buttonRect = EditorGUI.PrefixLabel(r, id, label); - } - else - { - Rect r = GUILayoutUtility.GetRect(buttonContent, style, options); - buttonRect = r; - } - - return EditorGUI.DropdownButton(buttonRect, buttonContent, FocusType.Passive, style); - } - - private static AudioMixerDrawUtils.Styles styles { get { return AudioMixerDrawUtils.styles; } } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerEffectView.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerEffectView.cs deleted file mode 100644 index a15af7d811..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerEffectView.cs +++ /dev/null @@ -1,593 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using System; -using UnityEditor.Audio; - -namespace UnityEditor -{ - class AudioMixerEffectView - { - private const float kMinPitch = 0.01f; - private const float kMaxPitch = 10.0f; - - private const int kLabelWidth = 170; - private const int kTextboxWidth = 70; - - private AudioMixerGroupController m_PrevGroup = null; - private readonly EffectDragging m_EffectDragging; - private int m_LastNumChannels = 0; - - private AudioMixerEffectPlugin m_SharedPlugin = new AudioMixerEffectPlugin(); - private Dictionary m_CustomEffectGUIs = new Dictionary(); - - static class Texts - { - public static GUIContent editInPlaymode = EditorGUIUtility.TrTextContent("Edit in Playmode"); - public static GUIContent pitch = EditorGUIUtility.TrTextContent("Pitch"); - public static GUIContent addEffect = EditorGUIUtility.TrTextContent("Add Effect"); - public static GUIContent volume = EditorGUIUtility.TrTextContent("Volume"); - public static GUIContent sendLevel = EditorGUIUtility.TrTextContent("Send level"); - public static GUIContent bus = EditorGUIUtility.TrTextContent("Receive"); - public static GUIContent none = EditorGUIUtility.TrTextContent("None"); - 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."); - public static string dB = "dB"; - public static string percentage = "%"; - public static string cpuFormatString = " - CPU: {0:#0.00}%"; - } - - public AudioMixerEffectView() - { - m_EffectDragging = new EffectDragging(); - - Type pluginType = typeof(IAudioEffectPluginGUI); - foreach (var assembly in System.AppDomain.CurrentDomain.GetAssemblies()) - { - //Debug.Log("Assembly: " + assembly.FullName); - try - { - var types = assembly.GetTypes(); - //Debug.Log("Contained types: " + types.ToString()); - foreach (Type t in types.Where(t => !t.IsAbstract && pluginType.IsAssignableFrom(t))) - { - //Debug.Log("Instantiating type: " + t.FullName); - RegisterCustomGUI(Activator.CreateInstance(t) as IAudioEffectPluginGUI); - } - } - catch (System.Exception) - { - //Debug.Log("Failed getting types in assembly: " + assembly.FullName); - } - } - } - - public bool RegisterCustomGUI(IAudioEffectPluginGUI gui) - { - string name = gui.Name; - if (m_CustomEffectGUIs.ContainsKey(name)) - { - var oldGUI = m_CustomEffectGUIs[name]; - Debug.LogError("Attempt to register custom GUI for plugin " + name + " failed as another plugin is already registered under this name."); - Debug.LogError("Plugin trying to register itself: " + gui.Description + " (Vendor: " + gui.Vendor + ")"); - Debug.LogError("Plugin already registered: " + oldGUI.Description + " (Vendor: " + oldGUI.Vendor + ")"); - return false; - } - - m_CustomEffectGUIs[name] = gui; - return true; - } - - public void OnGUI(AudioMixerGroupController group) - { - if (group == null) - return; - - var controller = group.controller; - var allGroups = controller.GetAllAudioGroupsSlow(); - var effectMap = new Dictionary(); - foreach (var g in allGroups) - foreach (var e in g.effects) - effectMap[e] = g; - - Rect totalRect = EditorGUILayout.BeginVertical(); - - if (EditorApplication.isPlaying) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - EditorGUI.BeginChangeCheck(); - GUILayout.Toggle(AudioSettings.editingInPlaymode, Texts.editInPlaymode, EditorStyles.miniButton, GUILayout.Width(120)); - if (EditorGUI.EndChangeCheck()) - AudioSettings.editingInPlaymode = !AudioSettings.editingInPlaymode; - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - } - - using (new EditorGUI.DisabledScope(!AudioMixerController.EditingTargetSnapshot())) - { - if (group != m_PrevGroup) - { - m_PrevGroup = group; - controller.m_HighlightEffectIndex = -1; - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - - // Do Effect modules - DoInitialModule(group, controller, allGroups); - for (int effectIndex = 0; effectIndex < group.effects.Length; effectIndex++) - { - DoEffectGUI(effectIndex, group, allGroups, effectMap, ref controller.m_HighlightEffectIndex); - } - - m_EffectDragging.HandleDragging(totalRect, group, controller); - - GUILayout.Space(10f); - - EditorGUILayout.BeginHorizontal(); - - GUILayout.FlexibleSpace(); - if (EditorGUILayout.DropdownButton(Texts.addEffect, FocusType.Passive, GUISkin.current.button)) - { - GenericMenu pm = new GenericMenu(); - Rect buttonRect = GUILayoutUtility.topLevel.GetLast(); - AudioMixerGroupController[] groupArray = new AudioMixerGroupController[] { group }; - AudioMixerChannelStripView.AddEffectItemsToMenu(controller, groupArray, group.effects.Length, string.Empty, pm); - pm.DropDown(buttonRect); - } - - EditorGUILayout.EndHorizontal(); - } - - EditorGUILayout.EndVertical(); - } - - public static float DoInitialModule(AudioMixerGroupController group, AudioMixerController controller, List allGroups) - { - Rect totalRect = EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins); - - // Pitch - float value = group.GetValueForPitch(controller, controller.TargetSnapshot); - if (AudioMixerEffectGUI.Slider(Texts.pitch, ref value, 100.0f, 1.0f, Texts.percentage, kMinPitch, kMaxPitch, controller, new AudioGroupParameterPath(group, group.GetGUIDForPitch()))) - { - Undo.RecordObject(controller.TargetSnapshot, "Change Pitch"); - group.SetValueForPitch(controller, controller.TargetSnapshot, value); - } - - GUILayout.Space(5f); - EditorGUILayout.EndVertical(); - - AudioMixerDrawUtils.DrawSplitter(); - - return totalRect.height; - } - - public void DoEffectGUI(int effectIndex, AudioMixerGroupController group, List allGroups, Dictionary effectMap, ref int highlightEffectIndex) - { - Event evt = Event.current; - - AudioMixerController controller = group.controller; - AudioMixerEffectController effect = group.effects[effectIndex]; - MixerParameterDefinition[] paramDefs = MixerEffectDefinitions.GetEffectParameters(effect.effectName); - - // This rect is valid after every layout event - Rect totalRect = EditorGUILayout.BeginVertical(); - - bool hovering = totalRect.Contains(evt.mousePosition); - EventType evtType = evt.GetTypeForControl(m_EffectDragging.dragControlID); - - if (evtType == EventType.MouseMove && hovering && highlightEffectIndex != effectIndex) - { - highlightEffectIndex = effectIndex; - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - - // Header - const float colorCodeWidth = 6f; - var gearSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.titleSettingsIcon); - Rect headerRect = GUILayoutUtility.GetRect(1, 17f); - Rect colorCodeRect = new Rect(headerRect.x + 6f, headerRect.y + 5f, colorCodeWidth, colorCodeWidth); - Rect labelRect = new Rect(headerRect.x + 8f + colorCodeWidth, headerRect.y, headerRect.width - 8f - colorCodeWidth - gearSize.x - 5f, headerRect.height); - Rect gearRect = new Rect(labelRect.xMax, headerRect.y, gearSize.x, gearSize.y); - Rect dragRect = new Rect(headerRect.x, headerRect.y, headerRect.width - gearSize.x - 5f, headerRect.height); - { - bool showCPU = EditorPrefs.GetBool(AudioMixerGroupEditor.kPrefKeyForShowCpuUsage, false) && EditorUtility.audioProfilingEnabled; - - float val = EditorGUIUtility.isProSkin ? 0.1f : 1.0f; - Color headerColor = new Color(val, val, val, 0.2f); - Color origColor = GUI.color; - GUI.color = headerColor; - GUI.DrawTexture(headerRect, EditorGUIUtility.whiteTexture); - GUI.color = origColor; - - Color effectColorCode = AudioMixerDrawUtils.GetEffectColor(effect); - EditorGUI.DrawRect(colorCodeRect, effectColorCode); - GUI.Label(labelRect, showCPU ? effect.effectName + string.Format(Texts.cpuFormatString, effect.GetCPUUsage(controller)) : effect.effectName, EditorStyles.boldLabel); - if (EditorGUI.DropdownButton(gearRect, EditorGUI.GUIContents.titleSettingsIcon, FocusType.Passive, EditorStyles.iconButton)) - { - ShowEffectContextMenu(group, effect, effectIndex, controller, gearRect); - } - - // Show context menu if right clicking in header rect (for convenience) - if (evt.type == EventType.ContextClick && headerRect.Contains(evt.mousePosition)) - { - ShowEffectContextMenu(group, effect, effectIndex, controller, new Rect(evt.mousePosition.x, headerRect.y, 1, headerRect.height)); - evt.Use(); - } - - if (evtType == EventType.Repaint) - EditorGUIUtility.AddCursorRect(dragRect, MouseCursor.ResizeVertical, m_EffectDragging.dragControlID); - } - - using (new EditorGUI.DisabledScope(effect.bypass || group.bypassEffects)) - { - EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins); - - if (effect.IsAttenuation()) - { - EditorGUILayout.BeginVertical(); - float value = group.GetValueForVolume(controller, controller.TargetSnapshot); - if (AudioMixerEffectGUI.Slider(Texts.volume, ref value, 1.0f, 1.0f, Texts.dB, AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume(), controller, new AudioGroupParameterPath(group, group.GetGUIDForVolume()))) - { - Undo.RecordObject(controller.TargetSnapshot, "Change Volume Fader"); - group.SetValueForVolume(controller, controller.TargetSnapshot, value); - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - - //FIXME - // 1) The VUMeter used is not in the same style that fits the rest of the Audio UI - // 2) The layout of the VU meters is hacked together and a lot of magic numbers are used. - int numChannels = 0; - float[] vuinfo_level = new float[9]; - float[] vuinfo_peak = new float[9]; - - numChannels = group.controller.GetGroupVUInfo(group.groupID, true, ref vuinfo_level, ref vuinfo_peak); - - if (evt.type == EventType.Layout) - { - m_LastNumChannels = numChannels; - } - else - { - if (numChannels != m_LastNumChannels) - HandleUtility.Repaint(); // Repaint to ensure correct rendered num channels - - // Ensure same num channels as in layout event to not break IMGUI controlID handling - numChannels = m_LastNumChannels; - } - - GUILayout.Space(4f); - for (int c = 0; c < numChannels; ++c) - { - float level = 1 - AudioMixerController.VolumeToScreenMapping(Mathf.Clamp(vuinfo_level[c], AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()), 1, true); - float peak = 1 - AudioMixerController.VolumeToScreenMapping(Mathf.Clamp(vuinfo_peak[c], AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume()), 1, true); - EditorGUILayout.VUMeterHorizontal(level, peak, GUILayout.Height(10)); - - //This allows the meters to drop to 0 after PlayMode has stopped. - if (!EditorApplication.isPlaying && peak > 0.0F) - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - GUILayout.Space(4f); - EditorGUILayout.EndVertical(); - } - - if (effect.IsSend()) - { - Rect buttonRect; - GUIContent buttonContent = (effect.sendTarget == null) ? Texts.none : GUIContent.Temp(effect.GetSendTargetDisplayString(effectMap)); - if (AudioMixerEffectGUI.PopupButton(Texts.bus, buttonContent, EditorStyles.popup, out buttonRect)) - ShowBusPopupMenu(effectIndex, @group, allGroups, effectMap, effect, buttonRect); - - if (effect.sendTarget != null) - { - float wetLevel = effect.GetValueForMixLevel(controller, controller.TargetSnapshot); - if (AudioMixerEffectGUI.Slider(Texts.sendLevel, ref wetLevel, 1.0f, 1.0f, Texts.dB, AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect, controller, new AudioEffectParameterPath(group, effect, effect.GetGUIDForMixLevel()))) - { - Undo.RecordObject(controller.TargetSnapshot, "Change Send Level"); - effect.SetValueForMixLevel(controller, controller.TargetSnapshot, wetLevel); - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - } - } - - if (MixerEffectDefinitions.EffectCanBeSidechainTarget(effect)) - { - bool anyTargetsFound = false; - foreach (var g in allGroups) - { - foreach (var e in g.effects) - { - if (e.IsSend() && e.sendTarget == effect) - { - anyTargetsFound = true; - break; - } - } - if (anyTargetsFound) - break; - } - if (!anyTargetsFound) - { - GUILayout.Label(EditorGUIUtility.TrTextContent("No Send sources connected.", EditorGUIUtility.warningIcon)); - } - } - - // Wet mix - if (effect.enableWetMix && !effect.IsReceive() && !effect.IsDuckVolume() && !effect.IsAttenuation() && !effect.IsSend()) - { - float wetLevel = effect.GetValueForMixLevel(controller, controller.TargetSnapshot); - if (AudioMixerEffectGUI.Slider(Texts.wet, ref wetLevel, 1.0f, 1.0f, Texts.dB, AudioMixerController.kMinVolume, AudioMixerController.kMaxEffect, controller, new AudioEffectParameterPath(group, effect, effect.GetGUIDForMixLevel()))) - { - Undo.RecordObject(controller.TargetSnapshot, "Change Mix Level"); - effect.SetValueForMixLevel(controller, controller.TargetSnapshot, wetLevel); - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - } - - // All other effects - bool drawDefaultGUI = true; - if (m_CustomEffectGUIs.ContainsKey(effect.effectName)) - { - var customGUI = m_CustomEffectGUIs[effect.effectName]; - m_SharedPlugin.m_Controller = controller; - m_SharedPlugin.m_Effect = effect; - m_SharedPlugin.m_ParamDefs = paramDefs; - drawDefaultGUI = customGUI.OnGUI(m_SharedPlugin); - } - if (drawDefaultGUI) - { - foreach (var p in paramDefs) - { - float value = effect.GetValueForParameter(controller, controller.TargetSnapshot, p.name); - 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)))) - { - Undo.RecordObject(controller.TargetSnapshot, "Change " + p.name); - effect.SetValueForParameter(controller, controller.TargetSnapshot, p.name, value); - } - } - if (paramDefs.Length > 0) - GUILayout.Space(6f); - } - } - - m_EffectDragging.HandleDragElement(effectIndex, totalRect, dragRect, group, allGroups); - - EditorGUILayout.EndVertical(); // indented effect contents - EditorGUILayout.EndVertical(); // calc total size - - AudioMixerDrawUtils.DrawSplitter(); - } - - private static void ShowEffectContextMenu(AudioMixerGroupController group, AudioMixerEffectController effect, int effectIndex, AudioMixerController controller, Rect buttonRect) - { - GenericMenu menu = new GenericMenu(); - - if (!effect.IsReceive()) - { - if (!effect.IsAttenuation() && !effect.IsSend() && !effect.IsDuckVolume()) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Allow Wet Mixing (causes higher memory usage)"), effect.enableWetMix, delegate() - { - Undo.RecordObject(effect, "Enable Wet Mixing"); - effect.enableWetMix = !effect.enableWetMix; - }); - menu.AddItem(EditorGUIUtility.TrTextContent("Bypass"), effect.bypass, delegate() - { - Undo.RecordObject(effect, "Bypass Effect"); - effect.bypass = !effect.bypass; - - controller.UpdateBypass(); - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - }); - menu.AddSeparator(""); - } - - menu.AddItem(EditorGUIUtility.TrTextContent("Copy effect settings to all snapshots"), false, delegate() - { - Undo.RecordObject(controller, "Copy effect settings to all snapshots"); - if (effect.IsAttenuation()) - controller.CopyAttenuationToAllSnapshots(group, controller.TargetSnapshot); - else - controller.CopyEffectSettingsToAllSnapshots(group, effectIndex, controller.TargetSnapshot, effect.IsSend()); - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - }); - - if (!effect.IsAttenuation() && !effect.IsSend() && !effect.IsDuckVolume() && effect.enableWetMix) - { - menu.AddItem(new GUIContent("Copy effect settings to all snapshots, including wet level"), false, delegate() - { - Undo.RecordObject(controller, "Copy effect settings to all snapshots, including wet level"); - controller.CopyEffectSettingsToAllSnapshots(group, effectIndex, controller.TargetSnapshot, true); - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - }); - } - - menu.AddSeparator(""); - } - - AudioMixerGroupController[] groupArray = new AudioMixerGroupController[] { group }; - AudioMixerChannelStripView.AddEffectItemsToMenu(controller, groupArray, effectIndex, "Add effect before/", menu); - AudioMixerChannelStripView.AddEffectItemsToMenu(controller, groupArray, effectIndex + 1, "Add effect after/", menu); - - if (!effect.IsAttenuation()) - { - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Remove this effect"), false, delegate() - { - controller.ClearSendConnectionsTo(effect); - controller.RemoveEffect(effect, group); - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - }); - } - - menu.DropDown(buttonRect); - } - - private static void ShowBusPopupMenu(int effectIndex, AudioMixerGroupController group, List allGroups, Dictionary effectMap, AudioMixerEffectController effect, Rect buttonRect) - { - GenericMenu pm = new GenericMenu(); - pm.AddItem(EditorGUIUtility.TrTextContent("None"), false, AudioMixerChannelStripView.ConnectSendPopupCallback, new AudioMixerChannelStripView.ConnectSendContext(effect, null)); - pm.AddSeparator(""); - AudioMixerChannelStripView.AddMenuItemsForReturns(pm, string.Empty, effectIndex, group, allGroups, effectMap, effect, true); - - if (pm.GetItemCount() == 2) - { - pm.AddDisabledItem(EditorGUIUtility.TrTextContent("No valid Receive targets found")); - } - - pm.DropDown(buttonRect); - } - - // ----------------------------------- - // Effect dragging logic and rendering - // ----------------------------------- - class EffectDragging - { - public EffectDragging() - { - m_DragControlID = GUIUtility.GetPermanentControlID(); - } - - public bool IsDraggingIndex(int effectIndex) - { - return m_MovingSrcIndex == effectIndex && GUIUtility.hotControl == m_DragControlID; - } - - public int dragControlID - { - get { return m_DragControlID; } - } - - private bool isDragging - { - get { return m_MovingSrcIndex != -1 && GUIUtility.hotControl == m_DragControlID; } - } - - private readonly Color kMoveColorBorderAllowed = new Color(1.0f, 1.0f, 1.0f, 1.0f); - private readonly Color kMoveColorHiAllowed = new Color(1.0f, 1.0f, 1.0f, 0.3f); - private readonly Color kMoveColorLoAllowed = new Color(1.0f, 1.0f, 1.0f, 0.0f); - private readonly Color kMoveColorBorderDisallowed = new Color(0.8f, 0.0f, 0.0f, 1.0f); - private readonly Color kMoveColorHiDisallowed = new Color(1.0f, 0.0f, 0.0f, 0.3f); - private readonly Color kMoveColorLoDisallowed = new Color(1.0f, 0.0f, 0.0f, 0.0f); - - private readonly int m_DragControlID = 0; - private int m_MovingSrcIndex = -1; - private int m_MovingDstIndex = -1; - private bool m_MovingEffectAllowed = false; - private float m_MovingPos = 0; - private Rect m_MovingRect = new Rect(0, 0, 0, 0); - private float m_DragHighlightPos = -1.0f; - private float m_DragHighlightHeight = 2f; - - // Called per effect - public void HandleDragElement(int effectIndex, Rect effectRect, Rect dragRect, AudioMixerGroupController group, List allGroups) - { - Event evt = Event.current; - - switch (evt.GetTypeForControl(m_DragControlID)) - { - case EventType.MouseDown: - if (evt.button == 0 && dragRect.Contains(evt.mousePosition) && GUIUtility.hotControl == 0) - { - m_MovingSrcIndex = effectIndex; - m_MovingPos = evt.mousePosition.y; - m_MovingRect = new Rect(effectRect.x, effectRect.y - m_MovingPos, effectRect.width, effectRect.height); - GUIUtility.hotControl = m_DragControlID; - EditorGUIUtility.SetWantsMouseJumping(1); - evt.Use(); - } - break; - - case EventType.Repaint: - if (effectIndex == m_MovingSrcIndex) - { - using (new EditorGUI.DisabledScope(true)) - { - AudioMixerDrawUtils.styles.channelStripAreaBackground.Draw(effectRect, false, false, false, false); - } - } - break; - } - - if (isDragging) - { - float h2 = effectRect.height * 0.5f; - float dy = evt.mousePosition.y - effectRect.y - h2; - - if (Mathf.Abs(dy) <= h2) - { - int newMovingDstIndex = (dy < 0.0f) ? effectIndex : (effectIndex + 1); - if (newMovingDstIndex != m_MovingDstIndex) - { - m_DragHighlightPos = (dy < 0.0f) ? effectRect.y : (effectRect.y + effectRect.height); - m_MovingDstIndex = newMovingDstIndex; - m_MovingEffectAllowed = !AudioMixerController.WillMovingEffectCauseFeedback(allGroups, group, m_MovingSrcIndex, group, newMovingDstIndex, null); - } - } - - // Do not draw drag highlight line for positions where no change will happen - if (m_MovingDstIndex == m_MovingSrcIndex || m_MovingDstIndex == m_MovingSrcIndex + 1) - { - m_DragHighlightPos = 0; - } - } - } - - // Called once per OnGUI - public void HandleDragging(Rect totalRect, AudioMixerGroupController group, AudioMixerController controller) - { - // Early out if we are not dragging - if (!isDragging) - return; - - Event evt = Event.current; - const float kMoveRange = 15; - - switch (evt.GetTypeForControl(m_DragControlID)) - { - case EventType.MouseDrag: - m_MovingPos = evt.mousePosition.y; - evt.Use(); - break; - - case EventType.MouseUp: - evt.Use(); - if (m_MovingSrcIndex != -1) - { - if (m_MovingDstIndex != -1 && m_MovingEffectAllowed) - { - var effects = group.effects.ToList(); - if (AudioMixerController.MoveEffect(ref effects, m_MovingSrcIndex, ref effects, m_MovingDstIndex)) - group.effects = effects.ToArray(); - } - m_MovingSrcIndex = -1; - m_MovingDstIndex = -1; - controller.m_HighlightEffectIndex = -1; - if (GUIUtility.hotControl == m_DragControlID) - GUIUtility.hotControl = 0; - EditorGUIUtility.SetWantsMouseJumping(0); - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - EditorGUIUtility.ExitGUI(); // Exit because we changed order of effects - } - break; - - case EventType.Repaint: - if (m_DragHighlightPos > 0.0f) - { - float w = totalRect.width; - Color moveColorLo = (m_MovingEffectAllowed) ? kMoveColorLoAllowed : kMoveColorLoDisallowed; - Color moveColorHi = (m_MovingEffectAllowed) ? kMoveColorHiAllowed : kMoveColorHiDisallowed; - Color moveColorBorder = (m_MovingEffectAllowed) ? kMoveColorBorderAllowed : kMoveColorBorderDisallowed; - AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingRect.x, m_DragHighlightPos - kMoveRange, w, kMoveRange), moveColorLo, moveColorHi); - AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingRect.x, m_DragHighlightPos, w, kMoveRange), moveColorHi, moveColorLo); - AudioMixerDrawUtils.DrawGradientRect(new Rect(m_MovingRect.x, m_DragHighlightPos - m_DragHighlightHeight / 2, w, m_DragHighlightHeight), moveColorBorder, moveColorBorder); - } - break; - } - } - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs deleted file mode 100644 index 584a8a62ac..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs +++ /dev/null @@ -1,174 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System; -using UnityEditorInternal; -using UnityEditor.Audio; - -namespace UnityEditor -{ - class AudioMixerExposedParameterView - { - private ReorderableListWithRenameAndScrollView m_ReorderableListWithRenameAndScrollView; - private AudioMixerController m_Controller; - private SerializedObject m_ControllerSerialized; - ReorderableListWithRenameAndScrollView.State m_State; - - private float height { get { return m_ReorderableListWithRenameAndScrollView.list.GetHeight(); } } - - public AudioMixerExposedParameterView(ReorderableListWithRenameAndScrollView.State state) - { - m_State = state; - } - - public void OnMixerControllerChanged(AudioMixerController controller) - { - m_Controller = controller; - - if (m_Controller) - m_Controller.ChangedExposedParameter += new ChangedExposedParameterHandler(RecreateListControl); - - RecreateListControl(); - } - - public void RecreateListControl() - { - if (m_Controller != null) - { - m_ControllerSerialized = new SerializedObject(m_Controller); - var exposedParams = m_ControllerSerialized.FindProperty("m_ExposedParameters"); - System.Diagnostics.Debug.Assert(exposedParams != null); - - ReorderableList reorderableList = new ReorderableList(m_ControllerSerialized, exposedParams, false, false, false, false); - reorderableList.onReorderCallback = EndDragChild; - reorderableList.drawElementCallback += DrawElement; - reorderableList.elementHeight = 16; - reorderableList.headerHeight = 0; - reorderableList.footerHeight = 0; - reorderableList.showDefaultBackground = false; - - m_ReorderableListWithRenameAndScrollView = new ReorderableListWithRenameAndScrollView(reorderableList, m_State); - m_ReorderableListWithRenameAndScrollView.onNameChangedAtIndex += NameChanged; - m_ReorderableListWithRenameAndScrollView.onDeleteItemAtIndex += Delete; - m_ReorderableListWithRenameAndScrollView.onGetNameAtIndex += GetNameOfElement; - } - } - - public void OnGUI(Rect rect) - { - if (m_Controller == null) - return; - - m_ReorderableListWithRenameAndScrollView.OnGUI(rect); - } - - public void OnContextClick(int itemIndex) - { - GenericMenu pm = new GenericMenu(); - pm.AddItem( - EditorGUIUtility.TrTextContent("Unexpose"), - false, - delegate(object data) { Delete((int)data); }, - itemIndex); - - pm.AddItem( - EditorGUIUtility.TrTextContent("Rename"), - false, - delegate(object data) { m_ReorderableListWithRenameAndScrollView.BeginRename((int)data, 0f); }, - itemIndex); - - pm.ShowAsContext(); - } - - void DrawElement(Rect rect, int index, bool isActive, bool isFocused) - { - Event evt = Event.current; - if (evt.type == EventType.ContextClick && rect.Contains(evt.mousePosition)) - { - OnContextClick(index); - evt.Use(); - } - - if (Event.current.type != EventType.Repaint) - return; - - // The left side of the text is drawn by the reorderable list, now draw the additional right aligned text - using (new EditorGUI.DisabledScope(true)) - { - m_ReorderableListWithRenameAndScrollView.elementStyleRightAligned.Draw(rect, GetInfoString(index), false, false, false, false); - } - } - - public Vector2 CalcSize() - { - float maxWidth = 0; - for (int index = 0; index < m_ReorderableListWithRenameAndScrollView.list.count; index++) - { - var width = WidthOfRow(index, m_ReorderableListWithRenameAndScrollView.elementStyle, m_ReorderableListWithRenameAndScrollView.elementStyleRightAligned); - if (width > maxWidth) - maxWidth = width; - } - return new Vector2(maxWidth, height); - } - - string GetInfoString(int index) - { - ExposedAudioParameter exposedParam = m_Controller.exposedParameters[index]; - return m_Controller.ResolveExposedParameterPath(exposedParam.guid, false); - } - - private float WidthOfRow(int index, GUIStyle leftStyle, GUIStyle rightStyle) - { - const float kMinSpacing = 25f; - string infoString = GetInfoString(index); - Vector2 infoSize = rightStyle.CalcSize(GUIContent.Temp(infoString)); - Vector2 size = leftStyle.CalcSize(GUIContent.Temp(GetNameOfElement(index))); - float width = size.x + infoSize.x + kMinSpacing; - return width; - } - - string GetNameOfElement(int index) - { - ExposedAudioParameter exposedParam = m_Controller.exposedParameters[index]; - return exposedParam.name; - } - - public void NameChanged(int index, string newName) - { - const int kMaxNameLength = 64; - if (newName.Length > kMaxNameLength) - { - newName = newName.Substring(0, kMaxNameLength); - Debug.LogWarning("Maximum name length of an exposed parameter is " + kMaxNameLength + " characters. Name truncated to '" + newName + "'"); - } - ExposedAudioParameter[] parameters = m_Controller.exposedParameters; - parameters[index].name = newName; - m_Controller.exposedParameters = parameters; - } - - void Delete(int index) - { - if (m_Controller != null) - { - Undo.RecordObject(m_Controller, "Unexpose Mixer Parameter"); - ExposedAudioParameter exposedParam = m_Controller.exposedParameters[index]; - m_Controller.RemoveExposedParameter(exposedParam.guid); - } - } - - public void EndDragChild(ReorderableList list) - { - m_ControllerSerialized.ApplyModifiedProperties(); - } - - public void OnEvent() - { - m_ReorderableListWithRenameAndScrollView.OnEvent(); - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs deleted file mode 100644 index a6355890cf..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditorInternal; -using UnityEditor.Audio; - -namespace UnityEditor -{ - internal partial class AudioMixerExposedParametersPopup : PopupWindowContent - { - // Shows pop up - internal static void Popup(AudioMixerController controller, GUIStyle style, params GUILayoutOption[] options) - { - GUIContent content = GetButtonContent(controller); - Rect buttonRect = GUILayoutUtility.GetRect(content, style, options); - if (EditorGUI.DropdownButton(buttonRect, content, FocusType.Passive, style)) - { - PopupWindow.Show(buttonRect, new AudioMixerExposedParametersPopup(controller), null, ShowMode.PopupMenuWithKeyboardFocus); - } - } - - // Cache to prevent constructing string on every event - static GUIContent m_ButtonContent = new GUIContent("", "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 ..'."); - static int m_LastNumExposedParams = -1; - static GUIContent GetButtonContent(AudioMixerController controller) - { - if (controller.numExposedParameters != m_LastNumExposedParams) - { - m_ButtonContent.text = string.Format("Exposed Parameters ({0})", controller.numExposedParameters); - m_LastNumExposedParams = controller.numExposedParameters; - } - return m_ButtonContent; - } - - // - private readonly AudioMixerExposedParameterView m_ExposedParametersView; - - AudioMixerExposedParametersPopup(AudioMixerController controller) - { - m_ExposedParametersView = new AudioMixerExposedParameterView(new ReorderableListWithRenameAndScrollView.State()); - m_ExposedParametersView.OnMixerControllerChanged(controller); - } - - public override void OnGUI(Rect rect) - { - m_ExposedParametersView.OnEvent(); - m_ExposedParametersView.OnGUI(rect); - } - - public override Vector2 GetWindowSize() - { - Vector2 size = m_ExposedParametersView.CalcSize(); - size.x = Math.Max(size.x, 125f); - size.y = Math.Max(size.y, 23f); - return size; - } - } -} // namespace diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupTreeView.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupTreeView.cs deleted file mode 100644 index fef6317fb6..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupTreeView.cs +++ /dev/null @@ -1,680 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System; -using UnityEditorInternal; -using UnityEditor.Audio; -using UnityEditor.IMGUI.Controls; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - // Item - - internal class AudioMixerTreeViewNode : TreeViewItem - { - public AudioMixerGroupController group { get; set; } - - public AudioMixerTreeViewNode(int instanceID, int depth, TreeViewItem parent, string displayName, AudioMixerGroupController group) - : base(instanceID, depth, parent, displayName) - { - this.group = group; - } - } - - // Dragging - // We want dragging to work from the mixer window to the inspector like the project browser, but also want - // custom dragging behavior (reparent the group sub assets) so we derive from AssetOrGameObjectTreeViewDragging - // and override DoDrag. - - internal class AudioGroupTreeViewDragging : AssetsTreeViewDragging - { - private AudioMixerGroupTreeView m_owner; - - public AudioGroupTreeViewDragging(TreeViewController treeView, AudioMixerGroupTreeView owner) - : base(treeView) - { - m_owner = owner; - } - - public override void StartDrag(TreeViewItem draggedItem, List draggedItemIDs) - { - if (!EditorApplication.isPlaying) - base.StartDrag(draggedItem, draggedItemIDs); - } - - public override DragAndDropVisualMode DoDrag(TreeViewItem parentNode, TreeViewItem targetNode, bool perform, DropPosition dragPos) - { - var parentGroupNode = parentNode as AudioMixerTreeViewNode; - var draggedGroups = new List(DragAndDrop.objectReferences).OfType().ToList(); - if (parentGroupNode != null && draggedGroups.Count > 0) - { - var draggedIDs = (from i in draggedGroups select i.GetInstanceID()).ToList(); - bool validDrag = ValidDrag(parentNode, draggedIDs) && !AudioMixerController.WillModificationOfTopologyCauseFeedback(m_owner.Controller.GetAllAudioGroupsSlow(), draggedGroups, parentGroupNode.group, null); - if (perform && validDrag) - { - AudioMixerGroupController parentGroup = parentGroupNode.group; - - // If insertionIndex is -1 we are dropping upon the parentNode - int insertionIndex = GetInsertionIndex(parentNode, targetNode, dragPos); - - m_owner.Controller.ReparentSelection(parentGroup, insertionIndex, draggedGroups); - m_owner.ReloadTree(); - 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) - } - return validDrag ? DragAndDropVisualMode.Move : DragAndDropVisualMode.Rejected; - } - return DragAndDropVisualMode.None; - } - - bool ValidDrag(TreeViewItem parent, List draggedInstanceIDs) - { - TreeViewItem currentParent = parent; - while (currentParent != null) - { - if (draggedInstanceIDs.Contains(currentParent.id)) - return false; - currentParent = currentParent.parent; - } - return true; - } - } - - // Datasource - - internal class AudioGroupDataSource : TreeViewDataSource - { - public AudioGroupDataSource(TreeViewController treeView, AudioMixerController controller) - : base(treeView) - { - m_Controller = controller; - } - - private void AddNodesRecursively(AudioMixerGroupController group, TreeViewItem parent, int depth) - { - var children = new List(); - for (int i = 0; i < group.children.Length; ++i) - { - int uniqueNodeID = GetUniqueNodeID(group.children[i]); - var node = new AudioMixerTreeViewNode(uniqueNodeID, depth, parent, group.children[i].name, group.children[i]); - node.parent = parent; - children.Add(node); - AddNodesRecursively(group.children[i], node, depth + 1); - } - parent.children = children; - } - - static public int GetUniqueNodeID(AudioMixerGroupController group) - { - return group.GetInstanceID(); // alternative: group.groupID.GetHashCode(); - } - - public override void FetchData() - { - if (m_Controller == null) - { - m_RootItem = null; - return; - } - - if (m_Controller.masterGroup == null) - { - Debug.LogError("The Master group is missing !!!"); - m_RootItem = null; - return; - } - - int uniqueNodeID = GetUniqueNodeID(m_Controller.masterGroup); - m_RootItem = new AudioMixerTreeViewNode(uniqueNodeID, 0, null, m_Controller.masterGroup.name, m_Controller.masterGroup); - AddNodesRecursively(m_Controller.masterGroup, m_RootItem, 1); - m_NeedRefreshRows = true; - } - - public override bool IsRenamingItemAllowed(TreeViewItem node) - { - var audioNode = node as AudioMixerTreeViewNode; - if (audioNode.group == m_Controller.masterGroup) - return false; - - return true; - } - - public AudioMixerController m_Controller; - } - - // Node GUI - - internal class AudioGroupTreeViewGUI : TreeViewGUI - { - readonly float column1Width = 20f; - readonly Texture2D k_VisibleON = EditorGUIUtility.FindTexture("VisibilityOn"); - public Action NodeWasToggled; - public AudioMixerController m_Controller = null; - - public AudioGroupTreeViewGUI(TreeViewController treeView) - : base(treeView) - { - k_BaseIndent = column1Width; - k_IconWidth = 0; - k_TopRowMargin = k_BottomRowMargin = 2f; - } - - void OpenGroupContextMenu(AudioMixerTreeViewNode audioNode, bool visible) - { - GenericMenu menu = new GenericMenu(); - - if (NodeWasToggled != null) - { - menu.AddItem(new GUIContent(visible ? "Hide group" : "Show Group"), false, () => NodeWasToggled(audioNode, !visible)); - } - menu.AddSeparator(string.Empty); - - AudioMixerGroupController[] groups; - if (m_Controller.CachedSelection.Contains(audioNode.group)) - groups = m_Controller.CachedSelection.ToArray(); - else - groups = new AudioMixerGroupController[] { audioNode.group }; - - AudioMixerColorCodes.AddColorItemsToGenericMenu(menu, groups); - menu.ShowAsContext(); - } - - override public void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool selected, bool focused) - { - Event evt = Event.current; - DoItemGUI(rowRect, row, node, selected, focused, false); - - if (m_Controller == null) - return; - - var audioNode = node as AudioMixerTreeViewNode; - if (audioNode != null) - { - bool oldSelected = m_Controller.CurrentViewContainsGroup(audioNode.group.groupID); - const float kIconSize = 16f; - - float xMargin = 3f; - Rect iconRect = new Rect(rowRect.x + xMargin, rowRect.y, kIconSize, kIconSize); - Rect iconBgRect = new Rect(iconRect.x + 1, iconRect.y + 1, iconRect.width - 2, iconRect.height - 2); - - int colorIndex = audioNode.group.userColorIndex; - if (colorIndex > 0) - EditorGUI.DrawRect(new Rect(rowRect.x, iconBgRect.y, 2, iconBgRect.height), AudioMixerColorCodes.GetColor(colorIndex)); - - EditorGUI.DrawRect(iconBgRect, new Color(0.5f, 0.5f, 0.5f, 0.2f)); - if (oldSelected) - GUI.DrawTexture(iconRect, k_VisibleON); - - Rect toggleRect = new Rect(2, rowRect.y, rowRect.height, rowRect.height); - if (evt.type == EventType.MouseUp && evt.button == 0 && toggleRect.Contains(evt.mousePosition)) - { - if (NodeWasToggled != null) - NodeWasToggled(audioNode, !oldSelected); - } - - if (evt.type == EventType.ContextClick && iconRect.Contains(evt.mousePosition)) - { - OpenGroupContextMenu(audioNode, oldSelected); - evt.Use(); - } - } - } - - protected override Texture GetIconForItem(TreeViewItem node) - { - if (node != null && node.icon != null) - return node.icon; - return null; - } - - protected override void SyncFakeItem() - { - } - - protected override void RenameEnded() - { - bool userAccepted = GetRenameOverlay().userAcceptedRename; - if (userAccepted) - { - string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name; - int instanceID = GetRenameOverlay().userData; - var audioNode = m_TreeView.FindItem(instanceID) as AudioMixerTreeViewNode; - if (audioNode != null) - { - ObjectNames.SetNameSmartWithInstanceID(instanceID, name); - foreach (var effect in audioNode.group.effects) - effect.ClearCachedDisplayName(); - m_TreeView.ReloadData(); - if (m_Controller != null) - m_Controller.OnSubAssetChanged(); - } - } - } - } - - - // TreeView - - internal class AudioMixerGroupPopupContext - { - public AudioMixerGroupPopupContext(AudioMixerController controller, AudioMixerGroupController group) - { - this.controller = controller; - this.groups = new AudioMixerGroupController[] { group }; - } - - public AudioMixerGroupPopupContext(AudioMixerController controller, AudioMixerGroupController[] groups) - { - this.controller = controller; - this.groups = groups; - } - - public AudioMixerController controller; - public AudioMixerGroupController[] groups; - } - - internal class AudioMixerGroupTreeView - { - private AudioMixerController m_Controller; - private AudioGroupDataSource m_AudioGroupTreeDataSource; - private TreeViewState m_AudioGroupTreeState; - private TreeViewController m_AudioGroupTree; - private AudioGroupTreeViewGUI m_TreeViewGUI; - private AudioMixerGroupController m_ScrollToItem; - - class Styles - { - 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."); - public GUIContent addText = EditorGUIUtility.TrTextContent("+", "Add child group"); - public Texture2D audioMixerGroupIcon = EditorGUIUtility.FindTexture(typeof(UnityEngine.Audio.AudioMixerGroup)); - } - static Styles s_Styles; - - public AudioMixerGroupTreeView(AudioMixerWindow mixerWindow, TreeViewState treeState) - { - m_AudioGroupTreeState = treeState; - - m_AudioGroupTree = new TreeViewController(mixerWindow, m_AudioGroupTreeState); - m_AudioGroupTree.deselectOnUnhandledMouseDown = false; - m_AudioGroupTree.selectionChangedCallback += OnTreeSelectionChanged; - m_AudioGroupTree.contextClickItemCallback += OnTreeViewContextClick; - m_AudioGroupTree.expandedStateChanged += SaveExpandedState; - - m_TreeViewGUI = new AudioGroupTreeViewGUI(m_AudioGroupTree); - m_TreeViewGUI.NodeWasToggled += OnNodeToggled; - - m_AudioGroupTreeDataSource = new AudioGroupDataSource(m_AudioGroupTree, m_Controller); - m_AudioGroupTree.Init(mixerWindow.position, - m_AudioGroupTreeDataSource, m_TreeViewGUI, - new AudioGroupTreeViewDragging(m_AudioGroupTree, this) - ); - m_AudioGroupTree.ReloadData(); - } - - public AudioMixerController Controller { get { return m_Controller; } } - - public AudioMixerGroupController ScrollToItem { get { return m_ScrollToItem; } } - - public void UseScrollView(bool useScrollView) - { - m_AudioGroupTree.SetUseScrollView(useScrollView); - } - - public void ReloadTreeData() - { - m_AudioGroupTree.ReloadData(); - } - - public void ReloadTree() - { - m_AudioGroupTree.ReloadData(); - if (m_Controller != null) - { - m_Controller.SanitizeGroupViews(); - m_Controller.OnSubAssetChanged(); - } - } - - public void AddChildGroupPopupCallback(object obj) - { - AudioMixerGroupPopupContext context = (AudioMixerGroupPopupContext)obj; - if (context.groups != null && context.groups.Length > 0) - AddAudioMixerGroup(context.groups[0]); - } - - public void AddSiblingGroupPopupCallback(object obj) - { - AudioMixerGroupPopupContext context = (AudioMixerGroupPopupContext)obj; - if (context.groups != null && context.groups.Length > 0) - { - var item = m_AudioGroupTree.FindItem(context.groups[0].GetInstanceID()) as AudioMixerTreeViewNode; - if (item != null) - { - var parent = item.parent as AudioMixerTreeViewNode; - AddAudioMixerGroup(parent.group); - } - } - } - - public void AddAudioMixerGroup(AudioMixerGroupController parent) - { - if (parent == null || m_Controller == null) - return; - - Undo.RecordObjects(new UnityEngine.Object[] { m_Controller, parent }, "Add Child Group"); - var newGroup = m_Controller.CreateNewGroup("New Group", true); - m_Controller.AddChildToParent(newGroup, parent); - m_Controller.AddGroupToCurrentView(newGroup); - - Selection.objects = new[] {newGroup}; - m_Controller.OnUnitySelectionChanged(); - m_AudioGroupTree.SetSelection(new int[] { newGroup.GetInstanceID() }, true); - ReloadTree(); - m_AudioGroupTree.BeginNameEditing(0f); - } - - static string PluralIfNeeded(int count) - { - return count > 1 ? "s" : ""; - } - - public void DeleteGroups(List groups, bool recordUndo) - { - foreach (AudioMixerGroupController group in groups) - { - if (group.HasDependentMixers()) - { - if (!EditorUtility.DisplayDialog("Referenced Group", "Deleted group is referenced by another AudioMixer, are you sure?", "Delete", "Cancel")) - return; - break; - } - } - - if (recordUndo) - Undo.RegisterCompleteObjectUndo(m_Controller, "Delete Group" + PluralIfNeeded(groups.Count)); - - m_Controller.DeleteGroups(groups.ToArray()); - ReloadTree(); - } - - public void DuplicateGroups(List groups, bool recordUndo) - { - if (recordUndo) - { - Undo.RecordObject(m_Controller, "Duplicate group" + PluralIfNeeded(groups.Count)); - Undo.RecordObject(m_Controller.masterGroup, ""); - } - - var duplicatedRoots = m_Controller.DuplicateGroups(groups.ToArray(), recordUndo); - if (duplicatedRoots.Count > 0) - { - ReloadTree(); - var instanceIDs = duplicatedRoots.Select(audioMixerGroup => audioMixerGroup.GetInstanceID()).ToArray(); - m_AudioGroupTree.SetSelection(instanceIDs, false); - m_AudioGroupTree.Frame(instanceIDs[instanceIDs.Length - 1], true, false); - } - } - - void DeleteGroupsPopupCallback(object obj) - { - var audioMixerGroupTreeView = (AudioMixerGroupTreeView)obj; - audioMixerGroupTreeView.DeleteGroups(GetGroupSelectionWithoutMasterGroup(), true); - } - - void DuplicateGroupPopupCallback(object obj) - { - var audioMixerGroupTreeView = (AudioMixerGroupTreeView)obj; - audioMixerGroupTreeView.DuplicateGroups(GetGroupSelectionWithoutMasterGroup(), true); - } - - void RenameGroupCallback(object obj) - { - var item = (TreeViewItem)obj; - m_AudioGroupTree.SetSelection(new int[] {item.id}, false); - m_AudioGroupTree.BeginNameEditing(0f); - } - - List GetGroupSelectionWithoutMasterGroup() - { - var items = GetAudioMixerGroupsFromNodeIDs(m_AudioGroupTree.GetSelection()); - items.Remove(m_Controller.masterGroup); - return items; - } - - public void OnTreeViewContextClick(int index) - { - var node = m_AudioGroupTree.FindItem(index); - if (node != null) - { - AudioMixerTreeViewNode mixerNode = node as AudioMixerTreeViewNode; - if (mixerNode != null && mixerNode.group != null) - { - GenericMenu pm = new GenericMenu(); - - if (!EditorApplication.isPlaying) - { - pm.AddItem(EditorGUIUtility.TrTextContent("Add child group"), false, AddChildGroupPopupCallback, new AudioMixerGroupPopupContext(m_Controller, mixerNode.group)); - if (mixerNode.group != m_Controller.masterGroup) - { - pm.AddItem(EditorGUIUtility.TrTextContent("Add sibling group"), false, AddSiblingGroupPopupCallback, new AudioMixerGroupPopupContext(m_Controller, mixerNode.group)); - pm.AddSeparator(""); - pm.AddItem(EditorGUIUtility.TrTextContent("Rename"), false, RenameGroupCallback, node); - - // Mastergroup cannot be deleted nor duplicated - var selection = GetGroupSelectionWithoutMasterGroup().ToArray(); - pm.AddItem(new GUIContent((selection.Length > 1) ? "Duplicate groups (and children)" : "Duplicate group (and children)"), false, DuplicateGroupPopupCallback, this); - pm.AddItem(new GUIContent((selection.Length > 1) ? "Remove groups (and children)" : "Remove group (and children)"), false, DeleteGroupsPopupCallback, this); - } - } - else - { - pm.AddDisabledItem(EditorGUIUtility.TrTextContent("Modifying group topology in play mode is not allowed")); - } - - pm.ShowAsContext(); - } - } - } - - void OnNodeToggled(AudioMixerTreeViewNode node, bool nodeWasEnabled) - { - var treeSelection = GetAudioMixerGroupsFromNodeIDs(m_AudioGroupTree.GetSelection()); - if (!treeSelection.Contains(node.group)) - treeSelection = new List {node.group}; - var newSelection = new List(); - var allGroups = m_Controller.GetAllAudioGroupsSlow(); - foreach (var g in allGroups) - { - bool inOldSelection = m_Controller.CurrentViewContainsGroup(g.groupID); - bool inNewSelection = treeSelection.Contains(g); - bool add = inOldSelection && !inNewSelection; - if (!inOldSelection && inNewSelection) - add = nodeWasEnabled; - if (add) - newSelection.Add(g.groupID); - } - m_Controller.SetCurrentViewVisibility(newSelection.ToArray()); - } - - List GetAudioMixerGroupsFromNodeIDs(int[] instanceIDs) - { - List newSelectedGroups = new List(); - foreach (var s in instanceIDs) - { - var node = m_AudioGroupTree.FindItem(s); - if (node != null) - { - AudioMixerTreeViewNode mixerNode = node as AudioMixerTreeViewNode; - if (mixerNode != null) - newSelectedGroups.Add(mixerNode.group); - } - } - return newSelectedGroups; - } - - public void OnTreeSelectionChanged(int[] selection) - { - var groups = GetAudioMixerGroupsFromNodeIDs(selection); - Selection.objects = groups.ToArray(); - m_Controller.OnUnitySelectionChanged(); - if (groups.Count == 1) - m_ScrollToItem = groups[0]; - InspectorWindow.RepaintAllInspectors(); - } - - public void InitSelection(bool revealSelectionAndFrameLastSelected) - { - if (m_Controller == null) - return; - - var groups = m_Controller.CachedSelection; - m_AudioGroupTree.SetSelection((from x in groups select x.GetInstanceID()).ToArray(), revealSelectionAndFrameLastSelected); - } - - public float GetTotalHeight() - { - if (m_Controller == null) - return 0f; - return m_AudioGroupTree.gui.GetTotalSize().y + AudioMixerDrawUtils.kSectionHeaderHeight; - } - - public void OnGUI(Rect rect) - { - int treeViewKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard); - - m_ScrollToItem = null; - - if (s_Styles == null) - s_Styles = new Styles(); - - m_AudioGroupTree.OnEvent(); - - Rect headerRect, contentRect; - using (new EditorGUI.DisabledScope(m_Controller == null)) - { - AudioMixerDrawUtils.DrawRegionBg(rect, out headerRect, out contentRect); - AudioMixerDrawUtils.HeaderLabel(headerRect, s_Styles.header, s_Styles.audioMixerGroupIcon); - } - - if (m_Controller != null) - { - AudioMixerGroupController parent = (m_Controller.CachedSelection.Count == 1) ? m_Controller.CachedSelection[0] : m_Controller.masterGroup; - using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) - { - if (GUI.Button(new Rect(headerRect.xMax - 15f, headerRect.y + 3f, 15f, 15f), s_Styles.addText, EditorStyles.label)) - AddAudioMixerGroup(parent); - } - - m_AudioGroupTree.OnGUI(contentRect, treeViewKeyboardControlID); - AudioMixerDrawUtils.DrawScrollDropShadow(contentRect, m_AudioGroupTree.state.scrollPos.y, m_AudioGroupTree.gui.GetTotalSize().y); - - HandleKeyboardEvents(treeViewKeyboardControlID); - HandleCommandEvents(treeViewKeyboardControlID); - } - } - - void HandleCommandEvents(int treeViewKeyboardControlID) - { - if (GUIUtility.keyboardControl != treeViewKeyboardControlID) - return; - - EventType eventType = Event.current.type; - if (eventType == EventType.ExecuteCommand || eventType == EventType.ValidateCommand) - { - bool execute = eventType == EventType.ExecuteCommand; - - if (Event.current.commandName == EventCommandNames.Delete || Event.current.commandName == EventCommandNames.SoftDelete) - { - Event.current.Use(); - if (execute) - { - DeleteGroups(GetGroupSelectionWithoutMasterGroup(), true); - GUIUtility.ExitGUI(); // Cached groups might have been deleted to so early out of event - } - } - else if (Event.current.commandName == EventCommandNames.Duplicate) - { - Event.current.Use(); - if (execute) - DuplicateGroups(GetGroupSelectionWithoutMasterGroup(), true); - } - } - } - - void HandleKeyboardEvents(int treeViewKeyboardControlID) - { - if (GUIUtility.keyboardControl != treeViewKeyboardControlID) - return; - - Event evt = Event.current; - if (evt.keyCode == KeyCode.Space && evt.type == EventType.KeyDown) - { - int[] selection = m_AudioGroupTree.GetSelection(); - if (selection.Length > 0) - { - AudioMixerTreeViewNode node = m_AudioGroupTree.FindItem(selection[0]) as AudioMixerTreeViewNode; - bool shown = m_Controller.CurrentViewContainsGroup(node.group.groupID); - OnNodeToggled(node, !shown); - evt.Use(); - } - } - } - - public void OnMixerControllerChanged(AudioMixerController controller) - { - if (m_Controller != controller) - { - m_TreeViewGUI.m_Controller = controller; - m_Controller = controller; - m_AudioGroupTreeDataSource.m_Controller = controller; - if (controller != null) - { - ReloadTree(); - InitSelection(false); - LoadExpandedState(); - m_AudioGroupTree.data.SetExpandedWithChildren(m_AudioGroupTree.data.root, true); - } - } - } - - static string GetUniqueAudioMixerName(AudioMixerController controller) - { - return "AudioMixer_" + controller.GetInstanceID(); - } - - void SaveExpandedState() - { - SessionState.SetIntArray(GetUniqueAudioMixerName(m_Controller), m_AudioGroupTreeState.expandedIDs.ToArray()); - } - - void LoadExpandedState() - { - int[] cachedExpandedState = SessionState.GetIntArray(GetUniqueAudioMixerName(m_Controller), null); - if (cachedExpandedState != null) - { - m_AudioGroupTreeState.expandedIDs = new List(cachedExpandedState); - } - else - { - // Expand whole tree. If no cached data then its the first time tree was loaded in this session - m_AudioGroupTree.state.expandedIDs = new List(); - m_AudioGroupTree.data.SetExpandedWithChildren(m_AudioGroupTree.data.root, true); - } - } - - public void EndRenaming() - { - m_AudioGroupTree.EndNameEditing(true); - } - - public void OnUndoRedoPerformed() - { - ReloadTree(); - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupViewList.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupViewList.cs deleted file mode 100644 index 7d943e6926..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerGroupViewList.cs +++ /dev/null @@ -1,248 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System; -using UnityEditorInternal; -using UnityEditor.Audio; - -namespace UnityEditor -{ - internal class AudioMixerGroupViewList - { - ReorderableListWithRenameAndScrollView m_ReorderableListWithRenameAndScrollView; - AudioMixerController m_Controller; - List m_Views; - readonly ReorderableListWithRenameAndScrollView.State m_State; - - class Styles - { - public GUIContent header = EditorGUIUtility.TrTextContent("Views", "A view is the saved visiblity state of the current Mixer Groups. Use views to setup often used combinations of Mixer Groups."); - public GUIContent addButton = new GUIContent("+"); - public Texture2D viewsIcon = EditorGUIUtility.FindTexture("AudioMixerView Icon"); - } - static Styles s_Styles; - - public AudioMixerGroupViewList(ReorderableListWithRenameAndScrollView.State state) - { - m_State = state; - } - - public void OnMixerControllerChanged(AudioMixerController controller) - { - m_Controller = controller; - RecreateListControl(); - } - - public void OnUndoRedoPerformed() - { - RecreateListControl(); - } - - public void OnEvent() - { - if (m_Controller == null) - return; - m_ReorderableListWithRenameAndScrollView.OnEvent(); - } - - public void RecreateListControl() - { - if (m_Controller == null) - return; - - m_Views = new List(m_Controller.views); - - // Ensure default view - if (m_Views.Count == 0) - { - var view = new MixerGroupView(); - view.guids = m_Controller.GetAllAudioGroupsSlow().Select(gr => gr.groupID).ToArray(); - view.name = "View"; - m_Views.Add(view); - SaveToBackend(); - } - - var reorderableList = new ReorderableList(m_Views, typeof(MixerGroupView), true, false, false, false); - reorderableList.onReorderCallback += EndDragChild; - reorderableList.elementHeight = 16; - reorderableList.headerHeight = 0; - reorderableList.footerHeight = 0; - reorderableList.showDefaultBackground = false; - reorderableList.index = m_Controller.currentViewIndex; - - if (m_Controller.currentViewIndex >= reorderableList.count) - Debug.LogError("State mismatch, currentViewIndex: " + m_Controller.currentViewIndex + ", num items: " + reorderableList.count); - - // Now extend reorderable list with scrollview and renaming functionality - m_ReorderableListWithRenameAndScrollView = new ReorderableListWithRenameAndScrollView(reorderableList, m_State); - m_ReorderableListWithRenameAndScrollView.onSelectionChanged += SelectionChanged; - m_ReorderableListWithRenameAndScrollView.onNameChangedAtIndex += NameChanged; - m_ReorderableListWithRenameAndScrollView.onDeleteItemAtIndex += Delete; - m_ReorderableListWithRenameAndScrollView.onGetNameAtIndex += GetNameOfElement; - m_ReorderableListWithRenameAndScrollView.onCustomDrawElement += CustomDrawElement; - } - - public float GetTotalHeight() - { - if (m_Controller == null) - return 0f; - return m_ReorderableListWithRenameAndScrollView.list.GetHeight() + AudioMixerDrawUtils.kSectionHeaderHeight; - } - - public void OnGUI(Rect rect) - { - if (s_Styles == null) - s_Styles = new Styles(); - - Rect headerRect, contentRect; - using (new EditorGUI.DisabledScope(m_Controller == null)) - { - AudioMixerDrawUtils.DrawRegionBg(rect, out headerRect, out contentRect); - AudioMixerDrawUtils.HeaderLabel(headerRect, s_Styles.header, s_Styles.viewsIcon); - } - - if (m_Controller != null) - { - // Ensure in-sync - if (m_ReorderableListWithRenameAndScrollView.list.index != m_Controller.currentViewIndex) - { - m_ReorderableListWithRenameAndScrollView.list.index = m_Controller.currentViewIndex; - m_ReorderableListWithRenameAndScrollView.FrameItem(m_Controller.currentViewIndex); - } - - m_ReorderableListWithRenameAndScrollView.OnGUI(contentRect); - - // Call after list to prevent id mismatch - if (GUI.Button(new Rect(headerRect.xMax - 15f, headerRect.y + 3f, 15f, 15f), s_Styles.addButton, EditorStyles.label)) - Add(); - } - } - - public void CustomDrawElement(Rect r, int index, bool isActive, bool isFocused) - { - Event evt = Event.current; - if (evt.type == EventType.MouseUp && evt.button == 1 && r.Contains(evt.mousePosition)) - { - ViewsContexttMenu.Show(r, index, this); - evt.Use(); - } - - bool isSelected = (index == m_ReorderableListWithRenameAndScrollView.list.index) && !m_ReorderableListWithRenameAndScrollView.IsRenamingIndex(index); - m_ReorderableListWithRenameAndScrollView.DrawElementText(r, index, isActive, isSelected, isFocused); - } - - void SaveToBackend() - { - m_Controller.views = m_Views.ToArray(); - } - - void LoadFromBackend() - { - m_Views.Clear(); - m_Views.AddRange(m_Controller.views); - } - - string GetNameOfElement(int index) - { - return m_Views[index].name; - } - - void Add() - { - m_Controller.CloneViewFromCurrent(); - LoadFromBackend(); - - int newSelectedIndex = m_Views.Count - 1; - m_Controller.currentViewIndex = newSelectedIndex; - m_ReorderableListWithRenameAndScrollView.BeginRename(newSelectedIndex, 0f); - } - - void Delete(int index) - { - if (m_Views.Count <= 1) - { - Debug.Log("Deleting all views is not allowed"); - return; - } - - m_Controller.DeleteView(index); - LoadFromBackend(); - } - - public void NameChanged(int index, string newName) - { - LoadFromBackend(); - MixerGroupView view = m_Views[index]; - view.name = newName; - m_Views[index] = view; - SaveToBackend(); - } - - public void SelectionChanged(int selectedIndex) - { - LoadFromBackend(); - m_Controller.SetView(selectedIndex); - } - - public void EndDragChild(ReorderableList list) - { - m_Views = m_ReorderableListWithRenameAndScrollView.list.list as List; - SaveToBackend(); - } - - void Rename(int index) - { - m_ReorderableListWithRenameAndScrollView.BeginRename(index, 0f); - } - - void DuplicateCurrentView() - { - m_Controller.CloneViewFromCurrent(); - LoadFromBackend(); - } - - internal class ViewsContexttMenu - { - class data - { - public int viewIndex; - public AudioMixerGroupViewList list; - } - - static public void Show(Rect buttonRect, int viewIndex, AudioMixerGroupViewList list) - { - var menu = new GenericMenu(); - data input = new data() { viewIndex = viewIndex, list = list }; - menu.AddItem(EditorGUIUtility.TrTextContent("Rename"), false, Rename, input); - menu.AddItem(EditorGUIUtility.TrTextContent("Duplicate"), false, Duplicate, input); - menu.AddItem(EditorGUIUtility.TrTextContent("Delete"), false, Delete, input); - - menu.DropDown(buttonRect); - } - - static void Rename(object userData) - { - data input = userData as data; - input.list.Rename(input.viewIndex); - } - - static void Duplicate(object userData) - { - data input = userData as data; - input.list.m_Controller.currentViewIndex = input.viewIndex; - input.list.DuplicateCurrentView(); - } - - static void Delete(object userData) - { - data input = userData as data; - input.list.Delete(input.viewIndex); - } - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerSelection.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerSelection.cs deleted file mode 100644 index 9780288e07..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerSelection.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditor.Audio; - -namespace UnityEditor -{ - internal class AudioMixerSelection - { - public AudioMixerSelection(AudioMixerController controller) - { - m_Controller = controller; - ChannelStripSelection = new List(); - SyncToUnitySelection(); - } - - private AudioMixerController m_Controller; - public List ChannelStripSelection { get; private set; } - - // Channelstrip selection - // We rely on SyncToUnitySelection is being called after setting Selection.objects through AudioWindow::OnSelectionChange () - public void SyncToUnitySelection() - { - if (m_Controller != null) - RefreshCachedChannelStripSelection(); - } - - public void SetChannelStrips(List newSelection) - { - Selection.objects = newSelection.ToArray(); - //Debug.Log("SetChannelStrips " + DebugUtils.ListToString(Selection.instanceIDs)); - } - - public void SetSingleChannelStrip(AudioMixerGroupController group) - { - Selection.objects = new[] {group}; - //Debug.Log("SetSingleChannelStrip " + DebugUtils.ListToString(Selection.instanceIDs)); - } - - public void ToggleChannelStrip(AudioMixerGroupController group) - { - var selection = new List(Selection.objects); - if (selection.Contains(group)) - selection.Remove(group); - else - selection.Add(group); - Selection.objects = selection.ToArray(); - } - - public void ClearChannelStrips() - { - Selection.objects = new Object[0]; - //Debug.Log("ClearChannelStrips " + DebugUtils.ListToString(Selection.instanceIDs)); - } - - public bool HasSingleChannelStripSelection() - { - return ChannelStripSelection.Count == 1; - } - - private void RefreshCachedChannelStripSelection() - { - var selected = Selection.GetFiltered(typeof(AudioMixerGroupController), SelectionMode.Deep); - ChannelStripSelection = new List(); - List allGroups = m_Controller.GetAllAudioGroupsSlow(); - - foreach (var g in allGroups) - if (selected.Contains(g)) - ChannelStripSelection.Add(g); - } - - // Call this after making changes to the group topology (when removing groups) - public void Sanitize() - { - RefreshCachedChannelStripSelection(); - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerSnapshotPopup.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerSnapshotPopup.cs deleted file mode 100644 index bb6b5658c8..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerSnapshotPopup.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{/* - internal partial class AudioMixerSnapshotPopup : IPopupWindowContent - { - internal static void SnapshotPopup (GameViewSizeGroupType groupType, int selectedIndex, System.Action itemClickedCallback, GUIStyle style, params GUILayoutOption[] options) - { - Rect buttonRect = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - EditorGUI.GameViewSizePopup(buttonRect, groupType, selectedIndex, itemClickedCallback, style); - } - - public static void ToolbarButton () - { - - } - - readonly AudioMixerSnapshotListView m_SnapshotListView = new AudioMixerSnapshotListView(); - - public void OnGUI (EditorWindow caller, Rect rect) - { - m_SnapshotListView.OnGUI (rect); - } - - public Vector2 GetWindowSize () - { - return new Vector2 (300, 600); - } - - public void OnDisable () - { - - - }}*/ -} // namespace diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerSnapshotView.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerSnapshotView.cs deleted file mode 100644 index 9e64551c8a..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerSnapshotView.cs +++ /dev/null @@ -1,299 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System; -using UnityEditorInternal; -using UnityEditor.Audio; - -namespace UnityEditor -{ - internal class AudioMixerSnapshotListView - { - private ReorderableListWithRenameAndScrollView m_ReorderableListWithRenameAndScrollView; - private AudioMixerController m_Controller; - List m_Snapshots; - ReorderableListWithRenameAndScrollView.State m_State; - - class Styles - { - public GUIContent starIcon = new GUIContent(EditorGUIUtility.FindTexture("Favorite"), "Start snapshot"); - 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."); - public GUIContent addButton = new GUIContent("+"); - public Texture2D snapshotsIcon = EditorGUIUtility.FindTexture(typeof(UnityEngine.Audio.AudioMixerSnapshot)); - } - static Styles s_Styles; - - - public AudioMixerSnapshotListView(ReorderableListWithRenameAndScrollView.State state) - { - m_State = state; - } - - public void OnMixerControllerChanged(AudioMixerController controller) - { - m_Controller = controller; - RecreateListControl(); - } - - int GetSnapshotIndex(AudioMixerSnapshotController snapshot) - { - for (int i = 0; i < m_Snapshots.Count; i++) - { - if (m_Snapshots[i] == snapshot) - return i; - } - - return 0; - } - - void RecreateListControl() - { - if (m_Controller == null) - return; - - m_Snapshots = new List(m_Controller.snapshots); - - ReorderableList reorderableList = new ReorderableList(m_Snapshots, typeof(AudioMixerSnapshotController), true, false, false, false); - reorderableList.onReorderCallback = EndDragChild; - reorderableList.elementHeight = 16f; - reorderableList.headerHeight = 0f; - reorderableList.footerHeight = 0f; - reorderableList.showDefaultBackground = false; - reorderableList.index = GetSnapshotIndex(m_Controller.TargetSnapshot); - - m_ReorderableListWithRenameAndScrollView = new ReorderableListWithRenameAndScrollView(reorderableList, m_State); - m_ReorderableListWithRenameAndScrollView.onSelectionChanged += SelectionChanged; - m_ReorderableListWithRenameAndScrollView.onNameChangedAtIndex += NameChanged; - m_ReorderableListWithRenameAndScrollView.onDeleteItemAtIndex += Delete; - m_ReorderableListWithRenameAndScrollView.onGetNameAtIndex += GetNameOfElement; - m_ReorderableListWithRenameAndScrollView.onCustomDrawElement += CustomDrawElement; - } - - void SaveToBackend() - { - m_Controller.snapshots = m_Snapshots.ToArray(); - - m_Controller.OnSubAssetChanged(); - } - - public void LoadFromBackend() - { - if (m_Controller == null) - return; - - m_Snapshots.Clear(); - m_Snapshots.AddRange(m_Controller.snapshots); - } - - public void OnEvent() - { - if (m_Controller == null) - return; - m_ReorderableListWithRenameAndScrollView.OnEvent(); - } - - public void CustomDrawElement(Rect r, int index, bool isActive, bool isFocused) - { - Event evt = Event.current; - if (evt.type == EventType.MouseUp && evt.button == 1 && r.Contains(evt.mousePosition)) - { - SnapshotMenu.Show(r, m_Snapshots[index], this); - evt.Use(); - } - - const float iconSize = 14f; - const float spacing = 5f; - - bool isSelected = (index == m_ReorderableListWithRenameAndScrollView.list.index) && !m_ReorderableListWithRenameAndScrollView.IsRenamingIndex(index); - - // Text - r.width -= iconSize + spacing; - m_ReorderableListWithRenameAndScrollView.DrawElementText(r, index, isActive, isSelected, isFocused); - - // Startup icon - if (m_Controller.startSnapshot == m_Snapshots[index]) - { - r.x = r.xMax + spacing + 5f; - r.y = r.y + (r.height - iconSize) / 2; - r.width = r.height = iconSize; - GUI.Label(r, s_Styles.starIcon, GUIStyle.none); - } - } - - public float GetTotalHeight() - { - if (m_Controller == null) - return 0f; - return m_ReorderableListWithRenameAndScrollView.list.GetHeight() + AudioMixerDrawUtils.kSectionHeaderHeight; - } - - public void OnGUI(Rect rect) - { - if (s_Styles == null) - s_Styles = new Styles(); - - Rect headerRect, contentRect; - using (new EditorGUI.DisabledScope(m_Controller == null)) - { - AudioMixerDrawUtils.DrawRegionBg(rect, out headerRect, out contentRect); - AudioMixerDrawUtils.HeaderLabel(headerRect, s_Styles.header, s_Styles.snapshotsIcon); - } - - if (m_Controller != null) - { - // Ensure gui is in-sync with backend (TargetSnapShotIndex can be changed anytime from the backend) - int targetIndex = GetSnapshotIndex(m_Controller.TargetSnapshot); - if (targetIndex != m_ReorderableListWithRenameAndScrollView.list.index) - { - m_ReorderableListWithRenameAndScrollView.list.index = targetIndex; - m_ReorderableListWithRenameAndScrollView.FrameItem(targetIndex); - } - m_ReorderableListWithRenameAndScrollView.OnGUI(contentRect); - - if (GUI.Button(new Rect(headerRect.xMax - 15f, headerRect.y + 3f, 15f, 15f), s_Styles.addButton, EditorStyles.label)) - Add(); - } - } - - public void SelectionChanged(int index) - { - //For some UI reason, selecting some region just below the last element of the - //re-orderable list will cause a selection index greater than is available. - if (index >= m_Snapshots.Count) - index = m_Snapshots.Count - 1; - - m_Controller.TargetSnapshot = m_Snapshots[index]; - UpdateViews(); - } - - string GetNameOfElement(int index) - { - return m_Snapshots[index].name; - } - - public void NameChanged(int index, string newName) - { - m_Snapshots[index].name = newName; - SaveToBackend(); - } - - void DuplicateCurrentSnapshot() - { - Undo.RecordObject(m_Controller, "Duplicate current snapshot"); - m_Controller.CloneNewSnapshotFromTarget(true); - LoadFromBackend(); - UpdateViews(); - } - - void Add() - { - Undo.RecordObject(m_Controller, "Add new snapshot"); - m_Controller.CloneNewSnapshotFromTarget(true); - LoadFromBackend(); - Rename(m_Controller.TargetSnapshot); - UpdateViews(); - } - - void DeleteSnapshot(AudioMixerSnapshotController snapshot) - { - AudioMixerSnapshotController[] snapshots = m_Controller.snapshots; - if (snapshots.Length <= 1) - { - Debug.Log("You must have at least 1 snapshot in an AudioMixer."); - return; - } - - m_Controller.RemoveSnapshot(snapshot); - LoadFromBackend(); - m_ReorderableListWithRenameAndScrollView.list.index = GetSnapshotIndex(m_Controller.TargetSnapshot); - UpdateViews(); - } - - void Delete(int index) - { - DeleteSnapshot(m_Snapshots[index]); - } - - public void EndDragChild(ReorderableList list) - { - m_Snapshots = m_ReorderableListWithRenameAndScrollView.list.list as List; - SaveToBackend(); - } - - private void UpdateViews() - { - AudioMixerWindow mixerWindow = (AudioMixerWindow)WindowLayout.FindEditorWindowOfType(typeof(AudioMixerWindow)); - if (mixerWindow != null) - mixerWindow.Repaint(); - - InspectorWindow.RepaintAllInspectors(); - } - - void SetAsStartupSnapshot(AudioMixerSnapshotController snapshot) - { - Undo.RecordObject(m_Controller, "Set start snapshot"); - m_Controller.startSnapshot = snapshot; - } - - void Rename(AudioMixerSnapshotController snapshot) - { - m_ReorderableListWithRenameAndScrollView.BeginRename(GetSnapshotIndex(snapshot), 0f); - } - - internal class SnapshotMenu - { - class data - { - public AudioMixerSnapshotController snapshot; - public AudioMixerSnapshotListView list; - } - - static public void Show(Rect buttonRect, AudioMixerSnapshotController snapshot, AudioMixerSnapshotListView list) - { - var menu = new GenericMenu(); - data input = new data() { snapshot = snapshot, list = list }; - menu.AddItem(EditorGUIUtility.TrTextContent("Set as start Snapshot"), false, SetAsStartupSnapshot, input); - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Rename"), false, Rename, input); - menu.AddItem(EditorGUIUtility.TrTextContent("Duplicate"), false, Duplicate, input); - menu.AddItem(EditorGUIUtility.TrTextContent("Delete"), false, Delete, input); - - menu.DropDown(buttonRect); - } - - static void SetAsStartupSnapshot(object userData) - { - data input = userData as data; - input.list.SetAsStartupSnapshot(input.snapshot); - } - - static void Rename(object userData) - { - data input = userData as data; - input.list.Rename(input.snapshot); - } - - static void Duplicate(object userData) - { - data input = userData as data; - input.list.DuplicateCurrentSnapshot(); - } - - static void Delete(object userData) - { - data input = userData as data; - input.list.DeleteSnapshot(input.snapshot); - } - } - - public void OnUndoRedoPerformed() - { - LoadFromBackend(); - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerUtility.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerUtility.cs deleted file mode 100644 index c837ea7345..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerUtility.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.Audio; - -namespace UnityEditor -{ - internal class AudioMixerUtility - { - static public void RepaintAudioMixerAndInspectors() - { - InspectorWindow.RepaintAllInspectors(); - AudioMixerWindow.RepaintAudioMixerWindow(); - } - - public class VisitorFetchInstanceIDs - { - public List instanceIDs = new List(); - public void Visitor(AudioMixerGroupController group) - { - instanceIDs.Add(group.GetInstanceID()); - } - } - - public static void VisitGroupsRecursivly(AudioMixerGroupController group, Action visitorCallback) - { - foreach (var child in group.children) - VisitGroupsRecursivly(child, visitorCallback); - - if (visitorCallback != null) - visitorCallback(group); - } - } -} -// namespace diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs deleted file mode 100644 index 1317daf679..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs +++ /dev/null @@ -1,809 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using System; -using UnityEditorInternal; -using UnityEditor.Audio; -using UnityEditor.IMGUI.Controls; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Audio Mixer", icon = "Audio Mixer")] - internal class AudioMixerWindow : EditorWindow, IHasCustomMenu - { - static AudioMixerWindow s_Instance; - - static string kAudioMixerUseRMSMetering = "AudioMixerUseRMSMetering"; - static string kAudioMixerUseHorzLayout = "AudioMixerUseHorzLayout"; - - enum SectionType - { - MixerTree, - GroupTree, - ViewList, - SnapshotList - }; - - public enum LayoutMode - { - Uninitialized = -1, - Horizontal = 0, - Vertical = 1 - } - - [Serializable] - class Layout - { - [SerializeField] - public SplitterState m_VerticalSplitter; - [SerializeField] - public SplitterState m_HorizontalSplitter; - } - - [NonSerialized] - bool m_Initialized; - - AudioMixerController m_Controller; - List m_AllControllers; - - AudioMixerChannelStripView.State m_ChannelStripViewState; - AudioMixerChannelStripView m_ChannelStripView; - TreeViewState m_AudioGroupTreeState; - AudioMixerGroupTreeView m_GroupTree; - [SerializeField] TreeViewStateWithAssetUtility m_MixersTreeState; // Use SerializeField so it is stored in the layout file (persistant) - AudioMixersTreeView m_MixersTree; - ReorderableListWithRenameAndScrollView.State m_ViewsState; - AudioMixerGroupViewList m_GroupViews; - ReorderableListWithRenameAndScrollView.State m_SnapshotState; - AudioMixerSnapshotListView m_SnapshotListView; - - [SerializeField] - Layout m_LayoutStripsOnTop; - [SerializeField] - Layout m_LayoutStripsOnRight; - [SerializeField] - SectionType[] m_SectionOrder = { SectionType.MixerTree, SectionType.SnapshotList, SectionType.GroupTree, SectionType.ViewList }; // default order - - [SerializeField] - LayoutMode m_LayoutMode = LayoutMode.Uninitialized; - [SerializeField] - bool m_SortGroupsAlphabetically = false; - [SerializeField] - bool m_ShowReferencedBuses = true; - [SerializeField] - bool m_ShowBusConnections = false; - [SerializeField] - bool m_ShowBusConnectionsOfSelection = false; - - Vector2 m_SectionsScrollPosition = Vector2.zero; - int m_RepaintCounter = 2; - Vector2 m_LastSize; - bool m_GroupsRenderedAboveSections = true; - - [NonSerialized] - bool m_ShowDeveloperOverlays = false; - - readonly TickTimerHelper m_Ticker = new TickTimerHelper(1.0 / 20.0); - - public AudioMixerController controller { get { return m_Controller; } } - - LayoutMode layoutMode - { - get - { - return m_LayoutMode; - } - set - { - m_LayoutMode = value; - m_RepaintCounter = 2; - EditorPrefs.SetBool(kAudioMixerUseHorzLayout, m_LayoutMode == LayoutMode.Horizontal); - } - } - - class GUIContents - { - public GUIContent rms; - public GUIContent editSnapShots; - public GUIContent infoText; - public GUIContent selectAudioMixer; - public GUIContent output; - public GUIStyle toolbarObjectField = new GUIStyle("ShurikenObjectField"); - public GUIStyle toolbarLabel = new GUIStyle(EditorStyles.miniLabel); - public GUIStyle mixerHeader = new GUIStyle(EditorStyles.largeLabel); - - public GUIContents() - { - rms = EditorGUIUtility.TrTextContent("RMS", "Switches between RMS (Root Mean Square) metering and peak metering. RMS is closer to the energy level and perceived loudness of the sound (hence lower than the peak meter), while peak-metering is useful for monitoring spikes in the signal that can cause clipping."); - editSnapShots = EditorGUIUtility.TrTextContent("Edit in Play Mode", "Edit in playmode and your changes are automatically saved. Note when editting is disabled then live values are shown.", EditorGUIUtility.IconContent("Animation.Record", "|Are scene and inspector changes recorded into the animation curves?").image); - infoText = EditorGUIUtility.TrTextContent("Create an AudioMixer asset from the Project Browser to get started"); - selectAudioMixer = new GUIContent("", "Select an Audio Mixer"); - output = EditorGUIUtility.TrTextContent("Output", "Select an Audio Mixer Group from another Audio Mixer to output to. If 'None' is selected then output is routed directly to the Audio Listener."); - toolbarLabel.alignment = TextAnchor.MiddleLeft; - toolbarObjectField.normal.textColor = toolbarLabel.normal.textColor; - - mixerHeader.fontStyle = FontStyle.Bold; - mixerHeader.fontSize = 17; - mixerHeader.margin = new RectOffset(); - mixerHeader.padding = new RectOffset(); - mixerHeader.alignment = TextAnchor.MiddleLeft; - if (!EditorGUIUtility.isProSkin) - mixerHeader.normal.textColor = new Color(0.4f, 0.4f, 0.4f, 1.0f); - else - mixerHeader.normal.textColor = new Color(0.7f, 0.7f, 0.7f, 1.0f); - } - } - private static GUIContents s_GuiContents; - - class AudioMixerPostprocessor : AssetPostprocessor - { - static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPath) - { - if (s_Instance != null) - { - bool anyMixers = importedAssets.Any(val => val.EndsWith(".mixer")); - anyMixers |= deletedAssets.Any(val => val.EndsWith(".mixer")); - anyMixers |= movedAssets.Any(val => val.EndsWith(".mixer")); - anyMixers |= movedFromPath.Any(val => val.EndsWith(".mixer")); - - if (anyMixers) - s_Instance.UpdateAfterAssetChange(); - } - } - } - - void UpdateAfterAssetChange() - { - if (m_Controller == null) - return; - - m_AllControllers = FindAllAudioMixerControllers(); - - m_Controller.SanitizeGroupViews(); - m_Controller.OnUnitySelectionChanged(); - - if (m_GroupTree != null) - m_GroupTree.ReloadTreeData(); - - if (m_GroupViews != null) - m_GroupViews.RecreateListControl(); - - if (m_SnapshotListView != null) - m_SnapshotListView.LoadFromBackend(); - - if (m_MixersTree != null) - m_MixersTree.ReloadTree(); - - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - - [RequiredByNativeCode] - public static void CreateAudioMixerWindow() - { - var win = GetWindow(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 - - if (win.m_Pos.width < 400f) - win.m_Pos = new Rect(win.m_Pos.x, win.m_Pos.y, 800, 450f); // Set default size if window is small - } - - public static void RepaintAudioMixerWindow() - { - if (s_Instance != null) - s_Instance.Repaint(); - } - - void Init() - { - if (m_Initialized) - return; - - if (m_LayoutStripsOnTop == null) - m_LayoutStripsOnTop = new Layout(); - - if (m_LayoutStripsOnTop.m_VerticalSplitter == null || m_LayoutStripsOnTop.m_VerticalSplitter.realSizes.Length != 2) - { - m_LayoutStripsOnTop.m_VerticalSplitter = new SplitterState(new int[] { 65, 35 }, new int[] { 85, 105 }, null); - } - - if (m_LayoutStripsOnTop.m_HorizontalSplitter == null || m_LayoutStripsOnTop.m_HorizontalSplitter.realSizes.Length != 4) - m_LayoutStripsOnTop.m_HorizontalSplitter = new SplitterState(new int[] { 60, 60, 60, 60 }, new int[] { 85, 85, 85, 85 }, null); - - if (m_LayoutStripsOnRight == null) - m_LayoutStripsOnRight = new Layout(); - - if (m_LayoutStripsOnRight.m_HorizontalSplitter == null || m_LayoutStripsOnRight.m_HorizontalSplitter.realSizes.Length != 2) - m_LayoutStripsOnRight.m_HorizontalSplitter = new SplitterState(new int[] { 30, 70 }, new int[] { 160, 160 }, null); - - if (m_LayoutStripsOnRight.m_VerticalSplitter == null || m_LayoutStripsOnRight.m_VerticalSplitter.realSizes.Length != 4) - m_LayoutStripsOnRight.m_VerticalSplitter = new SplitterState(new int[] { 60, 60, 60, 60 }, new int[] { 100, 85, 85, 85 }, null); - - if (m_AudioGroupTreeState == null) - m_AudioGroupTreeState = new TreeViewState(); - m_GroupTree = new AudioMixerGroupTreeView(this, m_AudioGroupTreeState); - - if (m_MixersTreeState == null) - m_MixersTreeState = new TreeViewStateWithAssetUtility(); - m_MixersTree = new AudioMixersTreeView(this, m_MixersTreeState, GetAllControllers); - - if (m_ViewsState == null) - m_ViewsState = new ReorderableListWithRenameAndScrollView.State(); - m_GroupViews = new AudioMixerGroupViewList(m_ViewsState); - - if (m_SnapshotState == null) - m_SnapshotState = new ReorderableListWithRenameAndScrollView.State(); - m_SnapshotListView = new AudioMixerSnapshotListView(m_SnapshotState); - - if (m_ChannelStripViewState == null) - m_ChannelStripViewState = new AudioMixerChannelStripView.State(); - m_ChannelStripView = new AudioMixerChannelStripView(m_ChannelStripViewState); - - OnMixerControllerChanged(); - - m_Initialized = true; - } - - List GetAllControllers() - { - return m_AllControllers; - } - - static List FindAllAudioMixerControllers() - { - var result = new List(); - var prop = new HierarchyProperty(HierarchyType.Assets); - prop.SetSearchFilter(new SearchFilter() { classNames = new[] { "AudioMixerController" } }); - while (prop.Next(null)) - { - var controller = prop.pptrValue as AudioMixerController; - if (controller) - result.Add(controller); - } - return result; - } - - public void Awake() - { - m_AllControllers = FindAllAudioMixerControllers(); - - if (m_MixersTreeState != null) - { - // Clear state that are serialized in the layout file that should not survive closing/starting Unity - m_MixersTreeState.OnAwake(); - m_MixersTreeState.selectedIDs = new List(); - } - } - - public void OnEnable() - { - if (m_LayoutMode == LayoutMode.Uninitialized) - { - // We use vertical layout as default as it is the most compact layout - m_LayoutMode = EditorPrefs.GetBool(kAudioMixerUseHorzLayout) ? LayoutMode.Horizontal : LayoutMode.Vertical; - } - titleContent = GetLocalizedTitleContent(); - - s_Instance = this; - - Undo.undoRedoPerformed += UndoRedoPerformed; - EditorApplication.pauseStateChanged += OnPauseStateChanged; - EditorApplication.playModeStateChanged += OnPlayModeStateChanged; - EditorApplication.projectChanged += OnProjectChanged; - } - - public void OnDisable() - { - EditorApplication.pauseStateChanged -= OnPauseStateChanged; - EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; - Undo.undoRedoPerformed -= UndoRedoPerformed; - EditorApplication.projectChanged -= OnProjectChanged; - } - - void OnPauseStateChanged(PauseState state) - { - OnPauseOrPlayModeStateChanged(); - } - - void OnPlayModeStateChanged(PlayModeStateChange state) - { - OnPauseOrPlayModeStateChanged(); - } - - void OnPauseOrPlayModeStateChanged() - { - m_Ticker.Reset(); // ensures immediate tick on play mode change - if (m_Controller != null) - { - Repaint(); - } - - EndRenaming(); - } - - void OnLostFocus() - { - EndRenaming(); - } - - void EndRenaming() - { - if (m_GroupTree != null) - m_GroupTree.EndRenaming(); - - if (m_MixersTree != null) - m_MixersTree.EndRenaming(); - } - - public void UndoRedoPerformed() - { - if (m_Controller == null) - return; - - // Undo may have deleted one of the selected groups - m_Controller.OnSubAssetChanged(); - m_Controller.SanitizeGroupViews(); - m_Controller.OnUnitySelectionChanged(); - - if (m_GroupTree != null) - m_GroupTree.OnUndoRedoPerformed(); - - if (m_GroupViews != null) - m_GroupViews.OnUndoRedoPerformed(); - - if (m_SnapshotListView != null) - m_SnapshotListView.OnUndoRedoPerformed(); - - if (m_MixersTree != null) - m_MixersTree.OnUndoRedoPerformed(); - - AudioMixerUtility.RepaintAudioMixerAndInspectors(); - } - - void OnMixerControllerChanged() - { - if (m_Controller) - m_Controller.ClearEventHandlers(); - - m_MixersTree.OnMixerControllerChanged(m_Controller); - m_GroupTree.OnMixerControllerChanged(m_Controller); - m_GroupViews.OnMixerControllerChanged(m_Controller); - m_ChannelStripView.OnMixerControllerChanged(m_Controller); - m_SnapshotListView.OnMixerControllerChanged(m_Controller); - - if (m_Controller) - m_Controller.ForceSetView(m_Controller.currentViewIndex); - } - - void OnProjectChanged() - { - if (m_MixersTree == null) - Init(); - - m_AllControllers = FindAllAudioMixerControllers(); - m_MixersTree.ReloadTree(); - } - - // Called from C++ - public void Update() - { - if (m_Ticker.DoTick()) - { - if (EditorApplication.isPlaying || (m_ChannelStripView != null && m_ChannelStripView.requiresRepaint)) - Repaint(); - } - } - - void DetectControllerChange() - { - AudioMixerController oldController = m_Controller; - if (Selection.activeObject is AudioMixerController) - m_Controller = Selection.activeObject as AudioMixerController; - if (m_Controller != oldController) - { - OnMixerControllerChanged(); - } - } - - // Called from C++ - void OnSelectionChange() - { - if (m_Controller != null) - m_Controller.OnUnitySelectionChanged(); - - if (m_GroupTree != null) - m_GroupTree.InitSelection(true); - - Repaint(); - } - - Dictionary GetEffectMap(List allGroups) - { - var effectMap = new Dictionary(); - foreach (var g in allGroups) - foreach (var e in g.effects) - effectMap[e] = g; - return effectMap; - } - - void DoToolbar() - { - EditorGUILayout.BeginHorizontal(EditorStyles.toolbar, GUILayout.Height(EditorGUI.kWindowToolbarHeight)); - GUILayout.FlexibleSpace(); - if (m_Controller != null) - { - if (Application.isPlaying) - { - Color orgColor = GUI.backgroundColor; - if (AudioSettings.editingInPlaymode) - GUI.backgroundColor = AnimationMode.animatedPropertyColor; - - EditorGUI.BeginChangeCheck(); - AudioSettings.editingInPlaymode = GUILayout.Toggle(AudioSettings.editingInPlaymode, s_GuiContents.editSnapShots, EditorStyles.toolbarButton); - if (EditorGUI.EndChangeCheck()) - InspectorWindow.RepaintAllInspectors(); - - GUI.backgroundColor = orgColor; - } - GUILayout.FlexibleSpace(); - - AudioMixerExposedParametersPopup.Popup(m_Controller, EditorStyles.toolbarPopup); - } - EditorGUILayout.EndHorizontal(); - } - - void RepaintIfNeeded() - { - if (m_RepaintCounter > 0) - { - if (Event.current.type == EventType.Repaint) - { - m_RepaintCounter--; - //Debug.Log ("Repainting (left: " + m_RepaintCounter + ")"); - } - Repaint(); - } - } - - public void OnGUI() - { - Init(); - - if (s_GuiContents == null) - s_GuiContents = new GUIContents(); - AudioMixerDrawUtils.InitStyles(); - - DetectControllerChange(); - - m_GroupViews.OnEvent(); - m_SnapshotListView.OnEvent(); - - DoToolbar(); - - List allGroups; - if (m_Controller != null) - allGroups = m_Controller.GetAllAudioGroupsSlow(); - else - allGroups = new List(); - - var effectMap = GetEffectMap(allGroups); - - m_GroupTree.UseScrollView(m_LayoutMode == LayoutMode.Horizontal); - - if (m_LayoutMode == LayoutMode.Horizontal) - LayoutWithStripsOnTop(allGroups, effectMap); - else - LayoutWithStripsOnRightSideOneScrollBar(allGroups, effectMap); - - // Ensure valid layout after maximizing window - if (m_LastSize.x != position.width || m_LastSize.y != position.height) - { - m_RepaintCounter = 2; - m_LastSize = new Vector2(position.width, position.height); - } - - RepaintIfNeeded(); - } - - void LayoutWithStripsOnRightSideOneScrollBar(List allGroups, Dictionary effectMap) - { - // Do layouting - SplitterState horizontalState = m_LayoutStripsOnRight.m_HorizontalSplitter; - SplitterGUILayout.BeginHorizontalSplit(horizontalState, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - SplitterGUILayout.EndHorizontalSplit(); - - float column1Width = horizontalState.realSizes[0]; - float column2Width = position.width - column1Width; - Rect column1Rect = new Rect(0, EditorGUI.kWindowToolbarHeight, column1Width, position.height - EditorGUI.kWindowToolbarHeight); - Rect column2Rect = new Rect(column1Width, EditorGUI.kWindowToolbarHeight, column2Width, column1Rect.height); - - // Column1 - - // Background color for mixertree and views (if needed) - if (EditorGUIUtility.isProSkin) - EditorGUI.DrawRect(column1Rect, EditorGUIUtility.isProSkin ? new Color(0.19f, 0.19f, 0.19f) : new Color(0.6f, 0.6f, 0.6f, 0f)); - - // Rects for sections - float spacing = AudioMixerDrawUtils.kSpaceBetweenSections; - Rect[] sectionRects = new Rect[m_SectionOrder.Length]; - const float xPos = 0f; - float yPos = 0f; - for (int i = 0; i < m_SectionOrder.Length; i++) - { - yPos += spacing; - if (i > 0) - yPos += sectionRects[i - 1].height; - sectionRects[i] = new Rect(xPos, yPos, column1Rect.width, GetHeightOfSection(m_SectionOrder[i])); - - // Adjust for left and right margins - const float margin = 4f; - sectionRects[i].x += margin; - sectionRects[i].width -= margin * 2; - } - Rect contentRect = new Rect(0, 0, 1, sectionRects.Last().yMax); - - // Adjust for scrollbar - if (contentRect.height > column1Rect.height) - { - for (int i = 0; i < sectionRects.Length; i++) - sectionRects[i].width -= 14; - } - - // Scroll view - m_SectionsScrollPosition = GUI.BeginScrollView(column1Rect, m_SectionsScrollPosition, contentRect); - DoSections(column1Rect, sectionRects, m_SectionOrder); - GUI.EndScrollView(); - - // Column2 - m_ChannelStripView.OnGUI(column2Rect, m_ShowReferencedBuses, m_ShowBusConnections, m_ShowBusConnectionsOfSelection, allGroups, effectMap, m_SortGroupsAlphabetically, m_ShowDeveloperOverlays, m_GroupTree.ScrollToItem); - - // Vertical line (split) - 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)); - } - - void LayoutWithStripsOnTop(List allGroups, Dictionary effectMap) - { - // Do layouting - SplitterState horizontalState = m_LayoutStripsOnTop.m_HorizontalSplitter; - SplitterState verticalState = m_LayoutStripsOnTop.m_VerticalSplitter; - - SplitterGUILayout.BeginVerticalSplit(verticalState, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - if (m_GroupsRenderedAboveSections) - { - GUILayout.BeginVertical(); - GUILayout.EndVertical(); - } - SplitterGUILayout.BeginHorizontalSplit(horizontalState, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - if (!m_GroupsRenderedAboveSections) - { - GUILayout.BeginVertical(); - GUILayout.EndVertical(); - } - SplitterGUILayout.EndHorizontalSplit(); - SplitterGUILayout.EndVerticalSplit(); - - float channelStripYPos = m_GroupsRenderedAboveSections ? EditorGUI.kWindowToolbarHeight : EditorGUI.kWindowToolbarHeight + verticalState.realSizes[0]; - float channelStripHeight = m_GroupsRenderedAboveSections ? verticalState.realSizes[0] : verticalState.realSizes[1]; - - float sectionsYPos = !m_GroupsRenderedAboveSections ? EditorGUI.kWindowToolbarHeight : EditorGUI.kWindowToolbarHeight + verticalState.realSizes[0]; - float sectionsHeight = !m_GroupsRenderedAboveSections ? verticalState.realSizes[0] : verticalState.realSizes[1]; - - Rect channelStripViewRect = new Rect(0, channelStripYPos, position.width, channelStripHeight); - Rect totalRectOfSections = new Rect(0, channelStripViewRect.yMax, position.width, position.height - channelStripViewRect.height); - - // Rects for sections - Rect[] sectionRects = new Rect[m_SectionOrder.Length]; - const float spaceFromBottom = 12f; - for (int i = 0; i < sectionRects.Length; i++) - { - float xPos = (i > 0) ? sectionRects[i - 1].xMax : 0f; - sectionRects[i] = new Rect(xPos, sectionsYPos, horizontalState.realSizes[i], sectionsHeight - spaceFromBottom); - } - - // Spacing between lists - const float halfSpaceBetween = 4f; - sectionRects[0].x += 2 * halfSpaceBetween; - sectionRects[0].width -= 3 * halfSpaceBetween; - sectionRects[sectionRects.Length - 1].x += halfSpaceBetween; - sectionRects[sectionRects.Length - 1].width -= 3 * halfSpaceBetween; - for (int i = 1; i < sectionRects.Length - 1; i++) - { - sectionRects[i].x += halfSpaceBetween; - sectionRects[i].width -= halfSpaceBetween * 2; - } - - // Do content - DoSections(totalRectOfSections, sectionRects, m_SectionOrder); - m_ChannelStripView.OnGUI(channelStripViewRect, m_ShowReferencedBuses, m_ShowBusConnections, m_ShowBusConnectionsOfSelection, allGroups, effectMap, m_SortGroupsAlphabetically, m_ShowDeveloperOverlays, m_GroupTree.ScrollToItem); - - // Horizontal line (split) - EditorGUI.DrawRect(new Rect(0, EditorGUI.kWindowToolbarHeight + verticalState.realSizes[0] - 1, position.width, 1), new Color(0f, 0f, 0f, 0.4f)); - } - - float GetHeightOfSection(SectionType sectionType) - { - switch (sectionType) - { - case SectionType.MixerTree: return m_MixersTree.GetTotalHeight(); - case SectionType.SnapshotList: return m_SnapshotListView.GetTotalHeight(); - case SectionType.GroupTree: return m_GroupTree.GetTotalHeight(); - case SectionType.ViewList: return m_GroupViews.GetTotalHeight(); - default: - Debug.LogError("Unhandled enum value"); - break; - } - return 0f; - } - - void DoSections(Rect totalRectOfSections, Rect[] sectionRects, SectionType[] sectionOrder) - { - Event evt = Event.current; - bool enabledGUI = m_Controller == null || AudioMixerController.EditingTargetSnapshot(); - - for (int i = 0; i < sectionOrder.Length; ++i) - { - Rect sectionRect = sectionRects[i]; - if (sectionRect.height <= 0.0f) - continue; - - switch (sectionOrder[i]) - { - case SectionType.MixerTree: - m_MixersTree.OnGUI(sectionRect); - break; - case SectionType.SnapshotList: - using (new EditorGUI.DisabledScope(!enabledGUI)) - { - m_SnapshotListView.OnGUI(sectionRect); - } - break; - case SectionType.GroupTree: - m_GroupTree.OnGUI(sectionRect); - break; - case SectionType.ViewList: - m_GroupViews.OnGUI(sectionRect); - break; - default: - Debug.LogError("Unhandled enum value"); - break; - } - - if (evt.type == EventType.ContextClick) - { - Rect sectionHeaderRect = new Rect(sectionRect.x, sectionRect.y, sectionRect.width - 15f, AudioMixerDrawUtils.kSectionHeaderHeight); - if (sectionHeaderRect.Contains(evt.mousePosition)) - { - ReorderContextMenu(sectionHeaderRect, i); - evt.Use(); - } - } - } - } - - void ReorderContextMenu(Rect rect, int sectionIndex) - { - Event evt = Event.current; - if (Event.current.type == EventType.ContextClick && rect.Contains(evt.mousePosition)) - { - GUIContent moveUp = new GUIContent(m_LayoutMode == LayoutMode.Horizontal ? "Move Left" : "Move Up"); - GUIContent moveDown = new GUIContent(m_LayoutMode == LayoutMode.Horizontal ? "Move Right" : "Move Down"); - - GenericMenu menu = new GenericMenu(); - if (sectionIndex > 1) - menu.AddItem(moveUp, false, ChangeSectionOrder, new Vector2(sectionIndex, -1)); - else - menu.AddDisabledItem(moveUp); - if (sectionIndex > 0 && sectionIndex < m_SectionOrder.Length - 1) - menu.AddItem(moveDown, false, ChangeSectionOrder, new Vector2(sectionIndex, 1)); - else - menu.AddDisabledItem(moveDown); - menu.ShowAsContext(); - } - } - - void ChangeSectionOrder(object userData) - { - Vector2 sectionIndexAndDirection = (Vector2)userData; - int sectionIndex = (int)sectionIndexAndDirection.x; - int direction = (int)sectionIndexAndDirection.y; - int newSectionIndex = Mathf.Clamp(sectionIndex + direction, 0, m_SectionOrder.Length - 1); - if (newSectionIndex != sectionIndex) - { - SectionType tmp = m_SectionOrder[sectionIndex]; - m_SectionOrder[sectionIndex] = m_SectionOrder[newSectionIndex]; - m_SectionOrder[newSectionIndex] = tmp; - } - } - - public MixerParameterDefinition ParamDef(string name, string desc, string units, float displayScale, float minRange, float maxRange, float defaultValue) - { - MixerParameterDefinition paramDef = new MixerParameterDefinition(); - paramDef.name = name; - paramDef.description = desc; - paramDef.units = units; - paramDef.displayScale = displayScale; - paramDef.minRange = minRange; - paramDef.maxRange = maxRange; - paramDef.defaultValue = defaultValue; - return paramDef; - } - - // Add items to the context menu for the AudioMixerWindow (the tree horizontal lines, upper right corner) - public virtual void AddItemsToMenu(GenericMenu menu) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Sort groups alphabetically"), m_SortGroupsAlphabetically, delegate { m_SortGroupsAlphabetically = !m_SortGroupsAlphabetically; }); - menu.AddItem(EditorGUIUtility.TrTextContent("Show referenced groups"), m_ShowReferencedBuses, delegate { m_ShowReferencedBuses = !m_ShowReferencedBuses; }); - menu.AddItem(EditorGUIUtility.TrTextContent("Show group connections"), m_ShowBusConnections, delegate { m_ShowBusConnections = !m_ShowBusConnections; }); - if (m_ShowBusConnections) - menu.AddItem(EditorGUIUtility.TrTextContent("Only highlight selected group connections"), m_ShowBusConnectionsOfSelection, delegate { m_ShowBusConnectionsOfSelection = !m_ShowBusConnectionsOfSelection; }); - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Vertical layout"), layoutMode == LayoutMode.Vertical, delegate { layoutMode = LayoutMode.Vertical; }); - menu.AddItem(EditorGUIUtility.TrTextContent("Horizontal layout"), layoutMode == LayoutMode.Horizontal, delegate { layoutMode = LayoutMode.Horizontal; }); - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Use RMS metering for display"), EditorPrefs.GetBool(kAudioMixerUseRMSMetering, true), delegate { EditorPrefs.SetBool(kAudioMixerUseRMSMetering, true); }); - menu.AddItem(EditorGUIUtility.TrTextContent("Use peak metering for display"), !EditorPrefs.GetBool(kAudioMixerUseRMSMetering, true), delegate { EditorPrefs.SetBool(kAudioMixerUseRMSMetering, false); }); - if (Unsupported.IsDeveloperMode()) - { - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Groups Rendered Above"), m_GroupsRenderedAboveSections, delegate { m_GroupsRenderedAboveSections = !m_GroupsRenderedAboveSections; }); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Build 10 groups"), false, delegate { m_Controller.BuildTestSetup(0, 7, 10); }); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Build 20 groups"), false, delegate { m_Controller.BuildTestSetup(0, 7, 20); }); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Build 40 groups"), false, delegate { m_Controller.BuildTestSetup(0, 7, 40); }); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Build 80 groups"), false, delegate { m_Controller.BuildTestSetup(0, 7, 80); }); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Build 160 groups"), false, delegate { m_Controller.BuildTestSetup(0, 7, 160); }); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Build chain of 10 groups"), false, delegate { m_Controller.BuildTestSetup(1, 1, 10); }); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Build chain of 20 groups "), false, delegate { m_Controller.BuildTestSetup(1, 1, 20); }); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Build chain of 40 groups"), false, delegate { m_Controller.BuildTestSetup(1, 1, 40); }); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Build chain of 80 groups"), false, delegate { m_Controller.BuildTestSetup(1, 1, 80); }); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Show overlays"), m_ShowDeveloperOverlays, delegate { m_ShowDeveloperOverlays = !m_ShowDeveloperOverlays; }); - } - } - } - - internal class AssetSelectionPopupMenu - { - static public void Show(Rect buttonRect, string[] classNames, int initialSelectedInstanceID) - { - var menu = new GenericMenu(); - var objs = FindAssetsOfType(classNames); - - if (objs.Any()) - { - objs.Sort((result1, result2) => EditorUtility.NaturalCompare(result1.name, result2.name)); - foreach (var obj in objs) - { - var assetName = new GUIContent(obj.name); - bool selected = obj.GetInstanceID() == initialSelectedInstanceID; - menu.AddItem(assetName, selected, SelectCallback, obj); - } - } - else - { - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("No Audio Mixers found in this project")); - } - menu.DropDown(buttonRect); - } - - static void SelectCallback(object userData) - { - UnityEngine.Object obj = userData as UnityEngine.Object; - if (obj != null) - Selection.activeInstanceID = obj.GetInstanceID(); - } - - static List FindAssetsOfType(string[] classNames) - { - var prop = new HierarchyProperty(HierarchyType.Assets); - prop.SetSearchFilter(new SearchFilter() { classNames = classNames }); - var objs = new List(); - while (prop.Next(null)) - { - objs.Add(prop.pptrValue); - } - return objs; - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixersTreeView.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixersTreeView.cs deleted file mode 100644 index 47adda790e..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixersTreeView.cs +++ /dev/null @@ -1,730 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using UnityEditor.ProjectWindowCallback; -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using System; -using UnityEditor.Audio; -using UnityEditor.IMGUI.Controls; -using UnityEngine.Audio; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - // Item - - internal class AudioMixerItem : TreeViewItem - { - public AudioMixerController mixer { get; set; } - public string infoText { get; set; } - public float labelWidth { get; set; } - bool lastSuspendedState { get; set; } - const string kSuspendedText = " - Inactive"; - - public AudioMixerItem(int id, int depth, TreeViewItem parent, string displayName, AudioMixerController mixer, string infoText) - : base(id, depth, parent, displayName) - { - this.mixer = mixer; - this.infoText = infoText; - UpdateSuspendedString(true); - } - - public void UpdateSuspendedString(bool force) - { - bool isSuspended = mixer.isSuspended; - if (lastSuspendedState != isSuspended || force) - { - lastSuspendedState = isSuspended; - - if (isSuspended) - AddSuspendedText(); - else - RemoveSuspendedText(); - } - } - - void RemoveSuspendedText() - { - int index = infoText.IndexOf(kSuspendedText, StringComparison.Ordinal); - if (index >= 0) - infoText = infoText.Remove(index, kSuspendedText.Length); - } - - void AddSuspendedText() - { - int index = infoText.IndexOf(kSuspendedText, StringComparison.Ordinal); - if (index < 0) - infoText += kSuspendedText; - } - } - - - // Dragging - - internal class AudioMixerTreeViewDragging : TreeViewDragging - { - private const string k_AudioMixerDraggingID = "AudioMixerDragging"; - Action, AudioMixerController> m_MixersDroppedOnMixerCallback; - - class DragData - { - public DragData(List draggedItems) - { - m_DraggedItems = draggedItems; - } - - public List m_DraggedItems; - } - - public AudioMixerTreeViewDragging(TreeViewController treeView, Action, AudioMixerController> mixerDroppedOnMixerCallback) - : base(treeView) - { - m_MixersDroppedOnMixerCallback = mixerDroppedOnMixerCallback; - } - - public override void StartDrag(TreeViewItem draggedNode, List draggedNodes) - { - // We do not allow changing routing in playmode for now - if (EditorApplication.isPlaying) - return; - - List draggedItems = GetAudioMixerItemsFromIDs(draggedNodes); - - DragAndDrop.PrepareStartDrag(); - DragAndDrop.SetGenericData(k_AudioMixerDraggingID, new DragData(draggedItems)); - string title = draggedNodes.Count + " AudioMixer" + (draggedNodes.Count > 1 ? "s" : ""); // title is only shown on OSX (at the cursor) - DragAndDrop.StartDrag(title); - } - - public override bool DragElement(TreeViewItem targetItem, Rect targetItemRect, int row) - { - // First ensure we are dragging AudioMixers (and not some other objects) - var dragData = DragAndDrop.GetGenericData(k_AudioMixerDraggingID) as DragData; - if (dragData == null) - { - DragAndDrop.visualMode = DragAndDropVisualMode.None; - return false; - } - - // Handle the case where we hover inside the treeview rect but not over any items - bool isDraggingOverEmptyArea = targetItem == null; - if (isDraggingOverEmptyArea && m_TreeView.GetTotalRect().Contains(Event.current.mousePosition)) - { - if (m_DropData != null) - { - // Ensure no rendering of target items - m_DropData.dropTargetControlID = 0; - m_DropData.rowMarkerControlID = 0; - } - - if (Event.current.type == EventType.DragPerform) - { - DragAndDrop.AcceptDrag(); - if (m_MixersDroppedOnMixerCallback != null) - m_MixersDroppedOnMixerCallback(GetAudioMixersFromItems(dragData.m_DraggedItems), null); - } - DragAndDrop.visualMode = DragAndDropVisualMode.Move; - Event.current.Use(); - return false; - } - - // Normal handling when over dragging over items - return base.DragElement(targetItem, targetItemRect, row); - } - - public override DragAndDropVisualMode DoDrag(TreeViewItem parentNode, TreeViewItem targetNode, bool perform, DropPosition dragPos) - { - var dragData = DragAndDrop.GetGenericData(k_AudioMixerDraggingID) as DragData; - if (dragData == null) - return DragAndDropVisualMode.None; - - var draggedItems = dragData.m_DraggedItems; - var parentMixerItem = parentNode as AudioMixerItem; - if (parentMixerItem != null && dragData != null) - { - List draggedMasterGroups = (from i in draggedItems select i.mixer.masterGroup).ToList(); - var allGroups = parentMixerItem.mixer.GetAllAudioGroupsSlow(); - bool causesFeedback = AudioMixerController.WillModificationOfTopologyCauseFeedback(allGroups, draggedMasterGroups, parentMixerItem.mixer.masterGroup, null); - bool validDrag = ValidDrag(parentNode, draggedItems) && !causesFeedback; - if (perform && validDrag) - { - if (m_MixersDroppedOnMixerCallback != null) - m_MixersDroppedOnMixerCallback(GetAudioMixersFromItems(draggedItems), parentMixerItem.mixer); - } - return validDrag ? DragAndDropVisualMode.Move : DragAndDropVisualMode.Rejected; - } - return DragAndDropVisualMode.None; - } - - bool ValidDrag(TreeViewItem parent, List draggedItems) - { - List draggedIDs = (from n in draggedItems select n.id).ToList(); - - TreeViewItem currentParent = parent; - while (currentParent != null) - { - if (draggedIDs.Contains(currentParent.id)) - return false; - currentParent = currentParent.parent; - } - return true; - } - - private List GetAudioMixerItemsFromIDs(List draggedMixers) - { - var found = TreeViewUtility.FindItemsInList(draggedMixers, m_TreeView.data.GetRows()); - return found.OfType().ToList(); - } - - private List GetAudioMixersFromItems(List draggedItems) - { - return (from i in draggedItems select i.mixer).ToList(); - } - } - - - // Datasource - - internal class AudioMixersDataSource : TreeViewDataSource - { - Func> m_GetAllControllersCallback; - - public AudioMixersDataSource(TreeViewController treeView, Func> getAllControllersCallback) - : base(treeView) - { - showRootItem = false; - m_GetAllControllersCallback = getAllControllersCallback; - } - - public override void FetchData() - { - int depth = -1; - bool expandAll = m_TreeView.state.expandedIDs.Count == 0; // State is persisted so only do this once per new AudioMixerWindow - - m_RootItem = new TreeViewItem(1010101010, depth, null, "InvisibleRoot"); - SetExpanded(m_RootItem.id, true); - - List m_Mixers = m_GetAllControllersCallback(); - - m_NeedRefreshRows = true; - if (m_Mixers.Count > 0) - { - // First create a tree view item for each controller - var roots = m_Mixers.Select(mixer => new AudioMixerItem(mixer.GetInstanceID(), 0, m_RootItem, mixer.name, mixer, GetInfoText(mixer))).ToList(); - - // Rearrange items to a tree based on output mixer group - foreach (var item in roots) - { - SetChildParentOfMixerItem(item, roots); - } - - SetItemDepthRecursive(m_RootItem, -1); // -1 because the root item is hidden - SortRecursive(m_RootItem); - - if (expandAll) - m_TreeView.data.SetExpandedWithChildren(m_RootItem, true); - } - } - - static string GetInfoText(AudioMixerController controller) - { - string s; - if (controller.outputAudioMixerGroup != null) - s = string.Format("({0} of {1})", controller.outputAudioMixerGroup.name, controller.outputAudioMixerGroup.audioMixer.name); - else - s = "(Audio Listener)"; - return s; - } - - void SetChildParentOfMixerItem(AudioMixerItem item, List items) - { - if (item.mixer.outputAudioMixerGroup != null) - { - var parentMixer = item.mixer.outputAudioMixerGroup.audioMixer; - var parentItem = TreeViewUtility.FindItemInList(parentMixer.GetInstanceID(), items) as AudioMixerItem; - if (parentItem != null) - { - parentItem.AddChild(item); - } - } - else - { - m_RootItem.AddChild(item); - } - } - - void SetItemDepthRecursive(TreeViewItem item, int depth) - { - item.depth = depth; - if (!item.hasChildren) - return; - - foreach (var child in item.children) - SetItemDepthRecursive(child, depth + 1); - } - - void SortRecursive(TreeViewItem item) - { - if (!item.hasChildren) - return; - item.children.Sort(new TreeViewItemAlphaNumericSort()); - - foreach (var child in item.children) - SortRecursive(child); - } - - public override bool IsRenamingItemAllowed(TreeViewItem item) - { - return true; - } - - public int GetInsertAfterItemIDForNewItem(string newName, TreeViewItem parentItem) - { - // Find pos under parent - int insertAfterID = parentItem.id; - - if (!parentItem.hasChildren) - return insertAfterID; - - for (int idx = 0; idx < parentItem.children.Count; ++idx) - { - int instanceID = parentItem.children[idx].id; - - // Use same name compare as when we sort in the backend: See AssetDatabase.cpp: SortChildren - string propertyPath = AssetDatabase.GetAssetPath(instanceID); - if (EditorUtility.NaturalCompare(Path.GetFileNameWithoutExtension(propertyPath), newName) > 0) - break; - - insertAfterID = instanceID; - } - return insertAfterID; - } - - override public void InsertFakeItem(int id, int parentID, string name, Texture2D icon) - { - TreeViewItem checkItem = FindItem(id); - if (checkItem != null) - { - Debug.LogError("Cannot insert fake Item because id is not unique " + id + " Item already there: " + checkItem.displayName); - return; - } - - if (FindItem(parentID) != null) - { - // Ensure parent Item's children is visible - SetExpanded(parentID, true); - - var visibleRows = GetRows(); - - TreeViewItem parentItem; - int parentIndex = TreeViewController.GetIndexOfID(visibleRows, parentID); - if (parentIndex >= 0) - parentItem = visibleRows[parentIndex]; - else - parentItem = m_RootItem; // Fallback to root Item as parent - - // Create fake item for insertion - int indentLevel = parentItem.depth + 1; - m_FakeItem = new TreeViewItem(id, indentLevel, parentItem, name); - m_FakeItem.icon = icon; - - // Find pos under parent - int insertAfterID = GetInsertAfterItemIDForNewItem(name, parentItem); - - // Find pos in expanded rows and insert - int index = TreeViewController.GetIndexOfID(visibleRows, insertAfterID); - if (index >= 0) - { - // Ensure to bypass all children of 'insertAfterID' - while (++index < visibleRows.Count) - { - if (visibleRows[index].depth <= indentLevel) - break; - } - - if (index < visibleRows.Count) - visibleRows.Insert(index, m_FakeItem); - else - visibleRows.Add(m_FakeItem); - } - else - { - // not visible parent: insert as first - if (visibleRows.Count > 0) - visibleRows.Insert(0, m_FakeItem); - else - visibleRows.Add(m_FakeItem); - } - - m_NeedRefreshRows = false; - - m_TreeView.Frame(m_FakeItem.id, true, false); - m_TreeView.Repaint(); - } - else - { - Debug.LogError("No parent Item found with ID: " + parentID); - } - } - } - - // Item GUI - - internal class AudioMixersTreeViewGUI : TreeViewGUI - { - public AudioMixersTreeViewGUI(TreeViewController treeView) - : base(treeView) - { - k_IconWidth = 0; - k_TopRowMargin = k_BottomRowMargin = 2f; - } - - protected override void OnContentGUI(Rect rect, int row, TreeViewItem item, string label, bool selected, bool focused, bool useBoldFont, bool isPinging) - { - if (Event.current.type != EventType.Repaint) - return; - - if (!isPinging) - { - // The rect is assumed indented and sized after the content when pinging - float indent = GetContentIndent(item); - rect.x += indent; - rect.width -= indent; - } - - AudioMixerItem mixerItem = item as AudioMixerItem; - if (mixerItem == null) - return; - - GUIStyle lineStyle = useBoldFont ? Styles.lineBoldStyle : Styles.lineStyle; - - // Draw text - lineStyle.padding.left = (int)(k_IconWidth + iconTotalPadding + k_SpaceBetweenIconAndText); - lineStyle.Draw(rect, label, false, false, selected, focused); - - // Draw info text - mixerItem.UpdateSuspendedString(false); - const float minSpaceBetween = 8f; - if (mixerItem.labelWidth <= 0) - mixerItem.labelWidth = lineStyle.CalcSize(GUIContent.Temp(label)).x; // only calc once - Rect infoRect = rect; - infoRect.x += mixerItem.labelWidth + minSpaceBetween; - using (new EditorGUI.DisabledScope(true)) - { - lineStyle.Draw(infoRect, mixerItem.infoText, false, false, false, false); - } - - // TODO Icon overlay (RCS) - if (iconOverlayGUI != null) - { - Rect iconOverlayRect = rect; - iconOverlayRect.width = k_IconWidth + iconTotalPadding; - iconOverlayGUI(item, iconOverlayRect); - } - } - - protected override Texture GetIconForItem(TreeViewItem node) - { - return null; // We do not want any icons - } - - protected CreateAssetUtility GetCreateAssetUtility() - { - return ((TreeViewStateWithAssetUtility)m_TreeView.state).createAssetUtility; - } - - protected override void RenameEnded() - { - string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name; - int instanceID = GetRenameOverlay().userData; - bool isCreating = GetCreateAssetUtility().IsCreatingNewAsset(); - bool userAccepted = GetRenameOverlay().userAcceptedRename; - - if (userAccepted) - { - if (isCreating) - { - // Create a new asset - GetCreateAssetUtility().EndNewAssetCreation(name); - m_TreeView.ReloadData(); - } - else - { - // Rename an existing asset - ObjectNames.SetNameSmartWithInstanceID(instanceID, name); - } - } - } - - override protected void ClearRenameAndNewItemState() - { - GetCreateAssetUtility().Clear(); - base.ClearRenameAndNewItemState(); - } - - AudioMixerItem GetSelectedItem() - { - return m_TreeView.FindItem(m_TreeView.GetSelection().FirstOrDefault()) as AudioMixerItem; - } - - override protected void SyncFakeItem() - { - if (!m_TreeView.data.HasFakeItem() && GetCreateAssetUtility().IsCreatingNewAsset()) - { - // Get selection from tree - int parentInstanceID = m_TreeView.data.root.id; - var selectedItem = GetSelectedItem(); - if (selectedItem != null) - parentInstanceID = selectedItem.parent.id; - m_TreeView.data.InsertFakeItem(GetCreateAssetUtility().instanceID, parentInstanceID, GetCreateAssetUtility().originalName, GetCreateAssetUtility().icon); - } - - if (m_TreeView.data.HasFakeItem() && !GetCreateAssetUtility().IsCreatingNewAsset()) - { - m_TreeView.data.RemoveFakeItem(); - } - } - - public void BeginCreateNewMixer() - { - //int instanceID, EndNameEditAction endAction, string pathName, Texture2D icon, string resourceFile - ClearRenameAndNewItemState(); - - // Use resouce file to store instanceID for output group so we can use that for the newly created audiomixer - string resourceFileData = string.Empty; - var selectedItem = GetSelectedItem(); - if (selectedItem != null && selectedItem.mixer.outputAudioMixerGroup != null) - resourceFileData = selectedItem.mixer.outputAudioMixerGroup.GetInstanceID().ToString(); - - int instanceID = 0; - - if (GetCreateAssetUtility().BeginNewAssetCreation( - instanceID, ScriptableObject.CreateInstance(), "NewAudioMixer.mixer", null, resourceFileData)) - { - SyncFakeItem(); - - // Start naming the asset - bool renameStarted = GetRenameOverlay().BeginRename(GetCreateAssetUtility().originalName, instanceID, 0f); - if (!renameStarted) - Debug.LogError("Rename not started (when creating new asset)"); - } - } - } - - - // TreeView - - internal class AudioMixersTreeView - { - private TreeViewController m_TreeView; - const int kObjectSelectorID = 1212; - List m_DraggedMixers; - - class Styles - { - 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."); - public GUIContent addText = EditorGUIUtility.TrTextContent("+", "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."); - public Texture2D audioMixerIcon = EditorGUIUtility.FindTexture(typeof(AudioMixerController)); - } - static Styles s_Styles; - - public AudioMixersTreeView(AudioMixerWindow mixerWindow, TreeViewState treeState, Func> getAllControllersCallback) - { - m_TreeView = new TreeViewController(mixerWindow, treeState); - m_TreeView.deselectOnUnhandledMouseDown = false; - m_TreeView.selectionChangedCallback += OnTreeSelectionChanged; - m_TreeView.contextClickItemCallback += OnTreeViewContextClick; - - var treeViewGUI = new AudioMixersTreeViewGUI(m_TreeView); - var treeViewDataSource = new AudioMixersDataSource(m_TreeView, getAllControllersCallback); - var treeViewDragging = new AudioMixerTreeViewDragging(m_TreeView, OnMixersDroppedOnMixerCallback); - m_TreeView.Init(mixerWindow.position, treeViewDataSource, treeViewGUI, treeViewDragging); - m_TreeView.ReloadData(); - } - - public void ReloadTree() - { - m_TreeView.ReloadData(); - m_TreeView.Repaint(); - } - - public void OnMixerControllerChanged(AudioMixerController controller) - { - if (controller != null) - m_TreeView.SetSelection(new int[] {controller.GetInstanceID()}, true); - } - - public void DeleteAudioMixerCallback(object obj) - { - AudioMixerController controller = (AudioMixerController)obj; - if (controller != null) - { - ProjectWindowUtil.DeleteAssets(new[] { controller.GetInstanceID() }.ToList(), true); - } - } - - public void OnTreeViewContextClick(int index) - { - AudioMixerItem node = (AudioMixerItem)m_TreeView.FindItem(index); - if (node != null) - { - GenericMenu pm = new GenericMenu(); - pm.AddItem(EditorGUIUtility.TrTextContent("Delete AudioMixer"), false, DeleteAudioMixerCallback, node.mixer); - pm.ShowAsContext(); - } - } - - public void OnTreeSelectionChanged(int[] selection) - { - Selection.instanceIDs = selection; - } - - public float GetTotalHeight() - { - const float minHeight = 20f; - return AudioMixerDrawUtils.kSectionHeaderHeight + Mathf.Max(minHeight, m_TreeView.gui.GetTotalSize().y); - } - - public void OnGUI(Rect rect) - { - int treeViewKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard); - - if (s_Styles == null) - s_Styles = new Styles(); - - m_TreeView.OnEvent(); - - Rect headerRect, contentRect; - AudioMixerDrawUtils.DrawRegionBg(rect, out headerRect, out contentRect); - AudioMixerDrawUtils.HeaderLabel(headerRect, s_Styles.header, s_Styles.audioMixerIcon); - - if (GUI.Button(new Rect(headerRect.xMax - 15f, headerRect.y + 3f, 15f, 15f), s_Styles.addText, EditorStyles.label)) - { - AudioMixersTreeViewGUI gui = m_TreeView.gui as AudioMixersTreeViewGUI; - gui.BeginCreateNewMixer(); - } - - m_TreeView.OnGUI(contentRect, treeViewKeyboardControlID); - - if (m_TreeView.data.rowCount == 0) - { - using (new EditorGUI.DisabledScope(true)) - { - GUI.Label(new RectOffset(-20, 0, -2, 0).Add(contentRect), "No mixers found"); - } - } - - AudioMixerDrawUtils.DrawScrollDropShadow(contentRect, m_TreeView.state.scrollPos.y, m_TreeView.gui.GetTotalSize().y); - - HandleCommandEvents(treeViewKeyboardControlID); - HandleObjectSelectorResult(); - } - - void HandleCommandEvents(int treeViewKeyboardControlID) - { - if (GUIUtility.keyboardControl != treeViewKeyboardControlID) - return; - - EventType eventType = Event.current.type; - if (eventType == EventType.ExecuteCommand || eventType == EventType.ValidateCommand) - { - bool execute = eventType == EventType.ExecuteCommand; - - if (Event.current.commandName == EventCommandNames.Delete || Event.current.commandName == EventCommandNames.SoftDelete) - { - Event.current.Use(); - if (execute) - ProjectWindowUtil.DeleteAssets(m_TreeView.GetSelection().ToList(), true); - } - else if (Event.current.commandName == EventCommandNames.Duplicate) - { - Event.current.Use(); - if (execute) - ProjectWindowUtil.DuplicateAssets(m_TreeView.GetSelection()); - } - } - } - - const string kExpandedStateIdentifier = "AudioMixerWindowMixers"; - - public void EndRenaming() - { - m_TreeView.EndNameEditing(true); - } - - public void OnUndoRedoPerformed() - { - ReloadTree(); - } - - void OnMixersDroppedOnMixerCallback(List draggedMixers, AudioMixerController droppedUponMixer) - { - // Set Unity selection when drag ended (when dragging non selected items we just render them as selected while dragging) - int[] draggedIDs = (from i in draggedMixers select i.GetInstanceID()).ToArray(); - m_TreeView.SetSelection(draggedIDs, true); - Selection.instanceIDs = draggedIDs; - - if (droppedUponMixer == null) - { - // Dragged to the root -> clear all outputgroups - Undo.RecordObjects(draggedMixers.ToArray(), "Set output group for mixer" + (draggedMixers.Count > 1 ? "s" : "")); - foreach (var mixer in draggedMixers) - mixer.outputAudioMixerGroup = null; - ReloadTree(); - } - else - { - // Show Object Selector for output group selection - m_DraggedMixers = draggedMixers; - Object startSelection = draggedMixers.Count == 1 ? draggedMixers[0].outputAudioMixerGroup : null; - ObjectSelector.get.Show(startSelection, typeof(AudioMixerGroup), null, false, new List() { droppedUponMixer.GetInstanceID() }); - ObjectSelector.get.objectSelectorID = kObjectSelectorID; - ObjectSelector.get.titleContent = EditorGUIUtility.TrTextContent("Select Output Audio Mixer Group"); - GUIUtility.ExitGUI(); - } - } - - void HandleObjectSelectorResult() - { - Event evt = Event.current; - if (evt.type == EventType.ExecuteCommand) - { - string commandName = evt.commandName; - if (commandName == ObjectSelector.ObjectSelectorUpdatedCommand && ObjectSelector.get.objectSelectorID == kObjectSelectorID) - { - if (m_DraggedMixers == null || m_DraggedMixers.Count == 0) - Debug.LogError("Unexpected invalid mixer list used for dragging"); - - var selected = ObjectSelector.GetCurrentObject(); - AudioMixerGroup selectedGroup = selected != null ? selected as AudioMixerGroup : null; - Undo.RecordObjects(m_DraggedMixers.ToArray(), "Set output group for mixer" + (m_DraggedMixers.Count > 1 ? "s" : "")); - foreach (var mixer in m_DraggedMixers) - { - if (mixer != null) - mixer.outputAudioMixerGroup = selectedGroup; - else - Debug.LogError("invalid mixer: is null"); - } - - GUI.changed = true; - evt.Use(); - - ReloadTree(); - - // Ensure newly selected output group is revealed - int[] selectedIDs = (from i in m_DraggedMixers select i.GetInstanceID()).ToArray(); - m_TreeView.SetSelection(selectedIDs, true); - } - - if (commandName == ObjectSelector.ObjectSelectorClosedCommand) - { - m_DraggedMixers = null; // cleanup stored state - } - } - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/ObjectTreeSelector.cs b/Editor/Mono/Audio/Mixer/GUI/ObjectTreeSelector.cs deleted file mode 100644 index 087174e762..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/ObjectTreeSelector.cs +++ /dev/null @@ -1,378 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Text; -using UnityEngine; -using UnityEngine.Events; - -namespace UnityEditor -{ - // TODO: - // Undo collapsing etc see ObjectSelector - // Check if sendCommandEvent to client view is needed - - // Description: Since TreeView is not serialized the client should set the tree view when requested - // by ObjectTreeSelector. Requested by calling treeViewNeededCallback provided by the client, - // use SetTreeView() to set tree view. - /* - internal class ObjectTreeSelectorData - { - public ObjectTreeSelector objectTreeSelector; - public TreeViewState state; - public Rect treeViewRect; - public int userData; - } - - internal class ObjectTreeSelector : EditorWindow - { - static ObjectTreeSelector s_Instance = null; - TreeView m_TreeView; - TreeViewState m_TreeViewState; - bool m_FocusSearchFilter; - const int kNoneItemID = 0; - int m_ErrorCounter = 0; - int m_OriginalSelectedID; - int m_UserData; - int m_LastSelectedID = -1; - string m_SelectedPath = ""; - const string kSearchFieldTag = "TreeSearchField"; - const float kBottomBarHeight = 17f; - const float kTopBarHeight = 27f; - SelectionEvent m_SelectionEvent; - TreeViewNeededEvent m_TreeViewNeededEvent; - - [Serializable] public class SelectionEvent : UnityEvent { } - [Serializable] public class TreeViewNeededEvent : UnityEvent { } - - class Styles - { - public GUIStyle searchBg = new GUIStyle("ProjectBrowserTopBarBg"); - public GUIStyle bottomBarBg = new GUIStyle("ProjectBrowserBottomBarBg"); - public Styles () - { - searchBg.border = new RectOffset(0,0,2,2); - searchBg.fixedHeight = 0; - - bottomBarBg.alignment = TextAnchor.MiddleLeft; - bottomBarBg.fontSize = EditorStyles.label.fontSize; - bottomBarBg.padding = new RectOffset(5,5,0,0); - } - } - static Styles s_Styles; - - - public static void Show (string windowTitle, UnityAction treeViewNeededCallback, UnityAction selectionCallback, int initialSelectedTreeViewItemID, int userData) - { - if (s_Instance == null) - { - s_Instance = (ObjectTreeSelector)GetWindow (typeof (ObjectTreeSelector), true, windowTitle, false); - s_Instance.minSize = new Vector2 (205, 220); - s_Instance.maxSize = new Vector2 (1900, 3000); - s_Instance.ShowAuxWindow (); // Use this if auto close on lost focus is wanted. - } - else - { - s_Instance.Repaint (); - } - - s_Instance.Init (treeViewNeededCallback, selectionCallback, initialSelectedTreeViewItemID, userData); - } - - ObjectTreeSelector () - { - hideFlags = HideFlags.DontSave; // Because we are a utility we do not want to be saved to layout - } - - void Init (UnityAction treeViewNeededCallback, UnityAction selectionCallback, int initialSelectedTreeViewItemID, int userData) - { - if (m_TreeViewNeededEvent == null) - m_TreeViewNeededEvent = new TreeViewNeededEvent(); - m_TreeViewNeededEvent.AddPersistentListener (treeViewNeededCallback); - - if (m_SelectionEvent == null) - m_SelectionEvent = new SelectionEvent(); - m_SelectionEvent.AddPersistentListener (selectionCallback); - - m_OriginalSelectedID = initialSelectedTreeViewItemID; - m_UserData = userData; - - // Clear previous state to ensure fresh start - m_TreeView = null; - m_TreeViewState = null; - m_ErrorCounter = 0; - m_FocusSearchFilter = true; // start by focusing search field - - // Initial setup - EnsureTreeViewIsValid (GetTreeViewRect ()); - if (m_TreeView != null) - { - m_TreeView.SetSelection (new [] {m_OriginalSelectedID}, true); - } - } - - // Call this when requested by ObjectTreeSelector (it calls treeViewNeededCallback) - public void SetTreeView (TreeView treeView) - { - m_TreeView = treeView; - - // Hook up to tree view events - m_TreeView.selectionChangedCallback -= OnItemSelectionChanged; - m_TreeView.selectionChangedCallback += OnItemSelectionChanged; - m_TreeView.itemDoubleClickedCallback -= OnItemDoubleClicked; - m_TreeView.itemDoubleClickedCallback += OnItemDoubleClicked; - } - - bool EnsureTreeViewIsValid (Rect treeViewRect) - { - if (m_TreeViewState == null) - m_TreeViewState = new TreeViewState (); - - if (m_TreeView == null) - { - var input = new ObjectTreeSelectorData () - { - state = m_TreeViewState, - treeViewRect = treeViewRect, - userData = m_UserData, - objectTreeSelector = this - }; - - m_TreeViewNeededEvent.Invoke (input); - if (m_TreeView != null) - { - if (m_TreeView.data.root == null) - { - m_TreeView.ReloadData (); - } - } - - if (m_TreeView == null) - { - if (m_ErrorCounter == 0) - { - Debug.LogError ("ObjectTreeSelector is missing its tree view. Ensure to call 'SetTreeView()' when the treeViewNeededCallback is invoked!"); - m_ErrorCounter++; - } - return false; - } - } - return true; - } - - Rect GetTreeViewRect () - { - return new Rect (0, kTopBarHeight, position.width, position.height - kBottomBarHeight - kTopBarHeight); - } - - public void OnGUI () - { - if (s_Styles == null) - s_Styles = new Styles (); - - Rect rect = new Rect (0,0, position.width, position.height); - Rect toolbarRect = new Rect (rect.x, rect.y, rect.width, kTopBarHeight); - Rect bottomRect = new Rect (rect.x, rect.yMax - kBottomBarHeight, rect.width, kBottomBarHeight); - Rect treeViewRect = GetTreeViewRect (); - - if (!EnsureTreeViewIsValid (treeViewRect)) - return; - - int treeViewControlID = GUIUtility.GetControlID ("Tree".GetHashCode (), FocusType.Keyboard); - - HandleCommandEvents (); - HandleKeyboard (treeViewControlID); - SearchArea (toolbarRect); - TreeViewArea (treeViewRect, treeViewControlID); - BottomBar (bottomRect); - - // Close window cancel changes - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - Cancel (); - } - - void BottomBar (Rect bottomRect) - { - int currentID = m_TreeView.GetSelection ().FirstOrDefault (); // 0 is none selected - - // Refresh cached string - if (currentID != m_LastSelectedID) - { - m_LastSelectedID = currentID; - m_SelectedPath = ""; - var selected = m_TreeView.FindNode (currentID); - if (selected != null) - { - StringBuilder sb = new StringBuilder(); - var item = selected; - while (item != null && item != m_TreeView.data.root) - { - if (item != selected) - sb.Insert (0, "/"); - sb.Insert(0, item.displayName); - item = item.parent; - } - m_SelectedPath = sb.ToString (); - } - } - - GUI.Label (bottomRect, GUIContent.none, s_Styles.bottomBarBg); - if (!string.IsNullOrEmpty (m_SelectedPath)) - GUI.Label (bottomRect, GUIContent.Temp (m_SelectedPath), EditorStyles.miniLabel); - } - - private void OnItemDoubleClicked (int id) - { - Close (); - } - - private void OnItemSelectionChanged (int[] selection) - { - if (m_SelectionEvent != null) - { - TreeViewItem item = null; - if (selection.Length > 0) - { - item = m_TreeView.FindNode (selection[0]); - } - FireSelectionEvent (item); - } - } - - void HandleKeyboard (int treeViewControlID) - { - if (Event.current.type != EventType.KeyDown) - return; - - switch (Event.current.keyCode) - { - case KeyCode.Return: - case KeyCode.KeypadEnter: - Event.current.Use (); - Close (); - GUI.changed = true; - GUIUtility.ExitGUI (); - break; - case KeyCode.DownArrow: - case KeyCode.UpArrow: - { - // When searchfield has focus give keyboard focus to the tree view on Down/UpArrow - bool hasSearchFilterFocus = GUI.GetNameOfFocusedControl () == kSearchFieldTag; - if (hasSearchFilterFocus) - { - GUIUtility.keyboardControl = treeViewControlID; - - // If nothing is selected ensure first item is selected, otherwise ensure current - // selection is visible (we just gave focus to the tree) - if (m_TreeView.IsLastClickedPartOfRows ()) - FrameSelectedTreeViewItem (); - else - m_TreeView.OffsetSelection (1); // Selects first item - - Event.current.Use (); - } - } - break; - default: - return; - } - } - - void FrameSelectedTreeViewItem () - { - m_TreeView.Frame (m_TreeView.state.lastClickedID, true, false); - } - - void HandleCommandEvents () - { - Event evt = Event.current; - - if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand) - return; - - if (evt.commandName == EventCommandNames.FrameSelected) - { - if (evt.type == EventType.ExecuteCommand && m_TreeView.HasSelection ()) - { - m_TreeView.searchString = string.Empty; - FrameSelectedTreeViewItem (); - } - evt.Use (); - GUIUtility.ExitGUI (); - } - if (evt.commandName == EventCommandNames.Find) - { - if (evt.type == EventType.ExecuteCommand) - { - FocusSearchField (); - } - evt.Use (); - } - } - - void FireSelectionEvent (TreeViewItem item) - { - if (m_SelectionEvent != null) - m_SelectionEvent.Invoke (item); - } - - void Cancel () - { - FireSelectionEvent (m_TreeView.FindNode (m_OriginalSelectedID)); - - Close (); - GUI.changed = true; - GUIUtility.ExitGUI (); - } - - void TreeViewArea (Rect treeViewRect, int treeViewControlID) - { - bool hasRows = m_TreeView.data.GetRows ().Count > 0; - if (hasRows) - { - m_TreeView.OnGUI (treeViewRect, treeViewControlID); - } - } - - void SearchArea (Rect toolbarRect) - { - GUI.Label (toolbarRect, GUIContent.none, s_Styles.searchBg); - - // ESC clears search field and removes it's focus. But if we get an esc event we only want to clear search field. - // So we need special handling afterwards. - bool wasEscape = Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape; - GUI.SetNextControlName (kSearchFieldTag); - string newSearchFilter = EditorGUI.SearchField (new Rect (5, 5, toolbarRect.width - 10, 15), m_TreeView.searchString); - - if (wasEscape && Event.current.type == EventType.Used) - { - // If we hit esc and the string WAS empty, it's an actual cancel event. - if (m_TreeView.searchString == string.Empty) - Cancel (); - - // Otherwise the string has been cleared and focus has been lost. We don't have anything else to recieve focus, so we want to refocus the search field. - m_FocusSearchFilter = true; - } - - if (newSearchFilter != m_TreeView.searchString || m_FocusSearchFilter) - { - m_TreeView.searchString = newSearchFilter; - Repaint (); - } - - if (m_FocusSearchFilter) - { - EditorGUI.FocusTextInControl (kSearchFieldTag); - if (Event.current.type == EventType.Repaint) - m_FocusSearchFilter = false; - } - } - - internal void FocusSearchField () - { - m_FocusSearchFilter = true; - } - }*/ -} // namespace diff --git a/Editor/Mono/Audio/Mixer/GUI/ReorderableListWithRenameAndScrollView.cs b/Editor/Mono/Audio/Mixer/GUI/ReorderableListWithRenameAndScrollView.cs deleted file mode 100644 index 2fecf736f8..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/ReorderableListWithRenameAndScrollView.cs +++ /dev/null @@ -1,330 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; - -namespace UnityEditorInternal -{ - internal class ReorderableListWithRenameAndScrollView - { - [Serializable] - public class State - { - public Vector2 m_ScrollPos = new Vector2(0, 0); - public RenameOverlay m_RenameOverlay = new RenameOverlay(); - } - - ReorderableList m_ReorderableList; - State m_State; - int m_LastSelectedIndex = -1; - bool m_HadKeyFocusAtMouseDown = false; - int m_FrameIndex = -1; - - public GUIStyle listElementStyle = null; // if null then a default style is used - public GUIStyle renameOverlayStyle = null; // if null then the default rename style is used - public Func onGetNameAtIndex; // rect, index, selected - public Action onNameChangedAtIndex; // index, new name - public Action onSelectionChanged; - public Action onDeleteItemAtIndex; - public ReorderableList.ElementCallbackDelegate onCustomDrawElement; - public ReorderableList list { get { return m_ReorderableList; } } - - public class Styles - { - public GUIStyle reorderableListLabel = new GUIStyle("PR Label"); - public GUIStyle reorderableListLabelRightAligned; - - public Styles() - { - Texture2D transparent = reorderableListLabel.hover.background; - reorderableListLabel.normal.background = transparent; - reorderableListLabel.active.background = transparent; - reorderableListLabel.focused.background = transparent; - reorderableListLabel.onNormal.background = transparent; - reorderableListLabel.onHover.background = transparent; - reorderableListLabel.onActive.background = transparent; - reorderableListLabel.onFocused.background = transparent; - reorderableListLabel.padding.left = reorderableListLabel.padding.right = 0; - reorderableListLabel.alignment = TextAnchor.MiddleLeft; - - reorderableListLabelRightAligned = new GUIStyle(reorderableListLabel); - reorderableListLabelRightAligned.alignment = TextAnchor.MiddleRight; - reorderableListLabelRightAligned.clipping = TextClipping.Overflow; - } - } - static Styles s_Styles; - - public GUIStyle elementStyle - { - get { return listElementStyle ?? s_Styles.reorderableListLabel; } - } - - public GUIStyle elementStyleRightAligned - { - get { return s_Styles.reorderableListLabelRightAligned; } - } - - public ReorderableListWithRenameAndScrollView(ReorderableList list, State state) - { - m_State = state; - - m_ReorderableList = list; - - // Add common handling for the following delegates - m_ReorderableList.drawElementCallback += DrawElement; - m_ReorderableList.onSelectCallback += SelectCallback; - m_ReorderableList.onMouseUpCallback += MouseUpCallback; - m_ReorderableList.onReorderCallback += ReorderCallback; - } - - RenameOverlay GetRenameOverlay() - { - return m_State.m_RenameOverlay; - } - - public void OnEvent() - { - GetRenameOverlay().OnEvent(); - } - - void EnsureRowIsVisible(int index, float scrollGUIHeight) - { - if (index < 0) - return; - - float topPixelOfRow = m_ReorderableList.elementHeight * index + 2; - float scrollBottom = topPixelOfRow - scrollGUIHeight + m_ReorderableList.elementHeight + 3; - m_State.m_ScrollPos.y = Mathf.Clamp(m_State.m_ScrollPos.y, scrollBottom, topPixelOfRow); - } - - public void OnGUI(Rect rect) - { - if (s_Styles == null) - s_Styles = new Styles(); - - //Event evt = Event.current; - - if (onGetNameAtIndex == null) - Debug.LogError("Ensure to set: 'onGetNameAtIndex'"); - - Event evt = Event.current; - - if (evt.type == EventType.MouseDown && rect.Contains(evt.mousePosition)) - m_HadKeyFocusAtMouseDown = m_ReorderableList.HasKeyboardControl(); - - if (m_FrameIndex != -1) - { - EnsureRowIsVisible(m_FrameIndex, rect.height); - m_FrameIndex = -1; - } - - GUILayout.BeginArea(rect); - m_State.m_ScrollPos = GUILayout.BeginScrollView(m_State.m_ScrollPos); - - m_ReorderableList.DoLayoutList(); - - GUILayout.EndScrollView(); - GUILayout.EndArea(); - AudioMixerDrawUtils.DrawScrollDropShadow(rect, m_State.m_ScrollPos.y, m_ReorderableList.GetHeight()); - - KeyboardHandling(); - CommandHandling(); - } - - public bool IsRenamingIndex(int index) - { - return GetRenameOverlay().IsRenaming() && GetRenameOverlay().userData == index && !GetRenameOverlay().isWaitingForDelay; - } - - public void DrawElement(Rect r, int index, bool isActive, bool isFocused) - { - if (IsRenamingIndex(index)) - { - // We do not want to set rect when they can be invalid, this can happen for layout or used events - if (r.width >= 0f && r.height >= 0f) - { - r.x -= 2; // Fit rename field text perfect with label - GetRenameOverlay().editFieldRect = r; - } - DoRenameOverlay(); - } - else - { - if (onCustomDrawElement != null) - onCustomDrawElement(r, index, isActive, isFocused); - else - DrawElementText(r, index, isActive, index == m_ReorderableList.index, isFocused); - } - } - - public void DrawElementText(Rect r, int index, bool isActive, bool isSelected, bool isFocused) - { - if (Event.current.type == EventType.Repaint && onGetNameAtIndex != null) - { - elementStyle.Draw(r, onGetNameAtIndex(index), false, false, isSelected, true); - } - } - - virtual public void DoRenameOverlay() - { - if (GetRenameOverlay().IsRenaming()) - if (!GetRenameOverlay().OnGUI()) - RenameEnded(); - } - - public void BeginRename(int index, float delay) - { - GetRenameOverlay().BeginRename(onGetNameAtIndex(index), index, delay); - m_ReorderableList.index = index; - m_LastSelectedIndex = index; - FrameItem(index); - } - - void RenameEnded() - { - if (GetRenameOverlay().userAcceptedRename) - { - if (onNameChangedAtIndex != null) - { - string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name; - int index = GetRenameOverlay().userData; - onNameChangedAtIndex(index, name); - } - } - - // We give keyboard focus back to our reorderable list because the rename utility stole it (now we give it back) - if (GetRenameOverlay().HasKeyboardFocus()) - m_ReorderableList.GrabKeyboardFocus(); - - GetRenameOverlay().Clear(); - } - - public void EndRename(bool acceptChanges) - { - if (GetRenameOverlay().IsRenaming()) - { - GetRenameOverlay().EndRename(acceptChanges); - RenameEnded(); - } - } - - public void ReorderCallback(ReorderableList list) - { - m_LastSelectedIndex = list.index; - } - - public void MouseUpCallback(ReorderableList list) - { - if (m_HadKeyFocusAtMouseDown && list.index == m_LastSelectedIndex) - BeginRename(list.index, 0.5f); - - m_LastSelectedIndex = list.index; - } - - // Fired on mousedown on elemement - public void SelectCallback(ReorderableList list) - { - FrameItem(list.index); - if (onSelectionChanged != null) - onSelectionChanged(list.index); - } - - void RemoveSelected() - { - if (m_ReorderableList.index < 0 || m_ReorderableList.index >= m_ReorderableList.count) - { - Debug.Log("Invalid index to remove " + m_ReorderableList.index); - return; - } - - if (onDeleteItemAtIndex != null) - onDeleteItemAtIndex(m_ReorderableList.index); - } - - public void FrameItem(int index) - { - m_FrameIndex = index; - } - - bool CanBeginRename() - { - return !GetRenameOverlay().IsRenaming() && m_ReorderableList.index >= 0; - } - - void CommandHandling() - { - Event evt = Event.current; - if (Event.current.type == EventType.ExecuteCommand) - { - switch (evt.commandName) - { - case EventCommandNames.OnLostFocus: - EndRename(true); - evt.Use(); - break; - } - } - } - - void KeyboardHandling() - { - Event evt = Event.current; - if (evt.type != EventType.KeyDown) - return; - - /*if (GUI.GetNameOfFocusedControl () == kRenameField) - { - switch (Event.current.keyCode) - { - case KeyCode.Escape: - EndRename (); - break; - } - }*/ - if (m_ReorderableList.HasKeyboardControl()) - { - switch (Event.current.keyCode) - { - case KeyCode.Home: - evt.Use(); - m_ReorderableList.index = 0; - //EndRename(true); - FrameItem(m_ReorderableList.index); - break; - - case KeyCode.End: - evt.Use(); - m_ReorderableList.index = m_ReorderableList.count - 1; - //EndRename(true); - FrameItem(m_ReorderableList.index); - break; - - case KeyCode.Return: - case KeyCode.KeypadEnter: - if (CanBeginRename() && Application.platform == RuntimePlatform.OSXEditor) - { - BeginRename(m_ReorderableList.index, 0f); - evt.Use(); - } - break; - - case KeyCode.F2: - if (CanBeginRename() && Application.platform != RuntimePlatform.OSXEditor) - { - BeginRename(m_ReorderableList.index, 0f); - evt.Use(); - } - break; - - case KeyCode.Delete: - RemoveSelected(); - evt.Use(); - break; - } - } - } - } -} diff --git a/Editor/Mono/Audio/Mixer/GUI/TreeViewForAudioMixerGroups.cs b/Editor/Mono/Audio/Mixer/GUI/TreeViewForAudioMixerGroups.cs deleted file mode 100644 index c9f9bf43f3..0000000000 --- a/Editor/Mono/Audio/Mixer/GUI/TreeViewForAudioMixerGroups.cs +++ /dev/null @@ -1,297 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Audio; -using UnityEditorInternal; -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.IMGUI.Controls; -using UnityEngine.Audio; - -namespace UnityEditor -{ - internal static class TreeViewForAudioMixerGroup - { - public static void CreateAndSetTreeView(ObjectTreeForSelector.TreeSelectorData data) - { - var ignoreController = InternalEditorUtility.GetObjectFromInstanceID(data.userData) as AudioMixerController; - - // Create treeview - var treeView = new TreeViewController(data.editorWindow, data.state); - var treeGui = new GroupTreeViewGUI(treeView); - var dataSource = new TreeViewDataSourceForMixers(treeView, ignoreController); - dataSource.onVisibleRowsChanged += treeGui.CalculateRowRects; - treeView.deselectOnUnhandledMouseDown = false; - treeView.Init(data.treeViewRect, dataSource, treeGui, null); - - // Set - data.objectTreeForSelector.SetTreeView(treeView); - } - - static readonly int kNoneItemID = 0; - static string s_NoneText = "None"; - - // GUI - - class GroupTreeViewGUI : TreeViewGUI - { - private readonly Texture2D k_AudioGroupIcon = EditorGUIUtility.FindTexture(typeof(AudioMixerGroup)); - private readonly Texture2D k_AudioListenerIcon = EditorGUIUtility.FindTexture(typeof(AudioListener)); - - private const float k_SpaceBetween = 25f; - private const float k_HeaderHeight = 20f; - - private List m_RowRects = new List(); - - public GroupTreeViewGUI(TreeViewController treeView) : base(treeView) - { - } - - public override Rect GetRowRect(int row, float rowWidth) - { - if (m_TreeView.isSearching) - { - return base.GetRowRect(row, rowWidth); - } - - if (m_TreeView.data.rowCount != m_RowRects.Count) - CalculateRowRects(); - - return m_RowRects[row]; - } - - public override void OnRowGUI(Rect rowRect, TreeViewItem item, int row, bool selected, bool focused) - { - // Use normal line height when searching (its just a list) - if (m_TreeView.isSearching) - { - base.OnRowGUI(rowRect, item, row, selected, focused); - return; - } - - DoItemGUI(rowRect, row, item, selected, focused, false); - bool isRootItem = item.parent == m_TreeView.data.root; - bool isNoneItem = item.id == kNoneItemID; - if (isRootItem && !isNoneItem) - { - AudioMixerController controller = ((MixerTreeViewItem)item).group.controller; - GUI.Label(new Rect(rowRect.x + 2f, rowRect.y - 18f, rowRect.width, 18f), GUIContent.Temp(controller.name), EditorStyles.boldLabel); - } - } - - protected override Texture GetIconForItem(TreeViewItem item) - { - if (item != null && item.icon != null) - return item.icon; - - if (item.id == kNoneItemID) - return k_AudioListenerIcon; - return k_AudioGroupIcon; - } - - protected override void SyncFakeItem() - { - } - - protected override void RenameEnded() - { - } - - // ------------------ - // Size section - - private bool IsController(TreeViewItem item) - { - return (item.parent == m_TreeView.data.root) && (item.id != kNoneItemID); - } - - public void CalculateRowRects() - { - if (m_TreeView.isSearching) - return; - const float startY = 2f; - float rowWidth = GUIClip.visibleRect.width; - var rows = m_TreeView.data.GetRows(); - m_RowRects = new List(rows.Count); - float curY = startY; - for (int i = 0; i < rows.Count; ++i) - { - bool isController = IsController(rows[i]); - float spacing = (isController ? k_SpaceBetween : 0f); - curY += spacing; - float height = k_LineHeight; - m_RowRects.Add(new Rect(0, curY, rowWidth, height)); - curY += height; - } - } - - // Calc correct width if horizontal scrollbar is wanted return new Vector2(1, height) - public override Vector2 GetTotalSize() - { - if (m_TreeView.isSearching) - { - Vector2 size = base.GetTotalSize(); - size.x = 1;// GetMaxWidth (rows); - return size; - } - - if (m_RowRects.Count == 0) - return new Vector2(1, 1); - - //float maxWidth = GUIClip.visibleRect.width; // GetMaxWidth (rows); - return new Vector2(1, m_RowRects[m_RowRects.Count - 1].yMax); - } - - public override int GetNumRowsOnPageUpDown(TreeViewItem fromItem, bool pageUp, float heightOfTreeView) - { - if (m_TreeView.isSearching) - return base.GetNumRowsOnPageUpDown(fromItem, pageUp, heightOfTreeView); - return (int)Mathf.Floor(heightOfTreeView / k_LineHeight); // good enough though not exact due to k_SpaceBetween - } - - // Should return the row number of the first and last row thats fits in the pixel rect defined by top and height - public override void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible) - { - if (m_TreeView.isSearching) - { - base.GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible); - return; - } - var rowCount = m_TreeView.data.rowCount; - if (rowCount != m_RowRects.Count) - Debug.LogError("Mismatch in state: rows vs cached rects"); - - int firstVisible = -1; - int lastVisible = -1; - - float topPixel = m_TreeView.state.scrollPos.y; - float heightInPixels = m_TreeView.GetTotalRect().height; - for (int i = 0; i < m_RowRects.Count; ++i) - { - bool visible = ((m_RowRects[i].y > topPixel && (m_RowRects[i].y < topPixel + heightInPixels))) || - ((m_RowRects[i].yMax > topPixel && (m_RowRects[i].yMax < topPixel + heightInPixels))); - - if (visible) - { - if (firstVisible == -1) - firstVisible = i; - lastVisible = i; - } - } - - if (firstVisible != -1 && lastVisible != -1) - { - firstRowVisible = firstVisible; - lastRowVisible = lastVisible; - } - else - { - firstRowVisible = 0; - lastRowVisible = rowCount - 1; - } - } - } - - class MixerTreeViewItem : TreeViewItem - { - public MixerTreeViewItem(int id, int depth, TreeViewItem parent, string displayName, AudioMixerGroupController groupController) - : base(id, depth, parent, displayName) - { - group = groupController; - } - - public AudioMixerGroupController group { get; set; } - } - - // Datasource - - class TreeViewDataSourceForMixers : TreeViewDataSource - { - public AudioMixerController ignoreThisController { get; private set; } - - public TreeViewDataSourceForMixers(TreeViewController treeView, AudioMixerController ignoreController) - : base(treeView) - { - showRootItem = false; - rootIsCollapsable = false; - ignoreThisController = ignoreController; - alwaysAddFirstItemToSearchResult = true; - } - - bool ShouldShowController(AudioMixerController controller, List allowedInstanceIDs) - { - if (!controller) - return false; - - if (allowedInstanceIDs != null && allowedInstanceIDs.Count > 0) - return allowedInstanceIDs.Contains(controller.GetInstanceID()); - - return true; - } - - public override void FetchData() - { - int depth = -1; - m_RootItem = new TreeViewItem(1010101010, depth, null, "InvisibleRoot"); - SetExpanded(m_RootItem.id, true); - - List allowedInstanceIDs = ObjectSelector.get.allowedInstanceIDs; - - HierarchyProperty prop = new HierarchyProperty(HierarchyType.Assets); - prop.SetSearchFilter(new SearchFilter() {classNames = new[] {"AudioMixerController"}}); - var controllers = new List(); - while (prop.Next(null)) - { - var controller = prop.pptrValue as AudioMixerController; - if (ShouldShowController(controller, allowedInstanceIDs)) - controllers.Add(controller); - } - - var roots = new List(); - - // First add the 'None' item, then add all groups - roots.Add(new TreeViewItem(kNoneItemID, 0, m_RootItem, s_NoneText)); - - foreach (var controller in controllers) - roots.Add(BuildSubTree(controller)); - - m_RootItem.children = roots; - - // 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) - if (controllers.Count == 1) - m_TreeView.data.SetExpandedWithChildren(m_RootItem, true); - - m_NeedRefreshRows = true; - } - - private TreeViewItem BuildSubTree(AudioMixerController controller) - { - AudioMixerGroupController masterGroup = controller.masterGroup; - var masterItem = new MixerTreeViewItem(masterGroup.GetInstanceID(), 0, m_RootItem, masterGroup.name, masterGroup); - AddChildrenRecursive(masterGroup, masterItem); - return masterItem; - } - - private void AddChildrenRecursive(AudioMixerGroupController group, TreeViewItem item) - { - item.children = new List(group.children.Length); - for (int i = 0; i < group.children.Length; ++i) - { - item.children.Add(new MixerTreeViewItem(group.children[i].GetInstanceID(), item.depth + 1, item, group.children[i].name, group.children[i])); - AddChildrenRecursive(group.children[i], item.children[i]); - } - } - - public override bool CanBeMultiSelected(TreeViewItem item) - { - return false; - } - - public override bool IsRenamingItemAllowed(TreeViewItem item) - { - return false; - } - } - } -} // namespace diff --git a/Editor/Mono/Audio/StreamedAudioClipPreview.cs b/Editor/Mono/Audio/StreamedAudioClipPreview.cs deleted file mode 100644 index 1fcfc9efe1..0000000000 --- a/Editor/Mono/Audio/StreamedAudioClipPreview.cs +++ /dev/null @@ -1,466 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Reflection; -using UnityEngine; - - -namespace UnityEditor -{ - class StreamedAudioClipPreview : WaveformPreview - { - static class AudioClipMinMaxOverview - { - static Dictionary s_Data = new Dictionary(); - public static float[] GetOverviewFor(AudioClip clip) - { - if (!s_Data.ContainsKey(clip)) - { - var path = AssetDatabase.GetAssetPath(clip); - if (path == null) - return null; - var importer = AssetImporter.GetAtPath(path); - if (importer == null) - return null; - - s_Data[clip] = AudioUtil.GetMinMaxData(importer as AudioImporter); - } - - return s_Data[clip]; - } - } - - struct ClipPreviewDetails - { - public float[] preview; - public int previewSamples; - public double normalizedDuration; - public double normalizedStart; - public double deltaStep; - public AudioClip clip; - public int previewPixelsToRender; - public double localStart; - public double localLength; - public bool looping; - - public ClipPreviewDetails(AudioClip clip, bool isLooping, int size, double localStart, double localLength) - { - if (size < 2) - throw new ArgumentException("Size has to be larger than 1"); - - if (localLength <= 0) - throw new ArgumentException("length has to be longer than zero", "localLength"); - - if (localStart < 0) - throw new ArgumentException("localStart has to be positive", "localStart"); - - if (clip == null) - throw new ArgumentNullException("clip"); - - this.clip = clip; - - preview = AudioClipMinMaxOverview.GetOverviewFor(clip); - - if (preview == null) - throw new ArgumentException("Clip " + clip + "'s overview preview is null"); - - looping = isLooping; - - this.localStart = localStart; - this.localLength = localLength; - - if (looping) - { - previewPixelsToRender = size; - } - else - { - var clampedLength = Math.Min(clip.length - localStart, localLength); - previewPixelsToRender = (int)Math.Min(size, size * Math.Max(0, clampedLength / localLength)); - } - - previewSamples = preview.Length / (clip.channels * 2); - normalizedDuration = localLength / clip.length; - normalizedStart = localStart / clip.length; - deltaStep = (previewSamples * normalizedDuration) / (size - 1); - } - - public bool IsCandidateForStreaming() - { - // shortcut, no need to start the stream if the start extends beyond the first clip region and the clip is "hold" - if (!looping && localStart >= clip.length) - return false; - - return deltaStep < 0.5; - } - } - struct Segment - { - public WaveformStreamer streamer; - public int streamingIndexOffset; - public int textureOffset; - public int segmentLength; - } - - class StreamingContext - { - public int index; - } - - Dictionary m_Contexts = new Dictionary(); - Segment[] m_StreamedSegments; - AudioClip m_Clip; - - public StreamedAudioClipPreview(AudioClip clip, int initialSize) - : base(clip, initialSize, clip.channels) - { - m_ClearTexture = false; - m_Clip = clip; - m_Start = 0; - m_Length = clip.length; - } - - protected override void InternalDispose() - { - base.InternalDispose(); - KillAndClearStreamers(); - m_StreamedSegments = null; - } - - protected override void OnModifications(MessageFlags cFlags) - { - bool restartStreaming = false; - - if (HasFlag(cFlags, MessageFlags.TextureChanged) || HasFlag(cFlags, MessageFlags.Size) || HasFlag(cFlags, MessageFlags.Length) || HasFlag(cFlags, MessageFlags.Looping)) - { - KillAndClearStreamers(); - - if (length <= 0) - return; - - var details = new ClipPreviewDetails(m_Clip, looping, (int)Size.x, start, length); - - UploadPreview(details); - - if (details.IsCandidateForStreaming()) - restartStreaming = true; - } - - if (!optimized) - { - KillAndClearStreamers(); - restartStreaming = false; - } - else if (HasFlag(cFlags, MessageFlags.Optimization) && !restartStreaming) - { - // optimization toggled on, need to query whether we should start streaming - var details = new ClipPreviewDetails(m_Clip, looping, (int)Size.x, start, length); - - if (details.IsCandidateForStreaming()) - restartStreaming = true; - } - - if (restartStreaming) - { - m_StreamedSegments = CalculateAndStartStreamers(start, length); - - if (m_StreamedSegments != null && m_StreamedSegments.Length > 0) - { - foreach (var r in m_StreamedSegments) - { - if (!m_Contexts.ContainsKey(r.streamer)) - m_Contexts.Add(r.streamer, new StreamingContext()); - } - } - } - - base.OnModifications(cFlags); - } - - void KillAndClearStreamers() - { - foreach (var c in m_Contexts) - { - c.Key.Stop(); - } - - m_Contexts.Clear(); - } - - Segment[] CalculateAndStartStreamers(double localStart, double localLength) - { - Segment[] segments = null; - var originalStart = localStart; - // we don't care about the global position, only the locally visible offset into the clip - localStart %= m_Clip.length; - - var secondsPerPixel = localLength / Size.x; - - if (!looping) - { - // holding (= !looping) is a special case handled before everything - // else, because it's very simple to implement since it defines a - // section capped by length of the clip - - if (originalStart > m_Clip.length) - return null; - - var clampedLength = Math.Min(m_Clip.length - originalStart, localLength); - var previewPixelsToRender = (int)Math.Min(Size.x, Size.x * Math.Max(0, clampedLength / localLength)); - - if (previewPixelsToRender < 1) - return null; - - segments = new Segment[1]; - - segments[0].streamer = new WaveformStreamer(m_Clip, originalStart, clampedLength, previewPixelsToRender, OnNewWaveformData); - segments[0].segmentLength = (int)Size.x; - segments[0].textureOffset = 0; - segments[0].streamingIndexOffset = 0; - - return segments; - } - - // epsilon added to discriminate between invisible floating point rounding errors - // and actual loops (i.e. more than a single pixel larger than then length) - if (localStart + localLength - secondsPerPixel > m_Clip.length) - { - var secondsToPixels = Size.x / localLength; - - // special case, the first part is clipped but at least one full length of the clip is available - // we can then use one streamer to fill in all visible segments - if (localLength >= m_Clip.length) - { - var numberOfLoops = localLength / m_Clip.length; - var streamer = new WaveformStreamer(m_Clip, 0, m_Clip.length, (int)(Size.x / numberOfLoops), OnNewWaveformData); - - var currentClipSegmentPart = m_Clip.length - localStart; - - var localPosition = 0.0; - - segments = new Segment[Mathf.CeilToInt((float)((localStart + localLength) / m_Clip.length))]; - - for (int i = 0; i < segments.Length; ++i) - { - var cappedLength = Math.Min(currentClipSegmentPart + localPosition, localLength) - localPosition; - segments[i].streamer = streamer; - segments[i].segmentLength = (int)(cappedLength * secondsToPixels); - segments[i].textureOffset = (int)(localPosition * secondsToPixels); - segments[i].streamingIndexOffset = (int)((m_Clip.length - currentClipSegmentPart) * secondsToPixels); - - localPosition += currentClipSegmentPart; - currentClipSegmentPart = m_Clip.length; - } - } - else - { - // two disjoint regions, since streaming is time-continuous we have to split it up in two portions - var firstPart = m_Clip.length - localStart; - var secondPart = localLength - firstPart; - - segments = new Segment[2]; - - segments[0].streamer = new WaveformStreamer(m_Clip, localStart, firstPart, (int)(firstPart * secondsToPixels), OnNewWaveformData); - segments[0].segmentLength = (int)(firstPart * secondsToPixels); - segments[0].textureOffset = 0; - segments[0].streamingIndexOffset = 0; - - segments[1].streamer = new WaveformStreamer(m_Clip, 0, secondPart, (int)(secondPart * secondsToPixels), OnNewWaveformData); - segments[1].segmentLength = (int)(secondPart * secondsToPixels); - segments[1].textureOffset = (int)(firstPart * secondsToPixels); - segments[1].streamingIndexOffset = 0; - } - } - else - { - // handle single visible part of clip, that does not extend beyond the end - // with a length less than a clip - equaling one streamer. - segments = new Segment[1]; - - segments[0].streamer = new WaveformStreamer(m_Clip, localStart, localLength, (int)Size.x, OnNewWaveformData); - segments[0].segmentLength = (int)Size.x; - segments[0].textureOffset = 0; - segments[0].streamingIndexOffset = 0; - } - - return segments; - } - - void UploadPreview(ClipPreviewDetails details) - { - var channels = details.clip.channels; - float[] resampledPreview = new float[(int)(channels * Size.x * 2)]; - - if (details.localStart + details.localLength > details.clip.length) - { - ResamplePreviewLooped(details, resampledPreview); - } - else - ResamplePreviewConfined(details, resampledPreview); - - SetMMWaveData(0, resampledPreview); - } - - void ResamplePreviewConfined(ClipPreviewDetails details, float[] resampledPreview) - { - var channels = m_Clip.channels; - var samples = details.previewSamples; - var delta = details.deltaStep; - var position = details.normalizedStart * samples; - var preview = details.preview; - - if (delta > 0.5) - { - int oldPosition = (int)position, floorPosition = oldPosition; - // for each step, there's more than one sample so we do min max on the min max data - // to avoid aliasing issues - for (int i = 0; i < details.previewPixelsToRender; ++i) - { - for (int c = 0; c < channels; ++c) - { - var x = oldPosition; - floorPosition = (int)position; - - float min = preview[2 * x * channels + c * 2]; - float max = preview[2 * x * channels + c * 2 + 1]; - - while (++x < floorPosition) - { - // yes, the data contained in the min max audio util overview is actually swapped (maxmin data) - min = Mathf.Max(min, preview[2 * x * channels + c * 2]); - max = Mathf.Min(max, preview[2 * x * channels + c * 2 + 1]); - } - - resampledPreview[2 * i * channels + c * 2] = max; - resampledPreview[2 * i * channels + c * 2 + 1] = min; - } - - position += delta; - oldPosition = floorPosition; - } - } - else - { - // fractionate interpolation - for (int i = 0; i < details.previewPixelsToRender; ++i) - { - var x = (int)(position - 1); - var x1 = x + 1; - float fraction = (float)((position - 1) - x); - - x = Mathf.Max(0, x); - x1 = Mathf.Min(x1, samples - 1); - - for (int c = 0; c < channels; ++c) - { - var minCurrent = preview[2 * x * channels + c * 2]; - var maxCurrent = preview[2 * x * channels + c * 2 + 1]; - - var minNext = preview[2 * x1 * channels + c * 2]; - var maxNext = preview[2 * x1 * channels + c * 2 + 1]; - - resampledPreview[2 * i * channels + c * 2] = fraction * maxNext + (1 - fraction) * maxCurrent; - resampledPreview[2 * i * channels + c * 2 + 1] = fraction * minNext + (1 - fraction) * minCurrent; - } - - position += delta; - } - } - } - - void ResamplePreviewLooped(ClipPreviewDetails details, float[] resampledPreview) - { - var previewSize = details.preview.Length; - var channels = m_Clip.channels; - var samples = details.previewSamples; - - var delta = details.deltaStep; - var position = details.normalizedStart * samples; - var preview = details.preview; - - if (delta > 0.5) - { - int oldPosition = (int)position, floorPosition = oldPosition; - // for each step, there's more than one sample so we do min max on the min max data - // to avoid aliasing issues - for (int i = 0; i < details.previewPixelsToRender; ++i) - { - for (int c = 0; c < channels; ++c) - { - var x = oldPosition; - floorPosition = (int)position; - - var wrappedIndex = (2 * x * channels + c * 2) % previewSize; - - float min = preview[wrappedIndex]; - float max = preview[wrappedIndex + 1]; - - while (++x < floorPosition) - { - wrappedIndex = (2 * x * channels + c * 2) % previewSize; - // yes, the data contained in the min max audio util overview is actually swapped (maxmin data) - min = Mathf.Max(min, preview[wrappedIndex]); - max = Mathf.Min(max, preview[wrappedIndex + 1]); - } - - resampledPreview[2 * i * channels + c * 2] = max; - resampledPreview[2 * i * channels + c * 2 + 1] = min; - } - - position += delta; - oldPosition = floorPosition; - } - } - else - { - // fractionate interpolation - for (int i = 0; i < details.previewPixelsToRender; ++i) - { - var x = (int)(position - 1); - var x1 = x + 1; - float fraction = (float)((position - 1) - x); - - for (int c = 0; c < channels; ++c) - { - var xWrapped = (2 * x * channels + c * 2) % previewSize; - - var minCurrent = preview[xWrapped]; - var maxCurrent = preview[xWrapped + 1]; - - var x1Wrapped = (2 * x1 * channels + c * 2) % previewSize; - - var minNext = preview[x1Wrapped]; - var maxNext = preview[x1Wrapped + 1]; - - resampledPreview[2 * i * channels + c * 2] = fraction * maxNext + (1 - fraction) * maxCurrent; - resampledPreview[2 * i * channels + c * 2 + 1] = fraction * minNext + (1 - fraction) * minCurrent; - } - - position += delta; - } - } - } - - bool OnNewWaveformData(WaveformStreamer streamer, float[] data, int remaining) - { - StreamingContext c = m_Contexts[streamer]; - - int pixelPos = c.index / m_Clip.channels; - - for (var i = 0; i < m_StreamedSegments.Length; i++) - { - if (m_StreamedSegments[i].streamer == streamer && pixelPos >= m_StreamedSegments[i].streamingIndexOffset && m_StreamedSegments[i].segmentLength > (pixelPos - m_StreamedSegments[i].streamingIndexOffset)) - { - SetMMWaveData((m_StreamedSegments[i].textureOffset - m_StreamedSegments[i].streamingIndexOffset) * m_Clip.channels + c.index, data); - } - } - - c.index += data.Length / 2; - - return remaining != 0; - } - } -} diff --git a/Editor/Mono/Audio/WaveformPreview.cs b/Editor/Mono/Audio/WaveformPreview.cs deleted file mode 100644 index e53394c7a4..0000000000 --- a/Editor/Mono/Audio/WaveformPreview.cs +++ /dev/null @@ -1,273 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - class WaveformPreview : IDisposable - { - static int s_BaseTextureWidth = 4096; - static Material s_Material; - - public double start { get { return m_Start; } } - public double length { get { return m_Length; } } - - public Color backgroundColor { get; set; } - public Color waveColor { get; set; } - public event Action updated; - public UnityEngine.Object presentedObject; - - public bool optimized - { - get { return m_Optimized; } - set - { - if (m_Optimized != value) - { - if (value) - m_Dirty = true; - - m_Optimized = value; - m_Flags |= MessageFlags.Optimization; - } - } - } - - public bool looping - { - get { return m_Looping; } - set - { - if (m_Looping != value) - { - m_Dirty = true; - m_Looping = value; - m_Flags |= MessageFlags.Looping; - } - } - } - - public enum ChannelMode - { - MonoSum, - Separate, - SpecificChannel - } - - [Flags] - protected enum MessageFlags - { - None = 0, - Size = 1 << 0, - Length = 1 << 1, - Start = 1 << 2, - Optimization = 1 << 3, - TextureChanged = 1 << 4, - ContentsChanged = 1 << 5, - Looping = 1 << 6 - } - - protected static bool HasFlag(MessageFlags flags, MessageFlags test) - { - return (flags & test) != 0; - } - - protected double m_Start; - protected double m_Length; - protected bool m_ClearTexture = true; - protected Vector2 Size { get { return m_Size; } } - - Texture2D m_Texture; - Vector2 m_Size; - int m_Channels; - int m_Samples; - int m_SpecificChannel; - ChannelMode m_ChannelMode; - - bool m_Looping; - bool m_Optimized; - bool m_Dirty; - bool m_Disposed; - MessageFlags m_Flags; - - protected WaveformPreview(UnityEngine.Object presentedObject, int samplesAndWidth, int channels) - { - this.presentedObject = presentedObject; - optimized = true; - m_Samples = samplesAndWidth; - m_Channels = channels; - backgroundColor = new Color(40 / 255.0f, 40 / 255.0f, 40 / 255.0f, 1.0f); - waveColor = new Color(255.0f / 255.0f, 140.0f / 255.0f, 0 / 255.0f, 1.0f); - UpdateTexture(samplesAndWidth, channels); - } - - protected internal WaveformPreview(UnityEngine.Object presentedObject, int samplesAndWidth, int channels, bool deferTextureCreation) - { - this.presentedObject = presentedObject; - optimized = true; - m_Samples = samplesAndWidth; - m_Channels = channels; - backgroundColor = new Color(40 / 255.0f, 40 / 255.0f, 40 / 255.0f, 1.0f); - waveColor = new Color(255.0f / 255.0f, 140.0f / 255.0f, 0 / 255.0f, 1.0f); - if (!deferTextureCreation) - UpdateTexture(samplesAndWidth, channels); - } - - public void Dispose() - { - if (!m_Disposed) - { - m_Disposed = true; - InternalDispose(); - - if (m_Texture != null) - UnityEngine.Object.Destroy(m_Texture); - - m_Texture = null; - } - } - - protected virtual void InternalDispose() {} - - public void Render(Rect rect) - { - if (s_Material == null) - { - s_Material = EditorGUIUtility.LoadRequired("Previews/PreviewAudioClipWaveform.mat") as Material; - } - - s_Material.SetTexture("_WavTex", m_Texture); - s_Material.SetFloat("_SampCount", m_Samples); - s_Material.SetFloat("_ChanCount", m_Channels); - s_Material.SetFloat("_RecPixelSize", 1.0f / rect.height); - s_Material.SetColor("_BacCol", backgroundColor); - s_Material.SetColor("_ForCol", waveColor); - - int mode = -2; - - if (m_ChannelMode == ChannelMode.Separate) - mode = -1; - else if (m_ChannelMode == ChannelMode.SpecificChannel) - mode = m_SpecificChannel; - - s_Material.SetInt("_ChanDrawMode", mode); - - Graphics.DrawTexture(rect, m_Texture, s_Material); - } - - public bool ApplyModifications() - { - if (m_Dirty || m_Texture == null) - { - m_Flags |= UpdateTexture((int)m_Size.x, m_Channels) ? MessageFlags.TextureChanged : MessageFlags.None; - OnModifications(m_Flags); - m_Flags = MessageFlags.None; - - m_Texture.Apply(); - m_Dirty = false; - return true; - } - - return false; - } - - public void SetChannelMode(ChannelMode mode, int specificChannelToRender) - { - m_ChannelMode = mode; - m_SpecificChannel = specificChannelToRender; - } - - public void SetChannelMode(ChannelMode mode) - { - SetChannelMode(mode, 0); - } - - bool UpdateTexture(int width, int channels) - { - int widthWithChannels = width * channels; - int textureHeight = 1 + widthWithChannels / s_BaseTextureWidth; - - Action updateTexture = - clear => - { - if (m_Texture == null) - { - m_Texture = new Texture2D(s_BaseTextureWidth, textureHeight, TextureFormat.RGBAHalf, false, true); - m_Texture.filterMode = FilterMode.Point; - clear = false; - } - else - { - m_Texture.Resize(s_BaseTextureWidth, textureHeight); - } - - if (!clear) - return; - - var fillColorArray = m_Texture.GetPixels(); - for (var i = 0; i < fillColorArray.Length; ++i) - fillColorArray[i] = Color.black; - - m_Texture.SetPixels(fillColorArray); - }; - - if (width == m_Samples && channels == m_Channels && m_Texture != null) - { - return false; - } - - // resample texture here - updateTexture(m_ClearTexture); - - m_Samples = width; - m_Channels = channels; - - return m_Dirty = true; - } - - public void OptimizeForSize(Vector2 newSize) - { - newSize = new Vector2(Mathf.Ceil(newSize.x), Mathf.Ceil(newSize.y)); - - if (newSize.x != m_Size.x) - { - m_Size = newSize; - m_Flags |= MessageFlags.Size; - m_Dirty = true; - } - } - - protected virtual void OnModifications(MessageFlags changedFlags) {} - - public void SetTimeInfo(double start, double length) - { - if (start != m_Start || length != m_Length) - { - m_Start = start; - m_Length = length; - m_Dirty = true; - m_Flags |= MessageFlags.Start | MessageFlags.Length; - } - } - - public virtual void SetMMWaveData(int interleavedOffset, float[] data) - { - // could be optimized, but profiling shows it isn't the bottleneck at all - for (int i = 0; i < data.Length; interleavedOffset++, i += 2) - { - int x = interleavedOffset % s_BaseTextureWidth; - int y = interleavedOffset / s_BaseTextureWidth; - m_Texture.SetPixel(x, y, new Color(data[i], data[i + 1], 0.0f, 0.0f)); - } - - m_Dirty = true; - m_Flags |= MessageFlags.ContentsChanged; - - if (updated != null) - updated(); - } - } -} diff --git a/Editor/Mono/Audio/WaveformPreviewFactory.cs b/Editor/Mono/Audio/WaveformPreviewFactory.cs deleted file mode 100644 index 23578dd93e..0000000000 --- a/Editor/Mono/Audio/WaveformPreviewFactory.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Reflection; -using UnityEngine; - - -namespace UnityEditor -{ - static class WaveformPreviewFactory - { - public static WaveformPreview Create(int initialSize, AudioClip clip) - { - return new StreamedAudioClipPreview(clip, initialSize); - } - } -} diff --git a/Editor/Mono/Audio/WaveformStreamer.bindings.cs b/Editor/Mono/Audio/WaveformStreamer.bindings.cs deleted file mode 100644 index 0b6ec9ccf6..0000000000 --- a/Editor/Mono/Audio/WaveformStreamer.bindings.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeType(Header = "Editor/Mono/Audio/WaveformStreamer.bindings.h")] - internal sealed partial class WaveformStreamer - { - internal IntPtr m_Data; - - public bool done - { - get { return Internal_WaveformStreamerQueryFinishedStatus(m_Data); } - } - public void Stop() - { - Internal_WaveformStreamerStop(m_Data); - } - - public WaveformStreamer(AudioClip clip, double start, double duration, - int numOutputSamples, Func onNewWaveformData) - { - m_Data = Internal_WaveformStreamerCreate(this, clip, start, duration, numOutputSamples, onNewWaveformData); - } - - private WaveformStreamer(AudioClip clip, double start, double duration, - int numOutputSamples, Func onNewWaveformData) - { - m_Data = Internal_WaveformStreamerCreateUntyped(this, clip, start, duration, numOutputSamples, onNewWaveformData); - } - - ~WaveformStreamer() - { - if (m_Data != IntPtr.Zero) - Internal_WaveformStreamerDestroy(m_Data); - } - - internal static object CreateUntypedWaveformStreamer(AudioClip clip, double start, double duration, - int numOutputSamples, Func onNewWaveformData) - { - return new WaveformStreamer(clip, start, duration, numOutputSamples, onNewWaveformData); - } - - [NativeThrows] - internal static extern IntPtr Internal_WaveformStreamerCreate(WaveformStreamer instance, [NotNull] AudioClip clip, double start, double duration, - int numOutputSamples, [NotNull] Func onNewWaveformData); - - internal static extern bool Internal_WaveformStreamerQueryFinishedStatus(IntPtr streamer); - - internal static extern void Internal_WaveformStreamerStop(IntPtr streamer); - - [NativeThrows] - internal static extern IntPtr Internal_WaveformStreamerCreateUntyped(object instance, [NotNull] AudioClip clip, double start, double duration, - int numOutputSamples, [NotNull] Func onNewWaveformData); - - [NativeMethod(IsThreadSafe = true)] - internal static extern void Internal_WaveformStreamerDestroy(IntPtr streamer); - } -} diff --git a/Editor/Mono/AvatarUtility.bindings.cs b/Editor/Mono/AvatarUtility.bindings.cs deleted file mode 100644 index 350561d434..0000000000 --- a/Editor/Mono/AvatarUtility.bindings.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - [NativeHeader("Runtime/Animation/Animator.h")] - [NativeHeader("Editor/Src/Animation/AvatarUtility.h")] - internal class AvatarUtility - { - extern static internal void SetHumanPose(Animator animator, float[] dof); - } -} diff --git a/Editor/Mono/BlendTree.bindings.cs b/Editor/Mono/BlendTree.bindings.cs deleted file mode 100644 index 835371be5c..0000000000 --- a/Editor/Mono/BlendTree.bindings.cs +++ /dev/null @@ -1,131 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; -using UnityEditor; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditor.Animations -{ - public enum BlendTreeType - { - Simple1D = 0 , - SimpleDirectional2D = 1, - FreeformDirectional2D = 2, - FreeformCartesian2D = 3, - Direct = 4 - } - - [NativeType("Editor/Src/Animation/BlendTree.h")] - [StructLayout(LayoutKind.Sequential)] - public struct ChildMotion - { - public Motion motion { get { return m_Motion; } set { m_Motion = value; } } - public float threshold { get { return m_Threshold; } set { m_Threshold = value; } } - public Vector2 position { get { return m_Position; } set { m_Position = value; } } - public float timeScale { get { return m_TimeScale; } set { m_TimeScale = value; } } - public float cycleOffset { get { return m_CycleOffset; } set { m_CycleOffset = value; } } - public string directBlendParameter { get { return m_DirectBlendParameter; } set { m_DirectBlendParameter = value; }} - public bool mirror { get { return m_Mirror; } set { m_Mirror = value; } } - - Motion m_Motion; - float m_Threshold; - Vector2 m_Position; - float m_TimeScale; - float m_CycleOffset; - string m_DirectBlendParameter; - bool m_Mirror; - } - - [NativeHeader("Editor/Src/Animation/BlendTree.bindings.h")] - [NativeType("Editor/Src/Animation/BlendTree.h")] - public partial class BlendTree : Motion - { - public BlendTree() - { - Internal_Create(this); - } - - [FreeFunction("BlendTreeBindings::Internal_Create")] - extern private static void Internal_Create([Writable] BlendTree self); - - extern public string blendParameter - { - get; - set; - } - extern public string blendParameterY - { - get; - set; - } - extern public BlendTreeType blendType - { - get; - set; - } - - extern public ChildMotion[] children - { - get; - set; - } - - extern internal int GetChildMotionCount(); - - internal Motion GetChildMotion(int index) - { - if (index < 0 && index >= GetChildMotionCount()) - throw new ArgumentOutOfRangeException("index"); - - return Internal_GetChildMotion(index); - } - - [NativeMethod("GetChildMotion")] - extern internal Motion Internal_GetChildMotion(int index); - - [NativeMethod("SetDirectBlendParameter")] - extern internal void SetDirectBlendTreeParameter(int index, string parameter); - - [NativeMethod("GetDirectBlendParameter")] - extern internal string GetDirectBlendTreeParameter(int index); - - extern public bool useAutomaticThresholds - { - get; - set; - } - extern public float minThreshold - { - get; - set; - } - extern public float maxThreshold - { - get; - set; - } - - extern internal void SortChildren(); - - extern internal int recursiveBlendParameterCount - { - get; - } - extern internal string GetRecursiveBlendParameter(int index); - extern internal float GetRecursiveBlendParameterMin(int index); - extern internal float GetRecursiveBlendParameterMax(int index); - - extern internal void SetInputBlendValue(string blendValueName, float value); - extern internal float GetInputBlendValue(string blendValueName); - - [NativeMethod("GetAnimationClips")] - extern internal AnimationClip[] GetAnimationClipsFlattened(); - } -} diff --git a/Editor/Mono/BlendTreePreviewUtility.bindings.cs b/Editor/Mono/BlendTreePreviewUtility.bindings.cs deleted file mode 100644 index fc5ac39bd6..0000000000 --- a/Editor/Mono/BlendTreePreviewUtility.bindings.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEngine.Internal; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace UnityEditorInternal -{ - [NativeHeader("Editor/Src/Animation/BlendTreePreviewUtility.h")] - public class BlendTreePreviewUtility - { - extern public static void GetRootBlendTreeChildWeights(Animator animator, int layerIndex, int stateHash, [Out] float[] weightArray); - - extern public static void CalculateRootBlendTreeChildWeights(Animator animator, int layerIndex, int stateHash, [Out] float[] weightArray, float blendX, float blendY); - - public static void CalculateBlendTexture(Animator animator, int layerIndex, int stateHash, Texture2D blendTexture, Texture2D[] weightTextures, Rect rect) - { - CalculateBlendTexture(animator, layerIndex, stateHash, blendTexture, weightTextures, rect.x, rect.y, rect.x + rect.width, rect.y + rect.height); - } - - extern protected static void CalculateBlendTexture(Animator animator, int layerIndex, int stateHash, Texture2D blendTexture, Texture2D[] weightTextures, float minX, float minY, float maxX, float maxY); - } -} diff --git a/Editor/Mono/BuildPipeline/AssemblyStripper.cs b/Editor/Mono/BuildPipeline/AssemblyStripper.cs deleted file mode 100644 index 975fd45365..0000000000 --- a/Editor/Mono/BuildPipeline/AssemblyStripper.cs +++ /dev/null @@ -1,314 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using UnityEditor.Build.Reporting; -using UnityEditor.Modules; -using UnityEditor.Scripting; -using UnityEditor.Scripting.Compilers; -using UnityEngine; -using UnityEditor; -using UnityEditor.Utils; -using Debug = UnityEngine.Debug; -using PackageInfo = Unity.DataContract.PackageInfo; - -namespace UnityEditorInternal -{ - internal class AssemblyStripper - { - private static bool debugUnstripped - { - get - { - return false; - } - } - - private static string[] Il2CppBlacklistPaths - { - get - { - return new[] { - Path.Combine("..", "platform_native_link.xml") - }; - } - } - - private static string MonoLinker2Path - { - get - { - return Path.Combine(MonoInstallationFinder.GetFrameWorksFolder(), "il2cpp/build/UnityLinker.exe"); - } - } - - private static string GetModuleWhitelist(string module, string moduleStrippingInformationFolder) - { - return Paths.Combine(moduleStrippingInformationFolder, module + ".xml"); - } - - private static bool StripAssembliesTo(string[] assemblies, string[] searchDirs, string outputFolder, string workingDirectory, out string output, out string error, string linkerPath, IIl2CppPlatformProvider platformProvider, IEnumerable additionalBlacklist) - { - if (!Directory.Exists(outputFolder)) - Directory.CreateDirectory(outputFolder); - - additionalBlacklist = additionalBlacklist.Select(s => Path.IsPathRooted(s) ? s : Path.Combine(workingDirectory, s)).Where(File.Exists); - - var userBlackLists = GetUserBlacklistFiles(); - - foreach (var ub in userBlackLists) - Console.WriteLine("UserBlackList: " + ub); - - additionalBlacklist = additionalBlacklist.Concat(userBlackLists); - - var args = new List - { - "--api=" + PlayerSettings.GetApiCompatibilityLevel(EditorUserBuildSettings.activeBuildTargetGroup).ToString(), - "-out=\"" + outputFolder + "\"", - "-l=none", - "-c=link", - "--link-symbols", - "-x=\"" + GetModuleWhitelist("Core", platformProvider.moduleStrippingInformationFolder) + "\"", - "-f=\"" + Path.Combine(platformProvider.il2CppFolder, "LinkerDescriptors") + "\"" - }; - args.AddRange(additionalBlacklist.Select(path => "-x \"" + path + "\"")); - - args.AddRange(searchDirs.Select(d => "-d \"" + d + "\"")); - args.AddRange(assemblies.Select(assembly => "-a \"" + Path.GetFullPath(assembly) + "\"")); - - return RunAssemblyLinker(args, out output, out error, linkerPath, workingDirectory); - } - - private static bool RunAssemblyLinker(IEnumerable args, out string @out, out string err, string linkerPath, string workingDirectory) - { - var argString = args.Aggregate((buff, s) => buff + " " + s); - Console.WriteLine("Invoking UnityLinker with arguments: " + argString); - Runner.RunManagedProgram(linkerPath, argString, workingDirectory, null, null); - - @out = ""; - err = ""; - - return true; - } - - private static List GetUserAssemblies(RuntimeClassRegistry rcr, string managedDir) - { - return rcr.GetUserAssemblies().Where(s => rcr.IsDLLUsed(s)).Select(s => Path.Combine(managedDir, s)).ToList(); - } - - internal static void StripAssemblies(string managedAssemblyFolderPath, IIl2CppPlatformProvider platformProvider, RuntimeClassRegistry rcr) - { - var assemblies = GetUserAssemblies(rcr, managedAssemblyFolderPath); - assemblies.AddRange(Directory.GetFiles(managedAssemblyFolderPath, "I18N*.dll", SearchOption.TopDirectoryOnly)); - var assembliesToStrip = assemblies.ToArray(); - - var searchDirs = new[] - { - managedAssemblyFolderPath - }; - - RunAssemblyStripper(assemblies, managedAssemblyFolderPath, assembliesToStrip, searchDirs, MonoLinker2Path, platformProvider, rcr); - } - - internal static void GenerateInternalCallSummaryFile(string icallSummaryPath, string managedAssemblyFolderPath, string strippedDLLPath) - { - var exe = Path.Combine(MonoInstallationFinder.GetFrameWorksFolder(), "Tools/InternalCallRegistrationWriter/InternalCallRegistrationWriter.exe"); - var dlls = Directory.GetFiles(strippedDLLPath, "UnityEngine.*Module.dll").Concat(new[] {Path.Combine(strippedDLLPath, "UnityEngine.dll")}); - var args = string.Format("-output=\"{0}\" -summary=\"{1}\" -assembly=\"{2}\"", - Path.Combine(managedAssemblyFolderPath, "UnityICallRegistration.cpp"), - icallSummaryPath, - dlls.Aggregate((dllArg, next) => dllArg + ";" + next) - ); - Runner.RunManagedProgram(exe, args); - } - - internal static IEnumerable GetUserBlacklistFiles() - { - return Directory.GetFiles("Assets", "link.xml", SearchOption.AllDirectories).Select(s => Path.Combine(Directory.GetCurrentDirectory(), s)); - } - - private static bool AddWhiteListsForModules(IEnumerable nativeModules, ref IEnumerable blacklists, string moduleStrippingInformationFolder) - { - bool result = false; - foreach (var module in nativeModules) - { - var moduleWhitelist = GetModuleWhitelist(module, moduleStrippingInformationFolder); - - if (File.Exists(moduleWhitelist)) - { - if (!blacklists.Contains(moduleWhitelist)) - { - blacklists = blacklists.Concat(new[] { moduleWhitelist }); - result = true; - } - } - } - return result; - } - - private static void RunAssemblyStripper(IEnumerable assemblies, string managedAssemblyFolderPath, string[] assembliesToStrip, string[] searchDirs, string monoLinkerPath, IIl2CppPlatformProvider platformProvider, RuntimeClassRegistry rcr) - { - string output; - string error; - var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(platformProvider.target); - bool isMono = PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.Mono2x; - bool stripEngineCode = rcr != null && PlayerSettings.stripEngineCode && platformProvider.supportsEngineStripping; - IEnumerable blacklists = Il2CppBlacklistPaths; - if (rcr != null) - { - blacklists = blacklists.Concat(new[] { - WriteMethodsToPreserveBlackList(rcr, platformProvider.target), - WriteUnityEngineBlackList(), - MonoAssemblyStripping.GenerateLinkXmlToPreserveDerivedTypes(managedAssemblyFolderPath, rcr) - }); - } - - if (PlayerSettingsEditor.IsLatestApiCompatibility(PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup))) - { - var il2cppFolder = Path.Combine(platformProvider.il2CppFolder, "LinkerDescriptors"); - blacklists = blacklists.Concat(Directory.GetFiles(il2cppFolder, "*45.xml")); - } - if (isMono) - { - // Apply mono-specific assembly whitelists, taken from old Mono assembly stripping code path. - var il2cppFolder = Path.Combine(platformProvider.il2CppFolder, "LinkerDescriptors"); - blacklists = blacklists.Concat(Directory.GetFiles(il2cppFolder, "*_mono.xml")); - - // The old Mono assembly stripper uses per-platform link.xml files if available. Apply these here. - var platformDescriptor = Path.Combine(BuildPipeline.GetBuildToolsDirectory(platformProvider.target), "link.xml"); - if (File.Exists(platformDescriptor)) - blacklists = blacklists.Concat(new[] {platformDescriptor}); - } - - if (!stripEngineCode) - { - // if we don't do stripping, add all modules blacklists. - foreach (var file in Directory.GetFiles(platformProvider.moduleStrippingInformationFolder, "*.xml")) - blacklists = blacklists.Concat(new[] {file}); - } - - var tempStripPath = Path.GetFullPath(Path.Combine(managedAssemblyFolderPath, "tempStrip")); - - bool addedMoreBlacklists; - do - { - addedMoreBlacklists = false; - - if (EditorUtility.DisplayCancelableProgressBar("Building Player", "Stripping assemblies", 0.0f)) - throw new OperationCanceledException(); - - if (!StripAssembliesTo( - assembliesToStrip, - searchDirs, - tempStripPath, - managedAssemblyFolderPath, - out output, - out error, - monoLinkerPath, - platformProvider, - blacklists)) - throw new Exception("Error in stripping assemblies: " + assemblies + ", " + error); - - if (platformProvider.supportsEngineStripping) - { - var icallSummaryPath = Path.Combine(managedAssemblyFolderPath, "ICallSummary.txt"); - GenerateInternalCallSummaryFile(icallSummaryPath, managedAssemblyFolderPath, tempStripPath); - - if (stripEngineCode) - { - // Find which modules we must include in the build based on Assemblies - HashSet nativeClasses; - HashSet nativeModules; - CodeStrippingUtils.GenerateDependencies(tempStripPath, icallSummaryPath, rcr, stripEngineCode, out nativeClasses, out nativeModules, platformProvider); - // Add module-specific blacklists. - addedMoreBlacklists = AddWhiteListsForModules(nativeModules, ref blacklists, platformProvider.moduleStrippingInformationFolder); - } - } - - // If we had to add more whitelists, we need to run AssemblyStripper again with the added whitelists. - } - while (addedMoreBlacklists); - - // keep unstripped files for debugging purposes - var tempUnstrippedPath = Path.GetFullPath(Path.Combine(managedAssemblyFolderPath, "tempUnstripped")); - if (debugUnstripped) - Directory.CreateDirectory(tempUnstrippedPath); - foreach (var file in Directory.GetFiles(managedAssemblyFolderPath)) - { - var extension = Path.GetExtension(file); - if (string.Equals(extension, ".dll", StringComparison.InvariantCultureIgnoreCase) || - string.Equals(extension, ".winmd", StringComparison.InvariantCultureIgnoreCase) || - string.Equals(extension, ".mdb", StringComparison.InvariantCultureIgnoreCase) || - string.Equals(extension, ".pdb", StringComparison.InvariantCultureIgnoreCase)) - { - if (debugUnstripped) - File.Move(file, Path.Combine(tempUnstrippedPath, Path.GetFileName(file))); - else - File.Delete(file); - } - } - - foreach (var file in Directory.GetFiles(tempStripPath)) - File.Move(file, Path.Combine(managedAssemblyFolderPath, Path.GetFileName(file))); - Directory.Delete(tempStripPath); - } - - private static string WriteMethodsToPreserveBlackList(RuntimeClassRegistry rcr, BuildTarget target) - { - var methodPerserveBlackList = Path.GetTempFileName(); - File.WriteAllText(methodPerserveBlackList, GetMethodPreserveBlacklistContents(rcr, target)); - return methodPerserveBlackList; - } - - private static string WriteUnityEngineBlackList() - { - // UnityEngine.dll would be stripped, as it contains no referenced symbols, only type forwarders. - // Since we need those type forwarders, we generate blacklist to preserve the assembly (but no members). - var unityEngineBlackList = Path.GetTempFileName(); - File.WriteAllText(unityEngineBlackList, ""); - return unityEngineBlackList; - } - - private static string GetMethodPreserveBlacklistContents(RuntimeClassRegistry rcr, BuildTarget target) - { - var sb = new StringBuilder(); - sb.AppendLine(""); - - var groupedByAssembly = rcr.GetMethodsToPreserve().GroupBy(m => m.assembly); - foreach (var assembly in groupedByAssembly) - { - var assemblyName = assembly.Key; - sb.AppendLine(string.Format("\t", assemblyName)); - var groupedByType = assembly.GroupBy(m => m.fullTypeName); - foreach (var type in groupedByType) - { - sb.AppendLine(string.Format("\t\t", type.Key)); - foreach (var method in type) - sb.AppendLine(string.Format("\t\t\t", method.methodName)); - sb.AppendLine("\t\t"); - } - sb.AppendLine("\t"); - } - - sb.AppendLine(""); - return sb.ToString(); - } - - static public void InvokeFromBuildPlayer(BuildTarget buildTarget, RuntimeClassRegistry usedClasses) - { - var stagingAreaData = Paths.Combine("Temp", "StagingArea", "Data"); - - var platformProvider = new BaseIl2CppPlatformProvider(buildTarget, Path.Combine(stagingAreaData, "Libraries")); - - var managedAssemblyFolderPath = Path.GetFullPath(Path.Combine(stagingAreaData, "Managed")); - AssemblyStripper.StripAssemblies(managedAssemblyFolderPath, platformProvider, usedClasses); - } - } -} diff --git a/Editor/Mono/BuildPipeline/AssemblyTypeInfoGenerator.cs b/Editor/Mono/BuildPipeline/AssemblyTypeInfoGenerator.cs deleted file mode 100644 index 82be57f2b6..0000000000 --- a/Editor/Mono/BuildPipeline/AssemblyTypeInfoGenerator.cs +++ /dev/null @@ -1,429 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -// #define DOLOG -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using Mono.Cecil; -using Unity.SerializationLogic; - -namespace UnityEditor -{ - using GenericInstanceTypeMap = System.Collections.Generic.Dictionary; - - internal class AssemblyTypeInfoGenerator - { - [Flags] - public enum FieldInfoFlags - { - None = 0, - FixedBuffer = (1 << 0) - } - - [StructLayout(LayoutKind.Sequential)] - public struct FieldInfo - { - public string name; - public string type; - public FieldInfoFlags flags; - public int fixedBufferLength; - public string fixedBufferTypename; - }; - - [StructLayout(LayoutKind.Sequential)] - public struct ClassInfo - { - public string name; - public FieldInfo[] fields; - }; - - - private AssemblyDefinition assembly_; - private List classes_ = new List(); - private TypeResolver typeResolver = new TypeResolver(null); - - public ClassInfo[] ClassInfoArray - { - get { return classes_.ToArray(); } - } - - private class AssemblyResolver : BaseAssemblyResolver - { - public static IAssemblyResolver WithSearchDirs(params string[] searchDirs) - { - var resolver = new AssemblyResolver(); - foreach (var searchDir in searchDirs) - resolver.AddSearchDirectory(searchDir); - - // remove the two directories installed by default as this can cause issues with assemblies outside of the Assets folder - resolver.RemoveSearchDirectory("."); - resolver.RemoveSearchDirectory("bin"); - - return resolver; - } - - readonly IDictionary m_Assemblies; - - private AssemblyResolver() - : this(new Hashtable()) - { - } - - private AssemblyResolver(IDictionary assemblyCache) - { - m_Assemblies = assemblyCache; - } - - public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) - { - var asm = (AssemblyDefinition)m_Assemblies[name.Name]; - if (asm != null) - return asm; - - asm = base.Resolve(name, parameters); - m_Assemblies[name.Name] = asm; - - return asm; - } - } - - public AssemblyTypeInfoGenerator(string assembly, string[] searchDirs) - { - assembly_ = AssemblyDefinition.ReadAssembly(assembly, new ReaderParameters - { - AssemblyResolver = AssemblyResolver.WithSearchDirs(searchDirs) - }); - } - - public AssemblyTypeInfoGenerator(string assembly, IAssemblyResolver resolver) - { - assembly_ = AssemblyDefinition.ReadAssembly(assembly, new ReaderParameters - { - AssemblyResolver = resolver - }); - } - - // In embedded API inner names are separated by plus instead of fwdslash, eg. MyClass+MyInner, not MyClass/MyInner - // so we convert '/' to '+' here. - // Generic parameters are placed in square brackets instead of angle brackets - private string GetMonoEmbeddedFullTypeNameFor(TypeReference type) - { - var typeSpec = type as TypeSpecification; - string typeName; - - // Strip modifiers like volatile, as Mono doesn't treat them as part of type - if (typeSpec != null && typeSpec.IsRequiredModifier) - { - type = typeSpec.ElementType; - } - else if (type.IsRequiredModifier) - { - type = type.GetElementType(); - } - - typeName = type.FullName; - - // Mono compiler generates internal types with names such as "__FixedBuffer0" and "c__Iterator0" - // so we only replace angle brackets with square brackets if the type is a generic instance or has generic parameters. - if (type.HasGenericParameters || type.IsGenericInstance) - typeName = typeName.Replace('<', '[').Replace('>', ']'); - - return typeName.Replace('/', '+'); - } - - /* We use this GenericInstanceTypeMap to map generic types to their generic instance types, - This is needed for correctly assess inheritance in cases like this: - - class One - { - public T one; - } - - class Two : One - { - } - - In this case, we look at type Two, and see that it inherits from type One, - so we map T -> int. When we come across looking at field "one", we see that its - declaring type is a generic instance type and that T maps to int, so it writes down - that class One has a field "int one". - - We use a new map for going through each type instance (check GatherClassInfo()). - */ - private TypeReference ResolveGenericInstanceType(TypeReference typeToResolve, GenericInstanceTypeMap genericInstanceTypeMap) - { - var arrayType = typeToResolve as ArrayType; - - if (arrayType != null) - { - typeToResolve = new ArrayType(ResolveGenericInstanceType(arrayType.ElementType, genericInstanceTypeMap), arrayType.Rank); - } - - while (genericInstanceTypeMap.ContainsKey(typeToResolve)) - { - typeToResolve = genericInstanceTypeMap[typeToResolve]; - } - - if (typeToResolve.IsGenericInstance) - { - // Handle the case of nested generics, like List>> - var genericInstance = ((GenericInstanceType)typeToResolve); - typeToResolve = MakeGenericInstance(genericInstance.ElementType, genericInstance.GenericArguments, genericInstanceTypeMap); - } - - return typeToResolve; - } - - private void AddType(TypeReference typeRef, GenericInstanceTypeMap genericInstanceTypeMap) - { - // Prevent duplicates - if (classes_.Any(x => x.name == GetMonoEmbeddedFullTypeNameFor(typeRef))) - { - return; - } - - TypeDefinition type; - - try - { - type = typeRef.Resolve(); - } // This will happen for types which we don't have access to, like Windows.Foundation.IAsyncOperation - catch (AssemblyResolutionException) - { - return; - } - catch (NotSupportedException) // "NotSupportedException: Version not supported: 255.255.255.255" is thrown when assembly references WinRT assembly (e.g. mscorlib) - { - return; - } - - if (type == null) return; - - if (typeRef.IsGenericInstance) - { - var arguments = ((GenericInstanceType)typeRef).GenericArguments; - var parameters = type.GenericParameters; - - for (int i = 0; i < arguments.Count; i++) - { - if (parameters[i] != arguments[i]) - { - genericInstanceTypeMap[parameters[i]] = arguments[i]; - } - } - - typeResolver.Add((GenericInstanceType)typeRef); - } - - /* Process class itself before nested/base types in case user does something evil, for example: - - class Outer - { - class Inner : Child - { - } - } - - class Child : Outer - { - } - */ - - bool shouldImplementDeserializable = false; - - try - { - shouldImplementDeserializable = UnitySerializationLogic.ShouldImplementIDeserializable(type); - } - catch - { - // If assembly has unknown reference (for ex., see tests VariousPlugins, where Metro plugins are used), skip field - } - - if (!shouldImplementDeserializable) - { - // In this case we only take care of processing the nested types, if any. - AddNestedTypes(type, genericInstanceTypeMap); - } - else - { - var ci = new ClassInfo(); - ci.name = GetMonoEmbeddedFullTypeNameFor(typeRef); - ci.fields = GetFields(type, typeRef.IsGenericInstance, genericInstanceTypeMap); - - classes_.Add(ci); - - // Fetch info for inner types - AddNestedTypes(type, genericInstanceTypeMap); - - // Add base type - AddBaseType(typeRef, genericInstanceTypeMap); - } - - if (typeRef.IsGenericInstance) - typeResolver.Remove((GenericInstanceType)typeRef); - } - - private void AddNestedTypes(TypeDefinition type, GenericInstanceTypeMap genericInstanceTypeMap) - { - foreach (TypeDefinition nestedType in type.NestedTypes) - { - AddType(nestedType, genericInstanceTypeMap); - } - } - - private void AddBaseType(TypeReference typeRef, GenericInstanceTypeMap genericInstanceTypeMap) - { - var baseType = typeRef.Resolve().BaseType; - if (baseType != null) - { - /* If we are processing generic instance type and - its base type happens to be a generic instance class as well, - we want to forward our generic arguments to the base. Consider: - - class One - { - T one; - } - - class Two : One - { - } - - class Three : Two - { - } - - In this case, three is inheriting from Two, - so we want Two to inherit from One, - however, cecil will tell us that base of Two is One, - therefore we have to create the generic instance type of One ourselves - */ - if (typeRef.IsGenericInstance && baseType.IsGenericInstance) - { - var genericInstance = ((GenericInstanceType)baseType); - baseType = MakeGenericInstance(genericInstance.ElementType, genericInstance.GenericArguments, genericInstanceTypeMap); - } - - AddType(baseType, genericInstanceTypeMap); - } - } - - private TypeReference MakeGenericInstance(TypeReference genericClass, IEnumerable arguments, GenericInstanceTypeMap genericInstanceTypeMap) - { - var genericInstance = new GenericInstanceType(genericClass); - - foreach (var argument in arguments.Select(x => ResolveGenericInstanceType(x, genericInstanceTypeMap))) - { - genericInstance.GenericArguments.Add(argument); - } - - return genericInstance; - } - - private FieldInfo[] GetFields(TypeDefinition type, bool isGenericInstance, GenericInstanceTypeMap genericInstanceTypeMap) - { - var fields = new List(); - - foreach (FieldDefinition field in type.Fields) - { - var fieldInfo = GetFieldInfo(type, field, isGenericInstance, genericInstanceTypeMap); - - if (fieldInfo != null) - { - fields.Add(fieldInfo.Value); - } - } - - return fields.ToArray(); - } - - private static CustomAttribute GetFixedBufferAttribute(FieldDefinition fieldDefinition) - { - if (!fieldDefinition.HasCustomAttributes) - return null; - - return fieldDefinition.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.FixedBufferAttribute"); - } - - private static int GetFixedBufferLength(CustomAttribute fixedBufferAttribute) - { - return (Int32)fixedBufferAttribute.ConstructorArguments[1].Value; - } - - private static string GetFixedBufferTypename(CustomAttribute fixedBufferAttribute) - { - var typeRef = (TypeReference)fixedBufferAttribute.ConstructorArguments[0].Value; - return typeRef.Name; - } - - private FieldInfo? GetFieldInfo(TypeDefinition type, FieldDefinition field, bool isDeclaringTypeGenericInstance, - GenericInstanceTypeMap genericInstanceTypeMap) - { - if (!WillSerialize(field)) - return null; - - var ti = new FieldInfo(); - ti.name = field.Name; - - TypeReference fieldType; - - if (isDeclaringTypeGenericInstance) - { - fieldType = ResolveGenericInstanceType(field.FieldType, genericInstanceTypeMap); - } - else - { - fieldType = field.FieldType; - } - - ti.type = GetMonoEmbeddedFullTypeNameFor(fieldType); - ti.flags = FieldInfoFlags.None; - - var fixedBufferAttribute = GetFixedBufferAttribute(field); - - if (fixedBufferAttribute != null) - { - ti.flags |= FieldInfoFlags.FixedBuffer; - ti.fixedBufferLength = GetFixedBufferLength(fixedBufferAttribute); - ti.fixedBufferTypename = GetFixedBufferTypename(fixedBufferAttribute); - } - return ti; - } - - private bool WillSerialize(FieldDefinition field) - { - try - { - return UnitySerializationLogic.WillUnitySerialize(field, typeResolver); - } - catch (Exception ex) - { - UnityEngine.Debug.LogFormat("Field '{0}' from '{1}', exception {2}", field.FullName, field.Module.FileName, ex.Message); - // If assembly has unknown reference (for ex., see tests VariousPlugins, where Metro plugins are used), skip field - return false; - } - } - - public ClassInfo[] GatherClassInfo() - { - foreach (ModuleDefinition module in assembly_.Modules) - { - foreach (TypeDefinition type in module.Types) - { - // Skip compiler-generated class - if (type.Name == "") - continue; - - AddType(type, new Dictionary()); - } - } - return classes_.ToArray(); - } - } -} diff --git a/Editor/Mono/BuildPipeline/AssemblyValidation.cs b/Editor/Mono/BuildPipeline/AssemblyValidation.cs deleted file mode 100644 index 14df74da4c..0000000000 --- a/Editor/Mono/BuildPipeline/AssemblyValidation.cs +++ /dev/null @@ -1,160 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEditor.Scripting.Compilers; -using UnityEngine; - -[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] -internal class AssemblyValidationRule : Attribute -{ - public int Priority; - - private readonly RuntimePlatform _platform; - - public AssemblyValidationRule(RuntimePlatform platform) - { - _platform = platform; - Priority = 0; - } - - public RuntimePlatform Platform - { - get { return _platform; } - } -} - -internal struct ValidationResult -{ - public bool Success; - public IValidationRule Rule; - public IEnumerable CompilerMessages; -} - -internal interface IValidationRule -{ - ValidationResult Validate(IEnumerable userAssemblies, params object[] options); -} - -internal class AssemblyValidation -{ - private static Dictionary> _rulesByPlatform; - - public static ValidationResult Validate(RuntimePlatform platform, IEnumerable userAssemblies, params object[] options) - { - WarmUpRulesCache(); - - var assemblies = userAssemblies as string[] ?? userAssemblies.ToArray(); - if (assemblies.Length != 0) - { - foreach (var validationRule in ValidationRulesFor(platform, options)) - { - var result = validationRule.Validate(assemblies, options); - if (!result.Success) - return result; - } - } - - return new ValidationResult { Success = true }; - } - - private static void WarmUpRulesCache() - { - if (_rulesByPlatform != null) - return; - - _rulesByPlatform = new Dictionary>(); - - var assembly = typeof(AssemblyValidation).Assembly; - foreach (var type in assembly.GetTypes().Where(IsValidationRule)) - RegisterValidationRule(type); - } - - private static bool IsValidationRule(Type type) - { - return ValidationRuleAttributesFor(type).Any(); - } - - private static IEnumerable ValidationRulesFor(RuntimePlatform platform, params object[] options) - { - return ValidationRuleTypesFor(platform).Select(t => CreateValidationRuleWithOptions(t, options)).Where(v => v != null); - } - - private static IEnumerable ValidationRuleTypesFor(RuntimePlatform platform) - { - if (!_rulesByPlatform.ContainsKey(platform)) - yield break; - - foreach (var validationType in _rulesByPlatform[platform]) - yield return validationType; - } - - private static IValidationRule CreateValidationRuleWithOptions(Type type, params object[] options) - { - var constructorOptions = new List(options); - while (true) - { - var currentOptions = constructorOptions.ToArray(); - var constructor = ConstructorFor(type, currentOptions); - if (constructor != null) - return (IValidationRule)constructor.Invoke(currentOptions); - - if (constructorOptions.Count == 0) - return null; - - constructorOptions.RemoveAt(constructorOptions.Count - 1); - } - } - - private static ConstructorInfo ConstructorFor(Type type, IEnumerable options) - { - var constructorArguments = options.Select(o => o.GetType()).ToArray(); - return type.GetConstructor(constructorArguments); - } - - internal static void RegisterValidationRule(Type type) - { - foreach (var attribute in ValidationRuleAttributesFor(type)) - RegisterValidationRuleForPlatform(attribute.Platform, type); - } - - internal static void RegisterValidationRuleForPlatform(RuntimePlatform platform, Type type) - { - if (!_rulesByPlatform.ContainsKey(platform)) - _rulesByPlatform[platform] = new List(); - - if (_rulesByPlatform[platform].IndexOf(type) == -1) - _rulesByPlatform[platform].Add(type); - - _rulesByPlatform[platform].Sort((a, b) => CompareValidationRulesByPriority(a, b, platform)); - } - - internal static int CompareValidationRulesByPriority(Type a, Type b, RuntimePlatform platform) - { - var aPriority = PriorityFor(a, platform); - var bPriority = PriorityFor(b, platform); - - if (aPriority == bPriority) - return 0; - - return (aPriority < bPriority ? -1 : 1); - } - - private static int PriorityFor(Type type, RuntimePlatform platform) - { - return - ValidationRuleAttributesFor(type). - Where(attr => attr.Platform == platform). - Select(attr => attr.Priority). - FirstOrDefault(); - } - - private static IEnumerable ValidationRuleAttributesFor(Type type) - { - return type.GetCustomAttributes(true).OfType(); - } -} diff --git a/Editor/Mono/BuildPipeline/BuildFailedException.cs b/Editor/Mono/BuildPipeline/BuildFailedException.cs deleted file mode 100644 index 5af2f66087..0000000000 --- a/Editor/Mono/BuildPipeline/BuildFailedException.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Scripting; - -namespace UnityEditor.Build -{ - [RequiredByNativeCode] - public class BuildFailedException : Exception - { - public BuildFailedException(string message) : - base(message) - { - } - - public BuildFailedException(Exception innerException) : - base(null, innerException) - { - } - - [RequiredByNativeCode] - private Exception BuildFailedException_GetInnerException() - { - return InnerException; - } - } -} diff --git a/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs b/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs deleted file mode 100644 index abf284f606..0000000000 --- a/Editor/Mono/BuildPipeline/BuildPipelineInterfaces.cs +++ /dev/null @@ -1,377 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Reflection; -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.Build.Reporting; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; - -namespace UnityEditor.Build -{ - public interface IOrderedCallback - { - int callbackOrder { get; } - } - - [Obsolete("Use IPreprocessBuildWithReport instead")] - public interface IPreprocessBuild : IOrderedCallback - { - void OnPreprocessBuild(BuildTarget target, string path); - } - - public interface IPreprocessBuildWithReport : IOrderedCallback - { - void OnPreprocessBuild(BuildReport report); - } - - [Obsolete("Use IPostprocessBuildWithReport instead")] - public interface IPostprocessBuild : IOrderedCallback - { - void OnPostprocessBuild(BuildTarget target, string path); - } - - public interface IPostprocessBuildWithReport : IOrderedCallback - { - void OnPostprocessBuild(BuildReport report); - } - - [Obsolete("Use IProcessSceneWithReport instead")] - public interface IProcessScene : IOrderedCallback - { - void OnProcessScene(UnityEngine.SceneManagement.Scene scene); - } - - public interface IProcessSceneWithReport : IOrderedCallback - { - void OnProcessScene(UnityEngine.SceneManagement.Scene scene, BuildReport report); - } - - public interface IActiveBuildTargetChanged : IOrderedCallback - { - void OnActiveBuildTargetChanged(BuildTarget previousTarget, BuildTarget newTarget); - } - - internal static class BuildPipelineInterfaces - { -#pragma warning disable 618 - private static List buildPreprocessors; - private static List buildPostprocessors; - private static List sceneProcessors; -#pragma warning restore 618 - - private static List buildPreprocessorsWithReport; - private static List buildPostprocessorsWithReport; - private static List sceneProcessorsWithReport; - - private static List buildTargetProcessors; - - [Flags] - internal enum BuildCallbacks - { - None = 0, - BuildProcessors = 1, - SceneProcessors = 2, - BuildTargetProcessors = 4 - } - - //common comparer for all callback types - internal static int CompareICallbackOrder(IOrderedCallback a, IOrderedCallback b) - { - return a.callbackOrder - b.callbackOrder; - } - - static void AddToList(object o, ref List list) where T : class - { - T inst = o as T; - if (inst == null) - return; - if (list == null) - list = new List(); - list.Add(inst); - } - - static void AddToListIfTypeImplementsInterface(Type t, ref object o, ref List list) where T : class - { - if (!ValidateType(t)) - return; - - if (o == null) - o = Activator.CreateInstance(t); - AddToList(o, ref list); - } - - private class AttributeCallbackWrapper : IPostprocessBuildWithReport, IProcessSceneWithReport, IActiveBuildTargetChanged - { - int m_callbackOrder; - MethodInfo m_method; - public int callbackOrder { get { return m_callbackOrder; } } - - public AttributeCallbackWrapper(MethodInfo m) - { - m_callbackOrder = ((CallbackOrderAttribute)Attribute.GetCustomAttribute(m, typeof(CallbackOrderAttribute))).callbackOrder; - m_method = m; - } - - public void OnActiveBuildTargetChanged(BuildTarget previousTarget, BuildTarget newTarget) - { - m_method.Invoke(null, new object[] { previousTarget, newTarget }); - } - - public void OnPostprocessBuild(BuildReport report) - { - m_method.Invoke(null, new object[] { report.summary.platform, report.summary.outputPath }); - } - - public void OnProcessScene(UnityEngine.SceneManagement.Scene scene, BuildReport report) - { - m_method.Invoke(null, null); - } - } - - //this variable is reinitialized on domain reload so any calls to Init after a domain reload will set things up correctly - static BuildCallbacks previousFlags = BuildCallbacks.None; - [RequiredByNativeCode] - internal static void InitializeBuildCallbacks(BuildCallbacks findFlags) - { - if (findFlags == previousFlags) - return; - - CleanupBuildCallbacks(); - previousFlags = findFlags; - - bool findBuildProcessors = (findFlags & BuildCallbacks.BuildProcessors) == BuildCallbacks.BuildProcessors; - bool findSceneProcessors = (findFlags & BuildCallbacks.SceneProcessors) == BuildCallbacks.SceneProcessors; - bool findTargetProcessors = (findFlags & BuildCallbacks.BuildTargetProcessors) == BuildCallbacks.BuildTargetProcessors; - var postProcessBuildAttributeParams = new Type[] { typeof(BuildTarget), typeof(string) }; - foreach (var t in EditorAssemblies.GetAllTypesWithInterface()) - { - if (t.IsAbstract || t.IsInterface) - continue; - - // Defer creating the instance until we actually add it to one of the lists - object instance = null; - - if (findBuildProcessors) - { - AddToListIfTypeImplementsInterface(t, ref instance, ref buildPreprocessors); - AddToListIfTypeImplementsInterface(t, ref instance, ref buildPreprocessorsWithReport); - AddToListIfTypeImplementsInterface(t, ref instance, ref buildPostprocessors); - AddToListIfTypeImplementsInterface(t, ref instance, ref buildPostprocessorsWithReport); - } - - if (findSceneProcessors) - { - AddToListIfTypeImplementsInterface(t, ref instance, ref sceneProcessors); - AddToListIfTypeImplementsInterface(t, ref instance, ref sceneProcessorsWithReport); - } - - if (findTargetProcessors) - { - AddToListIfTypeImplementsInterface(t, ref instance, ref buildTargetProcessors); - } - } - - if (findBuildProcessors) - { - foreach (var m in EditorAssemblies.GetAllMethodsWithAttribute()) - if (ValidateMethod(m, postProcessBuildAttributeParams)) - AddToList(new AttributeCallbackWrapper(m), ref buildPostprocessorsWithReport); - } - - if (findSceneProcessors) - { - foreach (var m in EditorAssemblies.GetAllMethodsWithAttribute()) - if (ValidateMethod(m, Type.EmptyTypes)) - AddToList(new AttributeCallbackWrapper(m), ref sceneProcessorsWithReport); - } - - if (buildPreprocessors != null) - buildPreprocessors.Sort(CompareICallbackOrder); - if (buildPreprocessorsWithReport != null) - buildPreprocessorsWithReport.Sort(CompareICallbackOrder); - if (buildPostprocessors != null) - buildPostprocessors.Sort(CompareICallbackOrder); - if (buildPostprocessorsWithReport != null) - buildPostprocessorsWithReport.Sort(CompareICallbackOrder); - if (buildTargetProcessors != null) - buildTargetProcessors.Sort(CompareICallbackOrder); - if (sceneProcessors != null) - sceneProcessors.Sort(CompareICallbackOrder); - if (sceneProcessorsWithReport != null) - sceneProcessorsWithReport.Sort(CompareICallbackOrder); - } - - internal static bool ValidateType(Type t) - { - return (typeof(T).IsAssignableFrom(t) && t != typeof(AttributeCallbackWrapper)); - } - - static bool ValidateMethod(MethodInfo method, Type[] expectedArguments) - { - Type attribute = typeof(T); - if (method.IsDefined(attribute, false)) - { - // Remove the `Attribute` from the name. - if (!method.IsStatic) - { - string atributeName = attribute.Name.Replace("Attribute", ""); - Debug.LogErrorFormat("Method {0} with {1} attribute must be static.", method.Name, atributeName); - return false; - } - - if (method.IsGenericMethod || method.IsGenericMethodDefinition) - { - string atributeName = attribute.Name.Replace("Attribute", ""); - Debug.LogErrorFormat("Method {0} with {1} attribute cannot be generic.", method.Name, atributeName); - return false; - } - - var parameters = method.GetParameters(); - bool signatureCorrect = parameters.Length == expectedArguments.Length; - if (signatureCorrect) - { - // Check types match - for (int i = 0; i < parameters.Length; ++i) - { - if (parameters[i].ParameterType != expectedArguments[i]) - { - signatureCorrect = false; - break; - } - } - } - - if (!signatureCorrect) - { - string atributeName = attribute.Name.Replace("Attribute", ""); - string expectedArgumentsString = "static void " + method.Name + "("; - - for (int i = 0; i < expectedArguments.Length; ++i) - { - expectedArgumentsString += expectedArguments[i].Name; - if (i != expectedArguments.Length - 1) - expectedArgumentsString += ", "; - } - expectedArgumentsString += ")"; - - Debug.LogErrorFormat("Method {0} with {1} attribute does not have the correct signature, expected: {2}.", method.Name, atributeName, expectedArgumentsString); - return false; - } - return true; - } - return false; - } - - private static bool InvokeCallbackInterfacesPair(List oneInterfaces, Action invocationOne, List twoInterfaces, Action invocationTwo, bool exitOnFailure) where T1 : IOrderedCallback where T2 : IOrderedCallback - { - if (oneInterfaces == null && twoInterfaces == null) - return true; - - // 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. - // So, we have to walk both lists simultaneously, calling whichever callback has the lower ordering value - IEnumerator e1 = (oneInterfaces != null) ? (IEnumerator)oneInterfaces.GetEnumerator() : null; - IEnumerator e2 = (twoInterfaces != null) ? (IEnumerator)twoInterfaces.GetEnumerator() : null; - if (e1 != null && !e1.MoveNext()) - e1 = null; - if (e2 != null && !e2.MoveNext()) - e2 = null; - - while (e1 != null || e2 != null) - { - try - { - if (e1 != null && (e2 == null || e1.Current.callbackOrder < e2.Current.callbackOrder)) - { - var callback = e1.Current; - if (!e1.MoveNext()) - e1 = null; - invocationOne(callback); - } - else if (e2 != null) - { - var callback = e2.Current; - if (!e2.MoveNext()) - e2 = null; - invocationTwo(callback); - } - } - catch (Exception e) - { - Debug.LogException(e); - if (exitOnFailure) - return false; - } - } - - return true; - } - - [RequiredByNativeCode] - internal static void OnBuildPreProcess(BuildReport report) - { -#pragma warning disable 618 - InvokeCallbackInterfacesPair( - buildPreprocessors, bpp => bpp.OnPreprocessBuild(report.summary.platform, report.summary.outputPath), - buildPreprocessorsWithReport, bpp => bpp.OnPreprocessBuild(report), - (report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0); -#pragma warning restore 618 - } - - [RequiredByNativeCode] - internal static void OnSceneProcess(UnityEngine.SceneManagement.Scene scene, BuildReport report) - { -#pragma warning disable 618 - InvokeCallbackInterfacesPair( - sceneProcessors, spp => spp.OnProcessScene(scene), - sceneProcessorsWithReport, spp => spp.OnProcessScene(scene, report), - report && ((report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0)); -#pragma warning restore 618 - } - - [RequiredByNativeCode] - internal static void OnBuildPostProcess(BuildReport report) - { -#pragma warning disable 618 - InvokeCallbackInterfacesPair( - buildPostprocessors, bpp => bpp.OnPostprocessBuild(report.summary.platform, report.summary.outputPath), - buildPostprocessorsWithReport, bpp => bpp.OnPostprocessBuild(report), - (report.summary.options & BuildOptions.StrictMode) != 0 || (report.summary.assetBundleOptions & BuildAssetBundleOptions.StrictMode) != 0); -#pragma warning restore 618 - } - - [RequiredByNativeCode] - internal static void OnActiveBuildTargetChanged(BuildTarget previousPlatform, BuildTarget newPlatform) - { - if (buildTargetProcessors != null) - { - foreach (IActiveBuildTargetChanged abtc in buildTargetProcessors) - { - try - { - abtc.OnActiveBuildTargetChanged(previousPlatform, newPlatform); - } - catch (Exception e) - { - Debug.LogException(e); - } - } - } - } - - [RequiredByNativeCode] - internal static void CleanupBuildCallbacks() - { - buildTargetProcessors = null; - buildPreprocessors = null; - buildPostprocessors = null; - sceneProcessors = null; - buildPreprocessorsWithReport = null; - buildPostprocessorsWithReport = null; - sceneProcessorsWithReport = null; - previousFlags = BuildCallbacks.None; - } - } -} diff --git a/Editor/Mono/BuildPipeline/BuildPlatform.cs b/Editor/Mono/BuildPipeline/BuildPlatform.cs deleted file mode 100644 index 280fe24c07..0000000000 --- a/Editor/Mono/BuildPipeline/BuildPlatform.cs +++ /dev/null @@ -1,190 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor.Build -{ - // All settings for a build platform. - internal class BuildPlatform - { - // short name used for texture settings, etc. - public string name; - public GUIContent title; - public Texture2D smallIcon; - public BuildTargetGroup targetGroup; - public bool forceShowTarget; - public string tooltip; - - public BuildPlatform(string locTitle, string iconId, BuildTargetGroup targetGroup, bool forceShowTarget) - : this(locTitle, "", iconId, targetGroup, forceShowTarget) - { - } - - public BuildPlatform(string locTitle, string tooltip, string iconId, BuildTargetGroup targetGroup, bool forceShowTarget) - { - this.targetGroup = targetGroup; - name = targetGroup != BuildTargetGroup.Unknown ? BuildPipeline.GetBuildTargetGroupName(defaultTarget) : ""; - title = EditorGUIUtility.TextContentWithIcon(locTitle, iconId); - smallIcon = EditorGUIUtility.IconContent(iconId + ".Small").image as Texture2D; - this.tooltip = tooltip; - this.forceShowTarget = forceShowTarget; - } - - // ADD_NEW_PLATFORM_HERE - public BuildTarget defaultTarget - { - get - { - switch (targetGroup) - { - case BuildTargetGroup.Standalone: - return BuildTarget.StandaloneWindows; - case BuildTargetGroup.iOS: - return BuildTarget.iOS; - case BuildTargetGroup.tvOS: - return BuildTarget.tvOS; - case BuildTargetGroup.PSP2: - return BuildTarget.PSP2; - case BuildTargetGroup.PS4: - return BuildTarget.PS4; - case BuildTargetGroup.XboxOne: - return BuildTarget.XboxOne; - case BuildTargetGroup.Android: - return BuildTarget.Android; - case BuildTargetGroup.N3DS: - return BuildTarget.N3DS; - case BuildTargetGroup.Switch: - return BuildTarget.Switch; - case BuildTargetGroup.Tizen: - return BuildTarget.Tizen; - case BuildTargetGroup.WebGL: - return BuildTarget.WebGL; - case BuildTargetGroup.WSA: - return BuildTarget.WSAPlayer; - case BuildTargetGroup.Facebook: - return BuildTarget.StandaloneWindows64; - default: - return (BuildTarget)(-1); - } - } - } - }; - - internal class BuildPlatforms - { - private static readonly BuildPlatforms s_Instance = new BuildPlatforms(); - - public static BuildPlatforms instance - { - get - { - return s_Instance; - } - } - - internal BuildPlatforms() - { - // This is pretty brittle, notLicensedMessages and buildTargetNotInstalled below must match the order here - // and since NaCl isn't listed in the build settings like the other platforms you must not add anything after it, if it - // must also be added in the license/notinstalled arrays. - // ADD_NEW_PLATFORM_HERE - List buildPlatformsList = new List(); - buildPlatformsList.Add(new BuildPlatform("PC, Mac & Linux Standalone", "BuildSettings.Standalone", BuildTargetGroup.Standalone, true)); - buildPlatformsList.Add(new BuildPlatform("iOS", "BuildSettings.iPhone", BuildTargetGroup.iOS, true)); - // TVOS TODO change the icon when it's ready - buildPlatformsList.Add(new BuildPlatform("tvOS", "BuildSettings.tvOS", BuildTargetGroup.tvOS, true)); - buildPlatformsList.Add(new BuildPlatform("Android", "BuildSettings.Android", BuildTargetGroup.Android, true)); - buildPlatformsList.Add(new BuildPlatform("Tizen", "BuildSettings.Tizen", BuildTargetGroup.Tizen, false)); - buildPlatformsList.Add(new BuildPlatform("Xbox One", "BuildSettings.XboxOne", BuildTargetGroup.XboxOne, true)); - buildPlatformsList.Add(new BuildPlatform("PS Vita", "BuildSettings.PSP2", BuildTargetGroup.PSP2, true)); - buildPlatformsList.Add(new BuildPlatform("PS4", "BuildSettings.PS4", BuildTargetGroup.PS4, true)); - buildPlatformsList.Add(new BuildPlatform("Universal Windows Platform", "BuildSettings.Metro", BuildTargetGroup.WSA, true)); - buildPlatformsList.Add(new BuildPlatform("WebGL", "BuildSettings.WebGL", BuildTargetGroup.WebGL, true)); - buildPlatformsList.Add(new BuildPlatform("Nintendo 3DS", "BuildSettings.N3DS", BuildTargetGroup.N3DS, false)); - buildPlatformsList.Add(new BuildPlatform("Facebook", "BuildSettings.Facebook", BuildTargetGroup.Facebook, true)); - buildPlatformsList.Add(new BuildPlatform("Nintendo Switch", "BuildSettings.Switch", BuildTargetGroup.Switch, false)); - - foreach (var buildPlatform in buildPlatformsList) - { - buildPlatform.tooltip = BuildPipeline.GetBuildTargetGroupDisplayName(buildPlatform.targetGroup) + " settings"; - } - - buildPlatforms = buildPlatformsList.ToArray(); - } - - public BuildPlatform[] buildPlatforms; - - public string GetBuildTargetDisplayName(BuildTargetGroup group, BuildTarget target) - { - foreach (BuildPlatform cur in buildPlatforms) - { - if (cur.defaultTarget == target && cur.targetGroup == group) - return cur.title.text; - } - - switch (target) - { - case BuildTarget.StandaloneWindows: - case BuildTarget.StandaloneWindows64: - return "Windows"; - case BuildTarget.StandaloneOSX: - // Deprecated -#pragma warning disable 612, 618 - case BuildTarget.StandaloneOSXIntel: - case BuildTarget.StandaloneOSXIntel64: -#pragma warning restore 612, 618 - return "Mac OS X"; - case BuildTarget.StandaloneLinux: - case BuildTarget.StandaloneLinux64: - case BuildTarget.StandaloneLinuxUniversal: - return "Linux"; - } - - return "Unsupported Target"; - } - - public string GetModuleDisplayName(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget) - { - switch (buildTargetGroup) - { - case BuildTargetGroup.Facebook: - return BuildPipeline.GetBuildTargetGroupDisplayName(buildTargetGroup); - default: - return GetBuildTargetDisplayName(buildTargetGroup, buildTarget); - } - } - - public int BuildPlatformIndexFromTargetGroup(BuildTargetGroup group) - { - for (int i = 0; i < buildPlatforms.Length; i++) - if (group == buildPlatforms[i].targetGroup) - return i; - return -1; - } - - public BuildPlatform BuildPlatformFromTargetGroup(BuildTargetGroup group) - { - int index = BuildPlatformIndexFromTargetGroup(group); - return index != -1 ? buildPlatforms[index] : null; - } - - public List GetValidPlatforms(bool includeMetaPlatforms) - { - List platforms = new List(); - foreach (BuildPlatform bp in buildPlatforms) - if ((bp.targetGroup == BuildTargetGroup.Standalone || BuildPipeline.IsBuildTargetSupported(bp.targetGroup, bp.defaultTarget)) && (!(bp.targetGroup == BuildTargetGroup.Facebook) || includeMetaPlatforms)) - platforms.Add(bp); - - return platforms; - } - - public List GetValidPlatforms() - { - return GetValidPlatforms(false); - } - }; -} diff --git a/Editor/Mono/BuildPipeline/BuildUtils.cs b/Editor/Mono/BuildPipeline/BuildUtils.cs deleted file mode 100644 index caeb0dda8a..0000000000 --- a/Editor/Mono/BuildPipeline/BuildUtils.cs +++ /dev/null @@ -1,147 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using UnityEditor.Modules; -using UnityEditor.Scripting; -using UnityEditor.Scripting.Compilers; -using UnityEngine; -using UnityEditor; -using UnityEditor.Build.Reporting; -using UnityEditor.Utils; -using Debug = UnityEngine.Debug; -using PackageInfo = Unity.DataContract.PackageInfo; -using System.Xml.Linq; -using System.Xml.XPath; - -namespace UnityEditorInternal -{ - internal class NativeProgram : Program - { - public NativeProgram(string executable, string arguments) - { - var startInfo = new ProcessStartInfo - { - Arguments = arguments, - CreateNoWindow = true, - FileName = executable, - RedirectStandardError = true, - RedirectStandardOutput = true, - WorkingDirectory = Application.dataPath + "/..", - UseShellExecute = false - }; - - _process.StartInfo = startInfo; - } - } - - internal class Runner - { - internal static void RunManagedProgram(string exe, string args) - { - RunManagedProgram(exe, args, Application.dataPath + "/..", null, null); - } - - internal static void RunManagedProgram(string exe, string args, string workingDirectory, CompilerOutputParserBase parser, Action setupStartInfo) - { - Program p; - - // Run on .NET if running on windows - // It's twice as fast as Mono for IL2CPP.exe - if (Application.platform == RuntimePlatform.WindowsEditor) - { - var startInfo = new ProcessStartInfo() - { - Arguments = args, - CreateNoWindow = true, - FileName = exe - }; - - if (setupStartInfo != null) - setupStartInfo(startInfo); - - p = new Program(startInfo); - } - else - { - p = new ManagedProgram(MonoInstallationFinder.GetMonoInstallation("MonoBleedingEdge"), null, exe, args, false, setupStartInfo); - } - - RunProgram(p, exe, args, workingDirectory, parser); - } - - internal static void RunNetCoreProgram(string exe, string args, string workingDirectory, CompilerOutputParserBase parser, Action setupStartInfo) - { - var p = new NetCoreProgram(exe, args, setupStartInfo); - RunProgram(p, exe, args, workingDirectory, parser); - } - - // Used when debugging il2cpp.exe from Windows, please don't remove it - public static void RunNativeProgram(string exe, string args) - { - using (var p = new NativeProgram(exe, args)) - { - p.Start(); - p.WaitForExit(); - if (p.ExitCode != 0) - { - Debug.LogError("Failed running " + exe + " " + args + "\n\n" + p.GetAllOutput()); - - throw new Exception(string.Format("{0} did not run properly!", exe)); - } - } - } - - private static void RunProgram(Program p, string exe, string args, string workingDirectory, CompilerOutputParserBase parser) - { - var stopwatch = new Stopwatch(); - stopwatch.Start(); - - using (p) - { - p.GetProcessStartInfo().WorkingDirectory = workingDirectory; - p.Start(); - p.WaitForExit(); - - stopwatch.Stop(); - Console.WriteLine("{0} exited after {1} ms.", exe, stopwatch.ElapsedMilliseconds); - - IEnumerable messages = null; - if (parser != null) - { - var errorOutput = p.GetErrorOutput(); - var standardOutput = p.GetStandardOutput(); - messages = parser.Parse(errorOutput, standardOutput, true); - } - - if (p.ExitCode != 0) - { - if (messages != null) - { - foreach (var message in messages) - Debug.LogPlayerBuildError(message.message, message.file, message.line, message.column); - } - - Debug.LogError("Failed running " + exe + " " + args + "\n\n" + p.GetAllOutput()); - - throw new Exception(string.Format("{0} did not run properly!", exe)); - } - else - { - if (messages != null) - { - foreach (var message in messages) - Console.WriteLine(message.message + " - " + message.file + " - " + message.line + " - " + message.column); - } - } - } - } - } -} diff --git a/Editor/Mono/BuildPipeline/BuildVerifier.cs b/Editor/Mono/BuildPipeline/BuildVerifier.cs deleted file mode 100644 index ea74b4fbc5..0000000000 --- a/Editor/Mono/BuildPipeline/BuildVerifier.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Xml.XPath; -using System.Collections.Generic; -using System.IO; -using UnityEngine; -namespace UnityEditor -{ - /// - /// Class intented to verify if build will compile / work on specified target platform - /// Currently only managed references are verified - /// - internal class BuildVerifier - { - private Dictionary> m_UnsupportedAssemblies = null; - private static BuildVerifier ms_Inst = null; - - protected BuildVerifier() - { - m_UnsupportedAssemblies = new Dictionary>(); - - var configPath = Path.Combine(Path.Combine(EditorApplication.applicationContentsPath, "Resources"), "BuildVerification.xml"); - var doc = new XPathDocument(configPath); - var navigator = doc.CreateNavigator(); - navigator.MoveToFirstChild(); - - var it = navigator.SelectChildren("assembly", ""); - - while (it.MoveNext()) - { - string name = it.Current.GetAttribute("name", ""); - if (string.IsNullOrEmpty(name)) - throw new ApplicationException(string.Format("Failed to load {0}, name attribute is empty", configPath)); - - string platform = it.Current.GetAttribute("platform", ""); - if (string.IsNullOrEmpty(platform)) - platform = "*"; - - if (!m_UnsupportedAssemblies.ContainsKey(platform)) - m_UnsupportedAssemblies.Add(platform, new HashSet()); - - m_UnsupportedAssemblies[platform].Add(name); - } - } - - protected void VerifyBuildInternal(BuildTarget target, string managedDllFolder) - { - foreach (var file in Directory.GetFiles(managedDllFolder)) - { - if (file.EndsWith(".dll")) - { - var fname = Path.GetFileName(file); - if (!VerifyAssembly(target, fname)) - Debug.LogWarningFormat( - "{0} assembly is referenced by user code, but is not supported" + - " on {1} platform. Various failures might follow.", fname, target.ToString()); - } - } - } - - protected bool VerifyAssembly(BuildTarget target, string assembly) - { - if (m_UnsupportedAssemblies.ContainsKey("*") && m_UnsupportedAssemblies["*"].Contains(assembly) || - m_UnsupportedAssemblies.ContainsKey(target.ToString()) && m_UnsupportedAssemblies[target.ToString()].Contains(assembly)) - return false; - - return true; - } - - public static void VerifyBuild(BuildTarget target, string managedDllFolder) - { - if (ms_Inst == null) - ms_Inst = new BuildVerifier(); - - ms_Inst.VerifyBuildInternal(target, managedDllFolder); - } - } -} diff --git a/Editor/Mono/BuildPipeline/CodeStrippingUtils.cs b/Editor/Mono/BuildPipeline/CodeStrippingUtils.cs deleted file mode 100644 index 9df34d9a2a..0000000000 --- a/Editor/Mono/BuildPipeline/CodeStrippingUtils.cs +++ /dev/null @@ -1,713 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security; -using System.Xml; -using UnityEditorInternal; -using Mono.Cecil; -using UnityEditor.Build.Reporting; -using UnityEditor.Scripting.ScriptCompilation; -using UnityEngine.Networking; -using UnityEditor.Utils; - -namespace UnityEditor -{ - internal class CodeStrippingUtils - { - private static UnityType s_GameManagerTypeInfo = null; - static UnityType GameManagerTypeInfo - { - get - { - if (s_GameManagerTypeInfo == null) - s_GameManagerTypeInfo = FindTypeByNameChecked("GameManager", "initializing code stripping utils"); - return s_GameManagerTypeInfo; - } - } - - static string[] s_blackListNativeClassNames = new string[] - { - "Behaviour", // GetFixedBehaviourManager is directly used by fixed update in the player loop - "PreloadData", - // will otherwise be stripped if scene only uses default materials not explicitly referenced - // (ie some components will get a default material if a material reference is null) - "Material", - - // those are used to create builtin textures and availability is checked at runtime - "Cubemap", - "Texture3D", - "Texture2DArray", - "RenderTexture", - - "Mesh", // Used by IMGUI (even on empty projects, it draws development console & watermarks) - "MeshFilter", // Used in the VR Splash screen. - "MeshRenderer", // Used in the VR Splash screen. - "Sprite", // Used by Unity splash screen. - "LowerResBlitTexture", - - "Transform", // well, Transform is always used - "RectTransform", // Transform depends on RectTransform's TransformHierarchyChangeDispatch - }; - - static UnityType[] s_blackListNativeClasses; - - public static UnityType[] BlackListNativeClasses - { - get - { - if (s_blackListNativeClasses == null) - { - s_blackListNativeClasses = s_blackListNativeClassNames.Select( - typeName => FindTypeByNameChecked(typeName, "code stripping blacklist native class")).ToArray(); - } - - return s_blackListNativeClasses; - } - } - - static readonly Dictionary s_blackListNativeClassesDependencyNames = new Dictionary - { - {"ParticleSystemRenderer", "ParticleSystem"}, - {"ParticleSystem", "ParticleSystemRenderer"} - }; - - static Dictionary s_blackListNativeClassesDependency; - - public static Dictionary BlackListNativeClassesDependency - { - get - { - if (s_blackListNativeClassesDependency == null) - { - s_blackListNativeClassesDependency = new Dictionary(); - foreach (var kv in s_blackListNativeClassesDependencyNames) - BlackListNativeClassesDependency.Add( - FindTypeByNameChecked(kv.Key, "code stripping blacklist native class dependency key"), - FindTypeByNameChecked(kv.Value, "code stripping blacklist native class dependency value")); - } - - return s_blackListNativeClassesDependency; - } - } - - private static UnityType FindTypeByNameChecked(string name, string msg) - { - UnityType result = UnityType.FindTypeByName(name); - if (result == null) - throw new ArgumentException(string.Format("Could not map typename '{0}' to type info ({1})", name, msg ?? "no context")); - return result; - } - - public static HashSet GetModulesFromICalls(string icallsListFile) - { - var icalls = File.ReadAllLines(icallsListFile); - var result = new HashSet(); - foreach (var icall in icalls) - { - var module = ModuleMetadata.GetICallModule(icall); - if (!string.IsNullOrEmpty(module)) - result.Add(module); - } - return result; - } - - public static void InjectCustomDependencies(BuildTarget target, StrippingInfo strippingInfo, HashSet nativeClasses, - HashSet nativeModules) - { - // This function can be used to inject user-readable dependency information for specific classes which would not be obvious otherwise. - // Can also be used to set up dependencies to modules which cannot be derived by the build pipeline without custom rules - const string connectSettingsName = "UnityConnectSettings"; - var connectSettings = UnityType.FindTypeByName(connectSettingsName); - const string cloudWebServicesManagerName = "CloudWebServicesManager"; - var cloudWebServicesManager = UnityType.FindTypeByName(cloudWebServicesManagerName); - if (nativeClasses.Contains(connectSettings) || nativeClasses.Contains(cloudWebServicesManager)) - { - if (PlayerSettings.submitAnalytics) - { - const string requiredMessage = "Required by HW Statistics (See Player Settings)"; - strippingInfo.RegisterDependency(connectSettingsName, requiredMessage); - strippingInfo.RegisterDependency(cloudWebServicesManagerName, requiredMessage); - strippingInfo.SetIcon(requiredMessage, "class/PlayerSettings"); - } - } - - const string analyticsManagerName = "UnityAnalyticsManager"; - var analyticsManager = UnityType.FindTypeByName(analyticsManagerName); - if (nativeClasses.Contains(analyticsManager)) - { - if (UnityEditor.Analytics.AnalyticsSettings.enabled) - { - const string requiredMessage = "Required by Unity Analytics (See Services Window)"; - strippingInfo.RegisterDependency(analyticsManagerName, requiredMessage); - strippingInfo.SetIcon(requiredMessage, "class/PlayerSettings"); - } - } - - if (UnityEditorInternal.VR.VRModule.ShouldInjectVRDependenciesForBuildTarget(target)) - { - const string moduleName = "VR"; - const string requiredMessage = "Required because VR is enabled in PlayerSettings"; - nativeModules.Add(moduleName); - strippingInfo.RegisterDependency(StrippingInfo.ModuleName(moduleName), requiredMessage); - strippingInfo.SetIcon(requiredMessage, "class/PlayerSettings"); - } - - foreach (string module in ModuleMetadata.GetModuleNames()) - { - if (!ModuleMetadata.IsStrippableModule(module)) - { - string requiredMessage = module + " is always required"; - nativeModules.Add(module); - strippingInfo.AddModule(module); - strippingInfo.RegisterDependency(StrippingInfo.ModuleName(module), requiredMessage); - strippingInfo.SetIcon(requiredMessage, "class/DefaultAsset"); - } - } - } - - public static void GenerateDependencies(string strippedAssemblyDir, string icallsListFile, RuntimeClassRegistry rcr, bool doStripping, out HashSet nativeClasses, out HashSet nativeModules, IIl2CppPlatformProvider platformProvider) - { - var strippingInfo = platformProvider == null ? null : StrippingInfo.GetBuildReportData(platformProvider.buildReport); - var userAssemblies = GetUserAssemblies(strippedAssemblyDir); - // [1] Extract native classes from scene and scripts - nativeClasses = doStripping ? GenerateNativeClassList(rcr, strippedAssemblyDir, userAssemblies, strippingInfo) : null; - - // Exclude module managers (GlobalGameManager) if no dependent classes are used. - if (nativeClasses != null) - ExcludeModuleManagers(ref nativeClasses); - - // [2] Prepare a list of modules to register - nativeModules = GetNativeModulesToRegister(nativeClasses, strippingInfo); - - if (nativeClasses != null && icallsListFile != null) - { - // Get required modules from icall list file - var icallModules = GetModulesFromICalls(icallsListFile); - - // Add GameManager classes for modules - foreach (var module in icallModules) - { - if (!nativeModules.Contains(module)) - { - if (strippingInfo != null) - { - strippingInfo.RegisterDependency(StrippingInfo.ModuleName(module), StrippingInfo.RequiredByScripts); - } - } - - var moduleClasses = ModuleMetadata.GetModuleTypes(module); - foreach (var klass in moduleClasses) - { - if (klass.IsDerivedFrom(GameManagerTypeInfo)) - { - nativeClasses.Add(klass); - } - } - } - - nativeModules.UnionWith(icallModules); - } - - ApplyManualStrippingOverrides(nativeClasses, nativeModules, strippingInfo); - - bool didAdd = true; - if (platformProvider != null) - { - while (didAdd) - { - didAdd = false; - foreach (var module in nativeModules.ToList()) - { - var dependecies = ModuleMetadata.GetModuleDependencies(module); - if (dependecies != null) - { - foreach (var dependentModule in dependecies) - { - if (!nativeModules.Contains(dependentModule)) - { - nativeModules.Add(dependentModule); - didAdd = true; - } - if (strippingInfo != null) - { - var moduleName = StrippingInfo.ModuleName(module); - strippingInfo.RegisterDependency(StrippingInfo.ModuleName(dependentModule), "Required by " + moduleName); - strippingInfo.SetIcon("Required by " + moduleName, $"package/com.unity.modules.{module.ToLower()}"); - } - } - } - } - } - } - - AssemblyReferenceChecker checker = new AssemblyReferenceChecker(); - checker.CollectReferencesFromRoots(strippedAssemblyDir, userAssemblies, true, 0.0f, true); - - if (strippingInfo != null) - { - foreach (var module in nativeModules) - strippingInfo.AddModule(module); - strippingInfo.AddModule("Core"); - } - - if (nativeClasses != null && strippingInfo != null) - InjectCustomDependencies(platformProvider.target, strippingInfo, nativeClasses, nativeModules); - } - - public static void ApplyManualStrippingOverrides(HashSet nativeClasses, HashSet nativeModules, StrippingInfo strippingInfo) - { - // Apply manual stripping overrides - foreach (var module in ModuleMetadata.GetModuleNames()) - { - var includeSetting = ModuleMetadata.GetModuleIncludeSettingForModule(module); - if (includeSetting == ModuleIncludeSetting.ForceInclude) - { - nativeModules.Add(module); - var moduleClasses = ModuleMetadata.GetModuleTypes(module); - foreach (var klass in moduleClasses) - { - nativeClasses.Add(klass); - if (strippingInfo != null) - { - strippingInfo.RegisterDependency(klass.name, "Force included module"); - strippingInfo.RegisterDependency(StrippingInfo.ModuleName(module), klass.name); - } - } - - if (strippingInfo != null) - strippingInfo.RegisterDependency(StrippingInfo.ModuleName(module), "Force included module"); - } - else if (includeSetting == ModuleIncludeSetting.ForceExclude) - { - if (nativeModules.Contains(module)) - { - nativeModules.Remove(module); - var moduleClasses = ModuleMetadata.GetModuleTypes(module); - foreach (var klass in moduleClasses) - { - if (nativeClasses.Contains(klass)) - { - nativeClasses.Remove(klass); - } - } - - if (strippingInfo != null) - strippingInfo.modules.Remove(StrippingInfo.ModuleName(module)); - } - } - } - } - - public static string GetModuleWhitelist(string module, string moduleStrippingInformationFolder) - { - return Paths.Combine(moduleStrippingInformationFolder, module + ".xml"); - } - - public static void WriteModuleAndClassRegistrationFile(string strippedAssemblyDir, string icallsListFile, string outputDir, RuntimeClassRegistry rcr, IEnumerable classesToSkip, IIl2CppPlatformProvider platformProvider) - { - HashSet nativeClasses; - HashSet nativeModules; - // by default, we only care about il2cpp - bool doStripping = PlayerSettings.stripEngineCode; - GenerateDependencies(strippedAssemblyDir, icallsListFile, rcr, doStripping, out nativeClasses, out nativeModules, platformProvider); - - var outputClassRegistration = Path.Combine(outputDir, "UnityClassRegistration.cpp"); - WriteModuleAndClassRegistrationFile(outputClassRegistration, nativeModules, nativeClasses, new HashSet(classesToSkip)); - } - - public static HashSet GetNativeModulesToRegister(HashSet nativeClasses, StrippingInfo strippingInfo) - { - return (nativeClasses == null) ? GetAllStrippableModules() : GetRequiredStrippableModules(nativeClasses, strippingInfo); - } - - private static HashSet GetAllStrippableModules() - { - HashSet nativeModules = new HashSet(); - foreach (string module in ModuleMetadata.GetModuleNames()) - if (ModuleMetadata.IsStrippableModule(module)) // Only handle strippable modules. Others are listed in RegisterStaticallyLinkedModules() - nativeModules.Add(module); - return nativeModules; - } - - private static HashSet GetRequiredStrippableModules(HashSet nativeClasses, StrippingInfo strippingInfo) - { - HashSet nativeClassesUsedInModules = new HashSet(); - HashSet nativeModules = new HashSet(); - foreach (string module in ModuleMetadata.GetModuleNames()) - { - if (ModuleMetadata.IsStrippableModule(module)) // Only handle strippable modules. Others are listed in RegisterStaticallyLinkedModules() - { - var moduleClasses = new HashSet(ModuleMetadata.GetModuleTypes(module)); - if (nativeClasses.Overlaps(moduleClasses)) // Include module if at least one of its classes is present - { - nativeModules.Add(module); - if (strippingInfo != null) - { - foreach (var klass in moduleClasses) - { - if (nativeClasses.Contains(klass)) - { - strippingInfo.RegisterDependency(StrippingInfo.ModuleName(module), klass.name); - // Don't list GlobalGameManagers in a module will automatically be added if the module is added. - nativeClassesUsedInModules.Add(klass); - } - } - } - } - } - } - - // Classes which have not been registered as belonging to a module belong to the Core module. - if (strippingInfo != null) - { - foreach (var klass in nativeClasses) - { - if (!nativeClassesUsedInModules.Contains(klass)) - strippingInfo.RegisterDependency(StrippingInfo.ModuleName("Core"), klass.name); - } - } - return nativeModules; - } - - private static void ExcludeModuleManagers(ref HashSet nativeClasses) - { - string[] moduleNames = ModuleMetadata.GetModuleNames(); - - foreach (string module in moduleNames) - { - if (!ModuleMetadata.IsStrippableModule(module)) // Only handle strippable modules - continue; - - var moduleClasses = ModuleMetadata.GetModuleTypes(module); - - // Find (non-)manager classes - HashSet managerClasses = new HashSet(); - HashSet nonManagerClasses = new HashSet(); - foreach (var klass in moduleClasses) - { - if (klass.IsDerivedFrom(GameManagerTypeInfo)) - managerClasses.Add(klass); - else - nonManagerClasses.Add(klass); - } - - // At least one non-manager class is required for the removal attempt - if (nonManagerClasses.Count == 0) - continue; - - // Exclude manager classes if no non-manager classes are present - if (!nativeClasses.Overlaps(nonManagerClasses)) - { - foreach (var klass in managerClasses) - nativeClasses.Remove(klass); - } - else - { - foreach (var klass in managerClasses) - nativeClasses.Add(klass); - } - } - } - - private static HashSet GenerateNativeClassList(RuntimeClassRegistry rcr, string directory, string[] rootAssemblies, StrippingInfo strippingInfo) - { - HashSet nativeClasses = CollectNativeClassListFromRoots(directory, rootAssemblies, strippingInfo); - - // Inject blacklisted native types - foreach (var klass in BlackListNativeClasses) - nativeClasses.Add(klass); - - foreach (var dependent in BlackListNativeClassesDependency.Keys) - { - if (nativeClasses.Contains(dependent)) - { - var provider = BlackListNativeClassesDependency[dependent]; - nativeClasses.Add(provider); - } - } - - // List native classes found in scenes - foreach (string klassName in rcr.GetAllNativeClassesIncludingManagersAsString()) - { - UnityType klass = UnityType.FindTypeByName(klassName); - if (klass != null && klass.baseClass != null) - { - nativeClasses.Add(klass); - if (strippingInfo != null) - { - if (!klass.IsDerivedFrom(GameManagerTypeInfo)) - { - var scenes = rcr.GetScenesForClass(klass.persistentTypeID); - if (scenes != null) - { - foreach (var scene in scenes) - { - strippingInfo.RegisterDependency(klassName, scene); - if (scene.EndsWith(".unity")) - strippingInfo.SetIcon(scene, "class/SceneAsset"); - else - strippingInfo.SetIcon(scene, "class/AssetBundle"); - } - } - } - } - } - } - - // Always include base classes of derived native classes. - HashSet nativeClassesAndBaseClasses = new HashSet(); - foreach (var klass in nativeClasses) - { - var current = klass; - while (current.baseClass != null) - { - nativeClassesAndBaseClasses.Add(current); - current = current.baseClass; - } - } - - return nativeClassesAndBaseClasses; - } - - private static HashSet CollectNativeClassListFromRoots(string directory, string[] rootAssemblies, StrippingInfo strippingInfo) - { - // Collect managed types - HashSet managedTypeNames = CollectManagedTypeReferencesFromRoots(directory, rootAssemblies, strippingInfo); - - // Extract native types from managed types - var infos = managedTypeNames.Select(name => UnityType.FindTypeByName(name)).Where(klass => klass != null && klass.baseClass != null); - return new HashSet(infos); - } - - // Collects all types from managed assemblies. - // Follows assembly references from given root assemblies. - // Assemblies should be already stripped. - private static HashSet CollectManagedTypeReferencesFromRoots(string directory, string[] rootAssemblies, StrippingInfo strippingInfo) - { - HashSet foundTypes = new HashSet(); - - AssemblyReferenceChecker checker = new AssemblyReferenceChecker(); - bool collectMethods = false; - bool ignoreSystemDlls = false; - checker.CollectReferencesFromRoots(directory, rootAssemblies, collectMethods, 0.0f, ignoreSystemDlls); - { - string[] fileNames = checker.GetAssemblyFileNames(); - AssemblyDefinition[] assemblies = checker.GetAssemblyDefinitions(); - - foreach (AssemblyDefinition definition in assemblies) - { - foreach (TypeDefinition typeDefinition in definition.MainModule.Types) - { - if (typeDefinition.Namespace.StartsWith("UnityEngine")) - { - // Skip blank types - if (typeDefinition.Fields.Count > 0 || typeDefinition.Methods.Count > 0 || typeDefinition.Properties.Count > 0) - { - string className = typeDefinition.Name; - foundTypes.Add(className); - if (strippingInfo != null) - { - if (!AssemblyReferenceChecker.IsIgnoredSystemDll(definition)) - strippingInfo.RegisterDependency(className, StrippingInfo.RequiredByScripts); - } - } - } - } - } - - AssemblyDefinition unityEngineAssemblyDefinition = null; - AssemblyDefinition unityEngineUIAssemblyDefinition = null; - for (int i = 0; i < fileNames.Length; i++) - { - if (fileNames[i] == "UnityEngine.dll") - unityEngineAssemblyDefinition = assemblies[i]; - - // UnityEngine.UI references UnityEngine.Collider, which causes the inclusion of Physics and Physics2D modules if - // UnityEngine.UI is referenced. UnityEngine.UI code is designed to only actually access Colliders if these modules - // are used, so don't include references from UnityEngine.UI here. - if (fileNames[i] == "UnityEngine.UI.dll") - unityEngineUIAssemblyDefinition = assemblies[i]; - } - - foreach (AssemblyDefinition definition in assemblies) - { - if (definition != unityEngineAssemblyDefinition && definition != unityEngineUIAssemblyDefinition) - { - foreach (TypeReference typeReference in definition.MainModule.GetTypeReferences()) - { - if (typeReference.Namespace.StartsWith("UnityEngine")) - { - string className = typeReference.Name; - foundTypes.Add(className); - if (strippingInfo != null) - { - if (!AssemblyReferenceChecker.IsIgnoredSystemDll(definition)) - strippingInfo.RegisterDependency(className, StrippingInfo.RequiredByScripts); - } - } - } - } - } - } - - return foundTypes; - } - - private static void WriteStaticallyLinkedModuleRegistration(TextWriter w, HashSet nativeModules, HashSet nativeClasses) - { - w.WriteLine("void InvokeRegisterStaticallyLinkedModuleClasses()"); - w.WriteLine("{"); - if (nativeClasses == null) - { - w.WriteLine("\tvoid RegisterStaticallyLinkedModuleClasses();"); - w.WriteLine("\tRegisterStaticallyLinkedModuleClasses();"); - } - else - { - w.WriteLine("\t// Do nothing (we're in stripping mode)"); - } - w.WriteLine("}"); - w.WriteLine(); - w.WriteLine("void RegisterStaticallyLinkedModulesGranular()"); - w.WriteLine("{"); - foreach (string module in nativeModules) - { - w.WriteLine("\tvoid RegisterModule_" + module + "();"); - w.WriteLine("\tRegisterModule_" + module + "();"); - w.WriteLine(); - } - w.WriteLine("}"); - } - - private static void WriteModuleAndClassRegistrationFile(string file, HashSet nativeModules, HashSet nativeClasses, HashSet classesToSkip) - { - using (TextWriter w = new StreamWriter(file)) - { - w.WriteLine("template void RegisterClass(const char*);"); - w.WriteLine("template void RegisterStrippedType(int, const char*, const char*);"); - - w.WriteLine(); - WriteStaticallyLinkedModuleRegistration(w, nativeModules, nativeClasses); - w.WriteLine(); - - // Forward declare types - if (nativeClasses != null) - { - foreach (var type in UnityType.GetTypes()) - { - if (type.baseClass == null || type.isEditorOnly || classesToSkip.Contains(type)) - continue; - - if (type.hasNativeNamespace) - w.Write("namespace {0} {{ class {1}; }} ", type.nativeNamespace, type.name); - else - w.Write("class {0}; ", type.name); - - if (nativeClasses.Contains(type)) - w.WriteLine("template <> void RegisterClass<{0}>(const char*);", type.qualifiedName); - else - w.WriteLine(); - } - w.WriteLine(); - } - - // Class registration function - w.WriteLine("void RegisterAllClasses()"); - w.WriteLine("{"); - - if (nativeClasses == null) - { - w.WriteLine("\tvoid RegisterAllClassesGranular();"); - w.WriteLine("\tRegisterAllClassesGranular();"); - } - else - { - w.WriteLine("void RegisterBuiltinTypes();"); - w.WriteLine("RegisterBuiltinTypes();"); - w.WriteLine("\t//Total: {0} non stripped classes", nativeClasses.Count); - - int index = 0; - foreach (var klass in nativeClasses) - { - w.WriteLine("\t//{0}. {1}", index, klass.qualifiedName); - if (classesToSkip.Contains(klass)) - w.WriteLine("\t//Skipping {0}", klass.qualifiedName); - else - w.WriteLine("\tRegisterClass<{0}>(\"{1}\");", klass.qualifiedName, klass.module); - ++index; - } - w.WriteLine(); - - // Register stripped classes - - // TODO (ulfj ) 2016-08-15 : Right now we cannot deal with types that are compiled into the editor - // but not the player due to other defines than UNITY_EDITOR in them module definition file - // (for example WorldAnchor only being there if ENABLE_HOLOLENS_MODULE_API). Doing this would - // require either some non trivial changes to the module registration macros or a way for these - // conditionals to be included in the RTTI so we can emit them when generating the code, so we - // disabling the registration of stripped classes for now and will get back to this when we have - // landed the remaining changes to the type system. - - //w.WriteLine("\t//Stripped classes"); - //foreach (var type in UnityType.GetTypes()) - //{ - // if (type.baseClass == null || type.isEditorOnly || classesToSkip.Contains(type) || nativeClasses.Contains(type)) - // continue; - - // w.WriteLine("\tRegisterStrippedType<{0}>({1}, \"{2}\", \"{3}\");", type.qualifiedName, type.persistentTypeID, type.name, type.nativeNamespace); - //} - } - w.WriteLine("}"); - w.Close(); - } - } - - private static readonly string[] s_TreatedAsUserAssemblies = - { - // Treat analytics as we user assembly. If it is not used, it won't be in the directory, - // so this should not add to the build size unless it is really used. - "UnityEngine.Analytics.dll", - }; - - public static string[] UserAssemblies - { - get - { - EditorCompilation.TargetAssemblyInfo[] allTargetAssemblies = EditorCompilationInterface.GetTargetAssemblies(); - - string[] targetAssemblyNames = new string[allTargetAssemblies.Length + s_TreatedAsUserAssemblies.Length]; - - for (int i = 0; i < allTargetAssemblies.Length; ++i) - { - targetAssemblyNames[i] = allTargetAssemblies[i].Name; - } - for (int i = 0; i < s_TreatedAsUserAssemblies.Length; ++i) - { - targetAssemblyNames[allTargetAssemblies.Length + i] = s_TreatedAsUserAssemblies[i]; - } - return targetAssemblyNames; - } - } - - private static string[] GetUserAssemblies(string strippedAssemblyDir) - { - var arguments = new List(); - - foreach (var assembly in UserAssemblies) - { - var files = Directory.GetFiles(strippedAssemblyDir, assembly, SearchOption.TopDirectoryOnly); - arguments.AddRange(files.Select(f => Path.GetFileName(f))); - } - - return arguments.ToArray(); - } - } //CodeStrippingUtils -} //UnityEditor diff --git a/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs b/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs deleted file mode 100644 index 64e5db3c20..0000000000 --- a/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs +++ /dev/null @@ -1,212 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEditor.Modules; -using UnityEngine; - -internal abstract class DesktopStandaloneBuildWindowExtension : DefaultBuildWindowExtension -{ - private GUIContent m_StandaloneTarget = EditorGUIUtility.TrTextContent("Target Platform", "Destination platform for standalone build"); - private GUIContent m_Architecture = EditorGUIUtility.TrTextContent("Architecture", "Build m_Architecture for standalone"); - - private BuildTarget[] m_StandaloneSubtargets; - private GUIContent[] m_StandaloneSubtargetStrings; - - private bool m_HasIl2CppPlayers; - private bool m_IsRunningOnHostPlatform; - - public DesktopStandaloneBuildWindowExtension(bool hasIl2CppPlayers) - { - SetupStandaloneSubtargets(); - - m_IsRunningOnHostPlatform = Application.platform == GetHostPlatform(); - m_HasIl2CppPlayers = hasIl2CppPlayers; - } - - private void SetupStandaloneSubtargets() - { - List standaloneSubtargetsList = new List(); - List standaloneSubtargetStringsList = new List(); - - if (ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget.StandaloneWindows))) - { - standaloneSubtargetsList.Add(BuildTarget.StandaloneWindows); - standaloneSubtargetStringsList.Add(EditorGUIUtility.TrTextContent("Windows")); - } - if (ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget.StandaloneOSX))) - { - standaloneSubtargetsList.Add(BuildTarget.StandaloneOSX); - standaloneSubtargetStringsList.Add(EditorGUIUtility.TrTextContent("Mac OS X")); - } - if (ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget.StandaloneLinux))) - { - standaloneSubtargetsList.Add(BuildTarget.StandaloneLinux); - standaloneSubtargetStringsList.Add(EditorGUIUtility.TrTextContent("Linux")); - } - - m_StandaloneSubtargets = standaloneSubtargetsList.ToArray(); - m_StandaloneSubtargetStrings = standaloneSubtargetStringsList.ToArray(); - } - - internal static BuildTarget GetBestStandaloneTarget(BuildTarget selectedTarget) - { - if (ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(selectedTarget))) - return selectedTarget; - if (RuntimePlatform.WindowsEditor == Application.platform && ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget.StandaloneWindows))) - return BuildTarget.StandaloneWindows; - if (RuntimePlatform.OSXEditor == Application.platform && ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget.StandaloneOSX))) - return BuildTarget.StandaloneOSX; - if (ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget.StandaloneOSX))) - return BuildTarget.StandaloneOSX; - if (ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget.StandaloneLinux))) - return BuildTarget.StandaloneLinux; - return BuildTarget.StandaloneWindows; - } - - private static Dictionary GetArchitecturesForPlatform(BuildTarget target) - { - switch (target) - { - case BuildTarget.StandaloneWindows: - case BuildTarget.StandaloneWindows64: - return new Dictionary() { - { EditorGUIUtility.TrTextContent("x86"), BuildTarget.StandaloneWindows }, - { EditorGUIUtility.TrTextContent("x86_64"), BuildTarget.StandaloneWindows64 }, - }; - case BuildTarget.StandaloneLinux: - case BuildTarget.StandaloneLinux64: - case BuildTarget.StandaloneLinuxUniversal: - return new Dictionary() { - { EditorGUIUtility.TrTextContent("x86"), BuildTarget.StandaloneLinux }, - { EditorGUIUtility.TrTextContent("x86_64"), BuildTarget.StandaloneLinux64 }, - { EditorGUIUtility.TrTextContent("x86 + x86_64 (Universal)"), BuildTarget.StandaloneLinuxUniversal }, - }; - default: - return null; - } - } - - private static BuildTarget DefaultTargetForPlatform(BuildTarget target) - { - switch (target) - { - case BuildTarget.StandaloneWindows: - case BuildTarget.StandaloneWindows64: - return BuildTarget.StandaloneWindows; - case BuildTarget.StandaloneLinux: - case BuildTarget.StandaloneLinux64: - case BuildTarget.StandaloneLinuxUniversal: - return BuildTarget.StandaloneLinux; - case BuildTarget.StandaloneOSX: - // Deprecated -#pragma warning disable 612, 618 - case BuildTarget.StandaloneOSXIntel: - case BuildTarget.StandaloneOSXIntel64: -#pragma warning restore 612, 618 - return BuildTarget.StandaloneOSX; - default: - return target; - } - } - - public override void ShowPlatformBuildOptions() - { - BuildTarget selectedTarget = GetBestStandaloneTarget(EditorUserBuildSettings.selectedStandaloneTarget); - BuildTarget newTarget = EditorUserBuildSettings.selectedStandaloneTarget; - - int selectedIndex = Math.Max(0, Array.IndexOf(m_StandaloneSubtargets, DefaultTargetForPlatform(selectedTarget))); - int newIndex = EditorGUILayout.Popup(m_StandaloneTarget, selectedIndex, m_StandaloneSubtargetStrings); - - if (newIndex == selectedIndex) - { - Dictionary architectures = GetArchitecturesForPlatform(selectedTarget); - if (null != architectures) - { - // Display architectures for the current target platform - GUIContent[] architectureNames = new List(architectures.Keys).ToArray(); - int selectedArchitecture = 0; - - if (newIndex == selectedIndex) - { - // Grab m_Architecture index for currently selected target - foreach (var architecture in architectures) - { - if (architecture.Value == selectedTarget) - { - selectedArchitecture = System.Math.Max(0, System.Array.IndexOf(architectureNames, architecture.Key)); - break; - } - } - } - selectedArchitecture = EditorGUILayout.Popup(m_Architecture, selectedArchitecture, architectureNames); - newTarget = architectures[architectureNames[selectedArchitecture]]; - } - } - else - { - newTarget = m_StandaloneSubtargets[newIndex]; - } - - if (newTarget != EditorUserBuildSettings.selectedStandaloneTarget) - { - // setting selectedStandaloneTarget has side-effect: stops playmode - EditorUserBuildSettings.selectedStandaloneTarget = newTarget; - GUIUtility.ExitGUI(); - } - - ShowIl2CppErrorIfNeeded(); - ShowIl2CppDebuggerWarningIfNeeded(); - } - - private void ShowIl2CppErrorIfNeeded() - { - if (PlayerSettings.GetScriptingBackend(BuildTargetGroup.Standalone) != ScriptingImplementation.IL2CPP) - return; - - var error = GetCannotBuildIl2CppPlayerInCurrentSetupError(); - if (string.IsNullOrEmpty(error)) - return; - - EditorGUILayout.HelpBox(error, MessageType.Error); - } - - void ShowIl2CppDebuggerWarningIfNeeded() - { - if (PlayerSettings.GetScriptingBackend(BuildTargetGroup.Standalone) != ScriptingImplementation.IL2CPP) - return; - - if (EditorUserBuildSettings.allowDebugging && EditorApplication.scriptingRuntimeVersion != ScriptingRuntimeVersion.Latest) - EditorGUILayout.HelpBox("Script debugging is only supported with IL2CPP on the .NET 4.x scripting runtime.", MessageType.Warning); - } - - public override bool EnabledBuildButton() - { - if (PlayerSettings.GetScriptingBackend(BuildTargetGroup.Standalone) == ScriptingImplementation.Mono2x) - return true; - - return string.IsNullOrEmpty(GetCannotBuildIl2CppPlayerInCurrentSetupError()); - } - - protected virtual string GetCannotBuildIl2CppPlayerInCurrentSetupError() - { - if (!m_IsRunningOnHostPlatform) - return string.Format("{0} IL2CPP player can only be built on {0}.", GetHostPlatformName()); - - if (!m_HasIl2CppPlayers) - return "Currently selected scripting backend (IL2CPP) is not installed."; // Note: error should match UWP player error message for consistency. - - return null; - } - - protected abstract RuntimePlatform GetHostPlatform(); - protected abstract string GetHostPlatformName(); - - public override bool EnabledBuildAndRunButton() - { - return true; - } -} diff --git a/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs b/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs deleted file mode 100644 index d6094f56d6..0000000000 --- a/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs +++ /dev/null @@ -1,465 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor; -using UnityEditor.Build.Reporting; -using UnityEditor.Modules; -using UnityEditor.Utils; -using UnityEditorInternal; -using UnityEngine; - -internal abstract class DesktopStandalonePostProcessor : DefaultBuildPostprocessor -{ - protected DesktopStandalonePostProcessor() - { - } - - public override void PostProcess(BuildPostProcessArgs args) - { - SetupStagingArea(args); - CopyStagingAreaIntoDestination(args); - ProcessSymbolFiles(args); - } - - public override bool SupportsLz4Compression() - { - return true; - } - - public override void UpdateBootConfig(BuildTarget target, BootConfigData config, BuildOptions options) - { - base.UpdateBootConfig(target, config, options); - - if (PlayerSettings.forceSingleInstance) - config.AddKey("single-instance"); - if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) - config.Set("scripting-runtime-version", "latest"); - if (IL2CPPUtils.UseIl2CppCodegenWithMonoBackend(BuildPipeline.GetBuildTargetGroup(target))) - config.Set("mono-codegen", "il2cpp"); - } - - private void CopyNativePlugins(BuildPostProcessArgs args, out List cppPlugins) - { - string buildTargetName = BuildPipeline.GetBuildTargetName(args.target); - IPluginImporterExtension pluginImpExtension = new DesktopPluginImporterExtension(); - - string pluginsFolder = GetStagingAreaPluginsFolder(args); - string subDir32Bit = Path.Combine(pluginsFolder, "x86"); - string subDir64Bit = Path.Combine(pluginsFolder, "x86_64"); - - bool haveCreatedPluginsFolder = false; - bool haveCreatedSubDir32Bit = false; - bool haveCreatedSubDir64Bit = false; - cppPlugins = new List(); - - foreach (PluginImporter imp in PluginImporter.GetImporters(args.target)) - { - BuildTarget t = args.target; - - // Skip .cpp files. They get copied to il2cpp output folder just before code compilation - if (DesktopPluginImporterExtension.IsCppPluginFile(imp.assetPath)) - { - cppPlugins.Add(imp.assetPath); - continue; - } - - // Skip managed DLLs. - if (!imp.isNativePlugin) - continue; - - // HACK: This should never happen. - if (string.IsNullOrEmpty(imp.assetPath)) - { - UnityEngine.Debug.LogWarning("Got empty plugin importer path for " + args.target.ToString()); - continue; - } - - if (!haveCreatedPluginsFolder) - { - Directory.CreateDirectory(pluginsFolder); - haveCreatedPluginsFolder = true; - } - - bool isDirectory = Directory.Exists(imp.assetPath); - string cpu = imp.GetPlatformData(t, "CPU"); - switch (cpu) - { - case "x86": - if (t == BuildTarget.StandaloneWindows64 || - t == BuildTarget.StandaloneLinux64) - { - continue; - } - if (!haveCreatedSubDir32Bit) - { - Directory.CreateDirectory(subDir32Bit); - haveCreatedSubDir32Bit = true; - } - break; - case "x86_64": - if (t != BuildTarget.StandaloneOSX && - t != BuildTarget.StandaloneWindows64 && - t != BuildTarget.StandaloneLinux64 && - t != BuildTarget.StandaloneLinuxUniversal) - { - continue; - } - if (!haveCreatedSubDir64Bit) - { - Directory.CreateDirectory(subDir64Bit); - haveCreatedSubDir64Bit = true; - } - break; - // This is a special case for CPU targets, means no valid CPU is selected - case "None": - continue; - } - - string destinationPath = pluginImpExtension.CalculateFinalPluginPath(buildTargetName, imp); - if (string.IsNullOrEmpty(destinationPath)) - continue; - - string finalDestinationPath = Path.Combine(pluginsFolder, destinationPath); - - if (isDirectory) - { - FileUtil.CopyDirectoryRecursive(imp.assetPath, finalDestinationPath); - } - else - { - FileUtil.UnityFileCopy(imp.assetPath, finalDestinationPath); - } - } - - // TODO: Move all plugins using GetExtensionPlugins to GetImporters and remove GetExtensionPlugins - foreach (UnityEditorInternal.PluginDesc pluginDesc in PluginImporter.GetExtensionPlugins(args.target)) - { - if (!haveCreatedPluginsFolder) - { - Directory.CreateDirectory(pluginsFolder); - haveCreatedPluginsFolder = true; - } - - string pluginCopyPath = Path.Combine(pluginsFolder, Path.GetFileName(pluginDesc.pluginPath)); - - // Plugins copied through GetImporters take priority, don't overwrite - if (Directory.Exists(pluginCopyPath) || File.Exists(pluginCopyPath)) - continue; - - if (Directory.Exists(pluginDesc.pluginPath)) - { - FileUtil.CopyDirectoryRecursive(pluginDesc.pluginPath, pluginCopyPath); - } - else - { - FileUtil.CopyFileIfExists(pluginDesc.pluginPath, pluginCopyPath, false); - } - } - } - - private void CopyCppPlugins(string cppOutputDir, IEnumerable cppPlugins) - { - foreach (var plugin in cppPlugins) - { - FileUtil.CopyFileOrDirectory(plugin, Path.Combine(cppOutputDir, Path.GetFileName(plugin))); - } - } - - private void SetupStagingArea(BuildPostProcessArgs args) - { - if (UseIl2Cpp && GetCreateSolution()) - { - throw new Exception("CreateSolution is not supported with IL2CPP build"); - } - - Directory.CreateDirectory(args.stagingAreaData); - - List cppPlugins; - CopyNativePlugins(args, out cppPlugins); - - if (args.target == BuildTarget.StandaloneWindows || - args.target == BuildTarget.StandaloneWindows64) - { - CreateApplicationData(args); - } - - PostprocessBuildPlayer.InstallStreamingAssets(args.stagingAreaData, args.report); - - if (UseIl2Cpp) - { - CopyVariationFolderIntoStagingArea(args); - IL2CPPUtils.RunIl2Cpp(args.stagingAreaData, GetPlatformProvider(args), (cppOutputDir) => CopyCppPlugins(cppOutputDir, cppPlugins), args.usedClassRegistry); - - // Move GameAssembly next to game executable - var il2cppOutputNativeDirectory = Path.Combine(args.stagingAreaData, "Native"); - var gameAssemblyDirectory = GetDirectoryForGameAssembly(args); - foreach (var file in Directory.GetFiles(il2cppOutputNativeDirectory)) - { - var fileName = Path.GetFileName(file); - if (fileName.StartsWith(".")) - continue; // Skip files starting with ., as they weren't output by our tools and potentially belong to the OS (like .DS_Store on macOS) - - FileUtil.MoveFileOrDirectory(file, Path.Combine(gameAssemblyDirectory, fileName)); - } - - if (PlaceIL2CPPSymbolMapNextToExecutable()) - { - // Move symbol map to be next to game executable - FileUtil.MoveFileOrDirectory(Paths.Combine(il2cppOutputNativeDirectory, "Data", "SymbolMap"), Path.Combine(args.stagingArea, "SymbolMap")); - } - - // Move il2cpp data directory one directory up - FileUtil.MoveFileOrDirectory(Path.Combine(il2cppOutputNativeDirectory, "Data"), Path.Combine(args.stagingAreaData, "il2cpp_data")); - - // Native directory is supposed to be empty at this point - FileUtil.DeleteFileOrDirectory(il2cppOutputNativeDirectory); - - var dataBackupFolder = Path.Combine(args.stagingArea, GetIl2CppDataBackupFolderName(args)); - FileUtil.CreateOrCleanDirectory(dataBackupFolder); - - // Move generated C++ code out of Data directory - FileUtil.MoveFileOrDirectory(Path.Combine(args.stagingAreaData, "il2cppOutput"), Path.Combine(dataBackupFolder, "il2cppOutput")); - - if (IL2CPPUtils.UseIl2CppCodegenWithMonoBackend(BuildPipeline.GetBuildTargetGroup(args.target))) - { - // Are we using IL2CPP code generation with the Mono runtime? If so, strip the assemblies so we can use them for metadata. - StripAssembliesToLeaveOnlyMetadata(args.target, args.stagingAreaDataManaged); - } - else - { - // Otherwise, move them to temp data directory as il2cpp does not need managed assemblies to run - FileUtil.MoveFileOrDirectory(args.stagingAreaDataManaged, Path.Combine(dataBackupFolder, "Managed")); - } - - ProcessPlatformSpecificIL2CPPOutput(args); - } - - if (GetInstallingIntoBuildsFolder(args)) - { - CopyDataForBuildsFolder(args); - } - else - { - if (!UseIl2Cpp) - { - CopyVariationFolderIntoStagingArea(args); - } - - if (GetCreateSolution()) - { - CopyPlayerSolutionIntoStagingArea(args); - } - RenameFilesInStagingArea(args); - } - } - - static void StripAssembliesToLeaveOnlyMetadata(BuildTarget target, string stagingAreaDataManaged) - { - AssemblyReferenceChecker checker = new AssemblyReferenceChecker(); - checker.CollectReferences(stagingAreaDataManaged, true, 0.0f, false); - - EditorUtility.DisplayProgressBar("Removing bytecode from assemblies", "Stripping assemblies so that only metadata remains", 0.95F); - MonoAssemblyStripping.MonoCilStrip(target, stagingAreaDataManaged, checker.GetAssemblyFileNames()); - } - - // Creates app.info which is used by Standalone player (when run in Low Integrity mode) when creating log file path at program start. - // Log file path is created very early in the program execution, when none of the Unity managers are even created, that's why we can't get it from PlayerSettings - // Note: In low integrity mode, we can only write to %USER PROFILE%\AppData\LocalLow on Windows - protected void CreateApplicationData(BuildPostProcessArgs args) - { - File.WriteAllText(Path.Combine(args.stagingAreaData, "app.info"), - string.Join("\n", new[] - { - args.companyName, - args.productName - })); - args.report.RecordFileAdded(Path.Combine(args.stagingAreaData, "app.info"), CommonRoles.appInfo); - } - - protected bool CopyPlayerFilter(string path, BuildPostProcessArgs args) - { - // Don't copy UnityEngine mdb files - return Path.GetExtension(path) != ".mdb" || !Path.GetFileName(path).StartsWith("UnityEngine."); - } - - protected virtual void CopyPlayerSolutionIntoStagingArea(BuildPostProcessArgs args) - { - throw new Exception("CreateSolution is not supported on " + BuildPipeline.GetBuildTargetName(args.target)); - } - - protected virtual void CopyVariationFolderIntoStagingArea(BuildPostProcessArgs args) - { - var playerFolder = args.playerPackage + "/Variations/" + GetVariationName(args); - FileUtil.CopyDirectoryFiltered(playerFolder, args.stagingArea, true, f => CopyPlayerFilter(f, args), recursive: true); - - RecordCommonFiles(args, playerFolder, args.stagingAreaData); - } - - protected static void RecordCommonFiles(BuildPostProcessArgs args, string variationSourceFolder, string monoFolderRoot) - { - // Mark all the managed DLLs in Data/Managed as engine API assemblies - // Data/Managed may already contain managed DLLs in the UnityEngine.*.dll naming scheme from the extensions - // So we find the files in the source Variations directory and mark the corresponding files in the output - foreach (var file in Directory.GetFiles(Path.Combine(variationSourceFolder, "Data/Managed"), "*.dll")) - { - var filename = Path.GetFileName(file); - if (!filename.StartsWith("UnityEngine")) - continue; - - var targetFilePath = Path.Combine(args.stagingArea, "Data/Managed/" + filename); - args.report.RecordFileAdded(targetFilePath, CommonRoles.managedEngineApi); - } - - // Mark the default resources file - args.report.RecordFileAdded(Path.Combine(args.stagingArea, "Data/Resources/unity default resources"), - CommonRoles.builtInResources); - - // Mark up each mono runtime - foreach (var monoName in new[] {"Mono", "MonoBleedingEdge"}) - { - args.report.RecordFilesAddedRecursive(Path.Combine(monoFolderRoot, monoName + "/EmbedRuntime"), - CommonRoles.monoRuntime); - args.report.RecordFilesAddedRecursive(Path.Combine(monoFolderRoot, monoName + "/etc"), - CommonRoles.monoConfig); - } - } - - private void CopyStagingAreaIntoDestination(BuildPostProcessArgs args) - { - if (GetInstallingIntoBuildsFolder(args)) - { - string dst = Unsupported.GetBaseUnityDeveloperFolder() + "/" + GetDestinationFolderForInstallingIntoBuildsFolder(args); - - if (!Directory.Exists(Path.GetDirectoryName(dst))) - { - throw new Exception("Installing in builds folder failed because the player has not been built (You most likely want to enable 'Development build')."); - } - - FileUtil.CopyDirectoryFiltered(args.stagingAreaData, dst, true, f => true, recursive: true); - } - else - { - if (GetCreateSolution()) - { - // TODO: smart overwrite - } - else - { - DeleteDestination(args); - } - - // Copy entire stagingarea over - FileUtil.CopyDirectoryFiltered(args.stagingArea, GetDestinationFolder(args), true, f => true, recursive: true); - args.report.RecordFilesMoved(args.stagingArea, GetDestinationFolder(args)); - } - } - - protected abstract string GetStagingAreaPluginsFolder(BuildPostProcessArgs args); - - protected abstract void DeleteDestination(BuildPostProcessArgs args); - - protected static string GetMonoFolderName(ScriptingRuntimeVersion scriptingRuntimeVersion) - { - switch (scriptingRuntimeVersion) - { - case ScriptingRuntimeVersion.Legacy: - return "Mono"; - case ScriptingRuntimeVersion.Latest: - return "MonoBleedingEdge"; - default: - throw new ArgumentOutOfRangeException("scriptingRuntimeVersion", "Unknown scripting runtime version"); - } - } - - protected void DeleteUnusedMono(string dataFolder, BuildReport report) - { - // Mono is built by the il2cpp builder, so we dont need the libs copied - bool deleteBoth = IL2CPPUtils.UseIl2CppCodegenWithMonoBackend(BuildTargetGroup.Standalone); - - if (deleteBoth || EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) - { - var monoPath = Path.Combine(dataFolder, GetMonoFolderName(ScriptingRuntimeVersion.Legacy)); - FileUtil.DeleteFileOrDirectory(monoPath); - report.RecordFilesDeletedRecursive(monoPath); - } - if (deleteBoth || EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - { - var monoPath = Path.Combine(dataFolder, GetMonoFolderName(ScriptingRuntimeVersion.Latest)); - FileUtil.DeleteFileOrDirectory(monoPath); - report.RecordFilesDeletedRecursive(monoPath); - } - } - - protected abstract string GetDestinationFolderForInstallingIntoBuildsFolder(BuildPostProcessArgs args); - - protected abstract void CopyDataForBuildsFolder(BuildPostProcessArgs args); - - protected bool GetInstallingIntoBuildsFolder(BuildPostProcessArgs args) - { - return (args.options & BuildOptions.InstallInBuildFolder) != 0; - } - - protected bool UseIl2Cpp - { - get - { - return PlayerSettings.GetScriptingBackend(BuildTargetGroup.Standalone) == ScriptingImplementation.IL2CPP; - } - } - - protected virtual bool GetCreateSolution() { return false; } - - protected virtual string GetDestinationFolder(BuildPostProcessArgs args) - { - return FileUtil.UnityGetDirectoryName(args.installPath); - } - - protected bool GetDevelopment(BuildPostProcessArgs args) - { - return ((args.options & BuildOptions.Development) != 0); - } - - protected virtual string GetVariationName(BuildPostProcessArgs args) - { - return string.Format("{0}_{1}", - PlatformStringFor(args.target), - (GetDevelopment(args) ? "development" : "nondevelopment")); - } - - protected abstract string PlatformStringFor(BuildTarget target); - protected abstract void RenameFilesInStagingArea(BuildPostProcessArgs args); - - protected abstract IIl2CppPlatformProvider GetPlatformProvider(BuildPostProcessArgs args); - - protected virtual void ProcessPlatformSpecificIL2CPPOutput(BuildPostProcessArgs args) - { - } - - protected virtual void ProcessSymbolFiles(BuildPostProcessArgs args) - { - } - - protected string GetIl2CppDataBackupFolderName(BuildPostProcessArgs args) - { - return Path.GetFileNameWithoutExtension(args.installPath) + "_BackUpThisFolder_ButDontShipItWithYourGame"; - } - - protected virtual string GetDirectoryForGameAssembly(BuildPostProcessArgs args) - { - return args.stagingArea; - } - - protected virtual bool PlaceIL2CPPSymbolMapNextToExecutable() - { - return true; - } - - internal class ScriptingImplementations : DefaultScriptingImplementations - { - } -} diff --git a/Editor/Mono/BuildPipeline/DesktopStandaloneUserBuildSettings.cs b/Editor/Mono/BuildPipeline/DesktopStandaloneUserBuildSettings.cs deleted file mode 100644 index a82ab677e2..0000000000 --- a/Editor/Mono/BuildPipeline/DesktopStandaloneUserBuildSettings.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using UnityEditor.Modules; -using System.Collections.Generic; -using System.Text; - -internal static class DesktopStandaloneUserBuildSettings -{ - internal static string PlatformName - { - get - { - return "Standalone"; - } - } -} diff --git a/Editor/Mono/BuildPipeline/GendarmeAssemblyValidation.cs b/Editor/Mono/BuildPipeline/GendarmeAssemblyValidation.cs deleted file mode 100644 index 6d11e65672..0000000000 --- a/Editor/Mono/BuildPipeline/GendarmeAssemblyValidation.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Scripting; -using UnityEditor.Scripting.Compilers; -using UnityEditor.Utils; - -internal struct GendarmeOptions -{ - public string RuleSet; - public string ConfigFilePath; - public string[] UserAssemblies; -} - -internal abstract class GendarmeValidationRule : IValidationRule -{ - private readonly string _gendarmeExePath; - - protected GendarmeValidationRule(string gendarmeExePath) - { - _gendarmeExePath = gendarmeExePath; - } - - public ValidationResult Validate(IEnumerable userAssemblies, params object[] options) - { - var commandLine = BuildGendarmeCommandLineArguments(userAssemblies); - var result = new ValidationResult - { - Success = true, - Rule = this, - CompilerMessages = null - }; - - try - { - result.Success = StartManagedProgram(_gendarmeExePath, commandLine, new GendarmeOutputParser(), ref result.CompilerMessages); - } - catch (Exception e) - { - result.Success = false; - result.CompilerMessages = new[] - { - new CompilerMessage - { - file = "Exception", - message = e.Message, - line = 0, - column = 0, - type = CompilerMessageType.Error - } - }; - } - - return result; - } - - protected abstract GendarmeOptions ConfigureGendarme(IEnumerable userAssemblies); - - protected string BuildGendarmeCommandLineArguments(IEnumerable userAssemblies) - { - var options = ConfigureGendarme(userAssemblies); - if (options.UserAssemblies == null || options.UserAssemblies.Length == 0) - return null; - - var commandLine = new List - { - "--config " + options.ConfigFilePath, - "--set " + options.RuleSet, - }; - commandLine.AddRange(options.UserAssemblies); - - return commandLine.Aggregate((agg, i) => agg + " " + i); - } - - private static bool StartManagedProgram(string exe, string arguments, CompilerOutputParserBase parser, ref IEnumerable compilerMessages) - { - using (var p = ManagedProgramFor(exe, arguments)) - { - p.LogProcessStartInfo(); - try - { - p.Start(); - } - catch - { - throw new Exception("Could not start " + exe); - } - - p.WaitForExit(); - - if (p.ExitCode == 0) - return true; - - compilerMessages = parser.Parse(p.GetErrorOutput(), p.GetStandardOutput(), true); - } - - return false; - } - - private static ManagedProgram ManagedProgramFor(string exe, string arguments) - { - return new ManagedProgram(MonoInstallationFinder.GetMonoInstallation("MonoBleedingEdge"), null, exe, arguments, false, null); - } -} diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/FileMirroring.cs b/Editor/Mono/BuildPipeline/Il2Cpp/FileMirroring.cs deleted file mode 100644 index 34d8c4da4b..0000000000 --- a/Editor/Mono/BuildPipeline/Il2Cpp/FileMirroring.cs +++ /dev/null @@ -1,158 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using System.IO; -using System.Linq; - -namespace UnityEditorInternal -{ - internal static class FileMirroring - { - public static void MirrorFile(string from, string to) - { - MirrorFile(from, to, CanSkipCopy); - } - - public static void MirrorFile(string from, string to, Func comparer) - { - if (comparer(from, to)) - return; - - if (!File.Exists(from)) - { - DeleteFileOrDirectory(to); - return; - } - - var parentDir = Path.GetDirectoryName(to); - if (!Directory.Exists(parentDir)) - Directory.CreateDirectory(parentDir); - - File.Copy(from, to, true); - } - - public static void MirrorFolder(string from, string to) - { - MirrorFolder(from, to, CanSkipCopy); - } - - public static void MirrorFolder(string from, string to, Func comparer) - { - from = Path.GetFullPath(from); - to = Path.GetFullPath(to); - - if (!Directory.Exists(from)) - { - if (Directory.Exists(to)) - Directory.Delete(to, true); - return; - } - if (!Directory.Exists(to)) - Directory.CreateDirectory(to); - - var toFileEntries = Directory.GetFileSystemEntries(to).Select(s => StripPrefix(s, to)); - var fromFileEntries = Directory.GetFileSystemEntries(from).Select(s => StripPrefix(s, from)); - - var shouldDeletes = toFileEntries.Except(fromFileEntries); - foreach (var shouldDelete in shouldDeletes) - DeleteFileOrDirectory(Path.Combine(to, shouldDelete)); - - foreach (var file in fromFileEntries) - { - var absFrom = Path.Combine(from, file); - var absTo = Path.Combine(to, file); - - var fromType = FileEntryTypeFor(absFrom); - var toType = FileEntryTypeFor(absTo); - - if (fromType == FileEntryType.File && toType == FileEntryType.Directory) - DeleteFileOrDirectory(absTo); - - if (fromType == FileEntryType.Directory) - { - if (toType == FileEntryType.File) - DeleteFileOrDirectory(absTo); - - if (toType != FileEntryType.Directory) - Directory.CreateDirectory(absTo); - - MirrorFolder(absFrom, absTo); - } - - if (fromType == FileEntryType.File) - MirrorFile(absFrom, absTo, comparer); - } - } - - static void DeleteFileOrDirectory(string path) - { - if (File.Exists(path)) - { - File.Delete(path); - return; - } - if (Directory.Exists(path)) - Directory.Delete(path, true); - } - - static string StripPrefix(string s, string prefix) - { - return s.Substring(prefix.Length + 1); - } - - enum FileEntryType - { - File, - Directory, - NotExisting - } - - static FileEntryType FileEntryTypeFor(string fileEntry) - { - if (File.Exists(fileEntry)) - return FileEntryType.File; - if (Directory.Exists(fileEntry)) - return FileEntryType.Directory; - return FileEntryType.NotExisting; - } - - public static bool CanSkipCopy(string from, string to) - { - bool noFrom = !File.Exists(from); - bool noTo = !File.Exists(to); - // Early out: true if neither files exist, false if only one exists - if (noFrom || noTo) - return noFrom && noTo; - return AreFilesIdentical(from, to); - } - - static bool AreFilesIdentical(string filePath1, string filePath2) - { - using (var file = File.OpenRead(filePath1)) - using (var file2 = File.OpenRead(filePath2)) - { - if (file.Length != file2.Length) - return false; - - const int bufferSize = 0x10000; - int count; - var buffer = new byte[bufferSize]; - var buffer2 = new byte[bufferSize]; - - while ((count = file.Read(buffer, 0, buffer.Length)) > 0) - { - file2.Read(buffer2, 0, buffer2.Length); - - for (int i = 0; i < count; i++) - if (buffer[i] != buffer2[i]) - return false; - } - } - - return true; - } - } -} diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/ICompilerSettings.cs b/Editor/Mono/BuildPipeline/Il2Cpp/ICompilerSettings.cs deleted file mode 100644 index e550bf6c0d..0000000000 --- a/Editor/Mono/BuildPipeline/Il2Cpp/ICompilerSettings.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -interface ICompilerSettings -{ - string[] LibPaths { get; } - string CompilerPath { get; } - string LinkerPath { get; } - string MachineSpecification { get; } -} diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs deleted file mode 100644 index ca0eba2b7f..0000000000 --- a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs +++ /dev/null @@ -1,603 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using UnityEditor.Modules; -using UnityEditor.Scripting; -using UnityEditor.Scripting.Compilers; -using UnityEngine; -using UnityEditor; -using UnityEditor.Build.Reporting; -using UnityEditor.Utils; -using Debug = UnityEngine.Debug; -using PackageInfo = Unity.DataContract.PackageInfo; -using System.Xml.Linq; -using System.Xml.XPath; -using UnityEditor.Experimental.Build.Player; - -namespace UnityEditorInternal -{ - internal class IL2CPPUtils - { - public const string BinaryMetadataSuffix = "-metadata.dat"; - - internal static IIl2CppPlatformProvider PlatformProviderForNotModularPlatform(BuildTarget target, bool developmentBuild) - { - throw new Exception("Platform unsupported, or already modular."); - } - - internal static IL2CPPBuilder RunIl2Cpp(string tempFolder, string stagingAreaData, IIl2CppPlatformProvider platformProvider, Action modifyOutputBeforeCompile, RuntimeClassRegistry runtimeClassRegistry) - { - var builder = new IL2CPPBuilder(tempFolder, stagingAreaData, platformProvider, modifyOutputBeforeCompile, runtimeClassRegistry, IL2CPPUtils.UseIl2CppCodegenWithMonoBackend(BuildPipeline.GetBuildTargetGroup(platformProvider.target))); - builder.Run(); - return builder; - } - - internal static IL2CPPBuilder RunIl2Cpp(string stagingAreaData, IIl2CppPlatformProvider platformProvider, Action modifyOutputBeforeCompile, RuntimeClassRegistry runtimeClassRegistry) - { - var builder = new IL2CPPBuilder(stagingAreaData, stagingAreaData, platformProvider, modifyOutputBeforeCompile, runtimeClassRegistry, IL2CPPUtils.UseIl2CppCodegenWithMonoBackend(BuildPipeline.GetBuildTargetGroup(platformProvider.target))); - builder.Run(); - return builder; - } - - internal static IL2CPPBuilder RunCompileAndLink(string tempFolder, string stagingAreaData, IIl2CppPlatformProvider platformProvider, Action modifyOutputBeforeCompile, RuntimeClassRegistry runtimeClassRegistry) - { - var builder = new IL2CPPBuilder(tempFolder, stagingAreaData, platformProvider, modifyOutputBeforeCompile, runtimeClassRegistry, IL2CPPUtils.UseIl2CppCodegenWithMonoBackend(BuildPipeline.GetBuildTargetGroup(platformProvider.target))); - builder.RunCompileAndLink(); - return builder; - } - - internal static void CopyEmbeddedResourceFiles(string tempFolder, string destinationFolder) - { - foreach (var file in Directory.GetFiles(Paths.Combine(IL2CPPBuilder.GetCppOutputPath(tempFolder), "Data", "Resources")).Where(f => f.EndsWith("-resources.dat"))) - File.Copy(file, Paths.Combine(destinationFolder, Path.GetFileName(file)), true); - } - - internal static void CopySymmapFile(string tempFolder, string destinationFolder) - { - CopySymmapFile(tempFolder, destinationFolder, string.Empty); - } - - internal static void CopySymmapFile(string tempFolder, string destinationFolder, string destinationFileNameSuffix) - { - const string fileName = "SymbolMap"; - var file = Path.Combine(tempFolder, fileName); - if (File.Exists(file)) - File.Copy(file, Path.Combine(destinationFolder, fileName + destinationFileNameSuffix), true); - } - - internal static void CopyMetadataFiles(string tempFolder, string destinationFolder) - { - foreach (var file in Directory.GetFiles(Paths.Combine(IL2CPPBuilder.GetCppOutputPath(tempFolder), "Data", "Metadata")).Where(f => f.EndsWith(BinaryMetadataSuffix))) - File.Copy(file, Paths.Combine(destinationFolder, Path.GetFileName(file)), true); - } - - internal static void CopyConfigFiles(string tempFolder, string destinationFolder) - { - var sourceFolder = Paths.Combine(IL2CPPBuilder.GetCppOutputPath(tempFolder), "Data", "etc"); - FileUtil.CopyDirectoryRecursive(sourceFolder, destinationFolder); - } - - internal static string editorIl2cppFolder - { - get - { - var dir = @"il2cpp"; - return Path.GetFullPath(Path.Combine(EditorApplication.applicationContentsPath, dir)); - } - } - - internal static string ApiCompatibilityLevelToDotNetProfileArgument(ApiCompatibilityLevel compatibilityLevel) - { - switch (compatibilityLevel) - { - case ApiCompatibilityLevel.NET_2_0_Subset: - return "legacyunity"; - - case ApiCompatibilityLevel.NET_2_0: - return "net20"; - - case ApiCompatibilityLevel.NET_4_6: - return "unityjit"; - - case ApiCompatibilityLevel.NET_Standard_2_0: - return "unityaot"; - - default: - throw new NotSupportedException(string.Format("ApiCompatibilityLevel.{0} is not supported by IL2CPP!", compatibilityLevel)); - } - } - - internal static bool UseIl2CppCodegenWithMonoBackend(BuildTargetGroup targetGroup) - { - return EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest && - EditorApplication.useLibmonoBackendForIl2cpp && - PlayerSettings.GetScriptingBackend(targetGroup) == ScriptingImplementation.IL2CPP; - } - } - - internal class IL2CPPBuilder - { - private readonly string m_TempFolder; - private readonly string m_StagingAreaData; - private readonly IIl2CppPlatformProvider m_PlatformProvider; - private readonly Action m_ModifyOutputBeforeCompile; - private readonly RuntimeClassRegistry m_RuntimeClassRegistry; - private readonly LinkXmlReader m_linkXmlReader = new LinkXmlReader(); - private readonly bool m_BuildForMonoRuntime; - - public IL2CPPBuilder(string tempFolder, string stagingAreaData, IIl2CppPlatformProvider platformProvider, Action modifyOutputBeforeCompile, RuntimeClassRegistry runtimeClassRegistry, bool buildForMonoRuntime) - { - m_TempFolder = tempFolder; - m_StagingAreaData = stagingAreaData; - m_PlatformProvider = platformProvider; - m_ModifyOutputBeforeCompile = modifyOutputBeforeCompile; - m_RuntimeClassRegistry = runtimeClassRegistry; - m_BuildForMonoRuntime = buildForMonoRuntime; - } - - public void Run() - { - var outputDirectory = GetCppOutputDirectoryInStagingArea(); - var managedDir = Path.GetFullPath(Path.Combine(m_StagingAreaData, "Managed")); - - // Make all assemblies in Staging/Managed writable for stripping. - foreach (var file in Directory.GetFiles(managedDir)) - { - var fileInfo = new FileInfo(file); - fileInfo.IsReadOnly = false; - } - - AssemblyStripper.StripAssemblies(managedDir, m_PlatformProvider, m_RuntimeClassRegistry); - - // The IL2CPP editor integration here is responsible to give il2cpp.exe an empty directory to use. - FileUtil.CreateOrCleanDirectory(outputDirectory); - - if (m_ModifyOutputBeforeCompile != null) - m_ModifyOutputBeforeCompile(outputDirectory); - - ConvertPlayerDlltoCpp(GetUserAssembliesToConvert(managedDir), outputDirectory, managedDir, m_PlatformProvider.supportsManagedDebugging); - - var compiler = m_PlatformProvider.CreateNativeCompiler(); - if (compiler != null && m_PlatformProvider.CreateIl2CppNativeCodeBuilder() == null) - { - var nativeLibPath = OutputFileRelativePath(); - - var includePaths = new List(m_PlatformProvider.includePaths); - includePaths.Add(outputDirectory); - - m_PlatformProvider.CreateNativeCompiler().CompileDynamicLibrary( - nativeLibPath, - NativeCompiler.AllSourceFilesIn(outputDirectory), - includePaths, - m_PlatformProvider.libraryPaths, - new string[0]); - } - } - - public void RunCompileAndLink() - { - var il2CppNativeCodeBuilder = m_PlatformProvider.CreateIl2CppNativeCodeBuilder(); - if (il2CppNativeCodeBuilder != null) - { - Il2CppNativeCodeBuilderUtils.ClearAndPrepareCacheDirectory(il2CppNativeCodeBuilder); - - var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(m_PlatformProvider.target); - var useDebugBuild = PlayerSettings.GetIl2CppCompilerConfiguration(buildTargetGroup) == Il2CppCompilerConfiguration.Debug; - var arguments = Il2CppNativeCodeBuilderUtils.AddBuilderArguments(il2CppNativeCodeBuilder, OutputFileRelativePath(), m_PlatformProvider.includePaths, useDebugBuild).ToList(); - - arguments.Add(string.Format("--map-file-parser=\"{0}\"", GetMapFileParserPath())); - arguments.Add(string.Format("--generatedcppdir=\"{0}\"", Path.GetFullPath(GetCppOutputDirectoryInStagingArea()))); - if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_4_6) - arguments.Add("--dotnetprofile=\"unityjit\""); - if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_Standard_2_0) - arguments.Add("--dotnetprofile=\"unityaot\""); - Action setupStartInfo = il2CppNativeCodeBuilder.SetupStartInfo; - var managedDir = Path.GetFullPath(Path.Combine(m_StagingAreaData, "Managed")); - - RunIl2CppWithArguments(arguments, setupStartInfo, managedDir); - } - } - - private string OutputFileRelativePath() - { - var nativeLibPath = Path.Combine(m_StagingAreaData, "Native"); - Directory.CreateDirectory(nativeLibPath); - nativeLibPath = Path.Combine(nativeLibPath, m_PlatformProvider.nativeLibraryFileName); - return nativeLibPath; - } - - internal List GetUserAssembliesToConvert(string managedDir) - { - var userAssemblies = GetUserAssemblies(managedDir); - userAssemblies.Add(Directory.GetFiles(managedDir, "UnityEngine.dll", SearchOption.TopDirectoryOnly).Single()); - userAssemblies.UnionWith(FilterUserAssemblies(Directory.GetFiles(managedDir, "*.dll", SearchOption.TopDirectoryOnly), m_linkXmlReader.IsDLLUsed, managedDir)); - - return userAssemblies.ToList(); - } - - private HashSet GetUserAssemblies(string managedDir) - { - HashSet userAssemblies = new HashSet(); - userAssemblies.UnionWith(FilterUserAssemblies(m_RuntimeClassRegistry.GetUserAssemblies(), m_RuntimeClassRegistry.IsDLLUsed, managedDir)); - userAssemblies.UnionWith(FilterUserAssemblies(Directory.GetFiles(managedDir, "I18N*.dll", SearchOption.TopDirectoryOnly), (assembly) => true, managedDir)); - - return userAssemblies; - } - - private IEnumerable FilterUserAssemblies(IEnumerable assemblies, Predicate isUsed, string managedDir) - { - return assemblies.Where(assembly => isUsed(assembly)).Select(usedAssembly => Path.Combine(managedDir, usedAssembly)); - } - - public string GetCppOutputDirectoryInStagingArea() - { - return GetCppOutputPath(m_TempFolder); - } - - public static string GetCppOutputPath(string tempFolder) - { - return Path.Combine(tempFolder, "il2cppOutput"); - } - - public static string GetMapFileParserPath() - { - return Path.GetFullPath( - Path.Combine( - EditorApplication.applicationContentsPath, - Application.platform == RuntimePlatform.WindowsEditor ? @"Tools\MapFileParser\MapFileParser.exe" : @"Tools/MapFileParser/MapFileParser")); - } - - private void ConvertPlayerDlltoCpp(ICollection userAssemblies, string outputDirectory, string workingDirectory, bool platformSupportsManagedDebugging) - { - if (userAssemblies.Count == 0) - return; - - var arguments = new List(); - - arguments.Add("--convert-to-cpp"); - - if (m_PlatformProvider.emitNullChecks) - arguments.Add("--emit-null-checks"); - - if (m_PlatformProvider.enableStackTraces) - arguments.Add("--enable-stacktrace"); - - if (m_PlatformProvider.enableArrayBoundsCheck) - arguments.Add("--enable-array-bounds-check"); - - if (m_PlatformProvider.enableDivideByZeroCheck) - arguments.Add("--enable-divide-by-zero-check"); - - if (m_PlatformProvider.developmentMode) - arguments.Add("--development-mode"); - - if (m_BuildForMonoRuntime) - arguments.Add("--mono-runtime"); - - var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(m_PlatformProvider.target); - if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_4_6) - arguments.Add("--dotnetprofile=\"unityjit\""); - - if (PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup) == ApiCompatibilityLevel.NET_Standard_2_0) - arguments.Add("--dotnetprofile=\"unityaot\""); - - if (EditorUserBuildSettings.allowDebugging && platformSupportsManagedDebugging && EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) - arguments.Add("--enable-debugger"); - - var il2CppNativeCodeBuilder = m_PlatformProvider.CreateIl2CppNativeCodeBuilder(); - if (il2CppNativeCodeBuilder != null) - { - var useDebugBuild = PlayerSettings.GetIl2CppCompilerConfiguration(buildTargetGroup) == Il2CppCompilerConfiguration.Debug; - - Il2CppNativeCodeBuilderUtils.ClearAndPrepareCacheDirectory(il2CppNativeCodeBuilder); - arguments.AddRange(Il2CppNativeCodeBuilderUtils.AddBuilderArguments(il2CppNativeCodeBuilder, OutputFileRelativePath(), m_PlatformProvider.includePaths, useDebugBuild)); - } - - arguments.Add(string.Format("--map-file-parser=\"{0}\"", GetMapFileParserPath())); - - var additionalArgs = PlayerSettings.GetAdditionalIl2CppArgs(); - if (!string.IsNullOrEmpty(additionalArgs)) - arguments.Add(additionalArgs); - - additionalArgs = System.Environment.GetEnvironmentVariable("IL2CPP_ADDITIONAL_ARGS"); - if (!string.IsNullOrEmpty(additionalArgs)) - { - arguments.Add(additionalArgs); - } - - var pathArguments = new List(userAssemblies); - arguments.AddRange(pathArguments.Select(arg => "--assembly=\"" + Path.GetFullPath(arg) + "\"")); - - arguments.Add(string.Format("--generatedcppdir=\"{0}\"", Path.GetFullPath(outputDirectory))); - - string progressMessage = "Converting managed assemblies to C++"; - if (il2CppNativeCodeBuilder != null) - { - progressMessage = "Building native binary with IL2CPP..."; - } - - if (EditorUtility.DisplayCancelableProgressBar("Building Player", progressMessage, 0.3f)) - throw new OperationCanceledException(); - - Action setupStartInfo = null; - if (il2CppNativeCodeBuilder != null) - setupStartInfo = il2CppNativeCodeBuilder.SetupStartInfo; - - if (PlayerBuildInterface.ExtraTypesProvider != null) - { - var extraTypes = new HashSet(); - foreach (var extraType in PlayerBuildInterface.ExtraTypesProvider()) - { - extraTypes.Add(extraType); - } - - var tempFile = Path.GetFullPath(Path.Combine(m_TempFolder, "extra-types.txt")); - File.WriteAllLines(tempFile, extraTypes.ToArray()); - arguments.Add(string.Format("--extra-types-file=\"{0}\"", tempFile)); - } - - RunIl2CppWithArguments(arguments, setupStartInfo, workingDirectory); - } - - private void RunIl2CppWithArguments(List arguments, Action setupStartInfo, string workingDirectory) - { - var args = arguments.Aggregate(String.Empty, (current, arg) => current + arg + " "); - - var useNetCore = ShouldUseIl2CppCore(); - string il2CppPath = useNetCore ? GetIl2CppCoreExe() : GetIl2CppExe(); - - Console.WriteLine("Invoking il2cpp with arguments: " + args); - - CompilerOutputParserBase il2cppOutputParser = m_PlatformProvider.CreateIl2CppOutputParser(); - if (il2cppOutputParser == null) - il2cppOutputParser = new Il2CppOutputParser(); - - if (useNetCore) - Runner.RunNetCoreProgram(il2CppPath, args, workingDirectory, il2cppOutputParser, setupStartInfo); - else - Runner.RunManagedProgram(il2CppPath, args, workingDirectory, il2cppOutputParser, setupStartInfo); - } - - private string GetIl2CppExe() - { - return m_PlatformProvider.il2CppFolder + "/build/il2cpp.exe"; - } - - private string GetIl2CppCoreExe() - { - return m_PlatformProvider.il2CppFolder + "/build/il2cppcore/il2cppcore.dll"; - } - - private bool ShouldUseIl2CppCore() - { - bool shouldUse = false; - if (Application.platform == RuntimePlatform.OSXEditor) - { - // On OSX 10.8 (and mabybe older versions, not sure) running .NET Core will result in the following error : - // dyld: lazy symbol binding failed: Symbol not found: __sincos_stret - // - // I'm not sure exactly what the issue is, but based on some google searching it's an issue not unique to .NET Core - // and it does not happen in 10.9 and later. - // - // Some of our graphics tests run on OSX 10.8 and some users may have 10.8, in order to keep 10.8 working - // we will fallback to running il2cpp on mono. - // And as a precaution, let's use il2cpp on mono for anything older than 10.8 as well - if (SystemInfo.operatingSystem.StartsWith("Mac OS X 10.")) - { - var versionText = SystemInfo.operatingSystem.Substring(9); - var version = new Version(versionText); - - if (version >= new Version(10, 9)) - shouldUse = true; - } - else - { - shouldUse = true; - } - } - - return shouldUse && NetCoreProgram.IsNetCoreAvailable(); - } - } - - internal interface IIl2CppPlatformProvider - { - BuildTarget target { get; } - bool emitNullChecks { get; } - bool enableStackTraces { get; } - bool enableArrayBoundsCheck { get; } - bool enableDivideByZeroCheck { get; } - string nativeLibraryFileName { get; } - string il2CppFolder { get; } - bool developmentMode { get; } - string moduleStrippingInformationFolder { get; } - bool supportsEngineStripping { get; } - bool supportsManagedDebugging { get; } - - BuildReport buildReport { get; } - string[] includePaths { get; } - string[] libraryPaths { get; } - - INativeCompiler CreateNativeCompiler(); - Il2CppNativeCodeBuilder CreateIl2CppNativeCodeBuilder(); - CompilerOutputParserBase CreateIl2CppOutputParser(); - } - - internal class BaseIl2CppPlatformProvider : IIl2CppPlatformProvider - { - public BaseIl2CppPlatformProvider(BuildTarget target, string libraryFolder) - { - this.target = target; - this.libraryFolder = libraryFolder; - } - - public virtual BuildTarget target { get; private set; } - - public virtual string libraryFolder { get; private set; } - - public virtual bool developmentMode - { - get { return false; } - } - - public virtual bool emitNullChecks - { - get { return true; } - } - - public virtual bool enableStackTraces - { - get { return true; } - } - - public virtual bool enableArrayBoundsCheck - { - get { return true; } - } - - public virtual bool enableDivideByZeroCheck - { - get { return false; } - } - - public virtual bool supportsEngineStripping - { - get { return false; } - } - - public virtual bool supportsManagedDebugging - { - get { return false; } - } - - public virtual BuildReport buildReport - { - get { return null; } - } - - public virtual string[] includePaths - { - get - { - return new[] { - GetFolderInPackageOrDefault("bdwgc/include"), - GetFolderInPackageOrDefault("libil2cpp/include") - }; - } - } - - public virtual string[] libraryPaths - { - get - { - return new[] { - GetFileInPackageOrDefault("bdwgc/lib/bdwgc." + staticLibraryExtension), - GetFileInPackageOrDefault("libil2cpp/lib/libil2cpp." + staticLibraryExtension) - }; - } - } - - public virtual string nativeLibraryFileName - { - get { return null; } - } - - public virtual string staticLibraryExtension - { - get { return "a"; } - } - - public virtual string il2CppFolder - { - get - { - var il2CppPackage = FindIl2CppPackage(); - if (il2CppPackage == null) - { - return Path.GetFullPath(Path.Combine( - EditorApplication.applicationContentsPath, - "il2cpp")); - } - - return il2CppPackage.basePath; - } - } - - public virtual string moduleStrippingInformationFolder - { - get { return Path.Combine(BuildPipeline.GetPlaybackEngineDirectory(EditorUserBuildSettings.activeBuildTarget, 0), "Whitelists"); } - } - - public virtual INativeCompiler CreateNativeCompiler() - { - return null; - } - - public virtual Il2CppNativeCodeBuilder CreateIl2CppNativeCodeBuilder() - { - return null; - } - - public virtual CompilerOutputParserBase CreateIl2CppOutputParser() - { - return null; - } - - protected string GetFolderInPackageOrDefault(string path) - { - var il2CppPackage = FindIl2CppPackage(); - if (il2CppPackage == null) - return Path.Combine(libraryFolder, path); - - var folder = Path.Combine(il2CppPackage.basePath, path); - return !Directory.Exists(folder) ? Path.Combine(libraryFolder, path) : folder; - } - - protected string GetFileInPackageOrDefault(string path) - { - var il2CppPackage = FindIl2CppPackage(); - if (il2CppPackage == null) - return Path.Combine(libraryFolder, path); - - var file = Path.Combine(il2CppPackage.basePath, path); - return !File.Exists(file) ? Path.Combine(libraryFolder, path) : file; - } - - private static PackageInfo FindIl2CppPackage() - { - return ModuleManager.packageManager.unityExtensions.FirstOrDefault(e => e.name == "IL2CPP"); - } - } - - internal class LinkXmlReader - { - private readonly List _assembliesInALinkXmlFile = new List(); - - public LinkXmlReader() - { - foreach (var linkXmlFile in AssemblyStripper.GetUserBlacklistFiles()) - { - XPathDocument linkXml = new XPathDocument(linkXmlFile); - var navigator = linkXml.CreateNavigator(); - navigator.MoveToFirstChild(); - var iterator = navigator.SelectChildren("assembly", string.Empty); - - while (iterator.MoveNext()) - _assembliesInALinkXmlFile.Add(iterator.Current.GetAttribute("fullname", string.Empty)); - } - } - - public bool IsDLLUsed(string assemblyFileName) - { - return _assembliesInALinkXmlFile.Contains(Path.GetFileNameWithoutExtension(assemblyFileName)); - } - } -} diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/INativeCompiler.cs b/Editor/Mono/BuildPipeline/Il2Cpp/INativeCompiler.cs deleted file mode 100644 index a6501d074e..0000000000 --- a/Editor/Mono/BuildPipeline/Il2Cpp/INativeCompiler.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; - -interface INativeCompiler -{ - void CompileDynamicLibrary(string outFile, IEnumerable sources, IEnumerable includePaths, IEnumerable libraries, IEnumerable libraryPaths); -} diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs b/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs deleted file mode 100644 index 7baea1079d..0000000000 --- a/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; - -namespace UnityEditorInternal -{ - public abstract class Il2CppNativeCodeBuilder - { - /// - /// Implement this property to tell IL2CPP about the platform for the C++ compiler. - /// This platform must be known in the Unity.IL2CPP.Builder code. - /// - public abstract string CompilerPlatform { get; } - - /// - /// Implement this property to tell IL2CPP about the architecture for the C++ compiler. - /// This architecture must be known in the Unity.IL2CPP.Builder code. - /// - public abstract string CompilerArchitecture { get; } - - /// - /// Provide any compiler flags IL2CPP should use in addition to the default ones. - /// The default value of this property is an empty string. - /// - public virtual string CompilerFlags - { - get { return string.Empty; } - } - - /// - /// Provide any linker flags IL2CPP should use in addition to the default ones. - /// The default value of this property is an empty string. - /// - public virtual string LinkerFlags - { - get { return string.Empty; } - } - - /// - /// IL2CPP should not try to set up the environment for the C++ compiler internally. Instead, it will - /// use the environment it is provided. If this is true, SetupEnvironment will be called. - /// The default value of this property is false. - /// - public virtual bool SetsUpEnvironment - { - get { return false; } - } - - /// - /// Provide a cache directory for IL2CPP to use to save build artifacts used for incremental builds. - /// If this does not exist, a full build will occur. - /// The default value of this property is an empty string, which disables incremental builds. - /// - public virtual string CacheDirectory - { - get { return string.Empty; } - } - - /// - /// Provide the path to a plugin - /// - public virtual string PluginPath - { - get { return string.Empty; } - } - - - public virtual IEnumerable AdditionalIl2CPPArguments - { - get { return new string[0]; } - } - - /// - /// If this property returns true the argument "--libil2cpp-static" will be used when calling il2cpp.exe - - /// - public virtual bool LinkLibIl2CppStatically - { - get { return true; } - } - - /// - /// Change the relative include paths into absolute paths that can be passed to the C++ compiler. - /// By default this method returns its input with each path relative to the current directory. - /// - /// The list of relative paths to convert - /// A list of full paths - public virtual IEnumerable ConvertIncludesToFullPaths(IEnumerable relativeIncludePaths) - { - var workingDirectory = Directory.GetCurrentDirectory(); - return relativeIncludePaths.Select(path => Path.Combine(workingDirectory, path)); - } - - /// - /// Change the relative path to the output file to an absolute path that can be passed to the C++ compiler. - /// By default this method returns its input relative to the current directory. - /// - /// The relative output file path to convert - /// The full output file path - public virtual string ConvertOutputFileToFullPath(string outputFileRelativePath) - { - return Path.Combine(Directory.GetCurrentDirectory(), outputFileRelativePath); - } - - public void SetupStartInfo(ProcessStartInfo startInfo) - { - if (SetsUpEnvironment) - SetupEnvironment(startInfo); - } - - /// - /// Override this method if SetsUpEnvironment is override to return true. This will allow - /// the ProcessStartInfo for IL2CPP to be modified. - /// - /// The ProcessStartInfo for IL2CPP - protected virtual void SetupEnvironment(ProcessStartInfo startInfo) - { - } - } -} diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilderUtils.cs b/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilderUtils.cs deleted file mode 100644 index 6c7dfacf79..0000000000 --- a/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilderUtils.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor; - -namespace UnityEditorInternal -{ - public static class Il2CppNativeCodeBuilderUtils - { - public static IEnumerable AddBuilderArguments(Il2CppNativeCodeBuilder builder, string outputRelativePath, IEnumerable includeRelativePaths, bool debugBuild) - { - var arguments = new List(); - - arguments.Add("--compile-cpp"); - if (builder.LinkLibIl2CppStatically) - arguments.Add("--libil2cpp-static"); - arguments.Add(FormatArgument("platform", builder.CompilerPlatform)); - arguments.Add(FormatArgument("architecture", builder.CompilerArchitecture)); - - if (debugBuild) - arguments.Add(FormatArgument("configuration", "Debug")); - else - arguments.Add(FormatArgument("configuration", "Release")); - - arguments.Add(FormatArgument("outputpath", builder.ConvertOutputFileToFullPath(outputRelativePath))); - - if (!string.IsNullOrEmpty(builder.CacheDirectory)) - arguments.Add(FormatArgument("cachedirectory", CacheDirectoryPathFor(builder.CacheDirectory))); - - if (!string.IsNullOrEmpty(builder.CompilerFlags)) - arguments.Add(FormatArgument("compiler-flags", builder.CompilerFlags)); - - if (!string.IsNullOrEmpty(builder.LinkerFlags)) - arguments.Add(FormatArgument("linker-flags", builder.LinkerFlags)); - - if (!string.IsNullOrEmpty(builder.PluginPath)) - arguments.Add(FormatArgument("plugin", builder.PluginPath)); - - foreach (var includePath in builder.ConvertIncludesToFullPaths(includeRelativePaths)) - arguments.Add(FormatArgument("additional-include-directories", includePath)); - - arguments.AddRange(builder.AdditionalIl2CPPArguments); - - return arguments; - } - - public static void ClearAndPrepareCacheDirectory(Il2CppNativeCodeBuilder builder) - { - var currentEditorVersion = InternalEditorUtility.GetFullUnityVersion(); - ClearCacheIfEditorVersionDiffers(builder, currentEditorVersion); - PrepareCacheDirectory(builder, currentEditorVersion); - } - - public static void ClearCacheIfEditorVersionDiffers(Il2CppNativeCodeBuilder builder, string currentEditorVersion) - { - var cacheDirectoryPath = CacheDirectoryPathFor(builder.CacheDirectory); - if (Directory.Exists(cacheDirectoryPath)) - { - if (!File.Exists(Path.Combine(builder.CacheDirectory, EditorVersionFilenameFor(currentEditorVersion)))) - Directory.Delete(cacheDirectoryPath, true); - } - } - - public static void PrepareCacheDirectory(Il2CppNativeCodeBuilder builder, string currentEditorVersion) - { - var cacheDirectoryPath = CacheDirectoryPathFor(builder.CacheDirectory); - Directory.CreateDirectory(cacheDirectoryPath); - var versionFilePath = Path.Combine(builder.CacheDirectory, EditorVersionFilenameFor(currentEditorVersion)); - if (!File.Exists(versionFilePath)) - File.Create(versionFilePath).Dispose(); - } - - public static string ObjectFilePathInCacheDirectoryFor(string builderCacheDirectory) - { - return CacheDirectoryPathFor(builderCacheDirectory); - } - - private static string CacheDirectoryPathFor(string builderCacheDirectory) - { - return builderCacheDirectory + "/il2cpp_cache"; - } - - private static string FormatArgument(string name, string value) - { - return string.Format("--{0}=\"{1}\"", name, EscapeEmbeddedQuotes(value)); - } - - private static string EditorVersionFilenameFor(string editorVersion) - { - return string.Format("il2cpp_cache {0}", editorVersion); - } - - private static string EscapeEmbeddedQuotes(string value) - { - return value.Replace("\"", "\\\""); - } - } -} diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/NativeCompiler.cs b/Editor/Mono/BuildPipeline/Il2Cpp/NativeCompiler.cs deleted file mode 100644 index 73f9fddf91..0000000000 --- a/Editor/Mono/BuildPipeline/Il2Cpp/NativeCompiler.cs +++ /dev/null @@ -1,116 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading; - -internal abstract class NativeCompiler : INativeCompiler -{ - protected virtual string objectFileExtension { get { return "o"; } } - - public abstract void CompileDynamicLibrary(string outFile, IEnumerable sources, IEnumerable includePaths, IEnumerable libraries, IEnumerable libraryPaths); - - protected virtual void SetupProcessStartInfo(ProcessStartInfo startInfo) - { - } - - protected void Execute(string arguments, string compilerPath) - { - var startInfo = new ProcessStartInfo(compilerPath, arguments); - - SetupProcessStartInfo(startInfo); - - RunProgram(startInfo); - } - - protected void ExecuteCommand(string command, params string[] arguments) - { - var startInfo = new ProcessStartInfo(command, arguments.Aggregate((buff, s) => buff + " " + s)); - - SetupProcessStartInfo(startInfo); - - RunProgram(startInfo); - } - - private void RunProgram(ProcessStartInfo startInfo) - { - using (var program = new UnityEditor.Utils.Program(startInfo)) - { - program.Start(); - - while (!program.WaitForExit(100)) - { - } - - var output = string.Empty; - var standardOutput = program.GetStandardOutput(); - if (standardOutput.Length > 0) - output = standardOutput.Aggregate((buf, s) => buf + Environment.NewLine + s); - - var errorOutput = program.GetErrorOutput(); - if (errorOutput.Length > 0) - output += errorOutput.Aggregate((buf, s) => buf + Environment.NewLine + s); - - if (program.ExitCode != 0) - { - UnityEngine.Debug.LogError("Failed running " + startInfo.FileName + " " + startInfo.Arguments + "\n\n" + output); - - throw new Exception("IL2CPP compile failed."); - } - } - } - - protected static string Aggregate(IEnumerable items, string prefix, string suffix) - { - return items.Aggregate("", (current, additionalFile) => current + (prefix + additionalFile + suffix)); - } - - class Counter - { - public int index; - } - - internal static void ParallelFor(T[] sources, Action action) - { - var threads = new Thread[Environment.ProcessorCount]; - var counter = new Counter(); - for (var i = 0; i < threads.Length; i++) - { - threads[i] = new Thread(delegate(object obj) - { - var c = (Counter)obj; - int index; - while ((index = Interlocked.Increment(ref c.index)) <= sources.Length) - { - action(sources[index - 1]); - } - }); - } - foreach (var t in threads) - t.Start(counter); - foreach (var t in threads) - t.Join(); - } - - protected internal static IEnumerable AllSourceFilesIn(string directory) - { - return Directory.GetFiles(directory, "*.cpp", SearchOption.AllDirectories) - .Concat(Directory.GetFiles(directory, "*.c", SearchOption.AllDirectories)); - } - - protected internal static bool IsSourceFile(string source) - { - var extension = Path.GetExtension(source); - return extension == "cpp" || extension == "c"; - } - - protected string ObjectFileFor(string source) - { - return Path.ChangeExtension(source, objectFileExtension); - } -} diff --git a/Editor/Mono/BuildPipeline/MonoAssemblyStripping.cs b/Editor/Mono/BuildPipeline/MonoAssemblyStripping.cs deleted file mode 100644 index 56cf7ede44..0000000000 --- a/Editor/Mono/BuildPipeline/MonoAssemblyStripping.cs +++ /dev/null @@ -1,333 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using System.IO; -using System; -using Mono.Cecil; -using Mono.Collections.Generic; -using System.Diagnostics; -using System.Text; -using UnityEditor.Utils; -using Debug = System.Diagnostics.Debug; -using System.Threading; - -namespace UnityEditor -{ - internal class MonoProcessRunner - { - public StringBuilder Output = new StringBuilder(""); - public StringBuilder Error = new StringBuilder(""); - - public bool Run(Process process) - { - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.RedirectStandardError = true; - - Thread outputReader = new Thread(ReadOutput); - Thread errorReader = new Thread(ReadErrors); - - process.Start(); - - outputReader.Start(process); - errorReader.Start(process); - - // We will only allow a single project to take up to 10 minutes to compile. - // if it takes longer we assume something is wrong and kill it this may be - // a bad assumption but it's what we currently do across the board. - bool exitOK = process.WaitForExit(1000 * 60 * 10); // 10 minutes - - // We give each thread up to 5ms to finish capturing output from the process. - // if they fail we assume that there is something wrong. This may not really - // be the case but we simply assume it is as we don't want to wait around for - // to long. - DateTime start = DateTime.Now; - while ((outputReader.IsAlive || errorReader.IsAlive) && (DateTime.Now - start).TotalMilliseconds < 5.0) - { - Thread.Sleep(0); - } - - // If our threads are still running nuke the threads using the standard - // exception mechanism, we forcefully do this because we can't wait around - // all day to get output back from a bad compilation process. - if (outputReader.IsAlive) - outputReader.Abort(); - - if (errorReader.IsAlive) - errorReader.Abort(); - - // Ensure things get cleaned up and threads are now gone. - outputReader.Join(); - errorReader.Join(); - - return exitOK; - } - - void ReadOutput(object process) - { - Process p = process as Process; - try - { - using (StreamReader outp = p.StandardOutput) - { - Output.Append(outp.ReadToEnd()); - } - } - catch (ThreadAbortException) {} - } - - void ReadErrors(object process) - { - Process p = process as Process; - try - { - using (StreamReader err = p.StandardError) - { - Error.Append(err.ReadToEnd()); - } - } - catch (ThreadAbortException) {} - } - } - - internal class MonoProcessUtility - { - public static string ProcessToString(Process process) - { - return process.StartInfo.FileName + " " + - process.StartInfo.Arguments + " current dir : " + - process.StartInfo.WorkingDirectory + "\n"; - } - - public static void RunMonoProcess(Process process, string name, string resultingFile) - { - MonoProcessRunner runner = new MonoProcessRunner(); - bool exitOK = runner.Run(process); - if (process.ExitCode != 0 || !File.Exists(resultingFile)) - { - string detailedMessage = "Failed " + name + ": " + ProcessToString(process) + " result file exists: " + File.Exists(resultingFile) + ". Timed out: " + !exitOK; - detailedMessage += "\n\n"; - detailedMessage += "stdout:\n" + runner.Output + "\n"; - detailedMessage += "stderr:\n" + runner.Error + "\n"; - System.Console.WriteLine(detailedMessage); - throw new UnityException(detailedMessage); - /// ;; TODO add micromscorlib warning - } - } - - public static Process PrepareMonoProcess(string workDir) - { - var process = new Process(); - - var executableName = Application.platform == RuntimePlatform.WindowsEditor ? "mono.exe" : "mono"; - process.StartInfo.FileName = Paths.Combine(MonoInstallationFinder.GetMonoInstallation(), "bin", executableName); - - // ;; TODO fix this hack for strange process handle duplication problem inside mono - process.StartInfo.EnvironmentVariables["_WAPI_PROCESS_HANDLE_OFFSET"] = "5"; - - // We run the linker on .NET 2.0 profile - var monoProfile = BuildPipeline.CompatibilityProfileToClassLibFolder(ApiCompatibilityLevel.NET_2_0); - process.StartInfo.EnvironmentVariables["MONO_PATH"] = MonoInstallationFinder.GetProfileDirectory(monoProfile); - process.StartInfo.UseShellExecute = false; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.RedirectStandardError = true; - process.StartInfo.CreateNoWindow = true; - - process.StartInfo.WorkingDirectory = workDir; - - return process; - } - - public static Process PrepareMonoProcessBleedingEdge(string workDir) - { - var process = new Process(); - - var executableName = Application.platform == RuntimePlatform.WindowsEditor ? "mono.exe" : "mono"; - process.StartInfo.FileName = Paths.Combine(MonoInstallationFinder.GetMonoBleedingEdgeInstallation(), "bin", executableName); - - // ;; TODO fix this hack for strange process handle duplication problem inside mono - process.StartInfo.EnvironmentVariables["_WAPI_PROCESS_HANDLE_OFFSET"] = "5"; - - // We run the stripper on .NET 4.6 profile - var monoProfile = BuildPipeline.CompatibilityProfileToClassLibFolder(ApiCompatibilityLevel.NET_4_6); - process.StartInfo.EnvironmentVariables["MONO_PATH"] = MonoInstallationFinder.GetProfileDirectory(monoProfile); - process.StartInfo.UseShellExecute = false; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.RedirectStandardError = true; - process.StartInfo.CreateNoWindow = true; - - process.StartInfo.WorkingDirectory = workDir; - - return process; - } - } - - internal class MonoAssemblyStripping - { - static void ReplaceFile(string src, string dst) - { - if (File.Exists(dst)) - FileUtil.DeleteFileOrDirectory(dst); - - FileUtil.CopyFileOrDirectory(src, dst); - } - - static public void MonoCilStrip(BuildTarget buildTarget, string managedLibrariesDirectory, string[] fileNames) - { - string basePath = MonoInstallationFinder.GetProfileDirectory(BuildPipeline.CompatibilityProfileToClassLibFolder(ApiCompatibilityLevel.NET_4_6), MonoInstallationFinder.MonoBleedingEdgeInstallation); - string cilStripper = Path.Combine(basePath, "mono-cil-strip.exe"); - - foreach (string fileName in fileNames) - { - Process process = MonoProcessUtility.PrepareMonoProcessBleedingEdge(managedLibrariesDirectory); - string outFile = fileName + ".out"; - - process.StartInfo.Arguments = "\"" + cilStripper + "\""; - process.StartInfo.Arguments += " \"" + fileName + "\" \"" + fileName + ".out\""; - - MonoProcessUtility.RunMonoProcess(process, "byte code stripper", Path.Combine(managedLibrariesDirectory, outFile)); - - ReplaceFile(managedLibrariesDirectory + "/" + outFile, managedLibrariesDirectory + "/" + fileName); - File.Delete(managedLibrariesDirectory + "/" + outFile); - } - } - - public static string GenerateLinkXmlToPreserveDerivedTypes(string librariesFolder, RuntimeClassRegistry usedClasses) - { - string path = Path.GetTempFileName(); - - using (TextWriter w = new StreamWriter(path)) - { - w.WriteLine(""); - foreach (var assembly in CollectAllAssemblies(librariesFolder, usedClasses)) - { - if (AssemblyHelper.IsUnityEngineModule(assembly)) - continue; - - var typesToPreserve = new HashSet(); - CollectBlackListTypes(typesToPreserve, assembly.MainModule.Types, usedClasses.GetAllManagedBaseClassesAsString()); - - // don't write out xml file for assemblies with no types since link.xml files on disk have special meaning to IL2CPP stripping - if (typesToPreserve.Count == 0) - continue; - - w.WriteLine("", assembly.Name.Name); - foreach (var typeToPreserve in typesToPreserve) - w.WriteLine("", typeToPreserve.FullName); - w.WriteLine(""); - } - w.WriteLine(""); - } - - return path; - } - - // this logic produces similar list of assemblies that IL2CPP will convert (it differs in the way it collects winmd files) - public static IEnumerable CollectAllAssemblies(string librariesFolder, RuntimeClassRegistry usedClasses) - { - var resolver = new DefaultAssemblyResolver(); - resolver.RemoveSearchDirectory("."); - resolver.RemoveSearchDirectory("bin"); - resolver.AddSearchDirectory(librariesFolder); - - var usedDlls = usedClasses.GetUserAssemblies().Where(s => usedClasses.IsDLLUsed(s)).Select(file => AssemblyNameReference.Parse(Path.GetFileNameWithoutExtension(file))); - return CollectAssembliesRecursive(usedDlls.Select(dll => ResolveAssemblyReference(resolver, dll)).Where(a => a != null)); - } - - private static HashSet CollectAssembliesRecursive(IEnumerable assemblies) - { - var pendingAssemblies = new HashSet(assemblies, new AssemblyDefinitionComparer()); - - var previousCount = 0; - while (pendingAssemblies.Count > previousCount) - { - previousCount = pendingAssemblies.Count; - pendingAssemblies.UnionWith(pendingAssemblies.ToArray().SelectMany(a => ResolveAssemblyReferences(a))); - } - - return pendingAssemblies; - } - - public static IEnumerable ResolveAssemblyReferences(AssemblyDefinition assembly) - { - return ResolveAssemblyReferences(assembly.MainModule.AssemblyResolver, assembly.MainModule.AssemblyReferences); - } - - public static IEnumerable ResolveAssemblyReferences(IAssemblyResolver resolver, IEnumerable assemblyReferences) - { - return assemblyReferences.Select(reference => ResolveAssemblyReference(resolver, reference)).Where(a => a != null); - } - - public static AssemblyDefinition ResolveAssemblyReference(IAssemblyResolver resolver, AssemblyNameReference assemblyName) - { - try - { - return resolver.Resolve(assemblyName, new ReaderParameters { AssemblyResolver = resolver, ApplyWindowsRuntimeProjections = true }); - } - catch (AssemblyResolutionException e) - { - // DefaultAssemblyResolver doesn't handle windows runtime references correctly. But that is okay, as they cannot derive from managed types anyway - if (e.AssemblyReference.IsWindowsRuntime) - return null; - - throw; - } - } - - class AssemblyDefinitionComparer : IEqualityComparer - { - public bool Equals(AssemblyDefinition x, AssemblyDefinition y) - { - return x.FullName == y.FullName; - } - - public int GetHashCode(AssemblyDefinition obj) - { - return obj.FullName.GetHashCode(); - } - } - - private static void CollectBlackListTypes(HashSet typesToPreserve, IList types, List baseTypes) - { - if (types == null) - return; - - foreach (TypeDefinition typ in types) - { - if (typ == null) - continue; - - foreach (string baseType in baseTypes) - { - if (!DoesTypeEnheritFrom(typ, baseType)) - continue; - typesToPreserve.Add(typ); - break; - } - CollectBlackListTypes(typesToPreserve, typ.NestedTypes, baseTypes); - } - } - - private static bool DoesTypeEnheritFrom(TypeReference type, string typeName) - { - while (type != null) - { - if (type.FullName == typeName) - return true; - - // If we can't resolve this might lead to trouble later. However, let's wait until it - // matters and throw there (maybe the error message will be better). Here we can just - // assume the type does not inherit from the given base class. - var typeDefinition = type.Resolve(); - if (typeDefinition == null) - return false; - - type = typeDefinition.BaseType; - } - return false; - } - } -} diff --git a/Editor/Mono/BuildPipeline/MonoCrossCompile.cs b/Editor/Mono/BuildPipeline/MonoCrossCompile.cs deleted file mode 100644 index da5a8a5144..0000000000 --- a/Editor/Mono/BuildPipeline/MonoCrossCompile.cs +++ /dev/null @@ -1,335 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditor.Scripting.ScriptCompilation; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using UnityEditorInternal; -using System; -using System.Threading; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Text.RegularExpressions; -using Mono.Cecil; - -namespace UnityEditor -{ - [Flags] - internal enum CrossCompileOptions - { - Dynamic = 0, - FastICall = 1 << 0, - Static = 1 << 1, - Debugging = 1 << 2, - ExplicitNullChecks = 1 << 3, - LoadSymbols = 1 << 4 - } - - internal class MonoCrossCompile - { - static public string ArtifactsPath = null; - - private class JobCompileAOT - { - public JobCompileAOT(BuildTarget target, string crossCompilerAbsolutePath, - string assembliesAbsoluteDirectory, CrossCompileOptions crossCompileOptions, - string input, string output, string additionalOptions) - { - m_target = target; - m_crossCompilerAbsolutePath = crossCompilerAbsolutePath; - m_assembliesAbsoluteDirectory = assembliesAbsoluteDirectory; - m_crossCompileOptions = crossCompileOptions; - m_input = input; - m_output = output; - m_additionalOptions = additionalOptions; - } - - public void ThreadPoolCallback(System.Object threadContext) - { - try - { - MonoCrossCompile.CrossCompileAOT(m_target, m_crossCompilerAbsolutePath, - m_assembliesAbsoluteDirectory, m_crossCompileOptions, - m_input, m_output, m_additionalOptions); - } - catch (Exception ex) - { - m_Exception = ex; - } - m_doneEvent.Set(); - } - - private BuildTarget m_target; - private string m_crossCompilerAbsolutePath; - private string m_assembliesAbsoluteDirectory; - private CrossCompileOptions m_crossCompileOptions; - public string m_input; - public string m_output; - public string m_additionalOptions; - - public ManualResetEvent m_doneEvent = new ManualResetEvent(false); - public Exception m_Exception = null; - } - - static public void CrossCompileAOTDirectory(BuildTarget buildTarget, CrossCompileOptions crossCompileOptions, - string sourceAssembliesFolder, string targetCrossCompiledASMFolder, - string additionalOptions) - { - CrossCompileAOTDirectory(buildTarget, crossCompileOptions, sourceAssembliesFolder, targetCrossCompiledASMFolder, "", additionalOptions); - } - - static public void CrossCompileAOTDirectory(BuildTarget buildTarget, CrossCompileOptions crossCompileOptions, - string sourceAssembliesFolder, string targetCrossCompiledASMFolder, - string pathExtension, string additionalOptions) - { - string crossCompilerPath = BuildPipeline.GetBuildToolsDirectory(buildTarget); - if (Application.platform == RuntimePlatform.OSXEditor) - crossCompilerPath = Path.Combine(Path.Combine(crossCompilerPath, pathExtension), "mono-xcompiler"); - else - crossCompilerPath = Path.Combine(Path.Combine(crossCompilerPath, pathExtension), "mono-xcompiler.exe"); - - sourceAssembliesFolder = Path.Combine(Directory.GetCurrentDirectory(), sourceAssembliesFolder); - targetCrossCompiledASMFolder = Path.Combine(Directory.GetCurrentDirectory(), targetCrossCompiledASMFolder); - - - // Generate AOT Files (using OSX cross-compiler) - foreach (string fileName in Directory.GetFiles(sourceAssembliesFolder)) - { - if (Path.GetExtension(fileName) != ".dll") - continue; - - // Cross AOT compile - string inputPath = Path.GetFileName(fileName); - string outputPath = Path.Combine(targetCrossCompiledASMFolder, inputPath + ".s"); - - if (EditorUtility.DisplayCancelableProgressBar("Building Player", "AOT cross compile " + inputPath, 0.95F)) - throw new OperationCanceledException(); - - CrossCompileAOT(buildTarget, crossCompilerPath, sourceAssembliesFolder, - crossCompileOptions, inputPath, outputPath, additionalOptions); - } - } - - static public bool CrossCompileAOTDirectoryParallel(BuildTarget buildTarget, CrossCompileOptions crossCompileOptions, - string sourceAssembliesFolder, string targetCrossCompiledASMFolder, - string additionalOptions) - { - return CrossCompileAOTDirectoryParallel(buildTarget, crossCompileOptions, sourceAssembliesFolder, - targetCrossCompiledASMFolder, "", additionalOptions); - } - - static public bool CrossCompileAOTDirectoryParallel(BuildTarget buildTarget, CrossCompileOptions crossCompileOptions, - string sourceAssembliesFolder, string targetCrossCompiledASMFolder, - string pathExtension, string additionalOptions) - { - string crossCompilerPath = BuildPipeline.GetBuildToolsDirectory(buildTarget); - if (Application.platform == RuntimePlatform.OSXEditor) - crossCompilerPath = Path.Combine(Path.Combine(crossCompilerPath, pathExtension), "mono-xcompiler"); - else - crossCompilerPath = Path.Combine(Path.Combine(crossCompilerPath, pathExtension), "mono-xcompiler.exe"); - - return CrossCompileAOTDirectoryParallel( - crossCompilerPath, buildTarget, crossCompileOptions, - sourceAssembliesFolder, targetCrossCompiledASMFolder, additionalOptions); - } - - static private bool WaitForBuildOfFile(List events, ref long timeout) - { - long timeMs1 = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - int finished = WaitHandle.WaitAny(events.ToArray(), (Int32)timeout); - long timeMs2 = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - - if (finished == WaitHandle.WaitTimeout) - return false; - - events.RemoveAt(finished); - timeout -= (timeMs2 - timeMs1); - if (timeout < 0) - timeout = 0; - return true; - } - - static public void DisplayAOTProgressBar(int totalFiles, int filesFinished) - { - string msg = String.Format(@"AOT cross compile ({0}/{1})", - (filesFinished + 1).ToString(), totalFiles.ToString()); - EditorUtility.DisplayProgressBar("Building Player", msg, 0.95F); - } - - static public bool CrossCompileAOTDirectoryParallel(string crossCompilerPath, BuildTarget buildTarget, CrossCompileOptions crossCompileOptions, - string sourceAssembliesFolder, string targetCrossCompiledASMFolder, string additionalOptions) - { - sourceAssembliesFolder = Path.Combine(Directory.GetCurrentDirectory(), sourceAssembliesFolder); - targetCrossCompiledASMFolder = Path.Combine(Directory.GetCurrentDirectory(), targetCrossCompiledASMFolder); - - - // Generate AOT Files (using OSX cross-compiler) - int workerThreads = 1; - int completionPortThreads = 1; - ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads); - - List jobList = new List(); - List eventList = new List(); - - - bool success = true; - - var dllList = new List(Directory.GetFiles(sourceAssembliesFolder) - .Where(path => Path.GetExtension(path) == ".dll")); - - int numFiles = dllList.Count; - int numFinished = 0; - DisplayAOTProgressBar(numFiles, numFinished); - - long timeout = System.Math.Min(30 * 1000 * 60, (numFiles + 3) * 1000 * 30); // 30 minute limit in case of FOOBARs, 30 seconds for each file - - foreach (string fileName in dllList) - { - // Cross AOT compile - string inputPath = Path.GetFileName(fileName); - string outputPath = Path.Combine(targetCrossCompiledASMFolder, inputPath + ".s"); - - JobCompileAOT job = new JobCompileAOT(buildTarget, crossCompilerPath, sourceAssembliesFolder, - crossCompileOptions, inputPath, outputPath, - additionalOptions); - jobList.Add(job); - eventList.Add(job.m_doneEvent); - ThreadPool.QueueUserWorkItem(job.ThreadPoolCallback); - - if (eventList.Count >= Environment.ProcessorCount) - { - success = WaitForBuildOfFile(eventList, ref timeout); - DisplayAOTProgressBar(numFiles, numFinished); - numFinished += 1; - if (!success) - break; - } - } - - while (eventList.Count > 0) - { - success = WaitForBuildOfFile(eventList, ref timeout); - DisplayAOTProgressBar(numFiles, numFinished); - numFinished += 1; - if (!success) - break; - } - - foreach (var job in jobList) - { - if (job.m_Exception != null) - { - Debug.LogErrorFormat("Cross compilation job {0} failed.\n{1}", job.m_input, job.m_Exception); - success = false; - } - } - return success; - } - - static bool IsDebugableAssembly(string fname) - { - return EditorCompilationInterface.Instance.IsRuntimeScriptAssembly(fname); - } - - static void CrossCompileAOT(BuildTarget target, string crossCompilerAbsolutePath, string assembliesAbsoluteDirectory, CrossCompileOptions crossCompileOptions, string input, string output, string additionalOptions) - { - string arguments = ""; - - // We don't want debugging for non-script assemblies (anyway source code is not available for the end users) - if (!IsDebugableAssembly(input)) - { - crossCompileOptions &= ~CrossCompileOptions.Debugging; - crossCompileOptions &= ~CrossCompileOptions.LoadSymbols; - } - - bool debugging = ((crossCompileOptions & CrossCompileOptions.Debugging) != 0); - bool loadSymbols = ((crossCompileOptions & CrossCompileOptions.LoadSymbols) != 0); - bool initDebugging = (debugging || loadSymbols); - if (initDebugging) - arguments += "--debug "; - - if (debugging) - { - // Do not put locals into registers when debugging - arguments += "--optimize=-linears "; - } - - arguments += "--aot=full,asmonly,"; - - if (initDebugging) - arguments += "write-symbols,"; - - if ((crossCompileOptions & CrossCompileOptions.Debugging) != 0) - arguments += "soft-debug,"; - else if (!initDebugging) - arguments += "nodebug,"; - - if (target != BuildTarget.iOS) - { - //arguments += "fail-if-methods-are-skipped,"; - arguments += "print-skipped,"; - } - - if (additionalOptions != null & additionalOptions.Trim().Length > 0) - arguments += additionalOptions.Trim() + ","; - - string outputFileName = Path.GetFileName(output); - // Mono outfile parameter doesnt take absolute paths, - // So we temporarily write into the assembliesAbsoluteDirectory and move it away afterwards - string outputTempPath = Path.Combine(assembliesAbsoluteDirectory, outputFileName); - if ((crossCompileOptions & CrossCompileOptions.FastICall) != 0) - arguments += "ficall,"; - if ((crossCompileOptions & CrossCompileOptions.Static) != 0) - arguments += "static,"; - arguments += "outfile=\"" + outputFileName + "\" \"" + input + "\" "; - - - System.Diagnostics.Process process = new System.Diagnostics.Process(); - process.StartInfo.FileName = crossCompilerAbsolutePath; - process.StartInfo.Arguments = arguments; - process.StartInfo.EnvironmentVariables["MONO_PATH"] = assembliesAbsoluteDirectory; - process.StartInfo.EnvironmentVariables["GAC_PATH"] = assembliesAbsoluteDirectory; - process.StartInfo.EnvironmentVariables["GC_DONT_GC"] = "yes please"; - if ((crossCompileOptions & CrossCompileOptions.ExplicitNullChecks) != 0) - process.StartInfo.EnvironmentVariables["MONO_DEBUG"] = "explicit-null-checks"; - process.StartInfo.UseShellExecute = false; - process.StartInfo.CreateNoWindow = true; - process.StartInfo.RedirectStandardOutput = true; - - - // todo: move this out of this file ... it needs to be initialised in the per-platform extension - // ArtifactsPath = Environment.ExpandEnvironmentVariables("%tmp%\\UnityPSVitaArtifacts\\"); - - if (ArtifactsPath != null) - { - if (!Directory.Exists(ArtifactsPath)) Directory.CreateDirectory(ArtifactsPath); - File.AppendAllText(ArtifactsPath + "output.txt", process.StartInfo.FileName + "\n"); - File.AppendAllText(ArtifactsPath + "output.txt", process.StartInfo.Arguments + "\n"); - File.AppendAllText(ArtifactsPath + "output.txt", assembliesAbsoluteDirectory + "\n"); - File.AppendAllText(ArtifactsPath + "output.txt", outputTempPath + "\n"); - File.AppendAllText(ArtifactsPath + "output.txt", input + "\n"); - File.AppendAllText(ArtifactsPath + "houtput.txt", outputFileName + "\n\n"); - File.Copy(assembliesAbsoluteDirectory + "\\" + input, ArtifactsPath + "\\" + input, true); - } - - process.StartInfo.WorkingDirectory = assembliesAbsoluteDirectory; - MonoProcessUtility.RunMonoProcess(process, "AOT cross compiler", outputTempPath); - // For some reason we can't pass a full path to outfile, so we move the .s file after compilation instead - File.Move(outputTempPath, output); - - //handle .def files if present for dlls - if ((crossCompileOptions & CrossCompileOptions.Static) == 0) - { - string defOutputTempPath = Path.Combine(assembliesAbsoluteDirectory, outputFileName + ".def"); - if (File.Exists(defOutputTempPath)) - File.Move(defOutputTempPath, output + ".def"); - } - } - } -} diff --git a/Editor/Mono/BuildPipeline/MonoInternalCallGenerator.cs b/Editor/Mono/BuildPipeline/MonoInternalCallGenerator.cs deleted file mode 100644 index 1fc2409f29..0000000000 --- a/Editor/Mono/BuildPipeline/MonoInternalCallGenerator.cs +++ /dev/null @@ -1,390 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditor.Utils; -using UnityEditorInternal; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System; -using System.Linq; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Text.RegularExpressions; -using Mono.Cecil; - -namespace UnityEditor -{ - internal class MonoAOTRegistration - { - static void ExtractNativeMethodsFromTypes(ICollection types, ArrayList res) - { - foreach (TypeDefinition typ in types) - { - foreach (MethodDefinition method in typ.Methods) - { - if (method.IsStatic && method.IsPInvokeImpl && method.PInvokeInfo.Module.Name.Equals("__Internal")) - { - if (res.Contains(method.Name)) - throw new SystemException("Duplicate native method found : " + method.Name + ". Please check your source carefully."); - - res.Add(method.Name); - } - } - - if (typ.HasNestedTypes) - ExtractNativeMethodsFromTypes(typ.NestedTypes, res); - } - } - - // Builds list of extern methods that are marked with DllImport("__Internal") attribute - // @TODO: This needs to be rewritten using cecil - static ArrayList BuildNativeMethodList(AssemblyDefinition[] assemblies) - { - ArrayList res = new ArrayList(); - - foreach (AssemblyDefinition ass in assemblies) - { - //string assname = ass.Name.Name; - if (!"System".Equals(ass.Name.Name)) - { - ExtractNativeMethodsFromTypes(ass.MainModule.Types, res); - } - } - - return res; - } - - static public HashSet BuildReferencedTypeList(AssemblyDefinition[] assemblies) - { - HashSet res = new HashSet(); - - foreach (AssemblyDefinition ass in assemblies) - { - //string assname = ass.Name.Name; - if (!ass.Name.Name.StartsWith("System") && !ass.Name.Name.Equals("UnityEngine")) - { - foreach (TypeReference typ in ass.MainModule.GetTypeReferences()) - { - res.Add(typ.FullName); - } - } - } - - return res; - } - - static public void WriteCPlusPlusFileForStaticAOTModuleRegistration(BuildTarget buildTarget, string file, - CrossCompileOptions crossCompileOptions, - bool advancedLic, string targetDevice, bool stripping, RuntimeClassRegistry usedClassRegistry, - AssemblyReferenceChecker checker, string stagingAreaDataManaged) - { - WriteCPlusPlusFileForStaticAOTModuleRegistration(buildTarget, file, crossCompileOptions, advancedLic, targetDevice, stripping, usedClassRegistry, checker, stagingAreaDataManaged, null); - } - - static public void WriteCPlusPlusFileForStaticAOTModuleRegistration(BuildTarget buildTarget, string file, - CrossCompileOptions crossCompileOptions, - bool advancedLic, string targetDevice, bool stripping, RuntimeClassRegistry usedClassRegistry, - AssemblyReferenceChecker checker, string stagingAreaDataManaged, IIl2CppPlatformProvider platformProvider) - { - // generate the Interal Call Summary file - var icallSummaryPath = Path.Combine(stagingAreaDataManaged, "ICallSummary.txt"); - var dlls = Directory.GetFiles(stagingAreaDataManaged, "UnityEngine.*Module.dll").Concat(new[] {Path.Combine(stagingAreaDataManaged, "UnityEngine.dll")}); - var exe = Path.Combine(MonoInstallationFinder.GetFrameWorksFolder(), "Tools/InternalCallRegistrationWriter/InternalCallRegistrationWriter.exe"); - var args = string.Format("-assembly=\"{0}\" -summary=\"{1}\"", - dlls.Aggregate((dllArg, next) => dllArg + ";" + next), icallSummaryPath - ); - Runner.RunManagedProgram(exe, args); - - HashSet nativeClasses; - HashSet nativeModules; - CodeStrippingUtils.GenerateDependencies(Path.GetDirectoryName(stagingAreaDataManaged), icallSummaryPath, usedClassRegistry, stripping, out nativeClasses, out nativeModules, platformProvider); - - using (TextWriter w = new StreamWriter(file)) - { - string[] fileNames = checker.GetAssemblyFileNames(); - AssemblyDefinition[] assemblies = checker.GetAssemblyDefinitions(); - - bool fastICall = (crossCompileOptions & CrossCompileOptions.FastICall) != 0; - - ArrayList nativeMethods = BuildNativeMethodList(assemblies); - - if (buildTarget == BuildTarget.iOS) - { - w.WriteLine("#include \"RegisterMonoModules.h\""); - w.WriteLine("#include "); - } - - w.WriteLine(""); - w.WriteLine("#if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR"); - w.WriteLine(" #define DECL_USER_FUNC(f) void f() __attribute__((weak_import))"); - w.WriteLine(" #define REGISTER_USER_FUNC(f)\\"); - w.WriteLine(" do {\\"); - w.WriteLine(" if(f != NULL)\\"); - w.WriteLine(" mono_dl_register_symbol(#f, (void*)f);\\"); - w.WriteLine(" else\\"); - w.WriteLine(" ::printf_console(\"Symbol \'%s\' not found. Maybe missing implementation for Simulator?\\n\", #f);\\"); - w.WriteLine(" }while(0)"); - w.WriteLine("#else"); - w.WriteLine(" #define DECL_USER_FUNC(f) void f() "); - w.WriteLine(" #if !defined(__arm64__)"); - w.WriteLine(" #define REGISTER_USER_FUNC(f) mono_dl_register_symbol(#f, (void*)&f)"); - w.WriteLine(" #else"); - w.WriteLine(" #define REGISTER_USER_FUNC(f)"); - w.WriteLine(" #endif"); - w.WriteLine("#endif"); - w.WriteLine("extern \"C\"\n{"); - - w.WriteLine(" typedef void* gpointer;"); - w.WriteLine(" typedef int gboolean;"); - - if (buildTarget == BuildTarget.iOS) - { - w.WriteLine(" const char* UnityIPhoneRuntimeVersion = \"{0}\";", Application.unityVersion); - w.WriteLine(" void mono_dl_register_symbol (const char* name, void *addr);"); - - w.WriteLine("#if !defined(__arm64__)"); - w.WriteLine(" extern int mono_ficall_flag;"); - w.WriteLine("#endif"); - } - - w.WriteLine(" void mono_aot_register_module(gpointer *aot_info);"); - - w.WriteLine("#if __ORBIS__ || SN_TARGET_PSP2"); - w.WriteLine("#define DLL_EXPORT __declspec(dllexport)"); // ps4 and psp2 need dllexport. - w.WriteLine("#else"); - w.WriteLine("#define DLL_EXPORT"); - w.WriteLine("#endif"); - - w.WriteLine("#if !(TARGET_IPHONE_SIMULATOR)"); - w.WriteLine(" extern gboolean mono_aot_only;"); - - for (int q = 0; q < fileNames.Length; ++q) - { - string fileName = fileNames[q]; - string assemblyName = assemblies[q].Name.Name; - assemblyName = assemblyName.Replace(".", "_"); - assemblyName = assemblyName.Replace("-", "_"); - assemblyName = assemblyName.Replace(" ", "_"); - - w.WriteLine(" extern gpointer* mono_aot_module_{0}_info; // {1}", assemblyName, fileName); - } - w.WriteLine("#endif // !(TARGET_IPHONE_SIMULATOR)"); - foreach (string nmethod in nativeMethods) - { - w.WriteLine(" DECL_USER_FUNC({0});", nmethod); - } - w.WriteLine("}"); - - w.WriteLine("DLL_EXPORT void RegisterMonoModules()"); - w.WriteLine("{"); - - w.WriteLine("#if !(TARGET_IPHONE_SIMULATOR) && !defined(__arm64__)"); - w.WriteLine(" mono_aot_only = true;"); - - if (buildTarget == BuildTarget.iOS) - { - w.WriteLine(" mono_ficall_flag = {0};", fastICall ? "true" : "false"); - } - - foreach (AssemblyDefinition definition in assemblies) - { - string assemblyName = definition.Name.Name; - assemblyName = assemblyName.Replace(".", "_"); - assemblyName = assemblyName.Replace("-", "_"); - assemblyName = assemblyName.Replace(" ", "_"); - w.WriteLine(" mono_aot_register_module(mono_aot_module_{0}_info);", assemblyName); - } - - w.WriteLine("#endif // !(TARGET_IPHONE_SIMULATOR) && !defined(__arm64__)"); - w.WriteLine(""); - - if (buildTarget == BuildTarget.iOS) - { - foreach (string nmethod in nativeMethods) - { - w.WriteLine(" REGISTER_USER_FUNC({0});", nmethod); - } - } - w.WriteLine("}"); - w.WriteLine(""); - - - if (buildTarget == BuildTarget.iOS) - { - var inputAssemblies = new List(); - - for (int i = 0; i < assemblies.Length; i++) - { - if (AssemblyHelper.IsUnityEngineModule(assemblies[i])) - inputAssemblies.Add(assemblies[i]); - } - - GenerateRegisterInternalCalls(inputAssemblies.ToArray(), w); - - GenerateRegisterModules(nativeClasses, nativeModules, w, stripping); - - if (stripping && usedClassRegistry != null) - GenerateRegisterClassesForStripping(nativeClasses, w); - else - GenerateRegisterClasses(nativeClasses, w); - } - - w.Close(); - } - } - - public static void GenerateRegisterModules(HashSet nativeClasses, HashSet nativeModules, TextWriter output, bool strippingEnabled) - { - output.WriteLine("void InvokeRegisterStaticallyLinkedModuleClasses()"); - output.WriteLine("{"); - if (nativeClasses == null) - { - output.WriteLine("\tvoid RegisterStaticallyLinkedModuleClasses();"); - output.WriteLine("\tRegisterStaticallyLinkedModuleClasses();"); - } - else - { - output.WriteLine("\t// Do nothing (we're in stripping mode)"); - } - output.WriteLine("}"); - output.WriteLine(); - - output.WriteLine("void RegisterStaticallyLinkedModulesGranular()"); - output.WriteLine("{"); - foreach (string module in nativeModules) - { - output.WriteLine("\tvoid RegisterModule_" + module + "();"); - output.WriteLine("\tRegisterModule_" + module + "();"); - output.WriteLine(); - } - output.WriteLine("}\n"); - } - - public static void GenerateRegisterClassesForStripping(HashSet nativeClassesAndBaseClasses, TextWriter output) - { - // Forward declare template function - output.WriteLine("template void RegisterClass(const char*);"); - output.WriteLine("template void RegisterStrippedType(int, const char*, const char*);"); - output.WriteLine(); - - // Forward declaration - foreach (var type in UnityType.GetTypes()) - { - if (type.baseClass == null || type.isEditorOnly) - continue; - - if (!type.hasNativeNamespace) - { - output.WriteLine("class {0};", type.name); - } - else - { - output.WriteLine("namespace {0} {{ class {1}; }}", type.nativeNamespace, type.name); - } - - output.WriteLine(); - } - - output.Write("void RegisterAllClasses() \n{\n"); - output.WriteLine("\tvoid RegisterBuiltinTypes();"); - output.WriteLine("\tRegisterBuiltinTypes();"); - - // Write non stripped class registration - output.WriteLine("\t// {0} Non stripped classes\n", nativeClassesAndBaseClasses.Count); - int count = 1; - foreach (var type in UnityType.GetTypes()) - { - if (type.baseClass == null || type.isEditorOnly || !nativeClassesAndBaseClasses.Contains(type)) - continue; - - output.WriteLine("\t// {0}. {1}", count++, type.qualifiedName); - output.WriteLine("\tRegisterClass<{0}>(\"{1}\");\n", type.qualifiedName, type.module); - } - - output.WriteLine(); - - // Write stripped class registration - - // TODO (ulfj ) 2016-08-15 : Right now we cannot deal with types that are compiled into the editor - // but not the player due to other defines than UNITY_EDITOR in them module definition file - // (for example WorldAnchor only being there if ENABLE_HOLOLENS_MODULE_API). Doing this would - // require either some non trivial changes to the module registration macros or a way for these - // conditionals to be included in the RTTI so we can emit them when generating the code, so we - // disabling the registration of stripped classes for now and will get back to this when we have - // landed the remaining changes to the type system. - - //output.WriteLine("\t// Stripped classes"); - //foreach (var type in UnityType.GetTypes()) - //{ - // if (type.baseClass == null || type.isEditorOnly || nativeClassesAndBaseClasses.Contains(type)) - // continue; - - // output.WriteLine("\tRegisterStrippedType<{0}>();", type.qualifiedName); - //} - - output.Write("\n}\n"); - } - - public static void GenerateRegisterClasses(HashSet allClasses, TextWriter output) - { - output.WriteLine("void RegisterAllClasses() \n{"); - output.WriteLine("\tvoid RegisterAllClassesGranular();"); - output.WriteLine("\tRegisterAllClassesGranular();"); - output.WriteLine("}"); - } - - // Generate a cpp file that registers all exposed internal calls - // for example: Register_UnityEngine_AnimationClip_get_length - // - public static void GenerateRegisterInternalCalls(AssemblyDefinition[] assemblies, TextWriter output) - { - output.Write("void RegisterAllStrippedInternalCalls ()\n{\n"); - - foreach (AssemblyDefinition definition in assemblies) - GenerateRegisterInternalCallsForTypes(definition.MainModule.Types, output); - - output.Write("}\n\n"); - } - - private static void GenerateRegisterInternalCallsForTypes(IEnumerable types, TextWriter output) - { - foreach (TypeDefinition typeDefinition in types) - { - foreach (MethodDefinition method in typeDefinition.Methods) - GenerateInternalCallMethod(typeDefinition, method, output); - - GenerateRegisterInternalCallsForTypes(typeDefinition.NestedTypes, output); - } - } - - static void GenerateInternalCallMethod(TypeDefinition typeDefinition, MethodDefinition method, TextWriter output) - { - if (!method.IsInternalCall) - return; - - string registerName = typeDefinition.FullName + "_" + method.Name; - registerName = registerName.Replace('/', '_'); - registerName = registerName.Replace('.', '_'); - - if (registerName.Contains("UnityEngine_Serialization")) - return; - - output.WriteLine("\tvoid Register_{0} ();", registerName); - output.WriteLine("\tRegister_{0} ();", registerName); - } - - /* - [MenuItem("Test/GenerateRegisterInternalCalls")] - public static void GenerateRegisterInternalCallsTest() - { - AssemblyDefinition[] definition = { AssemblyFactory.GetAssembly("/Users/joe/Sources/unity-trunk/build/iPhonePlayer/Managed/UnityEngine.dll")}; - GenerateRegisterInternalCalls(definition, new StreamWriter("/test.txt")); - } - */ - } -} diff --git a/Editor/Mono/BuildPipeline/PostProcessStandalonePlayer.cs b/Editor/Mono/BuildPipeline/PostProcessStandalonePlayer.cs deleted file mode 100644 index 14f87b7be7..0000000000 --- a/Editor/Mono/BuildPipeline/PostProcessStandalonePlayer.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Text; -using UnityEditor; -using UnityEditor.Modules; -using UnityEngine; - -internal class PostProcessStandalonePlayer -{ -} diff --git a/Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs b/Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs deleted file mode 100644 index f718c351eb..0000000000 --- a/Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs +++ /dev/null @@ -1,334 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Diagnostics; -using System.Linq; -using UnityEditor.Utils; -using UnityEngine; -using System.Collections.Generic; -using System.IO; -using System.Xml.XPath; -using UnityEditorInternal; -using System; -using System.Text.RegularExpressions; -using Mono.Cecil; -using UnityEditor.Build.Reporting; -using UnityEditor.Modules; -using UnityEditor.DeploymentTargets; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - class MissingBuildPropertiesException : Exception {} - - // Holds data needed to verify a target against a set of requirements - internal abstract class DeploymentTargetRequirements - { - } - - // Holds data needed for operating (launching etc) on a build - internal abstract class BuildProperties : ScriptableObject - { - public static BuildProperties GetFromBuildReport(BuildReport report) - { - var allData = report.GetAppendices(); - if (allData.Length > 0) - return allData[0]; - - throw new MissingBuildPropertiesException(); - } - - public abstract DeploymentTargetRequirements GetTargetRequirements(); - } - - internal static class PostprocessBuildPlayer - { - internal const string StreamingAssets = "Assets/StreamingAssets"; - - // Seems to be used only by PlatformDependent\AndroidPlayer\Editor\Managed\PostProcessAndroidPlayer.cs - internal static bool InstallPluginsByExtension(string pluginSourceFolder, string extension, string debugExtension, string destPluginFolder, bool copyDirectories) - { - bool installedPlugins = false; - - if (!Directory.Exists(pluginSourceFolder)) - return installedPlugins; - - string[] contents = Directory.GetFileSystemEntries(pluginSourceFolder); - foreach (string path in contents) - { - string fileName = Path.GetFileName(path); - string fileExtension = Path.GetExtension(path); - - bool filenameMatch = fileExtension.Equals(extension, StringComparison.OrdinalIgnoreCase) || - fileName.Equals(extension, StringComparison.OrdinalIgnoreCase); - bool debugMatch = debugExtension != null && debugExtension.Length != 0 && - (fileExtension.Equals(debugExtension, StringComparison.OrdinalIgnoreCase) || - fileName.Equals(debugExtension, StringComparison.OrdinalIgnoreCase)); - - // Do we really need to check the file name here? - if (filenameMatch || debugMatch) - { - if (!Directory.Exists(destPluginFolder)) - Directory.CreateDirectory(destPluginFolder); - - string targetPath = Path.Combine(destPluginFolder, fileName); - if (copyDirectories) - FileUtil.CopyDirectoryRecursive(path, targetPath); - else if (!Directory.Exists(path)) - FileUtil.UnityFileCopy(path, targetPath); - - installedPlugins = true; - } - } - return installedPlugins; - } - - internal static void InstallStreamingAssets(string stagingAreaDataPath) - { - InstallStreamingAssets(stagingAreaDataPath, null); - } - - internal static void InstallStreamingAssets(string stagingAreaDataPath, BuildReport report) - { - if (Directory.Exists(StreamingAssets)) - { - var outputPath = Path.Combine(stagingAreaDataPath, "StreamingAssets"); - FileUtil.CopyDirectoryRecursiveForPostprocess(StreamingAssets, outputPath, true); - if (report != null) - { - report.RecordFilesAddedRecursive(outputPath, CommonRoles.streamingAsset); - } - } - } - - static public string PrepareForBuild(BuildOptions options, BuildTargetGroup targetGroup, BuildTarget target) - { - var postprocessor = ModuleManager.GetBuildPostProcessor(targetGroup, target); - if (postprocessor == null) - return null; - return postprocessor.PrepareForBuild(options, target); - } - - static public bool SupportsScriptsOnlyBuild(BuildTargetGroup targetGroup, BuildTarget target) - { - IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(targetGroup, target); - if (postprocessor != null) - { - return postprocessor.SupportsScriptsOnlyBuild(); - } - - return false; - } - - static public string GetExtensionForBuildTarget(BuildTargetGroup targetGroup, BuildTarget target, BuildOptions options) - { - IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(targetGroup, target); - if (postprocessor == null) - return string.Empty; - return postprocessor.GetExtension(target, options); - } - - static public bool SupportsInstallInBuildFolder(BuildTargetGroup targetGroup, BuildTarget target) - { - IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(targetGroup, target); - if (postprocessor != null) - { - return postprocessor.SupportsInstallInBuildFolder(); - } - - switch (target) - { - case BuildTarget.PSP2: - case BuildTarget.Android: - case BuildTarget.WSAPlayer: - return true; - default: - return false; - } - } - - static public bool SupportsLz4Compression(BuildTargetGroup targetGroup, BuildTarget target) - { - IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(targetGroup, target); - if (postprocessor != null) - return postprocessor.SupportsLz4Compression(); - return false; - } - - private class NoTargetsFoundException : Exception - { - public NoTargetsFoundException() : base() {} - public NoTargetsFoundException(string message) : base(message) {} - } - - static public void Launch(BuildTargetGroup targetGroup, BuildTarget buildTarget, string path, string productName, BuildOptions options, BuildReport buildReport) - { - IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(targetGroup, buildTarget); - if (postprocessor != null) - { - BuildLaunchPlayerArgs args; - args.target = buildTarget; - args.playerPackage = BuildPipeline.GetPlaybackEngineDirectory(buildTarget, options); - args.installPath = path; - args.productName = productName; - args.options = options; - args.report = buildReport; - - postprocessor.LaunchPlayer(args); - } - else - { - throw new UnityException( - $"Launching for target group {targetGroup}, build target {buildTarget} is not supported: There is no build post-processor available."); - } - } - - static public void LaunchOnTargets(BuildTargetGroup targetGroup, BuildTarget buildTarget, Build.Reporting.BuildReport buildReport, List launchTargets) - { - try - { - // Early out so as not to show/update progressbars unnecessarily - if (buildReport == null || !DeploymentTargetManager.IsExtensionSupported(targetGroup, buildReport.summary.platform)) - throw new System.NotSupportedException(); - - ProgressHandler progressHandler = new ProgressHandler("Deploying Player", - delegate(string title, string message, float globalProgress) - { - if (EditorUtility.DisplayCancelableProgressBar(title, message, globalProgress)) - throw new DeploymentOperationAbortedException(); - }, 0.1f); // BuildPlayer.cpp starts off at 0.1f for some reason - - var taskManager = new ProgressTaskManager(progressHandler); - - // Launch on all selected targets - taskManager.AddTask(() => - { - int successfulLaunches = 0; - var exceptions = new List(); - foreach (var target in launchTargets) - { - try - { - DeploymentTargetManager.LaunchBuildOnTarget(targetGroup, buildReport, target, taskManager.SpawnProgressHandlerFromCurrentTask()); - successfulLaunches++; - } - catch (DeploymentOperationFailedException e) - { - exceptions.Add(e); - } - } - - foreach (var e in exceptions) - UnityEngine.Debug.LogException(e); - - if (successfulLaunches == 0) - { - // TODO: Maybe more specifically no compatible targets? - throw new NoTargetsFoundException("Could not launch build"); - } - }); - - taskManager.Run(); - } - catch (DeploymentOperationFailedException e) - { - UnityEngine.Debug.LogException(e); - EditorUtility.DisplayDialog(e.title, e.Message, "Ok"); - } - catch (DeploymentOperationAbortedException) - { - System.Console.WriteLine("Deployment aborted"); - } - catch (NoTargetsFoundException) - { - throw new UnityException(string.Format("Could not find any valid targets to launch on for {0}", buildTarget)); - } - } - - [RequiredByNativeCode] - static public void UpdateBootConfig(BuildTargetGroup targetGroup, BuildTarget target, BootConfigData config, BuildOptions options) - { - IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(targetGroup, target); - if (postprocessor != null) - postprocessor.UpdateBootConfig(target, config, options); - } - - static public void Postprocess(BuildTargetGroup targetGroup, BuildTarget target, string installPath, string companyName, string productName, - int width, int height, BuildOptions options, - RuntimeClassRegistry usedClassRegistry, BuildReport report) - { - string stagingArea = "Temp/StagingArea"; - string stagingAreaData = "Temp/StagingArea/Data"; - string stagingAreaDataManaged = "Temp/StagingArea/Data/Managed"; - string playerPackage = BuildPipeline.GetPlaybackEngineDirectory(target, options); - - // Disallow providing an empty string as the installPath - bool willInstallInBuildFolder = (options & BuildOptions.InstallInBuildFolder) != 0 && SupportsInstallInBuildFolder(targetGroup, target); - if (installPath == String.Empty && !willInstallInBuildFolder) - throw new Exception(installPath + " must not be an empty string"); - - IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(targetGroup, target); - if (postprocessor != null) - { - BuildPostProcessArgs args; - args.target = target; - args.stagingAreaData = stagingAreaData; - args.stagingArea = stagingArea; - args.stagingAreaDataManaged = stagingAreaDataManaged; - args.playerPackage = playerPackage; - args.installPath = installPath; - args.companyName = companyName; - args.productName = productName; - args.productGUID = PlayerSettings.productGUID; - args.options = options; - args.usedClassRegistry = usedClassRegistry; - args.report = report; - - BuildProperties props; - postprocessor.PostProcess(args, out props); - report.AddAppendix(props); - - return; - } - - // If postprocessor is not provided, build target is not supported - throw new UnityException(string.Format("Build target '{0}' not supported", target)); - } - - internal static string ExecuteSystemProcess(string command, string args, string workingdir) - { - var psi = new ProcessStartInfo() - { - FileName = command, - Arguments = args, - WorkingDirectory = workingdir, - CreateNoWindow = true - }; - var p = new Program(psi); - p.Start(); - while (!p.WaitForExit(100)) - ; - - string output = p.GetStandardOutputAsString(); - p.Dispose(); - return output; - } - - public static string subDir32Bit - { - get - { - return "x86"; - } - } - - public static string subDir64Bit - { - get - { - return "x86_64"; - } - } - } -} diff --git a/Editor/Mono/BuildPipeline/RuntimeClassMetadata.cs b/Editor/Mono/BuildPipeline/RuntimeClassMetadata.cs deleted file mode 100644 index 9ff6c4084c..0000000000 --- a/Editor/Mono/BuildPipeline/RuntimeClassMetadata.cs +++ /dev/null @@ -1,173 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEditorInternal; -using System; - - -namespace UnityEditor -{ - /// - /// Registry for Unity native-managed class dependencies. Aimed to make native and managed code stripping possible. - /// Note: only UnityEngine.dll content is covered there. - /// - internal class RuntimeClassRegistry - { - protected BuildTarget buildTarget; - protected HashSet monoBaseClasses = new HashSet(); - protected Dictionary m_UsedTypesPerUserAssembly = new Dictionary(); - protected Dictionary> classScenes = new Dictionary>(); - protected UnityType objectUnityType = null; - - public Dictionary UsedTypePerUserAssembly - { - get { return m_UsedTypesPerUserAssembly; } - } - - // Store all registered native classes (including managers) here. - // 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. - protected Dictionary allNativeClasses = new Dictionary(); - - public List GetScenesForClass(int ID) - { - if (!classScenes.ContainsKey(ID)) - return null; - return classScenes[ID]; - } - - public void AddNativeClassID(int ID) - { - string className = UnityType.FindTypeByPersistentTypeID(ID).name; - ////System.Console.WriteLine("Looking for ID {0} name {1} --> is manager? {2}", ID, className, functionalityGroups.ContainsValue(className)); - - // Native class found - if (className.Length > 0) - allNativeClasses[ID] = className; - } - - public void SetUsedTypesInUserAssembly(string[] typeNames, string assemblyName) - { - m_UsedTypesPerUserAssembly[assemblyName] = typeNames; - } - - public bool IsDLLUsed(string dll) - { - if (m_UsedTypesPerUserAssembly == null) - return true; - if (Array.IndexOf(CodeStrippingUtils.UserAssemblies, dll) != -1) - return true; - return m_UsedTypesPerUserAssembly.ContainsKey(dll); - } - - protected void AddManagedBaseClass(string className) - { - monoBaseClasses.Add(className); - } - - protected void AddNativeClassFromName(string className) - { - if (objectUnityType == null) - objectUnityType = UnityType.FindTypeByName("Object"); - - var t = UnityType.FindTypeByName(className); - - ////System.Console.WriteLine("Looking for name {1} ID {0}", classID, className); - if (t != null && t.persistentTypeID != objectUnityType.persistentTypeID) - allNativeClasses[t.persistentTypeID] = className; - } - - public List GetAllNativeClassesIncludingManagersAsString() - { - return new List(allNativeClasses.Values); - } - - public List GetAllManagedBaseClassesAsString() - { - return new List(monoBaseClasses); - } - - public static RuntimeClassRegistry Create() - { - return new RuntimeClassRegistry(); - } - - public void Initialize(int[] nativeClassIDs, BuildTarget buildTarget) - { - this.buildTarget = buildTarget; - InitRuntimeClassRegistry(); - foreach (int ID in nativeClassIDs) - AddNativeClassID(ID); - } - - public void SetSceneClasses(int[] nativeClassIDs, string scene) - { - foreach (int ID in nativeClassIDs) - { - AddNativeClassID(ID); - if (!classScenes.ContainsKey(ID)) - classScenes[ID] = new List(); - classScenes[ID].Add(scene); - } - } - - internal class MethodDescription - { - public string assembly; - public string fullTypeName; - public string methodName; - } - - internal List m_MethodsToPreserve = new List(); - - //invoked by native code - internal void AddMethodToPreserve(string assembly, string @namespace, string klassName, string methodName) - { - m_MethodsToPreserve.Add(new MethodDescription() - { - assembly = assembly, - fullTypeName = @namespace + (@namespace.Length > 0 ? "." : "") + klassName, - methodName = methodName - }); - } - - internal List GetMethodsToPreserve() - { - return m_MethodsToPreserve; - } - - internal List m_UserAssemblies = new List(); - - //invoked by native code - internal void AddUserAssembly(string assembly) - { - if (!m_UserAssemblies.Contains(assembly)) - m_UserAssemblies.Add(assembly); - } - - internal string[] GetUserAssemblies() - { - return m_UserAssemblies.ToArray(); - } - - protected void InitRuntimeClassRegistry() - { - BuildTargetGroup group = UnityEditor.BuildPipeline.GetBuildTargetGroup(buildTarget); - - // Don't strip any classes which extend the following base classes - AddManagedBaseClass("UnityEngine.MonoBehaviour"); - AddManagedBaseClass("UnityEngine.ScriptableObject"); - - if (group == BuildTargetGroup.Android) - { - AddManagedBaseClass("UnityEngine.AndroidJavaProxy"); - } - - string[] runtimeLoadDontStripClassNames = RuntimeInitializeOnLoadManager.dontStripClassNames; - foreach (string kclass in runtimeLoadDontStripClassNames) - AddManagedBaseClass(kclass); - } - } -} diff --git a/Editor/Mono/BuildPipeline/WinRT/WinRTUtils.cs b/Editor/Mono/BuildPipeline/WinRT/WinRTUtils.cs deleted file mode 100644 index ec796520e2..0000000000 --- a/Editor/Mono/BuildPipeline/WinRT/WinRTUtils.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using UnityEditorInternal; -using System; -using System.Threading; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System.Text.RegularExpressions; -using Mono.Cecil; - -internal class WinRTUtils -{ - public static string GetProcessorArchitecture(BuildTarget target) - { - return "x86"; - } -} diff --git a/Editor/Mono/BuildPlayerSceneTreeView.cs b/Editor/Mono/BuildPlayerSceneTreeView.cs deleted file mode 100644 index f84f26c7fb..0000000000 --- a/Editor/Mono/BuildPlayerSceneTreeView.cs +++ /dev/null @@ -1,322 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.IO; -using UnityEditor.IMGUI.Controls; - -namespace UnityEditor -{ - internal class BuildPlayerSceneTreeViewItem : TreeViewItem - { - private const string kAssetsFolder = "Assets/"; - private const string kSceneExtension = ".unity"; - - public static int kInvalidCounter = -1; - - public bool active; - public int counter; - public string fullName; - public GUID guid; - public void UpdateName() - { - var name = AssetDatabase.GUIDToAssetPath(guid.ToString()); - if (name != fullName) - { - fullName = name; - - displayName = fullName; - if (displayName.StartsWith(kAssetsFolder)) - displayName = displayName.Remove(0, kAssetsFolder.Length); - var ext = displayName.LastIndexOf(kSceneExtension); - if (ext > 0) - displayName = displayName.Substring(0, ext); - } - } - - public BuildPlayerSceneTreeViewItem(int id, int depth, string path, bool state) : base(id, depth) - { - active = state; - counter = kInvalidCounter; - guid = new GUID(AssetDatabase.AssetPathToGUID(path)); - fullName = ""; - displayName = path; - UpdateName(); - } - } - internal class BuildPlayerSceneTreeView : TreeView - { - public BuildPlayerSceneTreeView(TreeViewState state) : base(state) - { - showBorder = true; - EditorBuildSettings.sceneListChanged += HandleExternalSceneListChange; - } - - internal void UnsubscribeListChange() - { - EditorBuildSettings.sceneListChanged -= HandleExternalSceneListChange; - } - - private void HandleExternalSceneListChange() - { - Reload(); - } - - protected override TreeViewItem BuildRoot() - { - var root = new TreeViewItem(-1, -1); - root.children = new List(); - - List scenes = new List(EditorBuildSettings.scenes); - foreach (var sc in scenes) - { - var item = new BuildPlayerSceneTreeViewItem(sc.guid.GetHashCode(), 0, sc.path, sc.enabled); - root.AddChild(item); - } - return root; - } - - protected override bool CanBeParent(TreeViewItem item) - { - return false; - } - - protected override void BeforeRowsGUI() - { - int counter = 0; - foreach (var item in rootItem.children) - { - var bpst = item as BuildPlayerSceneTreeViewItem; - if (bpst != null) - bpst.UpdateName(); - - //Need to set counter here because RowGUI is only called on items that are visible. - if (bpst.active) - { - bpst.counter = counter; - counter++; - } - else - bpst.counter = BuildPlayerSceneTreeViewItem.kInvalidCounter; - } - - base.BeforeRowsGUI(); - } - - protected override void RowGUI(RowGUIArgs args) - { - var sceneItem = args.item as BuildPlayerSceneTreeViewItem; - if (sceneItem != null) - { - var sceneWasDeleted = sceneItem.guid.Empty(); - var sceneExists = !sceneWasDeleted && File.Exists(sceneItem.fullName); - - using (new EditorGUI.DisabledScope(!sceneExists)) - { - var newState = sceneItem.active; - if (!sceneExists) - newState = false; - newState = GUI.Toggle(new Rect(args.rowRect.x, args.rowRect.y, 16f, 16f), newState, ""); - if (newState != sceneItem.active) - { - if (GetSelection().Contains(sceneItem.id)) - { - var selection = GetSelection(); - foreach (var id in selection) - { - var item = FindItem(id, rootItem) as BuildPlayerSceneTreeViewItem; - item.active = newState; - } - } - else - { - sceneItem.active = newState; - } - - EditorBuildSettings.scenes = GetSceneList(); - } - - base.RowGUI(args); - - if (sceneItem.counter != BuildPlayerSceneTreeViewItem.kInvalidCounter) - { - TreeView.DefaultGUI.LabelRightAligned(args.rowRect, "" + sceneItem.counter, args.selected, args.focused); - } - else if (sceneItem.displayName == string.Empty || !sceneExists) - { - TreeView.DefaultGUI.LabelRightAligned(args.rowRect, "Deleted", args.selected, args.focused); - } - } - } - else - base.RowGUI(args); - } - - protected override DragAndDropVisualMode HandleDragAndDrop(DragAndDropArgs args) - { - DragAndDropVisualMode visualMode = DragAndDropVisualMode.None; - - var draggedIDs = DragAndDrop.GetGenericData("BuildPlayerSceneTreeViewItem") as List; - if (draggedIDs != null && draggedIDs.Count > 0) - { - visualMode = DragAndDropVisualMode.Move; - if (args.performDrop) - { - int newIndex = FindDropAtIndex(args); - - var result = new List(); - int toInsert = 0; - foreach (var item in rootItem.children) - { - if (toInsert == newIndex) - { - foreach (var id in draggedIDs) - { - result.Add(FindItem(id, rootItem)); - } - } - toInsert++; - if (!draggedIDs.Contains(item.id)) - { - result.Add(item); - } - } - - if (result.Count < rootItem.children.Count) //must be appending. - { - foreach (var id in draggedIDs) - { - result.Add(FindItem(id, rootItem)); - } - } - rootItem.children = result; - EditorBuildSettings.scenes = GetSceneList(); - ReloadAndSelect(draggedIDs); - Repaint(); - } - } - else if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0) - { - visualMode = DragAndDropVisualMode.Copy; - if (args.performDrop) - { - var scenes = new List(EditorBuildSettings.scenes); - var scenesToAdd = new List(); - var selection = new List(); - - foreach (var path in DragAndDrop.paths) - { - if (AssetDatabase.GetMainAssetTypeAtPath(path) == typeof(SceneAsset)) - { - var guid = new GUID(AssetDatabase.AssetPathToGUID(path)); - selection.Add(guid.GetHashCode()); - - bool unique = true; - foreach (var scene in scenes) - { - if (scene.path == path) - { - unique = false; - break; - } - } - if (unique) - scenesToAdd.Add(new EditorBuildSettingsScene(path, true)); - } - } - - - int newIndex = FindDropAtIndex(args); - scenes.InsertRange(newIndex, scenesToAdd); - EditorBuildSettings.scenes = scenes.ToArray(); - ReloadAndSelect(selection); - Repaint(); - } - } - return visualMode; - } - - private void ReloadAndSelect(IList hashCodes) - { - Reload(); - SetSelection(hashCodes, TreeViewSelectionOptions.RevealAndFrame); - SelectionChanged(hashCodes); - } - - protected override void DoubleClickedItem(int id) - { - BuildPlayerSceneTreeViewItem item = FindItem(id , rootItem) as BuildPlayerSceneTreeViewItem; - int instanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(item.fullName); - EditorGUIUtility.PingObject(instanceID); - } - - protected int FindDropAtIndex(DragAndDropArgs args) - { - int indexToDrop = args.insertAtIndex; - - // covers if(args.dragAndDropPosition == DragAndDropPosition.OutsideItems) and a safety check. - if (indexToDrop < 0 || indexToDrop > rootItem.children.Count) - indexToDrop = rootItem.children.Count; - - return indexToDrop; - } - - protected override bool CanStartDrag(CanStartDragArgs args) - { - return true; - } - - protected override void SetupDragAndDrop(SetupDragAndDropArgs args) - { - DragAndDrop.PrepareStartDrag(); - DragAndDrop.paths = null; - DragAndDrop.objectReferences = new UnityEngine.Object[] {}; - DragAndDrop.SetGenericData("BuildPlayerSceneTreeViewItem", new List(args.draggedItemIDs)); - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - DragAndDrop.StartDrag("BuildPlayerSceneTreeView"); - } - - protected override void KeyEvent() - { - if ((Event.current.keyCode == KeyCode.Delete || Event.current.keyCode == KeyCode.Backspace) && - (GetSelection().Count > 0)) - { - RemoveSelection(); - } - } - - protected override void ContextClicked() - { - if (GetSelection().Count > 0) - { - GenericMenu menu = new GenericMenu(); - menu.AddItem(EditorGUIUtility.TrTextContent("Remove Selection"), false, RemoveSelection); - menu.ShowAsContext(); - } - } - - protected void RemoveSelection() - { - foreach (var nodeID in GetSelection()) - { - rootItem.children.Remove(FindItem(nodeID, rootItem)); - } - EditorBuildSettings.scenes = GetSceneList(); - Reload(); - Repaint(); - } - - public EditorBuildSettingsScene[] GetSceneList() - { - var sceneList = new EditorBuildSettingsScene[rootItem.children.Count]; - for (int index = 0; index < rootItem.children.Count; index++) - { - var sceneItem = rootItem.children[index] as BuildPlayerSceneTreeViewItem; - sceneList[index] = new EditorBuildSettingsScene(sceneItem.fullName, sceneItem.active); - } - return sceneList; - } - } -} diff --git a/Editor/Mono/BuildPlayerWindow.cs b/Editor/Mono/BuildPlayerWindow.cs deleted file mode 100644 index 888ea30d4d..0000000000 --- a/Editor/Mono/BuildPlayerWindow.cs +++ /dev/null @@ -1,886 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Text.RegularExpressions; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEditor.SceneManagement; -using UnityEditor.Build; -using UnityEditorInternal; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.VersionControl; -using UnityEditor.Modules; -using GraphicsDeviceType = UnityEngine.Rendering.GraphicsDeviceType; -using Object = UnityEngine.Object; -using UnityEditor.Connect; - -namespace UnityEditor -{ - public partial class BuildPlayerWindow : EditorWindow - { - class Styles - { - 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)); - public GUIStyle selected = "OL SelectedRow"; - public GUIStyle box = "OL Box"; - public GUIStyle title = EditorStyles.boldLabel; - public GUIStyle evenRow = "CN EntryBackEven"; - public GUIStyle oddRow = "CN EntryBackOdd"; - public GUIStyle platformSelector = "PlayerSettingsPlatform"; - public GUIStyle toggle = "Toggle"; - public GUIStyle levelString = "PlayerSettingsLevel"; - public GUIStyle levelStringCounter = new GUIStyle("Label"); - public Vector2 toggleSize; - - public GUIContent becauseYouAreNot = EditorGUIUtility.TrTextContent("Because you are not a member of this project this build will not access Unity services.", EditorGUIUtility.GetHelpIcon(MessageType.Warning)); - public GUIContent noSessionDialogText = EditorGUIUtility.TrTextContent("In order to publish your build to UDN, you need to sign in via the AssetStore and tick the 'Stay signed in' checkbox."); - public GUIContent platformTitle = EditorGUIUtility.TrTextContent("Platform", "Which platform to build for"); - public GUIContent switchPlatform = EditorGUIUtility.TrTextContent("Switch Platform"); - public GUIContent build = EditorGUIUtility.TrTextContent("Build"); - public GUIContent buildAndRun = EditorGUIUtility.TrTextContent("Build And Run"); - public GUIContent scenesInBuild = EditorGUIUtility.TrTextContent("Scenes In Build", "Which scenes to include in the build"); - public GUIContent checkOut = EditorGUIUtility.TrTextContent("Check out"); - public GUIContent addOpenSource = EditorGUIUtility.TrTextContent("Add Open Scenes"); - public string noModuleLoaded = L10n.Tr("No {0} module loaded."); - public GUIContent openDownloadPage = EditorGUIUtility.TrTextContent("Open Download Page"); - 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."); - public GUIContent eula = EditorGUIUtility.TrTextContent("Eula"); - public string addToYourPro = L10n.Tr("Add {0} to your Unity Pro license"); - public GUIContent useNativeCompilation = EditorGUIUtility.TrTextContent("Use native compilation (no Mono runtime)"); - - public Texture2D activePlatformIcon = EditorGUIUtility.IconContent("BuildSettings.SelectedIcon").image as Texture2D; - - public const float kButtonWidth = 110; - - // List of platforms that appear in the window. To add one, add it here. - // Later on, we'll let the users add their own. - const string kShopURL = "https://store.unity3d.com/shop/"; - const string kDownloadURL = "http://unity3d.com/unity/download/"; - const string kMailURL = "http://unity3d.com/company/sales?type=sales"; - const string kPlatformInstallationURL = "https://unity3d.com/platform-installation"; - // ADD_NEW_PLATFORM_HERE - public GUIContent[,] notLicensedMessages = - { - { EditorGUIUtility.TextContent("Your license does not cover Standalone Publishing."), new GUIContent(""), new GUIContent(kShopURL) }, - { EditorGUIUtility.TextContent("Your license does not cover iOS Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, - { EditorGUIUtility.TextContent("Your license does not cover Apple TV Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, - { EditorGUIUtility.TextContent("Your license does not cover Android Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, - { EditorGUIUtility.TextContent("Your license does not cover Tizen Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, - { EditorGUIUtility.TextContent("Your license does not cover Xbox One Publishing. Please see the Xbox One section of the Platform Module Installation documentation for more details."), EditorGUIUtility.TrTextContent("Platform Module Installation"), new GUIContent(kPlatformInstallationURL) }, - { EditorGUIUtility.TextContent("Your license does not cover PS Vita Publishing. Please see the PS Vita section of the Platform Module Installation documentation for more details."), EditorGUIUtility.TrTextContent("Platform Module Installation"), new GUIContent(kPlatformInstallationURL) }, - { EditorGUIUtility.TextContent("Your license does not cover PS4 Publishing. Please see the PS4 section of the Platform Module Installation documentation for more details."), EditorGUIUtility.TrTextContent("Platform Module Installation"), new GUIContent(kPlatformInstallationURL) }, - { EditorGUIUtility.TextContent("Your license does not cover Universal Windows Platform Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, - { EditorGUIUtility.TextContent("Your license does not cover Windows Phone 8 Publishing."), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, - { EditorGUIUtility.TextContent("Your license does not cover Nintendo 3DS Publishing"), EditorGUIUtility.TrTextContent("Contact sales"), new GUIContent(kMailURL) }, - { EditorGUIUtility.TextContent("Your license does not cover Facebook Publishing"), EditorGUIUtility.TrTextContent("Go to Our Online Store"), new GUIContent(kShopURL) }, - { EditorGUIUtility.TextContent("Your license does not cover Nintendo Switch Publishing"), EditorGUIUtility.TrTextContent("Contact sales"), new GUIContent(kMailURL) }, - }; - - // ADD_NEW_PLATFORM_HERE - private GUIContent[,] buildTargetNotInstalled = - { - { EditorGUIUtility.TrTextContent("Standalone Player is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("iOS Player is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("Apple TV Player is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("Android Player is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("Tizen is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("Xbox One Player is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("PS Vita Player is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("PS4 Player is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("Universal Windows Platform Player is not supported in\nthis build.\n\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("Windows Phone 8 Player is not supported\nin this build.\n\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("Nintendo 3DS is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("Facebook is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - { EditorGUIUtility.TrTextContent("Nintendo Switch is not supported in this build.\nDownload a build that supports it."), null, new GUIContent(kDownloadURL) }, - }; - public GUIContent GetTargetNotInstalled(int index, int item) - { - if (index >= buildTargetNotInstalled.GetLength(0)) index = 0; - return buildTargetNotInstalled[index, item]; - } - - public GUIContent GetDownloadErrorForTarget(BuildTarget target) - { - return null; - } - - // string and matching enum values for standalone subtarget dropdowm - public GUIContent debugBuild = EditorGUIUtility.TrTextContent("Development Build"); - public GUIContent profileBuild = EditorGUIUtility.TrTextContent("Autoconnect Profiler"); - public GUIContent allowDebugging = EditorGUIUtility.TrTextContent("Script Debugging"); - public GUIContent waitForManagedDebugger = EditorGUIUtility.TrTextContent("Wait For Managed Debugger", "Show a dialog where you can attach a managed debugger before any script execution."); - public GUIContent symlinkiOSLibraries = EditorGUIUtility.TrTextContent("Symlink Unity libraries"); - public GUIContent explicitNullChecks = EditorGUIUtility.TrTextContent("Explicit Null Checks"); - public GUIContent explicitDivideByZeroChecks = EditorGUIUtility.TrTextContent("Divide By Zero Checks"); - public GUIContent explicitArrayBoundsChecks = EditorGUIUtility.TrTextContent("Array Bounds Checks"); - public GUIContent enableHeadlessMode = EditorGUIUtility.TrTextContent("Headless Mode"); - public GUIContent buildScriptsOnly = EditorGUIUtility.TrTextContent("Scripts Only Build"); - public GUIContent learnAboutUnityCloudBuild = EditorGUIUtility.TrTextContent("Learn about Unity Cloud Build"); - 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."); - - public Compression[] compressionTypes = - { - Compression.None, - Compression.Lz4, - Compression.Lz4HC - }; - - public GUIContent[] compressionStrings = - { - EditorGUIUtility.TrTextContent("Default"), - EditorGUIUtility.TrTextContent("LZ4"), - EditorGUIUtility.TrTextContent("LZ4HC"), - }; - - public Styles() - { - levelStringCounter.alignment = TextAnchor.MiddleRight; - - if (Unsupported.IsSourceBuild() && ( - buildTargetNotInstalled.GetLength(0) != notLicensedMessages.GetLength(0) || - buildTargetNotInstalled.GetLength(0) != BuildPlatforms.instance.buildPlatforms.Length)) - Debug.LogErrorFormat("Build platforms and messages are desynced in BuildPlayerWindow! ({0} vs. {1} vs. {2}) DON'T SHIP THIS!", buildTargetNotInstalled.GetLength(0), notLicensedMessages.GetLength(0), BuildPlatforms.instance.buildPlatforms.Length); - } - } - - - Vector2 scrollPosition = new Vector2(0, 0); - - - private const string kEditorBuildSettingsPath = "ProjectSettings/EditorBuildSettings.asset"; - internal const string kSettingDebuggingWaitForManagedDebugger = "WaitForManagedDebugger"; - - static Styles styles = null; - - public static void ShowBuildPlayerWindow() - { - EditorUserBuildSettings.selectedBuildTargetGroup = EditorUserBuildSettings.activeBuildTargetGroup; - EditorWindow.GetWindow(true, "Build Settings"); - } - - static bool BuildLocationIsValid(string path) - { - return path.Length > 0 && System.IO.Directory.Exists(FileUtil.DeleteLastPathNameComponent(path)); - } - - // This overload is used by the Build & Run menu item & hot key - prompt for location only if the configured - // output location is not valid. - static void BuildPlayerAndRun() - { - var buildTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget(); - var buildLocation = EditorUserBuildSettings.GetBuildLocation(buildTarget); - BuildPlayerAndRun(!BuildLocationIsValid(buildLocation)); - } - - // This overload is used by the default player window, to always prompt for build location - static void BuildPlayerAndRun(bool askForBuildLocation) - { - CallBuildMethods(askForBuildLocation, BuildOptions.AutoRunPlayer | BuildOptions.StrictMode); - } - - public BuildPlayerWindow() - { - position = new Rect(50, 50, 540, 530); - minSize = new Vector2(630, 580); - titleContent = EditorGUIUtility.TrTextContent("Build Settings"); - } - - BuildPlayerSceneTreeView m_TreeView = null; - [SerializeField] - IMGUI.Controls.TreeViewState m_TreeViewState; - void ActiveScenesGUI() - { - if (m_TreeView == null) - { - if (m_TreeViewState == null) - m_TreeViewState = new IMGUI.Controls.TreeViewState(); - m_TreeView = new BuildPlayerSceneTreeView(m_TreeViewState); - m_TreeView.Reload(); - } - Rect scenesInBuildRect = GUILayoutUtility.GetRect(styles.scenesInBuild, styles.title); - GUI.Label(scenesInBuildRect, styles.scenesInBuild, styles.title); - - Rect rect = GUILayoutUtility.GetRect(0, position.width, 0, position.height); - m_TreeView.OnGUI(rect); - } - - void OnDisable() - { - if (m_TreeView != null) - m_TreeView.UnsubscribeListChange(); - } - - void AddOpenScenes() - { - List list = new List(EditorBuildSettings.scenes); - - bool isSceneAdded = false; - for (int i = 0; i < SceneManager.sceneCount; i++) - { - Scene scene = SceneManager.GetSceneAt(i); - if (scene.path.Length == 0 && !EditorSceneManager.SaveScene(scene, "", false)) - continue; - - if (list.Any(s => s.path == scene.path)) - continue; - - GUID newGUID; - GUID.TryParse(scene.guid, out newGUID); - var buildSettingsScene = (newGUID == default(GUID)) ? - new EditorBuildSettingsScene(scene.path, true) : - new EditorBuildSettingsScene(newGUID, true); - list.Add(buildSettingsScene); - isSceneAdded = true; - } - - if (!isSceneAdded) - return; - - EditorBuildSettings.scenes = list.ToArray(); - m_TreeView.Reload(); - Repaint(); - GUIUtility.ExitGUI(); - } - - private void ActiveBuildTargetsGUI() - { - GUILayout.BeginVertical(); - GUILayout.BeginVertical(GUILayout.Width(255)); - GUILayout.Label(styles.platformTitle, styles.title); - scrollPosition = GUILayout.BeginScrollView(scrollPosition, "OL Box"); - - // Draw enabled build targets first, then draw disabled build targets - for (int requireEnabled = 0; requireEnabled < 2; requireEnabled++) - { - bool showRequired = requireEnabled == 0; - bool even = false; - foreach (BuildPlatform gt in BuildPlatforms.instance.buildPlatforms) - { - if (IsBuildTargetGroupSupported(gt.targetGroup, gt.defaultTarget) != showRequired) - continue; - - // Some build targets are not publicly available, show them only when they are actually in use - if (!IsBuildTargetGroupSupported(gt.targetGroup, gt.defaultTarget) && !gt.forceShowTarget) - continue; - - // Some build targets are only compatible with specific OS - if (!BuildPipeline.IsBuildTargetCompatibleWithOS(gt.defaultTarget)) - continue; - - ShowOption(gt, gt.title, even ? styles.evenRow : styles.oddRow); - even = !even; - } - GUI.contentColor = Color.white; - } - - GUILayout.EndScrollView(); - GUILayout.EndVertical(); - GUILayout.Space(10); - - // Switching build target in the editor - BuildTarget selectedTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget(); - BuildTargetGroup selectedTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; - - GUILayout.BeginHorizontal(); - - GUI.enabled = BuildPipeline.IsBuildTargetSupported(selectedTargetGroup, selectedTarget) && EditorUserBuildSettings.activeBuildTargetGroup != selectedTargetGroup; - if (GUILayout.Button(styles.switchPlatform, GUILayout.Width(Styles.kButtonWidth))) - { - EditorUserBuildSettings.SwitchActiveBuildTargetAsync(selectedTargetGroup, selectedTarget); - GUIUtility.ExitGUI(); - } - - GUI.enabled = BuildPipeline.IsBuildTargetSupported(selectedTargetGroup, selectedTarget); - if (GUILayout.Button(EditorGUIUtility.TrTextContent("Player Settings..."), GUILayout.Width(Styles.kButtonWidth))) - { - Selection.activeObject = Unsupported.GetSerializedAssetInterfaceSingleton("PlayerSettings"); - EditorWindow.GetWindow(); - } - - GUILayout.EndHorizontal(); - - GUI.enabled = true; - - GUILayout.EndVertical(); - } - - void ShowAlert() - { - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - GUILayout.BeginVertical(); - 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); - GUILayout.EndVertical(); - GUILayout.Space(5); - GUILayout.EndHorizontal(); - } - - void ShowOption(BuildPlatform bp, GUIContent title, GUIStyle background) - { - Rect r = GUILayoutUtility.GetRect(50, 36); - r.x += 1; - r.y += 1; - bool valid = BuildPipeline.LicenseCheck(bp.defaultTarget); - GUI.contentColor = new Color(1, 1, 1, valid ? 1 : .7f); - bool enabled = EditorUserBuildSettings.selectedBuildTargetGroup == bp.targetGroup; - if (Event.current.type == EventType.Repaint) - { - background.Draw(r, GUIContent.none, false, false, enabled, false); - GUI.Label(new Rect(r.x + 3, r.y + 3, 32, 32), title.image, GUIStyle.none); - - if (EditorUserBuildSettings.activeBuildTargetGroup == bp.targetGroup) - GUI.Label(new Rect(r.xMax - styles.activePlatformIcon.width - 8, r.y + 3 + (32 - styles.activePlatformIcon.height) / 2, - styles.activePlatformIcon.width, styles.activePlatformIcon.height), - styles.activePlatformIcon, GUIStyle.none); - } - - if (GUI.Toggle(r, enabled, title.text, styles.platformSelector)) - { - if (EditorUserBuildSettings.selectedBuildTargetGroup != bp.targetGroup) - { - EditorUserBuildSettings.selectedBuildTargetGroup = bp.targetGroup; - - // Repaint inspectors, as they may be showing platform target specific things. - Object[] inspectors = Resources.FindObjectsOfTypeAll(typeof(InspectorWindow)); - for (int i = 0; i < inspectors.Length; i++) - { - InspectorWindow inspector = inspectors[i] as InspectorWindow; - if (inspector != null) - inspector.Repaint(); - } - } - } - } - - void OnGUI() - { - if (styles == null) - { - styles = new Styles(); - styles.toggleSize = styles.toggle.CalcSize(new GUIContent("X")); - } - - if (!UnityConnect.instance.canBuildWithUPID) - { - ShowAlert(); - } - GUILayout.Space(5); - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - GUILayout.BeginVertical(); - - string message = ""; - var buildSettingsLocked = !AssetDatabase.IsOpenForEdit(kEditorBuildSettingsPath, out message, StatusQueryOptions.UseCachedIfPossible); - - using (new EditorGUI.DisabledScope(buildSettingsLocked)) - { - ActiveScenesGUI(); - // Clear all and Add Current Scene - GUILayout.BeginHorizontal(); - if (buildSettingsLocked) - { - GUI.enabled = true; - - if (Provider.enabled && GUILayout.Button(styles.checkOut)) - { - Asset asset = Provider.GetAssetByPath(kEditorBuildSettingsPath); - var assetList = new AssetList(); - assetList.Add(asset); - Provider.Checkout(assetList, CheckoutMode.Asset); - } - GUILayout.Label(message); - GUI.enabled = false; - } - GUILayout.FlexibleSpace(); - if (GUILayout.Button(styles.addOpenSource)) - AddOpenScenes(); - GUILayout.EndHorizontal(); - } - - GUILayout.Space(10); - - GUILayout.BeginHorizontal(GUILayout.Height(351)); - ActiveBuildTargetsGUI(); - GUILayout.Space(10); - GUILayout.BeginVertical(); - ShowBuildTargetSettings(); - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - - GUILayout.Space(10); - GUILayout.EndVertical(); - GUILayout.Space(10); - GUILayout.EndHorizontal(); - } - - internal static bool IsBuildTargetGroupSupported(BuildTargetGroup targetGroup, BuildTarget target) - { - if (targetGroup == BuildTargetGroup.Standalone) - return true; - else - return BuildPipeline.IsBuildTargetSupported(targetGroup, target); - } - - static void RepairSelectedBuildTargetGroup() - { - BuildTargetGroup group = EditorUserBuildSettings.selectedBuildTargetGroup; - if ((int)group == 0 || BuildPlatforms.instance.BuildPlatformIndexFromTargetGroup(group) < 0) - EditorUserBuildSettings.selectedBuildTargetGroup = BuildTargetGroup.Standalone; - } - - static bool IsAnyStandaloneModuleLoaded() - { - return ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget.StandaloneLinux)) || - ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget.StandaloneOSX)) || - ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget.StandaloneWindows)); - } - - static bool IsColorSpaceValid(BuildPlatform platform) - { - if (PlayerSettings.colorSpace == ColorSpace.Linear) - { - var hasMinGraphicsAPI = true; - var hasMinOSVersion = true; - - if (platform.targetGroup == BuildTargetGroup.iOS) - { - var apis = PlayerSettings.GetGraphicsAPIs(BuildTarget.iOS); - hasMinGraphicsAPI = !apis.Contains(GraphicsDeviceType.OpenGLES3) && !apis.Contains(GraphicsDeviceType.OpenGLES2); - - Version requiredVersion = new Version(8, 0); - hasMinOSVersion = PlayerSettings.iOS.IsTargetVersionEqualOrHigher(requiredVersion); - } - else if (platform.targetGroup == BuildTargetGroup.tvOS) - { - var apis = PlayerSettings.GetGraphicsAPIs(BuildTarget.tvOS); - hasMinGraphicsAPI = !apis.Contains(GraphicsDeviceType.OpenGLES3) && !apis.Contains(GraphicsDeviceType.OpenGLES2); - } - else if (platform.targetGroup == BuildTargetGroup.Android) - { - var apis = PlayerSettings.GetGraphicsAPIs(BuildTarget.Android); - hasMinGraphicsAPI = (apis.Contains(GraphicsDeviceType.Vulkan) || apis.Contains(GraphicsDeviceType.OpenGLES3)) && !apis.Contains(GraphicsDeviceType.OpenGLES2); - hasMinOSVersion = (int)PlayerSettings.Android.minSdkVersion >= 18; - } - else if (platform.targetGroup == BuildTargetGroup.WebGL) - { - var apis = PlayerSettings.GetGraphicsAPIs(BuildTarget.WebGL); - hasMinGraphicsAPI = apis.Contains(GraphicsDeviceType.OpenGLES3) && !apis.Contains(GraphicsDeviceType.OpenGLES2); - } - - return hasMinGraphicsAPI && hasMinOSVersion; - } - else - { - return true; - } - } - - // Major.Minor.Micro followed by one of abxfp followed by an identifier, optionally suffixed with " (revisionhash)" - static Regex s_VersionPattern = new Regex(@"(?\d+\.\d+\.\d+(?((?[abx])|[fp])[^\s]*))( \((?[a-fA-F\d]+)\))?", - RegexOptions.Compiled); - static Dictionary s_ModuleNames = new Dictionary() - { - { "tvOS", "AppleTV" }, - { "OSXStandalone", "Mac" }, - { "WindowsStandalone", "Windows" }, - { "LinuxStandalone", "Linux" }, - { "Facebook", "Facebook-Games"} - }; - static public string GetPlaybackEngineDownloadURL(string moduleName) - { - if (moduleName == "PS4" || moduleName == "PSP2" || moduleName == "XboxOne") - return "https://unity3d.com/platform-installation"; - - string fullVersion = InternalEditorUtility.GetFullUnityVersion(); - string revision = ""; - string shortVersion = ""; - Match versionMatch = s_VersionPattern.Match(fullVersion); - if (!versionMatch.Success || !versionMatch.Groups["shortVersion"].Success || !versionMatch.Groups["suffix"].Success) - Debug.LogWarningFormat("Error parsing version '{0}'", fullVersion); - - if (versionMatch.Groups["shortVersion"].Success) - shortVersion = versionMatch.Groups["shortVersion"].Value; - if (versionMatch.Groups["revision"].Success) - revision = versionMatch.Groups["revision"].Value; - - if (s_ModuleNames.ContainsKey(moduleName)) - moduleName = s_ModuleNames[moduleName]; - - string prefix = "download"; - string suffix = "download_unity"; - string folder = "Unknown"; - string extension = string.Empty; - - if (versionMatch.Groups["alphabeta"].Success) - { - // These releases are hosted on the beta site - prefix = "beta"; - suffix = "download"; - } - - if (Application.platform == RuntimePlatform.WindowsEditor) - { - folder = "TargetSupportInstaller"; - extension = ".exe"; - } - else if (Application.platform == RuntimePlatform.OSXEditor) - { - folder = "MacEditorTargetInstaller"; - extension = ".pkg"; - } - - return string.Format("http://{0}.unity3d.com/{1}/{2}/{3}/UnitySetup-{4}-Support-for-Editor-{5}{6}", prefix, suffix, revision, folder, moduleName, shortVersion, extension); - } - - bool IsModuleInstalled(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget) - { - bool licensed = BuildPipeline.LicenseCheck(buildTarget); - - string moduleName = Modules.ModuleManager.GetTargetStringFrom(buildTargetGroup, buildTarget); - - return licensed && - !string.IsNullOrEmpty(moduleName) && - Modules.ModuleManager.GetBuildPostProcessor(moduleName) == null && - (BuildTargetGroup.Standalone != EditorUserBuildSettings.selectedBuildTargetGroup || - !IsAnyStandaloneModuleLoaded()); - } - - void ShowBuildTargetSettings() - { - EditorGUIUtility.labelWidth = Mathf.Min(180, (position.width - 265) * 0.47f); - - BuildTarget buildTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget(); - BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; - BuildPlatform platform = BuildPlatforms.instance.BuildPlatformFromTargetGroup(buildTargetGroup); - bool licensed = BuildPipeline.LicenseCheck(buildTarget); - - // Draw the group name - GUILayout.Space(18); - - // Draw icon and text of title separately so we can control the space between them - Rect r = GUILayoutUtility.GetRect(50, 36); - r.x += 1; - GUI.Label(new Rect(r.x + 3, r.y + 3, 32, 32), platform.title.image, GUIStyle.none); - GUI.Toggle(r, false, platform.title.text, styles.platformSelector); - - GUILayout.Space(10); - - if (platform.targetGroup == BuildTargetGroup.WebGL && !BuildPipeline.IsBuildTargetSupported(platform.targetGroup, buildTarget)) - { - if (IntPtr.Size == 4) - { - GUILayout.Label("Building for WebGL requires a 64-bit Unity editor."); - GUIBuildButtons(false, false, false, platform); - return; - } - } - - string moduleName = Modules.ModuleManager.GetTargetStringFrom(buildTargetGroup, buildTarget); - - if (IsModuleInstalled(buildTargetGroup, buildTarget)) - { - GUILayout.Label(EditorGUIUtility.TextContent(string.Format(styles.noModuleLoaded, BuildPlatforms.instance.GetModuleDisplayName(buildTargetGroup, buildTarget)))); - if (GUILayout.Button(styles.openDownloadPage, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - { - string url = GetPlaybackEngineDownloadURL(moduleName); - Help.BrowseURL(url); - } - GUIBuildButtons(false, false, false, platform); - return; - } - else if (Application.HasProLicense() && !InternalEditorUtility.HasAdvancedLicenseOnBuildTarget(buildTarget)) - { - // Show copy for using personal edition build targets with pro edition editor - string infoText = string.Format(styles.infoText, - BuildPlatforms.instance.GetBuildTargetDisplayName(buildTargetGroup, buildTarget)); - - GUILayout.BeginVertical(EditorStyles.helpBox); - GUILayout.Label(infoText, EditorStyles.wordWrappedMiniLabel); - GUILayout.BeginHorizontal(); - if (GUILayout.Button(styles.eula, EditorStyles.miniButton)) - Application.OpenURL("http://unity3d.com/legal/eula"); - if (GUILayout.Button(string.Format(styles.addToYourPro, BuildPlatforms.instance.GetBuildTargetDisplayName(buildTargetGroup, buildTarget)), EditorStyles.miniButton)) - Application.OpenURL("http://unity3d.com/get-unity"); - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - } - - GUIContent error = styles.GetDownloadErrorForTarget(buildTarget); - if (error != null) - { - GUILayout.Label(error, EditorStyles.wordWrappedLabel); - GUIBuildButtons(false, false, false, platform); - return; - } - - // Draw not licensed buy now UI - if (!licensed) - { - int targetGroup = BuildPlatforms.instance.BuildPlatformIndexFromTargetGroup(platform.targetGroup); - - GUILayout.Label(styles.notLicensedMessages[targetGroup, 0], EditorStyles.wordWrappedLabel); - GUILayout.Space(5); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (styles.notLicensedMessages[targetGroup, 1].text.Length != 0) - { - if (GUILayout.Button(styles.notLicensedMessages[targetGroup, 1])) - { - Application.OpenURL(styles.notLicensedMessages[targetGroup, 2].text); - } - } - GUILayout.EndHorizontal(); - GUIBuildButtons(false, false, false, platform); - return; - } - - // FIXME: WHY IS THIS ALL IN ONE FUNCTION?! - // Draw the side bar to the right. Different options like specific Standalone player to build, profiling and debugging options, etc. - string module = ModuleManager.GetTargetStringFrom(platform.targetGroup, buildTarget); - IBuildWindowExtension buildWindowExtension = ModuleManager.GetBuildWindowExtension(module); - if (buildWindowExtension != null) - buildWindowExtension.ShowPlatformBuildOptions(); - - GUI.changed = false; - switch (platform.targetGroup) - { - case BuildTargetGroup.iOS: - case BuildTargetGroup.tvOS: - { - if (Application.platform == RuntimePlatform.OSXEditor) - EditorUserBuildSettings.symlinkLibraries = EditorGUILayout.Toggle(styles.symlinkiOSLibraries, EditorUserBuildSettings.symlinkLibraries); - } - break; - } - - GUI.enabled = true; - - bool enableBuildButton = buildWindowExtension != null ? buildWindowExtension.EnabledBuildButton() : true; - bool enableBuildAndRunButton = false; - - bool shouldDrawDebuggingToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawScriptDebuggingCheckbox() : true; - bool shouldDrawExplicitNullChecksToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawExplicitNullCheckbox() : false; - bool shouldDrawDivideByZeroChecksToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawExplicitDivideByZeroCheckbox() : false; - bool shouldDrawArrayBoundsChecksToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawExplicitArrayBoundsCheckbox() : false; - bool shouldDrawDevelopmentPlayerToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawDevelopmentPlayerCheckbox() : true; - bool enableHeadlessModeToggle = (buildTarget == BuildTarget.StandaloneLinux || buildTarget == BuildTarget.StandaloneLinux64 || buildTarget == BuildTarget.StandaloneLinuxUniversal); - - IBuildPostprocessor postprocessor = ModuleManager.GetBuildPostProcessor(buildTargetGroup, buildTarget); - bool enableBuildScriptsOnly = (postprocessor != null ? postprocessor.SupportsScriptsOnlyBuild() : false); - bool canInstallInBuildFolder = false; - - if (BuildPipeline.IsBuildTargetSupported(buildTargetGroup, buildTarget)) - { - bool shouldDrawConnectProfilerToggle = buildWindowExtension != null ? buildWindowExtension.ShouldDrawProfilerCheckbox() : true; - - GUI.enabled = shouldDrawDevelopmentPlayerToggle; - if (shouldDrawDevelopmentPlayerToggle) - EditorUserBuildSettings.development = EditorGUILayout.Toggle(styles.debugBuild, EditorUserBuildSettings.development); - - bool developmentBuild = EditorUserBuildSettings.development; - - GUI.enabled = developmentBuild; - - if (shouldDrawConnectProfilerToggle) - { - if (!GUI.enabled) - { - if (!developmentBuild) - styles.profileBuild.tooltip = "Profiling only enabled in Development Player"; - } - else - styles.profileBuild.tooltip = ""; - EditorUserBuildSettings.connectProfiler = EditorGUILayout.Toggle(styles.profileBuild, EditorUserBuildSettings.connectProfiler); - } - - GUI.enabled = developmentBuild; - if (shouldDrawDebuggingToggle) - { - EditorUserBuildSettings.allowDebugging = EditorGUILayout.Toggle(styles.allowDebugging, EditorUserBuildSettings.allowDebugging); - - // Not all platforms have native dialog implemented in Runtime\Misc\GiveDebuggerChanceToAttachIfRequired.cpp - // Display this option only for developer builds - if (EditorUserBuildSettings.allowDebugging && Unsupported.IsSourceBuild()) - { - var buildTargetName = BuildPipeline.GetBuildTargetName(buildTarget); - - bool value = EditorGUILayout.Toggle(styles.waitForManagedDebugger, EditorUserBuildSettings.GetPlatformSettings(buildTargetName, kSettingDebuggingWaitForManagedDebugger) == "true"); - EditorUserBuildSettings.SetPlatformSettings(buildTargetName, kSettingDebuggingWaitForManagedDebugger, value.ToString().ToLower()); - } - } - - - if (shouldDrawExplicitNullChecksToggle) - { - // Force 'ExplicitNullChecks' to true if it's a development build. - GUI.enabled = !developmentBuild; - if (GUI.enabled == false) - { - EditorUserBuildSettings.explicitNullChecks = true; - } - EditorUserBuildSettings.explicitNullChecks = EditorGUILayout.Toggle(styles.explicitNullChecks, EditorUserBuildSettings.explicitNullChecks); - // Undo force from above - GUI.enabled = developmentBuild; - } - - if (shouldDrawDivideByZeroChecksToggle) - { - // Force 'explicitDivideByZeroChecks' to true if it's a development build. - GUI.enabled = !developmentBuild; - if (GUI.enabled == false) - { - EditorUserBuildSettings.explicitDivideByZeroChecks = true; - } - EditorUserBuildSettings.explicitDivideByZeroChecks = EditorGUILayout.Toggle(styles.explicitDivideByZeroChecks, EditorUserBuildSettings.explicitDivideByZeroChecks); - // Undo force from above - GUI.enabled = developmentBuild; - } - - if (shouldDrawArrayBoundsChecksToggle) - { - // Force 'explicitArrayBoundsChecks' to true if it's a development build. - GUI.enabled = !developmentBuild; - if (GUI.enabled == false) - { - EditorUserBuildSettings.explicitArrayBoundsChecks = true; - } - EditorUserBuildSettings.explicitArrayBoundsChecks = EditorGUILayout.Toggle(styles.explicitArrayBoundsChecks, EditorUserBuildSettings.explicitArrayBoundsChecks); - // Undo force from above - GUI.enabled = developmentBuild; - } - - if (enableBuildScriptsOnly) - EditorUserBuildSettings.buildScriptsOnly = EditorGUILayout.Toggle(styles.buildScriptsOnly, EditorUserBuildSettings.buildScriptsOnly); - - GUI.enabled = !developmentBuild; - if (enableHeadlessModeToggle) - EditorUserBuildSettings.enableHeadlessMode = EditorGUILayout.Toggle(styles.enableHeadlessMode, EditorUserBuildSettings.enableHeadlessMode && !developmentBuild); - - GUI.enabled = true; - - GUILayout.FlexibleSpace(); - - if (postprocessor != null && postprocessor.SupportsLz4Compression()) - { - var cmpIdx = Array.IndexOf(styles.compressionTypes, EditorUserBuildSettings.GetCompressionType(buildTargetGroup)); - if (cmpIdx == -1) - cmpIdx = 1; // Lz4 by default. - cmpIdx = EditorGUILayout.Popup(styles.compressionMethod, cmpIdx, styles.compressionStrings); - EditorUserBuildSettings.SetCompressionType(buildTargetGroup, styles.compressionTypes[cmpIdx]); - } - - canInstallInBuildFolder = Unsupported.IsSourceBuild() && PostprocessBuildPlayer.SupportsInstallInBuildFolder(buildTargetGroup, buildTarget); - - if (enableBuildButton) - { - enableBuildAndRunButton = buildWindowExtension != null ? buildWindowExtension.EnabledBuildAndRunButton() - && !(EditorUserBuildSettings.installInBuildFolder) : !(EditorUserBuildSettings.installInBuildFolder); - } - } - else - { - GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); - - GUILayout.BeginVertical(GUILayout.ExpandWidth(true)); - - int targetGroup = BuildPlatforms.instance.BuildPlatformIndexFromTargetGroup(platform.targetGroup); - - GUILayout.Label(styles.GetTargetNotInstalled(targetGroup, 0)); - if (styles.GetTargetNotInstalled(targetGroup, 1) != null) - if (GUILayout.Button(styles.GetTargetNotInstalled(targetGroup, 1))) - Application.OpenURL(styles.GetTargetNotInstalled(targetGroup, 2).text); - - GUILayout.EndVertical(); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - } - - if (buildTarget == BuildTarget.Android) - AndroidPublishGUI(); - - GUIBuildButtons(buildWindowExtension, enableBuildButton, enableBuildAndRunButton, - canInstallInBuildFolder, platform); - } - - private static void GUIBuildButtons(bool enableBuildButton, - bool enableBuildAndRunButton, - bool canInstallInBuildFolder, - BuildPlatform platform) - { - GUIBuildButtons(null, enableBuildButton, enableBuildAndRunButton, canInstallInBuildFolder, platform); - } - - private static void GUIBuildButtons(IBuildWindowExtension buildWindowExtension, - bool enableBuildButton, - bool enableBuildAndRunButton, - bool canInstallInBuildFolder, - BuildPlatform platform) - { - GUILayout.FlexibleSpace(); - - if (canInstallInBuildFolder) - EditorUserBuildSettings.installInBuildFolder = GUILayout.Toggle(EditorUserBuildSettings.installInBuildFolder, "Install in Builds folder\n(for debugging with source code)", GUILayout.ExpandWidth(false)); - else - EditorUserBuildSettings.installInBuildFolder = false; - - if ((buildWindowExtension != null) && Unsupported.IsSourceBuild()) - buildWindowExtension.ShowInternalPlatformBuildOptions(); - - - if (buildWindowExtension != null) - buildWindowExtension.ShowPlatformBuildWarnings(); - - // Disable the 'Build' and 'Build And Run' buttons when the project setup doesn't satisfy the platform requirements - if (!IsColorSpaceValid(platform) && enableBuildButton && enableBuildAndRunButton) - { - enableBuildAndRunButton = false; - enableBuildButton = false; - EditorGUILayout.HelpBox(styles.invalidColorSpaceMessage); - } - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (EditorGUILayout.LinkLabel(styles.learnAboutUnityCloudBuild)) - { - Application.OpenURL(string.Format("{0}/from/editor/buildsettings?upid={1}&pid={2}¤tplatform={3}&selectedplatform={4}&unityversion={5}", - UnityEditorInternal.WebURLs.cloudBuildPage, CloudProjectSettings.projectId, PlayerSettings.productGUID, EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget(), Application.unityVersion)); - } - GUILayout.EndHorizontal(); - // Space 6 for alignment with platform column and to reduce missclicks with Build And Run button - GUILayout.Space(6); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - GUIContent buildButton = null; - GUIContent buildAndRunButton = null; - if (buildWindowExtension != null) - buildWindowExtension.GetBuildButtonTitles(out buildButton, out buildAndRunButton); - - buildButton = buildButton ?? styles.build; - buildAndRunButton = buildAndRunButton ?? styles.buildAndRun; - - // Build Button - GUI.enabled = enableBuildButton; - if (GUILayout.Button(buildButton, GUILayout.Width(Styles.kButtonWidth))) - { - CallBuildMethods(true, BuildOptions.ShowBuiltPlayer | BuildOptions.StrictMode); - GUIUtility.ExitGUI(); - } - // Build and Run button - GUI.enabled = enableBuildAndRunButton; - if (GUILayout.Button(buildAndRunButton, GUILayout.Width(Styles.kButtonWidth))) - { - BuildPlayerAndRun(true); - GUIUtility.ExitGUI(); - } - - GUILayout.EndHorizontal(); - } - } -} diff --git a/Editor/Mono/BuildPlayerWindowBuildMethods.cs b/Editor/Mono/BuildPlayerWindowBuildMethods.cs deleted file mode 100644 index a40d1eb055..0000000000 --- a/Editor/Mono/BuildPlayerWindowBuildMethods.cs +++ /dev/null @@ -1,392 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEditor.Modules; -using UnityEditor.Build; -using UnityEngine; -using UnityEditorInternal; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System; -using UnityEditor.Build.Reporting; -using UnityEditor.Connect; - -namespace UnityEditor -{ - public partial class BuildPlayerWindow : EditorWindow - { - static Func getBuildPlayerOptionsHandler; - static Action buildPlayerHandler; - static bool m_Building = false; - - /// - /// Exception thrown when an abort or error condition is reached within a build method delegate. - /// - public class BuildMethodException : System.Exception - { - /// - /// Constructor for aborting a method without displaying an error. - /// - public BuildMethodException() : base("") {} - - /// - /// Constructor for aborting on error that will print the log the given message as an error. - /// - /// - public BuildMethodException(string message) : base(message) {} - } - - /// - /// Register a delegate method to calculate BuildPlayerOptions that are passed to the build process. - /// - /// Delegate method - public static void RegisterGetBuildPlayerOptionsHandler(Func func) - { - // Display a warning if user scripts try to register this delegate multiple times - if (func != null && getBuildPlayerOptionsHandler != null) - Debug.LogWarning("The get build player options handler in BuildPlayerWindow is being reassigned!"); - - getBuildPlayerOptionsHandler = func; - } - - /// - /// Register a delegate method to execute a player build process. - /// - /// Delegate method - public static void RegisterBuildPlayerHandler(Action func) - { - // Display a warning if user scripts try to register this delegate multiple times - if (func != null && buildPlayerHandler != null) - Debug.LogWarning("The build player handler in BuildPlayerWindow is being reassigned!"); - - buildPlayerHandler = func; - } - - /// - /// Method called by the UI when the "Build" or "Build and Run" buttons are pressed. - /// - /// - static void CallBuildMethods(bool askForBuildLocation, BuildOptions defaultBuildOptions) - { - // One build at a time! - if (m_Building) - return; - try - { - m_Building = true; - BuildPlayerOptions options = new BuildPlayerOptions(); - options.options = defaultBuildOptions; - - if (getBuildPlayerOptionsHandler != null) - options = getBuildPlayerOptionsHandler(options); - else - options = DefaultBuildMethods.GetBuildPlayerOptionsInternal(askForBuildLocation, options); - - if (buildPlayerHandler != null) - buildPlayerHandler(options); - else - DefaultBuildMethods.BuildPlayer(options); - } - catch (BuildMethodException e) - { - if (!string.IsNullOrEmpty(e.Message)) - Debug.LogError(e); - } - finally - { - m_Building = false; - } - } - - /// - /// Default (legacy) implementation of player window build methods. - /// - public static class DefaultBuildMethods - { - /// - /// Default implementation of the build player method. - /// - /// - public static void BuildPlayer(BuildPlayerOptions options) - { - if (!UnityConnect.instance.canBuildWithUPID) - { - 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")) - throw new BuildMethodException(); - } - - if (!BuildPipeline.IsBuildTargetSupported(options.targetGroup, options.target)) - throw new BuildMethodException("Build target is not supported."); - - string module = ModuleManager.GetTargetStringFrom(EditorUserBuildSettings.selectedBuildTargetGroup, options.target); - IBuildWindowExtension buildWindowExtension = ModuleManager.GetBuildWindowExtension(module); - if (buildWindowExtension != null && (options.options & BuildOptions.AutoRunPlayer) != 0 && !buildWindowExtension.EnabledBuildAndRunButton()) - throw new BuildMethodException(); - - if (Unsupported.IsBleedingEdgeBuild()) - { - var sb = new System.Text.StringBuilder(); - sb.AppendLine("This version of Unity is a BleedingEdge build that has not seen any manual testing."); - sb.AppendLine("You should consider this build unstable."); - sb.AppendLine("We strongly recommend that you use a normal version of Unity instead."); - - if (EditorUtility.DisplayDialog("BleedingEdge Build", sb.ToString(), "Cancel", "OK")) - throw new BuildMethodException(); - } - - // See if we need to switch platforms and delay the build. We do this whenever - // we're trying to build for a target different from the active one so as to ensure - // that the compiled script code we have loaded is built for the same platform we - // are building for. As we can't reload while our editor stuff is still executing, - // we need to defer to after the next script reload then. - bool delayToAfterScriptReload = false; - if (EditorUserBuildSettings.activeBuildTarget != options.target || - EditorUserBuildSettings.activeBuildTargetGroup != options.targetGroup) - { - if (!EditorUserBuildSettings.SwitchActiveBuildTargetAsync(options.targetGroup, options.target)) - { - // Switching the build target failed. No point in trying to continue - // with a build. - var errStr = string.Format("Could not switch to build target '{0}', '{1}'.", - BuildPipeline.GetBuildTargetGroupDisplayName(options.targetGroup), - BuildPlatforms.instance.GetBuildTargetDisplayName(options.targetGroup, options.target)); - throw new BuildMethodException(errStr); - } - - if (EditorApplication.isCompiling) - delayToAfterScriptReload = true; - } - - // Trigger build. - // Note: report will be null, if delayToAfterScriptReload = true - var report = BuildPipeline.BuildPlayerInternalNoCheck(options.scenes, options.locationPathName, null, options.targetGroup, options.target, options.options, delayToAfterScriptReload); - - - if (report != null) - { - var resultStr = String.Format("Build completed with a result of '{0}'", report.summary.result.ToString("g")); - - switch (report.summary.result) - { - case Build.Reporting.BuildResult.Unknown: - Debug.LogWarning(resultStr); - break; - case Build.Reporting.BuildResult.Failed: - Debug.LogError(resultStr); - throw new BuildMethodException(report.SummarizeErrors()); - default: - Debug.Log(resultStr); - break; - } - } - } - - /// - /// Default implementation for calculating build options before building the player. - /// - /// - /// - public static BuildPlayerOptions GetBuildPlayerOptions(BuildPlayerOptions defaultBuildPlayerOptions) - { - return GetBuildPlayerOptionsInternal(true, defaultBuildPlayerOptions); - } - - internal static BuildPlayerOptions GetBuildPlayerOptionsInternal(bool askForBuildLocation, BuildPlayerOptions defaultBuildPlayerOptions) - { - var options = defaultBuildPlayerOptions; - - bool updateExistingBuild = false; - - BuildTarget buildTarget = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget(); - BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; - - // Pick location for the build - string newLocation = ""; - bool installInBuildFolder = EditorUserBuildSettings.installInBuildFolder && PostprocessBuildPlayer.SupportsInstallInBuildFolder(buildTargetGroup, buildTarget) && (Unsupported.IsSourceBuild() - || IsMetroPlayer(buildTarget)); - - //Check if Lz4 is supported for the current buildtargetgroup and enable it if need be - if (PostprocessBuildPlayer.SupportsLz4Compression(buildTargetGroup, buildTarget)) - { - if (EditorUserBuildSettings.GetCompressionType(buildTargetGroup) == Compression.Lz4) - options.options |= BuildOptions.CompressWithLz4; - else if (EditorUserBuildSettings.GetCompressionType(buildTargetGroup) == Compression.Lz4HC) - options.options |= BuildOptions.CompressWithLz4HC; - } - - bool developmentBuild = EditorUserBuildSettings.development; - if (developmentBuild) - options.options |= BuildOptions.Development; - if (EditorUserBuildSettings.allowDebugging && developmentBuild) - options.options |= BuildOptions.AllowDebugging; - if (EditorUserBuildSettings.symlinkLibraries) - options.options |= BuildOptions.SymlinkLibraries; - if (EditorUserBuildSettings.enableHeadlessMode) - options.options |= BuildOptions.EnableHeadlessMode; - if (EditorUserBuildSettings.connectProfiler && (developmentBuild || buildTarget == BuildTarget.WSAPlayer)) - options.options |= BuildOptions.ConnectWithProfiler; - if (EditorUserBuildSettings.buildScriptsOnly) - options.options |= BuildOptions.BuildScriptsOnly; - - if (installInBuildFolder) - options.options |= BuildOptions.InstallInBuildFolder; - - if (!installInBuildFolder) - { - if (askForBuildLocation && !PickBuildLocation(buildTargetGroup, buildTarget, options.options, out updateExistingBuild)) - throw new BuildMethodException(); - - newLocation = EditorUserBuildSettings.GetBuildLocation(buildTarget); - - if (newLocation.Length == 0) - { - throw new BuildMethodException("Build location for buildTarget " + buildTarget.ToString() + "is not valid."); - } - - if (!askForBuildLocation) - { - switch (UnityEditorInternal.InternalEditorUtility.BuildCanBeAppended(buildTarget, newLocation)) - { - case CanAppendBuild.Unsupported: - break; - case CanAppendBuild.Yes: - updateExistingBuild = true; - break; - case CanAppendBuild.No: - if (!PickBuildLocation(buildTargetGroup, buildTarget, options.options, out updateExistingBuild)) - throw new BuildMethodException(); - - newLocation = EditorUserBuildSettings.GetBuildLocation(buildTarget); - if (!BuildLocationIsValid(newLocation)) - throw new BuildMethodException("Build location for buildTarget " + buildTarget.ToString() + "is not valid."); - - break; - } - } - } - - if (updateExistingBuild) - options.options |= BuildOptions.AcceptExternalModificationsToPlayer; - - options.target = buildTarget; - options.targetGroup = buildTargetGroup; - options.locationPathName = EditorUserBuildSettings.GetBuildLocation(buildTarget); - options.assetBundleManifestPath = null; - - // Build a list of scenes that are enabled - ArrayList scenesList = new ArrayList(); - EditorBuildSettingsScene[] editorScenes = EditorBuildSettings.scenes; - foreach (EditorBuildSettingsScene scene in editorScenes) - { - if (scene.enabled) - scenesList.Add(scene.path); - } - - options.scenes = scenesList.ToArray(typeof(string)) as string[]; - - return options; - } - - static bool PickBuildLocation(BuildTargetGroup targetGroup, BuildTarget target, BuildOptions options, out bool updateExistingBuild) - { - updateExistingBuild = false; - var previousPath = EditorUserBuildSettings.GetBuildLocation(target); - - string defaultFolder; - string defaultName; - if (previousPath == String.Empty) - { - defaultFolder = FileUtil.DeleteLastPathNameComponent(Application.dataPath); - defaultName = ""; - } - else - { - defaultFolder = FileUtil.DeleteLastPathNameComponent(previousPath); - defaultName = FileUtil.GetLastPathNameComponent(previousPath); - } - - string extension = PostprocessBuildPlayer.GetExtensionForBuildTarget(targetGroup, target, options); - // Invalidate default name, if extension mismatches the default file (for ex., when switching between folder type export to file type export, see Android) - if (extension != Path.GetExtension(defaultName).Replace(".", "")) - defaultName = string.Empty; - - // Hack: For Windows Standalone, we want the BuildPanel to choose a folder, - // but we don't want BuildPlayer to take a folder path because historically it took an .exe path - // and we would be breaking tons of projects! - bool isWindowsStandalone = target == BuildTarget.StandaloneWindows || target == BuildTarget.StandaloneWindows64; - string realExtension = extension; - if (isWindowsStandalone) - { - extension = string.Empty; - // Remove the filename.exe part from the path - if (!string.IsNullOrEmpty(defaultName)) - defaultName = Path.GetDirectoryName(defaultName); - } - - string title = "Build " + BuildPlatforms.instance.GetBuildTargetDisplayName(targetGroup, target); - string path = EditorUtility.SaveBuildPanel(target, title, defaultFolder, defaultName, extension, out updateExistingBuild); - - if (isWindowsStandalone) - { - extension = realExtension; - path = Path.Combine(path, Path.GetFileName(path) + '.' + extension); - } - - if (path == string.Empty) - return false; - - // Enforce extension if needed - if (extension != string.Empty && FileUtil.GetPathExtension(path).ToLower() != extension) - path += '.' + extension; - - // A path may not be empty initially, but it could contain, e.g., a drive letter (as in Windows), - // so even appending an extention will work fine, but in reality the name will be, for example, - // G:/ - //Debug.Log(path); - - string currentlyChosenName = FileUtil.GetLastPathNameComponent(path); - if (currentlyChosenName == string.Empty) - return false; // No nameless projects, please - - // We don't want to re-create a directory that already exists, this may - // result in access-denials that will make users unhappy. - string check_dir = extension != string.Empty ? FileUtil.DeleteLastPathNameComponent(path) : path; - if (!Directory.Exists(check_dir)) - Directory.CreateDirectory(check_dir); - - // On OSX we've got replace/update dialog, for other platforms warn about deleting - // files in target folder. - if ((target == BuildTarget.iOS) && (Application.platform != RuntimePlatform.OSXEditor)) - if (!FolderIsEmpty(path) && !UserWantsToDeleteFiles(path)) - return false; - - EditorUserBuildSettings.SetBuildLocation(target, path); - return true; - } - - static bool FolderIsEmpty(string path) - { - if (!Directory.Exists(path)) - return true; - - return (Directory.GetDirectories(path).Length == 0) - && (Directory.GetFiles(path).Length == 0); - } - - static bool UserWantsToDeleteFiles(string path) - { - string text = - "WARNING: all files and folders located in target folder: '" + path + "' will be deleted by build process."; - return EditorUtility.DisplayDialog("Deleting existing files", text, "OK", "Cancel"); - } - - static bool IsMetroPlayer(BuildTarget target) - { - return target == BuildTarget.WSAPlayer; - } - } - } -} diff --git a/Editor/Mono/BuildPlayerWindowPublish.cs b/Editor/Mono/BuildPlayerWindowPublish.cs deleted file mode 100644 index 24288e0b42..0000000000 --- a/Editor/Mono/BuildPlayerWindowPublish.cs +++ /dev/null @@ -1,308 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditor.PackageManager; - -namespace UnityEditor -{ - public partial class BuildPlayerWindow : EditorWindow - { - enum PackmanOperationType : uint - { - None = 0, - List, - Add, - Remove, - Search, - Outdated - } - - private long getCurrentVersionOperationId = -1; - private long getLatestVersionOperationId = -1; - bool isVersionInitialized = false; - - private long packmanOperationId = -1; - - - private PackmanOperationType packmanOperationType = PackmanOperationType.None; - private bool packmanOperationRunning = false; - - private string xiaomiPackageName = "com.unity.xiaomi"; - private string currentXiaomiPackageVersion = ""; - private string latestXiaomiPackageVersion = ""; - - private bool xiaomiPackageInstalled = false; - - string CurrentXiaomiPackageId - { - get - { - return xiaomiPackageName + "@" + currentXiaomiPackageVersion; - } - } - - string LatestXiaomiPackageId - { - get - { - return xiaomiPackageName + "@" + latestXiaomiPackageVersion; - } - } - - class PublishStyles - { - public const int kIconSize = 32; - public const int kRowHeight = 36; - public GUIContent xiaomiIcon = EditorGUIUtility.IconContent("BuildSettings.Xiaomi"); - public GUIContent learnAboutXiaomiInstallation = EditorGUIUtility.TrTextContent("Installation and Setup"); - public GUIContent publishTitle = EditorGUIUtility.TrTextContent("SDKs for App Stores", "Integrations with 3rd party app stores"); - } - private PublishStyles publishStyles = null; - - private void AndroidPublishGUI() - { - if (publishStyles == null) - publishStyles = new PublishStyles(); - - GUILayout.BeginVertical(); - GUILayout.Label(publishStyles.publishTitle, styles.title); - - // Show Xiaomi UI. - using (new EditorGUILayout.HorizontalScope(styles.box, new GUILayoutOption[] { GUILayout.Height(PublishStyles.kRowHeight) })) - { - GUILayout.BeginVertical(); - GUILayout.Space(3); // fix top padding for box style - - GUILayout.BeginHorizontal(); - GUILayout.Space(4); // left padding - - // icon - GUILayout.BeginVertical(); - GUILayout.Space((PublishStyles.kRowHeight - PublishStyles.kIconSize) / 2); - GUILayout.Label(publishStyles.xiaomiIcon, new GUILayoutOption[] { GUILayout.Width(PublishStyles.kIconSize), GUILayout.Height(PublishStyles.kIconSize) }); - GUILayout.EndVertical(); - - // label - GUILayout.BeginVertical(); - GUILayout.FlexibleSpace(); - GUILayout.Label("Xiaomi Mi Game Center"); - GUILayout.FlexibleSpace(); - GUILayout.EndVertical(); - - // link - GUILayout.FlexibleSpace(); // right justify text - GUILayout.BeginVertical(); - GUILayout.FlexibleSpace(); - XiaomiPackageControlGUI(); - GUILayout.FlexibleSpace(); - GUILayout.EndVertical(); - - GUILayout.Space(4); // right padding - GUILayout.EndHorizontal(); - - GUILayout.EndVertical(); - } - - GUILayout.EndVertical(); - } - - private void XiaomiPackageControlGUI() - { - EditorGUI.BeginDisabledGroup(!isVersionInitialized || packmanOperationRunning); - - if (!xiaomiPackageInstalled) - { - if (GUILayout.Button("Add", GUILayout.Width(60))) - { - if (packmanOperationRunning) - return; - - NativeStatusCode code = NativeClient.Add(out packmanOperationId, LatestXiaomiPackageId); - if (code == NativeStatusCode.Error) - { - Debug.LogError("Add " + LatestXiaomiPackageId + " error, please add it again."); - return; - } - packmanOperationType = PackmanOperationType.Add; - System.Console.WriteLine("Add: OperationID " + packmanOperationId + " for " + LatestXiaomiPackageId); - packmanOperationRunning = true; - } - } - else - { - GUILayout.BeginHorizontal(); - if (!string.IsNullOrEmpty(latestXiaomiPackageVersion) && currentXiaomiPackageVersion != latestXiaomiPackageVersion) - { - if (GUILayout.Button("Update", GUILayout.Width(60))) - { - if (packmanOperationRunning) - return; - - if (EditorUtility.DisplayDialog("Update Xiaomi SDK", "Are you sure you want to update to " + latestXiaomiPackageVersion + " ?", "Yes", "No")) - { - NativeStatusCode code = NativeClient.Add(out packmanOperationId, LatestXiaomiPackageId); - if (code == NativeStatusCode.Error) - { - Debug.LogError("Update " + LatestXiaomiPackageId + " error, please update it again."); - return; - } - packmanOperationType = PackmanOperationType.Add; - System.Console.WriteLine("Update: OperationID " + packmanOperationId + " for " + LatestXiaomiPackageId); - packmanOperationRunning = true; - } - } - } - if (GUILayout.Button("Remove", GUILayout.Width(60))) - { - if (packmanOperationRunning) - return; - - NativeStatusCode code = NativeClient.Remove(out packmanOperationId, CurrentXiaomiPackageId); - if (code == NativeStatusCode.Error) - { - Debug.LogError("Remove " + CurrentXiaomiPackageId + " error, please remove it again."); - return; - } - packmanOperationType = PackmanOperationType.Remove; - System.Console.WriteLine("Remove: OperationID " + packmanOperationId + " for " + CurrentXiaomiPackageId); - packmanOperationRunning = true; - } - GUILayout.EndHorizontal(); - } - - EditorGUI.EndDisabledGroup(); - } - - bool CheckXiaomiPackageVersions() - { - if (isVersionInitialized) - return true; - - NativeStatusCode getCurrentVersionOperationStatus; - if (getCurrentVersionOperationId < 0) - getCurrentVersionOperationStatus = NativeClient.List(out getCurrentVersionOperationId); - else - getCurrentVersionOperationStatus = NativeClient.GetOperationStatus(getCurrentVersionOperationId); - - // Reset and return false if it fails with StatusCode.Error or Status.NotFound. - if (getCurrentVersionOperationStatus > NativeStatusCode.Done) - { - getCurrentVersionOperationId = -1; - return false; - } - - NativeStatusCode getLatestVersionOperationStatus; - if (getLatestVersionOperationId < 0) - getLatestVersionOperationStatus = NativeClient.Search(out getLatestVersionOperationId, xiaomiPackageName); - else - getLatestVersionOperationStatus = NativeClient.GetOperationStatus(getLatestVersionOperationId); - - // Reset and return false if it fails with StatusCode.Error or Status.NotFound. - if (getLatestVersionOperationStatus > NativeStatusCode.Done) - { - getLatestVersionOperationId = -1; - return false; - } - - // Get version info if both operations are done. - if (getCurrentVersionOperationStatus == NativeStatusCode.Done && getLatestVersionOperationStatus == NativeStatusCode.Done) - { - CheckPackmanOperation(getCurrentVersionOperationId, PackmanOperationType.List); - CheckPackmanOperation(getLatestVersionOperationId, PackmanOperationType.Search); - - System.Console.WriteLine("Current xiaomi package version is " + (string.IsNullOrEmpty(currentXiaomiPackageVersion) ? "empty" : currentXiaomiPackageVersion)); - System.Console.WriteLine("Latest xiaomi package version is " + (string.IsNullOrEmpty(latestXiaomiPackageVersion) ? "empty" : latestXiaomiPackageVersion)); - - isVersionInitialized = true; - return true; - } - - return false; - } - - void Update() - { - // If initialization operations haven't been finished. - if (!CheckXiaomiPackageVersions()) - return; - - if (!packmanOperationRunning) - return; - - packmanOperationRunning = !CheckPackmanOperation(packmanOperationId, packmanOperationType); - } - - bool CheckPackmanOperation(long operationId, PackmanOperationType operationType) - { - NativeStatusCode statusCode = NativeClient.GetOperationStatus(operationId); - if (statusCode == NativeStatusCode.NotFound) - { - Debug.LogError("OperationID " + operationId + " Not Found"); - return true; - } - else if (statusCode == NativeStatusCode.Error) - { - Error error = NativeClient.GetOperationError(operationId); - Debug.LogError("OperationID " + operationId + " failed with Error: " + error); - return true; - } - else if (statusCode == NativeStatusCode.InProgress || statusCode == NativeStatusCode.InQueue) - { - return false; - } - else if (statusCode == NativeStatusCode.Done) - { - System.Console.WriteLine("OperationID " + operationId + " Done"); - switch (operationType) - { - case PackmanOperationType.List: - ExtractCurrentXiaomiPackageInfo(operationId); - break; - case PackmanOperationType.Add: - currentXiaomiPackageVersion = latestXiaomiPackageVersion; - xiaomiPackageInstalled = true; - break; - case PackmanOperationType.Remove: - currentXiaomiPackageVersion = ""; - xiaomiPackageInstalled = false; - break; - case PackmanOperationType.Search: - ExtractLatestXiaomiPackageInfo(operationId); - break; - default: - System.Console.WriteLine("Type " + operationType + " Not Supported"); - break; - } - return true; - } - - return true; - } - - void ExtractCurrentXiaomiPackageInfo(long operationId) - { - // Get the package list to find if xiaomi package has been installed. - OperationStatus operationStatus = NativeClient.GetListOperationData(operationId); - foreach (var package in operationStatus.packageList) - { - if (package.packageId.StartsWith(xiaomiPackageName)) - { - xiaomiPackageInstalled = true; - currentXiaomiPackageVersion = package.version; - } - } - } - - void ExtractLatestXiaomiPackageInfo(long operationId) - { - var packageList = NativeClient.GetSearchOperationData(operationId); - foreach (var package in packageList) - { - latestXiaomiPackageVersion = package.version; - } - } - } -} diff --git a/Editor/Mono/BuildTarget.cs b/Editor/Mono/BuildTarget.cs deleted file mode 100644 index 861701029d..0000000000 --- a/Editor/Mono/BuildTarget.cs +++ /dev/null @@ -1,128 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; - -namespace UnityEditor -{ - // Target build platform. - // When adding new platform, read this first - https://confluence.hq.unity3d.com/display/DEV/Adding+new+platform - // When removing platform, read this first - https://confluence.hq.unity3d.com/display/DEV/Removing+platform - [NativeType("Runtime/Serialize/SerializationMetaFlags.h")] - public enum BuildTarget - { - // Build an OS X standalone (universal build, with x86_64 currently supported). - StandaloneOSX = 2, - - [System.Obsolete("Use StandaloneOSX instead (UnityUpgradable) -> StandaloneOSX", true)] - StandaloneOSXUniversal = 2, - - [System.Obsolete("StandaloneOSXIntel has been removed in 2017.3")] - StandaloneOSXIntel = 4, - - // Build a Windows standalone. - StandaloneWindows = 5, - - // *undocumented* - [System.Obsolete("WebPlayer has been removed in 5.4", true)] - WebPlayer = 6, - - // *undocumented* - [System.Obsolete("WebPlayerStreamed has been removed in 5.4", true)] - WebPlayerStreamed = 7, - - // Build an iOS player - iOS = 9, - - // *undocumented* - [System.Obsolete("PS3 has been removed in >=5.5")] - PS3 = 10, - - // *undocumented* - [System.Obsolete("XBOX360 has been removed in 5.5")] - XBOX360 = 11, - - // was StandaloneBroadcom = 12, - - // Build an Android .apk standalone app - Android = 13, - - // was StandaloneGLESEmu = 14, - // was StandaloneGLES20Emu = 15, - // was NaCl = 16, - - // Build a Linux standalone (i386 only). - StandaloneLinux = 17, - - // Build a Windows x86_64 standalone. - StandaloneWindows64 = 19, - - // *undocumented* - WebGL = 20, - - // *undocumented* - WSAPlayer = 21, - - // Build a Linux standalone (i386 only). - StandaloneLinux64 = 24, - - // Build a Linux standalone (i386/x86_64 universal). - StandaloneLinuxUniversal = 25, - - [System.Obsolete("Use WSAPlayer with Windows Phone 8.1 selected")] - WP8Player = 26, - - [System.Obsolete("StandaloneOSXIntel64 has been removed in 2017.3")] - StandaloneOSXIntel64 = 27, - - [System.Obsolete("BlackBerry has been removed in 5.4")] - BlackBerry = 28, - - // *undocumented* - Tizen = 29, - - /// Build a Vita Standalone - /// SA: BuildPipeline.BuildPlayer. - PSP2 = 30, - - /// Build a PS4 Standalone - /// SA: BuildPipeline.BuildPlayer. - PS4 = 31, - - /// Build a Unity PlayStation Mobile (PSM) application - /// SA: BuildPipeline.BuildPlayer. - [System.Obsolete("warning PSM has been removed in >= 5.3")] - PSM = 32, - - /// Build an Xbox One Standalone - /// SA: BuildPipeline.BuildPlayer. - XboxOne = 33, - - [System.Obsolete("SamsungTV has been removed in 2017.3")] - SamsungTV = 34, - - /// Build a Nintendo 3DS application - /// SA: BuildPipeline.BuildPlayer. - N3DS = 35, - - /// Build a Wii U player - [System.Obsolete("Wii U support was removed in 2018.1")] - WiiU = 36, - - tvOS = 37, - - Switch = 38, - - // obsolete identifiers. We're using different values so that ToString() works. - [System.Obsolete("Use iOS instead (UnityUpgradable) -> iOS", true)] - iPhone = -1, - [System.Obsolete("BlackBerry has been removed in 5.4")] - BB10 = -1, - [System.Obsolete("Use WSAPlayer instead (UnityUpgradable) -> WSAPlayer", true)] - MetroPlayer = -1, - - // *undocumented* - NoTarget = -2, - } -} diff --git a/Editor/Mono/BuildTargetGroup.cs b/Editor/Mono/BuildTargetGroup.cs deleted file mode 100644 index f030090315..0000000000 --- a/Editor/Mono/BuildTargetGroup.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; -using System; - -namespace UnityEditor -{ - // Build target group. - // ADD_NEW_PLATFORM_HERE - [NativeType(Header = "Editor/Src/BuildPipeline/BuildTargetPlatformSpecific.h")] - public enum BuildTargetGroup - { - // Unknown target. - Unknown = 0, - - // Mac/PC standalone target. - Standalone = 1, - - //*undocumented* - [Obsolete("WebPlayer was removed in 5.4, consider using WebGL", true)] - WebPlayer = 2, - - // Apple iOS target. - [Obsolete("Use iOS instead (UnityUpgradable) -> iOS", true)] - iPhone = 4, - - iOS = 4, - - // *undocumented* - [Obsolete("PS3 has been removed in >=5.5")] - PS3 = 5, - - // *undocumented* - [Obsolete("XBOX360 has been removed in 5.5")] - XBOX360 = 6, - - // Android target. - Android = 7, - - // was Broadcom = 8, - // was GLESEmu = 9, - // was GLES20Emu = 10, - // was NaCl = 11, - - WebGL = 13, - - WSA = 14, - - //*undocumented* - [Obsolete("Use WSA instead")] - Metro = 14, - - [Obsolete("Use WSA instead")] - WP8 = 15, - - //*undocumented* - [Obsolete("BlackBerry has been removed as of 5.4")] - BlackBerry = 16, - - Tizen = 17, - - /// Sony Playstation Vita target. - PSP2 = 18, - - /// Sony Playstation 4 target. - PS4 = 19, - - /// Unity Playstation Mobile target. - [Obsolete("warning PSM has been removed in >= 5.3")] - PSM = 20, - - /// Xbox One target. - XboxOne = 21, - - [Obsolete("SamsungTV has been removed as of 2017.3")] - SamsungTV = 22, - - /// Nintendo 3DS target. - N3DS = 23, - - [Obsolete("Wii U support was removed in 2018.1")] - WiiU = 24, - - tvOS = 25, - - Facebook = 26, - - Switch = 27, - } -} diff --git a/Editor/Mono/Burst/BurstCompilerService.bindings.cs b/Editor/Mono/Burst/BurstCompilerService.bindings.cs deleted file mode 100644 index 33a198b7bf..0000000000 --- a/Editor/Mono/Burst/BurstCompilerService.bindings.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using System; -using System.IO; -using UnityEngine.Bindings; -using System.Reflection; - -namespace Unity.Burst.LowLevel -{ - [NativeHeader("Runtime/Burst/Burst.h")] - [NativeHeader("Runtime/Burst/BurstDelegateCache.h")] - [StaticAccessor("BurstCompilerService::Get()", StaticAccessorType.Arrow)] - internal static partial class BurstCompilerService - { - [NativeMethod("Initialize")] - static extern string InitializeInternal(string path, ExtractCompilerFlags extractCompilerFlags); - - public static extern string GetDisassembly(MethodInfo m, string compilerOptions); - - [FreeFunction] - public static extern int CompileAsyncDelegateMethod(object delegateMethod, string compilerOptions); - [FreeFunction] - public unsafe static extern void* GetAsyncCompiledAsyncDelegateMethod(int userID); - - public static extern bool IsInitialized { get; } - } -} diff --git a/Editor/Mono/Burst/BurstCompilerService.cs b/Editor/Mono/Burst/BurstCompilerService.cs deleted file mode 100644 index 298d5e6c5c..0000000000 --- a/Editor/Mono/Burst/BurstCompilerService.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using System; -using System.IO; -using UnityEngine.Bindings; - -namespace Unity.Burst.LowLevel -{ - internal static partial class BurstCompilerService - { - public delegate bool ExtractCompilerFlags(Type jobType, out string flags); - - public static void Initialize(string folderRuntime, ExtractCompilerFlags extractCompilerFlags) - { - if (folderRuntime == null) throw new ArgumentNullException(nameof(folderRuntime)); - if (extractCompilerFlags == null) throw new ArgumentNullException(nameof(extractCompilerFlags)); - - if (!Directory.Exists(folderRuntime)) - { - Debug.LogError($"Unable to initialize the burst JIT compiler. The folder `{folderRuntime}` does not exist"); - return; - } - - var message = InitializeInternal(folderRuntime, extractCompilerFlags); - - if (!String.IsNullOrEmpty(message)) - Debug.LogError($"Unexpected error while trying to initialize the burst JIT compiler: {message}"); - } - } -} diff --git a/Editor/Mono/CSPreProcess.cs b/Editor/Mono/CSPreProcess.cs deleted file mode 100644 index 43e62f9e42..0000000000 --- a/Editor/Mono/CSPreProcess.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Diagnostics; -using System.IO; -using System; -using System.Linq; -using System.Text; -using UnityEditor.Scripting.Compilers; -using UnityEngine; -using UnityEditor.Modules; - -namespace UnityEditor -{ - internal class ManagedEditorCodeRebuilder - { - private static readonly char[] kNewlineChars = new[] { '\r', '\n' }; - - //called from native code. - static bool Run(out CompilerMessage[] messages, bool includeModules) - { - int exitcode; - messages = ParseResults(GetOutputStream(GetJamStartInfo(includeModules), out exitcode)); - return exitcode == 0; - } - - private static ProcessStartInfo GetJamStartInfo(bool includeModules) - { - StringBuilder moduleArgs = new StringBuilder(); - moduleArgs.Append("jam.pl LiveReloadableEditorAssemblies"); - if (includeModules) - { - foreach (string target in ModuleManager.GetJamTargets()) - moduleArgs.Append(" ").Append(target); - } - - return new ProcessStartInfo - { - WorkingDirectory = Unsupported.GetBaseUnityDeveloperFolder(), - RedirectStandardOutput = true, - RedirectStandardError = false, - //The only reason jam.pl exists is that I cannot figure out how to call jam.bat, or jam.exe directly. magic. - Arguments = moduleArgs.ToString(), - FileName = "perl", - }; - } - - private static CompilerMessage[] ParseResults(string text) - { - Console.Write(text); - var lines = text.Split(kNewlineChars, StringSplitOptions.RemoveEmptyEntries); - var prefix = Unsupported.GetBaseUnityDeveloperFolder(); - - var msgs = new MonoCSharpCompilerOutputParser().Parse(lines, false).ToList(); - for (var index = 0; index < msgs.Count; index++) - { - var msg = msgs[index]; - msg.file = Path.Combine(prefix, msg.file); - msgs[index] = msg; - } - return msgs.ToArray(); - } - - private static string GetOutputStream(ProcessStartInfo startInfo, out int exitCode) - { - startInfo.UseShellExecute = false; - startInfo.CreateNoWindow = true; - var p = new Process { StartInfo = startInfo }; - - // Read data asynchronously - var sbStandardOut = new StringBuilder(); - var sbStandardError = new StringBuilder(); - p.OutputDataReceived += (sender, data) => sbStandardOut.AppendLine(data.Data); - p.ErrorDataReceived += (sender, data) => sbStandardError.AppendLine(data.Data); - p.Start(); - if (startInfo.RedirectStandardError) - p.BeginErrorReadLine(); - else - p.BeginOutputReadLine(); - - // Wain until process is done - p.WaitForExit(); - - var output = startInfo.RedirectStandardError ? sbStandardError.ToString() : sbStandardOut.ToString(); - exitCode = p.ExitCode; - return output; - } - } -} diff --git a/Editor/Mono/Callbacks.cs b/Editor/Mono/Callbacks.cs deleted file mode 100644 index 980f29e149..0000000000 --- a/Editor/Mono/Callbacks.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; -using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [RequiredByNativeCode] - public abstract partial class CallbackOrderAttribute : Attribute - { - protected int m_CallbackOrder; - internal int callbackOrder { get {return m_CallbackOrder; } } - } - - [RequiredByNativeCode] - [System.Obsolete("PostProcessAttribute has been renamed to CallbackOrderAttribute.")] - public abstract partial class PostProcessAttribute : CallbackOrderAttribute - { - [System.Obsolete("PostProcessAttribute has been renamed. Use m_CallbackOrder of CallbackOrderAttribute.")] - protected int m_PostprocessOrder; - - [System.Obsolete("PostProcessAttribute has been renamed. Use callbackOrder of CallbackOrderAttribute.")] - internal int GetPostprocessOrder { get {return m_PostprocessOrder; } } - } - - namespace Callbacks - { - internal sealed partial class RegisterPluginsAttribute : CallbackOrderAttribute - { - public RegisterPluginsAttribute() { m_CallbackOrder = 1; } - public RegisterPluginsAttribute(int callbackOrder) { m_CallbackOrder = callbackOrder; } - } - - [RequiredByNativeCode] - public sealed partial class PostProcessBuildAttribute : CallbackOrderAttribute - { - public PostProcessBuildAttribute() { m_CallbackOrder = 1; } - public PostProcessBuildAttribute(int callbackOrder) { m_CallbackOrder = callbackOrder; } - } - - [RequiredByNativeCode] - public sealed partial class PostProcessSceneAttribute : CallbackOrderAttribute - { - private int m_version; - internal int version { get {return m_version; } } - - public PostProcessSceneAttribute() { m_CallbackOrder = 1; m_version = 0; } - - public PostProcessSceneAttribute(int callbackOrder) { m_CallbackOrder = callbackOrder; m_version = 0; } - - public PostProcessSceneAttribute(int callbackOrder, int version) { m_CallbackOrder = callbackOrder; m_version = version; } - } - - [RequiredByNativeCode] - public sealed partial class DidReloadScripts : CallbackOrderAttribute - { - public DidReloadScripts() { m_CallbackOrder = 1; } - - public DidReloadScripts(int callbackOrder) { m_CallbackOrder = callbackOrder; } - } - - // 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 - [RequiredByNativeCode] - public sealed partial class OnOpenAssetAttribute : CallbackOrderAttribute - { - public OnOpenAssetAttribute() { m_CallbackOrder = 1; } - public OnOpenAssetAttribute(int callbackOrder) { m_CallbackOrder = callbackOrder; } - } - } - - internal partial class Empty - { - internal static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) {} - internal static bool OnOpenAsset(int instanceID, int line) {return false; } - } -} diff --git a/Editor/Mono/ChangeTrackerHandle.bindings.cs b/Editor/Mono/ChangeTrackerHandle.bindings.cs deleted file mode 100644 index b415a0b992..0000000000 --- a/Editor/Mono/ChangeTrackerHandle.bindings.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/Utility/ChangeTracker.h")] - [RequiredByNativeCode] - internal struct ChangeTrackerHandle - { - IntPtr m_Handle; - - internal static ChangeTrackerHandle AcquireTracker(UnityEngine.Object obj) - { - if (obj == null) - throw new ArgumentNullException("Not a valid unity engine object"); - return new ChangeTrackerHandle() { m_Handle = Internal_AcquireTracker(obj) }; - } - - [FreeFunction("ChangeTrackerRegistry::AcquireTracker")] - private static extern IntPtr Internal_AcquireTracker(UnityEngine.Object o); - - internal void ReleaseTracker() - { - if (m_Handle == IntPtr.Zero) - throw new ArgumentNullException("Not a valid handle, has it been released already?"); - - Internal_ReleaseTracker(m_Handle); - m_Handle = IntPtr.Zero; - } - - [FreeFunction("ChangeTrackerRegistry::ReleaseTracker")] - private static extern void Internal_ReleaseTracker(IntPtr handle); - - // returns true if object changed since last poll - internal bool PollForChanges() - { - if (m_Handle == IntPtr.Zero) - throw new ArgumentNullException("Not a valid handle, has it been released already?"); - return Internal_PollChanges(m_Handle); - } - - [FreeFunction("ChangeTrackerRegistry::PollChanges")] - private static extern bool Internal_PollChanges(IntPtr handle); - - internal void ForceDirtyNextPoll() - { - if (m_Handle == IntPtr.Zero) - throw new ArgumentNullException("Not a valid handle, has it been released already?"); - Internal_ForceUpdate(m_Handle); - } - - [FreeFunction("ChangeTrackerRegistry::ForceUpdate")] - private static extern void Internal_ForceUpdate(IntPtr handle); - } -} diff --git a/Editor/Mono/CloudBuild/CloudBuild.cs b/Editor/Mono/CloudBuild/CloudBuild.cs deleted file mode 100644 index 191d3a8919..0000000000 --- a/Editor/Mono/CloudBuild/CloudBuild.cs +++ /dev/null @@ -1,182 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Collections.Generic; -using System.Diagnostics; -using UnityEngine; -using UnityEditor; -using UnityEditor.Utils; -using UnityEditor.Web; -using UnityEditorInternal; -using UnityEditor.Connect; - -namespace UnityEditor.CloudBuild -{ - [InitializeOnLoad] - internal class CloudBuild - { - static CloudBuild() - { - JSProxyMgr.GetInstance().AddGlobalObject("unity/cloudbuild", new CloudBuild()); - } - - public Dictionary> GetScmCandidates() - { - Dictionary> candidates = new Dictionary>(); - - Dictionary git = DetectGit(); - if (git != null) - { - candidates.Add("git", git); - } - Dictionary mercurial = DetectMercurial(); - if (mercurial != null) - { - candidates.Add("mercurial", mercurial); - } - - Dictionary subversion = DetectSubversion(); - if (subversion != null) - { - candidates.Add("subversion", subversion); - } - - Dictionary perforce = DetectPerforce(); - if (perforce != null) - { - candidates.Add("perforce", perforce); - } - return candidates; - } - - private Dictionary DetectGit() - { - Dictionary gitSettings = new Dictionary(); - - string url = RunCommand("git", "config --get remote.origin.url"); - if (String.IsNullOrEmpty(url)) - { - return null; - } - gitSettings.Add("url", url); - gitSettings.Add("branch", RunCommand("git", "rev-parse --abbrev-ref HEAD")); - gitSettings.Add("root", RemoveProjectDirectory(RunCommand("git", "rev-parse --show-toplevel"))); - return gitSettings; - } - - private Dictionary DetectMercurial() - { - Dictionary mercurialSettings = new Dictionary(); - - string url = RunCommand("hg", "paths default"); - if (String.IsNullOrEmpty(url)) - { - return null; - } - mercurialSettings.Add("url", url); - mercurialSettings.Add("branch", RunCommand("hg", "branch")); - mercurialSettings.Add("root", RemoveProjectDirectory(RunCommand("hg", "root"))); - return mercurialSettings; - } - - private Dictionary DetectSubversion() - { - Dictionary subversionSettings = new Dictionary(); - - string info = RunCommand("svn", "info"); - if (info == null) - { - return null; - } - string[] lines = info.Split(Environment.NewLine.ToCharArray()); - foreach (var s in lines) - { - string[] parts = s.Split(new char[] {':'}, 2); - if (parts.Length == 2) - { - if (parts[0].Equals("Repository Root")) - { - subversionSettings.Add("url", parts[1].Trim()); - } - - if (parts[0].Equals("URL")) - { - subversionSettings.Add("branch", parts[1].Trim()); - } - - if (parts[0].Equals("Working Copy Root Path")) - { - subversionSettings.Add("root", RemoveProjectDirectory(parts[1].Trim())); - } - } - } - if (!subversionSettings.ContainsKey("url")) - { - return null; - } - return subversionSettings; - } - - private Dictionary DetectPerforce() - { - Dictionary perforceSettings = new Dictionary(); - - string url = Environment.GetEnvironmentVariable("P4PORT"); - if (String.IsNullOrEmpty(url)) - { - return null; - } - perforceSettings.Add("url", url); - - string client = Environment.GetEnvironmentVariable("P4CLIENT"); - if (!String.IsNullOrEmpty(client)) - { - perforceSettings.Add("workspace", client); - } - return perforceSettings; - } - - private String RunCommand(string command, string arguments) - { - try - { - ProcessStartInfo startInfo = new ProcessStartInfo(command); - startInfo.Arguments = arguments; - Program program = new Program(startInfo); - program.Start(); - program.WaitForExit(); - if (program.ExitCode < 0) - { - return null; - } - var sb = new System.Text.StringBuilder(); - foreach (var s in program.GetStandardOutput()) - { - sb.AppendLine(s); - } - return sb.ToString().TrimEnd(Environment.NewLine.ToCharArray()); - } - catch (System.ComponentModel.Win32Exception) - { - // Problem executing, most likely Executable not found in path on Windows systems - return null; - } - } - - private String RemoveProjectDirectory(string workingDirectory) - { - string currentDirectory = Directory.GetCurrentDirectory(); - - // handle windows command line clients returning *nix like paths - if (currentDirectory.StartsWith(workingDirectory.Replace('/', '\\'))) - { - workingDirectory = workingDirectory.Replace('/', '\\'); - } - currentDirectory = currentDirectory.Replace(workingDirectory, ""); - return currentDirectory.Trim(Path.DirectorySeparatorChar); - } - } -} diff --git a/Editor/Mono/Collab/AssetAccess.cs b/Editor/Mono/Collab/AssetAccess.cs deleted file mode 100644 index a1253e1f89..0000000000 --- a/Editor/Mono/Collab/AssetAccess.cs +++ /dev/null @@ -1,128 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor.Collaboration -{ - internal static class AssetAccess - { - // Attempts to retrieve the Asset GUID within the Unity Object. - // Failure: returns false and the given 'assetGUID' is set to empty string. - // Success: returns true and updates 'assetGUID'. - public static bool TryGetAssetGUIDFromObject(UnityEngine.Object objectWithGUID, out string assetGUID) - { - if (objectWithGUID == null) - { - throw new ArgumentNullException("objectWithGuid"); - } - - bool success = false; - - if (objectWithGUID.GetType() == typeof(SceneAsset)) - { - success = TryGetAssetGUIDFromDatabase(objectWithGUID, out assetGUID); - } - else if (objectWithGUID.GetType() == typeof(GameObject)) - { - success = TryGetPrefabGUID(objectWithGUID, out assetGUID); - } - else - { - assetGUID = String.Empty; - } - return success; - } - - // Attempts to retrieve the Asset corresponding to the given GUID. - // Failure: returns false and the given 'asset' is set to null. - // Success: returns true and updates 'asset'. - public static bool TryGetAssetFromGUID(string assetGUID, out UnityEngine.Object asset) - { - if (assetGUID == null) - { - throw new ArgumentNullException("assetGUID"); - } - - bool success = false; - string objectPath = AssetDatabase.GUIDToAssetPath(assetGUID); - - if (objectPath == null) - { - asset = null; - } - else - { - asset = AssetDatabase.LoadMainAssetAtPath(objectPath); - success = (asset != null); - } - return success; - } - - // Expects the given 'gameObject' to have a 'PrefabType' which - // is either an 'instance' or straight prefab. - // Failure: assigns empty string to 'assetGUID', returns false. - // Success: assigns the retrieval of the GUID to 'assetGUID' and returns true. - private static bool TryGetPrefabGUID(UnityEngine.Object gameObject, out string assetGUID) - { - PrefabType prefabType = PrefabUtility.GetPrefabType(gameObject); - UnityEngine.Object prefabObject = null; - - if (prefabType == PrefabType.PrefabInstance) - { - prefabObject = PrefabUtility.GetPrefabParent(gameObject); - } - else if (prefabType == PrefabType.Prefab) - { - prefabObject = gameObject; - } - - bool success = false; - - if (prefabObject == null) - { - assetGUID = String.Empty; - } - else - { - success = TryGetAssetGUIDFromDatabase(prefabObject, out assetGUID); - } - return success; - } - - // Interacts with 'AssetDatabase' to retrieve 'objectWithGUID' path - // and in-turn uses this to access the GUID. - // Failure: assigns an empty string to 'assetGUID', returns false. - // Success: assigns the GUID result from 'AssetDatabase' to 'assetGUID' and returns true. - private static bool TryGetAssetGUIDFromDatabase(UnityEngine.Object objectWithGUID, out string assetGUID) - { - if (objectWithGUID == null) - { - throw new ArgumentNullException("objectWithGuid"); - } - - string _assetGUID = null; - string objectPath = AssetDatabase.GetAssetPath(objectWithGUID); - - if (!String.IsNullOrEmpty(objectPath)) - { - _assetGUID = AssetDatabase.AssetPathToGUID(objectPath); - } - - bool success = false; - if (String.IsNullOrEmpty(_assetGUID)) - { - assetGUID = String.Empty; - } - else - { - assetGUID = _assetGUID; - success = true; - } - return success; - } - } -} diff --git a/Editor/Mono/Collab/CloudBuildStatus.cs b/Editor/Mono/Collab/CloudBuildStatus.cs deleted file mode 100644 index 2cdd2e247d..0000000000 --- a/Editor/Mono/Collab/CloudBuildStatus.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using System.Runtime.InteropServices; -using UnityEngine.Scripting; - -namespace UnityEditor.Collaboration -{ - // Keep internal and undocumented until we expose more functionality - //*undocumented - [StructLayout(LayoutKind.Sequential)] - [UsedByNativeCode] - internal struct CloudBuildStatus - { - private string m_Platform; - private bool m_Complete; - private bool m_Successful; - - public string platform { get { return m_Platform; } } - public bool complete { get { return m_Complete; } } - public bool success { get { return m_Successful; } } - } -} diff --git a/Editor/Mono/Collab/Collab.bindings.cs b/Editor/Mono/Collab/Collab.bindings.cs deleted file mode 100644 index 59a9428f6f..0000000000 --- a/Editor/Mono/Collab/Collab.bindings.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditor.Collaboration -{ - [NativeHeader("Editor/Src/Collab/Collab.h")] - partial class Collab - { - [StaticAccessor("Collab::Get()", StaticAccessorType.Arrow)] - public static extern int GetRevisionsData( - bool withChanges, int startIndex, int numRevisions); - - [StaticAccessor("Collab::Get()", StaticAccessorType.Arrow)] - public static extern RevisionsData PopulateRevisionsData(IntPtr nativeData); - } -} diff --git a/Editor/Mono/Collab/Collab.cs b/Editor/Mono/Collab/Collab.cs deleted file mode 100644 index 86c2210281..0000000000 --- a/Editor/Mono/Collab/Collab.cs +++ /dev/null @@ -1,370 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.Scripting; -using UnityEditor; -using UnityEditor.Web; -using UnityEditorInternal; -using UnityEditor.Connect; -using UnityEditor.SceneManagement; - -namespace UnityEditor.Collaboration -{ - internal delegate void StateChangedDelegate(CollabInfo info); - internal delegate void ErrorDelegate(); - - [Flags] - internal enum CollabOperation : ulong - { - Noop = 0, - Publish = 1 << 0, - Update = 1 << 1, - Revert = 1 << 2, - GoBack = 1 << 3, - Restore = 1 << 4, - Diff = 1 << 5, - ConflictDiff = 1 << 6, - Exclude = 1 << 7, - Include = 1 << 8, - ChooseMine = 1 << 9, - ChooseTheirs = 1 << 10, - ExternalMerge = 1 << 11, - }; - - //*undocumented - // We want to raise this exception from Cpp code but it fails - //public class CollabException: Exception - //{ - // public CollabException(string message) : base(message) - // { - // } - //} - - [InitializeOnLoad] - internal partial class Collab - { - public event StateChangedDelegate StateChanged; - public event StateChangedDelegate RevisionUpdated; - public event StateChangedDelegate JobsCompleted; - public event ErrorDelegate ErrorOccurred; - public event ErrorDelegate ErrorCleared; - - private static Collab s_Instance; - private static bool s_IsFirstStateChange = true; - - [SerializeField] - public CollabFilters collabFilters = new CollabFilters(); - - public String projectBrowserSingleSelectionPath { get; set; } - - public String projectBrowserSingleMetaSelectionPath { get; set; } - - public string[] currentProjectBrowserSelection; - - [Flags] - public enum CollabStates : ulong - { - kCollabNone = 0, - kCollabLocal = 1, - - kCollabSynced = 1 << 1, - kCollabOutOfSync = 1 << 2, - kCollabIgnored = 1 << 3, - kCollabCheckedOutLocal = 1 << 4, - kCollabCheckedOutRemote = 1 << 5, - kCollabDeletedLocal = 1 << 6, - kCollabDeletedRemote = 1 << 7, - kCollabAddedLocal = 1 << 8, - kCollabAddedRemote = 1 << 9, - kCollabConflicted = 1 << 10, - kCollabMovedLocal = 1 << 11, - kCollabMovedRemote = 1 << 12, - kCollabUpdating = 1 << 13, - kCollabReadOnly = 1 << 14, - kCollabMetaFile = 1 << 15, - kCollabUseMine = 1 << 16, - kCollabUseTheir = 1 << 17, - kCollabMerged = 1 << 18, - kCollabPendingMerge = 1 << 19, - kCollabFolderMetaFile = 1 << 20, - KCollabContentChanged = 1 << 21, - KCollabContentConflicted = 1 << 22, - KCollabContentDeleted = 1 << 23, - - // always keep most significant - kCollabInvalidState = 1 << 30, - - kAnyLocalChanged = (kCollabAddedLocal | kCollabCheckedOutLocal | kCollabDeletedLocal | kCollabMovedLocal), - kAnyLocalEdited = (kCollabAddedLocal | kCollabCheckedOutLocal | kCollabMovedLocal) - }; - - internal enum CollabStateID { None, Uninitialized, Initialized }; - - public static string[] clientType = - { - "Cloud Server", - "Mock Server" - }; - - internal static string editorPrefCollabClientType = "CollabConfig_Client"; - - public static string GetProjectClientType() - { - var cvalue = EditorUserSettings.GetConfigValue(editorPrefCollabClientType); - return string.IsNullOrEmpty(cvalue) ? clientType[0] : cvalue; - } - - public static Collab instance - { - get - { - return s_Instance; - } - } - - static Collab() - { - s_Instance = new Collab(); - s_Instance.projectBrowserSingleSelectionPath = string.Empty; - s_Instance.projectBrowserSingleMetaSelectionPath = string.Empty; - JSProxyMgr.GetInstance().AddGlobalObject("unity/collab", s_Instance); - ObjectListArea.postAssetIconDrawCallback += CollabProjectHook.OnProjectWindowIconOverlay; - AssetsTreeViewGUI.postAssetIconDrawCallback += CollabProjectHook.OnProjectBrowserNavPanelIconOverlay; - InitializeSoftlocksViewController(); - CollabSettingsManager.statusNotifier[CollabSettingType.InProgressEnabled] += OnSettingStatusChanged; - CollabSettingsManager.statusNotifier[CollabSettingType.InProgressEnabled] += SoftlockViewController.Instance.softLockFilters.OnSettingStatusChanged; - } - - public static void OnSettingStatusChanged(CollabSettingType type, CollabSettingStatus status) - { - InitializeSoftlocksViewController(); - } - - public static bool InitializeSoftlocksViewController() - { - if (!CollabSettingsManager.IsAvailable(CollabSettingType.InProgressEnabled)) - return false; - - if (CollabSettingsManager.inProgressEnabled) - SoftlockViewController.Instance.TurnOn(); - else - SoftlockViewController.Instance.TurnOff(); - return true; - } - - - public void CancelJobWithoutException(int jobType) - { - try - { - CancelJobByType(jobType); - } - catch (Exception ex) - { - UnityEngine.Debug.Log("Cannot cancel job, reason:" + ex.Message); - } - } - - public CollabStates GetAssetState(string guid) - { - return (CollabStates)GetAssetStateInternal(guid); - } - - public CollabStates GetSelectedAssetState() - { - return (CollabStates)GetSelectedAssetStateInternal(); - } - - public void UpdateEditorSelectionCache() - { - var result = new List(); - - foreach (var elem in Selection.assetGUIDsDeepSelection) - { - var path = AssetDatabase.GUIDToAssetPath(elem); - result.Add(path); - - var meta = path + ".meta"; - if (File.Exists(meta)) - { - result.Add(meta); - } - } - currentProjectBrowserSelection = result.ToArray(); - } - - public CollabInfo GetCollabInfo() - { - return collabInfo; - } - - public static bool IsDiffToolsAvailable() - { - return InternalEditorUtility.GetAvailableDiffTools().Length > 0; - } - - public void SaveAssets() - { - AssetDatabase.SaveAssets(); - } - - public static void SwitchToDefaultMode() - { - bool in2D = EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D; - var sv = SceneView.lastActiveSceneView; - if (sv != null && sv.in2DMode != in2D) - { - sv.in2DMode = in2D; - } - } - - public void ShowInProjectBrowser(string filterString) - { - collabFilters.ShowInProjectBrowser(filterString); - } - - public PublishInfo GetChangesToPublish() - { - Change[] changes = GetChangesToPublishInternal(); - return new PublishInfo() - { - changes = changes, - filter = false - }; - } - - private static void OnStateChanged() - { - // register only once - if (s_IsFirstStateChange) - { - s_IsFirstStateChange = false; - UnityConnect.instance.StateChanged += OnUnityConnectStateChanged; - } - var handler = instance.StateChanged; - if (handler != null) - { - handler(instance.collabInfo); - } - } - - [RequiredByNativeCode] - private static void OnRevisionUpdated() - { - var handler = instance.RevisionUpdated; - if (handler != null) - { - handler(instance.collabInfo); - } - } - - [RequiredByNativeCode] - private static void SetCollabError() - { - var handler = instance.ErrorOccurred; - if (handler != null) - handler(); - } - - [RequiredByNativeCode] - private static void ClearCollabError() - { - var handler = instance.ErrorCleared; - if (handler != null) - handler(); - } - - private static void OnJobsCompleted() - { - var handler = instance.JobsCompleted; - if (handler != null) - { - handler(instance.collabInfo); - } - CollabTesting.OnJobsCompleted(); - } - - private static void PublishDialog(string changelist) - { - if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) - { - return; - } - - var dialog = CollabPublishDialog.ShowCollabWindow(changelist); - - if (dialog.Options.DoPublish) - Collab.instance.Publish(dialog.Options.Comments, true); - } - - private static void CannotPublishDialog(string infoMessage) - { - CollabCannotPublishDialog.ShowCollabWindow(infoMessage); - } - - private static void OnUnityConnectStateChanged(ConnectInfo state) - { - instance.SendNotification(); - } - - public static void OnProgressEnabledSettingStatusChanged(CollabSettingType type, CollabSettingStatus status) - { - if (type == CollabSettingType.InProgressEnabled && status == CollabSettingStatus.Available) - { - if (CollabSettingsManager.inProgressEnabled) - { - SoftlockViewController.Instance.softLockFilters.ShowInFavoriteSearchFilters(); - } - - CollabSettingsManager.statusNotifier[CollabSettingType.InProgressEnabled] -= OnProgressEnabledSettingStatusChanged; - } - } - - - [RequiredByNativeCode] - static void OnCollabEnabledForCurrentProject(bool enabled) - { - if (enabled) - { - instance.StateChanged += instance.collabFilters.OnCollabStateChanged; - instance.collabFilters.ShowInFavoriteSearchFilters(); - if (CollabSettingsManager.IsAvailable(CollabSettingType.InProgressEnabled)) - { - if (CollabSettingsManager.inProgressEnabled) - { - SoftlockViewController.Instance.softLockFilters.ShowInFavoriteSearchFilters(); - } - } - else - { - CollabSettingsManager.statusNotifier[CollabSettingType.InProgressEnabled] -= OnProgressEnabledSettingStatusChanged; - CollabSettingsManager.statusNotifier[CollabSettingType.InProgressEnabled] += OnProgressEnabledSettingStatusChanged; - } - } - else - { - instance.StateChanged -= instance.collabFilters.OnCollabStateChanged; - instance.collabFilters.HideFromFavoriteSearchFilters(); - SoftlockViewController.Instance.softLockFilters.HideFromFavoriteSearchFilters(); - CollabSettingsManager.statusNotifier[CollabSettingType.InProgressEnabled] -= OnProgressEnabledSettingStatusChanged; - - if (ProjectBrowser.s_LastInteractedProjectBrowser != null) - { - if (ProjectBrowser.s_LastInteractedProjectBrowser.Initialized() && ProjectBrowser.s_LastInteractedProjectBrowser.IsTwoColumns()) - { - int instanceID = AssetDatabase.GetMainAssetInstanceID("assets"); - ProjectBrowser.s_LastInteractedProjectBrowser.SetFolderSelection(new int[] { instanceID }, true); - } - ProjectBrowser.s_LastInteractedProjectBrowser.SetSearch(""); - ProjectBrowser.s_LastInteractedProjectBrowser.Repaint(); - } - } - } - }; -} diff --git a/Editor/Mono/Collab/CollabAnalytics.cs b/Editor/Mono/Collab/CollabAnalytics.cs deleted file mode 100644 index 299ad61831..0000000000 --- a/Editor/Mono/Collab/CollabAnalytics.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.Scripting; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor.Collaboration -{ - internal static class CollabAnalytics - { - [Serializable] - private struct CollabUserActionAnalyticsEvent - { - public string category; - public string action; - } - - public static void SendUserAction(string category, string action) - { - EditorAnalytics.SendCollabUserAction(new CollabUserActionAnalyticsEvent() { category = category, action = action }); - } - - public static string historyCategoryString = "History"; - }; -} diff --git a/Editor/Mono/Collab/CollabChange.cs b/Editor/Mono/Collab/CollabChange.cs deleted file mode 100644 index 5661d3b70a..0000000000 --- a/Editor/Mono/Collab/CollabChange.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using System.Runtime.InteropServices; - -namespace UnityEditor.Collaboration -{ - // Keep internal and undocumented until we expose more functionality - //*undocumented - [StructLayout(LayoutKind.Sequential)] - internal class Change - { - [Flags] - public enum RevertableStates : ulong - { - Revertable = 1 << 0, - NotRevertable = 1 << 1, - - Revertable_File = 1 << 2, - Revertable_Folder = 1 << 3, - Revertable_EmptyFolder = 1 << 4, - - NotRevertable_File = 1 << 5, - NotRevertable_Folder = 1 << 6, - NotRevertable_FileAdded = 1 << 7, - NotRevertable_FolderAdded = 1 << 8, - NotRevertable_FolderContainsAdd = 1 << 9, - - // do not exceed Javascript Number range - InvalidRevertableState = (ulong)1 << 31 - }; - - private string m_Path; - private Collab.CollabStates m_State; - private Change.RevertableStates m_RevertableState; - private string m_RelatedTo; - private string m_LocalStatus; - private string m_RemoteStatus; - private string m_ResolveStatus; - - private Change() {} - - public string path { get { return m_Path; } } - public System.UInt64 state { get { return (System.UInt64)m_State; } } - public bool isRevertable { get { return (m_RevertableState & Change.RevertableStates.Revertable) == Change.RevertableStates.Revertable; } } - public System.UInt64 revertableState { get { return (System.UInt64)m_RevertableState; } } - public string relatedTo { get { return m_RelatedTo; } } - - public bool isMeta { get { return (m_State & Collab.CollabStates.kCollabMetaFile) == Collab.CollabStates.kCollabMetaFile; } } - public bool isConflict { get { return (m_State & Collab.CollabStates.kCollabConflicted) == Collab.CollabStates.kCollabConflicted || (m_State & Collab.CollabStates.kCollabPendingMerge) == Collab.CollabStates.kCollabPendingMerge; } } - public bool isFolderMeta { get { return (m_State & Collab.CollabStates.kCollabFolderMetaFile) == Collab.CollabStates.kCollabFolderMetaFile; } } - public bool isResolved { get { return (m_State & Collab.CollabStates.kCollabUseMine) == Collab.CollabStates.kCollabUseMine || (m_State & Collab.CollabStates.kCollabUseTheir) == Collab.CollabStates.kCollabUseTheir || (m_State & Collab.CollabStates.kCollabMerged) == Collab.CollabStates.kCollabMerged; } } - - public string localStatus { get { return m_LocalStatus; } } - public string remoteStatus { get { return m_RemoteStatus; } } - public string resolveStatus { get { return m_ResolveStatus; } } - } - - internal class PublishInfo - { - public Change[] changes; - public bool filter; - } -} diff --git a/Editor/Mono/Collab/CollabChangeAction.cs b/Editor/Mono/Collab/CollabChangeAction.cs deleted file mode 100644 index 123f9bbb1e..0000000000 --- a/Editor/Mono/Collab/CollabChangeAction.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using System.Runtime.InteropServices; -using UnityEngine.Scripting; - -namespace UnityEditor.Collaboration -{ - // Keep internal and undocumented until we expose more functionality - //*undocumented - [StructLayout(LayoutKind.Sequential)] - [UsedByNativeCode] - internal struct ChangeAction - { - private string m_Path; - private string m_Action; - - public string path { get { return m_Path; } } - public string action { get { return m_Action; } } - } -} diff --git a/Editor/Mono/Collab/CollabDialogs.cs b/Editor/Mono/Collab/CollabDialogs.cs deleted file mode 100644 index 9d8735b3db..0000000000 --- a/Editor/Mono/Collab/CollabDialogs.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; -using UnityEditor.Web; -using UnityEditorInternal; -using UnityEditor.Connect; - -namespace UnityEditor.Collaboration -{ - internal struct PublishDialogOptions - { - public string Comments; - public bool DoPublish; - } - - internal class CollabPublishDialog : EditorWindow - { - public static CollabPublishDialog ShowCollabWindow(string changelist) - { - CollabPublishDialog dialog = ScriptableObject.CreateInstance(); - dialog.Changelist = changelist; - - var rect = new Rect(100, 100, 600, 225); - dialog.minSize = new Vector2(rect.width, rect.height); - dialog.maxSize = new Vector2(rect.width, rect.height); - dialog.position = rect; - dialog.ShowModal(); - - dialog.m_Parent.window.m_DontSaveToLayout = true; - - return dialog; - } - - static GUIContent DescribeChangesText = EditorGUIUtility.TrTextContent("Describe your changes here"); - static GUIContent ChangeAssetsText = EditorGUIUtility.TrTextContent("Changed assets:"); - static GUIContent PublishText = EditorGUIUtility.TrTextContent("Publish"); - static GUIContent CancelText = EditorGUIUtility.TrTextContent("Cancel"); - - public Vector2 scrollView; - public string Changelist; - - public CollabPublishDialog() - { - Options.Comments = ""; - } - - public void OnGUI() - { - GUILayout.BeginVertical(); - GUILayout.Label(DescribeChangesText); - Options.Comments = GUILayout.TextArea(Options.Comments, 1000, GUILayout.MinHeight(80)); - - - GUILayout.Label(ChangeAssetsText); - scrollView = EditorGUILayout.BeginScrollView(scrollView, false, false); - GUIStyle style = new GUIStyle(); - Vector2 textSize = style.CalcSize(new GUIContent(Changelist)); - EditorGUILayout.SelectableLabel(Changelist, EditorStyles.textField, GUILayout.ExpandHeight(true), GUILayout.MinHeight(textSize.y)); - EditorGUILayout.EndScrollView(); - - GUILayout.FlexibleSpace(); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - if (GUILayout.Button(CancelText)) - { - Options.DoPublish = false; - Close(); - } - - if (GUILayout.Button(PublishText)) - { - Options.DoPublish = true; - Close(); - } - - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - } - - public PublishDialogOptions Options; - }; - - internal class CollabCannotPublishDialog : EditorWindow - { - public static CollabCannotPublishDialog ShowCollabWindow(string infoMessage) - { - CollabCannotPublishDialog dialog = ScriptableObject.CreateInstance(); - dialog.InfoMessage = infoMessage; - - var rect = new Rect(100, 100, 600, 150); - dialog.minSize = new Vector2(rect.width, rect.height); - dialog.maxSize = new Vector2(rect.width, rect.height); - dialog.position = rect; - dialog.ShowModal(); - - dialog.m_Parent.window.m_DontSaveToLayout = true; - - return dialog; - } - - static GUIContent WarningText = EditorGUIUtility.TextContent(string.Format( - "Files that have been moved or in a changed folder cannot be selectively published, " + - "please use the Publish option in the collab window to publish all your changes.")); - static GUIContent IssuesText = EditorGUIUtility.TrTextContent("Issues:"); - static GUIContent AcceptText = EditorGUIUtility.TrTextContent("Accept"); - - public Vector2 scrollPosition; - public string InfoMessage; - - public void OnGUI() - { - GUILayout.BeginVertical(); - GUI.skin.label.wordWrap = true; - - GUILayout.BeginVertical(); - GUILayout.Label(WarningText); - - GUILayout.Label(IssuesText); - - scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); - GUIStyle warnStyle = new GUIStyle(); - warnStyle.normal.textColor = new Color(1f, 0.28f, 0f); - GUILayout.Label(string.Format(InfoMessage), warnStyle); - GUILayout.EndScrollView(); - - GUILayout.EndVertical(); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - if (GUILayout.Button(AcceptText)) - Close(); - GUILayout.EndHorizontal(); - - GUILayout.EndVertical(); - } - }; -} diff --git a/Editor/Mono/Collab/CollabEditorHooks.cs b/Editor/Mono/Collab/CollabEditorHooks.cs deleted file mode 100644 index e5e379c2aa..0000000000 --- a/Editor/Mono/Collab/CollabEditorHooks.cs +++ /dev/null @@ -1,194 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using UnityEngine; -using UnityEditor.Web; -using UnityEditor.Connect; - -namespace UnityEditor.Collaboration -{ - // Display hooks for the main project window. Icons are overlayed to show the version control state. - internal class CollabProjectHook - { - // GUI callback for each item visible in the project window/object list area - public static void OnProjectWindowIconOverlay(Rect iconRect, string guid, bool isListMode) - { - DrawProjectBrowserIconOverlay(iconRect, guid, isListMode); - } - - // Draw icons in the Favorites/Asset Folder area of the project browser - public static void OnProjectBrowserNavPanelIconOverlay(Rect iconRect, string guid) - { - DrawProjectBrowserIconOverlay(iconRect, guid, true); - } - - private static void DrawProjectBrowserIconOverlay(Rect iconRect, string guid, bool isListMode) - { - if (Collab.instance.IsCollabEnabledForCurrentProject()) - { - Collab.CollabStates assetState = GetAssetState(guid); - Overlay.DrawOverlays(assetState, iconRect, isListMode); - } - } - - public static Collab.CollabStates GetAssetState(String assetGuid) - { - if (!Collab.instance.IsCollabEnabledForCurrentProject()) - { - return Collab.CollabStates.kCollabNone; - } - - Collab.CollabStates assetState = Collab.instance.GetAssetState(assetGuid); - return assetState; - } - } - - internal class Overlay - { - public const double k_OverlaySizeOnSmallIcon = 0.6; - public const double k_OverlaySizeOnLargeIcon = 0.35; - - private static readonly Dictionary s_Overlays = new Dictionary(); - - protected static void LoadOverlays() - { - // Order of priority must match GetLocalStatus (CollabClient.h) - s_Overlays.Clear(); - s_Overlays.Add(Collab.CollabStates.kCollabIgnored, EditorGUIUtility.IconContent("CollabExclude Icon")); - s_Overlays.Add(Collab.CollabStates.kCollabConflicted, EditorGUIUtility.IconContent("CollabConflict Icon")); - s_Overlays.Add(Collab.CollabStates.kCollabPendingMerge, EditorGUIUtility.IconContent("CollabConflict Icon")); - s_Overlays.Add(Collab.CollabStates.kCollabMovedLocal, EditorGUIUtility.IconContent("CollabMoved Icon")); - s_Overlays.Add(Collab.CollabStates.kCollabCheckedOutLocal | Collab.CollabStates.kCollabMovedLocal, EditorGUIUtility.IconContent("CollabMoved Icon")); - s_Overlays.Add(Collab.CollabStates.kCollabCheckedOutLocal, EditorGUIUtility.IconContent("CollabEdit Icon")); - s_Overlays.Add(Collab.CollabStates.kCollabAddedLocal, EditorGUIUtility.IconContent("CollabCreate Icon")); - s_Overlays.Add(Collab.CollabStates.kCollabDeletedLocal, EditorGUIUtility.IconContent("CollabDeleted Icon")); - - // The folder overlay should take precedence on the folder content's status. - s_Overlays.Add(Collab.CollabStates.KCollabContentConflicted, EditorGUIUtility.IconContent("CollabChangesConflict Icon")); - s_Overlays.Add(Collab.CollabStates.KCollabContentChanged, EditorGUIUtility.IconContent("CollabChanges Icon")); - s_Overlays.Add(Collab.CollabStates.KCollabContentDeleted, EditorGUIUtility.IconContent("CollabChangesDeleted Icon")); - } - - protected static bool AreOverlaysLoaded() - { - if (s_Overlays.Count == 0) - return false; - - foreach (var icon in s_Overlays.Values) - { - if (icon == null) - return false; - } - - return true; - } - - protected static Collab.CollabStates GetOverlayStateForAsset(Collab.CollabStates assetStates) - { - foreach (var state in s_Overlays.Keys) - { - if (HasState(assetStates, state)) - return state; - } - - return Collab.CollabStates.kCollabNone; - } - - protected static void DrawOverlayElement(Collab.CollabStates singleState, Rect itemRect) - { - GUIContent content; - if (s_Overlays.TryGetValue(singleState, out content)) - { - Texture overlay = content.image; - if (overlay != null) - { - GUI.DrawTexture(itemRect, overlay, ScaleMode.ScaleToFit); - } - } - } - - protected static bool HasState(Collab.CollabStates assetStates, Collab.CollabStates includesState) - { - return ((assetStates & includesState) == includesState); - } - - public static void DrawOverlays(Collab.CollabStates assetState, Rect itemRect, bool isListMode) - { - if (assetState == Collab.CollabStates.kCollabInvalidState || assetState == Collab.CollabStates.kCollabNone) - return; - - if (Event.current.type != EventType.Repaint) - return; - - if (!AreOverlaysLoaded()) - LoadOverlays(); - - var state = GetOverlayStateForAsset(assetState); - DrawOverlayElement(state, GetRectForTopRight(itemRect, GetScale(itemRect, isListMode))); - } - - // Return a new Rect with its width and height scaled, and converted to the ceiling. - public static Rect ScaleRect(Rect rect, double scale) - { - Rect scaledRect = new Rect(rect); - scaledRect.width = Convert.ToInt32(Math.Ceiling(rect.width * scale)); - scaledRect.height = Convert.ToInt32(Math.Ceiling(rect.height * scale)); - return scaledRect; - } - - public static double GetScale(Rect rect, bool isListMode) - { - double scale = k_OverlaySizeOnLargeIcon; - if (isListMode) - { - scale = k_OverlaySizeOnSmallIcon; - } - return scale; - } - - public static Rect GetRectForTopRight(Rect projectBrowserDrawRect, double scale) - { - Rect scaledRect = ScaleRect(projectBrowserDrawRect, scale); - scaledRect.x += (projectBrowserDrawRect.width - scaledRect.width); - return scaledRect; - } - - public static Rect GetRectForBottomRight(Rect projectBrowserDrawRect, double scale) - { - Rect scaledRect = ScaleRect(projectBrowserDrawRect, scale); - scaledRect.x += (projectBrowserDrawRect.width - scaledRect.width); - scaledRect.y += (projectBrowserDrawRect.height - scaledRect.height); - return scaledRect; - } - } - - internal static class TextureUtility - { - public static Texture2D LoadTextureFromApplicationContents(string path) - { - var tex = new Texture2D(2, 2); - - string resourcesPath = Path.Combine(Path.Combine(Path.Combine(EditorApplication.applicationContentsPath, "Resources"), "Collab"), "overlays"); - path = Path.Combine(resourcesPath, path); - - try - { - var fs = File.OpenRead(path); - var bytes = new byte[fs.Length]; - fs.Read(bytes, 0, (int)fs.Length); - if (!tex.LoadImage(bytes)) return null; - } - catch (Exception) - { - Debug.LogWarning("Collab Overlay Texture load fail, path: " + path); - return null; - } - - return tex; - } - } -} diff --git a/Editor/Mono/Collab/CollabFilters.cs b/Editor/Mono/Collab/CollabFilters.cs deleted file mode 100644 index e3b58c47d0..0000000000 --- a/Editor/Mono/Collab/CollabFilters.cs +++ /dev/null @@ -1,168 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor; -using UnityEngine; - -namespace UnityEditor.Collaboration -{ - internal abstract class AbstractFilters - { - [SerializeField] - private List m_Filters; - - public List filters { get { return m_Filters; } set { m_Filters = value; } } - - public abstract void InitializeFilters(); - - public bool ContainsSearchFilter(string name, string searchString) - { - foreach (var filter in filters) - { - if (filter[0] == name && filter[1] == searchString) - return true; - } - return false; - } - - public void ShowInFavoriteSearchFilters() - { - if (SavedSearchFilters.GetRootInstanceID() == 0) - { - SavedSearchFilters.AddInitializedListener(ShowInFavoriteSearchFilters); - return; - } - - SavedSearchFilters.RemoveInitializedListener(ShowInFavoriteSearchFilters); - int prevInstanceID = 0; - foreach (var filter in filters) - { - int instanceID = SavedSearchFilters.GetFilterInstanceID(filter[0], filter[1]); - if (instanceID == 0) - { - SearchFilter searchFilter = SearchFilter.CreateSearchFilterFromString(filter[1]); - if (prevInstanceID == 0) - prevInstanceID = SavedSearchFilters.AddSavedFilter(filter[0], searchFilter, 64); - else - prevInstanceID = SavedSearchFilters.AddSavedFilterAfterInstanceID(filter[0], searchFilter, 64, prevInstanceID, false); - } - } - - SavedSearchFilters.RefreshSavedFilters(); - - foreach (ProjectBrowser pb in ProjectBrowser.GetAllProjectBrowsers()) - { - pb.Repaint(); - } - } - - public void HideFromFavoriteSearchFilters() - { - SavedSearchFilters.RefreshSavedFilters(); - - foreach (ProjectBrowser pb in ProjectBrowser.GetAllProjectBrowsers()) - { - pb.Repaint(); - } - } - } - - internal class CollabFilters : AbstractFilters - { - [SerializeField] - private bool m_SearchFilterWasSet = false; - - public override void InitializeFilters() - { - filters = new List() { - new string[] { "All Modified", "v:any" }, - new string[] { "All Conflicts", "v:conflicted" }, - new string[] { "All Excluded" , "v:ignored"}, - }; - } - - public CollabFilters() - { - InitializeFilters(); - } - - public void ShowInProjectBrowser(string filterString) - { - ProjectBrowser browser = ProjectBrowser.s_LastInteractedProjectBrowser; - if (browser == null) - { - List browsers = ProjectBrowser.GetAllProjectBrowsers(); - if (browsers != null && browsers.Count > 0) - { - browser = browsers.First(); - } - } - - if (!string.IsNullOrEmpty(filterString)) - { - if (browser == null) - { - browser = EditorWindow.GetWindow() as ProjectBrowser; - ShowInFavoriteSearchFilters(); - browser.RepaintImmediately(); - } - - m_SearchFilterWasSet = true; - - string filterSearchString = "v:" + filterString; - if (browser.IsTwoColumns()) - { - foreach (var filter in filters) - { - if (filterSearchString == filter[1]) - { - int instanceID = SavedSearchFilters.GetFilterInstanceID(filter[0], filterSearchString); - if (instanceID > ProjectWindowUtil.k_FavoritesStartInstanceID) - { - browser.SetFolderSelection(new int[] { instanceID }, true); - break; - } - } - } - } - - browser.SetSearch(filterSearchString); - browser.Repaint(); - browser.Focus(); - } - else - { - if (m_SearchFilterWasSet) - { - if (browser != null) - { - if (browser.IsTwoColumns()) - { - int instanceID = AssetDatabase.GetMainAssetInstanceID("assets"); - browser.SetFolderSelection(new int[] { instanceID }, true); - } - browser.SetSearch(""); - browser.Repaint(); - } - } - m_SearchFilterWasSet = false; - } - } - - public void OnCollabStateChanged(CollabInfo info) - { - if (!info.ready || info.inProgress || info.maintenance) - return; - - foreach (ProjectBrowser pb in ProjectBrowser.GetAllProjectBrowsers()) - { - pb.RefreshSearchIfFilterContains("v:"); - } - } - } -} diff --git a/Editor/Mono/Collab/CollabHistoryWindow.cs b/Editor/Mono/Collab/CollabHistoryWindow.cs deleted file mode 100644 index 1066c06c29..0000000000 --- a/Editor/Mono/Collab/CollabHistoryWindow.cs +++ /dev/null @@ -1,307 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using UnityEditor.Collaboration; -using UnityEditor.Experimental.UIElements; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleEnums; -using UnityEngine; -using UnityScript.Steps; -using UnityEditor.Connect; - -namespace UnityEditor -{ - internal class CollabHistoryWindow : EditorWindow, ICollabHistoryWindow - { - const string kWindowTitle = "Collab History"; - const string kServiceUrl = "developer.cloud.unity3d.com"; - - [MenuItem("Window/Collab History", false, 2011)] - public static void ShowHistoryWindow() - { - EditorWindow.GetWindow(kWindowTitle); - } - - [MenuItem("Window/Collab History", true)] - public static bool ValidateShowHistoryWindow() - { - return Collab.instance.IsCollabEnabledForCurrentProject(); - } - - CollabHistoryPresenter m_Presenter; - Dictionary m_Views; - List m_HistoryItems = new List(); - HistoryState m_State; - VisualElement m_Container; - PagedListView m_Pager; - ScrollView m_HistoryView; - int m_ItemsPerPage = 5; - string m_InProgressRev; - bool m_RevisionActionsEnabled; - - public CollabHistoryWindow() - { - minSize = new Vector2(275, 50); - } - - public void OnEnable() - { - SetupGUI(); - name = "CollabHistory"; - - if (m_Presenter == null) - { - m_Presenter = new CollabHistoryPresenter(this, new CollabHistoryItemFactory(), new RevisionsService(Collab.instance, UnityConnect.instance)); - } - m_Presenter.OnWindowEnabled(); - } - - public void OnDisable() - { - m_Presenter.OnWindowDisabled(); - } - - public bool revisionActionsEnabled - { - get { return m_RevisionActionsEnabled; } - set - { - if (m_RevisionActionsEnabled == value) - return; - - m_RevisionActionsEnabled = value; - foreach (var historyItem in m_HistoryItems) - { - historyItem.RevisionActionsEnabled = value; - } - } - } - - public void SetupGUI() - { - var root = this.GetRootVisualContainer(); - root.AddStyleSheetPath("StyleSheets/CollabHistoryCommon.uss"); - if (EditorGUIUtility.isProSkin) - { - root.AddStyleSheetPath("StyleSheets/CollabHistoryDark.uss"); - } - else - { - root.AddStyleSheetPath("StyleSheets/CollabHistoryLight.uss"); - } - - m_Container = new VisualElement(); - m_Container.StretchToParentSize(); - root.Add(m_Container); - - m_Pager = new PagedListView() - { - name = "PagedElement", - pageSize = m_ItemsPerPage - }; - - var errorView = new StatusView() - { - message = "An Error Occurred", - icon = EditorGUIUtility.LoadIconRequired("Collab.Warning") as Texture, - }; - - var noInternetView = new StatusView() - { - message = "No Internet Connection", - icon = EditorGUIUtility.LoadIconRequired("Collab.NoInternet") as Texture, - }; - - var maintenanceView = new StatusView() - { - message = "Maintenance", - }; - - var loginView = new StatusView() - { - message = "Sign in to access Collaborate", - buttonText = "Sign in...", - callback = SignInClick, - }; - - var noSeatView = new StatusView() - { - message = "Ask your project owner for access to Unity Teams", - buttonText = "Learn More", - callback = NoSeatClick, - }; - - var waitingView = new StatusView() - { - message = "Updating...", - }; - - m_HistoryView = new ScrollView() { name = "HistoryContainer", showHorizontal = false}; - m_HistoryView.contentContainer.StretchToParentWidth(); - m_HistoryView.Add(m_Pager); - - m_Views = new Dictionary() - { - {HistoryState.Error, errorView}, - {HistoryState.Offline, noInternetView}, - {HistoryState.Maintenance, maintenanceView}, - {HistoryState.LoggedOut, loginView}, - {HistoryState.NoSeat, noSeatView}, - {HistoryState.Waiting, waitingView}, - {HistoryState.Ready, m_HistoryView} - }; - } - - public void UpdateState(HistoryState state, bool force) - { - if (state == m_State && !force) - return; - - switch (state) - { - case HistoryState.Ready: - UpdateHistoryView(m_Pager); - break; - case HistoryState.Disabled: - Close(); - return; - } - - m_State = state; - m_Container.Clear(); - m_Container.Add(m_Views[m_State]); - } - - public void UpdateRevisions(IEnumerable datas, string tip, int totalRevisions, int currentPage) - { - var elements = new List(); - var isFullDateObtained = false; // Has everything from this date been obtained? - m_HistoryItems.Clear(); - - if (datas != null) - { - DateTime currentDate = DateTime.MinValue; - foreach (var data in datas) - { - if (data.timeStamp.Date != currentDate.Date) - { - elements.Add(new CollabHistoryRevisionLine(data.timeStamp, isFullDateObtained)); - currentDate = data.timeStamp; - } - - var item = new CollabHistoryItem(data); - m_HistoryItems.Add(item); - - var container = new VisualContainer(); - container.style.flexDirection = FlexDirection.Row; - if (data.current) - { - isFullDateObtained = true; - container.AddToClassList("currentRevision"); - container.AddToClassList("obtainedRevision"); - } - else if (data.obtained) - { - container.AddToClassList("obtainedRevision"); - } - else - { - container.AddToClassList("absentRevision"); - } - // If we use the index as-is, the latest commit will become #1, but we want it to be last - container.Add(new CollabHistoryRevisionLine(data.index)); - container.Add(item); - elements.Add(container); - } - } - - m_HistoryView.scrollOffset = new Vector2(0, 0); - m_Pager.totalItems = totalRevisions; - m_Pager.curPage = currentPage; - m_Pager.items = elements; - } - - public string inProgressRevision - { - get { return m_InProgressRev; } - set - { - m_InProgressRev = value; - foreach (var historyItem in m_HistoryItems) - { - historyItem.SetInProgressStatus(value); - } - } - } - - public int itemsPerPage - { - set - { - if (m_ItemsPerPage == value) - return; - m_Pager.pageSize = m_ItemsPerPage; - } - } - - public PageChangeAction OnPageChangeAction - { - set { m_Pager.OnPageChanged = value; } - } - - public RevisionAction OnGoBackAction - { - set { CollabHistoryItem.s_OnGoBack = value; } - } - - public RevisionAction OnUpdateAction - { - set { CollabHistoryItem.s_OnUpdate = value; } - } - - public RevisionAction OnRestoreAction - { - set { CollabHistoryItem.s_OnRestore = value; } - } - - public ShowBuildAction OnShowBuildAction - { - set { CollabHistoryItem.s_OnShowBuild = value; } - } - - public Action OnShowServicesAction - { - set { CollabHistoryItem.s_OnShowServices = value; } - } - - void UpdateHistoryView(VisualElement history) - { - } - - void NoSeatClick() - { - var connection = UnityConnect.instance; - var env = connection.GetEnvironment(); - // Map environment to url - prod is special - if (env == "production") - env = ""; - else - env += "-"; - - var url = "https://" + env + kServiceUrl - + "/orgs/" + connection.GetOrganizationId() - + "/projects/" + connection.GetProjectName() - + "/unity-teams/"; - Application.OpenURL(url); - } - - void SignInClick() - { - UnityConnect.instance.ShowLogin(); - } - } -} diff --git a/Editor/Mono/Collab/CollabProgressInfo.cs b/Editor/Mono/Collab/CollabProgressInfo.cs deleted file mode 100644 index d4fdb5be4e..0000000000 --- a/Editor/Mono/Collab/CollabProgressInfo.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Runtime.InteropServices; - -namespace UnityEditor.Collaboration -{ - // Keep internal and undocumented until we expose more functionality - //*undocumented - [StructLayout(LayoutKind.Sequential)] - internal class ProgressInfo - { - public enum ProgressType : uint - { - None = 0, - Count = 1, - Percent = 2, - Both = 3 - }; - - private int m_JobId; - private string m_Title; - private string m_ExtraInfo; - private ProgressType m_ProgressType; - private int m_Percentage; - private int m_CurrentCount; - private int m_TotalCount; - private int m_Completed; - private int m_Cancelled; - private int m_CanCancel; - private string m_LastErrorString; - private ulong m_LastError; - - private ProgressInfo() {} - - public int jobId { get { return m_JobId; } } - public string title { get { return m_Title; } } - public string extraInfo { get { return m_ExtraInfo; } } - public int currentCount { get { return m_CurrentCount; } } - public int totalCount { get { return m_TotalCount; } } - public bool completed { get { return m_Completed != 0; } } - public bool cancelled { get { return m_Cancelled != 0; } } - public bool canCancel { get { return m_CanCancel != 0; } } - public string lastErrorString { get { return m_LastErrorString; } } - public ulong lastError { get { return m_LastError; } } - - public int percentComplete - { - get - { - if (m_ProgressType == ProgressType.Percent || m_ProgressType == ProgressType.Both) - { - return m_Percentage; - } - - if (m_ProgressType == ProgressType.Count) - { - if (m_TotalCount == 0) return 0; - return (m_CurrentCount * 100) / m_TotalCount; - } - return 0; - } - } - - public bool isProgressTypeCount { get { return (m_ProgressType == ProgressType.Count || m_ProgressType == ProgressType.Both); } } - public bool isProgressTypePercent { get { return (m_ProgressType == ProgressType.Percent || m_ProgressType == ProgressType.Both); } } - public bool errorOccured { get { return (m_LastError != 0); } } - } -} diff --git a/Editor/Mono/Collab/CollabRevision.cs b/Editor/Mono/Collab/CollabRevision.cs deleted file mode 100644 index c36b9d7f24..0000000000 --- a/Editor/Mono/Collab/CollabRevision.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Runtime.InteropServices; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditor.Collaboration -{ - // Keep internal and undocumented until we expose more functionality - //*undocumented - [StructLayout(LayoutKind.Sequential)] - [UsedByNativeCode] - internal struct Revision - { - [NativeName("m_CommitterName")] - private string m_AuthorName; - [NativeName("m_CommitterEmail")] - private string m_Author; - private string m_Comment; - private string m_RevisionID; - private string m_Reference; - private ulong m_TimeStamp; - // Whether this revision has been obtained by the client - private bool m_IsObtained; - private ChangeAction[] m_Entries; - private CloudBuildStatus[] m_BuildStatuses; - - public string authorName { get { return m_AuthorName; } } - public string author { get { return m_Author; } } - public string comment { get { return m_Comment; } } - public string revisionID { get { return m_RevisionID; } } - public string reference { get { return m_Reference; } } - public ulong timeStamp { get { return m_TimeStamp; } } - public bool isObtained { get { return m_IsObtained; } } - public ChangeAction[] entries { get { return m_Entries; } } - public CloudBuildStatus[] buildStatuses { get { return m_BuildStatuses; } } - } -} diff --git a/Editor/Mono/Collab/CollabRevisionsData.cs b/Editor/Mono/Collab/CollabRevisionsData.cs deleted file mode 100644 index 0c13f70010..0000000000 --- a/Editor/Mono/Collab/CollabRevisionsData.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Runtime.InteropServices; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditor.Collaboration -{ - // Keep internal and undocumented until we expose more functionality - //*undocumented - [StructLayout(LayoutKind.Sequential)] - [UsedByNativeCode] - internal struct RevisionsData - { - private int m_RevisionsInRepo; - private int m_RevisionOffset; - private int m_ReturnedRevisions; - private Revision[] m_Revisions; - - public int RevisionsInRepo {get { return m_RevisionsInRepo; }} - public int RevisionOffset {get { return m_RevisionOffset; }} - public int ReturnedRevisions {get { return m_ReturnedRevisions; }} - public Revision[] Revisions {get { return m_Revisions; }} - } -} diff --git a/Editor/Mono/Collab/CollabTesting.cs b/Editor/Mono/Collab/CollabTesting.cs deleted file mode 100644 index 2eb9a6c289..0000000000 --- a/Editor/Mono/Collab/CollabTesting.cs +++ /dev/null @@ -1,91 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor.Collaboration -{ - internal class CollabTesting - { - [Flags] - public enum AsyncState - { - NotWaiting = 0, - WaitForJobComplete, - WaitForChannelMessageHandled - } - - private static IEnumerator _enumerator = null; - private static Action _runAfter = null; - private static AsyncState _nextState = AsyncState.NotWaiting; - - public static Func> Tick - { - set { _enumerator = value().GetEnumerator(); } - } - - public static Action AfterRun - { - set { _runAfter = value; } - } - - public static bool IsRunning - { - get { return _enumerator != null; } - } - - public static void OnJobsCompleted() - { - OnAsyncSignalReceived(AsyncState.WaitForJobComplete); - } - - public static void OnChannelMessageHandled() - { - OnAsyncSignalReceived(AsyncState.WaitForChannelMessageHandled); - } - - private static void OnAsyncSignalReceived(AsyncState stateToRemove) - { - if ((_nextState & stateToRemove) == 0) - return; - - _nextState &= ~stateToRemove; - if (_nextState == AsyncState.NotWaiting) - Execute(); - } - - public static void Execute() - { - if (_enumerator == null) - return; - - if (Collab.instance.AnyJobRunning()) - return; - - try - { - if (!_enumerator.MoveNext()) - End(); - else - _nextState = _enumerator.Current; - } - catch (Exception) - { - Debug.LogError("Something Went wrong with the test framework itself"); - throw; - } - } - - public static void End() - { - if (_enumerator != null) - { - _runAfter(); - _enumerator = null; - } - } - } -} diff --git a/Editor/Mono/Collab/CollabToolbarWindow.cs b/Editor/Mono/Collab/CollabToolbarWindow.cs deleted file mode 100644 index f5ab47d9d2..0000000000 --- a/Editor/Mono/Collab/CollabToolbarWindow.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.Collaboration; -using UnityEditor.Web; -using UnityEditor.Connect; - -namespace UnityEditor -{ - [InitializeOnLoad] - internal class WebViewStatic : ScriptableSingleton - { - [SerializeField] - WebView m_WebView; - - static public WebView GetWebView() - { - return instance.m_WebView; - } - - static public void SetWebView(WebView webView) - { - instance.m_WebView = webView; - } - } - - - internal class CollabToolbarWindow : WebViewEditorStaticWindow, IHasCustomMenu - { - internal override WebView webView - { - get {return WebViewStatic.GetWebView(); } - set {WebViewStatic.SetWebView(value); } - } - - private const string kWindowName = "Unity Collab Toolbar"; - - private static long s_LastClosedTime; - private static CollabToolbarWindow s_CollabToolbarWindow; - - public static bool s_ToolbarIsVisible = false; - - const int kWindowWidth = 320; - const int kWindowHeight = 350; - - public static void CloseToolbarWindows() - { - // Make sure browser-side code finishes executing before we kill the window - EditorApplication.CallDelayed(CloseToolbarWindowsImmediately, 1f); - } - - public static void CloseToolbarWindowsImmediately() - { - foreach (CollabToolbarWindow window in Resources.FindObjectsOfTypeAll()) - window.Close(); - } - - [MenuItem("Window/Collab Toolbar", false /*IsValidateFunction*/, 2011, true /* IsInternalMenu */)] - public static CollabToolbarWindow ShowToolbarWindow() - { - //Create a new window if it do not exist - return GetWindow(false, kWindowName) as CollabToolbarWindow; - } - - [MenuItem("Window/Collab Toolbar", true /*IsValidateFunction*/)] - public static bool ValidateShowToolbarWindow() - { - return true; - } - - internal static bool ShowCenteredAtPosition(Rect buttonRect) - { - buttonRect.x -= kWindowWidth / 2; - // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time. - long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - bool justClosed = nowMilliSeconds < s_LastClosedTime + 50; - if (!justClosed) - { - // Method may have been triggered programmatically, without a user event to consume. - if (Event.current.type != EventType.Layout) - { - Event.current.Use(); - } - if (s_CollabToolbarWindow == null) - s_CollabToolbarWindow = CreateInstance() as CollabToolbarWindow; - var windowSize = new Vector2(kWindowWidth, kWindowHeight); - s_CollabToolbarWindow.initialOpenUrl = "file:///" + EditorApplication.userJavascriptPackagesPath + "unityeditor-collab-toolbar/dist/index.html"; - s_CollabToolbarWindow.Init(); - s_CollabToolbarWindow.ShowAsDropDown(buttonRect, windowSize); - s_CollabToolbarWindow.OnFocus(); - return true; - } - return false; - } - - // Receives HTML title - public void OnReceiveTitle(string title) - { - titleContent.text = title; - } - - public new void OnInitScripting() - { - base.OnInitScripting(); - } - - public override void OnEnable() - { - minSize = new Vector2(kWindowWidth, kWindowHeight); - maxSize = new Vector2(kWindowWidth, kWindowHeight); - initialOpenUrl = "file:///" + EditorApplication.userJavascriptPackagesPath + "unityeditor-collab-toolbar/dist/index.html"; - base.OnEnable(); - if (s_CollabToolbarWindow) - { - s_ToolbarIsVisible = true; - NotifyVisibility(s_ToolbarIsVisible); - } - } - - internal void OnDisable() - { - s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - if (s_CollabToolbarWindow) - { - s_ToolbarIsVisible = false; - NotifyVisibility(s_ToolbarIsVisible); - } - s_CollabToolbarWindow = null; - } - - public new void OnDestroy() - { - OnLostFocus(); - base.OnDestroy(); - } - } -} diff --git a/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs b/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs deleted file mode 100644 index 9344df8b71..0000000000 --- a/Editor/Mono/Collab/Presenters/CollabHistoryPresenter.cs +++ /dev/null @@ -1,276 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEditor.Connect; -using UnityEditor.Web; - -namespace UnityEditor.Collaboration -{ - internal class CollabHistoryPresenter - { - const int k_ItemsPerPage = 5; - ICollabHistoryWindow m_Window; - ICollabHistoryItemFactory m_Factory; - IRevisionsService m_Service; - ConnectInfo m_ConnectState; - CollabInfo m_CollabState; - bool m_IsCollabError; - int m_TotalRevisions; - int m_CurrentPage; - int m_RequestedPage; - bool m_FetchInProgress; - - BuildAccess m_BuildAccess; - string m_ProgressRevision; - public bool BuildServiceEnabled {get; set; } - - public CollabHistoryPresenter(ICollabHistoryWindow window, ICollabHistoryItemFactory factory, IRevisionsService service) - { - m_Window = window; - m_Factory = factory; - m_Service = service; - m_CurrentPage = 0; - m_BuildAccess = new BuildAccess(); - } - - public void OnWindowEnabled() - { - UnityConnect.instance.StateChanged += OnConnectStateChanged; - Collab.instance.StateChanged += OnCollabStateChanged; - Collab.instance.RevisionUpdated += OnCollabRevisionUpdated; - Collab.instance.JobsCompleted += OnCollabJobsCompleted; - Collab.instance.ErrorOccurred += OnCollabError; - Collab.instance.ErrorCleared += OnCollabErrorCleared; - EditorApplication.playModeStateChanged += OnPlayModeStateChanged; - m_Service.FetchRevisionsCallback += OnFetchRevisions; - - if (Collab.instance.IsConnected()) - { - m_ConnectState = UnityConnect.instance.GetConnectInfo(); - // Copy the initialized fields of the collab info, even if the instance hasn't connected yet. - } - // Copy the initialized fields of the collab info, even if the instance hasn't connected yet. - m_CollabState = Collab.instance.GetCollabInfo(); - - m_Window.revisionActionsEnabled = !EditorApplication.isPlayingOrWillChangePlaymode; - - // Setup window callbacks - m_Window.OnPageChangeAction = OnUpdatePage; - m_Window.OnUpdateAction = OnUpdate; - m_Window.OnRestoreAction = OnRestore; - m_Window.OnGoBackAction = OnGoBack; - m_Window.OnShowBuildAction = ShowBuildForCommit; - m_Window.OnShowServicesAction = ShowServicePage; - m_Window.itemsPerPage = k_ItemsPerPage; - - // Initialize data - UpdateBuildServiceStatus(); - var state = RecalculateState(); - // Only try to load the page if we're ready - if (state == HistoryState.Ready) - OnUpdatePage(m_CurrentPage); - m_Window.UpdateState(state, true); - } - - public void OnWindowDisabled() - { - UnityConnect.instance.StateChanged -= OnConnectStateChanged; - Collab.instance.StateChanged -= OnCollabStateChanged; - Collab.instance.RevisionUpdated -= OnCollabRevisionUpdated; - Collab.instance.JobsCompleted -= OnCollabJobsCompleted; - EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; - } - - private void OnConnectStateChanged(ConnectInfo state) - { - /* bool initialized - bool ready - bool online - bool loggedIn - bool workOffline - bool showLoginWindow - bool error - string lastErrorMsg - bool maintenance - */ - m_ConnectState = state; - - m_Window.UpdateState(RecalculateState(), false); - } - - private void OnCollabStateChanged(CollabInfo state) - { - /* bool ready - bool update - bool publish - bool inProgress - bool maintenance - bool conflict - bool dirty - bool refresh - bool seat - string tip - */ - - // Sometimes a collab state change will trigger even though everything is the same - if (CollabStatesEqual(m_CollabState, state)) - return; - - if (m_CollabState.tip != state.tip) - OnUpdatePage(m_CurrentPage); - - m_CollabState = state; - m_Window.UpdateState(RecalculateState(), false); - if (state.inProgress) - { - m_Window.inProgressRevision = m_ProgressRevision; - } - else - { - m_Window.inProgressRevision = null; - } - } - - private void OnCollabRevisionUpdated(CollabInfo state) - { - if (m_CollabState.tip != state.tip) - OnUpdatePage(m_CurrentPage); - } - - private void OnCollabJobsCompleted(CollabInfo state) - { - m_ProgressRevision = null; - } - - private void OnCollabError() - { - m_IsCollabError = true; - m_Window.UpdateState(RecalculateState(), false); - } - - private void OnCollabErrorCleared() - { - m_IsCollabError = false; - m_FetchInProgress = true; - m_Service.GetRevisions(m_CurrentPage * k_ItemsPerPage, k_ItemsPerPage); - m_Window.UpdateState(RecalculateState(), false); - } - - private void OnPlayModeStateChanged(PlayModeStateChange stateChange) - { - // If entering play mode, disable - if (stateChange == PlayModeStateChange.ExitingEditMode || - stateChange == PlayModeStateChange.EnteredPlayMode) - { - m_Window.revisionActionsEnabled = false; - } - // If exiting play mode, enable! - else if (stateChange == PlayModeStateChange.EnteredEditMode || - stateChange == PlayModeStateChange.ExitingPlayMode) - { - m_Window.revisionActionsEnabled = true; - } - } - - private HistoryState RecalculateState() - { - if (!m_ConnectState.online) - return HistoryState.Offline; - if (m_ConnectState.maintenance || m_CollabState.maintenance) - return HistoryState.Maintenance; - if (!m_ConnectState.loggedIn) - return HistoryState.LoggedOut; - if (!m_CollabState.seat) - return HistoryState.NoSeat; - if (!Collab.instance.IsCollabEnabledForCurrentProject()) - return HistoryState.Disabled; - if (!Collab.instance.IsConnected() || !m_CollabState.ready || m_FetchInProgress) - return HistoryState.Waiting; - if (m_ConnectState.error || m_IsCollabError) - return HistoryState.Error; - - return HistoryState.Ready; - } - - private static bool CollabStatesEqual(CollabInfo c1, CollabInfo c2) - { - return c1.ready == c2.ready && - c1.update == c2.update && - c1.publish == c2.publish && - c1.inProgress == c2.inProgress && - c1.maintenance == c2.maintenance && - c1.conflict == c2.conflict && - c1.dirty == c2.dirty && - c1.refresh == c2.refresh && - c1.seat == c2.seat && - c1.tip == c2.tip; - } - - // TODO: Eventually this can be a listener on the build service status - public void UpdateBuildServiceStatus() - { - foreach (var service in UnityConnectServiceCollection.instance.GetAllServiceInfos()) - { - if (service.name.Equals("Build")) - { - BuildServiceEnabled = service.enabled; - } - } - } - - public void ShowBuildForCommit(string revisionID) - { - m_BuildAccess.ShowBuildForCommit(revisionID); - } - - public void ShowServicePage() - { - m_BuildAccess.ShowServicePage(); - } - - public void OnUpdatePage(int page) - { - m_FetchInProgress = true; - m_Service.GetRevisions(page * k_ItemsPerPage, k_ItemsPerPage); - m_Window.UpdateState(RecalculateState(), false); - m_RequestedPage = page; - } - - private void OnFetchRevisions(RevisionsResult data) - { - m_FetchInProgress = false; - IEnumerable items = null; - if (data != null) - { - m_CurrentPage = m_RequestedPage; - m_TotalRevisions = data.RevisionsInRepo; - items = m_Factory.GenerateElements(data.Revisions, m_TotalRevisions, m_CurrentPage * k_ItemsPerPage, m_Service.tipRevision, m_Window.inProgressRevision, m_Window.revisionActionsEnabled, BuildServiceEnabled, m_Service.currentUser); - } - - // State must be recalculated prior to inserting items - m_Window.UpdateState(RecalculateState(), false); - m_Window.UpdateRevisions(items, m_Service.tipRevision, m_TotalRevisions, m_CurrentPage); - } - - private void OnRestore(string revisionId, bool updatetorevision) - { - m_ProgressRevision = revisionId; - Collab.instance.ResyncToRevision(revisionId); - } - - private void OnGoBack(string revisionId, bool updatetorevision) - { - m_ProgressRevision = revisionId; - Collab.instance.GoBackToRevision(revisionId, false); - } - - private void OnUpdate(string revisionId, bool updatetorevision) - { - m_ProgressRevision = revisionId; - Collab.instance.Update(revisionId, updatetorevision); - } - } -} - diff --git a/Editor/Mono/Collab/RevisionsService.cs b/Editor/Mono/Collab/RevisionsService.cs deleted file mode 100644 index dcef43ec85..0000000000 --- a/Editor/Mono/Collab/RevisionsService.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.Collaboration; -using UnityEditor.Connect; -using UnityEngine.Scripting; - -namespace UnityEditor.Collaboration -{ - delegate void RevisionsDelegate(RevisionsResult revisionsResult); - - internal class RevisionsResult - { - public List Revisions = new List(); - public int RevisionsInRepo = -1; - - public int Count {get { return Revisions.Count; }} - - public void Clear() - { - Revisions.Clear(); - RevisionsInRepo = -1; - } - } - - internal interface IRevisionsService - { - event RevisionsDelegate FetchRevisionsCallback; - void GetRevisions(int offset, int count); - string tipRevision { get; } - string currentUser { get; } - } - - internal class RevisionsService : IRevisionsService - { - public event RevisionsDelegate FetchRevisionsCallback; - protected Collab collab; - protected UnityConnect connect; - private static RevisionsService instance; - - public string tipRevision { get { return collab.collabInfo.tip; } } - public string currentUser { get { return connect.GetUserInfo().userName; } } - - public RevisionsService(Collab collabInstance, UnityConnect connectInstance) - { - collab = collabInstance; - connect = connectInstance; - instance = this; - } - - public void GetRevisions(int offset, int count) - { - // Only send down request for the desired data. - Collab.GetRevisionsData(true, offset, count); - } - - [RequiredByNativeCode] - private static void OnFetchRevisions(IntPtr nativeData) - { - RevisionsService service = instance; - if (service == null || service.FetchRevisionsCallback == null) - return; - - RevisionsResult history = null; - if (nativeData != IntPtr.Zero) - { - RevisionsData data = Collab.PopulateRevisionsData(nativeData); - history = new RevisionsResult(); - history.Revisions.AddRange(data.Revisions); - history.RevisionsInRepo = data.RevisionsInRepo; - } - - service.FetchRevisionsCallback(history); - } - } -} diff --git a/Editor/Mono/Collab/Softlocks/CollabSoftLocks.cs b/Editor/Mono/Collab/Softlocks/CollabSoftLocks.cs deleted file mode 100644 index a2c693bbeb..0000000000 --- a/Editor/Mono/Collab/Softlocks/CollabSoftLocks.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System.Runtime.InteropServices; -using UnityEngine.Scripting; - -namespace UnityEditor.Collaboration -{ - // Keep internal and undocumented until we expose more functionality - //*undocumented - [StructLayout(LayoutKind.Sequential)] - internal class SoftLock - { - private string m_UserID; - private string m_MachineID; - private string m_DisplayName; - private ulong m_TimeStamp; - private string m_Hash; - - private SoftLock() {} - - public string userID { get { return m_UserID; } } - public string machineID { get { return m_MachineID; } } - public string displayName { get { return m_DisplayName; } } - public ulong timeStamp { get { return m_TimeStamp; } } - public string hash { get { return m_Hash; } } - } -} - diff --git a/Editor/Mono/Collab/Softlocks/SoftlockData.cs b/Editor/Mono/Collab/Softlocks/SoftlockData.cs deleted file mode 100644 index 65d9876ef4..0000000000 --- a/Editor/Mono/Collab/Softlocks/SoftlockData.cs +++ /dev/null @@ -1,192 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEditor.Utils; -using UnityEditor.Web; - -namespace UnityEditor.Collaboration -{ - // Access and query the current set of softlock data. - internal static class SoftLockData - { - internal delegate void OnSoftlockUpdate(string[] assetGUIDs); - internal static OnSoftlockUpdate SoftlockSubscriber = null; - - // Invoked from C++ - public static void SetSoftlockChanges(string[] assetGUIDs) - { - if (null != SoftlockSubscriber) - { - SoftlockSubscriber(assetGUIDs); - } - } - - // Returns whether the given object has soft lock support - // (i.e. is tracked in the back-end for simultaneous changes). - // Note: Scene is supported, but isn't a Unity Object. - public static bool AllowsSoftLocks(UnityEngine.Object unityObject) - { - if (unityObject == null) - { - throw new ArgumentNullException("unityObject"); - } - - bool supportsSoftLocks = false; - if (unityObject.GetType().Equals(typeof(SceneAsset))) - { - supportsSoftLocks = true; - } - else - { - supportsSoftLocks = IsPrefab(unityObject); - } - return supportsSoftLocks; - } - - public static bool IsPrefab(UnityEngine.Object unityObject) - { - PrefabType prefabType = PrefabUtility.GetPrefabType(unityObject); - bool isPrefab = (prefabType == PrefabType.PrefabInstance || prefabType == PrefabType.Prefab); - return isPrefab; - } - - public static bool IsPrefab(string assetGUID) - { - bool isPrefab = false; - UnityEngine.Object unityObject; - if (AssetAccess.TryGetAssetFromGUID(assetGUID, out unityObject)) - { - isPrefab = IsPrefab(unityObject); - } - return isPrefab; - } - - private static bool TryHasSoftLocks(Scene scene, out bool hasSoftLocks) - { - string assetGUID = AssetDatabase.AssetPathToGUID(scene.path); - bool success = TryHasSoftLocks(assetGUID, out hasSoftLocks); - return success; - } - - // Soft locks are present when collab is enabled and other users are - // editing the given object. - // Failure: assigns false to 'hasSoftLocks', returns false. - // Success: assigns true or false to 'hasSoftLocks', returns true. - public static bool TryHasSoftLocks(UnityEngine.Object objectWithGUID, out bool hasSoftLocks) - { - string assetGuid = null; - AssetAccess.TryGetAssetGUIDFromObject(objectWithGUID, out assetGuid); - bool success = TryHasSoftLocks(assetGuid, out hasSoftLocks); - return success; - } - - public static bool TryHasSoftLocks(string assetGuid, out bool hasSoftLocks) - { - hasSoftLocks = false; - bool success = false; - int count = 0; - - if (TryGetSoftlockCount(assetGuid, out count)) - { - success = true; - hasSoftLocks = (count > 0); - } - return success; - } - - // Provides the number of additional users editing the given scene. - // Failure: assigns 0 to count, return false. - // Success: assigns a value in [0, n] to count, returns true. - public static bool TryGetSoftlockCount(Scene scene, out int count) - { - bool success = false; - count = 0; - - if (!scene.IsValid()) - { - return false; - } - string assetGUID = AssetDatabase.AssetPathToGUID(scene.path); - success = TryGetSoftlockCount(assetGUID, out count); - return success; - } - - // Provides the number of additional users editing the given object. - // Failure: assigns 0 to count, return false. - // Success: assigns a value in [0, n] to count, returns true. - public static bool TryGetSoftlockCount(UnityEngine.Object objectWithGUID, out int count) - { - string assetGUID = null; - AssetAccess.TryGetAssetGUIDFromObject(objectWithGUID, out assetGUID); - bool success = TryGetSoftlockCount(assetGUID, out count); - return success; - } - - // Provides the number of additional users editing the given 'assetGUID'. - // Failure: assigns 0 to count, return false. - // Success: assigns a value in [0, n] to count, returns true. - public static bool TryGetSoftlockCount(string assetGuid, out int count) - { - bool success = false; - count = 0; - List softLocks = null; - - if (TryGetLocksOnAssetGUID(assetGuid, out softLocks)) - { - count = softLocks.Count; - success = true; - } - return success; - } - - private static bool TryGetLocksOnObject(UnityEngine.Object objectWithGUID, out List softLocks) - { - bool success = false; - string assetGUID = null; - - if (AssetAccess.TryGetAssetGUIDFromObject(objectWithGUID, out assetGUID)) - { - success = TryGetLocksOnAssetGUID(assetGUID, out softLocks); - } - else - { - softLocks = new List(); - } - return success; - } - - // Provides a list of 'SoftLock' items, representing - // the additional users editing the given assetGUID. - // Failure: assigns empty list to 'softLocks', return false. - // Success: assigns the retrieved list to 'softLocks', return true. (May be empty). - public static bool TryGetLocksOnAssetGUID(string assetGuid, out List softLocks) - { - if (assetGuid == null) - { - throw new ArgumentNullException("assetGuid"); - } - - if (!Collab.instance.IsCollabEnabledForCurrentProject() || assetGuid.Length == 0) - { - softLocks = new List(); - return false; - } - - SoftLock[] _softlocks = Collab.instance.GetSoftLocks(assetGuid); - softLocks = new List(); - - for (int index = 0; index < _softlocks.Length; index++) - { - softLocks.Add(_softlocks[index]); - } - return true; - } - } -} - diff --git a/Editor/Mono/Collab/Softlocks/SoftlockFilter.cs b/Editor/Mono/Collab/Softlocks/SoftlockFilter.cs deleted file mode 100644 index e79b005962..0000000000 --- a/Editor/Mono/Collab/Softlocks/SoftlockFilter.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor; - -namespace UnityEditor.Collaboration -{ - internal class SoftLockFilters : AbstractFilters - { - public override void InitializeFilters() - { - filters = new List() { - new string[] { "All In Progress" , "s:inprogress"}, - }; - } - - public SoftLockFilters() - { - InitializeFilters(); - } - - public void OnSettingStatusChanged(CollabSettingType type, CollabSettingStatus status) - { - if (type == CollabSettingType.InProgressEnabled && (status == CollabSettingStatus.Available)) - { - if (Collab.instance.IsCollabEnabledForCurrentProject() && CollabSettingsManager.inProgressEnabled) - ShowInFavoriteSearchFilters(); - else - HideFromFavoriteSearchFilters(); - } - } - } -} diff --git a/Editor/Mono/Collab/Softlocks/SoftlockUIData.cs b/Editor/Mono/Collab/Softlocks/SoftlockUIData.cs deleted file mode 100644 index e0d8c1df20..0000000000 --- a/Editor/Mono/Collab/Softlocks/SoftlockUIData.cs +++ /dev/null @@ -1,207 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEditor.SceneManagement; -using UnityEditor.Web; - -namespace UnityEditor.Collaboration -{ - // Composes Softlock data into structures used by the UI. - internal static class SoftLockUIData - { - private static Dictionary s_ImageCache = new Dictionary(); - private static Dictionary s_ImageNameCache = new Dictionary(); - private const string kIconMipSuffix = " Icon"; - - public enum SectionEnum - { - None, - Inspector, - Scene, - ProjectBrowser - } - - #region General - - // Provides the names of all additional users editing the asset - // with the given 'assetGuid'. - // Defaults to an empty list. - public static List GetLocksNamesOnAsset(string assetGuid) - { - List softLocks = null; - List names = new List(); - - if (SoftLockData.TryGetLocksOnAssetGUID(assetGuid, out softLocks)) - { - foreach (SoftLock softLock in softLocks) - { - names.Add(softLock.displayName); - } - } - return names; - } - - #endregion - #region Scene - - // Provides the names of all additional users editing the scene. - // Defaults to an empty list. - public static List GetLocksNamesOnScene(Scene scene) - { - List names = GetLockNamesOnScenePath(scene.path); - return names; - } - - public static List GetLockNamesOnScenePath(string scenePath) - { - string assetGuid = AssetDatabase.AssetPathToGUID(scenePath); - List names = GetLocksNamesOnAsset(assetGuid); - return names; - } - - public static string GetSceneNameFromPath(string scenePath) - { - string name = ""; - if (null != scenePath) - { - name = scenePath; - } - return name; - } - - // Provides the names of all additional users editing each scene. - // Defaults to an empty list, and may contain empty sub-lists. - public static List> GetLockNamesOnScenes(List scenes) - { - List> namesByScene = new List>(); - - if (scenes == null) - { - return namesByScene; - } - - foreach (Scene scene in scenes) - { - List names = GetLocksNamesOnScene(scene); - namesByScene.Add(names); - } - return namesByScene; - } - - // For each iteration, returns the pair (scene name : list of other users' names). - public static IEnumerable>> GetLockNamesOnOpenScenes() - { - if (Collab.instance.IsCollabEnabledForCurrentProject()) - { - for (int sceneIndex = 0; sceneIndex < EditorSceneManager.sceneCount; sceneIndex++) - { - Scene scene = SceneManager.GetSceneAt(sceneIndex); - List names = GetLocksNamesOnScene(scene); - string sceneName = scene.name; - if (String.IsNullOrEmpty(sceneName)) - { - // Default for unnamed scenes. - sceneName = "Untitled"; - } - KeyValuePair> sceneData = new KeyValuePair>(sceneName, names); - yield return sceneData; - } - } - } - - public static int CountOfLocksOnOpenScenes() - { - int count = 0; - - foreach (KeyValuePair> sceneData in GetLockNamesOnOpenScenes()) - { - count += sceneData.Value.Count; - } - return count; - } - - #endregion - #region Game Object - - // The usernames of additional people editing the given 'objectWithGUID'. - // Defaults to an empty list. - public static List GetLockNamesOnObject(UnityEngine.Object objectWithGUID) - { - string assetGUID = null; - AssetAccess.TryGetAssetGUIDFromObject(objectWithGUID, out assetGUID); - List names = GetLocksNamesOnAsset(assetGUID); - return names; - } - - #endregion - #region Icons - - // The icon for the particular section in the editor. - // Defaults to null. - public static Texture GetIconForSection(SectionEnum section) - { - string iconName = IconNameForSection(section); - Texture texture = GetIconForName(iconName); - return texture; - } - - private static string IconNameForSection(SectionEnum section) - { - string iconName; - if (!s_ImageNameCache.TryGetValue(section, out iconName)) - { - switch (section) - { - case SectionEnum.Inspector: - case SectionEnum.Scene: - iconName = "SoftlockInline.png"; - break; - - case SectionEnum.ProjectBrowser: - iconName = String.Format("SoftlockProjectBrowser{0}", kIconMipSuffix); - break; - - default: - return null; - } - s_ImageNameCache.Add(section, iconName); - } - return iconName; - } - - private static Texture GetIconForName(string fileName) - { - if (String.IsNullOrEmpty(fileName)) - { - return null; - } - - Texture texture; - // Note: a previous texture may have been destroyed - // by the system on the c++ side. - if (!s_ImageCache.TryGetValue(fileName, out texture) || texture == null) - { - if (fileName.EndsWith(kIconMipSuffix)) - { - texture = EditorGUIUtility.FindTexture(fileName) as Texture; - } - else - { - texture = EditorGUIUtility.LoadIconRequired(fileName) as Texture; - } - s_ImageCache.Remove(fileName); - s_ImageCache.Add(fileName, texture); - } - return texture; - } - - #endregion - } -} - diff --git a/Editor/Mono/Collab/Softlocks/SoftlockViewController.cs b/Editor/Mono/Collab/Softlocks/SoftlockViewController.cs deleted file mode 100644 index baebb7c0a5..0000000000 --- a/Editor/Mono/Collab/Softlocks/SoftlockViewController.cs +++ /dev/null @@ -1,531 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.Collaboration; -using UnityEngine.SceneManagement; -using UnityEditor.SceneManagement; -using System; -using UnityEditor.Web; - -namespace UnityEditor -{ - // Displays the Softlocks UI in the various areas of the Editor. - internal class SoftlockViewController - { - private static SoftlockViewController s_Instance; - public GUIStyle k_Style = null; - public GUIStyle k_StyleEmpty = new GUIStyle(); // For tooltips only. - public GUIContent k_Content = null; - - // Stores UI strings for reuse and Editor (inspector) references to trigger - // a repaint when softlock data changes. - private SoftlockViewController.Cache m_Cache = null; - - private const string k_TooltipHeader = "Unpublished changes by:"; - private const string k_TooltipPrefabHeader = "Unpublished Prefab changes by:"; - private const string k_TooltipNamePrefix = " \n \u2022 "; // u2022 displays a • (bullet point) - - private SoftlockViewController() {} - ~SoftlockViewController() {} - - [SerializeField] - private SoftLockFilters m_SoftLockFilters = new SoftLockFilters(); - - public SoftLockFilters softLockFilters { get { return m_SoftLockFilters; } } - - public static SoftlockViewController Instance - { - get - { - if (s_Instance == null) - { - s_Instance = new SoftlockViewController(); - s_Instance.m_Cache = new Cache(); - } - return s_Instance; - } - } - - // Initialises dependencies. - public void TurnOn() - { - RegisterDataDelegate(); - RegisterDrawDelegates(); - Repaint(); - } - - public void TurnOff() - { - UnregisterDataDelegate(); - UnregisterDrawDelegates(); - } - - private void UnregisterDataDelegate() - { - SoftLockData.SoftlockSubscriber -= Instance.OnSoftlockUpdate; - } - - private void RegisterDataDelegate() - { - UnregisterDataDelegate(); - SoftLockData.SoftlockSubscriber += Instance.OnSoftlockUpdate; - } - - private void UnregisterDrawDelegates() - { - ObjectListArea.postAssetIconDrawCallback -= Instance.DrawProjectBrowserGridUI; - ObjectListArea.postAssetLabelDrawCallback -= Instance.DrawProjectBrowserListUI; - Editor.OnPostIconGUI -= Instance.DrawInspectorUI; - GameObjectTreeViewGUI.OnPostHeaderGUI -= Instance.DrawSceneUI; - } - - // Connects to the areas of the Editor that display softlocks. - private void RegisterDrawDelegates() - { - UnregisterDrawDelegates(); - ObjectListArea.postAssetIconDrawCallback += Instance.DrawProjectBrowserGridUI; - ObjectListArea.postAssetLabelDrawCallback += Instance.DrawProjectBrowserListUI; - AssetsTreeViewGUI.postAssetLabelDrawCallback += Instance.DrawSingleColumnProjectBrowserUI; - Editor.OnPostIconGUI += Instance.DrawInspectorUI; - GameObjectTreeViewGUI.OnPostHeaderGUI += Instance.DrawSceneUI; - } - - // Returns true when the 'editor' supports Softlock UI and the - // user has Collaborate permissions. - private bool HasSoftlockSupport(Editor editor) - { - if (!Collab.instance.IsCollabEnabledForCurrentProject() || editor == null || editor.targets.Length > 1) - { - return false; - } - - if (editor.target == null || !SoftLockData.AllowsSoftLocks(editor.target)) - { - return false; - } - - // Support Scene and Game object Inspector headers, not others like MaterialEditor. - bool hasSupport = true; - Type editorType = editor.GetType(); - - if (editorType != typeof(GameObjectInspector) && editorType != typeof(GenericInspector)) - { - hasSupport = false; - } - - return hasSupport; - } - - private bool HasSoftlocks(string assetGUID) - { - if (!Collab.instance.IsCollabEnabledForCurrentProject()) - { - return false; - } - - bool hasSoftLocks; - bool isValid = (SoftLockData.TryHasSoftLocks(assetGUID, out hasSoftLocks) && hasSoftLocks); - return isValid; - } - - // Redraws softlock UI associated with the given list of 'assetGUIDs'. - public void OnSoftlockUpdate(string[] assetGUIDs) - { - // Remove cached UI for the assetGUIDs before triggered a redraw. - m_Cache.InvalidateAssetGUIDs(assetGUIDs); - Repaint(); - } - - // Repaints all the areas where softlocks are displayed. - public void Repaint() - { - RepaintInspectors(); - RepaintSceneHierarchy(); - RepaintProjectBrowsers(); - } - - private void RepaintSceneHierarchy() - { - List sceneUIs = SceneHierarchyWindow.GetAllSceneHierarchyWindows(); - foreach (SceneHierarchyWindow sceneUI in sceneUIs) - { - sceneUI.Repaint(); - } - } - - private void RepaintInspectors() - { - foreach (Editor editor in m_Cache.GetEditors()) - { - // Does not repaint when editor is not visible, but the editor's - // "DockArea" tab will redraw either way. - editor.Repaint(); - } - } - - private void RepaintProjectBrowsers() - { - foreach (ProjectBrowser pb in ProjectBrowser.GetAllProjectBrowsers()) - { - pb.RefreshSearchIfFilterContains("s:"); - pb.Repaint(); - } - } - - // Draws in the Hierarchy header, left of the context menu. - public void DrawSceneUI(Rect availableRect, string scenePath) - { - string assetGUID = AssetDatabase.AssetPathToGUID(scenePath); - if (!HasSoftlocks(assetGUID)) - { - return; - } - - int lockCount; - SoftLockData.TryGetSoftlockCount(assetGUID, out lockCount); - - GUIContent content = GetGUIContent(); - content.image = SoftLockUIData.GetIconForSection(SoftLockUIData.SectionEnum.Scene); - content.text = GetDisplayCount(lockCount); - content.tooltip = Instance.GetTooltip(assetGUID); - - Vector2 contentSize = GetStyle().CalcSize(content); - Rect drawRect = new Rect(availableRect.position, contentSize); - const int kRightMargin = 4; - drawRect.x = (availableRect.width - drawRect.width) - kRightMargin; - EditorGUI.LabelField(drawRect, content); - } - - // Assigned as a callback to Editor.OnPostHeaderGUI - // Draws the Scene Inspector (Editor.cs) as well as the Game Object Inspector (GameObjectInspector.cs) - private void DrawInspectorUI(Editor editor, Rect drawRect) - { - if (!HasSoftlockSupport(editor)) - { - return; - } - - m_Cache.StoreEditor(editor); - string assetGUID = null; - AssetAccess.TryGetAssetGUIDFromObject(editor.target, out assetGUID); - - if (!HasSoftlocks(assetGUID)) - { - return; - } - - Texture icon = SoftLockUIData.GetIconForSection(SoftLockUIData.SectionEnum.ProjectBrowser); - if (icon != null) - { - DrawIconWithTooltips(drawRect, icon, assetGUID); - } - } - - // Assigned callback to ObjectListArea.OnPostAssetDrawDelegate. - // Draws either overtop of the project browser asset (when in grid view). - private void DrawProjectBrowserGridUI(Rect iconRect, string assetGUID, bool isListMode) - { - if (isListMode || !HasSoftlocks(assetGUID)) - { - return; - } - - Rect drawRect = Rect.zero; - Texture icon = SoftLockUIData.GetIconForSection(SoftLockUIData.SectionEnum.ProjectBrowser); - if (icon != null) - { - drawRect = Overlay.GetRectForBottomRight(iconRect, Overlay.k_OverlaySizeOnLargeIcon); - DrawIconWithTooltips(drawRect, icon, assetGUID); - } - } - - // Should draw only in listMode and expects 'drawRect' to be the designed space for the icon, - // and not the entire row. - private bool DrawProjectBrowserListUI(Rect drawRect, string assetGUID, bool isListMode) - { - if (!isListMode || !HasSoftlocks(assetGUID)) - { - return false; - } - - // center icon. - Rect iconRect = drawRect; - iconRect.width = drawRect.height; - iconRect.x = (float)Math.Round(drawRect.center.x - (iconRect.width / 2F)); - return DrawInProjectBrowserListMode(iconRect, assetGUID); - } - - // Expects 'drawRect' to be the available width of the row. - private bool DrawSingleColumnProjectBrowserUI(Rect drawRect, string assetGUID) - { - if (ProjectBrowser.s_LastInteractedProjectBrowser.IsTwoColumns() || !HasSoftlocks(assetGUID)) - { - return false; - } - - Rect iconRect = drawRect; - iconRect.width = drawRect.height; - float spacingFromEnd = (iconRect.width / 2F); - iconRect.x = (float)Math.Round(drawRect.xMax - iconRect.width - spacingFromEnd); - return DrawInProjectBrowserListMode(iconRect, assetGUID); - } - - private bool DrawInProjectBrowserListMode(Rect iconRect, string assetGUID) - { - Texture icon = SoftLockUIData.GetIconForSection(SoftLockUIData.SectionEnum.ProjectBrowser); - bool didDraw = false; - if (icon != null) - { - DrawIconWithTooltips(iconRect, icon, assetGUID); - didDraw = true; - } - return didDraw; - } - - private void DrawIconWithTooltips(Rect iconRect, Texture icon, string assetGUID) - { - GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit); - DrawTooltip(iconRect, GetTooltip(assetGUID)); - } - - private void DrawTooltip(Rect frame, string tooltip) - { - GUIContent content = GetGUIContent(); - content.tooltip = tooltip; - GUI.Label(frame, content, k_StyleEmpty); - } - - #region String Helpers - - // Returns a string formatted as a vertical list of names with a heading. - private string GetTooltip(string assetGUID) - { - string formattedText; - if (!m_Cache.TryGetTooltipForGUID(assetGUID, out formattedText)) - { - List softLockNames = SoftLockUIData.GetLocksNamesOnAsset(assetGUID); - string tooltipHeaderText = (SoftLockData.IsPrefab(assetGUID) ? k_TooltipPrefabHeader : k_TooltipHeader); - formattedText = tooltipHeaderText; - - foreach (string name in softLockNames) - { - formattedText += k_TooltipNamePrefix + name + " "; - } - m_Cache.StoreTooltipForGUID(assetGUID, formattedText); - } - return formattedText; - } - - // Retrieves a previously generated string from cache - // or creates a string displaying the given 'count' surrounded by brackets. - // e.g. "(0)" - private static string GetDisplayCount(int count) - { - string totalLocksText; - if (!Instance.m_Cache.TryGetDisplayCount(count, out totalLocksText)) - { - totalLocksText = count.ToString(); - Instance.m_Cache.StoreDisplayCount(count, totalLocksText); - } - return totalLocksText; - } - - // When the given 'text' exceeds the given 'width', out-of-bound characters - // are removed as well as a few more to display a trailing ellipsis. - // If 'text' does not exceed width, text is returned. - private string FitTextToWidth(string text, float width, GUIStyle style) - { - int characterCountVisible = style.GetNumCharactersThatFitWithinWidth(text, width); - if (characterCountVisible > 1 && characterCountVisible != text.Length) - { - string ellipsedText; - int characterLength = (characterCountVisible - 1); - if (!Instance.m_Cache.TryGetEllipsedNames(text, characterLength, out ellipsedText)) - { - ellipsedText = text.Substring(0, characterLength) + (" \u2026"); // 'horizontal ellipsis' (U+2026) is: ... - Instance.m_Cache.StoreEllipsedNames(text, ellipsedText, characterLength); - } - return ellipsedText; - } - return text; - } - - #endregion - #region GUI Content - - public GUIContent GetGUIContent() - { - if (k_Content == null) - { - k_Content = new GUIContent(); - } - - k_Content.tooltip = string.Empty; - k_Content.text = null; - k_Content.image = null; - - return k_Content; - } - - public GUIStyle GetStyle() - { - if (k_Style == null) - { - k_Style = new GUIStyle(EditorStyles.label); - k_Style.normal.background = null; - } - return k_Style; - } - - #endregion - - // Stores UI strings for reuse and Editors as WeakReferences. - private class Cache - { - private List m_EditorReferences = new List(); - private List m_CachedWeakReferences = new List(); - private static Dictionary s_CachedStringCount = new Dictionary(); - private Dictionary m_AssetGUIDToTooltip = new Dictionary(); - private Dictionary> m_NamesListToEllipsedNames = new Dictionary>(); - - public Cache() {} - - // Removes cached strings references by the given 'assetGUIDs'. - public void InvalidateAssetGUIDs(string[] assetGUIDs) - { - for (int index = 0; index < assetGUIDs.Length; index++) - { - string assetGUID = assetGUIDs[index]; - m_AssetGUIDToTooltip.Remove(assetGUID); - } - } - - // Failure: assigns empty string ("") to 'ellipsedNames', returns false. - // Success: assigns the cached string to 'ellipsedNames', returns true. - public bool TryGetEllipsedNames(string allNames, int characterLength, out string ellipsedNames) - { - Dictionary ellipsedVersions; - if (m_NamesListToEllipsedNames.TryGetValue(allNames, out ellipsedVersions)) - { - return ellipsedVersions.TryGetValue(characterLength, out ellipsedNames); - } - ellipsedNames = ""; - return false; - } - - // 'allNames' and 'characterLength' will be the keys to access the cached 'ellipsedNames' - // see TryGetEllipsedNames() for retrieval. - public void StoreEllipsedNames(string allNames, string ellipsedNames, int characterLength) - { - Dictionary ellipsedVersions; - if (!m_NamesListToEllipsedNames.TryGetValue(allNames, out ellipsedVersions)) - { - ellipsedVersions = new Dictionary(); - } - ellipsedVersions[characterLength] = ellipsedNames; - m_NamesListToEllipsedNames[allNames] = ellipsedVersions; - } - - // Failure: assigns empty string ("") to 'tooltipText', returns false. - // Success: assigns the cached string to 'tooltipText', returns true. - public bool TryGetTooltipForGUID(string assetGUID, out string tooltipText) - { - return m_AssetGUIDToTooltip.TryGetValue(assetGUID, out tooltipText); - } - - // 'assetGUID' will be the key to access the cached 'tooltipText' - // see TryGetTooltipForGUID() for retrieval. - public void StoreTooltipForGUID(string assetGUID, string tooltipText) - { - m_AssetGUIDToTooltip[assetGUID] = tooltipText; - } - - // Failure: assigns empty string ("") to 'displayText', returns false. - // Success: assigns the cached string to 'displayText', returns true. - public bool TryGetDisplayCount(int count, out string displayText) - { - return s_CachedStringCount.TryGetValue(count, out displayText); - } - - // 'count' will be the key to access the cached 'displayText' - // see TryGetDisplayCount() for retrieval. - public void StoreDisplayCount(int count, string displayText) - { - s_CachedStringCount.Add(count, displayText); - } - - // Contains at most the list of all previously given Editors - // via StoreEditor(). Garbage collected Editor(s) will be missing. - public List GetEditors() - { - List editors = new List(); - - for (int index = 0; index < m_EditorReferences.Count; index++) - { - WeakReference reference = m_EditorReferences[index]; - Editor editor = reference.Target as Editor; - - if (editor == null) - { - m_EditorReferences.RemoveAt(index); - m_CachedWeakReferences.Add(reference); - index--; - } - else - { - editors.Add(editor); - } - } - return editors; - } - - // Stores the Editor in a WeakReference. - public void StoreEditor(Editor editor) - { - bool canAdd = true; - - // Check for duplicates and purge any null targets. - for (int index = 0; canAdd && (index < m_EditorReferences.Count); index++) - { - WeakReference reference = m_EditorReferences[index]; - Editor storedEditor = reference.Target as Editor; - - if (storedEditor == null) - { - m_EditorReferences.RemoveAt(index); - m_CachedWeakReferences.Add(reference); - index--; - } - else if (storedEditor == editor) - { - canAdd = false; - break; - } - } - - if (canAdd) - { - WeakReference editorReference; - - // Reuse any old WeakReference if available. - if (m_CachedWeakReferences.Count > 0) - { - editorReference = m_CachedWeakReferences[0]; - m_CachedWeakReferences.RemoveAt(0); - } - else - { - editorReference = new WeakReference(null); - } - editorReference.Target = editor; - m_EditorReferences.Add(editorReference); - } - } - } - } -} - diff --git a/Editor/Mono/Collab/Views/BuildStatusButton.cs b/Editor/Mono/Collab/Views/BuildStatusButton.cs deleted file mode 100644 index 81b07cb62b..0000000000 --- a/Editor/Mono/Collab/Views/BuildStatusButton.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEditor.Collaboration; -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Collaboration -{ - internal class BuildStatusButton : Button - { - private readonly string iconPrefix = "Icons/Collab.Build"; - private readonly string iconSuffix = ".png"; - Label labelElement = new Label(); - Image iconElement = new Image() {name = "BuildIcon"}; - - public BuildStatusButton(Action clickEvent) : base(clickEvent) - { - iconElement.image = EditorGUIUtility.Load(iconPrefix + iconSuffix) as Texture; - labelElement.text = "Build Now"; - Add(iconElement); - Add(labelElement); - } - - public BuildStatusButton(Action clickEvent, BuildState state, int failures) : base(clickEvent) - { - switch (state) - { - case BuildState.InProgress: - iconElement.image = EditorGUIUtility.Load(iconPrefix + iconSuffix) as Texture; - labelElement.text = "In progress"; - break; - - case BuildState.Failed: - iconElement.image = EditorGUIUtility.Load(iconPrefix + "Failed" + iconSuffix) as Texture; - labelElement.text = failures + ((failures == 1) ? " failure" : " failures"); - break; - - case BuildState.Success: - iconElement.image = EditorGUIUtility.Load(iconPrefix + "Succeeded" + iconSuffix) as Texture; - labelElement.text = "success"; - break; - } - - Add(iconElement); - Add(labelElement); - } - } -} diff --git a/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs b/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs deleted file mode 100644 index a6333b0c22..0000000000 --- a/Editor/Mono/Collab/Views/CollabHistoryDropDown.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Experimental.UIElements; -using System.Collections.Generic; -using UnityEditor.Connect; - -namespace UnityEditor.Collaboration -{ - internal class CollabHistoryDropDown : VisualElement - { - readonly VisualElement m_FilesContainer; - readonly Label m_ToggleLabel; - int m_ChangesTotal; - string m_RevisionId; - - public CollabHistoryDropDown(ICollection changes, int changesTotal, bool changesTruncated, string revisionId) - { - m_FilesContainer = new VisualElement(); - m_ChangesTotal = changesTotal; - m_RevisionId = revisionId; - - m_ToggleLabel = new Label(ToggleText(false)); - m_ToggleLabel.AddManipulator(new Clickable(ToggleDropdown)); - Add(m_ToggleLabel); - - foreach (ChangeData change in changes) - { - m_FilesContainer.Add(new CollabHistoryDropDownItem(change.path, change.action)); - } - - if (changesTruncated) - { - m_FilesContainer.Add(new Button(ShowAllClick) - { - text = "Show all on dashboard" - }); - } - } - - void ToggleDropdown() - { - if (Contains(m_FilesContainer)) - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "CollapseAssets"); - Remove(m_FilesContainer); - m_ToggleLabel.text = ToggleText(false); - } - else - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "ExpandAssets"); - Add(m_FilesContainer); - m_ToggleLabel.text = ToggleText(true); - } - } - - private string ToggleText(bool open) - { - var icon = open ? "\u25bc" : "\u25b6"; - var change = m_ChangesTotal == 1 ? "Change" : "Changes"; - return string.Format("{0} {1} Asset {2}", icon, m_ChangesTotal, change); - } - - private void ShowAllClick() - { - var host = UnityConnect.instance.GetConfigurationURL(CloudConfigUrl.CloudServicesDashboard); - var org = UnityConnect.instance.GetOrganizationId(); - var proj = UnityConnect.instance.GetProjectGUID(); - var url = string.Format("{0}/collab/orgs/{1}/projects/{2}/commits?commit={3}", host, org, proj, m_RevisionId); - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "ShowAllOnDashboard"); - Application.OpenURL(url); - } - } -} diff --git a/Editor/Mono/Collab/Views/CollabHistoryDropDownItem.cs b/Editor/Mono/Collab/Views/CollabHistoryDropDownItem.cs deleted file mode 100644 index 00385c19b6..0000000000 --- a/Editor/Mono/Collab/Views/CollabHistoryDropDownItem.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Linq; -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Collaboration -{ - internal class CollabHistoryDropDownItem : VisualElement - { - public CollabHistoryDropDownItem(string path, string action) - { - var fileName = Path.GetFileName(path); - var isFolder = Path.GetFileNameWithoutExtension(path).Equals(fileName); - var fileIcon = GetIconElement(action, fileName, isFolder); - var metaContainer = new VisualElement(); - var fileNameLabel = new Label - { - name = "FileName", - text = fileName - }; - var filePathLabel = new Label - { - name = "FilePath", - text = path - }; - metaContainer.Add(fileNameLabel); - metaContainer.Add(filePathLabel); - Add(fileIcon); - Add(metaContainer); - } - - private Image GetIconElement(string action, string fileName, bool isFolder) - { - var prefix = isFolder ? "Folder" : "File"; - var actionName = action.First().ToString().ToUpper() + action.Substring(1); - // Use the same icon for renamed and moved files - actionName = actionName.Equals("Renamed") ? "Moved" : actionName; - var iconElement = new Image - { - name = "FileIcon", - image = EditorGUIUtility.LoadIcon("Icons/Collab." + prefix + actionName + ".png") - }; - return iconElement; - } - } -} diff --git a/Editor/Mono/Collab/Views/CollabHistoryItem.cs b/Editor/Mono/Collab/Views/CollabHistoryItem.cs deleted file mode 100644 index e355e1e66d..0000000000 --- a/Editor/Mono/Collab/Views/CollabHistoryItem.cs +++ /dev/null @@ -1,228 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Security.Cryptography; -using UnityEditor.Connect; -using UnityEditor.Web; -using UnityEngine; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleEnums; - -namespace UnityEditor.Collaboration -{ - internal class CollabHistoryItem : VisualContainer - { - public static RevisionAction s_OnRestore; - public static RevisionAction s_OnGoBack; - public static RevisionAction s_OnUpdate; - public static ShowBuildAction s_OnShowBuild; - public static Action s_OnShowServices; - - private readonly string m_RevisionId; - private readonly string m_FullDescription; - private readonly DateTime m_TimeStamp; - private readonly Button m_Button; - private readonly HistoryProgressSpinner m_ProgressSpinner; - private VisualContainer m_ActionsTray; - private VisualElement m_Details; - private Label m_Description; - private Label m_TimeAgo; - private readonly Button m_ExpandCollapseButton; - private bool m_Expanded; - - private const int kMaxDescriptionChars = 500; - - public bool RevisionActionsEnabled - { - set - { - m_Button.SetEnabled(value); - } - } - - public DateTime timeStamp - { - get { return m_TimeStamp; } - } - - public CollabHistoryItem(RevisionData data) - { - m_RevisionId = data.id; - m_TimeStamp = data.timeStamp; - name = "HistoryItem"; - m_ActionsTray = new VisualContainer {name = "HistoryItemActionsTray"}; - m_ProgressSpinner = new HistoryProgressSpinner(); - m_Details = new VisualElement {name = "HistoryDetail"}; - var author = new Label(data.authorName) {name = "Author"}; - m_TimeAgo = new Label(TimeAgo.GetString(m_TimeStamp)); - m_FullDescription = data.comment; - var shouldTruncate = ShouldTruncateDescription(m_FullDescription); - if (shouldTruncate) - { - m_Description = new Label(GetTruncatedDescription(m_FullDescription)); - } - else - { - m_Description = new Label(m_FullDescription); - } - m_Description.name = "RevisionDescription"; - var dropdown = new CollabHistoryDropDown(data.changes, data.changesTotal, data.changesTruncated, data.id); - if (data.current) - { - m_Button = new Button(Restore) {name = "ActionButton", text = "Restore"}; - } - else if (data.obtained) - { - m_Button = new Button(GoBackTo) {name = "ActionButton", text = "Go back to..."}; - } - else - { - m_Button = new Button(UpdateTo) {name = "ActionButton", text = "Update"}; - } - m_Button.SetEnabled(data.enabled); - m_ProgressSpinner.ProgressEnabled = data.inProgress; - - m_ActionsTray.Add(m_ProgressSpinner); - m_ActionsTray.Add(m_Button); - - m_Details.Add(author); - m_Details.Add(m_TimeAgo); - m_Details.Add(m_Description); - - if (shouldTruncate) - { - m_ExpandCollapseButton = new Button(ToggleDescription) { name = "ToggleDescription", text = "Show More" }; - m_Details.Add(m_ExpandCollapseButton); - } - - if (data.buildState != BuildState.None) - { - BuildStatusButton buildButton; - if (data.buildState == BuildState.Configure) - buildButton = new BuildStatusButton(ShowServicePage); - else - buildButton = new BuildStatusButton(ShowBuildForCommit, data.buildState, data.buildFailures); - - m_Details.Add(buildButton); - } - - m_Details.Add(m_ActionsTray); - m_Details.Add(dropdown); - - Add(m_Details); - - this.schedule.Execute(UpdateTimeAgo).Every(1000 * 20); - } - - public static void SetUpCallbacks(RevisionAction Restore, RevisionAction GoBack, RevisionAction Update) - { - s_OnRestore = Restore; - s_OnGoBack = GoBack; - s_OnUpdate = Update; - } - - public void SetInProgressStatus(string revisionIdInProgress) - { - if (String.IsNullOrEmpty(revisionIdInProgress)) - { - m_Button.SetEnabled(true); - m_ProgressSpinner.ProgressEnabled = false; - } - else - { - m_Button.SetEnabled(false); - if (m_RevisionId.Equals(revisionIdInProgress)) - { - m_ProgressSpinner.ProgressEnabled = true; - } - } - } - - void ShowBuildForCommit() - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "ShowBuild"); - if (s_OnShowBuild != null) - { - s_OnShowBuild(m_RevisionId); - } - } - - void ShowServicePage() - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "ShowServices"); - if (s_OnShowServices != null) - { - s_OnShowServices(); - } - } - - void Restore() - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "Restore"); - if (s_OnRestore != null) - { - s_OnRestore(m_RevisionId, false); - } - } - - void GoBackTo() - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "GoBackTo"); - if (s_OnGoBack != null) - { - s_OnGoBack(m_RevisionId, false); - } - } - - void UpdateTo() - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "Update"); - if (s_OnUpdate != null) - { - s_OnUpdate(m_RevisionId, true); - } - } - - void UpdateTimeAgo() - { - m_TimeAgo.text = TimeAgo.GetString(m_TimeStamp); - } - - bool ShouldTruncateDescription(string description) - { - return description.Contains(Environment.NewLine) || description.Length > kMaxDescriptionChars; - } - - string GetTruncatedDescription(string description) - { - string result = description.Contains(Environment.NewLine) ? - description.Substring(0, description.IndexOf(Environment.NewLine)) : description; - if (result.Length > kMaxDescriptionChars) - { - result = result.Substring(0, kMaxDescriptionChars) + "..."; - } - return result; - } - - void ToggleDescription() - { - if (m_Expanded) - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "CollapseDescription"); - m_Expanded = false; - m_ExpandCollapseButton.text = "Show More"; - m_Description.text = GetTruncatedDescription(m_FullDescription); - } - else - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "ExpandDescription"); - m_Expanded = true; - m_ExpandCollapseButton.text = "Show Less"; - m_Description.text = m_FullDescription; - } - } - } -} diff --git a/Editor/Mono/Collab/Views/CollabHistoryItemFactory.cs b/Editor/Mono/Collab/Views/CollabHistoryItemFactory.cs deleted file mode 100644 index 7a3a55b616..0000000000 --- a/Editor/Mono/Collab/Views/CollabHistoryItemFactory.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Collaboration; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleEnums; -using UnityEngine; - -namespace UnityEditor.Collaboration -{ - internal class CollabHistoryItemFactory : ICollabHistoryItemFactory - { - const int k_MaxChangesPerRevision = 10; - - public IEnumerable GenerateElements(IEnumerable revisions, int totalRevisions, int startIndex, string tipRev, string inProgressRevision, bool revisionActionsEnabled, bool buildServiceEnabled, string currentUser) - { - int index = startIndex; - - foreach (var rev in revisions) - { - index++; - var current = rev.revisionID == tipRev; - - // Calculate build status - BuildState buildState = BuildState.None; - int buildFailures = 0; - if (rev.buildStatuses != null && rev.buildStatuses.Length > 0) - { - bool inProgress = false; - foreach (CloudBuildStatus buildStatus in rev.buildStatuses) - { - if (buildStatus.complete) - { - if (!buildStatus.success) - { - buildFailures++; - } - } - else - { - inProgress = true; - break; - } - } - - if (inProgress) - { - buildState = BuildState.InProgress; - } - else if (buildFailures > 0) - { - buildState = BuildState.Failed; - } - else - { - buildState = BuildState.Success; - } - } - else if (current && !buildServiceEnabled) - { - buildState = BuildState.Configure; - } - - // Calculate the number of changes performed on files and folders (not meta files) - var paths = new Dictionary(); - foreach (ChangeAction change in rev.entries) - { - if (change.path.EndsWith(".meta")) - { - var path = change.path.Substring(0, change.path.Length - 5); - // Actions taken on meta files are secondary to any actions taken on the main file - if (!paths.ContainsKey(path)) - paths[path] = new ChangeData() {path = path, action = change.action}; - } - else - { - paths[change.path] = new ChangeData() {path = change.path, action = change.action}; - } - } - - var displayName = (rev.author != currentUser) ? rev.authorName : "You"; - - var item = new RevisionData - { - id = rev.revisionID, - index = totalRevisions - index + 1, - timeStamp = TimeStampToDateTime(rev.timeStamp), - authorName = displayName, - comment = rev.comment, - - obtained = rev.isObtained, - current = current, - inProgress = rev.revisionID.Equals(inProgressRevision), - enabled = revisionActionsEnabled, - - buildState = buildState, - buildFailures = buildFailures, - - changes = paths.Values.Take(k_MaxChangesPerRevision).ToList(), - changesTotal = paths.Values.Count, - changesTruncated = paths.Values.Count > k_MaxChangesPerRevision, - }; - - yield return item; - } - } - - private static DateTime TimeStampToDateTime(double timeStamp) - { - DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - dateTime = dateTime.AddSeconds(timeStamp).ToLocalTime(); - return dateTime; - } - } -} diff --git a/Editor/Mono/Collab/Views/CollabHistoryRevisionLine.cs b/Editor/Mono/Collab/Views/CollabHistoryRevisionLine.cs deleted file mode 100644 index c77fc2a920..0000000000 --- a/Editor/Mono/Collab/Views/CollabHistoryRevisionLine.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEditor.Collaboration; -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Collaboration -{ - internal class CollabHistoryRevisionLine : VisualElement - { - public CollabHistoryRevisionLine(int number) - { - AddNumber(number); - AddLine("topLine"); - AddLine("bottomLine"); - AddIndicator(); - } - - public CollabHistoryRevisionLine(DateTime date, bool isFullDateObtained) - { - AddLine(isFullDateObtained ? "obtainedDateLine" : "absentDateLine"); - AddHeader(GetFormattedHeader(date)); - AddToClassList("revisionLineHeader"); - } - - private void AddHeader(string content) - { - Add(new Label - { - text = content - }); - } - - private void AddIndicator() - { - Add(new VisualElement - { - name = "RevisionIndicator" - }); - } - - private void AddLine(string className = null) - { - var line = new VisualElement - { - name = "RevisionLine" - }; - if (!String.IsNullOrEmpty(className)) - { - line.AddToClassList(className); - } - Add(line); - } - - private void AddNumber(int number) - { - Add(new Label - { - text = number.ToString(), - name = "RevisionIndex" - }); - } - - private string GetFormattedHeader(DateTime date) - { - string result = "Commits on " + date.ToString("MMM d"); - switch (date.Day) - { - case 1: - case 21: - case 31: - result += "st"; - break; - case 2: - case 22: - result += "nd"; - break; - case 3: - case 23: - result += "rd"; - break; - default: - result += "th"; - break; - } - return result; - } - } -} diff --git a/Editor/Mono/Collab/Views/HistoryProgressSpinner.cs b/Editor/Mono/Collab/Views/HistoryProgressSpinner.cs deleted file mode 100644 index e786145d25..0000000000 --- a/Editor/Mono/Collab/Views/HistoryProgressSpinner.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Collaboration -{ - internal class HistoryProgressSpinner : Image - { - private readonly Texture2D[] m_StatusWheelTextures; - private bool m_ProgressEnabled; - private IVisualElementScheduledItem m_Animation; - - public bool ProgressEnabled - { - set - { - if (m_ProgressEnabled == value) - return; - - m_ProgressEnabled = value; - visible = value; - - - if (value) - { - if (m_Animation == null) - { - m_Animation = this.schedule.Execute(AnimateProgress).Every(33); - } - else - { - m_Animation.Resume(); - } - } - else - { - if (m_Animation != null) - { - m_Animation.Pause(); - } - } - } - } - - public HistoryProgressSpinner() - { - m_StatusWheelTextures = new Texture2D[12]; - for (int i = 0; i < 12; i++) - { - m_StatusWheelTextures[i] = EditorGUIUtility.LoadIcon("WaitSpin" + i.ToString("00")); - } - image = m_StatusWheelTextures[0]; - style.width = m_StatusWheelTextures[0].width; - style.height = m_StatusWheelTextures[0].height; - visible = false; - } - - private void AnimateProgress(TimerState obj) - { - int frame = (int)Mathf.Repeat(Time.realtimeSinceStartup * 10, 11.99f); - image = m_StatusWheelTextures[frame]; - Dirty(ChangeType.Repaint); - } - } -} diff --git a/Editor/Mono/Collab/Views/ICollabHistoryItemFactory.cs b/Editor/Mono/Collab/Views/ICollabHistoryItemFactory.cs deleted file mode 100644 index 285a3be0e3..0000000000 --- a/Editor/Mono/Collab/Views/ICollabHistoryItemFactory.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.Collaboration; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Collaboration -{ - internal interface ICollabHistoryItemFactory - { - IEnumerable GenerateElements(IEnumerable revsRevisions, int mTotalRevisions, int startIndex, string tipRev, string inProgressRevision, bool revisionActionsEnabled, bool buildServiceEnabled, string currentUser); - } -} diff --git a/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs b/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs deleted file mode 100644 index df3f721b2f..0000000000 --- a/Editor/Mono/Collab/Views/ICollabHistoryWindow.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.Collaboration; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Collaboration -{ - internal delegate void PageChangeAction(int page); - internal delegate void RevisionAction(string revisionId, bool updateToRevision); - internal delegate void ShowBuildAction(string revisionId); - - internal enum HistoryState - { - Error, - Offline, - Maintenance, - LoggedOut, - NoSeat, - Disabled, - Waiting, - Ready, - } - - internal enum BuildState - { - None, - Configure, - Success, - Failed, - InProgress, - } - - internal struct RevisionData - { - public string id; - public int index; - public DateTime timeStamp; - public string authorName; - public string comment; - - // Whether this revision is on the client - public bool obtained; - public bool current; - public bool inProgress; - public bool enabled; - - public BuildState buildState; - public int buildFailures; - - public ICollection changes; - public int changesTotal; - public bool changesTruncated; - } - - internal struct ChangeData - { - public string path; - public string action; - } - - internal interface ICollabHistoryWindow - { - void UpdateState(HistoryState state, bool force); - void UpdateRevisions(IEnumerable items, string tip, int totalRevisions, int currentPage); - - bool revisionActionsEnabled { get; set; } - int itemsPerPage { set; } - string inProgressRevision { get; set; } - PageChangeAction OnPageChangeAction { set; } - RevisionAction OnGoBackAction { set; } - RevisionAction OnUpdateAction { set; } - RevisionAction OnRestoreAction { set; } - ShowBuildAction OnShowBuildAction { set; } - Action OnShowServicesAction { set; } - } -} diff --git a/Editor/Mono/Collab/Views/PagedListView.cs b/Editor/Mono/Collab/Views/PagedListView.cs deleted file mode 100644 index 40e0a3305e..0000000000 --- a/Editor/Mono/Collab/Views/PagedListView.cs +++ /dev/null @@ -1,194 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleEnums; - -namespace UnityEditor.Collaboration -{ - internal delegate bool IsPagerVisible(PagerLocation loc); - - internal interface IPagerData - { - int curPage { get; } - int totalPages { get; } - PageChangeAction OnPageChanged { get; } - } - - internal class PagerElement : VisualElement - { - IPagerData m_Data; - readonly Label m_PageText; - readonly Button m_DownButton; - readonly Button m_UpButton; - - public PagerElement(IPagerData dataSource) - { - m_Data = dataSource; - - this.style.flexDirection = FlexDirection.Row; - this.style.alignSelf = Align.Center; - - Add(m_DownButton = new Button(OnPageDownClicked) {text = "\u25c5 Newer"}); - m_DownButton.AddToClassList("PagerDown"); - - m_PageText = new Label(); - m_PageText.AddToClassList("PagerLabel"); - Add(m_PageText); - - Add(m_UpButton = new Button(OnPageUpClicked) {text = "Older \u25bb"}); - m_UpButton.AddToClassList("PagerUp"); - - UpdateControls(); - } - - void OnPageDownClicked() - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "NewerPage"); - m_Data.OnPageChanged(m_Data.curPage - 1); - } - - void OnPageUpClicked() - { - CollabAnalytics.SendUserAction(CollabAnalytics.historyCategoryString, "OlderPage"); - m_Data.OnPageChanged(m_Data.curPage + 1); - } - - public void Refresh() - { - UpdateControls(); - } - - void UpdateControls() - { - var curPage = m_Data.curPage; - var totalPages = m_Data.totalPages; - - m_PageText.text = (curPage + 1) + " / " + totalPages; - m_DownButton.SetEnabled(curPage > 0); - m_UpButton.SetEnabled(curPage < totalPages - 1); - } - } - - internal enum PagerLocation - { - Top, - Bottom, - } - - internal class PagedListView : VisualElement, IPagerData - { - public const int DefaultItemsPerPage = 10; - - readonly VisualElement m_ItemContainer; - readonly PagerElement m_PagerTop, m_PagerBottom; - int m_PageSize = DefaultItemsPerPage; - IEnumerable m_Items; - int m_TotalItems; - int m_CurPage; - - public int pageSize - { - set { m_PageSize = value; } - } - - public IEnumerable items - { - set - { - m_Items = value; - LayoutItems(); - } - } - - public int totalItems - { - set - { - if (m_TotalItems == value) - return; - - m_TotalItems = value; - UpdatePager(); - } - } - - public PageChangeAction OnPageChanged { get; set; } - - public PagedListView() - { - m_PagerTop = new PagerElement(this); - - m_ItemContainer = new VisualElement() - { - name = "PagerItems", - }; - Add(m_ItemContainer); - m_Items = new List(); - - m_PagerBottom = new PagerElement(this); - } - - void LayoutItems() - { - m_ItemContainer.Clear(); - foreach (var item in m_Items) - { - m_ItemContainer.Add(item); - } - } - - void UpdatePager() - { - if (m_PagerTop.parent != this && totalPages > 1 && curPage > 0) - Insert(0, m_PagerTop); - if (m_PagerTop.parent == this && (totalPages <= 1 || curPage == 0)) - Remove(m_PagerTop); - - if (m_PagerBottom.parent != this && totalPages > 1) - Add(m_PagerBottom); - if (m_PagerBottom.parent == this && totalPages <= 1) - Remove(m_PagerBottom); - - m_PagerTop.Refresh(); - m_PagerBottom.Refresh(); - } - - int pageCount - { - get - { - var pages = m_TotalItems / m_PageSize; - if (m_TotalItems % m_PageSize > 0) - pages++; - - return pages; - } - } - - public int curPage - { - get { return m_CurPage; } - set - { - m_CurPage = value; - UpdatePager(); - } - } - - public int totalPages - { - get - { - var extraPage = 0; - if (m_TotalItems % m_PageSize > 0) - extraPage = 1; - return m_TotalItems / m_PageSize + extraPage; - } - } - } -} diff --git a/Editor/Mono/Collab/Views/StatusView.cs b/Editor/Mono/Collab/Views/StatusView.cs deleted file mode 100644 index e70da199da..0000000000 --- a/Editor/Mono/Collab/Views/StatusView.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleEnums; - -namespace UnityEditor.Collaboration -{ - internal class StatusView : VisualContainer - { - Image m_Image; - Label m_Message; - Button m_Button; - Action m_Callback; - - public Texture icon - { - get { return m_Image.image; } - set - { - m_Image.image = value; - m_Image.visible = value != null; - // Until "display: hidden" is added, this is the only way to hide an element - m_Image.style.height = value != null ? 150 : 0; - } - } - - public string message - { - get { return m_Message.text; } - set - { - m_Message.text = value; - m_Message.visible = value != null; - } - } - - public string buttonText - { - get { return m_Button.text; } - set - { - m_Button.text = value; - UpdateButton(); - } - } - - public Action callback - { - get { return m_Callback; } - set - { - m_Callback = value; - UpdateButton(); - } - } - - public StatusView() - { - name = "StatusView"; - - this.StretchToParentSize(); - - m_Image = new Image() { name = "StatusIcon", visible = false, style = { height = 0 }}; - m_Message = new Label() { name = "StatusMessage", visible = false}; - m_Button = new Button(InternalCallaback) { name = "StatusButton", visible = false}; - - Add(m_Image); - Add(m_Message); - Add(m_Button); - } - - private void UpdateButton() - { - m_Button.visible = m_Button.text != null && m_Callback != null; - } - - private void InternalCallaback() - { - m_Callback(); - } - } -} diff --git a/Editor/Mono/Commands/GOCreationCommands.cs b/Editor/Mono/Commands/GOCreationCommands.cs deleted file mode 100644 index 098ebca656..0000000000 --- a/Editor/Mono/Commands/GOCreationCommands.cs +++ /dev/null @@ -1,270 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using UnityEngine.Video; - -namespace UnityEditor -{ - static class GOCreationCommands - { - internal static GameObject CreateGameObject(GameObject parent, string name, params Type[] types) - { - return ObjectFactory.CreateGameObject(GameObjectUtility.GetUniqueNameForSibling(parent != null ? parent.transform : null, name), types); - } - - internal static void Place(GameObject go, GameObject parent) - { - if (parent != null) - { - var transform = go.transform; - Undo.SetTransformParent(transform, parent.transform, "Reparenting"); - transform.localPosition = Vector3.zero; - transform.localRotation = Quaternion.identity; - transform.localScale = Vector3.one; - go.layer = parent.layer; - - if (parent.GetComponent()) - ObjectFactory.AddComponent(go); - } - else - { - SceneView.PlaceGameObjectInFrontOfSceneView(go); - } - EditorWindow.FocusWindowIfItsOpen(); - Selection.activeGameObject = go; - } - - [MenuItem("GameObject/Create Empty %#n", priority = 0)] - static void CreateEmpty(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - Place(CreateGameObject(parent, "GameObject"), parent); - } - - [MenuItem("GameObject/Create Empty Child &#n", priority = 0)] - static void CreateEmptyChild(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - if (parent == null) - parent = Selection.activeGameObject; - var go = CreateGameObject(parent, "GameObject"); - Place(go, parent); - } - - static void CreateAndPlacePrimitive(PrimitiveType type, GameObject parent) - { - // make sure to get the unique name before the GameObject is created - // or GetUniqueNameForSibling will always end up with (1) in empty scene - string uniqueName = GameObjectUtility.GetUniqueNameForSibling(parent != null ? parent.transform : null, type.ToString()); - var primitive = ObjectFactory.CreatePrimitive(type); - primitive.name = uniqueName; - Place(primitive, parent); - } - - [MenuItem("GameObject/3D Object/Cube", priority = 1)] - static void CreateCube(MenuCommand menuCommand) - { - CreateAndPlacePrimitive(PrimitiveType.Cube, menuCommand.context as GameObject); - } - - [MenuItem("GameObject/3D Object/Sphere", priority = 2)] - static void CreateSphere(MenuCommand menuCommand) - { - CreateAndPlacePrimitive(PrimitiveType.Sphere, menuCommand.context as GameObject); - } - - [MenuItem("GameObject/3D Object/Capsule", priority = 3)] - static void CreateCapsule(MenuCommand menuCommand) - { - CreateAndPlacePrimitive(PrimitiveType.Capsule, menuCommand.context as GameObject); - } - - [MenuItem("GameObject/3D Object/Cylinder", priority = 4)] - static void CreateCylinder(MenuCommand menuCommand) - { - CreateAndPlacePrimitive(PrimitiveType.Cylinder, menuCommand.context as GameObject); - } - - [MenuItem("GameObject/3D Object/Plane", priority = 5)] - static void CreatePlane(MenuCommand menuCommand) - { - CreateAndPlacePrimitive(PrimitiveType.Plane, menuCommand.context as GameObject); - } - - [MenuItem("GameObject/3D Object/Quad", priority = 6)] - static void CreateQuad(MenuCommand menuCommand) - { - CreateAndPlacePrimitive(PrimitiveType.Quad, menuCommand.context as GameObject); - } - - [MenuItem("GameObject/2D Object/Sprite", priority = 1)] - static void CreateSprite(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - var go = CreateGameObject(parent, "New Sprite", typeof(SpriteRenderer)); - var sprite = Selection.activeObject as Sprite; - if (sprite == null) - { - var texture = Selection.activeObject as Texture2D; - if (texture) - { - string path = AssetDatabase.GetAssetPath(texture); - sprite = AssetDatabase.LoadAllAssetsAtPath(path) - .OfType() - .First(); - if (sprite == null) - { - var importer = AssetImporter.GetAtPath(path) as TextureImporter; - if (importer != null && importer.textureType != TextureImporterType.Sprite) - { - EditorUtility.DisplayDialog( - "Sprite could not be assigned!", - "Can not assign a Sprite to the new SpriteRenderer because the selected Texture is not configured to generate Sprites.", - "OK"); - } - } - } - } - if (sprite != null) - { - go.GetComponent().sprite = sprite; - } - else - { - // TODO: assign a default sprite - } - Place(go, parent); - } - - [MenuItem("GameObject/Light/Directional Light", priority = 1)] - static void CreateDirectionalLight(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - var go = CreateGameObject(null, "Directional Light", typeof(Light)); - - go.GetComponent().type = LightType.Directional; - go.GetComponent().intensity = 1f; - go.GetComponent().SetLocalEulerAngles(new Vector3(50, -30, 0), RotationOrder.OrderZXY); - - Place(go, parent); - } - - [MenuItem("GameObject/Light/Point Light", priority = 2)] - static void CreatePointLight(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - var go = CreateGameObject(null, "Point Light", typeof(Light)); - - go.GetComponent().type = LightType.Point; - - Place(go, parent); - } - - [MenuItem("GameObject/Light/Spotlight", priority = 3)] - static void CreateSpotLight(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - var go = CreateGameObject(null, "Spot Light", typeof(Light)); - - go.GetComponent().type = LightType.Spot; - go.GetComponent().SetLocalEulerAngles(new Vector3(90, 0, 0), RotationOrder.OrderZXY); - - Place(go, parent); - } - - [MenuItem("GameObject/Light/Area Light", priority = 4)] - static void CreateAreaLight(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - var go = CreateGameObject(null, "Area Light", typeof(Light)); - - go.GetComponent().type = LightType.Area; - go.GetComponent().SetLocalEulerAngles(new Vector3(90, 0, 0), RotationOrder.OrderZXY); - - Place(go, parent); - } - - [MenuItem("GameObject/Light/Reflection Probe", priority = 20)] - static void CreateReflectionProbe(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - Place(CreateGameObject(parent, "Reflection Probe", typeof(ReflectionProbe)), parent); - } - - [MenuItem("GameObject/Light/Light Probe Group", priority = 21)] - static void CreateLightProbeGroup(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - Place(CreateGameObject(parent, "Light Probe Group", typeof(LightProbeGroup)), parent); - } - - [MenuItem("GameObject/Audio/Audio Source", priority = 1)] - static void CreateAudioSource(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - Place(CreateGameObject(parent, "Audio Source", typeof(AudioSource)), parent); - } - - [MenuItem("GameObject/Audio/Audio Reverb Zone", priority = 2)] - static void CreateAudioReverbZone(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - Place(CreateGameObject(parent, "Audio Reverb Zone", typeof(AudioReverbZone)), parent); - } - - [MenuItem("GameObject/Video/Video Player", priority = 1)] - static void CreateVideoPlayer(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - Place(CreateGameObject(parent, "Video Player", typeof(VideoPlayer)), parent); - } - - [MenuItem("GameObject/Effects/Particle System", priority = 1)] - static void CreateParticleSystem(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - var go = CreateGameObject(parent, "Particle System", typeof(ParticleSystem)); - - go.GetComponent().SetLocalEulerAngles(new Vector3(-90, 0, 0), RotationOrder.OrderZXY); - var renderer = go.GetComponent(); - renderer.materials = new Material[] - { - Material.GetDefaultParticleMaterial(), - null - }; - Place(go, parent); - } - - [MenuItem("GameObject/Effects/Trail", priority = 2)] - static void CreateTrail(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - var go = CreateGameObject(parent, "Trail", typeof(TrailRenderer)); - go.GetComponent().material = Material.GetDefaultLineMaterial(); - Place(go, parent); - } - - [MenuItem("GameObject/Effects/Line", priority = 3)] - static void CreateLine(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - var go = CreateGameObject(parent, "Line", typeof(LineRenderer)); - var line = go.GetComponent(); - line.material = Material.GetDefaultLineMaterial(); - line.widthMultiplier = 0.1f; - line.useWorldSpace = false; - Place(go, parent); - } - - [MenuItem("GameObject/Camera", priority = 11)] - static void CreateCamera(MenuCommand menuCommand) - { - var parent = menuCommand.context as GameObject; - Place(CreateGameObject(parent, "Camera", typeof(Camera), typeof(FlareLayer), typeof(AudioListener)), parent); - } - } -} diff --git a/Editor/Mono/CompilationPipeline.bindings.cs b/Editor/Mono/CompilationPipeline.bindings.cs deleted file mode 100644 index c182bbadd5..0000000000 --- a/Editor/Mono/CompilationPipeline.bindings.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; - -namespace UnityEditor.Compilation -{ - [NativeHeader("Editor/Src/ScriptCompilation/ScriptCompilationPipeline.h")] - public static partial class CompilationPipeline - { - [FreeFunction] - extern internal static void ClearEditorCompilationErrors(); - [FreeFunction] - extern internal static void LogEditorCompilationError(string message, int instanceID); - } -} diff --git a/Editor/Mono/ComponentUtility.cs b/Editor/Mono/ComponentUtility.cs deleted file mode 100644 index 607c5b08f8..0000000000 --- a/Editor/Mono/ComponentUtility.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditorInternal -{ - public partial class ComponentUtility - { - static private bool CompareComponentOrderAndTypes(List srcComponents, List dstComponents) - { - if (srcComponents.Count != dstComponents.Count) - return false; - - for (int i = 0; i != srcComponents.Count; i++) - { - if (srcComponents[i].GetType() != dstComponents[i].GetType()) - return false; - } - - return true; - } - - private static void DestroyComponents(List components) - { - // Delete in reverse order (to avoid errors when RequireComponent is used) - for (int i = components.Count - 1; i >= 0; i--) - UnityEngine.Object.DestroyImmediate(components[i]); - } - - public delegate bool IsDesiredComponent(Component c); - - public static void DestroyComponentsMatching(GameObject dst, IsDesiredComponent componentFilter) - { - var dstComponents = new List(); - dst.GetComponents(dstComponents); - dstComponents.RemoveAll(x => !componentFilter(x)); - DestroyComponents(dstComponents); - } - - public static void ReplaceComponentsIfDifferent(GameObject src, GameObject dst, IsDesiredComponent componentFilter) - { - var srcComponents = new List(); - src.GetComponents(srcComponents); - srcComponents.RemoveAll(x => !componentFilter(x)); - - var dstComponents = new List(); - dst.GetComponents(dstComponents); - dstComponents.RemoveAll(x => !componentFilter(x)); - - // Generate components - if (!CompareComponentOrderAndTypes(srcComponents, dstComponents)) - { - DestroyComponents(dstComponents); - - // Add src components to dst - dstComponents.Clear(); - for (int i = 0; i != srcComponents.Count; i++) - { - Component com = dst.AddComponent(srcComponents[i].GetType()); - dstComponents.Add(com); - } - } - - // Copy Data to components - for (int i = 0; i != srcComponents.Count; i++) - UnityEditor.EditorUtility.CopySerializedIfDifferent(srcComponents[i], dstComponents[i]); - } - } -} diff --git a/Editor/Mono/ConsoleWindow.cs b/Editor/Mono/ConsoleWindow.cs deleted file mode 100644 index daafbecdb4..0000000000 --- a/Editor/Mono/ConsoleWindow.cs +++ /dev/null @@ -1,854 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Globalization; -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Console", useTypeNameAsIconName = true)] - internal class ConsoleWindow : EditorWindow, IHasCustomMenu - { - internal delegate void EntryDoubleClickedDelegate(LogEntry entry); - - //TODO: move this out of here - internal class Constants - { - private static bool ms_Loaded; - private static int ms_logStyleLineCount; - public static GUIStyle Box; - public static GUIStyle Button; - public static GUIStyle MiniButton; - public static GUIStyle MiniButtonLeft; - public static GUIStyle MiniButtonMiddle; - public static GUIStyle MiniButtonRight; - public static GUIStyle LogStyle; - public static GUIStyle WarningStyle; - public static GUIStyle ErrorStyle; - public static GUIStyle IconLogStyle; - public static GUIStyle IconWarningStyle; - public static GUIStyle IconErrorStyle; - public static GUIStyle EvenBackground; - public static GUIStyle OddBackground; - public static GUIStyle MessageStyle; - public static GUIStyle StatusError; - public static GUIStyle StatusWarn; - public static GUIStyle StatusLog; - public static GUIStyle Toolbar; - public static GUIStyle CountBadge; - public static GUIStyle LogSmallStyle; - public static GUIStyle WarningSmallStyle; - public static GUIStyle ErrorSmallStyle; - public static GUIStyle IconLogSmallStyle; - public static GUIStyle IconWarningSmallStyle; - public static GUIStyle IconErrorSmallStyle; - public static readonly string ClearLabel = L10n.Tr("Clear"); - public static readonly string ClearOnPlayLabel = L10n.Tr("Clear on Play"); - public static readonly string ErrorPauseLabel = L10n.Tr("Error Pause"); - public static readonly string CollapseLabel = L10n.Tr("Collapse"); - public static readonly string StopForAssertLabel = L10n.Tr("Stop for Assert"); - public static readonly string StopForErrorLabel = L10n.Tr("Stop for Error"); - - public static int LogStyleLineCount - { - get { return ms_logStyleLineCount; } - set - { - ms_logStyleLineCount = value; - - // If Constants hasn't been initialized yet we just skip this for now - // and let Init() call this for us in a bit. - if (!ms_Loaded) - return; - UpdateLogStyleFixedHeights(); - } - } - - public static void Init() - { - if (ms_Loaded) - return; - ms_Loaded = true; - Box = new GUIStyle("CN Box"); - Button = new GUIStyle("Button"); - - MiniButton = new GUIStyle("ToolbarButton"); - MiniButtonLeft = new GUIStyle("ToolbarButton"); - MiniButtonMiddle = new GUIStyle("ToolbarButton"); - MiniButtonRight = new GUIStyle("ToolbarButton"); - Toolbar = new GUIStyle("Toolbar"); - LogStyle = new GUIStyle("CN EntryInfo"); - LogSmallStyle = new GUIStyle("CN EntryInfoSmall"); - WarningStyle = new GUIStyle("CN EntryWarn"); - WarningSmallStyle = new GUIStyle("CN EntryWarnSmall"); - ErrorStyle = new GUIStyle("CN EntryError"); - ErrorSmallStyle = new GUIStyle("CN EntryErrorSmall"); - IconLogStyle = new GUIStyle("CN EntryInfoIcon"); - IconLogSmallStyle = new GUIStyle("CN EntryInfoIconSmall"); - IconWarningStyle = new GUIStyle("CN EntryWarnIcon"); - IconWarningSmallStyle = new GUIStyle("CN EntryWarnIconSmall"); - IconErrorStyle = new GUIStyle("CN EntryErrorIcon"); - IconErrorSmallStyle = new GUIStyle("CN EntryErrorIconSmall"); - EvenBackground = new GUIStyle("CN EntryBackEven"); - OddBackground = new GUIStyle("CN EntryBackodd"); - MessageStyle = new GUIStyle("CN Message"); - StatusError = new GUIStyle("CN StatusError"); - StatusWarn = new GUIStyle("CN StatusWarn"); - StatusLog = new GUIStyle("CN StatusInfo"); - CountBadge = new GUIStyle("CN CountBadge"); - - // If the console window isn't open OnEnable() won't trigger so it will end up with 0 lines, - // so we always make sure we read it up when we initialize here. - LogStyleLineCount = EditorPrefs.GetInt("ConsoleWindowLogLineCount", 2); - } - - private static void UpdateLogStyleFixedHeights() - { - // Whenever we change the line height count or the styles are set we need to update the fixed height - // of the following GuiStyles so the entries do not get cropped incorrectly. - ErrorStyle.fixedHeight = (LogStyleLineCount * ErrorStyle.lineHeight) + ErrorStyle.border.top; - WarningStyle.fixedHeight = (LogStyleLineCount * WarningStyle.lineHeight) + WarningStyle.border.top; - LogStyle.fixedHeight = (LogStyleLineCount * LogStyle.lineHeight) + LogStyle.border.top; - } - } - - int m_LineHeight; - int m_BorderHeight; - - bool m_HasUpdatedGuiStyles; - - ListViewState m_ListView; - string m_ActiveText = ""; - private int m_ActiveInstanceID = 0; - bool m_DevBuild; - - Vector2 m_TextScroll = Vector2.zero; - - SplitterState spl = new SplitterState(new float[] {70, 30}, new int[] {32, 32}, null); - - static bool ms_LoadedIcons = false; - static internal Texture2D iconInfo, iconWarn, iconError; - static internal Texture2D iconInfoSmall, iconWarnSmall, iconErrorSmall; - static internal Texture2D iconInfoMono, iconWarnMono, iconErrorMono; - - int ms_LVHeight = 0; - - class ConsoleAttachProfilerUI : AttachProfilerUI - { - List additionalMenuItems = null; - - enum MenuItemIndex - { - PlayerLogging, - FullLog - } - - protected void SelectClick(object userData, string[] options, int selected) - { - if (selected == (int)MenuItemIndex.PlayerLogging) - { - var connected = PlayerConnectionLogReceiver.instance.State != PlayerConnectionLogReceiver.ConnectionState.Disconnected; - PlayerConnectionLogReceiver.instance.State = connected ? PlayerConnectionLogReceiver.ConnectionState.Disconnected : PlayerConnectionLogReceiver.ConnectionState.CleanLog; - return; - } - - if (selected == (int)MenuItemIndex.FullLog) - { - var cleanLog = PlayerConnectionLogReceiver.instance.State == PlayerConnectionLogReceiver.ConnectionState.CleanLog; - PlayerConnectionLogReceiver.instance.State = cleanLog ? PlayerConnectionLogReceiver.ConnectionState.FullLog : PlayerConnectionLogReceiver.ConnectionState.CleanLog; - return; - } - - if (selected < additionalMenuItems.Count) - return; - - SelectProfilerClick(userData, options, selected - additionalMenuItems.Count); - } - - protected override void OnGUIMenu(Rect connectRect, List profilers) - { - if (additionalMenuItems == null) - { - additionalMenuItems = new List {"Player Logging"}; - if (Unsupported.IsDeveloperMode()) - additionalMenuItems.Add("Full Log (Developer Mode Only)"); - additionalMenuItems.Add(""); - } - - var names = additionalMenuItems.Concat(profilers.Select(p => p.Name)).ToArray(); - - // "Player Logging" field is always enabled. - var enabled = new List {true}; - var selected = new List(); - - var connected = PlayerConnectionLogReceiver.instance.State != PlayerConnectionLogReceiver.ConnectionState.Disconnected; - if (connected) - { - selected.Add((int)MenuItemIndex.PlayerLogging); - if (Unsupported.IsDeveloperMode()) - { - if (PlayerConnectionLogReceiver.instance.State == PlayerConnectionLogReceiver.ConnectionState.FullLog) - selected.Add((int)MenuItemIndex.FullLog); - - // Enable "Show Full Log" - enabled.Add(true); - } - enabled.Add(true); - enabled.AddRange(profilers.Select(p => p.Enabled)); - } - else - { - // everything but first menu item is disabled. - enabled.AddRange(new bool[names.Length - 1]); - } - - int index = profilers.FindIndex(p => p.IsSelected()); - if (index != -1) - selected.Add(index + additionalMenuItems.Count); - - var seperators = new bool[enabled.Count]; - seperators[additionalMenuItems.Count - 1] = true; - EditorUtility.DisplayCustomMenuWithSeparators(connectRect, names, enabled.ToArray(), seperators, selected.ToArray(), SelectClick, profilers); - } - } - - ConsoleAttachProfilerUI m_AttachProfilerUI = new ConsoleAttachProfilerUI(); - - [Flags] - internal enum Mode - { - Error = 1 << 0, - Assert = 1 << 1, - Log = 1 << 2, - Fatal = 1 << 4, - DontPreprocessCondition = 1 << 5, - AssetImportError = 1 << 6, - AssetImportWarning = 1 << 7, - ScriptingError = 1 << 8, - ScriptingWarning = 1 << 9, - ScriptingLog = 1 << 10, - ScriptCompileError = 1 << 11, - ScriptCompileWarning = 1 << 12, - StickyError = 1 << 13, - MayIgnoreLineNumber = 1 << 14, - ReportBug = 1 << 15, - DisplayPreviousErrorInStatusBar = 1 << 16, - ScriptingException = 1 << 17, - DontExtractStacktrace = 1 << 18, - ShouldClearOnPlay = 1 << 19, - GraphCompileError = 1 << 20, - ScriptingAssertion = 1 << 21, - VisualScriptingError = 1 << 22 - }; - - enum ConsoleFlags - { - Collapse = 1 << 0, - ClearOnPlay = 1 << 1, - ErrorPause = 1 << 2, - Verbose = 1 << 3, - StopForAssert = 1 << 4, - StopForError = 1 << 5, - Autoscroll = 1 << 6, - LogLevelLog = 1 << 7, - LogLevelWarning = 1 << 8, - LogLevelError = 1 << 9, - ShowTimestamp = 1 << 10, - }; - - static ConsoleWindow ms_ConsoleWindow = null; - - static void ShowConsoleWindowImmediate() - { - ShowConsoleWindow(true); - } - - public static void ShowConsoleWindow(bool immediate) - { - if (ms_ConsoleWindow == null) - { - ms_ConsoleWindow = ScriptableObject.CreateInstance(); - ms_ConsoleWindow.Show(immediate); - ms_ConsoleWindow.Focus(); - } - else - { - ms_ConsoleWindow.Show(immediate); - ms_ConsoleWindow.Focus(); - } - } - - static internal void LoadIcons() - { - if (ms_LoadedIcons) - return; - - ms_LoadedIcons = true; - iconInfo = EditorGUIUtility.LoadIcon("console.infoicon"); - iconWarn = EditorGUIUtility.LoadIcon("console.warnicon"); - iconError = EditorGUIUtility.LoadIcon("console.erroricon"); - iconInfoSmall = EditorGUIUtility.LoadIcon("console.infoicon.sml"); - iconWarnSmall = EditorGUIUtility.LoadIcon("console.warnicon.sml"); - iconErrorSmall = EditorGUIUtility.LoadIcon("console.erroricon.sml"); - - // TODO: Once we get the proper monochrome images put them here. - /*iconInfoMono = EditorGUIUtility.LoadIcon("console.infoicon.mono"); - iconWarnMono = EditorGUIUtility.LoadIcon("console.warnicon.mono"); - iconErrorMono = EditorGUIUtility.LoadIcon("console.erroricon.mono");*/ - iconInfoMono = EditorGUIUtility.LoadIcon("console.infoicon.sml"); - iconWarnMono = EditorGUIUtility.LoadIcon("console.warnicon.inactive.sml"); - iconErrorMono = EditorGUIUtility.LoadIcon("console.erroricon.inactive.sml"); - Constants.Init(); - } - - [RequiredByNativeCode] - public static void LogChanged() - { - if (ms_ConsoleWindow == null) - return; - - ms_ConsoleWindow.DoLogChanged(); - } - - public void DoLogChanged() - { - ms_ConsoleWindow.Repaint(); - } - - public ConsoleWindow() - { - position = new Rect(200, 200, 800, 400); - m_ListView = new ListViewState(0, 0); - } - - void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - ms_ConsoleWindow = this; - m_DevBuild = Unsupported.IsDeveloperMode(); - - Constants.LogStyleLineCount = EditorPrefs.GetInt("ConsoleWindowLogLineCount", 2); - } - - void OnDisable() - { - if (ms_ConsoleWindow == this) - ms_ConsoleWindow = null; - } - - private int RowHeight - { - get - { - return (Constants.LogStyleLineCount * m_LineHeight) + m_BorderHeight; - } - } - - private static bool HasMode(int mode, Mode modeToCheck) { return (mode & (int)modeToCheck) != 0; } - private static bool HasFlag(ConsoleFlags flags) { return (LogEntries.consoleFlags & (int)flags) != 0; } - private static void SetFlag(ConsoleFlags flags, bool val) { LogEntries.SetConsoleFlag((int)flags, val); } - - static internal Texture2D GetIconForErrorMode(int mode, bool large) - { - // Errors - if (HasMode(mode, Mode.Fatal | Mode.Assert | - Mode.Error | Mode.ScriptingError | - Mode.AssetImportError | Mode.ScriptCompileError | - Mode.GraphCompileError | Mode.ScriptingAssertion)) - return large ? iconError : iconErrorSmall; - // Warnings - if (HasMode(mode, Mode.ScriptCompileWarning | Mode.ScriptingWarning | Mode.AssetImportWarning)) - return large ? iconWarn : iconWarnSmall; - // Logs - if (HasMode(mode, Mode.Log | Mode.ScriptingLog)) - return large ? iconInfo : iconInfoSmall; - - // Nothing - return null; - } - - static internal GUIStyle GetStyleForErrorMode(int mode, bool isIcon, bool isSmall) - { - // Errors - if (HasMode(mode, Mode.Fatal | Mode.Assert | - Mode.Error | Mode.ScriptingError | - Mode.AssetImportError | Mode.ScriptCompileError | - Mode.GraphCompileError | Mode.ScriptingAssertion)) - { - if (isIcon) - { - if (isSmall) - { - return Constants.IconErrorSmallStyle; - } - return Constants.IconErrorStyle; - } - - if (isSmall) - { - return Constants.ErrorSmallStyle; - } - return Constants.ErrorStyle; - } - // Warnings - if (HasMode(mode, Mode.ScriptCompileWarning | Mode.ScriptingWarning | Mode.AssetImportWarning)) - { - if (isIcon) - { - if (isSmall) - { - return Constants.IconWarningSmallStyle; - } - return Constants.IconWarningStyle; - } - - if (isSmall) - { - return Constants.WarningSmallStyle; - } - return Constants.WarningStyle; - } - // Logs - if (isIcon) - { - if (isSmall) - { - return Constants.IconLogSmallStyle; - } - return Constants.IconLogStyle; - } - - if (isSmall) - { - return Constants.LogSmallStyle; - } - return Constants.LogStyle; - } - - static internal GUIStyle GetStatusStyleForErrorMode(int mode) - { - // Errors - if (HasMode(mode, Mode.Fatal | Mode.Assert | - Mode.Error | Mode.ScriptingError | - Mode.AssetImportError | Mode.ScriptCompileError | - Mode.GraphCompileError | Mode.ScriptingAssertion)) - return Constants.StatusError; - // Warnings - if (HasMode(mode, Mode.ScriptCompileWarning | Mode.ScriptingWarning | Mode.AssetImportWarning)) - return Constants.StatusWarn; - // Logs - return Constants.StatusLog; - } - - static string ContextString(LogEntry entry) - { - StringBuilder context = new StringBuilder(); - - if (HasMode(entry.mode, Mode.Error)) - context.Append("Error "); - else if (HasMode(entry.mode, Mode.Log)) - context.Append("Log "); - else - context.Append("Assert "); - - context.Append("in file: "); - context.Append(entry.file); - context.Append(" at line: "); - context.Append(entry.line); - - if (entry.errorNum != 0) - { - context.Append(" and errorNum: "); - context.Append(entry.errorNum); - } - - return context.ToString(); - } - - static string GetFirstLine(string s) - { - int i = s.IndexOf("\n"); - return (i != -1) ? s.Substring(0, i) : s; - } - - static string GetFirstTwoLines(string s) - { - int i = s.IndexOf("\n"); - if (i != -1) - { - i = s.IndexOf("\n", i + 1); - if (i != -1) - return s.Substring(0, i); - } - - return s; - } - - void SetActiveEntry(LogEntry entry) - { - if (entry != null) - { - m_ActiveText = entry.condition; - // ping object referred by the log entry - if (m_ActiveInstanceID != entry.instanceID) - { - m_ActiveInstanceID = entry.instanceID; - if (entry.instanceID != 0) - EditorGUIUtility.PingObject(entry.instanceID); - } - } - else - { - m_ActiveText = string.Empty; - m_ActiveInstanceID = 0; - m_ListView.row = -1; - } - } - - // Used implicitly with CallStaticMonoMethod("ConsoleWindow", "ShowConsoleRow", param); - static void ShowConsoleRow(int row) - { - ShowConsoleWindow(false); - - if (ms_ConsoleWindow) - { - ms_ConsoleWindow.m_ListView.row = row; - ms_ConsoleWindow.m_ListView.selectionChanged = true; - ms_ConsoleWindow.Repaint(); - } - } - - void UpdateListView() - { - m_HasUpdatedGuiStyles = true; - int newRowHeight = RowHeight; - - // We reset the scroll list to auto scrolling whenever the log entry count is modified - m_ListView.rowHeight = newRowHeight; - m_ListView.row = -1; - m_ListView.scrollPos.y = LogEntries.GetCount() * newRowHeight; - } - - void OnGUI() - { - Event e = Event.current; - LoadIcons(); - - if (!m_HasUpdatedGuiStyles) - { - m_LineHeight = Mathf.RoundToInt(Constants.ErrorStyle.lineHeight); - m_BorderHeight = Constants.ErrorStyle.border.top + Constants.ErrorStyle.border.bottom; - UpdateListView(); - } - - GUILayout.BeginHorizontal(Constants.Toolbar); - - if (GUILayout.Button(Constants.ClearLabel, Constants.MiniButton)) - { - LogEntries.Clear(); - GUIUtility.keyboardControl = 0; - } - - int currCount = LogEntries.GetCount(); - - if (m_ListView.totalRows != currCount && m_ListView.totalRows > 0) - { - // scroll bar was at the bottom? - if (m_ListView.scrollPos.y >= m_ListView.rowHeight * m_ListView.totalRows - ms_LVHeight) - { - m_ListView.scrollPos.y = currCount * RowHeight - ms_LVHeight; - } - } - - EditorGUILayout.Space(); - - bool wasCollapsed = HasFlag(ConsoleFlags.Collapse); - SetFlag(ConsoleFlags.Collapse, GUILayout.Toggle(wasCollapsed, Constants.CollapseLabel, Constants.MiniButtonLeft)); - - bool collapsedChanged = (wasCollapsed != HasFlag(ConsoleFlags.Collapse)); - if (collapsedChanged) - { - // unselect if collapsed flag changed - m_ListView.row = -1; - - // scroll to bottom - m_ListView.scrollPos.y = LogEntries.GetCount() * RowHeight; - } - - SetFlag(ConsoleFlags.ClearOnPlay, GUILayout.Toggle(HasFlag(ConsoleFlags.ClearOnPlay), Constants.ClearOnPlayLabel, Constants.MiniButtonMiddle)); - SetFlag(ConsoleFlags.ErrorPause, GUILayout.Toggle(HasFlag(ConsoleFlags.ErrorPause), Constants.ErrorPauseLabel, Constants.MiniButtonRight)); - - m_AttachProfilerUI.OnGUILayout(this); - - EditorGUILayout.Space(); - - if (m_DevBuild) - { - GUILayout.FlexibleSpace(); - SetFlag(ConsoleFlags.StopForAssert, GUILayout.Toggle(HasFlag(ConsoleFlags.StopForAssert), Constants.StopForAssertLabel, Constants.MiniButtonLeft)); - SetFlag(ConsoleFlags.StopForError, GUILayout.Toggle(HasFlag(ConsoleFlags.StopForError), Constants.StopForErrorLabel, Constants.MiniButtonRight)); - } - - GUILayout.FlexibleSpace(); - - int errorCount = 0, warningCount = 0, logCount = 0; - LogEntries.GetCountsByType(ref errorCount, ref warningCount, ref logCount); - EditorGUI.BeginChangeCheck(); - bool setLogFlag = GUILayout.Toggle(HasFlag(ConsoleFlags.LogLevelLog), new GUIContent((logCount <= 999 ? logCount.ToString() : "999+"), logCount > 0 ? iconInfoSmall : iconInfoMono), Constants.MiniButtonRight); - bool setWarningFlag = GUILayout.Toggle(HasFlag(ConsoleFlags.LogLevelWarning), new GUIContent((warningCount <= 999 ? warningCount.ToString() : "999+"), warningCount > 0 ? iconWarnSmall : iconWarnMono), Constants.MiniButtonMiddle); - bool setErrorFlag = GUILayout.Toggle(HasFlag(ConsoleFlags.LogLevelError), new GUIContent((errorCount <= 999 ? errorCount.ToString() : "999+"), errorCount > 0 ? iconErrorSmall : iconErrorMono), Constants.MiniButtonLeft); - // Active entry index may no longer be valid - if (EditorGUI.EndChangeCheck()) - SetActiveEntry(null); - - SetFlag(ConsoleFlags.LogLevelLog, setLogFlag); - SetFlag(ConsoleFlags.LogLevelWarning, setWarningFlag); - SetFlag(ConsoleFlags.LogLevelError, setErrorFlag); - - GUILayout.EndHorizontal(); - - SplitterGUILayout.BeginVerticalSplit(spl); - int rowHeight = RowHeight; - EditorGUIUtility.SetIconSize(new Vector2(rowHeight, rowHeight)); - GUIContent tempContent = new GUIContent(); - int id = GUIUtility.GetControlID(0); - - /////@TODO: Make Frame selected work with ListViewState - using (new GettingLogEntriesScope(m_ListView)) - { - int selectedRow = -1; - bool openSelectedItem = false; - bool collapsed = HasFlag(ConsoleFlags.Collapse); - foreach (ListViewElement el in ListViewGUI.ListView(m_ListView, Constants.Box)) - { - if (e.type == EventType.MouseDown && e.button == 0 && el.position.Contains(e.mousePosition)) - { - selectedRow = m_ListView.row; - if (e.clickCount == 2) - openSelectedItem = true; - } - else if (e.type == EventType.Repaint) - { - int mode = 0; - string text = null; - LogEntries.GetLinesAndModeFromEntryInternal(el.row, Constants.LogStyleLineCount, ref mode, ref text); - - // Draw the background - GUIStyle s = el.row % 2 == 0 ? Constants.OddBackground : Constants.EvenBackground; - s.Draw(el.position, false, false, m_ListView.row == el.row, false); - - // Draw the icon - GUIStyle iconStyle = GetStyleForErrorMode(mode, true, Constants.LogStyleLineCount == 1); - iconStyle.Draw(el.position, false, false, m_ListView.row == el.row, false); - - // Draw the text - tempContent.text = text; - GUIStyle errorModeStyle = GetStyleForErrorMode(mode, false, Constants.LogStyleLineCount == 1); - errorModeStyle.Draw(el.position, tempContent, id, m_ListView.row == el.row); - - if (collapsed) - { - Rect badgeRect = el.position; - tempContent.text = LogEntries.GetEntryCount(el.row).ToString(CultureInfo.InvariantCulture); - Vector2 badgeSize = Constants.CountBadge.CalcSize(tempContent); - badgeRect.xMin = badgeRect.xMax - badgeSize.x; - badgeRect.yMin += ((badgeRect.yMax - badgeRect.yMin) - badgeSize.y) * 0.5f; - badgeRect.x -= 5f; - GUI.Label(badgeRect, tempContent, Constants.CountBadge); - } - } - } - - if (selectedRow != -1) - { - if (m_ListView.scrollPos.y >= m_ListView.rowHeight * m_ListView.totalRows - ms_LVHeight) - m_ListView.scrollPos.y = m_ListView.rowHeight * m_ListView.totalRows - ms_LVHeight - 1; - } - - // Make sure the selected entry is up to date - if (m_ListView.totalRows == 0 || m_ListView.row >= m_ListView.totalRows || m_ListView.row < 0) - { - if (m_ActiveText.Length != 0) - SetActiveEntry(null); - } - else - { - LogEntry entry = new LogEntry(); - LogEntries.GetEntryInternal(m_ListView.row, entry); - SetActiveEntry(entry); - - // see if selected entry changed. if so - clear additional info - LogEntries.GetEntryInternal(m_ListView.row, entry); - if (m_ListView.selectionChanged || !m_ActiveText.Equals(entry.condition)) - { - SetActiveEntry(entry); - } - } - - // Open entry using return key - if ((GUIUtility.keyboardControl == m_ListView.ID) && (e.type == EventType.KeyDown) && (e.keyCode == KeyCode.Return) && (m_ListView.row != 0)) - { - selectedRow = m_ListView.row; - openSelectedItem = true; - } - - if (e.type != EventType.Layout && ListViewGUI.ilvState.rectHeight != 1) - ms_LVHeight = ListViewGUI.ilvState.rectHeight; - - if (openSelectedItem) - { - LogEntries.RowGotDoubleClicked(selectedRow); - Event.current.Use(); - } - } - - EditorGUIUtility.SetIconSize(Vector2.zero); - - // Display active text (We want word wrapped text with a vertical scrollbar) - m_TextScroll = GUILayout.BeginScrollView(m_TextScroll, Constants.Box); - float height = Constants.MessageStyle.CalcHeight(GUIContent.Temp(m_ActiveText), position.width); - EditorGUILayout.SelectableLabel(m_ActiveText, Constants.MessageStyle, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true), GUILayout.MinHeight(height)); - GUILayout.EndScrollView(); - - SplitterGUILayout.EndVerticalSplit(); - - // Copy & Paste selected item - if ((e.type == EventType.ValidateCommand || e.type == EventType.ExecuteCommand) && e.commandName == EventCommandNames.Copy && m_ActiveText != string.Empty) - { - if (e.type == EventType.ExecuteCommand) - EditorGUIUtility.systemCopyBuffer = m_ActiveText; - e.Use(); - } - } - - public static bool GetConsoleErrorPause() - { - return HasFlag(ConsoleFlags.ErrorPause); - } - - public static void SetConsoleErrorPause(bool enabled) - { - SetFlag(ConsoleFlags.ErrorPause, enabled); - } - - public struct StackTraceLogTypeData - { - public LogType logType; - public StackTraceLogType stackTraceLogType; - } - - public void ToggleLogStackTraces(object userData) - { - StackTraceLogTypeData data = (StackTraceLogTypeData)userData; - PlayerSettings.SetStackTraceLogType(data.logType, data.stackTraceLogType); - } - - public void ToggleLogStackTracesForAll(object userData) - { - foreach (LogType logType in Enum.GetValues(typeof(LogType))) - PlayerSettings.SetStackTraceLogType(logType, (StackTraceLogType)userData); - } - - public void AddItemsToMenu(GenericMenu menu) - { - if (Application.platform == RuntimePlatform.OSXEditor) - menu.AddItem(EditorGUIUtility.TrTextContent("Open Player Log"), false, UnityEditorInternal.InternalEditorUtility.OpenPlayerConsole); - menu.AddItem(EditorGUIUtility.TrTextContent("Open Editor Log"), false, UnityEditorInternal.InternalEditorUtility.OpenEditorConsole); - - menu.AddItem(EditorGUIUtility.TrTextContent("Show Timestamp"), HasFlag(ConsoleFlags.ShowTimestamp), SetTimestamp); - - for (int i = 1; i <= 10; ++i) - { - var lineString = i == 1 ? "Line" : "Lines"; - menu.AddItem(new GUIContent(string.Format("Log Entry/{0} {1}", i, lineString)), i == Constants.LogStyleLineCount, SetLogLineCount, i); - } - - AddStackTraceLoggingMenu(menu); - } - - private void SetTimestamp() - { - SetFlag(ConsoleFlags.ShowTimestamp, !HasFlag(ConsoleFlags.ShowTimestamp)); - } - - private void SetLogLineCount(object obj) - { - int count = (int)obj; - EditorPrefs.SetInt("ConsoleWindowLogLineCount", count); - Constants.LogStyleLineCount = count; - - UpdateListView(); - } - - private void AddStackTraceLoggingMenu(GenericMenu menu) - { - // TODO: Maybe remove this, because it basically duplicates UI in PlayerSettings - foreach (LogType logType in Enum.GetValues(typeof(LogType))) - { - foreach (StackTraceLogType stackTraceLogType in Enum.GetValues(typeof(StackTraceLogType))) - { - StackTraceLogTypeData data; - data.logType = logType; - data.stackTraceLogType = stackTraceLogType; - - menu.AddItem(EditorGUIUtility.TrTextContent("Stack Trace Logging/" + logType + "/" + stackTraceLogType), PlayerSettings.GetStackTraceLogType(logType) == stackTraceLogType, - ToggleLogStackTraces, data); - } - } - - int stackTraceLogTypeForAll = (int)PlayerSettings.GetStackTraceLogType(LogType.Log); - foreach (LogType logType in Enum.GetValues(typeof(LogType))) - { - if (PlayerSettings.GetStackTraceLogType(logType) != (StackTraceLogType)stackTraceLogTypeForAll) - { - stackTraceLogTypeForAll = -1; - break; - } - } - - foreach (StackTraceLogType stackTraceLogType in Enum.GetValues(typeof(StackTraceLogType))) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Stack Trace Logging/All/" + stackTraceLogType), (StackTraceLogType)stackTraceLogTypeForAll == stackTraceLogType, - ToggleLogStackTracesForAll, stackTraceLogType); - } - } - - private static event EntryDoubleClickedDelegate entryWithManagedCallbackDoubleClicked; - - private static void SendEntryDoubleClicked(LogEntry entry) - { - if (ConsoleWindow.entryWithManagedCallbackDoubleClicked != null) - ConsoleWindow.entryWithManagedCallbackDoubleClicked(entry); - } - } - - internal class GettingLogEntriesScope : IDisposable - { - private bool m_Disposed; - - public GettingLogEntriesScope(ListViewState listView) - { - listView.totalRows = LogEntries.StartGettingEntries(); - } - - public void Dispose() - { - if (m_Disposed) - return; - LogEntries.EndGettingEntries(); - m_Disposed = true; - } - - ~GettingLogEntriesScope() - { - if (!m_Disposed) - Debug.LogError("Scope was not disposed! You should use the 'using' keyword or manually call Dispose."); - } - } -} diff --git a/Editor/Mono/ContainerWindow.cs b/Editor/Mono/ContainerWindow.cs deleted file mode 100644 index 7f6c01b585..0000000000 --- a/Editor/Mono/ContainerWindow.cs +++ /dev/null @@ -1,454 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Linq; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using IntPtr = System.IntPtr; -using System; - -namespace UnityEditor -{ - // See ContainerWindow.bindings for bindings - - [StructLayout(LayoutKind.Sequential)] - internal partial class ContainerWindow : ScriptableObject - { - [SerializeField] - MonoReloadableIntPtr m_WindowPtr; - - #pragma warning disable 0414 - [SerializeField] - Rect m_PixelRect; - [SerializeField] - int m_ShowMode; - [SerializeField] - string m_Title = ""; - #pragma warning restore 0414 - - [SerializeField] - [UnityEngine.Serialization.FormerlySerializedAs("m_MainView")] - View m_RootView; - [SerializeField] - Vector2 m_MinSize = new Vector2(120, 80); - [SerializeField] - Vector2 m_MaxSize = new Vector2(4000, 4000); - - internal bool m_DontSaveToLayout = false; - - const float kBorderSize = 4; - const float kTitleHeight = 24; - - private int m_ButtonCount; - private float m_TitleBarWidth; - - // Fit a container window to the screen. - static internal bool macEditor { get { return Application.platform == RuntimePlatform.OSXEditor; } } - - const float kButtonWidth = 13, kButtonHeight = 13, kButtonSpacing = 3, kButtonTop = 0; - - private static class Styles - { - // Title Bar Buttons (Non) - public static GUIStyle buttonClose = macEditor ? "WinBtnCloseMac" : "WinBtnClose"; - public static GUIStyle buttonMin = macEditor ? "WinBtnMinMac" : "WinBtnClose"; - public static GUIStyle buttonMax = macEditor ? "WinBtnMaxMac" : "WinBtnMax"; - - // Title Bar Button when window is not focused (OSX only) - public static GUIStyle buttonInactive = "WinBtnInactiveMac"; - } - - public ContainerWindow() - { - m_PixelRect = new Rect(0, 0, 400, 300); - } - - private void __internalAwake() - { - hideFlags = HideFlags.DontSave; - } - - internal ShowMode showMode { get { return (ShowMode)m_ShowMode; } } - - internal static bool IsPopup(ShowMode mode) - { - return (ShowMode.PopupMenu == mode || ShowMode.PopupMenuWithKeyboardFocus == mode); - } - - internal bool isPopup { get { return IsPopup((ShowMode)m_ShowMode); } } - - internal void ShowPopup() - { - m_ShowMode = (int)ShowMode.PopupMenu; - Internal_Show(m_PixelRect, m_ShowMode, m_MinSize, m_MaxSize); - if (m_RootView) - m_RootView.SetWindowRecurse(this); - Internal_SetTitle(m_Title); - Save(); - Internal_BringLiveAfterCreation(false, false); - } - - static Color skinBackgroundColor - { - get - { - return EditorGUIUtility.isProSkin ? Color.gray.RGBMultiplied(0.3f).AlphaMultiplied(0.5f) : Color.gray.AlphaMultiplied(0.32f); - } - } - - // Show the editor window. - public void Show(ShowMode showMode, bool loadPosition, bool displayImmediately) - { - if (showMode == ShowMode.AuxWindow) - showMode = ShowMode.Utility; - - if (showMode == ShowMode.Utility || IsPopup(showMode)) - m_DontSaveToLayout = true; - - m_ShowMode = (int)showMode; - - // Load previous position/size - if (!isPopup) - Load(loadPosition); - - Internal_Show(m_PixelRect, m_ShowMode, m_MinSize, m_MaxSize); - - // Tell the mainview its now in this window (quick hack to get platform-specific code to move its views to the right window) - if (m_RootView) - m_RootView.SetWindowRecurse(this); - Internal_SetTitle(m_Title); - - SetBackgroundColor(skinBackgroundColor); - - Internal_BringLiveAfterCreation(displayImmediately, true); - - // Window could be killed by now in user callbacks... - if (this == null) - return; - - // Fit window to screen - needs to be done after bringing the window live - position = FitWindowRectToScreen(m_PixelRect, true, false); - rootView.position = new Rect(0, 0, m_PixelRect.width, m_PixelRect.height); - rootView.Reflow(); - - // save position right away - Save(); - } - - public void OnEnable() - { - if (m_RootView) - m_RootView.Initialize(this); - SetBackgroundColor(skinBackgroundColor); - } - - public void SetMinMaxSizes(Vector2 min, Vector2 max) - { - m_MinSize = min; - m_MaxSize = max; - Rect r = position; - Rect r2 = r; - r2.width = Mathf.Clamp(r.width, min.x, max.x); - r2.height = Mathf.Clamp(r.height, min.y, max.y); - if (r2.width != r.width || r2.height != r.height) - position = r2; - Internal_SetMinMaxSizes(min, max); - } - - internal void InternalCloseWindow() - { - Save(); - if (m_RootView) - { - if (m_RootView is GUIView) - ((GUIView)m_RootView).RemoveFromAuxWindowList(); - DestroyImmediate(m_RootView, true); - m_RootView = null; - } - - DestroyImmediate(this, true); - } - - public void Close() - { - Save(); - InternalClose(); - DestroyImmediate(this, true); - } - - internal bool IsNotDocked() - { - return ( // halleluja - - (m_ShowMode == (int)ShowMode.Utility || m_ShowMode == (int)ShowMode.AuxWindow) || - - (rootView is SplitView && - rootView.children.Length == 1 && - rootView.children[0] is DockArea && - ((DockArea)rootView.children[0]).m_Panes.Count == 1) - ); - } - - private string NotDockedWindowID() - { - if (IsNotDocked()) - { - HostView v = rootView as HostView; - - if (v == null) - { - if (rootView is SplitView) - v = (HostView)rootView.children[0]; - else - return rootView.GetType().ToString(); - } - - - return (m_ShowMode == (int)ShowMode.Utility || m_ShowMode == (int)ShowMode.AuxWindow) ? v.actualView.GetType().ToString() - : ((DockArea)rootView.children[0]).m_Panes[0].GetType().ToString(); - } - else - return null; - } - - public void Save() - { - // only save it if its not docked and its not the MainWindow - if ((m_ShowMode != (int)ShowMode.MainWindow) && IsNotDocked() && !IsZoomed()) - { - string ID = NotDockedWindowID(); - - // save position/size - EditorPrefs.SetFloat(ID + "x", m_PixelRect.x); - EditorPrefs.SetFloat(ID + "y", m_PixelRect.y); - EditorPrefs.SetFloat(ID + "w", m_PixelRect.width); - EditorPrefs.SetFloat(ID + "h", m_PixelRect.height); - } - } - - private void Load(bool loadPosition) - { - if ((m_ShowMode != (int)ShowMode.MainWindow) && IsNotDocked()) - { - string ID = NotDockedWindowID(); - - // get position/size - Rect p = m_PixelRect; - if (loadPosition) - { - p.x = EditorPrefs.GetFloat(ID + "x", m_PixelRect.x); - p.y = EditorPrefs.GetFloat(ID + "y", m_PixelRect.y); - } - p.width = Mathf.Max(EditorPrefs.GetFloat(ID + "w", m_PixelRect.width), m_MinSize.x); - p.width = Mathf.Min(p.width, m_MaxSize.x); - p.height = Mathf.Max(EditorPrefs.GetFloat(ID + "h", m_PixelRect.height), m_MinSize.y); - p.height = Mathf.Min(p.height, m_MaxSize.y); - m_PixelRect = p; - } - } - - internal void OnResize() - { - if (rootView == null) - return; - rootView.position = new Rect(0, 0, position.width, position.height); - - // save position - Save(); - } - - // The title of the window - public string title - { - get { return m_Title; } - set { m_Title = value; Internal_SetTitle(value); } - } - - // Array of all visible ContainerWindows, from frontmost to last - static List s_AllWindows = new List(); - public static ContainerWindow[] windows - { - get - { - s_AllWindows.Clear(); - GetOrderedWindowList(); - return s_AllWindows.ToArray(); - } - } - - internal void AddToWindowList() - { - s_AllWindows.Add(this); - } - - // TODO: Handle title bar height and other things - public Vector2 WindowToScreenPoint(Vector2 windowPoint) - { - Vector2 hmm; - Internal_GetTopleftScreenPosition(out hmm); - return windowPoint + hmm;// + new Vector2 (position.x, position.y) + hmm; - } - - public View rootView - { - get { return m_RootView; } - set - { - m_RootView = value; - m_RootView.SetWindowRecurse(this); - m_RootView.position = new Rect(0, 0, position.width, position.height); - m_MinSize = value.minSize; - m_MaxSize = value.maxSize; - } - } - - public SplitView rootSplitView - { - get - { - if (m_ShowMode == (int)ShowMode.MainWindow && rootView && rootView.children.Length == 3) - return rootView.children[1] as SplitView; - else - return rootView as SplitView; - } - } - - internal string DebugHierarchy() - { - return rootView.DebugHierarchy(0); - } - - internal Rect GetDropDownRect(Rect buttonRect, Vector2 minSize, Vector2 maxSize, PopupLocationHelper.PopupLocation[] locationPriorityOrder) - { - return PopupLocationHelper.GetDropDownRect(buttonRect, minSize, maxSize, this, locationPriorityOrder); - } - - internal Rect GetDropDownRect(Rect buttonRect, Vector2 minSize, Vector2 maxSize) - { - return PopupLocationHelper.GetDropDownRect(buttonRect, minSize, maxSize, this); - } - - internal Rect FitPopupWindowRectToScreen(Rect rect, float minimumHeight) - { - const float maxHeight = 900; - float spaceFromBottom = 0f; - if (Application.platform == RuntimePlatform.OSXEditor) - spaceFromBottom = 10f; - - float minHeight = minimumHeight + spaceFromBottom; - Rect p = rect; - p.height = Mathf.Min(p.height, maxHeight); - p.height += spaceFromBottom; - p = FitWindowRectToScreen(p, true, true); - - float newHeight = Mathf.Max(p.yMax - rect.y, minHeight); - p.y = p.yMax - newHeight; - p.height = newHeight - spaceFromBottom; - - return p; - } - - public void HandleWindowDecorationEnd(Rect windowPosition) - { - // No Op - } - - public void HandleWindowDecorationStart(Rect windowPosition) - { - bool hasTitleBar = (windowPosition.y == 0 && showMode != ShowMode.Utility && !isPopup); - - if (!hasTitleBar) - return; - - bool hasWindowButtons = Mathf.Abs(windowPosition.xMax - position.width) < 2; - if (hasWindowButtons) - { - GUIStyle close = Styles.buttonClose; - GUIStyle min = Styles.buttonMin; - GUIStyle max = Styles.buttonMax; - - if (macEditor && (GUIView.focusedView == null || GUIView.focusedView.window != this)) - close = min = max = Styles.buttonInactive; - - BeginTitleBarButtons(windowPosition); - if (TitleBarButton(close)) - Close(); - if (macEditor && TitleBarButton(min)) - { - Minimize(); - GUIUtility.ExitGUI(); - } - if (TitleBarButton(max)) - ToggleMaximize(); - } - - DragTitleBar(new Rect(0, 0, position.width, kTitleHeight)); - } - - private void BeginTitleBarButtons(Rect windowPosition) - { - m_ButtonCount = 0; - m_TitleBarWidth = windowPosition.width; - } - - private bool TitleBarButton(GUIStyle style) - { - var buttonRect = new Rect(m_TitleBarWidth - kButtonWidth * ++m_ButtonCount - kBorderSize, kButtonTop, kButtonWidth, kButtonHeight); - return GUI.Button(buttonRect, GUIContent.none, style); - } - - // Snapping windows - static Vector2 s_LastDragMousePos; - static Rect dragPosition; - private void DragTitleBar(Rect titleBarRect) - { - int id = GUIUtility.GetControlID(FocusType.Passive); - Event evt = Event.current; - - switch (evt.GetTypeForControl(id)) - { - case EventType.Repaint: - EditorGUIUtility.AddCursorRect(titleBarRect, MouseCursor.Arrow); - break; - case EventType.MouseDown: - // If the mouse is inside the title bar rect, we say that we're the hot control - if (titleBarRect.Contains(evt.mousePosition) && GUIUtility.hotControl == 0 && evt.button == 0) - { - GUIUtility.hotControl = id; - Event.current.Use(); - s_LastDragMousePos = GUIUtility.GUIToScreenPoint(evt.mousePosition); - dragPosition = position; - Unsupported.SetAllowCursorLock(false, Unsupported.DisallowCursorLockReasons.SizeMove); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - Event.current.Use(); - Unsupported.SetAllowCursorLock(true, Unsupported.DisallowCursorLockReasons.SizeMove); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - Vector2 absMouse = GUIUtility.GUIToScreenPoint(evt.mousePosition); - Vector2 movement = absMouse - s_LastDragMousePos; - s_LastDragMousePos = absMouse; - - dragPosition.x += movement.x; - dragPosition.y += movement.y; - position = dragPosition; - - GUI.changed = true; - } - break; - } - } - } -} //namespace diff --git a/Editor/Mono/CustomEditorAttributes.cs b/Editor/Mono/CustomEditorAttributes.cs deleted file mode 100644 index b57a830a1e..0000000000 --- a/Editor/Mono/CustomEditorAttributes.cs +++ /dev/null @@ -1,183 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using System; -using System.Reflection; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - /// Remap Viewed type to inspector type - internal class CustomEditorAttributes - { - private static readonly Dictionary> kSCustomEditors = new Dictionary>(); - private static readonly Dictionary> kSCustomMultiEditors = new Dictionary>(); - private static bool s_Initialized; - - class MonoEditorType - { - public Type m_InspectedType; - public Type m_InspectorType; - public Type m_RenderPipelineType; - public bool m_EditorForChildClasses; - public bool m_IsFallback; - } - - internal static Type FindCustomEditorType(UnityEngine.Object o, bool multiEdit) - { - return FindCustomEditorTypeByType(o.GetType(), multiEdit); - } - - private static List s_SearchCache = new List(); - internal static Type FindCustomEditorTypeByType(Type type, bool multiEdit) - { - if (!s_Initialized) - { - var editorAssemblies = EditorAssemblies.loadedAssemblies; - for (int i = editorAssemblies.Length - 1; i >= 0; i--) - Rebuild(editorAssemblies[i]); - - s_Initialized = true; - } - - if (type == null) - return null; - - var editors = multiEdit ? kSCustomMultiEditors : kSCustomEditors; - for (int pass = 0; pass < 2; ++pass) - { - for (Type inspected = type; inspected != null; inspected = inspected.BaseType) - { - List foundEditors; - if (!editors.TryGetValue(inspected, out foundEditors)) - { - if (!inspected.IsGenericType) - continue; - - inspected = inspected.GetGenericTypeDefinition(); - - if (!editors.TryGetValue(inspected, out foundEditors)) - continue; - } - - s_SearchCache.Clear(); - foreach (var result in foundEditors) - { - if (!IsAppropriateEditor(result, inspected, type != inspected, pass == 1)) - continue; - - s_SearchCache.Add(result); - } - - Type toUse = null; - - // we have a render pipeline... - // we need to select the one with the correct RP asset - if (GraphicsSettings.renderPipelineAsset != null) - { - var rpType = GraphicsSettings.renderPipelineAsset.GetType(); - foreach (var editor in s_SearchCache) - { - if (editor.m_RenderPipelineType == rpType) - { - toUse = editor.m_InspectorType; - break; - } - } - } - - // no RP, fallback! - if (toUse == null) - { - foreach (var editor in s_SearchCache) - { - if (editor.m_RenderPipelineType == null) - { - toUse = editor.m_InspectorType; - break; - } - } - } - - s_SearchCache.Clear(); - if (toUse != null) - return toUse; - } - } - return null; - } - - private static bool IsAppropriateEditor(MonoEditorType editor, Type parentClass, bool isChildClass, bool isFallback) - { - if (isChildClass && !editor.m_EditorForChildClasses) - // skip if it's a child class and this editor doesn't want to match on children - return false; - if (isFallback != editor.m_IsFallback) - return false; - - return parentClass == editor.m_InspectedType || - (parentClass.IsGenericType && parentClass.GetGenericTypeDefinition() == editor.m_InspectedType); - } - - internal static void Rebuild(Assembly assembly) - { - Type[] types = AssemblyHelper.GetTypesFromAssembly(assembly); - foreach (var type in types) - { - object[] attrs = type.GetCustomAttributes(typeof(CustomEditor), false); - - foreach (CustomEditor inspectAttr in attrs) - { - var t = new MonoEditorType(); - if (inspectAttr.m_InspectedType == null) - Debug.Log("Can't load custom inspector " + type.Name + " because the inspected type is null."); - else if (!type.IsSubclassOf(typeof(Editor))) - { - // Suppress a warning on TweakMode, we did this bad in the default project folder - // and it's going to be too hard for customers to figure out how to fix it and also quite pointless. - if (type.FullName == "TweakMode" && type.IsEnum && - inspectAttr.m_InspectedType.FullName == "BloomAndFlares") - continue; - - Debug.LogWarning( - type.Name + - " uses the CustomEditor attribute but does not inherit from Editor.\nYou must inherit from Editor. See the Editor class script documentation."); - } - else - { - t.m_InspectedType = inspectAttr.m_InspectedType; - t.m_InspectorType = type; - t.m_EditorForChildClasses = inspectAttr.m_EditorForChildClasses; - t.m_IsFallback = inspectAttr.isFallback; - var attr = inspectAttr as CustomEditorForRenderPipelineAttribute; - if (attr != null) - t.m_RenderPipelineType = attr.renderPipelineType; - - List editors; - if (!kSCustomEditors.TryGetValue(inspectAttr.m_InspectedType, out editors)) - { - editors = new List(); - kSCustomEditors[inspectAttr.m_InspectedType] = editors; - } - editors.Add(t); - - if (type.GetCustomAttributes(typeof(CanEditMultipleObjects), false).Length > 0) - { - List multiEditors; - if (!kSCustomMultiEditors.TryGetValue(inspectAttr.m_InspectedType, out multiEditors)) - { - multiEditors = new List(); - kSCustomMultiEditors[inspectAttr.m_InspectedType] = multiEditors; - } - multiEditors.Add(t); - } - } - } - } - } - } -} diff --git a/Editor/Mono/DataWatchService.cs b/Editor/Mono/DataWatchService.cs deleted file mode 100644 index 89c27f7839..0000000000 --- a/Editor/Mono/DataWatchService.cs +++ /dev/null @@ -1,252 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine.Experimental.UIElements; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - class DataWatchHandle : IDataWatchHandle - { - public readonly int id; - public WeakReference service; - - public Object watched { get; private set; } - - public DataWatchHandle(int id, DataWatchService service, Object watched) - { - this.id = id; - this.service = new WeakReference(service); - this.watched = watched; - } - - public bool disposed - { - get - { - return ReferenceEquals(watched, null); - } - } - - public void Dispose() - { - if (disposed) - { - throw new InvalidOperationException("DataWatchHandle was already disposed of"); - } - if (service != null && service.IsAlive) - { - (service.Target as DataWatchService).RemoveWatch(this); - } - service = null; - watched = null; - } - } - - internal class DataWatchService : IDataWatchService - { - public static DataWatchService sharedInstance = new DataWatchService(); - private TimerEventScheduler m_Scheduler = new TimerEventScheduler(); - - internal bool disableThrottling - { - get { return m_Scheduler.disableThrottling; } - set { m_Scheduler.disableThrottling = value; } - } - - struct Spy - { - public readonly int handleID; - public readonly Action onDataChanged; - - public Spy(int handleID, Action onDataChanged) - { - this.handleID = handleID; - this.onDataChanged = onDataChanged; - } - } - - private class Watchers - { - public List spyList; - public ChangeTrackerHandle tracker; - public IScheduledItem scheduledItem; - public Object watchedObject; - private DataWatchService service; - - public bool isModified { get; set; } - - public Watchers(Object watched, DataWatchService dataWatch) - { - spyList = new List(); - tracker = ChangeTrackerHandle.AcquireTracker(watched); - watchedObject = watched; - service = dataWatch; - } - - public void AddSpy(int handle, Action onDataChanged) - { - spyList.Add(new Spy(handle, onDataChanged)); - } - - public bool IsEmpty() - { - return spyList == null; - } - - public void OnTimerPoolForChanges(TimerState ts) - { - if (PollForChanges()) - { - isModified = false; - service.NotifyDataChanged(this); - } - } - - public bool PollForChanges() - { - if (watchedObject == null) //object could have been deleted - { - isModified = true; - } - else - { - //we need to poll the tracker first if it exists, since it needs to update the object checksum - if (tracker.PollForChanges()) - { - isModified = true; - } - } - - return isModified; - } - } - - private Dictionary m_Handles = new Dictionary(); - private Dictionary m_Watched = new Dictionary(); - - public DataWatchService() - { - // TODO probably just do this when panel becomes active and stop when being inactive - Undo.postprocessModifications += PostProcessUndo; - } - - ~DataWatchService() - { - Undo.postprocessModifications -= PostProcessUndo; - } - - // callback to watch undo stack for changes - // TODO: add the hook before animation strips some changes in record mode - public UndoPropertyModification[] PostProcessUndo(UndoPropertyModification[] modifications) - { - foreach (var m in modifications) - { - var cv = m.currentValue; - if (cv == null || cv.target == null) - continue; - Watchers w; - if (m_Watched.TryGetValue(cv.target, out w)) - { - w.isModified = true; - } - } - return modifications; - } - - public void ForceDirtyNextPoll(Object obj) - { - Watchers watch; - if (m_Watched.TryGetValue(obj, out watch)) - { - watch.tracker.ForceDirtyNextPoll(); - watch.isModified = true; - } - } - - // go through all trackers and poll their native revisions - public void PollNativeData() - { - //using the scheduler allows us to automatically throttle data polling - m_Scheduler.UpdateScheduledEvents(); - } - - static List notificationTmpSpies = new List(); - - private void NotifyDataChanged(Watchers w) - { - notificationTmpSpies.Clear(); - notificationTmpSpies.AddRange(w.spyList); - - foreach (Spy spy in notificationTmpSpies) - { - spy.onDataChanged(w.watchedObject); - } - - if (w.watchedObject == null) - { - DoRemoveWatcher(w); - } - } - - private void DoRemoveWatcher(Watchers watchers) - { - m_Watched.Remove(watchers.watchedObject); - m_Scheduler.Unschedule(watchers.scheduledItem); - watchers.tracker.ReleaseTracker(); - } - - static int s_WatchID; - - public IDataWatchHandle AddWatch(Object watched, Action onDataChanged) - { - if (watched == null) - throw new ArgumentException("Object watched cannot be null"); - - DataWatchHandle handle = new DataWatchHandle(++s_WatchID, this, watched); - m_Handles[handle.id] = handle; - - Watchers watchers; - if (!m_Watched.TryGetValue(watched, out watchers)) - { - watchers = new Watchers(watched, this); - m_Watched[watched] = watchers; - - watchers.scheduledItem = m_Scheduler.ScheduleUntil(watchers.OnTimerPoolForChanges, 0, 0, null); //we poll as often as possible - } - watchers.spyList.Add(new Spy(handle.id, onDataChanged)); - return handle; - } - - public void RemoveWatch(IDataWatchHandle handle) - { - DataWatchHandle handleImpl = (DataWatchHandle)handle; - - if (m_Handles.Remove(handleImpl.id)) - { - Watchers watchers; - if (m_Watched.TryGetValue(handleImpl.watched, out watchers)) - { - List spyList = watchers.spyList; - for (int i = 0; i < spyList.Count; i++) - { - Spy spy = spyList[i]; - if (spy.handleID == handleImpl.id) - { - spyList.RemoveAt(i); - if (watchers.IsEmpty()) - { - DoRemoveWatcher(watchers); - } - } - } - } - return; - } - throw new ArgumentException("Data watch was not registered"); - } - } -} diff --git a/Editor/Mono/DefaultAsset.bindings.cs b/Editor/Mono/DefaultAsset.bindings.cs deleted file mode 100644 index b69efe56ee..0000000000 --- a/Editor/Mono/DefaultAsset.bindings.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/AssetPipeline/DefaultImporter.h")] - // This class is public for users to be able to make custom editors for this type (see case 656580) - public class DefaultAsset : UnityEngine.Object - { - private DefaultAsset() {} - internal extern string message { get; } - internal extern bool isWarning {[NativeName("IsWarning")] get; } - } - - [CustomEditor(typeof(DefaultAsset), isFallback = true)] // fallback so broad-matching user inspectors always win (e.g. case #656580) - class DefaultAssetInspector : Editor - { - public override void OnInspectorGUI() - { - var defaultAsset = (DefaultAsset)target; - if (defaultAsset.message.Length > 0) - { - EditorGUILayout.HelpBox( - defaultAsset.message, - defaultAsset.isWarning ? MessageType.Warning : MessageType.Info); - } - } - } -} diff --git a/Editor/Mono/DeploymentTargets/DefaultDeploymentTargetsExtension.cs b/Editor/Mono/DeploymentTargets/DefaultDeploymentTargetsExtension.cs deleted file mode 100644 index 7b7b938de9..0000000000 --- a/Editor/Mono/DeploymentTargets/DefaultDeploymentTargetsExtension.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.Modules; - -namespace UnityEditor.DeploymentTargets -{ - internal class DefaultDeploymentTargetInfo : IDeploymentTargetInfo - { - public virtual FlagSet GetSupportFlags() - { - return DeploymentTargetSupportFlags.None; - } - - public virtual TargetCheckResult CheckTarget(DeploymentTargetRequirements targetRequirements) - { - return new TargetCheckResult(); - } - - public string GetDisplayName() - { - return ""; - } - } - - internal abstract class DefaultDeploymentTargetsExtension - : IDeploymentTargetsExtension - { - public virtual List GetKnownTargets(ProgressHandler progressHandler = null) - { - return new List(); - } - - public virtual IDeploymentTargetInfo GetTargetInfo(DeploymentTargetId targetId, ProgressHandler progressHandler = null) - { - return new DefaultDeploymentTargetInfo(); - } - - public virtual void LaunchBuildOnTarget(BuildProperties buildProperties, DeploymentTargetId targetId, ProgressHandler progressHandler = null) - { - throw new NotSupportedException(); - } - } -} diff --git a/Editor/Mono/DeploymentTargets/DeploymentTargetManager.cs b/Editor/Mono/DeploymentTargets/DeploymentTargetManager.cs deleted file mode 100644 index af4cf30648..0000000000 --- a/Editor/Mono/DeploymentTargets/DeploymentTargetManager.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Modules; -using UnityEditor.Build.Reporting; -using UnityEngine; - -namespace UnityEditor.DeploymentTargets -{ - internal class DeploymentTargetManager - { - const string kExtensionErrorMessage = "Platform does not implement DeploymentTargetsExtension"; - - private static IDeploymentTargetsExtension GetExtension(BuildTargetGroup targetGroup, BuildTarget buildTarget) - { - IDeploymentTargetsExtension extension = ModuleManager.GetDeploymentTargetsExtension(targetGroup, buildTarget); - if (extension == null) - throw new NotSupportedException(kExtensionErrorMessage); - return extension; - } - - public static bool IsExtensionSupported(BuildTargetGroup targetGroup, BuildTarget buildTarget) - { - return ModuleManager.GetDeploymentTargetsExtension(targetGroup, buildTarget) != null; - } - - public static IDeploymentTargetInfo GetTargetInfo(BuildTargetGroup targetGroup, BuildTarget buildTarget, DeploymentTargetId targetId) - { - IDeploymentTargetsExtension extension = GetExtension(targetGroup, buildTarget); - return extension.GetTargetInfo(targetId); - } - - public static bool SupportsLaunchBuild(IDeploymentTargetInfo info, BuildProperties buildProperties) - { - return info.GetSupportFlags().HasFlags(DeploymentTargetSupportFlags.Launch) && - info.CheckTarget(buildProperties.GetTargetRequirements()).Passed(); - } - - public static bool SupportsLaunchBuild(IDeploymentTargetInfo info, BuildReport buildReport) - { - return SupportsLaunchBuild(info, BuildProperties.GetFromBuildReport(buildReport)); - } - - public static void LaunchBuildOnTarget(BuildTargetGroup targetGroup, BuildTarget buildTarget, BuildProperties buildProperties, DeploymentTargetId targetId, ProgressHandler progressHandler = null) - { - IDeploymentTargetsExtension extension = GetExtension(targetGroup, buildTarget); - extension.LaunchBuildOnTarget(buildProperties, targetId, progressHandler); - } - - public static void LaunchBuildOnTarget(BuildTargetGroup targetGroup, BuildReport buildReport, DeploymentTargetId targetId, ProgressHandler progressHandler = null) - { - LaunchBuildOnTarget(targetGroup, buildReport.summary.platform, BuildProperties.GetFromBuildReport(buildReport), targetId, progressHandler); - } - - public static List GetKnownTargets(BuildTargetGroup targetGroup, BuildTarget buildTarget) - { - IDeploymentTargetsExtension extension = GetExtension(targetGroup, buildTarget); - return extension.GetKnownTargets(); - } - - // Launch a build on any target on a platform - public static List FindValidTargetsForLaunchBuild(BuildTargetGroup targetGroup, BuildTarget buildTarget, BuildProperties buildProperties) - { - IDeploymentTargetsExtension extension = GetExtension(targetGroup, buildTarget); - List validTargetIds = new List(); - List knownTargets = extension.GetKnownTargets(); - foreach (var target in knownTargets) - { - if (target.status == DeploymentTargetStatus.Ready) - { - if (SupportsLaunchBuild(extension.GetTargetInfo(target.id), buildProperties)) - validTargetIds.Add(target.id); - } - } - return validTargetIds; - } - - public static List FindValidTargetsForLaunchBuild(BuildTargetGroup targetGroup, BuildReport buildReport) - { - return FindValidTargetsForLaunchBuild(targetGroup, buildReport.summary.platform, BuildProperties.GetFromBuildReport(buildReport)); - } - } -} diff --git a/Editor/Mono/DeploymentTargets/IDeploymentTargetsExtension.cs b/Editor/Mono/DeploymentTargets/IDeploymentTargetsExtension.cs deleted file mode 100644 index ecdff9937a..0000000000 --- a/Editor/Mono/DeploymentTargets/IDeploymentTargetsExtension.cs +++ /dev/null @@ -1,141 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Modules; -using UnityEngine; - -namespace UnityEditor.DeploymentTargets -{ - internal struct DeploymentTargetId - { - // Meta-targets, to be able to select targets that does not depend on the current connection state. - // For example: selecting "all" should launch on all connected targets, even if the number of connected targets - // changes between launches. - internal static readonly DeploymentTargetId kDefault = new DeploymentTargetId("__builtin__target_default"); - internal static readonly DeploymentTargetId kAll = new DeploymentTargetId("__builtin__target_all"); - - public string id; - - public DeploymentTargetId(string id) - { - if (string.IsNullOrEmpty(id)) - id = kDefault.id; - this.id = id; - } - - public static implicit operator DeploymentTargetId(string id) - { - return new DeploymentTargetId(id); - } - - public static implicit operator string(DeploymentTargetId id) - { - return id.id; - } - - // Weather this is a meta target (kDefault, kAll) or a specific one. - public bool IsSpecificTarget() - { - return id != kDefault.id && id != kAll.id; - } - } - - internal enum DeploymentTargetStatus - { - // Target is ready - Ready, - // Target is available but there are issues - NotReady, - // Target exists, but we cannot connect to it - Unavailable, - // Target does not exist or it has existed but no longer responds - Unknown, - } - - internal struct DeploymentTargetIdAndStatus - { - public DeploymentTargetId id; - public DeploymentTargetStatus status; - } - - [Flags] - internal enum DeploymentTargetSupportFlags - { - None = 0, - Launch = 0x01 << 0 - } - - internal enum CheckStatus - { - Ok = 0, - Failed - } - - internal struct CategoryCheckResult - { - public CheckStatus status; - public string failureMessage; - } - - internal struct TargetCheckResult - { - public CategoryCheckResult hardware; - public CategoryCheckResult sdk; - - public bool Passed() - { - return hardware.status == CheckStatus.Ok && - sdk.status == CheckStatus.Ok; - } - } - - internal interface IDeploymentTargetInfo - { - FlagSet GetSupportFlags(); - - // Checks a target requirements against target information - // Check passes if the target is compatible - TargetCheckResult CheckTarget(DeploymentTargetRequirements targetRequirements); - - string GetDisplayName(); - } - - internal class DeploymentOperationAbortedException : Exception {} - - internal class DeploymentOperationFailedException : Exception - { - public readonly string title; - public DeploymentOperationFailedException(string title, string message, Exception inner = null) : base(message, inner) - { - this.title = title; - } - } - - internal class CorruptBuildException : DeploymentOperationFailedException - { - public CorruptBuildException(string message = "Corrupt build.", Exception inner = null) : base("Corrupt build", message, inner) {} - } - - internal interface IDeploymentTargetsExtension - { - // Returns a list of all known targets and their status - // Can be called from a background thread - List GetKnownTargets(ProgressHandler progressHandler = null); - - // Returns info for a target - // Throws DeploymentOperationFailedException (or one of its subclasses) is something goes wrong. - // Throws DeploymentOperationAbortedException if process is cancelled by the user. - // Can be called from a background thread - IDeploymentTargetInfo GetTargetInfo(DeploymentTargetId targetId, ProgressHandler progressHandler = null); - - // Launches a build on a target - // Throws DeploymentOperationFailedException (or one of its subclasses) is something goes wrong. - // Throws DeploymentOperationAbortedException if process is cancelled by the user. - // Can be called from a background thread - void LaunchBuildOnTarget(BuildProperties buildProperties, DeploymentTargetId targetId, ProgressHandler progressHandler = null); - } -} diff --git a/Editor/Mono/DisplayUtility.cs b/Editor/Mono/DisplayUtility.cs deleted file mode 100644 index 66a71687f4..0000000000 --- a/Editor/Mono/DisplayUtility.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace UnityEditor -{ - internal class DisplayUtility - { - static string s_DisplayStr = "Display {0}"; - private static GUIContent[] s_GenericDisplayNames = - { - EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 1)), EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 2)), - EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 3)), EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 4)), - EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 5)), EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 6)), - EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 7)), EditorGUIUtility.TextContent(string.Format(s_DisplayStr, 8)) - }; - - private static readonly int[] s_DisplayIndices = { 0, 1, 2, 3, 4, 5, 6, 7 }; - - public static GUIContent[] GetGenericDisplayNames() - { - return s_GenericDisplayNames; - } - - public static int[] GetDisplayIndices() - { - return s_DisplayIndices; - } - - public static GUIContent[] GetDisplayNames() - { - GUIContent[] platformDisplayNames = Modules.ModuleManager.GetDisplayNames(EditorUserBuildSettings.activeBuildTarget.ToString()); - return platformDisplayNames != null ? platformDisplayNames : s_GenericDisplayNames; - } - } -} diff --git a/Editor/Mono/DrivenPropertyManagerInternal.bindings.cs b/Editor/Mono/DrivenPropertyManagerInternal.bindings.cs deleted file mode 100644 index 19059a6ed5..0000000000 --- a/Editor/Mono/DrivenPropertyManagerInternal.bindings.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; -using UnityEngine; -using UnityEngine.Bindings; - -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/DrivenPropertyManagerInternal.bindings.h")] - [StaticAccessor("DrivenPropertyManagerInternal", StaticAccessorType.DoubleColon)] - internal class DrivenPropertyManagerInternal - { - extern public static bool IsDriven(Object target, string propertyPath); - extern public static bool IsDriving(Object driver, Object target, string propertyPath); - } -} diff --git a/Editor/Mono/DrivenRectTransformUndo.cs b/Editor/Mono/DrivenRectTransformUndo.cs deleted file mode 100644 index 816771f88a..0000000000 --- a/Editor/Mono/DrivenRectTransformUndo.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [InitializeOnLoad] - internal class DrivenRectTransformUndo - { - // Static constructor - static DrivenRectTransformUndo() - { - Undo.willFlushUndoRecord += ForceUpdateCanvases; - // After undo or redo performed, the 'driven values' & 'driven properties mask' need to be updated. - Undo.undoRedoPerformed += ForceUpdateCanvases; - } - - static void ForceUpdateCanvases() - { - Canvas.ForceUpdateCanvases(); - } - } -} diff --git a/Editor/Mono/DropInfo.cs b/Editor/Mono/DropInfo.cs deleted file mode 100644 index 71d061b94f..0000000000 --- a/Editor/Mono/DropInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - internal class DropInfo - { - internal enum Type - { - // The window will be inserted as a tab into dropArea - Tab = 0, - // The window will be a new pane (inside a scrollView) - Pane = 1, - // A new window should be created. - Window - } - - public DropInfo(IDropArea source) - { - dropArea = source; - } - - // Who claimed the drop? - public IDropArea dropArea; - - // Extra data for the recipient to communicate between DragOVer and PerformDrop - public object userData = null; - - // Which type of dropzone are we looking for? - public Type type = Type.Window; - // Where should the preview end up on screen. - public Rect rect; - } -} diff --git a/Editor/Mono/EditorApplication.cs b/Editor/Mono/EditorApplication.cs deleted file mode 100644 index d790b48aa0..0000000000 --- a/Editor/Mono/EditorApplication.cs +++ /dev/null @@ -1,316 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using UnityEngine.SceneManagement; -using UnityEditor.SceneManagement; -using UnityEngine; -using UnityEngine.Events; -using UnityEngine.Scripting; -using UnityEditorInternal; - -namespace UnityEditor -{ - public enum PlayModeStateChange - { - EnteredEditMode, - ExitingEditMode, - EnteredPlayMode, - ExitingPlayMode, - } - - public enum PauseState - { - Paused, - Unpaused, - } - - public sealed partial class EditorApplication - { - internal static UnityAction projectWasLoaded; - internal static UnityAction editorApplicationQuit; - - static void Internal_ProjectWasLoaded() - { - if (projectWasLoaded != null) - projectWasLoaded(); - } - - [RequiredByNativeCode] - static bool Internal_EditorApplicationWantsToQuit() - { - if (wantsToQuit == null) - return true; - - foreach (Func continueQuit in wantsToQuit.GetInvocationList()) - { - try - { - if (!continueQuit()) - return false; - } - catch (Exception exception) - { - Debug.LogWarningFormat("EditorApplication.wantsToQuit: Exception raised during quit event." - + Environment.NewLine + - "Check the exception error's callstack to find out which event handler threw the exception."); - Debug.LogException(exception); - - if (InternalEditorUtility.isHumanControllingUs) - { - string st = exception.StackTrace; - StringBuilder dialogText = new StringBuilder("An exception was thrown here:"); - dialogText.AppendLine(Environment.NewLine); - dialogText.AppendLine(st.Substring(0, st.IndexOf(Environment.NewLine))); - - bool abortQuit = !EditorUtility.DisplayDialog("Error while quitting", - dialogText.ToString(), - "Ignore", "Cancel Quit"); - - if (abortQuit) - return false; - } - } - } - - return true; - } - - static void Internal_EditorApplicationQuit() - { - if (quitting != null) - quitting(); - - if (editorApplicationQuit != null) - editorApplicationQuit(); - } - - internal static bool supportsHiDPI { get { return Application.platform == RuntimePlatform.OSXEditor; } } - - // Delegate to be called for every visible list item in the ProjectWindow on every OnGUI event. - public delegate void ProjectWindowItemCallback(string guid, Rect selectionRect); - - // Delegate for OnGUI events for every visible list item in the ProjectWindow. - public static ProjectWindowItemCallback projectWindowItemOnGUI; - - // Can be used to ensure repaint of the ProjectWindow. - public static void RepaintProjectWindow() - { - foreach (ProjectBrowser pb in ProjectBrowser.GetAllProjectBrowsers()) - pb.Repaint(); - } - - // Can be used to ensure repaint of AnimationWindow - public static void RepaintAnimationWindow() - { - foreach (AnimEditor animEditor in AnimEditor.GetAllAnimationWindows()) - animEditor.Repaint(); - } - - // Delegate to be called for every visible list item in the HierarchyWindow on every OnGUI event. - public delegate void HierarchyWindowItemCallback(int instanceID, Rect selectionRect); - - // Delegate for OnGUI events for every visible list item in the HierarchyWindow. - public static HierarchyWindowItemCallback hierarchyWindowItemOnGUI; - - // Can be used to ensure repaint of the HierarchyWindow. - public static void RepaintHierarchyWindow() - { - foreach (SceneHierarchyWindow pw in Resources.FindObjectsOfTypeAll(typeof(SceneHierarchyWindow))) - pw.Repaint(); - } - - public static void DirtyHierarchyWindowSorting() - { - foreach (SceneHierarchyWindow pw in Resources.FindObjectsOfTypeAll(typeof(SceneHierarchyWindow))) - pw.DirtySortingMethods(); - } - - // Delegate to be called from [[EditorApplication]] callbacks. - public delegate void CallbackFunction(); - - // Delegate to be called from [[EditorApplication]] contextual inspector callbacks. - public delegate void SerializedPropertyCallbackFunction(GenericMenu menu, SerializedProperty property); - - // Delegate for generic updates. - public static CallbackFunction update; - - public static event Func wantsToQuit; - - public static event Action quitting; - - public static CallbackFunction delayCall; - - // Each time an object is (or a group of objects are) created, renamed, parented, unparented or destroyed this callback is raised. - public static event Action hierarchyChanged; - - [Obsolete("Use EditorApplication.hierarchyChanged")] - public static CallbackFunction hierarchyWindowChanged; - - public static event Action projectChanged; - - [Obsolete("Use EditorApplication.projectChanged")] - public static CallbackFunction projectWindowChanged; - - public static CallbackFunction searchChanged; - - internal static CallbackFunction assetLabelsChanged; - - internal static CallbackFunction assetBundleNameChanged; - - // Delegate for changed keyboard modifier keys. - public static CallbackFunction modifierKeysChanged; - - public static event Action pauseStateChanged; - - public static event Action playModeStateChanged; - - [Obsolete("Use EditorApplication.playModeStateChanged and/or EditorApplication.pauseStateChanged")] - public static CallbackFunction playmodeStateChanged; - - // Global key up/down event that was not handled by anyone - internal static CallbackFunction globalEventHandler; - - // Windows were reordered - internal static CallbackFunction windowsReordered; - - // Global contextual menus for inspector values - public static SerializedPropertyCallbackFunction contextualPropertyMenu; - - static void Internal_CallUpdateFunctions() - { - if (update != null) - update(); - } - - static void Internal_CallDelayFunctions() - { - CallbackFunction delay = delayCall; - delayCall = null; - - if (delay != null) - delay(); - } - - static void Internal_SwitchSkin() - { - EditorGUIUtility.Internal_SwitchSkin(); - } - - internal static void RequestRepaintAllViews() - { - foreach (GUIView view in Resources.FindObjectsOfTypeAll(typeof(GUIView))) - view.Repaint(); - } - - static void Internal_CallHierarchyHasChanged() - { - #pragma warning disable 618 - if (hierarchyWindowChanged != null) - hierarchyWindowChanged(); - #pragma warning restore 618 - - if (hierarchyChanged != null) - hierarchyChanged(); - } - - static void Internal_CallProjectHasChanged() - { - #pragma warning disable 618 - if (projectWindowChanged != null) - projectWindowChanged(); - #pragma warning restore 618 - - if (projectChanged != null) - projectChanged(); - } - - internal static void Internal_CallSearchHasChanged() - { - if (searchChanged != null) - searchChanged(); - } - - internal static void Internal_CallAssetLabelsHaveChanged() - { - if (assetLabelsChanged != null) - assetLabelsChanged(); - } - - internal static void Internal_CallAssetBundleNameChanged() - { - if (assetBundleNameChanged != null) - assetBundleNameChanged(); - } - - // Single use case for now ONLY! - internal static void CallDelayed(CallbackFunction function, float timeFromNow) - { - delayedCallback = function; - s_DelayedCallbackTime = Time.realtimeSinceStartup + timeFromNow; - update += CheckCallDelayed; - } - - static CallbackFunction delayedCallback; - static float s_DelayedCallbackTime = 0.0f; - - static void CheckCallDelayed() - { - if (Time.realtimeSinceStartup > s_DelayedCallbackTime) - { - update -= CheckCallDelayed; - delayedCallback(); - } - } - - static void Internal_PauseStateChanged(PauseState state) - { - #pragma warning disable 618 - if (playmodeStateChanged != null) - playmodeStateChanged(); - #pragma warning restore 618 - - if (pauseStateChanged != null) - pauseStateChanged(state); - } - - static void Internal_PlayModeStateChanged(PlayModeStateChange state) - { - #pragma warning disable 618 - if (playmodeStateChanged != null) - playmodeStateChanged(); - #pragma warning restore 618 - - if (playModeStateChanged != null) - playModeStateChanged(state); - } - - static void Internal_CallKeyboardModifiersChanged() - { - if (modifierKeysChanged != null) - modifierKeysChanged(); - } - - static void Internal_CallWindowsReordered() - { - if (windowsReordered != null) - windowsReordered(); - } - - [RequiredByNativeCode] - static void Internal_CallGlobalEventHandler() - { - if (globalEventHandler != null) - globalEventHandler(); - - // Ensure this is called last in order to make sure no null current events are passed to other handlers - WindowLayout.MaximizeKeyHandler(); - - Event.current = null; - } - } -} diff --git a/Editor/Mono/EditorApplication.deprecated.cs b/Editor/Mono/EditorApplication.deprecated.cs deleted file mode 100644 index d9b2c2184a..0000000000 --- a/Editor/Mono/EditorApplication.deprecated.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine.SceneManagement; -using UnityEditor.SceneManagement; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class EditorApplication - { - [Obsolete("Use EditorSceneManager.NewScene (NewSceneSetup.DefaultGameObjects)")] - public static void NewScene() - { - EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); - } - - [Obsolete("Use EditorSceneManager.NewScene (NewSceneSetup.EmptyScene)")] - public static void NewEmptyScene() - { - EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); - } - - // Opens the scene at /path/. - [Obsolete("Use EditorSceneManager.OpenScene")] - public static bool OpenScene(string path) - { - // Check that we're not in play mode first before opening the scene. - if (!isPlaying) - { - Scene scene = EditorSceneManager.OpenScene(path); - return scene.IsValid(); - } - else - { - throw new InvalidOperationException( - "EditorApplication.OpenScene() cannot be called when in the Unity Editor is in play mode."); - } - } - - [Obsolete("Use EditorSceneManager.OpenScene")] - public static void OpenSceneAdditive(string path) - { - // Case 712517: - // Behaviour change introduced in 5.3 - // Previously we allowed OpenSceneAdditive to be called during playmode. - // This is no longer allowed, if it happens we exit playmode which is - // consistent with EditorSceneManager.OpenScene(path, OpenSceneMode.Additive) - - if (Application.isPlaying) - { - Debug.LogWarning("Exiting playmode.\n" + - "OpenSceneAdditive was called at a point where there was no active scene.\n" + - "This usually means it was called in a PostprocessScene function during scene loading or it was called during playmode.\n" + - "This is no longer allowed. Use SceneManager.LoadScene to load scenes at runtime or in playmode."); - } - - Scene srcScene = EditorSceneManager.OpenScene(path, OpenSceneMode.Additive); - Scene dstScene = EditorSceneManager.GetActiveScene(); - SceneManager.MergeScenes(srcScene, dstScene); - } - - [Obsolete("Use EditorSceneManager.SaveScene")] - public static bool SaveScene() - { - return EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene(), "", false); - } - - [Obsolete("Use EditorSceneManager.SaveScene")] - public static bool SaveScene(string path) - { - return EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene(), path, false); - } - - [Obsolete("Use EditorSceneManager.SaveScene")] - public static bool SaveScene(string path, bool saveAsCopy) - { - return EditorSceneManager.SaveScene(EditorSceneManager.GetActiveScene(), path, saveAsCopy); - } - - [Obsolete("Use EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo")] - public static bool SaveCurrentSceneIfUserWantsTo() - { - return EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo(); - } - - [Obsolete("This function is internal and no longer supported")] - static internal bool SaveCurrentSceneIfUserWantsToForce() - { - return false; - } - - [Obsolete("Use EditorSceneManager.MarkSceneDirty or EditorSceneManager.MarkAllScenesDirty")] - public static void MarkSceneDirty() - { - EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); - } - - [Obsolete("Use Scene.isDirty instead. Use EditorSceneManager.GetScene API to get each open scene")] - public static bool isSceneDirty - { - get { return EditorSceneManager.GetActiveScene().isDirty; } - } - - [Obsolete("Use EditorSceneManager to see which scenes are currently loaded")] - public static string currentScene - { - get - { - Scene scene = EditorSceneManager.GetActiveScene(); - if (scene.IsValid()) - return scene.path; - - return ""; - } - set - { - } - } - } -} diff --git a/Editor/Mono/EditorAssemblies.bindings.cs b/Editor/Mono/EditorAssemblies.bindings.cs deleted file mode 100644 index 36f6892b94..0000000000 --- a/Editor/Mono/EditorAssemblies.bindings.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeHeader("Runtime/Mono/MonoAttributeHelpers.h")] - static partial class EditorAssemblies - { - const BindingFlags k_DefaultMethodBindingFlags = - BindingFlags.Public - | BindingFlags.NonPublic - | BindingFlags.Instance - | BindingFlags.Static; - - internal static IEnumerable GetAllMethodsWithAttribute(BindingFlags bindingFlags = k_DefaultMethodBindingFlags) - where T : Attribute - { - return Internal_GetAllMethodsWithAttribute(typeof(T), bindingFlags).Cast(); - } - - [FreeFunction(Name = "GetAllMethodsWithAttribute")] - extern static object[] Internal_GetAllMethodsWithAttribute(Type attrType, BindingFlags staticness); - - internal static IEnumerable GetAllTypesWithAttribute() where T : Attribute - { - return Internal_GetAllTypesWithAttribute(typeof(T)); - } - - [FreeFunction(Name = "GetAllTypesWithAttribute")] - extern static Type[] Internal_GetAllTypesWithAttribute(Type attrType); - - internal static IEnumerable GetAllTypesWithInterface() where T : class - { - return GetAllTypesWithInterface(typeof(T)); - } - - private static IEnumerable GetAllTypesWithInterface(Type interfaceType) - { - if (!interfaceType.IsInterface) - throw new ArgumentException(string.Format("Specified type {0} is not an interface.", interfaceType), nameof(interfaceType)); - return Internal_GetAllTypesWithInterface(interfaceType); - } - - [FreeFunction(Name = "GetAllTypesWithInterface")] - extern static Type[] Internal_GetAllTypesWithInterface(Type interfaceType); - } -} diff --git a/Editor/Mono/EditorAssemblies.cs b/Editor/Mono/EditorAssemblies.cs deleted file mode 100644 index 7434cf073e..0000000000 --- a/Editor/Mono/EditorAssemblies.cs +++ /dev/null @@ -1,144 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Runtime.CompilerServices; -using UnityEngine; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - /// - /// Marks a class as requiring eager initialization. - /// - /// Classes marked with this attribute will have their static constructors - /// executed whenever assemblies are loaded or reloaded. - /// - /// Very useful for event (re)wiring. - /// - [AttributeUsage(AttributeTargets.Class)] - public class InitializeOnLoadAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Method)] - public class InitializeOnLoadMethodAttribute : Attribute - { - } - - /// - /// Holds information about the current set of editor assemblies. - /// - static partial class EditorAssemblies - { - /// - /// The currently loaded editor assemblies - /// (This is kept up to date from ) - /// - static internal Assembly[] loadedAssemblies - { - get; private set; - } - - static internal IEnumerable loadedTypes - { - get { return loadedAssemblies.SelectMany(assembly => AssemblyHelper.GetTypesFromAssembly(assembly)); } - } - - static internal IEnumerable SubclassesOf(Type parent) - { - return parent.IsInterface ? - GetAllTypesWithInterface(parent) : - loadedTypes.Where(klass => klass.IsSubclassOf(parent)); - } - - static internal List m_RuntimeInitializeClassInfoList; - static internal int m_TotalNumRuntimeInitializeMethods; - - [RequiredByNativeCode] - private static void SetLoadedEditorAssemblies(Assembly[] assemblies) - { - loadedAssemblies = assemblies; - } - - [RequiredByNativeCode] - private static RuntimeInitializeClassInfo[] GetRuntimeInitializeClassInfos() - { - if (m_RuntimeInitializeClassInfoList == null) - return null; - return m_RuntimeInitializeClassInfoList.ToArray(); - } - - [RequiredByNativeCode] - private static int GetTotalNumRuntimeInitializeMethods() - { - return m_TotalNumRuntimeInitializeMethods; - } - - private static void StoreRuntimeInitializeClassInfo(Type type, List methodNames, List loadTypes) - { - RuntimeInitializeClassInfo classInfo = new RuntimeInitializeClassInfo(); - classInfo.assemblyName = type.Assembly.GetName().Name.ToString(); - classInfo.className = (string)type.ToString(); - classInfo.methodNames = methodNames.ToArray(); - classInfo.loadTypes = loadTypes.ToArray(); - m_RuntimeInitializeClassInfoList.Add(classInfo); - m_TotalNumRuntimeInitializeMethods += methodNames.Count; - } - - private static void ProcessEditorInitializeOnLoad(Type type) - { - try - { - RuntimeHelpers.RunClassConstructor(type.TypeHandle); - } - catch (TypeInitializationException x) - { - Debug.LogError(x.InnerException); - } - } - - private static void ProcessRuntimeInitializeOnLoad(MethodInfo method) - { - RuntimeInitializeLoadType loadType = RuntimeInitializeLoadType.AfterSceneLoad; - - object[] attrs = method.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), false); - if (attrs != null && attrs.Length > 0) - loadType = ((RuntimeInitializeOnLoadMethodAttribute)attrs[0]).loadType; - - StoreRuntimeInitializeClassInfo(method.DeclaringType, new List() { method.Name }, new List() { loadType }); - } - - private static void ProcessInitializeOnLoadMethod(MethodInfo method) - { - try - { - method.Invoke(null, null); - } - catch (TargetInvocationException x) - { - Debug.LogError(x.InnerException); - } - } - - [RequiredByNativeCode] - private static int[] ProcessInitializeOnLoadAttributes() - { - m_TotalNumRuntimeInitializeMethods = 0; - m_RuntimeInitializeClassInfoList = new List(); - - foreach (Type type in GetAllTypesWithAttribute()) - ProcessEditorInitializeOnLoad(type); - foreach (MethodInfo method in GetAllMethodsWithAttribute()) - ProcessRuntimeInitializeOnLoad(method); - foreach (MethodInfo method in GetAllMethodsWithAttribute()) - ProcessInitializeOnLoadMethod(method); - - return null; - } - } -} diff --git a/Editor/Mono/EditorBuildSettings.bindings.cs b/Editor/Mono/EditorBuildSettings.bindings.cs deleted file mode 100644 index b0b580cfde..0000000000 --- a/Editor/Mono/EditorBuildSettings.bindings.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine.Scripting; -using System.Runtime.CompilerServices; -using UnityEngine.Bindings; -using System.Runtime.InteropServices; -using Object = UnityEngine.Object; -using UnityEngine; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/EditorBuildSettings.h")] - [NativeAsStruct] - [StructLayout(LayoutKind.Sequential)] - [UsedByNativeCode] - public class EditorBuildSettingsScene : IComparable - { - [NativeName("enabled")] - bool m_enabled; - [NativeName("path")] - string m_path; - [NativeName("guid")] - GUID m_guid; - public EditorBuildSettingsScene() {} - public EditorBuildSettingsScene(string path, bool enabled) - { - m_path = path.Replace("\\", "/"); - m_enabled = enabled; - GUID.TryParse(AssetDatabase.AssetPathToGUID(path), out m_guid); - } - - public EditorBuildSettingsScene(GUID guid, bool enabled) - { - m_guid = guid; - m_enabled = enabled; - m_path = AssetDatabase.GUIDToAssetPath(guid.ToString()); - } - - public bool enabled { get { return m_enabled; } set { m_enabled = value; } } - public string path { get { return m_path; } set { m_path = value.Replace("\\", "/"); } } - public GUID guid { get { return m_guid; } set { m_guid = value; } } - public static string[] GetActiveSceneList(EditorBuildSettingsScene[] scenes) - { - return scenes.Where(scene => scene.enabled).Select(scene => scene.path).ToArray(); - } - - public int CompareTo(object obj) - { - if (obj is EditorBuildSettingsScene) - { - EditorBuildSettingsScene temp = (EditorBuildSettingsScene)obj; - return temp.path.CompareTo(path); - } - throw new ArgumentException("object is not a EditorBuildSettingsScene"); - } - } - - - [NativeHeader("Editor/Src/EditorBuildSettings.h")] - public partial class EditorBuildSettings : UnityEngine.Object - { - private EditorBuildSettings() {} - public static event Action sceneListChanged; - [RequiredByNativeCode] - private static void SceneListChanged() - { - if (sceneListChanged != null) - sceneListChanged(); - } - - public static EditorBuildSettingsScene[] scenes - { - get - { - return GetEditorBuildSettingsScenes(); - } - set - { - SetEditorBuildSettingsScenes(value); - } - } - static extern EditorBuildSettingsScene[] GetEditorBuildSettingsScenes(); - static extern void SetEditorBuildSettingsScenes(EditorBuildSettingsScene[] scenes); - - enum ConfigObjectResult - { - Succeeded, - FailedEntryNotFound, - FailedNullObj, - FailedNonPersistedObj, - FailedEntryExists, - FailedTypeMismatch - }; - - [NativeMethod("AddConfigObject")] - static extern ConfigObjectResult AddConfigObjectInternal(string name, Object obj, bool overwrite); - public static extern bool RemoveConfigObject(string name); - public static extern string[] GetConfigObjectNames(); - static extern Object GetConfigObject(string name); - public static void AddConfigObject(string name, Object obj, bool overwrite) - { - var result = AddConfigObjectInternal(name, obj, overwrite); - if (result == ConfigObjectResult.Succeeded) - return; - switch (result) - { - case ConfigObjectResult.FailedEntryExists: throw new Exception("Config object with name '" + name + "' already exists."); - case ConfigObjectResult.FailedNonPersistedObj: throw new Exception("Cannot add non-persisted config object with name '" + name + "'."); - case ConfigObjectResult.FailedNullObj: throw new Exception("Cannot add null config object with name '" + name + "'."); - } - } - - public static bool TryGetConfigObject(string name, out T result) where T : Object - { - result = GetConfigObject(name) as T; - return result != null; - } - } -} diff --git a/Editor/Mono/EditorGUI.EnumMaskField.deprecated.cs b/Editor/Mono/EditorGUI.EnumMaskField.deprecated.cs deleted file mode 100644 index f1d3594eb2..0000000000 --- a/Editor/Mono/EditorGUI.EnumMaskField.deprecated.cs +++ /dev/null @@ -1,424 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -#pragma warning disable 618 // disable obsolete warning - -namespace UnityEditor -{ - public partial class EditorGUI - { - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(Rect position, Enum enumValue) - { - return EnumMaskField(position, enumValue, EditorStyles.popup); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(Rect position, Enum enumValue, GUIStyle style) - { - return EnumMaskFieldInternal(position, enumValue, style); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(Rect position, string label, Enum enumValue) - { - return EnumMaskField(position, label, enumValue, EditorStyles.popup); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(Rect position, string label, Enum enumValue, GUIStyle style) - { - return EnumMaskFieldInternal(position, EditorGUIUtility.TempContent(label), enumValue, style); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(Rect position, GUIContent label, Enum enumValue) - { - return EnumMaskField(position, label, enumValue, EditorStyles.popup); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(Rect position, GUIContent label, Enum enumValue, GUIStyle style) - { - return EnumMaskFieldInternal(position, label, enumValue, style); - } - - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskPopup(Rect position, string label, Enum selected) - { - return EnumMaskPopup(position, label, selected, EditorStyles.popup); - } - - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskPopup(Rect position, string label, Enum selected, GUIStyle style) - { - int changedFlags; - bool changedToValue; - return EnumMaskPopup(position, label, selected, out changedFlags, out changedToValue, style); - } - - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskPopup(Rect position, GUIContent label, Enum selected) - { - return EnumMaskPopup(position, label, selected, EditorStyles.popup); - } - - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskPopup(Rect position, GUIContent label, Enum selected, GUIStyle style) - { - int changedFlags; - bool changedToValue; - return EnumMaskPopup(position, label, selected, out changedFlags, out changedToValue, style); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - static Enum EnumMaskField(Rect position, GUIContent label, Enum enumValue, GUIStyle style, out int changedFlags, out bool changedToValue) - { - return DoEnumMaskField(position, label, enumValue, style, out changedFlags, out changedToValue); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - static Enum EnumMaskFieldInternal(Rect position, Enum enumValue, GUIStyle style) - { - Type enumType = enumValue.GetType(); - if (!enumType.IsEnum) - throw new ArgumentException("Parameter enumValue must be of type System.Enum", "enumValue"); - - var names = Enum.GetNames(enumType).Select(ObjectNames.NicifyVariableName).ToArray(); - int flags = MaskFieldGUIDeprecated.DoMaskField( - IndentedRect(position), - GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position), - Convert.ToInt32(enumValue), - names, style); - return IntToEnumFlags(enumType, flags); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - static Enum EnumMaskFieldInternal(Rect position, GUIContent label, Enum enumValue, GUIStyle style) - { - Type enumType = enumValue.GetType(); - if (!enumType.IsEnum) - throw new ArgumentException("Parameter enumValue must be of type System.Enum", "enumValue"); - - var id = GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position); - var position2 = EditorGUI.PrefixLabel(position, id, label); - position.xMax = position2.x; - - var names = Enum.GetNames(enumType).Select(ObjectNames.NicifyVariableName).ToArray(); - int flags = MaskFieldGUIDeprecated.DoMaskField(position2, id, Convert.ToInt32(enumValue), names, style); - return IntToEnumFlags(enumType, flags); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - static Enum DoEnumMaskField(Rect position, GUIContent label, Enum enumValue, GUIStyle style, out int changedFlags, out bool changedToValue) - { - var enumType = enumValue.GetType(); - if (!enumType.IsEnum) - throw new ArgumentException("Parameter enumValue must be of type System.Enum", "enumValue"); - - var id = GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position); - var names = Enum.GetNames(enumType).Select(ObjectNames.NicifyVariableName).ToArray(); - int flags = MaskFieldGUIDeprecated.DoMaskField( - PrefixLabel(position, id, label), - id, - Convert.ToInt32(enumValue), - names, style, out changedFlags, out changedToValue); - return IntToEnumFlags(enumType, flags); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - static Enum EnumMaskPopup(Rect position, string label, Enum selected, out int changedFlags, out bool changedToValue, GUIStyle style) - { - return EnumMaskPopup(position, EditorGUIUtility.TempContent(label), selected, out changedFlags, out changedToValue, style); - } - - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - internal static Enum EnumMaskPopup(Rect position, GUIContent label, Enum selected, out int changedFlags, out bool changedToValue, GUIStyle style) - { - return EnumMaskPopupInternal(position, label, selected, out changedFlags, out changedToValue, style); - } - - // Make an enum mask popup selection field. - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - static Enum EnumMaskPopupInternal(Rect position, GUIContent label, Enum selected, out int changedFlags, out bool changedToValue, GUIStyle style) - { - return EnumMaskField(position, label, selected, style, out changedFlags, out changedToValue); - } - } - - public partial class EditorGUILayout - { - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(Enum enumValue, params GUILayoutOption[] options) - { - return EnumMaskField(enumValue, EditorStyles.popup, options); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(Enum enumValue, GUIStyle style, params GUILayoutOption[] options) - { - var r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.EnumMaskField(r, enumValue, style); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(string label, Enum enumValue, params GUILayoutOption[] options) - { - return EnumMaskField(label, enumValue, EditorStyles.popup, options); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(string label, Enum enumValue, GUIStyle style, params GUILayoutOption[] options) - { - var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.EnumMaskField(r, label, enumValue, style); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(GUIContent label, Enum enumValue, params GUILayoutOption[] options) - { - return EnumMaskField(label, enumValue, EditorStyles.popup, options); - } - - [Obsolete("EnumMaskField has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskField(GUIContent label, Enum enumValue, GUIStyle style, params GUILayoutOption[] options) - { - var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.EnumMaskField(r, label, enumValue, style); - } - - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskPopup(string label, Enum selected, params GUILayoutOption[] options) - { - return EnumMaskPopup(label, selected, EditorStyles.popup, options); - } - - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskPopup(string label, Enum selected, GUIStyle style, params GUILayoutOption[] options) - { - int changedFlags; - bool changedToValue; - return EnumMaskPopup(EditorGUIUtility.TempContent(label), selected, out changedFlags, out changedToValue, style, options); - } - - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskPopup(GUIContent label, Enum selected, params GUILayoutOption[] options) - { - return EnumMaskPopup(label, selected, EditorStyles.popup, options); - } - - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - public static Enum EnumMaskPopup(GUIContent label, Enum selected, GUIStyle style, params GUILayoutOption[] options) - { - int changedFlags; - bool changedToValue; - return EnumMaskPopup(label, selected, out changedFlags, out changedToValue, style, options); - } - - // Make an enum popup selection field for a bitmask. - [Obsolete("EnumMaskPopup has been deprecated. Use EnumFlagsField instead.")] - static Enum EnumMaskPopup(GUIContent label, Enum selected, out int changedFlags, out bool changedToValue, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.EnumMaskPopup(r, label, selected, out changedFlags, out changedToValue, style); - } - } - - // Class for storing state for mask menus so we can get the info back to OnGUI from the user selection - [Obsolete("MaskFieldGUIDeprecated is deprecated. Use MaskFieldGUI instead.")] - static class MaskFieldGUIDeprecated - { - // Class for storing state for mask menus so we can get the info back to OnGUI from the user selection - private class MaskCallbackInfo - { - // The global shared popup state - public static MaskCallbackInfo m_Instance; - - // Name of the command event sent from the popup menu to OnGUI when user has changed selection - private const string kMaskMenuChangedMessage = "MaskMenuChanged"; - - // The control ID of the popup menu that is currently displayed. - // Used to pass selection changes back again - private readonly int m_ControlID; - - // Which item was selected - private int m_Mask; - - //Flags to control all / nothing buttons - private bool m_SetAll; - private bool m_ClearAll; - private bool m_DoNothing; - - // Which view should we send it to. - private readonly GUIView m_SourceView; - - public MaskCallbackInfo(int controlID) - { - m_ControlID = controlID; - m_SourceView = GUIView.current; - } - - public static int GetSelectedValueForControl(int controlID, int mask, out int changedFlags, out bool changedToValue) - { - var evt = Event.current; - - // No flags are changed by default - changedFlags = 0; - changedToValue = false; - - if (evt.type == EventType.ExecuteCommand && evt.commandName == kMaskMenuChangedMessage) - { - if (m_Instance == null) - { - Debug.LogError("Mask menu has no instance"); - return mask; - } - if (m_Instance.m_ControlID == controlID) - { - if (!m_Instance.m_DoNothing) - { - if (m_Instance.m_ClearAll) - { - mask = 0; - changedFlags = ~0; - changedToValue = false; - } - else if (m_Instance.m_SetAll) - { - mask = ~0; - changedFlags = ~0; - changedToValue = true; - } - else - { - mask ^= m_Instance.m_Mask; - changedFlags = m_Instance.m_Mask; - changedToValue = (mask & m_Instance.m_Mask) != 0; - } - - GUI.changed = true; - } - m_Instance.m_DoNothing = false; - m_Instance.m_ClearAll = false; - m_Instance.m_SetAll = false; - m_Instance = null; - evt.Use(); - } - } - return mask; - } - - internal void SetMaskValueDelegate(object userData, string[] options, int selected) - { - switch (selected) - { - case 0: - m_ClearAll = true; - break; - case 1: - m_SetAll = true; - break; - default: - m_Mask = ((int[])userData)[selected - 2]; - break; - } - - if (m_SourceView) - m_SourceView.SendEvent(EditorGUIUtility.CommandEvent(kMaskMenuChangedMessage)); - } - } - - /// Make a field for a generic mask. - internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, GUIStyle style) - { - int dummyInt; - bool dummyBool; - return DoMaskField(position, controlID, mask, flagNames, style, out dummyInt, out dummyBool); - } - - internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, int[] flagValues, GUIStyle style) - { - int dummyInt; - bool dummyBool; - return DoMaskField(position, controlID, mask, flagNames, flagValues, style, out dummyInt, out dummyBool); - } - - internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, GUIStyle style, out int changedFlags, out bool changedToValue) - { - var flagValues = new int[flagNames.Length]; - for (int i = 0; i < flagValues.Length; ++i) - flagValues[i] = (1 << i); - - return DoMaskField(position, controlID, mask, flagNames, flagValues, style, out changedFlags, out changedToValue); - } - - /// Make a field for a generic mask. - /// This version also gives you back which flags were changed and what they were changed to. - /// This is useful if you want to make the same change to multiple objects. - internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, int[] flagValues, GUIStyle style, out int changedFlags, out bool changedToValue) - { - mask = MaskCallbackInfo.GetSelectedValueForControl(controlID, mask, out changedFlags, out changedToValue); - var selectedFlags = new List(); - var fullFlagNames = new List {"Nothing", "Everything"}; - - for (var i = 0; i < flagNames.Length; i++) - { - if ((mask & flagValues[i]) != 0) - selectedFlags.Add(i + 2); - } - - fullFlagNames.AddRange(flagNames); - - GUIContent buttonContent = EditorGUI.mixedValueContent; - if (!EditorGUI.showMixedValue) - { - switch (selectedFlags.Count) - { - case 0: - buttonContent = EditorGUIUtility.TempContent("Nothing"); - selectedFlags.Add(0); - break; - case 1: - buttonContent = new GUIContent(fullFlagNames[selectedFlags[0]]); - break; - default: - if (selectedFlags.Count >= flagNames.Length) - { - buttonContent = EditorGUIUtility.TempContent("Everything"); - selectedFlags.Add(1); - // When every available item is selected, we force to ~0 to keep the mask int value consistent - // between the cases where all items are individually selected vs. user clicks "everything" - mask = ~0; - } - else - buttonContent = EditorGUIUtility.TempContent("Mixed ..."); - break; - } - } - Event evt = Event.current; - if (evt.type == EventType.Repaint) - { - style.Draw(position, buttonContent, controlID, false); - } - else if ((evt.type == EventType.MouseDown && position.Contains(evt.mousePosition)) || evt.MainActionKeyForControl(controlID)) - { - MaskCallbackInfo.m_Instance = new MaskCallbackInfo(controlID); - evt.Use(); - EditorUtility.DisplayCustomMenu(position, fullFlagNames.ToArray(), - // Only show selections if we are not multi-editing - EditorGUI.showMixedValue ? new int[] {} : selectedFlags.ToArray(), - MaskCallbackInfo.m_Instance.SetMaskValueDelegate, flagValues); - EditorGUIUtility.keyboardControl = controlID; - } - return mask; - } - } -} - -#pragma warning restore 618 // restore obsolete warning diff --git a/Editor/Mono/EditorGUI.bindings.cs b/Editor/Mono/EditorGUI.bindings.cs deleted file mode 100644 index b6de8846e5..0000000000 --- a/Editor/Mono/EditorGUI.bindings.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using UnityEngineInternal; - -namespace UnityEditor -{ - public partial class EditorGUI - { - internal static int Popup(Rect position, GUIContent label, int selectedIndex, string[] displayedOptions, GUIStyle style) - { return PopupInternal(position, label, selectedIndex, EditorGUIUtility.TempContent(displayedOptions), style); } - internal static int Popup(Rect position, GUIContent label, int selectedIndex, string[] displayedOptions) - { return Popup(position, label, selectedIndex, displayedOptions, EditorStyles.popup); } - } -} diff --git a/Editor/Mono/EditorGUI.cs b/Editor/Mono/EditorGUI.cs deleted file mode 100644 index dbc47ec627..0000000000 --- a/Editor/Mono/EditorGUI.cs +++ /dev/null @@ -1,8378 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using UnityEditor.SceneManagement; -using UnityEngine; -using UnityEngine.Scripting; -using UnityEditorInternal; -using UnityEditor.Scripting.ScriptCompilation; -using Object = UnityEngine.Object; -using Event = UnityEngine.Event; -using UnityEditor.Build; - -namespace UnityEditor -{ - // Class for editor-only GUI. This class contains general purpose 2D additions to UnityGUI. - // These work pretty much like the normal GUI functions - and also have matching implementations in [[EditorGUILayout]] - public sealed partial class EditorGUI - { - private static RecycledTextEditor activeEditor; - - internal static DelayedTextEditor s_DelayedTextEditor = new DelayedTextEditor(); - - internal static RecycledTextEditor s_RecycledEditor = new RecycledTextEditor(); - internal static string s_OriginalText = ""; - internal static string s_RecycledCurrentEditingString; - internal static double s_RecycledCurrentEditingFloat; - internal static long s_RecycledCurrentEditingInt; - private static bool bKeyEventActive = false; - - internal static bool s_DragToPosition = true; - internal static bool s_Dragged = false; - internal static bool s_PostPoneMove = false; - internal static bool s_SelectAllOnMouseUp = true; - - private const double kFoldoutExpandTimeout = 0.7; - private static double s_FoldoutDestTime; - private static int s_DragUpdatedOverID = 0; - - private static int s_FoldoutHash = "Foldout".GetHashCode(); - private static int s_TagFieldHash = "s_TagFieldHash".GetHashCode(); - private static int s_PPtrHash = "s_PPtrHash".GetHashCode(); - private static int s_ObjectFieldHash = "s_ObjectFieldHash".GetHashCode(); - private static int s_ToggleHash = "s_ToggleHash".GetHashCode(); - private static int s_ColorHash = "s_ColorHash".GetHashCode(); - private static int s_CurveHash = "s_CurveHash".GetHashCode(); - private static int s_LayerMaskField = "s_LayerMaskField".GetHashCode(); - private static int s_MaskField = "s_MaskField".GetHashCode(); - private static int s_EnumFlagsField = "s_EnumFlagsField".GetHashCode(); - private static int s_GenericField = "s_GenericField".GetHashCode(); - private static int s_PopupHash = "EditorPopup".GetHashCode(); - private static int s_KeyEventFieldHash = "KeyEventField".GetHashCode(); - private static int s_TextFieldHash = "EditorTextField".GetHashCode(); - private static int s_SearchFieldHash = "EditorSearchField".GetHashCode(); - private static int s_TextAreaHash = "EditorTextField".GetHashCode(); - private static int s_PasswordFieldHash = "PasswordField".GetHashCode(); - private static int s_FloatFieldHash = "EditorTextField".GetHashCode(); - private static int s_DelayedTextFieldHash = "DelayedEditorTextField".GetHashCode(); - private static int s_ArraySizeFieldHash = "ArraySizeField".GetHashCode(); - private static int s_SliderHash = "EditorSlider".GetHashCode(); - private static int s_SliderKnobHash = "EditorSliderKnob".GetHashCode(); - private static int s_MinMaxSliderHash = "EditorMinMaxSlider".GetHashCode(); - private static int s_TitlebarHash = "GenericTitlebar".GetHashCode(); - private static int s_ProgressBarHash = "s_ProgressBarHash".GetHashCode(); - private static int s_SelectableLabelHash = "s_SelectableLabel".GetHashCode(); - private static int s_SortingLayerFieldHash = "s_SortingLayerFieldHash".GetHashCode(); - private static int s_TextFieldDropDownHash = "s_TextFieldDropDown".GetHashCode(); - - private static int s_DragCandidateState = 0; - private static float kDragDeadzone = 16; - private static Vector2 s_DragStartPos; - private static double s_DragStartValue = 0; - private static long s_DragStartIntValue = 0; - private static double s_DragSensitivity = 0; - internal const float kMiniLabelW = 13; - internal const float kLabelW = 80; - internal const float kSpacing = 5; - internal const float kSpacingSubLabel = 2; - internal const float kSliderMinW = 60; - internal const float kSliderMaxW = 100; - internal const float kSingleLineHeight = 16; - internal const float kStructHeaderLineHeight = 16; - internal const float kObjectFieldThumbnailHeight = 64; - internal const float kObjectFieldMiniThumbnailHeight = 18f; - internal const float kObjectFieldMiniThumbnailWidth = 32f; - internal static string kFloatFieldFormatString = "g7"; - internal static string kDoubleFieldFormatString = "g15"; - internal static string kIntFieldFormatString = "#######0"; - internal static int ms_IndentLevel = 0; - private const float kIndentPerLevel = 15; - internal const int kControlVerticalSpacing = 2; - internal const int kVerticalSpacingMultiField = 0; - internal static string s_UnitString = ""; - internal const int kInspTitlebarIconWidth = 16; - internal const int kWindowToolbarHeight = 17; - private static string kEnabledPropertyName = "m_Enabled"; - - private static float[] s_Vector2Floats = {0, 0}; - private static int[] s_Vector2Ints = { 0, 0 }; - private static GUIContent[] s_XYLabels = {EditorGUIUtility.TextContent("X"), EditorGUIUtility.TextContent("Y")}; - - private static float[] s_Vector3Floats = {0, 0, 0}; - private static int[] s_Vector3Ints = { 0, 0, 0 }; - private static GUIContent[] s_XYZLabels = {EditorGUIUtility.TextContent("X"), EditorGUIUtility.TextContent("Y"), EditorGUIUtility.TextContent("Z")}; - - private static float[] s_Vector4Floats = {0, 0, 0, 0}; - private static GUIContent[] s_XYZWLabels = {EditorGUIUtility.TextContent("X"), EditorGUIUtility.TextContent("Y"), EditorGUIUtility.TextContent("Z"), EditorGUIUtility.TextContent("W")}; - - private static GUIContent[] s_WHLabels = {EditorGUIUtility.TextContent("W"), EditorGUIUtility.TextContent("H")}; - - private static GUIContent s_CenterLabel = EditorGUIUtility.TrTextContent("Center"); - private static GUIContent s_ExtentLabel = EditorGUIUtility.TrTextContent("Extent"); - private static GUIContent s_PositionLabel = EditorGUIUtility.TrTextContent("Position"); - private static GUIContent s_SizeLabel = EditorGUIUtility.TrTextContent("Size"); - - internal static readonly GUIContent s_ClipingPlanesLabel = EditorGUIUtility.TrTextContent("Clipping Planes", "Distances from the camera to start and stop rendering."); - internal static readonly GUIContent[] s_NearAndFarLabels = { EditorGUIUtility.TrTextContent("Near", "The closest point relative to the camera that drawing will occur."), EditorGUIUtility.TrTextContent("Far", "The furthest point relative to the camera that drawing will occur.\n") }; - internal const float kNearFarLabelsWidth = 35f; - - private static int s_ColorPickID; - - private static int s_CurveID; - internal static Color kCurveColor = Color.green; - internal static Color kCurveBGColor = new Color(0.337f, 0.337f, 0.337f, 1f); - 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)); - - private const int kInspTitlebarToggleWidth = 16; - private const int kInspTitlebarSpacing = 2; - private static GUIContent s_PropertyFieldTempContent = new GUIContent(); - private static GUIContent s_IconDropDown; - private static Material s_IconTextureInactive; - - private static bool s_HasPrefixLabel; - private static GUIContent s_PrefixLabel = new GUIContent((string)null); - private static Rect s_PrefixTotalRect; - private static Rect s_PrefixRect; - private static GUIStyle s_PrefixStyle; - private static Color s_PrefixGUIColor; - - // Makes the following controls give the appearance of editing multiple different values. - public static bool showMixedValue - { - get { return s_ShowMixedValue; } - set { s_ShowMixedValue = value; } - } - - private static bool s_ShowMixedValue; - - private static GUIContent s_MixedValueContent = EditorGUIUtility.TrTextContent("\u2014", "Mixed Values"); - - internal static GUIContent mixedValueContent - { - get { return s_MixedValueContent; } - } - - private static Color s_MixedValueContentColor = new Color(1, 1, 1, 0.5f); - private static Color s_MixedValueContentColorTemp = Color.white; - - internal static void BeginHandleMixedValueContentColor() - { - s_MixedValueContentColorTemp = GUI.contentColor; - GUI.contentColor = showMixedValue ? (GUI.contentColor * s_MixedValueContentColor) : GUI.contentColor; - } - - internal static void EndHandleMixedValueContentColor() - { - GUI.contentColor = s_MixedValueContentColorTemp; - } - - [RequiredByNativeCode] - internal static bool IsEditingTextField() - { - return RecycledTextEditor.s_ActuallyEditing && activeEditor != null; - } - - internal static void EndEditingActiveTextField() - { - if (activeEditor != null) - { - activeEditor.EndEditing(); - } - } - - public static void FocusTextInControl(string name) - { - GUI.FocusControl(name); - EditorGUIUtility.editingTextField = true; - } - - // STACKS - - internal static void ClearStacks() - { - s_EnabledStack.Clear(); - s_ChangedStack.Clear(); - s_PropertyStack.Clear(); - ScriptAttributeUtility.s_DrawerStack.Clear(); - } - - private static Stack s_PropertyStack = new Stack(); - - private static Stack s_EnabledStack = new Stack(); - - // @TODO: API soon to be deprecated but still in a grace period; documentation states that users - // are encouraged to use EditorGUI.DisabledScope instead. Uncomment next line when appropriate. - // [System.Obsolete("Use DisabledScope instead", false)] - public class DisabledGroupScope : GUI.Scope - { - public DisabledGroupScope(bool disabled) - { - BeginDisabledGroup(disabled); - } - - protected override void CloseScope() - { - EndDisabledGroup(); - } - } - - // Create a group of controls that can be disabled. - // @TODO: API soon to be deprecated but still in a grace period; documentation states that users - // are encouraged to use EditorGUI.DisabledScope instead. Uncomment next line when appropriate. - // [System.Obsolete("Use DisabledScope instead", false)] - public static void BeginDisabledGroup(bool disabled) - { - BeginDisabled(disabled); - } - - // Ends a disabled group started with BeginDisabledGroup. - // @TODO: API soon to be deprecated but still in a grace period; documentation states that users - // are encouraged to use EditorGUI.DisabledScope instead. Uncomment next line when appropriate. - // [System.Obsolete("Use DisabledScope instead", false)] - public static void EndDisabledGroup() - { - EndDisabled(); - } - - public struct DisabledScope : IDisposable - { - bool m_Disposed; - - public DisabledScope(bool disabled) - { - m_Disposed = false; - - BeginDisabled(disabled); - } - - public void Dispose() - { - if (m_Disposed) - return; - m_Disposed = true; - if (!GUIUtility.guiIsExiting) - EndDisabled(); - } - } - - // Create a group of controls that can be disabled. - internal static void BeginDisabled(bool disabled) - { - s_EnabledStack.Push(GUI.enabled); - GUI.enabled &= !disabled; - } - - // Ends a disabled group started with BeginDisabled. - internal static void EndDisabled() - { - // Stack might have been cleared with ClearStack(), check before pop. - if (s_EnabledStack.Count > 0) - GUI.enabled = s_EnabledStack.Pop(); - } - - private static Stack s_ChangedStack = new Stack(); - - public class ChangeCheckScope : GUI.Scope - { - bool m_ChangeChecked; - bool m_Changed; - public bool changed - { - get - { - if (!m_ChangeChecked) - { - m_ChangeChecked = true; - m_Changed = EndChangeCheck(); - } - return m_Changed; - } - } - - public ChangeCheckScope() - { - BeginChangeCheck(); - } - - protected override void CloseScope() - { - if (!m_ChangeChecked) - EndChangeCheck(); - } - } - - // Check if any control was changed inside a block of code. - public static void BeginChangeCheck() - { - s_ChangedStack.Push(GUI.changed); - GUI.changed = false; - } - - // Ends a change check started with BeginChangeCheck (). - // Note: BeginChangeCheck/EndChangeCheck supports nesting - // For ex., - // BeginChangeCheck() - // BeginChangeCheck() - // - // EndChangeCheck() <-- will return true - // EndChangeCheck() <-- will return true - public static bool EndChangeCheck() - { - bool changed = GUI.changed; - GUI.changed |= s_ChangedStack.Pop(); - return changed; - } - - internal partial class RecycledTextEditor : TextEditor - { - internal static bool s_ActuallyEditing = false; // internal so we can save this state. - internal static bool s_AllowContextCutOrPaste = true; // e.g. selectable labels only allow for copying - - IMECompositionMode m_IMECompositionModeBackup; - - // *undocumented* - internal bool IsEditingControl(int id) - { - return GUIUtility.keyboardControl == id && controlID == id && s_ActuallyEditing && GUIView.current.hasFocus; - } - - // *undocumented* - public virtual void BeginEditing(int id, string newText, Rect position, GUIStyle style, bool multiline, bool passwordField) - { - if (IsEditingControl(id)) - { - return; - } - if (EditorGUI.activeEditor != null) - { - EditorGUI.activeEditor.EndEditing(); - } - - EditorGUI.activeEditor = this; - controlID = id; - text = s_OriginalText = newText; - this.multiline = multiline; - this.style = style; - this.position = position; - isPasswordField = passwordField; - s_ActuallyEditing = true; - scrollOffset = Vector2.zero; - UnityEditor.Undo.IncrementCurrentGroup(); - - m_IMECompositionModeBackup = Input.imeCompositionMode; - Input.imeCompositionMode = IMECompositionMode.On; - } - - // *undocumented* - public virtual void EndEditing() - { - if (EditorGUI.activeEditor == this) - { - EditorGUI.activeEditor = null; - } - - controlID = 0; - s_ActuallyEditing = false; - s_AllowContextCutOrPaste = true; - UnityEditor.Undo.IncrementCurrentGroup(); - - Input.imeCompositionMode = m_IMECompositionModeBackup; - } - } - - // There can be two way something can get focus - internal sealed partial class DelayedTextEditor : RecycledTextEditor - { - private int controlThatHadFocus = 0, messageControl = 0; - internal string controlThatHadFocusValue = ""; - private GUIView viewThatHadFocus; - private bool m_CommitCommandSentOnLostFocus; - private const string CommitCommand = "DelayedControlShouldCommit"; - - private bool m_IgnoreBeginGUI = false; - - //*undocumented* - public void BeginGUI() - { - if (m_IgnoreBeginGUI) - { - return; - } - if (GUIUtility.keyboardControl == controlID) - { - controlThatHadFocus = GUIUtility.keyboardControl; - controlThatHadFocusValue = text; - viewThatHadFocus = GUIView.current; - } - else - { - controlThatHadFocus = 0; - } - } - - //*undocumented* - public void EndGUI(EventType type) - { - int sendID = 0; - if (controlThatHadFocus != 0 && controlThatHadFocus != GUIUtility.keyboardControl) - { - sendID = controlThatHadFocus; - controlThatHadFocus = 0; - } - - if (sendID != 0 && !m_CommitCommandSentOnLostFocus) - { - messageControl = sendID; - // Debug.Log ("" + messageControl + " lost focus to " + GUIUtility.keyboardControl+ " in " + type+". Sending Message. value:" + controlThatHadFocusValue); - m_IgnoreBeginGUI = true; - - // Explicitly set the keyboardControl for the view that had focus in preparation for the following SendEvent, - // but only if the current view is the view that had focus. - // This is necessary as GUIView::OnInputEvent (native) will load the old keyboardControl for nested OnGUI calls. - if (GUIView.current == viewThatHadFocus) - viewThatHadFocus.SetKeyboardControl(GUIUtility.keyboardControl); - - viewThatHadFocus.SendEvent(EditorGUIUtility.CommandEvent(CommitCommand)); - m_IgnoreBeginGUI = false; - // Debug.Log ("Afterwards: " + GUIUtility.keyboardControl); - messageControl = 0; - } - } - - //*undocumented* - public override void EndEditing() - { - //The following block handles the case where a different window is focus while editing delayed text box - if (Event.current == null) - { - // We set this flag because of a bug that was trigger when you switched focus to another window really fast - // right after focusing on the text box. For some reason keyboardControl was changed and the commit message - // was being sent twice which caused layout issues. - m_CommitCommandSentOnLostFocus = true; - m_IgnoreBeginGUI = true; - messageControl = controlID; - var temp = GUIUtility.keyboardControl; - viewThatHadFocus.SetKeyboardControl(0); - - viewThatHadFocus.SendEvent(EditorGUIUtility.CommandEvent(CommitCommand)); - m_IgnoreBeginGUI = false; - viewThatHadFocus.SetKeyboardControl(temp); - messageControl = 0; - } - - base.EndEditing(); - } - - //*undocumented* - public string OnGUI(int id, string value, out bool changed) - { - Event evt = Event.current; - if (evt.type == EventType.ExecuteCommand && evt.commandName == CommitCommand && id == messageControl) - { - m_CommitCommandSentOnLostFocus = false; - // Only set changed to true if the value has actually changed. Otherwise EditorGUI.EndChangeCheck will report false positives, - // 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) - changed = value != controlThatHadFocusValue; - evt.Use(); - messageControl = 0; - return controlThatHadFocusValue; - } - changed = false; - - return value; - } - } - - internal sealed partial class PopupMenuEvent - { - public string commandName; - public GUIView receiver; - - public PopupMenuEvent(string cmd, GUIView v) - { - commandName = cmd; - receiver = v; - } - - public void SendEvent() - { - if (receiver) - { - receiver.SendEvent(EditorGUIUtility.CommandEvent(commandName)); - } - else - { - Debug.LogError("BUG: We don't have a receiver set up, please report"); - } - } - } - - private static void ShowTextEditorPopupMenu() - { - GenericMenu pm = new GenericMenu(); - if (s_RecycledEditor.hasSelection && !s_RecycledEditor.isPasswordField) - { - if (RecycledTextEditor.s_AllowContextCutOrPaste) - { - pm.AddItem(EditorGUIUtility.TrTextContent("Cut"), false, new PopupMenuEvent(EventCommandNames.Cut, GUIView.current).SendEvent); - } - pm.AddItem(EditorGUIUtility.TrTextContent("Copy"), false, new PopupMenuEvent(EventCommandNames.Copy, GUIView.current).SendEvent); - } - else - { - if (RecycledTextEditor.s_AllowContextCutOrPaste) - { - pm.AddDisabledItem(EditorGUIUtility.TrTextContent("Cut")); - } - pm.AddDisabledItem(EditorGUIUtility.TrTextContent("Copy")); - } - - if (s_RecycledEditor.CanPaste() && RecycledTextEditor.s_AllowContextCutOrPaste) - { - pm.AddItem(EditorGUIUtility.TrTextContent("Paste"), false, new PopupMenuEvent(EventCommandNames.Paste, GUIView.current).SendEvent); - } - else - { - // pm.AddDisabledItem (EditorGUIUtility.TrTextContent ("Paste")); - } - - pm.ShowAsContext(); - } - - // Is the platform-dependent "action" modifier key held down? (RO) - public static bool actionKey - { - get - { - if (Event.current == null) - { - return false; - } - if (Application.platform == RuntimePlatform.OSXEditor) - { - return Event.current.command; - } - else - { - return Event.current.control; - } - } - } - - internal static void BeginCollectTooltips() - { - EditorGUI.isCollectingTooltips = true; - } - - internal static void EndCollectTooltips() - { - EditorGUI.isCollectingTooltips = false; - } - - /// *listonly* - public static void DropShadowLabel(Rect position, string text) - { - DoDropShadowLabel(position, EditorGUIUtility.TempContent(text), "PreOverlayLabel", .6f); - } - - /// *listonly* - public static void DropShadowLabel(Rect position, GUIContent content) - { - DoDropShadowLabel(position, content, "PreOverlayLabel", .6f); - } - - /// *listonly* - public static void DropShadowLabel(Rect position, string text, GUIStyle style) - { - DoDropShadowLabel(position, EditorGUIUtility.TempContent(text), style, .6f); - } - - // Draws a label with a drop shadow. - public static void DropShadowLabel(Rect position, GUIContent content, GUIStyle style) - { - DoDropShadowLabel(position, content, style, .6f); - } - - internal static void DoDropShadowLabel(Rect position, GUIContent content, GUIStyle style, float shadowOpa) - { - if (Event.current.type != EventType.Repaint) - { - return; - } - - DrawLabelShadow(position, content, style, shadowOpa); - style.Draw(position, content, false, false, false, false); - } - - internal static void DrawLabelShadow(Rect position, GUIContent content, GUIStyle style, float shadowOpa) - { - Color temp = GUI.color, temp2 = GUI.contentColor, temp3 = GUI.backgroundColor; - - // Draw only background - GUI.contentColor = new Color(0, 0, 0, 0); - style.Draw(position, content, false, false, false, false); - - // Blur foreground - position.y += 1; - GUI.backgroundColor = new Color(0, 0, 0, 0); - GUI.contentColor = temp2; - Draw4(position, content, 1, GUI.color.a * shadowOpa, style); - Draw4(position, content, 2, GUI.color.a * shadowOpa * .42f, style); - - // Draw final foreground - GUI.color = temp; - GUI.backgroundColor = temp3; - } - - private static void Draw4(Rect position, GUIContent content, float offset, float alpha, GUIStyle style) - { - GUI.color = new Color(0, 0, 0, alpha); - position.y -= offset; - style.Draw(position, content, false, false, false, false); - position.y += offset * 2; - style.Draw(position, content, false, false, false, false); - position.y -= offset; - position.x -= offset; - style.Draw(position, content, false, false, false, false); - position.x += offset * 2; - style.Draw(position, content, false, false, false, false); - } - - // Should we select all text from the current field when the mouse goes up? - // (We need to keep track of this to support both SwipeSelection & initial click selects all) - 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) - { - Event evt = Event.current; - - // If the text field represents multiple values, the text should always start out being empty when editing it. - // This empty text will not be saved when simply clicking in the text field, or tabbing to it, - // since GUI.changed is only set to true if the user alters the string. - // Nevertheless, we also backup and return the original value if nothing changed. - // It's just nice that output is the same as input when nothing changed, - // even if the output should really be ignored when GUI.changed is false. - string origText = text; - - // We assume the text is actually valid, but we do not want to change the returned value if nothing was changed - // So we should only check for null string on the internal text and not affect the origText which will be returned if nothing changed - if (text == null) - { - text = string.Empty; - } - - if (showMixedValue) - { - text = string.Empty; - } - - // If we have keyboard control and our window have focus, we need to sync up the editor. - if (HasKeyboardFocus(id) && Event.current.type != EventType.Layout) - { - // If the editor is already set up, we just need to sync position, etc... - if (editor.IsEditingControl(id)) - { - editor.position = position; - editor.style = style; - editor.controlID = id; - editor.multiline = multiline; - editor.isPasswordField = passwordField; - editor.DetectFocusChange(); - } - else if (EditorGUIUtility.editingTextField || (evt.GetTypeForControl(id) == EventType.ExecuteCommand && evt.commandName == EventCommandNames.NewKeyboardFocus)) - { - // This one is worse: we are the new keyboardControl, but didn't know about it. - // this means a Tab operation or setting focus from code. - editor.BeginEditing(id, text, position, style, multiline, passwordField); - // If cursor is invisible, it's a selectable label, and we don't want to select all automatically - if (GUI.skin.settings.cursorColor.a > 0) - editor.SelectAll(); - - if (evt.GetTypeForControl(id) == EventType.ExecuteCommand) - { - evt.Use(); - } - } - } - - // Inform editor that someone removed focus from us. - if (editor.controlID == id && GUIUtility.keyboardControl != id) - { - editor.EndEditing(); - } - - bool mayHaveChanged = false; - string textBeforeKey = editor.text; - - switch (evt.GetTypeForControl(id)) - { - case EventType.ValidateCommand: - if (GUIUtility.keyboardControl == id) - { - switch (evt.commandName) - { - case EventCommandNames.Cut: - case EventCommandNames.Copy: - if (editor.hasSelection) - { - evt.Use(); - } - break; - case EventCommandNames.Paste: - if (editor.CanPaste()) - { - evt.Use(); - } - break; - case EventCommandNames.SelectAll: - case EventCommandNames.Delete: - evt.Use(); - break; - case EventCommandNames.UndoRedoPerformed: - editor.text = text; - evt.Use(); - break; - } - } - - break; - case EventType.ExecuteCommand: - if (GUIUtility.keyboardControl == id) - { - switch (evt.commandName) - { - case EventCommandNames.OnLostFocus: - if (activeEditor != null) - { - activeEditor.EndEditing(); - } - evt.Use(); - break; - case EventCommandNames.Cut: - editor.BeginEditing(id, text, position, style, multiline, passwordField); - editor.Cut(); - mayHaveChanged = true; - break; - case EventCommandNames.Copy: - editor.Copy(); - evt.Use(); - break; - case EventCommandNames.Paste: - editor.BeginEditing(id, text, position, style, multiline, passwordField); - editor.Paste(); - mayHaveChanged = true; - break; - case EventCommandNames.SelectAll: - editor.SelectAll(); - evt.Use(); - break; - case EventCommandNames.Delete: - // This "Delete" command stems from a Shift-Delete in the text editor. - // On Windows, Shift-Delete in text does a cut whereas on Mac, it does a delete. - editor.BeginEditing(id, text, position, style, multiline, passwordField); - if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX) - { - editor.Delete(); - } - else - { - editor.Cut(); - } - mayHaveChanged = true; - evt.Use(); - break; - } - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - if (s_Dragged && s_DragToPosition) - { - //GUIUtility.keyboardControl = id; - //editor.BeginEditing (id, text, position, style, multiline, passwordField); - editor.MoveSelectionToAltCursor(); - mayHaveChanged = true; - } - else if (s_PostPoneMove) - { - editor.MoveCursorToPosition(Event.current.mousePosition); - } - else if (s_SelectAllOnMouseUp) - { - // If cursor is invisible, it's a selectable label, and we don't want to select all automatically - if (GUI.skin.settings.cursorColor.a > 0) - { - editor.SelectAll(); - } - s_SelectAllOnMouseUp = false; - } - editor.MouseDragSelectsWholeWords(false); - s_DragToPosition = true; - s_Dragged = false; - s_PostPoneMove = false; - if (evt.button == 0) - { - GUIUtility.hotControl = 0; - evt.Use(); - } - } - break; - case EventType.MouseDown: - if (position.Contains(evt.mousePosition) && evt.button == 0) - { - // Does this text field already have focus? - if (editor.IsEditingControl(id)) - { // if so, process the event normally - if (Event.current.clickCount == 2 && GUI.skin.settings.doubleClickSelectsWord) - { - editor.MoveCursorToPosition(Event.current.mousePosition); - editor.SelectCurrentWord(); - editor.MouseDragSelectsWholeWords(true); - editor.DblClickSnap(TextEditor.DblClickSnapping.WORDS); - s_DragToPosition = false; - } - else if (Event.current.clickCount == 3 && GUI.skin.settings.tripleClickSelectsLine) - { - editor.MoveCursorToPosition(Event.current.mousePosition); - editor.SelectCurrentParagraph(); - editor.MouseDragSelectsWholeWords(true); - editor.DblClickSnap(TextEditor.DblClickSnapping.PARAGRAPHS); - s_DragToPosition = false; - } - else - { - // if mouse is over the selection, postpone cursor movement till Mouse Up - this is so we can do correct text dragging. - // if (editor.hasSelection && editor.IsOverSelection(Event.current.mousePosition)) - // s_PostPoneMove = true; - // else - editor.MoveCursorToPosition(Event.current.mousePosition); - s_SelectAllOnMouseUp = false; - } - } - else - { // Otherwise, mark this as initial click and begin editing - GUIUtility.keyboardControl = id; - editor.BeginEditing(id, text, position, style, multiline, passwordField); - editor.MoveCursorToPosition(Event.current.mousePosition); - // If cursor is invisible, it's a selectable label, and we don't want to select all automatically - if (GUI.skin.settings.cursorColor.a > 0) - { - s_SelectAllOnMouseUp = true; - } - } - - GUIUtility.hotControl = id; - evt.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - if (!evt.shift && editor.hasSelection && s_DragToPosition) - { - editor.MoveAltCursorToPosition(Event.current.mousePosition); - } - else - { - if (evt.shift) - { - editor.MoveCursorToPosition(Event.current.mousePosition); - } - else - { - editor.SelectToPosition(Event.current.mousePosition); - } - - s_DragToPosition = false; - s_SelectAllOnMouseUp = !editor.hasSelection; - } - s_Dragged = true; - evt.Use(); - } - break; - case EventType.ContextClick: - if (position.Contains(evt.mousePosition)) - { - if (!editor.IsEditingControl(id)) - { // First click: focus before showing popup - GUIUtility.keyboardControl = id; - editor.BeginEditing(id, text, position, style, multiline, passwordField); - editor.MoveCursorToPosition(Event.current.mousePosition); - } - ShowTextEditorPopupMenu(); - Event.current.Use(); - } - - break; - case EventType.KeyDown: - if (GUIUtility.keyboardControl == id) - { - char c = evt.character; - - // Let the editor handle all cursor keys, etc... - if (editor.IsEditingControl(id) && editor.HandleKeyEvent(evt)) - { - evt.Use(); - mayHaveChanged = true; - break; - } - - if (evt.keyCode == KeyCode.Escape) - { - if (editor.IsEditingControl(id)) - { - if (style == EditorStyles.toolbarSearchField || style == EditorStyles.searchField) - { - s_OriginalText = ""; - } - - editor.text = s_OriginalText; - - editor.EndEditing(); - mayHaveChanged = true; - } - } - else if (c == '\n' || (int)c == 3) - { - if (!editor.IsEditingControl(id)) - { - editor.BeginEditing(id, text, position, style, multiline, passwordField); - editor.SelectAll(); - } - else - { - if (!multiline || (evt.alt || evt.shift || evt.control)) - { - editor.EndEditing(); - } - else - { - editor.Insert(c); - mayHaveChanged = true; - break; - } - } - evt.Use(); - } - else if (c == '\t' || evt.keyCode == KeyCode.Tab) - { - // Only insert tabs if multiline - if (multiline && editor.IsEditingControl(id)) - { - bool validTabCharacter = (allowedletters == null || allowedletters.IndexOf(c) != -1); - bool validTabEvent = !(evt.alt || evt.shift || evt.control) && c == '\t'; - if (validTabEvent && validTabCharacter) - { - editor.Insert(c); - mayHaveChanged = true; - } - } - } - else if ((int)c == 25 || (int)c == 27) - { - // Note, OS X send characters for the following keys that we need to eat: - // ASCII 25: "End Of Medium" on pressing shift tab - // ASCII 27: "Escape" on pressing ESC - } - else if (editor.IsEditingControl(id)) - { - bool validCharacter = (allowedletters == null || allowedletters.IndexOf(c) != -1) && c != 0; - if (validCharacter) - { - editor.Insert(c); - mayHaveChanged = true; - } - else - { - // If the composition string is not empty, then it's likely that even though we didn't add a printable - // character to the string, we should refresh the GUI, to update the composition string. - if (Input.compositionString != "") - { - editor.ReplaceSelection(""); - mayHaveChanged = true; - } - evt.Use(); - } - } - } - - break; - case EventType.Repaint: - string drawText; - if (editor.IsEditingControl(id)) - { - drawText = passwordField ? "".PadRight(editor.text.Length, '*') : editor.text; - } - else if (showMixedValue) - { - drawText = s_MixedValueContent.text; - } - else - { - drawText = passwordField ? "".PadRight(text.Length, '*') : text; - } - - - if (!string.IsNullOrEmpty(s_UnitString) && !passwordField) - drawText += " " + s_UnitString; - - // Only change mousecursor if hotcontrol is not grabbed - if (GUIUtility.hotControl == 0) - { - EditorGUIUtility.AddCursorRect(position, MouseCursor.Text); - } - - if (!editor.IsEditingControl(id)) - { - BeginHandleMixedValueContentColor(); - style.Draw(position, EditorGUIUtility.TempContent(drawText), id, false); - EndHandleMixedValueContentColor(); - } - else - { - editor.DrawCursor(drawText); - } - break; - } - - if (GUIUtility.keyboardControl == id) - { - // TODO: remove the need for this with Optimized GUI blocks - EditorGUIUtility.textFieldInput = EditorGUIUtility.editingTextField; - } - - // Scroll offset might need to be updated - editor.UpdateScrollOffsetIfNeeded(evt); - - changed = false; - if (mayHaveChanged) - { - // If some action happened that could change the text AND - // the text actually changed, then set changed to true. - // Don't just compare the text only, since it also changes when changing text field. - // Don't leave out comparing the text though, since it will result in false positives. - changed = (textBeforeKey != editor.text); - evt.Use(); - } - if (changed) - { - GUI.changed = true; - return editor.text; - } - - RecycledTextEditor.s_AllowContextCutOrPaste = true; - - return origText; - } - - // KEYEVENTFIELD HERE =============================================================== - internal static Event KeyEventField(Rect position, Event evt) - { - return DoKeyEventField(position, evt, GUI.skin.textField); - } - - internal static Event DoKeyEventField(Rect position, Event _event, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_KeyEventFieldHash, FocusType.Passive, position); - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - // If the mouse is inside the button, we say that we're the hot control - if (position.Contains(evt.mousePosition)) - { - GUIUtility.hotControl = id; - evt.Use(); - if (bKeyEventActive) - // cancel - { - bKeyEventActive = false; - } - else - { - bKeyEventActive = true; - } - } - return _event; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = id; - - // If we got the mousedown, the mouseup is ours as well - // (no matter if the click was in the button or not) - evt.Use(); - } - return _event; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - evt.Use(); - } - break; - case EventType.Repaint: - if (bKeyEventActive) - { - GUIContent content = EditorGUIUtility.TempContent("[Please press a key]"); - style.Draw(position, content, id); - } - else - { - string str = InternalEditorUtility.TextifyEvent(_event); - style.Draw(position, EditorGUIUtility.TempContent(str), id); - } - break; - case EventType.KeyDown: - if ((GUIUtility.hotControl == id) && bKeyEventActive) - { - // ignore presses of just modifier keys - if (evt.character == '\0') - { - if (evt.alt && (evt.keyCode == KeyCode.AltGr || evt.keyCode == KeyCode.LeftAlt || evt.keyCode == KeyCode.RightAlt) || - evt.control && (evt.keyCode == KeyCode.LeftControl || evt.keyCode == KeyCode.RightControl) || - evt.command && (evt.keyCode == KeyCode.LeftApple || evt.keyCode == KeyCode.RightApple || evt.keyCode == KeyCode.LeftWindows || evt.keyCode == KeyCode.RightWindows) || - evt.shift && (evt.keyCode == KeyCode.LeftShift || evt.keyCode == KeyCode.RightShift || (int)evt.keyCode == 0)) - { - return _event; - } - } - bKeyEventActive = false; - GUI.changed = true; - GUIUtility.hotControl = 0; - Event e = new Event(evt); - evt.Use(); - return e; - } - break; - } - return _event; - } - - internal static Rect GetInspectorTitleBarObjectFoldoutRenderRect(Rect rect) - { - return new Rect(rect.x + 3f, rect.y + 3f, 16f, 16f); - } - - static bool IsValidForContextMenu(Object target) - { - // if the reference is *really* null, don't allow showing the context menu - if ((object)target == null) - return false; - - // UnityEngine.Object overrides == null, which means we might be dealing with an invalid object - bool isUnityNull = target == null; - - // if MonoBehaviour/Scriptable compares to null, then we are dealing with a missing script - // for which we still want to display context menu - if (isUnityNull && (target is MonoBehaviour || target is ScriptableObject)) - return true; - - return !isUnityNull; - } - - internal static bool DoObjectMouseInteraction(bool foldout, Rect interactionRect, Object[] targetObjs, int id) - { - // Always enabled, regardless of editor enabled state - var enabled = GUI.enabled; - GUI.enabled = true; - - // Context menu - Event evt = Event.current; - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (interactionRect.Contains(evt.mousePosition)) - { - if (evt.button == 1 && IsValidForContextMenu(targetObjs[0])) - { - EditorUtility.DisplayObjectContextMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), targetObjs, 0); - evt.Use(); - } - else if (evt.button == 0 && !(Application.platform == RuntimePlatform.OSXEditor && evt.control == true)) - { - GUIUtility.hotControl = id; - GUIUtility.keyboardControl = id; - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), id); - delay.mouseDownPosition = evt.mousePosition; - evt.Use(); - } - } - break; - - case EventType.ContextClick: - if (interactionRect.Contains(evt.mousePosition) && IsValidForContextMenu(targetObjs[0])) - { - EditorUtility.DisplayObjectContextMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), targetObjs, 0); - evt.Use(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - evt.Use(); - if (interactionRect.Contains(evt.mousePosition)) - { - GUI.changed = true; - foldout = !foldout; - } - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), id); - if (delay.CanStartDrag()) - { - GUIUtility.hotControl = 0; - DragAndDrop.PrepareStartDrag(); - DragAndDrop.objectReferences = targetObjs; - if (targetObjs.Length > 1) - { - DragAndDrop.StartDrag(""); - } - else - { - DragAndDrop.StartDrag(ObjectNames.GetDragAndDropTitle(targetObjs[0])); - } - } - evt.Use(); - } - break; - - case EventType.DragUpdated: - if (s_DragUpdatedOverID == id) - { - if (interactionRect.Contains(evt.mousePosition)) - { - if (Time.realtimeSinceStartup > s_FoldoutDestTime) - { - foldout = true; - HandleUtility.Repaint(); - } - } - else - { - s_DragUpdatedOverID = 0; - } - } - else - { - if (interactionRect.Contains(evt.mousePosition)) - { - s_DragUpdatedOverID = id; - s_FoldoutDestTime = Time.realtimeSinceStartup + kFoldoutExpandTimeout; - } - } - - if (interactionRect.Contains(evt.mousePosition)) - { - DragAndDrop.visualMode = InternalEditorUtility.InspectorWindowDrag(targetObjs, false); - Event.current.Use(); - } - break; - - case EventType.DragPerform: - if (interactionRect.Contains(evt.mousePosition)) - { - DragAndDrop.visualMode = InternalEditorUtility.InspectorWindowDrag(targetObjs, true); - DragAndDrop.AcceptDrag(); - Event.current.Use(); - } - break; - - case EventType.KeyDown: - if (EditorGUIUtility.keyboardControl == id) - { - if (evt.keyCode == KeyCode.LeftArrow) - { - foldout = false; - evt.Use(); - } - if (evt.keyCode == KeyCode.RightArrow) - { - foldout = true; - evt.Use(); - } - } - break; - } - - // Restore enabled state for the editors. - GUI.enabled = enabled; - - return foldout; - } - - // This is assumed to be called from the inpector only - private static void DoObjectFoldoutInternal(bool foldout, Rect interactionRect, Rect renderRect, Object[] targetObjs, int id) - { - // Always enabled, regardless of editor enabled state - var enabled = GUI.enabled; - GUI.enabled = true; - - // Context menu - Event evt = Event.current; - - switch (evt.GetTypeForControl(id)) - { - case EventType.Repaint: - bool isPressed = GUIUtility.hotControl == id; - EditorStyles.foldout.Draw(renderRect, isPressed, isPressed, foldout, false); - break; - } - - // Restore enabled state for the editors. - GUI.enabled = enabled; - } - - internal static bool DoObjectFoldout(bool foldout, Rect interactionRect, Rect renderRect, Object[] targetObjs, int id) - { - foldout = DoObjectMouseInteraction(foldout, interactionRect, targetObjs, id); - DoObjectFoldoutInternal(foldout, interactionRect, renderRect, targetObjs, id); - return foldout; - } - - // Make a label field. (Useful for showing read-only info.) - internal static void LabelFieldInternal(Rect position, GUIContent label, GUIContent label2, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Passive, position); - position = PrefixLabel(position, id, label); - if (Event.current.type == EventType.Repaint) - { - style.Draw(position, label2, id); - } - } - - /// *listonly* - public static bool Toggle(Rect position, bool value) - { - int id = GUIUtility.GetControlID(s_ToggleHash, FocusType.Keyboard, position); - return EditorGUIInternal.DoToggleForward(IndentedRect(position), id, value, GUIContent.none, EditorStyles.toggle); - } - - /// *listonly* - public static bool Toggle(Rect position, string label, bool value) - { - return Toggle(position, EditorGUIUtility.TempContent(label), value); - } - - /// *listonly* - public static bool Toggle(Rect position, bool value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_ToggleHash, FocusType.Keyboard, position); - return EditorGUIInternal.DoToggleForward(position, id, value, GUIContent.none, style); - } - - /// *listonly* - public static bool Toggle(Rect position, string label, bool value, GUIStyle style) - { - return Toggle(position, EditorGUIUtility.TempContent(label), value, style); - } - - /// *listonly* - public static bool Toggle(Rect position, GUIContent label, bool value) - { - int id = GUIUtility.GetControlID(s_ToggleHash, FocusType.Keyboard, position); - return EditorGUIInternal.DoToggleForward(PrefixLabel(position, id, label), id, value, GUIContent.none, EditorStyles.toggle); - } - - // Make a toggle. - public static bool Toggle(Rect position, GUIContent label, bool value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_ToggleHash, FocusType.Keyboard, position); - return EditorGUIInternal.DoToggleForward(PrefixLabel(position, id, label), id, value, GUIContent.none, style); - } - - // Make a toggle with the label on the right. - internal static bool ToggleLeftInternal(Rect position, GUIContent label, bool value, GUIStyle labelStyle) - { - int id = GUIUtility.GetControlID(s_ToggleHash, FocusType.Keyboard, position); - Rect toggleRect = IndentedRect(position); - Rect labelRect = IndentedRect(position); - labelRect.xMin += EditorStyles.toggle.padding.left; - HandlePrefixLabel(position, labelRect, label, id, labelStyle); - return EditorGUIInternal.DoToggleForward(toggleRect, id, value, GUIContent.none, EditorStyles.toggle); - } - - internal static bool DoToggle(Rect position, int id, bool value, GUIContent content, GUIStyle style) - { - return EditorGUIInternal.DoToggleForward(position, id, value, content, style); - } - - internal static string TextFieldInternal(int id, Rect position, string text, GUIStyle style) - { - bool dummy; - text = DoTextField(s_RecycledEditor, id, IndentedRect(position), text, style, null, out dummy, false, false, false); - return text; - } - - /// *listonly* - internal static string TextFieldInternal(Rect position, string text, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, position); - bool dummy; - text = DoTextField(s_RecycledEditor, id, IndentedRect(position), text, style, null, out dummy, false, false, false); - return text; - } - - // Make a text field. - internal static string TextFieldInternal(Rect position, GUIContent label, string text, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, position); - bool dummy; - text = DoTextField(s_RecycledEditor, id, PrefixLabel(position, id, label), text, style, null, out dummy, false, false, false); - return text; - } - - internal static string ToolbarSearchField(Rect position, string text, bool showWithPopupArrow) - { - int id = GUIUtility.GetControlID(s_SearchFieldHash, FocusType.Keyboard, position); - return ToolbarSearchField(id, position, text, showWithPopupArrow); - } - - internal static string ToolbarSearchField(int id, Rect position, string text, bool showWithPopupArrow) - { - bool dummy; - Rect textRect = position; - const float k_CancelButtonWidth = 14f; - textRect.width -= k_CancelButtonWidth; - - text = DoTextField(s_RecycledEditor, id, textRect, text, showWithPopupArrow ? EditorStyles.toolbarSearchFieldPopup : EditorStyles.toolbarSearchField, null, out dummy, false, false, false); - - Rect buttonRect = position; - buttonRect.x += position.width - k_CancelButtonWidth; - buttonRect.width = k_CancelButtonWidth; - if (GUI.Button(buttonRect, GUIContent.none, text != "" ? EditorStyles.toolbarSearchFieldCancelButton : EditorStyles.toolbarSearchFieldCancelButtonEmpty) && text != "") - { - s_RecycledEditor.text = text = ""; - GUIUtility.keyboardControl = 0; - } - - return text; - } - - internal static string ToolbarSearchField(Rect position, string[] searchModes, ref int searchMode, string text) - { - int id = GUIUtility.GetControlID(s_SearchFieldHash, FocusType.Keyboard, position); - return ToolbarSearchField(id, position, searchModes, ref searchMode, text); - } - - internal static string ToolbarSearchField(int id, Rect position, string[] searchModes, ref int searchMode, string text) - { - bool hasPopup = searchModes != null; - if (hasPopup) - { - searchMode = PopupCallbackInfo.GetSelectedValueForControl(id, searchMode); - - Rect popupPosition = position; - popupPosition.width = 20; - - if (Event.current.type == EventType.MouseDown && popupPosition.Contains(Event.current.mousePosition)) - { - PopupCallbackInfo.instance = new PopupCallbackInfo(id); - EditorUtility.DisplayCustomMenu(position, EditorGUIUtility.TempContent(searchModes), searchMode, PopupCallbackInfo.instance.SetEnumValueDelegate, null); - - if (s_RecycledEditor.IsEditingControl(id)) - { - Event.current.Use(); - } - } - } - - text = ToolbarSearchField(id, position, text, hasPopup); - - if (hasPopup && text == "" && !s_RecycledEditor.IsEditingControl(id) && Event.current.type == EventType.Repaint) - { - const float k_CancelButtonWidth = 14f; - position.width -= k_CancelButtonWidth; - using (new EditorGUI.DisabledScope(true)) - { - EditorStyles.toolbarSearchFieldPopup.Draw(position, EditorGUIUtility.TempContent(searchModes[searchMode]), id, false); - } - } - - return text; - } - - internal static string SearchField(Rect position, string text) - { - int id = GUIUtility.GetControlID(s_SearchFieldHash, FocusType.Keyboard, position); - bool dummy; - Rect textRect = position; - textRect.width -= 15; - text = DoTextField(s_RecycledEditor, id, textRect, text, EditorStyles.searchField, null, out dummy, false, false, false); - Rect buttonRect = position; - buttonRect.x += position.width - 15; - buttonRect.width = 15; - if (GUI.Button(buttonRect, GUIContent.none, text != "" ? EditorStyles.searchFieldCancelButton : EditorStyles.searchFieldCancelButtonEmpty) && text != "") - { - s_RecycledEditor.text = text = ""; - GUIUtility.keyboardControl = 0; - } - return text; - } - - internal static string ScrollableTextAreaInternal(Rect position, string text, ref Vector2 scrollPosition, GUIStyle style) - { - if (Event.current.type == EventType.Layout) - return text; - - int id = EditorGUIUtility.GetControlID(s_TextAreaHash, FocusType.Keyboard, position); - - position = IndentedRect(position); - float fullTextHeight = style.CalcHeight(GUIContent.Temp(text), position.width); - Rect viewRect = new Rect(0, 0, position.width, fullTextHeight); - - Vector2 oldStyleScrollValue = style.contentOffset; - - - if (position.height < viewRect.height) - { - //Scroll bar position - Rect scrollbarPosition = position; - scrollbarPosition.width = GUI.skin.verticalScrollbar.fixedWidth; - scrollbarPosition.height -= 2; - scrollbarPosition.y += 1; - scrollbarPosition.x = position.x + position.width - scrollbarPosition.width; - - position.width -= scrollbarPosition.width; - - //textEditor width changed, recalculate Text and viewRect areas. - fullTextHeight = style.CalcHeight(GUIContent.Temp(text), position.width); - viewRect = new Rect(0, 0, position.width, fullTextHeight); - - if (position.Contains(Event.current.mousePosition) && Event.current.type == EventType.ScrollWheel) - { - const float mouseWheelMultiplier = 10f; - float desiredY = scrollPosition.y + Event.current.delta.y * mouseWheelMultiplier; - scrollPosition.y = Mathf.Clamp(desiredY, 0f, viewRect.height); - Event.current.Use(); - } - - - scrollPosition.y = GUI.VerticalScrollbar(scrollbarPosition, scrollPosition.y, position.height, 0, viewRect.height); - - - if (!s_RecycledEditor.IsEditingControl(id)) - { - //When not editing we use the style.draw, so we need to change the offset on the style instead of the RecycledEditor. - style.contentOffset -= scrollPosition; - style.Internal_clipOffset = scrollPosition; - } - else - { - //Move the Editor offset to match our scrollbar - s_RecycledEditor.scrollOffset.y = scrollPosition.y; - } - } - bool dummy; - EventType beforeTextFieldEventType = Event.current.type; - string newValue = DoTextField(s_RecycledEditor, id, position, text, style, null, out dummy, false, true, false); - - //Only update the our scrollPosition if the user has interacted with the TextArea (the current event was used) - if (beforeTextFieldEventType != Event.current.type) - { - scrollPosition = s_RecycledEditor.scrollOffset; - } - - style.contentOffset = oldStyleScrollValue; - style.Internal_clipOffset = Vector2.zero; - return newValue; - } - - // Make a text area. - internal static string TextAreaInternal(Rect position, string text, GUIStyle style) - { - int id = EditorGUIUtility.GetControlID(s_TextAreaHash, FocusType.Keyboard, position); - bool dummy; - text = DoTextField(s_RecycledEditor, id, IndentedRect(position), text, style, null, out dummy, false, true, false); - return text; - } - - // Make a selectable label field. (Useful for showing read-only info that can be copy-pasted.) - internal static void SelectableLabelInternal(Rect position, string text, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_SelectableLabelHash, FocusType.Keyboard, position); - Event e = Event.current; - if (GUIUtility.keyboardControl == id && e.GetTypeForControl(id) == EventType.KeyDown) - { - switch (e.keyCode) - { - case KeyCode.LeftArrow: - case KeyCode.RightArrow: - case KeyCode.UpArrow: - case KeyCode.DownArrow: - case KeyCode.Home: - case KeyCode.End: - case KeyCode.PageUp: - case KeyCode.PageDown: - break; - case KeyCode.Space: - GUIUtility.hotControl = 0; - GUIUtility.keyboardControl = 0; - break; - default: - // Prevent using the event if it is the tab character otherwise tabbing keyfocus will break (case 562373) - if (e.character != '\t') - e.Use(); - break; - } - } - - if (e.type == EventType.ExecuteCommand && (e.commandName == EventCommandNames.Paste || e.commandName == EventCommandNames.Cut) && GUIUtility.keyboardControl == id) - { - e.Use(); - } - - - Color tempCursorColor = GUI.skin.settings.cursorColor; - GUI.skin.settings.cursorColor = new Color(0, 0, 0, 0); - - RecycledTextEditor.s_AllowContextCutOrPaste = false; - - bool dummy; - text = DoTextField(s_RecycledEditor, id, IndentedRect(position), text, style, string.Empty, out dummy, false, true, false); - - GUI.skin.settings.cursorColor = tempCursorColor; - } - - [Obsolete("Use PasswordField instead.")] - public static string DoPasswordField(int id, Rect position, string password, GUIStyle style) - { - bool guiChanged; - return DoTextField(s_RecycledEditor, id, position, password, style, null, out guiChanged, false, false, true); - } - - [Obsolete("Use PasswordField instead.")] - public static string DoPasswordField(int id, Rect position, GUIContent label, string password, GUIStyle style) - { - bool guiChanged; - return DoTextField(s_RecycledEditor, id, PrefixLabel(position, id, label), password, style, null, out guiChanged, false, false, true); - } - - /// *listonly* - internal static string PasswordFieldInternal(Rect position, string password, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_PasswordFieldHash, FocusType.Keyboard, position); - bool guiChanged; - return DoTextField(s_RecycledEditor, id, IndentedRect(position), password, style, null, out guiChanged, false, false, true); - } - - // Make a text field where the user can enter a password. - internal static string PasswordFieldInternal(Rect position, GUIContent label, string password, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_PasswordFieldHash, FocusType.Keyboard, position); - bool guiChanged; - return DoTextField(s_RecycledEditor, id, PrefixLabel(position, id, label), password, style, null, out guiChanged, false, false, true); - } - - /// *listonly* - internal static float FloatFieldInternal(Rect position, float value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position); - return DoFloatField(s_RecycledEditor, IndentedRect(position), new Rect(0, 0, 0, 0), id, value, kFloatFieldFormatString, style, false); - } - - // Make a text field for entering floats. - internal static float FloatFieldInternal(Rect position, GUIContent label, float value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position); - Rect position2 = PrefixLabel(position, id, label); - position.xMax = position2.x; - return DoFloatField(s_RecycledEditor, position2, position, id, value, kFloatFieldFormatString, style, true); - } - - /// *listonly* - internal static double DoubleFieldInternal(Rect position, double value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position); - return DoDoubleField(s_RecycledEditor, IndentedRect(position), new Rect(0, 0, 0, 0), id, value, kDoubleFieldFormatString, style, false); - } - - // Make a text field for entering floats. - internal static double DoubleFieldInternal(Rect position, GUIContent label, double value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position); - Rect position2 = PrefixLabel(position, id, label); - position.xMax = position2.x; - return DoDoubleField(s_RecycledEditor, position2, position, id, value, kDoubleFieldFormatString, style, true); - } - - // Handle dragging of value - internal static void DragNumberValue(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, bool isDouble, ref double doubleVal, ref long longVal, string formatString, GUIStyle style, double dragSensitivity) - { - Event evt = Event.current; - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (dragHotZone.Contains(evt.mousePosition) && evt.button == 0) - { - // When clicking the dragging rect ensure that the number field is not - // editing: otherwise we dont see the actual value but the editted temp value - EditorGUIUtility.editingTextField = false; - - GUIUtility.hotControl = id; - - if (activeEditor != null) - { - activeEditor.EndEditing(); - } - evt.Use(); - GUIUtility.keyboardControl = id; - - s_DragCandidateState = 1; - s_DragStartValue = doubleVal; - s_DragStartIntValue = longVal; - s_DragStartPos = evt.mousePosition; - s_DragSensitivity = dragSensitivity; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && s_DragCandidateState != 0) - { - GUIUtility.hotControl = 0; - s_DragCandidateState = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - switch (s_DragCandidateState) - { - case 1: - if ((Event.current.mousePosition - s_DragStartPos).sqrMagnitude > kDragDeadzone) - { - s_DragCandidateState = 2; - GUIUtility.keyboardControl = id; - } - evt.Use(); - break; - case 2: - // Don't change the editor.content.text here. - // Instead, wait for scripting validation to enforce clamping etc. and then - // update the editor.content.text in the repaint event. - if (isDouble) - { - doubleVal += HandleUtility.niceMouseDelta * s_DragSensitivity; - doubleVal = MathUtils.RoundBasedOnMinimumDifference(doubleVal, s_DragSensitivity); - } - else - { - longVal += (long)Math.Round(HandleUtility.niceMouseDelta * s_DragSensitivity); - } - GUI.changed = true; - - evt.Use(); - break; - } - } - break; - case EventType.KeyDown: - if (GUIUtility.hotControl == id && evt.keyCode == KeyCode.Escape && s_DragCandidateState != 0) - { - doubleVal = s_DragStartValue; - longVal = s_DragStartIntValue; - GUI.changed = true; - // s_LastEditorControl = -1; - GUIUtility.hotControl = 0; - evt.Use(); - } - break; - case EventType.Repaint: - EditorGUIUtility.AddCursorRect(dragHotZone, MouseCursor.SlideArrow); - break; - } - } - - internal static float DoFloatField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, float value, string formatString, GUIStyle style, bool draggable) - { - return DoFloatField(editor, position, dragHotZone, id, value, formatString, style, draggable, Event.current.GetTypeForControl(id) == EventType.MouseDown ? (float)NumericFieldDraggerUtility.CalculateFloatDragSensitivity(s_DragStartValue) : 0.0f); - } - - internal static float DoFloatField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, float value, string formatString, GUIStyle style, bool draggable, float dragSensitivity) - { - long dummy = 0; - double doubleValue = value; - DoNumberField(editor, position, dragHotZone, id, true, ref doubleValue, ref dummy, formatString, style, draggable, dragSensitivity); - return MathUtils.ClampToFloat(doubleValue); - } - - internal static int DoIntField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, int value, string formatString, GUIStyle style, bool draggable, float dragSensitivity) - { - double dummy = 0f; - long longValue = value; - DoNumberField(editor, position, dragHotZone, id, false, ref dummy, ref longValue, formatString, style, draggable, dragSensitivity); - - return MathUtils.ClampToInt(longValue); - } - - internal static double DoDoubleField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, double value, string formatString, GUIStyle style, bool draggable) - { - return DoDoubleField(editor, position, dragHotZone, id, value, formatString, style, draggable, Event.current.GetTypeForControl(id) == EventType.MouseDown ? NumericFieldDraggerUtility.CalculateFloatDragSensitivity(s_DragStartValue) : 0.0); - } - - internal static double DoDoubleField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, double value, string formatString, GUIStyle style, bool draggable, double dragSensitivity) - { - long dummy = 0; - DoNumberField(editor, position, dragHotZone, id, true, ref value, ref dummy, formatString, style, draggable, dragSensitivity); - return value; - } - - internal static long DoLongField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, long value, string formatString, GUIStyle style, bool draggable, double dragSensitivity) - { - double dummy = 0f; - DoNumberField(editor, position, dragHotZone, id, false, ref dummy, ref value, formatString, style, draggable, dragSensitivity); - return value; - } - - internal static readonly string s_AllowedCharactersForFloat = "inftynaeINFTYNAE0123456789.,-*/+%^()"; - - internal static readonly string s_AllowedCharactersForInt = "0123456789-*/+%^()"; - - static bool HasKeyboardFocus(int controlID) - { - // Every EditorWindow has its own keyboardControl state so we also need to - // check if the current OS view has focus to determine if the control has actual key focus (gets the input) - // and not just being a focused control in an unfocused window. - return (GUIUtility.keyboardControl == controlID && GUIView.current.hasFocus); - } - - internal static void DoNumberField(RecycledTextEditor editor, Rect position, Rect dragHotZone, int id, bool isDouble, ref double doubleVal, ref long longVal, string formatString, GUIStyle style, bool draggable, double dragSensitivity) - { - bool changed; - string allowedCharacters = isDouble ? s_AllowedCharactersForFloat : s_AllowedCharactersForInt; - if (draggable) - { - DragNumberValue(editor, position, dragHotZone, id, isDouble, ref doubleVal, ref longVal, formatString, style, dragSensitivity); - } - - Event evt = Event.current; - string str; - if (HasKeyboardFocus(id) || (evt.type == EventType.MouseDown && evt.button == 0 && position.Contains(evt.mousePosition))) - { - if (!editor.IsEditingControl(id)) - { - str = s_RecycledCurrentEditingString = isDouble ? doubleVal.ToString(formatString) : longVal.ToString(formatString); - } - else - { - str = s_RecycledCurrentEditingString; - // This piece of code will change the actively edited textfield to readjust whenever the underlying value changes. - /* - if (isFloat ? (s_RecycledCurrentEditingFloat == floatVal) : (s_RecycledCurrentEditingInt == intVal)) { - str = s_RecycledCurrentEditingString; - } - */ - if (evt.type == EventType.ValidateCommand && evt.commandName == EventCommandNames.UndoRedoPerformed) - { - str = isDouble ? doubleVal.ToString(formatString) : longVal.ToString(formatString); - } - } - } - else - { - str = isDouble ? doubleVal.ToString(formatString) : longVal.ToString(formatString); - } - - if (GUIUtility.keyboardControl == id) - { - str = DoTextField(editor, id, position, str, style, allowedCharacters, out changed, false, false, false); - - // If we are still actively editing, return the input values - if (changed) - { - GUI.changed = true; - s_RecycledCurrentEditingString = str; - - // clean up the text - if (isDouble) - { - if (StringToDouble(str, out doubleVal)) - { - s_RecycledCurrentEditingFloat = doubleVal; - } - } - else - { - StringToLong(str, out longVal); - s_RecycledCurrentEditingInt = longVal; - } - } - } - else - { - str = DoTextField(editor, id, position, str, style, allowedCharacters, out changed, false, false, false); - } - } - - internal static bool StringToDouble(string str, out double value) - { - string lowered = str.ToLower(); - if (lowered == "inf" || lowered == "infinity") - { - value = double.PositiveInfinity; - } - else if (lowered == "-inf" || lowered == "-infinity") - { - value = double.NegativeInfinity; - } - else - { - // Make sure that comma & period are interchangable. - str = str.Replace(',', '.'); - - if (!double.TryParse(str, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out value)) - { - value = ExpressionEvaluator.Evaluate(str); - return true; - } - - // Don't allow user to enter NaN - it opens a can of worms that can trigger many latent bugs, - // and is not really useful for anything. - if (double.IsNaN(value)) - { - value = 0; - } - - return true; - } - - return false; - } - - internal static bool StringToLong(string str, out long value) - { - if (!long.TryParse(str, out value)) - { - value = ExpressionEvaluator.Evaluate(str); - } - return true; - } - - internal static int ArraySizeField(Rect position, GUIContent label, int value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_ArraySizeFieldHash, FocusType.Keyboard, position); - - BeginChangeCheck(); - string str = DelayedTextFieldInternal(position, id, label, value.ToString(kIntFieldFormatString), "0123456789-", style); - if (EndChangeCheck()) - { - try - { - value = int.Parse(str, System.Globalization.CultureInfo.InvariantCulture.NumberFormat); - } - catch (System.FormatException) - { - } - } - return value; - } - - internal static string DelayedTextFieldInternal(Rect position, string value, string allowedLetters, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_DelayedTextFieldHash, FocusType.Keyboard, position); - return DelayedTextFieldInternal(position, id, GUIContent.none, value, allowedLetters, style); - } - - internal static string DelayedTextFieldInternal(Rect position, int id, GUIContent label, string value, string allowedLetters, GUIStyle style) - { - // Figure out which string should be shown: If we're currently editing we disregard the incoming value - string str; - if (HasKeyboardFocus(id)) - { - // If we just got focus, set up s_RecycledCurrentEditingString - if (!s_DelayedTextEditor.IsEditingControl(id)) - { - str = s_RecycledCurrentEditingString = value; - } - else - { - str = s_RecycledCurrentEditingString; - } - Event evt = Event.current; - if (evt.type == EventType.ValidateCommand && evt.commandName == EventCommandNames.UndoRedoPerformed) - { - str = value; - } - } - else - { - str = value; - } - - bool changed; - bool wasChanged = GUI.changed; - str = s_DelayedTextEditor.OnGUI(id, str, out changed); - GUI.changed = false; - - if (!changed) - { - str = EditorGUI.DoTextField(s_DelayedTextEditor, id, PrefixLabel(position, id, label), str, style, allowedLetters, out changed, false, false, false); - GUI.changed = false; - // If we are still actively editing, return the input values - if (GUIUtility.keyboardControl == id) - { - if (!s_DelayedTextEditor.IsEditingControl(id)) - { - if (value != str) - { - GUI.changed = true; - value = str; - } - } - else - { - s_RecycledCurrentEditingString = str; - } - } - } - else - { - GUI.changed = true; - value = str; - } - GUI.changed |= wasChanged; - return value; - } - - internal static void DelayedTextFieldInternal(Rect position, int id, SerializedProperty property, string allowedLetters, GUIContent label) - { - label = BeginProperty(position, label, property); - - BeginChangeCheck(); - string newValue = DelayedTextFieldInternal(position, id, label, property.stringValue, allowedLetters, EditorStyles.textField); - if (EndChangeCheck()) - property.stringValue = newValue; - - EndProperty(); - } - - internal static float DelayedFloatFieldInternal(Rect position, GUIContent label, float value, GUIStyle style) - { - float oldVal = value; - float newVal = oldVal; - - EditorGUI.BeginChangeCheck(); - int id = GUIUtility.GetControlID(s_DelayedTextFieldHash, FocusType.Keyboard, position); - string floatStr = EditorGUI.DelayedTextFieldInternal(position, id, label, oldVal.ToString(), s_AllowedCharactersForFloat, style); - if (EditorGUI.EndChangeCheck()) - { - if (float.TryParse(floatStr, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out newVal) && newVal != oldVal) - { - value = newVal; - GUI.changed = true; - } - } - return newVal; - } - - internal static void DelayedFloatFieldInternal(Rect position, SerializedProperty property, GUIContent label) - { - label = BeginProperty(position, label, property); - - BeginChangeCheck(); - float newValue = DelayedFloatFieldInternal(position, label, property.floatValue, EditorStyles.numberField); - if (EndChangeCheck()) - property.floatValue = newValue; - - EndProperty(); - } - - internal static double DelayedDoubleFieldInternal(Rect position, GUIContent label, double value, GUIStyle style) - { - double oldVal = value; - double newVal = oldVal; - - if (label != null) - position = EditorGUI.PrefixLabel(position, label); - - EditorGUI.BeginChangeCheck(); - string doubleStr = EditorGUI.DelayedTextFieldInternal(position, oldVal.ToString(), s_AllowedCharactersForFloat, style); - if (EditorGUI.EndChangeCheck()) - { - if (double.TryParse(doubleStr, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out newVal) && newVal != oldVal) - { - value = newVal; - GUI.changed = true; - } - } - return newVal; - } - - internal static int DelayedIntFieldInternal(Rect position, GUIContent label, int value, GUIStyle style) - { - int oldVal = value; - int newVal = oldVal; - - EditorGUI.BeginChangeCheck(); - int id = GUIUtility.GetControlID(s_DelayedTextFieldHash, FocusType.Keyboard, position); - string intStr = EditorGUI.DelayedTextFieldInternal(position, id, label, oldVal.ToString(), s_AllowedCharactersForInt, style); - if (EditorGUI.EndChangeCheck()) - { - if (int.TryParse(intStr, out newVal)) - { - if (newVal != oldVal) - { - value = newVal; - GUI.changed = true; - } - } - else - { - newVal = ExpressionEvaluator.Evaluate(intStr); - if (newVal != oldVal) - { - value = newVal; - GUI.changed = true; - } - } - } - return newVal; - } - - internal static void DelayedIntFieldInternal(Rect position, SerializedProperty property, GUIContent label) - { - label = BeginProperty(position, label, property); - - BeginChangeCheck(); - int newValue = DelayedIntFieldInternal(position, label, property.intValue, EditorStyles.numberField); - if (EndChangeCheck()) - property.intValue = newValue; - - EndProperty(); - } - - /// *listonly* - internal static int IntFieldInternal(Rect position, int value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position); - return DoIntField(s_RecycledEditor, IndentedRect(position), new Rect(0, 0, 0, 0), id, value, kIntFieldFormatString, style, false, NumericFieldDraggerUtility.CalculateIntDragSensitivity(value)); - } - - // Make a text field for entering integers. - internal static int IntFieldInternal(Rect position, GUIContent label, int value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position); - Rect position2 = PrefixLabel(position, id, label); - position.xMax = position2.x; - return DoIntField(s_RecycledEditor, position2, position, id, value, kIntFieldFormatString, style, true, NumericFieldDraggerUtility.CalculateIntDragSensitivity(value)); - } - - /// *listonly* - internal static long LongFieldInternal(Rect position, long value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position); - return DoLongField(s_RecycledEditor, IndentedRect(position), new Rect(0, 0, 0, 0), id, value, kIntFieldFormatString, style, false, NumericFieldDraggerUtility.CalculateIntDragSensitivity(value)); - } - - // Make a text field for entering integers. - internal static long LongFieldInternal(Rect position, GUIContent label, long value, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position); - Rect position2 = PrefixLabel(position, id, label); - position.xMax = position2.x; - return DoLongField(s_RecycledEditor, position2, position, id, value, kIntFieldFormatString, style, true, NumericFieldDraggerUtility.CalculateIntDragSensitivity(value)); - } - - /// *listonly* - public static float Slider(Rect position, float value, float leftValue, float rightValue) - { - int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position); - return DoSlider(IndentedRect(position), EditorGUIUtility.DragZoneRect(position), id, value, leftValue, rightValue, kFloatFieldFormatString); - } - - /// *listonly* - public static float Slider(Rect position, string label, float value, float leftValue, float rightValue) - { - return Slider(position, EditorGUIUtility.TempContent(label), value, leftValue, rightValue); - } - - // Make a slider the user can drag to change a value between a min and a max. - public static float Slider(Rect position, GUIContent label, float value, float leftValue, float rightValue) - { - return PowerSlider(position, label, value, leftValue, rightValue, 1.0f); - } - - internal static float Slider(Rect position, GUIContent label, float value, float sliderMin, float sliderMax, float textFieldMin, float textFieldMax) - { - var id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position); - var controlRect = PrefixLabel(position, id, label); - var dragZone = LabelHasContent(label) ? EditorGUIUtility.DragZoneRect(position) : new Rect(); // Ensure dragzone is empty when we have no label - return DoSlider(controlRect, dragZone, id, value, sliderMin, sliderMax, kFloatFieldFormatString, textFieldMin, textFieldMax, 1f, GUI.skin.horizontalSlider, GUI.skin.horizontalSliderThumb, null); - } - - /// *listonly* - internal static float PowerSlider(Rect position, string label, float sliderValue, float leftValue, float rightValue, float power) - { - return PowerSlider(position, EditorGUIUtility.TempContent(label), sliderValue, leftValue, rightValue, power); - } - - // Make a power slider the user can drag to change a value between a min and a max. - internal static float PowerSlider(Rect position, GUIContent label, float sliderValue, float leftValue, float rightValue, float power) - { - int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position); - Rect controlRect = PrefixLabel(position, id, label); - Rect dragZone = LabelHasContent(label) ? EditorGUIUtility.DragZoneRect(position) : new Rect(); // Ensure dragzone is empty when we have no label - return DoSlider(controlRect, dragZone, id, sliderValue, leftValue, rightValue, kFloatFieldFormatString, power); - } - - private static float PowPreserveSign(float f, float p) - { - var result = Mathf.Pow(Mathf.Abs(f), p); - return f < 0.0f ? -result : result; - } - - private static void DoPropertyContextMenu(SerializedProperty property) - { - GenericMenu pm = new GenericMenu(); - SerializedProperty propertyWithPath = property.serializedObject.FindProperty(property.propertyPath); - - ScriptAttributeUtility.GetHandler(property).AddMenuItems(property, pm); - - // Would be nice to allow to set to value of a specific target for properties with children too, - // but it's not currently supported. - if (property.hasMultipleDifferentValues && !property.hasVisibleChildren) - { - TargetChoiceHandler.AddSetToValueOfTargetMenuItems(pm, propertyWithPath, TargetChoiceHandler.SetToValueOfTarget); - } - - if (property.serializedObject.targetObjects.Length == 1 && property.isInstantiatedPrefab) - { - pm.AddItem(EditorGUIUtility.TrTextContent("Revert Value to Prefab"), false, TargetChoiceHandler.SetPrefabOverride, propertyWithPath); - } - - // If property is an element in an array, show duplicate and delete menu options - if (property.propertyPath.LastIndexOf(']') == property.propertyPath.Length - 1) - { - var parentArrayPropertyPath = property.propertyPath.Substring(0, property.propertyPath.LastIndexOf(".Array.data[")); - var parentArrayProperty = property.serializedObject.FindProperty(parentArrayPropertyPath); - - if (!parentArrayProperty.isFixedBuffer) - { - if (pm.GetItemCount() > 0) - { - pm.AddSeparator(""); - } - pm.AddItem(EditorGUIUtility.TrTextContent("Duplicate Array Element"), false, (a) => - { - TargetChoiceHandler.DuplicateArrayElement(a); - EditorGUIUtility.editingTextField = false; - }, propertyWithPath); - pm.AddItem(EditorGUIUtility.TrTextContent("Delete Array Element"), false, (a) => - { - TargetChoiceHandler.DeleteArrayElement(a); - EditorGUIUtility.editingTextField = false; - }, propertyWithPath); - } - } - - // If shift is held down, show debug menu options - if (Event.current.shift) - { - if (pm.GetItemCount() > 0) - { - pm.AddSeparator(""); - } - pm.AddItem(EditorGUIUtility.TrTextContent("Print Property Path"), false, e => Debug.Log(((SerializedProperty)e).propertyPath), propertyWithPath); - } - - if (EditorApplication.contextualPropertyMenu != null) - { - if (pm.GetItemCount() > 0) - { - pm.AddSeparator(""); - } - EditorApplication.contextualPropertyMenu(pm, property); - } - - Event.current.Use(); - if (pm.GetItemCount() == 0) - { - return; - } - - pm.ShowAsContext(); - } - - /// *listonly* - public static void Slider(Rect position, SerializedProperty property, float leftValue, float rightValue) - { - Slider(position, property, leftValue, rightValue, property.displayName); - } - - /// *listonly* - public static void Slider(Rect position, SerializedProperty property, float leftValue, float rightValue, string label) - { - Slider(position, property, leftValue, rightValue, EditorGUIUtility.TempContent(label)); - } - - // Make a slider the user can drag to change a value between a min and a max. - public static void Slider(Rect position, SerializedProperty property, float leftValue, float rightValue, GUIContent label) - { - label = BeginProperty(position, label, property); - - BeginChangeCheck(); - - float newValue = Slider(position, label, property.floatValue, leftValue, rightValue); - if (EndChangeCheck()) - { - property.floatValue = newValue; - } - - EndProperty(); - } - - /// *listonly* - public static int IntSlider(Rect position, int value, int leftValue, int rightValue) - { - int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position); - return Mathf.RoundToInt(DoSlider(IndentedRect(position), EditorGUIUtility.DragZoneRect(position), id, value, leftValue, rightValue, kIntFieldFormatString)); - } - - /// *listonly* - public static int IntSlider(Rect position, string label, int value, int leftValue, int rightValue) - { - return IntSlider(position, EditorGUIUtility.TempContent(label), value, leftValue, rightValue); - } - - // Make a slider the user can drag to change an integer value between a min and a max. - public static int IntSlider(Rect position, GUIContent label, int value, int leftValue, int rightValue) - { - int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position); - return Mathf.RoundToInt(DoSlider(PrefixLabel(position, id, label), EditorGUIUtility.DragZoneRect(position), id, value, leftValue, rightValue, kIntFieldFormatString)); - } - - /// *listonly* - public static void IntSlider(Rect position, SerializedProperty property, int leftValue, int rightValue) - { - IntSlider(position, property, leftValue, rightValue, property.displayName); - } - - /// *listonly* - public static void IntSlider(Rect position, SerializedProperty property, int leftValue, int rightValue, string label) - { - IntSlider(position, property, leftValue, rightValue, EditorGUIUtility.TempContent(label)); - } - - // Make a slider the user can drag to change a value between a min and a max. - public static void IntSlider(Rect position, SerializedProperty property, int leftValue, int rightValue, GUIContent label) - { - label = BeginProperty(position, label, property); - - BeginChangeCheck(); - - int newValue = IntSlider(position, label, property.intValue, leftValue, rightValue); - if (EndChangeCheck()) - { - property.intValue = newValue; - } - - EndProperty(); - } - - // Generic method for showing a left aligned and right aligned label within a rect - internal static void DoTwoLabels(Rect rect, GUIContent leftLabel, GUIContent rightLabel, GUIStyle labelStyle) - { - if (Event.current.type != EventType.Repaint) - return; - - TextAnchor oldAlignment = labelStyle.alignment; - - labelStyle.alignment = TextAnchor.UpperLeft; - GUI.Label(rect, leftLabel, labelStyle); - - labelStyle.alignment = TextAnchor.UpperRight; - GUI.Label(rect, rightLabel, labelStyle); - - labelStyle.alignment = oldAlignment; - } - - private static float DoSlider(Rect position, Rect dragZonePosition, int id, float value, float left, float right, string formatString) - { - return DoSlider(position, dragZonePosition, id, value, left, right, formatString, 1f); - } - - private static float DoSlider(Rect position, Rect dragZonePosition, int id, float value, float left, float right, string formatString, float power) - { - return DoSlider(position, dragZonePosition, id, value, left, right, formatString, power, GUI.skin.horizontalSlider, GUI.skin.horizontalSliderThumb, null); - } - - private static float DoSlider(Rect position, Rect dragZonePosition, int id, float value, float left, float right, string formatString, float power, GUIStyle sliderStyle, GUIStyle thumbStyle, Texture2D sliderBackground) - { - return DoSlider(position, dragZonePosition, id, value, left, right, formatString, left, right, power, sliderStyle, thumbStyle, sliderBackground); - } - - private static float DoSlider( - Rect position, Rect dragZonePosition, int id, float value, float sliderMin, float sliderMax, string formatString, float textFieldMin, float textFieldMax, float power, GUIStyle sliderStyle, GUIStyle thumbStyle, Texture2D sliderBackground - ) - { - int sliderId = GUIUtility.GetControlID(s_SliderKnobHash, FocusType.Passive, position); - // Map some nonsensical edge cases to avoid breaking the UI. - // A slider with such a large range is basically useless, anyway. - sliderMin = Mathf.Clamp(sliderMin, float.MinValue, float.MaxValue); - sliderMax = Mathf.Clamp(sliderMax, float.MinValue, float.MaxValue); - - float w = position.width; - if (w >= kSliderMinW + kSpacing + EditorGUIUtility.fieldWidth) - { - float sWidth = w - kSpacing - EditorGUIUtility.fieldWidth; - BeginChangeCheck(); - - // 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 - if (EditorGUIUtility.keyboardControl == id && !s_RecycledEditor.IsEditingControl(id)) - { - EditorGUIUtility.keyboardControl = sliderId; - } - - // Remap slider values according to power curve, if it's not identity - var remapLeft = sliderMin; - var remapRight = sliderMax; - var newSliderValue = value; - if (power != 1f) - { - remapLeft = PowPreserveSign(sliderMin, 1f / power); - remapRight = PowPreserveSign(sliderMax, 1f / power); - newSliderValue = PowPreserveSign(value, 1f / power); - } - - Rect sliderRect = new Rect(position.x, position.y, sWidth, position.height); - - if (sliderBackground != null && Event.current.type == EventType.Repaint) - { - var bgRect = sliderStyle.overflow.Add(sliderStyle.padding.Remove(sliderRect)); - Graphics.DrawTexture(bgRect, sliderBackground, new Rect(.5f / sliderBackground.width, .5f / sliderBackground.height, 1 - 1f / sliderBackground.width, 1 - 1f / sliderBackground.height), 0, 0, 0, 0, Color.grey); - } - - newSliderValue = GUI.Slider(sliderRect, newSliderValue, 0, remapLeft, remapRight, sliderStyle, showMixedValue ? "SliderMixed" : thumbStyle, true, sliderId); - if (power != 1f) - { - newSliderValue = PowPreserveSign(newSliderValue, power); - newSliderValue = Mathf.Clamp(newSliderValue, Mathf.Min(sliderMin, sliderMax), Mathf.Max(sliderMin, sliderMax)); - } - - // Do slider labels if present - if (EditorGUIUtility.sliderLabels.HasLabels()) - { - Color orgColor = GUI.color; - GUI.color = GUI.color * new Color(1f, 1f, 1f, 0.5f); - Rect labelRect = new Rect(sliderRect.x, sliderRect.y + 10, sliderRect.width, sliderRect.height); - DoTwoLabels(labelRect, EditorGUIUtility.sliderLabels.leftLabel, EditorGUIUtility.sliderLabels.rightLabel, EditorStyles.miniLabel); - GUI.color = orgColor; - EditorGUIUtility.sliderLabels.SetLabels(null, null); - } - - // The keyboard control id that we want to retain is the "main" one that is used for the combined control, including the text field. - // Whenever the keyboardControl is the sliderId after calling the slider function, we set it back to this main id, - // regardless of whether it had keyboard focus before the function call, or just got it. - if (EditorGUIUtility.keyboardControl == sliderId || EditorGUIUtility.hotControl == sliderId) - { - EditorGUIUtility.keyboardControl = id; - } - - if (EditorGUIUtility.keyboardControl == id && Event.current.type == EventType.KeyDown && !s_RecycledEditor.IsEditingControl(id) - && (Event.current.keyCode == KeyCode.LeftArrow || Event.current.keyCode == KeyCode.RightArrow)) - { - // Change by approximately 1/100 of entire range, or 1/10 if holding down shift - // But round to nearest power of ten to get nice resulting numbers. - float delta = MathUtils.GetClosestPowerOfTen(Mathf.Abs((sliderMax - sliderMin) * 0.01f)); - if (formatString == kIntFieldFormatString && delta < 1) - { - delta = 1; - } - if (Event.current.shift) - { - delta *= 10; - } - - // Increment or decrement by just over half the delta. - // This means that e.g. if delta is 1, incrementing from 1.0 will go to 2.0, - // but incrementing from 0.9 is going to 1.0 rather than 2.0. - // This feels more right since 1.0 is the "next" one. - if (Event.current.keyCode == KeyCode.LeftArrow) - { - newSliderValue -= delta * 0.5001f; - } - else - { - newSliderValue += delta * 0.5001f; - } - - // Now round to a multiple of our delta value so we get a round end result instead of just a round delta. - newSliderValue = MathUtils.RoundToMultipleOf(newSliderValue, delta); - GUI.changed = true; - Event.current.Use(); - } - if (EndChangeCheck()) - { - float valuesPerPixel = (sliderMax - sliderMin) / (sWidth - GUI.skin.horizontalSlider.padding.horizontal - GUI.skin.horizontalSliderThumb.fixedWidth); - newSliderValue = MathUtils.RoundBasedOnMinimumDifference(newSliderValue, Mathf.Abs(valuesPerPixel)); - value = Mathf.Clamp(newSliderValue, Mathf.Min(sliderMin, sliderMax), Mathf.Max(sliderMin, sliderMax)); - if (s_RecycledEditor.IsEditingControl(id)) - { - s_RecycledEditor.EndEditing(); - } - } - - BeginChangeCheck(); - var newTextFieldValue = DoFloatField(s_RecycledEditor, new Rect(position.x + sWidth + kSpacing, position.y, EditorGUIUtility.fieldWidth, position.height), dragZonePosition, id, value, formatString, EditorStyles.numberField, true); - if (EndChangeCheck()) - { - value = Mathf.Clamp(newTextFieldValue, Mathf.Min(textFieldMin, textFieldMax), Mathf.Max(textFieldMin, textFieldMax)); - } - } - else - { - w = Mathf.Min(EditorGUIUtility.fieldWidth, w); - position.x = position.xMax - w; - position.width = w; - value = DoFloatField(s_RecycledEditor, position, dragZonePosition, id, value, formatString, EditorStyles.numberField, true); - value = Mathf.Clamp(value, Mathf.Min(textFieldMin, textFieldMax), Mathf.Max(textFieldMin, textFieldMax)); - } - return value; - } - - /// *listonly* - [System.Obsolete("Switch the order of the first two parameters.")] - public static void MinMaxSlider(GUIContent label, Rect position, ref float minValue, ref float maxValue, float minLimit, float maxLimit) - { - MinMaxSlider(position, label, ref minValue, ref maxValue, minLimit, maxLimit); - } - - /// *listonly* - public static void MinMaxSlider(Rect position, string label, ref float minValue, ref float maxValue, float minLimit, float maxLimit) - { - MinMaxSlider(position, EditorGUIUtility.TempContent(label), ref minValue, ref maxValue, minLimit, maxLimit); - } - - /// *listonly* - public static void MinMaxSlider(Rect position, GUIContent label, ref float minValue, ref float maxValue, float minLimit, float maxLimit) - { - int id = GUIUtility.GetControlID(s_MinMaxSliderHash, FocusType.Passive); - DoMinMaxSlider(PrefixLabel(position, id, label), id, ref minValue, ref maxValue, minLimit, maxLimit); - } - - // Make a special slider the user can use to specify a range between a min and a max. - public static void MinMaxSlider(Rect position, ref float minValue, ref float maxValue, float minLimit, float maxLimit) - { - DoMinMaxSlider(IndentedRect(position), GUIUtility.GetControlID(s_MinMaxSliderHash, FocusType.Passive), ref minValue, ref maxValue, minLimit, maxLimit); - } - - private static void DoMinMaxSlider(Rect position, int id, ref float minValue, ref float maxValue, float minLimit, float maxLimit) - { - float size = maxValue - minValue; - BeginChangeCheck(); - EditorGUIExt.DoMinMaxSlider(position, id, ref minValue, ref size, minLimit, maxLimit, minLimit, maxLimit, GUI.skin.horizontalSlider, EditorStyles.minMaxHorizontalSliderThumb, true); - if (EndChangeCheck()) - { - maxValue = minValue + size; - } - } - - // The indent level of the field labels. - public static int indentLevel - { - get { return ms_IndentLevel; } - set { ms_IndentLevel = value; } - } - - internal static float indent - { - get { return indentLevel * kIndentPerLevel; } - } - - public class IndentLevelScope : GUI.Scope - { - int m_IndentOffset; - public IndentLevelScope() : this(1) {} - - public IndentLevelScope(int increment) - { - m_IndentOffset = increment; - EditorGUI.indentLevel += m_IndentOffset; - } - - protected override void CloseScope() - { - EditorGUI.indentLevel -= m_IndentOffset; - } - } - - /// *listonly* - private static int PopupInternal(Rect position, string label, int selectedIndex, string[] displayedOptions, GUIStyle style) - { - return PopupInternal(position, EditorGUIUtility.TempContent(label), selectedIndex, EditorGUIUtility.TempContent(displayedOptions), style); - } - - /// *listonly* - private static int PopupInternal(Rect position, GUIContent label, int selectedIndex, string[] displayedOptions, GUIStyle style) - { - return PopupInternal(position, label, selectedIndex, EditorGUIUtility.TempContent(displayedOptions), style); - } - - // Make a generic popup selection field. - private static int PopupInternal(Rect position, GUIContent label, int selectedIndex, GUIContent[] displayedOptions, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_PopupHash, FocusType.Keyboard, position); - if (label != null) - position = PrefixLabel(position, id, label); - return DoPopup(position, id, selectedIndex, displayedOptions, style); - } - - // Called from PropertyField - private static void Popup(Rect position, SerializedProperty property, GUIContent label) - { - BeginChangeCheck(); - int idx = EditorGUI.Popup(position, label, property.hasMultipleDifferentValues ? -1 : property.enumValueIndex, EditorGUIUtility.TempContent(property.enumLocalizedDisplayNames)); - if (EndChangeCheck()) - { - property.enumValueIndex = idx; - } - } - - // Should be called directly - based on int properties. - internal static void Popup(Rect position, SerializedProperty property, GUIContent[] displayedOptions, GUIContent label) - { - label = BeginProperty(position, label, property); - BeginChangeCheck(); - int idx = EditorGUI.Popup(position, label, property.hasMultipleDifferentValues ? -1 : property.intValue, displayedOptions); - if (EndChangeCheck()) - { - property.intValue = idx; - } - EndProperty(); - } - - // Make an enum popup selection field. - private static Enum EnumPopupInternal(Rect position, GUIContent label, Enum selected, GUIStyle style) - { - var enumType = selected.GetType(); - if (!enumType.IsEnum) - { - throw new ArgumentException("Parameter selected must be of type System.Enum", "selected"); - } - - bool localize = EditorUtility.IsUnityAssembly(enumType); - var enumData = GetNonObsoleteEnumData(enumType); - var i = Array.IndexOf(enumData.values, selected); - i = Popup(position, label, i, localize ? EditorGUIUtility.TrTempContent(enumData.displayNames) : EditorGUIUtility.TempContent(enumData.displayNames), style); - return (i < 0 || i >= enumData.flagValues.Length) ? selected : enumData.values[i]; - } - - /// *listonly* - private static int IntPopupInternal(Rect position, GUIContent label, int selectedValue, GUIContent[] displayedOptions, int[] optionValues, GUIStyle style) - { - // value --> index - int i; - if (optionValues != null) - { - for (i = 0; (i < optionValues.Length) && (selectedValue != optionValues[i]); ++i) - { - } - } - // value = index - else - { - i = selectedValue; - } - - i = PopupInternal(position, label, i, displayedOptions, style); - - if (optionValues == null) - { - return i; - } - // index --> value - else if (i < 0 || i >= optionValues.Length) - { - return selectedValue; - } - else - { - return optionValues[i]; - } - } - - internal static void IntPopupInternal(Rect position, SerializedProperty property, GUIContent[] displayedOptions, int[] optionValues, GUIContent label) - { - label = BeginProperty(position, label, property); - - BeginChangeCheck(); - int newValue = EditorGUI.IntPopupInternal(position, label, property.intValue, displayedOptions, optionValues, EditorStyles.popup); - if (EndChangeCheck()) - { - property.intValue = newValue; - } - - EndProperty(); - } - - internal static void SortingLayerField(Rect position, GUIContent label, SerializedProperty layerID, GUIStyle style, GUIStyle labelStyle) - { - int id = EditorGUIUtility.GetControlID(s_SortingLayerFieldHash, FocusType.Keyboard, position); - position = EditorGUI.PrefixLabel(position, id, label, labelStyle); - - Event evt = Event.current; - int selected = EditorGUI.PopupCallbackInfo.GetSelectedValueForControl(id, -1); - if (selected != -1) - { - int[] layerIDs = InternalEditorUtility.sortingLayerUniqueIDs; - if (selected >= layerIDs.Length) - { - TagManagerInspector.ShowWithInitialExpansion(TagManagerInspector.InitialExpansionState.SortingLayers); - } - else - { - layerID.intValue = layerIDs[selected]; - } - } - - if (evt.type == EventType.MouseDown && position.Contains(evt.mousePosition) || evt.MainActionKeyForControl(id)) - { - int i = 0; - int[] layerIDs = InternalEditorUtility.sortingLayerUniqueIDs; - string[] layerNames = InternalEditorUtility.sortingLayerNames; - for (i = 0; i < layerIDs.Length; i++) - { - if (layerIDs[i] == layerID.intValue) - break; - } - ArrayUtility.Add(ref layerNames, ""); - ArrayUtility.Add(ref layerNames, "Add Sorting Layer..."); - - EditorGUI.DoPopup(position, id, i, EditorGUIUtility.TempContent(layerNames), style); - } - else if (Event.current.type == EventType.Repaint) - { - GUIContent layerName; - if (layerID.hasMultipleDifferentValues) - layerName = EditorGUI.mixedValueContent; - else - layerName = EditorGUIUtility.TempContent(InternalEditorUtility.GetSortingLayerNameFromUniqueID(layerID.intValue)); - EditorGUI.showMixedValue = layerID.hasMultipleDifferentValues; - EditorGUI.BeginHandleMixedValueContentColor(); - style.Draw(position, layerName, id, false); - EditorGUI.EndHandleMixedValueContentColor(); - EditorGUI.showMixedValue = false; - } - } - - // sealed partial class for storing state for popup menus so we can get the info back to OnGUI from the user selection - internal sealed partial class PopupCallbackInfo - { - // The global shared popup state - public static PopupCallbackInfo instance = null; - - // Name of the command event sent from the popup menu to OnGUI when user has changed selection - internal const string kPopupMenuChangedMessage = "PopupMenuChanged"; - - // The control ID of the popup menu that is currently displayed. - // Used to pass selection changes back again... - private int m_ControlID = 0; - - // Which item was selected - private int m_SelectedIndex = 0; - - // Which view should we send it to. - private GUIView m_SourceView; - - // *undoc* - public PopupCallbackInfo(int controlID) - { - m_ControlID = controlID; - m_SourceView = GUIView.current; - } - - // *undoc* - public static int GetSelectedValueForControl(int controlID, int selected) - { - Event evt = Event.current; - if (evt.type == EventType.ExecuteCommand && evt.commandName == kPopupMenuChangedMessage) - { - if (instance == null) - { - Debug.LogError("Popup menu has no instance"); - return selected; - } - if (instance.m_ControlID == controlID) - { - selected = instance.m_SelectedIndex; - instance = null; - GUI.changed = true; - evt.Use(); - } - } - return selected; - } - - internal void SetEnumValueDelegate(object userData, string[] options, int selected) - { - m_SelectedIndex = selected; - if (m_SourceView) - { - m_SourceView.SendEvent(EditorGUIUtility.CommandEvent(kPopupMenuChangedMessage)); - } - } - } - - - internal static int DoPopup(Rect position, int controlID, int selected, GUIContent[] popupValues, GUIStyle style) - { - selected = PopupCallbackInfo.GetSelectedValueForControl(controlID, selected); - - GUIContent buttonContent = null; - if (buttonContent == null) - { - if (showMixedValue) - { - buttonContent = s_MixedValueContent; - } - else if (selected < 0 || selected >= popupValues.Length) - { - buttonContent = GUIContent.none; - } - else - { - buttonContent = popupValues[selected]; - } - } - - Event evt = Event.current; - switch (evt.type) - { - case EventType.Repaint: - // @TODO: Remove this hack and make all editor styles use the default font instead - Font originalFont = style.font; - if (originalFont && EditorGUIUtility.GetBoldDefaultFont() && originalFont == EditorStyles.miniFont) - { - style.font = EditorStyles.miniBoldFont; - } - - BeginHandleMixedValueContentColor(); - style.Draw(position, buttonContent, controlID, false); - EndHandleMixedValueContentColor(); - - style.font = originalFont; - break; - case EventType.MouseDown: - if (evt.button == 0 && position.Contains(evt.mousePosition)) - { - if (Application.platform == RuntimePlatform.OSXEditor) - { - position.y = position.y - selected * 16 - 19; - } - - PopupCallbackInfo.instance = new PopupCallbackInfo(controlID); - EditorUtility.DisplayCustomMenu(position, popupValues, showMixedValue ? -1 : selected, PopupCallbackInfo.instance.SetEnumValueDelegate, null); - EditorGUIUtility.keyboardControl = controlID; - evt.Use(); - } - break; - case EventType.KeyDown: - if (evt.MainActionKeyForControl(controlID)) - { - if (Application.platform == RuntimePlatform.OSXEditor) - { - position.y = position.y - selected * 16 - 19; - } - - PopupCallbackInfo.instance = new PopupCallbackInfo(controlID); - EditorUtility.DisplayCustomMenu(position, popupValues, showMixedValue ? -1 : selected, PopupCallbackInfo.instance.SetEnumValueDelegate, null); - evt.Use(); - } - break; - } - return selected; - } - - /// *listonly* - internal static string TagFieldInternal(Rect position, string tag, GUIStyle style) - { - position = IndentedRect(position); - - int id = GUIUtility.GetControlID(s_TagFieldHash, FocusType.Keyboard, position); - - Event evt = Event.current; - int selected = PopupCallbackInfo.GetSelectedValueForControl(id, -1); - if (selected != -1) - { - string[] tagValues = InternalEditorUtility.tags; - if (selected >= tagValues.Length) - { - TagManagerInspector.ShowWithInitialExpansion(TagManagerInspector.InitialExpansionState.Tags); - } - else - { - tag = tagValues[selected]; - } - } - - if ((evt.type == EventType.MouseDown && position.Contains(evt.mousePosition)) || evt.MainActionKeyForControl(id)) - { - int i = 0; - string[] tagValues = InternalEditorUtility.tags; - for (i = 0; i < tagValues.Length; i++) - { - if (tagValues[i] == tag) - { - break; - } - } - ArrayUtility.Add(ref tagValues, ""); - ArrayUtility.Add(ref tagValues, L10n.Tr("Add Tag...")); - - DoPopup(position, id, i, EditorGUIUtility.TempContent(tagValues), style); - return tag; - } - else if (Event.current.type == EventType.Repaint) - { - BeginHandleMixedValueContentColor(); - style.Draw(position, showMixedValue ? s_MixedValueContent : EditorGUIUtility.TempContent(tag), id, false); - EndHandleMixedValueContentColor(); - } - - return tag; - } - - // Make a tag selection field. - internal static string TagFieldInternal(Rect position, GUIContent label, string tag, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_TagFieldHash, FocusType.Keyboard, position); - position = PrefixLabel(position, id, label); - - Event evt = Event.current; - int selected = PopupCallbackInfo.GetSelectedValueForControl(id, -1); - if (selected != -1) - { - string[] tagValues = InternalEditorUtility.tags; - if (selected >= tagValues.Length) - { - TagManagerInspector.ShowWithInitialExpansion(TagManagerInspector.InitialExpansionState.Tags); - } - else - { - tag = tagValues[selected]; - } - } - - if (evt.type == EventType.MouseDown && position.Contains(evt.mousePosition) || evt.MainActionKeyForControl(id)) - { - int i = 0; - string[] tagValues = InternalEditorUtility.tags; - for (i = 0; i < tagValues.Length; i++) - { - if (tagValues[i] == tag) - { - break; - } - } - ArrayUtility.Add(ref tagValues, ""); - ArrayUtility.Add(ref tagValues, L10n.Tr("Add Tag...")); - - DoPopup(position, id, i, EditorGUIUtility.TempContent(tagValues), style); - return tag; - } - else if (Event.current.type == EventType.Repaint) - { - style.Draw(position, EditorGUIUtility.TempContent(tag), id, false); - } - - return tag; - } - - // Make a layer selection field. - // - // this one is slow, but we only have one of them (in the game object inspector), so we should be ok. - // ARGH. This code is SO bad - I will refactor and repent after 2.5 - Nicholas - internal static int LayerFieldInternal(Rect position, GUIContent label, int layer, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_TagFieldHash, FocusType.Keyboard, position); - position = PrefixLabel(position, id, label); - - Event evt = Event.current; - bool wasChangedBefore = GUI.changed; - int selected = PopupCallbackInfo.GetSelectedValueForControl(id, -1); - if (selected != -1) - { - if (selected >= InternalEditorUtility.layers.Length) - { - TagManagerInspector.ShowWithInitialExpansion(TagManagerInspector.InitialExpansionState.Layers); - GUI.changed = wasChangedBefore; - } - else - { - int count = 0; - for (int i = 0; i < 32; i++) - { - if (InternalEditorUtility.GetLayerName(i).Length != 0) - { - if (count == selected) - { - layer = i; - break; - } - count++; - } - } - } - } - - if ((evt.type == EventType.MouseDown && position.Contains(evt.mousePosition)) || evt.MainActionKeyForControl(id)) - { - int count = 0; - for (int i = 0; i < 32; i++) - { - if (InternalEditorUtility.GetLayerName(i).Length != 0) - { - if (i == layer) - { - break; - } - count++; - } - } - - string[] layers = InternalEditorUtility.GetLayersWithId(); - - ArrayUtility.Add(ref layers, ""); - ArrayUtility.Add(ref layers, L10n.Tr("Add Layer...")); - - DoPopup(position, id, count, EditorGUIUtility.TempContent(layers), style); - Event.current.Use(); - - return layer; - } - else if (evt.type == EventType.Repaint) - { - style.Draw(position, EditorGUIUtility.TempContent(InternalEditorUtility.GetLayerName(layer)), id, false); - } - - return layer; - } - - struct EnumData - { - public Enum[] values; - public int[] flagValues; - public string[] displayNames; - public bool flags; - public Type underlyingType; - public bool unsigned; - public bool serializable; - } - - private static readonly Dictionary s_NonObsoleteEnumData = new Dictionary(); - - private static EnumData GetNonObsoleteEnumData(Type enumType) - { - EnumData enumData; - if (!s_NonObsoleteEnumData.TryGetValue(enumType, out enumData)) - { - enumData = new EnumData(); - enumData.underlyingType = Enum.GetUnderlyingType(enumType); - enumData.unsigned = - enumData.underlyingType == typeof(byte) - || enumData.underlyingType == typeof(ushort) - || enumData.underlyingType == typeof(uint) - || enumData.underlyingType == typeof(ulong); - enumData.displayNames = Enum.GetNames(enumType).Where(n => enumType.GetField(n).GetCustomAttributes(typeof(ObsoleteAttribute), false).Length == 0).ToArray(); - enumData.values = enumData.displayNames.Select(n => (Enum)Enum.Parse(enumType, n)).ToArray(); - enumData.flagValues = enumData.unsigned ? - enumData.values.Select(v => unchecked((int)Convert.ToUInt64(v))).ToArray() : - enumData.values.Select(v => unchecked((int)Convert.ToInt64(v))).ToArray(); - for (int i = 0, length = enumData.displayNames.Length; i < length; ++i) - enumData.displayNames[i] = ObjectNames.NicifyVariableName(enumData.displayNames[i]); - // convert "everything" values to ~0 for unsigned 8- and 16-bit types - if (enumData.underlyingType == typeof(ushort)) - { - for (int i = 0, length = enumData.flagValues.Length; i < length; ++i) - { - if (enumData.flagValues[i] == 0xFFFFu) - enumData.flagValues[i] = ~0; - } - } - else if (enumData.underlyingType == typeof(byte)) - { - for (int i = 0, length = enumData.flagValues.Length; i < length; ++i) - { - if (enumData.flagValues[i] == 0xFFu) - enumData.flagValues[i] = ~0; - } - } - enumData.flags = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0; - enumData.serializable = enumData.underlyingType != typeof(long) && enumData.underlyingType != typeof(ulong); - s_NonObsoleteEnumData[enumType] = enumData; - } - return enumData; - } - - /// *listonly* - internal static int MaskFieldInternal(Rect position, GUIContent label, int mask, string[] displayedOptions, GUIStyle style) - { - var id = GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position); - position = EditorGUI.PrefixLabel(position, id, label); - return MaskFieldGUI.DoMaskField(position, id, mask, displayedOptions, style); - } - - internal static int MaskFieldInternal(Rect position, GUIContent label, int mask, string[] displayedOptions, int[] optionValues, GUIStyle style) - { - var id = GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position); - position = EditorGUI.PrefixLabel(position, id, label); - return MaskFieldGUI.DoMaskField(position, id, mask, displayedOptions, optionValues, style); - } - - // Make a field for masks. - internal static int MaskFieldInternal(Rect position, int mask, string[] displayedOptions, GUIStyle style) - { - var id = GUIUtility.GetControlID(s_MaskField, FocusType.Keyboard, position); - return MaskFieldGUI.DoMaskField(IndentedRect(position), id, mask, displayedOptions, style); - } - - public static Enum EnumFlagsField(Rect position, Enum enumValue) - { - return EnumFlagsField(position, enumValue, EditorStyles.popup); - } - - public static Enum EnumFlagsField(Rect position, Enum enumValue, GUIStyle style) - { - return EnumFlagsField(position, GUIContent.none, enumValue, style); - } - - public static Enum EnumFlagsField(Rect position, string label, Enum enumValue) - { - return EnumFlagsField(position, label, enumValue, EditorStyles.popup); - } - - public static Enum EnumFlagsField(Rect position, string label, Enum enumValue, GUIStyle style) - { - return EnumFlagsField(position, EditorGUIUtility.TempContent(label), enumValue, style); - } - - public static Enum EnumFlagsField(Rect position, GUIContent label, Enum enumValue) - { - return EnumFlagsField(position, label, enumValue, EditorStyles.popup); - } - - public static Enum EnumFlagsField(Rect position, GUIContent label, Enum enumValue, GUIStyle style) - { - int changedFlags; - bool changedToValue; - return EnumFlagsField(position, label, enumValue, out changedFlags, out changedToValue, style); - } - - // Internal version that also gives you back which flags were changed and what they were changed to. - internal static Enum EnumFlagsField(Rect position, GUIContent label, Enum enumValue, out int changedFlags, out bool changedToValue, GUIStyle style) - { - var enumType = enumValue.GetType(); - if (!enumType.IsEnum) - throw new ArgumentException("Parameter enumValue must be of type System.Enum", "enumValue"); - - var enumData = GetNonObsoleteEnumData(enumType); - if (!enumData.serializable) - // this is the same message used in ScriptPopupMenus.cpp - throw new NotSupportedException(string.Format("Unsupported enum base type for {0}", enumType.Name)); - - var id = GUIUtility.GetControlID(s_EnumFlagsField, FocusType.Keyboard, position); - position = PrefixLabel(position, id, label); - - var flagsInt = EnumFlagsToInt(enumData, enumValue); - - EditorGUI.BeginChangeCheck(); - flagsInt = MaskFieldGUI.DoMaskField(position, id, flagsInt, enumData.displayNames, enumData.flagValues, style, out changedFlags, out changedToValue); - if (!EditorGUI.EndChangeCheck()) - return enumValue; - - return IntToEnumFlags(enumType, flagsInt); - } - - public static void ObjectField(Rect position, SerializedProperty property) - { - ObjectField(position, property, null, null, EditorStyles.objectField); - } - - public static void ObjectField(Rect position, SerializedProperty property, GUIContent label) - { - ObjectField(position, property, null, label, EditorStyles.objectField); - } - - public static void ObjectField(Rect position, SerializedProperty property, System.Type objType) - { - ObjectField(position, property, objType, null, EditorStyles.objectField); - } - - public static void ObjectField(Rect position, SerializedProperty property, System.Type objType, GUIContent label) - { - ObjectField(position, property, objType, label, EditorStyles.objectField); - } - - // We don't expose SerializedProperty overloads with custom GUIStyle parameters according to our guidelines, - // but we have to provide it internally because ParticleSystem uses a style that's different from everything else. - internal static void ObjectField(Rect position, SerializedProperty property, System.Type objType, GUIContent label, GUIStyle style) - { - label = BeginProperty(position, label, property); - ObjectFieldInternal(position, property, objType, label, style); - EndProperty(); - } - - // This version doesn't do BeginProperty / EndProperty. It should not be called directly. - private static void ObjectFieldInternal(Rect position, SerializedProperty property, System.Type objType, GUIContent label, GUIStyle style) - { - int id = GUIUtility.GetControlID(s_PPtrHash, FocusType.Keyboard, position); - position = PrefixLabel(position, id, label); - - bool allowSceneObjects = false; - if (property != null) - { - // @TODO: Check all target objects. - Object objectBeingEdited = property.serializedObject.targetObject; - - // Allow scene objects if the object being edited is NOT persistent - if (objectBeingEdited != null && !EditorUtility.IsPersistent(objectBeingEdited)) - { - allowSceneObjects = true; - } - } - DoObjectField(position, position, id, null, objType, property, null, allowSceneObjects, style); - } - - /// *listonly* - public static Object ObjectField(Rect position, Object obj, System.Type objType, bool allowSceneObjects) - { - int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position); - return DoObjectField(IndentedRect(position), IndentedRect(position), id, obj, objType, null, null, allowSceneObjects); - } - - [System.Obsolete("Check the docs for the usage of the new parameter 'allowSceneObjects'.")] - public static Object ObjectField(Rect position, Object obj, System.Type objType) - { - int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position); - return DoObjectField(position, position, id, obj, objType, null, null, true); - } - - /// *listonly* - public static Object ObjectField(Rect position, string label, Object obj, System.Type objType, bool allowSceneObjects) - { - return ObjectField(position, EditorGUIUtility.TempContent(label), obj, objType, allowSceneObjects); - } - - [System.Obsolete("Check the docs for the usage of the new parameter 'allowSceneObjects'.")] - public static Object ObjectField(Rect position, string label, Object obj, System.Type objType) - { - return ObjectField(position, EditorGUIUtility.TempContent(label), obj, objType, true); - } - - // Make an object field. You can assign objects either by drag and drop objects or by selecting an object using the Object Picker. - public static Object ObjectField(Rect position, GUIContent label, Object obj, System.Type objType, bool allowSceneObjects) - { - int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position); - position = PrefixLabel(position, id, label); - if (EditorGUIUtility.HasObjectThumbnail(objType) && position.height > EditorGUI.kSingleLineHeight) - { - // Make object field with thumbnail quadratic and align to the right - float size = Mathf.Min(position.width, position.height); - position.height = size; - position.xMin = position.xMax - size; - } - return DoObjectField(position, position, id, obj, objType, null, null, allowSceneObjects); - } - - internal static void GetRectsForMiniThumbnailField(Rect position, out Rect thumbRect, out Rect labelRect) - { - thumbRect = IndentedRect(position); - thumbRect.y -= (EditorGUI.kObjectFieldMiniThumbnailHeight - EditorGUI.kSingleLineHeight) * 0.5f; // center around EditorGUI.kSingleLineHeight - thumbRect.height = EditorGUI.kObjectFieldMiniThumbnailHeight; - thumbRect.width = EditorGUI.kObjectFieldMiniThumbnailWidth; - - float labelStartX = thumbRect.x + 2 * kIndentPerLevel; // label aligns with indent levels for being able to have the following labels align with this label - labelRect = new Rect(labelStartX, position.y, thumbRect.x + EditorGUIUtility.labelWidth - labelStartX, position.height); - } - - // Make a object field with the preview to the left and the label on the right thats fits on a single line height - internal static Object MiniThumbnailObjectField(Rect position, GUIContent label, Object obj, System.Type objType) - { - int id = GUIUtility.GetControlID(s_ObjectFieldHash, FocusType.Keyboard, position); - - Rect thumbRect, labelRect; - GetRectsForMiniThumbnailField(position, out thumbRect, out labelRect); - HandlePrefixLabel(position, labelRect, label, id, EditorStyles.label); - return DoObjectField(thumbRect, thumbRect, id, obj, objType, null, null, false); - } - - [System.Obsolete("Check the docs for the usage of the new parameter 'allowSceneObjects'.")] - public static Object ObjectField(Rect position, GUIContent label, Object obj, System.Type objType) - { - return ObjectField(position, label, obj, objType, true); - } - - internal static GameObject GetGameObjectFromObject(Object obj) - { - var go = obj as GameObject; - if (go == null && obj is Component) - go = ((Component)obj).gameObject; - return go; - } - - internal static bool CheckForCrossSceneReferencing(Object obj1, Object obj2) - { - // If either object is not a component nor gameobject: cannot become a cross scene reference - GameObject go = GetGameObjectFromObject(obj1); - if (go == null) - return false; - - GameObject go2 = GetGameObjectFromObject(obj2); - if (go2 == null) - return false; - - // If either object is a prefab: cannot become a cross scene reference - if (EditorUtility.IsPersistent(go) || EditorUtility.IsPersistent(go2)) - return false; - - // If either scene is invalid: cannot become a cross scene reference - if (!go.scene.IsValid() || !go2.scene.IsValid()) - return false; - - return go.scene != go2.scene; - } - - private static bool ValidateObjectReferenceValue(SerializedProperty property, Object obj, ObjectFieldValidatorOptions options) - { - if ((options & ObjectFieldValidatorOptions.ExactObjectTypeValidation) == ObjectFieldValidatorOptions.ExactObjectTypeValidation) - return property.ValidateObjectReferenceValueExact(obj); - - return property.ValidateObjectReferenceValue(obj); - } - - internal static Object ValidateObjectFieldAssignment(Object[] references, System.Type objType, SerializedProperty property, ObjectFieldValidatorOptions options) - { - if (references.Length > 0) - { - bool dragAssignment = DragAndDrop.objectReferences.Length > 0; - bool isTextureRef = (references[0] != null && references[0].GetType() == typeof(Texture2D)); - - if ((objType == typeof(Sprite)) && isTextureRef && dragAssignment) - { - return SpriteUtility.TextureToSprite(references[0] as Texture2D); - } - - if (property != null) - { - if (references[0] != null && ValidateObjectReferenceValue(property, references[0], options)) - { - if (EditorSceneManager.preventCrossSceneReferences && CheckForCrossSceneReferencing(references[0], property.serializedObject.targetObject)) - return null; - - if (objType != null) - { - if (references[0].GetType() == typeof(GameObject) && typeof(Component).IsAssignableFrom(objType)) - { - GameObject go = (GameObject)references[0]; - references = go.GetComponents(typeof(Component)); - } - foreach (Object i in references) - { - if (i != null && objType.IsAssignableFrom(i.GetType())) - { - return i; - } - } - } - else - { - return references[0]; - } - } - - // If array, test against the target arrayElementType, if not test against the target Type. - string testElementType = property.type; - if (property.type == "vector") - testElementType = property.arrayElementType; - - if ((testElementType == "PPtr" || testElementType == "PPtr<$Sprite>") && isTextureRef && dragAssignment) - { - return SpriteUtility.TextureToSprite(references[0] as Texture2D); - } - } - else - { - if (references[0] != null && references[0].GetType() == typeof(GameObject) && typeof(Component).IsAssignableFrom(objType)) - { - GameObject go = (GameObject)references[0]; - references = go.GetComponents(typeof(Component)); - } - foreach (Object i in references) - { - if (i != null && objType.IsAssignableFrom(i.GetType())) - { - return i; - } - } - } - } - return null; - } - - private static Object HandleTextureToSprite(Texture2D tex) - { - Object[] assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(tex)); - - for (int i = 0; i < assets.Length; i++) - { - if (assets[i].GetType() == typeof(Sprite)) - { - return assets[i]; - } - } - - return tex; - } - - // Apply the indentLevel to a control rect - public static Rect IndentedRect(Rect source) - { - float x = indent; - return new Rect(source.x + x, source.y, source.width - x, source.height); - } - - // Make an X & Y field for entering a [[Vector2]]. - public static Vector2 Vector2Field(Rect position, string label, Vector2 value) - { - return Vector2Field(position, EditorGUIUtility.TempContent(label), value); - } - - // Make an X & Y field for entering a [[Vector2]]. - public static Vector2 Vector2Field(Rect position, GUIContent label, Vector2 value) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 2); - position.height = kSingleLineHeight; - return Vector2Field(position, value); - } - - // Make an X & Y field for entering a [[Vector2]]. - private static Vector2 Vector2Field(Rect position, Vector2 value) - { - s_Vector2Floats[0] = value.x; - s_Vector2Floats[1] = value.y; - position.height = kSingleLineHeight; - BeginChangeCheck(); - MultiFloatField(position, s_XYLabels, s_Vector2Floats); - if (EndChangeCheck()) - { - value.x = s_Vector2Floats[0]; - value.y = s_Vector2Floats[1]; - } - return value; - } - - // Make an X, Y & Z field for entering a [[Vector3]]. - public static Vector3 Vector3Field(Rect position, string label, Vector3 value) - { - return Vector3Field(position, EditorGUIUtility.TempContent(label), value); - } - - // Make an X, Y & Z field for entering a [[Vector3]]. - public static Vector3 Vector3Field(Rect position, GUIContent label, Vector3 value) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 3); - position.height = kSingleLineHeight; - return Vector3Field(position, value); - } - - // Make an X, Y & Z field for entering a [[Vector3]]. - private static Vector3 Vector3Field(Rect position, Vector3 value) - { - s_Vector3Floats[0] = value.x; - s_Vector3Floats[1] = value.y; - s_Vector3Floats[2] = value.z; - position.height = kSingleLineHeight; - BeginChangeCheck(); - MultiFloatField(position, s_XYZLabels, s_Vector3Floats); - if (EndChangeCheck()) - { - value.x = s_Vector3Floats[0]; - value.y = s_Vector3Floats[1]; - value.z = s_Vector3Floats[2]; - } - return value; - } - - // Make an X, Y field - not public (use PropertyField instead) - private static void Vector2Field(Rect position, SerializedProperty property, GUIContent label) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 2); - position.height = kSingleLineHeight; - SerializedProperty cur = property.Copy(); - cur.Next(true); - MultiPropertyField(position, s_XYLabels, cur, PropertyVisibility.All); - } - - // Make an X, Y and Z field - not public (use PropertyField instead) - private static void Vector3Field(Rect position, SerializedProperty property, GUIContent label) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 3); - position.height = kSingleLineHeight; - SerializedProperty cur = property.Copy(); - cur.Next(true); - MultiPropertyField(position, s_XYZLabels, cur, PropertyVisibility.All); - } - - // Make an X, Y, Z and W field - not public (use PropertyField instead) - static void Vector4Field(Rect position, SerializedProperty property, GUIContent label) - { - int id = EditorGUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 4); - position.height = kSingleLineHeight; - SerializedProperty cur = property.Copy(); - cur.Next(true); - MultiPropertyField(position, s_XYZWLabels, cur, PropertyVisibility.All); - } - - // Make an X, Y, Z & W field for entering a [[Vector4]]. - public static Vector4 Vector4Field(Rect position, string label, Vector4 value) - { - return Vector4Field(position, EditorGUIUtility.TempContent(label), value); - } - - // Make an X, Y, Z & W field for entering a [[Vector4]]. - public static Vector4 Vector4Field(Rect position, GUIContent label, Vector4 value) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 4); - position.height = kSingleLineHeight; - return Vector4FieldNoIndent(position, value); - } - - private static Vector4 Vector4FieldNoIndent(Rect position, Vector4 value) - { - s_Vector4Floats[0] = value.x; - s_Vector4Floats[1] = value.y; - s_Vector4Floats[2] = value.z; - s_Vector4Floats[3] = value.w; - position.height = kSingleLineHeight; - BeginChangeCheck(); - MultiFloatField(position, s_XYZWLabels, s_Vector4Floats); - if (EndChangeCheck()) - { - value.x = s_Vector4Floats[0]; - value.y = s_Vector4Floats[1]; - value.z = s_Vector4Floats[2]; - value.w = s_Vector4Floats[3]; - } - return value; - } - - // Make an X & Y int field for entering a [[Vector2Int]]. - public static Vector2Int Vector2IntField(Rect position, string label, Vector2Int value) - { - return Vector2IntField(position, EditorGUIUtility.TempContent(label), value); - } - - // Make an X & Y int field for entering a [[Vector2Int]]. - public static Vector2Int Vector2IntField(Rect position, GUIContent label, Vector2Int value) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 2); - position.height = kSingleLineHeight; - return Vector2IntField(position, value); - } - - // Make an X & Y int field for entering a [[Vector2Int]]. - private static Vector2Int Vector2IntField(Rect position, Vector2Int value) - { - s_Vector2Ints[0] = value.x; - s_Vector2Ints[1] = value.y; - position.height = kSingleLineHeight; - BeginChangeCheck(); - MultiIntField(position, s_XYLabels, s_Vector2Ints); - if (EndChangeCheck()) - { - value.x = s_Vector2Ints[0]; - value.y = s_Vector2Ints[1]; - } - return value; - } - - // Make an X, Y int field - not public (use PropertyField instead) - private static void Vector2IntField(Rect position, SerializedProperty property, GUIContent label) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 2); - position.height = kSingleLineHeight; - SerializedProperty cur = property.Copy(); - cur.Next(true); - MultiPropertyField(position, s_XYLabels, cur, PropertyVisibility.All); - } - - // Make an X, Y and Z int field for entering a [[Vector3Int]]. - public static Vector3Int Vector3IntField(Rect position, string label, Vector3Int value) - { - return Vector3IntField(position, EditorGUIUtility.TempContent(label), value); - } - - // Make an X, Y and Z int field for entering a [[Vector3Int]]. - public static Vector3Int Vector3IntField(Rect position, GUIContent label, Vector3Int value) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 3); - position.height = kSingleLineHeight; - return Vector3IntField(position, value); - } - - // Make an X, Y and Z int field for entering a [[Vector3Int]]. - private static Vector3Int Vector3IntField(Rect position, Vector3Int value) - { - s_Vector3Ints[0] = value.x; - s_Vector3Ints[1] = value.y; - s_Vector3Ints[2] = value.z; - position.height = kSingleLineHeight; - BeginChangeCheck(); - MultiIntField(position, s_XYZLabels, s_Vector3Ints); - if (EndChangeCheck()) - { - value.x = s_Vector3Ints[0]; - value.y = s_Vector3Ints[1]; - value.z = s_Vector3Ints[2]; - } - return value; - } - - // Make an X, Y and Z int field - not public (use PropertyField instead) - private static void Vector3IntField(Rect position, SerializedProperty property, GUIContent label) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 3); - position.height = kSingleLineHeight; - SerializedProperty cur = property.Copy(); - cur.Next(true); - MultiPropertyField(position, s_XYZLabels, cur, PropertyVisibility.All); - } - - /// *listonly* - public static Rect RectField(Rect position, Rect value) - { - return RectFieldNoIndent(IndentedRect(position), value); - } - - private static Rect RectFieldNoIndent(Rect position, Rect value) - { - position.height = kSingleLineHeight; - s_Vector2Floats[0] = value.x; - s_Vector2Floats[1] = value.y; - BeginChangeCheck(); - MultiFloatField(position, s_XYLabels, s_Vector2Floats); - if (EndChangeCheck()) - { - value.x = s_Vector2Floats[0]; - value.y = s_Vector2Floats[1]; - } - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - s_Vector2Floats[0] = value.width; - s_Vector2Floats[1] = value.height; - BeginChangeCheck(); - MultiFloatField(position, s_WHLabels, s_Vector2Floats); - if (EndChangeCheck()) - { - value.width = s_Vector2Floats[0]; - value.height = s_Vector2Floats[1]; - } - return value; - } - - /// *listonly* - public static Rect RectField(Rect position, string label, Rect value) - { - return RectField(position, EditorGUIUtility.TempContent(label), value); - } - - // Make an X, Y, W & H field for entering a [[Rect]]. - public static Rect RectField(Rect position, GUIContent label, Rect value) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 2); - return RectFieldNoIndent(position, value); - } - - // Make an X, Y, W & H for Rect using SerializedProperty (not public) - private static void RectField(Rect position, SerializedProperty property, GUIContent label) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 2); - position.height = kSingleLineHeight; - - SerializedProperty cur = property.Copy(); - cur.Next(true); - MultiPropertyField(position, s_XYLabels, cur, PropertyVisibility.All); - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - - MultiPropertyField(position, s_WHLabels, cur, PropertyVisibility.All); - } - - /// *listonly* - public static RectInt RectIntField(Rect position, RectInt value) - { - position.height = kSingleLineHeight; - s_Vector2Ints[0] = value.x; - s_Vector2Ints[1] = value.y; - BeginChangeCheck(); - MultiIntField(position, s_XYLabels, s_Vector2Ints); - if (EndChangeCheck()) - { - value.x = s_Vector2Ints[0]; - value.y = s_Vector2Ints[1]; - } - position.y += kSingleLineHeight; - s_Vector2Ints[0] = value.width; - s_Vector2Ints[1] = value.height; - BeginChangeCheck(); - MultiIntField(position, s_WHLabels, s_Vector2Ints); - if (EndChangeCheck()) - { - value.width = s_Vector2Ints[0]; - value.height = s_Vector2Ints[1]; - } - return value; - } - - /// *listonly* - public static RectInt RectIntField(Rect position, string label, RectInt value) - { - return RectIntField(position, EditorGUIUtility.TempContent(label), value); - } - - // Make an X, Y, W & H field for entering a [[Rect]]. - public static RectInt RectIntField(Rect position, GUIContent label, RectInt value) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 2); - position.height = kSingleLineHeight; - return RectIntField(position, value); - } - - // Make an X, Y, W & H for RectInt using SerializedProperty (not public) - private static void RectIntField(Rect position, SerializedProperty property, GUIContent label) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 2); - position.height = kSingleLineHeight; - - SerializedProperty cur = property.Copy(); - cur.Next(true); - MultiPropertyField(position, s_XYLabels, cur, PropertyVisibility.All); - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - - MultiPropertyField(position, s_WHLabels, cur, PropertyVisibility.All); - } - - private static Rect DrawBoundsFieldLabelsAndAdjustPositionForValues(Rect position, bool drawOutside, GUIContent firstContent, GUIContent secondContent) - { - const float kBoundsTextWidth = 53; - - if (drawOutside) - position.xMin -= kBoundsTextWidth; - - GUI.Label(position, firstContent, EditorStyles.label); - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - GUI.Label(position, secondContent, EditorStyles.label); - - position.y -= kSingleLineHeight + kVerticalSpacingMultiField; - position.xMin += kBoundsTextWidth; - - return position; - } - - /// *listonly* - public static Bounds BoundsField(Rect position, Bounds value) - { - return BoundsFieldNoIndent(IndentedRect(position), value, false); - } - - public static Bounds BoundsField(Rect position, string label, Bounds value) - { - return BoundsField(position, EditorGUIUtility.TempContent(label), value); - } - - // Make Center & Extents field for entering a [[Bounds]]. - public static Bounds BoundsField(Rect position, GUIContent label, Bounds value) - { - if (!LabelHasContent(label)) - return BoundsFieldNoIndent(IndentedRect(position), value, false); - - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 3); - if (EditorGUIUtility.wideMode) - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - - return BoundsFieldNoIndent(position, value, true); - } - - private static Bounds BoundsFieldNoIndent(Rect position, Bounds value, bool isBelowLabel) - { - position.height = kSingleLineHeight; - position = DrawBoundsFieldLabelsAndAdjustPositionForValues(position, EditorGUIUtility.wideMode && isBelowLabel, s_CenterLabel, s_ExtentLabel); - - value.center = Vector3Field(position, value.center); - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - value.extents = Vector3Field(position, value.extents); - return value; - } - - // private (use PropertyField) - private static void BoundsField(Rect position, SerializedProperty property, GUIContent label) - { - bool hasLabel = LabelHasContent(label); - if (hasLabel) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 3); - if (EditorGUIUtility.wideMode) - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - } - position.height = kSingleLineHeight; - position = DrawBoundsFieldLabelsAndAdjustPositionForValues(position, EditorGUIUtility.wideMode && hasLabel, s_CenterLabel, s_ExtentLabel); - - SerializedProperty cur = property.Copy(); - cur.Next(true); - cur.Next(true); - MultiPropertyField(position, s_XYZLabels, cur, PropertyVisibility.All); - cur.Next(true); - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - MultiPropertyField(position, s_XYZLabels, cur, PropertyVisibility.All); - } - - /// *listonly* - public static BoundsInt BoundsIntField(Rect position, BoundsInt value) - { - return BoundsIntFieldNoIndent(IndentedRect(position), value, false); - } - - public static BoundsInt BoundsIntField(Rect position, string label, BoundsInt value) - { - return BoundsIntField(position, EditorGUIUtility.TempContent(label), value); - } - - public static BoundsInt BoundsIntField(Rect position, GUIContent label, BoundsInt value) - { - if (!LabelHasContent(label)) - return BoundsIntFieldNoIndent(IndentedRect(position), value, false); - - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 3); - if (EditorGUIUtility.wideMode) - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - - return BoundsIntFieldNoIndent(position, value, true); - } - - private static BoundsInt BoundsIntFieldNoIndent(Rect position, BoundsInt value, bool isBelowLabel) - { - position.height = kSingleLineHeight; - position = DrawBoundsFieldLabelsAndAdjustPositionForValues(position, EditorGUIUtility.wideMode && isBelowLabel, s_PositionLabel, s_SizeLabel); - - value.position = Vector3IntField(position, value.position); - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - value.size = Vector3IntField(position, value.size); - return value; - } - - // private (use PropertyField) - private static void BoundsIntField(Rect position, SerializedProperty property, GUIContent label) - { - bool hasLabel = LabelHasContent(label); - if (hasLabel) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, 3); - if (EditorGUIUtility.wideMode) - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - } - position.height = kSingleLineHeight; - position = DrawBoundsFieldLabelsAndAdjustPositionForValues(position, EditorGUIUtility.wideMode && hasLabel, s_PositionLabel, s_SizeLabel); - - SerializedProperty cur = property.Copy(); - cur.Next(true); - cur.Next(true); - MultiPropertyField(position, s_XYZLabels, cur, PropertyVisibility.All); - cur.Next(true); - position.y += kSingleLineHeight + kVerticalSpacingMultiField; - MultiPropertyField(position, s_XYZLabels, cur, PropertyVisibility.All); - } - - public static void MultiFloatField(Rect position, GUIContent label, GUIContent[] subLabels, float[] values) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, subLabels.Length); - position.height = kSingleLineHeight; - MultiFloatField(position, subLabels, values); - } - - public static void MultiFloatField(Rect position, GUIContent[] subLabels, float[] values) - { - MultiFloatField(position, subLabels, values, kMiniLabelW); - } - - internal static void MultiFloatField(Rect position, GUIContent[] subLabels, float[] values, float labelWidth) - { - int eCount = values.Length; - float w = (position.width - (eCount - 1) * kSpacingSubLabel) / eCount; - Rect nr = new Rect(position); - nr.width = w; - float t = EditorGUIUtility.labelWidth; - int l = EditorGUI.indentLevel; - EditorGUIUtility.labelWidth = labelWidth; - EditorGUI.indentLevel = 0; - for (int i = 0; i < values.Length; i++) - { - values[i] = EditorGUI.FloatField(nr, subLabels[i], values[i]); - nr.x += w + kSpacingSubLabel; - } - EditorGUIUtility.labelWidth = t; - EditorGUI.indentLevel = l; - } - - public static void MultiIntField(Rect position, GUIContent[] subLabels, int[] values) - { - MultiIntField(position, subLabels, values, kMiniLabelW); - } - - internal static void MultiIntField(Rect position, GUIContent[] subLabels, int[] values, float labelWidth) - { - int eCount = values.Length; - float w = (position.width - (eCount - 1) * kSpacingSubLabel) / eCount; - Rect nr = new Rect(position); - nr.width = w; - float t = EditorGUIUtility.labelWidth; - int l = EditorGUI.indentLevel; - EditorGUIUtility.labelWidth = labelWidth; - EditorGUI.indentLevel = 0; - for (int i = 0; i < values.Length; i++) - { - values[i] = EditorGUI.IntField(nr, subLabels[i], values[i]); - nr.x += w + kSpacingSubLabel; - } - EditorGUIUtility.labelWidth = t; - EditorGUI.indentLevel = l; - } - - public static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, GUIContent label) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = MultiFieldPrefixLabel(position, id, label, subLabels.Length); - position.height = kSingleLineHeight; - MultiPropertyField(position, subLabels, valuesIterator); - } - - public static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator) - { - MultiPropertyField(position, subLabels, valuesIterator, PropertyVisibility.OnlyVisible); - } - - internal enum PropertyVisibility - { - All, - OnlyVisible - } - - private static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, PropertyVisibility visibility) - { - MultiPropertyField(position, subLabels, valuesIterator, visibility, kMiniLabelW, null); - } - - internal static void MultiPropertyField(Rect position, GUIContent[] subLabels, SerializedProperty valuesIterator, PropertyVisibility visibility, float labelWidth, bool[] disabledMask) - { - int eCount = subLabels.Length; - float w = (position.width - (eCount - 1) * kSpacingSubLabel) / eCount; - Rect nr = new Rect(position); - nr.width = w; - float t = EditorGUIUtility.labelWidth; - int l = EditorGUI.indentLevel; - EditorGUIUtility.labelWidth = labelWidth; - EditorGUI.indentLevel = 0; - for (int i = 0; i < subLabels.Length; i++) - { - if (disabledMask != null) - BeginDisabled(disabledMask[i]); - EditorGUI.PropertyField(nr, valuesIterator, subLabels[i]); - if (disabledMask != null) - EndDisabled(); - nr.x += w + kSpacingSubLabel; - - switch (visibility) - { - case PropertyVisibility.All: - valuesIterator.Next(false); - break; - - case PropertyVisibility.OnlyVisible: - valuesIterator.NextVisible(false); - break; - } - } - EditorGUIUtility.labelWidth = t; - EditorGUI.indentLevel = l; - } - - // Make a property field that look like a multi property field (but is made up of individual properties) - internal static void PropertiesField(Rect position, GUIContent label, SerializedProperty[] properties, GUIContent[] propertyLabels, float propertyLabelsWidth) - { - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - Rect fieldPosition = PrefixLabel(position, id, label); - fieldPosition.height = kSingleLineHeight; - - float oldLabelWidth = EditorGUIUtility.labelWidth; - int oldIndentLevel = EditorGUI.indentLevel; - - EditorGUIUtility.labelWidth = propertyLabelsWidth; - EditorGUI.indentLevel = 0; - for (int i = 0; i < properties.Length; i++) - { - PropertyField(fieldPosition, properties[i], propertyLabels[i]); - fieldPosition.y += kSingleLineHeight + kVerticalSpacingMultiField; - } - - EditorGUI.indentLevel = oldIndentLevel; - EditorGUIUtility.labelWidth = oldLabelWidth; - } - - internal static int CycleButton(Rect position, int selected, GUIContent[] options, GUIStyle style) - { - if (selected >= options.Length || selected < 0) - { - selected = 0; - GUI.changed = true; - } - if (GUI.Button(position, options[selected], style)) - { - selected++; - GUI.changed = true; - if (selected >= options.Length) - { - selected = 0; - } - } - return selected; - } - - /// *listonly* - public static Color ColorField(Rect position, Color value) - { - int id = GUIUtility.GetControlID(s_ColorHash, FocusType.Keyboard, position); - return DoColorField(IndentedRect(position), id, value, true, true, false); - } - - /// *listonly* - internal static Color ColorField(Rect position, Color value, bool showEyedropper, bool showAlpha) - { - int id = GUIUtility.GetControlID(s_ColorHash, FocusType.Keyboard, position); - return DoColorField(position, id, value, showEyedropper, showAlpha, false); - } - - /// *listonly* - public static Color ColorField(Rect position, string label, Color value) - { - return ColorField(position, EditorGUIUtility.TempContent(label), value); - } - - // Make a field for selecting a [[Color]]. - public static Color ColorField(Rect position, GUIContent label, Color value) - { - int id = GUIUtility.GetControlID(s_ColorHash, FocusType.Keyboard, position); - return DoColorField(PrefixLabel(position, id, label), id, value, true, true, false); - } - - /// *listonly* - internal static Color ColorField(Rect position, GUIContent label, Color value, bool showEyedropper, bool showAlpha) - { - int id = GUIUtility.GetControlID(s_ColorHash, FocusType.Keyboard, position); - return DoColorField(PrefixLabel(position, id, label), id, value, showEyedropper, showAlpha, false); - } - - #pragma warning disable 612 - [Obsolete("Use EditorGUI.ColorField(Rect position, GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr)")] - public static Color ColorField(Rect position, GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, ColorPickerHDRConfig hdrConfig) - { - return ColorField(position, label, value, showEyedropper, showAlpha, hdr); - } - - #pragma warning restore 612 - - public static Color ColorField(Rect position, GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr) - { - int id = GUIUtility.GetControlID(s_ColorHash, FocusType.Keyboard, position); - return DoColorField(PrefixLabel(position, id, label), id, value, showEyedropper, showAlpha, hdr); - } - - private static Color DoColorField(Rect position, int id, Color value, bool showEyedropper, bool showAlpha, bool hdr) - { - Event evt = Event.current; - GUIStyle style = EditorStyles.colorField; - Color origColor = value; - value = showMixedValue ? Color.white : value; - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (showEyedropper) - { - position.width -= 20; - } - - if (position.Contains(evt.mousePosition)) - { - switch (evt.button) - { - case 0: - // Left click: Show the ColorPicker - GUIUtility.keyboardControl = id; - showMixedValue = false; - ColorPicker.Show(GUIView.current, value, showAlpha, hdr); - GUIUtility.ExitGUI(); - break; - - case 1: - // Right click: Show color context menu - // See ExecuteCommand section below to see handling for copy & paste - GUIUtility.keyboardControl = id; - - var names = new[] {"Copy", "Paste"}; - var enabled = new[] {true, ColorClipboard.HasColor()}; - - EditorUtility.DisplayCustomMenu( - position, - names, - enabled, - null, - delegate(object data, string[] options, int selected) - { - if (selected == 0) - { - Event e = EditorGUIUtility.CommandEvent(EventCommandNames.Copy); - GUIView.current.SendEvent(e); - } - else if (selected == 1) - { - Event e = EditorGUIUtility.CommandEvent(EventCommandNames.Paste); - GUIView.current.SendEvent(e); - } - }, - null); - return origColor; - } - } - - if (showEyedropper) - { - position.width += 20; - if (position.Contains(evt.mousePosition)) - { - GUIUtility.keyboardControl = id; - EyeDropper.Start(GUIView.current); - s_ColorPickID = id; - GUIUtility.ExitGUI(); - } - } - break; - case EventType.Repaint: - Rect position2; - if (showEyedropper) - { - position2 = style.padding.Remove(position); - } - else - { - position2 = position; - } - - // Draw color field - if (showEyedropper && s_ColorPickID == id) - { - Color c = EyeDropper.GetPickedColor(); - c.a = value.a; - if (hdr) - c = c.linear; - EditorGUIUtility.DrawColorSwatch(position2, c, showAlpha, hdr); - } - else - { - EditorGUIUtility.DrawColorSwatch(position2, value, showAlpha, hdr); - } - - if (showEyedropper) - { - style.Draw(position, GUIContent.none, id); // Draw box outline and eyedropper icon - } - else - { - EditorStyles.colorPickerBox.Draw(position, GUIContent.none, id); // Draw box outline - } - - break; - - case EventType.ValidateCommand: - - switch (evt.commandName) - { - case EventCommandNames.UndoRedoPerformed: - // Set color in ColorPicker in case an undo/redo has been made - // when ColorPicker sends an event back to this control's GUIView, it someties retains keyboardControl - if ((GUIUtility.keyboardControl == id || ColorPicker.originalKeyboardControl == id) && ColorPicker.visible) - ColorPicker.color = value; - break; - - case EventCommandNames.Copy: - case EventCommandNames.Paste: - evt.Use(); - break; - } - break; - - case EventType.ExecuteCommand: - // when ColorPicker sends an event back to this control's GUIView, it someties retains keyboardControl - if (GUIUtility.keyboardControl == id || ColorPicker.originalKeyboardControl == id) - { - switch (evt.commandName) - { - case EventCommandNames.EyeDropperUpdate: - HandleUtility.Repaint(); - break; - case EventCommandNames.EyeDropperClicked: - GUI.changed = true; - HandleUtility.Repaint(); - Color c = EyeDropper.GetLastPickedColor(); - c.a = value.a; - s_ColorPickID = 0; - return hdr ? c.linear : c; - case EventCommandNames.EyeDropperCancelled: - HandleUtility.Repaint(); - s_ColorPickID = 0; - break; - case EventCommandNames.ColorPickerChanged: - GUI.changed = true; - HandleUtility.Repaint(); - return ColorPicker.color; - case EventCommandNames.Copy: - ColorClipboard.SetColor(value); - evt.Use(); - break; - - case EventCommandNames.Paste: - Color colorFromClipboard; - if (ColorClipboard.TryGetColor(hdr, out colorFromClipboard)) - { - // Do not change alpha if color field is not showing alpha - if (!showAlpha) - colorFromClipboard.a = origColor.a; - - origColor = colorFromClipboard; - - GUI.changed = true; - evt.Use(); - } - break; - } - } - break; - case EventType.KeyDown: - if (evt.MainActionKeyForControl(id)) - { - Event.current.Use(); - showMixedValue = false; - ColorPicker.Show(GUIView.current, value, showAlpha, hdr); - GUIUtility.ExitGUI(); - } - break; - } - return origColor; - } - - /// *listonly* - public static AnimationCurve CurveField(Rect position, AnimationCurve value) - { - int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position); - return DoCurveField(IndentedRect(position), id, value, kCurveColor, new Rect(), null); - } - - /// *listonly* - public static AnimationCurve CurveField(Rect position, string label, AnimationCurve value) - { - return CurveField(position, EditorGUIUtility.TempContent(label), value); - } - - /// *listonly* - public static AnimationCurve CurveField(Rect position, GUIContent label, AnimationCurve value) - { - int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position); - return DoCurveField(PrefixLabel(position, id, label), id, value, kCurveColor, new Rect(), null); - } - - // Variants with settings - /// *listonly* - public static AnimationCurve CurveField(Rect position, AnimationCurve value, Color color, Rect ranges) - { - int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position); - return DoCurveField(IndentedRect(position), id, value, color, ranges, null); - } - - /// *listonly* - public static AnimationCurve CurveField(Rect position, string label, AnimationCurve value, Color color, Rect ranges) - { - return CurveField(position, EditorGUIUtility.TempContent(label), value, color, ranges); - } - - // Make a field for editing an [[AnimationCurve]]. - public static AnimationCurve CurveField(Rect position, GUIContent label, AnimationCurve value, Color color, Rect ranges) - { - int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position); - return DoCurveField(PrefixLabel(position, id, label), id, value, color, ranges, null); - } - - /// *listonly* - public static void CurveField(Rect position, SerializedProperty property, Color color, Rect ranges) - { - CurveField(position, property, color, ranges, null); - } - - // Make a field for editing an [[AnimationCurve]]. - public static void CurveField(Rect position, SerializedProperty property, Color color, Rect ranges, GUIContent label) - { - label = BeginProperty(position, label, property); - - int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position); - DoCurveField(PrefixLabel(position, id, label), id, null, color, ranges, property); - - EndProperty(); - } - - private static void SetCurveEditorWindowCurve(AnimationCurve value, SerializedProperty property, Color color) - { - if (property != null) - { - CurveEditorWindow.curve = property.hasMultipleDifferentValues ? new AnimationCurve() : property.animationCurveValue; - } - else - { - CurveEditorWindow.curve = value; - } - CurveEditorWindow.color = color; - } - - internal static AnimationCurve DoCurveField(Rect position, int id, AnimationCurve value, Color color, Rect ranges, SerializedProperty property) - { - Event evt = Event.current; - - // Avoid crash problems caused by textures with zero or negative sizes! - position.width = Mathf.Max(position.width, 2); - position.height = Mathf.Max(position.height, 2); - - if (GUIUtility.keyboardControl == id && Event.current.type != EventType.Layout) - { - if (s_CurveID != id) - { - s_CurveID = id; - if (CurveEditorWindow.visible) - { - SetCurveEditorWindowCurve(value, property, color); - ShowCurvePopup(GUIView.current, ranges); - } - } - else - { - if (CurveEditorWindow.visible && Event.current.type == EventType.Repaint) - { - SetCurveEditorWindowCurve(value, property, color); - CurveEditorWindow.instance.Repaint(); - } - } - } - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (position.Contains(evt.mousePosition)) - { - s_CurveID = id; - GUIUtility.keyboardControl = id; - SetCurveEditorWindowCurve(value, property, color); - ShowCurvePopup(GUIView.current, ranges); - evt.Use(); - GUIUtility.ExitGUI(); - } - break; - case EventType.Repaint: - Rect position2 = position; - position2.y += 1; - position2.height -= 1; - if (ranges != new Rect()) - { - EditorGUIUtility.DrawCurveSwatch(position2, value, property, color, kCurveBGColor, ranges); - } - else - { - EditorGUIUtility.DrawCurveSwatch(position2, value, property, color, kCurveBGColor); - } - EditorStyles.colorPickerBox.Draw(position2, GUIContent.none, id, false); - break; - case EventType.ExecuteCommand: - if (s_CurveID == id) - { - switch (evt.commandName) - { - case CurveEditorWindow.CurveChangedCommand: - GUI.changed = true; - AnimationCurvePreviewCache.ClearCache(); - HandleUtility.Repaint(); - if (property != null) - { - property.animationCurveValue = CurveEditorWindow.curve; - if (property.hasMultipleDifferentValues) - { - Debug.LogError("AnimationCurve SerializedProperty hasMultipleDifferentValues is true after writing."); - } - } - return CurveEditorWindow.curve; - } - } - break; - case EventType.KeyDown: - if (evt.MainActionKeyForControl(id)) - { - s_CurveID = id; - SetCurveEditorWindowCurve(value, property, color); - ShowCurvePopup(GUIView.current, ranges); - evt.Use(); - GUIUtility.ExitGUI(); - } - - break; - } - return value; - } - - private static void ShowCurvePopup(GUIView viewToUpdate, Rect ranges) - { - CurveEditorSettings settings = new CurveEditorSettings(); - if (ranges.width > 0 && ranges.height > 0 && ranges.width != Mathf.Infinity && ranges.height != Mathf.Infinity) - { - settings.hRangeMin = ranges.xMin; - settings.hRangeMax = ranges.xMax; - settings.vRangeMin = ranges.yMin; - settings.vRangeMax = ranges.yMax; - } - CurveEditorWindow.instance.Show(GUIView.current, settings); - } - - private static bool ValidTargetForIconSelection(Object[] targets) - { - // @TODO: Handle icon dropdown for multiple objects. - return ((targets[0] as MonoScript) || (targets[0] as GameObject)) && targets.Length == 1; - } - - internal static void ObjectIconDropDown(Rect position, Object[] targets, bool showLabelIcons, Texture2D nullIcon, SerializedProperty iconProperty) - { - if (s_IconTextureInactive == null) - { - s_IconTextureInactive = (Material)EditorGUIUtility.LoadRequired("Inspectors/InactiveGUI.mat"); - } - if (Event.current.type == EventType.Repaint) - { - Texture2D icon = null; - if (!iconProperty.hasMultipleDifferentValues) - { - icon = AssetPreview.GetMiniThumbnail(targets[0]); - } - if (icon == null) - { - icon = nullIcon; - } - Vector2 iconSize = new Vector2(position.width, position.height); - if (icon) - { - iconSize.x = Mathf.Min(icon.width, iconSize.x); - iconSize.y = Mathf.Min(icon.height, iconSize.y); - } - Rect iconRect = new Rect(position.x + position.width / 2 - iconSize.x / 2, position.y + position.height / 2 - iconSize.y / 2 , iconSize.x, iconSize.y); - GameObject obj = targets[0] as GameObject; - - bool isInactive = obj && (!EditorUtility.IsPersistent(targets[0]) && (!obj.activeSelf || !obj.activeInHierarchy)); - - if (isInactive) - { - var imageAspect = (float)icon.width / (float)icon.height; - Rect iconScreenRect = new Rect(); - Rect sourceRect = new Rect(); - GUI.CalculateScaledTextureRects(iconRect, ScaleMode.ScaleToFit, imageAspect, ref iconScreenRect, ref sourceRect); - Graphics.DrawTexture(iconScreenRect, icon, sourceRect, 0, 0, 0, 0, new Color(.5f, .5f, .5f, 1f), s_IconTextureInactive); - } - else - { - GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit); - } - - if (ValidTargetForIconSelection(targets)) - { - if (s_IconDropDown == null) - { - s_IconDropDown = EditorGUIUtility.IconContent("Icon Dropdown"); - } - GUIStyle.none.Draw(new Rect(Mathf.Max(position.x + 2, iconRect.x - 6), iconRect.yMax - iconRect.height * 0.2f, 13, 8), s_IconDropDown, false, false, false, false); - } - } - - if (EditorGUI.DropdownButton(position, GUIContent.none, FocusType.Passive, GUIStyle.none)) - { - if (ValidTargetForIconSelection(targets)) - { - if (IconSelector.ShowAtPosition(targets[0], position, showLabelIcons)) - { - GUIUtility.ExitGUI(); - } - } - } - } - - // Titlebar without foldout - public static void InspectorTitlebar(Rect position, Object[] targetObjs) - { - GUIStyle baseStyle = GUIStyle.none; - int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position); - DoInspectorTitlebar(position, id, true, targetObjs, baseStyle); - } - - /// *listonly* - public static bool InspectorTitlebar(Rect position, bool foldout, Object targetObj, bool expandable) - { - return InspectorTitlebar(position, foldout, new Object[] {targetObj}, expandable); - } - - // foldable titlebar. - public static bool InspectorTitlebar(Rect position, bool foldout, Object[] targetObjs, bool expandable) - { - GUIStyle baseStyle = EditorStyles.inspectorTitlebar; - - // Important to get controlId for the foldout first, so it gets keyboard focus before the toggle does. - int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position); - DoInspectorTitlebar(position, id, foldout, targetObjs, baseStyle); - foldout = DoObjectMouseInteraction(foldout, position, targetObjs, id); - - if (expandable) - { - Rect renderRect = GetInspectorTitleBarObjectFoldoutRenderRect(position); - DoObjectFoldoutInternal(foldout, position, renderRect, targetObjs, id); - } - - return foldout; - } - - // Make an inspector-window-like titlebar. - internal static void DoInspectorTitlebar(Rect position, int id, bool foldout, Object[] targetObjs, GUIStyle baseStyle) - { - GUIStyle textStyle = EditorStyles.inspectorTitlebarText; - GUIStyle iconButtonStyle = EditorStyles.iconButton; - - Vector2 settingsElementSize = iconButtonStyle.CalcSize(GUIContents.titleSettingsIcon); - - Rect iconRect = new Rect(position.x + baseStyle.padding.left, position.y + baseStyle.padding.top, kInspTitlebarIconWidth, kInspTitlebarIconWidth); - Rect settingsRect = new Rect(position.xMax - baseStyle.padding.right - kInspTitlebarSpacing - kInspTitlebarIconWidth, iconRect.y, settingsElementSize.x, settingsElementSize.y); - Rect textRect = new Rect(iconRect.xMax + kInspTitlebarSpacing + kInspTitlebarSpacing + kInspTitlebarIconWidth, iconRect.y, 100, iconRect.height); - textRect.xMax = settingsRect.xMin - kInspTitlebarSpacing; - - Event evt = Event.current; - - int enabled = -1; - foreach (Object targetObj in targetObjs) - { - int thisEnabled = EditorUtility.GetObjectEnabled(targetObj); - if (enabled == -1) - { - enabled = thisEnabled; - } - else if (enabled != thisEnabled) - { - enabled = -2; - } - } - - if (enabled != -1) - { - bool enabledState = enabled != 0; - EditorGUI.showMixedValue = enabled == -2; - Rect toggleRect = iconRect; - toggleRect.x = iconRect.xMax + kInspTitlebarSpacing; - BeginChangeCheck(); - - Color previousColor = GUI.backgroundColor; - bool animated = AnimationMode.IsPropertyAnimated(targetObjs[0], kEnabledPropertyName); - if (animated) - { - Color animatedColor = AnimationMode.animatedPropertyColor; - if (AnimationMode.InAnimationRecording()) - animatedColor = AnimationMode.recordedPropertyColor; - else if (AnimationMode.IsPropertyCandidate(targetObjs[0], kEnabledPropertyName)) - animatedColor = AnimationMode.candidatePropertyColor; - - animatedColor.a *= GUI.color.a; - GUI.backgroundColor = animatedColor; - } - - int toggleId = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position); - enabledState = EditorGUIInternal.DoToggleForward(toggleRect, toggleId, enabledState, GUIContent.none, EditorStyles.toggle); - - if (animated) - { - GUI.backgroundColor = previousColor; - } - - if (EndChangeCheck()) - { - Undo.RecordObjects(targetObjs, (enabledState ? "Enable" : "Disable") + " Component" + (targetObjs.Length > 1 ? "s" : "")); - - foreach (Object targetObj in targetObjs) - { - EditorUtility.SetObjectEnabled(targetObj, enabledState); - } - } - - EditorGUI.showMixedValue = false; - - if (toggleRect.Contains(Event.current.mousePosition)) - { - // It's necessary to handle property context menu here in right mouse down because - // component contextual menu will override this otherwise. - if ((evt.type == EventType.MouseDown && evt.button == 1) || evt.type == EventType.ContextClick) - { - SerializedObject serializedObject = new SerializedObject(targetObjs[0]); - DoPropertyContextMenu(serializedObject.FindProperty(kEnabledPropertyName)); - evt.Use(); - } - } - } - - Rect headerItemRect = settingsRect; - headerItemRect.x -= kInspTitlebarIconWidth + kInspTitlebarSpacing; - headerItemRect = EditorGUIUtility.DrawEditorHeaderItems(headerItemRect, targetObjs); - textRect.xMax = headerItemRect.xMin - kInspTitlebarSpacing; - - - if (evt.type == EventType.Repaint) - { - var icon = AssetPreview.GetMiniThumbnail(targetObjs[0]); - GUIStyle.none.Draw(iconRect, EditorGUIUtility.TempContent(icon), false, false, false, false); - } - - // Temporarily set GUI.enabled = true to enable the Settings button. see Case 947218. - var oldGUIEnabledState = GUI.enabled; - - GUI.enabled = true; - - switch (evt.type) - { - case EventType.MouseDown: - if (settingsRect.Contains(evt.mousePosition)) - { - EditorUtility.DisplayObjectContextMenu(settingsRect, targetObjs, 0); - evt.Use(); - } - break; - case EventType.Repaint: - baseStyle.Draw(position, GUIContent.none, id, foldout); - position = baseStyle.padding.Remove(position); - textStyle.Draw(textRect, EditorGUIUtility.TempContent(ObjectNames.GetInspectorTitle(targetObjs[0])), id, foldout); - iconButtonStyle.Draw(settingsRect, GUIContents.titleSettingsIcon, id, foldout); - break; - } - - GUI.enabled = oldGUIEnabledState; - } - - internal static bool ToggleTitlebar(Rect position, GUIContent label, bool foldout, ref bool toggleValue) - { - // Important to get controlId for the foldout first, so it gets keyboard focus before the toggle does. - int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position); - - GUIStyle baseStyle = EditorStyles.inspectorTitlebar; - GUIStyle textStyle = EditorStyles.inspectorTitlebarText; - GUIStyle foldoutStyle = EditorStyles.foldout; - - Rect toggleRect = new Rect(position.x + baseStyle.padding.left, position.y + baseStyle.padding.top, kInspTitlebarIconWidth, kInspTitlebarIconWidth); - Rect textRect = new Rect(toggleRect.xMax + kInspTitlebarSpacing, toggleRect.y, 200, kInspTitlebarIconWidth); - - int toggleId = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position); - - toggleValue = EditorGUIInternal.DoToggleForward(toggleRect, toggleId, toggleValue, GUIContent.none, EditorStyles.toggle); - - if (Event.current.type == EventType.Repaint) - { - baseStyle.Draw(position, GUIContent.none, id, foldout); - foldoutStyle.Draw(GetInspectorTitleBarObjectFoldoutRenderRect(position), GUIContent.none, id, foldout); - position = baseStyle.padding.Remove(position); - textStyle.Draw(textRect, label, id, foldout); - } - - return EditorGUIInternal.DoToggleForward(IndentedRect(position), id, foldout, GUIContent.none, GUIStyle.none); - } - - - internal static bool FoldoutTitlebar(Rect position, GUIContent label, bool foldout, bool skipIconSpacing) - { - // Important to get controlId for the foldout first, so it gets keyboard focus before the toggle does. - int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position); - - if (Event.current.type == EventType.Repaint) - { - GUIStyle baseStyle = EditorStyles.inspectorTitlebar; - GUIStyle textStyle = EditorStyles.inspectorTitlebarText; - GUIStyle foldoutStyle = EditorStyles.foldout; - Rect textRect = new Rect(position.x + baseStyle.padding.left + kInspTitlebarSpacing + (skipIconSpacing ? 0 : kInspTitlebarIconWidth), position.y + baseStyle.padding.top, 200, kInspTitlebarIconWidth); - - baseStyle.Draw(position, GUIContent.none, id, foldout); - foldoutStyle.Draw(GetInspectorTitleBarObjectFoldoutRenderRect(position), GUIContent.none, id, foldout); - position = baseStyle.padding.Remove(position); - textStyle.Draw(textRect, EditorGUIUtility.TempContent(label.text), id, foldout); - } - - return EditorGUIInternal.DoToggleForward(IndentedRect(position), id, foldout, GUIContent.none, GUIStyle.none); - } - - [EditorHeaderItem(typeof(Object), -1000)] - internal static bool HelpIconButton(Rect position, Object[] objs) - { - var obj = objs[0]; - bool isDevBuild = Unsupported.IsSourceBuild(); - // For efficiency, only check in development builds if this script is a user script. - bool monoBehaviourFallback = !isDevBuild; - if (!monoBehaviourFallback) - { - EditorCompilation.TargetAssemblyInfo[] allTargetAssemblies = EditorCompilationInterface.GetTargetAssemblies(); - - string assemblyName = obj.GetType().Assembly.ToString(); - for (int i = 0; i < allTargetAssemblies.Length; ++i) - { - if (assemblyName == allTargetAssemblies[i].Name) - { - monoBehaviourFallback = true; - break; - } - } - } - bool hasHelp = Help.HasHelpForObject(obj, monoBehaviourFallback); - if (hasHelp || isDevBuild) - { - Color oldColor = GUI.color; - GUIContent content = new GUIContent(EditorGUI.GUIContents.helpIcon); - string helpTopic = Help.GetNiceHelpNameForObject(obj, monoBehaviourFallback); - if (isDevBuild && !hasHelp) - { - GUI.color = Color.yellow; - bool isScript = obj is MonoBehaviour; - string pageName = (isScript ? "script-" : "sealed partial class-") + helpTopic; - - content.tooltip = string.Format( - @"Could not find Reference page for {0} ({1}). -Docs for this object is missing or all docs are missing. -This warning only shows up in development builds.", helpTopic, pageName); - } - else - { - content.tooltip = string.Format("Open Reference for {0}.", helpTopic); - } - - GUIStyle helpIconStyle = EditorStyles.iconButton; - if (GUI.Button(position, content, helpIconStyle)) - { - Help.ShowHelpForObject(obj); - } - - GUI.color = oldColor; - return true; - } - return false; - } - - // Make a label with a foldout arrow to the left of it. - internal static bool FoldoutInternal(Rect position, bool foldout, GUIContent content, bool toggleOnLabelClick, GUIStyle style) - { - Rect origPosition = position; - if (EditorGUIUtility.hierarchyMode) - { - int offset = (EditorStyles.foldout.padding.left - EditorStyles.label.padding.left); - position.xMin -= offset; - } - - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - EventType eventType = Event.current.type; - // 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. - if (!GUI.enabled && GUIClip.enabled && (Event.current.rawType == EventType.MouseDown || Event.current.rawType == EventType.MouseDrag || Event.current.rawType == EventType.MouseUp)) - { - eventType = Event.current.rawType; - } - switch (eventType) - { - case EventType.MouseDown: - // If the mouse is inside the button, we say that we're the hot control - if (position.Contains(Event.current.mousePosition) && Event.current.button == 0) - { - GUIUtility.keyboardControl = GUIUtility.hotControl = id; - Event.current.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - - // If we got the mousedown, the mouseup is ours as well - // (no matter if the click was in the button or not) - Event.current.Use(); - - // toggle the passed-in value if the mouse was over the button & return true - Rect clickRect = position; - if (!toggleOnLabelClick) - { - clickRect.width = style.padding.left; - clickRect.x += indent; - } - if (clickRect.Contains(Event.current.mousePosition)) - { - GUI.changed = true; - return !foldout; - } - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - Event.current.Use(); - } - break; - case EventType.Repaint: - EditorStyles.foldoutSelected.Draw(position, GUIContent.none, id, s_DragUpdatedOverID == id); - - Rect drawRect = new Rect(position.x + indent, position.y, EditorGUIUtility.labelWidth - indent, position.height); - - // If mixed values, indicate it in the collapsed foldout field so it's easy to see at a glance if anything - // in the Inspector has different values. Don't show it when expanded, since the difference will be visible further down. - if (showMixedValue && !foldout) - { - style.Draw(drawRect, content, id, foldout); - - BeginHandleMixedValueContentColor(); - Rect fieldPosition = origPosition; - fieldPosition.xMin += EditorGUIUtility.labelWidth; - EditorStyles.label.Draw(fieldPosition, s_MixedValueContent, id, false); - EndHandleMixedValueContentColor(); - } - else - { - style.Draw(drawRect, content, id, foldout); - } - - break; - case EventType.KeyDown: - if (GUIUtility.keyboardControl == id) - { - KeyCode kc = Event.current.keyCode; - if ((kc == KeyCode.LeftArrow && foldout == true) || (kc == KeyCode.RightArrow && foldout == false)) - { - foldout = !foldout; - GUI.changed = true; - Event.current.Use(); - } - } - break; - case EventType.DragUpdated: - if (s_DragUpdatedOverID == id) - { - if (position.Contains(Event.current.mousePosition)) - { - if (Time.realtimeSinceStartup > s_FoldoutDestTime) - { - foldout = true; - Event.current.Use(); - } - } - else - { - s_DragUpdatedOverID = 0; - } - } - else - { - if (position.Contains(Event.current.mousePosition)) - { - s_DragUpdatedOverID = id; - s_FoldoutDestTime = Time.realtimeSinceStartup + kFoldoutExpandTimeout; - Event.current.Use(); - } - } - break; - case EventType.DragExited: - if (s_DragUpdatedOverID == id) - { - s_DragUpdatedOverID = 0; - Event.current.Use(); - } - break; - } - return foldout; - } - - // Make a progress bar. - public static void ProgressBar(Rect position, float value, string text) - { - int id = GUIUtility.GetControlID(s_ProgressBarHash, FocusType.Keyboard, position); - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Repaint: - EditorStyles.progressBarBack.Draw(position, false, false, false, false); - Rect barRect = new Rect(position); - value = Mathf.Clamp01(value); - barRect.width *= value; - EditorStyles.progressBarBar.Draw(barRect, false, false, false, false); - EditorStyles.progressBarText.Draw(position, text, false, false, false, false); - break; - } - } - - // Make a help box with a message to the user. - public static void HelpBox(Rect position, string message, MessageType type) - { - GUI.Label(position, EditorGUIUtility.TempContent(message, EditorGUIUtility.GetHelpIcon(type)), EditorStyles.helpBox); - } - - internal static bool LabelHasContent(GUIContent label) - { - if (label == null) - { - return true; - } - // @TODO: find out why checking for GUIContent.none doesn't work - return label.text != string.Empty || label.image != null; - } - - private static void DrawTextDebugHelpers(Rect labelPosition) - { - Color oldColor = GUI.color; - GUI.color = Color.white; - GUI.DrawTexture(new Rect(labelPosition.x, labelPosition.y, labelPosition.width, 4), EditorGUIUtility.whiteTexture); - GUI.color = Color.cyan; - GUI.DrawTexture(new Rect(labelPosition.x, labelPosition.yMax - 4, labelPosition.width, 4), EditorGUIUtility.whiteTexture); - GUI.color = oldColor; - } - - internal static void PrepareCurrentPrefixLabel(int controlId) - { - if (s_HasPrefixLabel) - { - if (!string.IsNullOrEmpty(s_PrefixLabel.text)) - { - Color curColor = GUI.color; - GUI.color = s_PrefixGUIColor; - EditorGUI.HandlePrefixLabel(EditorGUI.s_PrefixTotalRect, EditorGUI.s_PrefixRect, EditorGUI.s_PrefixLabel, controlId, EditorGUI.s_PrefixStyle); - GUI.color = curColor; - } - - s_HasPrefixLabel = false; - } - } - - // Draw a prefix label and select the corresponding control if the label is clicked. - // If no id or an id of 0 is specified, the id of the next control will be used. - // For regular inline controls, the PrefixLabel method should be used, - // but HandlePrefixLabel can be used for customized label placement. - internal static void HandlePrefixLabelInternal(Rect totalPosition, Rect labelPosition, GUIContent label, int id, GUIStyle style) - { - // If we don't know the controlID at this time, delay the handling of the prefix label until the next GUIUtility.GetControlID - if (id == 0 && label != null) - { - s_PrefixLabel.text = label.text; - s_PrefixLabel.image = label.image; - s_PrefixLabel.tooltip = label.tooltip; - s_PrefixTotalRect = totalPosition; - s_PrefixRect = labelPosition; - s_PrefixStyle = style; - s_PrefixGUIColor = GUI.color; - s_HasPrefixLabel = true; - return; - } - - // Control highlighting - if (Highlighter.searchMode == HighlightSearchMode.PrefixLabel || - Highlighter.searchMode == HighlightSearchMode.Auto) - { - Highlighter.Handle(totalPosition, label.text); - } - - //DrawTextDebugHelpers (labelPosition); - - switch (Event.current.type) - { - case EventType.Repaint: - labelPosition.width += 1; - style.DrawPrefixLabel(labelPosition, label, id); - break; - case EventType.MouseDown: - if (Event.current.button == 0 && labelPosition.Contains(Event.current.mousePosition)) - { - if (EditorGUIUtility.CanHaveKeyboardFocus(id)) - { - GUIUtility.keyboardControl = id; - } - EditorGUIUtility.editingTextField = false; - HandleUtility.Repaint(); - } - break; - } - } - - // Make a label in front of some control. - public static Rect PrefixLabel(Rect totalPosition, GUIContent label) - { - return PrefixLabel(totalPosition, 0, label, EditorStyles.label); - } - - public static Rect PrefixLabel(Rect totalPosition, GUIContent label, GUIStyle style) - { - return PrefixLabel(totalPosition, 0, label, style); - } - - public static Rect PrefixLabel(Rect totalPosition, int id, GUIContent label) - { - return PrefixLabel(totalPosition, id, label, EditorStyles.label); - } - - public static Rect PrefixLabel(Rect totalPosition, int id, GUIContent label, GUIStyle style) - { - if (!LabelHasContent(label)) - { - return IndentedRect(totalPosition); - } - - Rect labelPosition = new Rect(totalPosition.x + indent, totalPosition.y, EditorGUIUtility.labelWidth - indent, kSingleLineHeight); - Rect fieldPosition = new Rect(totalPosition.x + EditorGUIUtility.labelWidth, totalPosition.y, totalPosition.width - EditorGUIUtility.labelWidth, totalPosition.height); - HandlePrefixLabel(totalPosition, labelPosition, label, id, style); - return fieldPosition; - } - - internal static Rect MultiFieldPrefixLabel(Rect totalPosition, int id, GUIContent label, int columns) - { - if (!LabelHasContent(label)) - { - return IndentedRect(totalPosition); - } - - if (EditorGUIUtility.wideMode) - { - Rect labelPosition = new Rect(totalPosition.x + indent, totalPosition.y, EditorGUIUtility.labelWidth - indent, kSingleLineHeight); - Rect fieldPosition = totalPosition; - fieldPosition.xMin += EditorGUIUtility.labelWidth; - - - if (columns > 1) - { - // Tweak where the first sub-label is positioned to make it look like it lines up better. - labelPosition.width -= 1; - fieldPosition.xMin -= 1; - } - - // If there are 2 columns we use the same column widths as if there had been 3 columns - // in order to make columns line up neatly. - if (columns == 2) - { - float columnWidth = (fieldPosition.width - (3 - 1) * kSpacingSubLabel) / 3f; - fieldPosition.xMax -= (columnWidth + kSpacingSubLabel); - } - - HandlePrefixLabel(totalPosition, labelPosition, label, id); - return fieldPosition; - } - else - { - Rect labelPosition = new Rect(totalPosition.x + indent, totalPosition.y, totalPosition.width - indent, kSingleLineHeight); - Rect fieldPosition = totalPosition; - fieldPosition.xMin += indent + kIndentPerLevel; - fieldPosition.yMin += kSingleLineHeight + kVerticalSpacingMultiField; - HandlePrefixLabel(totalPosition, labelPosition, label, id); - return fieldPosition; - } - } - - public class PropertyScope : GUI.Scope - { - public GUIContent content { get; protected set; } - - public PropertyScope(Rect totalPosition, GUIContent label, SerializedProperty property) - { - content = BeginProperty(totalPosition, label, property); - } - - protected override void CloseScope() - { - EndProperty(); - } - } - - // Create a Property wrapper, useful for making regular GUI controls work with [[SerializedProperty]]. - public static GUIContent BeginProperty(Rect totalPosition, GUIContent label, SerializedProperty property) - { - return BeginPropertyInternal(totalPosition, label, property); - } - - // Create a Property wrapper, useful for making regular GUI controls work with [[SerializedProperty]]. - internal static GUIContent BeginPropertyInternal(Rect totalPosition, GUIContent label, SerializedProperty property) - { - Highlighter.HighlightIdentifier(totalPosition, property.propertyPath); - - if (s_PendingPropertyKeyboardHandling != null) - { - DoPropertyFieldKeyboardHandling(s_PendingPropertyKeyboardHandling); - } - - // Properties can be nested, so A BeginProperty may not be followed by its corresponding EndProperty - // before there have been one or more pairs of BeginProperty/EndProperty in between. - // The keyboard handling for a property (that handles duplicate and delete commands for array items) - // uses EditorGUI.lastControlID so it has to be executed for a property before any possible child - // properties are handled. However, it can't be done in it's own BeginProperty, because the controlID - // for the property is not yet known at that point. For that reason we mark the keyboard handling as - // pending and handle it either the next BeginProperty call (for the first child property) or if there's - // no child properties, then in the matching EndProperty call. - s_PendingPropertyKeyboardHandling = property; - - if (property == null) - { - string error = (label == null ? "" : label.text + ": ") + "SerializedProperty is null"; - HelpBox(totalPosition, "null", MessageType.Error); - throw new NullReferenceException(error); - } - - s_PropertyFieldTempContent.text = (label == null) ? property.localizedDisplayName : label.text; // no necessary to be translated. - s_PropertyFieldTempContent.tooltip = EditorGUI.isCollectingTooltips ? ((label == null) ? property.tooltip : label.tooltip) : null; - string attributeTooltip = ScriptAttributeUtility.GetHandler(property).tooltip; - if (attributeTooltip != null) - s_PropertyFieldTempContent.tooltip = attributeTooltip; - s_PropertyFieldTempContent.image = (label == null) ? null : label.image; - - // In inspector debug mode & when holding down alt. Show the property path of the property. - if (Event.current.alt && property.serializedObject.inspectorMode != InspectorMode.Normal) - { - s_PropertyFieldTempContent.tooltip = s_PropertyFieldTempContent.text = property.propertyPath; - } - - bool wasBoldDefaultFont = EditorGUIUtility.GetBoldDefaultFont(); - if (property.serializedObject.targetObjects.Length == 1 && property.isInstantiatedPrefab) - { - EditorGUIUtility.SetBoldDefaultFont(property.prefabOverride); - } - - s_PropertyStack.Push(new PropertyGUIData(property, totalPosition, wasBoldDefaultFont, GUI.enabled, GUI.backgroundColor)); - - if (GUIDebugger.active) - { - var targetObjectTypeName = property.serializedObject.targetObject != null ? - property.serializedObject.targetObject.GetType().AssemblyQualifiedName : null; - GUIDebugger.LogBeginProperty(targetObjectTypeName, property.propertyPath, totalPosition); - } - - showMixedValue = property.hasMultipleDifferentValues; - - if (property.isAnimated) - { - Color animatedColor = AnimationMode.animatedPropertyColor; - if (AnimationMode.InAnimationRecording()) - animatedColor = AnimationMode.recordedPropertyColor; - else if (property.isCandidate) - animatedColor = AnimationMode.candidatePropertyColor; - - animatedColor.a *= GUI.backgroundColor.a; - GUI.backgroundColor = animatedColor; - } - - GUI.enabled &= property.editable; - - return s_PropertyFieldTempContent; - } - - // Ends a Property wrapper started with ::ref::BeginProperty. - public static void EndProperty() - { - if (GUIDebugger.active) - { - GUIDebugger.LogEndProperty(); - } - - showMixedValue = false; - PropertyGUIData data = s_PropertyStack.Pop(); - // Context menu - // Handle context menu in EndProperty instead of BeginProperty. This ensures that child properties - // get the event rather than parent properties when clicking inside the child property rects, but the menu can - // still be invoked for the parent property by clicking inside the parent rect but outside the child rects. - if (Event.current.type == EventType.ContextClick && data.totalPosition.Contains(Event.current.mousePosition)) - { - DoPropertyContextMenu(data.property); - } - - EditorGUIUtility.SetBoldDefaultFont(data.wasBoldDefaultFont); - GUI.enabled = data.wasEnabled; - GUI.backgroundColor = data.color; - - if (s_PendingPropertyKeyboardHandling != null) - { - DoPropertyFieldKeyboardHandling(s_PendingPropertyKeyboardHandling); - } - - // Wait with deleting the property until the property stack is empty in order to avoid - // deleting a property in the middle of GUI calls that's dependent on it existing. - if (s_PendingPropertyDelete != null && s_PropertyStack.Count == 0) - { - // For SerializedProperty iteration reasons, if the property we delete is the current property, - // we have to delete on the actual iterator property rather than a copy of it, - // otherwise we get an error next time we call NextVisible on the iterator property. - if (s_PendingPropertyDelete.propertyPath == data.property.propertyPath) - { - data.property.DeleteCommand(); - } - else - { - s_PendingPropertyDelete.DeleteCommand(); - } - s_PendingPropertyDelete = null; - } - } - - private static SerializedProperty s_PendingPropertyKeyboardHandling = null; - private static SerializedProperty s_PendingPropertyDelete = null; - - private static void DoPropertyFieldKeyboardHandling(SerializedProperty property) - { - // Delete & Duplicate commands - if (Event.current.type == EventType.ExecuteCommand || Event.current.type == EventType.ValidateCommand) - { - if (GUIUtility.keyboardControl == EditorGUIUtility.s_LastControlID && (Event.current.commandName == EventCommandNames.Delete || Event.current.commandName == EventCommandNames.SoftDelete)) - { - if (Event.current.type == EventType.ExecuteCommand) - { - // Wait with deleting the property until the property stack is empty. See EndProperty. - s_PendingPropertyDelete = property.Copy(); - } - Event.current.Use(); - } - if (GUIUtility.keyboardControl == EditorGUIUtility.s_LastControlID && Event.current.commandName == EventCommandNames.Duplicate) - { - if (Event.current.type == EventType.ExecuteCommand) - { - property.DuplicateCommand(); - } - Event.current.Use(); - } - } - s_PendingPropertyKeyboardHandling = null; - } - - // Make a field for layer masks. - internal static void LayerMaskField(Rect position, SerializedProperty property, GUIContent label) - { - LayerMaskField(position, property, label, EditorStyles.layerMaskField); - } - - internal static void LayerMaskField(Rect position, SerializedProperty property, GUIContent label, GUIStyle style) - { - LayerMaskField(position, property.layerMaskBits, property, label, style, SetLayerMaskValueDelegate); - } - - internal static void LayerMaskField(Rect position, UInt32 layers, GUIContent label, EditorUtility.SelectMenuItemFunction callback) - { - LayerMaskField(position, layers, null, label, EditorStyles.layerMaskField, callback); - } - - internal static void LayerMaskField(Rect position, UInt32 layers, SerializedProperty property, GUIContent label, GUIStyle style, EditorUtility.SelectMenuItemFunction callback) - { - int id = GUIUtility.GetControlID(s_LayerMaskField, FocusType.Keyboard, position); - if (label != null) - { - position = PrefixLabel(position, id, label); - } - Event evt = Event.current; - if (evt.type == EventType.Repaint) - { - if (showMixedValue) - { - BeginHandleMixedValueContentColor(); - style.Draw(position, s_MixedValueContent, id, false); - EndHandleMixedValueContentColor(); - } - else - { - style.Draw(position, EditorGUIUtility.TempContent(SerializedProperty.GetLayerMaskStringValue(layers)), id, false); - } - } - else if ((evt.type == EventType.MouseDown && position.Contains(evt.mousePosition)) || evt.MainActionKeyForControl(id)) - { - SerializedProperty propertyWithPath = (property != null) ? property.serializedObject.FindProperty(property.propertyPath) : null; - var userData = new Tuple(propertyWithPath, layers); - EditorUtility.DisplayCustomMenu(position, SerializedProperty.GetLayerMaskNames(layers), (property != null && property.hasMultipleDifferentValues) ? new int[0] : SerializedProperty.GetLayerMaskSelectedIndex(layers), callback, userData); - Event.current.Use(); - EditorGUIUtility.keyboardControl = id; - } - } - - internal static void SetLayerMaskValueDelegate(object userData, string[] options, int selected) - { - var data = (Tuple)userData; - if (data.Item1 != null) - { - data.Item1.ToggleLayerMaskAtIndex(selected); - data.Item1.serializedObject.ApplyModifiedProperties(); - data.Item2 = data.Item1.layerMaskBits; - } - } - - // Helper function for helping with debugging the editor - internal static void ShowRepaints() - { - if (Unsupported.IsDeveloperMode()) - { - Color temp = GUI.backgroundColor; - GUI.backgroundColor = new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value, 1f); - var texture = EditorStyles.radioButton.normal.background; - var size = new Vector2(texture.width, texture.height); - GUI.Label(new Rect(Vector2.zero, EditorGUIUtility.PixelsToPoints(size)), string.Empty, EditorStyles.radioButton); - GUI.backgroundColor = temp; - } - } - - // Draws the alpha channel of a texture within a rectangle. - internal static void DrawTextureAlphaInternal(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel) - { - DrawPreviewTextureInternal(position, image, alphaMaterial, scaleMode, imageAspect, mipLevel); - } - - // Draws texture transparantly using the alpha channel. - internal static void DrawTextureTransparentInternal(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel) - { - if (imageAspect == 0f && image == null) - { - Debug.LogError("Please specify an image or a imageAspect"); - return; - } - - if (imageAspect == 0f) - imageAspect = (float)image.width / (float)image.height; - - DrawTransparencyCheckerTexture(position, scaleMode, imageAspect); - if (image != null) - DrawPreviewTexture(position, image, transparentMaterial, scaleMode, imageAspect, mipLevel); - } - - internal static void DrawTransparencyCheckerTexture(Rect position, ScaleMode scaleMode, float imageAspect) - { - Rect screenRect = new Rect(); - Rect sourceRect = new Rect(); - - GUI.CalculateScaledTextureRects(position, scaleMode, imageAspect, ref screenRect, ref sourceRect); - - GUI.DrawTextureWithTexCoords( - screenRect, - transparentCheckerTexture, - new Rect( - (float)screenRect.width * -.5f / (float)transparentCheckerTexture.width, - (float)screenRect.height * -.5f / (float)transparentCheckerTexture.height, - (float)screenRect.width / (float)transparentCheckerTexture.width, - (float)screenRect.height / (float)transparentCheckerTexture.height), - false); - } - - // Draws the texture within a rectangle. - internal static void DrawPreviewTextureInternal(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect, float mipLevel) - { - if (Event.current.type == EventType.Repaint) - { - if (imageAspect == 0) - imageAspect = (float)image.width / (float)image.height; - - if (mat == null) - mat = GetMaterialForSpecialTexture(image, colorMaterial); - mat.SetFloat("_Mip", mipLevel); - - RenderTexture rt = image as RenderTexture; - bool manualResolve = (rt != null) && rt.bindTextureMS; - - if (manualResolve) - { - var desc = rt.descriptor; - desc.bindMS = false; - desc.msaaSamples = 1; - RenderTexture resolved = RenderTexture.GetTemporary(desc); - resolved.Create(); - rt.ResolveAntiAliasedSurface(resolved); - image = resolved; - } - - Rect screenRect = new Rect(), sourceRect = new Rect(); - GUI.CalculateScaledTextureRects(position, scaleMode, imageAspect, ref screenRect, ref sourceRect); - Texture2D t2d = image as Texture2D; - if (t2d != null && TextureUtil.GetUsageMode(image) == TextureUsageMode.AlwaysPadded) - { - // In case of always padded textures, only show the non-padded area - sourceRect.width *= (float)t2d.width / TextureUtil.GetGPUWidth(t2d); - sourceRect.height *= (float)t2d.height / TextureUtil.GetGPUHeight(t2d); - } - Graphics.DrawTexture(screenRect, image, sourceRect, 0, 0, 0, 0, GUI.color, mat); - - - if (manualResolve) - { - RenderTexture.ReleaseTemporary(image as RenderTexture); - } - } - } - - // This will return appriopriate material to use with the texture according to its usage mode - internal static Material GetMaterialForSpecialTexture(Texture t, Material defaultMat = null) - { - // i am not sure WHY do we check that (i would guess this is api user error and exception make sense, not "return something") - if (t == null) return null; - - TextureUsageMode usage = TextureUtil.GetUsageMode(t); - TextureFormat format = TextureUtil.GetTextureFormat(t); - if (usage == TextureUsageMode.RealtimeLightmapRGBM || usage == TextureUsageMode.BakedLightmapRGBM || usage == TextureUsageMode.RGBMEncoded) - return lightmapRGBMMaterial; - else if (usage == TextureUsageMode.BakedLightmapDoubleLDR) - return lightmapDoubleLDRMaterial; - else if (usage == TextureUsageMode.BakedLightmapFullHDR) - return lightmapFullHDRMaterial; - else if (usage == TextureUsageMode.NormalmapDXT5nm || (usage == TextureUsageMode.NormalmapPlain && format == TextureFormat.BC5)) - return normalmapMaterial; - else if (TextureUtil.IsAlphaOnlyTextureFormat(format)) - return alphaMaterial; - return defaultMat; - } - - internal static Texture2D transparentCheckerTexture - { - get - { - if (EditorGUIUtility.isProSkin) - { - return EditorGUIUtility.LoadRequired("Previews/Textures/textureCheckerDark.png") as Texture2D; - } - else - { - return EditorGUIUtility.LoadRequired("Previews/Textures/textureChecker.png") as Texture2D; - } - } - } - - - private static Material GetPreviewMaterial(ref Material m, string shaderPath) - { - if (m == null) - { - m = new Material(EditorGUIUtility.LoadRequired(shaderPath) as Shader); - m.hideFlags = HideFlags.HideAndDontSave; - } - return m; - } - - private static Material s_ColorMaterial, s_AlphaMaterial, s_TransparentMaterial, s_NormalmapMaterial; - private static Material s_LightmapRGBMMaterial, s_LightmapDoubleLDRMaterial, s_LightmapFullHDRMaterial; - - internal static Material colorMaterial - { - get { return GetPreviewMaterial(ref s_ColorMaterial, "Previews/PreviewColor2D.shader"); } - } - internal static Material alphaMaterial - { - get { return GetPreviewMaterial(ref s_AlphaMaterial, "Previews/PreviewAlpha.shader"); } - } - internal static Material transparentMaterial - { - get { return GetPreviewMaterial(ref s_TransparentMaterial, "Previews/PreviewTransparent.shader"); } - } - internal static Material normalmapMaterial - { - get { return GetPreviewMaterial(ref s_NormalmapMaterial, "Previews/PreviewEncodedNormals.shader"); } - } - internal static Material lightmapRGBMMaterial - { - get { return GetPreviewMaterial(ref s_LightmapRGBMMaterial, "Previews/PreviewEncodedLightmapRGBM.shader"); } - } - internal static Material lightmapDoubleLDRMaterial - { - get { return GetPreviewMaterial(ref s_LightmapDoubleLDRMaterial, "Previews/PreviewEncodedLightmapDoubleLDR.shader"); } - } - internal static Material lightmapFullHDRMaterial - { - get { return GetPreviewMaterial(ref s_LightmapFullHDRMaterial, "Previews/PreviewEncodedLightmapFullHDR.shader"); } - } - - private static void SetExpandedRecurse(SerializedProperty property, bool expanded) - { - SerializedProperty search = property.Copy(); - search.isExpanded = expanded; - - int depth = search.depth; - while (search.NextVisible(true) && search.depth > depth) - { - if (search.hasVisibleChildren) - { - search.isExpanded = expanded; - } - } - } - - // Get the height needed for a ::ref::PropertyField control, not including its children and not taking custom PropertyDrawers into account. - internal static float GetSinglePropertyHeight(SerializedProperty property, GUIContent label) - { - if (property == null) - return kSingleLineHeight; - return GetPropertyHeight(property.propertyType, label); - } - - // Get the height needed for a simple builtin control type. - public static float GetPropertyHeight(SerializedPropertyType type, GUIContent label) - { - if (type == SerializedPropertyType.Vector3 || type == SerializedPropertyType.Vector2 || type == SerializedPropertyType.Vector4 || - type == SerializedPropertyType.Vector3Int || type == SerializedPropertyType.Vector2Int) - { - return (!LabelHasContent(label) || EditorGUIUtility.wideMode ? 0f : kStructHeaderLineHeight) + kSingleLineHeight; - } - - if (type == SerializedPropertyType.Rect || type == SerializedPropertyType.RectInt) - { - return (!LabelHasContent(label) || EditorGUIUtility.wideMode ? 0f : kStructHeaderLineHeight) + kSingleLineHeight * 2 + kVerticalSpacingMultiField; - } - - // Bounds field has label on its own line even in wide mode because the words "center" and "extends" - // would otherwise eat too much of the label space. - if (type == SerializedPropertyType.Bounds || type == SerializedPropertyType.BoundsInt) - { - return (!LabelHasContent(label) ? 0f : kStructHeaderLineHeight) + kSingleLineHeight * 2 + kVerticalSpacingMultiField; - } - - return kSingleLineHeight; - } - - // Get the height needed for a ::ref::PropertyField control. - internal static float GetPropertyHeightInternal(SerializedProperty property, GUIContent label, bool includeChildren) - { - return ScriptAttributeUtility.GetHandler(property).GetHeight(property, label, includeChildren); - } - - public static bool CanCacheInspectorGUI(SerializedProperty property) - { - return ScriptAttributeUtility.GetHandler(property).CanCacheInspectorGUI(property); - } - - internal static bool HasVisibleChildFields(SerializedProperty property) - { - switch (property.propertyType) - { - case SerializedPropertyType.Vector3: - case SerializedPropertyType.Vector2: - case SerializedPropertyType.Vector3Int: - case SerializedPropertyType.Vector2Int: - case SerializedPropertyType.Rect: - case SerializedPropertyType.RectInt: - case SerializedPropertyType.Bounds: - case SerializedPropertyType.BoundsInt: - return false; - } - return property.hasVisibleChildren; - } - - // Make a field for [[SerializedProperty]]. - internal static bool PropertyFieldInternal(Rect position, SerializedProperty property, GUIContent label, bool includeChildren) - { - return ScriptAttributeUtility.GetHandler(property).OnGUI(position, property, label, includeChildren); - } - - static string s_ArrayMultiInfoFormatString = EditorGUIUtility.TrTextContent("This field cannot display arrays with more than {0} elements when multiple objects are selected.").text; - static GUIContent s_ArrayMultiInfoContent = new GUIContent(); - - internal static bool DefaultPropertyField(Rect position, SerializedProperty property, GUIContent label) - { - label = BeginPropertyInternal(position, label, property); - - SerializedPropertyType type = property.propertyType; - - bool childrenAreExpanded = false; - - // Should we inline? All one-line vars as well as Vector2, Vector3, Rect and Bounds properties are inlined. - if (!HasVisibleChildFields(property)) - { - switch (type) - { - case SerializedPropertyType.Integer: - { - BeginChangeCheck(); - long newValue = EditorGUI.LongField(position, label, property.longValue); - if (EndChangeCheck()) - { - property.longValue = newValue; - } - break; - } - case SerializedPropertyType.Float: - { - BeginChangeCheck(); - - // Necessary to check for float type to get correct string formatting for float and double. - bool isFloat = property.type == "float"; - double newValue = isFloat ? EditorGUI.FloatField(position, label, property.floatValue) : - EditorGUI.DoubleField(position, label, property.doubleValue); - if (EndChangeCheck()) - { - property.doubleValue = newValue; - } - break; - } - case SerializedPropertyType.String: - { - BeginChangeCheck(); - string newValue = EditorGUI.TextField(position, label, property.stringValue); - if (EndChangeCheck()) - { - property.stringValue = newValue; - } - break; - } - // Multi @todo: Needs style work - case SerializedPropertyType.Boolean: - { - BeginChangeCheck(); - bool newValue = EditorGUI.Toggle(position, label, property.boolValue); - if (EndChangeCheck()) - { - property.boolValue = newValue; - } - break; - } - case SerializedPropertyType.Color: - { - BeginChangeCheck(); - Color newColor = EditorGUI.ColorField(position, label, property.colorValue); - if (EndChangeCheck()) - { - property.colorValue = newColor; - } - break; - } - case SerializedPropertyType.ArraySize: - { - BeginChangeCheck(); - int newValue = EditorGUI.ArraySizeField(position, label, property.intValue, EditorStyles.numberField); - if (EndChangeCheck()) - { - property.intValue = newValue; - } - break; - } - case SerializedPropertyType.FixedBufferSize: - { - EditorGUI.IntField(position, label, property.intValue); - break; - } - case SerializedPropertyType.Enum: - { - EditorGUI.Popup(position, property, label); - break; - } - // Multi @todo: Needs testing for texture types - case SerializedPropertyType.ObjectReference: - { - EditorGUI.ObjectFieldInternal(position, property, null, label, EditorStyles.objectField); - break; - } - case SerializedPropertyType.LayerMask: - { - EditorGUI.LayerMaskField(position, property, label); - break; - } - case SerializedPropertyType.Character: - { - char[] value = { (char)property.intValue }; - - bool wasChanged = GUI.changed; - GUI.changed = false; - string newValue = EditorGUI.TextField(position, label, new string(value)); - if (GUI.changed) - { - if (newValue.Length == 1) - { - property.intValue = newValue[0]; - } - // Value didn't get changed after all - else - { - GUI.changed = false; - } - } - GUI.changed |= wasChanged; - break; - } - case SerializedPropertyType.AnimationCurve: - { - int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position); - EditorGUI.DoCurveField(PrefixLabel(position, id, label), id, null, kCurveColor, new Rect(), property); - break; - } - case SerializedPropertyType.Gradient: - { - int id = GUIUtility.GetControlID(s_CurveHash, FocusType.Keyboard, position); - EditorGUI.DoGradientField(PrefixLabel(position, id, label), id, null, property, false); - break; - } - case SerializedPropertyType.Vector3: - { - Vector3Field(position, property, label); - break; - } - case SerializedPropertyType.Vector4: - { - Vector4Field(position, property, label); - break; - } - case SerializedPropertyType.Vector2: - { - Vector2Field(position, property, label); - break; - } - case SerializedPropertyType.Vector2Int: - { - Vector2IntField(position, property, label); - break; - } - case SerializedPropertyType.Vector3Int: - { - Vector3IntField(position, property, label); - break; - } - case SerializedPropertyType.Rect: - { - RectField(position, property, label); - break; - } - case SerializedPropertyType.RectInt: - { - RectIntField(position, property, label); - break; - } - case SerializedPropertyType.Bounds: - { - BoundsField(position, property, label); - break; - } - case SerializedPropertyType.BoundsInt: - { - BoundsIntField(position, property, label); - break; - } - default: - { - int genericID = GUIUtility.GetControlID(s_GenericField, FocusType.Keyboard, position); - EditorGUI.PrefixLabel(position, genericID, label); - break; - } - } - } - // Handle Foldout - else - { - Event tempEvent = new Event(Event.current); - - // Handle the actual foldout first, since that's the one that supports keyboard control. - // This makes it work more consistent with PrefixLabel. - childrenAreExpanded = property.isExpanded; - - bool newChildrenAreExpanded = childrenAreExpanded; - using (new EditorGUI.DisabledScope(!property.editable)) - { - GUIStyle foldoutStyle = (DragAndDrop.activeControlID == -10) ? EditorStyles.foldoutPreDrop : EditorStyles.foldout; - newChildrenAreExpanded = EditorGUI.Foldout(position, childrenAreExpanded, s_PropertyFieldTempContent, true, foldoutStyle); - } - - - if (childrenAreExpanded && property.isArray && property.arraySize > property.serializedObject.maxArraySizeForMultiEditing && property.serializedObject.isEditingMultipleObjects) - { - Rect boxRect = position; - boxRect.xMin += EditorGUIUtility.labelWidth - EditorGUI.indent; - - s_ArrayMultiInfoContent.text = s_ArrayMultiInfoContent.tooltip = string.Format(s_ArrayMultiInfoFormatString, property.serializedObject.maxArraySizeForMultiEditing); - EditorGUI.LabelField(boxRect, GUIContent.none, s_ArrayMultiInfoContent, EditorStyles.helpBox); - } - - if (newChildrenAreExpanded != childrenAreExpanded) - { - // Recursive set expanded - if (Event.current.alt) - { - SetExpandedRecurse(property, newChildrenAreExpanded); - } - // Expand one element only - else - { - property.isExpanded = newChildrenAreExpanded; - } - } - childrenAreExpanded = newChildrenAreExpanded; - - - // Check for drag & drop events here, to add objects to an array by dragging to the foldout. - // The event may have already been used by the Foldout control above, but we want to also use it here, - // so we use the event copy we made prior to calling the Foldout method. - - // We need to use last s_LastControlID here to ensure we do not break duplicate functionality (fix for case 598389) - // If we called GetControlID here s_LastControlID would be incremented and would not longer be in sync with GUIUtililty.keyboardFocus that - // is used for duplicating (See DoPropertyFieldKeyboardHandling) - int id = EditorGUIUtility.s_LastControlID; - switch (tempEvent.type) - { - case EventType.DragExited: - if (GUI.enabled) - { - HandleUtility.Repaint(); - } - - break; - case EventType.DragUpdated: - case EventType.DragPerform: - - if (position.Contains(tempEvent.mousePosition) && GUI.enabled) - { - Object[] references = DragAndDrop.objectReferences; - - // Check each single object, so we can add multiple objects in a single drag. - Object[] oArray = new Object[1]; - bool didAcceptDrag = false; - foreach (Object o in references) - { - oArray[0] = o; - Object validatedObject = ValidateObjectFieldAssignment(oArray, null, property, ObjectFieldValidatorOptions.None); - if (validatedObject != null) - { - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - if (tempEvent.type == EventType.DragPerform) - { - property.AppendFoldoutPPtrValue(validatedObject); - didAcceptDrag = true; - DragAndDrop.activeControlID = 0; - } - else - { - DragAndDrop.activeControlID = id; - } - } - } - if (didAcceptDrag) - { - GUI.changed = true; - DragAndDrop.AcceptDrag(); - } - } - break; - } - } - - EndProperty(); - - return childrenAreExpanded; - } - - internal static void DrawLegend(Rect position, Color color, string label, bool enabled) - { - position = new Rect(position.x + 2, position.y + 2, position.width - 2, position.height - 2); - Color oldCol = GUI.backgroundColor; - if (enabled) - { - GUI.backgroundColor = color; - } - else - { - // Tweaked to work on both light and dark skin: - GUI.backgroundColor = new Color(0.5f, 0.5f, 0.5f, 0.45f); - } - - GUI.Label(position, label, "ProfilerPaneSubLabel"); - GUI.backgroundColor = oldCol; - } - - internal static string TextFieldDropDown(Rect position, string text, string[] dropDownElement) - { - return TextFieldDropDown(position, GUIContent.none, text, dropDownElement); - } - - internal static string TextFieldDropDown(Rect position, GUIContent label, string text, string[] dropDownElement) - { - int id = EditorGUIUtility.GetControlID(s_TextFieldDropDownHash, FocusType.Keyboard, position); - return EditorGUI.DoTextFieldDropDown(PrefixLabel(position, id, label), id, text, dropDownElement, false); - } - - internal static string DelayedTextFieldDropDown(Rect position, string text, string[] dropDownElement) - { - return DelayedTextFieldDropDown(position, GUIContent.none, text, dropDownElement); - } - - internal static string DelayedTextFieldDropDown(Rect position, GUIContent label, string text, string[] dropDownElement) - { - int id = EditorGUIUtility.GetControlID(s_TextFieldDropDownHash, FocusType.Keyboard, position); - return EditorGUI.DoTextFieldDropDown(PrefixLabel(position, id, label), id, text, dropDownElement, true); - } - - public static bool DropdownButton(Rect position, GUIContent content, FocusType focusType) - { - return DropdownButton(position, content, focusType, "MiniPullDown"); - } - - public static bool DropdownButton(Rect position, GUIContent content, FocusType focusType, GUIStyle style) - { - int id = EditorGUIUtility.GetControlID(s_DropdownButtonHash, focusType, position); - return DropdownButton(id, position, content, style); - } - - // A button that returns true on mouse down - like a popup button - internal static bool DropdownButton(int id, Rect position, GUIContent content, GUIStyle style) - { - Event evt = Event.current; - switch (evt.type) - { - case EventType.Repaint: - if (showMixedValue) - { - BeginHandleMixedValueContentColor(); - style.Draw(position, s_MixedValueContent, id, false); - EndHandleMixedValueContentColor(); - } - else - style.Draw(position, content, id, false); - break; - case EventType.MouseDown: - if (position.Contains(evt.mousePosition) && evt.button == 0) - { - Event.current.Use(); - return true; - } - break; - case EventType.KeyDown: - if (GUIUtility.keyboardControl == id && evt.character == ' ') - { - Event.current.Use(); - return true; - } - break; - } - return false; - } - - static int EnumFlagsToInt(EnumData enumData, Enum enumValue) - { - if (enumData.unsigned) - { - if (enumData.underlyingType == typeof(uint)) - { - return unchecked((int)Convert.ToUInt32(enumValue)); - } - // ensure unsigned 16- and 8-bit variants will display using "Everything" label - else if (enumData.underlyingType == typeof(ushort)) - { - var unsigned = Convert.ToUInt16(enumValue); - return unchecked(unsigned == ushort.MaxValue ? ~0 : (int)unsigned); - } - else - { - var unsigned = Convert.ToByte(enumValue); - return unchecked(unsigned == byte.MaxValue ? ~0 : (int)unsigned); - } - } - - return Convert.ToInt32(enumValue); - } - - static Enum IntToEnumFlags(Type enumType, int value) - { - var enumData = GetNonObsoleteEnumData(enumType); - - // parsing a string seems to be the only way to go from a flags int to an enum value - if (enumData.unsigned) - { - if (enumData.underlyingType == typeof(uint)) - { - var unsigned = unchecked((uint)value); - return Enum.Parse(enumType, unsigned.ToString()) as Enum; - } - else if (enumData.underlyingType == typeof(ushort)) - { - var unsigned = unchecked((ushort)value); - return Enum.Parse(enumType, unsigned.ToString()) as Enum; - } - else - { - var unsigned = unchecked((byte)value); - return Enum.Parse(enumType, unsigned.ToString()) as Enum; - } - } - - return Enum.Parse(enumType, value.ToString()) as Enum; - } - - internal static bool isCollectingTooltips - { - get { return s_CollectingToolTips; } - set { s_CollectingToolTips = value; } - } - - internal static bool s_CollectingToolTips; - - internal static int AdvancedPopup(Rect rect, int selectedIndex, string[] displayedOptions) - { - return StatelessAdvancedDropdown.SearchablePopup(rect, selectedIndex, displayedOptions, "MiniPullDown"); - } - - internal static int AdvancedPopup(Rect rect, int selectedIndex, string[] displayedOptions, GUIStyle style) - { - return StatelessAdvancedDropdown.SearchablePopup(rect, selectedIndex, displayedOptions, style); - } - } - - - // Auto-layouted version of [[EditorGUI]] - sealed partial class EditorGUILayout - { - // @TODO: Make private (and rename to not claim it's a constant). Shouldn't really be used outside of EditorGUI. - // Places that use this directly should likely use GetControlRect instead. - internal static float kLabelFloatMinW - { - get { return EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; } - } - - internal static float kLabelFloatMaxW - { - get { return EditorGUIUtility.labelWidth + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; } - } - - internal static Rect s_LastRect; - - internal const float kPlatformTabWidth = 30; - - internal static SavedBool s_SelectedDefault = new SavedBool("Platform.ShownDefaultTab", true); - - - /// *listonly* - public static void LabelField(string label, params GUILayoutOption[] options) - { - LabelField(GUIContent.none, EditorGUIUtility.TempContent(label), EditorStyles.label, options); - } - - /// *listonly* - public static void LabelField(string label, GUIStyle style, params GUILayoutOption[] options) - { - LabelField(GUIContent.none, EditorGUIUtility.TempContent(label), style, options); - } - - /// *listonly* - public static void LabelField(GUIContent label, params GUILayoutOption[] options) - { - LabelField(GUIContent.none, label, EditorStyles.label, options); - } - - /// *listonly* - public static void LabelField(GUIContent label, GUIStyle style, params GUILayoutOption[] options) - { - LabelField(GUIContent.none, label, style, options); - } - - /// *listonly* - public static void LabelField(string label, string label2, params GUILayoutOption[] options) - { - LabelField(new GUIContent(label), EditorGUIUtility.TempContent(label2), EditorStyles.label, options); - } - - /// *listonly* - public static void LabelField(string label, string label2, GUIStyle style, params GUILayoutOption[] options) - { - LabelField(new GUIContent(label), EditorGUIUtility.TempContent(label2), style, options); - } - - /// *listonly* - public static void LabelField(GUIContent label, GUIContent label2, params GUILayoutOption[] options) - { - LabelField(label, label2, EditorStyles.label, options); - } - - // Make a label field. (Useful for showing read-only info.) - public static void LabelField(GUIContent label, GUIContent label2, GUIStyle style, params GUILayoutOption[] options) - { - if (!style.wordWrap) - { - // If we don't need wordwrapping, just allocate the standard space to avoid corner case layout issues - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options); - EditorGUI.LabelField(r, label, label2, style); - } - else - { - EditorGUILayout.BeginHorizontal(); - PrefixLabel(label, style); - Rect r = GUILayoutUtility.GetRect(label2, style, options); - int oldIndent = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; - EditorGUI.LabelField(r, label2, style); - EditorGUI.indentLevel = oldIndent; - EditorGUILayout.EndHorizontal(); - } - } - - /// *listonly* - internal static bool LinkLabel(string label, params GUILayoutOption[] options) - { - return LinkLabel(EditorGUIUtility.TempContent(label), options); - } - - /// *listonly* - internal static bool LinkLabel(GUIContent label, params GUILayoutOption[] options) - { - var position = s_LastRect = GUILayoutUtility.GetRect(label, EditorStyles.linkLabel, options); - - Handles.color = EditorStyles.linkLabel.normal.textColor; - Handles.DrawLine(new Vector3(position.xMin, position.yMax), new Vector3(position.xMax, position.yMax)); - Handles.color = Color.white; - - EditorGUIUtility.AddCursorRect(position, MouseCursor.Link); - - return GUI.Button(position, label, EditorStyles.linkLabel); - } - - /// *listonly* - public static bool Toggle(bool value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetToggleRect(false, options); - return EditorGUI.Toggle(r, value); - } - - /// *listonly* - public static bool Toggle(string label, bool value, params GUILayoutOption[] options) - { - return Toggle(EditorGUIUtility.TempContent(label), value, options); - } - - /// *listonly* - public static bool Toggle(GUIContent label, bool value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetToggleRect(true, options); - return EditorGUI.Toggle(r, label, value); - } - - /// *listonly* - public static bool Toggle(bool value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetToggleRect(false, options); - return EditorGUI.Toggle(r, value, style); - } - - /// *listonly* - public static bool Toggle(string label, bool value, GUIStyle style, params GUILayoutOption[] options) - { - return Toggle(EditorGUIUtility.TempContent(label), value, style, options); - } - - // Make a toggle. - public static bool Toggle(GUIContent label, bool value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetToggleRect(true, options); - return EditorGUI.Toggle(r, label, value, style); - } - - /// *listonly* - public static bool ToggleLeft(string label, bool value, params GUILayoutOption[] options) - { - return ToggleLeft(EditorGUIUtility.TempContent(label), value, options); - } - - /// *listonly* - public static bool ToggleLeft(GUIContent label, bool value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, options); - return EditorGUI.ToggleLeft(r, label, value); - } - - /// *listonly* - public static bool ToggleLeft(string label, bool value, GUIStyle labelStyle, params GUILayoutOption[] options) - { - return ToggleLeft(EditorGUIUtility.TempContent(label), value, labelStyle, options); - } - - // Make a toggle with the label on the right. - public static bool ToggleLeft(GUIContent label, bool value, GUIStyle labelStyle, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, options); - return EditorGUI.ToggleLeft(r, label, value, labelStyle); - } - - /// *listonly* - public static string TextField(string text, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.textField, options); - return EditorGUI.TextField(r, text); - } - - /// *listonly* - public static string TextField(string text, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.TextField(r, text, style); - } - - /// *listonly* - public static string TextField(string label, string text, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.textField, options); - return EditorGUI.TextField(r, label, text); - } - - /// *listonly* - public static string TextField(string label, string text, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.TextField(r, label, text, style); - } - - /// *listonly* - public static string TextField(GUIContent label, string text, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.textField, options); - return EditorGUI.TextField(r, label, text); - } - - // Make a text field. - public static string TextField(GUIContent label, string text, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.TextField(r, label, text, style); - } - - /// *listonly* - public static string DelayedTextField(string text, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.textField, options); - return EditorGUI.DelayedTextField(r, text); - } - - /// *listonly* - public static string DelayedTextField(string text, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedTextField(r, text, style); - } - - /// *listonly* - public static string DelayedTextField(string label, string text, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.textField, options); - return EditorGUI.DelayedTextField(r, label, text); - } - - /// *listonly* - public static string DelayedTextField(string label, string text, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedTextField(r, label, text, style); - } - - /// *listonly* - public static string DelayedTextField(GUIContent label, string text, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.textField, options); - return EditorGUI.DelayedTextField(r, label, text); - } - - // Make a delayed text field. - public static string DelayedTextField(GUIContent label, string text, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedTextField(r, label, text, style); - } - - /// *listonly* - public static void DelayedTextField(SerializedProperty property, params GUILayoutOption[] options) - { - EditorGUILayout.DelayedTextField(property, null, options); - } - - // Make a delayed text field. - public static void DelayedTextField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(EditorGUI.LabelHasContent(label), EditorGUI.kSingleLineHeight, EditorStyles.textField, options); - EditorGUI.DelayedTextField(r, property, label); - } - - internal static string ToolbarSearchField(string text, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GUILayoutUtility.GetRect(0, kLabelFloatMaxW * 1.5f, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchField, options); - int i = 0; - return EditorGUI.ToolbarSearchField(r, null, ref i, text); - } - - internal static string ToolbarSearchField(string text, string[] searchModes, ref int searchMode, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GUILayoutUtility.GetRect(0, kLabelFloatMaxW * 1.5f, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchField, options); - return EditorGUI.ToolbarSearchField(r, searchModes, ref searchMode, text); - } - - /// *listonly* - public static string TextArea(string text, params GUILayoutOption[] options) - { return TextArea(text, EditorStyles.textField, options); } - // Make a text area. - public static string TextArea(string text, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GUILayoutUtility.GetRect(EditorGUIUtility.TempContent(text), style, options); - return EditorGUI.TextArea(r, text, style); - } - - /// *listonly* - public static void SelectableLabel(string text, params GUILayoutOption[] options) - { - SelectableLabel(text, EditorStyles.label, options); - } - - // Make a selectable label field. (Useful for showing read-only info that can be copy-pasted.) - public static void SelectableLabel(string text, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight * 2, style, options); - EditorGUI.SelectableLabel(r, text, style); - } - - internal static Event KeyEventField(Event e, params GUILayoutOption[] options) - { - GUIContent content = EditorGUIUtility.TempContent("[Please press a key]"); - Rect r = GUILayoutUtility.GetRect(content, GUI.skin.textField, options); - return EditorGUI.KeyEventField(r, e); - } - - /// *listonly* - public static string PasswordField(string password, params GUILayoutOption[] options) - { - return PasswordField(password, EditorStyles.textField, options); - } - - /// *listonly* - public static string PasswordField(string password, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.PasswordField(r, password, style); - } - - /// *listonly* - public static string PasswordField(string label, string password, params GUILayoutOption[] options) - { - return PasswordField(EditorGUIUtility.TempContent(label), password, EditorStyles.textField, options); - } - - /// *listonly* - public static string PasswordField(string label, string password, GUIStyle style, params GUILayoutOption[] options) - { - return PasswordField(EditorGUIUtility.TempContent(label), password, style, options); - } - - /// *listonly* - public static string PasswordField(GUIContent label, string password, params GUILayoutOption[] options) - { - return PasswordField(label, password, EditorStyles.textField, options); - } - - // Make a text field where the user can enter a password. - public static string PasswordField(GUIContent label, string password, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.PasswordField(r, label, password, style); - } - - // Peak smoothing should be handled by client. Input: value and peak is normalized values (0 - 1). - internal static void VUMeterHorizontal(float value, float peak, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - EditorGUI.VUMeter.HorizontalMeter(r, value, peak, EditorGUI.VUMeter.horizontalVUTexture, Color.grey); - } - - // Auto-smoothing of peak - internal static void VUMeterHorizontal(float value, ref EditorGUI.VUMeter.SmoothingData data, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - EditorGUI.VUMeter.HorizontalMeter(r, value, ref data, EditorGUI.VUMeter.horizontalVUTexture, Color.grey); - } - - /// *listonly* - public static float FloatField(float value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.FloatField(r, value); - } - - /// *listonly* - public static float FloatField(float value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.FloatField(r, value, style); - } - - /// *listonly* - public static float FloatField(string label, float value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.FloatField(r, label, value); - } - - /// *listonly* - public static float FloatField(string label, float value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.FloatField(r, label, value, style); - } - - /// *listonly* - public static float FloatField(GUIContent label, float value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.FloatField(r, label, value); - } - - // Make a text field for entering float values. - public static float FloatField(GUIContent label, float value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.FloatField(r, label, value, style); - } - - /// *listonly* - public static float DelayedFloatField(float value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.DelayedFloatField(r, value); - } - - /// *listonly* - public static float DelayedFloatField(float value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedFloatField(r, value, style); - } - - /// *listonly* - public static float DelayedFloatField(string label, float value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.DelayedFloatField(r, label, value); - } - - /// *listonly* - public static float DelayedFloatField(string label, float value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedFloatField(r, label, value, style); - } - - /// *listonly* - public static float DelayedFloatField(GUIContent label, float value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.DelayedFloatField(r, label, value); - } - - // Make a delayed text field for entering float values. - public static float DelayedFloatField(GUIContent label, float value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedFloatField(r, label, value, style); - } - - /// *listonly* - public static void DelayedFloatField(SerializedProperty property, params GUILayoutOption[] options) - { - EditorGUILayout.DelayedFloatField(property, null, options); - } - - // Make a delayed text field for entering float values. - public static void DelayedFloatField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(EditorGUI.LabelHasContent(label), EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - EditorGUI.DelayedFloatField(r, property, label); - } - - /// *listonly* - public static double DoubleField(double value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.DoubleField(r, value); - } - - /// *listonly* - public static double DoubleField(double value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DoubleField(r, value, style); - } - - /// *listonly* - public static double DoubleField(string label, double value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.DoubleField(r, label, value); - } - - /// *listonly* - public static double DoubleField(string label, double value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DoubleField(r, label, value, style); - } - - /// *listonly* - public static double DoubleField(GUIContent label, double value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.DoubleField(r, label, value); - } - - // Make a text field for entering double values. - public static double DoubleField(GUIContent label, double value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DoubleField(r, label, value, style); - } - - /// *listonly* - public static double DelayedDoubleField(double value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.DelayedDoubleField(r, value); - } - - /// *listonly* - public static double DelayedDoubleField(double value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedDoubleField(r, value, style); - } - - /// *listonly* - public static double DelayedDoubleField(string label, double value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.DelayedDoubleField(r, label, value); - } - - /// *listonly* - public static double DelayedDoubleField(string label, double value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedDoubleField(r, label, value, style); - } - - /// *listonly* - public static double DelayedDoubleField(GUIContent label, double value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.DelayedDoubleField(r, label, value); - } - - // Make a delayed text field for entering double values. - public static double DelayedDoubleField(GUIContent label, double value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedDoubleField(r, label, value, style); - } - - /// *listonly* - public static int IntField(int value, params GUILayoutOption[] options) - { - return IntField(value, EditorStyles.numberField, options); - } - - /// *listonly* - public static int IntField(int value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.IntField(r, value, style); - } - - /// *listonly* - public static int IntField(string label, int value, params GUILayoutOption[] options) - { - return IntField(label, value, EditorStyles.numberField, options); - } - - /// *listonly* - public static int IntField(string label, int value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.IntField(r, label, value, style); - } - - /// *listonly* - public static int IntField(GUIContent label, int value, params GUILayoutOption[] options) - { - return IntField(label, value, EditorStyles.numberField, options); - } - - // Make a text field for entering integers. - public static int IntField(GUIContent label, int value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.IntField(r, label, value, style); - } - - /// *listonly* - public static int DelayedIntField(int value, params GUILayoutOption[] options) - { - return DelayedIntField(value, EditorStyles.numberField, options); - } - - /// *listonly* - public static int DelayedIntField(int value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedIntField(r, value, style); - } - - /// *listonly* - public static int DelayedIntField(string label, int value, params GUILayoutOption[] options) - { - return DelayedIntField(label, value, EditorStyles.numberField, options); - } - - /// *listonly* - public static int DelayedIntField(string label, int value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedIntField(r, label, value, style); - } - - /// *listonly* - public static int DelayedIntField(GUIContent label, int value, params GUILayoutOption[] options) - { - return DelayedIntField(label, value, EditorStyles.numberField, options); - } - - // Make a text field for entering integers. - public static int DelayedIntField(GUIContent label, int value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.DelayedIntField(r, label, value, style); - } - - /// *listonly* - public static void DelayedIntField(SerializedProperty property, params GUILayoutOption[] options) - { - DelayedIntField(property, null, options); - } - - // Make a text field for entering integers. - public static void DelayedIntField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(EditorGUI.LabelHasContent(label), EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - EditorGUI.DelayedIntField(r, property, label); - } - - /// *listonly* - public static long LongField(long value, params GUILayoutOption[] options) - { - return LongField(value, EditorStyles.numberField, options); - } - - /// *listonly* - public static long LongField(long value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.LongField(r, value, style); - } - - /// *listonly* - public static long LongField(string label, long value, params GUILayoutOption[] options) - { - return LongField(label, value, EditorStyles.numberField, options); - } - - /// *listonly* - public static long LongField(string label, long value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.LongField(r, label, value, style); - } - - /// *listonly* - public static long LongField(GUIContent label, long value, params GUILayoutOption[] options) - { - return LongField(label, value, EditorStyles.numberField, options); - } - - // Make a text field for entering integers. - public static long LongField(GUIContent label, long value, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.LongField(r, label, value, style); - } - - /// *listonly* - public static float Slider(float value, float leftValue, float rightValue, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(false, options); - return EditorGUI.Slider(r, value, leftValue, rightValue); - } - - /// *listonly* - public static float Slider(string label, float value, float leftValue, float rightValue, params GUILayoutOption[] options) - { - return Slider(EditorGUIUtility.TempContent(label), value, leftValue, rightValue, options); - } - - // Make a slider the user can drag to change a value between a min and a max. - public static float Slider(GUIContent label, float value, float leftValue, float rightValue, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(true, options); - return EditorGUI.Slider(r, label, value, leftValue, rightValue); - } - - /// *listonly* - public static void Slider(SerializedProperty property, float leftValue, float rightValue, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(false, options); - EditorGUI.Slider(r, property, leftValue, rightValue); - } - - /// *listonly* - public static void Slider(SerializedProperty property, float leftValue, float rightValue, string label, params GUILayoutOption[] options) - { - Slider(property, leftValue, rightValue, EditorGUIUtility.TempContent(label), options); - } - - // Make a slider the user can drag to change a value between a min and a max. - public static void Slider(SerializedProperty property, float leftValue, float rightValue, GUIContent label, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(true, options); - EditorGUI.Slider(r, property, leftValue, rightValue, label); - } - - /// *listonly* - internal static float PowerSlider(string label, float value, float leftValue, float rightValue, float power, params GUILayoutOption[] options) - { - return PowerSlider(EditorGUIUtility.TempContent(label), value, leftValue, rightValue, power, options); - } - - // Make a power slider the user can drag to change a value between a min and a max. - internal static float PowerSlider(GUIContent label, float value, float leftValue, float rightValue, float power, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(true, options); - return EditorGUI.PowerSlider(r, label, value, leftValue, rightValue, power); - } - - /// *listonly* - public static int IntSlider(int value, int leftValue, int rightValue, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(false, options); - return EditorGUI.IntSlider(r, value, leftValue, rightValue); - } - - /// *listonly* - public static int IntSlider(string label, int value, int leftValue, int rightValue, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(true, options); - return EditorGUI.IntSlider(r, label, value, leftValue, rightValue); - } - - // Make a slider the user can drag to change an integer value between a min and a max. - public static int IntSlider(GUIContent label, int value, int leftValue, int rightValue, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(true, options); - return EditorGUI.IntSlider(r, label, value, leftValue, rightValue); - } - - /// *listonly* - public static void IntSlider(SerializedProperty property, int leftValue, int rightValue, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(false, options); - EditorGUI.IntSlider(r, property, leftValue, rightValue, property.displayName); - } - - /// *listonly* - public static void IntSlider(SerializedProperty property, int leftValue, int rightValue, string label, params GUILayoutOption[] options) - { - IntSlider(property, leftValue, rightValue, EditorGUIUtility.TempContent(label), options); - } - - // Make a slider the user can drag to change an integer value between a min and a max. - public static void IntSlider(SerializedProperty property, int leftValue, int rightValue, GUIContent label, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(true, options); - EditorGUI.IntSlider(r, property, leftValue, rightValue, label); - } - - /// *listonly* - public static void MinMaxSlider(ref float minValue, ref float maxValue, float minLimit, float maxLimit, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(false, options); - EditorGUI.MinMaxSlider(r, ref minValue, ref maxValue, minLimit, maxLimit); - } - - /// *listonly* - public static void MinMaxSlider(string label, ref float minValue, ref float maxValue, float minLimit, float maxLimit, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(true, options); - EditorGUI.MinMaxSlider(r, label, ref minValue, ref maxValue, minLimit, maxLimit); - } - - // Make a special slider the user can use to specify a range between a min and a max. - public static void MinMaxSlider(GUIContent label, ref float minValue, ref float maxValue, float minLimit, float maxLimit, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetSliderRect(true, options); - EditorGUI.MinMaxSlider(r, label, ref minValue, ref maxValue, minLimit, maxLimit); - } - - /// *listonly* - public static int Popup(int selectedIndex, string[] displayedOptions, params GUILayoutOption[] options) - { - return Popup(selectedIndex, displayedOptions, EditorStyles.popup, options); - } - - /// *listonly* - public static int Popup(int selectedIndex, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.Popup(r, selectedIndex, displayedOptions, style); - } - - /// *listonly* - public static int Popup(int selectedIndex, GUIContent[] displayedOptions, params GUILayoutOption[] options) - { - return Popup(selectedIndex, displayedOptions, EditorStyles.popup, options); - } - - /// *listonly* - public static int Popup(int selectedIndex, GUIContent[] displayedOptions, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.Popup(r, selectedIndex, displayedOptions, style); - } - - /// *listonly* - public static int Popup(string label, int selectedIndex, string[] displayedOptions, params GUILayoutOption[] options) - { - return Popup(label, selectedIndex, displayedOptions, EditorStyles.popup, options); - } - - /// *listonly* - public static int Popup(GUIContent label, int selectedIndex, string[] displayedOptions, params GUILayoutOption[] options) - { - return Popup(label, selectedIndex, displayedOptions, EditorStyles.popup, options); - } - - /// *listonly* - public static int Popup(string label, int selectedIndex, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.Popup(r, label, selectedIndex, displayedOptions, style); - } - - /// *listonly* - public static int Popup(GUIContent label, int selectedIndex, GUIContent[] displayedOptions, params GUILayoutOption[] options) - { - return Popup(label, selectedIndex, displayedOptions, EditorStyles.popup, options); - } - - // Make a generic popup selection field. - public static int Popup(GUIContent label, int selectedIndex, GUIContent[] displayedOptions, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.Popup(r, label, selectedIndex, displayedOptions, style); - } - - internal static int Popup(GUIContent label, int selectedIndex, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.Popup(r, label, selectedIndex, displayedOptions, style); - } - - internal static void Popup(SerializedProperty property, GUIContent[] displayedOptions, params GUILayoutOption[] options) - { - Popup(property, displayedOptions, null, options); - } - - internal static void Popup(SerializedProperty property, GUIContent[] displayedOptions, GUIContent label, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup, options); - EditorGUI.Popup(r, property, displayedOptions, label); - } - - /// *listonly* - public static System.Enum EnumPopup(System.Enum selected, params GUILayoutOption[] options) - { - return EnumPopup(selected, EditorStyles.popup, options); - } - - /// *listonly* - public static System.Enum EnumPopup(System.Enum selected, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.EnumPopup(r, selected, style); - } - - /// *listonly* - public static System.Enum EnumPopup(string label, System.Enum selected, params GUILayoutOption[] options) - { - return EnumPopup(label, selected, EditorStyles.popup, options); - } - - /// *listonly* - public static System.Enum EnumPopup(string label, System.Enum selected, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.EnumPopup(r, GUIContent.Temp(label), selected, style); - } - - /// *listonly* - public static System.Enum EnumPopup(GUIContent label, System.Enum selected, params GUILayoutOption[] options) - { - return EnumPopup(label, selected, EditorStyles.popup, options); - } - - // Make an enum popup selection field. - public static System.Enum EnumPopup(GUIContent label, System.Enum selected, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.EnumPopup(r, label, selected, style); - } - - /// *listonly* - public static int IntPopup(int selectedValue, string[] displayedOptions, int[] optionValues, params GUILayoutOption[] options) - { - return IntPopup(selectedValue, displayedOptions, optionValues, EditorStyles.popup, options); - } - - /// *listonly* - public static int IntPopup(int selectedValue, string[] displayedOptions, int[] optionValues, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.IntPopup(r, selectedValue, displayedOptions, optionValues, style); - } - - /// *listonly* - public static int IntPopup(int selectedValue, GUIContent[] displayedOptions, int[] optionValues, params GUILayoutOption[] options) - { - return IntPopup(selectedValue, displayedOptions, optionValues, EditorStyles.popup, options); - } - - /// *listonly* - public static int IntPopup(int selectedValue, GUIContent[] displayedOptions, int[] optionValues, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.IntPopup(r, GUIContent.none, selectedValue, displayedOptions, optionValues, style); - } - - /// *listonly* - public static int IntPopup(string label, int selectedValue, string[] displayedOptions, int[] optionValues, params GUILayoutOption[] options) - { - return IntPopup(label, selectedValue, displayedOptions, optionValues, EditorStyles.popup, options); - } - - /// *listonly* - public static int IntPopup(string label, int selectedValue, string[] displayedOptions, int[] optionValues, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.IntPopup(r, label, selectedValue, displayedOptions, optionValues, style); - } - - /// *listonly* - public static int IntPopup(GUIContent label, int selectedValue, GUIContent[] displayedOptions, int[] optionValues, params GUILayoutOption[] options) - { - return IntPopup(label, selectedValue, displayedOptions, optionValues, EditorStyles.popup, options); - } - - // Make an integer popup selection field. - public static int IntPopup(GUIContent label, int selectedValue, GUIContent[] displayedOptions, int[] optionValues, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.IntPopup(r, label, selectedValue, displayedOptions, optionValues, style); - } - - /// *listonly* - public static void IntPopup(SerializedProperty property, GUIContent[] displayedOptions, int[] optionValues, params GUILayoutOption[] options) - { - IntPopup(property, displayedOptions, optionValues, null, options); - } - - // Make an integer popup selection field. - public static void IntPopup(SerializedProperty property, GUIContent[] displayedOptions, int[] optionValues, GUIContent label, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup, options); - EditorGUI.IntPopup(r, property, displayedOptions, optionValues, label); - } - - [System.Obsolete("This function is obsolete and the style is not used.")] - public static void IntPopup(SerializedProperty property, GUIContent[] displayedOptions, int[] optionValues, GUIContent label, GUIStyle style, params GUILayoutOption[] options) - { - IntPopup(property, displayedOptions, optionValues, label, options); - } - - /// *listonly* - public static string TagField(string tag, params GUILayoutOption[] options) - { - return TagField(tag, EditorStyles.popup, options); - } - - /// *listonly* - public static string TagField(string tag, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.TagField(r, tag, style); - } - - /// *listonly* - public static string TagField(string label, string tag, params GUILayoutOption[] options) - { - return TagField(EditorGUIUtility.TempContent(label), tag, EditorStyles.popup, options); - } - - /// *listonly* - public static string TagField(string label, string tag, GUIStyle style, params GUILayoutOption[] options) - { - return TagField(EditorGUIUtility.TempContent(label), tag, style, options); - } - - /// *listonly* - public static string TagField(GUIContent label, string tag, params GUILayoutOption[] options) - { - return TagField(label, tag, EditorStyles.popup, options); - } - - // Make a tag selection field. - public static string TagField(GUIContent label, string tag, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.TagField(r, label, tag, style); - } - - /// *listonly* - public static int LayerField(int layer, params GUILayoutOption[] options) - { - return LayerField(layer, EditorStyles.popup, options); - } - - /// *listonly* - public static int LayerField(int layer, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.LayerField(r, layer, style); - } - - /// *listonly* - public static int LayerField(string label, int layer, params GUILayoutOption[] options) - { - return LayerField(EditorGUIUtility.TempContent(label), layer, EditorStyles.popup, options); - } - - /// *listonly* - public static int LayerField(string label, int layer, GUIStyle style, params GUILayoutOption[] options) - { - return LayerField(EditorGUIUtility.TempContent(label), layer, style, options); - } - - /// *listonly* - public static int LayerField(GUIContent label, int layer, params GUILayoutOption[] options) - { - return LayerField(label, layer, EditorStyles.popup, options); - } - - // Make a layer selection field. - public static int LayerField(GUIContent label, int layer, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.LayerField(r, label, layer, style); - } - - /// *listonly* - public static int MaskField(GUIContent label, int mask, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options) - { - var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.MaskField(r, label, mask, displayedOptions, style); - } - - /// *listonly* - public static int MaskField(string label, int mask, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options) - { - var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.MaskField(r, label, mask, displayedOptions, style); - } - - /// *listonly* - public static int MaskField(GUIContent label, int mask, string[] displayedOptions, params GUILayoutOption[] options) - { - var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup, options); - return EditorGUI.MaskField(r, label, mask, displayedOptions, EditorStyles.popup); - } - - /// *listonly* - public static int MaskField(string label, int mask, string[] displayedOptions, params GUILayoutOption[] options) - { - var r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup, options); - return EditorGUI.MaskField(r, label, mask, displayedOptions, EditorStyles.popup); - } - - /// *listonly* - public static int MaskField(int mask, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options) - { - var r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.MaskField(r, mask, displayedOptions, style); - } - - // Make a field for masks. - public static int MaskField(int mask, string[] displayedOptions, params GUILayoutOption[] options) - { - var r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.popup, options); - return EditorGUI.MaskField(r, mask, displayedOptions, EditorStyles.popup); - } - - public static Enum EnumFlagsField(Enum enumValue, params GUILayoutOption[] options) - { - return EnumFlagsField(enumValue, EditorStyles.popup, options); - } - - public static Enum EnumFlagsField(Enum enumValue, GUIStyle style, params GUILayoutOption[] options) - { - var position = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.EnumFlagsField(position, enumValue, style); - } - - public static Enum EnumFlagsField(string label, Enum enumValue, params GUILayoutOption[] options) - { - return EnumFlagsField(label, enumValue, EditorStyles.popup, options); - } - - public static Enum EnumFlagsField(string label, Enum enumValue, GUIStyle style, params GUILayoutOption[] options) - { - return EnumFlagsField(EditorGUIUtility.TempContent(label), enumValue, style, options); - } - - public static Enum EnumFlagsField(GUIContent label, Enum enumValue, params GUILayoutOption[] options) - { - return EnumFlagsField(label, enumValue, EditorStyles.popup, options); - } - - public static Enum EnumFlagsField(GUIContent label, Enum enumValue, GUIStyle style, params GUILayoutOption[] options) - { - var position = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.EnumFlagsField(position, label, enumValue, style); - } - - [System.Obsolete("Check the docs for the usage of the new parameter 'allowSceneObjects'.")] - public static Object ObjectField(Object obj, System.Type objType, params GUILayoutOption[] options) - { - return ObjectField(obj, objType, true, options); - } - - /// *listonly* - public static Object ObjectField(Object obj, System.Type objType, bool allowSceneObjects, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, options); - return EditorGUI.ObjectField(r, obj, objType, allowSceneObjects); - } - - [System.Obsolete("Check the docs for the usage of the new parameter 'allowSceneObjects'.")] - public static Object ObjectField(string label, Object obj, System.Type objType, params GUILayoutOption[] options) - { - return ObjectField(label, obj, objType, true, options); - } - - /// *listonly* - public static Object ObjectField(string label, Object obj, System.Type objType, bool allowSceneObjects, params GUILayoutOption[] options) - { - return ObjectField(EditorGUIUtility.TempContent(label), obj, objType, allowSceneObjects, options); - } - - [System.Obsolete("Check the docs for the usage of the new parameter 'allowSceneObjects'.")] - public static Object ObjectField(GUIContent label, Object obj, System.Type objType, params GUILayoutOption[] options) - { - return ObjectField(label, obj, objType, true, options); - } - - // Make an object field. You can assign objects either by drag'n drop objects or by selecting an object using the Object Picker. - public static Object ObjectField(GUIContent label, Object obj, System.Type objType, bool allowSceneObjects, params GUILayoutOption[] options) - { - float height; - if (EditorGUIUtility.HasObjectThumbnail(objType)) - { - height = EditorGUI.kObjectFieldThumbnailHeight; - } - else - { - height = EditorGUI.kSingleLineHeight; - } - Rect r = s_LastRect = GetControlRect(true, height, options); - return EditorGUI.ObjectField(r, label, obj, objType, allowSceneObjects); - } - - /// *listonly* - public static void ObjectField(SerializedProperty property, params GUILayoutOption[] options) - { - ObjectField(property, (GUIContent)null, options); - } - - /// *listonly* - public static void ObjectField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.objectField, options); - EditorGUI.ObjectField(r, property, label); - } - - /// *listonly* - public static void ObjectField(SerializedProperty property, System.Type objType, params GUILayoutOption[] options) - { - ObjectField(property, objType, null, options); - } - - // Make an object field. You can assign objects either by drag'n drop objects or by selecting an object using the Object Picker. - public static void ObjectField(SerializedProperty property, System.Type objType, GUIContent label, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.objectField, options); - EditorGUI.ObjectField(r, property, objType, label); - } - - internal static Object MiniThumbnailObjectField(GUIContent label, Object obj, System.Type objType, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options); - return EditorGUI.MiniThumbnailObjectField(r, label, obj, objType); - } - - /// *listonly* - public static Vector2 Vector2Field(string label, Vector2 value, params GUILayoutOption[] options) - { - return Vector2Field(EditorGUIUtility.TempContent(label), value, options); - } - - // Make an X & Y field for entering a [[Vector2]]. - public static Vector2 Vector2Field(GUIContent label, Vector2 value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector2, label), EditorStyles.numberField, options); - return EditorGUI.Vector2Field(r, label, value); - } - - /// *listonly* - public static Vector3 Vector3Field(string label, Vector3 value, params GUILayoutOption[] options) - { - return Vector3Field(EditorGUIUtility.TempContent(label), value, options); - } - - // Make an X, Y & Z field for entering a [[Vector3]]. - public static Vector3 Vector3Field(GUIContent label, Vector3 value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, label), EditorStyles.numberField, options); - return EditorGUI.Vector3Field(r, label, value); - } - - // Make an X, Y, Z & W field for entering a [[Vector4]]. - public static Vector4 Vector4Field(string label, Vector4 value, params GUILayoutOption[] options) - { - return Vector4Field(EditorGUIUtility.TempContent(label), value, options); - } - - // Make an X, Y, Z & W field for entering a [[Vector4]]. - public static Vector4 Vector4Field(GUIContent label, Vector4 value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector4, label), EditorStyles.numberField, options); - return EditorGUI.Vector4Field(r, label, value); - } - - /// *listonly* - public static Vector2Int Vector2IntField(string label, Vector2Int value, params GUILayoutOption[] options) - { - return Vector2IntField(EditorGUIUtility.TempContent(label), value, options); - } - - // Make an X & Y field for entering a [[Vector2Int]]. - public static Vector2Int Vector2IntField(GUIContent label, Vector2Int value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector2Int, label), EditorStyles.numberField, options); - return EditorGUI.Vector2IntField(r, label, value); - } - - /// *listonly* - public static Vector3Int Vector3IntField(string label, Vector3Int value, params GUILayoutOption[] options) - { - return Vector3IntField(EditorGUIUtility.TempContent(label), value, options); - } - - // Make an X, Y & Z field for entering a [[Vector3Int]]. - public static Vector3Int Vector3IntField(GUIContent label, Vector3Int value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3Int, label), EditorStyles.numberField, options); - return EditorGUI.Vector3IntField(r, label, value); - } - - /// *listonly* - public static Rect RectField(Rect value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.GetPropertyHeight(SerializedPropertyType.Rect, GUIContent.none), EditorStyles.numberField, options); - return EditorGUI.RectField(r, value); - } - - /// *listonly* - public static Rect RectField(string label, Rect value, params GUILayoutOption[] options) - { - return RectField(EditorGUIUtility.TempContent(label), value, options); - } - - // Make an X, Y, W & H field for entering a [[Rect]]. - public static Rect RectField(GUIContent label, Rect value, params GUILayoutOption[] options) - { - bool hasLabel = EditorGUI.LabelHasContent(label); - float height = EditorGUI.GetPropertyHeight(SerializedPropertyType.Rect, label); - Rect r = s_LastRect = GetControlRect(hasLabel, height, EditorStyles.numberField, options); - return EditorGUI.RectField(r, label, value); - } - - /// *listonly* - public static RectInt RectIntField(RectInt value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.GetPropertyHeight(SerializedPropertyType.RectInt, GUIContent.none), EditorStyles.numberField, options); - return EditorGUI.RectIntField(r, value); - } - - /// *listonly* - public static RectInt RectIntField(string label, RectInt value, params GUILayoutOption[] options) - { - return RectIntField(EditorGUIUtility.TempContent(label), value, options); - } - - // Make an X, Y, W & H field for entering a [[RectInt]]. - public static RectInt RectIntField(GUIContent label, RectInt value, params GUILayoutOption[] options) - { - bool hasLabel = EditorGUI.LabelHasContent(label); - float height = EditorGUI.GetPropertyHeight(SerializedPropertyType.RectInt, label); - Rect r = s_LastRect = GetControlRect(hasLabel, height, EditorStyles.numberField, options); - return EditorGUI.RectIntField(r, label, value); - } - - /// *listonly* - public static Bounds BoundsField(Bounds value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.GetPropertyHeight(SerializedPropertyType.Bounds, GUIContent.none), EditorStyles.numberField, options); - return EditorGUI.BoundsField(r, value); - } - - /// *listonly* - public static Bounds BoundsField(string label, Bounds value, params GUILayoutOption[] options) - { - return BoundsField(EditorGUIUtility.TempContent(label), value, options); - } - - // Make Center & Extents field for entering a [[Bounds]]. - public static Bounds BoundsField(GUIContent label, Bounds value, params GUILayoutOption[] options) - { - bool hasLabel = EditorGUI.LabelHasContent(label); - float height = EditorGUI.GetPropertyHeight(SerializedPropertyType.Bounds, label); - Rect r = s_LastRect = GetControlRect(hasLabel, height, EditorStyles.numberField, options); - return EditorGUI.BoundsField(r, label, value); - } - - /// *listonly* - public static BoundsInt BoundsIntField(BoundsInt value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.GetPropertyHeight(SerializedPropertyType.BoundsInt, GUIContent.none), EditorStyles.numberField, options); - return EditorGUI.BoundsIntField(r, value); - } - - /// *listonly* - public static BoundsInt BoundsIntField(string label, BoundsInt value, params GUILayoutOption[] options) - { - return BoundsIntField(EditorGUIUtility.TempContent(label), value, options); - } - - // Make Center & Extents field for entering a [[BoundsInt]]. - public static BoundsInt BoundsIntField(GUIContent label, BoundsInt value, params GUILayoutOption[] options) - { - bool hasLabel = EditorGUI.LabelHasContent(label); - float height = EditorGUI.GetPropertyHeight(SerializedPropertyType.BoundsInt, label); - Rect r = s_LastRect = GetControlRect(hasLabel, height, EditorStyles.numberField, options); - return EditorGUI.BoundsIntField(r, label, value); - } - - // Make a property field that look like a multi property field (but is made up of individual properties) - internal static void PropertiesField(GUIContent label, SerializedProperty[] properties, GUIContent[] propertyLabels, float propertyLabelsWidth, params GUILayoutOption[] options) - { - bool hasLabel = EditorGUI.LabelHasContent(label); - float height = EditorGUI.kSingleLineHeight * properties.Length + EditorGUI.kVerticalSpacingMultiField * (properties.Length - 1); - Rect r = s_LastRect = GetControlRect(hasLabel, height, EditorStyles.numberField, options); - EditorGUI.PropertiesField(r, label, properties, propertyLabels, propertyLabelsWidth); - } - - internal static int CycleButton(int selected, GUIContent[] options, GUIStyle style) - { - if (GUILayout.Button(options[selected], style)) - { - selected++; - if (selected >= options.Length) - { - selected = 0; - } - } - return selected; - } - - /// *listonly* - public static Color ColorField(Color value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.ColorField(r, value); - } - - /// *listonly* - public static Color ColorField(string label, Color value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.ColorField(r, label, value); - } - - // Make a field for selecting a [[Color]]. - public static Color ColorField(GUIContent label, Color value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.ColorField(r, label, value); - } - - #pragma warning disable 612 - [Obsolete("Use EditorGUILayout.ColorField(GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, params GUILayoutOption[] options)")] - public static Color ColorField( - GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, ColorPickerHDRConfig hdrConfig, params GUILayoutOption[] options - ) - { - return ColorField(label, value, showEyedropper, showAlpha, hdr); - } - - #pragma warning restore 612 - - public static Color ColorField(GUIContent label, Color value, bool showEyedropper, bool showAlpha, bool hdr, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.ColorField(r, label, value, showEyedropper, showAlpha, hdr); - } - - /// *listonly* - public static AnimationCurve CurveField(AnimationCurve value, params GUILayoutOption[] options) - { - // TODO Change style - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.CurveField(r, value); - } - - /// *listonly* - public static AnimationCurve CurveField(string label, AnimationCurve value, params GUILayoutOption[] options) - { - // TODO Change style - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.CurveField(r, label, value); - } - - /// *listonly* - public static AnimationCurve CurveField(GUIContent label, AnimationCurve value, params GUILayoutOption[] options) - { - // TODO Change style - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.CurveField(r, label, value); - } - - // Variants with settings - /// *listonly* - public static AnimationCurve CurveField(AnimationCurve value, Color color, Rect ranges, params GUILayoutOption[] options) - { - // TODO Change style - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.CurveField(r, value, color, ranges); - } - - /// *listonly* - public static AnimationCurve CurveField(string label, AnimationCurve value, Color color, Rect ranges, params GUILayoutOption[] options) - { - // TODO Change style - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.CurveField(r, label, value, color, ranges); - } - - // Make a field for editing an [[AnimationCurve]]. - public static AnimationCurve CurveField(GUIContent label, AnimationCurve value, Color color, Rect ranges, params GUILayoutOption[] options) - { - // TODO Change style - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.CurveField(r, label, value, color, ranges); - } - - /// *listonly* - public static void CurveField(SerializedProperty property, Color color, Rect ranges, params GUILayoutOption[] options) - { - CurveField(property, color, ranges, null, options); - } - - // Make a field for editing an [[AnimationCurve]]. - public static void CurveField(SerializedProperty property, Color color, Rect ranges, GUIContent label, params GUILayoutOption[] options) - { - // TODO Change style - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - EditorGUI.CurveField(r, property, color, ranges, label); - } - - /// *listonly* - public static bool InspectorTitlebar(bool foldout, Object targetObj) - { - return InspectorTitlebar(foldout, targetObj, true); - } - - public static bool InspectorTitlebar(bool foldout, Object targetObj, bool expandable) - { - return EditorGUI.InspectorTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), foldout, - targetObj, expandable); - } - - // Make an inspector-window-like titlebar. - public static bool InspectorTitlebar(bool foldout, Object[] targetObjs) - { - return InspectorTitlebar(foldout, targetObjs, true); - } - - public static bool InspectorTitlebar(bool foldout, Object[] targetObjs, bool expandable) - { - return EditorGUI.InspectorTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), foldout, - targetObjs, expandable); - } - - public static void InspectorTitlebar(Object[] targetObjs) - { - EditorGUI.InspectorTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), targetObjs); - } - - // Make an foldout with a toggle and title - internal static bool ToggleTitlebar(bool foldout, GUIContent label, ref bool toggleValue) - { - return EditorGUI.ToggleTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), label, foldout, ref toggleValue); - } - - internal static bool ToggleTitlebar(bool foldout, GUIContent label, SerializedProperty property) - { - bool toggleValue = property.boolValue; - EditorGUI.BeginChangeCheck(); - foldout = EditorGUI.ToggleTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), label, foldout, ref toggleValue); - if (EditorGUI.EndChangeCheck()) - property.boolValue = toggleValue; - - return foldout; - } - - internal static bool FoldoutTitlebar(bool foldout, GUIContent label, bool skipIconSpacing) - { - return EditorGUI.FoldoutTitlebar(GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar), label, foldout, skipIconSpacing); - } - - // Make a label with a foldout arrow to the left of it. - internal static bool FoldoutInternal(bool foldout, GUIContent content, bool toggleOnLabelClick, GUIStyle style) - { - Rect r = s_LastRect = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, EditorGUIUtility.fieldWidth, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, style); - return EditorGUI.Foldout(r, foldout, content, toggleOnLabelClick, style); - } - - internal static void LayerMaskField(UInt32 layers, GUIContent label, EditorUtility.SelectMenuItemFunction callback, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options); - EditorGUI.LayerMaskField(r, layers, label, callback); - } - - internal static void LayerMaskField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, options); - EditorGUI.LayerMaskField(r, property, label); - } - - /// *listonly* - public static void HelpBox(string message, MessageType type) - { - EditorGUILayout.LabelField(GUIContent.none, EditorGUIUtility.TempContent(message, EditorGUIUtility.GetHelpIcon(type)), EditorStyles.helpBox); - } - - // Make a help box with a message to the user. - public static void HelpBox(string message, MessageType type, bool wide) - { - EditorGUILayout.LabelField(wide ? GUIContent.none : EditorGUIUtility.blankContent, - EditorGUIUtility.TempContent(message, EditorGUIUtility.GetHelpIcon(type)), - EditorStyles.helpBox); - } - - // Make a help box with a message to the user. - public static void HelpBox(GUIContent content, bool wide = true) - { - EditorGUILayout.LabelField(wide ? GUIContent.none : EditorGUIUtility.blankContent, - content, - EditorStyles.helpBox); - } - - // Make a label in front of some control. - internal static void PrefixLabelInternal(GUIContent label, GUIStyle followingStyle, GUIStyle labelStyle) - { - float p = followingStyle.margin.left; - if (!EditorGUI.LabelHasContent(label)) - { - GUILayoutUtility.GetRect(EditorGUI.indent - p, EditorGUI.kSingleLineHeight, followingStyle, GUILayout.ExpandWidth(false)); - return; - } - - Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.labelWidth - p, EditorGUI.kSingleLineHeight, followingStyle, GUILayout.ExpandWidth(false)); - r.xMin += EditorGUI.indent; - EditorGUI.HandlePrefixLabel(r, r, label, 0, labelStyle); - } - - // Make a small space between the previous control and the following. - public static void Space() - { - GUILayoutUtility.GetRect(6, 6); - } - - //[System.Obsolete ("Use Space() instead")] - // Make this function Obsolete when someone has time to _rename_ all - // the Standard Packages to Space(), as currently it shows tons of - // warnings. - // Same for the graphic tests. - // *undoc* - public static void Separator() - { - Space(); - } - - public class ToggleGroupScope : GUI.Scope - { - public bool enabled { get; protected set; } - - public ToggleGroupScope(string label, bool toggle) - { - enabled = BeginToggleGroup(label, toggle); - } - - public ToggleGroupScope(GUIContent label, bool toggle) - { - enabled = BeginToggleGroup(label, toggle); - } - - protected override void CloseScope() - { - EndToggleGroup(); - } - } - - /// *listonly* - public static bool BeginToggleGroup(string label, bool toggle) - { - return BeginToggleGroup(EditorGUIUtility.TempContent(label), toggle); - } - - // Begin a vertical group with a toggle to enable or disable all the controls within at once. - public static bool BeginToggleGroup(GUIContent label, bool toggle) - { - toggle = EditorGUILayout.ToggleLeft(label, toggle, EditorStyles.boldLabel); - EditorGUI.BeginDisabled(!toggle); - GUILayout.BeginVertical(); - - return toggle; - } - - // Close a group started with ::ref::BeginToggleGroup - public static void EndToggleGroup() - { - GUILayout.EndVertical(); - EditorGUI.EndDisabled(); - } - - public class HorizontalScope : GUI.Scope - { - public Rect rect { get; protected set; } - - public HorizontalScope(params GUILayoutOption[] options) - { - rect = BeginHorizontal(options); - } - - public HorizontalScope(GUIStyle style, params GUILayoutOption[] options) - { - rect = BeginHorizontal(style, options); - } - - internal HorizontalScope(GUIContent content, GUIStyle style, params GUILayoutOption[] options) - { - rect = BeginHorizontal(content, style, options); - } - - protected override void CloseScope() - { - EndHorizontal(); - } - } - - /// *listonly* - public static Rect BeginHorizontal(params GUILayoutOption[] options) - { - return BeginHorizontal(GUIContent.none, GUIStyle.none, options); - } - - // Begin a horizontal group and get its rect back. - public static Rect BeginHorizontal(GUIStyle style, params GUILayoutOption[] options) - { - return BeginHorizontal(GUIContent.none, style, options); - } - - // public static Rect BeginHorizontal (string text, params GUILayoutOption[] options) { return BeginHorizontal (EditorGUIUtility.TempContent (text), GUIStyle.none, options); } - /// *listonly* - // public static Rect BeginHorizontal (Texture image, params GUILayoutOption[] options) { return BeginHorizontal (EditorGUIUtility.TempContent (image), GUIStyle.none, options); } - /// *listonly* - // public static Rect BeginHorizontal (GUIContent content, params GUILayoutOption[] options) { return BeginHorizontal (content, GUIStyle.none, options); } - /// *listonly* - // public static Rect BeginHorizontal (string text, GUIStyle style, params GUILayoutOption[] options) { return BeginHorizontal (EditorGUIUtility.TempContent (text), style, options); } - /// *listonly* - // public static Rect BeginHorizontal (Texture image, GUIStyle style, params GUILayoutOption[] options) { return BeginHorizontal (EditorGUIUtility.TempContent (image), style, options); } - internal static Rect BeginHorizontal(GUIContent content, GUIStyle style, params GUILayoutOption[] options) - { - GUILayoutGroup g = GUILayoutUtility.BeginLayoutGroup(style, options, typeof(GUILayoutGroup)); - g.isVertical = false; - if (style != GUIStyle.none || content != GUIContent.none) - { - GUI.Box(g.rect, GUIContent.none, style); - } - return g.rect; - } - - // Close a group started with BeginHorizontal - public static void EndHorizontal() - { - GUILayout.EndHorizontal(); - } - - public class VerticalScope : GUI.Scope - { - public Rect rect { get; protected set; } - - public VerticalScope(params GUILayoutOption[] options) - { - rect = BeginVertical(options); - } - - public VerticalScope(GUIStyle style, params GUILayoutOption[] options) - { - rect = BeginVertical(style, options); - } - - internal VerticalScope(GUIContent content, GUIStyle style, params GUILayoutOption[] options) - { - rect = BeginVertical(content, style, options); - } - - protected override void CloseScope() - { - EndVertical(); - } - } - - /// *listonly* - public static Rect BeginVertical(params GUILayoutOption[] options) - { - return BeginVertical(GUIContent.none, GUIStyle.none, options); - } - - // Begin a vertical group and get its rect back. - public static Rect BeginVertical(GUIStyle style, params GUILayoutOption[] options) - { - return BeginVertical(GUIContent.none, style, options); - } - - /// *listonly* - // public static Rect BeginVertical (string text, params GUILayoutOption[] options) { return BeginVertical (EditorGUIUtility.TempContent (text), GUIStyle.none, options); } - /// *listonly* - // public static Rect BeginVertical (Texture image, params GUILayoutOption[] options) { return BeginVertical (EditorGUIUtility.TempContent (image), GUIStyle.none, options); } - /// *listonly* - // public static Rect BeginVertical (GUIContent content, params GUILayoutOption[] options) { return BeginVertical (content, GUIStyle.none, options); } - /// *listonly* - // public static Rect BeginVertical (string text, GUIStyle style, params GUILayoutOption[] options) { return BeginVertical (EditorGUIUtility.TempContent (text), style, options); } - /// *listonly* - // public static Rect BeginVertical (Texture image, GUIStyle style, params GUILayoutOption[] options) { return BeginVertical (EditorGUIUtility.TempContent (image), style, options); } - internal static Rect BeginVertical(GUIContent content, GUIStyle style, params GUILayoutOption[] options) - { - GUILayoutGroup g = GUILayoutUtility.BeginLayoutGroup(style, options, typeof(GUILayoutGroup)); - g.isVertical = true; - if (style != GUIStyle.none || content != GUIContent.none) - { - GUI.Box(g.rect, GUIContent.none, style); - } - return g.rect; - } - - // Close a group started with BeginVertical - public static void EndVertical() - { - GUILayout.EndVertical(); - } - - public class ScrollViewScope : GUI.Scope - { - public Vector2 scrollPosition { get; protected set; } - public bool handleScrollWheel { get; set; } - - public ScrollViewScope(Vector2 scrollPosition, params GUILayoutOption[] options) - { - handleScrollWheel = true; - this.scrollPosition = BeginScrollView(scrollPosition, options); - } - - public ScrollViewScope(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, params GUILayoutOption[] options) - { - handleScrollWheel = true; - this.scrollPosition = BeginScrollView(scrollPosition, alwaysShowHorizontal, alwaysShowVertical, options); - } - - public ScrollViewScope(Vector2 scrollPosition, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, params GUILayoutOption[] options) - { - handleScrollWheel = true; - this.scrollPosition = BeginScrollView(scrollPosition, horizontalScrollbar, verticalScrollbar, options); - } - - public ScrollViewScope(Vector2 scrollPosition, GUIStyle style, params GUILayoutOption[] options) - { - handleScrollWheel = true; - this.scrollPosition = BeginScrollView(scrollPosition, style, options); - } - - public ScrollViewScope(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options) - { - handleScrollWheel = true; - this.scrollPosition = BeginScrollView(scrollPosition, alwaysShowHorizontal, alwaysShowVertical, horizontalScrollbar, verticalScrollbar, background, options); - } - - internal ScrollViewScope(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, params GUILayoutOption[] options) - { - handleScrollWheel = true; - this.scrollPosition = BeginScrollView(scrollPosition, alwaysShowHorizontal, alwaysShowVertical, horizontalScrollbar, verticalScrollbar, options); - } - - protected override void CloseScope() - { - EndScrollView(handleScrollWheel); - } - } - - /// *listonly* - public static Vector2 BeginScrollView(Vector2 scrollPosition, params GUILayoutOption[] options) - { - return BeginScrollView(scrollPosition, false, false, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUI.skin.scrollView, options); - } - - /// *listonly* - public static Vector2 BeginScrollView(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, params GUILayoutOption[] options) - { - return BeginScrollView(scrollPosition, alwaysShowHorizontal, alwaysShowVertical, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUI.skin.scrollView, options); - } - - /// *listonly* - public static Vector2 BeginScrollView(Vector2 scrollPosition, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, params GUILayoutOption[] options) - { - return BeginScrollView(scrollPosition, false, false, horizontalScrollbar, verticalScrollbar, GUI.skin.scrollView, options); - } - - /// *listonly* - public static Vector2 BeginScrollView(Vector2 scrollPosition, GUIStyle style, params GUILayoutOption[] options) - { - string name = style.name; - - GUIStyle vertical = GUI.skin.FindStyle(name + "VerticalScrollbar"); - if (vertical == null) - { - vertical = GUI.skin.verticalScrollbar; - } - GUIStyle horizontal = GUI.skin.FindStyle(name + "HorizontalScrollbar"); - if (horizontal == null) - { - horizontal = GUI.skin.horizontalScrollbar; - } - return BeginScrollView(scrollPosition, false, false, horizontal, vertical, style, options); - } - - internal static Vector2 BeginScrollView(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, params GUILayoutOption[] options) - { - return BeginScrollView(scrollPosition, alwaysShowHorizontal, alwaysShowVertical, horizontalScrollbar, verticalScrollbar, GUI.skin.scrollView, options); - } - - // Begin an automatically layouted scrollview. - public static Vector2 BeginScrollView(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options) - { - GUIScrollGroup g = (GUIScrollGroup)GUILayoutUtility.BeginLayoutGroup(background, null, typeof(GUIScrollGroup)); - switch (Event.current.type) - { - case EventType.Layout: - g.resetCoords = true; - g.isVertical = true; - g.stretchWidth = 1; - g.stretchHeight = 1; - g.verticalScrollbar = verticalScrollbar; - g.horizontalScrollbar = horizontalScrollbar; - g.ApplyOptions(options); - break; - default: - break; - } - return EditorGUIInternal.DoBeginScrollViewForward(g.rect, scrollPosition, new Rect(0, 0, g.clientWidth, g.clientHeight), alwaysShowHorizontal, alwaysShowVertical, horizontalScrollbar, verticalScrollbar, background); - } - - internal class VerticalScrollViewScope : GUI.Scope - { - public Vector2 scrollPosition { get; protected set; } - public bool handleScrollWheel { get; set; } - - public VerticalScrollViewScope(Vector2 scrollPosition, params GUILayoutOption[] options) - { - handleScrollWheel = true; - this.scrollPosition = BeginVerticalScrollView(scrollPosition, options); - } - - public VerticalScrollViewScope(Vector2 scrollPosition, bool alwaysShowVertical, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options) - { - handleScrollWheel = true; - this.scrollPosition = BeginVerticalScrollView(scrollPosition, alwaysShowVertical, verticalScrollbar, background, options); - } - - protected override void CloseScope() - { - EndScrollView(handleScrollWheel); - } - } - - internal static Vector2 BeginVerticalScrollView(Vector2 scrollPosition, params GUILayoutOption[] options) - { - return BeginVerticalScrollView(scrollPosition, false, GUI.skin.verticalScrollbar, GUI.skin.scrollView, options); - } - - // Begin an automatically layouted scrollview. - internal static Vector2 BeginVerticalScrollView(Vector2 scrollPosition, bool alwaysShowVertical, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options) - { - GUIScrollGroup g = (GUIScrollGroup)GUILayoutUtility.BeginLayoutGroup(background, null, typeof(GUIScrollGroup)); - switch (Event.current.type) - { - case EventType.Layout: - g.resetCoords = true; - g.isVertical = true; - g.stretchWidth = 1; - g.stretchHeight = 1; - g.verticalScrollbar = verticalScrollbar; - g.horizontalScrollbar = GUIStyle.none; - g.allowHorizontalScroll = false; - g.ApplyOptions(options); - break; - default: - break; - } - return EditorGUIInternal.DoBeginScrollViewForward(g.rect, scrollPosition, new Rect(0, 0, g.clientWidth, g.clientHeight), false, alwaysShowVertical, GUI.skin.horizontalScrollbar, verticalScrollbar, background); - } - - internal class HorizontalScrollViewScope : GUI.Scope - { - public Vector2 scrollPosition { get; protected set; } - public bool handleScrollWheel { get; set; } - - public HorizontalScrollViewScope(Vector2 scrollPosition, params GUILayoutOption[] options) - { - handleScrollWheel = true; - this.scrollPosition = BeginHorizontalScrollView(scrollPosition, options); - } - - public HorizontalScrollViewScope(Vector2 scrollPosition, bool alwaysShowHorizontal, GUIStyle horizontalScrollbar, GUIStyle background, params GUILayoutOption[] options) - { - handleScrollWheel = true; - this.scrollPosition = BeginHorizontalScrollView(scrollPosition, alwaysShowHorizontal, horizontalScrollbar, background, options); - } - - protected override void CloseScope() - { - EndScrollView(handleScrollWheel); - } - } - - internal static Vector2 BeginHorizontalScrollView(Vector2 scrollPosition, params GUILayoutOption[] options) - { - return BeginHorizontalScrollView(scrollPosition, false, GUI.skin.horizontalScrollbar, GUI.skin.scrollView, options); - } - - // Begin an automatically layouted scrollview. - - internal static Vector2 BeginHorizontalScrollView(Vector2 scrollPosition, bool alwaysShowHorizontal, GUIStyle horizontalScrollbar, GUIStyle background, params GUILayoutOption[] options) - { - GUIScrollGroup g = (GUIScrollGroup)GUILayoutUtility.BeginLayoutGroup(background, null, typeof(GUIScrollGroup)); - switch (Event.current.type) - { - case EventType.Layout: - g.resetCoords = true; - g.isVertical = true; - g.stretchWidth = 1; - g.stretchHeight = 1; - g.verticalScrollbar = GUIStyle.none; - g.horizontalScrollbar = horizontalScrollbar; - g.allowHorizontalScroll = true; - g.allowVerticalScroll = false; - g.ApplyOptions(options); - break; - default: - break; - } - return EditorGUIInternal.DoBeginScrollViewForward(g.rect, scrollPosition, new Rect(0, 0, g.clientWidth, g.clientHeight), alwaysShowHorizontal, false, horizontalScrollbar, GUI.skin.verticalScrollbar, background); - } - - // Ends a scrollview started with a call to BeginScrollView. - public static void EndScrollView() - { - GUILayout.EndScrollView(true); - } - - internal static void EndScrollView(bool handleScrollWheel) - { - GUILayout.EndScrollView(handleScrollWheel); - } - - /// *listonly* - public static bool PropertyField(SerializedProperty property, params GUILayoutOption[] options) - { - return PropertyField(property, null, false, options); - } - - /// *listonly* - public static bool PropertyField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options) - { - return PropertyField(property, label, false, options); - } - - /// *listonly* - public static bool PropertyField(SerializedProperty property, bool includeChildren, params GUILayoutOption[] options) - { - return PropertyField(property, null, includeChildren, options); - } - - // Make a field for [[SerializedProperty]]. - public static bool PropertyField(SerializedProperty property, GUIContent label, bool includeChildren, params GUILayoutOption[] options) - { - return ScriptAttributeUtility.GetHandler(property).OnGUILayout(property, label, includeChildren, options); - } - - public static Rect GetControlRect(params GUILayoutOption[] options) - { - return GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.layerMaskField, options); - } - - public static Rect GetControlRect(bool hasLabel, params GUILayoutOption[] options) - { - return GetControlRect(hasLabel, EditorGUI.kSingleLineHeight, EditorStyles.layerMaskField, options); - } - - public static Rect GetControlRect(bool hasLabel, float height, params GUILayoutOption[] options) - { - return GetControlRect(hasLabel, height, EditorStyles.layerMaskField, options); - } - - public static Rect GetControlRect(bool hasLabel, float height, GUIStyle style, params GUILayoutOption[] options) - { - return GUILayoutUtility.GetRect( - hasLabel ? kLabelFloatMinW : EditorGUIUtility.fieldWidth, - kLabelFloatMaxW, - height, height, style, options); - } - - internal static Rect GetSliderRect(bool hasLabel, params GUILayoutOption[] options) - { - return GUILayoutUtility.GetRect( - hasLabel ? kLabelFloatMinW : EditorGUIUtility.fieldWidth, - kLabelFloatMaxW + EditorGUI.kSpacing + EditorGUI.kSliderMaxW, - EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - } - - internal static Rect GetToggleRect(bool hasLabel, params GUILayoutOption[] options) - { - // Toggle is 10 pixels wide while float fields are EditorGUIUtility.fieldWidth pixels wide. - // Store difference in variable and add to min and max width values used for float fields. - float toggleAdjust = (10 - EditorGUIUtility.fieldWidth); - return GUILayoutUtility.GetRect( - hasLabel ? kLabelFloatMinW + toggleAdjust : EditorGUIUtility.fieldWidth + toggleAdjust, - kLabelFloatMaxW + toggleAdjust, - EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - } - - public class FadeGroupScope : GUI.Scope - { - // when using the FadeGroupScope, make sure to only show the content when 'visible' is set to true, - // otherwise only the hide animation will run, and then the content will be visible again. - public bool visible { get; protected set; } - float m_Value; - - public FadeGroupScope(float value) - { - visible = BeginFadeGroup(value); - m_Value = value; - } - - protected override void CloseScope() - { - // See comments with BeginFadeGroup - if (m_Value != 0 && m_Value != 1) - EndFadeGroup(); - } - } - - public static bool BeginFadeGroup(float value) - { - // Fade groups interfere with layout even when the fade group is collapsed because - // the margins of the elements beofre and after are added together instead of overlapping. - // This creates unwanted extra space between controls if there's an inactive fade group in between. - // We avoid this by simply not having the fade group if it's collapsed. - if (value == 0) - { - return false; - } - // Active fade groups interfere with styles that have overflow, because the overflow part gets clipped. - // We avoid this by simply not having the fade group if it's fully expanded. - if (value == 1) - { - return true; - } - - GUILayoutFadeGroup g = (GUILayoutFadeGroup)GUILayoutUtility.BeginLayoutGroup(GUIStyle.none, null, typeof(GUILayoutFadeGroup)); - g.isVertical = true; - g.resetCoords = true; - g.fadeValue = value; - g.wasGUIEnabled = GUI.enabled; - g.guiColor = GUI.color; - if (value != 0.0f && value != 1.0f && Event.current.type == EventType.MouseDown) - { - Event.current.Use(); - } - - // 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. - EditorGUIUtility.LockContextWidth(); - GUI.BeginGroup(g.rect); - - return value != 0; - } - - public static void EndFadeGroup() - { - // If we're inside a fade group, end it here. - // See BeginFadeGroup for details on why it's not always present. - GUILayoutFadeGroup g = EditorGUILayoutUtilityInternal.topLevel as GUILayoutFadeGroup; - if (g != null) - { - GUI.EndGroup(); - EditorGUIUtility.UnlockContextWidth(); - GUI.enabled = g.wasGUIEnabled; - GUI.color = g.guiColor; - GUILayoutUtility.EndLayoutGroup(); - } - } - - internal static int BeginPlatformGrouping(BuildPlatform[] platforms, GUIContent defaultTab) - { - return BeginPlatformGrouping(platforms, defaultTab, GUI.skin.box); - } - - internal static int BeginPlatformGrouping(BuildPlatform[] platforms, GUIContent defaultTab, GUIStyle style) - { - int selectedPlatform = -1; - for (int i = 0; i < platforms.Length; i++) - { - if (platforms[i].targetGroup == EditorUserBuildSettings.selectedBuildTargetGroup) - selectedPlatform = i; - } - if (selectedPlatform == -1) - { - s_SelectedDefault.value = true; - selectedPlatform = 0; - } - - int selected = defaultTab == null ? selectedPlatform : (s_SelectedDefault.value ? -1 : selectedPlatform); - - bool tempEnabled = GUI.enabled; - GUI.enabled = true; - EditorGUI.BeginChangeCheck(); - Rect r = EditorGUILayout.BeginVertical(style); - r.width--; - int buttonCount = platforms.Length; - int buttonHeight = 18; - GUIStyle buttonStyle = EditorStyles.toolbarButton; - - // Make the widget that shows what is available - if (defaultTab != null) - { - if (GUI.Toggle(new Rect(r.x, r.y, r.width - buttonCount * kPlatformTabWidth, buttonHeight), selected == -1, defaultTab, buttonStyle)) - selected = -1; - } - for (int i = 0; i < buttonCount; i++) - { - Rect buttonRect; - if (defaultTab != null) - { - buttonRect = new Rect(r.xMax - (buttonCount - i) * kPlatformTabWidth, r.y, kPlatformTabWidth, buttonHeight); - } - else - { - int left = Mathf.RoundToInt(i * r.width / buttonCount); - int right = Mathf.RoundToInt((i + 1) * r.width / buttonCount); - buttonRect = new Rect(r.x + left, r.y, right - left, buttonHeight); - } - - if (GUI.Toggle(buttonRect, selected == i, new GUIContent(platforms[i].smallIcon, platforms[i].tooltip), buttonStyle)) - selected = i; - } - - // GUILayout.Space doesn't expand to available width, so use GetRect instead - GUILayoutUtility.GetRect(10, buttonHeight); - - GUI.enabled = tempEnabled; - - // Important that we only actually set the selectedBuildTargetGroup if the user clicked the button. - // If the current selectedBuildTargetGroup is one that is not among the tabs (because the build target - // is not supported), then this should not be changed unless the user explicitly does so. - // Otherwise, if the build window is open at the same time, the unsupported build target groups will - // not be selectable in the build window. - if (EditorGUI.EndChangeCheck()) - { - if (defaultTab == null) - { - EditorUserBuildSettings.selectedBuildTargetGroup = platforms[selected].targetGroup; - } - else - { - if (selected < 0) - { - s_SelectedDefault.value = true; - } - else - { - EditorUserBuildSettings.selectedBuildTargetGroup = platforms[selected].targetGroup; - s_SelectedDefault.value = false; - } - } - - // Repaint build window, if open. - Object[] buildWindows = Resources.FindObjectsOfTypeAll(typeof(BuildPlayerWindow)); - for (int i = 0; i < buildWindows.Length; i++) - { - BuildPlayerWindow buildWindow = buildWindows[i] as BuildPlayerWindow; - if (buildWindow != null) - buildWindow.Repaint(); - } - } - - return selected; - } - - internal static void EndPlatformGrouping() - { - EditorGUILayout.EndVertical(); - } - - internal static void MultiSelectionObjectTitleBar(Object[] objects) - { - string text = objects[0].name + " (" + ObjectNames.NicifyVariableName(ObjectNames.GetTypeName(objects[0])) + ")"; - if (objects.Length > 1) - { - text += " and " + (objects.Length - 1) + " other" + (objects.Length > 2 ? "s" : ""); - } - GUILayoutOption[] options = { GUILayout.Height(16f) }; - GUILayout.Label(EditorGUIUtility.TempContent(text, AssetPreview.GetMiniThumbnail(objects[0])), EditorStyles.boldLabel, options); - } - - // Returns true if specified bit is true for all targets - internal static bool BitToggleField(string label, SerializedProperty bitFieldProperty, int flag) - { - bool toggle = (bitFieldProperty.intValue & flag) != 0; - bool different = (bitFieldProperty.hasMultipleDifferentValuesBitwise & flag) != 0; - EditorGUI.showMixedValue = different; - EditorGUI.BeginChangeCheck(); - toggle = EditorGUILayout.Toggle(label, toggle); - if (EditorGUI.EndChangeCheck()) - { - // If toggle has mixed values, always set all to true when clicking it - if (different) - { - toggle = true; - } - different = false; - int bitIndex = -1; - for (int i = 0; i < 32; i++) - { - if (((1 << i) & flag) != 0) - { - bitIndex = i; - break; - } - } - bitFieldProperty.SetBitAtIndexForAllTargetsImmediate(bitIndex, toggle); - } - EditorGUI.showMixedValue = false; - return toggle && !different; - } - - internal static void SortingLayerField(GUIContent label, SerializedProperty layerID, GUIStyle style) - { - Rect r = EditorGUILayout.s_LastRect = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight, style); - EditorGUI.SortingLayerField(r, label, layerID, style, EditorStyles.label); - } - - internal static string TextFieldDropDown(string text, string[] dropDownElement) - { - return TextFieldDropDown(GUIContent.none, text, dropDownElement); - } - - internal static string TextFieldDropDown(GUIContent label, string text, string[] dropDownElement) - { - Rect rect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.textField); - return EditorGUI.TextFieldDropDown(rect, label, text, dropDownElement); - } - - internal static string DelayedTextFieldDropDown(string text, string[] dropDownElement) - { - return DelayedTextFieldDropDown(GUIContent.none, text, dropDownElement); - } - - internal static string DelayedTextFieldDropDown(GUIContent label, string text, string[] dropDownElement) - { - Rect rect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.textFieldDropDownText); - return EditorGUI.DelayedTextFieldDropDown(rect, label, text, dropDownElement); - } - - // A button that returns true on mouse down - like a popup button - public static bool DropdownButton(GUIContent content, FocusType focusType, params GUILayoutOption[] options) - { - return DropdownButton(content, focusType, "MiniPullDown", options); - } - - // A button that returns true on mouse down - like a popup button - public static bool DropdownButton(GUIContent content, FocusType focusType, GUIStyle style, params GUILayoutOption[] options) - { - s_LastRect = GUILayoutUtility.GetRect(content, style, options); - return EditorGUI.DropdownButton(s_LastRect, content, focusType, style); - } - - internal static int AdvancedPopup(int selectedIndex, string[] displayedOptions, params GUILayoutOption[] options) - { - return AdvancedPopup(selectedIndex, displayedOptions, "MiniPullDown", options); - } - - internal static int AdvancedPopup(int selectedIndex, string[] displayedOptions, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - return EditorGUI.AdvancedPopup(r, selectedIndex, displayedOptions, style); - } - } -} diff --git a/Editor/Mono/EditorGUIUtility.bindings.cs b/Editor/Mono/EditorGUIUtility.bindings.cs deleted file mode 100644 index bfb4e2edb5..0000000000 --- a/Editor/Mono/EditorGUIUtility.bindings.cs +++ /dev/null @@ -1,162 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/Utility/EditorGUIUtility.h")] - public partial class EditorGUIUtility : GUIUtility - { - // Get a texture from its source filename - public static Texture2D FindTexture(string name) - { - return FindTextureByName(name); - } - - // Get texture from managed type - internal static Texture2D FindTexture(Type type) - { - return FindTextureByType(type); - } - - extern static Texture2D FindTextureByName(string name); - extern static Texture2D FindTextureByType([NotNull] Type type); - - internal static GUIContent TrTextContent(string text, string tooltip = null, Texture icon = null) - { - string text_k = text != null ? text : ""; - string tooltip_k = tooltip != null ? tooltip : ""; - string key = string.Format("{0}|{1}|{2}", text_k, tooltip_k, icon != null ? icon.name : ""); - - GUIContent gc = (GUIContent)s_GUIContents[key]; - if (gc == null) - { - gc = new GUIContent(L10n.Tr(text)); - if (tooltip != null) - { - gc.tooltip = L10n.Tr(tooltip); - } - if (icon != null) - { - gc.image = icon; - } - s_GUIContents[key] = gc; - } - return gc; - } - - internal static GUIContent TrTextContent(string text, string tooltip, string iconName) - { - string text_k = text != null ? text : ""; - string tooltip_k = tooltip != null ? tooltip : ""; - string iconName_k = iconName != null ? iconName : ""; - string key = string.Format("{0}|{1}|{2}", text_k, tooltip_k, iconName_k); - - GUIContent gc = (GUIContent)s_GUIContents[key]; - if (gc == null) - { - gc = new GUIContent(L10n.Tr(text)); - if (tooltip != null) - { - gc.tooltip = L10n.Tr(tooltip); - } - if (iconName != null) - { - Texture icon = LoadIconRequired(iconName); - gc.image = icon; - } - s_GUIContents[key] = gc; - } - return gc; - } - - internal static GUIContent TrTextContent(string text, Texture icon) - { - return TrTextContent(text, null, icon); - } - - internal static GUIContent TrTextContentWithIcon(string text, Texture icon) - { - return TrTextContent(text, null, icon); - } - - internal static GUIContent TrTextContentWithIcon(string text, string iconName) - { - return TrTextContent(text, null, iconName); - } - - internal static GUIContent TrTextContentWithIcon(string text, string tooltip, string iconName) - { - return TrTextContent(text, tooltip, iconName); - } - - internal static GUIContent TrTextContentWithIcon(string text, string tooltip, Texture icon) - { - return TrTextContent(text, tooltip, icon); - } - - internal static GUIContent TrTextContentWithIcon(string text, string tooltip, MessageType messageType) - { - return TrTextContent(text, tooltip, GetHelpIcon(messageType)); - } - - internal static GUIContent TrTextContentWithIcon(string text, MessageType messageType) - { - return TrTextContentWithIcon(text, null, messageType); - } - - internal static GUIContent TrIconContent(string iconName, string tooltip = null) - { - string key = (tooltip == null ? iconName : iconName + tooltip); - GUIContent gc = (GUIContent)s_IconGUIContents[key]; - if (gc != null) - { - return gc; - } - gc = new GUIContent(); - - if (tooltip != null) - { - gc.tooltip = L10n.Tr(tooltip); - } - gc.image = LoadIconRequired(iconName); - s_IconGUIContents[key] = gc; - return gc; - } - - internal static GUIContent TrIconContent(Texture icon, string tooltip = null) - { - GUIContent gc = (tooltip != null) ? (GUIContent)s_IconGUIContents[tooltip] : null; - if (gc != null) - { - return gc; - } - gc = new GUIContent(); - gc.image = icon; - if (tooltip != null) - { - gc.tooltip = L10n.Tr(tooltip); - s_IconGUIContents[tooltip] = gc; - } - - return gc; - } - - internal static GUIContent TrTempContent(string t) - { - return TempContent(L10n.Tr(t)); - } - - internal static GUIContent[] TrTempContent(string[] texts) - { - GUIContent[] retval = new GUIContent[texts.Length]; - for (int i = 0; i < texts.Length; i++) - retval[i] = new GUIContent(L10n.Tr(texts[i])); - return retval; - } - } -} diff --git a/Editor/Mono/EditorGUIUtility.cs b/Editor/Mono/EditorGUIUtility.cs deleted file mode 100644 index 7847ceb64c..0000000000 --- a/Editor/Mono/EditorGUIUtility.cs +++ /dev/null @@ -1,347 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Rendering; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEngine.Assertions; -using UnityEngine.Events; -using UnityEngine.Profiling; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - public sealed partial class EditorGUIUtility - { - public class IconSizeScope : GUI.Scope - { - Vector2 m_OriginalIconSize; - - public IconSizeScope(Vector2 iconSizeWithinScope) - { - m_OriginalIconSize = GetIconSize(); - SetIconSize(iconSizeWithinScope); - } - - protected override void CloseScope() - { - SetIconSize(m_OriginalIconSize); - } - } - - internal static void RepaintCurrentWindow() - { - CheckOnGUI(); - GUIView.current.Repaint(); - } - - internal static bool HasCurrentWindowKeyFocus() - { - CheckOnGUI(); - return GUIView.current.hasFocus; - } - - internal static Material s_GUITextureBlit2SRGBMaterial; - internal static Material GUITextureBlit2SRGBMaterial - { - get - { - if (!s_GUITextureBlit2SRGBMaterial) - { - Shader shader = EditorGUIUtility.LoadRequired("SceneView/GUITextureBlit2SRGB.shader") as Shader; - s_GUITextureBlit2SRGBMaterial = new Material(shader); - s_GUITextureBlit2SRGBMaterial.hideFlags = HideFlags.HideAndDontSave; - } - s_GUITextureBlit2SRGBMaterial.SetFloat("_ManualTex2SRGB", QualitySettings.activeColorSpace == ColorSpace.Linear ? 1.0f : 0.0f); - return s_GUITextureBlit2SRGBMaterial; - } - } - - /// The current UI scaling factor for high-DPI displays. For instance, 2.0 on a retina display - - public - static new float pixelsPerPoint - { - get - { - return GUIUtility.pixelsPerPoint; - } - } - - public - static Rect PointsToPixels(Rect rect) - { - var cachedPixelsPerPoint = EditorGUIUtility.pixelsPerPoint; - rect.x *= cachedPixelsPerPoint; - rect.y *= cachedPixelsPerPoint; - rect.width *= cachedPixelsPerPoint; - rect.height *= cachedPixelsPerPoint; - return rect; - } - - public - static Rect PixelsToPoints(Rect rect) - { - var cachedInvPixelsPerPoint = 1f / EditorGUIUtility.pixelsPerPoint; - rect.x *= cachedInvPixelsPerPoint; - rect.y *= cachedInvPixelsPerPoint; - rect.width *= cachedInvPixelsPerPoint; - rect.height *= cachedInvPixelsPerPoint; - return rect; - } - - public - static Vector2 PointsToPixels(Vector2 position) - { - var cachedPixelsPerPoint = EditorGUIUtility.pixelsPerPoint; - position.x *= cachedPixelsPerPoint; - position.y *= cachedPixelsPerPoint; - return position; - } - - public - static Vector2 PixelsToPoints(Vector2 position) - { - var cachedInvPixelsPerPoint = 1f / EditorGUIUtility.pixelsPerPoint; - position.x *= cachedInvPixelsPerPoint; - position.y *= cachedInvPixelsPerPoint; - return position; - } - - // Given a rectangle, GUI style and a list of items, lay them out sequentially; - // left to right, top to bottom. - public static List GetFlowLayoutedRects(Rect rect, GUIStyle style, float horizontalSpacing, float verticalSpacing, List items) - { - var result = new List(items.Count); - var curPos = rect.position; - for (var i = 0; i < items.Count; ++i) - { - var gc = EditorGUIUtility.TempContent(items[i]); - var itemSize = style.CalcSize(gc); - var itemRect = new Rect(curPos, itemSize); - - // Reached right side, go to next row - if (curPos.x + itemSize.x + horizontalSpacing >= rect.xMax) - { - curPos.x = rect.x; - curPos.y += itemSize.y + verticalSpacing; - itemRect.position = curPos; - } - result.Add(itemRect); - - // Move next item to the left - curPos.x += itemSize.x + horizontalSpacing; - } - - return result; - } - - internal class SkinnedColor - { - Color normalColor; - Color proColor; - - public SkinnedColor(Color color, Color proColor) - { - normalColor = color; - this.proColor = proColor; - } - - public SkinnedColor(Color color) - { - normalColor = color; - proColor = color; - } - - public Color color - { - get - { - if (EditorGUIUtility.isProSkin) - return proColor; - else - return normalColor; - } - - set - { - if (EditorGUIUtility.isProSkin) - proColor = value; - else - normalColor = value; - } - } - - public static implicit operator Color(SkinnedColor colorSkin) - { - return colorSkin.color; - } - } - - internal static void ShowObjectPicker(Object obj, bool allowSceneObjects, string searchFilter, ObjectSelectorReceiver objectSelectorReceiver) where T : Object - { - System.Type objType = typeof(T); - ObjectSelector.get.Show(obj, objType, null, allowSceneObjects); - ObjectSelector.get.objectSelectorReceiver = objectSelectorReceiver; - ObjectSelector.get.searchFilter = searchFilter; - } - - private delegate bool HeaderItemDelegate(Rect rectangle, Object[] targets); - private static List s_EditorHeaderItemsMethods = null; - internal static Rect DrawEditorHeaderItems(Rect rectangle, Object[] targetObjs) - { - if (targetObjs.Length == 0 || (targetObjs.Length == 1 && targetObjs[0].GetType() == typeof(System.Object))) - return rectangle; - - if (s_EditorHeaderItemsMethods == null) - { - List targetObjTypes = new List(); - var type = targetObjs[0].GetType(); - while (type.BaseType != null) - { - targetObjTypes.Add(type); - type = type.BaseType; - } - - AttributeHelper.MethodInfoSorter methods = AttributeHelper.GetMethodsWithAttribute(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); - Func filter = (a) => targetObjTypes.Any(c => a.TargetType == c); - var methodInfos = methods.FilterAndSortOnAttribute(filter, (a) => a.callbackOrder); - s_EditorHeaderItemsMethods = new List(); - foreach (MethodInfo methodInfo in methodInfos) - { - s_EditorHeaderItemsMethods.Add((HeaderItemDelegate)Delegate.CreateDelegate(typeof(HeaderItemDelegate), methodInfo)); - } - } - - for (var index = 0; index < s_EditorHeaderItemsMethods.Count; index++) - { - HeaderItemDelegate dele = s_EditorHeaderItemsMethods[index]; - if (dele(rectangle, targetObjs)) - { - rectangle.x -= rectangle.width; - } - } - - return rectangle; - } - - /// - /// Use this container and helper class when implementing lock behaviour on a window when also using an . - /// - [Serializable] - internal class EditorLockTrackerWithActiveEditorTracker : EditorLockTracker - { - internal override bool isLocked - { - get - { - if (m_Tracker != null) - { - base.isLocked = m_Tracker.isLocked; - return m_Tracker.isLocked; - } - return base.isLocked; - } - set - { - if (m_Tracker != null) - { - m_Tracker.isLocked = value; - } - base.isLocked = value; - } - } - - [SerializeField, HideInInspector] - ActiveEditorTracker m_Tracker; - - internal ActiveEditorTracker tracker - { - get { return m_Tracker; } - set - { - m_Tracker = value; - if (m_Tracker != null) - { - isLocked = m_Tracker.isLocked; - } - } - } - } - - /// - /// Use this container and helper class when implementing lock behaviour on a window. - /// - [Serializable] - internal class EditorLockTracker - { - [Serializable] public class LockStateEvent : UnityEvent {} - [HideInInspector] - internal LockStateEvent lockStateChanged = new LockStateEvent(); - - const string k_LockMenuText = "Lock"; - static readonly GUIContent k_LockMenuGUIContent = EditorGUIUtility.TextContent(k_LockMenuText); - - /// - /// don't set or get this directly unless from within the property, - /// as that property also keeps track of the potentially existing tracker in - /// - [SerializeField, HideInInspector] - bool m_IsLocked; - - internal virtual bool isLocked - { - get - { - return m_IsLocked; - } - set - { - bool wasLocked = m_IsLocked; - m_IsLocked = value; - - if (wasLocked != m_IsLocked) - { - lockStateChanged.Invoke(m_IsLocked); - } - } - } - - internal virtual void AddItemsToMenu(GenericMenu menu, bool disabled = false) - { - if (disabled) - { - menu.AddDisabledItem(k_LockMenuGUIContent); - } - else - { - menu.AddItem(k_LockMenuGUIContent, isLocked, FlipLocked); - } - } - - internal void ShowButton(Rect position, GUIStyle lockButtonStyle, bool disabled = false) - { - using (new EditorGUI.DisabledScope(disabled)) - { - EditorGUI.BeginChangeCheck(); - bool newLock = GUI.Toggle(position, isLocked, GUIContent.none, lockButtonStyle); - - if (EditorGUI.EndChangeCheck()) - { - if (newLock != isLocked) - FlipLocked(); - } - } - } - - void FlipLocked() - { - isLocked = !isLocked; - } - } - } -} diff --git a/Editor/Mono/EditorGraphicsSettings.cs b/Editor/Mono/EditorGraphicsSettings.cs deleted file mode 100644 index 79bc4db5f0..0000000000 --- a/Editor/Mono/EditorGraphicsSettings.cs +++ /dev/null @@ -1,122 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Runtime.InteropServices; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; - -using UnityEngine; -using UnityEngine.Rendering; - - -namespace UnityEditor.Rendering -{ - public enum ShaderQuality - { - Low, - Medium, - High, - } - - [StructLayout(LayoutKind.Sequential)] - public struct TierSettings - { - public ShaderQuality standardShaderQuality; - public CameraHDRMode hdrMode; - public bool reflectionProbeBoxProjection; - public bool reflectionProbeBlending; - public bool hdr; - public bool detailNormalMap; - - public bool cascadedShadowMaps; - public bool prefer32BitShadowMaps; - public bool enableLPPV; - public bool semitransparentShadows; - - public RenderingPath renderingPath; - public RealtimeGICPUUsage realtimeGICPUUsage; - } - - - public sealed partial class EditorGraphicsSettings - { - public static TierSettings GetTierSettings(BuildTargetGroup target, GraphicsTier tier) - { - return GetTierSettingsImpl(target, tier); - } - - public static void SetTierSettings(BuildTargetGroup target, GraphicsTier tier, TierSettings settings) - { - if (settings.renderingPath == RenderingPath.UsePlayerSettings) - throw new ArgumentException("TierSettings.renderingPath must be actual rendering path (not UsePlayerSettings)", "settings"); - - SetTierSettingsImpl(target, tier, settings); - MakeTierSettingsAutomatic(target, tier, false); - OnUpdateTierSettingsImpl(target, true); - } - - internal static TierSettings GetCurrentTierSettings() - { - return GetCurrentTierSettingsImpl(); - } - } - - - // - // deprecated - // - - [Obsolete("Use TierSettings instead (UnityUpgradable) -> UnityEditor.Rendering.TierSettings", false)] - [StructLayout(LayoutKind.Sequential)] - public struct PlatformShaderSettings - { - [MarshalAs(UnmanagedType.I1)] public bool cascadedShadowMaps; - [MarshalAs(UnmanagedType.I1)] public bool reflectionProbeBoxProjection; - [MarshalAs(UnmanagedType.I1)] public bool reflectionProbeBlending; - - public ShaderQuality standardShaderQuality; - } - - public sealed partial class EditorGraphicsSettings - { - [Obsolete("Use GetTierSettings() instead (UnityUpgradable) -> GetTierSettings(*)", false)] - public static PlatformShaderSettings GetShaderSettingsForPlatform(BuildTargetGroup target, ShaderHardwareTier tier) - { - TierSettings ts = GetTierSettings(target, (GraphicsTier)tier); - - PlatformShaderSettings pss = new PlatformShaderSettings(); - pss.cascadedShadowMaps = ts.cascadedShadowMaps; - pss.standardShaderQuality = ts.standardShaderQuality; - pss.reflectionProbeBoxProjection = ts.reflectionProbeBoxProjection; - pss.reflectionProbeBlending = ts.reflectionProbeBlending; - return pss; - } - - [Obsolete("Use SetTierSettings() instead (UnityUpgradable) -> SetTierSettings(*)", false)] - public static void SetShaderSettingsForPlatform(BuildTargetGroup target, ShaderHardwareTier tier, PlatformShaderSettings settings) - { - // we want to preserve TierSettings members that are absent from PlatformShaderSettings - TierSettings ts = GetTierSettings(target, (GraphicsTier)tier); - - ts.standardShaderQuality = settings.standardShaderQuality; - ts.cascadedShadowMaps = settings.cascadedShadowMaps; - ts.reflectionProbeBoxProjection = settings.reflectionProbeBoxProjection; - ts.reflectionProbeBlending = settings.reflectionProbeBlending; - - SetTierSettings(target, (GraphicsTier)tier, ts); - } - - [Obsolete("Use GraphicsTier instead of ShaderHardwareTier enum", false)] - public static TierSettings GetTierSettings(BuildTargetGroup target, ShaderHardwareTier tier) - { - return GetTierSettings(target, (GraphicsTier)tier); - } - - [Obsolete("Use GraphicsTier instead of ShaderHardwareTier enum", false)] - public static void SetTierSettings(BuildTargetGroup target, ShaderHardwareTier tier, TierSettings settings) - { - SetTierSettings(target, (GraphicsTier)tier, settings); - } - } -} diff --git a/Editor/Mono/EditorHandles.cs b/Editor/Mono/EditorHandles.cs deleted file mode 100644 index 3677808f2b..0000000000 --- a/Editor/Mono/EditorHandles.cs +++ /dev/null @@ -1,575 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class Handles - { - public struct DrawingScope : IDisposable - { - private bool m_Disposed; - - public Color originalColor { get { return m_OriginalColor; } } - private Color m_OriginalColor; - - public Matrix4x4 originalMatrix { get { return m_OriginalMatrix; } } - private Matrix4x4 m_OriginalMatrix; - - public DrawingScope(Color color) : this(color, Handles.matrix) {} - - public DrawingScope(Matrix4x4 matrix) : this(Handles.color, matrix) {} - - public DrawingScope(Color color, Matrix4x4 matrix) - { - m_Disposed = false; - m_OriginalColor = Handles.color; - m_OriginalMatrix = Handles.matrix; - Handles.matrix = matrix; - Handles.color = color; - } - - public void Dispose() - { - if (m_Disposed) - return; - m_Disposed = true; - Handles.color = m_OriginalColor; - Handles.matrix = m_OriginalMatrix; - } - } - - static Mesh cubeMesh - { - get - { - if (s_CubeMesh == null) - Init(); - return s_CubeMesh; - } - } - - static Mesh coneMesh - { - get - { - if (s_ConeMesh == null) - Init(); - return s_ConeMesh; - } - } - - static Mesh cylinderMesh - { - get - { - if (s_CylinderMesh == null) - Init(); - return s_CylinderMesh; - } - } - - static Mesh quadMesh - { - get - { - if (s_QuadMesh == null) - Init(); - return s_QuadMesh; - } - } - - static Mesh sphereMesh - { - get - { - if (s_SphereMesh == null) - Init(); - return s_SphereMesh; - } - } - - internal static int s_xRotateHandleHash = "xRotateHandleHash".GetHashCode(); - internal static int s_yRotateHandleHash = "yRotateHandleHash".GetHashCode(); - internal static int s_zRotateHandleHash = "zRotateHandleHash".GetHashCode(); - internal static int s_cameraAxisRotateHandleHash = "cameraAxisRotateHandleHash".GetHashCode(); - internal static int s_xyzRotateHandleHash = "xyzRotateHandleHash".GetHashCode(); - internal static int s_xScaleHandleHash = "xScaleHandleHash".GetHashCode(); - internal static int s_yScaleHandleHash = "yScaleHandleHash".GetHashCode(); - internal static int s_zScaleHandleHash = "zScaleHandleHash".GetHashCode(); - internal static int s_xyzScaleHandleHash = "xyzScaleHandleHash".GetHashCode(); - - private static Color lineTransparency = new Color(1, 1, 1, 0.75f); - - internal const float kCameraViewLerpStart = 0.85f; - internal const float kCameraViewThreshold = 0.9f; - internal const float kCameraViewLerpSpeed = 1f / (1 - kCameraViewLerpStart); - - // The function for calling AddControl in Layout event and draw the handle in Repaint event. - public delegate void CapFunction(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType); - - // Signatures expecting DrawCapFunction were marked plannned obsolete by @juha on 2016-03-16, marked obsolete warning by @adamm on 2016-12-21 - [Obsolete("This delegate is obsolete. Use CapFunction instead.")] - public delegate void DrawCapFunction(int controlID, Vector3 position, Quaternion rotation, float size); - - public delegate float SizeFunction(Vector3 position); - - static PrefColor[] s_AxisColor = { s_XAxisColor, s_YAxisColor, s_ZAxisColor }; - static Vector3[] s_AxisVector = { Vector3.right, Vector3.up, Vector3.forward }; - - internal static Color s_DisabledHandleColor = new Color(0.5f, 0.5f, 0.5f, 0.5f); - - internal static Color GetColorByAxis(int axis) - { - return s_AxisColor[axis]; - } - - internal static Color ToActiveColorSpace(Color color) - { - return (QualitySettings.activeColorSpace == ColorSpace.Linear) ? color.linear : color; - } - - static Vector3 GetAxisVector(int axis) - { - return s_AxisVector[axis]; - } - - private static bool BeginLineDrawing(Matrix4x4 matrix, bool dottedLines, int mode) - { - if (Event.current.type != EventType.Repaint) - return false; - - Color col = color * lineTransparency; - if (dottedLines) - HandleUtility.ApplyDottedWireMaterial(zTest); - else - HandleUtility.ApplyWireMaterial(zTest); - GL.PushMatrix(); - GL.MultMatrix(matrix); - GL.Begin(mode); - GL.Color(col); - return true; - } - - private static void EndLineDrawing() - { - GL.End(); - GL.PopMatrix(); - } - - public static void DrawPolyLine(params Vector3[] points) - { - if (!BeginLineDrawing(matrix, false, GL.LINE_STRIP)) - return; - for (int i = 0; i < points.Length; i++) - { - GL.Vertex(points[i]); - } - EndLineDrawing(); - } - - public static void DrawLine(Vector3 p1, Vector3 p2) - { - DrawLine(p1, p2, false); - } - - internal static void DrawLine(Vector3 p1, Vector3 p2, bool dottedLine) - { - if (!BeginLineDrawing(matrix, dottedLine, GL.LINES)) - return; - GL.Vertex(p1); - GL.Vertex(p2); - EndLineDrawing(); - } - - public static void DrawLines(Vector3[] lineSegments) - { - if (!BeginLineDrawing(matrix, false, GL.LINES)) - return; - for (int i = 0; i < lineSegments.Length; i += 2) - { - var p1 = lineSegments[i + 0]; - var p2 = lineSegments[i + 1]; - GL.Vertex(p1); - GL.Vertex(p2); - } - EndLineDrawing(); - } - - public static void DrawLines(Vector3[] points, int[] segmentIndices) - { - if (!BeginLineDrawing(matrix, false, GL.LINES)) - return; - for (int i = 0; i < segmentIndices.Length; i += 2) - { - var p1 = points[segmentIndices[i + 0]]; - var p2 = points[segmentIndices[i + 1]]; - GL.Vertex(p1); - GL.Vertex(p2); - } - EndLineDrawing(); - } - - public static void DrawDottedLine(Vector3 p1, Vector3 p2, float screenSpaceSize) - { - if (!BeginLineDrawing(matrix, true, GL.LINES)) - return; - var dashSize = screenSpaceSize * EditorGUIUtility.pixelsPerPoint; - GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p1); - GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p2); - EndLineDrawing(); - } - - public static void DrawDottedLines(Vector3[] lineSegments, float screenSpaceSize) - { - if (!BeginLineDrawing(matrix, true, GL.LINES)) - return; - var dashSize = screenSpaceSize * EditorGUIUtility.pixelsPerPoint; - for (int i = 0; i < lineSegments.Length; i += 2) - { - var p1 = lineSegments[i + 0]; - var p2 = lineSegments[i + 1]; - GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p1); - GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p2); - } - EndLineDrawing(); - } - - public static void DrawDottedLines(Vector3[] points, int[] segmentIndices, float screenSpaceSize) - { - if (!BeginLineDrawing(matrix, true, GL.LINES)) - return; - var dashSize = screenSpaceSize * EditorGUIUtility.pixelsPerPoint; - for (int i = 0; i < segmentIndices.Length; i += 2) - { - var p1 = points[segmentIndices[i + 0]]; - var p2 = points[segmentIndices[i + 1]]; - GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p1); - GL.MultiTexCoord(1, p1); GL.MultiTexCoord2(2, dashSize, 0); GL.Vertex(p2); - } - EndLineDrawing(); - } - - public static void DrawWireCube(Vector3 center, Vector3 size) - { - Vector3 halfsize = size * 0.5f; - - Vector3[] points = new Vector3[10]; - points[0] = center + new Vector3(-halfsize.x, -halfsize.y, -halfsize.z); - points[1] = center + new Vector3(-halfsize.x, halfsize.y, -halfsize.z); - points[2] = center + new Vector3(halfsize.x, halfsize.y, -halfsize.z); - points[3] = center + new Vector3(halfsize.x, -halfsize.y, -halfsize.z); - points[4] = center + new Vector3(-halfsize.x, -halfsize.y, -halfsize.z); - - points[5] = center + new Vector3(-halfsize.x, -halfsize.y, halfsize.z); - points[6] = center + new Vector3(-halfsize.x, halfsize.y, halfsize.z); - points[7] = center + new Vector3(halfsize.x, halfsize.y, halfsize.z); - points[8] = center + new Vector3(halfsize.x, -halfsize.y, halfsize.z); - points[9] = center + new Vector3(-halfsize.x, -halfsize.y, halfsize.z); - - Handles.DrawPolyLine(points); - Handles.DrawLine(points[1], points[6]); - Handles.DrawLine(points[2], points[7]); - Handles.DrawLine(points[3], points[8]); - } - - public static Quaternion Disc(int id, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap) - { - return UnityEditorInternal.Disc.Do(id, rotation, position, axis, size, cutoffPlane, snap); - } - - public static Quaternion FreeRotateHandle(int id, Quaternion rotation, Vector3 position, float size) - { - return UnityEditorInternal.FreeRotate.Do(id, rotation, position, size); - } - - // Make a 3D slider - public static Vector3 Slider(Vector3 position, Vector3 direction) - { - return Slider(position, direction, HandleUtility.GetHandleSize(position), ArrowHandleCap, -1); - } - - public static Vector3 Slider(Vector3 position, Vector3 direction, float size, CapFunction capFunction, float snap) - { - int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Passive); - return UnityEditorInternal.Slider1D.Do(id, position, direction, size, capFunction, snap); - } - - public static Vector3 Slider(int controlID, Vector3 position, Vector3 direction, float size, CapFunction capFunction, float snap) - { - return UnityEditorInternal.Slider1D.Do(controlID, position, direction, size, capFunction, snap); - } - - public static Vector3 Slider(int controlID, Vector3 position, Vector3 offset, Vector3 direction, float size, CapFunction capFunction, float snap) - { - return UnityEditorInternal.Slider1D.Do(controlID, position, offset, direction, direction, size, capFunction, snap); - } - - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - public static Vector3 Slider(Vector3 position, Vector3 direction, float size, DrawCapFunction drawFunc, float snap) - { - int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Passive); - return UnityEditorInternal.Slider1D.Do(id, position, direction, size, drawFunc, snap); - } - - public static Vector3 FreeMoveHandle(Vector3 position, Quaternion rotation, float size, Vector3 snap, CapFunction capFunction) - { - int id = GUIUtility.GetControlID(s_FreeMoveHandleHash, FocusType.Passive); - return UnityEditorInternal.FreeMove.Do(id, position, rotation, size, snap, capFunction); - } - - public static Vector3 FreeMoveHandle(int controlID, Vector3 position, Quaternion rotation, float size, Vector3 snap, CapFunction capFunction) - { - return UnityEditorInternal.FreeMove.Do(controlID, position, rotation, size, snap, capFunction); - } - - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - public static Vector3 FreeMoveHandle(Vector3 position, Quaternion rotation, float size, Vector3 snap, DrawCapFunction capFunc) - { - int id = GUIUtility.GetControlID(s_FreeMoveHandleHash, FocusType.Passive); - return UnityEditorInternal.FreeMove.Do(id, position, rotation, size, snap, capFunc); - } - - // Make a single-float draggable handle. - public static float ScaleValueHandle(float value, Vector3 position, Quaternion rotation, float size, CapFunction capFunction, float snap) - { - int id = GUIUtility.GetControlID(s_ScaleValueHandleHash, FocusType.Passive); - return UnityEditorInternal.SliderScale.DoCenter(id, value, position, rotation, size, capFunction, snap); - } - - public static float ScaleValueHandle(int controlID, float value, Vector3 position, Quaternion rotation, float size, CapFunction capFunction, float snap) - { - return UnityEditorInternal.SliderScale.DoCenter(controlID, value, position, rotation, size, capFunction, snap); - } - - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - public static float ScaleValueHandle(float value, Vector3 position, Quaternion rotation, float size, DrawCapFunction capFunc, float snap) - { - int id = GUIUtility.GetControlID(s_ScaleValueHandleHash, FocusType.Passive); - return UnityEditorInternal.SliderScale.DoCenter(id, value, position, rotation, size, capFunc, snap); - } - - // Make a 3D Button. - public static bool Button(Vector3 position, Quaternion direction, float size, float pickSize, CapFunction capFunction) - { - int id = GUIUtility.GetControlID(s_ButtonHash, FocusType.Passive); - return UnityEditorInternal.Button.Do(id, position, direction, size, pickSize, capFunction); - } - - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - public static bool Button(Vector3 position, Quaternion direction, float size, float pickSize, DrawCapFunction capFunc) - { - int id = GUIUtility.GetControlID(s_ButtonHash, FocusType.Passive); - return UnityEditorInternal.Button.Do(id, position, direction, size, pickSize, capFunc); - } - - internal static bool Button(int controlID, Vector3 position, Quaternion direction, float size, float pickSize, CapFunction capFunction) - { - return UnityEditorInternal.Button.Do(controlID, position, direction, size, pickSize, capFunction); - } - - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - internal static bool Button(int controlID, Vector3 position, Quaternion direction, float size, float pickSize, DrawCapFunction capFunc) - { - return UnityEditorInternal.Button.Do(controlID, position, direction, size, pickSize, capFunc); - } - - // Draw a cube. Pass this into handle functions. - public static void CubeHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - switch (eventType) - { - case (EventType.Layout): - // TODO: Create DistanceToCube - HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size)); - break; - case (EventType.Repaint): - Graphics.DrawMeshNow(cubeMesh, StartCapDraw(position, rotation, size)); - break; - } - } - - // Draw a Sphere. Pass this into handle functions. - public static void SphereHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - switch (eventType) - { - case (EventType.Layout): - // TODO: Create DistanceToCube - HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size)); - break; - case (EventType.Repaint): - Graphics.DrawMeshNow(sphereMesh, StartCapDraw(position, rotation, size)); - break; - } - } - - // Draw a Cone. Pass this into handle functions. - public static void ConeHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - switch (eventType) - { - case (EventType.Layout): - // TODO: Create DistanceToCone - HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size)); - break; - case (EventType.Repaint): - Graphics.DrawMeshNow(coneMesh, StartCapDraw(position, rotation, size)); - break; - } - } - - // Draw a Cylinder. Pass this into handle functions. - public static void CylinderHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - switch (eventType) - { - case (EventType.Layout): - // TODO: Create DistanceToCylinder - HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size)); - break; - case (EventType.Repaint): - Graphics.DrawMeshNow(cylinderMesh, StartCapDraw(position, rotation, size)); - break; - } - } - - // Draw a camera-facing Rectangle. Pass this into handle functions. - static Vector3[] s_RectangleHandlePointsCache = new Vector3[5]; - public static void RectangleHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - RectangleHandleCap(controlID, position, rotation, new Vector2(size, size), eventType); - } - - internal static void RectangleHandleCap(int controlID, Vector3 position, Quaternion rotation, Vector2 size, EventType eventType) - { - switch (eventType) - { - case (EventType.Layout): - // TODO: Create DistanceToRectangle - HandleUtility.AddControl(controlID, HandleUtility.DistanceToRectangleInternal(position, rotation, size)); - break; - case (EventType.Repaint): - Vector3 sideways = rotation * new Vector3(size.x, 0, 0); - Vector3 up = rotation * new Vector3(0, size.y, 0); - s_RectangleHandlePointsCache[0] = position + sideways + up; - s_RectangleHandlePointsCache[1] = position + sideways - up; - s_RectangleHandlePointsCache[2] = position - sideways - up; - s_RectangleHandlePointsCache[3] = position - sideways + up; - s_RectangleHandlePointsCache[4] = position + sideways + up; - Handles.DrawPolyLine(s_RectangleHandlePointsCache); - break; - } - } - - // Draw a camera-facing dot. Pass this into handle functions. - public static void DotHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - switch (eventType) - { - case (EventType.Layout): - HandleUtility.AddControl(controlID, HandleUtility.DistanceToRectangle(position, rotation, size)); - break; - case (EventType.Repaint): - // Only apply matrix to the position because DotCap is camera facing - position = matrix.MultiplyPoint(position); - - Vector3 sideways = Camera.current.transform.right * size; - Vector3 up = Camera.current.transform.up * size; - - Color col = color * new Color(1, 1, 1, 0.99f); - HandleUtility.ApplyWireMaterial(); - GL.Begin(GL.QUADS); - GL.Color(col); - GL.Vertex(position + sideways + up); - GL.Vertex(position + sideways - up); - GL.Vertex(position - sideways - up); - GL.Vertex(position - sideways + up); - GL.End(); - break; - } - } - - // Draw a camera-facing Circle. Pass this into handle functions. - public static void CircleHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - switch (eventType) - { - case (EventType.Layout): - HandleUtility.AddControl(controlID, HandleUtility.DistanceToRectangle(position, rotation, size)); - break; - case (EventType.Repaint): - StartCapDraw(position, rotation, size); - Vector3 forward = rotation * new Vector3(0, 0, 1); - Handles.DrawWireDisc(position, forward, size); - break; - } - } - - // Draw an arrow like those used by the move tool. - public static void ArrowHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - ArrowHandleCap(controlID, position, rotation, size, eventType, Vector3.zero); - } - - internal static void ArrowHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType, Vector3 coneOffset) - { - switch (eventType) - { - case (EventType.Layout): - { - Vector3 direction = rotation * Vector3.forward; - HandleUtility.AddControl(controlID, HandleUtility.DistanceToLine(position, position + (direction + coneOffset) * size * .9f)); - HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position + (direction + coneOffset) * size, size * .2f)); - break; - } - case (EventType.Repaint): - { - Vector3 direction = rotation * Vector3.forward; - ConeHandleCap(controlID, position + (direction + coneOffset) * size, Quaternion.LookRotation(direction), size * .2f, eventType); - Handles.DrawLine(position, position + (direction + coneOffset) * size * .9f, false); - break; - } - } - } - - // Draw a camera facing selection frame. - public static void DrawSelectionFrame(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - if (eventType != EventType.Repaint) - return; - - Handles.StartCapDraw(position, rotation, size); - Vector3 sideways = rotation * new Vector3(size, 0, 0); - Vector3 up = rotation * new Vector3(0, size, 0); - - var point1 = position - sideways + up; - var point2 = position + sideways + up; - var point3 = position + sideways - up; - var point4 = position - sideways - up; - - Handles.DrawLine(point1, point2); - Handles.DrawLine(point2, point3); - Handles.DrawLine(point3, point4); - Handles.DrawLine(point4, point1); - } - - internal static float GetCameraViewLerpForWorldAxis(Vector3 viewVector, Vector3 axis) - { - return - Mathf.Clamp01(kCameraViewLerpSpeed * - (Mathf.Abs(Vector3.Dot(viewVector, axis)) - kCameraViewLerpStart)); - } - - internal static Vector3 GetCameraViewFrom(Vector3 position, Matrix4x4 matrix) - { - Camera camera = Camera.current; - return camera.orthographic - ? matrix.MultiplyVector(-camera.transform.forward).normalized - : matrix.MultiplyVector(position - camera.transform.position).normalized; - } - } -} diff --git a/Editor/Mono/EditorHandles/ArcHandle.cs b/Editor/Mono/EditorHandles/ArcHandle.cs deleted file mode 100644 index 19d083271a..0000000000 --- a/Editor/Mono/EditorHandles/ArcHandle.cs +++ /dev/null @@ -1,239 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public class ArcHandle - { - static readonly float s_DefaultAngleHandleSize = 0.08f; - static readonly float s_DefaultAngleHandleSizeRatio = 1.25f; - - static readonly float s_DefaultRadiusHandleSize = 0.03f; - - static readonly Dictionary s_MostRecentValidAngleHandleOrientations = - new Dictionary(); - - // only used inside of DefaultAngleHandleDrawFunction to look up and store the most recent valid orientation per handle - // done so that DefaultAngleHandleDrawFunction can be a static method, which makes angleHandleDrawFunction more usable by sub-classes - static int s_CurrentlyDrawingAngleHandleHash; - - public static void DefaultAngleHandleDrawFunction( - int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType - ) - { - Handles.DrawLine(Vector3.zero, position); - - // draw a cylindrical "hammer head" to indicate the direction the handle will move - Vector3 worldPosition = Handles.matrix.MultiplyPoint3x4(position); - Vector3 normal = worldPosition - Handles.matrix.MultiplyPoint3x4(Vector3.zero); - Vector3 tangent = Handles.matrix.MultiplyVector(Quaternion.AngleAxis(90f, Vector3.up) * position); - Quaternion mostRecentValidOrientation; - if (!s_MostRecentValidAngleHandleOrientations.TryGetValue(s_CurrentlyDrawingAngleHandleHash, out mostRecentValidOrientation)) - mostRecentValidOrientation = Quaternion.identity; - rotation = Mathf.Approximately(tangent.sqrMagnitude, 0f) ? - mostRecentValidOrientation : Quaternion.LookRotation(tangent, normal); - s_MostRecentValidAngleHandleOrientations[s_CurrentlyDrawingAngleHandleHash] = rotation; - Matrix4x4 matrix = - Matrix4x4.TRS(worldPosition, rotation, (Vector3.one + Vector3.forward * s_DefaultAngleHandleSizeRatio)); - using (new Handles.DrawingScope(matrix)) - Handles.CylinderHandleCap(controlID, Vector3.zero, Quaternion.identity, size, eventType); - s_CurrentlyDrawingAngleHandleHash = 0; - } - - public static float DefaultAngleHandleSizeFunction(Vector3 position) - { - return HandleUtility.GetHandleSize(position) * s_DefaultAngleHandleSize; - } - - public static float DefaultRadiusHandleSizeFunction(Vector3 position) - { - return HandleUtility.GetHandleSize(position) * s_DefaultRadiusHandleSize; - } - - private bool m_ControlIDsReserved = false; - private int m_AngleHandleControlID; - private int[] m_RadiusHandleControlIDs = new int[4]; - - public float angle { get; set; } - - public float radius { get; set; } - - public Color angleHandleColor { get; set; } - - public Color radiusHandleColor { get; set; } - - public Color fillColor { get; set; } - - public Color wireframeColor { get; set; } - - public Handles.CapFunction angleHandleDrawFunction { get; set; } - - public Handles.SizeFunction angleHandleSizeFunction { get; set; } - - public Handles.CapFunction radiusHandleDrawFunction { get; set; } - - public Handles.SizeFunction radiusHandleSizeFunction { get; set; } - - public ArcHandle() - { - radius = 1f; - SetColorWithoutRadiusHandle(Color.white, 0.1f); - angleHandleDrawFunction = DefaultAngleHandleDrawFunction; - angleHandleSizeFunction = DefaultAngleHandleSizeFunction; - radiusHandleDrawFunction = Handles.DotHandleCap; - radiusHandleSizeFunction = DefaultRadiusHandleSizeFunction; - } - - ~ArcHandle() - { - s_MostRecentValidAngleHandleOrientations.Remove(GetHashCode()); - } - - public void SetColorWithoutRadiusHandle(Color color, float fillColorAlpha) - { - SetColorWithRadiusHandle(color, fillColorAlpha); - radiusHandleColor = Color.clear; - wireframeColor = color; - } - - public void SetColorWithRadiusHandle(Color color, float fillColorAlpha) - { - fillColor = color * new Color(1f, 1f, 1f, fillColorAlpha); - angleHandleColor = color; - radiusHandleColor = color; - wireframeColor = color; - } - - public void DrawHandle() - { - if (!m_ControlIDsReserved) - GetControlIDs(); - m_ControlIDsReserved = false; - - if (Handles.color.a == 0f) - return; - - Vector3 scale = Handles.matrix.MultiplyPoint3x4(Vector3.one) - Handles.matrix.MultiplyPoint3x4(Vector3.zero); - if (scale.x == 0f && scale.z == 0f) - return; - - Vector3 angleHandlePosition = Quaternion.AngleAxis(angle, Vector3.up) * Vector3.forward * radius; - - float absAngle = Mathf.Abs(angle); - float excessAngle = angle % 360f; - - using (new Handles.DrawingScope(Handles.color * fillColor)) - { - if (Handles.color.a > 0f) - { - for (int i = 0, revolutions = (int)absAngle / 360; i < revolutions; ++i) - Handles.DrawSolidArc(Vector3.zero, Vector3.up, Vector3.forward, 360f, radius); - Handles.DrawSolidArc(Vector3.zero, Vector3.up, Vector3.forward, excessAngle, radius); - } - } - - using (new Handles.DrawingScope(Handles.color * wireframeColor)) - { - if (Handles.color.a > 0f) - { - Handles.DrawWireArc( - Vector3.zero, Vector3.up, Vector3.forward, absAngle >= 360f ? 360f : excessAngle, radius - ); - } - } - - // unless holding alt while already manipulating a control, exit before drawing control handles when holding alt, since alt-click will rotate scene view - if (Event.current.alt) - { - bool exit = true; - foreach (var id in m_RadiusHandleControlIDs) - { - if (id == GUIUtility.hotControl) - { - exit = false; - break; - } - } - if (exit && GUIUtility.hotControl != m_AngleHandleControlID) - return; - } - - using (new Handles.DrawingScope(Handles.color * radiusHandleColor)) - { - if (Handles.color.a > 0f) - { - // draw one radius handle in each cardinal direction encompassed by the arc (i.e. every 90 degrees) - float direction = Mathf.Sign(angle); - int numRadiusHandles = Mathf.Min(1 + (int)(Mathf.Min(360f, absAngle) * 0.01111111111f), 4); - for (int i = 0; i < numRadiusHandles; ++i) - { - Quaternion handleOrientation = Quaternion.AngleAxis(i * 90f * direction, Vector3.up); - using (new Handles.DrawingScope(Handles.matrix * Matrix4x4.TRS(Vector3.zero, handleOrientation, Vector3.one))) - { - Vector3 radiusHandlePosition = Vector3.forward * radius; - Vector3 newPosition; - EditorGUI.BeginChangeCheck(); - { - var size = radiusHandleSizeFunction == null ? 0f : radiusHandleSizeFunction(radiusHandlePosition); - newPosition = Handles.Slider( - m_RadiusHandleControlIDs[i], - radiusHandlePosition, - Vector3.forward, - size, - radiusHandleDrawFunction, - SnapSettings.move.z - ); - } - if (EditorGUI.EndChangeCheck()) - { - radius += (newPosition - radiusHandlePosition).z; - } - } - } - } - } - - // draw angle handle last so it will always take precedence when overlapping a radius handle - using (new Handles.DrawingScope(Handles.color * angleHandleColor)) - { - if (Handles.color.a > 0f && angleHandleDrawFunction != null) - { - EditorGUI.BeginChangeCheck(); - { - var size = angleHandleSizeFunction == null ? 0f : angleHandleSizeFunction(angleHandlePosition); - s_CurrentlyDrawingAngleHandleHash = GetHashCode(); - angleHandlePosition = Handles.Slider2D( - m_AngleHandleControlID, - angleHandlePosition, - Vector3.up, - Vector3.forward, - Vector3.right, - size, - angleHandleDrawFunction, - Vector2.zero - ); - } - if (EditorGUI.EndChangeCheck()) - { - float newAngle = Vector3.Angle(Vector3.forward, angleHandlePosition) * - Mathf.Sign(Vector3.Dot(Vector3.right, angleHandlePosition)); - angle += Mathf.DeltaAngle(angle, newAngle); - angle = Handles.SnapValue(angle, SnapSettings.rotation); - } - } - } - } - - internal void GetControlIDs() - { - m_AngleHandleControlID = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); - for (int i = 0; i < m_RadiusHandleControlIDs.Length; ++i) - m_RadiusHandleControlIDs[i] = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); - m_ControlIDsReserved = true; - } - } -} diff --git a/Editor/Mono/EditorHandles/BoneHandle.cs b/Editor/Mono/EditorHandles/BoneHandle.cs deleted file mode 100644 index ca7696d02c..0000000000 --- a/Editor/Mono/EditorHandles/BoneHandle.cs +++ /dev/null @@ -1,234 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - public sealed partial class Handles - { - private const float k_BoneThickness = 0.08f; - - internal static float DistanceToPolygone(Vector3[] vertices) - { - return HandleUtility.DistanceToPolyLine(vertices); - } - - internal static void DoBoneHandle(Transform target) - { - DoBoneHandle(target, null); - } - - internal static void DoBoneHandle(Transform target, Dictionary validBones) - { - int id = target.name.GetHashCode(); - Event evt = Event.current; - - bool hasValidChildBones = false; - if (validBones != null) - { - foreach (Transform child in target) - { - if (validBones.ContainsKey(child)) - { - hasValidChildBones = true; - break; - } - } - } - - Vector3 basePoint = target.position; - - List endPoints = new List(); - // [case 525602] do not draw root. - if (!hasValidChildBones && target.parent != null) - { - endPoints.Add(target.position + (target.position - target.parent.position) * 0.4f); - } - else - { - foreach (Transform child in target) - { - // Only render bone connections to valid bones - // (except if no child bones are valid - then draw all connections) - if (validBones != null && !validBones.ContainsKey(child)) - continue; - - endPoints.Add(child.position); - } - } - - for (int i = 0; i < endPoints.Count; i++) - { - Vector3 endPoint = endPoints[i]; - - - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - { - float len = Vector3.Magnitude(endPoint - basePoint); - float size = len * k_BoneThickness; - Vector3[] vertices = GetBoneVertices(endPoint, basePoint, size); - - HandleUtility.AddControl(id, DistanceToPolygone(vertices)); - - break; - } - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.MouseDown: - { - // am I closest to the thingy? - if (!evt.alt && HandleUtility.nearestControl == id && evt.button == 0) - { - GUIUtility.hotControl = id; // Grab mouse focus - if (evt.shift) - { - Object[] selected = Selection.objects; - if (ArrayUtility.Contains(selected, target) == false) - { - ArrayUtility.Add(ref selected, target); - Selection.objects = selected; - } - } - else - Selection.activeObject = target; - - EditorGUIUtility.PingObject(target); - - evt.Use(); - } - break; - } - case EventType.MouseDrag: - { - if (!evt.alt && GUIUtility.hotControl == id) - { - DragAndDrop.PrepareStartDrag(); - DragAndDrop.objectReferences = new UnityEngine.Object[] {target}; - DragAndDrop.StartDrag(ObjectNames.GetDragAndDropTitle(target)); - - // having a hot control set during drag makes the control eat the drag events - // and dragging of bones no longer works over the avatar configure window - // see case 912016 - GUIUtility.hotControl = 0; - - evt.Use(); - } - break; - } - case EventType.MouseUp: - { - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - } - break; - } - case EventType.Repaint: - { - float len = Vector3.Magnitude(endPoint - basePoint); - if (len > 0) - { - color = GUIUtility.hotControl == 0 && HandleUtility.nearestControl == id ? Handles.preselectionColor : color; - - // size used to be based on sqrt of length but that makes bones for - // huge creatures hair-thin and bones for tiny creatures bulky. - // So base on a fixed proportion instead. - float size = len * k_BoneThickness; - if (hasValidChildBones) - Handles.DrawBone(endPoint, basePoint, size); - else - Handles.SphereHandleCap(id, basePoint, target.rotation, size * .2f, EventType.Repaint); - } - break; - } - } - } - } - - internal static void DrawBone(Vector3 endPoint, Vector3 basePoint, float size) - { - if (Event.current.type != EventType.Repaint) - return; - - const int sConeSides = 3; - - Vector3[] vertices = GetBoneVertices(endPoint, basePoint, size); - - HandleUtility.ApplyWireMaterial(); - - GL.Begin(GL.TRIANGLES); - GL.Color(color); - for (int i = 0; i < sConeSides; i++) - { - GL.Vertex(vertices[i * 6 + 0]); - GL.Vertex(vertices[i * 6 + 1]); - GL.Vertex(vertices[i * 6 + 2]); - - GL.Vertex(vertices[i * 6 + 3]); - GL.Vertex(vertices[i * 6 + 4]); - GL.Vertex(vertices[i * 6 + 5]); - } - GL.End(); - - GL.Begin(GL.LINES); - GL.Color(color * new Color(1, 1, 1, 0) + new Color(0, 0, 0, 1.0f)); - for (int i = 0; i < sConeSides; i++) - { - GL.Vertex(vertices[i * 6 + 0]); - GL.Vertex(vertices[i * 6 + 1]); - - GL.Vertex(vertices[i * 6 + 1]); - GL.Vertex(vertices[i * 6 + 2]); - - // No need to draw the third edge of the triangle; it's drawn by the triangles that shares the edge. - } - GL.End(); - } - - internal static Vector3[] GetBoneVertices(Vector3 endPoint, Vector3 basePoint, float radius) - { - const int sConeSides = 3; - - Vector3 direction = Vector3.Normalize(endPoint - basePoint); - Vector3 tangent = Vector3.Cross(direction, Vector3.up); - if (Vector3.SqrMagnitude(tangent) < 0.1f) - tangent = Vector3.Cross(direction, Vector3.right); - tangent.Normalize(); - Vector3 bitangent = Vector3.Cross(direction, tangent); - - Vector3[] vertices = new Vector3[sConeSides * 6]; - const float kDelta = Mathf.PI * 2.0f / sConeSides; - float phi = 0.0f; - for (int i = 0; i < sConeSides; ++i) - { - float cs1 = Mathf.Cos(phi); - float ss1 = Mathf.Sin(phi); - float cs2 = Mathf.Cos(phi + kDelta); - float ss2 = Mathf.Sin(phi + kDelta); - Vector3 p1 = basePoint + tangent * (cs1 * radius) + bitangent * (ss1 * radius); - Vector3 p2 = basePoint + tangent * (cs2 * radius) + bitangent * (ss2 * radius); - - // triangle of the cone - vertices[i * 6 + 0] = endPoint; - vertices[i * 6 + 1] = p1; - vertices[i * 6 + 2] = p2; - - // triangle of the base point disk - vertices[i * 6 + 3] = basePoint; - vertices[i * 6 + 4] = p2; - vertices[i * 6 + 5] = p1; - phi += kDelta; - } - - return vertices; - } - } -} diff --git a/Editor/Mono/EditorHandles/BoundsHandle/BoxBoundsHandle.cs b/Editor/Mono/EditorHandles/BoundsHandle/BoxBoundsHandle.cs deleted file mode 100644 index 75a24010e1..0000000000 --- a/Editor/Mono/EditorHandles/BoundsHandle/BoxBoundsHandle.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public class BoxBoundsHandle : PrimitiveBoundsHandle - { - [Obsolete("Use parameterless constructor instead.")] - public BoxBoundsHandle(int controlIDHint) : base(controlIDHint) {} - - public BoxBoundsHandle() : base() {} - - public UnityEngine.Vector3 size { get { return GetSize(); } set { SetSize(value); } } - - protected override void DrawWireframe() - { - Handles.DrawWireCube(center, size); - } - } -} diff --git a/Editor/Mono/EditorHandles/BoundsHandle/CapsuleBoundsHandle.cs b/Editor/Mono/EditorHandles/BoundsHandle/CapsuleBoundsHandle.cs deleted file mode 100644 index 116b4fac3b..0000000000 --- a/Editor/Mono/EditorHandles/BoundsHandle/CapsuleBoundsHandle.cs +++ /dev/null @@ -1,203 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public class CapsuleBoundsHandle : PrimitiveBoundsHandle - { - public enum HeightAxis { X, Y, Z } - - private const int k_DirectionX = 0; - private const int k_DirectionY = 1; - private const int k_DirectionZ = 2; - - private static readonly Vector3[] s_HeightAxes = new[] { Vector3.right, Vector3.up, Vector3.forward }; - private static readonly int[] s_NextAxis = new[] { 1, 2, 0 }; - - public HeightAxis heightAxis - { - get { return (HeightAxis)m_HeightAxis; } - set - { - int newValue = (int)value; - if (m_HeightAxis == newValue) - return; - Vector3 size = Vector3.one * radius * 2f; - size[newValue] = GetSize()[m_HeightAxis]; - m_HeightAxis = newValue; - SetSize(size); - } - } - private int m_HeightAxis = k_DirectionY; - - public float height - { - get - { - // zero out height if height axis is disabled - return !IsAxisEnabled(m_HeightAxis) ? 0f : Mathf.Max(GetSize()[m_HeightAxis], 2f * radius); - } - set - { - // height cannot be less than diameter - value = Mathf.Max(Mathf.Abs(value), 2f * radius); - if (height == value) - return; - Vector3 size = GetSize(); - size[m_HeightAxis] = value; - SetSize(size); - } - } - - public float radius - { - get - { - int radiusAxis; - // return 0 if only enabled axis is a single radius axis - if (GetRadiusAxis(out radiusAxis) || IsAxisEnabled(m_HeightAxis)) - return 0.5f * GetSize()[radiusAxis]; - else - return 0f; - } - set - { - Vector3 size = GetSize(); - float diameter = 2f * value; - // height cannot be less than diameter - for (int axis = 0; axis < 3; ++axis) - size[axis] = axis == m_HeightAxis ? Mathf.Max(size[axis], diameter) : diameter; - SetSize(size); - } - } - - [Obsolete("Use parameterless constructor instead.")] - public CapsuleBoundsHandle(int controlIDHint) : base(controlIDHint) {} - - public CapsuleBoundsHandle() : base() {} - - protected override void DrawWireframe() - { - HeightAxis radAxis1 = HeightAxis.Y; - HeightAxis radAxis2 = HeightAxis.Z; - switch (heightAxis) - { - case HeightAxis.Y: - radAxis1 = HeightAxis.Z; - radAxis2 = HeightAxis.X; - break; - case HeightAxis.Z: - radAxis1 = HeightAxis.X; - radAxis2 = HeightAxis.Y; - break; - } - bool doHeightAxis = IsAxisEnabled((int)heightAxis); - bool doRadiusAxis1 = IsAxisEnabled((int)radAxis1); - bool doRadiusAxis2 = IsAxisEnabled((int)radAxis2); - - Vector3 hgtAx = s_HeightAxes[m_HeightAxis]; - Vector3 radAx1 = s_HeightAxes[s_NextAxis[m_HeightAxis]]; - Vector3 radAx2 = s_HeightAxes[s_NextAxis[s_NextAxis[m_HeightAxis]]]; - float rad = radius; - float hgt = height; - Vector3 top = center + hgtAx * (hgt * 0.5f - rad); - Vector3 bottom = center - hgtAx * (hgt * 0.5f - rad); - - // draw caps and connecting lines for each enabled axis if height axis is enabled - if (doHeightAxis) - { - if (doRadiusAxis2) - { - Handles.DrawWireArc(top, radAx1, radAx2, 180f, rad); - Handles.DrawWireArc(bottom, radAx1, radAx2, -180f, rad); - Handles.DrawLine(top + radAx2 * rad, bottom + radAx2 * rad); - Handles.DrawLine(top - radAx2 * rad, bottom - radAx2 * rad); - } - if (doRadiusAxis1) - { - Handles.DrawWireArc(top, radAx2, radAx1, -180f, rad); - Handles.DrawWireArc(bottom, radAx2, radAx1, 180f, rad); - Handles.DrawLine(top + radAx1 * rad, bottom + radAx1 * rad); - Handles.DrawLine(top - radAx1 * rad, bottom - radAx1 * rad); - } - } - - // do cross-section if both radius axes are enabled - if (doRadiusAxis1 && doRadiusAxis2) - { - Handles.DrawWireArc(top, hgtAx, radAx1, 360f, rad); - Handles.DrawWireArc(bottom, hgtAx, radAx1, -360f, rad); - } - } - - protected override Bounds OnHandleChanged(HandleDirection handle, Bounds boundsOnClick, Bounds newBounds) - { - int changedAxis = k_DirectionX; - switch (handle) - { - case HandleDirection.NegativeY: - case HandleDirection.PositiveY: - changedAxis = k_DirectionY; - break; - case HandleDirection.NegativeZ: - case HandleDirection.PositiveZ: - changedAxis = k_DirectionZ; - break; - } - - Vector3 upperBound = newBounds.max; - Vector3 lowerBound = newBounds.min; - - // ensure height cannot be made less than diameter - if (changedAxis == m_HeightAxis) - { - int radiusAxis; - GetRadiusAxis(out radiusAxis); - float diameter = upperBound[radiusAxis] - lowerBound[radiusAxis]; - float newHeight = upperBound[m_HeightAxis] - lowerBound[m_HeightAxis]; - if (newHeight < diameter) - { - if (handle == HandleDirection.PositiveX || handle == HandleDirection.PositiveY || handle == HandleDirection.PositiveZ) - upperBound[m_HeightAxis] = lowerBound[m_HeightAxis] + diameter; - else - lowerBound[m_HeightAxis] = upperBound[m_HeightAxis] - diameter; - } - } - // ensure radius changes uniformly and enlarges the height if necessary - else - { - // try to return height to its value at the time handle was clicked - upperBound[m_HeightAxis] = boundsOnClick.center[m_HeightAxis] + 0.5f * boundsOnClick.size[m_HeightAxis]; - lowerBound[m_HeightAxis] = boundsOnClick.center[m_HeightAxis] - 0.5f * boundsOnClick.size[m_HeightAxis]; - - float rad = 0.5f * (upperBound[changedAxis] - lowerBound[changedAxis]); - float halfCurrentHeight = 0.5f * (upperBound[m_HeightAxis] - lowerBound[m_HeightAxis]); - for (int axis = 0; axis < 3; ++axis) - { - if (axis == changedAxis) - continue; - float amt = axis == m_HeightAxis ? Mathf.Max(halfCurrentHeight, rad) : rad; - lowerBound[axis] = center[axis] - amt; - upperBound[axis] = center[axis] + amt; - } - } - return new Bounds((upperBound + lowerBound) * 0.5f, upperBound - lowerBound); - } - - // returns true only if both radius axes are enabled - private bool GetRadiusAxis(out int radiusAxis) - { - radiusAxis = s_NextAxis[m_HeightAxis]; - if (!IsAxisEnabled(radiusAxis)) - { - radiusAxis = s_NextAxis[radiusAxis]; - return false; - } - return IsAxisEnabled(s_NextAxis[radiusAxis]); - } - } -} diff --git a/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs b/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs deleted file mode 100644 index 8cdac7367a..0000000000 --- a/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs +++ /dev/null @@ -1,319 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - -namespace UnityEditor.IMGUI.Controls -{ - public abstract class PrimitiveBoundsHandle - { - [Flags] - public enum Axes - { - None = 0, - X = 1 << 0, - Y = 1 << 1, - Z = 1 << 2, - All = X | Y | Z - } - - protected enum HandleDirection - { - PositiveX, - NegativeX, - PositiveY, - NegativeY, - PositiveZ, - NegativeZ - } - - private static readonly float s_DefaultMidpointHandleSize = 0.03f; - private static readonly int[] s_NextAxis = new[] { 1, 2, 0 }; - - internal static GUIContent editModeButton - { - get - { - if (s_EditModeButton == null) - { - s_EditModeButton = new GUIContent( - EditorGUIUtility.IconContent("EditCollider").image, - 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 - ); - } - return s_EditModeButton; - } - } - private static GUIContent s_EditModeButton; - - public static float DefaultMidpointHandleSizeFunction(Vector3 position) - { - return HandleUtility.GetHandleSize(position) * s_DefaultMidpointHandleSize; - } - - private int[] m_ControlIDs = new int[6] { 0, 0, 0, 0, 0, 0 }; - private Bounds m_Bounds; - private Bounds m_BoundsOnClick; - - public Vector3 center - { - get { return m_Bounds.center; } - set { m_Bounds.center = value; } - } - - public Axes axes { get; set; } - - public Color handleColor { get; set; } - - public Color wireframeColor { get; set; } - - public Handles.CapFunction midpointHandleDrawFunction { get; set; } - - public Handles.SizeFunction midpointHandleSizeFunction { get; set; } - - [Obsolete("Use parameterless constructor instead.")] - public PrimitiveBoundsHandle(int controlIDHint) : this() {} - - public PrimitiveBoundsHandle() - { - handleColor = Color.white; - wireframeColor = Color.white; - axes = Axes.X | Axes.Y | Axes.Z; - midpointHandleDrawFunction = Handles.DotHandleCap; - midpointHandleSizeFunction = DefaultMidpointHandleSizeFunction; - } - - public void SetColor(Color color) - { - handleColor = color; - wireframeColor = color; - } - - public void DrawHandle() - { - for (int i = 0, count = m_ControlIDs.Length; i < count; ++i) - m_ControlIDs[i] = GUIUtility.GetControlID(GetHashCode(), FocusType.Passive); - - // wireframe (before handles so handles are rendered top most) - using (new Handles.DrawingScope(Handles.color * wireframeColor)) - DrawWireframe(); - - // unless holding alt to pin center, exit before drawing control handles when holding alt, since alt-click will rotate scene view - if (Event.current.alt) - { - bool exit = true; - foreach (var id in m_ControlIDs) - { - if (id == GUIUtility.hotControl) - { - exit = false; - break; - } - } - if (exit) - return; - } - - // bounding box extents - Vector3 minPos = m_Bounds.min; - Vector3 maxPos = m_Bounds.max; - - // handles - int prevHotControl = GUIUtility.hotControl; - Vector3 cameraLocalPos = Handles.inverseMatrix.MultiplyPoint(Camera.current.transform.position); - bool isCameraInsideBox = m_Bounds.Contains(cameraLocalPos); - EditorGUI.BeginChangeCheck(); - using (new Handles.DrawingScope(Handles.color * handleColor)) - MidpointHandles(ref minPos, ref maxPos, isCameraInsideBox); - bool changed = EditorGUI.EndChangeCheck(); - - // detect if any handles got hotControl - if (prevHotControl != GUIUtility.hotControl && GUIUtility.hotControl != 0) - { - m_BoundsOnClick = m_Bounds; - } - - // update if changed - if (changed) - { - // determine which handle changed to apply any further modifications - m_Bounds.center = (maxPos + minPos) * 0.5f; - m_Bounds.size = maxPos - minPos; - for (int i = 0, count = m_ControlIDs.Length; i < count; ++i) - { - if (GUIUtility.hotControl == m_ControlIDs[i]) - m_Bounds = OnHandleChanged((HandleDirection)i, m_BoundsOnClick, m_Bounds); - } - - // shift scales uniformly - if (Event.current.shift) - { - int hotControl = GUIUtility.hotControl; - Vector3 size = m_Bounds.size; - int scaleAxis = 0; - if (hotControl == m_ControlIDs[(int)HandleDirection.PositiveY] || hotControl == m_ControlIDs[(int)HandleDirection.NegativeY]) - { - scaleAxis = 1; - } - if (hotControl == m_ControlIDs[(int)HandleDirection.PositiveZ] || hotControl == m_ControlIDs[(int)HandleDirection.NegativeZ]) - { - scaleAxis = 2; - } - float scaleFactor = Mathf.Approximately(m_BoundsOnClick.size[scaleAxis], 0f) ? - 1f : size[scaleAxis] / m_BoundsOnClick.size[scaleAxis]; - int nextAxis = s_NextAxis[scaleAxis]; - size[nextAxis] = scaleFactor * m_BoundsOnClick.size[nextAxis]; - nextAxis = s_NextAxis[nextAxis]; - size[nextAxis] = scaleFactor * m_BoundsOnClick.size[nextAxis]; - m_Bounds.size = size; - } - - // alt scales from the center - if (Event.current.alt) - m_Bounds.center = m_BoundsOnClick.center; - } - } - - protected abstract void DrawWireframe(); - - protected virtual Bounds OnHandleChanged(HandleDirection handle, Bounds boundsOnClick, Bounds newBounds) - { - return newBounds; - } - - protected Vector3 GetSize() - { - Vector3 size = m_Bounds.size; - // zero out size on disabled axes - for (int axis = 0; axis < 3; ++axis) - { - if (!IsAxisEnabled(axis)) - size[axis] = 0f; - } - return size; - } - - protected void SetSize(Vector3 size) - { - m_Bounds.size = new Vector3(Mathf.Abs(size.x), Mathf.Abs(size.y), Mathf.Abs(size.z)); - } - - protected bool IsAxisEnabled(Axes axis) - { - return (axes & axis) == axis; - } - - protected bool IsAxisEnabled(int vector3Axis) - { - switch (vector3Axis) - { - case 0: - return IsAxisEnabled(Axes.X); - case 1: - return IsAxisEnabled(Axes.Y); - case 2: - return IsAxisEnabled(Axes.Z); - default: - throw new ArgumentOutOfRangeException("vector3Axis", "Must be 0, 1, or 2"); - } - } - - private void MidpointHandles(ref Vector3 minPos, ref Vector3 maxPos, bool isCameraInsideBox) - { - Vector3 xAxis = Vector3.right; - Vector3 yAxis = Vector3.up; - Vector3 zAxis = Vector3.forward; - Vector3 middle = (maxPos + minPos) * 0.5f; - - Vector3 localPos, newPos; - if (IsAxisEnabled(Axes.X)) - { - // +X - localPos = new Vector3(maxPos.x, middle.y, middle.z); - newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.PositiveX], localPos, yAxis, zAxis, isCameraInsideBox); - maxPos.x = Mathf.Max(newPos.x, minPos.x); - - // -X - localPos = new Vector3(minPos.x, middle.y, middle.z); - newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.NegativeX], localPos, yAxis, -zAxis, isCameraInsideBox); - minPos.x = Mathf.Min(newPos.x, maxPos.x); - } - - if (IsAxisEnabled(Axes.Y)) - { - // +Y - localPos = new Vector3(middle.x, maxPos.y, middle.z); - newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.PositiveY], localPos, xAxis, -zAxis, isCameraInsideBox); - maxPos.y = Mathf.Max(newPos.y, minPos.y); - - // -Y - localPos = new Vector3(middle.x, minPos.y, middle.z); - newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.NegativeY], localPos, xAxis, zAxis, isCameraInsideBox); - minPos.y = Mathf.Min(newPos.y, maxPos.y); - } - - if (IsAxisEnabled(Axes.Z)) - { - // +Z - localPos = new Vector3(middle.x, middle.y, maxPos.z); - newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.PositiveZ], localPos, yAxis, -xAxis, isCameraInsideBox); - maxPos.z = Mathf.Max(newPos.z, minPos.z); - - // -Z - localPos = new Vector3(middle.x, middle.y, minPos.z); - newPos = MidpointHandle(m_ControlIDs[(int)HandleDirection.NegativeZ], localPos, yAxis, xAxis, isCameraInsideBox); - minPos.z = Mathf.Min(newPos.z, maxPos.z); - } - } - - private Vector3 MidpointHandle(int id, Vector3 localPos, Vector3 localTangent, Vector3 localBinormal, bool isCameraInsideBox) - { - Color oldColor = Handles.color; - - AdjustMidpointHandleColor(localPos, localTangent, localBinormal, isCameraInsideBox); - - if (Handles.color.a > 0f && midpointHandleDrawFunction != null) - { - Vector3 localDir = Vector3.Cross(localTangent, localBinormal).normalized; - - var size = midpointHandleSizeFunction == null ? 0f : midpointHandleSizeFunction(localPos); - - localPos = UnityEditorInternal.Slider1D.Do( - id, localPos, localDir, size, midpointHandleDrawFunction, SnapSettings.scale - ); - } - - Handles.color = oldColor; - return localPos; - } - - private void AdjustMidpointHandleColor(Vector3 localPos, Vector3 localTangent, Vector3 localBinormal, bool isCameraInsideBox) - { - float alphaMultiplier = 1f; - - // if inside the box then ignore backfacing alpha multiplier (otherwise all handles will look disabled) - if (!isCameraInsideBox && axes == (Axes.X | Axes.Y | Axes.Z)) - { - // use tangent and binormal to calculate normal in case handle matrix is skewed - Vector3 worldTangent = Handles.matrix.MultiplyVector(localTangent); - Vector3 worldBinormal = Handles.matrix.MultiplyVector(localBinormal); - Vector3 worldDir = Vector3.Cross(worldTangent, worldBinormal).normalized; - - // adjust color if handle is backfacing - float cosV; - - if (Camera.current.orthographic) - cosV = Vector3.Dot(-Camera.current.transform.forward, worldDir); - else - cosV = Vector3.Dot((Camera.current.transform.position - Handles.matrix.MultiplyPoint(localPos)).normalized, worldDir); - - if (cosV < -0.0001f) - alphaMultiplier *= Handles.backfaceAlphaMultiplier; - } - - Handles.color *= new Color(1f, 1f, 1f, alphaMultiplier); - } - } -} diff --git a/Editor/Mono/EditorHandles/BoundsHandle/SphereBoundsHandle.cs b/Editor/Mono/EditorHandles/BoundsHandle/SphereBoundsHandle.cs deleted file mode 100644 index d06fbb469e..0000000000 --- a/Editor/Mono/EditorHandles/BoundsHandle/SphereBoundsHandle.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public class SphereBoundsHandle : PrimitiveBoundsHandle - { - [Obsolete("Use parameterless constructor instead.")] - public SphereBoundsHandle(int controlIDHint) : base(controlIDHint) {} - - public SphereBoundsHandle() : base() {} - - public float radius - { - get - { - Vector3 size = GetSize(); - float diameter = 0f; - for (int axis = 0; axis < 3; ++axis) - { - // only consider size values on enabled axes - if (IsAxisEnabled(axis)) - diameter = Mathf.Max(diameter, Mathf.Abs(size[axis])); - } - return diameter * 0.5f; - } - set { SetSize(2f * value * Vector3.one); } - } - - protected override void DrawWireframe() - { - bool x = IsAxisEnabled(Axes.X); - bool y = IsAxisEnabled(Axes.Y); - bool z = IsAxisEnabled(Axes.Z); - if (x && y) - Handles.DrawWireArc(center, Vector3.forward, Vector3.up, 360f, radius); - if (x && z) - Handles.DrawWireArc(center, Vector3.up, Vector3.right, 360f, radius); - if (y && z) - Handles.DrawWireArc(center, Vector3.right, Vector3.forward, 360f, radius); - if (x && !y && !z) - Handles.DrawLine(Vector3.right * radius, Vector3.left * radius); - if (!x && y && !z) - Handles.DrawLine(Vector3.up * radius, Vector3.down * radius); - if (!x && !y && z) - Handles.DrawLine(Vector3.forward * radius, Vector3.back * radius); - } - - protected override Bounds OnHandleChanged(HandleDirection handle, Bounds boundsOnClick, Bounds newBounds) - { - Vector3 upperBound = newBounds.max; - Vector3 lowerBound = newBounds.min; - // ensure radius changes uniformly - int changedAxis = 0; - switch (handle) - { - case HandleDirection.NegativeY: - case HandleDirection.PositiveY: - changedAxis = 1; - break; - case HandleDirection.NegativeZ: - case HandleDirection.PositiveZ: - changedAxis = 2; - break; - } - float rad = 0.5f * (upperBound[changedAxis] - lowerBound[changedAxis]); - for (int axis = 0; axis < 3; ++axis) - { - if (axis == changedAxis) - continue; - lowerBound[axis] = center[axis] - rad; - upperBound[axis] = center[axis] + rad; - } - return new Bounds((upperBound + lowerBound) * 0.5f, upperBound - lowerBound); - } - } -} diff --git a/Editor/Mono/EditorHandles/Button.cs b/Editor/Mono/EditorHandles/Button.cs deleted file mode 100644 index f924e1de24..0000000000 --- a/Editor/Mono/EditorHandles/Button.cs +++ /dev/null @@ -1,107 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - internal class Button - { - // DrawCapFunction was marked plannned obsolete by @juha on 2016-03-16, marked obsolete warning by @adamm on 2016-12-21 - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - #pragma warning disable 618 - public static bool Do(int id, Vector3 position, Quaternion direction, float size, float pickSize, Handles.DrawCapFunction capFunc) - #pragma warning restore 618 - { - Event evt = Event.current; - - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - if (GUI.enabled) - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(position, pickSize)); - break; - case EventType.MouseMove: - if (HandleUtility.nearestControl == id && evt.button == 0) - HandleUtility.Repaint(); - break; - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = id; // Grab mouse focus - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - - if (HandleUtility.nearestControl == id) - return true; - } - break; - case EventType.Repaint: - Color origColor = Handles.color; - if (HandleUtility.nearestControl == id && GUI.enabled && GUIUtility.hotControl == 0) - Handles.color = Handles.preselectionColor; - - capFunc(id, position, direction, size); - - Handles.color = origColor; - break; - } - return false; - } - - public static bool Do(int id, Vector3 position, Quaternion direction, float size, float pickSize, Handles.CapFunction capFunction) - { - Event evt = Event.current; - - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - if (GUI.enabled) - capFunction(id, position, direction, pickSize, EventType.Layout); - break; - case EventType.MouseMove: - if (HandleUtility.nearestControl == id && evt.button == 0) - HandleUtility.Repaint(); - break; - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = id; // Grab mouse focus - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - - if (HandleUtility.nearestControl == id) - return true; - } - break; - case EventType.Repaint: - Color origColor = Handles.color; - if (HandleUtility.nearestControl == id && GUI.enabled && GUIUtility.hotControl == 0) - Handles.color = Handles.preselectionColor; - - capFunction(id, position, direction, size, EventType.Repaint); - - Handles.color = origColor; - break; - } - return false; - } - } -} diff --git a/Editor/Mono/EditorHandles/ConeFrustrumHandle.cs b/Editor/Mono/EditorHandles/ConeFrustrumHandle.cs deleted file mode 100644 index d6b42a7031..0000000000 --- a/Editor/Mono/EditorHandles/ConeFrustrumHandle.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class Handles - { - // Description - // 'radius' is near-radius at start of cone frustrum (far-radius is derived from 'angle' and near-radius) - // 'angle' is cone angle from near disc of conefrustrum (if near-radius is 0 then angle is the half angle of view frustrum) - // 'range' is height of conefrustrum - internal static Vector3 DoConeFrustrumHandle(Quaternion rotation, Vector3 position, Vector3 radiusAngleRange) - { - Vector3 forward = rotation * Vector3.forward; - Vector3 up = rotation * Vector3.up; - Vector3 right = rotation * Vector3.right; - - float nearRadius = radiusAngleRange.x; - float angle = radiusAngleRange.y; - float range = radiusAngleRange.z; - - angle = Mathf.Max(0.0f, angle); - - // Range handle at the center of the cone (allow negative range) - bool temp = GUI.changed; - range = SizeSlider(position, forward, range); - GUI.changed |= temp; - - // Near plane of cone frustrum - temp = GUI.changed; - GUI.changed = false; - nearRadius = SizeSlider(position , up, nearRadius); - nearRadius = SizeSlider(position , -up, nearRadius); - nearRadius = SizeSlider(position , right, nearRadius); - nearRadius = SizeSlider(position , -right, nearRadius); - if (GUI.changed) - nearRadius = Mathf.Max(0.0f, nearRadius); - GUI.changed |= temp; - - // Far plane of cone frustrum - temp = GUI.changed; - GUI.changed = false; - float farRadius = Mathf.Min(1000f, Mathf.Abs(range * Mathf.Tan(Mathf.Deg2Rad * angle)) + nearRadius); - farRadius = SizeSlider(position + forward * range, up, farRadius); - farRadius = SizeSlider(position + forward * range, -up, farRadius); - farRadius = SizeSlider(position + forward * range, right, farRadius); - farRadius = SizeSlider(position + forward * range, -right, farRadius); - if (GUI.changed) - angle = Mathf.Clamp((Mathf.Rad2Deg * Mathf.Atan((farRadius - nearRadius) / Mathf.Abs(range))), 0.0F, 90f); - GUI.changed |= temp; - - // Draw - if (nearRadius > 0) - DrawWireDisc(position, forward, nearRadius); - - if (farRadius > 0) - DrawWireDisc(position + range * forward, forward, farRadius); - - DrawLine(position + up * nearRadius, (position + forward * range) + up * farRadius); - DrawLine(position - up * nearRadius, (position + forward * range) - up * farRadius); - DrawLine(position + right * nearRadius, (position + forward * range) + right * farRadius); - DrawLine(position - right * nearRadius, (position + forward * range) - right * farRadius); - - return new Vector3(nearRadius, angle, range); - } - } -} diff --git a/Editor/Mono/EditorHandles/ConeHandle.cs b/Editor/Mono/EditorHandles/ConeHandle.cs deleted file mode 100644 index df47a177fe..0000000000 --- a/Editor/Mono/EditorHandles/ConeHandle.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class Handles - { - internal static Vector2 DoConeHandle(Quaternion rotation, Vector3 position, Vector2 angleAndRange, float angleScale, float rangeScale, bool handlesOnly) - { - float spotAngle = angleAndRange.x; - float range = angleAndRange.y; - float actualRange = range * rangeScale; - - Vector3 forward = rotation * Vector3.forward; - Vector3 up = rotation * Vector3.up; - Vector3 right = rotation * Vector3.right; - - // Range handle at the center of the circle - bool temp = GUI.changed; - GUI.changed = false; - actualRange = SizeSlider(position, forward, actualRange); - if (GUI.changed) - range = Mathf.Max(0.0F, actualRange / rangeScale); - GUI.changed |= temp; - - // Angle handles on circle - temp = GUI.changed; - GUI.changed = false; - - float lightDisc = actualRange * Mathf.Tan(Mathf.Deg2Rad * spotAngle / 2.0f) * angleScale; - lightDisc = SizeSlider(position + forward * actualRange, up, lightDisc); - lightDisc = SizeSlider(position + forward * actualRange, -up, lightDisc); - lightDisc = SizeSlider(position + forward * actualRange, right, lightDisc); - lightDisc = SizeSlider(position + forward * actualRange, -right, lightDisc); - if (GUI.changed) - spotAngle = Mathf.Clamp((Mathf.Rad2Deg * Mathf.Atan(lightDisc / (actualRange * angleScale)) * 2), 0.0F, 179F); - GUI.changed |= temp; - - // Draw disc - if (!handlesOnly) - { - Handles.DrawLine(position, (position + forward * actualRange) + up * lightDisc); - Handles.DrawLine(position, (position + forward * actualRange) - up * lightDisc); - Handles.DrawLine(position, (position + forward * actualRange) + right * lightDisc); - Handles.DrawLine(position, (position + forward * actualRange) - right * lightDisc); - DrawWireDisc(position + actualRange * forward, forward, lightDisc); - } - - return new Vector2(spotAngle, range); - } - - static float SizeSlider(Vector3 p, Vector3 d, float r) - { - Vector3 position = p + d * r; - float size = HandleUtility.GetHandleSize(position); - bool temp = GUI.changed; - GUI.changed = false; - position = Handles.Slider(position, d, size * 0.03f, Handles.DotHandleCap, 0f); - if (GUI.changed) - r = Vector3.Dot(position - p, d); - GUI.changed |= temp; - return r; - } - } -} diff --git a/Editor/Mono/EditorHandles/Disc.cs b/Editor/Mono/EditorHandles/Disc.cs deleted file mode 100644 index 82982da2b8..0000000000 --- a/Editor/Mono/EditorHandles/Disc.cs +++ /dev/null @@ -1,207 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - internal class Disc - { - const int k_MaxSnapMarkers = 360 / 5; - const float k_RotationUnitSnapMajorMarkerStep = 45; - const float k_RotationUnitSnapMarkerSize = 0.1f; - const float k_RotationUnitSnapMajorMarkerSize = 0.2f; - const float k_GrabZoneScale = 0.3f; - - static Vector2 s_StartMousePosition, s_CurrentMousePosition; - static Vector3 s_StartPosition, s_StartAxis; - static Quaternion s_StartRotation; - static float s_RotationDist; - - public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap) - { - return Do(id, rotation, position, axis, size, cutoffPlane, snap, true, true, Handles.secondaryColor); - } - - public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap, bool enableRayDrag, bool showHotArc, Color fillColor) - { - if (Mathf.Abs(Vector3.Dot(Camera.current.transform.forward, axis)) > .999f) - cutoffPlane = false; - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - { - float d; - if (cutoffPlane) - { - Vector3 from = Vector3.Cross(axis, Camera.current.transform.forward).normalized; - d = HandleUtility.DistanceToArc(position, axis, from, 180, size) * k_GrabZoneScale; - } - else - { - d = HandleUtility.DistanceToDisc(position, axis, size) * k_GrabZoneScale; - } - - HandleUtility.AddControl(id, d); - break; - } - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && evt.button == 0) - { - GUIUtility.hotControl = id; // Grab mouse focus - Tools.LockHandlePosition(); - if (cutoffPlane) - { - Vector3 from = Vector3.Cross(axis, Camera.current.transform.forward).normalized; - s_StartPosition = HandleUtility.ClosestPointToArc(position, axis, from, 180, size); - } - else - { - s_StartPosition = HandleUtility.ClosestPointToDisc(position, axis, size); - } - s_RotationDist = 0; - s_StartRotation = rotation; - s_StartAxis = axis; - s_CurrentMousePosition = s_StartMousePosition = Event.current.mousePosition; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - // handle look to point rotation - bool rayDrag = EditorGUI.actionKey && evt.shift && enableRayDrag; - if (rayDrag) - { - if (HandleUtility.ignoreRaySnapObjects == null) - Handles.SetupIgnoreRaySnapObjects(); - object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(evt.mousePosition)); - if (hit != null && Vector3.Dot(axis.normalized, rotation * Vector3.forward) < 0.999) - { - RaycastHit rh = (RaycastHit)hit; - Vector3 lookPoint = rh.point - position; - Vector3 lookPointProjected = lookPoint - Vector3.Dot(lookPoint, axis.normalized) * axis.normalized; - rotation = Quaternion.LookRotation(lookPointProjected, rotation * Vector3.up); - } - } - else - { - Vector3 direction = Vector3.Cross(axis, position - s_StartPosition).normalized; - s_CurrentMousePosition += evt.delta; - s_RotationDist = HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, s_StartPosition, direction) / size * 30; - s_RotationDist = Handles.SnapValue(s_RotationDist, snap); - rotation = Quaternion.AngleAxis(s_RotationDist * -1, s_StartAxis) * s_StartRotation; - } - - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - Tools.UnlockHandlePosition(); - GUIUtility.hotControl = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.KeyDown: - if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == id) - { - // We do not use the event nor clear hotcontrol to ensure auto revert value kicks in from native side - Tools.UnlockHandlePosition(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.Repaint: - Color temp = Color.white; - - if (id == GUIUtility.hotControl) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - - // If we're dragging it, we'll go a bit further and draw a selection pie - if (GUIUtility.hotControl == id) - { - Color t = Handles.color; - Vector3 from = (s_StartPosition - position).normalized; - Handles.color = fillColor; - Handles.DrawLine(position, position + from * size); - var d = -Mathf.Sign(s_RotationDist) * Mathf.Repeat(Mathf.Abs(s_RotationDist), 360); - Vector3 to = Quaternion.AngleAxis(d, axis) * from; - Handles.DrawLine(position, position + to * size); - - Handles.color = fillColor * new Color(1, 1, 1, .2f); - for (int i = 0, revolutions = (int)Mathf.Abs(s_RotationDist * 0.002777777778f); i < revolutions; ++i) - Handles.DrawSolidDisc(position, axis, size); - Handles.DrawSolidArc(position, axis, from, d, size); - - // Draw snap markers - if (EditorGUI.actionKey && snap > 0) - { - DrawRotationUnitSnapMarkers(position, axis, size, k_RotationUnitSnapMarkerSize, snap, @from); - DrawRotationUnitSnapMarkers(position, axis, size, k_RotationUnitSnapMajorMarkerSize, k_RotationUnitSnapMajorMarkerStep, @from); - } - Handles.color = t; - } - - if (showHotArc && GUIUtility.hotControl == id || GUIUtility.hotControl != id && !cutoffPlane) - Handles.DrawWireDisc(position, axis, size); - else if (GUIUtility.hotControl != id && cutoffPlane) - { - Vector3 from = Vector3.Cross(axis, Camera.current.transform.forward).normalized; - Handles.DrawWireArc(position, axis, from, 180, size); - } - - if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - Handles.color = temp; - break; - } - - return rotation; - } - - static void DrawRotationUnitSnapMarkers(Vector3 position, Vector3 axis, float handleSize, float markerSize, float snap, Vector3 @from) - { - var iterationCount = Mathf.FloorToInt(360 / snap); - var performFading = iterationCount > k_MaxSnapMarkers; - var limitedIterationCount = Mathf.Min(iterationCount, k_MaxSnapMarkers); - - // center the markers around the current angle - var count = Mathf.RoundToInt(limitedIterationCount * 0.5f); - - for (var i = -count; i < count; ++i) - { - var rot = Quaternion.AngleAxis(i * snap, axis); - var u = rot * @from; - var startPoint = position + (1 - markerSize) * handleSize * u; - var endPoint = position + 1 * handleSize * u; - Handles.color = Handles.selectedColor; - if (performFading) - { - var alpha = 1 - Mathf.SmoothStep(0, 1, Mathf.Abs(i / ((float)limitedIterationCount - 1) - 0.5f) * 2); - Handles.color = new Color(Handles.color.r, Handles.color.g, Handles.color.b, alpha); - } - Handles.DrawLine(startPoint, endPoint); - } - } - } -} diff --git a/Editor/Mono/EditorHandles/FreeMove.cs b/Editor/Mono/EditorHandles/FreeMove.cs deleted file mode 100644 index e360b44307..0000000000 --- a/Editor/Mono/EditorHandles/FreeMove.cs +++ /dev/null @@ -1,300 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - internal class FreeMove - { - private static Vector2 s_StartMousePosition, s_CurrentMousePosition; - private static Vector3 s_StartPosition; - - // DrawCapFunction was marked plannned obsolete by @juha on 2016-03-16, marked obsolete warning by @adamm on 2016-12-21 - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - #pragma warning disable 618 - public static Vector3 Do(int id, Vector3 position, Quaternion rotation, float size, Vector3 snap, Handles.DrawCapFunction capFunc) - #pragma warning restore 618 - { - Vector3 worldPosition = Handles.matrix.MultiplyPoint(position); - Matrix4x4 origMatrix = Handles.matrix; - - VertexSnapping.HandleKeyAndMouseMove(id); - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - // We only want the position to be affected by the Handles.matrix. - Handles.matrix = Matrix4x4.identity; - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(worldPosition, size * 1.2f)); - Handles.matrix = origMatrix; - break; - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && evt.button == 0) - { - GUIUtility.hotControl = id; // Grab mouse focus - s_CurrentMousePosition = s_StartMousePosition = evt.mousePosition; - s_StartPosition = position; - HandleUtility.ignoreRaySnapObjects = null; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - bool rayDrag = EditorGUI.actionKey && evt.shift; - - if (rayDrag) - { - if (HandleUtility.ignoreRaySnapObjects == null) - Handles.SetupIgnoreRaySnapObjects(); - - object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(evt.mousePosition)); - if (hit != null) - { - RaycastHit rh = (RaycastHit)hit; - float offset = 0; - if (Tools.pivotMode == PivotMode.Center) - { - float geomOffset = HandleUtility.CalcRayPlaceOffset(HandleUtility.ignoreRaySnapObjects, rh.normal); - if (geomOffset != Mathf.Infinity) - { - offset = Vector3.Dot(position, rh.normal) - geomOffset; - } - } - position = Handles.inverseMatrix.MultiplyPoint(rh.point + (rh.normal * offset)); - } - else - { - rayDrag = false; - } - } - - if (!rayDrag) - { - // normal drag - s_CurrentMousePosition += new Vector2(evt.delta.x, -evt.delta.y) * EditorGUIUtility.pixelsPerPoint; - Vector3 screenPos = Camera.current.WorldToScreenPoint(Handles.matrix.MultiplyPoint(s_StartPosition)); - screenPos += (Vector3)(s_CurrentMousePosition - s_StartMousePosition); - position = Handles.inverseMatrix.MultiplyPoint(Camera.current.ScreenToWorldPoint(screenPos)); - - // Due to floating point inaccuracies, the back-and-forth transformations used may sometimes introduce - // tiny unintended movement in wrong directions. People notice when using a straight top/left/right ortho camera. - // In that case, just restrain the movement to the plane. - if (Camera.current.transform.forward == Vector3.forward || Camera.current.transform.forward == -Vector3.forward) - position.z = s_StartPosition.z; - if (Camera.current.transform.forward == Vector3.up || Camera.current.transform.forward == -Vector3.up) - position.y = s_StartPosition.y; - if (Camera.current.transform.forward == Vector3.right || Camera.current.transform.forward == -Vector3.right) - position.x = s_StartPosition.x; - - if (Tools.vertexDragging) - { - if (HandleUtility.ignoreRaySnapObjects == null) - Handles.SetupIgnoreRaySnapObjects(); - Vector3 near; - if (HandleUtility.FindNearestVertex(evt.mousePosition, null, out near)) - { - position = Handles.inverseMatrix.MultiplyPoint(near); - } - } - - if (EditorGUI.actionKey && !evt.shift) - { - Vector3 delta = position - s_StartPosition; - delta.x = Handles.SnapValue(delta.x, snap.x); - delta.y = Handles.SnapValue(delta.y, snap.y); - delta.z = Handles.SnapValue(delta.z, snap.z); - position = s_StartPosition + delta; - } - } - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - HandleUtility.ignoreRaySnapObjects = null; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.Repaint: - Color temp = Color.white; - - if (id == GUIUtility.hotControl) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - - // We only want the position to be affected by the Handles.matrix. - Handles.matrix = Matrix4x4.identity; - capFunc(id, worldPosition, Camera.current.transform.rotation, size); - Handles.matrix = origMatrix; - - if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - Handles.color = temp; - break; - } - return position; - } - - public static Vector3 Do(int id, Vector3 position, Quaternion rotation, float size, Vector3 snap, Handles.CapFunction handleFunction) - { - Vector3 worldPosition = Handles.matrix.MultiplyPoint(position); - Matrix4x4 origMatrix = Handles.matrix; - - VertexSnapping.HandleKeyAndMouseMove(id); - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - // We only want the position to be affected by the Handles.matrix. - Handles.matrix = Matrix4x4.identity; - handleFunction(id, worldPosition, Camera.current.transform.rotation, size, EventType.Layout); - Handles.matrix = origMatrix; - break; - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && evt.button == 0) - { - GUIUtility.hotControl = id; // Grab mouse focus - s_CurrentMousePosition = s_StartMousePosition = evt.mousePosition; - s_StartPosition = position; - HandleUtility.ignoreRaySnapObjects = null; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - bool rayDrag = EditorGUI.actionKey && evt.shift; - - if (rayDrag) - { - if (HandleUtility.ignoreRaySnapObjects == null) - Handles.SetupIgnoreRaySnapObjects(); - - object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(evt.mousePosition)); - if (hit != null) - { - RaycastHit rh = (RaycastHit)hit; - float offset = 0; - if (Tools.pivotMode == PivotMode.Center) - { - float geomOffset = HandleUtility.CalcRayPlaceOffset(HandleUtility.ignoreRaySnapObjects, rh.normal); - if (geomOffset != Mathf.Infinity) - { - offset = Vector3.Dot(position, rh.normal) - geomOffset; - } - } - position = Handles.inverseMatrix.MultiplyPoint(rh.point + (rh.normal * offset)); - } - else - { - rayDrag = false; - } - } - - if (!rayDrag) - { - // normal drag - s_CurrentMousePosition += new Vector2(evt.delta.x, -evt.delta.y) * EditorGUIUtility.pixelsPerPoint; - Vector3 screenPos = Camera.current.WorldToScreenPoint(Handles.matrix.MultiplyPoint(s_StartPosition)); - screenPos += (Vector3)(s_CurrentMousePosition - s_StartMousePosition); - position = Handles.inverseMatrix.MultiplyPoint(Camera.current.ScreenToWorldPoint(screenPos)); - - // Due to floating point inaccuracies, the back-and-forth transformations used may sometimes introduce - // tiny unintended movement in wrong directions. People notice when using a straight top/left/right ortho camera. - // In that case, just restrain the movement to the plane. - if (Camera.current.transform.forward == Vector3.forward || Camera.current.transform.forward == -Vector3.forward) - position.z = s_StartPosition.z; - if (Camera.current.transform.forward == Vector3.up || Camera.current.transform.forward == -Vector3.up) - position.y = s_StartPosition.y; - if (Camera.current.transform.forward == Vector3.right || Camera.current.transform.forward == -Vector3.right) - position.x = s_StartPosition.x; - - if (Tools.vertexDragging) - { - if (HandleUtility.ignoreRaySnapObjects == null) - Handles.SetupIgnoreRaySnapObjects(); - Vector3 near; - if (HandleUtility.FindNearestVertex(evt.mousePosition, null, out near)) - { - position = Handles.inverseMatrix.MultiplyPoint(near); - } - } - - if (EditorGUI.actionKey && !evt.shift) - { - Vector3 delta = position - s_StartPosition; - delta.x = Handles.SnapValue(delta.x, snap.x); - delta.y = Handles.SnapValue(delta.y, snap.y); - delta.z = Handles.SnapValue(delta.z, snap.z); - position = s_StartPosition + delta; - } - } - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - HandleUtility.ignoreRaySnapObjects = null; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.Repaint: - Color temp = Color.white; - - if (id == GUIUtility.hotControl) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - - // We only want the position to be affected by the Handles.matrix. - Handles.matrix = Matrix4x4.identity; - handleFunction(id, worldPosition, Camera.current.transform.rotation, size, EventType.Repaint); - Handles.matrix = origMatrix; - - if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - Handles.color = temp; - break; - } - return position; - } - } -} diff --git a/Editor/Mono/EditorHandles/FreeRotate.cs b/Editor/Mono/EditorHandles/FreeRotate.cs deleted file mode 100644 index 0a08ab0298..0000000000 --- a/Editor/Mono/EditorHandles/FreeRotate.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - internal class FreeRotate - { - static readonly Color s_DimmingColor = new Color(0f, 0f, 0f, 0.078f); - private static Vector2 s_CurrentMousePosition; - - public static Quaternion Do(int id, Quaternion rotation, Vector3 position, float size) - { - return Do(id, rotation, position, size, true); - } - - internal static Quaternion Do(int id, Quaternion rotation, Vector3 position, float size, bool drawCircle) - { - Vector3 worldPosition = Handles.matrix.MultiplyPoint(position); - Matrix4x4 origMatrix = Handles.matrix; - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - // We only want the position to be affected by the Handles.matrix. - Handles.matrix = Matrix4x4.identity; - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(worldPosition, size) + HandleUtility.kPickDistance); - Handles.matrix = origMatrix; - break; - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && evt.button == 0) - { - GUIUtility.hotControl = id; // Grab mouse focus - Tools.LockHandlePosition(); - s_CurrentMousePosition = evt.mousePosition; - HandleUtility.ignoreRaySnapObjects = null; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - // rayDrag rotates object to look at ray hit - bool rayDrag = EditorGUI.actionKey && evt.shift; - if (rayDrag) - { - if (HandleUtility.ignoreRaySnapObjects == null) - Handles.SetupIgnoreRaySnapObjects(); - - object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(evt.mousePosition)); - if (hit != null) - { - RaycastHit rh = (RaycastHit)hit; - Quaternion newRotation = Quaternion.LookRotation(rh.point - position); - if (Tools.pivotRotation == PivotRotation.Global) - { - Transform t = Selection.activeTransform; - if (t) - { - Quaternion delta = Quaternion.Inverse(t.rotation) * rotation; - newRotation = newRotation * delta; - } - } - rotation = newRotation; - } - } - else - { - s_CurrentMousePosition += evt.delta; - Vector3 rotDir = Camera.current.transform.TransformDirection(new Vector3(-evt.delta.y, -evt.delta.x, 0)); - rotation = Quaternion.AngleAxis(evt.delta.magnitude, rotDir.normalized) * rotation; - } - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - Tools.UnlockHandlePosition(); - GUIUtility.hotControl = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.KeyDown: - if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == id) - { - // We do not use the event nor clear hotcontrol to ensure auto revert value kicks in from native side - Tools.UnlockHandlePosition(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.Repaint: - Color temp = Color.white; - var isHot = id == GUIUtility.hotControl; - var isPreselected = id == HandleUtility.nearestControl && GUIUtility.hotControl == 0; - - if (isHot) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (isPreselected) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - - // We only want the position to be affected by the Handles.matrix. - Handles.matrix = Matrix4x4.identity; - if (drawCircle) - Handles.DrawWireDisc(worldPosition, Camera.current.transform.forward, size); - if (isPreselected || isHot) - { - Handles.color = s_DimmingColor; - Handles.DrawSolidDisc(worldPosition, Camera.current.transform.forward, size); - } - Handles.matrix = origMatrix; - - if (isHot || isPreselected) - Handles.color = temp; - break; - } - return rotation; - } - } -} diff --git a/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs b/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs deleted file mode 100644 index 2be23570a0..0000000000 --- a/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs +++ /dev/null @@ -1,529 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public class JointAngularLimitHandle - { - private enum ArcType { Solid, Wire } - - private static readonly Matrix4x4 s_XHandleOffset = - Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(90f, Vector3.forward), Vector3.one); - private static readonly Matrix4x4 s_ZHandleOffset = - Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis(90f, Vector3.left), Vector3.one); - - private static readonly float s_LockedColorAmount = 0.5f; - private static readonly Color s_LockedColor = new Color(0.5f, 0.5f, 0.5f, 0f); - - // handle functions need to be manually sorted - private static float GetSortingDistance(ArcHandle handle) - { - Vector3 worldPosition = Handles.matrix.MultiplyPoint3x4( - Quaternion.AngleAxis(handle.angle, Vector3.up) * Vector3.forward * handle.radius - ); - Vector3 toHandle = worldPosition - Camera.current.transform.position; - if (Camera.current.orthographic) - { - Vector3 lookVector = Camera.current.transform.forward; - toHandle = lookVector * Vector3.Dot(lookVector, toHandle); - } - return toHandle.sqrMagnitude; - } - - private static int CompareHandleFunctionsByDistance( - KeyValuePair func1, KeyValuePair func2 - ) - { - return func2.Value.CompareTo(func1.Value); - } - - private List> m_HandleFunctionDistances = - new List>(6); - - private ArcHandle m_XMinHandle; - private ArcHandle m_XMaxHandle; - private ArcHandle m_YMinHandle; - private ArcHandle m_YMaxHandle; - private ArcHandle m_ZMinHandle; - private ArcHandle m_ZMaxHandle; - - // when primary axis is limited, secondary and tertiary manipulators are reoriented about its average - private Matrix4x4 m_SecondaryAxesMatrix; - - public float xMin - { - get - { - switch (xMotion) - { - case ConfigurableJointMotion.Free: - return xRange.x; - case ConfigurableJointMotion.Locked: - return 0f; - default: - return Mathf.Clamp(m_XMinHandle.angle, xRange.x, m_XMaxHandle.angle); - } - } - set { m_XMinHandle.angle = value; } - } - - public float xMax - { - get - { - switch (xMotion) - { - case ConfigurableJointMotion.Free: - return xRange.y; - case ConfigurableJointMotion.Locked: - return 0f; - default: - return Mathf.Clamp(m_XMaxHandle.angle, m_XMinHandle.angle, xRange.y); - } - } - set { m_XMaxHandle.angle = value; } - } - - public float yMin - { - get - { - switch (yMotion) - { - case ConfigurableJointMotion.Free: - return yRange.x; - case ConfigurableJointMotion.Locked: - return 0f; - default: - return Mathf.Clamp(m_YMinHandle.angle, yRange.x, m_YMaxHandle.angle); - } - } - set { m_YMinHandle.angle = value; } - } - - public float yMax - { - get - { - switch (yMotion) - { - case ConfigurableJointMotion.Free: - return yRange.y; - case ConfigurableJointMotion.Locked: - return 0f; - default: - return Mathf.Clamp(m_YMaxHandle.angle, m_YMinHandle.angle, yRange.y); - } - } - set { m_YMaxHandle.angle = value; } - } - - public float zMin - { - get - { - switch (zMotion) - { - case ConfigurableJointMotion.Free: - return zRange.x; - case ConfigurableJointMotion.Locked: - return 0f; - default: - return Mathf.Clamp(m_ZMinHandle.angle, zRange.x, m_ZMaxHandle.angle); - } - } - set { m_ZMinHandle.angle = value; } - } - - public float zMax - { - get - { - switch (zMotion) - { - case ConfigurableJointMotion.Free: - return zRange.y; - case ConfigurableJointMotion.Locked: - return 0f; - default: - return Mathf.Clamp(m_ZMaxHandle.angle, m_ZMinHandle.angle, zRange.y); - } - } - set { m_ZMaxHandle.angle = value; } - } - - public Vector2 xRange { get; set; } - - public Vector2 yRange { get; set; } - - public Vector2 zRange { get; set; } - - public ConfigurableJointMotion xMotion { get; set; } - - public ConfigurableJointMotion yMotion { get; set; } - - public ConfigurableJointMotion zMotion { get; set; } - - public Color xHandleColor - { - get - { - // Handles.xAxisColor uses EditorPrefs so it cannot be called from a field initializer - if (!m_XHandleColorInitialized) - xHandleColor = Handles.xAxisColor; - return m_XMinHandle.angleHandleColor; - } - set - { - m_XMinHandle.SetColorWithoutRadiusHandle(value, fillAlpha); - m_XMaxHandle.SetColorWithoutRadiusHandle(value, fillAlpha); - m_XHandleColorInitialized = true; - } - } - private bool m_XHandleColorInitialized = false; - - public Color yHandleColor - { - get - { - // Handles.yAxisColor uses EditorPrefs so it cannot be called from a field initializer - if (!m_YHandleColorInitialized) - yHandleColor = Handles.yAxisColor; - return m_YMinHandle.angleHandleColor; - } - set - { - m_YMinHandle.SetColorWithoutRadiusHandle(value, fillAlpha); - m_YMaxHandle.SetColorWithoutRadiusHandle(value, fillAlpha); - m_YHandleColorInitialized = true; - } - } - private bool m_YHandleColorInitialized = false; - - public Color zHandleColor - { - get - { - // Handles.zAxisColor uses EditorPrefs so it cannot be called from a field initializer - if (!m_ZHandleColorInitialized) - zHandleColor = Handles.zAxisColor; - return m_ZMinHandle.angleHandleColor; - } - set - { - m_ZMinHandle.SetColorWithoutRadiusHandle(value, fillAlpha); - m_ZMaxHandle.SetColorWithoutRadiusHandle(value, fillAlpha); - m_ZHandleColorInitialized = true; - } - } - private bool m_ZHandleColorInitialized = false; - - public float radius - { - get { return m_XMinHandle.radius; } - set - { - m_XMinHandle.radius = value; - m_XMaxHandle.radius = value; - m_YMinHandle.radius = value; - m_YMaxHandle.radius = value; - m_ZMinHandle.radius = value; - m_ZMaxHandle.radius = value; - } - } - - public float fillAlpha { get; set; } - - public float wireframeAlpha { get; set; } - - public Handles.CapFunction angleHandleDrawFunction - { - get { return m_XMinHandle.angleHandleDrawFunction; } - set - { - m_XMinHandle.angleHandleDrawFunction = value; - m_XMaxHandle.angleHandleDrawFunction = value; - m_YMinHandle.angleHandleDrawFunction = value; - m_YMaxHandle.angleHandleDrawFunction = value; - m_ZMinHandle.angleHandleDrawFunction = value; - m_ZMaxHandle.angleHandleDrawFunction = value; - } - } - - public Handles.SizeFunction angleHandleSizeFunction - { - get { return m_XMinHandle.angleHandleSizeFunction; } - set - { - m_XMinHandle.angleHandleSizeFunction = value; - m_XMaxHandle.angleHandleSizeFunction = value; - m_YMinHandle.angleHandleSizeFunction = value; - m_YMaxHandle.angleHandleSizeFunction = value; - m_ZMinHandle.angleHandleSizeFunction = value; - m_ZMaxHandle.angleHandleSizeFunction = value; - } - } - - public JointAngularLimitHandle() - { - m_XMinHandle = new ArcHandle(); - m_XMaxHandle = new ArcHandle(); - m_YMinHandle = new ArcHandle(); - m_YMaxHandle = new ArcHandle(); - m_ZMinHandle = new ArcHandle(); - m_ZMaxHandle = new ArcHandle(); - xMotion = yMotion = zMotion = ConfigurableJointMotion.Limited; - radius = 1f; - fillAlpha = 0.1f; - wireframeAlpha = 1f; - xRange = yRange = zRange = new Vector2(-180f, 180f); - } - - public void DrawHandle() - { - m_SecondaryAxesMatrix = Handles.matrix; - - // ensure handle colors are up to date - xHandleColor = xHandleColor; - yHandleColor = yHandleColor; - zHandleColor = zHandleColor; - m_XMinHandle.fillColor = m_XMinHandle.wireframeColor = Color.clear; - m_XMaxHandle.fillColor = m_XMaxHandle.wireframeColor = Color.clear; - m_YMinHandle.fillColor = m_YMinHandle.wireframeColor = Color.clear; - m_YMaxHandle.fillColor = m_YMaxHandle.wireframeColor = Color.clear; - m_ZMinHandle.fillColor = m_ZMinHandle.wireframeColor = Color.clear; - m_ZMaxHandle.fillColor = m_ZMaxHandle.wireframeColor = Color.clear; - - // draw fill shapes as needed - Color fillScalar = new Color(1f, 1f, 1f, fillAlpha); - bool drawX = false, drawY = false, drawZ = false; - switch (xMotion) - { - case ConfigurableJointMotion.Free: - using (new Handles.DrawingScope(Handles.color * xHandleColor)) - { - Handles.DrawWireDisc(Vector3.zero, Vector3.right, radius); - Handles.color *= fillScalar; - Handles.DrawSolidDisc(Vector3.zero, Vector3.right, radius); - } - break; - case ConfigurableJointMotion.Limited: - drawX = true; - m_SecondaryAxesMatrix *= - Matrix4x4.TRS(Vector3.zero, Quaternion.AngleAxis((xMin + xMax) * 0.5f, Vector3.left), Vector3.one); - if (yMotion == ConfigurableJointMotion.Limited) - { - DrawMultiaxialFillShape(); - } - else - { - using (new Handles.DrawingScope(Handles.matrix * s_XHandleOffset)) - DrawArc(m_XMinHandle, m_XMaxHandle, xHandleColor * fillScalar, ArcType.Solid); - } - break; - case ConfigurableJointMotion.Locked: - using (new Handles.DrawingScope(Handles.color * Color.Lerp(xHandleColor, s_LockedColor, s_LockedColorAmount))) - Handles.DrawWireDisc(Vector3.zero, Vector3.right, radius); - break; - } - using (new Handles.DrawingScope(m_SecondaryAxesMatrix)) - { - switch (yMotion) - { - case ConfigurableJointMotion.Free: - using (new Handles.DrawingScope(Handles.color * yHandleColor)) - { - Handles.DrawWireDisc(Vector3.zero, Vector3.up, radius); - Handles.color *= fillScalar; - Handles.DrawSolidDisc(Vector3.zero, Vector3.up, radius); - } - break; - case ConfigurableJointMotion.Limited: - drawY = true; - if (xMotion != ConfigurableJointMotion.Limited) - DrawArc(m_YMinHandle, m_YMaxHandle, yHandleColor * fillScalar, ArcType.Solid); - break; - case ConfigurableJointMotion.Locked: - using (new Handles.DrawingScope(Handles.color * Color.Lerp(yHandleColor, s_LockedColor, s_LockedColorAmount))) - Handles.DrawWireDisc(Vector3.zero, Vector3.up, radius); - break; - } - switch (zMotion) - { - case ConfigurableJointMotion.Free: - using (new Handles.DrawingScope(Handles.color * zHandleColor)) - { - Handles.DrawWireDisc(Vector3.zero, Vector3.forward, radius); - Handles.color *= fillScalar; - Handles.DrawSolidDisc(Vector3.zero, Vector3.forward, radius); - } - break; - case ConfigurableJointMotion.Limited: - using (new Handles.DrawingScope(Handles.matrix * s_ZHandleOffset)) - DrawArc(m_ZMinHandle, m_ZMaxHandle, zHandleColor * fillScalar, ArcType.Solid); - drawZ = true; - break; - case ConfigurableJointMotion.Locked: - using (new Handles.DrawingScope(Handles.color * Color.Lerp(zHandleColor, s_LockedColor, s_LockedColorAmount))) - Handles.DrawWireDisc(Vector3.zero, Vector3.forward, radius); - break; - } - } - - // collect and sort handle drawing functions for all enabled axes - m_HandleFunctionDistances.Clear(); - m_XMinHandle.GetControlIDs(); - m_XMaxHandle.GetControlIDs(); - m_YMinHandle.GetControlIDs(); - m_YMaxHandle.GetControlIDs(); - m_ZMinHandle.GetControlIDs(); - m_ZMaxHandle.GetControlIDs(); - if (drawX) - { - using (new Handles.DrawingScope(Handles.matrix * s_XHandleOffset)) - { - DrawArc(m_XMinHandle, m_XMaxHandle, xHandleColor, ArcType.Wire); - - m_HandleFunctionDistances.Add(new KeyValuePair(DrawXMinHandle, GetSortingDistance(m_XMinHandle))); - m_HandleFunctionDistances.Add(new KeyValuePair(DrawXMaxHandle, GetSortingDistance(m_XMaxHandle))); - } - } - using (new Handles.DrawingScope(m_SecondaryAxesMatrix)) - { - if (drawY) - { - DrawArc(m_YMinHandle, m_YMaxHandle, yHandleColor, ArcType.Wire); - - m_HandleFunctionDistances.Add(new KeyValuePair(DrawYMinHandle, GetSortingDistance(m_YMinHandle))); - m_HandleFunctionDistances.Add(new KeyValuePair(DrawYMaxHandle, GetSortingDistance(m_YMaxHandle))); - } - if (drawZ) - { - using (new Handles.DrawingScope(Handles.matrix * s_ZHandleOffset)) - { - DrawArc(m_ZMinHandle, m_ZMaxHandle, zHandleColor, ArcType.Wire); - - m_HandleFunctionDistances.Add(new KeyValuePair(DrawZMinHandle, GetSortingDistance(m_ZMinHandle))); - m_HandleFunctionDistances.Add(new KeyValuePair(DrawZMaxHandle, GetSortingDistance(m_ZMaxHandle))); - } - } - } - m_HandleFunctionDistances.Sort(CompareHandleFunctionsByDistance); - - // draw handles - foreach (var handleFunction in m_HandleFunctionDistances) - handleFunction.Key(); - } - - private void DrawArc(ArcHandle minHandle, ArcHandle maxHandle, Color color, ArcType arcType) - { - float angle = maxHandle.angle - minHandle.angle; - Vector3 forward = Quaternion.AngleAxis(minHandle.angle, Vector3.up) * Vector3.forward; - using (new Handles.DrawingScope(Handles.color * color)) - { - if (arcType == ArcType.Solid) - { - for (int i = 0, revolutions = (int)Mathf.Abs(angle) / 360; i < revolutions; ++i) - Handles.DrawSolidArc(Vector3.zero, Vector3.up, Vector3.forward, 360f, radius); - Handles.DrawSolidArc(Vector3.zero, Vector3.up, forward, angle % 360f, radius); - } - else - { - for (int i = 0, revolutions = (int)Mathf.Abs(angle) / 360; i < revolutions; ++i) - Handles.DrawWireArc(Vector3.zero, Vector3.up, Vector3.forward, 360f, radius); - Handles.DrawWireArc(Vector3.zero, Vector3.up, forward, angle % 360f, radius); - } - } - } - - private void DrawMultiaxialFillShape() - { - Quaternion toXMin = Quaternion.AngleAxis(xMin, Vector3.left); - Quaternion toXMax = Quaternion.AngleAxis(xMax, Vector3.left); - Quaternion toYMin = Quaternion.AngleAxis(yMin, Vector3.up); - Quaternion toYMax = Quaternion.AngleAxis(yMax, Vector3.up); - - Color fillAlphaScalar = new Color(1f, 1f, 1f, fillAlpha); - Vector3 start; - using (new Handles.DrawingScope(Handles.color * (yHandleColor * fillAlphaScalar))) - { - float yAngle = yMax - yMin; - - start = toXMax * toYMax * Vector3.forward; - Handles.DrawSolidArc(Vector3.zero, toXMax * Vector3.down, start, yAngle, radius); - - start = toXMin * toYMax * Vector3.forward; - Handles.DrawSolidArc(Vector3.zero, toXMin * Vector3.down, start, yAngle, radius); - } - using (new Handles.DrawingScope(Handles.color * (xHandleColor * fillAlphaScalar))) - { - float xAngle = xMax - xMin; - - start = toXMax * toYMax * Vector3.forward; - Handles.DrawSolidArc(Vector3.zero, Vector3.right, start, xAngle, radius); - - start = toXMax * toYMin * Vector3.forward; - Handles.DrawSolidArc(Vector3.zero, Vector3.right, start, xAngle, radius); - } - } - - private void DrawXMinHandle() - { - using (new Handles.DrawingScope(Handles.matrix * s_XHandleOffset)) - { - m_XMinHandle.DrawHandle(); - m_XMinHandle.angle = Mathf.Clamp(m_XMinHandle.angle, xRange.x, m_XMaxHandle.angle); - } - } - - private void DrawXMaxHandle() - { - using (new Handles.DrawingScope(Handles.matrix * s_XHandleOffset)) - { - m_XMaxHandle.DrawHandle(); - m_XMaxHandle.angle = Mathf.Clamp(m_XMaxHandle.angle, m_XMinHandle.angle, xRange.y); - } - } - - private void DrawYMinHandle() - { - using (new Handles.DrawingScope(m_SecondaryAxesMatrix)) - { - m_YMinHandle.DrawHandle(); - m_YMinHandle.angle = Mathf.Clamp(m_YMinHandle.angle, yRange.x, m_YMaxHandle.angle); - } - } - - private void DrawYMaxHandle() - { - using (new Handles.DrawingScope(m_SecondaryAxesMatrix)) - { - m_YMaxHandle.DrawHandle(); - m_YMaxHandle.angle = Mathf.Clamp(m_YMaxHandle.angle, m_YMinHandle.angle, yRange.y); - } - } - - private void DrawZMinHandle() - { - using (new Handles.DrawingScope(m_SecondaryAxesMatrix * s_ZHandleOffset)) - { - m_ZMinHandle.DrawHandle(); - m_ZMinHandle.angle = Mathf.Clamp(m_ZMinHandle.angle, zRange.x, m_ZMaxHandle.angle); - } - } - - private void DrawZMaxHandle() - { - using (new Handles.DrawingScope(m_SecondaryAxesMatrix * s_ZHandleOffset)) - { - m_ZMaxHandle.DrawHandle(); - m_ZMaxHandle.angle = Mathf.Clamp(m_ZMaxHandle.angle, m_ZMinHandle.angle, zRange.y); - } - } - } -} diff --git a/Editor/Mono/EditorHandles/PositionHandle.cs b/Editor/Mono/EditorHandles/PositionHandle.cs deleted file mode 100644 index 578c7b7369..0000000000 --- a/Editor/Mono/EditorHandles/PositionHandle.cs +++ /dev/null @@ -1,452 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class Handles - { - internal struct PositionHandleIds - { - public static PositionHandleIds @default - { - get - { - return new PositionHandleIds( - GUIUtility.GetControlID(s_xAxisMoveHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_yAxisMoveHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_zAxisMoveHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_xyAxisMoveHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_xzAxisMoveHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_yzAxisMoveHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_FreeMoveHandleHash, FocusType.Passive) - ); - } - } - - public readonly int x, y, z, xy, yz, xz, xyz; - - public int this[int index] - { - get - { - switch (index) - { - case 0: return x; - case 1: return y; - case 2: return z; - case 3: return xy; - case 4: return yz; - case 5: return xz; - case 6: return xyz; - } - return -1; - } - } - - public bool Has(int id) - { - return x == id - || y == id - || z == id - || xy == id - || yz == id - || xz == id - || xyz == id; - } - - public PositionHandleIds(int x, int y, int z, int xy, int xz, int yz, int xyz) - { - this.x = x; - this.y = y; - this.z = z; - this.xy = xy; - this.yz = yz; - this.xz = xz; - this.xyz = xyz; - } - - public override int GetHashCode() - { - return x ^ y ^ z ^ xy ^ xz ^ yz ^ xyz; - } - - public override bool Equals(object obj) - { - if (!(obj is PositionHandleIds)) - return false; - - var o = (PositionHandleIds)obj; - return o.x == x && o.y == y && o.z == z - && o.xy == xy && o.xz == xz && o.yz == yz - && o.xyz == xyz; - } - } - - internal struct PositionHandleParam - { - public static PositionHandleParam DefaultHandle = new PositionHandleParam( - Handle.X | Handle.Y | Handle.Z | Handle.XY | Handle.XZ | Handle.YZ, - Vector3.zero, Vector3.one, Vector3.zero, Vector3.one * 0.25f, - Orientation.Signed, Orientation.Camera); - public static PositionHandleParam DefaultFreeMoveHandle = new PositionHandleParam( - Handle.X | Handle.Y | Handle.Z | Handle.XYZ, - Vector3.zero, Vector3.one, Vector3.zero, Vector3.one * 0.25f, - Orientation.Signed, Orientation.Signed); - - [Flags] - public enum Handle - { - X = 1 << 0, - Y = 1 << 1, - Z = 1 << 2, - XY = 1 << 3, - YZ = 1 << 4, - XZ = 1 << 5, - XYZ = 1 << 6 - } - - public enum Orientation - { - Signed, - Camera - } - - public readonly Vector3 axisOffset; - public readonly Vector3 axisSize; - public readonly Vector3 planeOffset; - public readonly Vector3 planeSize; - public readonly Handle handles; - public readonly Orientation axesOrientation; - public readonly Orientation planeOrientation; - - public bool ShouldShow(int axis) - { - return (handles & (Handle)(1 << axis)) != 0; - } - - public bool ShouldShow(Handle handle) - { - return (handles & handle) != 0; - } - - public PositionHandleParam( - Handle handles, - Vector3 axisOffset, - Vector3 axisSize, - Vector3 planeOffset, - Vector3 planeSize, - Orientation axesOrientation, - Orientation planeOrientation) - { - this.axisOffset = axisOffset; - this.axisSize = axisSize; - this.planeOffset = planeOffset; - this.planeSize = planeSize; - this.handles = handles; - this.axesOrientation = axesOrientation; - this.planeOrientation = planeOrientation; - } - } - - static Vector3[] verts = {Vector3.zero, Vector3.zero, Vector3.zero, Vector3.zero}; - - const float kFreeMoveHandleSizeFactor = 0.15f; - - // While the user has Free Move mode turned on by holding 'shift' or 'V' (for Vertex Snapping), - // this variable will be set to True. - static bool s_FreeMoveMode = false; - - // Which octant the planar move handles are in. - static Vector3 s_PlanarHandlesOctant = Vector3.one; - static Vector3 s_DoPositionHandle_AxisHandlesOctant = Vector3.one; - - // If the user is currently mouse dragging then this value will be True - // and will disallow toggling Free Move mode on or off, or changing the octant of the planar handles. - static bool currentlyDragging { get { return EditorGUIUtility.hotControl != 0; } } - - static Vector3 s_DoPositionHandle_ArrowCapConeOffset = Vector3.zero; - - public static Vector3 DoPositionHandle(Vector3 position, Quaternion rotation) - { - return DoPositionHandle(PositionHandleIds.@default, position, rotation); - } - - internal static Vector3 DoPositionHandle(PositionHandleIds ids, Vector3 position, Quaternion rotation) - { - Event evt = Event.current; - switch (evt.type) - { - case EventType.KeyDown: - // Holding 'V' turns on the FreeMove transform gizmo and enables vertex snapping. - if (evt.keyCode == KeyCode.V && !currentlyDragging) - { - s_FreeMoveMode = true; - } - break; - - case EventType.KeyUp: - // If the user has released the 'V' key, then rendering the transform gizmo - // one last time with Free Move mode off is technically incorrect since it can - // add one additional frame of input with FreeMove enabled, but the - // implementation is a fair bit simpler this way. - // Basic idea: Leave this call above the 'if' statement. - position = DoPositionHandle_Internal(ids, position, rotation, PositionHandleParam.DefaultHandle); - if (evt.keyCode == KeyCode.V && !evt.shift && !currentlyDragging) - { - s_FreeMoveMode = false; - } - return position; - - case EventType.Layout: - if (!currentlyDragging && !Tools.vertexDragging) - { - s_FreeMoveMode = evt.shift; - } - break; - } - - var param = s_FreeMoveMode ? PositionHandleParam.DefaultFreeMoveHandle : PositionHandleParam.DefaultHandle; - - return DoPositionHandle_Internal(ids, position, rotation, param); - } - - static float[] s_DoPositionHandle_Internal_CameraViewLerp = new float[6]; - static string[] s_DoPositionHandle_Internal_AxisNames = { "xAxis", "yAxis", "zAxis" }; - static int[] s_DoPositionHandle_Internal_NextIndex = { 1, 2, 0 }; - static int[] s_DoPositionHandle_Internal_PrevIndex = { 2, 0, 1 }; - static int[] s_DoPositionHandle_Internal_PrevPlaneIndex = { 5, 3, 4 }; - static Vector3 DoPositionHandle_Internal(PositionHandleIds ids, Vector3 position, Quaternion rotation, PositionHandleParam param) - { - Color temp = color; - - bool isStatic = (!Tools.s_Hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); - - // Calculate the camera view vector in Handle draw space - // this handle the case where the matrix is skewed - var handlePosition = matrix.MultiplyPoint3x4(position); - var drawToWorldMatrix = matrix * Matrix4x4.TRS(position, rotation, Vector3.one); - var invDrawToWorldMatrix = drawToWorldMatrix.inverse; - var viewVectorDrawSpace = GetCameraViewFrom(handlePosition, invDrawToWorldMatrix); - - var size = HandleUtility.GetHandleSize(position); - - // Calculate per axis camera lerp - for (var i = 0; i < 3; ++i) - s_DoPositionHandle_Internal_CameraViewLerp[i] = ids[i] == GUIUtility.hotControl ? 0 : GetCameraViewLerpForWorldAxis(viewVectorDrawSpace, GetAxisVector(i)); - // Calculate per plane camera lerp (xy, yz, xz) - for (var i = 0; i < 3; ++i) - s_DoPositionHandle_Internal_CameraViewLerp[3 + i] = Mathf.Max(s_DoPositionHandle_Internal_CameraViewLerp[i], s_DoPositionHandle_Internal_CameraViewLerp[(i + 1) % 3]); - - var isHot = ids.Has(GUIUtility.hotControl); - var axisOffset = param.axisOffset; - var planeOffset = param.planeOffset; - if (isHot) - { - axisOffset = Vector3.zero; - planeOffset = Vector3.zero; - } - - // Draw plane handles (xy, yz, xz) - var planeSize = isHot ? param.planeSize + param.planeOffset : param.planeSize; - for (var i = 0; i < 3; ++i) - { - if (!param.ShouldShow(3 + i) || isHot && ids[3 + i] != GUIUtility.hotControl) - continue; - - var cameraLerp = isHot ? 0 : s_DoPositionHandle_Internal_CameraViewLerp[3 + i]; - if (cameraLerp <= kCameraViewThreshold) - { - var offset = planeOffset * size; - offset[s_DoPositionHandle_Internal_PrevIndex[i]] = 0; - var planarSize = Mathf.Max(planeSize[i], planeSize[s_DoPositionHandle_Internal_NextIndex[i]]); - position = DoPlanarHandle(ids[3 + i], i, position, offset, rotation, size * planarSize, cameraLerp, viewVectorDrawSpace, param.planeOrientation); - } - } - - // Draw axis sliders - // Draw last to have priority over the planes - for (var i = 0; i < 3; ++i) - { - if (!param.ShouldShow(i)) - continue; - - if (!currentlyDragging) - { - switch (param.axesOrientation) - { - case PositionHandleParam.Orientation.Camera: - s_DoPositionHandle_AxisHandlesOctant[i] = viewVectorDrawSpace[i] > 0.01f ? -1 : 1; - break; - case PositionHandleParam.Orientation.Signed: - s_DoPositionHandle_AxisHandlesOctant[i] = 1; - break; - } - } - - var isThisAxisHot = isHot && ids[i] == GUIUtility.hotControl; - - var axisColor = GetColorByAxis(i); - color = isStatic ? Color.Lerp(axisColor, staticColor, staticBlend) : axisColor; - GUI.SetNextControlName(s_DoPositionHandle_Internal_AxisNames[i]); - - // if we are hot here, the hot handle must be opaque - var cameraLerp = isThisAxisHot ? 0 : s_DoPositionHandle_Internal_CameraViewLerp[i]; - - if (cameraLerp <= kCameraViewThreshold) - { - color = Color.Lerp(color, Color.clear, cameraLerp); - var axisVector = GetAxisVector(i); - var dir = rotation * axisVector; - var offset = dir * axisOffset[i] * size; - - dir *= s_DoPositionHandle_AxisHandlesOctant[i]; - offset *= s_DoPositionHandle_AxisHandlesOctant[i]; - - if (isHot && !isThisAxisHot) - color = s_DisabledHandleColor; - - // A plane with this axis is hot - if (isHot && (ids[s_DoPositionHandle_Internal_PrevPlaneIndex[i]] == GUIUtility.hotControl || ids[i + 3] == GUIUtility.hotControl)) - color = selectedColor; - - color = ToActiveColorSpace(color); - - s_DoPositionHandle_ArrowCapConeOffset = isHot - ? rotation * Vector3.Scale(Vector3.Scale(axisVector, param.axisOffset), s_DoPositionHandle_AxisHandlesOctant) - : Vector3.zero; - position = Slider(ids[i], position, offset, dir, size * param.axisSize[i], DoPositionHandle_ArrowCap, GridSnapping.active ? 0f : SnapSettings.move[i]); - } - } - - VertexSnapping.HandleKeyAndMouseMove(ids.xyz); - if (param.ShouldShow(PositionHandleParam.Handle.XYZ) && (isHot && ids.xyz == GUIUtility.hotControl || !isHot)) - { - color = ToActiveColorSpace(centerColor); - GUI.SetNextControlName("FreeMoveAxis"); - position = FreeMoveHandle(ids.xyz, position, rotation, size * kFreeMoveHandleSizeFactor, GridSnapping.active ? Vector3.zero : SnapSettings.move, RectangleHandleCap); - } - - color = temp; - - if (GridSnapping.active) - position = GridSnapping.Snap(position); - - return position; - } - - static Vector3 DoPlanarHandle( - int id, - int planePrimaryAxis, - Vector3 position, - Vector3 offset, - Quaternion rotation, - float handleSize, - float cameraLerp, - Vector3 viewVectorDrawSpace, - PositionHandleParam.Orientation orientation) - { - var positionOffset = offset; - - var axis1index = planePrimaryAxis; - var axis2index = (axis1index + 1) % 3; - var axisNormalIndex = (axis1index + 2) % 3; - - Color prevColor = Handles.color; - - bool isStatic = (!Tools.s_Hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); - color = isStatic ? staticColor : GetColorByAxis(axisNormalIndex); - color = Color.Lerp(color, Color.clear, cameraLerp); - - var updateOpacityFillColor = false; - if (GUIUtility.hotControl == id) - color = selectedColor; - else if (HandleUtility.nearestControl == id) - color = preselectionColor; - else - updateOpacityFillColor = true; - - color = ToActiveColorSpace(color); - - - // NOTE: The planar transform handles always face toward the camera so they won't - // obscure each other (unlike the X, Y, and Z axis handles which always face in the - // positive axis directions). Whenever the octant that the camera is in (relative to - // to the transform tool) changes, we need to move the planar transform handle - // positions to the correct octant. - - // Comments below assume axis1 is X and axis2 is Z to make it easier to visualize things. - - // Shift the planar transform handle in the positive direction by half its - // handleSize so that it doesn't overlap in the center of the transform gizmo, - // and also move the handle origin into the octant that the camera is in. - // Don't update the actant while dragging to avoid too much distraction. - if (!currentlyDragging) - { - switch (orientation) - { - case PositionHandleParam.Orientation.Camera: - // Offset the X position of the handle in negative direction if camera is in the -X octants; otherwise positive. - // Test against -0.01 instead of 0 to give a little bias to the positive quadrants. This looks better in axis views. - s_PlanarHandlesOctant[axis1index] = (viewVectorDrawSpace[axis1index] > 0.01f ? -1 : 1); - // Likewise with the other axis. - s_PlanarHandlesOctant[axis2index] = (viewVectorDrawSpace[axis2index] > 0.01f ? -1 : 1); - break; - case PositionHandleParam.Orientation.Signed: - s_PlanarHandlesOctant[axis1index] = 1; - s_PlanarHandlesOctant[axis2index] = 1; - break; - } - } - Vector3 handleOffset = s_PlanarHandlesOctant; - // Zero out the offset along the normal axis. - handleOffset[axisNormalIndex] = 0; - positionOffset = rotation * Vector3.Scale(positionOffset, handleOffset); - // Rotate and scale the offset - handleOffset = rotation * (handleOffset * handleSize * 0.5f); - - // Calculate 3 axes - Vector3 axis1 = Vector3.zero; - Vector3 axis2 = Vector3.zero; - Vector3 axisNormal = Vector3.zero; - axis1[axis1index] = 1; - axis2[axis2index] = 1; - axisNormal[axisNormalIndex] = 1; - axis1 = rotation * axis1; - axis2 = rotation * axis2; - axisNormal = rotation * axisNormal; - - // Draw the "filler" color for the handle - verts[0] = position + positionOffset + handleOffset + (axis1 + axis2) * handleSize * 0.5f; - verts[1] = position + positionOffset + handleOffset + (-axis1 + axis2) * handleSize * 0.5f; - verts[2] = position + positionOffset + handleOffset + (-axis1 - axis2) * handleSize * 0.5f; - verts[3] = position + positionOffset + handleOffset + (axis1 - axis2) * handleSize * 0.5f; - Color faceColor = updateOpacityFillColor ? new Color(color.r, color.g, color.b, 0.1f) : color; - faceColor = ToActiveColorSpace(faceColor); - Handles.DrawSolidRectangleWithOutline(verts, faceColor, Color.clear); - - // And then render the handle itself (this is the colored outline) - position = Slider2D(id, - position, - handleOffset + positionOffset, - axisNormal, - axis1, axis2, - handleSize * 0.5f, - RectangleHandleCap, - GridSnapping.active ? Vector2.zero : new Vector2(SnapSettings.move[axis1index], SnapSettings.move[axis2index]), - false); - - Handles.color = prevColor; - - return position; - } - - static void DoPositionHandle_ArrowCap(int controlId, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - ArrowHandleCap(controlId, position, rotation, size, eventType, s_DoPositionHandle_ArrowCapConeOffset); - } - } -} diff --git a/Editor/Mono/EditorHandles/RadiusHandle.cs b/Editor/Mono/EditorHandles/RadiusHandle.cs deleted file mode 100644 index 910cad534d..0000000000 --- a/Editor/Mono/EditorHandles/RadiusHandle.cs +++ /dev/null @@ -1,142 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class Handles - { - internal static float DoRadiusHandle(Quaternion rotation, Vector3 position, float radius, bool handlesOnly) - { - Vector3 planeNormal; - float frontAngle = 90; - Vector3[] dirs = new[] { - rotation * Vector3.right, - rotation * Vector3.up, - rotation * Vector3.forward, - rotation * -Vector3.right, - rotation * -Vector3.up, - rotation * -Vector3.forward - }; - - if (Camera.current.orthographic) - { - planeNormal = Camera.current.transform.forward; - - if (!handlesOnly) - { - // Draw periphery circle - DrawWireDisc(position, planeNormal, radius); - - // Draw two-shaded axis-aligned circles - for (int i = 0; i < 3; i++) - { - Vector3 from = Vector3.Cross(dirs[i], planeNormal).normalized; - DrawTwoShadedWireDisc(position, dirs[i], from, 180, radius); - } - } - } - else - { - // Since the geometry is transfromed by Handles.matrix during rendering, we transform the camera position - // by the inverse matrix so that the two-shaded wireframe will have the proper orientation. - Matrix4x4 invMatrix = Matrix4x4.Inverse(Handles.matrix); - - planeNormal = position - invMatrix.MultiplyPoint(Camera.current.transform.position); // vector from camera to center - float sqrDist = planeNormal.sqrMagnitude; // squared distance from camera to center - float sqrRadius = radius * radius; // squared radius - float sqrOffset = sqrRadius * sqrRadius / sqrDist; // squared distance from actual center to drawn disc center - float insideAmount = sqrOffset / sqrRadius; - - // If we are not inside the sphere, calculate where to draw the periphery - if (insideAmount < 1) - { - float drawnRadius = Mathf.Sqrt(sqrRadius - sqrOffset); // the radius of the drawn disc - frontAngle = Mathf.Atan2(drawnRadius, Mathf.Sqrt(sqrOffset)) * Mathf.Rad2Deg; - - // Draw periphery circle - if (!handlesOnly) - DrawWireDisc(position - sqrRadius * planeNormal / sqrDist, planeNormal, drawnRadius); - } - else - { - frontAngle = -1000; - } - - if (!handlesOnly) - { - // Draw two-shaded axis-aligned circles - for (int i = 0; i < 3; i++) - { - if (insideAmount < 1) - { - float Q = Vector3.Angle(planeNormal, dirs[i]); - Q = 90 - Mathf.Min(Q, 180 - Q); - float f = Mathf.Tan(Q * Mathf.Deg2Rad); - float g = Mathf.Sqrt(sqrOffset + f * f * sqrOffset) / radius; - if (g < 1) - { - float e = Mathf.Asin(g) * Mathf.Rad2Deg; - Vector3 from = Vector3.Cross(dirs[i], planeNormal).normalized; - from = Quaternion.AngleAxis(e, dirs[i]) * from; - DrawTwoShadedWireDisc(position, dirs[i], from, (90 - e) * 2, radius); - } - else - { - DrawTwoShadedWireDisc(position, dirs[i], radius); - } - } - else - { - DrawTwoShadedWireDisc(position, dirs[i], radius); - } - } - } - } - - Color origCol = color; - - // Draw handles - for (int i = 0; i < 6; i++) - { - // Get the id no matter if we're drawing the slider or not, - // in order to not corrupt the id order when slider handles pop in and out. - int id = GUIUtility.GetControlID(s_RadiusHandleHash, FocusType.Passive); - - // The angle between the axis and the center-camera vector - float angle = Vector3.Angle(dirs[i], -planeNormal); - - // Don't make the slider if the axis is pointing almost towards or away from the camera, - // but always draw it if the user is already dragging it. - if ((angle > 5 && angle < 175) || GUIUtility.hotControl == id) - { - // Give handles twice the alpha of the lines. - // If handle is not on front side of sphere, make it dimmer. - Color col = origCol; - if (angle > frontAngle + 5f) - col.a = Mathf.Clamp01(backfaceAlphaMultiplier * origCol.a * 2); - else - col.a = Mathf.Clamp01(origCol.a * 2); - color = ToActiveColorSpace(col); - - Vector3 pos = position + radius * dirs[i]; - bool temp = GUI.changed; - GUI.changed = false; - pos = Slider1D.Do(id, pos, dirs[i], HandleUtility.GetHandleSize(pos) * 0.03f, DotHandleCap, 0); - - - if (GUI.changed) - radius = Vector3.Distance(pos, position); - GUI.changed |= temp; - } - } - - color = origCol; - - return radius; - } - } -} diff --git a/Editor/Mono/EditorHandles/RectHandle.cs b/Editor/Mono/EditorHandles/RectHandle.cs deleted file mode 100644 index d05ee39454..0000000000 --- a/Editor/Mono/EditorHandles/RectHandle.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class Handles - { - internal static Vector2 DoRectHandles(Quaternion rotation, Vector3 position, Vector2 size) - { - Vector3 forward = rotation * Vector3.forward; - Vector3 up = rotation * Vector3.up; - Vector3 right = rotation * Vector3.right; - - float halfWidth = 0.5f * size.x; - float halfHeight = 0.5f * size.y; - - Vector3 topRight = position + up * halfHeight + right * halfWidth; - Vector3 bottomRight = position - up * halfHeight + right * halfWidth; - Vector3 bottomLeft = position - up * halfHeight - right * halfWidth; - Vector3 topLeft = position + up * halfHeight - right * halfWidth; - - // Draw rectangle - DrawLine(topRight, bottomRight); - DrawLine(bottomRight, bottomLeft); - DrawLine(bottomLeft, topLeft); - DrawLine(topLeft, topRight); - - // Give handles twice the alpha of the lines - Color col = Handles.color; - col.a = Mathf.Clamp01(col.a * 2); - Handles.color = col; - - // Draw handles - halfHeight = SizeSlider(position, up, halfHeight); - halfHeight = SizeSlider(position, -up, halfHeight); - halfWidth = SizeSlider(position, right, halfWidth); - halfWidth = SizeSlider(position, -right, halfWidth); - - // Draw the area light's normal only if it will not overlap with the current tool - if (!((Tools.current == Tool.Move || Tools.current == Tool.Scale) && Tools.pivotRotation == PivotRotation.Local)) - DrawLine(position, position + forward); - - size.x = 2.0f * halfWidth; - size.y = 2.0f * halfHeight; - - return size; - } - } -} diff --git a/Editor/Mono/EditorHandles/RotationHandle.cs b/Editor/Mono/EditorHandles/RotationHandle.cs deleted file mode 100644 index 736920a39b..0000000000 --- a/Editor/Mono/EditorHandles/RotationHandle.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class Handles - { - internal struct RotationHandleIds - { - public static RotationHandleIds @default - { - get - { - return new RotationHandleIds( - GUIUtility.GetControlID(s_xRotateHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_yRotateHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_zRotateHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_cameraAxisRotateHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_xyzRotateHandleHash, FocusType.Passive) - ); - } - } - - public readonly int x, y, z, cameraAxis, xyz; - - public int this[int index] - { - get - { - switch (index) - { - case 0: return x; - case 1: return y; - case 2: return z; - case 3: return cameraAxis; - case 4: return xyz; - } - return -1; - } - } - - public bool Has(int id) - { - return x == id - || y == id - || z == id - || cameraAxis == id - || xyz == id; - } - - public RotationHandleIds(int x, int y, int z, int cameraAxis, int xyz) - { - this.x = x; - this.y = y; - this.z = z; - this.cameraAxis = cameraAxis; - this.xyz = xyz; - } - - public override int GetHashCode() - { - return x ^ y ^ z ^ cameraAxis ^ xyz; - } - - public override bool Equals(object obj) - { - if (!(obj is RotationHandleIds)) - return false; - - var o = (RotationHandleIds)obj; - return o.x == x && o.y == y && o.z == z - && o.cameraAxis == cameraAxis && o.xyz == xyz; - } - } - - internal struct RotationHandleParam - { - [Flags] - public enum Handle - { - X = 1 << 0, - Y = 1 << 1, - Z = 1 << 2, - CameraAxis = 1 << 3, - XYZ = 1 << 4 - } - - static RotationHandleParam s_Default = new RotationHandleParam((Handle)(-1), Vector3.one, 1f, 1.1f, true, false); - public static RotationHandleParam Default { get { return s_Default; } set { s_Default = value; } } - - public readonly Vector3 axisSize; - public readonly float cameraAxisSize; - public readonly float xyzSize; - public readonly Handle handles; - public readonly bool enableRayDrag; - public readonly bool displayXYZCircle; - - public bool ShouldShow(int axis) - { - return (handles & (Handle)(1 << axis)) != 0; - } - - public bool ShouldShow(Handle handle) - { - return (handles & handle) != 0; - } - - public RotationHandleParam(Handle handles, Vector3 axisSize, float xyzSize, float cameraAxisSize, bool enableRayDrag, bool displayXYZCircle) - { - this.axisSize = axisSize; - this.xyzSize = xyzSize; - this.handles = handles; - this.cameraAxisSize = cameraAxisSize; - this.enableRayDrag = enableRayDrag; - this.displayXYZCircle = displayXYZCircle; - } - } - - static readonly Color k_RotationPieColor = new Color(246f / 255, 242f / 255, 50f / 255, .89f); - - public static Quaternion DoRotationHandle(Quaternion rotation, Vector3 position) - { - return DoRotationHandle(RotationHandleIds.@default, rotation, position, RotationHandleParam.Default); - } - - internal static Quaternion DoRotationHandle(RotationHandleIds ids, Quaternion rotation, Vector3 position, RotationHandleParam param) - { - var evt = Event.current; - var camTr = Camera.current.transform; - - var size = HandleUtility.GetHandleSize(position); - var temp = color; - var isStatic = (!Tools.s_Hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); - - var isHot = ids.Has(GUIUtility.hotControl); - - // Draw freerotation first to give it the lowest priority - if (!isStatic - && param.ShouldShow(RotationHandleParam.Handle.XYZ) - && (isHot && ids.xyz == GUIUtility.hotControl || !isHot)) - { - color = centerColor; - rotation = UnityEditorInternal.FreeRotate.Do(ids.xyz, rotation, position, size * param.xyzSize, param.displayXYZCircle); - } - - var radiusOfAxesHandles = -1f; - for (var i = 0; i < 3; ++i) - { - if (!param.ShouldShow(i)) - continue; - - var axisColor = GetColorByAxis(i); - color = isStatic ? Color.Lerp(axisColor, staticColor, staticBlend) : axisColor; - color = ToActiveColorSpace(color); - var axisDir = GetAxisVector(i); - - var radius = size * param.axisSize[i]; - radiusOfAxesHandles = Mathf.Max(radius, radiusOfAxesHandles); - - rotation = UnityEditorInternal.Disc.Do(ids[i], rotation, position, rotation * axisDir, radius, true, SnapSettings.rotation, param.enableRayDrag, true, k_RotationPieColor); - } - - if (radiusOfAxesHandles > 0 && evt.type == EventType.Repaint) - { - Handles.color = new Color(0, 0, 0, 0.2f); - Handles.DrawWireDisc(position, camTr.forward, radiusOfAxesHandles); - } - - if (isHot && evt.type == EventType.Repaint) - { - color = ToActiveColorSpace(s_DisabledHandleColor); - Handles.DrawWireDisc(position, camTr.forward, size * param.axisSize[0]); - } - - if (!isStatic - && param.ShouldShow(RotationHandleParam.Handle.CameraAxis) - && (isHot && ids.cameraAxis == GUIUtility.hotControl || !isHot)) - { - color = ToActiveColorSpace(centerColor); - rotation = UnityEditorInternal.Disc.Do(ids.cameraAxis, rotation, position, Camera.current.transform.forward, size * param.cameraAxisSize, false, 0, param.enableRayDrag, true, k_RotationPieColor); - } - - color = temp; - return rotation; - } - } -} diff --git a/Editor/Mono/EditorHandles/ScaleHandle.cs b/Editor/Mono/EditorHandles/ScaleHandle.cs deleted file mode 100644 index 06748bbe14..0000000000 --- a/Editor/Mono/EditorHandles/ScaleHandle.cs +++ /dev/null @@ -1,229 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class Handles - { - internal struct ScaleHandleIds - { - public static ScaleHandleIds @default - { - get - { - return new ScaleHandleIds( - GUIUtility.GetControlID(s_xScaleHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_yScaleHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_zScaleHandleHash, FocusType.Passive), - GUIUtility.GetControlID(s_xyzScaleHandleHash, FocusType.Passive) - ); - } - } - - public readonly int x, y, z, xyz; - - public int this[int index] - { - get - { - switch (index) - { - case 0: return x; - case 1: return y; - case 2: return z; - case 3: return xyz; - } - return -1; - } - } - - public bool Has(int id) - { - return x == id - || y == id - || z == id - || xyz == id; - } - - public ScaleHandleIds(int x, int y, int z, int xyz) - { - this.x = x; - this.y = y; - this.z = z; - this.xyz = xyz; - } - - public override int GetHashCode() - { - return x ^ y ^ z ^ xyz; - } - - public override bool Equals(object obj) - { - if (!(obj is ScaleHandleIds)) - return false; - - var o = (ScaleHandleIds)obj; - return o.x == x && o.y == y && o.z == z - && o.xyz == xyz; - } - } - - internal struct ScaleHandleParam - { - [Flags] - public enum Handle - { - X = 1 << 0, - Y = 1 << 1, - Z = 1 << 2, - XYZ = 1 << 3 - } - - public enum Orientation - { - Signed, - Camera - } - - static ScaleHandleParam s_Default = new ScaleHandleParam((Handle)(-1), Vector3.zero, Vector3.one, Vector3.one, 1, Orientation.Signed); - public static ScaleHandleParam Default { get { return s_Default; } set { s_Default = value; } } - - public readonly Vector3 axisOffset; - public readonly Vector3 axisSize; - public readonly Vector3 axisLineScale; - public readonly float xyzSize; - public readonly Handle handles; - public readonly Orientation orientation; - - public bool ShouldShow(int axis) - { - return (handles & (Handle)(1 << axis)) != 0; - } - - public bool ShouldShow(Handle handle) - { - return (handles & handle) != 0; - } - - public ScaleHandleParam(Handle handles, Vector3 axisOffset, Vector3 axisSize, Vector3 axisLineScale, float xyzSize, Orientation orientation) - { - this.axisOffset = axisOffset; - this.axisSize = axisSize; - this.axisLineScale = axisLineScale; - this.xyzSize = xyzSize; - this.handles = handles; - this.orientation = orientation; - } - } - - static Vector3 s_DoScaleHandle_AxisHandlesOctant = Vector3.one; - - public static Vector3 DoScaleHandle(Vector3 scale, Vector3 position, Quaternion rotation, float size) - { - return DoScaleHandle(ScaleHandleIds.@default, scale, position, rotation, size, ScaleHandleParam.Default); - } - - internal static Vector3 DoScaleHandle(ScaleHandleIds ids, Vector3 scale, Vector3 position, Quaternion rotation, float handleSize, ScaleHandleParam param) - { - // Calculate the camera view vector in Handle draw space - // this handle the case where the matrix is skewed - var handlePosition = matrix.MultiplyPoint3x4(position); - var drawToWorldMatrix = matrix * Matrix4x4.TRS(position, rotation, Vector3.one); - var invDrawToWorldMatrix = drawToWorldMatrix.inverse; - var viewVectorDrawSpace = GetCameraViewFrom(handlePosition, invDrawToWorldMatrix); - - var isStatic = (!Tools.s_Hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); - - var isHot = ids.Has(GUIUtility.hotControl); - - var axisOffset = param.axisOffset; - var axisLineScale = param.axisLineScale; - // When an axis is hot, draw the line from the center to the handle - // So ignore the offset - if (isHot) - { - axisLineScale += axisOffset; - axisOffset = Vector3.zero; - } - - var isCenterIsHot = ids.xyz == GUIUtility.hotControl; - - for (var i = 0; i < 3; ++i) - { - if (!param.ShouldShow(i)) - continue; - - if (!currentlyDragging) - { - switch (param.orientation) - { - case ScaleHandleParam.Orientation.Signed: - s_DoScaleHandle_AxisHandlesOctant[i] = 1; - break; - case ScaleHandleParam.Orientation.Camera: - s_DoScaleHandle_AxisHandlesOctant[i] = viewVectorDrawSpace[i] > 0.01f ? -1 : 1; - break; - } - } - - - var id = ids[i]; - var isThisAxisHot = isHot && id == GUIUtility.hotControl; - - var axisDir = GetAxisVector(i); - var axisColor = GetColorByAxis(i); - var offset = axisOffset[i]; - var cameraLerp = id == GUIUtility.hotControl ? 0 : GetCameraViewLerpForWorldAxis(viewVectorDrawSpace, axisDir); - // If we are here and is hot, then this axis is hot and must be opaque - cameraLerp = isHot ? 0 : cameraLerp; - color = isStatic ? Color.Lerp(axisColor, staticColor, staticBlend) : axisColor; - - axisDir *= s_DoScaleHandle_AxisHandlesOctant[i]; - - if (cameraLerp <= kCameraViewThreshold) - { - color = Color.Lerp(color, Color.clear, cameraLerp); - - if (isHot && !isThisAxisHot) - color = s_DisabledHandleColor; - if (isCenterIsHot) - color = selectedColor; - - color = ToActiveColorSpace(color); - - scale[i] = UnityEditorInternal.SliderScale.DoAxis( - id, - scale[i], - position, - rotation * axisDir, - rotation, - handleSize * param.axisSize[i], - SnapSettings.scale, - offset, - axisLineScale[i]); - } - } - - if (param.ShouldShow(ScaleHandleParam.Handle.XYZ) && (isHot && ids.xyz == GUIUtility.hotControl || !isHot)) - { - color = ToActiveColorSpace(centerColor); - EditorGUI.BeginChangeCheck(); - var s = ScaleValueHandle(ids.xyz, scale.x, position, rotation, handleSize * param.xyzSize, CubeHandleCap, SnapSettings.scale); - if (EditorGUI.EndChangeCheck() && !Mathf.Approximately(scale.x, 0)) - { - var dif = s / scale.x; - scale.x = s; - scale.y *= dif; - scale.z *= dif; - } - } - - return scale; - } - } -} diff --git a/Editor/Mono/EditorHandles/SimpleRadiusHandle.cs b/Editor/Mono/EditorHandles/SimpleRadiusHandle.cs deleted file mode 100644 index 33673b3df2..0000000000 --- a/Editor/Mono/EditorHandles/SimpleRadiusHandle.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class Handles - { - internal static float DoSimpleEdgeHandle(Quaternion rotation, Vector3 position, float radius) - { - Vector3 right = rotation * Vector3.right; - - // Radius handles at ends - EditorGUI.BeginChangeCheck(); - radius = SizeSlider(position, right, radius); - radius = SizeSlider(position, -right, radius); - if (EditorGUI.EndChangeCheck()) - radius = Mathf.Max(0.0f, radius); - - // Draw gizmo - if (radius > 0) - DrawLine(position - right * radius, position + right * radius); - - return radius; - } - - internal static float DoSimpleRadiusHandle(Quaternion rotation, Vector3 position, float radius, bool hemisphere) - { - Vector3 forward = rotation * Vector3.forward; - Vector3 up = rotation * Vector3.up; - Vector3 right = rotation * Vector3.right; - - // Radius handle in zenith - bool temp = GUI.changed; - GUI.changed = false; - radius = SizeSlider(position, forward, radius); - if (!hemisphere) - radius = SizeSlider(position, -forward, radius); - if (GUI.changed) - radius = Mathf.Max(0.0f, radius); - GUI.changed |= temp; - - // Radius handles at disc - temp = GUI.changed; - GUI.changed = false; - radius = SizeSlider(position, up, radius); - radius = SizeSlider(position, -up, radius); - radius = SizeSlider(position, right, radius); - radius = SizeSlider(position, -right, radius); - if (GUI.changed) - radius = Mathf.Max(0.0f, radius); - GUI.changed |= temp; - - // Draw gizmo - if (radius > 0) - { - DrawWireDisc(position, forward, radius); - DrawWireArc(position, up, -right, hemisphere ? 180 : 360, radius); - DrawWireArc(position, right, up, hemisphere ? 180 : 360, radius); - //DrawPeriphery (position, radius); - } - return radius; - } - - // static void DrawHemispherePeriphery (Vector3 position, float radius) - // { - // Vector3 planeNormal = position - Camera.current.transform.position; // vector from camera to center - // float sqrDist = planeNormal.sqrMagnitude; // squared distance from camera to center - // float sqrRadius = radius * radius; // squared radius - // float sqrOffset = sqrRadius * sqrRadius / sqrDist; // squared distance from actual center to drawn disc center - // float insideAmount = sqrOffset / sqrRadius; - // - // // If we are not inside the sphere, calculate where to draw the periphery - // if (insideAmount < 1) - // { - // float drawnRadius = Mathf.Sqrt(sqrRadius - sqrOffset); // the radius of the drawn disc - // - // // Draw periphery circle - // Vector3 tangent = Vector3.Cross(planeNormal, Vector3.up); - // if (tangent.sqrMagnitude < .001f) - // tangent = Vector3.Cross(planeNormal, Vector3.right); - // DrawWireArc(position - sqrRadius * planeNormal / sqrDist, planeNormal, tangent, -180, drawnRadius); - // } - // } - } -} diff --git a/Editor/Mono/EditorHandles/Slider1D.cs b/Editor/Mono/EditorHandles/Slider1D.cs deleted file mode 100644 index 2876e8ca10..0000000000 --- a/Editor/Mono/EditorHandles/Slider1D.cs +++ /dev/null @@ -1,185 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - internal class Slider1D - { - private static Vector2 s_StartMousePosition, s_CurrentMousePosition; - private static Vector3 s_StartPosition; - - // DrawCapFunction was marked plannned obsolete by @juha on 2016-03-16, marked obsolete warning by @adamm on 2016-12-21 - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - #pragma warning disable 618 - internal static Vector3 Do(int id, Vector3 position, Vector3 direction, float size, Handles.DrawCapFunction drawFunc, float snap) - #pragma warning restore 618 - { - return Do(id, position, direction, direction, size, drawFunc, snap); - } - - internal static Vector3 Do(int id, Vector3 position, Vector3 direction, float size, Handles.CapFunction capFunction, float snap) - { - return Do(id, position, Vector3.zero, direction, direction, size, capFunction, snap); - } - - // DrawCapFunction was marked plannned obsolete by @juha on 2016-03-16, marked obsolete warning by @adamm on 2016-12-21 - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - #pragma warning disable 618 - internal static Vector3 Do(int id, Vector3 position, Vector3 handleDirection, Vector3 slideDirection, float size, Handles.DrawCapFunction drawFunc, float snap) - #pragma warning disable 618 - { - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - // This is an ugly hack. It would be better if the drawFunc can handle it's own layout. - if (drawFunc == Handles.ArrowCap) - { - HandleUtility.AddControl(id, HandleUtility.DistanceToLine(position, position + slideDirection * size)); - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(position + slideDirection * size, size * .2f)); - } - else - { - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(position, size * .2f)); - } - break; - case EventType.MouseDown: - // am I closest to the thingy? - if ((HandleUtility.nearestControl == id && evt.button == 0) && GUIUtility.hotControl == 0) - { - GUIUtility.hotControl = id; // Grab mouse focus - s_CurrentMousePosition = s_StartMousePosition = evt.mousePosition; - s_StartPosition = position; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_CurrentMousePosition += evt.delta; - float dist = HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, s_StartPosition, slideDirection); - - dist = Handles.SnapValue(dist, snap); - - Vector3 worldDirection = Handles.matrix.MultiplyVector(slideDirection); - Vector3 worldPosition = Handles.matrix.MultiplyPoint(s_StartPosition) + worldDirection * dist; - position = Handles.inverseMatrix.MultiplyPoint(worldPosition); - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.Repaint: - Color temp = Color.white; - - if (id == GUIUtility.hotControl) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - drawFunc(id, position, Quaternion.LookRotation(handleDirection), size); - - if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - Handles.color = temp; - break; - } - return position; - } - - internal static Vector3 Do(int id, Vector3 position, Vector3 offset, Vector3 handleDirection, Vector3 slideDirection, float size, Handles.CapFunction capFunction, float snap) - { - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - if (capFunction != null) - capFunction(id, position + offset, Quaternion.LookRotation(handleDirection), size, EventType.Layout); - else - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(position + offset, size * .2f)); - break; - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && evt.button == 0 && GUIUtility.hotControl == 0) - { - GUIUtility.hotControl = id; // Grab mouse focus - s_CurrentMousePosition = s_StartMousePosition = evt.mousePosition; - s_StartPosition = position; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_CurrentMousePosition += evt.delta; - float dist = HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, s_StartPosition, slideDirection); - - dist = Handles.SnapValue(dist, snap); - - Vector3 worldDirection = Handles.matrix.MultiplyVector(slideDirection); - Vector3 worldPosition = Handles.matrix.MultiplyPoint(s_StartPosition) + worldDirection * dist; - position = Handles.inverseMatrix.MultiplyPoint(worldPosition); - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.Repaint: - Color temp = Color.white; - - if (id == GUIUtility.hotControl) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - - capFunction(id, position + offset, Quaternion.LookRotation(handleDirection), size, EventType.Repaint); - - if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - Handles.color = temp; - break; - } - return position; - } - } -} diff --git a/Editor/Mono/EditorHandles/Slider2D.cs b/Editor/Mono/EditorHandles/Slider2D.cs deleted file mode 100644 index d3f5f0adb0..0000000000 --- a/Editor/Mono/EditorHandles/Slider2D.cs +++ /dev/null @@ -1,433 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - internal class Slider2D - { - private static Vector2 s_CurrentMousePosition; - private static Vector3 s_StartPosition; - private static Vector2 s_StartPlaneOffset; - - // DrawCapFunction was marked plannned obsolete by @juha on 2016-03-16, marked obsolete warning by @adamm on 2016-12-21 - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - #pragma warning disable 618 - public static Vector3 Do( - int id, - Vector3 handlePos, - Vector3 handleDir, - Vector3 slideDir1, - Vector3 slideDir2, - float handleSize, - Handles.DrawCapFunction drawFunc, - float snap, - bool drawHelper) - #pragma warning restore 618 - { - return Do(id, handlePos, new Vector3(0, 0, 0), handleDir, slideDir1, slideDir2, handleSize, drawFunc, new Vector2(snap, snap), drawHelper); - } - - // DrawCapFunction was marked plannned obsolete by @juha on 2016-03-16, marked obsolete warning by @adamm on 2016-12-21 - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - #pragma warning disable 618 - public static Vector3 Do( - int id, - Vector3 handlePos, - Vector3 offset, - Vector3 handleDir, - Vector3 slideDir1, - Vector3 slideDir2, - float handleSize, - Handles.DrawCapFunction drawFunc, - float snap, - bool drawHelper) - #pragma warning restore 618 - { - return Do(id, handlePos, offset, handleDir, slideDir1, slideDir2, handleSize, drawFunc, new Vector2(snap, snap), drawHelper); - } - - // DrawCapFunction was marked plannned obsolete by @juha on 2016-03-16, marked obsolete warning by @adamm on 2016-12-21 - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - #pragma warning disable 618 - public static Vector3 Do( - int id, - Vector3 handlePos, - Vector3 offset, - Vector3 handleDir, - Vector3 slideDir1, - Vector3 slideDir2, - float handleSize, - Handles.DrawCapFunction drawFunc, - Vector2 snap, - bool drawHelper) - #pragma warning restore 618 - { - bool orgGuiChanged = GUI.changed; - GUI.changed = false; - - Vector2 delta = CalcDeltaAlongDirections(id, handlePos, offset, handleDir, slideDir1, slideDir2, handleSize, drawFunc, snap, drawHelper); - if (GUI.changed) - handlePos = s_StartPosition + slideDir1 * delta.x + slideDir2 * delta.y; - - GUI.changed |= orgGuiChanged; - return handlePos; - } - - // Returns the new handlePos - public static Vector3 Do( - int id, - Vector3 handlePos, - Vector3 handleDir, - Vector3 slideDir1, - Vector3 slideDir2, - float handleSize, - Handles.CapFunction capFunction, - float snap, - bool drawHelper) - { - return Do(id, handlePos, new Vector3(0, 0, 0), handleDir, slideDir1, slideDir2, handleSize, capFunction, new Vector2(snap, snap), drawHelper); - } - - // Returns the new handlePos - public static Vector3 Do( - int id, - Vector3 handlePos, - Vector3 offset, - Vector3 handleDir, - Vector3 slideDir1, - Vector3 slideDir2, - float handleSize, - Handles.CapFunction capFunction, - float snap, - bool drawHelper) - { - return Do(id, handlePos, offset, handleDir, slideDir1, slideDir2, handleSize, capFunction, new Vector2(snap, snap), drawHelper); - } - - // Returns the new handlePos - public static Vector3 Do( - int id, - Vector3 handlePos, - Vector3 offset, - Vector3 handleDir, - Vector3 slideDir1, - Vector3 slideDir2, - float handleSize, - Handles.CapFunction capFunction, - Vector2 snap, - bool drawHelper) - { - bool orgGuiChanged = GUI.changed; - GUI.changed = false; - - Vector2 delta = CalcDeltaAlongDirections(id, handlePos, offset, handleDir, slideDir1, slideDir2, handleSize, capFunction, snap, drawHelper); - if (GUI.changed) - handlePos = s_StartPosition + slideDir1 * delta.x + slideDir2 * delta.y; - - GUI.changed |= orgGuiChanged; - return handlePos; - } - - // DrawCapFunction was marked plannned obsolete by @juha on 2016-03-16, marked obsolete warning by @adamm on 2016-12-21 - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - #pragma warning disable 618 - private static Vector2 CalcDeltaAlongDirections( - int id, - Vector3 handlePos, - Vector3 offset, - Vector3 handleDir, - Vector3 slideDir1, - Vector3 slideDir2, - float handleSize, - Handles.DrawCapFunction drawFunc, - Vector2 snap, - bool drawHelper) - #pragma warning restore 618 - { - Vector2 deltaDistanceAlongDirections = new Vector2(0, 0); - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - // This is an ugly hack. It would be better if the drawFunc can handle it's own layout. - if (drawFunc == Handles.ArrowCap) - { - HandleUtility.AddControl(id, HandleUtility.DistanceToLine(handlePos + offset, handlePos + handleDir * handleSize)); - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle((handlePos + offset) + handleDir * handleSize, handleSize * .2f)); - } - else if (drawFunc == Handles.RectangleCap) - { - HandleUtility.AddControl(id, HandleUtility.DistanceToRectangle(handlePos + offset, Quaternion.LookRotation(handleDir, slideDir1), handleSize)); - } - else - { - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(handlePos + offset, handleSize * .5f)); - } - break; - - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && evt.button == 0 && GUIUtility.hotControl == 0) - { - Plane plane = new Plane(Handles.matrix.MultiplyVector(handleDir), Handles.matrix.MultiplyPoint(handlePos)); - Ray mouseRay = HandleUtility.GUIPointToWorldRay(evt.mousePosition); - float dist = 0.0f; - plane.Raycast(mouseRay, out dist); - - GUIUtility.hotControl = id; // Grab mouse focus - s_CurrentMousePosition = evt.mousePosition; - s_StartPosition = handlePos; - - Vector3 localMousePoint = Handles.inverseMatrix.MultiplyPoint(mouseRay.GetPoint(dist)); - Vector3 clickOffset = localMousePoint - handlePos; - s_StartPlaneOffset.x = Vector3.Dot(clickOffset, slideDir1); - s_StartPlaneOffset.y = Vector3.Dot(clickOffset, slideDir2); - - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_CurrentMousePosition += evt.delta; - Vector3 worldPosition = Handles.matrix.MultiplyPoint(handlePos); - Vector3 worldSlideDir1 = Handles.matrix.MultiplyVector(slideDir1).normalized; - Vector3 worldSlideDir2 = Handles.matrix.MultiplyVector(slideDir2).normalized; - - // Detect hit with plane (ray from campos to cursor) - Ray mouseRay = HandleUtility.GUIPointToWorldRay(s_CurrentMousePosition); - Plane plane = new Plane(worldPosition, worldPosition + worldSlideDir1, worldPosition + worldSlideDir2); - float dist = 0.0f; - if (plane.Raycast(mouseRay, out dist)) - { - Vector3 hitpos = Handles.inverseMatrix.MultiplyPoint(mouseRay.GetPoint(dist)); - - // Determine hitpos projection onto slideDirs - deltaDistanceAlongDirections.x = HandleUtility.PointOnLineParameter(hitpos, s_StartPosition, slideDir1); - deltaDistanceAlongDirections.y = HandleUtility.PointOnLineParameter(hitpos, s_StartPosition, slideDir2); - deltaDistanceAlongDirections -= s_StartPlaneOffset; - if (snap.x > 0 || snap.y > 0) - { - deltaDistanceAlongDirections.x = Handles.SnapValue(deltaDistanceAlongDirections.x, snap.x); - deltaDistanceAlongDirections.y = Handles.SnapValue(deltaDistanceAlongDirections.y, snap.y); - } - - GUI.changed = true; - } - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.Repaint: - { - if (drawFunc == null) - break; - - Vector3 position = handlePos + offset; - Quaternion rotation = Quaternion.LookRotation(handleDir, slideDir1); - - Color temp = Color.white; - - if (id == GUIUtility.hotControl) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - - drawFunc(id, position, rotation, handleSize); - - if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - Handles.color = temp; - - // Draw a helper rectangle to show what plane we are dragging in - if (drawHelper && GUIUtility.hotControl == id) - { - Vector3[] verts = new Vector3[4]; - float helperSize = handleSize * 10.0f; - verts[0] = position + (slideDir1 * helperSize + slideDir2 * helperSize); - verts[1] = verts[0] - slideDir1 * helperSize * 2.0f; - verts[2] = verts[1] - slideDir2 * helperSize * 2.0f; - verts[3] = verts[2] + slideDir1 * helperSize * 2.0f; - Color prevColor = Handles.color; - Handles.color = Color.white; - float outline = 0.6f; - Handles.DrawSolidRectangleWithOutline(verts, new Color(1, 1, 1, 0.05f), new Color(outline, outline, outline, 0.4f)); - Handles.color = prevColor; - } - } - - break; - } - - return deltaDistanceAlongDirections; - } - - // Returns the distance the new position has moved along slideDir1 and slideDir2 - private static Vector2 CalcDeltaAlongDirections( - int id, - Vector3 handlePos, - Vector3 offset, - Vector3 handleDir, - Vector3 slideDir1, - Vector3 slideDir2, - float handleSize, - Handles.CapFunction capFunction, - Vector2 snap, - bool drawHelper) - { - Vector3 position = handlePos + offset; - Quaternion rotation = Quaternion.LookRotation(handleDir, slideDir1); - Vector2 deltaDistanceAlongDirections = new Vector2(0, 0); - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - if (capFunction != null) - capFunction(id, position, rotation, handleSize, EventType.Layout); - else - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(handlePos + offset, handleSize * .5f)); - break; - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && evt.button == 0 && GUIUtility.hotControl == 0) - { - s_CurrentMousePosition = evt.mousePosition; - bool success = true; - Vector3 localMousePoint = Handles.inverseMatrix.MultiplyPoint(GetMousePosition(handleDir, handlePos, ref success)); - if (success) - { - GUIUtility.hotControl = id; // Grab mouse focus - s_StartPosition = handlePos; - - Vector3 clickOffset = localMousePoint - handlePos; - s_StartPlaneOffset.x = Vector3.Dot(clickOffset, slideDir1); - s_StartPlaneOffset.y = Vector3.Dot(clickOffset, slideDir2); - - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_CurrentMousePosition += evt.delta; - bool success = true; - Vector3 localMousePoint = Handles.inverseMatrix.MultiplyPoint(GetMousePosition(handleDir, handlePos, ref success)); - if (success) - { - // Determine hitpos projection onto slideDirs - deltaDistanceAlongDirections.x = HandleUtility.PointOnLineParameter(localMousePoint, s_StartPosition, slideDir1); - deltaDistanceAlongDirections.y = HandleUtility.PointOnLineParameter(localMousePoint, s_StartPosition, slideDir2); - deltaDistanceAlongDirections -= s_StartPlaneOffset; - if (snap.x > 0 || snap.y > 0) - { - deltaDistanceAlongDirections.x = Handles.SnapValue(deltaDistanceAlongDirections.x, snap.x); - deltaDistanceAlongDirections.y = Handles.SnapValue(deltaDistanceAlongDirections.y, snap.y); - } - - GUI.changed = true; - } - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.Repaint: - { - if (capFunction == null) - break; - - Color temp = Color.white; - if (id == GUIUtility.hotControl) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - - capFunction(id, position, rotation, handleSize, EventType.Repaint); - - if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - Handles.color = temp; - - // Draw a helper rectangle to show what plane we are dragging in - if (drawHelper && GUIUtility.hotControl == id) - { - Vector3[] verts = new Vector3[4]; - float helperSize = handleSize * 10.0f; - verts[0] = position + (slideDir1 * helperSize + slideDir2 * helperSize); - verts[1] = verts[0] - slideDir1 * helperSize * 2.0f; - verts[2] = verts[1] - slideDir2 * helperSize * 2.0f; - verts[3] = verts[2] + slideDir1 * helperSize * 2.0f; - Color prevColor = Handles.color; - Handles.color = Color.white; - float outline = 0.6f; - Handles.DrawSolidRectangleWithOutline(verts, new Color(1, 1, 1, 0.05f), new Color(outline, outline, outline, 0.4f)); - Handles.color = prevColor; - } - } - - break; - } - - return deltaDistanceAlongDirections; - } - - private static Vector3 GetMousePosition(Vector3 handleDirection, Vector3 handlePosition, ref bool success) - { - if (Camera.current != null) - { - Plane plane = new Plane(Handles.matrix.MultiplyVector(handleDirection), Handles.matrix.MultiplyPoint(handlePosition)); - Ray mouseRay = HandleUtility.GUIPointToWorldRay(s_CurrentMousePosition); - float dist = 0.0f; - success = plane.Raycast(mouseRay, out dist); - return mouseRay.GetPoint(dist); - } - else - { - success = true; - return s_CurrentMousePosition; - } - } - } -} diff --git a/Editor/Mono/EditorHandles/SliderScale.cs b/Editor/Mono/EditorHandles/SliderScale.cs deleted file mode 100644 index 4c314f7fb0..0000000000 --- a/Editor/Mono/EditorHandles/SliderScale.cs +++ /dev/null @@ -1,256 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - internal class SliderScale - { - private static float s_StartScale, s_ScaleDrawLength = 1.0f; - private static float s_ValueDrag; - private static Vector2 s_StartMousePosition, s_CurrentMousePosition; - - public static float DoAxis(int id, float scale, Vector3 position, Vector3 direction, Quaternion rotation, float size, float snap) - { - return DoAxis(id, scale, position, direction, rotation, size, snap, 0, 1); - } - - internal static float DoAxis(int id, float scale, Vector3 position, Vector3 direction, Quaternion rotation, float size, float snap, float handleOffset, float lineScale) - { - var positionOffset = direction * size * handleOffset; - var s = GUIUtility.hotControl == id - ? size * scale / s_StartScale - : size; - var startPosition = position + positionOffset; - var cubePosition = position + direction * (s * s_ScaleDrawLength * lineScale) + positionOffset; - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - HandleUtility.AddControl(id, HandleUtility.DistanceToLine(startPosition, cubePosition)); - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(cubePosition, size * .3f)); - break; - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && evt.button == 0) - { - GUIUtility.hotControl = id; // Grab mouse focus - s_CurrentMousePosition = s_StartMousePosition = evt.mousePosition; - s_StartScale = scale; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_CurrentMousePosition += evt.delta; - var dist = 1 + HandleUtility.CalcLineTranslation(s_StartMousePosition, s_CurrentMousePosition, position, direction) / size; - dist = Handles.SnapValue(dist, snap); - scale = s_StartScale * dist; - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.Repaint: - Color temp = Color.white; - if (id == GUIUtility.hotControl) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - - Handles.DrawLine(startPosition, cubePosition); - Handles.CubeHandleCap(id, cubePosition, rotation, size * .1f, EventType.Repaint); - - if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - Handles.color = temp; - break; - } - - return scale; - } - - // DrawCapFunction was marked plannned obsolete by @juha on 2016-03-16, marked obsolete warning by @adamm on 2016-12-21 - [Obsolete("DrawCapFunction is obsolete. Use the version with CapFunction instead. Example: Change SphereCap to SphereHandleCap.")] - #pragma warning disable 618 - public static float DoCenter(int id, float value, Vector3 position, Quaternion rotation, float size, Handles.DrawCapFunction capFunc, float snap) - #pragma warning restore 618 - { - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - HandleUtility.AddControl(id, HandleUtility.DistanceToCircle(position, size * .15f)); - break; - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && evt.button == 0) - { - GUIUtility.hotControl = id; // Grab mouse focus - s_StartScale = value; - s_ValueDrag = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_ValueDrag += HandleUtility.niceMouseDelta * .01f; - value = (Handles.SnapValue(s_ValueDrag, snap) + 1.0f) * s_StartScale; - s_ScaleDrawLength = value / s_StartScale; - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.KeyDown: - if (GUIUtility.hotControl == id) - { - // Cancel dragging on ESC - if (evt.keyCode == KeyCode.Escape) - { - value = s_StartScale; - s_ScaleDrawLength = 1.0f; - GUIUtility.hotControl = 0; - GUI.changed = true; - evt.Use(); - } - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - s_ScaleDrawLength = 1.0f; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.Repaint: - Color temp = Color.white; - if (id == GUIUtility.hotControl) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - capFunc(id, position, rotation, size * .15f); - - if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - Handles.color = temp; - break; - } - - return value; - } - - public static float DoCenter(int id, float value, Vector3 position, Quaternion rotation, float size, Handles.CapFunction capFunction, float snap) - { - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - capFunction(id, position, rotation, size * .15f, EventType.Layout); - break; - case EventType.MouseDown: - // am I closest to the thingy? - if (HandleUtility.nearestControl == id && evt.button == 0) - { - GUIUtility.hotControl = id; // Grab mouse focus - s_StartScale = value; - s_ValueDrag = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_ValueDrag += HandleUtility.niceMouseDelta * .01f; - value = (Handles.SnapValue(s_ValueDrag, snap) + 1.0f) * s_StartScale; - s_ScaleDrawLength = value / s_StartScale; - GUI.changed = true; - evt.Use(); - } - break; - case EventType.KeyDown: - if (GUIUtility.hotControl == id) - { - // Cancel dragging on ESC - if (evt.keyCode == KeyCode.Escape) - { - value = s_StartScale; - s_ScaleDrawLength = 1.0f; - GUIUtility.hotControl = 0; - GUI.changed = true; - evt.Use(); - } - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - s_ScaleDrawLength = 1.0f; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.MouseMove: - if (id == HandleUtility.nearestControl) - HandleUtility.Repaint(); - break; - case EventType.Repaint: - Color temp = Color.white; - if (id == GUIUtility.hotControl) - { - temp = Handles.color; - Handles.color = Handles.selectedColor; - } - else if (id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - { - temp = Handles.color; - Handles.color = Handles.preselectionColor; - } - capFunction(id, position, rotation, size * .15f, EventType.Repaint); - - if (id == GUIUtility.hotControl || id == HandleUtility.nearestControl && GUIUtility.hotControl == 0) - Handles.color = temp; - break; - } - - return value; - } - } -} diff --git a/Editor/Mono/EditorHandles/TransformHandle.cs b/Editor/Mono/EditorHandles/TransformHandle.cs deleted file mode 100644 index 54a8a83207..0000000000 --- a/Editor/Mono/EditorHandles/TransformHandle.cs +++ /dev/null @@ -1,342 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Runtime.InteropServices; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class Handles - { - internal struct TransformHandleIds - { - static readonly int s_TransformTranslationXHash = "TransformTranslationXHash".GetHashCode(); - static readonly int s_TransformTranslationYHash = "TransformTranslationYHash".GetHashCode(); - static readonly int s_TransformTranslationZHash = "TransformTranslationZHash".GetHashCode(); - static readonly int s_TransformTranslationXYHash = "TransformTranslationXYHash".GetHashCode(); - static readonly int s_TransformTranslationXZHash = "TransformTranslationXZHash".GetHashCode(); - static readonly int s_TransformTranslationYZHash = "TransformTranslationYZHash".GetHashCode(); - static readonly int s_TransformTranslationXYZHash = "TransformTranslationXYZHash".GetHashCode(); - static readonly int s_TransformRotationXHash = "TransformRotationXHash".GetHashCode(); - static readonly int s_TransformRotationYHash = "TransformRotationYHash".GetHashCode(); - static readonly int s_TransformRotationZHash = "TransformRotationZHash".GetHashCode(); - static readonly int s_TransformRotationCameraAxisHash = "TransformRotationCameraAxisHash".GetHashCode(); - static readonly int s_TransformRotationXYZHash = "TransformRotationXYZHash".GetHashCode(); - static readonly int s_TransformScaleXHash = "TransformScaleXHash".GetHashCode(); - static readonly int s_TransformScaleYHash = "TransformScaleYHash".GetHashCode(); - static readonly int s_TransformScaleZHash = "TransformScaleZHash".GetHashCode(); - static readonly int s_TransformScaleXYZHash = "TransformScaleXYZHash".GetHashCode(); - - public static TransformHandleIds Default - { - get - { - return new TransformHandleIds( - new PositionHandleIds( - GUIUtility.GetControlID(s_TransformTranslationXHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformTranslationYHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformTranslationZHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformTranslationXYHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformTranslationXZHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformTranslationYZHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformTranslationXYZHash, FocusType.Passive) - ), - new RotationHandleIds( - GUIUtility.GetControlID(s_TransformRotationXHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformRotationYHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformRotationZHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformRotationCameraAxisHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformRotationXYZHash, FocusType.Passive) - ), - new ScaleHandleIds( - GUIUtility.GetControlID(s_TransformScaleXHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformScaleYHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformScaleZHash, FocusType.Passive), - GUIUtility.GetControlID(s_TransformScaleXYZHash, FocusType.Passive) - ) - ); - } - } - - public readonly PositionHandleIds position; - public readonly RotationHandleIds rotation; - public readonly ScaleHandleIds scale; - - public bool Has(int id) - { - return position.Has(id) - || rotation.Has(id) - || scale.Has(id); - } - - public TransformHandleIds(PositionHandleIds position, RotationHandleIds rotation, ScaleHandleIds scale) - { - this.position = position; - this.rotation = rotation; - this.scale = scale; - } - } - - internal struct TransformHandleParam - { - static TransformHandleParam s_Default = new TransformHandleParam( - // Global - new PositionHandleParam( - PositionHandleParam.Handle.X | PositionHandleParam.Handle.Y | PositionHandleParam.Handle.Z - | PositionHandleParam.Handle.XY | PositionHandleParam.Handle.XZ | PositionHandleParam.Handle.YZ, - Vector3.one * 0.15f, - Vector3.one, - Vector3.zero, - Vector3.one * 0.375f, - PositionHandleParam.Orientation.Signed, - PositionHandleParam.Orientation.Camera - ), - new RotationHandleParam( - RotationHandleParam.Handle.X | RotationHandleParam.Handle.Y | RotationHandleParam.Handle.Z - | RotationHandleParam.Handle.CameraAxis | RotationHandleParam.Handle.XYZ, - Vector3.one * 1.4f, - 1.4f, - 1.5f, - false, - false - ), - new ScaleHandleParam( - ScaleHandleParam.Handle.XYZ, - Vector3.zero, - Vector3.one, - Vector3.one, - 1, - ScaleHandleParam.Orientation.Signed - ), - - // Camera aligned - new PositionHandleParam( - PositionHandleParam.Handle.X | PositionHandleParam.Handle.Y | PositionHandleParam.Handle.XY, - Vector3.one * 0.15f, - Vector3.one, - Vector3.zero, - Vector3.one * 0.375f, - PositionHandleParam.Orientation.Signed, - PositionHandleParam.Orientation.Signed - ), - new RotationHandleParam( - RotationHandleParam.Handle.Z | RotationHandleParam.Handle.XYZ, - Vector3.one * 1.4f, - 1.4f, - 1.5f, - false, - false - ), - new ScaleHandleParam( - ScaleHandleParam.Handle.XYZ, - Vector3.zero, - Vector3.one, - Vector3.one, - 1, - ScaleHandleParam.Orientation.Signed - ), - - // Local - new PositionHandleParam( - PositionHandleParam.Handle.X | PositionHandleParam.Handle.Y | PositionHandleParam.Handle.Z - | PositionHandleParam.Handle.XY | PositionHandleParam.Handle.XZ | PositionHandleParam.Handle.YZ, - Vector3.one * 0.15f, - Vector3.one, - Vector3.zero, - Vector3.one * 0.375f, - PositionHandleParam.Orientation.Signed, - PositionHandleParam.Orientation.Camera - ), - new RotationHandleParam( - RotationHandleParam.Handle.X | RotationHandleParam.Handle.Y | RotationHandleParam.Handle.Z - | RotationHandleParam.Handle.CameraAxis | RotationHandleParam.Handle.XYZ, - Vector3.one * 1.4f, - 1.4f, - 1.5f, - false, - false - ), - new ScaleHandleParam( - ScaleHandleParam.Handle.XYZ | ScaleHandleParam.Handle.X | ScaleHandleParam.Handle.Y | ScaleHandleParam.Handle.Z, - Vector3.one * 1.5f, - Vector3.one, - Vector3.one * 0.25f, - 1, - ScaleHandleParam.Orientation.Signed - ) - , - - // Vertex Snapping - new PositionHandleParam( - PositionHandleParam.Handle.X | PositionHandleParam.Handle.Y | PositionHandleParam.Handle.Z - | PositionHandleParam.Handle.XYZ, - Vector3.one * 0.15f, - Vector3.one, - Vector3.zero, - Vector3.one * 0.375f, - PositionHandleParam.Orientation.Signed, - PositionHandleParam.Orientation.Signed - ), - new RotationHandleParam( - 0, - Vector3.one * 1.4f, - 1.4f, - 1.5f, - false, - false - ), - new ScaleHandleParam( - 0, - Vector3.one * 1.5f, - Vector3.one, - Vector3.one * 0.25f, - 1, - ScaleHandleParam.Orientation.Signed - ) - ); - public static TransformHandleParam Default { get { return s_Default; } set { s_Default = value; } } - - public readonly PositionHandleParam position; - public readonly RotationHandleParam rotation; - public readonly ScaleHandleParam scale; - public readonly PositionHandleParam cameraAlignedPosition; - public readonly RotationHandleParam cameraAlignedRotation; - public readonly ScaleHandleParam cameraAlignedScale; - public readonly PositionHandleParam localPosition; - public readonly RotationHandleParam localRotation; - public readonly ScaleHandleParam localScale; - public readonly PositionHandleParam vertexSnappingPosition; - public readonly RotationHandleParam vertexSnappingRotation; - public readonly ScaleHandleParam vertexSnappingScale; - - public TransformHandleParam( - PositionHandleParam position, - RotationHandleParam rotation, - ScaleHandleParam scale, - PositionHandleParam cameraAlignedPosition, - RotationHandleParam cameraAlignedRotation, - ScaleHandleParam cameraAlignedScale, - PositionHandleParam localPosition, - RotationHandleParam localRotation, - ScaleHandleParam localScale, - PositionHandleParam vertexSnappingPosition, - RotationHandleParam vertexSnappingRotation, - ScaleHandleParam vertexSnappingScale) - { - this.position = position; - this.rotation = rotation; - this.scale = scale; - this.cameraAlignedPosition = cameraAlignedPosition; - this.cameraAlignedRotation = cameraAlignedRotation; - this.cameraAlignedScale = cameraAlignedScale; - this.localPosition = localPosition; - this.localRotation = localRotation; - this.localScale = localScale; - this.vertexSnappingPosition = vertexSnappingPosition; - this.vertexSnappingRotation = vertexSnappingRotation; - this.vertexSnappingScale = vertexSnappingScale; - } - } - - struct RotationHandleData - { - public bool rotationStarted; - public Quaternion initialRotation; - } - - static bool s_IsHotInCameraAlignedMode = false; - static Dictionary s_TransformHandle_RotationData = new Dictionary(); - internal static void TransformHandle(TransformHandleIds ids, ref Vector3 position, ref Quaternion rotation, ref Vector3 scale, TransformHandleParam param) - { - var workingRotation = rotation; - var pParam = param.position; - var rParam = param.rotation; - var sParam = param.scale; - - var isHot = ids.Has(GUIUtility.hotControl); - var cameraAligned = (isHot && s_IsHotInCameraAlignedMode || !isHot && Event.current.shift); - if (Tools.vertexDragging) - { - pParam = param.vertexSnappingPosition; - rParam = param.vertexSnappingRotation; - sParam = param.vertexSnappingScale; - } - else if (cameraAligned) - { - workingRotation = Camera.current.transform.rotation; - - pParam = param.cameraAlignedPosition; - rParam = param.cameraAlignedRotation; - sParam = param.cameraAlignedScale; - } - else if (Tools.pivotRotation == PivotRotation.Local) - { - pParam = param.localPosition; - rParam = param.localRotation; - sParam = param.localScale; - } - - // Draw only the hot control - if (ids.Has(GUIUtility.hotControl)) - { - if (ids.position.Has(GUIUtility.hotControl)) - position = DoPositionHandle_Internal(ids.position, position, workingRotation, pParam); - else if (ids.rotation.Has(GUIUtility.hotControl)) - { - var endRotation = DoRotationHandle(ids.rotation, workingRotation, position, rParam); - - if (cameraAligned) - { - // For camera aligned axis rotation, we need to store the initial rotation to rotate only the delta - if (!s_TransformHandle_RotationData.ContainsKey(ids.rotation)) - { - s_TransformHandle_RotationData[ids.rotation] = new RotationHandleData - { - rotationStarted = true, - initialRotation = rotation - }; - } - - // For freemove rotation, we already have the delta rotation properly - var initialRotation = ids.rotation.xyz != GUIUtility.hotControl - ? s_TransformHandle_RotationData[ids.rotation].initialRotation - : rotation; - var d = endRotation * Quaternion.Inverse(workingRotation); - float angle; - Vector3 axis; - d.ToAngleAxis(out angle, out axis); - rotation = Quaternion.AngleAxis(angle, axis) * initialRotation; - } - else - rotation = endRotation; - } - else if (ids.scale.Has(GUIUtility.hotControl)) - scale = DoScaleHandle(ids.scale, scale, position, workingRotation, HandleUtility.GetHandleSize(position), sParam); - } - else - { - if (s_TransformHandle_RotationData.ContainsKey(ids.rotation)) - { - var data = s_TransformHandle_RotationData[ids.rotation]; - data.rotationStarted = false; - s_TransformHandle_RotationData[ids.rotation] = data; - } - - // Drawing only - DoRotationHandle(ids.rotation, workingRotation, position, rParam); - // Draw scale position last so axes have priority - DoPositionHandle_Internal(ids.position, position, workingRotation, pParam); - DoScaleHandle(ids.scale, scale, position, workingRotation, HandleUtility.GetHandleSize(position), sParam); - } - - var nowIsHot = ids.Has(GUIUtility.hotControl); - if (nowIsHot && !isHot && cameraAligned) - s_IsHotInCameraAlignedMode = true; - else if (s_IsHotInCameraAlignedMode && (!isHot || !nowIsHot)) - s_IsHotInCameraAlignedMode = false; - } - } -} diff --git a/Editor/Mono/EditorHandles/VertexSnapping.cs b/Editor/Mono/EditorHandles/VertexSnapping.cs deleted file mode 100644 index fc5165d840..0000000000 --- a/Editor/Mono/EditorHandles/VertexSnapping.cs +++ /dev/null @@ -1,159 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - internal class VertexSnapping - { - private static Vector3 s_VertexSnappingOffset = Vector3.zero; - - // This method handles KeyUp, KeyDown and MouseMove for doing vertex snapping. - // To ensure correct behaviour the caller must do on it's own: - // - On MouseDown and MouseUp (if event is ours to use): - // HandleUtility.ignoreRaySnapObjects = null; - // - On MouseDrag (if event is ours to use): - // if (Tools.vertexDragging) - // { - // if (HandleUtility.ignoreRaySnapObjects == null) - // Handles.SetupIgnoreRaySnapObjects (); - // Vector3 near; - // if (HandleUtility.FindNearestVertex (evt.mousePosition, null, out near)) - // { - // // Snap position based on found near vertex - // } - // } - // - // This is not the most elegant code-reuse solution, - // but still a step up from the copy-pasted code that was used before. - public static void HandleKeyAndMouseMove(int id) - { - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseMove: - { - if (Tools.vertexDragging) - { - EnableVertexSnapping(id); - evt.Use(); - } - break; - } - case EventType.KeyDown: - { - // Vertex selection - if (evt.keyCode == KeyCode.V) - { - // We are searching for a vertex in our selection - if (!Tools.vertexDragging && !evt.shift) - EnableVertexSnapping(id); - - evt.Use(); - } - break; - } - case EventType.KeyUp: - { - // Vertex selection - if (evt.keyCode == KeyCode.V) - { - if (evt.shift) - Tools.vertexDragging = !Tools.vertexDragging; // toggle vertex dragging - else if (Tools.vertexDragging) - Tools.vertexDragging = false; // stop vertex dragging - - if (Tools.vertexDragging) - EnableVertexSnapping(id); - else - DisableVertexSnapping(id); - - evt.Use(); - } - break; - } - } - } - - private static void EnableVertexSnapping(int id) - { - Tools.vertexDragging = true; - if (GUIUtility.hotControl == id) - { - Tools.handleOffset = s_VertexSnappingOffset; - } - else - { - UpdateVertexSnappingOffset(); - s_VertexSnappingOffset = Tools.handleOffset; - } - } - - private static void DisableVertexSnapping(int id) - { - Tools.vertexDragging = false; - Tools.handleOffset = Vector3.zero; - if (GUIUtility.hotControl != id) - s_VertexSnappingOffset = Vector3.zero; - } - - // Iterates over selected objects, finds nearest vertex or pivot and sets Tools.handleOffset accordingly - private static void UpdateVertexSnappingOffset() - { - Event evt = Event.current; - Tools.vertexDragging = true; - Vector3 nearestVertex; - Transform[] selection = Selection.GetTransforms(SelectionMode.Deep | SelectionMode.ExcludePrefab | SelectionMode.Editable); - - // Make sure we're not ignoring any objects, that other handles may have set to ignore and forgot to reset. - HandleUtility.ignoreRaySnapObjects = null; - - Vector3 nearestPivot = FindNearestPivot(selection, evt.mousePosition); - bool foundVertex = HandleUtility.FindNearestVertex(evt.mousePosition, selection, out nearestVertex); - - Vector3 near; - - // Is nearest vertex closer than nearest pivot? - float distanceToNearestVertex = (HandleUtility.WorldToGUIPoint(nearestVertex) - evt.mousePosition).magnitude; - float distanceToNearestPivot = (HandleUtility.WorldToGUIPoint(nearestPivot) - evt.mousePosition).magnitude; - - if (foundVertex && (distanceToNearestVertex < distanceToNearestPivot)) - near = nearestVertex; - else - near = nearestPivot; - - // Important to reset handleOffset before querying handlePosition, - // since handlePosition depends on handleOffset. - Tools.handleOffset = Vector3.zero; - Tools.handleOffset = near - Tools.handlePosition; - } - - private static Vector3 FindNearestPivot(Transform[] transforms, Vector2 screenPosition) - { - bool foundPivot = false; - Vector3 pivot = Vector3.zero; - - foreach (Transform transform in transforms) - { - Vector3 worldPosition = ScreenToWorld(screenPosition, transform); - if (!foundPivot || (pivot - worldPosition).magnitude > (transform.position - worldPosition).magnitude) - { - pivot = transform.position; - foundPivot = true; - } - } - return pivot; - } - - private static Vector3 ScreenToWorld(Vector2 screen, Transform target) - { - Ray mouseRay = HandleUtility.GUIPointToWorldRay(screen); - float dist = 0.0f; - new Plane(target.forward, target.position).Raycast(mouseRay, out dist); - return mouseRay.GetPoint(dist); - } - } -} diff --git a/Editor/Mono/EditorHeaderItemAttribute.cs b/Editor/Mono/EditorHeaderItemAttribute.cs deleted file mode 100644 index 8a6fafc42b..0000000000 --- a/Editor/Mono/EditorHeaderItemAttribute.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - internal sealed partial class EditorHeaderItemAttribute : CallbackOrderAttribute - { - public EditorHeaderItemAttribute(Type targetType, int priority = 1) - { - TargetType = targetType; - m_CallbackOrder = priority; - } - - public Type TargetType; - - [RequiredSignature] - static extern bool SignatureBool(Rect rectangle, UnityEngine.Object[] targetObjets); - } -} diff --git a/Editor/Mono/EditorResourcesUtility.bindings.cs b/Editor/Mono/EditorResourcesUtility.bindings.cs deleted file mode 100644 index eb2b1515e3..0000000000 --- a/Editor/Mono/EditorResourcesUtility.bindings.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEditor; - -namespace UnityEditorInternal -{ - [NativeHeader("Editor/Src/EditorResources.h")] - internal class EditorResourcesUtility - { - [NativeProperty("EditorResources::kLightSkinSourcePath", true, TargetType.Field)] - public static extern string lightSkinSourcePath { get; } - [NativeProperty("EditorResources::kDarkSkinSourcePath", true, TargetType.Field)] - public static extern string darkSkinSourcePath { get; } - - [NativeProperty("EditorResources::kFontsPath", true, TargetType.Field)] - public static extern string fontsPath { get; } - [NativeProperty("EditorResources::kBrushesPath", true, TargetType.Field)] - public static extern string brushesPath { get; } - [NativeProperty("EditorResources::kIconsPath", true, TargetType.Field)] - public static extern string iconsPath { get; } - [NativeProperty("EditorResources::kGeneratedIconsPath", true, TargetType.Field)] - public static extern string generatedIconsPath { get; } - [NativeProperty("EditorResources::kFolderIconName", true, TargetType.Field)] - public static extern string folderIconName { get; } - [NativeProperty("EditorResources::kEmptyFolderIconName", true, TargetType.Field)] - public static extern string emptyFolderIconName { get; } - } -} diff --git a/Editor/Mono/EditorUserBuildSettings.bindings.cs b/Editor/Mono/EditorUserBuildSettings.bindings.cs deleted file mode 100644 index cab58c389a..0000000000 --- a/Editor/Mono/EditorUserBuildSettings.bindings.cs +++ /dev/null @@ -1,617 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using Object = UnityEngine.Object; -using UnityEngine.Bindings; -using System; -using System.ComponentModel; - -namespace UnityEditor -{ - /// Target PSP2 build platform. - /// - /// SA: EditorUserBuildSettings.psp2BuildSubtarget. - /// - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum PSP2BuildSubtarget - { - /// Build package that it's hosted on the PC - /// SA: EditorUserBuildSettings.psp2BuildSubtarget. - PCHosted = 0, - /// Build a package suited for TestKit testing - /// SA: EditorUserBuildSettings.psp2BuildSubtarget. - Package = 1, - } - - /// Target PS4 build platform. - /// - /// SA: EditorUserBuildSettings.ps4BuildSubtarget. - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum PS4BuildSubtarget - { - /// Build package that it's hosted on the PC - /// SA: EditorUserBuildSettings.ps4BuildSubtarget. - PCHosted = 0, - /// Build a package suited for TestKit testing - /// SA: EditorUserBuildSettings.ps4BuildSubtarget. - Package = 1, - Iso = 2, - } - - - /// Target PS4 build Hardware Target. - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum PS4HardwareTarget - { - /// Target only Base hardware (works identically on Neo hardware) - BaseOnly = 0, - - /// Obsolete. Use PS4ProAndBase instead. - [Obsolete("Enum member PS4HardwareTarget.NeoAndBase has been deprecated. Use PS4HardwareTarget.ProAndBase instead (UnityUpgradable) -> ProAndBase", true)] - NeoAndBase = 1, - - /// Target PS4 Pro hardware, also must work on Base hardware - ProAndBase = 1, - } - - - // Target Xbox build type. - [NativeType(Header = "Runtime/Serialize/BuildTarget.h")] - public enum XboxBuildSubtarget - { - // Development player - Development = 0, - // Master player (submission-proof) - Master = 1, - // Debug player (for building with source code) - Debug = 2, - } - - [NativeType(Header = "Runtime/Serialize/BuildTarget.h")] - public enum XboxOneDeployMethod - { - // copies files to the kit - Push = 0, - // run and load files from a connected PC - Pull = 1, - // PC network share loose files to the kit - RunFromPC = 2, - // Build Xbox One Package - Package = 3, - // Build Xbox One Package - if installed only install launch chunk for testing - PackageStreaming = 4, - } - - [EditorBrowsable(EditorBrowsableState.Never)] - [Obsolete("UnityEditor.AndroidBuildSubtarget has been deprecated. Use UnityEditor.MobileTextureSubtarget instead (UnityUpgradable)", true)] - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum AndroidBuildSubtarget - { - Generic = -1, - DXT = -1, - PVRTC = -1, - ATC = -1, - ETC = -1, - ETC2 = -1, - ASTC = -1, - } - - // Target texture build platform. - [NativeType(Header = "Runtime/Serialize/BuildTarget.h")] - public enum MobileTextureSubtarget - { - // Don't override texture compression. - Generic = 0, - // S3 texture compression, nonspecific to DXT variant. Supported on devices running Nvidia Tegra2 platform, including Motorala Xoom, Motorola Atrix, Droid Bionic, and others. - DXT = 1, - // 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. - PVRTC = 2, - [System.Obsolete("UnityEditor.MobileTextureSubtarget.ATC has been deprecated. Use UnityEditor.MobileTextureSubtarget.ETC instead (UnityUpgradable) -> UnityEditor.MobileTextureSubtarget.ETC", true)] - ATC = 3, - // ETC1 texture compression (or RGBA16 for textures with alpha), supported by all devices. - ETC = 4, - // ETC2/EAC texture compression, supported by GLES 3.0 devices - ETC2 = 5, - // Adaptive Scalable Texture Compression - ASTC = 6, - } - - // Fallback texture format for Android if ETC2 is selected, but not supported - [NativeType(Header = "Runtime/Serialize/BuildTarget.h")] - public enum AndroidETC2Fallback - { - // 32-bit uncompressed - Quality32Bit = 0, - // 16-bit uncompressed - Quality16Bit = 1, - // 32-bit uncompressed, downscaled 2x - Quality32BitDownscaled = 2, - } - - // Keep in sync with WSASubtarget in SerializationMetaFlags.h - [NativeType(Header = "Runtime/Serialize/BuildTarget.h")] - public enum WSASubtarget - { - AnyDevice = 0, - PC = 1, - Mobile = 2, - HoloLens = 3 - } - - // *undocumented* - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum WSASDK - { - // *undocumented* - SDK80 = 0, - // *undocumented* - SDK81 = 1, - // *undocumented* - PhoneSDK81 = 2, - // *undocumented* - UniversalSDK81 = 3, - // *undocumented* - UWP = 4, - } - - // *undocumented* - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum WSAUWPBuildType - { - // *undocumented* - XAML = 0, - // *undocumented* - D3D = 1, - } - - // *undocumented* - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum WSABuildAndRunDeployTarget - { - /// *undocumented* - LocalMachine = 0, - /// *undocumented* - WindowsPhone = 1, - /// *undocumented* - LocalMachineAndWindowsPhone = 2 - } - - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum WSABuildType - { - Debug = 0, - Release = 1, - Master = 2 - } - - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum iOSBuildType - { - Debug = 0, - - Release = 1, - } - - [NativeType(Header = "Runtime/Serialize/BuildTarget.h")] - internal enum Compression - { - None = 0, - Lz4 = 2, - Lz4HC = 3, - } - - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum AndroidBuildSystem - { - Internal = 0, - Gradle = 1, - [Obsolete("ADT/eclipse project export for Android is no longer supported - please use Gradle export instead", true)] - ADT = 2, - /// *undocumented* - VisualStudio = 3, - } - - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum AndroidBuildType - { - Debug = 0, - Development = 1, - Release = 2, - } - - // *undocumented* - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - internal enum AppleBuildAndRunType - { - Xcode = 0, - Xcodebuild = 1, - iOSDeploy = 2, - } - - [NativeType(Header = "Editor/Src/EditorUserBuildSettings.h")] - public enum AndroidMinification - { - None = 0, - Proguard = 1, - Gradle = 2, - } - - [NativeHeader("Editor/Src/EditorUserBuildSettings.h")] - [StaticAccessor("GetEditorUserBuildSettings()", StaticAccessorType.Dot)] - public partial class EditorUserBuildSettings : Object - { - private EditorUserBuildSettings() {} - - internal static AppleBuildAndRunType appleBuildAndRunType = AppleBuildAndRunType.Xcode; - - // The currently selected build target group. - public static extern BuildTargetGroup selectedBuildTargetGroup { get; set; } - - // The currently selected target for a standalone build. - public static extern BuildTarget selectedStandaloneTarget - { - [NativeMethod("GetSelectedStandaloneTarget")] - get; - [NativeMethod("SetSelectedStandaloneTargetFromBindings")] - set; - } - - internal static extern BuildTarget selectedFacebookTarget - { - [NativeMethod("GetSelectedFacebookTarget")] - get; - [NativeMethod("SetSelectedFacebookTargetFromBindings")] - set; - } - - internal static extern string facebookAccessToken { get; set; } - - ///PSP2 Build Subtarget - public static extern PSP2BuildSubtarget psp2BuildSubtarget - { - [NativeMethod("GetSelectedPSP2BuildSubtarget")] - get; - [NativeMethod("SetSelectedPSP2BuildSubtarget")] - set; - } - - - ///PS4 Build Subtarget - public static extern PS4BuildSubtarget ps4BuildSubtarget - { - [NativeMethod("GetSelectedPS4BuildSubtarget")] - get; - [NativeMethod("SetSelectedPS4BuildSubtarget")] - set; - } - - - ///PS4 Build Hardware Target - public static extern PS4HardwareTarget ps4HardwareTarget - { - [NativeMethod("GetPS4HardwareTarget")] - get; - [NativeMethod("SetPS4HardwareTarget")] - set; - } - - - // Are null references actively checked? - public static extern bool explicitNullChecks { get; set; } - - // Are divide by zeros actively checked? - public static extern bool explicitDivideByZeroChecks { get; set; } - - public static extern bool explicitArrayBoundsChecks { get; set; } - - // Should we write out submission materials when building? - public static extern bool needSubmissionMaterials { get; set; } - - // Should we write out compressed archives (Sony PsArc) - public static extern bool compressWithPsArc { get; set; } - - // Should we force an install on the build package, even if there are validation errors - public static extern bool forceInstallation { get; set; } - - // Should we move the package to the Bluray disc outer edge (larger ISO, but faster loading) - public static extern bool movePackageToDiscOuterEdge { get; set; } - - // Should we compress files added to the package file - public static extern bool compressFilesInPackage { get; set; } - - // Headless Mode for Linux Players - public static extern bool enableHeadlessMode { get; set; } - - - // Scripts only build - public static extern bool buildScriptsOnly { get; set; } - - //XboxOne Build subtarget - public static extern XboxBuildSubtarget xboxBuildSubtarget - { - [NativeMethod("GetSelectedXboxBuildSubtarget")] - get; - [NativeMethod("SetSelectedXboxBuildSubtarget")] - set; - } - - // 0..X levels are all considered part of the launch set of streaming install chunks - public static extern int streamingInstallLaunchRange { get; set; } - - //selected Xbox One Deploy Method - public static extern XboxOneDeployMethod xboxOneDeployMethod - { - [NativeMethod("GetSelectedXboxOneDeployMethod")] - get; - [NativeMethod("SetSelectedXboxOneDeployMethod")] - set; - } - - public static extern string xboxOneUsername { get; set; } - - public static extern string xboxOneNetworkSharePath { get; set; } - - - // Transitive property used when adding debug ports to the - // manifest for our test systems. This is required to - // allow the XboxOne to open the required ports in its - // manifest. - public static string xboxOneAdditionalDebugPorts { get; set; } - public static bool xboxOneRebootIfDeployFailsAndRetry { get; set; } - - // Android platform options. - public static extern MobileTextureSubtarget androidBuildSubtarget - { - [NativeMethod("GetSelectedAndroidBuildSubtarget")] - get; - [NativeMethod("SetSelectedAndroidBuildSubtarget")] - set; - } - - //Compression set/get methods for the map containing type for BuildTargetGroup - internal static Compression GetCompressionType(BuildTargetGroup targetGroup) - { - return (Compression)GetCompressionTypeInternal(targetGroup); - } - - [NativeMethod("GetSelectedCompressionType")] - private static extern int GetCompressionTypeInternal(BuildTargetGroup targetGroup); - - internal static void SetCompressionType(BuildTargetGroup targetGroup, Compression type) - { - SetCompressionTypeInternal(targetGroup, (int)type); - } - - [NativeMethod("SetSelectedCompressionType")] - private static extern void SetCompressionTypeInternal(BuildTargetGroup targetGroup, int type); - - public static extern AndroidETC2Fallback androidETC2Fallback - { - [NativeMethod("GetSelectedAndroidETC2Fallback")] - get; - [NativeMethod("SetSelectedAndroidETC2Fallback")] - set; - } - - public static extern AndroidBuildSystem androidBuildSystem { get; set; } - - public static extern AndroidBuildType androidBuildType { get; set; } - - public static extern AndroidMinification androidDebugMinification { get; set; } - - public static extern AndroidMinification androidReleaseMinification { get; set; } - - // *undocumented* - // NOTE: This setting should probably not be a part of the public API as is. Atm it is used by playmode tests - // and applied during build post-processing. We will however move towards separating building and launching - // which makes it unclear when connections should be attempted. In the future, the DeploymentTargets - // API will most likely support connecting to named external devices, which might make this setting obsolete. - internal static extern string androidDeviceSocketAddress { get; set; } - - internal static extern string androidCurrentDeploymentTargetId { get; set; } - - public static extern WSASubtarget wsaSubtarget - { - [NativeMethod("GetSelectedWSABuildSubtarget")] - get; - [NativeMethod("SetSelectedWSABuildSubtarget")] - set; - } - - [Obsolete("EditorUserBuildSettings.wsaSDK is obsolete and has no effect.It will be removed in a subsequent Unity release.")] - public static extern WSASDK wsaSDK - { - [NativeMethod("GetSelectedWSASDK")] - get; - [NativeMethod("SetSelectedWSASDK")] - set; - } - - - // *undocumented* - public static extern WSAUWPBuildType wsaUWPBuildType - { - [NativeMethod("GetSelectedWSAUWPBuildType")] - get; - [NativeMethod("SetSelectedWSAUWPBuildType")] - set; - } - - - public static extern string wsaUWPSDK - { - [NativeMethod("GetSelectedWSAUWPSDK")] - get; - [NativeMethod("SetSelectedWSAUWPSDK")] - set; - } - - public static extern string wsaUWPVisualStudioVersion - { - [NativeMethod("GetSelectedWSAUWPVSVersion")] - get; - [NativeMethod("SetSelectedWSAUWPVSVersion")] - set; - } - - // *undocumented* - public static extern WSABuildAndRunDeployTarget wsaBuildAndRunDeployTarget - { - [NativeMethod("GetSelectedWSABuildAndRunDeployTarget")] - get; - [NativeMethod("SetSelectedWSABuildAndRunDeployTarget")] - set; - } - // *undocumented* - public static extern bool wsaGenerateReferenceProjects - { - [NativeMethod("GetGenerateWSAReferenceProjects")] - get; - [NativeMethod("SetGenerateWSAReferenceProjects")] - set; - } - - public static extern void SetWSADotNetNative(WSABuildType config, bool enabled); - - public static extern bool GetWSADotNetNative(WSABuildType config); - - // Tizen platform options. - public static extern MobileTextureSubtarget tizenBuildSubtarget - { - [NativeMethod("GetSelectedTizenBuildSubtarget")] - get; - [NativeMethod("SetSelectedTizenBuildSubtarget")] - set; - } - - // The currently active build target. - public static extern BuildTarget activeBuildTarget { get; } - - - // The currently active build target. - internal static extern BuildTargetGroup activeBuildTargetGroup { get; } - - [NativeMethod("SwitchActiveBuildTargetSync")] - public static extern bool SwitchActiveBuildTarget(BuildTargetGroup targetGroup, BuildTarget target); - [NativeMethod("SwitchActiveBuildTargetAsync")] - public static extern bool SwitchActiveBuildTargetAsync(BuildTargetGroup targetGroup, BuildTarget target); - - // DEFINE directives for the compiler. - public static extern string[] activeScriptCompilationDefines - { - [NativeMethod("GetActiveScriptCompilationDefinesBindingMethod")] - get; - } - - // Get the current location for the build. - public static extern string GetBuildLocation(BuildTarget target); - - // Set a new location for the build. - public static extern void SetBuildLocation(BuildTarget target, string location); - - public static void SetPlatformSettings(string platformName, string name, string value) - { - string buildTargetGroup = BuildPipeline.GetBuildTargetGroupName(BuildPipeline.GetBuildTargetByName(platformName)); - SetPlatformSettings(buildTargetGroup, platformName, name, value); - } - - public static extern void SetPlatformSettings(string buildTargetGroup, string buildTarget, string name, string value); - - public static string GetPlatformSettings(string platformName, string name) - { - string buildTargetGroup = BuildPipeline.GetBuildTargetGroupName(BuildPipeline.GetBuildTargetByName(platformName)); - return GetPlatformSettings(buildTargetGroup, platformName, name); - } - - public static extern string GetPlatformSettings(string buildTargetGroup, string platformName, string name); - - // Enables a development build. - public static extern bool development { get; set; } - - // Use prebuilt UnityNative asm.js module - public static extern bool webGLUsePreBuiltUnityEngine { get; set; } - - // Start the player with a connection to the profiler. - public static extern bool connectProfiler { get; set; } - - // Enable source-level debuggers to connect. - public static extern bool allowDebugging { get; set; } - - // Export as Android Google Project instead of building it - public static extern bool exportAsGoogleAndroidProject { get; set; } - - // Symlink runtime libraries with an iOS Xcode project. - public static extern bool symlinkLibraries { get; set; } - - // Symlink trampoline for iOS Xcode project. - internal static extern bool symlinkTrampoline { get; set; } - - public static extern iOSBuildType iOSBuildConfigType - { - [NativeMethod("GetIOSBuildType")] - get; - [NativeMethod("SetIOSBuildType")] - set; - } - - // Create a 3DS .cia format image for deploying to test kits. - public static extern bool n3dsCreateCIAFile - { - [NativeMethod("GetCreateCIAFileFor3DS")] - get; - [NativeMethod("SetCreateCIAFileFor3DS")] - set; - } - - // Instead of creating a ROM file, create a buildable Visual Studio 2015 solution. - public static extern bool switchCreateSolutionFile - { - [NativeMethod("GetCreateSolutionFileForSwitch")] - get; - [NativeMethod("SetCreateSolutionFileForSwitch")] - set; - } - - - // Create a .nsp ROM file out of the loose-files .nspd folder - public static extern bool switchCreateRomFile - { - [NativeMethod("GetCreateRomFileForSwitch")] - get; - [NativeMethod("SetCreateRomFileForSwitch")] - set; - } - - - // Enable linkage of NVN Grahpics Debugger for Nintendo Switch. - public static extern bool switchNVNGraphicsDebugger - { - [NativeMethod("GetNVNGraphicsDebuggerForSwitch")] - get; - [NativeMethod("SetNVNGraphicsDebuggerForSwitch")] - set; - } - - // Enable linkage of DebugPad functionality for Nintendo Switch. - public static extern bool switchEnableDebugPad - { - [NativeMethod("GetEnableDebugPadForSwitch")] - get; - [NativeMethod("SetEnableDebugPadForSwitch")] - set; - } - - // Redirect attempts to write to "rom:" mount, to "host:" mount for Nintendo Switch (for debugging and tests only) - public static extern bool switchRedirectWritesToHostMount - { - [NativeMethod("GetRedirectWritesToHostMountForSwitch")] - get; - [NativeMethod("SetRedirectWritesToHostMountForSwitch")] - set; - } - - // Place the built player in the build folder. - public static extern bool installInBuildFolder { get; set; } - } -} diff --git a/Editor/Mono/EditorUserBuildSettings.deprecated.cs b/Editor/Mono/EditorUserBuildSettings.deprecated.cs deleted file mode 100644 index faff5e9f4c..0000000000 --- a/Editor/Mono/EditorUserBuildSettings.deprecated.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor -{ - public partial class EditorUserBuildSettings - { - // Select a new build target to be active. - [Obsolete("Please use SwitchActiveBuildTarget(BuildTargetGroup targetGroup, BuildTarget target)")] - public static bool SwitchActiveBuildTarget(BuildTarget target) - { - return SwitchActiveBuildTarget(BuildPipeline.GetBuildTargetGroup(target), target); - } - - // Triggered in response to SwitchActiveBuildTarget. - [Obsolete("UnityEditor.activeBuildTargetChanged has been deprecated.Use UnityEditor.Build.IActiveBuildTargetChanged instead.")] - public static Action activeBuildTargetChanged; - -#pragma warning disable 0618 - internal static void Internal_ActiveBuildTargetChanged() - { - if (activeBuildTargetChanged != null) - activeBuildTargetChanged(); - } - -#pragma warning restore 0618 - - // Force full optimisations for script complilation in Development builds (OBSOLETE, replaced by "IL2CPP optimization level" Player Setting) - [Obsolete("forceOptimizeScriptCompilation is obsolete - will always return false. Control script optimization using the 'IL2CPP optimization level' configuration in Player Settings / Other.")] - public static bool forceOptimizeScriptCompilation { get { return false; } } - } -} diff --git a/Editor/Mono/EditorUserBuildSettingsUtils.cs b/Editor/Mono/EditorUserBuildSettingsUtils.cs deleted file mode 100644 index 5226c39902..0000000000 --- a/Editor/Mono/EditorUserBuildSettingsUtils.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Build; - -namespace UnityEditor -{ - internal static class EditorUserBuildSettingsUtils - { - public static BuildTarget CalculateSelectedBuildTarget() - { - BuildTargetGroup targetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; - switch (targetGroup) - { - case BuildTargetGroup.Standalone: - return DesktopStandaloneBuildWindowExtension.GetBestStandaloneTarget(EditorUserBuildSettings.selectedStandaloneTarget); - case BuildTargetGroup.Facebook: - return EditorUserBuildSettings.selectedFacebookTarget; - default: - if (BuildPlatforms.instance == null) - throw new System.Exception("Build platforms are not initialized."); - BuildPlatform platform = BuildPlatforms.instance.BuildPlatformFromTargetGroup(targetGroup); - if (platform == null) - throw new System.Exception("Could not find build platform for target group " + targetGroup); - return platform.defaultTarget; - } - } - } -} diff --git a/Editor/Mono/EditorUtility.bindings.cs b/Editor/Mono/EditorUtility.bindings.cs deleted file mode 100644 index 4469538bef..0000000000 --- a/Editor/Mono/EditorUtility.bindings.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - public partial class EditorUtility - { - internal static bool IsUnityAssembly(Object target) - { - if (target == null) - return false; - System.Type type = target.GetType(); - return IsUnityAssembly(type); - } - - internal static bool IsUnityAssembly(System.Type type) - { - if (type == null) - return false; - string assembly_name = type.Assembly.GetName().Name; - if (assembly_name.StartsWith("UnityEditor")) - { - return true; - } - if (assembly_name.StartsWith("UnityEngine")) - { - return true; - } - return false; - } - } -} diff --git a/Editor/Mono/EditorWindow.cs b/Editor/Mono/EditorWindow.cs deleted file mode 100644 index 552b677ef0..0000000000 --- a/Editor/Mono/EditorWindow.cs +++ /dev/null @@ -1,994 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Linq; -using System; -using UnityEditor.Experimental.UIElements; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor -{ - // For bindings see: EditorWindow.bindings - - [ExcludeFromObjectFactory] - public partial class EditorWindow : ScriptableObject - { - [HideInInspector] - bool m_AutoRepaintOnSceneChange; - - [SerializeField] - [HideInInspector] - Vector2 m_MinSize = new Vector2(100, 100); - - [SerializeField] - [HideInInspector] - Vector2 m_MaxSize = new Vector2(4000, 4000); - - [SerializeField] - [HideInInspector] - internal GUIContent m_TitleContent; - - [HideInInspector] - int m_DepthBufferBits = 0; - - [SerializeField] - [HideInInspector] - internal Rect m_Pos = new Rect(0, 0, 320, 240); - - VisualElement m_RootVisualContainer; - - internal VisualElement rootVisualContainer - { - get - { - if (m_RootVisualContainer == null) - { - m_RootVisualContainer = new VisualElement() - { - name = VisualElementUtils.GetUniqueName("rootVisualContainer"), - pickingMode = PickingMode.Ignore, // do not eat events so IMGUI gets them - persistenceKey = "rootVisualContainer" - }; - UIElementsEditorUtility.AddDefaultEditorStyleSheets(m_RootVisualContainer); - } - return m_RootVisualContainer; - } - } - - [HideInInspector] - [SerializeField] - private SerializableJsonDictionary m_PersistentViewDataDictionary; - - private bool m_EnableViewDataPersistence; - - internal SerializableJsonDictionary viewDataDictionary - { - get - { - // If persistence is disabled, just don't even create the dictionary. Return null. - if (m_EnableViewDataPersistence && m_PersistentViewDataDictionary == null) - { - string editorPrefFileName = this.GetType().ToString(); - m_PersistentViewDataDictionary = EditorWindowPersistentViewData.instance[editorPrefFileName]; - } - return m_PersistentViewDataDictionary; - } - } - - internal void SavePersistentViewData() - { - if (m_EnableViewDataPersistence && m_PersistentViewDataDictionary != null) - { - string editorPrefFileName = this.GetType().ToString(); - EditorWindowPersistentViewData.instance.Save(editorPrefFileName, m_PersistentViewDataDictionary); - } - } - - internal ISerializableJsonDictionary GetViewDataDictionary() - { - return viewDataDictionary; - } - - // TODO: These should be made public when UIElements is no longer experimental. - internal void DisableViewDataPersistence() - { - m_EnableViewDataPersistence = false; - } - - internal void ClearPersistentViewData() - { - string editorPrefFileName = this.GetType().ToString(); - EditorWindowPersistentViewData.instance.Clear(editorPrefFileName); - DestroyImmediate(m_PersistentViewDataDictionary); - m_PersistentViewDataDictionary = null; - } - - // The GameView rect is in GUI space of the view - Rect m_GameViewRect; - Rect m_GameViewClippedRect; - Vector2 m_GameViewTargetSize; - - bool m_DontClearBackground; - EventInterests m_EventInterests = new EventInterests(); - bool m_DisableInputEvents; - - // Dockarea we're inside. - [NonSerialized] - internal HostView m_Parent; - - // Overlay a notification message over the window. - const double kWarningFadeoutWait = 4; - const double kWarningFadeoutTime = 1; - - internal GUIContent m_Notification = null; - Vector2 m_NotificationSize; - internal float m_FadeoutTime = 0; - - // Mark the beginning area of all popup windows. - public void BeginWindows() - { - EditorGUIInternal.BeginWindowsForward(1, GetInstanceID()); - } - - // Close a window group started with EditorWindow::ref::BeginWindows - public void EndWindows() - { - GUI.EndWindows(); - } - - internal virtual void OnResized() {} - - // Does the GUI in this editor window want MouseMove events? - public bool wantsMouseMove - { - get - { - return m_EventInterests.wantsMouseMove; - } - set - { - m_EventInterests.wantsMouseMove = value; - MakeParentsSettingsMatchMe(); - } - } - - // Does the GUI in this editor window want MouseEnter/LeaveWindow events? - public bool wantsMouseEnterLeaveWindow - { - get - { - return m_EventInterests.wantsMouseEnterLeaveWindow; - } - set - { - m_EventInterests.wantsMouseEnterLeaveWindow = value; - MakeParentsSettingsMatchMe(); - } - } - - internal void CheckForWindowRepaint() - { - double time = EditorApplication.timeSinceStartup; - if (time < m_FadeoutTime) - return; - if (time > m_FadeoutTime + kWarningFadeoutTime) - { - RemoveNotification(); - return; - } - Repaint(); - } - - internal GUIContent GetLocalizedTitleContent() - { - return GetLocalizedTitleContentFromType(GetType()); - } - - internal static GUIContent GetLocalizedTitleContentFromType(Type t) - { - EditorWindowTitleAttribute attr = GetEditorWindowTitleAttribute(t); - if (attr != null) - { - string iconName = ""; - if (!string.IsNullOrEmpty(attr.icon)) - iconName = attr.icon; - else if (attr.useTypeNameAsIconName) - iconName = t.ToString(); - - if (!string.IsNullOrEmpty(iconName)) - { - // This should error msg if icon is not found since icon has been explicitly requested by the user - return EditorGUIUtility.TrTextContentWithIcon(attr.title, iconName); - } - - return EditorGUIUtility.TrTextContent(attr.title); - } - - // Fallback to type name (Do not localize type name) - return new GUIContent(t.ToString()); - } - - static EditorWindowTitleAttribute GetEditorWindowTitleAttribute(Type t) - { - object[] attrs = t.GetCustomAttributes(true); - foreach (object attr in attrs) - { - Attribute realAttr = (Attribute)attr; - if (realAttr.TypeId == typeof(EditorWindowTitleAttribute)) - { - return (EditorWindowTitleAttribute)attr; - } - } - return null; - } - - // Show a notification message. - public void ShowNotification(GUIContent notification) - { - m_Notification = new GUIContent(notification); - if (m_FadeoutTime == 0) - EditorApplication.update += CheckForWindowRepaint; - m_FadeoutTime = (float)(EditorApplication.timeSinceStartup + kWarningFadeoutWait); - } - - // Stop showing notification message. - public void RemoveNotification() - { - if (m_FadeoutTime == 0) - return; - EditorApplication.update -= CheckForWindowRepaint; - m_Notification = null; - m_FadeoutTime = 0; - } - - internal void DrawNotification() - { - EditorStyles.notificationText.CalcMinMaxWidth(m_Notification, out m_NotificationSize.y, out m_NotificationSize.x); - m_NotificationSize.y = EditorStyles.notificationText.CalcHeight(m_Notification, m_NotificationSize.x); - - Vector2 warningSize = m_NotificationSize; - float targetWidth = position.width - EditorStyles.notificationText.margin.horizontal; - float targetHeight = position.height - EditorStyles.notificationText.margin.vertical - 20; - // See if we can fit horizontally. If not, rescale down. - if (targetWidth < m_NotificationSize.x) - { - float scale = targetWidth / m_NotificationSize.x; - warningSize.x *= scale; - - warningSize.y = EditorStyles.notificationText.CalcHeight(m_Notification, warningSize.x); - } - - if (warningSize.y > targetHeight) - warningSize.y = targetHeight; - - Rect r = new Rect((position.width - warningSize.x) * .5f, 20 + (position.height - 20 - warningSize.y) * .7f, warningSize.x, warningSize.y); - double time = EditorApplication.timeSinceStartup; - if (time > m_FadeoutTime) - GUI.color = new Color(1, 1, 1, 1 - (float)((time - m_FadeoutTime) / kWarningFadeoutTime)); - GUI.Label(r, GUIContent.none, EditorStyles.notificationBackground); - EditorGUI.DoDropShadowLabel(r, m_Notification, EditorStyles.notificationText, .3f); - } - - internal bool dontClearBackground - { - get - { - return m_DontClearBackground; - } - set - { - m_DontClearBackground = value; - if (m_Parent && m_Parent.actualView == this) - m_Parent.backgroundValid = false; - } - } - - - // Does the window automatically repaint whenever the scene has changed? - public bool autoRepaintOnSceneChange - { - get - { - return m_AutoRepaintOnSceneChange; - } - set - { - m_AutoRepaintOnSceneChange = value; - MakeParentsSettingsMatchMe(); - } - } - - public bool maximized - { - get - { - return WindowLayout.IsMaximized(this); - } - set - { - bool current = WindowLayout.IsMaximized(this); - if (value != current) - { - if (value) - WindowLayout.Maximize(this); - else - WindowLayout.Unmaximize(this); - } - } - } - - internal bool hasFocus { get { return m_Parent && m_Parent.actualView == this; } } - - internal bool docked { get { return m_Parent != null && m_Parent.window != null && !m_Parent.window.IsNotDocked(); } } - - // This property can be used to stop OS events from being sent to the EditorWindow - internal bool disableInputEvents - { - get { return m_DisableInputEvents; } - set - { - if (m_DisableInputEvents == value) - return; - m_DisableInputEvents = value; - MakeParentsSettingsMatchMe(); - } - } - - // The EditorWindow which currently has keyboard focus (RO) - static public EditorWindow focusedWindow - { - get - { - HostView view = GUIView.focusedView as HostView; - if (view != null) - return view.actualView; - else - return null; - } - } - - // The EditorWindow currently under the mouse cursor (RO) - static public EditorWindow mouseOverWindow - { - get - { - HostView view = GUIView.mouseOverView as HostView; - if (view != null) - return view.actualView; - else - return null; - } - } - - - internal int GetNumTabs() - { - DockArea da = m_Parent as DockArea; - if (da) - { - return da.m_Panes.Count; - } - return 0; - } - - internal bool ShowNextTabIfPossible() - { - DockArea da = m_Parent as DockArea; - if (da) - { - int idx = da.m_Panes.IndexOf(this); - idx = (idx + 1) % da.m_Panes.Count; - if (da.selected != idx) - { - da.selected = idx; - da.Repaint(); - return true; - } - } - return false; - } - - public void ShowTab() - { - DockArea da = m_Parent as DockArea; - if (da) - { - int idx = da.m_Panes.IndexOf(this); - if (da.selected != idx) - da.selected = idx; - } - - Repaint(); - } - - // Moves keyboard focus to this EditorWindow. - public void Focus() - { - if (m_Parent) - { - ShowTab(); - m_Parent.Focus(); - } - } - - internal void MakeParentsSettingsMatchMe() - { - if (!m_Parent || m_Parent.actualView != this) - return; - m_Parent.SetTitle(GetType().FullName); - m_Parent.autoRepaintOnSceneChange = m_AutoRepaintOnSceneChange; - bool parentChanged = m_Parent.depthBufferBits != m_DepthBufferBits; - m_Parent.depthBufferBits = m_DepthBufferBits; - m_Parent.SetInternalGameViewDimensions(m_GameViewRect, m_GameViewClippedRect, m_GameViewTargetSize); - m_Parent.eventInterests = m_EventInterests; - m_Parent.disableInputEvents = m_DisableInputEvents; - Vector2 parentBorderSizes = new Vector2(m_Parent.borderSize.left + m_Parent.borderSize.right, m_Parent.borderSize.top + m_Parent.borderSize.bottom); - m_Parent.SetMinMaxSizes(minSize + parentBorderSizes, maxSize + parentBorderSizes); - if (parentChanged) - m_Parent.RecreateContext(); - } - - // Show the EditorWindow as a floating utility window. - public void ShowUtility() - { - ShowWithMode(ShowMode.Utility); - } - - // Used for popup style windows. - public void ShowPopup() - { - if (m_Parent == null) - { - ContainerWindow cw = ScriptableObject.CreateInstance(); - cw.title = titleContent.text; - HostView host = ScriptableObject.CreateInstance(); - host.actualView = this; - - Rect r = m_Parent.borderSize.Add(new Rect(position.x, position.y, position.width, position.height)); - // Order is important here: first set rect of container, then assign main view, then apply various settings, then show. - // Otherwise the rect won't be set until first resize happens. - cw.position = r; - cw.rootView = host; - MakeParentsSettingsMatchMe(); - cw.ShowPopup(); - } - } - - internal void ShowWithMode(ShowMode mode) - { - if (m_Parent == null) - { - SavedGUIState oldState = SavedGUIState.Create(); - - ContainerWindow cw = ScriptableObject.CreateInstance(); - cw.title = titleContent.text; - HostView host = ScriptableObject.CreateInstance(); - host.actualView = this; - - Rect r = m_Parent.borderSize.Add(new Rect(position.x, position.y, position.width, position.height)); - // Order is important here: first set rect of container, then assign main view, then apply various settings, then show. - // Otherwise the rect won't be set until first resize happens. - cw.position = r; - cw.rootView = host; - MakeParentsSettingsMatchMe(); - cw.Show(mode, true, false); - // set min/max size now that native window is not null so that it will e.g., use proper styleMask on macOS - cw.SetMinMaxSizes(minSize, maxSize); - - oldState.ApplyAndForget(); - } - } - - // Show window with dropdown behaviour (e.g. window is closed when it loses focus) and having - public void ShowAsDropDown(Rect buttonRect, Vector2 windowSize) - { - ShowAsDropDown(buttonRect, windowSize, null); - } - - internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocationHelper.PopupLocation[] locationPriorityOrder) - { - ShowAsDropDown(buttonRect, windowSize, locationPriorityOrder, ShowMode.PopupMenu); - } - - // Show as drop down list with custom fit to screen callback - // 'buttonRect' is used for displaying the dropdown below that rect if possible otherwise above - // 'windowSize' is used for setting up initial size - // 'locationPriorityOrder' is for manual popup direction, if null it uses default order: down, up, left or right - internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocationHelper.PopupLocation[] locationPriorityOrder, ShowMode mode) - { - // Setup position before bringing window live (otherwise the dropshadow on Windows will be placed in 0,0 first frame) - position = ShowAsDropDownFitToScreen(buttonRect, windowSize, locationPriorityOrder); - - // Show window and focus - ShowWithMode(mode); - - // Fit to screen again now that we have a container window - position = ShowAsDropDownFitToScreen(buttonRect, windowSize, locationPriorityOrder); - - // Default to none resizable window - minSize = new Vector2(position.width, position.height); - maxSize = new Vector2(position.width, position.height); - - // Focus window - if (focusedWindow != this) - Focus(); - - // Add after unfreezing display because AuxWindowManager.cpp assumes that aux windows are added after we got/lost- focus calls. - m_Parent.AddToAuxWindowList(); - - // Dropdown windows should not be saved to layout - m_Parent.window.m_DontSaveToLayout = true; - } - - internal Rect ShowAsDropDownFitToScreen(Rect buttonRect, Vector2 windowSize, PopupLocationHelper.PopupLocation[] locationPriorityOrder) - { - if (m_Parent == null) - return new Rect(buttonRect.x, buttonRect.yMax, windowSize.x, windowSize.y); - - return m_Parent.window.GetDropDownRect(buttonRect, windowSize, windowSize, locationPriorityOrder); - } - - public void Show() - { - Show(false); - } - - // Show the EditorWindow. - public void Show(bool immediateDisplay) - { - // If somebody called show on us, set up the neccessary structure for us. - if (m_Parent == null) - CreateNewWindowForEditorWindow(this, true, immediateDisplay); - } - - // Show the editor window in the auxiliary window. - public void ShowAuxWindow() - { - ShowWithMode(ShowMode.AuxWindow); - - // We ensure Focus change before calling AddToAuxWindowList because the - // AuxWindowManager assumes that focus has been changed before a new window is added. - Focus(); - - m_Parent.AddToAuxWindowList(); - } - - // Show modal editor window. Other windows will not be accessible until this one is closed. - internal void ShowModal() - { - ShowWithMode(ShowMode.AuxWindow); - SavedGUIState guiState = SavedGUIState.Create(); - MakeModal(m_Parent.window); - guiState.ApplyAndForget(); - } - - // Returns the first EditorWindow of type /t/ which is currently on the screen. - static EditorWindow GetWindowPrivate(System.Type t, bool utility, string title, bool focus) - { - UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(t); - EditorWindow win = wins.Length > 0 ? (EditorWindow)(wins[0]) : null; - - if (!win) - { - win = ScriptableObject.CreateInstance(t) as EditorWindow; - if (title != null) - win.titleContent = new GUIContent(title); - if (utility) - win.ShowUtility(); - else - win.Show(); - } - else if (focus) - { - win.Show(); // For some corner cases in saved layouts, the window can be in an unvisible state. - // Since the caller asked for focus, it's fair to assume he wants it always to be visible. (case 586743) - win.Focus(); - } - - return win; - } - - public static T GetWindow() where T : EditorWindow - { - return GetWindow(false, null, true); - } - - public static T GetWindow(bool utility) where T : EditorWindow - { - return GetWindow(utility, null, true); - } - - public static T GetWindow(bool utility, string title) where T : EditorWindow - { - return GetWindow(utility, title, true); - } - - public static T GetWindow(string title) where T : EditorWindow - { - return GetWindow(title, true); - } - - public static T GetWindow(string title, bool focus) where T : EditorWindow - { - return GetWindow(false, title, focus); - } - - // Returns the first EditorWindow of type /T/ which is currently on the screen. - public static T GetWindow(bool utility, string title, bool focus) where T : EditorWindow - { - return GetWindow(typeof(T), utility, title, focus) as T; - } - - public static T GetWindow(params System.Type[] desiredDockNextTo) where T : EditorWindow - { - return GetWindow(null, true, desiredDockNextTo); - } - - public static T GetWindow(string title, params System.Type[] desiredDockNextTo) where T : EditorWindow - { - return GetWindow(title, true, desiredDockNextTo); - } - - // Returns the first EditorWindow of type /T/ which is currently on the screen. - public static T GetWindow(string title, bool focus, params System.Type[] desiredDockNextTo) where T : EditorWindow - { - var wins = Resources.FindObjectsOfTypeAll(typeof(T)) as T[]; - T win = wins.Length > 0 ? wins[0] : null; - - //If the window already exists just focus then return it... - if (win != null) - { - if (focus) - win.Focus(); - return win; - } - - win = CreateInstance(); - if (title != null) - win.titleContent = new GUIContent(title); - - //Iterate the desired dock next to types... - foreach (var desired in desiredDockNextTo) - { - var windows = ContainerWindow.windows; - foreach (var w in windows) - { - foreach (var view in w.rootView.allChildren) - { - var dockArea = view as DockArea; - if (dockArea == null) continue; - if (dockArea.m_Panes.Any(pane => pane.GetType() == desired)) - { - dockArea.AddTab(win); - return win; - } - } - } - } - win.Show(); - return win; - } - - // Focuses the first found EditorWindow of specified type if it is open. - public static void FocusWindowIfItsOpen(System.Type t) - { - UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(t); - EditorWindow win = wins.Length > 0 ? (wins[0] as EditorWindow) : null; - if (win) - win.Focus(); - } - - // Focuses the first found EditorWindow of type /T/ if it is open. - public static void FocusWindowIfItsOpen() where T : EditorWindow - { - FocusWindowIfItsOpen(typeof(T)); - } - - internal void RemoveFromDockArea() - { - DockArea da = m_Parent as DockArea; - if (da) - { - da.RemoveTab(this, true); - } - } - - // Returns the first EditorWindow of type /t/ which is currently on the screen. - static EditorWindow GetWindowWithRectPrivate(System.Type t, Rect rect, bool utility, string title) - { - UnityEngine.Object[] wins = Resources.FindObjectsOfTypeAll(t); - EditorWindow win = wins.Length > 0 ? (EditorWindow)(wins[0]) : null; - - if (!win) - { - win = ScriptableObject.CreateInstance(t) as EditorWindow; - win.minSize = new Vector2(rect.width, rect.height); - win.maxSize = new Vector2(rect.width, rect.height); - win.position = rect; - if (title != null) - win.titleContent = new GUIContent(title); - if (utility) - win.ShowUtility(); - else - win.Show(); - } - else - win.Focus(); - - return win; - } - - public static T GetWindowWithRect(Rect rect) where T : EditorWindow - { - return GetWindowWithRect(rect, false, null, true); - } - - public static T GetWindowWithRect(Rect rect, bool utility) where T : EditorWindow - { - return GetWindowWithRect(rect, utility, null, true); - } - - public static T GetWindowWithRect(Rect rect, bool utility, string title) where T : EditorWindow - { - return GetWindowWithRect(rect, utility, title, true); - } - - // Returns the first EditorWindow of type /t/ which is currently on the screen. - public static T GetWindowWithRect(Rect rect, bool utility, string title, bool focus) where T : EditorWindow - { - UnityEngine.Object[] windows = Resources.FindObjectsOfTypeAll(typeof(T)); - T window; - - if (windows.Length > 0) - { - window = (T)windows[0]; - if (focus) - window.Focus(); - } - else - { - window = ScriptableObject.CreateInstance(); - window.minSize = new Vector2(rect.width, rect.height); - window.maxSize = new Vector2(rect.width, rect.height); - window.position = rect; - if (title != null) - window.titleContent = new GUIContent(title); - if (utility) - window.ShowUtility(); - else - window.Show(); - } - - return window; - } - - internal static T GetWindowDontShow() where T : EditorWindow - { - UnityEngine.Object[] windows = Resources.FindObjectsOfTypeAll(typeof(T)); - return (windows.Length > 0) ? (T)windows[0] : ScriptableObject.CreateInstance(); - } - - // Close the editor window. - public void Close() - { - // Ensure to restore normal workspace before destroying. Fix case 406657. - if (WindowLayout.IsMaximized(this)) - WindowLayout.Unmaximize(this); - - DockArea da = m_Parent as DockArea; - if (da) - { - da.RemoveTab(this, true); - } - else - { - m_Parent.window.Close(); - } - UnityEngine.Object.DestroyImmediate(this, true); - } - - // Make the window repaint. - public void Repaint() - { - if (m_Parent && m_Parent.actualView == this) - { - m_Parent.Repaint(); - } - } - - internal void RepaintImmediately() - { - if (m_Parent && m_Parent.actualView == this) - m_Parent.RepaintImmediately(); - } - - // the minimum size of this window - public Vector2 minSize - { - get - { - return m_MinSize; - } - set - { - m_MinSize = value; MakeParentsSettingsMatchMe(); - } - } - - // the maximum size of this window - public Vector2 maxSize - { - get - { - return m_MaxSize; - } - set - { - m_MaxSize = value; - MakeParentsSettingsMatchMe(); - } - } - - - // The title of this window (legacy) - [System.Obsolete("Use titleContent instead (it supports setting a title icon as well).")] - public string title - { - get - { - return titleContent.text; - } - set - { - titleContent = EditorGUIUtility.TextContent(value); - } - } - - public GUIContent titleContent - { - get - { - return m_TitleContent ?? (m_TitleContent = new GUIContent()); // Ensure m_TitleContent is not null (so we can prevent null checks) - } - set - { - m_TitleContent = value; - if (m_TitleContent != null && m_Parent && m_Parent.window && m_Parent.window.rootView == m_Parent) - m_Parent.window.title = m_TitleContent.text; - } - } - - public int depthBufferBits - { - get { return m_DepthBufferBits; } - set { m_DepthBufferBits = value; } - } - - internal void SetParentGameViewDimensions(Rect rect, Rect clippedRect, Vector2 targetSize) - { - m_GameViewRect = rect; - m_GameViewClippedRect = clippedRect; - m_GameViewTargetSize = targetSize; - m_Parent.SetInternalGameViewDimensions(m_GameViewRect, m_GameViewClippedRect, m_GameViewTargetSize); - } - - [Obsolete("AA is not supported on EditorWindows", false)] - public int antiAlias - { - get { return 1; } - set {} - } - - // The position of the window in screen space. - public Rect position - { - get - { - return m_Pos; - } - set - { - m_Pos = value; - // We're setting the position of this editorWindow. - // Only handle this is we have a parent. (unless we're just getting set up) - if (m_Parent) - { - // 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 - // move the ContainerWindow that we're inside - DockArea da = m_Parent as DockArea; - if (!da) - { - m_Parent.window.position = value; - } - else if (da.parent && da.m_Panes.Count == 1 && !da.parent.parent) // We should have a DockArea, then a splitView, then null - { - var newPosition = da.borderSize.Add(value); - if (da.background != null) - { - newPosition.y -= da.background.margin.top; - } - da.window.position = newPosition; - } - else - { - // We're docked in a deeper hierarchy, so we need to undock us - da.RemoveTab(this); - // and then create a new window for us... - CreateNewWindowForEditorWindow(this, true, true); - } - } - } - } - - // Sends an Event to a window. - public bool SendEvent(Event e) - { - return m_Parent.SendEvent(e); - } - - public EditorWindow() - { - m_EnableViewDataPersistence = true; - - titleContent.text = GetType().ToString(); - } - - private void __internalAwake() - { - hideFlags = HideFlags.DontSave; // Can't be HideAndDontSave, as that would make scriptable wizard GUI be disabled - } - - // Internal stuff: - // Helper to show this EditorWindow - internal static void CreateNewWindowForEditorWindow(EditorWindow window, bool loadPosition, bool showImmediately) - { - CreateNewWindowForEditorWindow(window, new Vector2(window.position.x, window.position.y), loadPosition, showImmediately); - } - - internal static void CreateNewWindowForEditorWindow(EditorWindow window, Vector2 screenPosition, bool loadPosition, bool showImmediately) - { - ContainerWindow cw = ScriptableObject.CreateInstance(); - SplitView sw = ScriptableObject.CreateInstance(); - cw.rootView = sw; - DockArea da = ScriptableObject.CreateInstance(); - sw.AddChild(da); - da.AddTab(window); - Rect r = window.m_Parent.borderSize.Add(new Rect(screenPosition.x, screenPosition.y, window.position.width, window.position.height)); - cw.position = r; - sw.position = new Rect(0, 0, r.width, r.height); - window.MakeParentsSettingsMatchMe(); - cw.Show(ShowMode.NormalWindow, loadPosition, showImmediately); - //Need this, as show my change the size of the window, due to screen constraints - cw.OnResize(); - } - - // This is such a hack, but will do for now - [ContextMenu("Add Scene")] - internal void AddSceneTab() {} - - [ContextMenu("Add Game")] - internal void AddGameTab() {} - } - - [AttributeUsage(AttributeTargets.Class)] - internal class EditorWindowTitleAttribute : System.Attribute - { - public string title { get; set; } - public string icon { get; set; } - public bool useTypeNameAsIconName { get; set; } - } - - // makes UIElements opt-in while it's experimental, as a using statement is necessary to call this method - namespace Experimental.UIElements - { - public static class UIElementsEntryPoint - { - public static VisualElement GetRootVisualContainer(this EditorWindow window) - { - return window.rootVisualContainer; - } - } - } -} //namespace diff --git a/Editor/Mono/ExportPackageOptions.cs b/Editor/Mono/ExportPackageOptions.cs deleted file mode 100644 index fcb14d2b7d..0000000000 --- a/Editor/Mono/ExportPackageOptions.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -namespace UnityEditor -{ - // Export package option. Multiple options can be combined together using the | operator. - [Flags] - public enum ExportPackageOptions - { - // Default mode. Will not include dependencies or subdirectories nor include Library assets unless specifically included in the asset list. - Default = 0, - - // The export operation will be run asynchronously and reveal the exported package file in a file browser window after the export is finished. - Interactive = 1, - - // Will recurse through any subdirectories listed and include all assets inside them. - Recurse = 2, - - // In addition to the assets paths listed, all dependent assets will be included as well. - IncludeDependencies = 4, - - // The exported package will include all library assets, ie. the project settings located in the Library folder of the project. - IncludeLibraryAssets = 8 - } -} diff --git a/Editor/Mono/FileUtil.bindings.cs b/Editor/Mono/FileUtil.bindings.cs deleted file mode 100644 index b4a51e50b0..0000000000 --- a/Editor/Mono/FileUtil.bindings.cs +++ /dev/null @@ -1,144 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using System.IO; - - -namespace UnityEditor -{ - // Lets you do ''move'', ''copy'', ''delete'' operations over files or directories - [NativeHeader("Runtime/Utilities/FileUtilities.h")] - [NativeHeader("Editor/Platform/Interface/EditorUtility.h")] - public partial class FileUtil - { - // Deletes a file or a directory given a path. - [FreeFunction] - public static extern bool DeleteFileOrDirectory(string path); - - [FreeFunction("IsPathCreated")] - private static extern bool PathExists(string path); - - // Copies a file or directory. - public static void CopyFileOrDirectory(string source, string dest) - { - CheckForValidSourceAndDestinationArgumentsAndRaiseAnExceptionWhenNullOrEmpty(source, dest); - - if (PathExists(dest)) - { - throw new System.IO.IOException(string.Format( - "Failed to Copy File / Directory from '{0}' to '{1}': destination path already exists.", source, dest)); - } - - if (!CopyFileOrDirectoryInternal(source, dest)) - { - throw new System.IO.IOException(string.Format( - "Failed to Copy File / Directory from '{0}' to '{1}'.", source, dest)); - } - } - - [FreeFunction("CopyFileOrDirectory")] - private static extern bool CopyFileOrDirectoryInternal(string source, string dest); - - // Copies the file or directory following symbolic links. - public static void CopyFileOrDirectoryFollowSymlinks(string source, string dest) - { - CheckForValidSourceAndDestinationArgumentsAndRaiseAnExceptionWhenNullOrEmpty(source, dest); - - if (PathExists(dest)) - { - throw new System.IO.IOException(string.Format( - "Failed to Copy File / Directory from '{0}' to '{1}': destination path already exists.", source, dest)); - } - - if (!CopyFileOrDirectoryFollowSymlinksInternal(source, dest)) - { - throw new System.IO.IOException(string.Format( - "Failed to Copy File / Directory from '{0}' to '{1}'.", source, dest)); - } - } - - [FreeFunction("CopyFileOrDirectoryFollowSymlinks")] - private static extern bool CopyFileOrDirectoryFollowSymlinksInternal(string source, string dest); - - // Moves a file or a directory from a given path to another path. - public static void MoveFileOrDirectory(string source, string dest) - { - CheckForValidSourceAndDestinationArgumentsAndRaiseAnExceptionWhenNullOrEmpty(source, dest); - - if (PathExists(dest)) - { - throw new System.IO.IOException(string.Format( - "Failed to Copy File / Directory from '{0}' to '{1}': destination path already exists.", source, dest)); - } - - if (!MoveFileOrDirectoryInternal(source, dest)) - { - throw new System.IO.IOException(string.Format( - "Failed to Move File / Directory from '{0}' to '{1}'.", source, dest)); - } - } - - [FreeFunction("MoveFileOrDirectory")] - private static extern bool MoveFileOrDirectoryInternal(string source, string dest); - - private static void CheckForValidSourceAndDestinationArgumentsAndRaiseAnExceptionWhenNullOrEmpty(string source, string dest) - { - if (source == null) throw new ArgumentNullException("source"); - if (dest == null) throw new ArgumentNullException("dest"); - - if (source == string.Empty) throw new ArgumentException("source", "The source path cannot be empty."); - if (dest == string.Empty) throw new ArgumentException("dest", "The destination path cannot be empty."); - } - - // Returns a unique path in the Temp folder within your current project. - [FreeFunction] - public static extern string GetUniqueTempPathInProject(); - - [FreeFunction("GetActualPathSlow")] - internal static extern string GetActualPathName(string path); - - //*undocumented* - [FreeFunction] - public static extern string GetProjectRelativePath(string path); - - [FreeFunction] - internal static extern string GetLastPathNameComponent(string path); - - [FreeFunction] - internal static extern string DeleteLastPathNameComponent(string path); - - [FreeFunction("GetPathNameExtension")] - internal static extern string GetPathExtension(string path); - - [FreeFunction("DeletePathNameExtension")] - internal static extern string GetPathWithoutExtension(string path); - - [FreeFunction] - internal static extern string ResolveSymlinks(string path); - - [FreeFunction] - internal static extern bool IsSymlink(string path); - - // Replaces a file. - public static void ReplaceFile(string src, string dst) - { - if (File.Exists(dst)) - FileUtil.DeleteFileOrDirectory(dst); - - FileUtil.CopyFileOrDirectory(src, dst); - } - - // Replaces a directory. - public static void ReplaceDirectory(string src, string dst) - { - if (Directory.Exists(dst)) - FileUtil.DeleteFileOrDirectory(dst); - - FileUtil.CopyFileOrDirectory(src, dst); - } - } -} diff --git a/Editor/Mono/FileUtil.cs b/Editor/Mono/FileUtil.cs deleted file mode 100644 index 5222e33d7a..0000000000 --- a/Editor/Mono/FileUtil.cs +++ /dev/null @@ -1,318 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Text.RegularExpressions; -using UnityEngine; - -namespace UnityEditor -{ - public partial class FileUtil - { - internal static void ReplaceText(string path, params string[] input) - { - path = NiceWinPath(path); - string[] data = File.ReadAllLines(path); - - for (int i = 0; i < input.Length; i += 2) - { - for (int q = 0; q < data.Length; ++q) - { - data[q] = data[q].Replace(input[i], input[i + 1]); - } - } - - File.WriteAllLines(path, data); - } - - internal static bool ReplaceTextRegex(string path, params string[] input) - { - bool res = false; - path = NiceWinPath(path); - string[] data = File.ReadAllLines(path); - - for (int i = 0; i < input.Length; i += 2) - { - for (int q = 0; q < data.Length; ++q) - { - string s = data[q]; - data[q] = Regex.Replace(s, input[i], input[i + 1]); - - if (s != (string)data[q]) - res = true; - } - } - - File.WriteAllLines(path, data); - return res; - } - - internal static bool AppendTextAfter(string path, string find, string append) - { - bool res = false; - path = NiceWinPath(path); - var data = new List(File.ReadAllLines(path)); - - for (int q = 0; q < data.Count; ++q) - { - if (data[q].Contains(find)) - { - data.Insert(q + 1, append); - res = true; - break; - } - } - - File.WriteAllLines(path, data.ToArray()); - return res; - } - - internal static void CopyDirectoryRecursive(string source, string target) - { - CopyDirectoryRecursive(source, target, false, false); - } - - internal static void CopyDirectoryRecursiveIgnoreMeta(string source, string target) - { - CopyDirectoryRecursive(source, target, false, true); - } - - internal static void CopyDirectoryRecursive(string source, string target, bool overwrite) - { - CopyDirectoryRecursive(source, target, overwrite, false); - } - - internal static void CopyDirectory(string source, string target, bool overwrite) - { - CopyDirectoryFiltered(source, target, overwrite, f => true, false); - } - - internal static void CopyDirectoryRecursive(string source, string target, bool overwrite, bool ignoreMeta) - { - CopyDirectoryRecursiveFiltered(source, target, overwrite, ignoreMeta ? @"\.meta$" : null); - } - - internal static void CopyDirectoryRecursiveForPostprocess(string source, string target, bool overwrite) - { - CopyDirectoryRecursiveFiltered(source, target, overwrite, @".*/\.+|\.meta$"); - } - - internal static void CopyDirectoryRecursiveFiltered(string source, string target, bool overwrite, string regExExcludeFilter) - { - CopyDirectoryFiltered(source, target, overwrite, regExExcludeFilter, true); - } - - internal static void CopyDirectoryFiltered(string source, string target, bool overwrite, string regExExcludeFilter, bool recursive) - { - Regex exclude = null; - try - { - if (regExExcludeFilter != null) - exclude = new Regex(regExExcludeFilter); - } - catch (ArgumentException) - { - Debug.Log("CopyDirectoryRecursive: Pattern '" + regExExcludeFilter + "' is not a correct Regular Expression. Not excluding any files."); - return; - } - - Func includeCallback = file => (exclude == null || !exclude.IsMatch(file)); - - CopyDirectoryFiltered(source, target, overwrite, includeCallback, recursive); - } - - internal static void CopyDirectoryFiltered(string source, string target, bool overwrite, Func includeCallback, bool recursive) - { - // Check if the target directory exists, but dont create it yet until we know there are files to copy. - bool createDirectory = !Directory.Exists(target); - - // Copy each file into the new directory. - foreach (string fi in Directory.GetFiles(source)) - { - if (!includeCallback(fi)) - continue; - - if (createDirectory) - { - Directory.CreateDirectory(target); - overwrite = false; // no reason to perform this on subdirs - createDirectory = false; - } - - string fname = Path.GetFileName(fi); - string targetfname = Path.Combine(target, fname); - - UnityFileCopy(fi, targetfname, overwrite); - } - - if (!recursive) - return; - - // Copy each subdirectory recursively. - foreach (string di in Directory.GetDirectories(source)) - { - if (!includeCallback(di)) - continue; - - string fname = Path.GetFileName(di); - - CopyDirectoryFiltered(Path.Combine(source, fname), Path.Combine(target, fname), overwrite, includeCallback, recursive); - } - } - - internal static void UnityDirectoryDelete(string path) - { - UnityDirectoryDelete(path, false); - } - - internal static void UnityDirectoryDelete(string path, bool recursive) - { - Directory.Delete(NiceWinPath(path), recursive); - } - - // set the System.IO.FileAttributes.Normal recursively on all files in target_dir - internal static void UnityDirectoryRemoveReadonlyAttribute(string target_dir) - { - string[] files = Directory.GetFiles(target_dir); - string[] dirs = Directory.GetDirectories(target_dir); - - foreach (string file in files) - { - File.SetAttributes(file, System.IO.FileAttributes.Normal); - } - - foreach (string dir in dirs) - { - UnityDirectoryRemoveReadonlyAttribute(dir); - } - } - - internal static void MoveFileIfExists(string src, string dst) - { - if (File.Exists(src)) - { - DeleteFileOrDirectory(dst); - MoveFileOrDirectory(src, dst); - File.SetLastWriteTime(dst, DateTime.Now); - } - } - - internal static void CopyFileIfExists(string src, string dst, bool overwrite) - { - if (File.Exists(src)) - { - UnityFileCopy(src, dst, overwrite); - } - } - - internal static void UnityFileCopy(string from, string to, bool overwrite) - { - File.Copy(NiceWinPath(from), NiceWinPath(to), overwrite); - } - - internal static string NiceWinPath(string unityPath) - { - // IO functions do not like mixing of \ and / slashes, esp. for windows network paths (\\path) - return Application.platform == RuntimePlatform.WindowsEditor ? unityPath.Replace("/", @"\") : unityPath; - } - - internal static string UnityGetFileNameWithoutExtension(string path) - { - // this is because on Windows \\ means network path, in unity all \ are converted to / - // network paths become // and Path class functions think it's the same as / - return Path.GetFileNameWithoutExtension(path.Replace("//", @"\\")).Replace(@"\\", "//"); - } - - internal static string UnityGetFileName(string path) - { - // this is because on Windows \\ means network path, in unity all \ are converted to / - // network paths become // and Path class functions think it's the same as / - return Path.GetFileName(path.Replace("//", @"\\")).Replace(@"\\", "//"); - } - - internal static string UnityGetDirectoryName(string path) - { - // this is because on Windows \\ means network path, in unity all \ are converted to / - // network paths become // and Path class functions think it's the same as / - return Path.GetDirectoryName(path.Replace("//", @"\\")).Replace(@"\\", "//"); - } - - internal static void UnityFileCopy(string from, string to) - { - UnityFileCopy(from, to, false); - } - - internal static void CreateOrCleanDirectory(string dir) - { - if (Directory.Exists(dir)) - Directory.Delete(dir, true); - Directory.CreateDirectory(dir); - } - - internal static string RemovePathPrefix(string fullPath, string prefix) - { - var partsOfFull = fullPath.Split(Path.DirectorySeparatorChar); - var partsOfPrefix = prefix.Split(Path.DirectorySeparatorChar); - int index = 0; - - if (partsOfFull[0] == string.Empty) - index = 1; - - while (index < partsOfFull.Length - && index < partsOfPrefix.Length - && partsOfFull[index] == partsOfPrefix[index]) - ++index; - - if (index == partsOfFull.Length) - return ""; - - return string.Join(Path.DirectorySeparatorChar.ToString(), - partsOfFull, index, partsOfFull.Length - index); - } - - internal static string CombinePaths(params string[] paths) - { - if (null == paths) - return string.Empty; - return string.Join(Path.DirectorySeparatorChar.ToString(), paths); - } - - internal static List GetAllFilesRecursive(string path) - { - List files = new List(); - WalkFilesystemRecursively(path, - (p) => { files.Add(p); }, - (p) => { return true; }); - return files; - } - - internal static void WalkFilesystemRecursively(string path, - Action fileCallback, - Func directoryCallback) - { - foreach (string file in Directory.GetFiles(path)) - fileCallback(file); - foreach (string subdir in Directory.GetDirectories(path)) - { - if (directoryCallback(subdir)) - WalkFilesystemRecursively(subdir, fileCallback, directoryCallback); - } - } - - internal static long GetDirectorySize(string path) - { - var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories); - long filesSize = 0; - foreach (var file in files) - { - var info = new FileInfo(file); - filesSize += info.Length; - } - return filesSize; - } - } -} diff --git a/Editor/Mono/FlagSet.cs b/Editor/Mono/FlagSet.cs deleted file mode 100644 index 94294ffb9c..0000000000 --- a/Editor/Mono/FlagSet.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor -{ - // Holds a flag set. Can be used with enum flags. - // Has semantic value in separating a single value of an enum versus the flag set - [Serializable] - internal struct FlagSet where T : IConvertible - { - private ulong m_Flags; - - public bool HasFlags(T flags) - { - return (m_Flags & Convert.ToUInt64(flags)) != 0; - } - - public void SetFlags(T flags, bool value) - { - if (value) - m_Flags |= Convert.ToUInt64(flags); - else - m_Flags &= ~Convert.ToUInt64(flags); - } - - public FlagSet(T flags) - { - m_Flags = Convert.ToUInt64(flags); - } - - public static implicit operator FlagSet(T flags) {return new FlagSet(flags); } - } -} diff --git a/Editor/Mono/GI/LightmapEditorSettingsDeprecated.cs b/Editor/Mono/GI/LightmapEditorSettingsDeprecated.cs deleted file mode 100644 index 80a4a367c8..0000000000 --- a/Editor/Mono/GI/LightmapEditorSettingsDeprecated.cs +++ /dev/null @@ -1,197 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngineInternal; - -namespace UnityEditor -{ - [System.Obsolete("LightmapBakeQuality has been deprecated.", false)] - public enum LightmapBakeQuality - { - High = 0, - Low = 1, - } - - public partial class LightmapEditorSettings - { - [System.Obsolete("LightmapEditorSettings.aoContrast has been deprecated.", false)] - public static float aoContrast - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.aoAmount has been deprecated.", false)] - public static float aoAmount - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.lockAtlas has been deprecated.", false)] - public static bool lockAtlas - { - get { return false; } - set {} - } - [System.Obsolete("LightmapEditorSettings.skyLightColor has been deprecated.", false)] - public static Color skyLightColor - { - get { return Color.black; } - set {} - } - [System.Obsolete("LightmapEditorSettings.skyLightIntensity has been deprecated.", false)] - public static float skyLightIntensity - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.quality has been deprecated.", false)] - public static LightmapBakeQuality quality - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.bounceBoost has been deprecated.", false)] - public static float bounceBoost - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.finalGatherRays has been deprecated.", false)] - public static int finalGatherRays - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.finalGatherContrastThreshold has been deprecated.", false)] - public static float finalGatherContrastThreshold - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.finalGatherGradientThreshold has been deprecated.", false)] - public static float finalGatherGradientThreshold - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.finalGatherInterpolationPoints has been deprecated.", false)] - public static int finalGatherInterpolationPoints - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.lastUsedResolution has been deprecated.", false)] - public static float lastUsedResolution - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.bounces has been deprecated.", false)] - public static int bounces - { - get { return 0; } - set {} - } - [System.Obsolete("LightmapEditorSettings.bounceIntensity has been deprecated.", false)] - public static float bounceIntensity - { - get { return 0; } - set {} - } - [System.Obsolete("resolution is now called realtimeResolution (UnityUpgradable) -> realtimeResolution", false)] - public static float resolution - { - get { return realtimeResolution; } - set { realtimeResolution = value; } - } - [System.Obsolete("GIBakeBackend has been renamed to Lightmapper. (UnityUpgradable)", true)] - public enum GIBakeBackend - { - Radiosity = 0, - PathTracer = 1 - } - [System.Obsolete("The giBakeBackend property has been renamed to lightmapper. (UnityUpgradable) -> lightmapper", false)] - public static GIBakeBackend giBakeBackend - { - get - { - if (lightmapper == Lightmapper.ProgressiveCPU) - return GIBakeBackend.PathTracer; - else - return GIBakeBackend.Radiosity; - } - set - { - if (value == GIBakeBackend.PathTracer) - lightmapper = Lightmapper.ProgressiveCPU; - else - lightmapper = Lightmapper.Enlighten; - } - } - [System.Obsolete("PathTracerSampling has been renamed to Sampling. (UnityUpgradable) -> UnityEditor.LightmapEditorSettings/Sampling", false)] - public enum PathTracerSampling - { - Auto = 0, - Fixed = 1 - } - [System.Obsolete("The giPathTracerSampling property has been renamed to sampling. (UnityUpgradable) -> sampling", false)] - public static PathTracerSampling giPathTracerSampling - { - get - { - if (sampling == Sampling.Auto) - return PathTracerSampling.Auto; - else - return PathTracerSampling.Fixed; - } - set - { - if (value == PathTracerSampling.Auto) - sampling = Sampling.Auto; - else - sampling = Sampling.Fixed; - } - } - [System.Obsolete("PathTracerFilter has been renamed to FilterType. (UnityUpgradable) -> UnityEditor.LightmapEditorSettings/FilterType", false)] - public enum PathTracerFilter - { - Gaussian = 0, - ATrous = 1 - } - [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.")] - public static PathTracerFilter giPathTracerFilter - { - get - { - if (LightmapEditorSettings.filterTypeDirect == FilterType.Gaussian) - return PathTracerFilter.Gaussian; - else - return PathTracerFilter.ATrous; - } - set - { - LightmapEditorSettings.filterTypeDirect = FilterType.Gaussian; - LightmapEditorSettings.filterTypeIndirect = FilterType.Gaussian; - LightmapEditorSettings.filterTypeAO = FilterType.Gaussian; - } - } - - [System.Obsolete("LightmapEditorSettings.maxAtlasWidth is now called maxAtlasSize (UnityUpgradable) -> maxAtlasSize", false)] - public static int maxAtlasWidth - { - get { return maxAtlasSize; } - set { maxAtlasSize = value; } - } - - private static int m_MaxAtlasHeight = 1024; - - [System.Obsolete("LightmapEditorSettings.maxAtlasHeight has been deprecated. Only square atlases are supported, please use the maxAtlasSize instead. ")] - public static int maxAtlasHeight - { - get { return m_MaxAtlasHeight; } - set { m_MaxAtlasHeight = value; } - } - } -} diff --git a/Editor/Mono/GI/LightmapSnapshot.deprecated.cs b/Editor/Mono/GI/LightmapSnapshot.deprecated.cs deleted file mode 100644 index 91990a6f73..0000000000 --- a/Editor/Mono/GI/LightmapSnapshot.deprecated.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -namespace UnityEditor -{ - //Originally class was defined in Lightmapping.bindings - [System.Obsolete("LightmapSnapshot has been deprecated. Use LightingDataAsset instead (UnityUpgradable) -> LightingDataAsset", true)] - [UnityEngine.NativeClass(null)] - public class LightmapSnapshot : UnityEngine.Object // No **partial** needed since it is a **type** rename - { - //Original class had no public members - } -} - diff --git a/Editor/Mono/GI/Lightmapping.deprecated.cs b/Editor/Mono/GI/Lightmapping.deprecated.cs deleted file mode 100644 index a68547da5b..0000000000 --- a/Editor/Mono/GI/Lightmapping.deprecated.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; -using UnityEngineInternal; - -namespace UnityEditor -{ - public partial class Lightmapping - { - [System.Obsolete("lightmapSnapshot has been deprecated. Use lightingDataAsset instead (UnityUpgradable) -> lightingDataAsset", true)] - public static LightmapSnapshot lightmapSnapshot - { - get { return null; } - set {} - } - - [System.Obsolete("BakeSelectedAsync has been deprecated. Use BakeAsync instead (UnityUpgradable) -> BakeAsync()", true)] - public static bool BakeSelectedAsync() { return false; } - - [System.Obsolete("BakeSelected has been deprecated. Use Bake instead (UnityUpgradable) -> Bake()", true)] - public static bool BakeSelected() { return false; } - - [System.Obsolete("BakeLightProbesOnlyAsync has been deprecated. Use BakeAsync instead (UnityUpgradable) -> BakeAsync()", true)] - public static bool BakeLightProbesOnlyAsync() { return false; } - - [System.Obsolete("BakeLightProbesOnly has been deprecated. Use Bake instead (UnityUpgradable) -> Bake()", true)] - public static bool BakeLightProbesOnly() { return false; } - } -} - diff --git a/Editor/Mono/GUI/AboutWindow.cs b/Editor/Mono/GUI/AboutWindow.cs deleted file mode 100644 index 5da2b1f9ce..0000000000 --- a/Editor/Mono/GUI/AboutWindow.cs +++ /dev/null @@ -1,258 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEditor; -using UnityEditor.VisualStudioIntegration; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class AboutWindow : EditorWindow - { - static void ShowAboutWindow() - { - AboutWindow w = EditorWindow.GetWindowWithRect(new Rect(100, 100, 570, 340), true, "About Unity"); - w.position = new Rect(100, 100, 570, 340); - w.m_Parent.window.m_DontSaveToLayout = true; - - AboutWindowNames.ParseCredits(); - } - - private static GUIContent s_MonoLogo, s_AgeiaLogo, s_Header; - - private const string kSpecialThanksNames = "Thanks to Forest 'Yoggy' Johnson, Graham McAllister, David Janik-Jones, Raimund Schumacher, Alan J. Dickins and Emil 'Humus' Persson"; - - private static void LoadLogos() - { - if (s_MonoLogo != null) - return; - s_MonoLogo = EditorGUIUtility.IconContent("MonoLogo"); - s_AgeiaLogo = EditorGUIUtility.IconContent("AgeiaLogo"); - s_Header = EditorGUIUtility.IconContent("AboutWindow.MainHeader"); - } - - public void OnEnable() - { - EditorApplication.update += UpdateScroll; - m_LastScrollUpdate = EditorApplication.timeSinceStartup; - } - - public void OnDisable() - { - EditorApplication.update -= UpdateScroll; - } - - float m_TextYPos = 120; - float m_TextInitialYPos = 120; - float m_TotalCreditsHeight = Mathf.Infinity; - - double m_LastScrollUpdate = 0.0f; - - public void UpdateScroll() - { - double deltaTime = EditorApplication.timeSinceStartup - m_LastScrollUpdate; - m_LastScrollUpdate = EditorApplication.timeSinceStartup; - - if (GUIUtility.hotControl != 0) - return; - - m_TextYPos -= 40f * (float)deltaTime; - if (m_TextYPos < -m_TotalCreditsHeight) - m_TextYPos = m_TextInitialYPos; - Repaint(); - } - - bool m_ShowDetailedVersion = false; - public void OnGUI() - { - LoadLogos(); - GUILayout.Space(10); - GUILayout.BeginHorizontal(); - GUILayout.Space(5); - GUILayout.BeginVertical(); - GUILayout.FlexibleSpace(); - GUILayout.Label(s_Header, GUIStyle.none); - - ListenForSecretCodes(); - - var licenseTypeString = ""; - if (InternalEditorUtility.HasFreeLicense()) - licenseTypeString = " Personal"; - if (InternalEditorUtility.HasEduLicense()) - licenseTypeString = " Edu"; - - GUILayout.BeginHorizontal(); - GUILayout.Space(52f); // Ident version information - - string extensionVersion = FormatExtensionVersionString(); - - m_ShowDetailedVersion |= Event.current.alt; - if (m_ShowDetailedVersion) - { - int t = InternalEditorUtility.GetUnityVersionDate(); - DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0); - string branch = InternalEditorUtility.GetUnityBuildBranch(); - string branchString = ""; - if (branch.Length > 0) - { - branchString = "Branch: " + branch; - } - EditorGUILayout.SelectableLabel( - string.Format("Version {0}{1}{2}\n{3:r}\n{4}", InternalEditorUtility.GetFullUnityVersion(), licenseTypeString, extensionVersion, dt.AddSeconds(t), branchString), - GUILayout.Width(550), GUILayout.Height(42)); - - m_TextInitialYPos = 120 - 12; - } - else - { - GUILayout.Label(string.Format("Version {0}{1}{2}", Application.unityVersion, licenseTypeString, extensionVersion)); - } - - if (Event.current.type == EventType.ValidateCommand) - return; - - GUILayout.EndHorizontal(); - GUILayout.Space(4); - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - - GUILayout.FlexibleSpace(); - - float creditsWidth = position.width - 10; - float chunkOffset = m_TextYPos; - - Rect scrollAreaRect = GUILayoutUtility.GetRect(10, m_TextInitialYPos); - GUI.BeginGroup(scrollAreaRect); - foreach (string nameChunk in AboutWindowNames.Names(null, true)) - chunkOffset = DoCreditsNameChunk(nameChunk, creditsWidth, chunkOffset); - chunkOffset = DoCreditsNameChunk(kSpecialThanksNames, creditsWidth, chunkOffset); - m_TotalCreditsHeight = chunkOffset - m_TextYPos; - GUI.EndGroup(); - - HandleScrollEvents(scrollAreaRect); - - GUILayout.FlexibleSpace(); - - GUILayout.BeginHorizontal(); - GUILayout.Label(s_MonoLogo); - GUILayout.Label("Scripting powered by The Mono Project.\n\n(c) 2011 Novell, Inc.", "MiniLabel", GUILayout.Width(200)); - GUILayout.Label(s_AgeiaLogo); - GUILayout.Label("Physics powered by PhysX.\n\n(c) 2011 NVIDIA Corporation.", "MiniLabel", GUILayout.Width(200)); - GUILayout.EndHorizontal(); - GUILayout.FlexibleSpace(); - GUILayout.BeginHorizontal(); - GUILayout.Space(5); - GUILayout.BeginVertical(); - GUILayout.FlexibleSpace(); - - var VSTUlabel = UnityVSSupport.GetAboutWindowLabel(); - if (VSTUlabel.Length > 0) - GUILayout.Label(VSTUlabel, "MiniLabel"); - GUILayout.Label(InternalEditorUtility.GetUnityCopyright(), "MiniLabel"); - GUILayout.EndVertical(); - GUILayout.Space(10); - GUILayout.FlexibleSpace(); - GUILayout.BeginVertical(); - GUILayout.FlexibleSpace(); - GUILayout.Label(InternalEditorUtility.GetLicenseInfo(), "AboutWindowLicenseLabel"); - GUILayout.EndVertical(); - GUILayout.Space(5); - GUILayout.EndHorizontal(); - - GUILayout.Space(5); - } - - private void HandleScrollEvents(Rect scrollAreaRect) - { - int id = GUIUtility.GetControlID(FocusType.Passive); - - switch (Event.current.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (scrollAreaRect.Contains(Event.current.mousePosition)) - { - GUIUtility.hotControl = id; - Event.current.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - m_TextYPos += Event.current.delta.y; - m_TextYPos = Mathf.Min(m_TextYPos, m_TextInitialYPos); - m_TextYPos = Mathf.Max(m_TextYPos, -m_TotalCreditsHeight); - Event.current.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - Event.current.Use(); - } - break; - } - } - - private static float DoCreditsNameChunk(string nameChunk, float creditsWidth, float creditsChunkYOffset) - { - float creditsNamesHeight = EditorStyles.wordWrappedLabel.CalcHeight(GUIContent.Temp(nameChunk), creditsWidth); - Rect creditsNamesRect = new Rect(5, creditsChunkYOffset, creditsWidth, creditsNamesHeight); - GUI.Label(creditsNamesRect, nameChunk, EditorStyles.wordWrappedLabel); - return creditsNamesRect.yMax; - } - - private int m_InternalCodeProgress; - private void ListenForSecretCodes() - { - if (Event.current.type != EventType.KeyDown || (int)Event.current.character == 0) - return; - - if (SecretCodeHasBeenTyped("internal", ref m_InternalCodeProgress)) - { - bool enabled = !EditorPrefs.GetBool("DeveloperMode", false); - EditorPrefs.SetBool("DeveloperMode", enabled); - ShowNotification(new GUIContent("Developer Mode " + (enabled ? "On" : "Off"))); - InternalEditorUtility.RequestScriptReload(); - - // Repaint all views to show/hide debug repaint indicator - InternalEditorUtility.RepaintAllViews(); - } - } - - private bool SecretCodeHasBeenTyped(string code, ref int characterProgress) - { - if (characterProgress < 0 || characterProgress >= code.Length || code[characterProgress] != Event.current.character) - characterProgress = 0; - - // Don't use else here. Even if key was mismatch, it should still be recognized as first key of sequence if it matches. - if (code[characterProgress] == Event.current.character) - { - characterProgress++; - - if (characterProgress >= code.Length) - { - characterProgress = 0; - return true; - } - } - return false; - } - - private string FormatExtensionVersionString() - { - string extStr = EditorUserBuildSettings.selectedBuildTargetGroup.ToString(); - string ext = Modules.ModuleManager.GetExtensionVersion(extStr); - - if (!string.IsNullOrEmpty(ext)) - return " [" + extStr + ": " + ext + "]"; - - return ""; - } - } -} // namespace diff --git a/Editor/Mono/GUI/AboutWindowNames.cs b/Editor/Mono/GUI/AboutWindowNames.cs deleted file mode 100644 index 8d564c9f5c..0000000000 --- a/Editor/Mono/GUI/AboutWindowNames.cs +++ /dev/null @@ -1,157 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using UnityEditor; - -namespace UnityEditor -{ - static class AboutWindowNames - { - const int kChunkSize = 100; - - private static string s_Country = null; - private static string[] s_CachedNames = {}; - - // private static Dictionary s_flags = new Dictionary() { - // { "DK", "��" }, - // { "LT", "��" }, - // { "PT", "��" }, - // { "US", "��" } - // }; - - public class CreditEntry - { -#pragma warning disable 649 - public string name; - // Store diacritic free name for easing search - public string normalizedName; - public string country_code; - public string office; - public string region; - public string twitter; - public string nationality; - public string gravatar_hash; - public bool alumni; - - public string FormattedName - { - get - { - var formatted = name; - - // Emoji flags don't work yet - // if (!String.IsNullOrEmpty(nationality) && s_flags.ContainsKey(nationality)) - // formatted += " " + s_flags[nationality]; - - if (!String.IsNullOrEmpty(twitter)) - formatted += " ( @" + twitter + " )"; - return formatted; - } - } - } - - public static List s_Credits = new List(); - - private static string CreditsFilePath - { - get - { - return Path.Combine( - EditorApplication.applicationContentsPath, - "Resources/credits.csv" - ); - } - } - - public static string RemoveDiacritics(string text) - { - string formD = text.Normalize(NormalizationForm.FormD); - StringBuilder sb = new StringBuilder(); - - foreach (char ch in formD) - { - UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(ch); - if (uc != UnicodeCategory.NonSpacingMark) - { - sb.Append(ch); - } - } - - return sb.ToString().Normalize(NormalizationForm.FormC); - } - - public static void ParseCredits() - { - using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("credits.csv")) - { - using (var reader = new StreamReader(stream)) - { - string line; - do - { - line = reader.ReadLine(); - if (line != null) - { - if (line.Length > 0) - { - string[] entry = line.Split(','); - CreditEntry c = new CreditEntry() { - name = entry[0], - normalizedName = RemoveDiacritics(entry[0]), - alumni = (entry[1] == "1"), - country_code = entry[2], - region = (entry[3]), - twitter = entry[4], - }; - s_Credits.Add(c); - } - } - } - while (line != null); - } - } - } - - // TODO: Proper choice is pagination, and page size choice - public static string[] Names(string country_filter = null, bool chunked = false) - { - if ((s_Country == country_filter) - && (s_CachedNames.Length > 0)) - { - // TODO: Honor chunking - return s_CachedNames; - } - s_Country = country_filter; - List newNames = new List(); - - foreach (var entry in s_Credits) - { - if (String.IsNullOrEmpty(country_filter) || (entry.country_code == country_filter)) - { - newNames.Add(entry.FormattedName); - } - } - if (!chunked) - { - s_CachedNames = newNames.ToArray(); - } - else - { - string[] nameChunks = new string[newNames.Count / kChunkSize + 1]; - - for (int i = 0; i * kChunkSize < newNames.Count; i++) - nameChunks[i] = string.Join(", ", newNames.Skip(i * kChunkSize).Take(kChunkSize).ToArray()); - s_CachedNames = nameChunks.ToArray(); - } - return s_CachedNames; - } - } -} diff --git a/Editor/Mono/GUI/AngularDial.cs b/Editor/Mono/GUI/AngularDial.cs deleted file mode 100644 index 2de6769fbc..0000000000 --- a/Editor/Mono/GUI/AngularDial.cs +++ /dev/null @@ -1,121 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class EditorGUILayout - { - internal static float AngularDial( - GUIContent label, float angle, Texture thumbTexture, GUIStyle background, GUIStyle thumb, - params GUILayoutOption[] options - ) - { - var hasLabel = label != null && label != GUIContent.none; - var height = background == null || background.fixedHeight == 0 ? - EditorGUIUtility.singleLineHeight : background.fixedHeight; - var minWidth = (hasLabel ? EditorGUIUtility.labelWidth : 0f) - + (background != null ? background.fixedWidth : 0f); - var maxWidth = kLabelFloatMaxW; - var rect = GUILayoutUtility.GetRect(minWidth, maxWidth, height, height, background, options); - s_LastRect = rect; - return EditorGUI.AngularDial(rect, label, angle, thumbTexture, background, thumb); - } - } - - public sealed partial class EditorGUI - { - internal static float AngularDial( - Rect rect, GUIContent label, float angle, Texture thumbTexture, GUIStyle background, GUIStyle thumb - ) - { - var id = GUIUtility.GetControlID(FocusType.Passive); - var evt = Event.current; - - if (label != null && label != GUIContent.none) - rect = PrefixLabel(rect, id, label); - - var diameter = Mathf.Min(rect.width, rect.height); - var thumbDimensions = thumb == null || thumb == GUIStyle.none - ? Vector2.zero - : thumb.CalcSize(GUIContent.Temp(thumbTexture)); - var thumbSize = Mathf.Max(thumbDimensions.x, thumbDimensions.y); - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (rect.Contains(evt.mousePosition)) - { - var p = evt.mousePosition - rect.center; - var r = Mathf.Sqrt(p.x * p.x + p.y * p.y); - if (r < diameter * 0.5f && r > diameter * 0.5f - thumbSize) - return UseAngularDialEventAndGetAngle(id, evt, rect.center, angle); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - return UseAngularDialEventAndGetAngle(id, evt, rect.center, angle); - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - return UseAngularDialEventAndGetAngle(id, evt, rect.center, angle); - } - break; - case EventType.Repaint: - var hover = false; - if (rect.Contains(evt.mousePosition)) - { - var p = evt.mousePosition - rect.center; - var r = Mathf.Sqrt(p.x * p.x + p.y * p.y); - hover = r diameter * 0.5f - thumbSize; - } - var active = GUIUtility.hotControl == id; - - if (background != null && background != GUIStyle.none) - background.Draw(rect, hover, active, false, false); - - if (thumb != null && thumb != GUIStyle.none) - { - var thumbCenterRadius = diameter * 0.5f - thumbSize * 0.5f; - // negate angle since gui space goes top to bottom - var radians = -Mathf.Deg2Rad * angle; - var thumbCenter = - new Vector2(Mathf.Cos(radians), Mathf.Sin(radians)) * thumbCenterRadius + rect.center; - var size = thumb.CalcSize(GUIContent.none); - if (thumb.fixedWidth == 0f) - size.x = Mathf.Max(size.x, thumbSize); - if (thumb.fixedHeight == 0f) - size.y = Mathf.Max(size.y, thumbSize); - var thumbRect = new Rect { size = size, center = thumbCenter }; - thumbRect.center = thumbCenter; - - thumb.Draw(thumbRect, thumbTexture, thumbRect.Contains(evt.mousePosition), active, false, false); - } - break; - } - - return angle; - } - - private static float UseAngularDialEventAndGetAngle(int id, Event evt, Vector2 center, float angle) - { - GUIUtility.hotControl = evt.type == EventType.MouseUp ? 0 : id; - EditorGUIUtility.keyboardControl = 0; - GUI.changed = true; - evt.Use(); - - var normalized = (evt.mousePosition - center).normalized; - // negate angle since gui space goes top to bottom - var newAngle = -Mathf.Rad2Deg - * Mathf.Acos(normalized.x) - * Mathf.Sign(Vector2.Dot(Vector2.up, normalized)); - - // accumulate delta angle to allow for multiple revolutions - return angle + Mathf.DeltaAngle(angle, newAngle); - } - } -} diff --git a/Editor/Mono/GUI/AnimatedValues.cs b/Editor/Mono/GUI/AnimatedValues.cs deleted file mode 100644 index 2fb0b2d990..0000000000 --- a/Editor/Mono/GUI/AnimatedValues.cs +++ /dev/null @@ -1,259 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Events; - -namespace UnityEditor.AnimatedValues -{ - public abstract class BaseAnimValue - { - private T m_Start; - - [SerializeField] - private T m_Target; - - private double m_LastTime; - private double m_LerpPosition = 1f; - - public float speed = 2f; - - [NonSerialized] - public UnityEvent valueChanged; - - private bool m_Animating; - - protected BaseAnimValue(T value) - { - m_Start = value; - m_Target = value; - valueChanged = new UnityEvent(); - } - - protected BaseAnimValue(T value, UnityAction callback) - { - m_Start = value; - m_Target = value; - valueChanged = new UnityEvent(); - valueChanged.AddListener(callback); - } - - private static T2 Clamp(T2 val, T2 min, T2 max) where T2 : IComparable - { - if (val.CompareTo(min) < 0) return min; - if (val.CompareTo(max) > 0) return max; - return val; - } - - protected void BeginAnimating(T newTarget, T newStart) - { - m_Start = newStart; - m_Target = newTarget; - - EditorApplication.update += Update; - m_Animating = true; - m_LastTime = EditorApplication.timeSinceStartup; - m_LerpPosition = 0; - } - - public bool isAnimating - { - get { return m_Animating; } - } - - private void Update() - { - if (!m_Animating) - return; - - // update the lerpPosition - UpdateLerpPosition(); - - if (valueChanged != null) - valueChanged.Invoke(); - - if (lerpPosition >= 1f) - { - m_Animating = false; - EditorApplication.update -= Update; - } - } - - protected float lerpPosition - { - get - { - var v = 1.0 - m_LerpPosition; - var result = 1.0 - v * v * v * v; - return (float)result; - } - } - - private void UpdateLerpPosition() - { - double nowTime = EditorApplication.timeSinceStartup; - double deltaTime = nowTime - m_LastTime; - - m_LerpPosition = Clamp(m_LerpPosition + (deltaTime * speed), 0.0, 1.0); - m_LastTime = nowTime; - } - - protected void StopAnim(T newValue) - { - // If the new value is different, or we might be in the middle of a fade, we need to refresh. - // Checking GetValue is not reliable on its own, since for e.g. bool it'll return the "closest" value, - // but that doesn't mean the fade is done. - bool invoke = false; - if ((!newValue.Equals(GetValue()) || m_LerpPosition < 1) && valueChanged != null) - invoke = true; - - m_Target = newValue; - m_Start = newValue; - m_LerpPosition = 1; - m_Animating = false; - // Only refresh *after* we set the correct new value. - if (invoke) - valueChanged.Invoke(); - } - - protected T start - { - get { return m_Start; } - } - - public T target - { - get { return m_Target; } - set - { - if (!m_Target.Equals(value)) - BeginAnimating(value, this.value); - } - } - - public T value - { - get { return GetValue(); } - set { StopAnim(value); } - } - - protected abstract T GetValue(); - } - - [Serializable] - public class AnimFloat : BaseAnimValue - { - [SerializeField] - private float m_Value; - - public AnimFloat(float value) - : base(value) - {} - - public AnimFloat(float value, UnityAction callback) : base(value, callback) - {} - - protected override float GetValue() - { - m_Value = Mathf.Lerp(start, target, lerpPosition); - return m_Value; - } - } - - [Serializable] - public class AnimVector3 : BaseAnimValue - { - [SerializeField] - private Vector3 m_Value; - - public AnimVector3() - : base(Vector3.zero) - {} - - public AnimVector3(Vector3 value) - : base(value) - {} - - public AnimVector3(Vector3 value, UnityAction callback) - : base(value, callback) - {} - - protected override Vector3 GetValue() - { - m_Value = Vector3.Lerp(start, target, lerpPosition); - return m_Value; - } - } - - [Serializable] - public class AnimBool : BaseAnimValue - { - [SerializeField] - private float m_Value; - - public AnimBool() - : base(false) - {} - - public AnimBool(bool value) - : base(value) - {} - - public AnimBool(UnityAction callback) - : base(false, callback) - {} - - public AnimBool(bool value, UnityAction callback) - : base(value, callback) - {} - - public float faded - { - get - { - GetValue(); - return m_Value; - } - } - - protected override bool GetValue() - { - float startVal = target ? 0f : 1f; - float end = 1f - startVal; - - m_Value = Mathf.Lerp(startVal, end, lerpPosition); - - return m_Value > .5f; - } - - public float Fade(float from, float to) - { - return Mathf.Lerp(from, to, faded); - } - } - - [Serializable] - public class AnimQuaternion : BaseAnimValue - { - [SerializeField] - private Quaternion m_Value; - - - public AnimQuaternion(Quaternion value) - : base(value) - {} - - public AnimQuaternion(Quaternion value, UnityAction callback) - : base(value, callback) - {} - - protected override Quaternion GetValue() - { - m_Value = Quaternion.Slerp(start, target, lerpPosition); - return m_Value; - } - } -} -//namespace diff --git a/Editor/Mono/GUI/AppStatusBar.cs b/Editor/Mono/GUI/AppStatusBar.cs deleted file mode 100644 index 04d30d34f1..0000000000 --- a/Editor/Mono/GUI/AppStatusBar.cs +++ /dev/null @@ -1,136 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEngine.Scripting; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor -{ - internal class AppStatusBar : GUIView - { - static AppStatusBar s_AppStatusBar; - static GUIContent[] s_StatusWheel; - string m_LastMiniMemoryOverview = ""; - - protected override void OnEnable() - { - base.OnEnable(); - // Disable clipping on the root element to fix case 931831 - visualTree.clippingOptions = VisualElement.ClippingOptions.NoClipping; - s_AppStatusBar = this; - s_StatusWheel = new GUIContent[12]; - for (int i = 0; i < 12; i++) - s_StatusWheel[i] = EditorGUIUtility.IconContent("WaitSpin" + i.ToString("00")); - } - - [RequiredByNativeCode] - public static void StatusChanged() - { - if (s_AppStatusBar) - s_AppStatusBar.Repaint(); - } - - void OnInspectorUpdate() - { - string miniOverview = UnityEditorInternal.ProfilerDriver.miniMemoryOverview; - if (Unsupported.IsDeveloperMode() && m_LastMiniMemoryOverview != miniOverview) - { - m_LastMiniMemoryOverview = miniOverview; - Repaint(); - } - } - - static GUIStyle background; - - protected override void OldOnGUI() - { - ConsoleWindow.LoadIcons(); - if (background == null) - background = "AppToolbar"; - - if (EditorApplication.isPlayingOrWillChangePlaymode) - GUI.color = HostView.kPlayModeDarken; - - if (Event.current.type == EventType.Repaint) - background.Draw(new Rect(0, 0, position.width, position.height), false, false, false, false); - - bool compiling = EditorApplication.isCompiling; - - GUILayout.Space(2); - GUILayout.BeginHorizontal(); - GUILayout.Space(2); - - string statusText = LogEntries.GetStatusText(); - if (statusText != null) - { - // Render - int mask = LogEntries.GetStatusMask(); - GUIStyle errorStyle = ConsoleWindow.GetStatusStyleForErrorMode(mask); - - GUILayout.Label(ConsoleWindow.GetIconForErrorMode(mask, false), errorStyle); - - GUILayout.Space(2); - GUILayout.BeginVertical(); - GUILayout.Space(2); - - if (compiling) //leave space for indicator - GUILayout.Label(statusText, errorStyle, GUILayout.MaxWidth(GUIView.current.position.width - 52)); - else - GUILayout.Label(statusText, errorStyle); - GUILayout.FlexibleSpace(); - - GUILayout.EndVertical(); - - // Handle status bar click - if (Event.current.type == EventType.MouseDown) - { - Event.current.Use(); - LogEntries.ClickStatusBar(Event.current.clickCount); - GUIUtility.ExitGUI(); - } - } - - GUILayout.EndHorizontal(); - - if (Event.current.type == EventType.Repaint) - { - const float statusWheelWidth = 24; - const float progressBarStatusWheelSpacing = 3; - - float progressBarHorizontalPosition = position.width - statusWheelWidth; - if (AsyncProgressBar.isShowing) - { - const int progressBarWidth = 185; - progressBarHorizontalPosition -= progressBarWidth + progressBarStatusWheelSpacing; - EditorGUI.ProgressBar(new Rect(progressBarHorizontalPosition, 0, progressBarWidth, 19), AsyncProgressBar.progress, AsyncProgressBar.progressInfo); - } - - if (compiling) - { - int frame = (int)Mathf.Repeat(Time.realtimeSinceStartup * 10, 11.99f); - GUI.Label(new Rect(position.width - statusWheelWidth, 0, s_StatusWheel[frame].image.width, s_StatusWheel[frame].image.height), s_StatusWheel[frame], GUIStyle.none); - } - - if (Unsupported.IsBleedingEdgeBuild()) - { - var backup = GUI.color; - GUI.color = Color.yellow; - GUI.Label(new Rect(progressBarHorizontalPosition - 310, 0, 310, 19), "THIS IS AN UNTESTED BLEEDINGEDGE UNITY BUILD"); - GUI.color = backup; - } - else if (Unsupported.IsDeveloperMode()) - { - GUI.Label(new Rect(progressBarHorizontalPosition - 200, 0, 200, 19), m_LastMiniMemoryOverview, EditorStyles.progressBarText); - EditorGUIUtility.CleanCache(m_LastMiniMemoryOverview); - } - } - - DoWindowDecorationEnd(); - - EditorGUI.ShowRepaints(); - } - } -} //namespace diff --git a/Editor/Mono/GUI/AssetPopupBackend.cs b/Editor/Mono/GUI/AssetPopupBackend.cs deleted file mode 100644 index d3041c4691..0000000000 --- a/Editor/Mono/GUI/AssetPopupBackend.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AssetPopupBackend - { - public static void AssetPopup(SerializedProperty serializedProperty, GUIContent label, string fileExtension, string defaultFieldName) where T : Object, new() - { - bool orignalShowMixedValue = EditorGUI.showMixedValue; - EditorGUI.showMixedValue = serializedProperty.hasMultipleDifferentValues; - - var typeName = serializedProperty.objectReferenceTypeString; - GUIContent buttonContent; - if (serializedProperty.hasMultipleDifferentValues) - buttonContent = EditorGUI.mixedValueContent; - else if (serializedProperty.objectReferenceValue != null) - buttonContent = GUIContent.Temp(serializedProperty.objectReferenceStringValue); - else - buttonContent = GUIContent.Temp(defaultFieldName); - - Rect buttonRect; - if (AudioMixerEffectGUI.PopupButton(label, buttonContent, EditorStyles.popup, out buttonRect)) // move & rename PopupButton.. - ShowAssetsPopupMenu(buttonRect, typeName, serializedProperty, fileExtension, defaultFieldName); - - EditorGUI.showMixedValue = orignalShowMixedValue; - } - - public static void AssetPopup(SerializedProperty serializedProperty, GUIContent label, string fileExtension) where T : Object, new() - { - AssetPopup(serializedProperty, label, fileExtension, "Default"); - } - - // private - - static void ShowAssetsPopupMenu(Rect buttonRect, string typeName, SerializedProperty serializedProperty, string fileExtension, string defaultFieldName) where T : Object, new() - { - GenericMenu gm = new GenericMenu(); - - int selectedInstanceID = serializedProperty.objectReferenceValue != null ? serializedProperty.objectReferenceValue.GetInstanceID() : 0; - - - bool foundDefaultAsset = false; - var type = UnityEditor.UnityType.FindTypeByName(typeName); - int classID = type != null ? type.persistentTypeID : 0; - BuiltinResource[] resourceList = null; - - // Check the assets for one that matches the default name. - if (classID > 0) - { - resourceList = EditorGUIUtility.GetBuiltinResourceList(classID); - foreach (var resource in resourceList) - { - if (resource.m_Name == defaultFieldName) - { - gm.AddItem(new GUIContent(resource.m_Name), resource.m_InstanceID == selectedInstanceID, AssetPopupMenuCallback, new object[] { resource.m_InstanceID, serializedProperty }); - resourceList = resourceList.Where(x => x != resource).ToArray(); - foundDefaultAsset = true; - break; - } - } - } - - // If no defalut asset was found, add defualt null value. - if (!foundDefaultAsset) - { - gm.AddItem(new GUIContent(defaultFieldName), selectedInstanceID == 0, AssetPopupMenuCallback, new object[] { 0, serializedProperty }); - } - - // Add items from asset database - var property = new HierarchyProperty(HierarchyType.Assets); - var searchFilter = new SearchFilter() { classNames = new[] { typeName } }; - property.SetSearchFilter(searchFilter); - property.Reset(); - while (property.Next(null)) - { - gm.AddItem(new GUIContent(property.name), property.instanceID == selectedInstanceID, AssetPopupMenuCallback, new object[] { property.instanceID, serializedProperty }); - } - - // Add builtin items, except for the already added default item. - if (classID > 0 && resourceList != null) - { - foreach (var resource in resourceList) - { - gm.AddItem(new GUIContent(resource.m_Name), resource.m_InstanceID == selectedInstanceID, AssetPopupMenuCallback, new object[] { resource.m_InstanceID, serializedProperty }); - } - } - - // Create item - gm.AddSeparator(""); - gm.AddItem(EditorGUIUtility.TrTextContent("Create New..."), false, delegate - { - var newAsset = Activator.CreateInstance(); - ProjectWindowUtil.CreateAsset(newAsset, "New " + typeName + "." + fileExtension); - serializedProperty.objectReferenceValue = newAsset; - serializedProperty.m_SerializedObject.ApplyModifiedProperties(); - }); - - gm.DropDown(buttonRect); - } - - static void ShowAssetsPopupMenu(Rect buttonRect, string typeName, SerializedProperty serializedProperty, string fileExtension) where T : Object, new() - { - ShowAssetsPopupMenu(buttonRect, typeName, serializedProperty, fileExtension, "Default"); - } - - static void AssetPopupMenuCallback(object userData) - { - var data = userData as object[]; - var instanceID = (int)data[0]; - var serializedProperty = (SerializedProperty)data[1]; - - serializedProperty.objectReferenceValue = EditorUtility.InstanceIDToObject(instanceID); - serializedProperty.m_SerializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/GUI/AssetSaveDialog.cs b/Editor/Mono/GUI/AssetSaveDialog.cs deleted file mode 100644 index ddfc7475f3..0000000000 --- a/Editor/Mono/GUI/AssetSaveDialog.cs +++ /dev/null @@ -1,242 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using UnityEditor.Scripting; -using System.Collections.Generic; -using System.IO; - -namespace UnityEditor -{ - internal class AssetSaveDialog : EditorWindow - { - class Styles - { - public GUIStyle selected = "OL SelectedRow"; - public GUIStyle box = "OL Box"; - public GUIStyle button = "LargeButton"; - public GUIContent saveSelected = EditorGUIUtility.TrTextContent("Save Selected"); - public GUIContent saveAll = EditorGUIUtility.TrTextContent("Save All"); - public GUIContent dontSave = EditorGUIUtility.TrTextContent("Don't Save"); - public GUIContent close = EditorGUIUtility.TrTextContent("Close"); - public float buttonWidth; - public Styles() - { - buttonWidth = Mathf.Max(Mathf.Max(button.CalcSize(saveSelected).x, button.CalcSize(saveAll).x), button.CalcSize(dontSave).x); - } - } - - static Styles s_Styles = null; - List m_Assets; - List m_AssetsToSave; - ListViewState m_LV = new ListViewState(); - int m_InitialSelectedItem = -1; - bool[] m_SelectedItems; - List m_Content; - - void SetAssets(string[] assets) - { - m_Assets = new List(assets); - RebuildLists(true); - m_AssetsToSave = new List(); - } - - public static void ShowWindow(string[] inAssets, out string[] assetsThatShouldBeSaved) - { - int numMetaFiles = 0; - foreach (string path in inAssets) - { - if (path.EndsWith("meta")) - numMetaFiles++; - } - int numAssets = inAssets.Length - numMetaFiles; - - if (numAssets == 0) - { - assetsThatShouldBeSaved = inAssets; - return; - } - - string[] assets = new string[numAssets]; - string[] metaFiles = new string[numMetaFiles]; - - numAssets = 0; - numMetaFiles = 0; - - foreach (string path in inAssets) - { - if (path.EndsWith("meta")) - metaFiles[numMetaFiles++] = path; - else - assets[numAssets++] = path; - } - - AssetSaveDialog win = EditorWindow.GetWindowDontShow(); - win.titleContent = EditorGUIUtility.TrTextContent("Save Assets"); - win.SetAssets(assets); - win.ShowUtility(); - win.ShowModal(); - - assetsThatShouldBeSaved = new string[win.m_AssetsToSave.Count + numMetaFiles]; - win.m_AssetsToSave.CopyTo(assetsThatShouldBeSaved, 0); - metaFiles.CopyTo(assetsThatShouldBeSaved, win.m_AssetsToSave.Count); - } - - public static GUIContent GetContentForAsset(string path) - { - Texture icon = AssetDatabase.GetCachedIcon(path); - if (path.StartsWith("Library/")) - path = ObjectNames.NicifyVariableName(AssetDatabase.LoadMainAssetAtPath(path).name); - - if (path.StartsWith("Assets/")) - path = path.Substring(7); - - return new GUIContent(path, icon); - } - - void OnGUI() - { - if (s_Styles == null) - { - s_Styles = new Styles(); - minSize = new Vector2(500, 300); - position = new Rect(position.x, position.y, minSize.x, minSize.y); - } - - GUILayout.Space(10); - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - GUILayout.Label("Unity is about to save the following modified files. Unsaved changes will be lost!"); - GUILayout.Space(10); - GUILayout.EndHorizontal(); - GUILayout.Space(10); - - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - - int prevSelectedRow = m_LV.row; - int numSelected = 0; - foreach (ListViewElement el in ListViewGUILayout.ListView(m_LV, s_Styles.box)) - { - if (m_SelectedItems[el.row] && Event.current.type == EventType.Repaint) - { - Rect box = el.position; - box.x += 1; - box.y += 1; - box.width -= 1; - box.height -= 1; - s_Styles.selected.Draw(box, false, false, false, false); - } - - GUILayout.Label(m_Content[el.row]); - - if (ListViewGUILayout.HasMouseUp(el.position)) - { - Event.current.command = true; - Event.current.control = true; - ListViewGUILayout.MultiSelection(prevSelectedRow, el.row, ref m_InitialSelectedItem, ref m_SelectedItems); - } - if (m_SelectedItems[el.row]) - numSelected++; - } - - GUILayout.Space(10); - GUILayout.EndHorizontal(); - GUILayout.Space(10); - - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - - if (GUILayout.Button(s_Styles.close, s_Styles.button, GUILayout.Width(s_Styles.buttonWidth))) - { - CloseWindow(); - } - - GUILayout.FlexibleSpace(); - - GUI.enabled = numSelected > 0; - - bool allSelected = numSelected == m_Assets.Count; - - if (GUILayout.Button(s_Styles.dontSave, s_Styles.button, GUILayout.Width(s_Styles.buttonWidth))) - { - IgnoreSelectedAssets(); - } - - if (GUILayout.Button(allSelected ? s_Styles.saveAll : s_Styles.saveSelected, - s_Styles.button, GUILayout.Width(s_Styles.buttonWidth))) - { - SaveSelectedAssets(); - } - - if (m_Assets.Count == 0) - CloseWindow(); - - - GUI.enabled = true; - - GUILayout.Space(10); - GUILayout.EndHorizontal(); - - GUILayout.Space(10); - } - - void Cancel() - { - Close(); - GUIUtility.ExitGUI(); - } - - void CloseWindow() - { - Close(); - GUIUtility.ExitGUI(); - } - - void SaveSelectedAssets() - { - List newAssets = new List(); - for (int i = 0; i < m_SelectedItems.Length; i++) - { - if (m_SelectedItems[i]) - m_AssetsToSave.Add(m_Assets[i]); - else - newAssets.Add(m_Assets[i]); - } - - m_Assets = newAssets; - RebuildLists(false); - } - - void IgnoreSelectedAssets() - { - List newAssets = new List(); - for (int i = 0; i < m_SelectedItems.Length; i++) - { - if (!m_SelectedItems[i]) - newAssets.Add(m_Assets[i]); - } - - m_Assets = newAssets; - RebuildLists(false); - - if (m_Assets.Count == 0) - CloseWindow(); - } - - void RebuildLists(bool selected) - { - m_LV.totalRows = m_Assets.Count; - m_SelectedItems = new bool[m_Assets.Count]; - m_Content = new List(m_Assets.Count); - for (int i = 0; i < m_Assets.Count; i++) - { - m_SelectedItems[i] = selected; - m_Content.Add(GetContentForAsset(m_Assets[i])); - } - } - } -} diff --git a/Editor/Mono/GUI/BumpMapSettingsFixingWindow.cs b/Editor/Mono/GUI/BumpMapSettingsFixingWindow.cs deleted file mode 100644 index 12c9eb7f3c..0000000000 --- a/Editor/Mono/GUI/BumpMapSettingsFixingWindow.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class BumpMapSettingsFixingWindow : EditorWindow - { - public static void ShowWindow(string[] paths) - { - BumpMapSettingsFixingWindow win = EditorWindow.GetWindow(true); - win.SetPaths(paths); - win.ShowUtility(); - } - - class Styles - { - public GUIStyle selected = "OL SelectedRow"; - public GUIStyle box = "OL Box"; - public GUIStyle button = "LargeButton"; - 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."); - } - - static Styles s_Styles = null; - - ListViewState m_LV = new ListViewState(); - string[] m_Paths; - - public BumpMapSettingsFixingWindow() - { - titleContent = EditorGUIUtility.TrTextContent("NormalMap settings"); - } - - public void SetPaths(string[] paths) - { - m_Paths = paths; - m_LV.totalRows = paths.Length; - } - - void OnGUI() - { - if (s_Styles == null) - { - s_Styles = new Styles(); - minSize = new Vector2(400, 300); - position = new Rect(position.x, position.y, minSize.x, minSize.y); - } - - GUILayout.Space(5); - GUILayout.Label(s_Styles.overviewText); - GUILayout.Space(10); - - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - foreach (ListViewElement el in ListViewGUILayout.ListView(m_LV, s_Styles.box)) - { - if (el.row == m_LV.row && Event.current.type == EventType.Repaint) - s_Styles.selected.Draw(el.position, false, false, false, false); - - GUILayout.Label(m_Paths[el.row]); - } - GUILayout.Space(10); - GUILayout.EndHorizontal(); - GUILayout.Space(10); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Fix now", s_Styles.button)) - { - InternalEditorUtility.BumpMapSettingsFixingWindowReportResult(1); - Close(); - } - - if (GUILayout.Button("Ignore", s_Styles.button)) - { - InternalEditorUtility.BumpMapSettingsFixingWindowReportResult(0); - Close(); - } - GUILayout.Space(10); - GUILayout.EndHorizontal(); - - GUILayout.Space(10); - } - - void OnDestroy() - { - InternalEditorUtility.BumpMapSettingsFixingWindowReportResult(0); - } - } -} diff --git a/Editor/Mono/GUI/ButtonWithAnimatedIcon.cs b/Editor/Mono/GUI/ButtonWithAnimatedIcon.cs deleted file mode 100644 index 55fc989ac9..0000000000 --- a/Editor/Mono/GUI/ButtonWithAnimatedIcon.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class EditorGUI - { - internal static bool ButtonWithRotatedIcon(Rect rect, GUIContent guiContent, float iconAngle, bool mouseDownButton, GUIStyle style) - { - // Button with text and background (no icon - it's rendered separately below) - bool buttonPressed; - if (mouseDownButton) - buttonPressed = DropdownButton(rect, GUIContent.Temp(guiContent.text, guiContent.tooltip), FocusType.Passive, style); - else - buttonPressed = GUI.Button(rect, GUIContent.Temp(guiContent.text, guiContent.tooltip), style); - - // Icon (rendered left of text) - if (Event.current.type == EventType.Repaint && guiContent.image != null) - { - Vector2 iconSize = EditorGUIUtility.GetIconSize(); - if (iconSize == Vector2.zero) - { - iconSize.x = iconSize.y = rect.height - style.padding.vertical; - } - - const float spaceBetweenIconAndText = 3f; - const float spaceBetweenIconAndTop = 1f; - Rect iconRect = new Rect(rect.x + style.padding.left - spaceBetweenIconAndText - iconSize.x, rect.y + style.padding.top + spaceBetweenIconAndTop, iconSize.x, iconSize.y); - if (iconAngle == 0f) - { - GUI.DrawTexture(iconRect, guiContent.image); - } - else - { - Matrix4x4 prevMatrix = GUI.matrix; - GUIUtility.RotateAroundPivot(iconAngle, iconRect.center); - GUI.DrawTexture(iconRect, guiContent.image); - GUI.matrix = prevMatrix; - } - } - return buttonPressed; - } - } - - // Ensure to call Clear() before setting a instance to null to prevent mem leaking - // due to CallbackController using a delegate for update calls (if not de-registering this - // delegate, it will keep the instance from being gc'ed) - internal class ButtonWithAnimatedIconRotation - { - readonly CallbackController m_CallbackController; // used for continuous repaints - readonly Func m_AngleCallback; - readonly bool m_MouseDownButton; - - public ButtonWithAnimatedIconRotation(Func angleCallback, Action repaintCallback, float repaintsPerSecond, bool mouseDownButton) - { - m_CallbackController = new CallbackController(repaintCallback, repaintsPerSecond); - m_AngleCallback = angleCallback; - m_MouseDownButton = mouseDownButton; - } - - public bool OnGUI(Rect rect, GUIContent guiContent, bool animate, GUIStyle style) - { - if (animate && !m_CallbackController.active) - m_CallbackController.Start(); - if (!animate && m_CallbackController.active) - m_CallbackController.Stop(); - - float iconAngle = animate ? m_AngleCallback() : 0f; - return EditorGUI.ButtonWithRotatedIcon(rect, guiContent, iconAngle, m_MouseDownButton, style); - } - - public void Clear() - { - m_CallbackController.Stop(); - } - } -} diff --git a/Editor/Mono/GUI/CallbackController.cs b/Editor/Mono/GUI/CallbackController.cs deleted file mode 100644 index bfe7f78d49..0000000000 --- a/Editor/Mono/GUI/CallbackController.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - class CallbackController - { - readonly Action m_Callback; - readonly float m_CallbacksPerSecond; - double m_NextCallback; - - public CallbackController(Action callback, float callbacksPerSecond) - { - m_Callback = callback; - m_CallbacksPerSecond = Mathf.Max(callbacksPerSecond, 1f); - } - - public bool active { get; private set; } - - public void Start() - { - m_NextCallback = 0; - EditorApplication.update += Update; - active = true; - } - - public void Stop() - { - EditorApplication.update -= Update; - active = false; - } - - void Update() - { - double time = EditorApplication.timeSinceStartup; - if (time > m_NextCallback) - { - m_NextCallback = time + (1f / m_CallbacksPerSecond); - if (m_Callback != null) - m_Callback(); - } - } - } -} diff --git a/Editor/Mono/GUI/ColorClipboard.cs b/Editor/Mono/GUI/ColorClipboard.cs deleted file mode 100644 index 8381d0508c..0000000000 --- a/Editor/Mono/GUI/ColorClipboard.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Networking; - -namespace UnityEditor -{ - // ColorClipboard supports colors copied to the system copy buffer (as a hex string) and as a Color value to the Pasteboard (in c++) - static internal class ColorClipboard - { - public static void SetColor(Color color) - { - EditorGUIUtility.systemCopyBuffer = ""; - EditorGUIUtility.SetPasteboardColor(color); - } - - public static bool HasColor() - { - Color dummy; - return TryGetColor(false, out dummy); - } - - public static bool TryGetColor(bool allowHDR, out Color color) - { - bool validColor = false; - if (ColorUtility.TryParseHtmlString(EditorGUIUtility.systemCopyBuffer, out color)) - { - validColor = true; - } - else if (EditorGUIUtility.HasPasteboardColor()) - { - color = EditorGUIUtility.GetPasteboardColor(); - validColor = true; - } - - if (validColor) - { - // Ensure HDR colors are normalized for LDR color fields - if (!allowHDR && color.maxColorComponent > 1f) - color = color.RGBMultiplied(1f / color.maxColorComponent); - return true; - } - - return false; - } - } -} // namespace diff --git a/Editor/Mono/GUI/ColorMutator.cs b/Editor/Mono/GUI/ColorMutator.cs deleted file mode 100644 index aa6ff8f2c7..0000000000 --- a/Editor/Mono/GUI/ColorMutator.cs +++ /dev/null @@ -1,219 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal enum RgbaChannel { R, G, B, A } - internal enum HsvChannel { H, S, V } - - // includes color setters for RGB float, RGB byte, and HSV - // each mode preserves maximum componential integrity until editing using a different mode - // exposure and HDR interfaces assume that the supplied originalColor and all per-channel modifications are in linear space - [Serializable] - internal class ColorMutator - { - // specifies the max byte value to use when decomposing a float color into bytes with exposure - // this is the value used by Photoshop - private const byte k_MaxByteForOverexposedColor = 191; - - internal static void DecomposeHdrColor(Color linearColorHdr, out Color32 baseLinearColor, out float exposure) - { - baseLinearColor = linearColorHdr; - var maxColorComponent = linearColorHdr.maxColorComponent; - // replicate Photoshops's decomposition behaviour - if (maxColorComponent == 0f || maxColorComponent <= 1f && maxColorComponent > 1 / 255f) - { - exposure = 0f; - - baseLinearColor.r = (byte)Mathf.RoundToInt(linearColorHdr.r * 255f); - baseLinearColor.g = (byte)Mathf.RoundToInt(linearColorHdr.g * 255f); - baseLinearColor.b = (byte)Mathf.RoundToInt(linearColorHdr.b * 255f); - } - else - { - // calibrate exposure to the max float color component - var scaleFactor = k_MaxByteForOverexposedColor / maxColorComponent; - exposure = Mathf.Log(255f / scaleFactor) / Mathf.Log(2f); - - // maintain maximal integrity of byte values to prevent off-by-one errors when scaling up a color one component at a time - baseLinearColor.r = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.r)); - baseLinearColor.g = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.g)); - baseLinearColor.b = Math.Min(k_MaxByteForOverexposedColor, (byte)Mathf.CeilToInt(scaleFactor * linearColorHdr.b)); - } - } - - public Color originalColor - { - get { return m_OriginalColor; } - } - [SerializeField] private Color m_OriginalColor; - - public Color32 color - { - get - { - return new Color32( - m_Color[(int)RgbaChannel.R], - m_Color[(int)RgbaChannel.G], - m_Color[(int)RgbaChannel.B], - m_Color[(int)RgbaChannel.A] - ); - } - } - [SerializeField] private byte[] m_Color = new byte[4]; - - public byte GetColorChannel(RgbaChannel channel) - { - return m_Color[(int)channel]; - } - - public float GetColorChannelNormalized(RgbaChannel channel) - { - return m_Color[(int)channel] / 255f; - } - - public void SetColorChannel(RgbaChannel channel, byte value) - { - if (m_Color[(int)channel] == value) - return; - m_Color[(int)channel] = value; - m_ColorHdr[(int)channel] = (value / 255f); - if (channel != RgbaChannel.A) - m_ColorHdr[(int)channel] *= Mathf.Pow(2f, m_ExposureValue); - Color.RGBToHSV( - color, - out m_Hsv[(int)HsvChannel.H], - out m_Hsv[(int)HsvChannel.S], - out m_Hsv[(int)HsvChannel.V] - ); - } - - public void SetColorChannel(RgbaChannel channel, float normalizedValue) - { - SetColorChannel(channel, (byte)Mathf.RoundToInt(Mathf.Clamp01(normalizedValue) * 255f)); - } - - public Color exposureAdjustedColor - { - get - { - return new Color( - m_ColorHdr[(int)RgbaChannel.R], - m_ColorHdr[(int)RgbaChannel.G], - m_ColorHdr[(int)RgbaChannel.B], - m_ColorHdr[(int)RgbaChannel.A] - ); - } - } - [SerializeField] private float[] m_ColorHdr = new float[4]; - - public float GetColorChannelHdr(RgbaChannel channel) - { - return m_ColorHdr[(int)channel]; - } - - public void SetColorChannelHdr(RgbaChannel channel, float value) - { - if (m_ColorHdr[(int)channel] == value) - return; - m_ColorHdr[(int)channel] = value; - OnRgbaHdrChannelChanged((int)channel); - } - - public Vector3 colorHsv - { - get - { - return new Vector3( - m_Hsv[(int)HsvChannel.H], - m_Hsv[(int)HsvChannel.S], - m_Hsv[(int)HsvChannel.V] - ); - } - } - [SerializeField] private float[] m_Hsv = new float[3]; - - public float GetColorChannel(HsvChannel channel) - { - return m_Hsv[(int)channel]; - } - - public void SetColorChannel(HsvChannel channel, float value) - { - m_Hsv[(int)channel] = Mathf.Clamp01(value); - - var newColor = Color.HSVToRGB( - m_Hsv[(int)HsvChannel.H], m_Hsv[(int)HsvChannel.S], m_Hsv[(int)HsvChannel.V] - ); - m_Color[(int)RgbaChannel.R] = (byte)Mathf.CeilToInt(newColor.r * 255f); - m_Color[(int)RgbaChannel.G] = (byte)Mathf.CeilToInt(newColor.g * 255f); - m_Color[(int)RgbaChannel.B] = (byte)Mathf.CeilToInt(newColor.b * 255f); - - newColor *= Mathf.Pow(2f, m_ExposureValue); - m_ColorHdr[(int)RgbaChannel.R] = newColor.r; - m_ColorHdr[(int)RgbaChannel.G] = newColor.g; - m_ColorHdr[(int)RgbaChannel.B] = newColor.b; - } - - public float exposureValue - { - get { return m_ExposureValue; } - set - { - if (m_ExposureValue == value) - return; - m_ExposureValue = value; - var newRgbFloat = (Color)color * Mathf.Pow(2f, m_ExposureValue); - m_ColorHdr[(int)RgbaChannel.R] = newRgbFloat.r; - m_ColorHdr[(int)RgbaChannel.G] = newRgbFloat.g; - m_ColorHdr[(int)RgbaChannel.B] = newRgbFloat.b; - } - } - [SerializeField] private float m_ExposureValue; - - public ColorMutator(Color originalColor) - { - m_OriginalColor = originalColor; - Reset(); - } - - public void Reset() - { - if (m_ColorHdr == null || m_ColorHdr.Length != 4) - m_ColorHdr = new float[4]; - - m_ColorHdr[(int)RgbaChannel.R] = m_OriginalColor.r; - m_ColorHdr[(int)RgbaChannel.G] = m_OriginalColor.g; - m_ColorHdr[(int)RgbaChannel.B] = m_OriginalColor.b; - m_ColorHdr[(int)RgbaChannel.A] = m_OriginalColor.a; - - if (m_Color == null || m_Color.Length != 4) - m_Color = new byte[4]; - - OnRgbaHdrChannelChanged(-1); - } - - void OnRgbaHdrChannelChanged(int channel) - { - m_Color[(int)RgbaChannel.A] = (byte)Mathf.RoundToInt(Mathf.Clamp01(m_ColorHdr[(int)RgbaChannel.A]) * 255f); - if (channel == (int)RgbaChannel.A) - return; - - Color32 baseColor; - DecomposeHdrColor(exposureAdjustedColor, out baseColor, out m_ExposureValue); - m_Color[(int)RgbaChannel.R] = baseColor.r; - m_Color[(int)RgbaChannel.G] = baseColor.g; - m_Color[(int)RgbaChannel.B] = baseColor.b; - Color.RGBToHSV( - color, - out m_Hsv[(int)HsvChannel.H], - out m_Hsv[(int)HsvChannel.S], - out m_Hsv[(int)HsvChannel.V] - ); - } - } -} diff --git a/Editor/Mono/GUI/ColorPicker.cs b/Editor/Mono/GUI/ColorPicker.cs deleted file mode 100644 index 2d04d0c030..0000000000 --- a/Editor/Mono/GUI/ColorPicker.cs +++ /dev/null @@ -1,1415 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.Accessibility; - -namespace UnityEditor -{ - internal class ColorPicker : EditorWindow - { - private const string k_HeightPrefKey = "CPickerHeight"; - private const string k_ShowPresetsPrefKey = "CPPresetsShow"; - // HDR and LDR have different slider mode pref keys because they have different defaults for the sake of discoverability - private const string k_SliderModePrefKey = "CPSliderMode"; - private const string k_SliderModeHDRPrefKey = "CPSliderModeHDR"; - - // the default max amount of stops to use for the intensity slider; same as in Photoshop/Affinity - private const float k_DefaultExposureSliderMax = 10f; - - public static string presetsEditorPrefID { get { return "Color"; } } - - [SerializeField] - bool m_HDR; - - [SerializeField] - private ColorMutator m_Color; - - #pragma warning disable 649 - [SerializeField] - Texture2D m_ColorSlider; - - [SerializeField] - Color[] m_Colors; - const int kHueRes = 64; - const int kColorBoxSize = 32; - [SerializeField] - Texture2D m_ColorBox; - static int s_Slider2Dhash = "Slider2D".GetHashCode(); - [SerializeField] - bool m_ShowPresets = true; - - [SerializeField] - bool m_IsOSColorPicker = false; - [SerializeField] - bool m_ShowAlpha = true; - - [SerializeField] - Texture2D m_RTexture; float m_RTextureG = -1, m_RTextureB = -1; - [SerializeField] - Texture2D m_GTexture; float m_GTextureR = -1, m_GTextureB = -1; - [SerializeField] - Texture2D m_BTexture; float m_BTextureR = -1, m_BTextureG = -1; - - [SerializeField] - Texture2D m_HueTexture; float m_HueTextureS = -1, m_HueTextureV = -1; - [SerializeField] - Texture2D m_SatTexture; float m_SatTextureH = -1, m_SatTextureV = -1; - [SerializeField] - Texture2D m_ValTexture; float m_ValTextureH = -1, m_ValTextureS = -1; - - [NonSerialized] - int m_TextureColorBoxMode = -1; - [SerializeField] - float m_LastConstant = -1; - - [NonSerialized] - bool m_ColorSpaceBoxDirty; - - enum ColorBoxMode { HSV, EyeDropper } - - [SerializeField] - ColorBoxMode m_ColorBoxMode = ColorBoxMode.HSV; - - enum SliderMode { RGB, RGBFloat, HSV } - - [SerializeField] - SliderMode m_SliderMode = SliderMode.HSV; - - [SerializeField] - Texture2D m_AlphaTexture; float m_OldAlpha = -1; - - [SerializeField] - GUIView m_DelegateView; - - private Action m_ColorChangedCallback; - - [SerializeField] - int m_ModalUndoGroup = -1; - - // hdr float slider ranges dynamically adjust on mouse up - private float m_FloatSliderMaxOnMouseDown; - private bool m_DraggingFloatSlider; - - // the exposure slider range can dynamically grow if needed per color picker "session" - private float m_ExposureSliderMax = k_DefaultExposureSliderMax; - - PresetLibraryEditor m_ColorLibraryEditor; - PresetLibraryEditorState m_ColorLibraryEditorState; - - public static Color color - { - get { return instance.m_Color.exposureAdjustedColor; } - set - { - instance.SetColor(value); - instance.Repaint(); - } - } - - public static bool visible - { - get { return s_Instance != null; } - } - - public static ColorPicker instance - { - get - { - if (!s_Instance) - { - var hmm = Resources.FindObjectsOfTypeAll(typeof(ColorPicker)); - if (hmm != null && hmm.Length > 0) - s_Instance = (ColorPicker)hmm[0]; - if (!s_Instance) - { - s_Instance = CreateInstance(); - s_Instance.wantsMouseMove = true; - } - } - return s_Instance; - } - } - static ColorPicker s_Instance; - - public static int originalKeyboardControl { get; private set; } - - // ------- Soerens 2D slider -------- - - static void swap(ref float f1, ref float f2) { float tmp = f1; f1 = f2; f2 = tmp; } - - Vector2 Slider2D(Rect rect, Vector2 value, Vector2 maxvalue, Vector2 minvalue, GUIStyle thumbStyle) - { - int id = GUIUtility.GetControlID(s_Slider2Dhash, FocusType.Passive); - - // test max and min - if (maxvalue.x < minvalue.x) // swap - swap(ref maxvalue.x, ref minvalue.x); - if (maxvalue.y < minvalue.y) - swap(ref maxvalue.y, ref minvalue.y); - - Event e = Event.current; - - switch (e.GetTypeForControl(id)) - { - case EventType.MouseDown: - { - if (rect.Contains(e.mousePosition)) // inside this control - { - GUIUtility.hotControl = id; - GUIUtility.keyboardControl = 0; - value.x = (e.mousePosition.x - rect.x) / rect.width * (maxvalue.x - minvalue.x); - value.y = (e.mousePosition.y - rect.y) / rect.height * (maxvalue.y - minvalue.y); - GUI.changed = true; - - Event.current.Use(); - } - break; - } - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - e.Use(); - } - break; - case EventType.MouseDrag: - { - if (GUIUtility.hotControl != id) - break; - - // move thumb to mouse position - value.x = (e.mousePosition.x - rect.x) / rect.width * (maxvalue.x - minvalue.x); - value.y = (e.mousePosition.y - rect.y) / rect.height * (maxvalue.y - minvalue.y); - - // clamp - value.x = Mathf.Clamp(value.x, minvalue.x, maxvalue.x); - value.y = Mathf.Clamp(value.y, minvalue.y, maxvalue.y); - GUI.changed = true; - Event.current.Use(); - } - break; - - case EventType.Repaint: - { - // thumb (set to black for light colors to prevent blending with background) - var oldColor = GUI.color; - GUI.color = VisionUtility.ComputePerceivedLuminance(color) > Styles.highLuminanceThreshold ? - Styles.highLuminanceContentColor : Styles.lowLuminanceContentColor; - - var thumbRect = new Rect - { - size = thumbStyle.CalcSize(GUIContent.none), - center = new Vector2( - value.x / (maxvalue.x - minvalue.x) * rect.width + rect.x, - value.y / (maxvalue.y - minvalue.y) * rect.height + rect.y - ) - }; - thumbStyle.Draw(thumbRect, GUIContent.none, id); - - GUI.color = oldColor; - } - break; - } - return value; - } - - void RGBSliders() - { - var r = m_Color.GetColorChannelNormalized(RgbaChannel.R); - var g = m_Color.GetColorChannelNormalized(RgbaChannel.G); - var b = m_Color.GetColorChannelNormalized(RgbaChannel.B); - - m_RTexture = Update1DSlider(m_RTexture, kColorBoxSize, g, b, ref m_RTextureG, ref m_RTextureB, 0, false); - m_GTexture = Update1DSlider(m_GTexture, kColorBoxSize, r, b, ref m_GTextureR, ref m_GTextureB, 1, false); - m_BTexture = Update1DSlider(m_BTexture, kColorBoxSize, r, g, ref m_BTextureR, ref m_BTextureG, 2, false); - - RGBSlider("R", RgbaChannel.R, m_RTexture); - GUILayout.Space(Styles.extraVerticalSpacing); - RGBSlider("G", RgbaChannel.G, m_GTexture); - GUILayout.Space(Styles.extraVerticalSpacing); - RGBSlider("B", RgbaChannel.B, m_BTexture); - GUILayout.Space(Styles.extraVerticalSpacing); - } - - void RGBSlider(string label, RgbaChannel channel, Texture2D sliderBackground) - { - float value; - switch (m_SliderMode) - { - case SliderMode.RGB: - value = m_Color.GetColorChannel(channel); - EditorGUI.BeginChangeCheck(); - value = EditorGUILayout.SliderWithTexture( - GUIContent.Temp(label), value, 0f, 255f, EditorGUI.kIntFieldFormatString, 0f, 255f, sliderBackground - ); - if (EditorGUI.EndChangeCheck()) - { - m_Color.SetColorChannel(channel, value / 255f); - OnColorChanged(); - } - m_DraggingFloatSlider = false; - break; - case SliderMode.RGBFloat: - value = m_Color.GetColorChannelHdr(channel); - var maxRgbNormalized = ((Color)m_Color.color).maxColorComponent; - var evtType = Event.current.type; - var sliderMax = m_HDR && m_Color.exposureAdjustedColor.maxColorComponent > 1f ? m_Color.exposureAdjustedColor.maxColorComponent / maxRgbNormalized : 1f; - var textFieldMax = m_HDR ? float.MaxValue : 1f; - EditorGUI.BeginChangeCheck(); - value = EditorGUILayout.SliderWithTexture( - GUIContent.Temp(label), value, - 0f, m_DraggingFloatSlider ? m_FloatSliderMaxOnMouseDown : sliderMax, - EditorGUI.kFloatFieldFormatString, - 0f, textFieldMax, - sliderBackground - ); - switch (evtType) - { - case EventType.MouseDown: - m_FloatSliderMaxOnMouseDown = sliderMax; - m_DraggingFloatSlider = true; - break; - case EventType.MouseUp: - m_DraggingFloatSlider = false; - break; - } - if (EditorGUI.EndChangeCheck()) - { - m_Color.SetColorChannelHdr(channel, value); - OnColorChanged(); - } - break; - } - } - - Texture2D Update1DSlider( - Texture2D tex, int xSize, float const1, float const2, ref float oldConst1, ref float oldConst2, int idx, bool hsvSpace - ) - { - if (!tex || const1 != oldConst1 || const2 != oldConst2) - { - if (!tex) - tex = MakeTexture(xSize, 2); - - Color[] colors = new Color[xSize * 2]; - Color start = Color.black, step = Color.black; - switch (idx) - { - case 0: - start = new Color(0, const1, const2, 1); - step = new Color(1, 0, 0, 0); - break; - case 1: - start = new Color(const1, 0, const2, 1); - step = new Color(0, 1, 0, 0); - break; - case 2: - start = new Color(const1, const2, 0, 1); - step = new Color(0, 0, 1, 0); - break; - case 3: - start = m_Color.color; - start.a = 0f; - step = new Color(0, 0, 0, 1); - break; - } - FillArea(xSize, 2, colors, start, step, new Color(0, 0, 0, 0), !hsvSpace && m_HDR); - if (hsvSpace) - HSVToRGBArray(colors, m_HDR); - - oldConst1 = const1; - oldConst2 = const2; - tex.SetPixels(colors); - tex.Apply(); - } - return tex; - } - - void HSVSliders() - { - var h = m_Color.GetColorChannel(HsvChannel.H); - var s = m_Color.GetColorChannel(HsvChannel.S); - var v = m_Color.GetColorChannel(HsvChannel.V); - - m_HueTexture = Update1DSlider(m_HueTexture, kHueRes, 1, 1, ref m_HueTextureS, ref m_HueTextureV, 0, true); - m_SatTexture = Update1DSlider(m_SatTexture, kColorBoxSize, h, Mathf.Max(v, .2f), ref m_SatTextureH, ref m_SatTextureV, 1, true); - m_ValTexture = Update1DSlider(m_ValTexture, kColorBoxSize, h, s, ref m_ValTextureH, ref m_ValTextureS, 2, true); - - EditorGUI.BeginChangeCheck(); - h = EditorGUILayout.SliderWithTexture( - GUIContent.Temp("H"), h * 360f, 0f, 360f, EditorGUI.kIntFieldFormatString, m_HueTexture - ); - if (EditorGUI.EndChangeCheck()) - { - m_Color.SetColorChannel(HsvChannel.H, h / 360f); - OnColorChanged(); - } - GUILayout.Space(Styles.extraVerticalSpacing); - - EditorGUI.BeginChangeCheck(); - s = EditorGUILayout.SliderWithTexture( - GUIContent.Temp("S"), s * 100f, 0f, 100f, EditorGUI.kIntFieldFormatString, m_SatTexture - ); - if (EditorGUI.EndChangeCheck()) - { - m_Color.SetColorChannel(HsvChannel.S, s / 100f); - OnColorChanged(); - } - GUILayout.Space(Styles.extraVerticalSpacing); - - EditorGUI.BeginChangeCheck(); - v = EditorGUILayout.SliderWithTexture( - GUIContent.Temp("V"), v * 100f, 0f, 100f, EditorGUI.kIntFieldFormatString, m_ValTexture - ); - if (EditorGUI.EndChangeCheck()) - { - m_Color.SetColorChannel(HsvChannel.V, v / 100f); - OnColorChanged(); - } - GUILayout.Space(Styles.extraVerticalSpacing); - } - - static void FillArea(int xSize, int ySize, Color[] retval, Color topLeftColor, Color rightGradient, Color downGradient, bool convertToGamma) - { - // Calc the deltas for stepping. - Color rightDelta = new Color(0, 0, 0, 0), downDelta = new Color(0, 0, 0, 0); - if (xSize > 1) - rightDelta = rightGradient / (xSize - 1); - if (ySize > 1) - downDelta = downGradient / (ySize - 1); - - // Assign all colors into the array - Color p = topLeftColor; - int current = 0; - for (int y = 0; y < ySize; y++) - { - Color p2 = p; - for (int x = 0; x < xSize; x++) - { - retval[current++] = convertToGamma ? p2.gamma : p2; - p2 += rightDelta; - } - p += downDelta; - } - } - - static void HSVToRGBArray(Color[] colors, bool convertToGamma) - { - int s = colors.Length; - for (int i = 0; i < s; i++) - { - Color c = colors[i]; - Color c2 = Color.HSVToRGB(c.r, c.g, c.b); - c2.a = c.a; - colors[i] = convertToGamma ? c2.gamma : c2; - } - } - - public static Texture2D MakeTexture(int width, int height) - { - Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false, true); - tex.hideFlags = HideFlags.HideAndDontSave; - tex.wrapMode = TextureWrapMode.Clamp; - return tex; - } - - void DrawColorSpaceBox(Rect colorBoxRect, float constantValue) - { - if (Event.current.type != EventType.Repaint) - return; - - // If we've switched mode, regenerate box - if ((int)m_ColorBoxMode != m_TextureColorBoxMode) - { - int xSize = kColorBoxSize, ySize = kColorBoxSize; - - if (m_ColorBox == null) - m_ColorBox = MakeTexture(xSize, ySize); - - if (m_ColorBox.width != xSize || m_ColorBox.height != ySize) - m_ColorBox.Resize(xSize, ySize); - } - - if ((int)m_ColorBoxMode != m_TextureColorBoxMode || m_LastConstant != constantValue || m_ColorSpaceBoxDirty) - { - m_Colors = m_ColorBox.GetPixels(0); - int xSize = m_ColorBox.width; - int ySize = m_ColorBox.height; - - 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); - HSVToRGBArray(m_Colors, m_HDR); - - m_ColorBox.SetPixels(m_Colors, 0); - m_ColorBox.Apply(true); - m_LastConstant = constantValue; - m_TextureColorBoxMode = (int)m_ColorBoxMode; - } - 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, Color.grey); - } - - static class Styles - { - public const float fixedWindowWidth = 233; - public const float hexFieldWidth = 72f; - public const float sliderModeFieldWidth = hexFieldWidth; - public const float channelSliderLabelWidth = 14f; - public const float sliderTextFieldWidth = 45f; - public const float extraVerticalSpacing = 8f - EditorGUI.kControlVerticalSpacing; - public const float highLuminanceThreshold = 0.5f; - - public static readonly float hueDialThumbSize; - - public static readonly RectOffset colorBoxPadding = new RectOffset(6, 6, 6, 6); - - public static readonly Color lowLuminanceContentColor = Color.white; - public static readonly Color highLuminanceContentColor = Color.black; - - public static readonly GUIStyle originalColorSwatch = "ColorPickerOriginalColor"; - public static readonly GUIStyle currentColorSwatch = "ColorPickerCurrentColor"; - public static readonly GUIStyle colorBoxThumb = "ColorPicker2DThumb"; - public static readonly GUIStyle hueDialBackground = "ColorPickerHueRing"; - public static readonly GUIStyle hueDialBackgroundHDR = "ColorPickerHueRing-HDR"; - public static readonly GUIStyle hueDialThumb = "ColorPickerHueRingThumb"; - public static readonly GUIStyle sliderBackground = "ColorPickerSliderBackground"; - public static readonly GUIStyle sliderThumb = "ColorPickerHorizThumb"; - public static readonly GUIStyle background = new GUIStyle("ColorPickerBackground"); - public static readonly GUIStyle exposureSwatch = "ColorPickerExposureSwatch"; - public static readonly GUIStyle selectedExposureSwatchStroke = "ColorPickerCurrentExposureSwatchBorder"; - - public static readonly GUIContent eyeDropper = EditorGUIUtility.TrIconContent("EyeDropper.Large", "Pick a color from the screen."); - public static readonly GUIContent exposureValue = EditorGUIUtility.TrTextContent("Intensity", "Number of stops to over- or under-expose the color."); - public static readonly GUIContent hexLabel = EditorGUIUtility.TrTextContent("Hexadecimal"); - public static readonly GUIContent presetsToggle = EditorGUIUtility.TrTextContent("Swatches"); - - public static readonly ScalableGUIContent originalColorSwatchFill = - new ScalableGUIContent(string.Empty, "The original color. Click this swatch to reset the color picker to this value.", "ColorPicker-OriginalColor"); - public static readonly ScalableGUIContent currentColorSwatchFill = - new ScalableGUIContent(string.Empty, "The new color.", "ColorPicker-CurrentColor"); - public static readonly ScalableGUIContent hueDialThumbFill = new ScalableGUIContent("ColorPicker-HueRing-Thumb-Fill"); - - // force load the checker background from the light skin - public static readonly Texture2D alphaSliderCheckerBackground = - EditorGUIUtility.LoadRequired("Previews/Textures/textureChecker.png") as Texture2D; - - public static readonly GUIContent[] sliderModeLabels = new[] - { - EditorGUIUtility.TrTextContent("RGB 0-255"), - EditorGUIUtility.TrTextContent("RGB 0-1.0"), - EditorGUIUtility.TrTextContent("HSV") - }; - - public static readonly int[] sliderModeValues = new[] { 0, 1, 2 }; - - static Styles() - { - var thumbSize = hueDialThumb.CalcSize(hueDialThumbFill); - hueDialThumbSize = Mathf.Max(thumbSize.x, thumbSize.y); - } - } - - public string currentPresetLibrary - { - get - { - InitializePresetsLibraryIfNeeded(); - return m_ColorLibraryEditor.currentLibraryWithoutExtension; - } - set - { - InitializePresetsLibraryIfNeeded(); - m_ColorLibraryEditor.currentLibraryWithoutExtension = value; - } - } - - void InitializePresetsLibraryIfNeeded() - { - if (m_ColorLibraryEditorState == null) - { - m_ColorLibraryEditorState = new PresetLibraryEditorState(presetsEditorPrefID); - m_ColorLibraryEditorState.TransferEditorPrefsState(true); - } - - if (m_ColorLibraryEditor == null) - { - var saveLoadHelper = new ScriptableObjectSaveLoadHelper("colors", SaveType.Text); - m_ColorLibraryEditor = new PresetLibraryEditor(saveLoadHelper, m_ColorLibraryEditorState, OnClickedPresetSwatch); - m_ColorLibraryEditor.previewAspect = 1f; - m_ColorLibraryEditor.minMaxPreviewHeight = new Vector2(ColorPresetLibrary.kSwatchSize, ColorPresetLibrary.kSwatchSize); - m_ColorLibraryEditor.settingsMenuRightMargin = 2f; - m_ColorLibraryEditor.useOnePixelOverlappedGrid = true; - m_ColorLibraryEditor.alwaysShowScrollAreaHorizontalLines = false; - m_ColorLibraryEditor.marginsForGrid = new RectOffset(0, 0, 0, 0); - m_ColorLibraryEditor.marginsForList = new RectOffset(0, 5, 2, 2); - m_ColorLibraryEditor.InitializeGrid(Styles.fixedWindowWidth - (Styles.background.padding.left + Styles.background.padding.right)); - } - } - - void OnClickedPresetSwatch(int clickCount, object presetObject) - { - Color color = (Color)presetObject; - // extract RGB if not in HDR mode - if (!m_HDR && color.maxColorComponent > 1f) - color = new ColorMutator(color).color; - - SetColor(color); - } - - private Color GetGUIColor(Color color) - { - return m_HDR ? color.gamma : color; - } - - void DoColorSwatchAndEyedropper() - { - GUILayout.BeginHorizontal(); - - if (GUILayout.Button(Styles.eyeDropper, GUIStyle.none, GUILayout.Width(40), GUILayout.ExpandWidth(false))) - { - GUIUtility.keyboardControl = 0; - EyeDropper.Start(m_Parent, false); - m_ColorBoxMode = ColorBoxMode.EyeDropper; - GUIUtility.ExitGUI(); - } - - var swatchColor = m_Color.exposureAdjustedColor; - // current swatch and original swatch have the same size, so they can lay out in the same row - var rect = GUILayoutUtility.GetRect(Styles.currentColorSwatchFill, Styles.currentColorSwatch, GUILayout.ExpandWidth(true)); - - var swatchSize = Styles.currentColorSwatch.CalcSize(Styles.currentColorSwatchFill); - var swatchRect = new Rect - { - size = swatchSize, - y = rect.y, - x = rect.xMax - swatchSize.x - }; - - var backgroundColor = GUI.backgroundColor; - var contentColor = GUI.contentColor; - - var id = GUIUtility.GetControlID(FocusType.Passive); - if (Event.current.type == EventType.Repaint) - { - GUI.backgroundColor = m_Color.exposureAdjustedColor.a == 1f ? Color.clear : Color.white; - GUI.contentColor = GetGUIColor(m_Color.exposureAdjustedColor); - Styles.currentColorSwatch.Draw(swatchRect, Styles.currentColorSwatchFill, id); - } - - swatchRect.x -= swatchRect.width; - GUI.backgroundColor = m_Color.originalColor.a == 1f ? Color.clear : Color.white; - GUI.contentColor = GetGUIColor(m_Color.originalColor); - if (GUI.Button(swatchRect, Styles.originalColorSwatchFill, Styles.originalColorSwatch)) - { - m_Color.Reset(); - Event.current.Use(); - OnColorChanged(); - } - - GUI.backgroundColor = backgroundColor; - GUI.contentColor = contentColor; - - GUILayout.EndHorizontal(); - } - - void DoColorSpaceGUI() - { - var backgroundStyle = m_HDR ? Styles.hueDialBackgroundHDR : Styles.hueDialBackground; - var dialSize = backgroundStyle.CalcSize(GUIContent.none); - var dialRect = GUILayoutUtility.GetRect(dialSize.x, dialSize.y); - switch (m_ColorBoxMode) - { - case ColorBoxMode.HSV: - - dialRect.x += (dialRect.width - dialRect.height) * 0.5f; - dialRect.width = dialRect.height; - var hue = m_Color.GetColorChannel(HsvChannel.H); - var oldColor = GUI.contentColor; - GUI.contentColor = GetGUIColor(Color.HSVToRGB(hue, 1f, 1f)); - - EditorGUI.BeginChangeCheck(); - - hue = EditorGUI.AngularDial( - dialRect, - GUIContent.none, - hue * 360f, - ((GUIContent)Styles.hueDialThumbFill).image, - backgroundStyle, - Styles.hueDialThumb - ); - - if (EditorGUI.EndChangeCheck()) - { - hue = Mathf.Repeat(hue, 360f) / 360f; - m_Color.SetColorChannel(HsvChannel.H, hue); - OnColorChanged(); - } - GUI.contentColor = oldColor; - - var innerRadius = dialRect.width * 0.5f - Styles.hueDialThumbSize; - var size = Mathf.FloorToInt(Mathf.Sqrt(2f) * innerRadius); - if ((size & 1) == 1) - size += 1; - var svRect = new Rect { size = Vector2.one * size, center = dialRect.center }; - svRect = Styles.colorBoxPadding.Remove(svRect); - - DrawColorSpaceBox(svRect, m_Color.GetColorChannel(HsvChannel.H)); - - EditorGUI.BeginChangeCheck(); - - var sv = new Vector2(m_Color.GetColorChannel(HsvChannel.S), 1f - m_Color.GetColorChannel(HsvChannel.V)); - sv = Slider2D(svRect, sv, Vector2.zero, Vector2.one, Styles.colorBoxThumb); - - if (EditorGUI.EndChangeCheck()) - { - m_Color.SetColorChannel(HsvChannel.S, sv.x); - m_Color.SetColorChannel(HsvChannel.V, 1f - sv.y); - OnColorChanged(); - } - break; - case ColorBoxMode.EyeDropper: - EyeDropper.DrawPreview(dialRect); - break; - } - } - - void DoColorSliders(float availableWidth) - { - float oldLabelWidth = EditorGUIUtility.labelWidth; - float oldFieldWidth = EditorGUIUtility.fieldWidth; - EditorGUIUtility.labelWidth = availableWidth - Styles.sliderModeFieldWidth; - EditorGUIUtility.fieldWidth = Styles.sliderModeFieldWidth; - - m_SliderMode = (SliderMode)EditorGUILayout.IntPopup( - GUIContent.Temp(" "), (int)m_SliderMode, Styles.sliderModeLabels, Styles.sliderModeValues - ); - GUILayout.Space(Styles.extraVerticalSpacing); - - EditorGUIUtility.labelWidth = oldLabelWidth; - EditorGUIUtility.fieldWidth = oldFieldWidth; - - EditorGUIUtility.labelWidth = Styles.channelSliderLabelWidth; - - switch (m_SliderMode) - { - case SliderMode.HSV: - HSVSliders(); - break; - default: - RGBSliders(); - break; - } - - if (m_ShowAlpha) - { - m_AlphaTexture = Update1DSlider(m_AlphaTexture, kColorBoxSize, 0, 0, ref m_OldAlpha, ref m_OldAlpha, 3, false); - - float displayScale = 1f; - string formatString = EditorGUI.kFloatFieldFormatString; - switch (m_SliderMode) - { - case SliderMode.HSV: - displayScale = 100f; - formatString = EditorGUI.kIntFieldFormatString; - break; - case SliderMode.RGB: - displayScale = 255f; - formatString = EditorGUI.kIntFieldFormatString; - break; - } - - var rect = EditorGUILayout.GetControlRect(true); - - if (Event.current.type == EventType.Repaint) - { - var backgroundRect = rect; - backgroundRect.xMin += EditorGUIUtility.labelWidth; - backgroundRect.xMax -= EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; - backgroundRect = Styles.sliderBackground.padding.Remove(backgroundRect); - var uvLayout = new Rect - { - x = 0f, - y = 0f, - width = backgroundRect.width / backgroundRect.height, // texture aspect is 1:1 - height = 1f - }; - Graphics.DrawTexture(backgroundRect, Styles.alphaSliderCheckerBackground, uvLayout, 0, 0, 0, 0); - } - - EditorGUI.BeginChangeCheck(); - var alpha = m_Color.GetColorChannelNormalized(RgbaChannel.A) * displayScale; - alpha = EditorGUI.SliderWithTexture( - rect, GUIContent.Temp("A"), alpha, 0f, displayScale, formatString, m_AlphaTexture - ); - if (EditorGUI.EndChangeCheck()) - { - m_Color.SetColorChannel(RgbaChannel.A, alpha / displayScale); - OnColorChanged(); - } - GUILayout.Space(Styles.extraVerticalSpacing); - } - - EditorGUIUtility.labelWidth = oldLabelWidth; - } - - void DoHexField(float availableWidth) - { - float oldLabelWidth = EditorGUIUtility.labelWidth; - float oldFieldWidth = EditorGUIUtility.fieldWidth; - EditorGUIUtility.labelWidth = availableWidth - Styles.hexFieldWidth; - EditorGUIUtility.fieldWidth = Styles.hexFieldWidth; - - EditorGUI.BeginChangeCheck(); - var newColor = EditorGUILayout.HexColorTextField(Styles.hexLabel, m_Color.color, false); - if (EditorGUI.EndChangeCheck()) - { - m_Color.SetColorChannel(RgbaChannel.R, newColor.r); - m_Color.SetColorChannel(RgbaChannel.G, newColor.g); - m_Color.SetColorChannel(RgbaChannel.B, newColor.b); - OnColorChanged(); - } - - EditorGUIUtility.labelWidth = oldLabelWidth; - EditorGUIUtility.fieldWidth = oldFieldWidth; - } - - void DoExposureSlider() - { - var oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = - EditorStyles.label.CalcSize(Styles.exposureValue).x - + EditorStyles.label.margin.right; - - var sliderPosition = GUILayoutUtility.GetRect(0f, EditorGUIUtility.singleLineHeight); - - EditorGUI.BeginChangeCheck(); - var exposureValue = EditorGUI.Slider( - sliderPosition, Styles.exposureValue, m_Color.exposureValue, -m_ExposureSliderMax, m_ExposureSliderMax, float.MinValue, float.MaxValue - ); - if (EditorGUI.EndChangeCheck()) - { - m_Color.exposureValue = exposureValue; - OnColorChanged(); - } - - EditorGUIUtility.labelWidth = oldLabelWidth; - } - - void DoExposureSwatches() - { - var swatchesRect = - GUILayoutUtility.GetRect(GUIContent.none, Styles.exposureSwatch, GUILayout.ExpandWidth(true)); - - var numSwatches = 5; - var swatchRect = new Rect - { - x = swatchesRect.x + (swatchesRect.width - numSwatches * Styles.exposureSwatch.fixedWidth) * 0.5f, - y = swatchesRect.y, - width = Styles.exposureSwatch.fixedWidth, - height = Styles.exposureSwatch.fixedHeight - }; - var backgroundColor = GUI.backgroundColor; - var contentColor = GUI.contentColor; - for (int i = 0; i < numSwatches; ++i) - { - var stop = i - numSwatches / 2; - var col = (m_Color.exposureAdjustedColor * Mathf.Pow(2f, stop)).gamma; - col.a = 1f; - GUI.backgroundColor = col; - GUI.contentColor = VisionUtility.ComputePerceivedLuminance(col) < Styles.highLuminanceThreshold ? - Styles.lowLuminanceContentColor : Styles.highLuminanceContentColor; - - if ( - GUI.Button( - swatchRect, - GUIContent.Temp(stop == 0 ? null : (stop < 0 ? stop.ToString() : string.Format("+{0}", stop))), - Styles.exposureSwatch - ) - ) - { - m_Color.exposureValue = - Mathf.Clamp(m_Color.exposureValue + stop, -m_ExposureSliderMax, m_ExposureSliderMax); - OnColorChanged(); - } - - if (stop == 0 && Event.current.type == EventType.Repaint) - { - GUI.backgroundColor = GUI.contentColor; - Styles.selectedExposureSwatchStroke.Draw(swatchRect, false, false, false, false); - } - - swatchRect.x += swatchRect.width; - } - GUI.backgroundColor = backgroundColor; - GUI.contentColor = contentColor; - } - - void DoPresetsGUI() - { - var foldoutRect = GUILayoutUtility.GetRect(Styles.presetsToggle, EditorStyles.foldout); - foldoutRect.xMax -= 17f; // make room for presets settings menu button - m_ShowPresets = EditorGUI.Foldout(foldoutRect, m_ShowPresets, Styles.presetsToggle, true); - - if (m_ShowPresets) - { - GUILayout.Space(-(EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing)); // pull up to reuse space - var presetsRect = GUILayoutUtility.GetRect(0, Mathf.Clamp(m_ColorLibraryEditor.contentHeight, 20f, 250f)); - m_ColorLibraryEditor.OnGUI(presetsRect, color); - } - } - - void OnGUI() - { - InitializePresetsLibraryIfNeeded(); - - EventType type = Event.current.type; - - if (type == EventType.ExecuteCommand) - { - switch (Event.current.commandName) - { - case EventCommandNames.EyeDropperUpdate: - Repaint(); - break; - case EventCommandNames.EyeDropperClicked: - m_ColorBoxMode = ColorBoxMode.HSV; - Color col = EyeDropper.GetLastPickedColor(); - if (m_HDR) - col = col.linear; - m_Color.SetColorChannelHdr(RgbaChannel.R, col.r); - m_Color.SetColorChannelHdr(RgbaChannel.G, col.g); - m_Color.SetColorChannelHdr(RgbaChannel.B, col.b); - m_Color.SetColorChannelHdr(RgbaChannel.A, col.a); - OnColorChanged(); - break; - case EventCommandNames.EyeDropperCancelled: - OnEyedropperCancelled(); - break; - } - } - - Rect contentRect = EditorGUILayout.BeginVertical(Styles.background); - - // Setup layout values - float innerContentWidth = EditorGUILayout.GetControlRect(false, 1, EditorStyles.numberField).width; - EditorGUIUtility.labelWidth = innerContentWidth - Styles.sliderTextFieldWidth; - EditorGUIUtility.fieldWidth = Styles.sliderTextFieldWidth; - - GUILayout.Space(10); - DoColorSwatchAndEyedropper(); - - GUILayout.Space(10); - - DoColorSpaceGUI(); - - GUILayout.Space(10); - - DoColorSliders(innerContentWidth); - DoHexField(innerContentWidth); - GUILayout.Space(Styles.extraVerticalSpacing); - - if (m_HDR) - { - DoExposureSlider(); - GUILayout.Space(Styles.extraVerticalSpacing); - DoExposureSwatches(); - GUILayout.Space(Styles.extraVerticalSpacing); - } - - DoPresetsGUI(); - - // Call last to ensure we only use the copy paste events if no - // other controls wants to use these events - HandleCopyPasteEvents(); - - EditorGUILayout.EndVertical(); - - if (contentRect.height > 0 && Event.current.type == EventType.Repaint) - { - SetHeight(contentRect.height); - } - - if (Event.current.type == EventType.KeyDown) - { - switch (Event.current.keyCode) - { - case KeyCode.Escape: - // eyedropper GUIView never gets keyboard focus from ColorPicker, so esc to exit it must be handled here - if (m_ColorBoxMode == ColorBoxMode.EyeDropper) - { - EyeDropper.End(); - OnEyedropperCancelled(); - } - else - { - Undo.RevertAllDownToGroup(m_ModalUndoGroup); - m_Color.Reset(); - OnColorChanged(false); - Close(); - GUIUtility.ExitGUI(); - } - break; - case KeyCode.Return: - case KeyCode.KeypadEnter: - Close(); - break; - } - } - - // Remove keyfocus when clicked outside any control - if ((Event.current.type == EventType.MouseDown && Event.current.button != 1) || Event.current.type == EventType.ContextClick) - { - GUIUtility.keyboardControl = 0; - Repaint(); - } - } - - void OnEyedropperCancelled() - { - Repaint(); - m_ColorBoxMode = ColorBoxMode.HSV; - } - - void SetHeight(float newHeight) - { - if (newHeight == position.height) - return; - minSize = new Vector2(Styles.fixedWindowWidth, newHeight); - maxSize = new Vector2(Styles.fixedWindowWidth, newHeight); - } - - void HandleCopyPasteEvents() - { - Event evt = Event.current; - switch (evt.type) - { - case EventType.ValidateCommand: - switch (evt.commandName) - { - case EventCommandNames.Copy: - case EventCommandNames.Paste: - evt.Use(); - break; - } - break; - - case EventType.ExecuteCommand: - switch (evt.commandName) - { - case EventCommandNames.Copy: - ColorClipboard.SetColor(color); - evt.Use(); - break; - - case EventCommandNames.Paste: - Color colorFromClipboard; - if (ColorClipboard.TryGetColor(m_HDR, out colorFromClipboard)) - { - // Do not change alpha if color field is not showing alpha - if (!m_ShowAlpha) - colorFromClipboard.a = m_Color.GetColorChannelNormalized(RgbaChannel.A); - - SetColor(colorFromClipboard); - - GUI.changed = true; - evt.Use(); - } - break; - } - break; - } - } - - static Texture2D s_LeftGradientTexture; - static Texture2D s_RightGradientTexture; - - public static Texture2D GetGradientTextureWithAlpha1To0() - { - return s_LeftGradientTexture ?? (s_LeftGradientTexture = CreateGradientTexture("ColorPicker_1To0_Gradient", 4, 4, new Color(1, 1, 1, 1), new Color(1, 1, 1, 0))); - } - - public static Texture2D GetGradientTextureWithAlpha0To1() - { - return s_RightGradientTexture ?? (s_RightGradientTexture = CreateGradientTexture("ColorPicker_0To1_Gradient", 4, 4, new Color(1, 1, 1, 0), new Color(1, 1, 1, 1))); - } - - static Texture2D CreateGradientTexture(string name, int width, int height, Color leftColor, Color rightColor) - { - var texture = new Texture2D(width, height, TextureFormat.RGBA32, false, true); - texture.name = name; - texture.hideFlags = HideFlags.HideAndDontSave; - var pixels = new Color[width * height]; - - for (int i = 0; i < width; i++) - { - Color columnColor = Color.Lerp(leftColor, rightColor, i / (float)(width - 1)); - for (int j = 0; j < height; j++) - pixels[j * width + i] = columnColor; - } - - texture.SetPixels(pixels); - texture.wrapMode = TextureWrapMode.Clamp; - texture.Apply(); - return texture; - } - - void OnColorChanged(bool exitGUI = true) - { - m_OldAlpha = -1f; - m_ColorSpaceBoxDirty = true; - m_ExposureSliderMax = Mathf.Max(m_ExposureSliderMax, m_Color.exposureValue); - if (m_DelegateView != null) - { - var e = EditorGUIUtility.CommandEvent(EventCommandNames.ColorPickerChanged); - if (!m_IsOSColorPicker) - Repaint(); - m_DelegateView.SendEvent(e); - if (!m_IsOSColorPicker && exitGUI) - GUIUtility.ExitGUI(); - } - if (m_ColorChangedCallback != null) - { - m_ColorChangedCallback(color); - } - } - - private void SetColor(Color c) - { - if (m_IsOSColorPicker) - OSColorPicker.color = c; - else - { - m_Color.SetColorChannelHdr(RgbaChannel.R, c.r); - m_Color.SetColorChannelHdr(RgbaChannel.G, c.g); - m_Color.SetColorChannelHdr(RgbaChannel.B, c.b); - m_Color.SetColorChannelHdr(RgbaChannel.A, c.a); - OnColorChanged(); - Repaint(); - } - } - - public static void Show(GUIView viewToUpdate, Color col, bool showAlpha = true, bool hdr = false) - { - Show(viewToUpdate, null, col, showAlpha, hdr); - } - - public static void Show(Action colorChangedCallback, Color col, bool showAlpha = true, bool hdr = false) - { - Show(null, colorChangedCallback, col, showAlpha, hdr); - } - - static void Show(GUIView viewToUpdate, Action colorChangedCallback, Color col, bool showAlpha, bool hdr) - { - var cp = instance; - cp.m_HDR = hdr; - cp.m_Color = new ColorMutator(col); - cp.m_ShowAlpha = showAlpha; - cp.m_DelegateView = viewToUpdate; - cp.m_ColorChangedCallback = colorChangedCallback; - cp.m_ModalUndoGroup = Undo.GetCurrentGroup(); - cp.m_ExposureSliderMax = Mathf.Max(cp.m_ExposureSliderMax, cp.m_Color.exposureValue); - originalKeyboardControl = GUIUtility.keyboardControl; - - if (cp.m_HDR) - { - cp.m_IsOSColorPicker = false; - cp.m_SliderMode = (SliderMode)EditorPrefs.GetInt(k_SliderModeHDRPrefKey, (int)SliderMode.RGB); - } - - if (cp.m_IsOSColorPicker) - OSColorPicker.Show(showAlpha); - else - { - cp.titleContent = hdr ? EditorGUIUtility.TrTextContent("HDR Color") : EditorGUIUtility.TrTextContent("Color"); - float height = EditorPrefs.GetInt(k_HeightPrefKey, (int)cp.position.height); - cp.minSize = new Vector2(Styles.fixedWindowWidth, height); - cp.maxSize = new Vector2(Styles.fixedWindowWidth, height); - cp.InitializePresetsLibraryIfNeeded(); // Ensure the heavy lifting of loading presets is done before window is visible - cp.ShowAuxWindow(); - } - } - - void PollOSColorPicker() - { - if (m_IsOSColorPicker) - { - if (!OSColorPicker.visible || Application.platform != RuntimePlatform.OSXEditor) - { - DestroyImmediate(this); - } - else - { - Color c = OSColorPicker.color; - if (m_Color.color != c) - { - m_Color.SetColorChannel(RgbaChannel.R, c.r); - m_Color.SetColorChannel(RgbaChannel.G, c.g); - m_Color.SetColorChannel(RgbaChannel.B, c.b); - m_Color.SetColorChannel(RgbaChannel.A, c.a); - OnColorChanged(); - } - } - } - } - - void OnEnable() - { - hideFlags = HideFlags.DontSave; - m_IsOSColorPicker = EditorPrefs.GetBool("UseOSColorPicker"); - hideFlags = HideFlags.DontSave; - EditorApplication.update += PollOSColorPicker; - EditorGUIUtility.editingTextField = true; // To fix that color values is not directly editable when tabbing (case 557510) - - m_SliderMode = (SliderMode)EditorPrefs.GetInt(k_SliderModePrefKey, (int)SliderMode.RGB); - m_ShowPresets = EditorPrefs.GetInt(k_ShowPresetsPrefKey, 1) != 0; - } - - void OnDisable() - { - EditorPrefs.SetInt(m_HDR ? k_SliderModeHDRPrefKey : k_SliderModePrefKey, (int)m_SliderMode); - EditorPrefs.SetInt(k_ShowPresetsPrefKey, m_ShowPresets ? 1 : 0); - EditorPrefs.SetInt(k_HeightPrefKey, (int)position.height); - } - - public void OnDestroy() - { - Undo.CollapseUndoOperations(m_ModalUndoGroup); - - if (m_ColorSlider) - DestroyImmediate(m_ColorSlider); - if (m_ColorBox) - DestroyImmediate(m_ColorBox); - if (m_RTexture) - DestroyImmediate(m_RTexture); - if (m_GTexture) - DestroyImmediate(m_GTexture); - if (m_BTexture) - DestroyImmediate(m_BTexture); - if (m_HueTexture) - DestroyImmediate(m_HueTexture); - if (m_SatTexture) - DestroyImmediate(m_SatTexture); - if (m_ValTexture) - DestroyImmediate(m_ValTexture); - if (m_AlphaTexture) - DestroyImmediate(m_AlphaTexture); - s_Instance = null; - if (m_IsOSColorPicker) - OSColorPicker.Close(); - - EditorApplication.update -= PollOSColorPicker; - - if (m_ColorLibraryEditorState != null) - m_ColorLibraryEditorState.TransferEditorPrefsState(false); - - if (m_ColorLibraryEditor != null) - m_ColorLibraryEditor.UnloadUsedLibraries(); - - GUIUtility.keyboardControl = originalKeyboardControl; - originalKeyboardControl = 0; - } - } - - internal class EyeDropper : GUIView - { - const int kPixelSize = 10; - const int kDummyWindowSize = 8192; - internal static Color s_LastPickedColor; - GUIView m_DelegateView; - Texture2D m_Preview; - static EyeDropper s_Instance; - private static Vector2 s_PickCoordinates = Vector2.zero; - private bool m_Focused = false; - private Action m_ColorPickedCallback; - - public static void Start(GUIView viewToUpdate, bool stealFocus = true) - { - Start(viewToUpdate, null, stealFocus); - } - - public static void Start(Action colorPickedCallback, bool stealFocus = true) - { - Start(null, colorPickedCallback, stealFocus); - } - - static void Start(GUIView viewToUpdate, Action colorPickedCallback, bool stealFocus) - { - instance.m_DelegateView = viewToUpdate; - instance.m_ColorPickedCallback = colorPickedCallback; - ContainerWindow win = CreateInstance(); - win.m_DontSaveToLayout = true; - win.title = "EyeDropper"; - win.hideFlags = HideFlags.DontSave; - win.rootView = instance; - win.Show(ShowMode.PopupMenu, true, false); - instance.AddToAuxWindowList(); - win.SetInvisible(); - instance.SetMinMaxSizes(new Vector2(0, 0), new Vector2(kDummyWindowSize, kDummyWindowSize)); - win.position = new Rect(-kDummyWindowSize / 2, -kDummyWindowSize / 2, kDummyWindowSize, kDummyWindowSize); - instance.wantsMouseMove = true; - instance.StealMouseCapture(); - if (stealFocus) - instance.Focus(); - } - - public static void End() - { - if (s_Instance != null) - s_Instance.window.Close(); - } - - static EyeDropper instance - { - get - { - if (!s_Instance) - CreateInstance(); - return s_Instance; - } - } - - EyeDropper() - { - s_Instance = this; - } - - public static Color GetPickedColor() - { - return InternalEditorUtility.ReadScreenPixel(s_PickCoordinates, 1, 1)[0]; - } - - public static Color GetLastPickedColor() - { - return s_LastPickedColor; - } - - static class Styles - { - public static readonly GUIStyle eyeDropperHorizontalLine = "EyeDropperHorizontalLine"; - public static readonly GUIStyle eyeDropperVerticalLine = "EyeDropperVerticalLine"; - public static readonly GUIStyle eyeDropperPickedPixel = "EyeDropperPickedPixel"; - } - - public static void DrawPreview(Rect position) - { - if (Event.current.type != EventType.Repaint) - return; - - Texture2D preview = instance.m_Preview; - int width = (int)Mathf.Ceil(position.width / kPixelSize); - int height = (int)Mathf.Ceil(position.height / kPixelSize); - if (preview == null) - { - instance.m_Preview = preview = ColorPicker.MakeTexture(width, height); - preview.filterMode = FilterMode.Point; - } - if (preview.width != width || preview.height != height) - { - preview.Resize(width, height); - } - - Vector2 p = GUIUtility.GUIToScreenPoint(Event.current.mousePosition); - Vector2 mPos = p - new Vector2((width / 2), (height / 2)); - preview.SetPixels(InternalEditorUtility.ReadScreenPixel(mPos, width, height), 0); - preview.Apply(true); - - Graphics.DrawTexture(position, preview); - - // Draw grid on top - float xStep = position.width / width; - GUIStyle sep = Styles.eyeDropperVerticalLine; - for (float x = position.x; x < position.xMax; x += xStep) - { - Rect r = new Rect(Mathf.Round(x), position.y, xStep, position.height); - sep.Draw(r, false, false, false, false); - } - - float yStep = position.height / height; - sep = Styles.eyeDropperHorizontalLine; - for (float y = position.y; y < position.yMax; y += yStep) - { - Rect r = new Rect(position.x, Mathf.Floor(y), position.width, yStep); - sep.Draw(r, false, false, false, false); - } - - // Draw selected pixelSize - Rect newR = new Rect((p.x - mPos.x) * xStep + position.x, (p.y - mPos.y) * yStep + position.y, xStep, yStep); - Styles.eyeDropperPickedPixel.Draw(newR, false, false, false, false); - } - - protected override void OldOnGUI() - { - // On mouse move/click we remember screen coordinates where we are. Then we'll use that - // in GetPickedColor to read. The reason is that because GetPickedColor might be called from - // an event which is different, so the coordinates would be already wrong. - switch (Event.current.type) - { - case EventType.MouseMove: - s_PickCoordinates = GUIUtility.GUIToScreenPoint(Event.current.mousePosition); - StealMouseCapture(); - SendEvent(EventCommandNames.EyeDropperUpdate, true, false); - break; - case EventType.MouseDown: - if (Event.current.button == 0) - { - s_PickCoordinates = GUIUtility.GUIToScreenPoint(Event.current.mousePosition); - // We have to close helper window before we read color from screen. On Win - // the window covers whole desktop (see Show()) and is black with 0x01 alpha value. - // That might cause invalid picked color. - window.Close(); - s_LastPickedColor = GetPickedColor(); - Event.current.Use(); - SendEvent(EventCommandNames.EyeDropperClicked, true); - if (m_ColorPickedCallback != null) - { - m_ColorPickedCallback(s_LastPickedColor); - } - } - break; - case EventType.KeyDown: - if (Event.current.keyCode == KeyCode.Escape) - { - window.Close(); - Event.current.Use(); - SendEvent(EventCommandNames.EyeDropperCancelled, true); - } - break; - } - } - - void SendEvent(string eventName, bool exitGUI, bool focusOther = true) - { - if (m_DelegateView != null) - { - var e = EditorGUIUtility.CommandEvent(eventName); - if (focusOther) - m_DelegateView.Focus(); - m_DelegateView.SendEvent(e); - if (exitGUI) - GUIUtility.ExitGUI(); - } - } - - public new void OnDestroy() - { - if (m_Preview) - DestroyImmediate(m_Preview); - - if (!m_Focused) - { - // Window closed before it was focused - SendEvent(EventCommandNames.EyeDropperCancelled, false); - } - - base.OnDestroy(); - } - - protected override bool OnFocus() - { - m_Focused = true; - return base.OnFocus(); - } - } -} diff --git a/Editor/Mono/GUI/ColorPicker.deprecated.cs b/Editor/Mono/GUI/ColorPicker.deprecated.cs deleted file mode 100644 index a50d78b3d9..0000000000 --- a/Editor/Mono/GUI/ColorPicker.deprecated.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [Serializable, Obsolete] - public class ColorPickerHDRConfig - { - public float minBrightness; - public float maxBrightness; - public float minExposureValue; - public float maxExposureValue; - - public ColorPickerHDRConfig( - float minBrightness, float maxBrightness, float minExposureValue, float maxExposureValue - ) - { - this.minBrightness = minBrightness; - this.maxBrightness = maxBrightness; - this.minExposureValue = minExposureValue; - this.maxExposureValue = maxExposureValue; - } - } -} diff --git a/Editor/Mono/GUI/ColumnView.cs b/Editor/Mono/GUI/ColumnView.cs deleted file mode 100644 index cdbd9b54de..0000000000 --- a/Editor/Mono/GUI/ColumnView.cs +++ /dev/null @@ -1,329 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - internal class ColumnViewElement - { - public string name; - public object value; - - public ColumnViewElement(string name, object value) - { - this.name = name; - this.value = value; - } - } - - internal class ColumnView - { - public class Styles - { - public GUIStyle background = "OL Box"; - public GUIStyle selected = "PR Label"; - - // TODO: Make a proper style. - public Texture2D categoryArrowIcon = EditorStyles.foldout.normal.background; - } - - private static Styles s_Styles; - private readonly List m_ListViewStates; - private readonly List m_CachedSelectedIndices; - private Vector2 m_ScrollPosition; - private string m_SearchText = string.Empty; - - public string searchText - { - get { return m_SearchText; } - } - - public bool isSearching - { - get { return searchText != string.Empty; } - } - - public float columnWidth = 150f; - public int minimumNumberOfColumns = 1; - private int m_ColumnToFocusKeyboard = -1; - - public delegate void ObjectColumnFunction(object value); - public delegate object ObjectColumnGetDataFunction(object value); - - public ColumnView() - { - m_ListViewStates = new List(); - m_CachedSelectedIndices = new List(); - } - - private static void InitStyles() - { - if (s_Styles == null) - s_Styles = new Styles(); - } - - public void SetSelected(int column, int selectionIndex) - { - if (m_ListViewStates.Count == column) - m_ListViewStates.Add(new ListViewState()); - - if (m_CachedSelectedIndices.Count == column) - m_CachedSelectedIndices.Add(-1); - - m_CachedSelectedIndices[column] = selectionIndex; - m_ListViewStates[column].row = selectionIndex; - } - - public void SetKeyboardFocusColumn(int column) - { - m_ColumnToFocusKeyboard = column; - } - - public void OnGUI(List elements, ObjectColumnFunction previewColumnFunction) - { - OnGUI(elements, previewColumnFunction, null, null, null); - } - - public void OnGUI(List elements, ObjectColumnFunction previewColumnFunction, ObjectColumnFunction selectedSearchItemFunction, ObjectColumnFunction selectedRegularItemFunction, ObjectColumnGetDataFunction getDataForDraggingFunction) - { - InitStyles(); - m_ScrollPosition = GUILayout.BeginScrollView(m_ScrollPosition); - GUILayout.BeginHorizontal(); - - var columnElements = elements; - object selectedObject; - int listViewIndex = 0; - - do - { - if (m_ListViewStates.Count == listViewIndex) - m_ListViewStates.Add(new ListViewState()); - - if (m_CachedSelectedIndices.Count == listViewIndex) - m_CachedSelectedIndices.Add(-1); - - var listView = m_ListViewStates[listViewIndex]; - listView.totalRows = columnElements.Count; - - if (listViewIndex == 0) - GUILayout.BeginVertical(GUILayout.MaxWidth(columnWidth)); - - int selectedIndex = m_CachedSelectedIndices[listViewIndex]; - selectedIndex = DoListColumn(listView, columnElements, listViewIndex, selectedIndex, - listViewIndex == 0 ? selectedSearchItemFunction : null, selectedRegularItemFunction, - getDataForDraggingFunction); - - if (Event.current.type == EventType.Layout && m_ColumnToFocusKeyboard == listViewIndex) - { - m_ColumnToFocusKeyboard = -1; - GUIUtility.keyboardControl = listView.ID; - if (listView.row == -1 && columnElements.Count != 0) - selectedIndex = listView.row = 0; - } - - if (listViewIndex == 0) - { - // pass some of the keys to the list view, even if something else is active - if (isSearching) - { - var keyCode = StealImportantListviewKeys(); - if (keyCode != KeyCode.None) - ListViewShared.SendKey(m_ListViewStates[0], keyCode); - } - - m_SearchText = EditorGUILayout.ToolbarSearchField(m_SearchText); - GUILayout.EndVertical(); - } - - if (selectedIndex >= columnElements.Count) - selectedIndex = -1; - - if (Event.current.type == EventType.Layout && m_CachedSelectedIndices[listViewIndex] != selectedIndex && - m_ListViewStates.Count > listViewIndex + 1) - { - int from = listViewIndex + 1; - int range = m_ListViewStates.Count - (listViewIndex + 1); - m_ListViewStates.RemoveRange(from, range); - m_CachedSelectedIndices.RemoveRange(from, range); - } - - m_CachedSelectedIndices[listViewIndex] = selectedIndex; - - selectedObject = selectedIndex > -1 ? columnElements[selectedIndex].value : null; - - columnElements = selectedObject as List; - listViewIndex++; - } - while (columnElements != null); - - for (; listViewIndex < minimumNumberOfColumns; listViewIndex++) - { - DoDummyColumn(); - } - - DoPreviewColumn(selectedObject, previewColumnFunction); - - GUILayout.EndHorizontal(); - GUILayout.EndScrollView(); - } - - private static void DoItemSelectedEvent(ObjectColumnFunction selectedRegularItemFunction, object value) - { - if (selectedRegularItemFunction != null) - selectedRegularItemFunction(value); - Event.current.Use(); - } - - private void DoSearchItemSelectedEvent(ObjectColumnFunction selectedSearchItemFunction, object value) - { - m_SearchText = string.Empty; - DoItemSelectedEvent(selectedSearchItemFunction, value); - } - - private void DoDummyColumn() - { - // TODO: Don't know why this width needs one more pixel to match the list views. Bug in ScrollViews? - GUILayout.Box(GUIContent.none, s_Styles.background, GUILayout.Width(columnWidth + 1)); - } - - private static void DoPreviewColumn(object selectedObject, ObjectColumnFunction previewColumnFunction) - { - GUILayout.BeginVertical(s_Styles.background); - if (previewColumnFunction != null) - previewColumnFunction(selectedObject); - GUILayout.EndVertical(); - } - - private int DoListColumn(ListViewState listView, List columnViewElements, int columnIndex, int selectedIndex, ObjectColumnFunction selectedSearchItemFunction, ObjectColumnFunction selectedRegularItemFunction, ObjectColumnGetDataFunction getDataForDraggingFunction) - { - if (Event.current.type == EventType.KeyDown && - Event.current.keyCode == KeyCode.Return && listView.row > -1) - { - if (isSearching && selectedSearchItemFunction != null) - DoSearchItemSelectedEvent(selectedSearchItemFunction, columnViewElements[selectedIndex].value); - if (!isSearching && GUIUtility.keyboardControl == listView.ID && selectedRegularItemFunction != null) - DoItemSelectedEvent(selectedRegularItemFunction, columnViewElements[selectedIndex].value); - } - - if (GUIUtility.keyboardControl == listView.ID && Event.current.type == EventType.KeyDown && !isSearching) - { - switch (Event.current.keyCode) - { - case KeyCode.LeftArrow: - m_ColumnToFocusKeyboard = columnIndex - 1; - Event.current.Use(); - break; - case KeyCode.RightArrow: - m_ColumnToFocusKeyboard = columnIndex + 1; - Event.current.Use(); - break; - } - } - - foreach (ListViewElement element in ListViewGUILayout.ListView(listView, s_Styles.background, GUILayout.Width(columnWidth))) - { - var columnViewElement = columnViewElements[element.row]; - - if (element.row == listView.row) - { - if (Event.current.type == EventType.Repaint) - { - // FIXME: One Pixel offset is required when using OL Box style. Use a different style. - var rect = element.position; - rect.x++; - rect.y++; - - s_Styles.selected.Draw(rect, false, true, true, GUIUtility.keyboardControl == listView.ID); - } - } - - GUILayout.Label(columnViewElement.name); - - if (columnViewElement.value is List) - { - // TODO: Make a proper style. - var arrowRect = element.position; - arrowRect.x = arrowRect.xMax - s_Styles.categoryArrowIcon.width - 5; - arrowRect.y += 2; - GUI.Label(arrowRect, s_Styles.categoryArrowIcon); - } - - DoDoubleClick(element, columnViewElement, selectedSearchItemFunction, selectedRegularItemFunction); - DoDragAndDrop(listView, element, columnViewElements, getDataForDraggingFunction); - } - - if (Event.current.type == EventType.Layout) - selectedIndex = listView.row; - - return selectedIndex; - } - - private static void DoDragAndDrop(ListViewState listView, ListViewElement element, List columnViewElements, ObjectColumnGetDataFunction getDataForDraggingFunction) - { - if (GUIUtility.hotControl == listView.ID && Event.current.type == EventType.MouseDown && - element.position.Contains(Event.current.mousePosition) && - Event.current.button == 0) - { - var delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), listView.ID); - delay.mouseDownPosition = Event.current.mousePosition; - } - - if (GUIUtility.hotControl == listView.ID && - Event.current.type == EventType.MouseDrag && - GUIClip.visibleRect.Contains(Event.current.mousePosition)) - { - var delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), listView.ID); - - if (delay.CanStartDrag()) - { - var data = getDataForDraggingFunction == null ? null : - getDataForDraggingFunction(columnViewElements[listView.row].value); - - if (data == null) - return; - - DragAndDrop.PrepareStartDrag(); - - DragAndDrop.paths = null; - - DragAndDrop.SetGenericData("CustomDragData", data); - DragAndDrop.StartDrag(columnViewElements[listView.row].name); - - Event.current.Use(); - } - } - } - - private void DoDoubleClick(ListViewElement element, ColumnViewElement columnViewElement, ObjectColumnFunction selectedSearchItemFunction, ObjectColumnFunction selectedRegularItemFunction) - { - if (Event.current.type == EventType.MouseDown && - element.position.Contains(Event.current.mousePosition) && - Event.current.button == 0 && Event.current.clickCount == 2) - { - if (isSearching) - DoSearchItemSelectedEvent(selectedSearchItemFunction, columnViewElement.value); - else - DoItemSelectedEvent(selectedRegularItemFunction, columnViewElement.value); - } - } - - private static KeyCode StealImportantListviewKeys() - { - if (Event.current.type == EventType.KeyDown) - { - var key = Event.current.keyCode; - if (key == KeyCode.UpArrow || key == KeyCode.DownArrow || key == KeyCode.PageUp || key == KeyCode.PageDown) - { - Event.current.Use(); - return key; - } - } - - return KeyCode.None; - } - } -} diff --git a/Editor/Mono/GUI/CreateAssetUtility.cs b/Editor/Mono/GUI/CreateAssetUtility.cs deleted file mode 100644 index c33f28754c..0000000000 --- a/Editor/Mono/GUI/CreateAssetUtility.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using UnityEditor.ProjectWindowCallback; -using UnityEngine; - - -namespace UnityEditor -{ - [System.Serializable] - internal class CreateAssetUtility - { - [SerializeField] - EndNameEditAction m_EndAction; - [SerializeField] - int m_InstanceID; - [SerializeField] - string m_Path = ""; - [SerializeField] - Texture2D m_Icon; - [SerializeField] - string m_ResourceFile; - - public void Clear() - { - m_EndAction = null; - m_InstanceID = 0; - m_Path = ""; - m_Icon = null; - m_ResourceFile = ""; - } - - public int instanceID - { - get { return m_InstanceID; } - } - - public Texture2D icon - { - get { return m_Icon; } - } - - public string folder - { - get { return Path.GetDirectoryName(m_Path); } - } - - public string extension - { - get { return Path.GetExtension(m_Path); } - } - - public string originalName - { - get { return Path.GetFileNameWithoutExtension(m_Path); } - } - - public EndNameEditAction endAction - { - get { return m_EndAction; } - } - - static bool IsPathDataValid(string filePath) - { - // Ensure some path - if (string.IsNullOrEmpty(filePath)) - return false; - - // Ensure valid folder to place the asset in - string folder = Path.GetDirectoryName(filePath); - int instanceID = AssetDatabase.GetMainAssetInstanceID(folder); - return instanceID != 0; - } - - // Selection changes when calling BeginNewAsset if it succeeds - public bool BeginNewAssetCreation(int instanceID, EndNameEditAction newAssetEndAction, string filePath, Texture2D icon, string newAssetResourceFile) - { - string uniquePath; - if (!filePath.StartsWith("assets/", System.StringComparison.CurrentCultureIgnoreCase)) - { - uniquePath = AssetDatabase.GetUniquePathNameAtSelectedPath(filePath); - } - else - { - uniquePath = AssetDatabase.GenerateUniqueAssetPath(filePath); - } - - if (!IsPathDataValid(uniquePath)) - { - Debug.LogErrorFormat("Invalid generated unique path '{0}' (input path '{1}')", uniquePath, filePath); - Clear(); - return false; - } - - m_InstanceID = instanceID; - m_Path = uniquePath; - m_Icon = icon; - m_EndAction = newAssetEndAction; - m_ResourceFile = newAssetResourceFile; - - // Change selection to none or instanceID - Selection.activeObject = EditorUtility.InstanceIDToObject(instanceID); - return true; - } - - // The asset is created here - public void EndNewAssetCreation(string name) - { - string path = folder + "/" + name + extension; - EndNameEditAction endAction = m_EndAction; - int instanceID = m_InstanceID; - string resourceFile = m_ResourceFile; - Clear(); // Ensure clear if anything goes bad in EndNameEditAction and gui is exited. - - ProjectWindowUtil.EndNameEditAction(endAction, instanceID, path, resourceFile); - } - - public bool IsCreatingNewAsset() - { - return !string.IsNullOrEmpty(m_Path); - } - } -} // end namespace UnityEditor diff --git a/Editor/Mono/GUI/DockArea.cs b/Editor/Mono/GUI/DockArea.cs deleted file mode 100644 index f2aa28b132..0000000000 --- a/Editor/Mono/GUI/DockArea.cs +++ /dev/null @@ -1,850 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using UnityEditorInternal; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleEnums; - -namespace UnityEditor -{ - internal class DockArea : HostView, IDropArea - { - internal const float kTabHeight = 17; - internal const float kDockHeight = 39; - const float kSideBorders = 2.0f; - const float kBottomBorders = 2.0f; - const float kWindowButtonsWidth = 40.0f; // Context & Lock Inspector Buttons - - // Which pane window would we drop the currently dragged pane over - static int s_PlaceholderPos; - // Which pane is currently being dragged around - static EditorWindow s_DragPane; - // Where did it come from - internal static DockArea s_OriginalDragSource; - - // Mouse coords when we started the drag (used to figure out when we should trigger a drag) - static Vector2 s_StartDragPosition; - // Are we dragging yet? - static int s_DragMode; - // 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) - static internal View s_IgnoreDockingForView = null; - - static DropInfo s_DropInfo = null; - - [SerializeField] - internal List m_Panes = new List(); - [SerializeField] - internal int m_Selected; - [SerializeField] - internal int m_LastSelected; - - [NonSerialized] - internal GUIStyle tabStyle = null; - - bool m_IsBeingDestroyed; - - public int selected - { - get { return m_Selected; } - set - { - if (m_Selected != value) - m_LastSelected = m_Selected; - m_Selected = value; - if (m_Selected >= 0 && m_Selected < m_Panes.Count) - actualView = m_Panes[m_Selected]; - } - } - - public DockArea() - { - if (m_Panes != null && m_Panes.Count != 0) - Debug.LogError("m_Panes is filled in DockArea constructor."); - } - - void RemoveNullWindows() - { - List result = new List(); - foreach (EditorWindow i in m_Panes) - { - if (i != null) - result.Add(i); - } - m_Panes = result; - } - - protected override void OnDestroy() - { - // Prevents double-destroy that may be indirectly caused if Close() is called by OnLostFocus() - m_IsBeingDestroyed = true; - - if (hasFocus) - Invoke("OnLostFocus"); - - actualView = null; - - // Since m_Panes can me modified indirectly by OnDestroy() callbacks, make a copy of it for safe iteration - var windows = new List(m_Panes); - - foreach (EditorWindow w in windows) - { - // Avoid destroying a window that has already being destroyed (case 967778) - if (w == null) - continue; - UnityEngine.Object.DestroyImmediate(w, true); - } - - m_Panes.Clear(); - - base.OnDestroy(); - } - - protected override void OnEnable() - { - if (m_Panes != null) - { - if (m_Panes.Count == 0) - m_Selected = 0; - else - { - // before fix for case 840151, it is possible that out of range selected index was serialized (e.g., case 846859) - m_Selected = Math.Min(m_Selected, m_Panes.Count - 1); - actualView = m_Panes[m_Selected]; - } - } - - base.OnEnable(); - - imguiContainer.name = VisualElementUtils.GetUniqueName("Dockarea"); - } - - protected override void UpdateViewMargins(EditorWindow view) - { - base.UpdateViewMargins(view); - - if (view == null) - return; - - RectOffset margins = GetBorderSize(); - - IStyle style = view.rootVisualContainer.style; - style.positionTop = margins.top; - style.positionBottom = margins.bottom; - style.positionLeft = margins.left; - style.positionRight = margins.right; - style.positionType = PositionType.Absolute; - } - - public void AddTab(EditorWindow pane) - { - AddTab(m_Panes.Count, pane); - } - - public void AddTab(int idx, EditorWindow pane) - { - DeregisterSelectedPane(true); - m_Panes.Insert(idx, pane); - selected = idx; - - var sp = parent as SplitView; - if (sp) - sp.Reflow(); - - Repaint(); - } - - public void RemoveTab(EditorWindow pane) { RemoveTab(pane, true); } - public void RemoveTab(EditorWindow pane, bool killIfEmpty) - { - if (actualView == pane) - DeregisterSelectedPane(true); - int idx = m_Panes.IndexOf(pane); - if (idx == -1) - return; // Pane is not in the window - - m_Panes.Remove(pane); - - // Fixup last selected index - if (idx == m_LastSelected) - m_LastSelected = m_Panes.Count - 1; - else if (idx < m_LastSelected || m_LastSelected == m_Panes.Count) - --m_LastSelected; - - m_LastSelected = Mathf.Clamp(m_LastSelected, 0, m_Panes.Count - 1); - - // Fixup selected index - if (idx == m_Selected) - m_Selected = m_LastSelected; - else - m_Selected = m_Panes.IndexOf(actualView); - - if (m_Selected >= 0 && m_Selected < m_Panes.Count) - actualView = m_Panes[m_Selected]; - - Repaint(); - pane.m_Parent = null; - if (killIfEmpty) - KillIfEmpty(); - RegisterSelectedPane(); - } - - void KillIfEmpty() - { - // if we're empty, remove ourselves - if (m_Panes.Count != 0) - return; - - if (parent == null) - { - window.InternalCloseWindow(); - return; - } - - SplitView sw = parent as SplitView; - ICleanuppable p = parent as ICleanuppable; - sw.RemoveChildNice(this); - - if (!m_IsBeingDestroyed) - DestroyImmediate(this, true); - - if (p != null) - p.Cleanup(); - } - - Rect tabRect { get { return new Rect(0, 0, position.width, kTabHeight); } } - - public DropInfo DragOver(EditorWindow window, Vector2 mouseScreenPosition) - { - Rect r = screenPosition; - r.height = kDockHeight; - if (r.Contains(mouseScreenPosition)) - { - if (background == null) - background = "hostview"; - Rect scr = background.margin.Remove(screenPosition); - Vector2 pos = mouseScreenPosition - new Vector2(scr.x, scr.y); - - Rect tr = tabRect; - int mPos = GetTabAtMousePos(pos, tr); - float w = GetTabWidth(tr.width); - - if (s_PlaceholderPos != mPos) - { - Repaint(); - s_PlaceholderPos = mPos; - } - - DropInfo di = new DropInfo(this); - di.type = DropInfo.Type.Tab; - di.rect = new Rect(pos.x - w * .25f + scr.x, tr.y + scr.y, w, tr.height); - - return di; - } - return null; - } - - public bool PerformDrop(EditorWindow w, DropInfo info, Vector2 screenPos) - { - s_OriginalDragSource.RemoveTab(w, s_OriginalDragSource != this); - int pos2 = s_PlaceholderPos > m_Panes.Count ? m_Panes.Count : s_PlaceholderPos; - AddTab(pos2, w); - selected = pos2; - return true; - } - - protected override void OldOnGUI() - { - ClearBackground(); - // Call reset GUI state as first thing so GUI.color is correct when drawing window decoration. - EditorGUIUtility.ResetGUIState(); - - // Exit if the window was destroyed after entering play mode or on domain-reload. - if (window == null) - return; - - // Add CursorRects - SplitView sp = parent as SplitView; - - if (Event.current.type == EventType.Repaint && sp) - { - View view = this; - while (sp) - { - int id = sp.controlID; - - if (id == GUIUtility.hotControl || GUIUtility.hotControl == 0) - { - int idx = sp.IndexOfChild(view); - if (sp.vertical) - { - if (idx != 0) - EditorGUIUtility.AddCursorRect(new Rect(0, 0, position.width, SplitView.kGrabDist), MouseCursor.SplitResizeUpDown, id); - if (idx != sp.children.Length - 1) - EditorGUIUtility.AddCursorRect( - new Rect(0, position.height - SplitView.kGrabDist, position.width, SplitView.kGrabDist), - MouseCursor.SplitResizeUpDown, id); - } - else // horizontal - { - if (idx != 0) - EditorGUIUtility.AddCursorRect(new Rect(0, 0, SplitView.kGrabDist, position.height), MouseCursor.SplitResizeLeftRight, - id); - if (idx != sp.children.Length - 1) - EditorGUIUtility.AddCursorRect( - new Rect(position.width - SplitView.kGrabDist, 0, SplitView.kGrabDist, position.height), - MouseCursor.SplitResizeLeftRight, id); - } - } - - view = sp; - sp = sp.parent as SplitView; - } - - // reset - sp = parent as SplitView; - } - bool customBorder = false; - if (window.rootView.GetType() != typeof(MainView)) - { - customBorder = true; - if (windowPosition.y == 0) - background = "dockareaStandalone"; - else - background = "dockarea"; - } - else - background = "dockarea"; - - if (sp) - { - Event e = new Event(Event.current); - e.mousePosition += new Vector2(position.x, position.y); - sp.SplitGUI(e); - if (e.type == EventType.Used) - Event.current.Use(); - } - Rect r = background.margin.Remove(new Rect(0, 0, position.width, position.height)); - r.x = background.margin.left; - r.y = background.margin.top; - Rect wPos = windowPosition; - float sideBorder = kSideBorders; - if (wPos.x == 0) - { - r.x -= sideBorder; - r.width += sideBorder; - } - if (wPos.xMax == window.position.width) - { - r.width += sideBorder; - } - - if (wPos.yMax == window.position.height) - { - r.height += customBorder ? 2f : kBottomBorders; - } - - if (Event.current.type == EventType.Repaint) - { - background.Draw(r, GUIContent.none, 0); - } - - if (tabStyle == null) - tabStyle = "dragtab"; - - if (m_Panes.Count > 0) - { - // Set up the pane's position, so its GUI can use this - - // Contents: - // scroll it by -1, -1 so we top & left 1px gets culled (they are drawn already by the us, so we want to - // not have them here (thing that the default skin relies on) - BeginOffsetArea(new Rect(r.x + 2, r.y + kTabHeight, r.width - 4, r.height - kTabHeight - 2), GUIContent.none, "TabWindowBackground"); - - Vector2 basePos = GUIUtility.GUIToScreenPoint(Vector2.zero); - Rect p = borderSize.Remove(position); - p.x = basePos.x; - p.y = basePos.y; - - if (selected >= 0 && selected < m_Panes.Count) - { - m_Panes[selected].m_Pos = p; - } - - EndOffsetArea(); - } - - DragTab(new Rect(r.x + 1, r.y, r.width - kWindowButtonsWidth, kTabHeight), tabStyle); - - // TODO: Make this nice - right now this is meant to be overridden by Panes in Layout if they want something else. Inspector does this - tabStyle = "dragtab"; - - ShowGenericMenu(); - - if (m_Panes.Count > 0) - { - InvokeOnGUI(r); - } - - EditorGUI.ShowRepaints(); - Highlighter.ControlHighlightGUI(this); - } - - protected override void SetActualViewPosition(Rect newPos) - { - //Sit down and let me tell you the intent of this. - //the position property should return the "usable" dimension of the window - //In the case of DockArea i not the whole window, because we reserve some space on the top for the - //window tabs. Because of that we want to report a DockArea.position that does not contain the height of that bar. - //This is exactly what we try to do here, remove the tab area from the rect passed in. - //Note that this code path so far is only used when the HostView, SplitView, or any "parent" view changes its dimentions and - //tries to propagate that to its "children" - //There are other code paths that also set the Dockarea.position, that won't go through here. - //But its important that they all return the same values. - var adjustedDockAreaClientRect = borderSize.Remove(newPos); - base.SetActualViewPosition(adjustedDockAreaClientRect); - } - - void Maximize(object userData) - { - EditorWindow window = userData as EditorWindow; - if (window != null) - { - WindowLayout.Maximize(window); - } - } - - internal void Close(object userData) - { - EditorWindow window = userData as EditorWindow; - if (window != null) - { - window.Close(); - } - else - { - RemoveTab(null, false); - KillIfEmpty(); - } - } - - private bool AllowTabAction() - { - int mainWindowPaneCount = 0; - - ContainerWindow w = ContainerWindow.windows.First(e => e.showMode == ShowMode.MainWindow); - if (w != null) - { - foreach (View view in w.rootView.allChildren) - { - DockArea da = view as DockArea; - if (da != null) - { - mainWindowPaneCount += da.m_Panes.Count; - if (mainWindowPaneCount > 1) return true; - } - } - } - - return false; - } - - protected override void AddDefaultItemsToMenu(GenericMenu menu, EditorWindow view) - { - base.AddDefaultItemsToMenu(menu, view); - - if (parent.window.showMode == ShowMode.MainWindow) - menu.AddItem(EditorGUIUtility.TrTextContent("Maximize"), !(parent is SplitView), Maximize, view); - else - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Maximize")); - - bool closeAllowed = (window.showMode != ShowMode.MainWindow || AllowTabAction()); - if (closeAllowed) - menu.AddItem(EditorGUIUtility.TrTextContent("Close Tab"), false, Close, view); - else - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Close Tab")); - menu.AddSeparator(""); - - System.Type[] types = GetPaneTypes(); - GUIContent baseContent = EditorGUIUtility.TrTextContent("Add Tab"); - foreach (System.Type t in types) - { - if (t == null) - continue; - - GUIContent entry = new GUIContent(EditorWindow.GetLocalizedTitleContentFromType(t)); // make a copy since we modify the text below - entry.text = baseContent.text + "/" + entry.text; - menu.AddItem(entry, false, AddTabToHere, t); - } - } - - void AddTabToHere(object userData) - { - EditorWindow win = (EditorWindow)CreateInstance((System.Type)userData); - AddTab(win); - } - - float GetTabWidth(float width) - { - int count = m_Panes.Count; - if (s_DropInfo != null && System.Object.ReferenceEquals(s_DropInfo.dropArea, this)) - count++; - if (m_Panes.IndexOf(s_DragPane) != -1) - count--; - - return Mathf.Min(width / count, 100); - } - - int GetTabAtMousePos(Vector2 mousePos, Rect position) - { - int sel = (int)Mathf.Min((mousePos.x - position.xMin) / GetTabWidth(position.width), 100); - return sel; - } - - // Hack to get around Unity crashing when we have circular references in saved stuff - internal override void Initialize(ContainerWindow win) - { - base.Initialize(win); - RemoveNullWindows(); - foreach (EditorWindow i in m_Panes) - i.m_Parent = this; - } - - static void CheckDragWindowExists() - { - if (s_DragMode == 1 && !PaneDragTab.get.m_Window) - { - s_OriginalDragSource.RemoveTab(s_DragPane); - DestroyImmediate(s_DragPane); - PaneDragTab.get.Close(); - GUIUtility.hotControl = 0; - ResetDragVars(); - } - } - - void DragTab(Rect pos, GUIStyle tabStyle) - { - int id = GUIUtility.GetControlID(FocusType.Passive); - float elemWidth = GetTabWidth(pos.width); - - Event evt = Event.current; - - // Detect if hotcontrol was cleared while dragging (happens when pressing Esc). - // We do not listen for the Escape keydown event because it is sent to the dragged window (not this dockarea) - if (s_DragMode != 0 && GUIUtility.hotControl == 0) - { - PaneDragTab.get.Close(); - ResetDragVars(); - } - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (pos.Contains(evt.mousePosition) && GUIUtility.hotControl == 0) - { - int sel = GetTabAtMousePos(evt.mousePosition, pos); - if (sel < m_Panes.Count) - { - switch (evt.button) - { - case 0: - if (sel != selected) - selected = sel; - - GUIUtility.hotControl = id; - s_StartDragPosition = evt.mousePosition; - s_DragMode = 0; - evt.Use(); - break; - case 2: - m_Panes[sel].Close(); - evt.Use(); - break; - } - } - } - break; - case EventType.ContextClick: - if (pos.Contains(evt.mousePosition) && GUIUtility.hotControl == 0) - { - int sel = GetTabAtMousePos(evt.mousePosition, pos); - if (sel < m_Panes.Count) - PopupGenericMenu(m_Panes[sel], new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0)); - } - - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - Vector2 delta = evt.mousePosition - s_StartDragPosition; - evt.Use(); - Rect screenRect = screenPosition; - - // if we're not tabdragging yet, check to see if we should start - - // check if we're allowed to drag tab - bool dragAllowed = (window.showMode != ShowMode.MainWindow || AllowTabAction()); - - if (s_DragMode == 0 && delta.sqrMagnitude > 99 && dragAllowed) - { - s_DragMode = 1; - s_PlaceholderPos = selected; - s_DragPane = m_Panes[selected]; - - // 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 - if (m_Panes.Count == 1) - s_IgnoreDockingForView = this; - else - s_IgnoreDockingForView = null; - - s_OriginalDragSource = this; - PaneDragTab.get.Show( - new Rect(pos.x + screenRect.x + elemWidth * selected, pos.y + screenRect.y, elemWidth, pos.height), - s_DragPane.titleContent, - position.size, - GUIUtility.GUIToScreenPoint(evt.mousePosition) - ); - EditorApplication.update += CheckDragWindowExists; - // We just showed a window. Exit the GUI because the window might be - // repainting already (esp. on Windows) - GUIUtility.ExitGUI(); - } - if (s_DragMode == 1) - { - // Go over all container windows, ask them to dock the window. - DropInfo di = null; - ContainerWindow[] windows = ContainerWindow.windows; - Vector2 screenMousePos = GUIUtility.GUIToScreenPoint(evt.mousePosition); - ContainerWindow win = null; - foreach (ContainerWindow w in windows) - { - var rootSplitView = w.rootSplitView; - if (rootSplitView == null) - continue; - - di = rootSplitView.DragOverRootView(screenMousePos); - - if (di == null) - { - foreach (View view in w.rootView.allChildren) - { - IDropArea ida = view as IDropArea; - if (ida != null) - di = ida.DragOver(s_DragPane, screenMousePos); - - if (di != null) - break; - } - } - - if (di != null) - { - win = w; - break; - } - } - // Ok, we couldn't find anything, let's create a simplified DropIn - if (di == null) - { - di = new DropInfo(null); - } - - if (di.type != DropInfo.Type.Tab) - s_PlaceholderPos = -1; - - s_DropInfo = di; - - // Handle the window getting closed mid-drag - if (PaneDragTab.get.m_Window) - PaneDragTab.get.SetDropInfo(di, screenMousePos, win); - } - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - Vector2 screenMousePos = GUIUtility.GUIToScreenPoint(evt.mousePosition); - if (s_DragMode != 0) - { - // This is where we want to insert it. - s_DragMode = 0; - PaneDragTab.get.Close(); - EditorApplication.update -= CheckDragWindowExists; - - // Try to tell the current DPZ - if (s_DropInfo != null && s_DropInfo.dropArea != null) - { - s_DropInfo.dropArea.PerformDrop(s_DragPane, s_DropInfo, screenMousePos); - } - else - { - EditorWindow w = s_DragPane; - - ResetDragVars(); - - RemoveTab(w); - Rect wPos = w.position; - wPos.x = screenMousePos.x - wPos.width * .5f; - wPos.y = screenMousePos.y - wPos.height * .5f; - - // don't put windows top outside of the screen, on mac OS handles this - if (Application.platform == RuntimePlatform.WindowsEditor) - wPos.y = Mathf.Max(InternalEditorUtility.GetBoundsOfDesktopAtPoint(screenMousePos).y, wPos.y); - - EditorWindow.CreateNewWindowForEditorWindow(w, false, false); - - w.position = w.m_Parent.window.FitWindowRectToScreen(wPos, true, true); - - GUIUtility.hotControl = 0; - GUIUtility.ExitGUI(); - } - ResetDragVars(); - } - GUIUtility.hotControl = 0; - evt.Use(); - } - - break; - - case EventType.Repaint: - float xPos = pos.xMin; - int drawNum = 0; - if (actualView) - { - for (int i = 0; i < m_Panes.Count; i++) - { - // if we're dragging the tab we're about to draw, don't do that (handled by some window) - if (s_DragPane == m_Panes[i]) - continue; - - // If we need space for inserting a tab here, skip some horizontal - if (s_DropInfo != null && System.Object.ReferenceEquals(s_DropInfo.dropArea, this) && s_PlaceholderPos == drawNum) - xPos += elemWidth; - - Rect r = new Rect(xPos, pos.yMin, elemWidth, pos.height); - float roundR = Mathf.Round(r.x); - Rect r2 = new Rect(roundR, r.y, Mathf.Round(r.x + r.width) - roundR, r.height); - tabStyle.Draw(r2, m_Panes[i].titleContent, false, false, i == selected, hasFocus); - xPos += elemWidth; - drawNum++; - } - } - else - { - Rect r = new Rect(xPos, pos.yMin, elemWidth, pos.height); - float roundR = Mathf.Round(r.x); - Rect r2 = new Rect(roundR, r.y, Mathf.Round(r.x + r.width) - roundR, r.height); - tabStyle.Draw(r2, "Failed to load", false, false, true, false); - } - break; - } - selected = Mathf.Clamp(selected, 0, m_Panes.Count - 1); - } - - protected override RectOffset GetBorderSize() - { - if (!window) - return m_BorderSize; - - // Reset - m_BorderSize.left = m_BorderSize.right = m_BorderSize.top = m_BorderSize.bottom = 0; - - Rect r = windowPosition; - if (r.xMin != 0) - m_BorderSize.left += (int)kSideBorders; - if (r.xMax != window.position.width) - { - m_BorderSize.right += (int)kSideBorders; - } - - const int mainWindowTopAdjustment = 2; - const int floatingWindowTopAdjustment = 5; - m_BorderSize.top = (int)kTabHeight + (window != null && window.showMode != ShowMode.MainWindow ? floatingWindowTopAdjustment : mainWindowTopAdjustment); - m_BorderSize.bottom = (window != null && window.showMode != ShowMode.MainWindow ? 0 : (int)kBottomBorders); - - return m_BorderSize; - } - - static void ResetDragVars() - { - s_DragPane = null; - s_DropInfo = null; - s_PlaceholderPos = -1; - s_DragMode = 0; - s_OriginalDragSource = null; - } - } - - internal class MaximizedHostView : HostView - { - protected override void OldOnGUI() - { - ClearBackground(); - // Call reset GUI state as first thing so GUI.color is correct when drawing window decoration. - EditorGUIUtility.ResetGUIState(); - - Rect r = new Rect(-2, 0, position.width + 4, position.height); - background = "dockarea"; - r = background.margin.Remove(r); - Rect backRect = new Rect(r.x + 1, r.y, r.width - 2, DockArea.kTabHeight); - if (Event.current.type == EventType.Repaint) - { - background.Draw(r, GUIContent.none, false, false, false, false); - GUIStyle s = "dragTab"; - s.Draw(backRect, actualView.titleContent, false, false, true, hasFocus); - } - - if (Event.current.type == EventType.ContextClick && backRect.Contains(Event.current.mousePosition)) - { - PopupGenericMenu(actualView, new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 0, 0)); - } - ShowGenericMenu(); - if (actualView) - actualView.m_Pos = borderSize.Remove(screenPosition); - - InvokeOnGUI(r); - } - - protected override RectOffset GetBorderSize() - { - m_BorderSize.left = 0; - m_BorderSize.right = 0; - m_BorderSize.top = (int)DockArea.kTabHeight; - // Aras: I don't really know why, but this makes GUI be actually correct. - m_BorderSize.bottom = 4; - - return m_BorderSize; - } - - void Unmaximize(object userData) - { - EditorWindow ew = ((EditorWindow)userData); - WindowLayout.Unmaximize(ew); - } - - protected override void AddDefaultItemsToMenu(GenericMenu menu, EditorWindow window) - { - base.AddDefaultItemsToMenu(menu, window); - - menu.AddItem(EditorGUIUtility.TrTextContent("Maximize"), !(parent is SplitView), Unmaximize, window); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Close Tab")); - menu.AddSeparator(""); - System.Type[] types = GetPaneTypes(); - - GUIContent baseContent = EditorGUIUtility.TrTextContent("Add Tab"); - foreach (System.Type t in types) - { - if (t == null) - continue; - - GUIContent entry = new GUIContent(EditorWindow.GetLocalizedTitleContentFromType(t)); // make a copy since we modify the text below - entry.text = baseContent.text + "/" + entry.text; - menu.AddDisabledItem(entry); - } - } - } -} // namespace diff --git a/Editor/Mono/GUI/DragRect.cs b/Editor/Mono/GUI/DragRect.cs deleted file mode 100644 index 76c2387805..0000000000 --- a/Editor/Mono/GUI/DragRect.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - class DragRectGUI - { - static int dragRectHash = "DragRect".GetHashCode(); - static int s_DragCandidateState = 0; - static float s_DragSensitivity = 1.0f; - - public static int DragRect(Rect position, int value, int minValue, int maxValue) - { - Event evt = Event.current; - - int id = GUIUtility.GetControlID(dragRectHash, FocusType.Passive, position); - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (position.Contains(evt.mousePosition) && evt.button == 0) - { - GUIUtility.hotControl = id; - s_DragCandidateState = 1; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && s_DragCandidateState != 0) - { - GUIUtility.hotControl = 0; - s_DragCandidateState = 0; - evt.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - switch (s_DragCandidateState) - { - case 1: - value += (int)(HandleUtility.niceMouseDelta * s_DragSensitivity); - GUI.changed = true; - evt.Use(); - - if (value < minValue) - value = minValue; - else if (value > maxValue) - value = maxValue; - break; - } - } - break; - case EventType.Repaint: - EditorGUIUtility.AddCursorRect(position, MouseCursor.SlideArrow); - break; - } - - return value; - } - } -} diff --git a/Editor/Mono/GUI/EditorApplicationLayout.cs b/Editor/Mono/GUI/EditorApplicationLayout.cs deleted file mode 100644 index 4277a830c6..0000000000 --- a/Editor/Mono/GUI/EditorApplicationLayout.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.IO; -using UnityEditorInternal; - -// Description: -// EditorApplicationLayout handles the GUI when playmode changes (on a high level). - -// When entering playmode the flow is as follows (also see Application::SetIsPlaying() for actual loading): -// 1) Calling InitPlaymodeLayout prepares the main gameView WITHOUT rendering it. Sets it up, maximizes it if needed and intitializes its size. -// 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)) -// 3) Calling FinalizePlaymodeLayout finalizes and renders maximized window (if set). - - -namespace UnityEditor -{ - internal class EditorApplicationLayout - { - static private GameView m_GameView = null; - static private bool m_MaximizePending = false; - - - static internal bool IsInitializingPlaymodeLayout() - { - return m_GameView != null; - } - - static internal void SetPlaymodeLayout() - { - InitPlaymodeLayout(); - FinalizePlaymodeLayout(); - } - - static internal void SetStopmodeLayout() - { - WindowLayout.ShowAppropriateViewOnEnterExitPlaymode(false); - Toolbar.RepaintToolbar(); - } - - static internal void SetPausemodeLayout() - { - // We use the stopmode layout when pausing (maximized windows are unmaximized) - SetStopmodeLayout(); - } - - static internal void InitPlaymodeLayout() - { - m_GameView = WindowLayout.ShowAppropriateViewOnEnterExitPlaymode(true) as GameView; - if (m_GameView == null) - return; - - if (m_GameView.maximizeOnPlay) - { - DockArea da = m_GameView.m_Parent as DockArea; - - if (da != null) - m_MaximizePending = WindowLayout.MaximizePrepare(da.actualView); - } - - // Mark this game view as the start gameview so the backend - // can set size and mouseoffset properly for this game view - m_GameView.m_Parent.SetAsStartView(); - - Toolbar.RepaintToolbar(); - } - - static internal void FinalizePlaymodeLayout() - { - if (m_GameView != null) - { - if (m_MaximizePending) - WindowLayout.MaximizePresent(m_GameView); - - m_GameView.m_Parent.ClearStartView(); - } - - Clear(); - } - - static private void Clear() - { - m_MaximizePending = false; - m_GameView = null; - } - } -} // namespace diff --git a/Editor/Mono/GUI/EditorCache.cs b/Editor/Mono/GUI/EditorCache.cs deleted file mode 100644 index 9c5ae5190b..0000000000 --- a/Editor/Mono/GUI/EditorCache.cs +++ /dev/null @@ -1,173 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using UnityEditor; - -namespace UnityEditor -{ - [System.Flags] - internal enum EditorFeatures - { - None = 0, - PreviewGUI = 1, - OnSceneDrag = 4 - } - - internal class EditorWrapper : System.IDisposable - { - Editor editor; - - public delegate void VoidDelegate(SceneView sceneView); - - public VoidDelegate OnSceneDrag; - - public bool HasPreviewGUI() { return editor.HasPreviewGUI(); } - public void OnPreviewSettings() { editor.OnPreviewSettings(); } - public void OnPreviewGUI(Rect position, GUIStyle background) { editor.OnPreviewGUI(position, background); } - public void OnInteractivePreviewGUI(Rect r, GUIStyle background) { if (editor != null) editor.OnInteractivePreviewGUI(r, background); } - internal void OnAssetStoreInspectorGUI() { if (editor != null) editor.OnAssetStoreInspectorGUI(); } - public string GetInfoString() { return editor.GetInfoString(); } - - private EditorWrapper() {} - - static public EditorWrapper Make(Object obj, EditorFeatures requirements) - { - EditorWrapper cp = new EditorWrapper(); - if (cp.Init(obj, requirements)) - return cp; - else - { - cp.Dispose(); - return null; - } - } - - private bool Init(Object obj, EditorFeatures requirements) - { - MethodInfo onSceneDragMi; - - editor = Editor.CreateEditor(obj); - if (editor == null) - return false; - - if ((int)(requirements & EditorFeatures.PreviewGUI) > 0 && !editor.HasPreviewGUI()) - return false; - - System.Type t = editor.GetType(); - - onSceneDragMi = t.GetMethod("OnSceneDrag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - if (onSceneDragMi != null) - OnSceneDrag = (VoidDelegate)System.Delegate.CreateDelegate(typeof(VoidDelegate), editor, onSceneDragMi); - else if ((int)(requirements & EditorFeatures.OnSceneDrag) > 0) - return false; - else - OnSceneDrag = DefaultOnSceneDrag; - - return true; - } - - private void DefaultOnSceneDrag(SceneView sceneView) {} - - public string name - { - get { return editor.target.name; } - } - - public void Dispose() - { - if (editor != null) - { - OnSceneDrag = null; - - UnityEngine.Object.DestroyImmediate(editor); - editor = null; - } - - System.GC.SuppressFinalize(this); - } - - ~EditorWrapper() - { - Debug.LogError("Failed to dispose EditorWrapper."); - } - } - - internal class EditorCache : System.IDisposable - { - Dictionary m_EditorCache; - Dictionary m_UsedEditors; - EditorFeatures m_Requirements; - - public EditorCache() : this(EditorFeatures.None) {} - - - public EditorCache(EditorFeatures requirements) - { - m_Requirements = requirements; - m_EditorCache = new Dictionary(); - m_UsedEditors = new Dictionary(); - } - - public EditorWrapper this[Object o] - { - get - { - m_UsedEditors[o] = true; - if (m_EditorCache.ContainsKey(o)) - return m_EditorCache[o]; - - EditorWrapper w = EditorWrapper.Make(o, m_Requirements); - - - return m_EditorCache[o] = w; - } - } - - public void CleanupUntouchedEditors() - { - List toDelete = new List(); - foreach (Object key in m_EditorCache.Keys) - { - if (!m_UsedEditors.ContainsKey(key)) - toDelete.Add(key); - } - - if (m_EditorCache != null) - { - foreach (Object key in toDelete) - { - EditorWrapper ew = m_EditorCache[key]; - m_EditorCache.Remove(key); - - if (ew == null) - continue; - ew.Dispose(); - } - } - - m_UsedEditors.Clear(); - } - - public void CleanupAllEditors() - { - m_UsedEditors.Clear(); - CleanupUntouchedEditors(); - } - - public void Dispose() - { - CleanupAllEditors(); - System.GC.SuppressFinalize(this); - } - - ~EditorCache() - { - Debug.LogError("Failed to dispose EditorCache."); - } - } -} // namespace diff --git a/Editor/Mono/GUI/EditorGUIContents.cs b/Editor/Mono/GUI/EditorGUIContents.cs deleted file mode 100644 index a38d282d45..0000000000 --- a/Editor/Mono/GUI/EditorGUIContents.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Reflection; - -namespace UnityEditor -{ - public sealed partial class EditorGUI - { - // Common GUIContents used for EditorGUI controls. - internal sealed class GUIContents - { - // The settings dropdown icon top right in a component - [IconName("_Popup")] - internal static GUIContent titleSettingsIcon { get; private set; } - - // The help icon in a component - [IconName("_Help")] - internal static GUIContent helpIcon { get; private set; } - - // We use a static constructor to lazily initialize all static properties. This is useful because changed image files can then - // be picked up on assembly reload. - static GUIContents() - { - // Run through each static property and initialize it using the - // filename provided in the IconName Attribute. - PropertyInfo[] propertyInfos = typeof(GUIContents).GetProperties(System.Reflection.BindingFlags.Static | BindingFlags.NonPublic); - foreach (PropertyInfo property in propertyInfos) - { - IconName[] iconNames = (IconName[])property.GetCustomAttributes(typeof(IconName), false); - if (iconNames.Length > 0) - { - string name = iconNames[0].name; - GUIContent content = EditorGUIUtility.IconContent(name); - property.SetValue(null, content, null); - } - } - } - - private class IconName : System.Attribute - { - private string m_Name; - - public IconName(string name) - { - this.m_Name = name; - } - - public virtual string name - { - get { return m_Name; } - } - } - } - } -} diff --git a/Editor/Mono/GUI/EditorGUIInternal.cs b/Editor/Mono/GUI/EditorGUIInternal.cs deleted file mode 100644 index 34ada98357..0000000000 --- a/Editor/Mono/GUI/EditorGUIInternal.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using ICSharpCode.NRefactory.Ast; -using UnityEngine; -using System.Collections.Generic; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - //@todo This should be handled through friend assemblies instead - internal sealed class EditorGUIInternal : GUI - { - // Choose how toggles appear when showing mixed values - static internal GUIStyle mixedToggleStyle - { - get { return s_MixedToggleStyle; } - set { s_MixedToggleStyle = value; } - } - - private static GUIStyle s_MixedToggleStyle = EditorStyles.toggleMixed; - - static internal Rect GetTooltipRect() { return tooltipRect; } - static internal string GetMouseTooltip() { return mouseTooltip; } - internal static bool DoToggleForward(Rect position, int id, bool value, GUIContent content, GUIStyle style) - { - Event evt = Event.current; - - // Toggle selected toggle on space or return key - if (evt.MainActionKeyForControl(id)) - { - value = !value; - evt.Use(); - GUI.changed = true; - } - - if (EditorGUI.showMixedValue) - style = mixedToggleStyle; - - // Ignore mouse clicks that are not with the primary (left) mouse button so those can be grabbed by other things later. - EventType origType = evt.type; - bool nonLeftClick = (evt.type == EventType.MouseDown && evt.button != 0); - if (nonLeftClick) - evt.type = EventType.Ignore; - bool returnValue = DoToggle(position, id, EditorGUI.showMixedValue ? false : value, content, style.m_Ptr); - if (nonLeftClick) - evt.type = origType; - else if (evt.type != origType) - EditorGUIUtility.keyboardControl = id; // If control used event, give it keyboard focus. - return returnValue; - } - - internal static Vector2 DoBeginScrollViewForward(Rect position, Vector2 scrollPosition, Rect viewRect, bool alwaysShowHorizontal, bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background) - { - return DoBeginScrollView(position, scrollPosition, viewRect, alwaysShowHorizontal, alwaysShowVertical, horizontalScrollbar, verticalScrollbar, background); - } - - internal static void BeginWindowsForward(int skinMode, int editorWindowInstanceID) - { - BeginWindows(skinMode, editorWindowInstanceID); - } - - internal static void AssetPopup(SerializedProperty serializedProperty, GUIContent content, string fileExtension) where T : Object, new() - { - AssetPopup(serializedProperty, content, fileExtension, "Default"); - } - - internal static void AssetPopup(SerializedProperty serializedProperty, GUIContent content, string fileExtension, string defaultFieldName) where T : Object, new() - { - AssetPopupBackend.AssetPopup(serializedProperty, content, fileExtension, defaultFieldName); - } - } - - //@todo This should be handled through friend assemblies instead - internal sealed class EditorGUILayoutUtilityInternal : GUILayoutUtility - { - internal new static GUILayoutGroup BeginLayoutArea(GUIStyle style, System.Type LayoutType) - { - return GUILayoutUtility.DoBeginLayoutArea(style, LayoutType); - } - - internal new static GUILayoutGroup topLevel - { - get { return GUILayoutUtility.topLevel; } - } - } -} diff --git a/Editor/Mono/GUI/EditorStyles.cs b/Editor/Mono/GUI/EditorStyles.cs deleted file mode 100644 index 80e9234ef4..0000000000 --- a/Editor/Mono/GUI/EditorStyles.cs +++ /dev/null @@ -1,418 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -// See Style Guide in wiki for more information on editor styles. - -namespace UnityEditor -{ - // Common GUIStyles used for EditorGUI controls. - public sealed partial class EditorStyles - { - // Style used for the labelled on all EditorGUI overloads that take a prefix label - public static GUIStyle label { get { return s_Current.m_Label; } } - internal GUIStyle m_Label; - - // Style for label with small font. - public static GUIStyle miniLabel { get { return s_Current.m_MiniLabel; } } - private GUIStyle m_MiniLabel; - - // Style for label with large font. - public static GUIStyle largeLabel { get { return s_Current.m_LargeLabel; } } - private GUIStyle m_LargeLabel; - - // Style for bold label. - public static GUIStyle boldLabel { get { return s_Current.m_BoldLabel; } } - private GUIStyle m_BoldLabel; - - // Style for mini bold label. - public static GUIStyle miniBoldLabel { get { return s_Current.m_MiniBoldLabel; } } - private GUIStyle m_MiniBoldLabel; - - // Style for centered grey mini label. - public static GUIStyle centeredGreyMiniLabel { get { return s_Current.m_CenteredGreyMiniLabel; } } - private GUIStyle m_CenteredGreyMiniLabel; - - // Style for word wrapped mini label. - public static GUIStyle wordWrappedMiniLabel { get { return s_Current.m_WordWrappedMiniLabel; } } - private GUIStyle m_WordWrappedMiniLabel; - - // Style for word wrapped label. - public static GUIStyle wordWrappedLabel { get { return s_Current.m_WordWrappedLabel; } } - private GUIStyle m_WordWrappedLabel; - - // Style for link label. - internal static GUIStyle linkLabel { get { return s_Current.m_LinkLabel; } } - private GUIStyle m_LinkLabel; - - - // Style for white label. - public static GUIStyle whiteLabel { get { return s_Current.m_WhiteLabel; } } - private GUIStyle m_WhiteLabel; - - // Style for white mini label. - public static GUIStyle whiteMiniLabel { get { return s_Current.m_WhiteMiniLabel; } } - private GUIStyle m_WhiteMiniLabel; - - // Style for white large label. - public static GUIStyle whiteLargeLabel { get { return s_Current.m_WhiteLargeLabel; } } - private GUIStyle m_WhiteLargeLabel; - - // Style for white bold label. - public static GUIStyle whiteBoldLabel { get { return s_Current.m_WhiteBoldLabel; } } - private GUIStyle m_WhiteBoldLabel; - - // Style used for a radio button - public static GUIStyle radioButton { get { return s_Current.m_RadioButton; } } - private GUIStyle m_RadioButton; - - // Style used for a standalone small button. - public static GUIStyle miniButton { get { return s_Current.m_MiniButton; } } - private GUIStyle m_MiniButton; - - // Style used for the leftmost button in a horizontal button group. - public static GUIStyle miniButtonLeft { get { return s_Current.m_MiniButtonLeft; } } - private GUIStyle m_MiniButtonLeft; - - // Style used for the middle buttons in a horizontal group. - public static GUIStyle miniButtonMid { get { return s_Current.m_MiniButtonMid; } } - private GUIStyle m_MiniButtonMid; - - // Style used for the rightmost button in a horizontal group. - public static GUIStyle miniButtonRight { get { return s_Current.m_MiniButtonRight; } } - private GUIStyle m_MiniButtonRight; - - // Style used for EditorGUI::ref::TextField - public static GUIStyle textField { get { return s_Current.m_TextField; } } - internal GUIStyle m_TextField; - - // Style used for EditorGUI::ref::TextArea - public static GUIStyle textArea { get { return s_Current.m_TextArea; } } - internal GUIStyle m_TextArea; - - // Smaller text field - public static GUIStyle miniTextField { get { return s_Current.m_MiniTextField; } } - private GUIStyle m_MiniTextField; - - // Style used for field editors for numbers - public static GUIStyle numberField { get { return s_Current.m_NumberField; } } - private GUIStyle m_NumberField; - - // Style used for EditorGUI::ref::Popup, EditorGUI::ref::EnumPopup, - public static GUIStyle popup { get { return s_Current.m_Popup; } } - private GUIStyle m_Popup; - - // Style used for headings for structures (Vector3, Rect, etc) - [System.Obsolete("structHeadingLabel is deprecated, use EditorStyles.label instead.")] - public static GUIStyle structHeadingLabel { get { return s_Current.m_Label; } } - - // Style used for headings for object fields. - public static GUIStyle objectField { get { return s_Current.m_ObjectField; } } - private GUIStyle m_ObjectField; - - // Style used for headings for the Select button in object fields. - public static GUIStyle objectFieldThumb { get { return s_Current.m_ObjectFieldThumb; } } - private GUIStyle m_ObjectFieldThumb; - - // Style used for texture object field with minimal height (useful for single line texture objectfields) - public static GUIStyle objectFieldMiniThumb { get { return s_Current.m_ObjectFieldMiniThumb; } } - private GUIStyle m_ObjectFieldMiniThumb; - - // Style used for headings for Color fields. - public static GUIStyle colorField { get { return s_Current.m_ColorField; } } - private GUIStyle m_ColorField; - - // Style used for headings for Layer masks. - public static GUIStyle layerMaskField { get { return s_Current.m_LayerMaskField; } } - private GUIStyle m_LayerMaskField; - - // Style used for headings for EditorGUI::ref::Toggle. - public static GUIStyle toggle {get { return s_Current.m_Toggle; } } - private GUIStyle m_Toggle; - - internal static GUIStyle toggleMixed { get { return s_Current.m_ToggleMixed; } } - private GUIStyle m_ToggleMixed; - - // Style used for headings for EditorGUI::ref::Foldout. - public static GUIStyle foldout { get { return s_Current.m_Foldout; } } - private GUIStyle m_Foldout; - - // Style used for headings for EditorGUI::ref::Foldout. - public static GUIStyle foldoutPreDrop { get { return s_Current.m_FoldoutPreDrop; } } - private GUIStyle m_FoldoutPreDrop; - - // Style used for headings for EditorGUILayout::ref::BeginToggleGroup. - public static GUIStyle toggleGroup { get { return s_Current.m_ToggleGroup; } } - private GUIStyle m_ToggleGroup; - - internal static GUIStyle textFieldDropDown { get { return s_Current.m_TextFieldDropDown; } } - private GUIStyle m_TextFieldDropDown; - - internal static GUIStyle textFieldDropDownText { get { return s_Current.m_TextFieldDropDownText; } } - private GUIStyle m_TextFieldDropDownText; - - - // Standard font. - public static Font standardFont { get { return s_Current.m_StandardFont; } } - internal Font m_StandardFont; - - // Bold font. - public static Font boldFont { get { return s_Current.m_BoldFont; } } - internal Font m_BoldFont; - - // Mini font. - public static Font miniFont { get { return s_Current.m_MiniFont; } } - internal Font m_MiniFont; - - // Mini Bold font. - public static Font miniBoldFont { get { return s_Current.m_MiniBoldFont; } } - internal Font m_MiniBoldFont; - - // Toolbar background from top of windows. - public static GUIStyle toolbar { get { return s_Current.m_Toolbar; } } - private GUIStyle m_Toolbar; - - // Style for Button and Toggles in toolbars. - public static GUIStyle toolbarButton { get { return s_Current.m_ToolbarButton; } } - private GUIStyle m_ToolbarButton; - - // Toolbar Popup - public static GUIStyle toolbarPopup { get { return s_Current.m_ToolbarPopup; } } - private GUIStyle m_ToolbarPopup; - - // Toolbar Dropdown - public static GUIStyle toolbarDropDown { get { return s_Current.m_ToolbarDropDown; } } - private GUIStyle m_ToolbarDropDown; - - // Toolbar text field - public static GUIStyle toolbarTextField { get { return s_Current.m_ToolbarTextField; } } - private GUIStyle m_ToolbarTextField; - - public static GUIStyle inspectorDefaultMargins { get { return s_Current.m_InspectorDefaultMargins; } } - private GUIStyle m_InspectorDefaultMargins; - - public static GUIStyle inspectorFullWidthMargins { get { return s_Current.m_InspectorFullWidthMargins; } } - private GUIStyle m_InspectorFullWidthMargins; - - public static GUIStyle helpBox { get { return s_Current.m_HelpBox; } } - private GUIStyle m_HelpBox; - - internal static GUIStyle toolbarSearchField { get { return s_Current.m_ToolbarSearchField; } } - private GUIStyle m_ToolbarSearchField; - - internal static GUIStyle toolbarSearchFieldPopup { get { return s_Current.m_ToolbarSearchFieldPopup; } } - private GUIStyle m_ToolbarSearchFieldPopup; - - internal static GUIStyle toolbarSearchFieldCancelButton { get { return s_Current.m_ToolbarSearchFieldCancelButton; } } - private GUIStyle m_ToolbarSearchFieldCancelButton; - - internal static GUIStyle toolbarSearchFieldCancelButtonEmpty { get { return s_Current.m_ToolbarSearchFieldCancelButtonEmpty; } } - private GUIStyle m_ToolbarSearchFieldCancelButtonEmpty; - - internal static GUIStyle colorPickerBox { get { return s_Current.m_ColorPickerBox; } } - private GUIStyle m_ColorPickerBox; - - internal static GUIStyle inspectorBig { get { return s_Current.m_InspectorBig; } } - private GUIStyle m_InspectorBig; - - internal static GUIStyle inspectorTitlebar { get { return s_Current.m_InspectorTitlebar; } } - private GUIStyle m_InspectorTitlebar; - - internal static GUIStyle inspectorTitlebarText { get { return s_Current.m_InspectorTitlebarText; } } - private GUIStyle m_InspectorTitlebarText; - - internal static GUIStyle foldoutSelected { get { return s_Current.m_FoldoutSelected; } } - private GUIStyle m_FoldoutSelected; - - internal static GUIStyle iconButton { get { return s_Current.m_IconButton; } } - private GUIStyle m_IconButton; - - // Style for tooltips - internal static GUIStyle tooltip { get { return s_Current.m_Tooltip; } } - private GUIStyle m_Tooltip; - - // Style for notification text. - internal static GUIStyle notificationText { get { return s_Current.m_NotificationText; } } - private GUIStyle m_NotificationText; - - // Style for notification background area. - internal static GUIStyle notificationBackground { get { return s_Current.m_NotificationBackground; } } - private GUIStyle m_NotificationBackground; - - internal static GUIStyle assetLabel { get { return s_Current.m_AssetLabel; } } - private GUIStyle m_AssetLabel; - - internal static GUIStyle assetLabelPartial { get { return s_Current.m_AssetLabelPartial; } } - private GUIStyle m_AssetLabelPartial; - - internal static GUIStyle assetLabelIcon { get { return s_Current.m_AssetLabelIcon; } } - private GUIStyle m_AssetLabelIcon; - - internal static GUIStyle searchField { get { return s_Current.m_SearchField; } } - private GUIStyle m_SearchField; - - internal static GUIStyle searchFieldCancelButton { get { return s_Current.m_SearchFieldCancelButton; } } - private GUIStyle m_SearchFieldCancelButton; - - internal static GUIStyle searchFieldCancelButtonEmpty { get { return s_Current.m_SearchFieldCancelButtonEmpty; } } - private GUIStyle m_SearchFieldCancelButtonEmpty; - - internal static GUIStyle selectionRect { get { return s_Current.m_SelectionRect; } } - private GUIStyle m_SelectionRect; - - internal static GUIStyle minMaxHorizontalSliderThumb { get { return s_Current.m_MinMaxHorizontalSliderThumb; } } - private GUIStyle m_MinMaxHorizontalSliderThumb; - - internal static GUIStyle dropDownList { get { return s_Current.m_DropDownList; } } - private GUIStyle m_DropDownList; - - internal static GUIStyle progressBarBack { get { return s_Current.m_ProgressBarBack; } } - internal static GUIStyle progressBarBar { get { return s_Current.m_ProgressBarBar; } } - internal static GUIStyle progressBarText { get { return s_Current.m_ProgressBarText; } } - private GUIStyle m_ProgressBarBar, m_ProgressBarText, m_ProgressBarBack; - - internal static Vector2 knobSize {get {return s_Current.m_KnobSize; }} - internal static Vector2 miniKnobSize {get {return s_Current.m_MiniKnobSize; }} - private Vector2 m_KnobSize = new Vector2(40, 40); - private Vector2 m_MiniKnobSize = new Vector2(29, 29); - - // the editor styles currently in use - internal static EditorStyles s_Current; - - // the list of editor styles to use - private static EditorStyles[] s_CachedStyles = { null, null }; - - internal static void UpdateSkinCache() - { - UpdateSkinCache(EditorGUIUtility.skinIndex); - } - - internal static void UpdateSkinCache(int skinIndex) - { - // Don't cache the Game GUISkin styles - if (GUIUtility.s_SkinMode == 0) - return; - - if (s_CachedStyles[skinIndex] == null) - { - s_CachedStyles[skinIndex] = new EditorStyles(); - s_CachedStyles[skinIndex].InitSharedStyles(); - } - - s_Current = s_CachedStyles[skinIndex]; - EditorGUIUtility.s_FontIsBold = -1; - EditorGUIUtility.SetBoldDefaultFont(false); - } - - private void InitSharedStyles() - { - m_ColorPickerBox = GetStyle("ColorPickerBox"); - m_InspectorBig = GetStyle("In BigTitle"); - m_MiniLabel = GetStyle("miniLabel"); - m_LargeLabel = GetStyle("LargeLabel"); - m_BoldLabel = GetStyle("BoldLabel"); - m_MiniBoldLabel = GetStyle("MiniBoldLabel"); - m_WordWrappedLabel = GetStyle("WordWrappedLabel"); - m_WordWrappedMiniLabel = GetStyle("WordWrappedMiniLabel"); - m_WhiteLabel = GetStyle("WhiteLabel"); - m_WhiteMiniLabel = GetStyle("WhiteMiniLabel"); - m_WhiteLargeLabel = GetStyle("WhiteLargeLabel"); - m_WhiteBoldLabel = GetStyle("WhiteBoldLabel"); - m_MiniTextField = GetStyle("MiniTextField"); - m_RadioButton = GetStyle("Radio"); - m_MiniButton = GetStyle("miniButton"); - m_MiniButtonLeft = GetStyle("miniButtonLeft"); - m_MiniButtonMid = GetStyle("miniButtonMid"); - m_MiniButtonRight = GetStyle("miniButtonRight"); - m_Toolbar = GetStyle("toolbar"); - m_ToolbarButton = GetStyle("toolbarbutton"); - m_ToolbarPopup = GetStyle("toolbarPopup"); - m_ToolbarDropDown = GetStyle("toolbarDropDown"); - m_ToolbarTextField = GetStyle("toolbarTextField"); - m_ToolbarSearchField = GetStyle("ToolbarSeachTextField"); - m_ToolbarSearchFieldPopup = GetStyle("ToolbarSeachTextFieldPopup"); - m_ToolbarSearchFieldCancelButton = GetStyle("ToolbarSeachCancelButton"); - m_ToolbarSearchFieldCancelButtonEmpty = GetStyle("ToolbarSeachCancelButtonEmpty"); - m_SearchField = GetStyle("SearchTextField"); - m_SearchFieldCancelButton = GetStyle("SearchCancelButton"); - m_SearchFieldCancelButtonEmpty = GetStyle("SearchCancelButtonEmpty"); - m_HelpBox = GetStyle("HelpBox"); - m_AssetLabel = GetStyle("AssetLabel"); - m_AssetLabelPartial = GetStyle("AssetLabel Partial"); - m_AssetLabelIcon = GetStyle("AssetLabel Icon"); - m_SelectionRect = GetStyle("selectionRect"); - m_MinMaxHorizontalSliderThumb = GetStyle("MinMaxHorizontalSliderThumb"); - m_DropDownList = GetStyle("DropDownButton"); - m_BoldFont = GetStyle("BoldLabel").font; - m_StandardFont = GetStyle("Label").font; - m_MiniFont = GetStyle("MiniLabel").font; - m_MiniBoldFont = GetStyle("MiniBoldLabel").font; - m_ProgressBarBack = GetStyle("ProgressBarBack"); - m_ProgressBarBar = GetStyle("ProgressBarBar"); - m_ProgressBarText = GetStyle("ProgressBarText"); - m_FoldoutPreDrop = GetStyle("FoldoutPreDrop"); - m_InspectorTitlebar = GetStyle("IN Title"); - m_InspectorTitlebarText = GetStyle("IN TitleText"); - m_ToggleGroup = GetStyle("BoldToggle"); - m_Tooltip = GetStyle("Tooltip"); - m_NotificationText = GetStyle("NotificationText"); - m_NotificationBackground = GetStyle("NotificationBackground"); - - // Former LookLikeControls styles - m_Popup = m_LayerMaskField = GetStyle("MiniPopup"); - m_TextField = m_NumberField = GetStyle("textField"); - m_Label = GetStyle("ControlLabel"); - m_ObjectField = GetStyle("ObjectField"); - m_ObjectFieldThumb = GetStyle("ObjectFieldThumb"); - m_ObjectFieldMiniThumb = GetStyle("ObjectFieldMiniThumb"); - m_Toggle = GetStyle("Toggle"); - m_ToggleMixed = GetStyle("ToggleMixed"); - m_ColorField = GetStyle("ColorField"); - m_Foldout = GetStyle("Foldout"); - m_FoldoutSelected = GUIStyle.none; - m_IconButton = GetStyle("IconButton"); - m_TextFieldDropDown = GetStyle("TextFieldDropDown"); - m_TextFieldDropDownText = GetStyle("TextFieldDropDownText"); - - m_LinkLabel = new GUIStyle(m_Label); - // Match selection color which works nicely for both light and dark skins - m_LinkLabel.normal.textColor = new Color(0.25f, 0.5f, 0.9f, 1f); - m_LinkLabel.stretchWidth = false; - - m_TextArea = new GUIStyle(m_TextField); - m_TextArea.wordWrap = true; - - m_InspectorDefaultMargins = new GUIStyle(); - m_InspectorDefaultMargins.padding = new RectOffset( - InspectorWindow.kInspectorPaddingLeft, - InspectorWindow.kInspectorPaddingRight, 0, 0); - - // For the full width margins, use padding from right side in both sides, - // though adjust for overdraw by adding one in left side to get even margins. - m_InspectorFullWidthMargins = new GUIStyle(); - m_InspectorFullWidthMargins.padding = new RectOffset( - InspectorWindow.kInspectorPaddingRight + 1, - InspectorWindow.kInspectorPaddingRight, 0, 0); - - // Derive centered grey mini label from base minilabel - m_CenteredGreyMiniLabel = new GUIStyle(m_MiniLabel); - m_CenteredGreyMiniLabel.alignment = TextAnchor.MiddleCenter; - m_CenteredGreyMiniLabel.normal.textColor = Color.grey; - } - - private GUIStyle GetStyle(string styleName) - { - GUIStyle s = GUI.skin.FindStyle(styleName); - if (s == null) - s = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Inspector).FindStyle(styleName); - if (s == null) - { - Debug.LogError("Missing built-in guistyle " + styleName); - s = GUISkin.error; - } - return s; - } - } -} diff --git a/Editor/Mono/GUI/EditorUpdateWindow.cs b/Editor/Mono/GUI/EditorUpdateWindow.cs deleted file mode 100644 index 7ac2dcbe92..0000000000 --- a/Editor/Mono/GUI/EditorUpdateWindow.cs +++ /dev/null @@ -1,148 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class EditorUpdateWindow : EditorWindow - { - static void ShowEditorErrorWindow(string errorString) - { - LoadResources(); - - EditorUpdateWindow w = ShowWindow(); - - w.s_ErrorString = errorString; - w.s_HasConnectionError = true; - w.s_HasUpdate = false; - } - - static void ShowEditorUpdateWindow(string latestVersionString, string latestVersionMessage, string updateURL) - { - LoadResources(); - - EditorUpdateWindow w = ShowWindow(); - - w.s_LatestVersionString = latestVersionString; - w.s_LatestVersionMessage = latestVersionMessage; - w.s_UpdateURL = updateURL; - w.s_HasConnectionError = false; - w.s_HasUpdate = updateURL.Length > 0; - } - - private static EditorUpdateWindow ShowWindow() - { - return EditorWindow.GetWindowWithRect(typeof(EditorUpdateWindow), new Rect(100, 100, 570, 400), true, s_Title.text) as EditorUpdateWindow; - } - - private static GUIContent s_UnityLogo; - private static GUIContent s_Title; - private static GUIContent s_TextHasUpdate, s_TextUpToDate; - private static GUIContent s_CheckForNewUpdatesText; - - [SerializeField] - private string s_ErrorString; - - [SerializeField] - private string s_LatestVersionString; - - [SerializeField] - private string s_LatestVersionMessage; - - [SerializeField] - private string s_UpdateURL; - - [SerializeField] - private bool s_HasUpdate; - - [SerializeField] - private bool s_HasConnectionError; - - private static bool s_ShowAtStartup; - private Vector2 m_ScrollPos; - - private static void LoadResources() - { - if (s_UnityLogo != null) - return; - - s_ShowAtStartup = EditorPrefs.GetBool("EditorUpdateShowAtStartup", true); - - s_Title = EditorGUIUtility.TrTextContent("Unity Editor Update Check"); - - s_UnityLogo = EditorGUIUtility.IconContent("UnityLogo"); - 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}"); - s_TextUpToDate = EditorGUIUtility.TrTextContent("The Unity Editor is up to date. Currently installed version is {0}"); - - s_CheckForNewUpdatesText = EditorGUIUtility.TrTextContent("Check for Updates"); - } - - public void OnGUI() - { - LoadResources(); - - - GUILayout.BeginVertical(); - GUILayout.Space(10); - GUI.Box(new Rect(13, 8, s_UnityLogo.image.width, s_UnityLogo.image.height), s_UnityLogo, GUIStyle.none); - GUILayout.Space(5); - GUILayout.BeginHorizontal(); - GUILayout.Space(120); - GUILayout.BeginVertical(); - - if (s_HasConnectionError) - { - GUILayout.Label(s_ErrorString, "WordWrappedLabel", GUILayout.Width(405)); - } - else if (s_HasUpdate) - { - GUILayout.Label(string.Format(s_TextHasUpdate.text, InternalEditorUtility.GetFullUnityVersion(), s_LatestVersionString), "WordWrappedLabel", GUILayout.Width(300)); - - GUILayout.Space(20); - m_ScrollPos = EditorGUILayout.BeginScrollView(m_ScrollPos, GUILayout.Width(405), GUILayout.Height(200)); - GUILayout.Label(s_LatestVersionMessage, "WordWrappedLabel"); - EditorGUILayout.EndScrollView(); - - GUILayout.Space(20); - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Download new version", GUILayout.Width(200))) - Help.BrowseURL(s_UpdateURL); - - if (GUILayout.Button("Skip new version", GUILayout.Width(200))) - { - EditorPrefs.SetString("EditorUpdateSkipVersionString", s_LatestVersionString); - Close(); - } - GUILayout.EndHorizontal(); - } - else - { - GUILayout.Label(string.Format(s_TextUpToDate.text, Application.unityVersion), "WordWrappedLabel", GUILayout.Width(405)); - } - - - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - - GUILayout.Space(8); - - - GUILayout.FlexibleSpace(); - GUILayout.BeginHorizontal(GUILayout.Height(20)); - GUILayout.FlexibleSpace(); - GUI.changed = false; - s_ShowAtStartup = GUILayout.Toggle(s_ShowAtStartup, s_CheckForNewUpdatesText); - if (GUI.changed) - EditorPrefs.SetBool("EditorUpdateShowAtStartup", s_ShowAtStartup); - - GUILayout.Space(10); - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - } - } -} // namespace diff --git a/Editor/Mono/GUI/ExposablePopupMenu.cs b/Editor/Mono/GUI/ExposablePopupMenu.cs deleted file mode 100644 index 3a972a2511..0000000000 --- a/Editor/Mono/GUI/ExposablePopupMenu.cs +++ /dev/null @@ -1,165 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using System.IO; - -using UnityEditorInternal; -using UnityEngine; - - -namespace UnityEditor -{ - internal class ExposablePopupMenu - { - public class ItemData - { - public ItemData(GUIContent content, GUIStyle style, bool on, bool enabled, object userData) - { - m_GUIContent = content; - m_Style = style; - m_On = on; - m_Enabled = enabled; - m_UserData = userData; - } - - public GUIContent m_GUIContent; - public GUIStyle m_Style; - public bool m_On; - public bool m_Enabled; - public object m_UserData; - public float m_Width; - } - - public class PopupButtonData - { - public PopupButtonData(GUIContent content, GUIStyle style) - { - m_GUIContent = content; - m_Style = style; - } - - public GUIContent m_GUIContent; - public GUIStyle m_Style; - } - - List m_Items; - float m_WidthOfButtons; - float m_ItemSpacing; - PopupButtonData m_PopupButtonData; - float m_WidthOfPopup; - float m_MinWidthOfPopup; - System.Action m_SelectionChangedCallback = null; // - - public void Init(List items, float itemSpacing, float minWidthOfPopup, PopupButtonData popupButtonData, System.Action selectionChangedCallback) - { - m_Items = items; - m_ItemSpacing = itemSpacing; - m_PopupButtonData = popupButtonData; - m_SelectionChangedCallback = selectionChangedCallback; - m_MinWidthOfPopup = minWidthOfPopup; - CalcWidths(); - } - - public float OnGUI(Rect rect) - { - if (rect.width >= m_WidthOfButtons && rect.width > m_MinWidthOfPopup) - { - Rect buttonRect = rect; - - // Show as buttons - foreach (var item in m_Items) - { - buttonRect.width = item.m_Width; - - EditorGUI.BeginChangeCheck(); - - using (new EditorGUI.DisabledScope(!item.m_Enabled)) - { - GUI.Toggle(buttonRect, item.m_On, item.m_GUIContent, item.m_Style); - } - - if (EditorGUI.EndChangeCheck()) - { - SelectionChanged(item); - GUIUtility.ExitGUI(); // To make sure we can survive if m_Buttons are reallocated in the callback we exit gui - } - - buttonRect.x += item.m_Width + m_ItemSpacing; - } - - return m_WidthOfButtons; - } - else - { - // Show as popup - if (m_WidthOfPopup < rect.width) - rect.width = m_WidthOfPopup; - - //if (GUI.Button (rect, m_PopupButtonData.m_GUIContent, m_PopupButtonData.m_Style)) - if (EditorGUI.DropdownButton(rect, m_PopupButtonData.m_GUIContent, FocusType.Passive, m_PopupButtonData.m_Style)) - PopUpMenu.Show(rect, m_Items, this); - - return m_WidthOfPopup; - } - } - - void CalcWidths() - { - // Buttons - m_WidthOfButtons = 0f; - foreach (var item in m_Items) - { - item.m_Width = item.m_Style.CalcSize(item.m_GUIContent).x; - m_WidthOfButtons += item.m_Width; - } - m_WidthOfButtons += (m_Items.Count - 1) * m_ItemSpacing; - - // Popup - Vector2 size = m_PopupButtonData.m_Style.CalcSize(m_PopupButtonData.m_GUIContent); - size.x += 3f; // more space between text and arrow - m_WidthOfPopup = size.x; - } - - void SelectionChanged(ItemData item) - { - if (m_SelectionChangedCallback != null) - m_SelectionChangedCallback(item); - else - Debug.LogError("Callback is null"); - } - - internal class PopUpMenu - { - static List m_Data; - static ExposablePopupMenu m_Caller; - - static internal void Show(Rect activatorRect, List buttonData, ExposablePopupMenu caller) - { - m_Data = buttonData; - m_Caller = caller; - - GenericMenu menu = new GenericMenu(); - foreach (ItemData item in m_Data) - if (item.m_Enabled) - menu.AddItem(item.m_GUIContent, item.m_On, SelectionCallback, item); - else - menu.AddDisabledItem(item.m_GUIContent); - - menu.DropDown(activatorRect); - } - - static void SelectionCallback(object userData) - { - ItemData item = (ItemData)userData; - m_Caller.SelectionChanged(item); - - // Cleanup - m_Caller = null; - m_Data = null; - } - } - } -} // end namespace UnityEditor diff --git a/Editor/Mono/GUI/FallbackEditorWindow.cs b/Editor/Mono/GUI/FallbackEditorWindow.cs deleted file mode 100644 index 67be923855..0000000000 --- a/Editor/Mono/GUI/FallbackEditorWindow.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Reflection; - -namespace UnityEditor -{ - internal class FallbackEditorWindow : EditorWindow - { - FallbackEditorWindow() - { - } - - void OnEnable() - { - titleContent = EditorGUIUtility.TrTextContent("Failed to load"); - } - - void OnGUI() - { - GUILayout.BeginVertical(); - GUILayout.FlexibleSpace(); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - GUILayout.Label("EditorWindow could not be loaded because the script is not found in the project", "WordWrapLabel"); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - - GUILayout.FlexibleSpace(); - GUILayout.EndVertical(); - } - } -} // namespace diff --git a/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs b/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs deleted file mode 100644 index 23d20f1d1c..0000000000 --- a/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs +++ /dev/null @@ -1,312 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - -namespace UnityEditor -{ - internal class FlexibleMenu : PopupWindowContent - { - class Styles - { - public GUIStyle menuItem = "MenuItem"; - public GUIContent plusButtonText = new GUIContent("", "Add New Item"); - } - static Styles s_Styles; - - IFlexibleMenuItemProvider m_ItemProvider; - FlexibleMenuModifyItemUI m_ModifyItemUI; - readonly Action m_ItemClickedCallback; - Vector2 m_ScrollPosition = Vector2.zero; - bool m_ShowAddNewPresetItem; - int m_ShowEditWindowForIndex = -1; - int m_HoverIndex; - int[] m_SeperatorIndices; - float m_CachedWidth = -1f; - float m_MinTextWidth = 200f; - - const float lineHeight = 18f; - const float seperatorHeight = 8f; - const float leftMargin = 25f; - int maxIndex { get { return m_ShowAddNewPresetItem ? m_ItemProvider.Count() : m_ItemProvider.Count() - 1; } } - public int selectedIndex { get; set; } - protected float minTextWidth { get { return m_MinTextWidth; } set { m_MinTextWidth = value; ClearCachedWidth(); } } - - // itemClickedCallback arguments is clicked index, clicked item object - public FlexibleMenu(IFlexibleMenuItemProvider itemProvider, int selectionIndex, FlexibleMenuModifyItemUI modifyItemUi, Action itemClickedCallback) - { - m_ItemProvider = itemProvider; - m_ModifyItemUI = modifyItemUi; - m_ItemClickedCallback = itemClickedCallback; - m_SeperatorIndices = m_ItemProvider.GetSeperatorIndices(); - selectedIndex = selectionIndex; - m_ShowAddNewPresetItem = m_ModifyItemUI != null; - } - - public override Vector2 GetWindowSize() - { - return CalcSize(); - } - - bool IsDeleteModiferPressed() - { - return Event.current.alt; - } - - bool AllowDeleteClick(int index) - { - return IsDeleteModiferPressed() && m_ItemProvider.IsModificationAllowed(index) && GUIUtility.hotControl == 0; - } - - public override void OnGUI(Rect rect) - { - if (s_Styles == null) - s_Styles = new Styles(); - - Event evt = Event.current; - - Rect contentRect = new Rect(0, 0, 1, CalcSize().y); - m_ScrollPosition = GUI.BeginScrollView(rect, m_ScrollPosition, contentRect); - { - float curY = 0f; - for (int i = 0; i <= maxIndex; ++i) - { - int itemControlID = i + 1000000; - Rect itemRect = new Rect(0, curY, rect.width, lineHeight); - bool addSeperator = Array.IndexOf(m_SeperatorIndices, i) >= 0; - - // Add new preset button - if (m_ShowAddNewPresetItem && i == m_ItemProvider.Count()) - { - CreateNewItemButton(itemRect); - continue; - } - - if (m_ShowEditWindowForIndex == i) - { - m_ShowEditWindowForIndex = -1; - EditExistingItem(itemRect, i); - } - - // Handle event - switch (evt.type) - { - case EventType.Repaint: - bool hover = false; - if (m_HoverIndex == i) - { - if (itemRect.Contains(evt.mousePosition)) - hover = true; - else - m_HoverIndex = -1; - } - - // Overwrite if - if (m_ModifyItemUI != null && m_ModifyItemUI.IsShowing()) - { - hover = m_ItemProvider.GetItem(i) == m_ModifyItemUI.m_Object; - } - - s_Styles.menuItem.Draw(itemRect, GUIContent.Temp(m_ItemProvider.GetName(i)), hover, false, i == selectedIndex, false); - - if (addSeperator) - { - const float margin = 4f; - Rect seperatorRect = new Rect(itemRect.x + margin, itemRect.y + itemRect.height + seperatorHeight * 0.5f, itemRect.width - 2 * margin, 1); - 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 - } - - // We delete presets on alt-click - if (AllowDeleteClick(i)) - EditorGUIUtility.AddCursorRect(itemRect, MouseCursor.ArrowMinus); - break; - - case EventType.MouseDown: - if (evt.button == 0 && itemRect.Contains(evt.mousePosition)) - { - GUIUtility.hotControl = itemControlID; - if (!IsDeleteModiferPressed() && evt.clickCount == 1) - { - GUIUtility.hotControl = 0; - SelectItem(i); - editorWindow.Close(); - evt.Use(); - } - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == itemControlID) - { - GUIUtility.hotControl = 0; - if (evt.button == 0 && itemRect.Contains(evt.mousePosition)) - { - if (AllowDeleteClick(i)) - { - DeleteItem(i); - evt.Use(); - } - } - } - break; - - case EventType.ContextClick: - if (itemRect.Contains(evt.mousePosition)) - { - evt.Use(); - if (m_ModifyItemUI != null && m_ItemProvider.IsModificationAllowed(i)) - ItemContextMenu.Show(i, this); - } - break; - - case EventType.MouseMove: - if (itemRect.Contains(evt.mousePosition)) - { - if (m_HoverIndex != i) - { - m_HoverIndex = i; - Repaint(); - } - } - else if (m_HoverIndex == i) - { - m_HoverIndex = -1; - Repaint(); - } - break; - } - - curY += lineHeight; - if (addSeperator) - curY += seperatorHeight; - } // end foreach item - } GUI.EndScrollView(); - } - - void SelectItem(int index) - { - selectedIndex = index; - if (m_ItemClickedCallback != null && index >= 0) - m_ItemClickedCallback(index, m_ItemProvider.GetItem(index)); - } - - protected Vector2 CalcSize() - { - float height = (maxIndex + 1) * lineHeight + m_SeperatorIndices.Length * seperatorHeight; - if (m_CachedWidth < 0) - m_CachedWidth = Math.Max(m_MinTextWidth, CalcWidth()); - return new Vector2(m_CachedWidth, height); - } - - void ClearCachedWidth() - { - m_CachedWidth = -1f; - } - - float CalcWidth() - { - if (s_Styles == null) - s_Styles = new Styles(); - - float maxWidth = 0; - for (int i = 0; i < m_ItemProvider.Count(); ++i) - { - float w = s_Styles.menuItem.CalcSize(GUIContent.Temp(m_ItemProvider.GetName(i))).x; - maxWidth = Mathf.Max(w, maxWidth); - } - - const float rightMargin = 6f; - return maxWidth + rightMargin; - } - - void Repaint() - { - HandleUtility.Repaint(); // repaints current guiview (needs rename) - } - - void CreateNewItemButton(Rect itemRect) - { - if (m_ModifyItemUI == null) - return; - - Rect plusRect = new Rect(itemRect.x + leftMargin, itemRect.y, 15, 15); - if (GUI.Button(plusRect, s_Styles.plusButtonText, "OL Plus")) - { - plusRect.y -= 15f; - m_ModifyItemUI.Init(FlexibleMenuModifyItemUI.MenuType.Add, m_ItemProvider.Create(), - delegate(object obj) - { - ClearCachedWidth(); - int newIndex = m_ItemProvider.Add(obj); - SelectItem(newIndex); - EditorApplication.RequestRepaintAllViews(); // We want to repaint the flexible menu (currently in modifyItemUI) - }); - PopupWindow.Show(plusRect, m_ModifyItemUI, null, ShowMode.PopupMenuWithKeyboardFocus); - } - } - - void EditExistingItem(Rect itemRect, int index) - { - if (m_ModifyItemUI == null) - return; - - itemRect.y -= itemRect.height; - itemRect.x += itemRect.width; - m_ModifyItemUI.Init(FlexibleMenuModifyItemUI.MenuType.Edit, m_ItemProvider.GetItem(index), - delegate(object obj) - { - ClearCachedWidth(); - m_ItemProvider.Replace(index, obj); - EditorApplication.RequestRepaintAllViews(); // We want to repaint the flexible menu (currently in modifyItemUI) - }); - PopupWindow.Show(itemRect, m_ModifyItemUI, null, ShowMode.PopupMenuWithKeyboardFocus); - } - - void DeleteItem(int index) - { - ClearCachedWidth(); - m_ItemProvider.Remove(index); - selectedIndex = Mathf.Clamp(selectedIndex, 0, m_ItemProvider.Count() - 1); // ensure valid - } - - public static void DrawRect(Rect rect, Color color) - { - if (Event.current.type != EventType.Repaint) - return; - - Color orgColor = GUI.color; - GUI.color = GUI.color * color; - GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture); - GUI.color = orgColor; - } - - internal static class ItemContextMenu - { - static FlexibleMenu s_Caller; - - static public void Show(int itemIndex, FlexibleMenu caller) - { - s_Caller = caller; - GenericMenu menu = new GenericMenu(); - menu.AddItem(EditorGUIUtility.TrTextContent("Edit..."), false, Edit, itemIndex); - menu.AddItem(EditorGUIUtility.TrTextContent("Delete"), false, Delete, itemIndex); - menu.ShowAsContext(); - EditorGUIUtility.ExitGUI(); - } - - private static void Delete(object userData) - { - int itemIndex = (int)userData; - s_Caller.DeleteItem(itemIndex); - } - - private static void Edit(object userData) - { - int itemIndex = (int)userData; - s_Caller.m_ShowEditWindowForIndex = itemIndex; - } - } - } -} // namespace diff --git a/Editor/Mono/GUI/FlexibleMenu/FlexibleMenuModifyItemUI.cs b/Editor/Mono/GUI/FlexibleMenu/FlexibleMenuModifyItemUI.cs deleted file mode 100644 index 5f88d5e77f..0000000000 --- a/Editor/Mono/GUI/FlexibleMenu/FlexibleMenuModifyItemUI.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - -namespace UnityEditor -{ - abstract class FlexibleMenuModifyItemUI : PopupWindowContent - { - public enum MenuType { Add, Edit }; - protected MenuType m_MenuType; - public object m_Object; - protected Action m_AcceptedCallback; - private bool m_IsInitialized; - - public override void OnClose() - { - m_Object = null; - m_AcceptedCallback = null; - m_IsInitialized = false; - EditorApplication.RequestRepaintAllViews(); // When closed ensure FlexibileMenu gets repainted so hover can be removed - } - - public void Init(MenuType menuType, object obj, Action acceptedCallback) - { - m_MenuType = menuType; - m_Object = obj; - m_AcceptedCallback = acceptedCallback; - m_IsInitialized = true; - } - - public void Accepted() - { - if (m_AcceptedCallback != null) - m_AcceptedCallback(m_Object); - else - Debug.LogError("Missing callback. Did you remember to call Init ?"); - } - - public bool IsShowing() - { - return m_IsInitialized; - } - } -} // namespace diff --git a/Editor/Mono/GUI/FlexibleMenu/IFlexibleMenuItemProvider.cs b/Editor/Mono/GUI/FlexibleMenu/IFlexibleMenuItemProvider.cs deleted file mode 100644 index 056193f706..0000000000 --- a/Editor/Mono/GUI/FlexibleMenu/IFlexibleMenuItemProvider.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor -{ - interface IFlexibleMenuItemProvider - { - int Count(); - object GetItem(int index); - int Add(object obj); - void Replace(int index, object newPresetObject); - void Remove(int index); - object Create(); - void Move(int index, int destIndex, bool insertAfterDestIndex); - string GetName(int index); - bool IsModificationAllowed(int index); - int[] GetSeperatorIndices(); - } -} diff --git a/Editor/Mono/GUI/FlowLayout.cs b/Editor/Mono/GUI/FlowLayout.cs deleted file mode 100644 index b63403b9bc..0000000000 --- a/Editor/Mono/GUI/FlowLayout.cs +++ /dev/null @@ -1,327 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using System.Collections; -using System.Reflection; -using UnityEditorInternal; - - -namespace UnityEditor -{ - class FlowLayout : GUILayoutGroup - { - struct LineInfo - { - public float minSize, maxSize; - public float start, size; - public int topBorder, bottomBorder; - } - - int m_Lines; - LineInfo[] m_LineInfo; - - public override void CalcWidth() - { - bool hasMinWidth = minWidth != 0; - - base.CalcWidth(); - - if (isVertical) - { - // DONT - } - else - { - // Margin handling is somewhat different from other controls. - // Since we don't know what will wrap where we'll just take the Min margin of all child elements - if (!hasMinWidth) - { - minWidth = 0; - foreach (GUILayoutEntry i in entries) - { - // Here we should probably include margins of the element, but that does seem kind of annoying - minWidth = Mathf.Max(m_ChildMinWidth, i.minWidth); - } - } - } - } - - public override void SetHorizontal(float x, float width) - { - // Apply the base. Now everything is in one line (or column), and all we need is to insert the linebreaks - base.SetHorizontal(x, width); - - if (resetCoords) - x = 0; - - if (isVertical) - { - Debug.LogError("Wordwrapped vertical group. Don't. Just Don't"); - } - else - { // we're horizontally laid out: - // apply margins/padding here - // 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)... - - // Set the positions - m_Lines = 0; - float pulledOffset = 0; // How far we need to pull each item back. - foreach (GUILayoutEntry i in entries) - { - if (i.rect.xMax - pulledOffset > x + width) - { - // TODO: When we move a line back, we should re-expand - pulledOffset = i.rect.x - i.margin.left; - m_Lines++; - } - i.SetHorizontal(i.rect.x - pulledOffset, i.rect.width); - i.rect.y = m_Lines; - } - m_Lines++; - } - } - - public override void CalcHeight() - { - if (entries.Count == 0) - { - maxHeight = minHeight = 0; - return; - } - m_ChildMinHeight = m_ChildMaxHeight = 0; - int _topMarginMin = 0, _bottomMarginMin = 0; - m_StretchableCountY = 0; - if (isVertical) - { - } - else - { - m_LineInfo = new LineInfo[m_Lines]; - for (int i = 0; i < m_Lines; i++) - { - m_LineInfo[i].topBorder = 10000; - m_LineInfo[i].bottomBorder = 10000; - } - - // Figure out border values for each line - foreach (GUILayoutEntry i in entries) - { - i.CalcHeight(); - int j = (int)i.rect.y; - m_LineInfo[j].minSize = Mathf.Max(i.minHeight, m_LineInfo[j].minSize); - m_LineInfo[j].maxSize = Mathf.Max(i.maxHeight, m_LineInfo[j].maxSize); - m_LineInfo[j].topBorder = Mathf.Min(i.margin.top, m_LineInfo[j].topBorder); - m_LineInfo[j].bottomBorder = Mathf.Min(i.margin.bottom, m_LineInfo[j].bottomBorder); - } - - for (int i = 0; i < m_Lines; i++) - { - m_ChildMinHeight += m_LineInfo[i].minSize; - m_ChildMaxHeight += m_LineInfo[i].maxSize; - } - - // Add in the the extra lines - for (int i = 1; i < m_Lines; i++) - { - float space = Mathf.Max(m_LineInfo[i - 1].bottomBorder, m_LineInfo[i].topBorder); - m_ChildMinHeight += space; - m_ChildMaxHeight += space; - } - _topMarginMin = m_LineInfo[0].topBorder; - _bottomMarginMin = m_LineInfo[m_LineInfo.Length - 1].bottomBorder; - } - - // Do the dance between children & parent for haggling over how many empty pixels to have - float firstPadding, lastPadding; - - margin.top = _topMarginMin; - margin.bottom = _bottomMarginMin; - firstPadding = lastPadding = 0; - - minHeight = Mathf.Max(minHeight, m_ChildMinHeight + firstPadding + lastPadding); - if (maxHeight == 0) - { - stretchHeight += m_StretchableCountY + (style.stretchHeight ? 1 : 0); - maxHeight = m_ChildMaxHeight + firstPadding + lastPadding; - } - else - { - stretchHeight = 0; - } - maxHeight = Mathf.Max(maxHeight, minHeight); - } - - public override void SetVertical(float y, float height) - { - if (entries.Count == 0) - { - base.SetVertical(y, height); - return; - } - - if (isVertical) - { - base.SetVertical(y, height); - } - else - { - if (resetCoords) - y = 0; - - float clientY, clientHeight; - clientY = y - margin.top; - clientHeight = y + margin.vertical; - - // Figure out how to distribute the elements between the different lines - float heightToDistribute = clientHeight - spacing * (m_Lines - 1); - float minMaxScale = 0; - if (m_ChildMinHeight != m_ChildMaxHeight) - minMaxScale = Mathf.Clamp((heightToDistribute - m_ChildMinHeight) / (m_ChildMaxHeight - m_ChildMinHeight), 0, 1); - - float lineY = clientY; - for (int i = 0; i < m_Lines; i++) - { - if (i > 0) - lineY += Mathf.Max(m_LineInfo[i].topBorder, m_LineInfo[i - 1].bottomBorder); - m_LineInfo[i].start = lineY; - m_LineInfo[i].size = Mathf.Lerp(m_LineInfo[i].minSize, m_LineInfo[i].maxSize, minMaxScale); - lineY += m_LineInfo[i].size + spacing; - } - - - foreach (GUILayoutEntry i in entries) - { - LineInfo li = m_LineInfo[(int)i.rect.y]; - if (i.stretchHeight != 0) - i.SetVertical(li.start + i.margin.top, li.size - i.margin.vertical); - else - i.SetVertical(li.start + i.margin.top, Mathf.Clamp(li.size - i.margin.vertical, i.minHeight, i.maxHeight)); - } - } - } - } - - - // @TODO Make this serialize - // @TODO Handle animate-from nothing (with fade?) - // @TODO Figure out how to implement fade-away of contents - // @TODO Switch a bunch of others to use this - internal class GUISlideGroup - { - internal static GUISlideGroup current = null; - Dictionary animIDs = new Dictionary(); - const float kLerp = .1f; - const float kSnap = .5f; - - public void Begin() - { - if (current != null) - { - Debug.LogError("You cannot nest animGroups"); - return; - } - - current = this; - } - - public void End() - { - current = null; - } - - public void Reset() - { - current = null; - animIDs.Clear(); - } - - public Rect BeginHorizontal(int id, params GUILayoutOption[] options) - { - SlideGroupInternal g = (SlideGroupInternal)GUILayoutUtility.BeginLayoutGroup(GUIStyle.none, options, typeof(SlideGroupInternal)); - g.SetID(this, id); - g.isVertical = false; - return g.m_FinalRect; - } - - public void EndHorizontal() - { - GUILayoutUtility.EndLayoutGroup(); - } - - public Rect GetRect(int id, Rect r) - { - bool dummy; - if (Event.current.type != EventType.Repaint) - return r; - return GetRect(id, r, out dummy); - } - - Rect GetRect(int id, Rect r, out bool changed) - { - if (!animIDs.ContainsKey(id)) - { - animIDs.Add(id, r); - changed = false; - return r; - } - - Rect current = animIDs[id]; - if (current.y != r.y || current.height != r.height || current.x != r.x || current.width != r.width) - { - float lerp = kLerp; - if (Mathf.Abs(current.y - r.y) > kSnap) - r.y = Mathf.Lerp(current.y, r.y, lerp); - if (Mathf.Abs(current.height - r.height) > kSnap) - r.height = Mathf.Lerp(current.height, r.height, lerp); - if (Mathf.Abs(current.x - r.x) > kSnap) - r.x = Mathf.Lerp(current.x, r.x, lerp); - if (Mathf.Abs(current.width - r.width) > kSnap) - r.width = Mathf.Lerp(current.width, r.width, lerp); - animIDs[id] = r; - changed = true; - HandleUtility.Repaint(); - } - else - changed = false; - return r; - } - - class SlideGroupInternal : GUILayoutGroup - { - int m_ID; - GUISlideGroup m_Owner; -#pragma warning disable 649 - internal Rect m_FinalRect; - public void SetID(GUISlideGroup owner, int id) - { - m_ID = id; - m_Owner = owner; - } - - public override void SetHorizontal(float x, float width) - { - m_FinalRect.x = x; - m_FinalRect.width = width; - base.SetHorizontal(x, width); - } - - public override void SetVertical(float y, float height) - { - m_FinalRect.y = y; - m_FinalRect.height = height; - - Rect r = new Rect(rect.x, y, rect.width, height); - bool changed; - r = m_Owner.GetRect(m_ID, r, out changed); - - if (changed) - base.SetHorizontal(r.x, r.width); - base.SetVertical(r.y, r.height); - } - } - } -} // namespace diff --git a/Editor/Mono/GUI/GenericMenu.cs b/Editor/Mono/GUI/GenericMenu.cs deleted file mode 100644 index f94682e18b..0000000000 --- a/Editor/Mono/GUI/GenericMenu.cs +++ /dev/null @@ -1,120 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections; - -namespace UnityEditor -{ - public sealed class GenericMenu - { - // Callback function, called when a menu item is selected - public delegate void MenuFunction(); - - // Callback function with user data, called when a menu item is selected - public delegate void MenuFunction2(object userData); - - // Add an item to the menu - public void AddItem(GUIContent content, bool on, MenuFunction func) - { - menuItems.Add(new MenuItem(content, false, on, func)); - } - - // Add an item to the menu - public void AddItem(GUIContent content, bool on, MenuFunction2 func, object userData) - { - menuItems.Add(new MenuItem(content, false, on, func, userData)); - } - - // Add a disabled item to the menu - public void AddDisabledItem(GUIContent content) - { - menuItems.Add(new MenuItem(content, false, false, null)); - } - - // Add a seperator item to the menu - public void AddSeparator(string path) - { - menuItems.Add(new MenuItem(new GUIContent(path), true, false, null)); - } - - // Get number of items in the menu - public int GetItemCount() - { - return menuItems.Count; - } - - private ArrayList menuItems = new ArrayList(); - - private sealed class MenuItem - { - public GUIContent content; - public bool separator; - public bool on; - public MenuFunction func; - public MenuFunction2 func2; - public object userData; - public MenuItem(GUIContent _content, bool _separator, bool _on, MenuFunction _func) - { - content = _content; - separator = _separator; - on = _on; - func = _func; - } - - public MenuItem(GUIContent _content, bool _separator, bool _on, MenuFunction2 _func, object _userData) - { - content = _content; - separator = _separator; - on = _on; - func2 = _func; - userData = _userData; - } - } - - // Show the menu under the mouse - public void ShowAsContext() - { - if (Event.current == null) - return; - DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); - } - - // Show the menu at the given screen rect - public void DropDown(Rect position) - { - string[] titles = new string[menuItems.Count]; - bool[] enabled = new bool[menuItems.Count]; - ArrayList selected = new ArrayList(); - bool[] separator = new bool[menuItems.Count]; - - for (int idx = 0; idx < menuItems.Count; idx++) - { - MenuItem item = (MenuItem)menuItems[idx]; - titles[idx] = item.content.text; - enabled[idx] = ((item.func != null) || (item.func2 != null)); - separator[idx] = item.separator; - if (item.on) - selected.Add(idx); - } - - EditorUtility.DisplayCustomMenuWithSeparators(position, titles, enabled, separator, (int[])selected.ToArray(typeof(int)), CatchMenu, null, true); - } - - // 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) - internal void Popup(Rect position, int selectedIndex) - { - DropDown(position); - } - - private void CatchMenu(object userData, string[] options, int selected) - { - MenuItem i = (MenuItem)menuItems[selected]; - if (i.func2 != null) - i.func2(i.userData); - else if (i.func != null) - i.func(); - } - } -} diff --git a/Editor/Mono/GUI/GradientEditor.cs b/Editor/Mono/GUI/GradientEditor.cs deleted file mode 100644 index a72ac8f42d..0000000000 --- a/Editor/Mono/GUI/GradientEditor.cs +++ /dev/null @@ -1,605 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class GradientEditor - { - class Styles - { - public GUIStyle upSwatch = "Grad Up Swatch"; - public GUIStyle upSwatchOverlay = "Grad Up Swatch Overlay"; - public GUIStyle downSwatch = "Grad Down Swatch"; - public GUIStyle downSwatchOverlay = "Grad Down Swatch Overlay"; - - public GUIContent modeText = EditorGUIUtility.TrTextContent("Mode"); - public GUIContent alphaText = EditorGUIUtility.TrTextContent("Alpha"); - public GUIContent colorText = EditorGUIUtility.TrTextContent("Color"); - public GUIContent locationText = EditorGUIUtility.TrTextContent("Location"); - public GUIContent percentText = new GUIContent("%"); - - static GUIStyle GetStyle(string name) - { - GUISkin s = (GUISkin)EditorGUIUtility.LoadRequired("GradientEditor.GUISkin"); - return s.GetStyle(name); - } - } - static Styles s_Styles; - static Texture2D s_BackgroundTexture; - - public class Swatch - { - public float m_Time; - public Color m_Value; - public bool m_IsAlpha; - - public Swatch(float time, Color value, bool isAlpha) - { - m_Time = time; - m_Value = value; - m_IsAlpha = isAlpha; - } - } - - const int k_MaxNumKeys = 8; - List m_RGBSwatches; - List m_AlphaSwatches; - GradientMode m_GradientMode; - [System.NonSerialized] - Swatch m_SelectedSwatch; - Gradient m_Gradient; - int m_NumSteps; - bool m_HDR; - - // Fixed steps are only used if numSteps > 1 - public void Init(Gradient gradient, int numSteps, bool hdr) - { - m_Gradient = gradient; - m_NumSteps = numSteps; - m_HDR = hdr; - - BuildArrays(); - - if (m_RGBSwatches.Count > 0) - m_SelectedSwatch = m_RGBSwatches[0]; - } - - public Gradient target - { - get { return m_Gradient; } - } - - float GetTime(float actualTime) - { - actualTime = Mathf.Clamp01(actualTime); - - if (m_NumSteps > 1) - { - float stepSize = 1.0f / (m_NumSteps - 1); - int step = Mathf.RoundToInt(actualTime / stepSize); - return step / (float)(m_NumSteps - 1); - } - - return actualTime; - } - - void BuildArrays() - { - if (m_Gradient == null) - return; - GradientColorKey[] colorKeys = m_Gradient.colorKeys; - m_RGBSwatches = new List(colorKeys.Length); - for (int i = 0; i < colorKeys.Length; i++) - { - Color color = colorKeys[i].color; - color.a = 1f; - m_RGBSwatches.Add(new Swatch(colorKeys[i].time, color, false)); - } - - GradientAlphaKey[] alphaKeys = m_Gradient.alphaKeys; - m_AlphaSwatches = new List(alphaKeys.Length); - for (int i = 0; i < alphaKeys.Length; i++) - { - float a = alphaKeys[i].alpha; - m_AlphaSwatches.Add(new Swatch(alphaKeys[i].time, new Color(a, a, a, 1), true)); - } - m_GradientMode = m_Gradient.mode; - } - - public static void DrawGradientWithBackground(Rect position, Gradient gradient) - { - Texture2D gradientTexture = UnityEditorInternal.GradientPreviewCache.GetGradientPreview(gradient); - Rect r2 = new Rect(position.x + 1, position.y + 1, position.width - 2, position.height - 2); - - // Background checkers - Texture2D backgroundTexture = GetBackgroundTexture(); - Rect texCoordsRect = new Rect(0, 0, r2.width / backgroundTexture.width, r2.height / backgroundTexture.height); - GUI.DrawTextureWithTexCoords(r2, backgroundTexture, texCoordsRect, false); - - // Gradient texture - if (gradientTexture != null) - GUI.DrawTexture(r2, gradientTexture, ScaleMode.StretchToFill, true); - - // Frame over texture - GUI.Label(position, GUIContent.none, EditorStyles.colorPickerBox); - - // HDR label - float maxColorComponent = GetMaxColorComponent(gradient); - if (maxColorComponent > 1.0f) - { - GUI.Label(new Rect(position.x, position.y, position.width - 3, position.height), "HDR", EditorStyles.centeredGreyMiniLabel); - } - } - - public void OnGUI(Rect position) - { - if (s_Styles == null) - s_Styles = new Styles(); - - float modeHeight = 24f; - float swatchHeight = 16f; - float editSectionHeight = 26f; - float gradientTextureHeight = position.height - 2 * swatchHeight - editSectionHeight - modeHeight; - - position.height = modeHeight; - m_GradientMode = (GradientMode)EditorGUI.EnumPopup(position, s_Styles.modeText, m_GradientMode); - if (m_GradientMode != m_Gradient.mode) - AssignBack(); - - position.y += modeHeight; - position.height = swatchHeight; - - // Alpha swatches (no idea why they're top, but that's what Adobe & Apple seem to agree on) - ShowSwatchArray(position, m_AlphaSwatches, true); - - // Gradient texture - position.y += swatchHeight; - if (Event.current.type == EventType.Repaint) - { - position.height = gradientTextureHeight; - DrawGradientWithBackground(position, m_Gradient); - } - position.y += gradientTextureHeight; - position.height = swatchHeight; - - // Color swatches (bottom) - ShowSwatchArray(position, m_RGBSwatches, false); - - if (m_SelectedSwatch != null) - { - position.y += swatchHeight; - position.height = editSectionHeight; - position.y += 10; - - float locationWidth = 45; - float locationTextWidth = 60; - float space = 20; - float alphaOrColorTextWidth = 50; - float totalLocationWidth = locationTextWidth + space + locationTextWidth + locationWidth; - - // Alpha or Color field - Rect rect = position; - rect.height = 18; - rect.x += 17; - rect.width -= totalLocationWidth; - EditorGUIUtility.labelWidth = alphaOrColorTextWidth; - if (m_SelectedSwatch.m_IsAlpha) - { - EditorGUIUtility.fieldWidth = 30; - EditorGUI.BeginChangeCheck(); - float sliderValue = EditorGUI.IntSlider(rect, s_Styles.alphaText, (int)(m_SelectedSwatch.m_Value.r * 255), 0, 255) / 255f; - if (EditorGUI.EndChangeCheck()) - { - sliderValue = Mathf.Clamp01(sliderValue); - m_SelectedSwatch.m_Value.r = m_SelectedSwatch.m_Value.g = m_SelectedSwatch.m_Value.b = sliderValue; - AssignBack(); - HandleUtility.Repaint(); - } - } - else - { - EditorGUI.BeginChangeCheck(); - m_SelectedSwatch.m_Value = EditorGUI.ColorField(rect, s_Styles.colorText, m_SelectedSwatch.m_Value, true, false, m_HDR); - if (EditorGUI.EndChangeCheck()) - { - AssignBack(); - HandleUtility.Repaint(); - } - } - - // Location of key - rect.x += rect.width + space; - rect.width = locationWidth + locationTextWidth; - - EditorGUIUtility.labelWidth = locationTextWidth; - string orgFormatString = EditorGUI.kFloatFieldFormatString; - EditorGUI.kFloatFieldFormatString = "f1"; - - EditorGUI.BeginChangeCheck(); - float newLocation = EditorGUI.FloatField(rect, s_Styles.locationText, m_SelectedSwatch.m_Time * 100.0f) / 100.0f; - if (EditorGUI.EndChangeCheck()) - { - m_SelectedSwatch.m_Time = Mathf.Clamp(newLocation, 0f, 1f); - AssignBack(); - } - - EditorGUI.kFloatFieldFormatString = orgFormatString; - - rect.x += rect.width; - rect.width = 20; - GUI.Label(rect, s_Styles.percentText); - } - } - - void ShowSwatchArray(Rect position, List swatches, bool isAlpha) - { - int id = GUIUtility.GetControlID(652347689, FocusType.Passive); - Event evt = Event.current; - - float mouseSwatchTime = GetTime((Event.current.mousePosition.x - position.x) / position.width); - Vector2 fixedStepMousePosition = new Vector3(position.x + mouseSwatchTime * position.width, Event.current.mousePosition.y); - - switch (evt.GetTypeForControl(id)) - { - case EventType.Repaint: - { - bool hasSelection = false; - foreach (Swatch s in swatches) - { - if (m_SelectedSwatch == s) - { - hasSelection = true; - continue; - } - DrawSwatch(position, s, !isAlpha); - } - // selected swatch drawn last - if (hasSelection && m_SelectedSwatch != null) - DrawSwatch(position, m_SelectedSwatch, !isAlpha); - break; - } - case EventType.MouseDown: - { - Rect clickRect = position; - - // Swatches have some thickness thus we enlarge the clickable area - clickRect.xMin -= 10; - clickRect.xMax += 10; - if (clickRect.Contains(evt.mousePosition)) - { - GUIUtility.hotControl = id; - evt.Use(); - - // Make sure selected is topmost for the click - if (swatches.Contains(m_SelectedSwatch) && !m_SelectedSwatch.m_IsAlpha && CalcSwatchRect(position, m_SelectedSwatch).Contains(evt.mousePosition)) - { - if (evt.clickCount == 2) - { - GUIUtility.keyboardControl = id; - ColorPicker.Show(GUIView.current, m_SelectedSwatch.m_Value, false, m_HDR); - GUIUtility.ExitGUI(); - } - break; - } - - bool found = false; - foreach (Swatch s in swatches) - { - if (CalcSwatchRect(position, s).Contains(fixedStepMousePosition)) - { - found = true; - m_SelectedSwatch = s; - break; - } - } - - if (!found) - { - if (swatches.Count < k_MaxNumKeys) - { - Color currentColor = m_Gradient.Evaluate(mouseSwatchTime); - if (isAlpha) - currentColor = new Color(currentColor.a, currentColor.a, currentColor.a, 1f); - else - currentColor.a = 1f; - m_SelectedSwatch = new Swatch(mouseSwatchTime, currentColor, isAlpha); - swatches.Add(m_SelectedSwatch); - AssignBack(); - } - else - { - Debug.LogWarning("Max " + k_MaxNumKeys + " color keys and " + k_MaxNumKeys + " alpha keys are allowed in a gradient."); - } - } - } - break; - } - case EventType.MouseDrag: - - if (GUIUtility.hotControl == id && m_SelectedSwatch != null) - { - evt.Use(); - - // If user drags swatch outside in vertical direction, we'll remove the swatch - if ((evt.mousePosition.y + 5 < position.y || evt.mousePosition.y - 5 > position.yMax)) - { - if (swatches.Count > 1) - { - swatches.Remove(m_SelectedSwatch); - AssignBack(); - break; - } - } - else if (!swatches.Contains(m_SelectedSwatch)) - swatches.Add(m_SelectedSwatch); - - m_SelectedSwatch.m_Time = mouseSwatchTime; - AssignBack(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - evt.Use(); - - // If the dragged swatch is NOT in the timeline, it means it was dragged outside. - // We just forget about it and let GC get it later. - if (!swatches.Contains(m_SelectedSwatch)) - m_SelectedSwatch = null; - - // Remove duplicate keys on mouse up so that we do not kill any keys during the drag - RemoveDuplicateOverlappingSwatches(); - } - break; - - case EventType.KeyDown: - if (evt.keyCode == KeyCode.Delete) - { - if (m_SelectedSwatch != null) - { - List listToDeleteFrom; - if (m_SelectedSwatch.m_IsAlpha) - listToDeleteFrom = m_AlphaSwatches; - else - listToDeleteFrom = m_RGBSwatches; - - if (listToDeleteFrom.Count > 1) - { - listToDeleteFrom.Remove(m_SelectedSwatch); - AssignBack(); - HandleUtility.Repaint(); - } - } - evt.Use(); - } - break; - - case EventType.ValidateCommand: - if (evt.commandName == EventCommandNames.Delete) - Event.current.Use(); - break; - - case EventType.ExecuteCommand: - if (evt.commandName == EventCommandNames.ColorPickerChanged) - { - GUI.changed = true; - m_SelectedSwatch.m_Value = ColorPicker.color; - AssignBack(); - HandleUtility.Repaint(); - } - else if (evt.commandName == EventCommandNames.Delete) - { - if (swatches.Count > 1) - { - swatches.Remove(m_SelectedSwatch); - AssignBack(); - HandleUtility.Repaint(); - } - } - break; - } - } - - void DrawSwatch(Rect totalPos, Swatch s, bool upwards) - { - Color temp = GUI.backgroundColor; - Rect r = CalcSwatchRect(totalPos, s); - GUI.backgroundColor = s.m_Value; - GUIStyle back = upwards ? s_Styles.upSwatch : s_Styles.downSwatch; - GUIStyle overlay = upwards ? s_Styles.upSwatchOverlay : s_Styles.downSwatchOverlay; - back.Draw(r, false, false, m_SelectedSwatch == s, false); - GUI.backgroundColor = temp; - overlay.Draw(r, false, false, m_SelectedSwatch == s, false); - } - - Rect CalcSwatchRect(Rect totalRect, Swatch s) - { - float time = s.m_Time; - return new Rect(totalRect.x + Mathf.Round(totalRect.width * time) - 5, totalRect.y, 10, totalRect.height); - } - - int SwatchSort(Swatch lhs, Swatch rhs) - { - if (lhs.m_Time == rhs.m_Time && lhs == m_SelectedSwatch) - return -1; - if (lhs.m_Time == rhs.m_Time && rhs == m_SelectedSwatch) - return 1; - - return lhs.m_Time.CompareTo(rhs.m_Time); - } - - // Assign back all swatches, to target gradient. - void AssignBack() - { - m_RGBSwatches.Sort((a, b) => SwatchSort(a, b)); - GradientColorKey[] colorKeys = new GradientColorKey[m_RGBSwatches.Count]; - for (int i = 0; i < m_RGBSwatches.Count; i++) - { - colorKeys[i].color = m_RGBSwatches[i].m_Value; - colorKeys[i].time = m_RGBSwatches[i].m_Time; - } - - m_AlphaSwatches.Sort((a, b) => SwatchSort(a, b)); - GradientAlphaKey[] alphaKeys = new GradientAlphaKey[m_AlphaSwatches.Count]; - for (int i = 0; i < m_AlphaSwatches.Count; i++) - { - alphaKeys[i].alpha = m_AlphaSwatches[i].m_Value.r; // we use the red channel (see BuildArrays) - alphaKeys[i].time = m_AlphaSwatches[i].m_Time; - } - - m_Gradient.colorKeys = colorKeys; - m_Gradient.alphaKeys = alphaKeys; - m_Gradient.mode = m_GradientMode; - - GUI.changed = true; - } - - // Kill any swatches that are at the same time (For example as the result of dragging a swatch on top of another) - void RemoveDuplicateOverlappingSwatches() - { - bool didRemoveAny = false; - for (int i = 1; i < m_RGBSwatches.Count; i++) - { - if (Mathf.Approximately(m_RGBSwatches[i - 1].m_Time, m_RGBSwatches[i].m_Time)) - { - m_RGBSwatches.RemoveAt(i); - i--; - didRemoveAny = true; - } - } - - for (int i = 1; i < m_AlphaSwatches.Count; i++) - { - if (Mathf.Approximately(m_AlphaSwatches[i - 1].m_Time, m_AlphaSwatches[i].m_Time)) - { - m_AlphaSwatches.RemoveAt(i); - i--; - didRemoveAny = true; - } - } - - if (didRemoveAny) - AssignBack(); - } - - public static Texture2D GetBackgroundTexture() - { - if (s_BackgroundTexture == null) - s_BackgroundTexture = GradientEditor.CreateCheckerTexture(32, 4, 4, Color.white, new Color(0.7f, 0.7f, 0.7f)); - return s_BackgroundTexture; - } - - public static Texture2D CreateCheckerTexture(int numCols, int numRows, int cellPixelWidth, Color col1, Color col2) - { - int height = numRows * cellPixelWidth; - int width = numCols * cellPixelWidth; - - Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false); - texture.hideFlags = HideFlags.HideAndDontSave; - Color[] pixels = new Color[width * height]; - - for (int i = 0; i < numRows; i++) - for (int j = 0; j < numCols; j++) - for (int ci = 0; ci < cellPixelWidth; ci++) - for (int cj = 0; cj < cellPixelWidth; cj++) - pixels[(i * cellPixelWidth + ci) * width + j * cellPixelWidth + cj] = ((i + j) % 2 == 0) ? col1 : col2; - - texture.SetPixels(pixels); - texture.Apply(); - return texture; - } - - // GUI Helpers - public static void DrawGradientSwatch(Rect position, Gradient gradient, Color bgColor) - { - DrawGradientSwatchInternal(position, gradient, null, bgColor); - } - - public static void DrawGradientSwatch(Rect position, SerializedProperty property, Color bgColor) - { - DrawGradientSwatchInternal(position, null, property, bgColor); - } - - private static void DrawGradientSwatchInternal(Rect position, Gradient gradient, SerializedProperty property, Color bgColor) - { - if (Event.current.type != EventType.Repaint) - return; - - if (EditorGUI.showMixedValue) - { - Color oldColor = GUI.color; - float a = GUI.enabled ? 1 : 2; - - GUI.color = new Color(0.82f, 0.82f, 0.82f, a) * bgColor; - GUIStyle mgs = EditorGUIUtility.whiteTextureStyle; - mgs.Draw(position, false, false, false, false); - - EditorGUI.BeginHandleMixedValueContentColor(); - mgs.Draw(position, EditorGUI.mixedValueContent, false, false, false, false); - EditorGUI.EndHandleMixedValueContentColor(); - - GUI.color = oldColor; - return; - } - - // Draw Background - Texture2D backgroundTexture = GradientEditor.GetBackgroundTexture(); - if (backgroundTexture != null) - { - Color oldColor = GUI.color; - GUI.color = bgColor; - - GUIStyle backgroundStyle = EditorGUIUtility.GetBasicTextureStyle(backgroundTexture); - backgroundStyle.Draw(position, false, false, false, false); - - GUI.color = oldColor; - } - - // DrawTexture - Texture2D preview = null; - float maxColorComponent; - if (property != null) - { - preview = GradientPreviewCache.GetPropertyPreview(property); - maxColorComponent = GetMaxColorComponent(property.gradientValue); - } - else - { - preview = GradientPreviewCache.GetGradientPreview(gradient); - maxColorComponent = GetMaxColorComponent(gradient); - } - - if (preview == null) - { - Debug.Log("Warning: Could not create preview for gradient"); - return; - } - - GUIStyle gs = EditorGUIUtility.GetBasicTextureStyle(preview); - gs.Draw(position, false, false, false, false); - - // HDR label - if (maxColorComponent > 1.0f) - { - GUI.Label(new Rect(position.x, position.y - 1, position.width - 3, position.height + 2), "HDR", EditorStyles.centeredGreyMiniLabel); - } - } - - private static float GetMaxColorComponent(Gradient gradient) - { - float maxColorComponent = 0.0f; - GradientColorKey[] colorKeys = gradient.colorKeys; - for (int i = 0; i < colorKeys.Length; i++) - { - maxColorComponent = Mathf.Max(maxColorComponent, colorKeys[i].color.maxColorComponent); - } - return maxColorComponent; - } - } -} // namespace diff --git a/Editor/Mono/GUI/GradientField.cs b/Editor/Mono/GUI/GradientField.cs deleted file mode 100644 index 954296e3db..0000000000 --- a/Editor/Mono/GUI/GradientField.cs +++ /dev/null @@ -1,172 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - public sealed partial class EditorGUILayout - { - // Gradient versions - internal static Gradient GradientField(Gradient value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.GradientField(r, value); - } - - internal static Gradient GradientField(string label, Gradient value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.GradientField(label, r, value); - } - - internal static Gradient GradientField(GUIContent label, Gradient value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.GradientField(label, r, value); - } - - // SerializedProperty versions - internal static Gradient GradientField(SerializedProperty value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.GradientField(r, value); - } - - internal static Gradient GradientField(string label, SerializedProperty value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.GradientField(label, r, value); - } - - internal static Gradient GradientField(GUIContent label, SerializedProperty value, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.colorField, options); - return EditorGUI.GradientField(label, r, value); - } - } - - - public sealed partial class EditorGUI - { - static readonly int s_GradientHash = "s_GradientHash".GetHashCode(); - static int s_GradientID; - - // Gradient versions - internal static Gradient GradientField(Rect position, Gradient gradient) - { - return GradientField(position, gradient, false); - } - - internal static Gradient GradientField(Rect position, Gradient gradient, bool hdr) - { - int id = EditorGUIUtility.GetControlID(s_GradientHash, FocusType.Keyboard, position); - return DoGradientField(position, id, gradient, null, hdr); - } - - internal static Gradient GradientField(string label, Rect position, Gradient gradient) - { - return GradientField(EditorGUIUtility.TempContent(label), position, gradient); - } - - internal static Gradient GradientField(GUIContent label, Rect position, Gradient gradient) - { - int id = EditorGUIUtility.GetControlID(s_GradientHash, FocusType.Keyboard, position); - return DoGradientField(PrefixLabel(position, id, label), id, gradient, null, false); - } - - // SerializedProperty versions - internal static Gradient GradientField(Rect position, SerializedProperty gradient) - { - return GradientField(position, gradient, false); - } - - internal static Gradient GradientField(Rect position, SerializedProperty gradient, bool hdr) - { - int id = EditorGUIUtility.GetControlID(s_GradientHash, FocusType.Keyboard, position); - return DoGradientField(position, id, null, gradient, hdr); - } - - internal static Gradient GradientField(string label, Rect position, SerializedProperty property) - { - return GradientField(EditorGUIUtility.TempContent(label), position, property); - } - - internal static Gradient GradientField(GUIContent label, Rect position, SerializedProperty property) - { - int id = EditorGUIUtility.GetControlID(s_GradientHash, FocusType.Keyboard, position); - return DoGradientField(PrefixLabel(position, id, label), id, null, property, false); - } - - internal static Gradient DoGradientField(Rect position, int id, Gradient value, SerializedProperty property, bool hdr) - { - Event evt = Event.current; - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (position.Contains(evt.mousePosition)) - { - if (evt.button == 0) - { - s_GradientID = id; - GUIUtility.keyboardControl = id; - Gradient gradient = property != null ? property.gradientValue : value; - GradientPicker.Show(gradient, hdr); - GUIUtility.ExitGUI(); - } - else if (evt.button == 1) - { - if (property != null) - GradientContextMenu.Show(property.Copy()); - // TODO: make work for Gradient value - } - } - break; - case EventType.Repaint: - { - Rect r2 = new Rect(position.x + 1, position.y + 1, position.width - 2, position.height - 2); // Adjust for box drawn on top - if (property != null) - GradientEditor.DrawGradientSwatch(r2, property, Color.white); - else - GradientEditor.DrawGradientSwatch(r2, value, Color.white); - EditorStyles.colorPickerBox.Draw(position, GUIContent.none, id); - break; - } - case EventType.ExecuteCommand: - if (s_GradientID == id && evt.commandName == GradientPicker.GradientPickerChangedCommand) - { - GUI.changed = true; - GradientPreviewCache.ClearCache(); - HandleUtility.Repaint(); - if (property != null) - property.gradientValue = GradientPicker.gradient; - - return GradientPicker.gradient; - } - break; - case EventType.ValidateCommand: - if (s_GradientID == id && evt.commandName == EventCommandNames.UndoRedoPerformed) - { - if (property != null) - GradientPicker.SetCurrentGradient(property.gradientValue); - GradientPreviewCache.ClearCache(); - return value; - } - break; - case EventType.KeyDown: - if (GUIUtility.keyboardControl == id && (evt.keyCode == KeyCode.Space || evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter)) - { - Event.current.Use(); - Gradient gradient = property != null ? property.gradientValue : value; - GradientPicker.Show(gradient, hdr); - GUIUtility.ExitGUI(); - } - break; - } - return value; - } - } -} diff --git a/Editor/Mono/GUI/GradientPicker.cs b/Editor/Mono/GUI/GradientPicker.cs deleted file mode 100644 index 8fc662443a..0000000000 --- a/Editor/Mono/GUI/GradientPicker.cs +++ /dev/null @@ -1,260 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class GradientPicker : EditorWindow - { - private static GradientPicker s_GradientPicker; - public static string presetsEditorPrefID { get { return "Gradient"; } } - - private GradientEditor m_GradientEditor; - private PresetLibraryEditor m_GradientLibraryEditor; - [SerializeField] - private PresetLibraryEditorState m_GradientLibraryEditorState; - private Gradient m_Gradient; - private const int k_DefaultNumSteps = 0; - private GUIView m_DelegateView; - private System.Action m_Delegate; - private bool m_HDR; - private bool gradientChanged { get; set; } - - // Static methods - public static void Show(Gradient newGradient, bool hdr) - { - GUIView currentView = GUIView.current; - PrepareShow(hdr); - s_GradientPicker.m_DelegateView = currentView; - s_GradientPicker.m_Delegate = null; - s_GradientPicker.Init(newGradient, hdr); - - GradientPreviewCache.ClearCache(); - } - - public static void Show(Gradient newGradient, bool hdr, System.Action onGradientChanged) - { - PrepareShow(hdr); - s_GradientPicker.m_DelegateView = null; - s_GradientPicker.m_Delegate = onGradientChanged; - s_GradientPicker.Init(newGradient, hdr); - - GradientPreviewCache.ClearCache(); - } - - static void PrepareShow(bool hdr) - { - if (s_GradientPicker == null) - { - string title = hdr ? "HDR Gradient Editor" : "Gradient Editor"; - s_GradientPicker = (GradientPicker)GetWindow(typeof(GradientPicker), true, title, false); - Vector2 minSize = new Vector2(360, 224); - Vector2 maxSize = new Vector2(1900, 3000); - s_GradientPicker.minSize = minSize; - s_GradientPicker.maxSize = maxSize; - s_GradientPicker.wantsMouseMove = true; - s_GradientPicker.ShowAuxWindow(); // Use this if auto close on lost focus is wanted. - } - else - { - s_GradientPicker.Repaint(); // Ensure we get a OnGUI so we refresh if new gradient - } - } - - public static GradientPicker instance - { - get - { - if (!s_GradientPicker) - Debug.LogError("Gradient Picker not initalized, did you call Show first?"); - return s_GradientPicker; - } - } - - public string currentPresetLibrary - { - get - { - InitIfNeeded(); - return m_GradientLibraryEditor.currentLibraryWithoutExtension; - } - set - { - InitIfNeeded(); - m_GradientLibraryEditor.currentLibraryWithoutExtension = value; - } - } - - private void Init(Gradient newGradient, bool hdr) - { - m_Gradient = newGradient; - m_HDR = hdr; - if (m_GradientEditor != null) - m_GradientEditor.Init(newGradient, k_DefaultNumSteps, m_HDR); - Repaint(); - } - - private void SetGradientData(Gradient gradient) - { - m_Gradient.colorKeys = gradient.colorKeys; - m_Gradient.alphaKeys = gradient.alphaKeys; - m_Gradient.mode = gradient.mode; - Init(m_Gradient, m_HDR); - } - - public static bool visible - { - get { return s_GradientPicker != null; } - } - - public static Gradient gradient - { - get - { - if (s_GradientPicker != null) - return s_GradientPicker.m_Gradient; - return null; - } - } - - public void OnEnable() - { - hideFlags = HideFlags.DontSave; - // Use these if window is not an aux window for auto closing on play/stop - //EditorApplication.playmodeStateChanged += OnPlayModeStateChanged; - } - - public void OnDisable() - { - //EditorApplication.playmodeStateChanged -= OnPlayModeStateChanged; - if (m_GradientLibraryEditorState != null) - m_GradientLibraryEditorState.TransferEditorPrefsState(false); - - s_GradientPicker = null; - } - - public void OnDestroy() - { - m_GradientLibraryEditor.UnloadUsedLibraries(); - } - - void OnPlayModeStateChanged() - { - Close(); - } - - void InitIfNeeded() - { - // Init editor when needed - if (m_GradientEditor == null) - { - m_GradientEditor = new GradientEditor(); - m_GradientEditor.Init(m_Gradient, k_DefaultNumSteps, m_HDR); - } - - if (m_GradientLibraryEditorState == null) - { - m_GradientLibraryEditorState = new PresetLibraryEditorState(presetsEditorPrefID); - m_GradientLibraryEditorState.TransferEditorPrefsState(true); - } - - if (m_GradientLibraryEditor == null) - { - var saveLoadHelper = new ScriptableObjectSaveLoadHelper("gradients", SaveType.Text); - m_GradientLibraryEditor = new PresetLibraryEditor(saveLoadHelper, m_GradientLibraryEditorState, PresetClickedCallback); - m_GradientLibraryEditor.showHeader = true; - m_GradientLibraryEditor.minMaxPreviewHeight = new Vector2(14f, 14f); - } - } - - void PresetClickedCallback(int clickCount, object presetObject) - { - Gradient gradient = presetObject as Gradient; - if (gradient == null) - Debug.LogError("Incorrect object passed " + presetObject); - - SetCurrentGradient(gradient); - UnityEditorInternal.GradientPreviewCache.ClearCache(); - gradientChanged = true; - } - - public void OnGUI() - { - // When we start play (using shortcut keys) we get two OnGui calls and m_Gradient is null: so early out. - if (m_Gradient == null) - return; - - InitIfNeeded(); - - float gradientEditorHeight = Mathf.Min(position.height, 146); - float distBetween = 10f; - float presetLibraryHeight = position.height - gradientEditorHeight - distBetween; - - Rect gradientEditorRect = new Rect(10, 10, position.width - 20, gradientEditorHeight - 20); - Rect gradientLibraryRect = new Rect(0, gradientEditorHeight + distBetween, position.width, presetLibraryHeight); - - // Separator - EditorGUI.DrawRect(new Rect(gradientLibraryRect.x, gradientLibraryRect.y - 1, gradientLibraryRect.width, 1), new Color(0, 0, 0, 0.3f)); - EditorGUI.DrawRect(new Rect(gradientLibraryRect.x, gradientLibraryRect.y, gradientLibraryRect.width, 1), new Color(1, 1, 1, 0.1f)); - - // The meat - EditorGUI.BeginChangeCheck(); - m_GradientEditor.OnGUI(gradientEditorRect); - if (EditorGUI.EndChangeCheck()) - gradientChanged = true; - m_GradientLibraryEditor.OnGUI(gradientLibraryRect, m_Gradient); - if (gradientChanged) - { - gradientChanged = false; - SendEvent(true); - } - } - - public const string GradientPickerChangedCommand = "GradientPickerChanged"; - - void SendEvent(bool exitGUI) - { - if (m_DelegateView) - { - Event e = EditorGUIUtility.CommandEvent(GradientPickerChangedCommand); - Repaint(); - m_DelegateView.SendEvent(e); - if (exitGUI) - GUIUtility.ExitGUI(); - } - if (m_Delegate != null) - { - m_Delegate(gradient); - } - } - - public static void SetCurrentGradient(Gradient gradient) - { - if (s_GradientPicker == null) - return; - - s_GradientPicker.SetGradientData(gradient); - GUI.changed = true; - } - - public static void CloseWindow() - { - if (s_GradientPicker == null) - return; - - s_GradientPicker.Close(); - GUIUtility.ExitGUI(); - } - - public static void RepaintWindow() - { - if (s_GradientPicker == null) - return; - s_GradientPicker.Repaint(); - } - } -} // namespace diff --git a/Editor/Mono/GUI/HexColorTextField.cs b/Editor/Mono/GUI/HexColorTextField.cs deleted file mode 100644 index a1dec0afb0..0000000000 --- a/Editor/Mono/GUI/HexColorTextField.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class EditorGUILayout - { - internal static Color32 HexColorTextField(GUIContent label, Color32 color, bool showAlpha, params GUILayoutOption[] options) - { - return HexColorTextField(label, color, showAlpha, EditorStyles.textField, options); - } - - internal static Color32 HexColorTextField(GUIContent label, Color32 color, bool showAlpha, GUIStyle style, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.numberField, options); - return EditorGUI.HexColorTextField(r, label, color, showAlpha, style); - } - } - - public sealed partial class EditorGUI - { - internal static Color32 HexColorTextField(Rect rect, GUIContent label, Color32 color, bool showAlpha) - { - return HexColorTextField(rect, label, color, showAlpha, EditorStyles.textField); - } - - internal static Color32 HexColorTextField(Rect rect, GUIContent label, Color32 color, bool showAlpha, GUIStyle style) - { - var id = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, rect); - return DoHexColorTextField(id, PrefixLabel(rect, id, label), color, showAlpha, style); - } - - internal static Color32 DoHexColorTextField(int id, Rect rect, Color32 color, bool showAlpha, GUIStyle style) - { - const string kValidHexChars = "0123456789ABCDEFabcdef"; - - // Hex field - string hex = showAlpha ? ColorUtility.ToHtmlStringRGBA(color) : ColorUtility.ToHtmlStringRGB(color); - BeginChangeCheck(); - - bool dummy; - string newHex = DoTextField(s_RecycledEditor, id, rect, hex, style, kValidHexChars, out dummy, false, false, false); - - if (EndChangeCheck()) - { - s_RecycledEditor.text = s_RecycledEditor.text.ToUpper(); - - Color newColor; - if (ColorUtility.TryParseHtmlString("#" + newHex, out newColor)) - color = new Color(newColor.r, newColor.g, newColor.b, showAlpha ? newColor.a : color.a); - } - - return color; - } - } -} // namespace diff --git a/Editor/Mono/GUI/InternalEditorGUI.cs b/Editor/Mono/GUI/InternalEditorGUI.cs deleted file mode 100644 index de99b3b1eb..0000000000 --- a/Editor/Mono/GUI/InternalEditorGUI.cs +++ /dev/null @@ -1,322 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using UnityEngine; -using System.Collections.Generic; - -// NOTE: -// This file should only contain internal functions of the EditorGUI class -// - -namespace UnityEditor -{ - public sealed partial class EditorGUI - { - static int s_DropdownButtonHash = "DropdownButton".GetHashCode(); - static int s_MouseDeltaReaderHash = "MouseDeltaReader".GetHashCode(); - - internal static bool Button(Rect position, GUIContent content) - { - return Button(position, content, EditorStyles.miniButton); - } - - // We need an EditorGUI.Button that only reacts to left mouse button (GUI.Button reacts to all mouse buttons), so we - // can handle context click events for button areas etc. - internal static bool Button(Rect position, GUIContent content, GUIStyle style) - { - Event evt = Event.current; - switch (evt.type) - { - case EventType.MouseDown: - case EventType.MouseUp: - if (evt.button != 0) - return false; // ignore all input from other buttons than the left mouse button - break; - } - - return GUI.Button(position, content, style); - } - - // Button used for the icon selector where an icon can be selected by pressing and dragging the - // mouse cursor around to select different icons - internal static bool IconButton(int id, Rect position, GUIContent content, GUIStyle style) - { - GUIUtility.CheckOnGUI(); - switch (Event.current.GetTypeForControl(id)) - { - case EventType.MouseDown: - // If the mouse is inside the button, we say that we're the hot control - if (position.Contains(Event.current.mousePosition)) - { - GUIUtility.hotControl = id; - Event.current.Use(); - return true; - } - return false; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - - // If we got the mousedown, the mouseup is ours as well - // (no matter if the click was in the button or not) - Event.current.Use(); - - // But we only return true if the button was actually clicked - return position.Contains(Event.current.mousePosition); - } - return false; - case EventType.MouseDrag: - if (position.Contains(Event.current.mousePosition)) - { - GUIUtility.hotControl = id; - Event.current.Use(); - return true; - } - break; - case EventType.Repaint: - style.Draw(position, content, id); - break; - } - return false; - } - - internal static float WidthResizer(Rect position, float width, float minWidth, float maxWidth) - { - bool hasControl; - return Resizer.Resize(position, width, minWidth, maxWidth, true, out hasControl); - } - - internal static float WidthResizer(Rect position, float width, float minWidth, float maxWidth, out bool hasControl) - { - return Resizer.Resize(position, width, minWidth, maxWidth, true, out hasControl); - } - - internal static float HeightResizer(Rect position, float height, float minHeight, float maxHeight) - { - bool hasControl; - return Resizer.Resize(position, height, minHeight, maxHeight, false, out hasControl); - } - - internal static float HeightResizer(Rect position, float height, float minHeight, float maxHeight, out bool hasControl) - { - return Resizer.Resize(position, height, minHeight, maxHeight, false, out hasControl); - } - - static class Resizer - { - static float s_StartSize; - static Vector2 s_MouseDeltaReaderStartPos; - internal static float Resize(Rect position, float size, float minSize, float maxSize, bool horizontal, out bool hasControl) - { - int id = EditorGUIUtility.GetControlID(s_MouseDeltaReaderHash, FocusType.Passive, position); - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (GUIUtility.hotControl == 0 && position.Contains(evt.mousePosition) && evt.button == 0) - { - GUIUtility.hotControl = id; - GUIUtility.keyboardControl = 0; - s_MouseDeltaReaderStartPos = GUIClip.Unclip(evt.mousePosition); // We unclip to screenspace to prevent being affected by scrollviews - s_StartSize = size; - evt.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - evt.Use(); - Vector2 screenPos = GUIClip.Unclip(evt.mousePosition); // We unclip to screenspace to prevent being affected by scrollviews - float delta = horizontal ? (screenPos - s_MouseDeltaReaderStartPos).x : (screenPos - s_MouseDeltaReaderStartPos).y; - float newSize = s_StartSize + delta; - if (newSize >= minSize && newSize <= maxSize) - size = newSize; - else - size = Mathf.Clamp(newSize, minSize, maxSize); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && evt.button == 0) - { - GUIUtility.hotControl = 0; - evt.Use(); - } - break; - case EventType.Repaint: - var cursor = horizontal ? MouseCursor.SplitResizeLeftRight : MouseCursor.SplitResizeUpDown; - EditorGUIUtility.AddCursorRect(position, cursor, id); - break; - } - - hasControl = GUIUtility.hotControl == id; - return size; - } - } - - - // Get mouse delta values in different situations when click-dragging - static Vector2 s_MouseDeltaReaderLastPos; - internal static Vector2 MouseDeltaReader(Rect position, bool activated) - { - int id = EditorGUIUtility.GetControlID(s_MouseDeltaReaderHash, FocusType.Passive, position); - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (activated && GUIUtility.hotControl == 0 && position.Contains(evt.mousePosition) && evt.button == 0) - { - GUIUtility.hotControl = id; - GUIUtility.keyboardControl = 0; - s_MouseDeltaReaderLastPos = GUIClip.Unclip(evt.mousePosition); // We unclip to screenspace to prevent being affected by scrollviews - evt.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - Vector2 screenPos = GUIClip.Unclip(evt.mousePosition); // We unclip to screenspace to prevent being affected by scrollviews - Vector2 delta = (screenPos - s_MouseDeltaReaderLastPos); - s_MouseDeltaReaderLastPos = screenPos; - evt.Use(); - return delta; - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && evt.button == 0) - { - GUIUtility.hotControl = 0; - evt.Use(); - } - break; - } - return Vector2.zero; - } - - // Shows an active button and a triangle button on the right, which expands the dropdown list - // Returns true if button was activated, returns false if the the dropdown button was activated or the button was not clicked. - internal static bool ButtonWithDropdownList(string buttonName, string[] buttonNames, GenericMenu.MenuFunction2 callback, params GUILayoutOption[] options) - { - var content = EditorGUIUtility.TempContent(buttonName); - return ButtonWithDropdownList(content, buttonNames, callback, options); - } - - // Shows an active button and a triangle button on the right, which expands the dropdown list - // Returns true if button was activated, returns false if the the dropdown button was activated or the button was not clicked. - internal static bool ButtonWithDropdownList(GUIContent content, string[] buttonNames, GenericMenu.MenuFunction2 callback, params GUILayoutOption[] options) - { - var rect = GUILayoutUtility.GetRect(content, EditorStyles.dropDownList, options); - - var dropDownRect = rect; - const float kDropDownButtonWidth = 20f; - dropDownRect.xMin = dropDownRect.xMax - kDropDownButtonWidth; - - if (Event.current.type == EventType.MouseDown && dropDownRect.Contains(Event.current.mousePosition)) - { - var menu = new GenericMenu(); - for (int i = 0; i != buttonNames.Length; i++) - menu.AddItem(new GUIContent(buttonNames[i]), false, callback, i); - - menu.DropDown(rect); - Event.current.Use(); - - return false; - } - - return GUI.Button(rect, content, EditorStyles.dropDownList); - } - - internal static void GameViewSizePopup(Rect buttonRect, GameViewSizeGroupType groupType, int selectedIndex, IGameViewSizeMenuUser gameView, GUIStyle guiStyle) - { - var group = GameViewSizes.instance.GetGroup(groupType); - var text = ""; - if (selectedIndex >= 0 && selectedIndex < group.GetTotalCount()) - text = group.GetGameViewSize(selectedIndex).displayText; - - if (EditorGUI.DropdownButton(buttonRect, GUIContent.Temp(text), FocusType.Passive, guiStyle)) - { - var menuData = new GameViewSizesMenuItemProvider(groupType); - var flexibleMenu = new GameViewSizeMenu(menuData, selectedIndex, new GameViewSizesMenuModifyItemUI(), gameView); - PopupWindow.Show(buttonRect, flexibleMenu); - } - } - - public static void DrawRect(Rect rect, Color color) - { - if (Event.current.type != EventType.Repaint) - return; - - Color orgColor = GUI.color; - GUI.color = GUI.color * color; - GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture); - GUI.color = orgColor; - } - - internal static void DrawDelimiterLine(Rect rect) - { - DrawRect(rect, kSplitLineSkinnedColor.color); - } - - internal static void DrawOutline(Rect rect, float size, Color color) - { - if (Event.current.type != EventType.Repaint) - return; - - Color orgColor = GUI.color; - GUI.color = GUI.color * color; - GUI.DrawTexture(new Rect(rect.x, rect.y, rect.width, size), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(rect.x, rect.yMax - size, rect.width, size), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(rect.x, rect.y + 1, size, rect.height - 2 * size), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(rect.xMax - size, rect.y + 1, size, rect.height - 2 * size), EditorGUIUtility.whiteTexture); - - GUI.color = orgColor; - } - } - - internal struct PropertyGUIData - { - public SerializedProperty property; - public Rect totalPosition; - public bool wasBoldDefaultFont; - public bool wasEnabled; - public Color color; - public PropertyGUIData(SerializedProperty property, Rect totalPosition, bool wasBoldDefaultFont, bool wasEnabled, Color color) - { - this.property = property; - this.totalPosition = totalPosition; - this.wasBoldDefaultFont = wasBoldDefaultFont; - this.wasEnabled = wasEnabled; - this.color = color; - } - } - - internal class DebugUtils - { - internal static string ListToString(IEnumerable list) - { - if (list == null) - return "[null list]"; - - string r = "["; - int count = 0; - foreach (T item in list) - { - if (count != 0) - r += ", "; - if (item != null) - r += item.ToString(); - else - r += "'null'"; - count++; - } - r += "]"; - - if (count == 0) - return "[empty list]"; - - return "(" + count + ") " + r; - } - } -} diff --git a/Editor/Mono/GUI/InternalEditorGUILayout.cs b/Editor/Mono/GUI/InternalEditorGUILayout.cs deleted file mode 100644 index dba74acbd3..0000000000 --- a/Editor/Mono/GUI/InternalEditorGUILayout.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; - -// NOTE: -// This file should only contain internal functions of the EditorGUILayout class - -namespace UnityEditor -{ - public sealed partial class EditorGUILayout - { - internal static bool IconButton(int id, GUIContent content, GUIStyle style, params GUILayoutOption[] options) - { - s_LastRect = GUILayoutUtility.GetRect(content, style, options); - return EditorGUI.IconButton(id, s_LastRect, content, style); - } - - internal static void GameViewSizePopup(GameViewSizeGroupType groupType, int selectedIndex, IGameViewSizeMenuUser gameView, GUIStyle style, params GUILayoutOption[] options) - { - s_LastRect = GetControlRect(false, EditorGUI.kSingleLineHeight, style, options); - EditorGUI.GameViewSizePopup(s_LastRect, groupType, selectedIndex, gameView, style); - } - - internal static void SortingLayerField(GUIContent label, SerializedProperty layerID, GUIStyle style, GUIStyle labelStyle) - { - s_LastRect = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight, style); - EditorGUI.SortingLayerField(s_LastRect, label, layerID, style, labelStyle); - } - } -} diff --git a/Editor/Mono/GUI/Knob.cs b/Editor/Mono/GUI/Knob.cs deleted file mode 100644 index 26db3a8c56..0000000000 --- a/Editor/Mono/GUI/Knob.cs +++ /dev/null @@ -1,378 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - -namespace UnityEditor -{ - // State for when we're dragging a knob. - internal class KnobState - { - public float dragStartPos; - public float dragStartValue; - public bool isDragging; - public bool isEditing; - } - - public sealed partial class EditorGUILayout - { - public static float Knob(Vector2 knobSize, float value, float minValue, float maxValue, string unit, Color backgroundColor, Color activeColor, bool showValue, params GUILayoutOption[] options) - { - Rect r = s_LastRect = GetControlRect(false, knobSize.y, options); - return EditorGUI.Knob(r, knobSize, value, minValue, maxValue, unit, backgroundColor, activeColor, showValue, GUIUtility.GetControlID("Knob".GetHashCode(), FocusType.Passive, r)); - } - } - - public sealed partial class EditorGUI - { - internal struct KnobContext - { - readonly Rect position; - readonly Vector2 knobSize; - readonly float currentValue; - readonly float start; - readonly float end; - readonly string unit; - readonly Color activeColor; - readonly Color backgroundColor; - readonly bool showValue; - readonly int id; - - private const int kPixelRange = 250; - - public KnobContext(Rect position, Vector2 knobSize, float currentValue, float start, float end, string unit, Color backgroundColor, Color activeColor, bool showValue, int id) - { - this.position = position; - this.knobSize = knobSize; - this.currentValue = currentValue; - this.start = start; - this.end = end; - this.unit = unit; - this.activeColor = activeColor; - this.backgroundColor = backgroundColor; - this.showValue = showValue; - this.id = id; - } - - public float Handle() - { - if (KnobState().isEditing && CurrentEventType() != EventType.Repaint) - return DoKeyboardInput(); - - switch (CurrentEventType()) - { - case EventType.MouseDown: - return OnMouseDown(); - - case EventType.MouseDrag: - return OnMouseDrag(); - - case EventType.MouseUp: - return OnMouseUp(); - - case EventType.Repaint: - return OnRepaint(); - } - - return currentValue; - } - - private EventType CurrentEventType() - { - return CurrentEvent().type; - } - - private bool IsEmptyKnob() - { - return start == end; - } - - private Event CurrentEvent() - { - return Event.current; - } - - private float Clamp(float value) - { - return Mathf.Clamp(value, MinValue(), MaxValue()); - } - - private float ClampedCurrentValue() - { - return Clamp(currentValue); - } - - private float MaxValue() - { - return Mathf.Max(start, end); - } - - private float MinValue() - { - return Mathf.Min(start, end); - } - - private float GetCurrentValuePercent() - { - return (ClampedCurrentValue() - MinValue()) / (MaxValue() - MinValue()); - } - - private float MousePosition() - { - return CurrentEvent().mousePosition.y - position.y; - } - - private bool WasDoubleClick() - { - return CurrentEventType() == EventType.MouseDown && - CurrentEvent().clickCount == 2; - } - - private float ValuesPerPixel() - { - return kPixelRange / (MaxValue() - MinValue()); - } - - private KnobState KnobState() - { - return (KnobState)GUIUtility.GetStateObject(typeof(KnobState), id); - } - - private void StartDraggingWithValue(float dragStartValue) - { - var state = KnobState(); - state.dragStartPos = MousePosition(); - state.dragStartValue = dragStartValue; - state.isDragging = true; - } - - private float OnMouseDown() - { - // if the click is outside this control, just bail out... - if (!position.Contains(CurrentEvent().mousePosition) || KnobState().isEditing || IsEmptyKnob()) - return currentValue; - - GUIUtility.hotControl = id; - - if (WasDoubleClick()) - { - KnobState().isEditing = true; - } - else - { - // Record where we're dragging from, so the user can get back. - StartDraggingWithValue(ClampedCurrentValue()); - } - - CurrentEvent().Use(); - - return currentValue; - } - - private float OnMouseDrag() - { - if (GUIUtility.hotControl != id) - return currentValue; - - var state = KnobState(); - if (!state.isDragging) - return currentValue; - - GUI.changed = true; - CurrentEvent().Use(); - - // Recalculate the value from the mouse position. this has the side effect that values are relative to the - // click point - no matter where inside the trough the original value was. Also means user can get back original value - // if he drags back to start position. - float deltaPos = state.dragStartPos - MousePosition(); - var newValue = state.dragStartValue + (deltaPos / ValuesPerPixel()); - return Clamp(newValue); - } - - private float OnMouseUp() - { - if (GUIUtility.hotControl == id) - { - CurrentEvent().Use(); - GUIUtility.hotControl = 0; - KnobState().isDragging = false; - } - return currentValue; - } - - private void PrintValue() - { - Rect textRect = new Rect(position.x + knobSize.x / 2 - 8, position.y + knobSize.y / 2 - 8, position.width, 20); - string value = currentValue.ToString("0.##"); //FIXME: This needs to be done so it can handle any range types. - GUI.Label(textRect, value + " " + unit); - } - - private float DoKeyboardInput() - { - GUI.SetNextControlName("KnobInput"); - GUI.FocusControl("KnobInput"); - - EditorGUI.BeginChangeCheck(); - Rect inputRect = new Rect(position.x + knobSize.x / 2 - 6, position.y + knobSize.y / 2 - 7, position.width, 20); - - //FIXME: Hack - GUIStyle style = GUIStyle.none; - style.normal.textColor = new Color(.703f, .703f, .703f, 1.0f); - style.fontStyle = FontStyle.Normal; - - string newStr = EditorGUI.DelayedTextField(inputRect, currentValue.ToString("0.##"), style); - if (EditorGUI.EndChangeCheck() && !String.IsNullOrEmpty(newStr)) - { - KnobState().isEditing = false; - float newValue; - if (float.TryParse(newStr, out newValue) && newValue != currentValue) - { - return Clamp(newValue); - } - } - - return currentValue; - } - - private static Material knobMaterial; - static void CreateKnobMaterial() - { - if (!knobMaterial) - { - // use a regular IMGUI content shader - Shader shader = AssetDatabase.GetBuiltinExtraResource(typeof(Shader), "Internal-GUITextureClip.shader") as Shader; - knobMaterial = new Material(shader); - knobMaterial.hideFlags = HideFlags.HideAndDontSave; - knobMaterial.mainTexture = EditorGUIUtility.FindTexture("KnobCShape"); - knobMaterial.name = "Knob Material"; - if (knobMaterial.mainTexture == null) - Debug.Log("Did not find 'KnobCShape'"); - } - } - - Vector3 GetUVForPoint(Vector3 point) - { - Vector3 uv = new Vector3( - (point.x - position.x) / knobSize.x, - (point.y - position.y - knobSize.y) / -knobSize.y // we need to flip uv over Y otherwise image is upside-down - ); - return uv; - } - - void VertexPointWithUV(Vector3 point) - { - GL.TexCoord(GetUVForPoint(point)); - GL.Vertex(point); - } - - private void DrawValueArc(float angle) - { - if (Event.current.type != EventType.Repaint) - return; - - CreateKnobMaterial(); - - Vector3 center = new Vector3(position.x + knobSize.x / 2, position.y + knobSize.y / 2, 0); - Vector3 centerRight = new Vector3(position.x + knobSize.x, position.y + knobSize.y / 2, 0); - Vector3 bottomRight = new Vector3(position.x + knobSize.x, position.y + knobSize.y, 0); - Vector3 bottomleft = new Vector3(position.x, position.y + knobSize.y, 0); - Vector3 topLeft = new Vector3(position.x, position.y, 0); - Vector3 topRight = new Vector3(position.x + knobSize.x, position.y, 0); - - Vector3 lastCorner = bottomRight; - - knobMaterial.SetPass(0); - //Background - GL.Begin(GL.QUADS); - GL.Color(backgroundColor); - - VertexPointWithUV(topLeft); - VertexPointWithUV(topRight); - VertexPointWithUV(bottomRight); - VertexPointWithUV(bottomleft); - - GL.End(); - - //Forground - GL.Begin(GL.TRIANGLES); - GL.Color(activeColor * (GUI.enabled ? 1.0f : 0.5f)); - if (angle > 0.0f) - { - VertexPointWithUV(center); - VertexPointWithUV(centerRight); - VertexPointWithUV(bottomRight); - lastCorner = bottomRight; - - if (angle > (Mathf.PI / 2.0f)) - { - VertexPointWithUV(center); - VertexPointWithUV(bottomRight); - VertexPointWithUV(bottomleft); - lastCorner = bottomleft; - - if (angle > Mathf.PI) - { - VertexPointWithUV(center); - VertexPointWithUV(bottomleft); - VertexPointWithUV(topLeft); - lastCorner = topLeft; - } - } - if (angle == (Mathf.PI * (3.0f / 2.0f))) - { - VertexPointWithUV(center); - VertexPointWithUV(topLeft); - VertexPointWithUV(topRight); - VertexPointWithUV(center); - VertexPointWithUV(topRight); - VertexPointWithUV(centerRight); - } - else - { - //Project the last segment onto the square and draw it. - Vector3 projection; - float adjustedAngle = angle + Mathf.PI / 4.0f; - if (angle < Mathf.PI / 2.0f) - projection = bottomRight + new Vector3((knobSize.y / 2 * Mathf.Tan(Mathf.PI / 2.0f - adjustedAngle)) - knobSize.x / 2, 0, 0); - else if (angle < Mathf.PI) - projection = bottomleft + new Vector3(0, (knobSize.x / 2 * Mathf.Tan(Mathf.PI - adjustedAngle)) - knobSize.y / 2, 0); - else - projection = topLeft + new Vector3(-(knobSize.y / 2 * Mathf.Tan((Mathf.PI * 3.0f / 2.0f) - adjustedAngle)) + knobSize.x / 2, 0, 0); - - VertexPointWithUV(center); - VertexPointWithUV(lastCorner); - VertexPointWithUV(projection); - } - } - GL.End(); - } - - private float OnRepaint() - { - DrawValueArc(GetCurrentValuePercent() * Mathf.PI * (3.0f / 2.0f)); - - if (KnobState().isEditing) - return DoKeyboardInput(); - - if (showValue) - PrintValue(); - - return currentValue; - } - } - - // Show text, fixed Size input - internal static float Knob(Rect position, Vector2 knobSize, float currentValue, float start, float end, string unit, Color backgroundColor, Color activeColor, bool showValue, int id) - { - return new KnobContext(position, knobSize, currentValue, start, end, unit, backgroundColor, activeColor, showValue, id).Handle(); - } - - internal static float OffsetKnob(Rect position, float currentValue, float start, float end, float median, string unit, Color backgroundColor, Color activeColor, GUIStyle knob, int id) - { - ///@TODO Implement - return 0f; - } - } -} diff --git a/Editor/Mono/GUI/ListViewElement.cs b/Editor/Mono/GUI/ListViewElement.cs deleted file mode 100644 index 5c13c9ccdf..0000000000 --- a/Editor/Mono/GUI/ListViewElement.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal struct ListViewElement - { - public int row; - public int column; - public Rect position; - } -} diff --git a/Editor/Mono/GUI/ListViewGUI.cs b/Editor/Mono/GUI/ListViewGUI.cs deleted file mode 100644 index 9e1d4eb3eb..0000000000 --- a/Editor/Mono/GUI/ListViewGUI.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - /// *undocumented* - internal class ListViewGUI - { - static int[] dummyWidths = new int[1]; - - static internal ListViewShared.InternalListViewState ilvState = new ListViewShared.InternalListViewState(); - static int listViewHash = "ListView".GetHashCode(); - - static public ListViewShared.ListViewElementsEnumerator ListView(Rect pos, ListViewState state) - { - return DoListView(pos, state, null, string.Empty); - } - - static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, GUIStyle style, params GUILayoutOption[] options) - { - return ListView(state, 0, null, string.Empty, style, options); - } - - static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, int[] colWidths, GUIStyle style, params GUILayoutOption[] options) - { - return ListView(state, 0, colWidths, string.Empty, style, options); - } - - static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, ListViewOptions lvOptions, GUIStyle style, params GUILayoutOption[] options) - { - return ListView(state, lvOptions, null, string.Empty, style, options); - } - - static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, ListViewOptions lvOptions, string dragTitle, GUIStyle style, params GUILayoutOption[] options) - { - return ListView(state, lvOptions, null, dragTitle, style, options); - } - - static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, ListViewOptions lvOptions, int[] colWidths, string dragTitle, GUIStyle style, params GUILayoutOption[] options) - { - GUILayout.BeginHorizontal(style); - state.scrollPos = EditorGUILayout.BeginScrollView(state.scrollPos, options); - ilvState.beganHorizontal = true; - - state.draggedFrom = -1; - state.draggedTo = -1; - state.fileNames = null; - - if ((lvOptions & ListViewOptions.wantsReordering) != 0) ilvState.wantsReordering = true; - if ((lvOptions & ListViewOptions.wantsExternalFiles) != 0) ilvState.wantsExternalFiles = true; - if ((lvOptions & ListViewOptions.wantsToStartCustomDrag) != 0) ilvState.wantsToStartCustomDrag = true; - if ((lvOptions & ListViewOptions.wantsToAcceptCustomDrag) != 0) ilvState.wantsToAcceptCustomDrag = true; - - return DoListView(GUILayoutUtility.GetRect(1, state.totalRows * state.rowHeight + 3), state, colWidths, string.Empty); - } - - static public ListViewShared.ListViewElementsEnumerator DoListView(Rect pos, ListViewState state, int[] colWidths, string dragTitle) - { - int id = GUIUtility.GetControlID(listViewHash, FocusType.Passive); - state.ID = id; - - state.selectionChanged = false; - - Rect vRect; - - 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. - { - vRect = pos; - } - else - 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 - - if (vRect.width <= 0) vRect.width = 1; - if (vRect.height <= 0) vRect.height = 1; - - ilvState.rect = vRect; - - int invisibleRows = (int)((-pos.y + vRect.yMin) / state.rowHeight); - int endRow = invisibleRows + (int)System.Math.Ceiling((((vRect.yMin - pos.y) % state.rowHeight) + vRect.height) / state.rowHeight) - 1; - - if (colWidths == null) - { - dummyWidths[0] = (int)vRect.width; - colWidths = dummyWidths; - } - - ilvState.invisibleRows = invisibleRows; - ilvState.endRow = endRow; - ilvState.rectHeight = (int)vRect.height; - ilvState.state = state; - - if (invisibleRows < 0) - invisibleRows = 0; - - if (endRow >= state.totalRows) - endRow = state.totalRows - 1; - - return new ListViewShared.ListViewElementsEnumerator(ilvState, colWidths, invisibleRows, endRow, dragTitle, new Rect(0, invisibleRows * state.rowHeight, pos.width, state.rowHeight)); - } - - static public bool MultiSelection(int prevSelected, int currSelected, ref int initialSelected, ref bool[] selectedItems) - { - return ListViewShared.MultiSelection(ilvState, prevSelected, currSelected, ref initialSelected, ref selectedItems); - } - - static public bool HasMouseUp(Rect r) - { - return ListViewShared.HasMouseUp(ilvState, r, 0); - } - - static public bool HasMouseDown(Rect r) - { - return ListViewShared.HasMouseDown(ilvState, r, 0); - } - - static public bool HasMouseDown(Rect r, int button) - { - return ListViewShared.HasMouseDown(ilvState, r, button); - } - } -} diff --git a/Editor/Mono/GUI/ListViewGUILayout.cs b/Editor/Mono/GUI/ListViewGUILayout.cs deleted file mode 100644 index 60b1e549c3..0000000000 --- a/Editor/Mono/GUI/ListViewGUILayout.cs +++ /dev/null @@ -1,215 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - /// *undocumented* - internal class ListViewGUILayout - { - static int layoutedListViewHash = "layoutedListView".GetHashCode(); - - static ListViewState lvState = null; - - static int listViewHash = "ListView".GetHashCode(); - static int[] dummyWidths = new int[1]; - - static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, GUIStyle style, params GUILayoutOption[] options) - { - return ListView(state, 0, string.Empty, style, options); - } - - static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, string dragTitle, GUIStyle style, params GUILayoutOption[] options) - { - return ListView(state, 0, dragTitle, style, options); - } - - static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, ListViewOptions lvOptions, GUIStyle style, params GUILayoutOption[] options) - { - return ListView(state, lvOptions, string.Empty, style, options); - } - - static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState state, ListViewOptions lvOptions, string dragTitle, GUIStyle style, params GUILayoutOption[] options) - { - lvState = state; - - GUILayout.BeginHorizontal(style, options); // no good reason for this here, except drawing LVs background - - state.scrollPos = EditorGUILayout.BeginScrollView(state.scrollPos, options); - BeginLayoutedListview(state, GUIStyle.none); - - state.draggedFrom = -1; - state.draggedTo = -1; - state.fileNames = null; - - if ((lvOptions & ListViewOptions.wantsReordering) != 0) state.ilvState.wantsReordering = true; - if ((lvOptions & ListViewOptions.wantsExternalFiles) != 0) state.ilvState.wantsExternalFiles = true; - if ((lvOptions & ListViewOptions.wantsToStartCustomDrag) != 0) state.ilvState.wantsToStartCustomDrag = true; - if ((lvOptions & ListViewOptions.wantsToAcceptCustomDrag) != 0) state.ilvState.wantsToAcceptCustomDrag = true; - - return DoListView(state, null, dragTitle); - } - - static Rect dummyRect = new Rect(0, 0, 1, 1); - - static private ListViewShared.ListViewElementsEnumerator DoListView(ListViewState state, int[] colWidths, string dragTitle) - { - Rect vRect = dummyRect; - int invisibleRows = 0; - int endRow = 0; - - ListViewShared.InternalLayoutedListViewState ilvState = state.ilvState; - - //GUIUtility.CheckOnGUI (); - int id = GUIUtility.GetControlID(listViewHash, FocusType.Passive); - - state.ID = id; - state.selectionChanged = false; - ilvState.state = state; - - if (Event.current.type != EventType.Layout) - { - vRect = new Rect(0, state.scrollPos.y, GUIClip.visibleRect.width, GUIClip.visibleRect.height); - - if (vRect.width <= 0) vRect.width = 1; - if (vRect.height <= 0) vRect.height = 1; - - state.ilvState.rect = vRect; - - invisibleRows = (int)(vRect.yMin) / state.rowHeight; - endRow = invisibleRows + (int)System.Math.Ceiling(((vRect.yMin % state.rowHeight) + vRect.height) / state.rowHeight) - 1; - - //if (id == GUIUtility.hotControl) - //{ - // s = invisibleRows.ToString() + "::" + endRow.ToString(); - //} - - ilvState.invisibleRows = invisibleRows; - ilvState.endRow = endRow; - ilvState.rectHeight = (int)vRect.height; - - if (invisibleRows < 0) - invisibleRows = 0; - - if (endRow >= state.totalRows) - endRow = state.totalRows - 1; - } - - if (colWidths == null) - { - dummyWidths[0] = (int)vRect.width; - colWidths = dummyWidths; - } - - return new ListViewShared.ListViewElementsEnumerator(ilvState, colWidths, invisibleRows, endRow, dragTitle, new Rect(0, invisibleRows * state.rowHeight, vRect.width, state.rowHeight)); - } - - private static void BeginLayoutedListview(ListViewState state, GUIStyle style, params GUILayoutOption[] options) - { - GUILayoutedListViewGroup g = (GUILayoutedListViewGroup)GUILayoutUtility.BeginLayoutGroup(style, null, typeof(GUILayoutedListViewGroup)); - - g.state = state; - state.ilvState.group = g; - - GUIUtility.GetControlID(layoutedListViewHash, FocusType.Passive); - - switch (Event.current.type) - { - case EventType.Layout: - { - g.resetCoords = false; - g.isVertical = true; - g.ApplyOptions(options); - break; - } - } - } - - /// *undocumented* - internal class GUILayoutedListViewGroup : GUILayoutGroup - { - internal ListViewState state; - - public override void CalcWidth() - { - // Make LVs width independent of widths of elements inside it - base.CalcWidth(); - minWidth = 0; - maxWidth = 0; - stretchWidth = 10000; - } - - public override void CalcHeight() - { - minHeight = 0; - maxHeight = 0; - - base.CalcHeight(); - - margin.top = 0; - margin.bottom = 0; - - if (minHeight == 0) // empty lv? - { - minHeight = 1; - maxHeight = 1; - state.rowHeight = 1; - } - else - { - state.rowHeight = (int)minHeight; - minHeight *= state.totalRows; - maxHeight *= state.totalRows; - } - } - - private void AddYRecursive(GUILayoutEntry e, float y) - { - // this looks kind of bad, but in 99% of cases it would only be one level depth (e.g. few labels inside BeginHorizontal) - e.rect.y += y; - - GUILayoutGroup g = e as GUILayoutGroup; - - if (g != null) - { - for (int i = 0; i < g.entries.Count; i++) - AddYRecursive((GUILayoutEntry)g.entries[i], y); - } - } - - public void AddY() - { - if (entries.Count > 0) - AddYRecursive((GUILayoutEntry)entries[0], ((GUILayoutEntry)entries[0]).minHeight); - } - - public void AddY(float val) - { - if (entries.Count > 0) - AddYRecursive((GUILayoutEntry)entries[0], val); - } - } - - static public bool MultiSelection(int prevSelected, int currSelected, ref int initialSelected, ref bool[] selectedItems) - { - return ListViewShared.MultiSelection(lvState.ilvState, prevSelected, currSelected, ref initialSelected, ref selectedItems); - } - - static public bool HasMouseUp(Rect r) - { - return ListViewShared.HasMouseUp(lvState.ilvState, r, 0); - } - - static public bool HasMouseDown(Rect r) - { - return ListViewShared.HasMouseDown(lvState.ilvState, r, 0); - } - - static public bool HasMouseDown(Rect r, int button) - { - return ListViewShared.HasMouseDown(lvState.ilvState, r, button); - } - } -} diff --git a/Editor/Mono/GUI/ListViewOptions.cs b/Editor/Mono/GUI/ListViewOptions.cs deleted file mode 100644 index f488faf3aa..0000000000 --- a/Editor/Mono/GUI/ListViewOptions.cs +++ /dev/null @@ -1,8 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor -{ - internal enum ListViewOptions { wantsReordering = 1, wantsExternalFiles = 2, wantsToStartCustomDrag = 4, wantsToAcceptCustomDrag = 8 }; -} diff --git a/Editor/Mono/GUI/ListViewShared.cs b/Editor/Mono/GUI/ListViewShared.cs deleted file mode 100644 index f689d79ec9..0000000000 --- a/Editor/Mono/GUI/ListViewShared.cs +++ /dev/null @@ -1,694 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - /// *undocumented* - internal class ListViewShared - { - public static bool OSX = Application.platform == RuntimePlatform.OSXEditor; - - internal static int dragControlID = -1; - internal static bool isDragging = false; - - /// *undocumented* - internal class InternalListViewState - { - public int id = -1; - public int invisibleRows; - public int endRow; - public int rectHeight; - public ListViewState state; - public bool beganHorizontal = false; - public Rect rect; - public bool wantsReordering = false; - public bool wantsExternalFiles = false; - public bool wantsToStartCustomDrag = false; - public bool wantsToAcceptCustomDrag = false; - public int dragItem; - } - - /// *undocumented* - internal class InternalLayoutedListViewState : InternalListViewState - { - public ListViewGUILayout.GUILayoutedListViewGroup group; - } - - /// *undocumented* - internal class Constants - { - // this should not be pre-setup - // different windows (having different styles set) can draw using this - public static string insertion = "PR Insertion"; - } - - // Returns if LV selection has changed - /// *undocumented* - static bool DoLVPageUpDown(InternalListViewState ilvState, ref int selectedRow, ref Vector2 scrollPos, bool up) - { - int visibleRows = ilvState.endRow - ilvState.invisibleRows; - - if (up) - { - if (OSX) - { - scrollPos.y -= ilvState.state.rowHeight * visibleRows; - - if (scrollPos.y < 0) - scrollPos.y = 0; - } - else - { - selectedRow -= visibleRows; - - if (selectedRow < 0) - selectedRow = 0; - - return true; - } - } - else - { - if (OSX) - { - scrollPos.y += ilvState.state.rowHeight * visibleRows; - //FIXME: does this need an upper bound check? - } - else - { - selectedRow += visibleRows; - - if (selectedRow >= ilvState.state.totalRows) - selectedRow = ilvState.state.totalRows - 1; - - return true; - } - } - - return false; - } - - /// *undocumented* - static internal bool ListViewKeyboard(InternalListViewState ilvState, int totalCols) - { - int totalRows = ilvState.state.totalRows; - - if ((Event.current.type != EventType.KeyDown) || (totalRows == 0)) - return false; - - if ((GUIUtility.keyboardControl != ilvState.state.ID) || - Event.current.GetTypeForControl(ilvState.state.ID) != EventType.KeyDown) - return false; - - return SendKey(ilvState, Event.current.keyCode, totalCols); - } - - internal static void SendKey(ListViewState state, KeyCode keyCode) - { - SendKey(state.ilvState, keyCode, 1); - } - - internal static bool SendKey(InternalListViewState ilvState, KeyCode keyCode, int totalCols) - { - var state = ilvState.state; - - //ilvState.state.row, ref ilvState.state.column, ref ilvState.state.scrollPos - switch (keyCode) - { - case KeyCode.UpArrow: - { - if (state.row > 0) - state.row--; - break; - } - case KeyCode.DownArrow: - { - if (state.row < state.totalRows - 1) - state.row++; - break; - } - case KeyCode.Home: - { - state.row = 0; - break; - } - case KeyCode.End: - { - state.row = state.totalRows - 1; - break; - } - case KeyCode.LeftArrow: - if (state.column > 0) - state.column--; - break; - case KeyCode.RightArrow: - if (state.column < totalCols - 1) - state.column++; - break; - - case KeyCode.PageUp: - { - if (!DoLVPageUpDown(ilvState, ref state.row, ref state.scrollPos, true)) - { - Event.current.Use(); - return false; - } - break; - } - case KeyCode.PageDown: - { - if (!DoLVPageUpDown(ilvState, ref state.row, ref state.scrollPos, false)) - { - Event.current.Use(); - return false; - } - break; - } - default: - return false; - } - - state.scrollPos = ListViewScrollToRow(ilvState, state.scrollPos, state.row); - Event.current.Use(); - return true; - } - - static internal bool HasMouseDown(InternalListViewState ilvState, Rect r) - { - return HasMouseDown(ilvState, r, 0); - } - - static internal bool HasMouseDown(InternalListViewState ilvState, Rect r, int button) - { - if (Event.current.type == EventType.MouseDown && Event.current.button == button) - { - if (r.Contains(Event.current.mousePosition)) - { - GUIUtility.hotControl = ilvState.state.ID; - GUIUtility.keyboardControl = ilvState.state.ID; - ListViewShared.isDragging = false; - Event.current.Use(); - return true; - } - } - - return false; - } - - static internal bool HasMouseUp(InternalListViewState ilvState, Rect r) - { - return HasMouseUp(ilvState, r, 0); - } - - static internal bool HasMouseUp(InternalListViewState ilvState, Rect r, int button) - { - if (Event.current.type == EventType.MouseUp && Event.current.button == button) - { - if (r.Contains(Event.current.mousePosition)) - { - GUIUtility.hotControl = 0; - Event.current.Use(); - return true; - } - } - - return false; - } - - // Returns if selection was actually changed - static internal bool MultiSelection(InternalListViewState ilvState, int prevSelected, int currSelected, ref int initialSelected, ref bool[] selectedItems) - { - bool shiftIsDown = Event.current.shift; - bool ctrlIsDown = EditorGUI.actionKey; - bool selChanged = false; - - if ((shiftIsDown || ctrlIsDown) && (initialSelected == -1)) - initialSelected = prevSelected; - - // multi selection - if (shiftIsDown) - { - int from = System.Math.Min(initialSelected, currSelected); - int to = System.Math.Max(initialSelected, currSelected); - - if (!ctrlIsDown) - { - for (int i = 0; i < from; i++) - { - if (selectedItems[i]) - selChanged = true; - - selectedItems[i] = false; - } - - for (int i = to + 1; i < selectedItems.Length; i++) - { - if (selectedItems[i]) - selChanged = true; - - selectedItems[i] = false; - } - } - - if (from < 0) - from = to; - - for (int i = from; i <= to; i++) - { - if (!selectedItems[i]) - selChanged = true; - - selectedItems[i] = true; - } - } - else if (ctrlIsDown) - { - selectedItems[currSelected] = !selectedItems[currSelected]; - initialSelected = currSelected; - selChanged = true; - } - else - { - if (!selectedItems[currSelected]) - selChanged = true; - - for (int i = 0; i < selectedItems.Length; i++) - { - if (selectedItems[i] && currSelected != i) - selChanged = true; - - selectedItems[i] = false; - } - - initialSelected = -1; - selectedItems[currSelected] = true; - } - - if (ilvState != null) - ilvState.state.scrollPos = ListViewScrollToRow(ilvState, currSelected); - - return selChanged; - } - - static internal Vector2 ListViewScrollToRow(InternalListViewState ilvState, int row) - { - return ListViewScrollToRow(ilvState, ilvState.state.scrollPos, row); - } - - static internal int ListViewScrollToRow(InternalListViewState ilvState, int currPosY, int row) - { - return (int)ListViewScrollToRow(ilvState, new Vector2(0, currPosY), row).y; - } - - static internal Vector2 ListViewScrollToRow(InternalListViewState ilvState, Vector2 currPos, int row) - { - if ((ilvState.invisibleRows < row) && (ilvState.endRow > row)) - return currPos; - - if (row <= ilvState.invisibleRows) - currPos.y = ilvState.state.rowHeight * row; - else - currPos.y = ilvState.state.rowHeight * (row + 1) - ilvState.rectHeight; - - if (currPos.y < 0) - currPos.y = 0; - else if (currPos.y > ilvState.state.totalRows * ilvState.state.rowHeight - ilvState.rectHeight) - currPos.y = ilvState.state.totalRows * ilvState.state.rowHeight - ilvState.rectHeight; - - return currPos; - } - - /// *undocumented* - internal class ListViewElementsEnumerator : IEnumerator - { - private int[] colWidths; - private int xTo; - private int yFrom; - private int yTo; - - private Rect firstRect; - private Rect rect; - private int xPos = -1; - private int yPos = -1; - private ListViewElement element; - - private InternalListViewState ilvState; - private InternalLayoutedListViewState ilvStateL; - - private bool quiting; - private bool isLayouted; - - private string dragTitle; - - internal ListViewElementsEnumerator(InternalListViewState ilvState, int[] colWidths, int yFrom, int yTo, string dragTitle, Rect firstRect) - { - this.colWidths = colWidths; - this.xTo = colWidths.Length - 1; - this.yFrom = yFrom; - this.yTo = yTo; - this.firstRect = firstRect; - this.rect = firstRect; - this.quiting = ilvState.state.totalRows == 0; - - this.ilvState = ilvState; - this.ilvStateL = ilvState as InternalLayoutedListViewState; - - this.isLayouted = ilvStateL != null; - - this.dragTitle = dragTitle; - - ilvState.state.customDraggedFromID = 0; - - Reset(); - } - - public bool MoveNext() - { - if (xPos > -1) - { - if (ListViewShared.HasMouseDown(ilvState, rect)) - { - ilvState.state.selectionChanged = true; - ilvState.state.row = yPos; - ilvState.state.column = xPos; - ilvState.state.scrollPos = ListViewShared.ListViewScrollToRow(ilvState, yPos); // this is about clicking on a row that is partially visible - - if ((ilvState.wantsReordering || ilvState.wantsToStartCustomDrag) && (GUIUtility.hotControl == ilvState.state.ID)) - { - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), ilvState.state.ID); - delay.mouseDownPosition = Event.current.mousePosition; - ilvState.dragItem = yPos; - dragControlID = ilvState.state.ID; - } - } - // On Mouse drag, start drag & drop - if (!ListViewShared.isDragging && - (ilvState.wantsReordering || ilvState.wantsToStartCustomDrag) && - GUIUtility.hotControl == ilvState.state.ID && - Event.current.type == EventType.MouseDrag && - GUIClip.visibleRect.Contains(Event.current.mousePosition)) - { - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), ilvState.state.ID); - - if (delay.CanStartDrag()) - { - DragAndDrop.PrepareStartDrag(); - - DragAndDrop.objectReferences = new UnityEngine.Object[] {}; // this IS required for dragging to work - DragAndDrop.paths = null; - - if (ilvState.wantsReordering) - { - ilvState.state.dropHereRect = new Rect(ilvState.rect.x, 0, ilvState.rect.width, ilvState.state.rowHeight * 2); - DragAndDrop.StartDrag(dragTitle); - } - else if (ilvState.wantsToStartCustomDrag) - { - DragAndDrop.SetGenericData("CustomDragID", ilvState.state.ID); - DragAndDrop.StartDrag(dragTitle); - } - - ListViewShared.isDragging = true; - } - - Event.current.Use(); - } - } - - xPos++; - - if (xPos > xTo) - { - xPos = 0; - yPos++; - - rect.x = firstRect.x; - rect.width = colWidths[0]; - - if (yPos > yTo) - { - quiting = true; - } - else // move vertically - { - rect.y += rect.height; - } - } - else // move horizontally - { - if (xPos >= 1) - rect.x += colWidths[xPos - 1]; - - rect.width = colWidths[xPos]; - } - - element.row = yPos; - element.column = xPos; - element.position = rect; - - if (element.row >= ilvState.state.totalRows) - quiting = true; - - if (isLayouted && Event.current.type == EventType.Layout) - { - // this is just "on layout event enumerate just first row" (so we get height of single row) - if (yFrom + 1 == yPos) - { - quiting = true; - } - } - - if (isLayouted && yPos != yFrom) - GUILayout.EndHorizontal(); - - if (quiting) - { - if (ilvState.state.drawDropHere && Event.current.GetTypeForControl(ilvState.state.ID) == EventType.Repaint) - { - GUIStyle insertion = Constants.insertion; - insertion.Draw(insertion.margin.Remove(ilvState.state.dropHereRect), false, false, false, false); - } - - if (ListViewShared.ListViewKeyboard(ilvState, colWidths.Length)) - ilvState.state.selectionChanged = true; - - if (Event.current.GetTypeForControl(ilvState.state.ID) == EventType.MouseUp) - { - GUIUtility.hotControl = 0; - } - - if (ilvState.wantsReordering && (GUIUtility.hotControl == ilvState.state.ID)) - { - ListViewState lv = ilvState.state; - - switch (Event.current.type) - { - case EventType.DragUpdated: - { - DragAndDrop.visualMode = ilvState.rect.Contains(Event.current.mousePosition) ? - DragAndDropVisualMode.Move : DragAndDropVisualMode.None; - - Event.current.Use(); - - if (DragAndDrop.visualMode != DragAndDropVisualMode.None) - { - lv.dropHereRect.y = (Mathf.RoundToInt(Event.current.mousePosition.y / lv.rowHeight) - 1) * lv.rowHeight; - - if (lv.dropHereRect.y >= lv.rowHeight * lv.totalRows) - lv.dropHereRect.y = lv.rowHeight * (lv.totalRows - 1); - - lv.drawDropHere = true; - } - - break; - } - case EventType.DragPerform: - { - if (GUIClip.visibleRect.Contains(Event.current.mousePosition)) - { - ilvState.state.draggedFrom = ilvState.dragItem; - ilvState.state.draggedTo = Mathf.RoundToInt(Event.current.mousePosition.y / lv.rowHeight); - - if (ilvState.state.draggedTo > ilvState.state.totalRows) - ilvState.state.draggedTo = ilvState.state.totalRows; - - // the guy handling this would better actually rearrange items... - if (ilvState.state.draggedTo > ilvState.state.draggedFrom) - ilvState.state.row = ilvState.state.draggedTo - 1; - else - ilvState.state.row = ilvState.state.draggedTo; - - ilvState.state.selectionChanged = true; - - DragAndDrop.AcceptDrag(); - Event.current.Use(); - ilvState.wantsReordering = false; - ilvState.state.drawDropHere = false; - } - - GUIUtility.hotControl = 0; - break; - } - case EventType.DragExited: - { - ilvState.wantsReordering = false; - ilvState.state.drawDropHere = false; - - GUIUtility.hotControl = 0; - break; - } - } - } - else if (ilvState.wantsExternalFiles) - { - switch (Event.current.type) - { - case EventType.DragUpdated: - { - if ((GUIClip.visibleRect.Contains(Event.current.mousePosition)) && - (DragAndDrop.paths != null) && (DragAndDrop.paths.Length != 0)) // dragging files from somewhere - { - DragAndDrop.visualMode = ilvState.rect.Contains(Event.current.mousePosition) ? - DragAndDropVisualMode.Copy : DragAndDropVisualMode.None; - - Event.current.Use(); - - if (DragAndDrop.visualMode != DragAndDropVisualMode.None) - { - ilvState.state.dropHereRect = new Rect(ilvState.rect.x, - (Mathf.RoundToInt(Event.current.mousePosition.y / ilvState.state.rowHeight) - 1) * ilvState.state.rowHeight, - ilvState.rect.width, ilvState.state.rowHeight); - - if (ilvState.state.dropHereRect.y >= ilvState.state.rowHeight * ilvState.state.totalRows) - ilvState.state.dropHereRect.y = ilvState.state.rowHeight * (ilvState.state.totalRows - 1); - - ilvState.state.drawDropHere = true; - } - } - break; - } - case EventType.DragPerform: - { - if (GUIClip.visibleRect.Contains(Event.current.mousePosition)) - { - ilvState.state.fileNames = DragAndDrop.paths; - DragAndDrop.AcceptDrag(); - Event.current.Use(); - ilvState.wantsExternalFiles = false; - ilvState.state.drawDropHere = false; - ilvState.state.draggedTo = Mathf.RoundToInt(Event.current.mousePosition.y / ilvState.state.rowHeight); - if (ilvState.state.draggedTo > ilvState.state.totalRows) - ilvState.state.draggedTo = ilvState.state.totalRows; - ilvState.state.row = ilvState.state.draggedTo; - } - - GUIUtility.hotControl = 0; - - break; - } - case EventType.DragExited: - { - ilvState.wantsExternalFiles = false; - ilvState.state.drawDropHere = false; - - GUIUtility.hotControl = 0; - break; - } - } - } - else if (ilvState.wantsToAcceptCustomDrag && (dragControlID != ilvState.state.ID)) - { - switch (Event.current.type) - { - case EventType.DragUpdated: - { - object data = DragAndDrop.GetGenericData("CustomDragID"); - - if (GUIClip.visibleRect.Contains(Event.current.mousePosition) && data != null) - { - DragAndDrop.visualMode = ilvState.rect.Contains(Event.current.mousePosition) ? - DragAndDropVisualMode.Move : DragAndDropVisualMode.None; - - Event.current.Use(); - } - break; - } - case EventType.DragPerform: - { - object data = DragAndDrop.GetGenericData("CustomDragID"); - - if (GUIClip.visibleRect.Contains(Event.current.mousePosition) && data != null) - { - ilvState.state.customDraggedFromID = (int)data; - DragAndDrop.AcceptDrag(); - Event.current.Use(); - } - - GUIUtility.hotControl = 0; - break; - } - case EventType.DragExited: - { - GUIUtility.hotControl = 0; - break; - } - } - } - - if (ilvState.beganHorizontal) - { - EditorGUILayout.EndScrollView(); - GUILayout.EndHorizontal(); - ilvState.beganHorizontal = false; - } - - if (isLayouted) - { - GUILayoutUtility.EndLayoutGroup(); - EditorGUILayout.EndScrollView(); - } - - ilvState.wantsReordering = false; - ilvState.wantsExternalFiles = false; - } - else if (isLayouted) - { - if (yPos != yFrom) - { - ilvStateL.group.ResetCursor(); - ilvStateL.group.AddY(); - } - else - ilvStateL.group.AddY(ilvState.invisibleRows * ilvState.state.rowHeight); - } - - if (isLayouted) - { - if (!quiting) - GUILayout.BeginHorizontal(GUIStyle.none); // for each row - else - GUILayout.EndHorizontal(); // the one used for drawing LVs background - } - - return !quiting; - } - - public void Reset() - { - xPos = -1; - yPos = yFrom; - } - - ListViewElement IEnumerator.Current { get { return element; } } - object IEnumerator.Current { get { return element; } } - - public IEnumerator GetEnumerator() { return this; } - public void Dispose() {} - } - } -} diff --git a/Editor/Mono/GUI/ListViewState.cs b/Editor/Mono/GUI/ListViewState.cs deleted file mode 100644 index 5126afd108..0000000000 --- a/Editor/Mono/GUI/ListViewState.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - /// *undocumented* - [System.Serializable] - internal class ListViewState - { - const int c_rowHeight = 16; //TODO: - public int row; - public int column; - public Vector2 scrollPos; - public int totalRows; - public int rowHeight; - - public int ID; - public bool selectionChanged; - public int draggedFrom; - public int draggedTo; - public bool drawDropHere = false; - public Rect dropHereRect = new Rect(0, 0, 0, 0); - public string[] fileNames = null; - public int customDraggedFromID = 0; - - public ListViewState() { Init(0, c_rowHeight); } - public ListViewState(int totalRows) { Init(totalRows, c_rowHeight); } - public ListViewState(int totalRows, int rowHeight) { Init(totalRows, rowHeight); } - - /// *undocumented* - internal ListViewShared.InternalLayoutedListViewState ilvState = new ListViewShared.InternalLayoutedListViewState(); - - private void Init(int totalRows, int rowHeight) - { - this.row = -1; - this.column = 0; - this.scrollPos = Vector2.zero; - this.totalRows = totalRows; - this.rowHeight = rowHeight; - - selectionChanged = false; - } - } -} diff --git a/Editor/Mono/GUI/MainView.cs b/Editor/Mono/GUI/MainView.cs deleted file mode 100644 index 24f90a0854..0000000000 --- a/Editor/Mono/GUI/MainView.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class MainView : View, ICleanuppable - { - const float kStatusbarHeight = 20; - - private static readonly Vector2 kMinSize = new Vector2(950, 300); - private static readonly Vector2 kMaxSize = new Vector2(10000, 10000); - - void OnEnable() - { - SetMinMaxSizes(kMinSize, kMaxSize); - } - - protected override void SetPosition(Rect newPos) - { - base.SetPosition(newPos); - if (children.Length == 0) - return; - Toolbar t = (Toolbar)children[0]; - children[0].position = new Rect(0, 0, newPos.width, t.CalcHeight()); - if (children.Length > 2) - { - children[1].position = new Rect(0, t.CalcHeight(), newPos.width, newPos.height - t.CalcHeight() - children[2].position.height); - children[2].position = new Rect(0, newPos.height - children[2].position.height, newPos.width, children[2].position.height); - } - } - - protected override void ChildrenMinMaxChanged() - { - if (children.Length == 3) - { - Toolbar t = (Toolbar)children[0]; - var min = new Vector2(kMinSize.x, Mathf.Max(kMinSize.y, t.CalcHeight() + kStatusbarHeight + children[1].minSize.y)); - SetMinMaxSizes(min, kMaxSize); - } - base.ChildrenMinMaxChanged(); - } - - public static void MakeMain() - { - //Set up default window size - ContainerWindow cw = ScriptableObject.CreateInstance(); - var main = ScriptableObject.CreateInstance(); - main.SetMinMaxSizes(kMinSize, kMaxSize); - cw.rootView = main; - - Resolution res = Screen.currentResolution; - int width = Mathf.Clamp(res.width * 3 / 4, 800, 1400); - int height = Mathf.Clamp(res.height * 3 / 4, 600, 950); - cw.position = new Rect(60, 20, width, height); - - cw.Show(ShowMode.MainWindow, true, true); - cw.DisplayAllViews(); - } - - public void Cleanup() - { - // If we only have one child left, this means all views have been dragged out. - // So we resize the window to be just the toolbar - // On windows, this might need some special handling for the main menu - if (children[1].children.Length == 0) - { - Rect r = window.position; - Toolbar t = (Toolbar)children[0]; - r.height = t.CalcHeight() + kStatusbarHeight; - } - } - } -} //namespace diff --git a/Editor/Mono/GUI/MaskFieldGUI.cs b/Editor/Mono/GUI/MaskFieldGUI.cs deleted file mode 100644 index 59137ba93d..0000000000 --- a/Editor/Mono/GUI/MaskFieldGUI.cs +++ /dev/null @@ -1,246 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - // Class for storing state for mask menus so we can get the info back to OnGUI from the user selection - internal static class MaskFieldGUI - { - // Class for storing state for mask menus so we can get the info back to OnGUI from the user selection - private class MaskCallbackInfo - { - // The global shared popup state - public static MaskCallbackInfo m_Instance; - - // Name of the command event sent from the popup menu to OnGUI when user has changed selection - private const string kMaskMenuChangedMessage = "MaskMenuChanged"; - - // The control ID of the popup menu that is currently displayed. - // Used to pass selection changes back again - private readonly int m_ControlID; - - // New mask value - private int m_NewMask; - - // Which view should we send it to. - private readonly GUIView m_SourceView; - - public MaskCallbackInfo(int controlID) - { - m_ControlID = controlID; - m_SourceView = GUIView.current; - } - - public static int GetSelectedValueForControl(int controlID, int mask, out int changedFlags, out bool changedToValue) - { - var evt = Event.current; - - // No flags are changed by default - changedFlags = 0; - changedToValue = false; - - if (evt.type == EventType.ExecuteCommand && evt.commandName == kMaskMenuChangedMessage) - { - if (m_Instance == null) - { - Debug.LogError("Mask menu has no instance"); - return mask; - } - if (m_Instance.m_ControlID == controlID) - { - changedFlags = mask ^ m_Instance.m_NewMask; - changedToValue = (m_Instance.m_NewMask & changedFlags) != 0; - - if (changedFlags != 0) - { - mask = m_Instance.m_NewMask; - GUI.changed = true; - } - - m_Instance = null; - evt.Use(); - } - } - return mask; - } - - internal void SetMaskValueDelegate(object userData, string[] options, int selected) - { - int[] optionMaskValues = (int[])userData; - m_NewMask = optionMaskValues[selected]; - - if (m_SourceView) - m_SourceView.SendEvent(EditorGUIUtility.CommandEvent(kMaskMenuChangedMessage)); - } - } - - /// Make a field for a generic mask. - internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, GUIStyle style) - { - int dummyInt; - bool dummyBool; - return DoMaskField(position, controlID, mask, flagNames, style, out dummyInt, out dummyBool); - } - - internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, int[] flagValues, GUIStyle style) - { - int dummyInt; - bool dummyBool; - return DoMaskField(position, controlID, mask, flagNames, flagValues, style, out dummyInt, out dummyBool); - } - - internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, GUIStyle style, out int changedFlags, out bool changedToValue) - { - var flagValues = new int[flagNames.Length]; - for (int i = 0; i < flagValues.Length; ++i) - flagValues[i] = (1 << i); - - return DoMaskField(position, controlID, mask, flagNames, flagValues, style, out changedFlags, out changedToValue); - } - - /// Make a field for a generic mask. - /// This version also gives you back which flags were changed and what they were changed to. - /// This is useful if you want to make the same change to multiple objects. - internal static int DoMaskField(Rect position, int controlID, int mask, string[] flagNames, int[] flagValues, GUIStyle style, out int changedFlags, out bool changedToValue) - { - mask = MaskCallbackInfo.GetSelectedValueForControl(controlID, mask, out changedFlags, out changedToValue); - - string buttonText; - string[] optionNames; - int[] optionMaskValues; - int[] selectedOptions; - GetMenuOptions(mask, flagNames, flagValues, out buttonText, out optionNames, out optionMaskValues, out selectedOptions); - - Event evt = Event.current; - if (evt.type == EventType.Repaint) - { - GUIContent buttonContent = EditorGUI.showMixedValue ? EditorGUI.mixedValueContent : EditorGUIUtility.TempContent(buttonText); - style.Draw(position, buttonContent, controlID, false); - } - else if ((evt.type == EventType.MouseDown && position.Contains(evt.mousePosition)) || evt.MainActionKeyForControl(controlID)) - { - MaskCallbackInfo.m_Instance = new MaskCallbackInfo(controlID); - evt.Use(); - EditorUtility.DisplayCustomMenu(position, optionNames, - // Only show selections if we are not multi-editing - EditorGUI.showMixedValue ? new int[] {} : selectedOptions, - // optionMaskValues is from the pool so use a clone of the values for the current control - MaskCallbackInfo.m_Instance.SetMaskValueDelegate, optionMaskValues.Clone()); - EditorGUIUtility.keyboardControl = controlID; - } - - return mask; - } - - private static readonly List s_OptionNames = new List(); - private static readonly List s_OptionValues = new List(); - private static readonly List s_SelectedOptions = new List(); - private static readonly HashSet s_SelectedOptionsSet = new HashSet(); - - private static T[] GetBuffer(List pool, int bufferLength) - { - for (int i = pool.Count; i <= bufferLength; ++i) - pool.Add(null); - if (pool[bufferLength] == null) - pool[bufferLength] = new T[bufferLength]; - var buffer = pool[bufferLength]; - for (int i = 0, length = buffer.Length; i < length; ++i) - buffer[i] = default(T); - return buffer; - } - - internal static void GetMenuOptions(int mask, string[] flagNames, int[] flagValues, - out string buttonText, out string[] optionNames, out int[] optionMaskValues, out int[] selectedOptions) - { - bool hasNothingName = (flagValues[0] == 0); - bool hasEverythingName = (flagValues[flagValues.Length - 1] == ~0); - - var nothingName = (hasNothingName ? flagNames[0] : "Nothing"); - var everythingName = (hasEverythingName ? flagNames[flagValues.Length - 1] : "Everything"); - - var optionCount = flagNames.Length + (hasNothingName ? 0 : 1) + (hasEverythingName ? 0 : 1); - var flagCount = flagNames.Length - (hasNothingName ? 1 : 0) - (hasEverythingName ? 1 : 0); - - // These indices refer to flags that are not 0 and ~0 - var flagStartIndex = (hasNothingName ? 1 : 0); - var flagEndIndex = flagStartIndex + flagCount; - - // Button text - buttonText = "Mixed ..."; - if (mask == 0) - buttonText = nothingName; - else if (mask == ~0) - buttonText = everythingName; - else - { - for (var flagIndex = flagStartIndex; flagIndex < flagEndIndex; flagIndex++) - { - if (mask == flagValues[flagIndex]) - buttonText = flagNames[flagIndex]; - } - } - - // Options names - optionNames = GetBuffer(s_OptionNames, optionCount); - optionNames[0] = nothingName; - optionNames[1] = everythingName; - for (var flagIndex = flagStartIndex; flagIndex < flagEndIndex; flagIndex++) - { - var optionIndex = flagIndex - flagStartIndex + 2; - optionNames[optionIndex] = flagNames[flagIndex]; - } - - var flagMask = 0; // Disjunction of all flags (except 0 and ~0) - var intermediateMask = 0; // Mask used to compute new mask value for each option - - // Selected options - s_SelectedOptionsSet.Clear(); - if (mask == 0) - s_SelectedOptionsSet.Add(0); - if (mask == ~0) - s_SelectedOptionsSet.Add(1); - for (var flagIndex = flagStartIndex; flagIndex < flagEndIndex; flagIndex++) - { - var flagValue = flagValues[flagIndex]; - flagMask |= flagValue; - if ((mask & flagValue) == flagValue) - { - var optionIndex = flagIndex - flagStartIndex + 2; - s_SelectedOptionsSet.Add(optionIndex); - intermediateMask |= flagValue; - } - } - selectedOptions = GetBuffer(s_SelectedOptions, s_SelectedOptionsSet.Count); - var x = 0; - foreach (var selected in s_SelectedOptionsSet) - { - selectedOptions[x] = selected; - ++x; - } - - // Option mask values - optionMaskValues = GetBuffer(s_OptionValues, optionCount); - optionMaskValues[0] = 0; - optionMaskValues[1] = ~0; - for (var flagIndex = flagStartIndex; flagIndex < flagEndIndex; flagIndex++) - { - var optionIndex = flagIndex - flagStartIndex + 2; - var flagValue = flagValues[flagIndex]; - var flagSet = ((intermediateMask & flagValue) == flagValue); - var newMask = (flagSet ? intermediateMask & ~flagValue : intermediateMask | flagValue); - - // If all flag options are selected the mask becomes ~0 to be consistent with the "Everything" option - if (newMask == flagMask) - newMask = ~0; - - optionMaskValues[optionIndex] = newMask; - } - } - } -} diff --git a/Editor/Mono/GUI/ObjectField.cs b/Editor/Mono/GUI/ObjectField.cs deleted file mode 100644 index e5a0cd8024..0000000000 --- a/Editor/Mono/GUI/ObjectField.cs +++ /dev/null @@ -1,502 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor.SceneManagement; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - public sealed partial class EditorGUI - { - [Flags] - internal enum ObjectFieldValidatorOptions - { - None = 0, - ExactObjectTypeValidation = (1 << 0) - } - - internal delegate Object ObjectFieldValidator(Object[] references, System.Type objType, SerializedProperty property, ObjectFieldValidatorOptions options); - - internal static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, System.Type objType, SerializedProperty property, ObjectFieldValidator validator, bool allowSceneObjects) - { - return DoObjectField(position, dropRect, id, obj, objType, property, validator, allowSceneObjects, EditorStyles.objectField); - } - - internal enum ObjectFieldVisualType { IconAndText, LargePreview, MiniPreview } - - // when current event is mouse click, this function pings the object, or - // if shift/control is pressed and object is a texture, pops up a large texture - // preview window - internal static void PingObjectOrShowPreviewOnClick(Object targetObject, Rect position) - { - if (targetObject == null) - return; - - Event evt = Event.current; - // ping object - bool anyModifiersPressed = evt.shift || evt.control; - if (!anyModifiersPressed) - { - EditorGUIUtility.PingObject(targetObject); - return; - } - - // show large object preview popup; right now only for textures - if (targetObject is Texture) - { - PopupWindowWithoutFocus.Show( - new RectOffset(6, 3, 0, 3).Add(position), - new ObjectPreviewPopup(targetObject), - new[] { PopupLocationHelper.PopupLocation.Left, PopupLocationHelper.PopupLocation.Below, PopupLocationHelper.PopupLocation.Right }); - } - } - - static Object AssignSelectedObject(SerializedProperty property, ObjectFieldValidator validator, System.Type objectType, Event evt) - { - Object[] references = { ObjectSelector.GetCurrentObject() }; - Object assigned = validator(references, objectType, property, ObjectFieldValidatorOptions.None); - - // Assign the value - if (property != null) - property.objectReferenceValue = assigned; - - GUI.changed = true; - evt.Use(); - return assigned; - } - - internal static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, System.Type objType, SerializedProperty property, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style) - { - if (validator == null) - validator = ValidateObjectFieldAssignment; - Event evt = Event.current; - EventType eventType = evt.type; - - // special case test, so we continue to ping/select objects with the object field disabled - if (!GUI.enabled && GUIClip.enabled && (Event.current.rawType == EventType.MouseDown)) - eventType = Event.current.rawType; - - bool hasThumbnail = EditorGUIUtility.HasObjectThumbnail(objType); - - // Determine visual type - ObjectFieldVisualType visualType = ObjectFieldVisualType.IconAndText; - if (hasThumbnail && position.height <= kObjectFieldMiniThumbnailHeight && position.width <= kObjectFieldMiniThumbnailWidth) - visualType = ObjectFieldVisualType.MiniPreview; - else if (hasThumbnail && position.height > kSingleLineHeight) - visualType = ObjectFieldVisualType.LargePreview; - - Vector2 oldIconSize = EditorGUIUtility.GetIconSize(); - if (visualType == ObjectFieldVisualType.IconAndText) - EditorGUIUtility.SetIconSize(new Vector2(12, 12)); // Have to be this small to fit inside a single line height ObjectField - else if (visualType == ObjectFieldVisualType.LargePreview) - EditorGUIUtility.SetIconSize(new Vector2(64, 64)); - - switch (eventType) - { - case EventType.DragExited: - if (GUI.enabled) - HandleUtility.Repaint(); - - break; - case EventType.DragUpdated: - case EventType.DragPerform: - - if (dropRect.Contains(Event.current.mousePosition) && GUI.enabled) - { - Object[] references = DragAndDrop.objectReferences; - Object validatedObject = validator(references, objType, property, ObjectFieldValidatorOptions.None); - - if (validatedObject != null) - { - // If scene objects are not allowed and object is a scene object then clear - if (!allowSceneObjects && !EditorUtility.IsPersistent(validatedObject)) - validatedObject = null; - } - - if (validatedObject != null) - { - DragAndDrop.visualMode = DragAndDropVisualMode.Generic; - if (eventType == EventType.DragPerform) - { - if (property != null) - property.objectReferenceValue = validatedObject; - else - obj = validatedObject; - - GUI.changed = true; - DragAndDrop.AcceptDrag(); - DragAndDrop.activeControlID = 0; - } - else - { - DragAndDrop.activeControlID = id; - } - Event.current.Use(); - } - } - break; - case EventType.MouseDown: - // Ignore right clicks - if (Event.current.button != 0) - break; - if (position.Contains(Event.current.mousePosition)) - { - // Get button rect for Object Selector - Rect buttonRect; - switch (visualType) - { - case ObjectFieldVisualType.IconAndText: - case ObjectFieldVisualType.MiniPreview: - buttonRect = new Rect(position.xMax - 15, position.y, 15, position.height); - break; - case ObjectFieldVisualType.LargePreview: - buttonRect = new Rect(position.xMax - 36, position.yMax - 14, 36, 14); - break; - default: - throw new ArgumentOutOfRangeException(); - } - - EditorGUIUtility.editingTextField = false; - - if (buttonRect.Contains(Event.current.mousePosition)) - { - if (GUI.enabled) - { - GUIUtility.keyboardControl = id; - ObjectSelector.get.Show(obj, objType, property, allowSceneObjects); - ObjectSelector.get.objectSelectorID = id; - - evt.Use(); - GUIUtility.ExitGUI(); - } - } - else - { - Object actualTargetObject = property != null ? property.objectReferenceValue : obj; - Component com = actualTargetObject as Component; - if (com) - actualTargetObject = com.gameObject; - if (showMixedValue) - actualTargetObject = null; - - // One click shows where the referenced object is, or pops up a preview - if (Event.current.clickCount == 1) - { - GUIUtility.keyboardControl = id; - - PingObjectOrShowPreviewOnClick(actualTargetObject, position); - evt.Use(); - } - // Double click opens the asset in external app or changes selection to referenced object - else if (Event.current.clickCount == 2) - { - if (actualTargetObject) - { - AssetDatabase.OpenAsset(actualTargetObject); - GUIUtility.ExitGUI(); - } - evt.Use(); - } - } - } - break; - case EventType.ExecuteCommand: - string commandName = evt.commandName; - if (commandName == ObjectSelector.ObjectSelectorUpdatedCommand && ObjectSelector.get.objectSelectorID == id && GUIUtility.keyboardControl == id && (property == null || !property.isScript)) - return AssignSelectedObject(property, validator, objType, evt); - else if (commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == id && GUIUtility.keyboardControl == id && property != null && property.isScript) - { - if (ObjectSelector.get.GetInstanceID() == 0) - { - // User canceled object selection; don't apply - evt.Use(); - break; - } - return AssignSelectedObject(property, validator, objType, evt); - } - break; - case EventType.KeyDown: - if (GUIUtility.keyboardControl == id) - { - if (evt.keyCode == KeyCode.Backspace || evt.keyCode == KeyCode.Delete) - { - if (property != null) - property.objectReferenceValue = null; - else - obj = null; - - GUI.changed = true; - evt.Use(); - } - - // Apparently we have to check for the character being space instead of the keyCode, - // otherwise the Inspector will maximize upon pressing space. - if (evt.MainActionKeyForControl(id)) - { - ObjectSelector.get.Show(obj, objType, property, allowSceneObjects); - ObjectSelector.get.objectSelectorID = id; - evt.Use(); - GUIUtility.ExitGUI(); - } - } - break; - case EventType.Repaint: - GUIContent temp; - if (showMixedValue) - { - temp = s_MixedValueContent; - } - else if (property != null) - { - temp = EditorGUIUtility.TempContent(property.objectReferenceStringValue, AssetPreview.GetMiniThumbnail(property.objectReferenceValue)); - obj = property.objectReferenceValue; - if (obj != null) - { - Object[] references = { obj }; - if (EditorSceneManager.preventCrossSceneReferences && CheckForCrossSceneReferencing(obj, property.serializedObject.targetObject)) - { - if (!EditorApplication.isPlaying) - temp = EditorGUIUtility.TempContent("Scene mismatch (cross scene references not supported)"); - else - temp.text = temp.text + string.Format(" ({0})", GetGameObjectFromObject(obj).scene.name); - } - else if (validator(references, objType, property, ObjectFieldValidatorOptions.ExactObjectTypeValidation) == null) - temp = EditorGUIUtility.TempContent("Type mismatch"); - } - } - else - { - temp = EditorGUIUtility.ObjectContent(obj, objType); - } - - switch (visualType) - { - case ObjectFieldVisualType.IconAndText: - BeginHandleMixedValueContentColor(); - style.Draw(position, temp, id, DragAndDrop.activeControlID == id); - EndHandleMixedValueContentColor(); - break; - case ObjectFieldVisualType.LargePreview: - DrawObjectFieldLargeThumb(position, id, obj, temp); - break; - case ObjectFieldVisualType.MiniPreview: - DrawObjectFieldMiniThumb(position, id, obj, temp); - break; - default: - throw new ArgumentOutOfRangeException(); - } - break; - } - - EditorGUIUtility.SetIconSize(oldIconSize); - - return obj; - } - - private static void DrawObjectFieldLargeThumb(Rect position, int id, Object obj, GUIContent content) - { - GUIStyle thumbStyle = EditorStyles.objectFieldThumb; - thumbStyle.Draw(position, GUIContent.none, id, DragAndDrop.activeControlID == id); - - if (obj != null && !showMixedValue) - { - bool isCubemap = obj is Cubemap; - bool isSprite = obj is Sprite; - Rect thumbRect = thumbStyle.padding.Remove(position); - - if (isCubemap || isSprite) - { - Texture2D t2d = AssetPreview.GetAssetPreview(obj); - if (t2d != null) - { - if (isSprite || t2d.alphaIsTransparency) - DrawTextureTransparent(thumbRect, t2d); - else - DrawPreviewTexture(thumbRect, t2d); - } - else - { - // Preview not loaded -> Draw icon - thumbRect.x += (thumbRect.width - content.image.width) / 2f; - thumbRect.y += (thumbRect.height - content.image.width) / 2f; - GUIStyle.none.Draw(thumbRect, content.image, false, false, false, false); - - // Keep repaint until the object field has a proper preview - HandleUtility.Repaint(); - } - } - else - { - // Draw texture - Texture2D t2d = content.image as Texture2D; - if (t2d != null && t2d.alphaIsTransparency) - DrawTextureTransparent(thumbRect, t2d); - else - DrawPreviewTexture(thumbRect, content.image); - } - } - else - { - GUIStyle s2 = thumbStyle.name + "Overlay"; - BeginHandleMixedValueContentColor(); - - s2.Draw(position, content, id); - EndHandleMixedValueContentColor(); - } - GUIStyle s3 = thumbStyle.name + "Overlay2"; - s3.Draw(position, EditorGUIUtility.TempContent("Select"), id); - } - - private static void DrawObjectFieldMiniThumb(Rect position, int id, Object obj, GUIContent content) - { - GUIStyle thumbStyle = EditorStyles.objectFieldMiniThumb; - position.width = EditorGUI.kObjectFieldMiniThumbnailWidth; - BeginHandleMixedValueContentColor(); - bool hover = obj != null; // we use hover texture for enhancing the border if we have a reference - bool on = DragAndDrop.activeControlID == id; - bool keyFocus = GUIUtility.keyboardControl == id; - thumbStyle.Draw(position, hover, false, on, keyFocus); - EndHandleMixedValueContentColor(); - - if (obj != null && !showMixedValue) - { - Rect thumbRect = new Rect(position.x + 1, position.y + 1, position.height - 2, position.height - 2); // subtract 1 px border - Texture2D t2d = content.image as Texture2D; - if (t2d != null && t2d.alphaIsTransparency) - DrawTextureTransparent(thumbRect, t2d); - else - DrawPreviewTexture(thumbRect, content.image); - - // Tooltip - if (thumbRect.Contains(Event.current.mousePosition)) - GUI.Label(thumbRect, GUIContent.Temp(string.Empty, "Ctrl + Click to show preview")); - } - } - - internal static Object DoDropField(Rect position, int id, System.Type objType, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style) - { - if (validator == null) - validator = ValidateObjectFieldAssignment; - Event evt = Event.current; - EventType eventType = evt.type; - - // special case test, so we continue to ping/select objects with the object field disabled - if (!GUI.enabled && GUIClip.enabled && (Event.current.rawType == EventType.MouseDown)) - eventType = Event.current.rawType; - - switch (eventType) - { - case EventType.DragExited: - if (GUI.enabled) - HandleUtility.Repaint(); - break; - case EventType.DragUpdated: - case EventType.DragPerform: - - if (position.Contains(Event.current.mousePosition) && GUI.enabled) - { - Object[] references = DragAndDrop.objectReferences; - Object validatedObject = validator(references, objType, null, ObjectFieldValidatorOptions.None); - - if (validatedObject != null) - { - // If scene objects are not allowed and object is a scene object then clear - if (!allowSceneObjects && !EditorUtility.IsPersistent(validatedObject)) - validatedObject = null; - } - - if (validatedObject != null) - { - DragAndDrop.visualMode = DragAndDropVisualMode.Generic; - if (eventType == EventType.DragPerform) - { - GUI.changed = true; - DragAndDrop.AcceptDrag(); - DragAndDrop.activeControlID = 0; - Event.current.Use(); - return validatedObject; - } - else - { - DragAndDrop.activeControlID = id; - Event.current.Use(); - } - } - } - break; - case EventType.Repaint: - style.Draw(position, GUIContent.none, id, DragAndDrop.activeControlID == id); - break; - } - return null; - } - } - - internal class ObjectPreviewPopup : PopupWindowContent - { - readonly Editor m_Editor; - readonly GUIContent m_ObjectName; - const float kToolbarHeight = 17f; - - internal class Styles - { - public readonly GUIStyle toolbar = "preToolbar"; - public readonly GUIStyle toolbarText = "preToolbar2"; - public GUIStyle background = "preBackground"; - } - Styles s_Styles; - - public ObjectPreviewPopup(Object previewObject) - { - if (previewObject == null) - { - Debug.LogError("ObjectPreviewPopup: Check object is not null, before trying to show it!"); - return; - } - m_ObjectName = new GUIContent(previewObject.name, AssetDatabase.GetAssetPath(previewObject)); // Show path as tooltip on label - m_Editor = Editor.CreateEditor(previewObject); - } - - public override void OnClose() - { - if (m_Editor != null) - Editor.DestroyImmediate(m_Editor); - } - - public override void OnGUI(Rect rect) - { - if (m_Editor == null) - { - editorWindow.Close(); - return; - } - - if (s_Styles == null) - s_Styles = new Styles(); - - - // Toolbar - GUILayout.BeginArea(new Rect(rect.x, rect.y, rect.width, kToolbarHeight), s_Styles.toolbar); - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - m_Editor.OnPreviewSettings(); - EditorGUILayout.EndHorizontal(); - GUILayout.EndArea(); - - const float kMaxSettingsWidth = 140f; - GUI.Label(new Rect(rect.x + 5f, rect.y, rect.width - kMaxSettingsWidth, kToolbarHeight), m_ObjectName, s_Styles.toolbarText); - - // Object preview - Rect previewRect = new Rect(rect.x, rect.y + kToolbarHeight, rect.width, rect.height - kToolbarHeight); - m_Editor.OnPreviewGUI(previewRect, s_Styles.background); - } - - public override Vector2 GetWindowSize() - { - return new Vector2(300f, 300f + kToolbarHeight); - } - } -} diff --git a/Editor/Mono/GUI/PackageExport.cs b/Editor/Mono/GUI/PackageExport.cs deleted file mode 100644 index 1c707949e1..0000000000 --- a/Editor/Mono/GUI/PackageExport.cs +++ /dev/null @@ -1,273 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - internal class PackageExport : EditorWindow - { - [SerializeField] private ExportPackageItem[] m_ExportPackageItems; - [SerializeField] private bool m_IncludeDependencies = true; - [SerializeField] private TreeViewState m_TreeViewState; - [NonSerialized] private PackageExportTreeView m_Tree; - [NonSerialized] private bool m_DidScheduleUpdate = false; - - public ExportPackageItem[] items { get { return m_ExportPackageItems; } } - - internal static class Styles - { - public static GUIStyle title = new GUIStyle(EditorStyles.largeLabel); - public static GUIStyle bottomBarBg = "ProjectBrowserBottomBarBg"; - public static GUIStyle topBarBg = new GUIStyle("ProjectBrowserHeaderBgTop"); - public static GUIStyle loadingTextStyle = new GUIStyle(EditorStyles.label); - public static GUIContent allText = EditorGUIUtility.TrTextContent("All"); - public static GUIContent noneText = EditorGUIUtility.TrTextContent("None"); - public static GUIContent includeDependenciesText = EditorGUIUtility.TrTextContent("Include dependencies"); - public static GUIContent header = EditorGUIUtility.TrTextContent("Items to Export"); - - static Styles() - { - topBarBg.fixedHeight = 0; - topBarBg.border.top = topBarBg.border.bottom = 2; - - title.fontStyle = FontStyle.Bold; - title.alignment = TextAnchor.MiddleLeft; - - loadingTextStyle.alignment = TextAnchor.MiddleCenter; - } - } - - public PackageExport() - { - // Initial pos and minsize - position = new Rect(100, 100, 400, 300); - minSize = new Vector2(350, 350); - } - - // Called from from menu - static internal void ShowExportPackage() - { - GetWindow(true, "Exporting package"); - } - - internal static IEnumerable GetAssetItemsForExport(ICollection guids, bool includeDependencies) - { - // if nothing is selected, export all - if (0 == guids.Count) - { - string[] temp = new string[0]; // <--- I dont get this API - guids = new HashSet(AssetDatabase.CollectAllChildren(AssetDatabase.assetFolderGUID, temp)); - } - - ExportPackageItem[] assets = PackageUtility.BuildExportPackageItemsList(guids.ToArray(), includeDependencies); - - // If any scripts are included, add all scripts with dependencies - if (includeDependencies && assets.Any(asset => UnityEditorInternal.InternalEditorUtility.IsScriptOrAssembly(asset.assetPath))) - { - assets = PackageUtility.BuildExportPackageItemsList( - guids.Union(UnityEditorInternal.InternalEditorUtility.GetAllScriptGUIDs()).ToArray(), includeDependencies); - } - - // If the user exports the root Assets folder, we need to remove it from the list - // explicitly, as it doesnt make sense - assets = assets.Where(val => val.assetPath != "Assets").ToArray(); - - return assets; - } - - void RefreshAssetList() - { - m_ExportPackageItems = null; - } - - bool HasValidAssetList() - { - return m_ExportPackageItems != null; - } - - bool CheckAssetExportList() - { - if (m_ExportPackageItems.Length == 0) - { - GUILayout.Space(20f); - GUILayout.BeginVertical(EditorStyles.helpBox); - GUILayout.Label("Nothing to export!", EditorStyles.boldLabel); - GUILayout.Label("No assets to export were found in your project.", "WordWrappedLabel"); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("OK")) - { - Close(); - GUIUtility.ExitGUI(); - } - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - return true; - } - - return false; - } - - public void OnDestroy() - { - UnscheduleBuildAssetList(); - } - - public void OnGUI() - { - if (!HasValidAssetList()) - { - ScheduleBuildAssetList(); - } - else if (CheckAssetExportList()) - { - return; - } - - using (new EditorGUI.DisabledScope(!HasValidAssetList())) - { - TopArea(); - } - - TreeViewArea(!HasValidAssetList()); - - using (new EditorGUI.DisabledScope(!HasValidAssetList())) - { - BottomArea(); - } - } - - void TopArea() - { - float totalTopHeight = 53f; - Rect r = GUILayoutUtility.GetRect(position.width, totalTopHeight); - - // Background - GUI.Label(r, GUIContent.none, Styles.topBarBg); - - // Header - Rect titleRect = new Rect(r.x + 5f, r.yMin, r.width, r.height); - GUI.Label(titleRect, Styles.header, Styles.title); - } - - void BottomArea() - { - // Background - GUILayout.BeginVertical(Styles.bottomBarBg); - - GUILayout.Space(8); - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - if (GUILayout.Button(Styles.allText, GUILayout.Width(50))) - { - m_Tree.SetAllEnabled(PackageExportTreeView.EnabledState.All); - } - - if (GUILayout.Button(Styles.noneText, GUILayout.Width(50))) - { - m_Tree.SetAllEnabled(PackageExportTreeView.EnabledState.None); - } - - GUILayout.Space(10); - - EditorGUI.BeginChangeCheck(); - m_IncludeDependencies = GUILayout.Toggle(m_IncludeDependencies, Styles.includeDependenciesText); - if (EditorGUI.EndChangeCheck()) - { - RefreshAssetList(); - } - - GUILayout.FlexibleSpace(); - - if (GUILayout.Button(EditorGUIUtility.TrTextContent("Export..."))) - { - Export(); - GUIUtility.ExitGUI(); - } - GUILayout.Space(10); - GUILayout.EndHorizontal(); - GUILayout.Space(5); - GUILayout.EndVertical(); - } - - private void TreeViewArea(bool showLoadingScreen) - { - Rect treeAreaRect = GUILayoutUtility.GetRect(1, 9999, 1, 99999); - - if (showLoadingScreen) - { - GUI.Label(treeAreaRect, "Loading...", Styles.loadingTextStyle); - return; - } - - if (m_ExportPackageItems != null && m_ExportPackageItems.Length > 0) - { - if (m_TreeViewState == null) - m_TreeViewState = new TreeViewState(); - - if (m_Tree == null) - m_Tree = new PackageExportTreeView(this, m_TreeViewState, new Rect()); - - m_Tree.OnGUI(treeAreaRect); - } - } - - private void Export() - { - string fileName = EditorUtility.SaveFilePanel("Export package ...", "", "", "unitypackage"); - if (fileName != "") - { - // build guid list - List guids = new List(); - - foreach (ExportPackageItem ai in m_ExportPackageItems) - { - if (ai.enabledStatus > 0) - guids.Add(ai.guid); - } - - PackageUtility.ExportPackage(guids.ToArray(), fileName); - - Close(); - GUIUtility.ExitGUI(); - } - } - - private void ScheduleBuildAssetList() - { - if (!m_DidScheduleUpdate) - { - EditorApplication.update += BuildAssetList; - m_DidScheduleUpdate = true; - } - } - - private void UnscheduleBuildAssetList() - { - if (m_DidScheduleUpdate) - { - m_DidScheduleUpdate = false; - EditorApplication.update -= BuildAssetList; - } - } - - private void BuildAssetList() - { - UnscheduleBuildAssetList(); - - m_ExportPackageItems = GetAssetItemsForExport(Selection.assetGUIDsDeepSelection, m_IncludeDependencies).ToArray(); - - // GUI is reconstructed in OnGUI (when needed) - m_Tree = null; - m_TreeViewState = null; - - Repaint(); - } - } -} diff --git a/Editor/Mono/GUI/PackageExportTreeView.cs b/Editor/Mono/GUI/PackageExportTreeView.cs deleted file mode 100644 index dc16e2e28c..0000000000 --- a/Editor/Mono/GUI/PackageExportTreeView.cs +++ /dev/null @@ -1,483 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.IMGUI.Controls; -using UnityEditor.Utils; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class PackageExportTreeView - { - TreeViewController m_TreeView; - List m_Selection = new List(); - static readonly bool s_UseFoldouts = true; - public enum EnabledState - { - NotSet = -1, - None = 0, - All = 1, - Mixed = 2 - }; - - private PackageExport m_PackageExport; - - public ExportPackageItem[] items { get { return m_PackageExport.items; } } - - public PackageExportTreeView(PackageExport packageExport, TreeViewState treeViewState, Rect startRect) - { - m_PackageExport = packageExport; - - m_TreeView = new TreeViewController(m_PackageExport, treeViewState); - var dataSource = new PackageExportTreeViewDataSource(m_TreeView, this); - var gui = new PackageExportTreeViewGUI(m_TreeView, this); - - m_TreeView.Init(startRect, dataSource, gui, null); - m_TreeView.ReloadData(); - m_TreeView.selectionChangedCallback += SelectionChanged; - gui.itemWasToggled += ItemWasToggled; - - ComputeEnabledStateForFolders(); - } - - void ComputeEnabledStateForFolders() - { - var root = m_TreeView.data.root as PackageExportTreeViewItem; - var done = new HashSet(); - done.Add(root); // Dont compute for root: mark it as done - RecursiveComputeEnabledStateForFolders(root, done); - } - - void RecursiveComputeEnabledStateForFolders(PackageExportTreeViewItem pitem, HashSet done) - { - if (!pitem.isFolder) - return; - - // Depth first recursion to allow parent folders be dependant on child folders - - // Recurse - if (pitem.hasChildren) - { - foreach (var child in pitem.children) - { - RecursiveComputeEnabledStateForFolders(child as PackageExportTreeViewItem, done); - } - } - - // Now do logic - if (!done.Contains(pitem)) - { - EnabledState enabledState = GetFolderChildrenEnabledState(pitem); - pitem.enabledState = enabledState; - - // If 'item' is mixed then all of its parents will also be mixed - if (enabledState == EnabledState.Mixed) - { - done.Add(pitem); - var current = pitem.parent as PackageExportTreeViewItem; - while (current != null) - { - if (!done.Contains(current)) - { - current.enabledState = EnabledState.Mixed; - done.Add(current); - } - current = current.parent as PackageExportTreeViewItem; - } - } - } - } - - EnabledState GetFolderChildrenEnabledState(PackageExportTreeViewItem folder) - { - if (!folder.isFolder) - Debug.LogError("Should be a folder item!"); - - if (!folder.hasChildren) - return EnabledState.None; - - EnabledState amount = EnabledState.NotSet; - - var firstChild = folder.children[0] as PackageExportTreeViewItem; - EnabledState initial = firstChild.enabledState; - for (int i = 1; i < folder.children.Count; ++i) - { - var child = folder.children[i] as PackageExportTreeViewItem; - if (initial != child.enabledState) - { - amount = EnabledState.Mixed; - break; - } - } - - if (amount == EnabledState.NotSet) - { - amount = initial == EnabledState.All ? EnabledState.All : EnabledState.None; - } - - return amount; - } - - void SelectionChanged(int[] selectedIDs) - { - // Cache selected tree view items (from ids) - m_Selection = new List(); - var visibleItems = m_TreeView.data.GetRows(); - foreach (var visibleItem in visibleItems) - { - if (selectedIDs.Contains(visibleItem.id)) - { - var pitem = visibleItem as PackageExportTreeViewItem; - if (pitem != null) - m_Selection.Add(pitem); - } - } - } - - public void OnGUI(Rect rect) - { - int keyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard); - m_TreeView.OnGUI(rect, keyboardControlID); - - // Keyboard space toggles selection enabledness - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Space && - m_Selection != null && m_Selection.Count > 0 && GUIUtility.keyboardControl == keyboardControlID) - { - EnabledState newEnabled = m_Selection[0].enabledState != EnabledState.All ? EnabledState.All : EnabledState.None; - m_Selection[0].enabledState = newEnabled; - ItemWasToggled(m_Selection[0]); - - Event.current.Use(); - } - } - - public void SetAllEnabled(EnabledState enabled) - { - EnableChildrenRecursive(m_TreeView.data.root, enabled); - ComputeEnabledStateForFolders(); - } - - void ItemWasToggled(PackageExportTreeViewItem pitem) - { - if (m_Selection.Count <= 1) - { - EnableChildrenRecursive(pitem, pitem.enabledState); - } - else - { - foreach (var i in m_Selection) - i.enabledState = pitem.enabledState; - } - - ComputeEnabledStateForFolders(); - } - - void EnableChildrenRecursive(TreeViewItem parentItem, EnabledState enabled) - { - if (!parentItem.hasChildren) - return; - - foreach (TreeViewItem tvitem in parentItem.children) - { - var pitem = tvitem as PackageExportTreeViewItem; - pitem.enabledState = enabled; - EnableChildrenRecursive(pitem, enabled); - } - } - - // Item - private class PackageExportTreeViewItem : TreeViewItem - { - public ExportPackageItem item { get; set; } - - private EnabledState m_EnabledState = EnabledState.NotSet; - public EnabledState enabledState - { - get { return item != null ? (EnabledState)item.enabledStatus : m_EnabledState; } - set { if (item != null) item.enabledStatus = (int)value; else m_EnabledState = value; } - } - - // We assume that items that don't have ExportPackageItem assigned, are folders. - public bool isFolder - { - get { return item != null ? item.isFolder : true; } - } - - public PackageExportTreeViewItem(ExportPackageItem itemIn, int id, int depth, TreeViewItem parent, string displayName) - : base(id, depth, parent, displayName) - { - item = itemIn; - } - } - - // Gui - - private class PackageExportTreeViewGUI : TreeViewGUI - { - internal static class Constants - { - public static Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResourcesUtility.folderIconName); - } - - public Action itemWasToggled; - public int showPreviewForID { get; set; } - - private PackageExportTreeView m_PackageExportView; - protected float k_FoldoutWidth = 12f; - - public PackageExportTreeViewGUI(TreeViewController treeView, PackageExportTreeView view) - : base(treeView) - { - m_PackageExportView = view; - - k_BaseIndent = 4f; - if (!s_UseFoldouts) - k_FoldoutWidth = 0f; - } - - override public void OnRowGUI(Rect rowRect, TreeViewItem tvItem, int row, bool selected, bool focused) - { - k_IndentWidth = 18; - k_FoldoutWidth = 18; - const float k_ToggleWidth = 18f; - - var pitem = tvItem as PackageExportTreeViewItem; - - bool repainting = Event.current.type == EventType.Repaint; - - // 0. Selection row rect - if (selected && repainting) - Styles.selectionStyle.Draw(rowRect, false, false, true, focused); - - // 1. Foldout - if (m_TreeView.data.IsExpandable(tvItem)) - DoFoldout(rowRect, tvItem, row); - - // 2. Toggle only for items that are actually in the package. - Rect toggleRect = new Rect(k_BaseIndent + tvItem.depth * indentWidth + k_FoldoutWidth, rowRect.y, k_ToggleWidth, rowRect.height); - - DoToggle(pitem, toggleRect); - - // 3. Icon & Text - // Display folders that will not be included into the package as disabled. - using (new EditorGUI.DisabledScope(pitem.item == null)) - { - Rect contentRect = new Rect(toggleRect.xMax, rowRect.y, rowRect.width, rowRect.height); - DoIconAndText(pitem, contentRect, selected, focused); - } - } - - static void Toggle(ExportPackageItem[] items, PackageExportTreeViewItem pitem, Rect toggleRect) - { - bool enabled = pitem.enabledState > EnabledState.None; - - GUIStyle style = EditorStyles.toggle; - bool setMixed = pitem.isFolder && (pitem.enabledState == EnabledState.Mixed); - if (setMixed) - style = EditorStyles.toggleMixed; - - bool newEnabled = GUI.Toggle(toggleRect, enabled, GUIContent.none, style); - if (newEnabled != enabled) - pitem.enabledState = newEnabled ? EnabledState.All : EnabledState.None; - } - - void DoToggle(PackageExportTreeViewItem pitem, Rect toggleRect) - { - // Toggle on/off - EditorGUI.BeginChangeCheck(); - Toggle(m_PackageExportView.items, pitem, toggleRect); - if (EditorGUI.EndChangeCheck()) - { - // Only change selection if we already have single selection (Keep multi-selection when toggling) - if (m_TreeView.GetSelection().Length <= 1 || !m_TreeView.GetSelection().Contains(pitem.id)) - { - m_TreeView.SetSelection(new int[] { pitem.id }, false); - m_TreeView.NotifyListenersThatSelectionChanged(); - } - if (itemWasToggled != null) - itemWasToggled(pitem); - Event.current.Use(); - } - } - - void DoIconAndText(PackageExportTreeViewItem item, Rect contentRect, bool selected, bool focused) - { - EditorGUIUtility.SetIconSize(new Vector2(k_IconWidth, k_IconWidth)); // If not set we see icons scaling down if text is being cropped - GUIStyle lineStyle = Styles.lineStyle; - lineStyle.padding.left = 0; // padding could have been set by other tree views - contentRect.height += 5; // with the default row height, underscore and lower parts of characters like g, p, etc. were not visible - if (Event.current.type == EventType.Repaint) - lineStyle.Draw(contentRect, GUIContent.Temp(item.displayName, GetIconForItem(item)), false, false, selected, focused); - EditorGUIUtility.SetIconSize(Vector2.zero); - } - - protected override Texture GetIconForItem(TreeViewItem tItem) - { - var pItem = tItem as PackageExportTreeViewItem; - var item = pItem.item; - - // Undefined items are always folders. - if (item == null || item.isFolder) - { - return Constants.folderIcon; - } - - // We are using this TreeViewGUI when importing and exporting a package, so handle both situations: - - // Exporting a package can use cached icons (icons we generate on import) - Texture cachedIcon = AssetDatabase.GetCachedIcon(item.assetPath); - if (cachedIcon != null) - return cachedIcon; - - // Importing a package have to use icons based on file extension - return InternalEditorUtility.GetIconForFile(item.assetPath); - } - - protected override void RenameEnded() - { - } - } - - // Datasource - - private class PackageExportTreeViewDataSource : TreeViewDataSource - { - private PackageExportTreeView m_PackageExportView; - - public PackageExportTreeViewDataSource(TreeViewController treeView, PackageExportTreeView view) - : base(treeView) - { - m_PackageExportView = view; - rootIsCollapsable = false; - showRootItem = false; - } - - public override bool IsRenamingItemAllowed(TreeViewItem item) - { - return false; - } - - public override bool IsExpandable(TreeViewItem item) - { - if (!s_UseFoldouts) - return false; - - return base.IsExpandable(item); - } - - public override void FetchData() - { - int rootDepth = -1; // -1 so its children will have 0 depth - m_RootItem = new PackageExportTreeViewItem(null, "Assets".GetHashCode(), rootDepth, null, "InvisibleAssetsFolder"); - - bool initExpandedState = true; - if (initExpandedState) - m_TreeView.state.expandedIDs.Add(m_RootItem.id); - - ExportPackageItem[] items = m_PackageExportView.items; - - Dictionary treeViewFolders = new Dictionary(); - for (int i = 0; i < items.Length; i++) - { - var item = items[i]; - - if (PackageImport.HasInvalidCharInFilePath(item.assetPath)) - continue; // Do not add invalid paths (we already warn the user with a dialog in PackageImport.cs) - - string filename = Path.GetFileName(item.assetPath).ConvertSeparatorsToUnity(); - string folderPath = Path.GetDirectoryName(item.assetPath).ConvertSeparatorsToUnity(); - - // Ensure folders. This is for when installed packages have been moved to other folders. - TreeViewItem targetFolder = EnsureFolderPath(folderPath, treeViewFolders, initExpandedState); - - // Add file to folder - if (targetFolder != null) - { - int id = item.assetPath.GetHashCode(); - var newItem = new PackageExportTreeViewItem(item, id, targetFolder.depth + 1, targetFolder, filename); - targetFolder.AddChild(newItem); - - if (initExpandedState) - m_TreeView.state.expandedIDs.Add(id); - - // We need to ensure that the folder is available for - // EnsureFolderPath on subsequent iterations. - if (item.isFolder) - treeViewFolders[item.assetPath] = newItem; - } - } - - if (initExpandedState) - m_TreeView.state.expandedIDs.Sort(); - } - - TreeViewItem EnsureFolderPath(string folderPath, Dictionary treeViewFolders, bool initExpandedState) - { - // We're in the root folder, so just return the root item as the parent. - if (folderPath == "") - return m_RootItem; - - // Does folder path exist? - int id = folderPath.GetHashCode(); - TreeViewItem item = TreeViewUtility.FindItem(id, m_RootItem); - - if (item != null) - return item; - - // Add folders as needed - string[] splitPath = folderPath.Split('/'); - string currentPath = ""; - TreeViewItem currentItem = m_RootItem; - int folderDepth = -1; // Will be incremented to the right depth in the loop. - - for (int depth = 0; depth < splitPath.Length; ++depth) - { - string folder = splitPath[depth]; - if (currentPath != "") - currentPath += '/'; - - currentPath += folder; - - // Dont create a 'Assets' folder (we already have that as a hidden root) - if (depth == 0 && currentPath == "Assets") - continue; - - // Only increment the folder depth if we are past the root "Assets" folder. - ++folderDepth; - - id = currentPath.GetHashCode(); - - PackageExportTreeViewItem foundItem; - if (treeViewFolders.TryGetValue(currentPath, out foundItem)) - { - currentItem = foundItem; - } - else - { - // If we do not have a tree view item for this folder we create one - var folderItem = new PackageExportTreeViewItem(null, id, folderDepth, currentItem, folder); - - // Add to children array of the parent - currentItem.AddChild(folderItem); - currentItem = folderItem; - - // Auto expand all folder items - if (initExpandedState) - m_TreeView.state.expandedIDs.Add(id); - - // For faster finding of folders - treeViewFolders[currentPath] = folderItem; - } - } - - return currentItem; - } - } - } -} diff --git a/Editor/Mono/GUI/PackageImport.cs b/Editor/Mono/GUI/PackageImport.cs deleted file mode 100644 index 2527dc89d1..0000000000 --- a/Editor/Mono/GUI/PackageImport.cs +++ /dev/null @@ -1,392 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.Scripting; -using UnityEditor; -using UnityEditorInternal; -using System; -using UnityEditor.IMGUI.Controls; - -namespace UnityEditor -{ - [UsedByNativeCode] - internal class PackageImport : EditorWindow - { - [SerializeField] private ImportPackageItem[] m_ImportPackageItems; - [SerializeField] private string m_PackageName; - [SerializeField] private string m_PackageIconPath; - [SerializeField] TreeViewState m_TreeViewState; - [NonSerialized] PackageImportTreeView m_Tree; - - private bool m_ShowReInstall; - private bool m_ReInstallPackage; - - public bool canReInstall { get { return m_ShowReInstall; } } - public bool doReInstall { get { return m_ShowReInstall && m_ReInstallPackage; } } - public ImportPackageItem[] packageItems { get { return m_ImportPackageItems; } } - - private static Texture2D s_PackageIcon; - private static Texture2D s_Preview; - private static string s_LastPreviewPath; - - readonly static char[] s_InvalidPathChars = System.IO.Path.GetInvalidPathChars(); - - internal class Constants - { - public GUIStyle ConsoleEntryBackEven = "CN EntryBackEven"; - public GUIStyle ConsoleEntryBackOdd = "CN EntryBackOdd"; - public GUIStyle title = new GUIStyle(EditorStyles.largeLabel); - public GUIStyle bottomBarBg = "ProjectBrowserBottomBarBg"; - public GUIStyle topBarBg = new GUIStyle("ProjectBrowserHeaderBgTop"); - public GUIStyle textureIconDropShadow = "ProjectBrowserTextureIconDropShadow"; - public Color lineColor; - - public Constants() - { - lineColor = EditorGUIUtility.isProSkin ? new Color(0.1f, 0.1f, 0.1f) : new Color(0.4f, 0.4f, 0.4f); - topBarBg.fixedHeight = 0; - topBarBg.border.top = topBarBg.border.bottom = 2; - - title.fontStyle = FontStyle.Bold; - title.alignment = TextAnchor.MiddleLeft; - } - } - static Constants ms_Constants; - - - // Invoked from menu - [UsedByNativeCode] - public static void ShowImportPackage(string packagePath, ImportPackageItem[] items, string packageIconPath, bool allowReInstall) - { - if (!ValidateInput(items)) - return; - - var window = GetWindow(true, "Import Unity Package"); - window.Init(packagePath, items, packageIconPath, allowReInstall); - } - - public PackageImport() - { - minSize = new Vector2(350, 350); - } - - void OnDisable() - { - DestroyCreatedIcons(); - } - - void DestroyCreatedIcons() - { - if (s_Preview != null) - { - DestroyImmediate(s_Preview); - s_Preview = null; - s_LastPreviewPath = null; - } - - if (s_PackageIcon != null) - { - DestroyImmediate(s_PackageIcon); - s_PackageIcon = null; - } - } - - void Init(string packagePath, ImportPackageItem[] items, string packageIconPath, bool allowReInstall) - { - DestroyCreatedIcons(); - - m_ShowReInstall = allowReInstall; - m_ReInstallPackage = true; - m_TreeViewState = null; - m_Tree = null; - m_ImportPackageItems = items; - - m_PackageName = System.IO.Path.GetFileNameWithoutExtension(packagePath); - m_PackageIconPath = packageIconPath; - - Repaint(); - } - - private bool ShowTreeGUI(bool reInstalling, ImportPackageItem[] items) - { - if (reInstalling) - return true; - - if (items.Length == 0) - return false; - - for (int i = 0; i < items.Length; i++) - { - if (!items[i].isFolder && items[i].assetChanged) - return true; - } - - return false; - } - - public void OnGUI() - { - if (ms_Constants == null) - ms_Constants = new Constants(); - - if (m_TreeViewState == null) - m_TreeViewState = new TreeViewState(); - - if (m_Tree == null) - m_Tree = new PackageImportTreeView(this, m_TreeViewState, new Rect()); - - if (m_ImportPackageItems != null && ShowTreeGUI(doReInstall, m_ImportPackageItems)) - { - TopArea(); - m_Tree.OnGUI(GUILayoutUtility.GetRect(1, 9999, 1, 99999)); - BottomArea(); - } - else - { - GUILayout.Label("Nothing to import!", EditorStyles.boldLabel); - GUILayout.Label("All assets from this package are already in your project.", "WordWrappedLabel"); - GUILayout.FlexibleSpace(); - - // Background - GUILayout.BeginVertical(ms_Constants.bottomBarBg); - GUILayout.Space(8); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - ReInstallToggle(); - if (GUILayout.Button("OK")) - { - Close(); - GUIUtility.ExitGUI(); - } - GUILayout.Space(10); - GUILayout.EndHorizontal(); - GUILayout.Space(5); - GUILayout.EndVertical(); - } - } - - void ReInstallToggle() - { - if (m_ShowReInstall) - { - EditorGUI.BeginChangeCheck(); - bool reInstall = GUILayout.Toggle(m_ReInstallPackage, "Re-Install Package"); - if (EditorGUI.EndChangeCheck()) - m_ReInstallPackage = reInstall; - } - } - - void TopArea() - { - const float margin = 10f; - const float imageSize = 64; - - if (s_PackageIcon == null && !string.IsNullOrEmpty(m_PackageIconPath)) - LoadTexture(m_PackageIconPath, ref s_PackageIcon); - bool hasPackageIcon = s_PackageIcon != null; - - float totalTopHeight = hasPackageIcon ? (margin + imageSize + margin) : 52f; - Rect r = GUILayoutUtility.GetRect(position.width, totalTopHeight); - - // Background - GUI.Label(r, GUIContent.none, ms_Constants.topBarBg); - - Rect titleRect; - if (hasPackageIcon) - { - Rect iconRect = new Rect(r.x + margin, r.y + margin, imageSize, imageSize); - DrawTexture(iconRect, s_PackageIcon, true); - titleRect = new Rect(iconRect.xMax + 10f, iconRect.yMin, r.width, iconRect.height); - } - else - { - titleRect = new Rect(r.x + 5f, r.yMin, r.width, r.height); - } - - // Title - GUI.Label(titleRect, m_PackageName, ms_Constants.title); - } - - void BottomArea() - { - // Background - GUILayout.BeginVertical(ms_Constants.bottomBarBg); - - GUILayout.Space(8); - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - if (GUILayout.Button(EditorGUIUtility.TrTextContent("All"), GUILayout.Width(50))) - { - m_Tree.SetAllEnabled(PackageImportTreeView.EnabledState.All); - } - - if (GUILayout.Button(EditorGUIUtility.TrTextContent("None"), GUILayout.Width(50))) - { - m_Tree.SetAllEnabled(PackageImportTreeView.EnabledState.None); - } - - ReInstallToggle(); - - GUILayout.FlexibleSpace(); - if (GUILayout.Button(EditorGUIUtility.TrTextContent("Cancel"))) - { - PopupWindowWithoutFocus.Hide(); - Close(); - GUIUtility.ExitGUI(); - } - if (GUILayout.Button(EditorGUIUtility.TrTextContent("Import"))) - { - bool doImport = true; - if (doReInstall) - doImport = EditorUtility.DisplayDialog("Re-Install?", "Highlighted folders will be completely deleted first! Recommend backing up your project first. Are you sure?", "Do It", "Cancel"); - - if (doImport) - { - if (m_ImportPackageItems != null) - PackageUtility.ImportPackageAssets(m_PackageName, m_ImportPackageItems, doReInstall); - - PopupWindowWithoutFocus.Hide(); - Close(); - GUIUtility.ExitGUI(); - } - } - - GUILayout.Space(10); - GUILayout.EndHorizontal(); - GUILayout.Space(5); - GUILayout.EndVertical(); - } - - // Reuses old texture if it's created - static void LoadTexture(string filepath, ref Texture2D texture) - { - if (!texture) - texture = new Texture2D(128, 128); - - byte[] fileContents = null; - try - { - fileContents = System.IO.File.ReadAllBytes(filepath); - } - catch - { - // ignore - } - - if (filepath == "" || fileContents == null || !texture.LoadImage(fileContents)) - { - Color[] pixels = texture.GetPixels(); - for (int i = 0; i < pixels.Length; ++i) - pixels[i] = new Color(0.5f, 0.5f, 0.5f, 0f); - texture.SetPixels(pixels); - texture.Apply(); - } - } - - public static void DrawTexture(Rect r, Texture2D tex, bool useDropshadow) - { - if (tex == null) - return; - - // Clamp size (preserve aspect ratio) - float texwidth = tex.width; - float texheight = tex.height; - if (texwidth >= texheight && texwidth > r.width) - { - texheight = texheight * r.width / texwidth; - texwidth = r.width; - } - else if (texheight > texwidth && texheight > r.height) - { - texwidth = texwidth * r.height / texheight; - texheight = r.height; - } - - // Center - float x = r.x + Mathf.Round((r.width - texwidth) / 2.0f); - float y = r.y + Mathf.Round((r.height - texheight) / 2.0f); - - r = new Rect(x, y, texwidth, texheight); - - // Dropshadow - if (useDropshadow && Event.current.type == EventType.Repaint) - { - Rect borderPosition = new RectOffset(1, 1, 1, 1).Remove(ms_Constants.textureIconDropShadow.border.Add(r)); - ms_Constants.textureIconDropShadow.Draw(borderPosition, GUIContent.none, false, false, false, false); - } - - GUI.DrawTexture(r, tex, ScaleMode.ScaleToFit, true); - } - - public static Texture2D GetPreview(string previewPath) - { - if (previewPath != s_LastPreviewPath) - { - s_LastPreviewPath = previewPath; - LoadTexture(previewPath, ref s_Preview); - } - - return s_Preview; - } - - static bool ValidateInput(ImportPackageItem[] items) - { - string errorMessage; - if (!IsAllFilePathsValid(items, out errorMessage)) - { - errorMessage += "\nDo you want to import the valid file paths of the package or cancel importing?"; - return EditorUtility.DisplayDialog("Invalid file path found", errorMessage, "Import", "Cancel importing"); - } - return true; - } - - static bool IsAllFilePathsValid(ImportPackageItem[] assetItems, out string errorMessage) - { - foreach (var item in assetItems) - { - if (item.isFolder) - continue; - - char invalidChar; - int invalidCharIndex; - if (HasInvalidCharInFilePath(item.destinationAssetPath, out invalidChar, out invalidCharIndex)) - { - errorMessage = string.Format("Invalid character found in file path: '{0}'. Invalid ascii value: {1} (at character index {2}).", item.destinationAssetPath, (int)invalidChar, invalidCharIndex); - return false; - } - } - - errorMessage = ""; - return true; - } - - static bool HasInvalidCharInFilePath(string filePath, out char invalidChar, out int invalidCharIndex) - { - for (int i = 0; i < filePath.Length; ++i) - { - char c = filePath[i]; - if (s_InvalidPathChars.Contains(c)) - { - invalidChar = c; - invalidCharIndex = i; - return true; - } - } - - invalidChar = ' '; - invalidCharIndex = -1; - return false; - } - - public static bool HasInvalidCharInFilePath(string filePath) - { - char invalidChar; - int invalidCharIndex; - return HasInvalidCharInFilePath(filePath, out invalidChar, out invalidCharIndex); - } - } -} diff --git a/Editor/Mono/GUI/PackageImportTreeView.cs b/Editor/Mono/GUI/PackageImportTreeView.cs deleted file mode 100644 index 983bdae75a..0000000000 --- a/Editor/Mono/GUI/PackageImportTreeView.cs +++ /dev/null @@ -1,662 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.IMGUI.Controls; -using UnityEditor.Utils; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class PackageImportTreeView - { - TreeViewController m_TreeView; - List m_Selection = new List(); - static readonly bool s_UseFoldouts = true; - public enum EnabledState - { - NotSet = -1, - None = 0, - All = 1, - Mixed = 2 - }; - - private PackageImport m_PackageImport; - - public bool canReInstall { get { return m_PackageImport.canReInstall; } } - public bool doReInstall { get { return m_PackageImport.doReInstall; } } - public ImportPackageItem[] packageItems { get { return m_PackageImport.packageItems; } } - - - public PackageImportTreeView(PackageImport packageImport, TreeViewState treeViewState, Rect startRect) - { - m_PackageImport = packageImport; - - m_TreeView = new TreeViewController(m_PackageImport, treeViewState); - var dataSource = new PackageImportTreeViewDataSource(m_TreeView, this); - var gui = new PackageImportTreeViewGUI(m_TreeView, this); - - m_TreeView.Init(startRect, dataSource, gui, null); - m_TreeView.ReloadData(); - m_TreeView.selectionChangedCallback += SelectionChanged; - gui.itemWasToggled += ItemWasToggled; - - ComputeEnabledStateForFolders(); - } - - void ComputeEnabledStateForFolders() - { - var root = m_TreeView.data.root as PackageImportTreeViewItem; - var done = new HashSet(); - done.Add(root); // Dont compute for root: mark it as done - RecursiveComputeEnabledStateForFolders(root, done); - } - - void RecursiveComputeEnabledStateForFolders(PackageImportTreeViewItem pitem, HashSet done) - { - if (pitem.item != null && !pitem.item.isFolder) - return; - - // Depth first recursion to allow parent folders be dependant on child folders - - // Recurse - if (pitem.hasChildren) - { - foreach (var child in pitem.children) - { - RecursiveComputeEnabledStateForFolders(child as PackageImportTreeViewItem, done); - } - } - - // Now do logic - if (!done.Contains(pitem)) - { - EnabledState amount = GetFolderChildrenEnabledState(pitem); - pitem.enableState = amount; - - // If 'item' is mixed then all of its parents will also be mixed - if (amount == EnabledState.Mixed) - { - done.Add(pitem); - var current = pitem.parent as PackageImportTreeViewItem; - while (current != null) - { - if (!done.Contains(current)) - { - current.enableState = EnabledState.Mixed; - done.Add(current); - } - current = current.parent as PackageImportTreeViewItem; - } - } - } - } - - bool ItemShouldBeConsideredForEnabledCheck(PackageImportTreeViewItem pitem) - { - // Not even an item - if (pitem == null) - return false; - - // item was a folder that had to be created - // in this treeview. - if (pitem.item == null) - return true; - - var item = pitem.item; - // Its a package asset, its changed or we are doing a re-install - if (item.projectAsset || !(item.isFolder || item.assetChanged || doReInstall)) - return false; - - return true; - } - - EnabledState GetFolderChildrenEnabledState(PackageImportTreeViewItem folder) - { - if (folder.item != null && !folder.item.isFolder) - Debug.LogError("Should be a folder item!"); - - if (!folder.hasChildren) - return EnabledState.None; - - EnabledState amount = EnabledState.NotSet; - - int i = 0; - for (; i < folder.children.Count; ++i) - { - // We dont want to consider project assets in this calculation as they are - // ignored - var firstValidChild = folder.children[i] as PackageImportTreeViewItem; - if (ItemShouldBeConsideredForEnabledCheck(firstValidChild)) - { - amount = firstValidChild.enableState; - break; - } - } - - ++i; - for (; i < folder.children.Count; ++i) - { - // We dont want to consider project assets in this calculation as they are - // ignored - var childItem = folder.children[i] as PackageImportTreeViewItem; - if (ItemShouldBeConsideredForEnabledCheck(childItem)) - { - if (amount != childItem.enableState) - { - amount = EnabledState.Mixed; - break; - } - } - } - - if (amount == EnabledState.NotSet) - return EnabledState.None; - - return amount; - } - - void SelectionChanged(int[] selectedIDs) - { - // Cache selected tree view items (from ids) - m_Selection = new List(); - var visibleItems = m_TreeView.data.GetRows(); - foreach (var visibleItem in visibleItems) - { - if (selectedIDs.Contains(visibleItem.id)) - { - var pitem = visibleItem as PackageImportTreeViewItem; - if (pitem != null) - m_Selection.Add(pitem); - } - } - - // Show preview on selection - var selectedItem = m_Selection[0].item; - if (m_Selection.Count == 1 && selectedItem != null && !string.IsNullOrEmpty(selectedItem.previewPath)) - { - var gui = m_TreeView.gui as PackageImportTreeViewGUI; - gui.showPreviewForID = m_Selection[0].id; - } - else - { - PopupWindowWithoutFocus.Hide(); - } - } - - public void OnGUI(Rect rect) - { - // Remove preview popup on mouse scroll wheel events - if (Event.current.type == EventType.ScrollWheel) - PopupWindowWithoutFocus.Hide(); - - int keyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard); - m_TreeView.OnGUI(rect, keyboardControlID); - - // Keyboard space toggles selection enabledness - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Space && - m_Selection != null && m_Selection.Count > 0 && GUIUtility.keyboardControl == keyboardControlID) - { - var pitem = m_Selection[0]; - if (pitem != null) - { - EnabledState newEnabled = (pitem.enableState == EnabledState.None) ? EnabledState.All : EnabledState.None; - pitem.enableState = newEnabled; - ItemWasToggled(m_Selection[0]); - } - - Event.current.Use(); - } - } - - public void SetAllEnabled(EnabledState state) - { - EnableChildrenRecursive(m_TreeView.data.root, state); - ComputeEnabledStateForFolders(); - } - - void ItemWasToggled(PackageImportTreeViewItem pitem) - { - if (m_Selection.Count <= 1) - { - EnableChildrenRecursive(pitem, pitem.enableState); - } - else - { - foreach (var childPItem in m_Selection) - { - childPItem.enableState = pitem.enableState; - } - } - - ComputeEnabledStateForFolders(); - } - - void EnableChildrenRecursive(TreeViewItem parentItem, EnabledState state) - { - if (!parentItem.hasChildren) - return; - - foreach (TreeViewItem tvitem in parentItem.children) - { - var pitem = tvitem as PackageImportTreeViewItem; - pitem.enableState = state; - - EnableChildrenRecursive(pitem, state); - } - } - - // Item - - private class PackageImportTreeViewItem : TreeViewItem - { - public ImportPackageItem item { get; set; } - - public EnabledState enableState - { - get { return m_EnableState; } - set - { - // We only want to set the enabled state if the item - // is not a project asset. - if (item == null || !item.projectAsset) - { - m_EnableState = value; - if (item != null) - item.enabledStatus = (int)value; - } - } - } - - public PackageImportTreeViewItem(ImportPackageItem itemIn, int id, int depth, TreeViewItem parent, string displayName) - : base(id, depth, parent, displayName) - { - item = itemIn; - - if (item == null) - m_EnableState = EnabledState.All; - else - m_EnableState = (EnabledState)item.enabledStatus; - } - - private EnabledState m_EnableState; - } - - // Gui - - private class PackageImportTreeViewGUI : TreeViewGUI - { - internal static class Constants - { - public static Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResourcesUtility.folderIconName); - public static GUIContent badgeNew = EditorGUIUtility.TrIconContent("PackageBadgeNew", "This is a new Asset"); - public static GUIContent badgeDelete = EditorGUIUtility.TrIconContent("PackageBadgeDelete", "These files will be deleted!"); - public static GUIContent badgeWarn = EditorGUIUtility.TrIconContent("console.warnicon", "Warning: File exists in project, but with different GUID. Will override existing asset which may be undesired."); - public static GUIContent badgeChange = EditorGUIUtility.TrIconContent("playLoopOff", "This file is new or has changed."); - - public static GUIStyle paddinglessStyle; - - static Constants() - { - paddinglessStyle = new GUIStyle(); - paddinglessStyle.padding = new RectOffset(0, 0, 0, 0); - } - } - - public Action itemWasToggled; - public int showPreviewForID { get; set; } - - private PackageImportTreeView m_PackageImportView; - protected float k_FoldoutWidth = 12f; - - public PackageImportTreeViewGUI(TreeViewController treeView, PackageImportTreeView view) - : base(treeView) - { - m_PackageImportView = view; - - k_BaseIndent = 4f; - if (!s_UseFoldouts) - k_FoldoutWidth = 0f; - } - - override public void OnRowGUI(Rect rowRect, TreeViewItem tvItem, int row, bool selected, bool focused) - { - k_IndentWidth = 18; - k_FoldoutWidth = 18; - const float k_ToggleWidth = 18f; - - var pitem = tvItem as PackageImportTreeViewItem; - var item = pitem.item; - - bool repainting = Event.current.type == EventType.Repaint; - - // 0. Selection row rect - if (selected && repainting) - Styles.selectionStyle.Draw(rowRect, false, false, true, focused); - - bool validItem = (item != null); - bool isFolder = (item != null) ? item.isFolder : true; - bool assetChanged = (item != null) ? item.assetChanged : false; - bool pathConflict = (item != null) ? item.pathConflict : false; - bool exists = (item != null) ? item.exists : true; - bool projectAsset = (item != null) ? item.projectAsset : false; - bool doReInstall = m_PackageImportView.doReInstall; - - // 1. Foldout - if (m_TreeView.data.IsExpandable(tvItem)) - DoFoldout(rowRect, tvItem, row); - - // 2. Toggle only for items that are actually in the package. - Rect toggleRect = new Rect(k_BaseIndent + tvItem.depth * indentWidth + k_FoldoutWidth, rowRect.y, k_ToggleWidth, rowRect.height); - - if ((isFolder && !projectAsset) || (validItem && !projectAsset && (assetChanged || doReInstall))) - DoToggle(pitem, toggleRect); - - using (new EditorGUI.DisabledScope(!validItem || projectAsset)) - { - // 3. Icon & Text - Rect contentRect = new Rect(toggleRect.xMax, rowRect.y, rowRect.width, rowRect.height); - DoIconAndText(tvItem, contentRect, selected, focused); - - // 4. Preview popup - DoPreviewPopup(pitem, rowRect); - - // 4.5 Warning about file clashing. - if (repainting && validItem && pathConflict) - { - Rect labelRect = new Rect(rowRect.xMax - 58, rowRect.y, rowRect.height, rowRect.height); - EditorGUIUtility.SetIconSize(new Vector2(rowRect.height, rowRect.height)); - GUI.Label(labelRect, Constants.badgeWarn); - EditorGUIUtility.SetIconSize(Vector2.zero); - } - - - // 5. Optional badge ("New") - if (repainting && validItem && !(exists || pathConflict)) - { - // FIXME: Need to enable tooltips here. - Texture badge = Constants.badgeNew.image; - Rect labelRect = new Rect(rowRect.xMax - badge.width - 6, rowRect.y + (rowRect.height - badge.height) / 2, badge.width, badge.height); - GUI.Label(labelRect, Constants.badgeNew, Constants.paddinglessStyle); - } - - // 5. Optional badge ("Delete") - if (repainting && doReInstall && projectAsset) - { - // FIXME: Need to enable tooltips here. - Texture badge = Constants.badgeDelete.image; - Rect labelRect = new Rect(rowRect.xMax - badge.width - 6, rowRect.y + (rowRect.height - badge.height) / 2, badge.width, badge.height); - GUI.Label(labelRect, Constants.badgeDelete, Constants.paddinglessStyle); - } - - // 7. Show what stuff has changed - if (repainting && validItem && (exists || pathConflict) && assetChanged) - { - Texture badge = Constants.badgeChange.image; - Rect labelRect = new Rect(rowRect.xMax - badge.width - 6, rowRect.y, rowRect.height, rowRect.height); - GUI.Label(labelRect, Constants.badgeChange, Constants.paddinglessStyle); - } - } - } - - static void Toggle(ImportPackageItem[] items, PackageImportTreeViewItem pitem, Rect toggleRect) - { - bool enabled = (int)pitem.enableState > 0; - bool isFolder = (pitem.item == null) || pitem.item.isFolder; - - GUIStyle style = EditorStyles.toggle; - bool setMixed = isFolder && (pitem.enableState == EnabledState.Mixed); - if (setMixed) - style = EditorStyles.toggleMixed; - - bool newEnabled = GUI.Toggle(toggleRect, enabled, GUIContent.none, style); - if (newEnabled != enabled) - pitem.enableState = newEnabled ? EnabledState.All : EnabledState.None; - } - - void DoToggle(PackageImportTreeViewItem pitem, Rect toggleRect) - { - // Toggle on/off - EditorGUI.BeginChangeCheck(); - Toggle(m_PackageImportView.packageItems, pitem, toggleRect); - if (EditorGUI.EndChangeCheck()) - { - // Only change selection if we already have single selection (Keep multi-selection when toggling) - if (m_TreeView.GetSelection().Length <= 1 || !m_TreeView.GetSelection().Contains(pitem.id)) - { - m_TreeView.SetSelection(new int[] { pitem.id }, false); - m_TreeView.NotifyListenersThatSelectionChanged(); - } - if (itemWasToggled != null) - itemWasToggled(pitem); - Event.current.Use(); - } - } - - void DoPreviewPopup(PackageImportTreeViewItem pitem, Rect rowRect) - { - var item = pitem.item; - - if (item != null) - { - // Ensure preview is shown when clicking on an already selected item (the preview might have been closed) - if (Event.current.type == EventType.MouseDown && rowRect.Contains(Event.current.mousePosition) && !PopupWindowWithoutFocus.IsVisible()) - showPreviewForID = pitem.id; - - // Show preview - if (pitem.id == showPreviewForID && Event.current.type != EventType.Layout) - { - showPreviewForID = 0; - if (!string.IsNullOrEmpty(item.previewPath)) - { - Texture2D preview = PackageImport.GetPreview(item.previewPath); - Rect buttonRect = rowRect; - buttonRect.width = EditorGUIUtility.currentViewWidth; - PopupWindowWithoutFocus.Show(buttonRect, new PreviewPopup(preview), new[] { PopupLocationHelper.PopupLocation.Right, PopupLocationHelper.PopupLocation.Left, PopupLocationHelper.PopupLocation.Below }); - } - } - } - } - - void DoIconAndText(TreeViewItem item, Rect contentRect, bool selected, bool focused) - { - EditorGUIUtility.SetIconSize(new Vector2(k_IconWidth, k_IconWidth)); // If not set we see icons scaling down if text is being cropped - GUIStyle lineStyle = Styles.lineStyle; - lineStyle.padding.left = 0; // padding could have been set by other tree views - contentRect.height += 5; // with the default row height, underscore and lower parts of characters like g, p, etc. were not visible - if (Event.current.type == EventType.Repaint) - lineStyle.Draw(contentRect, GUIContent.Temp(item.displayName, GetIconForItem(item)), false, false, selected, focused); - EditorGUIUtility.SetIconSize(Vector2.zero); - } - - protected override Texture GetIconForItem(TreeViewItem tvItem) - { - var ourItem = tvItem as PackageImportTreeViewItem; - var item = ourItem.item; - - // Indefined items are always folders. - if (item == null || item.isFolder) - { - return Constants.folderIcon; - } - - // We are using this TreeViewGUI when importing and exporting a package, so handle both situations: - - // Exporting a package can use cached icons (icons we generate on import) - Texture cachedIcon = AssetDatabase.GetCachedIcon(item.destinationAssetPath); - if (cachedIcon != null) - return cachedIcon; - - // Importing a package have to use icons based on file extension - return InternalEditorUtility.GetIconForFile(item.destinationAssetPath); - } - - protected override void RenameEnded() - { - } - } - - // Datasource - - private class PackageImportTreeViewDataSource : TreeViewDataSource - { - private PackageImportTreeView m_PackageImportView; - - public PackageImportTreeViewDataSource(TreeViewController treeView, PackageImportTreeView view) - : base(treeView) - { - m_PackageImportView = view; - rootIsCollapsable = false; - showRootItem = false; - } - - public override bool IsRenamingItemAllowed(TreeViewItem item) - { - return false; - } - - public override bool IsExpandable(TreeViewItem item) - { - if (!s_UseFoldouts) - return false; - - return base.IsExpandable(item); - } - - public override void FetchData() - { - int rootDepth = -1; // -1 so its children will have 0 depth - m_RootItem = new PackageImportTreeViewItem(null, "Assets".GetHashCode(), rootDepth, null, "InvisibleAssetsFolder"); - - bool initExpandedState = true; - if (initExpandedState) - m_TreeView.state.expandedIDs.Add(m_RootItem.id); - - ImportPackageItem[] items = m_PackageImportView.packageItems; - - Dictionary treeViewFolders = new Dictionary(); - for (int i = 0; i < items.Length; i++) - { - var item = items[i]; - - if (PackageImport.HasInvalidCharInFilePath(item.destinationAssetPath)) - continue; // Do not add invalid paths (we already warn the user with a dialog in PackageImport.cs) - - string filename = Path.GetFileName(item.destinationAssetPath).ConvertSeparatorsToUnity(); - string folderPath = Path.GetDirectoryName(item.destinationAssetPath).ConvertSeparatorsToUnity(); - - // Ensure folders. This is for when installed packages have been moved to other folders. - TreeViewItem targetFolder = EnsureFolderPath(folderPath, treeViewFolders, initExpandedState); - - // Add file to folder - if (targetFolder != null) - { - int id = item.destinationAssetPath.GetHashCode(); - var newItem = new PackageImportTreeViewItem(item, id, targetFolder.depth + 1, targetFolder, filename); - targetFolder.AddChild(newItem); - - if (initExpandedState) - m_TreeView.state.expandedIDs.Add(id); - - // We need to ensure that the folder is available for - // EnsureFolderPath on subsequent iterations. - if (item.isFolder) - treeViewFolders[item.destinationAssetPath] = newItem; - } - } - - if (initExpandedState) - m_TreeView.state.expandedIDs.Sort(); - } - - TreeViewItem EnsureFolderPath(string folderPath, Dictionary treeViewFolders, bool initExpandedState) - { - //We're in the root folder, so just return the root item as the parent. - if (folderPath == "") - return m_RootItem; - - // Does folder path exist? - int id = folderPath.GetHashCode(); - TreeViewItem item = TreeViewUtility.FindItem(id, m_RootItem); - - if (item != null) - return item; - - // Add folders as needed - string[] splitPath = folderPath.Split('/'); - string currentPath = ""; - TreeViewItem currentItem = m_RootItem; - int folderDepth = -1; // Will be incremented to the right depth in the loop. - - for (int depth = 0; depth < splitPath.Length; ++depth) - { - string folder = splitPath[depth]; - if (currentPath != "") - currentPath += '/'; - - currentPath += folder; - - // Dont create a 'Assets' folder (we already have that as a hidden root) - if (depth == 0 && currentPath == "Assets") - continue; - - // Only increment the folder depth if we are past the root "Assets" folder. - ++folderDepth; - - id = currentPath.GetHashCode(); - - PackageImportTreeViewItem foundItem; - if (treeViewFolders.TryGetValue(currentPath, out foundItem)) - { - currentItem = foundItem; - } - else - { - // If we do not have a tree view item for this folder we create one - var folderItem = new PackageImportTreeViewItem(null, id, folderDepth, currentItem, folder); - - // Add to children array of the parent - currentItem.AddChild(folderItem); - currentItem = folderItem; - - // Auto expand all folder items - if (initExpandedState) - m_TreeView.state.expandedIDs.Add(id); - - // For faster finding of folders - treeViewFolders[currentPath] = folderItem; - } - } - - return currentItem; - } - } - - - class PreviewPopup : PopupWindowContent - { - readonly Texture2D m_Preview; - readonly Vector2 kPreviewSize = new Vector2(128f, 128f); - - public PreviewPopup(Texture2D preview) - { - m_Preview = preview; - } - - public override void OnGUI(Rect rect) - { - PackageImport.DrawTexture(rect, m_Preview, false); - } - - public override Vector2 GetWindowSize() - { - return kPreviewSize; - } - } - } -} diff --git a/Editor/Mono/GUI/PaneDragTab.cs b/Editor/Mono/GUI/PaneDragTab.cs deleted file mode 100644 index f27d7b57da..0000000000 --- a/Editor/Mono/GUI/PaneDragTab.cs +++ /dev/null @@ -1,167 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - // This uses a normal editor window with a single view inside. - internal class PaneDragTab : GUIView - { - const float kMaxArea = 50000.0f; - - [SerializeField] -#pragma warning disable 169 - bool m_Shadow; - - static PaneDragTab s_Get; - const float kTopThumbnailOffset = 10; - [SerializeField] - Vector2 m_FullWindowSize = new Vector2(80, 60); - - [SerializeField] - Rect m_TargetRect; - [SerializeField] - static GUIStyle s_PaneStyle, s_TabStyle; - - bool m_TabVisible; - - float m_TargetAlpha = 1.0f; - - DropInfo.Type m_Type = (DropInfo.Type)(-1); - - GUIContent m_Content; - [SerializeField] - internal ContainerWindow m_Window; - [SerializeField] - ContainerWindow m_InFrontOfWindow = null; - - static public PaneDragTab get - { - get - { - if (!s_Get) - { - Object[] objs = Resources.FindObjectsOfTypeAll(typeof(PaneDragTab)); - if (objs.Length != 0) - s_Get = (PaneDragTab)objs[0]; - if (s_Get) - { - return s_Get; - } - s_Get = ScriptableObject.CreateInstance(); - } - return s_Get; - } - } - - public void SetDropInfo(DropInfo di, Vector2 mouseScreenPos, ContainerWindow inFrontOf) - { - if (m_Type != di.type || (di.type == DropInfo.Type.Pane && di.rect != m_TargetRect)) - { - m_Type = di.type; - - switch (di.type) - { - case DropInfo.Type.Window: - m_TargetAlpha = 0.6f; - break; - case DropInfo.Type.Pane: - case DropInfo.Type.Tab: - m_TargetAlpha = 1.0f; - break; - } - } - - switch (di.type) - { - case DropInfo.Type.Window: - m_TargetRect = new Rect(mouseScreenPos.x - m_FullWindowSize.x / 2, mouseScreenPos.y - m_FullWindowSize.y / 2, - m_FullWindowSize.x, m_FullWindowSize.y); - break; - case DropInfo.Type.Pane: - case DropInfo.Type.Tab: - m_TargetRect = di.rect; - break; - } - - m_TabVisible = di.type == DropInfo.Type.Tab; - - m_TargetRect.x = Mathf.Round(m_TargetRect.x); - m_TargetRect.y = Mathf.Round(m_TargetRect.y); - m_TargetRect.width = Mathf.Round(m_TargetRect.width); - m_TargetRect.height = Mathf.Round(m_TargetRect.height); - - m_InFrontOfWindow = inFrontOf; - m_Window.MoveInFrontOf(m_InFrontOfWindow); - - // On Windows, repainting without setting proper size first results in one garbage frame... For some reason. - SetWindowPos(m_TargetRect); - // Yes, repaint. - Repaint(); - } - - public void Close() - { - if (m_Window) - m_Window.Close(); - DestroyImmediate(this, true); - s_Get = null; - } - - public void Show(Rect pixelPos, GUIContent content, Vector2 viewSize, Vector2 mouseScreenPosition) - { - m_Content = content; - // scale not to be larger then maxArea pixels. - var area = viewSize.x * viewSize.y; - m_FullWindowSize = viewSize * Mathf.Sqrt(Mathf.Clamp01(kMaxArea / area)); - - if (!m_Window) - { - m_Window = ScriptableObject.CreateInstance(); - m_Window.m_DontSaveToLayout = true; - SetMinMaxSizes(Vector2.zero, new Vector2(10000, 10000)); - SetWindowPos(pixelPos); - m_Window.rootView = this; - } - else - { - SetWindowPos(pixelPos); - } - m_Window.Show(ShowMode.NoShadow, true, false); - - m_TargetRect = pixelPos; - } - - void SetWindowPos(Rect screenPosition) - { - m_Window.position = screenPosition; - } - - protected override void OldOnGUI() - { - if (s_PaneStyle == null) - { - s_PaneStyle = "dragtabdropwindow"; - s_TabStyle = "dragtab"; - } - - if (Event.current.type == EventType.Repaint) - { - Color oldGUIColor = GUI.color; - GUI.color = Color.white; - s_PaneStyle.Draw(new Rect(0, 0, position.width, position.height), m_Content, false, false, true, true); - if (m_TabVisible) - { - s_TabStyle.Draw(new Rect(0, 0, position.width, position.height), m_Content, false, false, true, true); - } - GUI.color = oldGUIColor; - - m_Window.SetAlpha(m_TargetAlpha); //We currently only support this on macOS - } - } - } -} // namespace diff --git a/Editor/Mono/GUI/PingData.cs b/Editor/Mono/GUI/PingData.cs deleted file mode 100644 index fbbcdfdf79..0000000000 --- a/Editor/Mono/GUI/PingData.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - // Handles a "ping" in project/hierarchy windows. Zoom, wait and fadeoff. - // Init by setting: - // - m_PingStyle: Background style - // - m_ContentDraw: Content render callback function (is rendered on top of background ping style) - // - 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) - class PingData - { - public float m_TimeStart = -1f; - - public float m_ZoomTime = 0.2f; - public float m_WaitTime = 2.5f; - public float m_FadeOutTime = 1.5f; - public float m_PeakScale = 1.75f; - - public System.Action m_ContentDraw; - public Rect m_ContentRect; // Rect passed to m_ContentDraw - - // How wide is the view where we are pinging. Needed for the pivot point trick where pinged content is only partly visible. - public float m_AvailableWidth = 100f; - public GUIStyle m_PingStyle; - - public bool isPinging - { - get { return m_TimeStart > -1f; } - } - - public void HandlePing() - { - if (isPinging) - { - float totalTime = m_ZoomTime + m_WaitTime + m_FadeOutTime; - float t = (Time.realtimeSinceStartup - m_TimeStart); - - if (t > 0.0f && t < totalTime) - { - Color c = GUI.color; - Matrix4x4 m = GUI.matrix; - if (t < m_ZoomTime) - { - float peakTime = m_ZoomTime / 2f; - float scale = (m_PeakScale - 1f) * (((m_ZoomTime - Mathf.Abs(peakTime - t)) / peakTime) - 1f) + 1f; - Matrix4x4 mat = GUI.matrix; - - // If the content is only partly visible, the zoom pivot point is moved to right border. This avoids the nasty artefacts. - Vector2 pivotPoint = m_ContentRect.xMax < m_AvailableWidth ? m_ContentRect.center : new Vector2(m_AvailableWidth, m_ContentRect.center.y); - Vector2 point = GUIClip.Unclip(pivotPoint); - Matrix4x4 newMat = Matrix4x4.TRS(point, Quaternion.identity, new Vector3(scale, scale, 1)) * Matrix4x4.TRS(-point, Quaternion.identity, Vector3.one); - GUI.matrix = newMat * mat; - } - else if (t > m_ZoomTime + m_WaitTime) - { - float alpha = (totalTime - t) / m_FadeOutTime; - GUI.color = new Color(c.r, c.g, c.b, c.a * alpha); - } - - if (m_ContentDraw != null && Event.current.type == EventType.Repaint) - { - Rect backRect = m_ContentRect; - backRect.x -= m_PingStyle.padding.left; - backRect.y -= m_PingStyle.padding.top; - m_PingStyle.Draw(backRect, GUIContent.none, false, false, false, false); - m_ContentDraw(m_ContentRect); - } - - GUI.matrix = m; - GUI.color = c; - } - else - { - m_TimeStart = -1f; - } - } - } - } -} diff --git a/Editor/Mono/GUI/PopupLocationHelper.cs b/Editor/Mono/GUI/PopupLocationHelper.cs deleted file mode 100644 index 66d1dbe968..0000000000 --- a/Editor/Mono/GUI/PopupLocationHelper.cs +++ /dev/null @@ -1,172 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - - -namespace UnityEditor -{ - internal static class PopupLocationHelper - { - public enum PopupLocation { Below, Above, Left, Right } - - public static Rect GetDropDownRect(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow) - { - return GetDropDownRect(buttonRect, minSize, maxSize, popupContainerWindow, null); - } - - public static Rect GetDropDownRect(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow, PopupLocation[] locationPriorityOrder) - { - if (locationPriorityOrder == null) - locationPriorityOrder = new[] {PopupLocation.Below, PopupLocation.Above, PopupLocation.Left, PopupLocation.Right}; // Default priority order - - List croppedRects = new List(); - foreach (PopupLocation location in locationPriorityOrder) - { - Rect resultRect; - switch (location) - { - case PopupLocation.Below: - if (PopupBelow(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect)) - return resultRect; - croppedRects.Add(resultRect); - break; - case PopupLocation.Above: - if (PopupAbove(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect)) - return resultRect; - croppedRects.Add(resultRect); - break; - case PopupLocation.Left: - if (PopupLeft(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect)) - return resultRect; - croppedRects.Add(resultRect); - break; - case PopupLocation.Right: - if (PopupRight(buttonRect, minSize, maxSize, popupContainerWindow, out resultRect)) - return resultRect; - croppedRects.Add(resultRect); - break; - } - } - - // Popup did not fit any of the wanted locations. Now find and return the largest cropped rect instead - return GetLargestRect(croppedRects); - } - - private static Rect FitRect(Rect rect, ContainerWindow popupContainerWindow) - { - if (popupContainerWindow) - return popupContainerWindow.FitWindowRectToScreen(rect, true, true); - else - return ContainerWindow.FitRectToScreen(rect, true, true); - } - - private static bool PopupRight(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow, out Rect resultRect) - { - // Calculate how much space is available for the window right of the button - Rect dropDownRectRight = new Rect(buttonRect.xMax, buttonRect.y, maxSize.x, maxSize.y); - float spaceFromRight = 0; - dropDownRectRight.xMax += spaceFromRight; - dropDownRectRight.height += k_SpaceFromBottom; - - dropDownRectRight = FitRect(dropDownRectRight, popupContainerWindow); - float availableWidthRight = Mathf.Max(dropDownRectRight.xMax - buttonRect.xMax - spaceFromRight, 0); - float windowWidth = Mathf.Min(availableWidthRight, maxSize.x); - resultRect = new Rect(dropDownRectRight.x, dropDownRectRight.y, windowWidth, dropDownRectRight.height - k_SpaceFromBottom); - - if (availableWidthRight >= minSize.x) - return true; - return false; - } - - private static bool PopupLeft(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow, - out Rect resultRect) - { - // Calculate how much space is available for the window left of the button - Rect dropDownRectLeft = new Rect(buttonRect.x - maxSize.x, buttonRect.y, maxSize.x, maxSize.y); - float spaceFromLeft = 0; - dropDownRectLeft.xMin -= spaceFromLeft; - dropDownRectLeft.height += k_SpaceFromBottom; - - dropDownRectLeft = FitRect(dropDownRectLeft, popupContainerWindow); - float availableWidthLeft = Mathf.Max(buttonRect.x - dropDownRectLeft.x - spaceFromLeft, 0); - float windowWidth = Mathf.Min(availableWidthLeft, maxSize.x); - resultRect = new Rect(dropDownRectLeft.x, dropDownRectLeft.y, windowWidth, dropDownRectLeft.height - k_SpaceFromBottom); - - if (availableWidthLeft >= minSize.x) - return true; - return false; - } - - private static bool PopupAbove(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow, - out Rect resultRect) - { - Rect dropDownRectAbove = new Rect(buttonRect.x, buttonRect.y - maxSize.y, maxSize.x, maxSize.y); - float spaceFromTop = 0; - - // Expand dropdown height to include empty space above - dropDownRectAbove.yMin -= spaceFromTop; - // Fit rect to screen - dropDownRectAbove = FitRect(dropDownRectAbove, popupContainerWindow); - - // Calculate how much space is available for the window above the button - float availableHeightAbove = Mathf.Max(buttonRect.y - dropDownRectAbove.y - spaceFromTop, 0); - // If there's room for the window at its minimum size above the button, then place it there - if (availableHeightAbove >= minSize.y) - { - float windowHeight = Mathf.Min(availableHeightAbove, maxSize.y); - { - resultRect = new Rect(dropDownRectAbove.x, buttonRect.y - windowHeight, dropDownRectAbove.width, windowHeight); - return true; - } - } - resultRect = new Rect(dropDownRectAbove.x, buttonRect.y - availableHeightAbove, dropDownRectAbove.width, availableHeightAbove); - return false; - } - - private static bool PopupBelow(Rect buttonRect, Vector2 minSize, Vector2 maxSize, ContainerWindow popupContainerWindow, - out Rect resultRect) - { - Rect dropDownRectBelow = new Rect(buttonRect.x, buttonRect.yMax, maxSize.x, maxSize.y); - - // Expand dropdown height to include empty space below - dropDownRectBelow.height += k_SpaceFromBottom; - // Fit rect to screen - dropDownRectBelow = FitRect(dropDownRectBelow, popupContainerWindow); - - // Calculate how much space is available for the window below the button - float availableHeightBelow = Mathf.Max(dropDownRectBelow.yMax - buttonRect.yMax - k_SpaceFromBottom, 0); - // If there's room for the window at its minimum size below the button, then place it there - if (availableHeightBelow >= minSize.y) - { - float windowHeight = Mathf.Min(availableHeightBelow, maxSize.y); - resultRect = new Rect(dropDownRectBelow.x, buttonRect.yMax, dropDownRectBelow.width, windowHeight); - return true; - } - resultRect = new Rect(dropDownRectBelow.x, buttonRect.yMax, dropDownRectBelow.width, availableHeightBelow); - return false; - } - - private static Rect GetLargestRect(List rects) - { - Rect max = new Rect(); - foreach (Rect rect in rects) - if (rect.height * rect.width > max.height * max.width) - max = rect; - return max; - } - - // How much empty space there should be at minimum at the bottom of the screen below the popup - private static float k_SpaceFromBottom - { - get - { - if (Application.platform == RuntimePlatform.OSXEditor) - return 10f; - return 0; - } - } - } -} diff --git a/Editor/Mono/GUI/PopupWindow.cs b/Editor/Mono/GUI/PopupWindow.cs deleted file mode 100644 index 6ccc4a520c..0000000000 --- a/Editor/Mono/GUI/PopupWindow.cs +++ /dev/null @@ -1,131 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - /* - Note that content of PopupWindow do not survive assembly reloading because it derives from interface PopupWindowContent. - E.g use it for short lived content where closing on lost focus is ok. - */ - - public abstract class PopupWindowContent - { - public EditorWindow editorWindow { get; internal set; } - - public abstract void OnGUI(Rect rect); - public virtual Vector2 GetWindowSize() - { - return new Vector2(200, 200); - } - - public virtual void OnOpen() {} - public virtual void OnClose() {} - } - - public class PopupWindow : EditorWindow - { - PopupWindowContent m_WindowContent; - Vector2 m_LastWantedSize = Vector2.zero; - Rect m_ActivatorRect; - static double s_LastClosedTime; - static Rect s_LastActivatorRect; - - internal PopupWindow() - { - } - - public static void Show(Rect activatorRect, PopupWindowContent windowContent) - { - Show(activatorRect, windowContent, null); - } - - internal static void Show(Rect activatorRect, PopupWindowContent windowContent, PopupLocationHelper.PopupLocation[] locationPriorityOrder) - { - Show(activatorRect, windowContent, locationPriorityOrder, ShowMode.PopupMenu); - } - - // Shown on top of any previous windows - internal static void Show(Rect activatorRect, PopupWindowContent windowContent, PopupLocationHelper.PopupLocation[] locationPriorityOrder, ShowMode showMode) - { - if (ShouldShowWindow(activatorRect)) - { - PopupWindow win = CreateInstance(); - if (win != null) - { - win.Init(activatorRect, windowContent, locationPriorityOrder, showMode); - } - EditorGUIUtility.ExitGUI(); // Needed to prevent GUILayout errors on OSX - } - } - - static bool ShouldShowWindow(Rect activatorRect) - { - const double kJustClickedTime = 0.2; - bool justClosed = (EditorApplication.timeSinceStartup - s_LastClosedTime) < kJustClickedTime; - if (!justClosed || activatorRect != s_LastActivatorRect) - { - s_LastActivatorRect = activatorRect; - return true; - } - return false; - } - - void Init(Rect activatorRect, PopupWindowContent windowContent, PopupLocationHelper.PopupLocation[] locationPriorityOrder) - { - Init(activatorRect, windowContent, locationPriorityOrder, ShowMode.PopupMenu); - } - - void Init(Rect activatorRect, PopupWindowContent windowContent, PopupLocationHelper.PopupLocation[] locationPriorityOrder, ShowMode showMode) - { - hideFlags = HideFlags.DontSave; - wantsMouseMove = true; - m_WindowContent = windowContent; - m_WindowContent.editorWindow = this; - m_WindowContent.OnOpen(); - m_ActivatorRect = GUIUtility.GUIToScreenRect(activatorRect); - ShowAsDropDown(m_ActivatorRect, m_WindowContent.GetWindowSize(), locationPriorityOrder, showMode); - } - - internal void OnGUI() - { - FitWindowToContent(); - Rect windowRect = new Rect(0, 0, position.width, position.height); - m_WindowContent.OnGUI(windowRect); - GUI.Label(windowRect, GUIContent.none, "grey_border"); - } - - private void FitWindowToContent() - { - Vector2 wantedSize = m_WindowContent.GetWindowSize(); - if (m_LastWantedSize != wantedSize) - { - m_LastWantedSize = wantedSize; - Rect screenRect = m_Parent.window.GetDropDownRect(m_ActivatorRect, wantedSize, wantedSize); - minSize = maxSize = new Vector2(screenRect.width, screenRect.height); - position = screenRect; - } - } - - void CloseWindow() - { - Close(); - } - - void OnEnable() - { - AssemblyReloadEvents.beforeAssemblyReload += CloseWindow; - } - - void OnDisable() - { - AssemblyReloadEvents.beforeAssemblyReload -= CloseWindow; - - s_LastClosedTime = EditorApplication.timeSinceStartup; - if (m_WindowContent != null) - m_WindowContent.OnClose(); - } - } -} diff --git a/Editor/Mono/GUI/PopupWindowWithoutFocus.cs b/Editor/Mono/GUI/PopupWindowWithoutFocus.cs deleted file mode 100644 index da92e82c5d..0000000000 --- a/Editor/Mono/GUI/PopupWindowWithoutFocus.cs +++ /dev/null @@ -1,134 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; - -namespace UnityEditor -{ - class PopupWindowWithoutFocus : EditorWindow - { - static PopupWindowWithoutFocus s_PopupWindowWithoutFocus; - static double s_LastClosedTime; - static Rect s_LastActivatorRect; - - PopupWindowContent m_WindowContent; - PopupLocationHelper.PopupLocation[] m_LocationPriorityOrder; - Vector2 m_LastWantedSize = Vector2.zero; - Rect m_ActivatorRect; - float m_BorderWidth = 1f; - - public static void Show(Rect activatorRect, PopupWindowContent windowContent) - { - Show(activatorRect, windowContent, null); - } - - public static bool IsVisible() - { - return s_PopupWindowWithoutFocus != null; - } - - internal static void Show(Rect activatorRect, PopupWindowContent windowContent, PopupLocationHelper.PopupLocation[] locationPriorityOrder) - { - if (ShouldShowWindow(activatorRect)) - { - if (s_PopupWindowWithoutFocus == null) - s_PopupWindowWithoutFocus = CreateInstance(); - - s_PopupWindowWithoutFocus.Init(activatorRect, windowContent, locationPriorityOrder); - } - } - - public static void Hide() - { - if (s_PopupWindowWithoutFocus != null) - s_PopupWindowWithoutFocus.Close(); - } - - void Init(Rect activatorRect, PopupWindowContent windowContent, PopupLocationHelper.PopupLocation[] locationPriorityOrder) - { - m_WindowContent = windowContent; - m_WindowContent.editorWindow = this; - m_ActivatorRect = GUIUtility.GUIToScreenRect(activatorRect); - m_LastWantedSize = windowContent.GetWindowSize(); - m_LocationPriorityOrder = locationPriorityOrder; - - Vector2 windowSize = windowContent.GetWindowSize() + new Vector2(m_BorderWidth * 2, m_BorderWidth * 2); - position = PopupLocationHelper.GetDropDownRect(m_ActivatorRect, windowSize, windowSize, null, m_LocationPriorityOrder); - ShowPopup(); - Repaint(); - } - - void OnEnable() - { - hideFlags = HideFlags.DontSave; - s_PopupWindowWithoutFocus = this; - } - - void OnDisable() - { - s_LastClosedTime = EditorApplication.timeSinceStartup; - if (m_WindowContent != null) - m_WindowContent.OnClose(); - s_PopupWindowWithoutFocus = null; - } - - // Invoked from C++ - static bool OnGlobalMouseOrKeyEvent(EventType type, KeyCode keyCode, Vector2 mousePosition) - { - if (s_PopupWindowWithoutFocus == null) - return false; - - if (type == EventType.KeyDown && keyCode == KeyCode.Escape) - { - s_PopupWindowWithoutFocus.Close(); - return true; - } - - if (type == EventType.MouseDown && !s_PopupWindowWithoutFocus.position.Contains(mousePosition)) - { - s_PopupWindowWithoutFocus.Close(); - return true; - } - - return false; - } - - static bool ShouldShowWindow(Rect activatorRect) - { - const double kJustClickedTime = 0.2; - bool justClosed = (EditorApplication.timeSinceStartup - s_LastClosedTime) < kJustClickedTime; - if (!justClosed || activatorRect != s_LastActivatorRect) - { - s_LastActivatorRect = activatorRect; - return true; - } - return false; - } - - internal void OnGUI() - { - FitWindowToContent(); - Rect windowRect = new Rect(m_BorderWidth, m_BorderWidth, position.width - 2 * m_BorderWidth, position.height - 2 * m_BorderWidth); - m_WindowContent.OnGUI(windowRect); - GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, "grey_border"); - } - - private void FitWindowToContent() - { - Vector2 wantedSize = m_WindowContent.GetWindowSize(); - if (m_LastWantedSize != wantedSize) - { - m_LastWantedSize = wantedSize; - Vector2 windowSize = wantedSize + new Vector2(2 * m_BorderWidth, 2 * m_BorderWidth); - Rect screenRect = PopupLocationHelper.GetDropDownRect(m_ActivatorRect, windowSize, windowSize, null, m_LocationPriorityOrder); - m_Pos = screenRect; - minSize = maxSize = new Vector2(screenRect.width, screenRect.height); - } - } - } -} diff --git a/Editor/Mono/GUI/PragmaFixingWindow.cs b/Editor/Mono/GUI/PragmaFixingWindow.cs deleted file mode 100644 index 796ec721bb..0000000000 --- a/Editor/Mono/GUI/PragmaFixingWindow.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using UnityEditor.Scripting; - -namespace UnityEditor -{ - internal class PragmaFixingWindow : EditorWindow - { - public static void ShowWindow(string[] paths) - { - PragmaFixingWindow win = EditorWindow.GetWindow(true); - win.SetPaths(paths); - win.ShowModal(); - } - - class Styles - { - public GUIStyle selected = "OL SelectedRow"; - public GUIStyle box = "OL Box"; - public GUIStyle button = "LargeButton"; - } - - static Styles s_Styles = null; - - ListViewState m_LV = new ListViewState(); - string[] m_Paths; - - public PragmaFixingWindow() - { - titleContent = EditorGUIUtility.TrTextContent("Unity - #pragma fixing"); - } - - public void SetPaths(string[] paths) - { - m_Paths = paths; - m_LV.totalRows = paths.Length; - } - - void OnGUI() - { - if (s_Styles == null) - { - s_Styles = new Styles(); - minSize = new Vector2(450, 300); - position = new Rect(position.x, position.y, minSize.x, minSize.y); - } - - GUILayout.Space(10); - GUILayout.Label("#pragma implicit and #pragma downcast need to be added to following files\nfor backwards compatibility"); - GUILayout.Space(10); - - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - foreach (ListViewElement el in ListViewGUILayout.ListView(m_LV, s_Styles.box)) - { - if (el.row == m_LV.row && Event.current.type == EventType.Repaint) - s_Styles.selected.Draw(el.position, false, false, false, false); - - GUILayout.Label(m_Paths[el.row]); - } - GUILayout.Space(10); - GUILayout.EndHorizontal(); - GUILayout.Space(10); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Fix now", s_Styles.button)) - { - Close(); - PragmaFixing30.FixFiles(m_Paths); - // bugfix (377429): do not call AssetDatabase.Refresh here as that screws up project upgrading. - // When this script is invoked from Application::InitializeProject, the assets will be refreshed anyway. - GUIUtility.ExitGUI(); - } - - if (GUILayout.Button("Ignore", s_Styles.button)) - { - Close(); - GUIUtility.ExitGUI(); - } - - if (GUILayout.Button("Quit", s_Styles.button)) - { - EditorApplication.Exit(0); - GUIUtility.ExitGUI(); - } - - GUILayout.Space(10); - GUILayout.EndHorizontal(); - - GUILayout.Space(10); - } - } -} diff --git a/Editor/Mono/GUI/PreviewResizer.cs b/Editor/Mono/GUI/PreviewResizer.cs deleted file mode 100644 index c6f91814f1..0000000000 --- a/Editor/Mono/GUI/PreviewResizer.cs +++ /dev/null @@ -1,205 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [System.Serializable] - internal class PreviewResizer - { - // The raw preview size while dragging (not snapped to allowed values) (shared) - static float s_DraggedPreviewSize = 0; - // The returned preview size while dragging (shared) - static float s_CachedPreviewSizeWhileDragging = 0; - static float s_MouseDownLocation, s_MouseDownValue; - static bool s_MouseDragged; - - // The last saved preview size - only saved when not dragging - // The saved value is the size when expanded - when collapsed the value is negative, - // so it can be restored when expanded again. - [SerializeField] - private float m_CachedPref; - [SerializeField] - private int m_ControlHash; - [SerializeField] - private string m_PrefName; - - private int m_Id = 0; - - private int id - { - get - { - if (m_Id == 0) - m_Id = EditorGUIUtility.GetControlID(m_ControlHash, FocusType.Passive, new Rect()); - return m_Id; - } - } - - // Instances of this class should be serialized. - // The Init function will only have effect if the serialized values are not already set. - public void Init(string prefName) - { - if (m_ControlHash != 0 && !string.IsNullOrEmpty(m_PrefName)) - return; - - // The controlHash is set by the calling code - // There's one for the Inspector, one for LightmapEditor, etc. - m_ControlHash = prefName.GetHashCode(); - - // We'll have one pref name per controlHash - m_PrefName = "Preview_" + prefName; - - // This is the only place the pref is read. This means we can have e.g. multiple - // Inspectors that can be controlled individually as long as they're open. - m_CachedPref = EditorPrefs.GetFloat(m_PrefName, 1); - } - - public float ResizeHandle(Rect windowPosition, float minSize, float minRemainingSize, float resizerHeight) - { - return ResizeHandle(windowPosition, minSize, minRemainingSize, resizerHeight, new Rect()); - } - - public float ResizeHandle(Rect windowPosition, float minSize, float minRemainingSize, float resizerHeight, Rect dragRect) - { - // Sanity check the cached value. It can be positive or negative, but never smaller than the minSize - if (Mathf.Abs(m_CachedPref) < minSize) - m_CachedPref = minSize * Mathf.Sign(m_CachedPref); - - float maxPreviewSize = windowPosition.height - minRemainingSize; - bool dragging = (GUIUtility.hotControl == id); - - float previewSize = (dragging ? s_DraggedPreviewSize : Mathf.Max(0, m_CachedPref)); - bool expanded = (m_CachedPref > 0); - float lastSize = Mathf.Abs(m_CachedPref); - - Rect resizerRect = new Rect(0, windowPosition.height - previewSize - resizerHeight, windowPosition.width, resizerHeight); - if (dragRect.width != 0) - { - resizerRect.x = dragRect.x; - resizerRect.width = dragRect.width; - } - - bool expandedBefore = expanded; - previewSize = -PixelPreciseCollapsibleSlider(id, resizerRect, -previewSize, -maxPreviewSize, -0, ref expanded); - previewSize = Mathf.Min(previewSize, maxPreviewSize); - dragging = (GUIUtility.hotControl == id); - - if (dragging) - s_DraggedPreviewSize = previewSize; - - // First snap size between 0 and minimum size - if (previewSize < minSize) - previewSize = (previewSize < minSize * 0.5f ? 0 : minSize); - - // If user clicked area, adjust size - if (expanded != expandedBefore) - previewSize = (expanded ? lastSize : 0); - - // Determine new expanded state - expanded = (previewSize >= minSize / 2); - - // Keep track of last preview size while not dragging or collapsed - // Note we don't want to save when dragging preview OR window size, - // so just don't save while dragging anything at all - if (GUIUtility.hotControl == 0) - { - if (previewSize > 0) - lastSize = previewSize; - float newPref = lastSize * (expanded ? 1 : -1); - if (newPref != m_CachedPref) - { - // Save the value to prefs - m_CachedPref = newPref; - EditorPrefs.SetFloat(m_PrefName, m_CachedPref); - } - } - - s_CachedPreviewSizeWhileDragging = previewSize; - return previewSize; - } - - // This value will change in realtime while dragging - public bool GetExpanded() - { - if (GUIUtility.hotControl == id) - return (s_CachedPreviewSizeWhileDragging > 0); - else - return (m_CachedPref > 0); - } - - public float GetPreviewSize() - { - if (GUIUtility.hotControl == id) - return Mathf.Max(0, s_CachedPreviewSizeWhileDragging); - else - return Mathf.Max(0, m_CachedPref); - } - - // This value won't change until we have stopped dragging again - public bool GetExpandedBeforeDragging() - { - return (m_CachedPref > 0); - } - - public void SetExpanded(bool expanded) - { - // Set the sign based on whether it's collapsed or not, then save to prefs - m_CachedPref = Mathf.Abs(m_CachedPref) * (expanded ? 1 : -1); - EditorPrefs.SetFloat(m_PrefName, m_CachedPref); - } - - public void ToggleExpanded() - { - // Reverse the sign, then save to prefs - m_CachedPref = -m_CachedPref; - EditorPrefs.SetFloat(m_PrefName, m_CachedPref); - } - - // This is the slider behavior for resizing the preview area - public static float PixelPreciseCollapsibleSlider(int id, Rect position, float value, float min, float max, ref bool expanded) - { - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (GUIUtility.hotControl == 0 && evt.button == 0 && position.Contains(evt.mousePosition)) - { - GUIUtility.hotControl = id; - s_MouseDownLocation = evt.mousePosition.y; - s_MouseDownValue = value; - s_MouseDragged = false; - evt.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - value = Mathf.Clamp(evt.mousePosition.y - s_MouseDownLocation + s_MouseDownValue, min, max - 1); - GUI.changed = true; - s_MouseDragged = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - if (!s_MouseDragged) - expanded = !expanded; - evt.Use(); - } - break; - case EventType.Repaint: - if (GUIUtility.hotControl == 0) - EditorGUIUtility.AddCursorRect(position, MouseCursor.SplitResizeUpDown); - if (GUIUtility.hotControl == id) - EditorGUIUtility.AddCursorRect(new Rect(position.x, position.y - 100, position.width, position.height + 200), MouseCursor.SplitResizeUpDown); - break; - } - return value; - } - } -} diff --git a/Editor/Mono/GUI/QuadTree.cs b/Editor/Mono/GUI/QuadTree.cs deleted file mode 100644 index de305472df..0000000000 --- a/Editor/Mono/GUI/QuadTree.cs +++ /dev/null @@ -1,487 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using UnityEngine; -using UnityEditor; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - internal class RectUtils - { - public static bool Contains(Rect a, Rect b) - { - if (a.xMin > b.xMin) - return false; - if (a.xMax < b.xMax) - return false; - - if (a.yMin > b.yMin) - return false; - if (a.yMax < b.yMax) - return false; - - return true; - } - - public static Rect Encompass(Rect a, Rect b) - { - Rect newRect = a; - newRect.xMin = Math.Min(a.xMin, b.xMin); - newRect.yMin = Math.Min(a.yMin, b.yMin); - newRect.xMax = Math.Max(a.xMax, b.xMax); - newRect.yMax = Math.Max(a.yMax, b.yMax); - return newRect; - } - - public static Rect Inflate(Rect a, float factor) - { - return Inflate(a, factor, factor); - } - - public static Rect Inflate(Rect a, float factorX, float factorY) - { - float newWidth = a.width * factorX; - float newHeight = a.height * factorY; - - float offsetWidth = (newWidth - a.width) / 2.0f; - float offsetHeight = (newHeight - a.height) / 2.0f; - - Rect r = a; - r.xMin -= offsetWidth; - r.yMin -= offsetHeight; - r.xMax += offsetWidth; - r.yMax += offsetHeight; - return r; - } - - public static bool Intersects(Rect r1, Rect r2) - { - if (!r1.Overlaps(r2) && !r2.Overlaps(r1)) - return false; - return true; - } - - public static bool Intersection(Rect r1, Rect r2, out Rect intersection) - { - if (!r1.Overlaps(r2) && !r2.Overlaps(r1)) - { - intersection = new Rect(0, 0, 0, 0); - return false; - } - - float left = Mathf.Max(r1.xMin, r2.xMin); - float top = Mathf.Max(r1.yMin, r2.yMin); - - float right = Mathf.Min(r1.xMax, r2.xMax); - float bottom = Mathf.Min(r1.yMax, r2.yMax); - - intersection = new Rect(left, top, right - left, bottom - top); - return true; - } - - public static bool IntersectsSegment(Rect rect, Vector2 p1, Vector2 p2) - { - float minX = Mathf.Min(p1.x, p2.x); - float maxX = Mathf.Max(p1.x, p2.x); - - if (maxX > rect.xMax) - { - maxX = rect.xMax; - } - - if (minX < rect.xMin) - { - minX = rect.xMin; - } - - if (minX > maxX) - { - return false; - } - - float minY = Mathf.Min(p1.y, p2.y); - float maxY = Mathf.Max(p1.y, p2.y); - - float dx = p2.x - p1.x; - - if (Mathf.Abs(dx) > 0.0000001f) - { - float a = (p2.y - p1.y) / dx; - float b = p1.y - a * p1.x; - minY = a * minX + b; - maxY = a * maxX + b; - } - - if (minY > maxY) - { - float tmp = maxY; - maxY = minY; - minY = tmp; - } - - if (maxY > rect.yMax) - { - maxY = rect.yMax; - } - - if (minY < rect.yMin) - { - minY = rect.yMin; - } - - if (minY > maxY) - { - return false; - } - - return true; - } - - public static Rect OffsetX(Rect r, float offsetX) - { - return Offset(r, offsetX, 0.0f); - } - - public static Rect Offset(Rect r, float offsetX, float offsetY) - { - Rect nr = r; - nr.xMin += offsetX; - nr.yMin += offsetY; - return nr; - } - - public static Rect Offset(Rect a, Rect b) - { - Rect nr = a; - nr.xMin += b.xMin; - nr.yMin += b.yMin; - return nr; - } - - public static Rect Move(Rect r, Vector2 delta) - { - Rect nr = r; - nr.xMin += delta.x; - nr.yMin += delta.y; - nr.xMax += delta.x; - nr.yMax += delta.y; - return nr; - } - } - - internal interface IBounds - { - Rect boundingRect { get; } - } - - internal class QuadTreeNode where T : IBounds - { - private Rect m_BoundingRect; - private static Color m_DebugFillColor = new Color(1.0f, 1.0f, 1.0f, 0.01f); - private static Color m_DebugWireColor = new Color(1.0f, 0.0f, 0.0f, 0.5f); - private static Color m_DebugBoxFillColor = new Color(1.0f, 0.0f, 0.0f, 0.01f); - private const float kSmallestAreaForQuadTreeNode = 10.0f; - - List m_Elements = new List(); - List> m_ChildrenNodes = new List>(4); - - public QuadTreeNode(Rect r) - { - m_BoundingRect = r; - } - - public bool IsEmpty { get { return (m_BoundingRect.width == 0 && m_BoundingRect.height == 0) || m_ChildrenNodes.Count == 0; } } - public Rect BoundingRect { get { return m_BoundingRect; } } - - public int CountItemsIncludingChildren() - { - return Count(true); - } - - public int CountLocalItems() - { - return Count(false); - } - - private int Count(bool recursive) - { - int count = m_Elements.Count; - - if (recursive) - { - foreach (QuadTreeNode node in m_ChildrenNodes) - count += node.Count(recursive); - } - return count; - } - - public List GetElementsIncludingChildren() - { - return Elements(true); - } - - public List GetElements() - { - return Elements(false); - } - - private List Elements(bool recursive) - { - List results = new List(); - - if (recursive) - { - foreach (QuadTreeNode node in m_ChildrenNodes) - results.AddRange(node.Elements(recursive)); - } - - results.AddRange(m_Elements); - return results; - } - - public List IntersectsWith(Rect queryArea) - { - List results = new List(); - - foreach (T item in m_Elements) - { - if (RectUtils.Intersects(item.boundingRect, queryArea)) - { - results.Add(item); - } - } - - foreach (QuadTreeNode node in m_ChildrenNodes) - { - if (node.IsEmpty) - continue; - - if (RectUtils.Intersects(node.BoundingRect, queryArea)) - { - // the node completely contains the queryArea - // recurse down and stop - results.AddRange(node.IntersectsWith(queryArea)); - break; - } - } - - return results; - } - - public List ContainedBy(Rect queryArea) - { - List results = new List(); - - foreach (T item in m_Elements) - { - if (RectUtils.Contains(item.boundingRect, queryArea) || queryArea.Overlaps(item.boundingRect)) - { - results.Add(item); - } - } - - foreach (QuadTreeNode node in m_ChildrenNodes) - { - if (node.IsEmpty) - continue; - - if (RectUtils.Contains(node.BoundingRect, queryArea)) - { - // the node completely contains the queryArea - // recurse down and stop - results.AddRange(node.ContainedBy(queryArea)); - break; - } - - if (RectUtils.Contains(queryArea, node.BoundingRect)) - { - // the queryArea completely contains this node - // just add everything under this node, recursively - results.AddRange(node.Elements(true)); - continue; - } - - if (node.BoundingRect.Overlaps(queryArea)) - { - // the node intersects - // recurse and continue iterating siblings - results.AddRange(node.ContainedBy(queryArea)); - } - } - - return results; - } - - public void Remove(T item) - { - m_Elements.Remove(item); - foreach (QuadTreeNode node in m_ChildrenNodes) - { - node.Remove(item); - } - } - - public void Insert(T item) - { - if (!RectUtils.Contains(m_BoundingRect, item.boundingRect)) - { - Rect intersection = new Rect(); - if (!RectUtils.Intersection(item.boundingRect, m_BoundingRect, out intersection)) - { - // Ignore elements completely outside the quad tree - return; - } - } - - if (m_ChildrenNodes.Count == 0) - Subdivide(); - - // insert into children nodes - foreach (QuadTreeNode node in m_ChildrenNodes) - { - if (RectUtils.Contains(node.BoundingRect, item.boundingRect)) - { - node.Insert(item); - return; - } - } - - // item is not completely contained in any of the children nodes - // insert here - this.m_Elements.Add(item); - } - - private void Subdivide() - { - if ((m_BoundingRect.height * m_BoundingRect.width) <= kSmallestAreaForQuadTreeNode) - return; - - float halfWidth = (m_BoundingRect.width / 2f); - float halfHeight = (m_BoundingRect.height / 2f); - - m_ChildrenNodes.Add(new QuadTreeNode(new Rect(m_BoundingRect.position.x, m_BoundingRect.position.y, halfWidth, halfHeight))); - m_ChildrenNodes.Add(new QuadTreeNode(new Rect(m_BoundingRect.xMin, m_BoundingRect.yMin + halfHeight, halfWidth, halfHeight))); - m_ChildrenNodes.Add(new QuadTreeNode(new Rect(m_BoundingRect.xMin + halfWidth, m_BoundingRect.yMin, halfWidth, halfHeight))); - m_ChildrenNodes.Add(new QuadTreeNode(new Rect(m_BoundingRect.xMin + halfWidth, m_BoundingRect.yMin + halfHeight, halfWidth, halfHeight))); - } - - public void DebugDraw(Vector2 offset) - { - HandleUtility.ApplyWireMaterial(); - Rect screenSpaceRect = m_BoundingRect; - screenSpaceRect.x += offset.x; - screenSpaceRect.y += offset.y; - - Handles.DrawSolidRectangleWithOutline(screenSpaceRect, m_DebugFillColor, m_DebugWireColor); - foreach (QuadTreeNode node in m_ChildrenNodes) - { - node.DebugDraw(offset); - } - - foreach (IBounds i in Elements(false)) - { - Rect o = i.boundingRect; - o.x += offset.x; - o.y += offset.y; - Handles.DrawSolidRectangleWithOutline(o, m_DebugBoxFillColor, Color.yellow); - } - } - }; - - internal class QuadTree where T : IBounds - { - private QuadTreeNode m_Root = null; - private Rect m_Rectangle; - private Vector2 m_ScreenSpaceOffset = Vector2.zero; - - public QuadTree() - { - Clear(); - } - - public Vector2 screenSpaceOffset - { - get { return m_ScreenSpaceOffset; } - set - { - m_ScreenSpaceOffset = value; - } - } - - public Rect rectangle - { - get { return m_Rectangle; } - } - - public void Clear() - { - SetSize(new Rect(0, 0, 1, 1)); - } - - public void SetSize(Rect rectangle) - { - m_Root = null; - m_Rectangle = rectangle; - m_Root = new QuadTreeNode(m_Rectangle); - } - - public int Count { get { return m_Root.CountItemsIncludingChildren(); } } - - public void Insert(List items) - { - foreach (T i in items) - { - Insert(i); - } - } - - public void Insert(T item) - { - m_Root.Insert(item); - } - - public void Remove(T item) - { - m_Root.Remove(item); - } - - public List GetItemsAtPosition(Vector2 pos) - { - if (m_Root.BoundingRect.Contains(pos)) - { - Rect r = new Rect(pos, Vector2.one); - return IntersectsWith(r); - } - - return new List(); - } - - public List IntersectsWith(Rect area) - { - return m_Root.IntersectsWith(area); - } - - public List ContainedBy(Rect area) - { - area.x -= m_ScreenSpaceOffset.x; - area.y -= m_ScreenSpaceOffset.y; - return m_Root.ContainedBy(area); - } - - public List Elements() - { - return m_Root.GetElementsIncludingChildren(); - } - - public void DebugDraw() - { - m_Root.DebugDraw(m_ScreenSpaceOffset); - } - } -} diff --git a/Editor/Mono/GUI/RenameOverlay.cs b/Editor/Mono/GUI/RenameOverlay.cs deleted file mode 100644 index b091669f2e..0000000000 --- a/Editor/Mono/GUI/RenameOverlay.cs +++ /dev/null @@ -1,415 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditorInternal; -using UnityEngine.Assertions; -using UnityEngine.Events; - -namespace UnityEditor -{ - // Usage: - // BeginRename (string name, int userData, float delay) - Starts a rename - // EndRename (bool acceptChanges) - Ends rename and caches state (use property interface for client reaction) - // IsRenaming() - Is renaming active (we might still not show anything due to 'delay' parameter in BeginRename) - // Clear() - Clears rename state - // IMPORTANT: - // 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) - // 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 - - [System.Serializable] - internal class RenameOverlay - { - [SerializeField] - bool m_UserAcceptedRename; - [SerializeField] - string m_Name; - [SerializeField] - string m_OriginalName; - [SerializeField] - Rect m_EditFieldRect; - [SerializeField] - int m_UserData; - [SerializeField] - bool m_IsWaitingForDelay; - [SerializeField] - bool m_IsRenaming = false; - [SerializeField] - EventType m_OriginalEventType = EventType.Ignore; - [SerializeField] - bool m_IsRenamingFilename = false; - [SerializeField] - GUIView m_ClientGUIView; - - [System.NonSerialized] - Rect m_LastScreenPosition; - [System.NonSerialized] - bool m_UndoRedoWasPerformed; - - [System.NonSerialized] - DelayedCallback m_DelayedCallback; - - string k_RenameOverlayFocusName = "RenameOverlayField"; - - // property interface - public string name { get {return m_Name; }} - public string originalName { get {return m_OriginalName; }} - public bool userAcceptedRename { get {return m_UserAcceptedRename; }} - public int userData { get {return m_UserData; }} - public bool isWaitingForDelay { get {return m_IsWaitingForDelay; }} - public Rect editFieldRect { get {return m_EditFieldRect; } set {m_EditFieldRect = value; }} - public bool isRenamingFilename {get {return m_IsRenamingFilename; } set {m_IsRenamingFilename = value; }} - - private static GUIStyle s_DefaultTextFieldStyle = null; - private static int s_TextFieldHash = "RenameFieldTextField".GetHashCode(); - private int m_TextFieldControlID; - - // Returns true if started renaming - public bool BeginRename(string name, int userData, float delay) - { - if (m_IsRenaming) - { - return false; - } - - m_Name = name; - m_OriginalName = name; - m_UserData = userData; - m_UserAcceptedRename = false; - m_IsWaitingForDelay = delay > 0f; - m_IsRenaming = true; - m_EditFieldRect = new Rect(0, 0, 0, 0); - m_ClientGUIView = GUIView.current; - - if (delay > 0f) - m_DelayedCallback = new DelayedCallback(BeginRenameInternalCallback, delay); - else - BeginRenameInternalCallback(); - return true; - } - - void BeginRenameInternalCallback() - { - EditorGUI.s_RecycledEditor.text = m_Name; - EditorGUI.s_RecycledEditor.SelectAll(); - RepaintClientView(); - - m_IsWaitingForDelay = false; - - Undo.undoRedoPerformed -= UndoRedoWasPerformed; - Undo.undoRedoPerformed += UndoRedoWasPerformed; - } - - public void EndRename(bool acceptChanges) - { - EditorGUIUtility.editingTextField = false; - if (!m_IsRenaming) - return; - - Undo.undoRedoPerformed -= UndoRedoWasPerformed; - if (m_DelayedCallback != null) - m_DelayedCallback.Clear(); - - RemoveMessage(); - - if (isRenamingFilename) - m_Name = InternalEditorUtility.RemoveInvalidCharsFromFileName(m_Name, true); - - m_IsRenaming = false; - m_IsWaitingForDelay = false; - m_UserAcceptedRename = acceptChanges; - - // For issuing event for client to react on end of rename - RepaintClientView(); - } - - private void RepaintClientView() - { - if (m_ClientGUIView != null) - m_ClientGUIView.Repaint(); - } - - public void Clear() - { - m_IsRenaming = false; - m_UserAcceptedRename = false; - m_Name = ""; - m_OriginalName = ""; - m_EditFieldRect = new Rect(); - m_UserData = 0; - m_IsWaitingForDelay = false; - m_OriginalEventType = EventType.Ignore; - Undo.undoRedoPerformed -= UndoRedoWasPerformed; - - // m_IsRenamingFilename = false; // Only clear temp data used for renaming not state that we want to persist - } - - void UndoRedoWasPerformed() - { - // If undo/redo was performed then close the rename overlay as it does not support undo/redo - // We need to delay the EndRename until next OnGUI as clients poll the state of the rename overlay state there - m_UndoRedoWasPerformed = true; - } - - public bool HasKeyboardFocus() - { - return (GUI.GetNameOfFocusedControl() == k_RenameOverlayFocusName); - } - - public bool IsRenaming() - { - return m_IsRenaming; - } - - // Should be called as early as possible in an EditorWindow using this RenameOverlay - // Returns: false if rename was ended due to input while waiting for delay - public bool OnEvent() - { - if (!m_IsRenaming) - return true; - - if (!m_IsWaitingForDelay) - { - // We get control ID separate from OnGUI because we want to call OnGUI early and late: handle input first but render on top - GUIUtility.GetControlID(84895748, FocusType.Passive); - GUI.SetNextControlName(k_RenameOverlayFocusName); - EditorGUI.FocusTextInControl(k_RenameOverlayFocusName); - m_TextFieldControlID = GUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, m_EditFieldRect); - } - - // Workaround for Event not having the original eventType stored - m_OriginalEventType = Event.current.type; - - // Clear state if necessary while waiting for rename (0.5 second) - if (m_IsWaitingForDelay && (m_OriginalEventType == EventType.MouseDown || m_OriginalEventType == EventType.KeyDown)) - { - EndRename(false); - return false; - } - - return true; - } - - public bool OnGUI() - { - return OnGUI(null); - } - - // Should be called when IsRenaming () returns true to draw the overlay and handle events. - // Returns true if renaming is still active, false if not (user canceled, accepted, clicked outside edit rect etc). - // If textFieldStyle == null then a default style is used. - public bool OnGUI(GUIStyle textFieldStyle) - { - if (m_IsWaitingForDelay) - { - // Delayed start - return true; - } - - // Ended from outside - if (!m_IsRenaming) - { - return false; - } - - if (m_UndoRedoWasPerformed) - { - m_UndoRedoWasPerformed = false; - EndRename(false); - return false; - } - - if (m_EditFieldRect.width <= 0 || m_EditFieldRect.height <= 0 || m_TextFieldControlID == 0) - { - // 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 - // we ensure to issue repaints until these states are valid - HandleUtility.Repaint(); - return true; - } - - Event evt = Event.current; - if (evt.type == EventType.KeyDown) - { - if (evt.keyCode == KeyCode.Escape) - { - evt.Use(); - EndRename(false); - return false; - } - if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter) - { - evt.Use(); - EndRename(true); - return false; - } - } - - // Detect if we clicked outside the text field (must be before text field below which steals keyboard control) - if (m_OriginalEventType == EventType.MouseDown && !m_EditFieldRect.Contains(Event.current.mousePosition)) - { - EndRename(true); - return false; - } - - m_Name = DoTextField(m_Name, textFieldStyle); - - if (evt.type == EventType.ScrollWheel) - evt.Use(); - - return true; - } - - string DoTextField(string text, GUIStyle textFieldStyle) - { - if (m_TextFieldControlID == 0) - Debug.LogError("RenameOverlay: Ensure to call OnEvent() as early as possible in the OnGUI of the current EditorWindow!"); - - if (s_DefaultTextFieldStyle == null) - s_DefaultTextFieldStyle = "PR TextField"; - - if (isRenamingFilename) - EatInvalidChars(); - - GUI.changed = false; - bool dummy; - - // Ensure the rename textfield has keyboardcontrol (Could have been stolen previously in this OnGUI) - if (GUIUtility.keyboardControl != m_TextFieldControlID) - GUIUtility.keyboardControl = m_TextFieldControlID; - - GUIStyle style = textFieldStyle ?? s_DefaultTextFieldStyle; - Rect rect = EditorGUI.IndentedRect(m_EditFieldRect); - rect.xMin -= style.padding.left; // Adjust rect so rename text matches client text - - return EditorGUI.DoTextField(EditorGUI.s_RecycledEditor, m_TextFieldControlID, rect, text, style, null, out dummy, false, false, false); - } - - void EatInvalidChars() - { - if (isRenamingFilename) - { - Event evt = Event.current; - if (GUIUtility.keyboardControl == m_TextFieldControlID && evt.GetTypeForControl(m_TextFieldControlID) == EventType.KeyDown) - { - string errorMsg = ""; - - string invalidChars = EditorUtility.GetInvalidFilenameChars(); - if (invalidChars.IndexOf(evt.character) > -1) - errorMsg = "A file name can't contain any of the following characters:\t" + invalidChars; - - if (errorMsg != "") - { - evt.Use(); // Eat character: prevents the textfield from inputting this evt.character - ShowMessage(errorMsg); - } - else - { - RemoveMessage(); - } - } - - // Remove tooltip if screenpos of overlay has changed (handles the case where the main window is being moved or docked window - // is resized) - if (evt.type == EventType.Repaint) - { - Rect screenPos = GetScreenRect(); - if (!Mathf.Approximately(m_LastScreenPosition.x, screenPos.x) || !Mathf.Approximately(m_LastScreenPosition.y, screenPos.y)) - { - RemoveMessage(); - } - m_LastScreenPosition = screenPos; - } - } - } - - Rect GetScreenRect() - { - return GUIUtility.GUIToScreenRect(m_EditFieldRect); - } - - void ShowMessage(string msg) - { - TooltipView.Show(msg, GetScreenRect()); - } - - void RemoveMessage() - { - TooltipView.Close(); - } - } - - [Serializable] - internal class SerializableDelayedCallback : ScriptableObject - { - [SerializeField] - private long m_CallbackTicks; - - [SerializeField] - private UnityEvent m_Callback; - - protected SerializableDelayedCallback() - { - m_Callback = new UnityEvent(); - EditorApplication.update += Update; - } - - public static SerializableDelayedCallback SubscribeCallback(UnityAction action, TimeSpan delayUntilCallback) - { - var serializableDelayedCallback = ScriptableObject.CreateInstance(); - serializableDelayedCallback.m_CallbackTicks = DateTime.UtcNow.Add(delayUntilCallback).Ticks; - serializableDelayedCallback.m_Callback.AddPersistentListener(action, UnityEventCallState.EditorAndRuntime); - return serializableDelayedCallback; - } - - public void Cancel() - { - EditorApplication.update -= Update; - } - - private void Update() - { - var utcNowTicks = DateTime.UtcNow.Ticks; - if (utcNowTicks >= m_CallbackTicks) - { - EditorApplication.update -= Update; - m_Callback.Invoke(); - } - } - } - - internal class DelayedCallback - { - private System.Action m_Callback; - private double m_CallbackTime; - - public DelayedCallback(System.Action function, double timeFromNow) - { - Assert.IsTrue(function != null); - - m_Callback = function; - m_CallbackTime = EditorApplication.timeSinceStartup + timeFromNow; - EditorApplication.update += Update; - } - - public void Clear() - { - EditorApplication.update -= Update; - m_CallbackTime = 0.0; - m_Callback = null; - } - - void Update() - { - if (EditorApplication.timeSinceStartup > m_CallbackTime) - { - // Clear state before firing callback to ensure reset (callback could call ExitGUI) - var callback = m_Callback; - Clear(); - - callback(); - } - } - } -} // end namespace UnityEditor diff --git a/Editor/Mono/GUI/ReorderableList.cs b/Editor/Mono/GUI/ReorderableList.cs deleted file mode 100644 index 669cdcf6fd..0000000000 --- a/Editor/Mono/GUI/ReorderableList.cs +++ /dev/null @@ -1,855 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using System.Collections.Generic; -using Object = UnityEngine.Object; - - -namespace UnityEditorInternal -{ - //TODO: better handling for serializedObjects with mixed values - //TODO: make it not rely on GUILayout at all, so its safe to use under PropertyDrawers. - public class ReorderableList - { - public delegate void HeaderCallbackDelegate(Rect rect); - public delegate void FooterCallbackDelegate(Rect rect); - public delegate void ElementCallbackDelegate(Rect rect, int index, bool isActive, bool isFocused); - public delegate float ElementHeightCallbackDelegate(int index); - public delegate void DrawNoneElementCallback(Rect rect); - - public delegate void ReorderCallbackDelegateWithDetails(ReorderableList list, int oldIndex, int newIndex); - public delegate void ReorderCallbackDelegate(ReorderableList list); - public delegate void SelectCallbackDelegate(ReorderableList list); - public delegate void AddCallbackDelegate(ReorderableList list); - public delegate void AddDropdownCallbackDelegate(Rect buttonRect, ReorderableList list); - public delegate void RemoveCallbackDelegate(ReorderableList list); - public delegate void ChangedCallbackDelegate(ReorderableList list); - public delegate bool CanRemoveCallbackDelegate(ReorderableList list); - public delegate bool CanAddCallbackDelegate(ReorderableList list); - - - // draw callbacks - public HeaderCallbackDelegate drawHeaderCallback; - public FooterCallbackDelegate drawFooterCallback = null; - public ElementCallbackDelegate drawElementCallback; - public ElementCallbackDelegate drawElementBackgroundCallback; - public DrawNoneElementCallback drawNoneElementCallback = null; - - // layout callbacks - // if supplying own element heights, try to cache the results as this may be called frequently - public ElementHeightCallbackDelegate elementHeightCallback; - - // interaction callbacks - public ReorderCallbackDelegateWithDetails onReorderCallbackWithDetails; - public ReorderCallbackDelegate onReorderCallback; - public SelectCallbackDelegate onSelectCallback; - public AddCallbackDelegate onAddCallback; - public AddDropdownCallbackDelegate onAddDropdownCallback; - public RemoveCallbackDelegate onRemoveCallback; - public SelectCallbackDelegate onMouseUpCallback; - public CanRemoveCallbackDelegate onCanRemoveCallback; - public CanAddCallbackDelegate onCanAddCallback; - public ChangedCallbackDelegate onChangedCallback; - - private int m_ActiveElement = -1; - private float m_DragOffset = 0; - private GUISlideGroup m_SlideGroup; - - private SerializedObject m_SerializedObject; - private SerializedProperty m_Elements; - private IList m_ElementList; - private bool m_Draggable; - private float m_DraggedY; - private bool m_Dragging; - private List m_NonDragTargetIndices; - - private bool m_DisplayHeader; - public bool displayAdd; - public bool displayRemove; - - private int id = -1; - - // class for default rendering and behavior of reorderable list - stores styles and is statically available as s_Defaults - public class Defaults - { - public GUIContent iconToolbarPlus = EditorGUIUtility.TrIconContent("Toolbar Plus", "Add to list"); - public GUIContent iconToolbarPlusMore = EditorGUIUtility.TrIconContent("Toolbar Plus More", "Choose to add to list"); - public GUIContent iconToolbarMinus = EditorGUIUtility.TrIconContent("Toolbar Minus", "Remove selection from list"); - public readonly GUIStyle draggingHandle = "RL DragHandle"; - public readonly GUIStyle headerBackground = "RL Header"; - public readonly GUIStyle footerBackground = "RL Footer"; - public readonly GUIStyle boxBackground = "RL Background"; - public readonly GUIStyle preButton = "RL FooterButton"; - public GUIStyle elementBackground = new GUIStyle("RL Element"); - public const int padding = 6; - public const int dragHandleWidth = 20; - - // draw the default footer - public void DrawFooter(Rect rect, ReorderableList list) - { - float rightEdge = rect.xMax; - float leftEdge = rightEdge - 8f; - if (list.displayAdd) - leftEdge -= 25; - if (list.displayRemove) - leftEdge -= 25; - rect = new Rect(leftEdge, rect.y, rightEdge - leftEdge, rect.height); - Rect addRect = new Rect(leftEdge + 4, rect.y - 3, 25, 13); - Rect removeRect = new Rect(rightEdge - 29, rect.y - 3, 25, 13); - if (Event.current.type == EventType.Repaint) - { - footerBackground.Draw(rect, false, false, false, false); - } - if (list.displayAdd) - { - using (new EditorGUI.DisabledScope( - list.onCanAddCallback != null && !list.onCanAddCallback(list))) - { - if (GUI.Button(addRect, list.onAddDropdownCallback != null ? iconToolbarPlusMore : iconToolbarPlus, preButton)) - { - if (list.onAddDropdownCallback != null) - list.onAddDropdownCallback(addRect, list); - else if (list.onAddCallback != null) - list.onAddCallback(list); - else - DoAddButton(list); - - if (list.onChangedCallback != null) - list.onChangedCallback(list); - } - } - } - if (list.displayRemove) - { - using (new EditorGUI.DisabledScope( - list.index < 0 || list.index >= list.count || - (list.onCanRemoveCallback != null && !list.onCanRemoveCallback(list)))) - { - if (GUI.Button(removeRect, iconToolbarMinus, preButton)) - { - if (list.onRemoveCallback == null) - DoRemoveButton(list); - else - list.onRemoveCallback(list); - - if (list.onChangedCallback != null) - list.onChangedCallback(list); - } - } - } - } - - // default add button behavior - public void DoAddButton(ReorderableList list) - { - if (list.serializedProperty != null) - { - list.serializedProperty.arraySize += 1; - list.index = list.serializedProperty.arraySize - 1; - } - else - { - // this is ugly but there are a lot of cases like null types and default constructors - Type elementType = list.list.GetType().GetElementType(); - if (elementType == typeof(string)) - list.index = list.list.Add(""); - else if (elementType != null && elementType.GetConstructor(Type.EmptyTypes) == null) - Debug.LogError("Cannot add element. Type " + elementType.ToString() + " has no default constructor. Implement a default constructor or implement your own add behaviour."); - else if (list.list.GetType().GetGenericArguments()[0] != null) - list.index = list.list.Add(Activator.CreateInstance(list.list.GetType().GetGenericArguments()[0])); - else if (elementType != null) - list.index = list.list.Add(Activator.CreateInstance(elementType)); - else - Debug.LogError("Cannot add element of type Null."); - } - } - - // default remove button behavior - public void DoRemoveButton(ReorderableList list) - { - if (list.serializedProperty != null) - { - list.serializedProperty.DeleteArrayElementAtIndex(list.index); - if (list.index >= list.serializedProperty.arraySize - 1) - list.index = list.serializedProperty.arraySize - 1; - } - else - { - list.list.RemoveAt(list.index); - if (list.index >= list.list.Count - 1) - list.index = list.list.Count - 1; - } - } - - // draw the default header background - public void DrawHeaderBackground(Rect headerRect) - { - if (Event.current.type == EventType.Repaint) - headerBackground.Draw(headerRect, false, false, false, false); - } - - // draw the default header - public void DrawHeader(Rect headerRect, SerializedObject serializedObject, SerializedProperty element, IList elementList) - { - EditorGUI.LabelField(headerRect, EditorGUIUtility.TempContent((element != null) ? "Serialized Property" : "IList")); - } - - // draw the default element background - public void DrawElementBackground(Rect rect, int index, bool selected, bool focused, bool draggable) - { - if (Event.current.type == EventType.Repaint) - { - elementBackground.Draw(rect, false, selected, selected, focused); - } - } - - public void DrawElementDraggingHandle(Rect rect, int index, bool selected, bool focused, bool draggable) - { - if (Event.current.type == EventType.Repaint) - { - if (draggable) - draggingHandle.Draw(new Rect(rect.x + 5, rect.y + 7, 10, rect.height - (rect.height - 7)), false, false, false, false); - } - } - - // draw the default element - public void DrawElement(Rect rect, SerializedProperty element, System.Object listItem, bool selected, bool focused, bool draggable) - { - EditorGUI.LabelField(rect, EditorGUIUtility.TempContent((element != null) ? element.displayName : listItem.ToString())); - } - - // draw the default element - public void DrawNoneElement(Rect rect, bool draggable) - { - EditorGUI.LabelField(rect, EditorGUIUtility.TempContent("List is Empty")); - } - } - static Defaults s_Defaults; - public static Defaults defaultBehaviours - { - get - { - return s_Defaults; - } - } - - // constructors - public ReorderableList(IList elements, Type elementType) - { - InitList(null, null, elements, true, true, true, true); - } - - public ReorderableList(IList elements, Type elementType, bool draggable, bool displayHeader, bool displayAddButton, bool displayRemoveButton) - { - InitList(null, null, elements, draggable, displayHeader, displayAddButton, displayRemoveButton); - } - - public ReorderableList(SerializedObject serializedObject, SerializedProperty elements) - { - InitList(serializedObject, elements, null, true, true, true, true); - } - - public ReorderableList(SerializedObject serializedObject, SerializedProperty elements, bool draggable, bool displayHeader, bool displayAddButton, bool displayRemoveButton) - { - InitList(serializedObject, elements, null, draggable, displayHeader, displayAddButton, displayRemoveButton); - } - - private void InitList(SerializedObject serializedObject, SerializedProperty elements, IList elementList, bool draggable, bool displayHeader, bool displayAddButton, bool displayRemoveButton) - { - id = GUIUtility.GetPermanentControlID(); - m_SerializedObject = serializedObject; - m_Elements = elements; - m_ElementList = elementList; - m_Draggable = draggable; - m_Dragging = false; - m_SlideGroup = new GUISlideGroup(); - displayAdd = displayAddButton; - m_DisplayHeader = displayHeader; - displayRemove = displayRemoveButton; - if (m_Elements != null && m_Elements.editable == false) - m_Draggable = false; - if (m_Elements != null && m_Elements.isArray == false) - Debug.LogError("Input elements should be an Array SerializedProperty"); - } - - public SerializedProperty serializedProperty - { - get { return m_Elements; } - set { m_Elements = value; } - } - - public IList list - { - get { return m_ElementList; } - set { m_ElementList = value; } - } - - - // active element index accessor - public int index - { - get { return m_ActiveElement; } - set { m_ActiveElement = value; } - } - - // individual element height accessor - public float elementHeight = 21; - // header height accessor - public float headerHeight = 18; - // footer height accessor - public float footerHeight = 13; - // show default background - public bool showDefaultBackground = true; - - // draggable accessor - public bool draggable - { - get { return m_Draggable; } - set { m_Draggable = value; } - } - - - private Rect GetContentRect(Rect rect) - { - Rect r = rect; - - if (draggable) - r.xMin += Defaults.dragHandleWidth; - else - r.xMin += Defaults.padding; - r.xMax -= Defaults.padding; - return r; - } - - private float GetElementYOffset(int index) - { - return GetElementYOffset(index, -1); - } - - private float GetElementYOffset(int index, int skipIndex) - { - if (elementHeightCallback == null) - return index * elementHeight; - - float offset = 0; - for (int i = 0; i < index; i++) - { - if (i != skipIndex) - offset += elementHeightCallback(i); - } - return offset; - } - - private float GetElementHeight(int index) - { - if (elementHeightCallback == null) - return elementHeight; - - return elementHeightCallback(index); - } - - private Rect GetRowRect(int index, Rect listRect) - { - return new Rect(listRect.x, listRect.y + GetElementYOffset(index), listRect.width, GetElementHeight(index)); - } - - public int count - { - get - { - if (m_Elements != null) - { - if (!m_Elements.hasMultipleDifferentValues) - return m_Elements.arraySize; - - int smallerArraySize = m_Elements.arraySize; - foreach (Object targetObject in m_Elements.serializedObject.targetObjects) - { - SerializedObject serializedObject = new SerializedObject(targetObject); - SerializedProperty property = serializedObject.FindProperty(m_Elements.propertyPath); - smallerArraySize = Math.Min(property.arraySize, smallerArraySize); - } - return smallerArraySize; - } - return m_ElementList.Count; - } - } - - public void DoLayoutList() //TODO: better API? - { - if (s_Defaults == null) - s_Defaults = new Defaults(); - - // do the custom or default header GUI - Rect headerRect = GUILayoutUtility.GetRect(0, headerHeight, GUILayout.ExpandWidth(true)); - //Elements area - Rect listRect = GUILayoutUtility.GetRect(10, GetListElementHeight(), GUILayout.ExpandWidth(true)); - // do the footer GUI - Rect footerRect = GUILayoutUtility.GetRect(4, footerHeight, GUILayout.ExpandWidth(true)); - - // do the parts of our list - DoListHeader(headerRect); - DoListElements(listRect); - DoListFooter(footerRect); - } - - public void DoList(Rect rect) //TODO: better API? - { - if (s_Defaults == null) - s_Defaults = new Defaults(); - - // do the custom or default header GUI - Rect headerRect = new Rect(rect.x, rect.y, rect.width, headerHeight); - //Elements area - Rect listRect = new Rect(rect.x, headerRect.y + headerRect.height, rect.width, GetListElementHeight()); - // do the footer GUI - Rect footerRect = new Rect(rect.x, listRect.y + listRect.height, rect.width, footerHeight); - - // do the parts of our list - DoListHeader(headerRect); - DoListElements(listRect); - DoListFooter(footerRect); - } - - public float GetHeight() - { - float totalheight = 0f; - totalheight += GetListElementHeight(); - totalheight += headerHeight; - totalheight += footerHeight; - return totalheight; - } - - private float GetListElementHeight() - { - const float listElementPadding = 7; - - int arraySize = count; - if (arraySize == 0) - { - return elementHeight + listElementPadding; - } - - if (elementHeightCallback != null) - { - return GetElementYOffset(arraySize - 1) + GetElementHeight(arraySize - 1) + listElementPadding; - } - - return (elementHeight * arraySize) + listElementPadding; - } - - private void DoListElements(Rect listRect) - { - // How many elements? If none, make space for showing default line that shows no elements are present - int arraySize = count; - - // draw the background in repaint - if (showDefaultBackground && Event.current.type == EventType.Repaint) - s_Defaults.boxBackground.Draw(listRect, false, false, false, false); - - // resize to the area that we want to draw our elements into - listRect.yMin += 2; listRect.yMax -= 5; - - - // create the rect for individual elements in the list - Rect elementRect = listRect; - elementRect.height = elementHeight; - - // the content rect is what we will actually draw into -- it doesn't include the drag handle or padding - Rect elementContentRect = elementRect; - - - if (((m_Elements != null && m_Elements.isArray == true) || m_ElementList != null) && arraySize > 0) - { - // If there are elements, we need to draw them -- we will do this differently depending on if we are dragging or not - if (IsDragging() && Event.current.type == EventType.Repaint) - { - // we are dragging, so we need to build the new list of target indices - int targetIndex = CalculateRowIndex(); - m_NonDragTargetIndices.Clear(); - for (int i = 0; i < arraySize; i++) - { - if (i != m_ActiveElement) - m_NonDragTargetIndices.Add(i); - } - m_NonDragTargetIndices.Insert(targetIndex, -1); - - // now draw each element in the list (excluding the active element) - bool targetSeen = false; - for (int i = 0; i < m_NonDragTargetIndices.Count; i++) - { - if (m_NonDragTargetIndices[i] != -1) - { - elementRect.height = GetElementHeight(i); - // update the position of the rect (based on element position and accounting for sliding) - if (elementHeightCallback == null) - { - elementRect.y = listRect.y + GetElementYOffset(i, m_ActiveElement); - } - else - { - elementRect.y = listRect.y + GetElementYOffset(m_NonDragTargetIndices[i], m_ActiveElement); - if (targetSeen) - { - elementRect.y += elementHeightCallback(m_ActiveElement); - } - } - elementRect = m_SlideGroup.GetRect(m_NonDragTargetIndices[i], elementRect); - - // actually draw the element - if (drawElementBackgroundCallback == null) - s_Defaults.DrawElementBackground(elementRect, i, false, false, m_Draggable); - else - drawElementBackgroundCallback(elementRect, i, false, false); - - s_Defaults.DrawElementDraggingHandle(elementRect, i, false, false, m_Draggable); - - elementContentRect = GetContentRect(elementRect); - if (drawElementCallback == null) - { - if (m_Elements != null) - s_Defaults.DrawElement(elementContentRect, m_Elements.GetArrayElementAtIndex(m_NonDragTargetIndices[i]), null, false, false, m_Draggable); - else - s_Defaults.DrawElement(elementContentRect, null, m_ElementList[m_NonDragTargetIndices[i]], false, false, m_Draggable); - } - else - { - drawElementCallback(elementContentRect, m_NonDragTargetIndices[i], false, false); - } - } - else - { - targetSeen = true; - } - } - - // finally get the position of the active element - elementRect.y = m_DraggedY - m_DragOffset + listRect.y; - - // actually draw the element - if (drawElementBackgroundCallback == null) - s_Defaults.DrawElementBackground(elementRect, m_ActiveElement, true, true, m_Draggable); - else - drawElementBackgroundCallback(elementRect, m_ActiveElement, true, true); - - s_Defaults.DrawElementDraggingHandle(elementRect, m_ActiveElement, true, true, m_Draggable); - - - elementContentRect = GetContentRect(elementRect); - - // draw the active element - if (drawElementCallback == null) - { - if (m_Elements != null) - s_Defaults.DrawElement(elementContentRect, m_Elements.GetArrayElementAtIndex(m_ActiveElement), null, true, true, m_Draggable); - else - s_Defaults.DrawElement(elementContentRect, null, m_ElementList[m_ActiveElement], true, true, m_Draggable); - } - else - { - drawElementCallback(elementContentRect, m_ActiveElement, true, true); - } - } - else - { - // if we aren't dragging, we just draw all of the elements in order - for (int i = 0; i < arraySize; i++) - { - bool activeElement = (i == m_ActiveElement); - bool focusedElement = (i == m_ActiveElement && HasKeyboardControl()); - - // update the position of the element - elementRect.height = GetElementHeight(i); - elementRect.y = listRect.y + GetElementYOffset(i); - - // draw the background - if (drawElementBackgroundCallback == null) - s_Defaults.DrawElementBackground(elementRect, i, activeElement, focusedElement, m_Draggable); - else - drawElementBackgroundCallback(elementRect, i, activeElement, focusedElement); - s_Defaults.DrawElementDraggingHandle(elementRect, i, activeElement, focusedElement, m_Draggable); - - - elementContentRect = GetContentRect(elementRect); - - // do the callback for the element - if (drawElementCallback == null) - { - if (m_Elements != null) - s_Defaults.DrawElement(elementContentRect, m_Elements.GetArrayElementAtIndex(i), null, activeElement, focusedElement, m_Draggable); - else - s_Defaults.DrawElement(elementContentRect, null, m_ElementList[i], activeElement, focusedElement, m_Draggable); - } - else - { - drawElementCallback(elementContentRect, i, activeElement, focusedElement); - } - } - } - - // handle the interaction - DoDraggingAndSelection(listRect); - } - else - { - // there was no content, so we will draw an empty element - elementRect.y = listRect.y; - // draw the background - if (drawElementBackgroundCallback == null) - s_Defaults.DrawElementBackground(elementRect, -1, false, false, false); - else - drawElementBackgroundCallback(elementRect, -1, false, false); - s_Defaults.DrawElementDraggingHandle(elementRect, -1, false, false, false); - - elementContentRect = elementRect; - elementContentRect.xMin += Defaults.padding; - elementContentRect.xMax -= Defaults.padding; - if (drawNoneElementCallback == null) - s_Defaults.DrawNoneElement(elementContentRect, m_Draggable); - else - drawNoneElementCallback(elementContentRect); - } - } - - private void DoListHeader(Rect headerRect) - { - // draw the background on repaint - if (showDefaultBackground && Event.current.type == EventType.Repaint) - s_Defaults.DrawHeaderBackground(headerRect); - - // apply the padding to get the internal rect - headerRect.xMin += Defaults.padding; - headerRect.xMax -= Defaults.padding; - headerRect.height -= 2; - headerRect.y += 1; - - // perform the default or overridden callback - if (drawHeaderCallback != null) - drawHeaderCallback(headerRect); - else if (m_DisplayHeader) - s_Defaults.DrawHeader(headerRect, m_SerializedObject, m_Elements, m_ElementList); - } - - private void DoListFooter(Rect footerRect) - { - // perform callback or the default footer - if (drawFooterCallback != null) - drawFooterCallback(footerRect); - else if (displayAdd || displayRemove) - s_Defaults.DrawFooter(footerRect, this); // draw the footer if the add or remove buttons are required - } - - private void DoDraggingAndSelection(Rect listRect) - { - Event evt = Event.current; - int oldIndex = m_ActiveElement; - bool clicked = false; - switch (evt.GetTypeForControl(id)) - { - case EventType.KeyDown: - if (GUIUtility.keyboardControl != id) - return; - // if we have keyboard focus, arrow through the list - if (evt.keyCode == KeyCode.DownArrow) - { - m_ActiveElement += 1; - evt.Use(); - } - if (evt.keyCode == KeyCode.UpArrow) - { - m_ActiveElement -= 1; - evt.Use(); - } - if (evt.keyCode == KeyCode.Escape && GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - m_Dragging = false; - evt.Use(); - } - // don't allow arrowing through the ends of the list - m_ActiveElement = Mathf.Clamp(m_ActiveElement, 0, (m_Elements != null) ? m_Elements.arraySize - 1 : m_ElementList.Count - 1); - break; - - case EventType.MouseDown: - if (!listRect.Contains(Event.current.mousePosition) || Event.current.button != 0) - break; - // clicking on the list should end editing any existing edits - EditorGUI.EndEditingActiveTextField(); - // pick the active element based on click position - m_ActiveElement = GetRowIndex(Event.current.mousePosition.y - listRect.y); - - if (m_Draggable) - { - // if we can drag, set the hot control and start dragging (storing the offset) - m_DragOffset = (Event.current.mousePosition.y - listRect.y) - GetElementYOffset(m_ActiveElement); - UpdateDraggedY(listRect); - GUIUtility.hotControl = id; - m_SlideGroup.Reset(); - m_NonDragTargetIndices = new List(); - } - GrabKeyboardFocus(); - evt.Use(); - clicked = true; - break; - - case EventType.MouseDrag: - if (!m_Draggable || GUIUtility.hotControl != id) - break; - - // Set m_Dragging state on first MouseDrag event after we got hotcontrol (to prevent animating elements when deleting elements by context menu) - m_Dragging = true; - - // if we are dragging, update the position - UpdateDraggedY(listRect); - evt.Use(); - break; - - case EventType.MouseUp: - if (!m_Draggable) - { - // if mouse up was on the same index as mouse down we fire a mouse up callback (useful if for beginning renaming on mouseup) - if (onMouseUpCallback != null && IsMouseInsideActiveElement(listRect)) - { - // set the keyboard control - onMouseUpCallback(this); - } - break; - } - - // hotcontrol is only set when list is draggable - if (GUIUtility.hotControl != id) - break; - evt.Use(); - m_Dragging = false; - - try - { - // What will be the index of this if we release? - int targetIndex = CalculateRowIndex(); - if (m_ActiveElement != targetIndex) - { - // if the target index is different than the current index... - if (m_SerializedObject != null && m_Elements != null) - { - // if we are working with Serialized Properties, we can handle it for you - m_Elements.MoveArrayElement(m_ActiveElement, targetIndex); - m_SerializedObject.ApplyModifiedProperties(); - m_SerializedObject.Update(); - } - else if (m_ElementList != null) - { - // we are working with the IList, which is probably of a fixed length - System.Object tempObject = m_ElementList[m_ActiveElement]; - for (int i = 0; i < m_ElementList.Count - 1; i++) - { - if (i >= m_ActiveElement) - m_ElementList[i] = m_ElementList[i + 1]; - } - for (int i = m_ElementList.Count - 1; i > 0; i--) - { - if (i > targetIndex) - m_ElementList[i] = m_ElementList[i - 1]; - } - m_ElementList[targetIndex] = tempObject; - } - - var oldActiveElement = m_ActiveElement; - var newActiveElement = targetIndex; - - // update the active element, now that we've moved it - m_ActiveElement = targetIndex; - // give the user a callback - if (onReorderCallbackWithDetails != null) - onReorderCallbackWithDetails(this, oldActiveElement, newActiveElement); - else if (onReorderCallback != null) - onReorderCallback(this); - - if (onChangedCallback != null) - onChangedCallback(this); - } - else - { - // if mouse up was on the same index as mouse down we fire a mouse up callback (useful if for beginning renaming on mouseup) - if (onMouseUpCallback != null) - onMouseUpCallback(this); - } - } - finally - { - // It's quite possible a call to EndGUI was made in one of our callbacks - // (and thus an ExitGUIException thrown). We still need to cleanup before - // we exitGUI proper. - GUIUtility.hotControl = 0; - m_NonDragTargetIndices = null; - } - break; - } - // if the index has changed and there is a selected callback, call it - if ((m_ActiveElement != oldIndex || clicked) && onSelectCallback != null) - onSelectCallback(this); - } - - bool IsMouseInsideActiveElement(Rect listRect) - { - int mouseRowIndex = GetRowIndex(Event.current.mousePosition.y - listRect.y); - return mouseRowIndex == m_ActiveElement && GetRowRect(mouseRowIndex, listRect).Contains(Event.current.mousePosition); - } - - private void UpdateDraggedY(Rect listRect) - { - m_DraggedY = Mathf.Clamp(Event.current.mousePosition.y - listRect.y, m_DragOffset, listRect.height - (GetElementHeight(m_ActiveElement) - m_DragOffset)); - } - - private int CalculateRowIndex() - { - return GetRowIndex(m_DraggedY); - } - - private int GetRowIndex(float localY) - { - if (elementHeightCallback == null) - return Mathf.Clamp(Mathf.FloorToInt(localY / elementHeight), 0, count - 1); - - float rowYOffset = 0; - for (int i = 0; i < count; i++) - { - float rowYHeight = elementHeightCallback(i); - float rowYEnd = rowYOffset + rowYHeight; - if (localY >= rowYOffset && localY < rowYEnd) - { - return i; - } - rowYOffset += rowYHeight; - } - return count - 1; - } - - private bool IsDragging() - { - return m_Dragging; - } - - public void GrabKeyboardFocus() - { - GUIUtility.keyboardControl = id; - } - - public void ReleaseKeyboardFocus() - { - if (GUIUtility.keyboardControl == id) - { - GUIUtility.keyboardControl = 0; - } - } - - public bool HasKeyboardControl() - { - return GUIUtility.keyboardControl == id; - } - } -} diff --git a/Editor/Mono/GUI/ScalableGUIContent.cs b/Editor/Mono/GUI/ScalableGUIContent.cs deleted file mode 100644 index 75d95c2b25..0000000000 --- a/Editor/Mono/GUI/ScalableGUIContent.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.StyleSheets; -using UnityEngine; - -namespace UnityEditor -{ - [Serializable] - internal class ScalableGUIContent - { - [Serializable] - struct TextureResource - { - public float pixelsPerPoint; - public string resourcePath; - } - - [SerializeField] - private List m_TextureResources = new List(2); - - [SerializeField] - private string m_CurrentResourcePath; - - [SerializeField] - private GUIContent m_GuiContent; - - public ScalableGUIContent(string resourceName) : this(string.Empty, string.Empty, resourceName) - { - } - - public ScalableGUIContent(string text, string tooltip, string resourceName) - { - m_GuiContent = !string.IsNullOrEmpty(text) || !string.IsNullOrEmpty(tooltip) ? - EditorGUIUtility.TextContent(string.Format("{0}|{1}", text, tooltip)) : - new GUIContent(); - - // TODO: make this more sophisticated when/if we have more granular support for different DPI levels - m_TextureResources.Add(new TextureResource { pixelsPerPoint = 1f, resourcePath = resourceName}); - m_TextureResources.Add(new TextureResource { pixelsPerPoint = 2f, resourcePath = string.Format("{0}@2x", resourceName)}); - } - - public static implicit operator GUIContent(ScalableGUIContent gc) - { - var dpi = EditorGUIUtility.pixelsPerPoint; - var resourcePath = gc.m_CurrentResourcePath; - for (int i = 0, count = gc.m_TextureResources.Count; i < count; ++i) - { - if (gc.m_TextureResources[i].pixelsPerPoint > dpi) - break; - resourcePath = gc.m_TextureResources[i].resourcePath; - } - if (resourcePath != gc.m_CurrentResourcePath) - { - gc.m_GuiContent.image = - StyleSheetResourceUtil.LoadResource(resourcePath, typeof(Texture2D), false) as Texture2D; - gc.m_CurrentResourcePath = resourcePath; - } - return gc.m_GuiContent; - } - } -} diff --git a/Editor/Mono/GUI/ScreenShotting.cs b/Editor/Mono/GUI/ScreenShotting.cs deleted file mode 100644 index eaad932ac6..0000000000 --- a/Editor/Mono/GUI/ScreenShotting.cs +++ /dev/null @@ -1,179 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class ScreenShots - { - public static Color kToolbarBorderColor = new Color(0.54f, 0.54f, 0.54f, 1f); - public static Color kWindowBorderColor = new Color(0.51f, 0.51f, 0.51f, 1f); - public static bool s_TakeComponentScreenshot = false; - - [MenuItem("Window/Screenshot/Set Window Size %&l", false, 1000, true)] - public static void SetMainWindowSize() - { - var main = Resources.FindObjectsOfTypeAll()[0]; - main.window.position = new Rect(0, 0, 1024, 768); - } - - [MenuItem("Window/Screenshot/Set Window Size Small", false, 1000, true)] - public static void SetMainWindowSizeSmall() - { - var main = Resources.FindObjectsOfTypeAll()[0]; - main.window.position = new Rect(0, 0, 800 - 38, 600); - } - - [MenuItem("Window/Screenshot/Snap View %&j", false, 1000, true)] - public static void Screenshot() - { - GUIView v = GetMouseOverView(); - if (v != null) - { - string name = GetGUIViewName(v); - Rect r = v.screenPosition; - r.y -= 1; - r.height += 2; - SaveScreenShot(r, name); - } - } - - [MenuItem("Window/Screenshot/Snap View Toolbar", false, 1000, true)] - public static void ScreenshotToolbar() - { - GUIView v = GetMouseOverView(); - if (v != null) - { - string name = GetGUIViewName(v) + "Toolbar"; - Rect r = v.screenPosition; - r.y += 19; - r.height = 16; - r.width -= 2; - SaveScreenShotWithBorder(r, kToolbarBorderColor, name); - } - } - - [MenuItem("Window/Screenshot/Snap View Extended Right %&k", false, 1000, true)] - public static void ScreenshotExtendedRight() - { - GUIView v = GetMouseOverView(); - if (v != null) - { - string name = GetGUIViewName(v) + "Extended"; - var main = Resources.FindObjectsOfTypeAll()[0]; - Rect r = v.screenPosition; - r.xMax = main.window.position.xMax; - r.y -= 1; - r.height += 2; - SaveScreenShot(r, name); - } - } - - [MenuItem("Window/Screenshot/Snap Component", false, 1000, true)] - public static void ScreenShotComponent() - { - s_TakeComponentScreenshot = true; - } - - public static void ScreenShotComponent(Rect contentRect, Object target) - { - s_TakeComponentScreenshot = false; - - contentRect.yMax += 2; - contentRect.xMin += 1; - ScreenShots.SaveScreenShotWithBorder(contentRect, kWindowBorderColor, target.GetType().Name + "Inspector"); - } - - [MenuItem("Window/Screenshot/Snap Game View Content", false, 1000, true)] - public static void ScreenGameViewContent() - { - string path = GetUniquePathForName("ContentExample"); - ScreenCapture.CaptureScreenshot(path); - Debug.Log(string.Format("Saved screenshot at {0}", path)); - } - - static GUIView GetMouseOverView() - { - GUIView v = GUIView.mouseOverView; - if (v == null) - { - EditorApplication.Beep(); - Debug.LogWarning("Could not take screenshot."); - } - return v; - } - - static string GetGUIViewName(GUIView view) - { - HostView host = view as HostView; - if (host != null) - return host.actualView.GetType().Name; - return "Window"; - } - - public static void SaveScreenShot(Rect r, string name) - { - SaveScreenShot((int)r.width, (int)r.height, InternalEditorUtility.ReadScreenPixel(new Vector2(r.x, r.y), (int)r.width, (int)r.height), name); - } - - // Adds a gray border around the screenshot - // Useful for e.g. toolbars because they don't have a nice border all the way round due to the tabs - public static string SaveScreenShotWithBorder(Rect r, Color borderColor, string name) - { - int w = (int)r.width; - int h = (int)r.height; - Color[] colors1 = InternalEditorUtility.ReadScreenPixel(new Vector2(r.x, r.y), w, h); - Color[] colors2 = new Color[(w + 2) * (h + 2)]; - for (int x = 0; x < w; x++) - { - for (int y = 0; y < h; y++) - { - colors2[x + 1 + (w + 2) * (y + 1)] = colors1[x + w * y]; - } - } - for (int x = 0; x < w + 2; x++) - { - colors2[x] = borderColor; - colors2[x + (w + 2) * (h + 1)] = borderColor; - } - for (int y = 0; y < h + 2; y++) - { - colors2[y * (w + 2)] = borderColor; - colors2[y * (w + 2) + (w + 1)] = borderColor; - } - - return SaveScreenShot((int)(r.width + 2), (int)(r.height + 2), colors2, name); - } - - static string SaveScreenShot(int width, int height, Color[] pixels, string name) - { - Texture2D t = new Texture2D(width, height); - t.SetPixels(pixels, 0); - t.Apply(true); - - byte[] bytes = t.EncodeToPNG(); - Object.DestroyImmediate(t, true); - - string path = GetUniquePathForName(name); - System.IO.File.WriteAllBytes(path, bytes); - Debug.Log(string.Format("Saved screenshot at {0}", path)); - return path; - } - - static string GetUniquePathForName(string name) - { - string path = string.Format("{0}/../../{1}.png", Application.dataPath, name); - int i = 0; - while (System.IO.File.Exists(path)) - { - path = string.Format("{0}/../../{1}{2:000}.png", Application.dataPath, name, i); - i++; - } - return path; - } - } -} diff --git a/Editor/Mono/GUI/SearchField.cs b/Editor/Mono/GUI/SearchField.cs deleted file mode 100644 index 483ba8f0c6..0000000000 --- a/Editor/Mono/GUI/SearchField.cs +++ /dev/null @@ -1,133 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Runtime.Remoting.Messaging; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public class SearchField - { - int m_ControlID; - bool m_WantsFocus; - bool m_AutoSetFocusOnFindCommand = true; - const float kMinWidth = 36f; - const float kMaxWidth = 10000000f; - const float kMinToolbarWidth = 29f; - const float kMaxToolbarWidth = 200f; - - public delegate void SearchFieldCallback(); - public event SearchFieldCallback downOrUpArrowKeyPressed; - - public SearchField() - { - m_ControlID = GUIUtility.GetPermanentControlID(); - } - - public int searchFieldControlID - { - get { return m_ControlID; } - set { m_ControlID = value; } - } - - public bool autoSetFocusOnFindCommand - { - get { return m_AutoSetFocusOnFindCommand; } - set { m_AutoSetFocusOnFindCommand = value; } - } - - public void SetFocus() - { - m_WantsFocus = true; - } - - public bool HasFocus() - { - return GUIUtility.keyboardControl == m_ControlID; - } - - public string OnGUI(Rect rect, string text, GUIStyle style, GUIStyle cancelButtonStyle, GUIStyle emptyCancelButtonStyle) - { - CommandEventHandling(); - - FocusAndKeyHandling(); - - float cancelButtonWidth = cancelButtonStyle.fixedWidth; - - // Search field - Rect textRect = rect; - textRect.width -= cancelButtonWidth; - text = EditorGUI.TextFieldInternal(m_ControlID, textRect, text, style); - - // Cancel button - Rect buttonRect = rect; - buttonRect.x += rect.width - cancelButtonWidth; - buttonRect.width = cancelButtonWidth; - if (GUI.Button(buttonRect, GUIContent.none, text != "" ? cancelButtonStyle : emptyCancelButtonStyle) && text != "") - { - text = ""; - GUIUtility.keyboardControl = 0; - } - return text; - } - - public string OnGUI(Rect rect, string text) - { - return OnGUI(rect, text, EditorStyles.searchField, EditorStyles.searchFieldCancelButton, EditorStyles.searchFieldCancelButtonEmpty); - } - - public string OnGUI(string text, params GUILayoutOption[] options) - { - Rect rect = GUILayoutUtility.GetRect(kMinWidth, kMaxWidth, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.searchField, options); - return OnGUI(rect, text); - } - - public string OnToolbarGUI(Rect rect, string text) - { - return OnGUI(rect, text, EditorStyles.toolbarSearchField, EditorStyles.toolbarSearchFieldCancelButton, EditorStyles.toolbarSearchFieldCancelButtonEmpty); - } - - public string OnToolbarGUI(string text, params GUILayoutOption[] options) - { - Rect rect = GUILayoutUtility.GetRect(kMinToolbarWidth, kMaxToolbarWidth, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchField, options); - return OnToolbarGUI(rect, text); - } - - void FocusAndKeyHandling() - { - Event evt = Event.current; - if (m_WantsFocus && evt.type == EventType.Repaint) - { - GUIUtility.keyboardControl = m_ControlID; - EditorGUIUtility.editingTextField = true; - m_WantsFocus = false; - } - - if (evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.DownArrow || evt.keyCode == KeyCode.UpArrow) && - GUIUtility.keyboardControl == m_ControlID && GUIUtility.hotControl == 0) - { - if (downOrUpArrowKeyPressed != null) - { - downOrUpArrowKeyPressed(); - evt.Use(); - } - } - } - - void CommandEventHandling() - { - Event evt = Event.current; - - if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand) - return; - - if (m_AutoSetFocusOnFindCommand && evt.commandName == EventCommandNames.Find) - { - if (evt.type == EventType.ExecuteCommand) - SetFocus(); - evt.Use(); - } - } - } -} // namespace diff --git a/Editor/Mono/GUI/SliderWithTexture.cs b/Editor/Mono/GUI/SliderWithTexture.cs deleted file mode 100644 index 4a3350846b..0000000000 --- a/Editor/Mono/GUI/SliderWithTexture.cs +++ /dev/null @@ -1,113 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class EditorGUILayout - { - internal static void SliderWithTexture( - GUIContent label, - SerializedProperty property, - float sliderMin, float sliderMax, - float power, - Texture2D sliderBackground, - params GUILayoutOption[] options - ) - { - var rect = s_LastRect = GetSliderRect(false, options); - EditorGUI.SliderWithTexture(rect, label, property, sliderMin, sliderMax, power, sliderBackground); - } - - internal static float SliderWithTexture( - GUIContent label, - float sliderValue, float sliderMin, float sliderMax, - string formatString, - Texture2D sliderBackground, - params GUILayoutOption[] options - ) - { - return SliderWithTexture( - label, sliderValue, sliderMin, sliderMax, formatString, sliderMin, sliderMax, sliderBackground - ); - } - - internal static float SliderWithTexture( - GUIContent label, - float sliderValue, float sliderMin, float sliderMax, - string formatString, float textFieldMin, float textFieldMax, - Texture2D sliderBackground, - params GUILayoutOption[] options - ) - { - var rect = s_LastRect = GetSliderRect(false, options); - return EditorGUI.SliderWithTexture( - rect, label, sliderValue, sliderMin, sliderMax, formatString, textFieldMin, textFieldMax, 1f, sliderBackground - ); - } - } - - public sealed partial class EditorGUI - { - internal static void SliderWithTexture( - Rect position, - GUIContent label, - SerializedProperty property, - float sliderMin, float sliderMax, - float power, - Texture2D sliderBackground - ) - { - label = BeginProperty(position, label, property); - - BeginChangeCheck(); - - var formatString = property.propertyType == SerializedPropertyType.Integer ? - kIntFieldFormatString : kFloatFieldFormatString; - var newValue = SliderWithTexture( - position, label, property.floatValue, sliderMin, sliderMax, formatString, sliderMin, sliderMax, power, sliderBackground - ); - - if (EndChangeCheck()) - property.floatValue = newValue; - - EndProperty(); - } - - internal static float SliderWithTexture( - Rect rect, - GUIContent label, - float sliderValue, float sliderMin, float sliderMax, - string formatString, - Texture2D sliderBackground, - params GUILayoutOption[] options - ) - { - return SliderWithTexture( - rect, label, sliderValue, sliderMin, sliderMax, formatString, sliderMin, sliderMax, 1f, sliderBackground - ); - } - - internal static float SliderWithTexture( - Rect position, - GUIContent label, - float sliderValue, float sliderMin, float sliderMax, - string formatString, float textFieldMin, float textFieldMax, - float power, - Texture2D sliderBackground - ) - { - int id = GUIUtility.GetControlID(s_SliderHash, FocusType.Keyboard, position); - var controlRect = PrefixLabel(position, id, label); - var dragZone = - LabelHasContent(label) - ? EditorGUIUtility.DragZoneRect(position) - : default(Rect); // Ensure dragzone is empty when we have no label - return DoSlider( - controlRect, dragZone, id, sliderValue, sliderMin, sliderMax, formatString, textFieldMin, textFieldMax, power, "ColorPickerSliderBackground", "ColorPickerHorizThumb", sliderBackground - ); - } - } -} diff --git a/Editor/Mono/GUI/SplitView.cs b/Editor/Mono/GUI/SplitView.cs deleted file mode 100644 index 2c3682beb7..0000000000 --- a/Editor/Mono/GUI/SplitView.cs +++ /dev/null @@ -1,749 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections.Generic; - -namespace UnityEditor -{ - /// orders all children along an axis. Resizing, splitting, etc.. - class SplitView : View, ICleanuppable, IDropArea - { - const float kRootDropZoneThickness = 70f; - const float kRootDropZoneOffset = 50f; - const float kRootDropDestinationThickness = 200f; - const float kMaxViewDropZoneThickness = 300f; - const float kMinViewDropDestinationThickness = 100f; - - public bool vertical = false; - public int controlID = 0; - - [Flags] internal enum ViewEdge - { - None = 0, - Left = 1 << 0, - Bottom = 1 << 1, - Top = 1 << 2, - Right = 1 << 3, - BottomLeft = Bottom | Left, - BottomRight = Bottom | Right, - TopLeft = Top | Left, - TopRight = Top | Right, - FitsVertical = Top | Bottom, - FitsHorizontal = Left | Right, - Before = Top | Left, // "Before" in SplitView children - After = Bottom | Right // "After" in SplitView children - } - - private Rect RectFromEdge(Rect rect, ViewEdge edge, float thickness, float offset) - { - switch (edge) - { - case ViewEdge.Left: - return new Rect(rect.x - offset, rect.y, thickness, rect.height); - case ViewEdge.Right: - return new Rect(rect.xMax - thickness + offset, rect.y, thickness, rect.height); - case ViewEdge.Top: - return new Rect(rect.x, rect.y - offset, rect.width, thickness); - case ViewEdge.Bottom: - return new Rect(rect.x, rect.yMax - thickness + offset, rect.width, thickness); - default: - throw new ArgumentException("Specify exactly one edge"); - } - } - - // Extra info for dropping. - internal class ExtraDropInfo - { - public bool rootWindow; - public ViewEdge edge; - public int index; - public ExtraDropInfo(bool rootWindow, ViewEdge edge, int index) - { - this.rootWindow = rootWindow; - this.edge = edge; - this.index = index; - } - } - - SplitterState splitState = null; - - void SetupSplitter() - { - int[] actualSizes = new int[children.Length]; - int[] minSizes = new int[children.Length]; - - for (int j = 0; j < children.Length; j++) - { - View c = (View)children[j]; - actualSizes[j] = vertical ? (int)c.position.height : (int)c.position.width; - minSizes[j] = (int)(vertical ? c.minSize.y : c.minSize.x); - } - - splitState = new SplitterState(actualSizes, minSizes, null); - splitState.splitSize = 10; - } - - void SetupRectsFromSplitter() - { - if (children.Length == 0) - return; - - int cursor = 0; - - int total = 0; - foreach (int size in splitState.realSizes) - { - total += size; - } - float scale = 1; - if (total > (vertical ? position.height : position.width)) - scale = (vertical ? position.height : position.width) / total; - - // OSX webviews might trigger nested Repaint events when being resized - // so we protected the GUI state at this level - SavedGUIState state = SavedGUIState.Create(); - - for (int i = 0; i < children.Length; i++) - { - int size = (int)Mathf.Round(splitState.realSizes[i] * scale); - if (vertical) - children[i].position = new Rect(0, cursor, position.width, size); - else - children[i].position = new Rect(cursor, 0, size, position.height); - - cursor += size; - } - - state.ApplyAndForget(); - } - - // 2-part process: recalc children sizes bottomup, the reflow top-down - static void RecalcMinMaxAndReflowAll(SplitView start) - { - // search upwards and find the topmost - SplitView root = start, next = start; - do - { - root = next; - next = root.parent as SplitView; - } - while (next); - - RecalcMinMaxRecurse(root); - ReflowRecurse(root); - } - - static void RecalcMinMaxRecurse(SplitView node) - { - foreach (View i in node.children) - { - SplitView sv = i as SplitView; - if (sv) - RecalcMinMaxRecurse(sv); - } - node.ChildrenMinMaxChanged(); - } - - static void ReflowRecurse(SplitView node) - { - node.Reflow(); - foreach (View i in node.children) - { - SplitView sv = i as SplitView; - if (sv) - RecalcMinMaxRecurse(sv); - } - } - - internal override void Reflow() - { - SetupSplitter(); - - for (int k = 0; k < children.Length - 1; k++) - splitState.DoSplitter(k, k + 1, 0); - splitState.RelativeToRealSizes(vertical ? (int)position.height : (int)position.width); - SetupRectsFromSplitter(); - } - - void PlaceView(int i, float pos, float size) - { - float roundPos = Mathf.Round(pos); - if (vertical) - children[i].position = new Rect(0, roundPos, position.width, Mathf.Round(pos + size) - roundPos); - else - children[i].position = new Rect(roundPos, 0, Mathf.Round(pos + size) - roundPos, position.height); - } - - public override void AddChild(View child, int idx) - { - base.AddChild(child, idx); - ChildrenMinMaxChanged(); - splitState = null; - } - - public void RemoveChildNice(View child) - { - if (children.Length != 1) - { - // Make neighbors to grow to take space - int idx = IndexOfChild(child); - float moveToPos = 0; - if (idx == 0) - moveToPos = 0; - else if (idx == children.Length - 1) - moveToPos = 1; - else - moveToPos = .5f; - - moveToPos = vertical ? - Mathf.Lerp(child.position.yMin, child.position.yMax, moveToPos) : - Mathf.Lerp(child.position.xMin, child.position.xMax, moveToPos); - - - if (idx > 0) - { - View c = (View)children[idx - 1]; - Rect r = c.position; - if (vertical) - r.yMax = moveToPos; - else - r.xMax = moveToPos; - c.position = r; - - if (c is SplitView) - ((SplitView)c).Reflow(); - } - - if (idx < children.Length - 1) - { - View c = (View)children[idx + 1]; - Rect r = c.position; - if (vertical) - c.position = new Rect(r.x, moveToPos, r.width, r.yMax - moveToPos); - else - c.position = new Rect(moveToPos, r.y, r.xMax - moveToPos, r.height); - - if (c is SplitView) - ((SplitView)c).Reflow(); - } - } - RemoveChild(child); - } - - public override void RemoveChild(View child) - { - splitState = null; - base.RemoveChild(child); - } - - DropInfo RootViewDropZone(ViewEdge edge, Vector2 mousePos, Rect screenRect) - { - var offset = (edge & ViewEdge.FitsVertical) != 0 ? kRootDropZoneThickness : kRootDropZoneOffset; - if (!RectFromEdge(screenRect, edge, kRootDropZoneThickness, offset).Contains(mousePos)) - return null; - - var dropInfo = new DropInfo(this); - dropInfo.type = DropInfo.Type.Pane; - dropInfo.userData = new ExtraDropInfo(true, edge, 0); - dropInfo.rect = RectFromEdge(screenRect, edge, kRootDropDestinationThickness, 0f); - return dropInfo; - } - - public DropInfo DragOverRootView(Vector2 mouseScreenPosition) - { - if (children.Length == 1 && DockArea.s_IgnoreDockingForView == children[0]) - { - return null; // Prevent dragging the view from a single-view window into itself - } - return RootViewDropZone(ViewEdge.Bottom, mouseScreenPosition, screenPosition) - ?? RootViewDropZone(ViewEdge.Top, mouseScreenPosition, screenPosition) - ?? RootViewDropZone(ViewEdge.Left, mouseScreenPosition, screenPosition) - ?? RootViewDropZone(ViewEdge.Right, mouseScreenPosition, screenPosition); - } - - public DropInfo DragOver(EditorWindow w, Vector2 mouseScreenPosition) - { - for (var childIndex = 0; childIndex < children.Length; ++childIndex) - { - var child = children[childIndex]; - - // skip so you can't dock a view to a subview of itself - if (child == DockArea.s_IgnoreDockingForView) - continue; - - // Skip if child is a splitview (it'll handle its rect itself) - if (child is SplitView) - continue; - - // Collect flags of which edge zones the mouse is inside - var mouseEdges = ViewEdge.None; - var childRect = child.screenPosition; - var childRectWithoutDock = RectFromEdge(childRect, ViewEdge.Bottom, childRect.height - DockArea.kDockHeight, 0f); - var borderWidth = Mathf.Min(Mathf.Round(childRectWithoutDock.width / 3), kMaxViewDropZoneThickness); - var borderHeight = Mathf.Min(Mathf.Round(childRectWithoutDock.height / 3), kMaxViewDropZoneThickness); - var leftDropZone = RectFromEdge(childRectWithoutDock, ViewEdge.Left, borderWidth, 0f); - var rightDropZone = RectFromEdge(childRectWithoutDock, ViewEdge.Right, borderWidth, 0f); - var bottomDropZone = RectFromEdge(childRectWithoutDock, ViewEdge.Bottom, borderHeight, 0f); - var topDropZone = RectFromEdge(childRectWithoutDock, ViewEdge.Top, borderHeight, 0f); - - if (leftDropZone.Contains(mouseScreenPosition)) - mouseEdges |= ViewEdge.Left; - - if (rightDropZone.Contains(mouseScreenPosition)) - mouseEdges |= ViewEdge.Right; - - if (bottomDropZone.Contains(mouseScreenPosition)) - mouseEdges |= ViewEdge.Bottom; - - if (topDropZone.Contains(mouseScreenPosition)) - mouseEdges |= ViewEdge.Top; - - // If mouse is in more than one zone, it is in a corner. Find the corner and divide it diagonally... - var mouseToCorner = Vector2.zero; - var oppositeToCorner = Vector2.zero; - var ccwEdge = mouseEdges; - var cwEdge = mouseEdges; - switch (mouseEdges) - { - case ViewEdge.BottomLeft: - ccwEdge = ViewEdge.Bottom; - cwEdge = ViewEdge.Left; - mouseToCorner = new Vector2(childRectWithoutDock.x, childRectWithoutDock.yMax) - mouseScreenPosition; - oppositeToCorner = new Vector2(-borderWidth, borderHeight); - break; - case ViewEdge.BottomRight: - ccwEdge = ViewEdge.Right; - cwEdge = ViewEdge.Bottom; - mouseToCorner = new Vector2(childRectWithoutDock.xMax, childRectWithoutDock.yMax) - mouseScreenPosition; - oppositeToCorner = new Vector2(borderWidth, borderHeight); - break; - case ViewEdge.TopLeft: - ccwEdge = ViewEdge.Left; - cwEdge = ViewEdge.Top; - mouseToCorner = new Vector2(childRectWithoutDock.x, childRectWithoutDock.y) - mouseScreenPosition; - oppositeToCorner = new Vector2(-borderWidth, -borderHeight); - break; - case ViewEdge.TopRight: - ccwEdge = ViewEdge.Top; - cwEdge = ViewEdge.Right; - mouseToCorner = new Vector2(childRectWithoutDock.xMax, childRectWithoutDock.y) - mouseScreenPosition; - oppositeToCorner = new Vector2(borderWidth, -borderHeight); - break; - } - // ...then choose the edge based on the half the mouse is in - mouseEdges = mouseToCorner.x * oppositeToCorner.y - mouseToCorner.y * oppositeToCorner.x < 0 ? ccwEdge : cwEdge; - - if (mouseEdges != ViewEdge.None) // Valid drop zone - { - var targetThickness = Mathf.Round(((mouseEdges & ViewEdge.FitsHorizontal) != 0 ? childRect.width : childRect.height) / 3); - targetThickness = Mathf.Max(targetThickness, kMinViewDropDestinationThickness); - - var dropInfo = new DropInfo(this); - dropInfo.userData = new ExtraDropInfo(false, mouseEdges, childIndex); - dropInfo.type = DropInfo.Type.Pane; - dropInfo.rect = RectFromEdge(childRect, mouseEdges, targetThickness, 0f); - return dropInfo; - } - } - // Claim the drag if we are the root split view, so it doesn't fall through to obscured windows - if (screenPosition.Contains(mouseScreenPosition) && !(parent is SplitView)) - { - return new DropInfo(null); - } - - return null; - } - - /// Notification so other views can respond to this. - protected override void ChildrenMinMaxChanged() - { - Vector2 min = Vector2.zero, max = Vector2.zero; - if (vertical) - { - foreach (View child in children) - { - min.x = Mathf.Max(child.minSize.x, min.x); - max.x = Mathf.Max(child.maxSize.x, max.x); - min.y += child.minSize.y; - max.y += child.maxSize.y; - } - } - else - { - foreach (View child in children) - { - min.x += child.minSize.x; - max.x += child.maxSize.x; - min.y = Mathf.Max(child.minSize.y, min.y); - max.y = Mathf.Max(child.maxSize.y, max.y); - } - } - splitState = null; - - SetMinMaxSizes(min, max); - } - - public override string ToString() - { - return vertical ? "SplitView (vert)" : "SplitView (horiz)"; - } - - public bool PerformDrop(EditorWindow dropWindow, DropInfo dropInfo, Vector2 screenPos) - { - var extraInfo = dropInfo.userData as ExtraDropInfo; - var rootWindow = extraInfo.rootWindow; - var edge = extraInfo.edge; - var dropIndex = extraInfo.index; - var dropRect = dropInfo.rect; - var beginning = (edge & ViewEdge.Before) != 0; - var wantsVertical = (edge & ViewEdge.FitsVertical) != 0; - SplitView parentForDrop = null; - if (vertical == wantsVertical || children.Length < 2) - { // Current view can accommodate desired drop - if (!beginning) - { - if (rootWindow) - dropIndex = children.Length; - else - ++dropIndex; - } - parentForDrop = this; - } - else if (rootWindow) - { // Docking to a window: need to insert a parent - var newParent = ScriptableObject.CreateInstance(); - newParent.position = position; - if (window.rootView == this) - window.rootView = newParent; - else // Main window has MainView as its root - parent.AddChild(newParent, parent.IndexOfChild(this)); - newParent.AddChild(this); - position = new Rect(Vector2.zero, position.size); - - dropIndex = beginning ? 0 : 1; - parentForDrop = newParent; - } - else - { // Docking in a view: need to insert a child - var newChild = ScriptableObject.CreateInstance(); - - newChild.AddChild(children[dropIndex]); - AddChild(newChild, dropIndex); - newChild.position = newChild.children[0].position; - newChild.children[0].position = new Rect(Vector2.zero, newChild.position.size); - - dropIndex = beginning ? 0 : 1; - parentForDrop = newChild; - } - dropRect.position = dropRect.position - screenPosition.position; - var newDockArea = ScriptableObject.CreateInstance(); - parentForDrop.vertical = wantsVertical; - parentForDrop.MakeRoomForRect(dropRect); - parentForDrop.AddChild(newDockArea, dropIndex); - newDockArea.position = dropRect; - DockArea.s_OriginalDragSource.RemoveTab(dropWindow); - dropWindow.m_Parent = newDockArea; - newDockArea.AddTab(dropWindow); - Reflow(); - RecalcMinMaxAndReflowAll(this); - newDockArea.MakeVistaDWMHappyDance(); - return true; - } - - static string PosVals(float[] posVals) - { - string s = "["; - foreach (float p in posVals) - s += "" + p + ", "; - s += "]"; - return (s); - } - - void MakeRoomForRect(Rect r) - { - Rect[] sources = new Rect[children.Length]; - for (int i = 0; i < sources.Length; i++) - sources[i] = children[i].position; - - CalcRoomForRect(sources, r); - // string s = "Making room for " + r +" \nchildren {\n"; - for (int i = 0; i < sources.Length; i++) - { - // s += " " + sources[i] + " \n"; - children[i].position = sources[i]; - } - // s+= "}"; - // Debug.Log (s); - } - - void CalcRoomForRect(Rect[] sources, Rect r) - { - float start = vertical ? r.y : r.x; - float end = start + (vertical ? r.height : r.width); - float mid = (start + end) * .5f; - - // Find out where we should split - int splitPos; - for (splitPos = 0; splitPos < sources.Length; splitPos++) - { - float midPos = vertical ? - (sources[splitPos].y + sources[splitPos].height * .5f) : - (sources[splitPos].x + sources[splitPos].width * .5f); - if (midPos > mid) - break; - } - - float p2 = start; - for (int i = splitPos - 1; i >= 0; i--) - { - if (vertical) - { - sources[i].yMax = p2; - if (sources[i].height < children[i].minSize.y) - p2 = sources[i].yMin = sources[i].yMax - children[i].minSize.y; - else - break; - } - else - { - sources[i].xMax = p2; - if (sources[i].width < children[i].minSize.x) - p2 = sources[i].xMin = sources[i].xMax - children[i].minSize.x; - else - break; - } - } - // if we're below zero, move everything forward - if (p2 < 0) - { - float delta = -p2; - for (int i = 0; i < splitPos - 1; i++) - { - if (vertical) - sources[i].y += delta; - else - sources[i].x += delta; - } - end += delta; - } - - p2 = end; - for (int i = splitPos; i < sources.Length; i++) - { - if (vertical) - { - float tmp = sources[i].yMax; - sources[i].yMin = p2; - sources[i].yMax = tmp; - if (sources[i].height < children[i].minSize.y) - p2 = sources[i].yMax = sources[i].yMin + children[i].minSize.y; - else - break; - } - else - { - float tmp = sources[i].xMax; - sources[i].xMin = p2; - sources[i].xMax = tmp; - if (sources[i].width < children[i].minSize.x) - p2 = sources[i].xMax = sources[i].xMin + children[i].minSize.x; - else - break; - } - } - // if we're above max, move everything forward - float limit = vertical ? position.height : position.width; - if (p2 > limit) - { - float delta = limit - p2; - for (int i = 0; i < splitPos - 1; i++) - { - if (vertical) - sources[i].y += delta; - else - sources[i].x += delta; - } - end += delta; - } - } - - /// clean up this view & propagate down - public void Cleanup() - { - // if I'm a one-view splitview, I can propagate my child up and kill myself - - SplitView sp = parent as SplitView; - - if (children.Length == 1 && sp != null) - { - View c = children[0]; - c.position = position; - if (parent != null) - { - parent.AddChild(c, parent.IndexOfChild(this)); - parent.RemoveChild(this); - if (sp) - sp.Cleanup(); - c.position = position; - if (!Unsupported.IsDestroyScriptableObject(this)) - DestroyImmediate(this); - return; - } - else if (c is SplitView) - { - RemoveChild(c); - window.rootView = c; - c.position = new Rect(0, 0, c.window.position.width, window.position.height); - c.Reflow(); - if (!Unsupported.IsDestroyScriptableObject(this)) - DestroyImmediate(this); - return; - } - } - - if (sp) - { - sp.Cleanup(); - // the parent might have moved US up and gotten rid of itself - sp = parent as SplitView; - if (sp) - { - // If the parent has the same orientation as us, we can move our views up and kill ourselves - if (sp.vertical == vertical) - { - int idx = new List(parent.children).IndexOf(this); - foreach (View child in children) - { - sp.AddChild(child, idx++); - child.position = new Rect(position.x + child.position.x, position.y + child.position.y, child.position.width, child.position.height); - } - } - } - } - if (children.Length == 0) - { - if (parent == null && window != null) - { - // if we're root in the window, we'll remove ourselves - window.Close(); - } - else - { - ICleanuppable ic = parent as ICleanuppable; - if (parent is SplitView) - { - ((SplitView)parent).RemoveChildNice(this); - if (!Unsupported.IsDestroyScriptableObject(this)) - DestroyImmediate(this, true); - } - else - { - // This is we're root in the main window. - // We want to stay, but tell the parent (MainWindow) to Cleanup, so he can reduce us to zero-size - /* parent.RemoveChild (this);*/ - } - ic.Cleanup(); - } - return; - } - else - { - splitState = null; - Reflow(); - } - } - - internal const float kGrabDist = 5; - public void SplitGUI(Event evt) - { - if (splitState == null) - SetupSplitter(); - - SplitView sp = parent as SplitView; - if (sp) - { - Event e = new Event(evt); - e.mousePosition += new Vector2(position.x, position.y); - sp.SplitGUI(e); - if (e.type == EventType.Used) - evt.Use(); - } - - float pos = vertical ? evt.mousePosition.y : evt.mousePosition.x; - int id = GUIUtility.GetControlID(546739, FocusType.Passive); - controlID = id; - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (children.Length != 1) // is there a splitter - { - int cursor = vertical ? (int)children[0].position.y : (int)children[0].position.x; - - for (int i = 0; i < children.Length - 1; i++) - { - if (i >= splitState.realSizes.Length) - { - DockArea dock = GUIView.current as DockArea; - string name = "Non-dock area " + GUIView.current.GetType(); - if (dock && dock.m_Selected < dock.m_Panes.Count && dock.m_Panes[dock.m_Selected]) - name = dock.m_Panes[dock.m_Selected].GetType().ToString(); - - if (Unsupported.IsDeveloperMode()) - Debug.LogError("Real sizes out of bounds for: " + name + " index: " + i + " RealSizes: " + splitState.realSizes.Length); - - SetupSplitter(); - } - Rect splitterRect = vertical ? - new Rect(children[0].position.x, cursor + splitState.realSizes[i] - splitState.splitSize / 2, children[0].position.width, splitState.splitSize) : - new Rect(cursor + splitState.realSizes[i] - splitState.splitSize / 2, children[0].position.y, splitState.splitSize, children[0].position.height); - - if (splitterRect.Contains(evt.mousePosition)) - { - splitState.splitterInitialOffset = (int)pos; - splitState.currentActiveSplitter = i; - GUIUtility.hotControl = id; - evt.Use(); - break; - } - - cursor += splitState.realSizes[i]; - } - } - break; - case EventType.MouseDrag: - if (children.Length > 1 && (GUIUtility.hotControl == id) && (splitState.currentActiveSplitter >= 0)) - { - int diff = (int)pos - splitState.splitterInitialOffset; - - if (diff != 0) - { - splitState.splitterInitialOffset = (int)pos; - splitState.DoSplitter(splitState.currentActiveSplitter, splitState.currentActiveSplitter + 1, diff); - } - - SetupRectsFromSplitter(); - - - evt.Use(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - GUIUtility.hotControl = 0; - break; - } - } - - protected override void SetPosition(Rect newPos) - { - base.SetPosition(newPos); - Reflow(); - } - } -} // namespace diff --git a/Editor/Mono/GUI/Splitter.cs b/Editor/Mono/GUI/Splitter.cs deleted file mode 100644 index 407e25370a..0000000000 --- a/Editor/Mono/GUI/Splitter.cs +++ /dev/null @@ -1,485 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - /// *undocumented* - [System.Serializable] - internal class SplitterState - { - const int defaultSplitSize = 6; - - public int ID; - public int splitterInitialOffset; - public int currentActiveSplitter = -1; - - public int[] realSizes; - public float[] relativeSizes; // these should always add up to 1 - - public int[] minSizes; - public int[] maxSizes; - - public int lastTotalSize = 0; - - public int splitSize; - - public float xOffset; - - public SplitterState(params float[] relativeSizes) - { - Init(relativeSizes, null, null, 0); - } - - public SplitterState(int[] realSizes, int[] minSizes, int[] maxSizes) - { - this.realSizes = realSizes; - this.minSizes = minSizes == null ? new int[realSizes.Length] : minSizes; - this.maxSizes = maxSizes == null ? new int[realSizes.Length] : maxSizes; - relativeSizes = new float[realSizes.Length]; - - this.splitSize = splitSize == 0 ? defaultSplitSize : splitSize; - - RealToRelativeSizes(); - } - - public SplitterState(float[] relativeSizes, int[] minSizes, int[] maxSizes) - { - Init(relativeSizes, minSizes, maxSizes, 0); - } - - public SplitterState(float[] relativeSizes, int[] minSizes, int[] maxSizes, int splitSize) - { - Init(relativeSizes, minSizes, maxSizes, splitSize); - } - - private void Init(float[] relativeSizes, int[] minSizes, int[] maxSizes, int splitSize) - { - this.relativeSizes = relativeSizes; - this.minSizes = minSizes == null ? new int[relativeSizes.Length] : minSizes; - this.maxSizes = maxSizes == null ? new int[relativeSizes.Length] : maxSizes; - realSizes = new int[relativeSizes.Length]; - - this.splitSize = splitSize == 0 ? defaultSplitSize : splitSize; - - NormalizeRelativeSizes(); - } - - public void NormalizeRelativeSizes() - { - float check = 1.0f; // try to avoid rounding issues - float total = 0; - int k; - - // distribute space relatively - for (k = 0; k < relativeSizes.Length; k++) - total += relativeSizes[k]; - - for (k = 0; k < relativeSizes.Length; k++) - { - relativeSizes[k] = relativeSizes[k] / total; - check -= relativeSizes[k]; - } - - relativeSizes[relativeSizes.Length - 1] += check; - } - - public void RealToRelativeSizes() - { - float check = 1.0f; // try to avoid rounding issues - float total = 0; - int k; - - // distribute space relatively - for (k = 0; k < realSizes.Length; k++) - total += realSizes[k]; - - for (k = 0; k < realSizes.Length; k++) - { - relativeSizes[k] = realSizes[k] / total; - check -= relativeSizes[k]; - } - if (relativeSizes.Length > 0) - relativeSizes[relativeSizes.Length - 1] += check; - } - - public void RelativeToRealSizes(int totalSpace) - { - int spaceToShare = totalSpace, k; - - for (k = 0; k < relativeSizes.Length; k++) - { - realSizes[k] = (int)Mathf.Round(relativeSizes[k] * totalSpace); - - if (realSizes[k] < minSizes[k]) - realSizes[k] = minSizes[k]; - - spaceToShare -= realSizes[k]; - } - - if (spaceToShare < 0) - { - for (k = 0; k < relativeSizes.Length; k++) - { - if (realSizes[k] > minSizes[k]) - { - int spaceInThisOne = realSizes[k] - minSizes[k]; - int spaceToTake = -spaceToShare < spaceInThisOne ? -spaceToShare : spaceInThisOne; - - spaceToShare += spaceToTake; - realSizes[k] -= spaceToTake; - - if (spaceToShare >= 0) - break; - } - } - } - - int last = realSizes.Length - 1; - if (last >= 0) - { - realSizes[last] += spaceToShare; // try to avoid rounding issues - - if (realSizes[last] < minSizes[last]) // but never ignore min size! - realSizes[last] = minSizes[last]; - } - } - - public void DoSplitter(int i1, int i2, int diff) - { - // TODO: This does not handle all cases properly. Theres a hope we will not encounter those cases in the editor. - // Needs to be fixed once its passed to users. - int h1 = realSizes[i1]; - int h2 = realSizes[i2]; - int m1 = minSizes[i1]; - int m2 = minSizes[i2]; - int x1 = maxSizes[i1]; - int x2 = maxSizes[i2]; - - bool diffed = false; - - if (m1 == 0) m1 = 16; - if (m2 == 0) m2 = 16; - - // min constraint - if (h1 + diff < m1) - { - diff -= m1 - h1; - realSizes[i2] += realSizes[i1] - m1; - realSizes[i1] = m1; - - if (i1 != 0) - DoSplitter(i1 - 1, i2, diff); - else - // can't resize more... - splitterInitialOffset -= diff; - - diffed = true; - } - else if (h2 - diff < m2) - { - diff -= h2 - m2; - realSizes[i1] += realSizes[i2] - m2; - realSizes[i2] = m2; - - if (i2 != realSizes.Length - 1) - DoSplitter(i1, i2 + 1, diff); - else - // can't resize more... - splitterInitialOffset -= diff; - - diffed = true; - } - - // max constraint - if (!diffed) - { - if ((x1 != 0) && (h1 + diff > x1)) - { - diff -= realSizes[i1] - x1; - realSizes[i2] += realSizes[i1] - x1; - realSizes[i1] = x1; - - if (i1 != 0) - DoSplitter(i1 - 1, i2, diff); - else - // can't resize more... - splitterInitialOffset -= diff; - - diffed = true; - } - else if ((x2 != 0) && (h2 - diff > x2)) - { - diff -= h2 - x2; - realSizes[i1] += realSizes[i2] - x2; - realSizes[i2] = x2; - - if (i2 != realSizes.Length - 1) - DoSplitter(i1, i2 + 1, diff); - else - // can't resize more... - splitterInitialOffset -= diff; - - diffed = true; - } - } - - // normal case - we have space for resizing - if (!diffed) - { - realSizes[i1] += diff; - realSizes[i2] -= diff; - } - } - } - - class SplitterGUILayout - { - static int splitterHash = "Splitter".GetHashCode(); - - /// *undocumented* - internal class GUISplitterGroup : GUILayoutGroup - { - public SplitterState state; - - public override void SetHorizontal(float x, float width) - { - if (!isVertical) - { - int k; - - state.xOffset = x; - - if (width != state.lastTotalSize) - { - state.RelativeToRealSizes((int)width); - state.lastTotalSize = (int)width; - - // maintain constraints while resizing - for (k = 0; k < state.realSizes.Length - 1; k++) - state.DoSplitter(k, k + 1, 0); - } - - k = 0; - - foreach (GUILayoutEntry i in entries) - { - float thisSize = state.realSizes[k]; - - i.SetHorizontal(Mathf.Round(x), Mathf.Round(thisSize)); - x += thisSize + spacing; - k++; - } - } - else - { - base.SetHorizontal(x, width); - } - } - - public override void SetVertical(float y, float height) - { - rect.y = y; rect.height = height; - - RectOffset padding = style.padding; - - if (isVertical) - { - // 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)... - if (style != GUIStyle.none) - { - float topMar = padding.top, bottomMar = padding.bottom; - if (entries.Count != 0) - { - topMar = Mathf.Max(topMar, ((GUILayoutEntry)entries[0]).margin.top); - bottomMar = Mathf.Max(bottomMar, ((GUILayoutEntry)entries[entries.Count - 1]).margin.bottom); - } - y += topMar; - height -= bottomMar + topMar; - } - - // Set the positions - int k; - - if (height != state.lastTotalSize) - { - state.RelativeToRealSizes((int)height); - state.lastTotalSize = (int)height; - - // maintain constraints while resizing - for (k = 0; k < state.realSizes.Length - 1; k++) - state.DoSplitter(k, k + 1, 0); - } - - k = 0; - - foreach (GUILayoutEntry i in entries) - { - float thisSize = state.realSizes[k]; - - i.SetVertical(Mathf.Round(y), Mathf.Round(thisSize)); - y += thisSize + spacing; - k++; - } - } - else - { - // If we have a GUIStyle here, we need to respect the subelements' margins - if (style != GUIStyle.none) - { - foreach (GUILayoutEntry i in entries) - { - float topMar = Mathf.Max(i.margin.top, padding.top); - float thisY = y + topMar; - float thisHeight = height - Mathf.Max(i.margin.bottom, padding.bottom) - topMar; - - if (i.stretchHeight != 0) - i.SetVertical(thisY, thisHeight); - else - i.SetVertical(thisY, Mathf.Clamp(thisHeight, i.minHeight, i.maxHeight)); - } - } - else - { - // If not, the subelements' margins have already been propagated upwards to this group, so we can safely ignore them - float thisY = y - margin.top; - float thisHeight = height + margin.vertical; - foreach (GUILayoutEntry i in entries) - { - if (i.stretchHeight != 0) - i.SetVertical(thisY + i.margin.top, thisHeight - i.margin.vertical); - else - i.SetVertical(thisY + i.margin.top, Mathf.Clamp(thisHeight - i.margin.vertical, i.minHeight, i.maxHeight)); - } - } - } - } - } - - public static void BeginSplit(SplitterState state, GUIStyle style, bool vertical, params GUILayoutOption[] options) - { - int pos; - var g = (GUISplitterGroup)GUILayoutUtility.BeginLayoutGroup(style, null, typeof(GUISplitterGroup)); - state.ID = GUIUtility.GetControlID(splitterHash, FocusType.Passive); - - switch (Event.current.GetTypeForControl(state.ID)) - { - case EventType.Layout: - { - g.state = state; - g.resetCoords = false; - g.isVertical = vertical; - g.ApplyOptions(options); - break; - } - case EventType.MouseDown: - { - if ((Event.current.button == 0) && (Event.current.clickCount == 1)) - { - int cursor = g.isVertical ? (int)g.rect.y : (int)g.rect.x; - pos = g.isVertical ? (int)Event.current.mousePosition.y : (int)Event.current.mousePosition.x; - - for (int i = 0; i < state.relativeSizes.Length - 1; i++) - { - Rect splitterRect = g.isVertical ? - new Rect(state.xOffset + g.rect.x, cursor + state.realSizes[i] - state.splitSize / 2, g.rect.width, state.splitSize) : - new Rect(state.xOffset + cursor + state.realSizes[i] - state.splitSize / 2, g.rect.y, state.splitSize, g.rect.height); - - if (splitterRect.Contains(Event.current.mousePosition)) - { - state.splitterInitialOffset = pos; - state.currentActiveSplitter = i; - GUIUtility.hotControl = state.ID; - Event.current.Use(); - break; - } - - cursor += (int)state.realSizes[i]; - } - } - break; - } - case EventType.MouseDrag: - { - if ((GUIUtility.hotControl == state.ID) && (state.currentActiveSplitter >= 0)) - { - pos = g.isVertical ? (int)Event.current.mousePosition.y : (int)Event.current.mousePosition.x; - int diff = pos - state.splitterInitialOffset; - - if (diff != 0) - { - state.splitterInitialOffset = pos; - state.DoSplitter(state.currentActiveSplitter, state.currentActiveSplitter + 1, diff); - } - - Event.current.Use(); - } - break; - } - case EventType.MouseUp: - { - if (GUIUtility.hotControl == state.ID) - { - GUIUtility.hotControl = 0; - state.currentActiveSplitter = -1; - state.RealToRelativeSizes(); - Event.current.Use(); - } - break; - } - case EventType.Repaint: - { - int cursor = g.isVertical ? (int)g.rect.y : (int)g.rect.x; - - for (var i = 0; i < state.relativeSizes.Length - 1; i++) - { - var splitterRect = g.isVertical ? - new Rect(state.xOffset + g.rect.x, cursor + state.realSizes[i] - state.splitSize / 2, g.rect.width, state.splitSize) : - new Rect(state.xOffset + cursor + state.realSizes[i] - state.splitSize / 2, g.rect.y, state.splitSize, g.rect.height); - - EditorGUIUtility.AddCursorRect(splitterRect, g.isVertical ? MouseCursor.ResizeVertical : MouseCursor.SplitResizeLeftRight, state.ID); - - cursor += state.realSizes[i]; - } - } - - break; - } - } - - public static void BeginHorizontalSplit(SplitterState state, params GUILayoutOption[] options) - { - BeginSplit(state, GUIStyle.none, false, options); - } - - public static void BeginVerticalSplit(SplitterState state, params GUILayoutOption[] options) - { - BeginSplit(state, GUIStyle.none, true, options); - } - - public static void BeginHorizontalSplit(SplitterState state, GUIStyle style, params GUILayoutOption[] options) - { - BeginSplit(state, style, false, options); - } - - public static void BeginVerticalSplit(SplitterState state, GUIStyle style, params GUILayoutOption[] options) - { - BeginSplit(state, style, true, options); - } - - public static void EndVerticalSplit() - { - GUILayoutUtility.EndLayoutGroup(); - } - - public static void EndHorizontalSplit() - { - GUILayoutUtility.EndLayoutGroup(); - } - } -} diff --git a/Editor/Mono/GUI/StructPropertyGUI.cs b/Editor/Mono/GUI/StructPropertyGUI.cs deleted file mode 100644 index f59fb82175..0000000000 --- a/Editor/Mono/GUI/StructPropertyGUI.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class StructPropertyGUILayout - { - internal static void GenericStruct(SerializedProperty property, params GUILayoutOption[] options) - { - float height = EditorGUI.kStructHeaderLineHeight + EditorGUI.kSingleLineHeight * GetChildrenCount(property); - Rect rect = GUILayoutUtility.GetRect(EditorGUILayout.kLabelFloatMinW, EditorGUILayout.kLabelFloatMaxW, - height, height, EditorStyles.layerMaskField, options); - - StructPropertyGUI.GenericStruct(rect, property); - } - - internal static int GetChildrenCount(SerializedProperty property) - { - int count = 0; - SerializedProperty iterator = property.Copy(); - var end = iterator.GetEndProperty(); - while (!SerializedProperty.EqualContents(iterator, end)) - { - count++; - iterator.NextVisible(true); - } - - return count; - } - } - - internal class StructPropertyGUI - { - internal static void GenericStruct(Rect position, SerializedProperty property) - { - GUI.Label(EditorGUI.IndentedRect(position), property.displayName, EditorStyles.label); - position.y += EditorGUI.kStructHeaderLineHeight; - - DoChildren(position, property); - } - - private static void DoChildren(Rect position, SerializedProperty property) - { - position.height = EditorGUI.kSingleLineHeight; - - EditorGUI.indentLevel++; - - SerializedProperty iterator = property.Copy(); - var end = iterator.GetEndProperty(); - iterator.NextVisible(true); - while (!SerializedProperty.EqualContents(iterator, end)) - { - EditorGUI.PropertyField(position, iterator); - position.y += EditorGUI.kSingleLineHeight; - if (!iterator.NextVisible(false)) - break; - } - - EditorGUI.indentLevel--; - - EditorGUILayout.Space(); - } - } -} diff --git a/Editor/Mono/GUI/TargetChoiceHandler.cs b/Editor/Mono/GUI/TargetChoiceHandler.cs deleted file mode 100644 index 6486c5cb7f..0000000000 --- a/Editor/Mono/GUI/TargetChoiceHandler.cs +++ /dev/null @@ -1,132 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using Object = UnityEngine.Object; -using System.Collections; -using System.Collections.Generic; - -// NOTE: -// This file should only contain internal functions of the EditorGUI class -// - -namespace UnityEditor -{ - internal class TargetChoiceHandler - { - internal delegate void TargetChoiceMenuFunction(SerializedProperty property, Object target); - - internal static void DuplicateArrayElement(object userData) - { - SerializedProperty property = (SerializedProperty)userData; - property.DuplicateCommand(); - property.serializedObject.ApplyModifiedProperties(); - EditorUtility.ForceReloadInspectors(); - } - - internal static void DeleteArrayElement(object userData) - { - SerializedProperty property = (SerializedProperty)userData; - property.DeleteCommand(); - property.serializedObject.ApplyModifiedProperties(); - EditorUtility.ForceReloadInspectors(); - } - - internal static void SetPrefabOverride(object userData) - { - SerializedProperty property = (SerializedProperty)userData; - property.prefabOverride = false; - property.serializedObject.ApplyModifiedProperties(); - EditorUtility.ForceReloadInspectors(); - } - - internal static void SetToValueOfTarget(SerializedProperty property, Object target) - { - property.SetToValueOfTarget(target); - property.serializedObject.ApplyModifiedProperties(); - EditorUtility.ForceReloadInspectors(); - } - - private static void TargetChoiceForwardFunction(object userData) - { - var handler = (PropertyAndTargetHandler)userData; - handler.function(handler.property, handler.target); - } - - static internal void AddSetToValueOfTargetMenuItems(GenericMenu menu, SerializedProperty property, TargetChoiceMenuFunction func) - { - SerializedProperty propertyWithPath = property.serializedObject.FindProperty(property.propertyPath); - Object[] targets = property.serializedObject.targetObjects; - List options = new List(); - foreach (Object target in targets) - { - string option = string.Format("Set to Value of {0}", target.name); - if (options.Contains(option)) - { - for (int i = 1;; i++) - { - option = string.Format("Set to Value of {0}({1})", target.name, i); - if (!options.Contains(option)) - break; - } - } - options.Add(option); - menu.AddItem(EditorGUIUtility.TextContent(option), false, TargetChoiceForwardFunction, new PropertyAndTargetHandler(propertyWithPath, target, func)); - } - } - } - - public sealed partial class EditorGUI - { - /// Popup to choose which target to pick the value from. Use only when hasMultipleDifferentValues is true. - internal static void TargetChoiceField(Rect position, SerializedProperty property, GUIContent label) - { - TargetChoiceField(position, property, label, TargetChoiceHandler.SetToValueOfTarget); - } - - internal static void TargetChoiceField(Rect position, SerializedProperty property, GUIContent label, TargetChoiceHandler.TargetChoiceMenuFunction func) - { - EditorGUI.BeginProperty(position, label, property); - position = EditorGUI.PrefixLabel(position, 0, label); - EditorGUI.BeginHandleMixedValueContentColor(); - if (GUI.Button(position, EditorGUI.mixedValueContent, EditorStyles.popup)) - { - GenericMenu menu = new GenericMenu(); - TargetChoiceHandler.AddSetToValueOfTargetMenuItems(menu, property, func); - menu.DropDown(position); - } - EditorGUI.EndHandleMixedValueContentColor(); - EditorGUI.EndProperty(); - } - } - - public sealed partial class EditorGUILayout - { - /// Popup to choose which target to pick the value from. Use only when hasMultipleDifferentValues is true. - internal static void TargetChoiceField(SerializedProperty property, GUIContent label, params GUILayoutOption[] options) - { - TargetChoiceField(property, label, TargetChoiceHandler.SetToValueOfTarget, options); - } - - internal static void TargetChoiceField(SerializedProperty property, GUIContent label, TargetChoiceHandler.TargetChoiceMenuFunction func, params GUILayoutOption[] options) - { - Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, EditorGUILayout.kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.popup, options); - EditorGUI.TargetChoiceField(rect, property, label, func); - } - } - - internal class PropertyAndTargetHandler - { - public SerializedProperty property; - public Object target; - public TargetChoiceHandler.TargetChoiceMenuFunction function; - public PropertyAndTargetHandler(SerializedProperty property, Object target, TargetChoiceHandler.TargetChoiceMenuFunction function) - { - this.property = property; - this.target = target; - this.function = function; - } - } -} diff --git a/Editor/Mono/GUI/TextFieldDropDown.cs b/Editor/Mono/GUI/TextFieldDropDown.cs deleted file mode 100644 index c6bc16c559..0000000000 --- a/Editor/Mono/GUI/TextFieldDropDown.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - public sealed partial class EditorGUI - { - private const string kEmptyDropDownElement = "--empty--"; - - static internal string DoTextFieldDropDown(Rect rect, int id, string text, string[] dropDownElements, bool delayed) - { - Rect textFieldRect = new Rect(rect.x, rect.y, rect.width - EditorStyles.textFieldDropDown.fixedWidth, rect.height); - Rect popupRect = new Rect(textFieldRect.xMax, textFieldRect.y, EditorStyles.textFieldDropDown.fixedWidth, rect.height); - - - if (delayed) - { - text = DelayedTextField(textFieldRect, text, EditorStyles.textFieldDropDownText); - } - else - { - bool dummy; - text = DoTextField(s_RecycledEditor, id, textFieldRect, text, EditorStyles.textFieldDropDownText, null, out dummy, false, false, false); - } - - - EditorGUI.BeginChangeCheck(); - int oldIndent = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; - int parameterIndex = EditorGUI.Popup(popupRect, "", -1, dropDownElements.Length > 0 ? dropDownElements : new string[] { kEmptyDropDownElement }, EditorStyles.textFieldDropDown); - if (EditorGUI.EndChangeCheck() && dropDownElements.Length > 0) - { - text = dropDownElements[parameterIndex]; - } - EditorGUI.indentLevel = oldIndent; - return text; - } - } -} diff --git a/Editor/Mono/GUI/Toolbar.cs b/Editor/Mono/GUI/Toolbar.cs deleted file mode 100644 index 22ab68cacf..0000000000 --- a/Editor/Mono/GUI/Toolbar.cs +++ /dev/null @@ -1,656 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; -using UnityEditor.Connect; -using UnityEditorInternal; -using UnityEngine.Experimental.UIElements; -using UnityEditor.Collaboration; -using UnityEditor.Web; - -namespace UnityEditor -{ - class Toolbar : GUIView - { - void InitializeToolIcons() - { - if (s_ToolIcons != null) - return; - - s_ToolIcons = new GUIContent[] - { - EditorGUIUtility.TrIconContent("MoveTool", "Move Tool"), - EditorGUIUtility.TrIconContent("RotateTool", "Rotate Tool"), - EditorGUIUtility.TrIconContent("ScaleTool", "Scale Tool"), - EditorGUIUtility.TrIconContent("RectTool", "Rect Tool"), - EditorGUIUtility.TrIconContent("TransformTool", "Move, Rotate or Scale selected objects."), - EditorGUIUtility.IconContent("MoveTool On"), - EditorGUIUtility.IconContent("RotateTool On"), - EditorGUIUtility.IconContent("ScaleTool On"), - EditorGUIUtility.IconContent("RectTool On"), - EditorGUIUtility.IconContent("TransformTool On"), - }; - - string viewToolsTooltipText = "Hand Tool"; - - s_ViewToolIcons = new GUIContent[] - { - EditorGUIUtility.TrIconContent("ViewToolOrbit", viewToolsTooltipText), - EditorGUIUtility.TrIconContent("ViewToolMove", viewToolsTooltipText), - EditorGUIUtility.TrIconContent("ViewToolZoom", viewToolsTooltipText), - EditorGUIUtility.TrIconContent("ViewToolOrbit", viewToolsTooltipText), - EditorGUIUtility.TrIconContent("ViewToolOrbit", "Orbit the Scene view."), - EditorGUIUtility.TrIconContent("ViewToolOrbit On", viewToolsTooltipText), - EditorGUIUtility.TrIconContent("ViewToolMove On", viewToolsTooltipText), - EditorGUIUtility.TrIconContent("ViewToolZoom On", viewToolsTooltipText), - EditorGUIUtility.TrIconContent("ViewToolOrbit On"), - EditorGUIUtility.TrIconContent("ViewToolOrbit On", viewToolsTooltipText) - }; - - s_PivotIcons = new GUIContent[] - { - EditorGUIUtility.TrTextContentWithIcon("Center", "Toggle Tool Handle Position\n\nThe tool handle is placed at the center of the selection.", "ToolHandleCenter"), - EditorGUIUtility.TrTextContentWithIcon("Pivot", "Toggle Tool Handle Position\n\nThe tool handle is placed at the active object's pivot point.", "ToolHandlePivot"), - }; - - s_PivotRotation = new GUIContent[] - { - EditorGUIUtility.TrTextContentWithIcon("Local", "Toggle Tool Handle Rotation\n\nTool handles are in the active object's rotation.", "ToolHandleLocal"), - EditorGUIUtility.TrTextContentWithIcon("Global", "Toggle Tool Handle Rotation\n\nTool handles are in global rotation.", "ToolHandleGlobal") - }; - - s_LayerContent = EditorGUIUtility.TrTextContent("Layers", "Which layers are visible in the Scene views."); - - s_PlayIcons = new GUIContent[] - { - EditorGUIUtility.TrIconContent("PlayButton", "Play"), - EditorGUIUtility.TrIconContent("PauseButton", "Pause"), - EditorGUIUtility.TrIconContent("StepButton", "Step"), - EditorGUIUtility.TrIconContent("PlayButtonProfile", "Profiler Play"), - EditorGUIUtility.IconContent("PlayButton On"), - EditorGUIUtility.IconContent("PauseButton On"), - EditorGUIUtility.IconContent("StepButton On"), - EditorGUIUtility.IconContent("PlayButtonProfile On") - }; - - s_CloudIcon = EditorGUIUtility.IconContent("CloudConnect"); - s_AccountContent = EditorGUIUtility.TrTextContent("Account"); - - - // Must match enum CollabToolbarState - s_CollabIcons = new GUIContent[] - { - EditorGUIUtility.TrTextContentWithIcon("Collab", " You need to enable collab.", "CollabNew"), - EditorGUIUtility.TrTextContentWithIcon("Collab", " You are up to date.", "Collab"), - EditorGUIUtility.TrTextContentWithIcon("Collab", " Please fix your conflicts prior to publishing.", "CollabConflict"), - EditorGUIUtility.TrTextContentWithIcon("Collab", " Last operation failed. Please retry later.", "CollabError"), - EditorGUIUtility.TrTextContentWithIcon("Collab", " Please update, there are server changes.", "CollabPull"), - EditorGUIUtility.TrTextContentWithIcon("Collab", " You have files to publish.", "CollabPush"), - EditorGUIUtility.TrTextContentWithIcon("Collab", " Operation in progress.", "CollabProgress"), - EditorGUIUtility.TrTextContentWithIcon("Collab", " Collab is disabled.", "CollabNew"), - EditorGUIUtility.TrTextContentWithIcon("Collab", " Please check your network connection.", "CollabNew") - }; - } - - static GUIContent[] s_ToolIcons; - static readonly string[] s_ToolControlNames = new[] - { - "ToolbarPersistentToolsPan", - "ToolbarPersistentToolsTranslate", - "ToolbarPersistentToolsRotate", - "ToolbarPersistentToolsScale", - "ToolbarPersistentToolsRect", - "ToolbarPersistentToolsTransform", - }; - static GUIContent[] s_ViewToolIcons; - static GUIContent[] s_PivotIcons; - static GUIContent[] s_PivotRotation; - static GUIContent s_LayerContent; - static GUIContent[] s_PlayIcons; - private static GUIContent s_AccountContent; - static GUIContent s_CloudIcon; - // Must match s_CollabIcon array - enum CollabToolbarState - { - NeedToEnableCollab, - UpToDate, - Conflict, - OperationError, - ServerHasChanges, - FilesToPush, - InProgress, - Disabled, - Offline - } - - CollabToolbarState m_CollabToolbarState = CollabToolbarState.UpToDate; - static GUIContent[] s_CollabIcons; - const float kCollabButtonWidth = 78.0f; - ButtonWithAnimatedIconRotation m_CollabButton; - string m_DynamicTooltip; - static bool m_ShowCollabTooltip = false; - - GUIContent currentCollabContent - { - get - { - GUIContent content = new GUIContent(s_CollabIcons[(int)m_CollabToolbarState]); - if (!m_ShowCollabTooltip) - { - content.tooltip = null; - } - else if (m_DynamicTooltip != "") - { - content.tooltip = m_DynamicTooltip; - } - - if (Collab.instance.AreTestsRunning()) - { - content.text = "CTF"; - } - - return content; - } - } - - static class Styles - { - public readonly static GUIStyle collabButtonStyle = new GUIStyle("Dropdown") { padding = { left = 24 } }; // move text to make room for rotating icon - public static readonly GUIStyle dropdown = "Dropdown"; - public static readonly GUIStyle appToolbar = "AppToolbar"; - } - - protected override void OnEnable() - { - base.OnEnable(); - // Disable clipping on the root element to fix case 931831 - visualTree.clippingOptions = VisualElement.ClippingOptions.NoClipping; - EditorApplication.modifierKeysChanged += Repaint; - // when undo or redo is done, we need to reset global tools rotation - Undo.undoRedoPerformed += OnSelectionChange; - - UnityConnect.instance.StateChanged += OnUnityConnectStateChanged; - UnityConnect.instance.UserStateChanged += OnUnityConnectUserStateChanged; - - get = this; - Collab.instance.StateChanged += OnCollabStateChanged; - - if (m_CollabButton == null) - { - const int repaintsPerSecond = 20; - const float animSpeed = 500f; - const bool mouseDownButton = true; - m_CollabButton = new ButtonWithAnimatedIconRotation(() => (float)EditorApplication.timeSinceStartup * animSpeed, Repaint, repaintsPerSecond, mouseDownButton); - } - } - - protected override void OnDisable() - { - base.OnDisable(); - EditorApplication.modifierKeysChanged -= Repaint; - Undo.undoRedoPerformed -= OnSelectionChange; - UnityConnect.instance.StateChanged -= OnUnityConnectStateChanged; - UnityConnect.instance.UserStateChanged -= OnUnityConnectUserStateChanged; - - Collab.instance.StateChanged -= OnCollabStateChanged; - - if (m_CollabButton != null) - m_CollabButton.Clear(); - } - - // The actual array we display. We build this every frame to make sure it looks correct i.r.t. selection :) - static GUIContent[] s_ShownToolIcons = { null, null, null, null, null, null }; - - public static Toolbar get = null; - public static bool requestShowCollabToolbar = false; - - internal static string lastLoadedLayoutName - { - get - { - return string.IsNullOrEmpty(get.m_LastLoadedLayoutName) ? "Layout" : get.m_LastLoadedLayoutName; - } - set - { - get.m_LastLoadedLayoutName = value; - get.Repaint(); - } - } - [SerializeField] - private string m_LastLoadedLayoutName; - - override protected bool OnFocus() - { - return false; - } - - void OnSelectionChange() - { - Tools.OnSelectionChange(); - Repaint(); - } - - - protected void OnUnityConnectStateChanged(ConnectInfo state) - { - UpdateCollabToolbarState(); - RepaintToolbar(); - } - - protected void OnUnityConnectUserStateChanged(UserInfo state) - { - UpdateCollabToolbarState(); - } - - - Rect GetThinArea(Rect pos) - { - return new Rect(pos.x, 7, pos.width, 18); - } - - Rect GetThickArea(Rect pos) - { - return new Rect(pos.x, 5, pos.width, 24); - } - - void ReserveWidthLeft(float width, ref Rect pos) - { - pos.x -= width; - pos.width = width; - } - - void ReserveWidthRight(float width, ref Rect pos) - { - pos.x += pos.width; - pos.width = width; - } - - void ReserveRight(float width, ref Rect pos) - { - pos.x += width; - } - - void ReserveBottom(float height, ref Rect pos) - { - pos.y += height; - } - - protected override void OldOnGUI() - { - float space = 10; - float largeSpace = 20; - float standardButtonWidth = 32; - float pivotButtonWidth = 64; - float dropdownWidth = 80; - - InitializeToolIcons(); - - bool isOrWillEnterPlaymode = EditorApplication.isPlayingOrWillChangePlaymode; - if (isOrWillEnterPlaymode) - GUI.color = HostView.kPlayModeDarken; - - if (Event.current.type == EventType.Repaint) - Styles.appToolbar.Draw(new Rect(0, 0, position.width, position.height), false, false, false, false); - - // Position left aligned controls controls - start from left to right. - Rect pos = new Rect(0, 0, 0, 0); - - ReserveWidthRight(space, ref pos); - - ReserveWidthRight(standardButtonWidth * s_ShownToolIcons.Length, ref pos); - DoToolButtons(GetThickArea(pos)); - - ReserveWidthRight(largeSpace, ref pos); - - ReserveWidthRight(pivotButtonWidth * 2, ref pos); - DoPivotButtons(GetThinArea(pos)); - - // Position centered controls. - float playPauseStopWidth = 100; - pos = new Rect(Mathf.RoundToInt((position.width - playPauseStopWidth) / 2), 0, 140, 0); - - GUILayout.BeginArea(GetThickArea(pos)); - GUILayout.BeginHorizontal(); - { - DoPlayButtons(isOrWillEnterPlaymode); - } - GUILayout.EndHorizontal(); - GUILayout.EndArea(); - - // Position right aligned controls controls - start from right to left. - pos = new Rect(position.width, 0, 0, 0); - - // Right spacing side - ReserveWidthLeft(space, ref pos); - - ReserveWidthLeft(dropdownWidth, ref pos); - DoLayoutDropDown(GetThinArea(pos)); - - ReserveWidthLeft(space, ref pos); - - ReserveWidthLeft(dropdownWidth, ref pos); - DoLayersDropDown(GetThinArea(pos)); - - ReserveWidthLeft(largeSpace, ref pos); - - ReserveWidthLeft(dropdownWidth, ref pos); - if (EditorGUI.DropdownButton(GetThinArea(pos), s_AccountContent, FocusType.Passive, Styles.dropdown)) - { - ShowUserMenu(GetThinArea(pos)); - } - - - ReserveWidthLeft(space, ref pos); - - ReserveWidthLeft(32, ref pos); - if (GUI.Button(GetThinArea(pos), s_CloudIcon)) - UnityConnectServiceCollection.instance.ShowService(HubAccess.kServiceName, true, "cloud_icon"); // Should show hub when it's done - - ReserveWidthLeft(space, ref pos); - ReserveWidthLeft(kCollabButtonWidth, ref pos); - DoCollabDropDown(GetThinArea(pos)); - - - EditorGUI.ShowRepaints(); - Highlighter.ControlHighlightGUI(this); - } - - void ShowUserMenu(Rect dropDownRect) - { - var menu = new GenericMenu(); - if (!UnityConnect.instance.online) - { - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Go to account")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Sign in...")); - - if (!Application.HasProLicense()) - { - menu.AddSeparator(""); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Upgrade to Pro")); - } - } - else - { - string accountUrl = UnityConnect.instance.GetConfigurationURL(CloudConfigUrl.CloudPortal); - if (UnityConnect.instance.loggedIn) - menu.AddItem(EditorGUIUtility.TrTextContent("Go to account"), false, () => UnityConnect.instance.OpenAuthorizedURLInWebBrowser(accountUrl)); - else - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Go to account")); - - if (UnityConnect.instance.loggedIn) - { - string name = "Sign out " + UnityConnect.instance.userInfo.displayName; - menu.AddItem(new GUIContent(name), false, () => {UnityConnect.instance.Logout(); }); - } - else - menu.AddItem(EditorGUIUtility.TrTextContent("Sign in..."), false, () => {UnityConnect.instance.ShowLogin(); }); - - if (!Application.HasProLicense()) - { - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Upgrade to Pro"), false, () => Application.OpenURL("https://store.unity3d.com/")); - } - } - - menu.DropDown(dropDownRect); - } - - - void DoToolButtons(Rect rect) - { - // Handle temporary override with ALT - GUI.changed = false; - - int displayTool = Tools.viewToolActive ? 0 : (int)Tools.current; - - // Change the icon to match the correct view tool - for (int i = 1; i < s_ShownToolIcons.Length; i++) - { - s_ShownToolIcons[i] = s_ToolIcons[i - 1 + (i == displayTool ? s_ShownToolIcons.Length - 1 : 0)]; - s_ShownToolIcons[i].tooltip = s_ToolIcons[i - 1].tooltip; - } - s_ShownToolIcons[0] = s_ViewToolIcons[(int)Tools.viewTool + (displayTool == 0 ? s_ShownToolIcons.Length - 1 : 0)]; - - displayTool = GUI.Toolbar(rect, displayTool, s_ShownToolIcons, s_ToolControlNames, "Command", GUI.ToolbarButtonSize.FitToContents); - if (GUI.changed) - { - Tools.current = (Tool)displayTool; - Tools.ResetGlobalHandleRotation(); - } - } - - void DoPivotButtons(Rect rect) - { - GUI.SetNextControlName("ToolbarToolPivotPositionButton"); - Tools.pivotMode = (PivotMode)EditorGUI.CycleButton(new Rect(rect.x, rect.y, rect.width / 2, rect.height), (int)Tools.pivotMode, s_PivotIcons, "ButtonLeft"); - if (Tools.current == Tool.Scale && Selection.transforms.Length < 2) - GUI.enabled = false; - GUI.SetNextControlName("ToolbarToolPivotOrientationButton"); - PivotRotation tempPivot = (PivotRotation)EditorGUI.CycleButton(new Rect(rect.x + rect.width / 2, rect.y, rect.width / 2, rect.height), (int)Tools.pivotRotation, s_PivotRotation, "ButtonRight"); - if (Tools.pivotRotation != tempPivot) - { - Tools.pivotRotation = tempPivot; - if (tempPivot == PivotRotation.Global) - Tools.ResetGlobalHandleRotation(); - } - - if (Tools.current == Tool.Scale) - GUI.enabled = true; - - if (GUI.changed) - Tools.RepaintAllToolViews(); - } - - void DoPlayButtons(bool isOrWillEnterPlaymode) - { - // Enter / Exit Playmode - bool isPlaying = EditorApplication.isPlaying; - GUI.changed = false; - - int buttonOffset = isPlaying ? 4 : 0; - - Color c = GUI.color + new Color(.01f, .01f, .01f, .01f); - GUI.contentColor = new Color(1.0f / c.r, 1.0f / c.g, 1.0f / c.g, 1.0f / c.a); - GUI.SetNextControlName("ToolbarPlayModePlayButton"); - GUILayout.Toggle(isOrWillEnterPlaymode, s_PlayIcons[buttonOffset], "CommandLeft"); - GUI.backgroundColor = Color.white; - if (GUI.changed) - { - TogglePlaying(); - GUIUtility.ExitGUI(); - } - - // Pause game - GUI.changed = false; - - GUI.SetNextControlName("ToolbarPlayModePauseButton"); - bool isPaused = GUILayout.Toggle(EditorApplication.isPaused, s_PlayIcons[buttonOffset + 1], "CommandMid"); - if (GUI.changed) - { - EditorApplication.isPaused = isPaused; - GUIUtility.ExitGUI(); - } - - // Step playmode - GUI.SetNextControlName("ToolbarPlayModeStepButton"); - if (GUILayout.Button(s_PlayIcons[buttonOffset + 2], "CommandRight")) - { - EditorApplication.Step(); - GUIUtility.ExitGUI(); - } - - } - - void DoLayersDropDown(Rect rect) - { - GUIStyle dropStyle = "DropDown"; - if (EditorGUI.DropdownButton(rect, s_LayerContent, FocusType.Passive, dropStyle)) - { - if (LayerVisibilityWindow.ShowAtPosition(rect)) - { - GUIUtility.ExitGUI(); - } - } - } - - void DoLayoutDropDown(Rect rect) - { - // Layout DropDown - if (EditorGUI.DropdownButton(rect, GUIContent.Temp(lastLoadedLayoutName), FocusType.Passive, "DropDown")) - { - Vector2 temp = GUIUtility.GUIToScreenPoint(new Vector2(rect.x, rect.y)); - rect.x = temp.x; - rect.y = temp.y; - EditorUtility.Internal_DisplayPopupMenu(rect, "Window/Layouts", this, 0); - } - } - - void ShowPopup(Rect rect) - { - // window should be centered on the button - ReserveRight(kCollabButtonWidth / 2, ref rect); - ReserveBottom(5, ref rect); - // calculate screen rect before saving assets since it might open the AssetSaveDialog window - var screenRect = GUIUtility.GUIToScreenRect(rect); - // save all the assets - AssetDatabase.SaveAssets(); - if (CollabToolbarWindow.ShowCenteredAtPosition(screenRect)) - { - GUIUtility.ExitGUI(); - } - } - - void DoCollabDropDown(Rect rect) - { - UpdateCollabToolbarState(); - bool showPopup = requestShowCollabToolbar; - requestShowCollabToolbar = false; - - bool enable = !EditorApplication.isPlaying; - - using (new EditorGUI.DisabledScope(!enable)) - { - bool animate = m_CollabToolbarState == CollabToolbarState.InProgress; - - EditorGUIUtility.SetIconSize(new Vector2(12, 12)); - if (m_CollabButton.OnGUI(rect, currentCollabContent, animate, Styles.collabButtonStyle)) - { - showPopup = true; - } - EditorGUIUtility.SetIconSize(Vector2.zero); - } - - if (showPopup) - { - ShowPopup(rect); - } - } - - public void OnCollabStateChanged(CollabInfo info) - { - UpdateCollabToolbarState(); - } - - public void UpdateCollabToolbarState() - { - var currentCollabState = CollabToolbarState.UpToDate; - bool networkAvailable = UnityConnect.instance.connectInfo.online && UnityConnect.instance.connectInfo.loggedIn; - m_DynamicTooltip = ""; - - if (networkAvailable) - { - Collab collab = Collab.instance; - CollabInfo currentInfo = collab.collabInfo; - int errorCode = 0; - int errorPriority = (int)UnityConnect.UnityErrorPriority.None; - int errorBehaviour = (int)UnityConnect.UnityErrorBehaviour.Hidden; - string errorMsg = ""; - string errorShortMsg = ""; - bool error = false; - if (collab.GetError((int)(UnityConnect.UnityErrorFilter.ByContext | UnityConnect.UnityErrorFilter.ByChild), out errorCode, out errorPriority, out errorBehaviour, out errorMsg, out errorShortMsg)) - { - error = (errorPriority <= (int)UnityConnect.UnityErrorPriority.Error); - m_DynamicTooltip = errorShortMsg; - } - - if (!currentInfo.ready) - { - currentCollabState = CollabToolbarState.InProgress; - } - else if (error) - { - currentCollabState = CollabToolbarState.OperationError; - } - else if (currentInfo.inProgress) - { - currentCollabState = CollabToolbarState.InProgress; - } - else - { - bool collabEnable = Collab.instance.IsCollabEnabledForCurrentProject(); - - if (UnityConnect.instance.projectInfo.projectBound == false || !collabEnable) - { - currentCollabState = CollabToolbarState.NeedToEnableCollab; - } - else if (currentInfo.update) - { - currentCollabState = CollabToolbarState.ServerHasChanges; - } - else if (currentInfo.conflict) - { - currentCollabState = CollabToolbarState.Conflict; - } - else if (currentInfo.publish) - { - currentCollabState = CollabToolbarState.FilesToPush; - } - } - } - else - { - currentCollabState = CollabToolbarState.Offline; - } - - if (currentCollabState != m_CollabToolbarState || - CollabToolbarWindow.s_ToolbarIsVisible == m_ShowCollabTooltip) - { - m_CollabToolbarState = currentCollabState; - m_ShowCollabTooltip = !CollabToolbarWindow.s_ToolbarIsVisible; - RepaintToolbar(); - } - } - - - // Repaints all views, called from C++ when playmode entering is aborted - // and when the user clicks on the playmode button. - static void InternalWillTogglePlaymode() - { - InternalEditorUtility.RepaintAllViews(); - } - - static void TogglePlaying() - { - bool willPlay = !EditorApplication.isPlaying; - EditorApplication.isPlaying = willPlay; - - InternalWillTogglePlaymode(); - } - - static internal void RepaintToolbar() - { - if (get != null) - get.Repaint(); - } - - public float CalcHeight() - { - return 30; - } - } -} // namespace diff --git a/Editor/Mono/GUI/Tools/BuiltinTools.cs b/Editor/Mono/GUI/Tools/BuiltinTools.cs deleted file mode 100644 index d5cb52cd04..0000000000 --- a/Editor/Mono/GUI/Tools/BuiltinTools.cs +++ /dev/null @@ -1,978 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal abstract class ManipulationTool - { - protected virtual void OnToolGUI(SceneView view) - { - if (!Selection.activeTransform || Tools.s_Hidden) - return; - - bool isStatic = (!Tools.s_Hidden && EditorApplication.isPlaying && GameObjectUtility.ContainsStatic(Selection.gameObjects)); - using (new EditorGUI.DisabledScope(isStatic)) - { - Vector3 handlePosition = Tools.handlePosition; - - ToolGUI(view, handlePosition, isStatic); - - Handles.ShowStaticLabelIfNeeded(handlePosition); - } - } - - public abstract void ToolGUI(SceneView view, Vector3 handlePosition, bool isStatic); - } - - internal class ManipulationToolUtility - { - public static Vector3 minDragDifference { get; set; } - public static void SetMinDragDifferenceForPos(Vector3 position) - { - minDragDifference = Vector3.one * (HandleUtility.GetHandleSize(position) / 80f); - } - - public static void SetMinDragDifferenceForPos(Vector3 position, float multiplier) - { - minDragDifference = Vector3.one * (HandleUtility.GetHandleSize(position) * multiplier / 80f); - } - - public static void DisableMinDragDifference() - { - minDragDifference = Vector3.zero; - } - - public static void DisableMinDragDifferenceForAxis(int axis) - { - Vector2 diff = minDragDifference; - diff[axis] = 0; - minDragDifference = diff; - } - - public static void DisableMinDragDifferenceBasedOnSnapping(Vector3 positionBeforeSnapping, Vector3 positionAfterSnapping) - { - for (int axis = 0; axis < 3; axis++) - if (positionBeforeSnapping[axis] != positionAfterSnapping[axis]) - DisableMinDragDifferenceForAxis(axis); - } - - public delegate void HandleDragChange(string handleName, bool dragging); - public static HandleDragChange handleDragChange; - public static void BeginDragging(string handleName) - { - if (handleDragChange != null) - handleDragChange(handleName, true); - } - - public static void EndDragging(string handleName) - { - if (handleDragChange != null) - handleDragChange(handleName, false); - } - - public static void DetectDraggingBasedOnMouseDownUp(string handleName, EventType typeBefore) - { - if (typeBefore == EventType.MouseDrag && Event.current.type != EventType.MouseDrag) - BeginDragging(handleName); - else if (typeBefore == EventType.MouseUp && Event.current.type != EventType.MouseUp) - EndDragging(handleName); - } - } - - internal class TransformTool : ManipulationTool - { - static TransformTool s_Instance; - static Vector3 s_Scale; - - public static void OnGUI(SceneView view) - { - if (s_Instance == null) - s_Instance = new TransformTool(); - s_Instance.OnToolGUI(view); - } - - public override void ToolGUI(SceneView view, Vector3 handlePosition, bool isStatic) - { - var ids = Handles.TransformHandleIds.Default; - TransformManipulator.BeginManipulationHandling(false); - - // Lock position when scaling or rotating - if (ids.scale.Has(GUIUtility.hotControl) - || ids.rotation.Has(GUIUtility.hotControl)) - Tools.LockHandlePosition(); - else - Tools.UnlockHandlePosition(); - - EditorGUI.BeginChangeCheck(); - - if (Event.current.type == EventType.MouseDown) - s_Scale = Vector3.one; - - var startPosition = handlePosition; - var endPosition = startPosition; - var startRotation = Tools.handleRotation; - var endRotation = startRotation; - var startScale = s_Scale; - var endScale = startScale; - Handles.TransformHandle(ids, ref endPosition, ref endRotation, ref endScale, Handles.TransformHandleParam.Default); - s_Scale = endScale; - - if (EditorGUI.EndChangeCheck() && !isStatic) - { - Undo.RecordObjects(Selection.transforms, "Transform Manipulation"); - - if (TransformManipulator.HandleHasMoved(endPosition)) - { - ManipulationToolUtility.SetMinDragDifferenceForPos(handlePosition); - TransformManipulator.SetPositionDelta(endPosition, TransformManipulator.mouseDownHandlePosition); - } - - Quaternion deltaRotation = Quaternion.Inverse(startRotation) * endRotation; - float angle; - Vector3 axis; - deltaRotation.ToAngleAxis(out angle, out axis); - if (!Mathf.Approximately(angle, 0)) - { - foreach (Transform t in Selection.transforms) - { - // Rotate around handlePosition (Global or Local axis). - if (Tools.pivotMode == PivotMode.Center) - t.RotateAround(handlePosition, startRotation * axis, angle); - // Local rotation (Pivot mode with Local axis). - else if (TransformManipulator.individualSpace) - t.Rotate(t.rotation * axis, angle, Space.World); - // Pivot mode with Global axis. - else - t.Rotate(startRotation * axis, angle, Space.World); - - // sync euler hints after a rotate tool update tyo fake continuous rotation - t.SetLocalEulerHint(t.GetLocalEulerAngles(t.rotationOrder)); - - if (t.parent != null) - t.SendTransformChangedScale(); // force scale update, needed if tr has non-uniformly scaled parent. - } - Tools.handleRotation = endRotation; - } - - if (endScale != startScale) - TransformManipulator.SetScaleDelta(endScale, endRotation); - } - TransformManipulator.EndManipulationHandling(); - } - } - - internal class MoveTool : ManipulationTool - { - private static MoveTool s_Instance; - public static void OnGUI(SceneView view) - { - if (s_Instance == null) - s_Instance = new MoveTool(); - s_Instance.OnToolGUI(view); - } - - public override void ToolGUI(SceneView view, Vector3 handlePosition, bool isStatic) - { - TransformManipulator.BeginManipulationHandling(false); - EditorGUI.BeginChangeCheck(); - - // The AimConstraint changes the rotation of the active object as the object is moved around in the scene. - // This leads to very large "jumps" of the object, - // as the move tool assumes the handle rotation to not change while the object is dragged. - // Solution: when moving an object constrained with the AimConstraint, we ignore the rotation of the object. - Quaternion handleRotation = Tools.handleRotation; - var aimConstraintComponent = Selection.activeTransform.GetComponent(); - if (aimConstraintComponent != null && aimConstraintComponent.constraintActive) - handleRotation = TransformManipulator.mouseDownHandleRotation; - - Vector3 pos2 = Handles.PositionHandle(handlePosition, handleRotation); - if (EditorGUI.EndChangeCheck() && !isStatic && TransformManipulator.HandleHasMoved(pos2)) - { - ManipulationToolUtility.SetMinDragDifferenceForPos(handlePosition); - - if (Tools.vertexDragging) - ManipulationToolUtility.DisableMinDragDifference(); - - TransformManipulator.SetPositionDelta(pos2, TransformManipulator.mouseDownHandlePosition); - } - TransformManipulator.EndManipulationHandling(); - } - } - - internal class RotateTool : ManipulationTool - { - private static RotateTool s_Instance; - public static void OnGUI(SceneView view) - { - if (s_Instance == null) - s_Instance = new RotateTool(); - s_Instance.OnToolGUI(view); - } - - public override void ToolGUI(SceneView view, Vector3 handlePosition, bool isStatic) - { - Quaternion before = Tools.handleRotation; - - EditorGUI.BeginChangeCheck(); - Quaternion after = Handles.RotationHandle(before, handlePosition); - - if (EditorGUI.EndChangeCheck() && !isStatic) - { - Quaternion delta = Quaternion.Inverse(before) * after; - float angle; - Vector3 axis; - delta.ToAngleAxis(out angle, out axis); - - Undo.RecordObjects(Selection.transforms, "Rotate"); - foreach (Transform t in Selection.transforms) - { - // Rotate around handlePosition (Global or Local axis). - if (Tools.pivotMode == PivotMode.Center) - { - t.RotateAround(handlePosition, before * axis, angle); - } - // Local rotation (Pivot mode with Local axis). - else if (TransformManipulator.individualSpace) - { - t.Rotate(t.rotation * axis, angle, Space.World); - } - // Pivot mode with Global axis. - else - { - t.Rotate(before * axis, angle, Space.World); - } - - // sync euler hints after a rotate tool update tyo fake continuous rotation - t.SetLocalEulerHint(t.GetLocalEulerAngles(t.rotationOrder)); - - if (t.parent != null) - t.SendTransformChangedScale(); // force scale update, needed if tr has non-uniformly scaled parent. - } - Tools.handleRotation = after; - } - } - } - - internal class ScaleTool : ManipulationTool - { - private static ScaleTool s_Instance; - public static void OnGUI(SceneView view) - { - if (s_Instance == null) - s_Instance = new ScaleTool(); - s_Instance.OnToolGUI(view); - } - - private static Vector3 s_CurrentScale = Vector3.one; - - public override void ToolGUI(SceneView view, Vector3 handlePosition, bool isStatic) - { - // Allow global space scaling for multi-selection but not for a single object - Quaternion handleRotation = Selection.transforms.Length > 1 ? - Tools.handleRotation : Tools.handleLocalRotation; - - TransformManipulator.DebugAlignment(handleRotation); - - if (Event.current.type == EventType.MouseDown) - s_CurrentScale = Vector3.one; - - EditorGUI.BeginChangeCheck(); - - TransformManipulator.BeginManipulationHandling(true); - s_CurrentScale = Handles.ScaleHandle(s_CurrentScale, handlePosition, handleRotation, HandleUtility.GetHandleSize(handlePosition)); - TransformManipulator.EndManipulationHandling(); - - if (EditorGUI.EndChangeCheck() && !isStatic) - { - TransformManipulator.SetScaleDelta(s_CurrentScale, handleRotation); - } - } - } - - internal class RectTool : ManipulationTool - { - private static RectTool s_Instance; - - internal const string kChangingLeft = "ChangingLeft"; - internal const string kChangingRight = "ChangingRight"; - internal const string kChangingTop = "ChangingTop"; - internal const string kChangingBottom = "ChangingBottom"; - internal const string kChangingPosX = "ChangingPosX"; - internal const string kChangingPosY = "ChangingPosY"; - internal const string kChangingWidth = "ChangingWidth"; - internal const string kChangingHeight = "ChangingHeight"; - internal const string kChangingPivot = "ChangingPivot"; - - const float kMinVisibleSize = 0.2f; - - public static void OnGUI(SceneView view) - { - if (s_Instance == null) - s_Instance = new RectTool(); - s_Instance.OnToolGUI(view); - } - - public static Vector2 GetLocalRectPoint(Rect rect, int index) - { - switch (index) - { - case (0): return new Vector2(rect.xMin, rect.yMax); - case (1): return new Vector2(rect.xMax, rect.yMax); - case (2): return new Vector2(rect.xMax, rect.yMin); - case (3): return new Vector2(rect.xMin, rect.yMin); - } - return Vector3.zero; - } - - public override void ToolGUI(SceneView view, Vector3 handlePosition, bool isStatic) - { - Rect rect = Tools.handleRect; - Quaternion rectRotation = Tools.handleRectRotation; - - // Draw rect - Vector3[] verts = new Vector3[4]; - for (int i = 0; i < 4; i++) - { - Vector3 pos = GetLocalRectPoint(rect, i); - verts[i] = rectRotation * pos + handlePosition; - } - RectHandles.RenderRectWithShadow(false, verts); - - // Handle fading - Color oldColor = GUI.color; - float faded = 1; - if (Camera.current) - { - Vector3 viewDir = Camera.current.orthographic ? - Camera.current.transform.forward : - (handlePosition + rectRotation * rect.center - Camera.current.transform.position); - Vector3 rectRight = rectRotation * Vector3.right * rect.width; - Vector3 rectUp = rectRotation * Vector3.up * rect.height; - float visibleSize = Mathf.Sqrt(Vector3.Cross(Vector3.ProjectOnPlane(rectRight, viewDir), Vector3.ProjectOnPlane(rectUp, viewDir)).magnitude); - visibleSize /= HandleUtility.GetHandleSize(handlePosition); - faded = Mathf.Clamp01((visibleSize - kMinVisibleSize) / kMinVisibleSize * 2); - Color fadedColor = oldColor; - fadedColor.a *= faded; - GUI.color = fadedColor; - } - - Vector3 oldPivot = Tools.GetHandlePosition(); - - // Pivot handle - if (!Tools.vertexDragging) - { - RectTransform rectTransform = Selection.activeTransform.GetComponent(); - bool groupPivot = Selection.transforms.Length > 1; - bool rectTransformPivot = !groupPivot && Tools.pivotMode == PivotMode.Pivot && rectTransform != null; - using (new EditorGUI.DisabledScope(!groupPivot && !rectTransformPivot)) - { - EditorGUI.BeginChangeCheck(); - Vector3 newPivot = PivotHandleGUI(rect, oldPivot, rectRotation); - if (EditorGUI.EndChangeCheck() && !isStatic) - { - if (groupPivot) - { - Tools.localHandleOffset += Quaternion.Inverse(Tools.handleRotation) * (newPivot - oldPivot); - } - else if (rectTransformPivot) - { - Transform tr = Selection.activeTransform; - Undo.RecordObject(rectTransform, "Move Rectangle Pivot"); - Transform space = Tools.rectBlueprintMode && UnityEditorInternal.InternalEditorUtility.SupportsRectLayout(tr) ? tr.parent : tr; - Vector2 offset = space.InverseTransformVector(newPivot - oldPivot); - offset.x /= rectTransform.rect.width; - offset.y /= rectTransform.rect.height; - Vector2 pivot = rectTransform.pivot + offset; - - RectTransformEditor.SetPivotSmart(rectTransform, pivot.x, 0, true, space != rectTransform.transform); - RectTransformEditor.SetPivotSmart(rectTransform, pivot.y, 1, true, space != rectTransform.transform); - } - } - } - } - - TransformManipulator.BeginManipulationHandling(true); - if (!Tools.vertexDragging) - { - // Resize handles - EditorGUI.BeginChangeCheck(); - Vector3 scalePivot = handlePosition; - Vector3 scale = ResizeHandlesGUI(rect, handlePosition, rectRotation, out scalePivot); - if (EditorGUI.EndChangeCheck() && !isStatic) - { - TransformManipulator.SetResizeDelta(scale, scalePivot, rectRotation); - } - - bool enableRotation = true; - if (Tools.rectBlueprintMode) - { - foreach (Transform t in Selection.transforms) - { - if (t.GetComponent() != null) - enableRotation = false; - } - } - - if (enableRotation) - { - // Rotation handles - EditorGUI.BeginChangeCheck(); - Quaternion after = RotationHandlesGUI(rect, handlePosition, rectRotation); - if (EditorGUI.EndChangeCheck() && !isStatic) - { - Quaternion delta = Quaternion.Inverse(rectRotation) * after; - float angle; - Vector3 axis; - delta.ToAngleAxis(out angle, out axis); - axis = rectRotation * axis; - - Undo.RecordObjects(Selection.transforms, "Rotate"); - foreach (Transform t in Selection.transforms) - { - t.RotateAround(handlePosition, axis, angle); - - // sync euler hints after a rotate tool update tyo fake continuous rotation - t.SetLocalEulerHint(t.GetLocalEulerAngles(t.rotationOrder)); - - if (t.parent != null) - t.SendTransformChangedScale(); // force scale update, needed if transform has non-uniformly scaled parent. - } - Tools.handleRotation = Quaternion.AngleAxis(angle, axis) * Tools.handleRotation; - } - } - } - TransformManipulator.EndManipulationHandling(); - - TransformManipulator.BeginManipulationHandling(false); - // Move handle - EditorGUI.BeginChangeCheck(); - Vector3 newPos = MoveHandlesGUI(rect, handlePosition, rectRotation); - if (EditorGUI.EndChangeCheck() && !isStatic) - { - if (GridSnapping.active) - newPos = GridSnapping.Snap(newPos); - - if (TransformManipulator.HandleHasMoved(newPos)) - TransformManipulator.SetPositionDelta(newPos, TransformManipulator.mouseDownHandlePosition); - } - TransformManipulator.EndManipulationHandling(); - - GUI.color = oldColor; - } - - private static int s_ResizeHandlesHash = "ResizeHandles".GetHashCode(); - private static int s_RotationHandlesHash = "RotationHandles".GetHashCode(); - private static int s_MoveHandleHash = "MoveHandle".GetHashCode(); - private static int s_PivotHandleHash = "PivotHandle".GetHashCode(); - private static Rect s_StartRect = new Rect(); - - private static Vector3 GetRectPointInWorld(Rect rect, Vector3 pivot, Quaternion rotation, int xHandle, int yHandle) - { - Vector3 pos = new Vector2( - pos.x = Mathf.Lerp(rect.xMin, rect.xMax, xHandle * 0.5f), - pos.y = Mathf.Lerp(rect.yMin, rect.yMax, yHandle * 0.5f)); - return rotation * pos + pivot; - } - - static Vector3 ResizeHandlesGUI(Rect rect, Vector3 pivot, Quaternion rotation, out Vector3 scalePivot) - { - if (Event.current.type == EventType.MouseDown) - s_StartRect = rect; - - scalePivot = pivot; - Vector3 scale = Vector3.one; - - Quaternion inverseRotation = Quaternion.Inverse(rotation); - // Loop through the 8 handles (sides and corners) using a nested loop. - // (The loop covers 9 combinations, but the center position is ignored.) - for (int xHandle = 0; xHandle <= 2; xHandle++) - { - for (int yHandle = 0; yHandle <= 2; yHandle++) - { - // Ignore center - if (xHandle == 1 && yHandle == 1) - continue; - - Vector3 origPos = GetRectPointInWorld(s_StartRect, pivot, rotation, xHandle, yHandle); - Vector3 curPos = GetRectPointInWorld(rect, pivot, rotation, xHandle, yHandle); - - float size = 0.05f * HandleUtility.GetHandleSize(curPos); - int id = GUIUtility.GetControlID(s_ResizeHandlesHash, FocusType.Passive); - if (GUI.color.a > 0 || GUIUtility.hotControl == id) - { - EditorGUI.BeginChangeCheck(); - Vector3 newPos; - - EventType typeBefore = Event.current.type; - - if (xHandle == 1 || yHandle == 1) - { - // Side resizer (1D) - Vector3 sideDir = (xHandle == 1 ? rotation * Vector3.right * rect.width : rotation * Vector3.up * rect.height); - Vector3 slideDir = (xHandle == 1 ? rotation * Vector3.up : rotation * Vector3.right); - newPos = RectHandles.SideSlider(id, curPos, sideDir, slideDir, size, null, 0); - } - else - { - // Corner handle (2D) - Vector3 outwardsA = rotation * Vector3.right * (xHandle - 1); - Vector3 outwardsB = rotation * Vector3.up * (yHandle - 1); - newPos = RectHandles.CornerSlider(id, curPos, rotation * Vector3.forward, outwardsA, outwardsB, size, RectHandles.RectScalingHandleCap, Vector2.zero); - } - - // Calculate snapping values if applicable - bool supportsRectSnapping = Selection.transforms.Length == 1 && - UnityEditorInternal.InternalEditorUtility.SupportsRectLayout(Selection.activeTransform) && - Selection.activeTransform.parent.rotation == rotation; - if (supportsRectSnapping) - { - Transform transform = Selection.activeTransform; - RectTransform rectTransform = transform.GetComponent(); - Transform transformParent = transform.parent; - RectTransform rectTransformParent = transformParent.GetComponent(); - if (typeBefore == EventType.MouseDown && Event.current.type != EventType.MouseDown) - RectTransformSnapping.CalculateOffsetSnapValues(transformParent, transform, rectTransformParent, rectTransform, xHandle, yHandle); - } - - if (EditorGUI.EndChangeCheck()) - { - // Resize handles require more fine grained rounding of values than other tools. - // With other tools, the slight rounding is not notizable as long as it's just sub-pixel, - // because the manipulated object is being moved at the same time. - // However, with resize handles, when dragging one edge or corner, - // the opposite is standing still, and even slight rounding can cause shaking/vibration. - // At a fraction of the normal rounding, the shaking is very unlikely to happen though. - ManipulationToolUtility.SetMinDragDifferenceForPos(curPos, 0.1f); - - if (supportsRectSnapping) - { - Transform transformParent = Selection.activeTransform.parent; - RectTransform rectParent = transformParent.GetComponent(); - - Vector2 snapSize = Vector2.one * HandleUtility.GetHandleSize(newPos) * RectTransformSnapping.kSnapThreshold; - snapSize.x /= (inverseRotation * transformParent.TransformVector(Vector3.right)).x; - snapSize.y /= (inverseRotation * transformParent.TransformVector(Vector3.up)).y; - - Vector3 newPosInParent = transformParent.InverseTransformPoint(newPos) - (Vector3)rectParent.rect.min; - Vector3 newPosInParentSnapped = (Vector3)RectTransformSnapping.SnapToGuides(newPosInParent, snapSize) + Vector3.forward * newPosInParent.z; - ManipulationToolUtility.DisableMinDragDifferenceBasedOnSnapping(newPosInParent, newPosInParentSnapped); - newPos = transformParent.TransformPoint(newPosInParentSnapped + (Vector3)rectParent.rect.min); - } - - bool scaleFromPivot = Event.current.alt; - bool squashing = EditorGUI.actionKey; - bool uniformScaling = Event.current.shift && !squashing; - - if (!scaleFromPivot) - scalePivot = GetRectPointInWorld(s_StartRect, pivot, rotation, 2 - xHandle, 2 - yHandle); - - if (uniformScaling) - newPos = Vector3.Project(newPos - scalePivot, origPos - scalePivot) + scalePivot; - - Vector3 sizeBefore = inverseRotation * (origPos - scalePivot); - Vector3 sizeAfter = inverseRotation * (newPos - scalePivot); - if (xHandle != 1) - scale.x = sizeAfter.x / sizeBefore.x; - if (yHandle != 1) - scale.y = sizeAfter.y / sizeBefore.y; - - if (uniformScaling) - { - float refScale = (xHandle == 1 ? scale.y : scale.x); - scale = Vector3.one * refScale; - } - - if (squashing && xHandle == 1) - { - if (Event.current.shift) - scale.x = scale.z = 1 / Mathf.Sqrt(Mathf.Max(scale.y, 0.0001f)); - else - scale.x = 1 / Mathf.Max(scale.y, 0.0001f); - } - - if (uniformScaling) - { - float refScale = (xHandle == 1 ? scale.y : scale.x); - scale = Vector3.one * refScale; - } - - if (squashing && xHandle == 1) - { - if (Event.current.shift) - scale.x = scale.z = 1 / Mathf.Sqrt(Mathf.Max(scale.y, 0.0001f)); - else - scale.x = 1 / Mathf.Max(scale.y, 0.0001f); - } - if (squashing && yHandle == 1) - { - if (Event.current.shift) - scale.y = scale.z = 1 / Mathf.Sqrt(Mathf.Max(scale.x, 0.0001f)); - else - scale.y = 1 / Mathf.Max(scale.x, 0.0001f); - } - } - - if (xHandle == 0) - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingLeft, typeBefore); - if (xHandle == 2) - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingRight, typeBefore); - if (xHandle != 1) - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingWidth, typeBefore); - if (yHandle == 0) - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingBottom, typeBefore); - if (yHandle == 2) - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingTop, typeBefore); - if (yHandle != 1) - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingHeight, typeBefore); - } - } - } - - return scale; - } - - private static Vector3 s_StartMouseWorldPos; - private static Vector3 s_StartPosition; - private static Vector2 s_StartMousePos; - private static Vector3 s_StartRectPosition; - private static Vector2 s_CurrentMousePos; - private static bool s_Moving = false; - private static int s_LockAxis = -1; - - static Vector3 MoveHandlesGUI(Rect rect, Vector3 pivot, Quaternion rotation) - { - int id = GUIUtility.GetControlID(s_MoveHandleHash, FocusType.Passive); - - Vector3 newPos = pivot; - float discSize = HandleUtility.GetHandleSize(pivot) * 0.2f; - float discOpacity = (1 - GUI.color.a); - - Vector3[] corners = new Vector3[4]; - corners[0] = rotation * new Vector2(rect.x, rect.y) + pivot; - corners[1] = rotation * new Vector2(rect.xMax, rect.y) + pivot; - corners[2] = rotation * new Vector2(rect.xMax, rect.yMax) + pivot; - corners[3] = rotation * new Vector2(rect.x, rect.yMax) + pivot; - - VertexSnapping.HandleKeyAndMouseMove(id); - - bool supportsRectSnapping = Selection.transforms.Length == 1 && - UnityEditorInternal.InternalEditorUtility.SupportsRectLayout(Selection.activeTransform) && - Selection.activeTransform.parent.rotation == rotation; - - Event evt = Event.current; - EventType eventType = evt.GetTypeForControl(id); - Plane guiPlane = new Plane(corners[0], corners[1], corners[2]); - switch (eventType) - { - case EventType.MouseDown: - { - bool acceptClick = false; - - if (Tools.vertexDragging) - { - acceptClick = true; - } - else - { - acceptClick = - evt.button == 0 && - evt.modifiers == 0 && - RectHandles.RaycastGUIPointToWorldHit(evt.mousePosition, guiPlane, out s_StartMouseWorldPos) && - ( - SceneViewDistanceToRectangle(corners, evt.mousePosition) == 0f || - (discOpacity > 0 && SceneViewDistanceToDisc(pivot, rotation * Vector3.forward, discSize, evt.mousePosition) == 0f) - ); - } - - if (acceptClick) - { - s_StartPosition = pivot; - s_StartMousePos = s_CurrentMousePos = evt.mousePosition; - s_Moving = false; - s_LockAxis = -1; - GUIUtility.hotControl = GUIUtility.keyboardControl = id; - EditorGUIUtility.SetWantsMouseJumping(1); - HandleUtility.ignoreRaySnapObjects = null; - evt.Use(); - - // Calculate snapping values if applicable - if (supportsRectSnapping) - { - Transform transform = Selection.activeTransform; - RectTransform rectTransform = transform.GetComponent(); - Transform transformParent = transform.parent; - RectTransform rectTransformParent = transformParent.GetComponent(); - - s_StartRectPosition = rectTransform.anchoredPosition; - - RectTransformSnapping.CalculatePositionSnapValues(transformParent, transform, rectTransformParent, rectTransform); - } - } - break; - } - case EventType.MouseDrag: - { - if (GUIUtility.hotControl == id) - { - s_CurrentMousePos += evt.delta; - if (!s_Moving && (s_CurrentMousePos - s_StartMousePos).magnitude > 3f) - { - s_Moving = true; - // Re-raycast to get start mouse pos when effective dragging starts. - // This prevents a sudden unsnap when the dragging is enabled. - RectHandles.RaycastGUIPointToWorldHit(s_CurrentMousePos, guiPlane, out s_StartMouseWorldPos); - } - if (s_Moving) - { - if (Tools.vertexDragging) - { - if (HandleUtility.ignoreRaySnapObjects == null) - Handles.SetupIgnoreRaySnapObjects(); - Vector3 near; - if (HandleUtility.FindNearestVertex(s_CurrentMousePos, null, out near)) - { - // Snap position based on found near vertex - newPos = near; - GUI.changed = true; - } - ManipulationToolUtility.minDragDifference = Vector2.zero; - } - else - { - ManipulationToolUtility.SetMinDragDifferenceForPos(pivot); - Vector3 pos; - if (RectHandles.RaycastGUIPointToWorldHit(s_CurrentMousePos, guiPlane, out pos)) - { - Vector3 offset = pos - s_StartMouseWorldPos; - - // Snap to axis - if (evt.shift) - { - // Get offset in rect handles space - offset = Quaternion.Inverse(rotation) * offset; - // Determine lock axis if not already set - if (s_LockAxis == -1) - s_LockAxis = Mathf.Abs(offset.x) > Mathf.Abs(offset.y) ? 0 : 1; - // Cancel mocement on other axis - offset[1 - s_LockAxis] = 0; - // Put offset back in world space - offset = rotation * offset; - } - else - { - s_LockAxis = -1; - } - - if (supportsRectSnapping) - { - Transform transformParent = Selection.activeTransform.parent; - Vector3 rectPosition = s_StartRectPosition + transformParent.InverseTransformVector(offset); - rectPosition.z = 0; - - Quaternion inverseRotation = Quaternion.Inverse(rotation); - Vector2 snapSize = Vector2.one * HandleUtility.GetHandleSize(newPos) * RectTransformSnapping.kSnapThreshold; - snapSize.x /= (inverseRotation * transformParent.TransformVector(Vector3.right)).x; - snapSize.y /= (inverseRotation * transformParent.TransformVector(Vector3.up)).y; - - Vector3 newRectPosition = RectTransformSnapping.SnapToGuides(rectPosition, snapSize); - ManipulationToolUtility.DisableMinDragDifferenceBasedOnSnapping(rectPosition, newRectPosition); - offset = transformParent.TransformVector(newRectPosition - s_StartRectPosition); - } - - newPos = s_StartPosition + offset; - - GUI.changed = true; - } - } - } - evt.Use(); - } - break; - } - case EventType.MouseUp: - { - if (GUIUtility.hotControl == id) - { - if (!s_Moving) - Selection.activeGameObject = SceneViewPicking.PickGameObject(evt.mousePosition); - GUIUtility.hotControl = 0; - EditorGUIUtility.SetWantsMouseJumping(0); - HandleUtility.ignoreRaySnapObjects = null; - evt.Use(); - } - break; - } - case EventType.Repaint: - { - if (Tools.vertexDragging) - { - RectHandles.RectScalingHandleCap(id, pivot, rotation, 1, EventType.Repaint); - } - else - { - Handles.color = Handles.secondaryColor * new Color(1, 1, 1, 1.5f * discOpacity); - Handles.CircleHandleCap(id, pivot, rotation, discSize, EventType.Repaint); - Handles.color = Handles.secondaryColor * new Color(1, 1, 1, 0.3f * discOpacity); - Handles.DrawSolidDisc(pivot, rotation * Vector3.forward, discSize); - } - break; - } - } - - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingPosX, eventType); - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingLeft, eventType); - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingRight, eventType); - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingPosY, eventType); - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingTop, eventType); - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingBottom, eventType); - - return newPos; - } - - static float SceneViewDistanceToDisc(Vector3 center, Vector3 normal, float radius, Vector2 mousePos) - { - Plane plane = new Plane(normal, center); - Ray ray = HandleUtility.GUIPointToWorldRay(mousePos); - float dist; - if (plane.Raycast(ray, out dist)) - { - Vector3 worldMousePos = ray.GetPoint(dist); - return Mathf.Max(0, (worldMousePos - center).magnitude - radius); - } - return Mathf.Infinity; - } - - // Determine the distance from the mouse position to the world rectangle specified by the 4 points. - static float SceneViewDistanceToRectangle(Vector3[] worldPoints, Vector2 mousePos) - { - Vector2[] screenPoints = new Vector2[4]; - for (int i = 0; i < 4; ++i) - screenPoints[i] = HandleUtility.WorldToGUIPoint(worldPoints[i]); - return DistanceToRectangle(screenPoints, mousePos); - } - - static float DistancePointToLineSegment(Vector2 point, Vector2 a, Vector2 b) - { - float l2 = (b - a).sqrMagnitude; - if (l2 == 0f) - return (point - a).magnitude; - float t = Vector2.Dot(point - a, b - a) / l2; - if (t < 0f) - return (point - a).magnitude; - else if (t > 1f) - return (point - b).magnitude; - Vector2 projection = a + t * (b - a); - return (point - projection).magnitude; - } - - static float DistanceToRectangle(Vector2[] screenPoints, Vector2 mousePos) - { - bool oddNodes = false; - int j = 4; - - for (int i = 0; i < 5; i++) - { - Vector3 v0 = screenPoints[i % 4]; - Vector3 v1 = screenPoints[j % 4]; - - if ((v0.y > mousePos.y) != (v1.y > mousePos.y)) - { - if (mousePos.x < (v1.x - v0.x) * (mousePos.y - v0.y) / (v1.y - v0.y) + v0.x) - { - oddNodes = !oddNodes; - } - } - j = i; - } - - if (!oddNodes) - { - float dist, closestDist = -1f; - - for (int i = 0; i < 4; i++) - { - Vector3 v0 = screenPoints[i]; - Vector3 v1 = screenPoints[(i + 1) % 4]; - - dist = DistancePointToLineSegment(mousePos, v0, v1); - - if (dist < closestDist || closestDist < 0f) closestDist = dist; - } - return closestDist; - } - else return 0f; - } - - static Quaternion RotationHandlesGUI(Rect rect, Vector3 pivot, Quaternion rotation) - { - Vector3 euler = rotation.eulerAngles; - // Loop through the 4 corner handles - for (int xHandle = 0; xHandle <= 2; xHandle += 2) - { - for (int yHandle = 0; yHandle <= 2; yHandle += 2) - { - Vector3 curPos = GetRectPointInWorld(rect, pivot, rotation, xHandle, yHandle); - - float size = 0.05f * HandleUtility.GetHandleSize(curPos); - int id = GUIUtility.GetControlID(s_RotationHandlesHash, FocusType.Passive); - if (GUI.color.a > 0 || GUIUtility.hotControl == id) - { - EditorGUI.BeginChangeCheck(); - Vector3 outwardsA = rotation * Vector3.right * (xHandle - 1); - Vector3 outwardsB = rotation * Vector3.up * (yHandle - 1); - float angle = RectHandles.RotationSlider(id, curPos, euler.z, pivot, rotation * Vector3.forward, outwardsA, outwardsB, size, null, Vector2.zero); - if (EditorGUI.EndChangeCheck()) - { - if (Event.current.shift) - angle = Mathf.Round((angle - euler.z) / 15f) * 15f + euler.z; - euler.z = angle; - rotation = Quaternion.Euler(euler); - } - } - } - } - return rotation; - } - - static Vector3 PivotHandleGUI(Rect rect, Vector3 pivot, Quaternion rotation) - { - int id = GUIUtility.GetControlID(s_PivotHandleHash, FocusType.Passive); - EventType eventType = Event.current.GetTypeForControl(id); - if (GUI.color.a > 0 || GUIUtility.hotControl == id) - { - EventType typeBefore = eventType; - - EditorGUI.BeginChangeCheck(); - Vector3 newPivot = Handles.Slider2D(id, pivot, rotation * Vector3.forward, rotation * Vector3.right, rotation * Vector3.up, HandleUtility.GetHandleSize(pivot) * 0.1f, RectHandles.PivotHandleCap, Vector2.zero); - - if (typeBefore == EventType.MouseDown && GUIUtility.hotControl == id) - RectTransformSnapping.CalculatePivotSnapValues(rect, pivot, rotation); - - if (EditorGUI.EndChangeCheck()) - { - Vector2 offset = Quaternion.Inverse(rotation) * (newPivot - pivot); - offset.x /= rect.width; - offset.y /= rect.height; - Vector2 pivotCoordBefore = new Vector2(-rect.x / rect.width, -rect.y / rect.height); - Vector2 pivotCoordAfter = pivotCoordBefore + offset; - - Vector2 snapSize = HandleUtility.GetHandleSize(pivot) * RectTransformSnapping.kSnapThreshold * new Vector2(1 / rect.width, 1 / rect.height); - pivotCoordAfter = RectTransformSnapping.SnapToGuides(pivotCoordAfter, snapSize); - - offset = (pivotCoordAfter - pivotCoordBefore); - offset.x *= rect.width; - offset.y *= rect.height; - pivot += rotation * offset; - } - } - ManipulationToolUtility.DetectDraggingBasedOnMouseDownUp(kChangingPivot, eventType); - - return pivot; - } - } -} // namespace diff --git a/Editor/Mono/GUI/Tools/SnapSettings.cs b/Editor/Mono/GUI/Tools/SnapSettings.cs deleted file mode 100644 index 7f897ac561..0000000000 --- a/Editor/Mono/GUI/Tools/SnapSettings.cs +++ /dev/null @@ -1,154 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - internal class SnapSettings : EditorWindow - { - private static float s_MoveSnapX; - private static float s_MoveSnapY; - private static float s_MoveSnapZ; - - private static float s_ScaleSnap; - private static float s_RotationSnap; - - private static bool s_Initialized; - - private static void Initialize() - { - if (!s_Initialized) - { - s_MoveSnapX = EditorPrefs.GetFloat("MoveSnapX", 1f); - s_MoveSnapY = EditorPrefs.GetFloat("MoveSnapY", 1f); - s_MoveSnapZ = EditorPrefs.GetFloat("MoveSnapZ", 1f); - - s_ScaleSnap = EditorPrefs.GetFloat("ScaleSnap", .1f); - s_RotationSnap = EditorPrefs.GetFloat("RotationSnap", 15); - - s_Initialized = true; - } - } - - public static Vector3 move - { - get - { - Initialize(); - return new Vector3(s_MoveSnapX, s_MoveSnapY, s_MoveSnapZ); - } - set - { - EditorPrefs.SetFloat("MoveSnapX", value.x); - s_MoveSnapX = value.x; - EditorPrefs.SetFloat("MoveSnapY", value.y); - s_MoveSnapY = value.y; - EditorPrefs.SetFloat("MoveSnapZ", value.z); - s_MoveSnapZ = value.z; - } - } - - public static float scale - { - get - { - Initialize(); - return s_ScaleSnap; - } - set - { - EditorPrefs.SetFloat("ScaleSnap", value); - s_ScaleSnap = value; - } - } - - public static float rotation - { - get - { - Initialize(); - return s_RotationSnap; - } - set - { - EditorPrefs.SetFloat("RotationSnap", value); - s_RotationSnap = value; - } - } - - [MenuItem("Edit/Snap Settings...")] - static void ShowSnapSettings() - { - EditorWindow.GetWindowWithRect(new Rect(100, 100, 230, 130), true, "Snap settings"); - } - - class Styles - { - public GUIStyle buttonLeft = "ButtonLeft"; - public GUIStyle buttonMid = "ButtonMid"; - public GUIStyle buttonRight = "ButtonRight"; - public GUIContent snapAllAxes = EditorGUIUtility.TrTextContent("Snap All Axes", "Snaps selected objects to the grid"); - public GUIContent snapX = EditorGUIUtility.TrTextContent("X", "Snaps selected objects to the grid on the x axis"); - public GUIContent snapY = EditorGUIUtility.TrTextContent("Y", "Snaps selected objects to the grid on the y axis"); - public GUIContent snapZ = EditorGUIUtility.TrTextContent("Z", "Snaps selected objects to the grid on the z axis"); - public GUIContent moveX = EditorGUIUtility.TrTextContent("Move X", "Grid spacing X"); - public GUIContent moveY = EditorGUIUtility.TrTextContent("Move Y", "Grid spacing Y"); - public GUIContent moveZ = EditorGUIUtility.TrTextContent("Move Z", "Grid spacing Z"); - public GUIContent scale = EditorGUIUtility.TrTextContent("Scale", "Grid spacing for scaling"); - public GUIContent rotation = EditorGUIUtility.TrTextContent("Rotation", "Grid spacing for rotation in degrees"); - } - static Styles ms_Styles; - - void OnGUI() - { - if (ms_Styles == null) - ms_Styles = new Styles(); - - GUILayout.Space(5); - - EditorGUI.BeginChangeCheck(); - Vector3 m = move; - m.x = EditorGUILayout.FloatField(ms_Styles.moveX, m.x); - m.y = EditorGUILayout.FloatField(ms_Styles.moveY, m.y); - m.z = EditorGUILayout.FloatField(ms_Styles.moveZ, m.z); - - if (EditorGUI.EndChangeCheck()) - { - if (m.x <= 0) m.x = move.x; - if (m.y <= 0) m.y = move.y; - if (m.z <= 0) m.z = move.z; - move = m; - } - scale = EditorGUILayout.FloatField(ms_Styles.scale, scale); - rotation = EditorGUILayout.FloatField(ms_Styles.rotation, rotation); - - GUILayout.Space(5); - - bool snapX = false, snapY = false, snapZ = false; - GUILayout.BeginHorizontal(); - if (GUILayout.Button(ms_Styles.snapAllAxes, ms_Styles.buttonLeft)) { snapX = true; snapY = true; snapZ = true; } - if (GUILayout.Button(ms_Styles.snapX, ms_Styles.buttonMid)) { snapX = true; } - if (GUILayout.Button(ms_Styles.snapY, ms_Styles.buttonMid)) { snapY = true; } - if (GUILayout.Button(ms_Styles.snapZ, ms_Styles.buttonRight)) { snapZ = true; } - GUILayout.EndHorizontal(); - - if (snapX | snapY | snapZ) - { - Vector3 scaleTmp = new Vector3(1.0f / move.x, 1.0f / move.y, 1.0f / move.z); - - Undo.RecordObjects(Selection.transforms, "Snap " + (Selection.transforms.Length == 1 ? Selection.activeGameObject.name : " selection") + " to grid"); - foreach (Transform t in Selection.transforms) - { - Vector3 pos = t.position; - if (snapX) pos.x = Mathf.Round(pos.x * scaleTmp.x) / scaleTmp.x; - if (snapY) pos.y = Mathf.Round(pos.y * scaleTmp.y) / scaleTmp.y; - if (snapZ) pos.z = Mathf.Round(pos.z * scaleTmp.z) / scaleTmp.z; - t.position = pos; - } - } - } - } -} // namespace diff --git a/Editor/Mono/GUI/Tools/Tools.cs b/Editor/Mono/GUI/Tools/Tools.cs deleted file mode 100644 index 56e3389dea..0000000000 --- a/Editor/Mono/GUI/Tools/Tools.cs +++ /dev/null @@ -1,546 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - public enum ViewTool - { - None = -1, - Orbit = 0, - Pan = 1, - Zoom = 2, - FPS = 3 - } - - public enum PivotMode - { - Center = 0, - Pivot = 1 - } - - public enum PivotRotation - { - Local = 0, - Global = 1 - } - - public enum Tool - { - View = 0, - Move = 1, - Rotate = 2, - Scale = 3, - Rect = 4, - Transform = 5, - None = -1 - } - - public sealed partial class Tools : ScriptableObject - { - private static Tools get - { - get - { - if (!s_Get) - { - s_Get = ScriptableObject.CreateInstance(); - s_Get.hideFlags = HideFlags.HideAndDontSave; - } - return s_Get; - } - } - private static Tools s_Get; - - internal delegate void OnToolChangedFunc(Tool from, Tool to); - internal static OnToolChangedFunc onToolChanged; - - public static Tool current - { - get { return get.currentTool; } - set - { - if (get.currentTool != value) - { - Tool oldTool = get.currentTool; - get.currentTool = value; - if (onToolChanged != null) - onToolChanged(oldTool, value); - Tools.RepaintAllToolViews(); - } - } - } - - public static ViewTool viewTool - { - get - { - Event evt = Event.current; - if (evt != null && viewToolActive) - { - if (s_LockedViewTool == ViewTool.None) - { - bool controlKeyOnMac = (evt.control && Application.platform == RuntimePlatform.OSXEditor); - bool actionKey = EditorGUI.actionKey; - bool noModifiers = (!actionKey && !controlKeyOnMac && !evt.alt); - - if ((s_ButtonDown <= 0 && noModifiers) - || (s_ButtonDown <= 0 && actionKey) - || s_ButtonDown == 2 - || SceneView.lastActiveSceneView != null && (SceneView.lastActiveSceneView.in2DMode || SceneView.lastActiveSceneView.isRotationLocked) && !(s_ButtonDown == 1 && evt.alt || s_ButtonDown <= 0 && controlKeyOnMac) - ) - { - get.m_ViewTool = ViewTool.Pan; - } - else if ((s_ButtonDown <= 0 && controlKeyOnMac) - || (s_ButtonDown == 1 && evt.alt)) - { - get.m_ViewTool = ViewTool.Zoom; - } - else if (s_ButtonDown <= 0 && evt.alt) - { - get.m_ViewTool = ViewTool.Orbit; - } - else if (s_ButtonDown == 1 && !evt.alt) - { - get.m_ViewTool = ViewTool.FPS; - } - } - } - else - { - get.m_ViewTool = ViewTool.Pan; - } - return get.m_ViewTool; - } - set { get.m_ViewTool = value; } - } - internal static ViewTool s_LockedViewTool = ViewTool.None; - internal static int s_ButtonDown = -1; - internal static bool viewToolActive - { - get - { - if (GUIUtility.hotControl != 0 && s_LockedViewTool == ViewTool.None) - return false; - - return s_LockedViewTool != ViewTool.None || (current == 0) || Event.current.alt || (s_ButtonDown == 1) || (s_ButtonDown == 2); - } - } - - public static Vector3 handlePosition - { - get - { - Transform t = Selection.activeTransform; - if (!t) - return new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity); - - if (s_LockHandlePositionActive) - return s_LockHandlePosition; - - return GetHandlePosition(); - } - } - - internal static Vector3 GetHandlePosition() - { - Transform t = Selection.activeTransform; - if (!t) - return new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity); - - Vector3 totalOffset = handleOffset + handleRotation * localHandleOffset; - - switch (get.m_PivotMode) - { - case PivotMode.Center: - { - if (current == Tool.Rect) - return handleRotation * InternalEditorUtility.CalculateSelectionBoundsInSpace(Vector3.zero, handleRotation, rectBlueprintMode).center + totalOffset; - else - return InternalEditorUtility.CalculateSelectionBounds(true, false).center + totalOffset; - } - case PivotMode.Pivot: - { - if (current == Tool.Rect && rectBlueprintMode && InternalEditorUtility.SupportsRectLayout(t)) - return t.parent.TransformPoint(new Vector3(t.localPosition.x, t.localPosition.y, 0)) + totalOffset; - else - return t.position + totalOffset; - } - default: - { - return new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity); - } - } - } - - public static Rect handleRect - { - get - { - Bounds bounds = InternalEditorUtility.CalculateSelectionBoundsInSpace(handlePosition, handleRotation, rectBlueprintMode); - int axis = GetRectAxisForViewDir(bounds, handleRotation, SceneView.currentDrawingSceneView.camera.transform.forward); - return GetRectFromBoundsForAxis(bounds, axis); - } - } - - public static Quaternion handleRectRotation - { - get - { - Bounds bounds = InternalEditorUtility.CalculateSelectionBoundsInSpace(handlePosition, handleRotation, rectBlueprintMode); - int axis = GetRectAxisForViewDir(bounds, handleRotation, SceneView.currentDrawingSceneView.camera.transform.forward); - return GetRectRotationForAxis(handleRotation, axis); - } - } - - private static int GetRectAxisForViewDir(Bounds bounds, Quaternion rotation, Vector3 viewDir) - { - if (s_LockHandleRectAxisActive) - { - return s_LockHandleRectAxis; - } - if (viewDir == Vector3.zero) - { - return 2; - } - else - { - if (bounds.size == Vector3.zero) - bounds.size = Vector3.one; - int axis = -1; - float bestScore = -1; - for (int normalAxis = 0; normalAxis < 3; normalAxis++) - { - Vector3 edge1 = Vector3.zero; - Vector3 edge2 = Vector3.zero; - int axis1 = (normalAxis + 1) % 3; - int axis2 = (normalAxis + 2) % 3; - edge1[axis1] = bounds.size[axis1]; - edge2[axis2] = bounds.size[axis2]; - float score = Vector3.Cross(Vector3.ProjectOnPlane(rotation * edge1, viewDir), Vector3.ProjectOnPlane(rotation * edge2, viewDir)).magnitude; - if (score > bestScore) - { - bestScore = score; - axis = normalAxis; - } - } - return axis; - } - } - - private static Rect GetRectFromBoundsForAxis(Bounds bounds, int axis) - { - switch (axis) - { - case 0: return new Rect(-bounds.max.z, bounds.min.y, bounds.size.z, bounds.size.y); - case 1: return new Rect(bounds.min.x, -bounds.max.z, bounds.size.x, bounds.size.z); - case 2: - default: return new Rect(bounds.min.x, bounds.min.y, bounds.size.x, bounds.size.y); - } - } - - private static Quaternion GetRectRotationForAxis(Quaternion rotation, int axis) - { - switch (axis) - { - case 0: return rotation * Quaternion.Euler(0, 90, 0); - case 1: return rotation * Quaternion.Euler(-90, 0, 0); - case 2: - default: return rotation; - } - } - - internal static void LockHandleRectRotation() - { - Bounds bounds = InternalEditorUtility.CalculateSelectionBoundsInSpace(handlePosition, handleRotation, rectBlueprintMode); - s_LockHandleRectAxis = GetRectAxisForViewDir(bounds, handleRotation, SceneView.currentDrawingSceneView.camera.transform.forward); - s_LockHandleRectAxisActive = true; - } - - internal static void UnlockHandleRectRotation() - { - s_LockHandleRectAxisActive = false; - } - - public static PivotMode pivotMode - { - get { return get.m_PivotMode; } - set - { - if (get.m_PivotMode != value) - { - get.m_PivotMode = value; - EditorPrefs.SetInt("PivotMode", (int)pivotMode); - } - } - } - private PivotMode m_PivotMode; - - internal static int GetPivotMode() - { - return (int)pivotMode; - } - - public static bool rectBlueprintMode - { - get { return get.m_RectBlueprintMode; } - set - { - if (get.m_RectBlueprintMode != value) - { - get.m_RectBlueprintMode = value; - EditorPrefs.SetBool("RectBlueprintMode", rectBlueprintMode); - } - } - } - private bool m_RectBlueprintMode; - - public static Quaternion handleRotation - { - get - { - switch (get.m_PivotRotation) - { - case PivotRotation.Global: - return get.m_GlobalHandleRotation; - case PivotRotation.Local: - return handleLocalRotation; - } - return Quaternion.identity; - } - set - { - if (get.m_PivotRotation == PivotRotation.Global) - get.m_GlobalHandleRotation = value; - } - } - - public static PivotRotation pivotRotation - { - get { return get.m_PivotRotation; } - set - { - if (get.m_PivotRotation != value) - { - get.m_PivotRotation = value; - EditorPrefs.SetInt("PivotRotation", (int)pivotRotation); - } - } - } - private PivotRotation m_PivotRotation; - - internal static bool s_Hidden = false; - - public static bool hidden - { - get { return s_Hidden; } - set { s_Hidden = value; } - } - - internal static bool vertexDragging; - - static Vector3 s_LockHandlePosition; - static bool s_LockHandlePositionActive = false; - - static int s_LockHandleRectAxis; - static bool s_LockHandleRectAxisActive = false; - - public static int visibleLayers - { - get { return get.m_VisibleLayers; } - set - { - if (get.m_VisibleLayers != value) - { - get.m_VisibleLayers = value; - EditorGUIUtility.SetVisibleLayers(value); - EditorPrefs.SetInt("VisibleLayers", visibleLayers); - } - } - } - int m_VisibleLayers = -1; - - public static int lockedLayers - { - get { return get.m_LockedLayers; } - set - { - if (get.m_LockedLayers != value) - { - get.m_LockedLayers = value; - EditorGUIUtility.SetLockedLayers(value); - EditorPrefs.SetInt("LockedLayers", lockedLayers); - } - } - } - int m_LockedLayers = -1; - - private void OnEnable() - { - s_Get = this; - EditorApplication.globalEventHandler += ControlsHack; - pivotMode = (PivotMode)EditorPrefs.GetInt("PivotMode", 0); - rectBlueprintMode = EditorPrefs.GetBool("RectBlueprintMode", false); - pivotRotation = (PivotRotation)EditorPrefs.GetInt("PivotRotation", 0); - visibleLayers = EditorPrefs.GetInt("VisibleLayers", -1); - lockedLayers = EditorPrefs.GetInt("LockedLayers", 0); - } - - private void OnDisable() - { - EditorApplication.globalEventHandler -= ControlsHack; - } - - internal static void OnSelectionChange() - { - ResetGlobalHandleRotation(); - localHandleOffset = Vector3.zero; - } - - internal static void ResetGlobalHandleRotation() - { - get.m_GlobalHandleRotation = Quaternion.identity; - } - - internal Quaternion m_GlobalHandleRotation = Quaternion.identity; - Tool currentTool = Tool.Move; - ViewTool m_ViewTool = ViewTool.Pan; - - static PrefKey kViewKey = new PrefKey("Tools/View", "q"); - static PrefKey kMoveKey = new PrefKey("Tools/Move", "w"); - static PrefKey kRotateKey = new PrefKey("Tools/Rotate", "e"); - static PrefKey kScaleKey = new PrefKey("Tools/Scale", "r"); - static PrefKey kRectKey = new PrefKey("Tools/Rect Handles", "t"); - static PrefKey kTransformKey = new PrefKey("Tools/Transform Handles", "y"); - static PrefKey kPivotMode = new PrefKey("Tools/Pivot Mode", "z"); - static PrefKey kPivotRotation = new PrefKey("Tools/Pivot Rotation", "x"); - - internal static void ControlsHack() - { - Event evt = Event.current; - if (kViewKey.activated) - { - Tools.current = 0; - ResetGlobalHandleRotation(); - evt.Use(); - if (Toolbar.get) - Toolbar.get.Repaint(); - else - Debug.LogError("Press Play twice for sceneview keyboard shortcuts to work"); - } - if (kMoveKey.activated) - { - Tools.current = Tool.Move; - ResetGlobalHandleRotation(); - evt.Use(); - if (Toolbar.get) - Toolbar.get.Repaint(); - else - Debug.LogError("Press Play twice for sceneview keyboard shortcuts to work"); - } - if (kRotateKey.activated) - { - Tools.current = Tool.Rotate; - ResetGlobalHandleRotation(); - evt.Use(); - if (Toolbar.get) - Toolbar.get.Repaint(); - else - Debug.LogError("Press Play twice for sceneview keyboard shortcuts to work"); - } - if (kScaleKey.activated) - { - Tools.current = Tool.Scale; - ResetGlobalHandleRotation(); - evt.Use(); - if (Toolbar.get) - Toolbar.get.Repaint(); - else - Debug.LogError("Press Play twice for sceneview keyboard shortcuts to work"); - } - if (kRectKey.activated) - { - Tools.current = Tool.Rect; - ResetGlobalHandleRotation(); - evt.Use(); - if (Toolbar.get) - Toolbar.get.Repaint(); - else - Debug.LogError("Press Play twice for sceneview keyboard shortcuts to work"); - } - if (kTransformKey.activated) - { - Tools.current = Tool.Transform; - ResetGlobalHandleRotation(); - evt.Use(); - if (Toolbar.get) - Toolbar.get.Repaint(); - else - Debug.LogError("Press Play twice for sceneview keyboard shortcuts to work"); - } - if (kPivotMode.activated) - { - pivotMode = (PivotMode)(1 - (int)pivotMode); - ResetGlobalHandleRotation(); - evt.Use(); - Tools.RepaintAllToolViews(); - } - if (kPivotRotation.activated) - { - pivotRotation = (PivotRotation)(1 - (int)pivotRotation); - ResetGlobalHandleRotation(); - evt.Use(); - Tools.RepaintAllToolViews(); - } - } - - internal static void RepaintAllToolViews() - { - if (Toolbar.get) - Toolbar.get.Repaint(); - SceneView.RepaintAll(); - InspectorWindow.RepaintAllInspectors(); - } - - internal static void HandleKeys() - { - ControlsHack(); - } - - internal static void LockHandlePosition(Vector3 pos) - { - s_LockHandlePosition = pos; - s_LockHandlePositionActive = true; - } - - internal static Vector3 handleOffset; - internal static Vector3 localHandleOffset; - - internal static void LockHandlePosition() - { - LockHandlePosition(handlePosition); - } - - internal static void UnlockHandlePosition() - { - s_LockHandlePositionActive = false; - } - - internal static Quaternion handleLocalRotation - { - get - { - Transform t = Selection.activeTransform; - if (!t) - return Quaternion.identity; - if (rectBlueprintMode && InternalEditorUtility.SupportsRectLayout(t)) - return t.parent.rotation; - return t.rotation; - } - } - } -} diff --git a/Editor/Mono/GUI/Tools/TransformManipulator.cs b/Editor/Mono/GUI/Tools/TransformManipulator.cs deleted file mode 100644 index 264196d60c..0000000000 --- a/Editor/Mono/GUI/Tools/TransformManipulator.cs +++ /dev/null @@ -1,396 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - internal class TransformManipulator - { - private struct TransformData - { - public static Quaternion[] s_Alignments = new Quaternion[] - { - Quaternion.LookRotation(Vector3.right, Vector3.up), - Quaternion.LookRotation(Vector3.right, Vector3.forward), - Quaternion.LookRotation(Vector3.up, Vector3.forward), - Quaternion.LookRotation(Vector3.up, Vector3.right), - Quaternion.LookRotation(Vector3.forward, Vector3.right), - Quaternion.LookRotation(Vector3.forward, Vector3.up) - }; - - public Transform transform; - public Vector3 position; - public Vector3 localPosition; - public Quaternion rotation; - public Vector3 scale; - public RectTransform rectTransform; - public Rect rect; - public Vector2 anchoredPosition; - public Vector2 sizeDelta; - - public static TransformData GetData(Transform t) - { - TransformData data = new TransformData(); - data.SetupTransformValues(t); - - data.rectTransform = t.GetComponent(); - if (data.rectTransform != null) - { - data.sizeDelta = data.rectTransform.sizeDelta; - data.rect = data.rectTransform.rect; - data.anchoredPosition = data.rectTransform.anchoredPosition; - } - else - { - SpriteRenderer sr = t.GetComponent(); - if (sr != null && sr.drawMode != SpriteDrawMode.Simple) - data.sizeDelta = sr.size; - } - return data; - } - - private Quaternion GetRefAlignment(Quaternion targetRotation, Quaternion ownRotation) - { - float biggestDot = Mathf.NegativeInfinity; - Quaternion refAlignment = Quaternion.identity; - for (int i = 0; i < s_Alignments.Length; i++) - { - float dot = Mathf.Min( - Mathf.Abs(Vector3.Dot(targetRotation * Vector3.right, ownRotation * s_Alignments[i] * Vector3.right)), - Mathf.Abs(Vector3.Dot(targetRotation * Vector3.up, ownRotation * s_Alignments[i] * Vector3.up)), - Mathf.Abs(Vector3.Dot(targetRotation * Vector3.forward, ownRotation * s_Alignments[i] * Vector3.forward)) - ); - if (dot > biggestDot) - { - biggestDot = dot; - refAlignment = s_Alignments[i]; - } - } - return refAlignment; - } - - private void SetupTransformValues(Transform t) - { - transform = t; - position = t.position; - localPosition = t.localPosition; - rotation = t.rotation; - scale = t.localScale; - } - - private void SetScaleValue(Vector3 scale) - { - transform.localScale = scale; - } - - public void SetScaleDelta(Vector3 scaleDelta, Vector3 scalePivot, Quaternion scaleRotation, bool preferRectResize) - { - SetPosition(scaleRotation * Vector3.Scale(Quaternion.Inverse(scaleRotation) * (position - scalePivot), scaleDelta) + scalePivot); - - Vector3 minDifference = ManipulationToolUtility.minDragDifference; - if (transform.parent != null) - { - minDifference.x /= transform.parent.lossyScale.x; - minDifference.y /= transform.parent.lossyScale.y; - minDifference.z /= transform.parent.lossyScale.z; - } - - Quaternion ownRotation = (Tools.rectBlueprintMode && UnityEditorInternal.InternalEditorUtility.SupportsRectLayout(transform) ? transform.parent.rotation : rotation); - Quaternion refAlignment = GetRefAlignment(scaleRotation, ownRotation); - scaleDelta = refAlignment * scaleDelta; - scaleDelta = Vector3.Scale(scaleDelta, refAlignment * Vector3.one); - - if (preferRectResize) - { - if (rectTransform != null) - { - Vector2 newSizeDelta = sizeDelta + Vector2.Scale(rect.size, scaleDelta) - rect.size; - newSizeDelta.x = MathUtils.RoundBasedOnMinimumDifference(newSizeDelta.x, minDifference.x); - newSizeDelta.y = MathUtils.RoundBasedOnMinimumDifference(newSizeDelta.y, minDifference.y); - rectTransform.sizeDelta = newSizeDelta; - if (rectTransform.drivenByObject != null) - RectTransform.SendReapplyDrivenProperties(rectTransform); - return; - } - else - { - SpriteRenderer sr = transform.GetComponent(); - if (sr != null && sr.drawMode != SpriteDrawMode.Simple) - { - sr.size = Vector2.Scale(sizeDelta, scaleDelta); - return; - } - } - } - - SetScaleValue(Vector3.Scale(scale, scaleDelta)); - } - - private void SetPosition(Vector3 newPosition) - { - SetPositionDelta(newPosition - position, true); - } - - public void SetPositionDelta(Vector3 positionDelta, bool applySmartRounding) - { - Vector3 localPositionDelta = positionDelta; - Vector3 minDifference = ManipulationToolUtility.minDragDifference; - if (transform.parent != null) - { - localPositionDelta = transform.parent.InverseTransformVector(localPositionDelta); - minDifference.x /= transform.parent.lossyScale.x; - minDifference.y /= transform.parent.lossyScale.y; - minDifference.z /= transform.parent.lossyScale.z; - } - - // For zero delta, we don't want to change the value so we ignore rounding - bool zeroXDelta = Mathf.Approximately(localPositionDelta.x, 0f); - bool zeroYDelta = Mathf.Approximately(localPositionDelta.y, 0f); - bool zeroZDelta = Mathf.Approximately(localPositionDelta.z, 0f); - - if (rectTransform == null) - { - Vector3 newLocalPosition = localPosition + localPositionDelta; - - if (applySmartRounding) - { - newLocalPosition.x = zeroXDelta ? localPosition.x : MathUtils.RoundBasedOnMinimumDifference(newLocalPosition.x, minDifference.x); - newLocalPosition.y = zeroYDelta ? localPosition.y : MathUtils.RoundBasedOnMinimumDifference(newLocalPosition.y, minDifference.y); - newLocalPosition.z = zeroZDelta ? localPosition.z : MathUtils.RoundBasedOnMinimumDifference(newLocalPosition.z, minDifference.z); - } - - transform.localPosition = newLocalPosition; - } - else - { - // Set position.z - Vector3 newLocalPosition = localPosition + localPositionDelta; - - if (applySmartRounding) - newLocalPosition.z = zeroZDelta ? localPosition.z : MathUtils.RoundBasedOnMinimumDifference(newLocalPosition.z, minDifference.z); - - transform.localPosition = newLocalPosition; - - // Set anchoredPosition - Vector2 newAnchoredPosition = anchoredPosition + (Vector2)localPositionDelta; - - if (applySmartRounding) - { - newAnchoredPosition.x = zeroXDelta ? anchoredPosition.x : MathUtils.RoundBasedOnMinimumDifference(newAnchoredPosition.x, minDifference.x); - newAnchoredPosition.y = zeroYDelta ? anchoredPosition.y : MathUtils.RoundBasedOnMinimumDifference(newAnchoredPosition.y, minDifference.y); - } - - rectTransform.anchoredPosition = newAnchoredPosition; - - if (rectTransform.drivenByObject != null) - RectTransform.SendReapplyDrivenProperties(rectTransform); - } - } - - public void DebugAlignment(Quaternion targetRotation) - { - Quaternion refAlignment = Quaternion.identity; - if (!TransformManipulator.individualSpace) - refAlignment = GetRefAlignment(targetRotation, rotation); - - Vector3 dir; - Vector3 pos = transform.position; - float size = HandleUtility.GetHandleSize(pos) * 0.25f; - Color oldColor = Handles.color; - - Handles.color = Color.red; - dir = rotation * refAlignment * Vector3.right * size; - Handles.DrawLine(pos - dir, pos + dir); - - Handles.color = Color.green; - dir = rotation * refAlignment * Vector3.up * size; - Handles.DrawLine(pos - dir, pos + dir); - - Handles.color = Color.blue; - dir = rotation * refAlignment * Vector3.forward * size; - Handles.DrawLine(pos - dir, pos + dir); - - Handles.color = oldColor; - } - } - - static EventType s_EventTypeBefore = EventType.Ignore; - static TransformData[] s_MouseDownState = null; - static Vector3 s_StartHandlePosition = Vector3.zero; - static Vector3 s_PreviousHandlePosition = Vector3.zero; - static Quaternion s_StartHandleRotation = Quaternion.identity; - public static Vector3 mouseDownHandlePosition { get { return s_StartHandlePosition; } } - public static Quaternion mouseDownHandleRotation { get { return s_StartHandleRotation; } set { s_StartHandleRotation = value; } } - static Vector3 s_StartLocalHandleOffset = Vector3.zero; - static int s_HotControl = 0; - static bool s_LockHandle = false; - - public static bool active { get { return s_MouseDownState != null; } } - - public static bool individualSpace { get { return Tools.pivotRotation == PivotRotation.Local && Tools.pivotMode == PivotMode.Pivot; } } - - private static void BeginEventCheck() - { - var previousEvent = s_EventTypeBefore; - s_EventTypeBefore = Event.current.GetTypeForControl(s_HotControl); - if (!active || (previousEvent != EventType.MouseDown && s_EventTypeBefore == EventType.MouseDown)) - { - s_StartHandleRotation = Tools.handleRotation; - } - } - - private static EventType EndEventCheck() - { - EventType usedEvent = (s_EventTypeBefore != Event.current.GetTypeForControl(s_HotControl) ? s_EventTypeBefore : EventType.Ignore); - s_EventTypeBefore = EventType.Ignore; - if (usedEvent == EventType.MouseDown) - s_HotControl = GUIUtility.hotControl; - else if (usedEvent == EventType.MouseUp) - s_HotControl = 0; - return usedEvent; - } - - public static void BeginManipulationHandling(bool lockHandleWhileDragging) - { - BeginEventCheck(); - s_LockHandle = lockHandleWhileDragging; - } - - public static EventType EndManipulationHandling() - { - EventType usedEvent = EndEventCheck(); - - if (usedEvent == EventType.MouseDown) - { - RecordMouseDownState(Selection.transforms); - s_StartHandlePosition = Tools.handlePosition; - s_PreviousHandlePosition = s_StartHandlePosition; - s_StartLocalHandleOffset = Tools.localHandleOffset; - if (s_LockHandle) - Tools.LockHandlePosition(); - Tools.LockHandleRectRotation(); - } - else if (s_MouseDownState != null && (usedEvent == EventType.MouseUp || GUIUtility.hotControl != s_HotControl)) - { - s_StartHandleRotation = Tools.handleRotation; - s_MouseDownState = null; - if (s_LockHandle) - Tools.UnlockHandlePosition(); - Tools.UnlockHandleRectRotation(); - ManipulationToolUtility.DisableMinDragDifference(); - } - - return usedEvent; - } - - private static void RecordMouseDownState(Transform[] transforms) - { - s_MouseDownState = new TransformData[transforms.Length]; - for (int i = 0; i < transforms.Length; i++) - { - s_MouseDownState[i] = TransformData.GetData(transforms[i]); - } - } - - private static void SetLocalHandleOffsetScaleDelta(Vector3 scaleDelta, Quaternion pivotRotation) - { - Quaternion refAlignment = Quaternion.Inverse(Tools.handleRotation) * pivotRotation; - Tools.localHandleOffset = Vector3.Scale(Vector3.Scale(s_StartLocalHandleOffset, refAlignment * scaleDelta), refAlignment * Vector3.one); - } - - public static void SetScaleDelta(Vector3 scaleDelta, Quaternion pivotRotation) - { - if (s_MouseDownState == null) - return; - - SetLocalHandleOffsetScaleDelta(scaleDelta, pivotRotation); - - for (int i = 0; i < s_MouseDownState.Length; i++) - { - var cur = s_MouseDownState[i]; - Undo.RecordObject(cur.transform, "Scale"); - } - - Vector3 point = Tools.handlePosition; - for (int i = 0; i < s_MouseDownState.Length; i++) - { - // Scale about handlePosition or local pivot based on pivotMode - if (Tools.pivotMode == PivotMode.Pivot) - point = s_MouseDownState[i].position; - if (individualSpace) - pivotRotation = s_MouseDownState[i].rotation; - s_MouseDownState[i].SetScaleDelta(scaleDelta, point, pivotRotation, false); - } - } - - public static void SetResizeDelta(Vector3 scaleDelta, Vector3 pivotPosition, Quaternion pivotRotation) - { - if (s_MouseDownState == null) - return; - - SetLocalHandleOffsetScaleDelta(scaleDelta, pivotRotation); - - for (int i = 0; i < s_MouseDownState.Length; i++) - { - var cur = s_MouseDownState[i]; - if (cur.rectTransform != null) - Undo.RecordObject((Object)cur.rectTransform, "Resize"); - else - { - SpriteRenderer sr = cur.transform.GetComponent(); - if (sr != null && sr.drawMode != SpriteDrawMode.Simple) - Undo.RecordObjects(new Object[] {(Object)sr, (Object)cur.transform}, "Resize"); - else - Undo.RecordObject((Object)cur.transform, "Resize"); - } - } - - for (int i = 0; i < s_MouseDownState.Length; i++) - { - s_MouseDownState[i].SetScaleDelta(scaleDelta, pivotPosition, pivotRotation, true); - } - } - - public static void SetPositionDelta(Vector3 newPosition, Vector3 oldPosition) - { - if (s_MouseDownState == null) - return; - - s_PreviousHandlePosition = newPosition; - Vector3 positionDelta = newPosition - oldPosition; - - for (int i = 0; i < s_MouseDownState.Length; i++) - { - var cur = s_MouseDownState[i]; - Undo.RecordObject((cur.rectTransform != null ? (Object)cur.rectTransform : (Object)cur.transform), "Move"); - } - - if (s_MouseDownState.Length > 0) - { - s_MouseDownState[0].SetPositionDelta(positionDelta, true); - Vector3 firstDelta = s_MouseDownState[0].transform.position - s_MouseDownState[0].position; - - for (int i = 1; i < s_MouseDownState.Length; i++) - { - s_MouseDownState[i].SetPositionDelta(firstDelta, false); - } - } - } - - public static bool HandleHasMoved(Vector3 position) - { - return position != s_PreviousHandlePosition; - } - - public static void DebugAlignment(Quaternion targetRotation) - { - if (s_MouseDownState == null) - return; - for (int i = 0; i < s_MouseDownState.Length; i++) - s_MouseDownState[i].DebugAlignment(targetRotation); - } - } -} // namespace diff --git a/Editor/Mono/GUI/TreeView/AssetOrGameObjectTreeViewDragging.cs b/Editor/Mono/GUI/TreeView/AssetOrGameObjectTreeViewDragging.cs deleted file mode 100644 index 70c3f88430..0000000000 --- a/Editor/Mono/GUI/TreeView/AssetOrGameObjectTreeViewDragging.cs +++ /dev/null @@ -1,280 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEditor.IMGUI.Controls; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEditor.SceneManagement; -using UnityEditorInternal; - -namespace UnityEditor -{ - // Implements dragging behavior for HierarchyProperty based data: Assets or GameObjects - - internal class AssetsTreeViewDragging : TreeViewDragging - { - public AssetsTreeViewDragging(TreeViewController treeView) - : base(treeView) - { - } - - public override void StartDrag(TreeViewItem draggedItem, List draggedItemIDs) - { - DragAndDrop.PrepareStartDrag(); - - DragAndDrop.objectReferences = ProjectWindowUtil.GetDragAndDropObjects(draggedItem.id, draggedItemIDs); - - DragAndDrop.paths = ProjectWindowUtil.GetDragAndDropPaths(draggedItem.id, draggedItemIDs); - if (DragAndDrop.objectReferences.Length > 1) - DragAndDrop.StartDrag(""); - else - { - string title = ObjectNames.GetDragAndDropTitle(InternalEditorUtility.GetObjectFromInstanceID(draggedItem.id)); - DragAndDrop.StartDrag(title); - } - } - - public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPos) - { - var hierarchyProperty = new HierarchyProperty(HierarchyType.Assets); - if (parentItem == null || !hierarchyProperty.Find(parentItem.id, null)) - hierarchyProperty = null; - - // When hierarchyProperty == null then drag is performed on the Assets folder - return InternalEditorUtility.ProjectWindowDrag(hierarchyProperty, perform); - } - } - - - internal class GameObjectsTreeViewDragging : TreeViewDragging - { - const string kSceneHeaderDragString = "SceneHeaderList"; - - public GameObjectsTreeViewDragging(TreeViewController treeView) : base(treeView) {} - - public override void StartDrag(TreeViewItem draggedItem, List draggedItemIDs) - { - DragAndDrop.PrepareStartDrag(); - - if (Event.current.control || Event.current.command) - { - draggedItemIDs.Add(draggedItem.id); - } - - // Ensure correct order for hierarchy items (to preserve visible order when dropping at new location) - draggedItemIDs = m_TreeView.SortIDsInVisiblityOrder(draggedItemIDs); - - if (!draggedItemIDs.Contains(draggedItem.id)) - draggedItemIDs = new List {draggedItem.id}; - - Object[] draggedObjReferences = ProjectWindowUtil.GetDragAndDropObjects(draggedItem.id, draggedItemIDs); - DragAndDrop.objectReferences = draggedObjReferences; - - // After introducing multi-scene, UnityEngine.Scene can be selected in HierarchyWindow. - // UnityEngine.Scene is not a UnityEngine.Object. - // So DragAndDrop.objectReferences can't cover this case. - List draggedScenes = GetDraggedScenes(draggedItemIDs); - if (draggedScenes != null) - { - DragAndDrop.SetGenericData(kSceneHeaderDragString, draggedScenes); - - List paths = new List(); - foreach (Scene scene in draggedScenes) - { - if (scene.path.Length > 0) - paths.Add(scene.path); - } - DragAndDrop.paths = paths.ToArray(); - } - else - DragAndDrop.paths = new string[0]; - - string title; - if (draggedItemIDs.Count > 1) - title = ""; - else - { - if (draggedObjReferences.Length == 1) - title = ObjectNames.GetDragAndDropTitle(draggedObjReferences[0]); - else if (draggedScenes != null && draggedScenes.Count == 1) - title = draggedScenes[0].path; - else - { - title = "Unhandled dragged item"; - Debug.LogError("Unhandled dragged item"); - } - } - DragAndDrop.StartDrag(title); - - if (m_TreeView.data is GameObjectTreeViewDataSource) - { - ((GameObjectTreeViewDataSource)m_TreeView.data).SetupChildParentReferencesIfNeeded(); - } - } - - public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPos) - { - DragAndDropVisualMode dragSceneResult = DoDragScenes(parentItem as GameObjectTreeViewItem, targetItem as GameObjectTreeViewItem, perform, dropPos); - if (dragSceneResult != DragAndDropVisualMode.None) - return dragSceneResult; - - var option = InternalEditorUtility.HierarchyDropMode.kHierarchyDragNormal; - - var searchActive = !string.IsNullOrEmpty(((GameObjectTreeViewDataSource)m_TreeView.data).searchString); - if (searchActive) - option |= InternalEditorUtility.HierarchyDropMode.kHierarchySearchActive; - - if (parentItem == null || targetItem == null) - { - option |= InternalEditorUtility.HierarchyDropMode.kHierarchyDropUpon; - // We are dragging outside any treeview items: set it as last root sibling - return InternalEditorUtility.HierarchyWindowDrag(null, perform, option); // Using 'kHierarchyDropUpon' ensures last root sibling. - } - - // Here we are hovering over items - var hierarchyProperty = new HierarchyProperty(HierarchyType.GameObjects); - if (!hierarchyProperty.Find(targetItem.id, null)) - { - hierarchyProperty = null; - } - - var draggingUpon = dropPos == TreeViewDragging.DropPosition.Upon; - - if (searchActive && !draggingUpon) - { - return DragAndDropVisualMode.None; - } - - option |= (draggingUpon ? InternalEditorUtility.HierarchyDropMode.kHierarchyDropUpon : InternalEditorUtility.HierarchyDropMode.kHierarchyDropBetween); - - bool isDroppingBetweenParentAndFirstChild = parentItem != null && targetItem != parentItem && dropPos == DropPosition.Above && parentItem.children[0] == targetItem; - if (isDroppingBetweenParentAndFirstChild) - { - option |= InternalEditorUtility.HierarchyDropMode.kHierarchyDropAfterParent; - } - return InternalEditorUtility.HierarchyWindowDrag(hierarchyProperty, perform, option); - } - - public override void DragCleanup(bool revertExpanded) - { - DragAndDrop.SetGenericData(kSceneHeaderDragString, null); - - base.DragCleanup(revertExpanded); - } - - private List GetDraggedScenes(List draggedItemIDs) - { - List scenes = new List(); - foreach (int id in draggedItemIDs) - { - Scene scene = EditorSceneManager.GetSceneByHandle(id); - if (!SceneHierarchyWindow.IsSceneHeaderInHierarchyWindow(scene)) - return null; - scenes.Add(scene); - } - - return scenes; - } - - private DragAndDropVisualMode DoDragScenes(GameObjectTreeViewItem parentItem, GameObjectTreeViewItem targetItem, bool perform, DropPosition dropPos) - { - // We allow dragging SceneAssets on any game object in the Hierarchy to make it easy to drag in a Scene from - // the project browser. If dragging on a game object (not a sceneheader) we place the dropped scene - // below the game object's scene - - // Case: 1 - List scenes = DragAndDrop.GetGenericData(kSceneHeaderDragString) as List; - bool reorderExistingScenes = (scenes != null); - - // Case: 2 - bool insertNewScenes = false; - if (!reorderExistingScenes && DragAndDrop.objectReferences.Length > 0) - { - int sceneAssetCount = 0; - foreach (var dragged in DragAndDrop.objectReferences) - { - if (dragged is SceneAsset) - sceneAssetCount++; - } - insertNewScenes = (sceneAssetCount == DragAndDrop.objectReferences.Length); - } - - // Early out if not case 1 or 2 - if (!reorderExistingScenes && !insertNewScenes) - return DragAndDropVisualMode.None; - - if (perform) - { - List scenesToBeMoved = null; - if (insertNewScenes) - { - List insertedScenes = new List(); - foreach (var sceneAsset in DragAndDrop.objectReferences) - { - string scenePath = AssetDatabase.GetAssetPath(sceneAsset); - Scene scene = SceneManager.GetSceneByPath(scenePath); - if (SceneHierarchyWindow.IsSceneHeaderInHierarchyWindow(scene)) - m_TreeView.Frame(scene.handle, true, true); - else - { - bool unloaded = Event.current.alt; - if (unloaded) - scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.AdditiveWithoutLoading); - else - scene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Additive); - - if (SceneHierarchyWindow.IsSceneHeaderInHierarchyWindow(scene)) - insertedScenes.Add(scene); - } - } - if (targetItem != null) - scenesToBeMoved = insertedScenes; - - // Select added scenes and frame last scene - if (insertedScenes.Count > 0) - { - Selection.instanceIDs = insertedScenes.Select(x => x.handle).ToArray(); - m_TreeView.Frame(insertedScenes.Last().handle, true, false); - } - } - else // reorderExistingScenes - scenesToBeMoved = scenes; - - if (scenesToBeMoved != null) - { - if (targetItem != null) - { - Scene dstScene = targetItem.scene; - if (SceneHierarchyWindow.IsSceneHeaderInHierarchyWindow(dstScene)) - { - if (!targetItem.isSceneHeader || dropPos == DropPosition.Upon) - dropPos = DropPosition.Below; - - if (dropPos == DropPosition.Above) - { - for (int i = 0; i < scenesToBeMoved.Count; i++) - EditorSceneManager.MoveSceneBefore(scenesToBeMoved[i], dstScene); - } - else if (dropPos == DropPosition.Below) - { - for (int i = scenesToBeMoved.Count - 1; i >= 0; i--) - EditorSceneManager.MoveSceneAfter(scenesToBeMoved[i], dstScene); - } - } - } - else - { - Scene dstScene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1); - for (int i = scenesToBeMoved.Count - 1; i >= 0; i--) - EditorSceneManager.MoveSceneAfter(scenesToBeMoved[i], dstScene); - } - } - } - - return DragAndDropVisualMode.Move; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/GUI/TreeView/AssetsTreeViewDataSource.cs b/Editor/Mono/GUI/TreeView/AssetsTreeViewDataSource.cs deleted file mode 100644 index d1b8981501..0000000000 --- a/Editor/Mono/GUI/TreeView/AssetsTreeViewDataSource.cs +++ /dev/null @@ -1,318 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.IMGUI.Controls; -using UnityEditor.ProjectWindowCallback; -using UnityEngine; -using UnityEditorInternal; - - -namespace UnityEditor -{ - // AssetsTreeViewDataSource only fetches current visible items of the asset database tree, because we derive from LazyTreeViewDataSource - // Note: every time a Item's expanded state changes FetchData is called - - internal class AssetsTreeViewDataSource : LazyTreeViewDataSource - { - public bool foldersOnly { get; set; } - public bool foldersFirst { get; set; } - readonly int m_RootInstanceID; - const HierarchyType k_HierarchyType = HierarchyType.Assets; - - public AssetsTreeViewDataSource(TreeViewController treeView, int rootInstanceID, bool showRootItem, bool rootItemIsCollapsable) - : base(treeView) - { - m_RootInstanceID = rootInstanceID; - ((TreeViewDataSource)this).showRootItem = showRootItem; - rootIsCollapsable = rootItemIsCollapsable; - } - - static string CreateDisplayName(int instanceID) - { - return Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath(instanceID)); - } - - public override void FetchData() - { - // Create root Item - int depth = 0; - m_RootItem = new TreeViewItem(m_RootInstanceID, depth, null, CreateDisplayName(m_RootInstanceID)); - if (!showRootItem) - SetExpanded(m_RootItem, true); - - // Find start Item - var property = new HierarchyProperty(k_HierarchyType, false); - - property.Reset(); - bool found = property.Find(m_RootInstanceID, null); - if (!found) - Debug.LogError("Root Asset with id " + m_RootInstanceID + " not found!!"); - - int minDepth = property.depth + (showRootItem ? 0 : 1); - int[] expanded = expandedIDs.ToArray(); - Texture2D emptyFolderIcon = EditorGUIUtility.FindTexture(EditorResourcesUtility.emptyFolderIconName); - - // Fetch visible items - m_Rows = new List(); - while (property.NextWithDepthCheck(expanded, minDepth)) - { - if (!foldersOnly || property.isFolder) - { - depth = property.depth - minDepth; - TreeViewItem item; - if (property.isFolder) - item = new FolderTreeItem(property.instanceID, depth, null, property.name); - else - item = new NonFolderTreeItem(property.instanceID, depth, null, property.name); - - if (property.isFolder && !property.hasChildren) - item.icon = emptyFolderIcon; - else - item.icon = property.icon; - - if (property.hasChildren) - { - 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) - } - m_Rows.Add(item); - } - } - - // Setup reference between child and parent items - TreeViewUtility.SetChildParentReferences(m_Rows, m_RootItem); - - if (foldersFirst) - { - FoldersFirstRecursive(m_RootItem); - m_Rows.Clear(); - GetVisibleItemsRecursive(m_RootItem, m_Rows); - } - - // Must be called before InitSelection (it calls GetVisibleItems) - m_NeedRefreshRows = false; - - // We want to reset selection on copy/duplication/delete - bool frameLastSelected = false; // use false because we might just be expanding/collapsing a Item (which would prevent collapsing a Item with a selected child) - m_TreeView.SetSelection(Selection.instanceIDs, frameLastSelected); - } - - static void FoldersFirstRecursive(TreeViewItem item) - { - if (!item.hasChildren) - return; - - // Parent child relation is untouched, we simply move child folders to the beginning of - // the children array while keeping folders and files sorted. - TreeViewItem[] children = item.children.ToArray(); - for (int nonFolderPos = 0; nonFolderPos < item.children.Count; ++nonFolderPos) - { - if (children[nonFolderPos] == null) - continue; - - if (children[nonFolderPos] is NonFolderTreeItem) - { - for (int folderPos = nonFolderPos + 1; folderPos < children.Length; ++folderPos) - { - if (!(children[folderPos] is FolderTreeItem)) - continue; - - TreeViewItem folderItem = children[folderPos]; - int length = folderPos - nonFolderPos; - System.Array.Copy(children, nonFolderPos, children, nonFolderPos + 1, length); - children[nonFolderPos] = folderItem; - break; - } - } - - FoldersFirstRecursive(children[nonFolderPos]); - } - item.children = new List(children); - } - - protected override HashSet GetParentsAbove(int id) - { - int[] ancestorsInstanceIDs = ProjectWindowUtil.GetAncestors(id); - return new HashSet(ancestorsInstanceIDs); - } - - // Should return the items that have children from id and below - protected override HashSet GetParentsBelow(int id) - { - // Add all children expanded ids to hashset - HashSet parentsBelow = new HashSet(); - IHierarchyProperty search = new HierarchyProperty(k_HierarchyType); - if (search.Find(id, null)) - { - parentsBelow.Add(id); - - int depth = search.depth; - while (search.Next(null) && search.depth > depth) - { - if (search.hasChildren) - parentsBelow.Add(search.instanceID); - } - } - return parentsBelow; - } - - override public void OnExpandedStateChanged() - { - if (k_HierarchyType == HierarchyType.Assets) - InternalEditorUtility.expandedProjectWindowItems = expandedIDs.ToArray(); // Persist expanded state for ProjectBrowsers - - base.OnExpandedStateChanged(); - } - - override public bool IsRenamingItemAllowed(TreeViewItem item) - { - // Only main representations can be renamed (currently) - if (AssetDatabase.IsSubAsset(item.id)) - return false; - - // All items can be renamed except from the root Item - return item.parent != null; - } - - protected CreateAssetUtility GetCreateAssetUtility() - { - return ((TreeViewStateWithAssetUtility)m_TreeView.state).createAssetUtility; - } - - public int GetInsertAfterItemIDForNewItem(string newName, TreeViewItem parentItem, bool isCreatingNewFolder, bool foldersFirst) - { - if (!parentItem.hasChildren) - return parentItem.id; - - // Find pos under parent - int insertAfterID = parentItem.id; - for (int idx = 0; idx < parentItem.children.Count; ++idx) - { - int instanceID = parentItem.children[idx].id; - bool isFolder = parentItem.children[idx] is FolderTreeItem; - - // Skip folders when inserting a normal asset if folders is sorted first - if (foldersFirst && isFolder && !isCreatingNewFolder) - { - insertAfterID = instanceID; - continue; - } - - // When inserting a folder in folders first list break when we reach normal assets - if (foldersFirst && !isFolder && isCreatingNewFolder) - { - break; - } - - // Use same name compare as when we sort in the backend: See AssetDatabase.cpp: SortChildren - string propertyPath = AssetDatabase.GetAssetPath(instanceID); - if (EditorUtility.NaturalCompare(Path.GetFileNameWithoutExtension(propertyPath), newName) > 0) - { - break; - } - - insertAfterID = instanceID; - } - return insertAfterID; - } - - override public void InsertFakeItem(int id, int parentID, string name, Texture2D icon) - { - bool isCreatingNewFolder = GetCreateAssetUtility().endAction is DoCreateFolder; - - TreeViewItem checkItem = FindItem(id); - if (checkItem != null) - { - Debug.LogError("Cannot insert fake Item because id is not unique " + id + " Item already there: " + checkItem.displayName); - return; - } - - if (FindItem(parentID) != null) - { - // Ensure parent Item's children is visible - SetExpanded(parentID, true); - - var visibleRows = GetRows(); - - TreeViewItem parentItem; - int parentIndex = TreeViewController.GetIndexOfID(visibleRows, parentID); - if (parentIndex >= 0) - parentItem = visibleRows[parentIndex]; - else - parentItem = m_RootItem; // Fallback to root Item as parent - - // Create fake folder for insertion - int indentLevel = parentItem.depth + (parentItem == m_RootItem ? 0 : 1); - m_FakeItem = new TreeViewItem(id, indentLevel, parentItem, name); - m_FakeItem.icon = icon; - - // Find pos under parent - int insertAfterID = GetInsertAfterItemIDForNewItem(name, parentItem, isCreatingNewFolder, foldersFirst); - - // Find pos in expanded rows and insert - int index = TreeViewController.GetIndexOfID(visibleRows, insertAfterID); - if (index >= 0) - { - // Ensure to bypass all children of 'insertAfterID' - while (++index < visibleRows.Count) - { - if (visibleRows[index].depth <= indentLevel) - break; - } - - if (index < visibleRows.Count) - visibleRows.Insert(index, m_FakeItem); - else - visibleRows.Add(m_FakeItem); - } - else - { - // not visible parent: insert as first - if (visibleRows.Count > 0) - visibleRows.Insert(0, m_FakeItem); - else - visibleRows.Add(m_FakeItem); - } - - m_NeedRefreshRows = false; - - m_TreeView.Frame(m_FakeItem.id, true, false); - m_TreeView.Repaint(); - } - else - { - Debug.LogError("No parent Item found"); - } - } - - internal class SemiNumericDisplayNameListComparer : IComparer - { - public int Compare(TreeViewItem x, TreeViewItem y) - { - if (x == y) return 0; - if (x == null) return -1; - if (y == null) return 1; - return EditorUtility.NaturalCompare(x.displayName, y.displayName); - } - } - - // Classes used for type checking - class FolderTreeItem : TreeViewItem - { - public FolderTreeItem(int id, int depth, TreeViewItem parent, string displayName) - : base(id, depth, parent, displayName) - { - } - } - class NonFolderTreeItem : TreeViewItem - { - public NonFolderTreeItem(int id, int depth, TreeViewItem parent, string displayName) - : base(id, depth, parent, displayName) - { - } - } - } -} diff --git a/Editor/Mono/GUI/TreeView/AssetsTreeViewGUI.cs b/Editor/Mono/GUI/TreeView/AssetsTreeViewGUI.cs deleted file mode 100644 index df1f61e54b..0000000000 --- a/Editor/Mono/GUI/TreeView/AssetsTreeViewGUI.cs +++ /dev/null @@ -1,202 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEditor.ProjectWindowCallback; -using UnityEngine; -using UnityEditorInternal.VersionControl; -using UnityEditor.VersionControl; -using System.Collections.Generic; -using UnityEngine.Assertions; - -namespace UnityEditor -{ - internal class AssetsTreeViewGUI : TreeViewGUI - { - static bool s_VCEnabled; - const float k_IconOverlayPadding = 7f; - - internal delegate void OnAssetIconDrawDelegate(Rect iconRect, string guid); - internal static event OnAssetIconDrawDelegate postAssetIconDrawCallback = null; - - internal delegate bool OnAssetLabelDrawDelegate(Rect drawRect, string guid); - internal static event OnAssetLabelDrawDelegate postAssetLabelDrawCallback = null; - - private static IDictionary s_GUIDCache = null; - - public AssetsTreeViewGUI(TreeViewController treeView) - : base(treeView) - { - iconOverlayGUI += OnIconOverlayGUI; - labelOverlayGUI += OnLabelOverlayGUI; - k_TopRowMargin = 4f; - } - - // --------------------- - // OnGUI section - - override public void BeginRowGUI() - { - s_VCEnabled = Provider.isActive; - iconLeftPadding = iconRightPadding = s_VCEnabled ? k_IconOverlayPadding : 0f; - base.BeginRowGUI(); - } - - //------------------- - // Create asset and Rename asset section - - protected CreateAssetUtility GetCreateAssetUtility() - { - return ((TreeViewStateWithAssetUtility)m_TreeView.state).createAssetUtility; - } - - virtual protected bool IsCreatingNewAsset(int instanceID) - { - return GetCreateAssetUtility().IsCreatingNewAsset() && IsRenaming(instanceID); - } - - override protected void ClearRenameAndNewItemState() - { - GetCreateAssetUtility().Clear(); - base.ClearRenameAndNewItemState(); - } - - override protected void RenameEnded() - { - string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name; - int instanceID = GetRenameOverlay().userData; - bool isCreating = GetCreateAssetUtility().IsCreatingNewAsset(); - bool userAccepted = GetRenameOverlay().userAcceptedRename; - - if (userAccepted) - { - if (isCreating) - { - // Create a new asset - GetCreateAssetUtility().EndNewAssetCreation(name); - } - else - { - // Rename an existing asset - ObjectNames.SetNameSmartWithInstanceID(instanceID, name); - } - } - } - - override protected void SyncFakeItem() - { - if (!m_TreeView.data.HasFakeItem() && GetCreateAssetUtility().IsCreatingNewAsset()) - { - int parentInstanceID = AssetDatabase.GetMainAssetInstanceID(GetCreateAssetUtility().folder); - m_TreeView.data.InsertFakeItem(GetCreateAssetUtility().instanceID, parentInstanceID, GetCreateAssetUtility().originalName, GetCreateAssetUtility().icon); - } - - if (m_TreeView.data.HasFakeItem() && !GetCreateAssetUtility().IsCreatingNewAsset()) - { - m_TreeView.data.RemoveFakeItem(); - } - } - - // Not part of interface because it is very specific to creating assets - virtual public void BeginCreateNewAsset(int instanceID, EndNameEditAction endAction, string pathName, Texture2D icon, string resourceFile) - { - ClearRenameAndNewItemState(); - - if (GetCreateAssetUtility().BeginNewAssetCreation(instanceID, endAction, pathName, icon, resourceFile)) - { - SyncFakeItem(); - - // Start nameing the asset - bool renameStarted = GetRenameOverlay().BeginRename(GetCreateAssetUtility().originalName, instanceID, 0f); - if (!renameStarted) - Debug.LogError("Rename not started (when creating new asset)"); - } - } - - // Handles fetching rename icon or cached asset database icon - protected override Texture GetIconForItem(TreeViewItem item) - { - if (item == null) - return null; - - Texture icon = null; - if (IsCreatingNewAsset(item.id)) - icon = GetCreateAssetUtility().icon; - - if (icon == null) - icon = item.icon; - - if (icon == null && item.id != 0) - { - string path = AssetDatabase.GetAssetPath(item.id); - icon = AssetDatabase.GetCachedIcon(path); - } - return icon; - } - - private void OnIconOverlayGUI(TreeViewItem item, Rect overlayRect) - { - if (postAssetIconDrawCallback != null && AssetDatabase.IsMainAsset(item.id)) - { - string guid = GetGUIDForInstanceID(item.id); - postAssetIconDrawCallback(overlayRect, guid); - } - - // Draw vcs icons - if (s_VCEnabled && AssetDatabase.IsMainAsset(item.id)) - { - string guid = GetGUIDForInstanceID(item.id); - ProjectHooks.OnProjectWindowItem(guid, overlayRect); - } - } - - private void OnLabelOverlayGUI(TreeViewItem item, Rect labelRect) - { - if (postAssetLabelDrawCallback != null && AssetDatabase.IsMainAsset(item.id)) - { - string guid = GetGUIDForInstanceID(item.id); - postAssetLabelDrawCallback(labelRect, guid); - } - } - - // Returns a previously stored GUID for the given ID, - // else retrieves it from the asset database and stores it. - private static string GetGUIDForInstanceID(int instanceID) - { - if (s_GUIDCache == null) - { - s_GUIDCache = new Dictionary(); - } - - string GUID = null; - if (!s_GUIDCache.TryGetValue(instanceID, out GUID)) - { - string path = AssetDatabase.GetAssetPath(instanceID); - GUID = AssetDatabase.AssetPathToGUID(path); - Assert.IsTrue(!string.IsNullOrEmpty(GUID)); - s_GUIDCache.Add(instanceID, GUID); - } - - return GUID; - } - } - - - [System.Serializable] - internal class TreeViewStateWithAssetUtility : TreeViewState - { - [SerializeField] - CreateAssetUtility m_CreateAssetUtility = new CreateAssetUtility(); - - internal CreateAssetUtility createAssetUtility { get { return m_CreateAssetUtility; } set { m_CreateAssetUtility = value; } } - - internal override void OnAwake() - { - base.OnAwake(); - - // Clear state that should not survive closing/starting Unity (If TreeViewState is in EditorWindow that are serialized in a layout file) - m_CreateAssetUtility.Clear(); - } - } -} diff --git a/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs b/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs deleted file mode 100644 index 4cc67efb38..0000000000 --- a/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs +++ /dev/null @@ -1,575 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEditor.SceneManagement; -using UnityEditorInternal; -using System.Linq; -using System.Collections.Generic; -using UnityEditor.IMGUI.Controls; -using UnityEngine.Assertions; -using UnityEngine.Profiling; - -namespace UnityEditor -{ - // GameObjectTreeViewDataSource only fetches current visible items of the scene tree, because we derive from LazyTreeViewDataSource - // Note: every time a Item's expanded state changes FetchData is called - - internal class GameObjectTreeViewDataSource : LazyTreeViewDataSource - { - const double k_LongFetchTime = 0.05; // How much time is considered to be a long fetch - const double k_FetchDelta = 0.1; // How much time between long fetches is acceptable. - const int k_MaxDelayedFetch = 5; // How many consecutive fetches can be delayed. - const HierarchyType k_HierarchyType = HierarchyType.GameObjects; - const int k_DefaultStartCapacity = 1000; - - int m_RootInstanceID; - string m_SearchString = ""; - int m_SearchMode = 0; // 0 = All - double m_LastFetchTime = 0.0; - int m_DelayedFetches = 0; - bool m_NeedsChildParentReferenceSetup; - bool m_RowsPartiallyInitialized; - int m_RowCount; - List m_ListOfRows; // We need the generic List type in this class for Add/RemoveRange and Sorting (m_Rows is IList) - List m_StickySceneHeaderItems = new List(); - - public HierarchySorting sortingState = new TransformSorting(); - - public List sceneHeaderItems { get { return m_StickySceneHeaderItems; } } - public string searchString - { - get - { - return m_SearchString; - } - set - { - if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(m_SearchString)) - ClearSearchFilter(); - - m_SearchString = value; - } - } - public int searchMode { get { return m_SearchMode; } set { m_SearchMode = value; } } - public bool isFetchAIssue { get { return m_DelayedFetches >= k_MaxDelayedFetch; } } - - public GameObjectTreeViewDataSource(TreeViewController treeView, int rootInstanceID, bool showRoot, bool rootItemIsCollapsable) - : base(treeView) - { - m_RootInstanceID = rootInstanceID; - showRootItem = showRoot; - rootIsCollapsable = rootItemIsCollapsable; - } - - internal void SetupChildParentReferencesIfNeeded() - { - // Ensure all rows are initialized (not only the visible) - EnsureFullyInitialized(); - - // We delay the calling SetChildParentReferences until needed to ensure fast reloading of - // the game object hierarchy (in playmode this prevent hiccups for large scenes) - if (m_NeedsChildParentReferenceSetup) - { - m_NeedsChildParentReferenceSetup = false; - TreeViewUtility.SetChildParentReferences(GetRows(), m_RootItem); - } - } - - public void EnsureFullyInitialized() - { - if (m_RowsPartiallyInitialized) - { - InitializeFull(); - m_RowsPartiallyInitialized = false; - } - } - - override public int rowCount - { - get - { - return m_RowCount; - } - } - - public override void RevealItem(int itemID) - { - // Optimization: Only spend time on revealing item if it is part of the Hierarchy - if (IsValidHierarchyInstanceID(itemID)) - base.RevealItem(itemID); - } - - override public bool IsRevealed(int id) - { - return GetRow(id) != -1; - } - - private bool IsValidHierarchyInstanceID(int instanceID) - { - bool isScene = SceneHierarchyWindow.IsSceneHeaderInHierarchyWindow(EditorSceneManager.GetSceneByHandle(instanceID)); - bool isGameObject = InternalEditorUtility.GetTypeWithoutLoadingObject(instanceID) == typeof(GameObject); - return isScene || isGameObject; - } - - HierarchyProperty FindHierarchyProperty(int instanceID) - { - // Optimization: Prevent search by early out if 'id' is not a game object (or scene handle) - if (!IsValidHierarchyInstanceID(instanceID)) - return null; - - HierarchyProperty property = CreateHierarchyProperty(); - if (property.Find(instanceID, m_TreeView.state.expandedIDs.ToArray())) - return property; - - return null; - } - - override public int GetRow(int id) - { - bool isSearching = !string.IsNullOrEmpty(m_SearchString); - if (isSearching) - return base.GetRow(id); - - // We read from the backend directly instead of using GetRows() - // because we might not yet have initialized tree view after creating a new - // game object. GetRows also needs full init which we want to prevent - HierarchyProperty property = FindHierarchyProperty(id); - if (property != null) - return property.row; - - return -1; - } - - override public TreeViewItem GetItem(int row) - { - return m_Rows[row]; - } - - public override IList GetRows() - { - InitIfNeeded(); - EnsureFullyInitialized(); - - return m_Rows; - } - - override public TreeViewItem FindItem(int id) - { - // Since this is a LazyTreeViewDataSource that only knows about expanded items - // we need to reveal the item before searching for it (expand its ancestors) - RevealItem(id); - - // Since RevealItem can have reloaded data because items was revealed we need to make - // sure that parent child references is set up - SetupChildParentReferencesIfNeeded(); - - return base.FindItem(id); - } - - HierarchyProperty CreateHierarchyProperty() - { - HierarchyProperty property = new HierarchyProperty(k_HierarchyType); - property.Reset(); - property.alphaSorted = IsUsingAlphaSort(); - return property; - } - - void CreateRootItem(HierarchyProperty property) - { - int rootDepth = 0; // hiddden - - if (property.isValid) - { - // Game Object sub tree - m_RootItem = new GameObjectTreeViewItem(m_RootInstanceID, rootDepth, null, property.name); - } - else - { - // All game objects - m_RootItem = new GameObjectTreeViewItem(m_RootInstanceID, rootDepth, null, "RootOfAll"); - } - - // Ensure root is expanded if not shown - if (!showRootItem) - SetExpanded(m_RootItem, true); - } - - void ClearSearchFilter() - { - var property = CreateHierarchyProperty(); - property.SetSearchFilter("", 0); // 0 = All - } - - public override void FetchData() - { - Profiler.BeginSample("SceneHierarchyWindow.FetchData"); - m_RowsPartiallyInitialized = false; - double fetchStartTime = EditorApplication.timeSinceStartup; - - HierarchyProperty property = CreateHierarchyProperty(); - if (m_RootInstanceID != 0) - { - bool found = property.Find(m_RootInstanceID, null); - if (!found) - { - Debug.LogError("Root gameobject with id " + m_RootInstanceID + " not found!!"); - m_RootInstanceID = 0; - property.Reset(); - } - } - - CreateRootItem(property); - - // Must be set before SetSelection (they calls GetRows which will fetch again if m_NeedRefreshVisibleFolders = true) - m_NeedRefreshRows = false; - - m_NeedsChildParentReferenceSetup = true; - - bool subTreeWanted = m_RootInstanceID != 0; - bool isSearching = !string.IsNullOrEmpty(m_SearchString); - if (isSearching || subTreeWanted) - { - if (isSearching) - property.SetSearchFilter(m_SearchString, m_SearchMode); - - InitializeProgressivly(property, subTreeWanted, isSearching); - } - else - { - // We delay the setup of the full data and calling SetChildParentReferences to ensure fast reloading of - // the game object hierarchy - InitializeMinimal(); - } - - double fetchEndTime = EditorApplication.timeSinceStartup; - double fetchTotalTime = fetchEndTime - fetchStartTime; - double fetchDeltaTime = fetchEndTime - m_LastFetchTime; - - // If we have two relatively close consecutive fetches check execution time. - if (fetchDeltaTime > k_FetchDelta && fetchTotalTime > k_LongFetchTime) - m_DelayedFetches++; - else - m_DelayedFetches = 0; - m_LastFetchTime = fetchStartTime; - - // We want to reset selection on copy/duplication/delete - 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) - - CreateSceneHeaderItems(); - - if (SceneHierarchyWindow.s_Debug) - Debug.Log("Fetch time: " + fetchTotalTime * 1000.0 + " ms, alphaSort = " + IsUsingAlphaSort()); - - Profiler.EndSample(); - } - - public override bool CanBeParent(TreeViewItem item) - { - // Ensure parent child-parent references are setup if requesting parent information - SetupChildParentReferencesIfNeeded(); - - return base.CanBeParent(item); - } - - bool IsUsingAlphaSort() - { - return sortingState.GetType() == typeof(AlphabeticalSorting); - } - - static void Resize(List list, int count) - { - int cur = list.Count; - if (count < cur) - list.RemoveRange(count, cur - count); - else if (count > cur) - { - if (count > list.Capacity) // this bit is purely an optimisation, to avoid multiple automatic capacity changes. - list.Capacity = count + 20; // add some extra to prevent alloc'ing when adding to list - list.AddRange(Enumerable.Repeat(default(TreeViewItem), count - cur)); // add range is nulls - } - } - - private void ResizeItemList(int count) - { - AllocateBackingArrayIfNeeded(); - - if (m_ListOfRows.Count != count) - { - Resize(m_ListOfRows, count); - Assert.AreEqual(m_ListOfRows.Count, count, "List of rows count incorrect"); - } - } - - private void AllocateBackingArrayIfNeeded() - { - if (m_Rows == null) - { - int startCapacity = m_RowCount > k_DefaultStartCapacity ? m_RowCount : k_DefaultStartCapacity; - m_ListOfRows = new List(startCapacity); - m_Rows = m_ListOfRows; - } - } - - private void InitializeMinimal() - { - int[] expanded = m_TreeView.state.expandedIDs.ToArray(); - - HierarchyProperty property = CreateHierarchyProperty(); - m_RowCount = property.CountRemaining(expanded); - ResizeItemList(m_RowCount); - property.Reset(); - - if (SceneHierarchyWindow.debug) - Log("Init minimal (" + m_RowCount + ")"); - - int firstRow, lastRow; - m_TreeView.gui.GetFirstAndLastRowVisible(out firstRow, out lastRow); - - InitializeRows(property, firstRow, lastRow); - - m_RowsPartiallyInitialized = true; - } - - void InitializeFull() - { - if (SceneHierarchyWindow.debug) - Log("Init full (" + m_RowCount + ")"); - - HierarchyProperty property = CreateHierarchyProperty(); - m_RowCount = property.CountRemaining(m_TreeView.state.expandedIDs.ToArray()); - ResizeItemList(m_RowCount); - property.Reset(); - - InitializeRows(property, 0, m_RowCount - 1); - } - - // Used for search results, sub tree view (of e.g. a prefab) and custom sorting - void InitializeProgressivly(HierarchyProperty property, bool subTreeWanted, bool isSearching) - { - AllocateBackingArrayIfNeeded(); - - int minAllowedDepth = subTreeWanted ? property.depth + 1 : 0; - - if (!isSearching) - { - // Subtree setup - int row = 0; - int[] expanded = expandedIDs.ToArray(); - int subtractDepth = subTreeWanted ? property.depth + 1 : 0; - - while (property.NextWithDepthCheck(expanded, minAllowedDepth)) - { - var item = EnsureCreatedItem(row); - InitTreeViewItem(item, property, property.hasChildren, property.depth - subtractDepth); - row++; - } - m_RowCount = row; - } - else // Searching - { - m_RowCount = InitializeSearchResults(property, minAllowedDepth); - } - - // Now shrink to fit if needed - ResizeItemList(m_RowCount); - } - - // Returns number of rows in search result - int InitializeSearchResults(HierarchyProperty property, int minAllowedDepth) - { - // Search setup - const bool kShowItemHasChildren = false; - const int kItemDepth = 0; - int currentSceneHandle = -1; - int row = 0; - - var headerRows = new List(); - while (property.NextWithDepthCheck(null, minAllowedDepth)) - { - var item = EnsureCreatedItem(row); - // Add scene headers when encountering a new scene (and it's not a header in itself) - if (AddSceneHeaderToSearchIfNeeded(item, property, ref currentSceneHandle)) - { - row++; - headerRows.Add(row); - - if (IsSceneHeader(property)) - continue; // no need to add it - - item = EnsureCreatedItem(row); // prepare for item below - } - InitTreeViewItem(item, property, kShowItemHasChildren, kItemDepth); - row++; - } - - int numRows = row; - - // Now sort scene section - if (headerRows.Count > 0) - { - int currentSortStart = headerRows[0]; - for (int i = 1; i < headerRows.Count; i++) - { - int count = headerRows[i] - currentSortStart - 1; - m_ListOfRows.Sort(currentSortStart, count, new TreeViewItemAlphaNumericSort()); - currentSortStart = headerRows[i]; - } - - // last section - m_ListOfRows.Sort(currentSortStart, numRows - currentSortStart, new TreeViewItemAlphaNumericSort()); - } - - - return numRows; - } - - bool AddSceneHeaderToSearchIfNeeded(GameObjectTreeViewItem item, HierarchyProperty property, ref int currentSceneHandle) - { - Scene scene = property.GetScene(); - if (currentSceneHandle != scene.handle) - { - currentSceneHandle = scene.handle; - InitTreeViewItem(item, scene.handle, scene, true, 0, null, false, 0); - return true; - } - return false; - } - - GameObjectTreeViewItem EnsureCreatedItem(int row) - { - if (row >= m_Rows.Count) - m_Rows.Add(null); - - var item = (GameObjectTreeViewItem)m_Rows[row]; - if (item == null) - { - item = new GameObjectTreeViewItem(0, 0, null, null); - m_Rows[row] = item; - } - return item; - } - - void InitializeRows(HierarchyProperty property, int firstRow, int lastRow) - { - property.Reset(); - - int[] expanded = expandedIDs.ToArray(); - - // Skip items if needed - if (firstRow > 0) - { - int numRowsToSkip = firstRow; - if (!property.Skip(numRowsToSkip, expanded)) - Debug.LogError("Failed to skip " + numRowsToSkip); - } - - // Fetch visible items - int row = firstRow; - - while (property.Next(expanded) && row <= lastRow) - { - var item = EnsureCreatedItem(row); - InitTreeViewItem(item, property, property.hasChildren, property.depth); - row++; - } - } - - private void InitTreeViewItem(GameObjectTreeViewItem item, HierarchyProperty property, bool itemHasChildren, int itemDepth) - { - InitTreeViewItem(item, property.instanceID, property.GetScene(), IsSceneHeader(property), property.colorCode, property.pptrValue, itemHasChildren, itemDepth); - } - - private void InitTreeViewItem(GameObjectTreeViewItem item, int itemID, Scene scene, bool isSceneHeader, int colorCode, Object pptrObject, bool hasChildren, int depth) - { - item.children = null; - item.id = itemID; - item.depth = depth; - item.parent = null; - if (isSceneHeader) - item.displayName = string.IsNullOrEmpty(scene.name) ? "Untitled" : scene.name; - else - item.displayName = null; // For GameObject, name is empty as the name gets set from the objectPPTR if the Item is used in GameObjectTreeViewGUI. - - item.colorCode = colorCode; - item.objectPPTR = pptrObject; - item.shouldDisplay = true; - item.isSceneHeader = isSceneHeader; - item.scene = scene; - item.icon = isSceneHeader ? EditorGUIUtility.FindTexture(typeof(SceneAsset)) : null; - - if (hasChildren) - { - 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) - } - } - - bool IsSceneHeader(HierarchyProperty property) - { - return property.pptrValue == null; - } - - protected override HashSet GetParentsAbove(int id) - { - HashSet parents = new HashSet(); - if (!IsValidHierarchyInstanceID(id)) - return parents; - - IHierarchyProperty propertyIterator = new HierarchyProperty(k_HierarchyType); - if (propertyIterator.Find(id, null)) - { - while (propertyIterator.Parent()) - { - parents.Add((propertyIterator.instanceID)); - } - } - return parents; - } - - // Should return the items that have children from id and below - protected override HashSet GetParentsBelow(int id) - { - // Add all children expanded ids to hashset - HashSet parentsBelow = new HashSet(); - if (!IsValidHierarchyInstanceID(id)) - return parentsBelow; - - IHierarchyProperty search = new HierarchyProperty(k_HierarchyType); - if (search.Find(id, null)) - { - parentsBelow.Add(id); - - int depth = search.depth; - while (search.Next(null) && search.depth > depth) - { - if (search.hasChildren) - parentsBelow.Add(search.instanceID); - } - } - return parentsBelow; - } - - static void Log(string text) - { - //System.Console.WriteLine(text); - Debug.Log(text); - } - - void CreateSceneHeaderItems() - { - m_StickySceneHeaderItems.Clear(); - int numScenesInHierarchy = EditorSceneManager.sceneCount; - for (int i = 0; i < numScenesInHierarchy; ++i) - { - Scene scene = SceneManager.GetSceneAt(i); - - var item = new GameObjectTreeViewItem(0, 0, null, null); - InitTreeViewItem(item, scene.handle, scene, true, 0, null, false, 0); - - m_StickySceneHeaderItems.Add(item); - } - } - } -} diff --git a/Editor/Mono/GUI/TreeView/GameObjectTreeViewGUI.cs b/Editor/Mono/GUI/TreeView/GameObjectTreeViewGUI.cs deleted file mode 100644 index 1cadf3acc1..0000000000 --- a/Editor/Mono/GUI/TreeView/GameObjectTreeViewGUI.cs +++ /dev/null @@ -1,429 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEditor.IMGUI.Controls; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEditor.SceneManagement; - -namespace UnityEditor -{ - internal class GameObjectTreeViewGUI : TreeViewGUI - { - enum GameObjectColorType - { - Normal = 0, - Prefab = 1, - BrokenPrefab = 2, - Count = 3, - } - - internal static class GameObjectStyles - { - public static GUIStyle disabledLabel = new GUIStyle("PR DisabledLabel"); - public static GUIStyle prefabLabel = new GUIStyle("PR PrefabLabel"); - public static GUIStyle disabledPrefabLabel = new GUIStyle("PR DisabledPrefabLabel"); - public static GUIStyle brokenPrefabLabel = new GUIStyle("PR BrokenPrefabLabel"); - public static GUIStyle disabledBrokenPrefabLabel = new GUIStyle("PR DisabledBrokenPrefabLabel"); - public static GUIContent loadSceneGUIContent = new GUIContent(EditorGUIUtility.FindTexture("SceneLoadIn"), "Load scene"); - public static GUIContent unloadSceneGUIContent = new GUIContent(EditorGUIUtility.FindTexture("SceneLoadOut"), "Unload scene"); - public static GUIContent saveSceneGUIContent = new GUIContent(EditorGUIUtility.FindTexture("SceneSave"), "Save scene"); - public static GUIStyle optionsButtonStyle = "PaneOptions"; - public static GUIStyle sceneHeaderBg = "ProjectBrowserTopBarBg"; - - public static readonly int kSceneHeaderIconsInterval = 2; - - static GameObjectStyles() - { - disabledLabel.alignment = TextAnchor.MiddleLeft; - prefabLabel.alignment = TextAnchor.MiddleLeft; - disabledPrefabLabel.alignment = TextAnchor.MiddleLeft; - brokenPrefabLabel.alignment = TextAnchor.MiddleLeft; - disabledBrokenPrefabLabel.alignment = TextAnchor.MiddleLeft; - - ClearSelectionTexture(disabledLabel); - ClearSelectionTexture(prefabLabel); - ClearSelectionTexture(disabledPrefabLabel); - ClearSelectionTexture(brokenPrefabLabel); - ClearSelectionTexture(disabledBrokenPrefabLabel); - } - - static void ClearSelectionTexture(GUIStyle style) - { - var transparent = style.hover.background; - style.onNormal.background = transparent; - style.onActive.background = transparent; - style.onFocused.background = transparent; - } - } - - private float m_PrevScollPos; - private float m_PrevTotalHeight; - internal delegate void OnHeaderGUIDelegate(Rect availableRect, string scenePath); - internal static OnHeaderGUIDelegate OnPostHeaderGUI = null; - - public GameObjectTreeViewGUI(TreeViewController treeView, bool useHorizontalScroll) - : base(treeView, useHorizontalScroll) - { - k_TopRowMargin = 0f; - } - - public override void OnInitialize() - { - m_PrevScollPos = m_TreeView.state.scrollPos.y; - m_PrevTotalHeight = m_TreeView.GetTotalRect().height; - } - - public bool DetectUserInput() - { - if (DetectScrollChange()) - return true; - if (DetectTotalRectChange()) - return true; - if (DetectMouseDownInTreeViewRect()) - return true; - - return false; - } - - bool DetectScrollChange() - { - bool changed = false; - float curScroll = m_TreeView.state.scrollPos.y; - if (!Mathf.Approximately(curScroll, m_PrevScollPos)) - changed = true; - m_PrevScollPos = curScroll; - return changed; - } - - bool DetectTotalRectChange() - { - bool changed = false; - float curHeight = m_TreeView.GetTotalRect().height; - if (!Mathf.Approximately(curHeight, m_PrevTotalHeight)) - changed = true; - m_PrevTotalHeight = curHeight; - return changed; - } - - bool DetectMouseDownInTreeViewRect() - { - var evt = Event.current; - var mouseEvent = evt.type == EventType.MouseDown || evt.type == EventType.MouseUp; - var keyboardEvent = evt.type == EventType.KeyDown || evt.type == EventType.KeyUp; - if ((mouseEvent && m_TreeView.GetTotalRect().Contains(evt.mousePosition)) || keyboardEvent) - return true; - return false; - } - - bool showingStickyHeaders { get { return SceneManager.sceneCount > 1; } } - - void DoStickySceneHeaders() - { - int firstRow, lastRow; - GetFirstAndLastRowVisible(out firstRow, out lastRow); - if (firstRow >= 0 && lastRow >= 0) - { - float scrollY = m_TreeView.state.scrollPos.y; - if (firstRow == 0 && scrollY <= topRowMargin) - return; // Do nothing when first row is 0 since we do not need any sticky headers overlay - - var firstItem = (GameObjectTreeViewItem)m_TreeView.data.GetItem(firstRow); - var nextItem = (GameObjectTreeViewItem)m_TreeView.data.GetItem(firstRow + 1); - bool isFirstItemLastInScene = firstItem.scene != nextItem.scene; - float rowWidth = GUIClip.visibleRect.width; - Rect rect = GetRowRect(firstRow, rowWidth); - - // Do not do the sticky header if the scene is at top - if (firstItem.isSceneHeader && Mathf.Approximately(scrollY, rect.y)) - return; - - // Sticky header is achieved by ensuring the header never moves out of - // scroll and is aligned with last item in scene list if needed - if (!isFirstItemLastInScene) - rect.y = scrollY; - - var sceneHeaderItem = ((GameObjectTreeViewDataSource)m_TreeView.data).sceneHeaderItems.FirstOrDefault(p => p.scene == firstItem.scene); - if (sceneHeaderItem != null) - { - bool selected = m_TreeView.IsItemDragSelectedOrSelected(sceneHeaderItem); - bool focused = m_TreeView.HasFocus(); - bool boldFont = sceneHeaderItem.scene == SceneManager.GetActiveScene(); - DoItemGUI(rect, firstRow, sceneHeaderItem, selected, focused, boldFont); - - // Frame the actual scene header row (by clicking left of scene icon) - if (GUI.Button(new Rect(rect.x, rect.y, rect.height, rect.height), GUIContent.none, GUIStyle.none)) - m_TreeView.Frame(sceneHeaderItem.id, true, false); - - m_TreeView.HandleUnusedMouseEventsForItem(rect, sceneHeaderItem, firstRow); - - HandleStickyHeaderContextClick(rect, sceneHeaderItem); - } - } - } - - void HandleStickyHeaderContextClick(Rect rect, GameObjectTreeViewItem sceneHeaderItem) - { - Event evt = Event.current; - - // On OSX manually handle context click for sticky headers here to prevent items beneath the sticky header to also handle the event - if (Application.platform == RuntimePlatform.OSXEditor) - { - bool showContextMenu = (evt.type == EventType.MouseDown && evt.button == 1) || evt.type == EventType.ContextClick; // cmd+left click fires a context click event - if (showContextMenu && rect.Contains(Event.current.mousePosition)) - { - evt.Use(); - m_TreeView.contextClickItemCallback(sceneHeaderItem.id); - } - } - else if (Application.platform == RuntimePlatform.WindowsEditor) - { - if (evt.type == EventType.MouseDown && evt.button == 1 && rect.Contains(Event.current.mousePosition)) - { - // On Windows prevent right mouse down to propagate to items beneath (which will select items below this item) - evt.Use(); - } - } - } - - public override void BeginRowGUI() - { - if (DetectUserInput()) - { - var data = (GameObjectTreeViewDataSource)m_TreeView.data; - data.EnsureFullyInitialized(); - } - - base.BeginRowGUI(); - - // Sticky scene headers. Do non repaint events first to receive input first - if (showingStickyHeaders && Event.current.type != EventType.Repaint) - { - DoStickySceneHeaders(); - } - } - - public override void EndRowGUI() - { - base.EndRowGUI(); - - // Sticky scene headers. Do repaint events last to render on top. - if (showingStickyHeaders && Event.current.type == EventType.Repaint) - { - DoStickySceneHeaders(); - } - } - - public override Rect GetRectForFraming(int row) - { - Rect rect = base.GetRectForFraming(row); - if (showingStickyHeaders && row < m_TreeView.data.rowCount) - { - var item = m_TreeView.data.GetItem(row) as GameObjectTreeViewItem; - if (item != null && !item.isSceneHeader) - { - // For game objects under a sceneheader we create a larger frame rect to ensure row is shown - // beneath the sticky header (headers have same lineheight as rows) - rect.y -= k_LineHeight; - rect.height = 2 * k_LineHeight; - } - } - - return rect; - } - - //------------------- - // Create and Rename GameObject section - - override public bool BeginRename(TreeViewItem item, float delay) - { - GameObjectTreeViewItem goItem = item as GameObjectTreeViewItem; - if (goItem == null) - return false; - if (goItem.isSceneHeader) - return false; - - Object target = goItem.objectPPTR; - if ((target.hideFlags & HideFlags.NotEditable) != 0) - { - Debug.LogWarning("Unable to rename a GameObject with HideFlags.NotEditable."); - return false; - } - - return base.BeginRename(item, delay); - } - - override protected void RenameEnded() - { - string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name; - int instanceID = GetRenameOverlay().userData; - bool userAccepted = GetRenameOverlay().userAcceptedRename; - - if (userAccepted) - { - ObjectNames.SetNameSmartWithInstanceID(instanceID, name); - - // Manually set the name so no visual pop happens - TreeViewItem item = m_TreeView.data.FindItem(instanceID); - - if (item != null) - item.displayName = name; - - EditorApplication.RepaintAnimationWindow(); - } - } - - override protected void DoItemGUI(Rect rect, int row, TreeViewItem item, bool selected, bool focused, bool useBoldFont) - { - GameObjectTreeViewItem goItem = item as GameObjectTreeViewItem; - if (goItem == null) - return; - - // Scene header background (make it slightly transparent to hint it - // is not the normal scene header) - if (goItem.isSceneHeader) - { - Color oldColor = GUI.color; - GUI.color = GUI.color * new Color(1, 1, 1, 0.9f); - GUI.Label(rect, GUIContent.none, GameObjectStyles.sceneHeaderBg); - GUI.color = oldColor; - } - - base.DoItemGUI(rect, row, item, selected, focused, useBoldFont); - - // Scene header extras - if (goItem.isSceneHeader) - DoAdditionalSceneHeaderGUI(goItem, rect); - - if (SceneHierarchyWindow.s_Debug) - GUI.Label(new Rect(rect.xMax - 70, rect.y, 70, rect.height), "" + row + " (" + goItem.id + ")", EditorStyles.boldLabel); - } - - protected void DoAdditionalSceneHeaderGUI(GameObjectTreeViewItem goItem, Rect rect) - { - // Options button - const float optionsButtonWidth = 16f; - const float optionsButtonHeight = 6f; - const float margin = 4f; - Rect buttonRect = new Rect(rect.width - optionsButtonWidth - margin, rect.y + (rect.height - optionsButtonHeight) * 0.5f, optionsButtonWidth, rect.height); - if (Event.current.type == EventType.Repaint) - GameObjectStyles.optionsButtonStyle.Draw(buttonRect, false, false, false, false); - - // We want larger click area than the button icon - buttonRect.y = rect.y; - buttonRect.height = rect.height; - buttonRect.width = 24f; - if (EditorGUI.DropdownButton(buttonRect, GUIContent.none, FocusType.Passive, GUIStyle.none)) - { - // Ensure item is selected before using context menu (menu logic is based on selection) - m_TreeView.SelectionClick(goItem, true); - m_TreeView.contextClickItemCallback(goItem.id); - } - - if (null != OnPostHeaderGUI) - { - float optionsWidth = (rect.width - buttonRect.x); - float width = (rect.width - optionsWidth - margin); - float x = 0; - float y = rect.y; - float height = rect.height; - Rect availableRect = new Rect(x, y, width, height); - OnPostHeaderGUI(availableRect, goItem.scene.path); - } - } - - protected override void OnContentGUI(Rect rect, int row, TreeViewItem item, string label, bool selected, bool focused, - bool useBoldFont, bool isPinging) - { - if (Event.current.type != EventType.Repaint) - return; - - GameObjectTreeViewItem goItem = item as GameObjectTreeViewItem; - if (goItem == null) - return; - - if (goItem.isSceneHeader) - { - if (goItem.scene.isDirty) - label += "*"; - - switch (goItem.scene.loadingState) - { - case Scene.LoadingState.NotLoaded: - label += " (not loaded)"; - break; - case Scene.LoadingState.Loading: - label += " (is loading)"; - break; - } - - // Render disabled if scene is unloaded - bool isBold = (goItem.scene == SceneManager.GetActiveScene()); - using (new EditorGUI.DisabledScope(!goItem.scene.isLoaded)) - { - base.OnContentGUI(rect, row, item, label, selected, focused, isBold, isPinging); - } - return; - } - - if (!isPinging) - { - // The rect is assumed indented and sized after the content when pinging - rect.xMin += GetContentIndent(item) + extraSpaceBeforeIconAndLabel; - } - - int i = goItem.colorCode; - - if (string.IsNullOrEmpty(item.displayName)) - { - /* - * We refresh data between Editor and Player changes to the hierarchy. But we repaint after both has happened. - * So there is a possibility that the Player deleted a gameobject that is still cached in our DataSource. - * Due to risk mitigation for 4.5 we are working around this here. - * A proper fix should be to make sure we also fetch data after Player changes as well. - * Look into: Application.cpp and look where GetSceneTracker().TickHierarchyWindowHasChanged() is being called. - * Likely the proper fix will be adding another call to TickHierarchyWindowHasChanged after the Player had a chance to run. - */ - if (goItem.objectPPTR != null) - goItem.displayName = goItem.objectPPTR.name; - else - goItem.displayName = "deleted gameobject"; - label = goItem.displayName; - } - - GUIStyle lineStyle = Styles.lineStyle; - - if (!goItem.shouldDisplay) - { - lineStyle = GameObjectStyles.disabledLabel; // TODO: THis need to be a better color then just the disabled. - } - else - { - if ((i & 3) == (int)GameObjectColorType.Normal) - lineStyle = (i < 4) ? Styles.lineStyle : GameObjectStyles.disabledLabel; - else if ((i & 3) == (int)GameObjectColorType.Prefab) - lineStyle = (i < 4) ? GameObjectStyles.prefabLabel : GameObjectStyles.disabledPrefabLabel; - else if ((i & 3) == (int)GameObjectColorType.BrokenPrefab) - lineStyle = (i < 4) ? GameObjectStyles.brokenPrefabLabel : GameObjectStyles.disabledBrokenPrefabLabel; - } - - Texture icon = GetIconForItem(item); - - lineStyle.padding.left = 0; - if (icon != null) - { - Rect iconRect = rect; - iconRect.width = k_IconWidth; - GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit); - - rect.xMin += iconTotalPadding + k_IconWidth + k_SpaceBetweenIconAndText; - } - - // Draw text - lineStyle.Draw(rect, label, false, false, selected, focused); - } - } -} diff --git a/Editor/Mono/GUI/TreeView/GameObjectTreeViewItem.cs b/Editor/Mono/GUI/TreeView/GameObjectTreeViewItem.cs deleted file mode 100644 index 9827159af4..0000000000 --- a/Editor/Mono/GUI/TreeView/GameObjectTreeViewItem.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; -using UnityEngine.SceneManagement; - -namespace UnityEditor -{ - internal class GameObjectTreeViewItem : TreeViewItem - { - int m_ColorCode; - Object m_ObjectPPTR; - bool m_ShouldDisplay; - Scene m_UnityScene; - - public GameObjectTreeViewItem(int id, int depth, TreeViewItem parent, string displayName) - : base(id, depth, parent, displayName) - { - } - - public override string displayName - { - get - { - if (string.IsNullOrEmpty(base.displayName)) - { - if (m_ObjectPPTR != null) - displayName = objectPPTR.name; - else - displayName = "deleted gameobject"; - } - return base.displayName; - } - set { base.displayName = value; } - } - - virtual public int colorCode { get { return m_ColorCode; } set { m_ColorCode = value; } } - virtual public Object objectPPTR { get { return m_ObjectPPTR; } set { m_ObjectPPTR = value; } } - virtual public bool shouldDisplay { get { return m_ShouldDisplay; } set { m_ShouldDisplay = value; } } - - public bool isSceneHeader { get; set; } - public Scene scene - { - get { return m_UnityScene; } - set { m_UnityScene = value; } - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/ITreeViewDataSource.cs b/Editor/Mono/GUI/TreeView/ITreeViewDataSource.cs deleted file mode 100644 index 5a7ae5cb3f..0000000000 --- a/Editor/Mono/GUI/TreeView/ITreeViewDataSource.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -// The TreeView requires implementations from the following three interfaces: -// ITreeViewDataSource: Should handle data fetching, build the tree/data structure and hold expanded state -// ITreeViewGUI: Should handle visual representation of TreeView and input handling -// ITreeViewDragging Should handle dragging, temp expansion of items, allow/disallow dropping -// The TreeView handles: Navigation, Item selection and initiates dragging - - -namespace UnityEditor.IMGUI.Controls -{ - // Represents a complete data tree - internal interface ITreeViewDataSource - { - void OnInitialize(); - - // Return root of tree - TreeViewItem root { get; } - - // For data sources where GetRows() might be an expensive operation - int rowCount { get; } - - // Reload data - void ReloadData(); - - void InitIfNeeded(); - - // Find Item by id - TreeViewItem FindItem(int id); - - // Get current row of an item (using the current expanded state in TreeViewState) - // Returns -1 if not found - int GetRow(int id); - - // Check rowCount before requesting - TreeViewItem GetItem(int row); - - // Get the flattened tree of visible items. If possible use GetItem(int row) instead - IList GetRows(); - - bool IsRevealed(int id); - - void RevealItem(int id); - - // Expand / collapse interface - // The DataSource has the interface for this because it should be able to rebuild - // tree when expanding - void SetExpandedWithChildren(TreeViewItem item, bool expand); - void SetExpanded(TreeViewItem item, bool expand); - bool IsExpanded(TreeViewItem item); - bool IsExpandable(TreeViewItem item); - void SetExpandedWithChildren(int id, bool expand); - int[] GetExpandedIDs(); - void SetExpandedIDs(int[] ids); - bool SetExpanded(int id, bool expand); - bool IsExpanded(int id); - - // Selection - bool CanBeMultiSelected(TreeViewItem item); - bool CanBeParent(TreeViewItem item); - - // Renaming - bool IsRenamingItemAllowed(TreeViewItem item); - void InsertFakeItem(int id, int parentID, string name, Texture2D icon); - void RemoveFakeItem(); - bool HasFakeItem(); - - // Search - void OnSearchChanged(); - } -} // namespace UnityEditor diff --git a/Editor/Mono/GUI/TreeView/ITreeViewDragging.cs b/Editor/Mono/GUI/TreeView/ITreeViewDragging.cs deleted file mode 100644 index f7fad5c91f..0000000000 --- a/Editor/Mono/GUI/TreeView/ITreeViewDragging.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - - -namespace UnityEditor.IMGUI.Controls -{ - // The TreeView requires implementations from the following three interfaces: - // ITreeViewDataSource: Should handle data fetching and data structure - // ITreeViewGUI: Should handle visual representation of TreeView and input handling - // ITreeViewDragging Should handle dragging, temp expansion of items, allow/disallow dropping - // The TreeView handles: Navigation, Item selection and initiates dragging - - - // DragNDrop interface for tree views - internal interface ITreeViewDragging - { - void OnInitialize(); - bool CanStartDrag(TreeViewItem targetItem, List draggedItemIDs, Vector2 mouseDownPosition); - void StartDrag(TreeViewItem draggedItem, List draggedItemIDs); - bool DragElement(TreeViewItem targetItem, Rect targetItemRect, int row); // 'targetItem' is null when not hovering over any target Item. Returns true if drag was handled. - void DragCleanup(bool revertExpanded); - int GetDropTargetControlID(); - int GetRowMarkerControlID(); - bool drawRowMarkerAbove { get; set; } - } -} diff --git a/Editor/Mono/GUI/TreeView/ITreeViewGUI.cs b/Editor/Mono/GUI/TreeView/ITreeViewGUI.cs deleted file mode 100644 index 5a58489427..0000000000 --- a/Editor/Mono/GUI/TreeView/ITreeViewGUI.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -// The TreeView requires implementations from the following three interfaces: -// ITreeViewDataSource: Should handle data fetching and data structure -// ITreeViewGUI: Should handle visual representation of TreeView and input handling -// ITreeViewDragging Should handle dragging, temp expansion of items, allow/disallow dropping -// The TreeView handles: Navigation, Item selection and initiates dragging - - -namespace UnityEditor.IMGUI.Controls -{ - internal interface ITreeViewGUI - { - void OnInitialize(); - - // Should return the size of the entire visible content (in pixels). - Vector2 GetTotalSize(); - - // Should return the row number of the first and last row thats fits between top pixel and the height of the window - // If the treeview contains items with varying heights then use the minium height for determining the lastRowVisible - // this is needed when animating the treeview to ensure all items are rendered while animating. - // Can use TreeView.GetTotalRect and m_TreeView.state.scrollPos.y for calculating first and last values - void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible); - - Rect GetRowRect(int row, float rowWidth); - Rect GetRectForFraming(int row); - - int GetNumRowsOnPageUpDown(TreeViewItem fromItem, bool pageUp, float heightOfTreeView); - - // OnGUI: Implement to handle TreeView OnGUI - void OnRowGUI(Rect rowRect, TreeViewItem item, int row, bool selected, bool focused); - void BeginRowGUI(); // use for e.g clearing state before OnRowGUI calls - void EndRowGUI(); // use for handling stuff after all rows have had their OnRowGUI - - // Ping Item interface (implement a rendering of a 'ping' for a Item). - void BeginPingItem(TreeViewItem item, float topPixelOfRow, float availableWidth); - void EndPingItem(); - - // Rename interface (BeginRename should return true if rename is handled) - bool BeginRename(TreeViewItem item, float delay); - void EndRename(); - Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item); - - float GetContentIndent(TreeViewItem item); - - float halfDropBetweenHeight { get; } - float topRowMargin { get; } - float bottomRowMargin { get; } - } -} diff --git a/Editor/Mono/GUI/TreeView/LazyTreeViewDataSource.cs b/Editor/Mono/GUI/TreeView/LazyTreeViewDataSource.cs deleted file mode 100644 index 20034bd783..0000000000 --- a/Editor/Mono/GUI/TreeView/LazyTreeViewDataSource.cs +++ /dev/null @@ -1,126 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; - - -namespace UnityEditor.IMGUI.Controls -{ - // LazyTreeViewDataSource assumes that the Item tree only contains visible items, optimal for large data sets. - // Usage: - // - Override FetchData () and build the tree with visible items with m_RootItem as root (and and populate the m_VisibleRows List) - // - FetchData () is called every time the expanded state changes. - // - Configure showRootItem and rootIsCollapsable as wanted - // - // Note: if dealing with small trees consider using TreeViewDataSource instead: it assumes that the tree contains all items. - - internal abstract class LazyTreeViewDataSource : TreeViewDataSource - { - public LazyTreeViewDataSource(TreeViewController treeView) - : base(treeView) - { - } - - public static List CreateChildListForCollapsedParent() - { - // To mark a collapsed parent we use a list with one element that is null. - // The null element in the children list ensures we show the collapse arrow. - return new List() { null }; - } - - public static bool IsChildListForACollapsedParent(IList childList) - { - return (childList != null && childList.Count == 1 && childList[0] == null); // see CreateChildListForCollapsedParent - } - - // Return all ancestor items of the Item with 'id' - protected abstract HashSet GetParentsAbove(int id); - - // Return all descendant items that have children from the Item with 'id' - protected abstract HashSet GetParentsBelow(int id); - - override public void RevealItem(int itemID) - { - // Get existing expanded in hashset - HashSet expandedSet = new HashSet(expandedIDs); - int orgSize = expandedSet.Count; - - // Get all parents above id - HashSet candidates = GetParentsAbove(itemID); - - // Add parent ids - expandedSet.UnionWith(candidates); - - if (orgSize != expandedSet.Count) - { - // Bulk set expanded ids (is sorted in SetExpandedIDs) - SetExpandedIDs(expandedSet.ToArray()); - - // Refresh immediately if any Item was expanded - if (m_NeedRefreshRows) - FetchData(); - } - } - - override public TreeViewItem FindItem(int itemID) - { - // Since this is a LazyTreeViewDataSource that only knows about expanded items - // we need to reveal the item before searching for it (expand its ancestors) - RevealItem(itemID); - - // Now find the item after we have expanded and created parent items - return base.FindItem(itemID); - } - - override public void SetExpandedWithChildren(TreeViewItem item, bool expand) - { - SetExpandedWithChildren(item.id, expand); - } - - // Override for special handling of recursion - // We cannot recurse normally to tree Item children because we have not loaded children of collapsed items - // therefore let client implement GetParentsBelow to fetch ids instead - override public void SetExpandedWithChildren(int id, bool expand) - { - // Get existing expanded in hashset - HashSet oldExpandedSet = new HashSet(expandedIDs); - - // Add all children expanded ids to hashset - HashSet candidates = GetParentsBelow(id); - - if (expand) oldExpandedSet.UnionWith(candidates); - else oldExpandedSet.ExceptWith(candidates); - - // Bulk set expanded ids (is sorted in SetExpandedIDs) - SetExpandedIDs(oldExpandedSet.ToArray()); - - // Keep for debugging - // Debug.Log ("New expanded state (bulk): " + DebugUtils.ListToString(new List(expandedIDs))); - } - - public override void InitIfNeeded() - { - // Cached for large trees... - if (m_Rows == null || m_NeedRefreshRows) - { - FetchData(); // Only need to fetch visible data.. - - m_NeedRefreshRows = false; - - if (onVisibleRowsChanged != null) - onVisibleRowsChanged(); - - m_TreeView.Repaint(); - } - } - - // Get the flattened tree of visible items. Use GetFirstAndLastRowVisible to cull invisible items - override public IList GetRows() - { - InitIfNeeded(); - return m_Rows; - } - } -} diff --git a/Editor/Mono/GUI/TreeView/MultiColumnHeader.cs b/Editor/Mono/GUI/TreeView/MultiColumnHeader.cs deleted file mode 100644 index dacafac7d6..0000000000 --- a/Editor/Mono/GUI/TreeView/MultiColumnHeader.cs +++ /dev/null @@ -1,497 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public partial class MultiColumnHeader - { - MultiColumnHeaderState m_State; - float m_Height = DefaultGUI.defaultHeight; - float m_DividerWidth = 6; - Rect m_PreviousRect; - bool m_ResizeToFit = false; - bool m_CanSort = true; - GUIView m_GUIView; - Rect[] m_ColumnRects; - - public delegate void HeaderCallback(MultiColumnHeader multiColumnHeader); - public event HeaderCallback sortingChanged; - public event HeaderCallback visibleColumnsChanged; - - public MultiColumnHeader(MultiColumnHeaderState state) - { - m_State = state; - } - - public int sortedColumnIndex - { - get { return state.sortedColumnIndex; } - set - { - if (value != state.sortedColumnIndex) - { - state.sortedColumnIndex = value; - OnSortingChanged(); - } - } - } - - public void SetSortingColumns(int[] columnIndices, bool[] sortAscending) - { - if (columnIndices == null) - throw new ArgumentNullException("columnIndices"); - - if (sortAscending == null) - throw new ArgumentNullException("sortAscending"); - - if (columnIndices.Length != sortAscending.Length) - throw new ArgumentException("Input arrays should have same length"); - - if (columnIndices.Length > state.maximumNumberOfSortedColumns) - throw new ArgumentException("The maximum number of sorted columns is " + state.maximumNumberOfSortedColumns + ". Trying to set " + columnIndices.Length + " columns."); - - if (columnIndices.Length != columnIndices.Distinct().Count()) - throw new ArgumentException("Duplicate column indices are not allowed", "columnIndices"); - - bool changed = false; - - if (!columnIndices.SequenceEqual(state.sortedColumns)) - { - state.sortedColumns = columnIndices; - changed = true; - } - - for (int i = 0; i < columnIndices.Length; ++i) - { - var column = GetColumn(columnIndices[i]); - if (column.sortedAscending != sortAscending[i]) - { - column.sortedAscending = sortAscending[i]; - changed = true; - } - } - - if (changed) - OnSortingChanged(); - } - - public void SetSorting(int columnIndex, bool sortAscending) - { - bool changed = false; - if (state.sortedColumnIndex != columnIndex) - { - state.sortedColumnIndex = columnIndex; - changed = true; - } - - var column = GetColumn(columnIndex); - if (column.sortedAscending != sortAscending) - { - column.sortedAscending = sortAscending; - changed = true; - } - - if (changed) - OnSortingChanged(); - } - - public void SetSortDirection(int columnIndex, bool sortAscending) - { - var column = GetColumn(columnIndex); - if (column.sortedAscending != sortAscending) - { - column.sortedAscending = sortAscending; - OnSortingChanged(); - } - } - - public bool IsSortedAscending(int columnIndex) - { - return GetColumn(columnIndex).sortedAscending; - } - - public MultiColumnHeaderState.Column GetColumn(int columnIndex) - { - if (columnIndex < 0 || columnIndex >= state.columns.Length) - throw new ArgumentOutOfRangeException("columnIndex", string.Format("columnIndex {0} is not valid when the current column count is {1}", columnIndex, state.columns.Length)); - return state.columns[columnIndex]; - } - - public MultiColumnHeaderState state - { - get { return m_State; } - set - { - if (value == null) - throw new ArgumentNullException("state", "MultiColumnHeader state is not allowed to be null"); - m_State = value; - } - } - - public float height - { - get { return m_Height; } - set { m_Height = value; } - } - - public bool canSort - { - get { return m_CanSort; } - set - { - m_CanSort = value; - height = m_Height; - } - } - - public bool IsColumnVisible(int columnIndex) - { - return state.visibleColumns.Any(t => t == columnIndex); - } - - public int GetVisibleColumnIndex(int columnIndex) - { - for (int i = 0; i < state.visibleColumns.Length; i++) - { - if (state.visibleColumns[i] == columnIndex) - return i; - } - string visibleIndices = string.Join(", ", state.visibleColumns.Select(t => t.ToString()).ToArray()); - throw new ArgumentException(string.Format("Invalid columnIndex: {0}. The index is not part of the current visible columns: {1}", columnIndex, visibleIndices), "columnIndex"); - } - - public Rect GetCellRect(int visibleColumnIndex, Rect rowRect) - { - Rect result = GetColumnRect(visibleColumnIndex); - result.y = rowRect.y; - result.height = rowRect.height; - return result; - } - - public Rect GetColumnRect(int visibleColumnIndex) - { - if (visibleColumnIndex < 0 || visibleColumnIndex >= m_ColumnRects.Length) - 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"); - - return m_ColumnRects[visibleColumnIndex]; - } - - public void ResizeToFit() - { - m_ResizeToFit = true; - Repaint(); - } - - void UpdateColumnHeaderRects(Rect totalHeaderRect) - { - if (m_ColumnRects == null || m_ColumnRects.Length != state.visibleColumns.Length) - m_ColumnRects = new Rect[state.visibleColumns.Length]; - - Rect curRect = totalHeaderRect; - for (int v = 0; v < state.visibleColumns.Length; v++) - { - int columnIndex = state.visibleColumns[v]; - MultiColumnHeaderState.Column column = state.columns[columnIndex]; - - if (v > 0) - curRect.x += curRect.width; - curRect.width = column.width; - - m_ColumnRects[v] = curRect; - } - } - - // Virtual so clients can override header behavior and rendering entirely - public virtual void OnGUI(Rect rect, float xScroll) - { - Event evt = Event.current; - - if (m_GUIView == null) - m_GUIView = GUIView.current; - - DetectSizeChanges(rect); - - if (m_ResizeToFit && evt.type == EventType.Repaint) - { - m_ResizeToFit = false; - ResizeColumnsWidthsProportionally(rect.width - GUI.skin.verticalScrollbar.fixedWidth - state.widthOfAllVisibleColumns); - } - - // We create a guiclip to let the header be able to scroll horizontally according to the tree view's horizontal scroll - GUIClip.Push(rect, new Vector2(-xScroll, 0f), Vector2.zero, false); - { - Rect localRect = new Rect(0, 0, rect.width, rect.height); - - // Background ( We always add the width of the vertical scrollbar to accomodate if this is being shown below e.g by a tree view) - float widthOfAllColumns = state.widthOfAllVisibleColumns; - float backgroundWidth = (localRect.width > widthOfAllColumns ? localRect.width : widthOfAllColumns) + GUI.skin.verticalScrollbar.fixedWidth; - Rect backgroundRect = new Rect(0, 0, backgroundWidth, localRect.height); - GUI.Label(backgroundRect, GUIContent.none, DefaultStyles.background); - - // Context menu - if (evt.type == EventType.ContextClick && backgroundRect.Contains(evt.mousePosition)) - { - evt.Use(); - DoContextMenu(); - } - - // Update column rects (cached for clients to have fast access to column rects by using GetCellRect) - UpdateColumnHeaderRects(localRect); - - // Columns - for (int v = 0; v < state.visibleColumns.Length; v++) - { - int columnIndex = state.visibleColumns[v]; - MultiColumnHeaderState.Column column = state.columns[columnIndex]; - - Rect headerRect = m_ColumnRects[v]; - const float limitHeightOfDivider = 4f; - Rect dividerRect = new Rect(headerRect.xMax - 1, headerRect.y + limitHeightOfDivider, 1f, headerRect.height - 2 * limitHeightOfDivider); - - // Resize columns logic - Rect dragRect = new Rect(dividerRect.x - m_DividerWidth * 0.5f, localRect.y, m_DividerWidth, localRect.height); - bool hasControl; - column.width = EditorGUI.WidthResizer(dragRect, column.width, column.minWidth, column.maxWidth, out hasControl); - if (hasControl && evt.type == EventType.Repaint) - { - DrawColumnResizing(headerRect, column); - } - - // Draw divider (can be overridden) - DrawDivider(dividerRect, column); - - // Draw header (can be overridden) - ColumnHeaderGUI(column, headerRect, columnIndex); - } - } - GUIClip.Pop(); - } - - internal virtual void DrawColumnResizing(Rect headerRect, MultiColumnHeaderState.Column column) - { - const float margin = 1; - headerRect.y += margin; - headerRect.width -= margin; - headerRect.height -= 2 * margin; - EditorGUI.DrawRect(headerRect, new Color(0.5f, 0.5f, 0.5f, 0.1f)); - } - - internal virtual void DrawDivider(Rect dividerRect, MultiColumnHeaderState.Column column) - { - EditorGUI.DrawRect(dividerRect, new Color(0.5f, 0.5f, 0.5f, 0.5f)); - } - - protected virtual void ColumnHeaderClicked(MultiColumnHeaderState.Column column, int columnIndex) - { - if (state.sortedColumnIndex == columnIndex) - column.sortedAscending = !column.sortedAscending; - else - state.sortedColumnIndex = columnIndex; - - OnSortingChanged(); - } - - protected virtual void OnSortingChanged() - { - if (sortingChanged != null) - sortingChanged(this); - } - - protected virtual void ColumnHeaderGUI(MultiColumnHeaderState.Column column, Rect headerRect, int columnIndex) - { - if (canSort && column.canSort) - { - SortingButton(column, headerRect, columnIndex); - } - - GUIStyle style = GetStyle(column.headerTextAlignment); - - float labelHeight = EditorGUIUtility.singleLineHeight; - Rect labelRect = new Rect(headerRect.x, headerRect.yMax - labelHeight - DefaultGUI.labelSpaceFromBottom, headerRect.width, labelHeight); - GUI.Label(labelRect, column.headerContent, style); - } - - protected void SortingButton(MultiColumnHeaderState.Column column, Rect headerRect, int columnIndex) - { - // Button logic - if (EditorGUI.Button(headerRect, GUIContent.none, GUIStyle.none)) - { - ColumnHeaderClicked(column, columnIndex); - } - - // Draw sorting arrow - if (columnIndex == state.sortedColumnIndex && Event.current.type == EventType.Repaint) - { - var arrowRect = GetArrowRect(column, headerRect); - - Matrix4x4 normalMatrix = GUI.matrix; - if (column.sortedAscending) - GUIUtility.RotateAroundPivot(180, arrowRect.center - new Vector2(0, 1)); - - GUI.Label(arrowRect, "\u25BE", DefaultStyles.arrowStyle); - - if (column.sortedAscending) - GUI.matrix = normalMatrix; - } - } - - internal virtual Rect GetArrowRect(MultiColumnHeaderState.Column column, Rect headerRect) - { - float sortingArrowWidth = DefaultStyles.arrowStyle.fixedWidth; - float arrowYPos = headerRect.y; - float arrowXPos = 0f; - - switch (column.sortingArrowAlignment) - { - case TextAlignment.Left: - arrowXPos = headerRect.x + DefaultStyles.columnHeader.padding.left; - break; - case TextAlignment.Center: - arrowXPos = headerRect.x + headerRect.width * 0.5f - sortingArrowWidth * 0.5f; - break; - case TextAlignment.Right: - arrowXPos = headerRect.xMax - DefaultStyles.columnHeader.padding.right - sortingArrowWidth; - break; - default: - Debug.LogError("Unhandled enum"); - break; - } - - Rect arrowRect = new Rect(Mathf.Round(arrowXPos), arrowYPos, sortingArrowWidth, 16f); - return arrowRect; - } - - GUIStyle GetStyle(TextAlignment alignment) - { - switch (alignment) - { - case TextAlignment.Left: return DefaultStyles.columnHeader; - case TextAlignment.Center: return DefaultStyles.columnHeaderCenterAligned; - case TextAlignment.Right: return DefaultStyles.columnHeaderRightAligned; - default: return DefaultStyles.columnHeader; - } - } - - void DoContextMenu() - { - var menu = new GenericMenu(); - AddColumnHeaderContextMenuItems(menu); - menu.ShowAsContext(); - } - - protected virtual void AddColumnHeaderContextMenuItems(GenericMenu menu) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Resize to Fit"), false, ResizeToFit); - - menu.AddSeparator(""); - - for (int i = 0; i < state.columns.Length; ++i) - { - var column = state.columns[i]; - var menuText = !string.IsNullOrEmpty(column.contextMenuText) ? column.contextMenuText : column.headerContent.text; - if (column.allowToggleVisibility) - menu.AddItem(new GUIContent(menuText), state.visibleColumns.Contains(i), ToggleVisibility, i); - else - menu.AddDisabledItem(new GUIContent(menuText)); - } - } - - protected virtual void OnVisibleColumnsChanged() - { - if (visibleColumnsChanged != null) - visibleColumnsChanged(this); - } - - void ToggleVisibility(object userData) - { - ToggleVisibility((int)userData); - } - - protected virtual void ToggleVisibility(int columnIndex) - { - var newVisibleColumns = new List(state.visibleColumns); - if (newVisibleColumns.Contains(columnIndex)) - { - newVisibleColumns.Remove(columnIndex); - } - else - { - newVisibleColumns.Add(columnIndex); - newVisibleColumns.Sort(); - } - state.visibleColumns = newVisibleColumns.ToArray(); - Repaint(); - - OnVisibleColumnsChanged(); - } - - public void Repaint() - { - if (m_GUIView != null) - m_GUIView.Repaint(); - } - - void DetectSizeChanges(Rect rect) - { - if (Event.current.type == EventType.Repaint) - { - if (m_PreviousRect.width > 0f) - { - float deltaWidth = Mathf.Round(rect.width - m_PreviousRect.width); - if (deltaWidth != 0f) - { - float tep = GUI.skin.verticalScrollbar.fixedWidth; - bool isColumnsVisible = rect.width - tep > state.widthOfAllVisibleColumns; - if (isColumnsVisible || deltaWidth < 0f) - ResizeColumnsWidthsProportionally(deltaWidth); - } - } - m_PreviousRect = rect; - } - } - - void ResizeColumnsWidthsProportionally(float deltaWidth) - { - // Find auto resizing columns - List autoResizeColumns = null; - foreach (int i in state.visibleColumns) - { - MultiColumnHeaderState.Column column = state.columns[i]; - if (column.autoResize) - { - // Ignore the columns that cannot expand anymore - if (deltaWidth > 0f && column.width >= column.maxWidth) - continue; - // Ignore the columns that cannot shrink anymore - if (deltaWidth < 0f && column.width <= column.minWidth) - continue; - - if (autoResizeColumns == null) - autoResizeColumns = new List(); - - autoResizeColumns.Add(column); - } - } - - // Any auto resizing columns? - if (autoResizeColumns == null) - return; - - // Sum - float totalAutoResizeWidth = autoResizeColumns.Sum(x => x.width); - - // Distribute - foreach (var column in autoResizeColumns) - { - column.width += deltaWidth * (column.width / totalAutoResizeWidth); - column.width = Mathf.Clamp(column.width, column.minWidth, column.maxWidth); - } - } - } -} diff --git a/Editor/Mono/GUI/TreeView/MultiColumnHeaderDefaults.cs b/Editor/Mono/GUI/TreeView/MultiColumnHeaderDefaults.cs deleted file mode 100644 index a4c2eb8587..0000000000 --- a/Editor/Mono/GUI/TreeView/MultiColumnHeaderDefaults.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor.IMGUI.Controls -{ - public partial class MultiColumnHeader - { - public static class DefaultGUI - { - public static float defaultHeight { get { return 27f; } } - public static float minimumHeight { get { return 20f; } } - public static float columnContentMargin { get { return 3f; } } - internal static float labelSpaceFromBottom { get { return 3; } } - } - - public static class DefaultStyles - { - public static GUIStyle columnHeader; - public static GUIStyle columnHeaderRightAligned; - public static GUIStyle columnHeaderCenterAligned; - public static GUIStyle background; - internal static GUIStyle arrowStyle; - - static DefaultStyles() - { - // Use bar background with 1 pixel line at the bottom to let items have someting to clip against when scrolled - background = new GUIStyle("ProjectBrowserTopBarBg"); - background.fixedHeight = 0; - background.border = new RectOffset(3, 3, 3, 3); - - // Column header uses same colors as label, but slightly dimmed to let list items stand out more (similar to win 10) - // Use middle alignment to ensure labels are aligned regardless of icon size - columnHeader = new GUIStyle(EditorStyles.label); - columnHeader.alignment = TextAnchor.MiddleLeft; - columnHeader.padding = new RectOffset(4, 4, 0, 0); - Color col = columnHeader.normal.textColor; - col.a = 0.8f; - columnHeader.normal.textColor = col; - - columnHeaderRightAligned = new GUIStyle(columnHeader); - columnHeaderRightAligned.alignment = TextAnchor.MiddleRight; - - columnHeaderCenterAligned = new GUIStyle(columnHeader); - columnHeaderCenterAligned.alignment = TextAnchor.MiddleCenter; - - // Arrow uses same colors as label (derived) - arrowStyle = new GUIStyle(EditorStyles.label); - arrowStyle.padding = new RectOffset(); - arrowStyle.fixedWidth = 13f; - arrowStyle.alignment = TextAnchor.UpperCenter; // arrow is alligned at top - } - } - } -} diff --git a/Editor/Mono/GUI/TreeView/MultiColumnHeaderState.cs b/Editor/Mono/GUI/TreeView/MultiColumnHeaderState.cs deleted file mode 100644 index 563a497ed5..0000000000 --- a/Editor/Mono/GUI/TreeView/MultiColumnHeaderState.cs +++ /dev/null @@ -1,156 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - [Serializable] - public class MultiColumnHeaderState - { - [SerializeField] Column[] m_Columns; - [SerializeField] int[] m_VisibleColumns; - [SerializeField] List m_SortedColumns; // First item is most recent - [NonSerialized] int m_MaxNumberOfSortedColumns = 3; - - [Serializable] - public class Column - { - // Only serialize the fields that can be changed by the user (the others are reconstructed) - [SerializeField] public float width = 50; - [SerializeField] public bool sortedAscending; - [NonSerialized] public GUIContent headerContent = new GUIContent(); - [NonSerialized] public string contextMenuText; - [NonSerialized] public TextAlignment headerTextAlignment = TextAlignment.Left; - [NonSerialized] public TextAlignment sortingArrowAlignment = TextAlignment.Center; - [NonSerialized] public float minWidth = 20; - [NonSerialized] public float maxWidth = 1000000f; - [NonSerialized] public bool autoResize = true; - [NonSerialized] public bool allowToggleVisibility = true; - [NonSerialized] public bool canSort = true; - } - - public static bool CanOverwriteSerializedFields(MultiColumnHeaderState source, MultiColumnHeaderState destination) - { - if (source == null || destination == null) - return false; - - if (source.m_Columns == null || destination.m_Columns == null) - return false; - - return source.m_Columns.Length == destination.m_Columns.Length; - } - - public static void OverwriteSerializedFields(MultiColumnHeaderState source, MultiColumnHeaderState destination) - { - if (!CanOverwriteSerializedFields(source, destination)) - { - Debug.LogError("MultiColumnHeaderState: Not able to overwrite serialized fields"); - return; - } - - destination.m_VisibleColumns = source.m_VisibleColumns.ToArray(); - destination.m_SortedColumns = new List(source.m_SortedColumns); - - for (int i = 0; i < destination.m_Columns.Length; ++i) - { - destination.m_Columns[i].width = source.m_Columns[i].width; - destination.m_Columns[i].sortedAscending = source.m_Columns[i].sortedAscending; - } - } - - public MultiColumnHeaderState(Column[] columns) - { - if (columns == null) - throw new ArgumentException("columns are no allowed to be null", "columns"); - if (columns.Length == 0) - throw new ArgumentException("columns array should at least have one column: it is empty", "columns"); - - m_Columns = columns; - m_SortedColumns = new List(); - - // Default to all visible - m_VisibleColumns = new int[m_Columns.Length]; - for (int i = 0; i < m_Columns.Length; ++i) - m_VisibleColumns[i] = i; - } - - public int sortedColumnIndex - { - get - { - return m_SortedColumns.Count > 0 ? m_SortedColumns[0] : -1; - } - set - { - int current = m_SortedColumns.Count > 0 ? m_SortedColumns[0] : -1; - if (value != current) - { - if (value >= 0) - { - m_SortedColumns.Remove(value); - m_SortedColumns.Insert(0, value); - } - else - { - m_SortedColumns.Clear(); - } - } - } - } - - void RemoveInvalidSortingColumnsIndices() - { - m_SortedColumns.RemoveAll(x => x >= m_Columns.Length); - if (m_SortedColumns.Count > m_MaxNumberOfSortedColumns) - m_SortedColumns.RemoveRange(m_MaxNumberOfSortedColumns, m_SortedColumns.Count - m_MaxNumberOfSortedColumns); - } - - public int maximumNumberOfSortedColumns - { - get { return m_MaxNumberOfSortedColumns; } - set - { - m_MaxNumberOfSortedColumns = value; - RemoveInvalidSortingColumnsIndices(); - } - } - - public int[] sortedColumns - { - get { return m_SortedColumns.ToArray(); } - set - { - m_SortedColumns = value == null ? new List() : new List(value); - RemoveInvalidSortingColumnsIndices(); - } - } - - public Column[] columns - { - get { return m_Columns; } - } - - public int[] visibleColumns - { - get { return m_VisibleColumns; } - set - { - if (value == null) - throw new ArgumentException("visibleColumns should not be set to null"); - if (value.Length == 0) - throw new ArgumentException("visibleColumns should should not be set to an empty array. At least one visible column is required."); - m_VisibleColumns = value; - } - } - - public float widthOfAllVisibleColumns - { - get { return visibleColumns.Sum(t => columns[t].width); } - } - } -} diff --git a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControl.cs b/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControl.cs deleted file mode 100644 index 985e54fae4..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControl.cs +++ /dev/null @@ -1,825 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEngine; -using Debug = UnityEngine.Debug; - -namespace UnityEditor.IMGUI.Controls -{ - // The TreeView is a wrapper for the internal treeview system (wraps the TreeViewController and its 3 - // interfaces: ITreeViewDataSource, ITreeViewGUI, ITreeViewDragging) - // - It is intended for traditional treeviews and listviews (and supports multiple columns) - // - Usage: - // - Inherit from TreeView and implement the abtract methods. - // - Override the virtual methods for further customization (rendering, dragging, renaming etc) - // - Adjust layout properties - - public abstract partial class TreeView - { - TreeViewController m_TreeView; - TreeViewControlDataSource m_DataSource; - TreeViewControlGUI m_GUI; - TreeViewControlDragging m_Dragging; - MultiColumnHeader m_MultiColumnHeader; - List m_DefaultRows; - int m_TreeViewKeyControlID; - - OverriddenMethods m_OverriddenMethods; - - public TreeView(TreeViewState state) - { - Init(state); - } - - public TreeView(TreeViewState state, MultiColumnHeader multiColumnHeader) - { - m_MultiColumnHeader = multiColumnHeader; - Init(state); - } - - void Init(TreeViewState state) - { - if (state == null) - throw new ArgumentNullException("state", "Invalid TreeViewState: it is null"); - - m_TreeView = new TreeViewController(null, state); - m_DataSource = new TreeViewControlDataSource(m_TreeView, this); - m_GUI = new TreeViewControlGUI(m_TreeView, this); - m_Dragging = new TreeViewControlDragging(m_TreeView, this); - m_TreeView.Init(new Rect(), m_DataSource, m_GUI, m_Dragging); - - m_TreeView.searchChanged += SearchChanged; - m_TreeView.selectionChangedCallback += SelectionChanged; - m_TreeView.itemSingleClickedCallback += SingleClickedItem; - m_TreeView.itemDoubleClickedCallback += DoubleClickedItem; - m_TreeView.contextClickItemCallback += ContextClickedItem; - m_TreeView.contextClickOutsideItemsCallback += ContextClicked; - m_TreeView.expandedStateChanged += ExpandedStateChanged; - m_TreeView.keyboardInputCallback += KeyEvent; - - m_TreeViewKeyControlID = GUIUtility.GetPermanentControlID(); - } - - // The TreeView can be initialized in two ways: - // 1) Full tree: simplest conceptually and requires the least code. Just create the full tree - // in BuildRoot and return the root of tree. - // 2) For very large trees that often needs rebuilding of the tree structure it is more - // performant to just create the expanded rows and omitting all items under collapsed items. - // This can be achieved by: - // a) Just create the root item in BuildRoot (no descendants) - // b) Override BuildRows to handle how the rows are generated: Create the rows list - // only visiting expanded items. Also override GetAncestors and GetDescendantsWithChildren - // to use the backend data to fetch this information (since it might not be available in the TreeView) - protected abstract TreeViewItem BuildRoot(); - - - // Default implementation of BuildRows assumes full tree was built in BuildRoot. With full tree we can also support search out of the box - protected virtual IList BuildRows(TreeViewItem root) - { - // Reuse cached list (for capacity) - if (m_DefaultRows == null) - m_DefaultRows = new List(100); - m_DefaultRows.Clear(); - - if (hasSearch) - m_DataSource.SearchFullTree(searchString, m_DefaultRows); - else - AddExpandedRows(root, m_DefaultRows); - return m_DefaultRows; - } - - public void Reload() - { - if (m_OverriddenMethods == null) - m_OverriddenMethods = new OverriddenMethods(this); - m_TreeView.ReloadData(); - } - - public void Repaint() - { - m_TreeView.Repaint(); - } - - public TreeViewState state { get { return m_TreeView.state; } } - public MultiColumnHeader multiColumnHeader { get { return m_MultiColumnHeader; } set { m_MultiColumnHeader = value; }} - - protected TreeViewItem rootItem - { - get { return m_TreeView.data.root; } - } - - protected bool isInitialized - { - get { return m_DataSource.isInitialized; } - } - - // Layout variables - protected Rect treeViewRect - { - get { return m_TreeView.GetTotalRect(); } - set { m_TreeView.SetTotalRect(value); } - } - - protected float baseIndent - { - get { return m_GUI.k_BaseIndent; } - set { m_GUI.k_BaseIndent = value; } - } - - protected float foldoutWidth - { - get { return m_GUI.foldoutWidth; } - } - - protected float extraSpaceBeforeIconAndLabel - { - get { return m_GUI.extraSpaceBeforeIconAndLabel; } - set { m_GUI.extraSpaceBeforeIconAndLabel = value; } - } - - protected float customFoldoutYOffset - { - get { return m_GUI.customFoldoutYOffset; } - set { m_GUI.customFoldoutYOffset = value; } - } - - protected int columnIndexForTreeFoldouts - { - get { return m_GUI.columnIndexForTreeFoldouts; } - set - { - if (multiColumnHeader == null) - throw new InvalidOperationException("Setting columnIndexForTreeFoldouts can only be set when using TreeView with a MultiColumnHeader"); - - if (value < 0 || value >= multiColumnHeader.state.columns.Length) - throw new ArgumentOutOfRangeException("value", string.Format("Invalid index for columnIndexForTreeFoldouts: {0}. Number of available columns: {1}", value, multiColumnHeader.state.columns.Length)); - - m_GUI.columnIndexForTreeFoldouts = value; - } - } - - protected Rect GetCellRectForTreeFoldouts(Rect rowRect) - { - if (multiColumnHeader == null) - throw new InvalidOperationException("GetCellRect can only be called when 'multiColumnHeader' has been set"); - - int columnIndex = columnIndexForTreeFoldouts; - int visibleColumnIndex = multiColumnHeader.GetVisibleColumnIndex(columnIndex); - return multiColumnHeader.GetCellRect(visibleColumnIndex, rowRect); - } - - protected float depthIndentWidth - { - get { return m_GUI.k_IndentWidth; } - } - - protected bool showAlternatingRowBackgrounds { get; set; } - protected bool showBorder { get; set; } - protected bool showingHorizontalScrollBar { get { return m_TreeView.showingHorizontalScrollBar; }} - protected bool showingVerticalScrollBar { get { return m_TreeView.showingVerticalScrollBar; } } - - protected float cellMargin - { - get { return m_GUI.cellMargin; } - set { m_GUI.cellMargin = value; } - } - - public float totalHeight - { - get { return m_GUI.totalHeight + (showBorder ? m_GUI.borderWidth * 2 : 0f); } - } - - protected float rowHeight - { - get { return m_GUI.k_LineHeight; } - set { m_GUI.k_LineHeight = Mathf.Max(value, EditorGUIUtility.singleLineHeight); } - } - - public int treeViewControlID - { - get { return m_TreeViewKeyControlID; } - set { m_TreeViewKeyControlID = value; } - } - - protected bool isDragging - { - get { return m_TreeView.isDragging; } - } - - protected Rect GetRowRect(int row) - { - return m_TreeView.gui.GetRowRect(row, GUIClip.visibleRect.width); - } - - public virtual IList GetRows() - { - if (!isInitialized) - return null; - - return m_TreeView.data.GetRows(); - } - - protected IList FindRows(IList ids) - { - return GetRows().Where(item => ids.Contains(item.id)).ToList(); - } - - protected TreeViewItem FindItem(int id, TreeViewItem searchFromThisItem) - { - return TreeViewUtility.FindItem(id, searchFromThisItem); - } - - protected void GetFirstAndLastVisibleRows(out int firstRowVisible, out int lastRowVisible) - { - m_GUI.GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible); - } - - // Expanded interface - public void ExpandAll() - { - SetExpandedRecursive(rootItem.id, true); - } - - public void CollapseAll() - { - SetExpanded(new int[0]); - } - - public void SetExpandedRecursive(int id, bool expanded) - { - m_DataSource.SetExpandedWithChildren(id, expanded); - } - - public bool SetExpanded(int id, bool expanded) - { - return m_DataSource.SetExpanded(id, expanded); - } - - public void SetExpanded(IList ids) - { - m_DataSource.SetExpandedIDs(ids.ToArray()); - } - - public IList GetExpanded() - { - return m_DataSource.GetExpandedIDs(); - } - - public bool IsExpanded(int id) - { - return m_DataSource.IsExpanded(id); - } - - // Search interface - public bool hasSearch - { - get { return !string.IsNullOrEmpty(searchString); } - } - - public string searchString - { - get { return m_TreeView.searchString; } - set { m_TreeView.searchString = value; } - } - - // Selection interface - public IList GetSelection() - { - return m_TreeView.GetSelection(); - } - - public void SetSelection(IList selectedIDs) - { - SetSelection(selectedIDs, TreeViewSelectionOptions.None); - } - - public void SetSelection(IList selectedIDs, TreeViewSelectionOptions options) - { - bool fireSelectionChanged = (options & TreeViewSelectionOptions.FireSelectionChanged) != 0; - bool revealSelectionAndFrameLastSelected = (options & TreeViewSelectionOptions.RevealAndFrame) != 0; - bool animatedFraming = false; - - m_TreeView.SetSelection(selectedIDs.ToArray(), revealSelectionAndFrameLastSelected, animatedFraming); - if (fireSelectionChanged) - m_TreeView.NotifyListenersThatSelectionChanged(); - } - - public bool IsSelected(int id) - { - return m_TreeView.IsSelected(id); - } - - public bool HasSelection() - { - return m_TreeView.HasSelection(); - } - - public bool HasFocus() - { - return m_TreeView.HasFocus(); - } - - public void SetFocus() - { - GUIUtility.keyboardControl = m_TreeViewKeyControlID; - EditorGUIUtility.editingTextField = false; - } - - public void SetFocusAndEnsureSelectedItem() - { - SetFocus(); - - if (GetRows().Count > 0) - { - if (m_TreeView.IsLastClickedPartOfRows()) - FrameItem(state.lastClickedID); - else - SetSelection(new[] { GetRows()[0].id }, TreeViewSelectionOptions.FireSelectionChanged | TreeViewSelectionOptions.RevealAndFrame); - } - } - - protected void SelectionClick(TreeViewItem item, bool keepMultiSelection) - { - m_TreeView.SelectionClick(item, keepMultiSelection); - } - - // Rename interface - public bool BeginRename(TreeViewItem item) - { - return BeginRename(item, 0f); - } - - public bool BeginRename(TreeViewItem item, float delay) - { - return m_GUI.BeginRename(item, delay); - } - - public void EndRename() - { - m_GUI.EndRename(); - } - - // Frame interface - public void FrameItem(int id) - { - bool animated = false; - m_TreeView.Frame(id, true, false, animated); - } - - bool m_WarnedUser; - bool ValidTreeView() - { - if (isInitialized) - return true; - - if (!m_WarnedUser) - { - Debug.LogError("TreeView has not been properly intialized yet. Ensure to call Reload() before using the tree view."); - m_WarnedUser = true; - } - return false; - } - - // OnGUI entry - public virtual void OnGUI(Rect rect) - { - if (!ValidTreeView()) - return; - - m_TreeView.OnEvent(); - - if (showBorder) - rect = m_GUI.DoBorder(rect); - - if (m_MultiColumnHeader != null) - TreeViewWithMultiColumnHeader(rect); - else - m_TreeView.OnGUI(rect, m_TreeViewKeyControlID); - - CommandEventHandling(); - } - - public void SelectAllRows() - { - var rows = GetRows(); - var allowedSelection = (from treeViewItem in rows where CanMultiSelect(treeViewItem) select treeViewItem.id).ToList(); - SetSelection(allowedSelection, TreeViewSelectionOptions.FireSelectionChanged); - } - - void TreeViewWithMultiColumnHeader(Rect rect) - { - Rect columnHeaderRect = new Rect(rect.x, rect.y, rect.width, m_MultiColumnHeader.height); - Rect treeRect = new Rect(rect.x, columnHeaderRect.yMax, rect.width, rect.height - columnHeaderRect.height); - - 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) - - Event evt = Event.current; - if (evt.type == EventType.MouseDown && columnHeaderRect.Contains(evt.mousePosition)) - GUIUtility.keyboardControl = m_TreeViewKeyControlID; - - m_MultiColumnHeader.OnGUI(columnHeaderRect, scrollX); - m_TreeView.OnGUI(treeRect, m_TreeViewKeyControlID); - } - - // GUI helper methods (for custon drawing) - - protected float GetFoldoutIndent(TreeViewItem item) - { - return m_GUI.GetFoldoutIndent(item); - } - - protected float GetContentIndent(TreeViewItem item) - { - return m_GUI.GetContentIndent(item); - } - - protected IList SortItemIDsInRowOrder(IList ids) - { - return m_TreeView.SortIDsInVisiblityOrder(ids); - } - - protected void CenterRectUsingSingleLineHeight(ref Rect rect) - { - float singleLineHeight = EditorGUIUtility.singleLineHeight; - if (rect.height > singleLineHeight) - { - rect.y += (rect.height - singleLineHeight) * 0.5f; - rect.height = singleLineHeight; - } - } - - protected void AddExpandedRows(TreeViewItem root, IList rows) - { - if (root == null) - throw new ArgumentNullException("root", "root is null"); - - if (rows == null) - throw new ArgumentNullException("rows", "rows is null"); - - if (root.hasChildren) - foreach (TreeViewItem child in root.children) - GetExpandedRowsRecursive(child, rows); - } - - void GetExpandedRowsRecursive(TreeViewItem item, IList expandedRows) - { - if (item == null) - Debug.LogError("Found a TreeViewItem that is null. Invalid use of AddExpandedRows(): This method is only valid to call if you have built the full tree of TreeViewItems."); - - expandedRows.Add(item); - - if (item.hasChildren && IsExpanded(item.id)) - foreach (TreeViewItem child in item.children) - GetExpandedRowsRecursive(child, expandedRows); - } - - protected virtual void SelectionChanged(IList selectedIds) - { - } - - protected virtual void SingleClickedItem(int id) - { - } - - protected virtual void DoubleClickedItem(int id) - { - } - - protected virtual void ContextClickedItem(int id) - { - } - - protected virtual void ContextClicked() - { - } - - protected virtual void ExpandedStateChanged() - { - } - - protected virtual void SearchChanged(string newSearch) - { - } - - protected virtual void KeyEvent() - { - } - - // Used to reveal an item - protected virtual IList GetAncestors(int id) - { - // Default behavior assumes complete tree - return TreeViewUtility.GetParentsAboveItem(FindItem(id)).ToList(); - } - - // Used to expand children recursively below an item - protected virtual IList GetDescendantsThatHaveChildren(int id) - { - // Default behavior assumes complete tree - return TreeViewUtility.GetParentsBelowItem(FindItem(id)).ToList(); - } - - TreeViewItem FindItem(int id) - { - if (rootItem == null) - throw new InvalidOperationException("FindItem failed: root item has not been created yet"); - - var item = TreeViewUtility.FindItem(id, rootItem); - if (item == null) - throw new ArgumentException(string.Format("Could not find item with id: {0}. FindItem assumes complete tree is built. Most likely the item is not allocated because it is hidden under a collapsed item. Check if GetAncestors are overriden for the tree view.", id)); - return item; - } - - // Selection - protected virtual bool CanMultiSelect(TreeViewItem item) - { - return true; // default behavior - } - - // Renaming - protected virtual bool CanRename(TreeViewItem item) - { - return false; // Default to false so user have to enable renaming if wanted - } - - protected virtual void RenameEnded(RenameEndedArgs args) - { - } - - // Dragging - protected virtual bool CanStartDrag(CanStartDragArgs args) - { - return false; - } - - protected virtual void SetupDragAndDrop(SetupDragAndDropArgs args) - { - } - - protected virtual DragAndDropVisualMode HandleDragAndDrop(DragAndDropArgs args) - { - return DragAndDropVisualMode.None; - } - - protected virtual bool CanBeParent(TreeViewItem item) - { - return true; // default behavior - } - - protected virtual bool CanChangeExpandedState(TreeViewItem item) - { - // Default: Ignore expansion (foldout arrow) when showing search results - if (m_TreeView.isSearching) - return false; - return item.hasChildren; - } - - protected virtual bool DoesItemMatchSearch(TreeViewItem item, string search) - { - return item.displayName.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0; - } - - // Custom GUI - protected virtual void RowGUI(RowGUIArgs args) - { - m_GUI.DefaultRowGUI(args); - } - - protected virtual void BeforeRowsGUI() - { - if (showAlternatingRowBackgrounds) - m_GUI.DrawAlternatingRowBackgrounds(); - } - - protected virtual void AfterRowsGUI() - { - } - - protected virtual void RefreshCustomRowHeights() - { - if (!m_OverriddenMethods.hasGetCustomRowHeight) - throw new InvalidOperationException("Only call RefreshCustomRowHeights if you have overridden GetCustomRowHeight to customize the height of each row."); - m_GUI.RefreshRowRects(GetRows()); - } - - protected virtual float GetCustomRowHeight(int row, TreeViewItem item) - { - return rowHeight; - } - - protected virtual Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item) - { - return m_GUI.DefaultRenameRect(rowRect, row, item); - } - - protected virtual void CommandEventHandling() - { - Event evt = Event.current; - - if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand) - return; - - bool execute = evt.type == EventType.ExecuteCommand; - - if (HasFocus() && evt.commandName == EventCommandNames.SelectAll) - { - if (execute) - SelectAllRows(); - evt.Use(); - GUIUtility.ExitGUI(); - } - - if (evt.commandName == EventCommandNames.FrameSelected) - { - if (execute) - { - if (hasSearch) - searchString = string.Empty; - - if (HasSelection()) - FrameItem(GetSelection()[0]); - } - evt.Use(); - GUIUtility.ExitGUI(); - } - } - - protected static void SetupParentsAndChildrenFromDepths(TreeViewItem root, IList rows) - { - TreeViewUtility.SetChildParentReferences(rows, root); - } - - protected static void SetupDepthsFromParentsAndChildren(TreeViewItem root) - { - TreeViewUtility.SetDepthValuesForItems(root); - } - - protected static List CreateChildListForCollapsedParent() - { - return LazyTreeViewDataSource.CreateChildListForCollapsedParent(); - } - - protected static bool IsChildListForACollapsedParent(IList childList) - { - return LazyTreeViewDataSource.IsChildListForACollapsedParent(childList); - } - - class OverriddenMethods - { - public readonly bool hasRowGUI; - public readonly bool hasHandleDragAndDrop; - public readonly bool hasGetRenameRect; - public readonly bool hasBuildRows; - public readonly bool hasGetCustomRowHeight; - - public OverriddenMethods(TreeView treeView) - { - Type type = treeView.GetType(); - hasRowGUI = IsOverridden(type, "RowGUI"); - hasHandleDragAndDrop = IsOverridden(type, "HandleDragAndDrop"); - hasGetRenameRect = IsOverridden(type, "GetRenameRect"); - hasBuildRows = IsOverridden(type, "BuildRows"); - hasGetCustomRowHeight = IsOverridden(type, "GetCustomRowHeight"); - ValidateOverriddenMethods(treeView); - } - - static bool IsOverridden(Type type, string methodName) - { - var methodInfo = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); - if (methodInfo != null) - return methodInfo.GetBaseDefinition().DeclaringType != methodInfo.DeclaringType; - - Debug.LogError("IsOverridden: method name not found: " + methodName + " (check spelling against method declaration)"); - return false; - } - - void ValidateOverriddenMethods(TreeView treeView) - { - Type type = treeView.GetType(); - - bool hasCanRename = IsOverridden(type, "CanRename"); - bool hasRenameEnded = IsOverridden(type, "RenameEnded"); - if (hasRenameEnded != hasCanRename) - { - if (hasCanRename) - Debug.LogError(type.Name + ": If you are overriding CanRename you should also override RenameEnded (to handle the renaming)."); - - if (hasRenameEnded) - Debug.LogError(type.Name + ": If you are overriding RenameEnded you should also override CanRename (to allow renaming)."); - } - - bool hasCanStartDragAndDrop = IsOverridden(type, "CanStartDrag"); - bool hasSetupDragAndDrop = IsOverridden(type, "SetupDragAndDrop"); - if (hasCanStartDragAndDrop != hasSetupDragAndDrop) - { - if (hasCanStartDragAndDrop) - Debug.LogError(type.Name + ": If you are overriding CanStartDrag you should also override SetupDragAndDrop (to setup the drag)."); - - if (hasSetupDragAndDrop) - Debug.LogError(type.Name + ": If you are overriding SetupDragAndDrop you should also override CanStartDrag (to allow dragging)."); - } - } - }; - - // Nested because they are used by protected methods - protected struct RowGUIArgs - { - public TreeViewItem item; - public string label; - public Rect rowRect; - public int row; - public bool selected; - public bool focused; - public bool isRenaming; - internal MultiColumnInfo columnInfo { get; set; } - - public int GetNumVisibleColumns() - { - if (!HasMultiColumnInfo()) - throw new NotSupportedException("Only call this method if you are using a MultiColumnHeader with the TreeView."); - - return columnInfo.multiColumnHeaderState.visibleColumns.Length; - } - - public int GetColumn(int visibleColumnIndex) - { - if (!HasMultiColumnInfo()) - throw new NotSupportedException("Only call this method if you are using a MultiColumnHeader with the TreeView."); - - return columnInfo.multiColumnHeaderState.visibleColumns[visibleColumnIndex]; - } - - public Rect GetCellRect(int visibleColumnIndex) - { - if (!HasMultiColumnInfo()) - throw new NotSupportedException("Only call this method if you are using a MultiColumnHeader with the TreeView."); - - return columnInfo.cellRects[visibleColumnIndex]; - } - - internal bool HasMultiColumnInfo() - { - return columnInfo.multiColumnHeaderState != null; - } - - internal struct MultiColumnInfo - { - internal MultiColumnInfo(MultiColumnHeaderState multiColumnHeaderState, Rect[] cellRects) - { - this.multiColumnHeaderState = multiColumnHeaderState; - this.cellRects = cellRects; - } - - public MultiColumnHeaderState multiColumnHeaderState; - public Rect[] cellRects; - } - } - - protected struct DragAndDropArgs - { - public DragAndDropPosition dragAndDropPosition; - public TreeViewItem parentItem; - public int insertAtIndex; - public bool performDrop; - } - - protected struct SetupDragAndDropArgs - { - public IList draggedItemIDs; - } - - protected struct CanStartDragArgs - { - public TreeViewItem draggedItem; - public IList draggedItemIDs; - } - - protected struct RenameEndedArgs - { - public bool acceptedRename; - public int itemID; - public string originalName; - public string newName; - } - - protected enum DragAndDropPosition - { - UponItem, - BetweenItems, - OutsideItems - } - } - - [Flags] - public enum TreeViewSelectionOptions - { - None = 0, - FireSelectionChanged = 1, - RevealAndFrame = 2 - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDataSource.cs b/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDataSource.cs deleted file mode 100644 index 7fef75d816..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDataSource.cs +++ /dev/null @@ -1,133 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public partial class TreeView - { - internal class TreeViewControlDataSource : LazyTreeViewDataSource - { - readonly TreeView m_Owner; - - public TreeViewControlDataSource(TreeViewController treeView, TreeView owner) : base(treeView) - { - m_Owner = owner; - - // The user should just create the visible rows, we create the hidden root - showRootItem = false; - } - - public override void ReloadData() - { - // Clear root item to ensure client gets a call to BuildRoot every time Reload is called - m_RootItem = null; - base.ReloadData(); - } - - void ValidateRootItem() - { - if (m_RootItem == null) - { - throw new NullReferenceException("BuildRoot should set a valid root item."); - } - if (m_RootItem.depth != -1) - { - Debug.LogError("BuildRoot should ensure the root item has a depth == -1. The visible items start at depth == 0."); - m_RootItem.depth = -1; - } - if (m_RootItem.children == null && !m_Owner.m_OverriddenMethods.hasBuildRows) - { - 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."); - } - } - - public override void FetchData() - { - // Set before BuildRoot and BuildRows so we can call GetRows in them without recursion - m_NeedRefreshRows = false; - - // Root - if (m_RootItem == null) - { - m_RootItem = m_Owner.BuildRoot(); - ValidateRootItem(); - } - - // Rows - m_Rows = m_Owner.BuildRows(m_RootItem); - if (m_Rows == null) - throw new NullReferenceException("RefreshRows should set valid list of rows."); - - // Custom row rects - if (m_Owner.m_OverriddenMethods.hasGetCustomRowHeight) - m_Owner.m_GUI.RefreshRowRects(m_Rows); - } - - public void SearchFullTree(string search, List result) - { - if (string.IsNullOrEmpty(search)) - throw new ArgumentException("Invalid search: cannot be null or empty", "search"); - - if (result == null) - throw new ArgumentException("Invalid list: cannot be null", "result"); - - var stack = new Stack(); - stack.Push(m_RootItem); - while (stack.Count > 0) - { - TreeViewItem current = stack.Pop(); - if (current.children != null) - { - foreach (var child in current.children) - { - if (child != null) - { - if (m_Owner.DoesItemMatchSearch(child, search)) - result.Add(child); - - stack.Push(child); - } - } - } - } - - result.Sort((x, y) => EditorUtility.NaturalCompare(x.displayName, y.displayName)); - } - - protected override HashSet GetParentsAbove(int id) - { - return new HashSet(m_Owner.GetAncestors(id)); - } - - protected override HashSet GetParentsBelow(int id) - { - return new HashSet(m_Owner.GetDescendantsThatHaveChildren(id)); - } - - public override bool IsExpandable(TreeViewItem item) - { - return m_Owner.CanChangeExpandedState(item); - } - - public override bool CanBeMultiSelected(TreeViewItem item) - { - return m_Owner.CanMultiSelect(item); - } - - public override bool CanBeParent(TreeViewItem item) - { - return m_Owner.CanBeParent(item); - } - - public override bool IsRenamingItemAllowed(TreeViewItem item) - { - return m_Owner.CanRename(item); - } - } - } -} diff --git a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDefaults.cs b/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDefaults.cs deleted file mode 100644 index 518c64ea7f..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDefaults.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public partial class TreeView - { - public static class DefaultGUI - { - public static void FoldoutLabel(Rect rect, string label, bool selected, bool focused) - { - if (Event.current.type == EventType.Repaint) - DefaultStyles.foldoutLabel.Draw(rect, GUIContent.Temp(label), false, false, selected, focused); - } - - public static void Label(Rect rect, string label, bool selected, bool focused) - { - if (Event.current.type == EventType.Repaint) - DefaultStyles.label.Draw(rect, GUIContent.Temp(label), false, false, selected, focused); - } - - public static void LabelRightAligned(Rect rect, string label, bool selected, bool focused) - { - if (Event.current.type == EventType.Repaint) - DefaultStyles.labelRightAligned.Draw(rect, GUIContent.Temp(label), false, false, selected, focused); - } - - public static void BoldLabel(Rect rect, string label, bool selected, bool focused) - { - if (Event.current.type == EventType.Repaint) - DefaultStyles.boldLabel.Draw(rect, GUIContent.Temp(label), false, false, selected, focused); - } - - public static void BoldLabelRightAligned(Rect rect, string label, bool selected, bool focused) - { - if (Event.current.type == EventType.Repaint) - DefaultStyles.boldLabelRightAligned.Draw(rect, GUIContent.Temp(label), false, false, selected, focused); - } - - internal static float contentLeftMargin - { - get { return DefaultStyles.foldoutLabel.margin.left; } - } - } - - public static class DefaultStyles - { - public static GUIStyle foldoutLabel; - public static GUIStyle label; - public static GUIStyle labelRightAligned; - - public static GUIStyle boldLabel; - public static GUIStyle boldLabelRightAligned; - - public static GUIStyle backgroundEven = "OL EntryBackEven"; - public static GUIStyle backgroundOdd = "OL EntryBackOdd"; - - static DefaultStyles() - { - // Make a copy of lineStyle since left padding is being dynamically changed on that - // Note the left padding of 0 for exact placement of content after foldout or icon - foldoutLabel = new GUIStyle(TreeViewGUI.Styles.lineStyle); - foldoutLabel.padding.left = 0; - - // For generic labels use same padding values as the standard EditorStyles.label for consistency - label = new GUIStyle(foldoutLabel); - label.padding.left = 2; - label.padding.right = 2; - - labelRightAligned = new GUIStyle(label); - labelRightAligned.alignment = TextAnchor.UpperRight; - - boldLabel = new GUIStyle(label); - boldLabel.font = EditorStyles.boldLabel.font; - boldLabel.fontStyle = EditorStyles.boldLabel.fontStyle; - - boldLabelRightAligned = new GUIStyle(boldLabel); - boldLabelRightAligned.alignment = TextAnchor.UpperRight; - } - } - } -} diff --git a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDragging.cs b/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDragging.cs deleted file mode 100644 index 63963bc86e..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlDragging.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - - -namespace UnityEditor.IMGUI.Controls -{ - public partial class TreeView - { - private class TreeViewControlDragging : TreeViewDragging - { - private TreeView m_Owner; - - public TreeViewControlDragging(TreeViewController treeView, TreeView owner) - : base(treeView) - { - m_Owner = owner; - } - - public override bool CanStartDrag(TreeViewItem targetItem, List draggedItemIDs, Vector2 mouseDownPosition) - { - return m_Owner.CanStartDrag(new CanStartDragArgs { draggedItem = targetItem, draggedItemIDs = draggedItemIDs }); - } - - public override void StartDrag(TreeViewItem draggedItem, List draggedItemIDs) - { - m_Owner.SetupDragAndDrop(new SetupDragAndDropArgs { draggedItemIDs = draggedItemIDs}); - } - - public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPosition) - { - if (m_Owner.m_OverriddenMethods.hasHandleDragAndDrop) - { - var args = new DragAndDropArgs - { - dragAndDropPosition = GetDragAndDropPosition(parentItem, targetItem), - insertAtIndex = GetInsertionIndex(parentItem, targetItem, dropPosition), - parentItem = parentItem, - performDrop = perform - }; - - return m_Owner.HandleDragAndDrop(args); - } - - return DragAndDropVisualMode.None; - } - - DragAndDropPosition GetDragAndDropPosition(TreeViewItem parentItem, TreeViewItem targetItem) - { - if (parentItem == null) - return DragAndDropPosition.OutsideItems; - - if (parentItem == targetItem) - return DragAndDropPosition.UponItem; - - return DragAndDropPosition.BetweenItems; - } - } - } -} diff --git a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlGUI.cs b/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlGUI.cs deleted file mode 100644 index 710b8b1cd3..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControlGUI.cs +++ /dev/null @@ -1,362 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public partial class TreeView - { - class TreeViewControlGUI : TreeViewGUI - { - readonly TreeView m_Owner; - List m_RowRects; // If m_RowRects is null fixed row height is used - Rect[] m_CellRects; // Allocated once and reused - const float k_BackgroundWidth = 100000f; // The TreeView can have a horizontal scrollbar so ensure to fill out the entire width of the background - public float borderWidth = 1f; - - public TreeViewControlGUI(TreeViewController treeView, TreeView owner) - : base(treeView) - { - m_Owner = owner; - cellMargin = MultiColumnHeader.DefaultGUI.columnContentMargin; - } - - public void RefreshRowRects(IList rows) - { - if (m_RowRects == null) - m_RowRects = new List(rows.Count); - - if (m_RowRects.Capacity < rows.Count) - m_RowRects.Capacity = rows.Count; - - m_RowRects.Clear(); - float curY = k_TopRowMargin; - for (int row = 0; row < rows.Count; ++row) - { - float height = m_Owner.GetCustomRowHeight(row, rows[row]); - 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 - curY += height; - } - } - - public float cellMargin { get; set; } - - public float foldoutWidth - { - get { return Styles.foldoutWidth; } - } - - public int columnIndexForTreeFoldouts { get; set; } // column 0 is the default column for the tree foldouts - - public float totalHeight - { - get { return (useCustomRowRects ? customRowsTotalHeight : base.GetTotalSize().y) + (m_Owner.multiColumnHeader != null ? m_Owner.multiColumnHeader.height : 0f); } - } - - public override Vector2 GetTotalSize() - { - Vector2 contentSize = useCustomRowRects ? new Vector2(1, customRowsTotalHeight) : base.GetTotalSize(); - - // If we have multi column state we use the width of the columns so we show the horizontal scrollbar if needed - if (m_Owner.multiColumnHeader != null) - contentSize.x = Mathf.Floor(m_Owner.multiColumnHeader.state.widthOfAllVisibleColumns); - return contentSize; - } - - bool useCustomRowRects - { - get { return m_RowRects != null; } - } - - float customRowsTotalHeight - { - get - { - return - (m_RowRects.Count > 0 ? m_RowRects[m_RowRects.Count - 1].yMax : 0f) + k_BottomRowMargin - - (m_TreeView.expansionAnimator.isAnimating ? m_TreeView.expansionAnimator.deltaHeight : 0f); - } - } - - // 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 - protected override void OnContentGUI(Rect rect, int row, TreeViewItem item, string label, bool selected, bool focused, bool useBoldFont, bool isPinging) - { - // We do not support pinging in the TreeView (to simplify api) - if (isPinging) - return; - - // 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) - // to jump from row to row when mouse scrolling (due to culling of rows and the assigning of controlIDs in call-order) - GUIUtility.GetControlID(TreeViewController.GetItemControlID(item), FocusType.Passive); - - if (m_Owner.m_OverriddenMethods.hasRowGUI) - { - var args = new RowGUIArgs - { - rowRect = rect, - row = row, - item = item, - label = label, - selected = selected, - focused = focused, - isRenaming = IsRenaming(item.id), - }; - - // For multi column header we call OnRowGUI for each cell with the cell rect - if (m_Owner.multiColumnHeader != null) - { - //args.columnInfo = m_ColumnInfo; - var visibleColumns = m_Owner.multiColumnHeader.state.visibleColumns; - if (m_CellRects == null || m_CellRects.Length != visibleColumns.Length) - m_CellRects = new Rect[visibleColumns.Length]; - - var columns = m_Owner.multiColumnHeader.state.columns; - var columnRect = args.rowRect; - for (int i = 0; i < visibleColumns.Length; ++i) - { - var columnData = columns[visibleColumns[i]]; - columnRect.width = columnData.width; - - m_CellRects[i] = columnRect; - - // Use cell margins for all columns except the column with the tree view foldouts - // since that column assumes full cell rect for rename overlay placement - if (columnIndexForTreeFoldouts != visibleColumns[i]) - { - m_CellRects[i].x += cellMargin; - m_CellRects[i].width -= 2 * cellMargin; - } - - columnRect.x += columnData.width; - } - - args.columnInfo = new RowGUIArgs.MultiColumnInfo(m_Owner.multiColumnHeader.state, m_CellRects); - } - - m_Owner.RowGUI(args); - } - else - { - // Default item gui - base.OnContentGUI(rect, row, item, label, selected, focused, useBoldFont, false); - } - } - - internal void DefaultRowGUI(RowGUIArgs args) - { - base.OnContentGUI(args.rowRect, args.row, args.item, args.label, args.selected, args.focused, false, false); - } - - protected override Rect DoFoldout(Rect rowRect, TreeViewItem item, int row) - { - // For multicolumn setup we need to ensure foldouts are clipped so they are not in the next column - if (m_Owner.multiColumnHeader != null) - return DoMultiColumnFoldout(rowRect, item, row); - - return base.DoFoldout(rowRect, item, row); - } - - Rect DoMultiColumnFoldout(Rect rowRect, TreeViewItem item, int row) - { - if (!m_Owner.multiColumnHeader.IsColumnVisible(columnIndexForTreeFoldouts)) - return new Rect(); - - Rect cellRect = m_Owner.GetCellRectForTreeFoldouts(rowRect); - - // Clip foldout arrow if the cell is not big enough - if (GetContentIndent(item) > cellRect.width) - { - GUIClip.Push(cellRect, Vector2.zero, Vector2.zero, false); - cellRect.x = cellRect.y = 0f; // set guiclip coords - Rect foldoutRect = base.DoFoldout(cellRect, item, row); - GUIClip.Pop(); - return foldoutRect; - } - - return base.DoFoldout(cellRect, item, row); - } - - public override Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item) - { - if (m_Owner.m_OverriddenMethods.hasGetRenameRect) - { - return m_Owner.GetRenameRect(rowRect, row, item); - } - - return base.GetRenameRect(rowRect, row, item); - } - - public Rect DefaultRenameRect(Rect rowRect, int row, TreeViewItem item) - { - return base.GetRenameRect(rowRect, row, item); - } - - public override void BeginRowGUI() - { - base.BeginRowGUI(); - - if (m_Owner.isDragging && m_Owner.multiColumnHeader != null && columnIndexForTreeFoldouts > 0) - { - // Adjust insertion marker for multi column setups - int visibleColumnIndex = m_Owner.multiColumnHeader.GetVisibleColumnIndex(columnIndexForTreeFoldouts); - extraInsertionMarkerIndent = m_Owner.multiColumnHeader.GetColumnRect(visibleColumnIndex).x; - } - - m_Owner.BeforeRowsGUI(); - } - - public override void EndRowGUI() - { - base.EndRowGUI(); - m_Owner.AfterRowsGUI(); - } - - protected override void RenameEnded() - { - var renameState = m_TreeView.state.renameOverlay; - var renameEndedArgs = new RenameEndedArgs - { - acceptedRename = renameState.userAcceptedRename, - itemID = renameState.userData, - originalName = renameState.originalName, - newName = renameState.name - }; - m_Owner.RenameEnded(renameEndedArgs); - } - - public override Rect GetRowRect(int row, float rowWidth) - { - if (!useCustomRowRects) - { - return base.GetRowRect(row, rowWidth); - } - - if (row < 0 || row >= m_RowRects.Count) - { - 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)); - } - - Rect rowRect = m_RowRects[row]; - rowRect.width = rowWidth; - return rowRect; - } - - public override Rect GetRectForFraming(int row) - { - return GetRowRect(row, 1); - } - - // Should return the row number of the first and last row thats fits in the pixel rect defined by top and height - public override void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible) - { - if (!useCustomRowRects) - { - base.GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible); - return; - } - - if (m_TreeView.data.rowCount == 0) - { - firstRowVisible = lastRowVisible = -1; - return; - } - - var rowCount = m_TreeView.data.rowCount; - if (rowCount != m_RowRects.Count) - { - m_RowRects = null; - throw new InvalidOperationException(string.Format("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.", rowCount, m_RowRects.Count)); - } - - float topPixel = m_TreeView.state.scrollPos.y; - float heightInPixels = m_TreeView.GetTotalRect().height; - - int firstVisible = -1; - int lastVisible = -1; - for (int i = 0; i < m_RowRects.Count; ++i) - { - bool visible = ((m_RowRects[i].y > topPixel && (m_RowRects[i].y < topPixel + heightInPixels))) || - ((m_RowRects[i].yMax > topPixel && (m_RowRects[i].yMax < topPixel + heightInPixels))); - - if (visible) - { - if (firstVisible == -1) - firstVisible = i; - lastVisible = i; - } - } - - if (firstVisible != -1 && lastVisible != -1) - { - firstRowVisible = firstVisible; - lastRowVisible = lastVisible; - } - else - { - firstRowVisible = 0; - lastRowVisible = rowCount - 1; - } - } - - protected override void DrawItemBackground(Rect rect, int row, TreeViewItem item, bool selected, bool focused) - { - // To ensure backgrounds are also animated when animating expansion we render the rows backgrounds individually here. When not animating expansion the backgrounds - // are rendered in one go in DrawAlternatingRowBackgrounds() which also handles background outside rows - if (m_Owner.showAlternatingRowBackgrounds && m_TreeView.animatingExpansion) - { - rect.width = k_BackgroundWidth; - var bgStyle = row % 2 == 0 ? DefaultStyles.backgroundEven : DefaultStyles.backgroundOdd; - bgStyle.Draw(rect, false, false, false, false); - } - } - - public void DrawAlternatingRowBackgrounds() - { - if (Event.current.rawType != EventType.Repaint) - return; - - // Render entire bg - float contentYMax = m_Owner.treeViewRect.height + m_Owner.state.scrollPos.y; - - DefaultStyles.backgroundOdd.Draw(new Rect(0, 0, k_BackgroundWidth, contentYMax), false, false, false, false); - - int first = 0; - var numRows = m_Owner.GetRows().Count; - if (numRows > 0) - { - int last; - GetFirstAndLastRowVisible(out first, out last); - if (first < 0 || first >= numRows) - return; - } - - // Render every 2nd row for the entire background (we also show alternating colors below the last item) - Rect rowRect = new Rect(0, 0, 0, m_Owner.rowHeight); - for (int row = first; rowRect.yMax < contentYMax; row++) - { - if (row % 2 == 1) - continue; - - if (row < numRows) - rowRect = m_Owner.GetRowRect(row); - else if (row > 0) - rowRect.y += rowRect.height * 2; - rowRect.width = k_BackgroundWidth; - - DefaultStyles.backgroundEven.Draw(rowRect, false, false, false, false); - } - } - - // Returns the rect available within the borders - public Rect DoBorder(Rect rect) - { - EditorGUI.DrawOutline(rect, borderWidth, EditorGUI.kSplitLineSkinnedColor.color); - return new Rect(rect.x + borderWidth, rect.y + borderWidth, rect.width - 2 * borderWidth, rect.height - 2 * borderWidth); - } - } - } -} diff --git a/Editor/Mono/GUI/TreeView/TreeViewController.cs b/Editor/Mono/GUI/TreeView/TreeViewController.cs deleted file mode 100644 index 83e0fad58b..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewController.cs +++ /dev/null @@ -1,1265 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEditor.AnimatedValues; -using UnityEngine; -using UnityEditorInternal; - - -namespace UnityEditor.IMGUI.Controls -{ - /* - Description: - - The TreeViewController requires implementations from the following three interfaces: - ITreeViewDataSource: Should handle data fetching and data structure - ITreeViewGUI: Should handle visual representation of TreeView and mouse input on row controls - ITreeViewDragging: Should handle dragging, temp expansion of items, allow/disallow dropping - The TreeViewController handles: Navigation, Item selection and initiates dragging - - Important concepts: - 1) The Item Tree: the DataSource should create the tree structure of items with parent and children references - 2) Rows: the DataSource should be able to provide the visible items; a simple list that will become the rows we render. - 3) The root item might not be visible; its up to the data source to deliver a set of visible items from the tree - - */ - - - [System.Serializable] - public class TreeViewState - { - public List selectedIDs { get { return m_SelectedIDs; } set { m_SelectedIDs = value; } } - public int lastClickedID { get { return m_LastClickedID; } set { m_LastClickedID = value; } } - public List expandedIDs { get { return m_ExpandedIDs; } set { m_ExpandedIDs = value; } } - internal RenameOverlay renameOverlay { get { return m_RenameOverlay; } set { m_RenameOverlay = value; } } - - public string searchString { get { return m_SearchString; } set { m_SearchString = value; } } - public Vector2 scrollPos; - - // Selection state - [SerializeField] private List m_SelectedIDs = new List(); - [SerializeField] private int m_LastClickedID; // used for navigation - - // Expanded state (assumed sorted) - [SerializeField] private List m_ExpandedIDs = new List(); - - // Rename and create asset state - [SerializeField] private RenameOverlay m_RenameOverlay = new RenameOverlay(); - - // Search state (can be used by Datasource to filter tree when reloading) - [SerializeField] private string m_SearchString; - - internal virtual void OnAwake() - { - // Clear state that should not survive closing/starting Unity (If TreeViewState is in EditorWindow that are serialized in a layout file) - m_RenameOverlay.Clear(); - } - } - - internal class TreeViewController - { - public System.Action selectionChangedCallback { get; set; } // ids - public System.Action itemSingleClickedCallback { get; set; } // id - public System.Action itemDoubleClickedCallback { get; set; } // id - public System.Action 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 - public System.Action contextClickItemCallback { get; set; } // clicked item id - public System.Action contextClickOutsideItemsCallback { get; set; } - public System.Action keyboardInputCallback { get; set; } - public System.Action expandedStateChanged { get; set; } - public System.Action searchChanged { get; set; } - public System.Action scrollChanged { get; set; } - public System.Action onGUIRowCallback { get; set; } // - - // Main state - GUIView m_GUIView; // Containing view for this tree: used for checking if we have focus and for requesting repaints - public ITreeViewDataSource data { get; set; } // Data provider for this tree: handles data fetching - public ITreeViewDragging dragging { get; set; } // Handle dragging - public ITreeViewGUI gui { get; set; } // Handles GUI (input and rendering) - public TreeViewState state { get; set; } // State that persists script reloads - public GUIStyle horizontalScrollbarStyle { get; set; } - public GUIStyle verticalScrollbarStyle { get; set; } - public TreeViewItemExpansionAnimator expansionAnimator { get { return m_ExpansionAnimator; } } - readonly TreeViewItemExpansionAnimator m_ExpansionAnimator = new TreeViewItemExpansionAnimator(); - AnimFloat m_FramingAnimFloat; - - bool m_StopIteratingItems; - - public bool deselectOnUnhandledMouseDown { get; set; } - - List m_DragSelection = new List(); // Temp id state while dragging (not serialized) - bool m_UseScrollView = true; // Internal scrollview can be omitted when e.g mulitple tree views in one scrollview is wanted - bool m_AllowRenameOnMouseUp = true; - - internal const string kExpansionAnimationPrefKey = "TreeViewExpansionAnimation"; - bool m_UseExpansionAnimation = EditorPrefs.GetBool(kExpansionAnimationPrefKey, true); - public bool useExpansionAnimation { get { return m_UseExpansionAnimation; } set { m_UseExpansionAnimation = value; } } - - // Cached values during one event (for convenience) - bool m_GrabKeyboardFocus; - Rect m_TotalRect; - Rect m_VisibleRect; - Rect m_ContentRect; - bool m_HadFocusLastEvent; // Cached from last event for keyboard focus changed event - int m_KeyboardControlID; - - const float kSpaceForScrollBar = 16f; - - public TreeViewController(EditorWindow editorWindow, TreeViewState treeViewState) - { - m_GUIView = editorWindow ? editorWindow.m_Parent : GUIView.current; - state = treeViewState; - } - - public void Init(Rect rect, ITreeViewDataSource data, ITreeViewGUI gui, ITreeViewDragging dragging) - { - this.data = data; - this.gui = gui; - this.dragging = dragging; - m_TotalRect = rect; // We initialize the total rect because it might be needed for framing selection when reloading data the first time. - - // Allow sub systems to set up delegates etc after treeview references have been setup - data.OnInitialize(); - gui.OnInitialize(); - if (dragging != null) - dragging.OnInitialize(); - - expandedStateChanged += ExpandedStateHasChanged; - - m_FramingAnimFloat = new AnimFloat(state.scrollPos.y, AnimatedScrollChanged); - } - - void ExpandedStateHasChanged() - { - m_StopIteratingItems = true; - } - - public bool isSearching - { - get { return !string.IsNullOrEmpty(state.searchString); } - } - - public bool isDragging - { - get { return m_DragSelection != null && m_DragSelection.Count > 0; } - } - - public bool showingVerticalScrollBar - { - get { return m_ContentRect.height > m_VisibleRect.height; } - } - - public bool showingHorizontalScrollBar - { - get { return m_ContentRect.width > m_VisibleRect.width; } - } - - public string searchString - { - get - { - return state.searchString; - } - set - { - if (string.ReferenceEquals(state.searchString, value)) - return; - - if (state.searchString == value) - return; - - state.searchString = value; - data.OnSearchChanged(); - if (searchChanged != null) - searchChanged(state.searchString); - } - } - - public bool IsSelected(int id) - { - return state.selectedIDs.Contains(id); - } - - public bool HasSelection() - { - return state.selectedIDs.Count() > 0; - } - - public int[] GetSelection() - { - return state.selectedIDs.ToArray(); - } - - public int[] GetRowIDs() - { - return (from item in data.GetRows() select item.id).ToArray(); - } - - public void SetSelection(int[] selectedIDs, bool revealSelectionAndFrameLastSelected) - { - const bool animatedFraming = false; - SetSelection(selectedIDs, revealSelectionAndFrameLastSelected, animatedFraming); - } - - public void SetSelection(int[] selectedIDs, bool revealSelectionAndFrameLastSelected, bool animatedFraming) - { - // Keep for debugging - //Debug.Log ("SetSelection: new selection: " + DebugUtils.ListToString(new List(selectedIDs))); - - // Init new state - if (selectedIDs.Length > 0) - { - if (revealSelectionAndFrameLastSelected) - { - foreach (int id in selectedIDs) - data.RevealItem(id); - } - - state.selectedIDs = new List(selectedIDs); - - // Ensure that our key navigation is setup - bool hasLastClicked = state.selectedIDs.IndexOf(state.lastClickedID) >= 0; - if (!hasLastClicked) - { - // 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) - int lastSelectedID = selectedIDs.Last(); - if (data.GetRow(lastSelectedID) != -1) - { - state.lastClickedID = lastSelectedID; - hasLastClicked = true; - } - else - state.lastClickedID = 0; - } - - if (revealSelectionAndFrameLastSelected && hasLastClicked) - Frame(state.lastClickedID, true, false, animatedFraming); - } - else - { - state.selectedIDs.Clear(); - state.lastClickedID = 0; - } - - // Should not fire callback since this is called from outside - // NotifyListenersThatSelectionChanged () - } - - public TreeViewItem FindItem(int id) - { - return data.FindItem(id); - } - - public void SetUseScrollView(bool useScrollView) - { - m_UseScrollView = useScrollView; - } - - public void Repaint() - { - if (m_GUIView != null) - m_GUIView.Repaint(); - } - - public void ReloadData() - { - // Do not clear rename data here, we could be reloading due to assembly reload - // and we want to let our rename session survive that - - data.ReloadData(); - Repaint(); - - m_StopIteratingItems = true; - } - - public bool HasFocus() - { - bool hasKeyFocus = (m_GUIView != null) ? m_GUIView.hasFocus : EditorGUIUtility.HasCurrentWindowKeyFocus(); - return hasKeyFocus && (GUIUtility.keyboardControl == m_KeyboardControlID); - } - - static internal int GetItemControlID(TreeViewItem item) - { - return ((item != null) ? item.id : 0) + 10000000; - } - - public void HandleUnusedMouseEventsForItem(Rect rect, TreeViewItem item, int row) - { - int itemControlID = GetItemControlID(item); - - Event evt = Event.current; - - switch (evt.GetTypeForControl(itemControlID)) - { - case EventType.MouseDown: - if (rect.Contains(Event.current.mousePosition)) - { - // Handle mouse down on entire line - if (Event.current.button == 0) - { - // Grab keyboard - GUIUtility.keyboardControl = m_KeyboardControlID; - Repaint(); // Ensure repaint so we can show we have keyboard focus - - // Let client handle double click - if (Event.current.clickCount == 2) - { - if (itemDoubleClickedCallback != null) - itemDoubleClickedCallback(item.id); - } - else - { - var dragSelection = GetNewSelection(item, true, false); - bool canStartDrag = dragging != null && dragSelection.Count != 0 && dragging.CanStartDrag(item, dragSelection, Event.current.mousePosition); - if (canStartDrag) - { - // Prepare drag and drop delay (we start the drag after a couple of pixels mouse drag: See the case MouseDrag below) - m_DragSelection = dragSelection; - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), itemControlID); - delay.mouseDownPosition = Event.current.mousePosition; - } - else - { - // If dragging is not supported or not allowed for the drag selection then handle selection on mouse down - // (when dragging is handled we handle selection on mouse up to e.g allow to drag to object fields in the inspector) - m_DragSelection.Clear(); - if (m_AllowRenameOnMouseUp) - m_AllowRenameOnMouseUp = (state.selectedIDs.Count == 1 && state.selectedIDs[0] == item.id); // If first time selection then prevent starting a rename on the following mouse up after this mouse down - - SelectionClick(item, false); - - // Notify about single click - if (itemSingleClickedCallback != null) - itemSingleClickedCallback(item.id); - } - - GUIUtility.hotControl = itemControlID; - } - evt.Use(); - } - else if (Event.current.button == 1) - { - // Right mouse down selects; - bool keepMultiSelection = true; - SelectionClick(item, keepMultiSelection); - } - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == itemControlID && dragging != null && m_DragSelection.Count > 0) - { - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), itemControlID); - if (delay.CanStartDrag() && dragging.CanStartDrag(item, m_DragSelection, delay.mouseDownPosition)) - { - dragging.StartDrag(item, m_DragSelection); - GUIUtility.hotControl = 0; - } - - evt.Use(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == itemControlID) - { - // When having the temp dragging selection delay the the selection until mouse up - bool useMouseUpSelection = m_DragSelection.Count > 0; - - // Clear state before SelectionClick since it can ExitGUI early - GUIUtility.hotControl = 0; - m_DragSelection.Clear(); - evt.Use(); - - // On Mouse up either start name editing or change selection (if not done on mouse down) - if (rect.Contains(evt.mousePosition)) - { - Rect renameActivationRect = gui.GetRenameRect(rect, row, item); - List selected = state.selectedIDs; - if (m_AllowRenameOnMouseUp && selected != null && selected.Count == 1 && selected[0] == item.id && renameActivationRect.Contains(evt.mousePosition) && !EditorGUIUtility.HasHolddownKeyModifiers(evt)) - { - BeginNameEditing(0.5f); - } - else if (useMouseUpSelection) - { - SelectionClick(item, false); - - // Notify about single click - if (itemSingleClickedCallback != null) - itemSingleClickedCallback(item.id); - } - } - } - break; - - case EventType.DragUpdated: - case EventType.DragPerform: - { - //bool firstItem = row == 0; - if (dragging != null && dragging.DragElement(item, rect, row)) - GUIUtility.hotControl = 0; - } - break; - - case EventType.ContextClick: - if (rect.Contains(evt.mousePosition)) - { - // Do not use the event so the client can react to the context click (here we just handled the treeview selection) - if (contextClickItemCallback != null) - contextClickItemCallback(item.id); - } - break; - } - } - - public void GrabKeyboardFocus() - { - m_GrabKeyboardFocus = true; - } - - public void NotifyListenersThatSelectionChanged() - { - if (selectionChangedCallback != null) - selectionChangedCallback(state.selectedIDs.ToArray()); - } - - public void NotifyListenersThatDragEnded(int[] draggedIDs, bool draggedItemsFromOwnTreeView) - { - if (dragEndedCallback != null) - dragEndedCallback(draggedIDs, draggedItemsFromOwnTreeView); - } - - public Vector2 GetContentSize() - { - return gui.GetTotalSize(); - } - - public Rect GetTotalRect() - { - return m_TotalRect; - } - - public void SetTotalRect(Rect rect) - { - m_TotalRect = rect; - } - - public bool IsItemDragSelectedOrSelected(TreeViewItem item) - { - return m_DragSelection.Count > 0 ? m_DragSelection.Contains(item.id) : state.selectedIDs.Contains(item.id); - } - - public bool animatingExpansion { get { return m_UseExpansionAnimation && m_ExpansionAnimator.isAnimating; } } - - void DoItemGUI(TreeViewItem item, int row, float rowWidth, bool hasFocus) - { - // Check valid row - if (row < 0 || row >= data.rowCount) - { - Debug.LogError("Invalid. Org row: " + (row) + " Num rows " + data.rowCount); - return; - } - - bool selected = IsItemDragSelectedOrSelected(item); - - Rect rowRect = gui.GetRowRect(row, rowWidth); - - // 1. Before row GUI - if (animatingExpansion) - rowRect = m_ExpansionAnimator.OnBeginRowGUI(row, rowRect); - - // 2. Do row GUI - if (animatingExpansion) - m_ExpansionAnimator.OnRowGUI(row); - gui.OnRowGUI(rowRect, item, row, selected, hasFocus); - - // 3. Draw extra gui callbacks - if (onGUIRowCallback != null) - { - float indent = gui.GetContentIndent(item); - Rect indentedRect = new Rect(rowRect.x + indent, rowRect.y, rowRect.width - indent, rowRect.height); - onGUIRowCallback(item.id, indentedRect); - } - - // 4. After row GUI - if (animatingExpansion) - m_ExpansionAnimator.OnEndRowGUI(row); - - HandleUnusedMouseEventsForItem(rowRect, item, row); - } - - public void OnGUI(Rect rect, int keyboardControlID) - { - m_KeyboardControlID = keyboardControlID; - - Event evt = Event.current; - if (evt.type == EventType.Repaint) - m_TotalRect = rect; - - m_GUIView = GUIView.current; - - // End rename if the window do not have focus - if (m_GUIView != null && !m_GUIView.hasFocus && state.renameOverlay.IsRenaming()) - { - EndNameEditing(true); - } - - // Grab keyboard focus if requested or if we have a mousedown in entire rect - if (m_GrabKeyboardFocus || (evt.type == EventType.MouseDown && m_TotalRect.Contains(evt.mousePosition))) - { - m_GrabKeyboardFocus = false; - GUIUtility.keyboardControl = m_KeyboardControlID; - m_AllowRenameOnMouseUp = true; - Repaint(); // Ensure repaint so we can show we have keyboard focus - } - - bool hasFocus = HasFocus(); - - // Detect got focus (ignore layout event which might get fired infront of mousedown) - if (hasFocus != m_HadFocusLastEvent && evt.type != EventType.Layout) - { - m_HadFocusLastEvent = hasFocus; - - // We got focus this event - if (hasFocus) - { - if (evt.type == EventType.MouseDown) - 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 - } - } - - // Might change expanded state so call before InitIfNeeded (delayed collapse until animation is done) - if (animatingExpansion) - m_ExpansionAnimator.OnBeforeAllRowsGUI(); - - data.InitIfNeeded(); - - // Calc content size - Vector2 contentSize = gui.GetTotalSize(); - m_ContentRect = new Rect(0, 0, contentSize.x, contentSize.y); - - if (m_UseScrollView) - { - state.scrollPos = GUI.BeginScrollView(m_TotalRect, state.scrollPos, m_ContentRect, - horizontalScrollbarStyle != null ? horizontalScrollbarStyle : GUI.skin.horizontalScrollbar, - verticalScrollbarStyle != null ? verticalScrollbarStyle : GUI.skin.verticalScrollbar); - } - else - GUI.BeginClip(m_TotalRect); - - if (evt.type == EventType.Repaint) - m_VisibleRect = m_UseScrollView ? GUI.GetTopScrollView().visibleRect : m_TotalRect; - - gui.BeginRowGUI(); - - // Iterate visible items - int firstRow, lastRow; - gui.GetFirstAndLastRowVisible(out firstRow, out lastRow); - if (lastRow >= 0) - { - int numVisibleRows = lastRow - firstRow + 1; - float rowWidth = Mathf.Max(GUIClip.visibleRect.width, m_ContentRect.width); - - IterateVisibleItems(firstRow, numVisibleRows, rowWidth, hasFocus); - } - - // Call before gui.EndRowGUI() so stuff we render in EndRowGUI does not end up - // in the the animation clip rect - if (animatingExpansion) - m_ExpansionAnimator.OnAfterAllRowsGUI(); - - gui.EndRowGUI(); - - if (m_UseScrollView) - GUI.EndScrollView(showingVerticalScrollBar); - else - GUI.EndClip(); - - HandleUnusedEvents(); - KeyboardGUI(); - - // Prevent controlID inconsistency for the controls following this tree view: We use the hint parameter of GetControlID to - // 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 - // culled. - GUIUtility.GetControlID(33243602, FocusType.Passive); - } - - void IterateVisibleItems(int firstRow, int numVisibleRows, float rowWidth, bool hasFocus) - { - // We stop iterating items if datasource state changes while iterating its items. - // This can happen e.g when dragging items or items are expanding/collapsing. - m_StopIteratingItems = false; - - int rowOffset = 0; - for (int i = 0; i < numVisibleRows; ++i) - { - int row = firstRow + i; - - if (animatingExpansion) - { - // If we are animating expansion/collapsing then ensure items - // that are culled by the animation clip rect gets 'converted' into - // items after the expanding/collapsing items. When no more items can get culled - // then keep adding the offset (to not handle already handled items). - int endAnimRow = m_ExpansionAnimator.endRow; - if (m_ExpansionAnimator.CullRow(row, gui)) - { - rowOffset++; - row = endAnimRow + rowOffset; - } - else - { - row += rowOffset; - } - - // Ensure row is still valid after adding the rowOffset? - if (row >= data.rowCount) - { - continue; - } - } - else - { - // When not animating cull rows outside scroll rect - float screenSpaceRowY = gui.GetRowRect(row, rowWidth).y - state.scrollPos.y; - if (screenSpaceRowY > m_TotalRect.height) - { - continue; - } - } - - // Item GUI - DoItemGUI(data.GetItem(row), row, rowWidth, hasFocus); - - if (m_StopIteratingItems) - return; - } - } - - List GetVisibleSelectedIds() - { - // Do visible items - int firstRow, lastRow; - gui.GetFirstAndLastRowVisible(out firstRow, out lastRow); - if (lastRow < 0) - return new List(); - - List ids = new List(lastRow - firstRow); - for (int row = firstRow; row < lastRow; ++row) - { - var item = data.GetItem(row); - ids.Add(item.id); - } - - List selectedVisibleIDs = (from id in ids where state.selectedIDs.Contains(id) select id).ToList(); - return selectedVisibleIDs; - } - - private void ExpansionAnimationEnded(TreeViewAnimationInput setup) - { - // When collapsing we delay the actual collapse until the animation is done - if (!setup.expanding) - { - ChangeExpandedState(setup.item, false, setup.includeChildren); - } - } - - float GetAnimationDuration(float height) - { - // Speed up animation linearly for heights below kThreshold. - // We have found from usability testing that for smaller height changes (e.g 3-4 rows) - // we want a faster animation - const float kThreshold = 60f; - const float kMaxDuration = 0.07f; - return (height > kThreshold) ? kMaxDuration : (height * kMaxDuration / kThreshold); - } - - public void UserInputChangedExpandedState(TreeViewItem item, int row, bool expand) - { - var includeChildren = Event.current.alt; - if (useExpansionAnimation) - { - // We need to expand prior to starting animation so we have the expanded state ready - if (expand) - ChangeExpandedState(item, true, includeChildren); - - int rowStart = row + 1; - int rowEnd = GetLastChildRowUnder(row); - float rowWidth = GUIClip.visibleRect.width; - Rect allRowsRect = GetRectForRows(rowStart, rowEnd, rowWidth); - - float duration = GetAnimationDuration(allRowsRect.height); - var input = new TreeViewAnimationInput - { - animationDuration = duration, - startRow = rowStart, - endRow = rowEnd, - startRowRect = gui.GetRowRect(rowStart, rowWidth), - rowsRect = allRowsRect, - expanding = expand, - includeChildren = includeChildren, - animationEnded = ExpansionAnimationEnded, - item = item, - treeView = this - }; - - expansionAnimator.BeginAnimating(input); - } - else - { - ChangeExpandedState(item, expand, includeChildren); - } - } - - void ChangeExpandedState(TreeViewItem item, bool expand, bool includeChildren) - { - if (includeChildren) - data.SetExpandedWithChildren(item, expand); - else - data.SetExpanded(item, expand); - } - - int GetLastChildRowUnder(int row) - { - var rows = data.GetRows(); - int rowDepth = rows[row].depth; - for (int i = row + 1; i < rows.Count; ++i) - if (rows[i].depth <= rowDepth) - return i - 1; - - return rows.Count - 1; // end row - } - - protected virtual Rect GetRectForRows(int startRow, int endRow, float rowWidth) - { - Rect startRect = gui.GetRowRect(startRow, rowWidth); - Rect endRect = gui.GetRowRect(endRow, rowWidth); - return new Rect(startRect.x, startRect.y, rowWidth, endRect.yMax - startRect.yMin); - } - - void HandleUnusedEvents() - { - switch (Event.current.type) - { - case EventType.DragUpdated: - if (dragging != null && m_TotalRect.Contains(Event.current.mousePosition)) - { - dragging.DragElement(null, new Rect(), -1); - Repaint(); - Event.current.Use(); - } - break; - - case EventType.DragPerform: - if (dragging != null && m_TotalRect.Contains(Event.current.mousePosition)) - { - m_DragSelection.Clear(); - dragging.DragElement(null, new Rect(), -1); - Repaint(); - Event.current.Use(); - } - break; - - case EventType.DragExited: - if (dragging != null) - { - m_DragSelection.Clear(); - dragging.DragCleanup(true); - Repaint(); - } - break; - - case EventType.MouseDown: - if (deselectOnUnhandledMouseDown && Event.current.button == 0 && m_TotalRect.Contains(Event.current.mousePosition) && state.selectedIDs.Count > 0) - { - SetSelection(new int[0], false); - NotifyListenersThatSelectionChanged(); - } - break; - case EventType.ContextClick: - if (m_TotalRect.Contains(Event.current.mousePosition)) - { - if (contextClickOutsideItemsCallback != null) - contextClickOutsideItemsCallback(); - } - break; - } - } - - public void OnEvent() - { - state.renameOverlay.OnEvent(); - } - - public bool BeginNameEditing(float delay) - { - // No items selected for rename - if (state.selectedIDs.Count == 0) - return false; - - var visibleItems = data.GetRows(); - TreeViewItem visibleAndSelectedItem = null; - - foreach (int id in state.selectedIDs) - { - TreeViewItem item = visibleItems.FirstOrDefault(i => i.id == id); - if (visibleAndSelectedItem == null) - visibleAndSelectedItem = item; - else if (item != null) - return false; // Don't allow rename if more than one item is both visible and selected - } - - if (visibleAndSelectedItem != null && data.IsRenamingItemAllowed(visibleAndSelectedItem)) - return gui.BeginRename(visibleAndSelectedItem, delay); - - return false; - } - - // Let client end renaming from outside - public void EndNameEditing(bool acceptChanges) - { - if (state.renameOverlay.IsRenaming()) - { - state.renameOverlay.EndRename(acceptChanges); - gui.EndRename(); - } - } - - TreeViewItem GetItemAndRowIndex(int id, out int row) - { - row = data.GetRow(id); - if (row == -1) - return null; - return data.GetItem(row); - } - - void HandleFastCollapse(TreeViewItem item, int row) - { - if (item.depth == 0) - { - // At depth 0 traverse upwards until a parent is found and select that item - for (int i = row - 1; i >= 0; --i) - { - if (data.GetItem(i).hasChildren) - { - OffsetSelection(i - row); - return; - } - } - } - else if (item.depth > 0) - { - // Traverse upwards until parent of item is found and select that parent (users want this behavior) - for (int i = row - 1; i >= 0; --i) - { - if (data.GetItem(i).depth < item.depth) - { - OffsetSelection(i - row); - return; - } - } - } - } - - void HandleFastExpand(TreeViewItem item, int row) - { - int rowCount = data.rowCount; - - // Traverse downwards until a parent is found and select that parent - for (int i = row + 1; i < rowCount; ++i) - { - if (data.GetItem(i).hasChildren) - { - OffsetSelection(i - row); - break; - } - } - } - - private void ChangeFolding(int[] ids, bool expand) - { - // Handle folding of single item and multiple items separately - // Animation is only supported for folding of single item - if (ids.Length == 1) - ChangeFoldingForSingleItem(ids[0], expand); - else if (ids.Length > 1) - ChangeFoldingForMultipleItems(ids, expand); - } - - private void ChangeFoldingForSingleItem(int id, bool expand) - { - int row; - TreeViewItem item = GetItemAndRowIndex(id, out row); - if (item != null) - { - if (data.IsExpandable(item) && data.IsExpanded(item) != expand) - UserInputChangedExpandedState(item, row, expand); - else - { - expansionAnimator.SkipAnimating(); - if (expand) - HandleFastExpand(item, row); // Move selection to next parent - else - HandleFastCollapse(item, row); // Move selection to parent - } - } - } - - private void ChangeFoldingForMultipleItems(int[] ids, bool expand) - { - // Collect items that should be expanded/collapsed - var parents = new HashSet(); - foreach (var id in ids) - { - int row; - TreeViewItem item = GetItemAndRowIndex(id, out row); - if (item != null) - { - if (data.IsExpandable(item) && data.IsExpanded(item) != expand) - parents.Add(id); - } - } - - // Expand/collapse all collected items - if (Event.current.alt) - { - // Also expand/collapse children of selected items - foreach (var id in parents) - data.SetExpandedWithChildren(id, expand); - } - else - { - var expandedIDs = new HashSet(data.GetExpandedIDs()); - if (expand) - expandedIDs.UnionWith(parents); - else - expandedIDs.ExceptWith(parents); - data.SetExpandedIDs(expandedIDs.ToArray()); - } - } - - void KeyboardGUI() - { - if (m_KeyboardControlID != GUIUtility.keyboardControl || !GUI.enabled) - return; - - // Let client handle keyboard first - if (keyboardInputCallback != null) - keyboardInputCallback(); - - if (Event.current.type == EventType.KeyDown) - { - switch (Event.current.keyCode) - { - // Fold in - case KeyCode.LeftArrow: - ChangeFolding(state.selectedIDs.ToArray(), false); - Event.current.Use(); - break; - - // Fold out - case KeyCode.RightArrow: - ChangeFolding(state.selectedIDs.ToArray(), true); - Event.current.Use(); - break; - - case KeyCode.UpArrow: - Event.current.Use(); - OffsetSelection(-1); - break; - - // Select next or first - case KeyCode.DownArrow: - Event.current.Use(); - OffsetSelection(1); - break; - - case KeyCode.Home: - Event.current.Use(); - OffsetSelection(-1000000); - break; - - case KeyCode.End: - Event.current.Use(); - OffsetSelection(1000000); - break; - - case KeyCode.PageUp: - { - Event.current.Use(); - TreeViewItem lastClickedItem = data.FindItem(state.lastClickedID); - if (lastClickedItem != null) - { - int numRowsPageUp = gui.GetNumRowsOnPageUpDown(lastClickedItem, true, m_TotalRect.height); - OffsetSelection(-numRowsPageUp); - } - } - break; - - case KeyCode.PageDown: - { - Event.current.Use(); - TreeViewItem lastClickedItem = data.FindItem(state.lastClickedID); - if (lastClickedItem != null) - { - int numRowsPageDown = gui.GetNumRowsOnPageUpDown(lastClickedItem, true, m_TotalRect.height); - OffsetSelection(numRowsPageDown); - } - } - break; - - case KeyCode.Return: - case KeyCode.KeypadEnter: - if (Application.platform == RuntimePlatform.OSXEditor) - if (BeginNameEditing(0f)) - Event.current.Use(); - break; - - case KeyCode.F2: - if (Application.platform != RuntimePlatform.OSXEditor) - if (BeginNameEditing(0f)) - Event.current.Use(); - break; - - default: - if (Event.current.keyCode > KeyCode.A && Event.current.keyCode < KeyCode.Z) - { - // TODO: jump to folder with char? - } - break; - } - } - } - - static internal int GetIndexOfID(IList items, int id) - { - for (int i = 0; i < items.Count; ++i) - if (items[i].id == id) - return i; - return -1; - } - - public bool IsLastClickedPartOfRows() - { - var visibleRows = data.GetRows(); - if (visibleRows.Count == 0) - return false; - - return GetIndexOfID(visibleRows, state.lastClickedID) >= 0; - } - - public void OffsetSelection(int offset) - { - expansionAnimator.SkipAnimating(); - var visibleRows = data.GetRows(); - - if (visibleRows.Count == 0) - return; - - Event.current.Use(); - int index = GetIndexOfID(visibleRows, state.lastClickedID); - int newIndex = Mathf.Clamp(index + offset, 0, visibleRows.Count - 1); - EnsureRowIsVisible(newIndex, true); - SelectionByKey(visibleRows[newIndex]); - } - - bool GetFirstAndLastSelected(List items, out int firstIndex, out int lastIndex) - { - firstIndex = -1; - lastIndex = -1; - for (int i = 0; i < items.Count; ++i) - { - if (state.selectedIDs.Contains(items[i].id)) - { - if (firstIndex == -1) - firstIndex = i; - lastIndex = i; // just overwrite and we will have the last in the end... - } - } - return firstIndex != -1 && lastIndex != -1; - } - - // Returns list of selected ids - List GetNewSelection(TreeViewItem clickedItem, bool keepMultiSelection, bool useShiftAsActionKey) - { - // Get ids from items - var visibleRows = data.GetRows(); - List allIDs = new List(visibleRows.Count); - for (int i = 0; i < visibleRows.Count; ++i) - allIDs.Add(visibleRows[i].id); - - List selectedIDs = state.selectedIDs; - int lastClickedID = state.lastClickedID; - bool allowMultiselection = data.CanBeMultiSelected(clickedItem); - - return InternalEditorUtility.GetNewSelection(clickedItem.id, allIDs, selectedIDs, lastClickedID, keepMultiSelection, useShiftAsActionKey, allowMultiselection); - } - - void SelectionByKey(TreeViewItem itemSelected) - { - var newSelection = GetNewSelection(itemSelected, false, true); - NewSelectionFromUserInteraction(newSelection, itemSelected.id); - } - - public void SelectionClick(TreeViewItem itemClicked, bool keepMultiSelection) - { - var newSelection = GetNewSelection(itemClicked, keepMultiSelection, false); - NewSelectionFromUserInteraction(newSelection, itemClicked != null ? itemClicked.id : 0); - } - - void NewSelectionFromUserInteraction(List newSelection, int itemID) - { - state.lastClickedID = itemID; - - bool selectionChanged = !state.selectedIDs.SequenceEqual(newSelection); - if (selectionChanged) - { - state.selectedIDs = newSelection; - NotifyListenersThatSelectionChanged(); - } - } - - public void RemoveSelection() - { - if (state.selectedIDs.Count > 0) - { - state.selectedIDs.Clear(); - NotifyListenersThatSelectionChanged(); - } - } - - float GetTopPixelOfRow(int row) - { - return gui.GetRowRect(row, 1).y; - } - - void EnsureRowIsVisible(int row, bool animated) - { - // We don't want to change the scroll to make the row visible, - // if it's disabled: Causes content to be moved/rendered out of bounds. - if (!m_UseScrollView) - return; - - if (row >= 0) - { - // Adjusting for when the horizontal scrollbar is being shown. Before the TreeView has repainted - // once the m_VisibleRect is not valid, then we use m_TotalRect which is passed when initialized - float visibleHeight = m_VisibleRect.height > 0 ? m_VisibleRect.height : m_TotalRect.height; - - Rect frameRect = gui.GetRectForFraming(row); - float scrollTop = frameRect.y; - float scrollBottom = frameRect.yMax - visibleHeight; - - if (state.scrollPos.y < scrollBottom) - ChangeScrollValue(scrollBottom, animated); - else if (state.scrollPos.y > scrollTop) - ChangeScrollValue(scrollTop, animated); - } - } - - void AnimatedScrollChanged() - { - Repaint(); - state.scrollPos.y = m_FramingAnimFloat.value; - } - - void ChangeScrollValue(float targetScrollPos, bool animated) - { - if (m_UseExpansionAnimation && animated) - { - m_FramingAnimFloat.value = state.scrollPos.y; - m_FramingAnimFloat.target = targetScrollPos; - m_FramingAnimFloat.speed = 3f; - } - else - { - state.scrollPos.y = targetScrollPos; - } - } - - public void Frame(int id, bool frame, bool ping) - { - const bool animated = false; - Frame(id, frame, ping, animated); - } - - public void Frame(int id, bool frame, bool ping, bool animated) - { - float topPixelOfRow = -1f; - - if (frame) - { - data.RevealItem(id); - - int row = data.GetRow(id); - if (row >= 0) - { - topPixelOfRow = GetTopPixelOfRow(row); - EnsureRowIsVisible(row, animated); - } - } - - if (ping) - { - int row = data.GetRow(id); - if (topPixelOfRow == -1f) - { - // Was not framed first so we need to calc it here - if (row >= 0) - topPixelOfRow = GetTopPixelOfRow(row); - } - - if (topPixelOfRow >= 0f && row >= 0 && row < data.rowCount) - { - TreeViewItem item = data.GetItem(row); - float scrollBarOffset = GetContentSize().y > m_TotalRect.height ? -kSpaceForScrollBar : 0f; - gui.BeginPingItem(item, topPixelOfRow, m_TotalRect.width + scrollBarOffset); - } - } - } - - public void EndPing() - { - gui.EndPingItem(); - } - - // Item holding most basic data for TreeView event handling - // Extend this class to hold your specific tree data and make your DataSource - // create items of your type. During e.g OnGUI you can the cast Item to your own type when needed. - - - // Hidden items (under collapsed items) are added last - public List SortIDsInVisiblityOrder(IList ids) - { - if (ids.Count <= 1) - return ids.ToList(); // no sorting needed - - var visibleRows = data.GetRows(); - List sorted = new List(); - for (int i = 0; i < visibleRows.Count; ++i) - { - int id = visibleRows[i].id; - for (int j = 0; j < ids.Count; ++j) - { - if (ids[j] == id) - { - sorted.Add(id); - break; - } - } - } - - // Some rows with selection are collapsed (not visible) so add those to the end - if (ids.Count != sorted.Count) - { - sorted.AddRange(ids.Except(sorted)); - if (ids.Count != sorted.Count) - Debug.LogError("SortIDsInVisiblityOrder failed: " + ids.Count + " != " + sorted.Count); - } - - return sorted; - } - } -} // end namespace UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewDataSource.cs b/Editor/Mono/GUI/TreeView/TreeViewDataSource.cs deleted file mode 100644 index ed23094cec..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewDataSource.cs +++ /dev/null @@ -1,359 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - // TreeViewDataSource is a base abstract class for a data source for a TreeView. - // Usage: - // Override FetchData () and build the entire tree with m_RootItem as root. - // Configure showRootItem and rootIsCollapsable as wanted - // - // Note: if dealing with very large trees use LazyTreeViewDataSource instead: it assumes that tree only contains visible items. - - internal abstract class TreeViewDataSource : ITreeViewDataSource - { - protected readonly TreeViewController m_TreeView; // TreeView using this data source - protected TreeViewItem m_RootItem; - protected IList m_Rows; - protected bool m_NeedRefreshRows = true; - protected TreeViewItem m_FakeItem; - - public bool showRootItem { get; set; } - public bool rootIsCollapsable { get; set; } - public bool alwaysAddFirstItemToSearchResult { get; set; } // is only used in searches when showRootItem is false. It Doesn't make sense for visible roots - public TreeViewItem root { get { return m_RootItem; } } - public System.Action onVisibleRowsChanged; - - protected List expandedIDs - { - get {return m_TreeView.state.expandedIDs; } - set { m_TreeView.state.expandedIDs = value; } - } - - public TreeViewDataSource(TreeViewController treeView) - { - m_TreeView = treeView; - showRootItem = true; - rootIsCollapsable = false; - m_RootItem = null; - onVisibleRowsChanged = null; - } - - virtual public void OnInitialize() - { - } - - // Implement this function and build entire tree with m_RootItem as root - public abstract void FetchData(); - - public virtual void ReloadData() - { - m_FakeItem = null; - FetchData(); - } - - virtual public TreeViewItem FindItem(int id) - { - return TreeViewUtility.FindItem(id, m_RootItem); - } - - virtual public bool IsRevealed(int id) - { - IList rows = GetRows(); - return TreeViewController.GetIndexOfID(rows, id) >= 0; - } - - virtual public void RevealItem(int id) - { - if (IsRevealed(id)) - return; - - // Reveal (expand parents up to root) - TreeViewItem item = FindItem(id); - if (item != null) - { - TreeViewItem parent = item.parent; - while (parent != null) - { - SetExpanded(parent, true); - parent = parent.parent; - } - } - } - - virtual public void OnSearchChanged() - { - m_NeedRefreshRows = true; - } - - //---------------------------- - // Visible Item section - - protected void GetVisibleItemsRecursive(TreeViewItem item, IList items) - { - if (item != m_RootItem || showRootItem) - items.Add(item); - - if (item.hasChildren && IsExpanded(item)) - foreach (TreeViewItem child in item.children) - GetVisibleItemsRecursive(child, items); - } - - protected void SearchRecursive(TreeViewItem item, string search, IList searchResult) - { - if (item.displayName.ToLower().Contains(search)) - searchResult.Add(item); - - if (item.children != null) - foreach (TreeViewItem child in item.children) - SearchRecursive(child, search, searchResult); - } - - virtual protected List ExpandedRows(TreeViewItem root) - { - var result = new List(); - GetVisibleItemsRecursive(m_RootItem, result); - return result; - } - - // Searches the current tree by displayName. - virtual protected List Search(TreeViewItem root, string search) - { - var result = new List(); - - if (showRootItem) - { - SearchRecursive(root, search, result); - result.Sort(new TreeViewItemAlphaNumericSort()); - } - else - { - int startIndex = alwaysAddFirstItemToSearchResult ? 1 : 0; - - if (root.hasChildren) - { - for (int i = startIndex; i < root.children.Count; ++i) - { - SearchRecursive(root.children[i], search, result); - } - result.Sort(new TreeViewItemAlphaNumericSort()); - - if (alwaysAddFirstItemToSearchResult) - result.Insert(0, root.children[0]); - } - } - - return result; - } - - virtual public int rowCount - { - get - { - return GetRows().Count; - } - } - - virtual public int GetRow(int id) - { - var rows = GetRows(); - for (int row = 0; row < rows.Count; ++row) - { - if (rows[row].id == id) - return row; - } - return -1; - } - - virtual public TreeViewItem GetItem(int row) - { - return GetRows()[row]; - } - - // Get the flattend tree of visible items. - virtual public IList GetRows() - { - InitIfNeeded(); - return m_Rows; - } - - virtual public void InitIfNeeded() - { - // Cached for large trees... - if (m_Rows == null || m_NeedRefreshRows) - { - if (m_RootItem != null) - { - if (m_TreeView.isSearching) - m_Rows = Search(m_RootItem, m_TreeView.searchString.ToLower()); - else - m_Rows = ExpandedRows(m_RootItem); - } - else - { - Debug.LogError("TreeView root item is null. Ensure that your TreeViewDataSource sets up at least a root item."); - m_Rows = new List(); - } - - m_NeedRefreshRows = false; - - // TODO: This should be named something like: 'onVisibleRowsReloaded' - if (onVisibleRowsChanged != null) - onVisibleRowsChanged(); - - // Expanded state has changed ensure that we repaint - m_TreeView.Repaint(); - } - } - - public bool isInitialized - { - get { return m_RootItem != null && m_Rows != null; } - } - - //---------------------------- - // Expanded/collapsed section - - virtual public int[] GetExpandedIDs() - { - return expandedIDs.ToArray(); - } - - virtual public void SetExpandedIDs(int[] ids) - { - expandedIDs = new List(ids); - expandedIDs.Sort(); - m_NeedRefreshRows = true; - OnExpandedStateChanged(); - } - - virtual public bool IsExpanded(int id) - { - return expandedIDs.BinarySearch(id) >= 0; - } - - virtual public bool SetExpanded(int id, bool expand) - { - bool expanded = IsExpanded(id); - if (expand != expanded) - { - if (expand) - { - System.Diagnostics.Debug.Assert(!expandedIDs.Contains(id)); - expandedIDs.Add(id); - expandedIDs.Sort(); - } - else - { - expandedIDs.Remove(id); - } - m_NeedRefreshRows = true; - OnExpandedStateChanged(); - return true; - } - return false; - } - - virtual public void SetExpandedWithChildren(int id, bool expand) - { - SetExpandedWithChildren(FindItem(id), expand); - } - - virtual public void SetExpandedWithChildren(TreeViewItem fromItem, bool expand) - { - if (fromItem == null) - { - Debug.LogError("item is null"); - return; - } - - HashSet parents = TreeViewUtility.GetParentsBelowItem(fromItem); - - // Get existing expanded in hashset - HashSet oldExpandedSet = new HashSet(expandedIDs); - - if (expand) - oldExpandedSet.UnionWith(parents); - else - oldExpandedSet.ExceptWith(parents); - - // Bulk set expanded ids (is sorted in SetExpandedIDs) - SetExpandedIDs(oldExpandedSet.ToArray()); - } - - virtual public void SetExpanded(TreeViewItem item, bool expand) - { - SetExpanded(item.id, expand); - } - - virtual public bool IsExpanded(TreeViewItem item) - { - return IsExpanded(item.id); - } - - virtual public bool IsExpandable(TreeViewItem item) - { - // Ignore expansion (foldout arrow) when showing search results - if (m_TreeView.isSearching) - return false; - return item.hasChildren; - } - - virtual public bool CanBeMultiSelected(TreeViewItem item) - { - return true; - } - - virtual public bool CanBeParent(TreeViewItem item) - { - return true; - } - - virtual public void OnExpandedStateChanged() - { - if (m_TreeView.expandedStateChanged != null) - m_TreeView.expandedStateChanged(); - } - - //---------------------------- - // Renaming section - - virtual public bool IsRenamingItemAllowed(TreeViewItem item) - { - return true; - } - - //---------------------------- - // Insert tempoary Item section - - // Fake Item should be inserted into the m_VisibleRows (not the tree itself). - virtual public void InsertFakeItem(int id, int parentID, string name, Texture2D icon) - { - Debug.LogError("InsertFakeItem missing implementation"); - } - - virtual public bool HasFakeItem() - { - return m_FakeItem != null; - } - - virtual public void RemoveFakeItem() - { - if (!HasFakeItem()) - return; - - var visibleRows = GetRows(); - int index = TreeViewController.GetIndexOfID(visibleRows, m_FakeItem.id); - if (index != -1) - { - visibleRows.RemoveAt(index); - } - m_FakeItem = null; - } - } -} diff --git a/Editor/Mono/GUI/TreeView/TreeViewDragging.cs b/Editor/Mono/GUI/TreeView/TreeViewDragging.cs deleted file mode 100644 index 6756cacd40..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewDragging.cs +++ /dev/null @@ -1,396 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.Assertions; - -namespace UnityEditor.IMGUI.Controls -{ - // Abstract base class for common dragging behavior - // Usage: - // - Override StartDrag - // - Override DoDrag - // Features: - // - Expands items with children on hover (after ca 0.7 seconds) - // - - - internal abstract class TreeViewDragging : ITreeViewDragging - { - protected TreeViewController m_TreeView; - - protected class DropData - { - public int[] expandedArrayBeforeDrag; - public int lastControlID = -1; - public int dropTargetControlID = -1; - public int rowMarkerControlID = -1; - public double expandItemBeginTimer; - public Vector2 expandItemBeginPosition; - } - - public enum DropPosition - { - Upon = 0, - Below = 1, - Above = 2 - } - - protected DropData m_DropData = new DropData(); - const double k_DropExpandTimeout = 0.7; - - public TreeViewDragging(TreeViewController treeView) - { - m_TreeView = treeView; - } - - virtual public void OnInitialize() - { - } - - public int GetDropTargetControlID() - { - return m_DropData.dropTargetControlID; - } - - public int GetRowMarkerControlID() - { - return m_DropData.rowMarkerControlID; - } - - public bool drawRowMarkerAbove { get; set; } - - public virtual bool CanStartDrag(TreeViewItem targetItem, List draggedItemIDs, Vector2 mouseDownPosition) - { - return true; - } - - // This method is called from TreeView when a drag is started - // Client should setup the drag data - public abstract void StartDrag(TreeViewItem draggedItem, List draggedItemIDs); - - // This method is called from within DragElement when it has determined what is the parent item of the current targetItem - // (This depends on if dropPosition is above, below or upon) - // 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) - // Notes on arguments: - // When hovering outside any items: target and parent is null, dropPos is invalid - // If parentItem and targetItem is the same then insert as first child of parent, dropPos is invalid - // If parentItem and targetItem is different then use dropPos to insert dragged items relative to targetItem - // parentItem can be null when root is visible and hovering above or below the root - - // if targetItem is null then parent can be null if root is visible - // if targetitem is null then parent might be valid if root is hidden - public abstract DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPosition); - - protected float GetDropBetweenHalfHeight(TreeViewItem item, Rect itemRect) - { - return m_TreeView.data.CanBeParent(item) ? m_TreeView.gui.halfDropBetweenHeight : itemRect.height * 0.5f; - } - - protected bool TryGetDropPosition(TreeViewItem item, Rect itemRect, int row, out DropPosition dropPosition) - { - Vector2 currentMousePos = Event.current.mousePosition; - - if (itemRect.Contains(currentMousePos)) - { - float dropBetweenHalfHeight = GetDropBetweenHalfHeight(item, itemRect); - if (currentMousePos.y >= itemRect.yMax - dropBetweenHalfHeight) - dropPosition = DropPosition.Below; - else if (currentMousePos.y <= itemRect.yMin + dropBetweenHalfHeight) - dropPosition = DropPosition.Above; - else - dropPosition = DropPosition.Upon; - return true; - } - else - { - // Check overlap with next item (if any) - float nextOverlap = m_TreeView.gui.halfDropBetweenHeight; - int nextRow = row + 1; - if (nextRow < m_TreeView.data.rowCount) - { - Rect nextRect = m_TreeView.gui.GetRowRect(nextRow, itemRect.width); - bool nextCanBeParent = m_TreeView.data.CanBeParent(m_TreeView.data.GetItem(nextRow)); - if (nextCanBeParent) - nextOverlap = m_TreeView.gui.halfDropBetweenHeight; - else - nextOverlap = nextRect.height * 0.5f; - } - Rect nextOverlapRect = itemRect; - nextOverlapRect.y = itemRect.yMax; - nextOverlapRect.height = nextOverlap; - if (nextOverlapRect.Contains(currentMousePos)) - { - dropPosition = DropPosition.Below; - return true; - } - - // Check overlap above first item - if (row == 0) - { - Rect overlapUpwards = itemRect; - overlapUpwards.yMin -= m_TreeView.gui.halfDropBetweenHeight; - overlapUpwards.height = m_TreeView.gui.halfDropBetweenHeight; - if (overlapUpwards.Contains(currentMousePos)) - { - dropPosition = DropPosition.Above; - return true; - } - } - } - - dropPosition = DropPosition.Below; - return false; - } - - // This method is called from TreeView and handles: - // - Where the dragged items are dropped (above, below or upon) - // - Auto expansion of collapsed items when hovering over them - // - Setting up the render markers for drop location (horizontal lines) - // 'targetItem' is null when not hovering over any target Item, if so the rest if the arguments are invalid - public virtual bool DragElement(TreeViewItem targetItem, Rect targetItemRect, int row) - { - bool perform = Event.current.type == EventType.DragPerform; - - // Are we dragging outside any items - if (targetItem == null) - { - // If so clear any drop markers - if (m_DropData != null) - { - m_DropData.dropTargetControlID = 0; - m_DropData.rowMarkerControlID = 0; - } - - // And let client decide what happens when dragging outside items - - DragAndDrop.visualMode = DoDrag(null, null, perform, DropPosition.Below); - if (DragAndDrop.visualMode != DragAndDropVisualMode.None && perform) - FinalizeDragPerformed(true); - - return false; - } - - DropPosition dropPosition; - if (!TryGetDropPosition(targetItem, targetItemRect, row, out dropPosition)) - return false; - - TreeViewItem parentItem = null; - switch (dropPosition) - { - case DropPosition.Upon: - { - // Client must decide what happens when dropping upon: e.g: insert last or first in child list - parentItem = targetItem; - } - break; - case DropPosition.Below: - { - // When hovering between an expanded parent and its first child then make sure we change state to match that - if (m_TreeView.data.IsExpanded(targetItem) && targetItem.hasChildren) - { - parentItem = targetItem; - targetItem = targetItem.children[0]; - dropPosition = DropPosition.Above; - } - else - { - // Drop as next sibling to target - parentItem = targetItem.parent; - } - } - break; - case DropPosition.Above: - { - parentItem = targetItem.parent; - } - break; - default: - Assert.IsTrue(false, "Unhandled enum"); - break; - } - - - DragAndDropVisualMode mode = DragAndDropVisualMode.None; - if (perform) - { - // Try Drop on top of element - if (dropPosition == DropPosition.Upon) - mode = DoDrag(targetItem, targetItem, true, dropPosition); - - // Fall back to dropping on parent (drop between elements) - if (mode == DragAndDropVisualMode.None && parentItem != null) - { - mode = DoDrag(parentItem, targetItem, true, dropPosition); - } - - // Finalize drop - if (mode != DragAndDropVisualMode.None) - { - FinalizeDragPerformed(false); - } - else - { - DragCleanup(true); - m_TreeView.NotifyListenersThatDragEnded(null, false); - } - } - else // DragUpdate - { - if (m_DropData == null) - m_DropData = new DropData(); - m_DropData.dropTargetControlID = 0; - m_DropData.rowMarkerControlID = 0; - - int itemControlID = TreeViewController.GetItemControlID(targetItem); - HandleAutoExpansion(itemControlID, targetItem, targetItemRect); - - // Try drop on top of element - if (dropPosition == DropPosition.Upon) - mode = DoDrag(targetItem, targetItem, false, dropPosition); - - if (mode != DragAndDropVisualMode.None) - { - m_DropData.dropTargetControlID = itemControlID; - DragAndDrop.visualMode = mode; - } - // Fall back to dropping on parent (drop between elements) - else if (targetItem != null && parentItem != null) - { - mode = DoDrag(parentItem, targetItem, false, dropPosition); - - if (mode != DragAndDropVisualMode.None) - { - drawRowMarkerAbove = dropPosition == DropPosition.Above; - m_DropData.rowMarkerControlID = itemControlID; - DragAndDrop.visualMode = mode; - } - } - } - - Event.current.Use(); - return true; - } - - void FinalizeDragPerformed(bool revertExpanded) - { - DragCleanup(revertExpanded); - DragAndDrop.AcceptDrag(); - - List objs = new List(DragAndDrop.objectReferences); // TODO, what about when dragging non objects... - - bool draggedItemsFromOwnTreeView = true; - if (objs.Count > 0 && objs[0] != null && TreeViewUtility.FindItemInList(objs[0].GetInstanceID(), m_TreeView.data.GetRows()) == null) - draggedItemsFromOwnTreeView = false; - - int[] newSelection = new int[objs.Count]; - for (int i = 0; i < objs.Count; ++i) - { - if (objs[i] == null) - continue; - - newSelection[i] = (objs[i].GetInstanceID()); - } - m_TreeView.NotifyListenersThatDragEnded(newSelection, draggedItemsFromOwnTreeView); - } - - protected virtual void HandleAutoExpansion(int itemControlID, TreeViewItem targetItem, Rect targetItemRect) - { - Vector2 currentMousePos = Event.current.mousePosition; - - // Handle auto expansion - float targetItemIndent = m_TreeView.gui.GetContentIndent(targetItem); - float betweenHalfHeight = GetDropBetweenHalfHeight(targetItem, targetItemRect); - Rect indentedContentRect = new Rect(targetItemRect.x + targetItemIndent, targetItemRect.y + betweenHalfHeight, targetItemRect.width - targetItemIndent, targetItemRect.height - betweenHalfHeight * 2); - bool hoveringOverIndentedContent = indentedContentRect.Contains(currentMousePos); - - if (itemControlID != m_DropData.lastControlID || !hoveringOverIndentedContent || m_DropData.expandItemBeginPosition != currentMousePos) - { - m_DropData.lastControlID = itemControlID; - m_DropData.expandItemBeginTimer = Time.realtimeSinceStartup; - m_DropData.expandItemBeginPosition = currentMousePos; - } - - bool expandTimerExpired = Time.realtimeSinceStartup - m_DropData.expandItemBeginTimer > k_DropExpandTimeout; - bool mayExpand = hoveringOverIndentedContent && expandTimerExpired; - - // Auto open folders we are about to drag into - if (targetItem != null && mayExpand && targetItem.hasChildren && !m_TreeView.data.IsExpanded(targetItem)) - { - // Store the expanded array prior to drag so we can revert it with a delay later - if (m_DropData.expandedArrayBeforeDrag == null) - { - List expandedIDs = GetCurrentExpanded(); - m_DropData.expandedArrayBeforeDrag = expandedIDs.ToArray(); - } - - m_TreeView.data.SetExpanded(targetItem, true); - m_DropData.expandItemBeginTimer = Time.realtimeSinceStartup; - m_DropData.lastControlID = 0; - } - } - - public virtual void DragCleanup(bool revertExpanded) - { - if (m_DropData != null) - { - if (m_DropData.expandedArrayBeforeDrag != null && revertExpanded) - { - RestoreExpanded(new List(m_DropData.expandedArrayBeforeDrag)); - } - m_DropData = new DropData(); - } - } - - public List GetCurrentExpanded() - { - var visibleItems = m_TreeView.data.GetRows(); - List expandedIDs = (from item in visibleItems - where m_TreeView.data.IsExpanded(item) - select item.id).ToList(); - return expandedIDs; - } - - // We assume that we can only have expanded items during dragging - public void RestoreExpanded(List ids) - { - var visibleItems = m_TreeView.data.GetRows(); - foreach (TreeViewItem item in visibleItems) - m_TreeView.data.SetExpanded(item, ids.Contains(item.id)); - } - - internal static int GetInsertionIndex(TreeViewItem parentItem, TreeViewItem targetItem, DropPosition dropPosition) - { - if (parentItem == null) - return -1; - - int insertionIndex; - if (parentItem == targetItem) - { - // Let user decide what index item should be added to when dropping upon - insertionIndex = -1; - Assert.AreEqual(DropPosition.Upon, dropPosition); - } - else - { - int index = parentItem.children.IndexOf(targetItem); - if (index >= 0) - { - if (dropPosition == DropPosition.Below) - insertionIndex = index + 1; - else - insertionIndex = index; - } - else - { - Debug.LogError("Did not find targetItem,; should be a child of parentItem"); - insertionIndex = -1; - } - } - return insertionIndex; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewExpandAnimator.cs b/Editor/Mono/GUI/TreeView/TreeViewExpandAnimator.cs deleted file mode 100644 index 1e09233d63..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewExpandAnimator.cs +++ /dev/null @@ -1,320 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - // Setup animation, tracks animation, fires callback when done (fully expanded/collapsed) - // - - internal class TreeViewItemExpansionAnimator - { - TreeViewAnimationInput m_Setup; // when null we are not animating - bool m_InsideGUIClip; - Rect m_CurrentClipRect; - static bool s_Debug = false; - - public void BeginAnimating(TreeViewAnimationInput setup) - { - if (m_Setup != null) - { - if (m_Setup.item.id == setup.item.id && m_Setup.expanding != setup.expanding) - { - // If same item (changed expand/collapse while animating) then just change direction, but skip the time that already passed - if (m_Setup.elapsedTime >= 0) - { - setup.elapsedTime = m_Setup.animationDuration - m_Setup.elapsedTime; - } - else - Debug.LogError("Invalid duration " + m_Setup.elapsedTime); - - m_Setup = setup; - } - else - { - // Ensure current animation ends before starting a new (just finish it immediately) - SkipAnimating(); - m_Setup = setup; - } - - m_Setup.expanding = setup.expanding; - } - - m_Setup = setup; - if (m_Setup == null) - Debug.LogError("Setup is null"); - - if (printDebug) - Console.WriteLine("Begin animating: " + m_Setup); - - m_CurrentClipRect = GetCurrentClippingRect(); - } - - public void SkipAnimating() - { - if (m_Setup != null) - { - m_Setup.FireAnimationEndedEvent(); - m_Setup = null; - } - } - - // Returns true if row should be culled - public bool CullRow(int row, ITreeViewGUI gui) - { - if (!isAnimating) - { - return false; - } - - if (printDebug && row == 0) - Console.WriteLine("--------"); - - // Check rows that are inside animation clip rect if they can be culled - if (row > m_Setup.startRow && row <= m_Setup.endRow) - { - Rect rowRect = gui.GetRowRect(row, 1); // we do not care about the width - - // Check row Y local to clipRect - float rowY = rowRect.y - m_Setup.startRowRect.y; - - if (rowY > m_CurrentClipRect.height) - { - // Ensure to end animation clip since items after - // culling should be rendered normally - if (m_InsideGUIClip) - { - EndClip(); - } - - return true; - } - } - - // Row is not culled - return false; - } - - public void OnRowGUI(int row) - { - if (printDebug) - Console.WriteLine(row + " Do item " + DebugItemName(row)); - } - - // Call before of TreeViewGUI's OnRowGUI (Needs to be called for all items (changes rects for rows comming after the animating rows) - public Rect OnBeginRowGUI(int row, Rect rowRect) - { - if (!isAnimating) - return rowRect; - - if (row == m_Setup.startRow) - { - BeginClip(); - } - - // Make row rect local to guiclip if animating - if (row >= m_Setup.startRow && row <= m_Setup.endRow) - { - rowRect.y -= m_Setup.startRowRect.y; - } - // rows following the animation snap to cliprect bottom - else if (row > m_Setup.endRow) - { - rowRect.y -= m_Setup.rowsRect.height - m_CurrentClipRect.height; - } - - return rowRect; - } - - // Call at the after TreeViewGUI's OnRowGUI - public void OnEndRowGUI(int row) - { - if (!isAnimating) - return; - - if (m_InsideGUIClip && row == m_Setup.endRow) - { - EndClip(); - } - } - - // Call before all items are being handling - - - private void BeginClip() - { - GUI.BeginClip(m_CurrentClipRect); - m_InsideGUIClip = true; - if (printDebug) - Console.WriteLine("BeginClip startRow: " + m_Setup.startRow); - } - - private void EndClip() - { - GUI.EndClip(); - m_InsideGUIClip = false; - if (printDebug) - Console.WriteLine("EndClip endRow: " + m_Setup.endRow); - } - - public void OnBeforeAllRowsGUI() - { - if (!isAnimating) - return; - - // Cache to ensure consistent across all rows (it is dependant on time) - m_CurrentClipRect = GetCurrentClippingRect(); - - // Stop animation when duration has passed - if (m_Setup.elapsedTime > m_Setup.animationDuration) - { - m_Setup.FireAnimationEndedEvent(); - m_Setup = null; - - if (printDebug) - Debug.Log("Animation ended"); - } - } - - public void OnAfterAllRowsGUI() - { - // Ensure to end clip if not done in CullRow (while iterating rows) - if (m_InsideGUIClip) - { - EndClip(); - } - - if (isAnimating) - HandleUtility.Repaint(); - - // Capture time at intervals to ensure that expansion value is consistent across layout and repaint. - // This fixes that the scroll view showed its scrollbars during expansion since using realtime - // would give higher values on repaint than on layout event. - if (isAnimating && Event.current.type == EventType.Repaint) - m_Setup.CaptureTime(); - } - - public bool IsAnimating(int itemID) - { - if (!isAnimating) - return false; - - return m_Setup.item.id == itemID; - } - - // 1 fully expanded, 0 fully collapsed - public float expandedValueNormalized - { - get - { - float frac = m_Setup.elapsedTimeNormalized; - return m_Setup.expanding ? frac : (1.0f - frac); - } - } - - public int startRow - { - get { return m_Setup.startRow; } - } - - public int endRow - { - get { return m_Setup.endRow; } - } - - public float deltaHeight - { - get { return Mathf.Floor(m_Setup.rowsRect.height - m_Setup.rowsRect.height * expandedValueNormalized); } - } - - public bool isAnimating - { - get { return m_Setup != null; } - } - - public bool isExpanding - { - get { return m_Setup.expanding; } - } - - Rect GetCurrentClippingRect() - { - Rect rect = m_Setup.rowsRect; - rect.height *= expandedValueNormalized; - return rect; - } - - bool printDebug - { - get { return s_Debug && (m_Setup != null) && (m_Setup.treeView != null) && (Event.current.type == EventType.Repaint); } - } - - string DebugItemName(int row) - { - return m_Setup.treeView.data.GetRows()[row].displayName; - } - } - - internal class TreeViewAnimationInput - { - public TreeViewAnimationInput() - { - startTime = timeCaptured = EditorApplication.timeSinceStartup; - } - - public void CaptureTime() - { - timeCaptured = EditorApplication.timeSinceStartup; - } - - public float elapsedTimeNormalized - { - get - { - return Mathf.Clamp01((float)elapsedTime / (float)animationDuration); - } - } - - public double elapsedTime - { - get - { - return timeCaptured - startTime; - } - - set - { - startTime = timeCaptured - value; - } - } - - public int startRow { get; set; } - public int endRow { get; set; } - public Rect rowsRect {get; set; } // the rect encapsulating startrow and endrow - - public Rect startRowRect {get; set; } - public double startTime { get; set; } - public double timeCaptured { get; set; } - public double animationDuration { get; set; } - public bool expanding { get; set; } - public bool includeChildren { get; set; } - public TreeViewItem item { get; set; } - public TreeViewController treeView { get; set; } - - public System.Action animationEnded; // set to get a callback when animation ends - - public void FireAnimationEndedEvent() - { - if (animationEnded != null) - animationEnded(this); - } - - public override string ToString() - { - return "Input: startRow " + startRow + " endRow " + endRow + " rowsRect " + rowsRect + " startTime " + startTime + " anitmationDuration" + animationDuration + " " + expanding + " " + item.displayName; - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewGUI.cs b/Editor/Mono/GUI/TreeView/TreeViewGUI.cs deleted file mode 100644 index ae3751d751..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewGUI.cs +++ /dev/null @@ -1,502 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor.IMGUI.Controls -{ - internal abstract class TreeViewGUI : ITreeViewGUI - { - protected TreeViewController m_TreeView; - protected PingData m_Ping = new PingData(); - protected Rect m_DraggingInsertionMarkerRect; - protected bool m_UseHorizontalScroll; - - // Icon overlay - public float iconLeftPadding { get; set; } - public float iconRightPadding { get; set; } - public float iconTotalPadding { get { return iconLeftPadding + iconRightPadding; } } - public System.Action iconOverlayGUI { get; set; } // Rect includes iconLeftPadding and iconRightPadding - public System.Action labelOverlayGUI { get; set; } - - private bool m_AnimateScrollBarOnExpandCollapse = true; - - // Layout - public float k_LineHeight = 16f; - public float k_BaseIndent = 2f; - public float k_IndentWidth = 14f; - public float k_IconWidth = 16f; - public float k_SpaceBetweenIconAndText = 2f; - public float k_TopRowMargin = 0f; - public float k_BottomRowMargin = 0f; - public float indentWidth { get { return k_IndentWidth + iconTotalPadding; } } - public float k_HalfDropBetweenHeight = 4f; - public float customFoldoutYOffset = 0f; - public float extraInsertionMarkerIndent = 0f; - public float extraSpaceBeforeIconAndLabel { get; set; } - - public float halfDropBetweenHeight { get { return k_HalfDropBetweenHeight; } } - - public virtual float topRowMargin { get { return k_TopRowMargin; } } - public virtual float bottomRowMargin { get { return k_BottomRowMargin; } } - - // Styles - internal static class Styles - { - public static GUIStyle foldout = "IN Foldout"; - public static GUIStyle insertion = new GUIStyle("PR Insertion"); - public static GUIStyle ping = new GUIStyle("PR Ping"); - public static GUIStyle toolbarButton = "ToolbarButton"; - public static GUIStyle lineStyle = new GUIStyle("PR Label"); - public static GUIStyle lineBoldStyle; - public static GUIStyle selectionStyle = new GUIStyle("PR Label"); - public static GUIContent content = new GUIContent(EditorGUIUtility.FindTexture(EditorResourcesUtility.folderIconName)); - - static Styles() - { - // We want to render selection separately from text and icon, so clear background textures - - // TODO: Fix in new style setup - var transparent = lineStyle.hover.background; - lineStyle.onNormal.background = transparent; - lineStyle.onActive.background = transparent; - lineStyle.onFocused.background = transparent; - lineStyle.alignment = TextAnchor.UpperLeft; // We use UpperLeft to use same alignment as labels and controls so it is consistent when used in multi column treeviews - lineStyle.padding.top = 2; // Use a value that centers the text when the rect height is EditorGUIUtility.singleLineHeight - lineStyle.fixedHeight = 0; // Ensure drop marker rendering fits to entire rect - - lineBoldStyle = new GUIStyle(lineStyle); - lineBoldStyle.font = EditorStyles.boldLabel.font; - lineBoldStyle.fontStyle = EditorStyles.boldLabel.fontStyle; - ping.padding.left = 16; - ping.padding.right = 16; - ping.fixedHeight = 16; // needed because otherwise height becomes the largest mip map size in the icon - - selectionStyle.fixedHeight = 0; - selectionStyle.border = new RectOffset(); - - insertion.overflow = new RectOffset(4, 0, 0, 0); - } - - public static float foldoutWidth - { - get { return foldout.fixedWidth; } - } - } - - public TreeViewGUI(TreeViewController treeView) - { - m_TreeView = treeView; - } - - public TreeViewGUI(TreeViewController treeView, bool useHorizontalScroll) - { - m_TreeView = treeView; - m_UseHorizontalScroll = useHorizontalScroll; - } - - virtual public void OnInitialize() - { - } - - protected virtual Texture GetIconForItem(TreeViewItem item) - { - return item.icon; - } - - // ------------------ - // Size section - - // Calc correct width if horizontal scrollbar is wanted return new Vector2(1, height) - virtual public Vector2 GetTotalSize() - { - // Width is 1 to prevent showing horizontal scrollbar - float width = 1f; - if (m_UseHorizontalScroll) - { - var rows = m_TreeView.data.GetRows(); - width = GetMaxWidth(rows); - } - - // Height - float height = m_TreeView.data.rowCount * k_LineHeight + topRowMargin + bottomRowMargin; - - - if (m_AnimateScrollBarOnExpandCollapse && m_TreeView.expansionAnimator.isAnimating) - { - height -= m_TreeView.expansionAnimator.deltaHeight; - } - - return new Vector2(width, height); - } - - protected float GetMaxWidth(IList rows) - { - float maxWidth = 1f; - - foreach (TreeViewItem item in rows) - { - float width = 0f; - - width += GetContentIndent(item); - - if (item.icon != null) - width += k_IconWidth; - - float minNameWidth, maxNameWidth; - Styles.lineStyle.CalcMinMaxWidth(GUIContent.Temp(item.displayName), out minNameWidth, out maxNameWidth); - width += maxNameWidth; - - // Add some padding to the back - width += k_BaseIndent; - - if (width > maxWidth) - maxWidth = width; - } - - return maxWidth; - } - - virtual public int GetNumRowsOnPageUpDown(TreeViewItem fromItem, bool pageUp, float heightOfTreeView) - { - return (int)Mathf.Floor(heightOfTreeView / k_LineHeight); - } - - // Should return the row index of the first and last row thats fits in the pixel rect defined by top and height - virtual public void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible) - { - if (m_TreeView.data.rowCount == 0) - { - firstRowVisible = lastRowVisible = -1; - return; - } - - float topPixel = m_TreeView.state.scrollPos.y; - float heightInPixels = m_TreeView.GetTotalRect().height; - firstRowVisible = (int)Mathf.Floor((topPixel - topRowMargin) / k_LineHeight); - lastRowVisible = firstRowVisible + (int)Mathf.Ceil(heightInPixels / k_LineHeight); - - firstRowVisible = Mathf.Max(firstRowVisible, 0); - lastRowVisible = Mathf.Min(lastRowVisible, m_TreeView.data.rowCount - 1); - - // Validate - if (firstRowVisible >= m_TreeView.data.rowCount && firstRowVisible > 0) - { - // Reset scroll if it was invalid, this can be the case if scroll y value was serialized and loading new tree data - m_TreeView.state.scrollPos.y = 0f; - GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible); - } - } - - // --------------------- - // OnGUI section - - virtual public void BeginRowGUI() - { - // Reset - m_DraggingInsertionMarkerRect.x = -1; - - SyncFakeItem(); // After domain reload we ensure to reconstruct new Item state - - // Input for rename overlay (repainted in EndRowGUI to ensure rendered on top) - if (Event.current.type != EventType.Repaint) - DoRenameOverlay(); - } - - virtual public void EndRowGUI() - { - // Draw row marker when dragging - if (m_DraggingInsertionMarkerRect.x >= 0 && Event.current.type == EventType.Repaint) - { - Styles.insertion.Draw(m_DraggingInsertionMarkerRect, false, false, false, false); - } - // Render rename overlay last (input is handled in BeginRowGUI) - if (Event.current.type == EventType.Repaint) - DoRenameOverlay(); - - // Ping a Item - HandlePing(); - } - - virtual public void OnRowGUI(Rect rowRect, TreeViewItem item, int row, bool selected, bool focused) - { - DoItemGUI(rowRect, row, item, selected, focused, false); - } - - protected virtual void DrawItemBackground(Rect rect, int row, TreeViewItem item, bool selected, bool focused) - { - // override for custom rendering of background behind selection and drop effect rendering - } - - public virtual Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item) - { - float offset = GetContentIndent(item) + extraSpaceBeforeIconAndLabel; - - if (GetIconForItem(item) != null) - offset += k_SpaceBetweenIconAndText + k_IconWidth + iconTotalPadding; - - // By default we top align the rename rect to follow the label style, foldout and controls alignment - return new Rect(rowRect.x + offset, rowRect.y, rowRect.width - offset, EditorGUIUtility.singleLineHeight); - } - - virtual protected void DoItemGUI(Rect rect, int row, TreeViewItem item, bool selected, bool focused, bool useBoldFont) - { - EditorGUIUtility.SetIconSize(new Vector2(k_IconWidth, k_IconWidth)); // If not set we see icons scaling down if text is being cropped - - float indent = GetFoldoutIndent(item); - - int itemControlID = TreeViewController.GetItemControlID(item); - - bool isDropTarget = false; - if (m_TreeView.dragging != null) - isDropTarget = m_TreeView.dragging.GetDropTargetControlID() == itemControlID && m_TreeView.data.CanBeParent(item); - bool isRenamingThisItem = IsRenaming(item.id); - bool showFoldout = m_TreeView.data.IsExpandable(item); - - // Adjust edit field if needed (on repaint since on layout rect.width is invalid when using GUILayout) - if (isRenamingThisItem && Event.current.type == EventType.Repaint) - { - GetRenameOverlay().editFieldRect = GetRenameRect(rect, row, item); - } - - string label = item.displayName; - if (isRenamingThisItem) - { - selected = false; - label = ""; - } - - if (Event.current.type == EventType.Repaint) - { - // Draw background (can be overridden) - DrawItemBackground(rect, row, item, selected, focused); - - // Draw selection - if (selected) - Styles.selectionStyle.Draw(rect, false, false, true, focused); - - // Draw drop marker - if (isDropTarget) - Styles.lineStyle.Draw(rect, GUIContent.none, true, true, false, false); - - // Show insertion marker below this item (rendered end of rows) - if (m_TreeView.dragging != null && m_TreeView.dragging.GetRowMarkerControlID() == itemControlID) - { - float yPos = (m_TreeView.dragging.drawRowMarkerAbove ? rect.y : rect.yMax) - Styles.insertion.fixedHeight * 0.5f; - m_DraggingInsertionMarkerRect = new Rect(rect.x + indent + extraInsertionMarkerIndent + Styles.foldoutWidth + Styles.lineStyle.margin.left, yPos, rect.width - indent, rect.height); - } - } - - // Do row content (icon, label, controls etc) - OnContentGUI(rect, row, item, label, selected, focused, useBoldFont, false); - - // Do foldout - if (showFoldout) - { - DoFoldout(rect, item, row); - } - - EditorGUIUtility.SetIconSize(Vector2.zero); - } - - float GetTopPixelOfRow(int row) - { - return row * k_LineHeight + topRowMargin; - } - - public virtual Rect GetRowRect(int row, float rowWidth) - { - return new Rect(0, GetTopPixelOfRow(row), rowWidth, k_LineHeight); - } - - public virtual Rect GetRectForFraming(int row) - { - return GetRowRect(row, 1); // We ignore width by default when framing (only y scroll is affected) - } - - float GetFoldoutYPosition(float rectY) - { - // By default the arrow is aligned to the top to match text rendering - return rectY + customFoldoutYOffset; - } - - protected virtual Rect DoFoldout(Rect rect, TreeViewItem item, int row) - { - float indent = GetFoldoutIndent(item); - Rect foldoutRect = new Rect(rect.x + indent, GetFoldoutYPosition(rect.y), Styles.foldoutWidth, EditorGUIUtility.singleLineHeight); - FoldoutButton(foldoutRect, item, row, Styles.foldout); - return foldoutRect; - } - - protected virtual void FoldoutButton(Rect foldoutRect, TreeViewItem item, int row, GUIStyle foldoutStyle) - { - var expansionAnimator = m_TreeView.expansionAnimator; - - bool newExpandedValue; - EditorGUI.BeginChangeCheck(); - { - bool expandedState = expansionAnimator.IsAnimating(item.id) ? expansionAnimator.isExpanding : m_TreeView.data.IsExpanded(item); - newExpandedValue = GUI.Toggle(foldoutRect, expandedState, GUIContent.none, foldoutStyle); - } - if (EditorGUI.EndChangeCheck()) - { - m_TreeView.UserInputChangedExpandedState(item, row, newExpandedValue); - } - } - - protected virtual void OnContentGUI(Rect rect, int row, TreeViewItem item, string label, bool selected, bool focused, bool useBoldFont, bool isPinging) - { - if (Event.current.rawType != EventType.Repaint) - return; - - if (!isPinging) - { - // The rect is assumed indented and sized after the content when pinging - float indent = GetContentIndent(item) + extraSpaceBeforeIconAndLabel; - rect.xMin += indent; - } - - GUIStyle lineStyle = useBoldFont ? Styles.lineBoldStyle : Styles.lineStyle; - - // Draw icon - Rect iconRect = rect; - iconRect.width = k_IconWidth; - iconRect.x += iconLeftPadding; - - Texture icon = GetIconForItem(item); - if (icon != null) - GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit); - - if (iconOverlayGUI != null) - { - Rect iconOverlayRect = rect; - iconOverlayRect.width = k_IconWidth + iconTotalPadding; - iconOverlayGUI(item, iconOverlayRect); - } - - // Draw text - lineStyle.padding.left = 0; - - if (icon != null) - rect.xMin += k_IconWidth + iconTotalPadding + k_SpaceBetweenIconAndText; - lineStyle.Draw(rect, label, false, false, selected, focused); - - if (labelOverlayGUI != null) - { - labelOverlayGUI(item, rect); - } - } - - // Ping Item - // ------------- - - virtual public void BeginPingItem(TreeViewItem item, float topPixelOfRow, float availableWidth) - { - if (item == null) - return; - - // Setup ping - if (topPixelOfRow >= 0f) - { - m_Ping.m_TimeStart = Time.realtimeSinceStartup; - m_Ping.m_PingStyle = Styles.ping; - - GUIContent cont = GUIContent.Temp(item.displayName); - Vector2 contentSize = m_Ping.m_PingStyle.CalcSize(cont); - - m_Ping.m_ContentRect = new Rect(GetContentIndent(item) + extraSpaceBeforeIconAndLabel, - topPixelOfRow, - k_IconWidth + k_SpaceBetweenIconAndText + contentSize.x + iconTotalPadding, - contentSize.y); - m_Ping.m_AvailableWidth = availableWidth; - - int row = m_TreeView.data.GetRow(item.id); - - bool useBoldFont = item.displayName.Equals("Assets"); - m_Ping.m_ContentDraw = (Rect r) => - { - // get Item parameters from closure - OnContentGUI(r, row, item, item.displayName, false, false, useBoldFont, true); - }; - - m_TreeView.Repaint(); - } - } - - virtual public void EndPingItem() - { - m_Ping.m_TimeStart = -1f; - } - - void HandlePing() - { - m_Ping.HandlePing(); - - if (m_Ping.isPinging) - m_TreeView.Repaint(); - } - - //------------------- - // Rename section - - protected RenameOverlay GetRenameOverlay() - { - return m_TreeView.state.renameOverlay; - } - - virtual protected bool IsRenaming(int id) - { - return GetRenameOverlay().IsRenaming() && GetRenameOverlay().userData == id && !GetRenameOverlay().isWaitingForDelay; - } - - virtual public bool BeginRename(TreeViewItem item, float delay) - { - return GetRenameOverlay().BeginRename(item.displayName, item.id, delay); - } - - virtual public void EndRename() - { - // We give keyboard focus back to our tree view because the rename utility stole it (now we give it back) - if (GetRenameOverlay().HasKeyboardFocus()) - m_TreeView.GrabKeyboardFocus(); - - RenameEnded(); - ClearRenameAndNewItemState(); // Ensure clearing if RenameEnden is overrided - } - - virtual protected void RenameEnded() {} - - virtual public void DoRenameOverlay() - { - if (GetRenameOverlay().IsRenaming()) - if (!GetRenameOverlay().OnGUI()) - EndRename(); - } - - virtual protected void SyncFakeItem() {} - - - virtual protected void ClearRenameAndNewItemState() - { - m_TreeView.data.RemoveFakeItem(); - GetRenameOverlay().Clear(); - } - - virtual public float GetFoldoutIndent(TreeViewItem item) - { - // Ignore depth when showing search results - if (m_TreeView.isSearching) - return k_BaseIndent; - - return k_BaseIndent + item.depth * indentWidth; - } - - virtual public float GetContentIndent(TreeViewItem item) - { - return GetFoldoutIndent(item) + Styles.foldoutWidth + Styles.lineStyle.margin.left; - } - } -} diff --git a/Editor/Mono/GUI/TreeView/TreeViewGUIWithCustomItemHeights.cs b/Editor/Mono/GUI/TreeView/TreeViewGUIWithCustomItemHeights.cs deleted file mode 100644 index f4f50e3e0b..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewGUIWithCustomItemHeights.cs +++ /dev/null @@ -1,196 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.IMGUI.Controls; -using UnityEngine; - - -namespace UnityEditor -{ - // Total size: 1) When changing: non changing rows + changing rows fraction, 2) When not changing sum of rows - // Size of changing rows fraction used for finding new endRow after last changing row - - internal abstract class TreeViewGUIWithCustomItemsHeights : ITreeViewGUI - { - private List m_RowRects = new List(); - private float m_MaxWidthOfRows; - protected readonly TreeViewController m_TreeView; - - public TreeViewGUIWithCustomItemsHeights(TreeViewController treeView) - { - m_TreeView = treeView; - } - - public virtual void OnInitialize() - { - } - - public Rect GetRowRect(int row, float rowWidth) - { - if (m_RowRects.Count == 0) - { - Debug.LogError("Ensure precalc rects"); - return new Rect(); - } - - return m_RowRects[row]; - } - - public Rect GetRenameRect(Rect rowRect, int row, TreeViewItem item) - { - return new Rect(); - } - - public Rect GetRectForFraming(int row) - { - return GetRowRect(row, 1); - } - - public abstract void OnRowGUI(Rect rowRect, TreeViewItem item, int row, bool selected, bool focused); - - protected virtual float AddSpaceBefore(TreeViewItem item) - { - return 0; - } - - protected virtual Vector2 GetSizeOfRow(TreeViewItem item) - { - return new Vector2(m_TreeView.GetTotalRect().width, 16); - } - - public void CalculateRowRects() - { - if (m_TreeView.isSearching) - return; - const float startY = 2f; - var rows = m_TreeView.data.GetRows(); - m_RowRects = new List(rows.Count); - float curY = startY; - m_MaxWidthOfRows = 1f; - for (int i = 0; i < rows.Count; ++i) - { - TreeViewItem item = rows[i]; - float space = AddSpaceBefore(item); - curY += space; - Vector2 rowSize = GetSizeOfRow(item); - m_RowRects.Add(new Rect(0, curY, rowSize.x, rowSize.y)); - curY += rowSize.y; - if (rowSize.x > m_MaxWidthOfRows) - m_MaxWidthOfRows = rowSize.x; - } - } - - // Calc correct width if horizontal scrollbar is wanted return new Vector2(1, height) - public Vector2 GetTotalSize() - { - if (m_RowRects.Count == 0) - return new Vector2(0, 0); - - return new Vector2(m_MaxWidthOfRows, m_RowRects[m_RowRects.Count - 1].yMax); - } - - public int GetNumRowsOnPageUpDown(TreeViewItem fromItem, bool pageUp, float heightOfTreeView) - { - Debug.LogError("GetNumRowsOnPageUpDown: Not impemented"); - return (int)Mathf.Floor(heightOfTreeView / 30); // return something - } - - // Should return the row number of the first and last row thats fits in the pixel rect defined by top and height - public void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible) - { - float topPixel = m_TreeView.state.scrollPos.y; - float heightInPixels = m_TreeView.GetTotalRect().height; - - var rowCount = m_TreeView.data.rowCount; - if (rowCount != m_RowRects.Count) - { - Debug.LogError("Mismatch in state: rows vs cached rects. Did you remember to hook up: dataSource.onVisibleRowsChanged += gui.CalculateRowRects ?"); - CalculateRowRects(); - } - - int firstVisible = -1; - int lastVisible = -1; - - for (int i = 0; i < m_RowRects.Count; ++i) - { - bool visible = ((m_RowRects[i].y > topPixel && (m_RowRects[i].y < topPixel + heightInPixels))) || - ((m_RowRects[i].yMax > topPixel && (m_RowRects[i].yMax < topPixel + heightInPixels))); - - if (visible) - { - if (firstVisible == -1) - firstVisible = i; - lastVisible = i; - } - } - - if (firstVisible != -1 && lastVisible != -1) - { - firstRowVisible = firstVisible; - lastRowVisible = lastVisible; - } - else - { - firstRowVisible = 0; - lastRowVisible = rowCount - 1; - } - } - - public virtual void BeginRowGUI() - { - } - - public virtual void EndRowGUI() - { - } - - public virtual void BeginPingItem(TreeViewItem item, float topPixelOfRow, float availableWidth) - { - throw new NotImplementedException(); - } - - public virtual void EndPingItem() - { - throw new NotImplementedException(); - } - - public virtual bool BeginRename(TreeViewItem item, float delay) - { - throw new NotImplementedException(); - } - - public virtual void EndRename() - { - throw new NotImplementedException(); - } - - public virtual float halfDropBetweenHeight - { - get { return 8f; } - } - public virtual float topRowMargin { get; private set; } - public virtual float bottomRowMargin { get; private set; } - - protected float m_BaseIndent = 2f; - protected float m_IndentWidth = 14f; - protected float m_FoldoutWidth = 12f; - protected float indentWidth { get { return m_IndentWidth; } } - - virtual public float GetFoldoutIndent(TreeViewItem item) - { - // Ignore depth when showing search results - if (m_TreeView.isSearching) - return m_BaseIndent; - - return m_BaseIndent + item.depth * indentWidth; - } - - virtual public float GetContentIndent(TreeViewItem item) - { - return GetFoldoutIndent(item) + m_FoldoutWidth; - } - } -} diff --git a/Editor/Mono/GUI/TreeView/TreeViewItem.cs b/Editor/Mono/GUI/TreeView/TreeViewItem.cs deleted file mode 100644 index 44edd51115..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewItem.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor.IMGUI.Controls -{ - public class TreeViewItem : System.IComparable - { - int m_ID; // The id should be unique for all items in TreeView because it is used for searching, selection etc. - TreeViewItem m_Parent; - List m_Children = null; - int m_Depth; - string m_DisplayName; - Texture2D m_Icon; - - public TreeViewItem() {} - - public TreeViewItem(int id) - { - m_ID = id; - } - - public TreeViewItem(int id, int depth) - { - m_ID = id; - m_Depth = depth; - } - - public TreeViewItem(int id, int depth, string displayName) - { - m_Depth = depth; - m_ID = id; - m_DisplayName = displayName; - } - - internal TreeViewItem(int id, int depth, TreeViewItem parent, string displayName) - { - m_Depth = depth; - m_Parent = parent; - m_ID = id; - m_DisplayName = displayName; - } - - public virtual int id { get { return m_ID; } set { m_ID = value; }} - public virtual string displayName { get { return m_DisplayName; } set { m_DisplayName = value; } } - public virtual int depth { get { return m_Depth; } set { m_Depth = value; } } - public virtual bool hasChildren { get { return m_Children != null && m_Children.Count > 0; } } - public virtual List children { get { return m_Children; } set { m_Children = value; } } - public virtual TreeViewItem parent { get { return m_Parent; } set { m_Parent = value; } } - public virtual Texture2D icon { get { return m_Icon; } set { m_Icon = value; } } - - public void AddChild(TreeViewItem child) - { - if (m_Children == null) - m_Children = new List(); - - m_Children.Add(child); - - if (child != null) - child.parent = this; - } - - public virtual int CompareTo(TreeViewItem other) - { - return displayName.CompareTo(other.displayName); - } - - public override string ToString() - { - 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); - } - } - - class TreeViewItemAlphaNumericSort : IComparer - { - public int Compare(TreeViewItem lhs, TreeViewItem rhs) - { - if (lhs == rhs) return 0; - if (lhs == null) return -1; - if (rhs == null) return 1; - - return EditorUtility.NaturalCompare(lhs.displayName, rhs.displayName); - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTest.cs b/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTest.cs deleted file mode 100644 index e1cf5d1224..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTest.cs +++ /dev/null @@ -1,143 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; -using UnityEngine.Profiling; - - -namespace UnityEditor.TreeViewExamples -{ - internal class TreeViewStateWithColumns : TreeViewState - { - [SerializeField] - public float[] columnWidths; - } - - internal class TreeViewTest - { - private BackendData m_BackendData; - private TreeViewController m_TreeView; - private EditorWindow m_EditorWindow; - private bool m_Lazy; - private TreeViewColumnHeader m_ColumnHeader; - private GUIStyle m_HeaderStyle; - private GUIStyle m_HeaderStyleRightAligned; - - public int GetNumItemsInData() - { - return m_BackendData.IDCounter; - } - - public int GetNumItemsInTree() - { - var data = m_TreeView.data as LazyTestDataSource; - if (data != null) - return data.itemCounter; - - var data2 = m_TreeView.data as TestDataSource; - if (data2 != null) - return data2.itemCounter; - - return -1; - } - - public TreeViewTest(EditorWindow editorWindow, bool lazy) - { - m_EditorWindow = editorWindow; - m_Lazy = lazy; - } - - public void Init(Rect rect, BackendData backendData) - { - if (m_TreeView != null) - return; - - m_BackendData = backendData; - - var state = new TreeViewStateWithColumns(); - state.columnWidths = new float[] {250f, 90f, 93f, 98f, 74f, 78f}; - - m_TreeView = new TreeViewController(m_EditorWindow, state); - ITreeViewGUI gui = new TestGUI(m_TreeView); - ITreeViewDragging dragging = new TestDragging(m_TreeView, m_BackendData); - ITreeViewDataSource dataSource; - if (m_Lazy) dataSource = new LazyTestDataSource(m_TreeView, m_BackendData); - else dataSource = new TestDataSource(m_TreeView, m_BackendData); - m_TreeView.Init(rect, dataSource, gui, dragging); - - - m_ColumnHeader = new TreeViewColumnHeader(); - m_ColumnHeader.columnWidths = state.columnWidths; - m_ColumnHeader.minColumnWidth = 30f; - m_ColumnHeader.columnRenderer += OnColumnRenderer; - } - - void OnColumnRenderer(int column, Rect rect) - { - if (m_HeaderStyle == null) - { - m_HeaderStyle = new GUIStyle(EditorStyles.toolbarButton); - m_HeaderStyle.padding.left = 4; - m_HeaderStyle.alignment = TextAnchor.MiddleLeft; - - m_HeaderStyleRightAligned = new GUIStyle(EditorStyles.toolbarButton); - m_HeaderStyleRightAligned.padding.right = 4; - m_HeaderStyleRightAligned.alignment = TextAnchor.MiddleRight; - } - - string[] headers = new[] { "Name", "Date Modified", "Size", "Kind", "Author", "Platform", "Faster", "Slower" }; - GUI.Label(rect, headers[column], (column % 2 == 0) ? m_HeaderStyle : m_HeaderStyleRightAligned); - } - - public void OnGUI(Rect rect) - { - int keyboardControl = GUIUtility.GetControlID(FocusType.Keyboard, rect); - - const float kHeaderHeight = 17f; - const float kBottomHeight = 20f; - Rect headerRect = new Rect(rect.x, rect.y, rect.width, kHeaderHeight); - Rect bottomRect = new Rect(rect.x, rect.yMax - kBottomHeight, rect.width, kBottomHeight); - - // Header - GUI.Label(headerRect, "", EditorStyles.toolbar); - m_ColumnHeader.OnGUI(headerRect); - - Profiler.BeginSample("TREEVIEW"); - - // TreeView - rect.y += headerRect.height; - rect.height -= headerRect.height + bottomRect.height; - m_TreeView.OnEvent(); - m_TreeView.OnGUI(rect, keyboardControl); - - Profiler.EndSample(); - - // BottomBar - GUILayout.BeginArea(bottomRect, GetHeader(), EditorStyles.helpBox); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - m_BackendData.m_RecursiveFindParentsBelow = GUILayout.Toggle(m_BackendData.m_RecursiveFindParentsBelow, GUIContent.Temp("Recursive")); - if (GUILayout.Button("Ping", EditorStyles.miniButton)) - { - int id = GetNumItemsInData() / 2; - m_TreeView.Frame(id, true, true); - m_TreeView.SetSelection(new[] {id}, false); - } - if (GUILayout.Button("Frame", EditorStyles.miniButton)) - { - int id = GetNumItemsInData() / 10; - m_TreeView.Frame(id, true, false); - m_TreeView.SetSelection(new[] { id }, false); - } - GUILayout.EndHorizontal(); - GUILayout.EndArea(); - } - - private string GetHeader() - { - return (m_Lazy ? "LAZY: " : "FULL: ") + "GUI items: " + GetNumItemsInTree() + " (data items: " + GetNumItemsInData() + ")"; - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestBackEnd.cs b/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestBackEnd.cs deleted file mode 100644 index 9049664ee2..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestBackEnd.cs +++ /dev/null @@ -1,243 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.IMGUI.Controls; -using UnityEngine; - - -namespace UnityEditor.TreeViewExamples -{ - internal class BackendData - { - public class Foo - { - public Foo(string name, int depth, int id) - { - this.name = name; - this.depth = depth; this.id = id; - } - - public string name { get; set; } - public int id { get; set; } - public int depth { get; set; } - public Foo parent { get; set; } - public List children { get; set; } - public bool hasChildren { get { return children != null && children.Count > 0; } } - } - - public Foo root { get { return m_Root; } } - - private Foo m_Root; - public bool m_RecursiveFindParentsBelow = true; - public int IDCounter { get; private set; } - private int m_MaxItems = 10000; - private const int k_MinChildren = 3; - private const int k_MaxChildren = 15; - private const float k_ProbOfLastDescendent = 0.5f; - private const int k_MaxDepth = 12; - - public void GenerateData(int maxNumItems) - { - m_MaxItems = maxNumItems; - IDCounter = 1; - m_Root = new Foo("Root", 0, 0); - for (int i = 0; i < 10; ++i) - AddChildrenRecursive(m_Root, UnityEngine.Random.Range(k_MinChildren, k_MaxChildren), true); - } - - public Foo Find(int id) - { - return FindRecursive(id, m_Root); - } - - public Foo FindRecursive(int id, Foo parent) - { - if (!parent.hasChildren) - return null; - - foreach (var child in parent.children) - { - if (child.id == id) - return child; - - var result = FindRecursive(id, child); - if (result != null) - return result; - } - - return null; - } - - public HashSet GetParentsBelow(int id) - { - Foo searchFromThis = FindItemRecursive(root, id); - if (searchFromThis != null) - { - if (m_RecursiveFindParentsBelow) - return GetParentsBelowRecursive(searchFromThis); - - return GetParentsBelowStackBased(searchFromThis); - } - return new HashSet(); - } - - private HashSet GetParentsBelowStackBased(Foo searchFromThis) - { - Stack stack = new Stack(); - stack.Push(searchFromThis); - - HashSet parentsBelow = new HashSet(); - while (stack.Count > 0) - { - Foo current = stack.Pop(); - if (current.hasChildren) - { - parentsBelow.Add(current.id); - foreach (var foo in current.children) - { - stack.Push(foo); - } - } - } - - return parentsBelow; - } - - private HashSet GetParentsBelowRecursive(Foo searchFromThis) - { - HashSet result = new HashSet(); - GetParentsBelowRecursive(searchFromThis, result); - return result; - } - - private static void GetParentsBelowRecursive(Foo item, HashSet parentIDs) - { - if (!item.hasChildren) - return; - parentIDs.Add(item.id); - foreach (var child in item.children) - GetParentsBelowRecursive(child, parentIDs); - } - - public void ReparentSelection(Foo parentItem, int insertionIndex, List draggedItems) - { - // Invalid reparenting input - if (parentItem == null) - return; - - // We are moving items so we adjust the insertion index to accomodate that any items above the insertion index is removed before inserting - if (insertionIndex > 0) - insertionIndex -= parentItem.children.GetRange(0, insertionIndex).Count(draggedItems.Contains); - - // Remove draggedItems from their parents - foreach (var draggedItem in draggedItems) - { - draggedItem.parent.children.Remove(draggedItem); // remove from old parent - draggedItem.parent = parentItem; // set new parent - } - - if (!parentItem.hasChildren) - parentItem.children = new List(); - var newChildren = new List(parentItem.children); - - // 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. - if (insertionIndex == -1) - insertionIndex = 0; - - // Insert dragged items under new parent - newChildren.InsertRange(insertionIndex, draggedItems); - parentItem.children = newChildren; - } - - void AddChildrenRecursive(Foo foo, int numChildren, bool force) - { - if (IDCounter > m_MaxItems) - return; - - if (foo.depth >= k_MaxDepth) - return; - - if (!force && UnityEngine.Random.value < k_ProbOfLastDescendent) - return; - - if (foo.children == null) - foo.children = new List(numChildren); - for (int i = 0; i < numChildren; ++i) - { - Foo child = new Foo("Tud" + IDCounter, foo.depth + 1, ++IDCounter); - child.parent = foo; - foo.children.Add(child); - } - - if (IDCounter > m_MaxItems) - return; - - foreach (var child in foo.children) - { - AddChildrenRecursive(child, UnityEngine.Random.Range(k_MinChildren, k_MaxChildren), false); - } - } - - public static Foo FindItemRecursive(Foo item, int id) - { - if (item == null) - return null; - - if (item.id == id) - return item; - - if (item.children == null) - return null; - - foreach (Foo child in item.children) - { - Foo result = FindItemRecursive(child, id); - if (result != null) - return result; - } - return null; - } - } - - internal class TreeViewColumnHeader - { - public float[] columnWidths { get; set; } - public float minColumnWidth { get; set; } - public float dragWidth { get; set; } - public Action columnRenderer { get; set; } - - public TreeViewColumnHeader() - { - minColumnWidth = 10; - dragWidth = 6f; - } - - public void OnGUI(Rect rect) - { - const float dragAreaWidth = 3f; - float columnPos = rect.x; - for (int i = 0; i < columnWidths.Length; ++i) - { - Rect columnRect = new Rect(columnPos, rect.y, columnWidths[i], rect.height); - columnPos += columnWidths[i]; - Rect dragRect = new Rect(columnPos - dragWidth / 2, rect.y, dragAreaWidth, rect.height); - float deltaX = EditorGUI.MouseDeltaReader(dragRect, true).x; - if (deltaX != 0f) - { - columnWidths[i] += deltaX; - columnWidths[i] = Mathf.Max(columnWidths[i], minColumnWidth); - } - - if (columnRenderer != null) - columnRenderer(i, columnRect); - - if (Event.current.type == EventType.Repaint) - EditorGUIUtility.AddCursorRect(dragRect, MouseCursor.SplitResizeLeftRight); - } - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestDataSource.cs b/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestDataSource.cs deleted file mode 100644 index 6fccb91416..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestDataSource.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEditor.IMGUI.Controls; - - -namespace UnityEditor.TreeViewExamples -{ - class TestDataSource : TreeViewDataSource - { - private BackendData m_Backend; - public int itemCounter { get; private set; } - - public TestDataSource(TreeViewController treeView, BackendData data) : base(treeView) - { - m_Backend = data; - FetchData(); - } - - public override void FetchData() - { - itemCounter = 1; - m_RootItem = new FooTreeViewItem(m_Backend.root.id, 0, null, m_Backend.root.name, m_Backend.root); - AddChildrenRecursive(m_Backend.root, m_RootItem); - m_NeedRefreshRows = true; - } - - void AddChildrenRecursive(BackendData.Foo source, TreeViewItem dest) - { - if (source.hasChildren) - { - dest.children = new List(source.children.Count); - for (int i = 0; i < source.children.Count; ++i) - { - BackendData.Foo s = source.children[i]; - dest.children.Add(new FooTreeViewItem(s.id, dest.depth + 1, dest, s.name, s)); - itemCounter++; - AddChildrenRecursive(s, dest.children[i]); - } - } - } - - public override bool CanBeParent(TreeViewItem item) - { - return true; - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestDragging.cs b/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestDragging.cs deleted file mode 100644 index e48657c331..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestDragging.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEditor.IMGUI.Controls; - - -namespace UnityEditor.TreeViewExamples -{ - internal class TestDragging : TreeViewDragging - { - private const string k_GenericDragID = "FooDragging"; - private BackendData m_BackendData; - - - class FooDragData - { - public FooDragData(List draggedItems) - { - m_DraggedItems = draggedItems; - } - - public List m_DraggedItems; - } - - public TestDragging(TreeViewController treeView, BackendData data) - : base(treeView) - { - m_BackendData = data; - } - - public override void StartDrag(TreeViewItem draggedItem, List draggedItemIDs) - { - DragAndDrop.PrepareStartDrag(); - DragAndDrop.SetGenericData(k_GenericDragID, new FooDragData(GetItemsFromIDs(draggedItemIDs))); - string title = draggedItemIDs.Count + " Foo" + (draggedItemIDs.Count > 1 ? "s" : ""); // title is only shown on OSX (at the cursor) - DragAndDrop.StartDrag(title); - } - - public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPos) - { - var dragData = DragAndDrop.GetGenericData(k_GenericDragID) as FooDragData; - var fooParent = parentItem as FooTreeViewItem; - if (fooParent != null && dragData != null) - { - bool validDrag = ValidDrag(parentItem, dragData.m_DraggedItems); - if (perform && validDrag) - { - // Do reparenting here - List draggedFoos = (from x in dragData.m_DraggedItems where x is FooTreeViewItem select((FooTreeViewItem)x).foo).ToList(); - var selectedIDs = (from x in dragData.m_DraggedItems where x is FooTreeViewItem select((FooTreeViewItem)x).id).ToArray(); - int insertionIndex = GetInsertionIndex(parentItem, targetItem, dropPos); - m_BackendData.ReparentSelection(fooParent.foo, insertionIndex, draggedFoos); - m_TreeView.ReloadData(); - m_TreeView.SetSelection(selectedIDs, true); - } - return validDrag ? DragAndDropVisualMode.Move : DragAndDropVisualMode.None; - } - return DragAndDropVisualMode.None; - } - - bool ValidDrag(TreeViewItem parent, List draggedItems) - { - TreeViewItem currentParent = parent; - while (currentParent != null) - { - if (draggedItems.Contains(currentParent)) - return false; - currentParent = currentParent.parent; - } - return true; - } - - private List GetItemsFromIDs(IEnumerable draggedItemIDs) - { - // Note we only drag visible items here... - return TreeViewUtility.FindItemsInList(draggedItemIDs, m_TreeView.data.GetRows()); - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestGUI.cs b/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestGUI.cs deleted file mode 100644 index 538a03e95f..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestGUI.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEditorInternal; -using UnityEngine; - - -namespace UnityEditor.TreeViewExamples -{ - internal class FooTreeViewItem : TreeViewItem - { - public BackendData.Foo foo { get; private set; } - public FooTreeViewItem(int id, int depth, TreeViewItem parent, string displayName, BackendData.Foo foo) - : base(id, depth, parent, displayName) - { - this.foo = foo; - } - } - - - class TestGUI : TreeViewGUI - { - private Texture2D m_FolderIcon = EditorGUIUtility.FindTexture(EditorResourcesUtility.folderIconName); - private Texture2D m_Icon = EditorGUIUtility.FindTexture("boo Script Icon"); - private GUIStyle m_LabelStyle; - private GUIStyle m_LabelStyleRightAlign; - - public TestGUI(TreeViewController treeView) - : base(treeView) - { - } - - protected override Texture GetIconForItem(TreeViewItem item) - { - return (item.hasChildren) ? m_FolderIcon : m_Icon; - } - - protected override void RenameEnded() - { - } - - protected override void SyncFakeItem() - { - } - - float[] columnWidths { get { return ((TreeViewStateWithColumns)m_TreeView.state).columnWidths; } } - - protected override void OnContentGUI(Rect rect, int row, TreeViewItem item, string label, bool selected, bool focused, bool useBoldFont, bool isPinging) - { - if (Event.current.rawType != EventType.Repaint) - return; - - if (m_LabelStyle == null) - { - m_LabelStyle = new GUIStyle(Styles.lineStyle); - m_LabelStyle.padding.left = m_LabelStyle.padding.right = 6; - - m_LabelStyleRightAlign = new GUIStyle(Styles.lineStyle); - m_LabelStyleRightAlign.padding.right = m_LabelStyleRightAlign.padding.left = 6; - m_LabelStyleRightAlign.alignment = TextAnchor.MiddleRight; - } - - if (selected) - Styles.selectionStyle.Draw(rect, false, false, true, focused); - - // If pinging just render main label and icon (not columns) - if (isPinging || columnWidths == null || columnWidths.Length == 0) - { - base.OnContentGUI(rect, row, item, label, selected, focused, useBoldFont, isPinging); - return; - } - - Rect columnRect = rect; - for (int i = 0; i < columnWidths.Length; ++i) - { - columnRect.width = columnWidths[i]; - if (i == 0) - base.OnContentGUI(columnRect, row, item, label, selected, focused, useBoldFont, isPinging); - else - GUI.Label(columnRect, "Zksdf SDFS DFASDF ", (i % 2 == 0) ? m_LabelStyle : m_LabelStyleRightAlign); - columnRect.x += columnRect.width; - } - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestGUICustom.cs b/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestGUICustom.cs deleted file mode 100644 index 6150d5e55a..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestGUICustom.cs +++ /dev/null @@ -1,130 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.ComponentModel; -using UnityEditor.IMGUI.Controls; -using UnityEngine; - - -namespace UnityEditor.TreeViewExamples -{ - class TestGUICustomItemHeights : TreeViewGUIWithCustomItemsHeights - { - internal class Styles - { - public static GUIStyle foldout = "IN Foldout"; - } - - private float m_Column1Width = 300; - protected Rect m_DraggingInsertionMarkerRect; - - public TestGUICustomItemHeights(TreeViewController treeView) - : base(treeView) - { - m_FoldoutWidth = Styles.foldout.fixedWidth; - } - - protected override Vector2 GetSizeOfRow(TreeViewItem item) - { - return new Vector2(m_TreeView.GetTotalRect().width, item.hasChildren ? 20 : 36f); - } - - public override void BeginRowGUI() - { - // Reset - m_DraggingInsertionMarkerRect.x = -1; - } - - public override void EndRowGUI() - { - base.EndRowGUI(); - - // Draw row marker when dragging - if (m_DraggingInsertionMarkerRect.x >= 0 && Event.current.type == EventType.Repaint) - { - Rect insertionRect = m_DraggingInsertionMarkerRect; - insertionRect.height = 2f; - insertionRect.y -= insertionRect.height / 2; - if (!m_TreeView.dragging.drawRowMarkerAbove) - insertionRect.y += m_DraggingInsertionMarkerRect.height; - - EditorGUI.DrawRect(insertionRect, Color.white); - } - } - - public override void OnRowGUI(Rect rowRect, TreeViewItem item, int row, bool selected, bool focused) - { - rowRect.height -= 1f; - Rect column1Rect = rowRect; - Rect column2Rect = rowRect; - column1Rect.width = m_Column1Width; - column1Rect.xMin += GetFoldoutIndent(item); - column2Rect.xMin += m_Column1Width + 1; - - float indent = GetFoldoutIndent(item); - Rect tmpRect = rowRect; - - int itemControlID = TreeViewController.GetItemControlID(item); - - bool isDropTarget = false; - if (m_TreeView.dragging != null) - isDropTarget = m_TreeView.dragging.GetDropTargetControlID() == itemControlID && m_TreeView.data.CanBeParent(item); - bool showFoldout = m_TreeView.data.IsExpandable(item); - - - Color selectedColor = new Color(0.0f, 0.22f, 0.44f); - Color normalColor = new Color(0.1f, 0.1f, 0.1f); - - EditorGUI.DrawRect(column1Rect, selected ? selectedColor : normalColor); - EditorGUI.DrawRect(column2Rect, selected ? selectedColor : normalColor); - - if (isDropTarget) - { - EditorGUI.DrawRect(new Rect(rowRect.x, rowRect.y, 3, rowRect.height), Color.yellow); - } - - if (Event.current.type == EventType.Repaint) - { - Rect labelRect = column1Rect; - labelRect.xMin += m_FoldoutWidth; - - GUI.Label(labelRect, item.displayName, EditorStyles.largeLabel); - if (rowRect.height > 20f) - { - labelRect.y += 16f; - GUI.Label(labelRect, "Ut tincidunt tortor. Donec nonummy, enim in lacinia pulvinar", EditorStyles.miniLabel); - } - - // Show marker below this Item - if (m_TreeView.dragging != null && m_TreeView.dragging.GetRowMarkerControlID() == itemControlID) - m_DraggingInsertionMarkerRect = new Rect(rowRect.x + indent , rowRect.y, rowRect.width - indent, rowRect.height); - } - - // Draw foldout (after text content above to ensure drop down icon is rendered above selection highlight) - if (showFoldout) - { - tmpRect.x = indent; - tmpRect.width = m_FoldoutWidth; - EditorGUI.BeginChangeCheck(); - bool newExpandedValue = GUI.Toggle(tmpRect, m_TreeView.data.IsExpanded(item), GUIContent.none, Styles.foldout); - if (EditorGUI.EndChangeCheck()) - { - m_TreeView.UserInputChangedExpandedState(item, row, newExpandedValue); - } - } - } - - /* - void ChangeExpandedState(TreeViewItem item, bool expand) - { - if (Event.current.alt) - m_TreeView.data.SetExpandedWithChildren(item, expand); - else - m_TreeView.data.SetExpanded(item, expand); - - if (expand) - m_TreeView.UserExpandedItem(item); - }*/ - } -} diff --git a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestLazyDataSource.cs b/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestLazyDataSource.cs deleted file mode 100644 index 1299439d0b..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestLazyDataSource.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEditor.IMGUI.Controls; - - -namespace UnityEditor.TreeViewExamples -{ - class LazyTestDataSource : LazyTreeViewDataSource - { - private BackendData m_Backend; - public int itemCounter { get; private set; } - - public LazyTestDataSource(TreeViewController treeView, BackendData data) - : base(treeView) - { - m_Backend = data; - FetchData(); - } - - public override void FetchData() - { - // For LazyTreeViewDataSources we just generate the 'm_VisibleRows' items: - itemCounter = 1; - m_RootItem = new FooTreeViewItem(m_Backend.root.id, 0, null, m_Backend.root.name, m_Backend.root); - AddVisibleChildrenRecursive(m_Backend.root, m_RootItem); - - m_Rows = new List(); - GetVisibleItemsRecursive(m_RootItem, m_Rows); - m_NeedRefreshRows = false; - } - - void AddVisibleChildrenRecursive(BackendData.Foo source, TreeViewItem dest) - { - if (IsExpanded(source.id)) - { - if (source.children != null && source.children.Count > 0) - { - dest.children = new List(source.children.Count); - for (int i = 0; i < source.children.Count; ++i) - { - BackendData.Foo s = source.children[i]; - dest.children.Add(new FooTreeViewItem(s.id, dest.depth + 1, dest, s.name, s)); - ++itemCounter; - AddVisibleChildrenRecursive(s, dest.children[i]); - } - } - } - else - { - if (source.hasChildren) - { - dest.children = CreateChildListForCollapsedParent(); // ensure we show the collapse arrow (because we do not fetch data for collapsed items) - } - } - } - - public override bool CanBeParent(TreeViewItem item) - { - return item.hasChildren; - } - - protected override HashSet GetParentsAbove(int id) - { - HashSet parentsAbove = new HashSet(); - BackendData.Foo target = BackendData.FindItemRecursive(m_Backend.root, id); - - while (target != null) - { - if (target.parent != null) - parentsAbove.Add(target.parent.id); - target = target.parent; - } - return parentsAbove; - } - - protected override HashSet GetParentsBelow(int id) - { - HashSet parents = m_Backend.GetParentsBelow(id); - return parents; - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestWindow.cs b/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestWindow.cs deleted file mode 100644 index 969bebc7e3..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestWindow.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor.TreeViewExamples -{ - internal class TreeViewTestWindow : EditorWindow, IHasCustomMenu - { - // Test 1 - private BackendData m_BackendData; - private TreeViewTest m_TreeViewTest; - private TreeViewTest m_TreeViewTest2; - - // Test 2 - private BackendData m_BackendData2; - private TreeViewTestWithCustomHeight m_TreeViewWithCustomHeight; - - private TestType m_TestType = TestType.LargeTreesWithStandardGUI; - - enum TestType - { - LargeTreesWithStandardGUI, - TreeWithCustomItemHeight - } - - public TreeViewTestWindow() - { - titleContent = EditorGUIUtility.TrTextContent("TreeView Test"); - } - - void OnEnable() - { - position = new Rect(100, 100, 600, 600); - } - - void OnGUI() - { - switch (m_TestType) - { - case TestType.LargeTreesWithStandardGUI: - TestLargeTreesWithFixedItemHeightAndPingingAndFraming(); - break; - case TestType.TreeWithCustomItemHeight: - TestTreeWithCustomItemHeights(); - break; - } - } - - void TestTreeWithCustomItemHeights() - { - Rect rect = new Rect(0, 0, position.width, position.height); - if (m_TreeViewWithCustomHeight == null) - { - m_BackendData2 = new BackendData(); - m_BackendData2.GenerateData(300); - - m_TreeViewWithCustomHeight = new TreeViewTestWithCustomHeight(this, m_BackendData2, rect); - } - - m_TreeViewWithCustomHeight.OnGUI(rect); - } - - void TestLargeTreesWithFixedItemHeightAndPingingAndFraming() - { - Rect leftRect = new Rect(0, 0, position.width / 2, position.height); - Rect rightRect = new Rect(position.width / 2, 0, position.width / 2, position.height); - if (m_TreeViewTest == null) - { - m_BackendData = new BackendData(); - m_BackendData.GenerateData(1000000); - - bool lazy = false; - m_TreeViewTest = new TreeViewTest(this, lazy); - m_TreeViewTest.Init(leftRect, m_BackendData); - - lazy = true; - m_TreeViewTest2 = new TreeViewTest(this, lazy); - m_TreeViewTest2.Init(rightRect, m_BackendData); - } - - m_TreeViewTest.OnGUI(leftRect); - m_TreeViewTest2.OnGUI(rightRect); - EditorGUI.DrawRect(new Rect(leftRect.xMax - 1, 0, 2, position.height), new Color(0.4f, 0.4f, 0.4f, 0.8f)); - } - - public virtual void AddItemsToMenu(GenericMenu menu) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Large TreeView"), m_TestType == TestType.LargeTreesWithStandardGUI, () => m_TestType = TestType.LargeTreesWithStandardGUI); - menu.AddItem(EditorGUIUtility.TrTextContent("Custom Item Height TreeView"), m_TestType == TestType.TreeWithCustomItemHeight, () => m_TestType = TestType.TreeWithCustomItemHeight); - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestWithCustomHeight.cs b/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestWithCustomHeight.cs deleted file mode 100644 index 700b25b8d1..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewTests/TreeViewTestWithCustomHeight.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - - -namespace UnityEditor.TreeViewExamples -{ - internal class TreeViewTestWithCustomHeight - { - private BackendData m_BackendData; - private TreeViewController m_TreeView; - - public TreeViewTestWithCustomHeight(EditorWindow editorWindow, BackendData backendData, Rect rect) - { - m_BackendData = backendData; - - var state = new TreeViewState(); - - m_TreeView = new TreeViewController(editorWindow, state); - var gui = new TestGUICustomItemHeights(m_TreeView); - var dragging = new TestDragging(m_TreeView, m_BackendData); - var dataSource = new TestDataSource(m_TreeView, m_BackendData); - dataSource.onVisibleRowsChanged += gui.CalculateRowRects; - m_TreeView.Init(rect, dataSource, gui, dragging); - dataSource.SetExpanded(dataSource.root, true); - } - - public void OnGUI(Rect rect) - { - int keyboardControl = GUIUtility.GetControlID(FocusType.Keyboard, rect); - m_TreeView.OnGUI(rect, keyboardControl); - } - } -} // UnityEditor diff --git a/Editor/Mono/GUI/TreeView/TreeViewUtililty.cs b/Editor/Mono/GUI/TreeView/TreeViewUtililty.cs deleted file mode 100644 index c1925becf4..0000000000 --- a/Editor/Mono/GUI/TreeView/TreeViewUtililty.cs +++ /dev/null @@ -1,223 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor.IMGUI.Controls -{ - internal static class TreeViewUtility - { - internal static void SetParentAndChildrenForItems(IList rows, TreeViewItem root) - { - SetChildParentReferences(rows, root); - } - - // For setting depths values based on children state of the items - internal static void SetDepthValuesForItems(TreeViewItem root) - { - if (root == null) - throw new ArgumentNullException("root", "The root is null"); - - Stack stack = new Stack(); - stack.Push(root); - while (stack.Count > 0) - { - TreeViewItem current = stack.Pop(); - if (current.children != null) - { - foreach (var child in current.children) - { - if (child != null) - { - child.depth = current.depth + 1; - stack.Push(child); - } - } - } - } - } - - internal static List FindItemsInList(IEnumerable itemIDs, IList treeViewItems) - { - return (from x in treeViewItems where itemIDs.Contains(x.id) select x).ToList(); - } - - internal static TreeViewItem FindItemInList(int id, IList treeViewItems) where T : TreeViewItem - { - return treeViewItems.FirstOrDefault(t => t.id == id); - } - - // Assumes full tree - internal static TreeViewItem FindItem(int id, TreeViewItem searchFromThisItem) - { - return FindItemRecursive(id, searchFromThisItem); - } - - static TreeViewItem FindItemRecursive(int id, TreeViewItem item) - { - if (item == null) - return null; - - if (item.id == id) - return item; - - if (!item.hasChildren) - return null; - - foreach (TreeViewItem child in item.children) - { - TreeViewItem result = FindItemRecursive(id, child); - if (result != null) - return result; - } - return null; - } - - // Assumes full tree - internal static HashSet GetParentsAboveItem(TreeViewItem fromItem) - { - if (fromItem == null) - throw new ArgumentNullException("fromItem"); - - var hashSet = new HashSet(); - TreeViewItem parent = fromItem.parent; - while (parent != null) - { - hashSet.Add(parent.id); - parent = parent.parent; - } - return hashSet; - } - - // Assumes full tree - internal static HashSet GetParentsBelowItem(TreeViewItem fromItem) - { - if (fromItem == null) - throw new ArgumentNullException("fromItem"); - - Stack stack = new Stack(); - stack.Push(fromItem); - - HashSet parents = new HashSet(); - while (stack.Count > 0) - { - TreeViewItem current = stack.Pop(); - if (current.hasChildren) - { - parents.Add(current.id); - if (LazyTreeViewDataSource.IsChildListForACollapsedParent(current.children)) - throw new InvalidOperationException("Invalid tree for finding descendants: Ensure a complete tree when using this utillity method."); - - foreach (var foo in current.children) - { - stack.Push(foo); - } - } - } - return parents; - } - - internal static void DebugPrintToEditorLogRecursive(TreeViewItem item) - { - if (item == null) - return; - System.Console.WriteLine(new System.String(' ', item.depth * 3) + item.displayName); - - if (!item.hasChildren) - return; - - foreach (TreeViewItem child in item.children) - { - DebugPrintToEditorLogRecursive(child); - } - } - - // Setup child and parent references based on the depth of the tree view items in 'visibleItems' - internal static void SetChildParentReferences(IList visibleItems, TreeViewItem root) - { - for (int i = 0; i < visibleItems.Count; i++) - visibleItems[i].parent = null; - - // Set child and parent references using depth info - int rootChildCount = 0; - for (int i = 0; i < visibleItems.Count; i++) - { - SetChildParentReferences(i, visibleItems); - - if (visibleItems[i].parent == null) - rootChildCount++; - } - - // Ensure items without a parent gets 'root' as parent - if (rootChildCount > 0) - { - var rootChildren = new List(rootChildCount); - for (int i = 0; i < visibleItems.Count; i++) - { - if (visibleItems[i].parent == null) - { - rootChildren.Add(visibleItems[i]); - visibleItems[i].parent = root; - } - } - root.children = rootChildren; - } - else - root.children = new List(); - } - - static void SetChildren(TreeViewItem item, List newChildList) - { - // Do not touch children if we have a LazyParent and did not find any children == keep lazy children - if (LazyTreeViewDataSource.IsChildListForACollapsedParent(item.children) && newChildList == null) - return; - - item.children = newChildList; - } - - static void SetChildParentReferences(int parentIndex, IList visibleItems) - { - TreeViewItem parent = visibleItems[parentIndex]; - bool alreadyHasValidChildren = parent.children != null && parent.children.Count > 0 && parent.children[0] != null; - if (alreadyHasValidChildren) - return; - - int parentDepth = parent.depth; - int childCount = 0; - - // Count children based depth value, we are looking at children until it's the same depth as this object - for (int i = parentIndex + 1; i < visibleItems.Count; i++) - { - if (visibleItems[i].depth == parentDepth + 1) - childCount++; - if (visibleItems[i].depth <= parentDepth) - break; - } - - // Fill child array - List childList = null; - if (childCount != 0) - { - childList = new List(childCount); // Allocate once - childCount = 0; - for (int i = parentIndex + 1; i < visibleItems.Count; i++) - { - if (visibleItems[i].depth == parentDepth + 1) - { - visibleItems[i].parent = parent; - childList.Add(visibleItems[i]); - childCount++; - } - - if (visibleItems[i].depth <= parentDepth) - break; - } - } - - SetChildren(parent, childList); - } - } -} diff --git a/Editor/Mono/GUI/TypeSelectionList.cs b/Editor/Mono/GUI/TypeSelectionList.cs deleted file mode 100644 index 1f7384f211..0000000000 --- a/Editor/Mono/GUI/TypeSelectionList.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System; -using System.Collections.Generic; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - class TypeSelectionList - { - private List m_TypeSelections; - public List typeSelections { get { return m_TypeSelections; } } - - public TypeSelectionList(Object[] objects) - { - // Create dictionary of lists of objects indexed by their type. - Dictionary> types = new Dictionary>(); - foreach (Object o in objects) - { - string typeName = ObjectNames.GetTypeName(o); - if (!types.ContainsKey(typeName)) - types[typeName] = new List(); - types[typeName].Add(o); - } - - // Create and store a TypeSelection per type. - m_TypeSelections = new List(); - foreach (KeyValuePair> kvp in types) - m_TypeSelections.Add(new TypeSelection(kvp.Key, kvp.Value.ToArray())); - - // Sort the TypeSelections - m_TypeSelections.Sort(); - } - } - - class TypeSelection : IComparable - { - public GUIContent label; - public Object[] objects; - - public TypeSelection(string typeName, Object[] objects) - { - System.Diagnostics.Debug.Assert(objects != null || objects.Length >= 1); - this.objects = objects; - label = new GUIContent(objects.Length + " " + ObjectNames.NicifyVariableName(typeName) + (objects.Length > 1 ? "s" : "")); - label.image = AssetPreview.GetMiniTypeThumbnail(objects[0]); - } - - public int CompareTo(object o) - { - TypeSelection other = (TypeSelection)o; - - // Sort by amount of objects - if (other.objects.Length != objects.Length) - return other.objects.Length.CompareTo(objects.Length); - - // Sort alphabetically - return label.text.CompareTo(other.label.text); - } - } -} diff --git a/Editor/Mono/GUI/VUMeter.cs b/Editor/Mono/GUI/VUMeter.cs deleted file mode 100644 index b4142d24d0..0000000000 --- a/Editor/Mono/GUI/VUMeter.cs +++ /dev/null @@ -1,153 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class EditorGUI - { - internal class VUMeter - { - static Texture2D s_VerticalVUTexture; - static Texture2D s_HorizontalVUTexture; - const float VU_SPLIT = 0.9f; - - public struct SmoothingData - { - public float lastValue; - public float peakValue; - public float peakValueTime; - } - - public static Texture2D verticalVUTexture - { - get - { - if (s_VerticalVUTexture == null) - s_VerticalVUTexture = EditorGUIUtility.LoadIcon("VUMeterTextureVertical"); - return s_VerticalVUTexture; - } - } - - public static Texture2D horizontalVUTexture - { - get - { - if (s_HorizontalVUTexture == null) - s_HorizontalVUTexture = EditorGUIUtility.LoadIcon("VUMeterTextureHorizontal"); - return s_HorizontalVUTexture; - } - } - - public static void HorizontalMeter(Rect position, float value, float peak, Texture2D foregroundTexture, Color peakColor) - { - if (Event.current.type != EventType.Repaint) - return; - - Color temp = GUI.color; - - // Draw background - EditorStyles.progressBarBack.Draw(position, false, false, false, false); - - // Draw foreground - GUI.color = new Color(1f, 1f, 1f, GUI.enabled ? 1 : 0.5f); - float width = position.width * value - 2; - if (width < 2) - width = 2; - Rect newRect = new Rect(position.x + 1, position.y + 1, width, position.height - 2); - Rect uvRect = new Rect(0, 0, value, 1); - GUI.DrawTextureWithTexCoords(newRect, foregroundTexture, uvRect); - - // Draw peak indicator - GUI.color = peakColor; - float peakpos = position.width * peak - 2; - if (peakpos < 2) - peakpos = 2; - newRect = new Rect(position.x + peakpos, position.y + 1, 1, position.height - 2); - GUI.DrawTexture(newRect, EditorGUIUtility.whiteTexture, ScaleMode.StretchToFill); - - // Reset color - GUI.color = temp; - } - - public static void VerticalMeter(Rect position, float value, float peak, Texture2D foregroundTexture, Color peakColor) - { - if (Event.current.type != EventType.Repaint) - return; - - Color temp = GUI.color; - - // Draw background - EditorStyles.progressBarBack.Draw(position, false, false, false, false); - - // Draw foreground - GUI.color = new Color(1f, 1f, 1f, GUI.enabled ? 1 : 0.5f); - float height = (position.height - 2) * value; - if (height < 2) - height = 2; - Rect newRect = new Rect(position.x + 1, (position.y + position.height - 1) - height, position.width - 2, height); - Rect uvRect = new Rect(0, 0, 1, value); - GUI.DrawTextureWithTexCoords(newRect, foregroundTexture, uvRect); - - // Draw peak indicator - GUI.color = peakColor; - float peakpos = (position.height - 2) * peak; - if (peakpos < 2) - peakpos = 2; - newRect = new Rect(position.x + 1, (position.y + position.height - 1) - peakpos, position.width - 2, 1); - GUI.DrawTexture(newRect, EditorGUIUtility.whiteTexture, ScaleMode.StretchToFill); - - // Reset color - GUI.color = temp; - } - - // Auto smoothing version - public static void HorizontalMeter(Rect position, float value, ref SmoothingData data, Texture2D foregroundTexture, Color peakColor) - { - if (Event.current.type != EventType.Repaint) - return; - - float renderValue, renderPeak; - SmoothVUMeterData(ref value, ref data, out renderValue, out renderPeak); - HorizontalMeter(position, renderValue, renderPeak, foregroundTexture, peakColor); - } - - // Auto smoothing version - public static void VerticalMeter(Rect position, float value, ref SmoothingData data, Texture2D foregroundTexture, Color peakColor) - { - if (Event.current.type != EventType.Repaint) - return; - - float renderValue, renderPeak; - SmoothVUMeterData(ref value, ref data, out renderValue, out renderPeak); - VerticalMeter(position, renderValue, renderPeak, foregroundTexture, peakColor); - } - - static void SmoothVUMeterData(ref float value, ref SmoothingData data, out float renderValue, out float renderPeak) - { - if (value <= data.lastValue) - { - value = Mathf.Lerp(data.lastValue, value, Time.smoothDeltaTime * 7.0f); - } - else - { - value = Mathf.Lerp(value, data.lastValue, Time.smoothDeltaTime * 2.0f); - data.peakValue = value; - data.peakValueTime = Time.realtimeSinceStartup; - } - - if (value > 1.0f / VU_SPLIT) - value = 1.0f / VU_SPLIT; - if (data.peakValue > 1.0f / VU_SPLIT) - data.peakValue = 1.0f / VU_SPLIT; - - renderValue = value * VU_SPLIT; - renderPeak = data.peakValue * VU_SPLIT; - - data.lastValue = value; - } - } // VUMeter - } // UnityGUI -} // UnityEditor diff --git a/Editor/Mono/GUI/VerticalGrid.cs b/Editor/Mono/GUI/VerticalGrid.cs deleted file mode 100644 index a0c37349aa..0000000000 --- a/Editor/Mono/GUI/VerticalGrid.cs +++ /dev/null @@ -1,270 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class VerticalGrid - { - int m_Columns = 1; - int m_Rows; - float m_Height; - float m_HorizontalSpacing; - - public int columns { get {return m_Columns; } } - public int rows { get {return m_Rows; } } - public float height { get {return m_Height; } } - public float horizontalSpacing { get {return m_HorizontalSpacing; } } - - // Adjust grid values - public float fixedWidth { get; set; } - public Vector2 itemSize { get; set; } - public float verticalSpacing { get; set; } // spacing between each row of items - public float minHorizontalSpacing { get; set; } // minimum spacing between each column in grid - public float topMargin { get; set; } - public float bottomMargin { get; set; } - public float rightMargin { get; set; } - public float leftMargin { get; set; } - public float fixedHorizontalSpacing {get; set; } - public bool useFixedHorizontalSpacing {get; set; } - - // Call after setting parameters above and before using CalcRect - public void InitNumRowsAndColumns(int itemCount, int maxNumRows) - { - if (useFixedHorizontalSpacing) - { - // Set columns (with an excess of 1 fixedHorizontalSpacing) - m_Columns = CalcColumns(); - - // Set horizontal spacing - m_HorizontalSpacing = fixedHorizontalSpacing; - - // Set rows - m_Rows = Mathf.Min(maxNumRows, CalcRows(itemCount)); - - // Set height - m_Height = m_Rows * (itemSize.y + verticalSpacing) - verticalSpacing + topMargin + bottomMargin; - } - else // center columns - { - // Set columns (with an excess of 1 minHorizontalSpacing) - m_Columns = CalcColumns(); - - // Set horizontal spacing - m_HorizontalSpacing = Mathf.Max(0f, (fixedWidth - (m_Columns * itemSize.x + leftMargin + rightMargin)) / (m_Columns)); - - // Set rows - m_Rows = Mathf.Min(maxNumRows, CalcRows(itemCount)); - - if (m_Rows == 1) - m_HorizontalSpacing = minHorizontalSpacing; - - // Set height - m_Height = m_Rows * (itemSize.y + verticalSpacing) - verticalSpacing + topMargin + bottomMargin; - } - } - - public int CalcColumns() - { - float horizontalSpacing = useFixedHorizontalSpacing ? fixedHorizontalSpacing : minHorizontalSpacing; - int cols = (int)Mathf.Floor((fixedWidth - leftMargin - rightMargin) / (itemSize.x + horizontalSpacing)); - cols = Mathf.Max(cols, 1); - return cols; - } - - public int CalcRows(int itemCount) - { - int t = (int)Mathf.Ceil(itemCount / (float)CalcColumns()); - if (t < 0) - return int.MaxValue; - return t; - } - - public Rect CalcRect(int itemIdx, float yOffset) - { - float row = Mathf.Floor(itemIdx / columns); - float column = itemIdx - row * columns; - - if (useFixedHorizontalSpacing) - { - return new Rect(leftMargin + column * (itemSize.x + fixedHorizontalSpacing), - row * (itemSize.y + verticalSpacing) + topMargin + yOffset, - itemSize.x, - itemSize.y); - } - else - { - return new Rect(leftMargin + horizontalSpacing * 0.5f + column * (itemSize.x + horizontalSpacing), - row * (itemSize.y + verticalSpacing) + topMargin + yOffset, - itemSize.x, - itemSize.y); - } - } - - public int GetMaxVisibleItems(float height) - { - int visibleRows = (int)Mathf.Ceil((height - topMargin - bottomMargin) / (itemSize.y + verticalSpacing)); - return visibleRows * columns; - } - - public bool IsVisibleInScrollView(float scrollViewHeight, float scrollPos, float gridStartY, int maxIndex, out int startIndex, out int endIndex) - { - startIndex = endIndex = 0; - - // In grid coordinates - - float scrollViewStart = scrollPos; - float scrollViewEnd = scrollPos + scrollViewHeight; - - float offsetY = gridStartY + topMargin; - - // Entirely below view - if (offsetY > scrollViewEnd) - return false; - - // Entirely above view - if (offsetY + height < scrollViewStart) - return false; - - float itemHeightAndSpacing = itemSize.y + verticalSpacing; - - // startRow can be negative if grid is starting in the middle of the view - int startRow = Mathf.FloorToInt((scrollViewStart - offsetY) / itemHeightAndSpacing); - startIndex = startRow * columns; - startIndex = Mathf.Clamp(startIndex, 0, maxIndex); - - // endRow can be negative if grid is starting in the middle of the view - int endRow = Mathf.FloorToInt((scrollViewEnd - offsetY) / itemHeightAndSpacing); - endIndex = (endRow + 1) * columns - 1; - endIndex = Mathf.Clamp(endIndex, 0, maxIndex); - - return true; - } - - public override string ToString() - { - return string.Format("VerticalGrid: rows {0}, columns {1}, fixedWidth {2}, itemSize {3}", rows, columns, fixedWidth, itemSize); - } - } - - - internal class VerticalGridWithSplitter - { - int m_Columns = 1; - int m_Rows; - float m_Height; - float m_HorizontalSpacing; - - public int columns { get {return m_Columns; } } - public int rows { get {return m_Rows; } } - public float height { get {return m_Height; } } - public float horizontalSpacing { get {return m_HorizontalSpacing; } } - - // Adjust grid values - public float fixedWidth { get; set; } - public Vector2 itemSize { get; set; } - public float verticalSpacing { get; set; } // spacing between each row of items - public float minHorizontalSpacing { get; set; } // minimum spacing between each column in grid - public float topMargin { get; set; } - public float bottomMargin { get; set; } - public float rightMargin { get; set; } - public float leftMargin { get; set; } - - // Call after setting parameters above and before using CalcRect - public void InitNumRowsAndColumns(int itemCount, int maxNumRows) - { - // Set columns (with an excess of 1 minHorizontalSpacing) - m_Columns = (int)Mathf.Floor((fixedWidth - leftMargin - rightMargin) / (itemSize.x + minHorizontalSpacing)); - m_Columns = Mathf.Max(m_Columns, 1); - - // Set horizontal spacing - m_HorizontalSpacing = 0f; - if (m_Columns > 1) - m_HorizontalSpacing = (fixedWidth - (m_Columns * itemSize.x + leftMargin + rightMargin)) / (m_Columns - 1); - - // Set rows - m_Rows = Mathf.Min(maxNumRows, (int)Mathf.Ceil(itemCount / (float)m_Columns)); - - // Set height - m_Height = m_Rows * (itemSize.y + verticalSpacing) - verticalSpacing + topMargin + bottomMargin; - } - - public Rect CalcRect(int itemIdx, float yOffset) - { - float row = Mathf.Floor(itemIdx / columns); - float column = itemIdx - row * columns; - - return new Rect(column * (itemSize.x + horizontalSpacing) + leftMargin, - row * (itemSize.y + verticalSpacing) + topMargin + yOffset, - itemSize.x, - itemSize.y); - } - - public int GetMaxVisibleItems(float height) - { - int visibleRows = (int)Mathf.Ceil((height - topMargin - bottomMargin) / (itemSize.y + verticalSpacing)); - return visibleRows * columns; - } - - int m_SplitAfterRow; - float m_CurrentSplitHeight; - float m_LastSplitUpdate; - float m_TargetSplitHeight; - - public void ResetSplit() - { - m_SplitAfterRow = -1; - m_CurrentSplitHeight = 0f; - m_LastSplitUpdate = -1f; - m_TargetSplitHeight = 0f; - } - - public void OpenSplit(int splitAfterRowIndex, int numItems) - { - int numRows = (int)Mathf.Ceil(numItems / (float)m_Columns); - float splitHeight = numRows * (itemSize.y + verticalSpacing) - verticalSpacing + topMargin + bottomMargin; - m_SplitAfterRow = splitAfterRowIndex; - m_TargetSplitHeight = splitHeight; - m_LastSplitUpdate = Time.realtimeSinceStartup; - } - - // Returns Rect of split content starting from index 0 - public Rect CalcSplitRect(int splitIndex, float yOffset) - { - Rect rect = new Rect(0, 0, 0, 0); - - return rect; - } - - public void CloseSplit() - { - m_TargetSplitHeight = 0f; - } - - // Returns true if animating (client should ensure to repaint in this case) - public bool UpdateSplitAnimationOnGUI() - { - if (m_SplitAfterRow != -1) - { - float delta = Time.realtimeSinceStartup - m_LastSplitUpdate; - m_CurrentSplitHeight = delta * m_TargetSplitHeight; - - m_LastSplitUpdate = Time.realtimeSinceStartup; - - // Animate - if (m_CurrentSplitHeight != m_TargetSplitHeight && Event.current.type == EventType.Repaint) - { - m_CurrentSplitHeight = Mathf.MoveTowards(m_CurrentSplitHeight, m_TargetSplitHeight, 0.03f); - if (m_CurrentSplitHeight == 0 && m_TargetSplitHeight == 0) - { - ResetSplit(); - } - return true; - } - } - return false; - } - } -} diff --git a/Editor/Mono/GUI/WindowLayout.cs b/Editor/Mono/GUI/WindowLayout.cs deleted file mode 100644 index 48bded250c..0000000000 --- a/Editor/Mono/GUI/WindowLayout.cs +++ /dev/null @@ -1,998 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.IO; -using UnityEditorInternal; -using UnityEditor.VersionControl; -using UnityEditor.Connect; -using UnityEditor.Web; -using UnityEngine; - -using UnityObject = UnityEngine.Object; - -namespace UnityEditor -{ - internal class WindowLayout - { - static internal PrefKey s_MaximizeKey = new PrefKey("Window/Maximize View", "# "); - - private const string kMaximizeRestoreFile = "CurrentMaximizeLayout.dwlt"; - - /// Used by EditorWindowController to display the window - static void ShowWindowImmediate(EditorWindow win) - { - win.Show(true); - } - - static internal EditorWindow FindEditorWindowOfType(System.Type type) - { - UnityObject[] obj = Resources.FindObjectsOfTypeAll(type); - if (obj.Length > 0) - return obj[0] as EditorWindow; - else - return null; - } - - static IEnumerable FindEditorWindowsOfType() where T : class - { - foreach (UnityObject obj in Resources.FindObjectsOfTypeAll(typeof(T))) - if (obj is T) - yield return obj as T; - } - - static internal void CheckWindowConsistency() - { - UnityObject[] wins = Resources.FindObjectsOfTypeAll(typeof(EditorWindow)); - - foreach (EditorWindow win in wins) - { - if (win.m_Parent == null) - { - Debug.LogError("Invalid editor window " + win.GetType()); - } - } - } - - static internal EditorWindow TryGetLastFocusedWindowInSameDock() - { - // Get type of window that was docked together with game view and was focused before play mode - System.Type type = null; - string windowTypeName = WindowFocusState.instance.m_LastWindowTypeInSameDock; - if (windowTypeName != "") - type = System.Type.GetType(windowTypeName); - - // Also get the GameView - GameView gameView = FindEditorWindowOfType(typeof(GameView)) as GameView; - if (type != null && gameView && gameView.m_Parent != null && gameView.m_Parent is DockArea) - { - // Get all windows of that type - object[] potentials = Resources.FindObjectsOfTypeAll(type); - - DockArea dock = gameView.m_Parent as DockArea; - - // Find the one that is actually docked together with the GameView - for (int i = 0; i < potentials.Length; i++) - { - EditorWindow window = potentials[i] as EditorWindow; - if (window && window.m_Parent == dock) - return window; - } - } - - return null; - } - - static internal void SaveCurrentFocusedWindowInSameDock(EditorWindow windowToBeFocused) - { - if (windowToBeFocused.m_Parent != null && windowToBeFocused.m_Parent is DockArea) - { - DockArea dock = windowToBeFocused.m_Parent as DockArea; - // Get currently focused window/tab in that dock - EditorWindow actualView = dock.actualView; - if (actualView) - WindowFocusState.instance.m_LastWindowTypeInSameDock = actualView.GetType().ToString(); - } - } - - static internal void FindFirstGameViewAndSetToMaximizeOnPlay() - { - GameView gameView = (GameView)FindEditorWindowOfType(typeof(GameView)); - if (gameView) - gameView.maximizeOnPlay = true; - } - - static internal EditorWindow TryFocusAppropriateWindow(bool enteringPlaymode) - { - if (enteringPlaymode) - { - GameView gameView = (GameView)FindEditorWindowOfType(typeof(GameView)); - if (gameView) - { - SaveCurrentFocusedWindowInSameDock(gameView); - gameView.Focus(); - } - return gameView; - } - else - { - // If we can retrieve what window type was active when we went into play mode, - // go back to focus a window of that type. - EditorWindow window = TryGetLastFocusedWindowInSameDock(); - if (window) - window.ShowTab(); - return window; - } - } - - static internal EditorWindow GetMaximizedWindow() - { - UnityObject[] maximized = Resources.FindObjectsOfTypeAll(typeof(MaximizedHostView)); - if (maximized.Length != 0) - { - MaximizedHostView maximizedView = maximized[0] as MaximizedHostView; - if (maximizedView.actualView) - return maximizedView.actualView; - } - return null; - } - - static internal EditorWindow ShowAppropriateViewOnEnterExitPlaymode(bool entering) - { - // Prevent trying to go into the same state as we're already in, as it wil break things - if (WindowFocusState.instance.m_CurrentlyInPlayMode == entering) - return null; - - WindowFocusState.instance.m_CurrentlyInPlayMode = entering; - - EditorWindow window = null; - - EditorWindow maximized = GetMaximizedWindow(); - - if (entering) - { - WindowFocusState.instance.m_WasMaximizedBeforePlay = (maximized != null); - // If a view is already maximized before entering play mode, - // just keep that maximized view, no matter if it's the game view or some other. - // Trust that user has a good reason (desire by Ethan etc.) - if (maximized != null) - return maximized; - } - else - { - // If a view was already maximized before entering play mode, - // then it was kept when switching to play mode, and can simply still be kept when exiting - if (WindowFocusState.instance.m_WasMaximizedBeforePlay) - return maximized; - } - - // Unmaximize if maximized - if (maximized) - Unmaximize(maximized); - - // Try finding and focusing appropriate window/tab - window = TryFocusAppropriateWindow(entering); - if (window) - return window; - - // If we are entering Play more and no Game View was found, create one - if (entering) - { - // Try to create and focus a Game View tab docked together with the Scene View tab - EditorWindow sceneView = FindEditorWindowOfType(typeof(SceneView)); - GameView gameView; - if (sceneView && sceneView.m_Parent is DockArea) - { - DockArea dock = sceneView.m_Parent as DockArea; - if (dock) - { - WindowFocusState.instance.m_LastWindowTypeInSameDock = sceneView.GetType().ToString(); - gameView = ScriptableObject.CreateInstance(); - dock.AddTab(gameView); - return gameView; - } - } - - // If no Scene View was found at all, just create a floating Game View - gameView = ScriptableObject.CreateInstance(); - gameView.Show(true); - gameView.Focus(); - - return gameView; - } - - return window; - } - - static internal bool IsMaximized(EditorWindow window) - { - return window.m_Parent is MaximizedHostView; - } - - static internal void MaximizeKeyHandler() - { - if ((s_MaximizeKey.activated || Event.current.type == EditorGUIUtility.magnifyGestureEventType) && GUIUtility.hotControl == 0) - { - EventType type = Event.current.type; - Event.current.Use(); - EditorWindow mouseOver = EditorWindow.mouseOverWindow; - if (mouseOver) - { - if (!(mouseOver is PreviewWindow)) - { - if (type == EditorGUIUtility.magnifyGestureEventType) - { - if (Event.current.delta.x < -0.05) - { - if (IsMaximized(mouseOver)) - Unmaximize(mouseOver); - } - else if (Event.current.delta.x > 0.05) - { - if (!IsMaximized(mouseOver)) - Maximize(mouseOver); - } - } - else - { - if (IsMaximized(mouseOver)) - Unmaximize(mouseOver); - else - Maximize(mouseOver); - } - } - } - } - } - - public static void Unmaximize(EditorWindow win) - { - HostView maximizedHostView = win.m_Parent; - if (maximizedHostView == null) - { - Debug.LogError("Host view was not found"); - RevertFactorySettings(); - return; - } - - UnityObject[] newWindows = InternalEditorUtility.LoadSerializedFileAndForget(Path.Combine(layoutsProjectPath, kMaximizeRestoreFile)); - - if (newWindows.Length < 2) - { - Debug.Log("Maximized serialized file backup not found"); - RevertFactorySettings(); - return; - } - - SplitView oldRoot = newWindows[0] as SplitView; - EditorWindow oldWindow = newWindows[1] as EditorWindow; - - if (oldRoot == null) - { - Debug.Log("Maximization failed because the root split view was not found"); - RevertFactorySettings(); - return; - } - - ContainerWindow parentWindow = win.m_Parent.window; - if (parentWindow == null) - { - Debug.Log("Maximization failed because the root split view has no container window"); - RevertFactorySettings(); - return; - } - - try - { - ContainerWindow.SetFreezeDisplay(true); - - // Put the loaded SplitView where the MaximizedHostView was - if (maximizedHostView.parent) - { - int i = maximizedHostView.parent.IndexOfChild(maximizedHostView); - Rect r = maximizedHostView.position; - View parent = maximizedHostView.parent; - parent.RemoveChild(i); - parent.AddChild(oldRoot, i); - oldRoot.position = r; - - // Move the Editor Window to the right spot in the - DockArea newDockArea = oldWindow.m_Parent as DockArea; - - int oldDockAreaIndex = newDockArea.m_Panes.IndexOf(oldWindow); - - maximizedHostView.actualView = null; - win.m_Parent = null; - newDockArea.AddTab(oldDockAreaIndex, win); - newDockArea.RemoveTab(oldWindow); - UnityObject.DestroyImmediate(oldWindow); - - foreach (UnityObject o in newWindows) - { - EditorWindow curWin = o as EditorWindow; - if (curWin != null) - curWin.MakeParentsSettingsMatchMe(); - } - - parent.Initialize(parent.window); - //If parent window had to be resized, call this to make sure new size gets propagated - parent.position = parent.position; - oldRoot.Reflow(); - } - else - { - throw new System.Exception(); - } - - // Kill the maximizedMainView - UnityObject.DestroyImmediate(maximizedHostView); - - win.Focus(); - - parentWindow.DisplayAllViews(); - win.m_Parent.MakeVistaDWMHappyDance(); - } - catch (System.Exception ex) - { - Debug.Log("Maximization failed: " + ex); - RevertFactorySettings(); - } - - try - { - // Weird bug on AMD graphic cards under OSX Lion: Sometimes when unmaximizing we get stray white rectangles. - // work around that by issueing an extra repaint (case 438764) - if (Application.platform == RuntimePlatform.OSXEditor && SystemInfo.operatingSystem.Contains("10.7") && SystemInfo.graphicsDeviceVendor.Contains("ATI")) - { - foreach (GUIView v in Resources.FindObjectsOfTypeAll(typeof(GUIView))) - v.Repaint(); - } - } - finally - { - ContainerWindow.SetFreezeDisplay(false); - } - } - - public static void AddSplitViewAndChildrenRecurse(View splitview, ArrayList list) - { - list.Add(splitview); - DockArea dock = splitview as DockArea; - if (dock != null) - list.AddRange(dock.m_Panes); - - HostView host = splitview as DockArea; - if (host != null) - list.Add(dock.actualView); - - foreach (View child in splitview.children) - { - AddSplitViewAndChildrenRecurse(child, list); - } - } - - public static void SaveSplitViewAndChildren(View splitview, EditorWindow win, string path) - { - ArrayList all = new ArrayList(); - - AddSplitViewAndChildrenRecurse(splitview, all); - all.Remove(splitview); - all.Remove(win); - all.Insert(0, splitview); - all.Insert(1, win); - - InternalEditorUtility.SaveToSerializedFileAndForget(all.ToArray(typeof(UnityObject)) as UnityObject[], path, true); - } - - public static void Maximize(EditorWindow win) - { - bool maximizePending = MaximizePrepare(win); - if (maximizePending) - MaximizePresent(win); - } - - public static bool MaximizePrepare(EditorWindow win) - { - // Find Root SplitView - View itor = win.m_Parent.parent; - View rootSplit = itor; - while (itor != null && itor is SplitView) - { - rootSplit = itor; - itor = itor.parent; - } - - // Make sure it has a dockarea - DockArea dockArea = win.m_Parent as DockArea; - if (dockArea == null) - return false; - - if (itor == null) - return false; - - var mainView = rootSplit.parent as MainView; - if (mainView == null) - return false; - - ContainerWindow parentWindow = win.m_Parent.window; - if (parentWindow == null) - return false; - - int oldDockIndex = dockArea.m_Panes.IndexOf(win); - if (oldDockIndex == -1) - return false; - - dockArea.selected = oldDockIndex; - - // Save current state to disk - SaveSplitViewAndChildren(rootSplit, win, Path.Combine(layoutsProjectPath, kMaximizeRestoreFile)); - - // Remove the window from the HostView now in order to invoke OnBecameInvisible before OnBecameVisible - dockArea.actualView = null; - - dockArea.m_Panes[oldDockIndex] = null; - - MaximizedHostView maximizedHostView = ScriptableObject.CreateInstance(); - - int i = itor.IndexOfChild(rootSplit); - Rect p = rootSplit.position; - itor.RemoveChild(rootSplit); - itor.AddChild(maximizedHostView, i); - - maximizedHostView.actualView = win; - maximizedHostView.position = p; // Must be set after actualView so that value is propagated - - UnityObject.DestroyImmediate(rootSplit, true); - - return true; - } - - public static void MaximizePresent(EditorWindow win) - { - ContainerWindow.SetFreezeDisplay(true); - - win.Focus(); - - CheckWindowConsistency(); - - ContainerWindow parentWindow = win.m_Parent.window; - parentWindow.DisplayAllViews(); - - win.m_Parent.MakeVistaDWMHappyDance(); - - ContainerWindow.SetFreezeDisplay(false); - } - - public static bool LoadWindowLayout(string path, bool newProjectLayoutWasCreated) - { - Rect mainWindowPosition = new Rect(); - UnityObject[] containers = Resources.FindObjectsOfTypeAll(typeof(ContainerWindow)); - foreach (ContainerWindow window in containers) - { - if (window.showMode == ShowMode.MainWindow) - { - mainWindowPosition = window.position; - } - } - - bool layoutLoadingIssue = false; - - // Load new windows and show them - try - { - ContainerWindow.SetFreezeDisplay(true); - - CloseWindows(); - - // Load data - UnityObject[] loadedWindows = InternalEditorUtility.LoadSerializedFileAndForget(path); - - if (loadedWindows == null || loadedWindows.Length == 0) - { - throw new ArgumentException("Window layout at '" + path + "' could not be loaded."); - } - - List newWindows = new List(); - - // At this point, unparented editor windows are neither desired nor desirable. - // This can be caused by (legacy) serialization of FallbackEditorWindows or - // other serialization hiccups (note that unparented editor windows should not exist in theory). - // Same goes for empty DockAreas (no panes). Leave them behind. - for (int i = 0; i < loadedWindows.Length; i++) - { - UnityObject o = loadedWindows[i]; - - EditorWindow editorWin = o as EditorWindow; - if (editorWin != null) - { - if (editorWin.m_Parent == null) - { - UnityObject.DestroyImmediate(editorWin, true); - Console.WriteLine("LoadWindowLayout: Removed unparented EditorWindow while reading window layout: window #" + i + ", type=" + - o.GetType().ToString() + ", instanceID=" + o.GetInstanceID()); - layoutLoadingIssue = true; - continue; - } - } - else - { - DockArea dockArea = o as DockArea; - if (dockArea != null && dockArea.m_Panes.Count == 0) - { - dockArea.Close(null); - Console.WriteLine("LoadWindowLayout: Removed empty DockArea while reading window layout: window #" + i + ", instanceID=" + - o.GetInstanceID()); - layoutLoadingIssue = true; - continue; - } - } - - newWindows.Add(o); - } - - ContainerWindow mainWindowToSetSize = null; - ContainerWindow mainWindow = null; - - for (int i = 0; i < newWindows.Count; i++) - { - ContainerWindow cur = newWindows[i] as ContainerWindow; - if (cur != null && cur.showMode == ShowMode.MainWindow) - { - mainWindow = cur; - if (mainWindowPosition.width != 0.0) - { - mainWindowToSetSize = cur; - mainWindowToSetSize.position = mainWindowPosition; - } - } - } - - for (int i = 0; i < newWindows.Count; i++) - { - UnityObject o = newWindows[i]; - if (o == null) - { - Console.WriteLine("LoadWindowLayout: Error while reading window layout: window #" + i + " is null"); - layoutLoadingIssue = true; - // Keep going - } - else if (o.GetType() == null) - { - Console.WriteLine("LoadWindowLayout: Error while reading window layout: window #" + i + " type is null, instanceID=" + o.GetInstanceID()); - layoutLoadingIssue = true; - // Keep going - } - else - { - if (newProjectLayoutWasCreated) - { - MethodInfo method = o.GetType().GetMethod("OnNewProjectLayoutWasCreated", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - if (method != null) - method.Invoke(o, null); - } - } - } - - if (mainWindowToSetSize) - { - mainWindowToSetSize.position = mainWindowPosition; - mainWindowToSetSize.OnResize(); - } - - // Always show main window before other windows. So that other windows can - // get their parent/owner. - if (mainWindow == null) - { - Debug.LogError("Error while reading window layout: no main window found"); - throw new System.Exception(); - } - mainWindow.Show(mainWindow.showMode, true, true); - - // Show other windows - for (int i = 0; i < newWindows.Count; i++) - { - EditorWindow win = newWindows[i] as EditorWindow; - if (win) - win.minSize = win.minSize; // Causes minSize to be propagated upwards to parents! - - ContainerWindow containerWindow = newWindows[i] as ContainerWindow; - if (containerWindow && containerWindow != mainWindow) - containerWindow.Show(containerWindow.showMode, true, true); - } - - // Unmaximize maximized GameView if maximize on play is enabled - GameView gameView = GetMaximizedWindow() as GameView; - if (gameView != null && gameView.maximizeOnPlay) - Unmaximize(gameView); - - // For new projects, show services window if and only if online and logged in - if (newProjectLayoutWasCreated) - { - if (UnityConnect.instance.online && UnityConnect.instance.loggedIn && UnityConnect.instance.shouldShowServicesWindow) - { - UnityConnectServiceCollection.instance.ShowService(HubAccess.kServiceName, true, "new_project_created"); - } - else - { - UnityConnectServiceCollection.instance.CloseServices(); - } - } - } - catch (System.Exception ex) - { - Debug.LogError("Failed to load window layout: " + ex); - - int option = 0; - - - UnityObject[] containerWindows = Resources.FindObjectsOfTypeAll(typeof(ContainerWindow)); - - // Only show dialog if an actual window is present. If not, revert to default immediately - if (!Application.isTestRun && containerWindows.Length > 0) - option = EditorUtility.DisplayDialogComplex("Failed to load window layout", "This can happen if layout contains custom windows and there are compile errors in the project.", "Load Default Layout", "Quit", "Revert Factory Settings"); - - switch (option) - { - case 0: - LoadDefaultLayout(); - break; - case 1: - EditorApplication.Exit(0); - break; - case 2: - RevertFactorySettings(); - break; - } - - return false; - } - finally - { - ContainerWindow.SetFreezeDisplay(false); - - if (Path.GetExtension(path) == ".wlt") - Toolbar.lastLoadedLayoutName = Path.GetFileNameWithoutExtension(path); - else - Toolbar.lastLoadedLayoutName = null; - } - - if (layoutLoadingIssue) - Debug.Log("The editor layout could not be fully loaded, this can happen when the layout contains EditorWindows not available in this project"); - - return true; - } - - private static void LoadDefaultLayout() - { - InternalEditorUtility.LoadDefaultLayout(); - } - - public static void CloseWindows() - { - try - { - // Close any existing tooltips - TooltipView.Close(); - } - catch (System.Exception) {} - - // Close all container windows - UnityObject[] containers = Resources.FindObjectsOfTypeAll(typeof(ContainerWindow)); - foreach (ContainerWindow window in containers) - { - try - { - window.Close(); - } - catch (System.Exception) {} - } - - // Double check correct closing - UnityObject[] oldWindows = Resources.FindObjectsOfTypeAll(typeof(EditorWindow)); - if (oldWindows.Length != 0) - { - string output = ""; - foreach (EditorWindow killme in oldWindows) - { - output += "\n" + killme.GetType().Name; - UnityObject.DestroyImmediate(killme, true); - } - Debug.LogError("Failed to destroy editor windows: #" + oldWindows.Length + output); - } - - UnityObject[] oldViews = Resources.FindObjectsOfTypeAll(typeof(View)); - if (oldViews.Length != 0) - { - string output = ""; - foreach (View killme in oldViews) - { - output += "\n" + killme.GetType().Name; - UnityObject.DestroyImmediate(killme, true); - } - Debug.LogError("Failed to destroy views: #" + oldViews.Length + output); - } - } - - public static void SaveWindowLayout(string path) - { - TooltipView.Close(); - - ArrayList all = new ArrayList(); - UnityObject[] windows = Resources.FindObjectsOfTypeAll(typeof(EditorWindow)); - UnityObject[] containers = Resources.FindObjectsOfTypeAll(typeof(ContainerWindow)); - UnityObject[] views = Resources.FindObjectsOfTypeAll(typeof(View)); - - foreach (ContainerWindow w in containers) - { - // skip ContainerWindows that are "dont save me" - if (w.m_DontSaveToLayout) - continue; - all.Add(w); - } - foreach (View w in views) - { - // skip Views that belong to "dont save me" container - if (w.window != null && w.window.m_DontSaveToLayout) - continue; - all.Add(w); - } - foreach (EditorWindow w in windows) - { - // skip EditorWindows that belong to "dont save me" container - if (w.m_Parent != null && w.m_Parent.window != null && w.m_Parent.window.m_DontSaveToLayout) - continue; - all.Add(w); - } - - InternalEditorUtility.SaveToSerializedFileAndForget(all.ToArray(typeof(UnityObject)) as UnityObject[], path, true); - } - - public static void EnsureMainWindowHasBeenLoaded() - { - var mainViews = Resources.FindObjectsOfTypeAll(); - if (mainViews.Length == 0) - { - MainView.MakeMain(); - } - } - - internal static MainView FindMainView() - { - var mainViews = Resources.FindObjectsOfTypeAll(); - if (mainViews.Length == 0) - { - Debug.LogError("No Main View found!"); - return null; - } - return mainViews[0]; - } - - public static void SaveGUI() - { - View mainView = FindMainView(); - Rect rect = mainView.screenPosition; - SaveWindowLayout w = EditorWindow.GetWindowWithRect(new Rect(rect.xMax - 180, rect.y + 20, 200, 48), true, "Save Window Layout"); - w.m_Parent.window.m_DontSaveToLayout = true; - } - - private static void RevertFactorySettings() - { - InternalEditorUtility.RevertFactoryLayoutSettings(true); - } - - internal static string layoutsPreferencesPath - { - get { return InternalEditorUtility.unityPreferencesFolder + "/Layouts"; } - } - - internal static string layoutsProjectPath - { - get { return Directory.GetCurrentDirectory() + "/Library"; } - } - - public static void DeleteGUI() - { - View mainView = FindMainView(); - Rect rect = mainView.screenPosition; - DeleteWindowLayout w = EditorWindow.GetWindowWithRect(new Rect(rect.xMax - 180, rect.y + 20, 200, 150), true, "Delete Window Layout"); - w.m_Parent.window.m_DontSaveToLayout = true; - } - } - - [EditorWindowTitle(title = "Save Layout")] - internal class SaveWindowLayout : EditorWindow - { - internal string m_LayoutName = Toolbar.lastLoadedLayoutName; - internal bool didFocus = false; - - void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - } - - void OnGUI() - { - GUILayout.Space(5); - Event evt = Event.current; - bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter); - GUI.SetNextControlName("m_PreferencesName"); - m_LayoutName = EditorGUILayout.TextField(m_LayoutName); - - if (!didFocus) - { - didFocus = true; - EditorGUI.FocusTextInControl("m_PreferencesName"); - } - - GUI.enabled = m_LayoutName.Length != 0; - if (GUILayout.Button("Save") || hitEnter) - { - Close(); - string path = Path.Combine(WindowLayout.layoutsPreferencesPath, m_LayoutName + ".wlt"); - Toolbar.lastLoadedLayoutName = m_LayoutName; - WindowLayout.SaveWindowLayout(path); - InternalEditorUtility.ReloadWindowLayoutMenu(); - GUIUtility.ExitGUI(); - } - } - } - - [EditorWindowTitle(title = "Delete Layout")] - internal class DeleteWindowLayout : EditorWindow - { - internal string[] m_Paths; - private const int kMaxLayoutNameLength = 15; - - void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - } - - private void InitializePaths() - { - string[] allPaths = Directory.GetFiles(WindowLayout.layoutsPreferencesPath); - ArrayList filteredFiles = new ArrayList(); - foreach (string path in allPaths) - { - string name = Path.GetFileName(path); - if (Path.GetExtension(name) == ".wlt") - filteredFiles.Add(path); - } - - m_Paths = filteredFiles.ToArray(typeof(string)) as string[]; - } - - private Vector2 m_ScrollPos; - - void OnGUI() - { - if (m_Paths == null) - InitializePaths(); - m_ScrollPos = EditorGUILayout.BeginScrollView(m_ScrollPos); - foreach (string path in m_Paths) - { - string name = Path.GetFileNameWithoutExtension(path); - if (name.Length > kMaxLayoutNameLength) - name = name.Substring(0, kMaxLayoutNameLength) + "..."; - if (GUILayout.Button(name)) - { - if (Toolbar.lastLoadedLayoutName == name) - Toolbar.lastLoadedLayoutName = null; - - System.IO.File.Delete(path); - InternalEditorUtility.ReloadWindowLayoutMenu(); - InitializePaths(); - } - } - EditorGUILayout.EndScrollView(); - } - } - - internal class CreateBuiltinWindows - { - [MenuItem("Window/Scene %1", false, 2000)] - static void ShowSceneView() - { - EditorWindow.GetWindow(); - } - - [MenuItem("Window/Game %2", false, 2001)] - static void ShowGameView() - { - EditorWindow.GetWindow(); - } - - [MenuItem("Window/Inspector %3", false, 2002)] - static void ShowInspector() - { - EditorWindow.GetWindow(); - } - - [MenuItem("Window/Hierarchy %4", false, 2003)] - static void ShowNewHierarchy() - { - EditorWindow.GetWindow(); - } - - [MenuItem("Window/Project %5", false, 2004)] - static void ShowProject() - { - EditorWindow.GetWindow(); - } - - [MenuItem("Window/Animation %6", false, 2006)] - static void ShowAnimationWindow() - { - EditorWindow.GetWindow(); - } - - // Profiler is registered from native code (EditorWindowController.cpp), for license check - //[MenuItem ("Window/Profiler %7", false, 2007)] - static void ShowProfilerWindow() - { - EditorWindow.GetWindow(); - } - - [MenuItem("Window/Audio Mixer %8", false, 2008)] - static void ShowAudioMixer() - { - AudioMixerWindow.CreateAudioMixerWindow(); - } - - // Version Control is registered from native code (EditorWindowController.cpp), for license check - // [MenuItem ("Window/Version Control", false, 2010)] - static void ShowVersionControl() - { - EditorWindow.GetWindow(); - } - - [MenuItem("Window/Sprite Packer", false, 2014)] - static void ShowSpritePackerWindow() - { - EditorWindow.GetWindow(); - } - - [MenuItem("Window/Console %#c", false, 2200)] - static void ShowConsole() - { - EditorWindow.GetWindow(); - } - - [MenuItem("Window/Experimental/Look Dev", false, 2015)] - static void ShowLookDevTool() - { - EditorWindow.GetWindow(); - } - } - - internal class WindowFocusState : ScriptableObject - { - private static WindowFocusState m_Instance; - - internal string m_LastWindowTypeInSameDock = ""; - internal bool m_WasMaximizedBeforePlay = false; - internal bool m_CurrentlyInPlayMode = false; - - internal static WindowFocusState instance - { - get - { - if (m_Instance == null) - m_Instance = FindObjectOfType(typeof(WindowFocusState)) as WindowFocusState; - if (m_Instance == null) - m_Instance = ScriptableObject.CreateInstance(); - return m_Instance; - } - } - - void OnEnable() - { - hideFlags = HideFlags.HideAndDontSave; - m_Instance = this; - } - } -} // namespace diff --git a/Editor/Mono/GUID.bindings.cs b/Editor/Mono/GUID.bindings.cs deleted file mode 100644 index dd2c8ddefd..0000000000 --- a/Editor/Mono/GUID.bindings.cs +++ /dev/null @@ -1,131 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - [Serializable] - [RequiredByNativeCode] - [NativeHeader("Runtime/Utilities/GUID.h")] - public partial struct GUID : IComparable, IComparable - { - private uint m_Value0, m_Value1, m_Value2, m_Value3; - - public GUID(string hexRepresentation) - { - m_Value0 = 0; - m_Value1 = 0; - m_Value2 = 0; - m_Value3 = 0; - TryParse(hexRepresentation, out this); - } - - public static bool operator==(GUID x, GUID y) - { - 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; - } - - public static bool operator!=(GUID x, GUID y) - { - return !(x == y); - } - - public static bool operator<(GUID x, GUID y) - { - if (x.m_Value0 != y.m_Value0) - return x.m_Value0 < y.m_Value0; - if (x.m_Value1 != y.m_Value1) - return x.m_Value1 < y.m_Value1; - if (x.m_Value2 != y.m_Value2) - return x.m_Value2 < y.m_Value2; - return x.m_Value3 < y.m_Value3; - } - - public static bool operator>(GUID x, GUID y) - { - if (x < y) - return false; - if (x == y) - return false; - return true; - } - - public override bool Equals(object obj) - { - if (obj == null || !(obj is GUID)) - return false; - GUID rhs = (GUID)obj; - return rhs == this; - } - - public override int GetHashCode() - { - unchecked - { - var hashCode = (int)m_Value0; - hashCode = (hashCode * 397) ^ (int)m_Value1; - hashCode = (hashCode * 397) ^ (int)m_Value2; - hashCode = (hashCode * 397) ^ (int)m_Value3; - return hashCode; - } - } - - public int CompareTo(object obj) - { - if (obj == null) - return 1; - - GUID rhs = (GUID)obj; - return this.CompareTo(rhs); - } - - public int CompareTo(GUID rhs) - { - if (this < rhs) - return -1; - if (this > rhs) - return 1; - return 0; - } - - public bool Empty() - { - return m_Value0 == 0 && m_Value1 == 0 && m_Value2 == 0 && m_Value3 == 0; - } - - [Obsolete("Use TryParse instead")] - public bool ParseExact(string hex) - { - return TryParse(hex, out this); - } - - public static bool TryParse(string hex, out GUID result) - { - result = HexToGUIDInternal(hex); - return !result.Empty(); - } - - public static GUID Generate() - { - return GenerateGUIDInternal(); - } - - public override string ToString() - { - return GUIDToHexInternal(ref this); - } - - [NativeMethod(Name = "GUIDToString", IsFreeFunction = true)] - extern private static string GUIDToHexInternal(ref GUID value); - - [NativeMethod(Name = "CoreStringToGUID", IsFreeFunction = true)] - extern private static GUID HexToGUIDInternal(string hex); - - [NativeMethod(Name = "GenerateGUID", IsFreeFunction = true)] - extern private static GUID GenerateGUIDInternal(); - } -} diff --git a/Editor/Mono/GUIDebugger/BaseInspectView.cs b/Editor/Mono/GUIDebugger/BaseInspectView.cs deleted file mode 100644 index 1bd7f7c915..0000000000 --- a/Editor/Mono/GUIDebugger/BaseInspectView.cs +++ /dev/null @@ -1,271 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal interface IBaseInspectView - { - void UpdateInstructions(); - void DrawInstructionList(); - void DrawSelectedInstructionDetails(); - void ShowOverlay(); - void SelectRow(int index); - void ClearRowSelection(); - } - - internal abstract class BaseInspectView : IBaseInspectView - { - protected static class Styles - { - public static readonly GUIContent instructionsLabel = EditorGUIUtility.TrTextContent("Instructions"); - public static readonly GUIContent emptyViewLabel = EditorGUIUtility.TrTextContent("Select an Instruction on the left to see details"); - - public static readonly GUIStyle centeredLabel = new GUIStyle("PR Label"); - - static Styles() - { - centeredLabel.alignment = TextAnchor.MiddleCenter; - centeredLabel.padding.right = 0; - centeredLabel.padding.left = 0; - } - } - - protected ListViewState listViewState { get { return m_ListViewState; } } - [NonSerialized] - readonly ListViewState m_ListViewState = new ListViewState(); - - protected GUIViewDebuggerWindow debuggerWindow { get { return m_DebuggerWindow; } } - GUIViewDebuggerWindow m_DebuggerWindow; - - Vector2 m_InstructionDetailsScrollPos = new Vector2(); - - readonly SplitterState m_InstructionDetailStacktraceSplitter = new SplitterState(new float[] { 80, 20 }, new int[] { 100, 100 }, null); - - public BaseInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) - { - m_DebuggerWindow = guiViewDebuggerWindow; - } - - public abstract void UpdateInstructions(); - - public virtual void DrawInstructionList() - { - Event evt = Event.current; - m_ListViewState.totalRows = GetInstructionCount(); - - EditorGUILayout.BeginVertical(GUIViewDebuggerWindow.Styles.listBackgroundStyle); - GUILayout.Label(Styles.instructionsLabel); - - int id = GUIUtility.GetControlID(FocusType.Keyboard); - foreach (var element in ListViewGUI.ListView(m_ListViewState, GUIViewDebuggerWindow.Styles.listBackgroundStyle)) - { - ListViewElement listViewElement = (ListViewElement)element; - if (evt.type == EventType.MouseDown && evt.button == 0 && listViewElement.position.Contains(evt.mousePosition)) - { - if (evt.clickCount == 2) - { - OnDoubleClickInstruction(listViewElement.row); - } - } - // Paint list view element - if (evt.type == EventType.Repaint && listViewElement.row < GetInstructionCount()) - { - DoDrawInstruction(listViewElement, id); - } - } - EditorGUILayout.EndVertical(); - } - - public virtual void DrawSelectedInstructionDetails() - { - if (m_ListViewState.selectionChanged) - OnSelectedInstructionChanged(m_ListViewState.row); - else if (m_ListViewState.row >= GetInstructionCount()) - OnSelectedInstructionChanged(-1); - - if (!isInstructionSelected) - { - DoDrawNothingSelected(); - return; - } - - SplitterGUILayout.BeginVerticalSplit(m_InstructionDetailStacktraceSplitter); - - m_InstructionDetailsScrollPos = EditorGUILayout.BeginScrollView(m_InstructionDetailsScrollPos, GUIViewDebuggerWindow.Styles.boxStyle); - - DoDrawSelectedInstructionDetails(m_ListViewState.row); - EditorGUILayout.EndScrollView(); - - DrawInspectedStacktrace(); - SplitterGUILayout.EndVerticalSplit(); - } - - public abstract void ShowOverlay(); - - public virtual void SelectRow(int index) - { - m_ListViewState.row = index; - m_ListViewState.selectionChanged = true; - } - - public virtual void ClearRowSelection() - { - m_ListViewState.row = -1; - m_ListViewState.selectionChanged = true; - } - - protected abstract int GetInstructionCount(); - - protected abstract void DoDrawInstruction(ListViewElement el, int controlId); - - protected abstract void DrawInspectedStacktrace(); - - protected virtual bool isInstructionSelected { get { return m_ListViewState.row >= 0 && m_ListViewState.row < GetInstructionCount(); } } - - protected void DrawStackFrameList(StackFrame[] stackframes) - { - if (stackframes != null) - { - foreach (var stackframe in stackframes) - { - if (string.IsNullOrEmpty(stackframe.sourceFile)) - continue; - - GUILayout.Label(string.Format("{0} [{1}:{2}]", stackframe.signature, stackframe.sourceFile, stackframe.lineNumber), GUIViewDebuggerWindow.Styles.stackframeStyle); - //GUILayout.Label(string.Format("{0} - {1}", stackframe.methodName, stackframe.moduleName), stackframeStyle); - } - } - } - - protected void DrawInspectedRect(Rect instructionRect) - { - var totalRect = GUILayoutUtility.GetRect(0, 100); - - var reserveTopFieldHeight = Mathf.CeilToInt(EditorGUI.kSingleLineHeight * 2 + EditorGUI.kControlVerticalSpacing); - var reserveBottomFieldHeight = Mathf.CeilToInt(EditorGUI.kSingleLineHeight); - var reserveFieldWidth = 100; - var fieldsArea = new RectOffset(50, reserveFieldWidth, reserveTopFieldHeight, reserveBottomFieldHeight); - var visualRect = fieldsArea.Remove(totalRect); - - float aspectRatio = instructionRect.width / instructionRect.height; - var aspectedRect = new Rect(); - var dummy = new Rect(); - - GUI.CalculateScaledTextureRects(visualRect, ScaleMode.ScaleToFit, aspectRatio, ref aspectedRect, ref dummy); - visualRect = aspectedRect; - visualRect.width = Mathf.Max(80, visualRect.width); - visualRect.height = Mathf.Max(EditorGUI.kSingleLineHeight + 10, visualRect.height); - - var startPointFieldRect = new Rect(); - startPointFieldRect.height = EditorGUI.kSingleLineHeight; - startPointFieldRect.width = fieldsArea.left * 2; - startPointFieldRect.y = visualRect.y - fieldsArea.top; - startPointFieldRect.x = visualRect.x - startPointFieldRect.width / 2f; - - var endPointFieldRect = new Rect - { - height = EditorGUI.kSingleLineHeight, - width = fieldsArea.right * 2, - y = visualRect.yMax - }; - endPointFieldRect.x = visualRect.xMax - endPointFieldRect.width / 2f; - - var widthMarkersArea = new Rect - { - x = visualRect.x, - y = startPointFieldRect.yMax + EditorGUI.kControlVerticalSpacing, - width = visualRect.width, - height = EditorGUI.kSingleLineHeight - }; - - var widthFieldRect = widthMarkersArea; - widthFieldRect.width = widthMarkersArea.width / 3; - widthFieldRect.x = widthMarkersArea.x + (widthMarkersArea.width - widthFieldRect.width) / 2f; - - var heightMarkerArea = visualRect; - heightMarkerArea.x = visualRect.xMax; - heightMarkerArea.width = EditorGUI.kSingleLineHeight; - - var heightFieldRect = heightMarkerArea; - heightFieldRect.height = EditorGUI.kSingleLineHeight; - heightFieldRect.width = fieldsArea.right; - heightFieldRect.y = heightFieldRect.y + (heightMarkerArea.height - heightFieldRect.height) / 2f; - - //Draw TopLeft point - GUI.Label(startPointFieldRect, string.Format("({0},{1})", instructionRect.x, instructionRect.y), Styles.centeredLabel); - - Handles.color = new Color(1, 1, 1, 0.5f); - //Draw Width markers and value - var startP = new Vector3(widthMarkersArea.x, widthFieldRect.y); - var endP = new Vector3(widthMarkersArea.x, widthFieldRect.yMax); - Handles.DrawLine(startP, endP); - - startP.x = endP.x = widthMarkersArea.xMax; - Handles.DrawLine(startP, endP); - - startP.x = widthMarkersArea.x; - startP.y = endP.y = Mathf.Lerp(startP.y, endP.y, .5f); - endP.x = widthFieldRect.x; - Handles.DrawLine(startP, endP); - - startP.x = widthFieldRect.xMax; - endP.x = widthMarkersArea.xMax; - Handles.DrawLine(startP, endP); - - GUI.Label(widthFieldRect, instructionRect.width.ToString(), Styles.centeredLabel); - - //Draw Height markers and value - startP = new Vector3(heightMarkerArea.x, heightMarkerArea.y); - endP = new Vector3(heightMarkerArea.xMax, heightMarkerArea.y); - Handles.DrawLine(startP, endP); - - startP.y = endP.y = heightMarkerArea.yMax; - Handles.DrawLine(startP, endP); - - startP.x = endP.x = Mathf.Lerp(startP.x, endP.x, .5f); - startP.y = heightMarkerArea.y; - endP.y = heightFieldRect.y; - Handles.DrawLine(startP, endP); - - startP.y = heightFieldRect.yMax; - endP.y = heightMarkerArea.yMax; - Handles.DrawLine(startP, endP); - - GUI.Label(heightFieldRect, instructionRect.height.ToString()); - - GUI.Label(endPointFieldRect, string.Format("({0},{1})", instructionRect.xMax, instructionRect.yMax), Styles.centeredLabel); - - //Draws the rect - GUI.Box(visualRect, GUIContent.none); - } - - protected void DoSelectableInstructionDataField(string label, string instructionData) - { - var rect = EditorGUILayout.GetControlRect(true); - EditorGUI.LabelField(rect, label); - rect.xMin += EditorGUIUtility.labelWidth; - EditorGUI.SelectableLabel(rect, instructionData); - } - - internal abstract void DoDrawSelectedInstructionDetails(int selectedInstructionIndex); - - internal abstract string GetInstructionListName(int index); - - internal abstract void OnDoubleClickInstruction(int index); - - internal abstract void OnSelectedInstructionChanged(int newSelectionIndex); - - void DoDrawNothingSelected() - { - EditorGUILayout.BeginVertical(); - GUILayout.FlexibleSpace(); - GUILayout.Label(Styles.emptyViewLabel, GUIViewDebuggerWindow.Styles.centeredText); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndVertical(); - } - } -} diff --git a/Editor/Mono/GUIDebugger/GUIClipInspectView.cs b/Editor/Mono/GUIDebugger/GUIClipInspectView.cs deleted file mode 100644 index a23b8261b2..0000000000 --- a/Editor/Mono/GUIDebugger/GUIClipInspectView.cs +++ /dev/null @@ -1,130 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - class GUIClipInspectView : BaseInspectView - { - Vector2 m_StacktraceScrollPos = new Vector2(); - - List m_ClipList = new List(); - - public GUIClipInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow) - { - } - - public override void UpdateInstructions() - { - //TODO: find a better approach instead of getting the whole list everyframe. - m_ClipList.Clear(); - GUIViewDebuggerHelper.GetClipInstructions(m_ClipList); - } - - public override void ShowOverlay() - { - if (!isInstructionSelected) - { - debuggerWindow.ClearInstructionHighlighter(); - return; - } - - var clipInstruction = m_ClipList[listViewState.row]; - debuggerWindow.HighlightInstruction(debuggerWindow.inspected, clipInstruction.unclippedScreenRect, GUIStyle.none); - } - - protected override int GetInstructionCount() - { - return m_ClipList.Count; - } - - protected override void DoDrawInstruction(ListViewElement el, int id) - { - var clipInstruction = m_ClipList[el.row]; - var niceName = GetInstructionListName(el.row); - - GUIContent tempContent = GUIContent.Temp(niceName); - - var rect = el.position; - rect.xMin += clipInstruction.level * 12; - - GUIViewDebuggerWindow.Styles.listItemBackground.Draw(el.position, false, false, listViewState.row == el.row, false); - GUIViewDebuggerWindow.Styles.listItem.Draw(rect, tempContent, id, listViewState.row == el.row); - } - - protected override void DrawInspectedStacktrace() - { - var clipInstruction = m_ClipList[listViewState.row]; - m_StacktraceScrollPos = EditorGUILayout.BeginScrollView(m_StacktraceScrollPos, GUIViewDebuggerWindow.Styles.stacktraceBackground, GUILayout.ExpandHeight(false)); - DrawStackFrameList(clipInstruction.pushStacktrace); - EditorGUILayout.EndScrollView(); - } - - internal override void DoDrawSelectedInstructionDetails(int selectedInstructionIndex) - { - var clipInstruction = m_ClipList[selectedInstructionIndex]; - - DoSelectableInstructionDataField("RenderOffset", clipInstruction.renderOffset.ToString()); - DoSelectableInstructionDataField("ResetOffset", clipInstruction.resetOffset.ToString()); - DoSelectableInstructionDataField("screenRect", clipInstruction.screenRect.ToString()); - DoSelectableInstructionDataField("scrollOffset", clipInstruction.scrollOffset.ToString()); - } - - internal override string GetInstructionListName(int index) - { - var clipInstruction = m_ClipList[index]; - var stacktrace = clipInstruction.pushStacktrace; - - if (stacktrace.Length == 0) - return "Empty"; - - int frameIndex = GetInterestingFrameIndex(stacktrace); - - StackFrame interestingFrame = stacktrace[frameIndex]; - string methodName = interestingFrame.methodName; - return methodName; - } - - internal override void OnDoubleClickInstruction(int index) - { - throw new NotImplementedException(); - } - - internal override void OnSelectedInstructionChanged(int index) - { - listViewState.row = index; - ShowOverlay(); - } - - int GetInterestingFrameIndex(StackFrame[] stacktrace) - { - string currentProjectPath = Application.dataPath; - - int index = -1; - - for (int i = 0; i < stacktrace.Length; ++i) - { - StackFrame sf = stacktrace[i]; - if (string.IsNullOrEmpty(sf.sourceFile)) - continue; - if (sf.signature.StartsWith("UnityEngine.GUIClip")) - continue; - - if (index == -1) - index = i; - - if (sf.sourceFile.StartsWith(currentProjectPath)) - return i; - } - - if (index != -1) - return index; - - return stacktrace.Length - 1; - } - } -} diff --git a/Editor/Mono/GUIDebugger/GUILayoutInspectView.cs b/Editor/Mono/GUIDebugger/GUILayoutInspectView.cs deleted file mode 100644 index 955ff074b0..0000000000 --- a/Editor/Mono/GUIDebugger/GUILayoutInspectView.cs +++ /dev/null @@ -1,163 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - class GUILayoutInspectView : BaseInspectView - { - Vector2 m_StacktraceScrollPos = new Vector2(); - - readonly List m_LayoutInstructions = new List(); - - GUIStyle m_FakeMarginStyleForOverlay = new GUIStyle(); - - public GUILayoutInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow) - { - } - - public override void UpdateInstructions() - { - m_LayoutInstructions.Clear(); - GUIViewDebuggerHelper.GetLayoutInstructions(m_LayoutInstructions); - } - - public override void ShowOverlay() - { - if (!isInstructionSelected) - { - debuggerWindow.ClearInstructionHighlighter(); - return; - } - - IMGUILayoutInstruction instruction = m_LayoutInstructions[listViewState.row]; - - RectOffset offset = new RectOffset(); - offset.left = instruction.marginLeft; - offset.right = instruction.marginRight; - offset.top = instruction.marginTop; - offset.bottom = instruction.marginBottom; - - //TODO: right now the overlay only know about padding - //For now we just save margin into padding - //while the overlay isn't improved. - m_FakeMarginStyleForOverlay.padding = offset; - - Rect rect = instruction.unclippedRect; - - rect = offset.Add(rect); - - debuggerWindow.HighlightInstruction(debuggerWindow.inspected, rect, m_FakeMarginStyleForOverlay); - } - - protected override int GetInstructionCount() - { - return m_LayoutInstructions.Count; - } - - protected override void DoDrawInstruction(ListViewElement el, int id) - { - IMGUILayoutInstruction instruction = m_LayoutInstructions[el.row]; - - GUIContent tempContent = GUIContent.Temp(GetInstructionListName(el.row)); - - var rect = el.position; - rect.xMin += instruction.level * 10; - - GUIViewDebuggerWindow.Styles.listItemBackground.Draw(rect, false, false, listViewState.row == el.row, false); - GUIViewDebuggerWindow.Styles.listItem.Draw(rect, tempContent, id, listViewState.row == el.row); - } - - protected override void DrawInspectedStacktrace() - { - IMGUILayoutInstruction instruction = m_LayoutInstructions[listViewState.row]; - - m_StacktraceScrollPos = EditorGUILayout.BeginScrollView(m_StacktraceScrollPos, GUIViewDebuggerWindow.Styles.stacktraceBackground, GUILayout.ExpandHeight(false)); - DrawStackFrameList(instruction.stack); - EditorGUILayout.EndScrollView(); - } - - internal override void DoDrawSelectedInstructionDetails(int selectedInstructionIndex) - { - IMGUILayoutInstruction instruction = m_LayoutInstructions[selectedInstructionIndex]; - - using (new EditorGUI.DisabledScope(true)) - DrawInspectedRect(instruction.unclippedRect); - - DoSelectableInstructionDataField("margin.left", instruction.marginLeft.ToString()); - DoSelectableInstructionDataField("margin.top", instruction.marginTop.ToString()); - DoSelectableInstructionDataField("margin.right", instruction.marginRight.ToString()); - DoSelectableInstructionDataField("margin.bottom", instruction.marginBottom.ToString()); - - if (instruction.style != null) - DoSelectableInstructionDataField("Style Name", instruction.style.name); - - if (instruction.isGroup == 1) - return; - - DoSelectableInstructionDataField("IsVertical", (instruction.isVertical == 1).ToString()); - } - - internal override string GetInstructionListName(int index) - { - IMGUILayoutInstruction instruction = m_LayoutInstructions[index]; - var stacktrace = instruction.stack; - - int frameIndex = GetInterestingFrameIndex(stacktrace); - - if (frameIndex > 0) - --frameIndex; - - StackFrame interestingFrame = stacktrace[frameIndex]; - string methodName = interestingFrame.methodName; - return methodName; - } - - internal override void OnDoubleClickInstruction(int index) - { - throw new NotImplementedException(); - } - - internal override void OnSelectedInstructionChanged(int index) - { - listViewState.row = index; - ShowOverlay(); - } - - int GetInterestingFrameIndex(StackFrame[] stacktrace) - { - //We try to find the first frame that belongs to the user project. - //If there is no frame inside the user project, we will return the first frame outside any class starting with: - // - UnityEngine.GUILayoutUtility - string currentProjectPath = Application.dataPath; - - int index = -1; - - for (int i = 0; i < stacktrace.Length; ++i) - { - StackFrame sf = stacktrace[i]; - if (string.IsNullOrEmpty(sf.sourceFile)) - continue; - if (sf.signature.StartsWith("UnityEngine.GUIDebugger")) - continue; - if (sf.signature.StartsWith("UnityEngine.GUILayoutUtility")) - continue; - - if (index == -1) - index = i; - - if (sf.sourceFile.StartsWith(currentProjectPath)) - return i; - } - - if (index != -1) - return index; - - return stacktrace.Length - 1; - } - } -} diff --git a/Editor/Mono/GUIDebugger/GUINamedControlInspectView.cs b/Editor/Mono/GUIDebugger/GUINamedControlInspectView.cs deleted file mode 100644 index be18485b40..0000000000 --- a/Editor/Mono/GUIDebugger/GUINamedControlInspectView.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - class GUINamedControlInspectView : BaseInspectView - { - private readonly List m_NamedControlInstructions = new List(); - - private GUIStyle m_FakeMargingStyleForOverlay = new GUIStyle(); - - public GUINamedControlInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow) - { - } - - public override void UpdateInstructions() - { - m_NamedControlInstructions.Clear(); - GUIViewDebuggerHelper.GetNamedControlInstructions(m_NamedControlInstructions); - } - - protected override int GetInstructionCount() - { - return m_NamedControlInstructions.Count; - } - - protected override void DoDrawInstruction(ListViewElement el, int id) - { - GUIContent tempContent = GUIContent.Temp(GetInstructionListName(el.row)); - - var rect = el.position; - - GUIViewDebuggerWindow.Styles.listItemBackground.Draw(rect, false, false, listViewState.row == el.row, false); - GUIViewDebuggerWindow.Styles.listItem.Draw(rect, tempContent, id, listViewState.row == el.row); - } - - internal override string GetInstructionListName(int index) - { - IMGUINamedControlInstruction instruction = m_NamedControlInstructions[index]; - return "\"" + instruction.name + "\""; - } - - internal override void OnDoubleClickInstruction(int index) - { - } - - protected override void DrawInspectedStacktrace() - { - } - - internal override void DoDrawSelectedInstructionDetails(int index) - { - var instruction = m_NamedControlInstructions[listViewState.row]; - - using (new EditorGUI.DisabledScope(true)) - DrawInspectedRect(instruction.rect); - DoSelectableInstructionDataField("Name", instruction.name); - DoSelectableInstructionDataField("ID", instruction.id.ToString()); - } - - internal override void OnSelectedInstructionChanged(int index) - { - listViewState.row = index; - ShowOverlay(); - } - - public override void ShowOverlay() - { - if (!isInstructionSelected) - { - debuggerWindow.ClearInstructionHighlighter(); - return; - } - - var instruction = m_NamedControlInstructions[listViewState.row]; - - debuggerWindow.HighlightInstruction(debuggerWindow.inspected, instruction.rect, m_FakeMargingStyleForOverlay); - } - } -} diff --git a/Editor/Mono/GUIDebugger/GUIPropertyInspectView.cs b/Editor/Mono/GUIDebugger/GUIPropertyInspectView.cs deleted file mode 100644 index 5e550425f5..0000000000 --- a/Editor/Mono/GUIDebugger/GUIPropertyInspectView.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - class GUIPropertyInspectView : BaseInspectView - { - Vector2 m_StacktraceScrollPos = new Vector2(); - private GUIStyle m_FakeMargingStyleForOverlay = new GUIStyle(); - - List m_PropertyList = new List(); - - public GUIPropertyInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow) - { - } - - public override void UpdateInstructions() - { - //TODO: find a better approach instead of getting the whole list everyframe. - m_PropertyList.Clear(); - GUIViewDebuggerHelper.GetPropertyInstructions(m_PropertyList); - } - - public override void ShowOverlay() - { - if (!isInstructionSelected) - { - debuggerWindow.ClearInstructionHighlighter(); - return; - } - - var property = m_PropertyList[listViewState.row]; - debuggerWindow.HighlightInstruction(debuggerWindow.inspected, property.rect, m_FakeMargingStyleForOverlay); - } - - protected override int GetInstructionCount() - { - return m_PropertyList.Count; - } - - protected override void DoDrawInstruction(ListViewElement el, int id) - { - GUIContent tempContent = GUIContent.Temp(GetInstructionListName(el.row)); - - var rect = el.position; - - GUIViewDebuggerWindow.Styles.listItemBackground.Draw(rect, false, false, listViewState.row == el.row, false); - GUIViewDebuggerWindow.Styles.listItem.Draw(rect, tempContent, id, listViewState.row == el.row); - } - - protected override void DrawInspectedStacktrace() - { - var clipInstruction = m_PropertyList[listViewState.row]; - m_StacktraceScrollPos = EditorGUILayout.BeginScrollView(m_StacktraceScrollPos, GUIViewDebuggerWindow.Styles.stacktraceBackground, GUILayout.ExpandHeight(false)); - DrawStackFrameList(clipInstruction.beginStacktrace); - EditorGUILayout.EndScrollView(); - } - - internal override void DoDrawSelectedInstructionDetails(int selectedInstructionIndex) - { - var property = m_PropertyList[listViewState.row]; - - using (new EditorGUI.DisabledScope(true)) - DrawInspectedRect(property.rect); - - DoSelectableInstructionDataField("Target Type Name", property.targetTypeName); - DoSelectableInstructionDataField("Path", property.path); - } - - internal override string GetInstructionListName(int index) - { - var clipInstruction = m_PropertyList[index]; - return clipInstruction.path; - } - - internal override void OnDoubleClickInstruction(int index) - { - throw new NotImplementedException(); - } - - internal override void OnSelectedInstructionChanged(int index) - { - listViewState.row = index; - ShowOverlay(); - } - } -} diff --git a/Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.cs b/Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.cs deleted file mode 100644 index 9b80c69e13..0000000000 --- a/Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.cs +++ /dev/null @@ -1,147 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using System; -namespace UnityEditor -{ - [RequiredByNativeCode] - internal struct IMGUIDrawInstruction - { - public Rect rect; - public Rect visibleRect; - public GUIStyle usedGUIStyle; - public GUIContent usedGUIContent; - public StackFrame[] stackframes; - - public void Reset() - { - rect = new Rect(); - visibleRect = new Rect(); - usedGUIStyle = GUIStyle.none; - usedGUIContent = GUIContent.none; - } - } - [RequiredByNativeCode] - internal struct IMGUIClipInstruction - { - public Rect screenRect; - public Rect unclippedScreenRect; - public Vector2 scrollOffset; - public Vector2 renderOffset; - public bool resetOffset; - public int level; - - public StackFrame[] pushStacktrace; - public StackFrame[] popStacktrace; - } - - [RequiredByNativeCode] - internal struct IMGUILayoutInstruction - { - public int level; - public Rect unclippedRect; - - public int marginLeft; - public int marginRight; - public int marginTop; - public int marginBottom; - - public GUIStyle style; - - - public StackFrame[] stack; - - public int isGroup; - public int isVertical; - } - - [RequiredByNativeCode] - internal struct IMGUINamedControlInstruction - { - public string name; - public Rect rect; - public int id; - } - - [RequiredByNativeCode] - internal struct IMGUIPropertyInstruction - { - public string targetTypeName; - public string path; - public Rect rect; - public StackFrame[] beginStacktrace; - public StackFrame[] endStacktrace; - } - - //unified - internal enum InstructionType - { - kStyleDraw = 1, - kClipPush = 2, - kClipPop = 3, - kLayoutBeginGroup = 4, - kLayoutEndGroup = 5, - kLayoutEntry = 6, - kPropertyBegin = 7, - kPropertyEnd = 8, - kLayoutNamedControl = 9 - } - - //TODO: we are symbolicating the stacktraces of all instructions, - //and even worse, we do it everyframe. - //We should load the stacktrace info lazily. - - [RequiredByNativeCode] - internal struct IMGUIInstruction - { - public InstructionType type; - public int level; - public Rect unclippedRect; - public StackFrame[] stack; - - public int typeInstructionIndex; - public bool enabled; - } - - [NativeHeader("Editor/Mono/GUIDebugger/GUIViewDebuggerHelper.bindings.h")] - [UsedByNativeCode] - internal static partial class GUIViewDebuggerHelper - { - [NativeThrows] - static internal extern void GetViews(List views); - - static internal extern void DebugWindow([Unmarshalled] GUIView view); - - [FreeFunction("GetGUIDebuggerManager().StopDebuggingAll")] - static internal extern void StopDebugging(); - - private static GUIContent CreateGUIContent(string text, Texture image, string tooltip) - { - return new GUIContent(text, image, tooltip); - } - - internal static extern void GetDrawInstructions(List drawInstructions); - - internal static extern void GetClipInstructions(List clipInstructions); - - internal static extern void GetNamedControlInstructions(List namedControlInstructions); - - internal static extern void GetPropertyInstructions(List namedControlInstructions); - - internal static extern void GetLayoutInstructions(List layoutInstructions); - - internal static extern void GetUnifiedInstructions(List layoutInstructions); - - [FreeFunction("GetGUIDebuggerManager().ClearInstructions")] - internal static extern void ClearInstructions(); - } -} //namespace diff --git a/Editor/Mono/GUIDebugger/GUIViewDebuggerWindow.cs b/Editor/Mono/GUIDebugger/GUIViewDebuggerWindow.cs deleted file mode 100644 index ea2302a265..0000000000 --- a/Editor/Mono/GUIDebugger/GUIViewDebuggerWindow.cs +++ /dev/null @@ -1,479 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using UnityEditor.Experimental.UIElements.Debugger; -using UnityEngine; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - class GUIViewDebuggerWindow : EditorWindow - { - enum InstructionType - { - Draw, - Clip, - Layout, - NamedControl, - Property, - Unified, - } - - internal static class Styles - { - public static readonly string defaultWindowPopupText = ""; - - public static readonly GUIContent inspectedWindowLabel = EditorGUIUtility.TrTextContent("Inspected View: "); - - public static readonly GUIStyle listItem = new GUIStyle("PR Label"); - public static readonly GUIStyle listItemBackground = new GUIStyle("CN EntryBackOdd"); - public static readonly GUIStyle listBackgroundStyle = new GUIStyle("CN Box"); - public static readonly GUIStyle boxStyle = new GUIStyle("CN Box"); - public static readonly GUIStyle stackframeStyle = new GUIStyle(EditorStyles.label); - public static readonly GUIStyle stacktraceBackground = new GUIStyle("CN Box"); - public static readonly GUIStyle centeredText = new GUIStyle("PR Label"); - - public static readonly Color contentHighlighterColor = new Color(0.62f, 0.77f, 0.90f, 0.5f); - public static readonly Color paddingHighlighterColor = new Color(0.76f, 0.87f, 0.71f, 0.5f); - - static Styles() - { - stackframeStyle.margin = new RectOffset(0, 0, 0, 0); - stackframeStyle.padding = new RectOffset(0, 0, 0, 0); - stacktraceBackground.padding = new RectOffset(5, 5, 5, 5); - - centeredText.alignment = TextAnchor.MiddleCenter; - centeredText.stretchHeight = true; - centeredText.stretchWidth = true; - } - } - - static GUIViewDebuggerWindow s_ActiveInspector; - - static EditorWindow GetEditorWindow(GUIView view) - { - var hostView = view as HostView; - if (hostView != null) - return hostView.actualView; - - return null; - } - - static string GetViewName(GUIView view) - { - var editorWindow = GetEditorWindow(view); - if (editorWindow != null) - return editorWindow.titleContent.text; - - return view.GetType().Name; - } - - public GUIView inspected - { - get - { - if (m_Inspected != null || m_InspectedEditorWindow == null) - return m_Inspected; - // continue inspecting the same window if its dock area is destroyed by e.g., docking or undocking it - return inspected = m_InspectedEditorWindow.m_Parent; - } - private set - { - if (m_Inspected != value) - { - ClearInstructionHighlighter(); - - m_Inspected = value; - if (m_Inspected != null) - { - m_InspectedEditorWindow = (m_Inspected is HostView) ? ((HostView)m_Inspected).actualView : null; - GUIViewDebuggerHelper.DebugWindow(m_Inspected); - m_Inspected.Repaint(); - } - else - { - m_InspectedEditorWindow = null; - GUIViewDebuggerHelper.StopDebugging(); - } - if (instructionModeView != null) - instructionModeView.ClearRowSelection(); - - OnInspectedViewChanged(); - } - } - } - [SerializeField] - GUIView m_Inspected; - EditorWindow m_InspectedEditorWindow; - - public IBaseInspectView instructionModeView { get { return m_InstructionModeView; } } - IBaseInspectView m_InstructionModeView; - - protected GUIViewDebuggerWindow() - { - m_InstructionModeView = new StyleDrawInspectView(this); - } - - public void ClearInstructionHighlighter() - { - if (m_PaddingHighlighter != null && m_PaddingHighlighter.shadow.parent != null) - { - var parent = m_PaddingHighlighter.shadow.parent; - - m_PaddingHighlighter.RemoveFromHierarchy(); - m_ContentHighlighter.RemoveFromHierarchy(); - - parent.Dirty(ChangeType.Repaint); - } - } - - public void HighlightInstruction(GUIView view, Rect instructionRect, GUIStyle style) - { - if (!m_ShowHighlighter) - return; - - ClearInstructionHighlighter(); - - if (m_PaddingHighlighter == null) - { - var borderWidth = 1f; - m_PaddingHighlighter = new VisualElement(); - m_PaddingHighlighter.style.borderColor = UIElementsDebugger.Styles.kSizePaddingSecondaryColor; - m_PaddingHighlighter.style.borderLeftWidth = borderWidth; - m_PaddingHighlighter.style.borderRightWidth = borderWidth; - m_PaddingHighlighter.style.borderTopWidth = borderWidth; - m_PaddingHighlighter.style.borderBottomWidth = borderWidth; - m_PaddingHighlighter.pickingMode = PickingMode.Ignore; - m_ContentHighlighter = new VisualElement(); - m_ContentHighlighter.style.borderColor = UIElementsDebugger.Styles.kSizeSecondaryColor; - m_ContentHighlighter.style.borderLeftWidth = borderWidth; - m_ContentHighlighter.style.borderRightWidth = borderWidth; - m_ContentHighlighter.style.borderTopWidth = borderWidth; - m_ContentHighlighter.style.borderBottomWidth = borderWidth; - m_ContentHighlighter.pickingMode = PickingMode.Ignore; - } - m_PaddingHighlighter.layout = instructionRect; - view.visualTree.Add(m_PaddingHighlighter); - if (style != null) - instructionRect = style.padding.Remove(instructionRect); - m_ContentHighlighter.layout = instructionRect; - view.visualTree.Add(m_ContentHighlighter); - } - - InstructionType instructionType - { - get { return m_InstructionType; } - set - { - if (m_InstructionType != value || m_InstructionModeView == null) - { - m_InstructionType = value; - switch (m_InstructionType) - { - case InstructionType.Clip: - m_InstructionModeView = new GUIClipInspectView(this); - break; - case InstructionType.Draw: - m_InstructionModeView = new StyleDrawInspectView(this); - break; - case InstructionType.Layout: - m_InstructionModeView = new GUILayoutInspectView(this); - break; - case InstructionType.NamedControl: - m_InstructionModeView = new GUINamedControlInspectView(this); - break; - case InstructionType.Property: - m_InstructionModeView = new GUIPropertyInspectView(this); - break; - case InstructionType.Unified: - m_InstructionModeView = new UnifiedInspectView(this); - break; - } - m_InstructionModeView.UpdateInstructions(); - } - } - } - [SerializeField] - InstructionType m_InstructionType = InstructionType.Draw; - - VisualElement m_ContentHighlighter; - VisualElement m_PaddingHighlighter; - [SerializeField] - bool m_ShowHighlighter = true; - - [SerializeField] - private bool m_InspectOptimizedGUIBlocks = false; - - [NonSerialized] - bool m_QueuedPointInspection = false; - - [NonSerialized] - Vector2 m_PointToInspect; - - //TODO: figure out proper minimum values and make sure the window also has compatible minimum size - readonly SplitterState m_InstructionListDetailSplitter = new SplitterState(new float[] { 30, 70 }, new int[] { 32, 32 }, null); - - //Internal Tool for now. Uncomment it to enable it. - //[MenuItem("Window/GUIView Inspector")] - static void Init() - { - // Get existing open window or if none, make a new one: - if (s_ActiveInspector == null) - { - GUIViewDebuggerWindow window = (GUIViewDebuggerWindow)GetWindow(typeof(GUIViewDebuggerWindow)); - s_ActiveInspector = window; - } - s_ActiveInspector.Show(); - } - - void OnEnable() - { - titleContent = EditorGUIUtility.TrTextContent("IMGUI Debugger"); - GUIViewDebuggerHelper.onViewInstructionsChanged += OnInspectedViewChanged; - GUIView serializedInspected = m_Inspected; - inspected = null; - inspected = serializedInspected; - m_InstructionModeView = null; - instructionType = m_InstructionType; - } - - void OnDisable() - { - GUIViewDebuggerHelper.onViewInstructionsChanged -= OnInspectedViewChanged; - inspected = null; - } - - void OnBecameVisible() - { - OnShowOverlayChanged(); - } - - void OnBecameInvisible() - { - ClearInstructionHighlighter(); - } - - void OnGUI() - { - DoToolbar(); - ShowDrawInstructions(); - } - - private bool m_FlushingOptimizedGUIBlock; - - void OnInspectedViewChanged() - { - if (m_InspectOptimizedGUIBlocks && !m_FlushingOptimizedGUIBlock) - { - var inspector = m_InspectedEditorWindow as InspectorWindow; - if (inspector != null && inspector.tracker != null) - { - m_FlushingOptimizedGUIBlock = true; - foreach (var editor in inspector.tracker.activeEditors) - editor.isInspectorDirty = true; - inspector.Repaint(); - } - } - m_FlushingOptimizedGUIBlock = false; - RefreshData(); - Repaint(); - } - - void DoToolbar() - { - GUILayout.BeginHorizontal(EditorStyles.toolbar); - - DoWindowPopup(); - DoInspectTypePopup(); - DoInstructionOverlayToggle(); - DoOptimizedGUIBlockToggle(); - - GUILayout.EndHorizontal(); - } - - bool CanInspectView(GUIView view) - { - if (view == null) - return false; - - EditorWindow editorWindow = GetEditorWindow(view); - if (editorWindow == null) - return true; - - if (editorWindow == this) - return false; - - return true; - } - - void DoWindowPopup() - { - string selectedName = inspected == null ? Styles.defaultWindowPopupText : GetViewName(inspected); - - GUILayout.Label(Styles.inspectedWindowLabel, GUILayout.ExpandWidth(false)); - - Rect popupPosition = GUILayoutUtility.GetRect(GUIContent.Temp(selectedName), EditorStyles.toolbarDropDown, GUILayout.ExpandWidth(true)); - if (GUI.Button(popupPosition, GUIContent.Temp(selectedName), EditorStyles.toolbarDropDown)) - { - List views = new List(); - GUIViewDebuggerHelper.GetViews(views); - - List options = new List(views.Count + 1); - - options.Add(EditorGUIUtility.TrTextContent("None")); - - int selectedIndex = 0; - List selectableViews = new List(views.Count + 1); - for (int i = 0; i < views.Count; ++i) - { - GUIView view = views[i]; - - //We can't inspect ourselves, otherwise we get infinite recursion. - //Also avoid the InstructionOverlay - if (!CanInspectView(view)) - continue; - - GUIContent label = new GUIContent(string.Format("{0}. {1}", options.Count, GetViewName(view))); - options.Add(label); - selectableViews.Add(view); - - if (view == inspected) - selectedIndex = selectableViews.Count; - } - //TODO: convert this to a Unity Window style popup. This way we could highlight the window on hover ;) - EditorUtility.DisplayCustomMenu(popupPosition, options.ToArray(), selectedIndex, OnWindowSelected, selectableViews); - } - } - - void DoInspectTypePopup() - { - EditorGUI.BeginChangeCheck(); - var newInstructionType = (InstructionType)EditorGUILayout.EnumPopup(m_InstructionType, EditorStyles.toolbarDropDown); - if (EditorGUI.EndChangeCheck()) - instructionType = newInstructionType; - } - - void DoInstructionOverlayToggle() - { - EditorGUI.BeginChangeCheck(); - m_ShowHighlighter = GUILayout.Toggle(m_ShowHighlighter, GUIContent.Temp("Show Overlay"), EditorStyles.toolbarButton); - if (EditorGUI.EndChangeCheck()) - { - OnShowOverlayChanged(); - } - } - - void DoOptimizedGUIBlockToggle() - { - EditorGUI.BeginChangeCheck(); - m_InspectOptimizedGUIBlocks = GUILayout.Toggle(m_InspectOptimizedGUIBlocks, GUIContent.Temp("Force Inspect Optimized GUI Blocks"), EditorStyles.toolbarButton); - if (EditorGUI.EndChangeCheck()) - OnInspectedViewChanged(); - } - - void OnShowOverlayChanged() - { - if (m_ShowHighlighter == false) - { - ClearInstructionHighlighter(); - } - else - { - if (inspected != null) - { - instructionModeView.ShowOverlay(); - } - } - } - - void OnWindowSelected(object userdata, string[] options, int selected) - { - selected--; - inspected = selected < 0 ? null : ((List)userdata)[selected]; - } - - void RefreshData() - { - instructionModeView.UpdateInstructions(); - } - - void ShowDrawInstructions() - { - if (inspected == null) - { - ClearInstructionHighlighter(); - return; - } - - if (m_QueuedPointInspection) - { - instructionModeView.ClearRowSelection(); - instructionModeView.SelectRow(FindInstructionUnderPoint(m_PointToInspect)); - m_QueuedPointInspection = false; - } - - SplitterGUILayout.BeginHorizontalSplit(m_InstructionListDetailSplitter); - - instructionModeView.DrawInstructionList(); - - EditorGUILayout.BeginVertical(); - { - instructionModeView.DrawSelectedInstructionDetails(); - } - EditorGUILayout.EndVertical(); - - SplitterGUILayout.EndHorizontalSplit(); - } - - void InspectPointAt(Vector2 point) - { - m_PointToInspect = point; - m_QueuedPointInspection = true; - inspected.Repaint(); - Repaint(); - } - - int FindInstructionUnderPoint(Vector2 point) - { - List drawInstructions = new List(); - GUIViewDebuggerHelper.GetDrawInstructions(drawInstructions); - for (int i = 0; i < drawInstructions.Count; ++i) - { - Rect rect = drawInstructions[i].rect; - if (rect.Contains(point)) - { - return i; - } - } - return -1; - } - } - - //This needs to match ManagedStackFrameToMono in native - [StructLayout(LayoutKind.Sequential)] - struct StackFrame - { - public uint lineNumber; - public string sourceFile; - public string methodName; - public string signature; - public string moduleName; //TODO: we only get "Mono JIT Code" or "wrapper something", can we get the actual assembly name? - } - - internal static partial class GUIViewDebuggerHelper - { - internal static Action onViewInstructionsChanged; - - [RequiredByNativeCode] - private static void CallOnViewInstructionsChanged() - { - if (onViewInstructionsChanged != null) - onViewInstructionsChanged(); - } - } -} diff --git a/Editor/Mono/GUIDebugger/StyleDrawInspectView.cs b/Editor/Mono/GUIDebugger/StyleDrawInspectView.cs deleted file mode 100644 index 5da80c40bb..0000000000 --- a/Editor/Mono/GUIDebugger/StyleDrawInspectView.cs +++ /dev/null @@ -1,263 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - //The only purpose of this class is to enable us to view the used GUIStyle - //using Serialized Properties. - class GUIStyleHolder : ScriptableObject - { - public GUIStyle inspectedStyle; - - protected GUIStyleHolder() {} - } - - class StyleDrawInspectView : BaseInspectView - { - [Serializable] - class CachedInstructionInfo - { - public SerializedObject styleContainerSerializedObject = null; - public SerializedProperty styleSerializedProperty = null; - public readonly GUIStyleHolder styleContainer; - - public CachedInstructionInfo() - { - styleContainer = ScriptableObject.CreateInstance(); - } - } - - Vector2 m_StacktraceScrollPos = new Vector2(); - - [NonSerialized] List m_Instructions = new List(); - [NonSerialized] IMGUIDrawInstruction m_Instruction; - [NonSerialized] CachedInstructionInfo m_CachedInstructionInfo; - - public StyleDrawInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow) - { - } - - public override void UpdateInstructions() - { - m_Instructions.Clear(); - GUIViewDebuggerHelper.GetDrawInstructions(m_Instructions); - } - - public override void ClearRowSelection() - { - base.ClearRowSelection(); - m_CachedInstructionInfo = null; - } - - public override void ShowOverlay() - { - if (m_CachedInstructionInfo != null) - debuggerWindow.HighlightInstruction(debuggerWindow.inspected, m_Instruction.rect, m_Instruction.usedGUIStyle); - } - - protected override int GetInstructionCount() - { - return m_Instructions.Count; - } - - protected override void DoDrawInstruction(ListViewElement el, int id) - { - string listDisplayName = GetInstructionListName(el.row); - GUIContent tempContent = GUIContent.Temp(listDisplayName); - - GUIViewDebuggerWindow.Styles.listItemBackground.Draw(el.position, false, false, listViewState.row == el.row, false); - - GUIViewDebuggerWindow.Styles.listItem.Draw(el.position, tempContent, id, listViewState.row == el.row); - } - - protected override void DrawInspectedStacktrace() - { - m_StacktraceScrollPos = EditorGUILayout.BeginScrollView(m_StacktraceScrollPos, GUIViewDebuggerWindow.Styles.stacktraceBackground, GUILayout.ExpandHeight(false)); - DrawStackFrameList(m_Instruction.stackframes); - EditorGUILayout.EndScrollView(); - } - - protected override bool isInstructionSelected { get { return m_CachedInstructionInfo != null; } } - - internal override void DoDrawSelectedInstructionDetails(int selectedInstructionIndex) - { - using (new EditorGUI.DisabledScope(true)) - DrawInspectedRect(m_Instruction.rect); - - DoSelectableInstructionDataField("VisibleRect", m_Instruction.visibleRect.ToString()); - EditorGUILayout.Space(); - - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_CachedInstructionInfo.styleSerializedProperty, GUIContent.Temp("Style"), true); - if (EditorGUI.EndChangeCheck()) - { - m_CachedInstructionInfo.styleContainerSerializedObject.ApplyModifiedPropertiesWithoutUndo(); - debuggerWindow.inspected.Repaint(); - } - - GUILayout.Label(GUIContent.Temp("GUIContent")); - using (new EditorGUI.IndentLevelScope()) - { - DoSelectableInstructionDataField("Text", m_Instruction.usedGUIContent.text); - DoSelectableInstructionDataField("Tooltip", m_Instruction.usedGUIContent.tooltip); - using (new EditorGUI.DisabledScope(true)) - EditorGUILayout.ObjectField("Icon", m_Instruction.usedGUIContent.image, typeof(Texture2D), false); - } - } - - internal override string GetInstructionListName(int index) - { - //This means we will resolve the stack trace for all instructions. - //TODO: make sure only visible items do this. Also, cache so we don't have to do everyframe. - var methodName = GetInstructionListName(m_Instructions[index].stackframes); - - //TODO: use the signature we get from the managed stack - return string.Format("{0}. {1}", index, methodName); - } - - string GetInstructionListName(StackFrame[] stacktrace) - { - int frameIndex = GetInterestingFrameIndex(stacktrace); - - if (frameIndex > 0) - --frameIndex; - - StackFrame interestingFrame = stacktrace[frameIndex]; - return interestingFrame.methodName; - } - - internal override void OnDoubleClickInstruction(int index) - { - ShowInstructionInExternalEditor(m_Instructions[index].stackframes); - } - - internal override void OnSelectedInstructionChanged(int index) - { - listViewState.row = index; - - if (listViewState.row >= 0) - { - if (m_CachedInstructionInfo == null) - { - m_CachedInstructionInfo = new CachedInstructionInfo(); - } - - m_Instruction = m_Instructions[listViewState.row]; - - //updated Cached data related to the Selected Instruction - m_CachedInstructionInfo.styleContainer.inspectedStyle = m_Instruction.usedGUIStyle; - m_CachedInstructionInfo.styleContainerSerializedObject = null; - m_CachedInstructionInfo.styleSerializedProperty = null; - GetSelectedStyleProperty(out m_CachedInstructionInfo.styleContainerSerializedObject, out m_CachedInstructionInfo.styleSerializedProperty); - - //Hightlight the item - debuggerWindow.HighlightInstruction(debuggerWindow.inspected, m_Instruction.rect, m_Instruction.usedGUIStyle); - } - else - { - m_CachedInstructionInfo = null; - - debuggerWindow.ClearInstructionHighlighter(); - } - } - - int GetInterestingFrameIndex(StackFrame[] stacktrace) - { - //We try to find the first frame that belongs to the user project. - //If there is no frame inside the user project, we will return the first frame outside any class starting with: - //UnityEngine.GUI or UnityEditor.EditorGUI, this should include: - // - UnityEngine.GUIStyle - // - UnityEngine.GUILayout - // - UnityEngine.GUI - // - UnityEditor.EditorGUI - // - UnityEditor.EditorGUILayout - string currentProjectPath = Application.dataPath; - - int index = -1; - - for (int i = 0; i < stacktrace.Length; ++i) - { - StackFrame sf = stacktrace[i]; - if (string.IsNullOrEmpty(sf.sourceFile)) - continue; - if (sf.signature.StartsWith("UnityEngine.GUI")) - continue; - if (sf.signature.StartsWith("UnityEditor.EditorGUI")) - continue; - - if (index == -1) - index = i; - - if (sf.sourceFile.StartsWith(currentProjectPath)) - return i; - } - - if (index != -1) - return index; - - return stacktrace.Length - 1; - } - - void GetSelectedStyleProperty(out SerializedObject serializedObject, out SerializedProperty styleProperty) - { - //GUISkin[] guiskins = FindObjectsOfType(); - GUISkin guiskin = null; - //foreach (GUISkin gs in guiskins) - var gs = GUISkin.current; - { - GUIStyle style = gs.FindStyle(m_Instruction.usedGUIStyle.name); - if (style != null && style == m_Instruction.usedGUIStyle) - { - guiskin = gs; - //break; - } - } - styleProperty = null; - - if (guiskin != null) - { - serializedObject = new SerializedObject(guiskin); - SerializedProperty property = serializedObject.GetIterator(); - bool expanded = true; - while (property.NextVisible(expanded)) - { - if (property.type == "GUIStyle") - { - expanded = false; - SerializedProperty spt = property.FindPropertyRelative("m_Name"); - if (spt.stringValue == m_Instruction.usedGUIStyle.name) - { - styleProperty = property; - return; - } - } - else - { - expanded = true; - } - - //EditorGUILayout.PropertyField(property, true); - } - Debug.Log(string.Format("Showing editable Style from GUISkin: {0}, IsPersistant: {1}", guiskin.name, EditorUtility.IsPersistent(guiskin))); - } - - //Could not find the styles in the GUISkin. - serializedObject = new SerializedObject(m_CachedInstructionInfo.styleContainer); - styleProperty = serializedObject.FindProperty("inspectedStyle"); - } - - void ShowInstructionInExternalEditor(StackFrame[] frames) - { - int frameIndex = GetInterestingFrameIndex(frames); - StackFrame frame = frames[frameIndex]; - - InternalEditorUtility.OpenFileAtLineExternal(frame.sourceFile, (int)frame.lineNumber); - } - } -} diff --git a/Editor/Mono/GUIDebugger/UnifiedInspectView.cs b/Editor/Mono/GUIDebugger/UnifiedInspectView.cs deleted file mode 100644 index 4a589ab874..0000000000 --- a/Editor/Mono/GUIDebugger/UnifiedInspectView.cs +++ /dev/null @@ -1,164 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - class UnifiedInspectView : BaseInspectView - { - Vector2 m_StacktraceScrollPos = new Vector2(); - - readonly List m_Instructions = new List(); - BaseInspectView m_InstructionClipView; - BaseInspectView m_InstructionStyleView; - BaseInspectView m_InstructionPropertyView; - BaseInspectView m_InstructionLayoutView; - private BaseInspectView m_InstructionNamedControlView; - - public UnifiedInspectView(GUIViewDebuggerWindow guiViewDebuggerWindow) : base(guiViewDebuggerWindow) - { - m_InstructionClipView = new GUIClipInspectView(guiViewDebuggerWindow); - m_InstructionStyleView = new StyleDrawInspectView(guiViewDebuggerWindow); - m_InstructionLayoutView = new GUILayoutInspectView(guiViewDebuggerWindow); - m_InstructionPropertyView = new GUIPropertyInspectView(guiViewDebuggerWindow); - m_InstructionNamedControlView = new GUINamedControlInspectView(guiViewDebuggerWindow); - } - - public override void UpdateInstructions() - { - m_InstructionClipView.UpdateInstructions(); - m_InstructionStyleView.UpdateInstructions(); - m_InstructionLayoutView.UpdateInstructions(); - m_InstructionPropertyView.UpdateInstructions(); - m_InstructionNamedControlView.UpdateInstructions(); - - /* - This is an expensive operation, it will resolve the callstacks for all instructions. - Currently we marshall all instructions for every GUI Event. - This works okay for windows that doesn't repaint automatically. - We can optmize by only marshalling the visible instructions and caching it. - But I don't really think its needed right now. - */ - m_Instructions.Clear(); - GUIViewDebuggerHelper.GetUnifiedInstructions(m_Instructions); - } - - public override void ShowOverlay() - { - if (!isInstructionSelected) - { - debuggerWindow.ClearInstructionHighlighter(); - return; - } - - IMGUIInstruction instruction = m_Instructions[listViewState.row]; - var viewForType = GetInspectViewForType(instruction.type); - viewForType.ShowOverlay(); - } - - protected override int GetInstructionCount() - { - return m_Instructions.Count; - } - - protected override void DoDrawInstruction(ListViewElement el, int controlId) - { - IMGUIInstruction instruction = m_Instructions[el.row]; - - string listDisplayName = GetInstructionListName(el.row); - GUIContent tempContent = GUIContent.Temp(listDisplayName); - - var rect = el.position; - rect.xMin += instruction.level * 10; - - GUIViewDebuggerWindow.Styles.listItemBackground.Draw(rect, false, false, listViewState.row == el.row, false); - - GUIViewDebuggerWindow.Styles.listItem.Draw(rect, tempContent, controlId, listViewState.row == el.row); - } - - protected override void DrawInspectedStacktrace() - { - IMGUIInstruction instruction = m_Instructions[listViewState.row]; - - m_StacktraceScrollPos = EditorGUILayout.BeginScrollView(m_StacktraceScrollPos, GUIViewDebuggerWindow.Styles.stacktraceBackground, GUILayout.ExpandHeight(false)); - DrawStackFrameList(instruction.stack); - EditorGUILayout.EndScrollView(); - } - - internal override void DoDrawSelectedInstructionDetails(int selectedInstructionIndex) - { - IMGUIInstruction instruction = m_Instructions[selectedInstructionIndex]; - - var viewForType = GetInspectViewForType(instruction.type); - viewForType.DoDrawSelectedInstructionDetails(instruction.typeInstructionIndex); - } - - internal override string GetInstructionListName(int index) - { - IMGUIInstruction instruction = m_Instructions[index]; - - //string listDisplayName = instruction.type + " #" + instruction.typeInstructionIndex; - //return listDisplayName; - - var viewForType = GetInspectViewForType(instruction.type); - return viewForType.GetInstructionListName(instruction.typeInstructionIndex); - } - - internal override void OnSelectedInstructionChanged(int index) - { - listViewState.row = index; - - if (listViewState.row >= -0) - { - IMGUIInstruction instruction = m_Instructions[listViewState.row]; - - var viewForType = GetInspectViewForType(instruction.type); - viewForType.OnSelectedInstructionChanged(instruction.typeInstructionIndex); - - ShowOverlay(); - } - else - { - debuggerWindow.ClearInstructionHighlighter(); - } - } - - internal override void OnDoubleClickInstruction(int index) - { - IMGUIInstruction instruction = m_Instructions[index]; - - var viewForType = GetInspectViewForType(instruction.type); - viewForType.OnDoubleClickInstruction(instruction.typeInstructionIndex); - } - - BaseInspectView GetInspectViewForType(InstructionType type) - { - switch (type) - { - case InstructionType.kStyleDraw: - return m_InstructionStyleView; - - case InstructionType.kClipPop: - case InstructionType.kClipPush: - return m_InstructionClipView; - - case InstructionType.kLayoutBeginGroup: - case InstructionType.kLayoutEndGroup: - case InstructionType.kLayoutEntry: - return m_InstructionLayoutView; - case InstructionType.kPropertyBegin: - case InstructionType.kPropertyEnd: - return m_InstructionPropertyView; - case InstructionType.kLayoutNamedControl: - return m_InstructionNamedControlView; - default: - throw new NotImplementedException("Unhandled InstructionType"); - } - } - } -} diff --git a/Editor/Mono/GUIView.cs b/Editor/Mono/GUIView.cs deleted file mode 100644 index 685246bda2..0000000000 --- a/Editor/Mono/GUIView.cs +++ /dev/null @@ -1,237 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Linq; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using IntPtr = System.IntPtr; -using System; -using UnityEditor.StyleSheets; -using UnityEditor.Experimental.UIElements; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleSheets; - -namespace UnityEditor -{ - // See GUIView.bindings for bindings - - // This is what we (not users) derive from to create various views. (Main Toolbar, etc.) - [StructLayout(LayoutKind.Sequential)] - internal partial class GUIView : View - { - internal static event Action positionChanged = null; - - Panel m_Panel = null; - EditorCursorManager m_CursorManager = new EditorCursorManager(); - static EditorContextualMenuManager s_ContextualMenuManager = new EditorContextualMenuManager(); - - static GUIView() - { - Panel.loadResourceFunc = StyleSheetResourceUtil.LoadResource; - StyleSheetApplicator.createDefaultCursorStyleFunc = UIElementsEditorUtility.CreateDefaultCursorStyle; - Panel.TimeSinceStartup = () => (long)(EditorApplication.timeSinceStartup * 1000.0f); - } - - protected Panel panel - { - get - { - if (m_Panel == null) - { - UXMLEditorFactories.RegisterAll(); - m_Panel = UIElementsUtility.FindOrCreatePanel(this, ContextType.Editor, DataWatchService.sharedInstance); - m_Panel.cursorManager = m_CursorManager; - m_Panel.contextualMenuManager = s_ContextualMenuManager; - } - - return m_Panel; - } - } - - public VisualElement visualTree - { - get - { - return panel.visualTree; - } - } - - protected IMGUIContainer imguiContainer { get; private set; } - - int m_DepthBufferBits = 0; - EventInterests m_EventInterests; - bool m_AutoRepaintOnSceneChange = false; - private bool m_BackgroundValid = false; - - internal bool SendEvent(Event e) - { - int depth = SavedGUIState.Internal_GetGUIDepth(); - bool retval = false; - if (depth > 0) - { - SavedGUIState oldState = SavedGUIState.Create(); - retval = Internal_SendEvent(e); - oldState.ApplyAndForget(); - } - else - { - retval = Internal_SendEvent(e); - } - return retval; - } - - // Call into C++ here to move the underlying NSViews around - protected override void SetWindow(ContainerWindow win) - { - base.SetWindow(win); - Internal_Init(m_DepthBufferBits); - if (win) - Internal_SetWindow(win); - Internal_SetAutoRepaint(m_AutoRepaintOnSceneChange); - Internal_SetPosition(windowPosition); - Internal_SetWantsMouseMove(m_EventInterests.wantsMouseMove); - Internal_SetWantsMouseEnterLeaveWindow(m_EventInterests.wantsMouseMove); - - panel.visualTree.SetSize(windowPosition.size); - m_BackgroundValid = false; - } - - internal void RecreateContext() - { - Internal_Recreate(m_DepthBufferBits); - m_BackgroundValid = false; - } - - public EventInterests eventInterests - { - get { return m_EventInterests; } - set - { - m_EventInterests = value; - panel.IMGUIEventInterests = m_EventInterests; - Internal_SetWantsMouseMove(wantsMouseMove); - Internal_SetWantsMouseEnterLeaveWindow(wantsMouseEnterLeaveWindow); - } - } - - public bool wantsMouseMove - { - get { return m_EventInterests.wantsMouseMove; } - set - { - m_EventInterests.wantsMouseMove = value; - panel.IMGUIEventInterests = m_EventInterests; - Internal_SetWantsMouseMove(wantsMouseMove); - } - } - - public bool wantsMouseEnterLeaveWindow - { - get { return m_EventInterests.wantsMouseEnterLeaveWindow; } - set - { - m_EventInterests.wantsMouseEnterLeaveWindow = value; - panel.IMGUIEventInterests = m_EventInterests; - Internal_SetWantsMouseEnterLeaveWindow(wantsMouseEnterLeaveWindow); - } - } - - internal bool backgroundValid - { - get { return m_BackgroundValid; } - set { m_BackgroundValid = value; } - } - - public bool autoRepaintOnSceneChange - { - get { return m_AutoRepaintOnSceneChange; } - set { m_AutoRepaintOnSceneChange = value; Internal_SetAutoRepaint(m_AutoRepaintOnSceneChange); } - } - - public int depthBufferBits - { - get { return m_DepthBufferBits; } - set { m_DepthBufferBits = value; } - } - - [Obsolete("AA is not supported on GUIViews", false)] - public int antiAlias - { - get { return 1; } - set {} - } - - protected virtual void OnEnable() - { - imguiContainer = new IMGUIContainer(OldOnGUI) { useOwnerObjectGUIState = true }; - imguiContainer.StretchToParentSize(); - imguiContainer.persistenceKey = "Dockarea"; - visualTree.Insert(0, imguiContainer); - } - - protected virtual void OnDisable() - { - if (imguiContainer.HasMouseCapture()) - MouseCaptureController.ReleaseMouseCapture(); - visualTree.Remove(imguiContainer); - imguiContainer = null; - } - - protected virtual void OldOnGUI() {} - - // Without leaving this in here for MonoBehaviour::DoGUI(), GetMethod(MonoScriptCache::kGUI) will return null. - // In that case, commands are not delegated (e.g., keyboard-based delete in Hierarchy/Project) - protected virtual void OnGUI() {} - - protected override void SetPosition(Rect newPos) - { - Rect oldWinPos = windowPosition; - - base.SetPosition(newPos); - if (oldWinPos == windowPosition) - { - Internal_SetPosition(windowPosition); - return; - } - - Internal_SetPosition(windowPosition); - - m_BackgroundValid = false; - - panel.visualTree.SetSize(windowPosition.size); - if (positionChanged != null) - positionChanged(this); - - Repaint(); - } - - protected override void OnDestroy() - { - Internal_Close(); - - UIElementsUtility.RemoveCachedPanel(this.GetInstanceID()); - - base.OnDestroy(); - } - - // Draw resize handles, etc. - internal void DoWindowDecorationStart() - { - // On windows, we want both close window and side resizes. - // Titlebar dragging is done at the end, so we can drag next to tabs. - if (window != null) - window.HandleWindowDecorationStart(windowPosition); - } - - internal void DoWindowDecorationEnd() - { - if (window != null) - window.HandleWindowDecorationEnd(windowPosition); - } - } -} //namespace diff --git a/Editor/Mono/GameObjectUtility.bindings.cs b/Editor/Mono/GameObjectUtility.bindings.cs deleted file mode 100644 index 44e068d506..0000000000 --- a/Editor/Mono/GameObjectUtility.bindings.cs +++ /dev/null @@ -1,132 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeHeader("Editor/Mono/GameObjectUtility.bindings.h")] - public sealed partial class GameObjectUtility - { - public static extern StaticEditorFlags GetStaticEditorFlags(GameObject go); - public static extern void SetStaticEditorFlags(GameObject go, StaticEditorFlags flags); - public static extern bool AreStaticEditorFlagsSet(GameObject go, StaticEditorFlags flags); - - public static extern int GetNavMeshArea(GameObject go); - public static extern void SetNavMeshArea(GameObject go, int areaIndex); - - public static extern int GetNavMeshAreaFromName(string name); - public static extern string[] GetNavMeshAreaNames(); - - public static extern string GetUniqueNameForSibling(Transform parent, string name); - - internal static bool ContainsStatic(GameObject[] objects) - { - if (objects == null || objects.Length == 0) - return false; - for (int i = 0; i < objects.Length; i++) - { - if (objects[i] != null && objects[i].isStatic) - return true; - } - return false; - } - - internal static bool HasChildren(IEnumerable gameObjects) - { - return gameObjects.Any(go => go.transform.childCount > 0); - } - - internal enum ShouldIncludeChildren - { - HasNoChildren = -1, - IncludeChildren = 0, - DontIncludeChildren = 1, - Cancel = 2 - } - - internal static ShouldIncludeChildren DisplayUpdateChildrenDialogIfNeeded(IEnumerable gameObjects, - string title, string message) - { - if (!HasChildren(gameObjects)) - return ShouldIncludeChildren.HasNoChildren; - - return - (ShouldIncludeChildren) - EditorUtility.DisplayDialogComplex(title, message, "Yes, change children", "No, this object only", "Cancel"); - } - - public static void SetParentAndAlign(GameObject child, GameObject parent) - { - if (parent == null) - return; - - child.transform.SetParent(parent.transform, false); - - RectTransform rectTransform = child.transform as RectTransform; - if (rectTransform) - { - rectTransform.anchoredPosition = Vector2.zero; - Vector3 localPosition = rectTransform.localPosition; - localPosition.z = 0; - rectTransform.localPosition = localPosition; - } - else - { - child.transform.localPosition = Vector3.zero; - } - child.transform.localRotation = Quaternion.identity; - child.transform.localScale = Vector3.one; - - SetLayerRecursively(child, parent.layer); - } - - private static void SetLayerRecursively(GameObject go, int layer) - { - go.layer = layer; - Transform t = go.transform; - for (int i = 0; i < t.childCount; i++) - SetLayerRecursively(t.GetChild(i).gameObject, layer); - } - - [System.Obsolete("GetNavMeshArea instead.")] - public static int GetNavMeshLayer(GameObject go) - { - return GetNavMeshArea(go); - } - - [System.Obsolete("SetNavMeshArea instead.")] - public static void SetNavMeshLayer(GameObject go, int areaIndex) - { - SetNavMeshArea(go, areaIndex); - } - - [System.Obsolete("GetNavMeshAreaFromName instead.")] - public static int GetNavMeshLayerFromName(string name) - { - return GetNavMeshAreaFromName(name); - } - - [System.Obsolete("GetNavMeshAreaNames instead.")] - public static string[] GetNavMeshLayerNames() - { - return GetNavMeshAreaNames(); - } - - [System.Obsolete("use AnimatorUtility.OptimizeTransformHierarchy instead.")] - static void OptimizeTransformHierarchy(GameObject go) - { - AnimatorUtility.OptimizeTransformHierarchy(go, null); - } - - [System.Obsolete("use AnimatorUtility.DeoptimizeTransformHierarchy instead.")] - static void DeoptimizeTransformHierarchy(GameObject go) - { - AnimatorUtility.DeoptimizeTransformHierarchy(go); - } - } -} diff --git a/Editor/Mono/GameView/GameView.cs b/Editor/Mono/GameView/GameView.cs deleted file mode 100644 index 4e6842e7c2..0000000000 --- a/Editor/Mono/GameView/GameView.cs +++ /dev/null @@ -1,856 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEditorInternal; -using UnityEditor.AnimatedValues; -using UnityEditor.SceneManagement; -using UnityEditor.Modules; -using UnityEngine.Scripting; - -/* -The main GameView can be in the following states when entering playmode. -These states should be tested when changing the behavior when entering playmode. - - - GameView docked and visible - GameView docked and visible and maximizeOnPlay - GameView docked and hidden - GameView docked and hidden and maximizeOnPlay - GameView docked and hidden and resized - Maximized GameView (maximized from start) - No GameView but a SceneView exists - No GameView and no SceneView exists - Floating GameView in separate window -*/ - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Game", useTypeNameAsIconName = true)] - internal class GameView : EditorWindow, IHasCustomMenu, IGameViewSizeMenuUser - { - const int kBorderSize = 5; - const int kScaleSliderMinWidth = 30; - const int kScaleSliderMaxWidth = 150; - const int kScaleSliderSnapThreshold = 4; - const int kScaleLabelWidth = 30; - readonly Vector2 kWarningSize = new Vector2(400f, 140f); - readonly Color kClearBlack = new Color(0, 0 , 0, 0); - const float kMinScale = 1f; - const float kMaxScale = 5f; - const float kScrollZoomSnapDelay = 0.2f; - - float minScale - { - get - { - var clampedMinScale = Mathf.Min(kMinScale, ScaleThatFitsTargetInView(targetSize, viewInWindow.size)); - if (m_LowResolutionForAspectRatios[(int)currentSizeGroupType] && currentGameViewSize.sizeType == GameViewSizeType.AspectRatio) - clampedMinScale = Mathf.Max(clampedMinScale, EditorGUIUtility.pixelsPerPoint); - return clampedMinScale; - } - } - float maxScale - { - get { return Mathf.Max(kMaxScale * EditorGUIUtility.pixelsPerPoint, ScaleThatFitsTargetInView(targetSize, viewInWindow.size)); } - } - - [SerializeField] bool m_MaximizeOnPlay; - [SerializeField] bool m_Gizmos; - [SerializeField] bool m_Stats; - [SerializeField] int[] m_SelectedSizes = new int[0]; // We have a selection for each game view size group (e.g standalone, android etc) - [SerializeField] int m_TargetDisplay; - - [SerializeField] ZoomableArea m_ZoomArea; - [SerializeField] float m_defaultScale = -1f; - - [SerializeField] RenderTexture m_TargetTexture; - bool m_TargetClamped; - [SerializeField] ColorSpace m_CurrentColorSpace = ColorSpace.Uninitialized; - - [SerializeField] Vector2 m_LastWindowPixelSize; - - [SerializeField] bool m_ClearInEditMode = true; - [SerializeField] bool m_NoCameraWarning = true; - [SerializeField] bool[] m_LowResolutionForAspectRatios = new bool[0]; - - int m_SizeChangeID = int.MinValue; - - - internal static class Styles - { - public static GUIContent gizmosContent = EditorGUIUtility.TrTextContent("Gizmos"); - public static GUIContent zoomSliderContent = EditorGUIUtility.TrTextContent("Scale", "Size of the game view on the screen."); - public static GUIContent maximizeOnPlayContent = EditorGUIUtility.TrTextContent("Maximize On Play"); - public static GUIContent muteContent = EditorGUIUtility.TrTextContent("Mute Audio"); - public static GUIContent statsContent = EditorGUIUtility.TrTextContent("Stats"); - public static GUIContent frameDebuggerOnContent = EditorGUIUtility.TrTextContent("Frame Debugger On"); - public static GUIContent loadRenderDocContent = EditorGUIUtility.TrTextContent("Load RenderDoc"); - public static GUIContent noCameraWarningContextMenuContent = EditorGUIUtility.TrTextContent("Warn if No Cameras Rendering"); - public static GUIContent clearEveryFrameContextMenuContent = EditorGUIUtility.TrTextContent("Clear Every Frame in Edit Mode"); - public static GUIContent lowResAspectRatiosContextMenuContent = EditorGUIUtility.TrTextContent("Low Resolution Aspect Ratios"); - public static GUIContent renderdocContent; - public static GUIStyle gizmoButtonStyle; - public static GUIStyle gameViewBackgroundStyle; - - static Styles() - { - gameViewBackgroundStyle = (GUIStyle)"GameViewBackground"; - gizmoButtonStyle = (GUIStyle)"GV Gizmo DropDown"; - renderdocContent = EditorGUIUtility.TrIconContent("renderdoc", "Capture the current view and open in RenderDoc."); - } - }; - - static List s_GameViews = new List(); - static GameView s_LastFocusedGameView = null; - static double s_LastScrollTime; - - public GameView() - { - autoRepaintOnSceneChange = true; - m_TargetDisplay = 0; - InitializeZoomArea(); - } - - public bool lowResolutionForAspectRatios - { - get - { - EnsureSelectedSizeAreValid(); - return m_LowResolutionForAspectRatios[(int)currentSizeGroupType]; - } - set - { - EnsureSelectedSizeAreValid(); - if (value != m_LowResolutionForAspectRatios[(int)currentSizeGroupType]) - { - m_LowResolutionForAspectRatios[(int)currentSizeGroupType] = value; - UpdateZoomAreaAndParent(); - } - } - } - - public bool forceLowResolutionAspectRatios { get { return EditorGUIUtility.pixelsPerPoint == 1f; } } - public bool showLowResolutionToggle { get { return EditorApplication.supportsHiDPI; } } - - public bool maximizeOnPlay - { - get { return m_MaximizeOnPlay; } - set { m_MaximizeOnPlay = value; } - } - - int selectedSizeIndex - { - get - { - EnsureSelectedSizeAreValid(); - return m_SelectedSizes[(int)currentSizeGroupType]; - } - set - { - EnsureSelectedSizeAreValid(); - m_SelectedSizes[(int)currentSizeGroupType] = value; - } - } - - static GameViewSizeGroupType currentSizeGroupType - { - get { return GameViewSizes.instance.currentGroupType; } - } - - GameViewSize currentGameViewSize - { - get { return GameViewSizes.instance.currentGroup.GetGameViewSize(selectedSizeIndex); } - } - - // The area of the window that the rendered game view is limited to - Rect viewInWindow { get { return new Rect(0, EditorGUI.kWindowToolbarHeight, position.width, position.height - EditorGUI.kWindowToolbarHeight); } } - - internal Vector2 targetSize // Size of render target in pixels - { - get - { - var viewPixelRect = lowResolutionForAspectRatios ? viewInWindow : EditorGUIUtility.PointsToPixels(viewInWindow); - return GameViewSizes.GetRenderTargetSize(viewPixelRect, currentSizeGroupType, selectedSizeIndex, out m_TargetClamped); - } - } - - // Area of the render target in zoom content space (it is centered in content space) - Rect targetInContent - { - get - { - var targetSizeCached = targetSize; - return EditorGUIUtility.PixelsToPoints(new Rect(-0.5f * targetSizeCached, targetSizeCached)); - } - } - - Rect targetInView // Area of the render target in zoom view space - { - get - { - var targetInContentCached = targetInContent; - return new Rect( - m_ZoomArea.DrawingToViewTransformPoint(targetInContentCached.position), - m_ZoomArea.DrawingToViewTransformVector(targetInContentCached.size) - ); - } - } - - // The final image needs to be flipped upside-down if we use coordinates with zero at the top - Rect deviceFlippedTargetInView - { - get - { - if (!SystemInfo.graphicsUVStartsAtTop) - return targetInView; - else - { - var flippedTarget = targetInView; - flippedTarget.y += flippedTarget.height; - flippedTarget.height = -flippedTarget.height; - return flippedTarget; - } - } - } - - Rect viewInParent // The view area in parent view space - { - get - { - var viewInParent = viewInWindow; - var parentBorder = m_Parent.borderSize; - viewInParent.x += parentBorder.left; - // Note: DockArea has extra space on top of the tab area which is accounted for strangely. - // It is stored in borderSize.bottom but it should be added to the top instead - // @TODO: Make DockArea.borderSize more sensible (requires fixing all usages) - viewInParent.y += parentBorder.top + parentBorder.bottom; - return viewInParent; - } - } - - Rect targetInParent // Area of the render target in parent view space - { - get - { - var targetInViewCached = targetInView; - return new Rect(targetInViewCached.position + viewInParent.position, targetInViewCached.size); - } - } - - Rect clippedTargetInParent // targetInParent, but clipped to viewInParent to discard outside mouse events - { - get - { - var targetInParentCached = targetInParent; - var viewInParentCached = viewInParent; - var clippedTargetInParent = Rect.MinMaxRect( - Mathf.Max(targetInParentCached.xMin, viewInParentCached.xMin), - Mathf.Max(targetInParentCached.yMin, viewInParentCached.yMin), - Mathf.Min(targetInParentCached.xMax, viewInParentCached.xMax), - Mathf.Min(targetInParentCached.yMax, viewInParentCached.yMax) - ); - return clippedTargetInParent; - } - } - - // Area for warnings such as no cameras rendering - Rect warningPosition { get { return new Rect((viewInWindow.size - kWarningSize) * 0.5f, kWarningSize); } } - - Vector2 gameMouseOffset { get { return -viewInWindow.position - targetInView.position; } } - - float gameMouseScale { get { return EditorGUIUtility.pixelsPerPoint / m_ZoomArea.scale.y; } } - - Vector2 WindowToGameMousePosition(Vector2 windowMousePosition) - { - return (windowMousePosition + gameMouseOffset) * gameMouseScale; - } - - void InitializeZoomArea() - { - m_ZoomArea = new ZoomableArea(true, false); - m_ZoomArea.uniformScale = true; - m_ZoomArea.upDirection = ZoomableArea.YDirection.Negative; - } - - public void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - UpdateZoomAreaAndParent(); - dontClearBackground = true; - s_GameViews.Add(this); - } - - public void OnDisable() - { - s_GameViews.Remove(this); - if (m_TargetTexture) - { - DestroyImmediate(m_TargetTexture); - } - } - - internal static GameView GetMainGameView() - { - if (s_LastFocusedGameView == null && s_GameViews != null && s_GameViews.Count > 0) - s_LastFocusedGameView = s_GameViews[0]; - - return s_LastFocusedGameView; - } - - public static void RepaintAll() - { - if (s_GameViews == null) - return; - - foreach (GameView gv in s_GameViews) - gv.Repaint(); - } - - // This is here because NGUI uses it via reflection (noted in https://confluence.hq.unity3d.com/display/DEV/Game+View+Bucket) - internal static Vector2 GetSizeOfMainGameView() - { - return GetMainGameViewTargetSize(); - } - - internal static Vector2 GetMainGameViewTargetSize() - { - var gameView = GetMainGameView(); - // It's possible with a corrupted layout that a GameView doesn't have a parent view. - if (gameView != null && gameView.m_Parent) - return gameView.targetSize; - else - return new Vector2(640f, 480f); - } - - [RequiredByNativeCode] - private static void GetMainGameViewTargetSizeNoBox(out Vector2 result) - { - result = GetMainGameViewTargetSize(); - } - - private void UpdateZoomAreaAndParent() - { - // Configure ZoomableArea for new resolution so that old resolution doesn't restrict scale - bool oldScaleWasDefault = Mathf.Approximately(m_ZoomArea.scale.y, m_defaultScale); - ConfigureZoomArea(); - m_defaultScale = DefaultScaleForTargetInView(targetSize, viewInWindow.size); - if (oldScaleWasDefault) - { - m_ZoomArea.SetTransform(Vector2.zero, Vector2.one * m_defaultScale); - EnforceZoomAreaConstraints(); - } - - CopyDimensionsToParentView(); - m_LastWindowPixelSize = position.size * EditorGUIUtility.pixelsPerPoint; - EditorApplication.SetSceneRepaintDirty(); - } - - void AllowCursorLockAndHide(bool enable) - { - Unsupported.SetAllowCursorLock(enable, Unsupported.DisallowCursorLockReasons.Other); - Unsupported.SetAllowCursorHide(enable); - } - - private void OnFocus() - { - AllowCursorLockAndHide(true); - s_LastFocusedGameView = this; - InternalEditorUtility.OnGameViewFocus(true); - } - - private void OnLostFocus() - { - // We unlock the cursor when the game view loses focus to allow the user to regain cursor control. - // Fix for 389362: Ensure that we do not unlock cursor during init of play mode. Because we could - // be maximizing game view, which causes a lostfocus on the original game view, in these situations we do - // not unlock cursor. - if (!EditorApplicationLayout.IsInitializingPlaymodeLayout()) - { - AllowCursorLockAndHide(false); - } - - InternalEditorUtility.OnGameViewFocus(false); - } - - internal void CopyDimensionsToParentView() - { - if (m_Parent) - SetParentGameViewDimensions(targetInParent, clippedTargetInParent, targetSize); - } - - // Call when number of available aspects can have changed (after deserialization or gui change) - private void EnsureSelectedSizeAreValid() - { - // Early out if no change was recorded - if (GameViewSizes.instance.GetChangeID() == m_SizeChangeID) - return; - - m_SizeChangeID = GameViewSizes.instance.GetChangeID(); - - var sizeGroupTypes = System.Enum.GetValues(typeof(GameViewSizeGroupType)); - // Ensure deserialized array is resized if needed - if (m_SelectedSizes.Length != sizeGroupTypes.Length) - System.Array.Resize(ref m_SelectedSizes, sizeGroupTypes.Length); - - // Ensure deserialized selection index for each group is within valid range - foreach (GameViewSizeGroupType groupType in sizeGroupTypes) - { - var gvsg = GameViewSizes.instance.GetGroup(groupType); - var index = (int)groupType; - m_SelectedSizes[index] = Mathf.Clamp(m_SelectedSizes[index], 0, gvsg.GetTotalCount() - 1); - } - - // Resize low resolution array as necessary, and fill in new indices with defaults - var lowResolutionSettingsLength = m_LowResolutionForAspectRatios.Length; - if (m_LowResolutionForAspectRatios.Length != sizeGroupTypes.Length) - System.Array.Resize(ref m_LowResolutionForAspectRatios, sizeGroupTypes.Length); - for (var groupIndex = lowResolutionSettingsLength; groupIndex < sizeGroupTypes.Length; ++groupIndex) - m_LowResolutionForAspectRatios[groupIndex] = GameViewSizes.DefaultLowResolutionSettingForSizeGroupType((GameViewSizeGroupType)sizeGroupTypes.GetValue(groupIndex)); - } - - public bool IsShowingGizmos() - { - return m_Gizmos; - } - - private void OnSelectionChange() - { - if (m_Gizmos) - Repaint(); - } - - private void LoadRenderDoc() - { - if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) - { - RenderDoc.Load(); - ShaderUtil.RecreateGfxDevice(); - } - } - - public virtual void AddItemsToMenu(GenericMenu menu) - { - if (RenderDoc.IsInstalled() && !RenderDoc.IsLoaded()) - { - menu.AddItem(Styles.loadRenderDocContent, false, LoadRenderDoc); - } - menu.AddItem(Styles.noCameraWarningContextMenuContent, m_NoCameraWarning, ToggleNoCameraWarning); - menu.AddItem(Styles.clearEveryFrameContextMenuContent, m_ClearInEditMode, ToggleClearInEditMode); - } - - private void ToggleNoCameraWarning() - { - m_NoCameraWarning = !m_NoCameraWarning; - } - - private void ToggleClearInEditMode() - { - m_ClearInEditMode = !m_ClearInEditMode; - } - - public void SizeSelectionCallback(int indexClicked, object objectSelected) - { - if (indexClicked != selectedSizeIndex) - { - selectedSizeIndex = indexClicked; - dontClearBackground = true; // will cause re-clear - UpdateZoomAreaAndParent(); - } - } - - void SnapZoomDelayed() - { - if (EditorApplication.timeSinceStartup > s_LastScrollTime + kScrollZoomSnapDelay) - { - EditorApplication.update -= SnapZoomDelayed; - SnapZoom(m_ZoomArea.scale.y); - Repaint(); - } - } - - void SnapZoom(float newZoom) - { - var logScale = Mathf.Log10(newZoom); - var logMin = Mathf.Log10(minScale); - var logMax = Mathf.Log10(maxScale); - var shortestSliderDistance = System.Single.MaxValue; - if (logScale > logMin && logScale < logMax) - { - for (var i = 1; i <= maxScale; ++i) - { - // Snap distance is defined in points, so convert difference back to UI space - var sliderDistanceToI = kScaleSliderMaxWidth * Mathf.Abs(logScale - Mathf.Log10(i)) / (logMax - logMin); - if (sliderDistanceToI < kScaleSliderSnapThreshold && sliderDistanceToI < shortestSliderDistance) - { - newZoom = i; - shortestSliderDistance = sliderDistanceToI; - } - } - } - - var areaInMargins = m_ZoomArea.shownAreaInsideMargins; - var focalPoint = areaInMargins.position + areaInMargins.size * 0.5f; - m_ZoomArea.SetScaleFocused(focalPoint, Vector2.one * newZoom); - } - - void DoZoomSlider() - { - GUILayout.Label(Styles.zoomSliderContent, EditorStyles.miniLabel); - EditorGUI.BeginChangeCheck(); - // Zooming feels more natural on a log scale - var logScale = Mathf.Log10(m_ZoomArea.scale.y); - var logMin = Mathf.Log10(minScale); - var logMax = Mathf.Log10(maxScale); - logScale = GUILayout.HorizontalSlider(logScale, logMin, logMax, GUILayout.MaxWidth(kScaleSliderMaxWidth), GUILayout.MinWidth(kScaleSliderMinWidth)); - if (EditorGUI.EndChangeCheck()) - { - var newZoom = Mathf.Pow(10f, logScale); - SnapZoom(newZoom); - } - var scaleContent = EditorGUIUtility.TempContent(string.Format("{0}x", (m_ZoomArea.scale.y).ToString("G2"))); - scaleContent.tooltip = Styles.zoomSliderContent.tooltip; - GUILayout.Label(scaleContent, EditorStyles.miniLabel, GUILayout.Width(kScaleLabelWidth)); - scaleContent.tooltip = string.Empty; - } - - private void DoToolbarGUI() - { - GameViewSizes.instance.RefreshStandaloneAndRemoteDefaultSizes(); - - GUILayout.BeginHorizontal(EditorStyles.toolbar); - { - if (ModuleManager.ShouldShowMultiDisplayOption()) - { - int display = EditorGUILayout.Popup(m_TargetDisplay, DisplayUtility.GetDisplayNames(), EditorStyles.toolbarPopup, GUILayout.Width(80)); - EditorGUILayout.Space(); - if (display != m_TargetDisplay) - { - m_TargetDisplay = display; - UpdateZoomAreaAndParent(); - } - } - EditorGUILayout.GameViewSizePopup(currentSizeGroupType, selectedSizeIndex, this, EditorStyles.toolbarPopup, GUILayout.Width(160f)); - - DoZoomSlider(); - - if (FrameDebuggerUtility.IsLocalEnabled()) - { - GUILayout.FlexibleSpace(); - Color oldCol = GUI.color; - // This has nothing to do with animation recording. Can we replace this color with something else? - GUI.color *= AnimationMode.recordedPropertyColor; - GUILayout.Label(Styles.frameDebuggerOnContent, EditorStyles.miniLabel); - GUI.color = oldCol; - // Make frame debugger windows repaint after each time game view repaints. - // We want them to always display the latest & greatest game view - // rendering state. - if (Event.current.type == EventType.Repaint) - FrameDebuggerWindow.RepaintAll(); - } - - GUILayout.FlexibleSpace(); - - if (RenderDoc.IsLoaded()) - { - using (new EditorGUI.DisabledScope(!RenderDoc.IsSupported())) - { - if (GUILayout.Button(Styles.renderdocContent, EditorStyles.toolbarButton)) - { - m_Parent.CaptureRenderDoc(); - GUIUtility.ExitGUI(); - } - } - } - - m_MaximizeOnPlay = GUILayout.Toggle(m_MaximizeOnPlay, Styles.maximizeOnPlayContent, EditorStyles.toolbarButton); - EditorUtility.audioMasterMute = GUILayout.Toggle(EditorUtility.audioMasterMute, Styles.muteContent, EditorStyles.toolbarButton); - m_Stats = GUILayout.Toggle(m_Stats, Styles.statsContent, EditorStyles.toolbarButton); - - Rect r = GUILayoutUtility.GetRect(Styles.gizmosContent, Styles.gizmoButtonStyle); - Rect rightRect = new Rect(r.xMax - Styles.gizmoButtonStyle.border.right, r.y, Styles.gizmoButtonStyle.border.right, r.height); - if (EditorGUI.DropdownButton(rightRect, GUIContent.none, FocusType.Passive, GUIStyle.none)) - { - Rect rect = GUILayoutUtility.topLevel.GetLast(); - if (AnnotationWindow.ShowAtPosition(rect, true)) - { - GUIUtility.ExitGUI(); - } - } - m_Gizmos = GUI.Toggle(r, m_Gizmos, Styles.gizmosContent, Styles.gizmoButtonStyle); - } - GUILayout.EndHorizontal(); - } - - private void ClearTargetTexture() - { - if (m_TargetTexture.IsCreated()) - { - var previousTarget = RenderTexture.active; - RenderTexture.active = m_TargetTexture; - GL.Clear(true, true, kClearBlack); - RenderTexture.active = previousTarget; - } - } - - private void ConfigureTargetTexture(int width, int height) - { - var clearTexture = false; - // Changing color space requires destroying the entire RT object and recreating it - if (m_TargetTexture && m_CurrentColorSpace != QualitySettings.activeColorSpace) - { - DestroyImmediate(m_TargetTexture); - } - if (!m_TargetTexture) - { - m_CurrentColorSpace = QualitySettings.activeColorSpace; - m_TargetTexture = new RenderTexture(0, 0, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB); - m_TargetTexture.name = "GameView RT"; - m_TargetTexture.filterMode = FilterMode.Point; - m_TargetTexture.hideFlags = HideFlags.HideAndDontSave; - } - - // Changes to these attributes require a release of the texture - if (m_TargetTexture.width != width || m_TargetTexture.height != height) - { - m_TargetTexture.Release(); - m_TargetTexture.width = width; - m_TargetTexture.height = height; - m_TargetTexture.antiAliasing = 1; - clearTexture = true; - if (m_TargetClamped) - Debug.LogWarningFormat("GameView reduced to a reasonable size for this system ({0}x{1})", width, height); - } - - m_TargetTexture.Create(); - - if (clearTexture) - { - ClearTargetTexture(); - } - } - - private float ScaleThatFitsTargetInView(Vector2 targetInPixels, Vector2 viewInPoints) - { - var targetInPoints = EditorGUIUtility.PixelsToPoints(targetInPixels); - var viewToTargetRatio = new Vector2(viewInPoints.x / targetInPoints.x, viewInPoints.y / targetInPoints.y); - return Mathf.Min(viewToTargetRatio.x, viewToTargetRatio.y); - } - - private float DefaultScaleForTargetInView(Vector2 targetToFit, Vector2 viewSize) - { - var scale = ScaleThatFitsTargetInView(targetToFit, viewSize); - if (scale > 1f) - { - scale = Mathf.Min(maxScale * EditorGUIUtility.pixelsPerPoint, Mathf.FloorToInt(scale)); - } - return scale; - } - - private void ConfigureZoomArea() - { - m_ZoomArea.rect = viewInWindow; - // Sliders are sized with respect to canvas - var targetInContentCached = targetInContent; - m_ZoomArea.hBaseRangeMin = targetInContentCached.xMin; - m_ZoomArea.vBaseRangeMin = targetInContentCached.yMin; - m_ZoomArea.hBaseRangeMax = targetInContentCached.xMax; - m_ZoomArea.vBaseRangeMax = targetInContentCached.yMax; - // Restrict zooming - m_ZoomArea.hScaleMin = m_ZoomArea.vScaleMin = minScale; - m_ZoomArea.hScaleMax = m_ZoomArea.vScaleMax = maxScale; - } - - private void EnforceZoomAreaConstraints() - { - var shownArea = m_ZoomArea.shownArea; - var targetInContentCached = targetInContent; - - // When zoomed out, we disallow panning by automatically centering the view - if (shownArea.width > targetInContentCached.width) - { - shownArea.x = -0.5f * shownArea.width; - } - else - // When zoomed in, we prevent panning outside the render area - { - shownArea.x = Mathf.Clamp(shownArea.x, targetInContentCached.xMin, targetInContentCached.xMax - shownArea.width); - } - // Horizontal and vertical are separated because otherwise we get weird behaviour when only one is zoomed out - if (shownArea.height > targetInContent.height) - { - shownArea.y = -0.5f * shownArea.height; - } - else - { - shownArea.y = Mathf.Clamp(shownArea.y, targetInContentCached.yMin, targetInContentCached.yMax - shownArea.height); - } - - m_ZoomArea.shownArea = shownArea; - } - - private void OnGUI() - { - if (position.size * EditorGUIUtility.pixelsPerPoint != m_LastWindowPixelSize) // pixelsPerPoint only reliable in OnGUI() - { - UpdateZoomAreaAndParent(); - } - - DoToolbarGUI(); - - // Setup game view dimensions, so that player loop can use it for input - CopyDimensionsToParentView(); - - // This isn't ideal. Custom Cursors set by editor extensions for other windows can leak into the game view. - // To fix this we should probably stop using the global custom cursor (intended for runtime) for custom editor cursors. - // This has been noted for Cursors tech debt. - EditorGUIUtility.AddCursorRect(viewInWindow, MouseCursor.CustomCursor); - - EventType type = Event.current.type; - - // Gain mouse lock when clicking on game view content - if (type == EventType.MouseDown && viewInWindow.Contains(Event.current.mousePosition)) - { - AllowCursorLockAndHide(true); - } - // Lose mouse lock when pressing escape - else if (type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - { - AllowCursorLockAndHide(false); - } - - // We hide sliders when playing, and also when we are zoomed out beyond canvas edges - var playing = EditorApplication.isPlaying && !EditorApplication.isPaused; - var targetInContentCached = targetInContent; - m_ZoomArea.hSlider = !playing && m_ZoomArea.shownArea.width < targetInContentCached.width; - m_ZoomArea.vSlider = !playing && m_ZoomArea.shownArea.height < targetInContentCached.height; - m_ZoomArea.enableMouseInput = !playing; - ConfigureZoomArea(); - - // We don't want controls inside the GameView (e.g. the toolbar) to have keyboard focus while playing. - // The game should get the keyboard events. - if (playing) - EditorGUIUtility.keyboardControl = 0; - - var editorMousePosition = Event.current.mousePosition; - var gameMousePosition = WindowToGameMousePosition(editorMousePosition); - - GUI.color = Color.white; // Get rid of play mode tint - - var originalEventType = Event.current.type; - - m_ZoomArea.BeginViewGUI(); - - if (type == EventType.Repaint) - { - GUI.Box(m_ZoomArea.drawRect, GUIContent.none, Styles.gameViewBackgroundStyle); - - Vector2 oldOffset = GUIUtility.s_EditorScreenPointOffset; - GUIUtility.s_EditorScreenPointOffset = Vector2.zero; - SavedGUIState oldState = SavedGUIState.Create(); - - ConfigureTargetTexture((int)targetSize.x, (int)targetSize.y); - - if (m_ClearInEditMode && !EditorApplication.isPlaying) - ClearTargetTexture(); - - var currentTargetDisplay = 0; - if (ModuleManager.ShouldShowMultiDisplayOption()) - { - // Display Targets can have valid targets from 0 to 7. - System.Diagnostics.Debug.Assert(m_TargetDisplay < 8, "Display Target is Out of Range"); - currentTargetDisplay = m_TargetDisplay; - } - if (m_TargetTexture.IsCreated()) - { - EditorGUIUtility.RenderGameViewCamerasInternal(m_TargetTexture, currentTargetDisplay, GUIClip.Unclip(viewInWindow), gameMousePosition, m_Gizmos); - oldState.ApplyAndForget(); - GUIUtility.s_EditorScreenPointOffset = oldOffset; - - GUI.BeginGroup(m_ZoomArea.drawRect); - // Actually draw the game view to the screen, without alpha blending - Graphics.DrawTexture(deviceFlippedTargetInView, m_TargetTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, GUI.blitMaterial); - GUI.EndGroup(); - } - } - else if (type != EventType.Layout && type != EventType.Used) - { - if (WindowLayout.s_MaximizeKey.activated) - { - if (!EditorApplication.isPlaying || EditorApplication.isPaused) - return; - } - - bool mousePosInGameViewRect = viewInWindow.Contains(Event.current.mousePosition); - - // MouseDown events outside game view rect are not send to scripts but MouseUp events are (see below) - if (Event.current.rawType == EventType.MouseDown && !mousePosInGameViewRect) - return; - - var originalDisplayIndex = Event.current.displayIndex; - - // Transform events into local space, so the mouse position is correct - // Then queue it up for playback during playerloop - Event.current.mousePosition = gameMousePosition; - Event.current.displayIndex = m_TargetDisplay; - - EditorGUIUtility.QueueGameViewInputEvent(Event.current); - - bool useEvent = true; - - // Do not use mouse UP event if mousepos is outside game view rect (fix for case 380995: Gameview tab's context menu is not appearing on right click) - // Placed after event queueing above to ensure scripts can react on mouse up events. - if (Event.current.rawType == EventType.MouseUp && !mousePosInGameViewRect) - useEvent = false; - - // Don't use command events, or they won't be sent to other views. - if (type == EventType.ExecuteCommand || type == EventType.ValidateCommand) - useEvent = false; - - if (useEvent) - Event.current.Use(); - else - Event.current.mousePosition = editorMousePosition; - - // Reset display index - Event.current.displayIndex = originalDisplayIndex; - } - - m_ZoomArea.EndViewGUI(); - - if (originalEventType == EventType.ScrollWheel && Event.current.type == EventType.Used) - { - EditorApplication.update -= SnapZoomDelayed; - EditorApplication.update += SnapZoomDelayed; - s_LastScrollTime = EditorApplication.timeSinceStartup; - } - - EnforceZoomAreaConstraints(); - - if (m_TargetTexture) - { - if (m_ZoomArea.scale.y < 1f) - { - m_TargetTexture.filterMode = FilterMode.Bilinear; - } - else - { - m_TargetTexture.filterMode = FilterMode.Point; - } - } - - if (m_NoCameraWarning && !EditorGUIUtility.IsDisplayReferencedByCameras(m_TargetDisplay)) - { - GUI.Label(warningPosition, GUIContent.none, EditorStyles.notificationBackground); - var displayName = ModuleManager.ShouldShowMultiDisplayOption() ? DisplayUtility.GetDisplayNames()[m_TargetDisplay].text : string.Empty; - var cameraWarning = string.Format("{0}\nNo cameras rendering", displayName); - EditorGUI.DoDropShadowLabel(warningPosition, EditorGUIUtility.TempContent(cameraWarning), EditorStyles.notificationText, .3f); - } - - if (m_Stats) - GameViewGUI.GameViewStatsGUI(); - } - } -} diff --git a/Editor/Mono/GameView/GameViewSize.cs b/Editor/Mono/GameView/GameViewSize.cs deleted file mode 100644 index ce5c9e3855..0000000000 --- a/Editor/Mono/GameView/GameViewSize.cs +++ /dev/null @@ -1,171 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - -namespace UnityEditor -{ - internal enum GameViewSizeType - { - AspectRatio, - FixedResolution - }; - - [Serializable] - internal class GameViewSize - { - [SerializeField] string m_BaseText; - [SerializeField] GameViewSizeType m_SizeType; - [SerializeField] int m_Width; - [SerializeField] int m_Height; - [NonSerialized] string m_CachedDisplayText; - const int kMaxBaseTextLength = 40; - const int kMinResolution = 10; - const int kMinAspect = 0; - const int kMaxResolutionOrAspect = 99999; - - public string baseText - { - get {return m_BaseText; } - set - { - var oldBaseText = m_BaseText; - m_BaseText = value; - if (m_BaseText.Length > kMaxBaseTextLength) - m_BaseText = m_BaseText.Substring(0, kMaxBaseTextLength); - if (m_BaseText != oldBaseText) - Changed(); - } - } - public GameViewSizeType sizeType - { - get { return m_SizeType; } - set - { - var oldSizeType = m_SizeType; - m_SizeType = value; - Clamp(); - if (m_SizeType != oldSizeType) - Changed(); - } - } - public int width - { - get { return m_Width; } - set - { - var oldWidth = m_Width; - m_Width = value; - Clamp(); - if (m_Width != oldWidth) - Changed(); - } - } - public int height - { - get { return m_Height; } - set - { - var oldHeight = m_Height; - m_Height = value; - Clamp(); - if (m_Height != oldHeight) - Changed(); - } - } - - void Clamp() - { - int minValue = 0; - switch (sizeType) - { - case GameViewSizeType.AspectRatio: - minValue = kMinAspect; - break; - case GameViewSizeType.FixedResolution: - minValue = kMinResolution; - break; - default: - Debug.LogError("Unhandled enum!"); - break; - } - - m_Width = Mathf.Clamp(m_Width, minValue, kMaxResolutionOrAspect); - m_Height = Mathf.Clamp(m_Height, minValue, kMaxResolutionOrAspect); - } - - public GameViewSize(GameViewSizeType type, int width, int height, string baseText) - { - this.sizeType = type; - this.width = width; - this.height = height; - this.baseText = baseText; - } - - public GameViewSize(GameViewSize other) - { - Set(other); - } - - public void Set(GameViewSize other) - { - sizeType = other.sizeType; - width = other.width; - height = other.height; - baseText = other.baseText; - } - - public bool isFreeAspectRatio - { - get { return (width == 0); } - } - - public float aspectRatio - { - get - { - if (height == 0) - return 0f; - return width / (float)height; - } - } - - public string displayText - { - get { return m_CachedDisplayText ?? (m_CachedDisplayText = ComposeDisplayString()); } - } - - private string sizeText - { - get - { - if (sizeType == GameViewSizeType.AspectRatio) - return string.Format("{0}:{1}", width, height); - else if (sizeType == GameViewSizeType.FixedResolution) - return string.Format("{0}x{1}", width, height); - - Debug.LogError("Unhandled game view size type"); - return ""; - } - } - - private string ComposeDisplayString() - { - if (width == 0 && height == 0) - return baseText; - - if (string.IsNullOrEmpty(baseText)) - return sizeText; - - return baseText + " (" + sizeText + ")"; - } - - private void Changed() - { - m_CachedDisplayText = null; - GameViewSizes.instance.Changed(); - } - } -} diff --git a/Editor/Mono/GameView/GameViewSizeGroup.cs b/Editor/Mono/GameView/GameViewSizeGroup.cs deleted file mode 100644 index b97cb0f1d5..0000000000 --- a/Editor/Mono/GameView/GameViewSizeGroup.cs +++ /dev/null @@ -1,118 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - [System.Serializable] - internal class GameViewSizeGroup - { - [System.NonSerialized] - private List m_Builtin = new List(); - - [SerializeField] - private List m_Custom = new List(); - - // Builtin sizes first then custom sizes - public GameViewSize GetGameViewSize(int index) - { - if (index < m_Builtin.Count) - return m_Builtin[index]; - - index -= m_Builtin.Count; - - if (index >= 0 && index < m_Custom.Count) - return m_Custom[index]; - - Debug.LogError("Invalid index " + (index + m_Builtin.Count) + " " + m_Builtin.Count + " " + m_Custom.Count); - return new GameViewSize(GameViewSizeType.AspectRatio, 0, 0, ""); - } - - public string[] GetDisplayTexts() - { - List displayList = new List(); - foreach (GameViewSize size in m_Builtin) - displayList.Add(size.displayText); - foreach (GameViewSize size in m_Custom) - displayList.Add(size.displayText); - return displayList.ToArray(); - } - - public int GetTotalCount() - { - return m_Builtin.Count + m_Custom.Count; - } - - public int GetBuiltinCount() - { - return m_Builtin.Count; - } - - public int GetCustomCount() - { - return m_Custom.Count; - } - - public void AddBuiltinSizes(params GameViewSize[] sizes) - { - for (int i = 0; i < sizes.Length; i++) - AddBuiltinSize(sizes[i]); - } - - public void AddBuiltinSize(GameViewSize size) - { - m_Builtin.Add(size); - GameViewSizes.instance.Changed(); - } - - public void AddCustomSizes(params GameViewSize[] sizes) - { - for (int i = 0; i < sizes.Length; i++) - AddCustomSize(sizes[i]); - } - - public void AddCustomSize(GameViewSize size) - { - m_Custom.Add(size); - GameViewSizes.instance.Changed(); - } - - public void RemoveCustomSize(int index) - { - int customIndex = TotalIndexToCustomIndex(index); - if (customIndex >= 0 && customIndex < m_Custom.Count) - { - m_Custom.RemoveAt(customIndex); - GameViewSizes.instance.Changed(); - } - else - { - Debug.LogError("Invalid index " + index + " " + m_Builtin.Count + " " + m_Custom.Count); - } - } - - public bool IsCustomSize(int index) - { - if (index < m_Builtin.Count) - return false; - return true; - } - - public int TotalIndexToCustomIndex(int index) - { - return index - m_Builtin.Count; - } - - public int IndexOf(GameViewSize view) - { - int index = m_Builtin.IndexOf(view); - if (index >= 0) - return index; - - return m_Custom.IndexOf(view); - } - } -} diff --git a/Editor/Mono/GameView/GameViewSizeMenu.cs b/Editor/Mono/GameView/GameViewSizeMenu.cs deleted file mode 100644 index 0e911ffe86..0000000000 --- a/Editor/Mono/GameView/GameViewSizeMenu.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - -namespace UnityEditor -{ - // Resolution/Aspect ratio menu for the GameView, with an optional toggle for low-resolution aspect ratios - internal class GameViewSizeMenu : FlexibleMenu - { - const float kTopMargin = 7f; - const float kMargin = 9f; - IGameViewSizeMenuUser m_GameView; - - float frameHeight { get { return kTopMargin * 2 + EditorGUI.kSingleLineHeight; } } - float contentOffset { get { return frameHeight + EditorGUI.kControlVerticalSpacing; } } - - public GameViewSizeMenu(IFlexibleMenuItemProvider itemProvider, int selectionIndex, FlexibleMenuModifyItemUI modifyItemUi, IGameViewSizeMenuUser gameView) - : base(itemProvider, selectionIndex, modifyItemUi, gameView.SizeSelectionCallback) - { - m_GameView = gameView; - } - - public override Vector2 GetWindowSize() - { - var size = CalcSize(); - if (!m_GameView.showLowResolutionToggle) - return size; - size.y += frameHeight + EditorGUI.kControlVerticalSpacing; - return size; - } - - public override void OnGUI(Rect rect) - { - if (!m_GameView.showLowResolutionToggle) - { - base.OnGUI(rect); - return; - } - - var frameRect = new Rect(rect.x, rect.y, rect.width, frameHeight); - GUI.Label(frameRect, "", EditorStyles.inspectorBig); - - GUI.enabled = !m_GameView.forceLowResolutionAspectRatios; - - var toggleRect = new Rect(kMargin, kTopMargin, rect.width, EditorGUI.kSingleLineHeight); - m_GameView.lowResolutionForAspectRatios = GUI.Toggle(toggleRect, m_GameView.forceLowResolutionAspectRatios ? true : m_GameView.lowResolutionForAspectRatios, GameView.Styles.lowResAspectRatiosContextMenuContent); - - GUI.enabled = true; - - rect.height = rect.height - contentOffset; - rect.y = rect.y + contentOffset; - base.OnGUI(rect); - } - } -} // namespace diff --git a/Editor/Mono/GameView/GameViewSizes.cs b/Editor/Mono/GameView/GameViewSizes.cs deleted file mode 100644 index ca9c7ea361..0000000000 --- a/Editor/Mono/GameView/GameViewSizes.cs +++ /dev/null @@ -1,510 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using System; -using UnityEditor.Callbacks; - -namespace UnityEditor -{ - public enum GameViewSizeGroupType - { - Standalone, - [System.Obsolete("WebPlayer has been removed in 5.4")] - WebPlayer, - iOS, - Android, - [System.Obsolete("PS3 has been removed in 5.5", false)] - PS3, - [System.Obsolete("Wii U support was removed in 2018.1", false)] - WiiU, - Tizen, - [Obsolete("Windows Phone 8 was removed in 5.3", false)] - WP8, - N3DS, - HMD - } - - [FilePathAttribute("GameViewSizes.asset", FilePathAttribute.Location.PreferencesFolder)] - internal class GameViewSizes : ScriptableSingleton - { - // Written out to make it easy to find in text file (instead of an array) - [SerializeField] GameViewSizeGroup m_Standalone = new GameViewSizeGroup(); - [SerializeField] GameViewSizeGroup m_iOS = new GameViewSizeGroup(); - [SerializeField] GameViewSizeGroup m_Android = new GameViewSizeGroup(); - [SerializeField] GameViewSizeGroup m_Tizen = new GameViewSizeGroup(); - [SerializeField] GameViewSizeGroup m_N3DS = new GameViewSizeGroup(); - [SerializeField] GameViewSizeGroup m_HMD = new GameViewSizeGroup(); - - [NonSerialized] GameViewSize m_Remote = null; - [NonSerialized] Vector2 m_LastStandaloneScreenSize = new Vector2(-1, -1); - [NonSerialized] Vector2 m_LastRemoteScreenSize = new Vector2(-1, -1); - [NonSerialized] int m_ChangeID = 0; - [NonSerialized] static GameViewSizeGroupType s_GameViewSizeGroupType; - - public GameViewSizeGroupType currentGroupType - { - get { return s_GameViewSizeGroupType; } - } - - public GameViewSizeGroup currentGroup - { - get {return GetGroup(s_GameViewSizeGroupType); } - } - - private void OnEnable() - { - RefreshGameViewSizeGroupType(BuildTarget.NoTarget, EditorUserBuildSettings.activeBuildTarget); - } - - public GameViewSizeGroup GetGroup(GameViewSizeGroupType gameViewSizeGroupType) - { - InitBuiltinGroups(); - switch (gameViewSizeGroupType) - { -#pragma warning disable 618 - case GameViewSizeGroupType.WebPlayer: - case GameViewSizeGroupType.WP8: - case GameViewSizeGroupType.PS3: - case GameViewSizeGroupType.WiiU: -#pragma warning restore 618 - case GameViewSizeGroupType.Standalone: - return m_Standalone; - case GameViewSizeGroupType.iOS: - return m_iOS; - case GameViewSizeGroupType.Android: - return m_Android; - case GameViewSizeGroupType.Tizen: - return m_Tizen; - case GameViewSizeGroupType.N3DS: - return m_N3DS; - case GameViewSizeGroupType.HMD: - return m_HMD; - default: - Debug.LogError("Unhandled group enum! " + gameViewSizeGroupType); - break; - } - return m_Standalone; - } - - public void SaveToHDD() - { - bool saveAsText = true; - Save(saveAsText); - } - - public bool IsDefaultStandaloneScreenSize(GameViewSizeGroupType gameViewSizeGroupType, int index) - { - return gameViewSizeGroupType == GameViewSizeGroupType.Standalone && GetDefaultStandaloneIndex() == index; - } - - public bool IsRemoteScreenSize(GameViewSizeGroupType gameViewSizeGroupType, int index) - { - return GetGroup(gameViewSizeGroupType).IndexOf(m_Remote) == index; - } - - public int GetDefaultStandaloneIndex() - { - return m_Standalone.GetBuiltinCount() - 1; - } - - // returns true if screen size was changed - public void RefreshStandaloneAndRemoteDefaultSizes() - { - if (InternalEditorUtility.defaultScreenWidth != m_LastStandaloneScreenSize.x || - InternalEditorUtility.defaultScreenHeight != m_LastStandaloneScreenSize.y) - { - m_LastStandaloneScreenSize = new Vector2(InternalEditorUtility.defaultScreenWidth, - InternalEditorUtility.defaultScreenHeight); - RefreshStandaloneDefaultScreenSize((int)m_LastStandaloneScreenSize.x, (int)m_LastStandaloneScreenSize.y); - } - - if (InternalEditorUtility.remoteScreenWidth != m_LastRemoteScreenSize.x || - InternalEditorUtility.remoteScreenHeight != m_LastRemoteScreenSize.y) - { - m_LastRemoteScreenSize = new Vector2(InternalEditorUtility.remoteScreenWidth, - InternalEditorUtility.remoteScreenHeight); - RefreshRemoteScreenSize((int)m_LastRemoteScreenSize.x, (int)m_LastRemoteScreenSize.y); - } - - if (UnityEngine.XR.XRSettings.isDeviceActive && - m_Remote.width != UnityEngine.XR.XRSettings.eyeTextureWidth && - m_Remote.height != UnityEngine.XR.XRSettings.eyeTextureHeight) - { - RefreshRemoteScreenSize(UnityEngine.XR.XRSettings.eyeTextureWidth, UnityEngine.XR.XRSettings.eyeTextureHeight); - } - } - - public void RefreshStandaloneDefaultScreenSize(int width, int height) - { - GameViewSize gvs = m_Standalone.GetGameViewSize(GetDefaultStandaloneIndex()); - gvs.height = height; - gvs.width = width; - Changed(); - } - - public void RefreshRemoteScreenSize(int width, int height) - { - m_Remote.width = width; - m_Remote.height = height; - if (width > 0 && height > 0) - m_Remote.baseText = "Remote"; - else - m_Remote.baseText = "Remote (Not Connected)"; - Changed(); - } - - public void Changed() - { - m_ChangeID++; - } - - public int GetChangeID() - { - return m_ChangeID; - } - - private void InitBuiltinGroups() - { - bool isInitialized = m_Standalone.GetBuiltinCount() > 0; - if (isInitialized) - return; - - m_Remote = new GameViewSize(GameViewSizeType.FixedResolution, 0, 0, "Remote (Not Connected)"); - - // Shared - GameViewSize kFree = new GameViewSize(GameViewSizeType.AspectRatio, 0, 0, "Free Aspect"); - GameViewSize k5_4 = new GameViewSize(GameViewSizeType.AspectRatio, 5, 4, ""); - GameViewSize k4_3 = new GameViewSize(GameViewSizeType.AspectRatio, 4, 3, ""); - GameViewSize k3_2 = new GameViewSize(GameViewSizeType.AspectRatio, 3, 2, ""); - GameViewSize k16_10 = new GameViewSize(GameViewSizeType.AspectRatio, 16, 10, ""); - GameViewSize k16_9 = new GameViewSize(GameViewSizeType.AspectRatio, 16, 9, ""); - GameViewSize kStandalone = new GameViewSize(GameViewSizeType.FixedResolution, 0, 0, "Standalone"); - - // iOS - GameViewSize k_iPhoneTall = new GameViewSize(GameViewSizeType.FixedResolution, 320, 480, "iPhone Tall"); - GameViewSize k_iPhoneWide = new GameViewSize(GameViewSizeType.FixedResolution, 480, 320, "iPhone Wide"); - GameViewSize k_iPhone4GTall = new GameViewSize(GameViewSizeType.FixedResolution, 640, 960, "iPhone 4 Tall"); - GameViewSize k_iPhone4GWide = new GameViewSize(GameViewSizeType.FixedResolution, 960, 640, "iPhone 4 Wide"); - GameViewSize k_iPadTall = new GameViewSize(GameViewSizeType.FixedResolution, 768, 1024, "iPad Tall"); - GameViewSize k_iPadWide = new GameViewSize(GameViewSizeType.FixedResolution, 1024, 768, "iPad Wide"); - GameViewSize k_iPhone5Tall = new GameViewSize(GameViewSizeType.AspectRatio, 9, 16, "iPhone 5 Tall"); - GameViewSize k_iPhone5Wide = new GameViewSize(GameViewSizeType.AspectRatio, 16, 9, "iPhone 5 Wide"); - GameViewSize k_iPhoneTall2_3 = new GameViewSize(GameViewSizeType.AspectRatio, 2, 3, "iPhone Tall"); - GameViewSize k_iPhoneWide3_2 = new GameViewSize(GameViewSizeType.AspectRatio, 3, 2, "iPhone Wide"); - GameViewSize k_iPadTall3_4 = new GameViewSize(GameViewSizeType.AspectRatio, 3, 4, "iPad Tall"); - GameViewSize k_iPadWide4_3 = new GameViewSize(GameViewSizeType.AspectRatio, 4, 3, "iPad Wide"); - - // Android - GameViewSize k_HVGA_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 320, 480, "HVGA Portrait"); - GameViewSize k_HVGA_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 480, 320, "HVGA Landscape"); - GameViewSize k_WVGA_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 480, 800, "WVGA Portrait"); - GameViewSize k_WVGA_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 800, 480, "WVGA Landscape"); - GameViewSize k_FWVGA_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 480, 854, "FWVGA Portrait"); - GameViewSize k_FWVGA_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 854, 480, "FWVGA Landscape"); - GameViewSize k_WSVGA_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 600, 1024, "WSVGA Portrait"); - GameViewSize k_WSVGA_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 1024, 600, "WSVGA Landscape"); - GameViewSize k_WXGA_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 800, 1280, "WXGA Portrait"); - GameViewSize k_WXGA_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 1280, 800, "WXGA Landscape"); - GameViewSize k_3_2_Portrait = new GameViewSize(GameViewSizeType.AspectRatio, 2, 3, "3:2 Portrait"); - GameViewSize k_3_2_Landscape = new GameViewSize(GameViewSizeType.AspectRatio, 3, 2, "3:2 Landscape"); - GameViewSize k_16_10_Portrait = new GameViewSize(GameViewSizeType.AspectRatio, 10, 16, "16:10 Portrait"); - GameViewSize k_16_10_Landscape = new GameViewSize(GameViewSizeType.AspectRatio, 16, 10, "16:10 Landscape"); - - // Tizen - GameViewSize k_Tizen_720p_16_9 = new GameViewSize(GameViewSizeType.FixedResolution, 1280, 720, "16:9 Landscape"); - GameViewSize k_Tizen_720p_9_16 = new GameViewSize(GameViewSizeType.FixedResolution, 720, 1280, "9:16 Portrait"); - - // Nintendo 3DS - GameViewSize kN3DSTopScreen = new GameViewSize(GameViewSizeType.FixedResolution, 400, 240, "Top Screen"); - GameViewSize kN3DSBottomScreen = new GameViewSize(GameViewSizeType.FixedResolution, 320, 240, "Bottom Screen"); - - m_Standalone.AddBuiltinSizes(kFree, k5_4, k4_3, k3_2, k16_10, k16_9, kStandalone); - - m_iOS.AddBuiltinSizes(kFree, - k_iPhoneTall, k_iPhoneWide, - k_iPhone4GTall, k_iPhone4GWide, - k_iPadTall, k_iPadWide, - k_iPhone5Tall, k_iPhone5Wide, - k_iPhoneTall2_3, k_iPhoneWide3_2, - k_iPadTall3_4, k_iPadWide4_3); - m_Android.AddBuiltinSizes(kFree, m_Remote, - k_HVGA_Portrait, k_HVGA_Landscape, - k_WVGA_Portrait, k_WVGA_Landscape, - k_FWVGA_Portrait, k_FWVGA_Landscape, - k_WSVGA_Portrait, k_WSVGA_Landscape, - k_WXGA_Portrait, k_WXGA_Landscape, - k_3_2_Portrait, k_3_2_Landscape, - k_16_10_Portrait, k_16_10_Landscape); - m_Tizen.AddBuiltinSizes(kFree, - k_Tizen_720p_16_9, - k_Tizen_720p_9_16); - - m_N3DS.AddBuiltinSizes(kFree, kN3DSTopScreen, kN3DSBottomScreen); - - m_HMD.AddBuiltinSizes(kFree, m_Remote); - } - - internal static bool DefaultLowResolutionSettingForStandalone() - { - switch (EditorUserBuildSettings.activeBuildTarget) - { - case BuildTarget.StandaloneOSX: - return !PlayerSettings.macRetinaSupport; // if retina support enabled -> expecting LowRes setting disabled by default - default: - return true; - } - } - - internal static bool DefaultLowResolutionSettingForSizeGroupType(GameViewSizeGroupType sizeGroupType) - { - switch (sizeGroupType) - { - case GameViewSizeGroupType.Standalone: - return DefaultLowResolutionSettingForStandalone(); - case GameViewSizeGroupType.N3DS: - return true; - case GameViewSizeGroupType.iOS: - case GameViewSizeGroupType.Android: - case GameViewSizeGroupType.Tizen: - default: - return false; - } - } - - private static void RefreshDerivedGameViewSize(GameViewSizeGroupType groupType, int gameViewSizeIndex, GameViewSize gameViewSize) - { - if (GameViewSizes.instance.IsDefaultStandaloneScreenSize(groupType, gameViewSizeIndex)) - { - gameViewSize.width = (int)InternalEditorUtility.defaultScreenWidth; - gameViewSize.height = (int)InternalEditorUtility.defaultScreenHeight; - } - else if (GameViewSizes.instance.IsRemoteScreenSize(groupType, gameViewSizeIndex)) - { - int width = 0; - int height = 0; - if (UnityEngine.XR.XRSettings.isDeviceActive) - { - width = UnityEngine.XR.XRSettings.eyeTextureWidth; - height = UnityEngine.XR.XRSettings.eyeTextureHeight; - } - else - { - width = (int)InternalEditorUtility.remoteScreenWidth; - height = (int)InternalEditorUtility.remoteScreenHeight; - } - - if (width > 0 && height > 0) - { - gameViewSize.sizeType = GameViewSizeType.FixedResolution; - gameViewSize.width = width; - gameViewSize.height = height; - } - else - { - // Free aspect if invalid remote width or height - gameViewSize.sizeType = GameViewSizeType.AspectRatio; - gameViewSize.width = gameViewSize.height = 0; - } - } - } - - public static Rect GetConstrainedRect(Rect startRect, GameViewSizeGroupType groupType, int gameViewSizeIndex, out bool fitsInsideRect) - { - fitsInsideRect = true; - Rect constrainedRect = startRect; - GameViewSize gameViewSize = GameViewSizes.instance.GetGroup(groupType).GetGameViewSize(gameViewSizeIndex); - RefreshDerivedGameViewSize(groupType, gameViewSizeIndex, gameViewSize); - - if (gameViewSize.isFreeAspectRatio) - { - return startRect; - } - - float newRatio = 0; - bool useRatio; - switch (gameViewSize.sizeType) - { - case GameViewSizeType.AspectRatio: - { - newRatio = gameViewSize.aspectRatio; - useRatio = true; - } - break; - case GameViewSizeType.FixedResolution: - { - if (gameViewSize.height > startRect.height || gameViewSize.width > startRect.width) - { - newRatio = gameViewSize.aspectRatio; - useRatio = true; - fitsInsideRect = false; - } - else - { - constrainedRect.height = gameViewSize.height; - constrainedRect.width = gameViewSize.width; - useRatio = false; - } - } - break; - default: - throw new ArgumentException("Unrecognized size type"); - } - - if (useRatio) - { - constrainedRect.height = (constrainedRect.width / newRatio) > startRect.height - ? (startRect.height) - : (constrainedRect.width / newRatio); - constrainedRect.width = (constrainedRect.height * newRatio); - } - - // clamp - constrainedRect.height = Mathf.Clamp(constrainedRect.height, 0f, startRect.height); - constrainedRect.width = Mathf.Clamp(constrainedRect.width, 0f, startRect.width); - - // center - constrainedRect.y = (startRect.height * 0.5f - constrainedRect.height * 0.5f) + startRect.y; - constrainedRect.x = (startRect.width * 0.5f - constrainedRect.width * 0.5f) + startRect.x; - - // Round to whole pixels - actually is important for correct rendering of game view! - constrainedRect.width = Mathf.Floor(constrainedRect.width + 0.5f); - constrainedRect.height = Mathf.Floor(constrainedRect.height + 0.5f); - constrainedRect.x = Mathf.Floor(constrainedRect.x + 0.5f); - constrainedRect.y = Mathf.Floor(constrainedRect.y + 0.5f); - - return constrainedRect; - } - - public static Vector2 GetRenderTargetSize(Rect startRect, GameViewSizeGroupType groupType, int gameViewSizeIndex, out bool clamped) - { - GameViewSize gameViewSize = GameViewSizes.instance.GetGroup(groupType).GetGameViewSize(gameViewSizeIndex); - RefreshDerivedGameViewSize(groupType, gameViewSizeIndex, gameViewSize); - Vector2 targetSize; - clamped = false; - - // Free aspect takes up all available pixels by default - if (gameViewSize.isFreeAspectRatio) - { - targetSize = startRect.size; - } - else - { - switch (gameViewSize.sizeType) - { - // Aspect ratio is enforced, but fills up as much game view as it can - case GameViewSizeType.AspectRatio: - { - if (startRect.height == 0f || gameViewSize.aspectRatio == 0f) - { - targetSize = Vector2.zero; - break; - } - var startRatio = startRect.width / startRect.height; - if (startRatio < gameViewSize.aspectRatio) - { - targetSize = new Vector2(startRect.width, startRect.width / gameViewSize.aspectRatio); - } - else - { - targetSize = new Vector2(startRect.height * gameViewSize.aspectRatio, startRect.height); - } - } - break; - // Fixed resolution is fixed, but scaled down to fit, or scaled up to largest possible integer - case GameViewSizeType.FixedResolution: - { - targetSize = new Vector2(gameViewSize.width, gameViewSize.height); - } - break; - default: - throw new ArgumentException("Unrecognized size type"); - } - } - - // Prevent ludicrous render target sizes. Heuristics based on: - // - GPU supported max. texture size - // - "should be enough for anyone" (i.e. more than 8K resolution) - // - Available VRAM - // - // The reason is that while GPUs support large textures (e.g. 16k x 16k), trying to - // actually create one will just make you run out of memory. VRAM size estimate that we - // have is also only very approximate. - // Let's assume we can use 20% of VRAM for game view render target; - // and that we need 12 bytes/pixel (4 for color, double buffered, 4 for depth). - // Figure out what's the max texture area that fits there. - var maxVRAMArea = SystemInfo.graphicsMemorySize * 0.20f / 12f * 1024f * 1024f; - - var targetArea = targetSize.x * targetSize.y; - if (targetArea > maxVRAMArea) - { - var aspect = targetSize.y / targetSize.x; - targetSize.x = Mathf.Sqrt(maxVRAMArea * aspect); - targetSize.y = aspect * targetSize.x; - clamped = true; - } - - // Over 8K resolution (7680x4320) should be enough for anyone (tm) - var maxResolutionSize = 8192f; - var maxSize = Mathf.Min(SystemInfo.maxRenderTextureSize, maxResolutionSize); - - if (targetSize.x > maxSize || targetSize.y > maxSize) - { - if (targetSize.x > targetSize.y) - targetSize *= maxSize / targetSize.x; - else - targetSize *= maxSize / targetSize.y; - clamped = true; - } - - return targetSize; - } - - class BuildTargetChangedHandler : Build.IActiveBuildTargetChanged - { - public int callbackOrder { get { return 0; } } - - public void OnActiveBuildTargetChanged(BuildTarget oldTarget, BuildTarget newTarget) - { - RefreshGameViewSizeGroupType(oldTarget, newTarget); - } - } - - static void RefreshGameViewSizeGroupType(BuildTarget oldTarget, BuildTarget newTarget) - { - BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(newTarget); - s_GameViewSizeGroupType = BuildTargetGroupToGameViewSizeGroup(buildTargetGroup); - } - - public static GameViewSizeGroupType BuildTargetGroupToGameViewSizeGroup(BuildTargetGroup buildTargetGroup) - { - if (UnityEngine.XR.XRSettings.enabled && UnityEngine.XR.XRSettings.showDeviceView) - return GameViewSizeGroupType.HMD; - - switch (buildTargetGroup) - { - case BuildTargetGroup.Standalone: - return GameViewSizeGroupType.Standalone; - - case BuildTargetGroup.iOS: - return GameViewSizeGroupType.iOS; - - case BuildTargetGroup.Android: - return GameViewSizeGroupType.Android; - - case BuildTargetGroup.Tizen: - return GameViewSizeGroupType.Tizen; - - case BuildTargetGroup.N3DS: - return GameViewSizeGroupType.N3DS; - - default: - return GameViewSizeGroupType.Standalone; - } - } - } -} - -// namespace diff --git a/Editor/Mono/GameView/GameViewSizesMenuItemProvider.cs b/Editor/Mono/GameView/GameViewSizesMenuItemProvider.cs deleted file mode 100644 index 337c2712ae..0000000000 --- a/Editor/Mono/GameView/GameViewSizesMenuItemProvider.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class GameViewSizesMenuItemProvider : IFlexibleMenuItemProvider - { - private readonly GameViewSizeGroup m_GameViewSizeGroup; - - public GameViewSizesMenuItemProvider(GameViewSizeGroupType gameViewSizeGroupType) - { - m_GameViewSizeGroup = GameViewSizes.instance.GetGroup(gameViewSizeGroupType); - } - - public int Count() - { - return m_GameViewSizeGroup.GetTotalCount(); - } - - public object GetItem(int index) - { - return m_GameViewSizeGroup.GetGameViewSize(index); - } - - public int Add(object obj) - { - GameViewSize gameViewSize = CastToGameViewSize(obj); - if (gameViewSize == null) - return -1; - - m_GameViewSizeGroup.AddCustomSize(gameViewSize); - GameViewSizes.instance.SaveToHDD(); - return Count() - 1; // assumes that custom sizes is after builtin sizes - } - - public void Replace(int index, object obj) - { - GameViewSize newResolution = CastToGameViewSize(obj); - if (newResolution == null) - return; - - if (index < m_GameViewSizeGroup.GetBuiltinCount()) - { - Debug.LogError("Only custom game view sizes can be changed"); - return; - } - - GameViewSize gameViewSize = m_GameViewSizeGroup.GetGameViewSize(index); - if (gameViewSize != null) - { - gameViewSize.Set(newResolution); - GameViewSizes.instance.SaveToHDD(); - } - } - - public void Remove(int index) - { - if (index < m_GameViewSizeGroup.GetBuiltinCount()) - { - Debug.LogError("Only custom game view sizes can be changed"); - return; - } - - m_GameViewSizeGroup.RemoveCustomSize(index); - GameViewSizes.instance.SaveToHDD(); - } - - public object Create() - { - return new GameViewSize(GameViewSizeType.FixedResolution, 0, 0, ""); - } - - public void Move(int index, int destIndex, bool insertAfterDestIndex) - { - Debug.LogError("Missing impl"); - } - - public string GetName(int index) - { - GameViewSize gameViewSize = m_GameViewSizeGroup.GetGameViewSize(index); - if (gameViewSize != null) - return gameViewSize.displayText; - return ""; - } - - public bool IsModificationAllowed(int index) - { - return m_GameViewSizeGroup.IsCustomSize(index); // builtin sizes cannot be modified - } - - public int[] GetSeperatorIndices() - { - return new int[] {m_GameViewSizeGroup.GetBuiltinCount() - 1}; - } - - // Private section - - private static GameViewSize CastToGameViewSize(object obj) - { - GameViewSize newResolution = obj as GameViewSize; - if (obj == null) - { - Debug.LogError("Incorrect input"); - return null; - } - return newResolution; - } - } -} - -// namespace diff --git a/Editor/Mono/GameView/GameViewSizesMenuModifyItemUI.cs b/Editor/Mono/GameView/GameViewSizesMenuModifyItemUI.cs deleted file mode 100644 index 3c6eb2fd22..0000000000 --- a/Editor/Mono/GameView/GameViewSizesMenuModifyItemUI.cs +++ /dev/null @@ -1,152 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class GameViewSizesMenuModifyItemUI : FlexibleMenuModifyItemUI - { - private class Styles - { - public GUIContent headerAdd = EditorGUIUtility.TrTextContent("Add"); - public GUIContent headerEdit = EditorGUIUtility.TrTextContent("Edit"); - public GUIContent typeName = EditorGUIUtility.TrTextContent("Type"); - public GUIContent widthHeightText = EditorGUIUtility.TrTextContent("Width & Height"); - public GUIContent optionalText = EditorGUIUtility.TrTextContent("Label"); - public GUIContent ok = EditorGUIUtility.TrTextContent("OK"); - public GUIContent cancel = EditorGUIUtility.TrTextContent("Cancel"); - public GUIContent[] typeNames = new[] {EditorGUIUtility.TrTextContent("Aspect Ratio"), EditorGUIUtility.TrTextContent("Fixed Resolution")}; - } - - private static Styles s_Styles; - private GameViewSize m_GameViewSize; - - public override void OnClose() - { - m_GameViewSize = null; - base.OnClose(); - } - - override public Vector2 GetWindowSize() - { - return new Vector2(230, 140); - } - - override public void OnGUI(Rect rect) - { - if (s_Styles == null) - s_Styles = new Styles(); - - GameViewSize gameViewSizeState = m_Object as GameViewSize; - if (gameViewSizeState == null) - { - Debug.LogError("Invalid object"); - return; - } - - // We use a local gameviewsize to ensure we do not edit the original state (if user presses cancel state is not changed) - if (m_GameViewSize == null) - m_GameViewSize = new GameViewSize(gameViewSizeState); - - bool validSettings = m_GameViewSize.width > 0 && m_GameViewSize.height > 0; - const float kColumnWidth = 90f; - const float kSpacing = 10f; - - GUILayout.Space(3); - GUILayout.Label(m_MenuType == MenuType.Add ? s_Styles.headerAdd : s_Styles.headerEdit, - EditorStyles.boldLabel); - - Rect seperatorRect = GUILayoutUtility.GetRect(1, 1); - FlexibleMenu.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 - GUILayout.Space(4); - - // Optional text - GUILayout.BeginHorizontal(); - GUILayout.Label(s_Styles.optionalText, GUILayout.Width(kColumnWidth)); - GUILayout.Space(kSpacing); - m_GameViewSize.baseText = EditorGUILayout.TextField(m_GameViewSize.baseText); - GUILayout.EndHorizontal(); - - // Drop list (aspect / fixed res) - GUILayout.BeginHorizontal(); - GUILayout.Label(s_Styles.typeName, GUILayout.Width(kColumnWidth)); - GUILayout.Space(kSpacing); - m_GameViewSize.sizeType = (GameViewSizeType)EditorGUILayout.Popup((int)m_GameViewSize.sizeType, s_Styles.typeNames); - GUILayout.EndHorizontal(); - - // Width Height - GUILayout.BeginHorizontal(); - GUILayout.Label(s_Styles.widthHeightText, GUILayout.Width(kColumnWidth)); - GUILayout.Space(kSpacing); - m_GameViewSize.width = EditorGUILayout.IntField(m_GameViewSize.width); - GUILayout.Space(5); - m_GameViewSize.height = EditorGUILayout.IntField(m_GameViewSize.height); - GUILayout.EndHorizontal(); - - GUILayout.Space(10f); - - // Displayed text - float margin = 10f; - float cropWidth = rect.width - 2 * margin; - GUILayout.BeginHorizontal(); - GUILayout.Space(margin); - GUILayout.FlexibleSpace(); - string displayText = m_GameViewSize.displayText; - using (new EditorGUI.DisabledScope(string.IsNullOrEmpty(displayText))) - { - if (string.IsNullOrEmpty(displayText)) - displayText = "Result"; - else - displayText = GetCroppedText(displayText, cropWidth, EditorStyles.label); - GUILayout.Label(GUIContent.Temp(displayText), EditorStyles.label); - } - GUILayout.FlexibleSpace(); - GUILayout.Space(margin); - GUILayout.EndHorizontal(); - - GUILayout.Space(5f); - - // Cancel, Ok - GUILayout.BeginHorizontal(); - GUILayout.Space(10); - if (GUILayout.Button(s_Styles.cancel)) - { - editorWindow.Close(); - } - - using (new EditorGUI.DisabledScope(!validSettings)) - { - if (GUILayout.Button(s_Styles.ok)) - { - gameViewSizeState.Set(m_GameViewSize); - Accepted(); - editorWindow.Close(); - } - } - GUILayout.Space(10); - GUILayout.EndHorizontal(); - } - - string GetCroppedText(string fullText, float cropWidth, GUIStyle style) - { - // Check if we need to crop - int characterCountVisible = style.GetNumCharactersThatFitWithinWidth(fullText, cropWidth); - if (characterCountVisible == -1) - { - return fullText; - } - - if (characterCountVisible > 1 && characterCountVisible != fullText.Length) - return fullText.Substring(0, characterCountVisible - 1) + ("\u2026"); // 'horizontal ellipsis' (U+2026) is: ... - else - return fullText; - } - } -} - -// namespace diff --git a/Editor/Mono/GameView/IGameViewSizeMenuUser.cs b/Editor/Mono/GameView/IGameViewSizeMenuUser.cs deleted file mode 100644 index f7f3229000..0000000000 --- a/Editor/Mono/GameView/IGameViewSizeMenuUser.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor -{ - internal interface IGameViewSizeMenuUser - { - void SizeSelectionCallback(int indexClicked, object objectSelected); - bool lowResolutionForAspectRatios { get; set; } - bool forceLowResolutionAspectRatios { get; } - bool showLowResolutionToggle { get; } - } -} diff --git a/Editor/Mono/GameviewGUI.cs b/Editor/Mono/GameviewGUI.cs deleted file mode 100644 index 6f962d3854..0000000000 --- a/Editor/Mono/GameviewGUI.cs +++ /dev/null @@ -1,169 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System; -using System.Text; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - internal class GameViewGUI - { - private static string FormatNumber(long num) - { - if (num < 1000) - return num.ToString(); - if (num < 1000000) - return (num * 0.001).ToString("f1") + "k"; - return (num * 0.000001).ToString("f1") + "M"; - } - - private static int m_FrameCounter = 0; - private static float m_ClientTimeAccumulator = 0.0f; - private static float m_RenderTimeAccumulator = 0.0f; - private static float m_MaxTimeAccumulator = 0.0f; - private static float m_ClientFrameTime = 0.0f; - private static float m_RenderFrameTime = 0.0f; - private static float m_MaxFrameTime = 0.0f; - - // Cache bold style of scene skin - private static GUIStyle s_SectionHeaderStyle; - private static GUIStyle sectionHeaderStyle - { - get - { - if (s_SectionHeaderStyle == null) - s_SectionHeaderStyle = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Scene).GetStyle("BoldLabel"); - return s_SectionHeaderStyle; - } - } - - // Create label style from scene skin; add rich text support - private static GUIStyle s_LabelStyle; - private static GUIStyle labelStyle - { - get - { - if (s_LabelStyle == null) - { - s_LabelStyle = new GUIStyle(EditorGUIUtility.GetBuiltinSkin(EditorSkin.Scene).label); - s_LabelStyle.richText = true; - } - return s_LabelStyle; - } - } - - // Time per frame varies wildly, so we average a bit and display that. - private static void UpdateFrameTime() - { - if (Event.current.type != EventType.Repaint) - return; - - float frameTime = UnityStats.frameTime; - float renderTime = UnityStats.renderTime; - m_ClientTimeAccumulator += frameTime; - m_RenderTimeAccumulator += renderTime; - m_MaxTimeAccumulator += Mathf.Max(frameTime, renderTime); - ++m_FrameCounter; - - bool needsTime = m_ClientFrameTime == 0.0f && m_RenderFrameTime == 0.0f; - bool resetTime = m_FrameCounter > 30 || m_ClientTimeAccumulator > 0.3f || m_RenderTimeAccumulator > 0.3f; - - if (needsTime || resetTime) - { - m_ClientFrameTime = m_ClientTimeAccumulator / m_FrameCounter; - m_RenderFrameTime = m_RenderTimeAccumulator / m_FrameCounter; - m_MaxFrameTime = m_MaxTimeAccumulator / m_FrameCounter; - } - if (resetTime) - { - m_ClientTimeAccumulator = 0.0f; - m_RenderTimeAccumulator = 0.0f; - m_MaxTimeAccumulator = 0.0f; - m_FrameCounter = 0; - } - } - - private static string FormatDb(float vol) - { - if (vol == 0.0f) - return "-\u221E dB"; - return string.Format("{0:F1} dB", 20.0f * Mathf.Log10(vol)); - } - - [RequiredByNativeCode] - public static void GameViewStatsGUI() - { - GUI.skin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Scene); - - GUI.color = new Color(1, 1, 1, .75f); - float w = 300, h = 204; - - // Increase windows size to make room for network data - int connectionCount = Network.connections.Length; - if (connectionCount != 0) - h += 220; - - GUILayout.BeginArea(new Rect(GUIView.current.position.width - w - 10, 27, w, h), "Statistics", GUI.skin.window); - - // Audio stats - GUILayout.Label("Audio:", sectionHeaderStyle); - StringBuilder audioStats = new StringBuilder(400); - float audioLevel = UnityStats.audioLevel; - audioStats.Append(" Level: " + FormatDb(audioLevel) + (EditorUtility.audioMasterMute ? " (MUTED)\n" : "\n")); - audioStats.Append(String.Format(" Clipping: {0:F1}%", 100.0f * UnityStats.audioClippingAmount)); - GUILayout.Label(audioStats.ToString()); - - GUI.Label(new Rect(170, 40, 120, 20), String.Format("DSP load: {0:F1}%", 100.0f * UnityStats.audioDSPLoad)); - GUI.Label(new Rect(170, 53, 120, 20), String.Format("Stream load: {0:F1}%", 100.0f * UnityStats.audioStreamLoad)); - - // Graphics stats - GUILayout.Label("Graphics:", sectionHeaderStyle); - - // Time stats - UpdateFrameTime(); - - string timeStats = System.String.Format("{0:F1} FPS ({1:F1}ms)", - 1.0f / Mathf.Max(m_MaxFrameTime, 1.0e-5f), m_MaxFrameTime * 1000.0f); - GUI.Label(new Rect(170, 75, 120, 20), timeStats); - - int screenBytes = UnityStats.screenBytes; - int batchesSavedByDynamicBatching = UnityStats.dynamicBatchedDrawCalls - UnityStats.dynamicBatches; - int batchesSavedByStaticBatching = UnityStats.staticBatchedDrawCalls - UnityStats.staticBatches; - int batchesSavedByInstancing = UnityStats.instancedBatchedDrawCalls - UnityStats.instancedBatches; - - StringBuilder gfxStats = new StringBuilder(400); - if (m_ClientFrameTime > m_RenderFrameTime) - gfxStats.Append(String.Format(" CPU: main {0:F1}ms render thread {1:F1}ms\n", m_ClientFrameTime * 1000.0f, m_RenderFrameTime * 1000.0f)); - else - gfxStats.Append(String.Format(" CPU: main {0:F1}ms render thread {1:F1}ms\n", m_ClientFrameTime * 1000.0f, m_RenderFrameTime * 1000.0f)); - gfxStats.Append(String.Format(" Batches: {0} \tSaved by batching: {1}\n", UnityStats.batches, batchesSavedByDynamicBatching + batchesSavedByStaticBatching + batchesSavedByInstancing)); - gfxStats.Append(String.Format(" Tris: {0} \tVerts: {1} \n", FormatNumber(UnityStats.trianglesLong), FormatNumber(UnityStats.verticesLong))); - gfxStats.Append(String.Format(" Screen: {0} - {1}\n", UnityStats.screenRes, EditorUtility.FormatBytes(screenBytes))); - gfxStats.Append(String.Format(" SetPass calls: {0} \tShadow casters: {1} \n", UnityStats.setPassCalls, UnityStats.shadowCasters)); - gfxStats.Append(String.Format(" Visible skinned meshes: {0} Animations: {1}", UnityStats.visibleSkinnedMeshes, UnityStats.visibleAnimations)); - GUILayout.Label(gfxStats.ToString(), labelStyle); - - // Networking stats - if (connectionCount != 0) - { - GUILayout.Label("Network:", sectionHeaderStyle); - GUILayout.BeginHorizontal(); - for (int i = 0; i < connectionCount; i++) - { - GUILayout.Label(UnityStats.GetNetworkStats(i)); - } - GUILayout.EndHorizontal(); - } - else - { - GUILayout.Label("Network: (no players connected)", sectionHeaderStyle); - } - GUILayout.EndArea(); - } - } -} diff --git a/Editor/Mono/GenerateIconsWithMipLevels.cs b/Editor/Mono/GenerateIconsWithMipLevels.cs deleted file mode 100644 index 44573484ca..0000000000 --- a/Editor/Mono/GenerateIconsWithMipLevels.cs +++ /dev/null @@ -1,442 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.IO; -using System.Collections.Generic; -using Object = UnityEngine.Object; - -/* Some notes on icon caches and loading - * - * - * Caches: - * Icon name to Texture2D: - * gNamedTextures (ObjectImages::Texture2DNamed): string to Texture2D - * - * InstanceID to Image - * gCachedThumbnails (AssetImporter::GetThumbnailForInstanceID) : where image is retrieved from Texture from gNamedTextures - * Used for setting icon for hierarchyProperty - * - * InstanceID to Texture2D - * ms_HackedCache (AssetDatabaseProperty::GetCachedAssetDatabaseIcon) : where tetxure2D icon is generated from the image from gCachedThumbnails - * Cache max size: 200 - * Called from C# by AssetDatabase.GetCachedIcon (string assetpath) - * - * - * - * - Icon loading in Editor Default Resources project: - - Texture2DNamed handles reading local files instead of editor resources bundle - - Icon loading in other projects - - When reimport of asset (cpp): AssetDatabase::ImportAsset -> MonoImporter::GenerateAssetData -> ImageForMonoScript -> GetImageNames -> ObjectImages::Texture2DNamed - - IconContent -> LoadIconRequired -> LoadIcon -> LoadIconForSkin -> Load (EditorResourcesUtility.iconsPath + name) as Texture2D; - - AssetDatabase.GetCachedIcon (assetpath) -> CPP -> AssetDatabaseProperty::GetCachedAssetDatabaseIcon - - InternalEditorUtility.GetIconForFile (filename) -> EditorGUIUtility.FindTexture("boo Script Icon") -> CPP -> ObjectImages::Texture2DNamed(cpp) - - */ - -namespace UnityEditorInternal -{ - public class GenerateIconsWithMipLevels - { - static string k_IconSourceFolder = "Assets/MipLevels For Icons/"; - static string k_IconTargetFolder = "Assets/Editor Default Resources/Icons/Processed"; - static string k_IconMipIdentifier = "@"; - - class InputData - { - public string sourceFolder; - public string targetFolder; - public string mipIdentifier; - public string mipFileExtension; - public List generatedFileNames = new List(); // for internal use - - public string GetMipFileName(string baseName, int mipResolution) - { - return sourceFolder + baseName + mipIdentifier + mipResolution + "." + mipFileExtension; - } - } - - private static InputData GetInputData() - { - InputData data = new InputData(); - data.sourceFolder = k_IconSourceFolder; - data.targetFolder = k_IconTargetFolder; - data.mipIdentifier = k_IconMipIdentifier; - data.mipFileExtension = "png"; - return data; - } - - // Called from BuildEditorAssetBundles - public static void GenerateAllIconsWithMipLevels() - { - var data = GetInputData(); - - EnsureFolderIsCreated(data.targetFolder); - - float startTime = Time.realtimeSinceStartup; - GenerateIconsWithMips(data); - Debug.Log(string.Format("Generated {0} icons with mip levels in {1} seconds", data.generatedFileNames.Count, Time.realtimeSinceStartup - startTime)); - - RemoveUnusedFiles(data.generatedFileNames); - AssetDatabase.Refresh(); // For some reason we creash if we dont refresh twice... - InternalEditorUtility.RepaintAllViews(); - } - - public static bool VerifyIconPath(string assetPath, bool logError) - { - if (string.IsNullOrEmpty(assetPath)) - { - return false; - } - else if (assetPath.IndexOf(k_IconSourceFolder) < 0) - { - if (logError) - Debug.Log("Selection is not a valid mip texture, it should be located in: " + k_IconSourceFolder); - return false; - } - else if (assetPath.IndexOf(k_IconMipIdentifier) < 0) - { - if (logError) - Debug.Log("Selection does not have a valid mip identifier " + assetPath + " " + k_IconMipIdentifier); - return false; - } - return true; - } - - // Refresh just one icon (Used in Editor Resources project, find it in Tools/) - public static void GenerateSelectedIconsWithMips() - { - // If no selection do all - if (Selection.activeInstanceID == 0) - { - Debug.Log("Ensure to select a mip texture..." + Selection.activeInstanceID); - return; - } - - var data = GetInputData(); - - int instanceID = Selection.activeInstanceID; - string assetPath = AssetDatabase.GetAssetPath(instanceID); - - if (!VerifyIconPath(assetPath, true)) - { - return; - } - - float startTime = Time.realtimeSinceStartup; - - string baseName = assetPath.Replace(data.sourceFolder, ""); - baseName = baseName.Substring(0, baseName.LastIndexOf(data.mipIdentifier)); - - List assetPaths = GetIconAssetPaths(data.sourceFolder, data.mipIdentifier, data.mipFileExtension); - - EnsureFolderIsCreated(data.targetFolder); - GenerateIcon(data, baseName, assetPaths, null, null); - Debug.Log(string.Format("Generated {0} icon with mip levels in {1} seconds", baseName, Time.realtimeSinceStartup - startTime)); - InternalEditorUtility.RepaintAllViews(); - } - - // Refresh just one icon with provided mip levels - public static void GenerateIconWithMipLevels(string assetPath, Dictionary mipTextures, FileInfo fileInfo) - { - if (!VerifyIconPath(assetPath, true)) - { - return; - } - - var data = GetInputData(); - - float startTime = Time.realtimeSinceStartup; - - string baseName = assetPath.Replace(data.sourceFolder, ""); - baseName = baseName.Substring(0, baseName.LastIndexOf(data.mipIdentifier)); - - List assetPaths = GetIconAssetPaths(data.sourceFolder, data.mipIdentifier, data.mipFileExtension); - - EnsureFolderIsCreated(data.targetFolder); - if (GenerateIcon(data, baseName, assetPaths, mipTextures, fileInfo)) - { - Debug.Log(string.Format("Generated {0} icon with mip levels in {1} seconds", baseName, Time.realtimeSinceStartup - startTime)); - } - InternalEditorUtility.RepaintAllViews(); - } - - // Search for the mip level encoded in the asset path - public static int MipLevelForAssetPath(string assetPath, string separator) - { - if (string.IsNullOrEmpty(assetPath) || string.IsNullOrEmpty(separator)) - return -1; - - int separatorIndex = assetPath.IndexOf(separator); - if (separatorIndex == -1) - { - Debug.LogError("\"" + separator + "\" could not be found in asset path: " + assetPath); - return -1; - } - - int startIndex = separatorIndex + separator.Length; - int endIndex = assetPath.IndexOf(".", startIndex); - if (endIndex == -1) - { - Debug.LogError("Could not find path extension in asset path: " + assetPath); - return -1; - } - - return Int32.Parse(assetPath.Substring(startIndex, endIndex - startIndex)); - } - - // Private section - //---------------- - private static void GenerateIconsWithMips(InputData inputData) - { - List files = GetIconAssetPaths(inputData.sourceFolder, inputData.mipIdentifier, inputData.mipFileExtension); - - if (files.Count == 0) - { - Debug.LogWarning("No mip files found for generating icons! Searching in: " + inputData.sourceFolder + ", for files with extension: " + inputData.mipFileExtension); - } - - string[] baseNames = GetBaseNames(inputData, files); - - // Base name is assumed to be like: "Assets/Icons/..." - foreach (string baseName in baseNames) - GenerateIcon(inputData, baseName, files, null, null); - } - - private static bool GenerateIcon(InputData inputData, string baseName, List assetPathsOfAllIcons, Dictionary mipTextures, FileInfo sourceFileInfo) - { - //We need to create the folder before we Create the Asset. - //AssetDatabase.CreateFolder will trigger a Asset Garbage Collection and stack items are not preserved. - string generatedPath = inputData.targetFolder + "/" + baseName + " Icon" + ".asset"; - - if (sourceFileInfo != null && File.Exists(generatedPath)) - { - var fileInfo = new FileInfo(generatedPath); - if (fileInfo.LastWriteTime > sourceFileInfo.LastWriteTime) - { - // The resulting MIPS is newer than the source. Nothing to do. - return false; - } - } - - Debug.Log("Generating MIP levels for " + generatedPath); - - EnsureFolderIsCreatedRecursively(Path.GetDirectoryName(generatedPath)); - - Texture2D iconWithMips = CreateIconWithMipLevels(inputData, baseName, assetPathsOfAllIcons, mipTextures); - if (iconWithMips == null) - { - Debug.Log("CreateIconWithMipLevels failed"); - return false; - } - - iconWithMips.name = baseName + " Icon" + ".png"; // asset name must have .png as extension (used when loading the icon, search for LoadIconForSkin) - // Write texture to disk - - - AssetDatabase.CreateAsset(iconWithMips, generatedPath); - inputData.generatedFileNames.Add(generatedPath); - - return true; - } - - private static Texture2D CreateIconWithMipLevels(InputData inputData, string baseName, List assetPathsOfAllIcons, Dictionary mipTextures) - { - List allMipPaths = assetPathsOfAllIcons.FindAll(delegate(string o) { return o.IndexOf('/' + baseName + inputData.mipIdentifier) >= 0; }); - List allMips = new List(); - foreach (string path in allMipPaths) - { - int mipLevel = MipLevelForAssetPath(path, inputData.mipIdentifier); - - Texture2D mip = null; - if (mipTextures != null && mipTextures.ContainsKey(mipLevel)) - mip = mipTextures[mipLevel]; - else - mip = GetTexture2D(path); - - if (mip != null) - allMips.Add(mip); - else - Debug.LogError("Mip not found " + path); - } - - // Sort the mips by size (largest mip first) - allMips.Sort(delegate(Texture2D first, Texture2D second) - { - if (first.width == second.width) - return 0; - else if (first.width < second.width) - return 1; - else - return -1; - }); - - int minResolution = 99999; - int maxResolution = 0; - - foreach (Texture2D mip in allMips) - { - int width = mip.width; - if (width > maxResolution) - maxResolution = width; - if (width < minResolution) - minResolution = width; - } - - if (maxResolution == 0) - return null; - - // Create our icon - Texture2D iconWithMips = new Texture2D(maxResolution, maxResolution, TextureFormat.RGBA32, true, false); - - // Add max mip - if (BlitMip(iconWithMips, allMips, 0)) - iconWithMips.Apply(true); - else - return iconWithMips; // ERROR - - // Keep for debugging - //Debug.Log ("Processing max mip file: " + inputData.GetMipFileName (baseName, maxResolution) ); - - // Now add the rest - int resolution = maxResolution; - for (int i = 1; i < iconWithMips.mipmapCount; i++) - { - resolution /= 2; - if (resolution < minResolution) - break; - - BlitMip(iconWithMips, allMips, i); - } - iconWithMips.Apply(false, true); - - - return iconWithMips; - } - - private static bool BlitMip(Texture2D iconWithMips, List sortedTextures, int mipLevel) - { - if (mipLevel < 0 || mipLevel >= sortedTextures.Count) - { - Debug.LogError("Invalid mip level: " + mipLevel); - return false; - } - - Texture2D tex = sortedTextures[mipLevel]; - if (tex) - { - Blit(tex, iconWithMips, mipLevel); - return true; - } - else - { - Debug.LogError("No texture at mip level: " + mipLevel); - } - - return false; - } - - private static Texture2D GetTexture2D(string path) - { - return AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D; - } - - static List GetIconAssetPaths(string folderPath, string mustHaveIdentifier, string extension) - { - string curDirectory = Directory.GetCurrentDirectory(); - string absolute = Path.Combine(curDirectory, folderPath); - Uri absoluteUri = new Uri(absolute); - List files = new List(Directory.GetFiles(absolute, "*." + extension, SearchOption.AllDirectories)); - files.RemoveAll(delegate(string o) {return o.IndexOf(mustHaveIdentifier) < 0; }); // // Remove all files that do not have the 'mustHaveIdentifier' - for (int i = 0; i < files.Count; ++i) - { - Uri fileUri = new Uri(files[i]); - Uri relativeUri = absoluteUri.MakeRelativeUri(fileUri); - files[i] = folderPath + relativeUri.ToString(); - } - return files; - } - - static void Blit(Texture2D source, Texture2D dest, int mipLevel) - { - Color32[] pixels = source.GetPixels32(); - for (int i = 0; i < pixels.Length; i++) - { - Color32 p = pixels[i]; - if (p.a >= 3) - p.a -= 3; - pixels[i] = p; - } - dest.SetPixels32(pixels, mipLevel); - } - - private static void EnsureFolderIsCreatedRecursively(string targetFolder) - { - if (AssetDatabase.GetMainAssetInstanceID(targetFolder) == 0) - { - EnsureFolderIsCreatedRecursively(Path.GetDirectoryName(targetFolder)); - Debug.Log("Created target folder " + targetFolder); - AssetDatabase.CreateFolder(Path.GetDirectoryName(targetFolder), Path.GetFileName(targetFolder)); - } - } - - private static void EnsureFolderIsCreated(string targetFolder) - { - if (AssetDatabase.GetMainAssetInstanceID(targetFolder) == 0) - { - Debug.Log("Created target folder " + targetFolder); - AssetDatabase.CreateFolder(Path.GetDirectoryName(targetFolder), Path.GetFileName(targetFolder)); - } - } - - static void DeleteFile(string file) - { - if (AssetDatabase.GetMainAssetInstanceID(file) != 0) - { - Debug.Log("Deleted unused file: " + file); - AssetDatabase.DeleteAsset(file); - } - } - - // Get rid of old icons in the Icons folder (with same filename as a generated icon) - static void RemoveUnusedFiles(List generatedFiles) - { - for (int i = 0; i < generatedFiles.Count; ++i) - { - string deleteFile = generatedFiles[i].Replace("Icons/Processed", "Icons"); - deleteFile = deleteFile.Replace(".asset", ".png"); - DeleteFile(deleteFile); - - // Remove the d_ version as well - string fileName = Path.GetFileNameWithoutExtension(deleteFile); - if (!fileName.StartsWith("d_")) - { - deleteFile = deleteFile.Replace(fileName, ("d_" + fileName)); - DeleteFile(deleteFile); - } - } - AssetDatabase.Refresh(); - } - - private static string[] GetBaseNames(InputData inputData, List files) - { - string[] baseNames = new string[files.Count]; - int startPos = inputData.sourceFolder.Length; - for (int i = 0; i < files.Count; ++i) - { - baseNames[i] = files[i].Substring(startPos, files[i].IndexOf(inputData.mipIdentifier) - startPos); - } - HashSet hashset = new HashSet(baseNames); - baseNames = new string[hashset.Count]; - hashset.CopyTo(baseNames); - - return baseNames; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/GradientPreviewCache.bindings.cs b/Editor/Mono/GradientPreviewCache.bindings.cs deleted file mode 100644 index 2e5bc26057..0000000000 --- a/Editor/Mono/GradientPreviewCache.bindings.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditorInternal -{ - [NativeHeader("Editor/Src/GradientPreviewCache.h")] - [NativeHeader("Runtime/Graphics/Texture2D.h")] - [NativeHeader("Runtime/Math/Gradient.h")] - internal partial class GradientPreviewCache - { - public static extern Texture2D GenerateGradientPreview(Gradient gradient, Texture2D existingTexture); - } -} diff --git a/Editor/Mono/Grid/GridSnapping.cs b/Editor/Mono/Grid/GridSnapping.cs deleted file mode 100644 index 17e124810c..0000000000 --- a/Editor/Mono/Grid/GridSnapping.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal static class GridSnapping - { - public static Func snapPosition; - public static Func activeFunc; - - public static bool active - { - get { return (activeFunc != null ? activeFunc() : false); } - } - - public static Vector3 Snap(Vector3 position) - { - if (snapPosition != null) - return snapPosition(position); - return position; - } - } -} diff --git a/Editor/Mono/Help.bindings.cs b/Editor/Mono/Help.bindings.cs deleted file mode 100644 index 23058cd14d..0000000000 --- a/Editor/Mono/Help.bindings.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using Object = UnityEngine.Object; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; -using System.Collections.Generic; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - // Helper class to access Unity documentation. - [NativeHeader("Editor/Src/Panels/HelpPanel.h")] - [NativeHeader("Editor/Platform/Interface/EditorUtility.h")] - public class Help - { - // Is there a help page for this object? - public static bool HasHelpForObject(Object obj) { return HasHelpForObject(obj, true); } - - // Intentionally internal. Extra argument only used to make doc authoring easier. - [FreeFunction] - internal static extern bool HasHelpForObject(Object obj, bool defaultToMonoBehaviour); - - // Intentionally internal. - internal static string GetNiceHelpNameForObject(Object obj) - { - return GetNiceHelpNameForObject(obj, true); - } - - // Intentionally internal. - [FreeFunction] - internal static extern string GetNiceHelpNameForObject(Object obj, bool defaultToMonoBehaviour); - - public static string GetHelpURLForObject(Object obj) - { - return GetHelpURLForObject(obj, true); - } - - [FreeFunction] - private static extern string GetHelpURLForObject(Object obj, bool defaultToMonoBehaviour); - // Show help page for this object. - [FreeFunction] - public static extern void ShowHelpForObject(Object obj); - // Show a help page. - [FreeFunction("ShowNamedHelp")] - public static extern void ShowHelpPage(string page); - // Open /url/ in the default web browser. - [FreeFunction("OpenURLInWebbrowser")] - public static extern void BrowseURL(string url); - } -} diff --git a/Editor/Mono/HomeWindow.bindings.cs b/Editor/Mono/HomeWindow.bindings.cs deleted file mode 100644 index 66cc9c124f..0000000000 --- a/Editor/Mono/HomeWindow.bindings.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/HomeWindow/HomeWindow.h")] - static class HomeWindow - { - // NOTE: Keep in sync with enum in Editor/Src/HomeWindow/HomeWindow.h - public enum HomeMode - { - Login, - License, - Launching, - NewProjectOnly, - OpenProjectOnly, - ManageLicense, - Welcome, - Tutorial, - } - - [NativeMethod("StaticShow")] - public static extern bool Show(HomeMode mode); - } -} diff --git a/Editor/Mono/HostView.cs b/Editor/Mono/HostView.cs deleted file mode 100644 index 9b6309946a..0000000000 --- a/Editor/Mono/HostView.cs +++ /dev/null @@ -1,480 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections.Generic; -using System.Collections; -using System.Reflection; -using UnityEditorInternal; -using UnityEngineInternal; - -namespace UnityEditor -{ - internal class HostView : GUIView - { - internal static Color kViewColor = new Color(0.76f, 0.76f, 0.76f, 1); - internal static PrefColor kPlayModeDarken = new PrefColor("Playmode tint", .8f, .8f, .8f, 1); - - internal static event Action actualViewChanged; - - internal GUIStyle background; - [SerializeField] - private EditorWindow m_ActualView; - - [System.NonSerialized] - private Rect m_BackgroundClearRect = new Rect(0, 0, 0, 0); - [System.NonSerialized] - protected readonly RectOffset m_BorderSize = new RectOffset(); // added as member to prevent allocation - - internal EditorWindow actualView - { - get { return m_ActualView; } - set - { - if (m_ActualView == value) - return; - DeregisterSelectedPane(true); - m_ActualView = value; - RegisterSelectedPane(); - if (actualViewChanged != null) - actualViewChanged(this); - } - } - - protected virtual void UpdateViewMargins(EditorWindow view) - { - } - - protected override void SetPosition(Rect newPos) - { - base.SetPosition(newPos); - SetActualViewPosition(newPos); - } - - protected virtual void SetActualViewPosition(Rect newPos) - { - if (m_ActualView != null) - { - m_ActualView.m_Pos = newPos; - UpdateViewMargins(m_ActualView); - m_ActualView.OnResized(); - } - } - - protected override void SetWindow(ContainerWindow win) - { - base.SetWindow(win); - if (m_ActualView != null) - { - UpdateViewMargins(m_ActualView); - } - } - - protected override void OnEnable() - { - base.OnEnable(); - background = null; - RegisterSelectedPane(); - } - - protected override void OnDisable() - { - base.OnDisable(); - DeregisterSelectedPane(false); - } - - protected override void OldOnGUI() - { - ClearBackground(); - - // Call reset GUI state as first thing so GUI.color is correct when drawing window decoration. - EditorGUIUtility.ResetGUIState(); - DoWindowDecorationStart(); - if (background == null) - { - background = "hostview"; - // Fix annoying GUILayout issue: When using guilayout in Utility windows there was always padded 10 px at the top! Todo: Fix this in EditorResources - background.padding.top = 0; - } - GUILayout.BeginVertical(background); - - if (actualView) - actualView.m_Pos = screenPosition; - - Invoke("OnGUI"); - EditorGUIUtility.ResetGUIState(); - - if (m_ActualView != null) - if (m_ActualView.m_FadeoutTime != 0 && Event.current.type == EventType.Repaint) - m_ActualView.DrawNotification(); - - GUILayout.EndVertical(); - DoWindowDecorationEnd(); - - EditorGUI.ShowRepaints(); - } - - protected override bool OnFocus() - { - Invoke("OnFocus"); - - // Callback could have killed us. If so, die now... - if (this == null) - return false; - - Repaint(); - return true; - } - - void OnLostFocus() - { - EditorGUI.EndEditingActiveTextField(); - Invoke("OnLostFocus"); - Repaint(); - } - - protected override void OnDestroy() - { - if (m_ActualView) - UnityEngine.Object.DestroyImmediate(m_ActualView, true); - base.OnDestroy(); - } - - protected System.Type[] GetPaneTypes() - { - return new System.Type[] { - typeof(SceneView), - typeof(GameView), - typeof(InspectorWindow), - typeof(SceneHierarchyWindow), - typeof(ProjectBrowser), - typeof(ProfilerWindow), - typeof(AnimationWindow) - }; - } - - // Messages sent by Unity to editorwindows today. - // The implementation is not very good, but oh well... it gets the message across. - internal void OnProjectChange() - { - Invoke("OnProjectChange"); - } - - internal void OnSelectionChange() - { - Invoke("OnSelectionChange"); - } - - internal void OnDidOpenScene() - { - Invoke("OnDidOpenScene"); - } - - internal void OnInspectorUpdate() - { - Invoke("OnInspectorUpdate"); - } - - internal void OnHierarchyChange() - { - Invoke("OnHierarchyChange"); - } - - System.Reflection.MethodInfo GetPaneMethod(string methodName) - { - return GetPaneMethod(methodName, m_ActualView); - } - - System.Reflection.MethodInfo GetPaneMethod(string methodName, object obj) - { - if (obj == null) - return null; - - System.Type t = obj.GetType(); - - System.Reflection.MethodInfo method = null; - while (t != null) - { - method = t.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - if (method != null) - return method; - - t = t.BaseType; - } - return null; - } - - static public void EndOffsetArea() - { - if (Event.current.type == EventType.Used) - return; - GUILayoutUtility.EndLayoutGroup(); - GUI.EndGroup(); - } - - static public void BeginOffsetArea(Rect screenRect, GUIContent content, GUIStyle style) - { - GUILayoutGroup g = EditorGUILayoutUtilityInternal.BeginLayoutArea(style, typeof(GUILayoutGroup)); - switch (Event.current.type) - { - case EventType.Layout: - g.resetCoords = false; - g.minWidth = g.maxWidth = screenRect.width + 1; - g.minHeight = g.maxHeight = screenRect.height + 2; - g.rect = Rect.MinMaxRect(-1, -1, g.rect.xMax, g.rect.yMax - 10); - break; - } - GUI.BeginGroup(screenRect, content, style); - } - - public void InvokeOnGUI(Rect onGUIPosition) - { - // Handle window reloading. - if (Unsupported.IsDeveloperMode() && - actualView != null && - Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.F5) - { - Reload(actualView); - return; - } - - DoWindowDecorationStart(); - - GUIStyle overlay = "dockareaoverlay"; - if (actualView is GameView) // GameView exits GUI, so draw overlay border earlier - GUI.Box(onGUIPosition, GUIContent.none, overlay); - - BeginOffsetArea(new Rect(onGUIPosition.x + 2, onGUIPosition.y + DockArea.kTabHeight, onGUIPosition.width - 4, onGUIPosition.height - DockArea.kTabHeight - 2), GUIContent.none, "TabWindowBackground"); - EditorGUIUtility.ResetGUIState(); - bool isExitGUIException = false; - try - { - Invoke("OnGUI"); - } - catch (TargetInvocationException e) - { - if (e.InnerException is ExitGUIException) - isExitGUIException = true; - throw; - } - finally - { - // We can't reset gui state after ExitGUI we just want to bail completely - if (!isExitGUIException) - { - if (actualView != null && actualView.m_FadeoutTime != 0 && Event.current != null && Event.current.type == EventType.Repaint) - actualView.DrawNotification(); - - EndOffsetArea(); - - EditorGUIUtility.ResetGUIState(); - - DoWindowDecorationEnd(); - - if (Event.current.type == EventType.Repaint) - { - overlay.Draw(onGUIPosition, GUIContent.none, 0); - } - } - } - } - - /// TODO: Optimize with Delegate.CreateDelegate - protected void Invoke(string methodName) - { - Invoke(methodName, m_ActualView); - } - - protected void Invoke(string methodName, object obj) - { - System.Reflection.MethodInfo mi = GetPaneMethod(methodName, obj); - if (mi != null) - mi.Invoke(obj, null); - } - - protected void RegisterSelectedPane() - { - if (!m_ActualView) - return; - m_ActualView.m_Parent = this; - - visualTree.Add(m_ActualView.rootVisualContainer); - panel.getViewDataDictionary = m_ActualView.GetViewDataDictionary; - panel.savePersistentViewData = m_ActualView.SavePersistentViewData; - - if (GetPaneMethod("Update") != null) - EditorApplication.update += SendUpdate; - - if (GetPaneMethod("ModifierKeysChanged") != null) - EditorApplication.modifierKeysChanged += SendModKeysChanged; - - m_ActualView.MakeParentsSettingsMatchMe(); - - if (m_ActualView.m_FadeoutTime != 0) - { - EditorApplication.update += m_ActualView.CheckForWindowRepaint; - } - - try - { - Invoke("OnBecameVisible"); - Invoke("OnFocus"); - } - catch (TargetInvocationException ex) - { - // We need to catch these so the window initialization doesn't get screwed - Debug.LogError(ex.InnerException.GetType().Name + ":" + ex.InnerException.Message); - } - - UpdateViewMargins(m_ActualView); - } - - protected void DeregisterSelectedPane(bool clearActualView) - { - if (!m_ActualView) - return; - - if (m_ActualView.rootVisualContainer.shadow.parent == visualTree) - { - visualTree.Remove(m_ActualView.rootVisualContainer); - panel.getViewDataDictionary = null; - panel.savePersistentViewData = null; - } - - if (GetPaneMethod("Update") != null) - EditorApplication.update -= SendUpdate; - - if (GetPaneMethod("ModifierKeysChanged") != null) - EditorApplication.modifierKeysChanged -= SendModKeysChanged; - - if (m_ActualView.m_FadeoutTime != 0) - { - EditorApplication.update -= m_ActualView.CheckForWindowRepaint; - } - - if (clearActualView) - { - EditorWindow oldActualView = m_ActualView; - m_ActualView = null; - Invoke("OnLostFocus", oldActualView); - Invoke("OnBecameInvisible", oldActualView); - } - } - - void SendUpdate() { Invoke("Update"); } - void SendModKeysChanged() { Invoke("ModifierKeysChanged"); } - - internal RectOffset borderSize { get { return GetBorderSize(); } } - - protected virtual RectOffset GetBorderSize() { return m_BorderSize; } - - protected void ShowGenericMenu() - { - GUIStyle gs = "PaneOptions"; - Rect paneMenu = new Rect(position.width - gs.fixedWidth - 4, Mathf.Floor(background.margin.top + 20 - gs.fixedHeight), gs.fixedWidth, gs.fixedHeight); - if (EditorGUI.DropdownButton(paneMenu, GUIContent.none, FocusType.Passive, "PaneOptions")) - PopupGenericMenu(m_ActualView, paneMenu); - - // Give panes an option of showing a small button next to the generic menu (used for inspector lock icon - System.Reflection.MethodInfo mi = GetPaneMethod("ShowButton", m_ActualView); - if (mi != null) - { - object[] lockButton = { new Rect(position.width - gs.fixedWidth - 20, Mathf.Floor(background.margin.top + 4), 16, 16) }; - - mi.Invoke(m_ActualView, lockButton); - } - } - - public void PopupGenericMenu(EditorWindow view, Rect pos) - { - GenericMenu menu = new GenericMenu(); - - IHasCustomMenu menuProviderFactoryThingy = view as IHasCustomMenu; - if (menuProviderFactoryThingy != null) - menuProviderFactoryThingy.AddItemsToMenu(menu); - - AddDefaultItemsToMenu(menu, view); - menu.DropDown(pos); - Event.current.Use(); - } - - private void Inspect(object userData) - { - Selection.activeObject = (UnityEngine.Object)userData; - } - - internal void Reload(object userData) - { - EditorWindow window = userData as EditorWindow; - if (window == null) - return; - - // Get some info on the existing window. - Type windowType = window.GetType(); - - // Save what we can of the window. - string windowJson = EditorJsonUtility.ToJson(window); - - DockArea dockArea = window.m_Parent as DockArea; - if (dockArea != null) - { - int windowIndex = dockArea.m_Panes.IndexOf(window); - - // Destroy window. - dockArea.RemoveTab(window, false); // Don't kill dock if empty. - UnityEngine.Object.DestroyImmediate(window, true); - - // Create window. - window = EditorWindow.CreateInstance(windowType) as EditorWindow; - dockArea.AddTab(windowIndex, window); - } - else - { - // Close the existing window. - window.Close(); - - // Recreate window. - window = EditorWindow.CreateInstance(windowType) as EditorWindow; - if (window != null) - window.Show(); - } - - // Restore what we can of the window. - EditorJsonUtility.FromJsonOverwrite(windowJson, window); - } - - protected virtual void AddDefaultItemsToMenu(GenericMenu menu, EditorWindow window) - { - if (menu.GetItemCount() != 0) - menu.AddSeparator(""); - - if (Unsupported.IsDeveloperMode()) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Inspect Window"), false, Inspect, window); - menu.AddItem(EditorGUIUtility.TrTextContent("Inspect View"), false, Inspect, window.m_Parent); - menu.AddItem(EditorGUIUtility.TrTextContent("Reload Window _f5"), false, Reload, window); - - menu.AddSeparator(""); - } - } - - protected void ClearBackground() - { - if (Event.current.type != EventType.Repaint) - return; - EditorWindow view = actualView; - if (view != null && view.dontClearBackground) - { - if (backgroundValid && position == m_BackgroundClearRect) - return; - } - Color col = EditorGUIUtility.isProSkin ? EditorGUIUtility.kDarkViewBackground : kViewColor; - GL.Clear(true, true, EditorApplication.isPlayingOrWillChangePlaymode ? col * kPlayModeDarken : col); - backgroundValid = true; - m_BackgroundClearRect = position; - } - } -} diff --git a/Editor/Mono/ICleanuppable.cs b/Editor/Mono/ICleanuppable.cs deleted file mode 100644 index edb2df5192..0000000000 --- a/Editor/Mono/ICleanuppable.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor -{ - internal interface ICleanuppable - { - void Cleanup(); - } -} diff --git a/Editor/Mono/IDropArea.cs b/Editor/Mono/IDropArea.cs deleted file mode 100644 index bf898ae0dc..0000000000 --- a/Editor/Mono/IDropArea.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - // Interface for drag-dropping windows over each other. - // Must be implemented by anyone who can handle a dragged tab. - internal interface IDropArea - { - // Fill out a dropinfo class telling what should be done. - // NULL if no action - DropInfo DragOver(EditorWindow w, Vector2 screenPos); - - // If the client returned a DropInfo from the DragOver, they will get this call when the user releases the mouse - bool PerformDrop(EditorWindow w, DropInfo dropInfo, Vector2 screenPos); - } -} diff --git a/Editor/Mono/IHasCustomMenu.cs b/Editor/Mono/IHasCustomMenu.cs deleted file mode 100644 index 6419415567..0000000000 --- a/Editor/Mono/IHasCustomMenu.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; - -namespace UnityEditor -{ - public interface IHasCustomMenu - { - void AddItemsToMenu(GenericMenu menu); - } -} diff --git a/Editor/Mono/IconSelector.cs b/Editor/Mono/IconSelector.cs deleted file mode 100644 index 51f2ba43ac..0000000000 --- a/Editor/Mono/IconSelector.cs +++ /dev/null @@ -1,351 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class IconSelector : EditorWindow - { - public delegate void MonoScriptIconChangedCallback(MonoScript monoScript); - class Styles - { - public GUIStyle background = "sv_iconselector_back"; - public GUIStyle seperator = "sv_iconselector_sep"; - public GUIStyle selection = "sv_iconselector_selection"; - public GUIStyle selectionLabel = "sv_iconselector_labelselection"; - public GUIStyle noneButton = "sv_iconselector_button"; - } - - static IconSelector s_IconSelector = null; - static long s_LastClosedTime = 0; - static int s_LastInstanceID = -1; - static int s_HashIconSelector = "IconSelector".GetHashCode(); - static Styles m_Styles; - - Object m_TargetObject; - Texture2D m_StartIcon; - bool m_ShowLabelIcons; - private GUIContent[] m_LabelLargeIcons; - private GUIContent[] m_LabelIcons; - private GUIContent[] m_LargeIcons; - private GUIContent[] m_SmallIcons; - private GUIContent m_NoneButtonContent; - private MonoScriptIconChangedCallback m_MonoScriptIconChangedCallback; - - private GUIContent[] GetTextures(string baseName, string postFix, int startIndex, int count) - { - GUIContent[] textures = new GUIContent[count]; - for (int i = 0; i < count; ++i) - textures[i] = EditorGUIUtility.IconContent(baseName + (startIndex + i) + postFix); - return textures; - } - - void OnEnable() - { - hideFlags = HideFlags.DontSave; - } - - void OnDisable() - { - SaveIconChanges(); - - s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - s_IconSelector = null; - } - - void SaveIconChanges() - { - Texture2D currentIcon = EditorGUIUtility.GetIconForObject(m_TargetObject); - - // Only save if we had any changes - if (currentIcon != m_StartIcon) - { - MonoScript monoScript = m_TargetObject as MonoScript; - if (monoScript != null) - { - // If callback is set then it is the callback owner responsiblity to call CopyMonoScriptIconToImporters - if (m_MonoScriptIconChangedCallback != null) - m_MonoScriptIconChangedCallback(monoScript); - else - MonoImporter.CopyMonoScriptIconToImporters(monoScript); - } - } - } - - // Returns true if shown - internal static bool ShowAtPosition(Object targetObj, Rect activatorRect, bool showLabelIcons) - { - int instanceID = targetObj.GetInstanceID(); - // We could not use realtimeSinceStartUp since it is resetted when entering playmode, we assume an increasing time when comparing time. - long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - bool justClosed = nowMilliSeconds < s_LastClosedTime + 50; - if (instanceID != s_LastInstanceID || !justClosed) - { - Event.current.Use(); - s_LastInstanceID = instanceID; - if (s_IconSelector == null) - s_IconSelector = ScriptableObject.CreateInstance(); - s_IconSelector.Init(targetObj, activatorRect, showLabelIcons); - return true; - } - - return false; - } - - internal static void SetMonoScriptIconChangedCallback(MonoScriptIconChangedCallback callback) - { - if (s_IconSelector != null) - s_IconSelector.m_MonoScriptIconChangedCallback = callback; - else - Debug.Log("ERROR: setting callback on hidden IconSelector"); - } - - void Init(Object targetObj, Rect activatorRect, bool showLabelIcons) - { - m_TargetObject = targetObj; - m_StartIcon = EditorGUIUtility.GetIconForObject(m_TargetObject); - m_ShowLabelIcons = showLabelIcons; - Rect screenActivatorRect = GUIUtility.GUIToScreenRect(activatorRect); - - // Remove any keyboard control when opening this window - GUIUtility.keyboardControl = 0; - - // Init GUIContents - m_LabelLargeIcons = GetTextures("sv_label_", "", 0, 8); - m_LabelIcons = GetTextures("sv_icon_name", "", 0, 8); - m_SmallIcons = GetTextures("sv_icon_dot", "_sml", 0, 16); - m_LargeIcons = GetTextures("sv_icon_dot", "_pix16_gizmo", 0, 16); - m_NoneButtonContent = EditorGUIUtility.IconContent("sv_icon_none"); - m_NoneButtonContent.text = "None"; - - // Deal with window size - float k_Width = 140; - float k_Height = 86; - if (m_ShowLabelIcons) - k_Height = 126; - - ShowAsDropDown(screenActivatorRect, new Vector2(k_Width, k_Height)); - } - - private Texture2D ConvertLargeIconToSmallIcon(Texture2D largeIcon, ref bool isLabelIcon) - { - if (largeIcon == null) - return null; - - isLabelIcon = true; - for (int i = 0; i < m_LabelLargeIcons.Length; ++i) - if (m_LabelLargeIcons[i].image == largeIcon) - return (Texture2D)m_LabelIcons[i].image; - - isLabelIcon = false; - for (int i = 0; i < m_LargeIcons.Length; ++i) - if (m_LargeIcons[i].image == largeIcon) - return (Texture2D)m_SmallIcons[i].image; - - return largeIcon; - } - - private Texture2D ConvertSmallIconToLargeIcon(Texture2D smallIcon, bool labelIcon) - { - if (labelIcon) - { - for (int i = 0; i < m_LabelIcons.Length; ++i) - if (m_LabelIcons[i].image == smallIcon) - return (Texture2D)m_LabelLargeIcons[i].image; - } - else - { - for (int i = 0; i < m_SmallIcons.Length; ++i) - if (m_SmallIcons[i].image == smallIcon) - return (Texture2D)m_LargeIcons[i].image; - } - return smallIcon; - } - - void DoButton(GUIContent content, Texture2D selectedIcon, bool labelIcon) - { - int controlID = GUIUtility.GetControlID(s_HashIconSelector, FocusType.Keyboard); - - // Draw selection background if this is the selected icon - if (content.image == selectedIcon) - { - // When placing our selection background we assume that icons rendered from top left corner - Rect rect = GUILayoutUtility.topLevel.PeekNext(); - float pad = 2; - rect.x -= pad; - rect.y -= pad; - rect.width = selectedIcon.width + 2 * pad; - rect.height = selectedIcon.height + 2 * pad; - GUI.Label(rect, GUIContent.none, labelIcon ? m_Styles.selectionLabel : m_Styles.selection); - } - - // Do icon - if (EditorGUILayout.IconButton(controlID, content, GUIStyle.none)) - { - // Map to new icon - Texture2D largeIcon = ConvertSmallIconToLargeIcon((Texture2D)content.image, labelIcon); - Undo.RecordObject(m_TargetObject, "Set Icon On GameObject"); - EditorGUIUtility.SetIconForObject(m_TargetObject, largeIcon); - - // We assume that we are setting icon in an inspector or annotation window (todo: make repaint delegate) - EditorUtility.ForceReloadInspectors(); - AnnotationWindow.IconChanged(); - - // Close on double click - if (Event.current.clickCount == 2) - CloseWindow(); - } - } - - void DoTopSection(bool anySelected) - { - Rect selectIconRect = new Rect(6, 4, 110, 20); - GUI.Label(selectIconRect, "Select Icon"); - - // Draw selection background if none is selected - using (new EditorGUI.DisabledScope(!anySelected)) - { - Rect noneButtonRect = new Rect(93, 6, 43, 12); - if (GUI.Button(noneButtonRect, m_NoneButtonContent, m_Styles.noneButton)) - { - EditorGUIUtility.SetIconForObject(m_TargetObject, null); - EditorUtility.ForceReloadInspectors(); - AnnotationWindow.IconChanged(); - } - } - } - - private void CloseWindow() - { - Close(); - GUI.changed = true; - GUIUtility.ExitGUI(); - } - - internal void OnGUI() - { - // Here due to static vars being thrown out when reloading assemblies - if (m_Styles == null) - m_Styles = new Styles(); - - // Escape pressed? - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - { - CloseWindow(); - } - - Texture2D selectedIcon = EditorGUIUtility.GetIconForObject(m_TargetObject); - bool isSelectionALabelIcon = false; - if (Event.current.type == EventType.Repaint) - { - selectedIcon = ConvertLargeIconToSmallIcon(selectedIcon, ref isSelectionALabelIcon); - } - - Event evt = Event.current; - EventType eventType = evt.type; - - GUI.BeginGroup(new Rect(0, 0, position.width, position.height), m_Styles.background); - - DoTopSection(selectedIcon != null); - - GUILayout.Space(22); - GUILayout.BeginHorizontal(); - GUILayout.Space(1); - GUI.enabled = false; - GUILayout.Label("", m_Styles.seperator); - GUI.enabled = true; - GUILayout.Space(1); - GUILayout.EndHorizontal(); - GUILayout.Space(3); - - if (m_ShowLabelIcons) - { - // Label icons - GUILayout.BeginHorizontal(); - GUILayout.Space(6); - for (int i = 0; i < m_LabelIcons.Length / 2; ++i) - DoButton(m_LabelIcons[i], selectedIcon, true); - GUILayout.EndHorizontal(); - - GUILayout.Space(5); - - GUILayout.BeginHorizontal(); - GUILayout.Space(6); - for (int i = m_LabelIcons.Length / 2; i < m_LabelIcons.Length; ++i) - DoButton(m_LabelIcons[i], selectedIcon, true); - GUILayout.EndHorizontal(); - - GUILayout.Space(3); - GUILayout.BeginHorizontal(); - GUILayout.Space(1); - GUI.enabled = false; - GUILayout.Label("", m_Styles.seperator); - GUI.enabled = true; - GUILayout.Space(1); - GUILayout.EndHorizontal(); - GUILayout.Space(3); - } - - // Small icons - GUILayout.BeginHorizontal(); - GUILayout.Space(9); - for (int i = 0; i < m_SmallIcons.Length / 2; ++i) - DoButton(m_SmallIcons[i], selectedIcon, false); - GUILayout.Space(3); - GUILayout.EndHorizontal(); - - GUILayout.Space(6); - - GUILayout.BeginHorizontal(); - GUILayout.Space(9); - for (int i = m_SmallIcons.Length / 2; i < m_SmallIcons.Length; ++i) - DoButton(m_SmallIcons[i], selectedIcon, false); - GUILayout.Space(3); - GUILayout.EndHorizontal(); - GUILayout.Space(6); - - // Object selector section - GUI.backgroundColor = new Color(1, 1, 1, 0.7f); - bool clicked = false; - int id = GUIUtility.GetControlID(s_HashIconSelector, FocusType.Keyboard); - if (GUILayout.Button(EditorGUIUtility.TempContent("Other..."))) - { - GUIUtility.keyboardControl = id; - clicked = true; - } - GUI.backgroundColor = new Color(1, 1, 1, 1); - GUI.EndGroup(); - - if (clicked) - { - ObjectSelector.get.Show(m_TargetObject, typeof(Texture2D), null, false); - ObjectSelector.get.objectSelectorID = id; - GUI.backgroundColor = new Color(1, 1, 1, 0.7f); - evt.Use(); - GUIUtility.ExitGUI(); - } - - // Check for icon selected from ObjectSelector - switch (eventType) - { - case EventType.ExecuteCommand: - string commandName = evt.commandName; - if (commandName == ObjectSelector.ObjectSelectorUpdatedCommand && ObjectSelector.get.objectSelectorID == id && GUIUtility.keyboardControl == id) - { - Texture2D icon = ObjectSelector.GetCurrentObject() as Texture2D; - Undo.RecordObject(m_TargetObject, "Set Icon On GameObject"); - EditorGUIUtility.SetIconForObject(m_TargetObject, icon); - - GUI.changed = true; - evt.Use(); - } - break; - } - } - } -} diff --git a/Editor/Mono/ImportSettings/AnimationClipInfoProperties.cs b/Editor/Mono/ImportSettings/AnimationClipInfoProperties.cs deleted file mode 100644 index 776ab23ef0..0000000000 --- a/Editor/Mono/ImportSettings/AnimationClipInfoProperties.cs +++ /dev/null @@ -1,453 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using UnityEditor.Animations; -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections.Generic; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AnimationClipInfoProperties - { - SerializedProperty m_Property; - - private SerializedProperty Get(string property) { return m_Property.FindPropertyRelative(property); } - - public AnimationClipInfoProperties(SerializedProperty prop) { m_Property = prop; } - - public string name { get { return Get("name").stringValue; } set { Get("name").stringValue = value; } } - public string takeName { get { return Get("takeName").stringValue; } set { Get("takeName").stringValue = value; } } - public float firstFrame { get { return Get("firstFrame").floatValue; } set { Get("firstFrame").floatValue = value; } } - public float lastFrame { get { return Get("lastFrame").floatValue; } set { Get("lastFrame").floatValue = value; } } - public int wrapMode { get { return Get("wrapMode").intValue; } set { Get("wrapMode").intValue = value; } } - public bool loop { get { return Get("loop").boolValue; } set { Get("loop").boolValue = value; } } - - // Mecanim animation properties - public float orientationOffsetY { get { return Get("orientationOffsetY").floatValue; } set { Get("orientationOffsetY").floatValue = value; } } - public float level { get { return Get("level").floatValue; } set { Get("level").floatValue = value; } } - public float cycleOffset { get { return Get("cycleOffset").floatValue; } set { Get("cycleOffset").floatValue = value; } } - public float additiveReferencePoseFrame { get { return Get("additiveReferencePoseFrame").floatValue; } set { Get("additiveReferencePoseFrame").floatValue = value; } } - public bool hasAdditiveReferencePose { get { return Get("hasAdditiveReferencePose").boolValue; } set { Get("hasAdditiveReferencePose").boolValue = value; } } - public bool loopTime { get { return Get("loopTime").boolValue; } set { Get("loopTime").boolValue = value; } } - public bool loopBlend { get { return Get("loopBlend").boolValue; } set { Get("loopBlend").boolValue = value; } } - public bool loopBlendOrientation { get { return Get("loopBlendOrientation").boolValue; } set { Get("loopBlendOrientation").boolValue = value; } } - public bool loopBlendPositionY { get { return Get("loopBlendPositionY").boolValue; } set { Get("loopBlendPositionY").boolValue = value; } } - public bool loopBlendPositionXZ { get { return Get("loopBlendPositionXZ").boolValue; } set { Get("loopBlendPositionXZ").boolValue = value; } } - public bool keepOriginalOrientation { get { return Get("keepOriginalOrientation").boolValue; } set { Get("keepOriginalOrientation").boolValue = value; } } - public bool keepOriginalPositionY { get { return Get("keepOriginalPositionY").boolValue; } set { Get("keepOriginalPositionY").boolValue = value; } } - public bool keepOriginalPositionXZ { get { return Get("keepOriginalPositionXZ").boolValue; } set { Get("keepOriginalPositionXZ").boolValue = value; } } - public bool heightFromFeet { get { return Get("heightFromFeet").boolValue; } set { Get("heightFromFeet").boolValue = value; } } - public bool mirror { get { return Get("mirror").boolValue; } set { Get("mirror").boolValue = value; } } - public ClipAnimationMaskType maskType { get { return (ClipAnimationMaskType)Get("maskType").intValue; } set { Get("maskType").intValue = (int)value; } } - public SerializedProperty maskTypeProperty { get { return Get("maskType"); } } - public AvatarMask maskSource { get { return Get("maskSource").objectReferenceValue as AvatarMask; } set { Get("maskSource").objectReferenceValue = value; } } - public SerializedProperty maskSourceProperty { get { return Get("maskSource"); } } - public SerializedProperty bodyMaskProperty { get { return Get("bodyMask"); } } - public SerializedProperty transformMaskProperty { get { return Get("transformMask"); } } - - public bool MaskNeedsUpdating() - { - AvatarMask mask = maskSource; - if (mask == null) - return false; - - SerializedProperty bodyMask = Get("bodyMask"); - - if (bodyMask != null && bodyMask.isArray) - { - for (AvatarMaskBodyPart i = 0; i < AvatarMaskBodyPart.LastBodyPart; i++) - { - if (mask.GetHumanoidBodyPartActive(i) != (bodyMask.GetArrayElementAtIndex((int)i).intValue != 0)) - return true; - } - } - else - { - return true; - } - - SerializedProperty transformMask = Get("transformMask"); - - if (transformMask != null && transformMask.isArray) - { - if (transformMask.arraySize > 0 && (mask.transformCount != transformMask.arraySize)) - return true; - - int size = transformMask.arraySize; - for (int i = 0; i < size; i++) - { - SerializedProperty pathProperty = transformMask.GetArrayElementAtIndex(i).FindPropertyRelative("m_Path"); - SerializedProperty weightProperty = transformMask.GetArrayElementAtIndex(i).FindPropertyRelative("m_Weight"); - - if (mask.GetTransformPath(i) != pathProperty.stringValue || - mask.GetTransformActive(i) != (weightProperty.floatValue > 0.5f)) - return true; - } - } - else - { - return true; - } - - return false; - } - - public void MaskFromClip(AvatarMask mask) - { - SerializedProperty bodyMask = Get("bodyMask"); - - if (bodyMask != null && bodyMask.isArray) - { - for (AvatarMaskBodyPart i = 0; i < AvatarMaskBodyPart.LastBodyPart; i++) - { - mask.SetHumanoidBodyPartActive(i, bodyMask.GetArrayElementAtIndex((int)i).intValue != 0); - } - } - - SerializedProperty transformMask = Get("transformMask"); - - if (transformMask != null && transformMask.isArray) - { - if (transformMask.arraySize > 0 && (mask.transformCount != transformMask.arraySize)) - mask.transformCount = transformMask.arraySize; - - int size = transformMask.arraySize; - if (size == 0) - return; - - SerializedProperty prop = transformMask.GetArrayElementAtIndex(0); - - for (int i = 0; i < size; i++) - { - SerializedProperty pathProperty = prop.FindPropertyRelative("m_Path"); - SerializedProperty weightProperty = prop.FindPropertyRelative("m_Weight"); - mask.SetTransformPath(i, pathProperty.stringValue); - mask.SetTransformActive(i, weightProperty.floatValue > 0.5); - prop.Next(false); - } - } - } - - public void MaskToClip(AvatarMask mask) - { - SerializedProperty bodyMask = Get("bodyMask"); - - if (bodyMask != null && bodyMask.isArray) - { - for (AvatarMaskBodyPart i = 0; i < AvatarMaskBodyPart.LastBodyPart; i++) - { - if ((int)i >= bodyMask.arraySize) bodyMask.InsertArrayElementAtIndex((int)i); - bodyMask.GetArrayElementAtIndex((int)i).intValue = mask.GetHumanoidBodyPartActive(i) ? 1 : 0; - } - } - - SerializedProperty transformMask = Get("transformMask"); - ModelImporter.UpdateTransformMask(mask, transformMask); - } - - public void ClearCurves() - { - SerializedProperty curves = Get("curves"); - - if (curves != null && curves.isArray) - { - curves.ClearArray(); - } - } - - public int GetCurveCount() - { - int ret = 0; - - SerializedProperty curves = Get("curves"); - - if (curves != null && curves.isArray) - { - ret = curves.arraySize; - } - - return ret; - } - - public SerializedProperty GetCurveProperty(int index) - { - SerializedProperty ret = null; - - SerializedProperty curves = Get("curves"); - - if (curves != null && curves.isArray) - { - ret = curves.GetArrayElementAtIndex(index).FindPropertyRelative("curve"); - } - - return ret; - } - - public string GetCurveName(int index) - { - string ret = ""; - - SerializedProperty curves = Get("curves"); - - if (curves != null && curves.isArray) - { - ret = curves.GetArrayElementAtIndex(index).FindPropertyRelative("name").stringValue; - } - - return ret; - } - - public void SetCurveName(int index, string name) - { - SerializedProperty curves = Get("curves"); - - if (curves != null && curves.isArray) - { - curves.GetArrayElementAtIndex(index).FindPropertyRelative("name").stringValue = name; - } - } - - public AnimationCurve GetCurve(int index) - { - AnimationCurve ret = null; - - SerializedProperty curve = GetCurveProperty(index); - - if (curve != null) - { - ret = curve.animationCurveValue; - } - - return ret; - } - - public void SetCurve(int index, AnimationCurve curveValue) - { - SerializedProperty curve = GetCurveProperty(index); - - if (curve != null) - { - curve.animationCurveValue = curveValue; - } - } - - public void AddCurve() - { - SerializedProperty curves = Get("curves"); - - if (curves != null && curves.isArray) - { - curves.InsertArrayElementAtIndex(curves.arraySize); - curves.GetArrayElementAtIndex(curves.arraySize - 1).FindPropertyRelative("name").stringValue = "Curve"; - AnimationCurve newCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(1, 0)); - newCurve.preWrapMode = WrapMode.Default; - newCurve.postWrapMode = WrapMode.Default; - curves.GetArrayElementAtIndex(curves.arraySize - 1).FindPropertyRelative("curve").animationCurveValue = newCurve; - } - } - - public void RemoveCurve(int index) - { - SerializedProperty curves = Get("curves"); - - if (curves != null && curves.isArray) - { - curves.DeleteArrayElementAtIndex(index); - } - } - - public AnimationEvent GetEvent(int index) - { - AnimationEvent evt = new AnimationEvent(); - SerializedProperty events = Get("events"); - - if (events != null && events.isArray) - { - if (index < events.arraySize) - { - evt.floatParameter = events.GetArrayElementAtIndex(index).FindPropertyRelative("floatParameter").floatValue; - evt.functionName = events.GetArrayElementAtIndex(index).FindPropertyRelative("functionName").stringValue; - evt.intParameter = events.GetArrayElementAtIndex(index).FindPropertyRelative("intParameter").intValue; - evt.objectReferenceParameter = events.GetArrayElementAtIndex(index).FindPropertyRelative("objectReferenceParameter").objectReferenceValue; - evt.stringParameter = events.GetArrayElementAtIndex(index).FindPropertyRelative("data").stringValue; - evt.time = events.GetArrayElementAtIndex(index).FindPropertyRelative("time").floatValue; - } - else - { - Debug.LogWarning("Invalid Event Index"); - } - } - - return evt; - } - - public void SetEvent(int index, AnimationEvent animationEvent) - { - SerializedProperty events = Get("events"); - - if (events != null && events.isArray) - { - if (index < events.arraySize) - { - events.GetArrayElementAtIndex(index).FindPropertyRelative("floatParameter").floatValue = animationEvent.floatParameter; - events.GetArrayElementAtIndex(index).FindPropertyRelative("functionName").stringValue = animationEvent.functionName; - events.GetArrayElementAtIndex(index).FindPropertyRelative("intParameter").intValue = animationEvent.intParameter; - events.GetArrayElementAtIndex(index).FindPropertyRelative("objectReferenceParameter").objectReferenceValue = animationEvent.objectReferenceParameter; - events.GetArrayElementAtIndex(index).FindPropertyRelative("data").stringValue = animationEvent.stringParameter; - events.GetArrayElementAtIndex(index).FindPropertyRelative("time").floatValue = animationEvent.time; - } - else - { - Debug.LogWarning("Invalid Event Index"); - } - } - } - - public void ClearEvents() - { - SerializedProperty events = Get("events"); - - if (events != null && events.isArray) - { - events.ClearArray(); - } - } - - public int GetEventCount() - { - int ret = 0; - - SerializedProperty curves = Get("events"); - - if (curves != null && curves.isArray) - { - ret = curves.arraySize; - } - - return ret; - } - - public void AddEvent(float time) - { - SerializedProperty events = Get("events"); - - if (events != null && events.isArray) - { - events.InsertArrayElementAtIndex(events.arraySize); - events.GetArrayElementAtIndex(events.arraySize - 1).FindPropertyRelative("functionName").stringValue = "NewEvent"; - events.GetArrayElementAtIndex(events.arraySize - 1).FindPropertyRelative("time").floatValue = time; - } - } - - public void RemoveEvent(int index) - { - SerializedProperty events = Get("events"); - - if (events != null && events.isArray) - { - events.DeleteArrayElementAtIndex(index); - } - } - - public void SetEvents(AnimationEvent[] newEvents) - { - SerializedProperty events = Get("events"); - - if (events != null && events.isArray) - { - events.ClearArray(); - - foreach (AnimationEvent evt in newEvents) - { - events.InsertArrayElementAtIndex(events.arraySize); - SetEvent(events.arraySize - 1, evt); - } - } - } - - public AnimationEvent[] GetEvents() - { - AnimationEvent[] ret = new AnimationEvent[GetEventCount()]; - SerializedProperty events = Get("events"); - - if (events != null && events.isArray) - { - for (int i = 0; i < GetEventCount(); ++i) - { - ret[i] = GetEvent(i); - } - } - - return ret; - } - - public void AssignToPreviewClip(AnimationClip clip) - { - AnimationClipSettings info = new AnimationClipSettings(); - - info.startTime = firstFrame / clip.frameRate; - info.stopTime = lastFrame / clip.frameRate; - info.orientationOffsetY = orientationOffsetY; - info.level = level; - info.cycleOffset = cycleOffset; - info.loopTime = loopTime; - info.loopBlend = loopBlend; - info.loopBlendOrientation = loopBlendOrientation; - info.loopBlendPositionY = loopBlendPositionY; - info.loopBlendPositionXZ = loopBlendPositionXZ; - info.keepOriginalOrientation = keepOriginalOrientation; - info.keepOriginalPositionY = keepOriginalPositionY; - info.keepOriginalPositionXZ = keepOriginalPositionXZ; - info.heightFromFeet = heightFromFeet; - info.mirror = mirror; - info.hasAdditiveReferencePose = hasAdditiveReferencePose; - info.additiveReferencePoseTime = additiveReferencePoseFrame / clip.frameRate; - - AnimationUtility.SetAnimationClipSettingsNoDirty(clip, info); - } - - private float FixPrecisionErrors(float f) - { - float rounded = Mathf.Round(f); - if (Mathf.Abs(f - rounded) < 0.0001f) - return rounded; - return f; - } - - public void ExtractFromPreviewClip(AnimationClip clip) - { - AnimationClipSettings info = AnimationUtility.GetAnimationClipSettings(clip); - - // Ensure that we don't accidentally dirty settings due to floating point precision in the multiply / divide - if (firstFrame / clip.frameRate != info.startTime) - firstFrame = FixPrecisionErrors(info.startTime * clip.frameRate); - if (lastFrame / clip.frameRate != info.stopTime) - lastFrame = FixPrecisionErrors(info.stopTime * clip.frameRate); - - orientationOffsetY = info.orientationOffsetY; - level = info.level; - cycleOffset = info.cycleOffset; - loopTime = info.loopTime; - loopBlend = info.loopBlend; - loopBlendOrientation = info.loopBlendOrientation; - loopBlendPositionY = info.loopBlendPositionY; - loopBlendPositionXZ = info.loopBlendPositionXZ; - keepOriginalOrientation = info.keepOriginalOrientation; - keepOriginalPositionY = info.keepOriginalPositionY; - keepOriginalPositionXZ = info.keepOriginalPositionXZ; - heightFromFeet = info.heightFromFeet; - mirror = info.mirror; - - hasAdditiveReferencePose = info.hasAdditiveReferencePose; - - if (additiveReferencePoseFrame / clip.frameRate != info.additiveReferencePoseTime) - additiveReferencePoseFrame = FixPrecisionErrors(info.additiveReferencePoseTime * clip.frameRate); - } - } -} diff --git a/Editor/Mono/ImportSettings/AssetImporterEditor.cs b/Editor/Mono/ImportSettings/AssetImporterEditor.cs deleted file mode 100644 index d76453f9c0..0000000000 --- a/Editor/Mono/ImportSettings/AssetImporterEditor.cs +++ /dev/null @@ -1,284 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor.Experimental.AssetImporters -{ - public abstract class AssetImporterEditor : Editor - { - ulong m_AssetTimeStamp = 0; - bool m_MightHaveModified = false; - - private Editor m_AssetEditor; - // Called from ActiveEditorTracker.cpp to setup the target editor once created before Awake and OnEnable of the Editor. - internal void InternalSetAssetImporterTargetEditor(Object editor) - { - m_AssetEditor = editor as Editor; - } - - protected internal Object[] assetTargets { get { return m_AssetEditor != null ? m_AssetEditor.targets : null; } } - protected internal Object assetTarget { get { return m_AssetEditor != null ? m_AssetEditor.target : null; } } - protected internal SerializedObject assetSerializedObject { get { return m_AssetEditor != null ? m_AssetEditor.serializedObject : null; } } - - internal override string targetTitle - { - get - { - return string.Format(L10n.Tr("{0} Import Settings"), m_AssetEditor == null ? string.Empty : m_AssetEditor.targetTitle); - } - } - - internal override int referenceTargetIndex - { - get { return base.referenceTargetIndex; } - set - { - base.referenceTargetIndex = value; - if (m_AssetEditor != null) - m_AssetEditor.referenceTargetIndex = value; - } - } - - internal override IPreviewable preview - { - get - { - if (useAssetDrawPreview && m_AssetEditor != null) - return m_AssetEditor; - // Sometimes assetEditor has gone away because of "magical" workarounds and we need to fall back to base.Preview. - // See cases 597496 and 601174 for context. - return base.preview; - } - } - - //We usually want to redirect the DrawPreview to the assetEditor, but there are few cases we don't want that. - //If you want to use the Importer DrawPreview, then override useAssetDrawPreview to false. - protected virtual bool useAssetDrawPreview { get { return true; } } - - // Make the Importer use the icon of the asset - internal override void OnHeaderIconGUI(Rect iconRect) - { - if (m_AssetEditor != null) - m_AssetEditor.OnHeaderIconGUI(iconRect); - } - - // Let asset importers decide if the imported object should be shown as a separate editor or not - public virtual bool showImportedObject { get { return true; } } - - internal override SerializedObject GetSerializedObjectInternal() - { - if (m_SerializedObject == null) - m_SerializedObject = SerializedObject.LoadFromCache(GetInstanceID()); - if (m_SerializedObject == null) - m_SerializedObject = new SerializedObject(targets); - return m_SerializedObject; - } - - public virtual void OnEnable() - { - // warning: if you add anything here make sure every descent of this class calls this properly... - } - - public virtual void OnDisable() - { - ////FIXME: The code below wreaks havoc with tabbed editors. Triggering a re-import will - //// cause all active editors to be destroyed which, if we're part of a tabbed editor, - //// will take down our parent while it is trying to switch editors. Also, we'll be - //// doing all this while InspectorWindow.OnGUI() is still going through the active - //// editors to draw them so we're killing them right under its nose. - - // When destroying the inspector check if we have any unapplied modifications - // and apply them. - AssetImporter importer = target as AssetImporter; - if (Unsupported.IsDestroyScriptableObject(this) && m_MightHaveModified && importer != null && !InternalEditorUtility.ignoreInspectorChanges && HasModified() && !AssetWasUpdated()) - { - string dialogText = string.Format(L10n.Tr("Unapplied import settings for \'{0}\'"), importer.assetPath); - - if (targets.Length > 1) - dialogText = string.Format(L10n.Tr("Unapplied import settings for \'{0}\' files"), targets.Length); - - if (EditorUtility.DisplayDialog(L10n.Tr("Unapplied import settings"), dialogText, L10n.Tr("Apply"), L10n.Tr("Revert"))) - { - Apply(); - m_MightHaveModified = false; - ImportAssets(GetAssetPaths()); - } - } - - // Only cache SerializedObject if it has modified properties. - // If we have multiple editors (e.g. a tabbed editor and its editor for the active tab) we don't - // want the one that doesn't do anything with the SerializedObject to overwrite the cache. - if (m_SerializedObject != null && m_SerializedObject.hasModifiedProperties) - { - m_SerializedObject.Cache(GetInstanceID()); - m_SerializedObject = null; - } - } - - protected virtual void Awake() - { - ResetTimeStamp(); - ResetValues(); - } - - private string[] GetAssetPaths() - { - Object[] allTargets = targets; - string[] paths = new string[allTargets.Length]; - for (int i = 0; i < allTargets.Length; i++) - { - AssetImporter importer = allTargets[i] as AssetImporter; - paths[i] = importer.assetPath; - } - return paths; - } - - protected virtual void ResetValues() - { - serializedObject.SetIsDifferentCacheDirty(); - serializedObject.Update(); - } - - public virtual bool HasModified() - { - return serializedObject.hasModifiedProperties; - } - - protected virtual void Apply() - { - serializedObject.ApplyModifiedPropertiesWithoutUndo(); - } - - internal bool AssetWasUpdated() - { - AssetImporter importer = target as AssetImporter; - if (m_AssetTimeStamp == 0) - ResetTimeStamp(); - return importer != null && m_AssetTimeStamp != importer.assetTimeStamp; - } - - internal void ResetTimeStamp() - { - AssetImporter importer = target as AssetImporter; - if (importer != null) - m_AssetTimeStamp = importer.assetTimeStamp; - } - - protected internal void ApplyAndImport() - { - Apply(); - m_MightHaveModified = false; - ImportAssets(GetAssetPaths()); - ResetValues(); - } - - private void ImportAssets(string[] paths) - { - // When using the cache server we have to write all import settings to disk first. - // Then perform the import (Otherwise the cache server will not be used for the import) - foreach (string path in paths) - AssetDatabase.WriteImportSettingsIfDirty(path); - - try - { - AssetDatabase.StartAssetEditing(); - foreach (string path in paths) - AssetDatabase.ImportAsset(path); - } - finally - { - AssetDatabase.StopAssetEditing(); - } - - OnAssetImportDone(); - } - - internal virtual void OnAssetImportDone() - { - // Default, do nothing. - } - - protected void RevertButton() - { - RevertButton(L10n.Tr("Revert")); - } - - protected void RevertButton(string buttonText) - { - if (GUILayout.Button(buttonText)) - { - m_MightHaveModified = false; - ResetTimeStamp(); - ResetValues(); - if (HasModified()) - Debug.LogError("Importer reports modified values after reset."); - } - } - - protected bool ApplyButton() - { - return ApplyButton(L10n.Tr("Apply")); - } - - protected bool ApplyButton(string buttonText) - { - if (GUILayout.Button(buttonText)) - { - ApplyAndImport(); - return true; - } - return false; - } - - protected virtual bool OnApplyRevertGUI() - { - using (new EditorGUI.DisabledScope(!HasModified())) - { - RevertButton(); - return ApplyButton(); - } - } - - protected void ApplyRevertGUI() - { - if (m_AssetEditor == null || m_AssetEditor.target == null) - { - // always apply changes when buttons are hidden - Apply(); - return; - } - - m_MightHaveModified = true; - EditorGUILayout.Space(); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - var applied = false; - applied = OnApplyRevertGUI(); - - // If the .meta file was modified on disk, reload UI - if (AssetWasUpdated() && Event.current.type != EventType.Layout) - { - IPreviewable previewable = preview; - if (previewable != null) - previewable.ReloadPreviewInstances(); - - ResetTimeStamp(); - ResetValues(); - Repaint(); - } - - GUILayout.EndHorizontal(); - - // asset has changed... - // need to start rendering again. - if (applied) - GUIUtility.ExitGUI(); - } - } -} diff --git a/Editor/Mono/ImportSettings/AudioImporterInspector.cs b/Editor/Mono/ImportSettings/AudioImporterInspector.cs deleted file mode 100644 index 0016a8fb62..0000000000 --- a/Editor/Mono/ImportSettings/AudioImporterInspector.cs +++ /dev/null @@ -1,656 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditor.Build; - -using System.Collections.Generic; -using System; -using System.Linq; -using UnityEditor.Experimental.AssetImporters; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioImporter))] - [CanEditMultipleObjects] - internal class AudioImporterInspector : AssetImporterEditor - { - private static class Styles - { - public static readonly string[] kSampleRateStrings = new[] {"8,000 Hz", "11,025 Hz", "22,050 Hz", "44,100 Hz", "48,000 Hz", "96,000 Hz", "192,000 Hz"}; - public static readonly int[] kSampleRateValues = new[] {8000, 11025, 22050, 44100, 48000, 96000, 192000}; - } - - private struct MultiValueStatus - { - public bool multiLoadType; - public bool multiSampleRateSetting; - public bool multiSampleRateOverride; - public bool multiCompressionFormat; - public bool multiQuality; - public bool multiConversionMode; - } - - private struct SampleSettingProperties - { - public AudioImporterSampleSettings settings; - - //Override the settings for all the targets (only used for the platform overrides) - public bool forcedOverrideState; - public bool overrideIsForced; - - //Overridden status - public bool loadTypeChanged; - public bool sampleRateSettingChanged; - public bool sampleRateOverrideChanged; - public bool compressionFormatChanged; - public bool qualityChanged; - public bool conversionModeChanged; - - public bool HasModified() - { - return overrideIsForced || loadTypeChanged || sampleRateSettingChanged || sampleRateOverrideChanged || - compressionFormatChanged || qualityChanged || conversionModeChanged; - } - - public void ClearChangedFlags() - { - forcedOverrideState = false; - overrideIsForced = false; - loadTypeChanged = false; - sampleRateSettingChanged = false; - sampleRateOverrideChanged = false; - compressionFormatChanged = false; - qualityChanged = false; - conversionModeChanged = false; - } - } - - public SerializedProperty m_ForceToMono; - public SerializedProperty m_Normalize; - public SerializedProperty m_PreloadAudioData; - public SerializedProperty m_Ambisonic; - public SerializedProperty m_LoadInBackground; - public SerializedProperty m_OrigSize; - public SerializedProperty m_CompSize; - - private SampleSettingProperties m_DefaultSampleSettings; - private Dictionary m_SampleSettingOverrides; - - private IEnumerable GetAllAudioImporterTargets() - { - foreach (UnityEngine.Object importer in targets) - { - AudioImporter audioImporter = importer as AudioImporter; - if (audioImporter != null) - yield return audioImporter; - } - } - - private bool SyncSettingsToBackend() - { - BuildPlatform[] validPlatforms = BuildPlatforms.instance.GetValidPlatforms().ToArray(); - - foreach (AudioImporter importer in GetAllAudioImporterTargets()) - { - { - AudioImporterSampleSettings importerDefaults = importer.defaultSampleSettings; - - //Importer default settings - if (m_DefaultSampleSettings.loadTypeChanged) - importerDefaults.loadType = m_DefaultSampleSettings.settings.loadType; - - if (m_DefaultSampleSettings.sampleRateSettingChanged) - importerDefaults.sampleRateSetting = m_DefaultSampleSettings.settings.sampleRateSetting; - - if (m_DefaultSampleSettings.sampleRateOverrideChanged) - importerDefaults.sampleRateOverride = m_DefaultSampleSettings.settings.sampleRateOverride; - - if (m_DefaultSampleSettings.compressionFormatChanged) - importerDefaults.compressionFormat = m_DefaultSampleSettings.settings.compressionFormat; - - if (m_DefaultSampleSettings.qualityChanged) - importerDefaults.quality = m_DefaultSampleSettings.settings.quality; - - if (m_DefaultSampleSettings.conversionModeChanged) - importerDefaults.conversionMode = m_DefaultSampleSettings.settings.conversionMode; - - //Set the default settings on the importer after the changes. - importer.defaultSampleSettings = importerDefaults; - } - - //Get all the valid platforms, and write changes only for those ones - foreach (BuildPlatform platform in validPlatforms) - { - BuildTargetGroup platformGroup = platform.targetGroup; - - if (m_SampleSettingOverrides.ContainsKey(platformGroup)) - { - SampleSettingProperties overrideProperties = m_SampleSettingOverrides[platformGroup]; - - if (overrideProperties.overrideIsForced && !overrideProperties.forcedOverrideState) - { - importer.Internal_ClearSampleSettingOverride(platformGroup); - } - else if (importer.Internal_ContainsSampleSettingsOverride(platformGroup) || - (overrideProperties.overrideIsForced && overrideProperties.forcedOverrideState)) - { - AudioImporterSampleSettings overrideSettings = importer.Internal_GetOverrideSampleSettings(platformGroup); - - if (overrideProperties.loadTypeChanged) - overrideSettings.loadType = overrideProperties.settings.loadType; - - if (overrideProperties.sampleRateSettingChanged) - overrideSettings.sampleRateSetting = overrideProperties.settings.sampleRateSetting; - - if (overrideProperties.sampleRateOverrideChanged) - overrideSettings.sampleRateOverride = overrideProperties.settings.sampleRateOverride; - - if (overrideProperties.compressionFormatChanged) - overrideSettings.compressionFormat = overrideProperties.settings.compressionFormat; - - if (overrideProperties.qualityChanged) - overrideSettings.quality = overrideProperties.settings.quality; - - if (overrideProperties.conversionModeChanged) - overrideSettings.conversionMode = overrideProperties.settings.conversionMode; - - //Set the default settings on the importer after the changes. - importer.Internal_SetOverrideSampleSettings(platformGroup, overrideSettings); - } - - m_SampleSettingOverrides[platformGroup] = overrideProperties; - } - } - } - - //Now that we are in sync with the backend, we need to clear the changed flags within - //the properties - m_DefaultSampleSettings.ClearChangedFlags(); - - foreach (BuildPlatform platform in validPlatforms) - { - BuildTargetGroup platformGroup = platform.targetGroup; - if (m_SampleSettingOverrides.ContainsKey(platformGroup)) - { - SampleSettingProperties overrideProperties = m_SampleSettingOverrides[platformGroup]; - overrideProperties.ClearChangedFlags(); - m_SampleSettingOverrides[platformGroup] = overrideProperties; - } - } - - return true; - } - - private void ResetSettingsFromBackend() - { - if (GetAllAudioImporterTargets().Any()) - { - AudioImporter firstImporter = GetAllAudioImporterTargets().First(); - //Just load the settings from the first importer for the default settings - m_DefaultSampleSettings.settings = firstImporter.defaultSampleSettings; - m_DefaultSampleSettings.ClearChangedFlags(); - - m_SampleSettingOverrides = new Dictionary(); - List validPlatforms = BuildPlatforms.instance.GetValidPlatforms(); - foreach (BuildPlatform platform in validPlatforms) - { - BuildTargetGroup platformGroup = platform.targetGroup; - foreach (AudioImporter importer in GetAllAudioImporterTargets()) - { - if (importer.Internal_ContainsSampleSettingsOverride(platformGroup)) - { - SampleSettingProperties newProperties = new SampleSettingProperties(); - newProperties.settings = importer.Internal_GetOverrideSampleSettings(platformGroup); - - m_SampleSettingOverrides[platformGroup] = newProperties; - - //Just grab the first settings we find from any of the importers. - //This will be sorted later by checking if there are any differences between importers. - break; - } - } - - //If we failed to find a valid override setting, just create a default one for use later. - if (!m_SampleSettingOverrides.ContainsKey(platformGroup)) - { - SampleSettingProperties newProperties = new SampleSettingProperties(); - newProperties.settings = firstImporter.Internal_GetOverrideSampleSettings(platformGroup); - - m_SampleSettingOverrides[platformGroup] = newProperties; - } - } - } - } - - public bool CurrentPlatformHasAutoTranslatedCompression() - { - BuildTargetGroup targetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget); - - foreach (AudioImporter importer in GetAllAudioImporterTargets()) - { - AudioCompressionFormat defaultCompressionFormat = importer.defaultSampleSettings.compressionFormat; - // Because we only want to query if the importer does not have an override. - if (!importer.Internal_ContainsSampleSettingsOverride(targetGroup)) - { - AudioImporterSampleSettings overrideSettings = importer.Internal_GetOverrideSampleSettings(targetGroup); - AudioCompressionFormat overrideCompressionFormat = overrideSettings.compressionFormat; - - // If we dont have an override, but the translated compression format is different, - // this means we have audio translate happening. - if (defaultCompressionFormat != overrideCompressionFormat) - return true; - } - } - - return false; - } - - public bool IsHardwareSound(AudioCompressionFormat format) - { - switch (format) - { - case AudioCompressionFormat.HEVAG: - case AudioCompressionFormat.VAG: - case AudioCompressionFormat.XMA: - case AudioCompressionFormat.GCADPCM: - return true; - default: - return false; - } - } - - public bool CurrentSelectionContainsHardwareSounds() - { - BuildTargetGroup targetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget); - - foreach (AudioImporter importer in GetAllAudioImporterTargets()) - { - AudioImporterSampleSettings overrideSettings = importer.Internal_GetOverrideSampleSettings(targetGroup); - if (IsHardwareSound(overrideSettings.compressionFormat)) - return true; - } - - return false; - } - - public override void OnEnable() - { - m_ForceToMono = serializedObject.FindProperty("m_ForceToMono"); - m_Normalize = serializedObject.FindProperty("m_Normalize"); - m_PreloadAudioData = serializedObject.FindProperty("m_PreloadAudioData"); - m_Ambisonic = serializedObject.FindProperty("m_Ambisonic"); - m_LoadInBackground = serializedObject.FindProperty("m_LoadInBackground"); - m_OrigSize = serializedObject.FindProperty("m_PreviewData.m_OrigSize"); - m_CompSize = serializedObject.FindProperty("m_PreviewData.m_CompSize"); - - ResetSettingsFromBackend(); - } - - protected override void ResetValues() - { - base.ResetValues(); - ResetSettingsFromBackend(); - } - - public override void OnInspectorGUI() - { - serializedObject.UpdateIfRequiredOrScript(); - - bool selectionContainsTrackerFile = false; - foreach (AudioImporter importer in GetAllAudioImporterTargets()) - { - string assetPath = importer.assetPath; - string ext = FileUtil.GetPathExtension(assetPath).ToLowerInvariant(); - if (ext == "mod" || ext == "it" || ext == "s3m" || ext == "xm") - { - selectionContainsTrackerFile = true; - break; - } - } - - OnAudioImporterGUI(selectionContainsTrackerFile); - - int origSize = 0, compSize = 0; - foreach (AudioImporter importer in GetAllAudioImporterTargets()) - { - origSize += importer.origSize; - compSize += importer.compSize; - } - - GUILayout.Space(10); - - EditorGUILayout.HelpBox("Original Size: \t" + EditorUtility.FormatBytes(origSize) + "\nImported Size: \t" + EditorUtility.FormatBytes(compSize) + "\n" + - "Ratio: \t\t" + (100.0f * (float)compSize / (float)origSize).ToString("0.00") + "%", MessageType.Info); - - - if (CurrentPlatformHasAutoTranslatedCompression()) - { - GUILayout.Space(10); - EditorGUILayout.HelpBox("The selection contains different compression formats to the default settings for the current build platform.", MessageType.Info); - } - - if (CurrentSelectionContainsHardwareSounds()) - { - GUILayout.Space(10); - EditorGUILayout.HelpBox("The selection contains sounds that are decompressed in hardware. Advanced mixing is not available for these sounds.", MessageType.Info); - } - - ApplyRevertGUI(); - } - - private MultiValueStatus GetMultiValueStatus(BuildTargetGroup platform) - { - MultiValueStatus status; - status.multiLoadType = false; - status.multiSampleRateSetting = false; - status.multiSampleRateOverride = false; - status.multiCompressionFormat = false; - status.multiQuality = false; - status.multiConversionMode = false; - - AudioImporterSampleSettings settings; - - if (GetAllAudioImporterTargets().Any()) - { - //We have at least one AudioImporter - AudioImporter firstImporter = GetAllAudioImporterTargets().First(); - - if (platform == BuildTargetGroup.Unknown) - settings = firstImporter.defaultSampleSettings; - else - settings = firstImporter.Internal_GetOverrideSampleSettings(platform); - - foreach (AudioImporter importer in GetAllAudioImporterTargets().Except(new[] {firstImporter})) - { - AudioImporterSampleSettings compareSettings; - if (platform == BuildTargetGroup.Unknown) - compareSettings = importer.defaultSampleSettings; - else - compareSettings = importer.Internal_GetOverrideSampleSettings(platform); - - status.multiLoadType |= settings.loadType != compareSettings.loadType; - status.multiSampleRateSetting |= settings.sampleRateSetting != compareSettings.sampleRateSetting; - status.multiSampleRateOverride |= settings.sampleRateOverride != compareSettings.sampleRateOverride; - status.multiCompressionFormat |= settings.compressionFormat != compareSettings.compressionFormat; - status.multiQuality |= settings.quality != compareSettings.quality; - status.multiConversionMode |= settings.conversionMode != compareSettings.conversionMode; - } - } - - return status; - } - - enum OverrideStatus - { - NoOverrides, - MixedOverrides, - AllOverrides - } - - private OverrideStatus GetOverrideStatus(BuildTargetGroup platform) - { - bool mixedOverrides = false; - bool containsOverride = false; - - if (GetAllAudioImporterTargets().Any()) - { - AudioImporter firstImporter = GetAllAudioImporterTargets().First(); - - containsOverride = firstImporter.Internal_ContainsSampleSettingsOverride(platform); - foreach (AudioImporter importer in GetAllAudioImporterTargets().Except(new[] {firstImporter})) - { - bool overrideState = importer.Internal_ContainsSampleSettingsOverride(platform); - - if (overrideState != containsOverride) - mixedOverrides |= true; - - containsOverride |= overrideState; - } - } - - if (!containsOverride) - return OverrideStatus.NoOverrides; - else if (mixedOverrides) - return OverrideStatus.MixedOverrides; - else - return OverrideStatus.AllOverrides; - } - - private AudioCompressionFormat[] GetFormatsForPlatform(BuildTargetGroup platform) - { - List allowedFormats = new List(); - - //WebGL only supports AAC currently. - if (platform == BuildTargetGroup.WebGL) - { - allowedFormats.Add(AudioCompressionFormat.AAC); - return allowedFormats.ToArray(); - } - - allowedFormats.Add(AudioCompressionFormat.PCM); - - if (platform != BuildTargetGroup.PSP2) // Currently Vorbis is not supported on Vita - { - allowedFormats.Add(AudioCompressionFormat.Vorbis); - } - - allowedFormats.Add(AudioCompressionFormat.ADPCM); - - if (platform != BuildTargetGroup.Standalone && - platform != BuildTargetGroup.WSA && - platform != BuildTargetGroup.XboxOne && - platform != BuildTargetGroup.Unknown) - { - allowedFormats.Add(AudioCompressionFormat.MP3); - } - - if (platform == BuildTargetGroup.PSP2) - { - allowedFormats.Add(AudioCompressionFormat.HEVAG); - allowedFormats.Add(AudioCompressionFormat.ATRAC9); - } - - if (platform == BuildTargetGroup.PS4) - { - allowedFormats.Add(AudioCompressionFormat.ATRAC9); - } - - if (platform == BuildTargetGroup.XboxOne) - allowedFormats.Add(AudioCompressionFormat.XMA); - - return allowedFormats.ToArray(); - } - - private bool CompressionFormatHasQuality(AudioCompressionFormat format) - { - switch (format) - { - case AudioCompressionFormat.Vorbis: - case AudioCompressionFormat.MP3: - case AudioCompressionFormat.XMA: - case AudioCompressionFormat.AAC: - case AudioCompressionFormat.ATRAC9: - return true; - default: - return false; - } - } - - private void OnSampleSettingGUI(BuildTargetGroup platform, MultiValueStatus status, bool selectionContainsTrackerFile, ref SampleSettingProperties properties, bool disablePreloadAudioDataOption) - { - //Load Type - EditorGUI.showMixedValue = status.multiLoadType && !properties.loadTypeChanged; - EditorGUI.BeginChangeCheck(); - AudioClipLoadType newLoadType = (AudioClipLoadType)EditorGUILayout.EnumPopup("Load Type", properties.settings.loadType); - if (EditorGUI.EndChangeCheck()) - { - properties.settings.loadType = newLoadType; - properties.loadTypeChanged = true; - } - - using (new EditorGUI.DisabledScope(disablePreloadAudioDataOption)) - { - if (disablePreloadAudioDataOption) - EditorGUILayout.Toggle("Preload Audio Data", false); - else - EditorGUILayout.PropertyField(m_PreloadAudioData); - } - - if (!selectionContainsTrackerFile) - { - //Compression format - AudioCompressionFormat[] allowedFormats = GetFormatsForPlatform(platform); - EditorGUI.showMixedValue = status.multiCompressionFormat && !properties.compressionFormatChanged; - EditorGUI.BeginChangeCheck(); - AudioCompressionFormat newFormat = (AudioCompressionFormat)EditorGUILayout.IntPopup("Compression Format", - (int)properties.settings.compressionFormat, - Array.ConvertAll(allowedFormats, value => value.ToString()), - Array.ConvertAll(allowedFormats, value => (int)value)); - if (EditorGUI.EndChangeCheck()) - { - properties.settings.compressionFormat = newFormat; - properties.compressionFormatChanged = true; - } - - //Quality - if (CompressionFormatHasQuality(properties.settings.compressionFormat)) - { - EditorGUI.showMixedValue = status.multiQuality && !properties.qualityChanged; - EditorGUI.BeginChangeCheck(); - int newQuality = EditorGUILayout.IntSlider("Quality", (int)Mathf.Clamp(properties.settings.quality * 100.0f, 1.0f, 100.0f), 1, 100); - if (EditorGUI.EndChangeCheck()) - { - properties.settings.quality = 0.01f * newQuality; - properties.qualityChanged = true; - } - } - - if (platform != BuildTargetGroup.WebGL) - { - //Sample rate settings - EditorGUI.showMixedValue = status.multiSampleRateSetting && !properties.sampleRateSettingChanged; - EditorGUI.BeginChangeCheck(); - AudioSampleRateSetting newSetting = (AudioSampleRateSetting)EditorGUILayout.EnumPopup("Sample Rate Setting", properties.settings.sampleRateSetting); - if (EditorGUI.EndChangeCheck()) - { - properties.settings.sampleRateSetting = newSetting; - properties.sampleRateSettingChanged = true; - } - - //Sample rate settings - if (properties.settings.sampleRateSetting == AudioSampleRateSetting.OverrideSampleRate) - { - EditorGUI.showMixedValue = status.multiSampleRateOverride && !properties.sampleRateOverrideChanged; - EditorGUI.BeginChangeCheck(); - int newRate = EditorGUILayout.IntPopup("Sample Rate", (int)properties.settings.sampleRateOverride, - Styles.kSampleRateStrings, Styles.kSampleRateValues); - if (EditorGUI.EndChangeCheck()) - { - properties.settings.sampleRateOverride = (uint)newRate; - properties.sampleRateOverrideChanged = true; - } - } - } - - //TODO include the settings for things like HEVAG - EditorGUI.showMixedValue = false; - } - } - - private void OnAudioImporterGUI(bool selectionContainsTrackerFile) - { - if (!selectionContainsTrackerFile) - { - EditorGUILayout.PropertyField(m_ForceToMono); - EditorGUI.indentLevel++; - using (new EditorGUI.DisabledScope(!m_ForceToMono.boolValue)) - { - EditorGUILayout.PropertyField(m_Normalize); - } - EditorGUI.indentLevel--; - EditorGUILayout.PropertyField(m_LoadInBackground); - EditorGUILayout.PropertyField(m_Ambisonic); - } - - BuildPlatform[] validPlatforms = BuildPlatforms.instance.GetValidPlatforms().ToArray(); - GUILayout.Space(10); - int shownSettingsPage = EditorGUILayout.BeginPlatformGrouping(validPlatforms, GUIContent.Temp("Default")); - - if (shownSettingsPage == -1) - { - // If the loadtype is streaming on the selected platform, gray out the "Preload Audio Data" option and show the checkbox as unchecked. - bool disablePreloadAudioDataOption = (m_DefaultSampleSettings.settings.loadType == AudioClipLoadType.Streaming); - - MultiValueStatus multiStatus = GetMultiValueStatus(BuildTargetGroup.Unknown); - OnSampleSettingGUI(BuildTargetGroup.Unknown, multiStatus, selectionContainsTrackerFile, ref m_DefaultSampleSettings, disablePreloadAudioDataOption); - } - else - { - BuildTargetGroup platform = validPlatforms[shownSettingsPage].targetGroup; - SampleSettingProperties properties = m_SampleSettingOverrides[platform]; - OverrideStatus status = GetOverrideStatus(platform); - - // Define the UI state of the override here. - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = (status == OverrideStatus.MixedOverrides) && !properties.overrideIsForced; - bool overrideState = (properties.overrideIsForced && properties.forcedOverrideState) || - (!properties.overrideIsForced && status != OverrideStatus.NoOverrides); - overrideState = EditorGUILayout.ToggleLeft("Override for " + validPlatforms[shownSettingsPage].title.text, overrideState); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - properties.forcedOverrideState = overrideState; - properties.overrideIsForced = true; - } - - // If the loadtype is streaming on the selected platform, gray out the "Preload Audio Data" option and show the checkbox as unchecked. - bool disablePreloadAudioDataOption = ((properties.overrideIsForced && properties.forcedOverrideState) || GetOverrideStatus(platform) == OverrideStatus.AllOverrides) && properties.settings.loadType == AudioClipLoadType.Streaming; - - MultiValueStatus multiStatus = GetMultiValueStatus(platform); - bool platformSettingsDisabled = !((properties.overrideIsForced && properties.forcedOverrideState) || status == OverrideStatus.AllOverrides); - - using (new EditorGUI.DisabledScope(platformSettingsDisabled)) - { - OnSampleSettingGUI(platform, multiStatus, selectionContainsTrackerFile, ref properties, disablePreloadAudioDataOption); - } - - m_SampleSettingOverrides[platform] = properties; - } - - EditorGUILayout.EndPlatformGrouping(); - } - - public override bool HasModified() - { - if (base.HasModified()) - return true; - - if (m_DefaultSampleSettings.HasModified()) - return true; - - //Iterate over all the override settings - Dictionary.ValueCollection valueColl = m_SampleSettingOverrides.Values; - foreach (SampleSettingProperties props in valueColl) - { - if (props.HasModified()) - return true; - } - - return false; - } - - protected override void Apply() - { - base.Apply(); - SyncSettingsToBackend(); - - // This is necessary to enforce redrawing the static preview icons in the project browser, as properties like ForceToMono - // may have changed the preview completely. - foreach (ProjectBrowser pb in ProjectBrowser.GetAllProjectBrowsers()) - pb.Repaint(); - } - } -} diff --git a/Editor/Mono/ImportSettings/BaseAssetImporterTabUI.cs b/Editor/Mono/ImportSettings/BaseAssetImporterTabUI.cs deleted file mode 100644 index e13f8e05b0..0000000000 --- a/Editor/Mono/ImportSettings/BaseAssetImporterTabUI.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using Object = UnityEngine.Object; -using UnityEditor.Experimental.AssetImporters; -namespace UnityEditor -{ - internal abstract class BaseAssetImporterTabUI - { - AssetImporterEditor m_PanelContainer = null; - - public SerializedObject serializedObject - { - get { return m_PanelContainer.serializedObject; } - } - - public Object[] targets - { - get { return m_PanelContainer.targets; } - } - - public Object target - { - get { return m_PanelContainer.target; } - } - - public Object assetTarget - { - get { return m_PanelContainer.assetTarget; } - } - - public Object[] assetTargets - { - get { return m_PanelContainer.assetTargets; } - } - - public int referenceTargetIndex - { - get { return m_PanelContainer.referenceTargetIndex; } - set { m_PanelContainer.referenceTargetIndex = value; } - } - - protected Func Instantiate; - protected Action DestroyImmediate; - - internal BaseAssetImporterTabUI(AssetImporterEditor panelContainer) - { - m_PanelContainer = panelContainer; - - Instantiate = obj => AssetImporterEditor.Instantiate(obj); - DestroyImmediate = obj => AssetImporterEditor.DestroyImmediate(obj); - } - - internal abstract void OnEnable(); - internal virtual void OnDisable() {} - - internal virtual void PreApply() {} - - - internal virtual void PostApply() {} - - internal virtual void ResetValues() {} - - public abstract void OnInspectorGUI(); - - internal virtual bool HasModified() - { - return serializedObject.hasModifiedProperties; - } - - // The preview functionality is implemented as expected in the Editor class - // Classes that derive from the AssetImporterPanel can override part of the functionality, - // but overall we should still fall back to the implementation in the editor - public virtual void OnPreviewSettings() - { - } - - public virtual void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - m_PanelContainer.OnPreviewGUI(r, background); - } - - public virtual bool HasPreviewGUI() - { - return true; - } - - internal virtual void OnDestroy() - { - } - } -} diff --git a/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs b/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs deleted file mode 100644 index 89a1aee21c..0000000000 --- a/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs +++ /dev/null @@ -1,248 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using UnityEditor.Modules; -using UnityEngine; - -namespace UnityEditor -{ - internal class DesktopPluginImporterExtension : DefaultPluginImporterExtension - { - internal enum DesktopPluginCPUArchitecture - { - None, - AnyCPU, - x86, - x86_64 - }; - - internal class DesktopSingleCPUProperty : Property - { - public DesktopSingleCPUProperty(GUIContent name, string platformName) - : this(name, platformName, DesktopPluginCPUArchitecture.AnyCPU) - { - } - - public DesktopSingleCPUProperty(GUIContent name, string platformName, DesktopPluginCPUArchitecture architecture) - : base(name, "CPU", architecture, platformName) - { - } - - internal bool IsTargetEnabled(PluginImporterInspector inspector) - { - PluginImporterInspector.Compatibility compatibililty = inspector.GetPlatformCompatibility(platformName); - if (compatibililty == PluginImporterInspector.Compatibility.Mixed) - throw new Exception("Unexpected mixed value for '" + inspector.importer.assetPath + "', platform: " + platformName); - return compatibililty == PluginImporterInspector.Compatibility.Compatible; - } - - internal override void OnGUI(PluginImporterInspector inspector) - { - EditorGUILayout.BeginHorizontal(); - GUILayout.Space(10); - EditorGUI.BeginChangeCheck(); - - // This toggle controls two things: - // * Is platform enabled/disabled? - // * Platform CPU value - bool isTargetEnabled = EditorGUILayout.Toggle(name, IsTargetEnabled(inspector)); - if (EditorGUI.EndChangeCheck()) - { - value = isTargetEnabled ? defaultValue : DesktopPluginCPUArchitecture.None; - inspector.SetPlatformCompatibility(platformName, isTargetEnabled); - } - EditorGUILayout.EndHorizontal(); - } - } - - private DesktopSingleCPUProperty m_WindowsX86; - private DesktopSingleCPUProperty m_WindowsX86_X64; - - private DesktopSingleCPUProperty m_LinuxX86; - private DesktopSingleCPUProperty m_LinuxX86_X64; - - private DesktopSingleCPUProperty m_OSX_X64; - - - public DesktopPluginImporterExtension() - : base(null) - { - properties = GetProperties(); - } - - private Property[] GetProperties() - { - List properties = new List(); - m_WindowsX86 = new DesktopSingleCPUProperty(EditorGUIUtility.TrTextContent("x86"), BuildPipeline.GetBuildTargetName(BuildTarget.StandaloneWindows)); - m_WindowsX86_X64 = new DesktopSingleCPUProperty(EditorGUIUtility.TrTextContent("x86_x64"), BuildPipeline.GetBuildTargetName(BuildTarget.StandaloneWindows64)); - - m_LinuxX86 = new DesktopSingleCPUProperty(EditorGUIUtility.TrTextContent("x86"), BuildPipeline.GetBuildTargetName(BuildTarget.StandaloneLinux), DesktopPluginCPUArchitecture.x86); - m_LinuxX86_X64 = new DesktopSingleCPUProperty(EditorGUIUtility.TrTextContent("x86_x64"), BuildPipeline.GetBuildTargetName(BuildTarget.StandaloneLinux64), DesktopPluginCPUArchitecture.x86_64); - - m_OSX_X64 = new DesktopSingleCPUProperty(EditorGUIUtility.TrTextContent("x64"), BuildPipeline.GetBuildTargetName(BuildTarget.StandaloneOSX)); - - properties.Add(m_WindowsX86); - properties.Add(m_WindowsX86_X64); - - properties.Add(m_LinuxX86); - properties.Add(m_LinuxX86_X64); - - properties.Add(m_OSX_X64); - - return properties.ToArray(); - } - - private DesktopPluginCPUArchitecture CalculateMultiCPUArchitecture(bool x86, bool x64) - { - if (x86 && x64) return DesktopPluginCPUArchitecture.AnyCPU; - if (x86) return DesktopPluginCPUArchitecture.x86; - if (x64) return DesktopPluginCPUArchitecture.x86_64; - return DesktopPluginCPUArchitecture.None; - } - - private bool IsUsableOnWindows(PluginImporter imp) - { - if (!imp.isNativePlugin) - return true; - - string ext = Path.GetExtension(imp.assetPath).ToLower(); - return ext == ".dll" || IsCppPluginFile(imp.assetPath); - } - - private bool IsUsableOnOSX(PluginImporter imp) - { - if (!imp.isNativePlugin) - return true; - - string ext = Path.GetExtension(imp.assetPath).ToLower(); - return ext == ".so" || ext == ".bundle" || IsCppPluginFile(imp.assetPath); - } - - private bool IsUsableOnLinux(PluginImporter imp) - { - if (!imp.isNativePlugin) - return true; - - string ext = Path.GetExtension(imp.assetPath).ToLower(); - return ext == ".so" || IsCppPluginFile(imp.assetPath); - } - - public override void OnPlatformSettingsGUI(PluginImporterInspector inspector) - { - PluginImporter imp = inspector.importer; - EditorGUI.BeginChangeCheck(); - if (IsUsableOnWindows(imp)) - { - EditorGUILayout.LabelField(EditorGUIUtility.TrTextContent("Windows"), EditorStyles.boldLabel); - m_WindowsX86.OnGUI(inspector); - m_WindowsX86_X64.OnGUI(inspector); - EditorGUILayout.Space(); - } - - if (IsUsableOnLinux(imp)) - { - EditorGUILayout.LabelField(EditorGUIUtility.TrTextContent("Linux"), EditorStyles.boldLabel); - m_LinuxX86.OnGUI(inspector); - m_LinuxX86_X64.OnGUI(inspector); - EditorGUILayout.Space(); - } - - if (IsUsableOnOSX(imp)) - { - EditorGUILayout.LabelField(EditorGUIUtility.TrTextContent("Mac OS X"), EditorStyles.boldLabel); - m_OSX_X64.OnGUI(inspector); - } - - if (EditorGUI.EndChangeCheck()) - { - ValidateUniversalTargets(inspector); - hasModified = true; - } - } - - public void ValidateSingleCPUTargets(PluginImporterInspector inspector) - { - DesktopSingleCPUProperty[] singleCPUTargets = new[] - { - m_WindowsX86, - m_WindowsX86_X64, - m_LinuxX86, - m_LinuxX86_X64, - m_OSX_X64 - }; - - foreach (var target in singleCPUTargets) - { - string value = target.IsTargetEnabled(inspector) ? target.defaultValue.ToString() : DesktopPluginCPUArchitecture.None.ToString(); - foreach (var importer in inspector.importers) - { - importer.SetPlatformData(target.platformName, "CPU", value); - } - } - - ValidateUniversalTargets(inspector); - } - - private void ValidateUniversalTargets(PluginImporterInspector inspector) - { - bool linuxX86Enabled = m_LinuxX86.IsTargetEnabled(inspector); - bool linuxX86_X64Enabled = m_LinuxX86_X64.IsTargetEnabled(inspector); - - DesktopPluginCPUArchitecture linuxUniversal = CalculateMultiCPUArchitecture(linuxX86Enabled, linuxX86_X64Enabled); - foreach (var importer in inspector.importers) - importer.SetPlatformData(BuildTarget.StandaloneLinuxUniversal, "CPU", linuxUniversal.ToString()); - inspector.SetPlatformCompatibility(BuildPipeline.GetBuildTargetName(BuildTarget.StandaloneLinuxUniversal), linuxX86Enabled || linuxX86_X64Enabled); - - bool osxX64Enabled = m_OSX_X64.IsTargetEnabled(inspector); - - DesktopPluginCPUArchitecture osxUniversal = CalculateMultiCPUArchitecture(true, osxX64Enabled); - foreach (var importer in inspector.importers) - importer.SetPlatformData(BuildTarget.StandaloneOSX, "CPU", osxUniversal.ToString()); - inspector.SetPlatformCompatibility(BuildPipeline.GetBuildTargetName(BuildTarget.StandaloneOSX), osxX64Enabled); - } - - public override string CalculateFinalPluginPath(string platformName, PluginImporter imp) - { - BuildTarget target = BuildPipeline.GetBuildTargetByName(platformName); - bool pluginForWindows = target == BuildTarget.StandaloneWindows || target == BuildTarget.StandaloneWindows64; -#pragma warning disable 612, 618 - bool pluginForOSX = target == BuildTarget.StandaloneOSXIntel || target == BuildTarget.StandaloneOSXIntel64 || target == BuildTarget.StandaloneOSX; -#pragma warning restore 612, 618 - bool pluginForLinux = target == BuildTarget.StandaloneLinux || target == BuildTarget.StandaloneLinux64 || target == BuildTarget.StandaloneLinuxUniversal; - - if (!pluginForLinux && !pluginForOSX && !pluginForWindows) - throw new Exception(string.Format("Failed to resolve standalone platform, platform string '{0}', resolved target '{1}'", - platformName, target.ToString())); - - if (pluginForWindows && !IsUsableOnWindows(imp)) - return string.Empty; - if (pluginForOSX && !IsUsableOnOSX(imp)) - return string.Empty; - if (pluginForLinux && !IsUsableOnLinux(imp)) - return string.Empty; - - string cpu = imp.GetPlatformData(platformName, "CPU"); - - if (string.Compare(cpu, "None", true) == 0) - return string.Empty; - - if (!string.IsNullOrEmpty(cpu) && string.Compare(cpu, "AnyCPU", true) != 0) - { - return Path.Combine(cpu, Path.GetFileName(imp.assetPath)); - } - - // For files this will return filename, for directories, this will return last path component - return Path.GetFileName(imp.assetPath); - } - - internal static bool IsCppPluginFile(string assetPath) - { - var extension = Path.GetExtension(assetPath).ToLower(); - return extension == ".cpp" || extension == ".c" || extension == ".h"; - } - } -} diff --git a/Editor/Mono/ImportSettings/EditorPluginImporterExtension.cs b/Editor/Mono/ImportSettings/EditorPluginImporterExtension.cs deleted file mode 100644 index d6866b0f13..0000000000 --- a/Editor/Mono/ImportSettings/EditorPluginImporterExtension.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Text; -using System.Text.RegularExpressions; -using UnityEngine; -using UnityEditor; -using UnityEditor.Modules; - -namespace UnityEditor -{ - internal class EditorPluginImporterExtension : DefaultPluginImporterExtension - { - internal enum EditorPluginCPUArchitecture - { - AnyCPU, - x86, - x86_64 - }; - - internal enum EditorPluginOSArchitecture - { - AnyOS, - OSX, - Windows, - Linux - }; - - internal class EditorProperty : Property - { - public EditorProperty(GUIContent name, string key, object defaultValue) - : base(name, key, defaultValue, BuildPipeline.GetEditorTargetName()) - { - } - - internal override void Reset(PluginImporterInspector inspector) - { - string valueString = inspector.importer.GetEditorData(key); - ParseStringValue(inspector, valueString); - } - - internal override void Apply(PluginImporterInspector inspector) - { - inspector.importer.SetEditorData(key, value.ToString()); - } - } - - public EditorPluginImporterExtension() : base(GetProperties()) - { - } - - private static Property[] GetProperties() - { - return new[] - { - new EditorProperty(EditorGUIUtility.TrTextContent("CPU", "Is plugin compatible with 32bit or 64bit Editor?"), "CPU", EditorPluginCPUArchitecture.AnyCPU), - new EditorProperty(EditorGUIUtility.TrTextContent("OS", "Is plugin compatible with Windows, OS X or Linux Editor?"), "OS", EditorPluginOSArchitecture.AnyOS), - }; - } - } -} diff --git a/Editor/Mono/ImportSettings/ExposeTransformEditor.cs b/Editor/Mono/ImportSettings/ExposeTransformEditor.cs deleted file mode 100644 index da84973f02..0000000000 --- a/Editor/Mono/ImportSettings/ExposeTransformEditor.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class ExposeTransformEditor - { - private ReorderableList m_ExtraExposedTransformList; - - private string[] m_TransformPaths; - private SerializedProperty m_ExtraExposedTransformPaths; - - public void OnEnable(string[] transformPaths, SerializedObject serializedObject) - { - m_TransformPaths = transformPaths; - m_ExtraExposedTransformPaths = serializedObject.FindProperty("m_ExtraExposedTransformPaths"); - - // Customized exposed transforms - if (m_ExtraExposedTransformList == null) - { - m_ExtraExposedTransformList = new ReorderableList(serializedObject, m_ExtraExposedTransformPaths, false, true, true, true); - m_ExtraExposedTransformList.onAddDropdownCallback = AddTransformPathInList; - m_ExtraExposedTransformList.onRemoveCallback = RemoveTransformPathInList; - m_ExtraExposedTransformList.drawElementCallback = DrawTransformPathElement; - m_ExtraExposedTransformList.drawHeaderCallback = DrawTransformPathListHeader; - m_ExtraExposedTransformList.elementHeight = 16; - } - } - - public void OnGUI() - { - m_ExtraExposedTransformList.DoLayoutList(); - } - - private void TransformPathSelected(object userData, string[] options, int selected) - { - string newExposedPath = options[selected]; - for (int i = 0; i < m_ExtraExposedTransformPaths.arraySize; i++) - { - string itStr = m_ExtraExposedTransformPaths.GetArrayElementAtIndex(i).stringValue; - if (itStr == newExposedPath) - return; - } - - m_ExtraExposedTransformPaths.InsertArrayElementAtIndex(m_ExtraExposedTransformPaths.arraySize); - m_ExtraExposedTransformPaths.GetArrayElementAtIndex(m_ExtraExposedTransformPaths.arraySize - 1).stringValue = options[selected]; - } - - private void AddTransformPathInList(Rect rect, ReorderableList list) - { - EditorUtility.DisplayCustomMenu(rect, m_TransformPaths, null, TransformPathSelected, null); - } - - private void RemoveTransformPathInList(ReorderableList list) - { - m_ExtraExposedTransformPaths.DeleteArrayElementAtIndex(list.index); - } - - private void DrawTransformPathElement(Rect rect, int index, bool selected, bool focused) - { - string curPath = m_ExtraExposedTransformPaths.GetArrayElementAtIndex(index).stringValue; - GUI.Label(rect, curPath.Substring(curPath.LastIndexOf("/") + 1), EditorStyles.label); - } - - private void DrawTransformPathListHeader(Rect rect) - { - GUI.Label(rect, "Extra Transforms to Expose", EditorStyles.label); - } - } -} diff --git a/Editor/Mono/ImportSettings/IHVImageFormatImporterInspector.cs b/Editor/Mono/ImportSettings/IHVImageFormatImporterInspector.cs deleted file mode 100644 index c05d858fc8..0000000000 --- a/Editor/Mono/ImportSettings/IHVImageFormatImporterInspector.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Experimental.AssetImporters; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(IHVImageFormatImporter))] - [CanEditMultipleObjects] - internal class IHVImageFormatImporterInspector : AssetImporterEditor - { - public override bool showImportedObject { get { return false; } } - - SerializedProperty m_IsReadable; - SerializedProperty m_sRGBTexture; - SerializedProperty m_FilterMode; - SerializedProperty m_WrapU; - SerializedProperty m_WrapV; - SerializedProperty m_WrapW; - - internal class Styles - { - // copy pasted from TextureImporterInspector.TextureSettingsGUI() - public static readonly GUIContent readWrite = EditorGUIUtility.TrTextContent("Read/Write Enabled", "Enable to be able to access the raw pixel data from code."); - 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)."); - public static readonly GUIContent wrapMode = EditorGUIUtility.TrTextContent("Wrap Mode"); - public static readonly GUIContent filterMode = EditorGUIUtility.TrTextContent("Filter Mode"); - - public static readonly int[] filterModeValues = - { (int)FilterMode.Point, (int)FilterMode.Bilinear, (int)FilterMode.Trilinear }; - public static readonly GUIContent[] filterModeOptions = - { EditorGUIUtility.TextContent("Point (no filter)"), EditorGUIUtility.TextContent("Bilinear"), EditorGUIUtility.TrTextContent("Trilinear") }; - } - - - public override void OnEnable() - { - m_IsReadable = serializedObject.FindProperty("m_IsReadable"); - m_sRGBTexture = serializedObject.FindProperty("m_sRGBTexture"); - m_FilterMode = serializedObject.FindProperty("m_TextureSettings.m_FilterMode"); - m_WrapU = serializedObject.FindProperty("m_TextureSettings.m_WrapU"); - m_WrapV = serializedObject.FindProperty("m_TextureSettings.m_WrapV"); - m_WrapW = serializedObject.FindProperty("m_TextureSettings.m_WrapW"); - } - - // alas it looks impossible to share code so we copy paste from TextureImporterInspector.TextureSettingsGUI() - - bool m_ShowPerAxisWrapModes = false; - public void TextureSettingsGUI() - { - // NOTE: once we get ability to have 3D/Volume texture shapes, should pass true for isVolume based on m_TextureShape - bool isVolume = false; - TextureInspector.WrapModePopup(m_WrapU, m_WrapV, m_WrapW, isVolume, ref m_ShowPerAxisWrapModes); - - Rect rect = EditorGUILayout.GetControlRect(); - EditorGUI.BeginProperty(rect, Styles.filterMode, m_FilterMode); - EditorGUI.BeginChangeCheck(); - FilterMode filter = m_FilterMode.intValue == -1 ? FilterMode.Bilinear : (FilterMode)m_FilterMode.intValue; - filter = (FilterMode)EditorGUI.IntPopup(rect, Styles.filterMode, (int)filter, Styles.filterModeOptions, Styles.filterModeValues); - if (EditorGUI.EndChangeCheck()) - m_FilterMode.intValue = (int)filter; - EditorGUI.EndProperty(); - } - - public override void OnInspectorGUI() - { - EditorGUILayout.PropertyField(m_IsReadable, Styles.readWrite); - EditorGUILayout.PropertyField(m_sRGBTexture, Styles.sRGBTexture); - - EditorGUI.BeginChangeCheck(); - TextureSettingsGUI(); - if (EditorGUI.EndChangeCheck()) - { - // copy pasted from TextureImporterInspector.TextureSettingsGUI() - foreach (AssetImporter importer in targets) - { - Texture tex = AssetDatabase.LoadMainAssetAtPath(importer.assetPath) as Texture; - if (m_FilterMode.intValue != -1) - TextureUtil.SetFilterModeNoDirty(tex, (FilterMode)m_FilterMode.intValue); - if ((m_WrapU.intValue != -1 || m_WrapV.intValue != -1 || m_WrapW.intValue != -1) && - !m_WrapU.hasMultipleDifferentValues && !m_WrapV.hasMultipleDifferentValues && !m_WrapW.hasMultipleDifferentValues) - { - TextureUtil.SetWrapModeNoDirty(tex, (TextureWrapMode)m_WrapU.intValue, (TextureWrapMode)m_WrapV.intValue, (TextureWrapMode)m_WrapW.intValue); - } - } - SceneView.RepaintAll(); - } - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - ApplyRevertGUI(); - GUILayout.EndHorizontal(); - } - } -} diff --git a/Editor/Mono/ImportSettings/ModelImporterClipEditor.cs b/Editor/Mono/ImportSettings/ModelImporterClipEditor.cs deleted file mode 100644 index ef26351c0e..0000000000 --- a/Editor/Mono/ImportSettings/ModelImporterClipEditor.cs +++ /dev/null @@ -1,1018 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using UnityEngine; -using UnityEditor; -using UnityEditor.Animations; -using UnityEditorInternal; -using System.Collections.Generic; -using UnityEditor.Experimental.AssetImporters; -using UnityEngine.Profiling; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class ModelImporterClipEditor : BaseAssetImporterTabUI - { - AnimationClipEditor m_AnimationClipEditor; - ModelImporter singleImporter { get { return targets[0] as ModelImporter; } } - - public int m_SelectedClipIndexDoNotUseDirectly = -1; - public int selectedClipIndex - { - get { return m_SelectedClipIndexDoNotUseDirectly; } - set - { - m_SelectedClipIndexDoNotUseDirectly = value; - if (m_ClipList != null) - m_ClipList.index = value; - } - } - - public string selectedClipName - { - get - { - var clipInfo = GetSelectedClipInfo(); - return clipInfo != null ? clipInfo.name : ""; - } - } - - SerializedObject m_DefaultClipsSerializedObject = null; - - SerializedProperty m_AnimationType; - - SerializedProperty m_ImportAnimation; - SerializedProperty m_ClipAnimations; - SerializedProperty m_BakeSimulation; - SerializedProperty m_ResampleCurves; - SerializedProperty m_AnimationCompression; - SerializedProperty m_AnimationRotationError; - SerializedProperty m_AnimationPositionError; - SerializedProperty m_AnimationScaleError; - SerializedProperty m_AnimationWrapMode; - SerializedProperty m_LegacyGenerateAnimations; - SerializedProperty m_ImportAnimatedCustomProperties; - SerializedProperty m_ImportConstraints; - - SerializedProperty m_MotionNodeName; - public int motionNodeIndex { get; set; } - - public int pivotNodeIndex { get; set; } - - private SerializedProperty m_RigImportErrors; - private SerializedProperty m_RigImportWarnings; - private SerializedProperty m_AnimationImportErrors; - private SerializedProperty m_AnimationImportWarnings; - private SerializedProperty m_AnimationRetargetingWarnings; - private SerializedProperty m_AnimationDoRetargetingWarnings; - - GUIContent[] m_MotionNodeList; - static private bool motionNodeFoldout = false; - - private static bool importMessageFoldout = false; - - ReorderableList m_ClipList; - - private string[] referenceTransformPaths - { - get { return singleImporter.transformPaths; } - } - - private ModelImporterAnimationType animationType - { - get { return (ModelImporterAnimationType)m_AnimationType.intValue; } - set { m_AnimationType.intValue = (int)value; } - } - - private ModelImporterGenerateAnimations legacyGenerateAnimations - { - get { return (ModelImporterGenerateAnimations)m_LegacyGenerateAnimations.intValue; } - set { m_LegacyGenerateAnimations.intValue = (int)value; } - } - - private class Styles - { - public GUIContent ErrorsFoundWhileImportingThisAnimation = EditorGUIUtility.TrTextContentWithIcon("Error(s) found while importing this animation file. Open \"Import Messages\" foldout below for more details.", MessageType.Error); - public GUIContent WarningsFoundWhileImportingRig = EditorGUIUtility.TrTextContentWithIcon("Warning(s) found while importing rig in this animation file. Open \"Rig\" tab for more details.", MessageType.Warning); - public GUIContent WarningsFoundWhileImportingThisAnimation = EditorGUIUtility.TrTextContentWithIcon("Warning(s) found while importing this animation file. Open \"Import Messages\" foldout below for more details.", MessageType.Warning); - public GUIContent ImportAnimations = EditorGUIUtility.TrTextContent("Import Animation", "Controls if animations are imported."); - - public GUIStyle numberStyle = new GUIStyle(EditorStyles.label); - - public GUIContent AnimWrapModeLabel = EditorGUIUtility.TrTextContent("Wrap Mode", "The default Wrap Mode for the animation in the mesh being imported."); - - public GUIContent[] AnimWrapModeOpt = - { - EditorGUIUtility.TrTextContent("Default", "The animation plays as specified in the animation splitting options below."), - EditorGUIUtility.TrTextContent("Once", "The animation plays through to the end once and then stops."), - EditorGUIUtility.TrTextContent("Loop", "The animation plays through and then restarts when the end is reached."), - EditorGUIUtility.TrTextContent("PingPong", "The animation plays through and then plays in reverse from the end to the start, and so on."), - EditorGUIUtility.TrTextContent("ClampForever", "The animation plays through but the last frame is repeated indefinitely. This is not the same as Once mode because playback does not technically stop at the last frame (which is useful when blending animations).") - }; - - public GUIContent BakeIK = EditorGUIUtility.TrTextContent("Bake Animations", "Enable this when using IK or simulation in your animation package. Unity will convert to forward kinematics on import. This option is available only for Maya, 3dsMax and Cinema4D files."); - public GUIContent ResampleCurves = EditorGUIUtility.TrTextContent("Resample Curves ", " Curves will be resampled on every frame. Use this if you're having issues with the interpolation between keys in your original animation. Disable this to keep curves as close as possible to how they were originally authored."); - public GUIContent AnimCompressionLabel = EditorGUIUtility.TrTextContent("Anim. Compression", "The type of compression that will be applied to this mesh's animation(s)."); - public GUIContent[] AnimCompressionOptLegacy = - { - EditorGUIUtility.TrTextContent("Off", "Disables animation compression. This means that Unity doesn't reduce keyframe count on import, which leads to the highest precision animations, but slower performance and bigger file and runtime memory size. It is generally not advisable to use this option - if you need higher precision animation, you should enable keyframe reduction and lower allowed Animation Compression Error values instead."), - EditorGUIUtility.TrTextContent("Keyframe Reduction", "Reduces keyframes on import. If selected, the Animation Compression Errors options are displayed."), - EditorGUIUtility.TrTextContent("Keyframe Reduction and Compression", "Reduces keyframes on import and compresses keyframes when storing animations in files. This affects only file size - the runtime memory size is the same as Keyframe Reduction. If selected, the Animation Compression Errors options are displayed.") - }; - public GUIContent[] AnimCompressionOpt = - { - EditorGUIUtility.TrTextContent("Off", "Disables animation compression. This means that Unity doesn't reduce keyframe count on import, which leads to the highest precision animations, but slower performance and bigger file and runtime memory size. It is generally not advisable to use this option - if you need higher precision animation, you should enable keyframe reduction and lower allowed Animation Compression Error values instead."), - EditorGUIUtility.TrTextContent("Keyframe Reduction", "Reduces keyframes on import. If selected, the Animation Compression Errors options are displayed."), - EditorGUIUtility.TrTextContent("Optimal", "Reduces keyframes on import and choose between different curve representations to reduce memory usage at runtime. This affects the runtime memory size and how curves are evaluated.") - }; - - public GUIContent AnimRotationErrorLabel = EditorGUIUtility.TrTextContent("Rotation Error", "Defines how much rotation curves should be reduced. The smaller value you use - the higher precision you get."); - public GUIContent AnimPositionErrorLabel = EditorGUIUtility.TrTextContent("Position Error", "Defines how much position curves should be reduced. The smaller value you use - the higher precision you get."); - public GUIContent AnimScaleErrorLabel = EditorGUIUtility.TrTextContent("Scale Error", "Defines how much scale curves should be reduced. The smaller value you use - the higher precision you get."); - public GUIContent AnimationCompressionHelp = EditorGUIUtility.TrTextContent("Rotation error is defined as maximum angle deviation allowed in degrees, for others it is defined as maximum distance/delta deviation allowed in percents"); - public GUIContent clipMultiEditInfo = EditorGUIUtility.TrTextContent("Multi-object editing of clips not supported."); - - public GUIContent updateMuscleDefinitionFromSource = EditorGUIUtility.TrTextContent("Update", "Update the copy of the muscle definition from the source."); - - public GUIContent MotionSetting = EditorGUIUtility.TrTextContent("Motion", "Advanced setting for root motion and blending pivot"); - public GUIContent MotionNode = EditorGUIUtility.TrTextContent("Root Motion Node", "Define a transform node that will be used to create root motion curves"); - public GUIContent ImportMessages = EditorGUIUtility.TrTextContent("Import Messages"); - - public GUIContent GenerateRetargetingWarnings = EditorGUIUtility.TrTextContent("Generate Retargeting Quality Report"); - public GUIContent RetargetingQualityCompares = EditorGUIUtility.TrTextContentWithIcon("Retargeting Quality compares retargeted with original animation. It reports average and maximum position/orientation difference for body parts. It may slow down import time of this file.", MessageType.Info); - public GUIContent AnimationDataWas = EditorGUIUtility.TrTextContentWithIcon("Animation data was imported using a deprecated Generation option in the Rig tab. Please switch to a non-deprecated import mode in the Rig tab to be able to edit the animation import settings.", MessageType.Info); - public GUIContent TheAnimationsSettingsCanBe = EditorGUIUtility.TrTextContentWithIcon("The animations settings can be edited after clicking Apply.", MessageType.Info); - public GUIContent ErrorsFoundWhileImporting = EditorGUIUtility.TrTextContentWithIcon("Error(s) found while importing rig in this animation file. Open \"Rig\" tab for more details.", MessageType.Error); - public GUIContent NoAnimationDataAvailable = EditorGUIUtility.TrTextContentWithIcon("No animation data available in this model.", MessageType.Info); - public GUIContent TheRigsOfTheSelectedModelsHave = EditorGUIUtility.TrTextContentWithIcon("The rigs of the selected models have different Animation Types.", MessageType.Info); - public GUIContent TheRigsOfTheSelectedModelsAre = EditorGUIUtility.TrTextContentWithIcon("The rigs of the selected models are not setup to handle animation. Change the Animation Type in the Rig tab and click Apply.", MessageType.Info); - public GUIContent Clips = EditorGUIUtility.TrTextContent("Clips"); - public GUIContent Start = EditorGUIUtility.TrTextContent("Start"); - public GUIContent End = EditorGUIUtility.TrTextContent("End"); - public GUIContent MaskHasAPath = EditorGUIUtility.TrTextContent("Mask has a path that does not match the transform hierarchy. Animation may not import correctly."); - public GUIContent UpdateMask = EditorGUIUtility.TrTextContent("Update Mask"); - public GUIContent SourceMaskHasChanged = EditorGUIUtility.TrTextContent("Source Mask has changed since last import and must be updated."); - public GUIContent SourceMaskHasAPath = EditorGUIUtility.TrTextContent("Source Mask has a path that does not match the transform hierarchy. Animation may not import correctly."); - - public GUIContent Mask = EditorGUIUtility.TrTextContent("Mask", "Configure the mask for this clip to remove unnecessary curves."); - - public GUIContent ImportAnimatedCustomProperties = EditorGUIUtility.TrTextContent("Animated Custom Properties", "Controls if animated custom properties are imported."); - public GUIContent ImportConstraints = EditorGUIUtility.TrTextContent("Import Constraints", "Controls if the constraints are imported."); - - public Styles() - { - numberStyle.alignment = TextAnchor.UpperRight; - } - } - static Styles styles; - - public ModelImporterClipEditor(AssetImporterEditor panelContainer) - : base(panelContainer) - {} - - internal override void OnEnable() - { - m_ClipAnimations = serializedObject.FindProperty("m_ClipAnimations"); - - m_AnimationType = serializedObject.FindProperty("m_AnimationType"); - m_LegacyGenerateAnimations = serializedObject.FindProperty("m_LegacyGenerateAnimations"); - - // Animation - m_ImportAnimation = serializedObject.FindProperty("m_ImportAnimation"); - m_BakeSimulation = serializedObject.FindProperty("m_BakeSimulation"); - m_ResampleCurves = serializedObject.FindProperty("m_ResampleCurves"); - m_AnimationCompression = serializedObject.FindProperty("m_AnimationCompression"); - m_AnimationRotationError = serializedObject.FindProperty("m_AnimationRotationError"); - m_AnimationPositionError = serializedObject.FindProperty("m_AnimationPositionError"); - m_AnimationScaleError = serializedObject.FindProperty("m_AnimationScaleError"); - m_AnimationWrapMode = serializedObject.FindProperty("m_AnimationWrapMode"); - m_ImportAnimatedCustomProperties = serializedObject.FindProperty("m_ImportAnimatedCustomProperties"); - m_ImportConstraints = serializedObject.FindProperty("m_ImportConstraints"); - - m_RigImportErrors = serializedObject.FindProperty("m_RigImportErrors"); - m_RigImportWarnings = serializedObject.FindProperty("m_RigImportWarnings"); - m_AnimationImportErrors = serializedObject.FindProperty("m_AnimationImportErrors"); - m_AnimationImportWarnings = serializedObject.FindProperty("m_AnimationImportWarnings"); - m_AnimationRetargetingWarnings = serializedObject.FindProperty("m_AnimationRetargetingWarnings"); - m_AnimationDoRetargetingWarnings = serializedObject.FindProperty("m_AnimationDoRetargetingWarnings"); - - if (serializedObject.isEditingMultipleObjects) - return; - - // Find all serialized property before calling SetupDefaultClips - if (m_ClipAnimations.arraySize == 0) - SetupDefaultClips(); - - selectedClipIndex = EditorPrefs.GetInt("ModelImporterClipEditor.ActiveClipIndex", 0); - ValidateClipSelectionIndex(); - EditorPrefs.SetInt("ModelImporterClipEditor.ActiveClipIndex", selectedClipIndex); - - if (m_AnimationClipEditor != null && selectedClipIndex >= 0) - SyncClipEditor(); - - // Automatically select the first clip - if (m_ClipAnimations.arraySize != 0) - SelectClip(selectedClipIndex); - - string[] transformPaths = singleImporter.transformPaths; - m_MotionNodeList = new GUIContent[transformPaths.Length + 1]; - - m_MotionNodeList[0] = EditorGUIUtility.TrTextContent(""); - - for (int i = 0; i < transformPaths.Length; i++) - { - if (i == 0) - { - m_MotionNodeList[1] = EditorGUIUtility.TrTextContent(""); - } - else - { - m_MotionNodeList[i + 1] = new GUIContent(transformPaths[i]); - } - } - - m_MotionNodeName = serializedObject.FindProperty("m_MotionNodeName"); - motionNodeIndex = ArrayUtility.FindIndex(m_MotionNodeList, delegate(GUIContent content) { return content.text == m_MotionNodeName.stringValue; }); - motionNodeIndex = motionNodeIndex < 1 ? 0 : motionNodeIndex; - } - - void SyncClipEditor() - { - if (m_AnimationClipEditor == null || m_MaskInspector == null) - return; - - AnimationClipInfoProperties info = GetAnimationClipInfoAtIndex(selectedClipIndex); - - // It mandatory to set clip info into mask inspector first, this will update m_Mask. - m_MaskInspector.clipInfo = info; - - m_AnimationClipEditor.ShowRange(info); - m_AnimationClipEditor.mask = m_Mask; - } - - private void SetupDefaultClips() - { - // Create dummy SerializedObject where we can add a clip for each - // take without making any properties show up as changed. - m_DefaultClipsSerializedObject = new SerializedObject(target); - m_ClipAnimations = m_DefaultClipsSerializedObject.FindProperty("m_ClipAnimations"); - m_AnimationType = m_DefaultClipsSerializedObject.FindProperty("m_AnimationType"); - m_ClipAnimations.arraySize = 0; - - foreach (TakeInfo takeInfo in singleImporter.importedTakeInfos) - { - AddClip(takeInfo); - } - } - - // When switching to explicitly defined clips, we must fix up the recycleID's to not lose AnimationClip references. - // When m_ClipAnimations is defined, the clips are identified by the clipName - // When m_ClipAnimations is not defined, the clips are identified by the takeName - void PatchDefaultClipTakeNamesToSplitClipNames() - { - foreach (TakeInfo takeInfo in singleImporter.importedTakeInfos) - { - PatchImportSettingRecycleID.Patch(serializedObject, 74, takeInfo.name, takeInfo.defaultClipName); - } - } - - // A dummy SerializedObject is created when there are no explicitly defined clips. - // When the user modifies any settings these clips must be transferred to the model importer. - private void TransferDefaultClipsToCustomClips() - { - if (m_DefaultClipsSerializedObject == null) - return; - - bool wasEmpty = serializedObject.FindProperty("m_ClipAnimations").arraySize == 0; - if (!wasEmpty) - Debug.LogError("Transferring default clips failed, target already has clips"); - - // Transfer data to main SerializedObject - serializedObject.CopyFromSerializedProperty(m_ClipAnimations); - m_ClipAnimations = serializedObject.FindProperty("m_ClipAnimations"); - - m_DefaultClipsSerializedObject = null; - - PatchDefaultClipTakeNamesToSplitClipNames(); - - SyncClipEditor(); - } - - private void ValidateClipSelectionIndex() - { - // selected clip index can be invalid if array was changed and then reverted. - if (selectedClipIndex > m_ClipAnimations.arraySize - 1) - { - selectedClipIndex = 0; - } - } - - internal override void OnDestroy() - { - DestroyEditorsAndData(); - } - - internal override void OnDisable() - { - DestroyEditorsAndData(); - - base.OnDisable(); - } - - internal override void ResetValues() - { - base.ResetValues(); - m_ClipAnimations = serializedObject.FindProperty("m_ClipAnimations"); - m_AnimationType = serializedObject.FindProperty("m_AnimationType"); - m_DefaultClipsSerializedObject = null; - if (m_ClipAnimations.arraySize == 0) - SetupDefaultClips(); - - ValidateClipSelectionIndex(); - UpdateList(); - SelectClip(selectedClipIndex); - } - - void AnimationClipGUI() - { - string errors = m_AnimationImportErrors.stringValue; - string warnings = m_AnimationImportWarnings.stringValue; - string rigWarnings = m_RigImportWarnings.stringValue; - string retargetWarnings = m_AnimationRetargetingWarnings.stringValue; - - if (errors.Length > 0) - { - EditorGUILayout.HelpBox(styles.ErrorsFoundWhileImportingThisAnimation); - } - else - { - if (rigWarnings.Length > 0) - { - EditorGUILayout.HelpBox(styles.WarningsFoundWhileImportingRig); - } - - if (warnings.Length > 0) - { - EditorGUILayout.HelpBox(styles.WarningsFoundWhileImportingThisAnimation); - } - } - - // Show general animation import settings - AnimationSettings(); - - if (serializedObject.isEditingMultipleObjects) - return; - - Profiler.BeginSample("Clip inspector"); - - EditorGUILayout.Space(); - - // Show list of animations and inspector for individual animation - if (targets.Length == 1) - AnimationSplitTable(); - else - GUILayout.Label(styles.clipMultiEditInfo, EditorStyles.helpBox); - - Profiler.EndSample(); - - RootMotionNodeSettings(); - - importMessageFoldout = EditorGUILayout.Foldout(importMessageFoldout, styles.ImportMessages, true); - - if (importMessageFoldout) - { - if (errors.Length > 0) - EditorGUILayout.HelpBox(L10n.Tr(errors), MessageType.Error); - if (warnings.Length > 0) - EditorGUILayout.HelpBox(L10n.Tr(warnings), MessageType.Warning); - if (animationType == ModelImporterAnimationType.Human) - { - EditorGUILayout.PropertyField(m_AnimationDoRetargetingWarnings, styles.GenerateRetargetingWarnings); - - if (m_AnimationDoRetargetingWarnings.boolValue) - { - if (retargetWarnings.Length > 0) - { - EditorGUILayout.HelpBox(L10n.Tr(retargetWarnings), MessageType.Info); - } - } - else - { - EditorGUILayout.HelpBox(styles.RetargetingQualityCompares); - } - } - } - } - - public override void OnInspectorGUI() - { - if (styles == null) - styles = new Styles(); - - EditorGUILayout.PropertyField(m_ImportConstraints, styles.ImportConstraints); - EditorGUILayout.PropertyField(m_ImportAnimation, styles.ImportAnimations); - - if (m_ImportAnimation.boolValue && !m_ImportAnimation.hasMultipleDifferentValues) - { - bool hasNoValidAnimationData = targets.Length == 1 && singleImporter.importedTakeInfos.Length == 0 && singleImporter.animationType != ModelImporterAnimationType.None; - - if (IsDeprecatedMultiAnimationRootImport()) - EditorGUILayout.HelpBox(styles.AnimationDataWas); - else if (hasNoValidAnimationData) - { - if (serializedObject.hasModifiedProperties) - { - EditorGUILayout.HelpBox(styles.TheAnimationsSettingsCanBe); - } - else - { - string errors = m_RigImportErrors.stringValue; - - if (errors.Length > 0) - { - EditorGUILayout.HelpBox(styles.ErrorsFoundWhileImporting); - } - else - { - EditorGUILayout.HelpBox(styles.NoAnimationDataAvailable); - } - } - } - else if (m_AnimationType.hasMultipleDifferentValues) - EditorGUILayout.HelpBox(styles.TheRigsOfTheSelectedModelsHave); - else if (animationType == ModelImporterAnimationType.None) - EditorGUILayout.HelpBox(styles.TheRigsOfTheSelectedModelsAre); - else - { - if (m_ImportAnimation.boolValue && !m_ImportAnimation.hasMultipleDifferentValues) - AnimationClipGUI(); - } - } - } - - void AnimationSettings() - { - EditorGUILayout.Space(); - - // Bake IK - bool isBakeIKSupported = true; - foreach (ModelImporter importer in targets) - if (!importer.isBakeIKSupported) - isBakeIKSupported = false; - using (new EditorGUI.DisabledScope(!isBakeIKSupported)) - { - EditorGUILayout.PropertyField(m_BakeSimulation, styles.BakeIK); - } - - if (animationType == ModelImporterAnimationType.Generic) - { - EditorGUILayout.PropertyField(m_ResampleCurves, styles.ResampleCurves); - } - else - { - m_ResampleCurves.boolValue = true; - } - - // Wrap mode - if (animationType == ModelImporterAnimationType.Legacy) - { - EditorGUI.showMixedValue = m_AnimationWrapMode.hasMultipleDifferentValues; - EditorGUILayout.Popup(m_AnimationWrapMode, styles.AnimWrapModeOpt, styles.AnimWrapModeLabel); - EditorGUI.showMixedValue = false; - - // Compression - int[] kCompressionValues = { (int)ModelImporterAnimationCompression.Off, (int)ModelImporterAnimationCompression.KeyframeReduction, (int)ModelImporterAnimationCompression.KeyframeReductionAndCompression }; - EditorGUILayout.IntPopup(m_AnimationCompression, styles.AnimCompressionOptLegacy, kCompressionValues, styles.AnimCompressionLabel); - } - else - { - // Compression - int[] kCompressionValues = { (int)ModelImporterAnimationCompression.Off, (int)ModelImporterAnimationCompression.KeyframeReduction, (int)ModelImporterAnimationCompression.Optimal }; - EditorGUILayout.IntPopup(m_AnimationCompression, styles.AnimCompressionOpt, kCompressionValues, styles.AnimCompressionLabel); - } - - if (m_AnimationCompression.intValue > (int)ModelImporterAnimationCompression.Off) - { - // keyframe reduction settings - EditorGUILayout.PropertyField(m_AnimationRotationError, styles.AnimRotationErrorLabel); - EditorGUILayout.PropertyField(m_AnimationPositionError, styles.AnimPositionErrorLabel); - EditorGUILayout.PropertyField(m_AnimationScaleError, styles.AnimScaleErrorLabel); - GUILayout.Label(styles.AnimationCompressionHelp, EditorStyles.helpBox); - } - - EditorGUILayout.PropertyField(m_ImportAnimatedCustomProperties, styles.ImportAnimatedCustomProperties); - } - - void RootMotionNodeSettings() - { - if (animationType == ModelImporterAnimationType.Human || animationType == ModelImporterAnimationType.Generic) - { - motionNodeFoldout = EditorGUILayout.Foldout(motionNodeFoldout, styles.MotionSetting, true); - - if (motionNodeFoldout) - { - EditorGUI.BeginChangeCheck(); - motionNodeIndex = EditorGUILayout.Popup(styles.MotionNode, motionNodeIndex, m_MotionNodeList); - - if (EditorGUI.EndChangeCheck()) - { - if (motionNodeIndex > 0 && motionNodeIndex < m_MotionNodeList.Length) - { - m_MotionNodeName.stringValue = m_MotionNodeList[motionNodeIndex].text; - } - else - { - m_MotionNodeName.stringValue = ""; - } - } - } - } - } - - void DestroyEditorsAndData() - { - if (m_AnimationClipEditor != null) - { - Object.DestroyImmediate(m_AnimationClipEditor); - m_AnimationClipEditor = null; - } - - if (m_MaskInspector) - { - DestroyImmediate(m_MaskInspector); - m_MaskInspector = null; - } - if (m_Mask) - { - DestroyImmediate(m_Mask); - m_Mask = null; - } - } - - void SelectClip(int selected) - { - // If you were editing Clip Name (delayed text field had focus) and then selected a new clip from the clip list, - // the active string in the delayed text field would get applied to the new selected clip instead of the old. - // HACK: Calling EndGUI here on the recycled delayed text editor seems to fix this issue. - // Sometime we should reimplement delayed text field code to not be super confusing and then fix the issue more properly. - if (EditorGUI.s_DelayedTextEditor != null && Event.current != null) - EditorGUI.s_DelayedTextEditor.EndGUI(Event.current.type); - - DestroyEditorsAndData(); - - selectedClipIndex = selected; - if (selectedClipIndex < 0 || selectedClipIndex >= m_ClipAnimations.arraySize) - { - selectedClipIndex = -1; - return; - } - - AnimationClipInfoProperties info = GetAnimationClipInfoAtIndex(selected); - AnimationClip clip = singleImporter.GetPreviewAnimationClipForTake(info.takeName); - if (clip != null) - { - m_AnimationClipEditor = (AnimationClipEditor)Editor.CreateEditor(clip); - InitMask(info); - SyncClipEditor(); - } - } - - void UpdateList() - { - if (m_ClipList == null) - return; - List clipInfos = new List(); - for (int i = 0; i < m_ClipAnimations.arraySize; i++) - clipInfos.Add(GetAnimationClipInfoAtIndex(i)); - m_ClipList.list = clipInfos; - } - - void AddClipInList(ReorderableList list) - { - if (m_DefaultClipsSerializedObject != null) - TransferDefaultClipsToCustomClips(); - - - int takeIndex = 0; - if (0 < selectedClipIndex && selectedClipIndex < m_ClipAnimations.arraySize) - { - AnimationClipInfoProperties info = GetAnimationClipInfoAtIndex(selectedClipIndex); - for (int i = 0; i < singleImporter.importedTakeInfos.Length; i++) - { - if (singleImporter.importedTakeInfos[i].name == info.takeName) - { - takeIndex = i; - break; - } - } - } - - AddClip(singleImporter.importedTakeInfos[takeIndex]); - UpdateList(); - SelectClip(list.list.Count - 1); - } - - void RemoveClipInList(ReorderableList list) - { - TransferDefaultClipsToCustomClips(); - - RemoveClip(list.index); - UpdateList(); - SelectClip(Mathf.Min(list.index, list.count - 1)); - } - - void SelectClipInList(ReorderableList list) - { - SelectClip(list.index); - } - - const int kFrameColumnWidth = 45; - - private void DrawClipElement(Rect rect, int index, bool selected, bool focused) - { - AnimationClipInfoProperties info = m_ClipList.list[index] as AnimationClipInfoProperties; - rect.xMax -= kFrameColumnWidth * 2; - GUI.Label(rect, info.name, EditorStyles.label); - rect.x = rect.xMax; - rect.width = kFrameColumnWidth; - GUI.Label(rect, info.firstFrame.ToString("0.0"), styles.numberStyle); - rect.x = rect.xMax; - GUI.Label(rect, info.lastFrame.ToString("0.0"), styles.numberStyle); - } - - private void DrawClipHeader(Rect rect) - { - rect.xMax -= kFrameColumnWidth * 2; - GUI.Label(rect, styles.Clips, EditorStyles.label); - rect.x = rect.xMax; - rect.width = kFrameColumnWidth; - GUI.Label(rect, styles.Start, styles.numberStyle); - rect.x = rect.xMax; - GUI.Label(rect, styles.End, styles.numberStyle); - } - - void AnimationSplitTable() - { - if (m_ClipList == null) - { - m_ClipList = new ReorderableList(new List(), typeof(string), false, true, true, true); - m_ClipList.onAddCallback = AddClipInList; - m_ClipList.onSelectCallback = SelectClipInList; - m_ClipList.onRemoveCallback = RemoveClipInList; - m_ClipList.drawElementCallback = DrawClipElement; - m_ClipList.drawHeaderCallback = DrawClipHeader; - m_ClipList.elementHeight = 16; - UpdateList(); - m_ClipList.index = selectedClipIndex; - } - m_ClipList.DoLayoutList(); - - EditorGUI.BeginChangeCheck(); - - // Show selected clip info - { - AnimationClipInfoProperties clip = GetSelectedClipInfo(); - if (clip == null) - return; - - if (m_AnimationClipEditor != null && selectedClipIndex != -1) - { - GUILayout.Space(5); - - AnimationClip actualClip = m_AnimationClipEditor.target as AnimationClip; - - if (!actualClip.legacy) - GetSelectedClipInfo().AssignToPreviewClip(actualClip); - - TakeInfo[] importedTakeInfos = singleImporter.importedTakeInfos; - string[] takeNames = new string[importedTakeInfos.Length]; - for (int i = 0; i < importedTakeInfos.Length; i++) - takeNames[i] = importedTakeInfos[i].name; - - EditorGUI.BeginChangeCheck(); - string currentName = clip.name; - int takeIndex = ArrayUtility.IndexOf(takeNames, clip.takeName); - m_AnimationClipEditor.takeNames = takeNames; - m_AnimationClipEditor.takeIndex = ArrayUtility.IndexOf(takeNames, clip.takeName); - m_AnimationClipEditor.DrawHeader(); - - if (EditorGUI.EndChangeCheck()) - { - // We renamed the clip name, try to maintain the localIdentifierInFile so we don't lose any data. - if (clip.name != currentName) - { - TransferDefaultClipsToCustomClips(); - PatchImportSettingRecycleID.Patch(serializedObject, 74, currentName, clip.name); - } - - int newTakeIndex = m_AnimationClipEditor.takeIndex; - if (newTakeIndex != -1 && newTakeIndex != takeIndex) - { - clip.name = MakeUniqueClipName(takeNames[newTakeIndex]); - SetupTakeNameAndFrames(clip, importedTakeInfos[newTakeIndex]); - GUIUtility.keyboardControl = 0; - SelectClip(selectedClipIndex); - - // actualClip has been changed by SelectClip - actualClip = m_AnimationClipEditor.target as AnimationClip; - } - } - - m_AnimationClipEditor.OnInspectorGUI(); - - AvatarMaskSettings(GetSelectedClipInfo()); - - if (!actualClip.legacy) - GetSelectedClipInfo().ExtractFromPreviewClip(actualClip); - } - } - - if (EditorGUI.EndChangeCheck() || m_AnimationClipEditor.needsToGenerateClipInfo) - { - TransferDefaultClipsToCustomClips(); - m_AnimationClipEditor.needsToGenerateClipInfo = false; - } - } - - public override bool HasPreviewGUI() - { - return m_ImportAnimation.boolValue && m_AnimationClipEditor != null && m_AnimationClipEditor.HasPreviewGUI(); - } - - public override void OnPreviewSettings() - { - if (m_AnimationClipEditor != null) - m_AnimationClipEditor.OnPreviewSettings(); - } - - bool IsDeprecatedMultiAnimationRootImport() - { - if (animationType == ModelImporterAnimationType.Legacy) - return legacyGenerateAnimations == ModelImporterGenerateAnimations.InOriginalRoots || legacyGenerateAnimations == ModelImporterGenerateAnimations.InNodes; - else - return false; - } - - public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - if (m_AnimationClipEditor) - m_AnimationClipEditor.OnInteractivePreviewGUI(r, background); - } - - AnimationClipInfoProperties GetAnimationClipInfoAtIndex(int index) - { - return new AnimationClipInfoProperties(m_ClipAnimations.GetArrayElementAtIndex(index)); - } - - AnimationClipInfoProperties GetSelectedClipInfo() - { - if (selectedClipIndex >= 0 && selectedClipIndex < m_ClipAnimations.arraySize) - return GetAnimationClipInfoAtIndex(selectedClipIndex); - else - return null; - } - - /// - /// Removes the duplicate brackets from a name. - /// - /// The name without the duplicate suffix. - /// Name. - /// Number between the brackets (-1 if no brackets were found). - string RemoveDuplicateSuffix(string name, out int number) - { - number = -1; - - // The smallest format is " (1)". - int length = name.Length; - if (length < 4 || name[length - 1] != ')') - return name; - - // Has an opening bracket. - int openingBracket = name.LastIndexOf('(', length - 2); - if (openingBracket == -1 || name[openingBracket - 1] != ' ') - return name; - - // Brackets aren't empty. - int numberLength = length - openingBracket - 2; - if (numberLength == 0) - return name; - - // Only has digits between the brackets. - int i = 0; - while (i < numberLength && char.IsDigit(name[openingBracket + 1 + i])) - ++i; - if (i != numberLength) - return name; - - // Get number. - string numberString = name.Substring(openingBracket + 1, numberLength); - number = int.Parse(numberString); - - // Extract base name. - return name.Substring(0, openingBracket - 1); - } - - /// - /// Finds the next duplicate number. - /// - /// The next duplicate number (-1 if there is no other clip with the same name). - /// Base name. - int FindNextDuplicateNumber(string baseName) - { - int nextNumber = -1; - - for (int i = 0; i < m_ClipAnimations.arraySize; ++i) - { - AnimationClipInfoProperties clip = GetAnimationClipInfoAtIndex(i); - - int clipNumber; - string clipBaseName = RemoveDuplicateSuffix(clip.name, out clipNumber); - if (clipBaseName == baseName) - { - // Same base, so next number is at least 1. - if (nextNumber == -1) - nextNumber = 1; - - // Next number is one more than the maximum number found. - if (clipNumber != -1) - nextNumber = Math.Max(nextNumber, clipNumber + 1); - } - } - - return nextNumber; - } - - string MakeUniqueClipName(string name) - { - int dummy; - string baseName = RemoveDuplicateSuffix(name, out dummy); - - int nextNumber = FindNextDuplicateNumber(baseName); - if (nextNumber != -1) - name = baseName + " (" + nextNumber + ")"; - - return name; - } - - void RemoveClip(int index) - { - m_ClipAnimations.DeleteArrayElementAtIndex(index); - if (m_ClipAnimations.arraySize == 0) - { - SetupDefaultClips(); - m_ImportAnimation.boolValue = false; - } - } - - void SetupTakeNameAndFrames(AnimationClipInfoProperties info, TakeInfo takeInfo) - { - info.takeName = takeInfo.name; - info.firstFrame = (int)Mathf.Round(takeInfo.bakeStartTime * takeInfo.sampleRate); - info.lastFrame = (int)Mathf.Round(takeInfo.bakeStopTime * takeInfo.sampleRate); - } - - void AddClip(TakeInfo takeInfo) - { - string uniqueName = MakeUniqueClipName(takeInfo.defaultClipName); - - m_ClipAnimations.InsertArrayElementAtIndex(m_ClipAnimations.arraySize); - AnimationClipInfoProperties info = GetAnimationClipInfoAtIndex(m_ClipAnimations.arraySize - 1); - - info.name = uniqueName; - SetupTakeNameAndFrames(info, takeInfo); - info.wrapMode = (int)WrapMode.Default; - info.loop = false; - info.orientationOffsetY = 0; - info.level = 0; - info.cycleOffset = 0; - info.loopTime = false; - info.loopBlend = false; - info.loopBlendOrientation = false; - info.loopBlendPositionY = false; - info.loopBlendPositionXZ = false; - info.keepOriginalOrientation = false; - info.keepOriginalPositionY = true; - info.keepOriginalPositionXZ = false; - info.heightFromFeet = false; - info.mirror = false; - info.maskType = ClipAnimationMaskType.None; - - SetBodyMaskDefaultValues(info); - - - info.ClearEvents(); - info.ClearCurves(); - } - - private AvatarMask m_Mask = null; - private AvatarMaskInspector m_MaskInspector = null; - static private bool m_MaskFoldout = false; - - //////////////////////////////////////////////////////////////////////////////////////////////////////// - /// - private void AvatarMaskSettings(AnimationClipInfoProperties clipInfo) - { - if (clipInfo != null && m_AnimationClipEditor != null) - { - InitMask(clipInfo); - int prevIndent = EditorGUI.indentLevel; - - // Don't make toggling foldout cause GUI.changed to be true (shouldn't cause undoable action etc.) - bool wasChanged = GUI.changed; - m_MaskFoldout = EditorGUILayout.Foldout(m_MaskFoldout, styles.Mask, true); - GUI.changed = wasChanged; - - if (clipInfo.maskType == ClipAnimationMaskType.CreateFromThisModel && !m_MaskInspector.IsMaskUpToDate() && !m_MaskInspector.IsMaskEmpty()) - { - GUILayout.BeginHorizontal(EditorStyles.helpBox); - GUILayout.Label(styles.MaskHasAPath, - EditorStyles.wordWrappedMiniLabel); - GUILayout.FlexibleSpace(); - GUILayout.BeginVertical(); - GUILayout.Space(5); - if (GUILayout.Button(styles.UpdateMask)) - { - SetTransformMaskFromReference(clipInfo); - m_MaskInspector.FillNodeInfos(); - } - - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - } - else if (clipInfo.maskType == ClipAnimationMaskType.CopyFromOther && clipInfo.MaskNeedsUpdating()) - { - GUILayout.BeginHorizontal(EditorStyles.helpBox); - GUILayout.Label(styles.SourceMaskHasChanged, - EditorStyles.wordWrappedMiniLabel); - GUILayout.FlexibleSpace(); - GUILayout.BeginVertical(); - GUILayout.Space(5); - if (GUILayout.Button(styles.UpdateMask)) - { - clipInfo.MaskToClip(clipInfo.maskSource); - } - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - } - else if (clipInfo.maskType == ClipAnimationMaskType.CopyFromOther && !m_MaskInspector.IsMaskUpToDate()) - { - GUILayout.BeginHorizontal(EditorStyles.helpBox); - GUILayout.Label(styles.SourceMaskHasAPath, - EditorStyles.wordWrappedMiniLabel); - GUILayout.FlexibleSpace(); - GUILayout.BeginVertical(); - GUILayout.Space(5); - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - } - - if (m_MaskFoldout) - { - EditorGUI.indentLevel++; - m_MaskInspector.OnInspectorGUI(); - } - - EditorGUI.indentLevel = prevIndent; - } - } - - private void InitMask(AnimationClipInfoProperties clipInfo) - { - if (m_Mask == null) - { - AnimationClip clip = m_AnimationClipEditor.target as AnimationClip; - - m_Mask = new AvatarMask(); - m_MaskInspector = (AvatarMaskInspector)Editor.CreateEditor(m_Mask); - m_MaskInspector.canImport = false; - m_MaskInspector.showBody = clip.isHumanMotion; - m_MaskInspector.clipInfo = clipInfo; - } - } - - private void SetTransformMaskFromReference(AnimationClipInfoProperties clipInfo) - { - string[] transformPaths = referenceTransformPaths; - string[] humanTransforms = animationType == ModelImporterAnimationType.Human ? - AvatarMaskUtility.GetAvatarHumanAndActiveExtraTransforms(serializedObject, clipInfo.transformMaskProperty, transformPaths) : - AvatarMaskUtility.GetAvatarInactiveTransformMaskPaths(clipInfo.transformMaskProperty); - - AvatarMaskUtility.UpdateTransformMask(clipInfo.transformMaskProperty, transformPaths, humanTransforms, animationType == ModelImporterAnimationType.Human); - } - - private void SetBodyMaskDefaultValues(AnimationClipInfoProperties clipInfo) - { - SerializedProperty bodyMask = clipInfo.bodyMaskProperty; - bodyMask.ClearArray(); - for (int i = 0; i < (int)AvatarMaskBodyPart.LastBodyPart; ++i) - { - bodyMask.InsertArrayElementAtIndex(i); - bodyMask.GetArrayElementAtIndex(i).intValue = 1; - } - } - } -} diff --git a/Editor/Mono/ImportSettings/ModelImporterEditor.cs b/Editor/Mono/ImportSettings/ModelImporterEditor.cs deleted file mode 100644 index f11f5c3c8d..0000000000 --- a/Editor/Mono/ImportSettings/ModelImporterEditor.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - [CustomEditor(typeof(ModelImporter))] - [CanEditMultipleObjects] - internal class ModelImporterEditor : AssetImporterTabbedEditor - { - public override void OnEnable() - { - if (tabs == null) - { - tabs = new BaseAssetImporterTabUI[] { new ModelImporterModelEditor(this), new ModelImporterRigEditor(this), new ModelImporterClipEditor(this), new ModelImporterMaterialEditor(this) }; - m_TabNames = new string[] {"Model", "Rig", "Animation", "Materials"}; - } - base.OnEnable(); - } - - public override void OnDisable() - { - foreach (var tab in tabs) - { - tab.OnDisable(); - } - base.OnDisable(); - } - - //None of the ModelImporter sub editors support multi preview - public override bool HasPreviewGUI() - { - return base.HasPreviewGUI() && targets.Length < 2; - } - - public override GUIContent GetPreviewTitle() - { - var tab = activeTab as ModelImporterClipEditor; - if (tab != null) - return new GUIContent(tab.selectedClipName); - - return base.GetPreviewTitle(); - } - - // Only show the imported GameObject when the Model tab is active; not when the Animation tab is active - public override bool showImportedObject { get { return activeTab is ModelImporterModelEditor; } } - } -} diff --git a/Editor/Mono/ImportSettings/ModelImporterMaterialEditor.cs b/Editor/Mono/ImportSettings/ModelImporterMaterialEditor.cs deleted file mode 100644 index 8cbce2223f..0000000000 --- a/Editor/Mono/ImportSettings/ModelImporterMaterialEditor.cs +++ /dev/null @@ -1,504 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.Experimental.AssetImporters; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class ModelImporterMaterialEditor : BaseAssetImporterTabUI - { - bool m_ShowAllMaterialNameOptions = true; - bool m_ShowMaterialRemapOptions = false; - - // Material - SerializedProperty m_ImportMaterials; - SerializedProperty m_MaterialName; - SerializedProperty m_MaterialSearch; - SerializedProperty m_MaterialLocation; - - SerializedProperty m_Materials; - SerializedProperty m_ExternalObjects; - - SerializedProperty m_HasEmbeddedTextures; - - SerializedProperty m_SupportsEmbeddedMaterials; - - private bool m_HasEmbeddedMaterials = false; - - static class Styles - { - public static GUIContent ImportMaterials = EditorGUIUtility.TrTextContent("Import Materials"); - - public static GUIContent MaterialLocation = EditorGUIUtility.TrTextContent("Location"); - public static GUIContent[] MaterialLocationOpt = - { - EditorGUIUtility.TrTextContent("Use External Materials (Legacy)", "Use external materials if found in the project."), - EditorGUIUtility.TrTextContent("Use Embedded Materials", "Embed the material inside the imported asset.") - }; - - public static GUIContent MaterialName = EditorGUIUtility.TrTextContent("Naming"); - public static GUIContent[] MaterialNameOptMain = - { - EditorGUIUtility.TrTextContent("By Base Texture Name"), - EditorGUIUtility.TrTextContent("From Model's Material"), - EditorGUIUtility.TrTextContent("Model Name + Model's Material"), - }; - public static GUIContent[] MaterialNameOptAll = - { - EditorGUIUtility.TrTextContent("By Base Texture Name"), - EditorGUIUtility.TrTextContent("From Model's Material"), - EditorGUIUtility.TrTextContent("Model Name + Model's Material"), - EditorGUIUtility.TrTextContent("Texture Name or Model Name + Model's Material (Obsolete)"), - }; - public static GUIContent MaterialSearch = EditorGUIUtility.TrTextContent("Search"); - public static GUIContent[] MaterialSearchOpt = - { - EditorGUIUtility.TrTextContent("Local Materials Folder"), - EditorGUIUtility.TrTextContent("Recursive-Up"), - EditorGUIUtility.TrTextContent("Project-Wide") - }; - - public static GUIContent NoMaterialHelp = EditorGUIUtility.TrTextContent("Do not generate materials. Use Unity's default material instead."); - - public static GUIContent ExternalMaterialHelpStart = EditorGUIUtility.TrTextContent("For each imported material, Unity first looks for an existing material named %MAT%."); - public static GUIContent[] ExternalMaterialNameHelp = - { - EditorGUIUtility.TrTextContent("[BaseTextureName]"), - EditorGUIUtility.TrTextContent("[MaterialName]"), - EditorGUIUtility.TrTextContent("[ModelFileName]-[MaterialName]"), - EditorGUIUtility.TrTextContent("[BaseTextureName] or [ModelFileName]-[MaterialName] if no base texture can be found"), - }; - public static GUIContent[] ExternalMaterialSearchHelp = - { - EditorGUIUtility.TrTextContent("Unity will look for it in the local Materials folder."), - EditorGUIUtility.TrTextContent("Unity will do a recursive-up search for it in all Materials folders up to the Assets folder."), - EditorGUIUtility.TrTextContent("Unity will search for it anywhere inside the Assets folder.") - }; - public static GUIContent ExternalMaterialHelpEnd = EditorGUIUtility.TrTextContent("If it doesn't exist, a new one is created in the local Materials folder."); - - public static GUIContent InternalMaterialHelp = EditorGUIUtility.TrTextContent("Materials are embedded inside the imported asset."); - - public static GUIContent MaterialAssignmentsHelp = EditorGUIUtility.TrTextContent("Material assignments can be remapped below."); - - public static GUIContent ExternalMaterialMappings = EditorGUIUtility.TrTextContent("Remapped Materials", "External materials to use for each embedded material."); - - public static GUIContent NoMaterialMappingsHelp = EditorGUIUtility.TrTextContent("Re-import the asset to see the list of used materials."); - - public static GUIContent Textures = EditorGUIUtility.TrTextContent("Textures"); - public static GUIContent ExtractEmbeddedTextures = EditorGUIUtility.TrTextContent("Extract Textures...", "Click on this button to extract the embedded textures."); - - public static GUIContent Materials = EditorGUIUtility.TrTextContent("Materials"); - public static GUIContent ExtractEmbeddedMaterials = EditorGUIUtility.TrTextContent("Extract Materials...", "Click on this button to extract the embedded materials."); - - public static GUIContent RemapOptions = EditorGUIUtility.TrTextContent("On Demand Remap"); - public static GUIContent RemapMaterialsInProject = EditorGUIUtility.TrTextContent("Search and Remap", "Click on this button to search and remap the materials from the project."); - } - - public ModelImporterMaterialEditor(AssetImporterEditor panelContainer) - : base(panelContainer) - {} - - private void UpdateShowAllMaterialNameOptions() - { - // We need to display BasedOnTextureName_Or_ModelNameAndMaterialName obsolete option for objects which use this option -#pragma warning disable 618 - m_MaterialName = serializedObject.FindProperty("m_MaterialName"); - m_ShowAllMaterialNameOptions = (m_MaterialName.intValue == (int)ModelImporterMaterialName.BasedOnTextureName_Or_ModelNameAndMaterialName); -#pragma warning restore 618 - } - - private bool HasEmbeddedMaterials() - { - if (m_Materials.arraySize == 0) - return false; - - // if the m_ExternalObjecs map has any unapplied changes, keep the state of the button as is - if (m_ExternalObjects.serializedObject.hasModifiedProperties) - return m_HasEmbeddedMaterials; - - m_HasEmbeddedMaterials = true; - foreach (var t in m_ExternalObjects.serializedObject.targetObjects) - { - var importer = t as ModelImporter; - var externalObjectMap = importer.GetExternalObjectMap(); - var materialsList = importer.sourceMaterials; - - int remappedMaterialCount = 0; - foreach (var entry in externalObjectMap) - { - if (entry.Key.type == typeof(Material) && Array.Exists(materialsList, x => x.name == entry.Key.name)) - ++remappedMaterialCount; - } - - m_HasEmbeddedMaterials = m_HasEmbeddedMaterials && remappedMaterialCount != materialsList.Length; - } - return m_HasEmbeddedMaterials; - } - - internal override void OnEnable() - { - // Material - m_ImportMaterials = serializedObject.FindProperty("m_ImportMaterials"); - m_MaterialName = serializedObject.FindProperty("m_MaterialName"); - m_MaterialSearch = serializedObject.FindProperty("m_MaterialSearch"); - m_MaterialLocation = serializedObject.FindProperty("m_MaterialLocation"); - - m_Materials = serializedObject.FindProperty("m_Materials"); - m_ExternalObjects = serializedObject.FindProperty("m_ExternalObjects"); - - m_HasEmbeddedTextures = serializedObject.FindProperty("m_HasEmbeddedTextures"); - - m_SupportsEmbeddedMaterials = serializedObject.FindProperty("m_SupportsEmbeddedMaterials"); - - UpdateShowAllMaterialNameOptions(); - } - - internal override void ResetValues() - { - base.ResetValues(); - UpdateShowAllMaterialNameOptions(); - } - - internal override void PostApply() - { - UpdateShowAllMaterialNameOptions(); - } - - public override void OnInspectorGUI() - { - DoMaterialsGUI(); - } - - private void ExtractTexturesGUI() - { - using (new EditorGUILayout.HorizontalScope()) - { - EditorGUILayout.PrefixLabel(Styles.Textures); - - using ( - new EditorGUI.DisabledScope(!m_HasEmbeddedTextures.boolValue && - !m_HasEmbeddedTextures.hasMultipleDifferentValues)) - { - if (GUILayout.Button(Styles.ExtractEmbeddedTextures)) - { - // when extracting textures, we must handle the case when multiple selected assets could generate textures with the same name at the user supplied path - // we proceed as follows: - // 1. each asset extracts the textures in a separate temp folder - // 2. we remap the extracted assets to the respective asset importer - // 3. we generate unique names for each asset and move them to the user supplied path - // 4. we re-import all the assets to have the internal materials linked to the newly extracted textures - - List> outputsForTargets = new List>(); - // use the first target for selecting the destination folder, but apply that path for all targets - string destinationPath = (target as ModelImporter).assetPath; - destinationPath = EditorUtility.SaveFolderPanel("Select Textures Folder", - FileUtil.DeleteLastPathNameComponent(destinationPath), ""); - if (string.IsNullOrEmpty(destinationPath)) - { - // cancel the extraction if the user did not select a folder - return; - } - destinationPath = FileUtil.GetProjectRelativePath(destinationPath); - - try - { - // batch the extraction of the textures - AssetDatabase.StartAssetEditing(); - - foreach (var t in targets) - { - var tempPath = FileUtil.GetUniqueTempPathInProject(); - tempPath = tempPath.Replace("Temp", UnityEditorInternal.InternalEditorUtility.GetAssetsFolder()); - outputsForTargets.Add(Tuple.Create(t, tempPath)); - - var importer = t as ModelImporter; - importer.ExtractTextures(tempPath); - } - } - finally - { - AssetDatabase.StopAssetEditing(); - } - - try - { - // batch the remapping and the reimport of the assets - AssetDatabase.Refresh(); - AssetDatabase.StartAssetEditing(); - - foreach (var item in outputsForTargets) - { - var importer = item.Item1 as ModelImporter; - - var guids = AssetDatabase.FindAssets("t:Texture", new string[] {item.Item2}); - - foreach (var guid in guids) - { - var path = AssetDatabase.GUIDToAssetPath(guid); - var tex = AssetDatabase.LoadAssetAtPath(path); - if (tex == null) - continue; - - importer.AddRemap(new AssetImporter.SourceAssetIdentifier(tex), tex); - - var newPath = Path.Combine(destinationPath, FileUtil.UnityGetFileName(path)); - newPath = AssetDatabase.GenerateUniqueAssetPath(newPath); - AssetDatabase.MoveAsset(path, newPath); - } - - AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate); - - AssetDatabase.DeleteAsset(item.Item2); - } - } - finally - { - AssetDatabase.StopAssetEditing(); - } - } - } - } - } - - private bool ExtractMaterialsGUI() - { - using (new EditorGUILayout.HorizontalScope()) - { - EditorGUILayout.PrefixLabel(Styles.Materials); - using (new EditorGUI.DisabledScope(!HasEmbeddedMaterials())) - { - if (GUILayout.Button(Styles.ExtractEmbeddedMaterials)) - { - // use the first target for selecting the destination folder, but apply that path for all targets - string destinationPath = (target as ModelImporter).assetPath; - destinationPath = EditorUtility.SaveFolderPanel("Select Materials Folder", - FileUtil.DeleteLastPathNameComponent(destinationPath), ""); - if (string.IsNullOrEmpty(destinationPath)) - { - // cancel the extraction if the user did not select a folder - return false; - } - destinationPath = FileUtil.GetProjectRelativePath(destinationPath); - - try - { - // batch the extraction of the textures - AssetDatabase.StartAssetEditing(); - - PrefabUtility.ExtractMaterialsFromAsset(targets, destinationPath); - } - finally - { - AssetDatabase.StopAssetEditing(); - } - - // AssetDatabase.StopAssetEditing() invokes OnEnable(), which invalidates all the serialized properties, so we must return. - return true; - } - } - } - - return false; - } - - private bool MaterialRemapOptons() - { - m_ShowMaterialRemapOptions = EditorGUILayout.Foldout(m_ShowMaterialRemapOptions, Styles.RemapOptions); - if (m_ShowMaterialRemapOptions) - { - EditorGUI.indentLevel++; - EditorGUILayout.Popup(m_MaterialName, - m_ShowAllMaterialNameOptions ? Styles.MaterialNameOptAll : Styles.MaterialNameOptMain, - Styles.MaterialName); - EditorGUILayout.Popup(m_MaterialSearch, Styles.MaterialSearchOpt, Styles.MaterialSearch); - - string searchHelp = Styles.ExternalMaterialHelpStart.text.Replace("%MAT%", Styles.ExternalMaterialNameHelp[m_MaterialName.intValue].text) + "\n" + - Styles.ExternalMaterialSearchHelp[m_MaterialSearch.intValue].text; - - EditorGUILayout.HelpBox(searchHelp, MessageType.Info); - - EditorGUI.indentLevel--; - - using (new EditorGUILayout.HorizontalScope()) - { - GUILayout.FlexibleSpace(); - using (new EditorGUI.DisabledScope(assetTarget == null)) - { - if (GUILayout.Button(Styles.RemapMaterialsInProject)) - { - try - { - AssetDatabase.StartAssetEditing(); - - foreach (var t in targets) - { - var importer = t as ModelImporter; - // SearchAndReplaceMaterials will ensure the material name and search options get saved, while all other pending changes stay pending. - importer.SearchAndRemapMaterials((ModelImporterMaterialName)m_MaterialName.intValue, (ModelImporterMaterialSearch)m_MaterialSearch.intValue); - - AssetDatabase.WriteImportSettingsIfDirty(importer.assetPath); - AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate); - } - } - finally - { - AssetDatabase.StopAssetEditing(); - } - - return true; - } - } - } - EditorGUILayout.Space(); - } - - return false; - } - - void DoMaterialsGUI() - { - serializedObject.UpdateIfRequiredOrScript(); - - EditorGUILayout.PropertyField(m_ImportMaterials, Styles.ImportMaterials); - - string materialHelp = string.Empty; - if (!m_ImportMaterials.hasMultipleDifferentValues) - { - if (m_ImportMaterials.boolValue) - { - EditorGUILayout.Popup(m_MaterialLocation, Styles.MaterialLocationOpt, Styles.MaterialLocation); - if (!m_MaterialLocation.hasMultipleDifferentValues) - { - if (m_MaterialLocation.intValue == 0) - { - // (legacy) we're generating materials in the Materials folder - EditorGUILayout.Popup(m_MaterialName, - m_ShowAllMaterialNameOptions ? Styles.MaterialNameOptAll : Styles.MaterialNameOptMain, - Styles.MaterialName); - EditorGUILayout.Popup(m_MaterialSearch, Styles.MaterialSearchOpt, Styles.MaterialSearch); - - materialHelp = - Styles.ExternalMaterialHelpStart.text.Replace("%MAT%", - Styles.ExternalMaterialNameHelp[m_MaterialName.intValue].text) + "\n" + - Styles.ExternalMaterialSearchHelp[m_MaterialSearch.intValue].text + "\n" + - Styles.ExternalMaterialHelpEnd.text; - } - else if (m_Materials.arraySize > 0 && HasEmbeddedMaterials()) - { - // we're generating materials inside the prefab - materialHelp = Styles.InternalMaterialHelp.text; - } - } - - if (targets.Length == 1 && m_Materials.arraySize > 0 && m_MaterialLocation.intValue != 0) - { - materialHelp += " " + Styles.MaterialAssignmentsHelp.text; - } - - // display the extract buttons - if (m_MaterialLocation.intValue != 0 && !m_MaterialLocation.hasMultipleDifferentValues) - { - ExtractTexturesGUI(); - if (ExtractMaterialsGUI()) - return; - } - } - else - { - // we're not importing materials - materialHelp = Styles.NoMaterialHelp.text; - } - } - - if (!string.IsNullOrEmpty(materialHelp)) - { - EditorGUILayout.HelpBox(materialHelp, MessageType.Info); - } - - if ((targets.Length == 1 || m_SupportsEmbeddedMaterials.hasMultipleDifferentValues == false) && m_SupportsEmbeddedMaterials.boolValue == false - && m_MaterialLocation.intValue != 0 && !m_MaterialLocation.hasMultipleDifferentValues) - { - EditorGUILayout.Space(); - EditorGUILayout.HelpBox(Styles.NoMaterialMappingsHelp.text, MessageType.Warning); - } - - // hidden for multi-selection - if (m_ImportMaterials.boolValue && targets.Length == 1 && m_Materials.arraySize > 0 && m_MaterialLocation.intValue != 0 && !m_MaterialLocation.hasMultipleDifferentValues) - { - GUILayout.Label(Styles.ExternalMaterialMappings, EditorStyles.boldLabel); - - if (MaterialRemapOptons()) - return; - - // The list of material names is immutable, whereas the map of external objects can change based on user actions. - // For each material name, map the external object associated with it. - // 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 - for (int materialIdx = 0; materialIdx < m_Materials.arraySize; ++materialIdx) - { - var id = m_Materials.GetArrayElementAtIndex(materialIdx); - var name = id.FindPropertyRelative("name").stringValue; - var type = id.FindPropertyRelative("type").stringValue; - var assembly = id.FindPropertyRelative("assembly").stringValue; - - SerializedProperty materialProp = null; - Material material = null; - var propertyIdx = 0; - - for (int externalObjectIdx = 0, count = m_ExternalObjects.arraySize; externalObjectIdx < count; ++externalObjectIdx) - { - var pair = m_ExternalObjects.GetArrayElementAtIndex(externalObjectIdx); - var externalName = pair.FindPropertyRelative("first.name").stringValue; - var externalType = pair.FindPropertyRelative("first.type").stringValue; - - if (externalName == name && externalType == type) - { - materialProp = pair.FindPropertyRelative("second"); - material = materialProp != null ? materialProp.objectReferenceValue as Material : null; - propertyIdx = externalObjectIdx; - break; - } - } - - GUIContent nameLabel = EditorGUIUtility.TextContent(name); - nameLabel.tooltip = name; - if (materialProp != null) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.ObjectField(materialProp, typeof(Material), nameLabel); - if (EditorGUI.EndChangeCheck()) - { - if (materialProp.objectReferenceValue == null) - { - m_ExternalObjects.DeleteArrayElementAtIndex(propertyIdx); - } - } - } - else - { - EditorGUI.BeginChangeCheck(); - material = EditorGUILayout.ObjectField(nameLabel, material, typeof(Material), false) as Material; - if (EditorGUI.EndChangeCheck()) - { - if (material != null) - { - var newIndex = m_ExternalObjects.arraySize++; - var pair = m_ExternalObjects.GetArrayElementAtIndex(newIndex); - pair.FindPropertyRelative("first.name").stringValue = name; - pair.FindPropertyRelative("first.type").stringValue = type; - pair.FindPropertyRelative("first.assembly").stringValue = assembly; - pair.FindPropertyRelative("second").objectReferenceValue = material; - } - } - } - } - } - } - } -} diff --git a/Editor/Mono/ImportSettings/ModelImporterModelEditor.cs b/Editor/Mono/ImportSettings/ModelImporterModelEditor.cs deleted file mode 100644 index df6f42cbce..0000000000 --- a/Editor/Mono/ImportSettings/ModelImporterModelEditor.cs +++ /dev/null @@ -1,367 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using UnityEditor.Experimental.AssetImporters; - -namespace UnityEditor -{ - internal class ModelImporterModelEditor : BaseAssetImporterTabUI - { - bool m_SecondaryUVAdvancedOptions = false; - - // Model - SerializedProperty m_GlobalScale; - SerializedProperty m_UseFileScale; - SerializedProperty m_FileScale; - SerializedProperty m_MeshCompression; - SerializedProperty m_ImportBlendShapes; - SerializedProperty m_AddColliders; - SerializedProperty m_SwapUVChannels; - SerializedProperty m_GenerateSecondaryUV; - SerializedProperty m_SecondaryUVAngleDistortion; - SerializedProperty m_SecondaryUVAreaDistortion; - SerializedProperty m_SecondaryUVHardAngle; - SerializedProperty m_SecondaryUVPackMargin; - SerializedProperty m_NormalSmoothAngle; - SerializedProperty m_NormalImportMode; - SerializedProperty m_NormalCalculationMode; - SerializedProperty m_TangentImportMode; - SerializedProperty m_OptimizeMeshForGPU; - SerializedProperty m_IsReadable; - SerializedProperty m_KeepQuads; - SerializedProperty m_IndexFormat; - SerializedProperty m_WeldVertices; - SerializedProperty m_ImportCameras; - SerializedProperty m_ImportLights; - SerializedProperty m_ImportVisibility; - SerializedProperty m_PreserveHierarchy; - - public ModelImporterModelEditor(AssetImporterEditor panelContainer) - : base(panelContainer) - { - } - - internal override void OnEnable() - { - // Model - m_GlobalScale = serializedObject.FindProperty("m_GlobalScale"); - m_UseFileScale = serializedObject.FindProperty("m_UseFileScale"); - m_FileScale = serializedObject.FindProperty("m_FileScale"); - m_MeshCompression = serializedObject.FindProperty("m_MeshCompression"); - m_ImportBlendShapes = serializedObject.FindProperty("m_ImportBlendShapes"); - m_ImportCameras = serializedObject.FindProperty("m_ImportCameras"); - m_ImportLights = serializedObject.FindProperty("m_ImportLights"); - m_AddColliders = serializedObject.FindProperty("m_AddColliders"); - m_SwapUVChannels = serializedObject.FindProperty("swapUVChannels"); - m_GenerateSecondaryUV = serializedObject.FindProperty("generateSecondaryUV"); - m_SecondaryUVAngleDistortion = serializedObject.FindProperty("secondaryUVAngleDistortion"); - m_SecondaryUVAreaDistortion = serializedObject.FindProperty("secondaryUVAreaDistortion"); - m_SecondaryUVHardAngle = serializedObject.FindProperty("secondaryUVHardAngle"); - m_SecondaryUVPackMargin = serializedObject.FindProperty("secondaryUVPackMargin"); - m_NormalSmoothAngle = serializedObject.FindProperty("normalSmoothAngle"); - m_NormalImportMode = serializedObject.FindProperty("normalImportMode"); - m_NormalCalculationMode = serializedObject.FindProperty("normalCalculationMode"); - m_TangentImportMode = serializedObject.FindProperty("tangentImportMode"); - m_OptimizeMeshForGPU = serializedObject.FindProperty("optimizeMeshForGPU"); - m_IsReadable = serializedObject.FindProperty("m_IsReadable"); - m_KeepQuads = serializedObject.FindProperty("keepQuads"); - m_IndexFormat = serializedObject.FindProperty("indexFormat"); - m_WeldVertices = serializedObject.FindProperty("weldVertices"); - m_ImportVisibility = serializedObject.FindProperty("m_ImportVisibility"); - m_PreserveHierarchy = serializedObject.FindProperty("m_PreserveHierarchy"); - } - - internal override void PreApply() - { - ScaleAvatar(); - } - - class Styles - { - public GUIContent Meshes = EditorGUIUtility.TrTextContent("Meshes", "These options control how geometry is imported."); - public GUIContent ScaleFactor = EditorGUIUtility.TrTextContent("Scale Factor", "How much to scale the models compared to what is in the source file."); - public GUIContent UseFileUnits = EditorGUIUtility.TrTextContent("Use File Units", "Detect file units and import as 1FileUnit=1UnityUnit, otherwise it will import as 1cm=1UnityUnit. See ModelImporter.useFileUnits for more details."); - public GUIContent UseFileScale = EditorGUIUtility.TrTextContent("Use File Scale", "Use File Scale when importing."); - public GUIContent FileScaleFactor = EditorGUIUtility.TrTextContent("File Scale", "Scale defined by source file, or 1 if Use File Scale is disabled. Click Apply to update."); - public GUIContent ImportBlendShapes = EditorGUIUtility.TrTextContent("Import BlendShapes", "Should Unity import BlendShapes."); - public GUIContent GenerateColliders = EditorGUIUtility.TrTextContent("Generate Colliders", "Should Unity generate mesh colliders for all meshes."); - public GUIContent SwapUVChannels = EditorGUIUtility.TrTextContent("Swap UVs", "Swaps the 2 UV channels in meshes. Use if your diffuse texture uses UVs from the lightmap."); - - public GUIContent GenerateSecondaryUV = EditorGUIUtility.TrTextContent("Generate Lightmap UVs", "Generate lightmap UVs into UV2."); - public GUIContent GenerateSecondaryUVAdvanced = EditorGUIUtility.TrTextContent("Advanced"); - public GUIContent secondaryUVAngleDistortion = EditorGUIUtility.TrTextContent("Angle Error", "Measured in percents. Angle error measures deviation of UV angles from geometry angles. Area error measures deviation of UV triangles area from geometry triangles if they were uniformly scaled."); - public GUIContent secondaryUVAreaDistortion = EditorGUIUtility.TrTextContent("Area Error"); - public GUIContent secondaryUVHardAngle = EditorGUIUtility.TrTextContent("Hard Angle", "Angle between neighbor triangles that will generate seam."); - public GUIContent secondaryUVPackMargin = EditorGUIUtility.TrTextContent("Pack Margin", "Measured in pixels, assuming mesh will cover an entire 1024x1024 lightmap."); - public GUIContent secondaryUVDefaults = EditorGUIUtility.TrTextContent("Set Defaults"); - - public GUIContent TangentSpace = EditorGUIUtility.TrTextContent("Normals & Tangents"); - public GUIContent TangentSpaceNormalLabel = EditorGUIUtility.TrTextContent("Normals"); - public GUIContent TangentSpaceTangentLabel = EditorGUIUtility.TrTextContent("Tangents"); - - public GUIContent TangentSpaceOptionImport = EditorGUIUtility.TrTextContent("Import"); - public GUIContent TangentSpaceOptionCalculateLegacy = EditorGUIUtility.TrTextContent("Calculate Legacy"); - public GUIContent TangentSpaceOptionCalculateLegacySplit = EditorGUIUtility.TrTextContent("Calculate Legacy - Split Tangents"); - public GUIContent TangentSpaceOptionCalculate = EditorGUIUtility.TrTextContent("Calculate Tangent Space"); - public GUIContent TangentSpaceOptionNone = EditorGUIUtility.TrTextContent("None"); - public GUIContent TangentSpaceOptionNoneNoNormals = EditorGUIUtility.TrTextContent("None - (Normals required)"); - - public GUIContent NormalOptionImport = EditorGUIUtility.TrTextContent("Import"); - public GUIContent NormalOptionCalculate = EditorGUIUtility.TrTextContent("Calculate"); - public GUIContent NormalOptionNone = EditorGUIUtility.TrTextContent("None"); - - public GUIContent RecalculateNormalsLabel = EditorGUIUtility.TrTextContent("Normals Mode"); - public GUIContent[] RecalculateNormalsOpt = - { - EditorGUIUtility.TrTextContent("Unweighted Legacy"), - EditorGUIUtility.TrTextContent("Unweighted"), - EditorGUIUtility.TrTextContent("Area Weighted"), - EditorGUIUtility.TrTextContent("Angle Weighted"), - EditorGUIUtility.TrTextContent("Area and Angle Weighted") - }; - - public GUIContent[] TangentSpaceModeOptLabelsAll; - public GUIContent[] TangentSpaceModeOptLabelsCalculate; - public GUIContent[] TangentSpaceModeOptLabelsNone; - - public GUIContent[] NormalModeLabelsAll; - - - public ModelImporterTangents[] TangentSpaceModeOptEnumsAll; - public ModelImporterTangents[] TangentSpaceModeOptEnumsCalculate; - public ModelImporterTangents[] TangentSpaceModeOptEnumsNone; - - public GUIContent SmoothingAngle = EditorGUIUtility.TrTextContent("Smoothing Angle", "Normal Smoothing Angle"); - - public GUIContent MeshCompressionLabel = EditorGUIUtility.TrTextContent("Mesh Compression" , "Higher compression ratio means lower mesh precision. If enabled, the mesh bounds and a lower bit depth per component are used to compress the mesh data."); - public GUIContent[] MeshCompressionOpt = - { - EditorGUIUtility.TrTextContent("Off"), - EditorGUIUtility.TrTextContent("Low"), - EditorGUIUtility.TrTextContent("Medium"), - EditorGUIUtility.TrTextContent("High") - }; - - public GUIContent IndexFormatLabel = EditorGUIUtility.TrTextContent("Index Format", "Format of mesh index buffer. Auto mode picks 16 or 32 bit depending on mesh vertex count."); - public GUIContent[] IndexFormatOpt = - { - EditorGUIUtility.TrTextContent("Auto"), - EditorGUIUtility.TrTextContent("16 bit"), - EditorGUIUtility.TrTextContent("32 bit") - }; - - public GUIContent OptimizeMeshForGPU = EditorGUIUtility.TrTextContent("Optimize Mesh", "The vertices and indices will be reordered for better GPU performance."); - public GUIContent KeepQuads = EditorGUIUtility.TrTextContent("Keep Quads", "If model contains quad faces, they are kept for DX11 tessellation."); - public GUIContent WeldVertices = EditorGUIUtility.TrTextContent("Weld Vertices", "Combine vertices that share the same position in space."); - public GUIContent ImportVisibility = EditorGUIUtility.TrTextContent("Import Visibility", "Use visibility properties to enable or disable MeshRenderer components."); - public GUIContent ImportCameras = EditorGUIUtility.TrTextContent("Import Cameras"); - public GUIContent ImportLights = EditorGUIUtility.TrTextContent("Import Lights"); - public GUIContent PreserveHierarchy = EditorGUIUtility.TrTextContent("Preserve Hierarchy", "Always create an explicit prefab root, even if the model only has a single root."); - public GUIContent IsReadable = EditorGUIUtility.TrTextContent("Read/Write Enabled", "Allow vertices and indices to be accessed from script."); - - public Styles() - { - NormalModeLabelsAll = new GUIContent[] {NormalOptionImport, NormalOptionCalculate, NormalOptionNone}; - - TangentSpaceModeOptLabelsAll = new GUIContent[] {TangentSpaceOptionImport, TangentSpaceOptionCalculate, TangentSpaceOptionCalculateLegacy, TangentSpaceOptionCalculateLegacySplit, TangentSpaceOptionNone}; - TangentSpaceModeOptLabelsCalculate = new GUIContent[] {TangentSpaceOptionCalculate, TangentSpaceOptionCalculateLegacy, TangentSpaceOptionCalculateLegacySplit, TangentSpaceOptionNone}; - TangentSpaceModeOptLabelsNone = new GUIContent[] {TangentSpaceOptionNoneNoNormals}; - - TangentSpaceModeOptEnumsAll = new ModelImporterTangents[] { ModelImporterTangents.Import, ModelImporterTangents.CalculateMikk, ModelImporterTangents.CalculateLegacy, ModelImporterTangents.CalculateLegacyWithSplitTangents, ModelImporterTangents.None }; - TangentSpaceModeOptEnumsCalculate = new ModelImporterTangents[] { ModelImporterTangents.CalculateMikk, ModelImporterTangents.CalculateLegacy, ModelImporterTangents.CalculateLegacyWithSplitTangents, ModelImporterTangents.None }; - TangentSpaceModeOptEnumsNone = new ModelImporterTangents[] { ModelImporterTangents.None }; - } - } - - static Styles styles; - - public override void OnInspectorGUI() - { - // Material modes - if (styles == null) - styles = new Styles(); - - MeshesGUI(); - NormalsAndTangentsGUI(); - } - - void MeshesGUI() - { - GUILayout.Label(styles.Meshes, EditorStyles.boldLabel); - - using (new EditorGUI.DisabledScope(targets.Length > 1)) - { - // Global scale aka User scale - EditorGUILayout.PropertyField(m_GlobalScale, styles.ScaleFactor); - } - - // File Scale Factor - EditorGUILayout.PropertyField(m_UseFileScale, styles.UseFileScale); - if (m_UseFileScale.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_FileScale, styles.FileScaleFactor); - EditorGUI.indentLevel--; - } - - // mesh compression - EditorGUILayout.Popup(m_MeshCompression, styles.MeshCompressionOpt, styles.MeshCompressionLabel); - - EditorGUILayout.PropertyField(m_IsReadable, styles.IsReadable); - EditorGUILayout.PropertyField(m_OptimizeMeshForGPU, styles.OptimizeMeshForGPU); - - // Import BlendShapes - EditorGUILayout.PropertyField(m_ImportBlendShapes, styles.ImportBlendShapes); - - // Add Collider - EditorGUILayout.PropertyField(m_AddColliders, styles.GenerateColliders); - - // Keep Quads - EditorGUILayout.PropertyField(m_KeepQuads, styles.KeepQuads); - - EditorGUILayout.Popup(m_IndexFormat, styles.IndexFormatOpt, styles.IndexFormatLabel); - - // Weld Vertices - EditorGUILayout.PropertyField(m_WeldVertices, styles.WeldVertices); - - // Import visibility - EditorGUILayout.PropertyField(m_ImportVisibility, styles.ImportVisibility); - - // Import Cameras - EditorGUILayout.PropertyField(m_ImportCameras, styles.ImportCameras); - - // Import Lights - EditorGUILayout.PropertyField(m_ImportLights, styles.ImportLights); - - // Preserve Hierarchy - EditorGUILayout.PropertyField(m_PreserveHierarchy, styles.PreserveHierarchy); - - // Swap uv channel - EditorGUILayout.PropertyField(m_SwapUVChannels, styles.SwapUVChannels); - - // Secondary UV generation - EditorGUILayout.PropertyField(m_GenerateSecondaryUV, styles.GenerateSecondaryUV); - if (m_GenerateSecondaryUV.boolValue) - { - EditorGUI.indentLevel++; - m_SecondaryUVAdvancedOptions = EditorGUILayout.Foldout(m_SecondaryUVAdvancedOptions, styles.GenerateSecondaryUVAdvanced, true, EditorStyles.foldout); - if (m_SecondaryUVAdvancedOptions) - { - // TODO: all slider min/max values should be revisited - EditorGUI.BeginChangeCheck(); - EditorGUILayout.Slider(m_SecondaryUVHardAngle, 0, 180, styles.secondaryUVHardAngle); - EditorGUILayout.Slider(m_SecondaryUVPackMargin, 1, 64, styles.secondaryUVPackMargin); - EditorGUILayout.Slider(m_SecondaryUVAngleDistortion, 1, 75, styles.secondaryUVAngleDistortion); - EditorGUILayout.Slider(m_SecondaryUVAreaDistortion, 1, 75, styles.secondaryUVAreaDistortion); - if (EditorGUI.EndChangeCheck()) - { - m_SecondaryUVHardAngle.floatValue = Mathf.Round(m_SecondaryUVHardAngle.floatValue); - m_SecondaryUVPackMargin.floatValue = Mathf.Round(m_SecondaryUVPackMargin.floatValue); - m_SecondaryUVAngleDistortion.floatValue = Mathf.Round(m_SecondaryUVAngleDistortion.floatValue); - m_SecondaryUVAreaDistortion.floatValue = Mathf.Round(m_SecondaryUVAreaDistortion.floatValue); - } - } - EditorGUI.indentLevel--; - } - } - - void NormalsAndTangentsGUI() - { - // Tangent space - GUILayout.Label(styles.TangentSpace, EditorStyles.boldLabel); - - bool isTangentImportSupported = true; - foreach (ModelImporter importer in targets) - if (!importer.isTangentImportSupported) - isTangentImportSupported = false; - - // TODO : check if normal import is supported! - //normalImportMode = styles.TangentSpaceModeOptEnumsAll[EditorGUILayout.Popup(styles.TangentSpaceNormalLabel, (int)normalImportMode, styles.TangentSpaceModeOptLabelsAll)]; - EditorGUI.BeginChangeCheck(); - EditorGUILayout.Popup(m_NormalImportMode, styles.NormalModeLabelsAll, styles.TangentSpaceNormalLabel); - if (EditorGUI.EndChangeCheck()) - { - // Let the tangent mode follow the normal mode - that's a sane default and it's needed - // because the tangent mode value can't be lower than the normal mode. - // We make the tangent mode follow in BOTH directions for consistency - // - so that if you change the normal mode one way and then back, the tangent mode will also go back again. - - if (m_NormalImportMode.intValue == (int)ModelImporterNormals.None) - m_TangentImportMode.intValue = (int)ModelImporterTangents.None; - else if (m_NormalImportMode.intValue == (int)ModelImporterNormals.Import && isTangentImportSupported) - m_TangentImportMode.intValue = (int)ModelImporterTangents.Import; - else - m_TangentImportMode.intValue = (int)ModelImporterTangents.CalculateMikk; - } - - // Normal split angle - using (new EditorGUI.DisabledScope(m_NormalImportMode.intValue != (int)ModelImporterNormals.Calculate)) - { - // Normal calculation mode - EditorGUILayout.Popup(m_NormalCalculationMode, styles.RecalculateNormalsOpt, styles.RecalculateNormalsLabel); - - EditorGUI.BeginChangeCheck(); - EditorGUILayout.Slider(m_NormalSmoothAngle, 0, 180, styles.SmoothingAngle); - // Property is serialized as float but we want to show it as an int so we round the value when changed - if (EditorGUI.EndChangeCheck()) - m_NormalSmoothAngle.floatValue = Mathf.Round(m_NormalSmoothAngle.floatValue); - } - - // Choose the option values and labels based on what the NormalImportMode is - GUIContent[] tangentImportModeOptLabels = styles.TangentSpaceModeOptLabelsAll; - ModelImporterTangents[] tangentImportModeOptEnums = styles.TangentSpaceModeOptEnumsAll; - if (m_NormalImportMode.intValue == (int)ModelImporterNormals.Calculate || !isTangentImportSupported) - { - tangentImportModeOptLabels = styles.TangentSpaceModeOptLabelsCalculate; - tangentImportModeOptEnums = styles.TangentSpaceModeOptEnumsCalculate; - } - else if (m_NormalImportMode.intValue == (int)ModelImporterNormals.None) - { - tangentImportModeOptLabels = styles.TangentSpaceModeOptLabelsNone; - tangentImportModeOptEnums = styles.TangentSpaceModeOptEnumsNone; - } - - using (new EditorGUI.DisabledScope(m_NormalImportMode.intValue == (int)ModelImporterNormals.None)) - { - int tangentOption = Array.IndexOf(tangentImportModeOptEnums, (ModelImporterTangents)m_TangentImportMode.intValue); - EditorGUI.BeginChangeCheck(); - tangentOption = EditorGUILayout.Popup(styles.TangentSpaceTangentLabel, tangentOption, tangentImportModeOptLabels); - if (EditorGUI.EndChangeCheck()) - m_TangentImportMode.intValue = (int)tangentImportModeOptEnums[tangentOption]; - } - } - - private void ScaleAvatar() - { - //You can't scale multiple - if (m_GlobalScale.hasMultipleDifferentValues) - return; - - if (targets.Length != 1) - return; - - foreach (object o in targets) - { - float prevScale = (o as ModelImporter).globalScale; - float currentScale = m_GlobalScale.floatValue; - - if (prevScale != currentScale && currentScale != 0 && prevScale != 0) - { - float scaleFactor = currentScale / prevScale; - SerializedProperty skeletonBoneArray = serializedObject.FindProperty(AvatarSetupTool.sSkeleton); - for (int i = 0; i < skeletonBoneArray.arraySize; ++i) - { - SerializedProperty bone = skeletonBoneArray.GetArrayElementAtIndex(i); - bone.FindPropertyRelative(AvatarSetupTool.sPosition).vector3Value = - bone.FindPropertyRelative(AvatarSetupTool.sPosition).vector3Value * scaleFactor; - } - } - } - } - } -} diff --git a/Editor/Mono/ImportSettings/ModelImporterRigEditor.cs b/Editor/Mono/ImportSettings/ModelImporterRigEditor.cs deleted file mode 100644 index 292180ea3c..0000000000 --- a/Editor/Mono/ImportSettings/ModelImporterRigEditor.cs +++ /dev/null @@ -1,770 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor.SceneManagement; -using UnityEditorInternal; -using System.Collections.Generic; -using Object = UnityEngine.Object; -using System.IO; -using UnityEditor.Experimental.AssetImporters; - -namespace UnityEditor -{ - internal class ModelImporterRigEditor : BaseAssetImporterTabUI - { - const float kDeleteWidth = 17; - - ModelImporter singleImporter { get { return targets[0] as ModelImporter; } } - - public int m_SelectedClipIndex = -1; - - Avatar m_Avatar; - - SerializedProperty m_OptimizeGameObjects; - SerializedProperty m_AnimationType; - SerializedProperty m_AvatarSource; - SerializedProperty m_CopyAvatar; - SerializedProperty m_LegacyGenerateAnimations; - SerializedProperty m_AnimationCompression; - - SerializedProperty m_RootMotionBoneName; - SerializedProperty m_RootMotionBoneRotation; - - SerializedProperty m_SrcHasExtraRoot; - SerializedProperty m_DstHasExtraRoot; - - SerializedProperty m_RigImportErrors; - SerializedProperty m_RigImportWarnings; - - private static bool importMessageFoldout = false; - - GUIContent[] m_RootMotionBoneList; - - private ExposeTransformEditor m_ExposeTransformEditor; - - private ModelImporterAnimationType animationType - { - get { return (ModelImporterAnimationType)m_AnimationType.intValue; } - set { m_AnimationType.intValue = (int)value; } - } - - bool m_AvatarCopyIsUpToDate; - private bool m_CanMultiEditTransformList; - - public int rootIndex { get; set; } - - bool m_IsBiped = false; - List m_BipedMappingReport = null; - - private MappingRelevantSettings[] oldModelSettings = null; - private MappingRelevantSettings[] newModelSettings = null; - - private class Styles - { - public GUIContent AnimationType = EditorGUIUtility.TrTextContent("Animation Type", "The type of animation to support / import."); - public GUIContent[] AnimationTypeOpt = - { - EditorGUIUtility.TrTextContent("None", "No animation present."), - EditorGUIUtility.TrTextContent("Legacy", "Legacy animation system."), - EditorGUIUtility.TrTextContent("Generic", "Generic Mecanim animation."), - EditorGUIUtility.TrTextContent("Humanoid", "Humanoid Mecanim animation system.") - }; - - public GUIContent AnimLabel = EditorGUIUtility.TrTextContent("Generation", "Controls how animations are imported."); - public GUIContent[] AnimationsOpt = - { - EditorGUIUtility.TrTextContent("Don't Import", "No animation or skinning is imported."), - EditorGUIUtility.TrTextContent("Store in Original Roots (Deprecated)", "Animations are stored in the root objects of your animation package (these might be different from the root objects in Unity)."), - EditorGUIUtility.TrTextContent("Store in Nodes (Deprecated)", "Animations are stored together with the objects they animate. Use this when you have a complex animation setup and want full scripting control."), - EditorGUIUtility.TrTextContent("Store in Root (Deprecated)", "Animations are stored in the scene's transform root objects. Use this when animating anything that has a hierarchy."), - EditorGUIUtility.TrTextContent("Store in Root (New)") - }; - public GUIStyle helpText = new GUIStyle(EditorStyles.helpBox); - - public GUIContent avatar = EditorGUIUtility.TrTextContent("Animator"); - public GUIContent configureAvatar = EditorGUIUtility.TrTextContent("Configure..."); - public GUIContent avatarValid = EditorGUIUtility.TrTextContent("\u2713"); - public GUIContent avatarInvalid = EditorGUIUtility.TrTextContent("\u2715"); - public GUIContent avatarPending = EditorGUIUtility.TrTextContent("..."); - - - public GUIContent UpdateMuscleDefinitionFromSource = EditorGUIUtility.TrTextContent("Update", "Update the copy of the muscle definition from the source."); - public GUIContent RootNode = EditorGUIUtility.TrTextContent("Root node", "Specify the root node used to extract the animation translation."); - - public GUIContent AvatarDefinition = EditorGUIUtility.TrTextContent("Avatar Definition", "Choose between Create From This Model or Copy From Other Avatar. The first one create an Avatar for this file and the second one use an Avatar from another file to import animation."); - - public GUIContent[] AvatarDefinitionOpt = - { - EditorGUIUtility.TrTextContent("Create From This Model", "Create an Avatar based on the model from this file."), - EditorGUIUtility.TrTextContent("Copy From Other Avatar", "Copy an Avatar from another file to import muscle clip. No avatar will be created.") - }; - - public GUIContent UpdateReferenceClips = EditorGUIUtility.TrTextContent("Update reference clips", "Click on this button to update all the @convention file referencing this file. Should set all these files to Copy From Other Avatar, set the source Avatar to this one and reimport all these files."); - - public GUIContent ImportMessages = EditorGUIUtility.TrTextContent("Import Messages"); - - public Styles() - { - helpText.normal.background = null; - helpText.alignment = TextAnchor.MiddleLeft; - helpText.padding = new RectOffset(0, 0, 0, 0); - } - } - static Styles styles; - - public ModelImporterRigEditor(AssetImporterEditor panelContainer) - : base(panelContainer) - {} - - internal override void OnEnable() - { - m_AnimationType = serializedObject.FindProperty("m_AnimationType"); - m_AvatarSource = serializedObject.FindProperty("m_LastHumanDescriptionAvatarSource"); - m_OptimizeGameObjects = serializedObject.FindProperty("m_OptimizeGameObjects"); - - // Generic bone setup - m_RootMotionBoneName = serializedObject.FindProperty("m_HumanDescription.m_RootMotionBoneName"); - m_RootMotionBoneRotation = serializedObject.FindProperty("m_HumanDescription.m_RootMotionBoneRotation"); - - m_ExposeTransformEditor = new ExposeTransformEditor(); - - string[] transformPaths = singleImporter.transformPaths; - m_RootMotionBoneList = new GUIContent[transformPaths.Length]; - for (int i = 0; i < transformPaths.Length; i++) - m_RootMotionBoneList[i] = new GUIContent(transformPaths[i]); - - if (m_RootMotionBoneList.Length > 0) - m_RootMotionBoneList[0] = EditorGUIUtility.TrTextContent("None"); - - rootIndex = ArrayUtility.FindIndex(m_RootMotionBoneList, delegate(GUIContent content) { return FileUtil.GetLastPathNameComponent(content.text) == m_RootMotionBoneName.stringValue; }); - rootIndex = rootIndex < 1 ? 0 : rootIndex; - - m_SrcHasExtraRoot = serializedObject.FindProperty("m_HasExtraRoot"); - m_DstHasExtraRoot = serializedObject.FindProperty("m_HumanDescription.m_HasExtraRoot"); - - // Animation - m_CopyAvatar = serializedObject.FindProperty("m_CopyAvatar"); - m_LegacyGenerateAnimations = serializedObject.FindProperty("m_LegacyGenerateAnimations"); - m_AnimationCompression = serializedObject.FindProperty("m_AnimationCompression"); - - m_RigImportErrors = serializedObject.FindProperty("m_RigImportErrors"); - m_RigImportWarnings = serializedObject.FindProperty("m_RigImportWarnings"); - - m_ExposeTransformEditor.OnEnable(singleImporter.transformPaths, serializedObject); - - m_CanMultiEditTransformList = CanMultiEditTransformList(); - - // Check if avatar definition is same as the one it's copied from - CheckIfAvatarCopyIsUpToDate(); - - m_IsBiped = false; - m_BipedMappingReport = new List(); - - if (m_AnimationType.intValue == (int)ModelImporterAnimationType.Human) - { - GameObject go = assetTarget as GameObject; - if (go != null) - { - m_IsBiped = AvatarBipedMapper.IsBiped(go.transform, m_BipedMappingReport); - } - - if (m_Avatar == null) - { - ResetAvatar(); - } - } - } - - private bool CanMultiEditTransformList() - { - string[] transformPaths = singleImporter.transformPaths; - for (int i = 1; i < targets.Length; ++i) - { - ModelImporter modelImporter = targets[i] as ModelImporter; - if (!ArrayUtility.ArrayEquals(transformPaths, modelImporter.transformPaths)) - return false; - } - - return true; - } - - void CheckIfAvatarCopyIsUpToDate() - { - if (!(animationType == ModelImporterAnimationType.Human || animationType == ModelImporterAnimationType.Generic) || m_AvatarSource.objectReferenceValue == null) - { - m_AvatarCopyIsUpToDate = true; - return; - } - - // Get SerializedObject of this importer and the importer of the source avatar - string path = AssetDatabase.GetAssetPath(m_AvatarSource.objectReferenceValue); - ModelImporter sourceImporter = AssetImporter.GetAtPath(path) as ModelImporter; - - m_AvatarCopyIsUpToDate = DoesHumanDescriptionMatch(singleImporter, sourceImporter); - } - - internal override void OnDestroy() - { - m_Avatar = null; - } - - internal override void ResetValues() - { - base.ResetValues(); - ResetAvatar(); - } - - void ResetAvatar() - { - if (assetTarget != null) - { - var path = singleImporter.assetPath; - m_Avatar = AssetDatabase.LoadAssetAtPath(path); - } - } - - void LegacyGUI() - { - EditorGUILayout.Popup(m_LegacyGenerateAnimations, styles.AnimationsOpt, styles.AnimLabel); - // Show warning and fix button for deprecated import formats - if (m_LegacyGenerateAnimations.intValue == 1 || m_LegacyGenerateAnimations.intValue == 2 || m_LegacyGenerateAnimations.intValue == 3) - EditorGUILayout.HelpBox("The animation import setting \"" + styles.AnimationsOpt[m_LegacyGenerateAnimations.intValue].text + "\" is deprecated.", MessageType.Warning); - } - - // Show copy avatar bool as a dropdown - void AvatarSourceGUI() - { - EditorGUI.BeginChangeCheck(); - int copyValue = m_CopyAvatar.boolValue ? 1 : 0; - EditorGUI.showMixedValue = m_CopyAvatar.hasMultipleDifferentValues; - copyValue = EditorGUILayout.Popup(styles.AvatarDefinition, copyValue, styles.AvatarDefinitionOpt); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - m_CopyAvatar.boolValue = (copyValue == 1); - } - - void GenericGUI() - { - AvatarSourceGUI(); - - if (!m_CopyAvatar.hasMultipleDifferentValues) - { - if (!m_CopyAvatar.boolValue) - { - // Do not allow multi edit of root node if all rigs doesn't match - EditorGUI.BeginChangeCheck(); - using (new EditorGUI.DisabledScope(!m_CanMultiEditTransformList)) - { - rootIndex = EditorGUILayout.Popup(styles.RootNode, rootIndex, m_RootMotionBoneList); - } - if (EditorGUI.EndChangeCheck()) - { - if (rootIndex > 0 && rootIndex < m_RootMotionBoneList.Length) - { - m_RootMotionBoneName.stringValue = - FileUtil.GetLastPathNameComponent(m_RootMotionBoneList[rootIndex].text); - } - else - { - m_RootMotionBoneName.stringValue = ""; - } - } - } - else - CopyAvatarGUI(); - } - } - - void HumanoidGUI() - { - AvatarSourceGUI(); - - if (!m_CopyAvatar.hasMultipleDifferentValues) - { - if (!m_CopyAvatar.boolValue) - ConfigureAvatarGUI(); - else - CopyAvatarGUI(); - } - - if (m_IsBiped) - { - if (m_BipedMappingReport.Count > 0) - { - string report = "A Biped was detected, but cannot be configured properly because of an unsupported hierarchy. Adjust Biped settings in 3DS Max before exporting to correct this problem.\n"; - - for (int reportIter = 0; reportIter < m_BipedMappingReport.Count; reportIter++) - { - report += m_BipedMappingReport[reportIter]; - } - - EditorGUILayout.HelpBox(report, MessageType.Warning); - } - else - { - EditorGUILayout.HelpBox("A Biped was detected. Default Biped mapping and T-Pose have been configured for this avatar. Translation DoFs have been activated. Use Configure to modify default Biped setup.", MessageType.Info); - } - } - - EditorGUILayout.Space(); - } - - void ConfigureAvatarGUI() - { - if (targets.Length > 1) - { - GUILayout.Label("Can't configure avatar in multi-editing mode", EditorStyles.helpBox); - return; - } - - if (singleImporter.transformPaths.Length <= HumanTrait.RequiredBoneCount) - { - GUILayout.Label(string.Format("Not enough bones to create human avatar (requires {0})", HumanTrait.RequiredBoneCount, EditorStyles.helpBox)); - } - - // Validation text - GUIContent validationContent; - if (m_Avatar && !HasModified()) - { - if (m_Avatar.isHuman) - validationContent = styles.avatarValid; - else - validationContent = styles.avatarInvalid; - } - else - { - validationContent = styles.avatarPending; - GUILayout.Label("The avatar can be configured after settings have been applied.", EditorStyles.helpBox); - } - - Rect r = EditorGUILayout.GetControlRect(); - const int buttonWidth = 75; - GUI.Label(new Rect(r.xMax - buttonWidth - 18, r.y, 18, r.height), validationContent, EditorStyles.label); - - // Configure button - using (new EditorGUI.DisabledScope(m_Avatar == null)) - { - if (GUI.Button(new Rect(r.xMax - buttonWidth, r.y + 1, buttonWidth, r.height - 1), styles.configureAvatar, EditorStyles.miniButton)) - { - if (!isLocked) - { - if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) - { - Selection.activeObject = m_Avatar; - AvatarEditor.s_EditImmediatelyOnNextOpen = true; - } - GUIUtility.ExitGUI(); - } - else - Debug.Log("Cannot configure avatar, inspector is locked"); - } - } - } - - void CheckAvatar(Avatar sourceAvatar) - { - if (sourceAvatar != null) - { - if (sourceAvatar.isHuman && (animationType != ModelImporterAnimationType.Human)) - { - if (EditorUtility.DisplayDialog("Asigning an Humanoid Avatar on a Generic Rig", - "Do you want to change Animation Type to Humanoid ?", "Yes", "No")) - { - animationType = ModelImporterAnimationType.Human; - } - else - { - m_AvatarSource.objectReferenceValue = null; - } - } - else if (!sourceAvatar.isHuman && (animationType != ModelImporterAnimationType.Generic)) - { - if (EditorUtility.DisplayDialog("Asigning an Generic Avatar on a Humanoid Rig", - "Do you want to change Animation Type to Generic ?", "Yes", "No")) - { - animationType = ModelImporterAnimationType.Generic; - } - else - { - m_AvatarSource.objectReferenceValue = null; - } - } - } - } - - void CopyAvatarGUI() - { - GUILayout.Label( - @"If you have already created an Avatar for another model with a rig identical to this one, you can copy its Avatar definition. -With this option, this model will not create any avatar but only import animations.", EditorStyles.helpBox); - - EditorGUILayout.BeginHorizontal(); - - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_AvatarSource, GUIContent.Temp("Source")); - var sourceAvatar = m_AvatarSource.objectReferenceValue as Avatar; - if (EditorGUI.EndChangeCheck()) - { - CheckAvatar(sourceAvatar); - - AvatarSetupTool.ClearAll(serializedObject); - - if (sourceAvatar != null) - CopyHumanDescriptionFromOtherModel(sourceAvatar); - - m_AvatarCopyIsUpToDate = true; - } - - if (sourceAvatar != null && !m_AvatarSource.hasMultipleDifferentValues && !m_AvatarCopyIsUpToDate) - { - if (GUILayout.Button(styles.UpdateMuscleDefinitionFromSource, EditorStyles.miniButton)) - { - AvatarSetupTool.ClearAll(serializedObject); - CopyHumanDescriptionFromOtherModel(sourceAvatar); - m_AvatarCopyIsUpToDate = true; - } - } - - EditorGUILayout.EndHorizontal(); - } - - void ShowUpdateReferenceClip() - { - if (targets.Length > 1 || m_CopyAvatar.boolValue || !m_Avatar || !m_Avatar.isValid) - return; - - string[] paths = new string[0]; - ModelImporter importer = target as ModelImporter; - if (importer.referencedClips.Length > 0) - { - foreach (string clipGUID in importer.referencedClips) - ArrayUtility.Add(ref paths, AssetDatabase.GUIDToAssetPath(clipGUID)); - } - - // Show only button if some clip reference this avatar. - if (paths.Length > 0 && GUILayout.Button(styles.UpdateReferenceClips, GUILayout.Width(150))) - { - foreach (string path in paths) - SetupReferencedClip(path); - - try - { - AssetDatabase.StartAssetEditing(); - foreach (string path in paths) - AssetDatabase.ImportAsset(path); - } - finally - { - AssetDatabase.StopAssetEditing(); - } - } - } - - public override void OnInspectorGUI() - { - if (styles == null) - styles = new Styles(); - - string errors = m_RigImportErrors.stringValue; - string warnings = m_RigImportWarnings.stringValue; - - if (errors.Length > 0) - { - EditorGUILayout.Space(); - EditorGUILayout.HelpBox("Error(s) found while importing rig in this animation file. Open \"Import Messages\" foldout below for more details", MessageType.Error); - } - else - { - if (warnings.Length > 0) - { - EditorGUILayout.Space(); - EditorGUILayout.HelpBox("Warning(s) found while importing rig in this animation file. Open \"Import Messages\" foldout below for more details", MessageType.Warning); - } - } - - - // Animation type - EditorGUI.BeginChangeCheck(); - EditorGUILayout.Popup(m_AnimationType, styles.AnimationTypeOpt, styles.AnimationType); - if (EditorGUI.EndChangeCheck()) - { - m_AvatarSource.objectReferenceValue = null; - - if (animationType == ModelImporterAnimationType.Legacy) - m_AnimationCompression.intValue = (int)ModelImporterAnimationCompression.KeyframeReduction; - else if (animationType == ModelImporterAnimationType.Generic || animationType == ModelImporterAnimationType.Human) - m_AnimationCompression.intValue = (int)ModelImporterAnimationCompression.Optimal; - - m_DstHasExtraRoot.boolValue = m_SrcHasExtraRoot.boolValue; - } - - EditorGUILayout.Space(); - - if (!m_AnimationType.hasMultipleDifferentValues) - { - // Show GUI depending on animation type - if (animationType == ModelImporterAnimationType.Human) - HumanoidGUI(); - else if (animationType == ModelImporterAnimationType.Generic) - GenericGUI(); - else if (animationType == ModelImporterAnimationType.Legacy) - LegacyGUI(); - } - - ShowUpdateReferenceClip(); - - bool canOptimizeGameObjects = true; - if (animationType != ModelImporterAnimationType.Human && animationType != ModelImporterAnimationType.Generic) - canOptimizeGameObjects = false; - if (m_CopyAvatar.boolValue == true) - // If you have already created an Avatar for another model with a rig identical to this one, you can copy its Avatar definition. - // With this option, this model will not create any avatar but only import animations. - canOptimizeGameObjects = false; - - if (canOptimizeGameObjects) - { - EditorGUILayout.PropertyField(m_OptimizeGameObjects); - if (m_OptimizeGameObjects.boolValue && - serializedObject.targetObjects.Length == 1) // SerializedProperty can't handle multiple string arrays properly. - { - EditorGUILayout.Space(); - - // Do not allow multi edit of exposed transform list if all rigs doesn't match - using (new EditorGUI.DisabledScope(!m_CanMultiEditTransformList)) - { - m_ExposeTransformEditor.OnGUI(); - } - } - } - - if (errors.Length > 0 || warnings.Length > 0) - { - EditorGUILayout.Space(); - - importMessageFoldout = EditorGUILayout.Foldout(importMessageFoldout, styles.ImportMessages, true); - - if (importMessageFoldout) - { - if (errors.Length > 0) - EditorGUILayout.HelpBox(errors, MessageType.None); - else if (warnings.Length > 0) - EditorGUILayout.HelpBox(warnings, MessageType.None); - } - } - } - - static SerializedObject GetModelImporterSerializedObject(string assetPath) - { - ModelImporter importer = AssetImporter.GetAtPath(assetPath) as ModelImporter; - if (importer == null) - return null; - - return new SerializedObject(importer); - } - - static bool DoesHumanDescriptionMatch(ModelImporter importer, ModelImporter otherImporter) - { - SerializedObject so = new SerializedObject(new Object[] { importer, otherImporter }); - - so.maxArraySizeForMultiEditing = Math.Max(importer.transformPaths.Length, otherImporter.transformPaths.Length); - SerializedProperty prop = so.FindProperty("m_HumanDescription"); - bool matches = !prop.hasMultipleDifferentValues; - - so.Dispose(); - - return matches; - } - - static void CopyHumanDescriptionToDestination(SerializedObject sourceObject, SerializedObject targetObject) - { - targetObject.CopyFromSerializedProperty(sourceObject.FindProperty("m_HumanDescription")); - } - - private void CopyHumanDescriptionFromOtherModel(Avatar sourceAvatar) - { - string srcAssetPath = AssetDatabase.GetAssetPath(sourceAvatar); - SerializedObject srcImporter = GetModelImporterSerializedObject(srcAssetPath); - - CopyHumanDescriptionToDestination(srcImporter, serializedObject); - srcImporter.Dispose(); - } - - private void SetupReferencedClip(string otherModelImporterPath) - { - SerializedObject targetImporter = GetModelImporterSerializedObject(otherModelImporterPath); - - // We may receive a path that doesn't have a importer. - if (targetImporter != null) - { - targetImporter.CopyFromSerializedProperty(serializedObject.FindProperty("m_AnimationType")); - - SerializedProperty copyAvatar = targetImporter.FindProperty("m_CopyAvatar"); - if (copyAvatar != null) - copyAvatar.boolValue = true; - - SerializedProperty avatar = targetImporter.FindProperty("m_LastHumanDescriptionAvatarSource"); - if (avatar != null) - avatar.objectReferenceValue = m_Avatar; - - CopyHumanDescriptionToDestination(serializedObject, targetImporter); - targetImporter.ApplyModifiedProperties(); - targetImporter.Dispose(); - } - } - - public bool isLocked - { - get - { - foreach (InspectorWindow i in InspectorWindow.GetAllInspectorWindows()) - { - ActiveEditorTracker activeEditor = i.tracker; - foreach (Editor e in activeEditor.activeEditors) - { - // the tab is no longer an editor, so we must always refer to the panel container - if (e is ModelImporterEditor && ((ModelImporterEditor)e).activeTab == this) - { - return i.isLocked; - } - } - } - return false; - } - } - - private struct MappingRelevantSettings - { - public bool humanoid; - public bool copyAvatar; - public bool hasNoAnimation; - public bool usesOwnAvatar { get { return humanoid && !copyAvatar; } } - } - - internal override void PreApply() - { - // Store the old mapping relevant settings for each model - // Note that we need to do this *before* applying the pending modified properties. - oldModelSettings = new MappingRelevantSettings[targets.Length]; - for (int i = 0; i < targets.Length; i++) - { - // Find settings of individual model (doesn't include unapplied settings, so we get the "old" settings) - SerializedObject so = new SerializedObject(targets[i]); - SerializedProperty animationType = so.FindProperty("m_AnimationType"); - SerializedProperty copyAvatar = so.FindProperty("m_CopyAvatar"); - oldModelSettings[i].humanoid = animationType.intValue == (int)ModelImporterAnimationType.Human; - oldModelSettings[i].hasNoAnimation = animationType.intValue == (int)ModelImporterAnimationType.None; - oldModelSettings[i].copyAvatar = copyAvatar.boolValue; - } - - // Store the new mapping relevant settings for each model - newModelSettings = new MappingRelevantSettings[targets.Length]; - Array.Copy(oldModelSettings, newModelSettings, targets.Length); - for (int i = 0; i < targets.Length; i++) - { - // If the settings have multiple values they can't have been changed, since that causes them to have the same value. - // So only copy value from SerializedProperty if it does not have multiple values. - if (!m_AnimationType.hasMultipleDifferentValues) - newModelSettings[i].humanoid = m_AnimationType.intValue == (int)ModelImporterAnimationType.Human; - if (!m_CopyAvatar.hasMultipleDifferentValues) - newModelSettings[i].copyAvatar = m_CopyAvatar.boolValue; - } - } - - internal override void PostApply() - { - // But we might not be done yet! - // For all models which did not have own humanoid before but should have it now, - // we need to perform auto-mapping. (For the opposite case we also need to clear the mapping.) - // Iterate through all the models... - for (int i = 0; i < targets.Length; i++) - { - // If this model had its own humanoid avatar before but shouldn't have it now... - if (oldModelSettings[i].usesOwnAvatar && !newModelSettings[i].usesOwnAvatar && !newModelSettings[i].copyAvatar) - { - // ...then clear auto-setup on this model. - SerializedObject so = new SerializedObject(targets[i]); - AvatarSetupTool.ClearAll(so); - so.ApplyModifiedPropertiesWithoutUndo(); - } - - if (!m_CopyAvatar.boolValue && !newModelSettings[i].humanoid && rootIndex > 0) - { - ModelImporter importer = targets[i] as ModelImporter; - - GameObject go = AssetDatabase.LoadMainAssetAtPath(importer.assetPath) as GameObject; - // The character could be optimized right now - // 'm_OptimizeGameObjects' can't be used to tell if it is optimized, because the user can change this value from UI, - // and the change hasn't been applied yet. - Animator animator = go.GetComponent(); - bool noTransformHierarchy = animator && !animator.hasTransformHierarchy; - if (noTransformHierarchy) - { - go = Instantiate(go) as GameObject; - AnimatorUtility.DeoptimizeTransformHierarchy(go); - } - - Transform rootMotionTransform = go.transform.Find(m_RootMotionBoneList[rootIndex].text); - - if (rootMotionTransform != null) - { - m_RootMotionBoneRotation.quaternionValue = rootMotionTransform.rotation; - } - - SerializedObject so = new SerializedObject(targets[i]); - so.ApplyModifiedPropertiesWithoutUndo(); - - if (noTransformHierarchy) - DestroyImmediate(go); - } - - // If this model should have its own humanoid avatar before and didn't have it before, - // then we need to perform auto-mapping. - if (!oldModelSettings[i].usesOwnAvatar && newModelSettings[i].usesOwnAvatar) - { - ModelImporter importer = targets[i] as ModelImporter; - // Special case if the model didn't have animation before... - if (oldModelSettings[i].hasNoAnimation && assetTargets[i] != null) - { - // We have to do an extra import first, before the automapping works. - // Because the model doesn't have any skinned meshes when it was last imported with - // Animation Mode: None. And the auro-mapping relies on information in the skinned meshes. - var targetAnimationType = importer.animationType; - importer.animationType = ModelImporterAnimationType.Generic; // we dont want to build humanoid here, since it will generate errors. - AssetDatabase.ImportAsset(importer.assetPath); - importer.animationType = targetAnimationType; - } - - // Perform auto-setup on this model. - SerializedObject so = new SerializedObject(targets[i]); - GameObject go = assetTargets[i] as GameObject; - // The character could be optimized right now - // 'm_OptimizeGameObjects' can't be used to tell if it is optimized, because the user can change this value from UI, - // and the change hasn't been applied yet. - if (go != null) - { - Animator animator = go.GetComponent(); - bool noTransformHierarchy = animator && !animator.hasTransformHierarchy; - if (noTransformHierarchy) - { - go = Instantiate(go) as GameObject; - AnimatorUtility.DeoptimizeTransformHierarchy(go); - } - AvatarSetupTool.AutoSetupOnInstance(go, so); - m_IsBiped = AvatarBipedMapper.IsBiped(go.transform, m_BipedMappingReport); - - if (noTransformHierarchy) - DestroyImmediate(go); - } - - so.ApplyModifiedPropertiesWithoutUndo(); - } - } - - oldModelSettings = null; - newModelSettings = null; - } - } -} diff --git a/Editor/Mono/ImportSettings/MovieImporterInspector.cs b/Editor/Mono/ImportSettings/MovieImporterInspector.cs deleted file mode 100644 index d6e1751c3f..0000000000 --- a/Editor/Mono/ImportSettings/MovieImporterInspector.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditor.Experimental.AssetImporters; - -namespace UnityEditor -{ - [CustomEditor(typeof(MovieImporter))] - internal class MovieImporterInspector : AssetImporterEditor - { - private float m_quality; - private float m_duration; - private bool m_linearTexture; - - public static GUIContent linearTextureContent = EditorGUIUtility.TrTextContent("Bypass sRGB Sampling", "Texture will not be converted from gamma space to linear when sampled. Enable for IMGUI textures and non-color textures."); - - // Don't show the imported movie as a separate editor - public override bool showImportedObject { get { return false; } } - - public override bool HasModified() - { - MovieImporter importer = target as MovieImporter; - return (importer.quality != m_quality || importer.linearTexture != m_linearTexture); - } - - protected override void ResetValues() - { - MovieImporter importer = target as MovieImporter; - - m_quality = importer.quality; - m_linearTexture = importer.linearTexture; - // only read out this once (its pretty slow) - m_duration = importer.duration; - } - - protected override void Apply() - { - MovieImporter importer = target as MovieImporter; - importer.quality = m_quality; - importer.linearTexture = m_linearTexture; - } - - public override void OnInspectorGUI() - { - MovieImporter importer = target as MovieImporter; - - if (importer != null) - { - GUILayout.BeginVertical(); - - m_linearTexture = EditorGUILayout.Toggle(linearTextureContent, m_linearTexture); - - int bitrate = (int)(GetVideoBitrateForQuality(m_quality) + GetAudioBitrateForQuality(m_quality)); - float size = (bitrate / 8 * m_duration); - float kbsize = 1024.0f * 1024.0f; - - m_quality = EditorGUILayout.Slider("Quality", m_quality, 0.0f, 1.0f); - GUILayout.Label( - string.Format("Approx. {0:0.00} " + (size < kbsize ? "kB" : "MB") + ", {1} kbps", - size / (size < kbsize ? 1024.0f : kbsize), bitrate / 1000), EditorStyles.helpBox); - GUILayout.EndVertical(); - } - - ApplyRevertGUI(); - - MovieTexture movie = assetTarget as MovieTexture; - if (movie && movie.loop) - { - EditorGUILayout.Space(); - movie.loop = EditorGUILayout.Toggle("Loop", movie.loop); - GUILayout.Label("The Loop setting in the Inspector is obsolete. Use the Scripting API to control looping instead.\n\nThe loop setting will be disabled on next re-import or by disabling it above.", EditorStyles.helpBox); - } - } - - double GetAudioBitrateForQuality(double f) { return (56000 + 200000 * (f)); } - double GetVideoBitrateForQuality(double f) { return (100000 + 8000000 * (f)); } - double GetAudioQualityForBitrate(double f) { return (f - 56000) / 200000; } - double GetVideoQualityForBitrate(double f) { return (f - 100000) / 8000000; } - } -} diff --git a/Editor/Mono/ImportSettings/PatchImportSettingsRecycleID.cs b/Editor/Mono/ImportSettings/PatchImportSettingsRecycleID.cs deleted file mode 100644 index 6d31ab153e..0000000000 --- a/Editor/Mono/ImportSettings/PatchImportSettingsRecycleID.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; -using System; - -internal class PatchImportSettingRecycleID -{ - static public void Patch(SerializedObject serializedObject, int classID, string oldName, string newName) - { - PatchMultiple(serializedObject, classID, new string[] { oldName }, new string[] { newName }); - } - - // Patches multiple entries at once to avoid situations where swapping names of two entries would break references - static public void PatchMultiple(SerializedObject serializedObject, int classID, string[] oldNames, string[] newNames) - { - int left = oldNames.Length; - - SerializedProperty recycleMap = serializedObject.FindProperty("m_FileIDToRecycleName"); - foreach (SerializedProperty element in recycleMap) - { - SerializedProperty first = element.FindPropertyRelative("first"); - if (AssetImporter.LocalFileIDToClassID(first.longValue) == classID) - { - SerializedProperty second = element.FindPropertyRelative("second"); - int idx = Array.IndexOf(oldNames, second.stringValue); - if (idx >= 0) - { - second.stringValue = newNames[idx]; - if (--left == 0) - break; - } - } - } - } -} diff --git a/Editor/Mono/ImportSettings/PluginImporterInspector.cs b/Editor/Mono/ImportSettings/PluginImporterInspector.cs deleted file mode 100644 index c272f57a23..0000000000 --- a/Editor/Mono/ImportSettings/PluginImporterInspector.cs +++ /dev/null @@ -1,592 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using UnityEditor; -using UnityEngine; -using System.IO; -using UnityEditorInternal; -using UnityEditor.Modules; -using UnityEditor.Build; -using Mono.Cecil; - -namespace UnityEditor -{ - [CustomEditor(typeof(PluginImporter))] - [CanEditMultipleObjects] - internal class PluginImporterInspector : Experimental.AssetImporters.AssetImporterEditor - { - private delegate Compatibility ValueSwitcher(Compatibility value); - private bool m_HasModified; - private string m_ReferencesUnityEngineModule; - - // Notes regarding Standalone target - // Unlike other platforms, Standalone targets (OSX, Windows, Linux) are bundled as one target ("Standalone") in platform settings - // That's why value m_CompatibleWithPlatform for is controlled from two places: - // * ShowGeneralOptions (when clicking on 'Standalone' toggle, it enables or disables all those targets) - // * DesktopPluginImporterExtension (where it's possible to individually enable or disable specific Standalone target) - - internal enum Compatibility : int - { - Mixed = -1, - NotCompatible = 0, - Compatible = 1 - } - - private Compatibility m_CompatibleWithAnyPlatform; - private Compatibility m_CompatibleWithEditor; - private Compatibility[] m_CompatibleWithPlatform = new Compatibility[GetPlatformGroupArraySize()]; - - private readonly static BuildTarget[] m_StandaloneTargets = new BuildTarget[] - { - BuildTarget.StandaloneOSX, - BuildTarget.StandaloneWindows, - BuildTarget.StandaloneWindows64, - BuildTarget.StandaloneLinux, - BuildTarget.StandaloneLinux64, - BuildTarget.StandaloneLinuxUniversal - }; - - private Vector2 m_InformationScrollPosition = Vector2.zero; - private Dictionary m_PluginInformation; - private EditorPluginImporterExtension m_EditorExtension = null; - private DesktopPluginImporterExtension m_DesktopExtension = null; - - public override bool showImportedObject { get { return false; } } - - internal EditorPluginImporterExtension editorExtension - { - get - { - if (m_EditorExtension == null) - m_EditorExtension = new EditorPluginImporterExtension(); - return m_EditorExtension; - } - } - - internal DesktopPluginImporterExtension desktopExtension - { - get - { - if (m_DesktopExtension == null) - m_DesktopExtension = new DesktopPluginImporterExtension(); - return m_DesktopExtension; - } - } - - internal IPluginImporterExtension[] additionalExtensions - { - get - { - return new IPluginImporterExtension[] - { - editorExtension, - desktopExtension - }; - } - } - - internal PluginImporter importer - { - get { return target as PluginImporter; } - } - - internal PluginImporter[] importers - { - get { return targets.Cast().ToArray(); } - } - - private static bool IgnorePlatform(BuildTarget platform) - { - return false; - } - - private bool IsEditingPlatformSettingsSupported() - { - // We don't support editing platform settings when multiple objects are selected - return targets.Length == 1; - } - - private static int GetPlatformGroupArraySize() - { - int max = 0; - foreach (BuildTarget platform in typeof(BuildTarget).EnumGetNonObsoleteValues()) - if (max < (int)platform + 1) max = (int)platform + 1; - return max; - } - - private static bool IsStandaloneTarget(BuildTarget buildTarget) - { - return m_StandaloneTargets.Contains(buildTarget); - } - - private Compatibility compatibleWithStandalone - { - get - { - bool compatible = false; - foreach (var t in m_StandaloneTargets) - { - // Return mixed value if one of the values is mixed - if (m_CompatibleWithPlatform[(int)t] == Compatibility.Mixed) - return Compatibility.Mixed; - - // Otherwise revert to default behavior - compatible |= m_CompatibleWithPlatform[(int)t] > 0; - } - return compatible ? Compatibility.Compatible : Compatibility.NotCompatible; - } - - set - { - foreach (var t in m_StandaloneTargets) - m_CompatibleWithPlatform[(int)t] = value; - } - } - - internal static bool IsValidBuildTarget(BuildTarget buildTarget) - { - return buildTarget > 0; - } - - // Used by extensions, for ex., Standalone where we have options for enabling/disabling platform in platform specific extensions - internal Compatibility GetPlatformCompatibility(string platformName) - { - var buildTarget = BuildPipeline.GetBuildTargetByName(platformName); - if (!IsValidBuildTarget(buildTarget)) - return Compatibility.NotCompatible; - - return m_CompatibleWithPlatform[(int)buildTarget]; - } - - internal void SetPlatformCompatibility(string platformName, bool compatible) - { - SetPlatformCompatibility(platformName, compatible ? Compatibility.Compatible : Compatibility.NotCompatible); - } - - internal void SetPlatformCompatibility(string platformName, Compatibility compatibility) - { - if (compatibility == Compatibility.Mixed) - throw new ArgumentException("compatibility value cannot be Mixed"); - - var buildTarget = BuildPipeline.GetBuildTargetByName(platformName); - if (!IsValidBuildTarget(buildTarget) || m_CompatibleWithPlatform[(int)buildTarget] == compatibility) - return; - - m_CompatibleWithPlatform[(int)buildTarget] = compatibility; - m_HasModified = true; - } - - private static List GetValidBuildTargets() - { - List validBuildTargets = new List(); - foreach (BuildTarget platform in typeof(BuildTarget).EnumGetNonObsoleteValues()) - { - // We have some special enums with negative values which are not actual targets, ignore those - if (!IsValidBuildTarget(platform)) - continue; - - // Ignore Unknown or deprectated value - if (IgnorePlatform(platform)) - continue; - - // Ignore platforms which don't have module extensions loaded, accept standalone targets by default, as they don't have extensions - if (ModuleManager.IsPlatformSupported(platform) && - !ModuleManager.IsPlatformSupportLoaded(ModuleManager.GetTargetStringFromBuildTarget(platform)) && - !IsStandaloneTarget(platform)) - continue; - - validBuildTargets.Add(platform); - } - return validBuildTargets; - } - - private BuildPlatform[] GetBuildPlayerValidPlatforms() - { - List validPlatforms = BuildPlatforms.instance.GetValidPlatforms(); - List filtered = new List(); - - if (m_CompatibleWithEditor > Compatibility.NotCompatible) - { - BuildPlatform editorPlatform = new BuildPlatform("Editor settings", "Editor Settings", "BuildSettings.Editor", BuildTargetGroup.Unknown, true); - editorPlatform.name = BuildPipeline.GetEditorTargetName(); - filtered.Add(editorPlatform); - } - foreach (BuildPlatform bp in validPlatforms) - { - if (IgnorePlatform(bp.defaultTarget)) - continue; - - if (bp.targetGroup == BuildTargetGroup.Standalone) - { - if (compatibleWithStandalone < Compatibility.Compatible) - continue; - } - else - { - if (m_CompatibleWithPlatform[(int)bp.defaultTarget] < Compatibility.Compatible) - continue; - - IPluginImporterExtension extension = ModuleManager.GetPluginImporterExtension(bp.targetGroup); - if (extension == null) - continue; - } - - filtered.Add(bp); - } - - return filtered.ToArray(); - } - - private delegate bool GetComptability(PluginImporter imp); - private void ResetCompatability(ref Compatibility value, GetComptability getComptability) - { - value = getComptability(importer) ? Compatibility.Compatible : Compatibility.NotCompatible; - foreach (var imp in importers) - { - if (value != (getComptability(imp) ? Compatibility.Compatible : Compatibility.NotCompatible)) - { - value = Compatibility.Mixed; - break; - } - } - } - - protected override void ResetValues() - { - base.ResetValues(); - - m_HasModified = false; - - ResetCompatability(ref m_CompatibleWithAnyPlatform, (imp => { return imp.GetCompatibleWithAnyPlatform(); })); - ResetCompatability(ref m_CompatibleWithEditor, (imp => { return imp.GetCompatibleWithEditor(); })); - // If Any Platform is selected, initialize m_Compatible* variables using compatability function - // If Any Platform is unselected, initialize m_Compatible* variables using exclude function - // This gives correct initialization in case when plugin is imported for the first time, and only "Any Platform" is selected - if (m_CompatibleWithAnyPlatform < Compatibility.Compatible) - { - ResetCompatability(ref m_CompatibleWithEditor, (imp => { return imp.GetCompatibleWithEditor("", ""); })); - - foreach (BuildTarget platform in GetValidBuildTargets()) - { - ResetCompatability(ref m_CompatibleWithPlatform[(int)platform], (imp => { return imp.GetCompatibleWithPlatform(platform); })); - } - } - else - { - ResetCompatability(ref m_CompatibleWithEditor, (imp => { return !imp.GetExcludeEditorFromAnyPlatform(); })); - - foreach (BuildTarget platform in GetValidBuildTargets()) - { - ResetCompatability(ref m_CompatibleWithPlatform[(int)platform], (imp => { return !imp.GetExcludeFromAnyPlatform(platform); })); - } - } - - if (!IsEditingPlatformSettingsSupported()) - return; - - foreach (var extension in additionalExtensions) - { - extension.ResetValues(this); - } - - foreach (BuildTarget platform in GetValidBuildTargets()) - { - IPluginImporterExtension extension = ModuleManager.GetPluginImporterExtension(platform); - if (extension != null) - extension.ResetValues(this); - } - } - - public override bool HasModified() - { - bool modified = m_HasModified || base.HasModified(); - - if (!IsEditingPlatformSettingsSupported()) - return modified; - - foreach (var extension in additionalExtensions) - { - modified |= extension.HasModified(this); - } - - foreach (BuildTarget platform in GetValidBuildTargets()) - { - IPluginImporterExtension extension = ModuleManager.GetPluginImporterExtension(platform); - if (extension != null) modified |= extension.HasModified(this); - } - - return modified; - } - - protected override void Apply() - { - base.Apply(); - foreach (var imp in importers) - { - if (m_CompatibleWithAnyPlatform > Compatibility.Mixed) - imp.SetCompatibleWithAnyPlatform(m_CompatibleWithAnyPlatform == Compatibility.Compatible); - if (m_CompatibleWithEditor > Compatibility.Mixed) - imp.SetCompatibleWithEditor(m_CompatibleWithEditor == Compatibility.Compatible); - - foreach (BuildTarget platform in GetValidBuildTargets()) - { - if (m_CompatibleWithPlatform[(int)platform] > Compatibility.Mixed) - imp.SetCompatibleWithPlatform(platform, m_CompatibleWithPlatform[(int)platform] == Compatibility.Compatible); - } - - if (m_CompatibleWithEditor > Compatibility.Mixed) - imp.SetExcludeEditorFromAnyPlatform(m_CompatibleWithEditor == Compatibility.NotCompatible); - - foreach (BuildTarget platform in GetValidBuildTargets()) - { - if (m_CompatibleWithPlatform[(int)platform] > Compatibility.Mixed) - imp.SetExcludeFromAnyPlatform(platform, m_CompatibleWithPlatform[(int)platform] == Compatibility.NotCompatible); - } - } - - if (!IsEditingPlatformSettingsSupported()) - return; - - foreach (var extension in additionalExtensions) - { - extension.Apply(this); - } - - foreach (BuildTarget platform in GetValidBuildTargets()) - { - IPluginImporterExtension extension = ModuleManager.GetPluginImporterExtension(platform); - if (extension != null) extension.Apply(this); - } - } - - protected override void Awake() - { - m_EditorExtension = new EditorPluginImporterExtension(); - m_DesktopExtension = new DesktopPluginImporterExtension(); - - base.Awake(); - } - - public override void OnEnable() - { - if (!IsEditingPlatformSettingsSupported()) - return; - - foreach (var extension in additionalExtensions) - { - extension.OnEnable(this); - } - - foreach (BuildTarget platform in GetValidBuildTargets()) - { - IPluginImporterExtension extension = ModuleManager.GetPluginImporterExtension(platform); - if (extension != null) - { - extension.OnEnable(this); - extension.ResetValues(this); - } - } - - m_PluginInformation = new Dictionary(); - m_PluginInformation["Path"] = importer.assetPath; - m_PluginInformation["Type"] = importer.isNativePlugin ? "Native" : "Managed"; - if (!importer.isNativePlugin) - { - string info; - switch (importer.dllType) - { - case DllType.ManagedNET35: info = "Targets .NET 3.5"; break; - case DllType.ManagedNET40: info = "Targets .NET 4.x"; break; - case DllType.UnknownManaged: info = "Targets Unknown .NET"; break; - case DllType.WinMDNET40: info = "Managed WinMD"; break; - case DllType.WinMDNative: info = "Native WinMD"; break; - default: - throw new Exception("Unknown managed dll type: " + importer.dllType.ToString()); - } - - m_PluginInformation["Assembly Info"] = info; - } - - m_ReferencesUnityEngineModule = importer.HasDiscouragedReferences(); - } - - new void OnDisable() - { - base.OnDisable(); - - if (!IsEditingPlatformSettingsSupported()) - return; - - foreach (var extension in additionalExtensions) - { - extension.OnDisable(this); - } - - foreach (BuildTarget platform in GetValidBuildTargets()) - { - IPluginImporterExtension extension = ModuleManager.GetPluginImporterExtension(platform); - if (extension != null) extension.OnDisable(this); - } - } - - private Compatibility ToggleWithMixedValue(Compatibility value, string title) - { - EditorGUI.showMixedValue = value == Compatibility.Mixed; - - EditorGUI.BeginChangeCheck(); - - bool newBoolValue = EditorGUILayout.Toggle(title, value == Compatibility.Compatible); - if (EditorGUI.EndChangeCheck()) - return newBoolValue ? Compatibility.Compatible : Compatibility.NotCompatible; - - EditorGUI.showMixedValue = false; - return value; - } - - private void ShowPlatforms(ValueSwitcher switcher) - { - // Note: We use m_CompatibleWithEditor & m_CompatibleWithPlatform for displaying both Include & Exclude platforms - m_CompatibleWithEditor = switcher(ToggleWithMixedValue(switcher(m_CompatibleWithEditor), "Editor")); - EditorGUI.BeginChangeCheck(); - Compatibility value = ToggleWithMixedValue(switcher(compatibleWithStandalone), "Standalone"); - // We only want to change compatibleWithStandalone value, if user actually clicks on it - if (EditorGUI.EndChangeCheck()) - { - compatibleWithStandalone = switcher(value); - if (compatibleWithStandalone != Compatibility.Mixed) - desktopExtension.ValidateSingleCPUTargets(this); - } - - foreach (BuildTarget platform in GetValidBuildTargets()) - { - // Ignore Standalone targets, we're displaying it as one item - if (IsStandaloneTarget(platform)) - continue; - - m_CompatibleWithPlatform[(int)platform] = switcher(ToggleWithMixedValue(switcher(m_CompatibleWithPlatform[(int)platform]), platform.ToString())); - } - } - - private Compatibility SwitchToInclude(Compatibility value) - { - return value; - } - - private Compatibility SwitchToExclude(Compatibility value) - { - switch (value) - { - case Compatibility.Mixed: return Compatibility.Mixed; - case Compatibility.Compatible: return Compatibility.NotCompatible; - case Compatibility.NotCompatible: return Compatibility.Compatible; - default: - throw new InvalidEnumArgumentException("Invalid value: " + value.ToString()); - } - } - - private void ShowGeneralOptions() - { - EditorGUI.BeginChangeCheck(); - m_CompatibleWithAnyPlatform = ToggleWithMixedValue(m_CompatibleWithAnyPlatform, "Any Platform"); - - if (m_CompatibleWithAnyPlatform == Compatibility.Compatible) - { - GUILayout.Label("Exclude Platforms", EditorStyles.boldLabel); - ShowPlatforms(SwitchToExclude); - } - else if (m_CompatibleWithAnyPlatform == Compatibility.NotCompatible) - { - GUILayout.Label("Include Platforms", EditorStyles.boldLabel); - ShowPlatforms(SwitchToInclude); - } - - if (EditorGUI.EndChangeCheck()) - m_HasModified = true; - } - - private void ShowEditorSettings() - { - editorExtension.OnPlatformSettingsGUI(this); - } - - private void ShowPlatformSettings() - { - BuildPlatform[] validPlatforms = GetBuildPlayerValidPlatforms(); - if (validPlatforms.Length > 0) - { - GUILayout.Label("Platform settings", EditorStyles.boldLabel); - int platformIndex = EditorGUILayout.BeginPlatformGrouping(validPlatforms, null); - - if (validPlatforms[platformIndex].name == BuildPipeline.GetEditorTargetName()) - { - ShowEditorSettings(); - } - else - { - BuildTargetGroup targetGroup = validPlatforms[platformIndex].targetGroup; - if (targetGroup == BuildTargetGroup.Standalone) - { - desktopExtension.OnPlatformSettingsGUI(this); - } - else - { - IPluginImporterExtension extension = ModuleManager.GetPluginImporterExtension(targetGroup); - if (extension != null) extension.OnPlatformSettingsGUI(this); - } - } - EditorGUILayout.EndPlatformGrouping(); - } - } - - public override void OnInspectorGUI() - { - using (new EditorGUI.DisabledScope(false)) - { - GUILayout.Label("Select platforms for plugin", EditorStyles.boldLabel); - EditorGUILayout.BeginVertical(GUI.skin.box); - ShowGeneralOptions(); - EditorGUILayout.EndVertical(); - GUILayout.Space(10f); - - if (IsEditingPlatformSettingsSupported()) - ShowPlatformSettings(); - } - ApplyRevertGUI(); - - // Don't output additional information if we have multiple plugins selected - if (targets.Length > 1) - return; - - GUILayout.Label("Information", EditorStyles.boldLabel); - - m_InformationScrollPosition = EditorGUILayout.BeginVerticalScrollView(m_InformationScrollPosition); - - foreach (var prop in m_PluginInformation) - { - GUILayout.BeginHorizontal(); - GUILayout.Label(prop.Key, GUILayout.Width(85)); - EditorGUILayout.SelectableLabel(prop.Value, GUILayout.Height(EditorGUI.kSingleLineHeight)); - GUILayout.EndHorizontal(); - } - - EditorGUILayout.EndScrollView(); - GUILayout.FlexibleSpace(); - - // Warning for Case 648027 - // Once Mono loads a native plugin, it never releases a handle, thus plugin is never unloaded. - if (importer.isNativePlugin) - EditorGUILayout.HelpBox("Once a native plugin is loaded from script, it's never unloaded. If you deselect a native plugin and it's already loaded, please restart Unity.", MessageType.Warning); - if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy && importer.dllType == DllType.ManagedNET40 && m_CompatibleWithEditor == Compatibility.Compatible) - EditorGUILayout.HelpBox("Plugin targets .NET 4.x and is marked as compatible with Editor, Editor can only use assemblies targeting .NET 3.5 or lower, please unselect Editor as compatible platform.", MessageType.Error); - if (m_ReferencesUnityEngineModule != null) - EditorGUILayout.HelpBox($"This plugin references at least one UnityEngine module assemblies directly ({m_ReferencesUnityEngineModule}.dll). To assure forward compatibility, only reference UnityEngine.dll, which contains type forwarders for all the module dlls.", MessageType.Warning); - } - } -} diff --git a/Editor/Mono/ImportSettings/PrefabUtility.cs b/Editor/Mono/ImportSettings/PrefabUtility.cs deleted file mode 100644 index bff7746910..0000000000 --- a/Editor/Mono/ImportSettings/PrefabUtility.cs +++ /dev/null @@ -1,224 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - public sealed partial class PrefabUtility - { - private const string kMaterialExtension = ".mat"; - - [RequiredByNativeCode] - internal static void ExtractSelectedObjectsFromPrefab() - { - var assetsToReload = new HashSet(); - string folder = null; - foreach (var selectedObj in Selection.objects) - { - var path = AssetDatabase.GetAssetPath(selectedObj); - - // use the first selected element as the basis for the folder path where all the materials will be extracted - if (folder == null) - { - folder = EditorUtility.SaveFolderPanel("Select Materials Folder", FileUtil.DeleteLastPathNameComponent(path), ""); - if (string.IsNullOrEmpty(folder)) - { - // cancel the extraction if the user did not select a folder - return; - } - - folder = FileUtil.GetProjectRelativePath(folder); - } - - // TODO: [bogdanc 3/6/2017] if we want this function really generic, we need to know what extension the new asset files should have - var extension = selectedObj is Material ? kMaterialExtension : string.Empty; - var newAssetPath = FileUtil.CombinePaths(folder, selectedObj.name) + extension; - newAssetPath = AssetDatabase.GenerateUniqueAssetPath(newAssetPath); - - var error = AssetDatabase.ExtractAsset(selectedObj, newAssetPath); - if (string.IsNullOrEmpty(error)) - { - assetsToReload.Add(path); - } - } - - foreach (var path in assetsToReload) - { - AssetDatabase.WriteImportSettingsIfDirty(path); - AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); - } - } - - internal static void ExtractMaterialsFromAsset(Object[] targets, string destinationPath) - { - var assetsToReload = new HashSet(); - foreach (var t in targets) - { - var importer = t as ModelImporter; - - var materials = AssetDatabase.LoadAllAssetsAtPath(importer.assetPath).Where(x => x.GetType() == typeof(Material)); - - foreach (var material in materials) - { - var newAssetPath = FileUtil.CombinePaths(destinationPath, material.name) + kMaterialExtension; - newAssetPath = AssetDatabase.GenerateUniqueAssetPath(newAssetPath); - - var error = AssetDatabase.ExtractAsset(material, newAssetPath); - if (string.IsNullOrEmpty(error)) - { - assetsToReload.Add(importer.assetPath); - } - } - } - - foreach (var path in assetsToReload) - { - AssetDatabase.WriteImportSettingsIfDirty(path); - AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); - } - } - - private static void GetObjectListFromHierarchy(List hierarchy, GameObject gameObject) - { - Transform transform = null; - List components = new List(); - gameObject.GetComponents(components); - foreach (var component in components) - { - if (component is Transform) - transform = component as Transform; - - hierarchy.Add(component); - } - if (transform == null) - return; - - int childCount = transform.childCount; - for (var i = 0; i < childCount; i++) - GetObjectListFromHierarchy(hierarchy, transform.GetChild(i).gameObject); - } - - private static void RegisterNewObjects(List newHierarchy, List hierarchy, string actionName) - { - var danglingObjects = new List(); - - foreach (var i in newHierarchy) - { - var found = false; - foreach (var j in hierarchy) - { - if (j.GetInstanceID() == i.GetInstanceID()) - { - found = true; - break; - } - } - if (!found) - { - danglingObjects.Add(i); - } - } - - // We need to ensure that dangling components are registered in an acceptable order regarding dependencies. For example, if we're adding RigidBody and ConfigurableJoint, the RigidBody will need to be added first (as the ConfigurableJoint depends upon it existing) - var addedTypes = new HashSet() - { - typeof(Transform) - }; - var emptyPass = false; - while (danglingObjects.Count > 0 && !emptyPass) - { - emptyPass = true; - for (var i = 0; i < danglingObjects.Count; i++) - { - var danglingObject = danglingObjects[i]; - var reqs = danglingObject.GetType().GetCustomAttributes(typeof(RequireComponent), inherit: true); - var requiredComponentsExist = true; - foreach (RequireComponent req in reqs) - { - if ((req.m_Type0 != null && !addedTypes.Contains(req.m_Type0)) || (req.m_Type1 != null && !addedTypes.Contains(req.m_Type1)) || (req.m_Type2 != null && !addedTypes.Contains(req.m_Type2))) - { - requiredComponentsExist = false; - break; - } - } - if (requiredComponentsExist) - { - if (danglingObject is Transform) - danglingObject = ((Transform)danglingObject).gameObject; - - Undo.RegisterCreatedObjectUndo(danglingObject, actionName); - addedTypes.Add(danglingObject.GetType()); - danglingObjects.RemoveAt(i); - i--; - emptyPass = false; - } - } - } - - Debug.Assert(danglingObjects.Count == 0, "Dangling components have unfulfilled dependencies"); - foreach (var component in danglingObjects) - { - Undo.RegisterCreatedObjectUndo(component, actionName); - } - } - - internal static void RevertPrefabInstanceWithUndo(GameObject target) - { - var actionName = "Revert Prefab Instance"; - - PrefabType prefabType = GetPrefabType(target); - bool isDisconnected = (prefabType == PrefabType.DisconnectedModelPrefabInstance || prefabType == PrefabType.DisconnectedPrefabInstance); - - GameObject root = null; - if (isDisconnected) - root = FindRootGameObjectWithSameParentPrefab(target); - else - root = FindValidUploadPrefabInstanceRoot(target); - - List hierarchy = new List(); - GetObjectListFromHierarchy(hierarchy, root); - - Undo.RegisterFullObjectHierarchyUndo(root, actionName); - - if (isDisconnected) - { - ReconnectToLastPrefab(root); - Undo.RegisterCreatedObjectUndo(GetPrefabObject(root), actionName); - } - - RevertPrefabInstance(root); - List newHierarchy = new List(); - GetObjectListFromHierarchy(newHierarchy, FindPrefabRoot(root)); - - RegisterNewObjects(newHierarchy, hierarchy, actionName); - } - - internal static void ReplacePrefabWithUndo(GameObject target) - { - var actionName = "Apply instance to prefab"; - Object prefabParent = GetPrefabParent(target); - GameObject rootUploadGameObject = FindValidUploadPrefabInstanceRoot(target); - - Undo.RegisterFullObjectHierarchyUndo(prefabParent, actionName); - Undo.RegisterFullObjectHierarchyUndo(rootUploadGameObject, actionName); - Undo.RegisterCreatedObjectUndo(rootUploadGameObject, actionName); - - List prefabHierarchy = new List(); - GetObjectListFromHierarchy(prefabHierarchy, prefabParent as GameObject); - - ReplacePrefab(rootUploadGameObject, prefabParent, ReplacePrefabOptions.ConnectToPrefab); - - List newPrefabHierarchy = new List(); - GetObjectListFromHierarchy(newPrefabHierarchy, prefabParent as GameObject); - - RegisterNewObjects(newPrefabHierarchy, prefabHierarchy, actionName); - } - } -} diff --git a/Editor/Mono/ImportSettings/ScriptedImporterEditor.cs b/Editor/Mono/ImportSettings/ScriptedImporterEditor.cs deleted file mode 100644 index f285224239..0000000000 --- a/Editor/Mono/ImportSettings/ScriptedImporterEditor.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor.Experimental.AssetImporters -{ - [CustomEditor(typeof(ScriptedImporter), true)] - public class ScriptedImporterEditor : AssetImporterEditor - { - internal override string targetTitle - { - get { return base.targetTitle + " (" + ObjectNames.NicifyVariableName(GetType().Name) + ")"; } - } - - public override void OnInspectorGUI() - { - // Loop through properties and create one field (including children) for each top level property. - SerializedProperty property = serializedObject.GetIterator(); - bool expanded = true; - while (property.NextVisible(expanded)) - { - EditorGUILayout.PropertyField(property, true); - expanded = false; - } - - ApplyRevertGUI(); - } - - protected override bool OnApplyRevertGUI() - { - bool applied = base.OnApplyRevertGUI(); - if (applied) - { - // Displayed asset is un-loaded at this point due to reimport. - // force rebuild to force full asset load. - ActiveEditorTracker.sharedTracker.ForceRebuild(); - } - - return applied; - } - } -} diff --git a/Editor/Mono/ImportSettings/SpeedTreeImporterInspector.cs b/Editor/Mono/ImportSettings/SpeedTreeImporterInspector.cs deleted file mode 100644 index 4130467c4f..0000000000 --- a/Editor/Mono/ImportSettings/SpeedTreeImporterInspector.cs +++ /dev/null @@ -1,415 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEngine; -using UnityEditor.VersionControl; -using UnityEditor.AnimatedValues; -using UnityEditor.Experimental.AssetImporters; - -namespace UnityEditor -{ - [CustomEditor(typeof(SpeedTreeImporter))] - [CanEditMultipleObjects] - internal class SpeedTreeImporterInspector : AssetImporterEditor - { - private class Styles - { - public static GUIContent LODHeader = EditorGUIUtility.TrTextContent("LODs"); - public static GUIContent ResetLOD = EditorGUIUtility.TrTextContent("Reset LOD to...", "Unify the LOD settings for all selected assets."); - public static GUIContent SmoothLOD = EditorGUIUtility.TrTextContent("Smooth LOD", "Toggles smooth LOD transitions."); - public static GUIContent AnimateCrossFading = EditorGUIUtility.TrTextContent("Animate Cross-fading", "Cross-fading is animated instead of being calculated by distance."); - 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."); - public static GUIContent FadeOutWidth = EditorGUIUtility.TrTextContent("Fade Out Width", "Proportion of the billboard LOD region width which is used for fading out the billboard."); - - public static GUIContent MeshesHeader = EditorGUIUtility.TrTextContent("Meshes"); - public static GUIContent ScaleFactor = EditorGUIUtility.TrTextContent("Scale Factor", "How much to scale the tree model compared to what is in the .spm file."); - public static GUIContent ScaleFactorHelp = EditorGUIUtility.TrTextContent("The default value of Scale Factor is 0.3048, the conversion ratio from feet to meters, as these are the most conventional measurements used in SpeedTree and Unity, respectively."); - - public static GUIContent MaterialsHeader = EditorGUIUtility.TrTextContent("Materials"); - public static GUIContent MainColor = EditorGUIUtility.TrTextContent("Main Color", "The color modulating the diffuse lighting component."); - public static GUIContent HueVariation = EditorGUIUtility.TrTextContent("Hue Color", "Apply to LODs that have Hue Variation effect enabled."); - public static GUIContent AlphaTestRef = EditorGUIUtility.TrTextContent("Alpha Cutoff", "The alpha-test reference value."); - public static GUIContent CastShadows = EditorGUIUtility.TrTextContent("Cast Shadows", "The tree casts shadow."); - public static GUIContent ReceiveShadows = EditorGUIUtility.TrTextContent("Receive Shadows", "The tree receives shadow."); - public static GUIContent UseLightProbes = EditorGUIUtility.TrTextContent("Use Light Probes", "The tree uses light probe for lighting."); - public static GUIContent UseReflectionProbes = EditorGUIUtility.TrTextContent("Use Reflection Probes", "The tree uses reflection probe for rendering."); - public static GUIContent EnableBump = EditorGUIUtility.TrTextContent("Normal Map", "Enable normal mapping (aka Bump mapping)."); - public static GUIContent EnableHue = EditorGUIUtility.TrTextContent("Enable Hue Variation", "Enable Hue variation color (color is adjusted between Main Color and Hue Color)."); - public static GUIContent WindQuality = EditorGUIUtility.TrTextContent("Wind Quality", "Controls the wind quality."); - - public static GUIContent ApplyAndGenerate = EditorGUIUtility.TrTextContent("Apply & Generate Materials", "Apply current importer settings and generate materials with new settings."); - public static GUIContent Regenerate = EditorGUIUtility.TrTextContent("Regenerate Materials", "Regenerate materials from the current importer settings."); - }; - - private SerializedProperty m_LODSettings; - private SerializedProperty m_EnableSmoothLOD; - private SerializedProperty m_AnimateCrossFading; - private SerializedProperty m_BillboardTransitionCrossFadeWidth; - private SerializedProperty m_FadeOutWidth; - private SerializedProperty m_MainColor; - private SerializedProperty m_HueVariation; - private SerializedProperty m_AlphaTestRef; - private SerializedProperty m_ScaleFactor; - - private const float kFeetToMetersRatio = 0.3048f; - - // LODGroup GUI - private int m_SelectedLODSlider = -1; - private int m_SelectedLODRange = 0; - - private readonly AnimBool m_ShowSmoothLODOptions = new AnimBool(); - private readonly AnimBool m_ShowCrossFadeWidthOptions = new AnimBool(); - - public override void OnEnable() - { - m_LODSettings = serializedObject.FindProperty("m_LODSettings"); - m_EnableSmoothLOD = serializedObject.FindProperty("m_EnableSmoothLODTransition"); - m_AnimateCrossFading = serializedObject.FindProperty("m_AnimateCrossFading"); - m_BillboardTransitionCrossFadeWidth = serializedObject.FindProperty("m_BillboardTransitionCrossFadeWidth"); - m_FadeOutWidth = serializedObject.FindProperty("m_FadeOutWidth"); - m_MainColor = serializedObject.FindProperty("m_MainColor"); - m_HueVariation = serializedObject.FindProperty("m_HueVariation"); - m_AlphaTestRef = serializedObject.FindProperty("m_AlphaTestRef"); - m_ScaleFactor = serializedObject.FindProperty("m_ScaleFactor"); - - m_ShowSmoothLODOptions.value = m_EnableSmoothLOD.hasMultipleDifferentValues || m_EnableSmoothLOD.boolValue; - m_ShowSmoothLODOptions.valueChanged.AddListener(Repaint); - m_ShowCrossFadeWidthOptions.value = m_AnimateCrossFading.hasMultipleDifferentValues || !m_AnimateCrossFading.boolValue; - m_ShowCrossFadeWidthOptions.valueChanged.AddListener(Repaint); - } - - public override void OnDisable() - { - base.OnDisable(); - - m_ShowSmoothLODOptions.valueChanged.RemoveListener(Repaint); - m_ShowCrossFadeWidthOptions.valueChanged.RemoveListener(Repaint); - } - - private SpeedTreeImporter[] importers - { - get { return targets.Cast().ToArray(); } - } - - private bool upgradeMaterials - { - get { return importers.Any(i => i.materialsShouldBeRegenerated); } - } - - protected override bool OnApplyRevertGUI() - { - bool applied; - using (new EditorGUI.DisabledScope(!HasModified())) - { - RevertButton(); - applied = ApplyButton("Apply Prefab"); - } - - bool upgrade = upgradeMaterials; - GUIContent genButtonText = HasModified() || upgrade ? Styles.ApplyAndGenerate : Styles.Regenerate; - - if (GUILayout.Button(genButtonText)) - { - bool hasModified = HasModified(); - - // Apply the changes and generate the materials before importing so that asset previews are up-to-date. - if (hasModified) - Apply(); - - if (upgrade) - { - foreach (var importer in importers) - importer.SetMaterialVersionToCurrent(); - } - - GenerateMaterials(); - - if (hasModified || upgrade) - { - ApplyAndImport(); - applied = true; - } - } - - return applied; - } - - private void GenerateMaterials() - { - string[] matFolders = importers.Select(im => im.materialFolderPath).ToArray(); - string[] guids = AssetDatabase.FindAssets("t:Material", matFolders); - string[] paths = guids.Select(guid => AssetDatabase.GUIDToAssetPath(guid)).ToArray(); - - bool doGenerate = true; - if (paths.Length > 0) - doGenerate = Provider.PromptAndCheckoutIfNeeded(paths, String.Format("Materials will be checked out in:\n{0}", String.Join("\n", matFolders))); - - if (doGenerate) - { - foreach (var importer in importers) - importer.GenerateMaterials(); - } - } - - internal List GetLODInfoArray(Rect area) - { - int lodCount = m_LODSettings.arraySize; - return LODGroupGUI.CreateLODInfos( - lodCount, area, - i => i == lodCount - 1 && (target as SpeedTreeImporter).hasBillboard ? "Billboard" : String.Format("LOD {0}", i), - i => m_LODSettings.GetArrayElementAtIndex(i).FindPropertyRelative("height").floatValue); - } - - public bool HasSameLODConfig() - { - if (serializedObject.FindProperty("m_HasBillboard").hasMultipleDifferentValues) - return false; - if (m_LODSettings.FindPropertyRelative("Array.size").hasMultipleDifferentValues) - return false; - for (int i = 0; i < m_LODSettings.arraySize; ++i) - { - if (m_LODSettings.GetArrayElementAtIndex(i).FindPropertyRelative("height").hasMultipleDifferentValues) - return false; - } - return true; - } - - public bool CanUnifyLODConfig() - { - // differs only in LOD heights - return !serializedObject.FindProperty("m_HasBillboard").hasMultipleDifferentValues - && !m_LODSettings.FindPropertyRelative("Array.size").hasMultipleDifferentValues; - } - - public override void OnInspectorGUI() - { - ShowMeshGUI(); - ShowMaterialGUI(); - ShowLODGUI(); - - EditorGUILayout.Space(); - - if (upgradeMaterials) - EditorGUILayout.HelpBox(String.Format("SpeedTree materials need to be upgraded. Please back them up (if modified manually) then hit the \"{0}\" button below.", Styles.ApplyAndGenerate.text), MessageType.Warning); - - ApplyRevertGUI(); - } - - private void ShowMeshGUI() - { - GUILayout.Label(Styles.MeshesHeader, EditorStyles.boldLabel); - - EditorGUILayout.PropertyField(m_ScaleFactor, Styles.ScaleFactor); - - // Display a help box to explain the rationale for the default value (feet to meters conversion ratio). - if (!m_ScaleFactor.hasMultipleDifferentValues && Mathf.Approximately(m_ScaleFactor.floatValue, kFeetToMetersRatio)) - { - EditorGUILayout.HelpBox(Styles.ScaleFactorHelp.text, MessageType.Info); - } - } - - private void ShowMaterialGUI() - { - GUILayout.Label(Styles.MaterialsHeader, EditorStyles.boldLabel); - - EditorGUILayout.PropertyField(m_MainColor, Styles.MainColor); - EditorGUILayout.PropertyField(m_HueVariation, Styles.HueVariation); - EditorGUILayout.Slider(m_AlphaTestRef, 0f, 1f, Styles.AlphaTestRef); - } - - private void ShowLODGUI() - { - m_ShowSmoothLODOptions.target = m_EnableSmoothLOD.hasMultipleDifferentValues || m_EnableSmoothLOD.boolValue; - m_ShowCrossFadeWidthOptions.target = m_AnimateCrossFading.hasMultipleDifferentValues || !m_AnimateCrossFading.boolValue; - - GUILayout.Label(Styles.LODHeader, EditorStyles.boldLabel); - - EditorGUILayout.PropertyField(m_EnableSmoothLOD, Styles.SmoothLOD); - - EditorGUI.indentLevel++; - if (EditorGUILayout.BeginFadeGroup(m_ShowSmoothLODOptions.faded)) - { - EditorGUILayout.PropertyField(m_AnimateCrossFading, Styles.AnimateCrossFading); - if (EditorGUILayout.BeginFadeGroup(m_ShowCrossFadeWidthOptions.faded)) - { - EditorGUILayout.Slider(m_BillboardTransitionCrossFadeWidth, 0.0f, 1.0f, Styles.CrossFadeWidth); - EditorGUILayout.Slider(m_FadeOutWidth, 0.0f, 1.0f, Styles.FadeOutWidth); - } - EditorGUILayout.EndFadeGroup(); - } - EditorGUILayout.EndFadeGroup(); - EditorGUI.indentLevel--; - - EditorGUILayout.Space(); - if (HasSameLODConfig()) - { - EditorGUILayout.Space(); - - var area = GUILayoutUtility.GetRect(0, LODGroupGUI.kSliderBarHeight, GUILayout.ExpandWidth(true)); - var lods = GetLODInfoArray(area); - DrawLODLevelSlider(area, lods); - - EditorGUILayout.Space(); - EditorGUILayout.Space(); - - if (m_SelectedLODRange != -1 && lods.Count > 0) - { - EditorGUILayout.LabelField(lods[m_SelectedLODRange].LODName + " Options", EditorStyles.boldLabel); - bool isBillboard = (m_SelectedLODRange == lods.Count - 1) && importers[0].hasBillboard; - - EditorGUILayout.PropertyField(m_LODSettings.GetArrayElementAtIndex(m_SelectedLODRange).FindPropertyRelative("castShadows"), Styles.CastShadows); - EditorGUILayout.PropertyField(m_LODSettings.GetArrayElementAtIndex(m_SelectedLODRange).FindPropertyRelative("receiveShadows"), Styles.ReceiveShadows); - - var useLightProbes = m_LODSettings.GetArrayElementAtIndex(m_SelectedLODRange).FindPropertyRelative("useLightProbes"); - EditorGUILayout.PropertyField(useLightProbes, Styles.UseLightProbes); - if (!useLightProbes.hasMultipleDifferentValues && useLightProbes.boolValue && isBillboard) - EditorGUILayout.HelpBox("Enabling Light Probe for billboards breaks batched rendering and may cause performance problem.", MessageType.Warning); - - // TODO: reflection probe support when PBS is implemented - //EditorGUILayout.PropertyField(m_LODSettings.GetArrayElementAtIndex(m_SelectedLODRange).FindPropertyRelative("useReflectionProbes"), Styles.UseReflectionProbes); - - EditorGUILayout.PropertyField(m_LODSettings.GetArrayElementAtIndex(m_SelectedLODRange).FindPropertyRelative("enableBump"), Styles.EnableBump); - EditorGUILayout.PropertyField(m_LODSettings.GetArrayElementAtIndex(m_SelectedLODRange).FindPropertyRelative("enableHue"), Styles.EnableHue); - - int bestWindQuality = importers.Min(im => im.bestWindQuality); - if (bestWindQuality > 0) - { - if (isBillboard) - bestWindQuality = bestWindQuality >= 1 ? 1 : 0; // billboard has only one level of wind quality - EditorGUILayout.Popup( - m_LODSettings.GetArrayElementAtIndex(m_SelectedLODRange).FindPropertyRelative("windQuality"), - SpeedTreeImporter.windQualityNames.Take(bestWindQuality + 1).Select(s => new GUIContent(s)).ToArray(), - Styles.WindQuality); - } - } - } - else - { - if (CanUnifyLODConfig()) - { - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - Rect buttonRect = GUILayoutUtility.GetRect(Styles.ResetLOD, EditorStyles.miniButton); - if (GUI.Button(buttonRect, Styles.ResetLOD, EditorStyles.miniButton)) - { - var dropDownMenu = new GenericMenu(); - foreach (var importer in targets.Cast()) - { - var menuText = String.Format("{0}: {1}", - Path.GetFileNameWithoutExtension(importer.assetPath), - String.Join(" | ", importer.LODHeights.Select(height => String.Format("{0:0}%", height * 100)).ToArray())); - dropDownMenu.AddItem(new GUIContent(menuText), false, OnResetLODMenuClick, importer); - } - dropDownMenu.DropDown(buttonRect); - } - EditorGUILayout.EndHorizontal(); - } - var area = GUILayoutUtility.GetRect(0, LODGroupGUI.kSliderBarHeight, GUILayout.ExpandWidth(true)); - if (Event.current.type == EventType.Repaint) - LODGroupGUI.DrawMixedValueLODSlider(area); - } - - EditorGUILayout.Space(); - } - - private readonly int m_LODSliderId = "LODSliderIDHash".GetHashCode(); - private void DrawLODLevelSlider(Rect sliderPosition, List lods) - { - int sliderId = GUIUtility.GetControlID(m_LODSliderId, FocusType.Passive); - Event evt = Event.current; - - switch (evt.GetTypeForControl(sliderId)) - { - case EventType.Repaint: - { - LODGroupGUI.DrawLODSlider(sliderPosition, lods, m_SelectedLODRange); - break; - } - case EventType.MouseDown: - { - // Slightly grow position on the x because edge buttons overflow by 5 pixels - var barPosition = sliderPosition; - barPosition.x -= 5; - barPosition.width += 10; - - if (barPosition.Contains(evt.mousePosition)) - { - evt.Use(); - GUIUtility.hotControl = sliderId; - - // Check for button click - var clickedButton = false; - - // case:464019 have to re-sort the LOD array for these buttons to get the overlaps in the right order... - var lodsLeft = lods.Where(lod => lod.ScreenPercent > 0.5f).OrderByDescending(x => x.LODLevel); - var lodsRight = lods.Where(lod => lod.ScreenPercent <= 0.5f).OrderBy(x => x.LODLevel); - - var lodButtonOrder = new List(); - lodButtonOrder.AddRange(lodsLeft); - lodButtonOrder.AddRange(lodsRight); - - foreach (var lod in lodButtonOrder) - { - if (lod.m_ButtonPosition.Contains(evt.mousePosition)) - { - m_SelectedLODSlider = lod.LODLevel; - m_SelectedLODRange = lod.LODLevel; - clickedButton = true; - break; - } - } - - if (!clickedButton) - { - // Check for range click - foreach (var lod in lodButtonOrder) - { - if (lod.m_RangePosition.Contains(evt.mousePosition)) - { - m_SelectedLODSlider = -1; - m_SelectedLODRange = lod.LODLevel; - break; - } - } - } - } - break; - } - case EventType.MouseUp: - { - if (GUIUtility.hotControl == sliderId) - { - GUIUtility.hotControl = 0; - evt.Use(); - } - break; - } - case EventType.MouseDrag: - { - if (GUIUtility.hotControl == sliderId && m_SelectedLODSlider >= 0 && lods[m_SelectedLODSlider] != null) - { - evt.Use(); - - var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition); - // Bias by 0.1% so that there is no skipping when sliding - LODGroupGUI.SetSelectedLODLevelPercentage(cameraPercent - 0.001f, m_SelectedLODSlider, lods); - m_LODSettings.GetArrayElementAtIndex(m_SelectedLODSlider).FindPropertyRelative("height").floatValue = lods[m_SelectedLODSlider].RawScreenPercent; - } - break; - } - } - } - - private void OnResetLODMenuClick(object userData) - { - var toHeights = (userData as SpeedTreeImporter).LODHeights; - for (int i = 0; i < toHeights.Length; ++i) - m_LODSettings.GetArrayElementAtIndex(i).FindPropertyRelative("height").floatValue = toHeights[i]; - } - } -} diff --git a/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs b/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs deleted file mode 100644 index 6e545dea41..0000000000 --- a/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs +++ /dev/null @@ -1,520 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEditor.Modules; -using UnityEngine; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System; - -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [System.Serializable] - internal class TextureImportPlatformSettings - { - [SerializeField] private TextureImporterPlatformSettings m_PlatformSettings = new TextureImporterPlatformSettings(); - public TextureImporterPlatformSettings platformTextureSettings { get { return m_PlatformSettings; } } - - public string name { get { return m_PlatformSettings.name; } } - - // Is Overridden - [SerializeField] private bool m_OverriddenIsDifferent = false; - public bool overridden { get { return m_PlatformSettings.overridden; } } - public bool overriddenIsDifferent { get { return m_OverriddenIsDifferent; } } - public bool allAreOverridden { get { return isDefault || (overridden && !m_OverriddenIsDifferent); } } - public void SetOverriddenForAll(bool overridden) - { - m_PlatformSettings.overridden = overridden; - m_OverriddenIsDifferent = false; - SetChanged(); - } - - // Maximum texture size - [SerializeField] private bool m_MaxTextureSizeIsDifferent = false; - public int maxTextureSize { get { return m_PlatformSettings.maxTextureSize; } } - public bool maxTextureSizeIsDifferent { get { return m_MaxTextureSizeIsDifferent; } } - public void SetMaxTextureSizeForAll(int maxTextureSize) - { - Debug.Assert(allAreOverridden, "Attempting to set max texture size for all platforms even though settings are not overridden for all platforms."); - m_PlatformSettings.maxTextureSize = maxTextureSize; - m_MaxTextureSizeIsDifferent = false; - SetChanged(); - } - - // Resize Algorithm - [SerializeField] - private bool m_ResizeAlgorithmIsDifferent = false; - public TextureResizeAlgorithm resizeAlgorithm { get { return m_PlatformSettings.resizeAlgorithm; } } - public bool resizeAlgorithmIsDifferent { get { return m_ResizeAlgorithmIsDifferent; } } - public void SetResizeAlgorithmForAll(TextureResizeAlgorithm algorithm) - { - Debug.Assert(allAreOverridden, "Attempting to set resize algorithm for all platforms even though settings are not overridden for all platforms."); - m_PlatformSettings.resizeAlgorithm = algorithm; - m_ResizeAlgorithmIsDifferent = false; - SetChanged(); - } - - // Texture compression - [SerializeField] private bool m_TextureCompressionIsDifferent = false; - public TextureImporterCompression textureCompression { get { return m_PlatformSettings.textureCompression; } } - public bool textureCompressionIsDifferent { get { return m_TextureCompressionIsDifferent; } } - public void SetTextureCompressionForAll(TextureImporterCompression textureCompression) - { - Debug.Assert(allAreOverridden, "Attempting to set texture compression for all platforms even though settings are not overridden for all platforms."); - m_PlatformSettings.textureCompression = textureCompression; - m_TextureCompressionIsDifferent = false; - m_HasChanged = true; - } - - // Compression rate - [SerializeField] private bool m_CompressionQualityIsDifferent = false; - public int compressionQuality { get { return m_PlatformSettings.compressionQuality; } } - public bool compressionQualityIsDifferent { get { return m_CompressionQualityIsDifferent; } } - public void SetCompressionQualityForAll(int quality) - { - Debug.Assert(allAreOverridden, "Attempting to set texture compression quality for all platforms even though settings are not overridden for all platforms."); - m_PlatformSettings.compressionQuality = quality; - m_CompressionQualityIsDifferent = false; - SetChanged(); - } - - // Crunched compression - [SerializeField] private bool m_CrunchedCompressionIsDifferent = false; - public bool crunchedCompression { get { return m_PlatformSettings.crunchedCompression; } } - public bool crunchedCompressionIsDifferent { get { return m_CrunchedCompressionIsDifferent; } } - public void SetCrunchedCompressionForAll(bool crunched) - { - Debug.Assert(allAreOverridden, "Attempting to set texture crunched compression for all platforms even though settings are not overridden for all platforms."); - m_PlatformSettings.crunchedCompression = crunched; - m_CrunchedCompressionIsDifferent = false; - SetChanged(); - } - - // Texture format - [SerializeField] private bool m_TextureFormatIsDifferent = false; - public TextureImporterFormat format { get { return m_PlatformSettings.format; } } - public bool textureFormatIsDifferent { get { return m_TextureFormatIsDifferent; } } - public void SetTextureFormatForAll(TextureImporterFormat format) - { - Debug.Assert(allAreOverridden, "Attempting to set texture format for all platforms even though settings are not overridden for all platforms."); - m_PlatformSettings.format = format; - m_TextureFormatIsDifferent = false; - SetChanged(); - } - - // Alpha splitting - [SerializeField] - private bool m_AlphaSplitIsDifferent = false; - public bool allowsAlphaSplitting { get { return m_PlatformSettings.allowsAlphaSplitting; } } - public bool allowsAlphaSplitIsDifferent { get { return m_AlphaSplitIsDifferent; } } - public void SetAllowsAlphaSplitForAll(bool value) - { - Debug.Assert(allAreOverridden, "Attempting to set alpha splitting for all platforms even though settings are not overridden for all platforms."); - m_PlatformSettings.allowsAlphaSplitting = value; - m_AlphaSplitIsDifferent = false; - SetChanged(); - } - - // Android fallback format in case ETC2 is not supported - [SerializeField] - private bool m_AndroidETC2FallbackOverrideIsDifferent = false; - public AndroidETC2FallbackOverride androidETC2FallbackOverride { get { return m_PlatformSettings.androidETC2FallbackOverride; } } - public bool androidETC2FallbackOverrideIsDifferent { get { return m_AndroidETC2FallbackOverrideIsDifferent; } } - public void SetAndroidETC2FallbackOverrideForAll(AndroidETC2FallbackOverride value) - { - Debug.Assert(allAreOverridden, "Attempting to set android ETC2 fallback format for all platforms even though settings are not overridden for all platforms."); - m_PlatformSettings.androidETC2FallbackOverride = value; - m_AndroidETC2FallbackOverrideIsDifferent = false; - SetChanged(); - } - - [SerializeField] public BuildTarget m_Target; - [SerializeField] TextureImporter[] m_Importers; - public TextureImporter[] importers { get { return m_Importers; } } - - [SerializeField] bool m_HasChanged = false; - [SerializeField] TextureImporterInspector m_Inspector; - public bool isDefault { get { return name == TextureImporterInspector.s_DefaultPlatformName; } } - - public TextureImportPlatformSettings(string name, BuildTarget target, TextureImporterInspector inspector) - { - m_PlatformSettings.name = name; - - m_Target = target; - m_Inspector = inspector; - m_PlatformSettings.overridden = false; - m_Importers = inspector.targets.Select(x => x as TextureImporter).ToArray(); - for (int i = 0; i < importers.Length; i++) - { - TextureImporter imp = importers[i]; - TextureImporterPlatformSettings curPlatformSettings = imp.GetPlatformTextureSettings(name); - - if (i == 0) - { - m_PlatformSettings = curPlatformSettings; - } - else - { - if (curPlatformSettings.overridden != m_PlatformSettings.overridden) - m_OverriddenIsDifferent = true; - if (curPlatformSettings.format != m_PlatformSettings.format) - m_TextureFormatIsDifferent = true; - if (curPlatformSettings.maxTextureSize != m_PlatformSettings.maxTextureSize) - m_MaxTextureSizeIsDifferent = true; - if (curPlatformSettings.resizeAlgorithm != m_PlatformSettings.resizeAlgorithm) - m_ResizeAlgorithmIsDifferent = true; - if (curPlatformSettings.textureCompression != m_PlatformSettings.textureCompression) - m_TextureCompressionIsDifferent = true; - if (curPlatformSettings.compressionQuality != m_PlatformSettings.compressionQuality) - m_CompressionQualityIsDifferent = true; - if (curPlatformSettings.crunchedCompression != m_PlatformSettings.crunchedCompression) - m_CrunchedCompressionIsDifferent = true; - if (curPlatformSettings.allowsAlphaSplitting != m_PlatformSettings.allowsAlphaSplitting) - m_AlphaSplitIsDifferent = true; - if (curPlatformSettings.androidETC2FallbackOverride != m_PlatformSettings.androidETC2FallbackOverride) - m_AndroidETC2FallbackOverrideIsDifferent = true; - } - } - - Sync(); - } - - public bool SupportsFormat(TextureImporterFormat format, TextureImporter importer) - { - TextureImporterSettings settings = GetSettings(importer); - int[] testValues; - switch (m_Target) - { - case BuildTarget.PSP2: - testValues = kTextureFormatsValuePSP2; - break; - case BuildTarget.Switch: - testValues = kTextureFormatsValueSwitch; - break; - // on gles mobile targets we use rgb normal maps, so we can use whatever format we want - case BuildTarget.iOS: - case BuildTarget.tvOS: - testValues = kTextureFormatsValueApplePVR; - break; - case BuildTarget.Android: - testValues = kTextureFormatsValueAndroid; - break; - case BuildTarget.Tizen: - testValues = kTextureFormatsValueTizen; - break; - - default: - testValues = settings.textureType == TextureImporterType.NormalMap ? kNormalFormatsValueDefault : kTextureFormatsValueDefault; - break; - } - - if ((testValues as IList).Contains((int)format)) - return true; - return false; - } - - public TextureImporterSettings GetSettings(TextureImporter importer) - { - TextureImporterSettings settings = new TextureImporterSettings(); - // Get import settings for this importer - importer.ReadTextureSettings(settings); - // Get settings that have been changed in the inspector - m_Inspector.GetSerializedPropertySettings(settings); - return settings; - } - - public virtual void SetChanged() - { - m_HasChanged = true; - } - - public virtual bool HasChanged() - { - return m_HasChanged; - } - - public void Sync() - { - // Use settings from default if any of the targets are not overridden - if (!isDefault && (!overridden || m_OverriddenIsDifferent)) - { - TextureImportPlatformSettings defaultSettings = m_Inspector.m_PlatformSettings[0]; - m_PlatformSettings.maxTextureSize = defaultSettings.maxTextureSize; - m_MaxTextureSizeIsDifferent = defaultSettings.m_MaxTextureSizeIsDifferent; - m_PlatformSettings.resizeAlgorithm = defaultSettings.resizeAlgorithm; - m_ResizeAlgorithmIsDifferent = defaultSettings.m_ResizeAlgorithmIsDifferent; - m_PlatformSettings.textureCompression = defaultSettings.textureCompression; - m_TextureCompressionIsDifferent = defaultSettings.m_TextureCompressionIsDifferent; - m_PlatformSettings.format = defaultSettings.format; - m_TextureFormatIsDifferent = defaultSettings.m_TextureFormatIsDifferent; - m_PlatformSettings.compressionQuality = defaultSettings.compressionQuality; - m_CompressionQualityIsDifferent = defaultSettings.m_CompressionQualityIsDifferent; - m_PlatformSettings.crunchedCompression = defaultSettings.crunchedCompression; - m_CrunchedCompressionIsDifferent = defaultSettings.m_CrunchedCompressionIsDifferent; - m_PlatformSettings.allowsAlphaSplitting = defaultSettings.allowsAlphaSplitting; - m_AlphaSplitIsDifferent = defaultSettings.m_AlphaSplitIsDifferent; - m_AndroidETC2FallbackOverrideIsDifferent = defaultSettings.m_AndroidETC2FallbackOverrideIsDifferent; - } - - if ((overridden || m_OverriddenIsDifferent) && m_PlatformSettings.format < 0) - { - m_PlatformSettings.format = TextureImporter.FormatFromTextureParameters(GetSettings(importers[0]), - m_PlatformSettings, - importers[0].DoesSourceTextureHaveAlpha(), - importers[0].IsSourceTextureHDR(), - m_Target - ); - m_TextureFormatIsDifferent = false; - - for (int i = 1; i < importers.Length; i++) - { - TextureImporter imp = importers[i]; - TextureImporterSettings settings = GetSettings(imp); - - TextureImporterFormat format = TextureImporter.FormatFromTextureParameters(settings, - m_PlatformSettings, - imp.DoesSourceTextureHaveAlpha(), - imp.IsSourceTextureHDR(), - m_Target - ); - if (format != m_PlatformSettings.format) - m_TextureFormatIsDifferent = true; - } - } - } - - private bool GetOverridden(TextureImporter importer) - { - if (!m_OverriddenIsDifferent) - return overridden; - return importer.GetPlatformTextureSettings(name).overridden; - } - - public void Apply() - { - for (int i = 0; i < importers.Length; i++) - { - TextureImporter imp = importers[i]; - - TextureImporterPlatformSettings platformSettings = imp.GetPlatformTextureSettings(name); - - // Overwrite with inspector properties if same for all targets - if (!m_OverriddenIsDifferent) - platformSettings.overridden = m_PlatformSettings.overridden; - if (!m_TextureFormatIsDifferent) - platformSettings.format = m_PlatformSettings.format; - if (!m_MaxTextureSizeIsDifferent) - platformSettings.maxTextureSize = m_PlatformSettings.maxTextureSize; - if (!m_ResizeAlgorithmIsDifferent) - platformSettings.resizeAlgorithm = m_PlatformSettings.resizeAlgorithm; - if (!m_TextureCompressionIsDifferent) - platformSettings.textureCompression = m_PlatformSettings.textureCompression; - if (!m_CompressionQualityIsDifferent) - platformSettings.compressionQuality = m_PlatformSettings.compressionQuality; - if (!m_CrunchedCompressionIsDifferent) - platformSettings.crunchedCompression = m_PlatformSettings.crunchedCompression; - if (!m_AlphaSplitIsDifferent) - platformSettings.allowsAlphaSplitting = m_PlatformSettings.allowsAlphaSplitting; - if (!m_AndroidETC2FallbackOverrideIsDifferent) - platformSettings.androidETC2FallbackOverride = m_PlatformSettings.androidETC2FallbackOverride; - - imp.SetPlatformTextureSettings(platformSettings); - } - } - - public static readonly int[] kTextureFormatsValuePSP2 = - { - (int)TextureImporterFormat.DXT1, - (int)TextureImporterFormat.DXT5, - (int)TextureImporterFormat.RGB16, - (int)TextureImporterFormat.RGB24, - (int)TextureImporterFormat.RGBA16, - (int)TextureImporterFormat.RGBA32, - (int)TextureImporterFormat.Alpha8, - (int)TextureImporterFormat.RGBAHalf, - }; - - public static readonly int[] kTextureFormatsValueSwitch = - { - (int)TextureImporterFormat.DXT1, - (int)TextureImporterFormat.DXT5, - (int)TextureImporterFormat.DXT1Crunched, - (int)TextureImporterFormat.DXT5Crunched, - (int)TextureImporterFormat.RGB16, - (int)TextureImporterFormat.RGB24, - (int)TextureImporterFormat.Alpha8, - (int)TextureImporterFormat.ARGB16, - (int)TextureImporterFormat.RGBA32, - (int)TextureImporterFormat.RGBAHalf, - (int)TextureImporterFormat.BC4, - (int)TextureImporterFormat.BC5, - (int)TextureImporterFormat.BC6H, - (int)TextureImporterFormat.BC7, - - (int)TextureImporterFormat.ASTC_RGB_4x4, - (int)TextureImporterFormat.ASTC_RGB_5x5, - (int)TextureImporterFormat.ASTC_RGB_6x6, - (int)TextureImporterFormat.ASTC_RGB_8x8, - (int)TextureImporterFormat.ASTC_RGB_10x10, - (int)TextureImporterFormat.ASTC_RGB_12x12, - (int)TextureImporterFormat.ASTC_RGBA_4x4, - (int)TextureImporterFormat.ASTC_RGBA_5x5, - (int)TextureImporterFormat.ASTC_RGBA_6x6, - (int)TextureImporterFormat.ASTC_RGBA_8x8, - (int)TextureImporterFormat.ASTC_RGBA_10x10, - (int)TextureImporterFormat.ASTC_RGBA_12x12, - }; - - public static readonly int[] kTextureFormatsValueApplePVR = - { - (int)TextureImporterFormat.PVRTC_RGB2, - (int)TextureImporterFormat.PVRTC_RGBA2, - (int)TextureImporterFormat.PVRTC_RGB4, - (int)TextureImporterFormat.PVRTC_RGBA4, - - (int)TextureImporterFormat.ASTC_RGB_4x4, - (int)TextureImporterFormat.ASTC_RGB_5x5, - (int)TextureImporterFormat.ASTC_RGB_6x6, - (int)TextureImporterFormat.ASTC_RGB_8x8, - (int)TextureImporterFormat.ASTC_RGB_10x10, - (int)TextureImporterFormat.ASTC_RGB_12x12, - (int)TextureImporterFormat.ASTC_RGBA_4x4, - (int)TextureImporterFormat.ASTC_RGBA_5x5, - (int)TextureImporterFormat.ASTC_RGBA_6x6, - (int)TextureImporterFormat.ASTC_RGBA_8x8, - (int)TextureImporterFormat.ASTC_RGBA_10x10, - (int)TextureImporterFormat.ASTC_RGBA_12x12, - - (int)TextureImporterFormat.ETC_RGB4, - (int)TextureImporterFormat.ETC_RGB4Crunched, - (int)TextureImporterFormat.ETC2_RGB4, - (int)TextureImporterFormat.ETC2_RGB4_PUNCHTHROUGH_ALPHA, - (int)TextureImporterFormat.ETC2_RGBA8, - (int)TextureImporterFormat.ETC2_RGBA8Crunched, - - (int)TextureImporterFormat.EAC_R, - (int)TextureImporterFormat.EAC_RG, - - (int)TextureImporterFormat.RGB16, - (int)TextureImporterFormat.RGB24, - (int)TextureImporterFormat.Alpha8, - (int)TextureImporterFormat.RGBA16, - (int)TextureImporterFormat.RGBA32, - (int)TextureImporterFormat.RGBAHalf, - }; - - public static readonly int[] kTextureFormatsValueAndroid = - { - (int)TextureImporterFormat.DXT1, - (int)TextureImporterFormat.DXT1Crunched, - (int)TextureImporterFormat.DXT5, - (int)TextureImporterFormat.DXT5Crunched, - - (int)TextureImporterFormat.ETC_RGB4, - (int)TextureImporterFormat.ETC_RGB4Crunched, - (int)TextureImporterFormat.ETC2_RGB4, - (int)TextureImporterFormat.ETC2_RGB4_PUNCHTHROUGH_ALPHA, - (int)TextureImporterFormat.ETC2_RGBA8, - (int)TextureImporterFormat.ETC2_RGBA8Crunched, - - (int)TextureImporterFormat.EAC_R, - (int)TextureImporterFormat.EAC_RG, - - (int)TextureImporterFormat.PVRTC_RGB2, - (int)TextureImporterFormat.PVRTC_RGBA2, - (int)TextureImporterFormat.PVRTC_RGB4, - (int)TextureImporterFormat.PVRTC_RGBA4, - - (int)TextureImporterFormat.ASTC_RGB_4x4, - (int)TextureImporterFormat.ASTC_RGB_5x5, - (int)TextureImporterFormat.ASTC_RGB_6x6, - (int)TextureImporterFormat.ASTC_RGB_8x8, - (int)TextureImporterFormat.ASTC_RGB_10x10, - (int)TextureImporterFormat.ASTC_RGB_12x12, - (int)TextureImporterFormat.ASTC_RGBA_4x4, - (int)TextureImporterFormat.ASTC_RGBA_5x5, - (int)TextureImporterFormat.ASTC_RGBA_6x6, - (int)TextureImporterFormat.ASTC_RGBA_8x8, - (int)TextureImporterFormat.ASTC_RGBA_10x10, - (int)TextureImporterFormat.ASTC_RGBA_12x12, - - (int)TextureImporterFormat.RGB16, - (int)TextureImporterFormat.RGB24, - (int)TextureImporterFormat.Alpha8, - (int)TextureImporterFormat.RGBA16, - (int)TextureImporterFormat.RGBA32, - (int)TextureImporterFormat.RGBAHalf, - }; - - public static readonly int[] kTextureFormatsValueTizen = - { - (int)TextureImporterFormat.ETC_RGB4, - - (int)TextureImporterFormat.RGB16, - (int)TextureImporterFormat.RGB24, - (int)TextureImporterFormat.Alpha8, - (int)TextureImporterFormat.RGBA16, - (int)TextureImporterFormat.RGBA32, - }; - - public static readonly int[] kTextureFormatsValueWebGL = - { - (int)TextureImporterFormat.DXT1, - (int)TextureImporterFormat.DXT5, - (int)TextureImporterFormat.DXT1Crunched, - (int)TextureImporterFormat.DXT5Crunched, - (int)TextureImporterFormat.RGB16, - (int)TextureImporterFormat.RGB24, - (int)TextureImporterFormat.Alpha8, - (int)TextureImporterFormat.ARGB16, - (int)TextureImporterFormat.RGBA32 - }; - - public static readonly int[] kNormalFormatsValueDefault = - { - (int)TextureImporterFormat.BC5, - (int)TextureImporterFormat.BC7, - (int)TextureImporterFormat.DXT5, - (int)TextureImporterFormat.DXT5Crunched, - (int)TextureImporterFormat.ARGB16, - (int)TextureImporterFormat.RGBA32, - }; - public static readonly int[] kTextureFormatsValueDefault = - { - (int)TextureImporterFormat.DXT1, - (int)TextureImporterFormat.DXT5, - (int)TextureImporterFormat.DXT1Crunched, - (int)TextureImporterFormat.DXT5Crunched, - (int)TextureImporterFormat.RGB16, - (int)TextureImporterFormat.RGB24, - (int)TextureImporterFormat.Alpha8, - (int)TextureImporterFormat.ARGB16, - (int)TextureImporterFormat.RGBA32, - (int)TextureImporterFormat.RGBAHalf, - (int)TextureImporterFormat.BC4, - (int)TextureImporterFormat.BC5, - (int)TextureImporterFormat.BC6H, - (int)TextureImporterFormat.BC7, - }; - public static readonly int[] kTextureFormatsValueSingleChannel = - { - (int)TextureImporterFormat.Alpha8, - (int)TextureImporterFormat.R8, - (int)TextureImporterFormat.BC4, - (int)TextureImporterFormat.EAC_R, - }; - - public static readonly int[] kAndroidETC2FallbackOverrideValues = - { - (int)AndroidETC2FallbackOverride.UseBuildSettings, - (int)AndroidETC2FallbackOverride.Quality32Bit, - (int)AndroidETC2FallbackOverride.Quality16Bit, - (int)AndroidETC2FallbackOverride.Quality32BitDownscaled, - }; - } -} diff --git a/Editor/Mono/ImportSettings/TextureImporterInspector.cs b/Editor/Mono/ImportSettings/TextureImporterInspector.cs deleted file mode 100644 index 5637be2bb9..0000000000 --- a/Editor/Mono/ImportSettings/TextureImporterInspector.cs +++ /dev/null @@ -1,1635 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEditor.Modules; -using UnityEngine; -using UnityEditor.Build; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System; -using UnityEditor.Experimental.AssetImporters; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - // Cubemap convolution mode - public enum TextureImporterCubemapConvolution - { - // Do not convolve cubemap (default). - None = 0, - // Convolve for specular reflections with varying roughness. - Specular = 1, - // Convolve for diffuse-only reflection (irradiance cubemap). - Diffuse = 2 - }; - - // Kept for backward compatibility - public enum TextureImporterRGBMMode - { - Auto = 0, - On = 1, - Off = 2, - Encoded = 3, - } - - [CustomEditor(typeof(TextureImporter))] - [CanEditMultipleObjects] - internal class TextureImporterInspector : AssetImporterEditor - { - public static string s_DefaultPlatformName = "DefaultTexturePlatform"; - - [Flags] - private enum TextureInspectorGUIElement - { - None = 0, - PowerOfTwo = 1 << 0, - Readable = 1 << 1, - AlphaHandling = 1 << 2, - ColorSpace = 1 << 3, - MipMaps = 1 << 4, - NormalMap = 1 << 5, - Sprite = 1 << 6, - Cookie = 1 << 7, - CubeMapConvolution = 1 << 8, - CubeMapping = 1 << 9, - SingleChannelComponent = 1 << 11, - } - - private struct TextureInspectorTypeGUIProperties - { - public TextureInspectorGUIElement commonElements; - public TextureInspectorGUIElement advancedElements; - public TextureImporterShape shapeCaps; - - public TextureInspectorTypeGUIProperties(TextureInspectorGUIElement _commonElements, TextureInspectorGUIElement _advancedElements, TextureImporterShape _shapeCaps) - { - commonElements = _commonElements; - advancedElements = _advancedElements; - shapeCaps = _shapeCaps; - } - } - - SerializedProperty m_TextureType; - internal TextureImporterType textureType - { - get - { - if (m_TextureType.hasMultipleDifferentValues) - return (TextureImporterType)0; - return (TextureImporterType)(m_TextureType.intValue); - } - } - - private delegate void GUIMethod(TextureInspectorGUIElement guiElements); - private Dictionary m_GUIElementMethods = new Dictionary(); - - - internal bool textureTypeHasMultipleDifferentValues - { - get { return m_TextureType.hasMultipleDifferentValues; } - } - - public new void OnDisable() - { - base.OnDisable(); - - EditorPrefs.SetBool("TextureImporterShowAdvanced", m_ShowAdvanced); - } - - // Don't show the imported texture as a separate editor - public override bool showImportedObject { get { return false; } } - - public static bool IsCompressedDXTTextureFormat(TextureImporterFormat format) - { - return (format == TextureImporterFormat.DXT1 || format == TextureImporterFormat.DXT5); - } - - internal static bool IsGLESMobileTargetPlatform(BuildTarget target) - { - return target == BuildTarget.iOS || target == BuildTarget.tvOS || target == BuildTarget.Android || target == BuildTarget.Tizen; - } - - // Which platforms should we display? - // For each of these, what are the formats etc. to display? - [SerializeField] - internal List m_PlatformSettings; - - - internal static int[] s_TextureFormatsValueAll; - - internal static int[] TextureFormatsValueAll - { - get - { - if (s_TextureFormatsValueAll != null) - return s_TextureFormatsValueAll; - - bool requireETC = false; - bool requirePVRTC = false; - bool requireETC2 = false; - bool requireASTC = false; - - // Build available formats based on available platforms - BuildPlatform[] validPlatforms = GetBuildPlayerValidPlatforms(); - foreach (BuildPlatform platform in validPlatforms) - { - switch (platform.defaultTarget) - { - case BuildTarget.Android: - requirePVRTC = true; - requireETC = true; - requireETC2 = true; - requireASTC = true; - break; - case BuildTarget.iOS: - requirePVRTC = true; - requireETC = true; - requireETC2 = true; - break; - case BuildTarget.tvOS: - requirePVRTC = true; - requireASTC = true; - break; - case BuildTarget.Tizen: - requireETC = true; - break; - } - } - List formatValues = new List(); - - formatValues.AddRange(new[] { - (int)TextureImporterFormat.DXT1, - (int)TextureImporterFormat.DXT5, - }); - - if (requireETC) - formatValues.Add((int)TextureImporterFormat.ETC_RGB4); - - if (requirePVRTC) - formatValues.AddRange(new[] { - (int)TextureImporterFormat.PVRTC_RGB2, - (int)TextureImporterFormat.PVRTC_RGBA2, - (int)TextureImporterFormat.PVRTC_RGB4, - (int)TextureImporterFormat.PVRTC_RGBA4 - }); - - if (requireETC2) - formatValues.AddRange(new[] { - (int)TextureImporterFormat.ETC2_RGB4, - (int)TextureImporterFormat.ETC2_RGB4_PUNCHTHROUGH_ALPHA, - (int)TextureImporterFormat.ETC2_RGBA8 - }); - - if (requireASTC) - formatValues.AddRange(new[] { - (int)TextureImporterFormat.ASTC_RGB_4x4, - (int)TextureImporterFormat.ASTC_RGB_5x5, - (int)TextureImporterFormat.ASTC_RGB_6x6, - (int)TextureImporterFormat.ASTC_RGB_8x8, - (int)TextureImporterFormat.ASTC_RGB_10x10, - (int)TextureImporterFormat.ASTC_RGB_12x12, - (int)TextureImporterFormat.ASTC_RGBA_4x4, - (int)TextureImporterFormat.ASTC_RGBA_5x5, - (int)TextureImporterFormat.ASTC_RGBA_6x6, - (int)TextureImporterFormat.ASTC_RGBA_8x8, - (int)TextureImporterFormat.ASTC_RGBA_10x10, - (int)TextureImporterFormat.ASTC_RGBA_12x12 - }); - - - formatValues.AddRange(new[] { - (int)TextureImporterFormat.RGB16, - (int)TextureImporterFormat.ARGB16, - (int)TextureImporterFormat.RGBA16, - - (int)TextureImporterFormat.RGB24, - (int)TextureImporterFormat.Alpha8, - (int)TextureImporterFormat.ARGB32, - (int)TextureImporterFormat.RGBA32, - (int)TextureImporterFormat.RGBAHalf, - (int)TextureImporterFormat.BC6H, - (int)TextureImporterFormat.BC7, - - (int)TextureImporterFormat.DXT1Crunched, - (int)TextureImporterFormat.DXT5Crunched, - (int)TextureImporterFormat.ETC_RGB4Crunched, - (int)TextureImporterFormat.ETC2_RGBA8Crunched, - }); - - s_TextureFormatsValueAll = formatValues.ToArray(); - return s_TextureFormatsValueAll; - } - } - - internal static int[] s_NormalFormatsValueAll; - internal static int[] NormalFormatsValueAll - { - get - { - bool requireETC = false; - bool requirePVRTC = false; - bool requireETC2 = false; - bool requireASTC = false; - - // Build available normals formats based on available platforms - BuildPlatform[] validPlatforms = GetBuildPlayerValidPlatforms(); - foreach (BuildPlatform platform in validPlatforms) - { - switch (platform.defaultTarget) - { - case BuildTarget.Android: - requirePVRTC = true; - requireETC = true; - requireETC2 = true; - requireASTC = true; - break; - case BuildTarget.iOS: - case BuildTarget.tvOS: - requirePVRTC = true; - requireETC = true; - requireETC2 = true; - break; - case BuildTarget.Tizen: - requireETC = true; - break; - } - } - List formatValues = new List(); - - formatValues.AddRange(new[] { - (int)TextureImporterFormat.DXT5 - }); - - if (requirePVRTC) - formatValues.AddRange(new[] { - (int)TextureImporterFormat.PVRTC_RGB2, - (int)TextureImporterFormat.PVRTC_RGBA2, - (int)TextureImporterFormat.PVRTC_RGB4, - (int)TextureImporterFormat.PVRTC_RGBA4, - }); - - if (requireETC) - formatValues.AddRange(new int[] { - (int)TextureImporterFormat.ETC_RGB4, - }); - - if (requireETC2) - formatValues.AddRange(new[] { - (int)TextureImporterFormat.ETC2_RGB4, - (int)TextureImporterFormat.ETC2_RGB4_PUNCHTHROUGH_ALPHA, - (int)TextureImporterFormat.ETC2_RGBA8 - }); - - if (requireASTC) - formatValues.AddRange(new[] { - (int)TextureImporterFormat.ASTC_RGB_4x4, - (int)TextureImporterFormat.ASTC_RGB_5x5, - (int)TextureImporterFormat.ASTC_RGB_6x6, - (int)TextureImporterFormat.ASTC_RGB_8x8, - (int)TextureImporterFormat.ASTC_RGB_10x10, - (int)TextureImporterFormat.ASTC_RGB_12x12, - (int)TextureImporterFormat.ASTC_RGBA_4x4, - (int)TextureImporterFormat.ASTC_RGBA_5x5, - (int)TextureImporterFormat.ASTC_RGBA_6x6, - (int)TextureImporterFormat.ASTC_RGBA_8x8, - (int)TextureImporterFormat.ASTC_RGBA_10x10, - (int)TextureImporterFormat.ASTC_RGBA_12x12 - }); - - formatValues.AddRange(new[] { - (int)TextureImporterFormat.ARGB16, - (int)TextureImporterFormat.RGBA16, - - (int)TextureImporterFormat.RGBA32, - - (int)TextureImporterFormat.DXT5Crunched - }); - - s_NormalFormatsValueAll = formatValues.ToArray(); - - return s_NormalFormatsValueAll; - } - } - - internal static readonly TextureImporterFormat[] kFormatsWithCompressionSettings = - { - TextureImporterFormat.DXT1Crunched, - TextureImporterFormat.DXT5Crunched, - TextureImporterFormat.ETC_RGB4Crunched, - TextureImporterFormat.ETC2_RGBA8Crunched, - TextureImporterFormat.PVRTC_RGB2, - TextureImporterFormat.PVRTC_RGB4, - TextureImporterFormat.PVRTC_RGBA2, - TextureImporterFormat.PVRTC_RGBA4, - TextureImporterFormat.ETC_RGB4, - TextureImporterFormat.ETC2_RGB4, - TextureImporterFormat.ETC2_RGB4_PUNCHTHROUGH_ALPHA, - TextureImporterFormat.ETC2_RGBA8, - TextureImporterFormat.ASTC_RGB_4x4, - TextureImporterFormat.ASTC_RGB_5x5, - TextureImporterFormat.ASTC_RGB_6x6, - TextureImporterFormat.ASTC_RGB_8x8, - TextureImporterFormat.ASTC_RGB_10x10, - TextureImporterFormat.ASTC_RGB_12x12, - TextureImporterFormat.ASTC_RGBA_4x4, - TextureImporterFormat.ASTC_RGBA_5x5, - TextureImporterFormat.ASTC_RGBA_6x6, - TextureImporterFormat.ASTC_RGBA_8x8, - TextureImporterFormat.ASTC_RGBA_10x10, - TextureImporterFormat.ASTC_RGBA_12x12 - }; - -#pragma warning disable 649 - internal static string[] s_TextureFormatStringsAll; - internal static string[] s_TextureFormatStringsPSP2; - internal static string[] s_TextureFormatStringsSwitch; - internal static string[] s_TextureFormatStringsWebGL; - internal static string[] s_TextureFormatStringsApplePVR; - internal static string[] s_TextureFormatStringsAndroid; - internal static string[] s_TextureFormatStringsTizen; - internal static string[] s_TextureFormatStringsSingleChannel; - internal static string[] s_TextureFormatStringsDefault; - internal static string[] s_NormalFormatStringsDefault; - - enum CookieMode - { - Spot = 0, Directional = 1, Point = 2 - } - - readonly AnimBool m_ShowBumpGenerationSettings = new AnimBool(); - readonly AnimBool m_ShowCubeMapSettings = new AnimBool(); - readonly AnimBool m_ShowGenericSpriteSettings = new AnimBool(); - readonly AnimBool m_ShowMipMapSettings = new AnimBool(); - readonly AnimBool m_ShowSpriteMeshTypeOption = new AnimBool(); - readonly GUIContent m_EmptyContent = new GUIContent(" "); - - readonly int[] m_FilterModeOptions = (int[])(Enum.GetValues(typeof(FilterMode))); - - string m_ImportWarning = null; - private void UpdateImportWarning() - { - TextureImporter importer = target as TextureImporter; - m_ImportWarning = importer ? importer.GetImportWarnings() : null; - } - - internal class Styles - { - public readonly GUIContent textureTypeTitle = EditorGUIUtility.TrTextContent("Texture Type", "What will this texture be used for?"); - public readonly GUIContent[] textureTypeOptions = - { - EditorGUIUtility.TrTextContent("Default", "Texture is a normal image such as a diffuse texture or other."), - EditorGUIUtility.TrTextContent("Normal map", "Texture is a bump or normal map."), - EditorGUIUtility.TrTextContent("Editor GUI and Legacy GUI", "Texture is used for a GUI element."), - EditorGUIUtility.TrTextContent("Sprite (2D and UI)", "Texture is used for a sprite."), - EditorGUIUtility.TrTextContent("Cursor", "Texture is used for a cursor."), - EditorGUIUtility.TrTextContent("Cookie", "Texture is a cookie you put on a light."), - EditorGUIUtility.TrTextContent("Lightmap", "Texture is a lightmap."), - EditorGUIUtility.TrTextContent("Single Channel", "Texture is a one component texture."), - }; - public readonly int[] textureTypeValues = - { - (int)TextureImporterType.Default, - (int)TextureImporterType.NormalMap, - (int)TextureImporterType.GUI, - (int)TextureImporterType.Sprite, - (int)TextureImporterType.Cursor, - (int)TextureImporterType.Cookie, - (int)TextureImporterType.Lightmap, - (int)TextureImporterType.SingleChannel - }; - - public readonly GUIContent textureShape = EditorGUIUtility.TrTextContent("Texture Shape", "What shape is this texture?"); - private readonly GUIContent textureShape2D = EditorGUIUtility.TrTextContent("2D", "Texture is 2D."); - private readonly GUIContent textureShapeCube = EditorGUIUtility.TrTextContent("Cube", "Texture is a Cubemap."); - public readonly Dictionary textureShapeOptionsDictionnary = new Dictionary(); - public readonly Dictionary textureShapeValuesDictionnary = new Dictionary(); - - - public readonly GUIContent filterMode = EditorGUIUtility.TrTextContent("Filter Mode"); - public readonly GUIContent[] filterModeOptions = - { - EditorGUIUtility.TrTextContent("Point (no filter)"), - EditorGUIUtility.TrTextContent("Bilinear"), - EditorGUIUtility.TrTextContent("Trilinear") - }; - - public readonly GUIContent cookieType = EditorGUIUtility.TrTextContent("Light Type"); - public readonly GUIContent[] cookieOptions = - { - EditorGUIUtility.TrTextContent("Spotlight"), - EditorGUIUtility.TrTextContent("Directional"), - EditorGUIUtility.TrTextContent("Point"), - }; - public readonly GUIContent generateFromBump = EditorGUIUtility.TrTextContent("Create from Grayscale", "The grayscale of the image is used as a heightmap for generating the normal map."); - public readonly GUIContent bumpiness = EditorGUIUtility.TrTextContent("Bumpiness"); - public readonly GUIContent bumpFiltering = EditorGUIUtility.TrTextContent("Filtering"); - public readonly GUIContent[] bumpFilteringOptions = - { - EditorGUIUtility.TrTextContent("Sharp"), - EditorGUIUtility.TrTextContent("Smooth"), - }; - public readonly GUIContent cubemap = EditorGUIUtility.TrTextContent("Mapping"); - public readonly GUIContent[] cubemapOptions = - { - EditorGUIUtility.TrTextContent("Auto"), - 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."), - 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)."), - EditorGUIUtility.TrTextContent("Mirrored Ball (Spheremap)", "Texture contains an image of a mirrored ball.") - }; - public readonly int[] cubemapValues2 = - { - (int)TextureImporterGenerateCubemap.AutoCubemap, - (int)TextureImporterGenerateCubemap.FullCubemap, - (int)TextureImporterGenerateCubemap.Cylindrical, - (int)TextureImporterGenerateCubemap.Spheremap - }; - - public readonly GUIContent cubemapConvolution = EditorGUIUtility.TrTextContent("Convolution Type"); - public readonly GUIContent[] cubemapConvolutionOptions = - { - EditorGUIUtility.TrTextContent("None"), - EditorGUIUtility.TrTextContent("Specular (Glossy Reflection)", "Convolve cubemap for specular reflections with varying smoothness (Glossy Reflections)."), - EditorGUIUtility.TrTextContent("Diffuse (Irradiance)", "Convolve cubemap for diffuse-only reflection (Irradiance Cubemap).") - }; - public readonly int[] cubemapConvolutionValues = - { - (int)TextureImporterCubemapConvolution.None, - (int)TextureImporterCubemapConvolution.Specular, - (int)TextureImporterCubemapConvolution.Diffuse - }; - - public readonly GUIContent seamlessCubemap = EditorGUIUtility.TrTextContent("Fixup Edge Seams", "Enable if this texture is used for glossy reflections."); - public readonly GUIContent textureFormat = EditorGUIUtility.TrTextContent("Format"); - - public readonly GUIContent defaultPlatform = EditorGUIUtility.TrTextContent("Default"); - public readonly GUIContent mipmapFadeOutToggle = EditorGUIUtility.TrTextContent("Fadeout Mip Maps"); - public readonly GUIContent mipmapFadeOut = EditorGUIUtility.TrTextContent("Fade Range"); - public readonly GUIContent readWrite = EditorGUIUtility.TrTextContent("Read/Write Enabled", "Enable to be able to access the raw pixel data from code."); - - public readonly GUIContent alphaSource = EditorGUIUtility.TrTextContent("Alpha Source", "How is the alpha generated for the imported texture."); - public readonly GUIContent[] alphaSourceOptions = - { - EditorGUIUtility.TrTextContent("None", "No Alpha will be used."), - EditorGUIUtility.TrTextContent("Input Texture Alpha", "Use Alpha from the input texture if one is provided."), - EditorGUIUtility.TrTextContent("From Gray Scale", "Generate Alpha from image gray scale."), - }; - public readonly int[] alphaSourceValues = - { - (int)TextureImporterAlphaSource.None, - (int)TextureImporterAlphaSource.FromInput, - (int)TextureImporterAlphaSource.FromGrayScale, - }; - - public readonly GUIContent singleChannelComponent = EditorGUIUtility.TrTextContent("Channel", "As which color/alpha component the single channel texture is treated."); - public readonly GUIContent[] singleChannelComponentOptions = - { - EditorGUIUtility.TrTextContent("Alpha", "Use the alpha channel (compression not supported)."), - EditorGUIUtility.TrTextContent("Red", "Use the red color component."), - }; - public readonly int[] singleChannelComponentValues = - { - (int)TextureImporterSingleChannelComponent.Alpha, - (int)TextureImporterSingleChannelComponent.Red, - }; - - public readonly GUIContent generateMipMaps = EditorGUIUtility.TrTextContent("Generate Mip Maps"); - 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)."); - public readonly GUIContent borderMipMaps = EditorGUIUtility.TrTextContent("Border Mip Maps"); - public readonly GUIContent mipMapsPreserveCoverage = EditorGUIUtility.TrTextContent("Mip Maps Preserve Coverage", "The alpha channel of generated Mip Maps will preserve coverage during the alpha test."); - public readonly GUIContent alphaTestReferenceValue = EditorGUIUtility.TrTextContent("Alpha Cutoff Value", "The reference value used during the alpha test. Controls Mip Map coverage."); - public readonly GUIContent mipMapFilter = EditorGUIUtility.TrTextContent("Mip Map Filtering"); - public readonly GUIContent[] mipMapFilterOptions = - { - EditorGUIUtility.TrTextContent("Box"), - EditorGUIUtility.TrTextContent("Kaiser"), - }; - public readonly GUIContent npot = EditorGUIUtility.TrTextContent("Non Power of 2", "How non-power-of-two textures are scaled on import."); - public readonly GUIContent generateCubemap = EditorGUIUtility.TrTextContent("Generate Cubemap"); - - public readonly GUIContent compressionQuality = EditorGUIUtility.TrTextContent("Compressor Quality"); - public readonly GUIContent compressionQualitySlider = EditorGUIUtility.TrTextContent("Compressor Quality", "Use the slider to adjust compression quality from 0 (Fastest) to 100 (Best)"); - public readonly GUIContent[] mobileCompressionQualityOptions = - { - EditorGUIUtility.TrTextContent("Fast"), - EditorGUIUtility.TrTextContent("Normal"), - EditorGUIUtility.TrTextContent("Best") - }; - - public readonly GUIContent spriteMode = EditorGUIUtility.TrTextContent("Sprite Mode"); - public readonly GUIContent[] spriteModeOptions = - { - EditorGUIUtility.TrTextContent("Single"), - EditorGUIUtility.TrTextContent("Multiple"), - EditorGUIUtility.TrTextContent("Polygon"), - }; - public readonly GUIContent[] spriteMeshTypeOptions = - { - EditorGUIUtility.TrTextContent("Full Rect"), - EditorGUIUtility.TrTextContent("Tight"), - }; - - public readonly GUIContent spritePackingTag = EditorGUIUtility.TrTextContent("Packing Tag", "Tag for the Sprite Packing system."); - public readonly GUIContent spritePixelsPerUnit = EditorGUIUtility.TrTextContent("Pixels Per Unit", "How many pixels in the sprite correspond to one unit in the world."); - public readonly GUIContent spriteExtrude = EditorGUIUtility.TrTextContent("Extrude Edges", "How much empty area to leave around the sprite in the generated mesh."); - public readonly GUIContent spriteMeshType = EditorGUIUtility.TrTextContent("Mesh Type", "Type of sprite mesh to generate."); - public readonly GUIContent spriteAlignment = EditorGUIUtility.TrTextContent("Pivot", "Sprite pivot point in its localspace. May be used for syncing animation frames of different sizes."); - public readonly GUIContent[] spriteAlignmentOptions = - { - EditorGUIUtility.TrTextContent("Center"), - EditorGUIUtility.TrTextContent("Top Left"), - EditorGUIUtility.TrTextContent("Top"), - EditorGUIUtility.TrTextContent("Top Right"), - EditorGUIUtility.TrTextContent("Left"), - EditorGUIUtility.TrTextContent("Right"), - EditorGUIUtility.TrTextContent("Bottom Left"), - EditorGUIUtility.TrTextContent("Bottom"), - EditorGUIUtility.TrTextContent("Bottom Right"), - EditorGUIUtility.TrTextContent("Custom"), - }; - 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."); - - public readonly GUIContent alphaIsTransparency = EditorGUIUtility.TrTextContent("Alpha Is Transparency", "If the provided alpha channel is transparency, enable this to pre-filter the color to avoid texture filtering artifacts. This is not supported for HDR textures."); - public readonly GUIContent etc1Compression = EditorGUIUtility.TrTextContent("Compress using ETC1 (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."); - - public readonly GUIContent crunchedCompression = EditorGUIUtility.TrTextContent("Use Crunch Compression", "Texture is crunch-compressed to save space on disk when applicable."); - - public readonly GUIContent showAdvanced = EditorGUIUtility.TrTextContent("Advanced", "Show advanced settings."); - - public Styles() - { - // This is far from ideal, but it's better than having tons of logic in the GUI code itself. - // The combination should not grow too much anyway since only Texture3D will be added later. - GUIContent[] s2D_Options = { textureShape2D }; - GUIContent[] sCube_Options = { textureShapeCube }; - GUIContent[] s2D_Cube_Options = { textureShape2D, textureShapeCube }; - textureShapeOptionsDictionnary.Add(TextureImporterShape.Texture2D, s2D_Options); - textureShapeOptionsDictionnary.Add(TextureImporterShape.TextureCube, sCube_Options); - textureShapeOptionsDictionnary.Add(TextureImporterShape.Texture2D | TextureImporterShape.TextureCube, s2D_Cube_Options); - - int[] s2D_Values = { (int)TextureImporterShape.Texture2D }; - int[] sCube_Values = { (int)TextureImporterShape.TextureCube }; - int[] s2D_Cube_Values = { (int)TextureImporterShape.Texture2D, (int)TextureImporterShape.TextureCube }; - textureShapeValuesDictionnary.Add(TextureImporterShape.Texture2D, s2D_Values); - textureShapeValuesDictionnary.Add(TextureImporterShape.TextureCube, sCube_Values); - textureShapeValuesDictionnary.Add(TextureImporterShape.Texture2D | TextureImporterShape.TextureCube, s2D_Cube_Values); - } - } - - internal static Styles s_Styles; - - TextureInspectorTypeGUIProperties[] m_TextureTypeGUIElements = new TextureInspectorTypeGUIProperties[Enum.GetValues(typeof(TextureImporterType)).Length]; - List m_GUIElementsDisplayOrder = new List(); - - - void ToggleFromInt(SerializedProperty property, GUIContent label) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = property.hasMultipleDifferentValues; - int value = EditorGUILayout.Toggle(label, property.intValue > 0) ? 1 : 0; - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - property.intValue = value; - } - - void EnumPopup(SerializedProperty property, System.Type type, GUIContent label) - { - EditorGUILayout.IntPopup(property, - EditorGUIUtility.TempContent(System.Enum.GetNames(type)), - System.Enum.GetValues(type) as int[], - label); - } - - SerializedProperty m_AlphaSource; - SerializedProperty m_ConvertToNormalMap; - SerializedProperty m_HeightScale; - SerializedProperty m_NormalMapFilter; - SerializedProperty m_GenerateCubemap; - SerializedProperty m_CubemapConvolution; - SerializedProperty m_SeamlessCubemap; - SerializedProperty m_BorderMipMap; - SerializedProperty m_MipMapsPreserveCoverage; - SerializedProperty m_AlphaTestReferenceValue; - SerializedProperty m_NPOTScale; - SerializedProperty m_IsReadable; - SerializedProperty m_sRGBTexture; - SerializedProperty m_EnableMipMap; - SerializedProperty m_MipMapMode; - SerializedProperty m_FadeOut; - SerializedProperty m_MipMapFadeDistanceStart; - SerializedProperty m_MipMapFadeDistanceEnd; - - SerializedProperty m_Aniso; - SerializedProperty m_FilterMode; - SerializedProperty m_WrapU; - SerializedProperty m_WrapV; - SerializedProperty m_WrapW; - - SerializedProperty m_SpritePackingTag; - SerializedProperty m_SpritePixelsToUnits; - SerializedProperty m_SpriteExtrude; - SerializedProperty m_SpriteMeshType; - SerializedProperty m_Alignment; - SerializedProperty m_SpritePivot; - SerializedProperty m_SpriteGenerateFallbackPhysicsShape; - - SerializedProperty m_AlphaIsTransparency; - - SerializedProperty m_TextureShape; - - SerializedProperty m_SpriteMode; - - SerializedProperty m_SingleChannelComponent; - internal SpriteImportMode spriteImportMode - { - get - { - return (SpriteImportMode)m_SpriteMode.intValue; - } - } - - bool m_ShowAdvanced = false; - - int m_TextureWidth = 0; - int m_TextureHeight = 0; - bool m_IsPOT = false; - - void CacheSerializedProperties() - { - m_AlphaSource = serializedObject.FindProperty("m_AlphaUsage"); - m_ConvertToNormalMap = serializedObject.FindProperty("m_ConvertToNormalMap"); - m_HeightScale = serializedObject.FindProperty("m_HeightScale"); - m_NormalMapFilter = serializedObject.FindProperty("m_NormalMapFilter"); - m_GenerateCubemap = serializedObject.FindProperty("m_GenerateCubemap"); - m_SeamlessCubemap = serializedObject.FindProperty("m_SeamlessCubemap"); - m_BorderMipMap = serializedObject.FindProperty("m_BorderMipMap"); - m_MipMapsPreserveCoverage = serializedObject.FindProperty("m_MipMapsPreserveCoverage"); - m_AlphaTestReferenceValue = serializedObject.FindProperty("m_AlphaTestReferenceValue"); - m_NPOTScale = serializedObject.FindProperty("m_NPOTScale"); - m_IsReadable = serializedObject.FindProperty("m_IsReadable"); - m_sRGBTexture = serializedObject.FindProperty("m_sRGBTexture"); - m_EnableMipMap = serializedObject.FindProperty("m_EnableMipMap"); - m_MipMapMode = serializedObject.FindProperty("m_MipMapMode"); - m_FadeOut = serializedObject.FindProperty("m_FadeOut"); - m_MipMapFadeDistanceStart = serializedObject.FindProperty("m_MipMapFadeDistanceStart"); - m_MipMapFadeDistanceEnd = serializedObject.FindProperty("m_MipMapFadeDistanceEnd"); - - m_Aniso = serializedObject.FindProperty("m_TextureSettings.m_Aniso"); - m_FilterMode = serializedObject.FindProperty("m_TextureSettings.m_FilterMode"); - m_WrapU = serializedObject.FindProperty("m_TextureSettings.m_WrapU"); - m_WrapV = serializedObject.FindProperty("m_TextureSettings.m_WrapV"); - m_WrapW = serializedObject.FindProperty("m_TextureSettings.m_WrapW"); - - m_CubemapConvolution = serializedObject.FindProperty("m_CubemapConvolution"); - - m_SpriteMode = serializedObject.FindProperty("m_SpriteMode"); - m_SpritePackingTag = serializedObject.FindProperty("m_SpritePackingTag"); - m_SpritePixelsToUnits = serializedObject.FindProperty("m_SpritePixelsToUnits"); - m_SpriteExtrude = serializedObject.FindProperty("m_SpriteExtrude"); - m_SpriteMeshType = serializedObject.FindProperty("m_SpriteMeshType"); - m_Alignment = serializedObject.FindProperty("m_Alignment"); - m_SpritePivot = serializedObject.FindProperty("m_SpritePivot"); - m_SpriteGenerateFallbackPhysicsShape = serializedObject.FindProperty("m_SpriteGenerateFallbackPhysicsShape"); - - m_AlphaIsTransparency = serializedObject.FindProperty("m_AlphaIsTransparency"); - - m_TextureType = serializedObject.FindProperty("m_TextureType"); - m_TextureShape = serializedObject.FindProperty("m_TextureShape"); - - m_SingleChannelComponent = serializedObject.FindProperty("m_SingleChannelComponent"); - } - - void InitializeGUI() - { - // This is where we decide what GUI elements are displayed depending on the texture type. - // TODO: Maybe complement the bitfield with a list to add a concept of order in the display. Not sure if necessary... - TextureImporterShape shapeCapsAll = TextureImporterShape.Texture2D | TextureImporterShape.TextureCube; - - m_TextureTypeGUIElements[(int)TextureImporterType.Default] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.ColorSpace | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.CubeMapConvolution | TextureInspectorGUIElement.CubeMapping, - TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps - , shapeCapsAll); - m_TextureTypeGUIElements[(int)TextureImporterType.NormalMap] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.NormalMap | TextureInspectorGUIElement.CubeMapping, - TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps - , shapeCapsAll); - m_TextureTypeGUIElements[(int)TextureImporterType.Sprite] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.Sprite, - TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.MipMaps | TextureInspectorGUIElement.ColorSpace, - TextureImporterShape.Texture2D); - m_TextureTypeGUIElements[(int)TextureImporterType.Cookie] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.Cookie | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.CubeMapping, - TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps, - TextureImporterShape.Texture2D | TextureImporterShape.TextureCube); - m_TextureTypeGUIElements[(int)TextureImporterType.SingleChannel] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.SingleChannelComponent | TextureInspectorGUIElement.CubeMapping, - TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps - , shapeCapsAll); - m_TextureTypeGUIElements[(int)TextureImporterType.GUI] = new TextureInspectorTypeGUIProperties(0, - TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps, - TextureImporterShape.Texture2D); - m_TextureTypeGUIElements[(int)TextureImporterType.Cursor] = new TextureInspectorTypeGUIProperties(0, - TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps, - TextureImporterShape.Texture2D); - m_TextureTypeGUIElements[(int)TextureImporterType.Lightmap] = new TextureInspectorTypeGUIProperties(0, - TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps - , TextureImporterShape.Texture2D); - - m_GUIElementMethods.Clear(); - m_GUIElementMethods.Add(TextureInspectorGUIElement.PowerOfTwo, this.POTScaleGUI); - m_GUIElementMethods.Add(TextureInspectorGUIElement.Readable, this.ReadableGUI); - m_GUIElementMethods.Add(TextureInspectorGUIElement.ColorSpace, this.ColorSpaceGUI); - m_GUIElementMethods.Add(TextureInspectorGUIElement.AlphaHandling, this.AlphaHandlingGUI); - m_GUIElementMethods.Add(TextureInspectorGUIElement.MipMaps, this.MipMapGUI); - m_GUIElementMethods.Add(TextureInspectorGUIElement.NormalMap, this.BumpGUI); - m_GUIElementMethods.Add(TextureInspectorGUIElement.Sprite, this.SpriteGUI); - m_GUIElementMethods.Add(TextureInspectorGUIElement.Cookie, this.CookieGUI); - m_GUIElementMethods.Add(TextureInspectorGUIElement.CubeMapping, this.CubemapMappingGUI); - - // This list dictates the order in which the GUI Elements are displayed. - // It could be different for each TextureImporterType but let's keep it simple for now. - m_GUIElementsDisplayOrder.Clear(); - m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.CubeMapping); - m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.CubeMapConvolution); - m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.Cookie); - m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.ColorSpace); - m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.AlphaHandling); - m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.NormalMap); - m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.Sprite); - m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.PowerOfTwo); - m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.Readable); - m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.MipMaps); - - UnityEngine.Debug.Assert(m_GUIElementsDisplayOrder.Count == (Enum.GetValues(typeof(TextureInspectorGUIElement)).Length - 1), "Some GUIElement are not present in the list."); // -1 because TextureInspectorGUIElement.None - } - - public override void OnEnable() - { - s_DefaultPlatformName = TextureImporter.defaultPlatformName; // Can't be called everywhere so we save it here for later use. - - m_ShowAdvanced = EditorPrefs.GetBool("TextureImporterShowAdvanced", m_ShowAdvanced); - - CacheSerializedProperties(); - - m_ShowBumpGenerationSettings.valueChanged.AddListener(Repaint); - m_ShowCubeMapSettings.valueChanged.AddListener(Repaint); - m_ShowCubeMapSettings.value = (TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.TextureCube; - //@TODO change to use spriteMode enum when available - m_ShowGenericSpriteSettings.valueChanged.AddListener(Repaint); - m_ShowGenericSpriteSettings.value = m_SpriteMode.intValue != 0; - m_ShowSpriteMeshTypeOption.valueChanged.AddListener(Repaint); - m_ShowSpriteMeshTypeOption.value = ShouldShowSpriteMeshTypeOption(); - m_ShowMipMapSettings.valueChanged.AddListener(Repaint); - m_ShowMipMapSettings.value = m_EnableMipMap.boolValue; - - InitializeGUI(); - - var importer = target as TextureImporter; - if (importer == null) - return; - - importer.GetWidthAndHeight(ref m_TextureWidth, ref m_TextureHeight); - m_IsPOT = IsPowerOfTwo(m_TextureWidth) && IsPowerOfTwo(m_TextureHeight); - - InitializeTextureFormatStrings(); - } - - void SetSerializedPropertySettings(TextureImporterSettings settings) - { - m_AlphaSource.intValue = (int)settings.alphaSource; - m_ConvertToNormalMap.intValue = settings.convertToNormalMap ? 1 : 0; - m_HeightScale.floatValue = settings.heightmapScale; - m_NormalMapFilter.intValue = (int)settings.normalMapFilter; - m_GenerateCubemap.intValue = (int)settings.generateCubemap; - m_CubemapConvolution.intValue = (int)settings.cubemapConvolution; - m_SeamlessCubemap.intValue = settings.seamlessCubemap ? 1 : 0; - m_BorderMipMap.intValue = settings.borderMipmap ? 1 : 0; - m_MipMapsPreserveCoverage.intValue = settings.mipMapsPreserveCoverage ? 1 : 0; - m_AlphaTestReferenceValue.floatValue = settings.alphaTestReferenceValue; - m_NPOTScale.intValue = (int)settings.npotScale; - m_IsReadable.intValue = settings.readable ? 1 : 0; - m_EnableMipMap.intValue = settings.mipmapEnabled ? 1 : 0; - m_sRGBTexture.intValue = settings.sRGBTexture ? 1 : 0; - m_MipMapMode.intValue = (int)settings.mipmapFilter; - m_FadeOut.intValue = settings.fadeOut ? 1 : 0; - m_MipMapFadeDistanceStart.intValue = settings.mipmapFadeDistanceStart; - m_MipMapFadeDistanceEnd.intValue = settings.mipmapFadeDistanceEnd; - - m_SpriteMode.intValue = settings.spriteMode; - m_SpritePixelsToUnits.floatValue = settings.spritePixelsPerUnit; - m_SpriteExtrude.intValue = (int)settings.spriteExtrude; - m_SpriteMeshType.intValue = (int)settings.spriteMeshType; - m_Alignment.intValue = settings.spriteAlignment; - m_SpriteGenerateFallbackPhysicsShape.intValue = settings.spriteGenerateFallbackPhysicsShape ? 1 : 0; - - m_WrapU.intValue = (int)settings.wrapMode; - m_WrapV.intValue = (int)settings.wrapMode; - m_FilterMode.intValue = (int)settings.filterMode; - m_Aniso.intValue = settings.aniso; - - m_AlphaIsTransparency.intValue = settings.alphaIsTransparency ? 1 : 0; - - m_TextureType.intValue = (int)settings.textureType; - m_TextureShape.intValue = (int)settings.textureShape; - - m_SingleChannelComponent.intValue = (int)settings.singleChannelComponent; - } - - internal TextureImporterSettings GetSerializedPropertySettings() - { - return GetSerializedPropertySettings(new TextureImporterSettings()); - } - - internal TextureImporterSettings GetSerializedPropertySettings(TextureImporterSettings settings) - { - if (!m_AlphaSource.hasMultipleDifferentValues) - settings.alphaSource = (TextureImporterAlphaSource)m_AlphaSource.intValue; - - if (!m_ConvertToNormalMap.hasMultipleDifferentValues) - settings.convertToNormalMap = m_ConvertToNormalMap.intValue > 0; - - if (!m_HeightScale.hasMultipleDifferentValues) - settings.heightmapScale = m_HeightScale.floatValue; - - if (!m_NormalMapFilter.hasMultipleDifferentValues) - settings.normalMapFilter = (TextureImporterNormalFilter)m_NormalMapFilter.intValue; - - if (!m_GenerateCubemap.hasMultipleDifferentValues) - settings.generateCubemap = (TextureImporterGenerateCubemap)m_GenerateCubemap.intValue; - - if (!m_CubemapConvolution.hasMultipleDifferentValues) - settings.cubemapConvolution = (TextureImporterCubemapConvolution)m_CubemapConvolution.intValue; - - if (!m_SeamlessCubemap.hasMultipleDifferentValues) - settings.seamlessCubemap = m_SeamlessCubemap.intValue > 0; - - if (!m_BorderMipMap.hasMultipleDifferentValues) - settings.borderMipmap = m_BorderMipMap.intValue > 0; - - if (!m_MipMapsPreserveCoverage.hasMultipleDifferentValues) - settings.mipMapsPreserveCoverage = m_MipMapsPreserveCoverage.intValue > 0; - - if (!m_AlphaTestReferenceValue.hasMultipleDifferentValues) - settings.alphaTestReferenceValue = m_AlphaTestReferenceValue.floatValue; - - if (!m_NPOTScale.hasMultipleDifferentValues) - settings.npotScale = (TextureImporterNPOTScale)m_NPOTScale.intValue; - - if (!m_IsReadable.hasMultipleDifferentValues) - settings.readable = m_IsReadable.intValue > 0; - - - if (!m_sRGBTexture.hasMultipleDifferentValues) - settings.sRGBTexture = m_sRGBTexture.intValue > 0; - - if (!m_EnableMipMap.hasMultipleDifferentValues) - settings.mipmapEnabled = m_EnableMipMap.intValue > 0; - - if (!m_MipMapMode.hasMultipleDifferentValues) - settings.mipmapFilter = (TextureImporterMipFilter)m_MipMapMode.intValue; - - if (!m_FadeOut.hasMultipleDifferentValues) - settings.fadeOut = m_FadeOut.intValue > 0; - - if (!m_MipMapFadeDistanceStart.hasMultipleDifferentValues) - settings.mipmapFadeDistanceStart = m_MipMapFadeDistanceStart.intValue; - - if (!m_MipMapFadeDistanceEnd.hasMultipleDifferentValues) - settings.mipmapFadeDistanceEnd = m_MipMapFadeDistanceEnd.intValue; - - if (!m_SpriteMode.hasMultipleDifferentValues) - settings.spriteMode = m_SpriteMode.intValue; - - if (!m_SpritePixelsToUnits.hasMultipleDifferentValues) - settings.spritePixelsPerUnit = m_SpritePixelsToUnits.floatValue; - - if (!m_SpriteExtrude.hasMultipleDifferentValues) - settings.spriteExtrude = (uint)m_SpriteExtrude.intValue; - - if (!m_SpriteMeshType.hasMultipleDifferentValues) - settings.spriteMeshType = (SpriteMeshType)m_SpriteMeshType.intValue; - - if (!m_Alignment.hasMultipleDifferentValues) - settings.spriteAlignment = m_Alignment.intValue; - - if (!m_SpritePivot.hasMultipleDifferentValues) - settings.spritePivot = m_SpritePivot.vector2Value; - - if (!m_SpriteGenerateFallbackPhysicsShape.hasMultipleDifferentValues) - settings.spriteGenerateFallbackPhysicsShape = m_SpriteGenerateFallbackPhysicsShape.intValue > 0; - - if (!m_WrapU.hasMultipleDifferentValues) - settings.wrapModeU = (TextureWrapMode)m_WrapU.intValue; - if (!m_WrapV.hasMultipleDifferentValues) - settings.wrapModeU = (TextureWrapMode)m_WrapV.intValue; - if (!m_WrapW.hasMultipleDifferentValues) - settings.wrapModeU = (TextureWrapMode)m_WrapW.intValue; - - if (!m_FilterMode.hasMultipleDifferentValues) - settings.filterMode = (FilterMode)m_FilterMode.intValue; - - if (!m_Aniso.hasMultipleDifferentValues) - settings.aniso = m_Aniso.intValue; - - - if (!m_AlphaIsTransparency.hasMultipleDifferentValues) - settings.alphaIsTransparency = m_AlphaIsTransparency.intValue > 0; - - if (!m_TextureType.hasMultipleDifferentValues) - settings.textureType = (TextureImporterType)m_TextureType.intValue; - - if (!m_TextureShape.hasMultipleDifferentValues) - settings.textureShape = (TextureImporterShape)m_TextureShape.intValue; - - if (!m_SingleChannelComponent.hasMultipleDifferentValues) - settings.singleChannelComponent = (TextureImporterSingleChannelComponent)m_SingleChannelComponent.intValue; - - return settings; - } - - void CookieGUI(TextureInspectorGUIElement guiElements) - { - EditorGUI.BeginChangeCheck(); - CookieMode cm; - if (m_BorderMipMap.intValue > 0) - cm = CookieMode.Spot; - else if (m_TextureShape.intValue == (int)TextureImporterShape.TextureCube) - cm = CookieMode.Point; - else - cm = CookieMode.Directional; - - cm = (CookieMode)EditorGUILayout.Popup(s_Styles.cookieType, (int)cm, s_Styles.cookieOptions); - if (EditorGUI.EndChangeCheck()) - SetCookieMode(cm); - - if (cm == CookieMode.Point) - { - m_TextureShape.intValue = (int)TextureImporterShape.TextureCube; - } - else - { - m_TextureShape.intValue = (int)TextureImporterShape.Texture2D; - } - } - - void CubemapMappingGUI(TextureInspectorGUIElement guiElements) - { - m_ShowCubeMapSettings.target = (TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.TextureCube; - if (EditorGUILayout.BeginFadeGroup(m_ShowCubeMapSettings.faded)) - { - if ((TextureImporterShape)m_TextureShape.intValue == TextureImporterShape.TextureCube) - { - using (new EditorGUI.DisabledScope(!m_IsPOT && m_NPOTScale.intValue == (int)TextureImporterNPOTScale.None)) - { - EditorGUI.showMixedValue = m_GenerateCubemap.hasMultipleDifferentValues || m_SeamlessCubemap.hasMultipleDifferentValues; - - EditorGUI.BeginChangeCheck(); - - int value = EditorGUILayout.IntPopup(s_Styles.cubemap, m_GenerateCubemap.intValue, s_Styles.cubemapOptions, s_Styles.cubemapValues2); - if (EditorGUI.EndChangeCheck()) - m_GenerateCubemap.intValue = value; - - EditorGUI.indentLevel++; - - // Convolution - if (ShouldDisplayGUIElement(guiElements, TextureInspectorGUIElement.CubeMapConvolution)) - { - EditorGUILayout.IntPopup(m_CubemapConvolution, - s_Styles.cubemapConvolutionOptions, - s_Styles.cubemapConvolutionValues, - s_Styles.cubemapConvolution); - } - - ToggleFromInt(m_SeamlessCubemap, s_Styles.seamlessCubemap); - - EditorGUI.indentLevel--; - EditorGUI.showMixedValue = false; - EditorGUILayout.Space(); - } - } - } - EditorGUILayout.EndFadeGroup(); - } - - void ColorSpaceGUI(TextureInspectorGUIElement guiElements) - { - ToggleFromInt(m_sRGBTexture, s_Styles.sRGBTexture); - } - - void POTScaleGUI(TextureInspectorGUIElement guiElements) - { - using (new EditorGUI.DisabledScope(m_IsPOT)) - { - EnumPopup(m_NPOTScale, typeof(TextureImporterNPOTScale), s_Styles.npot); - } - } - - void ReadableGUI(TextureInspectorGUIElement guiElements) - { - ToggleFromInt(m_IsReadable, s_Styles.readWrite); - } - - - void AlphaHandlingGUI(TextureInspectorGUIElement guiElements) - { - bool showAlphaSource = true; - if (ShouldDisplayGUIElement(guiElements, TextureInspectorGUIElement.SingleChannelComponent)) - { - EditorGUI.showMixedValue = m_SingleChannelComponent.hasMultipleDifferentValues; - EditorGUI.BeginChangeCheck(); - int newSingleChannelComponent = EditorGUILayout.IntPopup(s_Styles.singleChannelComponent, m_SingleChannelComponent.intValue, s_Styles.singleChannelComponentOptions, s_Styles.singleChannelComponentValues); - - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - m_SingleChannelComponent.intValue = newSingleChannelComponent; - } - - showAlphaSource = (m_SingleChannelComponent.intValue == (int)TextureImporterSingleChannelComponent.Alpha); - } - - if (showAlphaSource) - { - int countWithAlpha = 0; - int countHDR = 0; - - bool success = CountImportersWithAlpha(targets, out countWithAlpha); - success = success && CountImportersWithHDR(targets, out countHDR); - - EditorGUI.showMixedValue = m_AlphaSource.hasMultipleDifferentValues; - EditorGUI.BeginChangeCheck(); - int newAlphaUsage = EditorGUILayout.IntPopup(s_Styles.alphaSource, m_AlphaSource.intValue, s_Styles.alphaSourceOptions, s_Styles.alphaSourceValues); - - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - m_AlphaSource.intValue = newAlphaUsage; - } - - bool showAlphaIsTransparency = success && (TextureImporterAlphaSource)m_AlphaSource.intValue != TextureImporterAlphaSource.None && countHDR == 0; // AlphaIsTransparency is not properly implemented for HDR texture yet. - using (new EditorGUI.DisabledScope(!showAlphaIsTransparency)) - { - ToggleFromInt(m_AlphaIsTransparency, s_Styles.alphaIsTransparency); - } - } - } - - private bool ShouldShowSpriteMeshTypeOption() - { - return m_SpriteMode.intValue != (int)SpriteImportMode.Polygon && !m_SpriteMode.hasMultipleDifferentValues; - } - - private void SpriteGUI(TextureInspectorGUIElement guiElements) - { - // Sprite mode selection - EditorGUI.BeginChangeCheck(); - - EditorGUILayout.IntPopup(m_SpriteMode, s_Styles.spriteModeOptions, new[] { 1, 2, 3 }, s_Styles.spriteMode); - - // Ensure that PropertyField focus will be cleared when we change spriteMode. - if (EditorGUI.EndChangeCheck()) - { - GUIUtility.keyboardControl = 0; - } - - EditorGUI.indentLevel++; - - // Show generic attributes - m_ShowGenericSpriteSettings.target = (m_SpriteMode.intValue != 0); - if (EditorGUILayout.BeginFadeGroup(m_ShowGenericSpriteSettings.faded)) - { - EditorGUILayout.PropertyField(m_SpritePackingTag, s_Styles.spritePackingTag); - EditorGUILayout.PropertyField(m_SpritePixelsToUnits, s_Styles.spritePixelsPerUnit); - - m_ShowSpriteMeshTypeOption.target = ShouldShowSpriteMeshTypeOption(); - if (EditorGUILayout.BeginFadeGroup(m_ShowSpriteMeshTypeOption.faded)) - { - EditorGUILayout.IntPopup(m_SpriteMeshType, s_Styles.spriteMeshTypeOptions, new[] { 0, 1 }, s_Styles.spriteMeshType); - } - EditorGUILayout.EndFadeGroup(); - - EditorGUILayout.IntSlider(m_SpriteExtrude, 0, 32, s_Styles.spriteExtrude); - - if (m_SpriteMode.intValue == (int)SpriteImportMode.Multiple) - { - EditorGUILayout.Popup(m_Alignment, s_Styles.spriteAlignmentOptions, s_Styles.spriteAlignment); - - if (m_Alignment.intValue == (int)SpriteAlignment.Custom) - { - GUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(m_SpritePivot, m_EmptyContent); - GUILayout.EndHorizontal(); - } - } - - if (m_SpriteMode.intValue != (int)SpriteImportMode.Polygon) - ToggleFromInt(m_SpriteGenerateFallbackPhysicsShape, s_Styles.spriteGenerateFallbackPhysicsShape); - - using (new EditorGUI.DisabledScope(targets.Length != 1)) - { - GUILayout.BeginHorizontal(); - - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Sprite Editor")) - { - if (HasModified()) - { - // To ensure Sprite Editor Window to have the latest texture import setting, - // We must applied those modified values first. - string dialogText = "Unapplied import settings for \'" + ((TextureImporter)target).assetPath + "\'.\n"; - dialogText += "Apply and continue to sprite editor or cancel."; - if (EditorUtility.DisplayDialog("Unapplied import settings", dialogText, "Apply", "Cancel")) - { - ApplyAndImport(); - SpriteEditorWindow.GetWindow(); - - // We reimported the asset which destroyed the editor, so we can't keep running the UI here. - GUIUtility.ExitGUI(); - } - } - else - { - SpriteEditorWindow.GetWindow(); - } - } - GUILayout.EndHorizontal(); - } - } - EditorGUILayout.EndFadeGroup(); - - EditorGUI.indentLevel--; - } - - void MipMapGUI(TextureInspectorGUIElement guiElements) - { - ToggleFromInt(m_EnableMipMap, s_Styles.generateMipMaps); - - m_ShowMipMapSettings.target = m_EnableMipMap.boolValue && !m_EnableMipMap.hasMultipleDifferentValues; - if (EditorGUILayout.BeginFadeGroup(m_ShowMipMapSettings.faded)) - { - EditorGUI.indentLevel++; - ToggleFromInt(m_BorderMipMap, s_Styles.borderMipMaps); - EditorGUILayout.Popup(m_MipMapMode, s_Styles.mipMapFilterOptions, s_Styles.mipMapFilter); - - ToggleFromInt(m_MipMapsPreserveCoverage, s_Styles.mipMapsPreserveCoverage); - if (m_MipMapsPreserveCoverage.intValue != 0 && !m_MipMapsPreserveCoverage.hasMultipleDifferentValues) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_AlphaTestReferenceValue, s_Styles.alphaTestReferenceValue); - EditorGUI.indentLevel--; - } - - // Mipmap fadeout - ToggleFromInt(m_FadeOut, s_Styles.mipmapFadeOutToggle); - if (m_FadeOut.intValue > 0) - { - EditorGUI.indentLevel++; - EditorGUI.BeginChangeCheck(); - float min = m_MipMapFadeDistanceStart.intValue; - float max = m_MipMapFadeDistanceEnd.intValue; - EditorGUILayout.MinMaxSlider(s_Styles.mipmapFadeOut, ref min, ref max, 0, 10); - if (EditorGUI.EndChangeCheck()) - { - m_MipMapFadeDistanceStart.intValue = Mathf.RoundToInt(min); - m_MipMapFadeDistanceEnd.intValue = Mathf.RoundToInt(max); - } - EditorGUI.indentLevel--; - } - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - } - - void BumpGUI(TextureInspectorGUIElement guiElements) - { - EditorGUI.BeginChangeCheck(); - - ToggleFromInt(m_ConvertToNormalMap, s_Styles.generateFromBump); - m_ShowBumpGenerationSettings.target = m_ConvertToNormalMap.intValue > 0; - if (EditorGUILayout.BeginFadeGroup(m_ShowBumpGenerationSettings.faded)) - { - EditorGUI.indentLevel++; - EditorGUILayout.Slider(m_HeightScale, 0.0F, 0.3F, s_Styles.bumpiness); - EditorGUILayout.Popup(m_NormalMapFilter, s_Styles.bumpFilteringOptions, s_Styles.bumpFiltering); - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - - if (EditorGUI.EndChangeCheck()) - SyncPlatformSettings(); - } - - bool m_ShowPerAxisWrapModes = false; - - void TextureSettingsGUI() - { - EditorGUI.BeginChangeCheck(); - - // Wrap mode - // NOTE: once we get ability to have 3D/Volume texture shapes, should pass true for isVolume based on m_TextureShape - bool isVolume = false; - TextureInspector.WrapModePopup(m_WrapU, m_WrapV, m_WrapW, isVolume, ref m_ShowPerAxisWrapModes); - - - // Display warning about repeat wrap mode on restricted npot emulation - if (m_NPOTScale.intValue == (int)TextureImporterNPOTScale.None && - (m_WrapU.intValue == (int)TextureWrapMode.Repeat || m_WrapV.intValue == (int)TextureWrapMode.Repeat) && - !ShaderUtil.hardwareSupportsFullNPOT) - { - bool displayWarning = false; - foreach (var target in targets) - { - int w = -1, h = -1; - var imp = (TextureImporter)target; - imp.GetWidthAndHeight(ref w, ref h); - if (!Mathf.IsPowerOfTwo(w) || !Mathf.IsPowerOfTwo(h)) - { - displayWarning = true; - break; - } - } - - if (displayWarning) - { - GUIContent c = EditorGUIUtility.TrTextContent("Graphics device doesn't support Repeat wrap mode on NPOT textures. Falling back to Clamp."); - EditorGUILayout.HelpBox(c.text, MessageType.Warning, true); - } - } - - // Filter mode - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_FilterMode.hasMultipleDifferentValues; - FilterMode filter = (FilterMode)m_FilterMode.intValue; - if ((int)filter == -1) - { - if (m_FadeOut.intValue > 0 || m_ConvertToNormalMap.intValue > 0) - filter = FilterMode.Trilinear; - else - filter = FilterMode.Bilinear; - } - filter = (FilterMode)EditorGUILayout.IntPopup(s_Styles.filterMode, (int)filter, s_Styles.filterModeOptions, m_FilterModeOptions); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - m_FilterMode.intValue = (int)filter; - - // Aniso - bool showAniso = (FilterMode)m_FilterMode.intValue != FilterMode.Point - && m_EnableMipMap.intValue > 0 - && (TextureImporterShape)m_TextureShape.intValue != TextureImporterShape.TextureCube; - using (new EditorGUI.DisabledScope(!showAniso)) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_Aniso.hasMultipleDifferentValues; - int aniso = m_Aniso.intValue; - if (aniso == -1) - aniso = 1; - aniso = EditorGUILayout.IntSlider("Aniso Level", aniso, 0, 16); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - m_Aniso.intValue = aniso; - - TextureInspector.DoAnisoGlobalSettingNote(aniso); - } - - if (EditorGUI.EndChangeCheck()) - ApplySettingsToTexture(); - } - - public override void OnInspectorGUI() - { - if (s_Styles == null) - s_Styles = new Styles(); - - bool wasEnabled = GUI.enabled; - - EditorGUILayout.Space(); - - // Texture Usage - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_TextureType.hasMultipleDifferentValues; - int newTextureType = EditorGUILayout.IntPopup(s_Styles.textureTypeTitle, m_TextureType.intValue, s_Styles.textureTypeOptions, s_Styles.textureTypeValues); - EditorGUI.showMixedValue = false; - // (case 857001) EndChangeCheck will return true even if the same value is selected. - // Consequently the sprite will be reset to Single mode and looks very confusing to the user. - if (EditorGUI.EndChangeCheck() && (m_TextureType.intValue != newTextureType)) - { - TextureImporterSettings settings = GetSerializedPropertySettings(); - settings.ApplyTextureType((TextureImporterType)newTextureType); - m_TextureType.intValue = newTextureType; - - SetSerializedPropertySettings(settings); - - SyncPlatformSettings(); - ApplySettingsToTexture(); - } - - // Texture Shape - int[] shapeArray = s_Styles.textureShapeValuesDictionnary[m_TextureTypeGUIElements[(int)newTextureType].shapeCaps]; - 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 - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_TextureShape.hasMultipleDifferentValues; - int newTextureShape = EditorGUILayout.IntPopup(s_Styles.textureShape, m_TextureShape.intValue, s_Styles.textureShapeOptionsDictionnary[m_TextureTypeGUIElements[(int)newTextureType].shapeCaps], s_Styles.textureShapeValuesDictionnary[m_TextureTypeGUIElements[(int)newTextureType].shapeCaps]); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - m_TextureShape.intValue = newTextureShape; - } - - // Switching usage can lead to a subset of the current available shapes. - if (Array.IndexOf(shapeArray, m_TextureShape.intValue) == -1) - { - m_TextureShape.intValue = shapeArray[0]; - } - - EditorGUILayout.Space(); - - if (!m_TextureType.hasMultipleDifferentValues) - { - DoGUIElements(m_TextureTypeGUIElements[newTextureType].commonElements, m_GUIElementsDisplayOrder); - if (m_TextureTypeGUIElements[newTextureType].advancedElements != 0) - { - EditorGUILayout.Space(); - - m_ShowAdvanced = EditorGUILayout.Foldout(m_ShowAdvanced, s_Styles.showAdvanced, true); - if (m_ShowAdvanced) - { - EditorGUI.indentLevel++; - DoGUIElements(m_TextureTypeGUIElements[newTextureType].advancedElements, m_GUIElementsDisplayOrder); - EditorGUI.indentLevel--; - } - } - } - - EditorGUILayout.Space(); - - // Filter mode, aniso, and wrap mode GUI - TextureSettingsGUI(); - - ShowPlatformSpecificSettings(); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - ApplyRevertGUI(); - GUILayout.EndHorizontal(); - - // screw this - after lots of retries i have no idea how to poll it only when we change related stuff - UpdateImportWarning(); - if (m_ImportWarning != null) - EditorGUILayout.HelpBox(m_ImportWarning, MessageType.Warning); - - GUI.enabled = wasEnabled; - } - - bool ShouldDisplayGUIElement(TextureInspectorGUIElement guiElements, TextureInspectorGUIElement guiElement) - { - return ((guiElements & guiElement) == guiElement); - } - - private void DoGUIElements(TextureInspectorGUIElement guiElements, List guiElementsDisplayOrder) - { - foreach (TextureInspectorGUIElement guiElement in guiElementsDisplayOrder) - { - if (ShouldDisplayGUIElement(guiElements, guiElement) && m_GUIElementMethods.ContainsKey(guiElement)) - { - m_GUIElementMethods[guiElement](guiElements); - } - } - } - - void ApplySettingsToTexture() - { - foreach (AssetImporter importer in targets) - { - Texture tex = AssetDatabase.LoadMainAssetAtPath(importer.assetPath) as Texture; - if (tex != null) // This can happen if the texture fails to import (for example, cube texture with non-PoT input). - { - if (m_Aniso.intValue != -1) - TextureUtil.SetAnisoLevelNoDirty(tex, m_Aniso.intValue); - if (m_FilterMode.intValue != -1) - TextureUtil.SetFilterModeNoDirty(tex, (FilterMode)m_FilterMode.intValue); - if ((m_WrapU.intValue != -1 || m_WrapV.intValue != -1 || m_WrapW.intValue != -1) && - !m_WrapU.hasMultipleDifferentValues && !m_WrapV.hasMultipleDifferentValues && !m_WrapW.hasMultipleDifferentValues) - { - TextureUtil.SetWrapModeNoDirty(tex, (TextureWrapMode)m_WrapU.intValue, (TextureWrapMode)m_WrapV.intValue, (TextureWrapMode)m_WrapW.intValue); - } - } - } - - SceneView.RepaintAll(); - } - - // Returns false if method fails to get info - static bool CountImportersWithAlpha(Object[] importers, out int count) - { - // DoesSourceTextureHaveAlpha will throw exception on importer reset (593478). - try - { - count = 0; - foreach (Object t in importers) - if ((t as TextureImporter).DoesSourceTextureHaveAlpha()) - count++; - return true; - } - catch - { - count = importers.Length; - return false; - } - } - - static bool CountImportersWithHDR(Object[] importers, out int count) - { - // DoesSourceTextureHaveAlpha will throw exception on importer reset (593478). - try - { - count = 0; - foreach (Object t in importers) - if ((t as TextureImporter).IsSourceTextureHDR()) - count++; - return true; - } - catch - { - count = importers.Length; - return false; - } - } - - void SetCookieMode(CookieMode cm) - { - switch (cm) - { - case CookieMode.Spot: - m_BorderMipMap.intValue = 1; - m_WrapU.intValue = m_WrapV.intValue = m_WrapW.intValue = (int)TextureWrapMode.Clamp; - m_GenerateCubemap.intValue = (int)TextureImporterGenerateCubemap.AutoCubemap; - m_TextureShape.intValue = (int)TextureImporterShape.Texture2D; - break; - case CookieMode.Point: - m_BorderMipMap.intValue = 0; - m_WrapU.intValue = m_WrapV.intValue = m_WrapW.intValue = (int)TextureWrapMode.Clamp; - m_GenerateCubemap.intValue = (int)TextureImporterGenerateCubemap.Spheremap; - m_TextureShape.intValue = (int)TextureImporterShape.TextureCube; - break; - case CookieMode.Directional: - m_BorderMipMap.intValue = 0; - m_WrapU.intValue = m_WrapV.intValue = m_WrapW.intValue = (int)TextureWrapMode.Repeat; - m_GenerateCubemap.intValue = (int)TextureImporterGenerateCubemap.AutoCubemap; - m_TextureShape.intValue = (int)TextureImporterShape.Texture2D; - break; - } - } - - void SyncPlatformSettings() - { - foreach (TextureImportPlatformSettings ps in m_PlatformSettings) - ps.Sync(); - } - - internal static string[] BuildTextureStrings(int[] texFormatValues) - { - string[] retval = new string[texFormatValues.Length]; - for (int i = 0; i < texFormatValues.Length; i++) - { - int val = texFormatValues[i]; - retval[i] = " " + TextureUtil.GetTextureFormatString((TextureFormat)val); - } - return retval; - } - - internal static void InitializeTextureFormatStrings() - { - if (s_TextureFormatStringsApplePVR == null) - s_TextureFormatStringsApplePVR = TextureImporterInspector.BuildTextureStrings(TextureImportPlatformSettings.kTextureFormatsValueApplePVR); - if (s_TextureFormatStringsAndroid == null) - s_TextureFormatStringsAndroid = TextureImporterInspector.BuildTextureStrings(TextureImportPlatformSettings.kTextureFormatsValueAndroid); - if (s_TextureFormatStringsTizen == null) - s_TextureFormatStringsTizen = TextureImporterInspector.BuildTextureStrings(TextureImportPlatformSettings.kTextureFormatsValueTizen); - if (s_TextureFormatStringsWebGL == null) - s_TextureFormatStringsWebGL = TextureImporterInspector.BuildTextureStrings(TextureImportPlatformSettings.kTextureFormatsValueWebGL); - if (s_TextureFormatStringsPSP2 == null) - s_TextureFormatStringsPSP2 = TextureImporterInspector.BuildTextureStrings(TextureImportPlatformSettings.kTextureFormatsValuePSP2); - if (s_TextureFormatStringsSwitch == null) - s_TextureFormatStringsSwitch = TextureImporterInspector.BuildTextureStrings(TextureImportPlatformSettings.kTextureFormatsValueSwitch); - if (s_TextureFormatStringsDefault == null) - s_TextureFormatStringsDefault = TextureImporterInspector.BuildTextureStrings(TextureImportPlatformSettings.kTextureFormatsValueDefault); - if (s_NormalFormatStringsDefault == null) - s_NormalFormatStringsDefault = TextureImporterInspector.BuildTextureStrings(TextureImportPlatformSettings.kNormalFormatsValueDefault); - if (s_TextureFormatStringsSingleChannel == null) - s_TextureFormatStringsSingleChannel = TextureImporterInspector.BuildTextureStrings(TextureImportPlatformSettings.kTextureFormatsValueSingleChannel); - } - - internal static bool IsFormatRequireCompressionSetting(TextureImporterFormat format) - { - return ArrayUtility.Contains(TextureImporterInspector.kFormatsWithCompressionSettings, format); - } - - protected void ShowPlatformSpecificSettings() - { - BuildPlatform[] validPlatforms = GetBuildPlayerValidPlatforms().ToArray(); - GUILayout.Space(10); - int shownTextureFormatPage = EditorGUILayout.BeginPlatformGrouping(validPlatforms, s_Styles.defaultPlatform); - TextureImportPlatformSettings realPS = m_PlatformSettings[shownTextureFormatPage + 1]; - - if (!realPS.isDefault) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = realPS.overriddenIsDifferent; - - string title = "Override for " + validPlatforms[shownTextureFormatPage].title.text; - bool newOverride = EditorGUILayout.ToggleLeft(title, realPS.overridden); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - realPS.SetOverriddenForAll(newOverride); - SyncPlatformSettings(); - } - } - - // Disable size and format GUI if not overwritten for all objects - bool notAllOverriddenForThisPlatform = (!realPS.isDefault && !realPS.allAreOverridden); - using (new EditorGUI.DisabledScope(notAllOverriddenForThisPlatform)) - { - // acquire the platform support module for this platform, and present the appropriate UI - ITextureImportSettingsExtension textureSettingsExtension = ModuleManager.GetTextureImportSettingsExtension(realPS.m_Target); - textureSettingsExtension.ShowImportSettings(this, realPS); - - //just do this once, regardless of whether things changed - SyncPlatformSettings(); - } - - EditorGUILayout.EndPlatformGrouping(); - } - - private static bool IsPowerOfTwo(int f) - { - return ((f & (f - 1)) == 0); - } - - public static BuildPlatform[] GetBuildPlayerValidPlatforms() - { - List validPlatforms = BuildPlatforms.instance.GetValidPlatforms(); - return validPlatforms.ToArray(); - } - - public virtual void BuildTargetList() - { - BuildPlatform[] validPlatforms = GetBuildPlayerValidPlatforms(); - - m_PlatformSettings = new List(); - m_PlatformSettings.Add(new TextureImportPlatformSettings(TextureImporterInspector.s_DefaultPlatformName, BuildTarget.StandaloneWindows, this)); - - foreach (BuildPlatform bp in validPlatforms) - m_PlatformSettings.Add(new TextureImportPlatformSettings(bp.name, bp.defaultTarget, this)); - } - - public override bool HasModified() - { - if (base.HasModified()) - return true; - - foreach (TextureImportPlatformSettings ps in m_PlatformSettings) - { - if (ps.HasChanged()) - return true; - } - - return false; - } - - public static void SelectMainAssets(Object[] targets) - { - ArrayList newSelection = new ArrayList(); - foreach (AssetImporter importer in targets) - { - Texture tex = AssetDatabase.LoadMainAssetAtPath(importer.assetPath) as Texture; - if (tex) - newSelection.Add(tex); - } - // The selection can be empty if for some reason the asset import failed. In this case, we don't want to cancel out the original selection so that user can correct its settings. - if (newSelection.Count > 0) - Selection.objects = newSelection.ToArray(typeof(Object)) as Object[]; - } - - protected override void ResetValues() - { - base.ResetValues(); - - CacheSerializedProperties(); - - BuildTargetList(); - System.Diagnostics.Debug.Assert(!HasModified(), "TextureImporter settings are marked as modified after calling Reset."); - ApplySettingsToTexture(); - - // since some texture types (like Cubemaps) might add/remove new assets during import - // and main asset of these textures might change, - // update selection to include main assets (case 561340) - SelectMainAssets(targets); - } - - protected override void Apply() - { - base.Apply(); - SyncPlatformSettings(); - foreach (TextureImportPlatformSettings ps in m_PlatformSettings) - ps.Apply(); - } - } -} diff --git a/Editor/Mono/ImportSettings/TrueTypeFontImporterInspector.cs b/Editor/Mono/ImportSettings/TrueTypeFontImporterInspector.cs deleted file mode 100644 index d710d2f134..0000000000 --- a/Editor/Mono/ImportSettings/TrueTypeFontImporterInspector.cs +++ /dev/null @@ -1,310 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Linq; -using System.IO; -using UnityEditor.Experimental.AssetImporters; - -namespace UnityEditor -{ - [CustomEditor(typeof(TrueTypeFontImporter))] - [CanEditMultipleObjects] - internal class TrueTypeFontImporterInspector : AssetImporterEditor - { - SerializedProperty m_FontSize; - SerializedProperty m_TextureCase; - SerializedProperty m_IncludeFontData; - SerializedProperty m_FontNamesArraySize; - SerializedProperty m_CustomCharacters; - SerializedProperty m_FontRenderingMode; - SerializedProperty m_AscentCalculationMode; - SerializedProperty m_UseLegacyBoundsCalculation; - SerializedProperty m_ShouldRoundAdvanceValue; - SerializedProperty m_FallbackFontReferencesArraySize; - - string m_FontNamesString = ""; - string m_DefaultFontNamesString = ""; - bool? m_FormatSupported = null; - bool m_ReferencesExpanded = false; - bool m_GotFontNamesFromImporter = false; - Font[] m_FallbackFontReferences = null; - - public override void OnEnable() - { - m_FontSize = serializedObject.FindProperty("m_FontSize"); - m_TextureCase = serializedObject.FindProperty("m_ForceTextureCase"); - m_IncludeFontData = serializedObject.FindProperty("m_IncludeFontData"); - m_FontNamesArraySize = serializedObject.FindProperty("m_FontNames.Array.size"); - m_CustomCharacters = serializedObject.FindProperty("m_CustomCharacters"); - m_FontRenderingMode = serializedObject.FindProperty("m_FontRenderingMode"); - m_AscentCalculationMode = serializedObject.FindProperty("m_AscentCalculationMode"); - m_UseLegacyBoundsCalculation = serializedObject.FindProperty("m_UseLegacyBoundsCalculation"); - m_ShouldRoundAdvanceValue = serializedObject.FindProperty("m_ShouldRoundAdvanceValue"); - m_FallbackFontReferencesArraySize = serializedObject.FindProperty("m_FallbackFontReferences.Array.size"); - - // We don't want to expose GUI for setting included fonts when selecting multiple fonts - if (targets.Length == 1) - { - m_DefaultFontNamesString = GetDefaultFontNames(); - m_FontNamesString = GetFontNames(); - var importer = (TrueTypeFontImporter)target; - m_FallbackFontReferences = importer.fontReferences; - } - } - - protected override void Apply() - { - m_FallbackFontReferencesArraySize.intValue = m_FallbackFontReferences.Length; - SerializedProperty fontReferenceProp = m_FallbackFontReferencesArraySize.Copy(); - - for (int i = 0; i < m_FallbackFontReferences.Length; i++) - { - fontReferenceProp.Next(false); - fontReferenceProp.objectReferenceValue = m_FallbackFontReferences[i]; - } - - base.Apply(); - } - - string GetDefaultFontNames() - { - return ((TrueTypeFontImporter)target).fontTTFName; - } - - string GetFontNames() - { - var importer = (TrueTypeFontImporter)target; - - string joinedFontNames = string.Join(", ", importer.fontNames); - if (string.IsNullOrEmpty(joinedFontNames)) - { - // Didn't get font names from importer - // Fall back to default font name, and lookup names/fallbacks in SetFontNames - joinedFontNames = m_DefaultFontNamesString; - } - else - { - // We've already got font names - don't look them up again - m_GotFontNamesFromImporter = true; - } - return joinedFontNames; - } - - void SetFontNames(string fontNames) - { - string[] names; - if (!m_GotFontNamesFromImporter) - { - // The import settings have never been touched. - names = new string[0]; - } - else - { - // Split into array of font names - // FIXME: Do we need to split and then trim? Or is the separator always ", "? - names = fontNames.Split(','); - for (int i = 0; i < names.Length; i++) - names[i] = names[i].Trim(); - } - - m_FontNamesArraySize.intValue = names.Length; - SerializedProperty fontNameProp = m_FontNamesArraySize.Copy(); - for (int i = 0; i < names.Length; i++) - { - fontNameProp.Next(false); - fontNameProp.stringValue = names[i]; - } - - var importer = (TrueTypeFontImporter)target; - m_FallbackFontReferences = importer.LookupFallbackFontReferences(names); - } - - private void ShowFormatUnsupportedGUI() - { - GUILayout.Space(5); - EditorGUILayout.HelpBox("Format of selected font is not supported by Unity.", MessageType.Warning); - } - - static GUIContent[] kCharacterStrings = - { - EditorGUIUtility.TrTextContent("Dynamic"), - EditorGUIUtility.TrTextContent("Unicode"), - EditorGUIUtility.TrTextContent("ASCII default set"), - EditorGUIUtility.TrTextContent("ASCII upper case"), - EditorGUIUtility.TrTextContent("ASCII lower case"), - EditorGUIUtility.TrTextContent("Custom set") - }; - static int[] kCharacterValues = - { - (int)FontTextureCase.Dynamic, - (int)FontTextureCase.Unicode, - (int)FontTextureCase.ASCII, - (int)FontTextureCase.ASCIIUpperCase, - (int)FontTextureCase.ASCIILowerCase, - (int)FontTextureCase.CustomSet, - }; - - static GUIContent[] kRenderingModeStrings = - { - EditorGUIUtility.TrTextContent("Smooth"), - EditorGUIUtility.TrTextContent("Hinted Smooth"), - EditorGUIUtility.TrTextContent("Hinted Raster"), - EditorGUIUtility.TrTextContent("OS Default"), - }; - static int[] kRenderingModeValues = - { - (int)FontRenderingMode.Smooth, - (int)FontRenderingMode.HintedSmooth, - (int)FontRenderingMode.HintedRaster, - (int)FontRenderingMode.OSDefault, - }; - - static GUIContent[] kAscentCalculationModeStrings = - { - EditorGUIUtility.TrTextContent("Legacy version 2 mode (glyph bounding boxes)"), - EditorGUIUtility.TrTextContent("Face ascender metric"), - EditorGUIUtility.TrTextContent("Face bounding box metric"), - }; - static int[] kAscentCalculationModeValues = - { - (int)AscentCalculationMode.Legacy2x, - (int)AscentCalculationMode.FaceAscender, - (int)AscentCalculationMode.FaceBoundingBox, - }; - - static string GetUniquePath(string basePath, string extension) - { - for (int i = 0; i < 10000; i++) - { - string path = string.Format("{0}{1}.{2}", basePath, (i == 0 ? string.Empty : i.ToString()), extension); - if (!File.Exists(path)) - return path; - } - return ""; - } - - [MenuItem("CONTEXT/TrueTypeFontImporter/Create Editable Copy")] - static void CreateEditableCopy(MenuCommand command) - { - var importer = (TrueTypeFontImporter)command.context; - if (importer.fontTextureCase == FontTextureCase.Dynamic) - { - EditorUtility.DisplayDialog( - "Cannot generate editable font asset for dynamic fonts", - "Please reimport the font in a different mode.", - "Ok"); - return; - } - string basePath = Path.Combine(Path.GetDirectoryName(importer.assetPath), Path.GetFileNameWithoutExtension(importer.assetPath)); - EditorGUIUtility.PingObject(importer.GenerateEditableFont(GetUniquePath(basePath + "_copy", "fontsettings"))); - } - - public override void OnInspectorGUI() - { - if (!m_FormatSupported.HasValue) - { - m_FormatSupported = true; - foreach (Object target in targets) - { - var importer = target as TrueTypeFontImporter; - if (importer == null || !importer.IsFormatSupported()) - m_FormatSupported = false; - } - } - - if (m_FormatSupported == false) - { - ShowFormatUnsupportedGUI(); - return; - } - - EditorGUILayout.PropertyField(m_FontSize); - if (m_FontSize.intValue < 1) - m_FontSize.intValue = 1; - if (m_FontSize.intValue > 500) - m_FontSize.intValue = 500; - - EditorGUILayout.IntPopup(m_FontRenderingMode, kRenderingModeStrings, kRenderingModeValues, EditorGUIUtility.TrTextContent("Rendering Mode")); - EditorGUILayout.IntPopup(m_TextureCase, kCharacterStrings, kCharacterValues, EditorGUIUtility.TrTextContent("Character")); - EditorGUILayout.IntPopup(m_AscentCalculationMode, kAscentCalculationModeStrings, kAscentCalculationModeValues, EditorGUIUtility.TrTextContent("Ascent Calculation Mode")); - EditorGUILayout.PropertyField(m_UseLegacyBoundsCalculation, EditorGUIUtility.TrTextContent("Use Legacy Bounds")); - EditorGUILayout.PropertyField(m_ShouldRoundAdvanceValue, new GUIContent("Should Round Advance Value")); - - if (!m_TextureCase.hasMultipleDifferentValues) - { - if ((FontTextureCase)m_TextureCase.intValue != FontTextureCase.Dynamic) - { - if ((FontTextureCase)m_TextureCase.intValue == FontTextureCase.CustomSet) - { - // Characters included - EditorGUI.BeginChangeCheck(); - GUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel("Custom Chars"); - EditorGUI.showMixedValue = m_CustomCharacters.hasMultipleDifferentValues; - string guiChars = EditorGUILayout.TextArea(m_CustomCharacters.stringValue, GUI.skin.textArea, GUILayout.MinHeight(EditorGUI.kSingleLineHeight * 2)); - EditorGUI.showMixedValue = false; - GUILayout.EndHorizontal(); - if (EditorGUI.EndChangeCheck()) - m_CustomCharacters.stringValue = new string(guiChars.Distinct().Where(c => c != '\n' && c != '\r').ToArray()); - } - } - else - { - EditorGUILayout.PropertyField(m_IncludeFontData, EditorGUIUtility.TrTextContent("Incl. Font Data")); - // The default font names are different based on font so it'll be a mess if we show - // this GUI when multiple fonts are selected. - if (targets.Length == 1) - { - EditorGUI.BeginChangeCheck(); - - GUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel("Font Names"); - GUI.SetNextControlName("fontnames"); - m_FontNamesString = EditorGUILayout.TextArea(m_FontNamesString, "TextArea", GUILayout.MinHeight(EditorGUI.kSingleLineHeight * 2)); - GUILayout.EndHorizontal(); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - using (new EditorGUI.DisabledScope(m_FontNamesString == m_DefaultFontNamesString)) - { - if (GUILayout.Button("Reset", "MiniButton")) - { - GUI.changed = true; - if (GUI.GetNameOfFocusedControl() == "fontnames") - GUIUtility.keyboardControl = 0; - m_FontNamesString = m_DefaultFontNamesString; - } - } - GUILayout.EndHorizontal(); - - if (EditorGUI.EndChangeCheck()) - SetFontNames(m_FontNamesString); - - m_ReferencesExpanded = EditorGUILayout.Foldout(m_ReferencesExpanded, "References to other fonts in project", true); - if (m_ReferencesExpanded) - { - EditorGUILayout.HelpBox("These are automatically generated by the inspector if any of the font names you supplied match fonts present in your project, which will then be used as fallbacks for this font.", MessageType.Info); - - using (new EditorGUI.DisabledScope(true)) - { - if (m_FallbackFontReferences != null && m_FallbackFontReferences.Length > 0) - { - for (int i = 0; i < m_FallbackFontReferences.Length; ++i) - EditorGUILayout.ObjectField(m_FallbackFontReferences[i], typeof(Font), false); - } - else - { - GUILayout.Label("No references to other fonts in project."); - } - } - } - } - } - } - - ApplyRevertGUI(); - } - } -} diff --git a/Editor/Mono/ImportSettings/VideoClipImporterInspector.cs b/Editor/Mono/ImportSettings/VideoClipImporterInspector.cs deleted file mode 100644 index 4e5b43274d..0000000000 --- a/Editor/Mono/ImportSettings/VideoClipImporterInspector.cs +++ /dev/null @@ -1,897 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using AnimatedBool = UnityEditor.AnimatedValues.AnimBool; -using System.Collections.Generic; -using UnityEditor; -using UnityEditorInternal; -using UnityEngine; -using UnityEditor.Build; -using System; -using UnityEditor.Experimental.AssetImporters; -using Math = System.Math; -using Path = System.IO.Path; - -namespace UnityEditor -{ - [CustomPreview(typeof(VideoClipImporter))] - internal class VideoClipImporterSourcePreview : ObjectPreview - { - class Styles - { - public GUIStyle labelStyle = new GUIStyle(EditorStyles.label); - - public Styles() - { - Color fontColor = new Color(0.7f, 0.7f, 0.7f); - labelStyle.padding.right += 4; - labelStyle.normal.textColor = fontColor; - } - } - - private Styles m_Styles = new Styles(); - - private GUIContent m_Title; - - private const float kLabelWidth = 120; - private const float kIndentWidth = 30; - private const float kValueWidth = 200; - - public override GUIContent GetPreviewTitle() - { - if (m_Title == null) - m_Title = EditorGUIUtility.TrTextContent("Source Info"); - return m_Title; - } - - public override bool HasPreviewGUI() - { - var importer = target as VideoClipImporter; - return importer != null && !importer.useLegacyImporter; - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (Event.current.type != EventType.Repaint) - return; - - var importer = (VideoClipImporter)target; - - RectOffset previewPadding = new RectOffset(-5, -5, -5, -5); - r = previewPadding.Add(r); - - // Prepare rects for columns - r.height = EditorGUIUtility.singleLineHeight; - Rect labelRect = r; - Rect valueRect = r; - labelRect.width = kLabelWidth; - valueRect.xMin += kLabelWidth; - valueRect.width = kValueWidth; - - ShowProperty(ref labelRect, ref valueRect, - "Original Size", EditorUtility.FormatBytes((long)importer.sourceFileSize)); - ShowProperty(ref labelRect, ref valueRect, - "Imported Size", EditorUtility.FormatBytes((long)importer.outputFileSize)); - - var frameCount = importer.frameCount; - var frameRate = importer.frameRate; - var duration = frameRate > 0 - ? TimeSpan.FromSeconds(frameCount / frameRate).ToString() - : new TimeSpan(0).ToString(); - - // TimeSpan uses 7 digits for fractional seconds. Limit this to 3 digits. - if (duration.IndexOf('.') != -1) - duration = duration.Substring(0, duration.Length - 4); - ShowProperty(ref labelRect, ref valueRect, "Duration", duration); - ShowProperty(ref labelRect, ref valueRect, "Frames", frameCount.ToString()); - ShowProperty(ref labelRect, ref valueRect, "FPS", frameRate.ToString("F2")); - - var originalWidth = importer.GetResizeWidth(VideoResizeMode.OriginalSize); - var originalHeight = importer.GetResizeHeight(VideoResizeMode.OriginalSize); - ShowProperty(ref labelRect, ref valueRect, "Pixels", originalWidth + "x" + originalHeight); - ShowProperty(ref labelRect, ref valueRect, "PAR", importer.pixelAspectRatioNumerator + ":" + importer.pixelAspectRatioDenominator); - ShowProperty(ref labelRect, ref valueRect, "Alpha", importer.sourceHasAlpha ? "Yes" : "No"); - - var audioTrackCount = importer.sourceAudioTrackCount; - ShowProperty(ref labelRect, ref valueRect, "Audio", - audioTrackCount == 0 ? "none" : audioTrackCount == 1 ? - GetAudioTrackDescription(importer, 0) : ""); - - if (audioTrackCount <= 1) - return; - - labelRect.xMin += kIndentWidth; - labelRect.width -= kIndentWidth; - - for (ushort i = 0; i < audioTrackCount; ++i) - ShowProperty(ref labelRect, ref valueRect, "Track #" + (i + 1), GetAudioTrackDescription(importer, i)); - } - - private string GetAudioTrackDescription(VideoClipImporter importer, ushort audioTrackIdx) - { - var channelCount = importer.GetSourceAudioChannelCount(audioTrackIdx); - string channelCountStr = - channelCount == 0 ? "No channels" : - channelCount == 1 ? "Mono" : - channelCount == 2 ? "Stereo" : - channelCount == 4 ? channelCount.ToString() : // Can be 3.1 or quad - ((channelCount - 1).ToString() + ".1"); - return importer.GetSourceAudioSampleRate(audioTrackIdx) + " Hz, " + channelCountStr; - } - - private void ShowProperty(ref Rect labelRect, ref Rect valueRect, string label, string value) - { - GUI.Label(labelRect, label, m_Styles.labelStyle); - GUI.Label(valueRect, value, m_Styles.labelStyle); - labelRect.y += EditorGUIUtility.singleLineHeight; - valueRect.y += EditorGUIUtility.singleLineHeight; - } - } - - [CustomEditor(typeof(VideoClipImporter))] - [CanEditMultipleObjects] - internal class VideoClipImporterInspector : AssetImporterEditor - { - internal struct MultiTargetSettingState - { - public void Init() - { - mixedTranscoding = false; - mixedCodec = false; - mixedResizeMode = false; - mixedAspectRatio = false; - mixedCustomWidth = false; - mixedCustomHeight = false; - mixedBitrateMode = false; - mixedSpatialQuality = false; - - firstTranscoding = false; - firstCodec = VideoCodec.Auto; - firstResizeMode = VideoResizeMode.OriginalSize; - firstAspectRatio = VideoEncodeAspectRatio.NoScaling; - firstCustomWidth = -1; - firstCustomHeight = -1; - firstBitrateMode = VideoBitrateMode.High; - firstSpatialQuality = VideoSpatialQuality.HighSpatialQuality; - } - - public bool mixedTranscoding; - public bool mixedCodec; - public bool mixedResizeMode; - public bool mixedAspectRatio; - public bool mixedCustomWidth; - public bool mixedCustomHeight; - public bool mixedBitrateMode; - public bool mixedSpatialQuality; - - public bool firstTranscoding; - public VideoCodec firstCodec; - public VideoResizeMode firstResizeMode; - public VideoEncodeAspectRatio firstAspectRatio; - public int firstCustomWidth; - public int firstCustomHeight; - public VideoBitrateMode firstBitrateMode; - public VideoSpatialQuality firstSpatialQuality; - } - - internal class InspectorTargetSettings - { - public bool overridePlatform; - public VideoImporterTargetSettings settings; - } - - SerializedProperty m_UseLegacyImporter; - SerializedProperty m_Quality; - SerializedProperty m_IsColorLinear; - - SerializedProperty m_EncodeAlpha; - SerializedProperty m_Deinterlace; - SerializedProperty m_FlipVertical; - SerializedProperty m_FlipHorizontal; - SerializedProperty m_ImportAudio; - - // An array of settings for each platform, for every target. - InspectorTargetSettings[,] m_TargetSettings; - - bool m_IsPlaying = false; - Vector2 m_Position = Vector2.zero; - AnimatedBool m_ShowResizeModeOptions = new AnimatedBool(); - bool m_ModifiedTargetSettings; - GUIContent m_PreviewTitle; - - class Styles - { - public GUIContent[] playIcons = - { - EditorGUIUtility.IconContent("preAudioPlayOff"), - EditorGUIUtility.IconContent("preAudioPlayOn") - }; - public GUIContent keepAlphaContent = EditorGUIUtility.TextContent( - "Keep Alpha|If the source clip has alpha, this will encode it in the resulting clip so that transparency is usable during render."); - public GUIContent deinterlaceContent = EditorGUIUtility.TextContent( - "Deinterlace|Remove interlacing on this video."); - public GUIContent flipHorizontalContent = EditorGUIUtility.TextContent( - "Flip Horizontally|Flip the video horizontally during transcoding."); - public GUIContent flipVerticalContent = EditorGUIUtility.TextContent( - "Flip Vertically|Flip the video vertically during transcoding."); - public GUIContent importAudioContent = EditorGUIUtility.TextContent( - "Import Audio|Defines if the audio tracks will be imported during transcoding."); - public GUIContent transcodeContent = EditorGUIUtility.TextContent( - "Transcode|Transcoding a clip gives more flexibility through the options below, but takes more time."); - public GUIContent dimensionsContent = EditorGUIUtility.TextContent( - "Dimensions|Pixel size of the resulting video."); - public GUIContent widthContent = EditorGUIUtility.TextContent( - "Width|Width in pixels of the resulting video."); - public GUIContent heightContent = EditorGUIUtility.TextContent( - "Height|Height in pixels of the resulting video."); - public GUIContent aspectRatioContent = EditorGUIUtility.TextContent( - "Aspect Ratio|How the original video is mapped into the target dimensions."); - public GUIContent codecContent = EditorGUIUtility.TextContent( - "Codec|Codec for the resulting clip. Automatic will make the best choice for the target platform."); - public GUIContent bitrateContent = EditorGUIUtility.TextContent( - "Bitrate Mode|Higher bit rates give a better quality, but impose higher load on network connections or storage."); - public GUIContent spatialQualityContent = EditorGUIUtility.TextContent( - "Spatial Quality|Adds a downsize during import to reduce bitrate using resolution."); - public GUIContent importerVersionContent = EditorGUIUtility.TextContent( - "Importer Version|Selects the type of video asset produced."); - public GUIContent[] importerVersionOptions = - { - EditorGUIUtility.TrTextContent("VideoClip", "Produce VideoClip asset (for use with VideoPlayer)"), - EditorGUIUtility.TrTextContent("MovieTexture (Deprecated)", "Produce MovieTexture asset (deprecated in factor of VideoClip)"), - }; - public GUIContent transcodeWarning = EditorGUIUtility.TextContent( - "Not all platforms transcoded. Clip is not guaranteed to be compatible on platforms without transcoding."); - public GUIContent transcodeSkippedWarning = EditorGUIUtility.TextContent( - "Transcode was skipped. Current clip does not match import settings. Reimport to resolve."); - public GUIContent multipleTranscodeSkippedWarning = EditorGUIUtility.TextContent( - "Transcode was skipped for some clips and they don't match import settings. Reimport to resolve."); - }; - - static Styles s_Styles; - - // Taken in MovieImporter.cpp. - static string[] s_LegacyFileTypes = {".ogg", ".ogv", ".mov", ".asf", ".mpg", ".mpeg", ".mp4"}; - - const int kNarrowLabelWidth = 42; - const int kToggleButtonWidth = 16; - const int kMinCustomWidth = 1; - const int kMaxCustomWidth = 16384; - const int kMinCustomHeight = 1; - const int kMaxCustomHeight = 16384; - - // Don't show the imported movie as a separate editor - public override bool showImportedObject { get { return false; } } - - private void ResetSettingsFromBackend() - { - m_TargetSettings = null; - if (targets.Length > 0) - { - List validPlatforms = BuildPlatforms.instance.GetValidPlatforms(); - m_TargetSettings = new InspectorTargetSettings[targets.Length, validPlatforms.Count + 1]; - - for (int i = 0; i < targets.Length; i++) - { - VideoClipImporter clipImporter = (VideoClipImporter)targets[i]; - - m_TargetSettings[i, 0] = new InspectorTargetSettings(); - m_TargetSettings[i, 0].overridePlatform = true; - m_TargetSettings[i, 0].settings = clipImporter.defaultTargetSettings; - - for (int j = 1; j < validPlatforms.Count + 1; j++) - { - BuildTargetGroup platformGroup = validPlatforms[j - 1].targetGroup; - m_TargetSettings[i, j] = new InspectorTargetSettings(); - m_TargetSettings[i, j].settings = clipImporter.Internal_GetTargetSettings(platformGroup); - - // We need to use this flag, and the nullity of the settings to determine if - // we have an override. This is because we could create an override later during a toggle - // and we want to keep that override even if we untoggle (to not lose the changes made) - m_TargetSettings[i, j].overridePlatform = m_TargetSettings[i, j].settings != null; - } - } - } - - m_ModifiedTargetSettings = false; - } - - private void WriteSettingsToBackend() - { - if (m_TargetSettings != null) - { - List validPlatforms = BuildPlatforms.instance.GetValidPlatforms(); - for (int i = 0; i < targets.Length; i++) - { - VideoClipImporter clipImporter = (VideoClipImporter)targets[i]; - clipImporter.defaultTargetSettings = m_TargetSettings[i, 0].settings; - - for (int j = 1; j < validPlatforms.Count + 1; j++) - { - BuildTargetGroup platformGroup = validPlatforms[j - 1].targetGroup; - if (m_TargetSettings[i, j].settings != null && m_TargetSettings[i, j].overridePlatform) - clipImporter.Internal_SetTargetSettings(platformGroup, m_TargetSettings[i, j].settings); - else - clipImporter.Internal_ClearTargetSettings(platformGroup); - } - } - } - - m_ModifiedTargetSettings = false; - } - - public override void OnEnable() - { - if (s_Styles == null) - s_Styles = new Styles(); - - m_UseLegacyImporter = serializedObject.FindProperty("m_UseLegacyImporter"); - m_Quality = serializedObject.FindProperty("m_Quality"); - m_IsColorLinear = serializedObject.FindProperty("m_IsColorLinear"); - m_EncodeAlpha = serializedObject.FindProperty("m_EncodeAlpha"); - m_Deinterlace = serializedObject.FindProperty("m_Deinterlace"); - m_FlipVertical = serializedObject.FindProperty("m_FlipVertical"); - m_FlipHorizontal = serializedObject.FindProperty("m_FlipHorizontal"); - m_ImportAudio = serializedObject.FindProperty("m_ImportAudio"); - - ResetSettingsFromBackend(); - - // We need to do this so we can calculate the correct fade state - MultiTargetSettingState state = CalculateMultiTargetSettingState(0); - - m_ShowResizeModeOptions.valueChanged.AddListener(Repaint); - m_ShowResizeModeOptions.value = state.mixedResizeMode || (state.firstResizeMode != VideoResizeMode.OriginalSize); - } - - public override void OnDisable() - { - VideoClipImporter importer = target as VideoClipImporter; - if (importer) - importer.StopPreview(); - base.OnDisable(); - } - - private List GetResizeModeList() - { - var resizeModeList = new List(); - VideoClipImporter importer = (VideoClipImporter)target; - foreach (VideoResizeMode mode in System.Enum.GetValues(typeof(VideoResizeMode))) - resizeModeList.Add(EditorGUIUtility.TextContent(importer.GetResizeModeName(mode))); - - return resizeModeList; - } - - private bool AnySettingsNotTranscoded() - { - if (m_TargetSettings != null) - { - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - for (int j = 0; j < m_TargetSettings.GetLength(1); j++) - { - if (m_TargetSettings[i, j].settings != null && !m_TargetSettings[i, j].settings.enableTranscoding) - return true; - } - } - } - - return false; - } - - private MultiTargetSettingState CalculateMultiTargetSettingState(int platformIndex) - { - MultiTargetSettingState state = new MultiTargetSettingState(); - state.Init(); - - if (m_TargetSettings == null || m_TargetSettings.Length == 0) - return state; - - int firstValidIndex = -1; - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - if (m_TargetSettings[i, platformIndex].overridePlatform) - { - if (firstValidIndex == -1) - { - firstValidIndex = i; - - state.firstTranscoding = m_TargetSettings[i, platformIndex].settings.enableTranscoding; - state.firstCodec = m_TargetSettings[i, platformIndex].settings.codec; - state.firstResizeMode = m_TargetSettings[i, platformIndex].settings.resizeMode; - state.firstAspectRatio = m_TargetSettings[i, platformIndex].settings.aspectRatio; - state.firstCustomWidth = m_TargetSettings[i, platformIndex].settings.customWidth; - state.firstCustomHeight = m_TargetSettings[i, platformIndex].settings.customHeight; - state.firstBitrateMode = m_TargetSettings[i, platformIndex].settings.bitrateMode; - state.firstSpatialQuality = m_TargetSettings[i, platformIndex].settings.spatialQuality; - } - else - { - state.mixedTranscoding = state.firstTranscoding != m_TargetSettings[i, platformIndex].settings.enableTranscoding; - state.mixedCodec = state.firstCodec != m_TargetSettings[i, platformIndex].settings.codec; - state.mixedResizeMode = state.firstResizeMode != m_TargetSettings[i, platformIndex].settings.resizeMode; - state.mixedAspectRatio = state.firstAspectRatio != m_TargetSettings[i, platformIndex].settings.aspectRatio; - state.mixedCustomWidth = state.firstCustomWidth != m_TargetSettings[i, platformIndex].settings.customWidth; - state.mixedCustomHeight = state.firstCustomHeight != m_TargetSettings[i, platformIndex].settings.customHeight; - state.mixedBitrateMode = state.firstBitrateMode != m_TargetSettings[i, platformIndex].settings.bitrateMode; - state.mixedSpatialQuality = state.firstSpatialQuality != m_TargetSettings[i, platformIndex].settings.spatialQuality; - } - } - } - - // If there are no override settings for this platform for ANY of the targets, - // then just get the default settings and use those. - if (firstValidIndex == -1) - { - // The default settings are always valid - state.firstTranscoding = m_TargetSettings[0, 0].settings.enableTranscoding; - state.firstCodec = m_TargetSettings[0, 0].settings.codec; - state.firstResizeMode = m_TargetSettings[0, 0].settings.resizeMode; - state.firstAspectRatio = m_TargetSettings[0, 0].settings.aspectRatio; - state.firstCustomWidth = m_TargetSettings[0, 0].settings.customWidth; - state.firstCustomHeight = m_TargetSettings[0, 0].settings.customHeight; - state.firstBitrateMode = m_TargetSettings[0, 0].settings.bitrateMode; - state.firstSpatialQuality = m_TargetSettings[0, 0].settings.spatialQuality; - } - - return state; - } - - private void OnCrossTargetInspectorGUI() - { - bool sourcesHaveAlpha = true; - bool sourcesHaveAudio = true; - for (int i = 0; i < targets.Length; ++i) - { - VideoClipImporter importer = (VideoClipImporter)targets[i]; - sourcesHaveAlpha &= importer.sourceHasAlpha; - sourcesHaveAudio &= (importer.sourceAudioTrackCount > 0); - } - - if (sourcesHaveAlpha) - EditorGUILayout.PropertyField(m_EncodeAlpha, s_Styles.keepAlphaContent); - - EditorGUILayout.PropertyField(m_Deinterlace, s_Styles.deinterlaceContent); - EditorGUILayout.Space(); - - EditorGUILayout.PropertyField(m_FlipHorizontal, s_Styles.flipHorizontalContent); - EditorGUILayout.PropertyField(m_FlipVertical, s_Styles.flipVerticalContent); - EditorGUILayout.Space(); - - using (new EditorGUI.DisabledScope(!sourcesHaveAudio)) - { - EditorGUILayout.PropertyField(m_ImportAudio, s_Styles.importAudioContent); - } - } - - private void FrameSettingsGUI(int platformIndex, MultiTargetSettingState multiState) - { - EditorGUI.showMixedValue = multiState.mixedResizeMode; - EditorGUI.BeginChangeCheck(); - VideoResizeMode resizeMode = (VideoResizeMode)EditorGUILayout.Popup(s_Styles.dimensionsContent, (int)multiState.firstResizeMode, GetResizeModeList().ToArray()); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - if (m_TargetSettings[i, platformIndex].settings != null) - { - m_TargetSettings[i, platformIndex].settings.resizeMode = resizeMode; - m_ModifiedTargetSettings = true; - } - } - } - - // First item is "Original". Options appear if another resize mode is chosen. - m_ShowResizeModeOptions.target = resizeMode != VideoResizeMode.OriginalSize; - if (EditorGUILayout.BeginFadeGroup(m_ShowResizeModeOptions.faded)) - { - EditorGUI.indentLevel++; - - if (resizeMode == VideoResizeMode.CustomSize) - { - EditorGUI.showMixedValue = multiState.mixedCustomWidth; - EditorGUI.BeginChangeCheck(); - int customWidth = EditorGUILayout.IntField(s_Styles.widthContent, multiState.firstCustomWidth); - customWidth = Mathf.Clamp(customWidth, kMinCustomWidth, kMaxCustomWidth); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - if (m_TargetSettings[i, platformIndex].settings != null) - { - m_TargetSettings[i, platformIndex].settings.customWidth = customWidth; - m_ModifiedTargetSettings = true; - } - } - } - - EditorGUI.showMixedValue = multiState.mixedCustomHeight; - EditorGUI.BeginChangeCheck(); - int customHeight = EditorGUILayout.IntField(s_Styles.heightContent, multiState.firstCustomHeight); - customHeight = Mathf.Clamp(customHeight, kMinCustomHeight, kMaxCustomHeight); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - if (m_TargetSettings[i, platformIndex].settings != null) - { - m_TargetSettings[i, platformIndex].settings.customHeight = customHeight; - m_ModifiedTargetSettings = true; - } - } - } - } - - EditorGUI.showMixedValue = multiState.mixedAspectRatio; - EditorGUI.BeginChangeCheck(); - VideoEncodeAspectRatio aspectRatio = (VideoEncodeAspectRatio)EditorGUILayout.EnumPopup(s_Styles.aspectRatioContent, multiState.firstAspectRatio); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - if (m_TargetSettings[i, platformIndex].settings != null) - { - m_TargetSettings[i, platformIndex].settings.aspectRatio = aspectRatio; - m_ModifiedTargetSettings = true; - } - } - } - - EditorGUI.indentLevel--; - } - - EditorGUILayout.EndFadeGroup(); - } - - private void EncodingSettingsGUI(int platformIndex, MultiTargetSettingState multiState) - { - EditorGUI.showMixedValue = multiState.mixedCodec; - EditorGUI.BeginChangeCheck(); - VideoCodec codec = (VideoCodec)EditorGUILayout.EnumPopup(s_Styles.codecContent, multiState.firstCodec); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - if (m_TargetSettings[i, platformIndex].settings != null) - { - m_TargetSettings[i, platformIndex].settings.codec = codec; - m_ModifiedTargetSettings = true; - } - } - } - - EditorGUI.showMixedValue = multiState.mixedBitrateMode; - EditorGUI.BeginChangeCheck(); - VideoBitrateMode bitrateMode = (VideoBitrateMode)EditorGUILayout.EnumPopup(s_Styles.bitrateContent, multiState.firstBitrateMode); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - if (m_TargetSettings[i, platformIndex].settings != null) - { - m_TargetSettings[i, platformIndex].settings.bitrateMode = bitrateMode; - m_ModifiedTargetSettings = true; - } - } - } - - EditorGUI.showMixedValue = multiState.mixedSpatialQuality; - EditorGUI.BeginChangeCheck(); - VideoSpatialQuality spatialQuality = (VideoSpatialQuality)EditorGUILayout.EnumPopup(s_Styles.spatialQualityContent, multiState.firstSpatialQuality); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - if (m_TargetSettings[i, platformIndex].settings != null) - { - m_TargetSettings[i, platformIndex].settings.spatialQuality = spatialQuality; - m_ModifiedTargetSettings = true; - } - } - } - } - - private bool HasMixedOverrideStatus(int platformIndex, out bool overrideState) - { - overrideState = false; - if (m_TargetSettings == null || m_TargetSettings.Length == 0) - return false; - - overrideState = m_TargetSettings[0, platformIndex].overridePlatform; - for (int i = 1; i < m_TargetSettings.GetLength(0); i++) - { - if (m_TargetSettings[i, platformIndex].overridePlatform != overrideState) - return true; - } - - return false; - } - - private VideoImporterTargetSettings CloneTargetSettings(VideoImporterTargetSettings settings) - { - VideoImporterTargetSettings newSettings = new VideoImporterTargetSettings(); - - newSettings.enableTranscoding = settings.enableTranscoding; - newSettings.codec = settings.codec; - newSettings.resizeMode = settings.resizeMode; - newSettings.aspectRatio = settings.aspectRatio; - newSettings.customWidth = settings.customWidth; - newSettings.customHeight = settings.customHeight; - newSettings.bitrateMode = settings.bitrateMode; - newSettings.spatialQuality = settings.spatialQuality; - - return newSettings; - } - - private void OnTargetSettingsInspectorGUI(int platformIndex, MultiTargetSettingState multiState) - { - EditorGUI.showMixedValue = multiState.mixedTranscoding; - EditorGUI.BeginChangeCheck(); - bool transcode = EditorGUILayout.Toggle(s_Styles.transcodeContent, multiState.firstTranscoding); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - if (m_TargetSettings[i, platformIndex].settings != null) - { - m_TargetSettings[i, platformIndex].settings.enableTranscoding = transcode; - m_ModifiedTargetSettings = true; - } - } - } - - EditorGUI.indentLevel++; - - using (new EditorGUI.DisabledScope(!(transcode || multiState.mixedTranscoding))) - { - FrameSettingsGUI(platformIndex, multiState); - EncodingSettingsGUI(platformIndex, multiState); - } - - EditorGUI.indentLevel--; - } - - private void OnTargetInspectorGUI(int platformIndex, string platformName) - { - bool enableOverrideSettings = true; - if (platformIndex != 0) - { - bool overrideState; - EditorGUI.showMixedValue = HasMixedOverrideStatus(platformIndex, out overrideState); - EditorGUI.BeginChangeCheck(); - overrideState = EditorGUILayout.Toggle("Override for " + platformName, overrideState); - enableOverrideSettings = overrideState || EditorGUI.showMixedValue; - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < m_TargetSettings.GetLength(0); i++) - { - m_TargetSettings[i, platformIndex].overridePlatform = overrideState; - m_ModifiedTargetSettings = true; - if (m_TargetSettings[i, platformIndex].settings == null) - m_TargetSettings[i, platformIndex].settings = CloneTargetSettings(m_TargetSettings[i, 0].settings); - } - } - } - - EditorGUILayout.Space(); - - MultiTargetSettingState multiState = CalculateMultiTargetSettingState(platformIndex); - using (new EditorGUI.DisabledScope(!enableOverrideSettings)) - { - OnTargetSettingsInspectorGUI(platformIndex, multiState); - } - } - - private void OnTargetsInspectorGUI() - { - BuildPlatform[] validPlatforms = BuildPlatforms.instance.GetValidPlatforms().ToArray(); - int shownSettingsPage = EditorGUILayout.BeginPlatformGrouping(validPlatforms, GUIContent.Temp("Default")); - - string platformName = (shownSettingsPage == -1) ? "Default" : validPlatforms[shownSettingsPage].name; - OnTargetInspectorGUI(shownSettingsPage + 1, platformName); - - EditorGUILayout.EndPlatformGrouping(); - } - - internal override void OnHeaderControlsGUI() - { - serializedObject.UpdateIfRequiredOrScript(); - - bool supportsLegacy = true; - for (int i = 0; supportsLegacy && i < targets.Length; ++i) - { - VideoClipImporter importer = (VideoClipImporter)targets[i]; - supportsLegacy &= IsFileSupportedByLegacy(importer.assetPath); - } - - if (!supportsLegacy) - { - base.OnHeaderControlsGUI(); - return; - } - - EditorGUI.showMixedValue = m_UseLegacyImporter.hasMultipleDifferentValues; - EditorGUI.BeginChangeCheck(); - var originalLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 100; - int selectionIndex = EditorGUILayout.Popup( - s_Styles.importerVersionContent, m_UseLegacyImporter.boolValue ? 1 : 0, - s_Styles.importerVersionOptions, EditorStyles.popup, GUILayout.MaxWidth(230)); - EditorGUIUtility.labelWidth = originalLabelWidth; - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - m_UseLegacyImporter.boolValue = selectionIndex == 1; - - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Open", EditorStyles.miniButton)) - { - AssetDatabase.OpenAsset(assetTargets); - GUIUtility.ExitGUI(); - } - } - - public override void OnInspectorGUI() - { - serializedObject.UpdateIfRequiredOrScript(); - - if (m_UseLegacyImporter.boolValue) - { - EditorGUILayout.PropertyField( - m_IsColorLinear, MovieImporterInspector.linearTextureContent); - EditorGUILayout.Slider(m_Quality, 0.0f, 1.0f); - } - else - { - OnCrossTargetInspectorGUI(); - EditorGUILayout.Space(); - OnTargetsInspectorGUI(); - - // Warn the user if there is no transcoding happening on at least one platform - if (AnySettingsNotTranscoded()) - EditorGUILayout.HelpBox(s_Styles.transcodeWarning.text, MessageType.Info); - } - - foreach (var t in targets) - { - VideoClipImporter importer = t as VideoClipImporter; - if (importer && importer.transcodeSkipped) - { - EditorGUILayout.HelpBox( - targets.Length == 1 ? s_Styles.transcodeSkippedWarning.text : - s_Styles.multipleTranscodeSkippedWarning.text, - MessageType.Error); - break; - } - } - - ApplyRevertGUI(); - } - - public override bool HasModified() - { - if (base.HasModified()) - return true; - - return m_ModifiedTargetSettings; - } - - protected override void Apply() - { - base.Apply(); - WriteSettingsToBackend(); - - // This is necessary to enforce redrawing the static preview icons in the project browser, as properties like ForceToMono - // may have changed the preview completely. - foreach (ProjectBrowser pb in ProjectBrowser.GetAllProjectBrowsers()) - pb.Repaint(); - } - - public override bool HasPreviewGUI() - { - return target != null; - } - - protected override bool useAssetDrawPreview { get { return false; } } - - public override GUIContent GetPreviewTitle() - { - if (m_PreviewTitle != null) - return m_PreviewTitle; - - m_PreviewTitle = new GUIContent(); - - if (targets.Length == 1) - { - AssetImporter importer = (AssetImporter)target; - m_PreviewTitle.text = Path.GetFileName(importer.assetPath); - } - else - m_PreviewTitle.text = targets.Length + " Video Clips"; - - return m_PreviewTitle; - } - - protected override void ResetValues() - { - base.ResetValues(); - OnEnable(); - } - - public override void OnPreviewSettings() - { - VideoClipImporter importer = (VideoClipImporter)target; - EditorGUI.BeginDisabledGroup(Application.isPlaying || HasModified() || importer.useLegacyImporter); - m_IsPlaying = PreviewGUI.CycleButton(m_IsPlaying ? 1 : 0, s_Styles.playIcons) != 0; - EditorGUI.EndDisabledGroup(); - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - var isRepainting = Event.current.type == EventType.Repaint; - if (isRepainting) - background.Draw(r, false, false, false, false); - - VideoClipImporter importer = (VideoClipImporter)target; - - if (m_IsPlaying && !importer.isPlayingPreview) - importer.PlayPreview(); - else if (!m_IsPlaying && importer.isPlayingPreview) - importer.StopPreview(); - - Texture image = importer.GetPreviewTexture(); - if (!image || image.width == 0 || image.height == 0) - return; - - // Compensate spatial quality zooming, if any. - float previewWidth = image.width; - float previewHeight = image.height; - if (importer.defaultTargetSettings.enableTranscoding) - { - VideoResizeMode resizeMode = importer.defaultTargetSettings.resizeMode; - previewWidth = importer.GetResizeWidth(resizeMode); - previewHeight = importer.GetResizeHeight(resizeMode); - } - - if (importer.pixelAspectRatioDenominator > 0) - previewWidth *= (float)importer.pixelAspectRatioNumerator / - (float)importer.pixelAspectRatioDenominator; - - float zoomLevel = 1.0f; - - if ((r.width / previewWidth * previewHeight) > r.height) - zoomLevel = r.height / previewHeight; - else - zoomLevel = r.width / previewWidth; - - zoomLevel = Mathf.Clamp01(zoomLevel); - - Rect wantedRect = new Rect(r.x, r.y, previewWidth * zoomLevel, previewHeight * zoomLevel); - - PreviewGUI.BeginScrollView( - r, m_Position, wantedRect, "PreHorizontalScrollbar", "PreHorizontalScrollbarThumb"); - - EditorGUI.DrawTextureTransparent(wantedRect, image, ScaleMode.StretchToFill); - - m_Position = PreviewGUI.EndScrollView(); - - if (m_IsPlaying && isRepainting) - GUIView.current.Repaint(); - } - - private bool IsFileSupportedByLegacy(string assetPath) - { - return System.Array.IndexOf( - s_LegacyFileTypes, Path.GetExtension(assetPath).ToLower()) != -1; - } - } -} - diff --git a/Editor/Mono/Inspector/AddComponent/AddComponentDataSource.cs b/Editor/Mono/Inspector/AddComponent/AddComponentDataSource.cs deleted file mode 100644 index 0c80858a4a..0000000000 --- a/Editor/Mono/Inspector/AddComponent/AddComponentDataSource.cs +++ /dev/null @@ -1,107 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - internal class AddComponentDataSource : AdvancedDropdownDataSource - { - protected override AdvancedDropdownItem FetchData() - { - return RebuildTree(); - } - - protected AdvancedDropdownItem RebuildTree() - { - AdvancedDropdownItem root = new ComponentDropdownItem(); - var menuDictionary = GetMenuDictionary(); - menuDictionary.Sort(CompareItems); - for (var i = 0; i < menuDictionary.Count; i++) - { - var menu = menuDictionary[i]; - if (menu.Value == "ADD") - { - continue; - } - - var menuPath = menu.Key; - var paths = menuPath.Split('/'); - - var parent = root; - for (var j = 0; j < paths.Length; j++) - { - var path = paths[j]; - if (j == paths.Length - 1) - { - var element = new ComponentDropdownItem(LocalizationDatabase.GetLocalizedString(path), menuPath, menu.Value); - element.searchable = true; - element.SetParent(parent); - parent.AddChild(element); - continue; - } - var group = parent.children.SingleOrDefault(c => c.name == path); - if (group == null) - { - group = new ComponentDropdownItem(path, -1); - group.SetParent(parent); - parent.AddChild(group); - } - parent = group; - } - } - root = root.children.Single(); - root.SetParent(null); - var newScript = new ComponentDropdownItem("New script", -1); - newScript.AddChild(new NewScriptDropdownItem()); - newScript.SetParent(root); - root.AddChild(newScript); - return root; - } - - private static List> GetMenuDictionary() - { - var menus = Unsupported.GetSubmenus("Component"); - var commands = Unsupported.GetSubmenusCommands("Component"); - - var menuDictionary = new Dictionary(menus.Length); - for (var i = 0; i < menus.Length; i++) - { - menuDictionary.Add(menus[i], commands[i]); - } - return menuDictionary.ToList(); - } - - private int CompareItems(KeyValuePair x, KeyValuePair y) - { - var legacyString = "legacy"; - var isStr1Legacy = x.Key.ToLower().Contains(legacyString); - var isStr2Legacy = y.Key.ToLower().Contains(legacyString); - if (isStr1Legacy && isStr2Legacy) - return x.Key.CompareTo(y.Key); - if (isStr1Legacy) - return 1; - if (isStr2Legacy) - return -1; - return x.Key.CompareTo(y.Key); - } - - protected override AdvancedDropdownItem Search(string searchString) - { - var searchTree = base.Search(searchString); - if (searchTree != null) - { - var addNewScriptGroup = new ComponentDropdownItem("New script", -1); - var addNewScript = new NewScriptDropdownItem(); - addNewScript.className = searchString; - addNewScriptGroup.AddChild(addNewScript); - addNewScript.SetParent(addNewScriptGroup); - addNewScriptGroup.SetParent(searchTree); - searchTree.AddChild(addNewScriptGroup); - } - return searchTree; - } - } -} diff --git a/Editor/Mono/Inspector/AddComponent/AddComponentGUI.cs b/Editor/Mono/Inspector/AddComponent/AddComponentGUI.cs deleted file mode 100644 index e229487736..0000000000 --- a/Editor/Mono/Inspector/AddComponent/AddComponentGUI.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class AddComponentGUI : AdvancedDropdownGUI - { - private Vector2 m_IconSize = new Vector2(16, 16); - public override Vector2 iconSize => m_IconSize; - - public override void DrawItem(AdvancedDropdownItem item, bool selected, bool hasSearch) - { - var nsItem = item as NewScriptDropdownItem; - if (nsItem == null) - { - base.DrawItem(item, selected, hasSearch); - return; - } - - GUILayout.Label("Name", EditorStyles.label); - - EditorGUI.FocusTextInControl("NewScriptName"); - GUI.SetNextControlName("NewScriptName"); - - nsItem.m_ClassName = EditorGUILayout.TextField(nsItem.m_ClassName); - - EditorGUILayout.Space(); - - EditorGUILayout.EnumPopup("Language", NewScriptDropdownItem.Language.CSharp); - - EditorGUILayout.Space(); - - var canCreate = nsItem.CanCreate(); - if (!canCreate && nsItem.m_ClassName != "") - GUILayout.Label(nsItem.GetError(), EditorStyles.helpBox); - - GUILayout.FlexibleSpace(); - - using (new EditorGUI.DisabledScope(!canCreate)) - { - if (GUILayout.Button("Create and Add")) - { - nsItem.Create(AddComponentWindow.s_AddComponentWindow.m_GameObjects); - } - } - - EditorGUILayout.Space(); - } - - internal override string DrawSearchFieldControl(string searchString) - { - float padding = 8f; - m_SearchRect = GUILayoutUtility.GetRect(0, 0); - m_SearchRect.x += padding; - m_SearchRect.y = 7; - m_SearchRect.width -= padding * 2; - m_SearchRect.height = 30; - var newSearch = EditorGUI.SearchField(m_SearchRect, searchString); - return newSearch; - } - } -} diff --git a/Editor/Mono/Inspector/AddComponent/AddComponentWindow.cs b/Editor/Mono/Inspector/AddComponent/AddComponentWindow.cs deleted file mode 100644 index e7e6208cf6..0000000000 --- a/Editor/Mono/Inspector/AddComponent/AddComponentWindow.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - [InitializeOnLoad] - internal class AddComponentWindow : AdvancedDropdownWindow - { - [Serializable] - internal class AnalyticsEventData - { - public string name; - public string filter; - public bool isNewScript; - } - - internal static AddComponentWindow s_AddComponentWindow = null; - - internal GameObject[] m_GameObjects; - internal string searchString => m_Search; - - private DateTime m_ComponentOpenTime; - private const string kComponentSearch = "ComponentSearchString"; - - public const string OpenAddComponentDropdown = "OpenAddComponentDropdown"; - - protected override bool isSearchFieldDisabled - { - get - { - var child = m_CurrentlyRenderedTree.GetSelectedChild(); - if (child != null) - return child is NewScriptDropdownItem; - return false; - } - } - - protected override void OnEnable() - { - base.OnEnable(); - gui = new AddComponentGUI(); - dataSource = new AddComponentDataSource(); - s_AddComponentWindow = this; - m_Search = EditorPrefs.GetString(kComponentSearch, ""); - showHeader = true; - } - - protected override void OnDisable() - { - s_AddComponentWindow = null; - EditorPrefs.SetString(kComponentSearch, m_Search); - } - - internal static bool Show(Rect rect, GameObject[] gos) - { - CloseAllOpenWindows(); - - Event.current.Use(); - s_AddComponentWindow = CreateAndInit(rect); - s_AddComponentWindow.m_GameObjects = gos; - s_AddComponentWindow.m_ComponentOpenTime = DateTime.UtcNow; - return true; - } - - protected override bool SpecialKeyboardHandling(Event evt) - { - var createScriptMenu = m_CurrentlyRenderedTree.GetSelectedChild(); - if (createScriptMenu is NewScriptDropdownItem) - { - // When creating new script name we want to dedicate both left/right arrow and backspace - // to editing the script name so they can't be used for navigating the menus. - // The only way to get back using the keyboard is pressing Esc. - if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter) - { - createScriptMenu.OnAction(); - evt.Use(); - GUIUtility.ExitGUI(); - } - if (evt.keyCode == KeyCode.Escape) - { - GoToParent(); - evt.Use(); - } - return true; - } - return false; - } - - internal static void SendUsabilityAnalyticsEvent(AnalyticsEventData eventData) - { - var openTime = s_AddComponentWindow.m_ComponentOpenTime; - UsabilityAnalytics.SendEvent("executeAddComponentWindow", openTime, DateTime.UtcNow - openTime, false, eventData); - } - - [UsedByNativeCode] - internal static bool ValidateAddComponentMenuItem() - { - if (FirstInspectorWithGameObject() != null) - return true; - return false; - } - - [UsedByNativeCode] - internal static void ExecuteAddComponentMenuItem() - { - var insp = FirstInspectorWithGameObject(); - if (insp != null) - insp.SendEvent(EditorGUIUtility.CommandEvent(OpenAddComponentDropdown)); - } - - private static InspectorWindow FirstInspectorWithGameObject() - { - foreach (var insp in InspectorWindow.GetInspectors()) - if (insp.GetInspectedObject() is GameObject) - return insp; - return null; - } - } -} diff --git a/Editor/Mono/Inspector/AddComponent/ComponentDropdownItem.cs b/Editor/Mono/Inspector/AddComponent/ComponentDropdownItem.cs deleted file mode 100644 index 7ed47e5d00..0000000000 --- a/Editor/Mono/Inspector/AddComponent/ComponentDropdownItem.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class ComponentDropdownItem : AdvancedDropdownItem - { - private string m_MenuPath; - private bool m_IsLegacy; - - private static class Styles - { - public static GUIStyle itemStyle = new GUIStyle("PR Label"); - - static Styles() - { - itemStyle.alignment = TextAnchor.MiddleLeft; - itemStyle.padding.left = 0; - itemStyle.fixedHeight = 20; - itemStyle.margin = new RectOffset(0, 0, 0, 0); - } - } - - public override GUIStyle lineStyle => Styles.itemStyle; - - internal ComponentDropdownItem() : base("ROOT", -1) - { - } - - public ComponentDropdownItem(string path, int menuPath) : base(path, menuPath) - { - } - - public ComponentDropdownItem(string name, string menuPath, string command) : base(name, -1) - { - m_MenuPath = menuPath; - m_IsLegacy = menuPath.Contains("Legacy"); - - if (command.StartsWith("SCRIPT")) - { - var scriptId = int.Parse(command.Substring(6)); - var obj = EditorUtility.InstanceIDToObject(scriptId); - var icon = AssetPreview.GetMiniThumbnail(obj); - m_Content = new GUIContent(name, icon); - } - else - { - var classId = int.Parse(command); - m_Content = new GUIContent(name, AssetPreview.GetMiniTypeThumbnailFromClassID(classId)); - } - m_ContentWhenSearching = new GUIContent(m_Content); - if (m_IsLegacy) - { - m_ContentWhenSearching.text += " (Legacy)"; - } - } - - public override int CompareTo(object o) - { - if (o is ComponentDropdownItem) - { - // legacy elements should always come after non legacy elements - var componentElement = (ComponentDropdownItem)o; - if (m_IsLegacy && !componentElement.m_IsLegacy) - return 1; - if (!m_IsLegacy && componentElement.m_IsLegacy) - return -1; - } - return base.CompareTo(o); - } - - public override bool OnAction() - { - AddComponentWindow.SendUsabilityAnalyticsEvent(new AddComponentWindow.AnalyticsEventData - { - name = name, - filter = AddComponentWindow.s_AddComponentWindow.searchString, - isNewScript = false - }); - - var gos = AddComponentWindow.s_AddComponentWindow.m_GameObjects; - EditorApplication.ExecuteMenuItemOnGameObjects(m_MenuPath, gos); - return true; - } - - public override string ToString() - { - return m_MenuPath; - } - } -} diff --git a/Editor/Mono/Inspector/AddComponent/NewScriptDropdownItem.cs b/Editor/Mono/Inspector/AddComponent/NewScriptDropdownItem.cs deleted file mode 100644 index 33a9833dd7..0000000000 --- a/Editor/Mono/Inspector/AddComponent/NewScriptDropdownItem.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Linq; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - class NewScriptDropdownItem : AdvancedDropdownItem - { - private readonly char[] kInvalidPathChars = new char[] {'<', '>', ':', '"', '|', '?', '*', (char)0}; - private readonly char[] kPathSepChars = new char[] {'/', '\\'}; - private readonly string kResourcesTemplatePath = "Resources/ScriptTemplates"; - - private string m_Directory = string.Empty; - - internal string m_ClassName = "NewBehaviourScript"; - - public string className - { - set { m_ClassName = value; } - get { return m_ClassName; } - } - - internal enum Language - { - CSharp = 0 - } - - public NewScriptDropdownItem() : base("New Script", -1) {} - - public override bool OnAction() - { - Create(AddComponentWindow.s_AddComponentWindow.m_GameObjects); - GUIUtility.ExitGUI(); - return true; - } - - internal bool CanCreate() - { - return m_ClassName.Length > 0 && - !File.Exists(TargetPath()) && - !ClassAlreadyExists() && - !ClassNameIsInvalid() && - !InvalidTargetPath(); - } - - public string GetError() - { - // Create string to tell the user what the problem is - var blockReason = string.Empty; - if (m_ClassName != string.Empty) - { - if (File.Exists(TargetPath())) - blockReason = "A script called \"" + m_ClassName + "\" already exists at that path."; - else if (ClassAlreadyExists()) - blockReason = "A class called \"" + m_ClassName + "\" already exists."; - else if (ClassNameIsInvalid()) - blockReason = "The script name may only consist of a-z, A-Z, 0-9, _."; - else if (InvalidTargetPath()) - blockReason = "The folder path contains invalid characters."; - } - return blockReason; - } - - internal void Create(GameObject[] gameObjects) - { - if (!CanCreate()) - return; - - CreateScript(); - - foreach (var go in gameObjects) - { - var script = AssetDatabase.LoadAssetAtPath(TargetPath(), typeof(MonoScript)) as MonoScript; - script.SetScriptTypeWasJustCreatedFromComponentMenu(); - InternalEditorUtility.AddScriptComponentUncheckedUndoable(go, script); - } - - AddComponentWindow.SendUsabilityAnalyticsEvent(new AddComponentWindow.AnalyticsEventData - { - name = m_ClassName, - filter = AddComponentWindow.s_AddComponentWindow.searchString, - isNewScript = true - }); - - AddComponentWindow.s_AddComponentWindow.Close(); - } - - private bool InvalidTargetPath() - { - if (m_Directory.IndexOfAny(kInvalidPathChars) >= 0) - return true; - if (TargetDir().Split(kPathSepChars, StringSplitOptions.None).Contains(string.Empty)) - return true; - return false; - } - - private string TargetPath() - { - return Path.Combine(TargetDir(), m_ClassName + ".cs"); - } - - private string TargetDir() - { - return Path.Combine("Assets", m_Directory.Trim(kPathSepChars)); - } - - private bool ClassNameIsInvalid() - { - return !System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(m_ClassName); - } - - private bool ClassExists(string className) - { - return AppDomain.CurrentDomain.GetAssemblies() - .Any(a => a.GetType(className, false) != null); - } - - private bool ClassAlreadyExists() - { - if (m_ClassName == string.Empty) - return false; - return ClassExists(m_ClassName); - } - - private void CreateScript() - { - var basePath = Path.Combine(EditorApplication.applicationContentsPath, kResourcesTemplatePath); - var templatePath = Path.Combine(basePath, "81-C# Script-NewBehaviourScript.cs.txt"); - ProjectWindowUtil.CreateScriptAssetFromTemplate(TargetPath(), templatePath); - AssetDatabase.Refresh(); - } - } -} diff --git a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownDataSource.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownDataSource.cs deleted file mode 100644 index 76a3a39cfb..0000000000 --- a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownDataSource.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; - -namespace UnityEditor -{ - internal abstract class AdvancedDropdownDataSource - { - private const string kSearchHeader = "Search"; - - private AdvancedDropdownItem m_MainTree; - private AdvancedDropdownItem m_SearchTree; - - public AdvancedDropdownItem mainTree { get { return m_MainTree; }} - public AdvancedDropdownItem searchTree { get { return m_SearchTree; }} - - public void ReloadData() - { - m_MainTree = FetchData(); - } - - protected abstract AdvancedDropdownItem FetchData(); - - public void RebuildSearch(string search) - { - m_SearchTree = Search(search); - } - - virtual protected AdvancedDropdownItem Search(string searchString) - { - if (string.IsNullOrEmpty(searchString)) - return null; - - // Support multiple search words separated by spaces. - var searchWords = searchString.ToLower().Split(' '); - - // We keep two lists. Matches that matches the start of an item always get first priority. - var matchesStart = new List(); - var matchesWithin = new List(); - - foreach (var e in m_MainTree.GetSearchableElements()) - { - var name = e.name.ToLower().Replace(" ", ""); - - var didMatchAll = true; - var didMatchStart = false; - - // See if we match ALL the seaarch words. - for (var w = 0; w < searchWords.Length; w++) - { - var search = searchWords[w]; - if (name.Contains(search)) - { - // If the start of the item matches the first search word, make a note of that. - if (w == 0 && name.StartsWith(search)) - didMatchStart = true; - } - else - { - // As soon as any word is not matched, we disregard this item. - didMatchAll = false; - break; - } - } - // We always need to match all search words. - // If we ALSO matched the start, this item gets priority. - if (didMatchAll) - { - if (didMatchStart) - matchesStart.Add(e); - else - matchesWithin.Add(e); - } - } - - matchesStart.Sort(); - matchesWithin.Sort(); - - var searchTree = new AdvancedDropdownItem(kSearchHeader, -1); - foreach (var element in matchesStart) - { - searchTree.AddChild(element); - } - foreach (var element in matchesWithin) - { - searchTree.AddChild(element); - } - return searchTree; - } - } -} diff --git a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs deleted file mode 100644 index 1939131d15..0000000000 --- a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownGUI.cs +++ /dev/null @@ -1,151 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using Event = UnityEngine.Event; - -namespace UnityEditor -{ - internal class AdvancedDropdownGUI - { - protected static class Styles - { - public static GUIStyle header = new GUIStyle(EditorStyles.inspectorBig); - public static GUIStyle rightArrow = "AC RightArrow"; - public static GUIStyle leftArrow = "AC LeftArrow"; - public static GUIStyle lineSeparator = new GUIStyle(); - - static Styles() - { - header.font = EditorStyles.boldLabel.font; - header.margin = new RectOffset(0, 0, 0, 0); - - lineSeparator.fixedHeight = 1; - lineSeparator.margin.bottom = 2; - lineSeparator.margin.top = 2; - } - } - - protected Rect m_SearchRect; - public virtual float HeaderHeight => m_SearchRect.height; - - private const int kWindowHeight = 395 - 80; - public virtual float WindowHeight => kWindowHeight; - - //This should ideally match line height - private Vector2 s_IconSize = new Vector2(13, 13); - public virtual Vector2 iconSize => s_IconSize; - - public virtual void DrawItem(AdvancedDropdownItem item, bool selected, bool hasSearch) - { - if (item.IsSeparator()) - { - DrawLineSeparator(); - return; - } - - var content = !hasSearch ? item.content : item.contentWhenSearching; - var rect = GUILayoutUtility.GetRect(content, item.lineStyle, GUILayout.ExpandWidth(true)); - if (item.IsSeparator() || Event.current.type != EventType.Repaint) - return; - - if (content.image == null) - { - item.lineStyle.Draw(rect, GUIContent.none, false, false, selected, selected); - rect.x += iconSize.x; - rect.width -= iconSize.x; - } - item.lineStyle.Draw(rect, content, false, false, selected, selected); - if (item.drawArrow) - { - var size = Styles.rightArrow.lineHeight; - var yOffset = item.lineStyle.fixedHeight / 2 - size / 2; - Rect arrowRect = new Rect(rect.x + rect.width - size, rect.y + yOffset, size, size); - Styles.rightArrow.Draw(arrowRect, false, false, false, false); - } - } - - protected virtual void DrawLineSeparator() - { - var rect = GUILayoutUtility.GetRect(GUIContent.none, Styles.lineSeparator, GUILayout.ExpandWidth(true)); - if (Event.current.type != EventType.Repaint) - return; - EditorGUIUtility.DrawVerticalSplitter(rect); - } - - public void DrawHeader(AdvancedDropdownItem group, Action backButtonPressed) - { - var content = GUIContent.Temp(group.name); - var headerRect = GUILayoutUtility.GetRect(content, Styles.header, GUILayout.ExpandWidth(true)); - - if (Event.current.type == EventType.Repaint) - Styles.header.Draw(headerRect, content, false, false, false, false); - - // Back button - if (group.parent != null) - { - var arrowSize = 13; - var y = headerRect.y + (headerRect.height / 2 - arrowSize / 2); - var arrowRect = new Rect(headerRect.x + 4, y, arrowSize, arrowSize); - if (Event.current.type == EventType.Repaint) - Styles.leftArrow.Draw(arrowRect, false, false, false, false); - if (Event.current.type == EventType.MouseDown && headerRect.Contains(Event.current.mousePosition)) - { - backButtonPressed(); - Event.current.Use(); - } - } - } - - public void DrawSearchField(bool isSearchFieldDisabled, string searchString, Action searchChanged) - { - if (!isSearchFieldDisabled) - { - EditorGUI.FocusTextInControl("ComponentSearch"); - } - - using (new EditorGUI.DisabledScope(isSearchFieldDisabled)) - { - GUI.SetNextControlName("ComponentSearch"); - - var newSearch = DrawSearchFieldControl(searchString); - - if (newSearch != searchString) - { - searchChanged(newSearch); - } - } - } - - internal virtual string DrawSearchFieldControl(string searchString) - { - var paddingX = 8f; - var paddingY = 2f; - m_SearchRect = GUILayoutUtility.GetRect(0, 0); - m_SearchRect.x += paddingX; - m_SearchRect.y += paddingY; - m_SearchRect.height = EditorStyles.toolbarSearchField.fixedHeight + paddingY * 2; - // Adjust to the frame - m_SearchRect.y += 1; - m_SearchRect.height += 1; - m_SearchRect.width -= paddingX * 2; - var newSearch = EditorGUI.ToolbarSearchField(m_SearchRect, searchString, false); - return newSearch; - } - - public Rect GetAnimRect(Rect position, float anim) - { - // Calculate rect for animated area - var rect = new Rect(position); - rect.x = position.width * anim; - rect.y = HeaderHeight; - rect.height -= HeaderHeight; - // Adjust to the frame - rect.x += 1; - rect.width -= 2; - return rect; - } - } -} diff --git a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownItem.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownItem.cs deleted file mode 100644 index c40e5e010b..0000000000 --- a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownItem.cs +++ /dev/null @@ -1,202 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using Event = UnityEngine.Event; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AdvancedDropdownItem : IComparable - { - internal static AdvancedDropdownItem s_SeparatorItem = new SeparatorDropdownItem(); - - private static class Styles - { - public static GUIStyle itemStyle = new GUIStyle("PR Label"); - - static Styles() - { - itemStyle.alignment = TextAnchor.MiddleLeft; - itemStyle.padding = new RectOffset(0, 0, 2, 2); - itemStyle.margin = new RectOffset(0, 0, 0, 0); - } - } - - public virtual GUIStyle lineStyle => Styles.itemStyle; - - protected GUIContent m_Content; - public virtual GUIContent content => m_Content; - - protected GUIContent m_ContentWhenSearching; - public virtual GUIContent contentWhenSearching => m_ContentWhenSearching; - - private string m_Name; - public string name => m_Name; - - private string m_Id; - public string id => m_Id; - - private AdvancedDropdownItem m_Parent; - public virtual AdvancedDropdownItem parent => m_Parent; - - private List m_Children = new List(); - public virtual List children => m_Children; - - public bool hasChildren => children.Any(); - public virtual bool drawArrow => hasChildren; - - public virtual bool searchable { get; set; } - - internal int m_Index = -1; - internal Vector2 m_Scroll; - internal int m_SelectedItem = 0; - - public int selectedItem - { - get { return m_SelectedItem; } - set - { - if (value < 0) - { - m_SelectedItem = 0; - } - else if (value >= children.Count) - { - m_SelectedItem = children.Count - 1; - } - else - { - m_SelectedItem = value; - } - } - } - - public AdvancedDropdownItem(string name, int index) : this(name, name, index) - { - } - - public AdvancedDropdownItem(string name, string id, int index) - { - m_Content = new GUIContent(name); - m_ContentWhenSearching = new GUIContent(id); - m_Name = name; - m_Id = id; - m_Index = index; - } - - public AdvancedDropdownItem(GUIContent content, int index) : this(content, content, index) - { - } - - public AdvancedDropdownItem(GUIContent content, GUIContent contentWhenSearching, int index) - { - m_Content = content; - m_ContentWhenSearching = contentWhenSearching; - m_Name = content.text; - m_Id = contentWhenSearching.text; - m_Index = index; - } - - internal void AddChild(AdvancedDropdownItem item) - { - children.Add(item); - } - - internal void SetParent(AdvancedDropdownItem item) - { - m_Parent = item; - } - - internal void AddSeparator() - { - children.Add(s_SeparatorItem); - } - - internal virtual bool IsSeparator() - { - return false; - } - - public virtual bool OnAction() - { - return true; - } - - public AdvancedDropdownItem GetSelectedChild() - { - if (children.Count == 0 || m_SelectedItem < 0) - return null; - return children[m_SelectedItem]; - } - - public int GetSelectedChildIndex() - { - var i = children[m_SelectedItem].m_Index; - if (i >= 0) - { - return i; - } - return m_SelectedItem; - } - - public IEnumerable GetSearchableElements() - { - if (searchable) - yield return this; - foreach (var child in children) - { - foreach (var searchableChildren in child.GetSearchableElements()) - { - yield return searchableChildren; - } - } - } - - public virtual int CompareTo(object o) - { - return name.CompareTo((o as AdvancedDropdownItem).name); - } - - public void MoveDownSelection() - { - var selectedIndex = selectedItem; - do - { - ++selectedIndex; - } - while (selectedIndex < children.Count && children[selectedIndex].IsSeparator()); - - if (selectedIndex < children.Count) - selectedItem = selectedIndex; - } - - public void MoveUpSelection() - { - var selectedIndex = selectedItem; - do - { - --selectedIndex; - } - while (selectedIndex >= 0 && children[selectedIndex].IsSeparator()); - if (selectedIndex >= 0) - selectedItem = selectedIndex; - } - - class SeparatorDropdownItem : AdvancedDropdownItem - { - public SeparatorDropdownItem() : base("SEPARATOR", -1) - { - } - - internal override bool IsSeparator() - { - return true; - } - } - } -} diff --git a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownSimpleDataSource.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownSimpleDataSource.cs deleted file mode 100644 index bd68193e3b..0000000000 --- a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownSimpleDataSource.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; - -namespace UnityEditor -{ - internal class AdvancedDropdownSimpleDataSource : AdvancedDropdownDataSource - { - private string[] m_DisplayedOptions; - public string[] DisplayedOptions {set { m_DisplayedOptions = value; }} - - private string m_Label; - public string Label { set { m_Label = value; } } - - private static int m_SelectedIndex; - public int SelectedIndex { set { m_SelectedIndex = value; } } - - protected override AdvancedDropdownItem FetchData() - { - var rootGroup = new AdvancedDropdownItem(m_Label, -1); - - for (int i = 0; i < m_DisplayedOptions.Length; i++) - { - var menuPath = m_DisplayedOptions[i]; - var paths = menuPath.Split('/'); - - AdvancedDropdownItem parent = rootGroup; - for (var j = 0; j < paths.Length; j++) - { - var path = paths[j]; - if (j == paths.Length - 1) - { - var element = new AdvancedDropdownItem(path, menuPath, i); - element.searchable = true; - element.SetParent(parent); - parent.AddChild(element); - - if (i == m_SelectedIndex) - { - var tempParent = parent; - AdvancedDropdownItem searchedItem = element; - while (tempParent != null) - { - tempParent.selectedItem = tempParent.children.IndexOf(searchedItem); - searchedItem = tempParent; - tempParent = tempParent.parent; - } - } - continue; - } - - var groupPathId = ""; - for (int k = 0; k <= j; k++) - groupPathId += paths[k] + "."; - - var group = parent.children.SingleOrDefault(c => c.id == groupPathId); - if (group == null) - { - group = new AdvancedDropdownItem(path, groupPathId, -1); - group.SetParent(parent); - parent.AddChild(group); - } - parent = group; - } - } - return rootGroup; - } - } -} diff --git a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownWindow.cs b/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownWindow.cs deleted file mode 100644 index 17a10b7db7..0000000000 --- a/Editor/Mono/Inspector/AdvancedDropdown/AdvancedDropdownWindow.cs +++ /dev/null @@ -1,371 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEditor.Callbacks; -using UnityEngine; -using Event = UnityEngine.Event; - -namespace UnityEditor -{ - [InitializeOnLoad] - internal class AdvancedDropdownWindow : EditorWindow - { - private static class Styles - { - public static GUIStyle background = "grey_border"; - public static GUIStyle previewHeader = new GUIStyle(EditorStyles.label); - public static GUIStyle previewText = new GUIStyle(EditorStyles.wordWrappedLabel); - - static Styles() - { - previewText.padding.left += 3; - previewText.padding.right += 3; - previewHeader.padding.left += 3 - 2; - previewHeader.padding.right += 3; - previewHeader.padding.top += 3; - previewHeader.padding.bottom += 2; - } - } - - protected AdvancedDropdownGUI gui = new AdvancedDropdownGUI(); - public AdvancedDropdownDataSource dataSource = new AdvancedDropdownSimpleDataSource(); - - protected AdvancedDropdownItem m_CurrentlyRenderedTree; - - private AdvancedDropdownItem m_AnimationTree; - private float m_NewAnimTarget = 0; - private long m_LastTime = 0; - private bool m_ScrollToSelected = true; - - [NonSerialized] - private bool m_DirtyList = true; - - protected string m_Search = ""; - private bool hasSearch { get { return !string.IsNullOrEmpty(m_Search); } } - - public event Action onSelected; - public bool showHeader { get; set; } = true; - - protected virtual bool isSearchFieldDisabled { get; } - - protected virtual void OnEnable() - { - m_DirtyList = true; - } - - protected virtual void OnDisable() - { - } - - public static T CreateAndInit(Rect rect) where T : AdvancedDropdownWindow - { - var instance = CreateInstance(); - instance.Init(rect); - return instance; - } - - public void Init(Rect buttonRect) - { - // Has to be done before calling Show / ShowWithMode - buttonRect = GUIUtility.GUIToScreenRect(buttonRect); - - OnDirtyList(); - m_CurrentlyRenderedTree = hasSearch ? dataSource.searchTree : dataSource.mainTree; - - - ShowAsDropDown(buttonRect, new Vector2(buttonRect.width, gui.WindowHeight), null, ShowMode.PopupMenuWithKeyboardFocus); - - Focus(); - - // Add after unfreezing display because AuxWindowManager.cpp assumes that aux windows are added after we got/lost- focus calls. - m_Parent.AddToAuxWindowList(); - - wantsMouseMove = true; - } - - internal void OnGUI() - { - GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, Styles.background); - - if (m_DirtyList) - { - OnDirtyList(); - } - - HandleKeyboard(); - OnGUISearch(); - - if (m_NewAnimTarget != 0 && Event.current.type == EventType.Layout) - { - long now = DateTime.Now.Ticks; - float deltaTime = (now - m_LastTime) / (float)TimeSpan.TicksPerSecond; - m_LastTime = now; - - m_NewAnimTarget = Mathf.MoveTowards(m_NewAnimTarget, 0, deltaTime * 4); - - if (m_NewAnimTarget == 0) - { - m_AnimationTree = null; - } - Repaint(); - } - - var anim = m_NewAnimTarget; - // Smooth the animation - anim = Mathf.Floor(anim) + Mathf.SmoothStep(0, 1, Mathf.Repeat(anim, 1)); - - if (anim == 0) - { - DrawDropdown(0, m_CurrentlyRenderedTree); - } - else if (anim < 0) - { - // Go to parent - // m_NewAnimTarget goes -1 -> 0 - DrawDropdown(anim, m_CurrentlyRenderedTree); - DrawDropdown(anim + 1, m_AnimationTree); - } - else // > 0 - { - // Go to child - // m_NewAnimTarget 1 -> 0 - DrawDropdown(anim - 1 , m_AnimationTree); - DrawDropdown(anim, m_CurrentlyRenderedTree); - } - } - - private void OnDirtyList() - { - m_DirtyList = false; - dataSource.ReloadData(); - if (hasSearch) - dataSource.RebuildSearch(m_Search); - } - - private void OnGUISearch() - { - gui.DrawSearchField(isSearchFieldDisabled, m_Search, (newSearch) => - { - dataSource.RebuildSearch(newSearch); - m_CurrentlyRenderedTree = - string.IsNullOrEmpty(newSearch) ? dataSource.mainTree : dataSource.searchTree; - m_Search = newSearch; - }); - } - - private void HandleKeyboard() - { - var evt = Event.current; - if (evt.type == EventType.KeyDown) - { - // Special handling when in new script panel - if (SpecialKeyboardHandling(evt)) - { - return; - } - - // Always do these - if (evt.keyCode == KeyCode.DownArrow) - { - m_CurrentlyRenderedTree.MoveDownSelection(); - m_ScrollToSelected = true; - evt.Use(); - } - if (evt.keyCode == KeyCode.UpArrow) - { - m_CurrentlyRenderedTree.MoveUpSelection(); - m_ScrollToSelected = true; - evt.Use(); - } - if (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter) - { - if (m_CurrentlyRenderedTree.GetSelectedChild().children.Any()) - { - GoToChild(m_CurrentlyRenderedTree); - } - else - { - if (m_CurrentlyRenderedTree.GetSelectedChild().OnAction()) - { - CloseWindow(); - } - } - evt.Use(); - } - - // Do these if we're not in search mode - if (!hasSearch) - { - if (evt.keyCode == KeyCode.LeftArrow || evt.keyCode == KeyCode.Backspace) - { - GoToParent(); - evt.Use(); - } - if (evt.keyCode == KeyCode.RightArrow) - { - if (m_CurrentlyRenderedTree.GetSelectedChild().children.Any()) - GoToChild(m_CurrentlyRenderedTree); - evt.Use(); - } - if (evt.keyCode == KeyCode.Escape) - { - Close(); - evt.Use(); - } - } - } - } - - private void CloseWindow() - { - if (onSelected != null) - onSelected(this); - Close(); - } - - internal string GetIdOfSelectedItem() - { - return m_CurrentlyRenderedTree.GetSelectedChild().id; - } - - protected virtual bool SpecialKeyboardHandling(Event evt) - { - return false; - } - - private void DrawDropdown(float anim, AdvancedDropdownItem group) - { - // Start of animated area (the part that moves left and right) - var areaPosition = position; - // Adjust to the frame - areaPosition.height -= 1; - GUILayout.BeginArea(gui.GetAnimRect(areaPosition, anim)); - // Header - if (showHeader) - gui.DrawHeader(group, GoToParent); - - DrawList(group); - GUILayout.EndArea(); - } - - private void DrawList(AdvancedDropdownItem item) - { - // Start of scroll view list - item.m_Scroll = GUILayout.BeginScrollView(item.m_Scroll); - EditorGUIUtility.SetIconSize(gui.iconSize); - Rect selectedRect = new Rect(); - for (var i = 0; i < item.children.Count; i++) - { - var child = item.children[i]; - bool selected = i == item.m_SelectedItem; - gui.DrawItem(child, selected, hasSearch); - var r = GUILayoutUtility.GetLastRect(); - if (selected) - selectedRect = r; - - // Select the element the mouse cursor is over. - // Only do it on mouse move - keyboard controls are allowed to overwrite this until the next time the mouse moves. - if (Event.current.type == EventType.MouseMove || Event.current.type == EventType.MouseDown) - { - //if (parent.selectedIndex != i && r.Contains(Event.current.mousePosition)) - if (!selected && r.Contains(Event.current.mousePosition)) - { - item.m_SelectedItem = i; - Event.current.Use(); - } - } - if (Event.current.type == EventType.MouseDown && r.Contains(Event.current.mousePosition)) - { - item.m_SelectedItem = i; - if (m_CurrentlyRenderedTree.GetSelectedChild().children.Any()) - { - GoToChild(m_CurrentlyRenderedTree); - } - else - { - if (m_CurrentlyRenderedTree.GetSelectedChild().OnAction()) - { - CloseWindow(); - GUIUtility.ExitGUI(); - } - } - Event.current.Use(); - } - } - EditorGUIUtility.SetIconSize(Vector2.zero); - - GUILayout.EndScrollView(); - - // Scroll to show selected - if (m_ScrollToSelected && Event.current.type == EventType.Repaint) - { - m_ScrollToSelected = false; - Rect scrollRect = GUILayoutUtility.GetLastRect(); - if (selectedRect.yMax - scrollRect.height > item.m_Scroll.y) - { - item.m_Scroll.y = selectedRect.yMax - scrollRect.height; - Repaint(); - } - if (selectedRect.y < item.m_Scroll.y) - { - item.m_Scroll.y = selectedRect.y; - Repaint(); - } - } - } - - protected void GoToParent() - { - if (m_CurrentlyRenderedTree.parent == null) - return; - m_LastTime = System.DateTime.Now.Ticks; - if (m_NewAnimTarget > 0) - m_NewAnimTarget = -1 + m_NewAnimTarget; - else - m_NewAnimTarget = -1; - m_AnimationTree = m_CurrentlyRenderedTree; - m_CurrentlyRenderedTree = m_CurrentlyRenderedTree.parent; - } - - private void GoToChild(AdvancedDropdownItem parent) - { - m_LastTime = System.DateTime.Now.Ticks; - if (m_NewAnimTarget < 0) - m_NewAnimTarget = 1 + m_NewAnimTarget; - else - m_NewAnimTarget = 1; - m_CurrentlyRenderedTree = parent.GetSelectedChild(); - m_AnimationTree = parent; - } - - public int GetSelectedIndex() - { - return m_CurrentlyRenderedTree.GetSelectedChildIndex(); - } - - [DidReloadScripts] - private static void OnScriptReload() - { - CloseAllOpenWindows(); - } - - protected static void CloseAllOpenWindows() - { - var windows = Resources.FindObjectsOfTypeAll(typeof(T)); - foreach (var window in windows) - { - try - { - ((EditorWindow)window).Close(); - } - catch - { - DestroyImmediate(window); - } - } - } - } -} diff --git a/Editor/Mono/Inspector/AdvancedDropdown/StatefulAdvancedDropdown.cs b/Editor/Mono/Inspector/AdvancedDropdown/StatefulAdvancedDropdown.cs deleted file mode 100644 index 0d91e2b983..0000000000 --- a/Editor/Mono/Inspector/AdvancedDropdown/StatefulAdvancedDropdown.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal class StatefulAdvancedDropdown - { - [NonSerialized] - private AdvancedDropdownWindow s_Instance; - - public Action onSelected { get; set; } - public string Label { get; set; } - public int SelectedIndex { get; set; } - public string[] DisplayedOptions { get; set; } - - public void Show(Rect rect) - { - if (s_Instance != null) - { - s_Instance.Close(); - s_Instance = null; - } - - s_Instance = ScriptableObject.CreateInstance(); - - var dataSource = new AdvancedDropdownSimpleDataSource(); - dataSource.DisplayedOptions = DisplayedOptions; - dataSource.SelectedIndex = SelectedIndex; - dataSource.Label = Label; - - s_Instance.dataSource = dataSource; - - s_Instance.onSelected += w => onSelected(w.GetIdOfSelectedItem()); - - s_Instance.Init(rect); - } - } -} diff --git a/Editor/Mono/Inspector/AdvancedDropdown/StatelessAdvancedDropdown.cs b/Editor/Mono/Inspector/AdvancedDropdown/StatelessAdvancedDropdown.cs deleted file mode 100644 index c2de7b650c..0000000000 --- a/Editor/Mono/Inspector/AdvancedDropdown/StatelessAdvancedDropdown.cs +++ /dev/null @@ -1,96 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal static class StatelessAdvancedDropdown - { - private static AdvancedDropdownWindow s_Instance; - private static EditorWindow s_ParentWindow; - private static bool m_WindowClosed; - private static int m_Result; - private static int s_CurrentControl; - - internal static void SearchablePopup(Rect rect, string label, int selectedIndex, string[] displayedOptions, - Action onSelected) - { - ResetAndCreateWindow(); - InitWindow(rect, label, selectedIndex, displayedOptions); - - s_Instance.onSelected += (w) => onSelected(w.GetIdOfSelectedItem()); - } - - public static int SearchablePopup(Rect rect, int selectedIndex, string[] displayedOptions) - { - return SearchablePopup(rect, selectedIndex, displayedOptions, "MiniPullDown"); - } - - public static int SearchablePopup(Rect rect, int selectedIndex, string[] displayedOptions, GUIStyle style) - { - string contentLabel = null; - if (selectedIndex >= 0) - { - contentLabel = displayedOptions[selectedIndex]; - } - - var content = new GUIContent(contentLabel); - - int id = EditorGUIUtility.GetControlID("AdvancedDropdown".GetHashCode(), FocusType.Keyboard, rect); - if (EditorGUI.DropdownButton(id, rect, content, "MiniPullDown")) - { - s_CurrentControl = id; - ResetAndCreateWindow(); - InitWindow(rect, content.text, selectedIndex, displayedOptions); - - s_Instance.onSelected += w => - { - m_Result = w.GetSelectedIndex(); - m_WindowClosed = true; - }; - } - if (m_WindowClosed && s_CurrentControl == id) - { - s_CurrentControl = 0; - m_WindowClosed = false; - return m_Result; - } - - return selectedIndex; - } - - private static void ResetAndCreateWindow() - { - if (s_Instance != null) - { - s_Instance.Close(); - s_Instance = null; - } - s_ParentWindow = EditorWindow.focusedWindow; - s_Instance = ScriptableObject.CreateInstance(); - m_WindowClosed = false; - } - - private static void InitWindow(Rect rect, string label, int selectedIndex, string[] displayedOptions) - { - var dataSource = new AdvancedDropdownSimpleDataSource(); - - dataSource.DisplayedOptions = displayedOptions; - dataSource.SelectedIndex = selectedIndex; - dataSource.Label = label; - - s_Instance.dataSource = dataSource; - - s_Instance.onSelected += (w) => - { - if (s_ParentWindow != null) - s_ParentWindow.Repaint(); - }; - - s_Instance.Init(rect); - } - } -} diff --git a/Editor/Mono/Inspector/AimConstraintEditor.cs b/Editor/Mono/Inspector/AimConstraintEditor.cs deleted file mode 100644 index 6f1ca2cdfe..0000000000 --- a/Editor/Mono/Inspector/AimConstraintEditor.cs +++ /dev/null @@ -1,142 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Animations; - -namespace UnityEditor -{ - [CustomEditor(typeof(AimConstraint))] - [CanEditMultipleObjects] - internal class AimConstraintEditor : ConstraintEditorBase - { - private SerializedProperty m_RotationAtRest; - private SerializedProperty m_RotationOffset; - private SerializedProperty m_AimVector; - private SerializedProperty m_UpVector; - private SerializedProperty m_WorldUpVector; - private SerializedProperty m_WorldUpObject; - private SerializedProperty m_WorldUpType; - private SerializedProperty m_Weight; - private SerializedProperty m_IsContraintActive; - private SerializedProperty m_IsLocked; - private SerializedProperty m_Sources; - - internal override SerializedProperty atRest { get { return m_RotationAtRest; } } - internal override SerializedProperty offset { get { return m_RotationOffset; } } - internal override SerializedProperty weight { get { return m_Weight; } } - internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } } - internal override SerializedProperty isLocked { get { return m_IsLocked; } } - internal override SerializedProperty sources { get { return m_Sources; } } - - private class Styles : ConstraintStyleBase - { - 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."); - GUIContent m_RotationOffset = EditorGUIUtility.TrTextContent("Rotation Offset", "The offset from the constrained orientation."); - - GUIContent m_RotationAxes = EditorGUIUtility.TrTextContent("Freeze Rotation Axes", "The axes along which the constraint is applied."); - - GUIContent m_AimVector = EditorGUIUtility.TrTextContent("Aim Vector", "Specifies which axis of the constrained object should aim at the target."); - GUIContent m_UpVector = EditorGUIUtility.TrTextContent("Up Vector", "Specifies the direction of the up vector in local space."); - GUIContent m_WorldUpVector = EditorGUIUtility.TrTextContent("World Up Vector", "Specifies the direction of the global up vector."); - GUIContent m_WorldUpObject = EditorGUIUtility.TrTextContent("World Up Object", "The reference object when the World Up Type is either Object Up or Object Rotation Up."); - GUIContent m_WorldUpType = EditorGUIUtility.TrTextContent("World Up Type", "Specifies how the world up vector should be computed."); - GUIContent[] m_WorldUpTypes = - { - EditorGUIUtility.TrTextContent("Scene Up", "Use the Y axis as the world up vector."), - EditorGUIUtility.TrTextContent("Object Up", "Use a vector that points to the reference object as the world up vector."), - EditorGUIUtility.TrTextContent("Object Rotation Up", "Use a vector defined in the reference object's local space as the world up vector."), - EditorGUIUtility.TrTextContent("Vector", "The world up vector is user defined."), - EditorGUIUtility.TrTextContent("None", "The world up vector is ignored.") - }; - public override GUIContent AtRest { get { return m_RotationAtRest; } } - public override GUIContent Offset { get { return m_RotationOffset; } } - public GUIContent FreezeAxes { get { return m_RotationAxes; } } - public GUIContent AimVector { get { return m_AimVector; } } - public GUIContent UpVector { get { return m_UpVector; } } - public GUIContent WorldUpVector { get { return m_WorldUpVector; } } - public GUIContent WorldUpObject { get { return m_WorldUpObject; } } - public GUIContent WorldUpType { get { return m_WorldUpType; } } - public GUIContent[] WorldUpTypes { get { return m_WorldUpTypes; } } - } - - private static Styles s_Style = null; - - public void OnEnable() - { - if (s_Style == null) - s_Style = new Styles(); - - m_RotationAtRest = serializedObject.FindProperty("m_RotationAtRest"); - m_RotationOffset = serializedObject.FindProperty("m_RotationOffset"); - - m_AimVector = serializedObject.FindProperty("m_AimVector"); - m_UpVector = serializedObject.FindProperty("m_UpVector"); - m_WorldUpVector = serializedObject.FindProperty("m_WorldUpVector"); - m_WorldUpObject = serializedObject.FindProperty("m_WorldUpObject"); - m_WorldUpType = serializedObject.FindProperty("m_UpType"); - - m_Weight = serializedObject.FindProperty("m_Weight"); - m_IsContraintActive = serializedObject.FindProperty("m_IsContraintActive"); - m_IsLocked = serializedObject.FindProperty("m_IsLocked"); - m_Sources = serializedObject.FindProperty("m_Sources"); - - OnEnable(s_Style); - } - - internal override void OnValueAtRestChanged() - { - foreach (var t in targets) - (t as AimConstraint).transform.SetLocalEulerAngles(atRest.vector3Value, RotationOrder.OrderZXY); - } - - internal override void ShowOffset(ConstraintStyleBase style) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(offset, style.Offset); - if (EditorGUI.EndChangeCheck()) - { - foreach (var t in targets) - (t as T).UserUpdateOffset(); - } - } - - internal override void ShowCustomProperties() - { - EditorGUILayout.PropertyField(m_AimVector, s_Style.AimVector); - EditorGUILayout.PropertyField(m_UpVector, s_Style.UpVector); - EditorGUILayout.Popup(m_WorldUpType, s_Style.WorldUpTypes, s_Style.WorldUpType); - - var worldUpType = (AimConstraint.WorldUpType)m_WorldUpType.intValue; - using (new EditorGUI.DisabledGroupScope(worldUpType != AimConstraint.WorldUpType.ObjectRotationUp && worldUpType != AimConstraint.WorldUpType.Vector)) - { - EditorGUILayout.PropertyField(m_WorldUpVector, s_Style.WorldUpVector); - } - - using (new EditorGUI.DisabledGroupScope(worldUpType != AimConstraint.WorldUpType.ObjectUp && worldUpType != AimConstraint.WorldUpType.ObjectRotationUp)) - { - EditorGUILayout.PropertyField(m_WorldUpObject, s_Style.WorldUpObject); - } - } - - internal override void ShowFreezeAxesControl() - { - Rect drawRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeAxes), EditorStyles.toggle); - EditorGUI.MultiPropertyField(drawRect, s_Style.Axes, serializedObject.FindProperty("m_AffectRotationX"), s_Style.FreezeAxes); - } - - public override void OnInspectorGUI() - { - if (s_Style == null) - s_Style = new Styles(); - - serializedObject.Update(); - - ShowConstraintEditor(s_Style); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/AnchoredJoint2DEditor.cs b/Editor/Mono/Inspector/AnchoredJoint2DEditor.cs deleted file mode 100644 index c6cbed3e26..0000000000 --- a/Editor/Mono/Inspector/AnchoredJoint2DEditor.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(AnchoredJoint2D), true)] - [CanEditMultipleObjects] - internal class AnchoredJoint2DEditor : Joint2DEditor - { - const float k_SnapDistance = 0.13f; - AnchoredJoint2D anchorJoint2D; - - public void OnSceneGUI() - { - anchorJoint2D = (AnchoredJoint2D)target; - - // Ignore disabled joint. - if (!anchorJoint2D.enabled) - return; - - Vector3 worldAnchor = TransformPoint(anchorJoint2D.transform, anchorJoint2D.anchor); - Vector3 worldConnectedAnchor = anchorJoint2D.connectedAnchor; - if (anchorJoint2D.connectedBody) - worldConnectedAnchor = TransformPoint(anchorJoint2D.connectedBody.transform, worldConnectedAnchor); - - // Draw line between anchors - Vector3 startPoint = worldAnchor + (worldConnectedAnchor - worldAnchor).normalized * HandleUtility.GetHandleSize(worldAnchor) * 0.1f; - Handles.color = Color.green; - Handles.DrawAAPolyLine(new Vector3[] { startPoint, worldConnectedAnchor }); - - // Connected anchor - if (HandleAnchor(ref worldConnectedAnchor, true)) - { - worldConnectedAnchor = SnapToSprites(worldConnectedAnchor); - worldConnectedAnchor = SnapToPoint(worldConnectedAnchor, worldAnchor, k_SnapDistance); - - if (anchorJoint2D.connectedBody) - worldConnectedAnchor = InverseTransformPoint(anchorJoint2D.connectedBody.transform, worldConnectedAnchor); - - Undo.RecordObject(anchorJoint2D, "Move Connected Anchor"); - anchorJoint2D.connectedAnchor = worldConnectedAnchor; - } - - // Anchor - if (HandleAnchor(ref worldAnchor, false)) - { - worldAnchor = SnapToSprites(worldAnchor); - worldAnchor = SnapToPoint(worldAnchor, worldConnectedAnchor, k_SnapDistance); - - Undo.RecordObject(anchorJoint2D, "Move Anchor"); - anchorJoint2D.anchor = InverseTransformPoint(anchorJoint2D.transform, worldAnchor); - } - } - - Vector3 SnapToSprites(Vector3 position) - { - SpriteRenderer spriteRenderer = anchorJoint2D.GetComponent(); - position = SnapToSprite(spriteRenderer, position, k_SnapDistance); - - if (anchorJoint2D.connectedBody) - { - spriteRenderer = anchorJoint2D.connectedBody.GetComponent(); - position = SnapToSprite(spriteRenderer, position, k_SnapDistance); - } - - return position; - } - } -} diff --git a/Editor/Mono/Inspector/AnimationClipEditor.cs b/Editor/Mono/Inspector/AnimationClipEditor.cs deleted file mode 100644 index 94b689f554..0000000000 --- a/Editor/Mono/Inspector/AnimationClipEditor.cs +++ /dev/null @@ -1,1791 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditor.Animations; -using UnityEditor.AnimatedValues; -using System; -using System.Reflection; -using System.Collections.Generic; -using System.Linq; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [CustomEditor(typeof(AnimationClip))] - internal class AnimationClipEditor : Editor - { - internal static void EditWithImporter(AnimationClip clip) - { - ModelImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(clip)) as ModelImporter; - - if (importer) - { - Selection.activeObject = AssetDatabase.LoadMainAssetAtPath(importer.assetPath); - ModelImporterEditor inspector = Editor.CreateEditor(importer) as ModelImporterEditor; - EditorPrefs.SetInt(inspector.GetType().Name + "ActiveEditorIndex", 2); - - int clipIndex = 0; - var clipAnimations = importer.clipAnimations; - for (int i = 0; i < clipAnimations.Length; i++) - { - if (clipAnimations[i].name == clip.name) - clipIndex = i; - } - - EditorPrefs.SetInt("ModelImporterClipEditor.ActiveClipIndex", clipIndex); - } - } - - private static class Styles - { - public static GUIContent StartFrame = EditorGUIUtility.TrTextContent("Start", "Start frame of the clip."); - public static GUIContent EndFrame = EditorGUIUtility.TrTextContent("End", "End frame of the clip."); - public static string AverageVelocity = L10n.Tr("Average Velocity: {0}\nAverage Angular Y Speed: {1} deg/s"); - - public static GUIContent HasAdditiveReferencePose = EditorGUIUtility.TrTextContent("Additive Reference Pose", "Enable to define the additive reference pose frame."); - public static GUIContent AdditiveReferencePoseFrame = EditorGUIUtility.TrTextContent("Pose Frame", "Pose Frame."); - public static GUIContent LoopTime = EditorGUIUtility.TrTextContent("Loop Time", "Enable to make the animation plays through and then restarts when the end is reached."); - public static GUIContent LoopPose = EditorGUIUtility.TrTextContent("Loop Pose", "Enable to make the animation loop seamlessly."); - 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."); - public static GUIContent RootTransformRotation = EditorGUIUtility.TrTextContent("Root Transform Rotation"); - public static GUIContent RootTransformRotationY = EditorGUIUtility.TrTextContent("Root Transform Position (Y)"); - public static GUIContent RootTransformPositionXZ = EditorGUIUtility.TrTextContent("Root Transform Position (XZ)"); - - 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."); - public static GUIContent OrientationOffsetY = EditorGUIUtility.TrTextContent("Offset", "Offset to the root rotation (in degrees)."); - - public static GUIContent BasedUponOrientation = EditorGUIUtility.TrTextContent("Based Upon", "What the root rotation is based upon."); - public static GUIContent BasedUponStartOrientation = EditorGUIUtility.TrTextContent("Based Upon (at Start)", "What the root rotation is based upon."); - - public static GUIContent[] BasedUponRotationHumanOpt = - { - EditorGUIUtility.TrTextContent("Original", "Keeps the rotation as it is authored in the source file."), - EditorGUIUtility.TrTextContent("Body Orientation", "Keeps the upper body pointing forward.") - }; - - public static GUIContent[] BasedUponRotationOpt = - { - EditorGUIUtility.TrTextContent("Original", "Keeps the rotation as it is authored in the source file."), - EditorGUIUtility.TrTextContent("Root Node Rotation", "Keeps the upper body pointing forward.") - }; - - 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."); - public static GUIContent PositionOffsetY = EditorGUIUtility.TrTextContent("Offset", "Offset to the vertical root position."); - - public static GUIContent BasedUponPositionY = EditorGUIUtility.TrTextContent("Based Upon", "What the vertical root position is based upon."); - public static GUIContent BasedUponStartPositionY = EditorGUIUtility.TrTextContent("Based Upon (at Start)", "What the vertical root position is based upon."); - - - public static GUIContent[] BasedUponPositionYHumanOpt = - { - EditorGUIUtility.TrTextContent("Original", "Keeps the vertical position as it is authored in the source file."), - EditorGUIUtility.TrTextContent("Center of Mass", "Keeps the center of mass aligned with root transform position."), - EditorGUIUtility.TrTextContent("Feet", "Keeps the feet aligned with the root transform position.") - }; - - public static GUIContent[] BasedUponPositionYOpt = - { - EditorGUIUtility.TrTextContent("Original", "Keeps the vertical position as it is authored in the source file."), - EditorGUIUtility.TrTextContent("Root Node Position") - }; - - 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."); - - public static GUIContent BasedUponPositionXZ = EditorGUIUtility.TrTextContent("Based Upon", "What the horizontal root position is based upon."); - public static GUIContent BasedUponStartPositionXZ = EditorGUIUtility.TrTextContent("Based Upon (at Start)", "What the horizontal root position is based upon."); - - public static GUIContent[] BasedUponPositionXZHumanOpt = - { - EditorGUIUtility.TrTextContent("Original", "Keeps the horizontal position as it is authored in the source file."), - EditorGUIUtility.TrTextContent("Center of Mass", "Keeps the center of mass aligned with root transform position.") - }; - - public static GUIContent[] BasedUponPositionXZOpt = - { - EditorGUIUtility.TrTextContent("Original", "Keeps the horizontal position as it is authored in the source file."), - EditorGUIUtility.TrTextContent("Root Node Position") - }; - - public static GUIContent Mirror = EditorGUIUtility.TrTextContent("Mirror", "Mirror left and right in this clip."); - - public static GUIContent Curves = EditorGUIUtility.TrTextContent("Curves", "Parameter-related curves."); - public static GUIContent Length = EditorGUIUtility.TrTextContent("Length"); - public static GUIContent AddLoopFrame = EditorGUIUtility.TrTextContent("Add Loop Frame"); - public static GUIContent WrapMode = EditorGUIUtility.TrTextContent("Wrap Mode"); - public static GUIContent Events = EditorGUIUtility.TrTextContent("Events"); - public static GUIContent LoopMatch = EditorGUIUtility.TrTextContent("loop match"); - - public static GUIContent AddEventContent = EditorGUIUtility.TrIconContent("Animation.AddEvent", "Add Event."); - - public static GUIContent GreenLightIcon = EditorGUIUtility.IconContent("lightMeter/greenLight"); - public static GUIContent LightRimIcon = EditorGUIUtility.IconContent("lightMeter/lightRim"); - public static GUIContent OrangeLightIcon = EditorGUIUtility.IconContent("lightMeter/orangeLight"); - public static GUIContent RedLightIcon = EditorGUIUtility.IconContent("lightMeter/redLight"); - - public static GUIContent PrevKeyContent = EditorGUIUtility.TrIconContent("Animation.PrevKey", "Go to previous key frame."); - public static GUIContent NextKeyContent = EditorGUIUtility.TrIconContent("Animation.NextKey", "Go to next key frame."); - public static GUIContent AddKeyframeContent = EditorGUIUtility.TrIconContent("Animation.AddKeyframe", "Add Keyframe."); - } - - static string s_LoopMeterStr = "LoopMeter"; - static int s_LoopMeterHint = s_LoopMeterStr.GetHashCode(); - - static string s_LoopOrientationMeterStr = "LoopOrientationMeter"; - static int s_LoopOrientationMeterHint = s_LoopOrientationMeterStr.GetHashCode(); - - static string s_LoopPositionYMeterStr = "LoopPostionYMeter"; - static int s_LoopPositionYMeterHint = s_LoopPositionYMeterStr.GetHashCode(); - - static string s_LoopPositionXZMeterStr = "LoopPostionXZMeter"; - static int s_LoopPositionXZMeterHint = s_LoopPositionXZMeterStr.GetHashCode(); - - static public float s_EventTimelineMax = 1.05f; - - // Update the ClipInfo if needed. - // Needed because of the dummy serialized property (m_DefaultClipsSerializedObject) TransferDefaultClipsToCustomClips - private void UpdateEventsPopupClipInfo(AnimationClipInfoProperties info) - { - if (m_EventManipulationHandler != null) - m_EventManipulationHandler.UpdateEvents(info); - } - - private AvatarMask m_Mask = null; - public AvatarMask mask - { - get { return m_Mask; } - set { m_Mask = value; } - } - - private AnimationClipInfoProperties m_ClipInfo = null; - public void ShowRange(AnimationClipInfoProperties info) - { - UpdateEventsPopupClipInfo(info); - m_ClipInfo = info; - info.AssignToPreviewClip(m_Clip); - } - - public string[] takeNames { get; set; } - public int takeIndex { get; set; } - private AnimationClip m_Clip = null; - private AnimatorController m_Controller = null; - private AnimatorStateMachine m_StateMachine; - private AnimatorState m_State; - - private AvatarPreview m_AvatarPreview = null; - - private TimeArea m_TimeArea; - private TimeArea m_EventTimeArea; - - - private bool m_DraggingRange = false; - private bool m_DraggingRangeBegin = false; - private bool m_DraggingRangeEnd = false; - private float m_DraggingStartFrame = 0; - private float m_DraggingStopFrame = 0; - private float m_DraggingAdditivePoseFrame = 0; - - private bool m_LoopTime = false; - private bool m_LoopBlend = false; - private bool m_LoopBlendOrientation = false; - private bool m_LoopBlendPositionY = false; - private bool m_LoopBlendPositionXZ = false; - private float m_StartFrame = 0; - private float m_StopFrame = 1; - private float m_AdditivePoseFrame = 0; - private float m_InitialClipLength = 0; - - static private bool m_ShowCurves = false; - - private EventManipulationHandler m_EventManipulationHandler; - static private bool m_ShowEvents = false; - - bool m_NeedsToGenerateClipInfo = false; - - public bool needsToGenerateClipInfo - { - get { return m_NeedsToGenerateClipInfo; } - set { m_NeedsToGenerateClipInfo = value; } - } - - const int kSamplesPerSecond = 60; - const int kPose = 0; - const int kRotation = 1; - const int kHeight = 2; - const int kPosition = 3; - Vector2[][][] m_QualityCurves = new Vector2[4][][]; - bool m_DirtyQualityCurves = false; - - private void InitController() - { - if (m_Clip.legacy) - return; - - if (m_AvatarPreview != null && m_AvatarPreview.Animator != null) - { - bool wasInitialized = true; - if (m_Controller == null) - { - m_Controller = new AnimatorController(); - m_Controller.pushUndo = false; - m_Controller.hideFlags = HideFlags.HideAndDontSave; - m_Controller.AddLayer("preview"); - - m_StateMachine = m_Controller.layers[0].stateMachine; - m_StateMachine.pushUndo = false; - m_StateMachine.hideFlags = HideFlags.HideAndDontSave; - - if (mask != null) - { - AnimatorControllerLayer[] layers = m_Controller.layers; - layers[0].avatarMask = mask; - m_Controller.layers = layers; - } - wasInitialized = false; - } - - if (m_State == null) - { - m_State = m_StateMachine.AddState("preview"); - m_State.pushUndo = false; - AnimatorControllerLayer[] layers = m_Controller.layers; - m_State.motion = m_Clip; - m_Controller.layers = layers; - - m_State.iKOnFeet = m_AvatarPreview.IKOnFeet; - m_State.hideFlags = HideFlags.HideAndDontSave; - wasInitialized = false; - } - - - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller); - if (AnimatorController.GetEffectiveAnimatorController(m_AvatarPreview.Animator) != m_Controller) - { - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller); - } - if (!wasInitialized) - { - m_AvatarPreview.Animator.Play(0, 0, 0); - m_AvatarPreview.Animator.Update(0); - m_AvatarPreview.ResetPreviewFocus(); - } - } - } - - internal override void OnHeaderIconGUI(Rect iconRect) - { - // It doesn't make sense to try and use the preview - Texture2D icon = null; - bool isLoadingAssetPreview = AssetPreview.IsLoadingAssetPreview(target.GetInstanceID()); - icon = AssetPreview.GetAssetPreview(target); - if (!icon) - { - // We have a static preview it just hasn't been loaded yet. Repaint until we have it loaded. - if (isLoadingAssetPreview) - Repaint(); - icon = AssetPreview.GetMiniThumbnail(target); - } - GUI.DrawTexture(iconRect, icon); - } - - internal override void OnHeaderTitleGUI(Rect titleRect, string header) - { - if (m_ClipInfo != null) - m_ClipInfo.name = EditorGUI.DelayedTextField(titleRect, m_ClipInfo.name, EditorStyles.textField); - else - base.OnHeaderTitleGUI(titleRect, header); - } - - internal override void OnHeaderControlsGUI() - { - if (m_ClipInfo != null && takeNames != null && takeNames.Length > 1) - { - EditorGUIUtility.labelWidth = 80; - takeIndex = EditorGUILayout.Popup("Source Take", takeIndex, takeNames); - } - else - { - base.OnHeaderControlsGUI(); - - ModelImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(target)) as ModelImporter; - if (importer != null && m_ClipInfo == null) - { - if (GUILayout.Button("Edit...", EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - { - EditWithImporter(target as AnimationClip); - } - } - } - } - - private void DestroyController() - { - if (m_AvatarPreview != null && m_AvatarPreview.Animator != null) - { - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, null); - } - - Object.DestroyImmediate(m_Controller); - Object.DestroyImmediate(m_State); - m_Controller = null; - m_StateMachine = null; - m_State = null; - } - - private void SetPreviewAvatar() - { - DestroyController(); - InitController(); - } - - void Init() - { - if (m_AvatarPreview == null) - { - m_AvatarPreview = new AvatarPreview(null, target as Motion); - m_AvatarPreview.OnAvatarChangeFunc = SetPreviewAvatar; - m_AvatarPreview.fps = Mathf.RoundToInt((target as AnimationClip).frameRate); - m_AvatarPreview.ShowIKOnFeetButton = (target as Motion).isHumanMotion; - m_AvatarPreview.ResetPreviewFocus(); - } - - // force an update on timeControl if AvatarPreviewer is closed when creating/editing animation curves - // prevent from having a nomralizedTime == -inf - if (m_AvatarPreview.timeControl.currentTime == Mathf.NegativeInfinity) - m_AvatarPreview.timeControl.Update(); - } - - internal void OnEnable() - { - m_Clip = target as AnimationClip; - - //case 790259: The length of the clip will be changed by this inspector, so we can't use it for sampling - m_InitialClipLength = m_Clip.stopTime - m_Clip.startTime; - - if (m_TimeArea == null) - { - m_TimeArea = new TimeArea(true); - m_TimeArea.hRangeLocked = false; - m_TimeArea.vRangeLocked = true; - m_TimeArea.hSlider = true; - m_TimeArea.vSlider = false; - m_TimeArea.hRangeMin = m_Clip.startTime; - m_TimeArea.hRangeMax = m_Clip.stopTime; - m_TimeArea.margin = 10; - m_TimeArea.scaleWithWindow = true; - m_TimeArea.SetShownHRangeInsideMargins(m_Clip.startTime, m_Clip.stopTime); - m_TimeArea.hTicks.SetTickModulosForFrameRate(m_Clip.frameRate); - m_TimeArea.ignoreScrollWheelUntilClicked = true; - } - - if (m_EventTimeArea == null) - { - m_EventTimeArea = new TimeArea(true); - m_EventTimeArea.hRangeLocked = true; - m_EventTimeArea.vRangeLocked = true; - m_EventTimeArea.hSlider = false; - m_EventTimeArea.vSlider = false; - m_EventTimeArea.hRangeMin = 0; - m_EventTimeArea.hRangeMax = s_EventTimelineMax; - m_EventTimeArea.margin = 10; - m_EventTimeArea.scaleWithWindow = true; - m_EventTimeArea.SetShownHRangeInsideMargins(0, s_EventTimelineMax); - m_EventTimeArea.hTicks.SetTickModulosForFrameRate(60); - m_EventTimeArea.ignoreScrollWheelUntilClicked = true; - } - - if (m_EventManipulationHandler == null) - m_EventManipulationHandler = new EventManipulationHandler(m_EventTimeArea); - } - - void OnDisable() - { - DestroyController(); - if (m_AvatarPreview != null) - m_AvatarPreview.OnDestroy(); - } - - public override bool HasPreviewGUI() - { - if (Event.current.type == EventType.Layout) - { - Init(); - } - return m_AvatarPreview != null; - } - - public override void OnPreviewSettings() - { - m_AvatarPreview.DoPreviewSettings(); - } - - void CalculateQualityCurves() - { - for (int i = 0; i < 4; i++) - m_QualityCurves[i] = new Vector2[2][]; - - for (int q = 0; q < 2; q++) - { - // [case 491172] - // 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 - // so it not possible for the user to see curve outside of this range. - float clipStartTime = Mathf.Clamp(m_ClipInfo.firstFrame / m_Clip.frameRate, m_Clip.startTime, m_Clip.stopTime); - float clipStopTime = Mathf.Clamp(m_ClipInfo.lastFrame / m_Clip.frameRate, m_Clip.startTime, m_Clip.stopTime); - - float fixedTime = (q == 0 ? clipStopTime : clipStartTime); - float startTime = (q == 0 ? 0 : clipStartTime); - float stopTime = (q == 0 ? clipStopTime : m_Clip.stopTime); - // Start sample may be a bit before start time; stop sample may be a bit after stop time - int startSample = Mathf.FloorToInt(startTime * kSamplesPerSecond); - int stopSample = Mathf.CeilToInt(stopTime * kSamplesPerSecond); - - m_QualityCurves[kPose][q] = new Vector2[stopSample - startSample + 1]; - m_QualityCurves[kRotation][q] = new Vector2[stopSample - startSample + 1]; - m_QualityCurves[kHeight][q] = new Vector2[stopSample - startSample + 1]; - m_QualityCurves[kPosition][q] = new Vector2[stopSample - startSample + 1]; - - QualityCurvesTime qualityCurvesTime = new QualityCurvesTime(); - qualityCurvesTime.fixedTime = fixedTime; - qualityCurvesTime.variableEndStart = startTime; - qualityCurvesTime.variableEndEnd = stopTime; - qualityCurvesTime.q = q; - - MuscleClipUtility.CalculateQualityCurves(m_Clip, qualityCurvesTime, - m_QualityCurves[kPose][q], m_QualityCurves[kRotation][q], - m_QualityCurves[kHeight][q], m_QualityCurves[kPosition][q]); - } - m_DirtyQualityCurves = false; - } - - public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - bool isRepaint = (Event.current.type == EventType.Repaint); - - InitController(); - - if (isRepaint) - m_AvatarPreview.timeControl.Update(); - - // Set to full take range - AnimationClip clip = target as AnimationClip; - AnimationClipSettings previewInfo = AnimationUtility.GetAnimationClipSettings(clip); - - // Set settings - m_AvatarPreview.timeControl.loop = true; // always looping, waiting for UI ctrl... - - // Sample Animation - if (isRepaint && m_AvatarPreview.PreviewObject != null) - { - if (clip.legacy == false && m_AvatarPreview.Animator != null) - { - if (m_State != null) - m_State.iKOnFeet = m_AvatarPreview.IKOnFeet; - - float normalizedTime = previewInfo.stopTime - previewInfo.startTime != 0 ? (m_AvatarPreview.timeControl.currentTime - previewInfo.startTime) / (previewInfo.stopTime - previewInfo.startTime) : 0.0f; - m_AvatarPreview.Animator.Play(0, 0, normalizedTime); - m_AvatarPreview.Animator.Update(m_AvatarPreview.timeControl.deltaTime); - } - else - { - clip.SampleAnimation(m_AvatarPreview.PreviewObject, m_AvatarPreview.timeControl.currentTime); - } - } - - m_AvatarPreview.DoAvatarPreview(r, background); - } - - public void ClipRangeGUI(ref float startFrame, ref float stopFrame, out bool changedStart, out bool changedStop, bool showAdditivePoseFrame, ref float additivePoseframe, out bool changedAdditivePoseframe) - { - changedStart = false; - changedStop = false; - changedAdditivePoseframe = false; - - m_DraggingRangeBegin = false; - m_DraggingRangeEnd = false; - - bool invalidRange = ( - startFrame + 0.01f < m_Clip.startTime * m_Clip.frameRate || - startFrame - 0.01f > m_Clip.stopTime * m_Clip.frameRate || - stopFrame + 0.01f < m_Clip.startTime * m_Clip.frameRate || - stopFrame - 0.01f > m_Clip.stopTime * m_Clip.frameRate); - bool fixRange = false; - if (invalidRange) - { - GUILayout.BeginHorizontal(EditorStyles.helpBox); - GUILayout.Label("The clip range is outside of the range of the source take.", EditorStyles.wordWrappedMiniLabel); - GUILayout.FlexibleSpace(); - GUILayout.BeginVertical(); - GUILayout.Space(5); - if (GUILayout.Button("Clamp Range")) - fixRange = true; - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - } - - // Time line - Rect timeRect = GUILayoutUtility.GetRect(10, 18 + 15); - GUI.Label(timeRect, "", "TE Toolbar"); - if (Event.current.type == EventType.Repaint) - m_TimeArea.rect = timeRect; - m_TimeArea.BeginViewGUI(); - m_TimeArea.EndViewGUI(); - timeRect.height -= 15; - - // Start and stop markers - int startHandleId = GUIUtility.GetControlID(3126789, FocusType.Passive); - int stopHandleId = GUIUtility.GetControlID(3126789, FocusType.Passive); - int additiveHandleId = GUIUtility.GetControlID(3126789, FocusType.Passive); - GUI.BeginGroup(new Rect(timeRect.x + 1, timeRect.y + 1, timeRect.width - 2, timeRect.height - 2)); - { - timeRect.x = timeRect.y = -1; - - // Draw selected range as blue tint - float startPixel = m_TimeArea.FrameToPixel(startFrame, m_Clip.frameRate, timeRect); - float stopPixel = m_TimeArea.FrameToPixel(stopFrame, m_Clip.frameRate, timeRect); - GUI.Label(new Rect(startPixel, timeRect.y, stopPixel - startPixel, timeRect.height), "", EditorStyles.selectionRect); - - // Draw time ruler - m_TimeArea.TimeRuler(timeRect, m_Clip.frameRate); - // Current time indicator - TimeArea.DrawPlayhead(m_TimeArea.TimeToPixel(m_AvatarPreview.timeControl.currentTime, timeRect), timeRect.yMin, timeRect.yMax, 2f, 1f); - - using (new EditorGUI.DisabledScope(invalidRange)) - { - // Range handles - float startTime = startFrame / m_Clip.frameRate; - TimeArea.TimeRulerDragMode inPoint = m_TimeArea.BrowseRuler(timeRect, startHandleId, ref startTime, 0, false, "TL InPoint"); - if (inPoint == TimeArea.TimeRulerDragMode.Cancel) - { - startFrame = m_DraggingStartFrame; - } - else if (inPoint != TimeArea.TimeRulerDragMode.None) - { - startFrame = startTime * m_Clip.frameRate; - // Snapping bias. Snap to whole frames when zoomed out. - startFrame = MathUtils.RoundBasedOnMinimumDifference(startFrame, m_TimeArea.PixelDeltaToTime(timeRect) * m_Clip.frameRate * 10); - changedStart = true; - } - float stopTime = stopFrame / m_Clip.frameRate; - - TimeArea.TimeRulerDragMode outPoint = m_TimeArea.BrowseRuler(timeRect, stopHandleId, ref stopTime, 0, false, "TL OutPoint"); - if (outPoint == TimeArea.TimeRulerDragMode.Cancel) - { - stopFrame = m_DraggingStopFrame; - } - else if (outPoint != TimeArea.TimeRulerDragMode.None) - { - stopFrame = stopTime * m_Clip.frameRate; - // Snapping bias. Snap to whole frames when zoomed out. - stopFrame = MathUtils.RoundBasedOnMinimumDifference(stopFrame, m_TimeArea.PixelDeltaToTime(timeRect) * m_Clip.frameRate * 10); - changedStop = true; - } - - // Additive pose frame Handle - if (showAdditivePoseFrame) - { - float additivePoseTime = additivePoseframe / m_Clip.frameRate; - TimeArea.TimeRulerDragMode additivePoint = m_TimeArea.BrowseRuler(timeRect, additiveHandleId, ref additivePoseTime, 0, false, "TL playhead"); - if (additivePoint == TimeArea.TimeRulerDragMode.Cancel) - { - additivePoseframe = m_DraggingAdditivePoseFrame; - } - else if (additivePoint != TimeArea.TimeRulerDragMode.None) - { - additivePoseframe = additivePoseTime * m_Clip.frameRate; - // Snapping bias. Snap to whole frames when zoomed out. - additivePoseframe = MathUtils.RoundBasedOnMinimumDifference(additivePoseframe, m_TimeArea.PixelDeltaToTime(timeRect) * m_Clip.frameRate * 10); - changedAdditivePoseframe = true; - } - } - } - - if (EditorGUIUtility.hotControl == startHandleId) - changedStart = true; - if (EditorGUIUtility.hotControl == stopHandleId) - changedStop = true; - if (EditorGUIUtility.hotControl == additiveHandleId) - changedAdditivePoseframe = true; - } - GUI.EndGroup(); - - // Start and stop time float fields - using (new EditorGUI.DisabledScope(invalidRange)) - { - EditorGUILayout.BeginHorizontal(); - { - EditorGUI.BeginChangeCheck(); - startFrame = EditorGUILayout.FloatField(Styles.StartFrame, Mathf.Round(startFrame * 1000) / 1000); - if (EditorGUI.EndChangeCheck()) - changedStart = true; - - GUILayout.FlexibleSpace(); - - EditorGUI.BeginChangeCheck(); - stopFrame = EditorGUILayout.FloatField(Styles.EndFrame, Mathf.Round(stopFrame * 1000) / 1000); - if (EditorGUI.EndChangeCheck()) - changedStop = true; - } - EditorGUILayout.EndHorizontal(); - } - - changedStart |= fixRange; - changedStop |= fixRange; - - // Start and stop time value clamping - if (changedStart) - startFrame = Mathf.Clamp(startFrame, m_Clip.startTime * m_Clip.frameRate, Mathf.Clamp(stopFrame, m_Clip.startTime * m_Clip.frameRate, stopFrame)); - - if (changedStop) - stopFrame = Mathf.Clamp(stopFrame, startFrame, m_Clip.stopTime * m_Clip.frameRate); - - if (changedAdditivePoseframe) - additivePoseframe = Mathf.Clamp(additivePoseframe, m_Clip.startTime * m_Clip.frameRate, m_Clip.stopTime * m_Clip.frameRate); - - // Keep track of whether we're currently dragging the range or not - if (changedStart || changedStop || changedAdditivePoseframe) - { - if (!m_DraggingRange) - m_DraggingRangeBegin = true; - m_DraggingRange = true; - } - else if (m_DraggingRange && EditorGUIUtility.hotControl == 0 && Event.current.type == EventType.Repaint) - { - m_DraggingRangeEnd = true; - m_DraggingRange = false; - m_DirtyQualityCurves = true; - Repaint(); - } - - GUILayout.Space(10); - } - - string GetStatsText() - { - string statsText = ""; - - bool IsHumanClip = targets.Length == 1 ? (target as Motion).isHumanMotion : false; - - // Muscle clip info is currently only available for humanoid - if (IsHumanClip) - { - statsText = string.Format(Styles.AverageVelocity, m_Clip.averageSpeed.ToString("0.000"), (m_Clip.averageAngularSpeed * 180.0f / Mathf.PI).ToString("0.0")); - } - - // Only show stats in final clip not for the preview clip - if (m_ClipInfo == null) - { - AnimationClipStats stats = new AnimationClipStats(); - stats.Reset(); - for (int clipIter = 0; clipIter < targets.Length; clipIter++) - { - AnimationClip clip = targets[clipIter] as AnimationClip; - if (clip != null) - { - AnimationClipStats clipStats = AnimationUtility.GetAnimationClipStats(clip); - stats.Combine(clipStats); - } - } - - if (statsText.Length != 0) - statsText += '\n'; - - float constantRatio = (float)stats.constantCurves / (float)stats.totalCurves * 100.0f; - float denseRatio = (float)stats.denseCurves / (float)stats.totalCurves * 100.0f; - float streamRatio = (float)stats.streamCurves / (float)stats.totalCurves * 100.0f; - - - 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); - statsText += string.Format("Curves Total: {0}, Constant: {1} ({2}%) Dense: {3} ({4}%) Stream: {5} ({6}%)\n", stats.totalCurves, stats.constantCurves, constantRatio.ToString("0.0"), stats.denseCurves, denseRatio.ToString("0.0"), stats.streamCurves, streamRatio.ToString("0.0")); - - statsText += EditorUtility.FormatBytes(stats.size); - } - - return statsText; - } - - private float GetClipLength() - { - if (m_ClipInfo == null) - return m_Clip.length; - else - return (m_ClipInfo.lastFrame - m_ClipInfo.firstFrame) / m_Clip.frameRate; - } - - // A minimal list of settings to be shown in the Asset Store preview inspector - internal override void OnAssetStoreInspectorGUI() - { - OnInspectorGUI(); - } - - public override void OnInspectorGUI() - { - Init(); - EditorGUIUtility.labelWidth = 50; - EditorGUIUtility.fieldWidth = 30; - - EditorGUILayout.BeginHorizontal(); - { - using (new EditorGUI.DisabledScope(true)) - { - GUILayout.Label(Styles.Length, EditorStyles.miniLabel, GUILayout.Width(50 - 4)); - GUILayout.Label(GetClipLength().ToString("0.000"), EditorStyles.miniLabel); - GUILayout.FlexibleSpace(); - GUILayout.Label(m_Clip.frameRate + " FPS", EditorStyles.miniLabel); - } - } - EditorGUILayout.EndHorizontal(); - - if (!m_Clip.legacy) - MuscleClipGUI(); - else - AnimationClipGUI(); - } - - private void AnimationClipGUI() - { - if (m_ClipInfo != null) - { - float startFrame = m_ClipInfo.firstFrame; - float stopFrame = m_ClipInfo.lastFrame; - float additivePoseFrame = 0; - bool changedStart = false; - bool changedStop = false; - bool changedAdditivePoseFrame = false; - ClipRangeGUI(ref startFrame, ref stopFrame, out changedStart, out changedStop, false, ref additivePoseFrame, out changedAdditivePoseFrame); - if (changedStart) - m_ClipInfo.firstFrame = startFrame; - if (changedStop) - m_ClipInfo.lastFrame = stopFrame; - - m_AvatarPreview.timeControl.startTime = startFrame / m_Clip.frameRate; - m_AvatarPreview.timeControl.stopTime = stopFrame / m_Clip.frameRate; - } - else - { - m_AvatarPreview.timeControl.startTime = 0; - m_AvatarPreview.timeControl.stopTime = m_Clip.length; - } - - EditorGUIUtility.labelWidth = 0; - EditorGUIUtility.fieldWidth = 0; - - if (m_ClipInfo != null) - m_ClipInfo.loop = EditorGUILayout.Toggle(Styles.AddLoopFrame, m_ClipInfo.loop); - - EditorGUI.BeginChangeCheck(); - int wrap = m_ClipInfo != null ? m_ClipInfo.wrapMode : (int)m_Clip.wrapMode; - wrap = (int)(WrapModeFixed)EditorGUILayout.EnumPopup(Styles.WrapMode, (WrapModeFixed)wrap); - if (EditorGUI.EndChangeCheck()) - { - if (m_ClipInfo != null) - m_ClipInfo.wrapMode = wrap; - else - m_Clip.wrapMode = (WrapMode)wrap; - } - } - - void CurveGUI() - { - if (m_ClipInfo == null) - return; - - float time = m_AvatarPreview.timeControl.normalizedTime; - - for (int i = 0; i < m_ClipInfo.GetCurveCount(); i++) - { - GUILayout.Space(5); - - GUILayout.BeginHorizontal(); - { - if (GUILayout.Button(GUIContent.none, "OL Minus", GUILayout.Width(17))) m_ClipInfo.RemoveCurve(i); - else - { - GUILayout.BeginVertical(GUILayout.Width(125)); - - string prevName = m_ClipInfo.GetCurveName(i); - string newName = EditorGUILayout.DelayedTextField(prevName, EditorStyles.textField); - - if (prevName != newName) - m_ClipInfo.SetCurveName(i, newName); - - SerializedProperty curveProperty = m_ClipInfo.GetCurveProperty(i); - AnimationCurve curve = curveProperty.animationCurveValue; - - int keyCount = curve.length; - bool isKey = false; - int keyIndex = keyCount - 1; - - for (int keyIter = 0; keyIter < keyCount; keyIter++) - { - if (Mathf.Abs(curve.keys[keyIter].time - time) < 0.0001f) - { - isKey = true; - keyIndex = keyIter; - break; - } - else if (curve.keys[keyIter].time > time) - { - keyIndex = keyIter; - break; - } - } - - GUILayout.BeginHorizontal(); - - if (GUILayout.Button(Styles.PrevKeyContent)) - { - if (keyIndex > 0) - { - keyIndex--; - m_AvatarPreview.timeControl.normalizedTime = curve.keys[keyIndex].time; - } - } - - if (GUILayout.Button(Styles.NextKeyContent)) - { - if (isKey && keyIndex < keyCount - 1) keyIndex++; - m_AvatarPreview.timeControl.normalizedTime = curve.keys[keyIndex].time; - } - - float val, newVal; - using (new EditorGUI.DisabledScope(!isKey)) - { - string orgFormat = EditorGUI.kFloatFieldFormatString; - EditorGUI.kFloatFieldFormatString = "n3"; - val = curve.Evaluate(time); - newVal = EditorGUILayout.FloatField(val, GUILayout.Width(60)); - EditorGUI.kFloatFieldFormatString = orgFormat; - } - - bool addKey = false; - - if (val != newVal) - { - if (isKey) curve.RemoveKey(keyIndex); - - addKey = true; - } - - using (new EditorGUI.DisabledScope(isKey)) - { - if (GUILayout.Button(Styles.AddKeyframeContent)) - { - addKey = true; - } - } - - if (addKey) - { - Keyframe key = new Keyframe(); - key.time = time; - key.value = newVal; - key.inTangent = 0; - key.outTangent = 0; - curve.AddKey(key); - m_ClipInfo.SetCurve(i, curve); - UnityEditorInternal.AnimationCurvePreviewCache.ClearCache(); - } - - GUILayout.EndHorizontal(); - - GUILayout.EndVertical(); - - EditorGUILayout.CurveField(curveProperty, EditorGUI.kCurveColor, new Rect(), GUIContent.none, GUILayout.Height(40)); - - Rect curveRect = GUILayoutUtility.GetLastRect(); - - keyCount = curve.length; - - TimeArea.DrawPlayhead(curveRect.x + time * curveRect.width, curveRect.yMin, curveRect.yMax, 1f, 1f); - - for (int keyIter = 0; keyIter < keyCount; keyIter++) - { - float keyTime = curve.keys[keyIter].time; - - Handles.color = Color.white; - 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)); - } - } - - GUILayout.EndHorizontal(); - } - } - - GUILayout.BeginHorizontal(); - if (GUILayout.Button(GUIContent.none, "OL Plus", GUILayout.Width(17))) m_ClipInfo.AddCurve(); - GUILayout.EndHorizontal(); - } - - private void EventsGUI() - { - if (m_ClipInfo == null) - return; - - GUILayout.BeginHorizontal(); - if (GUILayout.Button(Styles.AddEventContent, GUILayout.Width(25))) - { - m_ClipInfo.AddEvent(Mathf.Clamp01(m_AvatarPreview.timeControl.normalizedTime)); - m_EventManipulationHandler.SelectEvent(m_ClipInfo.GetEvents(), m_ClipInfo.GetEventCount() - 1, m_ClipInfo); - needsToGenerateClipInfo = true; - } - - Rect timeRect = GUILayoutUtility.GetRect(10, 18 + 15); - timeRect.xMin += 5; - timeRect.xMax -= 4; - GUI.Label(timeRect, "", "TE Toolbar"); - - if (Event.current.type == EventType.Repaint) - m_EventTimeArea.rect = timeRect; - timeRect.height -= 15; - m_EventTimeArea.TimeRuler(timeRect, 100.0f); - - - GUI.BeginGroup(new Rect(timeRect.x + 1, timeRect.y + 1, timeRect.width - 2, timeRect.height - 2)); - { - Rect localTimeRect = new Rect(-1, -1, timeRect.width, timeRect.height); - - AnimationEvent[] events = m_ClipInfo.GetEvents(); - - if (m_EventManipulationHandler.HandleEventManipulation(localTimeRect, ref events, m_ClipInfo)) // had changed - { - m_ClipInfo.SetEvents(events); - } - - // Current time indicator - TimeArea.DrawPlayhead(m_EventTimeArea.TimeToPixel(m_AvatarPreview.timeControl.normalizedTime, localTimeRect), localTimeRect.yMin, localTimeRect.yMax, 2f, 1f); - } - - - GUI.EndGroup(); - - GUILayout.EndHorizontal(); - - m_EventManipulationHandler.Draw(timeRect); - } - - private void MuscleClipGUI() - { - EditorGUI.BeginChangeCheck(); - - InitController(); - - AnimationClipSettings animationClipSettings = AnimationUtility.GetAnimationClipSettings(m_Clip); - - m_StartFrame = m_DraggingRange ? m_StartFrame : animationClipSettings.startTime * m_Clip.frameRate; - m_StopFrame = m_DraggingRange ? m_StopFrame : animationClipSettings.stopTime * m_Clip.frameRate; - m_AdditivePoseFrame = m_DraggingRange ? m_AdditivePoseFrame : animationClipSettings.additiveReferencePoseTime * m_Clip.frameRate; - - float startTime = m_StartFrame / m_Clip.frameRate; - float stopTime = m_StopFrame / m_Clip.frameRate; - float additivePoseTime = m_AdditivePoseFrame / m_Clip.frameRate; - - MuscleClipQualityInfo clipQualityInfo = MuscleClipUtility.GetMuscleClipQualityInfo(m_Clip, startTime, - stopTime); - - bool IsHumanClip = (target as Motion).isHumanMotion; - bool hasMotionCurves = AnimationUtility.HasMotionCurves(m_Clip); - bool hasRootCurves = AnimationUtility.HasRootCurves(m_Clip); - bool hasGenericRootTransform = AnimationUtility.HasGenericRootTransform(m_Clip); - bool hasMotionFloatCurves = AnimationUtility.HasMotionFloatCurves(m_Clip); - bool hasAnyRootCurves = hasRootCurves || hasMotionCurves; - - bool changedStart = false; - bool changedStop = false; - bool changedAdditivePoseFrame = false; - - if (m_ClipInfo != null) - { - if (hasAnyRootCurves) - { - if (m_DirtyQualityCurves) - CalculateQualityCurves(); - - // Calculate curves AFTER first repaint to be more responsive. - if (m_QualityCurves[0] == null && Event.current.type == EventType.Repaint) - { - m_DirtyQualityCurves = true; - Repaint(); - } - } - - ClipRangeGUI(ref m_StartFrame, ref m_StopFrame, out changedStart, out changedStop, animationClipSettings.hasAdditiveReferencePose, ref m_AdditivePoseFrame, out changedAdditivePoseFrame); - } - - // Update range info - if (!m_DraggingRange) - { - animationClipSettings.startTime = startTime; - animationClipSettings.stopTime = stopTime; - animationClipSettings.additiveReferencePoseTime = additivePoseTime; - } - - m_AvatarPreview.timeControl.startTime = startTime; - m_AvatarPreview.timeControl.stopTime = stopTime; - - // While dragging, only update the preview - if (changedStart) - m_AvatarPreview.timeControl.nextCurrentTime = startTime; - if (changedStop) - m_AvatarPreview.timeControl.nextCurrentTime = stopTime; - if (changedAdditivePoseFrame) - m_AvatarPreview.timeControl.nextCurrentTime = additivePoseTime; - - EditorGUIUtility.labelWidth = 0; - EditorGUIUtility.fieldWidth = 0; - - - // Loop time - // Toggle - Rect toggleLoopTimeRect = EditorGUILayout.GetControlRect(); - LoopToggle(toggleLoopTimeRect, Styles.LoopTime, ref animationClipSettings.loopTime); - - Rect toggleLoopPoseRect; - using (new EditorGUI.DisabledScope(!animationClipSettings.loopTime)) - { - EditorGUI.indentLevel++; - - // Loop pose - // Toggle - toggleLoopPoseRect = EditorGUILayout.GetControlRect(); - LoopToggle(toggleLoopPoseRect, Styles.LoopPose, ref animationClipSettings.loopBlend); - - // Offset - animationClipSettings.cycleOffset = EditorGUILayout.FloatField(Styles.LoopCycleOffset, animationClipSettings.cycleOffset); - - EditorGUI.indentLevel--; - } - - EditorGUILayout.Space(); - - bool showCurves = IsHumanClip && (changedStart || changedStop); - - if (hasRootCurves && !hasMotionCurves) - { - // Rotation - GUILayout.Label(Styles.RootTransformRotation, EditorStyles.label); - EditorGUI.indentLevel++; - // Toggle - Rect toggleRotRect = EditorGUILayout.GetControlRect(); - LoopToggle(toggleRotRect, Styles.BakeIntoPoseOrientation, ref animationClipSettings.loopBlendOrientation); - // Reference - int offsetRotation = (animationClipSettings.keepOriginalOrientation ? 0 : 1); - - offsetRotation = - EditorGUILayout.Popup( - animationClipSettings.loopBlendOrientation - ? Styles.BasedUponOrientation - : Styles.BasedUponStartOrientation, - offsetRotation, IsHumanClip ? Styles.BasedUponRotationHumanOpt : Styles.BasedUponRotationOpt); - - animationClipSettings.keepOriginalOrientation = (offsetRotation == 0); - // Offset - if (showCurves) - EditorGUILayout.GetControlRect(); - else - animationClipSettings.orientationOffsetY = EditorGUILayout.FloatField(Styles.OrientationOffsetY, - animationClipSettings - .orientationOffsetY); - EditorGUI.indentLevel--; - - EditorGUILayout.Space(); - - // Position Y - GUILayout.Label(Styles.RootTransformRotationY, EditorStyles.label); - EditorGUI.indentLevel++; - // Toggle - Rect toggleYRect = EditorGUILayout.GetControlRect(); - LoopToggle(toggleYRect, Styles.BakeIntoPosePositionY, ref animationClipSettings.loopBlendPositionY); - // Reference - if (IsHumanClip) - { - int offsetHeight; - if (animationClipSettings.keepOriginalPositionY) - offsetHeight = 0; - else if (animationClipSettings.heightFromFeet) - offsetHeight = 2; - else - offsetHeight = 1; - - offsetHeight = - EditorGUILayout.Popup( - animationClipSettings.loopBlendPositionY - ? Styles.BasedUponStartPositionY - : Styles.BasedUponPositionY, - offsetHeight, Styles.BasedUponPositionYHumanOpt); - - if (offsetHeight == 0) - { - animationClipSettings.keepOriginalPositionY = true; - animationClipSettings.heightFromFeet = false; - } - else if (offsetHeight == 1) - { - animationClipSettings.keepOriginalPositionY = false; - animationClipSettings.heightFromFeet = false; - } - else - { - animationClipSettings.keepOriginalPositionY = false; - animationClipSettings.heightFromFeet = true; - } - } - else - { - int offsetHeight = (animationClipSettings.keepOriginalPositionY ? 0 : 1); - offsetHeight = - EditorGUILayout.Popup( - animationClipSettings.loopBlendPositionY - ? Styles.BasedUponStartPositionY - : Styles.BasedUponPositionY, - offsetHeight, Styles.BasedUponPositionYOpt); - animationClipSettings.keepOriginalPositionY = (offsetHeight == 0); - } - // Offset - if (showCurves) - EditorGUILayout.GetControlRect(); - else - animationClipSettings.level = EditorGUILayout.FloatField(Styles.PositionOffsetY, - animationClipSettings.level); - EditorGUI.indentLevel--; - - EditorGUILayout.Space(); - - // Position XZ - GUILayout.Label(Styles.RootTransformPositionXZ, EditorStyles.label); - EditorGUI.indentLevel++; - // Toggle - Rect toggleXZRect = EditorGUILayout.GetControlRect(); - LoopToggle(toggleXZRect, Styles.BakeIntoPosePositionXZ, ref animationClipSettings.loopBlendPositionXZ); - // Reference - int offsetPosition = (animationClipSettings.keepOriginalPositionXZ ? 0 : 1); - offsetPosition = - EditorGUILayout.Popup( - animationClipSettings.loopBlendPositionXZ - ? Styles.BasedUponStartPositionXZ - : Styles.BasedUponPositionXZ, - offsetPosition, IsHumanClip ? Styles.BasedUponPositionXZHumanOpt : Styles.BasedUponPositionXZOpt); - animationClipSettings.keepOriginalPositionXZ = (offsetPosition == 0); - EditorGUI.indentLevel--; - - EditorGUILayout.Space(); - - if (hasAnyRootCurves) - { - // Lamps and toggles drawn later to make them be drawn on top - if (IsHumanClip) - { - LoopQualityLampAndCurve(toggleLoopPoseRect, clipQualityInfo.loop, s_LoopMeterHint, changedStart, - changedStop, - m_QualityCurves[kPose]); - } - - LoopQualityLampAndCurve(toggleRotRect, clipQualityInfo.loopOrientation, s_LoopOrientationMeterHint, - changedStart, - changedStop, m_QualityCurves[kRotation]); - LoopQualityLampAndCurve(toggleYRect, clipQualityInfo.loopPositionY, s_LoopPositionYMeterHint, changedStart, - changedStop, m_QualityCurves[kHeight]); - LoopQualityLampAndCurve(toggleXZRect, clipQualityInfo.loopPositionXZ, s_LoopPositionXZMeterHint, - changedStart, - changedStop, m_QualityCurves[kPosition]); - } - } - - if (IsHumanClip) - { - if (hasMotionCurves) - { - LoopQualityLampAndCurve(toggleLoopPoseRect, clipQualityInfo.loop, s_LoopMeterHint, changedStart, - changedStop, - m_QualityCurves[kPose]); - } - animationClipSettings.mirror = EditorGUILayout.Toggle(Styles.Mirror, animationClipSettings.mirror); - } - - if (m_ClipInfo != null) - { - animationClipSettings.hasAdditiveReferencePose = EditorGUILayout.Toggle(Styles.HasAdditiveReferencePose, animationClipSettings.hasAdditiveReferencePose); - using (new EditorGUI.DisabledScope(!animationClipSettings.hasAdditiveReferencePose)) - { - EditorGUI.indentLevel++; - - m_AdditivePoseFrame = EditorGUILayout.FloatField(Styles.AdditiveReferencePoseFrame, m_AdditivePoseFrame); - m_AdditivePoseFrame = Mathf.Clamp(m_AdditivePoseFrame, m_Clip.startTime * m_Clip.frameRate, m_Clip.stopTime * m_Clip.frameRate); - - animationClipSettings.additiveReferencePoseTime = m_AdditivePoseFrame / m_Clip.frameRate; - EditorGUI.indentLevel--; - } - } - - if (hasGenericRootTransform && hasMotionFloatCurves) - { - EditorGUILayout.HelpBox("Root contains both root motion and transform curves", MessageType.Warning); - } - else if (hasMotionFloatCurves) - { - EditorGUILayout.HelpBox("Root contains root motion curves", MessageType.Info); - } - else if (hasGenericRootTransform) - { - EditorGUILayout.HelpBox("Root contains position and rotation curves", MessageType.Info); - - if (m_ClipInfo == null) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - bool generateCurves = AnimationUtility.GetGenerateMotionCurves(m_Clip); - generateCurves = GUILayout.Toggle(generateCurves, "Generate Root Motion Curves at Runtime"); - AnimationUtility.SetGenerateMotionCurves(m_Clip, generateCurves); - - GUILayout.EndHorizontal(); - - EditorGUILayout.Space(); - } - } - - // Stats - string statsText = GetStatsText(); - if (statsText != "") - GUILayout.Label(statsText, EditorStyles.helpBox); - - EditorGUILayout.Space(); - - bool wasChanged; - - // Additional curves - if (m_ClipInfo != null) - { - // Don't make toggling foldout cause GUI.changed to be true (shouldn't cause undoable action etc.) - wasChanged = GUI.changed; - m_ShowCurves = EditorGUILayout.Foldout(m_ShowCurves, Styles.Curves, true); - GUI.changed = wasChanged; - if (m_ShowCurves) - CurveGUI(); - } - - if (m_ClipInfo != null) - { - wasChanged = GUI.changed; - m_ShowEvents = EditorGUILayout.Foldout(m_ShowEvents, Styles.Events, true); - GUI.changed = wasChanged; - if (m_ShowEvents) - EventsGUI(); - } - - if (m_DraggingRangeBegin) - { - m_LoopTime = animationClipSettings.loopTime; - m_LoopBlend = animationClipSettings.loopBlend; - m_LoopBlendOrientation = animationClipSettings.loopBlendOrientation; - m_LoopBlendPositionY = animationClipSettings.loopBlendPositionY; - m_LoopBlendPositionXZ = animationClipSettings.loopBlendPositionXZ; - - animationClipSettings.loopTime = false; - animationClipSettings.loopBlend = false; - animationClipSettings.loopBlendOrientation = false; - animationClipSettings.loopBlendPositionY = false; - animationClipSettings.loopBlendPositionXZ = false; - - m_DraggingStartFrame = animationClipSettings.startTime * m_Clip.frameRate; - m_DraggingStopFrame = animationClipSettings.stopTime * m_Clip.frameRate; - m_DraggingAdditivePoseFrame = animationClipSettings.additiveReferencePoseTime * m_Clip.frameRate; - - //case 790259: The length of the clip will be changed by this inspector, so we can't use it for sampling - animationClipSettings.startTime = 0; - animationClipSettings.stopTime = m_InitialClipLength; - - AnimationUtility.SetAnimationClipSettingsNoDirty(m_Clip, animationClipSettings); - - DestroyController(); - } - - if (m_DraggingRangeEnd) - { - animationClipSettings.loopTime = m_LoopTime; - animationClipSettings.loopBlend = m_LoopBlend; - animationClipSettings.loopBlendOrientation = m_LoopBlendOrientation; - animationClipSettings.loopBlendPositionY = m_LoopBlendPositionY; - animationClipSettings.loopBlendPositionXZ = m_LoopBlendPositionXZ; - } - - if (EditorGUI.EndChangeCheck() || m_DraggingRangeEnd) - { - if (!m_DraggingRange) - { - Undo.RegisterCompleteObjectUndo(m_Clip, "Muscle Clip Edit"); - AnimationUtility.SetAnimationClipSettingsNoDirty(m_Clip, animationClipSettings); - EditorUtility.SetDirty(m_Clip); - DestroyController(); - } - } - } - - private void LoopToggle(Rect r, GUIContent content, ref bool val) - { - if (!m_DraggingRange) - val = EditorGUI.Toggle(r, content, val); - else - { - EditorGUI.LabelField(r, content, GUIContent.none); - using (new EditorGUI.DisabledScope(true)) - { - EditorGUI.Toggle(r, " ", false); - } - } - } - - private void LoopQualityLampAndCurve(Rect position, float value, int lightMeterHint, bool changedStart, bool changedStop, Vector2[][] curves) - { - if (m_ClipInfo == null) - return; - - GUIStyle style = new GUIStyle(EditorStyles.miniLabel); - style.alignment = TextAnchor.MiddleRight; - - Rect labelPosition = position; - labelPosition.xMax -= 20; - labelPosition.xMin += EditorGUIUtility.labelWidth; - GUI.Label(labelPosition, Styles.LoopMatch, style); - - Event evt = Event.current; - int id = GUIUtility.GetControlID(lightMeterHint, FocusType.Passive, position); - switch (evt.GetTypeForControl(id)) - { - case EventType.Repaint: - { - const int lampSize = 22; - Rect lampPosition = position; - float overflow = (lampSize - lampPosition.height) / 2; - lampPosition.y -= overflow; - lampPosition.xMax += overflow; - lampPosition.height = lampSize; - lampPosition.xMin = lampPosition.xMax - lampSize; - - if (value < .33f) - GUI.DrawTexture(lampPosition, Styles.RedLightIcon.image); - else if (value < .66f) - GUI.DrawTexture(lampPosition, Styles.OrangeLightIcon.image); - else - GUI.DrawTexture(lampPosition, Styles.GreenLightIcon.image); - GUI.DrawTexture(lampPosition, Styles.LightRimIcon.image); - break; - } - } - - if (changedStart || changedStop) - { - Rect r = position; - r.y += r.height + 1; - r.height = 18; - - // Draw border for quality curve - GUI.color = new Color(0, 0, 0, !EditorGUIUtility.isProSkin ? 0.8f : 0.3f); - GUI.DrawTexture(r, EditorGUIUtility.whiteTexture); - - // Subtract 1 pixel so curve is drawn inside border - r = new RectOffset(-1, -1, -1, -1).Add(r); - - // Draw background for quality curve - if (!EditorGUIUtility.isProSkin) - GUI.color = new Color(90f / 255f, 90f / 255f, 90f / 255f, 1); - else - GUI.color = new Color(65f / 255f, 65f / 255f, 65f / 255f, 1); - GUI.DrawTexture(r, EditorGUIUtility.whiteTexture); - - - GUI.color = Color.white; - - GUI.BeginGroup(r); - { - // Calculate matrix to apply to points - Matrix4x4 matrix = m_TimeArea.drawingToViewMatrix; - matrix.m00 = r.width / m_TimeArea.shownArea.width; - matrix.m11 = r.height - 1; - matrix.m03 = -m_TimeArea.shownArea.x * r.width / m_TimeArea.shownArea.width; - matrix.m13 = 0; - - // Apply matrix and assign color for each sample - Vector2[] keys = curves[changedStart ? 0 : 1]; - Vector3[] points = new Vector3[keys.Length]; - Color[] colors = new Color[keys.Length]; - Color curveColorRed = new Color(1.0f, 0.3f, 0.3f); - Color curveColorOrange = new Color(1.0f, 0.8f, 0.0f); - Color curveColorGreen = new Color(0.0f, 1.0f, 0.0f); - for (int i = 0; i < points.Length; i++) - { - points[i] = keys[i]; - points[i] = matrix.MultiplyPoint3x4(points[i]); - if (1 - keys[i].y < .33f) - colors[i] = curveColorRed; - else if (1 - keys[i].y < .66f) - colors[i] = curveColorOrange; - else - colors[i] = curveColorGreen; - } - - // Draw curve based on calculated points and colors - Handles.DrawAAPolyLine(colors, points); - - // Draw start and end markers - GUI.color = new Color(0.3f, 0.6f, 1.0f); - // Draw marker for moving end - float timePixel = matrix.MultiplyPoint3x4(new Vector3((changedStart ? m_StartFrame : m_StopFrame) / m_Clip.frameRate, 0, 0)).x; - GUI.DrawTexture(new Rect(timePixel, 0, 1, r.height), EditorGUIUtility.whiteTexture); - // Draw marker for static end - timePixel = matrix.MultiplyPoint3x4(new Vector3((changedStart ? m_StopFrame : m_StartFrame) / m_Clip.frameRate, 0, 0)).x; - GUI.DrawTexture(new Rect(timePixel, 0, 1, r.height), EditorGUIUtility.whiteTexture); - GUI.color = Color.white; - } - GUI.EndGroup(); - } - } - } - - // TODO merge this with AnimationWindow once its re-done for 2D - internal class EventManipulationHandler - { - private Rect[] m_EventRects = new Rect[0]; - private static AnimationEvent[] m_EventsAtMouseDown; - private static float[] m_EventTimes; - private int m_HoverEvent = -1; - - private string m_InstantTooltipText = null; - private Vector2 m_InstantTooltipPoint = Vector2.zero; - private readonly GUIContent m_DeleteAnimationEventText = EditorGUIUtility.TrTextContent("Delete Animation Event"); - private readonly GUIContent m_DeleteAnimationEventsText = EditorGUIUtility.TrTextContent("Delete Animation Events"); - - private bool[] m_EventsSelected; - private AnimationWindowEvent[] m_Events; - - private TimeArea m_Timeline; - - public EventManipulationHandler(TimeArea timeArea) - { - m_Timeline = timeArea; - } - - public void SelectEvent(AnimationEvent[] events , int index, AnimationClipInfoProperties clipInfo) - { - m_EventsSelected = new bool[events.Length]; - m_EventsSelected[index] = true; - - EditEvents(clipInfo, m_EventsSelected); - } - - public bool HandleEventManipulation(Rect rect, ref AnimationEvent[] events, AnimationClipInfoProperties clipInfo) - { - Texture eventMarker = EditorGUIUtility.IconContent("Animation.EventMarker").image; - - bool hasChanged = false; - - // Calculate rects - Rect[] hitRects = new Rect[events.Length]; - Rect[] drawRects = new Rect[events.Length]; - int shared = 1; - int sharedLeft = 0; - for (int i = 0; i < events.Length; i++) - { - AnimationEvent evt = events[i]; - - if (sharedLeft == 0) - { - shared = 1; - while (i + shared < events.Length && events[i + shared].time == evt.time) - shared++; - sharedLeft = shared; - } - sharedLeft--; - - // Important to take floor of positions of GUI stuff to get pixel correct alignment of - // stuff drawn with both GUI and Handles/GL. Otherwise things are off by one pixel half the time. - float keypos = Mathf.Floor(m_Timeline.TimeToPixel(evt.time, rect)); - int sharedOffset = 0; - if (shared > 1) - { - float spread = Mathf.Min((shared - 1) * (eventMarker.width - 1), (int)(1.0f / m_Timeline.PixelDeltaToTime(rect) - eventMarker.width * 2)); - sharedOffset = Mathf.FloorToInt(Mathf.Max(0, spread - (eventMarker.width - 1) * (sharedLeft))); - } - - Rect r = new Rect( - keypos + sharedOffset - eventMarker.width / 2, - (rect.height - 10) * (float)(sharedLeft - shared + 1) / Mathf.Max(1, shared - 1), - eventMarker.width, - eventMarker.height); - - hitRects[i] = r; - drawRects[i] = r; - } - - // Store rects used for tooltip testing - m_EventRects = new Rect[hitRects.Length]; - for (int i = 0; i < hitRects.Length; i++) - m_EventRects[i] = new Rect(hitRects[i].x + rect.x, hitRects[i].y + rect.y, hitRects[i].width, hitRects[i].height); - - // Selection control - if (m_EventsSelected == null || m_EventsSelected.Length != events.Length || m_EventsSelected.Length == 0) - { - m_EventsSelected = new bool[events.Length]; - m_Events = null; - } - - Vector2 offset = Vector2.zero; - int clickedIndex; - float startSelection, endSelection; - - // TODO: GUIStyle.none has hopping margins that need to be fixed - HighLevelEvent hEvent = EditorGUIExt.MultiSelection( - rect, - drawRects, - new GUIContent(eventMarker), - hitRects, - ref m_EventsSelected, - null, - out clickedIndex, - out offset, - out startSelection, - out endSelection, - GUIStyle.none - ); - - - if (hEvent != HighLevelEvent.None) - { - switch (hEvent) - { - case HighLevelEvent.BeginDrag: - m_EventsAtMouseDown = events; - m_EventTimes = new float[events.Length]; - for (int i = 0; i < events.Length; i++) - m_EventTimes[i] = events[i].time; - break; - case HighLevelEvent.SelectionChanged: - EditEvents(clipInfo, m_EventsSelected); - break; - case HighLevelEvent.Delete: - hasChanged = DeleteEvents(ref events, m_EventsSelected); - break; - case HighLevelEvent.Drag: - for (int i = events.Length - 1; i >= 0; i--) - { - if (m_EventsSelected[i]) - { - AnimationEvent evt = m_EventsAtMouseDown[i]; - evt.time = Mathf.Clamp01(m_EventTimes[i] + (offset.x / rect.width)); - } - } - int[] order = new int[m_EventsSelected.Length]; - for (int i = 0; i < order.Length; i++) - { - order[i] = i; - } - System.Array.Sort(m_EventsAtMouseDown, order, new AnimationEventTimeLine.EventComparer()); - bool[] selectedOld = (bool[])m_EventsSelected.Clone(); - float[] timesOld = (float[])m_EventTimes.Clone(); - for (int i = 0; i < order.Length; i++) - { - m_EventsSelected[i] = selectedOld[order[i]]; - m_EventTimes[i] = timesOld[order[i]]; - } - - events = m_EventsAtMouseDown; - hasChanged = true; - break; - - case HighLevelEvent.ContextClick: - - int selectedEventsCount = m_EventsSelected.Count(selected => selected); - - GenericMenu menu = new GenericMenu(); - menu.AddItem( - EditorGUIUtility.TrTextContent("Add Animation Event"), - false, - EventLineContextMenuAdd, - new EventModificationContextMenuObject(clipInfo, events[clickedIndex].time, clickedIndex, m_EventsSelected)); - menu.AddItem((selectedEventsCount > 1 ? - m_DeleteAnimationEventsText : - m_DeleteAnimationEventText), - false, - EventLineContextMenuDelete, - new EventModificationContextMenuObject(clipInfo, events[clickedIndex].time, clickedIndex, m_EventsSelected)); - menu.ShowAsContext(); - // Mouse may move while context menu is open - make sure instant tooltip is handled - m_InstantTooltipText = null; - break; - } - } - - if (Event.current.type == EventType.ContextClick && rect.Contains(Event.current.mousePosition)) - { - Event.current.Use(); - - int selectedEventsCount = m_EventsSelected.Count(selected => selected); - float mousePosTime = Mathf.Max(m_Timeline.PixelToTime(Event.current.mousePosition.x, rect), 0.0f); - - GenericMenu menu = new GenericMenu(); - menu.AddItem( - EditorGUIUtility.TrTextContent("Add Animation Event"), - false, - EventLineContextMenuAdd, - new EventModificationContextMenuObject(clipInfo, mousePosTime, -1, m_EventsSelected)); - - if (selectedEventsCount > 0) - { - menu.AddItem((selectedEventsCount > 1 ? - m_DeleteAnimationEventsText : - m_DeleteAnimationEventText), - false, - EventLineContextMenuDelete, - new EventModificationContextMenuObject(clipInfo, mousePosTime, -1, m_EventsSelected)); - } - menu.ShowAsContext(); - // Mouse may move while context menu is open - make sure instant tooltip is handled - m_InstantTooltipText = null; - } - - CheckRectsOnMouseMove(rect, events, hitRects); - - return hasChanged; - } - - private class EventModificationContextMenuObject - { - public AnimationClipInfoProperties m_Info; - public float m_Time; - public int m_Index; - public bool[] m_Selected; - - public EventModificationContextMenuObject(AnimationClipInfoProperties info, float time, int index, bool[] selected) - { - m_Info = info; - m_Time = time; - m_Index = index; - m_Selected = selected; - } - }; - - public void EventLineContextMenuAdd(object obj) - { - EventModificationContextMenuObject context = (EventModificationContextMenuObject)obj; - - context.m_Info.AddEvent(context.m_Time); - SelectEvent(context.m_Info.GetEvents(), context.m_Info.GetEventCount() - 1, context.m_Info); - } - - public void EventLineContextMenuDelete(object obj) - { - EventModificationContextMenuObject context = (EventModificationContextMenuObject)obj; - - if (Array.Exists(context.m_Selected, selected => selected)) - { - for (int i = context.m_Selected.Length - 1; i >= 0; --i) - { - if (context.m_Selected[i]) - context.m_Info.RemoveEvent(i); - } - } - else if (context.m_Index >= 0) - { - context.m_Info.RemoveEvent(context.m_Index); - } - } - - private void CheckRectsOnMouseMove(Rect eventLineRect, AnimationEvent[] events, Rect[] hitRects) - { - Vector2 mouse = Event.current.mousePosition; - bool hasFound = false; - m_InstantTooltipText = ""; - - if (events.Length == hitRects.Length) - { - for (int i = hitRects.Length - 1; i >= 0; i--) - { - if (hitRects[i].Contains(mouse)) - { - hasFound = true; - if (m_HoverEvent != i) - { - m_HoverEvent = i; - m_InstantTooltipText = events[m_HoverEvent].functionName; - m_InstantTooltipPoint = new Vector2(mouse.x, mouse.y); - } - } - } - } - if (!hasFound) - m_HoverEvent = -1; - } - - public void Draw(Rect window) - { - EditorGUI.indentLevel++; - if (m_Events != null && m_Events.Length > 0) - AnimationWindowEventInspector.OnEditAnimationEvents(m_Events); - else - AnimationWindowEventInspector.OnDisabledAnimationEvent(); - - EditorGUI.indentLevel--; - - if (m_InstantTooltipText != null && m_InstantTooltipText != "") - { - // Draw body of tooltip - GUIStyle style = (GUIStyle)"AnimationEventTooltip"; - Vector2 size = style.CalcSize(new GUIContent(m_InstantTooltipText)); - Rect rect = new Rect(window.x + m_InstantTooltipPoint.x, window.y + m_InstantTooltipPoint.y, size.x, size.y); - - // Right align tooltip rect if it would otherwise exceed the bounds of the window - if (rect.xMax > window.width) - rect.x = window.width - rect.width; - - GUI.Label(rect, m_InstantTooltipText, style); - } - } - - public bool DeleteEvents(ref AnimationEvent[] eventList, bool[] deleteIndices) - { - bool deletedAny = false; - - for (int i = eventList.Length - 1; i >= 0; i--) - { - if (deleteIndices[i]) - { - ArrayUtility.RemoveAt(ref eventList, i); - deletedAny = true; - } - } - - if (deletedAny) - { - m_EventsSelected = new bool[eventList.Length]; - m_Events = null; - } - - return deletedAny; - } - - public void EditEvents(AnimationClipInfoProperties clipInfo, bool[] selectedIndices) - { - List awEvents = new List(); - - for (int index = 0; index < selectedIndices.Length; ++index) - { - if (selectedIndices[index]) - awEvents.Add(AnimationWindowEvent.Edit(clipInfo, index)); - } - - m_Events = awEvents.ToArray(); - } - - public void UpdateEvents(AnimationClipInfoProperties clipInfo) - { - if (m_Events == null) - return; - - foreach (AnimationWindowEvent awEvent in m_Events) - { - awEvent.clipInfo = clipInfo; - } - } - } -} diff --git a/Editor/Mono/Inspector/AnimationEditor.cs b/Editor/Mono/Inspector/AnimationEditor.cs deleted file mode 100644 index 6924db0d6e..0000000000 --- a/Editor/Mono/Inspector/AnimationEditor.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(Animation))] - [CanEditMultipleObjects] - internal class AnimationEditor : Editor - { - private int m_PrePreviewAnimationArraySize = -1; - - public void OnEnable() - { - m_PrePreviewAnimationArraySize = -1; - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - SerializedProperty clipProperty = serializedObject.FindProperty("m_Animation"); - - EditorGUILayout.PropertyField(clipProperty, true); - int newAnimID = clipProperty.objectReferenceInstanceIDValue; - - SerializedProperty arrProperty = serializedObject.FindProperty("m_Animations"); - int arrSize = arrProperty.arraySize; - - // Remember the array size when ObjectSelector becomes visible - if (ObjectSelector.isVisible && m_PrePreviewAnimationArraySize == -1) - m_PrePreviewAnimationArraySize = arrSize; - - // Make sure the array is the original array size + 1 at max (+1 for the ObjectSelector preview slot) - if (m_PrePreviewAnimationArraySize != -1) - { - // Always resize if the last anim element is not the current animation - int lastAnimID = arrSize > 0 ? arrProperty.GetArrayElementAtIndex(arrSize - 1).objectReferenceInstanceIDValue : -1; - if (lastAnimID != newAnimID) - arrProperty.arraySize = m_PrePreviewAnimationArraySize; - if (!ObjectSelector.isVisible) - m_PrePreviewAnimationArraySize = -1; - } - - DrawPropertiesExcluding(serializedObject, "m_Animation", "m_UserAABB"); - - serializedObject.ApplyModifiedProperties(); - } - - // A minimal list of settings to be shown in the Asset Store preview inspector - internal override void OnAssetStoreInspectorGUI() - { - OnInspectorGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/AnimatorInspector.cs b/Editor/Mono/Inspector/AnimatorInspector.cs deleted file mode 100644 index 430ab6bab1..0000000000 --- a/Editor/Mono/Inspector/AnimatorInspector.cs +++ /dev/null @@ -1,154 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - [CustomEditor(typeof(Animator))] - [CanEditMultipleObjects] - internal class AnimatorInspector : Editor - { - SerializedProperty m_Avatar; - SerializedProperty m_ApplyRootMotion; - SerializedProperty m_CullingMode; - SerializedProperty m_UpdateMode; - SerializedProperty m_WarningMessage; - - AnimBool m_ShowWarningMessage = new AnimBool(); - bool m_IsRootPositionOrRotationControlledByCurves; - - private bool IsWarningMessageEmpty { get { return m_WarningMessage != null && m_WarningMessage.stringValue.Length > 0; } } - private string WarningMessage { get { return m_WarningMessage != null ? m_WarningMessage.stringValue : ""; } } - - class Styles - { - public GUIContent applyRootMotion = new GUIContent(EditorGUIUtility.TrTextContent("Apply Root Motion")); - public GUIContent updateMode = new GUIContent(EditorGUIUtility.TrTextContent("Update Mode")); - public GUIContent cullingMode = new GUIContent(EditorGUIUtility.TrTextContent("Culling Mode")); - - public Styles() - { - applyRootMotion.tooltip = "Automatically move the object using the root motion from the animations"; - updateMode.tooltip = "Controls when and how often the Animator is updated"; - cullingMode.tooltip = "Controls what is updated when the object has been culled"; - } - } - static Styles styles; - - private void Init() - { - if (styles == null) - { - styles = new Styles(); - } - InitShowOptions(); - } - - private void InitShowOptions() - { - m_ShowWarningMessage.value = IsWarningMessageEmpty; - - m_ShowWarningMessage.valueChanged.AddListener(Repaint); - } - - private void UpdateShowOptions() - { - m_ShowWarningMessage.target = IsWarningMessageEmpty; - } - - void OnEnable() - { - m_Avatar = serializedObject.FindProperty("m_Avatar"); - m_ApplyRootMotion = serializedObject.FindProperty("m_ApplyRootMotion"); - m_CullingMode = serializedObject.FindProperty("m_CullingMode"); - m_UpdateMode = serializedObject.FindProperty("m_UpdateMode"); - m_WarningMessage = serializedObject.FindProperty("m_WarningMessage"); - - - Init(); - } - - public override void OnInspectorGUI() - { - bool isEditingMultipleObjects = targets.Length > 1; - - bool cullingModeChanged = false; - bool updateModeChanged = false; - - Animator firstAnimator = target as Animator; - - serializedObject.UpdateIfRequiredOrScript(); - - UpdateShowOptions(); - - EditorGUI.BeginChangeCheck(); - var controller = EditorGUILayout.ObjectField("Controller", firstAnimator.runtimeAnimatorController, typeof(RuntimeAnimatorController), false) as RuntimeAnimatorController; - if (EditorGUI.EndChangeCheck()) - { - foreach (Animator animator in targets) - { - Undo.RecordObject(animator, "Changed AnimatorController"); - animator.runtimeAnimatorController = controller; - } - AnimationWindowUtility.ControllerChanged(); - } - - EditorGUILayout.PropertyField(m_Avatar); - if (firstAnimator.supportsOnAnimatorMove && !isEditingMultipleObjects) - { - EditorGUILayout.LabelField("Apply Root Motion", "Handled by Script"); - } - else - { - EditorGUILayout.PropertyField(m_ApplyRootMotion, styles.applyRootMotion); - - // This might change between layout & repaint so we have local cached value to only update on layout - if (Event.current.type == EventType.Layout) - m_IsRootPositionOrRotationControlledByCurves = firstAnimator.isRootPositionOrRotationControlledByCurves; - - if (!m_ApplyRootMotion.boolValue && m_IsRootPositionOrRotationControlledByCurves) - { - EditorGUILayout.HelpBox("Root position or rotation are controlled by curves", MessageType.Info, true); - } - } - - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_UpdateMode, styles.updateMode); - updateModeChanged = EditorGUI.EndChangeCheck(); - - - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_CullingMode, styles.cullingMode); - cullingModeChanged = EditorGUI.EndChangeCheck(); - - - if (!isEditingMultipleObjects) - EditorGUILayout.HelpBox(firstAnimator.GetStats(), MessageType.Info, true); - - if (EditorGUILayout.BeginFadeGroup(m_ShowWarningMessage.faded)) - { - EditorGUILayout.HelpBox(WarningMessage, MessageType.Warning, true); - } - EditorGUILayout.EndFadeGroup(); - - - serializedObject.ApplyModifiedProperties(); - - foreach (Animator animator in targets) - { - if (cullingModeChanged) - animator.OnCullingModeChanged(); - - if (updateModeChanged) - animator.OnUpdateModeChanged(); - } - } - } -} diff --git a/Editor/Mono/Inspector/AnimatorOverrideControllerInspector.cs b/Editor/Mono/Inspector/AnimatorOverrideControllerInspector.cs deleted file mode 100644 index 47d131609f..0000000000 --- a/Editor/Mono/Inspector/AnimatorOverrideControllerInspector.cs +++ /dev/null @@ -1,213 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class AnimationClipOverrideComparer : IComparer> - { - public int Compare(KeyValuePair x, KeyValuePair y) - { - return string.Compare(x.Key.name, y.Key.name, System.StringComparison.OrdinalIgnoreCase); - } - } - - [CustomEditor(typeof(AnimatorOverrideController))] - [CanEditMultipleObjects] - internal class AnimatorOverrideControllerInspector : Editor - { - SerializedProperty m_Controller; - - private List> m_Clips; - - ReorderableList m_ClipList; - string m_Search; - - void OnEnable() - { - AnimatorOverrideController animatorOverrideController = target as AnimatorOverrideController; - - m_Controller = serializedObject.FindProperty("m_Controller"); - m_Search = ""; - - if (m_Clips == null) - m_Clips = new List>(); - - if (m_ClipList == null) - { - animatorOverrideController.GetOverrides(m_Clips); - - m_Clips.Sort(new AnimationClipOverrideComparer()); - - m_ClipList = new ReorderableList(m_Clips, typeof(KeyValuePair), false, true, false, false); - m_ClipList.drawElementCallback = DrawClipElement; - m_ClipList.drawHeaderCallback = DrawClipHeader; - m_ClipList.onSelectCallback = SelectClip; - m_ClipList.elementHeight = 16; - } - animatorOverrideController.OnOverrideControllerDirty += Repaint; - } - - void OnDisable() - { - AnimatorOverrideController animatorOverrideController = target as AnimatorOverrideController; - animatorOverrideController.OnOverrideControllerDirty -= Repaint; - } - - public override void OnInspectorGUI() - { - bool isEditingMultipleObjects = targets.Length > 1; - bool changeCheck = false; - - serializedObject.UpdateIfRequiredOrScript(); - - AnimatorOverrideController animatorOverrideController = target as AnimatorOverrideController; - RuntimeAnimatorController runtimeAnimatorController = m_Controller.hasMultipleDifferentValues ? null : animatorOverrideController.runtimeAnimatorController; - - EditorGUI.BeginChangeCheck(); - runtimeAnimatorController = EditorGUILayout.ObjectField("Controller", runtimeAnimatorController, typeof(Animations.AnimatorController), false) as RuntimeAnimatorController; - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < targets.Length; i++) - { - AnimatorOverrideController controller = targets[i] as AnimatorOverrideController; - controller.runtimeAnimatorController = runtimeAnimatorController; - } - - changeCheck = true; - } - - { - GUI.SetNextControlName("OverridesSearch"); - - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape && GUI.GetNameOfFocusedControl() == "OverridesSearch") - m_Search = ""; - - EditorGUI.BeginChangeCheck(); - string newSearch = EditorGUILayout.ToolbarSearchField(m_Search); - if (EditorGUI.EndChangeCheck()) - m_Search = newSearch; - } - - - using (new EditorGUI.DisabledScope(m_Controller == null || (isEditingMultipleObjects && m_Controller.hasMultipleDifferentValues) || runtimeAnimatorController == null)) - { - EditorGUI.BeginChangeCheck(); - animatorOverrideController.GetOverrides(m_Clips); - - if (m_Search.Length > 0) - FilterOverrides(); - else // If there is not filter simply sort all the list. - m_Clips.Sort(new AnimationClipOverrideComparer()); - - m_ClipList.list = m_Clips; - m_ClipList.DoLayoutList(); - if (EditorGUI.EndChangeCheck()) - { - for (int i = 0; i < targets.Length; i++) - { - AnimatorOverrideController controller = targets[i] as AnimatorOverrideController; - controller.ApplyOverrides(m_Clips); - } - changeCheck = true; - } - } - - if (changeCheck) - animatorOverrideController.PerformOverrideClipListCleanup(); - } - - private void FilterOverrides() - { - if (m_Search.Length == 0) - return; - - // Support multiple search words separated by spaces. - string[] searchWords = m_Search.ToLower().Split(' '); - - // We keep two lists. Matches that matches the start of an item always get first priority. - List> matchesStart = new List>(); - List> matchesWithin = new List>(); - foreach (KeyValuePair kvp in m_Clips) - { - string name = kvp.Key.name; - name = name.ToLower().Replace(" ", ""); - - bool didMatchAll = true; - bool didMatchStart = false; - - // See if we match ALL the search words. - for (int w = 0; w < searchWords.Length; w++) - { - string search = searchWords[w]; - if (name.Contains(search)) - { - // If the start of the item matches the first search word, make a note of that. - if (w == 0 && name.StartsWith(search)) - didMatchStart = true; - } - else - { - // As soon as any word is not matched, we disregard this item. - didMatchAll = false; - break; - } - } - // We always need to match all search words. - // If we ALSO matched the start, this item gets priority. - if (didMatchAll) - { - if (didMatchStart) - matchesStart.Add(kvp); - else - matchesWithin.Add(kvp); - } - } - - m_Clips.Clear(); - - matchesStart.Sort(new AnimationClipOverrideComparer()); - matchesWithin.Sort(new AnimationClipOverrideComparer()); - - // Add search results - m_Clips.AddRange(matchesStart); - m_Clips.AddRange(matchesWithin); - } - - private void DrawClipElement(Rect rect, int index, bool selected, bool focused) - { - AnimationClip originalClip = m_Clips[index].Key; - AnimationClip overrideClip = m_Clips[index].Value; - - rect.xMax = rect.xMax / 2.0f; - GUI.Label(rect, originalClip.name, EditorStyles.label); - rect.xMin = rect.xMax; - rect.xMax *= 2.0f; - - EditorGUI.BeginChangeCheck(); - overrideClip = EditorGUI.ObjectField(rect, "", overrideClip, typeof(AnimationClip), false) as AnimationClip; - if (EditorGUI.EndChangeCheck()) - m_Clips[index] = new KeyValuePair(originalClip, overrideClip); - } - - private void DrawClipHeader(Rect rect) - { - rect.xMax = rect.xMax / 2.0f; - GUI.Label(rect, "Original", EditorStyles.label); - rect.xMin = rect.xMax; - rect.xMax *= 2.0f; - GUI.Label(rect, "Override", EditorStyles.label); - } - - private void SelectClip(ReorderableList list) - { - if (0 <= list.index && list.index < m_Clips.Count) - EditorGUIUtility.PingObject(m_Clips[list.index].Key); - } - } -} diff --git a/Editor/Mono/Inspector/AreaEffector2DEditor.cs b/Editor/Mono/Inspector/AreaEffector2DEditor.cs deleted file mode 100644 index e202549f66..0000000000 --- a/Editor/Mono/Inspector/AreaEffector2DEditor.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - /// - /// Prompts the end-user to add 2D colliders if non exist for 2D effector to work with. - /// - [CustomEditor(typeof(AreaEffector2D), true)] - [CanEditMultipleObjects] - internal class AreaEffector2DEditor : Effector2DEditor - { - readonly AnimBool m_ShowForceRollout = new AnimBool(); - SerializedProperty m_UseGlobalAngle; - SerializedProperty m_ForceAngle; - SerializedProperty m_ForceMagnitude; - SerializedProperty m_ForceVariation; - SerializedProperty m_ForceTarget; - - static readonly AnimBool m_ShowDampingRollout = new AnimBool(); - SerializedProperty m_Drag; - SerializedProperty m_AngularDrag; - - public override void OnEnable() - { - base.OnEnable(); - - m_ShowForceRollout.value = true; - m_ShowForceRollout.valueChanged.AddListener(Repaint); - m_UseGlobalAngle = serializedObject.FindProperty("m_UseGlobalAngle"); - m_ForceAngle = serializedObject.FindProperty("m_ForceAngle"); - m_ForceMagnitude = serializedObject.FindProperty("m_ForceMagnitude"); - m_ForceVariation = serializedObject.FindProperty("m_ForceVariation"); - m_ForceTarget = serializedObject.FindProperty("m_ForceTarget"); - - m_ShowDampingRollout.valueChanged.AddListener(Repaint); - m_Drag = serializedObject.FindProperty("m_Drag"); - m_AngularDrag = serializedObject.FindProperty("m_AngularDrag"); - } - - public override void OnDisable() - { - base.OnDisable(); - - m_ShowForceRollout.valueChanged.RemoveListener(Repaint); - m_ShowDampingRollout.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - - serializedObject.Update(); - - // Force. - m_ShowForceRollout.target = EditorGUILayout.Foldout(m_ShowForceRollout.target, "Force", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowForceRollout.faded)) - { - EditorGUILayout.PropertyField(m_UseGlobalAngle); - EditorGUILayout.PropertyField(m_ForceAngle); - EditorGUILayout.PropertyField(m_ForceMagnitude); - EditorGUILayout.PropertyField(m_ForceVariation); - EditorGUILayout.PropertyField(m_ForceTarget); - EditorGUILayout.Space(); - } - EditorGUILayout.EndFadeGroup(); - - // Drag. - m_ShowDampingRollout.target = EditorGUILayout.Foldout(m_ShowDampingRollout.target, "Damping", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowDampingRollout.faded)) - { - EditorGUILayout.PropertyField(m_Drag); - EditorGUILayout.PropertyField(m_AngularDrag); - } - EditorGUILayout.EndFadeGroup(); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs b/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs deleted file mode 100644 index 77fbe87c06..0000000000 --- a/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs +++ /dev/null @@ -1,677 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditorInternal; -using UnityEditor.Scripting.ScriptCompilation; -using UnityEditor.Experimental.AssetImporters; -using UnityEditor.Compilation; -using System; - -namespace UnityEditor -{ - [CustomEditor(typeof(UnityEditorInternal.AssemblyDefinitionImporter))] - [CanEditMultipleObjects] - internal class AssemblyDefinitionImporterInspector : AssetImporterEditor - { - internal class Styles - { - public static readonly GUIContent name = EditorGUIUtility.TrTextContent("Name"); - public static readonly GUIContent unityReferences = EditorGUIUtility.TrTextContent("Unity References"); - public static readonly GUIContent references = EditorGUIUtility.TrTextContent("References"); - public static readonly GUIContent options = EditorGUIUtility.TrTextContent("Options"); - public static readonly GUIContent allowUnsafeCode = EditorGUIUtility.TrTextContent("Allow 'unsafe' Code"); - public static readonly GUIContent platforms = EditorGUIUtility.TrTextContent("Platforms"); - public static readonly GUIContent anyPlatform = EditorGUIUtility.TrTextContent("Any Platform"); - public static readonly GUIContent includePlatforms = EditorGUIUtility.TrTextContent("Include Platforms"); - public static readonly GUIContent excludePlatforms = EditorGUIUtility.TrTextContent("Exclude Platforms"); - public static readonly GUIContent selectAll = EditorGUIUtility.TrTextContent("Select all"); - public static readonly GUIContent deselectAll = EditorGUIUtility.TrTextContent("Deselect all"); - public static readonly GUIContent apply = EditorGUIUtility.TrTextContent("Apply"); - public static readonly GUIContent revert = EditorGUIUtility.TrTextContent("Revert"); - public static readonly GUIContent loadError = EditorGUIUtility.TrTextContent("Load error"); - } - - GUIStyle m_TextStyle; - - internal enum MixedBool : int - { - Mixed = -1, - False = 0, - True = 1 - } - - internal class AssemblyDefinitionReference - { - public string path - { - get { return AssetDatabase.GetAssetPath(asset); } - } - public AssemblyDefinitionAsset asset; - public CustomScriptAssemblyData data; - public MixedBool displayValue; - } - - internal class AssemblyDefintionState - { - public string path - { - get { return AssetDatabase.GetAssetPath(asset); } - } - public AssemblyDefinitionAsset asset; - public string name; - public List references; - public MixedBool[] optionalUnityReferences; - public MixedBool allowUnsafeCode; - public MixedBool compatibleWithAnyPlatform; - public MixedBool[] platformCompatibility; - public bool modified; - } - - AssemblyDefintionState[] m_TargetStates; - - AssemblyDefintionState m_State; - ReorderableList m_ReferencesList; - - public override bool showImportedObject { get { return false; } } - - public override void OnInspectorGUI() - { - if (m_State == null) - { - try - { - LoadAssemblyDefinitionFiles(); - } - catch (Exception e) - { - m_State = null; - ShowLoadErrorExceptionGUI(e); - return; - } - } - - var platforms = Compilation.CompilationPipeline.GetAssemblyDefinitionPlatforms(); - var optionalUnityReferences = CustomScriptAssembly.OptinalUnityAssemblies; - - using (new EditorGUI.DisabledScope(false)) - { - EditorGUI.BeginChangeCheck(); - - if (targets.Length > 1) - { - using (new EditorGUI.DisabledScope(true)) - { - var value = string.Join(", ", m_TargetStates.Select(t => t.name).ToArray()); - EditorGUILayout.TextField(Styles.name, value, EditorStyles.textField); - } - } - else - { - m_State.name = EditorGUILayout.TextField(Styles.name, m_State.name, EditorStyles.textField); - } - - GUILayout.Label(Styles.references, EditorStyles.boldLabel); - m_ReferencesList.DoLayoutList(); - - GUILayout.Label(Styles.unityReferences, EditorStyles.boldLabel); - EditorGUILayout.BeginVertical(GUI.skin.box); - for (int i = 0; i < optionalUnityReferences.Length; ++i) - { - m_State.optionalUnityReferences[i] = ToggleWithMixedValue(new GUIContent(optionalUnityReferences[i].DisplayName), m_State.optionalUnityReferences[i]); - - if (m_State.optionalUnityReferences[i] == MixedBool.True) - { - EditorGUILayout.HelpBox(optionalUnityReferences[i].AdditinalInformationWhenEnabled, MessageType.Info); - } - } - EditorGUILayout.EndVertical(); - GUILayout.Space(10f); - - GUILayout.Label(Styles.options, EditorStyles.boldLabel); - EditorGUILayout.BeginVertical(GUI.skin.box); - m_State.allowUnsafeCode = ToggleWithMixedValue(Styles.allowUnsafeCode, m_State.allowUnsafeCode); - EditorGUILayout.EndVertical(); - GUILayout.Space(10f); - - GUILayout.Label(Styles.platforms, EditorStyles.boldLabel); - EditorGUILayout.BeginVertical(GUI.skin.box); - var compatibleWithAnyPlatform = m_State.compatibleWithAnyPlatform; - m_State.compatibleWithAnyPlatform = ToggleWithMixedValue(Styles.anyPlatform, m_State.compatibleWithAnyPlatform); - - if (compatibleWithAnyPlatform == MixedBool.Mixed && m_State.compatibleWithAnyPlatform != MixedBool.Mixed) - { - // Switching from mixed state to non-mixed state. - // Invert state include/exclude compatibility of states that have the opposite compatibility, - // so all states are either include or exclude. - UpdatePlatformCompatibility(m_State.compatibleWithAnyPlatform, m_TargetStates); - - // Now that we have potentially update the compatibility states, we now also - // need to update the combined state to reflect the changes. - UpdateCombinedCompatibility(); - } - else if (m_State.compatibleWithAnyPlatform != compatibleWithAnyPlatform) - { - InversePlatformCompatibility(m_State); - } - - if (m_State.compatibleWithAnyPlatform != MixedBool.Mixed) - { - GUILayout.Label(m_State.compatibleWithAnyPlatform == MixedBool.True ? Styles.excludePlatforms : Styles.includePlatforms, EditorStyles.boldLabel); - - for (int i = 0; i < platforms.Length; ++i) - { - m_State.platformCompatibility[i] = ToggleWithMixedValue(new GUIContent(platforms[i].DisplayName), m_State.platformCompatibility[i]); - } - - EditorGUILayout.Space(); - - GUILayout.BeginHorizontal(); - - if (GUILayout.Button(Styles.selectAll)) - { - SetPlatformCompatibility(m_State, MixedBool.True); - } - - if (GUILayout.Button(Styles.deselectAll)) - { - SetPlatformCompatibility(m_State, MixedBool.False); - } - - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - } - - EditorGUILayout.EndVertical(); - GUILayout.Space(10f); - - if (EditorGUI.EndChangeCheck()) - m_State.modified = true; - } - - EditorGUILayout.Space(); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - using (new EditorGUI.DisabledScope(!m_State.modified)) - { - if (GUILayout.Button(Styles.revert)) - { - LoadAssemblyDefinitionFiles(); - } - - if (GUILayout.Button(Styles.apply)) - { - SaveAndUpdateAssemblyDefinitionStates(m_State, m_TargetStates); - } - } - - GUILayout.EndHorizontal(); - } - - public override void OnDisable() - { - if (m_State != null && m_State.modified) - { - AssetImporter importer = target as AssetImporter; - - string dialogText = "Unapplied import settings for \'" + importer.assetPath + "\'"; - - if (targets.Length > 1) - dialogText = "Unapplied import settings for \'" + targets.Length + "\' files"; - - if (EditorUtility.DisplayDialog("Unapplied import settings", dialogText, "Apply", "Revert")) - { - SaveAndUpdateAssemblyDefinitionStates(m_State, m_TargetStates); - } - } - } - - static void UpdatePlatformCompatibility(MixedBool compatibleWithAnyPlatform, AssemblyDefintionState[] states) - { - if (compatibleWithAnyPlatform == MixedBool.Mixed) - throw new ArgumentOutOfRangeException("compatibleWithAnyPlatform"); - - foreach (var state in states) - { - // Same include/exclude compatibility - if (state.compatibleWithAnyPlatform == compatibleWithAnyPlatform) - continue; - - // Opposite compatibility, invert. - state.compatibleWithAnyPlatform = compatibleWithAnyPlatform; - InversePlatformCompatibility(state); - } - } - - static MixedBool ToMixedBool(bool value) - { - return value ? MixedBool.True : MixedBool.False; - } - - static bool ToBool(MixedBool value) - { - if (value == MixedBool.Mixed) - throw new System.ArgumentException("Cannot convert MixedBool.Mixed to bool"); - - return value == MixedBool.True; - } - - static MixedBool ToggleWithMixedValue(GUIContent title, MixedBool value) - { - EditorGUI.showMixedValue = value == MixedBool.Mixed; - - EditorGUI.BeginChangeCheck(); - - bool newBoolValue = EditorGUILayout.Toggle(title, value == MixedBool.True); - if (EditorGUI.EndChangeCheck()) - return newBoolValue ? MixedBool.True : MixedBool.False; - - EditorGUI.showMixedValue = false; - return value; - } - - static void InversePlatformCompatibility(AssemblyDefintionState state) - { - var platforms = Compilation.CompilationPipeline.GetAssemblyDefinitionPlatforms(); - - for (int i = 0; i < platforms.Length; ++i) - state.platformCompatibility[i] = InverseCompability(state.platformCompatibility[i]); - } - - static void SetPlatformCompatibility(AssemblyDefintionState state, MixedBool compatibility) - { - var platforms = Compilation.CompilationPipeline.GetAssemblyDefinitionPlatforms(); - - for (int i = 0; i < platforms.Length; ++i) - state.platformCompatibility[i] = compatibility; - } - - static MixedBool InverseCompability(MixedBool compatibility) - { - if (compatibility == MixedBool.True) - return MixedBool.False; - - if (compatibility == MixedBool.False) - return MixedBool.True; - - return MixedBool.Mixed; - } - - void ShowLoadErrorExceptionGUI(Exception e) - { - if (m_TextStyle == null) - m_TextStyle = "ScriptText"; - - GUILayout.Label(Styles.loadError, EditorStyles.boldLabel); - Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.TempContent(e.Message), m_TextStyle); - EditorGUI.HelpBox(rect, e.Message, MessageType.Error); - } - - void LoadAssemblyDefinitionFiles() - { - m_TargetStates = new AssemblyDefintionState[targets.Length]; - - for (int i = 0; i < targets.Length; ++i) - { - var importer = targets[i] as AssetImporter; - - if (importer == null) - continue; - - m_TargetStates[i] = LoadAssemblyDefintionState(importer.assetPath); - } - - // Show as many references as the shortest list of references. - int minReferencesCount = m_TargetStates.Min(t => t.references.Count()); - - m_State = new AssemblyDefintionState(); - m_State.name = m_TargetStates[0].name; - m_State.references = new List(); - m_State.modified = m_TargetStates[0].modified; - m_State.allowUnsafeCode = m_TargetStates[0].allowUnsafeCode; - - for (int i = 0; i < minReferencesCount; ++i) - m_State.references.Add(m_TargetStates[0].references[i]); - - for (int i = 1; i < m_TargetStates.Length; ++i) - { - var targetState = m_TargetStates[i]; - - for (int r = 0; r < minReferencesCount; ++r) - { - // If already set to mixed, continue. - if (m_State.references[r].displayValue == MixedBool.Mixed) - continue; - - // If different from existing value, set to mixed. - if (m_State.references[r].path != targetState.references[r].path) - m_State.references[r].displayValue = MixedBool.Mixed; - } - - if (m_State.allowUnsafeCode != MixedBool.Mixed) - { - if (m_State.allowUnsafeCode != targetState.allowUnsafeCode) - m_State.allowUnsafeCode = MixedBool.Mixed; - } - - m_State.modified |= targetState.modified; - } - - UpdateCombinedCompatibility(); - - m_ReferencesList = new ReorderableList(m_State.references, typeof(AssemblyDefinitionReference), false, false, true, true); - m_ReferencesList.drawElementCallback = DrawReferenceListElement; - m_ReferencesList.onAddCallback = AddReferenceListElement; - m_ReferencesList.onRemoveCallback = RemoveReferenceListElement; - - - m_ReferencesList.elementHeight = EditorGUIUtility.singleLineHeight + 2; - m_ReferencesList.headerHeight = 3; - } - - void UpdateCombinedCompatibility() - { - // Merge platform compability for all targets - m_State.compatibleWithAnyPlatform = m_TargetStates[0].compatibleWithAnyPlatform; - - var platforms = Compilation.CompilationPipeline.GetAssemblyDefinitionPlatforms(); - m_State.platformCompatibility = new MixedBool[platforms.Length]; - - var optionalUnityReferences = CustomScriptAssembly.OptinalUnityAssemblies; - m_State.optionalUnityReferences = new MixedBool[optionalUnityReferences.Length]; - - Array.Copy(m_TargetStates[0].platformCompatibility, m_State.platformCompatibility, platforms.Length); - Array.Copy(m_TargetStates[0].optionalUnityReferences, m_State.optionalUnityReferences, optionalUnityReferences.Length); - - for (int i = 1; i < m_TargetStates.Length; ++i) - { - var targetState = m_TargetStates[i]; - - if (m_State.compatibleWithAnyPlatform != MixedBool.Mixed) - { - if (m_State.compatibleWithAnyPlatform != targetState.compatibleWithAnyPlatform) - m_State.compatibleWithAnyPlatform = MixedBool.Mixed; - } - - for (int j = 0; j < m_State.optionalUnityReferences.Length; ++j) - { - if (m_State.optionalUnityReferences[j] != MixedBool.Mixed) - { - if (m_State.optionalUnityReferences[j] != targetState.optionalUnityReferences[j]) - m_State.optionalUnityReferences[j] = MixedBool.Mixed; - } - } - - for (int p = 0; p < platforms.Length; ++p) - { - // If already set to mixed, continue. - if (m_State.platformCompatibility[p] == MixedBool.Mixed) - continue; - - // If different from existing value, set to mixed. - if (m_State.platformCompatibility[p] != targetState.platformCompatibility[p]) - m_State.platformCompatibility[p] = MixedBool.Mixed; - } - } - } - - static AssemblyDefintionState LoadAssemblyDefintionState(string path) - { - var asset = AssetDatabase.LoadAssetAtPath(path); - - if (asset == null) - return null; - - var data = CustomScriptAssemblyData.FromJson(asset.text); - - if (data == null) - return null; - - var state = new AssemblyDefintionState(); - - state.asset = asset; - state.name = data.name; - state.references = new List(); - state.allowUnsafeCode = ToMixedBool(data.allowUnsafeCode); - - if (data.references != null) - { - foreach (var reference in data.references) - { - try - { - var assemblyDefinitionFile = new AssemblyDefinitionReference(); - var referencePath = Compilation.CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(reference); - - if (string.IsNullOrEmpty(referencePath)) - throw new AssemblyDefinitionException(string.Format("Could not find assembly reference '{0}'", reference), path); - - assemblyDefinitionFile.asset = AssetDatabase.LoadAssetAtPath(referencePath); - - if (assemblyDefinitionFile.asset == null) - throw new AssemblyDefinitionException(string.Format("Reference assembly definition file '{0}' not found", referencePath), path); - - assemblyDefinitionFile.data = CustomScriptAssemblyData.FromJson(assemblyDefinitionFile.asset.text); - assemblyDefinitionFile.displayValue = MixedBool.False; - state.references.Add(assemblyDefinitionFile); - } - catch (AssemblyDefinitionException e) - { - UnityEngine.Debug.LogException(e, asset); - state.references.Add(new AssemblyDefinitionReference()); - state.modified = true; - } - } - } - - var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms(); - state.platformCompatibility = new MixedBool[platforms.Length]; - - var OptinalUnityAssemblies = CustomScriptAssembly.OptinalUnityAssemblies; - state.optionalUnityReferences = new MixedBool[OptinalUnityAssemblies.Length]; - - if (data.optionalUnityReferences != null) - { - for (int i = 0; i < OptinalUnityAssemblies.Length; i++) - { - var optionalUnityReferences = OptinalUnityAssemblies[i].OptionalUnityReferences.ToString(); - var any = data.optionalUnityReferences.Any(x => x == optionalUnityReferences); - if (any) - { - state.optionalUnityReferences[i] = MixedBool.True; - } - } - } - - state.compatibleWithAnyPlatform = MixedBool.True; - string[] dataPlatforms = null; - - if (data.includePlatforms != null && data.includePlatforms.Length > 0) - { - state.compatibleWithAnyPlatform = MixedBool.False; - dataPlatforms = data.includePlatforms; - } - else if (data.excludePlatforms != null && data.excludePlatforms.Length > 0) - { - state.compatibleWithAnyPlatform = MixedBool.True; - dataPlatforms = data.excludePlatforms; - } - - if (dataPlatforms != null) - foreach (var platform in dataPlatforms) - { - var platformIndex = GetPlatformIndex(platforms, platform); - state.platformCompatibility[platformIndex] = MixedBool.True; - } - - return state; - } - - static AssemblyDefinitionReference CreateAssemblyDefinitionReference(string assemblyName) - { - var assemblyDefinitionFile = new AssemblyDefinitionReference(); - var path = Compilation.CompilationPipeline.GetAssemblyDefinitionFilePathFromAssemblyName(assemblyName); - - if (string.IsNullOrEmpty(path)) - throw new System.Exception(string.Format("Could not get assembly definition filename for assembly '{0}'", assemblyName)); - - assemblyDefinitionFile.asset = AssetDatabase.LoadAssetAtPath(path); - - if (assemblyDefinitionFile.asset == null) - throw new FileNotFoundException(string.Format("Assembly definition file '{0}' not found", assemblyDefinitionFile.path), assemblyDefinitionFile.path); - - assemblyDefinitionFile.data = CustomScriptAssemblyData.FromJson(assemblyDefinitionFile.asset.text); - - return assemblyDefinitionFile; - } - - static void SaveAndUpdateAssemblyDefinitionStates(AssemblyDefintionState combinedState, AssemblyDefintionState[] states) - { - int combinedReferenceCount = combinedState.references.Count(); - - // Update the name if there is only one file selected. - if (states.Length == 1) - states[0].name = combinedState.name; - - foreach (var state in states) - { - if (combinedState.allowUnsafeCode != MixedBool.Mixed) - state.allowUnsafeCode = combinedState.allowUnsafeCode; - - for (int i = 0; i < combinedReferenceCount; ++i) - { - if (combinedState.references[i].displayValue != MixedBool.Mixed) - state.references[i] = combinedState.references[i]; - } - - if (combinedState.compatibleWithAnyPlatform != MixedBool.Mixed) - state.compatibleWithAnyPlatform = combinedState.compatibleWithAnyPlatform; - - for (int i = 0; i < combinedState.platformCompatibility.Length; ++i) - { - if (combinedState.platformCompatibility[i] != MixedBool.Mixed) - state.platformCompatibility[i] = combinedState.platformCompatibility[i]; - } - - for (int i = 0; i < combinedState.optionalUnityReferences.Length; ++i) - { - if (combinedState.platformCompatibility[i] != MixedBool.Mixed) - state.optionalUnityReferences[i] = combinedState.optionalUnityReferences[i]; - } - - SaveAssemblyDefinitionState(state); - } - - combinedState.modified = false; - } - - static void SaveAssemblyDefinitionState(AssemblyDefintionState state) - { - var references = state.references.Where(r => r.asset != null); - var platforms = Compilation.CompilationPipeline.GetAssemblyDefinitionPlatforms(); - var OptinalUnityAssemblies = CustomScriptAssembly.OptinalUnityAssemblies; - - CustomScriptAssemblyData data = new CustomScriptAssemblyData(); - - data.name = state.name; - - data.references = references.Select(r => r.data.name).ToArray(); - - List optionalUnityReferences = new List(); - - for (int i = 0; i < OptinalUnityAssemblies.Length; i++) - { - if (state.optionalUnityReferences[i] == MixedBool.True) - optionalUnityReferences.Add(OptinalUnityAssemblies[i].OptionalUnityReferences.ToString()); - } - data.optionalUnityReferences = optionalUnityReferences.ToArray(); - - data.allowUnsafeCode = ToBool(state.allowUnsafeCode); - - List dataPlatforms = new List(); - - for (int i = 0; i < platforms.Length; ++i) - { - if (state.platformCompatibility[i] == MixedBool.True) - dataPlatforms.Add(platforms[i].Name); - } - - if (dataPlatforms.Any()) - { - if (state.compatibleWithAnyPlatform == MixedBool.True) - data.excludePlatforms = dataPlatforms.ToArray(); - else - data.includePlatforms = dataPlatforms.ToArray(); - } - - var json = CustomScriptAssemblyData.ToJson(data); - File.WriteAllText(state.path, json); - state.modified = false; - - AssetDatabase.ImportAsset(state.path); - } - - static int GetPlatformIndex(AssemblyDefinitionPlatform[] platforms, string name) - { - for (int i = 0; i < platforms.Length; ++i) - { - if (string.Equals(platforms[i].Name, name, System.StringComparison.InvariantCultureIgnoreCase)) - return i; - } - - throw new System.ArgumentException(string.Format("Unknown platform '{0}'", name) , name); - } - - void DrawReferenceListElement(Rect rect, int index, bool selected, bool focused) - { - var list = m_ReferencesList.list; - var assemblyDefinitionFile = list[index] as AssemblyDefinitionReference; - - rect.height -= 2; - var label = assemblyDefinitionFile.data != null ? assemblyDefinitionFile.data.name : "(Missing Reference)"; - var asset = assemblyDefinitionFile.asset; - - bool mixed = assemblyDefinitionFile.displayValue == MixedBool.Mixed; - EditorGUI.showMixedValue = mixed; - assemblyDefinitionFile.asset = EditorGUI.ObjectField(rect, mixed ? "(Multiple Values)" : label, asset, typeof(AssemblyDefinitionAsset), false) as AssemblyDefinitionAsset; - EditorGUI.showMixedValue = false; - - if (asset != assemblyDefinitionFile.asset && assemblyDefinitionFile.asset != null) - { - assemblyDefinitionFile.data = CustomScriptAssemblyData.FromJson(assemblyDefinitionFile.asset.text); - - foreach (var state in m_TargetStates) - state.references[index] = assemblyDefinitionFile; - } - } - - void AddReferenceListElement(ReorderableList list) - { - ReorderableList.defaultBehaviours.DoAddButton(list); - - foreach (var state in m_TargetStates) - { - // Only add references to lists that are smaller or equal to the combined references list size. - if (state.references.Count <= list.count) - { - int index = Math.Min(list.index, state.references.Count()); - state.references.Insert(index, list.list[list.index] as AssemblyDefinitionReference); - } - } - } - - void RemoveReferenceListElement(ReorderableList list) - { - foreach (var state in m_TargetStates) - state.references.RemoveAt(list.index); - - ReorderableList.defaultBehaviours.DoRemoveButton(list); - } - } -} diff --git a/Editor/Mono/Inspector/AssetBundleNameGUI.cs b/Editor/Mono/Inspector/AssetBundleNameGUI.cs deleted file mode 100644 index 783ad05505..0000000000 --- a/Editor/Mono/Inspector/AssetBundleNameGUI.cs +++ /dev/null @@ -1,225 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Linq; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AssetBundleNameGUI - { - static private readonly GUIContent kAssetBundleName = EditorGUIUtility.TrTextContent("AssetBundle"); - static private readonly int kAssetBundleNameFieldIdHash = "AssetBundleNameFieldHash".GetHashCode(); - - static private readonly int kAssetBundleVariantFieldIdHash = "AssetBundleVariantFieldHash".GetHashCode(); - - private class Styles - { - private static GUISkin s_DarkSkin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Scene); - - public static GUIStyle label = GetStyle("ControlLabel"); - public static GUIStyle popup = GetStyle("MiniPopup"); - public static GUIStyle textField = GetStyle("textField"); - - public static Color cursorColor = s_DarkSkin.settings.cursorColor; - - private static GUIStyle GetStyle(string name) - { - return new GUIStyle(s_DarkSkin.GetStyle(name)); - } - } - - private bool m_ShowAssetBundleNameTextField = false; - private bool m_ShowAssetBundleVariantTextField = false; - - public void OnAssetBundleNameGUI(IEnumerable assets) - { - EditorGUIUtility.labelWidth = 90f; - - Rect bundleRect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight); - Rect variantRect = bundleRect; - - bundleRect.width *= 0.8f; - variantRect.xMin += bundleRect.width + EditorGUI.kSpacing; - - - int id = GUIUtility.GetControlID(kAssetBundleNameFieldIdHash, FocusType.Passive, bundleRect); - - bundleRect = EditorGUI.PrefixLabel(bundleRect, id, kAssetBundleName, Styles.label); - if (m_ShowAssetBundleNameTextField) - AssetBundleTextField(bundleRect, id, assets, false); - else - AssetBundlePopup(bundleRect, id, assets, false); - - id = GUIUtility.GetControlID(kAssetBundleVariantFieldIdHash, FocusType.Passive, variantRect); - - if (m_ShowAssetBundleVariantTextField) - AssetBundleTextField(variantRect, id, assets, true); - else - AssetBundlePopup(variantRect, id, assets, true); - } - - private void ShowNewAssetBundleField(bool isVariant) - { - m_ShowAssetBundleNameTextField = !isVariant; - m_ShowAssetBundleVariantTextField = isVariant; - - EditorGUIUtility.editingTextField = true; - } - - private void AssetBundleTextField(Rect rect, int id, IEnumerable assets, bool isVariant) - { - // CursorColor is stored at the GUISkin level, but the styles we are using don't necessarily match the GUI.skin. - // TextField assumes that the style matches the current GUI.skin, this is wrong and should be fixed. We'll workaround for now. - Color oldCursorColor = GUI.skin.settings.cursorColor; - GUI.skin.settings.cursorColor = Styles.cursorColor; - - EditorGUI.BeginChangeCheck(); - string temp = EditorGUI.DelayedTextFieldInternal(rect, id, GUIContent.none, "", null, Styles.textField); - if (EditorGUI.EndChangeCheck()) - { - SetAssetBundleForAssets(assets, temp, isVariant); - ShowAssetBundlePopup(); - } - - GUI.skin.settings.cursorColor = oldCursorColor; - - // editing was cancelled - if (EditorGUI.IsEditingTextField() == false && Event.current.type != EventType.Layout) - ShowAssetBundlePopup(); - } - - private void ShowAssetBundlePopup() - { - m_ShowAssetBundleNameTextField = false; - m_ShowAssetBundleVariantTextField = false; - } - - private void AssetBundlePopup(Rect rect, int id, IEnumerable assets, bool isVariant) - { - List displayedOptions = new List(); - displayedOptions.Add("None"); - displayedOptions.Add(""); // seperator - - // Anyway to optimize this by caching GetAssetBundleNameFromAssets() and GetAllAssetBundleNames() when they actually change? - // As we can change the assetBundle name by script, the UI needs to detect this kind of change. - bool mixedValue; - IEnumerable assetBundleFromAssets = GetAssetBundlesFromAssets(assets, isVariant, out mixedValue); - - string[] assetBundles = isVariant ? AssetDatabase.GetAllAssetBundleVariants() : AssetDatabase.GetAllAssetBundleNamesWithoutVariant(); - displayedOptions.AddRange(assetBundles); - - displayedOptions.Add(""); // seperator - int newAssetBundleIndex = displayedOptions.Count; - displayedOptions.Add("New..."); - - // These two options are invalid for variant, so skip them for variant. - int removeUnusedIndex = -1; - int filterSelectedIndex = -1; - if (!isVariant) - { - removeUnusedIndex = displayedOptions.Count; - displayedOptions.Add("Remove Unused Names"); - filterSelectedIndex = displayedOptions.Count; - if (assetBundleFromAssets.Count() != 0) - displayedOptions.Add("Filter Selected Name" + (mixedValue ? "s" : "")); - } - - int selectedIndex = 0; - string firstAssetBundle = assetBundleFromAssets.FirstOrDefault(); - if (!String.IsNullOrEmpty(firstAssetBundle)) - selectedIndex = displayedOptions.IndexOf(firstAssetBundle); - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = mixedValue; - selectedIndex = EditorGUI.DoPopup(rect, id, selectedIndex, EditorGUIUtility.TempContent(displayedOptions.ToArray()), Styles.popup); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - if (selectedIndex == 0) // None - SetAssetBundleForAssets(assets, null, isVariant); - else if (selectedIndex == newAssetBundleIndex) // New... - ShowNewAssetBundleField(isVariant); - else if (selectedIndex == removeUnusedIndex) // Remove Unused Names - AssetDatabase.RemoveUnusedAssetBundleNames(); - else if (selectedIndex == filterSelectedIndex) // Filter Selected Name(s) - FilterSelected(assetBundleFromAssets); - else - SetAssetBundleForAssets(assets, displayedOptions[selectedIndex], isVariant); - } - } - - private void FilterSelected(IEnumerable assetBundleNames) - { - var searchFilter = new SearchFilter(); - searchFilter.assetBundleNames = assetBundleNames.Where(name => !String.IsNullOrEmpty(name)).ToArray(); - - if (ProjectBrowser.s_LastInteractedProjectBrowser != null) - ProjectBrowser.s_LastInteractedProjectBrowser.SetSearch(searchFilter); - else - Debug.LogWarning("No Project Browser found to apply AssetBundle filter."); - } - - private IEnumerable GetAssetBundlesFromAssets(IEnumerable assets, bool isVariant, out bool isMixed) - { - var assetBundles = new HashSet(); - string lastAssetBundle = null; - isMixed = false; - - foreach (Object obj in assets) - { - if (obj is MonoScript) - continue; - - AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(obj)); - if (importer == null) - continue; - - string currentAssetBundle = isVariant ? importer.assetBundleVariant : importer.assetBundleName; - - if (lastAssetBundle != null && lastAssetBundle != currentAssetBundle) - isMixed = true; - lastAssetBundle = currentAssetBundle; - - if (!String.IsNullOrEmpty(currentAssetBundle)) - assetBundles.Add(currentAssetBundle); - } - - return assetBundles; - } - - private void SetAssetBundleForAssets(IEnumerable assets, string name, bool isVariant) - { - bool assetBundleNameChanged = false; - foreach (Object obj in assets) - { - if (obj is MonoScript) - continue; - - AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(obj)); - if (importer == null) - continue; - - if (isVariant) - importer.assetBundleVariant = name; - else - importer.assetBundleName = name; - - assetBundleNameChanged = true; - } - - if (assetBundleNameChanged) - { - EditorApplication.Internal_CallAssetBundleNameChanged(); - } - } - } -} diff --git a/Editor/Mono/Inspector/AssetStoreAssetInspector.cs b/Editor/Mono/Inspector/AssetStoreAssetInspector.cs deleted file mode 100644 index cc522230b1..0000000000 --- a/Editor/Mono/Inspector/AssetStoreAssetInspector.cs +++ /dev/null @@ -1,547 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - /** - * In addition to being an inspector for AssetStoreAssets this - * inspector works as the object that is selected when an - * asset store asset is selected ie. - * Selection.object == AssetStoreAssetInspector.Instance - * when asset store assets are selected. - */ - [CustomEditor(typeof(AssetStoreAssetInspector))] - internal class AssetStoreAssetInspector : Editor - { - static AssetStoreAssetInspector s_SharedAssetStoreAssetInspector; - - public static AssetStoreAssetInspector Instance - { - get - { - if (s_SharedAssetStoreAssetInspector == null) - { - s_SharedAssetStoreAssetInspector = ScriptableObject.CreateInstance(); - s_SharedAssetStoreAssetInspector.hideFlags = HideFlags.HideAndDontSave; - } - return s_SharedAssetStoreAssetInspector; - } - } - - class Styles - { - public GUIStyle link = new GUIStyle(EditorStyles.label); - public Styles() - { - link.normal.textColor = new Color(.26f, .51f, .75f, 1f); - } - } - - static Styles styles; - - bool packageInfoShown = true; - - // Payment info for all selected assets - internal static string s_PurchaseMessage = ""; - internal static string s_PaymentMethodCard = ""; - internal static string s_PaymentMethodExpire = ""; - internal static string s_PriceText = ""; - static GUIContent[] sStatusWheel; - - public static bool OfflineNoticeEnabled { get; set; } - - // Asset store payment availability - internal enum PaymentAvailability - { - BasketNotEmpty, - ServiceDisabled, - AnonymousUser, - Ok - } - - internal static PaymentAvailability m_PaymentAvailability; - internal static PaymentAvailability paymentAvailability - { - get - { - if (AssetStoreClient.LoggedOut()) - m_PaymentAvailability = PaymentAvailability.AnonymousUser; - return m_PaymentAvailability; - } - set - { - if (AssetStoreClient.LoggedOut()) - m_PaymentAvailability = PaymentAvailability.AnonymousUser; - else - m_PaymentAvailability = value; - } - } - - int lastAssetID; - - // Callback for curl to call - public void OnDownloadProgress(string id, string message, int bytes, int total) - { - AssetStoreAsset activeAsset = AssetStoreAssetSelection.GetFirstAsset(); - if (activeAsset == null) return; - AssetStoreAsset.PreviewInfo info = activeAsset.previewInfo; - if (info == null) return; - - if (activeAsset.packageID.ToString() != id) - return; - - if ((message == "downloading" || message == "connecting") && !OfflineNoticeEnabled) - { - info.downloadProgress = (float)bytes / (float)total; - } - else - { - info.downloadProgress = -1f; - } - Repaint(); - } - - public void Update() - { - // Repaint if asset has changed. - // This has to be done here because the .target is always set to - // this inspector when inspecting asset store assets. - AssetStoreAsset a = AssetStoreAssetSelection.GetFirstAsset(); - bool hasProgress = a != null && a.previewInfo != null && (a.previewInfo.buildProgress >= 0f || a.previewInfo.downloadProgress >= 0f); - if ((a == null && lastAssetID != 0) || - (a != null && lastAssetID != a.id) || - hasProgress) - { - lastAssetID = a == null ? 0 : a.id; - Repaint(); - } - - // Repaint when the main asset of a possibly downloaded bundle is ready for preview - if (a != null && a.previewBundle != null) - { - a.previewBundle.Unload(false); - a.previewBundle = null; - Repaint(); - } - } - - public override void OnInspectorGUI() - { - if (styles == null) - { - // Set the singleton in case the DrawEditors() has created this window - s_SharedAssetStoreAssetInspector = this; - styles = new Styles(); - } - - AssetStoreAsset activeAsset = AssetStoreAssetSelection.GetFirstAsset(); - AssetStoreAsset.PreviewInfo info = null; - if (activeAsset != null) - info = activeAsset.previewInfo; - - if (activeAsset != null) - target.name = string.Format("Asset Store: {0}", activeAsset.name); - else - target.name = "Asset Store"; - - EditorGUILayout.BeginVertical(); - - bool guiEnabled = GUI.enabled; - - GUI.enabled = activeAsset != null && activeAsset.packageID != 0; - - if (OfflineNoticeEnabled) - { - Color col = GUI.color; - GUI.color = Color.yellow; - GUILayout.Label("Network is offline"); - GUI.color = col; - } - - if (activeAsset != null) - { - string typeName = activeAsset.className == null ? "" : activeAsset.className.Split(new char[] {' '}, 2)[0]; - bool isPackage = activeAsset.id == -activeAsset.packageID; - if (isPackage) - typeName = "Package"; - if (activeAsset.HasLivePreview) - typeName = activeAsset.Preview.GetType().Name; - EditorGUILayout.LabelField("Type", typeName); - - if (isPackage) - { - packageInfoShown = true; - } - else - { - EditorGUILayout.Separator(); - packageInfoShown = EditorGUILayout.Foldout(packageInfoShown , "Part of package", true); - } - if (packageInfoShown) - { - EditorGUILayout.LabelField("Name", info == null ? "-" : info.packageName); - EditorGUILayout.LabelField("Version", info == null ? "-" : info.packageVersion); - string price = info == null ? "-" : (activeAsset.price != null && activeAsset.price != "" ? activeAsset.price : "free"); - EditorGUILayout.LabelField("Price", price); - string rating = info != null && info.packageRating >= 0 ? info.packageRating.ToString() + " of 5" : "-"; - EditorGUILayout.LabelField("Rating", rating); - EditorGUILayout.LabelField("Size", info == null ? "-" : intToSizeString(info.packageSize)); - string assetCount = info != null && info.packageAssetCount >= 0 ? info.packageAssetCount.ToString() : "-"; - EditorGUILayout.LabelField("Asset count", assetCount); - GUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel("Web page"); - bool hasPageUrl = info != null && info.packageShortUrl != null && info.packageShortUrl != ""; - bool guiBefore = GUI.enabled; - GUI.enabled = hasPageUrl; - - if (GUILayout.Button(hasPageUrl ? new GUIContent(info.packageShortUrl, "View in browser") : EditorGUIUtility.TempContent("-"), styles.link)) - { - Application.OpenURL(info.packageShortUrl); - } - if (GUI.enabled) - EditorGUIUtility.AddCursorRect(GUILayoutUtility.GetLastRect(), MouseCursor.Link); - GUI.enabled = guiBefore; - GUILayout.EndHorizontal(); - EditorGUILayout.LabelField("Publisher", info == null ? "-" : info.publisherName); - } - - if (activeAsset.id != 0) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - string actionLabel; - if (info != null && info.isDownloadable) - actionLabel = "Import package"; - else - actionLabel = "Buy for " + activeAsset.price; - - bool lastEnabled = GUI.enabled; - bool building = info != null && info.buildProgress >= 0; - bool downloading = info != null && info.downloadProgress >= 0; - if (building || downloading || info == null) - { - actionLabel = ""; - GUI.enabled = false; - } - - if (GUILayout.Button(actionLabel, GUILayout.Height(40), GUILayout.Width(120))) - { - if (info.isDownloadable) - ImportPackage(activeAsset); - else - InitiateBuySelected(); - GUIUtility.ExitGUI(); - } - - Rect r; - if (Event.current.type == EventType.Repaint) - { - r = GUILayoutUtility.GetLastRect(); - r.height -= 4; - float width = r.width; - r.width = r.height; - r.y += 2; - r.x += 2; - - if (building || downloading) - { - r.width = width - r.height - 4; - r.x += r.height; - EditorGUI.ProgressBar(r, - downloading ? info.downloadProgress : info.buildProgress, - downloading ? "Downloading" : "Building"); - } - } - - GUI.enabled = lastEnabled; - GUILayout.Space(4); - - if (GUILayout.Button("Open Asset Store", GUILayout.Height(40), GUILayout.Width(120))) - { - OpenItemInAssetStore(activeAsset); - GUIUtility.ExitGUI(); - } - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - } - GUILayout.FlexibleSpace(); - } - EditorWrapper editor = previewEditor; - if (editor != null && activeAsset != null && activeAsset.HasLivePreview) - editor.OnAssetStoreInspectorGUI(); - - GUI.enabled = guiEnabled; - - EditorGUILayout.EndVertical(); - } - - public static void OpenItemInAssetStore(AssetStoreAsset activeAsset) - { - if (activeAsset.id != 0) - { - AssetStore.Open(string.Format("content/{0}?assetID={1}", activeAsset.packageID, activeAsset.id)); - UsabilityAnalytics.Track(string.Format("/AssetStore/ViewInStore/{0}/{1}", activeAsset.packageID, activeAsset.id)); - } - } - - private static string intToSizeString(int inValue) - { - if (inValue < 0) - return "unknown"; - float val = (float)inValue; - string[] scale = new string[] { "TB", "GB", "MB", "KB", "Bytes" }; - int idx = scale.Length - 1; - while (val > 1000.0f && idx >= 0) - { - val /= 1000f; - idx--; - } - - if (idx < 0) - return ""; - - return string.Format("{0:#.##} {1}", val, scale[idx]); - } - - public override bool HasPreviewGUI() - { - return (target != null && AssetStoreAssetSelection.Count != 0); - } - - EditorWrapper m_PreviewEditor; - Object m_PreviewObject; - - public void OnEnable() - { - EditorApplication.update += Update; - AssetStoreUtils.RegisterDownloadDelegate(this); - } - - public void OnDisable() - { - EditorApplication.update -= Update; - if (m_PreviewEditor != null) - { - m_PreviewEditor.Dispose(); - m_PreviewEditor = null; - } - if (m_PreviewObject != null) - m_PreviewObject = null; - AssetStoreUtils.UnRegisterDownloadDelegate(this); - } - - private EditorWrapper previewEditor - { - get - { - AssetStoreAsset asset = AssetStoreAssetSelection.GetFirstAsset(); - if (asset == null) return null; - Object preview = asset.Preview; - if (preview == null) return null; - - if (preview != m_PreviewObject) - { - m_PreviewObject = preview; - - if (m_PreviewEditor != null) - m_PreviewEditor.Dispose(); - - m_PreviewEditor = EditorWrapper.Make(m_PreviewObject, EditorFeatures.PreviewGUI); - } - - return m_PreviewEditor; - } - } - - public override void OnPreviewSettings() - { - AssetStoreAsset asset = AssetStoreAssetSelection.GetFirstAsset(); - if (asset == null) return; - - EditorWrapper editor = previewEditor; - if (editor != null && asset.HasLivePreview) - editor.OnPreviewSettings(); - } - - public override string GetInfoString() - { - EditorWrapper editor = previewEditor; - AssetStoreAsset a = AssetStoreAssetSelection.GetFirstAsset(); - if (a == null) - return "No item selected"; - - if (editor != null && a.HasLivePreview) - return editor.GetInfoString(); - - return ""; - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (m_PreviewObject == null) return; - EditorWrapper editor = previewEditor; - - // Special handling for animation clips because they only have - // an interactive preview available which shows play button etc. - // The OnPreviewGUI is also used for the small icons in the top - // of the inspectors where buttons should not be rendered. - - if (editor != null && m_PreviewObject is AnimationClip) - editor.OnPreviewGUI(r, background); // currently renders nothing for animation clips - else - OnInteractivePreviewGUI(r, background); - } - - public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - EditorWrapper editor = previewEditor; - if (editor != null) - { - editor.OnInteractivePreviewGUI(r, background); - } - - // If the live preview is not available yes the show a spinner - AssetStoreAsset a = AssetStoreAssetSelection.GetFirstAsset(); - if (a != null && !a.HasLivePreview && !string.IsNullOrEmpty(a.dynamicPreviewURL)) - { - GUIContent c = StatusWheel; - r.y += (r.height - c.image.height) / 2f; - r.x += (r.width - c.image.width) / 2f; - GUI.Label(r, StatusWheel); - Repaint(); - } - } - - static GUIContent StatusWheel - { - get - { - if (sStatusWheel == null) - { - sStatusWheel = new GUIContent[12]; - for (int i = 0; i < 12; i++) - { - GUIContent gc = new GUIContent(); - gc.image = EditorGUIUtility.LoadIcon("WaitSpin" + i.ToString("00")) as Texture2D; - sStatusWheel[i] = gc; - } - } - int frame = (int)Mathf.Repeat(Time.realtimeSinceStartup * 10, 11.99f); - return sStatusWheel[frame]; - } - } - - public override GUIContent GetPreviewTitle() - { - return GUIContent.Temp("Asset Store Preview"); - } - - /** - * Initiate a purchase of the selected package from the asset store. - * The package will be the one that contains the currently selected asset. - * - * Since not all users may have allowed for single click purchases this can result - * in two scenarios: - * 1. single click allowed and a native purchase acknowledgement dialog appears to - * finalize the purchase. - * 2. single click is not allowed and the package is put to an asset store basket. - * Then the asset store window is displayed with the basket open. - */ - void InitiateBuySelected(bool firstAttempt) - { - //Debug.Log("payavail " + paymentAvailability.ToString()); - // Ask the asset store if the use has allowed single click payments - AssetStoreAsset asset = AssetStoreAssetSelection.GetFirstAsset(); - if (asset == null) - { - EditorUtility.DisplayDialog("No asset selected", "Please select asset before buying a package", "ok"); - } - else if (paymentAvailability == PaymentAvailability.AnonymousUser) - { - // Maybe the asset store window did a login already and we have a session key - // then we just need to fetch the new info - if (AssetStoreClient.LoggedIn()) - { - AssetStoreAssetSelection.RefreshFromServer(delegate() { - InitiateBuySelected(false); - }); - } - else if (firstAttempt) LoginAndInitiateBuySelected(); - } - else if (paymentAvailability == PaymentAvailability.ServiceDisabled) - { - // Use the asset store window to complete the purchase since single click is not possible - if (asset.previewInfo == null) return; - AssetStore.Open(string.Format("content/{0}/directpurchase", asset.packageID)); - } - else if (paymentAvailability == PaymentAvailability.BasketNotEmpty) - { - // Use the asset store window to complete the purchase since there is already \ - // something in the users basket - if (asset.previewInfo == null) return; - - // Maybe the basket has been emptied and this is a retry by the user - if (firstAttempt) - AssetStoreAssetSelection.RefreshFromServer(delegate() { - InitiateBuySelected(false); - }); - else - AssetStore.Open(string.Format("content/{0}/basketpurchase", asset.packageID)); - } - else - { - // Show single click window - AssetStoreInstaBuyWindow.ShowAssetStoreInstaBuyWindow(asset, - AssetStoreAssetInspector.s_PurchaseMessage, - AssetStoreAssetInspector.s_PaymentMethodCard, - AssetStoreAssetInspector.s_PaymentMethodExpire, - AssetStoreAssetInspector.s_PriceText - ); - } - } - - void InitiateBuySelected() - { - InitiateBuySelected(true); - } - - void LoginAndInitiateBuySelected() - { - AssetStoreLoginWindow.Login("Please login to the Asset Store in order to get payment information about the package.", - delegate(string errorMessage) { - if (errorMessage != null) - return; // aborted - - AssetStoreAssetSelection.RefreshFromServer(delegate() { - InitiateBuySelected(false); - }); - }); - } - - void ImportPackage(AssetStoreAsset asset) - { - if (paymentAvailability == PaymentAvailability.AnonymousUser) - LoginAndImport(asset); - else - AssetStoreInstaBuyWindow.ShowAssetStoreInstaBuyWindowBuilding(asset); - } - - void LoginAndImport(AssetStoreAsset asset) - { - AssetStoreLoginWindow.Login("Please login to the Asset Store in order to get download information for the package.", - delegate(string errorMessage) { - if (errorMessage != null) - return; // aborted - - AssetStoreAssetSelection.RefreshFromServer(delegate() { - AssetStoreInstaBuyWindow.ShowAssetStoreInstaBuyWindowBuilding(asset); - }); - }); - } - } // Inspector class -} // UnityEditor namespace diff --git a/Editor/Mono/Inspector/AudioChorusFilterEditor.cs b/Editor/Mono/Inspector/AudioChorusFilterEditor.cs deleted file mode 100644 index b43e4085df..0000000000 --- a/Editor/Mono/Inspector/AudioChorusFilterEditor.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioChorusFilter))] - class AudioChorusFilterEditor : Editor - { - } -} diff --git a/Editor/Mono/Inspector/AudioClipInspector.cs b/Editor/Mono/Inspector/AudioClipInspector.cs deleted file mode 100644 index 1b4a6e491b..0000000000 --- a/Editor/Mono/Inspector/AudioClipInspector.cs +++ /dev/null @@ -1,348 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioClip))] - [CanEditMultipleObjects] - internal class AudioClipInspector : Editor - { - private PreviewRenderUtility m_PreviewUtility; - - // Any number of AudioClip inspectors can be docked in addition to the object browser, and they are all showing and modifying the same shared state. - static AudioClipInspector m_PlayingInspector; - static AudioClip m_PlayingClip; - static bool playing { get { return m_PlayingClip != null && AudioUtil.IsClipPlaying(m_PlayingClip); } } - static bool m_bAutoPlay; - static bool m_bLoop; - - Vector2 m_Position = Vector2.zero; - Rect m_wantedRect; - - static GUIStyle s_PreButton; - - static GUIContent[] s_PlayIcons = {null, null}; - static GUIContent[] s_AutoPlayIcons = {null, null}; - static GUIContent[] s_LoopIcons = {null, null}; - - static Texture2D s_DefaultIcon; - - override public void OnInspectorGUI() - { - // Override with inspector that doesn't show anything - } - - static void Init() - { - if (s_PreButton != null) - return; - s_PreButton = "preButton"; - - m_bAutoPlay = EditorPrefs.GetBool("AutoPlayAudio", false); - - s_AutoPlayIcons[0] = EditorGUIUtility.TrIconContent("preAudioAutoPlayOff", "Turn Auto Play on"); - s_AutoPlayIcons[1] = EditorGUIUtility.TrIconContent("preAudioAutoPlayOn", "Turn Auto Play off"); - s_PlayIcons[0] = EditorGUIUtility.TrIconContent("preAudioPlayOff", "Play"); - s_PlayIcons[1] = EditorGUIUtility.TrIconContent("preAudioPlayOn", "Stop"); - s_LoopIcons[0] = EditorGUIUtility.TrIconContent("preAudioLoopOff", "Loop on"); - s_LoopIcons[1] = EditorGUIUtility.TrIconContent("preAudioLoopOn", "Loop off"); - - s_DefaultIcon = EditorGUIUtility.LoadIcon("Profiler.Audio"); - } - - public void OnDisable() - { - // This check is necessary because the order of OnEnable/OnDisable varies depending on whether the inspector is embedded in the project browser or object selector. - if (m_PlayingInspector == this) - { - AudioUtil.StopAllClips(); - m_PlayingClip = null; - } - - EditorPrefs.SetBool("AutoPlayAudio", m_bAutoPlay); - } - - public void OnEnable() - { - AudioUtil.StopAllClips(); - m_PlayingClip = null; - m_PlayingInspector = this; - - m_bAutoPlay = EditorPrefs.GetBool("AutoPlayAudio", false); - } - - public void OnDestroy() - { - if (m_PreviewUtility != null) - { - m_PreviewUtility.Cleanup(); - m_PreviewUtility = null; - } - } - - public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) - { - AudioClip clip = target as AudioClip; - - AssetImporter importer = AssetImporter.GetAtPath(assetPath); - AudioImporter audioImporter = importer as AudioImporter; - - if (audioImporter == null || !ShaderUtil.hardwareSupportsRectRenderTexture) - return null; - - if (m_PreviewUtility == null) - m_PreviewUtility = new PreviewRenderUtility(); - - m_PreviewUtility.BeginStaticPreview(new Rect(0, 0, width, height)); - - // 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 - // the higher resolution into account when drawing into the offscreen, otherwise only the upper-left quarter of the preview texture will be drawn. - DoRenderPreview(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); - - return m_PreviewUtility.EndStaticPreview(); - } - - public override bool HasPreviewGUI() - { - return (targets != null); - } - - public override void OnPreviewSettings() - { - if (s_DefaultIcon == null) Init(); - - AudioClip clip = target as AudioClip; - - using (new EditorGUI.DisabledScope(AudioUtil.IsMovieAudio(clip))) - { - bool isEditingMultipleObjects = targets.Length > 1; - - using (new EditorGUI.DisabledScope(isEditingMultipleObjects)) - { - bool oldAutoPlay = isEditingMultipleObjects ? false : m_bAutoPlay; - bool newAutoPlay = PreviewGUI.CycleButton(oldAutoPlay ? 1 : 0, s_AutoPlayIcons) != 0; - if (oldAutoPlay != newAutoPlay) - { - m_bAutoPlay = newAutoPlay; - InspectorWindow.RepaintAllInspectors(); - } - - bool oldLoop = isEditingMultipleObjects ? false : m_bLoop; - bool newLoop = PreviewGUI.CycleButton(oldLoop ? 1 : 0, s_LoopIcons) != 0; - if (oldLoop != newLoop) - { - m_bLoop = newLoop; - if (playing) - AudioUtil.LoopClip(clip, newLoop); - InspectorWindow.RepaintAllInspectors(); - } - } - - using (new EditorGUI.DisabledScope(isEditingMultipleObjects && !playing && m_PlayingInspector != this)) - { - bool curPlaying = m_PlayingInspector == this && playing; - bool newPlaying = PreviewGUI.CycleButton(curPlaying ? 1 : 0, s_PlayIcons) != 0; - - if (newPlaying != curPlaying) - { - AudioUtil.StopAllClips(); - - if (newPlaying) - { - AudioUtil.PlayClip(clip, 0, m_bLoop); - m_PlayingClip = clip; - m_PlayingInspector = this; - } - } - } - } - } - - // 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. - private void DoRenderPreview(AudioClip clip, AudioImporter audioImporter, Rect wantedRect, float scaleFactor) - { - scaleFactor *= 0.95f; // Reduce amplitude slightly to make highly compressed signals fit. - float[] minMaxData = (audioImporter == null) ? null : AudioUtil.GetMinMaxData(audioImporter); - int numChannels = clip.channels; - int numSamples = (minMaxData == null) ? 0 : (minMaxData.Length / (2 * numChannels)); - float h = (float)wantedRect.height / (float)numChannels; - for (int channel = 0; channel < numChannels; channel++) - { - Rect channelRect = new Rect(wantedRect.x, wantedRect.y + h * channel, wantedRect.width, h); - Color curveColor = new Color(1.0f, 140.0f / 255.0f, 0.0f, 1.0f); - - AudioCurveRendering.DrawMinMaxFilledCurve( - channelRect, - delegate(float x, out Color col, out float minValue, out float maxValue) - { - col = curveColor; - if (numSamples <= 0) - { - minValue = 0.0f; - maxValue = 0.0f; - } - else - { - float p = Mathf.Clamp(x * (numSamples - 2), 0.0f, numSamples - 2); - int i = (int)Mathf.Floor(p); - int offset1 = (i * numChannels + channel) * 2; - int offset2 = offset1 + numChannels * 2; - minValue = Mathf.Min(minMaxData[offset1 + 1], minMaxData[offset2 + 1]) * scaleFactor; - maxValue = Mathf.Max(minMaxData[offset1 + 0], minMaxData[offset2 + 0]) * scaleFactor; - if (minValue > maxValue) { float tmp = minValue; minValue = maxValue; maxValue = tmp; } - } - } - ); - } - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (s_DefaultIcon == null) Init(); - - AudioClip clip = target as AudioClip; - - Event evt = Event.current; - if (evt.type != EventType.Repaint && evt.type != EventType.Layout && evt.type != EventType.Used) - { - int px2sample = (AudioUtil.GetSampleCount(clip) / (int)r.width); - - switch (evt.type) - { - case EventType.MouseDrag: - case EventType.MouseDown: - { - if (r.Contains(evt.mousePosition) && !AudioUtil.IsMovieAudio(clip)) - { - if (m_PlayingClip != clip || !AudioUtil.IsClipPlaying(clip)) - { - AudioUtil.StopAllClips(); - AudioUtil.PlayClip(clip, 0, m_bLoop); - m_PlayingClip = clip; - m_PlayingInspector = this; - } - AudioUtil.SetClipSamplePosition(clip, px2sample * (int)evt.mousePosition.x); - evt.Use(); - } - } - break; - } - return; - } - - if (Event.current.type == EventType.Repaint) - background.Draw(r, false, false, false, false); - - int c = AudioUtil.GetChannelCount(clip); - m_wantedRect = new Rect(r.x, r.y , r.width, r.height); - float sec2px = ((float)m_wantedRect.width / clip.length); - - bool previewAble = AudioUtil.HasPreview(clip) || !(AudioUtil.IsTrackerFile(clip) || AudioUtil.IsMovieAudio(clip)); - if (!previewAble) - { - float labelY = (r.height > 150) ? r.y + (r.height / 2) - 10 : r.y + (r.height / 2) - 25; - if (r.width > 64) - { - if (AudioUtil.IsTrackerFile(clip)) - { - EditorGUI.DropShadowLabel(new Rect(r.x, labelY, r.width, 20), string.Format("Module file with " + AudioUtil.GetMusicChannelCount(clip) + " channels.")); - } - else if (AudioUtil.IsMovieAudio(clip)) - { - if (r.width > 450) - EditorGUI.DropShadowLabel(new Rect(r.x, labelY, r.width, 20), "Audio is attached to a movie. To audition the sound, play the movie."); - else - { - EditorGUI.DropShadowLabel(new Rect(r.x, labelY, r.width, 20), "Audio is attached to a movie."); - EditorGUI.DropShadowLabel(new Rect(r.x, labelY + 10, r.width, 20), "To audition the sound, play the movie."); - } - } - else - EditorGUI.DropShadowLabel(new Rect(r.x, labelY, r.width, 20), "Can not show PCM data for this file"); - } - - if (m_PlayingInspector == this && m_PlayingClip == clip) - { - float t = AudioUtil.GetClipPosition(clip); - - System.TimeSpan ts = new System.TimeSpan(0, 0, 0, 0, (int)(t * 1000.0f)); - - EditorGUI.DropShadowLabel(new Rect(m_wantedRect.x, m_wantedRect.y, m_wantedRect.width, 20), string.Format("Playing - {0:00}:{1:00}.{2:000}", ts.Minutes, ts.Seconds, ts.Milliseconds)); - } - } - else - { - PreviewGUI.BeginScrollView(m_wantedRect, m_Position, m_wantedRect, "PreHorizontalScrollbar", "PreHorizontalScrollbarThumb"); - - if (Event.current.type == EventType.Repaint) - { - DoRenderPreview(clip, AudioUtil.GetImporterFromClip(clip), m_wantedRect, 1.0f); - } - - for (int i = 0; i < c; ++i) - { - if (c > 1 && r.width > 64) - { - var labelRect = new Rect(m_wantedRect.x + 5, m_wantedRect.y + (m_wantedRect.height / c) * i, 30, 20); - EditorGUI.DropShadowLabel(labelRect, "ch " + (i + 1).ToString()); - } - } - - if (m_PlayingInspector == this && m_PlayingClip == clip) - { - float t = AudioUtil.GetClipPosition(clip); - - System.TimeSpan ts = new System.TimeSpan(0, 0, 0, 0, (int)(t * 1000.0f)); - - GUI.DrawTexture(new Rect(m_wantedRect.x + (int)(sec2px * t), m_wantedRect.y, 2, m_wantedRect.height), EditorGUIUtility.whiteTexture); - if (r.width > 64) - EditorGUI.DropShadowLabel(new Rect(m_wantedRect.x, m_wantedRect.y, m_wantedRect.width, 20), string.Format("{0:00}:{1:00}.{2:000}", ts.Minutes, ts.Seconds, ts.Milliseconds)); - else - EditorGUI.DropShadowLabel(new Rect(m_wantedRect.x, m_wantedRect.y, m_wantedRect.width, 20), string.Format("{0:00}:{1:00}", ts.Minutes, ts.Seconds)); - } - - - PreviewGUI.EndScrollView(); - } - - - // autoplay start? - if (m_bAutoPlay && m_PlayingClip != clip && m_PlayingInspector == this) - { - AudioUtil.StopAllClips(); - AudioUtil.PlayClip(clip, 0, m_bLoop); - m_PlayingClip = clip; - m_PlayingInspector = this; - } - - // force update GUI - if (playing) - GUIView.current.Repaint(); - } - - public override string GetInfoString() - { - AudioClip clip = target as AudioClip; - int c = AudioUtil.GetChannelCount(clip); - string ch = c == 1 ? "Mono" : c == 2 ? "Stereo" : (c - 1).ToString() + ".1"; - AudioCompressionFormat platformFormat = AudioUtil.GetTargetPlatformSoundCompressionFormat(clip); - AudioCompressionFormat editorFormat = AudioUtil.GetSoundCompressionFormat(clip); - string s = platformFormat.ToString(); - if (platformFormat != editorFormat) - s += " (" + editorFormat.ToString() + " in editor" + ")"; - s += ", " + AudioUtil.GetFrequency(clip) + " Hz, " + ch + ", "; - - System.TimeSpan ts = new System.TimeSpan(0, 0, 0, 0, (int)AudioUtil.GetDuration(clip)); - - if ((uint)AudioUtil.GetDuration(clip) == 0xffffffff) - s += "Unlimited"; - else - s += string.Format("{0:00}:{1:00}.{2:000}", ts.Minutes, ts.Seconds, ts.Milliseconds); - - return s; - } - } -} diff --git a/Editor/Mono/Inspector/AudioDistortionFilterInspector.cs b/Editor/Mono/Inspector/AudioDistortionFilterInspector.cs deleted file mode 100644 index f3e0153897..0000000000 --- a/Editor/Mono/Inspector/AudioDistortionFilterInspector.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioDistortionFilter))] - class AudioDistortionFilterEditor : Editor - { - } -} diff --git a/Editor/Mono/Inspector/AudioEchoFilterInspector.cs b/Editor/Mono/Inspector/AudioEchoFilterInspector.cs deleted file mode 100644 index 0d4bde1e24..0000000000 --- a/Editor/Mono/Inspector/AudioEchoFilterInspector.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioEchoFilter))] - class AudioEchoFilterEditor : Editor - { - } -} diff --git a/Editor/Mono/Inspector/AudioExtensionEditor.cs b/Editor/Mono/Inspector/AudioExtensionEditor.cs deleted file mode 100644 index b64191f52e..0000000000 --- a/Editor/Mono/Inspector/AudioExtensionEditor.cs +++ /dev/null @@ -1,130 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.Collections.Generic; -using System.Linq; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AudioExtensionEditor : ScriptableObject - { - private bool foundAllExtensionProperties = false; - - public struct ExtensionPropertyInfo - { - public ExtensionPropertyInfo(string nameIn, float defaultValueIn) - { - propertyName = new PropertyName(nameIn); - defaultValue = defaultValueIn; - serializedProperty = null; - } - - public PropertyName propertyName; - public float defaultValue; - public SerializedProperty serializedProperty; - } -#pragma warning disable 649 - protected ExtensionPropertyInfo[] m_ExtensionProperties; - - public virtual void InitExtensionPropertyInfo() {} - protected virtual int GetNumSerializedExtensionProperties(Object obj) { return 0; } - - public void OnEnable() - { - InitExtensionPropertyInfo(); - } - - public int GetNumExtensionProperties() - { - return m_ExtensionProperties.Length; - } - - public PropertyName GetExtensionPropertyName(int index) - { - return m_ExtensionProperties[index].propertyName; - } - - public float GetExtensionPropertyDefaultValue(int index) - { - return m_ExtensionProperties[index].defaultValue; - } - - public bool FindAudioExtensionProperties(SerializedObject serializedObject) - { - SerializedProperty extensionPropertyValues = null; - - if (serializedObject != null) - extensionPropertyValues = serializedObject.FindProperty("m_ExtensionPropertyValues"); - - if (extensionPropertyValues == null) - { - foundAllExtensionProperties = false; - return false; - } - - int minNumSerializedExtensionProperties = extensionPropertyValues.arraySize; - if (extensionPropertyValues.hasMultipleDifferentValues) - minNumSerializedExtensionProperties = GetMinNumSerializedExtensionProperties(serializedObject); - - if ((extensionPropertyValues == null) || (minNumSerializedExtensionProperties == 0)) - { - foundAllExtensionProperties = false; - return false; - } - - if (!foundAllExtensionProperties && (serializedObject != null)) - { - int numPropertiesFound = 0; - for (int sourceIndex = 0; sourceIndex < minNumSerializedExtensionProperties; sourceIndex++) - { - SerializedProperty extensionPropertyValue = extensionPropertyValues.GetArrayElementAtIndex(sourceIndex); - - if (extensionPropertyValue == null) - continue; - - SerializedProperty propertyName = extensionPropertyValue.FindPropertyRelative("propertyName"); - for (int extensionIndex = 0; extensionIndex < m_ExtensionProperties.Length; extensionIndex++) - { - if ((m_ExtensionProperties[extensionIndex].propertyName == propertyName.stringValue) && !propertyName.hasMultipleDifferentValues) - { - m_ExtensionProperties[extensionIndex].serializedProperty = extensionPropertyValue.FindPropertyRelative("propertyValue"); - numPropertiesFound++; - } - } - } - - foundAllExtensionProperties = (numPropertiesFound == m_ExtensionProperties.Length) ? true : false; - } - - return foundAllExtensionProperties; - } - - protected static void PropertyFieldAsBool(SerializedProperty property, GUIContent title) - { - Rect rect = EditorGUILayout.GetControlRect(); - title = EditorGUI.BeginProperty(rect, title, property); - EditorGUI.BeginChangeCheck(); - bool newValue = EditorGUI.Toggle(rect, title, property.floatValue > 0.0f ? true : false); - if (EditorGUI.EndChangeCheck()) - { - property.floatValue = newValue ? 1.0f : 0.0f; - } - EditorGUI.EndProperty(); - } - - private int GetMinNumSerializedExtensionProperties(SerializedObject serializedObject) - { - Object[] targets = serializedObject.targetObjects; - int minNumSerializedExtensionProperties = (targets.Length > 0) ? int.MaxValue : 0; - - for (int i = 0; i < targets.Length; i++) - minNumSerializedExtensionProperties = Math.Min(minNumSerializedExtensionProperties, GetNumSerializedExtensionProperties(targets[i])); - - return minNumSerializedExtensionProperties; - } - } -} diff --git a/Editor/Mono/Inspector/AudioFilterGUI.cs b/Editor/Mono/Inspector/AudioFilterGUI.cs deleted file mode 100644 index 1a07d13b84..0000000000 --- a/Editor/Mono/Inspector/AudioFilterGUI.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal class AudioFilterGUI - { - private EditorGUI.VUMeter.SmoothingData[] dataOut; - - public void DrawAudioFilterGUI(MonoBehaviour behaviour) - { - int channelCount = AudioUtil.GetCustomFilterChannelCount(behaviour); - - if (channelCount > 0) - { - if (dataOut == null) - { - dataOut = new EditorGUI.VUMeter.SmoothingData[channelCount]; - } - - double ms = (double)AudioUtil.GetCustomFilterProcessTime(behaviour) / 1000000.0; // ms - float limit = (float)ms / ((float)AudioSettings.outputSampleRate / 1024.0f / (float)channelCount); - - GUILayout.BeginHorizontal(); - GUILayout.Space(13); - GUILayout.BeginVertical(); - EditorGUILayout.Space(); - for (int c = 0; c < channelCount; ++c) - { - EditorGUILayout.VUMeterHorizontal(AudioUtil.GetCustomFilterMaxOut(behaviour, c), ref dataOut[c], GUILayout.MinWidth(50), GUILayout.Height(5)); - } - GUILayout.EndVertical(); - Color old = GUI.color; - GUI.color = new Color(limit, 1.0f - limit, 0.0f, 1.0f); - GUILayout.Box(string.Format("{0:00.00}ms", ms), GUILayout.MinWidth(40), GUILayout.Height(20)); - GUI.color = old; - - GUILayout.EndHorizontal(); - EditorGUILayout.Space(); - - // force repaint - GUIView.current.Repaint(); - } - } - } -} diff --git a/Editor/Mono/Inspector/AudioHighPassFIlterInspector.cs b/Editor/Mono/Inspector/AudioHighPassFIlterInspector.cs deleted file mode 100644 index abd6afede8..0000000000 --- a/Editor/Mono/Inspector/AudioHighPassFIlterInspector.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioHighPassFilter))] - class AudioHighPassFilterEditor : Editor - { - } -} diff --git a/Editor/Mono/Inspector/AudioListenerExtensionEditor.cs b/Editor/Mono/Inspector/AudioListenerExtensionEditor.cs deleted file mode 100644 index bba46d1ae1..0000000000 --- a/Editor/Mono/Inspector/AudioListenerExtensionEditor.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class AudioListenerExtensionEditor : AudioExtensionEditor - { - public virtual void OnAudioListenerGUI() {} - - protected override int GetNumSerializedExtensionProperties(Object obj) - { - AudioListener listener = obj as AudioListener; - int numSerializedExtensionProperties = listener ? listener.GetNumExtensionProperties() : 0; - - return numSerializedExtensionProperties; - } - } -} diff --git a/Editor/Mono/Inspector/AudioListenerInspector.cs b/Editor/Mono/Inspector/AudioListenerInspector.cs deleted file mode 100644 index afa101e99b..0000000000 --- a/Editor/Mono/Inspector/AudioListenerInspector.cs +++ /dev/null @@ -1,206 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioListener))] - [CanEditMultipleObjects] - class AudioListenerInspector : Editor - { - private AudioListenerExtensionEditor m_SpatializerEditor = null; - private bool m_AddSpatializerExtension = false; - private bool m_AddSpatializerExtensionMixedValues = false; - - private GUIContent addSpatializerExtensionLabel = EditorGUIUtility.TrTextContent("Override Spatializer Settings", "Override the Google spatializer's default settings."); - - void OnEnable() - { - Undo.undoRedoPerformed += UndoRedoPerformed; - - UpdateSpatializerExtensionMixedValues(); - if (m_AddSpatializerExtension) - CreateExtensionEditors(); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - bool allowExtensionEditing = (m_AddSpatializerExtension && !m_AddSpatializerExtensionMixedValues) || !serializedObject.isEditingMultipleObjects; - if (AudioExtensionManager.IsListenerSpatializerExtensionRegistered() && allowExtensionEditing) - { - EditorGUI.showMixedValue = m_AddSpatializerExtensionMixedValues; - bool addSpatializerExtensionNew = EditorGUILayout.Toggle(addSpatializerExtensionLabel, m_AddSpatializerExtension); - EditorGUI.showMixedValue = false; - - bool showExtensionProperties = false; - if (m_AddSpatializerExtension != addSpatializerExtensionNew) - { - m_AddSpatializerExtension = addSpatializerExtensionNew; - if (m_AddSpatializerExtension) - { - CreateExtensionEditors(); - - if (m_SpatializerEditor != null) - showExtensionProperties = m_SpatializerEditor.FindAudioExtensionProperties(serializedObject); - } - else - { - ClearExtensionProperties(); - DestroyExtensionEditors(); - showExtensionProperties = false; - } - } - else if (m_SpatializerEditor != null) - { - showExtensionProperties = m_SpatializerEditor.FindAudioExtensionProperties(serializedObject); - if (!showExtensionProperties) - { - m_AddSpatializerExtension = false; - ClearExtensionProperties(); - DestroyExtensionEditors(); - } - } - - if ((m_SpatializerEditor != null) && showExtensionProperties) - { - EditorGUI.indentLevel++; - m_SpatializerEditor.OnAudioListenerGUI(); - EditorGUI.indentLevel--; - - // Update AudioSourceExtension properties, if we are currently playing in Editor. - for (int i = 0; i < targets.Length; i++) - { - AudioListener listener = targets[i] as AudioListener; - if (listener != null) - { - AudioListenerExtension extension = AudioExtensionManager.GetSpatializerExtension(listener); - if (extension != null) - { - string extensionName = AudioExtensionManager.GetListenerSpatializerExtensionType().Name; - for (int j = 0; j < m_SpatializerEditor.GetNumExtensionProperties(); j++) - { - PropertyName propertyName = m_SpatializerEditor.GetExtensionPropertyName(j); - float value = 0.0f; - if (listener.ReadExtensionProperty(extensionName, propertyName, ref value)) - { - extension.WriteExtensionProperty(propertyName, value); - } - } - } - } - } - } - } - - serializedObject.ApplyModifiedProperties(); - } - - void OnDisable() - { - DestroyExtensionEditors(); - - Undo.undoRedoPerformed -= UndoRedoPerformed; - } - - private void UpdateSpatializerExtensionMixedValues() - { - m_AddSpatializerExtension = false; - - int numTargetsWithSpatializerExtensions = 0; - for (int i = 0; i < targets.Length; i++) - { - AudioListener listener = targets[i] as AudioListener; - if (listener != null) - { - System.Type spatializerExtensionType = AudioExtensionManager.GetListenerSpatializerExtensionType(); - if ((spatializerExtensionType != null) && (listener.GetNumExtensionPropertiesForThisExtension(spatializerExtensionType.Name) > 0)) - { - m_AddSpatializerExtension = true; - numTargetsWithSpatializerExtensions++; - } - } - } - - m_AddSpatializerExtensionMixedValues = ((numTargetsWithSpatializerExtensions == 0) || (numTargetsWithSpatializerExtensions == targets.Length)) ? false : true; - if (m_AddSpatializerExtensionMixedValues) - m_AddSpatializerExtension = false; - } - - // Created editors for all the enabled extensions of this AudioSource. - private void CreateExtensionEditors() - { - if (m_SpatializerEditor != null) - DestroyExtensionEditors(); - - System.Type spatializerEditorType = AudioExtensionManager.GetListenerSpatializerExtensionEditorType(); - m_SpatializerEditor = ScriptableObject.CreateInstance(spatializerEditorType) as AudioListenerExtensionEditor; - - if (m_SpatializerEditor != null) - { - for (int i = 0; i < targets.Length; i++) - { - AudioListener listener = targets[i] as AudioListener; - if (listener != null) - { - Undo.RecordObject(listener, "Add AudioListener extension properties"); - PropertyName extensionName = AudioExtensionManager.GetListenerSpatializerExtensionName(); - for (int j = 0; j < m_SpatializerEditor.GetNumExtensionProperties(); j++) - { - PropertyName propertyName = m_SpatializerEditor.GetExtensionPropertyName(j); - float value = 0.0f; - - // If the AudioListener is missing an extension property, then create it now. - if (!listener.ReadExtensionProperty(extensionName, propertyName, ref value)) - { - value = m_SpatializerEditor.GetExtensionPropertyDefaultValue(j); - listener.WriteExtensionProperty(AudioExtensionManager.GetSpatializerName(), extensionName, propertyName, value); - } - } - } - } - } - - m_AddSpatializerExtensionMixedValues = false; - } - - private void DestroyExtensionEditors() - { - DestroyImmediate(m_SpatializerEditor); - m_SpatializerEditor = null; - } - - private void ClearExtensionProperties() - { - for (int i = 0; i < targets.Length; i++) - { - AudioListener listener = targets[i] as AudioListener; - if (listener != null) - { - Undo.RecordObject(listener, "Remove AudioListener extension properties"); - listener.ClearExtensionProperties(AudioExtensionManager.GetListenerSpatializerExtensionName()); - } - } - - m_AddSpatializerExtensionMixedValues = false; - } - - private void UndoRedoPerformed() - { - DestroyExtensionEditors(); - - UpdateSpatializerExtensionMixedValues(); - if (!m_AddSpatializerExtension && !m_AddSpatializerExtensionMixedValues) - ClearExtensionProperties(); - - if (m_AddSpatializerExtension) - CreateExtensionEditors(); - - Repaint(); - } - } -} diff --git a/Editor/Mono/Inspector/AudioLowPassFilterInspector.cs b/Editor/Mono/Inspector/AudioLowPassFilterInspector.cs deleted file mode 100644 index d480a47052..0000000000 --- a/Editor/Mono/Inspector/AudioLowPassFilterInspector.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioLowPassFilter))] - [CanEditMultipleObjects] - internal class AudioLowPassFilterInspector : Editor - { - SerializedProperty m_LowpassResonanceQ; - SerializedProperty m_LowpassLevelCustomCurve; - - void OnEnable() - { - m_LowpassResonanceQ = serializedObject.FindProperty("m_LowpassResonanceQ"); - m_LowpassLevelCustomCurve = serializedObject.FindProperty("lowpassLevelCustomCurve"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - AudioSourceInspector.AnimProp( - EditorGUIUtility.TrTextContent("Cutoff Frequency"), - m_LowpassLevelCustomCurve, - 0.0f, AudioSourceInspector.kMaxCutoffFrequency, true); - - EditorGUILayout.PropertyField(m_LowpassResonanceQ); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/AudioManagerInspector.cs b/Editor/Mono/Inspector/AudioManagerInspector.cs deleted file mode 100644 index 4ff57c5a0d..0000000000 --- a/Editor/Mono/Inspector/AudioManagerInspector.cs +++ /dev/null @@ -1,133 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -using System.Collections.Generic; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioManager))] - internal class AudioManagerInspector : ProjectSettingsBaseEditor - { - private class Styles - { - public static GUIContent Volume = EditorGUIUtility.TrTextContent("Global Volume", "Initial volume multiplier (AudioListener.volume)"); - public static GUIContent RolloffScale = EditorGUIUtility.TrTextContent("Volume Rolloff Scale", "Global volume rolloff multiplier (applies only to logarithmic volume curves)."); - public static GUIContent DopplerFactor = EditorGUIUtility.TrTextContent("Doppler Factor", "Global Doppler speed multiplier for sounds in motion."); - 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."); - 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."); - public static GUIContent DSPBufferSize = EditorGUIUtility.TrTextContent("DSP Buffer Size", "Length of mixing buffer. This determines the output latency of the game."); - 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."); - public static GUIContent RealVoiceCount = EditorGUIUtility.TrTextContent("Max Real Voices", "Maximum number of actual simultanously playing sounds."); - public static GUIContent SpatializerPlugin = EditorGUIUtility.TrTextContent("Spatializer Plugin", "Native audio plugin performing spatialized filtering of 3D sources."); - public static GUIContent AmbisonicDecoderPlugin = EditorGUIUtility.TrTextContent("Ambisonic Decoder Plugin", "Native audio plugin performing ambisonic-to-binaural filtering of sources."); - 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."); - 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."); - } - - private SerializedProperty m_Volume; - private SerializedProperty m_RolloffScale; - private SerializedProperty m_DopplerFactor; - private SerializedProperty m_DefaultSpeakerMode; - private SerializedProperty m_SampleRate; - private SerializedProperty m_DSPBufferSize; - private SerializedProperty m_VirtualVoiceCount; - private SerializedProperty m_RealVoiceCount; - private SerializedProperty m_SpatializerPlugin; - private SerializedProperty m_AmbisonicDecoderPlugin; - private SerializedProperty m_DisableAudio; - private SerializedProperty m_VirtualizeEffects; - - private void OnEnable() - { - m_Volume = serializedObject.FindProperty("m_Volume"); - m_RolloffScale = serializedObject.FindProperty("Rolloff Scale"); - m_DopplerFactor = serializedObject.FindProperty("Doppler Factor"); - m_DefaultSpeakerMode = serializedObject.FindProperty("Default Speaker Mode"); - m_SampleRate = serializedObject.FindProperty("m_SampleRate"); - m_DSPBufferSize = serializedObject.FindProperty("m_DSPBufferSize"); - m_VirtualVoiceCount = serializedObject.FindProperty("m_VirtualVoiceCount"); - m_RealVoiceCount = serializedObject.FindProperty("m_RealVoiceCount"); - m_SpatializerPlugin = serializedObject.FindProperty("m_SpatializerPlugin"); - m_AmbisonicDecoderPlugin = serializedObject.FindProperty("m_AmbisonicDecoderPlugin"); - m_DisableAudio = serializedObject.FindProperty("m_DisableAudio"); - m_VirtualizeEffects = serializedObject.FindProperty("m_VirtualizeEffects"); - } - - //This function assumes that index 0 is None... - private int FindPluginStringIndex(string[] strs, string element) - { - //Skip past the first "None" entry - for (int i = 1; i < strs.Length; i++) - { - if (element == strs[i]) - return i; - } - - return 0; - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_Volume, Styles.Volume); - EditorGUILayout.PropertyField(m_RolloffScale, Styles.RolloffScale); - EditorGUILayout.PropertyField(m_DopplerFactor, Styles.DopplerFactor); - EditorGUILayout.PropertyField(m_DefaultSpeakerMode, Styles.DefaultSpeakerMode); - EditorGUILayout.PropertyField(m_SampleRate, Styles.SampleRate); - EditorGUILayout.PropertyField(m_DSPBufferSize, Styles.DSPBufferSize); - EditorGUILayout.PropertyField(m_VirtualVoiceCount, Styles.VirtualVoiceCount); - EditorGUILayout.PropertyField(m_RealVoiceCount, Styles.RealVoiceCount); - - List plugins = new List(AudioSettings.GetSpatializerPluginNames()); - plugins.Insert(0, "None"); - string[] pluginsArray = plugins.ToArray(); - - List pluginsGUIContent = new List(); - foreach (var s in pluginsArray) - pluginsGUIContent.Add(new GUIContent(s)); - - List ambisonicDecoderPlugins = new List(AudioUtil.GetAmbisonicDecoderPluginNames()); - ambisonicDecoderPlugins.Insert(0, "None"); - string[] ambisonicDecoderPluginsArray = ambisonicDecoderPlugins.ToArray(); - - List ambisonicDecoderPluginsGUIContent = new List(); - foreach (var s in ambisonicDecoderPluginsArray) - ambisonicDecoderPluginsGUIContent.Add(new GUIContent(s)); - - EditorGUI.BeginChangeCheck(); - int pluginIndex = FindPluginStringIndex(pluginsArray, m_SpatializerPlugin.stringValue); - pluginIndex = EditorGUILayout.Popup(Styles.SpatializerPlugin, pluginIndex, pluginsGUIContent.ToArray()); - if (EditorGUI.EndChangeCheck()) - { - if (pluginIndex == 0) - m_SpatializerPlugin.stringValue = ""; - else - m_SpatializerPlugin.stringValue = pluginsArray[pluginIndex]; - } - - EditorGUI.BeginChangeCheck(); - pluginIndex = FindPluginStringIndex(ambisonicDecoderPluginsArray, m_AmbisonicDecoderPlugin.stringValue); - pluginIndex = EditorGUILayout.Popup(Styles.AmbisonicDecoderPlugin, pluginIndex, ambisonicDecoderPluginsGUIContent.ToArray()); - if (EditorGUI.EndChangeCheck()) - { - if (pluginIndex == 0) - m_AmbisonicDecoderPlugin.stringValue = ""; - else - m_AmbisonicDecoderPlugin.stringValue = ambisonicDecoderPluginsArray[pluginIndex]; - } - - EditorGUI.BeginChangeCheck(); - - EditorGUILayout.PropertyField(m_DisableAudio, Styles.DisableAudio); - EditorGUILayout.PropertyField(m_VirtualizeEffects, Styles.VirtualizeEffects); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/AudioMixerControllerInspector.cs b/Editor/Mono/Inspector/AudioMixerControllerInspector.cs deleted file mode 100644 index e2bc685854..0000000000 --- a/Editor/Mono/Inspector/AudioMixerControllerInspector.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.Audio; -using UnityEngine.Audio; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioMixerController))] - [CanEditMultipleObjects] - internal class AudioMixerControllerInspector : Editor - { - static class Texts - { - 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."); - 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."); - public static GUIContent m_UpdateModeLabel = EditorGUIUtility.TrTextContent("Update Mode", "Update AudioMixer transitions with game time or unscaled realtime."); - public static string dB = "dB"; - } - - SerializedProperty m_EnableSuspend; - SerializedProperty m_SuspendThreshold; - SerializedProperty m_UpdateMode; - - public void OnEnable() - { - m_SuspendThreshold = serializedObject.FindProperty("m_SuspendThreshold"); - m_EnableSuspend = serializedObject.FindProperty("m_EnableSuspend"); - m_UpdateMode = serializedObject.FindProperty("m_UpdateMode"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - EditorGUILayout.PropertyField(m_EnableSuspend, Texts.m_EnableSuspendLabel); - using (new EditorGUI.DisabledScope(!m_EnableSuspend.boolValue || m_EnableSuspend.hasMultipleDifferentValues)) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.s_UnitString = Texts.dB; - float displayValue = m_SuspendThreshold.floatValue; - displayValue = EditorGUILayout.PowerSlider(Texts.m_SuspendThresholdLabel, displayValue, AudioMixerController.kMinVolume, AudioMixerController.GetMaxVolume(), 1.0f); - EditorGUI.s_UnitString = null; - if (EditorGUI.EndChangeCheck()) - m_SuspendThreshold.floatValue = displayValue; - } - EditorGUILayout.PropertyField(m_UpdateMode, Texts.m_UpdateModeLabel); - serializedObject.ApplyModifiedProperties(); - } - } - - // Here we need an inspector for runtime objects that are loaded in the editor (via asset bundles) - // We need to inform the user that such objects are not editable in the editor. - [CustomEditor(typeof(AudioMixer))] - [CanEditMultipleObjects] - internal class AudioMixerInspector : Editor - { - public override void OnInspectorGUI() - { - GUILayout.Space(10); - EditorGUILayout.HelpBox("Modification and inspection of built AudioMixer assets is disabled. Please modify the source asset and re-build.", MessageType.Info); - } - } -} diff --git a/Editor/Mono/Inspector/AudioMixerGroupEditor.cs b/Editor/Mono/Inspector/AudioMixerGroupEditor.cs deleted file mode 100644 index d73ce4a813..0000000000 --- a/Editor/Mono/Inspector/AudioMixerGroupEditor.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Security.Permissions; -using UnityEngine; -using UnityEditor.Audio; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioMixerGroupController))] - internal class AudioMixerGroupEditor : Editor - { - private AudioMixerEffectView m_EffectView = null; - private readonly TickTimerHelper m_Ticker = new TickTimerHelper(1.0 / 20.0); - public static readonly string kPrefKeyForShowCpuUsage = "AudioMixerShowCPU"; - - void OnEnable() - { - EditorApplication.update += Update; - } - - void OnDisable() - { - EditorApplication.update -= Update; - } - - public void Update() - { - if (EditorApplication.isPlaying && m_Ticker.DoTick()) - { - Repaint(); // Ensure repaint to update vu meters and effects in playmode - } - } - - public override void OnInspectorGUI() - { - AudioMixerDrawUtils.InitStyles(); - if (m_EffectView == null) - m_EffectView = new AudioMixerEffectView(); - - AudioMixerGroupController group = target as AudioMixerGroupController; - m_EffectView.OnGUI(group); - } - - public override bool UseDefaultMargins() - { - // Makes inspector be full width - return false; - } - - internal override void DrawHeaderHelpAndSettingsGUI(Rect r) - { - if (m_EffectView == null) - return; - - AudioMixerGroupController group = target as AudioMixerGroupController; - - base.DrawHeaderHelpAndSettingsGUI(r); - Rect rect = new Rect(r.x + 44f, r.yMax - 20f, r.width - 50f, 15f); - GUI.Label(rect, GUIContent.Temp(group.controller.name), EditorStyles.miniLabel); - } - - // Add item to the context menu of the AudioMixerGroupController inspector header - [MenuItem("CONTEXT/AudioMixerGroupController/Copy all effect settings to all snapshots")] - static void CopyAllEffectToSnapshots(MenuCommand command) - { - AudioMixerGroupController group = command.context as AudioMixerGroupController; - AudioMixerController controller = group.controller; - if (controller == null) - return; - - Undo.RecordObject(controller, "Copy all effect settings to all snapshots"); - controller.CopyAllSettingsToAllSnapshots(group, controller.TargetSnapshot); - } - - [MenuItem("CONTEXT/AudioMixerGroupController/Toggle CPU usage display (only available on first editor instance)")] - static void ShowCPUUsage(MenuCommand command) - { - bool value = EditorPrefs.GetBool(kPrefKeyForShowCpuUsage, false); - EditorPrefs.SetBool(kPrefKeyForShowCpuUsage, !value); - } - } - - [CustomEditor(typeof(AudioMixerSnapshotController))] - [CanEditMultipleObjects] - internal class AudioMixerSnapshotControllerInspector : Editor - { - public override void OnInspectorGUI() - { - } - } -} diff --git a/Editor/Mono/Inspector/AudioReverbFilterEditor.cs b/Editor/Mono/Inspector/AudioReverbFilterEditor.cs deleted file mode 100644 index 8273c9ae65..0000000000 --- a/Editor/Mono/Inspector/AudioReverbFilterEditor.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioReverbFilter))] - [CanEditMultipleObjects] - class AudioReverbFilterEditor : Editor - { - SerializedProperty m_ReverbPreset; - - SerializedProperty m_DryLevel; // room effect level (at mid frequencies) - SerializedProperty m_Room; // room effect level (at mid frequencies) - SerializedProperty m_RoomHF; // relative room effect level at high frequencies - SerializedProperty m_RoomLF; // relative room effect level at low frequencies - SerializedProperty m_DecayTime; // reverberation decay time at mid frequencies - SerializedProperty m_DecayHFRatio; // high-frequency to mid-frequency decay time ratio - SerializedProperty m_ReflectionsLevel; // early reflections level relative to room effect - SerializedProperty m_ReflectionsDelay; // initial reflection delay time - SerializedProperty m_ReverbLevel; // late reverberation level relative to room effect - SerializedProperty m_ReverbDelay; // late reverberation delay time relative to initial reflection - SerializedProperty m_HFReference; // reference high frequency (hz) - SerializedProperty m_LFReference; // reference low frequency (hz) - SerializedProperty m_Diffusion; // Value that controls the echo density in the late reverberation decay - SerializedProperty m_Density; // Value that controls the modal density in the late reverberation decay - - - void OnEnable() - { - m_ReverbPreset = serializedObject.FindProperty("m_ReverbPreset"); - m_DryLevel = serializedObject.FindProperty("m_DryLevel"); // room effect level (at mid frequencies) - m_Room = serializedObject.FindProperty("m_Room"); // room effect level (at mid frequencies) - m_RoomHF = serializedObject.FindProperty("m_RoomHF"); // relative room effect level at high frequencies - m_RoomLF = serializedObject.FindProperty("m_RoomLF"); // relative room effect level at low frequencies - m_DecayTime = serializedObject.FindProperty("m_DecayTime"); // reverberation decay time at mid frequencies - m_DecayHFRatio = serializedObject.FindProperty("m_DecayHFRatio"); // high-frequency to mid-frequency decay time ratio - m_ReflectionsLevel = serializedObject.FindProperty("m_ReflectionsLevel"); // early reflections level relative to room effect - m_ReflectionsDelay = serializedObject.FindProperty("m_ReflectionsDelay"); // initial reflection delay time - m_ReverbLevel = serializedObject.FindProperty("m_ReverbLevel"); // late reverberation level relative to room effect - m_ReverbDelay = serializedObject.FindProperty("m_ReverbDelay"); // late reverberation delay time relative to initial reflection - m_HFReference = serializedObject.FindProperty("m_HFReference"); // reference high frequency (hz) - m_LFReference = serializedObject.FindProperty("m_LFReference"); // reference low frequency (hz) - m_Diffusion = serializedObject.FindProperty("m_Diffusion"); // Value that controls the echo density in the late reverberation decay - m_Density = serializedObject.FindProperty("m_Density"); // Value that controls the modal density in the late reverberation decay - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_ReverbPreset); - if (EditorGUI.EndChangeCheck()) - serializedObject.SetIsDifferentCacheDirty(); - - using (new EditorGUI.DisabledScope(m_ReverbPreset.enumValueIndex != 27 || m_ReverbPreset.hasMultipleDifferentValues)) - { - EditorGUILayout.Slider(m_DryLevel, -10000, 0); - EditorGUILayout.Slider(m_Room, -10000, 0); - EditorGUILayout.Slider(m_RoomHF, -10000, 0); - EditorGUILayout.Slider(m_RoomLF, -10000, 0); - EditorGUILayout.Slider(m_DecayTime, 0.1f, 20.0f); - EditorGUILayout.Slider(m_DecayHFRatio, 0.1f, 2.0f); - EditorGUILayout.Slider(m_ReflectionsLevel, -10000, 1000); - EditorGUILayout.Slider(m_ReflectionsDelay, 0.0f, 0.3f); - EditorGUILayout.Slider(m_ReverbLevel, -10000, 2000); - EditorGUILayout.Slider(m_ReverbDelay, 0.0f, 0.1f); - EditorGUILayout.Slider(m_HFReference, 1000.0f, 20000.0f); - EditorGUILayout.Slider(m_LFReference, 20.0f, 1000.0f); - EditorGUILayout.Slider(m_Diffusion, 0.0f, 100.0f); - EditorGUILayout.Slider(m_Density, 0.0f, 100.0f); - } - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/AudioReverbZoneEditor.cs b/Editor/Mono/Inspector/AudioReverbZoneEditor.cs deleted file mode 100644 index 9041bf45ea..0000000000 --- a/Editor/Mono/Inspector/AudioReverbZoneEditor.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioReverbZone))] - [CanEditMultipleObjects] - class AudioReverbZoneEditor : Editor - { - SerializedProperty m_MinDistance; - SerializedProperty m_MaxDistance; - SerializedProperty m_ReverbPreset; - - SerializedProperty m_Room; // room effect level (at mid frequencies) - SerializedProperty m_RoomHF; // relative room effect level at high frequencies - SerializedProperty m_RoomLF; // relative room effect level at low frequencies - SerializedProperty m_DecayTime; // reverberation decay time at mid frequencies - SerializedProperty m_DecayHFRatio; // high-frequency to mid-frequency decay time ratio - SerializedProperty m_Reflections; // early reflections level relative to room effect - SerializedProperty m_ReflectionsDelay; // initial reflection delay time - SerializedProperty m_Reverb; // late reverberation level relative to room effect - SerializedProperty m_ReverbDelay; // late reverberation delay time relative to initial reflection - SerializedProperty m_HFReference; // reference high frequency (hz) - SerializedProperty m_LFReference; // reference low frequency (hz) - SerializedProperty m_Diffusion; // Value that controls the echo density in the late reverberation decay - SerializedProperty m_Density; // Value that controls the modal density in the late reverberation decay - - void OnEnable() - { - m_MinDistance = serializedObject.FindProperty("m_MinDistance"); - m_MaxDistance = serializedObject.FindProperty("m_MaxDistance"); - m_ReverbPreset = serializedObject.FindProperty("m_ReverbPreset"); - m_Room = serializedObject.FindProperty("m_Room"); // room effect level (at mid frequencies) - m_RoomHF = serializedObject.FindProperty("m_RoomHF"); // relative room effect level at high frequencies - m_RoomLF = serializedObject.FindProperty("m_RoomLF"); // relative room effect level at low frequencies - m_DecayTime = serializedObject.FindProperty("m_DecayTime"); // reverberation decay time at mid frequencies - m_DecayHFRatio = serializedObject.FindProperty("m_DecayHFRatio"); // high-frequency to mid-frequency decay time ratio - m_Reflections = serializedObject.FindProperty("m_Reflections"); // early reflections level relative to room effect - m_ReflectionsDelay = serializedObject.FindProperty("m_ReflectionsDelay"); // initial reflection delay time - m_Reverb = serializedObject.FindProperty("m_Reverb"); // late reverberation level relative to room effect - m_ReverbDelay = serializedObject.FindProperty("m_ReverbDelay"); // late reverberation delay time relative to initial reflection - m_HFReference = serializedObject.FindProperty("m_HFReference"); // reference high frequency (hz) - m_LFReference = serializedObject.FindProperty("m_LFReference"); // reference low frequency (hz) - m_Diffusion = serializedObject.FindProperty("m_Diffusion"); // Value that controls the echo density in the late reverberation decay - m_Density = serializedObject.FindProperty("m_Density"); // Value that controls the modal density in the late reverberation decay - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_MinDistance); - EditorGUILayout.PropertyField(m_MaxDistance); - - EditorGUILayout.Space(); - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_ReverbPreset); - // Changing the preset changes all the other properties as well, so we need to do a full refresh afterwards - if (EditorGUI.EndChangeCheck()) - serializedObject.SetIsDifferentCacheDirty(); - - using (new EditorGUI.DisabledScope(m_ReverbPreset.enumValueIndex != 27 || m_ReverbPreset.hasMultipleDifferentValues)) - { - EditorGUILayout.IntSlider(m_Room, -10000, 0); - EditorGUILayout.IntSlider(m_RoomHF, -10000, 0); - EditorGUILayout.IntSlider(m_RoomLF, -10000, 0); - EditorGUILayout.Slider(m_DecayTime, 0.1f, 20.0f); - EditorGUILayout.Slider(m_DecayHFRatio, 0.1f, 2.0f); - EditorGUILayout.IntSlider(m_Reflections, -10000, 1000); - EditorGUILayout.Slider(m_ReflectionsDelay, 0.0f, 0.3f); - EditorGUILayout.IntSlider(m_Reverb, -10000, 2000); - EditorGUILayout.Slider(m_ReverbDelay, 0.0f, 0.1f); - EditorGUILayout.Slider(m_HFReference, 1000.0f, 20000.0f); - EditorGUILayout.Slider(m_LFReference, 20.0f, 1000.0f); - EditorGUILayout.Slider(m_Diffusion, 0.0f, 100.0f); - EditorGUILayout.Slider(m_Density, 0.0f, 100.0f); - } - - serializedObject.ApplyModifiedProperties(); - } - - void OnSceneGUI() - { - AudioReverbZone zone = (AudioReverbZone)target; - - Color tempColor = Handles.color; - if (zone.enabled) - Handles.color = new Color(0.50f, 0.70f, 1.00f, 0.5f); - else - Handles.color = new Color(0.30f, 0.40f, 0.60f, 0.5f); - - Vector3 position = zone.transform.position; - - EditorGUI.BeginChangeCheck(); - float minDistance = Handles.RadiusHandle(Quaternion.identity, position, zone.minDistance, true); - float maxDistance = Handles.RadiusHandle(Quaternion.identity, position, zone.maxDistance, true); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(zone, "Reverb Distance"); - zone.minDistance = minDistance; - zone.maxDistance = maxDistance; - } - - Handles.color = tempColor; - } - } -} diff --git a/Editor/Mono/Inspector/AudioSourceExtensionEditor.cs b/Editor/Mono/Inspector/AudioSourceExtensionEditor.cs deleted file mode 100644 index 8ddb9afcf1..0000000000 --- a/Editor/Mono/Inspector/AudioSourceExtensionEditor.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - internal class AudioSourceExtensionEditor : AudioExtensionEditor - { - public virtual void OnAudioSourceGUI() {} - public virtual void OnAudioSourceSceneGUI(AudioSource source) {} - - protected override int GetNumSerializedExtensionProperties(Object obj) - { - AudioSource source = obj as AudioSource; - int numSerializedExtensionProperties = source ? source.GetNumExtensionProperties() : 0; - - return numSerializedExtensionProperties; - } - } -} diff --git a/Editor/Mono/Inspector/AudioSourceInspector.cs b/Editor/Mono/Inspector/AudioSourceInspector.cs deleted file mode 100644 index 6abc5c2ecf..0000000000 --- a/Editor/Mono/Inspector/AudioSourceInspector.cs +++ /dev/null @@ -1,900 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - [CustomEditor(typeof(AudioSource))] - [CanEditMultipleObjects] - class AudioSourceInspector : Editor - { - SerializedProperty m_AudioClip; - SerializedProperty m_PlayOnAwake; - SerializedProperty m_Volume; - SerializedProperty m_Pitch; - SerializedProperty m_Loop; - SerializedProperty m_Mute; - SerializedProperty m_Spatialize; - SerializedProperty m_SpatializePostEffects; - SerializedProperty m_Priority; - SerializedProperty m_DopplerLevel; - SerializedProperty m_MinDistance; - SerializedProperty m_MaxDistance; - SerializedProperty m_Pan2D; - SerializedProperty m_RolloffMode; - SerializedProperty m_BypassEffects; - SerializedProperty m_BypassListenerEffects; - SerializedProperty m_BypassReverbZones; - SerializedProperty m_OutputAudioMixerGroup; - - SerializedObject m_LowpassObject; - - AudioSourceExtensionEditor m_SpatializerEditor = null; - private bool m_AddSpatializerExtension = false; - private bool m_AddSpatializerExtensionMixedValues = false; - - class AudioCurveWrapper - { - public AudioCurveType type; - public GUIContent legend; - public int id; - public Color color; - public SerializedProperty curveProp; - public float rangeMin; - public float rangeMax; - public AudioCurveWrapper(AudioCurveType type, string legend, int id, Color color, SerializedProperty curveProp, float rangeMin, float rangeMax) - { - this.type = type; - this.legend = new GUIContent(legend); - this.id = id; - this.color = color; - this.curveProp = curveProp; - this.rangeMin = rangeMin; - this.rangeMax = rangeMax; - } - } - private AudioCurveWrapper[] m_AudioCurves; - - CurveEditor m_CurveEditor = null; - Vector3 m_LastSourcePosition; - Vector3 m_LastListenerPosition; - - const int kRolloffCurveID = 0; - const int kSpatialBlendCurveID = 1; - const int kSpreadCurveID = 2; - const int kLowPassCurveID = 3; - const int kReverbZoneMixCurveID = 4; - internal const float kMaxCutoffFrequency = 22000.0f; - const float EPSILON = 0.0001f; - - - static CurveEditorSettings m_CurveEditorSettings = new CurveEditorSettings(); - internal static Color kRolloffCurveColor = new Color(0.90f, 0.30f, 0.20f, 1.0f); - internal static Color kSpatialCurveColor = new Color(0.25f, 0.70f, 0.20f, 1.0f); - internal static Color kSpreadCurveColor = new Color(0.25f, 0.55f, 0.95f, 1.0f); - internal static Color kLowPassCurveColor = new Color(0.80f, 0.25f, 0.90f, 1.0f); - internal static Color kReverbZoneMixCurveColor = new Color(0.70f, 0.70f, 0.20f, 1.0f); - - internal bool[] m_SelectedCurves = new bool[0]; - - private enum AudioCurveType { Volume, SpatialBlend, Lowpass, Spread, ReverbZoneMix } - - private bool m_Expanded3D = false; - - class Styles - { - public GUIStyle labelStyle = "ProfilerBadge"; - public GUIContent rolloffLabel = EditorGUIUtility.TrTextContent("Volume Rolloff", "Which type of rolloff curve to use"); - public string controlledByCurveLabel = "Controlled by curve"; - public GUIContent audioClipLabel = EditorGUIUtility.TrTextContent("AudioClip", "The AudioClip asset played by the AudioSource. Can be undefined if the AudioSource is generating a live stream of audio via OnAudioFilterRead."); - public 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 Stereo sounds have each left/right value faded up and down according to the specified pan value."); - public 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."); - public 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."); - public GUIContent dopplerLevelLabel = EditorGUIUtility.TrTextContent("Doppler Level", "Specifies how much the pitch is changed based on the relative velocity between AudioListener and AudioSource."); - public GUIContent spreadLabel = EditorGUIUtility.TrTextContent("Spread", "Sets the spread of a 3d sound in speaker space"); - public GUIContent outputMixerGroupLabel = EditorGUIUtility.TrTextContent("Output", "Set whether the sound should play through an Audio Mixer first or directly to the Audio Listener"); - public GUIContent volumeLabel = EditorGUIUtility.TrTextContent("Volume", "Sets the overall volume of the sound."); - public GUIContent pitchLabel = EditorGUIUtility.TrTextContent("Pitch", "Sets the frequency of the sound. Use this to slow down or speed up the sound."); - public 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."); - public GUIContent spatializeLabel = EditorGUIUtility.TrTextContent("Spatialize", "Enables or disables custom spatialization for the AudioSource."); - public 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."); - public GUIContent priorityLeftLabel = EditorGUIUtility.TrTextContent("High"); - public GUIContent priorityRightLabel = EditorGUIUtility.TrTextContent("Low"); - public GUIContent spatialLeftLabel = EditorGUIUtility.TrTextContent("2D"); - public GUIContent spatialRightLabel = EditorGUIUtility.TrTextContent("3D"); - public GUIContent panLeftLabel = EditorGUIUtility.TrTextContent("Left"); - public GUIContent panRightLabel = EditorGUIUtility.TrTextContent("Right"); - public GUIContent addSpatializerExtensionLabel = EditorGUIUtility.TrTextContent("Override Spatializer Settings", "Override the Google spatializer's default property settings."); - } - static Styles ms_Styles; - - Vector3 GetSourcePos(Object target) - { - AudioSource source = (AudioSource)target; - if (source == null) - return new Vector3(0.0f, 0.0f, 0.0f); - return source.transform.position; - } - - private void UpdateSpatializerExtensionMixedValues() - { - m_AddSpatializerExtension = false; - - int numTargetsWithSpatializerExtensions = 0; - for (int i = 0; i < targets.Length; i++) - { - AudioSource source = targets[i] as AudioSource; - if (source != null) - { - System.Type spatializerExtensionType = AudioExtensionManager.GetSourceSpatializerExtensionType(); - if ((spatializerExtensionType != null) && (source.GetNumExtensionPropertiesForThisExtension(spatializerExtensionType.Name) > 0)) - { - m_AddSpatializerExtension = true; - numTargetsWithSpatializerExtensions++; - } - } - } - - m_AddSpatializerExtensionMixedValues = ((numTargetsWithSpatializerExtensions == 0) || (numTargetsWithSpatializerExtensions == targets.Length)) ? false : true; - if (m_AddSpatializerExtensionMixedValues) - m_AddSpatializerExtension = false; - } - - // Created editors for all the enabled extensions of this AudioSource. - private void CreateExtensionEditors() - { - if (m_SpatializerEditor != null) - DestroyExtensionEditors(); - - System.Type spatializerEditorType = AudioExtensionManager.GetSourceSpatializerExtensionEditorType(); - m_SpatializerEditor = ScriptableObject.CreateInstance(spatializerEditorType) as AudioSourceExtensionEditor; - - if (m_SpatializerEditor != null) - { - for (int i = 0; i < targets.Length; i++) - { - AudioSource source = targets[i] as AudioSource; - if (source != null) - { - Undo.RecordObject(source, "Add AudioSource extension properties"); - string extensionName = AudioExtensionManager.GetSourceSpatializerExtensionType().Name; - for (int j = 0; j < m_SpatializerEditor.GetNumExtensionProperties(); j++) - { - PropertyName propertyName = m_SpatializerEditor.GetExtensionPropertyName(j); - float value = 0.0f; - - // If the AudioSource is missing an extension property, then create it now. - if (!source.ReadExtensionProperty(extensionName, propertyName, ref value)) - { - value = m_SpatializerEditor.GetExtensionPropertyDefaultValue(j); - source.WriteExtensionProperty(AudioExtensionManager.GetSourceSpatializerExtensionName(), extensionName, propertyName, value); - } - } - } - } - } - - m_AddSpatializerExtensionMixedValues = false; - } - - private void DestroyExtensionEditors() - { - DestroyImmediate(m_SpatializerEditor); - m_SpatializerEditor = null; - } - - private void ClearExtensionProperties() - { - for (int i = 0; i < targets.Length; i++) - { - AudioSource source = targets[i] as AudioSource; - if (source != null) - { - Undo.RecordObject(source, "Remove AudioSource extension properties"); - source.ClearExtensionProperties(AudioExtensionManager.GetSourceSpatializerExtensionName()); - } - } - - m_AddSpatializerExtensionMixedValues = false; - } - - void OnEnable() - { - m_AudioClip = serializedObject.FindProperty("m_audioClip"); - m_PlayOnAwake = serializedObject.FindProperty("m_PlayOnAwake"); - m_Volume = serializedObject.FindProperty("m_Volume"); - m_Pitch = serializedObject.FindProperty("m_Pitch"); - m_Loop = serializedObject.FindProperty("Loop"); - m_Mute = serializedObject.FindProperty("Mute"); - m_Spatialize = serializedObject.FindProperty("Spatialize"); - m_SpatializePostEffects = serializedObject.FindProperty("SpatializePostEffects"); - m_Priority = serializedObject.FindProperty("Priority"); - m_DopplerLevel = serializedObject.FindProperty("DopplerLevel"); - m_MinDistance = serializedObject.FindProperty("MinDistance"); - m_MaxDistance = serializedObject.FindProperty("MaxDistance"); - m_Pan2D = serializedObject.FindProperty("Pan2D"); - m_RolloffMode = serializedObject.FindProperty("rolloffMode"); - m_BypassEffects = serializedObject.FindProperty("BypassEffects"); - m_BypassListenerEffects = serializedObject.FindProperty("BypassListenerEffects"); - m_BypassReverbZones = serializedObject.FindProperty("BypassReverbZones"); - m_OutputAudioMixerGroup = serializedObject.FindProperty("OutputAudioMixerGroup"); - - m_AudioCurves = new AudioCurveWrapper[] - { - new AudioCurveWrapper(AudioCurveType.Volume, "Volume", kRolloffCurveID, kRolloffCurveColor, serializedObject.FindProperty("rolloffCustomCurve"), 0, 1), - new AudioCurveWrapper(AudioCurveType.SpatialBlend, "Spatial Blend", kSpatialBlendCurveID, kSpatialCurveColor, serializedObject.FindProperty("panLevelCustomCurve"), 0, 1), - new AudioCurveWrapper(AudioCurveType.Spread, "Spread", kSpreadCurveID, kSpreadCurveColor, serializedObject.FindProperty("spreadCustomCurve"), 0, 1), - new AudioCurveWrapper(AudioCurveType.Lowpass, "Low-Pass", kLowPassCurveID, kLowPassCurveColor, null, 0, 1), - new AudioCurveWrapper(AudioCurveType.ReverbZoneMix, "Reverb Zone Mix", kReverbZoneMixCurveID, kReverbZoneMixCurveColor, serializedObject.FindProperty("reverbZoneMixCustomCurve"), 0, 1.1f) - }; - - m_CurveEditorSettings.hRangeMin = 0.0f; - m_CurveEditorSettings.vRangeMin = 0.0f; - m_CurveEditorSettings.vRangeMax = 1.1f; - m_CurveEditorSettings.hRangeMax = 1.0f; - m_CurveEditorSettings.vSlider = false; - m_CurveEditorSettings.hSlider = false; - - TickStyle hTS = new TickStyle(); - hTS.tickColor.color = new Color(0.0f, 0.0f, 0.0f, 0.15f); - hTS.distLabel = 30; - m_CurveEditorSettings.hTickStyle = hTS; - TickStyle vTS = new TickStyle(); - vTS.tickColor.color = new Color(0.0f, 0.0f, 0.0f, 0.15f); - vTS.distLabel = 20; - m_CurveEditorSettings.vTickStyle = vTS; - - m_CurveEditorSettings.undoRedoSelection = true; - - m_CurveEditor = new CurveEditor(new Rect(0, 0, 1000, 100), new CurveWrapper[0], false); - m_CurveEditor.settings = m_CurveEditorSettings; - m_CurveEditor.margin = 25; - m_CurveEditor.SetShownHRangeInsideMargins(0.0f, 1.0f); - m_CurveEditor.SetShownVRangeInsideMargins(0.0f, 1.1f); - m_CurveEditor.ignoreScrollWheelUntilClicked = true; - - m_LastSourcePosition = GetSourcePos(target); - m_LastListenerPosition = AudioUtil.GetListenerPos(); - EditorApplication.update += Update; - Undo.undoRedoPerformed += UndoRedoPerformed; - - m_Expanded3D = EditorPrefs.GetBool("AudioSourceExpanded3D", m_Expanded3D); - - UpdateSpatializerExtensionMixedValues(); - if (m_AddSpatializerExtension) - CreateExtensionEditors(); - } - - void OnDisable() - { - m_CurveEditor.OnDisable(); - - DestroyExtensionEditors(); - - Undo.undoRedoPerformed -= UndoRedoPerformed; - EditorApplication.update -= Update; - - EditorPrefs.SetBool("AudioSourceExpanded3D", m_Expanded3D); - } - - CurveWrapper[] GetCurveWrapperArray() - { - List wrappers = new List(); - - foreach (AudioCurveWrapper audioCurve in m_AudioCurves) - { - if (audioCurve.curveProp == null) - continue; - - bool includeCurve = false; - AnimationCurve curve = audioCurve.curveProp.animationCurveValue; - - // Special handling of volume rolloff curve - if (audioCurve.type == AudioCurveType.Volume) - { - AudioRolloffMode mode = (AudioRolloffMode)m_RolloffMode.enumValueIndex; - if (m_RolloffMode.hasMultipleDifferentValues) - { - includeCurve = false; - } - else if (mode == AudioRolloffMode.Custom) - { - includeCurve = !audioCurve.curveProp.hasMultipleDifferentValues; - } - else - { - includeCurve = !m_MinDistance.hasMultipleDifferentValues && !m_MaxDistance.hasMultipleDifferentValues; - if (mode == AudioRolloffMode.Linear) - curve = AnimationCurve.Linear(m_MinDistance.floatValue / m_MaxDistance.floatValue, 1.0f, 1.0f, 0.0f); - else if (mode == AudioRolloffMode.Logarithmic) - curve = Logarithmic(m_MinDistance.floatValue / m_MaxDistance.floatValue, 1.0f, 1.0f); - } - } - // All other curves - else - { - includeCurve = !audioCurve.curveProp.hasMultipleDifferentValues; - } - - if (includeCurve) - { - if (curve.length == 0) - Debug.LogError(audioCurve.legend.text + " curve has no keys!"); - else - wrappers.Add(GetCurveWrapper(curve, audioCurve)); - } - } - - return wrappers.ToArray(); - } - - private CurveWrapper GetCurveWrapper(AnimationCurve curve, AudioCurveWrapper audioCurve) - { - float colorMultiplier = !EditorGUIUtility.isProSkin ? 0.9f : 1.0f; - Color colorMult = new Color(colorMultiplier, colorMultiplier, colorMultiplier, 1); - - CurveWrapper wrapper = new CurveWrapper(); - wrapper.id = audioCurve.id; - wrapper.groupId = -1; - wrapper.color = audioCurve.color * colorMult; - wrapper.hidden = false; - wrapper.readOnly = false; - wrapper.renderer = new NormalCurveRenderer(curve); - wrapper.renderer.SetCustomRange(0.0f, 1.0f); - wrapper.getAxisUiScalarsCallback = GetAxisScalars; - return wrapper; - } - - // Callback for Curve Editor to get axis labels - public Vector2 GetAxisScalars() - { - return new Vector2(m_MaxDistance.floatValue, 1); - } - - private static float LogarithmicValue(float distance, float minDistance, float rolloffScale) - { - if ((distance > minDistance) && (rolloffScale != 1.0f)) - { - distance -= minDistance; - distance *= rolloffScale; - distance += minDistance; - } - if (distance < .000001f) - distance = .000001f; - return minDistance / distance; - } - - /// A logarithmic curve starting at /timeStart/, /valueStart/ and ending at /timeEnd/, /valueEnd/ - private static AnimationCurve Logarithmic(float timeStart, float timeEnd, float logBase) - { - float value, slope, s; - List keys = new List(); - // Just plain set the step to 2 always. It can't really be any less, - // or the curvature will end up being imprecise in certain edge cases. - float step = 2; - timeStart = Mathf.Max(timeStart, 0.0001f); - for (float d = timeStart; d < timeEnd; d *= step) - { - // Add key w. sensible tangents - value = LogarithmicValue(d, timeStart, logBase); - s = d / 50.0f; - slope = (LogarithmicValue(d + s, timeStart, logBase) - LogarithmicValue(d - s, timeStart, logBase)) / (s * 2); - keys.Add(new Keyframe(d, value, slope, slope)); - } - - // last key - value = LogarithmicValue(timeEnd, timeStart, logBase); - s = timeEnd / 50.0f; - slope = (LogarithmicValue(timeEnd + s, timeStart, logBase) - LogarithmicValue(timeEnd - s, timeStart, logBase)) / (s * 2); - keys.Add(new Keyframe(timeEnd, value, slope, slope)); - - return new AnimationCurve(keys.ToArray()); - } - - static void InitStyles() - { - if (ms_Styles == null) - ms_Styles = new Styles(); - } - - private void Update() - { - // listener moved? - Vector3 sourcePos = GetSourcePos(target); - Vector3 listenerPos = AudioUtil.GetListenerPos(); - if ((m_LastSourcePosition - sourcePos).sqrMagnitude > EPSILON || (m_LastListenerPosition - listenerPos).sqrMagnitude > EPSILON) - { - m_LastSourcePosition = sourcePos; - m_LastListenerPosition = listenerPos; - Repaint(); - } - } - - private void UndoRedoPerformed() - { - DestroyExtensionEditors(); - - UpdateSpatializerExtensionMixedValues(); - if (!m_AddSpatializerExtension && !m_AddSpatializerExtensionMixedValues) - ClearExtensionProperties(); - - if (m_AddSpatializerExtension) - CreateExtensionEditors(); - - Repaint(); - } - - private void HandleLowPassFilter() - { - AudioCurveWrapper audioCurve = m_AudioCurves[kLowPassCurveID]; - - // Low pass filter present for all targets? - AudioLowPassFilter[] filterArray = new AudioLowPassFilter[targets.Length]; - for (int i = 0; i < targets.Length; i++) - { - filterArray[i] = ((AudioSource)targets[i]).GetComponent(); - if (filterArray[i] == null) - { - m_LowpassObject = null; - audioCurve.curveProp = null; - // Return if any of the GameObjects don't have an AudioLowPassFilter - return; - } - } - - // All the GameObjects have an AudioLowPassFilter. - // If we don't have the corresponding SerializedObject and SerializedProperties, create them. - if (audioCurve.curveProp == null) - { - m_LowpassObject = new SerializedObject(filterArray); - audioCurve.curveProp = m_LowpassObject.FindProperty("lowpassLevelCustomCurve"); - } - } - - public override void OnInspectorGUI() - { - InitStyles(); - serializedObject.Update(); - - if (m_LowpassObject != null) - m_LowpassObject.Update(); - - HandleLowPassFilter(); - - UpdateWrappersAndLegend(); - - EditorGUILayout.PropertyField(m_AudioClip, ms_Styles.audioClipLabel); - EditorGUILayout.Space(); - EditorGUILayout.PropertyField(m_OutputAudioMixerGroup, ms_Styles.outputMixerGroupLabel); - EditorGUILayout.PropertyField(m_Mute); - EditorGUILayout.PropertyField(m_BypassEffects); - if (targets.Any(t => (t as AudioSource).outputAudioMixerGroup != null)) - { - using (new EditorGUI.DisabledScope(true)) - { - EditorGUILayout.PropertyField(m_BypassListenerEffects); - } - } - else - { - EditorGUILayout.PropertyField(m_BypassListenerEffects); - } - EditorGUILayout.PropertyField(m_BypassReverbZones); - - EditorGUILayout.PropertyField(m_PlayOnAwake); - EditorGUILayout.PropertyField(m_Loop); - - EditorGUILayout.Space(); - EditorGUIUtility.sliderLabels.SetLabels(ms_Styles.priorityLeftLabel, ms_Styles.priorityRightLabel); - EditorGUILayout.IntSlider(m_Priority, 0, 256, ms_Styles.priorityLabel); - EditorGUIUtility.sliderLabels.SetLabels(null, null); - EditorGUILayout.Space(); - EditorGUILayout.Slider(m_Volume, 0f, 1.0f, ms_Styles.volumeLabel); - EditorGUILayout.Space(); - EditorGUILayout.Slider(m_Pitch, -3.0f, 3.0f, ms_Styles.pitchLabel); - - EditorGUILayout.Space(); - - EditorGUIUtility.sliderLabels.SetLabels(ms_Styles.panLeftLabel, ms_Styles.panRightLabel); - EditorGUILayout.Slider(m_Pan2D, -1f, 1f, ms_Styles.panStereoLabel); - EditorGUIUtility.sliderLabels.SetLabels(null, null); - EditorGUILayout.Space(); - - // 3D Level control - EditorGUIUtility.sliderLabels.SetLabels(ms_Styles.spatialLeftLabel, ms_Styles.spatialRightLabel); - AnimProp(ms_Styles.spatialBlendLabel, m_AudioCurves[kSpatialBlendCurveID].curveProp, 0.0f, 1.0f, false); - EditorGUIUtility.sliderLabels.SetLabels(null, null); - EditorGUILayout.Space(); - - // 3D Level control - AnimProp(ms_Styles.reverbZoneMixLabel, m_AudioCurves[kReverbZoneMixCurveID].curveProp, 0.0f, 1.1f, false); - EditorGUILayout.Space(); - - m_Expanded3D = EditorGUILayout.Foldout(m_Expanded3D, "3D Sound Settings", true); - if (m_Expanded3D) - { - EditorGUI.indentLevel++; - Audio3DGUI(); - EditorGUI.indentLevel--; - } - - if (AudioUtil.canUseSpatializerEffect) - { - EditorGUILayout.PropertyField(m_Spatialize, ms_Styles.spatializeLabel); - if (m_Spatialize.boolValue && !m_Spatialize.hasMultipleDifferentValues) - { - for (int i = 0; i < targets.Length; i++) - { - AudioSource source = targets[i] as AudioSource; - AudioSourceExtension extension = (source != null) ? AudioExtensionManager.GetSpatializerExtension(source) : null; - - // If we are playing in Editor or previewing in the scene view, spatialize is true, and we do not have a spatializer extension, try to add one. - // We may have just toggled spatialize here in the Editor. - if ((source != null) && source.spatialize && source.isPlaying) - { - if (extension == null) - extension = AudioExtensionManager.AddSpatializerExtension(source); - - AudioExtensionManager.GetReadyToPlay(extension); - } - } - - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_SpatializePostEffects, ms_Styles.spatializePostEffectsLabel); - - bool allowExtensionEditing = (m_AddSpatializerExtension && !m_AddSpatializerExtensionMixedValues) || !serializedObject.isEditingMultipleObjects; - if (AudioExtensionManager.IsSourceSpatializerExtensionRegistered() && allowExtensionEditing) - { - EditorGUI.showMixedValue = m_AddSpatializerExtensionMixedValues; - bool addSpatializerExtensionNew = EditorGUILayout.Toggle(ms_Styles.addSpatializerExtensionLabel, m_AddSpatializerExtension); - EditorGUI.showMixedValue = false; - - bool showExtensionProperties = false; - if (m_AddSpatializerExtension != addSpatializerExtensionNew) - { - m_AddSpatializerExtension = addSpatializerExtensionNew; - if (m_AddSpatializerExtension) - { - CreateExtensionEditors(); - - if (m_SpatializerEditor != null) - showExtensionProperties = m_SpatializerEditor.FindAudioExtensionProperties(serializedObject); - } - else - { - ClearExtensionProperties(); - DestroyExtensionEditors(); - showExtensionProperties = false; - } - } - else if (m_SpatializerEditor != null) - { - showExtensionProperties = m_SpatializerEditor.FindAudioExtensionProperties(serializedObject); - if (!showExtensionProperties) - { - m_AddSpatializerExtension = false; - ClearExtensionProperties(); - DestroyExtensionEditors(); - } - } - - if ((m_SpatializerEditor != null) && showExtensionProperties) - { - EditorGUI.indentLevel++; - m_SpatializerEditor.OnAudioSourceGUI(); - EditorGUI.indentLevel--; - - // Push any AudioSource extension property changes to the AudioSourceExtension properties. We always attempt to do this - // because we may be playing in Editor or previewing sound in the scene view. - for (int i = 0; i < targets.Length; i++) - { - AudioSource source = targets[i] as AudioSource; - AudioSourceExtension extension = (source != null) ? AudioExtensionManager.GetSpatializerExtension(source) : null; - - if ((source != null) && (extension != null) && source.isPlaying) - { - string extensionName = AudioExtensionManager.GetSourceSpatializerExtensionType().Name; - for (int j = 0; j < m_SpatializerEditor.GetNumExtensionProperties(); j++) - { - PropertyName propertyName = m_SpatializerEditor.GetExtensionPropertyName(j); - float value = 0.0f; - if (source.ReadExtensionProperty(extensionName, propertyName, ref value)) - { - extension.WriteExtensionProperty(propertyName, value); - } - } - } - } - } - } - } - } - - serializedObject.ApplyModifiedProperties(); - if (m_LowpassObject != null) - m_LowpassObject.ApplyModifiedProperties(); - } - - private static void SetRolloffToTarget(SerializedProperty property, Object target) - { - property.SetToValueOfTarget(target); - property.serializedObject.FindProperty("rolloffMode").SetToValueOfTarget(target); - property.serializedObject.ApplyModifiedProperties(); - EditorUtility.ForceReloadInspectors(); - } - - private void Audio3DGUI() - { - EditorGUILayout.Slider(m_DopplerLevel, 0.0f, 5.0f, ms_Styles.dopplerLevelLabel); - - // Spread control - AnimProp(ms_Styles.spreadLabel, m_AudioCurves[kSpreadCurveID].curveProp, 0.0f, 360.0f, true); - - // Rolloff mode - if (m_RolloffMode.hasMultipleDifferentValues || - (m_RolloffMode.enumValueIndex == (int)AudioRolloffMode.Custom && m_AudioCurves[kRolloffCurveID].curveProp.hasMultipleDifferentValues) - ) - { - EditorGUILayout.TargetChoiceField(m_AudioCurves[kRolloffCurveID].curveProp, ms_Styles.rolloffLabel , SetRolloffToTarget); - } - else - { - EditorGUILayout.PropertyField(m_RolloffMode, ms_Styles.rolloffLabel); - - if ((AudioRolloffMode)m_RolloffMode.enumValueIndex != AudioRolloffMode.Custom) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_MinDistance); - if (EditorGUI.EndChangeCheck()) - { - m_MinDistance.floatValue = Mathf.Clamp(m_MinDistance.floatValue, 0, m_MaxDistance.floatValue / 1.01f); - } - } - else - { - using (new EditorGUI.DisabledScope(true)) - { - EditorGUILayout.LabelField(m_MinDistance.displayName, ms_Styles.controlledByCurveLabel); - } - } - } - - // Max distance control - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_MaxDistance); - if (EditorGUI.EndChangeCheck()) - m_MaxDistance.floatValue = Mathf.Min(Mathf.Max(Mathf.Max(m_MaxDistance.floatValue, 0.01f), m_MinDistance.floatValue * 1.01f), 1000000.0f); - - Rect r = GUILayoutUtility.GetAspectRect(1.333f, GUI.skin.textField); - r.xMin += EditorGUI.indent; - if (Event.current.type != EventType.Layout && Event.current.type != EventType.Used) - { - m_CurveEditor.rect = new Rect(r.x, r.y, r.width, r.height); - } - - // Draw Curve Editor - UpdateWrappersAndLegend(); - GUI.Label(m_CurveEditor.drawRect, GUIContent.none, "TextField"); - - m_CurveEditor.hRangeLocked = Event.current.shift; - m_CurveEditor.vRangeLocked = EditorGUI.actionKey; - - m_CurveEditor.OnGUI(); - - // Draw current listener position - if (targets.Length == 1) - { - AudioSource t = (AudioSource)target; - AudioListener audioListener = (AudioListener)FindObjectOfType(typeof(AudioListener)); - if (audioListener != null) - { - float distToListener = (AudioUtil.GetListenerPos() - t.transform.position).magnitude; - DrawLabel("Listener", distToListener, r); - } - } - - // Draw legend - DrawLegend(); - - if (!m_CurveEditor.InLiveEdit()) - { - // Check if any of the curves changed - foreach (AudioCurveWrapper audioCurve in m_AudioCurves) - { - if ((m_CurveEditor.GetCurveWrapperFromID(audioCurve.id) != null) && (m_CurveEditor.GetCurveWrapperFromID(audioCurve.id).changed)) - { - AnimationCurve changedCurve = m_CurveEditor.GetCurveWrapperFromID(audioCurve.id).curve; - - // Never save a curve with no keys - if (changedCurve.length > 0) - { - audioCurve.curveProp.animationCurveValue = changedCurve; - m_CurveEditor.GetCurveWrapperFromID(audioCurve.id).changed = false; - - // Volume curve special handling - if (audioCurve.type == AudioCurveType.Volume) - m_RolloffMode.enumValueIndex = (int)AudioRolloffMode.Custom; - } - } - } - } - } - - void UpdateWrappersAndLegend() - { - if (m_CurveEditor.InLiveEdit()) - return; - - m_CurveEditor.animationCurves = GetCurveWrapperArray(); - SyncShownCurvesToLegend(GetShownAudioCurves()); - } - - void DrawLegend() - { - List legendRects = new List(); - List curves = GetShownAudioCurves(); - - Rect legendRect = GUILayoutUtility.GetRect(10, 20); - legendRect.x += 4 + EditorGUI.indent; - legendRect.width -= 8 + EditorGUI.indent; - int width = Mathf.Min(75, Mathf.FloorToInt(legendRect.width / curves.Count)); - for (int i = 0; i < curves.Count; i++) - { - legendRects.Add(new Rect(legendRect.x + width * i, legendRect.y, width, legendRect.height)); - } - - bool resetSelections = false; - if (curves.Count != m_SelectedCurves.Length) - { - m_SelectedCurves = new bool[curves.Count]; - resetSelections = true; - } - - if (EditorGUIExt.DragSelection(legendRects.ToArray(), ref m_SelectedCurves, GUIStyle.none) || resetSelections) - { - // If none are selected, select all - bool someSelected = false; - for (int i = 0; i < curves.Count; i++) - { - if (m_SelectedCurves[i]) - someSelected = true; - } - if (!someSelected) - { - for (int i = 0; i < curves.Count; i++) - { - m_SelectedCurves[i] = true; - } - } - - SyncShownCurvesToLegend(curves); - } - - for (int i = 0; i < curves.Count; i++) - { - EditorGUI.DrawLegend(legendRects[i], curves[i].color, curves[i].legend.text, m_SelectedCurves[i]); - if (curves[i].curveProp.hasMultipleDifferentValues) - { - GUI.Button(new Rect(legendRects[i].x, legendRects[i].y + 20, legendRects[i].width, 20), "Different"); - } - } - } - - private List GetShownAudioCurves() - { - return m_AudioCurves.Where(f => m_CurveEditor.GetCurveWrapperFromID(f.id) != null).ToList(); - } - - private void SyncShownCurvesToLegend(List curves) - { - if (curves.Count != m_SelectedCurves.Length) - return; // Selected curves in sync'ed later in this frame - - for (int i = 0; i < curves.Count; i++) - m_CurveEditor.GetCurveWrapperFromID(curves[i].id).hidden = !m_SelectedCurves[i]; - - // Need to apply animation curves again to synch selections - m_CurveEditor.animationCurves = m_CurveEditor.animationCurves; - } - - void DrawLabel(string label, float value, Rect r) - { - Vector2 size = ms_Styles.labelStyle.CalcSize(new GUIContent(label)); - size.x += 2; - Vector2 posA = m_CurveEditor.DrawingToViewTransformPoint(new Vector2(value / m_MaxDistance.floatValue, 0)); - Vector2 posB = m_CurveEditor.DrawingToViewTransformPoint(new Vector2(value / m_MaxDistance.floatValue, 1)); - GUI.BeginGroup(r); - Color temp = Handles.color; - Handles.color = new Color(1, 0, 0, 0.3f); - Handles.DrawLine(new Vector3(posA.x , posA.y, 0), new Vector3(posB.x , posB.y, 0)); - Handles.DrawLine(new Vector3(posA.x + 1, posA.y, 0), new Vector3(posB.x + 1, posB.y, 0)); - Handles.color = temp; - GUI.Label(new Rect(Mathf.Floor(posB.x - size.x / 2), 2, size.x, 15), label, ms_Styles.labelStyle); - GUI.EndGroup(); - } - - internal static void AnimProp(GUIContent label, SerializedProperty prop, float min, float max, bool useNormalizedValue) - { - // AnimProp can be called from other classes so styes have not necessarily been inited yet. - InitStyles(); - - if (prop.hasMultipleDifferentValues) - { - EditorGUILayout.TargetChoiceField(prop, label); - return; - } - - AnimationCurve curve = prop.animationCurveValue; - if (curve == null) - { - Debug.LogError(label.text + " curve is null!"); - return; - } - else if (curve.length == 0) - { - Debug.LogError(label.text + " curve has no keys!"); - return; - } - - if (curve.length != 1) - { - using (new EditorGUI.DisabledScope(true)) - { - EditorGUILayout.LabelField(label.text, ms_Styles.controlledByCurveLabel); - } - } - else - { - float f = useNormalizedValue ? Mathf.Lerp(min, max, curve.keys[0].value) : curve.keys[0].value; - f = MathUtils.DiscardLeastSignificantDecimal(f); - EditorGUI.BeginChangeCheck(); - if (max > min) - f = EditorGUILayout.Slider(label, f, min, max); - else - f = EditorGUILayout.Slider(label, f, max, min); - - if (EditorGUI.EndChangeCheck()) - { - Keyframe kf = curve.keys[0]; - kf.time = 0.0f; - kf.value = useNormalizedValue ? Mathf.InverseLerp(min, max, f) : f; - curve.MoveKey(0, kf); - } - } - - prop.animationCurveValue = curve; - } - - void OnSceneGUI() - { - AudioSource source = (AudioSource)target; - - Color tempColor = Handles.color; - if (source.enabled) - Handles.color = new Color(0.50f, 0.70f, 1.00f, 0.5f); - else - Handles.color = new Color(0.30f, 0.40f, 0.60f, 0.5f); - - Vector3 position = source.transform.position; - - EditorGUI.BeginChangeCheck(); - float minDistance = Handles.RadiusHandle(Quaternion.identity, position, source.minDistance, true); - float maxDistance = Handles.RadiusHandle(Quaternion.identity, position, source.maxDistance, true); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(source, "AudioSource Distance"); - source.minDistance = minDistance; - source.maxDistance = maxDistance; - } - - Handles.color = tempColor; - - if (m_Spatialize.boolValue && (m_SpatializerEditor != null)) - m_SpatializerEditor.OnAudioSourceSceneGUI(source); - } - } -} diff --git a/Editor/Mono/Inspector/Avatar/AvatarAutoMapper.cs b/Editor/Mono/Inspector/Avatar/AvatarAutoMapper.cs deleted file mode 100644 index 23829ef96c..0000000000 --- a/Editor/Mono/Inspector/Avatar/AvatarAutoMapper.cs +++ /dev/null @@ -1,917 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class AvatarAutoMapper - { - private enum Side { None, Left, Right } - - private struct BoneMappingItem - { - public int parent; - public int bone; - public int minStep; - public int maxStep; - public float lengthRatio; - public Vector3 dir; - public Side side; - public bool optional; - public bool alwaysInclude; - public string[] keywords; - private int[] children; - - public BoneMappingItem(int parent, int bone, int minStep, int maxStep, float lengthRatio, Vector3 dir, Side side, bool optional, bool alwaysInclude, params string[] keywords) - { - this.parent = parent; - this.bone = bone; - this.minStep = minStep; - this.maxStep = maxStep; - this.lengthRatio = lengthRatio; - this.dir = dir; - this.side = side; - this.optional = optional; - this.alwaysInclude = alwaysInclude; - this.keywords = keywords; - this.children = null; - } - - public BoneMappingItem(int parent, int bone, int minStep, int maxStep, float lengthRatio, Side side, bool optional, bool alwaysInclude, params string[] keywords) - : this(parent, bone, minStep, maxStep, lengthRatio, Vector3.zero, side, optional, alwaysInclude, keywords) {} - - public BoneMappingItem(int parent, int bone, int minStep, int maxStep, float lengthRatio, Vector3 dir, Side side, params string[] keywords) - : this(parent, bone, minStep, maxStep, lengthRatio, dir, side, false, false, keywords) {} - - public BoneMappingItem(int parent, int bone, int minStep, int maxStep, float lengthRatio, Side side, params string[] keywords) - : this(parent, bone, minStep, maxStep, lengthRatio, Vector3.zero, side, false, false, keywords) {} - - public int[] GetChildren(BoneMappingItem[] mappingData) - { - if (children == null) - { - List list = new List(); - for (int i = 0; i < mappingData.Length; i++) - if (mappingData[i].parent == bone) - list.Add(i); - children = list.ToArray(); - } - return children; - } - } - - private class BoneMatch : IComparable - { - public BoneMatch parent; - public List children = new List(); - public bool doMap = false; - public BoneMatch humanBoneParent - { - get - { - BoneMatch p = parent; - while (p.parent != null && (p.item.bone < 0)) - p = p.parent; - return p; - } - } - public BoneMappingItem item; - public Transform bone; - public float score; - public float siblingScore; - public float totalSiblingScore { get { return score + siblingScore; } } - public List debugTracker = new List(); - public BoneMatch(BoneMatch parent, Transform bone, BoneMappingItem item) - { - this.parent = parent; - this.bone = bone; - this.item = item; - } - - public int CompareTo(BoneMatch other) - { - if (other == null) - return 1; - return other.totalSiblingScore.CompareTo(totalSiblingScore); - } - } - - private struct QueuedBone - { - public Transform bone; - public int level; - public QueuedBone(Transform bone, int level) { this.bone = bone; this.level = level; } - } - - private static bool kDebug = false; - - private static string[] kShoulderKeywords = {"shoulder", "collar", "clavicle"}; - private static string[] kUpperArmKeywords = {"up"}; - private static string[] kLowerArmKeywords = {"lo", "fore", "elbow"}; - private static string[] kHandKeywords = {"hand", "wrist"}; - - private static string[] kUpperLegKeywords = {"up", "thigh"}; - private static string[] kLowerLegKeywords = {"lo", "calf", "knee", "shin"}; - private static string[] kFootKeywords = {"foot", "ankle"}; - private static string[] kToeKeywords = {"toe", "!end", "!top", "!nub"}; - - private static string[] kNeckKeywords = {"neck"}; - private static string[] kHeadKeywords = {"head"}; - private static string[] kJawKeywords = {"jaw", "open", "!teeth", "!tongue", "!pony", "!braid", "!end", "!top", "!nub"}; - private static string[] kEyeKeywords = {"eye", "ball", "!brow", "!lid", "!pony", "!braid", "!end", "!top", "!nub"}; - - private static string[] kThumbKeywords = {"thu", "!palm", "!wrist", "!end", "!top", "!nub"}; - private static string[] kIndexFingerKeywords = {"ind", "point", "!palm", "!wrist", "!end", "!top", "!nub"}; - private static string[] kMiddleFingerKeywords = {"mid", "long", "!palm", "!wrist", "!end", "!top", "!nub"}; - private static string[] kRingFingerKeywords = {"rin", "!palm", "!wrist", "!end", "!top", "!nub"}; - private static string[] kLittleFingerKeywords = {"lit", "pin", "!palm", "!wrist", "!end", "!top", "!nub"}; - - private static BoneMappingItem[] s_MappingDataBody = new BoneMappingItem[] - { - new BoneMappingItem(-1, (int)HumanBodyBones.Hips, 1, 3, 0.0f, Side.None), - - new BoneMappingItem((int)HumanBodyBones.Hips, (int)HumanBodyBones.RightUpperLeg, 1, 2, 0.0f, Vector3.right, Side.Right, kUpperLegKeywords), - new BoneMappingItem((int)HumanBodyBones.RightUpperLeg, (int)HumanBodyBones.RightLowerLeg, 1, 2, 3.0f, -Vector3.up, Side.Right, kLowerLegKeywords), - new BoneMappingItem((int)HumanBodyBones.RightLowerLeg, (int)HumanBodyBones.RightFoot, 1, 2, 1.0f, -Vector3.up, Side.Right, kFootKeywords), - new BoneMappingItem((int)HumanBodyBones.RightFoot, (int)HumanBodyBones.RightToes, 1, 2, 0.5f, Vector3.forward, Side.Right, true, true, kToeKeywords), - - new BoneMappingItem((int)HumanBodyBones.Hips, (int)HumanBodyBones.Spine, 1, 3, 0.0f, Vector3.up, Side.None), - new BoneMappingItem((int)HumanBodyBones.Spine, (int)HumanBodyBones.Chest, 0, 3, 1.4f, Vector3.up, Side.None, true, false), - new BoneMappingItem((int)HumanBodyBones.Chest, (int)HumanBodyBones.UpperChest, 0, 3, 1.4f, Vector3.up, Side.None, true, false), - - new BoneMappingItem((int)HumanBodyBones.UpperChest, (int)HumanBodyBones.RightShoulder, 1, 3, 0.0f, Vector3.right, Side.Right, true, false, kShoulderKeywords), - new BoneMappingItem((int)HumanBodyBones.RightShoulder, (int)HumanBodyBones.RightUpperArm, 0, 2, 0.5f, Vector3.right, Side.Right, kUpperArmKeywords), - new BoneMappingItem((int)HumanBodyBones.RightUpperArm, (int)HumanBodyBones.RightLowerArm, 1, 2, 2.0f, Vector3.right, Side.Right, kLowerArmKeywords), - new BoneMappingItem((int)HumanBodyBones.RightLowerArm, (int)HumanBodyBones.RightHand, 1, 2, 1.0f, Vector3.right, Side.Right, kHandKeywords), - - new BoneMappingItem((int)HumanBodyBones.UpperChest, (int)HumanBodyBones.Neck, 1, 3, 1.8f, Vector3.up, Side.None, true, false, kNeckKeywords), - new BoneMappingItem((int)HumanBodyBones.Neck, (int)HumanBodyBones.Head, 0, 2, 0.3f, Vector3.up, Side.None, kHeadKeywords), - - new BoneMappingItem((int)HumanBodyBones.Head, (int)HumanBodyBones.Jaw, 1, 2, 0.0f, Vector3.forward, Side.None, true, false, kJawKeywords), - new BoneMappingItem((int)HumanBodyBones.Head, (int)HumanBodyBones.RightEye, 1, 2, 0.0f, new Vector3(1, 1, 1), Side.Right, true, false, kEyeKeywords), - - new BoneMappingItem((int)HumanBodyBones.RightHand, -2, 1, 2, 0.0f, new Vector3(1, -1, 2), Side.Right, true, false, kThumbKeywords), - new BoneMappingItem((int)HumanBodyBones.RightHand, -3, 1, 2, 0.0f, new Vector3(3, 0, 1), Side.Right, true, false, kIndexFingerKeywords), - }; - - private static BoneMappingItem[] s_LeftMappingDataHand = new BoneMappingItem[] - { - new BoneMappingItem(-2, -1, 1, 2, 0.0f, Side.None), - - new BoneMappingItem(-1, (int)HumanBodyBones.LeftThumbProximal, 1, 3, 0.0f, new Vector3(2, 0, 1), Side.None, kThumbKeywords), - new BoneMappingItem(-1, (int)HumanBodyBones.LeftIndexProximal, 1, 3, 0.0f, new Vector3(4, 0, 1), Side.None, kIndexFingerKeywords), - new BoneMappingItem(-1, (int)HumanBodyBones.LeftMiddleProximal, 1, 3, 0.0f, new Vector3(4, 0, 0), Side.None, kMiddleFingerKeywords), - new BoneMappingItem(-1, (int)HumanBodyBones.LeftRingProximal, 1, 3, 0.0f, new Vector3(4, 0, -1), Side.None, kRingFingerKeywords), - new BoneMappingItem(-1, (int)HumanBodyBones.LeftLittleProximal, 1, 3, 0.0f, new Vector3(4, 0, -2), Side.None, kLittleFingerKeywords), - - new BoneMappingItem((int)HumanBodyBones.LeftThumbProximal, (int)HumanBodyBones.LeftThumbIntermediate, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.LeftIndexProximal, (int)HumanBodyBones.LeftIndexIntermediate, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.LeftMiddleProximal, (int)HumanBodyBones.LeftMiddleIntermediate, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.LeftRingProximal, (int)HumanBodyBones.LeftRingIntermediate, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.LeftLittleProximal, (int)HumanBodyBones.LeftLittleIntermediate, 1, 1, 0.0f, Side.None, false, true), - - new BoneMappingItem((int)HumanBodyBones.LeftThumbIntermediate, (int)HumanBodyBones.LeftThumbDistal, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.LeftIndexIntermediate, (int)HumanBodyBones.LeftIndexDistal, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.LeftMiddleIntermediate, (int)HumanBodyBones.LeftMiddleDistal, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.LeftRingIntermediate, (int)HumanBodyBones.LeftRingDistal, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.LeftLittleIntermediate, (int)HumanBodyBones.LeftLittleDistal, 1, 1, 0.0f, Side.None, false, true), - }; - - private static BoneMappingItem[] s_RightMappingDataHand = new BoneMappingItem[] - { - new BoneMappingItem(-2, -1, 1, 2, 0.0f, Side.None), - - new BoneMappingItem(-1, (int)HumanBodyBones.RightThumbProximal, 1, 3, 0.0f, new Vector3(2, 0, 1), Side.None, kThumbKeywords), - new BoneMappingItem(-1, (int)HumanBodyBones.RightIndexProximal, 1, 3, 0.0f, new Vector3(4, 0, 1), Side.None, kIndexFingerKeywords), - new BoneMappingItem(-1, (int)HumanBodyBones.RightMiddleProximal, 1, 3, 0.0f, new Vector3(4, 0, 0), Side.None, kMiddleFingerKeywords), - new BoneMappingItem(-1, (int)HumanBodyBones.RightRingProximal, 1, 3, 0.0f, new Vector3(4, 0, -1), Side.None, kRingFingerKeywords), - new BoneMappingItem(-1, (int)HumanBodyBones.RightLittleProximal, 1, 3, 0.0f, new Vector3(4, 0, -2), Side.None, kLittleFingerKeywords), - - new BoneMappingItem((int)HumanBodyBones.RightThumbProximal, (int)HumanBodyBones.RightThumbIntermediate, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.RightIndexProximal, (int)HumanBodyBones.RightIndexIntermediate, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.RightMiddleProximal, (int)HumanBodyBones.RightMiddleIntermediate, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.RightRingProximal, (int)HumanBodyBones.RightRingIntermediate, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.RightLittleProximal, (int)HumanBodyBones.RightLittleIntermediate, 1, 1, 0.0f, Side.None, false, true), - - new BoneMappingItem((int)HumanBodyBones.RightThumbIntermediate, (int)HumanBodyBones.RightThumbDistal, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.RightIndexIntermediate, (int)HumanBodyBones.RightIndexDistal, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.RightMiddleIntermediate, (int)HumanBodyBones.RightMiddleDistal, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.RightRingIntermediate, (int)HumanBodyBones.RightRingDistal, 1, 1, 0.0f, Side.None, false, true), - new BoneMappingItem((int)HumanBodyBones.RightLittleIntermediate, (int)HumanBodyBones.RightLittleDistal, 1, 1, 0.0f, Side.None, false, true), - }; - - private static bool s_DidPerformInit = false; - - private Dictionary m_ValidBones; - private bool m_TreatDummyBonesAsReal = false; - - private Quaternion m_Orientation; - private int m_MappingIndexOffset = 0; - private BoneMappingItem[] m_MappingData; - - private Dictionary m_BoneHasKeywordDict; - private Dictionary m_BoneHasBadKeywordDict; - private Dictionary m_BoneMatchDict; - - private static int GetLeftBoneIndexFromRight(int rightIndex) - { - if (rightIndex < 0) - { - return rightIndex; - } - else if (rightIndex < (int)HumanBodyBones.LastBone) - { - string name = Enum.GetName(typeof(HumanBodyBones), rightIndex); - name = name.Replace("Right", "Left"); - return (int)(HumanBodyBones)Enum.Parse(typeof(HumanBodyBones), name); - } - - return -1; - } - - public static void InitGlobalMappingData() - { - if (s_DidPerformInit) - return; - - List mappingData = new List(s_MappingDataBody); - - // Add left side bones to match right side ones. - int size = mappingData.Count; - for (int i = 0; i < size; i++) - { - BoneMappingItem item = mappingData[i]; - if (item.side == Side.Right) - { - // Get left HumanBodyBones that mirrors right one. - int bone = GetLeftBoneIndexFromRight(item.bone); - // Get left parent HumanBodyBones that mirrors parent of right one - int parentBone = GetLeftBoneIndexFromRight(item.parent); - // Add left BoneMappingItem that mirrors right one. - 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)); - } - } - - s_MappingDataBody = mappingData.ToArray(); - - // Cache children for each BoneMappingItem - for (int i = 0; i < s_MappingDataBody.Length; i++) - s_MappingDataBody[i].GetChildren(s_MappingDataBody); - for (int i = 0; i < s_LeftMappingDataHand.Length; i++) - s_LeftMappingDataHand[i].GetChildren(s_LeftMappingDataHand); - for (int i = 0; i < s_RightMappingDataHand.Length; i++) - s_RightMappingDataHand[i].GetChildren(s_RightMappingDataHand); - - s_DidPerformInit = true; - } - - public static Dictionary MapBones(Transform root, Dictionary validBones) - { - AvatarAutoMapper mapper = new AvatarAutoMapper(validBones); - return mapper.MapBones(root); - } - - public AvatarAutoMapper(Dictionary validBones) - { - m_BoneHasKeywordDict = new Dictionary(); - m_BoneHasBadKeywordDict = new Dictionary(); - m_BoneMatchDict = new Dictionary(); - m_ValidBones = validBones; - } - - public Dictionary MapBones(Transform root) - { - InitGlobalMappingData(); - - Dictionary mapping = new Dictionary(); - - // Perform body mapping - { - m_Orientation = Quaternion.identity; - m_MappingData = s_MappingDataBody; - m_MappingIndexOffset = 0; - m_BoneMatchDict.Clear(); - BoneMatch rootMatch = new BoneMatch(null, root, m_MappingData[0]); - - m_TreatDummyBonesAsReal = false; - MapBonesFromRootDown(rootMatch, mapping); - // There are 15 required bones. If we mapped less than that, check if we can do better. - if (mapping.Count < 15) - { - m_TreatDummyBonesAsReal = true; - MapBonesFromRootDown(rootMatch, mapping); - } - - // Check if character has correct alignment - if (mapping.ContainsKey((int)HumanBodyBones.LeftUpperLeg) && mapping.ContainsKey((int)HumanBodyBones.RightUpperLeg) && - mapping.ContainsKey((int)HumanBodyBones.LeftUpperArm) && mapping.ContainsKey((int)HumanBodyBones.RightUpperArm)) - { - m_Orientation = AvatarSetupTool.AvatarComputeOrientation( - mapping[(int)HumanBodyBones.LeftUpperLeg].position, mapping[(int)HumanBodyBones.RightUpperLeg].position, - mapping[(int)HumanBodyBones.LeftUpperArm].position, mapping[(int)HumanBodyBones.RightUpperArm].position); - - // If not standard aligned, try to map again with correct alignment assumptions - if (Vector3.Angle(m_Orientation * Vector3.up, Vector3.up) > 20 || Vector3.Angle(m_Orientation * Vector3.forward, Vector3.forward) > 20) - { - if (kDebug) - Debug.Log("*** Mapping with new computed orientation"); - mapping.Clear(); - m_BoneMatchDict.Clear(); - MapBonesFromRootDown(rootMatch, mapping); - } - } - - // For models that don't have meshes, all bones are marked valid; even the root. - // So we use this to check if this model has meshes or not. - bool modelHasMeshes = !(m_ValidBones.ContainsKey(root) && m_ValidBones[root] == true); - - // Fix up hips to be valid bone closest to the root - // For models with meshes, valid bones further up are mapped to part of the mesh (otherwise they wouldn't be valid). - // For models with no meshes we don't know which transforms are valid bones and which aren't - // so we skip this step and use the found hips bone as-is. - if (modelHasMeshes && mapping.Count > 0 && mapping.ContainsKey((int)HumanBodyBones.Hips)) - { - while (true) - { - Transform parent = mapping[(int)HumanBodyBones.Hips].parent; - if (parent != null && parent != rootMatch.bone && m_ValidBones.ContainsKey(parent) && m_ValidBones[parent] == true) - mapping[(int)HumanBodyBones.Hips] = parent; - else - break; - } - } - - // Move upper chest to chest if no chest was found - if (!mapping.ContainsKey((int)HumanBodyBones.Chest) && - mapping.ContainsKey((int)HumanBodyBones.UpperChest)) - { - mapping.Add((int)HumanBodyBones.Chest, mapping[(int)HumanBodyBones.UpperChest]); - mapping.Remove((int)HumanBodyBones.UpperChest); - } - } - - int kMinFingerBones = 3; - - Quaternion bodyOrientation = m_Orientation; - - // Perform left hand mapping - if (mapping.ContainsKey((int)HumanBodyBones.LeftHand)) - { - Transform lowerArm = mapping[(int)HumanBodyBones.LeftLowerArm]; - Transform hand = mapping[(int)HumanBodyBones.LeftHand]; - - // Use reference orientation based on lower arm for mapping hand - m_Orientation = Quaternion.FromToRotation(bodyOrientation * -Vector3.right, hand.position - lowerArm.position) * bodyOrientation; - - m_MappingData = s_LeftMappingDataHand; - m_MappingIndexOffset = (int)HumanBodyBones.LeftThumbProximal; - m_BoneMatchDict.Clear(); - BoneMatch rootMatch = new BoneMatch(null, lowerArm, m_MappingData[0]); - m_TreatDummyBonesAsReal = true; - - int mappingCountBefore = mapping.Count; - MapBonesFromRootDown(rootMatch, mapping); - - // If we only mapped 2 finger bones or less, then cancel mapping of fingers - if (mapping.Count < mappingCountBefore + kMinFingerBones) - { - for (int i = (int)HumanBodyBones.LeftThumbProximal; i <= (int)HumanBodyBones.LeftLittleDistal; i++) - mapping.Remove(i); - } - } - - // Perform right hand mapping - if (mapping.ContainsKey((int)HumanBodyBones.RightHand)) - { - Transform lowerArm = mapping[(int)HumanBodyBones.RightLowerArm]; - Transform hand = mapping[(int)HumanBodyBones.RightHand]; - - // Use reference orientation based on lower arm for mapping hand - m_Orientation = Quaternion.FromToRotation(bodyOrientation * Vector3.right, hand.position - lowerArm.position) * bodyOrientation; - - m_MappingData = s_RightMappingDataHand; - m_MappingIndexOffset = (int)HumanBodyBones.RightThumbProximal; - m_BoneMatchDict.Clear(); - BoneMatch rootMatch = new BoneMatch(null, lowerArm, m_MappingData[0]); - m_TreatDummyBonesAsReal = true; - - int mappingCountBefore = mapping.Count; - MapBonesFromRootDown(rootMatch, mapping); - - // If we only mapped 2 finger bones or less, then cancel mapping of fingers - if (mapping.Count < mappingCountBefore + kMinFingerBones) - { - for (int i = (int)HumanBodyBones.RightThumbProximal; i <= (int)HumanBodyBones.RightLittleDistal; i++) - mapping.Remove(i); - } - } - - return mapping; - } - - private void MapBonesFromRootDown(BoneMatch rootMatch, Dictionary mapping) - { - // Perform mapping - List childMatches = RecursiveFindPotentialBoneMatches(rootMatch, m_MappingData[0], true); - if (childMatches != null && childMatches.Count > 0) - { - if (kDebug) - { - EvaluateBoneMatch(childMatches[0], true); - } - ApplyMapping(childMatches[0], mapping); - } - } - - private void ApplyMapping(BoneMatch match, Dictionary mapping) - { - if (match.doMap) - mapping[match.item.bone] = match.bone; - foreach (BoneMatch child in match.children) - ApplyMapping(child, mapping); - } - - private string GetStrippedAndNiceBoneName(Transform bone) - { - string[] strings = bone.name.Split(':'); - return ObjectNames.NicifyVariableName(strings[strings.Length - 1]); - } - - private int BoneHasBadKeyword(Transform bone, params string[] keywords) - { - string key = bone.GetInstanceID() + ":" + String.Concat(keywords); - if (m_BoneHasBadKeywordDict.ContainsKey(key)) - return m_BoneHasBadKeywordDict[key]; - - int score = 0; - string boneName; - - // If parent transform has any of keywords, don't accept. - Transform parent = bone.parent; - while (parent.parent != null && m_ValidBones.ContainsKey(parent) && !m_ValidBones[parent]) - parent = parent.parent; - boneName = GetStrippedAndNiceBoneName(parent).ToLower(); - foreach (string word in keywords) - if (word[0] != '!' && boneName.Contains(word)) - { - score = -20; - m_BoneHasBadKeywordDict[key] = score; - return score; - } - - // If this transform has any of the illegal keywords, don't accept. - boneName = GetStrippedAndNiceBoneName(bone).ToLower(); - foreach (string word in keywords) - if (word[0] == '!' && boneName.Contains(word.Substring(1))) - { - score = -1000; - m_BoneHasBadKeywordDict[key] = score; - return score; - } - - m_BoneHasBadKeywordDict[key] = score; - return score; - } - - private int BoneHasKeyword(Transform bone, params string[] keywords) - { - string key = bone.GetInstanceID() + ":" + String.Concat(keywords); - if (m_BoneHasKeywordDict.ContainsKey(key)) - return m_BoneHasKeywordDict[key]; - - int score = 0; - - // If this transform has any of the keywords, accept. - string boneName = GetStrippedAndNiceBoneName(bone).ToLower(); - foreach (string word in keywords) - if (word[0] != '!' && boneName.Contains(word)) - { - score = 20; - m_BoneHasKeywordDict[key] = score; - return score; - } - - m_BoneHasKeywordDict[key] = score; - return score; - } - - private const string kLeftMatch = @"(^|.*[ \.:_-])[lL]($|[ \.:_-].*)"; - private const string kRightMatch = @"(^|.*[ \.:_-])[rR]($|[ \.:_-].*)"; - private bool MatchesSideKeywords(string boneName, bool left) - { - if (boneName.ToLower().Contains(left ? "left" : "right")) - return true; - - if (System.Text.RegularExpressions.Regex.Match(boneName, left ? kLeftMatch : kRightMatch).Length > 0) - return true; - - return false; - } - - private int GetBoneSideMatchPoints(BoneMatch match) - { - string boneName = match.bone.name; - if (match.item.side == Side.None) - if (MatchesSideKeywords(boneName, false) || MatchesSideKeywords(boneName, true)) - return -1000; - - bool left = (match.item.side == Side.Left); - if (MatchesSideKeywords(boneName, left)) - return 15; - if (MatchesSideKeywords(boneName, !left)) - return -1000; - - return 0; - } - - private int GetMatchKey(BoneMatch parentMatch, Transform t, BoneMappingItem goalItem) - { - SimpleProfiler.Begin("GetMatchKey"); - int key = goalItem.bone; - key += t.GetInstanceID() * 1000; - if (parentMatch != null) - { - key += parentMatch.bone.GetInstanceID() * 1000000; - if (parentMatch.parent != null) - key += parentMatch.parent.bone.GetInstanceID() * 1000000000; - } - SimpleProfiler.End(); - return key; - } - - // Returns possible matches sorted with best-scoring ones first in the list - private List RecursiveFindPotentialBoneMatches(BoneMatch parentMatch, BoneMappingItem goalItem, bool confirmedChoice) - { - List matches = new List(); - - // We want to search with breadh first search so we have to use a queue - Queue queue = new Queue(); - - // Find matches - queue.Enqueue(new QueuedBone(parentMatch.bone, 0)); - while (queue.Count > 0) - { - QueuedBone current = queue.Dequeue(); - Transform t = current.bone; - if (current.level >= goalItem.minStep && (m_TreatDummyBonesAsReal || m_ValidBones == null || (m_ValidBones.ContainsKey(t) && m_ValidBones[t]))) - { - BoneMatch match; - var key = GetMatchKey(parentMatch, t, goalItem); - if (m_BoneMatchDict.ContainsKey(key)) - { - match = m_BoneMatchDict[key]; - } - else - { - match = new BoneMatch(parentMatch, t, goalItem); - - // RECURSIVE CALL - EvaluateBoneMatch(match, false); - m_BoneMatchDict[key] = match; - } - - if (match.score > 0 || kDebug) - matches.Add(match); - } - SimpleProfiler.Begin("Queue"); - if (current.level < goalItem.maxStep) - { - foreach (Transform child in t) - if (m_ValidBones == null || m_ValidBones.ContainsKey(child)) - if (!m_TreatDummyBonesAsReal && m_ValidBones != null && !m_ValidBones[child]) - queue.Enqueue(new QueuedBone(child, current.level)); - else - queue.Enqueue(new QueuedBone(child, current.level + 1)); - } - SimpleProfiler.End(); - } - - if (matches.Count == 0) - return null; - - // Sort by match score with best matches first - SimpleProfiler.Begin("SortAndTrim"); - matches.Sort(); - if (matches[0].score <= 0) - return null; - - if (kDebug && confirmedChoice) - DebugMatchChoice(matches); - - // Keep top 3 priorities only for optimization - while (matches.Count > 3) - matches.RemoveAt(matches.Count - 1); - matches.TrimExcess(); - SimpleProfiler.End(); - - return matches; - } - - private string GetNameOfBone(int boneIndex) - { - if (boneIndex < 0) - return "" + boneIndex; - - return "" + (HumanBodyBones)boneIndex; - } - - private string GetMatchString(BoneMatch match) - { - return GetNameOfBone(match.item.bone) + ":" + (match.bone == null ? "null" : match.bone.name); - } - - private void DebugMatchChoice(List matches) - { - string str = GetNameOfBone(matches[0].item.bone) + " preferred order: "; - for (int i = 0; i < matches.Count; i++) - str += matches[i].bone.name + " (" + matches[i].score.ToString("0.0") + " / " + matches[i].totalSiblingScore.ToString("0.0") + "), "; - foreach (BoneMatch m in matches) - { - str += "\n Match " + m.bone.name + " (" + m.score.ToString("0.0") + " / " + m.totalSiblingScore.ToString("0.0") + "):"; - foreach (string s in m.debugTracker) - str += "\n - " + s; - } - Debug.Log(str); - } - - private bool IsParentOfOther(Transform knownCommonParent, Transform potentialParent, Transform potentialChild) - { - Transform t = potentialChild; - while (t != knownCommonParent) - { - if (t == potentialParent) - return true; - if (t == knownCommonParent) - return false; - t = t.parent; - } - return false; - } - - private bool ShareTransformPath(Transform commonParent, Transform childA, Transform childB) - { - return IsParentOfOther(commonParent, childA, childB) || IsParentOfOther(commonParent, childB, childA); - } - - private List GetBestChildMatches(BoneMatch parentMatch, List> childMatchesLists) - { - List bestMatches = new List(); - if (childMatchesLists.Count == 1) - { - bestMatches.Add(childMatchesLists[0][0]); - return bestMatches; - } - - int[] choices = new int[childMatchesLists.Count]; - float dummyScore; - choices = GetBestChildMatchChoices(parentMatch, childMatchesLists, choices, out dummyScore); - for (int i = 0; i < choices.Length; i++) - { - if (choices[i] >= 0) - bestMatches.Add(childMatchesLists[i][choices[i]]); - } - return bestMatches; - } - - private int[] GetBestChildMatchChoices(BoneMatch parentMatch, List> childMatchesLists, int[] choices, out float score) - { - // See if any choices share the same transform path. - List sharedIndices = new List(); - for (int i = 0; i < choices.Length; i++) - { - if (choices[i] < 0) - continue; - sharedIndices.Clear(); - sharedIndices.Add(i); - for (int j = i + 1; j < choices.Length; j++) - { - if (choices[j] < 0) - continue; - if (ShareTransformPath(parentMatch.bone, childMatchesLists[i][choices[i]].bone, childMatchesLists[j][choices[j]].bone)) - sharedIndices.Add(j); - } - - if (sharedIndices.Count > 1) - break; - } - - if (sharedIndices.Count <= 1) - { - // If no shared transform paths, calculate score and return choices. - score = 0; - for (int i = 0; i < choices.Length; i++) - if (choices[i] >= 0) - score += childMatchesLists[i][choices[i]].totalSiblingScore; - return choices; - } - else - { - // If transform paths are shared by multiple choices, call function recursively. - float bestScore = 0; - int[] bestChoices = choices; - for (int i = 0; i < sharedIndices.Count; i++) - { - int[] altChoices = new int[choices.Length]; - Array.Copy(choices, altChoices, choices.Length); - // In each call, one of the choices retains their priority while the remaining are bumped one priority down. - for (int j = 0; j < sharedIndices.Count; j++) - { - if (i != j) - { - if (sharedIndices[j] >= altChoices.Length) - Debug.LogError("sharedIndices[j] (" + sharedIndices[j] + ") >= altChoices.Length (" + altChoices.Length + ")"); - if (sharedIndices[j] >= childMatchesLists.Count) - Debug.LogError("sharedIndices[j] (" + sharedIndices[j] + ") >= childMatchesLists.Count (" + childMatchesLists.Count + ")"); - if (altChoices[sharedIndices[j]] < childMatchesLists[sharedIndices[j]].Count - 1) - altChoices[sharedIndices[j]]++; - else - altChoices[sharedIndices[j]] = -1; - } - } - float altScore; - altChoices = GetBestChildMatchChoices(parentMatch, childMatchesLists, altChoices, out altScore); - if (altScore > bestScore) - { - bestScore = altScore; - bestChoices = altChoices; - } - } - // Return the choices with the best score - score = bestScore; - return bestChoices; - } - } - - private void EvaluateBoneMatch(BoneMatch match, bool confirmedChoice) - { - match.score = 0; - match.siblingScore = 0; - - // Things to copy from identical match: score, siblingScore, children, doMap - - // Iterate child BoneMappingitems - List> childMatchesLists = new List>(); - int intendedChildCount = 0; - foreach (int c in match.item.GetChildren(m_MappingData)) - { - BoneMappingItem i = m_MappingData[c]; - if (i.parent == match.item.bone) - { - intendedChildCount++; - // RECURSIVE CALL - List childMatches = RecursiveFindPotentialBoneMatches(match, i, confirmedChoice); - if (childMatches == null || childMatches.Count == 0) - continue; - childMatchesLists.Add(childMatches); - } - } - - // Best best child matches - bool sameAsParentOrChild = (match.bone == match.humanBoneParent.bone); - int childCount = 0; - if (childMatchesLists.Count > 0) - { - SimpleProfiler.Begin("GetBestChildMatches"); - match.children = GetBestChildMatches(match, childMatchesLists); - SimpleProfiler.End(); - - // Handle child matches - foreach (BoneMatch childMatch in match.children) - { - // RECURSIVE CALL for debugging purposes - if (kDebug && confirmedChoice) - EvaluateBoneMatch(childMatch, confirmedChoice); - - // Transfer info from best child match to parent - childCount++; - match.score += childMatch.score; - if (kDebug) - match.debugTracker.AddRange(childMatch.debugTracker); - if (childMatch.bone == match.bone && childMatch.item.bone >= 0) - sameAsParentOrChild = true; - } - } - - SimpleProfiler.Begin("ScoreBoneMatch"); - // Keyword score the bone if it's not optional or if it's different from both parent bone and all child bones - if (!match.item.optional || !sameAsParentOrChild) - ScoreBoneMatch(match); - SimpleProfiler.End(); - - // Rate bone according to how well it matches goal direction - SimpleProfiler.Begin("MatchesDir"); - if (match.item.dir != Vector3.zero) - { - Vector3 goalDir = match.item.dir; - if (m_MappingIndexOffset >= (int)HumanBodyBones.LeftThumbProximal && m_MappingIndexOffset < (int)HumanBodyBones.RightThumbProximal) - goalDir.x *= -1; - Vector3 dir = (match.bone.position - match.humanBoneParent.bone.position).normalized; - dir = Quaternion.Inverse(m_Orientation) * dir; - float dirMatchingScore = Vector3.Dot(dir, goalDir) * (match.item.optional ? 5 : 10); - - match.siblingScore += dirMatchingScore; - if (kDebug) - match.debugTracker.Add("* " + dirMatchingScore + ": " + GetMatchString(match) + " matched dir (" + (match.bone.position - match.humanBoneParent.bone.position).normalized + " , " + goalDir + ")"); - - if (dirMatchingScore > 0) - { - match.score += 10; - if (kDebug) - match.debugTracker.Add(10 + ": " + GetMatchString(match) + " matched dir (" + (match.bone.position - match.humanBoneParent.bone.position).normalized + " , " + goalDir + ")"); - } - } - SimpleProfiler.End(); - - // Give small score if bone matches side it belongs to. - SimpleProfiler.Begin("MatchesSide"); - if (m_MappingIndexOffset == 0) - { - int sideMatchingScore = GetBoneSideMatchPoints(match); - if (match.parent.item.side == Side.None || sideMatchingScore < 0) - { - match.siblingScore += sideMatchingScore; - if (kDebug) - match.debugTracker.Add("* " + sideMatchingScore + ": " + GetMatchString(match) + " matched side"); - } - } - SimpleProfiler.End(); - - // These criteria can not push a bone above the threshold, but they can help to break ties. - if (match.score > 0) - { - // Reward optional bones being included - if (match.item.optional && !sameAsParentOrChild) - { - match.score += 5; - if (kDebug) - match.debugTracker.Add(5 + ": " + GetMatchString(match) + " optional bone is included"); - } - - // Handle end bones - if (intendedChildCount == 0 && match.bone.childCount > 0) - { - // Reward end bones having a dummy child transform - match.score += 1; - if (kDebug) - match.debugTracker.Add(1 + ": " + GetMatchString(match) + " has dummy child bone"); - } - - // Give score to bones length ratio according to match with goal ratio. - SimpleProfiler.Begin("LengthRatio"); - if (match.item.lengthRatio != 0) - { - float parentLength = Vector3.Distance(match.bone.position, match.humanBoneParent.bone.position); - if (parentLength == 0 && match.bone != match.humanBoneParent.bone) - { - match.score -= 1000; - if (kDebug) - match.debugTracker.Add((-1000) + ": " + GetMatchString(match.humanBoneParent) + " has zero length"); - } - - float grandParentLength = Vector3.Distance(match.humanBoneParent.bone.position, match.humanBoneParent.humanBoneParent.bone.position); - if (grandParentLength > 0) - { - float logRatio = Mathf.Log(parentLength / grandParentLength, 2); - float logGoalRatio = Mathf.Log(match.item.lengthRatio, 2); - float ratioScore = 10 * Mathf.Clamp(1 - 0.6f * Mathf.Abs(logRatio - logGoalRatio), 0, 1); - match.score += ratioScore; - if (kDebug) - match.debugTracker.Add(ratioScore + ": parent " + GetMatchString(match.humanBoneParent) + " matched lengthRatio - " + parentLength + " / " + grandParentLength + " = " + (parentLength / grandParentLength) + " (" + logRatio + ") goal: " + match.item.lengthRatio + " (" + logGoalRatio + ")"); - } - } - SimpleProfiler.End(); - } - - // Only map optional bones if they're not the same as the parent or child. - if (match.item.bone >= 0 && (!match.item.optional || !sameAsParentOrChild)) - match.doMap = true; - } - - private void ScoreBoneMatch(BoneMatch match) - { - int badKeywordScore = BoneHasBadKeyword(match.bone, match.item.keywords); - match.score += badKeywordScore; - if (kDebug && badKeywordScore != 0) - match.debugTracker.Add(badKeywordScore + ": " + GetMatchString(match) + " matched bad keywords"); - if (badKeywordScore < 0) - return; - - int keywordScore = BoneHasKeyword(match.bone, match.item.keywords); - match.score += keywordScore; - if (kDebug && keywordScore != 0) - match.debugTracker.Add(keywordScore + ": " + GetMatchString(match) + " matched keywords"); - - // If child bone with no required keywords, give a minimal score so it can still be included in mapping - if (match.item.keywords.Length == 0 && match.item.alwaysInclude) - { - match.score += 1; - if (kDebug) - match.debugTracker.Add(1 + ": " + GetMatchString(match) + " always-include point"); - } - } - } -} diff --git a/Editor/Mono/Inspector/Avatar/AvatarBipedMapper.cs b/Editor/Mono/Inspector/Avatar/AvatarBipedMapper.cs deleted file mode 100644 index 8938e5a8a3..0000000000 --- a/Editor/Mono/Inspector/Avatar/AvatarBipedMapper.cs +++ /dev/null @@ -1,282 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; -using System.Linq; - -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AvatarBipedMapper - { - private struct BipedBone - { - public string name; - public int index; - - public BipedBone(string name, int index) - { - this.name = name; - this.index = index; - } - } - - private static BipedBone[] s_BipedBones = new BipedBone[] - { - // body - new BipedBone("Pelvis", (int)HumanBodyBones.Hips), - new BipedBone("L Thigh", (int)HumanBodyBones.LeftUpperLeg), - new BipedBone("R Thigh", (int)HumanBodyBones.RightUpperLeg), - new BipedBone("L Calf", (int)HumanBodyBones.LeftLowerLeg), - new BipedBone("R Calf", (int)HumanBodyBones.RightLowerLeg), - new BipedBone("L Foot", (int)HumanBodyBones.LeftFoot), - new BipedBone("R Foot", (int)HumanBodyBones.RightFoot), - new BipedBone("Spine", (int)HumanBodyBones.Spine), - new BipedBone("Spine1", (int)HumanBodyBones.Chest), - new BipedBone("Spine2", (int)HumanBodyBones.UpperChest), - new BipedBone("Neck", (int)HumanBodyBones.Neck), - new BipedBone("Head", (int)HumanBodyBones.Head), - new BipedBone("L Clavicle", (int)HumanBodyBones.LeftShoulder), - new BipedBone("R Clavicle", (int)HumanBodyBones.RightShoulder), - new BipedBone("L UpperArm", (int)HumanBodyBones.LeftUpperArm), - new BipedBone("R UpperArm", (int)HumanBodyBones.RightUpperArm), - new BipedBone("L Forearm", (int)HumanBodyBones.LeftLowerArm), - new BipedBone("R Forearm", (int)HumanBodyBones.RightLowerArm), - new BipedBone("L Hand", (int)HumanBodyBones.LeftHand), - new BipedBone("R Hand", (int)HumanBodyBones.RightHand), - new BipedBone("L Toe0", (int)HumanBodyBones.LeftToes), - new BipedBone("R Toe0", (int)HumanBodyBones.RightToes), - // Left Hand - new BipedBone("L Finger0", (int)HumanBodyBones.LeftThumbProximal), - new BipedBone("L Finger01", (int)HumanBodyBones.LeftThumbIntermediate), - new BipedBone("L Finger02", (int)HumanBodyBones.LeftThumbDistal), - new BipedBone("L Finger1", (int)HumanBodyBones.LeftIndexProximal), - new BipedBone("L Finger11", (int)HumanBodyBones.LeftIndexIntermediate), - new BipedBone("L Finger12", (int)HumanBodyBones.LeftIndexDistal), - new BipedBone("L Finger2", (int)HumanBodyBones.LeftMiddleProximal), - new BipedBone("L Finger21", (int)HumanBodyBones.LeftMiddleIntermediate), - new BipedBone("L Finger22", (int)HumanBodyBones.LeftMiddleDistal), - new BipedBone("L Finger3", (int)HumanBodyBones.LeftRingProximal), - new BipedBone("L Finger31", (int)HumanBodyBones.LeftRingIntermediate), - new BipedBone("L Finger32", (int)HumanBodyBones.LeftRingDistal), - new BipedBone("L Finger4", (int)HumanBodyBones.LeftLittleProximal), - new BipedBone("L Finger41", (int)HumanBodyBones.LeftLittleIntermediate), - new BipedBone("L Finger42", (int)HumanBodyBones.LeftLittleDistal), - // Right Hand - new BipedBone("R Finger0", (int)HumanBodyBones.RightThumbProximal), - new BipedBone("R Finger01", (int)HumanBodyBones.RightThumbIntermediate), - new BipedBone("R Finger02", (int)HumanBodyBones.RightThumbDistal), - new BipedBone("R Finger1", (int)HumanBodyBones.RightIndexProximal), - new BipedBone("R Finger11", (int)HumanBodyBones.RightIndexIntermediate), - new BipedBone("R Finger12", (int)HumanBodyBones.RightIndexDistal), - new BipedBone("R Finger2", (int)HumanBodyBones.RightMiddleProximal), - new BipedBone("R Finger21", (int)HumanBodyBones.RightMiddleIntermediate), - new BipedBone("R Finger22", (int)HumanBodyBones.RightMiddleDistal), - new BipedBone("R Finger3", (int)HumanBodyBones.RightRingProximal), - new BipedBone("R Finger31", (int)HumanBodyBones.RightRingIntermediate), - new BipedBone("R Finger32", (int)HumanBodyBones.RightRingDistal), - new BipedBone("R Finger4", (int)HumanBodyBones.RightLittleProximal), - new BipedBone("R Finger41", (int)HumanBodyBones.RightLittleIntermediate), - new BipedBone("R Finger42", (int)HumanBodyBones.RightLittleDistal) - }; - - public static bool IsBiped(Transform root, List report) - { - if (report != null) - { - report.Clear(); - } - - Transform[] humanToTransform = new Transform[HumanTrait.BoneCount]; - return MapBipedBones(root, ref humanToTransform, report); - } - - public static Dictionary MapBones(Transform root) - { - Dictionary ret = new Dictionary(); - - Transform[] humanToTransform = new Transform[HumanTrait.BoneCount]; - - if (MapBipedBones(root, ref humanToTransform, null)) - { - for (int boneIter = 0; boneIter < HumanTrait.BoneCount; boneIter++) - { - if (humanToTransform[boneIter] != null) - { - ret.Add(boneIter, humanToTransform[boneIter]); - } - } - } - - // Move upper chest to chest if no chest was found - if (!ret.ContainsKey((int)HumanBodyBones.Chest) && - ret.ContainsKey((int)HumanBodyBones.UpperChest)) - { - ret.Add((int)HumanBodyBones.Chest, ret[(int)HumanBodyBones.UpperChest]); - ret.Remove((int)HumanBodyBones.UpperChest); - } - - return ret; - } - - private static bool MapBipedBones(Transform root, ref Transform[] humanToTransform, List report) - { - for (int bipedBoneIter = 0; bipedBoneIter < s_BipedBones.Length; bipedBoneIter++) - { - int boneIndex = s_BipedBones[bipedBoneIter].index; - - int parentIndex = HumanTrait.GetParentBone(boneIndex); - - bool required = HumanTrait.RequiredBone(boneIndex); - bool parentRequired = parentIndex != -1 ? HumanTrait.RequiredBone(parentIndex) : true; - - Transform parentTransform = parentIndex != -1 ? humanToTransform[parentIndex] : root; - - if (parentTransform == null && !parentRequired) - { - parentIndex = HumanTrait.GetParentBone(parentIndex); - parentRequired = parentIndex != -1 ? HumanTrait.RequiredBone(parentIndex) : true; - parentTransform = parentIndex != -1 ? humanToTransform[parentIndex] : null; - - if (parentTransform == null && !parentRequired) - { - parentIndex = HumanTrait.GetParentBone(parentIndex); - parentTransform = parentIndex != -1 ? humanToTransform[parentIndex] : null; - } - } - - humanToTransform[boneIndex] = MapBipedBone(bipedBoneIter, parentTransform, parentTransform, report); - - if (humanToTransform[boneIndex] == null && required) - { - return false; - } - } - - return true; - } - - private static Transform MapBipedBone(int bipedBoneIndex, Transform transform, Transform parentTransform, List report) - { - Transform ret = null; - - if (transform != null) - { - int childCount = transform.childCount; - - for (int childIter = 0; ret == null && childIter < childCount; childIter++) - { - string boneName = s_BipedBones[bipedBoneIndex].name; - int boneIndex = s_BipedBones[bipedBoneIndex].index; - - if (transform.GetChild(childIter).name.EndsWith(boneName)) - { - ret = transform.GetChild(childIter); - - if (ret != null && report != null && boneIndex != (int)HumanBodyBones.Hips && transform != parentTransform) - { - string current = "- Invalid parent for " + ret.name + ". Expected " + parentTransform.name + ", but found " + transform.name + "."; - - if (boneIndex == (int)HumanBodyBones.LeftUpperLeg || boneIndex == (int)HumanBodyBones.RightUpperLeg) - { - current += " Disable Triangle Pelvis"; - } - else if (boneIndex == (int)HumanBodyBones.LeftShoulder || boneIndex == (int)HumanBodyBones.RightShoulder) - { - current += " Enable Triangle Neck"; - } - else if (boneIndex == (int)HumanBodyBones.Neck) - { - current += " Preferred is three Spine Links"; - } - else if (boneIndex == (int)HumanBodyBones.Head) - { - current += " Preferred is one Neck Links"; - } - - current += "\n"; - - report.Add(current); - } - } - } - - for (int childIter = 0; ret == null && childIter < childCount; childIter++) - { - ret = MapBipedBone(bipedBoneIndex, transform.GetChild(childIter), parentTransform, report); - } - } - - return ret; - } - - internal static void BipedPose(GameObject go, AvatarSetupTool.BoneWrapper[] bones) - { - BipedPose(go.transform, true); - - // Orient Biped - Quaternion rot = AvatarSetupTool.AvatarComputeOrientation(bones); - go.transform.rotation = Quaternion.Inverse(rot) * go.transform.rotation; - - // Move Biped feet to ground plane - AvatarSetupTool.MakeCharacterPositionValid(bones); - } - - private static void BipedPose(Transform t, bool ignore) - { - if (t.name.EndsWith("Pelvis")) - { - t.localRotation = Quaternion.Euler(270, 90, 0); - ignore = false; - } - else if (t.name.EndsWith("Thigh")) - { - t.localRotation = Quaternion.Euler(0, 180, 0); - } - else if (t.name.EndsWith("Toe0")) - { - t.localRotation = Quaternion.Euler(0, 0, 270); - } - else if (t.name.EndsWith("L Clavicle")) - { - t.localRotation = Quaternion.Euler(0, 270, 180); - } - else if (t.name.EndsWith("R Clavicle")) - { - t.localRotation = Quaternion.Euler(0, 90, 180); - } - else if (t.name.EndsWith("L Hand")) - { - t.localRotation = Quaternion.Euler(270, 0, 0); - } - else if (t.name.EndsWith("R Hand")) - { - t.localRotation = Quaternion.Euler(90, 0, 0); - } - else if (t.name.EndsWith("L Finger0")) - { - t.localRotation = Quaternion.Euler(0, 315, 0); - } - else if (t.name.EndsWith("R Finger0")) - { - t.localRotation = Quaternion.Euler(0, 45, 0); - } - else if (!ignore) - { - t.localRotation = Quaternion.identity; - } - - foreach (Transform child in t) - { - BipedPose(child, ignore); - } - } - } -} diff --git a/Editor/Mono/Inspector/Avatar/AvatarColliderEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarColliderEditor.cs deleted file mode 100644 index 05af699d04..0000000000 --- a/Editor/Mono/Inspector/Avatar/AvatarColliderEditor.cs +++ /dev/null @@ -1,243 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class AvatarColliderEditor : AvatarSubEditor - { - // Code below has not been updated to match refactoring work. - // It will have to be updated and cleaned up when we start to implement support for these editors. - /*class Styles - { - public GUIContent CreateCollider = EditorGUIUtility.TrTextContent ("Create Collider"); - public GUIContent UserLayer = EditorGUIUtility.TrTextContent ("Colliders physics layer"); - - public GUILayoutOption[] CreateColliderSize = new GUILayoutOption[] { GUILayout.MaxWidth (60) }; - } - - static Styles styles { get { if (s_Styles == null) s_Styles = new Styles (); return s_Styles; } } - static Styles s_Styles; - - SerializedProperty[] m_Position; - SerializedProperty[] m_Rotation; - SerializedProperty[] m_Scale; - - SerializedProperty m_CreateCollider; - SerializedProperty m_UserLayer; - - //string[] m_HumanBoneName; - - int m_HumanBoneCount; - - protected Transform[] m_Bones; - - static string sCreateCollider = "m_CreateCollider"; - static string sUserLayer = "m_UserLayer"; - static string sColliderPosition = "m_ColliderPosition"; - static string sColliderRotation = "m_ColliderRotation"; - static string sColliderScale = "m_ColliderScale"; - - public AvatarColliderEditor () - { - m_CreateCollider = null; - m_UserLayer = null; - - m_HumanBoneCount = HumanTrait.BoneCount; - - m_Position = new SerializedProperty[m_HumanBoneCount]; - m_Rotation = new SerializedProperty[m_HumanBoneCount]; - m_Scale = new SerializedProperty[m_HumanBoneCount]; - m_Bones = new Transform[m_HumanBoneCount]; - for (int i = 0; i < m_HumanBoneCount; i++) - { - m_Position[i] = null; - m_Rotation[i] = null; - m_Scale[i] = null; - m_Bones[i] = null; - } - } - - internal void Initialize () - { - Transform[] allTransforms = null; - - allTransforms = Object.FindSceneObjectsOfType (typeof (Transform)) as Transform[]; - - //string path = AssetDatabase.GetAssetPath (m_AvatarAsset); - //GameObject mainAsset = AssetDatabase.LoadMainAssetAtPath (path) as GameObject; - //if (mainAsset != null) - //{ - // Transform root = mainAsset.GetComponent (typeof (Transform)) as Transform; - // if (root) - // { - // allTransforms = new Transform[0]; - // ArrayUtility.Add (ref allTransforms, root); - // for (int i = 0; i < allTransforms.Length; i++) - // { - // for (int j = 0; j < allTransforms[i].GetChildCount (); j++) - // ArrayUtility.Add (ref allTransforms, allTransforms[i].GetChild (j)); - // } - // } - //} - - SerializedProperty humanBody = serializedObject.FindProperty (sHuman); - if (humanBody.isArray) - { - for (int i = 0; i < humanBody.arraySize; i++) - { - SerializedProperty boneProperty = humanBody.GetArrayElementAtIndex (i); - if (boneProperty != null) - { - SerializedProperty positionProperty = boneProperty.FindPropertyRelative (sColliderPosition); - SerializedProperty rotationProperty = boneProperty.FindPropertyRelative (sColliderRotation); - SerializedProperty scaleProperty = boneProperty.FindPropertyRelative (sColliderScale); - SerializedProperty boneNameProperty = boneProperty.FindPropertyRelative (sBoneName); - - if (positionProperty != null && rotationProperty != null && scaleProperty != null) - { - m_Position[i] = positionProperty; - m_Rotation[i] = rotationProperty; - m_Scale[i] = scaleProperty; - } - - if (boneNameProperty != null && allTransforms != null) - m_Bones[i] = ArrayUtility.Find (allTransforms, delegate (Transform t) { return t != null && t.name == boneNameProperty.stringValue; }); - } - } - } - } - - public override void OnEnable (AvatarInspector inspector) - { - base.OnEnable (inspector); - m_CreateCollider = serializedObject.FindProperty (sCreateCollider); - m_UserLayer = serializedObject.FindProperty (sUserLayer); - - Initialize (); - - if (gameObject) - { - Animator animator = gameObject.GetComponent (typeof (Animator)) as Animator; - if (animator != null) - { - animator.WriteDefaultPose (); - SceneView.RepaintAll (); - } - } - } - - internal void LayerField (SerializedProperty property, GUIContent label) - { - float height = EditorGUI.GetSinglePropertyHeight (property, label); - Rect position = GUILayoutUtility.GetRect (10, height); - label = EditorGUI.BeginProperty (position, label, property); - - EditorGUI.BeginChangeCheck (); - int newValue = EditorGUI.LayerField (position, label, property.intValue); - if (EditorGUI.EndChangeCheck ()) - property.intValue = newValue; - - EditorGUI.EndProperty (); - } - - public override void OnInspectorGUI () - { - bool wasEnabled = GUI.enabled; - - GUI.enabled = wasEnabled && avatarAsset.IsValid (); - - GUILayout.BeginVertical (GUI.skin.label); - { - EditorGUILayout.Space (); - EditorGUILayout.PropertyField (m_CreateCollider, styles.CreateCollider); - LayerField (m_UserLayer, styles.UserLayer); - - //EditorGUILayout.PropertyField (m_UserLayer, styles.UserLayer); - } - GUILayout.EndVertical (); - - ApplyRevertGUI (); - - GUI.enabled = wasEnabled; - } - - public override void OnSceneGUI () - { - if (gameObject != null) - { - Animator animator = gameObject.GetComponent (typeof (Animator)) as Animator; - if (animator != null) - { - Avatar avatar = animator.GetAvatar (); - - for (int i = 0; i < m_HumanBoneCount; i++) - { - if (HumanTrait.HasCollider (avatar, i)) - { - //AvatarUtility.HumanGetColliderTransform (avatar, i, ); - } - } - - switch (Tools.current) - { - case Tool.Move: - { - // Vector3 newHandleGT = Handles.PositionHandle (handleGT, handleGQ); - // if (newHandleGT != handleGT) - // { - // handleLT = boneInvGQ * (newHandleGT - boneGT); - // handleLT.x /= boneGS.x; - // handleLT.y /= boneGS.y; - // handleLT.z /= boneGS.z; - - // positionP.vector3Value = handleLT; - - // foreach (AvatarInspector ai in Resources.FindObjectsOfTypeAll (typeof (AvatarInspector))) - // ai.Repaint (); - // } - break; - } - case Tool.Rotate: - { - // Quaternion newHandleGQ = Handles.RotationHandle (handleGQ, handleGT); - // if (newHandleGQ != handleGQ) - // { - // Quaternion handleLQ = boneInvGQ * newHandleGQ; - // MathUtils.QuaternionNormalize (ref handleLQ); - // rotationP.quaternionValue = handleLQ; - - // foreach (AvatarInspector ai in Resources.FindObjectsOfTypeAll (typeof (AvatarInspector))) - // ai.Repaint (); - // } - break; - } - case Tool.Scale: - { - // Vector3 newHandleGS = Handles.ScaleHandle (handleGS, handleGT, handleGQ, 0.5f); - // if (newHandleGS != handleGS) - // { - // Vector3 handleLS = newHandleGS; - // handleLS.x /= boneGS.x; - // handleLS.y /= boneGS.y; - // handleLS.z /= boneGS.z; - - // scaleP.vector3Value = handleLS; - - // foreach (AvatarInspector ai in Resources.FindObjectsOfTypeAll (typeof (AvatarInspector))) - // ai.Repaint (); - // } - break; - } - } - } - } - }*/ - } -} diff --git a/Editor/Mono/Inspector/Avatar/AvatarControl.cs b/Editor/Mono/Inspector/Avatar/AvatarControl.cs deleted file mode 100644 index c95dfa60de..0000000000 --- a/Editor/Mono/Inspector/Avatar/AvatarControl.cs +++ /dev/null @@ -1,283 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.Collections.Generic; - -namespace UnityEditor -{ - public enum BodyPart - { - None = -1, - Avatar = 0, - Body, - Head, - LeftArm, - LeftFingers, - RightArm, - RightFingers, - LeftLeg, - RightLeg, - Last - } - - internal class AvatarControl - { - class Styles - { - // IF you change the order of this array, please update: - // BodyPartMapping - // m_BodyPartHumanBone - // BodyPart - - public GUIContent[] Silhouettes = - { - EditorGUIUtility.IconContent("AvatarInspector/BodySilhouette"), - EditorGUIUtility.IconContent("AvatarInspector/HeadZoomSilhouette"), - EditorGUIUtility.IconContent("AvatarInspector/LeftHandZoomSilhouette"), - EditorGUIUtility.IconContent("AvatarInspector/RightHandZoomSilhouette") - }; - - public GUIContent[,] BodyPart = - { - { - null, - EditorGUIUtility.IconContent("AvatarInspector/Torso"), - EditorGUIUtility.IconContent("AvatarInspector/Head"), - EditorGUIUtility.IconContent("AvatarInspector/LeftArm"), - EditorGUIUtility.IconContent("AvatarInspector/LeftFingers"), - EditorGUIUtility.IconContent("AvatarInspector/RightArm"), - EditorGUIUtility.IconContent("AvatarInspector/RightFingers"), - EditorGUIUtility.IconContent("AvatarInspector/LeftLeg"), - EditorGUIUtility.IconContent("AvatarInspector/RightLeg") - }, - { - null, - null, - EditorGUIUtility.IconContent("AvatarInspector/HeadZoom"), - null, - null, - null, - null, - null, - null - }, - { - null, - null, - null, - null, - EditorGUIUtility.IconContent("AvatarInspector/LeftHandZoom"), - null, - null, - null, - null - }, - { - null, - null, - null, - null, - null, - null, - EditorGUIUtility.IconContent("AvatarInspector/RightHandZoom"), - null, - null - }, - }; - } - - static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - static Styles s_Styles; - - public enum BodyPartColor - { - Off = 0x00, - Green = 0x01 << 0, - Red = 0x01 << 1, - IKGreen = 0x01 << 2, - IKRed = 0x01 << 3, - } - - public delegate BodyPartColor BodyPartFeedback(BodyPart bodyPart); - - static public int ShowBoneMapping(int shownBodyView, BodyPartFeedback bodyPartCallback, AvatarSetupTool.BoneWrapper[] bones, SerializedObject serializedObject, AvatarMappingEditor editor) - { - GUILayout.BeginHorizontal(); - { - GUILayout.FlexibleSpace(); - - if (styles.Silhouettes[shownBodyView].image) - { - Rect rect = GUILayoutUtility.GetRect(styles.Silhouettes[shownBodyView], GUIStyle.none, GUILayout.MaxWidth(styles.Silhouettes[shownBodyView].image.width)); - DrawBodyParts(rect, shownBodyView, bodyPartCallback); - - for (int i = 0; i < bones.Length; i++) - DrawBone(shownBodyView, i, rect, bones[i], serializedObject, editor); - } - else - GUILayout.Label("texture missing,\nfix me!"); - - GUILayout.FlexibleSpace(); - } - GUILayout.EndHorizontal(); - - // Body view buttons - Rect buttonsRect = GUILayoutUtility.GetLastRect(); - const float buttonHeight = 16; - string[] labels = new string[] { "Body", "Head", "Left Hand", "Right Hand"}; - buttonsRect.x += 5; - buttonsRect.width = 70; - buttonsRect.yMin = buttonsRect.yMax - (buttonHeight * 4 + 5); - buttonsRect.height = buttonHeight; - for (int i = 0; i < labels.Length; i++) - { - if (GUI.Toggle(buttonsRect, shownBodyView == i, labels[i], EditorStyles.miniButton)) - shownBodyView = i; - buttonsRect.y += buttonHeight; - } - - return shownBodyView; - } - - static public void DrawBodyParts(Rect rect, int shownBodyView, BodyPartFeedback bodyPartCallback) - { - GUI.color = new Color(0.2f, 0.2f, 0.2f, 1.0f); - if (styles.Silhouettes[shownBodyView] != null) - GUI.DrawTexture(rect, styles.Silhouettes[shownBodyView].image); - for (int i = 1; i < (int)BodyPart.Last; i++) - DrawBodyPart(shownBodyView, i, rect, bodyPartCallback((BodyPart)i)); - } - - static protected void DrawBodyPart(int shownBodyView, int i, Rect rect, BodyPartColor bodyPartColor) - { - if (styles.BodyPart[shownBodyView, i] != null && styles.BodyPart[shownBodyView, i].image != null) - { - if ((bodyPartColor & BodyPartColor.Green) == BodyPartColor.Green) - GUI.color = Color.green; - else if ((bodyPartColor & BodyPartColor.Red) == BodyPartColor.Red) - GUI.color = Color.red; - else - GUI.color = Color.gray; - GUI.DrawTexture(rect, styles.BodyPart[shownBodyView, i].image); - GUI.color = Color.white; - } - } - - static Vector2[,] s_BonePositions = new Vector2[4, HumanTrait.BoneCount]; - - public static List GetViewsThatContainBone(int bone) - { - List views = new List(); - - if (bone < 0 || bone >= HumanTrait.BoneCount) - return views; - - for (int i = 0; i < 4; i++) - { - if (s_BonePositions[i, bone] != Vector2.zero) - views.Add(i); - } - return views; - } - - static AvatarControl() - { - // Body view - int view = 0; - // hips - s_BonePositions[view, (int)HumanBodyBones.Hips] = new Vector2(0.00f, 0.08f); - - // upper leg - s_BonePositions[view, (int)HumanBodyBones.LeftUpperLeg] = new Vector2(0.16f, 0.01f); - s_BonePositions[view, (int)HumanBodyBones.RightUpperLeg] = new Vector2(-0.16f, 0.01f); - - // lower leg - s_BonePositions[view, (int)HumanBodyBones.LeftLowerLeg] = new Vector2(0.21f, -0.40f); - s_BonePositions[view, (int)HumanBodyBones.RightLowerLeg] = new Vector2(-0.21f, -0.40f); - - // foot - s_BonePositions[view, (int)HumanBodyBones.LeftFoot] = new Vector2(0.23f, -0.80f); - s_BonePositions[view, (int)HumanBodyBones.RightFoot] = new Vector2(-0.23f, -0.80f); - - // spine - head - s_BonePositions[view, (int)HumanBodyBones.Spine] = new Vector2(0.00f, 0.20f); - s_BonePositions[view, (int)HumanBodyBones.Chest] = new Vector2(0.00f, 0.35f); - s_BonePositions[view, (int)HumanBodyBones.UpperChest] = new Vector2(0.00f, 0.50f); - s_BonePositions[view, (int)HumanBodyBones.Neck] = new Vector2(0.00f, 0.66f); - s_BonePositions[view, (int)HumanBodyBones.Head] = new Vector2(0.00f, 0.76f); - - // shoulder - s_BonePositions[view, (int)HumanBodyBones.LeftShoulder] = new Vector2(0.14f, 0.60f); - s_BonePositions[view, (int)HumanBodyBones.RightShoulder] = new Vector2(-0.14f, 0.60f); - - // upper arm - s_BonePositions[view, (int)HumanBodyBones.LeftUpperArm] = new Vector2(0.30f, 0.57f); - s_BonePositions[view, (int)HumanBodyBones.RightUpperArm] = new Vector2(-0.30f, 0.57f); - - // lower arm - s_BonePositions[view, (int)HumanBodyBones.LeftLowerArm] = new Vector2(0.48f, 0.30f); - s_BonePositions[view, (int)HumanBodyBones.RightLowerArm] = new Vector2(-0.48f, 0.30f); - - // hand - s_BonePositions[view, (int)HumanBodyBones.LeftHand] = new Vector2(0.66f, 0.03f); - s_BonePositions[view, (int)HumanBodyBones.RightHand] = new Vector2(-0.66f, 0.03f); - - // toe - s_BonePositions[view, (int)HumanBodyBones.LeftToes] = new Vector2(0.25f, -0.89f); - s_BonePositions[view, (int)HumanBodyBones.RightToes] = new Vector2(-0.25f, -0.89f); - - // Head view - view = 1; - // neck - head - s_BonePositions[view, (int)HumanBodyBones.Neck] = new Vector2(-0.20f, -0.62f); - s_BonePositions[view, (int)HumanBodyBones.Head] = new Vector2(-0.15f, -0.30f); - // left, right eye - s_BonePositions[view, (int)HumanBodyBones.LeftEye] = new Vector2(0.63f, 0.16f); - s_BonePositions[view, (int)HumanBodyBones.RightEye] = new Vector2(0.15f, 0.16f); - // jaw - s_BonePositions[view, (int)HumanBodyBones.Jaw] = new Vector2(0.45f, -0.40f); - - // Left hand view - view = 2; - // finger bases, thumb - little - s_BonePositions[view, (int)HumanBodyBones.LeftThumbProximal] = new Vector2(-0.35f, 0.11f); - s_BonePositions[view, (int)HumanBodyBones.LeftIndexProximal] = new Vector2(0.19f, 0.11f); - s_BonePositions[view, (int)HumanBodyBones.LeftMiddleProximal] = new Vector2(0.22f, 0.00f); - s_BonePositions[view, (int)HumanBodyBones.LeftRingProximal] = new Vector2(0.16f, -0.12f); - s_BonePositions[view, (int)HumanBodyBones.LeftLittleProximal] = new Vector2(0.09f, -0.23f); - - // finger tips, thumb - little - s_BonePositions[view, (int)HumanBodyBones.LeftThumbDistal] = new Vector2(-0.03f, 0.33f); - s_BonePositions[view, (int)HumanBodyBones.LeftIndexDistal] = new Vector2(0.65f, 0.16f); - s_BonePositions[view, (int)HumanBodyBones.LeftMiddleDistal] = new Vector2(0.74f, 0.00f); - s_BonePositions[view, (int)HumanBodyBones.LeftRingDistal] = new Vector2(0.66f, -0.14f); - s_BonePositions[view, (int)HumanBodyBones.LeftLittleDistal] = new Vector2(0.45f, -0.25f); - - // finger middles, thumb - little - for (int i = 0; i < 5; i++) - 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); - - // Right hand view - view = 3; - for (int i = 0; i < 15; i++) - s_BonePositions[view, (int)HumanBodyBones.LeftThumbProximal + i + 15] = Vector2.Scale(s_BonePositions[view - 1, (int)HumanBodyBones.LeftThumbProximal + i], new Vector2(-1, 1)); - } - - static protected void DrawBone(int shownBodyView, int i, Rect rect, AvatarSetupTool.BoneWrapper bone, SerializedObject serializedObject, AvatarMappingEditor editor) - { - if (s_BonePositions[shownBodyView, i] == Vector2.zero) - return; - - Vector2 pos = s_BonePositions[shownBodyView, i]; - pos.y *= -1; // because higher values should be up - pos.Scale(new Vector2(rect.width * 0.5f, rect.height * 0.5f)); - pos = rect.center + pos; - int kIconSize = AvatarSetupTool.BoneWrapper.kIconSize; - Rect r = new Rect(pos.x - kIconSize * 0.5f, pos.y - kIconSize * 0.5f, kIconSize, kIconSize); - bone.BoneDotGUI(r, r, i, true, true, true, serializedObject, editor); - } - } -} diff --git a/Editor/Mono/Inspector/Avatar/AvatarEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarEditor.cs deleted file mode 100644 index ec823adc5f..0000000000 --- a/Editor/Mono/Inspector/Avatar/AvatarEditor.cs +++ /dev/null @@ -1,660 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.SceneManagement; -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; -using UnityEngine.SceneManagement; - -namespace UnityEditor -{ - [System.Serializable] - internal class AvatarSubEditor : ScriptableObject - { - /* - // Will be used to patch animation when handiness changes. - public class AvatarSetter : AssetPostprocessor - { - public void OnPostprocessModel(GameObject go) - { - ModelImporter modelImporter = (ModelImporter)assetImporter; - ModelImporterEditor inspector = ActiveEditorTracker.MakeCustomEditor(modelImporter) as ModelImporterEditor; - - SerializedProperty humanDescription = inspector.serializedObject.FindProperty("m_HumanDescription"); - - Avatar avatar = AssetDatabase.LoadAssetAtPath("Assets/1_Characters/Dude/Dude.fbx", typeof(UnityEngine.Avatar)) as Avatar; - if (avatar == null) - Debug.Log("Could not find avatar when importing : " + modelImporter.assetPath); - - if (avatar != null && modelImporter != null) - modelImporter.UpdateHumanDescription(avatar, humanDescription); - - EditorUtility.SetDirty(inspector); - EditorUtility.SetDirty(modelImporter); - } - } - */ - - //[MenuItem ("Mecanim/Write All Assets")] - static void DoWriteAllAssets() - { - UnityEngine.Object[] objects = Resources.FindObjectsOfTypeAll(typeof(UnityEngine.Object)); - foreach (UnityEngine.Object asset in objects) - { - if (AssetDatabase.Contains(asset)) - EditorUtility.SetDirty(asset); - } - AssetDatabase.SaveAssets(); - } - - protected AvatarEditor m_Inspector; - protected GameObject gameObject { get { return m_Inspector.m_GameObject; } } - protected GameObject prefab { get { return m_Inspector.prefab; } } - protected Dictionary modelBones { get { return m_Inspector.m_ModelBones; } } - protected Transform root { get { return gameObject == null ? null : gameObject.transform; } } - protected SerializedObject serializedObject { get { return m_Inspector.serializedAssetImporter; } } - protected Avatar avatarAsset { get { return m_Inspector.avatar; } } - - public virtual void Enable(AvatarEditor inspector) - { - this.m_Inspector = inspector; - } - - public virtual void Disable() - { - } - - public virtual void OnDestroy() - { - if (HasModified()) - { - AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(avatarAsset)); - if (importer) - { - if (EditorUtility.DisplayDialog("Unapplied import settings", "Unapplied import settings for \'" + importer.assetPath + "\'", "Apply", "Revert")) - ApplyAndImport(); - else - ResetValues(); - } - } - } - - public virtual void OnInspectorGUI() - { - } - - public virtual void OnSceneGUI() - { - } - - protected bool HasModified() - { - if (!m_Inspector) - return false; - if (serializedObject.hasModifiedProperties) - return true; - - return false; - } - - protected virtual void ResetValues() - { - serializedObject.Update(); - } - - protected void Apply() - { - serializedObject.ApplyModifiedProperties(); - } - - public void ApplyAndImport() - { - Apply(); - - string assetPath = AssetDatabase.GetAssetPath(avatarAsset); - AssetDatabase.ImportAsset(assetPath); - - ResetValues(); - } - - protected void ApplyRevertGUI() - { - EditorGUILayout.Space(); - - using (new GUILayout.HorizontalScope()) - { - using (new EditorGUI.DisabledScope(!HasModified())) - { - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Revert")) - { - ResetValues(); - System.Diagnostics.Debug.Assert(!HasModified(), "Avatar settings are marked as modified after calling Reset."); - } - - if (GUILayout.Button("Apply")) - { - ApplyAndImport(); - } - } - - if (GUILayout.Button("Done")) - { - m_Inspector.SwitchToAssetMode(); - GUIUtility.ExitGUI(); - } - } - } - } - - [CustomEditor(typeof(Avatar))] - internal class AvatarEditor : Editor - { - private class Styles - { - public GUIContent[] tabs = - { - EditorGUIUtility.TrTextContent("Mapping"), - EditorGUIUtility.TrTextContent("Muscles & Settings"), - //EditorGUIUtility.TrTextContent ("Handle"), - //EditorGUIUtility.TrTextContent ("Collider") - }; - - public GUIContent editCharacter = EditorGUIUtility.TrTextContent("Configure Avatar"); - - public GUIContent reset = EditorGUIUtility.TrTextContent("Reset"); - } - - static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - static Styles s_Styles; - - enum EditMode - { - NotEditing, - Starting, - Editing, - Stopping - } - - protected int m_TabIndex; - internal GameObject m_GameObject; - internal Dictionary m_ModelBones = null; - private EditMode m_EditMode = EditMode.NotEditing; - internal bool m_CameFromImportSettings = false; - private bool m_SwitchToEditMode = false; - internal static bool s_EditImmediatelyOnNextOpen = false; - - private SceneSetup[] sceneSetup; - - // These member are used when the avatar is part of an asset - // This is used as a backend by the AvatarSubEditors to serialize - // only the FBXImporter part and not mess up with the Editor's serializedObject. - internal SerializedObject m_SerializedAssetImporter = null; - public SerializedObject serializedAssetImporter - { - get - { - // TODO find a better sync for that and be in better control of the lifetime - if (m_SerializedAssetImporter == null) - { - m_SerializedAssetImporter = CreateSerializedImporterForTarget(target); - } - return m_SerializedAssetImporter; - } - } - - internal Avatar avatar { get { return target as Avatar; } } - - protected bool m_InspectorLocked; - - [Serializable] - protected class SceneStateCache - { - public SceneView view; - public SceneView.SceneViewState state; - } - - protected List m_SceneStates; - - // We'd prefer to have just one AvatarEditor member but due to Serialization issues, - // we need to keep one of each type. It should still be treated as a single one though. - // I.e. only one should be used at a time; the rest should be null. - protected AvatarSubEditor editor - { - get - { - switch (m_TabIndex) - { - case sMuscleTab: return m_MuscleEditor; - case sHandleTab: return m_HandleEditor; - case sColliderTab: return m_ColliderEditor; - default: - case sMappingTab: return m_MappingEditor; - } - } - set - { - switch (m_TabIndex) - { - case sMuscleTab: m_MuscleEditor = value as AvatarMuscleEditor; break; - case sHandleTab: m_HandleEditor = value as AvatarHandleEditor; break; - case sColliderTab: m_ColliderEditor = value as AvatarColliderEditor; break; - default: - case sMappingTab: m_MappingEditor = value as AvatarMappingEditor; break; - } - } - } - private AvatarMuscleEditor m_MuscleEditor; - private AvatarHandleEditor m_HandleEditor; - private AvatarColliderEditor m_ColliderEditor; - private AvatarMappingEditor m_MappingEditor; - - const int sMappingTab = 0; - const int sMuscleTab = 1; - const int sHandleTab = 2; - const int sColliderTab = 3; - const int sDefaultTab = sMappingTab; - - public GameObject prefab - { - get - { - string path = AssetDatabase.GetAssetPath(target); - return AssetDatabase.LoadMainAssetAtPath(path) as GameObject; - } - } - - static private SerializedObject CreateSerializedImporterForTarget(UnityEngine.Object target) - { - SerializedObject so = null; - AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(target)); - if (importer != null) - { - so = new SerializedObject(importer); - } - return so; - } - - void OnEnable() - { - EditorApplication.update += Update; - m_SwitchToEditMode = false; - if (m_EditMode == EditMode.Editing) - { - m_ModelBones = AvatarSetupTool.GetModelBones(m_GameObject.transform, false, null); - editor.Enable(this); - } - else if (m_EditMode == EditMode.NotEditing) - { - editor = null; - - if (s_EditImmediatelyOnNextOpen) - { - m_CameFromImportSettings = true; - s_EditImmediatelyOnNextOpen = false; - } - } - } - - void OnDisable() - { - if (m_EditMode == EditMode.Editing) - editor.Disable(); - - EditorApplication.update -= Update; - - if (m_SerializedAssetImporter != null) - { - m_SerializedAssetImporter.Cache(GetInstanceID()); - m_SerializedAssetImporter = null; - } - } - - void OnDestroy() - { - // If we are in Edit mode, we need to switch back to asset mode first - if (m_EditMode == EditMode.Editing) - SwitchToAssetMode(); - } - - void SelectAsset() - { - UnityEngine.Object obj; - if (m_CameFromImportSettings) - { - string path = AssetDatabase.GetAssetPath(target); - obj = AssetDatabase.LoadMainAssetAtPath(path); - } - else - obj = target; - - Selection.activeObject = obj; - } - - protected void CreateEditor() - { - switch (m_TabIndex) - { - case sMuscleTab: editor = ScriptableObject.CreateInstance(); break; - case sHandleTab: editor = ScriptableObject.CreateInstance(); break; - case sColliderTab: editor = ScriptableObject.CreateInstance(); break; - default: - case sMappingTab: editor = ScriptableObject.CreateInstance(); break; - } - - editor.hideFlags = HideFlags.HideAndDontSave; - editor.Enable(this); - } - - protected void DestroyEditor() - { - editor.OnDestroy(); - editor = null; - } - - // @TODO@MECANIM: Implement context Reset - probably best in C++ - /*[MenuItem ("CONTEXT/Avatar/Reset")] - static void ResetValues (MenuCommand command) - { - Debug.Log ("Reset"); - - AssetImporter importer = AssetImporter.GetAtPath (AssetDatabase.GetAssetPath (command.context)); - SerializedObject serializedObject = new SerializedObject (importer); - - if (importer && serializedObject != null) - { - string sHuman = "m_HumanDescription.m_Human"; - string sSkeleton = "m_HumanDescription.m_Skeleton"; - SerializedProperty human = serializedObject.FindProperty (sHuman); - if (human != null && human.isArray) - human.ClearArray (); - - SerializedProperty skeleton = serializedObject.FindProperty (sSkeleton); - if (skeleton != null && skeleton.isArray) - skeleton.ClearArray (); - - if (GetCurrentEditor () != null) - { - GetCurrentEditor ().ApplyAndImport (); - GetCurrentEditor ().OnEnable (this); - } - } - }*/ - - public override bool UseDefaultMargins() { return false; } - - public override void OnInspectorGUI() - { - GUI.enabled = true; - - using (new EditorGUILayout.VerticalScope(EditorStyles.inspectorFullWidthMargins)) - { - if (m_EditMode == EditMode.Editing) - { - EditingGUI(); - } - else if (!m_CameFromImportSettings) - { - EditButtonGUI(); - } - else - { - if (m_EditMode == EditMode.NotEditing && Event.current.type == EventType.Repaint) - { - m_SwitchToEditMode = true; - } - } - } - } - - void EditButtonGUI() - { - if (avatar == null || !avatar.isHuman) - return; - - // Can only edit avatar from a model importer - string assetPath = AssetDatabase.GetAssetPath(avatar); - ModelImporter modelImporter = AssetImporter.GetAtPath(assetPath) as ModelImporter; - if (modelImporter == null) - return; - - using (new EditorGUILayout.HorizontalScope()) - { - GUILayout.FlexibleSpace(); - if (GUILayout.Button(styles.editCharacter, GUILayout.Width(120)) && - EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) - { - SwitchToEditMode(); - GUIUtility.ExitGUI(); - } - - GUILayout.FlexibleSpace(); - } - } - - void EditingGUI() - { - using (new EditorGUILayout.HorizontalScope()) - { - GUILayout.FlexibleSpace(); - { - int tabIndex = m_TabIndex; - bool wasEnable = GUI.enabled; - GUI.enabled = !(avatar == null || !avatar.isHuman); - tabIndex = GUILayout.Toolbar(tabIndex, styles.tabs, "LargeButton", - GUI.ToolbarButtonSize.FitToContents); - GUI.enabled = wasEnable; - if (tabIndex != m_TabIndex) - { - DestroyEditor(); - if (avatar != null && avatar.isHuman) - m_TabIndex = tabIndex; - - CreateEditor(); - } - } - GUILayout.FlexibleSpace(); - } - - editor.OnInspectorGUI(); - } - - public void OnSceneGUI() - { - if (m_EditMode == EditMode.Editing) - editor.OnSceneGUI(); - } - - internal void SwitchToEditMode() - { - m_EditMode = EditMode.Starting; - - // Lock inspector - ChangeInspectorLock(true); - - // Store current setup in hierarchy - sceneSetup = EditorSceneManager.GetSceneManagerSetup(); - - // Load temp scene - Scene scene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); - scene.name = "Avatar Configuration"; - - // Instantiate character - m_GameObject = Instantiate(prefab) as GameObject; - if (serializedAssetImporter.FindProperty("m_OptimizeGameObjects").boolValue) - AnimatorUtility.DeoptimizeTransformHierarchy(m_GameObject); - - // First get all available modelBones - Dictionary modelBones = AvatarSetupTool.GetModelBones(m_GameObject.transform, true, null); - AvatarSetupTool.BoneWrapper[] humanBones = AvatarSetupTool.GetHumanBones(serializedAssetImporter, modelBones); - - m_ModelBones = AvatarSetupTool.GetModelBones(m_GameObject.transform, false, humanBones); - - Selection.activeObject = m_GameObject; - - // Unfold all nodes in hierarchy - // TODO@MECANIM: Only expand actual bones - foreach (SceneHierarchyWindow shw in Resources.FindObjectsOfTypeAll(typeof(SceneHierarchyWindow))) - shw.SetExpandedRecursive(m_GameObject.GetInstanceID(), true); - CreateEditor(); - - m_EditMode = EditMode.Editing; - - // Frame in scene view - m_SceneStates = new List(); - foreach (SceneView s in SceneView.sceneViews) - { - m_SceneStates.Add(new SceneStateCache {state = new SceneView.SceneViewState(s.sceneViewState), view = s}); - s.sceneViewState.showFlares = false; - s.sceneViewState.showMaterialUpdate = false; - s.sceneViewState.showFog = false; - s.sceneViewState.showSkybox = false; - s.sceneViewState.showImageEffects = false; - s.sceneViewState.showParticleSystems = false; - s.FrameSelected(); - } - } - - internal void SwitchToAssetMode() - { - foreach (var state in m_SceneStates) - { - if (state.view == null) - continue; - - state.view.sceneViewState.showFog = state.state.showFog; - state.view.sceneViewState.showFlares = state.state.showFlares; - state.view.sceneViewState.showMaterialUpdate = state.state.showMaterialUpdate; - state.view.sceneViewState.showSkybox = state.state.showSkybox; - state.view.sceneViewState.showImageEffects = state.state.showImageEffects; - state.view.sceneViewState.showParticleSystems = state.state.showParticleSystems; - } - - m_EditMode = EditMode.Stopping; - - DestroyEditor(); - - ChangeInspectorLock(m_InspectorLocked); - - // if the user started play mode While in Edit mode it not clear what we should do - // for now let the active scene open and do nothing - if (!EditorApplication.isPlaying) - { - EditorApplication.CallbackFunction CleanUpSceneOnDestroy = null; - CleanUpSceneOnDestroy = () => - { - string currentScene = SceneManager.GetActiveScene().path; - if (currentScene.Length > 0) - { - // in this case the user did save manually the current scene and want to keep it or - // he did open a new scene - // do nothing - } - // Restore scene that was loaded when user pressed Configure button - else if (sceneSetup != null && sceneSetup.Length > 0) - { - EditorSceneManager.RestoreSceneManagerSetup(sceneSetup); - sceneSetup = null; - } - else - EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); - - // Make sure that we restore the "original" selection - // globally. - // This should really be done in a more controlled manner - // so that a globally important/observable state (i.e. selection) is not set - // in a "random" very granular piece of control flow and - // by an unrelated editor for which it is not the responsability to do so. - - SelectAsset(); - - if (!m_CameFromImportSettings) - m_EditMode = EditMode.NotEditing; - - EditorApplication.update -= CleanUpSceneOnDestroy; - }; - - EditorApplication.update += CleanUpSceneOnDestroy; - } - - // Reset back the Edit Mode specific states (they probably should be better encapsulated) - m_GameObject = null; - m_ModelBones = null; - } - - void ChangeInspectorLock(bool locked) - { - foreach (InspectorWindow i in InspectorWindow.GetAllInspectorWindows()) - { - ActiveEditorTracker activeEditor = i.tracker; - foreach (Editor e in activeEditor.activeEditors) - { - if (e == this) - { - m_InspectorLocked = i.isLocked; - i.isLocked = locked; - } - } - } - } - - public void Update() - { - if (m_SwitchToEditMode) - { - m_SwitchToEditMode = false; - SwitchToEditMode(); - - Repaint(); - } - - if (m_EditMode == EditMode.Editing) - { - if (m_GameObject == null || m_ModelBones == null || EditorApplication.isPlaying) - SwitchToAssetMode(); - - else if (m_ModelBones != null) - { - foreach (KeyValuePair pair in m_ModelBones) - { - if (pair.Key == null) - { - SwitchToAssetMode(); - return; - } - } - } - } - } - - public bool HasFrameBounds() - { - if (m_ModelBones != null) - { - foreach (KeyValuePair pair in m_ModelBones) - { - if (pair.Key == Selection.activeTransform) - return true; - } - } - - return false; - } - - public Bounds OnGetFrameBounds() - { - Transform bone = Selection.activeTransform; - Bounds bounds = new Bounds(bone.position, new Vector3(0, 0, 0)); - foreach (Transform child in bone) - bounds.Encapsulate(child.position); - - if (bone.parent) bounds.Encapsulate(bone.parent.position); - - return bounds; - } - } -} diff --git a/Editor/Mono/Inspector/Avatar/AvatarHandleEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarHandleEditor.cs deleted file mode 100644 index 93d39d7161..0000000000 --- a/Editor/Mono/Inspector/Avatar/AvatarHandleEditor.cs +++ /dev/null @@ -1,466 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class AvatarHandleEditor : AvatarSubEditor - { - // Code below has not been updated to match refactoring work. - // It will have to be updated and cleaned up when we start to implement support for these editors. - /*class Styles - { - static public int FoldoutSize = 20; - - public int AlignTransform = FoldoutSize; - - public GUIContent Position = EditorGUIUtility.TrTextContent ("Position"); - public GUIContent Rotation = EditorGUIUtility.TrTextContent ("Rotation"); - public GUIContent Scale = EditorGUIUtility.TrTextContent ("Scale"); - public GUIContent LookAt = EditorGUIUtility.TrTextContent ("Look At"); - - public GUILayoutOption[] ToggleSize = new GUILayoutOption[] { GUILayout.MaxWidth (FoldoutSize) }; - - } - - static Styles styles { get { if (s_Styles == null) s_Styles = new Styles (); return s_Styles; } } - static Styles s_Styles; - - Transform[] m_Transforms; - - bool[] m_Toggle; - - SerializedProperty m_HandleList; - - string[] m_HumanBoneName; - - string[] m_BoneName; - - static string sHandles = "m_HumanDescription.m_Handles"; - static string sLookAt = "m_LookAt"; - - static string sDefaultHandleName = "Handle"; - - public AvatarHandleEditor () - { - m_Transforms = null; - m_Toggle = null; - m_BoneName = null; - - m_HumanBoneName = HumanTrait.BoneName; - } - - internal void Initialize () - { - if (m_HandleList != null && m_HandleList.isArray) - { - m_Toggle = new bool[m_HandleList.arraySize]; - for (int i = 0; i < m_HandleList.arraySize; i++) - { - m_Toggle[i] = false; - } - } - - SerializedProperty humanBody = serializedObject.FindProperty (sHuman); - if (humanBody.isArray) - { - m_BoneName = new string[0]; - for (int i = 0; i < humanBody.arraySize; i++) - { - SerializedProperty boneProperty = humanBody.GetArrayElementAtIndex (i); - if (boneProperty != null) - { - SerializedProperty humanNameProperty = boneProperty.FindPropertyRelative (sHumanName); - SerializedProperty boneNameProperty = boneProperty.FindPropertyRelative (sBoneName); - if (boneNameProperty != null && humanNameProperty != null) - { - // Add only human body bone, hand are not supported for now - int index = ArrayUtility.FindIndex (m_HumanBoneName, delegate (string s) { return s == humanNameProperty.stringValue; }); - if (index != -1 && index < (int)HumanBodyBones.LastBone) - ArrayUtility.Add (ref m_BoneName, boneNameProperty.stringValue); - } - } - } - } - } - - public override void OnEnable (AvatarInspector inspector) - { - base.OnEnable (inspector); - - m_HandleList = serializedObject.FindProperty (sHandles); - - m_Transforms = Object.FindSceneObjectsOfType (typeof (Transform)) as Transform[]; - - Initialize (); - - if (gameObject) - { - Animator animator = gameObject.GetComponent (typeof (Animator)) as Animator; - if (animator != null) - { - animator.WriteDefaultPose (); - SceneView.RepaintAll (); - } - } - } - - public override void OnInspectorGUI () - { - bool wasEnabled = GUI.enabled; - - GUI.enabled = wasEnabled && avatarAsset.IsValid (); - - DisplayHandles (); - - ApplyRevertGUI (); - - GUI.enabled = wasEnabled; - } - - public override void OnSceneGUI () - { - if (gameObject != null) - { - Animator animator = gameObject.GetComponent (typeof (Animator)) as Animator; - if (m_Transforms != null && animator != null && m_HandleList != null && m_HandleList.isArray) - { - for (int i = 0; i < m_HandleList.arraySize; i++) - { - SerializedProperty handleP = m_HandleList.GetArrayElementAtIndex (i); - SerializedProperty positionP = handleP.FindPropertyRelative (sPosition); - SerializedProperty rotationP = handleP.FindPropertyRelative (sRotation); - SerializedProperty scaleP = handleP.FindPropertyRelative (sScale); - //SerializedProperty nameP = handleP.FindPropertyRelative (sName); - SerializedProperty boneNameP = handleP.FindPropertyRelative (sBoneName); - - int index = ArrayUtility.FindIndex (m_Transforms, delegate (Transform t) { return t.name == boneNameP.stringValue; }); - if (index != -1) - { - Vector3 boneGT = m_Transforms[index].position; - Quaternion boneGQ = m_Transforms[index].rotation; - Quaternion boneInvGQ = Quaternion.Inverse (boneGQ); - Vector3 boneGS = m_Transforms[index].lossyScale; - - Vector3 handleLT = positionP.vector3Value; - handleLT.x *= boneGS.x; - handleLT.y *= boneGS.y; - handleLT.z *= boneGS.z; - - Vector3 handleGT = boneGT + (boneGQ * handleLT); - Quaternion handleGQ = boneGQ * rotationP.quaternionValue; - Vector3 handleGS = scaleP.vector3Value; - - MathUtils.QuaternionNormalize (ref handleGQ); - - handleGS.x *= boneGS.x; - handleGS.y *= boneGS.y; - handleGS.z *= boneGS.z; - - switch (Tools.current) - { - case Tool.Move: - { - Vector3 newHandleGT = Handles.PositionHandle (handleGT, handleGQ); - if (newHandleGT != handleGT) - { - handleLT = boneInvGQ * (newHandleGT - boneGT); - handleLT.x /= boneGS.x; - handleLT.y /= boneGS.y; - handleLT.z /= boneGS.z; - - positionP.vector3Value = handleLT; - - foreach (AvatarInspector ai in Resources.FindObjectsOfTypeAll (typeof (AvatarInspector))) - ai.Repaint (); - } - break; - } - case Tool.Rotate: - { - Quaternion newHandleGQ = Handles.RotationHandle (handleGQ, handleGT); - if (newHandleGQ != handleGQ) - { - Quaternion handleLQ = boneInvGQ * newHandleGQ; - MathUtils.QuaternionNormalize (ref handleLQ); - rotationP.quaternionValue = handleLQ; - - foreach (AvatarInspector ai in Resources.FindObjectsOfTypeAll (typeof (AvatarInspector))) - ai.Repaint (); - } - break; - } - case Tool.Scale: - { - Vector3 newHandleGS = Handles.ScaleHandle (handleGS, handleGT, handleGQ, 0.5f); - if (newHandleGS != handleGS) - { - Vector3 handleLS = newHandleGS; - handleLS.x /= boneGS.x; - handleLS.y /= boneGS.y; - handleLS.z /= boneGS.z; - - scaleP.vector3Value = handleLS; - - foreach (AvatarInspector ai in Resources.FindObjectsOfTypeAll (typeof (AvatarInspector))) - ai.Repaint (); - } - break; - } - } - } - } - } - } - } - - protected void DisplayHandles () - { - int deleteHandle = -1; - GUILayout.BeginVertical (GUI.skin.label); - { - if (m_HandleList != null && m_HandleList.isArray) - { - for (int i = 0; i < m_HandleList.arraySize; i++) - { - SerializedProperty handleP = m_HandleList.GetArrayElementAtIndex (i); - SerializedProperty nameP = handleP.FindPropertyRelative (sName); - SerializedProperty boneNameP = handleP.FindPropertyRelative (sBoneName); - - GUILayout.BeginHorizontal (GUI.skin.label); - { - m_Toggle[i] = GUILayout.Toggle (m_Toggle[i], "", EditorStyles.foldout, styles.ToggleSize); - - string name = nameP.stringValue; - name = EditorGUILayout.TextField (name); - if (name != nameP.stringValue) - { - string[] names = GetHandlesName (); - nameP.stringValue = GenerateUniqueHandleName (name, names); - } - - int option = ArrayUtility.FindIndex (m_BoneName, delegate (string s){return s == boneNameP.stringValue;} ); - option = EditorGUILayout.Popup (option, m_BoneName); - if (boneNameP.stringValue != m_BoneName[option]) - { - boneNameP.stringValue = m_BoneName[option]; - SceneView.RepaintAll (); - } - - if (GUILayout.Button (GUIContent.none, "OL Minus")) - deleteHandle = i; - } - GUILayout.EndHorizontal (); - - if (m_Toggle[i]) - { - SerializedProperty boneP = FindHumanBone (serializedObject, m_HumanBoneName[ (int)HumanBodyBones.Head], false); - if (boneP != null) - { - SerializedProperty avatarBoneNameP = boneP.FindPropertyRelative (sBoneName); - if (avatarBoneNameP != null && avatarBoneNameP.stringValue == boneNameP.stringValue) - { - GUILayout.BeginHorizontal (GUI.skin.label); - { - GUILayout.Space (styles.AlignTransform); - SerializedProperty lookAtP = handleP.FindPropertyRelative (sLookAt); - bool isLookAt = lookAtP.boolValue; - isLookAt = GUILayout.Toggle (isLookAt, styles.LookAt); - if (isLookAt != lookAtP.boolValue) - lookAtP.boolValue = isLookAt; - } - GUILayout.EndHorizontal (); - } - } - - SerializedProperty positionP = handleP.FindPropertyRelative (sPosition); - SerializedProperty rotationP = handleP.FindPropertyRelative (sRotation); - SerializedProperty scaleP = handleP.FindPropertyRelative (sScale); - - GUILayout.BeginHorizontal (GUI.skin.label); - { - GUILayout.Space (styles.AlignTransform); - - Vector3 value = positionP.vector3Value; - value = EditorGUILayout.Vector3Field (styles.Position.text, value); - if (value != positionP.vector3Value) - { - positionP.vector3Value = value; - SceneView.RepaintAll (); - } - } - GUILayout.EndHorizontal (); - - GUILayout.BeginHorizontal (GUI.skin.label); - { - GUILayout.Space (styles.AlignTransform); - - Vector3 value = rotationP.quaternionValue.eulerAngles; - value = EditorGUILayout.Vector3Field (styles.Rotation.text, value); - if (value != rotationP.quaternionValue.eulerAngles) - { - Quaternion q = new Quaternion (); - q.eulerAngles = value; - rotationP.quaternionValue = q; - SceneView.RepaintAll (); - } - } - GUILayout.EndHorizontal (); - - GUILayout.BeginHorizontal (GUI.skin.label); - { - GUILayout.Space (styles.AlignTransform); - - Vector3 value = scaleP.vector3Value; - value = EditorGUILayout.Vector3Field (styles.Scale.text, value); - if (value != scaleP.vector3Value) - { - scaleP.vector3Value = value; - SceneView.RepaintAll (); - } - } - GUILayout.EndHorizontal (); - } - } - - if (GUILayout.Button (GUIContent.none, "OL Plus")) - { - CreateHandle (); - } - } - } - GUILayout.EndVertical (); - - if (deleteHandle != -1 && m_HandleList != null && m_HandleList.isArray) - { - m_HandleList.DeleteArrayElementAtIndex (deleteHandle); - } - } - - void ComputeLocal (Transform parent, Transform child, out Vector3 localP, out Quaternion localQ, out Vector3 localS) - { - Quaternion parentInvGQ = Quaternion.Inverse (parent.rotation); - Vector3 parentGS = parent.lossyScale; - localP = (parentInvGQ * (child.position - parent.position)); - localP.x /= parentGS.x; - localP.y /= parentGS.y; - localP.z /= parentGS.z; - - localQ = parentInvGQ * child.rotation; - - localS = child.lossyScale; - localS.x /= parentGS.x; - localS.y /= parentGS.y; - localS.z /= parentGS.z; - } - - protected void CreateHandle () - { - string[] names = GetHandlesName (); - if (Selection.objects.Length == 2) - { - // Find out which one is a human bone and which one is the prop - Transform bone = null; - Transform prop = null; - int boneId = -1; - - for (int objIter = 0; objIter < Selection.objects.Length && bone == null; objIter++) - { - for (int boneIter = 0; boneIter < m_BoneName.Length; boneIter++) - { - if (Selection.objects[objIter].name == m_BoneName[boneIter]) - { - GameObject go1 = Selection.objects[objIter] as GameObject; - GameObject go2 = Selection.objects[ (objIter + 1) % 2] as GameObject; - - bone = go1.GetComponent (); - prop = go2.GetComponent (); - - boneId = boneIter; - break; - } - } - } - - if (bone != null && prop != null) - { - ArrayUtility.Add (ref m_Toggle, false); - m_HandleList.arraySize++; - - SerializedProperty handleP = m_HandleList.GetArrayElementAtIndex (m_HandleList.arraySize - 1); - - Vector3 localP = Vector3.zero; - Quaternion localQ = Quaternion.identity; - Vector3 localS = Vector3.one; - - ComputeLocal (bone, prop, out localP, out localQ, out localS); - - handleP.FindPropertyRelative (sName).stringValue = GenerateUniqueHandleName (prop.name+"_Handle", names); - handleP.FindPropertyRelative (sBoneName).stringValue = m_BoneName[boneId]; - handleP.FindPropertyRelative (sPosition).vector3Value = localP; - handleP.FindPropertyRelative (sRotation).quaternionValue = localQ; - handleP.FindPropertyRelative (sScale).vector3Value = localS; - } - } - else - { - ArrayUtility.Add (ref m_Toggle, false); - m_HandleList.arraySize++; - - SerializedProperty handleP = m_HandleList.GetArrayElementAtIndex (m_HandleList.arraySize - 1); - - handleP.FindPropertyRelative (sName).stringValue = GenerateUniqueHandleName (sDefaultHandleName, names); - handleP.FindPropertyRelative (sBoneName).stringValue = m_BoneName[0]; - handleP.FindPropertyRelative (sPosition).vector3Value = Vector3.zero; - handleP.FindPropertyRelative (sRotation).quaternionValue = Quaternion.identity; - handleP.FindPropertyRelative (sScale).vector3Value = Vector3.one; - } - } - - string[] GetHandlesName () - { - string[] names = new string[0]; - if (m_HandleList != null && m_HandleList.isArray) - { - for (int i = 0; i < m_HandleList.arraySize; i++) - { - SerializedProperty handleP = m_HandleList.GetArrayElementAtIndex (i); - SerializedProperty nameP = handleP.FindPropertyRelative (sName); - - ArrayUtility.Add (ref names, nameP.stringValue); - } - } - return names; - } - - string GenerateUniqueHandleName (string name, string[] names) - { - string attemptName = name; - int attempt = 1; - - bool collision = true; - while (collision) - { - collision = false; - foreach (string s in names) - { - if (attemptName == s) - { - attemptName = name + attempt.ToString (); - attempt++; - collision = true; - break; - } - } - } - - return attemptName; - }*/ - } -} diff --git a/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs deleted file mode 100644 index 857869ce61..0000000000 --- a/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs +++ /dev/null @@ -1,872 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; -using System.Linq; - -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - public enum BoneState - { - None, - NotFound, - Duplicate, - InvalidHierarchy, - BoneLenghtIsZero, - Valid - }; - - [System.Serializable] - internal class AvatarMappingEditor : AvatarSubEditor - { - internal class Styles - { - public GUIContent[] BodyPartMapping = - { - EditorGUIUtility.TrTextContent("Avatar"), - EditorGUIUtility.TrTextContent("Body"), - EditorGUIUtility.TrTextContent("Head"), - EditorGUIUtility.TrTextContent("Left Arm"), - EditorGUIUtility.TrTextContent("Left Fingers"), - EditorGUIUtility.TrTextContent("Right Arm"), - EditorGUIUtility.TrTextContent("Right Fingers"), - EditorGUIUtility.TrTextContent("Left Leg"), - EditorGUIUtility.TrTextContent("Right Leg") - }; - - public GUIContent RequiredBone = EditorGUIUtility.TrTextContent("Optional Bones"); - public GUIContent DoneCharacter = EditorGUIUtility.TrTextContent("Done"); - - public GUIContent mapping = EditorGUIUtility.TrTextContent("Mapping"); - public GUIContent clearMapping = EditorGUIUtility.TrTextContent("Clear"); - public GUIContent autoMapping = EditorGUIUtility.TrTextContent("Automap"); - public GUIContent bipedMapping = EditorGUIUtility.TrTextContent("Biped"); - public GUIContent loadMapping = EditorGUIUtility.TrTextContent("Load"); - public GUIContent saveMapping = EditorGUIUtility.TrTextContent("Save"); - - public GUIContent pose = EditorGUIUtility.TrTextContent("Pose"); - public GUIContent resetPose = EditorGUIUtility.TrTextContent("Reset"); - public GUIContent sampleBindPose = EditorGUIUtility.TrTextContent("Sample Bind-Pose"); - public GUIContent enforceTPose = EditorGUIUtility.TrTextContent("Enforce T-Pose"); - public GUIContent bipedPose = EditorGUIUtility.TrTextContent("Biped Pose"); - - public GUIContent ShowError = EditorGUIUtility.TrTextContent("Show Error (s)..."); - public GUIContent CloseError = EditorGUIUtility.TrTextContent("Close Error (s)"); - - public GUIContent dotFill = EditorGUIUtility.IconContent("AvatarInspector/DotFill"); - public GUIContent dotFrame = EditorGUIUtility.IconContent("AvatarInspector/DotFrame"); - public GUIContent dotFrameDotted = EditorGUIUtility.IconContent("AvatarInspector/DotFrameDotted"); - public GUIContent dotSelection = EditorGUIUtility.IconContent("AvatarInspector/DotSelection"); - - public GUIStyle box = new GUIStyle("box"); - public GUIStyle toolbar = "TE Toolbar"; - public GUIStyle toolbarDropDown = "TE ToolbarDropDown"; - - public GUIStyle errorLabel = new GUIStyle(EditorStyles.wordWrappedMiniLabel); - - public Styles() - { - box.padding = new RectOffset(0, 0, 0, 0); - box.margin = new RectOffset(0, 0, 0, 0); - errorLabel.normal.textColor = new Color(0.6f, 0, 0, 1); - } - } - - internal static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - static Styles s_Styles; - - protected bool[] m_BodyPartToggle; - protected bool[] m_BodyPartFoldout; - protected int m_BodyView = 0; - - [SerializeField] - protected AvatarSetupTool.BoneWrapper[] m_Bones; - internal static int s_SelectedBoneIndex = -1; - internal static bool s_DirtySelection = false; - internal static int s_KeyboardControl = 0; - protected bool m_HasSkinnedMesh; - bool m_IsBiped; - - Editor m_CurrentTransformEditor; - bool m_CurrentTransformEditorFoldout; - - // This list containt the mecanim's human bones id for each body part - protected int[][] m_BodyPartHumanBone = - { - new int[] {-1}, - new int[] { (int)HumanBodyBones.Hips, (int)HumanBodyBones.Spine, (int)HumanBodyBones.Chest, (int)HumanBodyBones.UpperChest}, - new int[] { (int)HumanBodyBones.Neck, (int)HumanBodyBones.Head, (int)HumanBodyBones.LeftEye, (int)HumanBodyBones.RightEye, (int)HumanBodyBones.Jaw}, - new int[] { (int)HumanBodyBones.LeftShoulder, (int)HumanBodyBones.LeftUpperArm, (int)HumanBodyBones.LeftLowerArm, (int)HumanBodyBones.LeftHand}, - new int[] - { - (int)HumanBodyBones.LeftThumbProximal , (int)HumanBodyBones.LeftThumbIntermediate, (int)HumanBodyBones.LeftThumbDistal, - (int)HumanBodyBones.LeftIndexProximal , (int)HumanBodyBones.LeftIndexIntermediate, (int)HumanBodyBones.LeftIndexDistal, - (int)HumanBodyBones.LeftMiddleProximal , (int)HumanBodyBones.LeftMiddleIntermediate, (int)HumanBodyBones.LeftMiddleDistal, - (int)HumanBodyBones.LeftRingProximal , (int)HumanBodyBones.LeftRingIntermediate, (int)HumanBodyBones.LeftRingDistal, - (int)HumanBodyBones.LeftLittleProximal , (int)HumanBodyBones.LeftLittleIntermediate, (int)HumanBodyBones.LeftLittleDistal - }, - new int[] { (int)HumanBodyBones.RightShoulder, (int)HumanBodyBones.RightUpperArm, (int)HumanBodyBones.RightLowerArm, (int)HumanBodyBones.RightHand}, - new int[] - { - (int)HumanBodyBones.RightThumbProximal , (int)HumanBodyBones.RightThumbIntermediate, (int)HumanBodyBones.RightThumbDistal, - (int)HumanBodyBones.RightIndexProximal , (int)HumanBodyBones.RightIndexIntermediate, (int)HumanBodyBones.RightIndexDistal, - (int)HumanBodyBones.RightMiddleProximal , (int)HumanBodyBones.RightMiddleIntermediate, (int)HumanBodyBones.RightMiddleDistal, - (int)HumanBodyBones.RightRingProximal , (int)HumanBodyBones.RightRingIntermediate, (int)HumanBodyBones.RightRingDistal, - (int)HumanBodyBones.RightLittleProximal , (int)HumanBodyBones.RightLittleIntermediate, (int)HumanBodyBones.RightLittleDistal - }, - new int[] { (int)HumanBodyBones.LeftUpperLeg, (int)HumanBodyBones.LeftLowerLeg, (int)HumanBodyBones.LeftFoot, (int)HumanBodyBones.LeftToes}, - new int[] { (int)HumanBodyBones.RightUpperLeg, (int)HumanBodyBones.RightLowerLeg, (int)HumanBodyBones.RightFoot, (int)HumanBodyBones.RightToes} - }; - - public AvatarMappingEditor() - { - m_BodyPartToggle = new bool[(int)BodyPart.Last]; - m_BodyPartFoldout = new bool[(int)BodyPart.Last]; - for (int i = 0; i < (int)BodyPart.Last; i++) - { - m_BodyPartToggle[i] = false; - m_BodyPartFoldout[i] = true; - } - } - - public override void Enable(AvatarEditor inspector) - { - base.Enable(inspector); - Init(); - } - - public override void Disable() - { - if (m_CurrentTransformEditor != null) - DestroyImmediate(m_CurrentTransformEditor); - - base.Disable(); - } - - public override void OnDestroy() - { - if (m_CurrentTransformEditor != null) - DestroyImmediate(m_CurrentTransformEditor); - base.OnDestroy(); - } - - protected void Init() - { - if (gameObject == null) - return; - - m_IsBiped = AvatarBipedMapper.IsBiped(gameObject.transform, null); - - // Handle human bones - if (m_Bones == null) - m_Bones = AvatarSetupTool.GetHumanBones(serializedObject, modelBones); - ValidateMapping(); - - if (m_CurrentTransformEditor != null) - { - DestroyImmediate(m_CurrentTransformEditor); - m_CurrentTransformEditor = null; - } - m_CurrentTransformEditorFoldout = true; - m_HasSkinnedMesh = (gameObject.GetComponentInChildren() != null); - - // Handle pose - InitPose(); - - // Repaint - SceneView.RepaintAll(); - } - - protected override void ResetValues() - { - base.ResetValues(); - ResetBones(); - Init(); - } - - protected void ResetBones() - { - for (int i = 0; i < m_Bones.Length; i++) - m_Bones[i].Reset(serializedObject, modelBones); - } - - protected bool IsValidHuman() - { - Animator animator = gameObject.GetComponent(); - if (animator == null) - return false; - - Avatar avatar = animator.avatar; - return avatar != null && avatar.isHuman; - } - - protected void InitPose() - { - if (IsValidHuman()) - { - Animator animator = gameObject.GetComponent(); - animator.WriteDefaultPose(); - AvatarSetupTool.TransferDescriptionToPose(serializedObject, root); - } - } - - protected void ValidateMapping() - { - for (int i = 0; i < m_Bones.Length; i++) - { - string error; - m_Bones[i].state = GetBoneState(i, out error); - m_Bones[i].error = error; - } - } - - private void EnableBodyParts(bool[] toggles, params int[] parts) - { - for (int i = 0; i < m_BodyPartToggle.Length; i++) - toggles[i] = false; - foreach (int i in parts) - toggles[i] = true; - } - - private void HandleBodyView(int bodyView) - { - if (bodyView == 0) - EnableBodyParts(m_BodyPartToggle, 1, 3, 5, 7, 8); - if (bodyView == 1) - EnableBodyParts(m_BodyPartToggle, 2); - if (bodyView == 2) - EnableBodyParts(m_BodyPartToggle, 4); - if (bodyView == 3) - EnableBodyParts(m_BodyPartToggle, 6); - } - - Vector2 m_FoldoutScroll = Vector2.zero; - - public override void OnInspectorGUI() - { - if (Event.current.type == EventType.ValidateCommand && Event.current.commandName == EventCommandNames.UndoRedoPerformed) - { - AvatarSetupTool.TransferPoseToDescription(serializedObject, root); - for (int i = 0; i < m_Bones.Length; i++) - m_Bones[i].Serialize(serializedObject); - } - - UpdateSelectedBone(); - - // case 837655. GUI.keyboardControl is overriden when changing scene selection. - // Late update here to bypass this issue. - if (s_KeyboardControl != 0) - { - GUIUtility.keyboardControl = s_KeyboardControl; - s_KeyboardControl = 0; - } - - GUILayout.BeginVertical(); - { - EditorGUI.BeginChangeCheck(); - - GUILayout.BeginVertical("", "TE NodeBackground"); - { - m_BodyView = AvatarControl.ShowBoneMapping(m_BodyView, new AvatarControl.BodyPartFeedback(this.IsValidBodyPart), m_Bones, serializedObject, this); - HandleBodyView(m_BodyView); - } - GUILayout.EndVertical(); - - m_FoldoutScroll = GUILayout.BeginScrollView(m_FoldoutScroll, styles.box, GUILayout.MinHeight(80), GUILayout.MaxHeight(500), GUILayout.ExpandHeight(true)); - { - DisplayFoldout(); - GUILayout.FlexibleSpace(); - } - GUILayout.EndScrollView(); - - if (EditorGUI.EndChangeCheck()) - { - ValidateMapping(); - SceneView.RepaintAll(); - } - - DisplayMappingButtons(); - } - GUILayout.EndVertical(); - - if (EditorGUIUtility.hotControl == 0) - TransferPoseIfChanged(); - - //DebugPoseButtons (); - - ApplyRevertGUI(); - - if (Selection.activeTransform != null) - { - // Selection is changing, clean up before we create a new editor - if (m_CurrentTransformEditor != null && m_CurrentTransformEditor.target != Selection.activeTransform) - DestroyImmediate(m_CurrentTransformEditor); - - if (m_CurrentTransformEditor == null) - m_CurrentTransformEditor = Editor.CreateEditor(Selection.activeTransform); - - EditorGUILayout.Space(); - m_CurrentTransformEditorFoldout = EditorGUILayout.InspectorTitlebar(m_CurrentTransformEditorFoldout, Selection.activeTransform, true); - - if (m_CurrentTransformEditorFoldout && m_CurrentTransformEditor != null) - m_CurrentTransformEditor.OnInspectorGUI(); - } - else if (m_CurrentTransformEditor != null) - { - DestroyImmediate(m_CurrentTransformEditor); - m_CurrentTransformEditor = null; - } - } - - protected void DebugPoseButtons() - { - if (GUILayout.Button("Default Pose") && IsValidHuman()) - { - Animator animator = gameObject.GetComponent(); - animator.WriteDefaultPose(); - } - if (GUILayout.Button("Description Pose")) - AvatarSetupTool.TransferDescriptionToPose(serializedObject, root); - } - - protected void TransferPoseIfChanged() - { - foreach (GameObject selected in Selection.gameObjects) - { - if (TransformChanged(selected.transform)) - { - AvatarSetupTool.TransferPoseToDescription(serializedObject, root); - m_Inspector.Repaint(); - break; - } - } - } - - protected void DisplayMappingButtons() - { - GUILayout.BeginHorizontal("", styles.toolbar, GUILayout.ExpandWidth(true)); - { - Rect r; - - // Mapping - r = GUILayoutUtility.GetRect(styles.mapping, styles.toolbarDropDown); - if (GUI.Button(r, styles.mapping, styles.toolbarDropDown)) - { - GenericMenu menu = new GenericMenu(); - menu.AddItem(styles.clearMapping, false, ClearMapping); - if (m_IsBiped) - menu.AddItem(styles.bipedMapping, false, PerformBipedMapping); - menu.AddItem(styles.autoMapping, false, PerformAutoMapping); - menu.AddItem(styles.loadMapping, false, ApplyTemplate); - menu.AddItem(styles.saveMapping, false, SaveHumanTemplate); - menu.DropDown(r); - } - - // Pose - r = GUILayoutUtility.GetRect(styles.pose, styles.toolbarDropDown); - if (GUI.Button(r, styles.pose, styles.toolbarDropDown)) - { - GenericMenu menu = new GenericMenu(); - menu.AddItem(styles.resetPose, false, CopyPrefabPose); - if (m_IsBiped) - menu.AddItem(styles.bipedPose, false, BipedPose); - if (m_HasSkinnedMesh) - menu.AddItem(styles.sampleBindPose, false, SampleBindPose); - else - menu.AddItem(styles.sampleBindPose, false, null); - menu.AddItem(styles.enforceTPose, false, MakePoseValid); - menu.DropDown(r); - } - - GUILayout.FlexibleSpace(); - } - GUILayout.EndHorizontal(); - } - - protected void CopyPrefabPose() - { - AvatarSetupTool.CopyPose(gameObject, prefab); - AvatarSetupTool.TransferPoseToDescription(serializedObject, root); - m_Inspector.Repaint(); - } - - protected void SampleBindPose() - { - AvatarSetupTool.SampleBindPose(gameObject); - AvatarSetupTool.TransferPoseToDescription(serializedObject, root); - m_Inspector.Repaint(); - } - - protected void BipedPose() - { - AvatarBipedMapper.BipedPose(gameObject, m_Bones); - - AvatarSetupTool.TransferPoseToDescription(serializedObject, root); - m_Inspector.Repaint(); - } - - protected void MakePoseValid() - { - AvatarSetupTool.MakePoseValid(m_Bones); - AvatarSetupTool.TransferPoseToDescription(serializedObject, root); - m_Inspector.Repaint(); - } - - protected void PerformAutoMapping() - { - AutoMapping(); - ValidateMapping(); - SceneView.RepaintAll(); - } - - protected void PerformBipedMapping() - { - BipedMapping(); - ValidateMapping(); - SceneView.RepaintAll(); - } - - protected void AutoMapping() - { - Dictionary mapping = AvatarAutoMapper.MapBones(gameObject.transform, modelBones); - foreach (KeyValuePair kvp in mapping) - { - AvatarSetupTool.BoneWrapper bone = m_Bones[kvp.Key]; - bone.bone = kvp.Value; - bone.Serialize(serializedObject); - } - } - - protected void BipedMapping() - { - Dictionary mapping = AvatarBipedMapper.MapBones(gameObject.transform); - foreach (KeyValuePair kvp in mapping) - { - AvatarSetupTool.BoneWrapper bone = m_Bones[kvp.Key]; - bone.bone = kvp.Value; - bone.Serialize(serializedObject); - } - } - - protected void ClearMapping() - { - if (serializedObject != null) - { - Undo.RegisterCompleteObjectUndo(this, "Clear Mapping"); - AvatarSetupTool.ClearHumanBoneArray(serializedObject); - ResetBones(); - ValidateMapping(); - SceneView.RepaintAll(); - } - } - - protected Vector4 QuaternionToVector4(Quaternion rot) - { - return new Vector4(rot.x, rot.y, rot.z, rot.w); - } - - protected Quaternion Vector4ToQuaternion(Vector4 rot) - { - return new Quaternion(rot.x, rot.y, rot.z, rot.w); - } - - protected bool IsAnyBodyPartActive() - { - // Avatar body part has nothing to show - for (int i = 1; i < m_BodyPartToggle.Length; i++) - { - if (m_BodyPartToggle[i]) - return true; - } - return false; - } - - private void UpdateSelectedBone() - { - // Look for selected bone slot - int oldSelectedBoneIndex = s_SelectedBoneIndex; - if (s_SelectedBoneIndex < 0 || s_SelectedBoneIndex >= m_Bones.Length || m_Bones[s_SelectedBoneIndex].bone != Selection.activeTransform) - { - s_SelectedBoneIndex = -1; - if (Selection.activeTransform != null) - { - for (int i = 0; i < m_Bones.Length; i++) - { - if (m_Bones[i].bone == Selection.activeTransform) - { - s_SelectedBoneIndex = i; - break; - } - } - } - } - if (s_SelectedBoneIndex != oldSelectedBoneIndex) - { - // If selected bone changed, change visual to show image that contains that bone. - List views = AvatarControl.GetViewsThatContainBone(s_SelectedBoneIndex); - if (views.Count > 0 && !views.Contains(m_BodyView)) - m_BodyView = views[0]; - } - } - - protected void DisplayFoldout() - { - Dictionary bones = modelBones; - - EditorGUIUtility.SetIconSize(Vector2.one * 16); - - // Legend - EditorGUILayout.BeginHorizontal(); - GUI.color = Color.grey; - GUILayout.Label(styles.dotFrameDotted.image, GUILayout.ExpandWidth(false)); - GUI.color = Color.white; - GUILayout.Label("Optional Bone", GUILayout.ExpandWidth(true)); - EditorGUILayout.EndHorizontal(); - - // Avatar body part has nothing to show - for (int i = 1; i < m_BodyPartToggle.Length; i++) - { - if (m_BodyPartToggle[i]) - { - // Unfold body part ui whenever a new selection is made. - if ((s_DirtySelection == true) && (m_BodyPartFoldout[i] == false)) - { - for (int j = 0; j < m_BodyPartHumanBone[i].Length; j++) - { - int boneIndex = m_BodyPartHumanBone[i][j]; - if (s_SelectedBoneIndex == boneIndex) - m_BodyPartFoldout[i] = true; - } - } - - m_BodyPartFoldout[i] = GUILayout.Toggle(m_BodyPartFoldout[i], styles.BodyPartMapping[i], EditorStyles.foldout); - EditorGUI.indentLevel++; - if (m_BodyPartFoldout[i]) - { - for (int j = 0; j < m_BodyPartHumanBone[i].Length; j++) - { - int boneIndex = m_BodyPartHumanBone[i][j]; - if (boneIndex == -1) - continue; - - AvatarSetupTool.BoneWrapper bone = m_Bones[boneIndex]; - string displayBoneName = bone.humanBoneName; - - // @TODO@MECANIM: do properly - if ((BodyPart)i == BodyPart.RightArm || (BodyPart)i == BodyPart.RightFingers || (BodyPart)i == BodyPart.RightLeg) - displayBoneName = displayBoneName.Replace("Right", ""); - if ((BodyPart)i == BodyPart.LeftArm || (BodyPart)i == BodyPart.LeftFingers || (BodyPart)i == BodyPart.LeftLeg) - displayBoneName = displayBoneName.Replace("Left", ""); - - displayBoneName = ObjectNames.NicifyVariableName(displayBoneName); - - Rect r = EditorGUILayout.GetControlRect(); - - Rect selectRect = r; - selectRect.width -= 15; - - Rect rect = new Rect(r.x + EditorGUI.indent, r.y - 1, AvatarSetupTool.BoneWrapper.kIconSize, AvatarSetupTool.BoneWrapper.kIconSize); - - bone.BoneDotGUI(rect, selectRect, boneIndex, true, false, true, serializedObject, this); - r.xMin += AvatarSetupTool.BoneWrapper.kIconSize; - - Transform newBoneTransform = EditorGUI.ObjectField(r, new GUIContent(displayBoneName), bone.bone, typeof(Transform), true) as Transform; - if (newBoneTransform != bone.bone) - { - Undo.RegisterCompleteObjectUndo(this, "Avatar mapping modified"); - bone.bone = newBoneTransform; - bone.Serialize(serializedObject); - - // User adding a bone manually, if it not in the modelBones dict, we must explictly add it - if (newBoneTransform != null && !bones.ContainsKey(newBoneTransform)) - bones[newBoneTransform] = true; - } - - if (!string.IsNullOrEmpty(bone.error)) - { - GUILayout.BeginHorizontal(); - GUILayout.Space(EditorGUI.indent + AvatarSetupTool.BoneWrapper.kIconSize + 4); - GUILayout.Label(bone.error, s_Styles.errorLabel); - GUILayout.EndHorizontal(); - } - } - } - EditorGUI.indentLevel--; - } - } - - s_DirtySelection = false; - - EditorGUIUtility.SetIconSize(Vector2.zero); - } - - bool TransformChanged(Transform tr) - { - SerializedProperty bone = AvatarSetupTool.FindSkeletonBone(serializedObject, tr, false, false); - if (bone != null) - { - SerializedProperty positionP = bone.FindPropertyRelative(AvatarSetupTool.sPosition); - if (positionP != null && positionP.vector3Value != tr.localPosition) - return true; - - SerializedProperty rotationP = bone.FindPropertyRelative(AvatarSetupTool.sRotation); - if (rotationP != null && rotationP.quaternionValue != tr.localRotation) - return true; - - SerializedProperty scaleP = bone.FindPropertyRelative(AvatarSetupTool.sScale); - if (scaleP != null && scaleP.vector3Value != tr.localScale) - return true; - } - return false; - } - - protected BoneState GetBoneState(int i, out string error) - { - error = string.Empty; - AvatarSetupTool.BoneWrapper bone = m_Bones[i]; - - if (bone.bone == null) - return BoneState.None; - - int ancestorIndex = AvatarSetupTool.GetFirstHumanBoneAncestor(m_Bones, i); - - AvatarSetupTool.BoneWrapper ancestor = m_Bones[ancestorIndex > 0 ? ancestorIndex : 0]; - - if (i == 0 && bone.bone.parent == null) - { - error = bone.messageName + " cannot be the root transform"; - return BoneState.InvalidHierarchy; - } - - if (ancestor.bone != null && !bone.bone.IsChildOf(ancestor.bone)) - { - error = bone.messageName + " is not a child of " + ancestor.messageName + "."; - return BoneState.InvalidHierarchy; - } - - if (i == (int)HumanBodyBones.UpperChest) - { - AvatarSetupTool.BoneWrapper chest = m_Bones[(int)HumanBodyBones.Chest]; - - if (chest.bone == null) - { - error = "Chest must be assigned before assigning UpperChest."; - return BoneState.InvalidHierarchy; - } - } - - // Hips bone is a special case, for hips GetFirstAnscestor return hips - if (i != (int)HumanBodyBones.Jaw && ancestor.bone != null && ancestor.bone != bone.bone && (bone.bone.position - ancestor.bone.position).sqrMagnitude < Mathf.Epsilon) - { - error = bone.messageName + " has bone length of zero."; - return BoneState.BoneLenghtIsZero; - } - - // Does this transfrom is already set - //List match = ArrayUtility.FindAll (m_BoneWrappers, delegate (Transform t) { return t == m_BoneWrappers[i].bone; }); - IEnumerable match = m_Bones.Where(f => f.bone == bone.bone); - // when we search in the list we must add 1 because the bone is in this list - if (match.Count() > 1) - { - error = bone.messageName + " is also assigned to "; - bool first = true; - for (int j = 0; j < m_Bones.Length; j++) - { - if (i != j && m_Bones[i].bone == m_Bones[j].bone) - { - if (first) - first = false; - else - error += ", "; - error += ObjectNames.NicifyVariableName(m_Bones[j].humanBoneName); - } - } - error += "."; - return BoneState.Duplicate; - } - else - return BoneState.Valid; - } - - protected AvatarControl.BodyPartColor IsValidBodyPart(BodyPart bodyPart) - { - AvatarControl.BodyPartColor ik = AvatarControl.BodyPartColor.Off; - bool hasAnyBone = false; - - int idx = (int)bodyPart; - if (bodyPart != BodyPart.LeftFingers && bodyPart != BodyPart.RightFingers) - { - int i; - for (i = 0; i < m_BodyPartHumanBone[idx].Length; i++) - { - if (m_BodyPartHumanBone[idx][i] != -1) - { - BoneState state = m_Bones[m_BodyPartHumanBone[idx][i]].state; - hasAnyBone |= state == BoneState.Valid; - - // if it a required bone and no bone is set this body part is not valid - if (HumanTrait.RequiredBone(m_BodyPartHumanBone[idx][i]) == true && state == BoneState.None) - return AvatarControl.BodyPartColor.Red; - else if (state != BoneState.Valid && state != BoneState.None) - return AvatarControl.BodyPartColor.Red; - } - } - } - else - { - bool hasAllFinger = true; - - int i; - int phalangeCount = 3; - for (i = 0; i < m_BodyPartHumanBone[idx].Length / phalangeCount; i++) - { - bool hasFinger = false; - int fingerIndex = i * phalangeCount; - int j; - for (j = phalangeCount - 1; j >= 0; j--) - { - bool hasBone = m_Bones[m_BodyPartHumanBone[idx][fingerIndex + j]].state == BoneState.Valid; - hasAllFinger &= hasBone; - if (hasFinger) - { - if (!hasBone) - return AvatarControl.BodyPartColor.Red | AvatarControl.BodyPartColor.IKRed; - } - else - hasAnyBone |= hasFinger = !hasFinger && hasBone; - } - } - - ik = hasAllFinger ? AvatarControl.BodyPartColor.IKGreen : AvatarControl.BodyPartColor.IKRed; - } - - if (!hasAnyBone) - return AvatarControl.BodyPartColor.Off | AvatarControl.BodyPartColor.IKRed; - - return AvatarControl.BodyPartColor.Green | ik; - } - - private HumanTemplate OpenHumanTemplate() - { - string assetsDirectory = "Assets/"; - - // Go forward with presenting user a save clip dialog - string templatePath = EditorUtility.OpenFilePanel("Open Human Template", assetsDirectory, "ht"); - - // If user canceled or save path is invalid, we can't create a template - if (templatePath == "") - return null; - - // At this point we know that we can create a template - string relativeTemplatePath = FileUtil.GetProjectRelativePath(templatePath); - HumanTemplate template = AssetDatabase.LoadMainAssetAtPath(relativeTemplatePath) as HumanTemplate; - - // Asset not found in project, try to import it into the project - if (template == null) - { - if (EditorUtility.DisplayDialog("Human Template not found in project", "Import asset \'" + templatePath + "\' into project", "Yes", "No")) - { - string newFileName = assetsDirectory + FileUtil.GetLastPathNameComponent(templatePath); - - newFileName = AssetDatabase.GenerateUniqueAssetPath(newFileName); - - // Copy file - FileUtil.CopyFileOrDirectory(templatePath, newFileName); - - AssetDatabase.Refresh(); - - template = AssetDatabase.LoadMainAssetAtPath(newFileName) as HumanTemplate; - - if (template == null) - { - Debug.Log("Failed importing file \'" + templatePath + "\' to \'" + newFileName + "\'"); - } - } - } - return template; - } - - static public bool MatchName(string transformName, string boneName) - { - string delimStr = ":"; - char[] delimiter = delimStr.ToCharArray(); - - string[] transformSplit = transformName.Split(delimiter); - string[] boneSplit = boneName.Split(delimiter); - - return transformName == boneName || - (transformSplit.Length > 1 && transformSplit[1] == boneName) || // transform does have a prefix - (boneSplit.Length > 1 && transformName == boneSplit[1]) || // boneName does have a prefix - (transformSplit.Length > 1 && boneSplit.Length > 1 && transformSplit[1] == boneSplit[1]); // both have a different prefix - } - - protected void ApplyTemplate() - { - Undo.RegisterCompleteObjectUndo(this, "Apply Template"); - - HumanTemplate humanTemplate = OpenHumanTemplate(); - if (humanTemplate == null) - return; - - for (int i = 0; i < m_Bones.Length; i++) - { - string boneName = humanTemplate.Find(m_Bones[i].humanBoneName); - if (boneName.Length > 0) - { - Transform transform = modelBones.Keys.FirstOrDefault(f => AvatarMappingEditor.MatchName(f.name, boneName)); - m_Bones[i].bone = transform; - } - else - { - m_Bones[i].bone = null; - } - m_Bones[i].Serialize(serializedObject); - } - - ValidateMapping(); - SceneView.RepaintAll(); - } - - private void SaveHumanTemplate() - { - // Go forward with presenting user a save clip dialog - string newTemplatePath = EditorUtility.SaveFilePanelInProject("Create New Human Template", "New Human Template", "ht", "Create a new human template"); - - // If user canceled or save path is invalid, we can't create a template - if (newTemplatePath == "") - return; - - // At this point we know that we can create a template - HumanTemplate humanTemplate = new HumanTemplate(); - humanTemplate.ClearTemplate(); - - for (int i = 0; i < m_Bones.Length; i++) - { - if (m_Bones[i].bone != null) - humanTemplate.Insert(m_Bones[i].humanBoneName, m_Bones[i].bone.name); - } - - AssetDatabase.CreateAsset(humanTemplate, newTemplatePath); - } - - public override void OnSceneGUI() - { - // It seems styles can't safely be created from inside OnSceneGUI so not much we can do here. :( - if (s_Styles == null) - return; - - AvatarSkeletonDrawer.DrawSkeleton(root, modelBones, m_Bones); - - if (EditorGUIUtility.hotControl == 0) - TransferPoseIfChanged(); - } - } -} diff --git a/Editor/Mono/Inspector/Avatar/AvatarMuscleEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarMuscleEditor.cs deleted file mode 100644 index d65f91a1ec..0000000000 --- a/Editor/Mono/Inspector/Avatar/AvatarMuscleEditor.cs +++ /dev/null @@ -1,1130 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor -{ - [System.Serializable] - internal class AvatarMuscleEditor : AvatarSubEditor - { - class Styles - { - public GUIContent[] muscleBodyGroup = - { - EditorGUIUtility.TrTextContent("Body"), - EditorGUIUtility.TrTextContent("Head"), - EditorGUIUtility.TrTextContent("Left Arm"), - EditorGUIUtility.TrTextContent("Left Fingers"), - EditorGUIUtility.TrTextContent("Right Arm"), - EditorGUIUtility.TrTextContent("Right Fingers"), - EditorGUIUtility.TrTextContent("Left Leg"), - EditorGUIUtility.TrTextContent("Right Leg") - }; - - public GUIContent[] muscleTypeGroup = - { - EditorGUIUtility.TrTextContent("Open Close"), - EditorGUIUtility.TrTextContent("Left Right"), - EditorGUIUtility.TrTextContent("Roll Left Right"), - EditorGUIUtility.TrTextContent("In Out"), - EditorGUIUtility.TrTextContent("Roll In Out"), - EditorGUIUtility.TrTextContent("Finger Open Close"), - EditorGUIUtility.TrTextContent("Finger In Out") - }; - - public GUIContent armTwist = EditorGUIUtility.TrTextContent("Upper Arm Twist"); - public GUIContent foreArmTwist = EditorGUIUtility.TrTextContent("Lower Arm Twist"); - public GUIContent upperLegTwist = EditorGUIUtility.TrTextContent("Upper Leg Twist"); - public GUIContent legTwist = EditorGUIUtility.TrTextContent("Lower Leg Twist"); - public GUIContent armStretch = EditorGUIUtility.TrTextContent("Arm Stretch"); - public GUIContent legStretch = EditorGUIUtility.TrTextContent("Leg Stretch"); - public GUIContent feetSpacing = EditorGUIUtility.TrTextContent("Feet Spacing"); - public GUIContent hasTranslationDoF = EditorGUIUtility.TrTextContent("Translation DoF"); - - public GUIStyle box = new GUIStyle("OL box noexpand"); - public GUIStyle title = new GUIStyle("OL TITLE"); - - public GUIStyle toolbar = "TE Toolbar"; - public GUIStyle toolbarDropDown = "TE ToolbarDropDown"; - - public GUIContent muscle = EditorGUIUtility.TrTextContent("Muscles"); - public GUIContent resetMuscle = EditorGUIUtility.TrTextContent("Reset"); - - public Styles() - { - box.padding = new RectOffset(0, 0, 4, 4); - } - } - - static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - static Styles s_Styles; - - // This list containt the mecanim's musle id for each muscle group - protected int[][] m_Muscles = - { - new int[] { (int)DoF.BodyDoFStart + (int)BodyDoF.SpineFrontBack, - (int)DoF.BodyDoFStart + (int)BodyDoF.SpineLeftRight, - (int)DoF.BodyDoFStart + (int)BodyDoF.SpineRollLeftRight, - (int)DoF.BodyDoFStart + (int)BodyDoF.ChestFrontBack, - (int)DoF.BodyDoFStart + (int)BodyDoF.ChestLeftRight, - (int)DoF.BodyDoFStart + (int)BodyDoF.ChestRollLeftRight, - (int)DoF.BodyDoFStart + (int)BodyDoF.UpperChestFrontBack, - (int)DoF.BodyDoFStart + (int)BodyDoF.UpperChestLeftRight, - (int)DoF.BodyDoFStart + (int)BodyDoF.UpperChestRollLeftRight}, - - new int[] { (int)DoF.HeadDoFStart + (int)HeadDoF.NeckFrontBack, - (int)DoF.HeadDoFStart + (int)HeadDoF.NeckLeftRight, - (int)DoF.HeadDoFStart + (int)HeadDoF.NeckRollLeftRight, - (int)DoF.HeadDoFStart + (int)HeadDoF.HeadFrontBack, - (int)DoF.HeadDoFStart + (int)HeadDoF.HeadLeftRight, - (int)DoF.HeadDoFStart + (int)HeadDoF.HeadRollLeftRight, - (int)DoF.HeadDoFStart + (int)HeadDoF.LeftEyeDownUp, - (int)DoF.HeadDoFStart + (int)HeadDoF.LeftEyeInOut, - (int)DoF.HeadDoFStart + (int)HeadDoF.RightEyeDownUp, - (int)DoF.HeadDoFStart + (int)HeadDoF.RightEyeInOut, - (int)DoF.HeadDoFStart + (int)HeadDoF.JawDownUp, - (int)DoF.HeadDoFStart + (int)HeadDoF.JawLeftRight}, - - new int[] { (int)DoF.LeftArmDoFStart + (int)ArmDoF.ShoulderDownUp, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ShoulderFrontBack, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ArmDownUp, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ArmFrontBack, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ArmRollInOut, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ForeArmCloseOpen, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ForeArmRollInOut, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.HandDownUp, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.HandInOut}, - - new int[] { - (int)DoF.LeftThumbDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.LeftThumbDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.LeftThumbDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.LeftThumbDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.LeftIndexDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.LeftIndexDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.LeftIndexDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.LeftIndexDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.LeftMiddleDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.LeftMiddleDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.LeftMiddleDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.LeftMiddleDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.LeftRingDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.LeftRingDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.LeftRingDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.LeftRingDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.LeftLittleDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.LeftLittleDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.LeftLittleDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.LeftLittleDoFStart + (int)FingerDoF.DistalCloseOpen - }, - - new int[] { (int)DoF.RightArmDoFStart + (int)ArmDoF.ShoulderDownUp, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ShoulderFrontBack, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ArmDownUp, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ArmFrontBack, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ArmRollInOut, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ForeArmCloseOpen, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ForeArmRollInOut, - (int)DoF.RightArmDoFStart + (int)ArmDoF.HandDownUp, - (int)DoF.RightArmDoFStart + (int)ArmDoF.HandInOut}, - - new int[] { - (int)DoF.RightThumbDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.RightThumbDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.RightThumbDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.RightThumbDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.RightIndexDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.RightIndexDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.RightIndexDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.RightIndexDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.RightMiddleDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.RightMiddleDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.RightMiddleDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.RightMiddleDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.RightRingDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.RightRingDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.RightRingDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.RightRingDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.RightLittleDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.RightLittleDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.RightLittleDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.RightLittleDoFStart + (int)FingerDoF.DistalCloseOpen - }, - - new int[] { - (int)DoF.LeftLegDoFStart + (int)LegDoF.UpperLegFrontBack, - (int)DoF.LeftLegDoFStart + (int)LegDoF.UpperLegInOut, - (int)DoF.LeftLegDoFStart + (int)LegDoF.UpperLegRollInOut, - (int)DoF.LeftLegDoFStart + (int)LegDoF.LegCloseOpen, - (int)DoF.LeftLegDoFStart + (int)LegDoF.LegRollInOut, - (int)DoF.LeftLegDoFStart + (int)LegDoF.FootCloseOpen, - (int)DoF.LeftLegDoFStart + (int)LegDoF.FootInOut, - (int)DoF.LeftLegDoFStart + (int)LegDoF.ToesUpDown, - }, - - new int[] { - (int)DoF.RightLegDoFStart + (int)LegDoF.UpperLegFrontBack, - (int)DoF.RightLegDoFStart + (int)LegDoF.UpperLegInOut, - (int)DoF.RightLegDoFStart + (int)LegDoF.UpperLegRollInOut, - (int)DoF.RightLegDoFStart + (int)LegDoF.LegCloseOpen, - (int)DoF.RightLegDoFStart + (int)LegDoF.LegRollInOut, - (int)DoF.RightLegDoFStart + (int)LegDoF.FootCloseOpen, - (int)DoF.RightLegDoFStart + (int)LegDoF.FootInOut, - (int)DoF.RightLegDoFStart + (int)LegDoF.ToesUpDown, - } - }; - - protected int[][] m_MasterMuscle = - { - // Body open close - new int[] { - (int)DoF.BodyDoFStart + (int)BodyDoF.SpineFrontBack, - (int)DoF.BodyDoFStart + (int)BodyDoF.ChestFrontBack, - (int)DoF.BodyDoFStart + (int)BodyDoF.UpperChestFrontBack, - (int)DoF.HeadDoFStart + (int)HeadDoF.NeckFrontBack, - (int)DoF.HeadDoFStart + (int)HeadDoF.HeadFrontBack, - - (int)DoF.LeftLegDoFStart + (int)LegDoF.UpperLegFrontBack, - (int)DoF.LeftLegDoFStart + (int)LegDoF.LegCloseOpen, - (int)DoF.LeftLegDoFStart + (int)LegDoF.FootCloseOpen, - (int)DoF.RightLegDoFStart + (int)LegDoF.UpperLegFrontBack, - (int)DoF.RightLegDoFStart + (int)LegDoF.LegCloseOpen, - (int)DoF.RightLegDoFStart + (int)LegDoF.FootCloseOpen, - - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ShoulderDownUp, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ArmDownUp, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ForeArmCloseOpen, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.HandDownUp, - - (int)DoF.RightArmDoFStart + (int)ArmDoF.ShoulderDownUp, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ArmDownUp, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ForeArmCloseOpen, - (int)DoF.RightArmDoFStart + (int)ArmDoF.HandDownUp - }, - - // Body Left Right - new int[] { - (int)DoF.BodyDoFStart + (int)BodyDoF.SpineLeftRight, - (int)DoF.BodyDoFStart + (int)BodyDoF.ChestLeftRight, - (int)DoF.BodyDoFStart + (int)BodyDoF.UpperChestLeftRight, - (int)DoF.HeadDoFStart + (int)HeadDoF.NeckLeftRight, - (int)DoF.HeadDoFStart + (int)HeadDoF.HeadLeftRight, - }, - - // Roll Left Right - new int[] { - (int)DoF.BodyDoFStart + (int)BodyDoF.SpineRollLeftRight, - (int)DoF.BodyDoFStart + (int)BodyDoF.ChestRollLeftRight, - (int)DoF.BodyDoFStart + (int)BodyDoF.UpperChestRollLeftRight, - (int)DoF.HeadDoFStart + (int)HeadDoF.NeckRollLeftRight, - (int)DoF.HeadDoFStart + (int)HeadDoF.HeadRollLeftRight, - }, - - // In Out - new int[] { - (int)DoF.LeftLegDoFStart + (int)LegDoF.UpperLegInOut, - (int)DoF.LeftLegDoFStart + (int)LegDoF.FootInOut, - (int)DoF.RightLegDoFStart + (int)LegDoF.UpperLegInOut, - (int)DoF.RightLegDoFStart + (int)LegDoF.FootInOut, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ShoulderFrontBack, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ArmFrontBack, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.HandInOut, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ShoulderFrontBack, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ArmFrontBack, - (int)DoF.RightArmDoFStart + (int)ArmDoF.HandInOut - }, - - // Roll In Out - new int[] { - (int)DoF.LeftLegDoFStart + (int)LegDoF.UpperLegRollInOut, - (int)DoF.LeftLegDoFStart + (int)LegDoF.LegRollInOut, - (int)DoF.RightLegDoFStart + (int)LegDoF.UpperLegRollInOut, - (int)DoF.RightLegDoFStart + (int)LegDoF.LegRollInOut, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ArmRollInOut, - (int)DoF.LeftArmDoFStart + (int)ArmDoF.ForeArmRollInOut, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ArmRollInOut, - (int)DoF.RightArmDoFStart + (int)ArmDoF.ForeArmRollInOut - }, - - // Finger open close - new int[] { - (int)DoF.LeftThumbDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.LeftThumbDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.LeftThumbDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.LeftIndexDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.LeftIndexDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.LeftIndexDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.LeftMiddleDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.LeftMiddleDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.LeftMiddleDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.LeftRingDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.LeftRingDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.LeftRingDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.LeftLittleDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.LeftLittleDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.LeftLittleDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.RightThumbDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.RightThumbDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.RightThumbDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.RightIndexDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.RightIndexDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.RightIndexDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.RightMiddleDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.RightMiddleDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.RightMiddleDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.RightRingDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.RightRingDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.RightRingDoFStart + (int)FingerDoF.DistalCloseOpen, - - (int)DoF.RightLittleDoFStart + (int)FingerDoF.ProximalDownUp, - (int)DoF.RightLittleDoFStart + (int)FingerDoF.IntermediateCloseOpen, - (int)DoF.RightLittleDoFStart + (int)FingerDoF.DistalCloseOpen - }, - - // Finger In Out - new int[] { - (int)DoF.LeftThumbDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.LeftIndexDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.LeftMiddleDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.LeftRingDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.LeftLittleDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.RightThumbDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.RightIndexDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.RightMiddleDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.RightRingDoFStart + (int)FingerDoF.ProximalInOut, - (int)DoF.RightLittleDoFStart + (int)FingerDoF.ProximalInOut, - } - }; - - - bool[] m_MuscleBodyGroupToggle; - bool[] m_MuscleToggle; - - int m_FocusedMuscle; - - [SerializeField] - float[] m_MuscleValue = null; - - [SerializeField] - float[] m_MuscleMasterValue = null; - - [SerializeField] - protected float m_ArmTwistFactor; - - [SerializeField] - protected float m_ForeArmTwistFactor; - - [SerializeField] - protected float m_UpperLegTwistFactor; - - [SerializeField] - protected float m_LegTwistFactor; - - [SerializeField] - protected float m_ArmStretchFactor; - - [SerializeField] - protected float m_LegStretchFactor; - - [SerializeField] - protected float m_FeetSpacingFactor; - - [SerializeField] - protected bool m_HasTranslationDoF; - - string[] m_MuscleName = null; - int m_MuscleCount = 0; - - SerializedProperty[] m_MuscleMin = null; - SerializedProperty[] m_MuscleMax = null; - - [SerializeField] - float[] m_MuscleMinEdit = null; - - [SerializeField] - float[] m_MuscleMaxEdit = null; - - SerializedProperty[] m_Modified = null; - - // These member are used when the avatar is part of an asset - SerializedProperty m_ArmTwistProperty; - SerializedProperty m_ForeArmTwistProperty; - SerializedProperty m_UpperLegTwistProperty; - SerializedProperty m_LegTwistProperty; - - SerializedProperty m_ArmStretchProperty; - SerializedProperty m_LegStretchProperty; - - SerializedProperty m_FeetSpacingProperty; - - SerializedProperty m_HasTranslationDoFProperty; - - const string sMinX = "m_Limit.m_Min.x"; - const string sMinY = "m_Limit.m_Min.y"; - const string sMinZ = "m_Limit.m_Min.z"; - - const string sMaxX = "m_Limit.m_Max.x"; - const string sMaxY = "m_Limit.m_Max.y"; - const string sMaxZ = "m_Limit.m_Max.z"; - const string sModified = "m_Limit.m_Modified"; - - const string sArmTwist = "m_HumanDescription.m_ArmTwist"; - const string sForeArmTwist = "m_HumanDescription.m_ForeArmTwist"; - const string sUpperLegTwist = "m_HumanDescription.m_UpperLegTwist"; - const string sLegTwist = "m_HumanDescription.m_LegTwist"; - - const string sArmStretch = "m_HumanDescription.m_ArmStretch"; - const string sLegStretch = "m_HumanDescription.m_LegStretch"; - - const string sFeetSpacing = "m_HumanDescription.m_FeetSpacing"; - - const string sHasTranslationDoF = "m_HumanDescription.m_HasTranslationDoF"; - - const float sMuscleMin = -180.0f; - const float sMuscleMax = 180.0f; - - const float kPreviewWidth = 80; - const float kNumberWidth = 38; - const float kLineHeight = 16; - - static Rect GetSettingsRect(Rect wholeWidthRect) - { - wholeWidthRect.xMin += (kPreviewWidth + 3); - wholeWidthRect.width -= 4; - return wholeWidthRect; - } - - static Rect GetSettingsRect() - { - return GetSettingsRect(GUILayoutUtility.GetRect(10, kLineHeight)); - } - - static Rect GetPreviewRect(Rect wholeWidthRect) - { - wholeWidthRect.width = kPreviewWidth - 9; - wholeWidthRect.x += 5; - wholeWidthRect.height = kLineHeight; - return wholeWidthRect; - } - - void HeaderGUI(string h1, string h2) - { - GUILayout.BeginHorizontal(); - GUILayout.Label(h1, styles.title, GUILayout.Width(kPreviewWidth)); - GUILayout.Label(h2, styles.title, GUILayout.ExpandWidth(true)); - GUILayout.EndHorizontal(); - } - - static float PreviewSlider(Rect position, float val) - { - val = GUI.HorizontalSlider(GetPreviewRect(position), val, -1, 1); - if (val > -0.1f && val < 0.1f) - val = 0; - return val; - } - - protected AvatarSetupTool.BoneWrapper[] m_Bones; - - internal void ResetValuesFromProperties() - { - m_ArmTwistFactor = m_ArmTwistProperty.floatValue; - m_ForeArmTwistFactor = m_ForeArmTwistProperty.floatValue; - m_UpperLegTwistFactor = m_UpperLegTwistProperty.floatValue; - m_LegTwistFactor = m_LegTwistProperty.floatValue; - m_ArmStretchFactor = m_ArmStretchProperty.floatValue; - m_LegStretchFactor = m_LegStretchProperty.floatValue; - m_FeetSpacingFactor = m_FeetSpacingProperty.floatValue; - m_HasTranslationDoF = m_HasTranslationDoFProperty.boolValue; - - // limit is a special case, because they are added dynamicly by the editor - // all the default value are wrong, we must explictly query mecanim to get the default value when - // m_Modified is set to false. - for (int i = 0; i < m_Bones.Length; i++) - { - if (m_Modified[i] != null) - { - bool modified = m_Modified[i].boolValue; - - int dx = HumanTrait.MuscleFromBone(i, 0); - int dy = HumanTrait.MuscleFromBone(i, 1); - int dz = HumanTrait.MuscleFromBone(i, 2); - if (dx != -1) - { - m_MuscleMinEdit[dx] = modified ? m_MuscleMin[dx].floatValue : HumanTrait.GetMuscleDefaultMin(dx); - m_MuscleMaxEdit[dx] = modified ? m_MuscleMax[dx].floatValue : HumanTrait.GetMuscleDefaultMax(dx); - } - - if (dy != -1) - { - m_MuscleMinEdit[dy] = modified ? m_MuscleMin[dy].floatValue : HumanTrait.GetMuscleDefaultMin(dy); - m_MuscleMaxEdit[dy] = modified ? m_MuscleMax[dy].floatValue : HumanTrait.GetMuscleDefaultMax(dy); - } - - if (dz != -1) - { - m_MuscleMinEdit[dz] = modified ? m_MuscleMin[dz].floatValue : HumanTrait.GetMuscleDefaultMin(dz); - m_MuscleMaxEdit[dz] = modified ? m_MuscleMax[dz].floatValue : HumanTrait.GetMuscleDefaultMax(dz); - } - } - } - } - - internal void InitializeProperties() - { - m_ArmTwistProperty = serializedObject.FindProperty(sArmTwist); - m_ForeArmTwistProperty = serializedObject.FindProperty(sForeArmTwist); - m_UpperLegTwistProperty = serializedObject.FindProperty(sUpperLegTwist); - m_LegTwistProperty = serializedObject.FindProperty(sLegTwist); - m_ArmStretchProperty = serializedObject.FindProperty(sArmStretch); - m_LegStretchProperty = serializedObject.FindProperty(sLegStretch); - m_FeetSpacingProperty = serializedObject.FindProperty(sFeetSpacing); - m_HasTranslationDoFProperty = serializedObject.FindProperty(sHasTranslationDoF); - - for (int i = 0; i < m_Bones.Length; i++) - { - SerializedProperty bone = m_Bones[i].GetSerializedProperty(serializedObject, false); - if (bone != null) - { - m_Modified[i] = bone.FindPropertyRelative(sModified); - - int dx = HumanTrait.MuscleFromBone(i, 0); - int dy = HumanTrait.MuscleFromBone(i, 1); - int dz = HumanTrait.MuscleFromBone(i, 2); - - - if (dx != -1) - { - m_MuscleMin[dx] = bone.FindPropertyRelative(sMinX); - m_MuscleMax[dx] = bone.FindPropertyRelative(sMaxX); - } - - if (dy != -1) - { - m_MuscleMin[dy] = bone.FindPropertyRelative(sMinY); - m_MuscleMax[dy] = bone.FindPropertyRelative(sMaxY); - } - - if (dz != -1) - { - m_MuscleMin[dz] = bone.FindPropertyRelative(sMinZ); - m_MuscleMax[dz] = bone.FindPropertyRelative(sMaxZ); - } - } - } - } - - internal void Initialize() - { - // Handle human bones - if (m_Bones == null) - m_Bones = AvatarSetupTool.GetHumanBones(serializedObject, modelBones); - - m_FocusedMuscle = -1; - - m_MuscleBodyGroupToggle = new bool[m_Muscles.Length]; - for (int i = 0; i < m_Muscles.Length; i++) - { - m_MuscleBodyGroupToggle[i] = false; - } - - m_MuscleName = HumanTrait.MuscleName; - for (int i = 0; i < m_MuscleName.Length; i++) - { - if (m_MuscleName[i].StartsWith("Right")) - m_MuscleName[i] = m_MuscleName[i].Substring(5).Trim(); - if (m_MuscleName[i].StartsWith("Left")) - m_MuscleName[i] = m_MuscleName[i].Substring(4).Trim(); - } - m_MuscleCount = HumanTrait.MuscleCount; - - m_MuscleToggle = new bool[m_MuscleCount]; - m_MuscleValue = new float[m_MuscleCount]; - m_MuscleMin = new SerializedProperty[m_MuscleCount]; - m_MuscleMax = new SerializedProperty[m_MuscleCount]; - - m_MuscleMinEdit = new float[m_MuscleCount]; - m_MuscleMaxEdit = new float[m_MuscleCount]; - - for (int i = 0; i < m_MuscleCount; i++) - { - m_MuscleToggle[i] = false; - m_MuscleValue[i] = 0; - m_MuscleMin[i] = null; - m_MuscleMin[i] = null; - } - - m_Modified = new SerializedProperty[m_Bones.Length]; - for (int i = 0; i < m_Bones.Length; i++) - { - m_Modified[i] = null; - } - - InitializeProperties(); - ResetValuesFromProperties(); - - m_MuscleMasterValue = new float[m_MasterMuscle.Length]; - for (int i = 0; i < m_MasterMuscle.Length; i++) - { - m_MuscleMasterValue[i] = 0; - } - } - - public override void Enable(AvatarEditor inspector) - { - base.Enable(inspector); - - Initialize(); - - WritePose(); - } - - public override void OnInspectorGUI() - { - if (Event.current.type == EventType.ValidateCommand && Event.current.commandName == EventCommandNames.UndoRedoPerformed) - { - WritePose(); - } - - if (avatarAsset == null) - { - return; - } - - using (new EditorGUI.DisabledScope(!avatarAsset.isHuman)) - { - EditorGUIUtility.labelWidth = 110; - EditorGUIUtility.fieldWidth = 40; - - GUILayout.BeginHorizontal(); - GUILayout.BeginVertical(); - - MuscleGroupGUI(); - EditorGUILayout.Space(); - MuscleGUI(); - EditorGUILayout.Space(); - PropertiesGUI(); - - GUILayout.EndVertical(); - GUILayout.Space(1); - GUILayout.EndHorizontal(); - - DisplayMuscleButtons(); - - ApplyRevertGUI(); - } - } - - protected void DisplayMuscleButtons() - { - GUILayout.BeginHorizontal("", styles.toolbar, GUILayout.ExpandWidth(true)); - { - Rect r; - - // Muscle - r = GUILayoutUtility.GetRect(styles.muscle, styles.toolbarDropDown); - if (GUI.Button(r, styles.muscle, styles.toolbarDropDown)) - { - GenericMenu menu = new GenericMenu(); - menu.AddItem(styles.resetMuscle, false, ResetMuscleToDefault); - menu.DropDown(r); - } - - GUILayout.FlexibleSpace(); - } - GUILayout.EndHorizontal(); - } - - protected override void ResetValues() - { - serializedObject.Update(); - ResetValuesFromProperties(); - } - - protected void ResetMuscleToDefault() - { - Avatar avatar = null; - // For live update, update instanciate avatar to adjust pose - if (gameObject != null) - { - Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator; - avatar = animator.avatar; - } - - for (int i = 0; i < m_MuscleCount; i++) - { - float min = HumanTrait.GetMuscleDefaultMin(i); - float max = HumanTrait.GetMuscleDefaultMax(i); - - if (m_MuscleMin[i] != null && m_MuscleMax[i] != null) - { - m_MuscleMin[i].floatValue = m_MuscleMinEdit[i] = min; - m_MuscleMax[i].floatValue = m_MuscleMaxEdit[i] = max; - } - - int humanId = HumanTrait.BoneFromMuscle(i); - if (m_Modified[humanId] != null && humanId != -1) - m_Modified[humanId].boolValue = false; - - if (avatar != null) - avatar.SetMuscleMinMax(i, min, max); - } - - WritePose(); - } - - protected void UpdateAvatarParameter(HumanParameter parameterId, float value) - { - // For live update, update instanciate avatar to adjust pose - if (gameObject != null) - { - Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator; - Avatar avatar = animator.avatar; - avatar.SetParameter((int)parameterId, value); - } - } - - protected bool UpdateMuscle(int muscleId, float min, float max) - { - Undo.RegisterCompleteObjectUndo(this, "Updated muscle range"); - m_MuscleMin[muscleId].floatValue = min; - m_MuscleMax[muscleId].floatValue = max; - - int humanId = HumanTrait.BoneFromMuscle(muscleId); - if (humanId != -1) - { - if (!m_Modified[humanId].boolValue) - { - int mx = HumanTrait.MuscleFromBone(humanId, 0); - int my = HumanTrait.MuscleFromBone(humanId, 1); - int mz = HumanTrait.MuscleFromBone(humanId, 2); - - if (mx != -1 && mx != muscleId) - { - m_MuscleMin[mx].floatValue = HumanTrait.GetMuscleDefaultMin(mx); - m_MuscleMax[mx].floatValue = HumanTrait.GetMuscleDefaultMax(mx); - } - - if (my != -1 && my != muscleId) - { - m_MuscleMin[my].floatValue = HumanTrait.GetMuscleDefaultMin(my); - m_MuscleMax[my].floatValue = HumanTrait.GetMuscleDefaultMax(my); - } - - if (mz != -1 && mz != muscleId) - { - m_MuscleMin[mz].floatValue = HumanTrait.GetMuscleDefaultMin(mz); - m_MuscleMax[mz].floatValue = HumanTrait.GetMuscleDefaultMax(mz); - } - } - - m_Modified[humanId].boolValue = true; - } - - // OnSceneGUI need focused muscle to know which one to draw - m_FocusedMuscle = muscleId; - - // For live update, update instanciate avatar to adjust pose - if (gameObject != null) - { - Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator; - Avatar avatar = animator.avatar; - avatar.SetMuscleMinMax(muscleId, min, max); - } - - // Need to repaint scene to update muscle range handle - SceneView.RepaintAll(); - - return gameObject != null; - } - - protected void MuscleGroupGUI() - { - bool recomputePose = false; - - HeaderGUI("Preview", "Muscle Group Preview"); - GUILayout.BeginVertical(styles.box); - { - { - Rect r = GUILayoutUtility.GetRect(10, kLineHeight); - Rect settingsRect = GetSettingsRect(r); - Rect previewRect = GetPreviewRect(r); - if (GUI.Button(previewRect, "Reset All", EditorStyles.miniButton)) - { - for (int i = 0; i < m_MuscleMasterValue.Length; i++) - m_MuscleMasterValue[i] = 0; - for (int i = 0; i < m_MuscleValue.Length; i++) - m_MuscleValue[i] = 0; - recomputePose = true; - } - - GUI.Label(settingsRect, "Reset All Preview Values", EditorStyles.label); - } - - for (int i = 0; i < m_MasterMuscle.Length; i++) - { - Rect r = GUILayoutUtility.GetRect(10, kLineHeight); - Rect settingsRect = GetSettingsRect(r); - - float oldValue = m_MuscleMasterValue[i]; - m_MuscleMasterValue[i] = PreviewSlider(r, m_MuscleMasterValue[i]); - if (m_MuscleMasterValue[i] != oldValue) - { - Undo.RegisterCompleteObjectUndo(this, "Muscle preview"); - for (int j = 0; j < m_MasterMuscle[i].Length; j++) - { - if (m_MasterMuscle[i][j] != -1) - { - m_MuscleValue[m_MasterMuscle[i][j]] = m_MuscleMasterValue[i]; - } - } - } - // Muscle value changed and we do have a game object to update - recomputePose |= m_MuscleMasterValue[i] != oldValue && gameObject != null; - - GUI.Label(settingsRect, styles.muscleTypeGroup[i], EditorStyles.label); - } - } - GUILayout.EndVertical(); - - if (recomputePose) - WritePose(); - } - - protected void MuscleGUI() - { - bool recomputePose = false; - - HeaderGUI("Preview", "Per-Muscle Settings"); - GUILayout.BeginVertical(styles.box); - { - Rect r, settingsRect; - const int indentPerLevel = 15; - for (int i = 0; i < m_MuscleBodyGroupToggle.Length; i++) - { - r = GUILayoutUtility.GetRect(10, kLineHeight); - settingsRect = GetSettingsRect(r); - m_MuscleBodyGroupToggle[i] = GUI.Toggle(settingsRect, m_MuscleBodyGroupToggle[i], styles.muscleBodyGroup[i], EditorStyles.foldout); - if (m_MuscleBodyGroupToggle[i]) - { - for (int j = 0; j < m_Muscles[i].Length; j++) - { - int muscleId = m_Muscles[i][j]; - // Some muscle can be optionnal like Toes, if this bone is not characterized you can't edit this muscle - if (muscleId != -1 && m_MuscleMin[muscleId] != null && m_MuscleMax[muscleId] != null) - { - bool expanded = m_MuscleToggle[muscleId]; - - r = GUILayoutUtility.GetRect(10, expanded ? kLineHeight * 2 : kLineHeight); - settingsRect = GetSettingsRect(r); - settingsRect.xMin += indentPerLevel; - - // Foldout - settingsRect.height = kLineHeight; - m_MuscleToggle[muscleId] = GUI.Toggle(settingsRect, m_MuscleToggle[muscleId], m_MuscleName[muscleId], EditorStyles.foldout); - - // Preview slider - float value = PreviewSlider(r, m_MuscleValue[muscleId]); - // OnSceneGUI need focused muscle to know which one to draw - if (m_MuscleValue[muscleId] != value) - { - Undo.RegisterCompleteObjectUndo(this, "Muscle preview"); - m_FocusedMuscle = muscleId; - m_MuscleValue[muscleId] = value; - recomputePose |= (gameObject != null); - } - - if (expanded) - { - bool muscleChanged = false; - - settingsRect.xMin += indentPerLevel; - settingsRect.y += kLineHeight; - - Rect sliderRect = settingsRect; - - if (settingsRect.width > 160) - { - Rect numberRect = settingsRect; - numberRect.width = kNumberWidth; - - EditorGUI.BeginChangeCheck(); - m_MuscleMinEdit[muscleId] = EditorGUI.FloatField(numberRect, m_MuscleMinEdit[muscleId]); - muscleChanged |= EditorGUI.EndChangeCheck(); - - numberRect.x = settingsRect.xMax - kNumberWidth; - - EditorGUI.BeginChangeCheck(); - m_MuscleMaxEdit[muscleId] = EditorGUI.FloatField(numberRect, m_MuscleMaxEdit[muscleId]); - muscleChanged |= EditorGUI.EndChangeCheck(); - - sliderRect.xMin += (kNumberWidth + 5); - sliderRect.xMax -= (kNumberWidth + 5); - } - - EditorGUI.BeginChangeCheck(); - EditorGUI.MinMaxSlider(sliderRect, ref m_MuscleMinEdit[muscleId], ref m_MuscleMaxEdit[muscleId], sMuscleMin, sMuscleMax); - muscleChanged |= EditorGUI.EndChangeCheck(); - - if (muscleChanged) - { - m_MuscleMinEdit[muscleId] = Mathf.Clamp(m_MuscleMinEdit[muscleId], sMuscleMin, 0); - m_MuscleMaxEdit[muscleId] = Mathf.Clamp(m_MuscleMaxEdit[muscleId], 0, sMuscleMax); - recomputePose |= UpdateMuscle(muscleId, m_MuscleMinEdit[muscleId], m_MuscleMaxEdit[muscleId]); - } - } - } - } - } - } - } - GUILayout.EndVertical(); - - if (recomputePose) - WritePose(); - } - - protected void PropertiesGUI() - { - bool recomputePose = false; - - HeaderGUI("", "Additional Settings"); - GUILayout.BeginVertical(styles.box); - { - m_ArmTwistFactor = EditorGUI.Slider(GetSettingsRect(), styles.armTwist, m_ArmTwistFactor, 0, 1); - if (m_ArmTwistProperty.floatValue != m_ArmTwistFactor) - { - Undo.RegisterCompleteObjectUndo(this, "Upper arm twist"); - m_ArmTwistProperty.floatValue = m_ArmTwistFactor; - UpdateAvatarParameter(HumanParameter.UpperArmTwist, m_ArmTwistFactor); - recomputePose = true; - } - - m_ForeArmTwistFactor = EditorGUI.Slider(GetSettingsRect(), styles.foreArmTwist, m_ForeArmTwistFactor, 0, 1); - if (m_ForeArmTwistProperty.floatValue != m_ForeArmTwistFactor) - { - Undo.RegisterCompleteObjectUndo(this, "Lower arm twist"); - m_ForeArmTwistProperty.floatValue = m_ForeArmTwistFactor; - UpdateAvatarParameter(HumanParameter.LowerArmTwist, m_ForeArmTwistFactor); - recomputePose = true; - } - - m_UpperLegTwistFactor = EditorGUI.Slider(GetSettingsRect(), styles.upperLegTwist, m_UpperLegTwistFactor, 0, 1); - if (m_UpperLegTwistProperty.floatValue != m_UpperLegTwistFactor) - { - Undo.RegisterCompleteObjectUndo(this, "Upper leg twist"); - m_UpperLegTwistProperty.floatValue = m_UpperLegTwistFactor; - UpdateAvatarParameter(HumanParameter.UpperLegTwist, m_UpperLegTwistFactor); - recomputePose = true; - } - - m_LegTwistFactor = EditorGUI.Slider(GetSettingsRect(), styles.legTwist, m_LegTwistFactor, 0, 1); - if (m_LegTwistProperty.floatValue != m_LegTwistFactor) - { - Undo.RegisterCompleteObjectUndo(this, "Lower leg twist"); - m_LegTwistProperty.floatValue = m_LegTwistFactor; - UpdateAvatarParameter(HumanParameter.LowerLegTwist, m_LegTwistFactor); - recomputePose = true; - } - - m_ArmStretchFactor = EditorGUI.Slider(GetSettingsRect(), styles.armStretch, m_ArmStretchFactor, 0, 1); - if (m_ArmStretchProperty.floatValue != m_ArmStretchFactor) - { - Undo.RegisterCompleteObjectUndo(this, "Arm stretch"); - m_ArmStretchProperty.floatValue = m_ArmStretchFactor; - UpdateAvatarParameter(HumanParameter.ArmStretch, m_ArmStretchFactor); - recomputePose = true; - } - - m_LegStretchFactor = EditorGUI.Slider(GetSettingsRect(), styles.legStretch, m_LegStretchFactor, 0, 1); - if (m_LegStretchProperty.floatValue != m_LegStretchFactor) - { - Undo.RegisterCompleteObjectUndo(this, "Leg stretch"); - m_LegStretchProperty.floatValue = m_LegStretchFactor; - UpdateAvatarParameter(HumanParameter.LegStretch, m_LegStretchFactor); - recomputePose = true; - } - - m_FeetSpacingFactor = EditorGUI.Slider(GetSettingsRect(), styles.feetSpacing, m_FeetSpacingFactor, 0, 1); - if (m_FeetSpacingProperty.floatValue != m_FeetSpacingFactor) - { - Undo.RegisterCompleteObjectUndo(this, "Feet spacing"); - m_FeetSpacingProperty.floatValue = m_FeetSpacingFactor; - UpdateAvatarParameter(HumanParameter.FeetSpacing, m_FeetSpacingFactor); - recomputePose = true; - } - - m_HasTranslationDoF = EditorGUI.Toggle(GetSettingsRect(), styles.hasTranslationDoF, m_HasTranslationDoF); - if (m_HasTranslationDoFProperty.boolValue != m_HasTranslationDoF) - { - Undo.RegisterCompleteObjectUndo(this, "Translation DoF"); - m_HasTranslationDoFProperty.boolValue = m_HasTranslationDoF; - } - } - GUILayout.EndVertical(); - - if (recomputePose) - WritePose(); - } - - protected void WritePose() - { - if (gameObject) - { - Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator; - if (animator != null) - { - Avatar avatar = animator.avatar; - if (avatar != null && avatar.isValid && avatar.isHuman) - { - AvatarUtility.SetHumanPose(animator, m_MuscleValue); - SceneView.RepaintAll(); - } - } - } - } - - public void DrawMuscleHandle(Transform t, int humanId) - { - Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator; - Avatar avatar = animator.avatar; - - int mx = HumanTrait.MuscleFromBone(humanId, 0); - int my = HumanTrait.MuscleFromBone(humanId, 1); - int mz = HumanTrait.MuscleFromBone(humanId, 2); - - float axisLen = avatar.GetAxisLength(humanId); - Quaternion preQ = avatar.GetPreRotation(humanId); - Quaternion postQ = avatar.GetPostRotation(humanId); - - preQ = t.parent.rotation * preQ; - postQ = t.rotation * postQ; - - Vector3 normal; - Vector3 from; - - Color alpha = new Color(1, 1, 1, 0.5f); - Quaternion zyRoll = avatar.GetZYRoll(humanId, Vector3.zero); - Vector3 sign = avatar.GetLimitSign(humanId); - - // Draw axis - normal = postQ * Vector3.right; - Vector3 axisEnd = t.position + (normal * axisLen); - Handles.color = Color.white; - Handles.DrawLine(t.position, axisEnd); - - if (mx != -1) - { - Quaternion zyPostQ = avatar.GetZYPostQ(humanId, t.parent.rotation, t.rotation); - - float minx = m_MuscleMinEdit[mx]; - float maxx = m_MuscleMaxEdit[mx]; - - normal = postQ * Vector3.right; - from = zyPostQ * Vector3.forward; - - Handles.color = Color.black; - //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f)); - - Vector3 xDoF = t.position + (normal * axisLen * 0.75f); - - normal = postQ * Vector3.right * sign.x; - Quaternion q = Quaternion.AngleAxis(minx, normal); - from = q * from; - - Handles.color = Color.yellow; - //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f)); - - // Draw Muscle range - Handles.color = Handles.xAxisColor * alpha; - Handles.DrawSolidArc(xDoF, normal, from, maxx - minx, axisLen * 0.25f); - - from = postQ * Vector3.forward; - Handles.color = Handles.centerColor; - Handles.DrawLine(xDoF, xDoF + (from * axisLen * 0.25f)); - } - - if (my != -1) - { - float miny = m_MuscleMinEdit[my]; - float maxy = m_MuscleMaxEdit[my]; - - normal = preQ * Vector3.up * sign.y; - from = preQ * zyRoll * Vector3.right; - - Handles.color = Color.black; - //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f)); - - Quaternion q = Quaternion.AngleAxis(miny, normal); - from = q * from; - - Handles.color = Color.yellow; - //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f)); - - // Draw Muscle range - Handles.color = Handles.yAxisColor * alpha; - Handles.DrawSolidArc(t.position, normal, from, maxy - miny, axisLen * 0.25f); - } - if (mz != -1) - { - float minz = m_MuscleMinEdit[mz]; - float maxz = m_MuscleMaxEdit[mz]; - - normal = preQ * Vector3.forward * sign.z; - from = preQ * zyRoll * Vector3.right; - - Handles.color = Color.black; - //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f)); - - Quaternion q = Quaternion.AngleAxis(minz, normal); - from = q * from; - - Handles.color = Color.yellow; - //Handles.DrawLine (t.position, t.position + (from * axisLen * 0.75f)); - - // Draw Muscle range - Handles.color = Handles.zAxisColor * alpha; - Handles.DrawSolidArc(t.position, normal, from, maxz - minz, axisLen * 0.25f); - } - } - - public override void OnSceneGUI() - { - AvatarSkeletonDrawer.DrawSkeleton(root, modelBones); - - if (gameObject == null) - return; - - Animator animator = gameObject.GetComponent(typeof(Animator)) as Animator; - if (m_FocusedMuscle == -1 || animator == null) - return; - - int humanId = HumanTrait.BoneFromMuscle(m_FocusedMuscle); - if (humanId != -1) - { - DrawMuscleHandle(m_Bones[humanId].bone, humanId); - } - } - } -} diff --git a/Editor/Mono/Inspector/Avatar/AvatarSetupTool.cs b/Editor/Mono/Inspector/Avatar/AvatarSetupTool.cs deleted file mode 100644 index dd8baa2b97..0000000000 --- a/Editor/Mono/Inspector/Avatar/AvatarSetupTool.cs +++ /dev/null @@ -1,1340 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.Collections.Generic; -using System.Linq; - -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal static class AvatarSetupTool - { - [System.Serializable] - internal class BoneWrapper - { - private static string sHumanName = "m_HumanName"; - private static string sBoneName = "m_BoneName"; - - private string m_HumanBoneName; - public string humanBoneName { get { return m_HumanBoneName; } } - public string error = string.Empty; - public Transform bone; - public BoneState state; - - public string messageName - { - get - { - return ObjectNames.NicifyVariableName(m_HumanBoneName) + " Transform '" + (bone ? bone.name : "None") + "'"; - } - } - - public BoneWrapper(string humanBoneName, SerializedObject serializedObject, Dictionary bones) - { - m_HumanBoneName = humanBoneName; - Reset(serializedObject, bones); - } - - public void Reset(SerializedObject serializedObject, Dictionary bones) - { - bone = null; - SerializedProperty property = GetSerializedProperty(serializedObject, false); - if (property != null) - { - string boneName = property.FindPropertyRelative(sBoneName).stringValue; - bone = bones.Keys.FirstOrDefault(b => (b != null && b.name == boneName)); - } - state = BoneState.Valid; - } - - public void Serialize(SerializedObject serializedObject) - { - if (bone == null) - { - DeleteSerializedProperty(serializedObject); - } - else - { - SerializedProperty property = GetSerializedProperty(serializedObject, true); - if (property != null) - property.FindPropertyRelative(sBoneName).stringValue = bone.name; - } - } - - protected void DeleteSerializedProperty(SerializedObject serializedObject) - { - SerializedProperty humanBoneArray = serializedObject.FindProperty(sHuman); - if (humanBoneArray == null || !humanBoneArray.isArray) - return; - - for (int i = 0; i < humanBoneArray.arraySize; i++) - { - SerializedProperty humanNameP = humanBoneArray.GetArrayElementAtIndex(i).FindPropertyRelative(sHumanName); - if (humanNameP.stringValue == humanBoneName) - { - humanBoneArray.DeleteArrayElementAtIndex(i); - break; - } - } - } - - public SerializedProperty GetSerializedProperty(SerializedObject serializedObject, bool createIfMissing) - { - SerializedProperty humanBoneArray = serializedObject.FindProperty(sHuman); - if (humanBoneArray == null || !humanBoneArray.isArray) - return null; - - for (int i = 0; i < humanBoneArray.arraySize; i++) - { - SerializedProperty humanNameP = humanBoneArray.GetArrayElementAtIndex(i).FindPropertyRelative(sHumanName); - if (humanNameP.stringValue == humanBoneName) - return humanBoneArray.GetArrayElementAtIndex(i); - } - - if (createIfMissing) - { - humanBoneArray.arraySize++; - SerializedProperty bone = humanBoneArray.GetArrayElementAtIndex(humanBoneArray.arraySize - 1); - if (bone != null) - { - bone.FindPropertyRelative(sHumanName).stringValue = humanBoneName; - return bone; - } - } - - return null; - } - - public const int kIconSize = 19; - - static Color kBoneValid = new Color(0, 0.75f, 0, 1.0f); - static Color kBoneInvalid = new Color(1.0f, 0.3f, 0.25f, 1.0f); - static Color kBoneInactive = Color.gray; - static Color kBoneSelected = new Color(0.4f, 0.7f, 1.0f, 1.0f); - static Color kBoneDrop = new Color(0.1f, 0.7f, 1.0f, 1.0f); - public void BoneDotGUI(Rect rect, Rect selectRect, int boneIndex, bool doClickSelect, bool doDragDrop, bool doDeleteKey, SerializedObject serializedObject, AvatarMappingEditor editor) - { - int id = GUIUtility.GetControlID(FocusType.Passive, rect); - int keyboardID = GUIUtility.GetControlID(FocusType.Keyboard, selectRect); - - if (doClickSelect) - HandleClickSelection(keyboardID, selectRect, boneIndex); - - if (doDeleteKey) - HandleDeleteSelection(keyboardID, serializedObject, editor); - - if (doDragDrop) - HandleDragDrop(rect, boneIndex, id, serializedObject, editor); - - Color old = GUI.color; - - // Selection - if (AvatarMappingEditor.s_SelectedBoneIndex == boneIndex) - { - GUI.color = kBoneSelected; - GUI.DrawTexture(rect, AvatarMappingEditor.styles.dotSelection.image); - } - - // State color - if (DragAndDrop.activeControlID == id) - GUI.color = kBoneDrop; - else if (state == BoneState.Valid) - GUI.color = kBoneValid; - else if (state == BoneState.None) - GUI.color = kBoneInactive; - else - GUI.color = kBoneInvalid; - - // Frame - Texture tex; - if (HumanTrait.RequiredBone(boneIndex)) - tex = AvatarMappingEditor.styles.dotFrame.image; - else - tex = AvatarMappingEditor.styles.dotFrameDotted.image; - GUI.DrawTexture(rect, tex); - - // Fill - if (bone != null || DragAndDrop.activeControlID == id) - GUI.DrawTexture(rect, AvatarMappingEditor.styles.dotFill.image); - - GUI.color = old; - } - - public void HandleClickSelection(int keyboardID, Rect selectRect, int boneIndex) - { - Event evt = Event.current; - if (evt.type == EventType.MouseDown && selectRect.Contains(evt.mousePosition)) - { - AvatarMappingEditor.s_SelectedBoneIndex = boneIndex; - AvatarMappingEditor.s_DirtySelection = true; - // case 837655. Late update GUIUtility.keyboardControl to avoid it being overriden during scene selection. - AvatarMappingEditor.s_KeyboardControl = keyboardID; - Selection.activeTransform = bone; - if (bone != null) - EditorGUIUtility.PingObject(bone); - evt.Use(); - } - } - - public void HandleDeleteSelection(int keyboardID, SerializedObject serializedObject, AvatarMappingEditor editor) - { - Event evt = Event.current; - if (evt.type == EventType.KeyDown) - { - if (GUIUtility.keyboardControl == keyboardID) - { - if ((evt.keyCode == KeyCode.Backspace) || (evt.keyCode == KeyCode.Delete)) - { - Undo.RegisterCompleteObjectUndo(editor, "Avatar mapping modified"); - - // Unreference transform component in selected bone. - bone = null; - state = BoneState.None; - Serialize(serializedObject); - - // Clear scene selection. - Selection.activeTransform = null; - - GUI.changed = true; - evt.Use(); - } - } - } - } - - private void HandleDragDrop(Rect dropRect, int boneIndex, int id, SerializedObject serializedObject, AvatarMappingEditor editor) - { - EventType eventType = Event.current.type; - switch (eventType) - { - case EventType.DragExited: - if (GUI.enabled) - HandleUtility.Repaint(); - break; - case EventType.DragUpdated: - case EventType.DragPerform: - if (dropRect.Contains(Event.current.mousePosition) && GUI.enabled) - { - Object[] references = DragAndDrop.objectReferences; - Object validatedObject = references.Length == 1 ? references[0] : null; - if (validatedObject != null) - { - if (!(validatedObject is Transform || validatedObject is GameObject) || EditorUtility.IsPersistent(validatedObject)) - validatedObject = null; - } - if (validatedObject != null) - { - DragAndDrop.visualMode = DragAndDropVisualMode.Generic; - if (eventType == EventType.DragPerform) - { - Undo.RegisterCompleteObjectUndo(editor, "Avatar mapping modified"); - - if (validatedObject is GameObject) - bone = (validatedObject as GameObject).transform; - else - bone = validatedObject as Transform; - - Serialize(serializedObject); - - GUI.changed = true; - DragAndDrop.AcceptDrag(); - DragAndDrop.activeControlID = 0; - } - else - { - DragAndDrop.activeControlID = id; - } - Event.current.Use(); - } - } - break; - } - } - } - - private class BonePoseData - { - public Vector3 direction = Vector3.zero; - public bool compareInGlobalSpace = false; - public float maxAngle; - public int[] childIndices = null; - public Vector3 planeNormal = Vector3.zero; - public BonePoseData(Vector3 dir, bool globalSpace, float maxAngleDiff) - { - direction = (dir == Vector3.zero ? dir : dir.normalized); - compareInGlobalSpace = globalSpace; - maxAngle = maxAngleDiff; - } - - public BonePoseData(Vector3 dir, bool globalSpace, float maxAngleDiff, int[] children) : this(dir, globalSpace, maxAngleDiff) - { - childIndices = children; - } - - public BonePoseData(Vector3 dir, bool globalSpace, float maxAngleDiff, Vector3 planeNormal, int[] children) : this(dir, globalSpace, maxAngleDiff, children) - { - this.planeNormal = planeNormal; - } - } - - private static string sHuman = "m_HumanDescription.m_Human"; - private static string sHasTranslationDoF = "m_HumanDescription.m_HasTranslationDoF"; - - internal static string sSkeleton = "m_HumanDescription.m_Skeleton"; - internal static string sName = "m_Name"; - internal static string sParentName = "m_ParentName"; - internal static string sPosition = "m_Position"; - internal static string sRotation = "m_Rotation"; - internal static string sScale = "m_Scale"; - - private static BonePoseData[] sBonePoses = new BonePoseData[] - { - new BonePoseData(Vector3.up, true, 15), // Hips, - new BonePoseData(new Vector3(-0.05f, -1, 0), true, 15), // LeftUpperLeg, - new BonePoseData(new Vector3(0.05f, -1, 0), true, 15), // RightUpperLeg, - new BonePoseData(new Vector3(-0.05f, -1, -0.15f), true, 20), // LeftLowerLeg, - new BonePoseData(new Vector3(0.05f, -1, -0.15f), true, 20), // RightLowerLeg, - new BonePoseData(new Vector3(-0.05f, 0, 1), true, 20, Vector3.up, null), // LeftFoot, - new BonePoseData(new Vector3(0.05f, 0, 1), true, 20, Vector3.up, null), // RightFoot, - new BonePoseData(Vector3.up, true, 30, new int[] {(int)HumanBodyBones.Chest, (int)HumanBodyBones.UpperChest, (int)HumanBodyBones.Neck, (int)HumanBodyBones.Head}), // Spine, - new BonePoseData(Vector3.up, true, 30, new int[] {(int)HumanBodyBones.UpperChest, (int)HumanBodyBones.Neck, (int)HumanBodyBones.Head}), // Chest, - new BonePoseData(Vector3.up, true, 30), // Neck, - null, // Head, - new BonePoseData(-Vector3.right, true, 20), // LeftShoulder, - new BonePoseData(Vector3.right, true, 20), // RightShoulder, - new BonePoseData(-Vector3.right, true, 05), // LeftArm, - new BonePoseData(Vector3.right, true, 05), // RightArm, - new BonePoseData(-Vector3.right, true, 05), // LeftForeArm, - new BonePoseData(Vector3.right, true, 05), // RightForeArm, - new BonePoseData(-Vector3.right, false, 10, Vector3.forward, new int[] {(int)HumanBodyBones.LeftMiddleProximal}), // LeftHand, - new BonePoseData(Vector3.right, false, 10, Vector3.forward, new int[] {(int)HumanBodyBones.RightMiddleProximal}), // RightHand, - null, // LeftToes, - null, // RightToes, - null, // LeftEye, - null, // RightEye, - null, // Jaw, - new BonePoseData(new Vector3(-1, 0, 1), false, 10), // Left Thumb - new BonePoseData(new Vector3(-1, 0, 1), false, 05), - new BonePoseData(new Vector3(-1, 0, 1), false, 05), - new BonePoseData(-Vector3.right, false, 10), // Left Index - new BonePoseData(-Vector3.right, false, 05), - new BonePoseData(-Vector3.right, false, 05), - new BonePoseData(-Vector3.right, false, 10), // Left Middle - new BonePoseData(-Vector3.right, false, 05), - new BonePoseData(-Vector3.right, false, 05), - new BonePoseData(-Vector3.right, false, 10), // Left Ring - new BonePoseData(-Vector3.right, false, 05), - new BonePoseData(-Vector3.right, false, 05), - new BonePoseData(-Vector3.right, false, 10), // Left Little - new BonePoseData(-Vector3.right, false, 05), - new BonePoseData(-Vector3.right, false, 05), - new BonePoseData(new Vector3(1, 0, 1), false, 10), // Right Thumb - new BonePoseData(new Vector3(1, 0, 1), false, 05), - new BonePoseData(new Vector3(1, 0, 1), false, 05), - new BonePoseData(Vector3.right, false, 10), // Right Index - new BonePoseData(Vector3.right, false, 05), - new BonePoseData(Vector3.right, false, 05), - new BonePoseData(Vector3.right, false, 10), // Right Middle - new BonePoseData(Vector3.right, false, 05), - new BonePoseData(Vector3.right, false, 05), - new BonePoseData(Vector3.right, false, 10), // Right Ring - new BonePoseData(Vector3.right, false, 05), - new BonePoseData(Vector3.right, false, 05), - new BonePoseData(Vector3.right, false, 10), // Right Little - new BonePoseData(Vector3.right, false, 05), - new BonePoseData(Vector3.right, false, 05), - new BonePoseData(Vector3.up, true, 30, new int[] {(int)HumanBodyBones.Neck, (int)HumanBodyBones.Head}), // UpperChest, - }; - - public static Dictionary GetModelBones(Transform root, bool includeAll, BoneWrapper[] humanBones) - { - if (root == null) - return null; - - // Find out which transforms are actual bones and which are parents of actual bones - Dictionary bones = new Dictionary(); - List skinnedBones = new List(); - - if (!includeAll) - { - // Find out in advance which bones are used by SkinnedMeshRenderers - SkinnedMeshRenderer[] skinnedMeshRenderers = root.GetComponentsInChildren(); - - foreach (SkinnedMeshRenderer rend in skinnedMeshRenderers) - { - Transform[] meshBones = rend.bones; - bool[] meshBonesUsed = new bool[meshBones.Length]; - BoneWeight[] weights = rend.sharedMesh.boneWeights; - foreach (BoneWeight w in weights) - { - if (w.weight0 != 0) - meshBonesUsed[w.boneIndex0] = true; - if (w.weight1 != 0) - meshBonesUsed[w.boneIndex1] = true; - if (w.weight2 != 0) - meshBonesUsed[w.boneIndex2] = true; - if (w.weight3 != 0) - meshBonesUsed[w.boneIndex3] = true; - } - for (int i = 0; i < meshBones.Length; i++) - { - if (meshBonesUsed[i]) - if (!skinnedBones.Contains(meshBones[i])) - skinnedBones.Add(meshBones[i]); - } - } - - // Recursive call - DetermineIsActualBone(root, bones, skinnedBones, false, humanBones); - } - - // If not enough bones were found, fallback to treating all transforms as bones - if (bones.Count < HumanTrait.RequiredBoneCount) - { - bones.Clear(); - skinnedBones.Clear(); - DetermineIsActualBone(root, bones, skinnedBones, true, humanBones); - } - - return bones; - } - - private static bool DetermineIsActualBone(Transform tr, Dictionary bones, List skinnedBones, bool includeAll, BoneWrapper[] humanBones) - { - bool actualBone = includeAll; - bool boneParent = false; - bool boneChild = false; - - // Actual bone parent if any of children are bones - int childBones = 0; - foreach (Transform child in tr) - if (DetermineIsActualBone(child, bones, skinnedBones, includeAll, humanBones)) - childBones++; - - if (childBones > 0) - boneParent = true; - if (childBones > 1) - actualBone = true; - - // Actual bone if used by skinned mesh - if (!actualBone) - if (skinnedBones.Contains(tr)) - actualBone = true; - - // Actual bone if contains component other than transform - if (!actualBone) - { - Component[] components = tr.GetComponents(); - if (components.Length > 1) - { - foreach (Component comp in components) - { - if ((comp is Renderer) && !(comp is SkinnedMeshRenderer)) - { - Bounds bounds = (comp as Renderer).bounds; - - // Double size of bounds in order to still make bone valid - // if its pivot is just slightly outside of renderer bounds. - bounds.extents = bounds.size; - - // If the parent is inside the bounds, this transform is probably - // just a geometry dummy for the parent bone - if (tr.childCount == 0 && tr.parent && bounds.Contains(tr.parent.position)) - { - if (tr.parent.GetComponent() != null) - actualBone = true; - else - boneChild = true; - } - // if not, give transform itself a chance. - // If pivot is way outside of bounds, it's not an actual bone. - else if (bounds.Contains(tr.position)) - { - actualBone = true; - } - } - } - } - } - - // Actual bone if the bone is define in human definition. - if (!actualBone && humanBones != null) - { - foreach (var boneWrapper in humanBones) - { - if (tr == boneWrapper.bone) - { - actualBone = true; - break; - } - } - } - - if (actualBone) - bones[tr] = true; - else if (boneParent) - { - if (!bones.ContainsKey(tr)) - bones[tr] = false; - } - else if (boneChild) - bones[tr.parent] = true; - - return bones.ContainsKey(tr); - } - - public static int GetFirstHumanBoneAncestor(BoneWrapper[] bones, int boneIndex) - { - boneIndex = HumanTrait.GetParentBone(boneIndex); - while (boneIndex > 0 && bones[boneIndex].bone == null) - boneIndex = HumanTrait.GetParentBone(boneIndex); - return boneIndex; - } - - public static int GetHumanBoneChild(BoneWrapper[] bones, int boneIndex) - { - for (int i = 0; i < HumanTrait.BoneCount; i++) - if (HumanTrait.GetParentBone(i) == boneIndex) - return i; - return -1; - } - - public static BoneWrapper[] GetHumanBones(SerializedObject serializedObject, Dictionary actualBones) - { - string[] humanBoneNames = HumanTrait.BoneName; - BoneWrapper[] bones = new BoneWrapper[humanBoneNames.Length]; - for (int i = 0; i < humanBoneNames.Length; i++) - bones[i] = new BoneWrapper(humanBoneNames[i], serializedObject, actualBones); - return bones; - } - - public static void ClearAll(SerializedObject serializedObject) - { - ClearHumanBoneArray(serializedObject); - ClearSkeletonBoneArray(serializedObject); - } - - public static void ClearHumanBoneArray(SerializedObject serializedObject) - { - SerializedProperty humanBody = serializedObject.FindProperty(sHuman); - if (humanBody != null && humanBody.isArray) - humanBody.ClearArray(); - } - - public static void ClearSkeletonBoneArray(SerializedObject serializedObject) - { - SerializedProperty skeleton = serializedObject.FindProperty(sSkeleton); - if (skeleton != null && skeleton.isArray) - skeleton.ClearArray(); - } - - public static void AutoSetupOnInstance(GameObject modelPrefab, SerializedObject modelImporterSerializedObject) - { - GameObject instance = GameObject.Instantiate(modelPrefab) as GameObject; - instance.hideFlags = HideFlags.HideAndDontSave; - AvatarSetupTool.AutoSetup(modelPrefab, instance, modelImporterSerializedObject); - GameObject.DestroyImmediate(instance); - } - - public static bool IsPoseValidOnInstance(GameObject modelPrefab, SerializedObject modelImporterSerializedObject) - { - GameObject instance = GameObject.Instantiate(modelPrefab) as GameObject; - instance.hideFlags = HideFlags.HideAndDontSave; - - Dictionary modelBones = GetModelBones(instance.transform, false, null); - BoneWrapper[] humanBones = GetHumanBones(modelImporterSerializedObject, modelBones); - - TransferDescriptionToPose(modelImporterSerializedObject, instance.transform); - bool valid = IsPoseValid(humanBones); - - GameObject.DestroyImmediate(instance); - return valid; - } - - public static void AutoSetup(GameObject modelPrefab, GameObject modelInstance, SerializedObject modelImporterSerializedObject) - { - SerializedProperty humanBoneArray = modelImporterSerializedObject.FindProperty(sHuman); - SerializedProperty hasTranslationDoF = modelImporterSerializedObject.FindProperty(sHasTranslationDoF); - - if (humanBoneArray == null || !humanBoneArray.isArray) - return; - - SimpleProfiler.Begin("AutoSetup Total"); - - SimpleProfiler.Begin("ClearHumanBoneArray"); - ClearHumanBoneArray(modelImporterSerializedObject); - SimpleProfiler.End(); - - SimpleProfiler.Begin("IsBiped"); - bool isBiped = AvatarBipedMapper.IsBiped(modelInstance.transform, null); - SimpleProfiler.End(); - - SimpleProfiler.Begin("SampleBindPose"); - SampleBindPose(modelInstance); - SimpleProfiler.End(); - - // Perform auto-mapping and get back mapping - SimpleProfiler.Begin("GetModelBones"); - Dictionary modelBones = GetModelBones(modelInstance.transform, false, null); - SimpleProfiler.End(); - - Dictionary mapping = null; - - if (isBiped) - { - SimpleProfiler.Begin("MapBipedBones"); - mapping = AvatarBipedMapper.MapBones(modelInstance.transform); - SimpleProfiler.End(); - } - else - { - SimpleProfiler.Begin("MapBones"); - mapping = AvatarAutoMapper.MapBones(modelInstance.transform, modelBones); - SimpleProfiler.End(); - } - - // Apply mapping to SerializedObject - SimpleProfiler.Begin("ApplyMapping"); - BoneWrapper[] humanBones = GetHumanBones(modelImporterSerializedObject, modelBones); - for (int i = 0; i < humanBones.Length; i++) - { - BoneWrapper bone = humanBones[i]; - if (mapping.ContainsKey(i)) - bone.bone = mapping[i]; - else - bone.bone = null; - bone.Serialize(modelImporterSerializedObject); - } - SimpleProfiler.End(); - - if (!isBiped) - { - // Check error of current pose (bind pose) - float bindPoseError = GetPoseError(humanBones); - - // Check error of reset pose - CopyPose(modelInstance, modelPrefab); - float resetPoseError = GetPoseError(humanBones); - - // If the bind pose was better, sample the bind pose again to use that as a starting point for the T-pose. - // Otherwise use the reset pose as starting point. - if (bindPoseError < resetPoseError) - SampleBindPose(modelInstance); - - // Move bones into valid T-pose - SimpleProfiler.Begin("MakePoseValid"); - MakePoseValid(humanBones); - SimpleProfiler.End(); - } - else - { - SimpleProfiler.Begin("SetBipedPose"); - AvatarBipedMapper.BipedPose(modelInstance, humanBones); - SimpleProfiler.End(); - - hasTranslationDoF.boolValue = true; - } - - // Apply pose to SerializedObject - SimpleProfiler.Begin("TransferPose"); - TransferPoseToDescription(modelImporterSerializedObject, modelInstance.transform); - SimpleProfiler.End(); - - SimpleProfiler.End(); - SimpleProfiler.PrintTimes(); - } - - public static bool TestAndValidateAutoSetup(GameObject modelAsset) - { - // Sanity check - if (modelAsset == null) - { - Debug.LogError("GameObject is null"); - return false; - } - if (PrefabUtility.GetPrefabType(modelAsset) != PrefabType.ModelPrefab) - { - Debug.LogError(modelAsset.name + ": GameObject is not a ModelPrefab", modelAsset); - return false; - } - if (modelAsset.transform.parent != null) - { - Debug.LogError(modelAsset.name + ": GameObject is not the root", modelAsset); - return false; - } - - // Get importer - string path = AssetDatabase.GetAssetPath(modelAsset); - ModelImporter importer = AssetImporter.GetAtPath(path) as ModelImporter; - if (importer == null) - { - Debug.LogError(modelAsset.name + ": Could not load ModelImporter (path:" + path + ")", modelAsset); - return false; - } - - // Get CreateAvatar property - SerializedObject serializedObject = new SerializedObject(importer); - SerializedProperty animationType = serializedObject.FindProperty("m_AnimationType"); - if (animationType == null) - { - Debug.LogError(modelAsset.name + ": Could not find property m_AnimationType on ModelImporter", modelAsset); - return false; - } - - // Clear avatar import settings and reimport - animationType.intValue = 2; - ClearAll(serializedObject); - serializedObject.ApplyModifiedProperties(); - AssetDatabase.ImportAsset(path); - - // Setup avatar import settings and reimport - animationType.intValue = 3; - AutoSetupOnInstance(modelAsset, serializedObject); - serializedObject.ApplyModifiedProperties(); - AssetDatabase.ImportAsset(path); - - // Check if Avatar is valid - Avatar avatar = AssetDatabase.LoadAssetAtPath(path, typeof(Avatar)) as Avatar; - if (avatar == null) - { - Debug.LogError(modelAsset.name + ": Did not find Avatar after reimport with CreateAvatar enabled", modelAsset); - return false; - } - if (!avatar.isHuman) - { - Debug.LogError(modelAsset.name + ": Avatar is not valid after reimport", modelAsset); - return false; - } - if (!IsPoseValidOnInstance(modelAsset, serializedObject)) - { - Debug.LogError(modelAsset.name + ": Avatar has invalid pose after reimport", modelAsset); - return false; - } - - // Check that mapping matches reference mapping - { - string pathWithoutExtension = path.Substring(0, path.Length - System.IO.Path.GetExtension(path).Length); - - // Get reference template - string templatePath = pathWithoutExtension + ".ht"; - HumanTemplate humanTemplate = AssetDatabase.LoadMainAssetAtPath(templatePath) as HumanTemplate; - if (humanTemplate == null) - Debug.LogWarning(modelAsset.name + ": Didn't find template at path " + templatePath); - else - { - // Get file with bones to ignore, if present - List ignoreBones = null; - string ignorePath = pathWithoutExtension + ".ignore"; - if (System.IO.File.Exists(ignorePath)) - ignoreBones = new List(System.IO.File.ReadAllLines(ignorePath)); - - // Create instance - GameObject instance = GameObject.Instantiate(modelAsset) as GameObject; - instance.hideFlags = HideFlags.HideAndDontSave; - - // Get BoneWrapper array - Dictionary modelBones = GetModelBones(instance.transform, false, null); - BoneWrapper[] humanBones = GetHumanBones(serializedObject, modelBones); - - // Test that bone mapping match the one in the reference - bool mismatch = false; - for (int i = 0; i < humanBones.Length; i++) - { - // Ignore bones in the ignore file - if (ignoreBones != null && ignoreBones.Contains(humanBones[i].humanBoneName)) - continue; - - string referenceBoneName = humanTemplate.Find(humanBones[i].humanBoneName); - string actualBoneName = (humanBones[i].bone == null ? "" : humanBones[i].bone.name); - if (!AvatarMappingEditor.MatchName(actualBoneName, referenceBoneName)) - { - mismatch = true; - Debug.LogError(modelAsset.name + ": Avatar has bone " + humanBones[i].humanBoneName + " mapped to \"" + actualBoneName + "\" but expected \"" + referenceBoneName + "\"", modelAsset); - } - } - - GameObject.DestroyImmediate(instance); - - if (mismatch) - return false; - } - } - - return true; - } - - public static void DebugTransformTree(Transform tr, Dictionary bones, int level) - { - string pre = " "; - if (bones.ContainsKey(tr)) - if (bones[tr]) - pre = "* "; - else - pre = ". "; - Debug.Log(" ".Substring(0, level * 2) + pre + tr.name + "\n\n"); - foreach (Transform child in tr) - DebugTransformTree(child, bones, level + 1); - } - - public static SerializedProperty FindSkeletonBone(SerializedObject serializedObject, Transform t, bool createMissing, bool isRoot) - { - SerializedProperty skeletonBoneArray = serializedObject.FindProperty(sSkeleton); - if (skeletonBoneArray == null || !skeletonBoneArray.isArray) - return null; - return FindSkeletonBone(skeletonBoneArray, t, createMissing, isRoot); - } - - public static SerializedProperty FindSkeletonBone(SerializedProperty skeletonBoneArray, Transform t, bool createMissing, bool isRoot) - { - if (isRoot && skeletonBoneArray.arraySize > 0) - { - SerializedProperty boneP = skeletonBoneArray.GetArrayElementAtIndex(0); - SerializedProperty boneNameP = boneP.FindPropertyRelative(sName); - if (boneNameP.stringValue == t.name) - return boneP; - } - else - { - // So root object name is not unique among all his child - // so we always need to skip the first element which is the root - for (int i = 1; i < skeletonBoneArray.arraySize; i++) - { - SerializedProperty boneP = skeletonBoneArray.GetArrayElementAtIndex(i); - SerializedProperty boneNameP = boneP.FindPropertyRelative(sName); - if (boneNameP.stringValue == t.name) - return boneP; - } - } - - if (createMissing) - { - skeletonBoneArray.arraySize++; - SerializedProperty bone = skeletonBoneArray.GetArrayElementAtIndex(skeletonBoneArray.arraySize - 1); - if (bone != null) - { - bone.FindPropertyRelative(sName).stringValue = t.name; - bone.FindPropertyRelative(sParentName).stringValue = isRoot ? "" : t.parent.name; - - bone.FindPropertyRelative(sPosition).vector3Value = t.localPosition; - bone.FindPropertyRelative(sRotation).quaternionValue = t.localRotation; - bone.FindPropertyRelative(sScale).vector3Value = t.localScale; - return bone; - } - } - return null; - } - - public static void CopyPose(GameObject go, GameObject source) - { - GameObject instance = GameObject.Instantiate(source) as GameObject; - instance.hideFlags = HideFlags.HideAndDontSave; - AnimatorUtility.DeoptimizeTransformHierarchy(instance); - CopyPose(go.transform, instance.transform); - GameObject.DestroyImmediate(instance); - } - - private static void CopyPose(Transform t, Transform source) - { - t.localPosition = source.localPosition; - t.localRotation = source.localRotation; - t.localScale = source.localScale; - foreach (Transform child in t) - { - Transform sourceChild = source.Find(child.name); - if (sourceChild) - CopyPose(child, sourceChild); - } - } - - public static void GetBindPoseBonePositionRotation(Matrix4x4 skinMatrix, Matrix4x4 boneMatrix, Transform bone, out Vector3 position, out Quaternion rotation) - { - // Get global matrix for bone - Matrix4x4 bindMatrixGlobal = skinMatrix * boneMatrix.inverse; - - // Get local X, Y, Z, and position of matrix - Vector3 mX = new Vector3(bindMatrixGlobal.m00, bindMatrixGlobal.m10, bindMatrixGlobal.m20); - Vector3 mY = new Vector3(bindMatrixGlobal.m01, bindMatrixGlobal.m11, bindMatrixGlobal.m21); - Vector3 mZ = new Vector3(bindMatrixGlobal.m02, bindMatrixGlobal.m12, bindMatrixGlobal.m22); - Vector3 mP = new Vector3(bindMatrixGlobal.m03, bindMatrixGlobal.m13, bindMatrixGlobal.m23); - - // Set position - // Adjust scale of matrix to compensate for difference in binding scale and model scale - float bindScale = mZ.magnitude; - float modelScale = Mathf.Abs(bone.lossyScale.z); - position = mP * (modelScale / bindScale); - - // Set rotation - // Check if scaling is negative and handle accordingly - if (Vector3.Dot(Vector3.Cross(mX, mY), mZ) >= 0) - rotation = Quaternion.LookRotation(mZ, mY); - else - rotation = Quaternion.LookRotation(-mZ, -mY); - } - - public static void SampleBindPose(GameObject go) - { - List skins = new List(go.GetComponentsInChildren()); - skins.Sort(new SkinTransformHierarchySorter()); - foreach (SkinnedMeshRenderer skin in skins) - { - //Debug.Log ("Sampling skinning of SkinnedMeshRenderer "+skin.name); - Matrix4x4 goMatrix = skin.transform.localToWorldMatrix; - List bones = new List(skin.bones); - Vector3[] backupLocalPosition = new Vector3[bones.Count]; - - // backup local position of bones. Only use rotation given by bind pose - for (int i = 0; i < bones.Count; i++) - { - backupLocalPosition[i] = bones[i].localPosition; - } - - // Set all parents to be null to be able to set global alignments of bones without affecting their children. - Dictionary parents = new Dictionary(); - foreach (Transform bone in bones) - { - parents[bone] = bone.parent; - bone.parent = null; - } - - // Set global space position and rotation of each bone - for (int i = 0; i < bones.Count; i++) - { - Vector3 position; - Quaternion rotation; - GetBindPoseBonePositionRotation(goMatrix, skin.sharedMesh.bindposes[i], bones[i], out position, out rotation); - bones[i].position = position; - bones[i].rotation = rotation; - } - - // Reconnect bones in their original hierarchy - foreach (Transform bone in bones) - bone.parent = parents[bone]; - - // put back local postion of bones - for (int i = 0; i < bones.Count; i++) - { - bones[i].localPosition = backupLocalPosition[i]; - } - } - } - - public static void ShowBindPose(SkinnedMeshRenderer skin) - { - Matrix4x4 goMatrix = skin.transform.localToWorldMatrix; - for (int i = 0; i < skin.bones.Length; i++) - { - Vector3 position; - Quaternion rotation; - GetBindPoseBonePositionRotation(goMatrix, skin.sharedMesh.bindposes[i], skin.bones[i], out position, out rotation); - float size = HandleUtility.GetHandleSize(position); - Handles.color = Handles.xAxisColor; - Handles.DrawLine(position, position + rotation * Vector3.right * 0.3f * size); - Handles.color = Handles.yAxisColor; - Handles.DrawLine(position, position + rotation * Vector3.up * 0.3f * size); - Handles.color = Handles.zAxisColor; - Handles.DrawLine(position, position + rotation * Vector3.forward * 0.3f * size); - } - } - - private class SkinTransformHierarchySorter : IComparer - { - public int Compare(SkinnedMeshRenderer skinA, SkinnedMeshRenderer skinB) - { - Transform a = skinA.transform; - Transform b = skinB.transform; - while (true) - { - if (a == null) - if (b == null) - return 0; - else - return -1; - if (b == null) - return 1; - a = a.parent; - b = b.parent; - } - } - } - - public static void TransferPoseToDescription(SerializedObject serializedObject, Transform root) - { - SkeletonBone[] skeletonBones = new SkeletonBone[0]; - if (root) - TransferPoseToDescription(serializedObject, root, true, ref skeletonBones); - - SerializedProperty skeletonBoneArray = serializedObject.FindProperty(sSkeleton); - ModelImporter.UpdateSkeletonPose(skeletonBones, skeletonBoneArray); - } - - private static void TransferPoseToDescription(SerializedObject serializedObject, Transform transform, bool isRoot, ref SkeletonBone[] skeletonBones) - { - SkeletonBone skeletonBone = new SkeletonBone(); - - skeletonBone.name = transform.name; - skeletonBone.parentName = isRoot ? "" : transform.parent.name; - skeletonBone.position = transform.localPosition; - skeletonBone.rotation = transform.localRotation; - skeletonBone.scale = transform.localScale; - - ArrayUtility.Add(ref skeletonBones, skeletonBone); - - foreach (Transform child in transform) - TransferPoseToDescription(serializedObject, child, false, ref skeletonBones); - } - - public static void TransferDescriptionToPose(SerializedObject serializedObject, Transform root) - { - if (root != null) - TransferDescriptionToPose(serializedObject, root, true); - } - - private static void TransferDescriptionToPose(SerializedObject serializedObject, Transform transform, bool isRoot) - { - SerializedProperty bone = FindSkeletonBone(serializedObject, transform, false, isRoot); - if (bone != null) - { - SerializedProperty positionP = bone.FindPropertyRelative(sPosition); - SerializedProperty rotationP = bone.FindPropertyRelative(sRotation); - SerializedProperty scaleP = bone.FindPropertyRelative(sScale); - transform.localPosition = positionP.vector3Value; - transform.localRotation = rotationP.quaternionValue; - transform.localScale = scaleP.vector3Value; - } - - foreach (Transform child in transform) - TransferDescriptionToPose(serializedObject, child, false); - } - - // BONE ALIGNMENT HANDLING - - public static bool IsPoseValid(BoneWrapper[] bones) - { - return (GetPoseError(bones) == 0); - } - - public static float GetPoseError(BoneWrapper[] bones) - { - Quaternion orientation = AvatarComputeOrientation(bones); - float error = 0; - - for (int i = 0; i < sBonePoses.Length; i++) - error += GetBoneAlignmentError(bones, orientation, i); - - error += GetCharacterPositionError(bones); - - return error; - } - - // Enforces TPose T-Pose - public static void MakePoseValid(BoneWrapper[] bones) - { - Quaternion orientation = AvatarComputeOrientation(bones); - for (int i = 0; i < sBonePoses.Length; i++) - { - MakeBoneAlignmentValid(bones, orientation, i); - // Recalculate orientation after handling hips since they may have changed it - if (i == (int)HumanBodyBones.Hips) - orientation = AvatarComputeOrientation(bones); - } - - // Move feet to ground plane - MakeCharacterPositionValid(bones); - } - - public static float GetBoneAlignmentError(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex) - { - if (boneIndex < 0 || boneIndex >= sBonePoses.Length) - return 0; - - BoneWrapper bone = bones[boneIndex]; - BonePoseData pose = sBonePoses[boneIndex]; - if (bone.bone == null || pose == null) - return 0; - - if (boneIndex == (int)HumanBodyBones.Hips) - { - float angleX = Vector3.Angle(avatarOrientation * Vector3.right, Vector3.right); - float angleY = Vector3.Angle(avatarOrientation * Vector3.up, Vector3.up); - float angleZ = Vector3.Angle(avatarOrientation * Vector3.forward, Vector3.forward); - return Mathf.Max(0, Mathf.Max(angleX, angleY, angleZ) - pose.maxAngle); - } - - Vector3 dir = GetBoneAlignmentDirection(bones, avatarOrientation, boneIndex); - if (dir == Vector3.zero) - return 0; - Quaternion space = GetRotationSpace(bones, avatarOrientation, boneIndex); - Vector3 goalDir = space * pose.direction; - if (pose.planeNormal != Vector3.zero) - dir = Vector3.ProjectOnPlane(dir, space * pose.planeNormal); - - // Check if the bone direction is not close enough to the target direction - return Mathf.Max(0, Vector3.Angle(dir, goalDir) - pose.maxAngle); - } - - public static void MakeBoneAlignmentValid(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex) - { - if (boneIndex < 0 || boneIndex >= sBonePoses.Length || boneIndex >= bones.Length) - return; - - BoneWrapper bone = bones[boneIndex]; - BonePoseData pose = sBonePoses[boneIndex]; - if (bone.bone == null || pose == null) - return; - - if (boneIndex == (int)HumanBodyBones.Hips) - { - float angleX = Vector3.Angle(avatarOrientation * Vector3.right, Vector3.right); - float angleY = Vector3.Angle(avatarOrientation * Vector3.up, Vector3.up); - float angleZ = Vector3.Angle(avatarOrientation * Vector3.forward, Vector3.forward); - if (angleX > pose.maxAngle || angleY > pose.maxAngle || angleZ > pose.maxAngle) - bone.bone.rotation = Quaternion.Inverse(avatarOrientation) * bone.bone.rotation; - return; - } - - Vector3 dir = GetBoneAlignmentDirection(bones, avatarOrientation, boneIndex); - if (dir == Vector3.zero) - return; - Quaternion space = GetRotationSpace(bones, avatarOrientation, boneIndex); - Vector3 goalDir = space * pose.direction; - if (pose.planeNormal != Vector3.zero) - dir = Vector3.ProjectOnPlane(dir, space * pose.planeNormal); - - // If the bone direction is not close enough to the target direction, - // rotate it so it matches the target direction. - float deltaAngle = Vector3.Angle(dir, goalDir); - if (deltaAngle > pose.maxAngle * 0.99f) - { - Quaternion adjust = Quaternion.FromToRotation(dir, goalDir); - - // If this bone is hip or knee, remember global foor rotation and apply it after this adjustment - Transform footBone = null; - Quaternion footRot = Quaternion.identity; - if (boneIndex == (int)HumanBodyBones.LeftUpperLeg || boneIndex == (int)HumanBodyBones.LeftLowerLeg) - footBone = bones[(int)HumanBodyBones.LeftFoot].bone; - if (boneIndex == (int)HumanBodyBones.RightUpperLeg || boneIndex == (int)HumanBodyBones.RightLowerLeg) - footBone = bones[(int)HumanBodyBones.RightFoot].bone; - if (footBone != null) - footRot = footBone.rotation; - - // Adjust only enough to fall within maxAngle - float adjustAmount = Mathf.Clamp01(1.05f - (pose.maxAngle / deltaAngle)); - adjust = Quaternion.Slerp(Quaternion.identity, adjust, adjustAmount); - - bone.bone.rotation = adjust * bone.bone.rotation; - - // Revert foot rotation to what it was - if (footBone != null) - footBone.rotation = footRot; - } - } - - private static Quaternion GetRotationSpace(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex) - { - Quaternion parentDelta = Quaternion.identity; - BonePoseData pose = sBonePoses[boneIndex]; - if (!pose.compareInGlobalSpace) - { - int parentIndex = HumanTrait.GetParentBone(boneIndex); - - if (parentIndex > 0) - { - BonePoseData parentPose = sBonePoses[parentIndex]; - if (bones[parentIndex].bone != null && parentPose != null) - { - Vector3 parentDir = GetBoneAlignmentDirection(bones, avatarOrientation, parentIndex); - if (parentDir != Vector3.zero) - { - Vector3 parentPoseDir = avatarOrientation * parentPose.direction; - parentDelta = Quaternion.FromToRotation(parentPoseDir, parentDir); - } - } - } - } - - return parentDelta * avatarOrientation; - } - - private static Vector3 GetBoneAlignmentDirection(BoneWrapper[] bones, Quaternion avatarOrientation, int boneIndex) - { - if (sBonePoses[boneIndex] == null) - return Vector3.zero; - - BoneWrapper bone = bones[boneIndex]; - Vector3 dir; - - // Get the child bone - BonePoseData pose = sBonePoses[boneIndex]; - int childBoneIndex = -1; - if (pose.childIndices != null) - { - foreach (int i in pose.childIndices) - { - if (bones[i].bone != null) - { - childBoneIndex = i; - break; - } - } - } - else - { - childBoneIndex = GetHumanBoneChild(bones, boneIndex); - } - - // TODO@MECANIM Something si wrong with the indexes - //if (boneIndex == (int)HumanBodyBones.LeftHand) - // Debug.Log ("Child bone for left hand: "+childBoneIndex); - - if (childBoneIndex >= 0 && bones[childBoneIndex] != null && bones[childBoneIndex].bone != null) - { - // Get direction from bone to child - BoneWrapper childBone = bones[childBoneIndex]; - dir = childBone.bone.position - bone.bone.position; - - // TODO@MECANIM Something si wrong with the indexes - //if (boneIndex == (int)HumanBodyBones.LeftHand) - // Debug.Log (" - "+childBone.humanBoneName + " - " +childBone.bone.name); - } - else - { - if (bone.bone.childCount != 1) - return Vector3.zero; - - dir = Vector3.zero; - // Get direction from bone to child - foreach (Transform child in bone.bone) - { - dir = child.position - bone.bone.position; - break; - } - } - - return dir.normalized; - } - - public static Quaternion AvatarComputeOrientation(BoneWrapper[] bones) - { - Transform leftUpLeg = bones[(int)HumanBodyBones.LeftUpperLeg].bone; - Transform rightUpLeg = bones[(int)HumanBodyBones.RightUpperLeg].bone; - Transform leftArm = bones[(int)HumanBodyBones.LeftUpperArm].bone; - Transform rightArm = bones[(int)HumanBodyBones.RightUpperArm].bone; - if (leftUpLeg != null && rightUpLeg != null && leftArm != null && rightArm != null) - return AvatarComputeOrientation(leftUpLeg.position, rightUpLeg.position, leftArm.position, rightArm.position); - else - return Quaternion.identity; - } - - public static Quaternion AvatarComputeOrientation(Vector3 leftUpLeg, Vector3 rightUpLeg, Vector3 leftArm, Vector3 rightArm) - { - Vector3 legsRightDir = Vector3.Normalize(rightUpLeg - leftUpLeg); - Vector3 armsRightDir = Vector3.Normalize(rightArm - leftArm); - Vector3 torsoRightDir = Vector3.Normalize(legsRightDir + armsRightDir); - - // Find out if torso right dir seems sensible or completely arbitrary. - // It's sensible if it's aligned along some axis. - bool sensibleOrientation = - Mathf.Abs(torsoRightDir.x * torsoRightDir.y) < 0.05f && - Mathf.Abs(torsoRightDir.y * torsoRightDir.z) < 0.05f && - Mathf.Abs(torsoRightDir.z * torsoRightDir.x) < 0.05f; - - Vector3 legsAvgPos = (leftUpLeg + rightUpLeg) * 0.5f; - Vector3 armsAvgPos = (leftArm + rightArm) * 0.5f; - Vector3 torsoUpDir = Vector3.Normalize(armsAvgPos - legsAvgPos); - - // If the orientation is sensible, assume character up vector is aligned along x, y, or z axis, so fix it to closest axis - if (sensibleOrientation) - { - int axisIndex = 0; - for (int i = 1; i < 3; i++) - if (Mathf.Abs(torsoUpDir[i]) > Mathf.Abs(torsoUpDir[axisIndex])) - axisIndex = i; - float sign = Mathf.Sign(torsoUpDir[axisIndex]); - torsoUpDir = Vector3.zero; - torsoUpDir[axisIndex] = sign; - } - - Vector3 torsoForwardDir = Vector3.Cross(torsoRightDir, torsoUpDir); - - if (torsoForwardDir == Vector3.zero || torsoUpDir == Vector3.zero) - return Quaternion.identity; - - return Quaternion.LookRotation(torsoForwardDir, torsoUpDir); - } - - private static float GetCharacterPositionError(BoneWrapper[] bones) - { - float error; - GetCharacterPositionAdjustVector(bones, out error); - return error; - } - - internal static void MakeCharacterPositionValid(BoneWrapper[] bones) - { - float error; - Vector3 adjustVector = GetCharacterPositionAdjustVector(bones, out error); - if (adjustVector != Vector3.zero) - bones[(int)HumanBodyBones.Hips].bone.position += adjustVector; - } - - private static Vector3 GetCharacterPositionAdjustVector(BoneWrapper[] bones, out float error) - { - error = 0; - - // Get hip bones - Transform leftUpLeg = bones[(int)HumanBodyBones.LeftUpperLeg].bone; - Transform rightUpLeg = bones[(int)HumanBodyBones.RightUpperLeg].bone; - if (leftUpLeg == null || rightUpLeg == null) - return Vector3.zero; - Vector3 avgHipPos = (leftUpLeg.position + rightUpLeg.position) * 0.5f; - - // Get foot bones - // Prefer toe bones but use foot bones if toes are not mapped - bool usingToes = true; - Transform leftFoot = bones[(int)HumanBodyBones.LeftToes].bone; - Transform rightFoot = bones[(int)HumanBodyBones.RightToes].bone; - if (leftFoot == null || rightFoot == null) - { - usingToes = false; - leftFoot = bones[(int)HumanBodyBones.LeftFoot].bone; - rightFoot = bones[(int)HumanBodyBones.RightFoot].bone; - } - if (leftFoot == null || rightFoot == null) - return Vector3.zero; - Vector3 avgFootPos = (leftFoot.position + rightFoot.position) * 0.5f; - - // Get approximate length of legs - float hipsHeight = avgHipPos.y - avgFootPos.y; - if (hipsHeight <= 0) - return Vector3.zero; - - Vector3 adjustVector = Vector3.zero; - - // We can force the feet to be at an approximate good height. - // But the feet might be at a perfect height from the start if the bind pose is good. - // So only do it if the feet look like they're not at a good position from the beginning. - // Check if feet are already at height that looks about right. - if (avgFootPos.y < 0 || avgFootPos.y > hipsHeight * (usingToes ? 0.1f : 0.3f)) - { - // Current height is not good, so adjust it using best guess based on human anatomy. - float estimatedFootBottomHeight = avgHipPos.y - hipsHeight * (usingToes ? 1.03f : 1.13f); - adjustVector.y = -estimatedFootBottomHeight; - } - - // Move the avg hip pos to the center on the left-right axis if it's not already there. - if (Mathf.Abs(avgHipPos.x) > 0.01f * hipsHeight) - adjustVector.x = -avgHipPos.x; - - // Move the avg hip pos to the center on the front-back axis if it's not already approximately there. - if (Mathf.Abs(avgHipPos.z) > 0.2f * hipsHeight) - adjustVector.z = -avgHipPos.z; - - error = adjustVector.magnitude * 100 / hipsHeight; - return adjustVector; - } - } -} diff --git a/Editor/Mono/Inspector/Avatar/AvatarSkeletonDrawer.cs b/Editor/Mono/Inspector/Avatar/AvatarSkeletonDrawer.cs deleted file mode 100644 index d450f89064..0000000000 --- a/Editor/Mono/Inspector/Avatar/AvatarSkeletonDrawer.cs +++ /dev/null @@ -1,169 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; -using System.Linq; - -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AvatarSkeletonDrawer - { - private static bool sPoseError; - - private static Color kSkeletonColor = new Color(103.0f / 255.0f, 103.0f / 255.0f, 103.0f / 255.0f, 0.25f); - private static Color kDummyColor = new Color(60.0f / 255.0f, 60.0f / 255.0f, 60.0f / 255.0f, 0.25f); - private static Color kHumanColor = new Color(0, 210.0f / 255.0f, 74.0f / 255.0f, 0.25f); - private static Color kErrorColor = new Color(1, 0, 0, 0.25f); - private static Color kErrorMessageColor = new Color(1, 0, 0, 0.75f); - private static Color kSelectedColor = new Color(128.0f / 255.0f, 192.0f / 255.0f, 255.0f / 255.0f, 0.15f); - - public static void DrawSkeleton(Transform reference, Dictionary actualBones) - { - DrawSkeleton(reference, actualBones, null); - } - - public static void DrawSkeleton(Transform reference, Dictionary actualBones, AvatarSetupTool.BoneWrapper[] bones) - { - // it can happen when the avatar tool is in edit mode and the user exit the tool in an unsual way - // new scene - // delete GO - // press play - if (reference == null || actualBones == null) - return; - - sPoseError = false; - - Bounds meshBounds = new Bounds(); - Renderer[] renderers = reference.root.GetComponentsInChildren(); - if (renderers != null) - { - foreach (Renderer renderer in renderers) - { - meshBounds.Encapsulate(renderer.bounds.min); - meshBounds.Encapsulate(renderer.bounds.max); - } - } - - Quaternion orientation = Quaternion.identity; - if (bones != null) - orientation = AvatarSetupTool.AvatarComputeOrientation(bones); - - DrawSkeletonSubTree(actualBones, bones, orientation, reference, meshBounds); - - Camera camera = Camera.current; - if (sPoseError && camera != null) - { - GUIStyle style = new GUIStyle(GUI.skin.label); - style.normal.textColor = Color.red; - style.wordWrap = false; - style.alignment = TextAnchor.MiddleLeft; - style.fontSize = 20; - - GUIContent content = EditorGUIUtility.TrTextContent("Character is not in T pose"); - - Rect rect = GUILayoutUtility.GetRect(content, style); - - rect.x = 30; - rect.y = 30; //camera.pixelHeight; - - Handles.BeginGUI(); - GUI.Label(rect, content, style); - Handles.EndGUI(); - } - } - - private static bool DrawSkeletonSubTree(Dictionary actualBones, AvatarSetupTool.BoneWrapper[] bones, Quaternion orientation, Transform tr, Bounds bounds) - { - // if this transform is not a valid bone - if (!actualBones.ContainsKey(tr)) - return false; - - int drawnChildren = 0; - foreach (Transform child in tr) - if (DrawSkeletonSubTree(actualBones, bones, orientation, child, bounds)) - drawnChildren++; - - if (!actualBones[tr] && drawnChildren <= 1) - return false; - - int index = -1; - if (bones != null) - { - for (int i = 0; i < bones.Length; i++) - { - if (bones[i].bone == tr) - { - index = i; - break; - } - } - } - - // There is no need to check for a pose error if the avatar is not yet valid or tools is not the active one - bool poseError = AvatarSetupTool.GetBoneAlignmentError(bones, orientation, index) > 0; - sPoseError |= poseError; - - if (poseError) - { - DrawPoseError(tr, bounds); - Handles.color = kErrorColor; - } - else if (index != -1) - Handles.color = kHumanColor; - else if (!actualBones[tr]) - Handles.color = kDummyColor; - else - Handles.color = kSkeletonColor; - - Handles.DoBoneHandle(tr, actualBones); - if (Selection.activeObject == tr) - { - Handles.color = kSelectedColor; - Handles.DoBoneHandle(tr, actualBones); - } - - return true; - } - - private static void DrawPoseError(Transform node, Bounds bounds) - { - Camera camera = Camera.current; - if (camera) - { - GUIStyle style = new GUIStyle(GUI.skin.label); - style.normal.textColor = Color.red; - style.wordWrap = false; - style.alignment = TextAnchor.MiddleLeft; - - Vector3 start = node.position; - Vector3 end = node.position + Vector3.up * 0.20f; - if (node.position.x <= node.root.position.x) - end.x = bounds.min.x; - else - end.x = bounds.max.x; - - GUIContent content = new GUIContent(node.name); - Rect rect = HandleUtility.WorldPointToSizedRect(end, content, style); - rect.x += 2; - if (node.position.x > node.root.position.x) - rect.x -= rect.width; - - Handles.BeginGUI(); - rect.y -= style.CalcSize(content).y / 4; - GUI.Label(rect, content, style); - Handles.EndGUI(); - - Handles.color = kErrorMessageColor; - Handles.DrawLine(start, end); - } - } - } -} diff --git a/Editor/Mono/Inspector/AvatarMaskInspector.cs b/Editor/Mono/Inspector/AvatarMaskInspector.cs deleted file mode 100644 index 3c0a830b3a..0000000000 --- a/Editor/Mono/Inspector/AvatarMaskInspector.cs +++ /dev/null @@ -1,764 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Reflection; -using System.Collections.Generic; -using System.Linq; -using UnityEngine.Profiling; - -namespace UnityEditor -{ - internal class BodyMaskEditor - { - class Styles - { - public GUIContent UnityDude = EditorGUIUtility.IconContent("AvatarInspector/BodySIlhouette"); - public GUIContent PickingTexture = EditorGUIUtility.IconContent("AvatarInspector/BodyPartPicker"); - - public GUIContent[] BodyPart = - { - EditorGUIUtility.IconContent("AvatarInspector/MaskEditor_Root"), - EditorGUIUtility.IconContent("AvatarInspector/Torso"), - - EditorGUIUtility.IconContent("AvatarInspector/Head"), - - EditorGUIUtility.IconContent("AvatarInspector/LeftLeg"), - EditorGUIUtility.IconContent("AvatarInspector/RightLeg"), - - EditorGUIUtility.IconContent("AvatarInspector/LeftArm"), - EditorGUIUtility.IconContent("AvatarInspector/RightArm"), - - EditorGUIUtility.IconContent("AvatarInspector/LeftFingers"), - EditorGUIUtility.IconContent("AvatarInspector/RightFingers"), - - EditorGUIUtility.IconContent("AvatarInspector/LeftFeetIk"), - EditorGUIUtility.IconContent("AvatarInspector/RightFeetIk"), - - EditorGUIUtility.IconContent("AvatarInspector/LeftFingersIk"), - EditorGUIUtility.IconContent("AvatarInspector/RightFingersIk"), - }; - } - - static Styles styles = new Styles(); - - - static protected Color[] m_MaskBodyPartPicker = - { - new Color(255 / 255.0f, 144 / 255.0f, 0 / 255.0f), // root - new Color(0 / 255.0f, 174 / 255.0f, 240 / 255.0f), // body - new Color(171 / 255.0f, 160 / 255.0f, 0 / 255.0f), // head - - new Color(0 / 255.0f, 255 / 255.0f, 255 / 255.0f), // ll - new Color(247 / 255.0f, 151 / 255.0f, 121 / 255.0f), // rl - - new Color(0 / 255.0f, 255 / 255.0f, 0 / 255.0f), // la - new Color(86 / 255.0f, 116 / 255.0f, 185 / 255.0f), // ra - - new Color(255 / 255.0f, 255 / 255.0f, 0 / 255.0f), // lh - new Color(130 / 255.0f, 202 / 255.0f, 156 / 255.0f), // rh - - new Color(82 / 255.0f, 82 / 255.0f, 82 / 255.0f), // lfi - new Color(255 / 255.0f, 115 / 255.0f, 115 / 255.0f), // rfi - new Color(159 / 255.0f, 159 / 255.0f, 159 / 255.0f), // lhi - new Color(202 / 255.0f, 202 / 255.0f, 202 / 255.0f), // rhi - - new Color(101 / 255.0f, 101 / 255.0f, 101 / 255.0f), // hi - }; - - static string sAvatarBodyMaskStr = "AvatarMask"; - static int s_Hint = sAvatarBodyMaskStr.GetHashCode(); - - static public void Show(SerializedProperty bodyMask, int count) - { - if (styles.UnityDude.image) - { - Rect rect = GUILayoutUtility.GetRect(styles.UnityDude, GUIStyle.none, GUILayout.MaxWidth(styles.UnityDude.image.width)); - rect.x += (GUIView.current.position.width - rect.width) / 2; - - Color oldColor = GUI.color; - - GUI.color = bodyMask.GetArrayElementAtIndex(0).intValue == 1 ? Color.green : Color.red; - - if (styles.BodyPart[0].image) - GUI.DrawTexture(rect, styles.BodyPart[0].image); - - GUI.color = new Color(0.2f, 0.2f, 0.2f, 1.0f); - GUI.DrawTexture(rect, styles.UnityDude.image); - - for (int i = 1; i < count; i++) - { - GUI.color = bodyMask.GetArrayElementAtIndex(i).intValue == 1 ? Color.green : Color.red; - if (styles.BodyPart[i].image) - GUI.DrawTexture(rect, styles.BodyPart[i].image); - } - GUI.color = oldColor; - - DoPicking(rect, bodyMask, count); - } - } - - static protected void DoPicking(Rect rect, SerializedProperty bodyMask, int count) - { - if (styles.PickingTexture.image) - { - int id = GUIUtility.GetControlID(s_Hint, FocusType.Passive, rect); - - Event evt = Event.current; - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - { - if (rect.Contains(evt.mousePosition)) - { - evt.Use(); - - // Texture coordinate start at 0,0 at bottom, left - // Screen coordinate start at 0,0 at top, left - // So we need to convert from screen coord to texture coord - int top = (int)evt.mousePosition.x - (int)rect.x; - int left = styles.UnityDude.image.height - ((int)evt.mousePosition.y - (int)rect.y); - - Texture2D pickTexture = styles.PickingTexture.image as Texture2D; - Color color = pickTexture.GetPixel(top, left); - - bool anyBodyPartPick = false; - for (int i = 0; i < count; i++) - { - if (m_MaskBodyPartPicker[i] == color) - { - GUI.changed = true; - bodyMask.GetArrayElementAtIndex(i).intValue = bodyMask.GetArrayElementAtIndex(i).intValue == 1 ? 0 : 1; - anyBodyPartPick = true; - } - } - - if (!anyBodyPartPick) - { - bool atLeastOneSelected = false; - - for (int i = 0; i < count && !atLeastOneSelected; i++) - { - atLeastOneSelected = bodyMask.GetArrayElementAtIndex(i).intValue == 1 ? true : false; - } - - for (int i = 0; i < count; i++) - { - bodyMask.GetArrayElementAtIndex(i).intValue = !atLeastOneSelected ? 1 : 0; - } - GUI.changed = true; - } - } - break; - } - } - } - } - } - - [CustomEditor(typeof(AvatarMask))] - internal class AvatarMaskInspector : Editor - { - private static class Styles - { - public static GUIContent MaskDefinition = EditorGUIUtility.TrTextContent("Definition", "Choose between Create From This Model, Copy From Other Avatar. The first one create a Mask for this file and the second one use a Mask from another file to import animation."); - - public static GUIContent[] MaskDefinitionOpt = - { - EditorGUIUtility.TrTextContent("Create From This Model", "Create a Mask based on the model from this file. For Humanoid rig all the human transform are always imported and converted to muscle curve, thus they cannot be unchecked."), - EditorGUIUtility.TrTextContent("Copy From Other Mask", "Copy a Mask from another file to import animation clip."), - EditorGUIUtility.TrTextContent("None ", " Import Everything") - }; - - 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."); - public static GUIContent TransformMask = EditorGUIUtility.TrTextContent("Transform", "Define which transform are active. Also define which animation curves will be imported for an Animation Clip."); - - public static GUIStyle foldoutStyle = new GUIStyle(EditorStyles.foldout); - public static GUIStyle labelStyle = new GUIStyle(EditorStyles.label); - - static Styles() - { - foldoutStyle.richText = labelStyle.richText = true; - } - } - - - // Body mask data - private bool m_ShowBodyMask = true; - private bool m_BodyMaskFoldout = false; - - - /// Transform mask data - /// - /// Accelaration scructure - /// - struct NodeInfo - { - public enum State { disabled, enabled, invalid }; - - public bool m_Expanded; - public bool m_Show; - public State m_State; - public int m_ParentIndex; - public List m_ChildIndices; - public int m_Depth; - public SerializedProperty m_Path; - public SerializedProperty m_Weight; - public string m_Name; - }; - - - private bool m_CanImport = true; - public bool canImport - { - get { return m_CanImport; } - set { m_CanImport = value; } - } - - private SerializedProperty m_BodyMask = null; - private SerializedProperty m_TransformMask = null; - private SerializedProperty m_AnimationType = null; - private AnimationClipInfoProperties m_ClipInfo = null; - private string[] m_TransformPaths = null; - public AnimationClipInfoProperties clipInfo - { - get { return m_ClipInfo; } - set - { - m_ClipInfo = value; - if (m_ClipInfo != null) - { - m_ClipInfo.MaskFromClip(target as AvatarMask); - SerializedObject so = m_ClipInfo.maskTypeProperty.serializedObject; - m_AnimationType = so.FindProperty("m_AnimationType"); - - ModelImporter modelImporter = so.targetObject as ModelImporter; - m_TransformPaths = modelImporter.transformPaths; - } - else - { - m_TransformPaths = null; - m_AnimationType = null; - } - - InitializeSerializedProperties(); - } - } - - private ModelImporterAnimationType animationType - { - get - { - if (m_AnimationType != null) - return (ModelImporterAnimationType)m_AnimationType.intValue; - else - return ModelImporterAnimationType.None; - } - } - - private NodeInfo[] m_NodeInfos; - - private Avatar m_RefAvatar; - private ModelImporter m_RefImporter; - private bool m_TransformMaskFoldout = false; - private string[] m_HumanTransform = null; - - private void InitializeSerializedProperties() - { - if (clipInfo != null) - { - m_BodyMask = clipInfo.bodyMaskProperty; - m_TransformMask = clipInfo.transformMaskProperty; - } - else - { - m_BodyMask = serializedObject.FindProperty("m_Mask"); - m_TransformMask = serializedObject.FindProperty("m_Elements"); - } - - FillNodeInfos(); - } - - private void OnEnable() - { - // The AvatarMaskInspector is instantiated in the ModelImporterClipEditor, which does not derive from the Editor class anymore. - // All editors are added to a list so that OnEnable() and other methods can be called on them at certain times. - // When going in game while having settings pending to be applied, at some point the target (ModelImporterClipEditor.m_Mask) becomes null, - // since the parent becomes updated before this class. - if (target == null) - { - return; - } - - InitializeSerializedProperties(); - } - - public bool showBody - { - get { return m_ShowBodyMask; } - set { m_ShowBodyMask = value; } - } - - public string[] humanTransforms - { - get - { - if (animationType == ModelImporterAnimationType.Human && clipInfo != null) - { - if (m_HumanTransform == null) - { - SerializedObject so = clipInfo.maskTypeProperty.serializedObject; - ModelImporter modelImporter = so.targetObject as ModelImporter; - - m_HumanTransform = AvatarMaskUtility.GetAvatarHumanTransform(so, modelImporter.transformPaths); - } - } - else - m_HumanTransform = null; - return m_HumanTransform; - } - } - - private ClipAnimationMaskType IndexToMaskType(int index) - { - ClipAnimationMaskType ret; - switch (index) - { - case 2: - ret = ClipAnimationMaskType.None; - break; - default: - ret = (ClipAnimationMaskType)index; - break; - } - return ret; - } - - private int MaskTypeToIndex(ClipAnimationMaskType maskType) - { - int ret; - switch (maskType) - { - case ClipAnimationMaskType.None: - ret = 2; - break; - default: - ret = (int)maskType; - break; - } - return ret; - } - - public override void OnInspectorGUI() - { - Profiler.BeginSample("AvatarMaskInspector.OnInspectorGUI()"); - if (clipInfo == null) - serializedObject.Update(); - - bool showCopyFromOtherGUI = false; - - if (clipInfo != null) - { - EditorGUI.BeginChangeCheck(); - int maskType = MaskTypeToIndex(clipInfo.maskType); - EditorGUI.showMixedValue = clipInfo.maskTypeProperty.hasMultipleDifferentValues; - maskType = EditorGUILayout.Popup(Styles.MaskDefinition, maskType, Styles.MaskDefinitionOpt); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - clipInfo.maskType = IndexToMaskType(maskType); - UpdateMask(clipInfo.maskType); - } - - showCopyFromOtherGUI = clipInfo.maskType == ClipAnimationMaskType.CopyFromOther; - } - - if (showCopyFromOtherGUI) - CopyFromOtherGUI(); - - bool wasEnabled = GUI.enabled; - GUI.enabled = !showCopyFromOtherGUI; - - EditorGUI.BeginChangeCheck(); - OnBodyInspectorGUI(); - OnTransformInspectorGUI(); - if (clipInfo != null && EditorGUI.EndChangeCheck()) - { - AvatarMask mask = target as AvatarMask; - clipInfo.MaskFromClip(mask); - } - - GUI.enabled = wasEnabled; - - if (clipInfo == null) - serializedObject.ApplyModifiedProperties(); - - Profiler.EndSample(); - } - - protected void CopyFromOtherGUI() - { - if (clipInfo == null) - return; - - EditorGUILayout.BeginHorizontal(); - - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(clipInfo.maskSourceProperty, GUIContent.Temp("Source")); - AvatarMask maskSource = clipInfo.maskSourceProperty.objectReferenceValue as AvatarMask; - if (EditorGUI.EndChangeCheck() && maskSource != null) - UpdateMask(clipInfo.maskType); - - EditorGUILayout.EndHorizontal(); - } - - public bool IsMaskEmpty() - { - return m_NodeInfos.Length == 0; - } - - public bool IsMaskUpToDate() - { - if (clipInfo == null) - return false; - - if (m_NodeInfos.Length != m_TransformPaths.Length) - return false; - - if (m_TransformMask.arraySize > 0) - { - SerializedProperty prop = m_TransformMask.GetArrayElementAtIndex(0); - - for (int i = 1; i < m_NodeInfos.Length; i++) - { - string path = m_NodeInfos[i].m_Path.stringValue; - int index = ArrayUtility.FindIndex(m_TransformPaths, s => s == path); - if (index == -1) - return false; - - prop.Next(false); - } - } - - return true; - } - - private void UpdateMask(ClipAnimationMaskType maskType) - { - if (clipInfo == null) - return; - - if (maskType == ClipAnimationMaskType.CreateFromThisModel) - { - SerializedObject so = clipInfo.maskTypeProperty.serializedObject; - ModelImporter modelImporter = so.targetObject as ModelImporter; - - AvatarMaskUtility.UpdateTransformMask(m_TransformMask, modelImporter.transformPaths, humanTransforms); - FillNodeInfos(); - } - else if (maskType == ClipAnimationMaskType.CopyFromOther) - { - AvatarMask maskSource = clipInfo.maskSourceProperty.objectReferenceValue as AvatarMask; - if (maskSource != null) - { - AvatarMask maskDest = target as AvatarMask; - maskDest.Copy(maskSource); - - // If this is a human clip make sure that all human transform path are set to true - if (humanTransforms != null) - AvatarMaskUtility.SetActiveHumanTransforms(maskDest, humanTransforms); - - clipInfo.MaskToClip(maskDest); - FillNodeInfos(); - } - } - else if (maskType == ClipAnimationMaskType.None) - { - var emptyMask = new AvatarMask(); - ModelImporter.UpdateTransformMask(emptyMask, clipInfo.transformMaskProperty); - } - - AvatarMask mask = target as AvatarMask; - clipInfo.MaskFromClip(mask); - } - - public void OnBodyInspectorGUI() - { - if (m_ShowBodyMask) - { - // Don't make toggling foldout cause GUI.changed to be true (shouldn't cause undoable action etc.) - bool wasChanged = GUI.changed; - m_BodyMaskFoldout = EditorGUILayout.Foldout(m_BodyMaskFoldout, Styles.BodyMask, true); - GUI.changed = wasChanged; - if (m_BodyMaskFoldout) - BodyMaskEditor.Show(m_BodyMask, (int)AvatarMaskBodyPart.LastBodyPart); - } - } - - public void OnTransformInspectorGUI() - { - float left = 0 , top = 0 , right = 0, bottom = 0; - - // Don't make toggling foldout cause GUI.changed to be true (shouldn't cause undoable action etc.) - bool wasChanged = GUI.changed; - m_TransformMaskFoldout = EditorGUILayout.Foldout(m_TransformMaskFoldout, Styles.TransformMask, true); - GUI.changed = wasChanged; - if (m_TransformMaskFoldout) - { - if (canImport) - ImportAvatarReference(); - - if (m_NodeInfos == null || m_TransformMask.arraySize != m_NodeInfos.Length) - FillNodeInfos(); - - if (IsMaskEmpty()) - { - GUILayout.BeginVertical(); - GUILayout.BeginHorizontal(EditorStyles.helpBox); - string message; - if (animationType == ModelImporterAnimationType.Generic) - { - message = "No transform mask defined, everything will be imported"; - } - else if (animationType == ModelImporterAnimationType.Human) - { - message = "No transform mask defined, only human curves will be imported"; - } - else - { - message = "No transform mask defined"; - } - - GUILayout.Label(message, - EditorStyles.wordWrappedMiniLabel); - - GUILayout.EndHorizontal(); - - if (!canImport && clipInfo.maskType == ClipAnimationMaskType.CreateFromThisModel) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - string fixMaskButtonLabel = "Create Mask"; - if (GUILayout.Button(fixMaskButtonLabel)) - UpdateMask(clipInfo.maskType); - GUILayout.EndHorizontal(); - } - - - GUILayout.EndVertical(); - } - else - { - ComputeShownElements(); - - GUILayout.Space(1); - int prevIndent = EditorGUI.indentLevel; - int size = m_TransformMask.arraySize; - for (int i = 1; i < size; i++) - { - if (m_NodeInfos[i].m_Show) - { - GUILayout.BeginHorizontal(); - EditorGUI.indentLevel = m_NodeInfos[i].m_Depth + 1; - - EditorGUI.BeginChangeCheck(); - Rect toggleRect = GUILayoutUtility.GetRect(15, 15, GUILayout.ExpandWidth(false)); - GUILayoutUtility.GetRect(10, 15, GUILayout.ExpandWidth(false)); - toggleRect.x += 15; - - EditorGUI.BeginDisabledGroup(m_NodeInfos[i].m_State == NodeInfo.State.disabled || m_NodeInfos[i].m_State == NodeInfo.State.invalid); - bool rightClick = Event.current.button == 1; - - bool isActive = m_NodeInfos[i].m_Weight.floatValue > 0.0f; - isActive = GUI.Toggle(toggleRect, isActive, ""); - - if (EditorGUI.EndChangeCheck()) - { - m_NodeInfos[i].m_Weight.floatValue = isActive ? 1.0f : 0.0f; - if (!rightClick) - CheckChildren(i, isActive); - } - - string textValue; - if (m_NodeInfos[i].m_State == NodeInfo.State.invalid) - textValue = "" + m_NodeInfos[i].m_Name + ""; - else - textValue = m_NodeInfos[i].m_Name; - - if (m_NodeInfos[i].m_ChildIndices.Count > 0) - m_NodeInfos[i].m_Expanded = EditorGUILayout.Foldout(m_NodeInfos[i].m_Expanded, textValue, true, Styles.foldoutStyle); - else - EditorGUILayout.LabelField(textValue, Styles.labelStyle); - - EditorGUI.EndDisabledGroup(); - if (i == 1) - { - top = toggleRect.yMin; - left = toggleRect.xMin; - } - else if (i == size - 1) - { - bottom = toggleRect.yMax; - } - - right = Mathf.Max(right, GUILayoutUtility.GetLastRect().xMax); - - GUILayout.EndHorizontal(); - } - } - - EditorGUI.indentLevel = prevIndent; - } - } - - Rect bounds = Rect.MinMaxRect(left, top, right, bottom); - - if (Event.current != null && Event.current.type == EventType.MouseUp && Event.current.button == 1 && bounds.Contains(Event.current.mousePosition)) - { - var menu = new GenericMenu(); - menu.AddItem(EditorGUIUtility.TrTextContent("Select all"), false, SelectAll); - menu.AddItem(EditorGUIUtility.TrTextContent("Deselect all"), false, DeselectAll); - menu.ShowAsContext(); - Event.current.Use(); - } - } - - private void SetAllTransformActive(bool active) - { - for (int i = 0; i < m_NodeInfos.Length; i++) - if (m_NodeInfos[i].m_State == NodeInfo.State.enabled) - m_NodeInfos[i].m_Weight.floatValue = active ? 1.0f : 0.0f; - } - - private void SelectAll() - { - SetAllTransformActive(true); - } - - private void DeselectAll() - { - SetAllTransformActive(false); - } - - private void ImportAvatarReference() - { - EditorGUI.BeginChangeCheck(); - m_RefAvatar = EditorGUILayout.ObjectField("Use skeleton from", m_RefAvatar, typeof(Avatar), true) as Avatar; - if (EditorGUI.EndChangeCheck()) - m_RefImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(m_RefAvatar)) as ModelImporter; - - if (m_RefImporter != null && GUILayout.Button("Import skeleton")) - AvatarMaskUtility.UpdateTransformMask(m_TransformMask, m_RefImporter.transformPaths, null); - } - - public void FillNodeInfos() - { - m_NodeInfos = new NodeInfo[m_TransformMask.arraySize]; - if (m_TransformMask.arraySize == 0) - return; - - string[] paths = new string[m_TransformMask.arraySize]; - - SerializedProperty prop = m_TransformMask.GetArrayElementAtIndex(0); - prop.Next(false); - - for (int i = 1; i < m_NodeInfos.Length; i++) - { - m_NodeInfos[i].m_Path = prop.FindPropertyRelative("m_Path"); - m_NodeInfos[i].m_Weight = prop.FindPropertyRelative("m_Weight"); - - paths[i] = m_NodeInfos[i].m_Path.stringValue; - string fullPath = paths[i]; - if (m_CanImport) - { - // in avatar mask inspector UI,everything is enabled. - m_NodeInfos[i].m_State = NodeInfo.State.enabled; - } - else if (humanTransforms != null) - { - // Enable only transforms that are not human. Human transforms in this case are handled by muscle curves and cannot be imported. - if (ArrayUtility.FindIndex(humanTransforms, s => fullPath == s) == -1) - { - if (m_TransformPaths != null && ArrayUtility.FindIndex(m_TransformPaths, s => fullPath == s) == -1) - m_NodeInfos[i].m_State = NodeInfo.State.invalid; - else - m_NodeInfos[i].m_State = NodeInfo.State.enabled; - } - else - { - m_NodeInfos[i].m_State = NodeInfo.State.disabled; - } - } - else if (m_TransformPaths != null && ArrayUtility.FindIndex(m_TransformPaths, s => fullPath == s) == -1) - { - // mask does not map to an existing hierarchy node. It's invalid. - m_NodeInfos[i].m_State = NodeInfo.State.invalid; - } - else - { - m_NodeInfos[i].m_State = NodeInfo.State.enabled; - } - - - m_NodeInfos[i].m_Expanded = true; - m_NodeInfos[i].m_ParentIndex = -1; - m_NodeInfos[i].m_ChildIndices = new List(); - - m_NodeInfos[i].m_Depth = i == 0 ? 0 : fullPath.Count(f => f == '/'); - - string parentPath = ""; - int lastIndex = fullPath.LastIndexOf('/'); - if (lastIndex > 0) - parentPath = fullPath.Substring(0, lastIndex); - - lastIndex = lastIndex == -1 ? 0 : lastIndex + 1; - m_NodeInfos[i].m_Name = fullPath.Substring(lastIndex); - - for (int j = 1; j < i; j++) // parents are already processed - { - string otherPath = paths[j]; - if (parentPath != "" && otherPath == parentPath) - { - m_NodeInfos[i].m_ParentIndex = j; - m_NodeInfos[j].m_ChildIndices.Add(i); - } - } - - prop.Next(false); - } - } - - private void ComputeShownElements() - { - for (int i = 0; i < m_NodeInfos.Length; i++) - { - if (m_NodeInfos[i].m_ParentIndex == -1) - ComputeShownElements(i, true); - } - } - - private void ComputeShownElements(int currentIndex, bool show) - { - m_NodeInfos[currentIndex].m_Show = show; - bool showChilds = show && m_NodeInfos[currentIndex].m_Expanded; - foreach (int index in m_NodeInfos[currentIndex].m_ChildIndices) - { - ComputeShownElements(index, showChilds); - } - } - - private void CheckChildren(int index, bool value) - { - foreach (int childIndex in m_NodeInfos[index].m_ChildIndices) - { - if (m_NodeInfos[childIndex].m_State == NodeInfo.State.enabled) - m_NodeInfos[childIndex].m_Weight.floatValue = value ? 1.0f : 0.0f; - CheckChildren(childIndex, value); - } - } - } -} diff --git a/Editor/Mono/Inspector/AvatarMaskUtility.cs b/Editor/Mono/Inspector/AvatarMaskUtility.cs deleted file mode 100644 index cab122c203..0000000000 --- a/Editor/Mono/Inspector/AvatarMaskUtility.cs +++ /dev/null @@ -1,163 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections; -using UnityEditor; -using System.Collections.Generic; -using System.Linq; - -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class AvatarMaskUtility - { - private static string sHuman = "m_HumanDescription.m_Human"; - private static string sBoneName = "m_BoneName"; - - static public string[] GetAvatarHumanTransform(SerializedObject so, string[] refTransformsPath) - { - SerializedProperty humanBoneArray = so.FindProperty(sHuman); - if (humanBoneArray == null || !humanBoneArray.isArray) - return null; - - List humanTransforms = new List(); - for (int i = 0; i < humanBoneArray.arraySize; i++) - { - SerializedProperty transformNameP = humanBoneArray.GetArrayElementAtIndex(i).FindPropertyRelative(sBoneName); - humanTransforms.Add(transformNameP.stringValue); - } - - return TokeniseHumanTransformsPath(refTransformsPath, humanTransforms.ToArray()); - } - - static public string[] GetAvatarHumanAndActiveExtraTransforms(SerializedObject so, SerializedProperty transformMaskProperty, string[] refTransformsPath) - { - SerializedProperty humanBoneArray = so.FindProperty(sHuman); - if (humanBoneArray == null || !humanBoneArray.isArray) - return null; - - List humanTransforms = new List(); - for (int i = 0; i < humanBoneArray.arraySize; i++) - { - SerializedProperty transformNameP = humanBoneArray.GetArrayElementAtIndex(i).FindPropertyRelative(sBoneName); - humanTransforms.Add(transformNameP.stringValue); - } - - List values = new List(TokeniseHumanTransformsPath(refTransformsPath, humanTransforms.ToArray())); - - for (int i = 0; i < transformMaskProperty.arraySize; i++) - { - float weight = transformMaskProperty.GetArrayElementAtIndex(i).FindPropertyRelative("m_Weight").floatValue; - string transformName = transformMaskProperty.GetArrayElementAtIndex(i).FindPropertyRelative("m_Path").stringValue; - - if (weight > 0.0f && !values.Contains(transformName)) - { - values.Add(transformName); - } - } - - return values.ToArray(); - } - - static public string[] GetAvatarInactiveTransformMaskPaths(SerializedProperty transformMaskProperty) - { - if (transformMaskProperty == null || !transformMaskProperty.isArray) - return null; - - List transformPaths = new List(); - for (int i = 0; i < transformMaskProperty.arraySize; i++) - { - SerializedProperty weight = transformMaskProperty.GetArrayElementAtIndex(i).FindPropertyRelative("m_Weight"); - if (weight.floatValue < 0.5f) - { - SerializedProperty transformNameP = transformMaskProperty.GetArrayElementAtIndex(i).FindPropertyRelative("m_Path"); - transformPaths.Add(transformNameP.stringValue); - } - } - - return transformPaths.ToArray(); - } - - static public void UpdateTransformMask(AvatarMask mask, string[] refTransformsPath, string[] humanTransforms) - { - mask.transformCount = refTransformsPath.Length; - for (int i = 0; i < refTransformsPath.Length; i++) - { - mask.SetTransformPath(i, refTransformsPath[i]); - - bool isActiveTransform = humanTransforms == null - ? true - : ArrayUtility.FindIndex(humanTransforms, s => refTransformsPath[i] == s) != -1; - mask.SetTransformActive(i, isActiveTransform); - } - } - - static public void UpdateTransformMask(SerializedProperty transformMask, string[] refTransformsPath, string[] currentPaths, bool areActivePaths = true) - { - // if areActivePaths=true, currentPaths is treated as the list of active transform paths - // else, currentPaths is treated as the list of inactive transform paths - AvatarMask refMask = new AvatarMask(); - - refMask.transformCount = refTransformsPath.Length; - - for (int i = 0; i < refTransformsPath.Length; i++) - { - bool isActiveTransform; - if (currentPaths == null) - isActiveTransform = true; - else if (areActivePaths) - isActiveTransform = ArrayUtility.FindIndex(currentPaths, s => refTransformsPath[i] == s) != -1; - else - isActiveTransform = ArrayUtility.FindIndex(currentPaths, s => refTransformsPath[i] == s) == -1; - - refMask.SetTransformPath(i, refTransformsPath[i]); - refMask.SetTransformActive(i, isActiveTransform); - } - ModelImporter.UpdateTransformMask(refMask, transformMask); - } - - static public void SetActiveHumanTransforms(AvatarMask mask, string[] humanTransforms) - { - for (int i = 0; i < mask.transformCount; i++) - { - string path = mask.GetTransformPath(i); - if (ArrayUtility.FindIndex(humanTransforms, s => path == s) != -1) - mask.SetTransformActive(i, true); - } - } - - static private string[] TokeniseHumanTransformsPath(string[] refTransformsPath, string[] humanTransforms) - { - if (humanTransforms == null) - return null; - - // all list must always include the string "" which is the root game object - string[] tokeniseTransformsPath = new string[] {""}; - - for (int i = 0; i < humanTransforms.Length; i++) - { - int index1 = ArrayUtility.FindIndex(refTransformsPath, s => humanTransforms[i] == FileUtil.GetLastPathNameComponent(s)); - if (index1 != -1) - { - int insertIndex = tokeniseTransformsPath.Length; - - string path = refTransformsPath[index1]; - while (path.Length > 0) - { - int index2 = ArrayUtility.FindIndex(tokeniseTransformsPath, s => path == s); - if (index2 == -1) - ArrayUtility.Insert(ref tokeniseTransformsPath, insertIndex, path); - - int lastIndex = path.LastIndexOf('/'); - path = path.Substring(0, lastIndex != -1 ? lastIndex : 0); - } - } - } - - return tokeniseTransformsPath; - } - } -} diff --git a/Editor/Mono/Inspector/AvatarPreview.cs b/Editor/Mono/Inspector/AvatarPreview.cs deleted file mode 100644 index ba5fe175f0..0000000000 --- a/Editor/Mono/Inspector/AvatarPreview.cs +++ /dev/null @@ -1,1081 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Assertions; -using UnityEngine.Rendering; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AvatarPreview - { - const string kIkPref = "AvatarpreviewShowIK"; - const string k2DPref = "Avatarpreview2D"; - const string kReferencePref = "AvatarpreviewShowReference"; - const string kSpeedPref = "AvatarpreviewSpeed"; - const float kTimeControlRectHeight = 21; - - public delegate void OnAvatarChange(); - OnAvatarChange m_OnAvatarChangeFunc = null; - - public OnAvatarChange OnAvatarChangeFunc - { - set { m_OnAvatarChangeFunc = value; } - } - - public bool IKOnFeet - { - get { return m_IKOnFeet; } - } - - public bool ShowIKOnFeetButton - { - get { return m_ShowIKOnFeetButton; } - set { m_ShowIKOnFeetButton = value; } - } - - public bool is2D - { - get { return m_2D; } - set - { - m_2D = value; - if (m_2D) - { - m_PreviewDir = new Vector2(); - } - } - } - - public Animator Animator - { - get { return m_PreviewInstance != null ? m_PreviewInstance.GetComponent(typeof(Animator)) as Animator : null; } - } - - public GameObject PreviewObject - { - get { return m_PreviewInstance; } - } - - public ModelImporterAnimationType animationClipType - { - get { return GetAnimationType(m_SourcePreviewMotion); } - } - - public Vector3 bodyPosition - { - get - { - if (Animator && Animator.isHuman) - return Animator.bodyPositionInternal; - ; - - if (m_PreviewInstance != null) - return GameObjectInspector.GetRenderableCenterRecurse(m_PreviewInstance, 1, 8); - - return Vector3.zero; - } - } - - public Vector3 rootPosition - { - get { return m_PreviewInstance ? m_PreviewInstance.transform.position : Vector3.zero; } - } - - - public TimeControl timeControl; - - // 60 is the default framerate for animations created inside Unity so as good a default as any. - public int fps = 60; - - private Material m_FloorMaterial; - private Material m_FloorMaterialSmall; - private Material m_ShadowMaskMaterial; - private Material m_ShadowPlaneMaterial; - - PreviewRenderUtility m_PreviewUtility; - GameObject m_PreviewInstance; - GameObject m_ReferenceInstance; - GameObject m_DirectionInstance; - GameObject m_PivotInstance; - GameObject m_RootInstance; - float m_BoundingVolumeScale; - Motion m_SourcePreviewMotion; - Animator m_SourceScenePreviewAnimator; - - const string s_PreviewStr = "Preview"; - int m_PreviewHint = s_PreviewStr.GetHashCode(); - - const string s_PreviewSceneStr = "PreviewSene"; - int m_PreviewSceneHint = s_PreviewSceneStr.GetHashCode(); - - Texture2D m_FloorTexture; - Mesh m_FloorPlane; - - bool m_ShowReference = false; - - bool m_IKOnFeet = false; - bool m_ShowIKOnFeetButton = true; - - bool m_2D; - - bool m_IsValid; - int m_ModelSelectorId = EditorGUIUtility.GetPermanentControlID(); - - - private const float kFloorFadeDuration = 0.2f; - private const float kFloorScale = 5; - private const float kFloorScaleSmall = 0.2f; - private const float kFloorTextureScale = 4; - private const float kFloorAlpha = 0.5f; - private const float kFloorShadowAlpha = 0.3f; - - private float m_PrevFloorHeight = 0; - private float m_NextFloorHeight = 0; - - private Vector2 m_PreviewDir = new Vector2(120, -20); - private float m_AvatarScale = 1.0f; - private float m_ZoomFactor = 1.0f; - private Vector3 m_PivotPositionOffset = Vector3.zero; - - private class Styles - { - public GUIContent speedScale = EditorGUIUtility.TrIconContent("SpeedScale", "Changes animation preview speed"); - public GUIContent pivot = EditorGUIUtility.TrIconContent("AvatarPivot", "Displays avatar's pivot and mass center"); - public GUIContent ik = EditorGUIUtility.TrTextContent("IK", "Toggles feet IK preview"); - public GUIContent is2D = EditorGUIUtility.TrTextContent("2D", "Toggles 2D preview mode"); - public GUIContent avatarIcon = EditorGUIUtility.TrIconContent("Avatar Icon", "Changes the model to use for previewing."); - - public GUIStyle preButton = "preButton"; - public GUIStyle preSlider = "preSlider"; - public GUIStyle preSliderThumb = "preSliderThumb"; - public GUIStyle preLabel = "preLabel"; - } - private static Styles s_Styles; - - void SetPreviewCharacterEnabled(bool enabled, bool showReference) - { - if (m_PreviewInstance != null) - PreviewRenderUtility.SetEnabledRecursive(m_PreviewInstance, enabled); - PreviewRenderUtility.SetEnabledRecursive(m_ReferenceInstance, showReference && enabled); - PreviewRenderUtility.SetEnabledRecursive(m_DirectionInstance, showReference && enabled); - PreviewRenderUtility.SetEnabledRecursive(m_PivotInstance, showReference && enabled); - PreviewRenderUtility.SetEnabledRecursive(m_RootInstance, showReference && enabled); - } - - static AnimationClip GetFirstAnimationClipFromMotion(Motion motion) - { - AnimationClip clip = motion as AnimationClip; - if (clip) - return clip; - - Animations.BlendTree blendTree = motion as Animations.BlendTree; - if (blendTree) - { - AnimationClip[] clips = blendTree.GetAnimationClipsFlattened(); - if (clips.Length > 0) - return clips[0]; - } - - return null; - } - - static public ModelImporterAnimationType GetAnimationType(GameObject go) - { - Animator animator = go.GetComponent(); - if (animator) - { - Avatar avatar = animator.avatar; - if (avatar && avatar.isHuman) - return ModelImporterAnimationType.Human; - else - return ModelImporterAnimationType.Generic; - } - else if (go.GetComponent() != null) - { - return ModelImporterAnimationType.Legacy; - } - else - return ModelImporterAnimationType.None; - } - - static public ModelImporterAnimationType GetAnimationType(Motion motion) - { - AnimationClip clip = GetFirstAnimationClipFromMotion(motion); - if (clip) - { - if (clip.legacy) - return ModelImporterAnimationType.Legacy; - else if (clip.humanMotion) - return ModelImporterAnimationType.Human; - else - return ModelImporterAnimationType.Generic; - } - else - return ModelImporterAnimationType.None; - } - - static public bool IsValidPreviewGameObject(GameObject target, ModelImporterAnimationType requiredClipType) - { - if (target != null && !target.activeSelf) - Debug.LogWarning("Can't preview inactive object, using fallback object"); - - return target != null && target.activeSelf && GameObjectInspector.HasRenderableParts(target) && - !(requiredClipType != ModelImporterAnimationType.None && GetAnimationType(target) != requiredClipType); - } - - static public GameObject FindBestFittingRenderableGameObjectFromModelAsset(Object asset, ModelImporterAnimationType animationType) - { - if (asset == null) - return null; - - ModelImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(asset)) as ModelImporter; - if (importer == null) - return null; - - string assetPath = importer.CalculateBestFittingPreviewGameObject(); - GameObject tempGO = AssetDatabase.LoadMainAssetAtPath(assetPath) as GameObject; - - // We should also check for isHumanClip matching the animationclip requiremenets... - if (IsValidPreviewGameObject(tempGO, ModelImporterAnimationType.None)) - return tempGO; - else - return null; - } - - static GameObject CalculatePreviewGameObject(Animator selectedAnimator, Motion motion, ModelImporterAnimationType animationType) - { - AnimationClip sourceClip = GetFirstAnimationClipFromMotion(motion); - - // Use selected preview - GameObject selected = AvatarPreviewSelection.GetPreview(animationType); - if (IsValidPreviewGameObject(selected, ModelImporterAnimationType.None)) - return selected; - - if (selectedAnimator != null && IsValidPreviewGameObject(selectedAnimator.gameObject, animationType)) - return selectedAnimator.gameObject; - - // Find the best fitting preview game object for the asset we are viewing (Handles @ convention, will pick base path for you) - selected = FindBestFittingRenderableGameObjectFromModelAsset(sourceClip, animationType); - if (selected != null) - return selected; - - if (animationType == ModelImporterAnimationType.Human) - return GetHumanoidFallback(); - else if (animationType == ModelImporterAnimationType.Generic) - return GetGenericAnimationFallback(); - - return null; - } - - static GameObject GetGenericAnimationFallback() - { - return (GameObject)EditorGUIUtility.Load("Avatar/DefaultGeneric.fbx"); - } - - static GameObject GetHumanoidFallback() - { - return (GameObject)EditorGUIUtility.Load("Avatar/DefaultAvatar.fbx"); - } - - public void ResetPreviewInstance() - { - Object.DestroyImmediate(m_PreviewInstance); - GameObject go = CalculatePreviewGameObject(m_SourceScenePreviewAnimator, m_SourcePreviewMotion, animationClipType); - SetupBounds(go); - } - - void SetupBounds(GameObject go) - { - m_IsValid = go != null && go != GetGenericAnimationFallback(); - - if (go != null) - { - m_PreviewInstance = EditorUtility.InstantiateForAnimatorPreview(go); - previewUtility.AddSingleGO(m_PreviewInstance); - - Bounds bounds = new Bounds(m_PreviewInstance.transform.position, Vector3.zero); - GameObjectInspector.GetRenderableBoundsRecurse(ref bounds, m_PreviewInstance); - - m_BoundingVolumeScale = Mathf.Max(bounds.size.x, Mathf.Max(bounds.size.y, bounds.size.z)); - - - if (Animator && Animator.isHuman) - m_AvatarScale = m_ZoomFactor = Animator.humanScale; - else - m_AvatarScale = m_ZoomFactor = m_BoundingVolumeScale / 2; - } - } - - void InitInstance(Animator scenePreviewObject, Motion motion) - { - m_SourcePreviewMotion = motion; - m_SourceScenePreviewAnimator = scenePreviewObject; - - if (m_PreviewInstance == null) - { - GameObject go = CalculatePreviewGameObject(scenePreviewObject, motion, animationClipType); - SetupBounds(go); - } - - if (timeControl == null) - { - timeControl = new TimeControl(); - } - - if (m_ReferenceInstance == null) - { - GameObject referenceGO = (GameObject)EditorGUIUtility.Load("Avatar/dial_flat.prefab"); - m_ReferenceInstance = (GameObject)Object.Instantiate(referenceGO, Vector3.zero, Quaternion.identity); - EditorUtility.InitInstantiatedPreviewRecursive(m_ReferenceInstance); - previewUtility.AddSingleGO(m_ReferenceInstance); - } - - if (m_DirectionInstance == null) - { - GameObject directionGO = (GameObject)EditorGUIUtility.Load("Avatar/arrow.fbx"); - m_DirectionInstance = (GameObject)Object.Instantiate(directionGO, Vector3.zero, Quaternion.identity); - EditorUtility.InitInstantiatedPreviewRecursive(m_DirectionInstance); - previewUtility.AddSingleGO(m_DirectionInstance); - } - - if (m_PivotInstance == null) - { - GameObject pivotGO = (GameObject)EditorGUIUtility.Load("Avatar/root.fbx"); - m_PivotInstance = (GameObject)Object.Instantiate(pivotGO, Vector3.zero, Quaternion.identity); - EditorUtility.InitInstantiatedPreviewRecursive(m_PivotInstance); - previewUtility.AddSingleGO(m_PivotInstance); - } - - if (m_RootInstance == null) - { - GameObject rootGO = (GameObject)EditorGUIUtility.Load("Avatar/root.fbx"); - m_RootInstance = (GameObject)Object.Instantiate(rootGO, Vector3.zero, Quaternion.identity); - EditorUtility.InitInstantiatedPreviewRecursive(m_RootInstance); - previewUtility.AddSingleGO(m_RootInstance); - } - - // Load preview settings from prefs - m_IKOnFeet = EditorPrefs.GetBool(kIkPref, false); - m_ShowReference = EditorPrefs.GetBool(kReferencePref, true); - is2D = EditorPrefs.GetBool(k2DPref, EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D); - timeControl.playbackSpeed = EditorPrefs.GetFloat(kSpeedPref, 1f); - - SetPreviewCharacterEnabled(false, false); - - m_PivotPositionOffset = Vector3.zero; - } - - private PreviewRenderUtility previewUtility - { - get - { - if (m_PreviewUtility == null) - { - m_PreviewUtility = new PreviewRenderUtility(); - m_PreviewUtility.camera.fieldOfView = 30.0f; - m_PreviewUtility.camera.allowHDR = false; - m_PreviewUtility.camera.allowMSAA = false; - m_PreviewUtility.ambientColor = new Color(.1f, .1f, .1f, 0); - m_PreviewUtility.lights[0].intensity = 1.4f; - m_PreviewUtility.lights[0].transform.rotation = Quaternion.Euler(40f, 40f, 0); - m_PreviewUtility.lights[1].intensity = 1.4f; - } - return m_PreviewUtility; - } - } - - private void Init() - { - if (s_Styles == null) - s_Styles = new Styles(); - - if (m_FloorPlane == null) - { - m_FloorPlane = Resources.GetBuiltinResource(typeof(Mesh), "New-Plane.fbx") as Mesh; - } - - if (m_FloorTexture == null) - { - m_FloorTexture = (Texture2D)EditorGUIUtility.Load("Avatar/Textures/AvatarFloor.png"); - } - - if (m_FloorMaterial == null) - { - Shader shader = EditorGUIUtility.LoadRequired("Previews/PreviewPlaneWithShadow.shader") as Shader; - m_FloorMaterial = new Material(shader); - m_FloorMaterial.mainTexture = m_FloorTexture; - m_FloorMaterial.mainTextureScale = Vector2.one * kFloorScale * kFloorTextureScale; - m_FloorMaterial.SetVector("_Alphas", new Vector4(kFloorAlpha, kFloorShadowAlpha, 0, 0)); - m_FloorMaterial.hideFlags = HideFlags.HideAndDontSave; - - m_FloorMaterialSmall = new Material(m_FloorMaterial); - m_FloorMaterialSmall.mainTextureScale = Vector2.one * kFloorScaleSmall * kFloorTextureScale; - m_FloorMaterialSmall.hideFlags = HideFlags.HideAndDontSave; - } - - if (m_ShadowMaskMaterial == null) - { - Shader shader = EditorGUIUtility.LoadRequired("Previews/PreviewShadowMask.shader") as Shader; - m_ShadowMaskMaterial = new Material(shader); - m_ShadowMaskMaterial.hideFlags = HideFlags.HideAndDontSave; - } - - if (m_ShadowPlaneMaterial == null) - { - Shader shader = EditorGUIUtility.LoadRequired("Previews/PreviewShadowPlaneClip.shader") as Shader; - m_ShadowPlaneMaterial = new Material(shader); - m_ShadowPlaneMaterial.hideFlags = HideFlags.HideAndDontSave; - } - } - - public void OnDestroy() - { - if (m_PreviewUtility != null) - { - m_PreviewUtility.Cleanup(); - m_PreviewUtility = null; - } - - if (timeControl != null) - timeControl.OnDisable(); - } - - public void DoSelectionChange() - { - m_OnAvatarChangeFunc(); - } - - public AvatarPreview(Animator previewObjectInScene, Motion objectOnSameAsset) - { - InitInstance(previewObjectInScene, objectOnSameAsset); - } - - float PreviewSlider(float val, float snapThreshold) - { - val = GUILayout.HorizontalSlider(val, 0.1f, 2.0f, s_Styles.preSlider, s_Styles.preSliderThumb, GUILayout.MaxWidth(64)); - if (val > 0.25f - snapThreshold && val < 0.25f + snapThreshold) - val = 0.25f; - else if (val > 0.5f - snapThreshold && val < 0.5f + snapThreshold) - val = 0.5f; - else if (val > 0.75f - snapThreshold && val < 0.75f + snapThreshold) - val = 0.75f; - else if (val > 1.0f - snapThreshold && val < 1.0f + snapThreshold) - val = 1.0f; - else if (val > 1.25f - snapThreshold && val < 1.25f + snapThreshold) - val = 1.25f; - else if (val > 1.5f - snapThreshold && val < 1.5f + snapThreshold) - val = 1.5f; - else if (val > 1.75f - snapThreshold && val < 1.75f + snapThreshold) - val = 1.75f; - - return val; - } - - public void DoPreviewSettings() - { - Init(); - - if (m_ShowIKOnFeetButton) - { - EditorGUI.BeginChangeCheck(); - m_IKOnFeet = GUILayout.Toggle(m_IKOnFeet, s_Styles.ik, s_Styles.preButton); - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetBool(kIkPref, m_IKOnFeet); - } - - EditorGUI.BeginChangeCheck(); - GUILayout.Toggle(is2D, s_Styles.is2D, s_Styles.preButton); - if (EditorGUI.EndChangeCheck()) - { - is2D = !is2D; - EditorPrefs.SetBool(k2DPref, is2D); - } - - EditorGUI.BeginChangeCheck(); - m_ShowReference = GUILayout.Toggle(m_ShowReference, s_Styles.pivot, s_Styles.preButton); - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetBool(kReferencePref, m_ShowReference); - - GUILayout.Box(s_Styles.speedScale, s_Styles.preLabel); - EditorGUI.BeginChangeCheck(); - timeControl.playbackSpeed = PreviewSlider(timeControl.playbackSpeed, 0.03f); - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetFloat(kSpeedPref, timeControl.playbackSpeed); - GUILayout.Label(timeControl.playbackSpeed.ToString("f2"), s_Styles.preLabel); - } - - private RenderTexture RenderPreviewShadowmap(Light light, float scale, Vector3 center, Vector3 floorPos, out Matrix4x4 outShadowMatrix) - { - Assert.IsTrue(Event.current.type == EventType.Repaint); - - // Set ortho camera and position it - var cam = previewUtility.camera; - cam.orthographic = true; - cam.orthographicSize = scale * 2.0f; - cam.nearClipPlane = 1 * scale; - cam.farClipPlane = 25 * scale; - cam.transform.rotation = is2D ? Quaternion.identity : light.transform.rotation; - cam.transform.position = center - light.transform.forward * (scale * 5.5f); - - // Clear to black - CameraClearFlags oldFlags = cam.clearFlags; - cam.clearFlags = CameraClearFlags.SolidColor; - Color oldColor = cam.backgroundColor; - cam.backgroundColor = new Color(0, 0, 0, 0); - - // Create render target for shadow map - const int kShadowSize = 256; - RenderTexture oldRT = cam.targetTexture; - RenderTexture rt = RenderTexture.GetTemporary(kShadowSize, kShadowSize, 16); - rt.isPowerOfTwo = true; - rt.wrapMode = TextureWrapMode.Clamp; - rt.filterMode = FilterMode.Bilinear; - cam.targetTexture = rt; - - // Enable character and render with camera into the shadowmap - SetPreviewCharacterEnabled(true, false); - m_PreviewUtility.camera.Render(); - - // Draw a quad, with shader that will produce white color everywhere - // where something was rendered (via inverted depth test) - RenderTexture.active = rt; - GL.PushMatrix(); - GL.LoadOrtho(); - m_ShadowMaskMaterial.SetPass(0); - GL.Begin(GL.QUADS); - GL.Vertex3(0, 0, -99.0f); - GL.Vertex3(1, 0, -99.0f); - GL.Vertex3(1, 1, -99.0f); - GL.Vertex3(0, 1, -99.0f); - GL.End(); - - // Render floor with black color, to mask out any shadow from character - // parts that are under the preview plane - GL.LoadProjectionMatrix(cam.projectionMatrix); - GL.LoadIdentity(); - GL.MultMatrix(cam.worldToCameraMatrix); - m_ShadowPlaneMaterial.SetPass(0); - GL.Begin(GL.QUADS); - float sc = kFloorScale * scale; - GL.Vertex(floorPos + new Vector3(-sc, 0, -sc)); - GL.Vertex(floorPos + new Vector3(sc, 0, -sc)); - GL.Vertex(floorPos + new Vector3(sc, 0, sc)); - GL.Vertex(floorPos + new Vector3(-sc, 0, sc)); - GL.End(); - - GL.PopMatrix(); - - // Shadowmap sampling matrix, from world space into shadowmap space - Matrix4x4 texMatrix = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.5f), Quaternion.identity, - new Vector3(0.5f, 0.5f, 0.5f)); - outShadowMatrix = texMatrix * cam.projectionMatrix * cam.worldToCameraMatrix; - - // Restore previous camera parameters - cam.orthographic = false; - cam.clearFlags = oldFlags; - cam.backgroundColor = oldColor; - cam.targetTexture = oldRT; - - return rt; - } - - public void DoRenderPreview(Rect previewRect, GUIStyle background) - { - var probe = RenderSettings.ambientProbe; - previewUtility.BeginPreview(previewRect, background); - - Quaternion bodyRot; - Quaternion rootRot; - Vector3 rootPos; - Vector3 bodyPos = rootPosition; - Vector3 pivotPos; - - if (Animator && Animator.isHuman) - { - rootRot = Animator.rootRotation; - rootPos = Animator.rootPosition; - - bodyRot = Animator.bodyRotation; - - pivotPos = Animator.pivotPosition; - } - else if (Animator && Animator.hasRootMotion) - { - rootRot = Animator.rootRotation; - rootPos = Animator.rootPosition; - - bodyRot = Quaternion.identity; - - pivotPos = Vector3.zero; - } - else - { - rootRot = Quaternion.identity; - rootPos = Vector3.zero; - - bodyRot = Quaternion.identity; - - pivotPos = Vector3.zero; - } - - SetupPreviewLightingAndFx(probe); - - Vector3 direction = bodyRot * Vector3.forward; - direction[1] = 0; - Quaternion directionRot = Quaternion.LookRotation(direction); - Vector3 directionPos = rootPos; - - Quaternion pivotRot = rootRot; - - // Scale all Preview Objects to fit avatar size. - PositionPreviewObjects(pivotRot, pivotPos, bodyRot, bodyPosition, directionRot, rootRot, rootPos, directionPos, m_AvatarScale); - - bool dynamicFloorHeight = is2D ? false : Mathf.Abs(m_NextFloorHeight - m_PrevFloorHeight) > m_ZoomFactor * 0.01f; - - // Calculate floor height and alpha - float mainFloorHeight, mainFloorAlpha; - if (dynamicFloorHeight) - { - float fadeMoment = m_NextFloorHeight < m_PrevFloorHeight ? kFloorFadeDuration : (1 - kFloorFadeDuration); - mainFloorHeight = timeControl.normalizedTime < fadeMoment ? m_PrevFloorHeight : m_NextFloorHeight; - mainFloorAlpha = Mathf.Clamp01(Mathf.Abs(timeControl.normalizedTime - fadeMoment) / kFloorFadeDuration); - } - else - { - mainFloorHeight = m_PrevFloorHeight; - mainFloorAlpha = is2D ? 0.5f : 1; - } - - Quaternion floorRot = is2D ? Quaternion.Euler(0, -90, 90) : Quaternion.identity; - Vector3 floorPos = new Vector3(0, 0, 0); - floorPos = m_ReferenceInstance.transform.position; - floorPos.y = mainFloorHeight; - - // Render shadow map - Matrix4x4 shadowMatrix; - RenderTexture shadowMap = RenderPreviewShadowmap(previewUtility.lights[0], m_BoundingVolumeScale / 2, bodyPosition, floorPos, out shadowMatrix); - - float tempZoomFactor = (is2D ? 1.0f : m_ZoomFactor); - // Position camera - previewUtility.camera.orthographic = is2D; - previewUtility.camera.nearClipPlane = 0.5f * tempZoomFactor; - previewUtility.camera.farClipPlane = 100.0f * m_AvatarScale; - Quaternion camRot = Quaternion.Euler(-m_PreviewDir.y, -m_PreviewDir.x, 0); - - // Add panning offset - Vector3 camPos = camRot * (Vector3.forward * -5.5f * tempZoomFactor) + bodyPos + m_PivotPositionOffset; - previewUtility.camera.transform.position = camPos; - previewUtility.camera.transform.rotation = camRot; - - if (is2D) - previewUtility.camera.orthographicSize = 2.0f * m_ZoomFactor; - // Render main floor - { - if (!is2D) - floorPos.y = mainFloorHeight; - - Material mat = m_FloorMaterial; - Matrix4x4 matrix = Matrix4x4.TRS(floorPos, floorRot, Vector3.one * kFloorScale * m_AvatarScale); - - mat.mainTextureOffset = -new Vector2(floorPos.x, floorPos.z) * kFloorScale * 0.08f * (1.0f / m_AvatarScale); - mat.SetTexture("_ShadowTexture", shadowMap); - mat.SetMatrix("_ShadowTextureMatrix", shadowMatrix); - mat.SetVector("_Alphas", new Vector4(kFloorAlpha * mainFloorAlpha, kFloorShadowAlpha * mainFloorAlpha, 0, 0)); - mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Background; - - Graphics.DrawMesh(m_FloorPlane, matrix, mat, Camera.PreviewCullingLayer, previewUtility.camera, 0); - } - - // Render small floor - if (dynamicFloorHeight) - { - bool topIsNext = m_NextFloorHeight > m_PrevFloorHeight; - float floorHeight = topIsNext ? m_NextFloorHeight : m_PrevFloorHeight; - float otherFloorHeight = topIsNext ? m_PrevFloorHeight : m_NextFloorHeight; - float floorAlpha = (floorHeight == mainFloorHeight ? 1 - mainFloorAlpha : 1) * Mathf.InverseLerp(otherFloorHeight, floorHeight, rootPos.y); - floorPos.y = floorHeight; - - Material mat = m_FloorMaterialSmall; - mat.mainTextureOffset = -new Vector2(floorPos.x, floorPos.z) * kFloorScaleSmall * 0.08f; - mat.SetTexture("_ShadowTexture", shadowMap); - mat.SetMatrix("_ShadowTextureMatrix", shadowMatrix); - mat.SetVector("_Alphas", new Vector4(kFloorAlpha * floorAlpha, 0, 0, 0)); - Matrix4x4 matrix = Matrix4x4.TRS(floorPos, floorRot, Vector3.one * kFloorScaleSmall * m_AvatarScale); - Graphics.DrawMesh(m_FloorPlane, matrix, mat, Camera.PreviewCullingLayer, previewUtility.camera, 0); - } - - SetPreviewCharacterEnabled(true, m_ShowReference); - previewUtility.Render(m_Option != PreviewPopupOptions.DefaultModel); - SetPreviewCharacterEnabled(false, false); - - RenderTexture.ReleaseTemporary(shadowMap); - } - - private void SetupPreviewLightingAndFx(SphericalHarmonicsL2 probe) - { - previewUtility.lights[0].intensity = 1.4f; - previewUtility.lights[0].transform.rotation = Quaternion.Euler(40f, 40f, 0); - previewUtility.lights[1].intensity = 1.4f; - RenderSettings.ambientMode = AmbientMode.Custom; - RenderSettings.ambientLight = new Color(0.1f, 0.1f, 0.1f, 1.0f); - RenderSettings.ambientProbe = probe; - } - - private float m_LastNormalizedTime = -1000; - private float m_LastStartTime = -1000; - private float m_LastStopTime = -1000; - private bool m_NextTargetIsForward = true; - private void PositionPreviewObjects(Quaternion pivotRot, Vector3 pivotPos, Quaternion bodyRot, Vector3 bodyPos, - Quaternion directionRot, Quaternion rootRot, Vector3 rootPos, Vector3 directionPos, - float scale) - { - m_ReferenceInstance.transform.position = rootPos; - m_ReferenceInstance.transform.rotation = rootRot; - m_ReferenceInstance.transform.localScale = Vector3.one * scale * 1.25f; - - m_DirectionInstance.transform.position = directionPos; - m_DirectionInstance.transform.rotation = directionRot; - m_DirectionInstance.transform.localScale = Vector3.one * scale * 2; - - m_PivotInstance.transform.position = pivotPos; - m_PivotInstance.transform.rotation = pivotRot; - m_PivotInstance.transform.localScale = Vector3.one * scale * 0.1f; - - m_RootInstance.transform.position = bodyPos; - m_RootInstance.transform.rotation = bodyRot; - m_RootInstance.transform.localScale = Vector3.one * scale * 0.25f; - - if (Animator) - { - float normalizedTime = timeControl.normalizedTime; - float normalizedDelta = timeControl.deltaTime / (timeControl.stopTime - timeControl.startTime); - - // Always set last height to next height after wrapping the time. - if (normalizedTime - normalizedDelta < 0 || normalizedTime - normalizedDelta >= 1) - m_PrevFloorHeight = m_NextFloorHeight; - - // Check that AvatarPreview is getting reliable info about time and deltaTime. - if (m_LastNormalizedTime != -1000 && timeControl.startTime == m_LastStartTime && timeControl.stopTime == m_LastStopTime) - { - float difference = normalizedTime - normalizedDelta - m_LastNormalizedTime; - if (difference > 0.5f) - difference -= 1; - else if (difference < -0.5f) - difference += 1; - } - m_LastNormalizedTime = normalizedTime; - m_LastStartTime = timeControl.startTime; - m_LastStopTime = timeControl.stopTime; - - // Alternate getting the height for next time and previous time. - if (m_NextTargetIsForward) - m_NextFloorHeight = Animator.targetPosition.y; - else - m_PrevFloorHeight = Animator.targetPosition.y; - - // Flip next target time. - m_NextTargetIsForward = !m_NextTargetIsForward; - Animator.SetTarget(AvatarTarget.Root, m_NextTargetIsForward ? 1 : 0); - } - } - - public void AvatarTimeControlGUI(Rect rect) - { - Rect timeControlRect = rect; - timeControlRect.height = kTimeControlRectHeight; - - timeControl.DoTimeControl(timeControlRect); - - // Show current time in seconds:frame and in percentage - rect.y = rect.yMax - 20; - float time = timeControl.currentTime - timeControl.startTime; - EditorGUI.DropShadowLabel(new Rect(rect.x, rect.y, rect.width, 20), - 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)) - ); - } - - enum PreviewPopupOptions { Auto, DefaultModel, Other } - - protected enum ViewTool { None, Pan, Zoom, Orbit } - protected ViewTool m_ViewTool = ViewTool.None; - protected ViewTool viewTool - { - get - { - Event evt = Event.current; - if (m_ViewTool == ViewTool.None) - { - bool controlKeyOnMac = (evt.control && Application.platform == RuntimePlatform.OSXEditor); - - // actionKey could be command key on mac or ctrl on windows - bool actionKey = EditorGUI.actionKey; - - bool noModifiers = (!actionKey && !controlKeyOnMac && !evt.alt); - - if ((evt.button <= 0 && noModifiers) || (evt.button <= 0 && actionKey) || evt.button == 2) - m_ViewTool = ViewTool.Pan; - else if ((evt.button <= 0 && controlKeyOnMac) || (evt.button == 1 && evt.alt)) - m_ViewTool = ViewTool.Zoom; - else if (evt.button <= 0 && evt.alt || evt.button == 1) - m_ViewTool = ViewTool.Orbit; - } - return m_ViewTool; - } - } - - protected MouseCursor currentCursor - { - get - { - switch (m_ViewTool) - { - case ViewTool.Orbit: return MouseCursor.Orbit; - case ViewTool.Pan: return MouseCursor.Pan; - case ViewTool.Zoom: return MouseCursor.Zoom; - default: return MouseCursor.Arrow; - } - } - } - - - protected void HandleMouseDown(Event evt, int id, Rect previewRect) - { - if (viewTool != ViewTool.None && previewRect.Contains(evt.mousePosition)) - { - EditorGUIUtility.SetWantsMouseJumping(1); - evt.Use(); - GUIUtility.hotControl = id; - } - } - - protected void HandleMouseUp(Event evt, int id) - { - if (GUIUtility.hotControl == id) - { - m_ViewTool = ViewTool.None; - - GUIUtility.hotControl = 0; - EditorGUIUtility.SetWantsMouseJumping(0); - evt.Use(); - } - } - - protected void HandleMouseDrag(Event evt, int id, Rect previewRect) - { - if (m_PreviewInstance == null) - return; - - if (GUIUtility.hotControl == id) - { - switch (m_ViewTool) - { - case ViewTool.Orbit: DoAvatarPreviewOrbit(evt, previewRect); break; - case ViewTool.Pan: DoAvatarPreviewPan(evt); break; - - // case 605415 invert zoom delta to match scene view zooming - case ViewTool.Zoom: DoAvatarPreviewZoom(evt, -HandleUtility.niceMouseDeltaZoom * (evt.shift ? 2.0f : 0.5f)); break; - default: Debug.Log("Enum value not handled"); break; - } - } - } - - protected void HandleViewTool(Event evt, EventType eventType, int id, Rect previewRect) - { - switch (eventType) - { - case EventType.ScrollWheel: DoAvatarPreviewZoom(evt, HandleUtility.niceMouseDeltaZoom * (evt.shift ? 2.0f : 0.5f)); break; - case EventType.MouseDown: HandleMouseDown(evt, id, previewRect); break; - case EventType.MouseUp: HandleMouseUp(evt, id); break; - case EventType.MouseDrag: HandleMouseDrag(evt, id, previewRect); break; - } - } - - public void DoAvatarPreviewDrag(EventType type) - { - if (type == EventType.DragUpdated) - { - DragAndDrop.visualMode = DragAndDropVisualMode.Link; - } - else if (type == EventType.DragPerform) - { - DragAndDrop.visualMode = DragAndDropVisualMode.Link; - GameObject newPreviewObject = DragAndDrop.objectReferences[0] as GameObject; - - if (newPreviewObject) - { - DragAndDrop.AcceptDrag(); - SetPreview(newPreviewObject); - } - } - } - - public void DoAvatarPreviewOrbit(Event evt, Rect previewRect) - { - //Reset 2D on Orbit - if (is2D) - { - is2D = false; - } - m_PreviewDir -= evt.delta * (evt.shift ? 3 : 1) / Mathf.Min(previewRect.width, previewRect.height) * 140.0f; - m_PreviewDir.y = Mathf.Clamp(m_PreviewDir.y, -90, 90); - evt.Use(); - } - - public void DoAvatarPreviewPan(Event evt) - { - Camera cam = previewUtility.camera; - Vector3 screenPos = cam.WorldToScreenPoint(bodyPosition + m_PivotPositionOffset); - Vector3 delta = new Vector3(-evt.delta.x, evt.delta.y, 0); - // delta panning is scale with the zoom factor to allow fine tuning when user is zooming closely. - screenPos += delta * Mathf.Lerp(0.25f, 2.0f, m_ZoomFactor * 0.5f); - Vector3 worldDelta = cam.ScreenToWorldPoint(screenPos) - (bodyPosition + m_PivotPositionOffset); - m_PivotPositionOffset += worldDelta; - evt.Use(); - } - - public void ResetPreviewFocus() - { - m_PivotPositionOffset = bodyPosition - rootPosition; - } - - public void DoAvatarPreviewFrame(Event evt, EventType type, Rect previewRect) - { - if (type == EventType.KeyDown && evt.keyCode == KeyCode.F) - { - ResetPreviewFocus(); - m_ZoomFactor = m_AvatarScale; - evt.Use(); - } - - if (type == EventType.KeyDown && Event.current.keyCode == KeyCode.G) - { - m_PivotPositionOffset = GetCurrentMouseWorldPosition(evt, previewRect) - bodyPosition; - evt.Use(); - } - } - - protected Vector3 GetCurrentMouseWorldPosition(Event evt, Rect previewRect) - { - Camera cam = previewUtility.camera; - - float scaleFactor = previewUtility.GetScaleFactor(previewRect.width, previewRect.height); - Vector3 mouseLocal = new Vector3((evt.mousePosition.x - previewRect.x) * scaleFactor, (previewRect.height - (evt.mousePosition.y - previewRect.y)) * scaleFactor, 0); - mouseLocal.z = Vector3.Distance(bodyPosition, cam.transform.position); - return cam.ScreenToWorldPoint(mouseLocal); - } - - public void DoAvatarPreviewZoom(Event evt, float delta) - { - float zoomDelta = -delta * 0.05f; - m_ZoomFactor += m_ZoomFactor * zoomDelta; - - // zoom is clamp too 10 time closer than the original zoom - m_ZoomFactor = Mathf.Max(m_ZoomFactor, m_AvatarScale / 10.0f); - evt.Use(); - } - - public void DoAvatarPreview(Rect rect, GUIStyle background) - { - Init(); - - Rect choserRect = new Rect(rect.xMax - 16, rect.yMax - 16, 16, 16); - if (EditorGUI.DropdownButton(choserRect, GUIContent.none, FocusType.Passive, GUIStyle.none)) - { - GenericMenu menu = new GenericMenu(); - menu.AddItem(EditorGUIUtility.TrTextContent("Auto"), false, SetPreviewAvatarOption, PreviewPopupOptions.Auto); - menu.AddItem(EditorGUIUtility.TrTextContent("Unity Model"), false, SetPreviewAvatarOption, PreviewPopupOptions.DefaultModel); - menu.AddItem(EditorGUIUtility.TrTextContent("Other..."), false, SetPreviewAvatarOption, PreviewPopupOptions.Other); - menu.ShowAsContext(); - } - - Rect previewRect = rect; - previewRect.yMin += kTimeControlRectHeight; - previewRect.height = Mathf.Max(previewRect.height, 64f); - - int previewID = GUIUtility.GetControlID(m_PreviewHint, FocusType.Passive, previewRect); - Event evt = Event.current; - EventType type = evt.GetTypeForControl(previewID); - - if (type == EventType.Repaint && m_IsValid) - { - DoRenderPreview(previewRect, background); - previewUtility.EndAndDrawPreview(previewRect); - } - - AvatarTimeControlGUI(rect); - - GUI.DrawTexture(choserRect, s_Styles.avatarIcon.image); - - int previewSceneID = GUIUtility.GetControlID(m_PreviewSceneHint, FocusType.Passive); - type = evt.GetTypeForControl(previewSceneID); - - DoAvatarPreviewDrag(type); - HandleViewTool(evt, type, previewSceneID, previewRect); - DoAvatarPreviewFrame(evt, type, previewRect); - - if (!m_IsValid) - { - Rect warningRect = previewRect; - warningRect.yMax -= warningRect.height / 2 - 16; - EditorGUI.DropShadowLabel( - warningRect, - "No model is available for preview.\nPlease drag a model into this Preview Area."); - } - - // Check for model selected from ObjectSelector - if (evt.type == EventType.ExecuteCommand) - { - string commandName = evt.commandName; - if (commandName == ObjectSelector.ObjectSelectorUpdatedCommand && ObjectSelector.get.objectSelectorID == m_ModelSelectorId) - { - SetPreview(ObjectSelector.GetCurrentObject() as GameObject); - evt.Use(); - } - } - - // Apply the current cursor - if (evt.type == EventType.Repaint) - EditorGUIUtility.AddCursorRect(previewRect, currentCursor); - } - - private PreviewPopupOptions m_Option; - void SetPreviewAvatarOption(object obj) - { - m_Option = (PreviewPopupOptions)obj; - if (m_Option == PreviewPopupOptions.Auto) - { - SetPreview(null); - } - else if (m_Option == PreviewPopupOptions.DefaultModel) - { - SetPreview(GetHumanoidFallback()); - } - else if (m_Option == PreviewPopupOptions.Other) - { - ObjectSelector.get.Show(null, typeof(GameObject), null, false); - ObjectSelector.get.objectSelectorID = m_ModelSelectorId; - } - } - - void SetPreview(GameObject gameObject) - { - AvatarPreviewSelection.SetPreview(animationClipType, gameObject); - - Object.DestroyImmediate(m_PreviewInstance); - InitInstance(m_SourceScenePreviewAnimator, m_SourcePreviewMotion); - - if (m_OnAvatarChangeFunc != null) - m_OnAvatarChangeFunc(); - } - - int Repeat(int t, int length) - { - // Have to do double modulo in order to work for negative numbers. - // This is quicker than a branch to test for negative number. - return ((t % length) + length) % length; - } - } // class AvatarPreview -} // namespace UnityEditor diff --git a/Editor/Mono/Inspector/AvatarPreviewSelection.cs b/Editor/Mono/Inspector/AvatarPreviewSelection.cs deleted file mode 100644 index cafd672df1..0000000000 --- a/Editor/Mono/Inspector/AvatarPreviewSelection.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Reflection; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class AvatarPreviewSelection : ScriptableSingleton - { - [SerializeField] - GameObject[] m_PreviewModels; - - void Awake() - { - int length = (int)ModelImporterAnimationType.Human + 1; - if (m_PreviewModels == null || m_PreviewModels.Length != length) - m_PreviewModels = new GameObject[length]; - } - - static public void SetPreview(ModelImporterAnimationType type, GameObject go) - { - if (!System.Enum.IsDefined(typeof(ModelImporterAnimationType), type)) - return; - - if (instance.m_PreviewModels[(int)type] != go) - { - instance.m_PreviewModels[(int)type] = go; - instance.Save(false); - } - } - - static public GameObject GetPreview(ModelImporterAnimationType type) - { - if (!System.Enum.IsDefined(typeof(ModelImporterAnimationType), type)) - return null; - - return instance.m_PreviewModels[(int)type]; - } - } // class AvatarPreviewSelection -} // namespace UnityEditor diff --git a/Editor/Mono/Inspector/BillboardAssetInspector.cs b/Editor/Mono/Inspector/BillboardAssetInspector.cs deleted file mode 100644 index e23a5ccba4..0000000000 --- a/Editor/Mono/Inspector/BillboardAssetInspector.cs +++ /dev/null @@ -1,265 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; - -using UnityEngine; -using UnityEditorInternal; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [CustomEditor(typeof(BillboardAsset))] - [CanEditMultipleObjects] - internal class BillboardAssetInspector : Editor - { - private SerializedProperty m_Width; - private SerializedProperty m_Height; - private SerializedProperty m_Bottom; - private SerializedProperty m_Images; - private SerializedProperty m_Vertices; - private SerializedProperty m_Indices; - private SerializedProperty m_Material; - - private bool m_PreviewShaded = true; - private Vector2 m_PreviewDir = new Vector2(-120, 20); - private PreviewRenderUtility m_PreviewUtility; - private Mesh m_ShadedMesh; - private Mesh m_GeometryMesh; - private MaterialPropertyBlock m_ShadedMaterialProperties; - private Material m_GeometryMaterial; - private Material m_WireframeMaterial; - - private class GUIStyles - { - public readonly GUIContent m_Shaded = EditorGUIUtility.TrTextContent("Shaded"); - public readonly GUIContent m_Geometry = EditorGUIUtility.TrTextContent("Geometry"); - public readonly GUIStyle m_DropdownButton = new GUIStyle("MiniPopup"); - }; - - private static GUIStyles s_Styles = null; - private static GUIStyles Styles - { - get - { - if (s_Styles == null) - s_Styles = new GUIStyles(); - return s_Styles; - } - } - - private void OnEnable() - { - m_Width = serializedObject.FindProperty("width"); - m_Height = serializedObject.FindProperty("height"); - m_Bottom = serializedObject.FindProperty("bottom"); - m_Images = serializedObject.FindProperty("imageTexCoords"); - m_Vertices = serializedObject.FindProperty("vertices"); - m_Indices = serializedObject.FindProperty("indices"); - m_Material = serializedObject.FindProperty("material"); - } - - private void OnDisable() - { - if (m_PreviewUtility != null) - { - m_PreviewUtility.Cleanup(); - m_PreviewUtility = null; - DestroyImmediate(m_ShadedMesh, true); - DestroyImmediate(m_GeometryMesh, true); - m_GeometryMaterial = null; - if (m_WireframeMaterial != null) - { - DestroyImmediate(m_WireframeMaterial, true); - } - } - } - - private void InitPreview() - { - if (m_PreviewUtility == null) - { - m_PreviewUtility = new PreviewRenderUtility(); - m_ShadedMesh = new Mesh(); - m_ShadedMesh.hideFlags = HideFlags.HideAndDontSave; - m_ShadedMesh.MarkDynamic(); - m_GeometryMesh = new Mesh(); - m_GeometryMesh.hideFlags = HideFlags.HideAndDontSave; - m_GeometryMesh.MarkDynamic(); - m_ShadedMaterialProperties = new MaterialPropertyBlock(); - m_GeometryMaterial = Material.GetDefaultMaterial(); - m_WireframeMaterial = ModelInspector.CreateWireframeMaterial(); - EditorUtility.SetCameraAnimateMaterials(m_PreviewUtility.camera, true); - } - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_Width); - EditorGUILayout.PropertyField(m_Height); - EditorGUILayout.PropertyField(m_Bottom); - EditorGUILayout.PropertyField(m_Material); - - serializedObject.ApplyModifiedProperties(); - } - - public override bool HasPreviewGUI() - { - return (target != null); - } - - public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - return null; - - InitPreview(); - - m_PreviewUtility.BeginStaticPreview(new Rect(0, 0, width, height)); - - DoRenderPreview(true); - - return m_PreviewUtility.EndStaticPreview(); - } - - public override void OnPreviewSettings() - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - return; - - bool switchable = m_Material.objectReferenceValue != null; - GUI.enabled = switchable; - if (!switchable) - m_PreviewShaded = false; - - var content = m_PreviewShaded ? Styles.m_Shaded : Styles.m_Geometry; - var rect = GUILayoutUtility.GetRect(content, Styles.m_DropdownButton, GUILayout.Width(75)); - - if (EditorGUI.DropdownButton(rect, content, FocusType.Passive, Styles.m_DropdownButton)) - { - GUIUtility.hotControl = 0; - var dropDownMenu = new GenericMenu(); - dropDownMenu.AddItem(Styles.m_Shaded, m_PreviewShaded, () => m_PreviewShaded = true); - dropDownMenu.AddItem(Styles.m_Geometry, !m_PreviewShaded, () => m_PreviewShaded = false); - dropDownMenu.DropDown(rect); - } - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - { - if (Event.current.type == EventType.Repaint) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), "Preview requires\nrender texture support"); - return; - } - - InitPreview(); - - m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, r); - - if (Event.current.type != EventType.Repaint) - return; - - m_PreviewUtility.BeginPreview(r, background); - - DoRenderPreview(m_PreviewShaded); - - m_PreviewUtility.EndAndDrawPreview(r); - } - - public override string GetInfoString() - { - string info = String.Format("{0} verts, {1} tris, {2} images", - m_Vertices.arraySize, - m_Indices.arraySize / 3, - m_Images.arraySize); - return info; - } - - // Make a mesh out of the BillboardAsset that is used for rendering by SpeedTree billboard shader. - // Vertices are expanded by the shader therefore the mesh vertices are not used (filled by zeroes). - private void MakeRenderMesh(Mesh mesh, BillboardAsset billboard) - { - mesh.SetVertices(Enumerable.Repeat(Vector3.zero, billboard.vertexCount).ToList()); - mesh.SetColors(Enumerable.Repeat(Color.black, billboard.vertexCount).ToList()); - mesh.SetUVs(0, billboard.GetVertices().ToList()); - mesh.SetUVs(1, Enumerable.Repeat(new Vector4(1.0f, 1.0f, 0.0f, 0.0f), billboard.vertexCount).ToList()); - mesh.SetTriangles(billboard.GetIndices().Select(v => (int)v).ToList(), 0); - } - - // Make a mesh out of the BillboardAsset that is suitable for previewing the geometry. - // The vertices are expanded and made double-face. - private void MakePreviewMesh(Mesh mesh, BillboardAsset billboard) - { - float width = billboard.width; - float height = billboard.height; - float bottom = billboard.bottom; - mesh.SetVertices(Enumerable.Repeat( - billboard.GetVertices().Select(v => new Vector3( - (v.x - 0.5f) * width, - v.y * height + bottom, - 0)), - // Repeat the sequence twice - 2).SelectMany(s => s).ToList()); - - // (0,0,1) for the front-facing vertices and (0,0,-1) for the back-facing vertices - mesh.SetNormals( - Enumerable.Repeat(Vector3.forward, billboard.vertexCount).Concat( - Enumerable.Repeat(-Vector3.forward, billboard.vertexCount)).ToList()); - - // make a new triangle list with second half triangles flipped - var indices = new int[billboard.indexCount * 2]; - var billboardIndices = billboard.GetIndices(); - for (int i = 0; i < billboard.indexCount / 3; ++i) - { - indices[i * 3 + 0] = billboardIndices[i * 3 + 0]; - indices[i * 3 + 1] = billboardIndices[i * 3 + 1]; - indices[i * 3 + 2] = billboardIndices[i * 3 + 2]; - indices[i * 3 + 0 + billboard.indexCount] = billboardIndices[i * 3 + 2]; - indices[i * 3 + 1 + billboard.indexCount] = billboardIndices[i * 3 + 1]; - indices[i * 3 + 2 + billboard.indexCount] = billboardIndices[i * 3 + 0]; - } - mesh.SetTriangles(indices, 0); - } - - private void DoRenderPreview(bool shaded) - { - var billboard = target as BillboardAsset; - - Bounds bounds = new Bounds( - new Vector3(0, (m_Height.floatValue + m_Bottom.floatValue) * 0.5f, 0), - new Vector3(m_Width.floatValue, m_Height.floatValue, m_Width.floatValue)); - - float halfSize = bounds.extents.magnitude; - float distance = 8.0f * halfSize; - - var rotation = Quaternion.Euler(-m_PreviewDir.y, -m_PreviewDir.x, 0); - m_PreviewUtility.camera.transform.rotation = rotation; - m_PreviewUtility.camera.transform.position = rotation * (-Vector3.forward * distance); - m_PreviewUtility.camera.nearClipPlane = distance - halfSize * 1.1f; - m_PreviewUtility.camera.farClipPlane = distance + halfSize * 1.1f; - - m_PreviewUtility.lights[0].intensity = 1.4f; - m_PreviewUtility.lights[0].transform.rotation = rotation * Quaternion.Euler(40f, 40f, 0); - m_PreviewUtility.lights[1].intensity = 1.4f; - m_PreviewUtility.ambientColor = new Color(.1f, .1f, .1f, 0); - if (shaded) - { - MakeRenderMesh(m_ShadedMesh, billboard); - billboard.MakeMaterialProperties(m_ShadedMaterialProperties, m_PreviewUtility.camera); - ModelInspector.RenderMeshPreviewSkipCameraAndLighting(m_ShadedMesh, bounds, m_PreviewUtility, billboard.material, null, m_ShadedMaterialProperties, new Vector2(0, 0), -1); - } - else - { - MakePreviewMesh(m_GeometryMesh, billboard); - ModelInspector.RenderMeshPreviewSkipCameraAndLighting(m_GeometryMesh, bounds, m_PreviewUtility, m_GeometryMaterial, m_WireframeMaterial, null, new Vector2(0, 0), -1); - } - } - } -} diff --git a/Editor/Mono/Inspector/BillboardRendererInspector.cs b/Editor/Mono/Inspector/BillboardRendererInspector.cs deleted file mode 100644 index 870db1fa13..0000000000 --- a/Editor/Mono/Inspector/BillboardRendererInspector.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(BillboardRenderer))] - [CanEditMultipleObjects] - internal class BillboardRendererInspector : RendererEditorBase - { - private string[] m_ExcludedProperties; - - public override void OnEnable() - { - base.OnEnable(); - InitializeProbeFields(); - - List excludedProperties = new List(); - excludedProperties.AddRange(new[] - { - "m_Materials", - "m_LightmapParameters" - }); - excludedProperties.AddRange(Probes.GetFieldsStringArray()); - m_ExcludedProperties = excludedProperties.ToArray(); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - DrawPropertiesExcluding(serializedObject, m_ExcludedProperties); - - m_Probes.OnGUI(targets, (Renderer)target, false); - - RenderRenderingLayer(); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/BlendTreeInspector.cs b/Editor/Mono/Inspector/BlendTreeInspector.cs deleted file mode 100644 index 7a89cb7a88..0000000000 --- a/Editor/Mono/Inspector/BlendTreeInspector.cs +++ /dev/null @@ -1,2208 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEngine; -using UnityEditor; -using UnityEditor.Animations; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - -using Object = UnityEngine.Object; - - -namespace UnityEditor -{ - [CustomEditor(typeof(BlendTree))] - internal class BlendTreeInspector : Editor - { - class Styles - { - public readonly GUIStyle background = "MeBlendBackground"; - public readonly GUIStyle triangleLeft = "MeBlendTriangleLeft"; - public readonly GUIStyle triangleRight = "MeBlendTriangleRight"; - public readonly GUIStyle blendPosition = "MeBlendPosition"; - public GUIStyle clickDragFloatFieldLeft = new GUIStyle(EditorStyles.miniTextField); - public GUIStyle clickDragFloatFieldRight = new GUIStyle(EditorStyles.miniTextField); - public GUIStyle clickDragFloatLabelLeft = new GUIStyle(EditorStyles.miniLabel); - public GUIStyle clickDragFloatLabelRight = new GUIStyle(EditorStyles.miniLabel); - public GUIStyle headerIcon = new GUIStyle(); - public GUIStyle errorStyle = new GUIStyle(EditorStyles.wordWrappedLabel); - public GUIContent speedIcon = new GUIContent(EditorGUIUtility.IconContent("SpeedScale")); - public GUIContent mirrorIcon = new GUIContent(EditorGUIUtility.IconContent("Mirror")); - public Texture2D pointIcon = EditorGUIUtility.LoadIcon("blendKey"); - public Texture2D pointIconSelected = EditorGUIUtility.LoadIcon("blendKeySelected"); - public Texture2D pointIconOverlay = EditorGUIUtility.LoadIcon("blendKeyOverlay"); - public Texture2D samplerIcon = EditorGUIUtility.LoadIcon("blendSampler"); - - public Color visBgColor; - public Color visWeightColor; - public Color visWeightShapeColor; - public Color visWeightLineColor; - public Color visPointColor; - public Color visPointEmptyColor; - public Color visPointOverlayColor; - public Color visSamplerColor; - - public Styles() - { - errorStyle.alignment = TextAnchor.MiddleCenter; - speedIcon.tooltip = "Changes animation speed."; - mirrorIcon.tooltip = "Mirror animation."; - headerIcon.alignment = TextAnchor.MiddleCenter; - - clickDragFloatFieldLeft.alignment = TextAnchor.MiddleLeft; - clickDragFloatFieldRight.alignment = TextAnchor.MiddleRight; - clickDragFloatLabelLeft.alignment = TextAnchor.MiddleLeft; - clickDragFloatLabelRight.alignment = TextAnchor.MiddleRight; - - visBgColor = !EditorGUIUtility.isProSkin ? new Color(0.95f, 0.95f, 1.00f) : new Color(0.20f, 0.20f, 0.20f); - visWeightColor = !EditorGUIUtility.isProSkin ? new Color(0.50f, 0.60f, 0.90f, 0.80f) : new Color(0.65f, 0.75f, 1.00f, 0.65f); - visWeightShapeColor = !EditorGUIUtility.isProSkin ? new Color(0.40f, 0.65f, 1.00f, 0.15f) : new Color(0.40f, 0.65f, 1.00f, 0.12f); - visWeightLineColor = !EditorGUIUtility.isProSkin ? new Color(0 , 0 , 0 , 0.30f) : new Color(1 , 1 , 1 , 0.60f); - visPointColor = new Color(0.50f, 0.70f, 1.00f); - visPointEmptyColor = !EditorGUIUtility.isProSkin ? new Color(0.80f, 0.80f, 0.80f) : new Color(0.60f, 0.60f, 0.60f); - visPointOverlayColor = !EditorGUIUtility.isProSkin ? new Color(0 , 0 , 0 , 0.20f) : new Color(1 , 1 , 1 , 0.40f); - visSamplerColor = new Color(1.00f, 0.40f, 0.40f); - } - } - static Styles styles; - internal static AnimatorController currentController = null; - internal static Animator currentAnimator = null; - internal static BlendTree parentBlendTree = null; - internal static Action blendParameterInputChanged = null; - private readonly int m_BlendAnimationID = "BlendAnimationIDHash".GetHashCode(); - private readonly int m_ClickDragFloatID = "ClickDragFloatIDHash".GetHashCode(); - private float m_DragAndDropDelta; - private float m_OriginMin; - private float m_OriginMax; - private UnityEditorInternal.ReorderableList m_ReorderableList; - private SerializedProperty m_Childs; - private SerializedProperty m_BlendParameter; - private SerializedProperty m_BlendParameterY; - private BlendTree m_BlendTree; - private SerializedProperty m_UseAutomaticThresholds; - private SerializedProperty m_NormalizedBlendValues; - - private SerializedProperty m_MinThreshold; - private SerializedProperty m_MaxThreshold; - private SerializedProperty m_Name; - - private SerializedProperty m_BlendType; - - private AnimBool m_ShowGraph = new AnimBool(); - private AnimBool m_ShowCompute = new AnimBool(); - private AnimBool m_ShowAdjust = new AnimBool(); - private bool m_ShowGraphValue = false; - - private float[] m_Weights; - private const int kVisResolution = 64; - private Texture2D m_BlendTex = null; - private List m_WeightTexs = new List(); - private string m_WarningMessage = null; - - private PreviewBlendTree m_PreviewBlendTree; - private VisualizationBlendTree m_VisBlendTree; - private GameObject m_VisInstance = null; - - private int ParameterCount { get { return m_BlendType.intValue > (int)BlendTreeType.Simple1D ? (m_BlendType.intValue < (int)BlendTreeType.Direct ? 2 : 0) : 1; } } - - static internal void SetParameterValue(Animator animator, BlendTree blendTree, BlendTree parentBlendTree, string parameterName, float parameterValue) - { - bool liveLink = EditorApplication.isPlaying && animator != null && animator.enabled && animator.gameObject.activeInHierarchy; - - if (liveLink) - animator.SetFloat(parameterName, parameterValue); - - blendTree.SetInputBlendValue(parameterName, parameterValue); - if (blendParameterInputChanged != null) - blendParameterInputChanged(blendTree); - - if (parentBlendTree != null) - { - parentBlendTree.SetInputBlendValue(parameterName, parameterValue); - if (blendParameterInputChanged != null) - blendParameterInputChanged(parentBlendTree); - } - } - - static internal float GetParameterValue(Animator animator, BlendTree blendTree, string parameterName) - { - bool liveLink = EditorApplication.isPlaying && animator != null && animator.enabled && animator.gameObject.activeInHierarchy; - - if (liveLink) - { - return animator.GetFloat(parameterName); - } - else - { - return blendTree.GetInputBlendValue(parameterName); - } - } - - public void OnEnable() - { - m_Name = serializedObject.FindProperty("m_Name"); - m_BlendParameter = serializedObject.FindProperty("m_BlendParameter"); - m_BlendParameterY = serializedObject.FindProperty("m_BlendParameterY"); - m_UseAutomaticThresholds = serializedObject.FindProperty("m_UseAutomaticThresholds"); - m_NormalizedBlendValues = serializedObject.FindProperty("m_NormalizedBlendValues"); - m_MinThreshold = serializedObject.FindProperty("m_MinThreshold"); - m_MaxThreshold = serializedObject.FindProperty("m_MaxThreshold"); - m_BlendType = serializedObject.FindProperty("m_BlendType"); - } - - void Init() - { - if (styles == null) - styles = new Styles(); - if (m_BlendTree == null) - m_BlendTree = target as BlendTree; - if (styles == null) - styles = new Styles(); - if (m_PreviewBlendTree == null) - m_PreviewBlendTree = new PreviewBlendTree(); - if (m_VisBlendTree == null) - m_VisBlendTree = new VisualizationBlendTree(); - if (m_Childs == null) - { - m_Childs = serializedObject.FindProperty("m_Childs"); - m_ReorderableList = new UnityEditorInternal.ReorderableList(serializedObject, m_Childs); - m_ReorderableList.drawHeaderCallback = DrawHeader; - m_ReorderableList.drawElementCallback = DrawChild; - m_ReorderableList.onReorderCallback = EndDragChild; - m_ReorderableList.onAddDropdownCallback = AddButton; - m_ReorderableList.onRemoveCallback = RemoveButton; - if (m_BlendType.intValue == (int)BlendTreeType.Simple1D) - SortByThreshold(); - m_ShowGraphValue = m_BlendType.intValue == (int)BlendTreeType.Direct ? m_Childs.arraySize >= 1 : m_Childs.arraySize >= 2; - m_ShowGraph.value = m_ShowGraphValue; - m_ShowAdjust.value = AllMotions(); - m_ShowCompute.value = !m_UseAutomaticThresholds.boolValue; - - m_ShowGraph.valueChanged.AddListener(Repaint); - m_ShowAdjust.valueChanged.AddListener(Repaint); - m_ShowCompute.valueChanged.AddListener(Repaint); - } - - m_PreviewBlendTree.Init(m_BlendTree, currentAnimator); - - bool hasInitVisIntance = false; - if (m_VisInstance == null) - { - GameObject go = (GameObject)EditorGUIUtility.Load("Avatar/DefaultAvatar.fbx"); - m_VisInstance = (GameObject)EditorUtility.InstantiateForAnimatorPreview(go); - - foreach (Renderer renderer in m_VisInstance.GetComponentsInChildren()) - renderer.enabled = false; - - hasInitVisIntance = true; - } - m_VisBlendTree.Init(m_BlendTree, m_VisInstance.GetComponent()); - - if (hasInitVisIntance && - (m_BlendType.intValue == (int)BlendTreeType.SimpleDirectional2D || - m_BlendType.intValue == (int)BlendTreeType.FreeformDirectional2D || - m_BlendType.intValue == (int)BlendTreeType.FreeformCartesian2D)) - { - UpdateBlendVisualization(); - ValidatePositions(); - } - } - - internal override void OnHeaderIconGUI(Rect iconRect) - { - Texture2D icon = AssetPreview.GetMiniThumbnail(target); - GUI.Label(iconRect, icon); - } - - internal override void OnHeaderTitleGUI(Rect titleRect, string header) - { - serializedObject.Update(); - - Rect textFieldRect = titleRect; - textFieldRect.height = 16f; - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_Name.hasMultipleDifferentValues; - string newName = EditorGUI.DelayedTextField(textFieldRect, m_Name.stringValue, EditorStyles.textField); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck() && !String.IsNullOrEmpty(newName)) - { - foreach (Object obj in targets) - ObjectNames.SetNameSmart(obj, newName); - } - serializedObject.ApplyModifiedProperties(); - } - - internal override void OnHeaderControlsGUI() - { - EditorGUIUtility.labelWidth = 80; - serializedObject.Update(); - EditorGUILayout.PropertyField(m_BlendType); - serializedObject.ApplyModifiedProperties(); - } - - private List CollectParameters(AnimatorController controller) - { - List parameterList = new List(); - if (controller != null) - { - AnimatorControllerParameter[] parameters = controller.parameters; - for (int i = 0; i < parameters.Length; i++) - { - AnimatorControllerParameter animatorParameter = parameters[i]; - // only deal with floats - if (animatorParameter.type == AnimatorControllerParameterType.Float) - { - parameterList.Add(animatorParameter.name); - } - } - } - - return parameterList; - } - - private void ParameterGUI() - { - EditorGUILayout.BeginHorizontal(); - - // Label - if (ParameterCount > 1) - EditorGUILayout.PrefixLabel(EditorGUIUtility.TempContent("Parameters")); - else - EditorGUILayout.PrefixLabel(EditorGUIUtility.TempContent("Parameter")); - - serializedObject.Update(); - - // Available parameters - // Populate parameters list and find indexes of used blend parameters - string currentParameter = m_BlendTree.blendParameter; - string currentParameterY = m_BlendTree.blendParameterY; - - List parameters = CollectParameters(currentController); - - EditorGUI.BeginChangeCheck(); - currentParameter = EditorGUILayout.DelayedTextFieldDropDown(currentParameter, parameters.ToArray()); - if (EditorGUI.EndChangeCheck()) - { - m_BlendParameter.stringValue = currentParameter; - } - - if (ParameterCount > 1) - { - // Show second blend parameter - EditorGUI.BeginChangeCheck(); - currentParameterY = EditorGUILayout.TextFieldDropDown(currentParameterY, parameters.ToArray()); - if (EditorGUI.EndChangeCheck()) - { - m_BlendParameterY.stringValue = currentParameterY; - } - } - - serializedObject.ApplyModifiedProperties(); - - EditorGUILayout.EndHorizontal(); - } - - public override void OnInspectorGUI() - { - Init(); - serializedObject.Update(); - - if (m_BlendType.intValue != (int)BlendTreeType.Direct) - { - // Parameters - ParameterGUI(); - } - - m_ShowGraphValue = m_BlendType.intValue == (int)BlendTreeType.Direct ? m_Childs.arraySize >= 1 : m_Childs.arraySize >= 2; - m_ShowGraph.target = m_ShowGraphValue; - - m_UseAutomaticThresholds = serializedObject.FindProperty("m_UseAutomaticThresholds"); - GUI.enabled = true; - if (EditorGUILayout.BeginFadeGroup(m_ShowGraph.faded)) - { - if (m_BlendType.intValue == (int)BlendTreeType.Simple1D) - { - BlendGraph(EditorGUILayout.GetControlRect(false, 40, styles.background)); - ThresholdValues(); - } - else if (m_BlendType.intValue == (int)BlendTreeType.Direct) - { - for (int i = 0; i < m_BlendTree.recursiveBlendParameterCount; i++) - { - string eventName = m_BlendTree.GetRecursiveBlendParameter(i); - float eventMin = m_BlendTree.GetRecursiveBlendParameterMin(i); - float eventMax = m_BlendTree.GetRecursiveBlendParameterMax(i); - - EditorGUI.BeginChangeCheck(); - float eventValue = EditorGUILayout.Slider(eventName, GetParameterValue(currentAnimator, m_BlendTree, eventName), eventMin, eventMax); - if (EditorGUI.EndChangeCheck()) - SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, eventName, eventValue); - } - } - else // 2D blend tree types - { - GUILayout.Space(1); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - Rect graphRect = GUILayoutUtility.GetAspectRect(1, GUILayout.MaxWidth(235)); - GUI.Label(new Rect(graphRect.x - 1, graphRect.y - 1, graphRect.width + 2, graphRect.height + 2), GUIContent.none, EditorStyles.textField); - GUI.BeginGroup(graphRect); - graphRect.x = 0; - graphRect.y = 0; - BlendGraph2D(graphRect); - GUI.EndGroup(); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - } - - GUILayout.Space(5); - } - - EditorGUILayout.EndFadeGroup(); - if (m_ReorderableList != null) - { - m_ReorderableList.DoLayoutList(); - } - - if (m_BlendType.intValue == (int)BlendTreeType.Direct) - { - EditorGUILayout.PropertyField(m_NormalizedBlendValues, EditorGUIUtility.TempContent("Normalized Blend Values")); - } - - if (m_ShowGraphValue) - { - GUILayout.Space(10); - AutoCompute(); - } - serializedObject.ApplyModifiedProperties(); - } - - private void SetMinMaxThresholds() - { - float min = Mathf.Infinity; - float max = Mathf.NegativeInfinity; - for (int i = 0; i < m_Childs.arraySize; i++) - { - SerializedProperty child = m_Childs.GetArrayElementAtIndex(i); - SerializedProperty threshold = child.FindPropertyRelative("m_Threshold"); - min = (threshold.floatValue < min) ? threshold.floatValue : min; - max = (threshold.floatValue > max) ? threshold.floatValue : max; - } - m_MinThreshold.floatValue = m_Childs.arraySize > 0 ? min : 0; - m_MaxThreshold.floatValue = m_Childs.arraySize > 0 ? max : 1; - } - - private void ThresholdValues() - { - Rect r = EditorGUILayout.GetControlRect(); - Rect r1 = r; - Rect r2 = r; - r1.width /= 4; - r2.width /= 4; - r2.x = r.x + r.width - r2.width; - - float min = m_MinThreshold.floatValue; - float max = m_MaxThreshold.floatValue; - - EditorGUI.BeginChangeCheck(); - min = ClickDragFloat(r1, min); - max = ClickDragFloat(r2, max, true); - - if (EditorGUI.EndChangeCheck()) - { - float newMin = Mathf.Min(min, max); - float newMax = Mathf.Max(min, max); - - if (m_Childs.arraySize >= 2) - { - // Get first and last threshold properties. - SerializedProperty firstChild = m_Childs.GetArrayElementAtIndex(0); - SerializedProperty lastChild = m_Childs.GetArrayElementAtIndex(m_Childs.arraySize - 1); - SerializedProperty firstThreshold = firstChild.FindPropertyRelative("m_Threshold"); - SerializedProperty lastThreshold = lastChild.FindPropertyRelative("m_Threshold"); - - // Store previous values. - float previousMin = firstThreshold.floatValue; - float previousMax = lastThreshold.floatValue; - - // Set the new thresholds. - firstThreshold.floatValue = newMin; - lastThreshold.floatValue = newMax; - - if (!m_UseAutomaticThresholds.boolValue) - { - // Since this isn't being automatically calculated, we need to scale the values. - int arraySize = m_Childs.arraySize; - for (int i = 1; i < arraySize - 1; ++i) - { - SerializedProperty child = m_Childs.GetArrayElementAtIndex(i); - SerializedProperty threshold = child.FindPropertyRelative("m_Threshold"); - float ratio = Mathf.InverseLerp(previousMin, previousMax, threshold.floatValue); - threshold.floatValue = Mathf.Lerp(newMin, newMax, ratio); - } - } - - // Clamp the current blend value within the new boundaries. - float blendValue = GetParameterValue(currentAnimator, m_BlendTree, m_BlendTree.blendParameter); - blendValue = Mathf.Clamp(blendValue, newMin, newMax); - SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, m_BlendTree.blendParameter, blendValue); - } - - // Set the new min/max thresholds. - m_MinThreshold.floatValue = newMin; - m_MaxThreshold.floatValue = newMax; - } - } - - private static bool s_ClickDragFloatDragged; - private static float s_ClickDragFloatDistance; - public float ClickDragFloat(Rect position, float value) - { - return ClickDragFloat(position, value, false); - } - - public float ClickDragFloat(Rect position, float value, bool alignRight) - { - bool changed; - - // TODO: Why does the cursor change to arrow when editing the text? - - string allowedCharacters = "inftynaeINFTYNAE0123456789.,-"; - int id = EditorGUIUtility.GetControlID(m_ClickDragFloatID, FocusType.Keyboard, position); - Event evt = Event.current; - string str; - switch (evt.type) - { - case EventType.MouseUp: - if (GUIUtility.hotControl != id) - break; - evt.Use(); - if (position.Contains(evt.mousePosition) && !s_ClickDragFloatDragged) - { - EditorGUIUtility.editingTextField = true; - } - else - { - GUIUtility.keyboardControl = 0; - GUIUtility.hotControl = 0; - s_ClickDragFloatDragged = false; - } - break; - case EventType.MouseDown: - if (GUIUtility.keyboardControl == id && EditorGUIUtility.editingTextField) - break; - if (position.Contains(evt.mousePosition)) - { - evt.Use(); - s_ClickDragFloatDragged = false; - s_ClickDragFloatDistance = 0f; - GUIUtility.hotControl = id; - GUIUtility.keyboardControl = id; - EditorGUIUtility.editingTextField = false; - break; - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl != id || EditorGUIUtility.editingTextField) - break; - s_ClickDragFloatDistance += Mathf.Abs(HandleUtility.niceMouseDelta); - if (s_ClickDragFloatDistance >= 5f) - { - s_ClickDragFloatDragged = true; - value += HandleUtility.niceMouseDelta * .03f; - value = MathUtils.RoundBasedOnMinimumDifference(value, .03f); - GUI.changed = true; - } - evt.Use(); - break; - } - - GUIStyle style = (GUIUtility.keyboardControl == id && EditorGUIUtility.editingTextField) ? - (alignRight ? styles.clickDragFloatFieldRight : styles.clickDragFloatFieldLeft) : - (alignRight ? styles.clickDragFloatLabelRight : styles.clickDragFloatLabelLeft); - if (GUIUtility.keyboardControl == id) - { - if (!EditorGUI.s_RecycledEditor.IsEditingControl(id)) - { - str = EditorGUI.s_RecycledCurrentEditingString = value.ToString("g7"); - } - else - { - str = EditorGUI.s_RecycledCurrentEditingString; - if (evt.type == EventType.ValidateCommand && evt.commandName == EventCommandNames.UndoRedoPerformed) - str = value.ToString("g7"); - } - - str = EditorGUI.DoTextField(EditorGUI.s_RecycledEditor, id, position, str, style , allowedCharacters, out changed, false, false, false); - if (changed) - { - GUI.changed = true; - EditorGUI.s_RecycledCurrentEditingString = str; - string lowered = str.ToLower(); - if (lowered == "inf" || lowered == "infinity") - { - value = Mathf.Infinity; - } - else if (lowered == "-inf" || lowered == "-infinity") - { - value = Mathf.NegativeInfinity; - } - else - { - str = str.Replace(',', '.'); - if (!float.TryParse(str, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out value)) - { - EditorGUI.s_RecycledCurrentEditingFloat = 0; - value = 0; - return value; - } - if (System.Single.IsNaN(value)) - value = 0; - EditorGUI.s_RecycledCurrentEditingFloat = value; - } - } - } - else - { - str = value.ToString("g7"); - str = EditorGUI.DoTextField(EditorGUI.s_RecycledEditor, id, position, str, style, allowedCharacters, out changed, false, false, false); - } - return value; - } - - private void BlendGraph(Rect area) - { - // Adjust padding for rect - // (This is normally not needed anymore, but this style has some overdraw that needs to be compensated.) - area.xMin += 1; - area.xMax -= 1; - - int sliderId = GUIUtility.GetControlID(m_BlendAnimationID, FocusType.Passive); - - // get points array from child objects - int childCount = m_Childs.arraySize; - float[] points = new float[childCount]; - for (int i = 0; i < childCount; i++) - { - SerializedProperty child = m_Childs.GetArrayElementAtIndex(i); - SerializedProperty threshold = child.FindPropertyRelative("m_Threshold"); - points[i] = threshold.floatValue; - } - - // move points to GUI space - float min = Mathf.Min(points); - float max = Mathf.Max(points); - for (int i = 0; i < points.Length; i++) - { - points[i] = area.x + (Mathf.InverseLerp(min, max, points[i]) * area.width); - } - - // get blend bar info - string currentParameter = m_BlendTree.blendParameter; - float blendBar = area.x + (Mathf.InverseLerp(min, max, GetParameterValue(currentAnimator, m_BlendTree, currentParameter)) * area.width); - Rect barRect = new Rect(blendBar - 4f, area.y, 9f, 42f); - - Event evt = Event.current; - switch (evt.GetTypeForControl(sliderId)) - { - case EventType.Repaint: - styles.background.Draw(area, GUIContent.none, false, false, false, false); - if (m_Childs.arraySize >= 2) - { - for (int i = 0; i < points.Length; i++) - { - // draw the animation triangle - float last = (i == 0) ? points[i] : points[i - 1]; - float next = (i == points.Length - 1) ? points[i] : points[i + 1]; - bool drawSelected = (m_ReorderableList.index == i) ? true : false; - DrawAnimation(points[i], last, next, drawSelected, area); - } - Color oldColor = Handles.color; - Handles.color = new Color(0f, 0f, 0f, 0.25f); - Handles.DrawLine(new Vector3(area.x, area.y + area.height, 0f), new Vector3(area.x + area.width, area.y + area.height, 0f)); - Handles.color = oldColor; - // draw the current input bar - styles.blendPosition.Draw(barRect, GUIContent.none, false, false, false, false); - } - else - { - GUI.Label(area, EditorGUIUtility.TempContent("Please Add Motion Fields or Blend Trees"), styles.errorStyle); - } - break; - case EventType.MouseDown: - float curBlendValue = 0.0f; - if (barRect.Contains(evt.mousePosition)) - { - evt.Use(); - GUIUtility.hotControl = sliderId; - m_ReorderableList.index = -1; - - // Get current blend value. - curBlendValue = GetParameterValue(currentAnimator, m_BlendTree, currentParameter); - } - else if (area.Contains(evt.mousePosition)) - { - evt.Use(); - GUIUtility.hotControl = sliderId; - GUIUtility.keyboardControl = sliderId; - - // determine closest animation or blend tree - float clickPosition = evt.mousePosition.x; - float distance = Mathf.Infinity; - for (int i = 0; i < points.Length; i++) - { - float last = (i == 0) ? points[i] : points[i - 1]; - float next = (i == points.Length - 1) ? points[i] : points[i + 1]; - if (Mathf.Abs(clickPosition - points[i]) < distance) - { - if (clickPosition < next && clickPosition > last) - { - distance = Mathf.Abs(clickPosition - points[i]); - m_ReorderableList.index = i; - } - } - } - - // turn off automatic thresholds - m_UseAutomaticThresholds.boolValue = false; - - // Get current blend value. - SerializedProperty child = m_Childs.GetArrayElementAtIndex(m_ReorderableList.index); - SerializedProperty threshold = child.FindPropertyRelative("m_Threshold"); - curBlendValue = threshold.floatValue; - } - - // Get drag'n'drop infos. - float mouseBlendValue = (evt.mousePosition.x - area.x) / area.width; - mouseBlendValue = Mathf.LerpUnclamped(min, max, mouseBlendValue); - m_DragAndDropDelta = mouseBlendValue - curBlendValue; - m_OriginMin = min; - m_OriginMax = max; - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl != sliderId) - break; - - evt.Use(); - - // Convert mouse position to blend space. - float newMouseBlendValue = (evt.mousePosition.x - area.x) / area.width; - newMouseBlendValue = Mathf.LerpUnclamped(m_OriginMin, m_OriginMax, newMouseBlendValue); - float newBlendValue = newMouseBlendValue - m_DragAndDropDelta; - - if (m_ReorderableList.index == -1) - { - // the user is dragging the blend position - newBlendValue = Mathf.Clamp(newBlendValue, min, max); - SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, currentParameter, newBlendValue); - } - else - { - // set the new threshold based on mousePosition - SerializedProperty child = m_Childs.GetArrayElementAtIndex(m_ReorderableList.index); - SerializedProperty threshold = child.FindPropertyRelative("m_Threshold"); - - // get neighboring thresholds - SerializedProperty lastChild = (m_ReorderableList.index <= 0) ? child : m_Childs.GetArrayElementAtIndex(m_ReorderableList.index - 1); - SerializedProperty nextChild = (m_ReorderableList.index == m_Childs.arraySize - 1) ? child : m_Childs.GetArrayElementAtIndex(m_ReorderableList.index + 1); - SerializedProperty lastThreshold = lastChild.FindPropertyRelative("m_Threshold"); - SerializedProperty nextThreshold = nextChild.FindPropertyRelative("m_Threshold"); - - // change threshold value - threshold.floatValue = newBlendValue; - - // reorder if dragged beyond range - if (threshold.floatValue < lastThreshold.floatValue && m_ReorderableList.index != 0) - { - m_Childs.MoveArrayElement(m_ReorderableList.index, m_ReorderableList.index - 1); - m_ReorderableList.index -= 1; - } - if (threshold.floatValue > nextThreshold.floatValue && m_ReorderableList.index < m_Childs.arraySize - 1) - { - m_Childs.MoveArrayElement(m_ReorderableList.index, m_ReorderableList.index + 1); - m_ReorderableList.index += 1; - } - - // snap to near thresholds - float snapThreshold = 3f * ((max - min) / area.width); - if (threshold.floatValue - lastThreshold.floatValue <= snapThreshold) - { - threshold.floatValue = lastThreshold.floatValue; - } - else if (nextThreshold.floatValue - threshold.floatValue <= snapThreshold) - { - threshold.floatValue = nextThreshold.floatValue; - } - SetMinMaxThresholds(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == sliderId) - { - evt.Use(); - GUIUtility.hotControl = 0; - m_ReorderableList.index = -1; - } - break; - } - } - - private void UpdateBlendVisualization() - { - Vector2[] points = GetActiveMotionPositions(); - - if (m_BlendTex == null) - { - m_BlendTex = new Texture2D(kVisResolution, kVisResolution, TextureFormat.RGBA32, false); - m_BlendTex.hideFlags = HideFlags.HideAndDontSave; - m_BlendTex.wrapMode = TextureWrapMode.Clamp; - } - while (m_WeightTexs.Count < points.Length) - { - Texture2D tex = new Texture2D(kVisResolution, kVisResolution, TextureFormat.RGBA32, false); - tex.wrapMode = TextureWrapMode.Clamp; - tex.hideFlags = HideFlags.HideAndDontSave; - m_WeightTexs.Add(tex); - } - while (m_WeightTexs.Count > points.Length) - { - DestroyImmediate(m_WeightTexs[m_WeightTexs.Count - 1]); - m_WeightTexs.RemoveAt(m_WeightTexs.Count - 1); - } - - // Calculate min and max for all the points - if (GUIUtility.hotControl == 0) - m_BlendRect = Get2DBlendRect(GetMotionPositions()); - - m_VisBlendTree.Reset(); - - System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); - watch.Start(); - Texture2D[] textures = m_WeightTexs.ToArray(); - // While dragging, only update the weight texture that's being dragged. - if (GUIUtility.hotControl != 0 && m_ReorderableList.index >= 0) - { - int[] indices = GetMotionToActiveMotionIndices(); - for (int i = 0; i < textures.Length; i++) - if (indices[m_ReorderableList.index] != i) - textures[i] = null; - } - UnityEditorInternal.BlendTreePreviewUtility.CalculateBlendTexture(m_VisBlendTree.animator, 0, m_VisBlendTree.animator.GetCurrentAnimatorStateInfo(0).fullPathHash, - m_BlendTex, textures, m_BlendRect); - watch.Stop(); - - //Debug.Log ("CalculateBlendTexture took "+watch.ElapsedMilliseconds+" ms"); - } - - private Vector2[] GetMotionPositions() - { - int childCount = m_Childs.arraySize; - Vector2[] points = new Vector2[childCount]; - for (int i = 0; i < childCount; i++) - { - SerializedProperty child = m_Childs.GetArrayElementAtIndex(i); - SerializedProperty position = child.FindPropertyRelative("m_Position"); - points[i] = position.vector2Value; - } - return points; - } - - private Vector2[] GetActiveMotionPositions() - { - List points = new List(); - int childCount = m_Childs.arraySize; - for (int i = 0; i < childCount; i++) - { - SerializedProperty child = m_Childs.GetArrayElementAtIndex(i); - SerializedProperty motion = child.FindPropertyRelative("m_Motion"); - if (motion.objectReferenceValue != null) - { - SerializedProperty position = child.FindPropertyRelative("m_Position"); - points.Add(position.vector2Value); - } - } - return points.ToArray(); - } - - private int[] GetMotionToActiveMotionIndices() - { - int childCount = m_Childs.arraySize; - int[] indices = new int[childCount]; - int activeMotion = 0; - for (int i = 0; i < childCount; i++) - { - SerializedProperty child = m_Childs.GetArrayElementAtIndex(i); - SerializedProperty motion = child.FindPropertyRelative("m_Motion"); - if (motion.objectReferenceValue == null) - indices[i] = -1; - else - { - indices[i] = activeMotion; - activeMotion++; - } - } - return indices; - } - - private Rect Get2DBlendRect(Vector2[] points) - { - Vector2 center = Vector2.zero; - float maxDist = 0; - - if (points.Length == 0) - { - return new Rect(); - } - - if (m_BlendType.intValue == (int)BlendTreeType.FreeformCartesian2D) - { - // Make min and max rect with center at the bounds center - Vector2 min = points[0]; - Vector2 max = points[0]; - for (int i = 1; i < points.Length; i++) - { - max.x = Mathf.Max(max.x, points[i].x); - max.y = Mathf.Max(max.y, points[i].y); - min.x = Mathf.Min(min.x, points[i].x); - min.y = Mathf.Min(min.y, points[i].y); - } - center = (min + max) * 0.5f; - maxDist = Mathf.Max(max.x - min.x, max.y - min.y) * 0.5f; - } - else - { - // Make min and max a rect with the origin in the center - for (int i = 0; i < points.Length; i++) - { - maxDist = Mathf.Max(maxDist, points[i].x); - maxDist = Mathf.Max(maxDist, -points[i].x); - maxDist = Mathf.Max(maxDist, points[i].y); - maxDist = Mathf.Max(maxDist, -points[i].y); - } - } - - if (maxDist == 0) - maxDist = 1; - maxDist *= 1.35f; - return new Rect(center.x - maxDist, center.y - maxDist, maxDist * 2, maxDist * 2); - } - - private Rect m_BlendRect; - private int m_SelectedPoint = -1; - private bool s_DraggingPoint = false; - - private float ConvertFloat(float input, float fromMin, float fromMax, float toMin, float toMax) - { - float lerp = (input - fromMin) / (fromMax - fromMin); - return toMin * (1 - lerp) + toMax * lerp; - } - - private void BlendGraph2D(Rect area) - { - if (m_VisBlendTree.controllerDirty) - { - UpdateBlendVisualization(); - ValidatePositions(); - } - - // Get points array from child objects - Vector2[] points = GetMotionPositions(); - int[] presences = GetMotionToActiveMotionIndices(); - - Vector2 min = new Vector2(m_BlendRect.xMin, m_BlendRect.yMin); - Vector2 max = new Vector2(m_BlendRect.xMax, m_BlendRect.yMax); - - // Move points to GUI space - for (int i = 0; i < points.Length; i++) - { - points[i].x = ConvertFloat(points[i].x, min.x, max.x, area.xMin, area.xMax); - points[i].y = ConvertFloat(points[i].y, min.y, max.y, area.yMax, area.yMin); - } - - // Get the input blend info - string currentParameterX = m_BlendTree.blendParameter; - string currentParameterY = m_BlendTree.blendParameterY; - float inputX = GetParameterValue(currentAnimator, m_BlendTree, currentParameterX); - float inputY = GetParameterValue(currentAnimator, m_BlendTree, currentParameterY); - - // Get child weights - int activeChildCount = GetActiveMotionPositions().Length; - if (m_Weights == null || activeChildCount != m_Weights.Length) - m_Weights = new float[activeChildCount]; - - UnityEditorInternal.BlendTreePreviewUtility.CalculateRootBlendTreeChildWeights(m_VisBlendTree.animator, 0, m_VisBlendTree.animator.GetCurrentAnimatorStateInfo(0).fullPathHash, m_Weights, inputX, inputY); - - // Move input into GUI space - inputX = area.x + Mathf.InverseLerp(min.x, max.x, inputX) * area.width; - inputY = area.y + (1 - Mathf.InverseLerp(min.y, max.y, inputY)) * area.height; - Rect inputRect = new Rect(inputX - 5, inputY - 5, 11, 11); - - int drag2dId = GUIUtility.GetControlID(m_BlendAnimationID, FocusType.Passive); - - Event evt = Event.current; - switch (evt.GetTypeForControl(drag2dId)) - { - case EventType.Repaint: - GUI.color = styles.visBgColor; - GUI.DrawTexture(area, EditorGUIUtility.whiteTexture); - - // Draw weight texture - if (m_ReorderableList.index < 0) - { - Color col = styles.visWeightColor; - col.a *= 0.75f; - GUI.color = col; - GUI.DrawTexture(area, m_BlendTex); - } - else if (presences[m_ReorderableList.index] >= 0) - { - GUI.color = styles.visWeightColor; - GUI.DrawTexture(area, m_WeightTexs[presences[m_ReorderableList.index]]); - } - GUI.color = Color.white; - - // Draw the weight circles - if (!s_DraggingPoint) - { - for (int i = 0; i < points.Length; i++) - if (presences[i] >= 0) - DrawWeightShape(points[i], m_Weights[presences[i]], 0); - for (int i = 0; i < points.Length; i++) - if (presences[i] >= 0) - DrawWeightShape(points[i], m_Weights[presences[i]], 1); - } - - // Draw the animation points - for (int i = 0; i < points.Length; i++) - { - Rect pointRect = new Rect(points[i].x - 6, points[i].y - 6, 13, 13); - bool drawSelected = (m_ReorderableList.index == i) ? true : false; - - if (presences[i] < 0) - GUI.color = styles.visPointEmptyColor; - else - GUI.color = styles.visPointColor; - GUI.DrawTexture(pointRect, drawSelected ? styles.pointIconSelected : styles.pointIcon); - - if (drawSelected) - { - GUI.color = styles.visPointOverlayColor; - GUI.DrawTexture(pointRect, styles.pointIconOverlay); - } - } - - // Draw the input (sampler) point - if (!s_DraggingPoint) - { - GUI.color = styles.visSamplerColor; - GUI.DrawTexture(inputRect, styles.samplerIcon); - } - GUI.color = Color.white; - - break; - case EventType.MouseDown: - if (inputRect.Contains(evt.mousePosition)) - { - evt.Use(); - GUIUtility.hotControl = drag2dId; - m_SelectedPoint = -1; - } - else if (area.Contains(evt.mousePosition)) - { - m_ReorderableList.index = -1; - - for (int i = 0; i < points.Length; i++) - { - Rect pointRect = new Rect(points[i].x - 4, points[i].y - 4, 9, 9); - if (pointRect.Contains(evt.mousePosition)) - { - evt.Use(); - GUIUtility.hotControl = drag2dId; - m_SelectedPoint = i; - m_ReorderableList.index = i; - } - } - - // Use in any case so we deselect point and get repaint. - evt.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl != drag2dId) - break; - - if (m_SelectedPoint == -1) - { - // Convert mouse position to point in blend space - Vector2 mousePosition; - mousePosition.x = ConvertFloat(evt.mousePosition.x, area.xMin, area.xMax, min.x, max.x); - mousePosition.y = ConvertFloat(evt.mousePosition.y, area.yMax, area.yMin, min.y, max.y); - - // Set blend values - SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, currentParameterX, mousePosition.x); - SetParameterValue(currentAnimator, m_BlendTree, parentBlendTree, currentParameterY, mousePosition.y); - - evt.Use(); - } - else - { - for (int i = 0; i < points.Length; i++) - { - if (m_SelectedPoint == i) - { - // Convert mouse position to point in blend space - Vector2 mousePosition; - mousePosition.x = ConvertFloat(evt.mousePosition.x, area.xMin, area.xMax, min.x, max.x); - mousePosition.y = ConvertFloat(evt.mousePosition.y, area.yMax, area.yMin, min.y, max.y); - - float minDiff = (max.x - min.x) / area.width; - mousePosition.x = MathUtils.RoundBasedOnMinimumDifference(mousePosition.x, minDiff); - mousePosition.y = MathUtils.RoundBasedOnMinimumDifference(mousePosition.y, minDiff); - mousePosition.x = Mathf.Clamp(mousePosition.x, -10000, 10000); - mousePosition.y = Mathf.Clamp(mousePosition.y, -10000, 10000); - - SerializedProperty child = m_Childs.GetArrayElementAtIndex(i); - SerializedProperty position = child.FindPropertyRelative("m_Position"); - position.vector2Value = mousePosition; - - evt.Use(); - s_DraggingPoint = true; - } - } - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl != drag2dId) - break; - - evt.Use(); - GUIUtility.hotControl = 0; - s_DraggingPoint = false; - - break; - } - - // Draw message - if (m_ReorderableList.index >= 0 && presences[m_ReorderableList.index] < 0) - ShowHelp(area, EditorGUIUtility.TempContent("The selected child has no Motion assigned.")); - else if (m_WarningMessage != null) - ShowHelp(area, EditorGUIUtility.TempContent(m_WarningMessage)); - } - - private void ShowHelp(Rect area, GUIContent content) - { - float height = EditorStyles.helpBox.CalcHeight(content, area.width); - GUI.Label(new Rect(area.x, area.y, area.width, height), content, EditorStyles.helpBox); - } - - private void ValidatePositions() - { - m_WarningMessage = null; - Vector2[] points = GetMotionPositions(); - - // Check for duplicate positions (relevant for all blend types) - bool duplicatePositions = m_BlendRect.width == 0 || m_BlendRect.height == 0; - for (int i = 0; i < points.Length; i++) - { - for (int j = 0; j < i && !duplicatePositions; j++) - { - if (((points[i] - points[j]) / m_BlendRect.height).sqrMagnitude < 0.0001f) - { - duplicatePositions = true; - break; - } - } - } - if (duplicatePositions) - { - m_WarningMessage = "Two or more of the positions are too close to each other."; - return; - } - - // Checks for individual blend types below - - if (m_BlendType.intValue == (int)BlendTreeType.SimpleDirectional2D) - { - List angles = points.Where(e => e != Vector2.zero).Select(e => Mathf.Atan2(e.y, e.x)).OrderBy(e => e).ToList(); - float maxAngle = 0; - float minAngle = 180; - for (int i = 0; i < angles.Count; i++) - { - float angle = angles[(i + 1) % angles.Count] - angles[i]; - if (i == angles.Count - 1) - angle += Mathf.PI * 2; - if (angle > maxAngle) - maxAngle = angle; - if (angle < minAngle) - minAngle = angle; - } - if (maxAngle * Mathf.Rad2Deg >= 180) - m_WarningMessage = "Simple Directional blend should have motions with directions less than 180 degrees apart."; - else if (minAngle * Mathf.Rad2Deg < 2) - m_WarningMessage = "Simple Directional blend should not have multiple motions in almost the same direction."; - } - else if (m_BlendType.intValue == (int)BlendTreeType.FreeformDirectional2D) - { - // Check if this blend type has a motion in the center. - bool hasCenter = false; - for (int i = 0; i < points.Length; i++) - { - if (points[i] == Vector2.zero) - { - hasCenter = true; - break; - } - } - if (!hasCenter) - m_WarningMessage = "Freeform Directional blend should have one motion at position (0,0) to avoid discontinuities."; - } - } - - private int kNumCirclePoints = 20; - private void DrawWeightShape(Vector2 point, float weight, int pass) - { - if (weight <= 0) - return; - point.x = Mathf.Round(point.x); - point.y = Mathf.Round(point.y); - float radius = 20 * Mathf.Sqrt(weight); - - // Calculate points in a circle - Vector3[] points = new Vector3[kNumCirclePoints + 2]; - for (int i = 0; i < kNumCirclePoints; i++) - { - float v = (float)i / kNumCirclePoints; - 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; - } - // First and last point have to meet each other in a straight line; otherwise we'll get a gap - points[0] = points[kNumCirclePoints + 1] = (points[1] + points[kNumCirclePoints]) * 0.5f; - - if (pass == 0) - { - // Draw disc - Handles.color = styles.visWeightShapeColor; - Handles.DrawSolidDisc(point + new Vector2(0.5f, 0.5f), -Vector3.forward, radius); - } - else - { - // Draw outline - Handles.color = styles.visWeightLineColor; - Handles.DrawAAPolyLine(points); - } - } - - private void DrawAnimation(float val, float min, float max, bool selected, Rect area) - { - float top = area.y; - Rect leftRect = new Rect(min, top, val - min, area.height); - Rect rightRect = new Rect(val, top, max - val, area.height); - styles.triangleLeft.Draw(leftRect, selected, selected, false, false); - styles.triangleRight.Draw(rightRect, selected, selected, false, false); - area.height -= 1; - Color oldColor = Handles.color; - Color newColor = selected ? new Color(1f, 1f, 1f, 0.6f) : new Color(1f, 1f, 1f, 0.4f); - Handles.color = newColor; - if (selected) - Handles.DrawLine(new Vector3(val, top, 0), new Vector3(val, top + area.height, 0)); - Vector3[] points = new Vector3[2] {new Vector3(min, top + area.height, 0f), new Vector3(val, top, 0f)}; - Handles.DrawAAPolyLine(points); - points = new Vector3[2] {new Vector3(val, top, 0f), new Vector3(max, top + area.height, 0f)}; - Handles.DrawAAPolyLine(points); - Handles.color = oldColor; - } - - public void EndDragChild(UnityEditorInternal.ReorderableList list) - { - List dragThresholds = new List(); - for (int i = 0; i < m_Childs.arraySize; i++) - { - SerializedProperty child = m_Childs.GetArrayElementAtIndex(i); - SerializedProperty threshold = child.FindPropertyRelative("m_Threshold"); - dragThresholds.Add(threshold.floatValue); - } - dragThresholds.Sort(); - for (int i = 0; i < m_Childs.arraySize; i++) - { - SerializedProperty child = m_Childs.GetArrayElementAtIndex(i); - SerializedProperty threshold = child.FindPropertyRelative("m_Threshold"); - threshold.floatValue = dragThresholds[i]; - } - serializedObject.ApplyModifiedProperties(); - } - - private void DrawHeader(Rect headerRect) - { - headerRect.xMin += 14; // Ignore width used by drag-handles while calculating column widths. - headerRect.y++; - headerRect.height = 16; - - Rect[] rects = GetRowRects(headerRect, m_BlendType.intValue); - int col = 0; - - rects[col].xMin = rects[col].xMin - 14; // Make first column extend into space of drag-handles. - GUI.Label(rects[col], EditorGUIUtility.TempContent("Motion"), EditorStyles.label); - col++; - if (m_Childs.arraySize >= 1) - { - if (m_BlendType.intValue == (int)BlendTreeType.Simple1D) - { - GUI.Label(rects[col], EditorGUIUtility.TempContent("Threshold"), EditorStyles.label); - col++; - } - else if (m_BlendType.intValue == (int)BlendTreeType.Direct) - { - GUI.Label(rects[col], EditorGUIUtility.TempContent("Parameter"), EditorStyles.label); - col++; - } - else - { - GUI.Label(rects[col], EditorGUIUtility.TempContent("Pos X"), EditorStyles.label); - col++; - GUI.Label(rects[col], EditorGUIUtility.TempContent("Pos Y"), EditorStyles.label); - col++; - } - - GUI.Label(rects[col], styles.speedIcon, styles.headerIcon); - col++; - GUI.Label(rects[col], styles.mirrorIcon, styles.headerIcon); - } - } - - public void AddButton(Rect rect, UnityEditorInternal.ReorderableList list) - { - GenericMenu menu = new GenericMenu(); - menu.AddItem(EditorGUIUtility.TrTextContent("Add Motion Field"), false, AddChildAnimation); - menu.AddItem(EditorGUIUtility.TempContent("New Blend Tree"), false, AddBlendTreeCallback); - menu.Popup(rect, 0); - } - - public static bool DeleteBlendTreeDialog(string toDelete) - { - string title = "Delete selected Blend Tree asset?"; - - string subTitle = toDelete; - - return EditorUtility.DisplayDialog(title, subTitle, "Delete", "Cancel"); - } - - public void RemoveButton(UnityEditorInternal.ReorderableList list) - { - SerializedProperty child = m_Childs.GetArrayElementAtIndex(list.index); - SerializedProperty motion = child.FindPropertyRelative("m_Motion"); - - Motion actualMotion = motion.objectReferenceValue as Motion; - - if (actualMotion == null || DeleteBlendTreeDialog(actualMotion.name)) - { - m_Childs.DeleteArrayElementAtIndex(list.index); - if (list.index >= m_Childs.arraySize) - list.index = m_Childs.arraySize - 1; - SetMinMaxThresholds(); - - serializedObject.ApplyModifiedProperties(); - - // Layout has changed, bail out now. - EditorGUIUtility.ExitGUI(); - } - } - - private Rect[] GetRowRects(Rect r, int blendType) - { - int rowCount = blendType > (int)BlendTreeType.Simple1D && blendType < (int)BlendTreeType.Direct ? 2 : 1; - Rect[] rects = new Rect[3 + rowCount]; - - float remainingWidth = r.width; - float mirrorWidth = 16; - remainingWidth -= mirrorWidth; - remainingWidth -= 8 + 8 + 8 + (4 * (rowCount - 1)); - float numberWidth = Mathf.FloorToInt(remainingWidth * 0.2f); - float motionWidth = remainingWidth - numberWidth * (rowCount + 1); - - float x = r.x; - int col = 0; - - rects[col] = new Rect(x, r.y, motionWidth, r.height); - x += motionWidth + 8; - col++; - - for (int i = 0; i < rowCount; i++) - { - rects[col] = new Rect(x, r.y, numberWidth, r.height); - x += numberWidth + 4; - col++; - } - x += 4; - - rects[col] = new Rect(x, r.y, numberWidth, r.height); - x += numberWidth + 8; - col++; - - rects[col] = new Rect(x, r.y, mirrorWidth, r.height); - - return rects; - } - - public void DrawChild(Rect r, int index, bool isActive, bool isFocused) - { - SerializedProperty child = m_Childs.GetArrayElementAtIndex(index); - SerializedProperty motion = child.FindPropertyRelative("m_Motion"); - - r.y++; - r.height = 16; - Rect[] rects = GetRowRects(r, m_BlendType.intValue); - int col = 0; - - // show a property field for the motion clip - EditorGUI.BeginChangeCheck(); - - Motion prevMotion = m_BlendTree.children[index].motion; - EditorGUI.PropertyField(rects[col], motion, GUIContent.none); - col++; - if (EditorGUI.EndChangeCheck()) - { - if (prevMotion is BlendTree && prevMotion != (motion.objectReferenceValue as Motion)) - { - if (EditorUtility.DisplayDialog("Changing BlendTree will delete previous BlendTree", "You cannot undo this action.", "Delete", "Cancel")) - { - MecanimUtilities.DestroyBlendTreeRecursive(prevMotion as BlendTree); - } - else - { - motion.objectReferenceValue = prevMotion; - } - } - } - - // use a delayed text field and force re-sort if value is manually changed - if (m_BlendType.intValue == (int)BlendTreeType.Simple1D) - { - // Threshold in 1D blending - SerializedProperty threshold = child.FindPropertyRelative("m_Threshold"); - using (new EditorGUI.DisabledScope(m_UseAutomaticThresholds.boolValue)) - { - float nr = threshold.floatValue; - EditorGUI.BeginChangeCheck(); - string floatStr = EditorGUI.DelayedTextFieldInternal(rects[col], nr.ToString(), "inftynaeINFTYNAE0123456789.,-", EditorStyles.textField); - col++; - if (EditorGUI.EndChangeCheck()) - { - if (float.TryParse(floatStr, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out nr)) - { - threshold.floatValue = nr; - serializedObject.ApplyModifiedProperties(); - m_BlendTree.SortChildren(); - SetMinMaxThresholds(); - GUI.changed = true; - } - } - } - } - else if (m_BlendType.intValue == (int)BlendTreeType.Direct) - { - List parameters = CollectParameters(currentController); - Animations.ChildMotion[] childs = m_BlendTree.children; - - string directParam = childs[index].directBlendParameter; - - EditorGUI.BeginChangeCheck(); - directParam = EditorGUI.TextFieldDropDown(rects[col], directParam, parameters.ToArray()); - col++; - - if (EditorGUI.EndChangeCheck()) - { - childs[index].directBlendParameter = directParam; - m_BlendTree.children = childs; - } - } - else - { - // Position in 2D blending - SerializedProperty position = child.FindPropertyRelative("m_Position"); - Vector2 pos = position.vector2Value; - for (int i = 0; i < 2; i++) - { - EditorGUI.BeginChangeCheck(); - string valStr = EditorGUI.DelayedTextFieldInternal(rects[col], pos[i].ToString(), "inftynaeINFTYNAE0123456789.,-", EditorStyles.textField); - col++; - if (EditorGUI.EndChangeCheck()) - { - float coord; - if (float.TryParse(valStr, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out coord)) - { - pos[i] = Mathf.Clamp(coord, -10000, 10000); - position.vector2Value = pos; - serializedObject.ApplyModifiedProperties(); - GUI.changed = true; - } - } - } - } - - // If this is an animation, include the time scale. - if (motion.objectReferenceValue is AnimationClip) - { - SerializedProperty timeScale = child.FindPropertyRelative("m_TimeScale"); - EditorGUI.PropertyField(rects[col], timeScale, GUIContent.none); - } - else - { - // Otherwise show disabled dummy field with default value of 1. - using (new EditorGUI.DisabledScope(true)) - { - EditorGUI.IntField(rects[col], 1); - } - } - col++; - - // If this is a humanoid animation, include the mirror toggle. - if (motion.objectReferenceValue is AnimationClip && (motion.objectReferenceValue as AnimationClip).isHumanMotion) - { - SerializedProperty mirror = child.FindPropertyRelative("m_Mirror"); - EditorGUI.PropertyField(rects[col], mirror, GUIContent.none); - - SerializedProperty cycle = child.FindPropertyRelative("m_CycleOffset"); - cycle.floatValue = mirror.boolValue ? 0.5f : 0.0f; - } - else - { - // Otherwise show disabled dummy toggle that's disabled. - using (new EditorGUI.DisabledScope(true)) - { - EditorGUI.Toggle(rects[col], false); - } - } - } - - private bool AllMotions() - { - bool allClips = true; - for (int i = 0; i < m_Childs.arraySize && allClips; i++) - { - SerializedProperty motion = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative("m_Motion"); - allClips = motion.objectReferenceValue is AnimationClip; - } - return allClips; - } - - private void AutoCompute() - { - if (m_BlendType.intValue == (int)BlendTreeType.Simple1D) - { - EditorGUILayout.PropertyField(m_UseAutomaticThresholds, EditorGUIUtility.TempContent("Automate Thresholds")); - m_ShowCompute.target = !m_UseAutomaticThresholds.boolValue; - } - else if (m_BlendType.intValue == (int)BlendTreeType.Direct) - { - m_ShowCompute.target = false; - } - else - { - m_ShowCompute.target = true; - } - - m_ShowAdjust.target = AllMotions(); - - if (EditorGUILayout.BeginFadeGroup(m_ShowCompute.faded)) - { - Rect controlRect = EditorGUILayout.GetControlRect(); - GUIContent label = (ParameterCount == 1) ? - EditorGUIUtility.TempContent("Compute Thresholds") : - EditorGUIUtility.TempContent("Compute Positions"); - controlRect = EditorGUI.PrefixLabel(controlRect, 0, label); - - if (EditorGUI.DropdownButton(controlRect, EditorGUIUtility.TempContent("Select"), FocusType.Passive, EditorStyles.popup)) - { - GenericMenu menu = new GenericMenu(); - if (ParameterCount == 1) - { - AddComputeMenuItems(menu, string.Empty, ChildPropertyToCompute.Threshold); - } - else - { - menu.AddItem(EditorGUIUtility.TrTextContent("Velocity XZ"), false, ComputePositionsFromVelocity); - menu.AddItem(EditorGUIUtility.TrTextContent("Speed And Angular Speed"), false, ComputePositionsFromSpeedAndAngularSpeed); - AddComputeMenuItems(menu, "X Position From/", ChildPropertyToCompute.PositionX); - AddComputeMenuItems(menu, "Y Position From/", ChildPropertyToCompute.PositionY); - } - menu.DropDown(controlRect); - } - } - EditorGUILayout.EndFadeGroup(); - - if (EditorGUILayout.BeginFadeGroup(m_ShowAdjust.faded)) - { - Rect controlRect = EditorGUILayout.GetControlRect(); - controlRect = EditorGUI.PrefixLabel(controlRect, 0, EditorGUIUtility.TempContent("Adjust Time Scale")); - - if (EditorGUI.DropdownButton(controlRect, EditorGUIUtility.TempContent("Select"), FocusType.Passive, EditorStyles.popup)) - { - GenericMenu menu = new GenericMenu(); - menu.AddItem(EditorGUIUtility.TrTextContent("Homogeneous Speed"), false, ComputeTimeScaleFromSpeed); - menu.AddItem(EditorGUIUtility.TrTextContent("Reset Time Scale"), false, ResetTimeScale); - menu.DropDown(controlRect); - } - } - EditorGUILayout.EndFadeGroup(); - } - - enum ChildPropertyToCompute - { - Threshold, - PositionX, - PositionY - } - - delegate float GetFloatFromMotion(Motion motion, float mirrorMultiplier); - - void AddComputeMenuItems(GenericMenu menu, string menuItemPrefix, ChildPropertyToCompute prop) - { - menu.AddItem(new GUIContent(menuItemPrefix + "Speed"), false, ComputeFromSpeed, prop); - menu.AddItem(new GUIContent(menuItemPrefix + "Velocity X"), false, ComputeFromVelocityX, prop); - menu.AddItem(new GUIContent(menuItemPrefix + "Velocity Y"), false, ComputeFromVelocityY, prop); - menu.AddItem(new GUIContent(menuItemPrefix + "Velocity Z"), false, ComputeFromVelocityZ, prop); - menu.AddItem(new GUIContent(menuItemPrefix + "Angular Speed (Rad)"), false, ComputeFromAngularSpeedRadians, prop); - menu.AddItem(new GUIContent(menuItemPrefix + "Angular Speed (Deg)"), false, ComputeFromAngularSpeedDegrees, prop); - } - - private void ComputeFromSpeed(object obj) - { - ChildPropertyToCompute prop = (ChildPropertyToCompute)obj; - ComputeProperty((Motion m, float mirrorMultiplier) => m.apparentSpeed, prop); - } - - private void ComputeFromVelocityX(object obj) - { - ChildPropertyToCompute prop = (ChildPropertyToCompute)obj; - ComputeProperty((Motion m, float mirrorMultiplier) => m.averageSpeed.x * mirrorMultiplier, prop); - } - - private void ComputeFromVelocityY(object obj) - { - ChildPropertyToCompute prop = (ChildPropertyToCompute)obj; - ComputeProperty((Motion m, float mirrorMultiplier) => m.averageSpeed.y, prop); - } - - private void ComputeFromVelocityZ(object obj) - { - ChildPropertyToCompute prop = (ChildPropertyToCompute)obj; - ComputeProperty((Motion m, float mirrorMultiplier) => m.averageSpeed.z, prop); - } - - private void ComputeFromAngularSpeedDegrees(object obj) - { - ChildPropertyToCompute prop = (ChildPropertyToCompute)obj; - ComputeProperty((Motion m, float mirrorMultiplier) => m.averageAngularSpeed * 180.0f / Mathf.PI * mirrorMultiplier, prop); - } - - private void ComputeFromAngularSpeedRadians(object obj) - { - ChildPropertyToCompute prop = (ChildPropertyToCompute)obj; - ComputeProperty((Motion m, float mirrorMultiplier) => m.averageAngularSpeed * mirrorMultiplier, prop); - } - - private void ComputeProperty(GetFloatFromMotion func, ChildPropertyToCompute prop) - { - float mean = 0.0f; - float[] values = new float[m_Childs.arraySize]; - - m_UseAutomaticThresholds.boolValue = false; - for (int i = 0; i < m_Childs.arraySize; i++) - { - SerializedProperty motion = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative("m_Motion"); - SerializedProperty mirror = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative("m_Mirror"); - Motion motionObj = motion.objectReferenceValue as Motion; - if (motionObj != null) - { - float val = func(motionObj, mirror.boolValue ? -1 : 1); - values[i] = val; - mean += val; - if (prop == ChildPropertyToCompute.Threshold) - { - SerializedProperty threshold = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative("m_Threshold"); - threshold.floatValue = val; - } - else - { - SerializedProperty position = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative("m_Position"); - Vector2 pos = position.vector2Value; - if (prop == ChildPropertyToCompute.PositionX) - pos.x = val; - else - pos.y = val; - position.vector2Value = pos; - } - } - } - - mean /= (float)m_Childs.arraySize; - float variance = 0.0f; - for (int i = 0; i < values.Length; i++) - { - variance += Mathf.Pow(values[i] - mean, 2.0f); - } - variance /= values.Length; - - if (variance < Mathf.Epsilon) - { - Debug.LogWarning("Could not compute threshold for '" + m_BlendTree.name + "' there is not enough data"); - m_SerializedObject.Update(); - } - else - { - m_SerializedObject.ApplyModifiedProperties(); - if (prop == ChildPropertyToCompute.Threshold) - { - SortByThreshold(); - SetMinMaxThreshold(); - } - } - } - - private void ComputePositionsFromVelocity() - { - ComputeFromVelocityX(ChildPropertyToCompute.PositionX); - ComputeFromVelocityZ(ChildPropertyToCompute.PositionY); - } - - private void ComputePositionsFromSpeedAndAngularSpeed() - { - ComputeFromAngularSpeedRadians(ChildPropertyToCompute.PositionX); - ComputeFromSpeed(ChildPropertyToCompute.PositionY); - } - - private void ComputeTimeScaleFromSpeed() - { - float apparentSpeed = m_BlendTree.apparentSpeed; - for (int i = 0; i < m_Childs.arraySize; i++) - { - SerializedProperty motion = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative("m_Motion"); - AnimationClip clip = motion.objectReferenceValue as AnimationClip; - if (clip != null) - { - if (!clip.legacy) - { - if (clip.apparentSpeed < Mathf.Epsilon) - { - Debug.LogWarning("Could not adjust time scale for " + clip.name + " because it has no speed"); - } - else - { - SerializedProperty timeScale = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative("m_TimeScale"); - timeScale.floatValue = apparentSpeed / clip.apparentSpeed; - } - } - else - { - Debug.LogWarning("Could not adjust time scale for " + clip.name + " because it is not a muscle clip"); - } - } - } - m_SerializedObject.ApplyModifiedProperties(); - } - - private void ResetTimeScale() - { - for (int i = 0; i < m_Childs.arraySize; i++) - { - SerializedProperty motion = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative("m_Motion"); - AnimationClip clip = motion.objectReferenceValue as AnimationClip; - if (clip != null && !clip.legacy) - { - SerializedProperty timeScale = m_Childs.GetArrayElementAtIndex(i).FindPropertyRelative("m_TimeScale"); - timeScale.floatValue = 1; - } - } - m_SerializedObject.ApplyModifiedProperties(); - } - - private void SortByThreshold() - { - m_SerializedObject.Update(); - for (int i = 0; i < m_Childs.arraySize; i++) - { - float minThreshold = Mathf.Infinity; - int minIndex = -1; - for (int j = i; j < m_Childs.arraySize; j++) - { - SerializedProperty testElement = m_Childs.GetArrayElementAtIndex(j); - float testThreshold = testElement.FindPropertyRelative("m_Threshold").floatValue; - if (testThreshold < minThreshold) - { - minThreshold = testThreshold; - minIndex = j; - } - } - if (minIndex != i) - m_Childs.MoveArrayElement(minIndex, i); - } - - m_SerializedObject.ApplyModifiedProperties(); - } - - private void SetMinMaxThreshold() - { - m_SerializedObject.Update(); - SerializedProperty minThreshold = m_Childs.GetArrayElementAtIndex(0).FindPropertyRelative("m_Threshold"); - SerializedProperty maxThreshold = m_Childs.GetArrayElementAtIndex(m_Childs.arraySize - 1).FindPropertyRelative("m_Threshold"); - m_MinThreshold.floatValue = Mathf.Min(minThreshold.floatValue, maxThreshold.floatValue); - m_MaxThreshold.floatValue = Mathf.Max(minThreshold.floatValue, maxThreshold.floatValue); - m_SerializedObject.ApplyModifiedProperties(); - } - - void AddChildAnimation() - { - m_BlendTree.AddChild(null); - int numChildren = m_BlendTree.children.Length; - m_BlendTree.SetDirectBlendTreeParameter(numChildren - 1, currentController.GetDefaultBlendTreeParameter()); - SetNewThresholdAndPosition(numChildren - 1); - m_ReorderableList.index = numChildren - 1; - } - - void AddBlendTreeCallback() - { - BlendTree tree = m_BlendTree.CreateBlendTreeChild(0); - ChildMotion[] children = m_BlendTree.children; - int numChildren = children.Length; - - if (currentController != null) - { - tree.blendParameter = m_BlendTree.blendParameter; - m_BlendTree.SetDirectBlendTreeParameter(numChildren - 1, currentController.GetDefaultBlendTreeParameter()); - } - - SetNewThresholdAndPosition(numChildren - 1); - m_ReorderableList.index = m_Childs.arraySize - 1; - } - - void SetNewThresholdAndPosition(int index) - { - serializedObject.Update(); - - // Set new threshold - if (!m_UseAutomaticThresholds.boolValue) - { - float newThreshold = 0f; - if (m_Childs.arraySize >= 3 && index == m_Childs.arraySize - 1) - { - float threshold1 = m_Childs.GetArrayElementAtIndex(index - 2).FindPropertyRelative("m_Threshold").floatValue; - float threshold2 = m_Childs.GetArrayElementAtIndex(index - 1).FindPropertyRelative("m_Threshold").floatValue; - newThreshold = threshold2 + (threshold2 - threshold1); - } - else - { - if (m_Childs.arraySize == 1) - newThreshold = 0; - else - newThreshold = m_Childs.GetArrayElementAtIndex(m_Childs.arraySize - 1).FindPropertyRelative("m_Threshold").floatValue + 1; - } - SerializedProperty addedThreshold = m_Childs.GetArrayElementAtIndex(index).FindPropertyRelative("m_Threshold"); - addedThreshold.floatValue = newThreshold; - SetMinMaxThresholds(); - } - - // Set new position - Vector2 newPosition = Vector2.zero; - if (m_Childs.arraySize >= 1) - { - Vector2 center = m_BlendRect.center; - Vector2[] points = GetMotionPositions(); - float goodMinDist = m_BlendRect.width * 0.07f; - bool satisfied = false; - // Try to place new point along circle around center until successful - for (int iter = 0; iter < 24; iter++) - { - satisfied = true; - for (int i = 0; i < points.Length && satisfied; i++) - if (i != index && Vector2.Distance(points[i], newPosition) < goodMinDist) - satisfied = false; - - if (satisfied) - break; - - float radians = iter * 15 * Mathf.Deg2Rad; - newPosition = center + new Vector2(-Mathf.Cos(radians), Mathf.Sin(radians)) * 0.37f * m_BlendRect.width; - newPosition.x = MathUtils.RoundBasedOnMinimumDifference(newPosition.x, m_BlendRect.width * 0.005f); - newPosition.y = MathUtils.RoundBasedOnMinimumDifference(newPosition.y, m_BlendRect.width * 0.005f); - } - } - SerializedProperty addedPosition = m_Childs.GetArrayElementAtIndex(index).FindPropertyRelative("m_Position"); - addedPosition.vector2Value = newPosition; - - serializedObject.ApplyModifiedProperties(); - } - - public override bool HasPreviewGUI() - { - if (m_PreviewBlendTree != null) - { - return m_PreviewBlendTree.HasPreviewGUI(); - } - return false; - } - - public override void OnPreviewSettings() - { - if (m_PreviewBlendTree != null) - m_PreviewBlendTree.OnPreviewSettings(); - } - - public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - if (m_PreviewBlendTree != null) - m_PreviewBlendTree.OnInteractivePreviewGUI(r, background); - } - - public void OnDisable() - { - if (m_PreviewBlendTree != null) - m_PreviewBlendTree.OnDisable(); - - if (m_VisBlendTree != null) - m_VisBlendTree.Reset(); - } - - public void OnDestroy() - { - if (m_PreviewBlendTree != null) - m_PreviewBlendTree.OnDestroy(); - if (m_VisBlendTree != null) - m_VisBlendTree.Destroy(); - if (m_VisInstance != null) - DestroyImmediate(m_VisInstance); - for (int i = 0; i < m_WeightTexs.Count; i++) - DestroyImmediate(m_WeightTexs[i]); - if (m_BlendTex != null) - DestroyImmediate(m_BlendTex); - } - } - - class VisualizationBlendTree - { - private AnimatorController m_Controller; - private AnimatorStateMachine m_StateMachine; - private AnimatorState m_State; - private BlendTree m_BlendTree; - private Animator m_Animator; - private bool m_ControllerIsDirty = false; - - public Animator animator { get { return m_Animator; } } - - public void Init(BlendTree blendTree, Animator animator) - { - m_BlendTree = blendTree; - m_Animator = animator; - m_Animator.logWarnings = false; - m_Animator.fireEvents = false; - m_Animator.enabled = false; - m_Animator.cullingMode = AnimatorCullingMode.AlwaysAnimate; - CreateStateMachine(); - } - - public bool controllerDirty - { - get - { - return m_ControllerIsDirty; - } - } - protected virtual void ControllerDirty() - { - m_ControllerIsDirty = true; - } - - private void CreateParameters() - { - for (int i = 0; i < m_BlendTree.recursiveBlendParameterCount; i++) - m_Controller.AddParameter(m_BlendTree.GetRecursiveBlendParameter(i), AnimatorControllerParameterType.Float); - } - - private void CreateStateMachine() - { - if (m_Controller == null) - { - m_Controller = new AnimatorController(); - m_Controller.pushUndo = false; - m_Controller.AddLayer("viz"); - m_StateMachine = m_Controller.layers[0].stateMachine; - m_StateMachine.pushUndo = false; - CreateParameters(); - m_State = m_StateMachine.AddState("viz"); - m_State.pushUndo = false; - m_State.motion = m_BlendTree; - m_State.iKOnFeet = false; - - m_State.hideFlags = HideFlags.HideAndDontSave; - m_StateMachine.hideFlags = HideFlags.HideAndDontSave; - m_Controller.hideFlags = HideFlags.HideAndDontSave; - - AnimatorController.SetAnimatorController(m_Animator, m_Controller); - - m_Controller.OnAnimatorControllerDirty += ControllerDirty; - m_ControllerIsDirty = false; - } - } - - private void ClearStateMachine() - { - if (m_Animator != null) - AnimatorController.SetAnimatorController(m_Animator, null); - - if (m_Controller != null) - m_Controller.OnAnimatorControllerDirty -= ControllerDirty; - - Object.DestroyImmediate(m_Controller); - Object.DestroyImmediate(m_State); - m_StateMachine = null; - m_Controller = null; - m_State = null; - } - - public void Reset() - { - ClearStateMachine(); - CreateStateMachine(); - } - - public void Destroy() - { - ClearStateMachine(); - } - - public void Update() - { - if (m_ControllerIsDirty) - Reset(); - - int count = m_BlendTree.recursiveBlendParameterCount; - if (m_Controller.parameters.Length < count) - return; - - for (int i = 0; i < count; i++) - { - string blendParameter = m_BlendTree.GetRecursiveBlendParameter(i); - float value = BlendTreeInspector.GetParameterValue(animator, m_BlendTree, blendParameter); - animator.SetFloat(blendParameter, value); - } - animator.EvaluateController(); - } - } - - class PreviewBlendTree - { - private AnimatorController m_Controller; - private AvatarPreview m_AvatarPreview; - private AnimatorStateMachine m_StateMachine; - private AnimatorState m_State; - private BlendTree m_BlendTree; - - - private bool m_ControllerIsDirty = false; - protected virtual void ControllerDirty() - { - m_ControllerIsDirty = true; - } - - bool m_PrevIKOnFeet; - - public Animator PreviewAnimator { get { return m_AvatarPreview.Animator; } } - - public void Init(BlendTree blendTree, Animator animator) - { - m_BlendTree = blendTree; - if (m_AvatarPreview == null) - { - m_AvatarPreview = new AvatarPreview(animator, m_BlendTree); - m_AvatarPreview.OnAvatarChangeFunc = OnPreviewAvatarChanged; - m_AvatarPreview.ResetPreviewFocus(); - m_PrevIKOnFeet = m_AvatarPreview.IKOnFeet; - } - - CreateStateMachine(); - } - - public void CreateParameters() - { - for (int i = 0; i < m_BlendTree.recursiveBlendParameterCount; i++) - { - m_Controller.AddParameter(m_BlendTree.GetRecursiveBlendParameter(i), AnimatorControllerParameterType.Float); - } - } - - private void CreateStateMachine() - { - if (m_AvatarPreview != null && m_AvatarPreview.Animator != null) - { - if (m_Controller == null) - { - m_Controller = new AnimatorController(); - m_Controller.pushUndo = false; - m_Controller.AddLayer("preview"); - m_StateMachine = m_Controller.layers[0].stateMachine; - m_StateMachine.pushUndo = false; - CreateParameters(); - - m_State = m_StateMachine.AddState("preview"); - m_State.pushUndo = false; - m_State.motion = m_BlendTree; - m_State.iKOnFeet = m_AvatarPreview.IKOnFeet; - - m_State.hideFlags = HideFlags.HideAndDontSave; - m_Controller.hideFlags = HideFlags.HideAndDontSave; - m_StateMachine.hideFlags = HideFlags.HideAndDontSave; - - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller); - m_Controller.OnAnimatorControllerDirty += ControllerDirty; - - m_ControllerIsDirty = false; - } - - if (AnimatorController.GetEffectiveAnimatorController(m_AvatarPreview.Animator) != m_Controller) - AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, m_Controller); - } - } - - private void ClearStateMachine() - { - if (m_AvatarPreview != null && m_AvatarPreview.Animator != null) AnimatorController.SetAnimatorController(m_AvatarPreview.Animator, null); - - if (m_Controller != null) - m_Controller.OnAnimatorControllerDirty -= ControllerDirty; - - Object.DestroyImmediate(m_Controller); - Object.DestroyImmediate(m_State); - m_StateMachine = null; - m_Controller = null; - m_State = null; - } - - private void OnPreviewAvatarChanged() - { - ResetStateMachine(); - } - - public void ResetStateMachine() - { - ClearStateMachine(); - CreateStateMachine(); - } - - public void OnDisable() - { - ClearStateMachine(); - m_AvatarPreview.OnDestroy(); - } - - public void OnDestroy() - { - ClearStateMachine(); - if (m_AvatarPreview != null) - { - m_AvatarPreview.OnDestroy(); - m_AvatarPreview = null; - } - } - - private void UpdateAvatarState() - { - if (Event.current.type != EventType.Repaint) - return; - - if (m_AvatarPreview.PreviewObject == null || m_ControllerIsDirty) - { - m_AvatarPreview.ResetPreviewInstance(); - if (m_AvatarPreview.PreviewObject) - ResetStateMachine(); - } - - if (m_AvatarPreview.Animator) - { - if (m_PrevIKOnFeet != m_AvatarPreview.IKOnFeet) - { - m_PrevIKOnFeet = m_AvatarPreview.IKOnFeet; - Vector3 prevPos = m_AvatarPreview.Animator.rootPosition; - Quaternion prevRotation = m_AvatarPreview.Animator.rootRotation; - ResetStateMachine(); - m_AvatarPreview.Animator.Update(m_AvatarPreview.timeControl.currentTime); - m_AvatarPreview.Animator.Update(0); // forces deltaPos/Rot to 0,0,0 - m_AvatarPreview.Animator.rootPosition = prevPos; - m_AvatarPreview.Animator.rootRotation = prevRotation; - } - - if (m_AvatarPreview.Animator) - { - for (int i = 0; i < m_BlendTree.recursiveBlendParameterCount; i++) - { - string blendParameter = m_BlendTree.GetRecursiveBlendParameter(i); - float value = BlendTreeInspector.GetParameterValue(m_AvatarPreview.Animator, m_BlendTree, blendParameter); - m_AvatarPreview.Animator.SetFloat(blendParameter, value); - } - } - - m_AvatarPreview.timeControl.loop = true; - - float stateLength = 1.0f; - float stateTime = 0.0f; - - if (m_AvatarPreview.Animator.layerCount > 0) - { - AnimatorStateInfo stateInfo = m_AvatarPreview.Animator.GetCurrentAnimatorStateInfo(0); - stateLength = stateInfo.length; - stateTime = stateInfo.normalizedTime; - } - - m_AvatarPreview.timeControl.startTime = 0.0f; - m_AvatarPreview.timeControl.stopTime = stateLength; - - m_AvatarPreview.timeControl.Update(); - - float deltaTime = m_AvatarPreview.timeControl.deltaTime; - - if (!m_BlendTree.isLooping) - { - if (stateTime >= 1.0f) - { - deltaTime -= stateLength; - } - else if (stateTime < 0.0f) - { - deltaTime += stateLength; - } - } - - m_AvatarPreview.Animator.Update(deltaTime); - } - } - - public void TestForReset() - { - if ((m_State != null && m_AvatarPreview != null && m_State.iKOnFeet != m_AvatarPreview.IKOnFeet)) - { - ResetStateMachine(); - } - } - - public bool HasPreviewGUI() - { - return true; - } - - public void OnPreviewSettings() - { - m_AvatarPreview.DoPreviewSettings(); - } - - public void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - UpdateAvatarState(); - - m_AvatarPreview.DoAvatarPreview(r, background); - } - } -} diff --git a/Editor/Mono/Inspector/BoxCollider2DEditor.cs b/Editor/Mono/Inspector/BoxCollider2DEditor.cs deleted file mode 100644 index b7dff110bd..0000000000 --- a/Editor/Mono/Inspector/BoxCollider2DEditor.cs +++ /dev/null @@ -1,120 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor.IMGUI.Controls; -using UnityEditor.AnimatedValues; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - [CustomEditor(typeof(BoxCollider2D))] - [CanEditMultipleObjects] - internal class BoxCollider2DEditor : Collider2DEditorBase - { - private SerializedProperty m_Size; - private SerializedProperty m_EdgeRadius; - private SerializedProperty m_UsedByComposite; - private readonly AnimBool m_ShowCompositeRedundants = new AnimBool(); - private readonly BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle(); - - protected override GUIContent editModeButton { get { return PrimitiveBoundsHandle.editModeButton; } } - - public override void OnEnable() - { - base.OnEnable(); - - m_Size = serializedObject.FindProperty("m_Size"); - m_EdgeRadius = serializedObject.FindProperty("m_EdgeRadius"); - m_BoundsHandle.axes = BoxBoundsHandle.Axes.X | BoxBoundsHandle.Axes.Y; - m_UsedByComposite = serializedObject.FindProperty("m_UsedByComposite"); - m_AutoTiling = serializedObject.FindProperty("m_AutoTiling"); - m_ShowCompositeRedundants.value = !m_UsedByComposite.boolValue; - m_ShowCompositeRedundants.valueChanged.AddListener(Repaint); - } - - public override void OnDisable() - { - base.OnDisable(); - - m_ShowCompositeRedundants.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - bool disableEditCollider = !CanEditCollider(); - if (disableEditCollider) - { - EditorGUILayout.HelpBox(Styles.s_ColliderEditDisableHelp.text, MessageType.Info); - if (editingCollider) - EditMode.QuitEditMode(); - } - else - InspectorEditButtonGUI(); - - base.OnInspectorGUI(); - - EditorGUILayout.PropertyField(m_Size); - - m_ShowCompositeRedundants.target = !m_UsedByComposite.boolValue; - if (EditorGUILayout.BeginFadeGroup(m_ShowCompositeRedundants.faded)) - EditorGUILayout.PropertyField(m_EdgeRadius); - EditorGUILayout.EndFadeGroup(); - - serializedObject.ApplyModifiedProperties(); - - FinalizeInspectorGUI(); - } - - protected virtual void OnSceneGUI() - { - if (!editingCollider) - return; - - BoxCollider2D collider = (BoxCollider2D)target; - - if (Mathf.Approximately(collider.transform.lossyScale.sqrMagnitude, 0f)) - return; - - // collider matrix is 2d projection of transform's rotation onto x/y plane about transform's origin - Matrix4x4 handleMatrix = collider.transform.localToWorldMatrix; - handleMatrix.SetRow(0, Vector4.Scale(handleMatrix.GetRow(0), new Vector4(1f, 1f, 0f, 1f))); - handleMatrix.SetRow(1, Vector4.Scale(handleMatrix.GetRow(1), new Vector4(1f, 1f, 0f, 1f))); - handleMatrix.SetRow(2, new Vector4(0f, 0f, 1f, collider.transform.position.z)); - if (collider.usedByComposite && collider.composite != null) - { - // composite offset is rotated by composite's transformation matrix and projected back onto 2D plane - var compositeOffset = collider.composite.transform.rotation * collider.composite.offset; - compositeOffset.z = 0f; - handleMatrix = Matrix4x4.TRS(compositeOffset, Quaternion.identity, Vector3.one) * handleMatrix; - } - using (new Handles.DrawingScope(handleMatrix)) - { - m_BoundsHandle.center = collider.offset; - m_BoundsHandle.size = collider.size; - - m_BoundsHandle.SetColor(collider.enabled ? Handles.s_ColliderHandleColor : Handles.s_ColliderHandleColorDisabled); - EditorGUI.BeginChangeCheck(); - m_BoundsHandle.DrawHandle(); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(collider, string.Format("Modify {0}", ObjectNames.NicifyVariableName(target.GetType().Name))); - - // test for size change after using property setter in case input data was sanitized - Vector2 oldSize = collider.size; - collider.size = m_BoundsHandle.size; - - // because projection of offset is a lossy operation, only do it if the size has actually changed - // this check prevents drifting while dragging handle when size is zero (case 863949) - if (collider.size != oldSize) - { - collider.offset = m_BoundsHandle.center; - } - } - } - } - } -} diff --git a/Editor/Mono/Inspector/BoxColliderEditor.cs b/Editor/Mono/Inspector/BoxColliderEditor.cs deleted file mode 100644 index f799393a69..0000000000 --- a/Editor/Mono/Inspector/BoxColliderEditor.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(BoxCollider))] - [CanEditMultipleObjects] - internal class BoxColliderEditor : PrimitiveCollider3DEditor - { - SerializedProperty m_Center; - SerializedProperty m_Size; - private readonly BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle(); - - protected GUIContent centerContent = EditorGUIUtility.TrTextContent("Center", "The position of the Collider in the object’s local space."); - protected GUIContent sizeContent = EditorGUIUtility.TrTextContent("Size", "The size of the Collider in the X, Y, Z directions."); - - - public override void OnEnable() - { - base.OnEnable(); - - m_Center = serializedObject.FindProperty("m_Center"); - m_Size = serializedObject.FindProperty("m_Size"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - InspectorEditButtonGUI(); - EditorGUILayout.PropertyField(m_IsTrigger, triggerContent); - EditorGUILayout.PropertyField(m_Material, materialContent); - EditorGUILayout.PropertyField(m_Center, centerContent); - EditorGUILayout.PropertyField(m_Size, sizeContent); - - serializedObject.ApplyModifiedProperties(); - } - - protected override PrimitiveBoundsHandle boundsHandle { get { return m_BoundsHandle; } } - - protected override void CopyColliderPropertiesToHandle() - { - BoxCollider collider = (BoxCollider)target; - m_BoundsHandle.center = TransformColliderCenterToHandleSpace(collider.transform, collider.center); - m_BoundsHandle.size = Vector3.Scale(collider.size, collider.transform.lossyScale); - } - - protected override void CopyHandlePropertiesToCollider() - { - BoxCollider collider = (BoxCollider)target; - collider.center = TransformHandleCenterToColliderSpace(collider.transform, m_BoundsHandle.center); - Vector3 size = Vector3.Scale(m_BoundsHandle.size, InvertScaleVector(collider.transform.lossyScale)); - size = new Vector3(Mathf.Abs(size.x), Mathf.Abs(size.y), Mathf.Abs(size.z)); - collider.size = size; - } - } -} diff --git a/Editor/Mono/Inspector/BuoyancyEffector2DEditor.cs b/Editor/Mono/Inspector/BuoyancyEffector2DEditor.cs deleted file mode 100644 index 02391f5c48..0000000000 --- a/Editor/Mono/Inspector/BuoyancyEffector2DEditor.cs +++ /dev/null @@ -1,143 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - /// - /// Prompts the end-user to add 2D colliders if non exist for 2D effector to work with. - /// - [CustomEditor(typeof(BuoyancyEffector2D), true)] - [CanEditMultipleObjects] - internal class BuoyancyEffector2DEditor : Effector2DEditor - { - SerializedProperty m_Density; - SerializedProperty m_SurfaceLevel; - - static readonly AnimBool m_ShowDampingRollout = new AnimBool(); - SerializedProperty m_LinearDrag; - SerializedProperty m_AngularDrag; - - static readonly AnimBool m_ShowFlowRollout = new AnimBool(); - SerializedProperty m_FlowAngle; - SerializedProperty m_FlowMagnitude; - SerializedProperty m_FlowVariation; - - public override void OnEnable() - { - base.OnEnable(); - - m_Density = serializedObject.FindProperty("m_Density"); - m_SurfaceLevel = serializedObject.FindProperty("m_SurfaceLevel"); - - m_ShowDampingRollout.valueChanged.AddListener(Repaint); - m_LinearDrag = serializedObject.FindProperty("m_LinearDrag"); - m_AngularDrag = serializedObject.FindProperty("m_AngularDrag"); - - m_ShowFlowRollout.valueChanged.AddListener(Repaint); - m_FlowAngle = serializedObject.FindProperty("m_FlowAngle"); - m_FlowMagnitude = serializedObject.FindProperty("m_FlowMagnitude"); - m_FlowVariation = serializedObject.FindProperty("m_FlowVariation"); - } - - public override void OnDisable() - { - base.OnDisable(); - - m_ShowDampingRollout.valueChanged.RemoveListener(Repaint); - m_ShowFlowRollout.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_Density); - EditorGUILayout.PropertyField(m_SurfaceLevel); - - // Drag. - m_ShowDampingRollout.target = EditorGUILayout.Foldout(m_ShowDampingRollout.target, "Damping", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowDampingRollout.faded)) - { - EditorGUILayout.PropertyField(m_LinearDrag); - EditorGUILayout.PropertyField(m_AngularDrag); - EditorGUILayout.Space(); - } - EditorGUILayout.EndFadeGroup(); - - // Flow. - m_ShowFlowRollout.target = EditorGUILayout.Foldout(m_ShowFlowRollout.target, "Flow", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowFlowRollout.faded)) - { - EditorGUILayout.PropertyField(m_FlowAngle); - EditorGUILayout.PropertyField(m_FlowMagnitude); - EditorGUILayout.PropertyField(m_FlowVariation); - } - EditorGUILayout.EndFadeGroup(); - - serializedObject.ApplyModifiedProperties(); - } - - public void OnSceneGUI() - { - var effector = (BuoyancyEffector2D)target; - - // Ignore disabled effector. - if (!effector.enabled) - return; - - - var effectorPosition = effector.transform.position; - var surfaceY = effectorPosition.y + (effector.transform.lossyScale.y * effector.surfaceLevel); - - var intersections = new List(); - var farLeft = float.NegativeInfinity; - var farRight = farLeft; - - // Fetch all the effector-collider bounds. - foreach (var c in effector.gameObject.GetComponents().Where(c => c.enabled && c.usedByEffector)) - { - var b = c.bounds; - var left = b.min.x; - var right = b.max.x; - if (float.IsNegativeInfinity(farLeft)) - { - farLeft = left; - farRight = right; - } - else - { - if (left < farLeft) - farLeft = left; - - if (right > farRight) - farRight = right; - } - - var start = new Vector3(left, surfaceY, 0.0f); - var end = new Vector3(right, surfaceY, 0.0f); - - intersections.Add(start); - intersections.Add(end); - } - - // Draw the overall surface. - Handles.color = Color.red; - Handles.DrawAAPolyLine(new Vector3[] { new Vector3(farLeft, surfaceY, 0.0f), new Vector3(farRight, surfaceY, 0.0f) }); - - // Draw the collider intersections. - Handles.color = Color.cyan; - for (var i = 0; i < intersections.Count - 1; i = i + 2) - { - Handles.DrawAAPolyLine(intersections[i], intersections[i + 1]); - } - } - } -} diff --git a/Editor/Mono/Inspector/CameraEditor.cs b/Editor/Mono/Inspector/CameraEditor.cs deleted file mode 100644 index 3084ffe3d5..0000000000 --- a/Editor/Mono/Inspector/CameraEditor.cs +++ /dev/null @@ -1,748 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Text; -using UnityEngine; -using UnityEngine.Rendering; -using AnimatedBool = UnityEditor.AnimatedValues.AnimBool; -using UnityEngine.Scripting; -using UnityEditor.Modules; - -namespace UnityEditor -{ - [CustomEditor(typeof(Camera))] - [CanEditMultipleObjects] - public class CameraEditor : Editor - { - public sealed class Settings - { - private SerializedObject m_SerializedObject; - public Settings(SerializedObject so) - { - m_SerializedObject = so; - } - - // Manually entered rendering path names/values, since we want to show them - // in different order than they appear in the enum. - private static readonly GUIContent[] kCameraRenderPaths = - { - EditorGUIUtility.TrTextContent("Use Graphics Settings"), - EditorGUIUtility.TrTextContent("Forward"), - EditorGUIUtility.TrTextContent("Deferred"), - EditorGUIUtility.TrTextContent("Legacy Vertex Lit"), - EditorGUIUtility.TrTextContent("Legacy Deferred (light prepass)") - }; - private static readonly int[] kCameraRenderPathValues = - { - (int)RenderingPath.UsePlayerSettings, - (int)RenderingPath.Forward, - (int)RenderingPath.DeferredShading, - (int)RenderingPath.VertexLit, - (int)RenderingPath.DeferredLighting - }; - - public SerializedProperty clearFlags { get; private set; } - public SerializedProperty backgroundColor { get; private set; } - public SerializedProperty normalizedViewPortRect { get; private set; } - public SerializedProperty fieldOfView { get; private set; } - public SerializedProperty orthographic { get; private set; } - public SerializedProperty orthographicSize { get; private set; } - public SerializedProperty depth { get; private set; } - public SerializedProperty cullingMask { get; private set; } - public SerializedProperty renderingPath { get; private set; } - public SerializedProperty occlusionCulling { get; private set; } - public SerializedProperty targetTexture { get; private set; } - public SerializedProperty HDR { get; private set; } - public SerializedProperty allowMSAA { get; private set; } - public SerializedProperty allowDynamicResolution { get; private set; } - public SerializedProperty stereoConvergence { get; private set; } - public SerializedProperty stereoSeparation { get; private set; } - public SerializedProperty nearClippingPlane { get; private set; } - public SerializedProperty farClippingPlane { get; private set; } - - - public SerializedProperty targetDisplay { get; private set; } - - public SerializedProperty targetEye { get; private set; } - - private static readonly GUIContent[] kTargetEyes = - { - EditorGUIUtility.TrTextContent("Both"), - EditorGUIUtility.TrTextContent("Left"), - EditorGUIUtility.TrTextContent("Right"), - EditorGUIUtility.TrTextContent("None (Main Display)"), - }; - private static readonly int[] kTargetEyeValues = { (int)StereoTargetEyeMask.Both, (int)StereoTargetEyeMask.Left, (int)StereoTargetEyeMask.Right, (int)StereoTargetEyeMask.None }; - - public void OnEnable() - { - clearFlags = m_SerializedObject.FindProperty("m_ClearFlags"); - backgroundColor = m_SerializedObject.FindProperty("m_BackGroundColor"); - normalizedViewPortRect = m_SerializedObject.FindProperty("m_NormalizedViewPortRect"); - nearClippingPlane = m_SerializedObject.FindProperty("near clip plane"); - farClippingPlane = m_SerializedObject.FindProperty("far clip plane"); - fieldOfView = m_SerializedObject.FindProperty("field of view"); - orthographic = m_SerializedObject.FindProperty("orthographic"); - orthographicSize = m_SerializedObject.FindProperty("orthographic size"); - depth = m_SerializedObject.FindProperty("m_Depth"); - cullingMask = m_SerializedObject.FindProperty("m_CullingMask"); - renderingPath = m_SerializedObject.FindProperty("m_RenderingPath"); - occlusionCulling = m_SerializedObject.FindProperty("m_OcclusionCulling"); - targetTexture = m_SerializedObject.FindProperty("m_TargetTexture"); - HDR = m_SerializedObject.FindProperty("m_HDR"); - allowMSAA = m_SerializedObject.FindProperty("m_AllowMSAA"); - allowDynamicResolution = m_SerializedObject.FindProperty("m_AllowDynamicResolution"); - - stereoConvergence = m_SerializedObject.FindProperty("m_StereoConvergence"); - stereoSeparation = m_SerializedObject.FindProperty("m_StereoSeparation"); - - targetDisplay = m_SerializedObject.FindProperty("m_TargetDisplay"); - - targetEye = m_SerializedObject.FindProperty("m_TargetEye"); - } - - public void Update() - { - m_SerializedObject.Update(); - } - - public void ApplyModifiedProperties() - { - m_SerializedObject.ApplyModifiedProperties(); - } - - public void DrawClearFlags() - { - EditorGUILayout.PropertyField(clearFlags, EditorGUIUtility.TextContent("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.")); - } - - public void DrawBackgroundColor() - { - EditorGUILayout.PropertyField(backgroundColor, EditorGUIUtility.TextContent("Background|The Camera clears the screen to this color before rendering.")); - } - - public void DrawCullingMask() - { - EditorGUILayout.PropertyField(cullingMask); - } - - public void DrawProjection() - { - ProjectionType projectionType = orthographic.boolValue ? ProjectionType.Orthographic : ProjectionType.Perspective; - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = orthographic.hasMultipleDifferentValues; - projectionType = (ProjectionType)EditorGUILayout.EnumPopup(EditorGUIUtility.TextContent("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."), projectionType); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - orthographic.boolValue = (projectionType == ProjectionType.Orthographic); - - if (!orthographic.hasMultipleDifferentValues) - { - if (projectionType == ProjectionType.Orthographic) - EditorGUILayout.PropertyField(orthographicSize, new GUIContent("Size")); - else - EditorGUILayout.Slider(fieldOfView, 1f, 179f, EditorGUIUtility.TextContent("Field of View|The width of the Camera’s view angle, measured in degrees along the local Y axis.")); - } - } - - public void DrawClippingPlanes() - { - EditorGUILayout.PropertiesField(EditorGUI.s_ClipingPlanesLabel, new[] {nearClippingPlane, farClippingPlane}, EditorGUI.s_NearAndFarLabels, EditorGUI.kNearFarLabelsWidth); - } - - public void DrawNormalizedViewPort() - { - EditorGUILayout.PropertyField(normalizedViewPortRect, EditorGUIUtility.TextContent("Viewport Rect|Four values that indicate where on the screen this camera view will be drawn. Measured in Viewport Coordinates (values 0–1).")); - } - - public void DrawDepth() - { - EditorGUILayout.PropertyField(depth); - } - - public void DrawRenderingPath() - { - EditorGUILayout.IntPopup(renderingPath, kCameraRenderPaths, kCameraRenderPathValues, EditorGUIUtility.TempContent("Rendering Path")); - } - - public void DrawTargetTexture(bool deferred) - { - EditorGUILayout.PropertyField(targetTexture); - - // show warning if we have deferred but manual MSAA set - // only do this if the m_TargetTexture has the same values across all target cameras - if (!targetTexture.hasMultipleDifferentValues) - { - var targetTexture = this.targetTexture.objectReferenceValue as RenderTexture; - if (targetTexture - && targetTexture.antiAliasing > 1 - && deferred) - { - EditorGUILayout.HelpBox("Manual MSAA target set with deferred rendering. This will lead to undefined behavior.", MessageType.Warning, true); - } - } - } - - public void DrawOcclusionCulling() - { - EditorGUILayout.PropertyField(occlusionCulling); - } - - public void DrawHDR() - { - EditorGUILayout.PropertyField(HDR, EditorGUIUtility.TempContent("Allow HDR")); - } - - public void DrawMSAA() - { - EditorGUILayout.PropertyField(allowMSAA); - } - - public void DrawDynamicResolution() - { - EditorGUILayout.PropertyField(allowDynamicResolution); - } - - public void DrawVR() - { - if (PlayerSettings.virtualRealitySupported) - { - EditorGUILayout.PropertyField(stereoSeparation); - EditorGUILayout.PropertyField(stereoConvergence); - } - } - - public void DrawMultiDisplay() - { - if (ModuleManager.ShouldShowMultiDisplayOption()) - { - int prevDisplay = targetDisplay.intValue; - EditorGUILayout.Space(); - EditorGUILayout.IntPopup(targetDisplay, DisplayUtility.GetDisplayNames(), DisplayUtility.GetDisplayIndices(), EditorGUIUtility.TempContent("Target Display")); - if (prevDisplay != targetDisplay.intValue) - GameView.RepaintAll(); - } - } - - public void DrawTargetEye() - { - EditorGUILayout.IntPopup(targetEye, kTargetEyes, kTargetEyeValues, EditorGUIUtility.TempContent("Target Eye")); - } - } - - private class Styles - { - public static GUIContent iconRemove = EditorGUIUtility.IconContent("Toolbar Minus", "|Remove command buffer"); - public static GUIStyle invisibleButton = "InvisibleButton"; - } - - readonly AnimatedBool m_ShowBGColorOptions = new AnimatedBool(); - readonly AnimatedBool m_ShowOrthoOptions = new AnimatedBool(); - readonly AnimatedBool m_ShowTargetEyeOption = new AnimatedBool(); - - private Camera camera { get { return target as Camera; } } - - private static bool IsDeferredRenderingPath(RenderingPath rp) { return rp == RenderingPath.DeferredLighting || rp == RenderingPath.DeferredShading; } - - private bool wantDeferredRendering - { - get - { - bool isCamDeferred = IsDeferredRenderingPath(camera.renderingPath); - bool isTierDeferred = IsDeferredRenderingPath(Rendering.EditorGraphicsSettings.GetCurrentTierSettings().renderingPath); - return isCamDeferred || (camera.renderingPath == RenderingPath.UsePlayerSettings && isTierDeferred); - } - } - - enum ProjectionType { Perspective, Orthographic }; - - private Camera m_PreviewCamera; - protected Camera previewCamera - { - get - { - if (m_PreviewCamera == null) - m_PreviewCamera = EditorUtility.CreateGameObjectWithHideFlags("Preview Camera", HideFlags.HideAndDontSave, typeof(Camera), typeof(Skybox)).GetComponent(); - m_PreviewCamera.enabled = false; - return m_PreviewCamera; - } - } - - private RenderTexture m_PreviewTexture; - - // should match color in GizmosDrawers.cpp - private static readonly Color kGizmoCamera = new Color(233f / 255f, 233f / 255f, 233f / 255f, 128f / 255f); - - private const float kPreviewNormalizedSize = 0.2f; - - private bool m_CommandBuffersShown = true; - - private Settings m_Settings; - protected Settings settings - { - get - { - if (m_Settings == null) - m_Settings = new Settings(serializedObject); - return m_Settings; - } - } - - bool clearFlagsHasMultipleValues - { - get { return settings.clearFlags.hasMultipleDifferentValues; } - } - bool orthographicHasMultipleValues - { - get { return settings.orthographic.hasMultipleDifferentValues; } - } - - int targetEyeValue - { - get { return settings.targetEye.intValue; } - } - - - public void OnEnable() - { - settings.OnEnable(); - - var c = (Camera)target; - m_ShowBGColorOptions.value = !clearFlagsHasMultipleValues && (c.clearFlags == CameraClearFlags.SolidColor || c.clearFlags == CameraClearFlags.Skybox); - m_ShowOrthoOptions.value = c.orthographic; - m_ShowTargetEyeOption.value = targetEyeValue != (int)StereoTargetEyeMask.Both || PlayerSettings.virtualRealitySupported; - - m_ShowBGColorOptions.valueChanged.AddListener(Repaint); - m_ShowOrthoOptions.valueChanged.AddListener(Repaint); - m_ShowTargetEyeOption.valueChanged.AddListener(Repaint); - } - - internal void OnDisable() - { - m_ShowBGColorOptions.valueChanged.RemoveListener(Repaint); - m_ShowOrthoOptions.valueChanged.RemoveListener(Repaint); - m_ShowTargetEyeOption.valueChanged.RemoveListener(Repaint); - } - - public void OnDestroy() - { - if (m_PreviewCamera != null) - DestroyImmediate(m_PreviewCamera.gameObject, true); - } - - private void DepthTextureModeGUI() - { - // Camera's depth texture mode is not serialized data, so can't get to it through - // serialized property (hence no multi-edit). - if (targets.Length != 1) - return; - var cam = target as Camera; - if (cam == null || cam.depthTextureMode == DepthTextureMode.None) - return; - - List buffers = new List(); - if ((cam.depthTextureMode & DepthTextureMode.Depth) != 0) - buffers.Add("Depth"); - if ((cam.depthTextureMode & DepthTextureMode.DepthNormals) != 0) - buffers.Add("DepthNormals"); - if ((cam.depthTextureMode & DepthTextureMode.MotionVectors) != 0) - buffers.Add("MotionVectors"); - if (buffers.Count == 0) - return; - - StringBuilder sb = new StringBuilder("Info: renders "); - for (int i = 0; i < buffers.Count; ++i) - { - if (i != 0) - sb.Append(" & "); - - sb.Append(buffers[i]); - } - sb.Append(buffers.Count > 1 ? " textures" : " texture"); - EditorGUILayout.HelpBox(sb.ToString(), MessageType.None, true); - } - - static Rect GetRemoveButtonRect(Rect r) - { - var buttonSize = Styles.invisibleButton.CalcSize(Styles.iconRemove); - return new Rect(r.xMax - buttonSize.x, r.y + (int)(r.height / 2 - buttonSize.y / 2), buttonSize.x, buttonSize.y); - } - - /** - * Draws the 2D bounds of the camera when in 2D mode. - */ - [DrawGizmo(GizmoType.NonSelected)] - static void DrawCameraBound(Camera camera, GizmoType gizmoType) - { - var sv = SceneView.currentDrawingSceneView; - if (sv != null && sv.in2DMode) - { - if (camera == Camera.main && camera.orthographic) - CameraEditor.RenderGizmo(camera); - } - } - - private void CommandBufferGUI() - { - // Command buffers are not serialized data, so can't get to them through - // serialized property (hence no multi-edit). - if (targets.Length != 1) - return; - var cam = target as Camera; - if (cam == null) - return; - int count = cam.commandBufferCount; - if (count == 0) - return; - - m_CommandBuffersShown = GUILayout.Toggle(m_CommandBuffersShown, GUIContent.Temp(count + " command buffers"), EditorStyles.foldout); - if (!m_CommandBuffersShown) - return; - EditorGUI.indentLevel++; - foreach (CameraEvent ce in (CameraEvent[])System.Enum.GetValues(typeof(CameraEvent))) - { - CommandBuffer[] cbs = cam.GetCommandBuffers(ce); - foreach (CommandBuffer cb in cbs) - { - using (new GUILayout.HorizontalScope()) - { - // row with event & command buffer information label - Rect rowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.miniLabel); - rowRect.xMin += EditorGUI.indent; - Rect minusRect = GetRemoveButtonRect(rowRect); - rowRect.xMax = minusRect.x; - GUI.Label(rowRect, string.Format("{0}: {1} ({2})", ce, cb.name, EditorUtility.FormatBytes(cb.sizeInBytes)), EditorStyles.miniLabel); - // and a button to remove it - if (GUI.Button(minusRect, Styles.iconRemove, Styles.invisibleButton)) - { - cam.RemoveCommandBuffer(ce, cb); - SceneView.RepaintAll(); - GameView.RepaintAll(); - GUIUtility.ExitGUI(); - } - } - } - } - // "remove all" button - using (new GUILayout.HorizontalScope()) - { - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Remove all", EditorStyles.miniButton)) - { - cam.RemoveAllCommandBuffers(); - SceneView.RepaintAll(); - GameView.RepaintAll(); - } - } - EditorGUI.indentLevel--; - } - - public override void OnInspectorGUI() - { - settings.Update(); - - var c = (Camera)target; - m_ShowBGColorOptions.target = !clearFlagsHasMultipleValues && (c.clearFlags == CameraClearFlags.SolidColor || c.clearFlags == CameraClearFlags.Skybox); - m_ShowOrthoOptions.target = !orthographicHasMultipleValues && c.orthographic; - m_ShowTargetEyeOption.target = targetEyeValue != (int)StereoTargetEyeMask.Both || PlayerSettings.virtualRealitySupported; - - settings.DrawClearFlags(); - - if (EditorGUILayout.BeginFadeGroup(m_ShowBGColorOptions.faded)) - settings.DrawBackgroundColor(); - EditorGUILayout.EndFadeGroup(); - - settings.DrawCullingMask(); - - EditorGUILayout.Space(); - - settings.DrawProjection(); - - settings.DrawClippingPlanes(); - - settings.DrawNormalizedViewPort(); - - EditorGUILayout.Space(); - settings.DrawDepth(); - settings.DrawRenderingPath(); - if (m_ShowOrthoOptions.target && wantDeferredRendering) - EditorGUILayout.HelpBox("Deferred rendering does not work with Orthographic camera, will use Forward.", - MessageType.Warning, true); - - settings.DrawTargetTexture(wantDeferredRendering); - settings.DrawOcclusionCulling(); - settings.DrawHDR(); - settings.DrawMSAA(); - settings.DrawDynamicResolution(); - - DisplayCameraWarnings(); - - settings.DrawVR(); - settings.DrawMultiDisplay(); - - if (EditorGUILayout.BeginFadeGroup(m_ShowTargetEyeOption.faded)) - settings.DrawTargetEye(); - EditorGUILayout.EndFadeGroup(); - - DepthTextureModeGUI(); - CommandBufferGUI(); - - serializedObject.ApplyModifiedProperties(); - } - - private void DisplayCameraWarnings() - { - Camera camera = target as Camera; - if (camera != null) - { - string[] warnings = camera.GetCameraBufferWarnings(); - if (warnings.Length > 0) - EditorGUILayout.HelpBox(string.Join("\n\n", warnings), MessageType.Warning, true); - } - } - - public virtual void OnOverlayGUI(Object target, SceneView sceneView) - { - if (target == null) return; - - // cache some deep values - var c = (Camera)target; - - Vector2 previewSize = GameView.GetMainGameViewTargetSize(); - if (previewSize.x < 0f) - { - // Fallback to Scene View of not a valid game view size - previewSize.x = sceneView.position.width; - previewSize.y = sceneView.position.height; - } - // Apply normalizedviewport rect of camera - Rect normalizedViewPortRect = c.rect; - previewSize.x *= Mathf.Max(normalizedViewPortRect.width, 0f); - previewSize.y *= Mathf.Max(normalizedViewPortRect.height, 0f); - - // Prevent using invalid previewSize - if (previewSize.x <= 0f || previewSize.y <= 0f) - return; - - float aspect = previewSize.x / previewSize.y; - - // Scale down (fit to scene view) - previewSize.y = kPreviewNormalizedSize * sceneView.position.height; - previewSize.x = previewSize.y * aspect; - if (previewSize.y > sceneView.position.height * 0.5f) - { - previewSize.y = sceneView.position.height * 0.5f; - previewSize.x = previewSize.y * aspect; - } - if (previewSize.x > sceneView.position.width * 0.5f) - { - previewSize.x = sceneView.position.width * 0.5f; - previewSize.y = previewSize.x / aspect; - } - - // Get and reserve rect - Rect cameraRect = GUILayoutUtility.GetRect(previewSize.x, previewSize.y); - - if (Event.current.type == EventType.Repaint) - { - // setup camera and render - previewCamera.CopyFrom(c); - // also make sure to sync any Skybox component on the preview camera - var dstSkybox = previewCamera.GetComponent(); - if (dstSkybox) - { - var srcSkybox = c.GetComponent(); - if (srcSkybox && srcSkybox.enabled) - { - dstSkybox.enabled = true; - dstSkybox.material = srcSkybox.material; - } - else - { - dstSkybox.enabled = false; - } - } - - var previewTexture = GetPreviewTextureWithSize((int)cameraRect.width, (int)cameraRect.height); - previewTexture.antiAliasing = Mathf.Max(1, QualitySettings.antiAliasing); - previewCamera.targetTexture = previewTexture; - previewCamera.pixelRect = new Rect(0, 0, cameraRect.width, cameraRect.height); - - Handles.EmitGUIGeometryForCamera(c, previewCamera); - - GL.sRGBWrite = QualitySettings.activeColorSpace == ColorSpace.Linear; - previewCamera.Render(); - GL.sRGBWrite = false; - Graphics.DrawTexture(cameraRect, previewTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, EditorGUIUtility.GUITextureBlit2SRGBMaterial); - } - } - - private RenderTexture GetPreviewTextureWithSize(int width, int height) - { - if (m_PreviewTexture == null || m_PreviewTexture.width != width || m_PreviewTexture.height != height) - { - m_PreviewTexture = new RenderTexture(width, height, 24, RenderTextureFormat.Default, RenderTextureReadWrite.Linear); - } - return m_PreviewTexture; - } - - [RequiredByNativeCode] - static float GetGameViewAspectRatio() - { - Vector2 gameViewSize = GameView.GetMainGameViewTargetSize(); - if (gameViewSize.x < 0f) - { - // Fallback to Scene View of not a valid game view size - gameViewSize.x = Screen.width; - gameViewSize.y = Screen.height; - } - - return gameViewSize.x / gameViewSize.y; - } - - static float GetFrustumAspectRatio(Camera camera) - { - Rect normalizedViewPortRect = camera.rect; - if (normalizedViewPortRect.width <= 0f || normalizedViewPortRect.height <= 0f) - return -1f; - - float viewportAspect = normalizedViewPortRect.width / normalizedViewPortRect.height; - return GetGameViewAspectRatio() * viewportAspect; - } - - // Returns near- and far-corners in this order: leftBottom, leftTop, rightTop, rightBottom - // Assumes input arrays are of length 4 (if allocated) - static bool GetFrustum(Camera camera, Vector3[] near, Vector3[] far, out float frustumAspect) - { - frustumAspect = GetFrustumAspectRatio(camera); - if (frustumAspect < 0) - return false; - - if (far != null) - { - far[0] = new Vector3(0, 0, camera.farClipPlane); // leftBottomFar - far[1] = new Vector3(0, 1, camera.farClipPlane); // leftTopFar - far[2] = new Vector3(1, 1, camera.farClipPlane); // rightTopFar - far[3] = new Vector3(1, 0, camera.farClipPlane); // rightBottomFar - for (int i = 0; i < 4; ++i) - far[i] = camera.ViewportToWorldPoint(far[i]); - } - - if (near != null) - { - near[0] = new Vector3(0, 0, camera.nearClipPlane); // leftBottomNear - near[1] = new Vector3(0, 1, camera.nearClipPlane); // leftTopNear - near[2] = new Vector3(1, 1, camera.nearClipPlane); // rightTopNear - near[3] = new Vector3(1, 0, camera.nearClipPlane); // rightBottomNear - for (int i = 0; i < 4; ++i) - near[i] = camera.ViewportToWorldPoint(near[i]); - } - return true; - } - - // Called from C++ when we need to render a Camera's gizmo - internal static void RenderGizmo(Camera camera) - { - var near = new Vector3[4]; - var far = new Vector3[4]; - float frustumAspect; - if (GetFrustum(camera, near, far, out frustumAspect)) - { - Color orgColor = Handles.color; - Handles.color = kGizmoCamera; - for (int i = 0; i < 4; ++i) - { - Handles.DrawLine(near[i], near[(i + 1) % 4]); - Handles.DrawLine(far[i], far[(i + 1) % 4]); - Handles.DrawLine(near[i], far[i]); - } - Handles.color = orgColor; - } - } - - static bool IsViewPortRectValidToRender(Rect normalizedViewPortRect) - { - if (normalizedViewPortRect.width <= 0f || normalizedViewPortRect.height <= 0f) - return false; - if (normalizedViewPortRect.x >= 1f || normalizedViewPortRect.xMax <= 0f) - return false; - if (normalizedViewPortRect.y >= 1f || normalizedViewPortRect.yMax <= 0f) - return false; - return true; - } - - public virtual void OnSceneGUI() - { - var c = (Camera)target; - - if (!IsViewPortRectValidToRender(c.rect)) - return; - - SceneViewOverlay.Window(EditorGUIUtility.TrTextContent("Camera Preview"), OnOverlayGUI, (int)SceneViewOverlay.Ordering.Camera, target, SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget); - - Color orgHandlesColor = Handles.color; - Color slidersColor = kGizmoCamera; - slidersColor.a *= 2f; - Handles.color = slidersColor; - - // get the corners of the far clip plane in world space - var far = new Vector3[4]; - float frustumAspect; - if (!GetFrustum(c, null, far, out frustumAspect)) - return; - Vector3 leftBottomFar = far[0]; - Vector3 leftTopFar = far[1]; - Vector3 rightTopFar = far[2]; - Vector3 rightBottomFar = far[3]; - - // manage our own gui changed state, so we can use it for individual slider changes - bool guiChanged = GUI.changed; - - // FOV handles - Vector3 farMid = Vector3.Lerp(leftBottomFar, rightTopFar, 0.5f); - - // Top and bottom handles - float halfHeight = -1.0f; - Vector3 changedPosition = MidPointPositionSlider(leftTopFar, rightTopFar, c.transform.up); - if (!GUI.changed) - changedPosition = MidPointPositionSlider(leftBottomFar, rightBottomFar, -c.transform.up); - if (GUI.changed) - halfHeight = (changedPosition - farMid).magnitude; - - // Left and right handles - GUI.changed = false; - changedPosition = MidPointPositionSlider(rightBottomFar, rightTopFar, c.transform.right); - if (!GUI.changed) - changedPosition = MidPointPositionSlider(leftBottomFar, leftTopFar, -c.transform.right); - if (GUI.changed) - halfHeight = (changedPosition - farMid).magnitude / frustumAspect; - - // Update camera settings if changed - if (halfHeight >= 0.0f) - { - Undo.RecordObject(c, "Adjust Camera"); - if (c.orthographic) - { - c.orthographicSize = halfHeight; - } - else - { - Vector3 pos = farMid + c.transform.up * halfHeight; - c.fieldOfView = Vector3.Angle(c.transform.forward, (pos - c.transform.position)) * 2f; - } - guiChanged = true; - } - - GUI.changed = guiChanged; - Handles.color = orgHandlesColor; - } - - private static Vector3 MidPointPositionSlider(Vector3 position1, Vector3 position2, Vector3 direction) - { - Vector3 midPoint = Vector3.Lerp(position1, position2, 0.5f); - return Handles.Slider(midPoint, direction, HandleUtility.GetHandleSize(midPoint) * 0.03f, Handles.DotHandleCap, 0f); - } - } -} diff --git a/Editor/Mono/Inspector/CanvasEditor.cs b/Editor/Mono/Inspector/CanvasEditor.cs deleted file mode 100644 index bb3a80f462..0000000000 --- a/Editor/Mono/Inspector/CanvasEditor.cs +++ /dev/null @@ -1,267 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - /// - /// Editor class used to edit UI Canvases. - /// - - [CanEditMultipleObjects] - [CustomEditor(typeof(Canvas))] - internal class CanvasEditor : Editor - { - SerializedProperty m_RenderMode; - SerializedProperty m_Camera; - SerializedProperty m_PixelPerfect; - SerializedProperty m_PixelPerfectOverride; - SerializedProperty m_PlaneDistance; - SerializedProperty m_SortingLayerID; - SerializedProperty m_SortingOrder; - SerializedProperty m_TargetDisplay; - SerializedProperty m_OverrideSorting; - SerializedProperty m_ShaderChannels; - - AnimBool m_OverlayMode; - AnimBool m_CameraMode; - AnimBool m_WorldMode; - - AnimBool m_SortingOverride; - - private static class Styles - { - 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."); - public static GUIContent renderCamera = EditorGUIUtility.TrTextContent("Render Camera", "The Camera which will render the canvas. This is also the camera used to send events."); - public static GUIContent sortingOrder = EditorGUIUtility.TrTextContent("Sort Order", "The order in which Screen Space - Overlay canvas will render"); - public static string s_RootAndNestedMessage = "Cannot multi-edit root Canvas together with nested Canvas."; - public static GUIContent m_SortingLayerStyle = EditorGUIUtility.TrTextContent("Sorting Layer", "Name of the Renderer's sorting layer"); - public static GUIContent targetDisplay = EditorGUIUtility.TrTextContent("Target Display", "Display on which to render the canvas when in overlay mode"); - public static GUIContent m_SortingOrderStyle = EditorGUIUtility.TrTextContent("Order in Layer", "Renderer's order within a sorting layer"); - public static GUIContent m_ShaderChannel = EditorGUIUtility.TrTextContent("Additional Shader Channels"); - } - - private bool m_AllNested = false; - private bool m_AllRoot = false; - - private bool m_AllOverlay = false; - private bool m_NoneOverlay = false; - - private string[] shaderChannelOptions = { "TexCoord1", "TexCoord2", "TexCoord3", "Normal", "Tangent" }; - - - enum PixelPerfect - { - Inherit, - On, - Off - } - - private PixelPerfect pixelPerfect = PixelPerfect.Inherit; - - void OnEnable() - { - m_RenderMode = serializedObject.FindProperty("m_RenderMode"); - m_Camera = serializedObject.FindProperty("m_Camera"); - m_PixelPerfect = serializedObject.FindProperty("m_PixelPerfect"); - m_PlaneDistance = serializedObject.FindProperty("m_PlaneDistance"); - - m_SortingLayerID = serializedObject.FindProperty("m_SortingLayerID"); - m_SortingOrder = serializedObject.FindProperty("m_SortingOrder"); - m_TargetDisplay = serializedObject.FindProperty("m_TargetDisplay"); - m_OverrideSorting = serializedObject.FindProperty("m_OverrideSorting"); - m_PixelPerfectOverride = serializedObject.FindProperty("m_OverridePixelPerfect"); - m_ShaderChannels = serializedObject.FindProperty("m_AdditionalShaderChannelsFlag"); - - m_OverlayMode = new AnimBool(m_RenderMode.intValue == 0); - m_OverlayMode.valueChanged.AddListener(Repaint); - - m_CameraMode = new AnimBool(m_RenderMode.intValue == 1); - m_CameraMode.valueChanged.AddListener(Repaint); - - m_WorldMode = new AnimBool(m_RenderMode.intValue == 2); - m_WorldMode.valueChanged.AddListener(Repaint); - - m_SortingOverride = new AnimBool(m_OverrideSorting.boolValue); - m_SortingOverride.valueChanged.AddListener(Repaint); - - if (m_PixelPerfectOverride.boolValue) - pixelPerfect = m_PixelPerfect.boolValue ? PixelPerfect.On : PixelPerfect.Off; - else - pixelPerfect = PixelPerfect.Inherit; - - m_AllNested = true; - m_AllRoot = true; - m_AllOverlay = true; - m_NoneOverlay = true; - - for (int i = 0; i < targets.Length; i++) - { - Canvas canvas = targets[i] as Canvas; - - if (canvas.transform.parent == null || canvas.transform.parent.GetComponentInParent() == null) - m_AllNested = false; - else - m_AllRoot = false; - - if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) - m_NoneOverlay = false; - else - m_AllOverlay = false; - } - } - - void OnDisable() - { - m_OverlayMode.valueChanged.RemoveListener(Repaint); - m_CameraMode.valueChanged.RemoveListener(Repaint); - m_WorldMode.valueChanged.RemoveListener(Repaint); - m_SortingOverride.valueChanged.RemoveListener(Repaint); - } - - private void AllRootCanvases() - { - EditorGUILayout.PropertyField(m_RenderMode); - - m_OverlayMode.target = m_RenderMode.intValue == 0; - m_CameraMode.target = m_RenderMode.intValue == 1; - m_WorldMode.target = m_RenderMode.intValue == 2; - - EditorGUI.indentLevel++; - if (EditorGUILayout.BeginFadeGroup(m_OverlayMode.faded)) - { - EditorGUILayout.PropertyField(m_PixelPerfect); - EditorGUILayout.PropertyField(m_SortingOrder, Styles.sortingOrder); - GUIContent[] displayNames = DisplayUtility.GetDisplayNames(); - EditorGUILayout.IntPopup(m_TargetDisplay, displayNames, DisplayUtility.GetDisplayIndices(), Styles.targetDisplay); - } - EditorGUILayout.EndFadeGroup(); - - if (EditorGUILayout.BeginFadeGroup(m_CameraMode.faded)) - { - EditorGUILayout.PropertyField(m_PixelPerfect); - EditorGUILayout.PropertyField(m_Camera, Styles.renderCamera); - - if (m_Camera.objectReferenceValue != null) - EditorGUILayout.PropertyField(m_PlaneDistance); - - EditorGUILayout.Space(); - - if (m_Camera.objectReferenceValue != null) - EditorGUILayout.SortingLayerField(Styles.m_SortingLayerStyle, m_SortingLayerID, EditorStyles.popup, EditorStyles.label); - EditorGUILayout.PropertyField(m_SortingOrder, Styles.m_SortingOrderStyle); - - if (m_Camera.objectReferenceValue == null) - EditorGUILayout.HelpBox("Screen Space - A canvas with no specified camera acts like a Overlay Canvas." + - " Please assign a camera to it in the 'Render Camera' field.", MessageType.Warning); - } - EditorGUILayout.EndFadeGroup(); - - if (EditorGUILayout.BeginFadeGroup(m_WorldMode.faded)) - { - EditorGUILayout.PropertyField(m_Camera, Styles.eventCamera); - EditorGUILayout.Space(); - EditorGUILayout.SortingLayerField(Styles.m_SortingLayerStyle, m_SortingLayerID, EditorStyles.popup); - EditorGUILayout.PropertyField(m_SortingOrder, Styles.m_SortingOrderStyle); - } - EditorGUILayout.EndFadeGroup(); - EditorGUI.indentLevel--; - } - - private void AllNestedCanvases() - { - EditorGUI.BeginChangeCheck(); - pixelPerfect = (PixelPerfect)EditorGUILayout.EnumPopup("Pixel Perfect", pixelPerfect); - - if (EditorGUI.EndChangeCheck()) - { - if (pixelPerfect == PixelPerfect.Inherit) - { - m_PixelPerfectOverride.boolValue = false; - } - else if (pixelPerfect == PixelPerfect.Off) - { - m_PixelPerfectOverride.boolValue = true; - m_PixelPerfect.boolValue = false; - } - else - { - m_PixelPerfectOverride.boolValue = true; - m_PixelPerfect.boolValue = true; - } - } - - // we need to pass through the property setter to trigger a canvasHierarchyChanged event and so on - // see case 787195 - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_OverrideSorting); - if (EditorGUI.EndChangeCheck()) - { - ((Canvas)serializedObject.targetObject).overrideSorting = m_OverrideSorting.boolValue; - m_SortingOverride.target = m_OverrideSorting.boolValue; - } - - if (EditorGUILayout.BeginFadeGroup(m_SortingOverride.faded)) - { - GUIContent sortingOrderStyle = null; - if (m_AllOverlay) - { - sortingOrderStyle = Styles.sortingOrder; - } - else if (m_NoneOverlay) - { - sortingOrderStyle = Styles.m_SortingOrderStyle; - EditorGUILayout.SortingLayerField(Styles.m_SortingLayerStyle, m_SortingLayerID, EditorStyles.popup); - } - if (sortingOrderStyle != null) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_SortingOrder, sortingOrderStyle); - if (EditorGUI.EndChangeCheck()) - ((Canvas)serializedObject.targetObject).sortingOrder = m_SortingOrder.intValue; - } - } - EditorGUILayout.EndFadeGroup(); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - if (m_AllRoot || m_AllNested) - { - if (m_AllRoot) - { - AllRootCanvases(); - } - else if (m_AllNested) - { - AllNestedCanvases(); - } - - int newShaderChannelValue = 0; - EditorGUI.BeginChangeCheck(); - newShaderChannelValue = EditorGUILayout.MaskField(Styles.m_ShaderChannel, m_ShaderChannels.intValue, shaderChannelOptions); - - - if (EditorGUI.EndChangeCheck()) - m_ShaderChannels.intValue = newShaderChannelValue; - - if (m_RenderMode.intValue == 0) // Overlay canvas - { - if (((newShaderChannelValue & (int)AdditionalCanvasShaderChannels.Normal) | (newShaderChannelValue & (int)AdditionalCanvasShaderChannels.Tangent)) != 0) - EditorGUILayout.HelpBox("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.", MessageType.Warning); - } - } - else - { - GUILayout.Label(Styles.s_RootAndNestedMessage, EditorStyles.helpBox); - } - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/CapsuleCollider2DEditor.cs b/Editor/Mono/Inspector/CapsuleCollider2DEditor.cs deleted file mode 100644 index 574808d67d..0000000000 --- a/Editor/Mono/Inspector/CapsuleCollider2DEditor.cs +++ /dev/null @@ -1,111 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(CapsuleCollider2D))] - [CanEditMultipleObjects] - internal class CapsuleCollider2DEditor : PrimitiveCollider2DEditor - { - private SerializedProperty m_Size; - private SerializedProperty m_Direction; - private readonly CapsuleBoundsHandle m_BoundsHandle = new CapsuleBoundsHandle(); - - public override void OnEnable() - { - base.OnEnable(); - - m_Size = serializedObject.FindProperty("m_Size"); - m_Direction = serializedObject.FindProperty("m_Direction"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - InspectorEditButtonGUI(); - - base.OnInspectorGUI(); - - EditorGUILayout.PropertyField(m_Size); - EditorGUILayout.PropertyField(m_Direction); - - serializedObject.ApplyModifiedProperties(); - - FinalizeInspectorGUI(); - } - - protected override PrimitiveBoundsHandle boundsHandle { get { return m_BoundsHandle; } } - - protected override void CopyColliderSizeToHandle() - { - CapsuleCollider2D collider = (CapsuleCollider2D)target; - Vector3 handleHeightAxis, handleRadiusAxis; - GetHandleVectorsInWorldSpace(collider, out handleHeightAxis, out handleRadiusAxis); - m_BoundsHandle.height = m_BoundsHandle.radius = 0f; - m_BoundsHandle.height = handleHeightAxis.magnitude; - m_BoundsHandle.radius = handleRadiusAxis.magnitude * 0.5f; - } - - protected override bool CopyHandleSizeToCollider() - { - CapsuleCollider2D collider = (CapsuleCollider2D)target; - - // transform handle axes into world space - Vector3 localDiameterAxis, localHeightAxis; - if (collider.direction == CapsuleDirection2D.Horizontal) - { - localDiameterAxis = Vector3.up; - localHeightAxis = Vector3.right; - } - else - { - localDiameterAxis = Vector3.right; - localHeightAxis = Vector3.up; - } - Vector3 worldHeight = Handles.matrix * (localHeightAxis * m_BoundsHandle.height); - Vector3 worldDiameter = Handles.matrix * (localDiameterAxis * m_BoundsHandle.radius * 2f); - - // project collider's diameter and height axes onto world x/y plane and scale by handle values - Matrix4x4 colliderTransformMatrix = collider.transform.localToWorldMatrix; - Vector3 projectedDiameter = ProjectOntoWorldPlane(colliderTransformMatrix * localDiameterAxis).normalized * worldDiameter.magnitude; - Vector3 projectedHeight = ProjectOntoWorldPlane(colliderTransformMatrix * localHeightAxis).normalized * worldHeight.magnitude; - - // project results back in collider's local space - projectedDiameter = ProjectOntoColliderPlane(projectedDiameter, colliderTransformMatrix); - projectedHeight = ProjectOntoColliderPlane(projectedHeight, colliderTransformMatrix); - Vector2 oldSize = collider.size; - collider.size = colliderTransformMatrix.inverse * (projectedDiameter + projectedHeight); - - // test for size change after using property setter in case input data was sanitized - return collider.size != oldSize; - } - - protected override Quaternion GetHandleRotation() - { - Vector3 diameterVector, heightVector; - GetHandleVectorsInWorldSpace(target as CapsuleCollider2D, out heightVector, out diameterVector); - return Quaternion.LookRotation(Vector3.forward, heightVector); - } - - private void GetHandleVectorsInWorldSpace(CapsuleCollider2D collider, out Vector3 handleHeightVector, out Vector3 handleDiameterVector) - { - Matrix4x4 colliderTransformMatrix = collider.transform.localToWorldMatrix; - Vector3 x = ProjectOntoWorldPlane(colliderTransformMatrix * (Vector3.right * collider.size.x)); - Vector3 y = ProjectOntoWorldPlane(colliderTransformMatrix * (Vector3.up * collider.size.y)); - if (collider.direction == CapsuleDirection2D.Horizontal) - { - handleDiameterVector = y; - handleHeightVector = x; - } - else - { - handleDiameterVector = x; - handleHeightVector = y; - } - } - } -} diff --git a/Editor/Mono/Inspector/CapsuleColliderEditor.cs b/Editor/Mono/Inspector/CapsuleColliderEditor.cs deleted file mode 100644 index 2161128bd6..0000000000 --- a/Editor/Mono/Inspector/CapsuleColliderEditor.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(CapsuleCollider))] - [CanEditMultipleObjects] - internal class CapsuleColliderEditor : PrimitiveCollider3DEditor - { - SerializedProperty m_Center; - SerializedProperty m_Radius; - SerializedProperty m_Height; - SerializedProperty m_Direction; - - private readonly CapsuleBoundsHandle m_BoundsHandle = new CapsuleBoundsHandle(); - - public override void OnEnable() - { - base.OnEnable(); - - m_Center = serializedObject.FindProperty("m_Center"); - m_Radius = serializedObject.FindProperty("m_Radius"); - m_Height = serializedObject.FindProperty("m_Height"); - m_Direction = serializedObject.FindProperty("m_Direction"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - InspectorEditButtonGUI(); - EditorGUILayout.PropertyField(m_IsTrigger); - EditorGUILayout.PropertyField(m_Material); - EditorGUILayout.PropertyField(m_Center); - EditorGUILayout.PropertyField(m_Radius); - EditorGUILayout.PropertyField(m_Height); - EditorGUILayout.PropertyField(m_Direction); - - serializedObject.ApplyModifiedProperties(); - } - - protected override PrimitiveBoundsHandle boundsHandle { get { return m_BoundsHandle; } } - - protected override void CopyColliderPropertiesToHandle() - { - CapsuleCollider collider = (CapsuleCollider)target; - m_BoundsHandle.center = TransformColliderCenterToHandleSpace(collider.transform, collider.center); - float radiusScaleFactor; - Vector3 sizeScale = - GetCapsuleColliderHandleScale(collider.transform.lossyScale, collider.direction, out radiusScaleFactor); - m_BoundsHandle.height = m_BoundsHandle.radius = 0f; - m_BoundsHandle.height = collider.height * Mathf.Abs(sizeScale[collider.direction]); - m_BoundsHandle.radius = collider.radius * radiusScaleFactor; - switch (collider.direction) - { - case 0: - m_BoundsHandle.heightAxis = CapsuleBoundsHandle.HeightAxis.X; - break; - case 1: - m_BoundsHandle.heightAxis = CapsuleBoundsHandle.HeightAxis.Y; - break; - case 2: - m_BoundsHandle.heightAxis = CapsuleBoundsHandle.HeightAxis.Z; - break; - } - } - - protected override void CopyHandlePropertiesToCollider() - { - CapsuleCollider collider = (CapsuleCollider)target; - collider.center = TransformHandleCenterToColliderSpace(collider.transform, m_BoundsHandle.center); - float radiusScaleFactor; - Vector3 sizeScale = - GetCapsuleColliderHandleScale(collider.transform.lossyScale, collider.direction, out radiusScaleFactor); - sizeScale = InvertScaleVector(sizeScale); - // only apply changes to collider radius/height if scale factor from transform is non-zero - if (radiusScaleFactor != 0f) - collider.radius = m_BoundsHandle.radius / radiusScaleFactor; - if (sizeScale[collider.direction] != 0f) - collider.height = m_BoundsHandle.height * Mathf.Abs(sizeScale[collider.direction]); - } - - protected override void OnSceneGUI() - { - // prevent possibility that user increases height if radius scale is zero and user drags (non-moving) radius handles to exceed height extents - CapsuleCollider collider = (CapsuleCollider)target; - float radiusScaleFactor; - GetCapsuleColliderHandleScale(collider.transform.lossyScale, collider.direction, out radiusScaleFactor); - boundsHandle.axes = PrimitiveBoundsHandle.Axes.All; - if (radiusScaleFactor == 0f) - { - switch (collider.direction) - { - case 0: - boundsHandle.axes = PrimitiveBoundsHandle.Axes.X; - break; - case 1: - boundsHandle.axes = PrimitiveBoundsHandle.Axes.Y; - break; - case 2: - boundsHandle.axes = PrimitiveBoundsHandle.Axes.Z; - break; - } - } - - base.OnSceneGUI(); - } - - private Vector3 GetCapsuleColliderHandleScale(Vector3 lossyScale, int capsuleDirection, out float radiusScaleFactor) - { - radiusScaleFactor = 0f; - for (int axis = 0; axis < 3; ++axis) - { - if (axis != capsuleDirection) - radiusScaleFactor = Mathf.Max(radiusScaleFactor, Mathf.Abs(lossyScale[axis])); - } - for (int axis = 0; axis < 3; ++axis) - { - if (axis != capsuleDirection) - lossyScale[axis] = Mathf.Sign(lossyScale[axis]) * radiusScaleFactor; - } - return lossyScale; - } - } -} diff --git a/Editor/Mono/Inspector/CharacterControllerEditor.cs b/Editor/Mono/Inspector/CharacterControllerEditor.cs deleted file mode 100644 index a300b6ab98..0000000000 --- a/Editor/Mono/Inspector/CharacterControllerEditor.cs +++ /dev/null @@ -1,165 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(CharacterController))] - [CanEditMultipleObjects] - internal class CharacterControllerEditor : Editor - { - SerializedProperty m_Height; - SerializedProperty m_Radius; - SerializedProperty m_SlopeLimit; - SerializedProperty m_StepOffset; - SerializedProperty m_SkinWidth; - SerializedProperty m_MinMoveDistance; - SerializedProperty m_Center; - - private int m_HandleControlID; - - public void OnEnable() - { - m_Height = serializedObject.FindProperty("m_Height"); - m_Radius = serializedObject.FindProperty("m_Radius"); - m_SlopeLimit = serializedObject.FindProperty("m_SlopeLimit"); - m_StepOffset = serializedObject.FindProperty("m_StepOffset"); - m_SkinWidth = serializedObject.FindProperty("m_SkinWidth"); - m_MinMoveDistance = serializedObject.FindProperty("m_MinMoveDistance"); - m_Center = serializedObject.FindProperty("m_Center"); - - m_HandleControlID = -1; - } - - public void OnDisable() - { - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_SlopeLimit); - EditorGUILayout.PropertyField(m_StepOffset); - EditorGUILayout.PropertyField(m_SkinWidth); - EditorGUILayout.PropertyField(m_MinMoveDistance); - - EditorGUILayout.PropertyField(m_Center); - EditorGUILayout.PropertyField(m_Radius); - EditorGUILayout.PropertyField(m_Height); - - serializedObject.ApplyModifiedProperties(); - } - - public void OnSceneGUI() - { - bool dragging = GUIUtility.hotControl == m_HandleControlID; - - CharacterController cc = (CharacterController)target; - - // Use our own color for handles - Color tempColor = Handles.color; - if (cc.enabled) - Handles.color = Handles.s_ColliderHandleColor; - else - Handles.color = Handles.s_ColliderHandleColorDisabled; - - bool orgGuiEnabled = GUI.enabled; - if (!Event.current.shift && !dragging) - { - GUI.enabled = false; - Handles.color = new Color(1, 0, 0, .001f); - } - - float height = cc.height * cc.transform.lossyScale.y; - float radius = cc.radius * Mathf.Max(cc.transform.lossyScale.x, cc.transform.lossyScale.z); - height = Mathf.Max(height, radius * 2); - - Matrix4x4 matrix = Matrix4x4.TRS(cc.transform.TransformPoint(cc.center), Quaternion.identity, Vector3.one); - - int prevHotControl = GUIUtility.hotControl; - - // Height (two handles) - Vector3 halfHeight = Vector3.up * height * 0.5f; - float adjusted = SizeHandle(halfHeight, Vector3.up, matrix, true); - if (!GUI.changed) - adjusted = SizeHandle(-halfHeight, Vector3.down, matrix, true); - if (GUI.changed) - { - Undo.RecordObject(cc, "Character Controller Resize"); - float heightScale = height / cc.height; - cc.height += adjusted / heightScale; - } - - // Radius (four handles) - adjusted = SizeHandle(Vector3.left * radius, Vector3.left, matrix, true); - if (!GUI.changed) - adjusted = SizeHandle(-Vector3.left * radius, -Vector3.left, matrix, true); - if (!GUI.changed) - adjusted = SizeHandle(Vector3.forward * radius, Vector3.forward, matrix, true); - if (!GUI.changed) - adjusted = SizeHandle(-Vector3.forward * radius, -Vector3.forward, matrix, true); - if (GUI.changed) - { - Undo.RecordObject(cc, "Character Controller Resize"); - float radiusScale = radius / cc.radius; - cc.radius += adjusted / radiusScale; - } - - // Detect if any of our handles got hotcontrol - if (prevHotControl != GUIUtility.hotControl && GUIUtility.hotControl != 0) - m_HandleControlID = GUIUtility.hotControl; - - if (GUI.changed) - { - const float minValue = 0.00001f; - cc.radius = Mathf.Max(cc.radius, minValue); - cc.height = Mathf.Max(cc.height, minValue); - } - - // Reset original color - Handles.color = tempColor; - GUI.enabled = orgGuiEnabled; - } - - private static float SizeHandle(Vector3 localPos, Vector3 localPullDir, Matrix4x4 matrix, bool isEdgeHandle) - { - Vector3 worldDir = matrix.MultiplyVector(localPullDir); - Vector3 worldPos = matrix.MultiplyPoint(localPos); - - float handleSize = HandleUtility.GetHandleSize(worldPos); - bool orgGUIchanged = GUI.changed; - GUI.changed = false; - Color tempColor = Handles.color; - - // Adjust color of handle if in background - float displayThreshold = 0.0f; - if (isEdgeHandle) - displayThreshold = Mathf.Cos(Mathf.PI * 0.25f); - float cosV; - if (Camera.current.orthographic) - cosV = Vector3.Dot(-Camera.current.transform.forward, worldDir); - else - cosV = Vector3.Dot((Camera.current.transform.position - worldPos).normalized, worldDir); - if (cosV < -displayThreshold) - Handles.color = new Color(Handles.color.r, Handles.color.g, Handles.color.b, Handles.color.a * Handles.backfaceAlphaMultiplier); - - // Now do handle - Vector3 newWorldPos = Handles.Slider(worldPos, worldDir, handleSize * 0.03f, Handles.DotHandleCap, 0f); - float adjust = 0.0f; - if (GUI.changed) - { - // Project newWorldPos to worldDir (the sign of the return value indicates if we growing or shrinking) - adjust = HandleUtility.PointOnLineParameter(newWorldPos, worldPos, worldDir); - } - - // Reset states - GUI.changed |= orgGUIchanged; - Handles.color = tempColor; - - return adjust; - } - } -} diff --git a/Editor/Mono/Inspector/CharacterJointEditor.cs b/Editor/Mono/Inspector/CharacterJointEditor.cs deleted file mode 100644 index 739a17d697..0000000000 --- a/Editor/Mono/Inspector/CharacterJointEditor.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(CharacterJoint)), CanEditMultipleObjects] - class CharacterJointEditor : JointEditor - { - protected override void DoAngularLimitHandles(CharacterJoint joint) - { - base.DoAngularLimitHandles(joint); - - angularLimitHandle.xMotion = ConfigurableJointMotion.Limited; - angularLimitHandle.yMotion = ConfigurableJointMotion.Limited; - angularLimitHandle.zMotion = ConfigurableJointMotion.Limited; - - SoftJointLimit limit; - - limit = joint.lowTwistLimit; - angularLimitHandle.xMin = limit.limit; - - limit = joint.highTwistLimit; - angularLimitHandle.xMax = limit.limit; - - limit = joint.swing1Limit; - angularLimitHandle.yMax = limit.limit; - angularLimitHandle.yMin = -limit.limit; - - limit = joint.swing2Limit; - angularLimitHandle.zMax = limit.limit; - angularLimitHandle.zMin = -limit.limit; - - EditorGUI.BeginChangeCheck(); - - angularLimitHandle.radius = GetAngularLimitHandleSize(Vector3.zero); - angularLimitHandle.DrawHandle(); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(joint, Styles.editAngularLimitsUndoMessage); - - limit = joint.lowTwistLimit; - limit.limit = angularLimitHandle.xMin; - joint.lowTwistLimit = limit; - - limit = joint.highTwistLimit; - limit.limit = angularLimitHandle.xMax; - joint.highTwistLimit = limit; - - limit = joint.swing1Limit; - limit.limit = angularLimitHandle.yMax == limit.limit ? -angularLimitHandle.yMin : angularLimitHandle.yMax; - joint.swing1Limit = limit; - - limit = joint.swing2Limit; - limit.limit = angularLimitHandle.zMax == limit.limit ? -angularLimitHandle.zMin : angularLimitHandle.zMax; - joint.swing2Limit = limit; - } - } - } -} diff --git a/Editor/Mono/Inspector/CircleCollider2DEditor.cs b/Editor/Mono/Inspector/CircleCollider2DEditor.cs deleted file mode 100644 index fa374e02c7..0000000000 --- a/Editor/Mono/Inspector/CircleCollider2DEditor.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(CircleCollider2D))] - [CanEditMultipleObjects] - internal class CircleCollider2DEditor : PrimitiveCollider2DEditor - { - private SerializedProperty m_Radius; - private readonly SphereBoundsHandle m_BoundsHandle = new SphereBoundsHandle(); - - public override void OnEnable() - { - base.OnEnable(); - - m_Radius = serializedObject.FindProperty("m_Radius"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - InspectorEditButtonGUI(); - - base.OnInspectorGUI(); - - EditorGUILayout.PropertyField(m_Radius); - - serializedObject.ApplyModifiedProperties(); - - FinalizeInspectorGUI(); - } - - protected override PrimitiveBoundsHandle boundsHandle { get { return m_BoundsHandle; } } - - protected override void CopyColliderSizeToHandle() - { - CircleCollider2D collider = (CircleCollider2D)target; - m_BoundsHandle.radius = collider.radius * GetRadiusScaleFactor(); - } - - protected override bool CopyHandleSizeToCollider() - { - CircleCollider2D collider = (CircleCollider2D)target; - - float oldRadius = collider.radius; - float scaleFactor = GetRadiusScaleFactor(); - collider.radius = - Mathf.Approximately(scaleFactor, 0f) ? 0f : m_BoundsHandle.radius / GetRadiusScaleFactor(); - - // test for size change after using property setter in case input data was sanitized - return collider.radius != oldRadius; - } - - private float GetRadiusScaleFactor() - { - Vector3 lossyScale = ((Component)target).transform.lossyScale; - return Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y)); - } - } -} diff --git a/Editor/Mono/Inspector/ClothInspector.cs b/Editor/Mono/Inspector/ClothInspector.cs deleted file mode 100644 index de2cb08024..0000000000 --- a/Editor/Mono/Inspector/ClothInspector.cs +++ /dev/null @@ -1,1719 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEditorInternal; -using UnityEditor.IMGUI.Controls; - -using UnityObject = UnityEngine.Object; - - -namespace UnityEditor -{ - class ClothInspectorState : ScriptableSingleton - { - [SerializeField] public ClothInspector.DrawMode DrawMode = ClothInspector.DrawMode.MaxDistance; - [SerializeField] public bool ManipulateBackfaces = false; - [SerializeField] public bool PaintMaxDistanceEnabled = true; - [SerializeField] public bool PaintCollisionSphereDistanceEnabled = false; - [SerializeField] public float PaintMaxDistance = 0.2f; - [SerializeField] public float PaintCollisionSphereDistance = 0.0f; - [SerializeField] public ClothInspector.ToolMode ToolMode = ClothInspector.ToolMode.Paint; - [SerializeField] public ClothInspector.CollToolMode CollToolMode = ClothInspector.CollToolMode.Select; - [SerializeField] public float BrushRadius = 0.075f; - [SerializeField] public bool SetSelfAndInterCollision = false; - [SerializeField] public ClothInspector.CollisionVisualizationMode VisualizeSelfOrInterCollision = ClothInspector.CollisionVisualizationMode.SelfCollision; - [SerializeField] public float SelfCollisionDistance = 0.1f; - [SerializeField] public float SelfCollisionStiffness = 0.2f; - [SerializeField] public float InterCollisionDistance = 0.1f; - [SerializeField] public float InterCollisionStiffness = 0.2f; - [SerializeField] public float ConstraintSize = 0.05f; - } - - [CustomEditor(typeof(Cloth))] - [CanEditMultipleObjects] - class ClothInspector : Editor - { - public enum DrawMode { MaxDistance = 1, CollisionSphereDistance }; - public enum ToolMode { Select, Paint }; - public enum CollToolMode { Select, Paint, Erase }; - enum RectSelectionMode { Replace, Add, Substract }; - public enum CollisionVisualizationMode { SelfCollision, InterCollision }; - - bool[] m_ParticleSelection; - bool[] m_ParticleRectSelection; - bool[] m_SelfAndInterCollisionSelection; - - Vector3[] m_ClothParticlesInWorldSpace; - - Vector3 m_BrushPos; - Vector3 m_BrushNorm; - int m_BrushFace = -1; - - int m_MouseOver = -1; - Vector3[] m_LastVertices; - Vector2 m_SelectStartPoint; - Vector2 m_SelectMousePoint; - bool m_RectSelecting = false; - bool m_DidSelect = false; - float[] m_MaxVisualizedValue = new float[3]; - float[] m_MinVisualizedValue = new float[3]; - RectSelectionMode m_RectSelectionMode = RectSelectionMode.Add; - int m_NumVerts = 0; - - const float kDisabledValue = float.MaxValue; - - static Texture2D s_ColorTexture = null; - static bool s_BrushCreated = false; - - public static PrefColor s_BrushColor = new PrefColor("Cloth/Brush Color 2", 0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, 51.0f / 255.0f); - public static PrefColor s_SelfAndInterCollisionParticleColor = new PrefColor("Cloth/Self or Inter Collision Particle Color 2", 145.0f / 255.0f, 244.0f / 255.0f, 139.0f / 255.0f, 0.5f); - public static PrefColor s_UnselectedSelfAndInterCollisionParticleColor = new PrefColor("Cloth/Unselected Self or Inter Collision Particle Color 2", 0.1f, 0.1f, 0.1f, 0.5f); - public static PrefColor s_SelectedParticleColor = new PrefColor("Cloth/Selected Self or Inter Collision Particle Color 2", 64.0f / 255.0f, 160.0f / 255.0f, 255.0f / 255.0f, 0.5f); - - public static ToolMode[] s_ToolMode = - { - ToolMode.Paint, - ToolMode.Select - }; - - SerializedProperty m_SelfCollisionDistance; - SerializedProperty m_SelfCollisionStiffness; - - int m_NumSelection = 0; - - SkinnedMeshRenderer m_SkinnedMeshRenderer; - - private static class Styles - { - public static readonly GUIContent editConstraintsLabel = EditorGUIUtility.TrTextContent("Edit Constraints"); - public static readonly GUIContent editSelfInterCollisionLabel = EditorGUIUtility.TrTextContent("Edit Collision Particles"); - public static readonly GUIContent selfInterCollisionParticleColor = EditorGUIUtility.TrTextContent("Visualization Color"); - public static readonly GUIContent selfInterCollisionBrushColor = EditorGUIUtility.TrTextContent("Brush Color"); - public static readonly GUIContent clothSelfCollisionAndInterCollision = EditorGUIUtility.TrTextContent("Cloth Self-Collision And Inter-Collision"); - public static readonly GUIContent paintCollisionParticles = EditorGUIUtility.TrTextContent("Paint Collision Particles"); - public static readonly GUIContent selectCollisionParticles = EditorGUIUtility.TrTextContent("Select Collision Particles"); - public static readonly GUIContent brushRadiusString = EditorGUIUtility.TrTextContent("Brush Radius"); - public static readonly GUIContent selfAndInterCollisionMode = EditorGUIUtility.TrTextContent("Paint or Select Particles"); - public static readonly GUIContent backFaceManipulationMode = EditorGUIUtility.TrTextContent("Back Face Manipulation"); - public static readonly GUIContent manipulateBackFaceString = EditorGUIUtility.TrTextContent("Manipulate Backfaces"); - public static readonly GUIContent selfCollisionString = EditorGUIUtility.TrTextContent("Self Collision"); - public static readonly GUIContent setSelfAndInterCollisionString = EditorGUIUtility.TrTextContent("Self-Collision and Inter-Collision"); - - public static readonly int clothEditorWindowWidth = 300; - - public static GUIContent[] toolContents = - { - EditorGUIUtility.IconContent("EditCollider"), - EditorGUIUtility.IconContent("EditCollider") - }; - - public static GUIContent[] toolIcons = - { - EditorGUIUtility.TrTextContent("Select"), - EditorGUIUtility.TrTextContent("Paint") - }; - - public static GUIContent[] drawModeStrings = - { - EditorGUIUtility.TrTextContent("Fixed"), - EditorGUIUtility.TrTextContent("Max Distance"), - EditorGUIUtility.TrTextContent("Surface Penetration") - }; - - public static GUIContent[] toolModeStrings = - { - EditorGUIUtility.TrTextContent("Select"), - EditorGUIUtility.TrTextContent("Paint"), - EditorGUIUtility.TrTextContent("Erase") - }; - - public static GUIContent[] collToolModeIcons = - { - EditorGUIUtility.TrTextContent("Select"), - EditorGUIUtility.TrTextContent("Paint"), - EditorGUIUtility.TrTextContent("Erase") - }; - - public static GUIContent[] collVisModeStrings = - { - EditorGUIUtility.TrTextContent("Self Collision"), - EditorGUIUtility.TrTextContent("Inter Collision"), - }; - - public static GUIContent paintIcon = EditorGUIUtility.TrIconContent("ClothInspector.PaintValue", "Change this vertex coefficient value by painting in the scene view."); - - public static EditMode.SceneViewEditMode[] sceneViewEditModes = new[] - { - EditMode.SceneViewEditMode.ClothConstraints, - EditMode.SceneViewEditMode.ClothSelfAndInterCollisionParticles - }; - - public static GUIContent selfCollisionDistanceGUIContent = EditorGUIUtility.TrTextContent("Self Collision Distance"); - public static GUIContent selfCollisionStiffnessGUIContent = EditorGUIUtility.TrTextContent("Self Collision Stiffness"); - - static Styles() - { - toolContents[0].tooltip = EditorGUIUtility.TrTextContent("Edit cloth constraints").text; - toolContents[1].tooltip = EditorGUIUtility.TrTextContent("Edit cloth self or inter collision").text; - - toolIcons[0].tooltip = EditorGUIUtility.TrTextContent("Select cloth particles for use in self or inter collision").text; - toolIcons[1].tooltip = EditorGUIUtility.TrTextContent("Paint cloth particles for use in self or inter collision").text; - - collToolModeIcons[0].tooltip = EditorGUIUtility.TrTextContent("Select cloth particles.").text; - collToolModeIcons[1].tooltip = EditorGUIUtility.TrTextContent("Paint cloth particles.").text; - collToolModeIcons[2].tooltip = EditorGUIUtility.TrTextContent("Erase cloth particles.").text; - } - } - - ClothInspectorState state - { - get - { - return ClothInspectorState.instance; - } - } - - DrawMode drawMode - { - get - { - return state.DrawMode; - } - set - { - if (state.DrawMode != value) - { - state.DrawMode = value; - Repaint(); - } - } - } - - Cloth cloth - { - get - { - return (Cloth)target; - } - } - - public bool editingConstraints - { - get { return EditMode.editMode == EditMode.SceneViewEditMode.ClothConstraints && EditMode.IsOwner(this); } - } - - public bool editingSelfAndInterCollisionParticles - { - get { return EditMode.editMode == EditMode.SceneViewEditMode.ClothSelfAndInterCollisionParticles && EditMode.IsOwner(this); } - } - - GUIContent GetDrawModeString(DrawMode mode) - { - return Styles.drawModeStrings[(int)mode]; - } - - GUIContent GetCollVisModeString(CollisionVisualizationMode mode) - { - return Styles.collVisModeStrings[(int)mode]; - } - - bool IsMeshValid() - { - if (cloth.vertices.Length != m_NumVerts) - { - InitInspector(); - return true; - } - else if (m_NumVerts == 0) - { - return false; - } - - return true; - } - - Texture2D GenerateColorTexture(int width) - { - var tex = new Texture2D(width, 1, TextureFormat.RGBA32, false); - tex.hideFlags = HideFlags.HideAndDontSave; - tex.wrapMode = TextureWrapMode.Clamp; - tex.hideFlags = HideFlags.DontSave; - - Color[] colors = new Color[width]; - for (int i = 0; i < width; i++) - colors[i] = GetGradientColor(i / (float)(width - 1)); - tex.SetPixels(colors); - tex.Apply(); - return tex; - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - // Multi-editing in scene not supported - if (targets.Length <= 1) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - EditMode.DoInspectorToolbar(Styles.sceneViewEditModes, Styles.toolContents, this); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - } - - if (editingSelfAndInterCollisionParticles) - { - if ((state.SetSelfAndInterCollision) || ((state.CollToolMode == CollToolMode.Paint) || (state.CollToolMode == CollToolMode.Erase))) - { - if (cloth.selfCollisionDistance >= 0.0f) - { - state.SelfCollisionDistance = cloth.selfCollisionDistance; - m_SelfCollisionDistance.floatValue = cloth.selfCollisionDistance; - } - else - { - cloth.selfCollisionDistance = state.SelfCollisionDistance; - m_SelfCollisionDistance.floatValue = state.SelfCollisionDistance; - } - - if (cloth.selfCollisionStiffness >= 0.0f) - { - state.SelfCollisionStiffness = cloth.selfCollisionStiffness; - m_SelfCollisionStiffness.floatValue = cloth.selfCollisionStiffness; - } - else - { - cloth.selfCollisionStiffness = state.SelfCollisionStiffness; - m_SelfCollisionStiffness.floatValue = cloth.selfCollisionStiffness; - } - - Rect rect = GUILayoutUtility.GetRect(new GUIContent(), GUIStyle.none, GUILayout.ExpandWidth(true), GUILayout.Height(17)); - EditorGUI.LabelField(rect, Styles.selfCollisionString, EditorStyles.boldLabel); - Rect rectDist = GUILayoutUtility.GetRect(new GUIContent(), GUIStyle.none, GUILayout.ExpandWidth(true), GUILayout.Height(17)); - EditorGUI.PropertyField(rectDist, m_SelfCollisionDistance, Styles.selfCollisionDistanceGUIContent); - Rect rectStiff = GUILayoutUtility.GetRect(new GUIContent(), GUIStyle.none, GUILayout.ExpandWidth(true), GUILayout.Height(17)); - EditorGUI.PropertyField(rectStiff, m_SelfCollisionStiffness, Styles.selfCollisionStiffnessGUIContent); - GUILayout.Space(10); - } - - if (Physics.interCollisionDistance >= 0.0f) - { - state.InterCollisionDistance = Physics.interCollisionDistance; - } - else - { - Physics.interCollisionDistance = state.InterCollisionDistance; - } - - if (Physics.interCollisionStiffness >= 0.0f) - { - state.InterCollisionStiffness = Physics.interCollisionStiffness; - } - else - { - Physics.interCollisionStiffness = state.InterCollisionStiffness; - } - } - - DrawPropertiesExcluding(serializedObject, "m_SelfAndInterCollisionIndices", "m_VirtualParticleIndices", "m_SelfCollisionDistance", "m_SelfCollisionStiffness"); - - serializedObject.ApplyModifiedProperties(); - - MeshRenderer meshRenderer = cloth.GetComponent(); - if (meshRenderer != null) - Debug.LogWarning("MeshRenderer will not work with a cloth component! Use only SkinnedMeshRenderer. Any MeshRenderer's attached to a cloth component will be deleted at runtime."); - } - - public bool Raycast(out Vector3 pos, out Vector3 norm, out int face) - { - Ray mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); - - GameObject go = cloth.gameObject; - MeshCollider meshCollider = go.GetComponent(); - - RaycastHit hit; - if (meshCollider.Raycast(mouseRay, out hit, Mathf.Infinity)) - { - norm = hit.normal; - pos = hit.point; - face = hit.triangleIndex; - return true; - } - - norm = Vector2.zero; - pos = Vector3.zero; - face = -1; - return false; - } - - void UpdatePreviewBrush() - { - Raycast(out m_BrushPos, out m_BrushNorm, out m_BrushFace); - } - - void DrawBrush() - { - if (m_BrushFace >= 0) - { - Handles.color = s_BrushColor; - Handles.DrawSolidDisc(m_BrushPos, m_BrushNorm, state.BrushRadius); - } - } - - internal override Bounds GetWorldBoundsOfTarget(UnityObject targetObject) - { - Cloth cloth = (Cloth)targetObject; - var skin = cloth.GetComponent(); - return skin == null ? base.GetWorldBoundsOfTarget(targetObject) : skin.bounds; - } - - bool SelectionMeshDirty() - { - if (m_LastVertices != null) - { - Vector3[] vertices = cloth.vertices; - Transform t = m_SkinnedMeshRenderer.actualRootBone; - if (m_LastVertices.Length != vertices.Length) - return true; - for (int i = 0; i < m_LastVertices.Length; i++) - { - var v = t.rotation * vertices[i] + t.position; - // we use !(==) here instead of !=, since Vector3 != is incorrectly written to return false if one component is NaN. - if (!(m_LastVertices[i] == v)) - return true; - } - } - - return false; - } - - void GenerateSelectionMesh() - { - if (!IsMeshValid()) - { - return; - } - - Vector3[] vertices = cloth.vertices; - int length = vertices.Length; - m_ParticleSelection = new bool[length]; - m_ParticleRectSelection = new bool[length]; - - m_LastVertices = new Vector3[length]; - Transform t = m_SkinnedMeshRenderer.actualRootBone; - for (int i = 0; i < length; i++) - { - m_LastVertices[i] = t.rotation * vertices[i] + t.position; - } - } - - void InitSelfAndInterCollisionSelection() - { - int length = cloth.vertices.Length; - m_SelfAndInterCollisionSelection = new bool[length]; - for (int i = 0; i < length; i++) - { - m_SelfAndInterCollisionSelection[i] = false; - } - - List selfAndInterCollisionIndices = new List(length); - selfAndInterCollisionIndices.Clear(); - - cloth.GetSelfAndInterCollisionIndices(selfAndInterCollisionIndices); - - length = selfAndInterCollisionIndices.Count; - for (int i = 0; i < length; i++) - { - m_SelfAndInterCollisionSelection[selfAndInterCollisionIndices[i]] = true; - } - } - - void InitClothParticlesInWorldSpace() - { - Vector3[] vertices = cloth.vertices; - int length = vertices.Length; - m_ClothParticlesInWorldSpace = new Vector3[length]; - - Transform t = m_SkinnedMeshRenderer.actualRootBone; - Quaternion rotation = t.rotation; - Vector3 position = t.position; - for (int i = 0; i < length; i++) - { - m_ClothParticlesInWorldSpace[i] = rotation * vertices[i] + position; - } - } - - void DrawSelfAndInterCollisionParticles() - { - Transform t = m_SkinnedMeshRenderer.actualRootBone; - Vector3[] vertices = cloth.vertices; - - int id = GUIUtility.GetControlID(FocusType.Passive); - float size = state.SelfCollisionDistance; - if (state.VisualizeSelfOrInterCollision == CollisionVisualizationMode.SelfCollision) - { - size = state.SelfCollisionDistance; - } - else if (state.VisualizeSelfOrInterCollision == CollisionVisualizationMode.InterCollision) - { - size = state.InterCollisionDistance; - } - - int length = m_SelfAndInterCollisionSelection.Length; - for (int i = 0; i < length; i++) - { - Vector3 distanceBetween = m_ClothParticlesInWorldSpace[i] - m_BrushPos; - bool forwardFacing = Vector3.Dot(t.rotation * cloth.normals[i], Camera.current.transform.forward) <= 0; - if (forwardFacing || state.ManipulateBackfaces) - { - if ((m_SelfAndInterCollisionSelection[i] == true) && !(m_ParticleSelection[i] == true)) - { - Handles.color = s_SelfAndInterCollisionParticleColor; - } - else if (!(m_SelfAndInterCollisionSelection[i] == true) && !(m_ParticleSelection[i] == true)) - { - Handles.color = s_UnselectedSelfAndInterCollisionParticleColor; - } - - if ((m_ParticleSelection[i] == true) && (m_NumSelection > 0) && (state.CollToolMode == CollToolMode.Select)) - { - Handles.color = s_SelectedParticleColor; - } - - if ((distanceBetween.magnitude < state.BrushRadius) && forwardFacing && ((state.CollToolMode == CollToolMode.Paint) || (state.CollToolMode == CollToolMode.Erase))) - { - if (m_BrushFace > -1) // check mouse pointer is over a valid mesh face - { - Handles.color = s_SelectedParticleColor; - } - } - - Handles.SphereHandleCap(id, m_ClothParticlesInWorldSpace[i], t.rotation, size, EventType.Repaint); - } - } - } - - void InitInspector() - { - InitBrushCollider(); - InitSelfAndInterCollisionSelection(); - InitClothParticlesInWorldSpace(); - - m_NumVerts = cloth.vertices.Length; - } - - void OnEnable() - { - if (s_ColorTexture == null) - s_ColorTexture = GenerateColorTexture(100); - - m_SkinnedMeshRenderer = cloth.GetComponent(); - - InitInspector(); - - GenerateSelectionMesh(); - - m_SelfCollisionDistance = serializedObject.FindProperty("m_SelfCollisionDistance"); - m_SelfCollisionStiffness = serializedObject.FindProperty("m_SelfCollisionStiffness"); - - SceneView.onPreSceneGUIDelegate += OnPreSceneGUICallback; - } - - void InitBrushCollider() - { - if (cloth != null) - { - GameObject go = cloth.gameObject; - MeshCollider oldMeshCollider = go.GetComponent(); - if (oldMeshCollider != null) - { - if (((oldMeshCollider.hideFlags & HideFlags.HideInHierarchy) != 0) || ((oldMeshCollider.hideFlags & HideFlags.HideInInspector) != 0)) - { - DestroyImmediate(oldMeshCollider, true); - } - } - - MeshCollider meshCollider = go.AddComponent(); - meshCollider.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector | - HideFlags.DontSaveInEditor | HideFlags.NotEditable; - - meshCollider.sharedMesh = m_SkinnedMeshRenderer.sharedMesh; - - s_BrushCreated = true; - } - } - - public void OnDestroy() - { - SceneView.onPreSceneGUIDelegate -= OnPreSceneGUICallback; - - if (s_BrushCreated == true) - { - if (cloth != null) - { - GameObject go = cloth.gameObject; - MeshCollider meshCollider = go.GetComponent(); - if (meshCollider != null) - { - if (((meshCollider.hideFlags & HideFlags.HideInHierarchy) != 0) || ((meshCollider.hideFlags & HideFlags.HideInInspector) != 0)) - { - DestroyImmediate(meshCollider, true); - } - } - s_BrushCreated = false; - } - } - } - - float GetCoefficient(ClothSkinningCoefficient coefficient) - { - switch (drawMode) - { - case DrawMode.MaxDistance: - return coefficient.maxDistance; - case DrawMode.CollisionSphereDistance: - return coefficient.collisionSphereDistance; - } - return 0; - } - - Color GetGradientColor(float val) - { - if (val < 0.3f) - return Color.Lerp(Color.red, Color.magenta, val / 0.2f); - else if (val < 0.7f) - return Color.Lerp(Color.magenta, Color.yellow, (val - 0.2f) / 0.5f); - else - return Color.Lerp(Color.yellow, Color.green, (val - 0.7f) / 0.3f); - } - - void OnDisable() - { - SceneView.onPreSceneGUIDelegate -= OnPreSceneGUICallback; - } - - float CoefficientField(float value, float useValue, bool enabled, DrawMode mode) - { - var label = GetDrawModeString(mode); - - using (new EditorGUI.DisabledScope(!enabled)) - { - GUILayout.BeginHorizontal(); - EditorGUI.showMixedValue = useValue < 0; - EditorGUI.BeginChangeCheck(); - useValue = EditorGUILayout.Toggle(GUIContent.none, useValue != 0) ? 1 : 0; - if (EditorGUI.EndChangeCheck()) - { - if (useValue > 0) - value = 0; - else - value = kDisabledValue; - drawMode = mode; - } - GUILayout.Space(-152); - EditorGUI.showMixedValue = false; - - using (new EditorGUI.DisabledScope(useValue != 1)) - { - float fieldValue = value; - EditorGUI.showMixedValue = value < 0; - EditorGUI.BeginChangeCheck(); - - int oldHotControl = GUIUtility.keyboardControl; - if (useValue > 0) - fieldValue = EditorGUILayout.FloatField(label, value); - else - EditorGUILayout.FloatField(label, 0); - - bool changed = EditorGUI.EndChangeCheck(); - if (changed) - { - value = fieldValue; - if (value < 0) - value = 0; - } - - if (changed || oldHotControl != GUIUtility.keyboardControl) - // if we got focus or changed values, set draw mode. - drawMode = mode; - } - } - - if (useValue > 0) - { - float min = m_MinVisualizedValue[(int)mode]; - float max = m_MaxVisualizedValue[(int)mode]; - if (max - min > 0) - DrawColorBox(null, GetGradientColor((value - min) / (max - min))); - else - DrawColorBox(null, GetGradientColor(value <= min ? 0 : 1)); - } - else - DrawColorBox(null, Color.black); - - EditorGUI.showMixedValue = false; - GUILayout.EndHorizontal(); - return value; - } - - float PaintField(float value, ref bool enabled, DrawMode mode) - { - var label = GetDrawModeString(mode); - GUILayout.BeginHorizontal(); - enabled = GUILayout.Toggle(enabled, Styles.paintIcon, "MiniButton", GUILayout.ExpandWidth(false)); - bool useValue; - float retVal; - using (new EditorGUI.DisabledScope(!enabled)) - { - EditorGUI.BeginChangeCheck(); - useValue = EditorGUILayout.Toggle(GUIContent.none, value < kDisabledValue); - if (EditorGUI.EndChangeCheck()) - { - if (useValue) - value = 0; - else - value = kDisabledValue; - drawMode = mode; - } - GUILayout.Space(-162); - - using (new EditorGUI.DisabledScope(!useValue)) - { - retVal = value; - int oldHotControl = GUIUtility.keyboardControl; - EditorGUI.BeginChangeCheck(); - if (useValue) - retVal = EditorGUILayout.FloatField(label, value); - else - EditorGUILayout.FloatField(label, 0); - - if (retVal < 0) - retVal = 0; - - if (EditorGUI.EndChangeCheck() || oldHotControl != GUIUtility.keyboardControl) - // if we got focus or changed values, set draw mode. - drawMode = mode; - } - } - - if (useValue) - { - float min = m_MinVisualizedValue[(int)mode]; - float max = m_MaxVisualizedValue[(int)mode]; - if (max - min > 0) - DrawColorBox(null, GetGradientColor((value - min) / (max - min))); - else - DrawColorBox(null, GetGradientColor(value <= min ? 0 : 1)); - } - else - DrawColorBox(null, Color.black); - - - GUILayout.EndHorizontal(); - return retVal; - } - - void SelectionGUI() - { - ClothSkinningCoefficient[] coefficients = cloth.coefficients; - - float maxDistance = 0; - float useMaxDistance = 0; - float collisionSphereDistance = 0; - float useCollisionSphereDistance = 0; - int numSelection = 0; - bool firstVertex = true; - - for (int i = 0; i < m_ParticleSelection.Length; i++) - { - if (m_ParticleSelection[i]) - { - if (firstVertex) - { - maxDistance = coefficients[i].maxDistance; - useMaxDistance = (maxDistance < kDisabledValue) ? 1 : 0; - collisionSphereDistance = coefficients[i].collisionSphereDistance; - useCollisionSphereDistance = (collisionSphereDistance < kDisabledValue) ? 1 : 0; - firstVertex = false; - } - if (coefficients[i].maxDistance != maxDistance) - maxDistance = -1; - if (coefficients[i].collisionSphereDistance != collisionSphereDistance) - collisionSphereDistance = -1; - if (useMaxDistance != ((coefficients[i].maxDistance < kDisabledValue) ? 1 : 0)) - useMaxDistance = -1; - if (useCollisionSphereDistance != ((coefficients[i].collisionSphereDistance < kDisabledValue) ? 1 : 0)) - useCollisionSphereDistance = -1; - numSelection++; - } - } - - float maxDistanceNew = CoefficientField(maxDistance, useMaxDistance, numSelection > 0, DrawMode.MaxDistance); - if (maxDistanceNew != maxDistance) - { - for (int i = 0; i < coefficients.Length; i++) - { - if (m_ParticleSelection[i]) - coefficients[i].maxDistance = maxDistanceNew; - } - cloth.coefficients = coefficients; - Undo.RegisterCompleteObjectUndo(target, "Change Cloth Coefficients"); - } - - float collisionSphereDistanceNew = CoefficientField(collisionSphereDistance, useCollisionSphereDistance, numSelection > 0, DrawMode.CollisionSphereDistance); - if (collisionSphereDistanceNew != collisionSphereDistance) - { - for (int i = 0; i < coefficients.Length; i++) - { - if (m_ParticleSelection[i]) - coefficients[i].collisionSphereDistance = collisionSphereDistanceNew; - } - cloth.coefficients = coefficients; - Undo.RegisterCompleteObjectUndo(target, "Change Cloth Coefficients"); - } - - using (new EditorGUI.DisabledScope(true)) - { - GUILayout.BeginHorizontal(); - if (numSelection > 0) - { - GUILayout.FlexibleSpace(); - GUILayout.Label(numSelection + " selected"); - } - else - { - GUILayout.Label("Select cloth vertices to edit their constraints."); - GUILayout.FlexibleSpace(); - } - GUILayout.EndHorizontal(); - } - - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Backspace) - { - for (int i = 0; i < coefficients.Length; i++) - { - if (m_ParticleSelection[i]) - { - switch (drawMode) - { - case DrawMode.MaxDistance: - coefficients[i].maxDistance = kDisabledValue; - break; - case DrawMode.CollisionSphereDistance: - coefficients[i].collisionSphereDistance = kDisabledValue; - break; - } - } - } - cloth.coefficients = coefficients; - } - } - - void CollSelectionGUI() - { - if (!IsMeshValid()) - { - return; - } - - bool firstFound = false; - bool mixedValue = false; - int numSelection = 0; - int lengthSelection = m_ParticleRectSelection.Length; - for (int i = 0; i < lengthSelection; i++) - { - if (m_ParticleRectSelection[i]) - { - if (firstFound == false) - { - state.SetSelfAndInterCollision = m_SelfAndInterCollisionSelection[i]; - firstFound = true; - } - else - { - if (state.SetSelfAndInterCollision != m_SelfAndInterCollisionSelection[i]) - { - mixedValue = true; - state.SetSelfAndInterCollision = false; - } - } - numSelection++; - } - } - - m_NumSelection = numSelection; - if (m_NumSelection == 0) - { - state.SetSelfAndInterCollision = false; - } - - using (new EditorGUI.DisabledScope(m_NumSelection == 0)) - { - EditorGUILayout.BeginHorizontal(); - EditorGUI.showMixedValue = mixedValue; - EditorGUI.BeginChangeCheck(); - bool setSelfAndInterCollision = EditorGUILayout.Toggle(GUIContent.none, state.SetSelfAndInterCollision); - if (EditorGUI.EndChangeCheck()) - { - state.SetSelfAndInterCollision = setSelfAndInterCollision; - for (int i = 0; i < lengthSelection; i++) - { - if (m_ParticleRectSelection[i]) - { - m_SelfAndInterCollisionSelection[i] = state.SetSelfAndInterCollision; - } - } - - Undo.RegisterCompleteObjectUndo(target, "Change Cloth Particles Selected for self or inter collision"); - } - - EditorGUILayout.LabelField(Styles.setSelfAndInterCollisionString); - EditorGUI.showMixedValue = false; - EditorGUILayout.EndHorizontal(); - } - } - - void EditBrushSize() - { - EditorGUI.BeginChangeCheck(); - float fieldValue = EditorGUILayout.FloatField(Styles.brushRadiusString, state.BrushRadius); - bool changed = EditorGUI.EndChangeCheck(); - if (changed) - { - state.BrushRadius = fieldValue; - if (state.BrushRadius < 0.0f) - state.BrushRadius = 0.0f; - } - } - - void PaintGUI() - { - state.PaintMaxDistance = PaintField(state.PaintMaxDistance, ref state.PaintMaxDistanceEnabled, DrawMode.MaxDistance); - - state.PaintCollisionSphereDistance = PaintField(state.PaintCollisionSphereDistance, ref state.PaintCollisionSphereDistanceEnabled, DrawMode.CollisionSphereDistance); - - // Automatically switch visualization mode if we are only painting a coefficient we are not visualizing - if (state.PaintMaxDistanceEnabled && !state.PaintCollisionSphereDistanceEnabled) - drawMode = DrawMode.MaxDistance; - else if (!state.PaintMaxDistanceEnabled && state.PaintCollisionSphereDistanceEnabled) - drawMode = DrawMode.CollisionSphereDistance; - - using (new EditorGUI.DisabledScope(true)) - { - GUILayout.BeginHorizontal(); - GUILayout.Label("Set constraints to paint onto cloth vertices."); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - } - - EditBrushSize(); - } - - int GetMouseVertex(Event e) - { - // No cloth manipulation Tool enabled -> don't interact with vertices. - if (Tools.current != Tool.None) - return -1; - - if (m_LastVertices == null) - { - return -1; - } - - Vector3[] normals = cloth.normals; - ClothSkinningCoefficient[] coefficients = cloth.coefficients; - Ray mouseRay = HandleUtility.GUIPointToWorldRay(e.mousePosition); - float minDistance = 1000; - int found = -1; - Quaternion rotation = m_SkinnedMeshRenderer.actualRootBone.rotation; - for (int i = 0; i < coefficients.Length; i++) - { - Vector3 dir = m_LastVertices[i] - mouseRay.origin; - float sqrDistance = Vector3.Cross(dir, mouseRay.direction).sqrMagnitude; - bool forwardFacing = Vector3.Dot(rotation * normals[i], Camera.current.transform.forward) <= 0; - if ((forwardFacing || state.ManipulateBackfaces) && sqrDistance < minDistance && sqrDistance < 0.05f * 0.05f) - { - minDistance = sqrDistance; - found = i; - } - } - return found; - } - - void DrawConstraints() - { - if (SelectionMeshDirty()) - GenerateSelectionMesh(); - - Transform t = m_SkinnedMeshRenderer.actualRootBone; - int id = GUIUtility.GetControlID(FocusType.Passive); - ClothSkinningCoefficient[] coefficients = cloth.coefficients; - int length = coefficients.Length; - float min = 0; - float max = 0; - for (int i = 0; i < length; i++) - { - float value = GetCoefficient(coefficients[i]); - if (value >= kDisabledValue) - continue; - if (value < min) - min = value; - if (value > max) - max = value; - } - - m_MaxVisualizedValue[(int)drawMode] = max; - m_MinVisualizedValue[(int)drawMode] = min; - - Vector3[] normals = cloth.normals; - for (int i = 0; i < length; i++) - { - bool forwardFacing = Vector3.Dot(t.rotation * normals[i], Camera.current.transform.forward) <= 0; - if (forwardFacing || state.ManipulateBackfaces) - { - float val = GetCoefficient(coefficients[i]); - Color color; - if (val >= kDisabledValue) - color = Color.black; - else - { - if (max - min != 0) - val = (val - min) / (max - min); - else - val = 0.0f; - color = GetGradientColor(val); - } - - Handles.color = color; - - Vector3 distanceBetween = m_ClothParticlesInWorldSpace[i] - m_BrushPos; - if ((m_ParticleSelection[i] == true) && (state.CollToolMode == CollToolMode.Select)) - { - Handles.color = s_SelectedParticleColor; - } - - if ((distanceBetween.magnitude < state.BrushRadius) && forwardFacing && (state.ToolMode == ToolMode.Paint)) - { - if (m_BrushFace > -1) // check mouse pointer is over a valid mesh face - { - Handles.color = s_SelectedParticleColor; - } - } - - Handles.SphereHandleCap(id, m_ClothParticlesInWorldSpace[i], t.rotation, state.ConstraintSize, EventType.Repaint); - } - } - } - - bool UpdateRectParticleSelection() - { - if (!IsMeshValid()) - { - return false; - } - - bool selectionChanged = false; - - Vector3[] normals = cloth.normals; - ClothSkinningCoefficient[] coefficients = cloth.coefficients; - - float minX = Mathf.Min(m_SelectStartPoint.x, m_SelectMousePoint.x); - float maxX = Mathf.Max(m_SelectStartPoint.x, m_SelectMousePoint.x); - float minY = Mathf.Min(m_SelectStartPoint.y, m_SelectMousePoint.y); - float maxY = Mathf.Max(m_SelectStartPoint.y, m_SelectMousePoint.y); - Ray topLeft = HandleUtility.GUIPointToWorldRay(new Vector2(minX, minY)); - Ray topRight = HandleUtility.GUIPointToWorldRay(new Vector2(maxX, minY)); - Ray botLeft = HandleUtility.GUIPointToWorldRay(new Vector2(minX, maxY)); - Ray botRight = HandleUtility.GUIPointToWorldRay(new Vector2(maxX, maxY)); - - Plane top = new Plane(topRight.origin + topRight.direction, topLeft.origin + topLeft.direction, topLeft.origin); - Plane bottom = new Plane(botLeft.origin + botLeft.direction, botRight.origin + botRight.direction, botRight.origin); - Plane left = new Plane(topLeft.origin + topLeft.direction, botLeft.origin + botLeft.direction, botLeft.origin); - Plane right = new Plane(botRight.origin + botRight.direction, topRight.origin + topRight.direction, topRight.origin); - - Quaternion rotation = m_SkinnedMeshRenderer.actualRootBone.rotation; - - int length = coefficients.Length; - for (int i = 0; i < length; i++) - { - Vector3 v = m_LastVertices[i]; - bool forwardFacing = Vector3.Dot(rotation * normals[i], Camera.current.transform.forward) <= 0; - bool selected = top.GetSide(v) && bottom.GetSide(v) && left.GetSide(v) && right.GetSide(v); - selected = selected && (state.ManipulateBackfaces || forwardFacing); - if (m_ParticleRectSelection[i] != selected) - { - m_ParticleRectSelection[i] = selected; - selectionChanged = true; - } - } - return selectionChanged; - } - - void ApplyRectSelection() - { - if (!IsMeshValid()) - { - return; - } - - int length = cloth.coefficients.Length; - for (int i = 0; i < length; i++) - { - switch (m_RectSelectionMode) - { - case RectSelectionMode.Replace: - m_ParticleSelection[i] = m_ParticleRectSelection[i]; - break; - - case RectSelectionMode.Add: - m_ParticleSelection[i] |= m_ParticleRectSelection[i]; - break; - - case RectSelectionMode.Substract: - m_ParticleSelection[i] = m_ParticleSelection[i] && !m_ParticleRectSelection[i]; - break; - } - } - } - - bool RectSelectionModeFromEvent() - { - Event e = Event.current; - RectSelectionMode mode = RectSelectionMode.Replace; - if (e.shift) - mode = RectSelectionMode.Add; - if (e.alt) - mode = RectSelectionMode.Substract; - if (m_RectSelectionMode != mode) - { - m_RectSelectionMode = mode; - return true; - } - return false; - } - - internal void SendCommandsOnModifierKeys() - { - SceneView.lastActiveSceneView.SendEvent(EditorGUIUtility.CommandEvent(EventCommandNames.ModifierKeysChanged)); - } - - void SelectionPreSceneGUI(int id) - { - Event e = Event.current; - switch (e.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (e.alt || e.control || e.command || e.button != 0) - break; - GUIUtility.hotControl = id; - int found = GetMouseVertex(e); - if (found != -1) - { - if (e.shift) - m_ParticleSelection[found] = !m_ParticleSelection[found]; - else - { - for (int i = 0; i < m_ParticleSelection.Length; i++) - m_ParticleSelection[i] = false; - m_ParticleSelection[found] = true; - } - m_DidSelect = true; - Repaint(); - } - else - m_DidSelect = false; - - m_SelectStartPoint = e.mousePosition; - e.Use(); - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - if (!m_RectSelecting && (e.mousePosition - m_SelectStartPoint).magnitude > 2f) - { - if (!(e.alt || e.control || e.command)) - { - EditorApplication.modifierKeysChanged += SendCommandsOnModifierKeys; - m_RectSelecting = true; - RectSelectionModeFromEvent(); - } - } - if (m_RectSelecting) - { - m_SelectMousePoint = new Vector2(Mathf.Max(e.mousePosition.x, 0), Mathf.Max(e.mousePosition.y, 0)); - RectSelectionModeFromEvent(); - UpdateRectParticleSelection(); - e.Use(); - } - } - break; - - case EventType.ExecuteCommand: - if (m_RectSelecting && e.commandName == EventCommandNames.ModifierKeysChanged) - { - RectSelectionModeFromEvent(); - UpdateRectParticleSelection(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == id && e.button == 0) - { - GUIUtility.hotControl = 0; - - if (m_RectSelecting) - { - EditorApplication.modifierKeysChanged -= SendCommandsOnModifierKeys; - m_RectSelecting = false; - RectSelectionModeFromEvent(); - ApplyRectSelection(); - } - else if (!m_DidSelect) - { - if (!(e.alt || e.control || e.command)) - { - // If nothing was clicked, deselect all - ClothSkinningCoefficient[] coefficients = cloth.coefficients; - for (int i = 0; i < coefficients.Length; i++) - m_ParticleSelection[i] = false; - } - } - // Disable text focus when selection changes, otherwise we cannot update inspector fields - // if text is currently selected. - GUIUtility.keyboardControl = 0; - SceneView.RepaintAll(); - } - break; - } - } - - void GetBrushedConstraints(Event e) - { - if (!IsMeshValid()) - { - return; - } - - Vector3[] vertices = cloth.vertices; - Vector3[] normals = cloth.normals; - ClothSkinningCoefficient[] coefficients = cloth.coefficients; - Quaternion rotation = m_SkinnedMeshRenderer.actualRootBone.rotation; - int length = vertices.Length; - for (int i = 0; i < length; i++) - { - Vector3 distanceBetween = m_ClothParticlesInWorldSpace[i] - m_BrushPos; - bool forwardFacing = Vector3.Dot(rotation * normals[i], Camera.current.transform.forward) <= 0; - if ((distanceBetween.magnitude < state.BrushRadius) && (forwardFacing || state.ManipulateBackfaces)) - { - bool changed = false; - if (state.PaintMaxDistanceEnabled && coefficients[i].maxDistance != state.PaintMaxDistance) - { - coefficients[i].maxDistance = state.PaintMaxDistance; - changed = true; - } - if (state.PaintCollisionSphereDistanceEnabled && coefficients[i].collisionSphereDistance != state.PaintCollisionSphereDistance) - { - coefficients[i].collisionSphereDistance = state.PaintCollisionSphereDistance; - changed = true; - } - if (changed) - { - Undo.RegisterCompleteObjectUndo(target, "Paint Cloth Constraints"); - cloth.coefficients = coefficients; - Repaint(); - } - } - } - } - - void GetBrushedParticles(Event e) - { - if (!IsMeshValid()) - { - return; - } - - Vector3[] vertices = cloth.vertices; - Vector3[] normals = cloth.normals; - Quaternion rotation = m_SkinnedMeshRenderer.actualRootBone.rotation; - int length = vertices.Length; - for (int i = 0; i < length; i++) - { - Vector3 distanceBetween = m_ClothParticlesInWorldSpace[i] - m_BrushPos; - bool forwardFacing = Vector3.Dot(rotation * normals[i], Camera.current.transform.forward) <= 0; - if ((distanceBetween.magnitude < state.BrushRadius) && (forwardFacing || state.ManipulateBackfaces)) - { - if (e.button == 0) - { - if (state.CollToolMode == CollToolMode.Paint) - { - m_SelfAndInterCollisionSelection[i] = true; - } - else if (state.CollToolMode == CollToolMode.Erase) - { - m_SelfAndInterCollisionSelection[i] = false; - } - } - - int id = GUIUtility.GetControlID(FocusType.Passive); - float size = cloth.selfCollisionDistance; - if (state.VisualizeSelfOrInterCollision == CollisionVisualizationMode.SelfCollision) - { - size = cloth.selfCollisionDistance; - } - else if (state.VisualizeSelfOrInterCollision == CollisionVisualizationMode.InterCollision) - { - size = Physics.interCollisionDistance; - } - - Handles.color = s_SelectedParticleColor; - Handles.SphereHandleCap(id, m_ClothParticlesInWorldSpace[i], rotation, size, EventType.Repaint); - Repaint(); - } - } - - Undo.RegisterCompleteObjectUndo(target, "Paint Collision"); - } - - void PaintPreSceneGUI(int id) - { - if (!IsMeshValid()) - { - return; - } - - Event e = Event.current; - EventType type = e.GetTypeForControl(id); - if (type == EventType.MouseDown || type == EventType.MouseDrag) - { - ClothSkinningCoefficient[] coefficients = cloth.coefficients; - if (GUIUtility.hotControl != id && (e.alt || e.control || e.command || e.button != 0)) - return; - if (type == EventType.MouseDown) - GUIUtility.hotControl = id; - - if (editingSelfAndInterCollisionParticles) - { - GetBrushedParticles(e); - } - - if (editingConstraints) - { - GetBrushedConstraints(e); - } - e.Use(); - } - else if (type == EventType.MouseUp) - { - if (GUIUtility.hotControl == id && e.button == 0) - { - GUIUtility.hotControl = 0; - e.Use(); - } - } - } - - private void OnPreSceneGUICallback(SceneView sceneView) - { - // Multi-editing in scene not supported - if (targets.Length > 1) - return; - - if (editingConstraints || editingSelfAndInterCollisionParticles) - { - OnPreSceneGUI(); - } - } - - void OnPreSceneGUI() - { - if (!IsMeshValid()) - { - return; - } - - // Disable Scene view tools, so we can use our own. - Tools.current = Tool.None; - if (state.ToolMode == (ToolMode)(-1)) - state.ToolMode = ToolMode.Select; - - if (m_ParticleSelection == null) - { - GenerateSelectionMesh(); - } - else - { - ClothSkinningCoefficient[] coefficients = cloth.coefficients; - if (m_ParticleSelection.Length != coefficients.Length) - InitInspector(); - } - - Handles.BeginGUI(); - int id = GUIUtility.GetControlID(FocusType.Passive); - - Event e = Event.current; - switch (e.GetTypeForControl(id)) - { - case EventType.Layout: - HandleUtility.AddDefaultControl(id); - break; - - case EventType.MouseMove: - case EventType.MouseDrag: - int oldMouseOver = m_MouseOver; - m_MouseOver = GetMouseVertex(e); - if (m_MouseOver != oldMouseOver) - SceneView.RepaintAll(); - break; - } - - if (editingConstraints) - { - switch (state.ToolMode) - { - case ToolMode.Select: - SelectionPreSceneGUI(id); - break; - - case ToolMode.Paint: - PaintPreSceneGUI(id); - break; - } - } - - if (editingSelfAndInterCollisionParticles) - { - switch (state.CollToolMode) - { - case CollToolMode.Select: - SelectionPreSceneGUI(id); - break; - - case CollToolMode.Paint: - case CollToolMode.Erase: - PaintPreSceneGUI(id); - break; - } - } - - Handles.EndGUI(); - } - - public void OnSceneGUI() - { - if (editingConstraints) - { - OnSceneEditConstraintsGUI(); - return; - } - - if (editingSelfAndInterCollisionParticles) - { - OnSceneEditSelfAndInterCollisionParticlesGUI(); - return; - } - } - - void OnSceneEditConstraintsGUI() - { - if ((Event.current.type == EventType.Repaint) && (state.ToolMode == ToolMode.Paint)) - { - UpdatePreviewBrush(); - DrawBrush(); - } - - // Multi-editing in scene not supported - if (Selection.gameObjects.Length > 1) - return; - - if (Event.current.type == EventType.Repaint) - DrawConstraints(); - - var evt = Event.current; - if (evt.commandName == EventCommandNames.SelectAll) - { - if (evt.type == EventType.ValidateCommand) - evt.Use(); - - if (evt.type == EventType.ExecuteCommand) - { - int numVertices = cloth.vertices.Length; - for (int i = 0; i < numVertices; i++) - m_ParticleSelection[i] = true; - SceneView.RepaintAll(); - state.ToolMode = ToolMode.Select; - evt.Use(); - } - } - - Handles.BeginGUI(); - if (m_RectSelecting && state.ToolMode == ToolMode.Select && Event.current.type == EventType.Repaint) - EditorStyles.selectionRect.Draw(EditorGUIExt.FromToRect(m_SelectStartPoint, m_SelectMousePoint), GUIContent.none, false, false, false, false); - Handles.EndGUI(); - - SceneViewOverlay.Window(EditorGUIUtility.TrTextContent("Cloth Constraints"), ConstraintEditing, (int)SceneViewOverlay.Ordering.ClothConstraints, SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget); - } - - void OnSceneEditSelfAndInterCollisionParticlesGUI() - { - // Multi-editing in scene not supported - if (Selection.gameObjects.Length > 1) - return; - - DrawSelfAndInterCollisionParticles(); - - if ((Event.current.type == EventType.Repaint) && ((state.CollToolMode == CollToolMode.Paint) || ((state.CollToolMode == CollToolMode.Erase)))) - { - UpdatePreviewBrush(); - DrawBrush(); - } - - Handles.BeginGUI(); - if (m_RectSelecting && state.CollToolMode == CollToolMode.Select && Event.current.type == EventType.Repaint) - EditorStyles.selectionRect.Draw(EditorGUIExt.FromToRect(m_SelectStartPoint, m_SelectMousePoint), GUIContent.none, false, false, false, false); - Handles.EndGUI(); - - SceneViewOverlay.Window(Styles.clothSelfCollisionAndInterCollision, SelfAndInterCollisionEditing, (int)SceneViewOverlay.Ordering.ClothSelfAndInterCollision, SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget); - } - - public void VisualizationMenuSetMaxDistanceMode() - { - drawMode = DrawMode.MaxDistance; - if (!state.PaintMaxDistanceEnabled) - { - state.PaintCollisionSphereDistanceEnabled = false; - state.PaintMaxDistanceEnabled = true; - } - } - - public void VisualizationMenuSetCollisionSphereMode() - { - drawMode = DrawMode.CollisionSphereDistance; - if (!state.PaintCollisionSphereDistanceEnabled) - { - state.PaintCollisionSphereDistanceEnabled = true; - state.PaintMaxDistanceEnabled = false; - } - } - - public void VisualizationMenuToggleManipulateBackfaces() - { - state.ManipulateBackfaces = !state.ManipulateBackfaces; - } - - public void VisualizationMenuSelfCollision() - { - state.VisualizeSelfOrInterCollision = CollisionVisualizationMode.SelfCollision; - } - - public void VisualizationMenuInterCollision() - { - state.VisualizeSelfOrInterCollision = CollisionVisualizationMode.InterCollision; - } - - public void DrawColorBox(Texture gradientTex, Color col) - { - if (!GUI.enabled) - { - col = new Color(0.3f, 0.3f, 0.3f, 1.0f); - EditorGUI.showMixedValue = false; - } - GUILayout.BeginVertical(); - GUILayout.Space(5); - Rect r = GUILayoutUtility.GetRect(new GUIContent(), GUIStyle.none, GUILayout.ExpandWidth(true), GUILayout.Height(10)); - GUI.Box(r, GUIContent.none); - r = new Rect(r.x + 1, r.y + 1, r.width - 2, r.height - 2); - if (gradientTex) - GUI.DrawTexture(r, gradientTex); - else - EditorGUIUtility.DrawColorSwatch(r, col, false); - GUILayout.EndVertical(); - } - - bool IsConstrained() - { - ClothSkinningCoefficient[] coefficients = cloth.coefficients; - foreach (var c in coefficients) - { - if (c.maxDistance < kDisabledValue) - return true; - if (c.collisionSphereDistance < kDisabledValue) - return true; - } - return false; - } - - void ConstraintEditing(UnityObject unused, SceneView sceneView) - { - GUILayout.BeginVertical(GUILayout.Width(Styles.clothEditorWindowWidth)); - GUILayout.BeginHorizontal(); - GUILayout.Label("Visualization ", GUILayout.ExpandWidth(false)); - GUILayout.BeginVertical(); - if (EditorGUILayout.DropdownButton(GetDrawModeString(drawMode), FocusType.Passive, EditorStyles.toolbarDropDown)) - { - Rect buttonRect = GUILayoutUtility.topLevel.GetLast(); - GenericMenu menu = new GenericMenu(); - menu.AddItem(GetDrawModeString(DrawMode.MaxDistance), drawMode == DrawMode.MaxDistance , VisualizationMenuSetMaxDistanceMode); - menu.AddItem(GetDrawModeString(DrawMode.CollisionSphereDistance), drawMode == DrawMode.CollisionSphereDistance , VisualizationMenuSetCollisionSphereMode); - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Manipulate Backfaces"), state.ManipulateBackfaces , VisualizationMenuToggleManipulateBackfaces); - menu.DropDown(buttonRect); - } - - GUILayout.BeginHorizontal(); - GUILayout.Label(m_MinVisualizedValue[(int)drawMode].ToString(), GUILayout.ExpandWidth(false)); - DrawColorBox(s_ColorTexture, Color.clear); - GUILayout.Label(m_MaxVisualizedValue[(int)drawMode].ToString(), GUILayout.ExpandWidth(false)); - - GUILayout.Label("Unconstrained "); - GUILayout.Space(-24); - GUILayout.BeginHorizontal(GUILayout.Width(20)); - DrawColorBox(null, Color.black); - GUILayout.EndHorizontal(); - - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - - if (Tools.current != Tool.None) - state.ToolMode = (ToolMode)(-1); - - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - state.ToolMode = (ToolMode)GUILayout.Toolbar((int)state.ToolMode, Styles.toolIcons); - using (var check = new EditorGUI.ChangeCheckScope()) - { - if (check.changed) - { - // delselect text, so we don't end up having a text field highlighted in the new tab - GUIUtility.keyboardControl = 0; - SceneView.RepaintAll(); - } - } - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - - switch (state.ToolMode) - { - case ToolMode.Select: - Tools.current = Tool.None; - SelectionGUI(); - break; - - case ToolMode.Paint: - Tools.current = Tool.None; - PaintGUI(); - break; - } - - if (!IsConstrained()) - EditorGUILayout.HelpBox("No constraints have been set up, so the cloth will move freely. Set up vertex constraints here to restrict it.", MessageType.Info); - - GUILayout.EndVertical(); - } - - void SelectManipulateBackFaces() - { - GUILayout.BeginHorizontal(); - EditorGUI.BeginChangeCheck(); - bool manipulateBackfaces = EditorGUILayout.Toggle(GUIContent.none, state.ManipulateBackfaces); - if (EditorGUI.EndChangeCheck()) - { - state.ManipulateBackfaces = manipulateBackfaces; - } - EditorGUILayout.LabelField(Styles.manipulateBackFaceString); - GUILayout.EndHorizontal(); - } - - void ResetParticleSelection() - { - int lengthSelection = m_ParticleRectSelection.Length; - for (int i = 0; i < lengthSelection; i++) - { - m_ParticleRectSelection[i] = false; - m_ParticleSelection[i] = false; - } - } - - void SelfAndInterCollisionEditing(UnityObject unused, SceneView sceneView) - { - GUILayout.BeginVertical(GUILayout.Width(Styles.clothEditorWindowWidth)); - GUILayout.BeginHorizontal(); - GUILayout.Label("Visualization ", GUILayout.ExpandWidth(false)); - GUILayout.BeginVertical(); - if (EditorGUILayout.DropdownButton(GetCollVisModeString(state.VisualizeSelfOrInterCollision), FocusType.Passive, EditorStyles.toolbarDropDown)) - { - Rect buttonRect = GUILayoutUtility.topLevel.GetLast(); - GenericMenu menu = new GenericMenu(); - menu.AddItem(GetCollVisModeString(CollisionVisualizationMode.SelfCollision), state.VisualizeSelfOrInterCollision == CollisionVisualizationMode.SelfCollision, VisualizationMenuSelfCollision); - menu.AddItem(GetCollVisModeString(CollisionVisualizationMode.InterCollision), state.VisualizeSelfOrInterCollision == CollisionVisualizationMode.InterCollision, VisualizationMenuInterCollision); - menu.DropDown(buttonRect); - } - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - - if (Tools.current != Tool.None) - state.ToolMode = (ToolMode)(-1); - - CollToolMode oldCollToolMode = state.CollToolMode; - state.CollToolMode = (CollToolMode)GUILayout.Toolbar((int)state.CollToolMode, Styles.collToolModeIcons); - if (state.CollToolMode != oldCollToolMode) - { - // delselect text, so we don't end up having a text field highlighted in the new tab - GUIUtility.keyboardControl = 0; - SceneView.RepaintAll(); - } - - switch (state.CollToolMode) - { - case CollToolMode.Select: - Tools.current = Tool.None; - CollSelectionGUI(); - break; - - case CollToolMode.Paint: - case CollToolMode.Erase: - Tools.current = Tool.None; - ResetParticleSelection(); - EditBrushSize(); - break; - } - - SelectManipulateBackFaces(); - - int countIndices = 0; - int length = m_SelfAndInterCollisionSelection.Length; - for (int i = 0; i < length; i++) - { - if (m_SelfAndInterCollisionSelection[i] == true) - { - countIndices++; - } - } - - if (countIndices > 0) - { - List selfAndInterCollisionIndices = new List(countIndices); - selfAndInterCollisionIndices.Clear(); - for (UInt32 i = 0; i < length; i++) - { - if (m_SelfAndInterCollisionSelection[i] == true) - { - selfAndInterCollisionIndices.Add(i); - } - } - - cloth.SetSelfAndInterCollisionIndices(selfAndInterCollisionIndices); - } - - GUILayout.EndVertical(); - } - } -} - diff --git a/Editor/Mono/Inspector/Collider2DEditorBase.cs b/Editor/Mono/Inspector/Collider2DEditorBase.cs deleted file mode 100644 index fc8edfc47d..0000000000 --- a/Editor/Mono/Inspector/Collider2DEditorBase.cs +++ /dev/null @@ -1,259 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEditorInternal; -using UnityEngine; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - [CanEditMultipleObjects] - internal abstract class Collider2DEditorBase : ColliderEditorBase - { - protected class Styles - { - public static readonly GUIContent s_ColliderEditDisableHelp = EditorGUIUtility.TrTextContent("Collider cannot be edited because it is driven by SpriteRenderer's tiling properties."); - public static readonly GUIContent s_AutoTilingLabel = EditorGUIUtility.TrTextContent("Auto Tiling ", " When enabled, the collider's shape will update automaticaly based on the SpriteRenderer's tiling properties"); - } - - private SerializedProperty m_Density; - private readonly AnimBool m_ShowDensity = new AnimBool(); - private readonly AnimBool m_ShowInfo = new AnimBool(); - private readonly AnimBool m_ShowContacts = new AnimBool(); - Vector2 m_ContactScrollPosition; - - static ContactPoint2D[] m_Contacts = new ContactPoint2D[100]; - - private SerializedProperty m_Material; - private SerializedProperty m_IsTrigger; - private SerializedProperty m_UsedByEffector; - private SerializedProperty m_UsedByComposite; - private SerializedProperty m_Offset; - protected SerializedProperty m_AutoTiling; - - private readonly AnimBool m_ShowCompositeRedundants = new AnimBool(); - - public override void OnEnable() - { - base.OnEnable(); - - m_Density = serializedObject.FindProperty("m_Density"); - - m_ShowDensity.value = ShouldShowDensity(); - m_ShowDensity.valueChanged.AddListener(Repaint); - - m_ShowInfo.valueChanged.AddListener(Repaint); - m_ShowContacts.valueChanged.AddListener(Repaint); - m_ContactScrollPosition = Vector2.zero; - - m_Material = serializedObject.FindProperty("m_Material"); - m_IsTrigger = serializedObject.FindProperty("m_IsTrigger"); - m_UsedByEffector = serializedObject.FindProperty("m_UsedByEffector"); - m_UsedByComposite = serializedObject.FindProperty("m_UsedByComposite"); - m_Offset = serializedObject.FindProperty("m_Offset"); - m_AutoTiling = serializedObject.FindProperty("m_AutoTiling"); - - m_ShowCompositeRedundants.value = !m_UsedByComposite.boolValue; - m_ShowCompositeRedundants.valueChanged.AddListener(Repaint); - } - - public override void OnDisable() - { - m_ShowDensity.valueChanged.RemoveListener(Repaint); - m_ShowInfo.valueChanged.RemoveListener(Repaint); - m_ShowContacts.valueChanged.RemoveListener(Repaint); - m_ShowCompositeRedundants.valueChanged.RemoveListener(Repaint); - - base.OnDisable(); - } - - public override void OnInspectorGUI() - { - m_ShowCompositeRedundants.target = !m_UsedByComposite.boolValue; - if (EditorGUILayout.BeginFadeGroup(m_ShowCompositeRedundants.faded)) - { - // Density property. - m_ShowDensity.target = ShouldShowDensity(); - if (EditorGUILayout.BeginFadeGroup(m_ShowDensity.faded)) - EditorGUILayout.PropertyField(m_Density); - FixedEndFadeGroup(m_ShowDensity.faded); - - EditorGUILayout.PropertyField(m_Material); - EditorGUILayout.PropertyField(m_IsTrigger); - EditorGUILayout.PropertyField(m_UsedByEffector); - } - FixedEndFadeGroup(m_ShowCompositeRedundants.faded); - - // Only show 'Used By Composite' if all targets are capable of being composited. - if (targets.Where(x => (x as Collider2D).compositeCapable == false).Count() == 0) - EditorGUILayout.PropertyField(m_UsedByComposite); - - if (m_AutoTiling != null) - EditorGUILayout.PropertyField(m_AutoTiling, Styles.s_AutoTilingLabel); - - EditorGUILayout.PropertyField(m_Offset); - } - - public void FinalizeInspectorGUI() - { - ShowColliderInfoProperties(); - - // Check for collider error state. - CheckColliderErrorState(); - - // If used-by-composite is enabled but there is not composite then show a warning. - if (targets.Length == 1) - { - var collider = target as Collider2D; - if (collider.isActiveAndEnabled && collider.composite == null && m_UsedByComposite.boolValue) - EditorGUILayout.HelpBox("This collider will not function with a composite until there is a CompositeCollider2D on the GameObject that the attached Rigidbody2D is on.", MessageType.Warning); - } - - // Check for effector warnings. - Effector2DEditor.CheckEffectorWarnings(target as Collider2D); - } - - private void ShowColliderInfoProperties() - { - m_ShowInfo.target = EditorGUILayout.Foldout(m_ShowInfo.target, "Info", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowInfo.faded)) - { - if (targets.Length == 1) - { - var collider = targets[0] as Collider2D; - EditorGUI.BeginDisabledGroup(true); - EditorGUILayout.ObjectField("Attached Body", collider.attachedRigidbody, typeof(Rigidbody2D), false); - EditorGUILayout.FloatField("Friction", collider.friction); - EditorGUILayout.FloatField("Bounciness", collider.bounciness); - EditorGUILayout.FloatField("Shape Count", collider.shapeCount); - if (collider.isActiveAndEnabled) - EditorGUILayout.BoundsField("Bounds", collider.bounds); - EditorGUI.EndDisabledGroup(); - - ShowContacts(collider); - - // We need to repaint as some of the above properties can change without causing a repaint. - Repaint(); - } - else - { - EditorGUILayout.HelpBox("Cannot show Info properties when multiple colliders are selected.", MessageType.Info); - } - } - EditorGUILayout.EndFadeGroup(); - } - - bool ShouldShowDensity() - { - if (targets.Select(x => (x as Collider2D).attachedRigidbody).Distinct().Count() > 1) - return false; - - var rigidbody = (target as Collider2D).attachedRigidbody; - return rigidbody && rigidbody.useAutoMass && rigidbody.bodyType == RigidbodyType2D.Dynamic; - } - - void ShowContacts(Collider2D collider) - { - EditorGUI.indentLevel++; - m_ShowContacts.target = EditorGUILayout.Foldout(m_ShowContacts.target, "Contacts"); - if (EditorGUILayout.BeginFadeGroup(m_ShowContacts.faded)) - { - var contactCount = collider.GetContacts(m_Contacts); - if (contactCount > 0) - { - m_ContactScrollPosition = EditorGUILayout.BeginScrollView(m_ContactScrollPosition, GUILayout.Height(180)); - EditorGUI.BeginDisabledGroup(true); - - for (var i = 0; i < contactCount; ++i) - { - var contact = m_Contacts[i]; - EditorGUILayout.HelpBox(string.Format("Contact#{0}", i), MessageType.None); - EditorGUI.indentLevel++; - EditorGUILayout.Vector2Field("Point", contact.point); - EditorGUILayout.Vector2Field("Normal", contact.normal); - EditorGUILayout.Vector2Field("Relative Velocity", contact.relativeVelocity); - EditorGUILayout.FloatField("Normal Impulse", contact.normalImpulse); - EditorGUILayout.FloatField("Tangent Impulse", contact.tangentImpulse); - EditorGUILayout.ObjectField("Collider", contact.collider, typeof(Collider2D), false); - EditorGUILayout.ObjectField("Rigidbody", contact.rigidbody, typeof(Rigidbody2D), false); - EditorGUILayout.ObjectField("OtherRigidbody", contact.otherRigidbody, typeof(Rigidbody2D), false); - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - EditorGUI.EndDisabledGroup(); - EditorGUILayout.EndScrollView(); - } - else - { - EditorGUILayout.HelpBox("No Contacts", MessageType.Info); - } - } - FixedEndFadeGroup(m_ShowContacts.faded); - EditorGUI.indentLevel--; - } - - // Fix for nested fade-groups as found here: - // http://answers.unity3d.com/questions/1096244/custom-editor-fade-group-inside-fade-group.html - static void FixedEndFadeGroup(float value) - { - if (value == 0.0f || value == 1.0f) - return; - - EditorGUILayout.EndFadeGroup(); - } - - internal override void OnForceReloadInspector() - { - base.OnForceReloadInspector(); - - // Whenever inspector get reloaded (reset, move up/down), quit the edit mode if was in editing mode. - // Not sure why this pattern is used here but not for any other editors that implement edit mode button - if (editingCollider) - EditMode.QuitEditMode(); - } - - protected void CheckColliderErrorState() - { - switch ((target as Collider2D).errorState) - { - case ColliderErrorState2D.NoShapes: - // Show warning. - EditorGUILayout.HelpBox("The collider did not create any collision shapes as they all failed verification. This could be because they were deemed too small or the vertices were too close. Vertices can also become close under certain rotations or very small scaling.", MessageType.Warning); - break; - - case ColliderErrorState2D.RemovedShapes: - // Show warning. - EditorGUILayout.HelpBox("The collider created collision shape(s) but some were removed as they failed verification. This could be because they were deemed too small or the vertices were too close. Vertices can also become close under certain rotations or very small scaling.", MessageType.Warning); - break; - } - } - - protected void BeginColliderInspector() - { - serializedObject.Update(); - using (new EditorGUI.DisabledScope(targets.Length > 1)) - { - InspectorEditButtonGUI(); - } - } - - protected void EndColliderInspector() - { - serializedObject.ApplyModifiedProperties(); - } - - protected bool CanEditCollider() - { - var e = targets.FirstOrDefault((x) => - { - var sr = (x as Component).GetComponent(); - return (sr != null && sr.drawMode != SpriteDrawMode.Simple && m_AutoTiling.boolValue == true); - } - ); - return e == false; - } - } -} diff --git a/Editor/Mono/Inspector/Collider3DEditorBase.cs b/Editor/Mono/Inspector/Collider3DEditorBase.cs deleted file mode 100644 index 79fb55a870..0000000000 --- a/Editor/Mono/Inspector/Collider3DEditorBase.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class Collider3DEditorBase : ColliderEditorBase - { - protected SerializedProperty m_Material; - protected SerializedProperty m_IsTrigger; - - protected GUIContent materialContent = EditorGUIUtility.TrTextContent("Material", "Reference to the Physic Material that determines how this Collider interacts with others."); - protected GUIContent triggerContent = EditorGUIUtility.TrTextContent("Is Trigger", "If enabled, this Collider is used for triggering events and is ignored by the physics engine."); - - public override void OnEnable() - { - base.OnEnable(); - m_Material = serializedObject.FindProperty("m_Material"); - m_IsTrigger = serializedObject.FindProperty("m_IsTrigger"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_IsTrigger, triggerContent); - EditorGUILayout.PropertyField(m_Material, materialContent); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/ColliderEditorBase.cs b/Editor/Mono/Inspector/ColliderEditorBase.cs deleted file mode 100644 index 8ba254a4a8..0000000000 --- a/Editor/Mono/Inspector/ColliderEditorBase.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - internal abstract class ColliderEditorBase : Editor - { - protected virtual void OnEditStart() {} - protected virtual void OnEditEnd() {} - - public bool editingCollider - { - get { return EditMode.editMode == EditMode.SceneViewEditMode.Collider && EditMode.IsOwner(this); } - } - - public virtual void OnEnable() - { - EditMode.editModeStarted += OnEditModeStart; - EditMode.editModeEnded += OnEditModeEnd; - } - - public virtual void OnDisable() - { - EditMode.editModeStarted -= OnEditModeStart; - EditMode.editModeEnded -= OnEditModeEnd; - } - - protected virtual GUIContent editModeButton { get { return EditorGUIUtility.IconContent("EditCollider"); } } - - protected void InspectorEditButtonGUI() - { - EditMode.DoEditModeInspectorModeButton( - EditMode.SceneViewEditMode.Collider, - "Edit Collider", - editModeButton, - this - ); - } - - internal override Bounds GetWorldBoundsOfTarget(Object targetObject) - { - if (targetObject is Collider2D) - return ((Collider2D)targetObject).bounds; - else if (targetObject is Collider) - return ((Collider)targetObject).bounds; - else - return base.GetWorldBoundsOfTarget(targetObject); - } - - protected void OnEditModeStart(IToolModeOwner owner, EditMode.SceneViewEditMode mode) - { - if (mode == EditMode.SceneViewEditMode.Collider && owner == (IToolModeOwner)this) - OnEditStart(); - } - - protected void OnEditModeEnd(IToolModeOwner owner) - { - if (owner == (IToolModeOwner)this) - OnEditEnd(); - } - } -} diff --git a/Editor/Mono/Inspector/ColliderEditorUtility.cs b/Editor/Mono/Inspector/ColliderEditorUtility.cs deleted file mode 100644 index d81d0c4be5..0000000000 --- a/Editor/Mono/Inspector/ColliderEditorUtility.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class ColliderEditorUtility - { - private static GUIStyle s_EditColliderButtonStyle; - private const float k_EditColliderbuttonWidth = 22; - private const float k_EditColliderbuttonHeight = 22; - private const float k_SpaceBetweenLabelAndButton = 5; - - public static bool InspectorEditButtonGUI(bool editing) - { - if (s_EditColliderButtonStyle == null) - { - s_EditColliderButtonStyle = new GUIStyle("Button"); - s_EditColliderButtonStyle.padding = new RectOffset(0, 0, 0, 0); - s_EditColliderButtonStyle.margin = new RectOffset(0, 0, 0, 0); - } - - EditorGUI.BeginChangeCheck(); - Rect rect = EditorGUILayout.GetControlRect(true, k_EditColliderbuttonHeight); - Rect buttonRect = new Rect(rect.xMin + EditorGUIUtility.labelWidth, rect.yMin, k_EditColliderbuttonWidth, k_EditColliderbuttonHeight); - - GUIContent labelContent = EditorGUIUtility.TrTextContent("Edit Collider"); - Vector2 labelSize = GUI.skin.label.CalcSize(labelContent); - - Rect labelRect = new Rect( - buttonRect.xMax + k_SpaceBetweenLabelAndButton, - rect.yMin + (rect.height - labelSize.y) * .5f, - labelSize.x, - rect.height); - - GUILayout.Space(2f); - bool newValue = GUI.Toggle(buttonRect, editing, EditorGUIUtility.IconContent("EditCollider"), s_EditColliderButtonStyle); - GUI.Label(labelRect, "Edit Collider"); - if (EditorGUI.EndChangeCheck()) - SceneView.RepaintAll(); - - return newValue; - } - } -} diff --git a/Editor/Mono/Inspector/ColorPresetLibraryInspector.cs b/Editor/Mono/Inspector/ColorPresetLibraryInspector.cs deleted file mode 100644 index c0703c639f..0000000000 --- a/Editor/Mono/Inspector/ColorPresetLibraryInspector.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(ColorPresetLibrary))] - internal class ColorPresetLibraryEditor : Editor - { - private GenericPresetLibraryInspector m_GenericPresetLibraryInspector; - - public void OnEnable() - { - m_GenericPresetLibraryInspector = new GenericPresetLibraryInspector(target, "Color Preset Library", OnEditButtonClicked); - m_GenericPresetLibraryInspector.useOnePixelOverlappedGrid = true; - m_GenericPresetLibraryInspector.maxShowNumPresets = 2000; // does not use a preview cache so show many - } - - public void OnDestroy() - { - if (m_GenericPresetLibraryInspector != null) - m_GenericPresetLibraryInspector.OnDestroy(); - } - - public override void OnInspectorGUI() - { - m_GenericPresetLibraryInspector.itemViewMode = PresetLibraryEditorState.GetItemViewMode(ColorPicker.presetsEditorPrefID); // ensure in-sync - if (m_GenericPresetLibraryInspector != null) - m_GenericPresetLibraryInspector.OnInspectorGUI(); - } - - private void OnEditButtonClicked(string libraryPath) - { - ColorPicker.Show(GUIView.current, Color.white); - ColorPicker.instance.currentPresetLibrary = libraryPath; - } - } -} // namespace diff --git a/Editor/Mono/Inspector/CompositeCollider2DEditor.cs b/Editor/Mono/Inspector/CompositeCollider2DEditor.cs deleted file mode 100644 index a66a9cfae7..0000000000 --- a/Editor/Mono/Inspector/CompositeCollider2DEditor.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEditor.AnimatedValues; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(CompositeCollider2D))] - [CanEditMultipleObjects] - internal class CompositeCollider2DEditor : Collider2DEditorBase - { - private SerializedProperty m_GeometryType; - private SerializedProperty m_GenerationType; - private SerializedProperty m_VertexDistance; - private SerializedProperty m_EdgeRadius; - readonly AnimBool m_ShowEdgeRadius = new AnimBool(); - readonly AnimBool m_ShowManualGenerationButton = new AnimBool(); - - public override void OnEnable() - { - base.OnEnable(); - - m_GeometryType = serializedObject.FindProperty("m_GeometryType"); - m_GenerationType = serializedObject.FindProperty("m_GenerationType"); - m_VertexDistance = serializedObject.FindProperty("m_VertexDistance"); - m_EdgeRadius = serializedObject.FindProperty("m_EdgeRadius"); - m_ShowEdgeRadius.value = targets.Where(x => (x as CompositeCollider2D).geometryType == CompositeCollider2D.GeometryType.Polygons).Count() == 0; - m_ShowEdgeRadius.valueChanged.AddListener(Repaint); - m_ShowManualGenerationButton.value = targets.Where(x => (x as CompositeCollider2D).generationType != CompositeCollider2D.GenerationType.Manual).Count() == 0; - m_ShowManualGenerationButton.valueChanged.AddListener(Repaint); - } - - public override void OnDisable() - { - m_ShowEdgeRadius.valueChanged.RemoveListener(Repaint); - m_ShowManualGenerationButton.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - base.OnInspectorGUI(); - - EditorGUILayout.PropertyField(m_GeometryType); - EditorGUILayout.PropertyField(m_GenerationType); - EditorGUILayout.PropertyField(m_VertexDistance); - - m_ShowManualGenerationButton.target = targets.Where(x => (x as CompositeCollider2D).generationType != CompositeCollider2D.GenerationType.Manual).Count() == 0; - if (EditorGUILayout.BeginFadeGroup(m_ShowManualGenerationButton.faded)) - { - if (GUILayout.Button("Regenerate Collider")) - foreach (var composite in targets) - (composite as CompositeCollider2D).GenerateGeometry(); - } - EditorGUILayout.EndFadeGroup(); - - m_ShowEdgeRadius.target = targets.Where(x => (x as CompositeCollider2D).geometryType == CompositeCollider2D.GeometryType.Polygons).Count() == 0; - if (EditorGUILayout.BeginFadeGroup(m_ShowEdgeRadius.faded)) - EditorGUILayout.PropertyField(m_EdgeRadius); - EditorGUILayout.EndFadeGroup(); - - if (targets.Where(x => - (x as CompositeCollider2D).geometryType == CompositeCollider2D.GeometryType.Outlines && - (x as CompositeCollider2D).attachedRigidbody != null && - (x as CompositeCollider2D).attachedRigidbody.bodyType == RigidbodyType2D.Dynamic).Count() > 0) - EditorGUILayout.HelpBox("Outline geometry is composed of edges and will not preserve the original collider's center-of-mass or rotational inertia. The CompositeCollider2D is attached to a Dynamic Rigidbody2D so you may need to explicitly set these if they are required.", MessageType.Info); - - serializedObject.ApplyModifiedProperties(); - - FinalizeInspectorGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/ComputeShaderInspector.cs b/Editor/Mono/Inspector/ComputeShaderInspector.cs deleted file mode 100644 index 23d7b1c800..0000000000 --- a/Editor/Mono/Inspector/ComputeShaderInspector.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Rendering; -using System.Collections.Generic; -using System.Globalization; - -namespace UnityEditor -{ - [CustomEditor(typeof(ComputeShader))] - internal class ComputeShaderInspector : Editor - { - private const float kSpace = 5f; - Vector2 m_ScrollPosition = Vector2.zero; - - // Compute kernel information is stored split by platform, then by kernels; - // but for the inspector we want to show kernels, then platforms they are in. - class KernelInfo - { - internal string name; - internal string platforms; - }; - - internal class Styles - { - public static GUIContent showCompiled = EditorGUIUtility.TrTextContent("Show compiled code"); - public static GUIContent kernelsHeading = EditorGUIUtility.TrTextContent("Kernels:"); - } - - static List GetKernelDisplayInfo(ComputeShader cs) - { - var kernelInfo = new List(); - var platformCount = ShaderUtil.GetComputeShaderPlatformCount(cs); - for (var i = 0; i < platformCount; ++i) - { - var platform = ShaderUtil.GetComputeShaderPlatformType(cs, i); - var kernelCount = ShaderUtil.GetComputeShaderPlatformKernelCount(cs, i); - for (var j = 0; j < kernelCount; ++j) - { - var kernelName = ShaderUtil.GetComputeShaderPlatformKernelName(cs, i, j); - var found = false; - foreach (var ki in kernelInfo) - { - if (ki.name == kernelName) - { - ki.platforms += ' '; - ki.platforms += platform.ToString(); - found = true; - } - } - if (!found) - { - var ki = new KernelInfo(); - ki.name = kernelName; - ki.platforms = platform.ToString(); - kernelInfo.Add(ki); - } - } - } - return kernelInfo; - } - - public override void OnInspectorGUI() - { - var cs = target as ComputeShader; - if (cs == null) - return; - - GUI.enabled = true; - - EditorGUI.indentLevel = 0; - - ShowKernelInfoSection(cs); - ShowCompiledCodeSection(cs); - ShowShaderErrors(cs); - } - - private void ShowKernelInfoSection(ComputeShader cs) - { - GUILayout.Label(Styles.kernelsHeading, EditorStyles.boldLabel); - var kernelInfo = GetKernelDisplayInfo(cs); - foreach (var ki in kernelInfo) - { - EditorGUILayout.LabelField(ki.name, ki.platforms); - } - } - - private void ShowCompiledCodeSection(ComputeShader cs) - { - GUILayout.Space(kSpace); - if (GUILayout.Button(Styles.showCompiled, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - { - ShaderUtil.OpenCompiledComputeShader(cs, true); - GUIUtility.ExitGUI(); - } - } - - private void ShowShaderErrors(ComputeShader s) - { - int n = ShaderUtil.GetComputeShaderErrorCount(s); - if (n < 1) - return; - ShaderInspector.ShaderErrorListUI(s, ShaderUtil.GetComputeShaderErrors(s), ref m_ScrollPosition); - } - } -} diff --git a/Editor/Mono/Inspector/ConfigurableJointEditor.cs b/Editor/Mono/Inspector/ConfigurableJointEditor.cs deleted file mode 100644 index 904cf612f8..0000000000 --- a/Editor/Mono/Inspector/ConfigurableJointEditor.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(ConfigurableJoint)), CanEditMultipleObjects] - class ConfigurableJointEditor : JointEditor - { - protected override void GetActors( - ConfigurableJoint joint, - out Rigidbody dynamicActor, - out Rigidbody connectedActor, - out int jointFrameActorIndex, - out bool rightHandedLimit - ) - { - base.GetActors(joint, out dynamicActor, out connectedActor, out jointFrameActorIndex, out rightHandedLimit); - if (joint.swapBodies) - { - jointFrameActorIndex = 0; - rightHandedLimit = true; - } - } - - protected override void DoAngularLimitHandles(ConfigurableJoint joint) - { - base.DoAngularLimitHandles(joint); - - angularLimitHandle.xMotion = joint.angularXMotion; - angularLimitHandle.yMotion = joint.angularYMotion; - angularLimitHandle.zMotion = joint.angularZMotion; - - SoftJointLimit limit; - - limit = joint.lowAngularXLimit; - angularLimitHandle.xMin = limit.limit; - - limit = joint.highAngularXLimit; - angularLimitHandle.xMax = limit.limit; - - limit = joint.angularYLimit; - angularLimitHandle.yMax = limit.limit; - angularLimitHandle.yMin = -limit.limit; - - limit = joint.angularZLimit; - angularLimitHandle.zMax = limit.limit; - angularLimitHandle.zMin = -limit.limit; - - EditorGUI.BeginChangeCheck(); - - angularLimitHandle.radius = GetAngularLimitHandleSize(Vector3.zero); - angularLimitHandle.DrawHandle(); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(joint, Styles.editAngularLimitsUndoMessage); - - limit = joint.lowAngularXLimit; - limit.limit = angularLimitHandle.xMin; - joint.lowAngularXLimit = limit; - - limit = joint.highAngularXLimit; - limit.limit = angularLimitHandle.xMax; - joint.highAngularXLimit = limit; - - limit = joint.angularYLimit; - limit.limit = angularLimitHandle.yMax == limit.limit ? -angularLimitHandle.yMin : angularLimitHandle.yMax; - joint.angularYLimit = limit; - - limit = joint.angularZLimit; - limit.limit = angularLimitHandle.zMax == limit.limit ? -angularLimitHandle.zMin : angularLimitHandle.zMax; - joint.angularZLimit = limit; - } - } - } -} diff --git a/Editor/Mono/Inspector/ConstraintEditorBase.cs b/Editor/Mono/Inspector/ConstraintEditorBase.cs deleted file mode 100644 index c50e8170cc..0000000000 --- a/Editor/Mono/Inspector/ConstraintEditorBase.cs +++ /dev/null @@ -1,239 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Animations; -using Object = UnityEngine.Object; -using UnityEditorInternal; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal abstract class ConstraintStyleBase - { - GUIContent m_Activate = EditorGUIUtility.TextContent("Activate|Activate the constraint at the current offset from the sources."); - GUIContent m_Zero = EditorGUIUtility.TextContent("Zero|Activate the constraint at zero offset from the sources."); - - GUIContent m_Sources = EditorGUIUtility.TextContent("Sources"); - - GUIContent m_Weight = EditorGUIUtility.TextContent("Weight"); - - GUIContent m_IsActive = EditorGUIUtility.TextContent("Is Active|When set, the constraint is being evaluated."); - GUIContent m_IsLocked = EditorGUIUtility.TextContent("Lock|When set, evaluate with the current offset. When not set, update the offset based on the current transform."); - - GUIContent[] m_Axes = - { - EditorGUIUtility.TextContent("X"), - EditorGUIUtility.TextContent("Y"), - EditorGUIUtility.TextContent("Z") - }; - - GUIContent m_ConstraintSettings = EditorGUIUtility.TextContent("Constraint Settings"); - - public virtual GUIContent Activate { get { return m_Activate; } } - public virtual GUIContent Zero { get { return m_Zero; } } - - public abstract GUIContent AtRest { get; } - public abstract GUIContent Offset { get; } - - public virtual GUIContent Sources { get { return m_Sources; } } - - public virtual GUIContent Weight { get { return m_Weight; } } - - public virtual GUIContent IsActive { get { return m_IsActive; } } - public virtual GUIContent IsLocked { get { return m_IsLocked; } } - - public virtual GUIContent[] Axes { get { return m_Axes; } } - - public virtual GUIContent ConstraintSettings { get { return m_ConstraintSettings; } } - } - - internal abstract class ConstraintEditorBase : Editor - { - private bool m_ShowConstraintSettings = false; - - internal abstract SerializedProperty atRest { get; } - internal abstract SerializedProperty offset { get; } - internal abstract SerializedProperty weight { get; } - internal abstract SerializedProperty isContraintActive { get; } - internal abstract SerializedProperty isLocked { get; } - internal abstract SerializedProperty sources { get; } - - private ReorderableList m_SourceList; - - private int m_SelectedSourceIdx = -1; - protected int selectedSourceIndex { get { return m_SelectedSourceIdx; } set { m_SelectedSourceIdx = value; } } - - protected const int kSourceWeightWidth = 60; - - public void OnEnable(ConstraintStyleBase style) - { - Undo.undoRedoPerformed += OnUndoRedoPerformed; - - m_SourceList = new ReorderableList(serializedObject, sources, sources.editable, true, sources.editable, sources.editable); - m_SourceList.drawElementCallback += DrawElementCallback; - m_SourceList.onAddCallback += OnAddCallback; - m_SourceList.drawHeaderCallback += rect => EditorGUI.LabelField(rect, style.Sources); - m_SourceList.onRemoveCallback += OnRemoveCallback; - m_SourceList.onSelectCallback += OnSelectedCallback; - m_SourceList.onReorderCallbackWithDetails += OnReorderCallback; - - if (sources.arraySize > 0 && m_SelectedSourceIdx == -1) - { - SelectSource(0); - } - } - - public void OnDisable() - { - Undo.undoRedoPerformed -= OnUndoRedoPerformed; - } - - internal void OnUndoRedoPerformed() - { - // must call UserUpdateOffset to allow the offsets to be updated by the Undo system, otherwise the constraint can override them - foreach (var t in targets) - (t as IConstraintInternal).UserUpdateOffset(); - } - - protected void SelectSource(int index) - { - m_SelectedSourceIdx = index; - - if (m_SourceList.index != index) - { - m_SourceList.index = index; - } - } - - protected virtual void OnSelectedCallback(ReorderableList list) - { - SelectSource(list.index); - } - - protected virtual void OnReorderCallback(ReorderableList list, int oldActiveElement, int newActiveElement) {} - - protected virtual void OnRemoveCallback(ReorderableList list) - { - ReorderableList.defaultBehaviours.DoRemoveButton(list); - if (m_SelectedSourceIdx >= list.serializedProperty.arraySize) - { - SelectSource(list.serializedProperty.arraySize - 1); - } - } - - protected virtual void OnAddCallback(ReorderableList list) - { - var index = list.serializedProperty.arraySize; - ReorderableList.defaultBehaviours.DoAddButton(list); - - var source = list.serializedProperty.GetArrayElementAtIndex(index); - source.FindPropertyRelative("sourceTransform").objectReferenceValue = null; - source.FindPropertyRelative("weight").floatValue = 1.0f; - - SelectSource(index); - } - - private void DrawElementCallback(Rect rect, int index, bool isActive, bool isFocused) - { - rect.height = EditorGUIUtility.singleLineHeight; - rect.y += 1; - - var element = sources.GetArrayElementAtIndex(index); - var source = element.FindPropertyRelative("sourceTransform"); - var weight = element.FindPropertyRelative("weight"); - - EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width - kSourceWeightWidth, EditorGUIUtility.singleLineHeight), source, GUIContent.none); - EditorGUI.PropertyField(new Rect(rect.x + rect.width - kSourceWeightWidth, rect.y, kSourceWeightWidth, EditorGUIUtility.singleLineHeight), weight, GUIContent.none); - } - - internal abstract void OnValueAtRestChanged(); - internal abstract void ShowFreezeAxesControl(); - - /// Show the custom constraint properties that are not included in the foldout - internal virtual void ShowCustomProperties() {} - - internal void ShowConstraintEditor(ConstraintStyleBase style) where T : class, IConstraintInternal - { - if (m_SelectedSourceIdx == -1 || m_SelectedSourceIdx >= m_SourceList.serializedProperty.arraySize) - { - SelectSource(0); - } - - using (new EditorGUI.DisabledScope(Application.isPlaying)) - { - using (new EditorGUILayout.HorizontalScope()) - { - if (GUILayout.Button(style.Activate)) - { - List recordObjects = new List(); - recordObjects.AddRange(targets); - foreach (var t in targets) - recordObjects.Add((t as T).transform); - Undo.RegisterCompleteObjectUndo(recordObjects.ToArray(), "Activate the Constraint"); - - foreach (var t in targets) - (t as T).ActivateAndPreserveOffset(); - } - - if (GUILayout.Button(style.Zero)) - { - List recordObjects = new List(); - recordObjects.AddRange(targets); - foreach (var t in targets) - recordObjects.Add((t as T).transform); - Undo.RegisterCompleteObjectUndo(recordObjects.ToArray(), "Zero the Constraint"); - - foreach (var t in targets) - (t as T).ActivateWithZeroOffset(); - } - } - } - - EditorGUILayout.PropertyField(isContraintActive, style.IsActive); - EditorGUILayout.Slider(weight, 0.0f, 1.0f, style.Weight); - ShowCustomProperties(); - - m_ShowConstraintSettings = EditorGUILayout.Foldout(m_ShowConstraintSettings, style.ConstraintSettings, true); - if (m_ShowConstraintSettings) - { - EditorGUI.indentLevel++; - using (new EditorGUI.DisabledScope(Application.isPlaying)) - { - EditorGUILayout.PropertyField(isLocked, style.IsLocked); - } - using (new EditorGUI.DisabledGroupScope(isLocked.boolValue)) - { - ShowValueAtRest(style); - - ShowOffset(style); - } - ShowFreezeAxesControl(); - EditorGUI.indentLevel--; - } - m_SourceList.DoLayoutList(); - } - - internal virtual void ShowValueAtRest(ConstraintStyleBase style) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(atRest, style.AtRest); - if (EditorGUI.EndChangeCheck()) - { - OnValueAtRestChanged(); - } - } - - internal virtual void ShowOffset(ConstraintStyleBase style) where T : class, IConstraintInternal - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(offset, style.Offset); - if (EditorGUI.EndChangeCheck()) - { - foreach (var t in targets) - (t as T).UserUpdateOffset(); - } - } - } -} diff --git a/Editor/Mono/Inspector/CubemapInspector.cs b/Editor/Mono/Inspector/CubemapInspector.cs deleted file mode 100644 index 4085ab40d6..0000000000 --- a/Editor/Mono/Inspector/CubemapInspector.cs +++ /dev/null @@ -1,163 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Globalization; -using UnityEngine; - - -namespace UnityEditor -{ - [CustomEditor(typeof(Cubemap))] - internal class CubemapInspector : TextureInspector - { - static private readonly string[] kSizes = { "16", "32", "64", "128" , "256" , "512" , "1024" , "2048" }; - static private readonly int[] kSizesValues = { 16, 32, 64, 128, 256, 512, 1024, 2048 }; - const int kTextureSize = 64; - - private Texture2D[] m_Images; - - protected override void OnEnable() - { - base.OnEnable(); - InitTexturesFromCubemap(); - } - - protected override void OnDisable() - { - base.OnDisable(); - - if (m_Images != null) - { - for (int i = 0; i < m_Images.Length; ++i) - { - if (m_Images[i] && !EditorUtility.IsPersistent(m_Images[i])) - DestroyImmediate(m_Images[i]); - } - } - m_Images = null; - } - - private void InitTexturesFromCubemap() - { - var c = target as Cubemap; - if (c != null) - { - if (m_Images == null) - m_Images = new Texture2D[6]; - for (int i = 0; i < m_Images.Length; ++i) - { - if (m_Images[i] && !EditorUtility.IsPersistent(m_Images[i])) - DestroyImmediate(m_Images[i]); - - if (TextureUtil.GetSourceTexture(c, (CubemapFace)i)) - { - m_Images[i] = TextureUtil.GetSourceTexture(c, (CubemapFace)i); - } - else - { - m_Images[i] = new Texture2D(kTextureSize, kTextureSize, TextureFormat.RGBA32, false); - m_Images[i].hideFlags = HideFlags.HideAndDontSave; - TextureUtil.CopyCubemapFaceIntoTexture(c, (CubemapFace)i, m_Images[i]); - } - } - } - } - - public override void OnInspectorGUI() - { - if (m_Images == null) - InitTexturesFromCubemap(); - - EditorGUIUtility.labelWidth = 50; - var c = target as Cubemap; - if (c == null) - return; - - GUILayout.BeginVertical(); - - GUILayout.BeginHorizontal(); - ShowFace("Right\n(+X)", CubemapFace.PositiveX); - ShowFace("Left\n(-X)", CubemapFace.NegativeX); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - ShowFace("Top\n(+Y)", CubemapFace.PositiveY); - ShowFace("Bottom\n(-Y)", CubemapFace.NegativeY); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - ShowFace("Front\n(+Z)", CubemapFace.PositiveZ); - ShowFace("Back\n(-Z)", CubemapFace.NegativeZ); - GUILayout.EndHorizontal(); - - GUILayout.EndVertical(); - - EditorGUIUtility.labelWidth = 0; - - EditorGUILayout.Space(); - - EditorGUI.BeginChangeCheck(); - - EditorGUILayout.HelpBox("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.", MessageType.Warning); - int faceSize = TextureUtil.GetGPUWidth(c); - faceSize = EditorGUILayout.IntPopup("Face size", faceSize, kSizes, kSizesValues); - - int mipMaps = TextureUtil.GetMipmapCount(c); - bool useMipMap = EditorGUILayout.Toggle("MipMaps", mipMaps > 1); - - - bool linear = TextureUtil.GetLinearSampled(c); - linear = EditorGUILayout.Toggle("Linear", linear); - - bool readable = TextureUtil.IsCubemapReadable(c); - readable = EditorGUILayout.Toggle("Readable", readable); - - if (EditorGUI.EndChangeCheck()) - { - // reformat the cubemap - if (TextureUtil.ReformatCubemap(ref c, faceSize, faceSize, c.format, useMipMap, linear)) - InitTexturesFromCubemap(); - - TextureUtil.MarkCubemapReadable(c, readable); - c.Apply(); - } - } - - // A minimal list of settings to be shown in the Asset Store preview inspector - internal override void OnAssetStoreInspectorGUI() - { - OnInspectorGUI(); - } - - private void ShowFace(string label, CubemapFace face) - { - var c = target as Cubemap; - var iface = (int)face; - GUI.changed = false; - - var tex = (Texture2D)ObjectField(label, m_Images[iface], typeof(Texture2D), false); - if (GUI.changed) - { - TextureUtil.CopyTextureIntoCubemapFace(tex, c, face); - // enable this line in order to retain connections from cube faces to their corresponding - // texture2D assets, this allows auto-update functionality when editing the source texture - // images - //TextureUtil.SetSourceTexture(c, face, tex); - m_Images[iface] = tex; - } - } - - // Variation of ObjectField where label is not restricted to one line - public static Object ObjectField(string label, Object obj, System.Type objType, bool allowSceneObjects, params GUILayoutOption[] options) - { - GUILayout.BeginHorizontal(); - Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.labelWidth, EditorGUI.kSingleLineHeight * 2, EditorStyles.label, GUILayout.ExpandWidth(false)); - GUI.Label(r, label, EditorStyles.label); - r = GUILayoutUtility.GetAspectRect(1, EditorStyles.objectField, GUILayout.Width(64)); - Object retval = EditorGUI.ObjectField(r, obj, objType, allowSceneObjects); - GUILayout.EndHorizontal(); - return retval; - } - } -} diff --git a/Editor/Mono/Inspector/CubemapPreview.cs b/Editor/Mono/Inspector/CubemapPreview.cs deleted file mode 100644 index 0b2a878a4b..0000000000 --- a/Editor/Mono/Inspector/CubemapPreview.cs +++ /dev/null @@ -1,208 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Globalization; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class CubemapPreview - { - private enum PreviewType - { - RGB = 0, - Alpha = 1 - } - // Preview settings - [SerializeField] - private PreviewType m_PreviewType = PreviewType.RGB; - [SerializeField] - float m_MipLevel = 0.0F; - private float m_Intensity = 1.0f; - - // Cached preview data - private PreviewRenderUtility m_PreviewUtility; - private Mesh m_Mesh; - public Vector2 m_PreviewDir = new Vector2(0, 0); - - static class Styles - { - public static GUIStyle preButton = "preButton"; - public static GUIStyle preSlider = "preSlider"; - public static GUIStyle preSliderThumb = "preSliderThumb"; - public static GUIStyle preLabel = "preLabel"; - public static GUIContent smallZoom = EditorGUIUtility.IconContent("PreTextureMipMapLow"); - public static GUIContent largeZoom = EditorGUIUtility.IconContent("PreTextureMipMapHigh"); - public static GUIContent alphaIcon = EditorGUIUtility.IconContent("PreTextureAlpha"); - public static GUIContent RGBIcon = EditorGUIUtility.IconContent("PreTextureRGB"); - } - - public void OnDisable() - { - if (m_PreviewUtility != null) - { - m_PreviewUtility.Cleanup(); - m_PreviewUtility = null; - } - } - - public float mipLevel { get { return m_MipLevel; } set { m_MipLevel = value; } } - - // For mip maps we render by default with mipLevel 0 but allow for - public float GetMipLevelForRendering(Texture texture) - { - return Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(texture)); - } - - public void SetIntensity(float intensity) - { - m_Intensity = intensity; - } - - void InitPreview() - { - // Initialized? - if (m_PreviewUtility != null) - return; - - m_PreviewUtility = new PreviewRenderUtility(); - m_PreviewUtility.camera.fieldOfView = 15f; - m_Mesh = PreviewRenderUtility.GetPreviewSphere(); - } - - public void OnPreviewSettings(Object[] targets) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - return; - GUI.enabled = true; - InitPreview(); - - bool showMode = true; - bool alphaOnly = true; - //@TODO: Share some code with texture inspector??? - bool hasAlpha = false; - int mipCount = 8; - foreach (Texture t2 in targets) - { - mipCount = Mathf.Max(mipCount, TextureUtil.GetMipmapCount(t2)); - - Cubemap cubemap = t2 as Cubemap; - if (cubemap) - { - TextureFormat format = cubemap.format; - if (!TextureUtil.IsAlphaOnlyTextureFormat(format)) - alphaOnly = false; - if (TextureUtil.HasAlphaTextureFormat(format)) - { - TextureUsageMode mode = TextureUtil.GetUsageMode(t2); - if (mode == TextureUsageMode.Default) // all other texture usage modes don't displayable alpha - hasAlpha = true; - } - } - else - { - hasAlpha = true; - alphaOnly = false; - } - } - - if (alphaOnly) - { - m_PreviewType = PreviewType.Alpha; - showMode = false; - } - else if (!hasAlpha) - { - m_PreviewType = PreviewType.RGB; - showMode = false; - } - - if (showMode) - { - GUIContent[] kPreviewIcons = { Styles.RGBIcon, Styles.alphaIcon }; - int index = (int)m_PreviewType; - if (GUILayout.Button(kPreviewIcons[index], Styles.preButton)) - m_PreviewType = (PreviewType)(++index % kPreviewIcons.Length); - } - - GUI.enabled = (mipCount != 1); - GUILayout.Box(Styles.smallZoom, Styles.preLabel); - GUI.changed = false; - m_MipLevel = Mathf.Round(GUILayout.HorizontalSlider(m_MipLevel, mipCount - 1, 0, Styles.preSlider, Styles.preSliderThumb, GUILayout.MaxWidth(64))); - GUILayout.Box(Styles.largeZoom, Styles.preLabel); - GUI.enabled = true; - } - - public void OnPreviewGUI(Texture t, Rect r, GUIStyle background) - { - if (t == null) - return; - - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - { - if (Event.current.type == EventType.Repaint) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), "Cubemap preview requires\nrender texture support"); - return; - } - - m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, r); - - if (Event.current.type != EventType.Repaint) - return; - - InitPreview(); - m_PreviewUtility.BeginPreview(r, background); - const float previewDistance = 6.0f; - - RenderCubemap(t, m_PreviewDir, previewDistance); - - Texture renderedTexture = m_PreviewUtility.EndPreview(); - GUI.DrawTexture(r, renderedTexture, ScaleMode.StretchToFill, false); - - if (mipLevel != 0) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 20), "Mip " + mipLevel); - } - - public Texture2D RenderStaticPreview(Texture t, int width, int height) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - return null; - - InitPreview(); - m_PreviewUtility.BeginStaticPreview(new Rect(0, 0, width, height)); - const float previewDistance = 5.3f; - Vector2 previewDirection = new Vector2(0, 0); - - // When rendering the cubemap preview we don't need lighting so we provide a custom list with no lights. - // 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. - m_PreviewUtility.ambientColor = Color.black; - - RenderCubemap(t, previewDirection, previewDistance); - - return m_PreviewUtility.EndStaticPreview(); - } - - private void RenderCubemap(Texture t, Vector2 previewDir, float previewDistance) - { - m_PreviewUtility.camera.transform.position = -Vector3.forward * previewDistance; - m_PreviewUtility.camera.transform.rotation = Quaternion.identity; - Quaternion rot = Quaternion.Euler(previewDir.y, 0, 0) * Quaternion.Euler(0, previewDir.x, 0); - - var mat = EditorGUIUtility.LoadRequired("Previews/PreviewCubemapMaterial.mat") as Material; - mat.mainTexture = t; - - mat.SetMatrix("_CubemapRotation", Matrix4x4.TRS(Vector3.zero, rot, Vector3.one)); - - // -1 indicates "use regular sampling"; mips 0 and larger sample only that mip level for preview - float mipLevel = GetMipLevelForRendering(t); - mat.SetFloat("_Mip", mipLevel); - mat.SetFloat("_Alpha", (m_PreviewType == PreviewType.Alpha) ? 1.0f : 0.0f); - mat.SetFloat("_Intensity", m_Intensity); - - m_PreviewUtility.DrawMesh(m_Mesh, Vector3.zero, rot, mat, 0); - m_PreviewUtility.Render(); - } - } -} diff --git a/Editor/Mono/Inspector/CurvePresetLibraryInspector.cs b/Editor/Mono/Inspector/CurvePresetLibraryInspector.cs deleted file mode 100644 index 348d1c61de..0000000000 --- a/Editor/Mono/Inspector/CurvePresetLibraryInspector.cs +++ /dev/null @@ -1,99 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(CurvePresetLibrary))] - internal class CurvePresetLibraryEditor : Editor - { - private GenericPresetLibraryInspector m_GenericPresetLibraryInspector; - private CurveLibraryType m_CurveLibraryType; - - public void OnEnable() - { - string filePath = AssetDatabase.GetAssetPath(target.GetInstanceID()); - m_CurveLibraryType = GetCurveLibraryTypeFromExtension(Path.GetExtension(filePath).TrimStart('.')); - m_GenericPresetLibraryInspector = new GenericPresetLibraryInspector(target, GetHeader(), OnEditButtonClicked); - m_GenericPresetLibraryInspector.presetSize = new Vector2(72, 20); - m_GenericPresetLibraryInspector.lineSpacing = 5f; - } - - public void OnDestroy() - { - if (m_GenericPresetLibraryInspector != null) - m_GenericPresetLibraryInspector.OnDestroy(); - } - - public override void OnInspectorGUI() - { - string editorPrefPrefix = CurvePresetsContentsForPopupWindow.GetBasePrefText(m_CurveLibraryType); - m_GenericPresetLibraryInspector.itemViewMode = PresetLibraryEditorState.GetItemViewMode(editorPrefPrefix); // ensure in-sync - if (m_GenericPresetLibraryInspector != null) - m_GenericPresetLibraryInspector.OnInspectorGUI(); - } - - private void OnEditButtonClicked(string libraryPath) - { - Rect ranges = GetCurveRanges(); - CurveEditorSettings settings = new CurveEditorSettings(); - if (ranges.width > 0 && ranges.height > 0 && ranges.width != Mathf.Infinity && ranges.height != Mathf.Infinity) - { - settings.hRangeMin = ranges.xMin; - settings.hRangeMax = ranges.xMax; - settings.vRangeMin = ranges.yMin; - settings.vRangeMax = ranges.yMax; - } - - CurveEditorWindow.curve = new AnimationCurve(); - CurveEditorWindow.color = new Color(0, 0.8f, 0f); - CurveEditorWindow.instance.Show(GUIView.current, settings); - - CurveEditorWindow.instance.currentPresetLibrary = libraryPath; - } - - private string GetHeader() - { - switch (m_CurveLibraryType) - { - case CurveLibraryType.NormalizedZeroToOne: - return "Curve Preset Library (Normalized 0 - 1)"; - case CurveLibraryType.Unbounded: - return "Curve Preset Library"; - default: - return "Curve Preset Library ?"; - } - } - - private Rect GetCurveRanges() - { - switch (m_CurveLibraryType) - { - case CurveLibraryType.NormalizedZeroToOne: - return new Rect(0, 0, 1, 1); - case CurveLibraryType.Unbounded: - return new Rect(); - default: - return new Rect(); - } - } - - CurveLibraryType GetCurveLibraryTypeFromExtension(string extension) - { - string curveNormalized = PresetLibraryLocations.GetCurveLibraryExtension(true); - string curve = PresetLibraryLocations.GetCurveLibraryExtension(false); - if (extension.Equals(curveNormalized, StringComparison.OrdinalIgnoreCase)) - return CurveLibraryType.NormalizedZeroToOne; - - if (extension.Equals(curve, StringComparison.OrdinalIgnoreCase)) - return CurveLibraryType.Unbounded; - - Debug.LogError("Extension not recognized!"); - return CurveLibraryType.NormalizedZeroToOne; - } - } -} // namespace diff --git a/Editor/Mono/Inspector/CustomPreviewAttribute.cs b/Editor/Mono/Inspector/CustomPreviewAttribute.cs deleted file mode 100644 index 37e365e08a..0000000000 --- a/Editor/Mono/Inspector/CustomPreviewAttribute.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor -{ - // Tells a custom [[IPreviewable]] which run-time [[Serializable]] class or [[PropertyAttribute]] it's a drawer for. - [System.AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] - public sealed class CustomPreviewAttribute : Attribute - { - internal Type m_Type; - - // Tells a PropertyDrawer class which run-time class or attribute it's a drawer for. - public CustomPreviewAttribute(Type type) - { - m_Type = type; - } - } -} diff --git a/Editor/Mono/Inspector/CustomRenderTextureEditor.cs b/Editor/Mono/Inspector/CustomRenderTextureEditor.cs deleted file mode 100644 index 6222f24081..0000000000 --- a/Editor/Mono/Inspector/CustomRenderTextureEditor.cs +++ /dev/null @@ -1,503 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using System.Collections.Generic; -using System.IO; -using AnimatedBool = UnityEditor.AnimatedValues.AnimBool; - -namespace UnityEditor -{ - - [CustomEditor(typeof(CustomRenderTexture))] - [CanEditMultipleObjects] - internal class CustomRenderTextureEditor : RenderTextureEditor - { - private class Styles - { - public readonly GUIStyle separator = "sv_iconselector_sep"; - public readonly GUIContent materials = EditorGUIUtility.TrTextContent("Materials"); - public readonly GUIContent shaderPass = EditorGUIUtility.TrTextContent("Shader Pass", "Shader Pass used to update the Custom Render Texture."); - 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."); - public readonly GUIContent updateMode = EditorGUIUtility.TrTextContent("Update Mode", "Specify how the texture should be updated."); - public readonly GUIContent updatePeriod = EditorGUIUtility.TrTextContent("Period", "Period in seconds at which real-time textures are updated (0.0 will update every frame)."); - 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."); - public readonly GUIContent initializationMode = EditorGUIUtility.TrTextContent("Initialization Mode", "Specify how the texture should be initialized."); - public readonly GUIContent initSource = EditorGUIUtility.TrTextContent("Source", "Specify if the texture is initialized by a Material or by a Texture and a Color."); - public readonly GUIContent initColor = EditorGUIUtility.TrTextContent("Color", "Color with which the Custom Render Texture is initialized."); - public readonly GUIContent initTexture = EditorGUIUtility.TrTextContent("Texture", "Texture with which the Custom Render Texture is initialized (multiplied by the initialization color)."); - public readonly GUIContent initMaterial = EditorGUIUtility.TrTextContent("Material", "Material with which the Custom Render Texture is initialized."); - public readonly GUIContent updateZoneSpace = EditorGUIUtility.TrTextContent("Update Zone Space", "Space in which the update zones are expressed (Normalized or Pixel space)."); - public readonly GUIContent updateZoneList = EditorGUIUtility.TrTextContent("Update Zones", "List of partial update zones."); - public readonly GUIContent cubemapFacesLabel = EditorGUIUtility.TrTextContent("Cubemap Faces", "Enable or disable rendering on each face of the cubemap."); - public readonly GUIContent updateZoneCenter = EditorGUIUtility.TrTextContent("Center", "Center of the partial update zone."); - public readonly GUIContent updateZoneSize = EditorGUIUtility.TrTextContent("Size", "Size of the partial update zone."); - public readonly GUIContent updateZoneRotation = EditorGUIUtility.TrTextContent("Rotation", "Rotation of the update zone."); - 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."); - public readonly GUIContent saveButton = EditorGUIUtility.TrTextContent("Save Texture", "Save the content of the Custom Render Texture to an EXR or PNG file."); - - public readonly GUIContent[] updateModeStrings = { EditorGUIUtility.TextContent("OnLoad"), EditorGUIUtility.TextContent("Realtime"), EditorGUIUtility.TrTextContent("OnDemand") }; - public readonly int[] updateModeValues = { (int)CustomRenderTextureUpdateMode.OnLoad, (int)CustomRenderTextureUpdateMode.Realtime, (int)CustomRenderTextureUpdateMode.OnDemand }; - - public readonly GUIContent[] initSourceStrings = { EditorGUIUtility.TextContent("Texture and Color"), EditorGUIUtility.TrTextContent("Material") }; - public readonly int[] initSourceValues = { (int)CustomRenderTextureInitializationSource.TextureAndColor, (int)CustomRenderTextureInitializationSource.Material }; - - public readonly GUIContent[] updateZoneSpaceStrings = { EditorGUIUtility.TextContent("Normalized"), EditorGUIUtility.TrTextContent("Pixel") }; - public readonly int[] updateZoneSpaceValues = { (int)CustomRenderTextureUpdateZoneSpace.Normalized, (int)CustomRenderTextureUpdateZoneSpace.Pixel }; - - public readonly GUIContent[] cubemapFaces = { EditorGUIUtility.TextContent("+X"), EditorGUIUtility.TextContent("-X"), EditorGUIUtility.TextContent("+Y"), EditorGUIUtility.TextContent("-Y"), EditorGUIUtility.TextContent("+Z"), EditorGUIUtility.TrTextContent("-Z") }; - } - - static Styles s_Styles = null; - private static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - - private SerializedProperty m_Material; - private SerializedProperty m_ShaderPass; - private SerializedProperty m_InitializationMode; - private SerializedProperty m_InitSource; - private SerializedProperty m_InitColor; - private SerializedProperty m_InitTexture; - private SerializedProperty m_InitMaterial; - private SerializedProperty m_UpdateMode; - private SerializedProperty m_UpdatePeriod; - private SerializedProperty m_UpdateZoneSpace; - private SerializedProperty m_UpdateZones; - private SerializedProperty m_WrapUpdateZones; - private SerializedProperty m_DoubleBuffered; - private SerializedProperty m_CubeFaceMask; - - private UnityEditorInternal.ReorderableList m_RectList; - - private const float kCubefaceToggleWidth = 70.0f; - private const float kRListAddButtonOffset = 16.0f; - private const float kIndentSize = 15.0f; - private const float kToggleWidth = 100.0f; - - readonly AnimatedBool m_ShowInitSourceAsMaterial = new AnimatedBool(); - - private bool multipleEditing { get { return targets.Length > 1; } } - - void UpdateZoneVec3PropertyField(Rect rect, SerializedProperty prop, GUIContent label, bool as2D) - { - EditorGUI.BeginProperty(rect, label, prop); - if (!as2D) - { - prop.vector3Value = EditorGUI.Vector3Field(rect, label, prop.vector3Value); - } - else - { - Vector2 newValue = EditorGUI.Vector2Field(rect, label, new Vector2(prop.vector3Value.x, prop.vector3Value.y)); - prop.vector3Value = new Vector3(newValue.x, newValue.y, prop.vector3Value.z); - } - EditorGUI.EndProperty(); - } - - private void OnDrawElement(Rect rect, int index, bool isActive, bool isFocused) - { - CustomRenderTexture customRenderTexture = target as CustomRenderTexture; - bool is3DTexture = customRenderTexture.dimension == UnityEngine.Rendering.TextureDimension.Tex3D; - bool isDoubleBuffer = customRenderTexture.doubleBuffered; - - var element = m_RectList.serializedProperty.GetArrayElementAtIndex(index); - - float lineHeight = EditorGUIUtility.singleLineHeight; - rect.y += EditorGUIUtility.standardVerticalSpacing; - rect.height = lineHeight; - EditorGUI.LabelField(rect, string.Format("Update Zone {0}", index)); - rect.y += lineHeight; - SerializedProperty centerProp = element.FindPropertyRelative("updateZoneCenter"); - UpdateZoneVec3PropertyField(rect, centerProp, styles.updateZoneCenter, !is3DTexture); - - rect.y += lineHeight + EditorGUIUtility.standardVerticalSpacing; - SerializedProperty sizeProp = element.FindPropertyRelative("updateZoneSize"); - UpdateZoneVec3PropertyField(rect, sizeProp, styles.updateZoneSize, !is3DTexture); - - if (!is3DTexture) - { - rect.y += (EditorGUIUtility.standardVerticalSpacing + lineHeight); - EditorGUI.PropertyField(rect, element.FindPropertyRelative("rotation"), styles.updateZoneRotation); - } - - // Shader pass - List shaderPassNames = new List(); - List shaderPassValues = new List(); - Material material = m_Material.objectReferenceValue as Material; - if (material != null) - { - BuildShaderPassPopup(material, shaderPassNames, shaderPassValues, true); - } - - using (new EditorGUI.DisabledScope(shaderPassNames.Count == 0)) - { - SerializedProperty passIndexProperty = element.FindPropertyRelative("passIndex"); - rect.y += (EditorGUIUtility.standardVerticalSpacing + lineHeight); - EditorGUI.IntPopup(rect, passIndexProperty, shaderPassNames.ToArray(), shaderPassValues.ToArray(), styles.shaderPass); - } - - if (isDoubleBuffer) - { - rect.y += (EditorGUIUtility.standardVerticalSpacing + lineHeight); - EditorGUI.PropertyField(rect, element.FindPropertyRelative("needSwap"), styles.updateZoneRotation); - } - } - - private void OnDrawHeader(Rect rect) - { - GUI.Label(rect, styles.updateZoneList); - } - - private void OnAdd(ReorderableList l) - { - CustomRenderTexture customRenderTexture = target as CustomRenderTexture; - var index = l.serializedProperty.arraySize; - l.serializedProperty.arraySize++; - l.index = index; - var element = l.serializedProperty.GetArrayElementAtIndex(index); - Vector3 defaultCenter = new Vector3(0.5f, 0.5f, 0.5f); - Vector3 defaultSize = new Vector3(1.0f, 1.0f, 1.0f); - if (customRenderTexture.updateZoneSpace == CustomRenderTextureUpdateZoneSpace.Pixel) - { - Vector3 size = new Vector3((float)customRenderTexture.width, (float)customRenderTexture.height, (float)customRenderTexture.volumeDepth); - defaultCenter.Scale(size); - defaultSize.Scale(size); - } - element.FindPropertyRelative("updateZoneCenter").vector3Value = defaultCenter; - element.FindPropertyRelative("updateZoneSize").vector3Value = defaultSize; - element.FindPropertyRelative("rotation").floatValue = 0.0f; - element.FindPropertyRelative("passIndex").intValue = -1; - element.FindPropertyRelative("needSwap").boolValue = false; - } - - private void OnRemove(ReorderableList l) - { - l.serializedProperty.arraySize--; - if (l.index == l.serializedProperty.arraySize) - { - l.index--; - } - } - - private float OnElementHeight(int index) - { - CustomRenderTexture customRenderTexture = target as CustomRenderTexture; - bool is3DTexture = customRenderTexture.dimension == UnityEngine.Rendering.TextureDimension.Tex3D; - bool isDoubleBuffer = customRenderTexture.doubleBuffered; - int lineCount = 4; // 4 lines : Index, Zone Origin, Zone Size, Shader Pass - if (!is3DTexture) // We don't support rotation for 3D textures so we don't show it. - lineCount++; - if (isDoubleBuffer) // "Swap" only shown for double buffered custom textures - lineCount++; - - return (EditorGUIUtility.singleLineHeight + 2.0f) * lineCount; - } - - protected override void OnEnable() - { - base.OnEnable(); - m_Material = serializedObject.FindProperty("m_Material"); - m_ShaderPass = serializedObject.FindProperty("m_ShaderPass"); - m_InitializationMode = serializedObject.FindProperty("m_InitializationMode"); - m_InitSource = serializedObject.FindProperty("m_InitSource"); - m_InitColor = serializedObject.FindProperty("m_InitColor"); - m_InitTexture = serializedObject.FindProperty("m_InitTexture"); - m_InitMaterial = serializedObject.FindProperty("m_InitMaterial"); - m_UpdateMode = serializedObject.FindProperty("m_UpdateMode"); - m_UpdatePeriod = serializedObject.FindProperty("m_UpdatePeriod"); - m_UpdateZoneSpace = serializedObject.FindProperty("m_UpdateZoneSpace"); - m_UpdateZones = serializedObject.FindProperty("m_UpdateZones"); - m_WrapUpdateZones = serializedObject.FindProperty("m_WrapUpdateZones"); - m_DoubleBuffered = serializedObject.FindProperty("m_DoubleBuffered"); - m_CubeFaceMask = serializedObject.FindProperty("m_CubemapFaceMask"); - - m_RectList = new UnityEditorInternal.ReorderableList(serializedObject, m_UpdateZones); - m_RectList.drawElementCallback = OnDrawElement; - m_RectList.drawHeaderCallback = OnDrawHeader; - m_RectList.onAddCallback = OnAdd; - m_RectList.onRemoveCallback = OnRemove; - m_RectList.elementHeightCallback = OnElementHeight; - m_RectList.footerHeight = 0; - - m_ShowInitSourceAsMaterial.value = !m_InitSource.hasMultipleDifferentValues && (m_InitSource.intValue == (int)CustomRenderTextureInitializationSource.Material); - m_ShowInitSourceAsMaterial.valueChanged.AddListener(Repaint); - } - - protected override void OnDisable() - { - base.OnDisable(); - - m_ShowInitSourceAsMaterial.valueChanged.RemoveListener(Repaint); - } - - void DisplayRenderTextureGUI() - { - OnRenderTextureGUI(0); - GUILayout.Space(10.0f); - } - - void BuildShaderPassPopup(Material material, List names, List values, bool addDefaultPass) - { - names.Clear(); - values.Clear(); - - int shaderPassCount = material.passCount; - for (int i = 0; i < shaderPassCount; ++i) - { - string name = material.GetPassName(i); - if (name.Length == 0) - { - name = string.Format("Unnamed Pass {0}", i); - } - names.Add(EditorGUIUtility.TextContent(name)); - values.Add(i); - } - - if (addDefaultPass) - { - CustomRenderTexture customRenderTexture = target as CustomRenderTexture; - - GUIContent defaultName = EditorGUIUtility.TextContent(string.Format("Default ({0})", names[customRenderTexture.shaderPass].text)); - names.Insert(0, defaultName); - values.Insert(0, -1); - } - } - - void DisplayMaterialGUI() - { - EditorGUILayout.PropertyField(m_Material, true); - EditorGUI.indentLevel++; - - List shaderPassNames = new List(); - List shaderPassValues = new List(); - Material material = m_Material.objectReferenceValue as Material; - if (material != null) - { - BuildShaderPassPopup(material, shaderPassNames, shaderPassValues, false); - } - - 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. - { - if (material != null) - EditorGUILayout.IntPopup(m_ShaderPass, shaderPassNames.ToArray(), shaderPassValues.ToArray(), styles.shaderPass); - } - - EditorGUI.indentLevel--; - } - - void DisplayInitializationGUI() - { - m_ShowInitSourceAsMaterial.target = !m_InitSource.hasMultipleDifferentValues && (m_InitSource.intValue == (int)CustomRenderTextureInitializationSource.Material); - - EditorGUILayout.IntPopup(m_InitializationMode, styles.updateModeStrings, styles.updateModeValues, styles.initializationMode); - EditorGUI.indentLevel++; - - EditorGUILayout.IntPopup(m_InitSource, styles.initSourceStrings, styles.initSourceValues, styles.initSource); - if (!m_InitSource.hasMultipleDifferentValues) - { - EditorGUI.indentLevel++; - if (EditorGUILayout.BeginFadeGroup(m_ShowInitSourceAsMaterial.faded)) - { - EditorGUILayout.PropertyField(m_InitMaterial, styles.initMaterial); - } - EditorGUILayout.EndFadeGroup(); - - if (EditorGUILayout.BeginFadeGroup(1 - m_ShowInitSourceAsMaterial.faded)) - { - EditorGUILayout.PropertyField(m_InitColor, styles.initColor); - EditorGUILayout.PropertyField(m_InitTexture, styles.initTexture); - } - EditorGUILayout.EndFadeGroup(); - EditorGUI.indentLevel--; - } - EditorGUI.indentLevel--; - } - - void DisplayUpdateGUI() - { - EditorGUILayout.IntPopup(m_UpdateMode, styles.updateModeStrings, styles.updateModeValues, styles.updateMode); - - EditorGUI.indentLevel++; - - if (m_UpdateMode.intValue == (int)CustomRenderTextureUpdateMode.Realtime) - { - EditorGUILayout.PropertyField(m_UpdatePeriod, styles.updatePeriod); - } - - EditorGUILayout.PropertyField(m_DoubleBuffered, styles.doubleBuffered); - EditorGUILayout.PropertyField(m_WrapUpdateZones, styles.wrapUpdateZones); - - bool isCubemap = true; - foreach (Object o in targets) - { - CustomRenderTexture customRenderTexture = o as CustomRenderTexture; - if (customRenderTexture != null && customRenderTexture.dimension != UnityEngine.Rendering.TextureDimension.Cube) - isCubemap = false; - } - - if (isCubemap) - { - int newFaceMask = 0; - int currentFaceMask = m_CubeFaceMask.intValue; - - var AllRects = GUILayoutUtility.GetRect(0, EditorGUIUtility.singleLineHeight * 3 + EditorGUIUtility.standardVerticalSpacing * 2); - EditorGUI.BeginProperty(AllRects, GUIContent.none, m_CubeFaceMask); - - Rect toggleRect = AllRects; - toggleRect.width = kToggleWidth; - toggleRect.height = EditorGUIUtility.singleLineHeight; - int faceIndex = 0; - { - Rect labelRect = AllRects; - EditorGUI.LabelField(labelRect, styles.cubemapFacesLabel); - - EditorGUI.BeginChangeCheck(); - for (int i = 0; i < 3; ++i) - { - toggleRect.x = AllRects.x + EditorGUIUtility.labelWidth - kIndentSize; - - { - for (int j = 0; j < 2; ++j) - { - bool value = EditorGUI.ToggleLeft(toggleRect, styles.cubemapFaces[faceIndex], (currentFaceMask & (1 << faceIndex)) != 0); - if (value) - newFaceMask |= (int)(1 << faceIndex); - faceIndex++; - - toggleRect.x += kToggleWidth; - } - } - - toggleRect.y += EditorGUIUtility.singleLineHeight; - } - if (EditorGUI.EndChangeCheck()) - { - m_CubeFaceMask.intValue = newFaceMask; - } - } - EditorGUI.EndProperty(); - } - - - EditorGUILayout.IntPopup(m_UpdateZoneSpace, styles.updateZoneSpaceStrings, styles.updateZoneSpaceValues, styles.updateZoneSpace); - - if (!multipleEditing) - { - 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. - // Reorderable list seems to not take indentLevel into account properly. - float indentSize = kIndentSize; - listRect.x += indentSize; - listRect.width -= indentSize; - m_RectList.DoList(listRect); - } - else - { - EditorGUILayout.HelpBox("Update Zones cannot be changed while editing multiple Custom Textures.", MessageType.Info); - } - - EditorGUI.indentLevel--; - } - - void DisplayCustomRenderTextureGUI() - { - CustomRenderTexture customRenderTexture = target as CustomRenderTexture; - - DisplayMaterialGUI(); - EditorGUILayout.Space(); - DisplayInitializationGUI(); - EditorGUILayout.Space(); - DisplayUpdateGUI(); - - EditorGUILayout.Space(); - - if (customRenderTexture.updateMode != CustomRenderTextureUpdateMode.Realtime && customRenderTexture.initializationMode == CustomRenderTextureUpdateMode.Realtime) - EditorGUILayout.HelpBox("Initialization Mode is set to Realtime but Update Mode is not. This will result in update never being visible.", MessageType.Warning); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - DisplayRenderTextureGUI(); - DisplayCustomRenderTextureGUI(); - - serializedObject.ApplyModifiedProperties(); - } - - [MenuItem("CONTEXT/CustomRenderTexture/Export", false)] - static void SaveToDisk(MenuCommand command) - { - CustomRenderTexture texture = command.context as CustomRenderTexture; - int width = texture.width; - int height = texture.height; - int depth = texture.volumeDepth; - - // 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). - bool isFormatHDR = IsHDRFormat(texture.format); - bool isFloatFormat = (texture.format == RenderTextureFormat.ARGBFloat || texture.format == RenderTextureFormat.RFloat); - - TextureFormat format = isFormatHDR ? TextureFormat.RGBAFloat : TextureFormat.RGBA32; - int finalWidth = width; - if (texture.dimension == UnityEngine.Rendering.TextureDimension.Tex3D) - finalWidth = width * depth; - else if (texture.dimension == UnityEngine.Rendering.TextureDimension.Cube) - finalWidth = width * 6; - - Texture2D tex = new Texture2D(finalWidth, height, format, false); - - // Read screen contents into the texture - if (texture.dimension == UnityEngine.Rendering.TextureDimension.Tex2D) - { - Graphics.SetRenderTarget(texture); - tex.ReadPixels(new Rect(0, 0, width, height), 0, 0); - tex.Apply(); - } - else if (texture.dimension == UnityEngine.Rendering.TextureDimension.Tex3D) - { - int offset = 0; - for (int i = 0; i < depth; ++i) - { - Graphics.SetRenderTarget(texture, 0, CubemapFace.Unknown, i); - tex.ReadPixels(new Rect(0, 0, width, height), offset, 0); - tex.Apply(); - offset += width; - } - } - else - { - int offset = 0; - for (int i = 0; i < 6; ++i) - { - Graphics.SetRenderTarget(texture, 0, (CubemapFace)i); - tex.ReadPixels(new Rect(0, 0, width, height), offset, 0); - tex.Apply(); - offset += width; - } - } - - // Encode texture into PNG - byte[] bytes = null; - if (isFormatHDR) - bytes = tex.EncodeToEXR(Texture2D.EXRFlags.CompressZIP | (isFloatFormat ? Texture2D.EXRFlags.OutputAsFloat : 0)); - else - bytes = tex.EncodeToPNG(); - - Object.DestroyImmediate(tex); - - var extension = isFormatHDR ? "exr" : "png"; - - var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(texture.GetInstanceID())); - string assetPath = EditorUtility.SaveFilePanel("Save Custom Render Texture", directory, texture.name, extension); - if (!string.IsNullOrEmpty(assetPath)) - { - File.WriteAllBytes(assetPath, bytes); - AssetDatabase.Refresh(); - } - } - - override public string GetInfoString() - { - return base.GetInfoString(); - } - } -} diff --git a/Editor/Mono/Inspector/DirectorEditor.cs b/Editor/Mono/Inspector/DirectorEditor.cs deleted file mode 100644 index 529a671e18..0000000000 --- a/Editor/Mono/Inspector/DirectorEditor.cs +++ /dev/null @@ -1,299 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditorInternal; -using UnityEngine.Playables; - -namespace UnityEditor -{ - [CustomEditor(typeof(PlayableDirector))] - [CanEditMultipleObjects] - internal class DirectorEditor : Editor - { - private static class Styles - { - public static readonly GUIContent PlayableText = EditorGUIUtility.TrTextContent("Playable"); - public static readonly GUIContent InitialTimeContent = EditorGUIUtility.TrTextContent("Initial Time", "The time at which the Playable will begin playing"); - public static readonly GUIContent TimeContent = EditorGUIUtility.TrTextContent("Current Time", "The current Playable time"); - public static readonly GUIContent InitialStateContent = EditorGUIUtility.TrTextContent("Play On Awake", "Whether the Playable should be playing after it loads"); - public static readonly GUIContent UpdateMethod = EditorGUIUtility.TrTextContent("Update Method", "Controls how the Playable updates every frame"); - public static readonly GUIContent WrapModeContent = EditorGUIUtility.TrTextContent("Wrap Mode", "Controls the behaviour of evaluating the Playable outside its duration"); - public static readonly GUIContent NoBindingsContent = EditorGUIUtility.TrTextContent("This channel will not playback because it is not currently assigned"); - public static readonly GUIContent BindingsTitleContent = EditorGUIUtility.TrTextContent("Bindings"); - } - - private SerializedProperty m_PlayableAsset; - private SerializedProperty m_InitialState; - private SerializedProperty m_WrapMode; - private SerializedProperty m_InitialTime; - private SerializedProperty m_UpdateMethod; - private SerializedProperty m_SceneBindings; - - private GUIContent m_AnimatorContent; - private GUIContent m_AudioContent; - private GUIContent m_VideoContent; - private GUIContent m_ScriptContent; - private Texture m_DefaultScriptContentTexture; - - private struct BindingPropertyPair - { - public PlayableBinding binding; - public SerializedProperty property; - } - - private List m_BindingPropertiesCache = new List(); - - private PlayableBinding[] m_SynchedPlayableBindings = null; - - public void OnEnable() - { - m_PlayableAsset = serializedObject.FindProperty("m_PlayableAsset"); - m_InitialState = serializedObject.FindProperty("m_InitialState"); - m_WrapMode = serializedObject.FindProperty("m_WrapMode"); - m_UpdateMethod = serializedObject.FindProperty("m_DirectorUpdateMode"); - m_InitialTime = serializedObject.FindProperty("m_InitialTime"); - m_SceneBindings = serializedObject.FindProperty("m_SceneBindings"); - - m_AnimatorContent = new GUIContent(AssetPreview.GetMiniTypeThumbnail(typeof(Animator))); - m_AudioContent = new GUIContent(AssetPreview.GetMiniTypeThumbnail(typeof(AudioSource))); - m_VideoContent = new GUIContent(AssetPreview.GetMiniTypeThumbnail(typeof(RenderTexture))); - m_ScriptContent = new GUIContent(EditorGUIUtility.FindTexture(typeof(ScriptableObject))); - m_DefaultScriptContentTexture = m_ScriptContent.image; - } - - public override void OnInspectorGUI() - { - if (PlayableAssetOutputsChanged()) - SynchSceneBindings(); - - serializedObject.Update(); - - if (PropertyFieldAsObject(m_PlayableAsset, Styles.PlayableText, typeof(PlayableAsset), false)) - { - serializedObject.ApplyModifiedProperties(); - SynchSceneBindings(); - - // some editors (like Timeline) needs to repaint when the playable asset changes - InternalEditorUtility.RepaintAllViews(); - } - - EditorGUILayout.PropertyField(m_UpdateMethod, Styles.UpdateMethod); - - var rect = EditorGUILayout.GetControlRect(true); - var label = EditorGUI.BeginProperty(rect, Styles.InitialStateContent, m_InitialState); - bool playOnAwake = m_InitialState.enumValueIndex != (int)PlayState.Paused; - EditorGUI.BeginChangeCheck(); - playOnAwake = EditorGUI.Toggle(rect, label, playOnAwake); - if (EditorGUI.EndChangeCheck()) - { - m_InitialState.enumValueIndex = (int)(playOnAwake ? PlayState.Playing : PlayState.Paused); - } - EditorGUI.EndProperty(); - - EditorGUILayout.PropertyField(m_WrapMode, Styles.WrapModeContent); - - PropertyFieldAsFloat(m_InitialTime, Styles.InitialTimeContent); - - if (Application.isPlaying) - { - // time field isn't functional in Editor, unless the sequencer window is open, - // at which point it isn't required. In playmode it can provide valuable feedback, - // and allow the user to scrub and debug without the sequencer window - CurrentTimeField(); - } - - if (targets.Length == 1) - { - var playableAsset = m_PlayableAsset.objectReferenceValue as PlayableAsset; - if (playableAsset != null) - DoDirectorBindingInspector(); - } - - serializedObject.ApplyModifiedProperties(); - } - - private bool PlayableAssetOutputsChanged() - { - var playableAsset = m_PlayableAsset.objectReferenceValue as PlayableAsset; - - if (m_SynchedPlayableBindings == null) - return playableAsset != null; - - if (playableAsset == null) - return true; - - if (playableAsset.outputs.Count() != m_SynchedPlayableBindings.Length) - return true; - - return playableAsset.outputs.Where((t, i) => t.sourceObject != m_SynchedPlayableBindings[i].sourceObject).Any(); - } - - private void BindingInspector(SerializedProperty bindingProperty, PlayableBinding binding) - { - if (binding.sourceObject == null) - return; - - var source = bindingProperty.objectReferenceValue; - - if (binding.streamType == DataStreamType.Audio) - { - m_AudioContent.text = binding.streamName; - m_AudioContent.tooltip = source == null ? Styles.NoBindingsContent.text : string.Empty; - PropertyFieldAsObject(bindingProperty, m_AudioContent, typeof(AudioSource), true); - } - else if (binding.streamType == DataStreamType.Animation) - { - m_AnimatorContent.text = binding.streamName; - m_AnimatorContent.tooltip = source is GameObject ? Styles.NoBindingsContent.text : string.Empty; - PropertyFieldAsObject(bindingProperty, m_AnimatorContent, typeof(Animator), true, true); - } - if (binding.streamType == DataStreamType.Texture) - { - m_VideoContent.text = binding.streamName; - m_VideoContent.tooltip = source == null ? Styles.NoBindingsContent.text : string.Empty; - PropertyFieldAsObject(bindingProperty, m_VideoContent, typeof(RenderTexture), false); - } - else if (binding.streamType == DataStreamType.None) - { - m_ScriptContent.text = binding.streamName; - m_ScriptContent.tooltip = source == null ? Styles.NoBindingsContent.text : string.Empty; - m_ScriptContent.image = AssetPreview.GetMiniTypeThumbnail(binding.sourceBindingType) ?? m_DefaultScriptContentTexture; - - if (binding.sourceBindingType != null && typeof(UnityEngine.Object).IsAssignableFrom(binding.sourceBindingType)) - PropertyFieldAsObject(bindingProperty, m_ScriptContent, binding.sourceBindingType, true); - } - } - - private void DoDirectorBindingInspector() - { - if (!m_BindingPropertiesCache.Any()) - return; - - m_SceneBindings.isExpanded = EditorGUILayout.Foldout(m_SceneBindings.isExpanded, Styles.BindingsTitleContent); - if (m_SceneBindings.isExpanded) - { - EditorGUI.indentLevel++; - - foreach (var bindingPropertyPair in m_BindingPropertiesCache) - { - BindingInspector(bindingPropertyPair.property, bindingPropertyPair.binding); - } - - EditorGUI.indentLevel--; - } - } - - void SynchSceneBindings() - { - if (targets.Length > 1) - return; - - var director = (PlayableDirector)target; - var playableAsset = m_PlayableAsset.objectReferenceValue as PlayableAsset; - - m_BindingPropertiesCache.Clear(); - m_SynchedPlayableBindings = null; - - if (playableAsset == null) - return; - - var bindings = playableAsset.outputs; - m_SynchedPlayableBindings = bindings.ToArray(); - - foreach (var binding in m_SynchedPlayableBindings) - { - if (!director.HasGenericBinding(binding.sourceObject)) - director.SetGenericBinding(binding.sourceObject, null); - } - - serializedObject.Update(); - - var serializedProperties = new SerializedProperty[m_SceneBindings.arraySize]; - for (int i = 0; i < m_SceneBindings.arraySize; ++i) - { - serializedProperties[i] = m_SceneBindings.GetArrayElementAtIndex(i); - } - - foreach (var binding in m_SynchedPlayableBindings) - { - foreach (var prop in serializedProperties) - { - if (prop.FindPropertyRelative("key").objectReferenceValue == binding.sourceObject) - { - m_BindingPropertiesCache.Add(new BindingPropertyPair { binding = binding, property = prop.FindPropertyRelative("value")}); - break; - } - } - } - } - - // To show the current time field in play mode - public override bool RequiresConstantRepaint() - { - return Application.isPlaying; - } - - private static void PropertyFieldAsFloat(SerializedProperty property, GUIContent title) - { - Rect rect = EditorGUILayout.GetControlRect(); - title = EditorGUI.BeginProperty(rect, title, property); - EditorGUI.BeginChangeCheck(); - float newValue = EditorGUI.FloatField(rect, title, (float)property.doubleValue); - if (EditorGUI.EndChangeCheck()) - { - property.doubleValue = newValue; - } - EditorGUI.EndProperty(); - } - - private static bool PropertyFieldAsObject(SerializedProperty property, GUIContent title, Type objType, bool allowSceneObjects, bool useBehaviourGameObject = false) - { - Rect rect = EditorGUILayout.GetControlRect(); - var label = EditorGUI.BeginProperty(rect, title, property); - EditorGUI.BeginChangeCheck(); - var result = EditorGUI.ObjectField(rect, label, property.objectReferenceValue, objType, allowSceneObjects); - bool changed = EditorGUI.EndChangeCheck(); - - if (changed) - { - if (useBehaviourGameObject) - { - var behaviour = result as Behaviour; - property.objectReferenceValue = behaviour != null ? behaviour.gameObject : null; - } - else - { - property.objectReferenceValue = result; - } - } - - EditorGUI.EndProperty(); - - return changed; - } - - // Does not use Properties because time is not a serialized property - private void CurrentTimeField() - { - if (targets.Length == 1) - { - var director = (PlayableDirector)target; - EditorGUI.BeginChangeCheck(); - float t = EditorGUILayout.FloatField(Styles.TimeContent, (float)director.time); - if (EditorGUI.EndChangeCheck()) - { - director.time = t; - } - } - else - { - EditorGUILayout.TextField(Styles.TimeContent, EditorGUI.mixedValueContent.text); - } - } - } -} diff --git a/Editor/Mono/Inspector/DistanceJoint2DEditor.cs b/Editor/Mono/Inspector/DistanceJoint2DEditor.cs deleted file mode 100644 index 8ee81b7cc4..0000000000 --- a/Editor/Mono/Inspector/DistanceJoint2DEditor.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(DistanceJoint2D))] - [CanEditMultipleObjects] - internal class DistanceJoint2DEditor : AnchoredJoint2DEditor - { - new public void OnSceneGUI() - { - var distanceJoint2D = (DistanceJoint2D)target; - - // Ignore disabled joint. - if (!distanceJoint2D.enabled) - return; - - // Start and end points for distance gizmo - Vector3 anchor = TransformPoint(distanceJoint2D.transform, distanceJoint2D.anchor); - Vector3 connectedAnchor = distanceJoint2D.connectedAnchor; - - // If connectedBody present, convert the position to match that - if (distanceJoint2D.connectedBody) - connectedAnchor = TransformPoint(distanceJoint2D.connectedBody.transform, connectedAnchor); - - DrawDistanceGizmo(anchor, connectedAnchor, distanceJoint2D.distance); - - base.OnSceneGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/DoubleCurvePresetLibraryInspector.cs b/Editor/Mono/Inspector/DoubleCurvePresetLibraryInspector.cs deleted file mode 100644 index 4c17a55e18..0000000000 --- a/Editor/Mono/Inspector/DoubleCurvePresetLibraryInspector.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(DoubleCurvePresetLibrary))] - internal class DoubleCurvePresetLibraryEditor : Editor - { - private GenericPresetLibraryInspector m_GenericPresetLibraryInspector; - - public void OnEnable() - { - m_GenericPresetLibraryInspector = new GenericPresetLibraryInspector(target, GetHeader(), null); - m_GenericPresetLibraryInspector.presetSize = new Vector2(72, 20); - m_GenericPresetLibraryInspector.lineSpacing = 5f; - } - - private string GetHeader() - { - return "Particle Curve Preset Library"; - } - - public void OnDestroy() - { - if (m_GenericPresetLibraryInspector != null) - m_GenericPresetLibraryInspector.OnDestroy(); - } - - public override void OnInspectorGUI() - { - if (m_GenericPresetLibraryInspector != null) - m_GenericPresetLibraryInspector.OnInspectorGUI(); - } - } -} // namespace diff --git a/Editor/Mono/Inspector/EdgeCollider2DEditor.cs b/Editor/Mono/Inspector/EdgeCollider2DEditor.cs deleted file mode 100644 index 1819ae59fd..0000000000 --- a/Editor/Mono/Inspector/EdgeCollider2DEditor.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - -namespace UnityEditor -{ - [CustomEditor(typeof(EdgeCollider2D))] - [CanEditMultipleObjects] - internal class EdgeCollider2DEditor : Collider2DEditorBase - { - private PolygonEditorUtility m_PolyUtility = new PolygonEditorUtility(); - - private SerializedProperty m_EdgeRadius; - private SerializedProperty m_Points; - - public override void OnEnable() - { - base.OnEnable(); - - m_EdgeRadius = serializedObject.FindProperty("m_EdgeRadius"); - m_Points = serializedObject.FindProperty("m_Points"); - m_Points.isExpanded = false; - } - - public override void OnInspectorGUI() - { - BeginColliderInspector(); - base.OnInspectorGUI(); - - EditorGUILayout.PropertyField(m_EdgeRadius); - - if (targets.Length == 1) - { - EditorGUI.BeginDisabledGroup(editingCollider); - EditorGUILayout.PropertyField(m_Points, true); - EditorGUI.EndDisabledGroup(); - } - - EndColliderInspector(); - - FinalizeInspectorGUI(); - } - - protected override void OnEditStart() - { - m_PolyUtility.StartEditing(target as Collider2D); - } - - protected override void OnEditEnd() - { - m_PolyUtility.StopEditing(); - } - - public void OnSceneGUI() - { - if (!editingCollider) - return; - - m_PolyUtility.OnSceneGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/EditMode.cs b/Editor/Mono/Inspector/EditMode.cs deleted file mode 100644 index 5a6092340b..0000000000 --- a/Editor/Mono/Inspector/EditMode.cs +++ /dev/null @@ -1,354 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - // TODO: We need to make the editMode state e.g a string so users are able to extend with new edit mode states - // and so we still can serialize it (to survive assembly reloads) - - [InitializeOnLoad] - public class EditMode - { - private static class Styles - { - public static readonly GUIStyle multiButtonStyle; - public static readonly GUIStyle singleButtonStyle; - - static Styles() - { - multiButtonStyle = "Command"; - - singleButtonStyle = new GUIStyle("Button"); - singleButtonStyle.padding = multiButtonStyle.padding; - singleButtonStyle.margin = multiButtonStyle.margin; - } - } - - private const string kEditModeStringKey = "EditModeState"; - private const string kPrevToolStringKey = "EditModePrevTool"; - private const string kOwnerStringKey = "EditModeOwner"; - private static bool s_Debug = false; - - static EditMode() - { - ownerID = SessionState.GetInt(kOwnerStringKey, ownerID); - editMode = (SceneViewEditMode)SessionState.GetInt(kEditModeStringKey, (int)editMode); - toolBeforeEnteringEditMode = (Tool)SessionState.GetInt(kPrevToolStringKey, (int)toolBeforeEnteringEditMode); - Selection.selectionChanged += OnSelectionChange; - - if (s_Debug) - Debug.Log("EditMode static constructor: " + ownerID + " " + editMode + " " + toolBeforeEnteringEditMode); - } - - private const float k_EditColliderbuttonWidth = 33; - private const float k_EditColliderbuttonHeight = 23; - private const float k_SpaceBetweenLabelAndButton = 5; - - public static OnEditModeStopFunc onEditModeEndDelegate; - public delegate void OnEditModeStopFunc(Editor editor); - internal static event Action editModeEnded; - - public static OnEditModeStartFunc onEditModeStartDelegate; - public delegate void OnEditModeStartFunc(Editor editor, SceneViewEditMode mode); - internal static event Action editModeStarted; - - private static Tool s_ToolBeforeEnteringEditMode = Tool.Move; - private static int s_OwnerID; - private static SceneViewEditMode s_EditMode; - - public enum SceneViewEditMode - { - None = 0, - Collider, - ClothConstraints, - ClothSelfAndInterCollisionParticles, - ReflectionProbeBox, - ReflectionProbeOrigin, - LightProbeProxyVolumeBox, - LightProbeProxyVolumeOrigin, - LightProbeGroup, - ParticleSystemCollisionModulePlanesMove, - ParticleSystemCollisionModulePlanesRotate, - JointAngularLimits, - GridPainting, - GridPicking, - GridEraser, - GridFloodFill, - GridBox, - GridSelect, - GridMove, - } - - private static Tool toolBeforeEnteringEditMode - { - get { return s_ToolBeforeEnteringEditMode; } - set - { - s_ToolBeforeEnteringEditMode = value; - SessionState.SetInt(kPrevToolStringKey, (int)s_ToolBeforeEnteringEditMode); - if (s_Debug) - Debug.Log("Set toolBeforeEnteringEditMode " + value); - } - } - - public static bool IsOwner(Editor editor) - { - return IsOwner((IToolModeOwner)editor); - } - - internal static bool IsOwner(IToolModeOwner owner) - { - return owner.GetInstanceID() == s_OwnerID; - } - - private static int ownerID - { - get - { - return s_OwnerID; - } - set - { - s_OwnerID = value; - SessionState.SetInt(kOwnerStringKey, s_OwnerID); - if (s_Debug) - Debug.Log("Set ownerID " + value); - } - } - - public static SceneViewEditMode editMode - { - get - { - return s_EditMode; - } - private set - { - if (s_EditMode == SceneViewEditMode.None && value != SceneViewEditMode.None) - { - // We consider Tool.None to be exotic fallback state and want to always recover to something else (like move) instead - toolBeforeEnteringEditMode = Tools.current != Tool.None ? Tools.current : Tool.Move; - Tools.current = Tool.None; - } - else if (s_EditMode != SceneViewEditMode.None && value == SceneViewEditMode.None) - { - ResetToolToPrevious(); - } - s_EditMode = value; - SessionState.SetInt(kEditModeStringKey, (int)s_EditMode); - if (s_Debug) - Debug.Log("Set editMode " + s_EditMode); - } - } - - public static void ResetToolToPrevious() - { - if (Tools.current == Tool.None) - Tools.current = toolBeforeEnteringEditMode; - } - - static void EndSceneViewEditing() - { - ChangeEditMode(SceneViewEditMode.None, new Bounds(Vector3.zero, Vector3.positiveInfinity), null); - } - - public static void OnSelectionChange() - { - IToolModeOwner owner = InternalEditorUtility.GetObjectFromInstanceID(ownerID) as IToolModeOwner; - if (owner != null && owner.ModeSurvivesSelectionChange((int)s_EditMode)) - return; - QuitEditMode(); - } - - public static void QuitEditMode() - { - if (Tools.current == Tool.None && editMode != SceneViewEditMode.None) - ResetToolToPrevious(); - EndSceneViewEditing(); - } - - static void DetectMainToolChange() - { - if (Tools.current != Tool.None && editMode != SceneViewEditMode.None) - EndSceneViewEditing(); - } - - [Obsolete("Use signature passing Func rather than Bounds.")] - public static void DoEditModeInspectorModeButton(SceneViewEditMode mode, string label, GUIContent icon, Bounds bounds, Editor caller) - { - DoEditModeInspectorModeButton(mode, label, icon, () => bounds, (IToolModeOwner)caller); - } - - public static void DoEditModeInspectorModeButton(SceneViewEditMode mode, string label, GUIContent icon, Func getBoundsOfTargets, Editor caller) - { - DoEditModeInspectorModeButton(mode, label, icon, getBoundsOfTargets, (IToolModeOwner)caller); - } - - internal static void DoEditModeInspectorModeButton(SceneViewEditMode mode, string label, GUIContent icon, IToolModeOwner owner) - { - DoEditModeInspectorModeButton(mode, label, icon, null, owner); - } - - private static void DoEditModeInspectorModeButton(SceneViewEditMode mode, string label, GUIContent icon, Func getBoundsOfTargets, IToolModeOwner owner) - { - DetectMainToolChange(); - - Rect rect = EditorGUILayout.GetControlRect(true, k_EditColliderbuttonHeight, Styles.singleButtonStyle); - Rect buttonRect = new Rect(rect.xMin + EditorGUIUtility.labelWidth, rect.yMin, k_EditColliderbuttonWidth, k_EditColliderbuttonHeight); - - GUIContent labelContent = new GUIContent(label); - Vector2 labelSize = GUI.skin.label.CalcSize(labelContent); - - Rect labelRect = new Rect( - buttonRect.xMax + k_SpaceBetweenLabelAndButton, - rect.yMin + (rect.height - labelSize.y) * .5f, - labelSize.x, - rect.height); - - int callerID = owner.GetInstanceID(); - bool modeEnabled = editMode == mode && ownerID == callerID; - - EditorGUI.BeginChangeCheck(); - - bool toggleEnabled = false; - using (new EditorGUI.DisabledScope(!owner.areToolModesAvailable)) - { - toggleEnabled = GUI.Toggle(buttonRect, modeEnabled, icon, Styles.singleButtonStyle); - GUI.Label(labelRect, label); - } - - if (EditorGUI.EndChangeCheck()) - { - ChangeEditMode(toggleEnabled ? mode : SceneViewEditMode.None, getBoundsOfTargets == null ? owner.GetWorldBoundsOfTargets() : getBoundsOfTargets(), owner); - } - } - - [Obsolete("Use signature passing Func rather than Bounds.")] - public static void DoInspectorToolbar(SceneViewEditMode[] modes, GUIContent[] guiContents, Bounds bounds, Editor caller) - { - DoInspectorToolbar(modes, guiContents, () => bounds, (IToolModeOwner)caller); - } - - public static void DoInspectorToolbar(SceneViewEditMode[] modes, GUIContent[] guiContents, Func getBoundsOfTargets, Editor caller) - { - DoInspectorToolbar(modes, guiContents, getBoundsOfTargets, (IToolModeOwner)caller); - } - - internal static void DoInspectorToolbar(SceneViewEditMode[] modes, GUIContent[] guiContents, IToolModeOwner owner) - { - DoInspectorToolbar(modes, guiContents, null, owner); - } - - private static void DoInspectorToolbar(SceneViewEditMode[] modes, GUIContent[] guiContents, Func getBoundsOfTargets, IToolModeOwner owner) - { - DetectMainToolChange(); - - int callerID = owner.GetInstanceID(); - - int selectedIndex = ArrayUtility.IndexOf(modes, editMode); - if (ownerID != callerID) - selectedIndex = -1; - EditorGUI.BeginChangeCheck(); - int newSelectedIndex = selectedIndex; - using (new EditorGUI.DisabledScope(!owner.areToolModesAvailable)) - newSelectedIndex = GUILayout.Toolbar(selectedIndex, guiContents, Styles.multiButtonStyle); - if (EditorGUI.EndChangeCheck()) - { - // Buttons can be toggled - SceneViewEditMode newEditMode = newSelectedIndex == selectedIndex ? SceneViewEditMode.None : modes[newSelectedIndex]; - ChangeEditMode(newEditMode, getBoundsOfTargets == null ? owner.GetWorldBoundsOfTargets() : getBoundsOfTargets(), owner); - } - } - - public static void ChangeEditMode(SceneViewEditMode mode, Bounds bounds, Editor caller) - { - ChangeEditMode(mode, bounds, (IToolModeOwner)caller); - } - - internal static void ChangeEditMode(SceneViewEditMode mode, IToolModeOwner owner) - { - ChangeEditMode(mode, owner.GetWorldBoundsOfTargets(), owner); - } - - internal static void ChangeEditMode(SceneViewEditMode mode, Bounds bounds, IToolModeOwner owner) - { - IToolModeOwner oldOwner = InternalEditorUtility.GetObjectFromInstanceID(ownerID) as IToolModeOwner; - - editMode = mode; - - ownerID = mode != SceneViewEditMode.None ? owner.GetInstanceID() : 0; - - if (onEditModeEndDelegate != null && oldOwner is Editor) - onEditModeEndDelegate(oldOwner as Editor); - if (editModeEnded != null) - editModeEnded(oldOwner); - - if (editMode != SceneViewEditMode.None) - { - if (onEditModeStartDelegate != null && owner is Editor) - onEditModeStartDelegate(owner as Editor, editMode); - if (editModeStarted != null) - editModeStarted(owner, editMode); - } - - EditModeChanged(bounds); - - InspectorWindow.RepaintAllInspectors(); - } - - // We make sure edited object is seen by the camera. We need object bounds to do that check. - private static void EditModeChanged(Bounds bounds) - { - // When entering the edit mode, check if the collider is seen by the scene view camera. If not, then we frame it. - if (editMode != SceneViewEditMode.None && SceneView.lastActiveSceneView != null && SceneView.lastActiveSceneView.camera != null) - if (!SeenByCamera(SceneView.lastActiveSceneView.camera, bounds)) - SceneView.lastActiveSceneView.Frame(bounds, EditorApplication.isPlaying); - - SceneView.RepaintAll(); - } - - private static bool SeenByCamera(Camera camera, Bounds bounds) - { - return AnyPointSeenByCamera(camera, GetPoints(bounds)); - } - - private static Vector3[] GetPoints(Bounds bounds) - { - return BoundsToPoints(bounds); - } - - private static Vector3[] BoundsToPoints(Bounds bounds) - { - Vector3[] result = new Vector3[8]; - result[0] = new Vector3(bounds.min.x, bounds.min.y, bounds.min.z); - result[1] = new Vector3(bounds.min.x, bounds.min.y, bounds.max.z); - result[2] = new Vector3(bounds.min.x, bounds.max.y, bounds.min.z); - result[3] = new Vector3(bounds.min.x, bounds.max.y, bounds.max.z); - result[4] = new Vector3(bounds.max.x, bounds.min.y, bounds.min.z); - result[5] = new Vector3(bounds.max.x, bounds.min.y, bounds.max.z); - result[6] = new Vector3(bounds.max.x, bounds.max.y, bounds.min.z); - result[7] = new Vector3(bounds.max.x, bounds.max.y, bounds.max.z); - return result; - } - - private static bool AnyPointSeenByCamera(Camera camera, Vector3[] points) - { - foreach (Vector3 point in points) - if (PointSeenByCamera(camera, point)) - return true; - - return false; - } - - private static bool PointSeenByCamera(Camera camera, Vector3 point) - { - Vector3 viewPoint = camera.WorldToViewportPoint(point); - return viewPoint.x > 0.0f && viewPoint.x < 1.0f && viewPoint.y > 0.0f && viewPoint.y < 1.0f; - } - } -} diff --git a/Editor/Mono/Inspector/Editor.cs b/Editor/Mono/Inspector/Editor.cs deleted file mode 100644 index 78e8f54229..0000000000 --- a/Editor/Mono/Inspector/Editor.cs +++ /dev/null @@ -1,752 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.Experimental.AssetImporters; -using UnityEngine; - -using UnityObject = UnityEngine.Object; - -namespace UnityEditor -{ - internal interface IPreviewable - { - void Initialize(UnityObject[] targets); - - UnityObject target { get; } - bool MoveNextTarget(); - void ResetTarget(); - - bool HasPreviewGUI(); - GUIContent GetPreviewTitle(); - void DrawPreview(Rect previewArea); - void OnPreviewGUI(Rect r, GUIStyle background); - void OnInteractivePreviewGUI(Rect r, GUIStyle background); - void OnPreviewSettings(); - string GetInfoString(); - - void ReloadPreviewInstances(); - } - - public class ObjectPreview : IPreviewable - { - class Styles - { - public GUIStyle preBackground = "preBackground"; - public GUIStyle preBackgroundSolid = new GUIStyle("preBackground"); - public GUIStyle previewMiniLabel = new GUIStyle(EditorStyles.whiteMiniLabel); - public GUIStyle dropShadowLabelStyle = new GUIStyle("PreOverlayLabel"); - - public Styles() - { - preBackgroundSolid.overflow = preBackgroundSolid.border; - previewMiniLabel.alignment = TextAnchor.UpperCenter; - } - } - static Styles s_Styles; - - const int kPreviewLabelHeight = 12; - const int kPreviewMinSize = 55; - const int kGridTargetCount = 25; - const int kGridSpacing = 10; - const int kPreviewLabelPadding = 5; - - protected UnityObject[] m_Targets; - protected int m_ReferenceTargetIndex; - - public virtual void Initialize(UnityObject[] targets) - { - m_ReferenceTargetIndex = 0; - m_Targets = targets; - } - - public virtual bool MoveNextTarget() - { - m_ReferenceTargetIndex++; - - return (m_ReferenceTargetIndex < m_Targets.Length - 1); - } - - public virtual void ResetTarget() - { - m_ReferenceTargetIndex = 0; - } - - public virtual UnityObject target - { - get - { - return m_Targets[m_ReferenceTargetIndex]; - } - } - - public virtual bool HasPreviewGUI() - { - return false; - } - - public virtual GUIContent GetPreviewTitle() - { - GUIContent guiContent = new GUIContent(); - if (m_Targets.Length == 1) - guiContent.text = target.name; - else - { - guiContent.text = m_Targets.Length + " "; - if (target is MonoBehaviour) - guiContent.text += MonoScript.FromMonoBehaviour(target as MonoBehaviour).GetClass().Name; - else - guiContent.text += ObjectNames.NicifyVariableName(ObjectNames.GetClassName(target)); - - guiContent.text += "s"; - } - - return guiContent; - } - - public virtual void OnPreviewGUI(Rect r, GUIStyle background) - { - if (Event.current.type == EventType.Repaint) - background.Draw(r, false, false, false, false); - } - - public virtual void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - OnPreviewGUI(r, background); - } - - public virtual void OnPreviewSettings() - { - } - - public virtual string GetInfoString() - { - return ""; - } - - public void DrawPreview(Rect previewArea) - { - DrawPreview(this, previewArea, m_Targets); - } - - public virtual void ReloadPreviewInstances() - { - } - - internal static void DrawPreview(IPreviewable defaultPreview, Rect previewArea, UnityObject[] targets) - { - if (s_Styles == null) - s_Styles = new Styles(); - - string text = string.Empty; - Event evt = Event.current; - - // If multiple targets, draw a grid of previews - if (targets.Length > 1) - { - // Draw the previews inside the region of the background that's solid colored - Rect previewPositionInner = new RectOffset(16, 16, 20, 25).Remove(previewArea); - - // Number of previews to aim at - int maxRows = Mathf.Max(1, Mathf.FloorToInt((previewPositionInner.height + kGridSpacing) / (kPreviewMinSize + kGridSpacing + kPreviewLabelHeight))); - int maxCols = Mathf.Max(1, Mathf.FloorToInt((previewPositionInner.width + kGridSpacing) / (kPreviewMinSize + kGridSpacing))); - int countWithMinimumSize = maxRows * maxCols; - int neededCount = Mathf.Min(targets.Length, kGridTargetCount); - - // Get number of columns and rows - bool fixedSize = true; - int[] division = new int[2] { maxCols, maxRows }; - if (neededCount < countWithMinimumSize) - { - division = GetGridDivision(previewPositionInner, neededCount, kPreviewLabelHeight); - fixedSize = false; - } - - // The available cells in the grid may be slightly higher than what was aimed at. - // If the number of targets is also higher, we might as well fill in the remaining cells. - int count = Mathf.Min(division[0] * division[1], targets.Length); - - // Calculations become simpler if we add one spacing to the width and height, - // so there is the same number of spaces and previews. - previewPositionInner.width += kGridSpacing; - previewPositionInner.height += kGridSpacing; - - Vector2 cellSize = new Vector2( - Mathf.FloorToInt(previewPositionInner.width / division[0] - kGridSpacing), - Mathf.FloorToInt(previewPositionInner.height / division[1] - kGridSpacing) - ); - float previewSize = Mathf.Min(cellSize.x, cellSize.y - kPreviewLabelHeight); - if (fixedSize) - previewSize = Mathf.Min(previewSize, kPreviewMinSize); - - bool selectingOne = (evt.type == EventType.MouseDown && evt.button == 0 && evt.clickCount == 2 && - previewArea.Contains(evt.mousePosition)); - - defaultPreview.ResetTarget(); - for (int i = 0; i < count; i++) - { - Rect r = new Rect( - previewPositionInner.x + (i % division[0]) * previewPositionInner.width / division[0], - previewPositionInner.y + (i / division[0]) * previewPositionInner.height / division[1], - cellSize.x, - cellSize.y - ); - - if (selectingOne && r.Contains(Event.current.mousePosition)) - { - if (defaultPreview.target is AssetImporter) - // The new selection should be the asset itself, not the importer - Selection.objects = new[] { AssetDatabase.LoadAssetAtPath(((AssetImporter)defaultPreview.target).assetPath)}; - else - Selection.objects = new UnityObject[] {defaultPreview.target}; - } - - // Make room for label underneath - r.height -= kPreviewLabelHeight; - // Make preview square - Rect rSquare = new Rect(r.x + (r.width - previewSize) * 0.5f, r.y + (r.height - previewSize) * 0.5f, previewSize, previewSize); - - // Draw preview inside a group to prevent overdraw - // @TODO: Make style with solid color that doesn't have overdraw - GUI.BeginGroup(rSquare); - Editor.m_AllowMultiObjectAccess = false; - defaultPreview.OnInteractivePreviewGUI(new Rect(0, 0, previewSize, previewSize), s_Styles.preBackgroundSolid); - Editor.m_AllowMultiObjectAccess = true; - GUI.EndGroup(); - - // Draw the name of the object - r.y = rSquare.yMax; - r.height = 16; - GUI.Label(r, targets[i].name, s_Styles.previewMiniLabel); - defaultPreview.MoveNextTarget(); - } - 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 - - if (Event.current.type == EventType.Repaint) - text = string.Format("Previewing {0} of {1} Objects", count, targets.Length); - } - // If only a single target, just draw that one - else - { - defaultPreview.OnInteractivePreviewGUI(previewArea, s_Styles.preBackground); - - if (Event.current.type == EventType.Repaint) - { - // TODO: This should probably be calculated during import and stored together with the asset somehow. Or maybe not. Not sure, really... - text = defaultPreview.GetInfoString(); - if (text != string.Empty) - { - text = text.Replace("\n", " "); - text = string.Format("{0}\n{1}", defaultPreview.target.name, text); - } - } - } - - // Draw the asset info. - if (Event.current.type == EventType.Repaint && text != string.Empty) - { - var textHeight = s_Styles.dropShadowLabelStyle.CalcHeight(GUIContent.Temp(text), previewArea.width); - EditorGUI.DropShadowLabel(new Rect(previewArea.x, previewArea.yMax - textHeight - kPreviewLabelPadding, previewArea.width, textHeight), text); - } - } - - // Get the number or columns and rows for a grid with a certain minimum number of cells - // such that the cells are as close to square as possible. - private static int[] GetGridDivision(Rect rect, int minimumNr, int labelHeight) - { - // The edge size of a square calculated based on area - float approxSize = Mathf.Sqrt(rect.width * rect.height / minimumNr); - int xCount = Mathf.FloorToInt(rect.width / approxSize); - int yCount = Mathf.FloorToInt(rect.height / (approxSize + labelHeight)); - // This heuristic is not entirely optimal and could probably be improved - while (xCount * yCount < minimumNr) - { - float ratioIfXInc = AbsRatioDiff((xCount + 1) / rect.width, yCount / (rect.height - yCount * labelHeight)); - float ratioIfYInc = AbsRatioDiff(xCount / rect.width, (yCount + 1) / (rect.height - (yCount + 1) * labelHeight)); - if (ratioIfXInc < ratioIfYInc) - { - xCount++; - if (xCount * yCount > minimumNr) - yCount = Mathf.CeilToInt((float)minimumNr / xCount); - } - else - { - yCount++; - if (xCount * yCount > minimumNr) - xCount = Mathf.CeilToInt((float)minimumNr / yCount); - } - } - return new int[] { xCount, yCount }; - } - - private static float AbsRatioDiff(float x, float y) - { - return Mathf.Max(x / y, y / x); - } - } - - internal interface IToolModeOwner - { - bool areToolModesAvailable { get; } - int GetInstanceID(); - Bounds GetWorldBoundsOfTargets(); - bool ModeSurvivesSelectionChange(int toolMode); - } - - [AttributeUsage(AttributeTargets.Class)] - public class CustomEditorForRenderPipelineAttribute : CustomEditor - { - internal Type renderPipelineType; - - public CustomEditorForRenderPipelineAttribute(Type inspectedType, Type renderPipeline) : base(inspectedType) - { - renderPipelineType = renderPipeline; - } - - public CustomEditorForRenderPipelineAttribute(Type inspectedType, Type renderPipeline, bool editorForChildClasses) : base(inspectedType, editorForChildClasses) - { - renderPipelineType = renderPipeline; - } - } - - [ExcludeFromObjectFactory] - public partial class Editor : ScriptableObject, IPreviewable, IToolModeOwner - { - static Styles s_Styles; - - private const float kImageSectionWidth = 44; - internal delegate void OnEditorGUIDelegate(Editor editor, Rect drawRect); - internal static OnEditorGUIDelegate OnPostIconGUI = null; - - internal virtual IPreviewable preview - { - get - { - if (m_DummyPreview == null) - { - m_DummyPreview = new ObjectPreview(); - m_DummyPreview.Initialize(targets); - } - return m_DummyPreview; - } - } - - internal PropertyHandlerCache propertyHandlerCache - { - get { return m_PropertyHandlerCache; } - } - - class Styles - { - public GUIContent open = EditorGUIUtility.TrTextContent("Open"); - public GUIStyle inspectorBig = new GUIStyle(EditorStyles.inspectorBig); - public GUIStyle inspectorBigInner = new GUIStyle("IN BigTitle inner"); - public GUIStyle centerStyle = new GUIStyle(); - - public Styles() - { - centerStyle.alignment = TextAnchor.MiddleCenter; - inspectorBig.padding.bottom -= 1; - } - } - - bool IToolModeOwner.areToolModesAvailable - { - get - { - // tool modes not available when the target is a prefab parent - return !EditorUtility.IsPersistent(target); - } - } - - Bounds IToolModeOwner.GetWorldBoundsOfTargets() - { - var result = new Bounds(); - bool initialized = false; - - foreach (var t in targets) - { - if (t == null) - continue; - - Bounds targetBounds = GetWorldBoundsOfTarget(t); - - if (!initialized) - result = targetBounds; - result.Encapsulate(targetBounds); - - initialized = true; - } - - return result; - } - - internal virtual Bounds GetWorldBoundsOfTarget(UnityObject targetObject) - { - return targetObject is Component ? ((Component)targetObject).gameObject.CalculateBounds() : new Bounds(); - } - - bool IToolModeOwner.ModeSurvivesSelectionChange(int toolMode) - { - return false; - } - - internal static bool DoDrawDefaultInspector(SerializedObject obj) - { - EditorGUI.BeginChangeCheck(); - obj.Update(); - - // Loop through properties and create one field (including children) for each top level property. - SerializedProperty property = obj.GetIterator(); - bool expanded = true; - while (property.NextVisible(expanded)) - { - using (new EditorGUI.DisabledScope("m_Script" == property.propertyPath)) - { - EditorGUILayout.PropertyField(property, true); - } - expanded = false; - } - - obj.ApplyModifiedProperties(); - return EditorGUI.EndChangeCheck(); - } - - internal bool DoDrawDefaultInspector() - { - return DoDrawDefaultInspector(serializedObject); - } - - // This is the method that should be called from externally e.g. myEditor.DrawHeader (); - // Do not make this method virtual - override OnHeaderGUI instead. - public void DrawHeader() - { - // If we call DrawHeader from inside an an editor's OnInspectorGUI call, we have to do special handling. - // (See DrawHeaderFromInsideHierarchy for details.) - // We know we're inside the OnInspectorGUI block (or a similar vertical block) if hierarchyMode is set to true. - if (EditorGUIUtility.hierarchyMode) - DrawHeaderFromInsideHierarchy(); - else - OnHeaderGUI(); - } - - // This is the method to override to create custom header GUI. - // Do not make this method internal or public - call DrawHeader instead. - protected virtual void OnHeaderGUI() - { - DrawHeaderGUI(this, targetTitle); - } - - internal virtual void OnHeaderControlsGUI() - { - // Ensure we take up the same amount of height as regular controls - GUILayoutUtility.GetRect(10, 10, 16, 16, EditorStyles.layerMaskField); - - GUILayout.FlexibleSpace(); - - bool showOpenButton = true; - // only show open button for the main object of an asset and for AssetImportInProgressProxy (asset not yet imported) - if (!(this is AssetImporterEditor) && !(targets[0] is AssetImportInProgressProxy)) - { - var assetPath = AssetDatabase.GetAssetPath(targets[0]); - // Don't show open button if the target is not an asset - if (!AssetDatabase.IsMainAsset(targets[0])) - showOpenButton = false; - // Don't show open button if the target has an importer - // (but ignore AssetImporters since they're not shown) - AssetImporter importer = AssetImporter.GetAtPath(assetPath); - if (importer && importer.GetType() != typeof(AssetImporter)) - showOpenButton = false; - } - - if (showOpenButton && !ShouldHideOpenButton()) - { - if (GUILayout.Button(s_Styles.open, EditorStyles.miniButton)) - { - if (this is AssetImporterEditor) - AssetDatabase.OpenAsset((this as AssetImporterEditor).assetTargets); - else - AssetDatabase.OpenAsset(targets); - GUIUtility.ExitGUI(); - } - } - } - - protected virtual bool ShouldHideOpenButton() - { - return false; - } - - internal virtual void OnHeaderIconGUI(Rect iconRect) - { - if (s_Styles == null) - s_Styles = new Styles(); - - Texture2D icon = null; - if (!HasPreviewGUI()) - { - // Fetch isLoadingAssetPreview to ensure that there is no situation where a preview needs a repaint because it hasn't finished loading yet. - bool isLoadingAssetPreview = AssetPreview.IsLoadingAssetPreview(target.GetInstanceID()); - icon = AssetPreview.GetAssetPreview(target); - if (!icon) - { - // We have a static preview it just hasn't been loaded yet. Repaint until we have it loaded. - if (isLoadingAssetPreview) - Repaint(); - icon = AssetPreview.GetMiniThumbnail(target); - } - } - - if (HasPreviewGUI()) - // OnPreviewGUI must have all events; not just Repaint, or else the control IDs will mis-match. - OnPreviewGUI(iconRect, s_Styles.inspectorBigInner); - else if (icon) - GUI.Label(iconRect, icon, s_Styles.centerStyle); - } - - internal virtual void OnHeaderTitleGUI(Rect titleRect, string header) - { - titleRect.yMin -= 2; - titleRect.yMax += 2; - GUI.Label(titleRect, header, EditorStyles.largeLabel); - } - - internal virtual void DrawHeaderHelpAndSettingsGUI(Rect r) - { - // Help - var settingsSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.titleSettingsIcon); - - float currentOffset = settingsSize.x; - - const int kTopMargin = 5; - // Settings - Rect settingsRect = new Rect(r.xMax - currentOffset, r.y + kTopMargin, settingsSize.x, settingsSize.y); - if (EditorGUI.DropdownButton(settingsRect, EditorGUI.GUIContents.titleSettingsIcon, FocusType.Passive, - EditorStyles.iconButton)) - EditorUtility.DisplayObjectContextMenu(settingsRect, targets, 0); - currentOffset += settingsSize.x; - - // Show Editor Header Items. - EditorGUIUtility.DrawEditorHeaderItems(new Rect(r.xMax - currentOffset, r.y + kTopMargin, settingsSize.x, settingsSize.y), targets); - } - - // If we call DrawHeaderGUI from inside an an editor's OnInspectorGUI call, we have to do special handling. - // Since OnInspectorGUI is wrapped inside a BeginVertical/EndVertical block that adds padding, - // and we don't want this padding for headers, we have to stop the vertical block, - // draw the header, and then start a new vertical block with the same style. - private void DrawHeaderFromInsideHierarchy() - { - GUIStyle style = GUILayoutUtility.topLevel.style; - EditorGUILayout.EndVertical(); - OnHeaderGUI(); - EditorGUILayout.BeginVertical(style); - } - - internal static Rect DrawHeaderGUI(Editor editor, string header) - { - return DrawHeaderGUI(editor, header, 0f); - } - - internal static Rect DrawHeaderGUI(Editor editor, string header, float leftMargin) - { - if (s_Styles == null) - s_Styles = new Styles(); - - GUILayout.BeginHorizontal(s_Styles.inspectorBig); - GUILayout.Space(kImageSectionWidth - 6); - GUILayout.BeginVertical(); - GUILayout.Space(19); - GUILayout.BeginHorizontal(); - if (leftMargin > 0f) - GUILayout.Space(leftMargin); - if (editor) - editor.OnHeaderControlsGUI(); - else - EditorGUILayout.GetControlRect(); - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - Rect fullRect = GUILayoutUtility.GetLastRect(); - - // Content rect - Rect r = new Rect(fullRect.x + leftMargin, fullRect.y, fullRect.width - leftMargin, fullRect.height); - - // Icon - Rect iconRect = new Rect(r.x + 6, r.y + 6, 32, 32); - - if (editor) - editor.OnHeaderIconGUI(iconRect); - else - GUI.Label(iconRect, AssetPreview.GetMiniTypeThumbnail(typeof(UnityObject)), s_Styles.centerStyle); - - if (editor) - editor.DrawPostIconContent(iconRect); - - // Title - Rect titleRect = new Rect(r.x + kImageSectionWidth, r.y + 6, r.width - kImageSectionWidth - 38 - 4, 16); - if (editor) - editor.OnHeaderTitleGUI(titleRect, header); - else - GUI.Label(titleRect, header, EditorStyles.largeLabel); - - // Help and Settings - if (editor) - editor.DrawHeaderHelpAndSettingsGUI(r); - - // Context Menu - Event evt = Event.current; - if (editor != null && evt.type == EventType.MouseDown && evt.button == 1 && r.Contains(evt.mousePosition)) - { - EditorUtility.DisplayObjectContextMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), editor.targets, 0); - evt.Use(); - } - - return fullRect; - } - - internal void DrawPostIconContent(Rect iconRect) - { - if (OnPostIconGUI != null) - { - // Post icon draws 16 x 16 at bottom right corner - const float k_Size = 16; - Rect drawRect = iconRect; - drawRect.x = (drawRect.xMax - k_Size) + 4; // Move slightly outside bounds for overlap effect. - drawRect.y = (drawRect.yMax - k_Size) + 1; - drawRect.width = k_Size; - drawRect.height = k_Size; - OnPostIconGUI(this, drawRect); - } - } - - internal void DrawPostIconContent() - { - if (Event.current.type == EventType.Repaint) - { - Rect iconRect = GUILayoutUtility.GetLastRect(); - DrawPostIconContent(iconRect); - } - } - - public virtual void DrawPreview(Rect previewArea) - { - ObjectPreview.DrawPreview(this, previewArea, targets); - } - - // Auxiliary method that determines whether this editor has a set of public properties and, as thus, - // can be expanded via a foldout. This is used in order to determine whether a foldout needs to be - // rendered on top of the inspector title bar or not. Some examples of editors that don't require - // a foldout are GUI Layer and Audio Listener. - internal bool CanBeExpandedViaAFoldout() - { - if (m_SerializedObject == null) - m_SerializedObject = new SerializedObject(targets, m_Context); - else - m_SerializedObject.Update(); - m_SerializedObject.inspectorMode = m_InspectorMode; - - SerializedProperty property = m_SerializedObject.GetIterator(); - - bool analyzePropertyChildren = true; - while (property.NextVisible(analyzePropertyChildren)) - { - if (EditorGUI.GetPropertyHeight(property, null, true) > 0) - { - return true; - } - analyzePropertyChildren = false; - } - - return false; - } - - static internal bool IsAppropriateFileOpenForEdit(UnityObject assetObject) - { - string message; - return IsAppropriateFileOpenForEdit(assetObject, out message); - } - - static internal bool IsAppropriateFileOpenForEdit(UnityObject assetObject, out string message) - { - message = string.Empty; - - // Need to check for null early to avoid an exception being thrown in - // AssetDatabase.IsNativeAsset(). One of these exceptions, unhandled, - // caused case 930291 and case 930931. For both cases, the UI broke because - // it was exiting early due to the exception. - if (assetObject == null) - return false; - - StatusQueryOptions opts = EditorUserSettings.allowAsyncStatusUpdate ? StatusQueryOptions.UseCachedAsync : StatusQueryOptions.UseCachedIfPossible; - if (AssetDatabase.IsNativeAsset(assetObject)) - { - if (!AssetDatabase.IsOpenForEdit(assetObject, out message, opts)) - return false; - } - else if (AssetDatabase.IsForeignAsset(assetObject)) - { - if (!AssetDatabase.IsMetaFileOpenForEdit(assetObject, out message, opts)) - return false; - } - - return true; - } - - internal virtual bool IsEnabled() - { - // disable editor if any objects in the editor are not editable - foreach (UnityObject target in targets) - { - if ((target.hideFlags & HideFlags.NotEditable) != 0) - return false; - - if (EditorUtility.IsPersistent(target) && !IsAppropriateFileOpenForEdit(target)) - return false; - } - - return true; - } - - internal bool IsOpenForEdit() - { - string message; - return IsOpenForEdit(out message); - } - - internal bool IsOpenForEdit(out string message) - { - message = ""; - - foreach (UnityObject target in targets) - { - if (EditorUtility.IsPersistent(target) && !IsAppropriateFileOpenForEdit(target)) - return false; - } - - return true; - } - - public virtual bool UseDefaultMargins() - { - return true; - } - - public void Initialize(UnityObject[] targets) - { - throw new InvalidOperationException("You shouldn't call Initialize for Editors"); - } - - public bool MoveNextTarget() - { - referenceTargetIndex++; - return referenceTargetIndex < targets.Length; - } - - public void ResetTarget() - { - referenceTargetIndex = 0; - } - } -} diff --git a/Editor/Mono/Inspector/EditorDragging.cs b/Editor/Mono/Inspector/EditorDragging.cs deleted file mode 100644 index d456704eb2..0000000000 --- a/Editor/Mono/Inspector/EditorDragging.cs +++ /dev/null @@ -1,274 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEditor; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - internal class EditorDragging - { - const string k_DraggingModeKey = "InspectorEditorDraggingMode"; - - InspectorWindow m_InspectorWindow; - bool m_TargetAbove; - int m_TargetIndex = -1; - int m_LastIndex = -1; - float m_LastMarkerY = 0f; - - enum DraggingMode - { - NotApplicable, - Component, - Script, - } - - static class Styles - { - public static readonly GUIStyle insertionMarker = "InsertionMarker"; - } - - public EditorDragging(InspectorWindow inspectorWindow) - { - m_InspectorWindow = inspectorWindow; - } - - public void HandleDraggingToEditor(int editorIndex, Rect dragRect, Rect contentRect, ActiveEditorTracker tracker) - { - if (dragRect.height == 0f) - return; - - if (contentRect.height == 0f) - contentRect = dragRect; - - var targetHeight = 8f; - var targetRect = new Rect(contentRect.x, contentRect.yMax - (targetHeight - 2f), contentRect.width, targetHeight * 2f + 1f); - - var markerY = contentRect.yMax; - - m_LastIndex = editorIndex; - m_LastMarkerY = markerY; - - HandleEditorDragging(editorIndex, targetRect, markerY, false, tracker); - } - - public void HandleDraggingToBottomArea(Rect bottomRect, ActiveEditorTracker tracker) - { - var editorIndex = m_LastIndex; - if (editorIndex >= 0 && editorIndex < tracker.activeEditors.Length) - HandleEditorDragging(editorIndex, bottomRect, m_LastMarkerY, true, tracker); - } - - void HandleEditorDragging(int editorIndex, Rect targetRect, float markerY, bool bottomTarget, ActiveEditorTracker tracker) - { - var evt = Event.current; - switch (evt.type) - { - case EventType.DragUpdated: - if (targetRect.Contains(evt.mousePosition)) - { - var draggingMode = DragAndDrop.GetGenericData(k_DraggingModeKey) as DraggingMode ? ; - if (!draggingMode.HasValue) - { - var draggedObjects = DragAndDrop.objectReferences; - - if (draggedObjects.Length == 0) - draggingMode = DraggingMode.NotApplicable; - else if (draggedObjects.All(o => o is Component && !(o is Transform))) - draggingMode = DraggingMode.Component; - else if (draggedObjects.All(o => o is MonoScript)) - draggingMode = DraggingMode.Script; - else - draggingMode = DraggingMode.NotApplicable; - - DragAndDrop.SetGenericData(k_DraggingModeKey, draggingMode); - } - - if (draggingMode.Value != DraggingMode.NotApplicable) - { - var editors = tracker.activeEditors; - var draggedObjects = DragAndDrop.objectReferences; - - if (bottomTarget) - { - m_TargetAbove = false; - m_TargetIndex = m_LastIndex; - } - else - { - m_TargetAbove = evt.mousePosition.y < targetRect.y + targetRect.height / 2f; - m_TargetIndex = editorIndex; - - if (m_TargetAbove) - { - m_TargetIndex++; - while (m_TargetIndex < editors.Length && m_InspectorWindow.ShouldCullEditor(editors, m_TargetIndex)) - m_TargetIndex++; - - if (m_TargetIndex == editors.Length) - { - m_TargetIndex = -1; - return; - } - } - } - - if (m_TargetAbove && m_InspectorWindow.EditorHasLargeHeader(m_TargetIndex, editors)) - { - m_TargetIndex--; - while (m_TargetIndex >= 0 && m_InspectorWindow.ShouldCullEditor(editors, m_TargetIndex)) - m_TargetIndex--; - - if (m_TargetIndex == -1) - return; - - m_TargetAbove = false; - } - - if (draggingMode.Value == DraggingMode.Script) - { - // Validate dragging scripts - // Always allow script dragging, instead fail during DragPerform with a dialog box - DragAndDrop.visualMode = DragAndDropVisualMode.Link; - } - else - { - // Validate dragging components - var valid = false; - if (editors[m_TargetIndex].targets.All(t => t is Component)) - { - var targetComponents = editors[m_TargetIndex].targets.Cast().ToArray(); - var sourceComponents = DragAndDrop.objectReferences.Cast().ToArray(); - valid = MoveOrCopyComponents(sourceComponents, targetComponents, EditorUtility.EventHasDragCopyModifierPressed(evt), true); - } - - if (valid) - DragAndDrop.visualMode = EditorUtility.EventHasDragCopyModifierPressed(evt) ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.Move; - else - { - DragAndDrop.visualMode = DragAndDropVisualMode.None; - m_TargetIndex = -1; - return; - } - } - - evt.Use(); - } - } - else - m_TargetIndex = -1; - break; - - case EventType.DragPerform: - if (m_TargetIndex != -1) - { - var draggingMode = DragAndDrop.GetGenericData(k_DraggingModeKey) as DraggingMode ? ; - if (!draggingMode.HasValue || draggingMode.Value == DraggingMode.NotApplicable) - { - m_TargetIndex = -1; - return; - } - - var editors = tracker.activeEditors; - if (!editors[m_TargetIndex].targets.All(t => t is Component)) - return; - - var targetComponents = editors[m_TargetIndex].targets.Cast().ToArray(); - - if (draggingMode.Value == DraggingMode.Script) - { - var scripts = DragAndDrop.objectReferences.Cast(); - - // Ensure all script components can be added - var valid = true; - foreach (var targetComponent in targetComponents) - { - var gameObject = targetComponent.gameObject; - if (scripts.Any(s => !ComponentUtility.WarnCanAddScriptComponent(targetComponent.gameObject, s))) - { - valid = false; - break; - } - } - - if (valid) - { - Undo.IncrementCurrentGroup(); - var undoGroup = Undo.GetCurrentGroup(); - - // Add script components - var index = 0; - var addedComponents = new Component[targetComponents.Length * scripts.Count()]; - foreach (var targetComponent in targetComponents) - { - var gameObject = targetComponent.gameObject; - foreach (var script in scripts) - addedComponents[index++] = Undo.AddComponent(gameObject, script.GetClass()); - } - - // Move added components relative to target components - if (!ComponentUtility.MoveComponentsRelativeToComponents(addedComponents, targetComponents, m_TargetAbove)) - { - // Revert added components if move operation fails (e.g. user aborts when asked to break prefab instance) - Undo.RevertAllDownToGroup(undoGroup); - } - } - } - else - { - // Handle dragging components - var sourceComponents = DragAndDrop.objectReferences.Cast().ToArray(); - if (sourceComponents.Length == 0 || targetComponents.Length == 0) - return; - - MoveOrCopyComponents(sourceComponents, targetComponents, EditorUtility.EventHasDragCopyModifierPressed(evt), false); - } - - m_TargetIndex = -1; - DragAndDrop.AcceptDrag(); - evt.Use(); - EditorGUIUtility.ExitGUI(); - } - break; - - case EventType.DragExited: - m_TargetIndex = -1; - break; - - case EventType.Repaint: - if (m_TargetIndex != -1 && targetRect.Contains(evt.mousePosition)) - { - var markerRect = new Rect(targetRect.x, markerY, targetRect.width, 3f); - if (!m_TargetAbove) - markerRect.y += 2f; - - Styles.insertionMarker.Draw(markerRect, false, false, false, false); - } - break; - } - } - - bool MoveOrCopyComponents(Component[] sourceComponents, Component[] targetComponents, bool copy, bool validateOnly) - { - // This version only allows reordering of components - - if (copy) - return false; - - if (sourceComponents.Length == 1 && targetComponents.Length == 1) - { - if (sourceComponents[0].gameObject != targetComponents[0].gameObject) - return false; - - return ComponentUtility.MoveComponentRelativeToComponent(sourceComponents[0], targetComponents[0], m_TargetAbove, validateOnly); - } - else - return ComponentUtility.MoveComponentsRelativeToComponents(sourceComponents, targetComponents, m_TargetAbove, validateOnly); - } - - } -} diff --git a/Editor/Mono/Inspector/EditorSettingsInspector.cs b/Editor/Mono/Inspector/EditorSettingsInspector.cs deleted file mode 100644 index 7955261bd8..0000000000 --- a/Editor/Mono/Inspector/EditorSettingsInspector.cs +++ /dev/null @@ -1,715 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEditorInternal; -using UnityEngine; -using UnityEditor.Hardware; -using UnityEditor.VersionControl; -using UnityEditor.Collaboration; -using UnityEditor.Web; - -namespace UnityEditor -{ - [CustomEditor(typeof(EditorSettings))] - internal class EditorSettingsInspector : ProjectSettingsBaseEditor - { - struct PopupElement - { - public readonly string id; - public readonly bool requiresTeamLicense; - public readonly GUIContent content; - - public bool Enabled - { - get { return (!requiresTeamLicense || InternalEditorUtility.HasTeamLicense()); } - } - - public PopupElement(string content) - : this(content, false) - { - } - - public PopupElement(string content, bool requiresTeamLicense) - { - this.id = content; - this.content = new GUIContent(content); - this.requiresTeamLicense = requiresTeamLicense; - } - } - - private PopupElement[] vcDefaultPopupList = - { - new PopupElement(ExternalVersionControl.Disabled), - new PopupElement(ExternalVersionControl.Generic), - }; - - private PopupElement[] vcPopupList = null; - - private PopupElement[] serializationPopupList = - { - new PopupElement("Mixed"), - new PopupElement("Force Binary"), - new PopupElement("Force Text"), - }; - - private PopupElement[] behaviorPopupList = - { - new PopupElement("3D"), - new PopupElement("2D"), - }; - - private PopupElement[] spritePackerPopupList = - { - new PopupElement("Disabled"), - new PopupElement("Enabled For Builds(Legacy Sprite Packer)"), - new PopupElement("Always Enabled(Legacy Sprite Packer)"), - new PopupElement("Enabled For Builds"), - new PopupElement("Always Enabled"), - }; - - private PopupElement[] lineEndingsPopupList = - { - new PopupElement("OS Native"), - new PopupElement("Unix"), - new PopupElement("Windows"), - }; - - private PopupElement[] spritePackerPaddingPowerPopupList = - { - new PopupElement("1"), - new PopupElement("2"), - new PopupElement("3"), - }; - - private PopupElement[] remoteDevicePopupList; - private DevDevice[] remoteDeviceList; - private PopupElement[] remoteCompressionList = - { - new PopupElement("JPEG"), - new PopupElement("PNG"), - }; - private PopupElement[] remoteResolutionList = - { - new PopupElement("Downsize"), - new PopupElement("Normal"), - }; - private PopupElement[] remoteJoystickSourceList = - { - new PopupElement("Remote"), - new PopupElement("Local"), - }; - - private string[] logLevelPopupList = - { - "Verbose", "Info", "Notice", "Fatal" - }; - - private string[] semanticMergePopupList = - { - "Off", "Premerge", "Ask" - }; - - private PopupElement[] etcTextureCompressorPopupList = - { - new PopupElement("Legacy"), - new PopupElement("Default"), - new PopupElement("Custom"), - }; - - private PopupElement[] etcTextureFastCompressorPopupList = - { - new PopupElement("etcpak"), - new PopupElement("ETCPACK Fast"), - }; - - private PopupElement[] etcTextureNormalCompressorPopupList = - { - new PopupElement("etcpak"), - new PopupElement("ETCPACK Fast"), - new PopupElement("Etc2Comp Fast"), - new PopupElement("Etc2Comp Best"), - }; - - private PopupElement[] etcTextureBestCompressorPopupList = - { - new PopupElement("Etc2Comp Fast"), - new PopupElement("Etc2Comp Best"), - new PopupElement("ETCPACK Best"), - }; - - public void OnEnable() - { - Plugin[] availvc = Plugin.availablePlugins; - - List popupArray = new List(vcDefaultPopupList); - foreach (var plugin in availvc) - { - popupArray.Add(new PopupElement(plugin.name, true)); - } - - - vcPopupList = popupArray.ToArray(); - - DevDeviceList.Changed += OnDeviceListChanged; - BuildRemoteDeviceList(); - } - - public void OnDisable() - { - DevDeviceList.Changed -= OnDeviceListChanged; - } - - void OnDeviceListChanged() - { - BuildRemoteDeviceList(); - } - - void BuildRemoteDeviceList() - { - var devices = new List(); - var popupList = new List(); - - devices.Add(DevDevice.none); - popupList.Add(new PopupElement("None")); - - // TODO: move Android stuff to editor extension - devices.Add(new DevDevice("Any Android Device", "Any Android Device", - "virtual", "Android", DevDeviceState.Connected, - DevDeviceFeatures.RemoteConnection)); - popupList.Add(new PopupElement("Any Android Device")); - - foreach (var device in DevDeviceList.GetDevices()) - { - bool supportsRemote = (device.features & DevDeviceFeatures.RemoteConnection) != 0; - if (!device.isConnected || !supportsRemote) - continue; - - devices.Add(device); - popupList.Add(new PopupElement(device.name)); - } - - remoteDeviceList = devices.ToArray(); - remoteDevicePopupList = popupList.ToArray(); - } - - public override void OnInspectorGUI() - { - // GUI.enabled hack because we don't want some controls to be disabled if the EditorSettings.asset is locked - // since some of the controls are not dependent on the Editor Settings asset. Unfortunately, this assumes - // that the editor will only be disabled because of version control locking which may change in the future. - var editorEnabled = GUI.enabled; - - ShowUnityRemoteGUI(editorEnabled); - - GUILayout.Space(10); - bool collabEnabled = Collab.instance.IsCollabEnabledForCurrentProject(); - using (new EditorGUI.DisabledScope(!collabEnabled)) - { - GUI.enabled = !collabEnabled; - GUILayout.Label("Version Control", EditorStyles.boldLabel); - - ExternalVersionControl selvc = EditorSettings.externalVersionControl; - CreatePopupMenuVersionControl("Mode", vcPopupList, selvc, SetVersionControlSystem); - GUI.enabled = editorEnabled && !collabEnabled; - } - if (collabEnabled) - { - EditorGUILayout.HelpBox("Version Control not available when using Collaboration feature.", MessageType.Warning); - } - - if (VersionControlSystemHasGUI()) - { - GUI.enabled = true; - bool hasRequiredFields = false; - - if (EditorSettings.externalVersionControl == ExternalVersionControl.Generic || - EditorSettings.externalVersionControl == ExternalVersionControl.Disabled) - { - // no specific UI for these VCS types - } - else - { - ConfigField[] configFields = Provider.GetActiveConfigFields(); - - hasRequiredFields = true; - - foreach (ConfigField field in configFields) - { - string newVal; - string oldVal = EditorUserSettings.GetConfigValue(field.name); - if (field.isPassword) - { - newVal = EditorGUILayout.PasswordField(field.label, oldVal); - if (newVal != oldVal) - EditorUserSettings.SetPrivateConfigValue(field.name, newVal); - } - else - { - newVal = EditorGUILayout.TextField(field.label, oldVal); - if (newVal != oldVal) - EditorUserSettings.SetConfigValue(field.name, newVal); - } - - if (field.isRequired && string.IsNullOrEmpty(newVal)) - hasRequiredFields = false; - } - } - - // Log level popup - string logLevel = EditorUserSettings.GetConfigValue("vcSharedLogLevel"); - int idx = System.Array.FindIndex(logLevelPopupList, (item) => item.ToLower() == logLevel); - if (idx == -1) - { - logLevel = "notice"; - idx = System.Array.FindIndex(logLevelPopupList, (item) => item.ToLower() == logLevel); - if (idx == -1) - { - idx = 0; - } - logLevel = logLevelPopupList[idx]; - EditorUserSettings.SetConfigValue("vcSharedLogLevel", logLevel); - } - int newIdx = EditorGUILayout.Popup("Log Level", idx, logLevelPopupList); - if (newIdx != idx) - { - EditorUserSettings.SetConfigValue("vcSharedLogLevel", logLevelPopupList[newIdx].ToLower()); - } - - GUI.enabled = editorEnabled; - - string osState = "Connected"; - if (Provider.onlineState == OnlineState.Updating) - osState = "Connecting..."; - else if (Provider.onlineState == OnlineState.Offline) - osState = "Disconnected"; - - EditorGUILayout.LabelField("Status", osState); - - if (Provider.onlineState != OnlineState.Online && !string.IsNullOrEmpty(Provider.offlineReason)) - { - GUI.enabled = false; - GUILayout.TextArea(Provider.offlineReason); - GUI.enabled = editorEnabled; - } - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - GUI.enabled = hasRequiredFields && Provider.onlineState != OnlineState.Updating; - if (GUILayout.Button("Connect", EditorStyles.miniButton)) - Provider.UpdateSettings(); - GUILayout.EndHorizontal(); - - EditorUserSettings.AutomaticAdd = EditorGUILayout.Toggle("Automatic add", EditorUserSettings.AutomaticAdd); - - if (Provider.requiresNetwork) - { - bool workOfflineNew = EditorGUILayout.Toggle("Work Offline", EditorUserSettings.WorkOffline); // Enabled has a slightly different behaviour - if (workOfflineNew != EditorUserSettings.WorkOffline) - { - // On toggling on show a warning - if (workOfflineNew && !EditorUtility.DisplayDialog("Confirm working offline", "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.", "Work offline", "Cancel")) - { - workOfflineNew = false; // User cancelled working offline - } - EditorUserSettings.WorkOffline = workOfflineNew; - EditorApplication.RequestRepaintAllViews(); - } - - EditorUserSettings.allowAsyncStatusUpdate = EditorGUILayout.Toggle("Allow Async Update", EditorUserSettings.allowAsyncStatusUpdate); - } - - if (Provider.hasCheckoutSupport) - EditorUserSettings.showFailedCheckout = EditorGUILayout.Toggle("Show failed checkouts", EditorUserSettings.showFailedCheckout); - - GUI.enabled = editorEnabled; - - // Semantic merge popup - EditorUserSettings.semanticMergeMode = (SemanticMergeMode)EditorGUILayout.Popup("Smart merge", (int)EditorUserSettings.semanticMergeMode, semanticMergePopupList); - - DrawOverlayDescriptions(); - } - - GUILayout.Space(10); - - int index = (int)EditorSettings.serializationMode; - using (new EditorGUI.DisabledScope(!collabEnabled)) - { - GUI.enabled = !collabEnabled; - GUILayout.Label("Asset Serialization", EditorStyles.boldLabel); - GUI.enabled = editorEnabled && !collabEnabled; - - - CreatePopupMenu("Mode", serializationPopupList, index, SetAssetSerializationMode); - } - if (collabEnabled) - { - EditorGUILayout.HelpBox("Asset Serialization is forced to Text when using Collaboration feature.", MessageType.Warning); - } - - GUILayout.Space(10); - - GUI.enabled = true; - GUILayout.Label("Default Behavior Mode", EditorStyles.boldLabel); - GUI.enabled = editorEnabled; - - index = Mathf.Clamp((int)EditorSettings.defaultBehaviorMode, 0, behaviorPopupList.Length - 1); - CreatePopupMenu("Mode", behaviorPopupList, index, SetDefaultBehaviorMode); - - GUILayout.Space(10); - - GUI.enabled = true; - GUILayout.Label("Sprite Packer", EditorStyles.boldLabel); - GUI.enabled = editorEnabled; - - index = Mathf.Clamp((int)EditorSettings.spritePackerMode, 0, spritePackerPopupList.Length - 1); - CreatePopupMenu("Mode", spritePackerPopupList, index, SetSpritePackerMode); - - if (EditorSettings.spritePackerMode == SpritePackerMode.AlwaysOn - || EditorSettings.spritePackerMode == SpritePackerMode.BuildTimeOnly) - { - index = Mathf.Clamp((int)(EditorSettings.spritePackerPaddingPower - 1), 0, 2); - CreatePopupMenu("Padding Power (Legacy Sprite Packer)", spritePackerPaddingPowerPopupList, index, SetSpritePackerPaddingPower); - } - - DoProjectGenerationSettings(); - DoEtcTextureCompressionSettings(); - DoInternalSettings(); - DoLineEndingsSettings(); - } - - private void DoProjectGenerationSettings() - { - GUILayout.Space(10); - GUILayout.Label("C# Project Generation", EditorStyles.boldLabel); - - var old = EditorSettings.Internal_ProjectGenerationUserExtensions; - string newvalue = EditorGUILayout.TextField("Additional extensions to include", old); - if (newvalue != old) - EditorSettings.Internal_ProjectGenerationUserExtensions = newvalue; - - old = EditorSettings.projectGenerationRootNamespace; - newvalue = EditorGUILayout.TextField("Root namespace", old); - if (newvalue != old) - EditorSettings.projectGenerationRootNamespace = newvalue; - } - - private void DoInternalSettings() - { - if (!EditorPrefs.GetBool("DeveloperMode", false)) - return; - - GUILayout.Space(10); - GUILayout.Label("Internal Settings", EditorStyles.boldLabel); - - var postfix = "-testable"; - EditorGUI.BeginChangeCheck(); - var isEnabled = EditorSettings.Internal_UserGeneratedProjectSuffix == postfix; - isEnabled = EditorGUILayout.Toggle("Internals visible in user scripts", isEnabled); - if (EditorGUI.EndChangeCheck()) - { - EditorSettings.Internal_UserGeneratedProjectSuffix = isEnabled ? postfix : ""; - } - if (isEnabled) - { - EditorGUILayout.HelpBox("If you want this to be set for other people, remember to manually add ProjectSettings/EditorSettings.asset to the repository", MessageType.Info); - } - } - - private void DoEtcTextureCompressionSettings() - { - GUILayout.Space(10); - - GUILayout.Label("ETC Texture Compressor", EditorStyles.boldLabel); - - int index = Mathf.Clamp((int)EditorSettings.etcTextureCompressorBehavior, 0, etcTextureCompressorPopupList.Length - 1); - CreatePopupMenu("Behavior", etcTextureCompressorPopupList, index, SetEtcTextureCompressorBehavior); - - EditorGUI.indentLevel++; - EditorGUI.BeginDisabledGroup(index < 2); - - index = Mathf.Clamp((int)EditorSettings.etcTextureFastCompressor, 0, etcTextureFastCompressorPopupList.Length - 1); - CreatePopupMenu("Fast", etcTextureFastCompressorPopupList, index, SetEtcTextureFastCompressor); - - index = Mathf.Clamp((int)EditorSettings.etcTextureNormalCompressor, 0, etcTextureNormalCompressorPopupList.Length - 1); - CreatePopupMenu("Normal", etcTextureNormalCompressorPopupList, index, SetEtcTextureNormalCompressor); - - index = Mathf.Clamp((int)EditorSettings.etcTextureBestCompressor, 0, etcTextureBestCompressorPopupList.Length - 1); - CreatePopupMenu("Best", etcTextureBestCompressorPopupList, index, SetEtcTextureBestCompressor); - - EditorGUI.EndDisabledGroup(); - EditorGUI.indentLevel--; - } - - private void DoLineEndingsSettings() - { - GUILayout.Space(10); - GUILayout.Label("Line Endings For New Scripts", EditorStyles.boldLabel); - - int index = (int)EditorSettings.lineEndingsForNewScripts; - CreatePopupMenu("Mode", lineEndingsPopupList, index, SetLineEndingsForNewScripts); - } - - static int GetIndexById(DevDevice[] elements, string id, int defaultIndex) - { - for (int i = 0; i < elements.Length; i++) - if (elements[i].id == id) - return i; - - return defaultIndex; - } - - static int GetIndexById(PopupElement[] elements, string id, int defaultIndex) - { - for (int i = 0; i < elements.Length; i++) - if (elements[i].id == id) - return i; - - return defaultIndex; - } - - private void ShowUnityRemoteGUI(bool editorEnabled) - { - GUI.enabled = true; - GUILayout.Label("Unity Remote", EditorStyles.boldLabel); - GUI.enabled = editorEnabled; - - // Find selected device index - string id = EditorSettings.unityRemoteDevice; - // We assume first device to be "None", and default to it, hence 0 - int index = GetIndexById(remoteDeviceList, id, 0); - - var content = new GUIContent(remoteDevicePopupList[index].content); - var popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup); - popupRect = EditorGUI.PrefixLabel(popupRect, 0, EditorGUIUtility.TrTextContent("Device")); - if (EditorGUI.DropdownButton(popupRect, content, FocusType.Passive, EditorStyles.popup)) - DoPopup(popupRect, remoteDevicePopupList, index, SetUnityRemoteDevice); - - int compression = GetIndexById(remoteCompressionList, EditorSettings.unityRemoteCompression, 0); - content = new GUIContent(remoteCompressionList[compression].content); - popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup); - popupRect = EditorGUI.PrefixLabel(popupRect, 0, EditorGUIUtility.TrTextContent("Compression")); - if (EditorGUI.DropdownButton(popupRect, content, FocusType.Passive, EditorStyles.popup)) - DoPopup(popupRect, remoteCompressionList, compression, SetUnityRemoteCompression); - - int resolution = GetIndexById(remoteResolutionList, EditorSettings.unityRemoteResolution, 0); - content = new GUIContent(remoteResolutionList[resolution].content); - popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup); - popupRect = EditorGUI.PrefixLabel(popupRect, 0, EditorGUIUtility.TrTextContent("Resolution")); - if (EditorGUI.DropdownButton(popupRect, content, FocusType.Passive, EditorStyles.popup)) - DoPopup(popupRect, remoteResolutionList, resolution, SetUnityRemoteResolution); - - int joystickSource = GetIndexById(remoteJoystickSourceList, EditorSettings.unityRemoteJoystickSource, 0); - content = new GUIContent(remoteJoystickSourceList[joystickSource].content); - popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup); - popupRect = EditorGUI.PrefixLabel(popupRect, 0, EditorGUIUtility.TrTextContent("Joystick Source")); - if (EditorGUI.DropdownButton(popupRect, content, FocusType.Passive, EditorStyles.popup)) - DoPopup(popupRect, remoteJoystickSourceList, joystickSource, SetUnityRemoteJoystickSource); - } - - private void DrawOverlayDescriptions() - { - Texture2D atlas = Provider.overlayAtlas; - if (atlas == null) - return; - - GUILayout.Space(10); - GUILayout.Label("Overlay legends", EditorStyles.boldLabel); - GUILayout.BeginHorizontal(); - GUILayout.BeginVertical(); - DrawOverlayDescription(Asset.States.Local); - DrawOverlayDescription(Asset.States.OutOfSync); - DrawOverlayDescription(Asset.States.CheckedOutLocal); - DrawOverlayDescription(Asset.States.CheckedOutRemote); - DrawOverlayDescription(Asset.States.DeletedLocal); - DrawOverlayDescription(Asset.States.DeletedRemote); - GUILayout.EndVertical(); - GUILayout.BeginVertical(); - DrawOverlayDescription(Asset.States.AddedLocal); - DrawOverlayDescription(Asset.States.AddedRemote); - DrawOverlayDescription(Asset.States.Conflicted); - DrawOverlayDescription(Asset.States.LockedLocal); - DrawOverlayDescription(Asset.States.LockedRemote); - DrawOverlayDescription(Asset.States.Updating); - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - } - - void DrawOverlayDescription(Asset.States state) - { - Rect atlasUV = Provider.GetAtlasRectForState((int)state); - if (atlasUV.width == 0f) - return; // no overlay - - Texture2D atlas = Provider.overlayAtlas; - if (atlas == null) - return; - - GUILayout.Label(" " + Asset.StateToString(state), EditorStyles.miniLabel); - Rect r = GUILayoutUtility.GetLastRect(); - r.width = 16f; - GUI.DrawTextureWithTexCoords(r, atlas, atlasUV); - } - - private void CreatePopupMenuVersionControl(string title, PopupElement[] elements, string selectedValue, GenericMenu.MenuFunction2 func) - { - var selectedIndex = System.Array.FindIndex(elements, (PopupElement typeElem) => (typeElem.id == selectedValue)); - var content = new GUIContent(elements[selectedIndex].content); - CreatePopupMenu(title, content, elements, selectedIndex, func); - } - - private void CreatePopupMenu(string title, PopupElement[] elements, int selectedIndex, GenericMenu.MenuFunction2 func) - { - CreatePopupMenu(title, elements[selectedIndex].content, elements, selectedIndex, func); - } - - private void CreatePopupMenu(string title, GUIContent content, PopupElement[] elements, int selectedIndex, GenericMenu.MenuFunction2 func) - { - var popupRect = GUILayoutUtility.GetRect(content, EditorStyles.popup); - popupRect = EditorGUI.PrefixLabel(popupRect, 0, new GUIContent(title)); - if (EditorGUI.DropdownButton(popupRect, content, FocusType.Passive, EditorStyles.popup)) - DoPopup(popupRect, elements, selectedIndex, func); - } - - private void DoPopup(Rect popupRect, PopupElement[] elements, int selectedIndex, GenericMenu.MenuFunction2 func) - { - GenericMenu menu = new GenericMenu(); - for (int i = 0; i < elements.Length; i++) - { - var element = elements[i]; - - if (element.Enabled) - menu.AddItem(element.content, i == selectedIndex, func, i); - else - menu.AddDisabledItem(element.content); - } - menu.DropDown(popupRect); - } - - private bool VersionControlSystemHasGUI() - { - bool collabEnabled = Collab.instance.IsCollabEnabledForCurrentProject(); - if (!collabEnabled) - { - ExternalVersionControl system = EditorSettings.externalVersionControl; - return - system != ExternalVersionControl.Disabled && - system != ExternalVersionControl.AutoDetect && - system != ExternalVersionControl.Generic; - } - - return false; - } - - private void SetVersionControlSystem(object data) - { - int popupIndex = (int)data; - if (popupIndex < 0 && popupIndex >= vcPopupList.Length) - return; - - PopupElement el = vcPopupList[popupIndex]; - string oldVC = EditorSettings.externalVersionControl; - - EditorSettings.externalVersionControl = el.id; - Provider.UpdateSettings(); - AssetDatabase.Refresh(); - - if (oldVC != el.id) - { - if (el.content.text == ExternalVersionControl.Disabled || - el.content.text == ExternalVersionControl.Generic - ) - { - // Close the normal version control window - WindowPending.CloseAllWindows(); - } - } - } - - private void SetAssetSerializationMode(object data) - { - int popupIndex = (int)data; - - EditorSettings.serializationMode = (SerializationMode)popupIndex; - } - - private void SetUnityRemoteDevice(object data) - { - EditorSettings.unityRemoteDevice = remoteDeviceList[(int)data].id; - } - - private void SetUnityRemoteCompression(object data) - { - EditorSettings.unityRemoteCompression = remoteCompressionList[(int)data].id; - } - - private void SetUnityRemoteResolution(object data) - { - EditorSettings.unityRemoteResolution = remoteResolutionList[(int)data].id; - } - - private void SetUnityRemoteJoystickSource(object data) - { - EditorSettings.unityRemoteJoystickSource = remoteJoystickSourceList[(int)data].id; - } - - private void SetDefaultBehaviorMode(object data) - { - int popupIndex = (int)data; - - EditorSettings.defaultBehaviorMode = (EditorBehaviorMode)popupIndex; - } - - private void SetSpritePackerMode(object data) - { - int popupIndex = (int)data; - - EditorSettings.spritePackerMode = (SpritePackerMode)popupIndex; - } - - private void SetSpritePackerPaddingPower(object data) - { - int popupIndex = (int)data; - - EditorSettings.spritePackerPaddingPower = popupIndex + 1; - } - - private void SetEtcTextureCompressorBehavior(object data) - { - int newValue = (int)data; - - if (EditorSettings.etcTextureCompressorBehavior == newValue) - return; - - EditorSettings.etcTextureCompressorBehavior = newValue; - - if (newValue == 0) - EditorSettings.SetEtcTextureCompressorLegacyBehavior(); - else - EditorSettings.SetEtcTextureCompressorDefaultBehavior(); - } - - private void SetEtcTextureFastCompressor(object data) - { - EditorSettings.etcTextureFastCompressor = (int)data; - } - - private void SetEtcTextureNormalCompressor(object data) - { - EditorSettings.etcTextureNormalCompressor = (int)data; - } - - private void SetEtcTextureBestCompressor(object data) - { - EditorSettings.etcTextureBestCompressor = (int)data; - } - - private void SetLineEndingsForNewScripts(object data) - { - int popupIndex = (int)data; - - EditorSettings.lineEndingsForNewScripts = (LineEndingsMode)popupIndex; - } - } -} diff --git a/Editor/Mono/Inspector/Effector2DEditor.cs b/Editor/Mono/Inspector/Effector2DEditor.cs deleted file mode 100644 index 47e495d96e..0000000000 --- a/Editor/Mono/Inspector/Effector2DEditor.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using UnityEditor.AnimatedValues; -using UnityEngine; - -namespace UnityEditor -{ - /// - /// Prompts the end-user to add 2D colliders if non exist for 2D effector to work with. - /// - [CustomEditor(typeof(Effector2D), true)] - [CanEditMultipleObjects] - internal class Effector2DEditor : Editor - { - SerializedProperty m_UseColliderMask; - SerializedProperty m_ColliderMask; - readonly AnimBool m_ShowColliderMask = new AnimBool(); - - public virtual void OnEnable() - { - m_UseColliderMask = serializedObject.FindProperty("m_UseColliderMask"); - m_ColliderMask = serializedObject.FindProperty("m_ColliderMask"); - - m_ShowColliderMask.value = (target as Effector2D).useColliderMask; - m_ShowColliderMask.valueChanged.AddListener(Repaint); - } - - public virtual void OnDisable() - { - m_ShowColliderMask.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - // Fetch the effector. - var effector = target as Effector2D; - - // Update collider-mask fade-group. - m_ShowColliderMask.target = effector.useColliderMask; - - EditorGUILayout.PropertyField(m_UseColliderMask); - if (EditorGUILayout.BeginFadeGroup(m_ShowColliderMask.faded)) - EditorGUILayout.PropertyField(m_ColliderMask); - EditorGUILayout.EndFadeGroup(); - - serializedObject.ApplyModifiedProperties(); - - // Finish if any enabled 2D colliders used by the effector exist. - if (effector.GetComponents().Any(collider => collider.enabled && collider.usedByEffector)) - return; - - // Show appropriate feedback. - if (effector.requiresCollider) - EditorGUILayout.HelpBox("This effector will not function until there is at least one enabled 2D collider with 'Used by Effector' checked on this GameObject.", MessageType.Warning); - else - EditorGUILayout.HelpBox("This effector can optionally work without a 2D collider.", MessageType.Info); - } - - /// - /// Checks collider types for compatibility warnings. - /// - /// - public static void CheckEffectorWarnings(Collider2D collider) - { - // Finish if the collider is not used by the effector. - if (!collider.usedByEffector || collider.usedByComposite) - return; - - // Fetch the effector. - var effector = collider.GetComponent(); - - // Warning if there's no effector or it's not enabled. - if (effector == null || !effector.enabled) - { - // Show warning. - EditorGUILayout.HelpBox("This collider will not function with an effector until there is at least one enabled 2D effector on this GameObject.", MessageType.Warning); - - // Finish if there was no effector. - if (effector == null) - return; - } - - // Handle collision/trigger effector preferences. - if (effector.designedForNonTrigger && collider.isTrigger) - { - // Show warning. - EditorGUILayout.HelpBox("This collider has 'Is Trigger' checked but this should be unchecked when used with the '" + effector.GetType().Name + "' component which is designed to work with collisions.", MessageType.Warning); - } - else if (effector.designedForTrigger && !collider.isTrigger) - { - // Show warning. - EditorGUILayout.HelpBox("This collider has 'Is Trigger' unchecked but this should be checked when used with the '" + effector.GetType().Name + "' component which is designed to work with triggers.", MessageType.Warning); - } - } - } -} diff --git a/Editor/Mono/Inspector/Enlighten/LightmapParameters.cs b/Editor/Mono/Inspector/Enlighten/LightmapParameters.cs deleted file mode 100644 index 54aa012402..0000000000 --- a/Editor/Mono/Inspector/Enlighten/LightmapParameters.cs +++ /dev/null @@ -1,127 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - [CustomEditor(typeof(LightmapParameters))] - [CanEditMultipleObjects] - class LightmapParametersEditor : Editor - { - SerializedProperty m_Resolution; - SerializedProperty m_ClusterResolution; - SerializedProperty m_IrradianceBudget; - SerializedProperty m_IrradianceQuality; - SerializedProperty m_BackFaceTolerance; - SerializedProperty m_ModellingTolerance; - SerializedProperty m_EdgeStitching; - SerializedProperty m_SystemTag; - SerializedProperty m_IsTransparent; - - SerializedProperty m_AOQuality; - SerializedProperty m_AOAntiAliasingSamples; - SerializedProperty m_BlurRadius; - SerializedProperty m_BakedLightmapTag; - SerializedProperty m_Pushoff; - - SerializedProperty m_AntiAliasingSamples; - SerializedProperty m_DirectLightQuality; - - public void OnEnable() - { - m_Resolution = serializedObject.FindProperty("resolution"); - m_ClusterResolution = serializedObject.FindProperty("clusterResolution"); - m_IrradianceBudget = serializedObject.FindProperty("irradianceBudget"); - m_IrradianceQuality = serializedObject.FindProperty("irradianceQuality"); - m_BackFaceTolerance = serializedObject.FindProperty("backFaceTolerance"); - m_ModellingTolerance = serializedObject.FindProperty("modellingTolerance"); - m_EdgeStitching = serializedObject.FindProperty("edgeStitching"); - m_IsTransparent = serializedObject.FindProperty("isTransparent"); - m_SystemTag = serializedObject.FindProperty("systemTag"); - m_AOQuality = serializedObject.FindProperty("AOQuality"); - m_AOAntiAliasingSamples = serializedObject.FindProperty("AOAntiAliasingSamples"); - m_BlurRadius = serializedObject.FindProperty("blurRadius"); - m_AntiAliasingSamples = serializedObject.FindProperty("antiAliasingSamples"); - m_DirectLightQuality = serializedObject.FindProperty("directLightQuality"); - m_BakedLightmapTag = serializedObject.FindProperty("bakedLightmapTag"); - m_Pushoff = serializedObject.FindProperty("pushoff"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - GUILayout.Label(Styles.precomputedRealtimeGIContent, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_Resolution, Styles.resolutionContent); - EditorGUILayout.Slider(m_ClusterResolution, 0.1F, 1.0F, Styles.clusterResolutionContent); - EditorGUILayout.IntSlider(m_IrradianceBudget, 32, 2048, Styles.irradianceBudgetContent); - EditorGUILayout.IntSlider(m_IrradianceQuality, 512, 131072, Styles.irradianceQualityContent); - EditorGUILayout.Slider(m_ModellingTolerance, 0.0f, 1.0f, Styles.modellingToleranceContent); - EditorGUILayout.PropertyField(m_EdgeStitching, Styles.edgeStitchingContent); - EditorGUILayout.PropertyField(m_IsTransparent, Styles.isTransparent); - EditorGUILayout.PropertyField(m_SystemTag, Styles.systemTagContent); - EditorGUILayout.Space(); - - bool usesPathTracerBakeBackend = LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveCPU; - - GUILayout.Label(Styles.bakedGIContent, EditorStyles.boldLabel); - using (new EditorGUI.DisabledScope(usesPathTracerBakeBackend)) - { - EditorGUILayout.PropertyField(m_BlurRadius, Styles.blurRadiusContent); - } - EditorGUILayout.PropertyField(m_AntiAliasingSamples, Styles.antiAliasingSamplesContent); - using (new EditorGUI.DisabledScope(usesPathTracerBakeBackend)) - { - EditorGUILayout.PropertyField(m_DirectLightQuality, Styles.directLightQualityContent); - } - EditorGUILayout.PropertyField(m_BakedLightmapTag, Styles.bakedLightmapTagContent); - EditorGUILayout.Slider(m_Pushoff, 0.0f, 1.0f, Styles.pushoffContent); - EditorGUILayout.Space(); - - using (new EditorGUI.DisabledScope(usesPathTracerBakeBackend)) - { - GUILayout.Label(Styles.bakedAOContent, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_AOQuality, Styles.aoQualityContent); - EditorGUILayout.PropertyField(m_AOAntiAliasingSamples, Styles.aoAntiAliasingSamplesContent); - } - - GUILayout.Label(Styles.generalGIContent, EditorStyles.boldLabel); - EditorGUILayout.Slider(m_BackFaceTolerance, 0.0f, 1.0f, Styles.backFaceToleranceContent); - - serializedObject.ApplyModifiedProperties(); - } - - internal override void OnHeaderControlsGUI() - { - GUILayoutUtility.GetRect(10, 10, 16, 16, EditorStyles.layerMaskField); - GUILayout.FlexibleSpace(); - } - - private class Styles - { - public static readonly GUIContent generalGIContent = EditorGUIUtility.TrTextContent("General GI", "Settings used in both Precomputed Realtime Global Illumination and Baked Global Illumination."); - public static readonly GUIContent precomputedRealtimeGIContent = EditorGUIUtility.TrTextContent("Precomputed Realtime GI", "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 - 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."); - 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."); - 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."); - 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."); - public static readonly GUIContent backFaceToleranceContent = EditorGUIUtility.TrTextContent("Backface Tolerance", "The percentage of rays shot from an output texel that must hit front faces to be considered usable. Allows a texel to be invalidated if too many of the rays cast from it hit back faces (the texel is inside some geometry). In that case artefacts are avoided by cloning valid values from surrounding texels. For example, if backface tolerance is 0.0, the texel is rejected only if it sees nothing but backfaces. If it is 1.0, the ray origin is rejected if it has even one ray that hits a backface."); - public static readonly GUIContent modellingToleranceContent = EditorGUIUtility.TrTextContent("Modelling Tolerance", "Maximum size of gaps that can be ignored for GI."); - 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."); - 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."); - public static readonly GUIContent bakedGIContent = EditorGUIUtility.TrTextContent("Baked GI", "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 - public static readonly GUIContent blurRadiusContent = EditorGUIUtility.TrTextContent("Blur Radius", "The radius (in texels) of the post-processing filter that blurs baked direct lighting. This reduces aliasing artefacts and produces softer shadows."); - public static readonly GUIContent antiAliasingSamplesContent = EditorGUIUtility.TrTextContent("Anti-aliasing Samples", "The maximum number of times to supersample a texel to reduce aliasing. Progressive lightmapper supersamples the positions and normals buffers (part of the G-buffer) and hence the sample count is a multiplier on the amount of memory used for those buffers. Progressive lightmapper clamps the value to the [1;16] range."); - public static readonly GUIContent directLightQualityContent = EditorGUIUtility.TrTextContent("Direct Light Quality", "The number of rays used for lights with an area. Allows for accurate soft shadowing."); - public static readonly GUIContent bakedAOContent = EditorGUIUtility.TrTextContent("Baked AO", "Settings used in Baked Ambient Occlusion, where the information on dark corners and crevices in static geometry is baked. It is multiplied by indirect lighting when compositing the baked lightmap."); - public static readonly GUIContent aoQualityContent = EditorGUIUtility.TrTextContent("Quality", "The number of rays to cast for computing ambient occlusion."); - public static readonly GUIContent aoAntiAliasingSamplesContent = EditorGUIUtility.TrTextContent("Anti-aliasing Samples", "The maximum number of times to supersample a texel to reduce aliasing in ambient occlusion."); - 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."); - 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."); - 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."); - }; - } -} diff --git a/Editor/Mono/Inspector/FontInspector.cs b/Editor/Mono/Inspector/FontInspector.cs deleted file mode 100644 index 359735a891..0000000000 --- a/Editor/Mono/Inspector/FontInspector.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - - -namespace UnityEditor -{ - [CustomEditor(typeof(Font))] - [CanEditMultipleObjects] - internal class FontInspector : Editor - { - public override void OnInspectorGUI() - { - foreach (Object o in targets) - { - // Dont draw the default inspector for imported font assets. - // It can be very slow when there is a lot of embedded font data, - // and the presented information is not useful to the user anyways. - // We still need it for editable, "Custom Font" assets, though. - if (o.hideFlags == HideFlags.NotEditable) - return; - } - - DrawDefaultInspector(); - } - } -} diff --git a/Editor/Mono/Inspector/GameObjectInspector.cs b/Editor/Mono/Inspector/GameObjectInspector.cs deleted file mode 100644 index 6f1b2bbb0f..0000000000 --- a/Editor/Mono/Inspector/GameObjectInspector.cs +++ /dev/null @@ -1,848 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.SceneManagement; -using UnityEditor.VersionControl; -using UnityEditorInternal; -using UnityEngine; - -using UnityObject = UnityEngine.Object; - -namespace UnityEditor -{ - [CustomEditor(typeof(GameObject))] - [CanEditMultipleObjects] - internal class GameObjectInspector : Editor - { - SerializedProperty m_Name; - SerializedProperty m_IsActive; - SerializedProperty m_Layer; - SerializedProperty m_Tag; - SerializedProperty m_StaticEditorFlags; - SerializedProperty m_Icon; - - class Styles - { - public GUIContent goIcon = EditorGUIUtility.IconContent("GameObject Icon"); - public GUIContent typelessIcon = EditorGUIUtility.IconContent("Prefab Icon"); - public GUIContent prefabIcon = EditorGUIUtility.IconContent("PrefabNormal Icon"); - public GUIContent modelIcon = EditorGUIUtility.IconContent("PrefabModel Icon"); - - public 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."); - public GUIContent layerContent = EditorGUIUtility.TrTextContent("Layer", "The layer that this GameObject is in.\n\nChoose Add Layer... to edit the list of available layers."); - public 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."); - - public float tagFieldWidth = EditorStyles.boldLabel.CalcSize(EditorGUIUtility.TempContent("Tag")).x; - public float layerFieldWidth = EditorStyles.boldLabel.CalcSize(EditorGUIUtility.TempContent("Layer")).x; - - public GUIStyle staticDropdown = "StaticDropdown"; - public GUIStyle header = new GUIStyle("IN GameObjectHeader"); - public GUIStyle layerPopup = new GUIStyle(EditorStyles.popup); - - public GUIStyle instanceManagementInfo = new GUIStyle(EditorStyles.helpBox); - - public GUIContent goTypeLabelMultiple = EditorGUIUtility.TrTextContent("Multiple"); - - public GUIContent[] goTypeLabel = - { - null,// None = 0, - EditorGUIUtility.TrTextContent("Prefab"), // Prefab = 1 - EditorGUIUtility.TrTextContent("Model"), // ModelPrefab = 2 - EditorGUIUtility.TrTextContent("Prefab"), // PrefabInstance = 3 - EditorGUIUtility.TrTextContent("Model"), // ModelPrefabInstance = 4 - EditorGUIUtility.TrTextContent("Missing", "The source Prefab or Model has been deleted."), // MissingPrefabInstance - 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."), // DisconnectedPrefabInstance - EditorGUIUtility.TrTextContent("Model", "You have broken the prefab connection. Changes to the model will not be applied to this object before you Revert."), // DisconnectedModelPrefabInstance - }; - - public Styles() - { - GUIStyle miniButtonMid = "MiniButtonMid"; - instanceManagementInfo.padding = miniButtonMid.padding; - instanceManagementInfo.alignment = miniButtonMid.alignment; - - // 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. - layerPopup.margin.right = 0; - header.padding.bottom -= 3; - } - } - static Styles s_Styles; - const float kIconSize = 24; - Vector2 previewDir; - - class PreviewData : IDisposable - { - bool m_Disposed; - GameObject m_GameObject; - - public readonly PreviewRenderUtility renderUtility; - public GameObject gameObject { get { return m_GameObject; } } - - public PreviewData(UnityObject targetObject) - { - renderUtility = new PreviewRenderUtility(); - renderUtility.camera.fieldOfView = 30.0f; - UpdateGameObject(targetObject); - } - - public void UpdateGameObject(UnityObject targetObject) - { - UnityObject.DestroyImmediate(gameObject); - m_GameObject = EditorUtility.InstantiateForAnimatorPreview(targetObject); - renderUtility.AddManagedGO(gameObject); - } - - public void Dispose() - { - if (m_Disposed) - return; - renderUtility.Cleanup(); - UnityObject.DestroyImmediate(gameObject); - m_GameObject = null; - m_Disposed = true; - } - } - - Dictionary m_PreviewInstances = new Dictionary(); - - bool m_HasInstance = false; - bool m_AllOfSamePrefabType = true; - - public void OnEnable() - { - if (EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D) - previewDir = new Vector2(0, 0); - else - previewDir = new Vector2(120, -20); - - m_Name = serializedObject.FindProperty("m_Name"); - m_IsActive = serializedObject.FindProperty("m_IsActive"); - m_Layer = serializedObject.FindProperty("m_Layer"); - m_Tag = serializedObject.FindProperty("m_TagString"); - m_StaticEditorFlags = serializedObject.FindProperty("m_StaticEditorFlags"); - m_Icon = serializedObject.FindProperty("m_Icon"); - - CalculatePrefabStatus(); - } - - void CalculatePrefabStatus() - { - m_HasInstance = false; - m_AllOfSamePrefabType = true; - PrefabType firstType = PrefabUtility.GetPrefabType(targets[0] as GameObject); - foreach (GameObject go in targets) - { - PrefabType type = PrefabUtility.GetPrefabType(go); - if (type != firstType) - m_AllOfSamePrefabType = false; - if (type != PrefabType.None && type != PrefabType.Prefab && type != PrefabType.ModelPrefab) - m_HasInstance = true; - } - } - - void OnDisable() {} - - - private static bool ShowMixedStaticEditorFlags(StaticEditorFlags mask) - { - uint countedBits = 0; - uint numFlags = 0; - foreach (var i in Enum.GetValues(typeof(StaticEditorFlags))) - { - numFlags++; - if ((mask & (StaticEditorFlags)i) > 0) - countedBits++; - } - - //If we have more then one selected... but it is not all the flags - //All indictates 'everything' which means it should be a tick! - return countedBits > 0 && countedBits != numFlags; - } - - protected override void OnHeaderGUI() - { - if (s_Styles == null) - s_Styles = new Styles(); - - bool enabledTemp = GUI.enabled; - GUI.enabled = true; - EditorGUILayout.BeginVertical(s_Styles.header); - GUI.enabled = enabledTemp; - DrawInspector(); - EditorGUILayout.EndVertical(); - } - - public override void OnInspectorGUI() {} - - internal bool DrawInspector() - { - serializedObject.Update(); - - GameObject go = target as GameObject; - - GUIContent iconContent = null; - - PrefabType prefabType = PrefabType.None; - // Leave iconContent to be null if multiple objects not the same type. - if (m_AllOfSamePrefabType) - { - prefabType = PrefabUtility.GetPrefabType(go); - switch (prefabType) - { - case PrefabType.None: - iconContent = s_Styles.goIcon; - break; - case PrefabType.Prefab: - case PrefabType.PrefabInstance: - case PrefabType.DisconnectedPrefabInstance: - case PrefabType.MissingPrefabInstance: - iconContent = s_Styles.prefabIcon; - break; - case PrefabType.ModelPrefab: - case PrefabType.ModelPrefabInstance: - case PrefabType.DisconnectedModelPrefabInstance: - iconContent = s_Styles.modelIcon; - break; - } - } - else - iconContent = s_Styles.typelessIcon; - - EditorGUILayout.BeginHorizontal(); - EditorGUI.ObjectIconDropDown(GUILayoutUtility.GetRect(kIconSize, kIconSize, GUILayout.ExpandWidth(false)), targets, true, iconContent.image as Texture2D, m_Icon); - DrawPostIconContent(); - - using (new EditorGUI.DisabledScope(prefabType == PrefabType.ModelPrefab)) - { - EditorGUILayout.BeginVertical(); - - EditorGUILayout.BeginHorizontal(); - - EditorGUILayout.BeginHorizontal(GUILayout.Width(s_Styles.tagFieldWidth)); - - GUILayout.FlexibleSpace(); - - // IsActive - EditorGUI.PropertyField(GUILayoutUtility.GetRect(EditorStyles.toggle.padding.left, EditorGUIUtility.singleLineHeight, EditorStyles.toggle, GUILayout.ExpandWidth(false)), m_IsActive, GUIContent.none); - - EditorGUILayout.EndHorizontal(); - - // Name - EditorGUILayout.DelayedTextField(m_Name, GUIContent.none); - - // Static flags toggle - DoStaticToggleField(go); - - // Static flags dropdown - DoStaticFlagsDropDown(go); - - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.BeginHorizontal(); - - // Tag - DoTagsField(go); - - // Layer - DoLayerField(go); - - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.EndVertical(); - } - - EditorGUILayout.EndHorizontal(); - - // Seems to be a bug in margin not being applied consistently as tag/layer line, account for it here - GUILayout.Space(2f); - - // Prefab Toolbar - using (new EditorGUI.DisabledScope(prefabType == PrefabType.ModelPrefab)) - DoPrefabButtons(prefabType, go); - - serializedObject.ApplyModifiedProperties(); - - return true; - } - - private void DoPrefabButtons(PrefabType prefabType, GameObject go) - { - // @TODO: If/when we support multi-editing of prefab/model instances, - // handle it here. Only show prefab bar if all are same type? - if (!m_HasInstance) return; - - using (new EditorGUI.DisabledScope(EditorApplication.isPlayingOrWillChangePlaymode)) - { - EditorGUILayout.BeginHorizontal(); - - // Prefab information - GUIContent prefixLabel = targets.Length > 1 ? s_Styles.goTypeLabelMultiple : s_Styles.goTypeLabel[(int)prefabType]; - - if (prefixLabel != null) - { - EditorGUILayout.BeginHorizontal(GUILayout.Width(kIconSize + s_Styles.tagFieldWidth)); - GUILayout.FlexibleSpace(); - if (prefabType == PrefabType.DisconnectedModelPrefabInstance || prefabType == PrefabType.MissingPrefabInstance || prefabType == PrefabType.DisconnectedPrefabInstance) - { - GUI.contentColor = GUI.skin.GetStyle("CN StatusWarn").normal.textColor; - GUILayout.Label(prefixLabel, EditorStyles.whiteLabel, GUILayout.ExpandWidth(false)); - GUI.contentColor = Color.white; - } - else - GUILayout.Label(prefixLabel, GUILayout.ExpandWidth(false)); - EditorGUILayout.EndHorizontal(); - } - - if (targets.Length > 1) - GUILayout.Label("Instance Management Disabled", s_Styles.instanceManagementInfo); - else - { - // Select prefab - if (prefabType != PrefabType.MissingPrefabInstance) - { - if (GUILayout.Button("Select", "MiniButtonLeft")) - { - Selection.activeObject = PrefabUtility.GetPrefabParent(target); - EditorGUIUtility.PingObject(Selection.activeObject); - } - } - - using (new EditorGUI.DisabledScope(AnimationMode.InAnimationMode())) - { - if (prefabType != PrefabType.MissingPrefabInstance) - { - // Revert this gameobject and components to prefab - if (GUILayout.Button("Revert", "MiniButtonMid")) - { - PrefabUtility.RevertPrefabInstanceWithUndo(go); - - // case931300 - The selected gameobject might get destroyed by RevertPrefabInstance - if (go != null) - { - CalculatePrefabStatus(); - } - - // This is necessary because Revert can potentially destroy game objects and components - // In that case the Editor classes would be destroyed but still be invoked. (case 837113) - GUIUtility.ExitGUI(); - } - - // Apply to prefab - if (prefabType == PrefabType.PrefabInstance || prefabType == PrefabType.DisconnectedPrefabInstance) - { - GameObject rootUploadGameObject = PrefabUtility.FindValidUploadPrefabInstanceRoot(go); - - GUI.enabled = rootUploadGameObject != null && !AnimationMode.InAnimationMode(); - - if (GUILayout.Button("Apply", "MiniButtonRight")) - { - UnityObject prefabParent = PrefabUtility.GetPrefabParent(rootUploadGameObject); - string prefabAssetPath = AssetDatabase.GetAssetPath(prefabParent); - - bool editablePrefab = Provider.PromptAndCheckoutIfNeeded( - new string[] { prefabAssetPath }, - "The version control requires you to check out the prefab before applying changes."); - - if (editablePrefab) - { - PrefabUtility.ReplacePrefabWithUndo(rootUploadGameObject); - - CalculatePrefabStatus(); - - // This is necessary because ReplacePrefab can potentially destroy game objects and components - // In that case the Editor classes would be destroyed but still be invoked. (case 468434) - GUIUtility.ExitGUI(); - } - } - } - } - } - - // Edit model prefab - if (prefabType == PrefabType.DisconnectedModelPrefabInstance || prefabType == PrefabType.ModelPrefabInstance) - { - if (GUILayout.Button("Open", "MiniButtonRight")) - { - AssetDatabase.OpenAsset(PrefabUtility.GetPrefabParent(target)); - GUIUtility.ExitGUI(); - } - } - } - EditorGUILayout.EndHorizontal(); - } - } - - private void DoLayerField(GameObject go) - { - EditorGUIUtility.labelWidth = s_Styles.layerFieldWidth; - Rect layerRect = GUILayoutUtility.GetRect(GUIContent.none, s_Styles.layerPopup); - EditorGUI.BeginProperty(layerRect, GUIContent.none, m_Layer); - EditorGUI.BeginChangeCheck(); - int layer = EditorGUI.LayerField(layerRect, s_Styles.layerContent, go.layer, s_Styles.layerPopup); - if (EditorGUI.EndChangeCheck()) - { - GameObjectUtility.ShouldIncludeChildren includeChildren = GameObjectUtility.DisplayUpdateChildrenDialogIfNeeded(targets.OfType(), - "Change Layer", string.Format("Do you want to set layer to {0} for all child objects as well?", InternalEditorUtility.GetLayerName(layer))); - if (includeChildren != GameObjectUtility.ShouldIncludeChildren.Cancel) - { - m_Layer.intValue = layer; - SetLayer(layer, includeChildren == GameObjectUtility.ShouldIncludeChildren.IncludeChildren); - } - // Displaying the dialog to ask the user whether to update children nukes the gui state - EditorGUIUtility.ExitGUI(); - } - EditorGUI.EndProperty(); - } - - private void DoTagsField(GameObject go) - { - string tagName = null; - try - { - tagName = go.tag; - } - catch (System.Exception) - { - tagName = "Undefined"; - } - EditorGUIUtility.labelWidth = s_Styles.tagFieldWidth; - Rect tagRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.popup); - EditorGUI.BeginProperty(tagRect, GUIContent.none, m_Tag); - EditorGUI.BeginChangeCheck(); - string tag = EditorGUI.TagField(tagRect, s_Styles.tagContent, tagName); - if (EditorGUI.EndChangeCheck()) - { - m_Tag.stringValue = tag; - Undo.RecordObjects(targets, "Change Tag of " + targetTitle); - foreach (UnityObject obj in targets) - (obj as GameObject).tag = tag; - } - EditorGUI.EndProperty(); - } - - private void DoStaticFlagsDropDown(GameObject go) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_StaticEditorFlags.hasMultipleDifferentValues; - int changedFlags; - bool changedToValue; - EditorGUI.EnumFlagsField( - GUILayoutUtility.GetRect(GUIContent.none, s_Styles.staticDropdown, GUILayout.ExpandWidth(false)), - GUIContent.none, - GameObjectUtility.GetStaticEditorFlags(go), - out changedFlags, out changedToValue, - s_Styles.staticDropdown - ); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - SceneModeUtility.SetStaticFlags(targets, changedFlags, changedToValue); - serializedObject.SetIsDifferentCacheDirty(); - - // Displaying the dialog to ask the user whether to update children nukes the gui state (case 962453) - EditorGUIUtility.ExitGUI(); - } - } - - private void DoStaticToggleField(GameObject go) - { - var staticRect = GUILayoutUtility.GetRect(s_Styles.staticContent, EditorStyles.toggle, GUILayout.ExpandWidth(false)); - EditorGUI.BeginProperty(staticRect, GUIContent.none, m_StaticEditorFlags); - EditorGUI.BeginChangeCheck(); - var toggleRect = staticRect; - EditorGUI.showMixedValue |= ShowMixedStaticEditorFlags((StaticEditorFlags)m_StaticEditorFlags.intValue); - // Ignore mouse clicks that are not with the primary (left) mouse button so those can be grabbed by other things later. - Event evt = Event.current; - EventType origType = evt.type; - bool nonLeftClick = (evt.type == EventType.MouseDown && evt.button != 0); - if (nonLeftClick) - evt.type = EventType.Ignore; - var toggled = EditorGUI.ToggleLeft(toggleRect, s_Styles.staticContent, go.isStatic); - if (nonLeftClick) - evt.type = origType; - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - SceneModeUtility.SetStaticFlags(targets, ~0, toggled); - serializedObject.SetIsDifferentCacheDirty(); - - // Displaying the dialog to ask the user whether to update children nukes the gui state (case 962453) - EditorGUIUtility.ExitGUI(); - } - EditorGUI.EndProperty(); - } - - UnityObject[] GetObjects(bool includeChildren) - { - return SceneModeUtility.GetObjects(targets, includeChildren); - } - - void SetLayer(int layer, bool includeChildren) - { - UnityObject[] objects = GetObjects(includeChildren); - Undo.RecordObjects(objects, "Change Layer of " + targetTitle); - foreach (GameObject go in objects) - go.layer = layer; - } - - public override void ReloadPreviewInstances() - { - foreach (var pair in m_PreviewInstances) - { - var index = pair.Key; - if (index > targets.Length) - continue; - - var previewData = pair.Value; - previewData.UpdateGameObject(targets[index]); - } - } - - PreviewData GetPreviewData() - { - PreviewData previewData; - if (!m_PreviewInstances.TryGetValue(referenceTargetIndex, out previewData)) - { - previewData = new PreviewData(target); - m_PreviewInstances.Add(referenceTargetIndex, previewData); - } - if (!previewData.gameObject) - ReloadPreviewInstances(); - return previewData; - } - - public void OnDestroy() - { - foreach (var previewData in m_PreviewInstances.Values) - previewData.Dispose(); - m_PreviewInstances.Clear(); - } - - public static bool HasRenderableParts(GameObject go) - { - // Do we have a mesh? - var renderers = go.GetComponentsInChildren(); - foreach (var renderer in renderers) - { - var filter = renderer.gameObject.GetComponent(); - if (filter && filter.sharedMesh) - return true; - } - - // Do we have a skinned mesh? - var skins = go.GetComponentsInChildren(); - foreach (var skin in skins) - { - if (skin.sharedMesh) - return true; - } - - // Do we have a Sprite? - var sprites = go.GetComponentsInChildren(); - foreach (var sprite in sprites) - { - if (sprite.sprite) - return true; - } - - // Nope, we don't have it. - return false; - } - - public static void GetRenderableBoundsRecurse(ref Bounds bounds, GameObject go) - { - // Do we have a mesh? - MeshRenderer renderer = go.GetComponent(typeof(MeshRenderer)) as MeshRenderer; - MeshFilter filter = go.GetComponent(typeof(MeshFilter)) as MeshFilter; - if (renderer && filter && filter.sharedMesh) - { - // To prevent origo from always being included in bounds we initialize it - // with renderer.bounds. This ensures correct bounds for meshes with origo outside the mesh. - if (bounds.extents == Vector3.zero) - bounds = renderer.bounds; - else - bounds.Encapsulate(renderer.bounds); - } - - // Do we have a skinned mesh? - SkinnedMeshRenderer skin = go.GetComponent(typeof(SkinnedMeshRenderer)) as SkinnedMeshRenderer; - if (skin && skin.sharedMesh) - { - if (bounds.extents == Vector3.zero) - bounds = skin.bounds; - else - bounds.Encapsulate(skin.bounds); - } - - // Do we have a Sprite? - SpriteRenderer sprite = go.GetComponent(typeof(SpriteRenderer)) as SpriteRenderer; - if (sprite && sprite.sprite) - { - if (bounds.extents == Vector3.zero) - bounds = sprite.bounds; - else - bounds.Encapsulate(sprite.bounds); - } - - // Recurse into children - foreach (Transform t in go.transform) - { - GetRenderableBoundsRecurse(ref bounds, t.gameObject); - } - } - - private static float GetRenderableCenterRecurse(ref Vector3 center, GameObject go, int depth, int minDepth, int maxDepth) - { - if (depth > maxDepth) - return 0; - - float ret = 0; - - if (depth > minDepth) - { - // Do we have a mesh? - MeshRenderer renderer = go.GetComponent(typeof(MeshRenderer)) as MeshRenderer; - MeshFilter filter = go.GetComponent(typeof(MeshFilter)) as MeshFilter; - SkinnedMeshRenderer skin = go.GetComponent(typeof(SkinnedMeshRenderer)) as SkinnedMeshRenderer; - SpriteRenderer sprite = go.GetComponent(typeof(SpriteRenderer)) as SpriteRenderer; - - if (renderer == null && filter == null && skin == null && sprite == null) - { - ret = 1; - center = center + go.transform.position; - } - else if (renderer != null && filter != null) - { - // case 542145, epsilon is too small. Accept up to 1 centimeter before discarding this model. - if (Vector3.Distance(renderer.bounds.center, go.transform.position) < 0.01F) - { - ret = 1; - center = center + go.transform.position; - } - } - else if (skin != null) - { - // case 542145, epsilon is too small. Accept up to 1 centimeter before discarding this model. - if (Vector3.Distance(skin.bounds.center, go.transform.position) < 0.01F) - { - ret = 1; - center = center + go.transform.position; - } - } - else if (sprite != null) - { - if (Vector3.Distance(sprite.bounds.center, go.transform.position) < 0.01F) - { - ret = 1; - center = center + go.transform.position; - } - } - } - - depth++; - // Recurse into children - foreach (Transform t in go.transform) - { - ret += GetRenderableCenterRecurse(ref center, t.gameObject, depth, minDepth, maxDepth); - } - - return ret; - } - - public static Vector3 GetRenderableCenterRecurse(GameObject go, int minDepth, int maxDepth) - { - Vector3 center = Vector3.zero; - - float sum = GetRenderableCenterRecurse(ref center, go, 0, minDepth, maxDepth); - - if (sum > 0) - { - center = center / sum; - } - else - { - center = go.transform.position; - } - - return center; - } - - public override bool HasPreviewGUI() - { - if (!EditorUtility.IsPersistent(target)) - return false; - - return HasStaticPreview(); - } - - private bool HasStaticPreview() - { - if (targets.Length > 1) - return true; - - if (target == null) - return false; - - GameObject go = target as GameObject; - - // Is this a camera? - Camera camera = go.GetComponent(typeof(Camera)) as Camera; - if (camera) - return true; - - return HasRenderableParts(go); - } - - public override void OnPreviewSettings() - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - return; - GUI.enabled = true; - } - - private void DoRenderPreview() - { - var previewData = GetPreviewData(); - - Bounds bounds = new Bounds(previewData.gameObject.transform.position, Vector3.zero); - GetRenderableBoundsRecurse(ref bounds, previewData.gameObject); - float halfSize = Mathf.Max(bounds.extents.magnitude, 0.0001f); - float distance = halfSize * 3.8f; - - Quaternion rot = Quaternion.Euler(-previewDir.y, -previewDir.x, 0); - Vector3 pos = bounds.center - rot * (Vector3.forward * distance); - - previewData.renderUtility.camera.transform.position = pos; - previewData.renderUtility.camera.transform.rotation = rot; - previewData.renderUtility.camera.nearClipPlane = distance - halfSize * 1.1f; - previewData.renderUtility.camera.farClipPlane = distance + halfSize * 1.1f; - - previewData.renderUtility.lights[0].intensity = .7f; - previewData.renderUtility.lights[0].transform.rotation = rot * Quaternion.Euler(40f, 40f, 0); - previewData.renderUtility.lights[1].intensity = .7f; - previewData.renderUtility.lights[1].transform.rotation = rot * Quaternion.Euler(340, 218, 177); - - previewData.renderUtility.ambientColor = new Color(.1f, .1f, .1f, 0); - - previewData.renderUtility.Render(true); - } - - public override Texture2D RenderStaticPreview(string assetPath, UnityObject[] subAssets, int width, int height) - { - if (!HasStaticPreview() || !ShaderUtil.hardwareSupportsRectRenderTexture) - { - return null; - } - - var previewUtility = GetPreviewData().renderUtility; - previewUtility.BeginStaticPreview(new Rect(0, 0, width, height)); - - DoRenderPreview(); - - return previewUtility.EndStaticPreview(); - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - { - if (Event.current.type == EventType.Repaint) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), "Preview requires\nrender texture support"); - return; - } - - previewDir = PreviewGUI.Drag2D(previewDir, r); - - if (Event.current.type != EventType.Repaint) - return; - - var previewUtility = GetPreviewData().renderUtility; - previewUtility.BeginPreview(r, background); - - DoRenderPreview(); - - previewUtility.EndAndDrawPreview(r); - } - - // Handle dragging in scene view - public static GameObject dragObject; - - public void OnSceneDrag(SceneView sceneView) - { - GameObject go = target as GameObject; - PrefabType prefabType = PrefabUtility.GetPrefabType(go); - if (prefabType != PrefabType.Prefab && prefabType != PrefabType.ModelPrefab) - return; - - Event evt = Event.current; - switch (evt.type) - { - case EventType.DragUpdated: - if (dragObject == null) - { - dragObject = (GameObject)PrefabUtility.InstantiatePrefab(PrefabUtility.FindPrefabRoot(go)); - dragObject.hideFlags = HideFlags.HideInHierarchy; - dragObject.name = go.name; - } - - if (HandleUtility.ignoreRaySnapObjects == null) - HandleUtility.ignoreRaySnapObjects = dragObject.GetComponentsInChildren(); - - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(evt.mousePosition)); - if (hit != null) - { - RaycastHit rh = (RaycastHit)hit; - float offset = 0; - if (Tools.pivotMode == PivotMode.Center) - { - float geomOffset = HandleUtility.CalcRayPlaceOffset(HandleUtility.ignoreRaySnapObjects, rh.normal); - if (geomOffset != Mathf.Infinity) - offset = Vector3.Dot(dragObject.transform.position, rh.normal) - geomOffset; - } - dragObject.transform.position = Matrix4x4.identity.MultiplyPoint(rh.point + (rh.normal * offset)); - } - else - dragObject.transform.position = HandleUtility.GUIPointToWorldRay(evt.mousePosition).GetPoint(10); - - // Use prefabs original z position when in 2D mode - if (sceneView.in2DMode) - { - Vector3 dragPosition = dragObject.transform.position; - dragPosition.z = PrefabUtility.FindPrefabRoot(go).transform.position.z; - dragObject.transform.position = dragPosition; - } - - evt.Use(); - break; - case EventType.DragPerform: - string uniqueName = GameObjectUtility.GetUniqueNameForSibling(null, dragObject.name); - dragObject.hideFlags = 0; - Undo.RegisterCreatedObjectUndo(dragObject, "Place " + dragObject.name); - EditorUtility.SetDirty(dragObject); - DragAndDrop.AcceptDrag(); - Selection.activeObject = dragObject; - HandleUtility.ignoreRaySnapObjects = null; - if (SceneView.mouseOverWindow != null) - SceneView.mouseOverWindow.Focus(); - dragObject.name = uniqueName; - dragObject = null; - evt.Use(); - break; - case EventType.DragExited: - if (dragObject) - { - UnityObject.DestroyImmediate(dragObject, false); - HandleUtility.ignoreRaySnapObjects = null; - dragObject = null; - evt.Use(); - } - break; - } - } - } -} diff --git a/Editor/Mono/Inspector/GenericInspector.cs b/Editor/Mono/Inspector/GenericInspector.cs deleted file mode 100644 index 5f00e15bbd..0000000000 --- a/Editor/Mono/Inspector/GenericInspector.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; - -namespace UnityEditor -{ - internal class GenericInspector : Editor - { - private AudioFilterGUI m_AudioFilterGUI = null; - - internal override bool GetOptimizedGUIBlock(bool isDirty, bool isVisible, out OptimizedGUIBlock block, out float height) - { - bool result = GetOptimizedGUIBlockImplementation(isDirty, isVisible, out block, out height); - - // Don't use optimizedGUI for audio filters - if (target is MonoBehaviour) - { - if (AudioUtil.HasAudioCallback(target as MonoBehaviour) && AudioUtil.GetCustomFilterChannelCount(target as MonoBehaviour) > 0) - { - return false; - } - } - - if (IsMissingMonoBehaviourTarget()) - return false; - - return result; - } - - internal override bool OnOptimizedInspectorGUI(Rect contentRect) - { - bool result = OptimizedInspectorGUIImplementation(contentRect); - return result; - } - - public bool MissingMonoBehaviourGUI() - { - serializedObject.Update(); - SerializedProperty scriptProperty = serializedObject.FindProperty("m_Script"); - if (scriptProperty == null) - return false; - - EditorGUILayout.PropertyField(scriptProperty); - - MonoScript targetScript = scriptProperty.objectReferenceValue as MonoScript; - bool showScriptWarning = true; - if (targetScript != null && targetScript.GetScriptTypeWasJustCreatedFromComponentMenu()) - showScriptWarning = false; - - if (showScriptWarning) - { - GUIContent c = EditorGUIUtility.TrTextContent("The associated script can not be loaded.\nPlease fix any compile errors\nand assign a valid script."); - EditorGUILayout.HelpBox(c.text, MessageType.Warning, true); - } - - if (serializedObject.ApplyModifiedProperties()) - { - EditorUtility.ForceRebuildInspectors(); - } - - return true; - } - - bool IsMissingMonoBehaviourTarget() - { - return target.GetType() == typeof(MonoBehaviour) || target.GetType() == typeof(ScriptableObject); - } - - public override void OnInspectorGUI() - { - if (IsMissingMonoBehaviourTarget() && MissingMonoBehaviourGUI()) - return; - - base.OnInspectorGUI(); - - if (target is MonoBehaviour) - { - // Does this have a AudioRead callback? - if (AudioUtil.HasAudioCallback(target as MonoBehaviour) && AudioUtil.GetCustomFilterChannelCount(target as MonoBehaviour) > 0) - { - if (m_AudioFilterGUI == null) - m_AudioFilterGUI = new AudioFilterGUI(); - m_AudioFilterGUI.DrawAudioFilterGUI(target as MonoBehaviour); - } - } - } - } -} //namespace diff --git a/Editor/Mono/Inspector/GenericPresetLibraryInspector.cs b/Editor/Mono/Inspector/GenericPresetLibraryInspector.cs deleted file mode 100644 index 89e175dda2..0000000000 --- a/Editor/Mono/Inspector/GenericPresetLibraryInspector.cs +++ /dev/null @@ -1,172 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using UnityEngine; - -namespace UnityEditor -{ - class GenericPresetLibraryInspector where T : ScriptableObject - { - readonly ScriptableObjectSaveLoadHelper m_SaveLoadHelper; - readonly UnityEngine.Object m_Target; - readonly string m_Header; - readonly VerticalGrid m_Grid; - readonly Action m_EditButtonClickedCallback; - private static GUIStyle s_EditButtonStyle; - private float m_LastRepaintedWidth = -1f; - - // Configure - public int maxShowNumPresets { get; set; } - public Vector2 presetSize { get; set; } - public float lineSpacing { get; set; } - public string extension { get { return m_SaveLoadHelper.fileExtensionWithoutDot; } } - public bool useOnePixelOverlappedGrid { get; set; } - public RectOffset marginsForList { get; set; } - public RectOffset marginsForGrid { get; set; } - public PresetLibraryEditorState.ItemViewMode itemViewMode { get; set; } - - public GenericPresetLibraryInspector(UnityEngine.Object target, string header, Action editButtonClicked) - { - m_Target = target; - m_Header = header; - m_EditButtonClickedCallback = editButtonClicked; - - string assetPath = AssetDatabase.GetAssetPath(m_Target.GetInstanceID()); - string extension = Path.GetExtension(assetPath); - if (!string.IsNullOrEmpty(extension)) - extension = extension.TrimStart('.'); - m_SaveLoadHelper = new ScriptableObjectSaveLoadHelper(extension, SaveType.Text); - m_Grid = new VerticalGrid(); - - // Default configuration - maxShowNumPresets = 49; // We clear some preview caches when they reach 50 (See AnimationCurvePreviewCache and GradientPreviewCache) - presetSize = new Vector2(14, 14); - lineSpacing = 1f; - useOnePixelOverlappedGrid = false; - marginsForList = new RectOffset(10, 10, 5, 5); - marginsForGrid = new RectOffset(10, 10, 5, 5); - itemViewMode = PresetLibraryEditorState.ItemViewMode.List; - } - - public void OnDestroy() - { - PresetLibraryManager.instance.UnloadAllLibrariesFor(m_SaveLoadHelper); - } - - public void OnInspectorGUI() - { - if (s_EditButtonStyle == null) - { - s_EditButtonStyle = new GUIStyle(EditorStyles.miniButton); - s_EditButtonStyle.margin.top = 7; - } - - string assetPath = AssetDatabase.GetAssetPath(m_Target.GetInstanceID()); - string libraryPath = Path.ChangeExtension(assetPath, null); - bool isInAnEditorFolder = libraryPath.Contains("/Editor/"); - - GUILayout.BeginHorizontal(); - GUILayout.Label(m_Header, EditorStyles.boldLabel); - GUILayout.FlexibleSpace(); - if (isInAnEditorFolder && m_EditButtonClickedCallback != null && GUILayout.Button("Edit...", s_EditButtonStyle)) - { - if (m_EditButtonClickedCallback != null) - m_EditButtonClickedCallback(libraryPath); - } - GUILayout.EndHorizontal(); - - GUILayout.Space(6); - - if (!isInAnEditorFolder) - { - GUIContent c = EditorGUIUtility.TrTextContent("Preset libraries should be placed in an 'Editor' folder.", EditorGUIUtility.warningIcon); - GUILayout.Label(c, EditorStyles.helpBox); - } - - DrawPresets(libraryPath); - } - - private void DrawPresets(string libraryPath) - { - if (GUIClip.visibleRect.width > 0) - m_LastRepaintedWidth = GUIClip.visibleRect.width; - - if (m_LastRepaintedWidth < 0) - { - GUILayoutUtility.GetRect(1, 1); // Ensure consistent call - HandleUtility.Repaint(); // Wait until we have a proper width - return; - } - - PresetLibrary lib = PresetLibraryManager.instance.GetLibrary(m_SaveLoadHelper, libraryPath) as PresetLibrary; - if (lib == null) - { - Debug.Log("Could not load preset library '" + libraryPath + "'"); - return; - } - - SetupGrid(m_LastRepaintedWidth, lib.Count(), itemViewMode); - - - int showNumPresets = Mathf.Min(lib.Count(), maxShowNumPresets); - int hiddenNumPresets = lib.Count() - showNumPresets; - float contentHeight = m_Grid.CalcRect(showNumPresets - 1, 0f).yMax + (hiddenNumPresets > 0 ? 20f : 0f); - - Rect reservedRect = GUILayoutUtility.GetRect(1, contentHeight); - - float spaceBetweenPresetAndText = presetSize.x + 6f; - for (int index = 0; index < showNumPresets; ++index) - { - Rect r = m_Grid.CalcRect(index, reservedRect.y); - Rect presetRect = new Rect(r.x, r.y, presetSize.x, presetSize.y); - lib.Draw(presetRect, index); - if (itemViewMode == PresetLibraryEditorState.ItemViewMode.List) - { - Rect nameRect = new Rect(r.x + spaceBetweenPresetAndText, r.y, r.width - spaceBetweenPresetAndText, r.height); - string name = lib.GetName(index); - GUI.Label(nameRect, name); - } - } - if (hiddenNumPresets > 0) - { - Rect textRect = new Rect(m_Grid.CalcRect(0, 0).x, reservedRect.y + contentHeight - 20f, reservedRect.width, 20f); - GUI.Label(textRect, string.Format("+ {0} more...", hiddenNumPresets)); - } - } - - void SetupGrid(float availableWidth, int itemCount, PresetLibraryEditorState.ItemViewMode presetsViewMode) - { - m_Grid.useFixedHorizontalSpacing = useOnePixelOverlappedGrid; - m_Grid.fixedHorizontalSpacing = useOnePixelOverlappedGrid ? -1 : 0; - - switch (presetsViewMode) - { - case PresetLibraryEditorState.ItemViewMode.Grid: - m_Grid.fixedWidth = availableWidth; - m_Grid.topMargin = marginsForGrid.top; - m_Grid.bottomMargin = marginsForGrid.bottom; - m_Grid.leftMargin = marginsForGrid.left; - m_Grid.rightMargin = marginsForGrid.right; - m_Grid.verticalSpacing = useOnePixelOverlappedGrid ? -1 : lineSpacing; - m_Grid.minHorizontalSpacing = 8f; - m_Grid.itemSize = presetSize; // no text - m_Grid.InitNumRowsAndColumns(itemCount, int.MaxValue); - break; - case PresetLibraryEditorState.ItemViewMode.List: - m_Grid.fixedWidth = availableWidth; - m_Grid.topMargin = marginsForList.top; - m_Grid.bottomMargin = marginsForList.bottom; - m_Grid.leftMargin = marginsForList.left; - m_Grid.rightMargin = marginsForList.right; - m_Grid.verticalSpacing = lineSpacing; - m_Grid.minHorizontalSpacing = 0f; - m_Grid.itemSize = new Vector2(availableWidth - m_Grid.leftMargin, presetSize.y); - m_Grid.InitNumRowsAndColumns(itemCount, int.MaxValue); - break; - } - } - } -} diff --git a/Editor/Mono/Inspector/GradientPresetLibraryInspector.cs b/Editor/Mono/Inspector/GradientPresetLibraryInspector.cs deleted file mode 100644 index 9618f7b627..0000000000 --- a/Editor/Mono/Inspector/GradientPresetLibraryInspector.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(GradientPresetLibrary))] - internal class GradientPresetLibraryEditor : Editor - { - private GenericPresetLibraryInspector m_GenericPresetLibraryInspector; - - public void OnEnable() - { - m_GenericPresetLibraryInspector = new GenericPresetLibraryInspector(target, "Gradient Preset Library", OnEditButtonClicked); - m_GenericPresetLibraryInspector.presetSize = new Vector2(72, 16); - m_GenericPresetLibraryInspector.lineSpacing = 4f; - } - - public void OnDestroy() - { - if (m_GenericPresetLibraryInspector != null) - m_GenericPresetLibraryInspector.OnDestroy(); - } - - public override void OnInspectorGUI() - { - m_GenericPresetLibraryInspector.itemViewMode = PresetLibraryEditorState.GetItemViewMode("Gradient"); // ensure in-sync - if (m_GenericPresetLibraryInspector != null) - m_GenericPresetLibraryInspector.OnInspectorGUI(); - } - - private void OnEditButtonClicked(string libraryPath) - { - GradientPicker.Show(new Gradient(), true); - GradientPicker.instance.currentPresetLibrary = libraryPath; - } - } -} // namespace diff --git a/Editor/Mono/Inspector/GraphicsSettingsInspector.cs b/Editor/Mono/Inspector/GraphicsSettingsInspector.cs deleted file mode 100644 index d8ddc98797..0000000000 --- a/Editor/Mono/Inspector/GraphicsSettingsInspector.cs +++ /dev/null @@ -1,176 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; - -using TierSettingsEditor = UnityEditor.GraphicsSettingsWindow.TierSettingsEditor; -using BuiltinShadersEditor = UnityEditor.GraphicsSettingsWindow.BuiltinShadersEditor; -using AlwaysIncludedShadersEditor = UnityEditor.GraphicsSettingsWindow.AlwaysIncludedShadersEditor; -using ShaderStrippingEditor = UnityEditor.GraphicsSettingsWindow.ShaderStrippingEditor; -using ShaderPreloadEditor = UnityEditor.GraphicsSettingsWindow.ShaderPreloadEditor; - -using UnityEngine.Experimental.Rendering; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - [CustomEditor(typeof(UnityEngine.Rendering.GraphicsSettings))] - internal class GraphicsSettingsInspector : ProjectSettingsBaseEditor - { - internal class Styles - { - public static readonly GUIContent showEditorWindow = EditorGUIUtility.TrTextContent("Open Editor..."); - public static readonly GUIContent closeEditorWindow = EditorGUIUtility.TrTextContent("Close Editor"); - public static readonly GUIContent tierSettings = EditorGUIUtility.TrTextContent("Tier Settings"); - public static readonly GUIContent builtinSettings = EditorGUIUtility.TrTextContent("Built-in Shader Settings"); - public static readonly GUIContent shaderStrippingSettings = EditorGUIUtility.TrTextContent("Shader Stripping"); - public static readonly GUIContent shaderPreloadSettings = EditorGUIUtility.TrTextContent("Shader Preloading"); - public static readonly GUIContent cameraSettings = EditorGUIUtility.TrTextContent("Camera Settings"); - public static readonly GUIContent renderPipeSettings = EditorGUIUtility.TrTextContent("Scriptable Render Pipeline Settings"); - public static readonly GUIContent renderPipeLabel = EditorGUIUtility.TrTextContent("Scriptable Render Pipeline"); - } - - Editor m_TierSettingsEditor; - Editor m_BuiltinShadersEditor; - Editor m_AlwaysIncludedShadersEditor; - Editor m_ShaderStrippingEditor; - Editor m_ShaderPreloadEditor; - SerializedProperty m_TransparencySortMode; - SerializedProperty m_TransparencySortAxis; - SerializedProperty m_ScriptableRenderLoop; - - Object graphicsSettings - { - get { return UnityEngine.Rendering.GraphicsSettings.GetGraphicsSettings(); } - } - - Editor tierSettingsEditor - { - get - { - Editor.CreateCachedEditor(graphicsSettings, typeof(TierSettingsEditor), ref m_TierSettingsEditor); - ((TierSettingsEditor)m_TierSettingsEditor).verticalLayout = true; - return m_TierSettingsEditor; - } - } - Editor builtinShadersEditor - { - get { Editor.CreateCachedEditor(graphicsSettings, typeof(BuiltinShadersEditor), ref m_BuiltinShadersEditor); return m_BuiltinShadersEditor; } - } - Editor alwaysIncludedShadersEditor - { - get { Editor.CreateCachedEditor(graphicsSettings, typeof(AlwaysIncludedShadersEditor), ref m_AlwaysIncludedShadersEditor); return m_AlwaysIncludedShadersEditor; } - } - Editor shaderStrippingEditor - { - get { Editor.CreateCachedEditor(graphicsSettings, typeof(ShaderStrippingEditor), ref m_ShaderStrippingEditor); return m_ShaderStrippingEditor; } - } - Editor shaderPreloadEditor - { - get { Editor.CreateCachedEditor(graphicsSettings, typeof(ShaderPreloadEditor), ref m_ShaderPreloadEditor); return m_ShaderPreloadEditor; } - } - - public void OnEnable() - { - m_TransparencySortMode = serializedObject.FindProperty("m_TransparencySortMode"); - m_TransparencySortAxis = serializedObject.FindProperty("m_TransparencySortAxis"); - m_ScriptableRenderLoop = serializedObject.FindProperty("m_CustomRenderPipeline"); - } - - private void HandleEditorWindowButton() - { - TierSettingsWindow window = TierSettingsWindow.GetInstance(); - GUIContent text = window == null ? Styles.showEditorWindow : Styles.closeEditorWindow; - if (GUILayout.Button(text, EditorStyles.miniButton, GUILayout.Width(110))) - { - if (window) - { - window.Close(); - } - else - { - TierSettingsWindow.CreateWindow(); - TierSettingsWindow.GetInstance().Show(); - } - } - } - - // this is category animation is blatantly copied from PlayerSettingsEditor.cs - private bool showTierSettingsUI = true; // show by default, as otherwise users are confused - private UnityEditor.AnimatedValues.AnimBool tierSettingsAnimator = null; - - private void TierSettingsGUI() - { - if (tierSettingsAnimator == null) - tierSettingsAnimator = new UnityEditor.AnimatedValues.AnimBool(showTierSettingsUI, Repaint); - - bool enabled = GUI.enabled; - GUI.enabled = true; // we don't want to disable the expand behavior - EditorGUILayout.BeginVertical(GUI.skin.box); - - EditorGUILayout.BeginHorizontal(); - Rect r = GUILayoutUtility.GetRect(20, 18); r.x += 3; r.width += 6; - showTierSettingsUI = GUI.Toggle(r, showTierSettingsUI, Styles.tierSettings, EditorStyles.inspectorTitlebarText); - HandleEditorWindowButton(); - EditorGUILayout.EndHorizontal(); - - tierSettingsAnimator.target = showTierSettingsUI; - GUI.enabled = enabled; - - if (EditorGUILayout.BeginFadeGroup(tierSettingsAnimator.faded) && TierSettingsWindow.GetInstance() == null) - tierSettingsEditor.OnInspectorGUI(); - EditorGUILayout.EndFadeGroup(); - EditorGUILayout.EndVertical(); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - GUILayout.Label(Styles.renderPipeSettings, EditorStyles.boldLabel); - Rect renderLoopRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(m_ScriptableRenderLoop)); - - EditorGUI.BeginProperty(renderLoopRect, Styles.renderPipeLabel, m_ScriptableRenderLoop); - - m_ScriptableRenderLoop.objectReferenceValue = - EditorGUI.ObjectField(renderLoopRect, m_ScriptableRenderLoop.objectReferenceValue, typeof(RenderPipelineAsset), false); - - EditorGUI.EndProperty(); - EditorGUILayout.Space(); - - - bool usingSRP = GraphicsSettings.renderPipelineAsset != null; - - if (usingSRP) - EditorGUILayout.HelpBox("A Scriptable Render Pipeline is in use, some settings will not be used and are hidden", MessageType.Info); - - if (!usingSRP) - { - GUILayout.Label(Styles.cameraSettings, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_TransparencySortMode); - EditorGUILayout.PropertyField(m_TransparencySortAxis); - - EditorGUILayout.Space(); - } - - TierSettingsGUI(); - - GUILayout.Label(Styles.builtinSettings, EditorStyles.boldLabel); - if (!usingSRP) - builtinShadersEditor.OnInspectorGUI(); - alwaysIncludedShadersEditor.OnInspectorGUI(); - - EditorGUILayout.Space(); - GUILayout.Label(Styles.shaderStrippingSettings, EditorStyles.boldLabel); - shaderStrippingEditor.OnInspectorGUI(); - - EditorGUILayout.Space(); - GUILayout.Label(Styles.shaderPreloadSettings, EditorStyles.boldLabel); - shaderPreloadEditor.OnInspectorGUI(); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/HingeJoint2DEditor.cs b/Editor/Mono/Inspector/HingeJoint2DEditor.cs deleted file mode 100644 index 521cf41002..0000000000 --- a/Editor/Mono/Inspector/HingeJoint2DEditor.cs +++ /dev/null @@ -1,160 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor.IMGUI.Controls; -using UnityEditorInternal; -using UnityEngine; -using UnityObject = UnityEngine.Object; - -namespace UnityEditor -{ - [CustomEditor(typeof(HingeJoint2D))] - [CanEditMultipleObjects] - internal class HingeJoint2DEditor : AnchoredJoint2DEditor - { - new protected static class Styles - { - public static readonly GUIContent editAngularLimitsButton = new GUIContent(EditorGUIUtility.IconContent("JointAngularLimits")); - public static readonly string editAngularLimitsUndoMessage = EditorGUIUtility.TrTextContent("Change Joint Angular Limits").text; - public static readonly Color handleColor = new Color(0f, 1f, 0f, 0.7f); - public static readonly float handleRadius = 0.8f; - - static Styles() - { - editAngularLimitsButton.tooltip = EditorGUIUtility.TrTextContent("Edit joint angular limits.").text; - } - } - - private JointAngularLimitHandle m_AngularLimitHandle = new JointAngularLimitHandle(); - - new public void OnEnable() - { - base.OnEnable(); - - m_AngularLimitHandle.xHandleColor = Color.white; - m_AngularLimitHandle.yHandleColor = Color.clear; - m_AngularLimitHandle.zHandleColor = Color.clear; - - m_AngularLimitHandle.yMotion = ConfigurableJointMotion.Locked; - m_AngularLimitHandle.zMotion = ConfigurableJointMotion.Locked; - - // +/-PHYSICS_2D_LARGE_RANGE_CLAMP, which is currently used in JointAngleLimits2D.CheckConsistency() - m_AngularLimitHandle.xRange = new Vector2(-1e+6f, 1e+6f); - } - - public override void OnInspectorGUI() - { - HingeJoint2D joint = (HingeJoint2D)target; - EditMode.DoEditModeInspectorModeButton( - EditMode.SceneViewEditMode.JointAngularLimits, - "Edit Joint Angular Limits", - Styles.editAngularLimitsButton, - this - ); - - base.OnInspectorGUI(); - } - - internal override Bounds GetWorldBoundsOfTarget(UnityObject targetObject) - { - var bounds = base.GetWorldBoundsOfTarget(targetObject); - // ensure joint's anchor point is included in bounds - var joint = (HingeJoint2D)targetObject; - bounds.Encapsulate(TransformPoint(joint.transform, joint.anchor)); - return bounds; - } - - private static readonly Quaternion s_RightHandedHandleOrientationOffset = - Quaternion.AngleAxis(180f, Vector3.right) * Quaternion.AngleAxis(90f, Vector3.up); - private static readonly Quaternion s_LeftHandedHandleOrientationOffset = - Quaternion.AngleAxis(180f, Vector3.forward) * Quaternion.AngleAxis(90f, Vector3.up); - - new public void OnSceneGUI() - { - var hingeJoint2D = (HingeJoint2D)target; - - // Ignore disabled joint. - if (!hingeJoint2D.enabled) - return; - - m_AngularLimitHandle.xMotion = hingeJoint2D.useLimits ? ConfigurableJointMotion.Limited : ConfigurableJointMotion.Free; - - JointAngleLimits2D limit; - - limit = hingeJoint2D.limits; - m_AngularLimitHandle.xMin = limit.min; - m_AngularLimitHandle.xMax = limit.max; - - // only display control handles on manipulator if in edit mode - var editMode = EditMode.editMode == EditMode.SceneViewEditMode.JointAngularLimits && EditMode.IsOwner(this); - if (editMode) - m_AngularLimitHandle.angleHandleDrawFunction = ArcHandle.DefaultAngleHandleDrawFunction; - else - m_AngularLimitHandle.angleHandleDrawFunction = null; - - // to enhance usability, orient the manipulator to best illustrate its affects on the dynamic body in the system - var dynamicBody = hingeJoint2D.attachedRigidbody; - var dynamicBodyLocalReferencePosition = Vector3.right; - var dynamicAnchor = hingeJoint2D.anchor; - var connectedBody = hingeJoint2D.connectedBody; - var handleOrientationOffset = s_RightHandedHandleOrientationOffset; - if ( - dynamicBody.bodyType != RigidbodyType2D.Dynamic - && hingeJoint2D.connectedBody != null - && hingeJoint2D.connectedBody.bodyType == RigidbodyType2D.Dynamic - ) - { - dynamicBody = hingeJoint2D.connectedBody; - dynamicBodyLocalReferencePosition = Vector3.left; - dynamicAnchor = hingeJoint2D.connectedAnchor; - connectedBody = hingeJoint2D.attachedRigidbody; - handleOrientationOffset = s_LeftHandedHandleOrientationOffset; - } - - var handlePosition = TransformPoint(dynamicBody.transform, dynamicAnchor); - var handleOrientation = ( - connectedBody == null ? - Quaternion.identity : - Quaternion.LookRotation(Vector3.forward, connectedBody.transform.rotation * Vector3.up) - ) * handleOrientationOffset; - var dynamicActorReferencePosition = - handlePosition - + Quaternion.LookRotation(Vector3.forward, dynamicBody.transform.rotation * Vector3.up) - * dynamicBodyLocalReferencePosition; - - var handleMatrix = Matrix4x4.TRS(handlePosition, handleOrientation, Vector3.one); - - EditorGUI.BeginChangeCheck(); - - using (new Handles.DrawingScope(Styles.handleColor, handleMatrix)) - { - var radius = HandleUtility.GetHandleSize(Vector3.zero) * Styles.handleRadius; - m_AngularLimitHandle.radius = radius; - - // reference line within arc to illustrate affected local axis - Handles.DrawLine( - Vector3.zero, - handleMatrix.inverse.MultiplyPoint3x4(dynamicActorReferencePosition).normalized * radius - ); - - m_AngularLimitHandle.DrawHandle(); - } - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(hingeJoint2D, Styles.editAngularLimitsUndoMessage); - - limit = hingeJoint2D.limits; - limit.min = m_AngularLimitHandle.xMin; - limit.max = m_AngularLimitHandle.xMax; - hingeJoint2D.limits = limit; - - dynamicBody.WakeUp(); - } - - base.OnSceneGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/HingeJointEditor.cs b/Editor/Mono/Inspector/HingeJointEditor.cs deleted file mode 100644 index 89b599a3ee..0000000000 --- a/Editor/Mono/Inspector/HingeJointEditor.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(HingeJoint)), CanEditMultipleObjects] - class HingeJointEditor : JointEditor - { - private static readonly GUIContent s_WarningMessage = - EditorGUIUtility.TrTextContent("Min and max limits must be within the range [-180, 180]."); - - private SerializedProperty m_MinLimit; - private SerializedProperty m_MaxLimit; - - void OnEnable() - { - angularLimitHandle.yMotion = ConfigurableJointMotion.Locked; - angularLimitHandle.zMotion = ConfigurableJointMotion.Locked; - - angularLimitHandle.yHandleColor = Color.clear; - angularLimitHandle.zHandleColor = Color.clear; - - angularLimitHandle.xRange = new Vector2(-Physics.k_MaxFloatMinusEpsilon, Physics.k_MaxFloatMinusEpsilon); - - m_MinLimit = serializedObject.FindProperty("m_Limits.min"); - m_MaxLimit = serializedObject.FindProperty("m_Limits.max"); - } - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - - float min = m_MinLimit.floatValue; - float max = m_MaxLimit.floatValue; - - if (min < -180f || min > 180f || max < -180f || max > 180f) - EditorGUILayout.HelpBox(s_WarningMessage.text, MessageType.Warning); - } - - protected override void GetActors( - HingeJoint joint, - out Rigidbody dynamicActor, - out Rigidbody connectedActor, - out int jointFrameActorIndex, - out bool rightHandedLimit - ) - { - base.GetActors(joint, out dynamicActor, out connectedActor, out jointFrameActorIndex, out rightHandedLimit); - rightHandedLimit = true; - } - - protected override void DoAngularLimitHandles(HingeJoint joint) - { - base.DoAngularLimitHandles(joint); - - angularLimitHandle.xMotion = joint.useLimits ? ConfigurableJointMotion.Limited : ConfigurableJointMotion.Free; - - JointLimits limit; - - limit = joint.limits; - angularLimitHandle.xMin = limit.min; - angularLimitHandle.xMax = limit.max; - - EditorGUI.BeginChangeCheck(); - - angularLimitHandle.radius = GetAngularLimitHandleSize(Vector3.zero); - angularLimitHandle.DrawHandle(); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(joint, Styles.editAngularLimitsUndoMessage); - - limit = joint.limits; - limit.min = angularLimitHandle.xMin; - limit.max = angularLimitHandle.xMax; - joint.limits = limit; - } - } - } -} diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs deleted file mode 100644 index fd2e8ed44a..0000000000 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ /dev/null @@ -1,1615 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -//#define PERF_PROFILE -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.Experimental.AssetImporters; -using UnityEngine; -using UnityEditorInternal; -using UnityEditorInternal.VersionControl; -using Object = UnityEngine.Object; -using UnityEditor.VersionControl; -using UnityEngine.Events; -using UnityEngine.Profiling; -using UnityEngine.SceneManagement; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Inspector", useTypeNameAsIconName = true)] - internal class InspectorWindow : EditorWindow, IHasCustomMenu, ISerializationCallbackReceiver - { - internal Vector2 m_ScrollPosition; - internal InspectorMode m_InspectorMode = InspectorMode.Normal; - - static readonly List m_AllInspectors = new List(); - static bool s_AllOptimizedGUIBlocksNeedsRebuild; - - const float kBottomToolbarHeight = 17f; - internal const int kInspectorPaddingLeft = 4 + 10; - internal const int kInspectorPaddingRight = 4; - - private const long delayRepaintWhilePlayingAnimation = 150; // Delay between repaints in milliseconds while playing animation - private long s_LastUpdateWhilePlayingAnimation = 0; - - bool m_ResetKeyboardControl; - protected ActiveEditorTracker m_Tracker; - - [SerializeField] - protected List m_ObjectsLockedBeforeSerialization = new List(); - - [SerializeField] - protected List m_InstanceIDsLockedBeforeSerialization = new List(); - - [SerializeField] - EditorGUIUtility.EditorLockTrackerWithActiveEditorTracker m_LockTracker = new EditorGUIUtility.EditorLockTrackerWithActiveEditorTracker(); - - Editor m_LastInteractedEditor; - bool m_IsOpenForEdit = false; - - private static Styles s_Styles; - internal static Styles styles { get { return s_Styles ?? (s_Styles = new Styles()); } } - - [SerializeField] - PreviewResizer m_PreviewResizer = new PreviewResizer(); - [SerializeField] - PreviewWindow m_PreviewWindow; - - LabelGUI m_LabelGUI = new LabelGUI(); - AssetBundleNameGUI m_AssetBundleNameGUI = new AssetBundleNameGUI(); - - TypeSelectionList m_TypeSelectionList = null; - - private double m_lastRenderedTime; - private bool m_InvalidateGUIBlockCache = true; - - private List m_Previews; - private IPreviewable m_SelectedPreview; - - private EditorDragging editorDragging; - - internal class Styles - { - public readonly GUIStyle preToolbar = "preToolbar"; - public readonly GUIStyle preToolbar2 = "preToolbar2"; - public readonly GUIStyle preDropDown = "preDropDown"; - public readonly GUIStyle dragHandle = "RL DragHandle"; - public readonly GUIStyle lockButton = "IN LockButton"; - public readonly GUIStyle insertionMarker = "InsertionMarker"; - public readonly GUIContent preTitle = EditorGUIUtility.TrTextContent("Preview"); - public readonly GUIContent labelTitle = EditorGUIUtility.TrTextContent("Asset Labels"); - public readonly GUIContent addComponentLabel = EditorGUIUtility.TrTextContent("Add Component"); - public GUIStyle preBackground = "preBackground"; - public GUIStyle addComponentArea = EditorStyles.inspectorTitlebar; - public GUIStyle addComponentButtonStyle = "AC Button"; - public GUIStyle previewMiniLabel = new GUIStyle(EditorStyles.whiteMiniLabel); - public GUIStyle typeSelection = new GUIStyle("PR Label"); - public GUIStyle lockedHeaderButton = "preButton"; - public GUIStyle stickyNote = new GUIStyle("VCS_StickyNote"); - public GUIStyle stickyNoteArrow = new GUIStyle("VCS_StickyNoteArrow"); - public GUIStyle stickyNotePerforce = new GUIStyle("VCS_StickyNoteP4"); - public GUIStyle stickyNoteLabel = new GUIStyle("VCS_StickyNoteLabel"); - public readonly GUIContent VCS_NotConnectedMessage = EditorGUIUtility.TrTextContent("VCS Plugin {0} is enabled but not connected"); - - public Styles() - { - typeSelection.padding.left = 12; - } - } - - internal InspectorWindow() - { - editorDragging = new EditorDragging(this); - } - - void Awake() - { - if (!m_AllInspectors.Contains(this)) - m_AllInspectors.Add(this); - } - - void OnDestroy() - { - if (m_PreviewWindow != null) - m_PreviewWindow.Close(); - if (m_Tracker != null && !m_Tracker.Equals(ActiveEditorTracker.sharedTracker)) - m_Tracker.Destroy(); - } - - protected virtual void OnEnable() - { - RefreshTitle(); - minSize = new Vector2(275, 50); - - if (!m_AllInspectors.Contains(this)) - m_AllInspectors.Add(this); - - m_PreviewResizer.Init("InspectorPreview"); - m_LabelGUI.OnEnable(); - - // ensure tracker is valid here in case domain is reloaded before first time inspector is drawn - // fixes case 829182 - CreateTracker(); - - RestoreLockStateFromSerializedData(); - - if (m_LockTracker == null) - { - m_LockTracker = new EditorGUIUtility.EditorLockTrackerWithActiveEditorTracker(); - } - m_LockTracker.tracker = tracker; - m_LockTracker.lockStateChanged.AddListener(LockStateChanged); - - - EditorApplication.projectWasLoaded += OnProjectWasLoaded; - } - - private void OnProjectWasLoaded() - { - // EditorApplication.projectWasLoaded, which acalls this, fires after OnEnabled - // therefore the logic in OnEnabled already tried to de-serialize the locked opbjects, including those it only had InstanceIDs of - // This needs to get fixed here as the InstanceIDs have been reshuffled with the new session and could resolving to random Objects - if (m_InstanceIDsLockedBeforeSerialization.Count > 0) - { - // Game objects will have new instanceIDs in a new Unity session, so take out all objects that where reconstructed from InstanceIDs - for (int i = m_InstanceIDsLockedBeforeSerialization.Count - 1; i >= 0; i--) - { - for (int j = m_ObjectsLockedBeforeSerialization.Count - 1; j >= 0; j--) - { - if (m_ObjectsLockedBeforeSerialization[j] == null || m_ObjectsLockedBeforeSerialization[j].GetInstanceID() == m_InstanceIDsLockedBeforeSerialization[i]) - { - m_ObjectsLockedBeforeSerialization.RemoveAt(j); - break; - } - } - } - m_InstanceIDsLockedBeforeSerialization.Clear(); - RestoreLockStateFromSerializedData(); - } - } - - protected virtual void OnDisable() - { - m_AllInspectors.Remove(this); - if (m_LockTracker != null) - m_LockTracker.lockStateChanged.RemoveListener(LockStateChanged); - - EditorApplication.projectWasLoaded -= OnProjectWasLoaded; - } - - void OnLostFocus() - { - m_LabelGUI.OnLostFocus(); - } - - static internal void RepaintAllInspectors() - { - foreach (var win in m_AllInspectors) - win.Repaint(); - } - - internal static List GetInspectors() - { - return m_AllInspectors; - } - - void OnSelectionChange() - { - m_Previews = null; - m_SelectedPreview = null; - m_TypeSelectionList = null; - if (m_Parent != null) // parent may be null in some situations (case 970700, 851988) - m_Parent.ClearKeyboardControl(); - ScriptAttributeUtility.ClearGlobalCache(); - Repaint(); - } - - static internal InspectorWindow[] GetAllInspectorWindows() - { - return m_AllInspectors.ToArray(); - } - - private void OnInspectorUpdate() - { - // Check if scripts have changed without calling set dirty - tracker.VerifyModifiedMonoBehaviours(); - - if (!tracker.isDirty || !ReadyToRepaint()) - return; - - Repaint(); - } - - public virtual void AddItemsToMenu(GenericMenu menu) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Normal"), m_InspectorMode == InspectorMode.Normal, SetNormal); - menu.AddItem(EditorGUIUtility.TrTextContent("Debug"), m_InspectorMode == InspectorMode.Debug, SetDebug); - if (Unsupported.IsDeveloperMode()) - menu.AddItem(EditorGUIUtility.TrTextContent("Debug-Internal"), m_InspectorMode == InspectorMode.DebugInternal, SetDebugInternal); - - menu.AddSeparator(string.Empty); - m_LockTracker.AddItemsToMenu(menu); - } - - void RefreshTitle() - { - string iconName = "UnityEditor.InspectorWindow"; - if (m_InspectorMode == InspectorMode.Normal) - titleContent = EditorGUIUtility.TrTextContentWithIcon("Inspector", iconName); - else - titleContent = EditorGUIUtility.TrTextContentWithIcon("Debug", iconName); - } - - void SetMode(InspectorMode mode) - { - m_InspectorMode = mode; - RefreshTitle(); - tracker.inspectorMode = mode; - m_ResetKeyboardControl = true; - } - - void SetDebug() - { - SetMode(InspectorMode.Debug); - } - - void SetNormal() - { - SetMode(InspectorMode.Normal); - } - - void SetDebugInternal() - { - SetMode(InspectorMode.DebugInternal); - } - - void FlipLocked() - { - isLocked = !isLocked; - } - - public bool isLocked - { - get - { - //this makes sure the getter for InspectorWindow.tracker gets called and creates an ActiveEditorTracker if needed - m_LockTracker.tracker = tracker; - return m_LockTracker.isLocked; - } - set - { - //this makes sure the getter for InspectorWindow.tracker gets called and creates an ActiveEditorTracker if needed - m_LockTracker.tracker = tracker; - m_LockTracker.isLocked = value; - } - } - - static void DoInspectorDragAndDrop(Rect rect, Object[] targets) - { - if (!Dragging(rect)) - return; - - DragAndDrop.visualMode = InternalEditorUtility.InspectorWindowDrag(targets, Event.current.type == EventType.DragPerform); - - if (Event.current.type == EventType.DragPerform) - DragAndDrop.AcceptDrag(); - } - - private static bool Dragging(Rect rect) - { - return (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) && rect.Contains(Event.current.mousePosition); - } - - internal ActiveEditorTracker tracker - { - get - { - CreateTracker(); - return m_Tracker; - } - } - - protected virtual void CreateTracker() - { - if (m_Tracker != null) - { - // Ensure that inspector mode - // This shouldn't be necessary but there are some non-reproducable bugs objects showing up as not able to multi-edit - // because this state goes out of sync. - m_Tracker.inspectorMode = m_InspectorMode; - return; - } - - var sharedTracker = ActiveEditorTracker.sharedTracker; - bool sharedTrackerInUse = m_AllInspectors.Any(i => i.m_Tracker != null && i.m_Tracker.Equals(sharedTracker)); - m_Tracker = sharedTrackerInUse ? new ActiveEditorTracker() : ActiveEditorTracker.sharedTracker; - m_Tracker.inspectorMode = m_InspectorMode; - m_Tracker.RebuildIfNecessary(); - } - - protected virtual void CreatePreviewables() - { - if (m_Previews != null) - return; - - m_Previews = new List(); - - if (tracker.activeEditors.Length == 0) - return; - - foreach (var editor in tracker.activeEditors) - { - IEnumerable previews = GetPreviewsForType(editor); - foreach (var preview in previews) - { - m_Previews.Add(preview); - } - } - } - - private IEnumerable GetPreviewsForType(Editor editor) - { - //TODO: cache this in a map. probably in another utility class - List previews = new List(); - - foreach (var type in EditorAssemblies.GetAllTypesWithInterface()) - { - if (typeof(Editor).IsAssignableFrom(type)) //we don't want Editor classes with preview here. - continue; - - var attrs = type.GetCustomAttributes(typeof(CustomPreviewAttribute), false); - foreach (var attr in attrs) - { - var previewAttr = (CustomPreviewAttribute)attr; - if (editor.target == null || previewAttr.m_Type != editor.target.GetType()) - continue; - - var preview = Activator.CreateInstance(type) as IPreviewable; - preview.Initialize(editor.targets); - previews.Add(preview); - } - } - return previews; - } - - protected virtual void ShowButton(Rect r) - { - m_LockTracker.ShowButton(r, styles.lockButton); - } - - private void LockStateChanged(bool lockeState) - { - tracker.RebuildIfNecessary(); - } - - - static internal InspectorWindow s_CurrentInspectorWindow; - - - protected virtual void OnGUI() - { - Profiler.BeginSample("InspectorWindow.OnGUI"); - - CreatePreviewables(); - FlushAllOptimizedGUIBlocksIfNeeded(); - - ResetKeyboardControl(); - m_ScrollPosition = EditorGUILayout.BeginVerticalScrollView(m_ScrollPosition); - { - if (Event.current.type == EventType.Repaint) - tracker.ClearDirty(); - - s_CurrentInspectorWindow = this; - Editor[] editors = tracker.activeEditors; - - Profiler.BeginSample("InspectorWindow.DrawEditors()"); - DrawEditors(editors); - Profiler.EndSample(); - - if (tracker.hasComponentsWhichCannotBeMultiEdited) - { - if (editors.Length == 0 && !tracker.isLocked && Selection.objects.Length > 0) - { - DrawSelectionPickerList(); - } - else - { - // Visually separates the Add Component button from the existing components - Rect lineRect = GUILayoutUtility.GetRect(10, 4, EditorStyles.inspectorTitlebar); - if (Event.current.type == EventType.Repaint) - DrawSplitLine(lineRect.y); - - GUILayout.Label( - "Components that are only on some of the selected objects cannot be multi-edited.", - EditorStyles.helpBox); - - GUILayout.Space(4); - } - } - - s_CurrentInspectorWindow = null; - EditorGUI.indentLevel = 0; - - AddComponentButton(tracker.activeEditors); - - GUI.enabled = true; - CheckDragAndDrop(tracker.activeEditors); - MoveFocusOnKeyPress(); - } - EditorGUILayout.EndScrollView(); - - Profiler.BeginSample("InspectorWindow.DrawPreviewAndLabels"); - DrawPreviewAndLabels(); - Profiler.EndSample(); - - if (tracker.activeEditors.Length > 0) - { - DrawVCSShortInfo(); - } - - - Profiler.EndSample(); - } - - internal virtual Editor GetLastInteractedEditor() - { - return m_LastInteractedEditor; - } - - internal IPreviewable GetEditorThatControlsPreview(IPreviewable[] editors) - { - if (editors.Length == 0) - return null; - - if (m_SelectedPreview != null) - { - return m_SelectedPreview; - } - - // Find last interacted editor, if not found check if we had an editor of similar type, - // if not found use first editor that can show a preview otherwise return null. - - IPreviewable lastInteractedEditor = GetLastInteractedEditor(); - Type lastType = (lastInteractedEditor != null) ? lastInteractedEditor.GetType() : null; - - IPreviewable firstEditorThatHasPreview = null; - IPreviewable similarEditorAsLast = null; - foreach (IPreviewable e in editors) - { - if (e == null || e.target == null) - continue; - - // If target is an asset, but not the same asset as the asset - // of the first editor, then ignore it. This will prevent showing - // preview of materials attached to a GameObject but should cover - // future use cases as well. - if (EditorUtility.IsPersistent(e.target) && - AssetDatabase.GetAssetPath(e.target) != AssetDatabase.GetAssetPath(editors[0].target)) - continue; - - // If main editor is an asset importer editor and this is an editor of the imported object, ignore. - if (editors[0] is AssetImporterEditor && !(e is AssetImporterEditor)) - continue; - - if (e.HasPreviewGUI()) - { - if (e == lastInteractedEditor) - return e; - - if (similarEditorAsLast == null && e.GetType() == lastType) - similarEditorAsLast = e; - - if (firstEditorThatHasPreview == null) - firstEditorThatHasPreview = e; - } - } - - if (similarEditorAsLast != null) - return similarEditorAsLast; - - if (firstEditorThatHasPreview != null) - return firstEditorThatHasPreview; - - // Found no valid editor - return null; - } - - internal IPreviewable[] GetEditorsWithPreviews(Editor[] editors) - { - IList editorsWithPreview = new List(); - - int i = -1; - foreach (Editor e in editors) - { - ++i; - if (e.target == null) - continue; - - // If target is an asset, but not the same asset as the asset - // of the first editor, then ignore it. This will prevent showing - // preview of materials attached to a GameObject but should cover - // future use cases as well. - if (EditorUtility.IsPersistent(e.target) && - AssetDatabase.GetAssetPath(e.target) != AssetDatabase.GetAssetPath(editors[0].target)) - continue; - - if (!EditorUtility.IsPersistent(editors[0].target) && EditorUtility.IsPersistent(e.target)) - continue; - - if (ShouldCullEditor(editors, i)) - continue; - - // If main editor is an asset importer editor and this is an editor of the imported object, ignore. - if (editors[0] is AssetImporterEditor && !(e is AssetImporterEditor)) - continue; - - if (e.HasPreviewGUI()) - { - editorsWithPreview.Add(e); - } - } - - foreach (var previewable in m_Previews) - { - if (previewable.HasPreviewGUI()) - editorsWithPreview.Add(previewable); - } - - return editorsWithPreview.ToArray(); - } - - internal Object GetInspectedObject() - { - Editor editor = GetFirstNonImportInspectorEditor(tracker.activeEditors); - if (editor == null) - return null; - return editor.target; - } - - Editor GetFirstNonImportInspectorEditor(Editor[] editors) - { - foreach (Editor e in editors) - { - // Check for target rather than the editor type itself, - // because some importers use default inspector - if (e.target is AssetImporter) - continue; - return e; - } - return null; - } - - private void MoveFocusOnKeyPress() - { - var key = Event.current.keyCode; - - if (Event.current.type != EventType.KeyDown || (key != KeyCode.DownArrow && key != KeyCode.UpArrow && key != KeyCode.Tab)) - return; - - if (key != KeyCode.Tab) - EditorGUIUtility.MoveFocusAndScroll(key == KeyCode.DownArrow); - else - EditorGUIUtility.ScrollForTabbing(!Event.current.shift); - - Event.current.Use(); - } - - private void ResetKeyboardControl() - { - if (m_ResetKeyboardControl) - { - GUIUtility.keyboardControl = 0; - m_ResetKeyboardControl = false; - } - } - - private void CheckDragAndDrop(Editor[] editors) - { - Rect remainingRect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true)); - - if (remainingRect.Contains(Event.current.mousePosition)) - { - Editor editor = GetFirstNonImportInspectorEditor(editors); - if (editor != null) - DoInspectorDragAndDrop(remainingRect, editor.targets); - - if (Event.current.type == EventType.MouseDown) - { - GUIUtility.keyboardControl = 0; - Event.current.Use(); - } - } - - editorDragging.HandleDraggingToBottomArea(remainingRect, m_Tracker); - } - - static bool HasLabel(Object target) - { - return HasLabel(target, AssetDatabase.GetAssetPath(target)); - } - - static bool HasLabel(Object target, string assetPath) - { - return EditorUtility.IsPersistent(target) && assetPath.StartsWith("assets", StringComparison.OrdinalIgnoreCase); - } - - private Object[] GetInspectedAssets() - { - // 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 - Editor assetEditor = GetFirstNonImportInspectorEditor(tracker.activeEditors); - if (assetEditor != null && assetEditor.targets.Length == 1) - { - string assetPath = AssetDatabase.GetAssetPath(assetEditor.target); - if (HasLabel(assetEditor.target, assetPath) && !Directory.Exists(assetPath)) - return assetEditor.targets; - } - - // This is used if more than one asset is selected - // Ideally the tracker should be refactored to track not just editors but also the selection that caused them, so we wouldn't need this - return Selection.objects.Where(HasLabel).ToArray(); - } - - private void DrawPreviewAndLabels() - { - if (m_PreviewWindow && Event.current.type == EventType.Repaint) - m_PreviewWindow.Repaint(); - - IPreviewable[] editorsWithPreviews = GetEditorsWithPreviews(tracker.activeEditors); - IPreviewable previewEditor = GetEditorThatControlsPreview(editorsWithPreviews); - - // Do we have a preview? - bool hasPreview = previewEditor != null && - previewEditor.HasPreviewGUI() && - (m_PreviewWindow == null); - - Object[] assets = GetInspectedAssets(); - bool hasLabels = assets.Length > 0; - bool hasBundleName = assets.Any(a => !(a is MonoScript) && AssetDatabase.IsMainAsset(a)); - - if (!hasPreview && !hasLabels) - return; - - Event evt = Event.current; - - // Preview / Asset Labels toolbar - Rect rect = EditorGUILayout.BeginHorizontal(GUIContent.none, styles.preToolbar, GUILayout.Height(kBottomToolbarHeight)); - Rect dragRect; - Rect dragIconRect = new Rect(); - const float dragPadding = 3f; - const float minDragWidth = 20f; - { - GUILayout.FlexibleSpace(); - dragRect = GUILayoutUtility.GetLastRect(); - // The label rect is also needed to know which area should be draggable. - GUIContent title; - if (hasPreview) - { - GUIContent userDefinedTitle = previewEditor.GetPreviewTitle(); - title = userDefinedTitle ?? styles.preTitle; - } - else - { - title = styles.labelTitle; - } - - dragIconRect.x = dragRect.x + dragPadding; - dragIconRect.y = dragRect.y + (kBottomToolbarHeight - s_Styles.dragHandle.fixedHeight) / 2 + 1; - dragIconRect.width = dragRect.width - dragPadding * 2; - dragIconRect.height = s_Styles.dragHandle.fixedHeight; - - //If we have more than one component with Previews, show a DropDown menu. - if (editorsWithPreviews.Length > 1) - { - Vector2 foldoutSize = styles.preDropDown.CalcSize(title); - float maxFoldoutWidth = (dragIconRect.xMax - dragRect.xMin) - dragPadding - minDragWidth; - float foldoutWidth = Mathf.Min(maxFoldoutWidth, foldoutSize.x); - Rect foldoutRect = new Rect(dragRect.x, dragRect.y, foldoutWidth, foldoutSize.y); - dragRect.xMin += foldoutWidth; - dragIconRect.xMin += foldoutWidth; - - GUIContent[] panelOptions = new GUIContent[editorsWithPreviews.Length]; - int selectedPreview = -1; - for (int index = 0; index < editorsWithPreviews.Length; index++) - { - IPreviewable currentEditor = editorsWithPreviews[index]; - GUIContent previewTitle = currentEditor.GetPreviewTitle() ?? styles.preTitle; - - string fullTitle; - if (previewTitle == styles.preTitle) - { - string componentTitle = ObjectNames.GetTypeName(currentEditor.target); - if (currentEditor.target is MonoBehaviour) - { - componentTitle = MonoScript.FromMonoBehaviour(currentEditor.target as MonoBehaviour).GetClass().Name; - } - fullTitle = previewTitle.text + " - " + componentTitle; - } - else - { - fullTitle = previewTitle.text; - } - - panelOptions[index] = new GUIContent(fullTitle); - if (editorsWithPreviews[index] == previewEditor) - { - selectedPreview = index; - } - } - - if (GUI.Button(foldoutRect, title, styles.preDropDown)) - { - EditorUtility.DisplayCustomMenu(foldoutRect, panelOptions, selectedPreview, OnPreviewSelected, editorsWithPreviews); - } - } - else - { - float maxLabelWidth = (dragIconRect.xMax - dragRect.xMin) - dragPadding - minDragWidth; - float labelWidth = Mathf.Min(maxLabelWidth, styles.preToolbar2.CalcSize(title).x); - Rect labelRect = new Rect(dragRect.x, dragRect.y, labelWidth, dragRect.height); - - dragIconRect.xMin = labelRect.xMax + dragPadding; - - GUI.Label(labelRect, title, styles.preToolbar2); - } - - if (hasPreview && Event.current.type == EventType.Repaint) - { - s_Styles.dragHandle.Draw(dragIconRect, GUIContent.none, false, false, false, false); - } - - if (hasPreview && m_PreviewResizer.GetExpandedBeforeDragging()) - previewEditor.OnPreviewSettings(); - } EditorGUILayout.EndHorizontal(); - - - // Detach preview on right click in preview title bar - if (evt.type == EventType.MouseUp && evt.button == 1 && rect.Contains(evt.mousePosition) && m_PreviewWindow == null) - DetachPreview(); - - // Logic for resizing and collapsing - float previewSize; - if (hasPreview) - { - // If we have a preview we'll use the ResizerControl which handles both resizing and collapsing - - // We have to subtract space used by version control bar from the window size we pass to the PreviewResizer - Rect windowRect = position; - if (EditorSettings.externalVersionControl != ExternalVersionControl.Disabled && - EditorSettings.externalVersionControl != ExternalVersionControl.AutoDetect && - EditorSettings.externalVersionControl != ExternalVersionControl.Generic - ) - { - windowRect.height -= kBottomToolbarHeight; - } - previewSize = m_PreviewResizer.ResizeHandle(windowRect, 100, 100, kBottomToolbarHeight, dragRect); - } - else - { - // If we don't have a preview, just toggle the collapseble state with a button - if (GUI.Button(rect, GUIContent.none, GUIStyle.none)) - m_PreviewResizer.ToggleExpanded(); - - previewSize = 0; - } - - // If collapsed, early out - if (!m_PreviewResizer.GetExpanded()) - return; - - // The preview / label area (not including the toolbar) - GUILayout.BeginVertical(styles.preBackground, GUILayout.Height(previewSize)); - { - // Draw preview - if (hasPreview) - { - previewEditor.DrawPreview(GUILayoutUtility.GetRect(0, 10240, 64, 10240)); - } - - if (hasLabels) - { - using (new EditorGUI.DisabledScope(assets.Any(a => EditorUtility.IsPersistent(a) && !Editor.IsAppropriateFileOpenForEdit(a)))) - { - m_LabelGUI.OnLabelGUI(assets); - } - } - - if (hasBundleName) - { - m_AssetBundleNameGUI.OnAssetBundleNameGUI(assets); - } - } GUILayout.EndVertical(); - } - - internal Object[] GetTargetsForPreview(IPreviewable previewEditor) - { - Editor editorForType = null; - foreach (var editor in tracker.activeEditors) - { - if (editor.target.GetType() != previewEditor.target.GetType()) - { - continue; - } - - editorForType = editor; - break; - } - return editorForType.targets; - } - - private void OnPreviewSelected(object userData, string[] options, int selected) - { - IPreviewable[] availabePreviews = userData as IPreviewable[]; - m_SelectedPreview = availabePreviews[selected]; - } - - private void DetachPreview() - { - Event.current.Use(); - m_PreviewWindow = ScriptableObject.CreateInstance(typeof(PreviewWindow)) as PreviewWindow; - m_PreviewWindow.SetParentInspector(this); - m_PreviewWindow.Show(); - Repaint(); - GUIUtility.ExitGUI(); - } - - protected virtual void DrawVCSSticky(float offset) - { - string message = ""; - Editor assetEditor = GetFirstNonImportInspectorEditor(tracker.activeEditors); - bool hasRemovedSticky = EditorPrefs.GetBool("vcssticky"); - if (!hasRemovedSticky && !Editor.IsAppropriateFileOpenForEdit(assetEditor.target, out message)) - { - var rect = new Rect(10, position.height - 94, position.width - 20, 80); - rect.y -= offset; - if (Event.current.type == EventType.Repaint) - { - styles.stickyNote.Draw(rect, false, false, false, false); - - Rect iconRect = new Rect(rect.x, rect.y + rect.height / 2 - 32, 64, 64); - if (EditorSettings.externalVersionControl == "Perforce") // TODO: remove hardcoding of perforce - { - styles.stickyNotePerforce.Draw(iconRect, false, false, false, false); - } - - Rect textRect = new Rect(rect.x + iconRect.width, rect.y, rect.width - iconRect.width, rect.height); - GUI.Label(textRect, EditorGUIUtility.TrTextContent("Under Version Control\nCheck out this asset in order to make changes."), styles.stickyNoteLabel); - - Rect arrowRect = new Rect(rect.x + rect.width / 2, rect.y + 80, 19, 14); - styles.stickyNoteArrow.Draw(arrowRect, false, false, false, false); - } - } - } - - private void DrawVCSShortInfo() - { - if (Provider.enabled && - EditorSettings.externalVersionControl != ExternalVersionControl.Disabled && - EditorSettings.externalVersionControl != ExternalVersionControl.AutoDetect && - EditorSettings.externalVersionControl != ExternalVersionControl.Generic) - { - Editor assetEditor = GetFirstNonImportInspectorEditor(tracker.activeEditors); - string assetPath = AssetDatabase.GetAssetPath(assetEditor.target); - Asset asset = Provider.GetAssetByPath(assetPath); - if (asset == null || !(asset.path.StartsWith("Assets") || asset.path.StartsWith("ProjectSettings"))) - return; - - Asset metaAsset = Provider.GetAssetByPath(assetPath.Trim('/') + ".meta"); - - string currentState = asset.StateToString(); - string currentMetaState = metaAsset == null ? String.Empty : metaAsset.StateToString(); - - //We also need to take into account the global VCS state here, as it being offline (or not connected) - //can also cause IsOpenForEdit to return false for checkout-enabled or lock-enabled VCS - if (currentState == string.Empty && Provider.onlineState != OnlineState.Online) - { - currentState = String.Format(s_Styles.VCS_NotConnectedMessage.text, Provider.GetActivePlugin().name); - } - - bool showMetaState = metaAsset != null && (metaAsset.state & ~Asset.States.MetaFile) != asset.state; - bool showAssetState = currentState != ""; - - float labelHeight = showMetaState && showAssetState ? kBottomToolbarHeight * 2 : kBottomToolbarHeight; - GUILayout.Label(GUIContent.none, styles.preToolbar, GUILayout.Height(labelHeight)); - - var rect = GUILayoutUtility.GetLastRect(); - - bool isLayoutOrRepaint = Event.current.type == EventType.Layout || Event.current.type == EventType.Repaint; - - if (showAssetState && isLayoutOrRepaint) - { - Texture2D icon = AssetDatabase.GetCachedIcon(assetPath) as Texture2D; - if (showMetaState) - { - Rect assetRect = rect; - assetRect.height = kBottomToolbarHeight; - DrawVCSShortInfoAsset(asset, BuildTooltip(asset, null), assetRect, icon, currentState); - - Texture2D metaIcon = InternalEditorUtility.GetIconForFile(metaAsset.path) as Texture2D; - assetRect.y += kBottomToolbarHeight; - DrawVCSShortInfoAsset(metaAsset, BuildTooltip(null, metaAsset), assetRect, metaIcon, currentMetaState); - } - else - { - DrawVCSShortInfoAsset(asset, BuildTooltip(asset, metaAsset), rect, icon, currentState); - } - } - else if (currentMetaState != "" && isLayoutOrRepaint) - { - Texture2D metaIcon = InternalEditorUtility.GetIconForFile(metaAsset.path) as Texture2D; - DrawVCSShortInfoAsset(metaAsset, BuildTooltip(asset, metaAsset), rect, metaIcon, currentMetaState); - } - - string message = ""; - bool openForEdit = Editor.IsAppropriateFileOpenForEdit(assetEditor.target, out message); - if (!openForEdit) - { - if (Provider.isActive) //Only ofer a checkout button if we think we're in a state to open the file for edit - { - float buttonWidth = 80; - Rect buttonRect = new Rect(rect.x + rect.width - buttonWidth, rect.y, buttonWidth, rect.height); - if (GUI.Button(buttonRect, "Check out", styles.lockedHeaderButton)) - { - EditorPrefs.SetBool("vcssticky", true); - // TODO: Retrieve default CheckoutMode from VC settings (depends on asset type; native vs. imported) - Task task = Provider.Checkout(assetEditor.targets, CheckoutMode.Both); - task.Wait(); - Repaint(); - } - } - DrawVCSSticky(rect.height / 2); - } - } - } - - protected string BuildTooltip(Asset asset, Asset metaAsset) - { - var sb = new System.Text.StringBuilder(); - if (asset != null) - { - sb.AppendLine("Asset:"); - sb.AppendLine(asset.AllStateToString()); - } - if (metaAsset != null) - { - sb.AppendLine("Meta file:"); - sb.AppendLine(metaAsset.AllStateToString()); - } - return sb.ToString(); - } - - protected void DrawVCSShortInfoAsset(Asset asset, string tooltip, Rect rect, Texture2D icon, string currentState) - { - Rect overlayRect = new Rect(rect.x, rect.y, 28, 16); - Rect iconRect = overlayRect; - iconRect.x += 6; - iconRect.width = 16; - if (icon != null) - GUI.DrawTexture(iconRect, icon); - Overlay.DrawOverlay(asset, overlayRect); - - Rect textRect = new Rect(rect.x + 26, rect.y, rect.width - 31, rect.height); - GUIContent content = GUIContent.Temp(currentState); - content.tooltip = tooltip; - EditorGUI.LabelField(textRect, content, styles.preToolbar2); - } - - private void DrawEditors(Editor[] editors) - { - if (editors.Length == 0) - return; - - // We need to force optimized GUI to dirty when object becomes open for edit - // e.g. after checkout in version control. If this is not done the optimized - // GUI will need an extra repaint before it gets ungrayed out. - - Object inspectedObject = GetInspectedObject(); - string msg = String.Empty; - - // Force header to be flush with the top of the window - GUILayout.Space(0); - - // When inspecting a material asset force visible properties (MaterialEditor can be collapsed when shown on a GameObject) - if (inspectedObject is Material) - { - // Find material editor. MaterialEditor is in either index 0 or 1. - for (int i = 0; i <= 1 && i < editors.Length; i++) - { - MaterialEditor me = editors[i] as MaterialEditor; - if (me != null) - { - me.forceVisible = true; - break; - } - } - } - - bool rebuildOptimizedGUIBlocks = false; - if (Event.current.type == EventType.Repaint) - { - if (inspectedObject != null - && m_IsOpenForEdit != Editor.IsAppropriateFileOpenForEdit(inspectedObject, out msg)) - { - m_IsOpenForEdit = !m_IsOpenForEdit; - rebuildOptimizedGUIBlocks = true; - } - if (m_InvalidateGUIBlockCache) - { - rebuildOptimizedGUIBlocks = true; - m_InvalidateGUIBlockCache = false; - } - } - else if (Event.current.type == EventType.ExecuteCommand && Event.current.commandName == EventCommandNames.EyeDropperUpdate) - { - rebuildOptimizedGUIBlocks = true; - } - - Editor.m_AllowMultiObjectAccess = true; - bool showImportedObjectBarNext = false; - Rect importedObjectBarRect = new Rect(); - for (int editorIndex = 0; editorIndex < editors.Length; editorIndex++) - { - if (ShouldCullEditor(editors, editorIndex)) - { - if (Event.current.type == EventType.Repaint) - editors[editorIndex].isInspectorDirty = false; - continue; - } - - bool oldValue = GUIUtility.textFieldInput; - DrawEditor(editors, editorIndex, rebuildOptimizedGUIBlocks, ref showImportedObjectBarNext, ref importedObjectBarRect); - if (Event.current.type == EventType.Repaint && !oldValue && GUIUtility.textFieldInput) // Did this editor set textFieldInput=true? - { - // If so, We need to flush the OptimizedGUIBlock every frame, so that EditorGUI.DoTextField() repaint keeps getting called and textFieldInput set to true. - // textFieldInput is reset to false at beginning of every repaint in c++ GUIView::DoPaint() - FlushOptimizedGUIBlock(editors[editorIndex]); - } - } - - EditorGUIUtility.ResetGUIState(); - - // Draw the bar to show that the imported object is below - if (importedObjectBarRect.height > 0) - { - // Clip the label to avoid a black border at the bottom - GUI.BeginGroup(importedObjectBarRect); - GUI.Label(new Rect(0, 0, importedObjectBarRect.width, importedObjectBarRect.height), "Imported Object", "OL Title"); - GUI.EndGroup(); - } - } - - internal override void OnResized() - { - m_InvalidateGUIBlockCache = true; - } - - private void DrawEditor(Editor[] editors, int editorIndex, bool rebuildOptimizedGUIBlock, ref bool showImportedObjectBarNext, ref Rect importedObjectBarRect) - { - var editor = editors[editorIndex]; - // Protect us against someone triggering an asset reimport during - // OnGUI as that will kill all active editors. - if (editor == null) - return; - - Object target = editor.target; - // see case 891450: - // inspector onGui starts, fetch ActiveEditorTrackers - this includes a MaterialEditor created with a canvasRenderer material - // then, disabling a Mask component deletes this material - // after that, either Active Editors are fetched again and the count is different OR the material is invalid and crashes the whole app - // The target is considered invalid if the MonoBehaviour is missing, to ensure that the missing MonoBehaviour field is drawn - // we only do not draw an editor if the target is invalid and it is not a MonoBehaviour. case: 917810 - if (!target && target.GetType() != typeof(UnityEngine.MonoBehaviour)) - return; - GUIUtility.GetControlID(target.GetInstanceID(), FocusType.Passive); - EditorGUIUtility.ResetGUIState(); - - // cache the layout group we expect to have at the end of drawing this editor - GUILayoutGroup expectedGroup = GUILayoutUtility.current.topLevel; - - // Display title bar and early out if folded - int wasVisibleState = tracker.GetVisible(editorIndex); - bool wasVisible; - - if (wasVisibleState == -1) - { - // Init our state with last state - wasVisible = InternalEditorUtility.GetIsInspectorExpanded(target); - tracker.SetVisible(editorIndex, wasVisible ? 1 : 0); - } - else - wasVisible = wasVisibleState == 1; - - rebuildOptimizedGUIBlock |= editor.isInspectorDirty; - - // Reset dirtyness when repainting - if (Event.current.type == EventType.Repaint) - { - editor.isInspectorDirty = false; - } - - //set the current PropertyHandlerCache to the current editor - ScriptAttributeUtility.propertyHandlerCache = editor.propertyHandlerCache; - - bool largeHeader = EditorHasLargeHeader(editorIndex, editors); - - // Draw large headers before we do the culling of unsupported editors below, - // so the large header is always shown even when the editor can't be. - if (largeHeader) - { - String message = String.Empty; - bool IsOpenForEdit = editor.IsOpenForEdit(out message); - - if (showImportedObjectBarNext) - { - showImportedObjectBarNext = false; - GUILayout.Space(15); - importedObjectBarRect = GUILayoutUtility.GetRect(16, 16); - importedObjectBarRect.height = 17; - } - - wasVisible = true; - - // Header - using (new EditorGUI.DisabledScope(!IsOpenForEdit)) // Only disable the entire header if the asset is locked by VCS - { - editor.DrawHeader(); - } - } - - if (editor.target is AssetImporter) - showImportedObjectBarNext = true; - - // Culling of editors that can't be properly shown. - // If the current editor is a GenericInspector even though a custom editor for it exists, - // then it's either a fallback for a custom editor that doesn't support multi-object editing, - // or we're in debug mode. - bool multiEditingNotSupported = false; - if (editor is GenericInspector && CustomEditorAttributes.FindCustomEditorType(target, false) != null) - { - if (m_InspectorMode == InspectorMode.DebugInternal) - { - // Do nothing - } - else if (m_InspectorMode == InspectorMode.Normal) - { - // If we're not in debug mode and it thus must be a fallback, - // hide the editor and show a notification. - multiEditingNotSupported = true; - } - else if (target is AssetImporter) - { - // If we are in debug mode and it's an importer type, - // hide the editor and show a notification. - multiEditingNotSupported = true; - } - // If we are in debug mode and it's an NOT importer type, - // just show the debug inspector as usual. - } - - // Dragging handle used for editor reordering - Rect dragRect = new Rect(); - - // Draw small headers (the header above each component) after the culling above - // so we don't draw a component header for all the components that can't be shown. - if (!largeHeader) - { - using (new EditorGUI.DisabledScope(!editor.IsEnabled())) - { - bool isVisible = UnityEditor.EditorGUILayout.InspectorTitlebar(wasVisible, editor.targets, editor.CanBeExpandedViaAFoldout()); - if (wasVisible != isVisible) - { - tracker.SetVisible(editorIndex, isVisible ? 1 : 0); - InternalEditorUtility.SetIsInspectorExpanded(target, isVisible); - if (isVisible) - m_LastInteractedEditor = editor; - else if (m_LastInteractedEditor == editor) - m_LastInteractedEditor = null; - } - } - - dragRect = GUILayoutUtility.GetLastRect(); - } - - if (multiEditingNotSupported && wasVisible) - { - GUILayout.Label("Multi-object editing not supported.", EditorStyles.helpBox); - return; - } - - DisplayDeprecationMessageIfNecessary(editor); - - // We need to reset again after drawing the header. - EditorGUIUtility.ResetGUIState(); - - Rect contentRect = new Rect(); - bool excludedClass = ModuleMetadata.GetModuleIncludeSettingForObject(target) == ModuleIncludeSetting.ForceExclude; - if (excludedClass) - EditorGUILayout.HelpBox("The module which implements this component type has been force excluded in player settings. This object will be removed in play mode and from any builds you make.", MessageType.Warning); - - using (new EditorGUI.DisabledScope(!editor.IsEnabled() || excludedClass)) - { - var genericEditor = editor as GenericInspector; - if (genericEditor) - genericEditor.m_InspectorMode = m_InspectorMode; - - // Optimize block code path - float height; - OptimizedGUIBlock optimizedBlock; - - EditorGUIUtility.hierarchyMode = true; - EditorGUIUtility.wideMode = position.width > 330; - - //set the current PropertyHandlerCache to the current editor - ScriptAttributeUtility.propertyHandlerCache = editor.propertyHandlerCache; - - if (editor.GetOptimizedGUIBlock(rebuildOptimizedGUIBlock, wasVisible, out optimizedBlock, out height)) - { - contentRect = GUILayoutUtility.GetRect(0, wasVisible ? height : 0); - HandleLastInteractedEditor(contentRect, editor); - - // Layout events are ignored in the optimized code path - if (Event.current.type == EventType.Layout) - { - return; - } - - // Try reusing optimized block - if (optimizedBlock.Begin(rebuildOptimizedGUIBlock, contentRect)) - { - // Draw content - if (wasVisible) - { - GUI.changed = false; - editor.OnOptimizedInspectorGUI(contentRect); - } - } - - optimizedBlock.End(); - } - else - { - // Render contents if folded out - if (wasVisible) - { - GUIStyle editorWrapper = (editor.UseDefaultMargins() ? EditorStyles.inspectorDefaultMargins : GUIStyle.none); - contentRect = EditorGUILayout.BeginVertical(editorWrapper); - { - HandleLastInteractedEditor(contentRect, editor); - - GUI.changed = false; - - try - { - editor.OnInspectorGUI(); - } - catch (Exception e) - { - if (GUIUtility.ShouldRethrowException(e)) - throw; - - Debug.LogException(e); - } - } - EditorGUILayout.EndVertical(); - } - - // early out if an event has been used - if (Event.current.type == EventType.Used) - { - return; - } - } - } - - editorDragging.HandleDraggingToEditor(editorIndex, dragRect, contentRect, m_Tracker); - - // Check and try to cleanup layout groups. - if (GUILayoutUtility.current.topLevel != expectedGroup) - { - if (!GUILayoutUtility.current.layoutGroups.Contains(expectedGroup)) - { - // We can't recover from this, so we error. - Debug.LogError("Expected top level layout group missing! Too many GUILayout.EndScrollView/EndVertical/EndHorizontal?"); - GUIUtility.ExitGUI(); - } - else - { - // We can recover from this, so we warning. - Debug.LogWarning("Unexpected top level layout group! Missing GUILayout.EndScrollView/EndVertical/EndHorizontal?"); - - while (GUILayoutUtility.current.topLevel != expectedGroup) - GUILayoutUtility.EndLayoutGroup(); - } - } - - HandleComponentScreenshot(contentRect, editor); - } - - internal void RepaintImmediately(bool rebuildOptimizedGUIBlocks) - { - m_InvalidateGUIBlockCache = rebuildOptimizedGUIBlocks; - RepaintImmediately(); - } - - internal bool EditorHasLargeHeader(int editorIndex, Editor[] trackerActiveEditors) - { - var target = trackerActiveEditors[editorIndex].target; - return AssetDatabase.IsMainAsset(target) || AssetDatabase.IsSubAsset(target) || editorIndex == 0 || target is Material; - } - - private void DisplayDeprecationMessageIfNecessary(Editor editor) - { - if (!editor || !editor.target) return; - - var obsoleteAttribute = (ObsoleteAttribute)Attribute.GetCustomAttribute(editor.target.GetType(), typeof(ObsoleteAttribute)); - if (obsoleteAttribute == null) return; - - string message = String.IsNullOrEmpty(obsoleteAttribute.Message) ? "This component has been marked as obsolete." : obsoleteAttribute.Message; - EditorGUILayout.HelpBox(message, obsoleteAttribute.IsError ? MessageType.Error : MessageType.Warning); - } - - private void HandleComponentScreenshot(Rect contentRect, Editor editor) - { - if (ScreenShots.s_TakeComponentScreenshot) - { - contentRect.yMin -= 16; - if (contentRect.Contains(Event.current.mousePosition)) - { - Rect globalComponentRect = GUIClip.Unclip(contentRect); - globalComponentRect.position = globalComponentRect.position + m_Parent.screenPosition.position; - ScreenShots.ScreenShotComponent(globalComponentRect, editor.target); - } - } - } - - internal bool ShouldCullEditor(Editor[] editors, int editorIndex) - { - if (editors[editorIndex].hideInspector) - return true; - - Object currentTarget = editors[editorIndex].target; - - // Objects that should always be hidden - if (currentTarget is ParticleSystemRenderer) - return true; - - // Hide regular AssetImporters (but not inherited types) - if (currentTarget != null && currentTarget.GetType() == typeof(AssetImporter)) - return true; - - // Let asset importers decide if the imported object should be shown or not - if (m_InspectorMode == InspectorMode.Normal && editorIndex != 0) - { - AssetImporterEditor importerEditor = editors[0] as AssetImporterEditor; - if (importerEditor != null && !importerEditor.showImportedObject) - return true; - } - - return false; - } - - void DrawSelectionPickerList() - { - if (m_TypeSelectionList == null) - m_TypeSelectionList = new TypeSelectionList(Selection.objects); - - // Force header to be flush with the top of the window - GUILayout.Space(0); - - Editor.DrawHeaderGUI(null, Selection.objects.Length + " Objects"); - - GUILayout.Label("Narrow the Selection:", EditorStyles.label); - GUILayout.Space(4); - - Vector2 oldSize = EditorGUIUtility.GetIconSize(); - EditorGUIUtility.SetIconSize(new Vector2(16, 16)); - foreach (TypeSelection ts in m_TypeSelectionList.typeSelections) - { - Rect r = GUILayoutUtility.GetRect(16, 16, GUILayout.ExpandWidth(true)); - if (GUI.Button(r, ts.label, styles.typeSelection)) - { - Selection.objects = ts.objects; - Event.current.Use(); - } - if (GUIUtility.hotControl == 0) - EditorGUIUtility.AddCursorRect(r, MouseCursor.Link); - GUILayout.Space(4); - } - EditorGUIUtility.SetIconSize(oldSize); - } - - void HandleLastInteractedEditor(Rect componentRect, Editor editor) - { - if (editor != m_LastInteractedEditor && - Event.current.type == EventType.MouseDown && componentRect.Contains(Event.current.mousePosition)) - { - // Don't use the event because the editor might want to use it. - // But don't move the check down below the editor either, - // because we want to set the last interacted editor simultaneously. - m_LastInteractedEditor = editor; - Repaint(); - } - } - - private void AddComponentButton(Editor[] editors) - { - Editor editor = GetFirstNonImportInspectorEditor(editors); - if (editor != null && editor.target != null && editor.target is GameObject && editor.IsEnabled()) - { - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - var content = s_Styles.addComponentLabel; - Rect rect = GUILayoutUtility.GetRect(content, styles.addComponentButtonStyle); - - // Visually separates the Add Component button from the existing components - if (Event.current.type == EventType.Repaint) - DrawSplitLine(rect.y - 11); - - Event evt = Event.current; - bool openWindow = false; - switch (evt.type) - { - case EventType.ExecuteCommand: - string commandName = evt.commandName; - if (commandName == AddComponentWindow.OpenAddComponentDropdown) - { - openWindow = true; - evt.Use(); - } - break; - } - - if (EditorGUI.DropdownButton(rect, content, FocusType.Passive, styles.addComponentButtonStyle) || openWindow) - { - if (AddComponentWindow.Show(rect, editor.targets.Select(o => (GameObject)o).ToArray())) - GUIUtility.ExitGUI(); - } - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - } - } - - private bool ReadyToRepaint() - { - if (AnimationMode.InAnimationPlaybackMode()) - { - long timeNow = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - if (timeNow - s_LastUpdateWhilePlayingAnimation < delayRepaintWhilePlayingAnimation) - return false; - s_LastUpdateWhilePlayingAnimation = timeNow; - } - - return true; - } - - private void DrawSplitLine(float y) - { - Rect position = new Rect(0, y, this.m_Pos.width + 1, 1); - Rect uv = new Rect(0, 1f, 1, 1f - 1f / EditorStyles.inspectorTitlebar.normal.background.height); - GUI.DrawTextureWithTexCoords(position, EditorStyles.inspectorTitlebar.normal.background, uv); - } - - // Invoked from C++ - internal static void ShowWindow() - { - GetWindow(typeof(InspectorWindow)); - } - - // Called from OptimizedGUIBlock::FlushAll(); - private static void FlushOptimizedGUI() - { - // Delay flushing since FlushOptimizedGUI is called when going into playmode (assembly reload) - // for every TextMeshGenerator::Flush () in c++. - // By delaying we also ensure that our editor trackers are fully constructed before flushing (fixes case 718491) - s_AllOptimizedGUIBlocksNeedsRebuild = true; - } - - private static void FlushAllOptimizedGUIBlocksIfNeeded() - { - if (!s_AllOptimizedGUIBlocksNeedsRebuild) - return; - s_AllOptimizedGUIBlocksNeedsRebuild = false; - - foreach (var inspector in m_AllInspectors) - { - foreach (var editor in inspector.tracker.activeEditors) - FlushOptimizedGUIBlock(editor); - } - } - - private static void FlushOptimizedGUIBlock(Editor editor) - { - if (editor == null) - return; - - OptimizedGUIBlock optimizedBlock; - float height; - if (editor.GetOptimizedGUIBlock(false, false, out optimizedBlock, out height)) - { - optimizedBlock.valid = false; - } - } - - private void Update() - { - Editor[] editors = tracker.activeEditors; - if (editors == null) - return; - - bool wantsRepaint = false; - foreach (var myEditor in editors) - { - if (myEditor.RequiresConstantRepaint() && !myEditor.hideInspector) - wantsRepaint = true; - } - - if (wantsRepaint && m_lastRenderedTime + 0.033f < EditorApplication.timeSinceStartup) - { - m_lastRenderedTime = EditorApplication.timeSinceStartup; - Repaint(); - } - } - - void ISerializationCallbackReceiver.OnBeforeSerialize() - { - m_ObjectsLockedBeforeSerialization.Clear(); - - m_InstanceIDsLockedBeforeSerialization.Clear(); - - if (m_Tracker != null && m_Tracker.isLocked) - { - m_Tracker.GetObjectsLockedByThisTracker(m_ObjectsLockedBeforeSerialization); - // take out non persistent and track them in a list of instance IDs, because they wouldn't survive serialization as Objects - for (int i = m_ObjectsLockedBeforeSerialization.Count - 1; i >= 0; i--) - { - if (!EditorUtility.IsPersistent(m_ObjectsLockedBeforeSerialization[i])) - { - m_InstanceIDsLockedBeforeSerialization.Add(m_ObjectsLockedBeforeSerialization[i].GetInstanceID()); - m_ObjectsLockedBeforeSerialization.RemoveAt(i); - } - } - } - } - - void ISerializationCallbackReceiver.OnAfterDeserialize() - { - } - - void RestoreLockStateFromSerializedData() - { - if (m_Tracker == null) - return; - - // try to retrieve all Objects from their stored instance ids in the list. - // this is only used for nonpersistent objects (scene objects) - - if (m_InstanceIDsLockedBeforeSerialization.Count > 0) - { - for (int i = 0; i < m_InstanceIDsLockedBeforeSerialization.Count; i++) - { - Object instance = EditorUtility.InstanceIDToObject(m_InstanceIDsLockedBeforeSerialization[i]); - //don't add null objects (i.e. - if (instance) - m_ObjectsLockedBeforeSerialization.Add(instance); - } - } - - for (int i = m_ObjectsLockedBeforeSerialization.Count - 1; i >= 0; i--) - { - if (m_ObjectsLockedBeforeSerialization[i] == null) - { - m_ObjectsLockedBeforeSerialization.RemoveAt(i); - } - } - - // set the tracker to the serialized list. if it contains nulls or is empty, the tracker won't lock - // this fixes case 775007 - m_Tracker.SetObjectsLockedByThisTracker(m_ObjectsLockedBeforeSerialization); - // since this method likely got called during OnEnable, and rebuilding the tracker could call OnDisable on all Editors, - // some of which might not have gotten their enable yet, the rebuilding needs to happen delayed in EditorApplication.update - new DelayedCallback(tracker.RebuildIfNecessary, 0f); - } - } -} diff --git a/Editor/Mono/Inspector/Joint2DEditor.cs b/Editor/Mono/Inspector/Joint2DEditor.cs deleted file mode 100644 index 2ee02f108a..0000000000 --- a/Editor/Mono/Inspector/Joint2DEditor.cs +++ /dev/null @@ -1,179 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(Joint2D))] - [CanEditMultipleObjects] - internal class Joint2DEditor : Editor - { - SerializedProperty m_BreakForce; - SerializedProperty m_BreakTorque; - - public void OnEnable() - { - m_BreakForce = serializedObject.FindProperty("m_BreakForce"); - m_BreakTorque = serializedObject.FindProperty("m_BreakTorque"); - } - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - - EditorGUILayout.PropertyField(m_BreakForce); - - // Distance/Spring/Target joints produce no reaction torque so they're not supported. - var targetType = target.GetType(); - if (targetType != typeof(DistanceJoint2D) && - targetType != typeof(TargetJoint2D) && - targetType != typeof(SpringJoint2D)) - EditorGUILayout.PropertyField(m_BreakTorque); - - serializedObject.ApplyModifiedProperties(); - } - - public class Styles - { - public readonly GUIStyle anchor = "U2D.pivotDot"; - public readonly GUIStyle anchorActive = "U2D.pivotDotActive"; - public readonly GUIStyle connectedAnchor = "U2D.dragDot"; - public readonly GUIStyle connectedAnchorActive = "U2D.dragDotActive"; - } - protected static Styles s_Styles; - - protected bool HandleAnchor(ref Vector3 position, bool isConnectedAnchor) - { - if (s_Styles == null) - s_Styles = new Styles(); - - var drawCapFunction = isConnectedAnchor ? (Handles.CapFunction)ConnectedAnchorHandleCap : (Handles.CapFunction)AnchorHandleCap; - - int id = target.GetInstanceID() + (isConnectedAnchor ? 1 : 0); - - EditorGUI.BeginChangeCheck(); - position = Handles.Slider2D(id, position, Vector3.back, Vector3.right, Vector3.up, 0, drawCapFunction, Vector2.zero); - return EditorGUI.EndChangeCheck(); - } - - public static void AnchorHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - if (controlID == GUIUtility.keyboardControl) - HandleCap(controlID, position, s_Styles.anchorActive, eventType); - else - HandleCap(controlID, position, s_Styles.anchor, eventType); - } - - public static void ConnectedAnchorHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - if (controlID == GUIUtility.keyboardControl) - HandleCap(controlID, position, s_Styles.connectedAnchorActive, eventType); - else - HandleCap(controlID, position, s_Styles.connectedAnchor, eventType); - } - - static void HandleCap(int controlID, Vector3 position, GUIStyle guiStyle, EventType eventType) - { - switch (eventType) - { - case EventType.Layout: - HandleUtility.AddControl(controlID, HandleUtility.DistanceToRectangleInternal(position, Quaternion.identity, Vector2.zero)); - break; - case EventType.Repaint: - Handles.BeginGUI(); - - position = HandleUtility.WorldToGUIPoint(position); - var w = guiStyle.fixedWidth; - var h = guiStyle.fixedHeight; - var r = new Rect(position.x - w / 2f, position.y - h / 2f, w, h); - - guiStyle.Draw(r, GUIContent.none, controlID); - Handles.EndGUI(); - break; - } - } - - public static void DrawAALine(Vector3 start, Vector3 end) - { - Handles.DrawAAPolyLine(new Vector3[] { start, end }); - } - - public static void DrawDistanceGizmo(Vector3 anchor, Vector3 connectedAnchor, float distance) - { - Vector3 direction = (anchor - connectedAnchor).normalized; - Vector3 endPosition = connectedAnchor + (direction * distance); - - Vector3 normal = Vector3.Cross(direction, Vector3.forward); - normal *= HandleUtility.GetHandleSize(connectedAnchor) * 0.16f; - - Handles.color = Color.green; - - DrawAALine(anchor, endPosition); - DrawAALine(connectedAnchor + normal, connectedAnchor - normal); - DrawAALine(endPosition + normal, endPosition - normal); - } - - static Matrix4x4 GetAnchorSpaceMatrix(Transform transform) - { - // Anchor space transformation matrix - return Matrix4x4.TRS(transform.position, Quaternion.Euler(0, 0, transform.rotation.eulerAngles.z), transform.lossyScale); - } - - protected static Vector3 TransformPoint(Transform transform, Vector3 position) - { - // Local to World - return GetAnchorSpaceMatrix(transform).MultiplyPoint(position); - } - - protected static Vector3 InverseTransformPoint(Transform transform, Vector3 position) - { - // World to Local - return GetAnchorSpaceMatrix(transform).inverse.MultiplyPoint(position); - } - - protected static Vector3 SnapToSprite(SpriteRenderer spriteRenderer, Vector3 position, float snapDistance) - { - if (spriteRenderer == null) - return position; - - snapDistance = HandleUtility.GetHandleSize(position) * snapDistance; - - var x = spriteRenderer.sprite.bounds.size.x / 2; - var y = spriteRenderer.sprite.bounds.size.y / 2; - var anchors = new[] { new Vector2(-x, -y), new Vector2(0, -y), new Vector2(x, -y), - new Vector2(-x, 0), new Vector2(0, 0), new Vector2(x, 0), - new Vector2(-x, y), new Vector2(0, y), new Vector2(x, y)}; - - foreach (var anchor in anchors) - { - var worldAnchor = spriteRenderer.transform.TransformPoint(anchor); - if (Vector2.Distance(position, worldAnchor) <= snapDistance) - return worldAnchor; - } - - return position; - } - - protected static Vector3 SnapToPoint(Vector3 position, Vector3 snapPosition, float snapDistance) - { - snapDistance = HandleUtility.GetHandleSize(position) * snapDistance; - return Vector3.Distance(position, snapPosition) <= snapDistance ? snapPosition : position; - } - - protected static Vector2 RotateVector2(Vector2 direction, float angle) - { - var theta = Mathf.Deg2Rad * -angle; - - var cs = Mathf.Cos(theta); - var sn = Mathf.Sin(theta); - - var px = direction.x * cs - direction.y * sn; - var py = direction.x * sn + direction.y * cs; - - return new Vector2(px, py); - } - } -} diff --git a/Editor/Mono/Inspector/JointEditor.cs b/Editor/Mono/Inspector/JointEditor.cs deleted file mode 100644 index 38f23ff642..0000000000 --- a/Editor/Mono/Inspector/JointEditor.cs +++ /dev/null @@ -1,137 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor.IMGUI.Controls; -using UnityEditorInternal; -using UnityEngine; -using UnityObject = UnityEngine.Object; - -namespace UnityEditor -{ - abstract class JointEditor : Editor where T : Joint - { - protected static class Styles - { - public static readonly GUIContent editAngularLimitsButton = new GUIContent(EditorGUIUtility.IconContent("JointAngularLimits")); - public static readonly string editAngularLimitsUndoMessage = EditorGUIUtility.TrTextContent("Change Joint Angular Limits").text; - - static Styles() - { - editAngularLimitsButton.tooltip = EditorGUIUtility.TrTextContent("Edit joint angular limits.").text; - } - } - - protected static float GetAngularLimitHandleSize(Vector3 position) - { - return HandleUtility.GetHandleSize(position); - } - - protected JointAngularLimitHandle angularLimitHandle { get { return m_AngularLimitHandle; } } - private JointAngularLimitHandle m_AngularLimitHandle = new JointAngularLimitHandle(); - - protected bool editingAngularLimits - { - get { return EditMode.editMode == EditMode.SceneViewEditMode.JointAngularLimits && EditMode.IsOwner(this); } - } - - public override void OnInspectorGUI() - { - DoInspectorEditButtons(); - base.OnInspectorGUI(); - } - - protected void DoInspectorEditButtons() - { - T joint = (T)target; - EditMode.DoEditModeInspectorModeButton( - EditMode.SceneViewEditMode.JointAngularLimits, - "Edit Joint Angular Limits", - Styles.editAngularLimitsButton, - this - ); - } - - internal override Bounds GetWorldBoundsOfTarget(UnityObject targetObject) - { - var bounds = base.GetWorldBoundsOfTarget(targetObject); - // ensure joint's anchor point is included in bounds - bounds.Encapsulate(GetAngularLimitHandleMatrix((T)targetObject).MultiplyPoint3x4(Vector3.zero)); - return bounds; - } - - protected virtual void OnSceneGUI() - { - if (editingAngularLimits) - { - T joint = (T)target; - EditorGUI.BeginChangeCheck(); - - using (new Handles.DrawingScope(GetAngularLimitHandleMatrix(joint))) - DoAngularLimitHandles(joint); - - // wake up rigidbodies in case current orientation is out of bounds of new limits - if (EditorGUI.EndChangeCheck()) - { - var rigidbody = joint.GetComponent(); - if (rigidbody.isKinematic && joint.connectedBody != null) - joint.connectedBody.WakeUp(); - else - rigidbody.WakeUp(); - } - } - } - - protected virtual void GetActors( - T joint, - out Rigidbody dynamicActor, - out Rigidbody connectedActor, - out int jointFrameActorIndex, - out bool rightHandedLimit - ) - { - jointFrameActorIndex = 1; - rightHandedLimit = false; - - dynamicActor = joint.GetComponent(); - connectedActor = joint.connectedBody; - - if (dynamicActor.isKinematic && connectedActor != null && !connectedActor.isKinematic) - { - var temp = connectedActor; - connectedActor = dynamicActor; - dynamicActor = temp; - } - } - - private Matrix4x4 GetAngularLimitHandleMatrix(T joint) - { - Rigidbody dynamicActor, connectedActor; - int jointFrameActorIndex; - bool rightHandedLimit; - GetActors(joint, out dynamicActor, out connectedActor, out jointFrameActorIndex, out rightHandedLimit); - - var connectedBodyRotation = - connectedActor == null ? Quaternion.identity : connectedActor.transform.rotation; - - // to enhance usability, orient the limit region so the dynamic body is within it, assuming bodies were bound on opposite sides of the anchor - var jointFrame = joint.GetActorLocalPose(jointFrameActorIndex); - var jointFrameOrientation = Quaternion.LookRotation( - jointFrame.MultiplyVector(Vector3.forward), - jointFrame.MultiplyVector(rightHandedLimit ? Vector3.down : Vector3.up) - ); - - // point of rotation is about the anchor of the joint body, which is not necessarily aligned to the anchor on the connected body - var jointAnchorPosition = joint.anchor; - if (dynamicActor != null) - jointAnchorPosition = dynamicActor.transform.TransformPoint(jointAnchorPosition); - - return Matrix4x4.TRS(jointAnchorPosition, connectedBodyRotation * jointFrameOrientation, Vector3.one); - } - - protected virtual void DoAngularLimitHandles(T joint) - { - } - } -} diff --git a/Editor/Mono/Inspector/LODGroupEditor.cs b/Editor/Mono/Inspector/LODGroupEditor.cs deleted file mode 100644 index fce60b8f3a..0000000000 --- a/Editor/Mono/Inspector/LODGroupEditor.cs +++ /dev/null @@ -1,1245 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor.AnimatedValues; -using UnityEditorInternal; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - [CustomEditor(typeof(LODGroup))] - internal class LODGroupEditor : Editor - { - private int m_SelectedLODSlider = -1; - private int m_SelectedLOD = -1; - private int m_NumberOfLODs; - - private LODGroup m_LODGroup; - private bool m_IsPrefab; - - private SerializedProperty m_FadeMode; - private SerializedProperty m_AnimateCrossFading; - private SerializedProperty m_LODs; - - private AnimBool m_ShowAnimateCrossFading = new AnimBool(); - private AnimBool m_ShowFadeTransitionWidth = new AnimBool(); - - void OnEnable() - { - // TODO: support multi-editing? - m_FadeMode = serializedObject.FindProperty("m_FadeMode"); - m_AnimateCrossFading = serializedObject.FindProperty("m_AnimateCrossFading"); - m_LODs = serializedObject.FindProperty("m_LODs"); - - m_ShowAnimateCrossFading.value = m_FadeMode.intValue != (int)LODFadeMode.None; - m_ShowAnimateCrossFading.valueChanged.AddListener(Repaint); - m_ShowFadeTransitionWidth.value = false; - m_ShowFadeTransitionWidth.valueChanged.AddListener(Repaint); - - EditorApplication.update += Update; - - m_LODGroup = (LODGroup)target; - - // Calculate if the newly selected LOD group is a prefab... they require special handling - var type = PrefabUtility.GetPrefabType(m_LODGroup.gameObject); - m_IsPrefab = type == PrefabType.Prefab || type == PrefabType.ModelPrefab; - - Repaint(); - } - - void OnDisable() - { - EditorApplication.update -= Update; - - m_ShowAnimateCrossFading.valueChanged.RemoveListener(Repaint); - m_ShowFadeTransitionWidth.valueChanged.RemoveListener(Repaint); - if (m_PreviewUtility != null) - m_PreviewUtility.Cleanup(); - } - - // Find the given sceen space recangular bounds from a list of vector 3 points. - private static Rect CalculateScreenRect(IEnumerable points) - { - var points2 = points.Select(p => HandleUtility.WorldToGUIPoint(p)).ToList(); - - var min = new Vector2(float.MaxValue, float.MaxValue); - var max = new Vector2(float.MinValue, float.MinValue); - - foreach (var point in points2) - { - min.x = (point.x < min.x) ? point.x : min.x; - max.x = (point.x > max.x) ? point.x : max.x; - - min.y = (point.y < min.y) ? point.y : min.y; - max.y = (point.y > max.y) ? point.y : max.y; - } - - return new Rect(min.x, min.y, max.x - min.x, max.y - min.y); - } - - public void OnSceneGUI() - { - if (Event.current.type != EventType.Repaint - || Camera.current == null - || SceneView.lastActiveSceneView != SceneView.currentDrawingSceneView) - return; - - Camera camera = SceneView.lastActiveSceneView.camera; - var worldReferencePoint = LODUtility.CalculateWorldReferencePoint(m_LODGroup); - - if (Vector3.Dot(camera.transform.forward, - (camera.transform.position - worldReferencePoint).normalized) > 0) - return; - - var info = LODUtility.CalculateVisualizationData(camera, m_LODGroup, -1); - float size = info.worldSpaceSize; - - // Draw cap around LOD to visualize it's size - Handles.color = info.activeLODLevel != -1 ? LODGroupGUI.kLODColors[info.activeLODLevel] : LODGroupGUI.kCulledLODColor; - - Handles.SelectionFrame(0, worldReferencePoint, camera.transform.rotation, size / 2); - - // Calculate a screen rect for the on scene title - Vector3 sideways = camera.transform.right * size / 2.0f; - Vector3 up = camera.transform.up * size / 2.0f; - var rect = CalculateScreenRect( - new[] - { - worldReferencePoint - sideways + up, - worldReferencePoint - sideways - up, - worldReferencePoint + sideways + up, - worldReferencePoint + sideways - up - }); - - // Place the screen space lable directaly under the - var midPoint = rect.x + rect.width / 2.0f; - rect = new Rect(midPoint - LODGroupGUI.kSceneLabelHalfWidth, rect.yMax, LODGroupGUI.kSceneLabelHalfWidth * 2, LODGroupGUI.kSceneLabelHeight); - - if (rect.yMax > Screen.height - LODGroupGUI.kSceneLabelHeight) - rect.y = Screen.height - LODGroupGUI.kSceneLabelHeight - LODGroupGUI.kSceneHeaderOffset; - - Handles.BeginGUI(); - GUI.Label(rect, GUIContent.none, EditorStyles.notificationBackground); - EditorGUI.DoDropShadowLabel(rect, GUIContent.Temp(info.activeLODLevel >= 0 ? "LOD " + info.activeLODLevel : "Culled"), LODGroupGUI.Styles.m_LODLevelNotifyText, 0.3f); - Handles.EndGUI(); - } - - private Vector3 m_LastCameraPos = Vector3.zero; - public void Update() - { - if (SceneView.lastActiveSceneView == null || SceneView.lastActiveSceneView.camera == null) - { - return; - } - - // Update the last camera positon and repaint if the camera has moved - if (SceneView.lastActiveSceneView.camera.transform.position != m_LastCameraPos) - { - m_LastCameraPos = SceneView.lastActiveSceneView.camera.transform.position; - Repaint(); - } - } - - private const string kLODDataPath = "m_LODs.Array.data[{0}]"; - private const string kPixelHeightDataPath = "m_LODs.Array.data[{0}].screenRelativeHeight"; - private const string kRenderRootPath = "m_LODs.Array.data[{0}].renderers"; - private const string kFadeTransitionWidthDataPath = "m_LODs.Array.data[{0}].fadeTransitionWidth"; - - private int activeLOD - { - get {return m_SelectedLOD; } - } - - private ModelImporter GetImporter() - { - return AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(PrefabUtility.GetPrefabParent(target))) as ModelImporter; - } - - private bool IsLODUsingCrossFadeWidth(int lod) - { - if (m_FadeMode.intValue == (int)LODFadeMode.None || m_AnimateCrossFading.boolValue) - return false; - if (m_FadeMode.intValue == (int)LODFadeMode.CrossFade) - return true; - // SpeedTree: only last mesh LOD and billboard LOD do crossfade - if (m_NumberOfLODs > 0 && m_SelectedLOD == m_NumberOfLODs - 1) - return true; - if (m_NumberOfLODs > 1 && m_SelectedLOD == m_NumberOfLODs - 2) - { - // the second last LOD uses cross-fade if the last LOD is a billboard - var renderers = serializedObject.FindProperty(String.Format(kRenderRootPath, m_NumberOfLODs - 1)); - if (renderers.arraySize == 1 && renderers.GetArrayElementAtIndex(0).FindPropertyRelative("renderer").objectReferenceValue is BillboardRenderer) - return true; - } - return false; - } - - public override void OnInspectorGUI() - { - var initiallyEnabled = GUI.enabled; - - // Grab the latest data from the object - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_FadeMode); - - m_ShowAnimateCrossFading.target = m_FadeMode.intValue != (int)LODFadeMode.None; - if (EditorGUILayout.BeginFadeGroup(m_ShowAnimateCrossFading.faded)) - EditorGUILayout.PropertyField(m_AnimateCrossFading); - EditorGUILayout.EndFadeGroup(); - - m_NumberOfLODs = m_LODs.arraySize; - - // This could happen when you select a newly inserted LOD level and then undo the insertion. - // It's valid for m_SelectedLOD to become -1, which means nothing is selected. - if (m_SelectedLOD >= m_NumberOfLODs) - { - m_SelectedLOD = m_NumberOfLODs - 1; - } - - // Prepass to remove all empty renderers - if (m_NumberOfLODs > 0 && activeLOD >= 0) - { - var renderersProperty = serializedObject.FindProperty(string.Format(kRenderRootPath, activeLOD)); - for (var i = renderersProperty.arraySize - 1; i >= 0; i--) - { - var rendererRef = renderersProperty.GetArrayElementAtIndex(i).FindPropertyRelative("renderer"); - var renderer = rendererRef.objectReferenceValue as Renderer; - - if (renderer == null) - renderersProperty.DeleteArrayElementAtIndex(i); - } - } - - // Add some space at the top.. - GUILayout.Space(LODGroupGUI.kSliderBarTopMargin); - - // Precalculate and cache the slider bar position for this update - var sliderBarPosition = GUILayoutUtility.GetRect(0, LODGroupGUI.kSliderBarHeight, GUILayout.ExpandWidth(true)); - - // Precalculate the lod info (button locations / ranges ect) - var lods = LODGroupGUI.CreateLODInfos(m_NumberOfLODs, sliderBarPosition, - i => String.Format("LOD {0}", i), - i => serializedObject.FindProperty(string.Format(kPixelHeightDataPath, i)).floatValue); - - DrawLODLevelSlider(sliderBarPosition, lods); - GUILayout.Space(LODGroupGUI.kSliderBarBottomMargin); - - if (QualitySettings.lodBias != 1.0f) - EditorGUILayout.HelpBox(string.Format("Active LOD bias is {0:0.0#}. Distances are adjusted accordingly.", QualitySettings.lodBias), MessageType.Warning); - - // Draw the info for the selected LOD - if (m_NumberOfLODs > 0 && activeLOD >= 0 && activeLOD < m_NumberOfLODs) - { - m_ShowFadeTransitionWidth.target = IsLODUsingCrossFadeWidth(activeLOD); - if (EditorGUILayout.BeginFadeGroup(m_ShowFadeTransitionWidth.faded)) - EditorGUILayout.PropertyField(serializedObject.FindProperty(string.Format(kFadeTransitionWidthDataPath, activeLOD))); - EditorGUILayout.EndFadeGroup(); - DrawRenderersInfo(EditorGUIUtility.currentViewWidth); - } - - GUILayout.Space(8); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - bool needUpdateBounds = LODUtility.NeedUpdateLODGroupBoundingBox(m_LODGroup); - using (new EditorGUI.DisabledScope(!needUpdateBounds)) - { - if (GUILayout.Button(needUpdateBounds ? LODGroupGUI.Styles.m_RecalculateBounds : LODGroupGUI.Styles.m_RecalculateBoundsDisabled, GUILayout.ExpandWidth(false))) - { - Undo.RecordObject(m_LODGroup, "Recalculate LODGroup Bounds"); - m_LODGroup.RecalculateBounds(); - } - } - - if (GUILayout.Button(LODGroupGUI.Styles.m_LightmapScale, GUILayout.ExpandWidth(false))) - SendPercentagesToLightmapScale(); - - GUILayout.EndHorizontal(); - - GUILayout.Space(5); - - var importer = PrefabUtility.GetPrefabType(target) == PrefabType.ModelPrefabInstance ? GetImporter() : null; - if (importer != null) - { - var importerRef = new SerializedObject(importer); - var importerLODLevels = importerRef.FindProperty("m_LODScreenPercentages"); - var lodNumberOnImporterMatches = importerLODLevels.isArray && importerLODLevels.arraySize == lods.Count; - - var guiState = GUI.enabled; - if (!lodNumberOnImporterMatches) - GUI.enabled = false; - - if (GUILayout.Button(lodNumberOnImporterMatches ? LODGroupGUI.Styles.m_UploadToImporter : LODGroupGUI.Styles.m_UploadToImporterDisabled)) - { - // Number of imported LOD's is the same as in the imported model - for (var i = 0; i < importerLODLevels.arraySize; i++) - importerLODLevels.GetArrayElementAtIndex(i).floatValue = lods[i].RawScreenPercent; - - importerRef.ApplyModifiedProperties(); - - AssetDatabase.ImportAsset(importer.assetPath); - } - GUI.enabled = guiState; - } - - // Apply the property, handle undo - serializedObject.ApplyModifiedProperties(); - - GUI.enabled = initiallyEnabled; - } - - // Draw the renderers for the current LOD group - // Arrange in a grid - private void DrawRenderersInfo(float availableWidth) - { - var horizontalCount = Mathf.FloorToInt(availableWidth / LODGroupGUI.kRenderersButtonHeight); - var titleArea = GUILayoutUtility.GetRect(LODGroupGUI.Styles.m_RendersTitle, LODGroupGUI.Styles.m_LODSliderTextSelected); - if (Event.current.type == EventType.Repaint) - EditorStyles.label.Draw(titleArea, LODGroupGUI.Styles.m_RendersTitle, false, false, false, false); - - // Draw renderer info - var renderersProperty = serializedObject.FindProperty(string.Format(kRenderRootPath, activeLOD)); - - var numberOfButtons = renderersProperty.arraySize + 1; - var numberOfRows = Mathf.CeilToInt(numberOfButtons / (float)horizontalCount); - - var drawArea = GUILayoutUtility.GetRect(0, numberOfRows * LODGroupGUI.kRenderersButtonHeight, GUILayout.ExpandWidth(true)); - var rendererArea = drawArea; - GUI.Box(drawArea, GUIContent.none); - rendererArea.width -= 2 * LODGroupGUI.kRenderAreaForegroundPadding; - rendererArea.x += LODGroupGUI.kRenderAreaForegroundPadding; - - var buttonWidth = rendererArea.width / horizontalCount; - - var buttons = new List(); - - for (int i = 0; i < numberOfRows; i++) - { - for (int k = 0; k < horizontalCount && (i * horizontalCount + k) < renderersProperty.arraySize; k++) - { - var drawPos = new Rect( - LODGroupGUI.kButtonPadding + rendererArea.x + k * buttonWidth, - LODGroupGUI.kButtonPadding + rendererArea.y + i * LODGroupGUI.kRenderersButtonHeight, - buttonWidth - LODGroupGUI.kButtonPadding * 2, - LODGroupGUI.kRenderersButtonHeight - LODGroupGUI.kButtonPadding * 2); - buttons.Add(drawPos); - DrawRendererButton(drawPos, i * horizontalCount + k); - } - } - - if (m_IsPrefab) - return; - - //+ button - int horizontalPos = (numberOfButtons - 1) % horizontalCount; - int verticalPos = numberOfRows - 1; - HandleAddRenderer(new Rect( - LODGroupGUI.kButtonPadding + rendererArea.x + horizontalPos * buttonWidth, - LODGroupGUI.kButtonPadding + rendererArea.y + verticalPos * LODGroupGUI.kRenderersButtonHeight, - buttonWidth - LODGroupGUI.kButtonPadding * 2, - LODGroupGUI.kRenderersButtonHeight - LODGroupGUI.kButtonPadding * 2), buttons, drawArea); - } - - private void HandleAddRenderer(Rect position, IEnumerable alreadyDrawn, Rect drawArea) - { - Event evt = Event.current; - switch (evt.type) - { - case EventType.Repaint: - { - LODGroupGUI.Styles.m_LODStandardButton.Draw(position, GUIContent.none, false, false, false, false); - LODGroupGUI.Styles.m_LODRendererAddButton.Draw(new Rect(position.x - LODGroupGUI.kButtonPadding, position.y, position.width, position.height), "Add", false, false, false, false); - break; - } - case EventType.DragUpdated: - case EventType.DragPerform: - { - bool dragArea = false; - if (drawArea.Contains(evt.mousePosition)) - { - if (alreadyDrawn.All(x => !x.Contains(evt.mousePosition))) - dragArea = true; - } - - if (!dragArea) - break; - - // If we are over a valid range, make sure we have a game object... - if (DragAndDrop.objectReferences.Count() > 0) - { - DragAndDrop.visualMode = m_IsPrefab ? DragAndDropVisualMode.None : DragAndDropVisualMode.Copy; - - if (evt.type == EventType.DragPerform) - { - // First try gameobjects... - var selectedGameObjects = - from go in DragAndDrop.objectReferences - where go as GameObject != null - select go as GameObject; - - var renderers = GetRenderers(selectedGameObjects, true); - AddGameObjectRenderers(renderers, true); - DragAndDrop.AcceptDrag(); - - evt.Use(); - break; - } - } - evt.Use(); - break; - } - case EventType.MouseDown: - { - if (position.Contains(evt.mousePosition)) - { - evt.Use(); - int id = "LODGroupSelector".GetHashCode(); - ObjectSelector.get.Show(null, typeof(Renderer), null, true); - ObjectSelector.get.objectSelectorID = id; - GUIUtility.ExitGUI(); - } - break; - } - case EventType.ExecuteCommand: - { - string commandName = evt.commandName; - if (commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == "LODGroupSelector".GetHashCode()) - { - var selectedObject = ObjectSelector.GetCurrentObject() as GameObject; - if (selectedObject != null) - AddGameObjectRenderers(GetRenderers(new List { selectedObject }, true), true); - evt.Use(); - GUIUtility.ExitGUI(); - } - break; - } - } - } - - private void DrawRendererButton(Rect position, int rendererIndex) - { - var renderersProperty = serializedObject.FindProperty(string.Format(kRenderRootPath, activeLOD)); - var rendererRef = renderersProperty.GetArrayElementAtIndex(rendererIndex).FindPropertyRelative("renderer"); - var renderer = rendererRef.objectReferenceValue as Renderer; - - var deleteButton = new Rect(position.xMax - LODGroupGUI.kDeleteButtonSize, position.yMax - LODGroupGUI.kDeleteButtonSize, LODGroupGUI.kDeleteButtonSize, LODGroupGUI.kDeleteButtonSize); - - Event evt = Event.current; - switch (evt.type) - { - case EventType.Repaint: - { - if (renderer != null) - { - GUIContent content; - - var filter = renderer.GetComponent(); - if (filter != null && filter.sharedMesh != null) - content = new GUIContent(AssetPreview.GetAssetPreview(filter.sharedMesh), renderer.gameObject.name); - else if (renderer is SkinnedMeshRenderer) - content = new GUIContent(AssetPreview.GetAssetPreview((renderer as SkinnedMeshRenderer).sharedMesh), renderer.gameObject.name); - else - content = new GUIContent(ObjectNames.NicifyVariableName(renderer.GetType().Name), renderer.gameObject.name); - - LODGroupGUI.Styles.m_LODBlackBox.Draw(position, GUIContent.none, false, false, false, false); - - LODGroupGUI.Styles.m_LODRendererButton.Draw( - new Rect( - position.x + LODGroupGUI.kButtonPadding, - position.y + LODGroupGUI.kButtonPadding, - position.width - 2 * LODGroupGUI.kButtonPadding, position.height - 2 * LODGroupGUI.kButtonPadding), - content, false, false, false, false); - } - else - { - LODGroupGUI.Styles.m_LODBlackBox.Draw(position, GUIContent.none, false, false, false, false); - LODGroupGUI.Styles.m_LODRendererButton.Draw(position, "", false, false, false, false); - } - - if (!m_IsPrefab) - { - LODGroupGUI.Styles.m_LODBlackBox.Draw(deleteButton, GUIContent.none, false, false, false, false); - LODGroupGUI.Styles.m_LODRendererRemove.Draw(deleteButton, LODGroupGUI.Styles.m_IconRendererMinus, false, false, false, false); - } - break; - } - case EventType.MouseDown: - { - if (!m_IsPrefab && deleteButton.Contains(evt.mousePosition)) - { - renderersProperty.DeleteArrayElementAtIndex(rendererIndex); - evt.Use(); - serializedObject.ApplyModifiedProperties(); - m_LODGroup.RecalculateBounds(); - } - else if (position.Contains(evt.mousePosition)) - { - EditorGUIUtility.PingObject(renderer); - evt.Use(); - } - break; - } - } - } - - // Get all the renderers that are attached to this game object - private IEnumerable GetRenderers(IEnumerable selectedGameObjects, bool searchChildren) - { - // Only allow renderers that are parented to this LODGroup - if (EditorUtility.IsPersistent(m_LODGroup)) - return new List(); - - var validSearchObjects = from go in selectedGameObjects - where go.transform.IsChildOf(m_LODGroup.transform) - select go; - - var nonChildObjects = from go in selectedGameObjects - where !go.transform.IsChildOf(m_LODGroup.transform) - select go; - - // Handle reparenting - var validChildren = new List(); - if (nonChildObjects.Count() > 0) - { - const string kReparent = "Some objects are not children of the LODGroup GameObject. Do you want to reparent them and add them to the LODGroup?"; - if (EditorUtility.DisplayDialog( - "Reparent GameObjects", - kReparent, - "Yes, Reparent", - "No, Use Only Existing Children")) - { - foreach (var go in nonChildObjects) - { - if (EditorUtility.IsPersistent(go)) - { - var newGo = Instantiate(go) as GameObject; - if (newGo != null) - { - newGo.transform.parent = m_LODGroup.transform; - newGo.transform.localPosition = Vector3.zero; - newGo.transform.localRotation = Quaternion.identity; - validChildren.Add(newGo); - } - } - else - { - go.transform.parent = m_LODGroup.transform; - validChildren.Add(go); - } - } - validSearchObjects = validSearchObjects.Union(validChildren); - } - } - - //Get all the renderers - var renderers = new List(); - foreach (var go in validSearchObjects) - { - if (searchChildren) - renderers.AddRange(go.GetComponentsInChildren()); - else - renderers.Add(go.GetComponent()); - } - - // Then try renderers - var selectedRenderers = from go in DragAndDrop.objectReferences - where go as Renderer != null - select go as Renderer; - - renderers.AddRange(selectedRenderers); - return renderers; - } - - // Add the given renderers to the current LOD group - private void AddGameObjectRenderers(IEnumerable toAdd, bool add) - { - var renderersProperty = serializedObject.FindProperty(string.Format(kRenderRootPath, activeLOD)); - - if (!add) - renderersProperty.ClearArray(); - - // On add make a list of the old renderers (to check for dupes) - var oldRenderers = new List(); - for (var i = 0; i < renderersProperty.arraySize; i++) - { - var lodRenderRef = renderersProperty.GetArrayElementAtIndex(i).FindPropertyRelative("renderer"); - var renderer = lodRenderRef.objectReferenceValue as Renderer; - - if (renderer == null) - continue; - - oldRenderers.Add(renderer); - } - - foreach (var renderer in toAdd) - { - // Ensure that we don't add the renderer if it already exists - if (oldRenderers.Contains(renderer)) - continue; - - renderersProperty.arraySize += 1; - renderersProperty. - GetArrayElementAtIndex(renderersProperty.arraySize - 1). - FindPropertyRelative("renderer").objectReferenceValue = renderer; - - // Stop readd - oldRenderers.Add(renderer); - } - serializedObject.ApplyModifiedProperties(); - m_LODGroup.RecalculateBounds(); - } - - // Callabck action for mouse context clicks on the LOD slider(right click ect) - private class LODAction - { - private readonly float m_Percentage; - private readonly List m_LODs; - private readonly Vector2 m_ClickedPosition; - private readonly SerializedObject m_ObjectRef; - private readonly SerializedProperty m_LODsProperty; - - public delegate void Callback(); - private readonly Callback m_Callback; - - public LODAction(List lods, float percentage, Vector2 clickedPosition, SerializedProperty propLODs, Callback callback) - { - m_LODs = lods; - m_Percentage = percentage; - m_ClickedPosition = clickedPosition; - m_LODsProperty = propLODs; - m_ObjectRef = propLODs.serializedObject; - m_Callback = callback; - } - - public void InsertLOD() - { - if (!m_LODsProperty.isArray) - return; - - // Find where to insert - int insertIndex = -1; - foreach (var lod in m_LODs) - { - if (m_Percentage > lod.RawScreenPercent) - { - insertIndex = lod.LODLevel; - break; - } - } - - // Clicked in the culled area... duplicate last - if (insertIndex < 0) - { - m_LODsProperty.InsertArrayElementAtIndex(m_LODs.Count); - insertIndex = m_LODs.Count; - } - else - { - m_LODsProperty.InsertArrayElementAtIndex(insertIndex); - } - - // Null out the copied renderers (we want the list to be empty) - var renderers = m_ObjectRef.FindProperty(string.Format(kRenderRootPath, insertIndex)); - renderers.arraySize = 0; - - var newLOD = m_LODsProperty.GetArrayElementAtIndex(insertIndex); - newLOD.FindPropertyRelative("screenRelativeHeight").floatValue = m_Percentage; - if (m_Callback != null) - m_Callback(); - - m_ObjectRef.ApplyModifiedProperties(); - } - - public void DeleteLOD() - { - if (m_LODs.Count <= 0) - return; - - // Check for range click - foreach (var lod in m_LODs) - { - var numberOfRenderers = m_ObjectRef.FindProperty(string.Format(kRenderRootPath, lod.LODLevel)).arraySize; - if (lod.m_RangePosition.Contains(m_ClickedPosition) && (numberOfRenderers == 0 - || EditorUtility.DisplayDialog("Delete LOD", - "Are you sure you wish to delete this LOD?", - "Yes", - "No"))) - { - var lodData = m_ObjectRef.FindProperty(string.Format(kLODDataPath, lod.LODLevel)); - lodData.DeleteCommand(); - - m_ObjectRef.ApplyModifiedProperties(); - if (m_Callback != null) - m_Callback(); - break; - } - } - } - } - - private void DeletedLOD() - { - m_SelectedLOD--; - } - - // Set the camera distance so that the current LOD group covers the desired percentage of the screen - private static void UpdateCamera(float desiredPercentage, LODGroup group) - { - var worldReferencePoint = LODUtility.CalculateWorldReferencePoint(group); - var percentage = Mathf.Max(desiredPercentage / QualitySettings.lodBias, 0.000001f); - - // Figure out a distance based on the percentage - var distance = LODUtility.CalculateDistance(SceneView.lastActiveSceneView.camera, percentage, group); - - if (SceneView.lastActiveSceneView.camera.orthographic) - distance *= Mathf.Sqrt(2 * SceneView.lastActiveSceneView.camera.aspect); - - SceneView.lastActiveSceneView.LookAtDirect(worldReferencePoint, SceneView.lastActiveSceneView.camera.transform.rotation, distance); - } - - private void UpdateSelectedLODFromCamera(IEnumerable lods, float cameraPercent) - { - foreach (var lod in lods) - { - if (cameraPercent > lod.RawScreenPercent) - { - m_SelectedLOD = lod.LODLevel; - break; - } - } - } - - private readonly int m_LODSliderId = "LODSliderIDHash".GetHashCode(); - private readonly int m_CameraSliderId = "LODCameraIDHash".GetHashCode(); - private void DrawLODLevelSlider(Rect sliderPosition, List lods) - { - int sliderId = GUIUtility.GetControlID(m_LODSliderId, FocusType.Passive); - int camerId = GUIUtility.GetControlID(m_CameraSliderId, FocusType.Passive); - Event evt = Event.current; - - switch (evt.GetTypeForControl(sliderId)) - { - case EventType.Repaint: - { - LODGroupGUI.DrawLODSlider(sliderPosition, lods, activeLOD); - break; - } - case EventType.MouseDown: - { - // Handle right click first - if (evt.button == 1 && sliderPosition.Contains(evt.mousePosition)) - { - var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition); - var pm = new GenericMenu(); - if (lods.Count >= 8) - { - pm.AddDisabledItem(EditorGUIUtility.TrTextContent("Insert Before")); - } - else - { - pm.AddItem(EditorGUIUtility.TrTextContent("Insert Before"), false, - new LODAction(lods, cameraPercent, evt.mousePosition, m_LODs, null). - InsertLOD); - } - - // Figure out if we clicked in the culled region - var disabledRegion = true; - if (lods.Count > 0 && lods[lods.Count - 1].RawScreenPercent < cameraPercent) - disabledRegion = false; - - if (disabledRegion) - pm.AddDisabledItem(EditorGUIUtility.TrTextContent("Delete")); - else - pm.AddItem(EditorGUIUtility.TrTextContent("Delete"), false, - new LODAction(lods, cameraPercent, evt.mousePosition, m_LODs, DeletedLOD). - DeleteLOD); - pm.ShowAsContext(); - - // Do selection - bool selected = false; - foreach (var lod in lods) - { - if (lod.m_RangePosition.Contains(evt.mousePosition)) - { - m_SelectedLOD = lod.LODLevel; - selected = true; - break; - } - } - - if (!selected) - m_SelectedLOD = -1; - - evt.Use(); - - break; - } - - // Slightly grow position on the x because edge buttons overflow by 5 pixels - var barPosition = sliderPosition; - barPosition.x -= 5; - barPosition.width += 10; - - if (barPosition.Contains(evt.mousePosition)) - { - evt.Use(); - GUIUtility.hotControl = sliderId; - - // Check for button click - var clickedButton = false; - - // case:464019 have to re-sort the LOD array for these buttons to get the overlaps in the right order... - var lodsLeft = lods.Where(lod => lod.ScreenPercent > 0.5f).OrderByDescending(x => x.LODLevel); - var lodsRight = lods.Where(lod => lod.ScreenPercent <= 0.5f).OrderBy(x => x.LODLevel); - - var lodButtonOrder = new List(); - lodButtonOrder.AddRange(lodsLeft); - lodButtonOrder.AddRange(lodsRight); - - foreach (var lod in lodButtonOrder) - { - if (lod.m_ButtonPosition.Contains(evt.mousePosition)) - { - m_SelectedLODSlider = lod.LODLevel; - clickedButton = true; - // Bias by 0.1% so that there is no skipping when sliding - BeginLODDrag(lod.RawScreenPercent + 0.001f, m_LODGroup); - break; - } - } - - if (!clickedButton) - { - // Check for range click - foreach (var lod in lodButtonOrder) - { - if (lod.m_RangePosition.Contains(evt.mousePosition)) - { - m_SelectedLODSlider = -1; - m_SelectedLOD = lod.LODLevel; - break; - } - } - } - } - break; - } - - case EventType.MouseDrag: - { - if (GUIUtility.hotControl == sliderId && m_SelectedLODSlider >= 0 && lods[m_SelectedLODSlider] != null) - { - evt.Use(); - - var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition); - // Bias by 0.1% so that there is no skipping when sliding - LODGroupGUI.SetSelectedLODLevelPercentage(cameraPercent - 0.001f, m_SelectedLODSlider, lods); - var percentageProperty = serializedObject.FindProperty(string.Format(kPixelHeightDataPath, lods[m_SelectedLODSlider].LODLevel)); - percentageProperty.floatValue = lods[m_SelectedLODSlider].RawScreenPercent; - - UpdateLODDrag(cameraPercent, m_LODGroup); - } - break; - } - - case EventType.MouseUp: - { - if (GUIUtility.hotControl == sliderId) - { - GUIUtility.hotControl = 0; - m_SelectedLODSlider = -1; - EndLODDrag(); - evt.Use(); - } - break; - } - - case EventType.DragUpdated: - case EventType.DragPerform: - { - // -2 = invalid region - // -1 = culledregion - // rest = LOD level - var lodLevel = -2; - // Is the mouse over a valid LOD level range? - foreach (var lod in lods) - { - if (lod.m_RangePosition.Contains(evt.mousePosition)) - { - lodLevel = lod.LODLevel; - break; - } - } - - if (lodLevel == -2) - { - var culledRange = LODGroupGUI.GetCulledBox(sliderPosition, lods.Count > 0 ? lods[lods.Count - 1].ScreenPercent : 1.0f); - if (culledRange.Contains(evt.mousePosition)) - { - lodLevel = -1; - } - } - - if (lodLevel >= -1) - { - // Actually set LOD level now - m_SelectedLOD = lodLevel; - - if (DragAndDrop.objectReferences.Count() > 0) - { - DragAndDrop.visualMode = m_IsPrefab ? DragAndDropVisualMode.None : DragAndDropVisualMode.Copy; - - if (evt.type == EventType.DragPerform) - { - // First try gameobjects... - var selectedGameObjects = from go in DragAndDrop.objectReferences - where go as GameObject != null - select go as GameObject; - var renderers = GetRenderers(selectedGameObjects, true); - - if (lodLevel == -1) - { - m_LODs.arraySize++; - var pixelHeightNew = serializedObject.FindProperty(string.Format(kPixelHeightDataPath, lods.Count)); - - if (lods.Count == 0) - pixelHeightNew.floatValue = 0.5f; - else - { - var pixelHeightPrevious = serializedObject.FindProperty(string.Format(kPixelHeightDataPath, lods.Count - 1)); - pixelHeightNew.floatValue = pixelHeightPrevious.floatValue / 2.0f; - } - - m_SelectedLOD = lods.Count; - AddGameObjectRenderers(renderers, false); - } - else - { - AddGameObjectRenderers(renderers, true); - } - DragAndDrop.AcceptDrag(); - } - } - evt.Use(); - break; - } - - break; - } - case EventType.DragExited: - { - evt.Use(); - break; - } - } - if (SceneView.lastActiveSceneView != null && SceneView.lastActiveSceneView.camera != null && !m_IsPrefab) - { - var camera = SceneView.lastActiveSceneView.camera; - - var info = LODUtility.CalculateVisualizationData(camera, m_LODGroup, -1); - var linearHeight = info.activeRelativeScreenSize; - var relativeHeight = LODGroupGUI.DelinearizeScreenPercentage(linearHeight); - - var worldReferencePoint = LODUtility.CalculateWorldReferencePoint(m_LODGroup); - var vectorFromObjectToCamera = (SceneView.lastActiveSceneView.camera.transform.position - worldReferencePoint).normalized; - if (Vector3.Dot(camera.transform.forward, vectorFromObjectToCamera) > 0f) - relativeHeight = 1.0f; - - var cameraRect = LODGroupGUI.CalcLODButton(sliderPosition, Mathf.Clamp01(relativeHeight)); - var cameraIconRect = new Rect(cameraRect.center.x - 15, cameraRect.y - 25, 32, 32); - var cameraLineRect = new Rect(cameraRect.center.x - 1, cameraRect.y, 2, cameraRect.height); - var cameraPercentRect = new Rect(cameraIconRect.center.x - 5, cameraLineRect.yMax, 35, 20); - - switch (evt.GetTypeForControl(camerId)) - { - case EventType.Repaint: - { - // Draw a marker to indicate the current scene camera distance - var colorCache = GUI.backgroundColor; - GUI.backgroundColor = new Color(colorCache.r, colorCache.g, colorCache.b, 0.8f); - LODGroupGUI.Styles.m_LODCameraLine.Draw(cameraLineRect, false, false, false, false); - GUI.backgroundColor = colorCache; - GUI.Label(cameraIconRect, LODGroupGUI.Styles.m_CameraIcon, GUIStyle.none); - LODGroupGUI.Styles.m_LODSliderText.Draw(cameraPercentRect, String.Format("{0:0}%", Mathf.Clamp01(linearHeight) * 100.0f), false, false, false, false); - break; - } - case EventType.MouseDown: - { - if (cameraIconRect.Contains(evt.mousePosition)) - { - evt.Use(); - var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition); - - // Update the selected LOD to be where the camera is if we click the camera - UpdateSelectedLODFromCamera(lods, cameraPercent); - GUIUtility.hotControl = camerId; - - BeginLODDrag(cameraPercent, m_LODGroup); - } - break; - } - case EventType.MouseDrag: - { - if (GUIUtility.hotControl == camerId) - { - evt.Use(); - var cameraPercent = LODGroupGUI.GetCameraPercent(evt.mousePosition, sliderPosition); - - // Change the active LOD level if the camera moves into a new LOD level - UpdateSelectedLODFromCamera(lods, cameraPercent); - UpdateLODDrag(cameraPercent, m_LODGroup); - } - break; - } - case EventType.MouseUp: - { - if (GUIUtility.hotControl == camerId) - { - EndLODDrag(); - GUIUtility.hotControl = 0; - evt.Use(); - } - break; - } - } - } - } - - private void BeginLODDrag(float desiredPercentage, LODGroup group) - { - if (SceneView.lastActiveSceneView == null || SceneView.lastActiveSceneView.camera == null || m_IsPrefab) - return; - - UpdateCamera(desiredPercentage, group); - SceneView.lastActiveSceneView.ClearSearchFilter(); - SceneView.lastActiveSceneView.SetSceneViewFiltering(true); - HierarchyProperty.FilterSingleSceneObject(group.gameObject.GetInstanceID(), false); - SceneView.RepaintAll(); - } - - private void UpdateLODDrag(float desiredPercentage, LODGroup group) - { - if (SceneView.lastActiveSceneView == null || SceneView.lastActiveSceneView.camera == null || m_IsPrefab) - return; - - UpdateCamera(desiredPercentage, group); - SceneView.RepaintAll(); - } - - private void EndLODDrag() - { - if (SceneView.lastActiveSceneView == null || SceneView.lastActiveSceneView.camera == null || m_IsPrefab) - return; - - SceneView.lastActiveSceneView.SetSceneViewFiltering(false); - SceneView.lastActiveSceneView.ClearSearchFilter(); - // Clearing the search filter of a SceneView will not actually reset the visibility values - // of the GameObjects in the scene so we have to explicitly do that (case 770915). - HierarchyProperty.ClearSceneObjectsFilter(); - } - - //Code to be able to send percentages to this gameobjects lightmap scale - private class LODLightmapScale - { - public readonly float m_Scale; - public readonly List m_Renderers; - - public LODLightmapScale(float scale, List renderers) - { - m_Scale = scale; - m_Renderers = renderers; - } - } - - private void SendPercentagesToLightmapScale() - { - //List of renderers per LOD - var lodRenderers = new List(); - - for (var i = 0; i < m_NumberOfLODs; i++) - { - var renderersProperty = serializedObject.FindProperty(string.Format(kRenderRootPath, i)); - var renderersAtLOD = new List(); - - for (var k = 0; k < renderersProperty.arraySize; k++) - { - var rendererRef = renderersProperty.GetArrayElementAtIndex(k).FindPropertyRelative("renderer"); - - if (rendererRef != null) - renderersAtLOD.Add(rendererRef); - } - var pixelHeight = i == 0 ? 1.0f : serializedObject.FindProperty(string.Format(kPixelHeightDataPath, i - 1)).floatValue; - lodRenderers.Add(new LODLightmapScale(pixelHeight, renderersAtLOD)); - } - - for (var i = 0; i < m_NumberOfLODs; i++) - { - SetLODLightmapScale(lodRenderers[i]); - } - } - - private static void SetLODLightmapScale(LODLightmapScale lodRenderer) - { - foreach (var renderer in lodRenderer.m_Renderers) - { - if (renderer.objectReferenceValue == null) - continue; - var so = new SerializedObject(renderer.objectReferenceValue); - var lightmapScaleProp = so.FindProperty("m_ScaleInLightmap"); - lightmapScaleProp.floatValue = Mathf.Max(0.0f, lodRenderer.m_Scale * (1.0f / LightmapVisualization.GetLightmapLODLevelScale((Renderer)renderer.objectReferenceValue))); - so.ApplyModifiedProperties(); - } - } - - // / PREVIEW GUI CODE BELOW - public override bool HasPreviewGUI() - { - return (target != null); - } - - private PreviewRenderUtility m_PreviewUtility; - static private readonly GUIContent[] kSLightIcons = {null, null}; - private Vector2 m_PreviewDir = new Vector2(0, -20); - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - { - if (Event.current.type == EventType.Repaint) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), "LOD preview \nnot available"); - return; - } - - InitPreview(); - m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, r); - m_PreviewDir.y = Mathf.Clamp(m_PreviewDir.y, -89.0f, 89.0f); - - if (Event.current.type != EventType.Repaint) - return; - - m_PreviewUtility.BeginPreview(r, background); - - DoRenderPreview(); - - m_PreviewUtility.EndAndDrawPreview(r); - } - - void InitPreview() - { - if (m_PreviewUtility == null) - m_PreviewUtility = new PreviewRenderUtility(); - - if (kSLightIcons[0] == null) - { - kSLightIcons[0] = EditorGUIUtility.IconContent("PreMatLight0"); - kSLightIcons[1] = EditorGUIUtility.IconContent("PreMatLight1"); - } - } - - protected void DoRenderPreview() - { - if (m_PreviewUtility.renderTexture.width <= 0 - || m_PreviewUtility.renderTexture.height <= 0 - || m_NumberOfLODs <= 0 - || activeLOD < 0) - return; - - var bounds = new Bounds(Vector3.zero, Vector3.zero); - bool boundsSet = false; - - var meshsToRender = new List(); - var renderers = serializedObject.FindProperty(string.Format(kRenderRootPath, activeLOD)); - for (int i = 0; i < renderers.arraySize; i++) - { - var lodRenderRef = renderers.GetArrayElementAtIndex(i).FindPropertyRelative("renderer"); - var renderer = lodRenderRef.objectReferenceValue as Renderer; - - if (renderer == null) - continue; - - var meshFilter = renderer.GetComponent(); - if (meshFilter != null && meshFilter.sharedMesh != null && meshFilter.sharedMesh.subMeshCount > 0) - { - meshsToRender.Add(meshFilter); - } - - if (!boundsSet) - { - bounds = renderer.bounds; - boundsSet = true; - } - else - bounds.Encapsulate(renderer.bounds); - } - - if (!boundsSet) - return; - - var halfSize = bounds.extents.magnitude; - var distance = halfSize * 10.0f; - - var viewDir = -(m_PreviewDir / 100.0f); - - 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); - - m_PreviewUtility.camera.transform.LookAt(bounds.center); - m_PreviewUtility.camera.nearClipPlane = 0.05f; - m_PreviewUtility.camera.farClipPlane = 1000.0f; - - m_PreviewUtility.lights[0].intensity = 1.0f; - m_PreviewUtility.lights[0].transform.rotation = Quaternion.Euler(50f, 50f, 0); - m_PreviewUtility.lights[1].intensity = 1.0f; - - m_PreviewUtility.ambientColor = new Color(.2f, .2f, .2f, 0); - - foreach (var meshFilter in meshsToRender) - { - for (int k = 0; k < meshFilter.sharedMesh.subMeshCount; k++) - { - if (k < meshFilter.GetComponent().sharedMaterials.Length) - { - var matrix = Matrix4x4.TRS(meshFilter.transform.position, meshFilter.transform.rotation, meshFilter.transform.localScale); - m_PreviewUtility.DrawMesh( - meshFilter.sharedMesh, - matrix, - meshFilter.GetComponent().sharedMaterials[k], - k); - } - } - } - - m_PreviewUtility.Render(); - } - - override public string GetInfoString() - { - if (SceneView.lastActiveSceneView == null - || SceneView.lastActiveSceneView.camera == null - || m_NumberOfLODs <= 0 - || activeLOD < 0) - return ""; - - var materials = new List(); - var renderers = serializedObject.FindProperty(string.Format(kRenderRootPath, activeLOD)); - for (int i = 0; i < renderers.arraySize; i++) - { - var renderRef = renderers.GetArrayElementAtIndex(i).FindPropertyRelative("renderer"); - var renderer = renderRef.objectReferenceValue as Renderer; - - if (renderer != null) - materials.AddRange(renderer.sharedMaterials); - } - - var camera = SceneView.lastActiveSceneView.camera; - - var info = LODUtility.CalculateVisualizationData(camera, m_LODGroup, activeLOD); - 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"; - } - } -} diff --git a/Editor/Mono/Inspector/LODGroupGUI.cs b/Editor/Mono/Inspector/LODGroupGUI.cs deleted file mode 100644 index 8a463cf27c..0000000000 --- a/Editor/Mono/Inspector/LODGroupGUI.cs +++ /dev/null @@ -1,272 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal static class LODGroupGUI - { - // Default colors for each LOD group.... - public static readonly Color[] kLODColors = - { - new Color(0.4831376f, 0.6211768f, 0.0219608f, 1.0f), - new Color(0.2792160f, 0.4078432f, 0.5835296f, 1.0f), - new Color(0.2070592f, 0.5333336f, 0.6556864f, 1.0f), - new Color(0.5333336f, 0.1600000f, 0.0282352f, 1.0f), - new Color(0.3827448f, 0.2886272f, 0.5239216f, 1.0f), - new Color(0.8000000f, 0.4423528f, 0.0000000f, 1.0f), - new Color(0.4486272f, 0.4078432f, 0.0501960f, 1.0f), - new Color(0.7749016f, 0.6368624f, 0.0250984f, 1.0f) - }; - - public static readonly Color kCulledLODColor = new Color(.4f, 0f, 0f, 1f); - - public const int kSceneLabelHalfWidth = 100; - public const int kSceneLabelHeight = 45; - public const int kSceneHeaderOffset = 40; - - public const int kSliderBarTopMargin = 18; - public const int kSliderBarHeight = 30; - public const int kSliderBarBottomMargin = 16; - - public const int kRenderersButtonHeight = 60; - public const int kButtonPadding = 2; - public const int kDeleteButtonSize = 20; - - public const int kSelectedLODRangePadding = 3; - - public const int kRenderAreaForegroundPadding = 3; - - public class GUIStyles - { - public readonly GUIStyle m_LODSliderBG = "LODSliderBG"; - public readonly GUIStyle m_LODSliderRange = "LODSliderRange"; - public readonly GUIStyle m_LODSliderRangeSelected = "LODSliderRangeSelected"; - public readonly GUIStyle m_LODSliderText = "LODSliderText"; - public readonly GUIStyle m_LODSliderTextSelected = "LODSliderTextSelected"; - public readonly GUIStyle m_LODStandardButton = "Button"; - public readonly GUIStyle m_LODRendererButton = "LODRendererButton"; - public readonly GUIStyle m_LODRendererAddButton = "LODRendererAddButton"; - public readonly GUIStyle m_LODRendererRemove = "LODRendererRemove"; - public readonly GUIStyle m_LODBlackBox = "LODBlackBox"; - public readonly GUIStyle m_LODCameraLine = "LODCameraLine"; - - public readonly GUIStyle m_LODSceneText = "LODSceneText"; - public readonly GUIStyle m_LODRenderersText = "LODRenderersText"; - public readonly GUIStyle m_LODLevelNotifyText = "LODLevelNotifyText"; - - public readonly GUIContent m_IconRendererPlus = EditorGUIUtility.TrIconContent("Toolbar Plus", "Add New Renderers"); - public readonly GUIContent m_IconRendererMinus = EditorGUIUtility.TrIconContent("Toolbar Minus", "Remove Renderer"); - public readonly GUIContent m_CameraIcon = EditorGUIUtility.IconContent("Camera Icon"); - - public readonly GUIContent m_UploadToImporter = EditorGUIUtility.TrTextContent("Upload to Importer", "Upload the modified screen percentages to the model importer."); - 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."); - public readonly GUIContent m_RecalculateBounds = EditorGUIUtility.TrTextContent("Recalculate Bounds", "Recalculate bounds to encapsulate all child renderers."); - public readonly GUIContent m_RecalculateBoundsDisabled = EditorGUIUtility.TrTextContent("Recalculate Bounds", "Bounds are already up-to-date."); - public readonly GUIContent m_LightmapScale = EditorGUIUtility.TrTextContent("Recalculate Lightmap Scale", "Set the lightmap scale to match the LOD percentages."); - public readonly GUIContent m_RendersTitle = EditorGUIUtility.TrTextContent("Renderers:"); - - 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."); - 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."); - 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."); - } - - private static GUIStyles s_Styles; - - public static GUIStyles Styles - { - get - { - if (s_Styles == null) - s_Styles = new GUIStyles(); - return s_Styles; - } - } - - public static float DelinearizeScreenPercentage(float percentage) - { - if (Mathf.Approximately(0.0f, percentage)) - return 0.0f; - - return Mathf.Sqrt(percentage); - } - - public static float LinearizeScreenPercentage(float percentage) - { - return percentage * percentage; - } - - public static Rect CalcLODButton(Rect totalRect, float percentage) - { - return new Rect(totalRect.x + (Mathf.Round(totalRect.width * (1.0f - percentage))) - 5, totalRect.y, 10, totalRect.height); - } - - public static Rect GetCulledBox(Rect totalRect, float previousLODPercentage) - { - var r = CalcLODRange(totalRect, previousLODPercentage, 0.0f); - r.height -= 2; - r.width -= 1; - r.center += new Vector2(0f, 1.0f); - return r; - } - - public class LODInfo - { - public Rect m_ButtonPosition; - public Rect m_RangePosition; - - public LODInfo(int lodLevel, string name, float screenPercentage) - { - LODLevel = lodLevel; - LODName = name; - RawScreenPercent = screenPercentage; - } - - public int LODLevel { get; private set; } - public string LODName { get; private set; } - public float RawScreenPercent { get; set; } - - public float ScreenPercent - { - get { return DelinearizeScreenPercentage(RawScreenPercent); } - set { RawScreenPercent = LinearizeScreenPercentage(value); } - } - } - - public static List CreateLODInfos(int numLODs, Rect area, Func nameGen, Func heightGen) - { - var lods = new List(); - - for (int i = 0; i < numLODs; ++i) - { - var lodInfo = new LODInfo(i, nameGen(i), heightGen(i)); - lodInfo.m_ButtonPosition = CalcLODButton(area, lodInfo.ScreenPercent); - var previousPercentage = i == 0 ? 1.0f : lods[i - 1].ScreenPercent; - lodInfo.m_RangePosition = CalcLODRange(area, previousPercentage, lodInfo.ScreenPercent); - lods.Add(lodInfo); - } - - return lods; - } - - public static float GetCameraPercent(Vector2 position, Rect sliderRect) - { - var percentage = Mathf.Clamp(1.0f - (position.x - sliderRect.x) / sliderRect.width, 0.01f, 1.0f); - percentage = LODGroupGUI.LinearizeScreenPercentage(percentage); - return percentage; - } - - public static void SetSelectedLODLevelPercentage(float newScreenPercentage, int lod, List lods) - { - // Find the lower detail lod... clamp value to stop overlapping slider - var minimum = 0.0f; - var lowerLOD = lods.FirstOrDefault(x => x.LODLevel == lods[lod].LODLevel + 1); - if (lowerLOD != null) - minimum = lowerLOD.RawScreenPercent; - - // Find the higher detail lod... clamp value to stop overlapping slider - var maximum = 1.0f; - var higherLOD = lods.FirstOrDefault(x => x.LODLevel == lods[lod].LODLevel - 1); - if (higherLOD != null) - maximum = higherLOD.RawScreenPercent; - - maximum = Mathf.Clamp01(maximum); - minimum = Mathf.Clamp01(minimum); - - // Set that value - lods[lod].RawScreenPercent = Mathf.Clamp(newScreenPercentage, minimum, maximum); - } - - public static void DrawLODSlider(Rect area, IList lods, int selectedLevel) - { - Styles.m_LODSliderBG.Draw(area, GUIContent.none, false, false, false, false); - for (int i = 0; i < lods.Count; i++) - { - var lod = lods[i]; - DrawLODRange(lod, i == 0 ? 1.0f : lods[i - 1].RawScreenPercent, i == selectedLevel); - DrawLODButton(lod); - } - - // Draw the last range (culled) - DrawCulledRange(area, lods.Count > 0 ? lods[lods.Count - 1].RawScreenPercent : 1.0f); - } - - public static void DrawMixedValueLODSlider(Rect area) - { - Styles.m_LODSliderBG.Draw(area, GUIContent.none, false, false, false, false); - var r = GetCulledBox(area, 1.0f); - // Draw the range of a lod level on the slider - var tempColor = GUI.color; - GUI.color = kLODColors[1] * 0.6f; // more greyish - Styles.m_LODSliderRange.Draw(r, GUIContent.none, false, false, false, false); - GUI.color = tempColor; - var centeredStyle = new GUIStyle(EditorStyles.whiteLargeLabel) - { - alignment = TextAnchor.MiddleCenter - }; - GUI.Label(area, "---", centeredStyle); - } - - private static Rect CalcLODRange(Rect totalRect, float startPercent, float endPercent) - { - var startX = Mathf.Round(totalRect.width * (1.0f - startPercent)); - var endX = Mathf.Round(totalRect.width * (1.0f - endPercent)); - - return new Rect(totalRect.x + startX, totalRect.y, endX - startX, totalRect.height); - } - - private static void DrawLODButton(LODInfo currentLOD) - { - // Make the lod button areas a horizonal resizer - EditorGUIUtility.AddCursorRect(currentLOD.m_ButtonPosition, MouseCursor.ResizeHorizontal); - } - - private static void DrawLODRange(LODInfo currentLOD, float previousLODPercentage, bool isSelected) - { - var tempColor = GUI.backgroundColor; - var startPercentageString = string.Format("{0}\n{1:0}%", currentLOD.LODName, previousLODPercentage * 100); - if (isSelected) - { - var foreground = currentLOD.m_RangePosition; - foreground.width -= kSelectedLODRangePadding * 2; - foreground.height -= kSelectedLODRangePadding * 2; - foreground.center += new Vector2(kSelectedLODRangePadding, kSelectedLODRangePadding); - Styles.m_LODSliderRangeSelected.Draw(currentLOD.m_RangePosition, GUIContent.none, false, false, false, false); - GUI.backgroundColor = kLODColors[currentLOD.LODLevel]; - if (foreground.width > 0) - Styles.m_LODSliderRange.Draw(foreground, GUIContent.none, false, false, false, false); - Styles.m_LODSliderText.Draw(currentLOD.m_RangePosition, startPercentageString, false, false, false, false); - } - else - { - GUI.backgroundColor = kLODColors[currentLOD.LODLevel]; - GUI.backgroundColor *= 0.6f; - Styles.m_LODSliderRange.Draw(currentLOD.m_RangePosition, GUIContent.none, false, false, false, false); - Styles.m_LODSliderText.Draw(currentLOD.m_RangePosition, startPercentageString, false, false, false, false); - } - GUI.backgroundColor = tempColor; - } - - private static void DrawCulledRange(Rect totalRect, float previousLODPercentage) - { - if (Mathf.Approximately(previousLODPercentage, 0.0f)) return; - - var r = GetCulledBox(totalRect, DelinearizeScreenPercentage(previousLODPercentage)); - // Draw the range of a lod level on the slider - var tempColor = GUI.color; - GUI.color = kCulledLODColor; - Styles.m_LODSliderRange.Draw(r, GUIContent.none, false, false, false, false); - GUI.color = tempColor; - - // Draw some details for the current marker - var startPercentageString = string.Format("Culled\n{0:0}%", previousLODPercentage * 100); - Styles.m_LODSliderText.Draw(r, startPercentageString, false, false, false, false); - } - } -} diff --git a/Editor/Mono/Inspector/LabelGUI.cs b/Editor/Mono/Inspector/LabelGUI.cs deleted file mode 100644 index c7b69c305f..0000000000 --- a/Editor/Mono/Inspector/LabelGUI.cs +++ /dev/null @@ -1,239 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Linq; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class LabelGUI - { - HashSet m_CurrentAssetsSet; - PopupList.InputData m_AssetLabels; - string m_ChangedLabel; - bool m_CurrentChanged = false; - bool m_ChangeWasAdd = false; - bool m_IgnoreNextAssetLabelsChangedCall = false; - - static Action s_AssetLabelsForObjectChangedDelegates; - private static int s_MaxShownLabels = 10; - - public void OnEnable() - { - s_AssetLabelsForObjectChangedDelegates += AssetLabelsChangedForObject; - EditorApplication.projectChanged += InvalidateLabels; - } - - public void OnDisable() - { - s_AssetLabelsForObjectChangedDelegates -= AssetLabelsChangedForObject; - EditorApplication.projectChanged -= InvalidateLabels; - SaveLabels(); - } - - public void OnLostFocus() - { - SaveLabels(); - } - - public void InvalidateLabels() - { - m_AssetLabels = null; - m_CurrentAssetsSet = null; - } - - public void AssetLabelsChangedForObject(Object asset) - { - if (!m_IgnoreNextAssetLabelsChangedCall && m_CurrentAssetsSet != null && m_CurrentAssetsSet.Contains(asset)) - { - m_AssetLabels = null; // someone else changed the labels for one of our selected assets, so invalidate cache - } - m_IgnoreNextAssetLabelsChangedCall = false; - } - - public void SaveLabels() - { - if (m_CurrentChanged && m_AssetLabels != null && m_CurrentAssetsSet != null) - { - bool anyLabelsWereChanged = false; - foreach (var currentAsset in m_CurrentAssetsSet) - { - bool currentAssetWasChanged = false; // when multi-editing, some assets might e.g. already have the label that was added to all - string[] currentLabels = AssetDatabase.GetLabels(currentAsset); - List currentLabelList = currentLabels.ToList(); - if (m_ChangeWasAdd) - { - if (!currentLabelList.Contains(m_ChangedLabel)) - { - currentLabelList.Add(m_ChangedLabel); - currentAssetWasChanged = true; - } - } - else - { - if (currentLabelList.Contains(m_ChangedLabel)) - { - currentLabelList.Remove(m_ChangedLabel); - currentAssetWasChanged = true; - } - } - if (currentAssetWasChanged) - { - AssetDatabase.SetLabels(currentAsset, currentLabelList.ToArray()); - if (s_AssetLabelsForObjectChangedDelegates != null) - { - m_IgnoreNextAssetLabelsChangedCall = true; - s_AssetLabelsForObjectChangedDelegates(currentAsset); - } - anyLabelsWereChanged = true; - } - } - if (anyLabelsWereChanged) - EditorApplication.Internal_CallAssetLabelsHaveChanged(); - m_CurrentChanged = false; - } - } - - public void AssetLabelListCallback(PopupList.ListElement element) - { - m_ChangedLabel = element.text; - element.selected = !element.selected; - m_ChangeWasAdd = element.selected; - element.partiallySelected = false; - m_CurrentChanged = true; - SaveLabels(); - InspectorWindow.RepaintAllInspectors(); - } - - public void InitLabelCache(Object[] assets) - { - HashSet newAssetSet = new HashSet(assets); - // Init only if new asset - if (m_CurrentAssetsSet == null || !m_CurrentAssetsSet.SetEquals(newAssetSet)) - { - List all; - List partial; - GetLabelsForAssets(assets, out all, out partial); - - m_AssetLabels = new PopupList.InputData - { - m_CloseOnSelection = false, - m_AllowCustom = true, - m_OnSelectCallback = AssetLabelListCallback, - m_MaxCount = 15, - m_SortAlphabetically = true - }; - - Dictionary allLabels = AssetDatabase.GetAllLabels(); - foreach (var pair in allLabels) - { - PopupList.ListElement element = m_AssetLabels.NewOrMatchingElement(pair.Key); - if (element.filterScore < pair.Value) - { - element.filterScore = pair.Value; - } - element.selected = all.Any(label => string.Equals(label, pair.Key, StringComparison.OrdinalIgnoreCase)); - element.partiallySelected = partial.Any(label => string.Equals(label, pair.Key, StringComparison.OrdinalIgnoreCase)); - } - } - - m_CurrentAssetsSet = newAssetSet; - m_CurrentChanged = false; - } - - public void OnLabelGUI(Object[] assets) - { - InitLabelCache(assets); - - // For the label list as a whole - // 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 - // (the rounded sides of labels makes this look like the horizontal and vertical padding is the same) - float leftPadding = 1.0f; - float rightPadding = 2.0f; - float topPadding = 3.0f; - float bottomPadding = 5.0f; - - GUIStyle labelButton = EditorStyles.assetLabelIcon; - - float buttonWidth = labelButton.margin.left + labelButton.fixedWidth + rightPadding; - - // Assumes we are already in a vertical layout - GUILayout.Space(topPadding); - - // Create a rect to test how wide the label list can be - Rect widthProbeRect = GUILayoutUtility.GetRect(0, 10240, 0, 0); - widthProbeRect.width -= buttonWidth; // reserve some width for the button - - EditorGUILayout.BeginHorizontal(); - - // Left padding - GUILayoutUtility.GetRect(leftPadding, leftPadding, 0, 0); - - // Draw labels (fully selected) - DrawLabelList(false, widthProbeRect.xMax); - - // Draw labels (partially selected) - DrawLabelList(true, widthProbeRect.xMax); - - GUILayout.FlexibleSpace(); - - Rect r = GUILayoutUtility.GetRect(labelButton.fixedWidth, labelButton.fixedWidth, labelButton.fixedHeight + bottomPadding, labelButton.fixedHeight + bottomPadding); - r.x = widthProbeRect.xMax + labelButton.margin.left; - if (EditorGUI.DropdownButton(r, GUIContent.none, FocusType.Passive, labelButton)) - { - PopupWindow.Show(r, new PopupList(m_AssetLabels), null, ShowMode.PopupMenuWithKeyboardFocus); - } - - EditorGUILayout.EndHorizontal(); - } - - private void DrawLabelList(bool partiallySelected, float xMax) - { - GUIStyle labelStyle = partiallySelected ? EditorStyles.assetLabelPartial : EditorStyles.assetLabel; - Event evt = Event.current; - 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)) - { - Rect rt = GUILayoutUtility.GetRect(content, labelStyle); - if (Event.current.type == EventType.Repaint && rt.xMax >= xMax) - break; - GUI.Label(rt, content, labelStyle); - if (rt.xMax <= xMax && evt.type == EventType.MouseDown && rt.Contains(evt.mousePosition) && evt.button == 0 && GUI.enabled) - { - evt.Use(); - rt.x = xMax; - PopupWindow.Show(rt, new PopupList(m_AssetLabels, content.text), null, ShowMode.PopupMenuWithKeyboardFocus); - } - } - } - - private void GetLabelsForAssets(Object[] assets, out List all, out List partial) - { - all = new List(); - partial = new List(); - - Dictionary labelAssetCount = new Dictionary(); - foreach (Object asset in assets) - { - string[] currentLabels = AssetDatabase.GetLabels(asset); - foreach (string label in currentLabels) - { - labelAssetCount[label] = labelAssetCount.ContainsKey(label) ? labelAssetCount[label] + 1 : 1; - } - } - - foreach (KeyValuePair entry in labelAssetCount) - { - var list = (entry.Value == assets.Length) ? all : partial; - list.Add(entry.Key); - } - } - } -} diff --git a/Editor/Mono/Inspector/LayoutDropdownWindow.cs b/Editor/Mono/Inspector/LayoutDropdownWindow.cs deleted file mode 100644 index 67787fb7c9..0000000000 --- a/Editor/Mono/Inspector/LayoutDropdownWindow.cs +++ /dev/null @@ -1,564 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class LayoutDropdownWindow : PopupWindowContent - { - class Styles - { - public Color tableHeaderColor; - public Color tableLineColor; - public Color parentColor; - public Color selfColor; - public Color simpleAnchorColor; - public Color stretchAnchorColor; - public Color anchorCornerColor; - public Color pivotColor; - - public GUIStyle frame; - public GUIStyle label = new GUIStyle(EditorStyles.miniLabel); - - public Styles() - { - frame = new GUIStyle(); - Texture2D tex = new Texture2D(4, 4); - tex.SetPixels(new Color[] { - Color.white, Color.white, Color.white, Color.white, - Color.white, Color.clear, Color.clear, Color.white, - Color.white, Color.clear, Color.clear, Color.white, - Color.white, Color.white, Color.white, Color.white - }); - tex.filterMode = FilterMode.Point; - tex.Apply(); - tex.hideFlags = HideFlags.HideAndDontSave; - frame.normal.background = tex; - frame.border = new RectOffset(2, 2, 2, 2); - - label.alignment = TextAnchor.LowerCenter; - - if (EditorGUIUtility.isProSkin) - { - tableHeaderColor = new Color(0.18f, 0.18f, 0.18f, 1); - tableLineColor = new Color(1, 1, 1, 0.3f); - parentColor = new Color(0.4f, 0.4f, 0.4f, 1); - selfColor = new Color(0.6f, 0.6f, 0.6f, 1); - simpleAnchorColor = new Color(0.7f, 0.3f, 0.3f, 1); - stretchAnchorColor = new Color(0.0f, 0.6f, 0.8f, 1); - anchorCornerColor = new Color(0.8f, 0.6f, 0.0f, 1); - pivotColor = new Color(0.0f, 0.6f, 0.8f, 1); - } - else - { - tableHeaderColor = new Color(0.8f, 0.8f, 0.8f, 1); - tableLineColor = new Color(0, 0, 0, 0.5f); - parentColor = new Color(0.55f, 0.55f, 0.55f, 1); - selfColor = new Color(0.2f, 0.2f, 0.2f, 1); - simpleAnchorColor = new Color(0.8f, 0.3f, 0.3f, 1); - stretchAnchorColor = new Color(0.2f, 0.5f, 0.9f, 1); - anchorCornerColor = new Color(0.6f, 0.4f, 0.0f, 1); - pivotColor = new Color(0.2f, 0.5f, 0.9f, 1); - } - } - } - static Styles s_Styles; - - SerializedProperty m_AnchorMin; - SerializedProperty m_AnchorMax; - - Vector2[,] m_InitValues; - - const int kTopPartHeight = 38; - static float[] kPivotsForModes = new float[] { 0, 0.5f, 1, 0.5f, 0.5f }; // Only for actual modes, not for Undefined. - static string[] kHLabels = new string[] { "custom", "left", "center", "right", "stretch", "%" }; - static string[] kVLabels = new string[] { "custom", "top", "middle", "bottom", "stretch", "%" }; - - public enum LayoutMode { Undefined = -1, Min = 0, Middle = 1, Max = 2, Stretch = 3 } - - public LayoutDropdownWindow(SerializedObject so) - { - m_AnchorMin = so.FindProperty("m_AnchorMin"); - m_AnchorMax = so.FindProperty("m_AnchorMax"); - - m_InitValues = new Vector2[so.targetObjects.Length, 4]; - for (int i = 0; i < so.targetObjects.Length; i++) - { - RectTransform gui = so.targetObjects[i] as RectTransform; - m_InitValues[i, 0] = gui.anchorMin; - m_InitValues[i, 1] = gui.anchorMax; - m_InitValues[i, 2] = gui.anchoredPosition; - m_InitValues[i, 3] = gui.sizeDelta; - } - } - - public override void OnOpen() - { - EditorApplication.modifierKeysChanged += editorWindow.Repaint; - } - - public override void OnClose() - { - EditorApplication.modifierKeysChanged -= editorWindow.Repaint; - } - - public override Vector2 GetWindowSize() - { - return new Vector2(262, 262 + kTopPartHeight); - } - - public override void OnGUI(Rect rect) - { - if (s_Styles == null) - s_Styles = new Styles(); - - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Return) - editorWindow.Close(); - - GUI.Label(new Rect(rect.x + 5, rect.y + 3, rect.width - 10, 16), EditorGUIUtility.TrTextContent("Anchor Presets"), EditorStyles.boldLabel); - 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); - - Color oldColor = GUI.color; - GUI.color = s_Styles.tableLineColor * oldColor; - GUI.DrawTexture(new Rect(0, kTopPartHeight - 1, 400, 1), EditorGUIUtility.whiteTexture); - GUI.color = oldColor; - - GUI.BeginGroup(new Rect(rect.x, rect.y + kTopPartHeight, rect.width, rect.height - kTopPartHeight)); - TableGUI(rect); - GUI.EndGroup(); - } - - static LayoutMode SwappedVMode(LayoutMode vMode) - { - if (vMode == LayoutMode.Min) - return LayoutMode.Max; - else if (vMode == LayoutMode.Max) - return LayoutMode.Min; - return vMode; - } - - internal static void DrawLayoutModeHeadersOutsideRect(Rect rect, - SerializedProperty anchorMin, - SerializedProperty anchorMax, - SerializedProperty position, - SerializedProperty sizeDelta) - { - LayoutMode hMode = GetLayoutModeForAxis(anchorMin, anchorMax, 0); - LayoutMode vMode = GetLayoutModeForAxis(anchorMin, anchorMax, 1); - vMode = SwappedVMode(vMode); - DrawLayoutModeHeaderOutsideRect(rect, 0, hMode); - DrawLayoutModeHeaderOutsideRect(rect, 1, vMode); - } - - internal static void DrawLayoutModeHeaderOutsideRect(Rect position, int axis, LayoutMode mode) - { - Rect headerRect = new Rect(position.x, position.y - 16, position.width, 16); - - Matrix4x4 normalMatrix = GUI.matrix; - if (axis == 1) - GUIUtility.RotateAroundPivot(-90, position.center); - - int index = (int)(mode) + 1; - GUI.Label(headerRect, axis == 0 ? kHLabels[index] : kVLabels[index], s_Styles.label); - - GUI.matrix = normalMatrix; - } - - void TableGUI(Rect rect) - { - int padding = 6; - int size = 31 + padding * 2; - int spacing = 0; - int[] groupings = new int[] { 15, 30, 30, 30, 45, 45 }; - - Color oldColor = GUI.color; - - int headerW = 62; - GUI.color = s_Styles.tableHeaderColor * oldColor; - GUI.DrawTexture(new Rect(0, 0, 400, headerW), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(0, 0, headerW, 400), EditorGUIUtility.whiteTexture); - GUI.color = s_Styles.tableLineColor * oldColor; - GUI.DrawTexture(new Rect(0, headerW, 400, 1), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(headerW, 0, 1, 400), EditorGUIUtility.whiteTexture); - GUI.color = oldColor; - - LayoutMode hMode = GetLayoutModeForAxis(m_AnchorMin, m_AnchorMax, 0); - LayoutMode vMode = GetLayoutModeForAxis(m_AnchorMin, m_AnchorMax, 1); - vMode = SwappedVMode(vMode); - - bool doPivot = Event.current.shift; - bool doPosition = Event.current.alt; - - int number = 5; - - for (int i = 0; i < number; i++) - { - LayoutMode cellHMode = (LayoutMode)(i - 1); - - for (int j = 0; j < number; j++) - { - LayoutMode cellVMode = (LayoutMode)(j - 1); - - if (i == 0 && j == 0 && vMode >= 0 && hMode >= 0) - continue; - - Rect position = new Rect( - i * (size + spacing) + groupings[i], - j * (size + spacing) + groupings[j], - size, - size); - - if (j == 0 && !(i == 0 && hMode != LayoutMode.Undefined)) - DrawLayoutModeHeaderOutsideRect(position, 0, cellHMode); - if (i == 0 && !(j == 0 && vMode != LayoutMode.Undefined)) - DrawLayoutModeHeaderOutsideRect(position, 1, cellVMode); - - bool selected = (cellHMode == hMode) && (cellVMode == vMode); - - bool selectedHeader = false; - if (i == 0 && cellVMode == vMode) - selectedHeader = true; - if (j == 0 && cellHMode == hMode) - selectedHeader = true; - - if (Event.current.type == EventType.Repaint) - { - if (selected) - { - GUI.color = Color.white * oldColor; - s_Styles.frame.Draw(position, false, false, false, false); - } - else if (selectedHeader) - { - GUI.color = new Color(1, 1, 1, 0.7f) * oldColor; - s_Styles.frame.Draw(position, false, false, false, false); - } - } - - DrawLayoutMode( - new Rect(position.x + padding, position.y + padding, position.width - padding * 2, position.height - padding * 2), - cellHMode, cellVMode, - doPivot, doPosition); - - int clickCount = Event.current.clickCount; - if (GUI.Button(position, GUIContent.none, GUIStyle.none)) - { - SetLayoutModeForAxis(m_AnchorMin, 0, cellHMode, doPivot, doPosition, m_InitValues); - SetLayoutModeForAxis(m_AnchorMin, 1, SwappedVMode(cellVMode), doPivot, doPosition, m_InitValues); - if (clickCount == 2) - editorWindow.Close(); - else - editorWindow.Repaint(); - } - } - } - GUI.color = oldColor; - } - - static LayoutMode GetLayoutModeForAxis( - SerializedProperty anchorMin, - SerializedProperty anchorMax, - int axis) - { - if (anchorMin.vector2Value[axis] == 0 && anchorMax.vector2Value[axis] == 0) - return LayoutMode.Min; - if (anchorMin.vector2Value[axis] == 0.5f && anchorMax.vector2Value[axis] == 0.5f) - return LayoutMode.Middle; - if (anchorMin.vector2Value[axis] == 1 && anchorMax.vector2Value[axis] == 1) - return LayoutMode.Max; - if (anchorMin.vector2Value[axis] == 0 && anchorMax.vector2Value[axis] == 1) - return LayoutMode.Stretch; - return LayoutMode.Undefined; - } - - static void SetLayoutModeForAxis( - SerializedProperty anchorMin, - int axis, LayoutMode layoutMode, - bool doPivot, bool doPosition, Vector2[,] defaultValues) - { - anchorMin.serializedObject.ApplyModifiedProperties(); - - for (int i = 0; i < anchorMin.serializedObject.targetObjects.Length; i++) - { - RectTransform gui = anchorMin.serializedObject.targetObjects[i] as RectTransform; - Undo.RecordObject(gui, "Change Rectangle Anchors"); - - if (doPosition) - { - if (defaultValues != null && defaultValues.Length > i) - { - Vector2 temp; - - temp = gui.anchorMin; - temp[axis] = defaultValues[i, 0][axis]; - gui.anchorMin = temp; - - temp = gui.anchorMax; - temp[axis] = defaultValues[i, 1][axis]; - gui.anchorMax = temp; - - temp = gui.anchoredPosition; - temp[axis] = defaultValues[i, 2][axis]; - gui.anchoredPosition = temp; - - temp = gui.sizeDelta; - temp[axis] = defaultValues[i, 3][axis]; - gui.sizeDelta = temp; - } - } - - if (doPivot && layoutMode != LayoutMode.Undefined) - { - RectTransformEditor.SetPivotSmart(gui, kPivotsForModes[(int)layoutMode], axis, true, true); - } - - Vector2 refPosition = Vector2.zero; - switch (layoutMode) - { - case LayoutMode.Min: - RectTransformEditor.SetAnchorSmart(gui, 0, axis, false, true, true); - RectTransformEditor.SetAnchorSmart(gui, 0, axis, true, true, true); - refPosition = gui.offsetMin; - EditorUtility.SetDirty(gui); - break; - case LayoutMode.Middle: - RectTransformEditor.SetAnchorSmart(gui, 0.5f, axis, false, true, true); - RectTransformEditor.SetAnchorSmart(gui, 0.5f, axis, true, true, true); - refPosition = (gui.offsetMin + gui.offsetMax) * 0.5f; - EditorUtility.SetDirty(gui); - break; - case LayoutMode.Max: - RectTransformEditor.SetAnchorSmart(gui, 1, axis, false, true, true); - RectTransformEditor.SetAnchorSmart(gui, 1, axis, true, true, true); - refPosition = gui.offsetMax; - EditorUtility.SetDirty(gui); - break; - case LayoutMode.Stretch: - RectTransformEditor.SetAnchorSmart(gui, 0, axis, false, true, true); - RectTransformEditor.SetAnchorSmart(gui, 1, axis, true, true, true); - refPosition = (gui.offsetMin + gui.offsetMax) * 0.5f; - EditorUtility.SetDirty(gui); - break; - } - - if (doPosition) - { - // Handle position - Vector2 rectPosition = gui.anchoredPosition; - rectPosition[axis] -= refPosition[axis]; - gui.anchoredPosition = rectPosition; - - // Handle sizeDelta - if (layoutMode == LayoutMode.Stretch) - { - Vector2 rectSizeDelta = gui.sizeDelta; - rectSizeDelta[axis] = 0; - gui.sizeDelta = rectSizeDelta; - } - } - } - anchorMin.serializedObject.Update(); - } - - internal static void DrawLayoutMode(Rect rect, - SerializedProperty anchorMin, - SerializedProperty anchorMax, - SerializedProperty position, - SerializedProperty sizeDelta) - { - LayoutMode hMode = GetLayoutModeForAxis(anchorMin, anchorMax, 0); - LayoutMode vMode = GetLayoutModeForAxis(anchorMin, anchorMax, 1); - vMode = SwappedVMode(vMode); - DrawLayoutMode(rect, hMode, vMode); - } - - internal static void DrawLayoutMode(Rect position, LayoutMode hMode, LayoutMode vMode) - { - DrawLayoutMode(position, hMode, vMode, false, false); - } - - internal static void DrawLayoutMode(Rect position, LayoutMode hMode, LayoutMode vMode, bool doPivot) - { - DrawLayoutMode(position, hMode, vMode, doPivot, false); - } - - internal static void DrawLayoutMode(Rect position, LayoutMode hMode, LayoutMode vMode, bool doPivot, bool doPosition) - { - if (s_Styles == null) - s_Styles = new Styles(); - - Color oldColor = GUI.color; - - // Make parent size the largest possible square, but enforce it's an uneven number. - int parentWidth = (int)Mathf.Min(position.width, position.height); - if (parentWidth % 2 == 0) - parentWidth--; - - int selfWidth = parentWidth / 2; - if (selfWidth % 2 == 0) - selfWidth++; - - Vector2 parentSize = parentWidth * Vector2.one; - Vector2 selfSize = selfWidth * Vector2.one; - Vector2 padding = (position.size - parentSize) / 2; - padding.x = Mathf.Floor(padding.x); - padding.y = Mathf.Floor(padding.y); - Vector2 padding2 = (position.size - selfSize) / 2; - padding2.x = Mathf.Floor(padding2.x); - padding2.y = Mathf.Floor(padding2.y); - - Rect outer = new Rect(position.x + padding.x, position.y + padding.y, parentSize.x, parentSize.y); - Rect inner = new Rect(position.x + padding2.x, position.y + padding2.y, selfSize.x, selfSize.y); - if (doPosition) - { - for (int axis = 0; axis < 2; axis++) - { - LayoutMode mode = (axis == 0 ? hMode : vMode); - - if (mode == LayoutMode.Min) - { - Vector2 center = inner.center; - center[axis] += outer.min[axis] - inner.min[axis]; - inner.center = center; - } - if (mode == LayoutMode.Middle) - { - // TODO - } - if (mode == LayoutMode.Max) - { - Vector2 center = inner.center; - center[axis] += outer.max[axis] - inner.max[axis]; - inner.center = center; - } - if (mode == LayoutMode.Stretch) - { - Vector2 innerMin = inner.min; - Vector2 innerMax = inner.max; - innerMin[axis] = outer.min[axis]; - innerMax[axis] = outer.max[axis]; - inner.min = innerMin; - inner.max = innerMax; - } - } - } - - Rect anchor = new Rect(); - Vector2 min = Vector2.zero; - Vector2 max = Vector2.zero; - for (int axis = 0; axis < 2; axis++) - { - LayoutMode mode = (axis == 0 ? hMode : vMode); - - if (mode == LayoutMode.Min) - { - min[axis] = outer.min[axis] + 0.5f; - max[axis] = outer.min[axis] + 0.5f; - } - if (mode == LayoutMode.Middle) - { - min[axis] = outer.center[axis]; - max[axis] = outer.center[axis]; - } - if (mode == LayoutMode.Max) - { - min[axis] = outer.max[axis] - 0.5f; - max[axis] = outer.max[axis] - 0.5f; - } - if (mode == LayoutMode.Stretch) - { - min[axis] = outer.min[axis] + 0.5f; - max[axis] = outer.max[axis] - 0.5f; - } - } - anchor.min = min; - anchor.max = max; - - // Draw parent rect - if (Event.current.type == EventType.Repaint) - { - GUI.color = s_Styles.parentColor * oldColor; - s_Styles.frame.Draw(outer, false, false, false, false); - } - - // Draw anchor lines - if (hMode != LayoutMode.Undefined && hMode != LayoutMode.Stretch) - { - GUI.color = s_Styles.simpleAnchorColor * oldColor; - GUI.DrawTexture(new Rect(anchor.xMin - 0.5f, outer.y + 1, 1, outer.height - 2), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(anchor.xMax - 0.5f, outer.y + 1, 1, outer.height - 2), EditorGUIUtility.whiteTexture); - } - if (vMode != LayoutMode.Undefined && vMode != LayoutMode.Stretch) - { - GUI.color = s_Styles.simpleAnchorColor * oldColor; - GUI.DrawTexture(new Rect(outer.x + 1, anchor.yMin - 0.5f, outer.width - 2, 1), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(outer.x + 1, anchor.yMax - 0.5f, outer.width - 2, 1), EditorGUIUtility.whiteTexture); - } - - // Draw stretch mode arrows - if (hMode == LayoutMode.Stretch) - { - GUI.color = s_Styles.stretchAnchorColor * oldColor; - DrawArrow(new Rect(inner.x + 1, inner.center.y - 0.5f, inner.width - 2, 1)); - } - if (vMode == LayoutMode.Stretch) - { - GUI.color = s_Styles.stretchAnchorColor * oldColor; - DrawArrow(new Rect(inner.center.x - 0.5f, inner.y + 1, 1, inner.height - 2)); - } - - // Draw self rect - if (Event.current.type == EventType.Repaint) - { - GUI.color = s_Styles.selfColor * oldColor; - s_Styles.frame.Draw(inner, false, false, false, false); - } - - // Draw pivot - if (doPivot && hMode != LayoutMode.Undefined && vMode != LayoutMode.Undefined) - { - Vector2 pivot = new Vector2( - Mathf.Lerp(inner.xMin + 0.5f, inner.xMax - 0.5f, kPivotsForModes[(int)hMode]), - Mathf.Lerp(inner.yMin + 0.5f, inner.yMax - 0.5f, kPivotsForModes[(int)vMode]) - ); - - GUI.color = s_Styles.pivotColor * oldColor; - GUI.DrawTexture(new Rect(pivot.x - 2.5f, pivot.y - 1.5f, 5, 3), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(pivot.x - 1.5f, pivot.y - 2.5f, 3, 5), EditorGUIUtility.whiteTexture); - } - - // Draw anchor corners - if (hMode != LayoutMode.Undefined && vMode != LayoutMode.Undefined) - { - GUI.color = s_Styles.anchorCornerColor * oldColor; - GUI.DrawTexture(new Rect(anchor.xMin - 1.5f, anchor.yMin - 1.5f, 2, 2), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(anchor.xMax - 0.5f, anchor.yMin - 1.5f, 2, 2), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(anchor.xMin - 1.5f, anchor.yMax - 0.5f, 2, 2), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(anchor.xMax - 0.5f, anchor.yMax - 0.5f, 2, 2), EditorGUIUtility.whiteTexture); - } - - GUI.color = oldColor; - } - - static void DrawArrow(Rect lineRect) - { - GUI.DrawTexture(lineRect, EditorGUIUtility.whiteTexture); - if (lineRect.width == 1) - { - GUI.DrawTexture(new Rect(lineRect.x - 1, lineRect.y + 1, 3, 1), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(lineRect.x - 2, lineRect.y + 2, 5, 1), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(lineRect.x - 1, lineRect.yMax - 2, 3, 1), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(lineRect.x - 2, lineRect.yMax - 3, 5, 1), EditorGUIUtility.whiteTexture); - } - else - { - GUI.DrawTexture(new Rect(lineRect.x + 1, lineRect.y - 1, 1, 3), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(lineRect.x + 2, lineRect.y - 2, 1, 5), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(lineRect.xMax - 2, lineRect.y - 1, 1, 3), EditorGUIUtility.whiteTexture); - GUI.DrawTexture(new Rect(lineRect.xMax - 3, lineRect.y - 2, 1, 5), EditorGUIUtility.whiteTexture); - } - } - } -} diff --git a/Editor/Mono/Inspector/LegacyIlluminShaderGUI.cs b/Editor/Mono/Inspector/LegacyIlluminShaderGUI.cs deleted file mode 100644 index 0bdb9e2700..0000000000 --- a/Editor/Mono/Inspector/LegacyIlluminShaderGUI.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal class LegacyIlluminShaderGUI : ShaderGUI - { - public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) - { - base.OnGUI(materialEditor, props); - - materialEditor.LightmapEmissionProperty(0); - - // We assume that illumin shader always has emission - foreach (Material material in materialEditor.targets) - material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/Inspector/LightEditor.cs b/Editor/Mono/Inspector/LightEditor.cs deleted file mode 100644 index 6a858c23dd..0000000000 --- a/Editor/Mono/Inspector/LightEditor.cs +++ /dev/null @@ -1,668 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEngine; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - [CustomEditor(typeof(Light))] - [CanEditMultipleObjects] - public class LightEditor : Editor - { - public sealed class Settings - { - private SerializedObject m_SerializedObject; - - public SerializedProperty lightType { get; private set; } - public SerializedProperty range { get; private set; } - public SerializedProperty spotAngle { get; private set; } - public SerializedProperty cookieSize { get; private set; } - public SerializedProperty color { get; private set; } - public SerializedProperty intensity { get; private set; } - public SerializedProperty bounceIntensity { get; private set; } - public SerializedProperty colorTemperature { get; private set; } - public SerializedProperty useColorTemperature { get; private set; } - public SerializedProperty cookieProp { get; private set; } - public SerializedProperty shadowsType { get; private set; } - public SerializedProperty shadowsStrength { get; private set; } - public SerializedProperty shadowsResolution { get; private set; } - public SerializedProperty shadowsBias { get; private set; } - public SerializedProperty shadowsNormalBias { get; private set; } - public SerializedProperty shadowsNearPlane { get; private set; } - public SerializedProperty halo { get; private set; } - public SerializedProperty flare { get; private set; } - public SerializedProperty renderMode { get; private set; } - public SerializedProperty cullingMask { get; private set; } - public SerializedProperty lightmapping { get; private set; } - public SerializedProperty areaSizeX { get; private set; } - public SerializedProperty areaSizeY { get; private set; } - public SerializedProperty bakedShadowRadiusProp { get; private set; } - public SerializedProperty bakedShadowAngleProp { get; private set; } - - - Texture2D m_KelvinGradientTexture; - const float kMinKelvin = 1000f; - const float kMaxKelvin = 20000f; - const float kSliderPower = 2f; - - public Settings(SerializedObject so) - { - m_SerializedObject = so; - } - - class Styles - { - public readonly GUIContent Type = EditorGUIUtility.TrTextContent("Type", "Specifies the current type of light. Possible types are Directional, Spot, Point, and Area lights."); - public readonly GUIContent Range = EditorGUIUtility.TrTextContent("Range", "Controls how far the light is emitted from the center of the object."); - public readonly GUIContent SpotAngle = EditorGUIUtility.TrTextContent("Spot Angle", "Controls the angle in degrees at the base of a Spot light's cone."); - public readonly GUIContent Color = EditorGUIUtility.TrTextContent("Color", "Controls the color being emitted by the light."); - public readonly GUIContent UseColorTemperature = EditorGUIUtility.TrTextContent("Use color temperature mode", "Choose between RGB and temperature mode for light's color."); - public readonly GUIContent ColorFilter = EditorGUIUtility.TrTextContent("Filter", "A colored gel can be put in front of the light source to tint the light."); - public 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"); - public readonly GUIContent Intensity = EditorGUIUtility.TrTextContent("Intensity", "Controls the brightness of the light. Light color is multiplied by this value."); - public 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."); - public readonly GUIContent LightBounceIntensity = EditorGUIUtility.TrTextContent("Indirect Multiplier", "Controls the intensity of indirect light being contributed to the scene. A value of 0 will cause Realtime lights to be removed from realtime global illumination and Baked and Mixed lights to no longer emit indirect lighting. Has no effect when both Realtime and Baked Global Illumination are disabled."); - public readonly GUIContent ShadowType = EditorGUIUtility.TrTextContent("Shadow Type", "Specifies whether Hard Shadows, Soft Shadows, or No Shadows will be cast by the light."); - //realtime - public readonly GUIContent ShadowRealtimeSettings = EditorGUIUtility.TrTextContent("Realtime Shadows", "Settings for realtime direct shadows."); - public readonly GUIContent ShadowStrength = EditorGUIUtility.TrTextContent("Strength", "Controls how dark the shadows cast by the light will be."); - public 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."); - public 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."); - public 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."); - public 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."); - //baked - public 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."); - public readonly GUIContent BakedShadowAngle = EditorGUIUtility.TrTextContent("Baked Shadow Angle", "Controls the amount of artificial softening applied to the edges of shadows cast by directional lights."); - - public readonly GUIContent Cookie = EditorGUIUtility.TrTextContent("Cookie", "Specifies the Texture mask to cast shadows, create silhouettes, or patterned illumination for the light."); - public readonly GUIContent CookieSize = EditorGUIUtility.TrTextContent("Cookie Size", "Controls the size of the cookie mask currently assigned to the light."); - public readonly GUIContent DrawHalo = EditorGUIUtility.TrTextContent("Draw Halo", "When enabled, draws a spherical halo of light with a radius equal to the lights range value."); - public readonly GUIContent Flare = EditorGUIUtility.TrTextContent("Flare", "Specifies the flare object to be used by the light to render lens flares in the scene."); - public 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"); - public 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."); - - public readonly GUIContent AreaWidth = EditorGUIUtility.TrTextContent("Width", "Controls the width in units of the area light."); - public readonly GUIContent AreaHeight = EditorGUIUtility.TrTextContent("Height", "Controls the height in units of the area light."); - - public readonly GUIContent BakingWarning = EditorGUIUtility.TrTextContent("Light mode is currently overridden to Realtime mode. Enable Baked Global Illumination to use Mixed or Baked light modes."); - public readonly GUIContent IndirectBounceShadowWarning = EditorGUIUtility.TrTextContent("Realtime indirect bounce shadowing is not supported for Spot and Point lights."); - public readonly GUIContent CookieWarning = EditorGUIUtility.TrTextContent("Cookie textures for spot lights should be set to clamp, not repeat, to avoid artifacts."); - - public readonly GUIContent[] LightmapBakeTypeTitles = { EditorGUIUtility.TrTextContent("Realtime"), EditorGUIUtility.TrTextContent("Mixed"), EditorGUIUtility.TrTextContent("Baked") }; - public readonly int[] LightmapBakeTypeValues = { (int)LightmapBakeType.Realtime, (int)LightmapBakeType.Mixed, (int)LightmapBakeType.Baked }; - } - - static Styles s_Styles; - - public bool isRealtime { get { return lightmapping.intValue == 4; } } - public bool isCompletelyBaked { get { return lightmapping.intValue == 2; } } - public bool isBakedOrMixed { get { return !isRealtime; } } - public Texture cookie { get { return cookieProp.objectReferenceValue as Texture; } } - - internal bool typeIsSame { get { return !lightType.hasMultipleDifferentValues; } } - internal bool shadowTypeIsSame { get { return !shadowsType.hasMultipleDifferentValues; } } - private bool lightmappingTypeIsSame { get { return !lightmapping.hasMultipleDifferentValues; } } - public Light light { get { return m_SerializedObject.targetObject as Light; } } - - internal bool bounceWarningValue - { - get - { - return typeIsSame && (light.type == LightType.Point || light.type == LightType.Spot) && - lightmappingTypeIsSame && isRealtime && !bounceIntensity.hasMultipleDifferentValues && bounceIntensity.floatValue > 0.0F; - } - } - internal bool bakingWarningValue { get { return !Lightmapping.bakedGI && lightmappingTypeIsSame && isBakedOrMixed; } } - - internal bool cookieWarningValue - { - get - { - return typeIsSame && light.type == LightType.Spot && - !cookieProp.hasMultipleDifferentValues && cookie && cookie.wrapMode != TextureWrapMode.Clamp; - } - } - - public void OnEnable() - { - lightType = m_SerializedObject.FindProperty("m_Type"); - range = m_SerializedObject.FindProperty("m_Range"); - spotAngle = m_SerializedObject.FindProperty("m_SpotAngle"); - cookieSize = m_SerializedObject.FindProperty("m_CookieSize"); - color = m_SerializedObject.FindProperty("m_Color"); - intensity = m_SerializedObject.FindProperty("m_Intensity"); - bounceIntensity = m_SerializedObject.FindProperty("m_BounceIntensity"); - colorTemperature = m_SerializedObject.FindProperty("m_ColorTemperature"); - useColorTemperature = m_SerializedObject.FindProperty("m_UseColorTemperature"); - cookieProp = m_SerializedObject.FindProperty("m_Cookie"); - shadowsType = m_SerializedObject.FindProperty("m_Shadows.m_Type"); - shadowsStrength = m_SerializedObject.FindProperty("m_Shadows.m_Strength"); - shadowsResolution = m_SerializedObject.FindProperty("m_Shadows.m_Resolution"); - shadowsBias = m_SerializedObject.FindProperty("m_Shadows.m_Bias"); - shadowsNormalBias = m_SerializedObject.FindProperty("m_Shadows.m_NormalBias"); - shadowsNearPlane = m_SerializedObject.FindProperty("m_Shadows.m_NearPlane"); - halo = m_SerializedObject.FindProperty("m_DrawHalo"); - flare = m_SerializedObject.FindProperty("m_Flare"); - renderMode = m_SerializedObject.FindProperty("m_RenderMode"); - cullingMask = m_SerializedObject.FindProperty("m_CullingMask"); - lightmapping = m_SerializedObject.FindProperty("m_Lightmapping"); - areaSizeX = m_SerializedObject.FindProperty("m_AreaSize.x"); - areaSizeY = m_SerializedObject.FindProperty("m_AreaSize.y"); - bakedShadowRadiusProp = m_SerializedObject.FindProperty("m_ShadowRadius"); - bakedShadowAngleProp = m_SerializedObject.FindProperty("m_ShadowAngle"); - - if (m_KelvinGradientTexture == null) - m_KelvinGradientTexture = CreateKelvinGradientTexture("KelvinGradientTexture", 300, 16, kMinKelvin, kMaxKelvin); - } - - public void OnDestroy() - { - if (m_KelvinGradientTexture != null) - DestroyImmediate(m_KelvinGradientTexture); - } - - static Texture2D CreateKelvinGradientTexture(string name, int width, int height, float minKelvin, float maxKelvin) - { - var texture = new Texture2D(width, height, TextureFormat.ARGB32, false); - texture.name = name; - texture.hideFlags = HideFlags.HideAndDontSave; - var pixels = new Color32[width * height]; - - float mappedMax = Mathf.Pow(maxKelvin, 1f / kSliderPower); - float mappedMin = Mathf.Pow(minKelvin, 1f / kSliderPower); - - for (int i = 0; i < width; i++) - { - float pixelfrac = i / (float)(width - 1); - float mappedValue = (mappedMax - mappedMin) * pixelfrac + mappedMin; - float kelvin = Mathf.Pow(mappedValue, kSliderPower); - Color kelvinColor = Mathf.CorrelatedColorTemperatureToRGB(kelvin); - for (int j = 0; j < height; j++) - pixels[j * width + i] = kelvinColor.gamma; - } - - texture.SetPixels32(pixels); - texture.wrapMode = TextureWrapMode.Clamp; - texture.Apply(); - return texture; - } - - public void Update() - { - if (s_Styles == null) - s_Styles = new Styles(); - - m_SerializedObject.Update(); - } - - public void DrawLightType() - { - EditorGUILayout.PropertyField(lightType, s_Styles.Type); - } - - public void DrawRange(bool showAreaOptions) - { - // If the light is an area light, the range is determined by other parameters. - // Therefore, disable area light's range for editing, but just update the editor field. - if (showAreaOptions) - { - GUI.enabled = false; - string areaLightToolTip = "For area lights " + range.displayName + " is computed from Width, Height and Intensity"; - GUIContent areaRangeWithToolTip = new GUIContent(range.displayName, areaLightToolTip); - EditorGUILayout.FloatField(areaRangeWithToolTip, light.range); - GUI.enabled = true; - } - else - EditorGUILayout.PropertyField(range, s_Styles.Range); - } - - public void DrawSpotAngle() - { - EditorGUILayout.Slider(spotAngle, 1f, 179f, s_Styles.SpotAngle); - } - - public void DrawArea() - { - EditorGUILayout.PropertyField(areaSizeX, s_Styles.AreaWidth); - EditorGUILayout.PropertyField(areaSizeY, s_Styles.AreaHeight); - } - - public void DrawColor() - { - if (GraphicsSettings.lightsUseLinearIntensity && GraphicsSettings.lightsUseColorTemperature) - { - EditorGUILayout.PropertyField(useColorTemperature, s_Styles.UseColorTemperature); - if (useColorTemperature.boolValue) - { - EditorGUILayout.LabelField(s_Styles.Color); - EditorGUI.indentLevel += 1; - EditorGUILayout.PropertyField(color, s_Styles.ColorFilter); - EditorGUILayout.SliderWithTexture(s_Styles.ColorTemperature, colorTemperature, kMinKelvin, kMaxKelvin, kSliderPower, m_KelvinGradientTexture); - EditorGUI.indentLevel -= 1; - } - else - EditorGUILayout.PropertyField(color, s_Styles.Color); - } - else - EditorGUILayout.PropertyField(color, s_Styles.Color); - } - - public void DrawLightmapping() - { - EditorGUILayout.IntPopup(lightmapping, s_Styles.LightmapBakeTypeTitles, s_Styles.LightmapBakeTypeValues, s_Styles.LightmappingMode); - - // Warning if GI Baking disabled and m_Lightmapping isn't realtime - if (bakingWarningValue) - { - EditorGUILayout.HelpBox(s_Styles.BakingWarning.text, MessageType.Info); - } - } - - public void DrawIntensity() - { - EditorGUILayout.PropertyField(intensity, s_Styles.Intensity); - } - - public void DrawBounceIntensity() - { - EditorGUILayout.PropertyField(bounceIntensity, s_Styles.LightBounceIntensity); - // Indirect shadows warning (Should be removed when we support realtime indirect shadows) - if (bounceWarningValue) - { - EditorGUILayout.HelpBox(s_Styles.IndirectBounceShadowWarning.text, MessageType.Info); - } - } - - public void DrawCookie() - { - EditorGUILayout.PropertyField(cookieProp, s_Styles.Cookie); - - if (cookieWarningValue) - { - // warn on spotlights if the cookie is set to repeat - EditorGUILayout.HelpBox(s_Styles.CookieWarning.text, MessageType.Warning); - } - } - - public void DrawCookieSize() - { - EditorGUILayout.PropertyField(cookieSize, s_Styles.CookieSize); - } - - public void DrawHalo() - { - EditorGUILayout.PropertyField(halo, s_Styles.DrawHalo); - } - - public void DrawFlare() - { - EditorGUILayout.PropertyField(flare, s_Styles.Flare); - } - - public void DrawRenderMode() - { - EditorGUILayout.PropertyField(renderMode, s_Styles.RenderMode); - } - - public void DrawCullingMask() - { - EditorGUILayout.PropertyField(cullingMask, s_Styles.CullingMask); - } - - public void ApplyModifiedProperties() - { - m_SerializedObject.ApplyModifiedProperties(); - } - - public void DrawShadowsType() - { - EditorGUILayout.Space(); - EditorGUILayout.PropertyField(shadowsType, s_Styles.ShadowType); - } - - public void DrawBakedShadowRadius() - { - using (new EditorGUI.DisabledScope(shadowsType.intValue != (int)LightShadows.Soft)) - { - EditorGUILayout.PropertyField(bakedShadowRadiusProp, s_Styles.BakedShadowRadius); - } - } - - public void DrawBakedShadowAngle() - { - using (new EditorGUI.DisabledScope(shadowsType.intValue != (int)LightShadows.Soft)) - { - EditorGUILayout.Slider(bakedShadowAngleProp, 0.0F, 90.0F, s_Styles.BakedShadowAngle); - } - } - - public void DrawRuntimeShadow() - { - EditorGUILayout.LabelField(s_Styles.ShadowRealtimeSettings); - EditorGUI.indentLevel += 1; - EditorGUILayout.Slider(shadowsStrength, 0f, 1f, s_Styles.ShadowStrength); - EditorGUILayout.PropertyField(shadowsResolution, s_Styles.ShadowResolution); - EditorGUILayout.Slider(shadowsBias, 0.0f, 2.0f, s_Styles.ShadowBias); - EditorGUILayout.Slider(shadowsNormalBias, 0.0f, 3.0f, s_Styles.ShadowNormalBias); - - // this min bound should match the calculation in SharedLightData::GetNearPlaneMinBound() - float nearPlaneMinBound = Mathf.Min(0.01f * range.floatValue, 0.1f); - EditorGUILayout.Slider(shadowsNearPlane, nearPlaneMinBound, 10.0f, s_Styles.ShadowNearPlane); - EditorGUI.indentLevel -= 1; - } - } - - private class Style - { - public readonly GUIContent iconRemove = EditorGUIUtility.TrIconContent("Toolbar Minus", "Remove command buffer"); - public 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."); - public readonly GUIStyle invisibleButton = "InvisibleButton"; - } - - private static Style s_Styles; - - private Settings m_Settings; - protected Settings settings - { - get - { - if (m_Settings == null) - m_Settings = new Settings(serializedObject); - return m_Settings; - } - } - - AnimBool m_AnimShowSpotOptions = new AnimBool(); - AnimBool m_AnimShowPointOptions = new AnimBool(); - AnimBool m_AnimShowDirOptions = new AnimBool(); - AnimBool m_AnimShowAreaOptions = new AnimBool(); - AnimBool m_AnimShowRuntimeOptions = new AnimBool(); - AnimBool m_AnimShowShadowOptions = new AnimBool(); - AnimBool m_AnimBakedShadowAngleOptions = new AnimBool(); - AnimBool m_AnimBakedShadowRadiusOptions = new AnimBool(); - AnimBool m_AnimShowLightBounceIntensity = new AnimBool(); - - private bool m_CommandBuffersShown = true; - - // Should match same colors in GizmoDrawers.cpp! - internal static Color kGizmoLight = new Color(254 / 255f, 253 / 255f, 136 / 255f, 128 / 255f); - internal static Color kGizmoDisabledLight = new Color(135 / 255f, 116 / 255f, 50 / 255f, 128 / 255f); - - private void SetOptions(AnimBool animBool, bool initialize, bool targetValue) - { - if (initialize) - { - animBool.value = targetValue; - animBool.valueChanged.AddListener(Repaint); - } - else - { - animBool.target = targetValue; - } - } - - bool spotOptionsValue { get { return settings.typeIsSame && settings.light.type == LightType.Spot; } } - bool pointOptionsValue { get { return settings.typeIsSame && settings.light.type == LightType.Point; } } - bool dirOptionsValue { get { return settings.typeIsSame && settings.light.type == LightType.Directional; } } - bool areaOptionsValue { get { return settings.typeIsSame && settings.light.type == LightType.Area; } } - bool runtimeOptionsValue { get { return settings.typeIsSame && (settings.light.type != LightType.Area && !settings.isCompletelyBaked); } } - bool bakedShadowRadius { get { return settings.typeIsSame && (settings.light.type == LightType.Point || settings.light.type == LightType.Spot) && settings.isBakedOrMixed; } } - bool bakedShadowAngle { get { return settings.typeIsSame && settings.light.type == LightType.Directional && settings.isBakedOrMixed; } } - bool shadowOptionsValue { get { return settings.shadowTypeIsSame && settings.light.shadows != LightShadows.None; } } - - - private void UpdateShowOptions(bool initialize) - { - SetOptions(m_AnimShowSpotOptions, initialize, spotOptionsValue); - SetOptions(m_AnimShowPointOptions, initialize, pointOptionsValue); - SetOptions(m_AnimShowDirOptions, initialize, dirOptionsValue); - SetOptions(m_AnimShowAreaOptions, initialize, areaOptionsValue); - SetOptions(m_AnimShowShadowOptions, initialize, shadowOptionsValue); - SetOptions(m_AnimShowRuntimeOptions, initialize, runtimeOptionsValue); - SetOptions(m_AnimBakedShadowAngleOptions, initialize, bakedShadowAngle); - SetOptions(m_AnimBakedShadowRadiusOptions, initialize, bakedShadowRadius); - SetOptions(m_AnimShowLightBounceIntensity, initialize, true); - } - - protected virtual void OnEnable() - { - settings.OnEnable(); - - UpdateShowOptions(true); - } - - protected virtual void OnDestroy() - { - if (m_Settings != null) - { - m_Settings.OnDestroy(); - m_Settings = null; - } - } - - private void CommandBufferGUI() - { - // Command buffers are not serialized data, so can't get to them through - // serialized property (hence no multi-edit). - if (targets.Length != 1) - return; - var light = target as Light; - if (light == null) - return; - int count = light.commandBufferCount; - if (count == 0) - return; - - m_CommandBuffersShown = GUILayout.Toggle(m_CommandBuffersShown, GUIContent.Temp(count + " command buffers"), EditorStyles.foldout); - if (!m_CommandBuffersShown) - return; - EditorGUI.indentLevel++; - foreach (LightEvent le in (LightEvent[])System.Enum.GetValues(typeof(LightEvent))) - { - CommandBuffer[] cbs = light.GetCommandBuffers(le); - foreach (CommandBuffer cb in cbs) - { - using (new GUILayout.HorizontalScope()) - { - // row with event & command buffer information label - Rect rowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.miniLabel); - rowRect.xMin += EditorGUI.indent; - Rect minusRect = GetRemoveButtonRect(rowRect); - rowRect.xMax = minusRect.x; - GUI.Label(rowRect, string.Format("{0}: {1} ({2})", le, cb.name, EditorUtility.FormatBytes(cb.sizeInBytes)), EditorStyles.miniLabel); - // and a button to remove it - if (GUI.Button(minusRect, s_Styles.iconRemove, s_Styles.invisibleButton)) - { - light.RemoveCommandBuffer(le, cb); - SceneView.RepaintAll(); - GameView.RepaintAll(); - GUIUtility.ExitGUI(); - } - } - } - } - // "remove all" button - using (new GUILayout.HorizontalScope()) - { - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Remove all", EditorStyles.miniButton)) - { - light.RemoveAllCommandBuffers(); - SceneView.RepaintAll(); - GameView.RepaintAll(); - } - } - EditorGUI.indentLevel--; - } - - static Rect GetRemoveButtonRect(Rect r) - { - var buttonSize = s_Styles.invisibleButton.CalcSize(s_Styles.iconRemove); - return new Rect(r.xMax - buttonSize.x, r.y + (int)(r.height / 2 - buttonSize.y / 2), buttonSize.x, buttonSize.y); - } - - public override void OnInspectorGUI() - { - if (s_Styles == null) - s_Styles = new Style(); - - settings.Update(); - - UpdateShowOptions(false); - - // Light type (shape and usage) - settings.DrawLightType(); - - EditorGUILayout.Space(); - - // When we are switching between two light types that don't show the range (directional and area lights) - // we want the fade group to stay hidden. - //bool keepRangeHidden = m_ShowDirOptions.isAnimating && m_ShowDirOptions.target; - //float fadeRange = keepRangeHidden ? 0.0f : 1.0f - m_ShowDirOptions.faded; - // Light Range - if (EditorGUILayout.BeginFadeGroup(1.0f - m_AnimShowDirOptions.faded)) - settings.DrawRange(m_AnimShowAreaOptions.target); - EditorGUILayout.EndFadeGroup(); - - if (EditorGUILayout.BeginFadeGroup(m_AnimShowSpotOptions.faded)) - settings.DrawSpotAngle(); - EditorGUILayout.EndFadeGroup(); - - // Area width & height - if (EditorGUILayout.BeginFadeGroup(m_AnimShowAreaOptions.faded)) - settings.DrawArea(); - EditorGUILayout.EndFadeGroup(); - - settings.DrawColor(); - - EditorGUILayout.Space(); - - // Baking type - if (EditorGUILayout.BeginFadeGroup(1.0F - m_AnimShowAreaOptions.faded)) - settings.DrawLightmapping(); - EditorGUILayout.EndFadeGroup(); - - settings.DrawIntensity(); - - if (EditorGUILayout.BeginFadeGroup(m_AnimShowLightBounceIntensity.faded)) - settings.DrawBounceIntensity(); - EditorGUILayout.EndFadeGroup(); - - ShadowsGUI(); - - if (EditorGUILayout.BeginFadeGroup(m_AnimShowRuntimeOptions.faded)) - settings.DrawCookie(); - EditorGUILayout.EndFadeGroup(); - - // Cookie size also requires directional light - if (EditorGUILayout.BeginFadeGroup(m_AnimShowRuntimeOptions.faded * m_AnimShowDirOptions.faded)) - settings.DrawCookieSize(); - EditorGUILayout.EndFadeGroup(); - - settings.DrawHalo(); - settings.DrawFlare(); - settings.DrawRenderMode(); - settings.DrawCullingMask(); - - EditorGUILayout.Space(); - if (SceneView.lastActiveSceneView != null && SceneView.lastActiveSceneView.m_SceneLighting == false) - EditorGUILayout.HelpBox(s_Styles.DisabledLightWarning.text, MessageType.Warning); - - CommandBufferGUI(); - - settings.ApplyModifiedProperties(); - serializedObject.ApplyModifiedProperties(); - } - - void ShadowsGUI() - { - //NOTE: FadeGroup's dont support nesting. Thus we just multiply the fade values here. - - // Shadows drop-down. Area lights can only be baked and always have shadows. - float show = 1 - m_AnimShowAreaOptions.faded; - - if (EditorGUILayout.BeginFadeGroup(show)) - settings.DrawShadowsType(); - EditorGUILayout.EndFadeGroup(); - - EditorGUI.indentLevel += 1; - show *= m_AnimShowShadowOptions.faded; - - // Baked Shadow radius - if (EditorGUILayout.BeginFadeGroup(show * m_AnimBakedShadowRadiusOptions.faded)) - settings.DrawBakedShadowRadius(); - EditorGUILayout.EndFadeGroup(); - - // Baked Shadow angle - if (EditorGUILayout.BeginFadeGroup(show * m_AnimBakedShadowAngleOptions.faded)) - settings.DrawBakedShadowAngle(); - EditorGUILayout.EndFadeGroup(); - - // Runtime shadows - shadow strength, resolution, bias - if (EditorGUILayout.BeginFadeGroup(show * m_AnimShowRuntimeOptions.faded)) - settings.DrawRuntimeShadow(); - EditorGUILayout.EndFadeGroup(); - - EditorGUI.indentLevel -= 1; - - EditorGUILayout.Space(); - } - - protected virtual void OnSceneGUI() - { - Light t = target as Light; - - Color temp = Handles.color; - if (t.enabled) - Handles.color = kGizmoLight; - else - Handles.color = kGizmoDisabledLight; - - float thisRange = t.range; - switch (t.type) - { - case LightType.Point: - thisRange = Handles.RadiusHandle(Quaternion.identity, t.transform.position, thisRange, true); - - if (GUI.changed) - { - Undo.RecordObject(t, "Adjust Point Light"); - t.range = thisRange; - } - - break; - - case LightType.Spot: - // Give handles twice the alpha of the lines - Color col = Handles.color; - col.a = Mathf.Clamp01(temp.a * 2); - Handles.color = col; - - Vector2 angleAndRange = new Vector2(t.spotAngle, t.range); - angleAndRange = Handles.ConeHandle(t.transform.rotation, t.transform.position, angleAndRange, 1.0f, 1.0f, true); - if (GUI.changed) - { - Undo.RecordObject(t, "Adjust Spot Light"); - t.spotAngle = angleAndRange.x; - t.range = Mathf.Max(angleAndRange.y, 0.01F); - } - break; - case LightType.Area: - EditorGUI.BeginChangeCheck(); - Vector2 size = Handles.DoRectHandles(t.transform.rotation, t.transform.position, t.areaSize); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(t, "Adjust Area Light"); - t.areaSize = size; - } - break; - default: - break; - } - Handles.color = temp; - } - } -} diff --git a/Editor/Mono/Inspector/LightProbeGroupInspector.cs b/Editor/Mono/Inspector/LightProbeGroupInspector.cs deleted file mode 100644 index e8d9c77d07..0000000000 --- a/Editor/Mono/Inspector/LightProbeGroupInspector.cs +++ /dev/null @@ -1,755 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Xml.Serialization; -using UnityEditorInternal; -using UnityEngine; -using System.Linq; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class LightProbeGroupEditor : IEditablePoint - { - private bool m_Editing; - - private List m_SourcePositions; - private List m_Selection = new List(); - - private LightProbeGroupSelection m_SerializedSelectedProbes; - - private readonly LightProbeGroup m_Group; - private bool m_ShouldRecalculateTetrahedra; - private Vector3 m_LastPosition = Vector3.zero; - private Quaternion m_LastRotation = Quaternion.identity; - private Vector3 m_LastScale = Vector3.one; - private LightProbeGroupInspector m_Inspector; - - public bool drawTetrahedra { get; set; } - - public LightProbeGroupEditor(LightProbeGroup group, LightProbeGroupInspector inspector) - { - m_Group = group; - MarkTetrahedraDirty(); - m_SerializedSelectedProbes = ScriptableObject.CreateInstance(); - m_SerializedSelectedProbes.hideFlags = HideFlags.HideAndDontSave; - m_Inspector = inspector; - drawTetrahedra = true; - } - - public void SetEditing(bool editing) - { - m_Editing = editing; - } - - public void AddProbe(Vector3 position) - { - Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, "Add Probe"); - m_SourcePositions.Add(position); - SelectProbe(m_SourcePositions.Count - 1); - - MarkTetrahedraDirty(); - } - - private void SelectProbe(int i) - { - if (!m_Selection.Contains(i)) - m_Selection.Add(i); - } - - public void SelectAllProbes() - { - DeselectProbes(); - - var count = m_SourcePositions.Count; - for (var i = 0; i < count; i++) - m_Selection.Add(i); - } - - public void DeselectProbes() - { - m_Selection.Clear(); - m_SerializedSelectedProbes.m_Selection = m_Selection; - } - - private IEnumerable SelectedProbePositions() - { - return m_Selection.Select(t => m_SourcePositions[t]).ToList(); - } - - public void DuplicateSelectedProbes() - { - var selectionCount = m_Selection.Count; - if (selectionCount == 0) return; - - Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, "Duplicate Probes"); - - foreach (var position in SelectedProbePositions()) - { - m_SourcePositions.Add(position); - } - - MarkTetrahedraDirty(); - } - - private void CopySelectedProbes() - { - //Convert probes to world position for serialization - var localPositions = SelectedProbePositions(); - - var serializer = new XmlSerializer(typeof(Vector3[])); - var writer = new StringWriter(); - - serializer.Serialize(writer, localPositions.Select(pos => m_Group.transform.TransformPoint(pos)).ToArray()); - writer.Close(); - GUIUtility.systemCopyBuffer = writer.ToString(); - } - - private static bool CanPasteProbes() - { - try - { - var deserializer = new XmlSerializer(typeof(Vector3[])); - var reader = new StringReader(GUIUtility.systemCopyBuffer); - deserializer.Deserialize(reader); - reader.Close(); - return true; - } - catch - { - return false; - } - } - - private bool PasteProbes() - { - //If we can't paste / paste buffer is bad do nothing - try - { - var deserializer = new XmlSerializer(typeof(Vector3[])); - var reader = new StringReader(GUIUtility.systemCopyBuffer); - var pastedProbes = (Vector3[])deserializer.Deserialize(reader); - reader.Close(); - - if (pastedProbes.Length == 0) return false; - - Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, "Paste Probes"); - - var oldLength = m_SourcePositions.Count; - - //Need to convert into local space... - foreach (var position in pastedProbes) - { - m_SourcePositions.Add(m_Group.transform.InverseTransformPoint(position)); - } - - //Change selection to be the newly pasted probes - DeselectProbes(); - for (int i = oldLength; i < oldLength + pastedProbes.Length; i++) - { - SelectProbe(i); - } - MarkTetrahedraDirty(); - - return true; - } - catch - { - return false; - } - } - - public void RemoveSelectedProbes() - { - int selectionCount = m_Selection.Count; - if (selectionCount == 0) - return; - - Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, "Delete Probes"); - - var reverseSortedIndicies = m_Selection.OrderByDescending(x => x); - foreach (var index in reverseSortedIndicies) - { - m_SourcePositions.RemoveAt(index); - } - DeselectProbes(); - MarkTetrahedraDirty(); - } - - public void PullProbePositions() - { - if (m_Group != null && m_SerializedSelectedProbes != null) - { - m_SourcePositions = new List(m_Group.probePositions); - m_Selection = new List(m_SerializedSelectedProbes.m_Selection); - } - } - - public void PushProbePositions() - { - m_Group.probePositions = m_SourcePositions.ToArray(); - m_SerializedSelectedProbes.m_Selection = m_Selection; - } - - private void DrawTetrahedra() - { - if (Event.current.type != EventType.Repaint) - return; - - if (SceneView.lastActiveSceneView) - { - LightProbeVisualization.DrawTetrahedra(m_ShouldRecalculateTetrahedra, - SceneView.lastActiveSceneView.camera.transform.position); - m_ShouldRecalculateTetrahedra = false; - } - } - - public void HandleEditMenuHotKeyCommands() - { - //Handle other events! - if (Event.current.type == EventType.ValidateCommand - || Event.current.type == EventType.ExecuteCommand) - { - bool execute = Event.current.type == EventType.ExecuteCommand; - switch (Event.current.commandName) - { - case EventCommandNames.SoftDelete: - case EventCommandNames.Delete: - if (execute) RemoveSelectedProbes(); - Event.current.Use(); - break; - case EventCommandNames.Duplicate: - if (execute) DuplicateSelectedProbes(); - Event.current.Use(); - break; - case EventCommandNames.SelectAll: - if (execute) - SelectAllProbes(); - Event.current.Use(); - break; - case EventCommandNames.Cut: - if (execute) - { - CopySelectedProbes(); - RemoveSelectedProbes(); - } - Event.current.Use(); - break; - case EventCommandNames.Copy: - if (execute) CopySelectedProbes(); - Event.current.Use(); - break; - } - } - } - - public static void TetrahedralizeSceneProbes(out Vector3[] positions, out int[] indices) - { - var probeGroups = Object.FindObjectsOfType(typeof(LightProbeGroup)) as LightProbeGroup[]; - - if (probeGroups == null) - { - positions = new Vector3[0]; - indices = new int[0]; - return; - } - var probePositions = new List(); - - foreach (var group in probeGroups) - { - var localPositions = group.probePositions; - foreach (var position in localPositions) - { - var wPosition = group.transform.TransformPoint(position); - probePositions.Add(wPosition); - } - } - - if (probePositions.Count == 0) - { - positions = new Vector3[0]; - indices = new int[0]; - return; - } - - Lightmapping.Tetrahedralize(probePositions.ToArray(), out indices, out positions); - } - - public bool OnSceneGUI(Transform transform) - { - if (!m_Group.enabled) - return m_Editing; - - if (Event.current.type == EventType.Layout) - { - //If the group has moved / scaled since last frame need to retetra);) - if (m_LastPosition != m_Group.transform.position - || m_LastRotation != m_Group.transform.rotation - || m_LastScale != m_Group.transform.localScale) - { - MarkTetrahedraDirty(); - } - - m_LastPosition = m_Group.transform.position; - m_LastRotation = m_Group.transform.rotation; - m_LastScale = m_Group.transform.localScale; - } - - //See if we should enter edit mode! - bool firstSelect = false; - if (Event.current.type == EventType.MouseDown && Event.current.button == 0) - { - //We have no probes selected and have clicked the mouse... Did we click a probe - if (SelectedCount == 0) - { - var selected = PointEditor.FindNearest(Event.current.mousePosition, transform, this); - var clickedProbe = selected != -1; - - if (clickedProbe && !m_Editing) - { - m_Inspector.StartEditMode(); - m_Editing = true; - firstSelect = true; - } - } - } - - //Need to cache this as select points will use it! - var mouseUpEvent = Event.current.type == EventType.MouseUp; - - if (m_Editing) - { - if (PointEditor.SelectPoints(this, transform, ref m_Selection, firstSelect)) - { - Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, "Select Probes"); - } - } - - //Special handling for paste (want to be able to paste when not in edit mode!) - - if ((Event.current.type == EventType.ValidateCommand || Event.current.type == EventType.ExecuteCommand) - && Event.current.commandName == EventCommandNames.Paste) - { - if (Event.current.type == EventType.ValidateCommand) - { - if (CanPasteProbes()) - Event.current.Use(); - } - if (Event.current.type == EventType.ExecuteCommand) - { - if (PasteProbes()) - { - Event.current.Use(); - m_Editing = true; - } - } - } - - if (drawTetrahedra) - DrawTetrahedra(); - - PointEditor.Draw(this, transform, m_Selection, true); - - if (!m_Editing) - return m_Editing; - - HandleEditMenuHotKeyCommands(); - - if (m_Editing && PointEditor.MovePoints(this, transform, m_Selection)) - { - Undo.RegisterCompleteObjectUndo(new Object[] { m_Group, m_SerializedSelectedProbes }, "Move Probes"); - if (LightProbeVisualization.dynamicUpdateLightProbes) - MarkTetrahedraDirty(); - } - - if (m_Editing && mouseUpEvent && !LightProbeVisualization.dynamicUpdateLightProbes) - { - MarkTetrahedraDirty(); - } - - return m_Editing; - } - - public void MarkTetrahedraDirty() - { - m_ShouldRecalculateTetrahedra = true; - } - - public Bounds selectedProbeBounds - { - get - { - List selectedPoints = new List(); - foreach (var idx in m_Selection) - selectedPoints.Add(m_SourcePositions[(int)idx]); - return GetBounds(selectedPoints); - } - } - - public Bounds bounds - { - get { return GetBounds(m_SourcePositions); } - } - - private Bounds GetBounds(List positions) - { - if (positions.Count == 0) - return new Bounds(); - - if (positions.Count == 1) - return new Bounds(m_Group.transform.TransformPoint(positions[0]), new Vector3(1f, 1f, 1f)); - - return GeometryUtility.CalculateBounds(positions.ToArray(), m_Group.transform.localToWorldMatrix); - } - - /// Get the world-space position of a specific point - public Vector3 GetPosition(int idx) - { - return m_SourcePositions[idx]; - } - - public Vector3 GetWorldPosition(int idx) - { - return m_Group.transform.TransformPoint(m_SourcePositions[idx]); - } - - public void SetPosition(int idx, Vector3 position) - { - if (m_SourcePositions[idx] == position) - return; - - m_SourcePositions[idx] = position; - } - - private static readonly Color kCloudColor = new Color(200f / 255f, 200f / 255f, 20f / 255f, 0.85f); - private static readonly Color kSelectedCloudColor = new Color(.3f, .6f, 1, 1); - - public Color GetDefaultColor() - { - return kCloudColor; - } - - public Color GetSelectedColor() - { - return kSelectedCloudColor; - } - - public float GetPointScale() - { - return 10.0f * AnnotationUtility.iconSize; - } - - public Vector3[] GetSelectedPositions() - { - var selectedCount = SelectedCount; - var result = new Vector3[selectedCount]; - for (int i = 0; i < selectedCount; i++) - { - result[i] = m_SourcePositions[m_Selection[i]]; - } - return result; - } - - public void UpdateSelectedPosition(int idx, Vector3 position) - { - if (idx > (SelectedCount - 1)) - return; - - m_SourcePositions[m_Selection[idx]] = position; - } - - public IEnumerable GetPositions() - { - return m_SourcePositions; - } - - public Vector3[] GetUnselectedPositions() - { - var totalProbeCount = Count; - var selectedProbeCount = SelectedCount; - - if (selectedProbeCount == totalProbeCount) - { - return new Vector3[0]; - } - else if (selectedProbeCount == 0) - { - return m_SourcePositions.ToArray(); - } - else - { - var selectionList = new bool[totalProbeCount]; - - // Mark everything unselected - for (int i = 0; i < totalProbeCount; i++) - { - selectionList[i] = false; - } - - // Mark selected - for (int i = 0; i < selectedProbeCount; i++) - { - selectionList[m_Selection[i]] = true; - } - - // Get remaining unselected - var result = new Vector3[totalProbeCount - selectedProbeCount]; - var unselectedCount = 0; - for (int i = 0; i < totalProbeCount; i++) - { - if (selectionList[i] == false) - { - result[unselectedCount++] = m_SourcePositions[i]; - } - } - - return result; - } - } - - /// How many points are there in the array. - public int Count { get { return m_SourcePositions.Count; } } - - - /// How many points are selected in the array. - public int SelectedCount { get { return m_Selection.Count; } } - } - - [CustomEditor(typeof(LightProbeGroup))] - class LightProbeGroupInspector : Editor - { - private static class Styles - { - public static readonly GUIContent showWireframe = EditorGUIUtility.TrTextContent("Show Wireframe", "Show the tetrahedron wireframe visualizing the blending between probes."); - public static readonly GUIContent selectedProbePosition = EditorGUIUtility.TrTextContent("Selected Probe Position", "The local position of this probe relative to the parent group."); - public static readonly GUIContent addProbe = EditorGUIUtility.TrTextContent("Add Probe"); - public static readonly GUIContent deleteSelected = EditorGUIUtility.TrTextContent("Delete Selected"); - public static readonly GUIContent selectAll = EditorGUIUtility.TrTextContent("Select All"); - public static readonly GUIContent duplicateSelected = EditorGUIUtility.TrTextContent("Duplicate Selected"); - public static readonly GUIContent editModeButton; - - static Styles() - { - editModeButton = EditorGUIUtility.IconContent("EditCollider"); - } - } - private LightProbeGroupEditor m_Editor; - - public void OnEnable() - { - m_Editor = new LightProbeGroupEditor(target as LightProbeGroup, this); - m_Editor.PullProbePositions(); - m_Editor.DeselectProbes(); - m_Editor.PushProbePositions(); - SceneView.onSceneGUIDelegate += OnSceneGUIDelegate; - Undo.undoRedoPerformed += UndoRedoPerformed; - EditMode.editModeStarted += OnEditModeStarted; - EditMode.editModeEnded += OnEditModeEnded; - } - - private void OnEditModeEnded(IToolModeOwner owner) - { - if (owner == (IToolModeOwner)this) - { - EndEditProbes(); - } - } - - private void OnEditModeStarted(IToolModeOwner owner, EditMode.SceneViewEditMode mode) - { - if (owner == (IToolModeOwner)this && mode == EditMode.SceneViewEditMode.LightProbeGroup) - { - StartEditProbes(); - } - } - - public void StartEditMode() - { - EditMode.ChangeEditMode(EditMode.SceneViewEditMode.LightProbeGroup, m_Editor.bounds, this); - } - - private void StartEditProbes() - { - if (m_EditingProbes) - return; - - m_EditingProbes = true; - m_Editor.SetEditing(true); - Tools.s_Hidden = true; - SceneView.RepaintAll(); - } - - private void EndEditProbes() - { - if (!m_EditingProbes) - return; - - m_Editor.drawTetrahedra = true; - m_Editor.DeselectProbes(); - m_Editor.SetEditing(false); - m_EditingProbes = false; - Tools.s_Hidden = false; - SceneView.RepaintAll(); - } - - public void OnDisable() - { - EndEditProbes(); - Undo.undoRedoPerformed -= UndoRedoPerformed; - SceneView.onSceneGUIDelegate -= OnSceneGUIDelegate; - if (target != null) - { - m_Editor.PushProbePositions(); - m_Editor = null; - } - } - - private void UndoRedoPerformed() - { - // Update the cached probe positions from the ones just restored in the LightProbeGroup - m_Editor.PullProbePositions(); - - m_Editor.MarkTetrahedraDirty(); - } - - private bool m_EditingProbes; - private bool m_ShouldFocus; - public override void OnInspectorGUI() - { - EditorGUI.BeginChangeCheck(); - - m_Editor.PullProbePositions(); - EditMode.DoEditModeInspectorModeButton( - EditMode.SceneViewEditMode.LightProbeGroup, - "Edit Light Probes", - Styles.editModeButton, - this - ); - - GUILayout.Space(3); - EditorGUI.BeginDisabledGroup(EditMode.editMode != EditMode.SceneViewEditMode.LightProbeGroup); - - m_Editor.drawTetrahedra = EditorGUILayout.Toggle(Styles.showWireframe, m_Editor.drawTetrahedra); - - EditorGUI.BeginDisabledGroup(m_Editor.SelectedCount == 0); - Vector3 pos = m_Editor.SelectedCount > 0 ? m_Editor.GetSelectedPositions()[0] : Vector3.zero; - Vector3 newPosition = EditorGUILayout.Vector3Field(Styles.selectedProbePosition, pos); - if (newPosition != pos) - { - Vector3[] selectedPositions = m_Editor.GetSelectedPositions(); - Vector3 delta = newPosition - pos; - for (int i = 0; i < selectedPositions.Length; i++) - m_Editor.UpdateSelectedPosition(i, selectedPositions[i] + delta); - } - EditorGUI.EndDisabledGroup(); - - GUILayout.Space(3); - - GUILayout.BeginHorizontal(); - GUILayout.BeginVertical(); - - if (GUILayout.Button(Styles.addProbe)) - { - var position = Vector3.zero; - if (SceneView.lastActiveSceneView) - { - var probeGroup = target as LightProbeGroup; - if (probeGroup) position = probeGroup.transform.InverseTransformPoint(position); - } - StartEditProbes(); - m_Editor.DeselectProbes(); - m_Editor.AddProbe(position); - } - - if (GUILayout.Button(Styles.deleteSelected)) - { - StartEditProbes(); - m_Editor.RemoveSelectedProbes(); - } - GUILayout.EndVertical(); - GUILayout.BeginVertical(); - - if (GUILayout.Button(Styles.selectAll)) - { - StartEditProbes(); - m_Editor.SelectAllProbes(); - } - - if (GUILayout.Button(Styles.duplicateSelected)) - { - StartEditProbes(); - m_Editor.DuplicateSelectedProbes(); - } - - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - EditorGUI.EndDisabledGroup(); - - m_Editor.HandleEditMenuHotKeyCommands(); - m_Editor.PushProbePositions(); - - if (EditorGUI.EndChangeCheck()) - { - m_Editor.MarkTetrahedraDirty(); - SceneView.RepaintAll(); - } - } - - internal override Bounds GetWorldBoundsOfTarget(Object targetObject) - { - return m_Editor.bounds; - } - - private void InternalOnSceneView() - { - if (!EditorGUIUtility.IsGizmosAllowedForObject(target)) - return; - - if (SceneView.lastActiveSceneView != null) - { - if (m_ShouldFocus) - { - m_ShouldFocus = false; - SceneView.lastActiveSceneView.FrameSelected(); - } - } - - m_Editor.PullProbePositions(); - var lpg = target as LightProbeGroup; - if (lpg != null) - { - if (m_Editor.OnSceneGUI(lpg.transform)) - StartEditProbes(); - else - EndEditProbes(); - } - m_Editor.PushProbePositions(); - } - - public void OnSceneGUI() - { - if (Event.current.type != EventType.Repaint) - InternalOnSceneView(); - } - - public void OnSceneGUIDelegate(SceneView sceneView) - { - if (Event.current.type == EventType.Repaint) - InternalOnSceneView(); - } - - public bool HasFrameBounds() - { - return m_Editor.SelectedCount > 0; - } - - public Bounds OnGetFrameBounds() - { - return m_Editor.selectedProbeBounds; - } - } -} diff --git a/Editor/Mono/Inspector/LightProbeProxyVolumeEditor.cs b/Editor/Mono/Inspector/LightProbeProxyVolumeEditor.cs deleted file mode 100644 index dea9898f48..0000000000 --- a/Editor/Mono/Inspector/LightProbeProxyVolumeEditor.cs +++ /dev/null @@ -1,384 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEditor.AnimatedValues; -using UnityEditor.IMGUI.Controls; -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - [CustomEditor(typeof(LightProbeProxyVolume))] - [CanEditMultipleObjects] - internal class LightProbeProxyVolumeEditor : Editor - { - static LightProbeProxyVolumeEditor s_LastInteractedEditor; - - private SerializedProperty m_ResolutionX; - private SerializedProperty m_ResolutionY; - private SerializedProperty m_ResolutionZ; - private SerializedProperty m_BoundingBoxSize; - private SerializedProperty m_BoundingBoxOrigin; - private SerializedProperty m_BoundingBoxMode; - private SerializedProperty m_ResolutionMode; - private SerializedProperty m_ResolutionProbesPerUnit; - private SerializedProperty m_ProbePositionMode; - private SerializedProperty m_RefreshMode; - - // Should match gizmo color in GizmoDrawers.cpp! - internal static Color kGizmoLightProbeProxyVolumeColor = new Color(0xFF / 255f, 0xE5 / 255f, 0x94 / 255f, 0x80 / 255f); - internal static Color kGizmoLightProbeProxyVolumeHandleColor = new Color(0xFF / 255f, 0xE5 / 255f, 0xAA / 255f, 0xFF / 255f); - - private BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle(); - - private static class Styles - { - static Styles() - { - richTextMiniLabel.richText = true; - } - - public static GUIStyle richTextMiniLabel = new GUIStyle(EditorStyles.miniLabel); - 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."); - public static GUIContent resolutionXText = new GUIContent("X"); - public static GUIContent resolutionYText = new GUIContent("Y"); - public static GUIContent resolutionZText = new GUIContent("Z"); - public static GUIContent sizeText = EditorGUIUtility.TrTextContent("Size"); - public static GUIContent bbSettingsText = EditorGUIUtility.TrTextContent("Bounding Box Settings"); - public static GUIContent originText = EditorGUIUtility.TrTextContent("Origin"); - 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."); - 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."); - 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."); - public static GUIContent refreshModeText = EditorGUIUtility.TrTextContent("Refresh Mode"); - public static GUIContent[] bbMode = (Enum.GetNames(typeof(LightProbeProxyVolume.BoundingBoxMode)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray(); - public static GUIContent[] resMode = (Enum.GetNames(typeof(LightProbeProxyVolume.ResolutionMode)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray(); - public static GUIContent[] probePositionMode = (Enum.GetNames(typeof(LightProbeProxyVolume.ProbePositionMode)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray(); - public static GUIContent[] refreshMode = (Enum.GetNames(typeof(LightProbeProxyVolume.RefreshMode)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray(); - public static GUIContent resProbesPerUnit = EditorGUIUtility.TrTextContent("Density", "Density in probes per world unit."); - 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."); - public static GUIContent noRendererNode = EditorGUIUtility.TrTextContent("The component is unused by this game object because there is no Renderer component attached."); - 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)."); - public static GUIContent componentUnsuportedOnTreesNote = EditorGUIUtility.TrTextContent("Tree rendering doesn't support Light Probe Proxy Volume components."); - - public static int[] volTextureSizesValues = { 1, 2, 4, 8, 16, 32 }; - public static GUIContent[] volTextureSizes = volTextureSizesValues.Select(n => new GUIContent(n.ToString())).ToArray(); - - public static GUIContent[] toolContents = - { - PrimitiveBoundsHandle.editModeButton, - EditorGUIUtility.TrIconContent("MoveTool", "Move the selected objects.") - }; - public static EditMode.SceneViewEditMode[] sceneViewEditModes = new[] - { - EditMode.SceneViewEditMode.LightProbeProxyVolumeBox, - EditMode.SceneViewEditMode.LightProbeProxyVolumeOrigin - }; - - public static string baseSceneEditingToolText = "Light Probe Proxy Volume Scene Editing Mode: "; - public static GUIContent[] toolNames = - { - new GUIContent(baseSceneEditingToolText + "Box Bounds", ""), - new GUIContent(baseSceneEditingToolText + "Box Origin", "") - }; - } - - private bool IsLightProbeVolumeProxyEditMode(EditMode.SceneViewEditMode editMode) - { - return editMode == EditMode.SceneViewEditMode.LightProbeProxyVolumeBox || - editMode == EditMode.SceneViewEditMode.LightProbeProxyVolumeOrigin; - } - - private bool sceneViewEditing - { - get { return IsLightProbeVolumeProxyEditMode(EditMode.editMode) && EditMode.IsOwner(this); } - } - - private AnimBool m_ShowBoundingBoxOptions = new AnimBool(); - private AnimBool m_ShowComponentUnusedWarning = new AnimBool(); - private AnimBool m_ShowResolutionXYZOptions = new AnimBool(); - private AnimBool m_ShowResolutionProbesOption = new AnimBool(); - private AnimBool m_ShowNoRendererWarning = new AnimBool(); - private AnimBool m_ShowNoLightProbesWarning = new AnimBool(); - - private bool boundingBoxOptionsValue { get { return (!m_BoundingBoxMode.hasMultipleDifferentValues) && (m_BoundingBoxMode.intValue == (int)LightProbeProxyVolume.BoundingBoxMode.Custom); } } - private bool resolutionXYZOptionValue { get { return (!m_ResolutionMode.hasMultipleDifferentValues) && (m_ResolutionMode.intValue == (int)LightProbeProxyVolume.ResolutionMode.Custom); } } - private bool resolutionProbesOptionValue { get { return (!m_ResolutionMode.hasMultipleDifferentValues) && (m_ResolutionMode.intValue == (int)LightProbeProxyVolume.ResolutionMode.Automatic); } } - private bool noLightProbesWarningValue { get { return (LightmapSettings.lightProbes == null) || (LightmapSettings.lightProbes.count == 0); } } - private bool componentUnusedWarningValue - { - get - { - Renderer renderer = ((LightProbeProxyVolume)target).GetComponent(typeof(Renderer)) as Renderer; - bool useLightProbes = (renderer != null) && LightProbes.AreLightProbesAllowed(renderer); - return (renderer != null) && (targets.Length == 1) && ((renderer.lightProbeUsage != LightProbeUsage.UseProxyVolume) || !useLightProbes); - } - } - - private bool noRendererWarningValue - { - get - { - var proxyVolume = (LightProbeProxyVolume)target; - Renderer renderer = proxyVolume.GetComponent(typeof(Renderer)) as Renderer; - return (renderer == null && proxyVolume.boundingBoxMode != LightProbeProxyVolume.BoundingBoxMode.Custom) && (targets.Length == 1); - } - } - - private void SetOptions(AnimBool animBool, bool initialize, bool targetValue) - { - if (initialize) - { - animBool.value = targetValue; - animBool.valueChanged.AddListener(Repaint); - } - else - { - animBool.target = targetValue; - } - } - - private void UpdateShowOptions(bool initialize) - { - SetOptions(m_ShowBoundingBoxOptions, initialize, boundingBoxOptionsValue); - SetOptions(m_ShowComponentUnusedWarning, initialize, componentUnusedWarningValue); - SetOptions(m_ShowResolutionXYZOptions, initialize, resolutionXYZOptionValue); - SetOptions(m_ShowResolutionProbesOption, initialize, resolutionProbesOptionValue); - SetOptions(m_ShowNoRendererWarning, initialize, noRendererWarningValue); - SetOptions(m_ShowNoLightProbesWarning, initialize, noLightProbesWarningValue); - } - - public void OnEnable() - { - m_ResolutionX = serializedObject.FindProperty("m_ResolutionX"); - m_ResolutionY = serializedObject.FindProperty("m_ResolutionY"); - m_ResolutionZ = serializedObject.FindProperty("m_ResolutionZ"); - m_BoundingBoxSize = serializedObject.FindProperty("m_BoundingBoxSize"); - m_BoundingBoxOrigin = serializedObject.FindProperty("m_BoundingBoxOrigin"); - m_BoundingBoxMode = serializedObject.FindProperty("m_BoundingBoxMode"); - m_ResolutionMode = serializedObject.FindProperty("m_ResolutionMode"); - m_ResolutionProbesPerUnit = serializedObject.FindProperty("m_ResolutionProbesPerUnit"); - m_ProbePositionMode = serializedObject.FindProperty("m_ProbePositionMode"); - m_RefreshMode = serializedObject.FindProperty("m_RefreshMode"); - - m_BoundsHandle.handleColor = kGizmoLightProbeProxyVolumeHandleColor; - m_BoundsHandle.wireframeColor = Color.clear; - - UpdateShowOptions(true); - } - - internal override Bounds GetWorldBoundsOfTarget(UnityEngine.Object targetObject) - { - return ((LightProbeProxyVolume)target).boundsGlobal; - } - - void DoToolbar() - { - using (new EditorGUI.DisabledScope(m_BoundingBoxMode.intValue != (int)LightProbeProxyVolume.BoundingBoxMode.Custom)) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - var oldEditMode = EditMode.editMode; - - EditorGUI.BeginChangeCheck(); - EditMode.DoInspectorToolbar(Styles.sceneViewEditModes, Styles.toolContents, this); - if (EditorGUI.EndChangeCheck()) - s_LastInteractedEditor = this; - - if (oldEditMode != EditMode.editMode) - { - if (Toolbar.get != null) - Toolbar.get.Repaint(); - } - - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - - // Info box for tools - GUILayout.BeginVertical(EditorStyles.helpBox); - string helpText = Styles.baseSceneEditingToolText; - if (sceneViewEditing) - { - int index = ArrayUtility.IndexOf(Styles.sceneViewEditModes, EditMode.editMode); - if (index >= 0) - helpText = Styles.toolNames[index].text; - } - GUILayout.Label(helpText, Styles.richTextMiniLabel); - GUILayout.EndVertical(); - EditorGUILayout.Space(); - } - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - UpdateShowOptions(false); - - var tree = ((LightProbeProxyVolume)target).GetComponent(); - if (tree != null) - { - EditorGUILayout.HelpBox(Styles.componentUnsuportedOnTreesNote.text, MessageType.Info); - return; - } - - EditorGUILayout.Space(); - - EditorGUILayout.Popup(m_RefreshMode, Styles.refreshMode, Styles.refreshModeText); - - EditorGUILayout.Popup(m_BoundingBoxMode, Styles.bbMode, Styles.bbModeText); - - if (EditorGUILayout.BeginFadeGroup(m_ShowBoundingBoxOptions.faded)) - { - if (targets.Length == 1) - DoToolbar(); - - GUILayout.Label(Styles.bbSettingsText); - - EditorGUI.indentLevel++; - - EditorGUILayout.PropertyField(m_BoundingBoxSize, Styles.sizeText); - EditorGUILayout.PropertyField(m_BoundingBoxOrigin, Styles.originText); - - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - - EditorGUILayout.Space(); - - GUILayout.Label(Styles.volumeResolutionText); - - EditorGUI.indentLevel++; - { - EditorGUILayout.Popup(m_ResolutionMode, Styles.resMode, Styles.resModeText); - - if (EditorGUILayout.BeginFadeGroup(m_ShowResolutionXYZOptions.faded)) - { - EditorGUILayout.IntPopup(m_ResolutionX, Styles.volTextureSizes, Styles.volTextureSizesValues, Styles.resolutionXText, GUILayout.MinWidth(40)); - EditorGUILayout.IntPopup(m_ResolutionY, Styles.volTextureSizes, Styles.volTextureSizesValues, Styles.resolutionYText, GUILayout.MinWidth(40)); - EditorGUILayout.IntPopup(m_ResolutionZ, Styles.volTextureSizes, Styles.volTextureSizesValues, Styles.resolutionZText, GUILayout.MinWidth(40)); - } - EditorGUILayout.EndFadeGroup(); - - if (EditorGUILayout.BeginFadeGroup(m_ShowResolutionProbesOption.faded)) - { - GUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(m_ResolutionProbesPerUnit, Styles.resProbesPerUnit); - GUILayout.Label(" probes per unit", EditorStyles.wordWrappedMiniLabel); - GUILayout.EndHorizontal(); - } - EditorGUILayout.EndFadeGroup(); - } - - EditorGUI.indentLevel--; - - EditorGUILayout.Space(); - - EditorGUILayout.Popup(m_ProbePositionMode, Styles.probePositionMode, Styles.probePositionText); - - if (EditorGUILayout.BeginFadeGroup(m_ShowComponentUnusedWarning.faded) && LightProbeProxyVolume.isFeatureSupported) - { - EditorGUILayout.HelpBox(Styles.componentUnusedNote.text, MessageType.Warning); - } - EditorGUILayout.EndFadeGroup(); - - if (EditorGUILayout.BeginFadeGroup(m_ShowNoRendererWarning.faded)) - { - EditorGUILayout.HelpBox(Styles.noRendererNode.text, MessageType.Info); - } - EditorGUILayout.EndFadeGroup(); - - if (EditorGUILayout.BeginFadeGroup(m_ShowNoLightProbesWarning.faded)) - { - EditorGUILayout.HelpBox(Styles.noLightProbes.text, MessageType.Info); - } - EditorGUILayout.EndFadeGroup(); - - serializedObject.ApplyModifiedProperties(); - } - - [DrawGizmo(GizmoType.Active)] - static void RenderBoxGizmo(LightProbeProxyVolume probeProxyVolume, GizmoType gizmoType) - { - if (s_LastInteractedEditor == null) - return; - - if (s_LastInteractedEditor.sceneViewEditing && EditMode.editMode == EditMode.SceneViewEditMode.LightProbeProxyVolumeBox) - { - Color oldColor = Gizmos.color; - Gizmos.color = kGizmoLightProbeProxyVolumeColor; - Vector3 position = probeProxyVolume.originCustom; - Matrix4x4 oldMatrix = Gizmos.matrix; - - Gizmos.matrix = probeProxyVolume.transform.localToWorldMatrix; - Gizmos.DrawCube(position, -1f * probeProxyVolume.sizeCustom); - - Gizmos.matrix = oldMatrix; - Gizmos.color = oldColor; - } - } - - public void OnSceneGUI() - { - if (!sceneViewEditing) - return; - - if (m_BoundingBoxMode.intValue != (int)LightProbeProxyVolume.BoundingBoxMode.Custom) - EditMode.QuitEditMode(); - - switch (EditMode.editMode) - { - case EditMode.SceneViewEditMode.LightProbeProxyVolumeBox: - DoBoxEditing(); - break; - case EditMode.SceneViewEditMode.LightProbeProxyVolumeOrigin: - DoOriginEditing(); - break; - } - } - - void DoOriginEditing() - { - LightProbeProxyVolume proxyVolume = (LightProbeProxyVolume)target; - - Vector3 handlePosition = proxyVolume.transform.TransformPoint(proxyVolume.originCustom); - - EditorGUI.BeginChangeCheck(); - - Vector3 newPostion = Handles.PositionHandle(handlePosition, proxyVolume.transform.rotation); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(proxyVolume, "Modified Light Probe Proxy Volume Box Origin"); - proxyVolume.originCustom = proxyVolume.transform.InverseTransformPoint(newPostion); - EditorUtility.SetDirty(target); - } - } - - void DoBoxEditing() - { - // Drawing of the probe box is done from GizmoDrawers.cpp, - // here we only want to show the box editing handles when needed. - LightProbeProxyVolume proxyVolume = (LightProbeProxyVolume)target; - - using (new Handles.DrawingScope(proxyVolume.transform.localToWorldMatrix)) - { - m_BoundsHandle.center = proxyVolume.originCustom; - m_BoundsHandle.size = proxyVolume.sizeCustom; - - EditorGUI.BeginChangeCheck(); - m_BoundsHandle.DrawHandle(); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(proxyVolume, "Modified Light Probe Proxy Volume AABB"); - proxyVolume.originCustom = m_BoundsHandle.center; - proxyVolume.sizeCustom = m_BoundsHandle.size; - EditorUtility.SetDirty(target); - } - } - } - } -} diff --git a/Editor/Mono/Inspector/LightProbesInspector.cs b/Editor/Mono/Inspector/LightProbesInspector.cs deleted file mode 100644 index 820e7cb4b3..0000000000 --- a/Editor/Mono/Inspector/LightProbesInspector.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - [CustomEditor(typeof(LightProbes))] - class LightProbesInspector : Editor - { - public override void OnInspectorGUI() - { - GUILayout.BeginVertical(EditorStyles.helpBox); - var lp = target as LightProbes; - GUIStyle labelStyle = EditorStyles.wordWrappedMiniLabel; - GUILayout.Label("Light probe count: " + lp.count, labelStyle); - GUILayout.Label("Cell count: " + lp.cellCount, labelStyle); - GUILayout.EndVertical(); - } - } -} diff --git a/Editor/Mono/Inspector/LightingSettingsInspector.cs b/Editor/Mono/Inspector/LightingSettingsInspector.cs deleted file mode 100644 index 72430f50c8..0000000000 --- a/Editor/Mono/Inspector/LightingSettingsInspector.cs +++ /dev/null @@ -1,620 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Linq; -using UnityEditor.AnimatedValues; -using UnityEngine.Experimental.Rendering; - -namespace UnityEditor -{ - internal class LightingSettingsInspector - { - class Styles - { - public 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, scaled, and packed for optimisation purposes. When disabled, the authored UVs will get scaled and packed, but not merged."); - public GUIContent IgnoreNormalsForChartDetection = EditorGUIUtility.TrTextContent("Ignore Normals", "When enabled, prevents the UV charts from being split during the precompute process for Realtime Global Illumination lighting."); - public int[] MinimumChartSizeValues = { 2, 4 }; - public GUIContent[] MinimumChartSizeStrings = - { - EditorGUIUtility.TrTextContent("2 (Minimum)"), - EditorGUIUtility.TrTextContent("4 (Stitchable)"), - }; - public GUIContent Lighting = new GUIContent(EditorGUIUtility.TrTextContent("Lighting").text); // prevent the Lighting window icon from being added - public 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."); - public 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."); - public GUIContent StitchLightmapSeams = EditorGUIUtility.TrTextContent("Stitch Seams", "When enabled, seams in baked lightmaps will get smoothed."); - public 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."); - public 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."); - public 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."); - public GUIContent AtlasTilingX = EditorGUIUtility.TrTextContent("Tiling X"); - public GUIContent AtlasTilingY = EditorGUIUtility.TrTextContent("Tiling Y"); - public GUIContent AtlasOffsetX = EditorGUIUtility.TrTextContent("Offset X"); - public GUIContent AtlasOffsetY = EditorGUIUtility.TrTextContent("Offset Y"); - public 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 LightmapEditorSettings class."); - public 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."); - public GUIContent ZeroAreaPackingMesh = EditorGUIUtility.TrTextContent("Mesh used by the renderer has zero UV or surface area. Non zero area is required for lightmapping."); - public GUIContent NoNormalsNoLightmapping = EditorGUIUtility.TrTextContent("Mesh used by the renderer doesn't have normals. Normals are needed for lightmapping."); - public GUIContent UVOverlap = EditorGUIUtility.TrTextContent("This GameObject has overlapping UVs. Please enable 'Generate Lightmap UVs' on the Asset or fix in your modelling package."); - public GUIContent Atlas = EditorGUIUtility.TrTextContent("Baked Lightmap"); - public GUIContent RealtimeLM = EditorGUIUtility.TrTextContent("Realtime Lightmap"); - public 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."); - public GUIContent AtlasIndex = EditorGUIUtility.TrTextContent("Lightmap Index"); - public GUIContent PVRInstanceHash = EditorGUIUtility.TrTextContent("Instance Hash", "The hash of the baked GI instance."); - public GUIContent PVRAtlasHash = EditorGUIUtility.TrTextContent("Atlas Hash", "The hash of the atlas this baked GI instance is a part of."); - public GUIContent PVRAtlasInstanceOffset = EditorGUIUtility.TrTextContent("Atlas Instance Offset", "The offset into the transform array instances of this atlas start at."); - public GUIContent RealtimeLMResolution = EditorGUIUtility.TrTextContent("System Resolution", "The resolution in texels of the realtime lightmap that this renderer belongs to."); - public GUIContent RealtimeLMInstanceResolution = EditorGUIUtility.TrTextContent("Instance Resolution", "The resolution in texels of the realtime lightmap packed instance."); - public GUIContent RealtimeLMInputSystemHash = EditorGUIUtility.TrTextContent("System Hash", "The hash of the realtime system that the renderer belongs to."); - public GUIContent RealtimeLMInstanceHash = EditorGUIUtility.TrTextContent("Instance Hash", "The hash of the realtime GI instance."); - public GUIContent RealtimeLMGeometryHash = EditorGUIUtility.TrTextContent("Geometry Hash", "The hash of the realtime GI geometry that the renderer is using."); - public GUIContent UVCharting = EditorGUIUtility.TrTextContent("UV Charting Control"); - public GUIContent LightmapSettings = EditorGUIUtility.TrTextContent("Lightmap Settings"); - public GUIContent LightmapStatic = EditorGUIUtility.TrTextContent("Lightmap Static", "Controls whether the geometry will be marked as Static for lightmapping purposes. When enabled, this mesh will be present in lightmap calculations."); - public GUIContent CastShadows = EditorGUIUtility.TrTextContent("Cast Shadows", "Specifies whether a geometry creates shadows or not when a shadow-casting Light shines on it."); - public GUIContent ReceiveShadows = EditorGUIUtility.TrTextContent("Receive Shadows", "When enabled, any shadows cast from other objects are drawn on the geometry."); - public 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."); - - public GUIContent LightmapInfoBox = EditorGUIUtility.TrTextContent("To enable generation of lightmaps for this Mesh Renderer, please enable the 'Lightmap Static' property."); - public GUIContent TerrainLightmapInfoBox = EditorGUIUtility.TrTextContent("To enable generation of lightmaps for this Mesh Renderer, please enable the 'Lightmap Static' property."); - public 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."); - public 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."); - public GUIContent GINotEnabledInfo = EditorGUIUtility.TrTextContent("Lightmapping settings are currently disabled. Enable Baked Global Illumination or Realtime Global Illumination to display these settings."); - } - - static Styles s_Styles; - - bool m_ShowSettings = false; - bool m_ShowChartingSettings = true; - bool m_ShowLightmapSettings = true; - bool m_ShowBakedLM = false; - bool m_ShowRealtimeLM = false; - - SerializedObject m_SerializedObject; - SerializedObject m_GameObjectsSerializedObject; - SerializedObject m_LightmapSettings; - - SerializedProperty m_StaticEditorFlags; - SerializedProperty m_ImportantGI; - SerializedProperty m_StitchLightmapSeams; - SerializedProperty m_LightmapParameters; - SerializedProperty m_LightmapIndex; - SerializedProperty m_LightmapTilingOffsetX; - SerializedProperty m_LightmapTilingOffsetY; - SerializedProperty m_LightmapTilingOffsetZ; - SerializedProperty m_LightmapTilingOffsetW; - SerializedProperty m_PreserveUVs; - SerializedProperty m_AutoUVMaxDistance; - SerializedProperty m_IgnoreNormalsForChartDetection; - SerializedProperty m_AutoUVMaxAngle; - SerializedProperty m_MinimumChartSize; - SerializedProperty m_LightmapScale; - SerializedProperty m_CastShadows; - SerializedProperty m_ReceiveShadows; - SerializedProperty m_MotionVectors; - - SerializedProperty m_EnabledBakedGI; - SerializedProperty m_EnabledRealtimeGI; - - Renderer[] m_Renderers; - Terrain[] m_Terrains; - - public bool showSettings { get { return m_ShowSettings; } set { m_ShowSettings = value; } } - public bool showChartingSettings { get { return m_ShowChartingSettings; } set { m_ShowChartingSettings = value; } } - public bool showLightmapSettings { get { return m_ShowLightmapSettings; } set { m_ShowLightmapSettings = value; } } - - private bool isPrefabAsset - { - get - { - if (m_SerializedObject == null || m_SerializedObject.targetObject == null) - return false; - - PrefabType type = PrefabUtility.GetPrefabType(m_SerializedObject.targetObject); - return (type == PrefabType.Prefab || type == PrefabType.ModelPrefab); - } - } - - public LightingSettingsInspector(SerializedObject serializedObject) - { - m_SerializedObject = serializedObject; - - m_GameObjectsSerializedObject = new SerializedObject(serializedObject.targetObjects.Select(t => ((Component)t).gameObject).ToArray()); - - m_ImportantGI = m_SerializedObject.FindProperty("m_ImportantGI"); - m_StitchLightmapSeams = m_SerializedObject.FindProperty("m_StitchLightmapSeams"); - m_LightmapParameters = m_SerializedObject.FindProperty("m_LightmapParameters"); - m_LightmapIndex = m_SerializedObject.FindProperty("m_LightmapIndex"); - m_LightmapTilingOffsetX = m_SerializedObject.FindProperty("m_LightmapTilingOffset.x"); - m_LightmapTilingOffsetY = m_SerializedObject.FindProperty("m_LightmapTilingOffset.y"); - m_LightmapTilingOffsetZ = m_SerializedObject.FindProperty("m_LightmapTilingOffset.z"); - m_LightmapTilingOffsetW = m_SerializedObject.FindProperty("m_LightmapTilingOffset.w"); - m_PreserveUVs = m_SerializedObject.FindProperty("m_PreserveUVs"); - m_AutoUVMaxDistance = m_SerializedObject.FindProperty("m_AutoUVMaxDistance"); - m_IgnoreNormalsForChartDetection = m_SerializedObject.FindProperty("m_IgnoreNormalsForChartDetection"); - m_AutoUVMaxAngle = m_SerializedObject.FindProperty("m_AutoUVMaxAngle"); - m_MinimumChartSize = m_SerializedObject.FindProperty("m_MinimumChartSize"); - m_LightmapScale = m_SerializedObject.FindProperty("m_ScaleInLightmap"); - m_CastShadows = serializedObject.FindProperty("m_CastShadows"); - m_ReceiveShadows = serializedObject.FindProperty("m_ReceiveShadows"); - m_MotionVectors = serializedObject.FindProperty("m_MotionVectors"); - - m_Renderers = m_SerializedObject.targetObjects.OfType().ToArray(); - m_Terrains = m_SerializedObject.targetObjects.OfType().ToArray(); - - m_StaticEditorFlags = m_GameObjectsSerializedObject.FindProperty("m_StaticEditorFlags"); - - m_LightmapSettings = new SerializedObject(LightmapEditorSettings.GetLightmapSettings()); - m_EnabledBakedGI = m_LightmapSettings.FindProperty("m_GISettings.m_EnableBakedLightmaps"); - m_EnabledRealtimeGI = m_LightmapSettings.FindProperty("m_GISettings.m_EnableRealtimeLightmaps"); - } - - public bool Begin() - { - if (s_Styles == null) - s_Styles = new Styles(); - - m_ShowSettings = EditorGUILayout.Foldout(m_ShowSettings, s_Styles.Lighting, true); - if (!m_ShowSettings) - return false; - - EditorGUI.indentLevel += 1; - return true; - } - - public void End() - { - if (m_ShowSettings) - { - EditorGUI.indentLevel -= 1; - } - } - - public void RenderMeshSettings(bool showLightmapSettings) - { - if (s_Styles == null) - s_Styles = new Styles(); - - if (m_SerializedObject == null || m_GameObjectsSerializedObject == null || m_GameObjectsSerializedObject.targetObjects.Length == 0) - return; - - m_GameObjectsSerializedObject.Update(); - m_LightmapSettings.Update(); - - EditorGUILayout.PropertyField(m_CastShadows, s_Styles.CastShadows, true); - bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath(); - - if (SupportedRenderingFeatures.active.rendererSupportsReceiveShadows) - { - using (new EditorGUI.DisabledScope(isDeferredRenderingPath)) - EditorGUILayout.PropertyField(m_ReceiveShadows, s_Styles.ReceiveShadows, true); - } - - if (SupportedRenderingFeatures.active.rendererSupportsMotionVectors) - EditorGUILayout.PropertyField(m_MotionVectors, s_Styles.MotionVectors, true); - - if (!showLightmapSettings) - return; - - LightmapStaticSettings(); - - if (!(m_EnabledBakedGI.boolValue || m_EnabledRealtimeGI.boolValue) && !isPrefabAsset) - { - EditorGUILayout.HelpBox(s_Styles.GINotEnabledInfo.text, MessageType.Info); - return; - } - - bool enableSettings = (m_StaticEditorFlags.intValue & (int)StaticEditorFlags.LightmapStatic) != 0; - - // We want to show the lightmap settings if the lightmap static flag is set. - // Most of the settings apply to both, realtime and baked GI. - if (enableSettings) - { - bool showEnlightenSettings = isPrefabAsset || m_EnabledRealtimeGI.boolValue || (m_EnabledBakedGI.boolValue && LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.Enlighten); - bool showProgressiveSettings = isPrefabAsset || (m_EnabledBakedGI.boolValue && LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.Enlighten); - - if (showEnlightenSettings) - { - m_ShowChartingSettings = EditorGUILayout.Foldout(m_ShowChartingSettings, s_Styles.UVCharting, true); - if (m_ShowChartingSettings) - RendererUVSettings(); - } - - m_ShowLightmapSettings = EditorGUILayout.Foldout(m_ShowLightmapSettings, s_Styles.LightmapSettings, true); - - if (m_ShowLightmapSettings) - { - EditorGUI.indentLevel += 1; - - float lodScale = LightmapVisualization.GetLightmapLODLevelScale(m_Renderers[0]); - for (int i = 1; i < m_Renderers.Length; i++) - { - if (!Mathf.Approximately(lodScale, LightmapVisualization.GetLightmapLODLevelScale(m_Renderers[i]))) - lodScale = 1.0F; - } - - float lightmapScale = LightmapScaleGUI(lodScale) * LightmapVisualization.GetLightmapLODLevelScale(m_Renderers[0]); - - // tell the user if the object's size in lightmap has reached the max atlas size - float cachedSurfaceArea = InternalMeshUtil.GetCachedMeshSurfaceArea((MeshRenderer)m_Renderers[0]); - - ShowClampedSizeInLightmapGUI(lightmapScale, cachedSurfaceArea); - - // Enlighten specific - if (showEnlightenSettings) - EditorGUILayout.PropertyField(m_ImportantGI, s_Styles.ImportantGI); - - if (showProgressiveSettings) - EditorGUILayout.PropertyField(m_StitchLightmapSeams, s_Styles.StitchLightmapSeams); - - LightmapParametersGUI(m_LightmapParameters, s_Styles.LightmapParameters); - - m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, s_Styles.Atlas, true); - if (m_ShowBakedLM) - ShowAtlasGUI(m_Renderers[0].GetInstanceID()); - - m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, s_Styles.RealtimeLM, true); - if (m_ShowRealtimeLM) - ShowRealtimeLMGUI(m_Renderers[0]); - - EditorGUI.indentLevel -= 1; - } - - if (LightmapEditorSettings.HasZeroAreaMesh(m_Renderers[0])) - EditorGUILayout.HelpBox(s_Styles.ZeroAreaPackingMesh.text, MessageType.Warning); - - if (LightmapEditorSettings.HasClampedResolution(m_Renderers[0])) - EditorGUILayout.HelpBox(s_Styles.ClampedPackingResolution.text, MessageType.Warning); - - if (!HasNormals(m_Renderers[0])) - EditorGUILayout.HelpBox(s_Styles.NoNormalsNoLightmapping.text, MessageType.Warning); - - if (LightmapEditorSettings.HasUVOverlaps(m_Renderers[0])) - EditorGUILayout.HelpBox(s_Styles.UVOverlap.text, MessageType.Warning); - - m_SerializedObject.ApplyModifiedProperties(); - } - else - EditorGUILayout.HelpBox(s_Styles.LightmapInfoBox.text, MessageType.Info); - } - - public void RenderTerrainSettings() - { - if (s_Styles == null) - s_Styles = new Styles(); - - if (m_SerializedObject == null || m_GameObjectsSerializedObject == null || m_GameObjectsSerializedObject.targetObjects.Length == 0) - return; - - m_GameObjectsSerializedObject.Update(); - m_LightmapSettings.Update(); - - LightmapStaticSettings(); - - if (!(m_EnabledBakedGI.boolValue || m_EnabledRealtimeGI.boolValue) && !isPrefabAsset) - { - EditorGUILayout.HelpBox(s_Styles.GINotEnabledInfo.text, MessageType.Info); - return; - } - - bool enableSettings = (m_StaticEditorFlags.intValue & (int)StaticEditorFlags.LightmapStatic) != 0; - - if (enableSettings) - { - m_ShowLightmapSettings = EditorGUILayout.Foldout(m_ShowLightmapSettings, s_Styles.LightmapSettings, true); - - if (m_ShowLightmapSettings) - { - EditorGUI.indentLevel += 1; - - using (new EditorGUI.DisabledScope(!enableSettings)) - { - if (GUI.enabled) - ShowTerrainChunks(m_Terrains); - - float lightmapScale = LightmapScaleGUI(1.0f); - - // tell the user if the object's size in lightmap has reached the max atlas size - var terrainData = m_Terrains[0].terrainData; - float cachedSurfaceArea = terrainData != null ? terrainData.size.x * terrainData.size.z : 0; - ShowClampedSizeInLightmapGUI(lightmapScale, cachedSurfaceArea); - - LightmapParametersGUI(m_LightmapParameters, s_Styles.LightmapParameters); - - if (GUI.enabled && m_Terrains.Length == 1 && m_Terrains[0].terrainData != null) - ShowBakePerformanceWarning(m_Terrains[0]); - - m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, s_Styles.Atlas, true); - if (m_ShowBakedLM) - ShowAtlasGUI(m_Terrains[0].GetInstanceID()); - - m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, s_Styles.RealtimeLM, true); - if (m_ShowRealtimeLM) - ShowRealtimeLMGUI(m_Terrains[0]); - - m_SerializedObject.ApplyModifiedProperties(); - } - EditorGUI.indentLevel -= 1; - } - GUILayout.Space(10); - } - else - EditorGUILayout.HelpBox(s_Styles.TerrainLightmapInfoBox.text, MessageType.Info); - } - - void LightmapStaticSettings() - { - bool lightmapStatic = (m_StaticEditorFlags.intValue & (int)StaticEditorFlags.LightmapStatic) != 0; - - EditorGUI.BeginChangeCheck(); - lightmapStatic = EditorGUILayout.Toggle(s_Styles.LightmapStatic, lightmapStatic); - - if (EditorGUI.EndChangeCheck()) - { - SceneModeUtility.SetStaticFlags(m_GameObjectsSerializedObject.targetObjects, (int)StaticEditorFlags.LightmapStatic, lightmapStatic); - m_GameObjectsSerializedObject.Update(); - } - } - - void RendererUVSettings() - { - EditorGUI.indentLevel++; - - // TODO: This is very temporary and the flag needs to be changed. Will fix / Jen - bool optimizeRealtimeUVs = !m_PreserveUVs.boolValue; - - EditorGUI.BeginChangeCheck(); - optimizeRealtimeUVs = EditorGUILayout.Toggle(s_Styles.OptimizeRealtimeUVs, optimizeRealtimeUVs); - - if (EditorGUI.EndChangeCheck()) - { - m_PreserveUVs.boolValue = !optimizeRealtimeUVs; - } - - EditorGUI.indentLevel++; - bool disabledAutoUVs = m_PreserveUVs.boolValue; - using (new EditorGUI.DisabledScope(disabledAutoUVs)) - { - EditorGUILayout.PropertyField(m_AutoUVMaxDistance, s_Styles.AutoUVMaxDistance); - if (m_AutoUVMaxDistance.floatValue < 0.0f) - m_AutoUVMaxDistance.floatValue = 0.0f; - EditorGUILayout.Slider(m_AutoUVMaxAngle, 0, 180, s_Styles.AutoUVMaxAngle); - } - EditorGUI.indentLevel--; - - EditorGUILayout.PropertyField(m_IgnoreNormalsForChartDetection, s_Styles.IgnoreNormalsForChartDetection); - - EditorGUILayout.IntPopup(m_MinimumChartSize, s_Styles.MinimumChartSizeStrings, s_Styles.MinimumChartSizeValues, s_Styles.MinimumChartSize); - EditorGUI.indentLevel--; - } - - void ShowClampedSizeInLightmapGUI(float lightmapScale, float cachedSurfaceArea) - { - float sizeInLightmap = Mathf.Sqrt(cachedSurfaceArea) * LightmapEditorSettings.bakeResolution * lightmapScale; - - if (sizeInLightmap > LightmapEditorSettings.maxAtlasSize) - EditorGUILayout.HelpBox(s_Styles.ClampedSize.text, MessageType.Info); - } - - float LightmapScaleGUI(float lodScale) - { - float lightmapScale = lodScale * m_LightmapScale.floatValue; - - Rect rect = EditorGUILayout.GetControlRect(); - EditorGUI.BeginProperty(rect, s_Styles.ScaleInLightmap, m_LightmapScale); - EditorGUI.BeginChangeCheck(); - lightmapScale = EditorGUI.FloatField(rect, s_Styles.ScaleInLightmap, lightmapScale); - if (EditorGUI.EndChangeCheck()) - m_LightmapScale.floatValue = Mathf.Max(lightmapScale / Mathf.Max(lodScale, float.Epsilon), 0.0f); - EditorGUI.EndProperty(); - - return lightmapScale; - } - - void ShowAtlasGUI(int instanceID) - { - EditorGUI.indentLevel += 1; - - Hash128 instanceHash; - LightmapEditorSettings.GetPVRInstanceHash(instanceID, out instanceHash); - EditorGUILayout.LabelField(s_Styles.PVRInstanceHash, GUIContent.Temp(instanceHash.ToString())); - - Hash128 atlasHash; - LightmapEditorSettings.GetPVRAtlasHash(instanceID, out atlasHash); - EditorGUILayout.LabelField(s_Styles.PVRAtlasHash, GUIContent.Temp(atlasHash.ToString())); - - int atlasInstanceOffset; - LightmapEditorSettings.GetPVRAtlasInstanceOffset(instanceID, out atlasInstanceOffset); - EditorGUILayout.LabelField(s_Styles.PVRAtlasInstanceOffset, GUIContent.Temp(atlasInstanceOffset.ToString())); - - EditorGUILayout.LabelField(s_Styles.AtlasIndex, GUIContent.Temp(m_LightmapIndex.intValue.ToString())); - EditorGUILayout.LabelField(s_Styles.AtlasTilingX, GUIContent.Temp(m_LightmapTilingOffsetX.floatValue.ToString())); - EditorGUILayout.LabelField(s_Styles.AtlasTilingY, GUIContent.Temp(m_LightmapTilingOffsetY.floatValue.ToString())); - EditorGUILayout.LabelField(s_Styles.AtlasOffsetX, GUIContent.Temp(m_LightmapTilingOffsetZ.floatValue.ToString())); - EditorGUILayout.LabelField(s_Styles.AtlasOffsetY, GUIContent.Temp(m_LightmapTilingOffsetW.floatValue.ToString())); - EditorGUI.indentLevel -= 1; - } - - void ShowRealtimeLMGUI(Terrain terrain) - { - EditorGUI.indentLevel += 1; - - // Resolution of the system. - int width, height; - int numChunksInX, numChunksInY; - if (LightmapEditorSettings.GetTerrainSystemResolution(terrain, out width, out height, out numChunksInX, out numChunksInY)) - { - var str = width.ToString() + "x" + height.ToString(); - if (numChunksInX > 1 || numChunksInY > 1) - str += string.Format(" ({0}x{1} chunks)", numChunksInX, numChunksInY); - EditorGUILayout.LabelField(s_Styles.RealtimeLMResolution, GUIContent.Temp(str)); - } - - EditorGUI.indentLevel -= 1; - } - - void ShowRealtimeLMGUI(Renderer renderer) - { - EditorGUI.indentLevel += 1; - - // The hash of the instance. - Hash128 instanceHash; - if (LightmapEditorSettings.GetInstanceHash(renderer, out instanceHash)) - { - EditorGUILayout.LabelField(s_Styles.RealtimeLMInstanceHash, GUIContent.Temp(instanceHash.ToString())); - } - - // The hash of the geometry. - Hash128 geometryHash; - if (LightmapEditorSettings.GetGeometryHash(renderer, out geometryHash)) - { - EditorGUILayout.LabelField(s_Styles.RealtimeLMGeometryHash, GUIContent.Temp(geometryHash.ToString())); - } - - // Resolution of the packed instance. - int instWidth, instHeight; - if (LightmapEditorSettings.GetInstanceResolution(renderer, out instWidth, out instHeight)) - { - EditorGUILayout.LabelField(s_Styles.RealtimeLMInstanceResolution, GUIContent.Temp(instWidth.ToString() + "x" + instHeight.ToString())); - } - - // The hash of the system. - Hash128 inputSystemHash; - if (LightmapEditorSettings.GetInputSystemHash(renderer, out inputSystemHash)) - { - EditorGUILayout.LabelField(s_Styles.RealtimeLMInputSystemHash, GUIContent.Temp(inputSystemHash.ToString())); - } - - // Resolution of the system. - int width, height; - if (LightmapEditorSettings.GetSystemResolution(renderer, out width, out height)) - { - EditorGUILayout.LabelField(s_Styles.RealtimeLMResolution, GUIContent.Temp(width.ToString() + "x" + height.ToString())); - } - - EditorGUI.indentLevel -= 1; - } - - static bool HasNormals(Renderer renderer) - { - Mesh mesh = null; - if (renderer is MeshRenderer) - { - MeshFilter mf = renderer.GetComponent(); - if (mf != null) - mesh = mf.sharedMesh; - } - else if (renderer is SkinnedMeshRenderer) - { - mesh = (renderer as SkinnedMeshRenderer).sharedMesh; - } - return mesh != null && InternalMeshUtil.HasNormals(mesh); - } - - static private bool isBuiltIn(SerializedProperty prop) - { - if (prop.objectReferenceValue != null) - { - var parameters = prop.objectReferenceValue as LightmapParameters; - return (parameters.hideFlags == HideFlags.NotEditable); - } - - return false; - } - - static public bool LightmapParametersGUI(SerializedProperty prop, GUIContent content) - { - EditorGUILayout.BeginHorizontal(); - - EditorGUIInternal.AssetPopup(prop, content, "giparams", "Scene Default Parameters"); - - string label = "Edit..."; - - if (isBuiltIn(prop)) - label = "View"; - - bool editClicked = false; - - // If object is null, then get the scene parameter setting and view this instead. - if (prop.objectReferenceValue == null) - { - SerializedObject so = new SerializedObject(LightmapEditorSettings.GetLightmapSettings()); - SerializedProperty lightmapParameters = so.FindProperty("m_LightmapEditorSettings.m_LightmapParameters"); - - using (new EditorGUI.DisabledScope(lightmapParameters == null)) - { - if (isBuiltIn(lightmapParameters)) - label = "View"; - else - label = "Edit..."; - - if (GUILayout.Button(label, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - { - Selection.activeObject = lightmapParameters.objectReferenceValue; - editClicked = true; - } - } - } - else - { - if (GUILayout.Button(label, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - { - Selection.activeObject = prop.objectReferenceValue; - editClicked = true; - } - } - - EditorGUILayout.EndHorizontal(); - - return editClicked; - } - - void ShowTerrainChunks(Terrain[] terrains) - { - int terrainChunksX = 0, terrainChunksY = 0; - foreach (var terrain in terrains) - { - int tmpChunksX = 0, tmpChunksY = 0; - Lightmapping.GetTerrainGIChunks(terrain, ref tmpChunksX, ref tmpChunksY); - if (terrainChunksX == 0 && terrainChunksY == 0) - { - terrainChunksX = tmpChunksX; - terrainChunksY = tmpChunksY; - } - else if (terrainChunksX != tmpChunksX || terrainChunksY != tmpChunksY) - { - terrainChunksX = terrainChunksY = 0; - break; - } - } - if (terrainChunksX * terrainChunksY > 1) - EditorGUILayout.HelpBox(string.Format(L10n.Tr("Terrain is chunked up into {0} instances for baking."), terrainChunksX * terrainChunksY), MessageType.None); - } - - void ShowBakePerformanceWarning(Terrain terrain) - { - var terrainWidth = terrain.terrainData.size.x; - var terrainHeight = terrain.terrainData.size.z; - var lightmapParameters = (LightmapParameters)m_LightmapParameters.objectReferenceValue ?? new LightmapParameters(); - - var terrainSystemTexelsInWidth = terrainWidth * lightmapParameters.resolution * LightmapEditorSettings.realtimeResolution; - var terrainSystemTexelsInHeight = terrainHeight * lightmapParameters.resolution * LightmapEditorSettings.realtimeResolution; - const int kTerrainTexelsThreshold = 64 * 8; - if (terrainSystemTexelsInWidth > kTerrainTexelsThreshold || terrainSystemTexelsInHeight > kTerrainTexelsThreshold) - { - EditorGUILayout.HelpBox(s_Styles.ResolutionTooHighWarning.text, MessageType.Warning); - } - - var terrainClustersInWidth = terrainSystemTexelsInWidth * lightmapParameters.clusterResolution; - var terrainClustersInHeight = terrainSystemTexelsInHeight * lightmapParameters.clusterResolution; - var terrainTrisPerClusterInWidth = terrain.terrainData.heightmapResolution / terrainClustersInWidth; - var terrainTrisPerClusterInHeight = terrain.terrainData.heightmapResolution / terrainClustersInHeight; - const float kTerrainClusterTriDensityThreshold = 256.0f / 5.0f; - if (terrainTrisPerClusterInWidth > kTerrainClusterTriDensityThreshold || terrainTrisPerClusterInHeight > kTerrainClusterTriDensityThreshold) - { - EditorGUILayout.HelpBox(s_Styles.ResolutionTooLowWarning.text, MessageType.Warning); - } - } - } -} diff --git a/Editor/Mono/Inspector/LineRendererCurveEditor.cs b/Editor/Mono/Inspector/LineRendererCurveEditor.cs deleted file mode 100644 index dbf342186e..0000000000 --- a/Editor/Mono/Inspector/LineRendererCurveEditor.cs +++ /dev/null @@ -1,157 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - internal class LineRendererCurveEditor - { - private class Styles - { - public static GUIContent widthMultiplier = EditorGUIUtility.TrTextContent("Width", "The multiplier applied to the curve, describing the width (in world space) along the line."); - } - - private bool m_Refresh = false; - private CurveEditor m_Editor = null; - private CurveEditorSettings m_Settings = new CurveEditorSettings(); - - private SerializedProperty m_WidthMultiplier; - private SerializedProperty m_WidthCurve; - - public void OnEnable(SerializedObject serializedObject) - { - m_WidthMultiplier = serializedObject.FindProperty("m_Parameters.widthMultiplier"); - m_WidthCurve = serializedObject.FindProperty("m_Parameters.widthCurve"); - - m_Settings.hRangeMin = 0.0f; - m_Settings.vRangeMin = 0.0f; - m_Settings.vRangeMax = 1.0f; - m_Settings.hRangeMax = 1.0f; - m_Settings.vSlider = false; - m_Settings.hSlider = false; - - TickStyle hTS = new TickStyle(); - hTS.tickColor.color = new Color(0.0f, 0.0f, 0.0f, 0.15f); - hTS.distLabel = 30; - m_Settings.hTickStyle = hTS; - TickStyle vTS = new TickStyle(); - vTS.tickColor.color = new Color(0.0f, 0.0f, 0.0f, 0.15f); - vTS.distLabel = 20; - m_Settings.vTickStyle = vTS; - - m_Settings.undoRedoSelection = true; - - m_Editor = new CurveEditor(new Rect(0, 0, 1000, 100), new CurveWrapper[0], false); - m_Editor.settings = m_Settings; - m_Editor.margin = 25; - m_Editor.SetShownHRangeInsideMargins(0.0f, 1.0f); - m_Editor.SetShownVRangeInsideMargins(0.0f, 1.0f); - m_Editor.ignoreScrollWheelUntilClicked = true; - - Undo.undoRedoPerformed += UndoRedoPerformed; - } - - public void OnDisable() - { - m_Editor.OnDisable(); - Undo.undoRedoPerformed -= UndoRedoPerformed; - } - - private CurveWrapper GetCurveWrapper(AnimationCurve curve) - { - float colorMultiplier = !EditorGUIUtility.isProSkin ? 0.9f : 1.0f; - Color colorMult = new Color(colorMultiplier, colorMultiplier, colorMultiplier, 1); - - CurveWrapper wrapper = new CurveWrapper(); - wrapper.id = 0; - wrapper.groupId = -1; - wrapper.color = new Color(1.0f, 0.0f, 0.0f, 1.0f) * colorMult; - wrapper.hidden = false; - wrapper.readOnly = false; - wrapper.renderer = new NormalCurveRenderer(curve); - wrapper.renderer.SetCustomRange(0.0f, 1.0f); - wrapper.getAxisUiScalarsCallback = GetAxisScalars; - return wrapper; - } - - public Vector2 GetAxisScalars() - { - return new Vector2(1.0f, m_WidthMultiplier.floatValue); - } - - private void UndoRedoPerformed() - { - m_Refresh = true; - } - - public void CheckCurveChangedExternally() - { - CurveWrapper cw = m_Editor.GetCurveWrapperFromID(0); - if (m_WidthCurve != null) - { - AnimationCurve propCurve = m_WidthCurve.animationCurveValue; - if ((cw == null) != m_WidthCurve.hasMultipleDifferentValues) - { - m_Refresh = true; - } - else if (cw != null) - { - if (cw.curve.length == 0) - m_Refresh = true; - else if (propCurve.length >= 1 && propCurve.keys[0].value != cw.curve.keys[0].value) - m_Refresh = true; - } - } - else if (cw != null) - { - m_Refresh = true; - } - } - - public void OnInspectorGUI() - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_WidthMultiplier, Styles.widthMultiplier); - if (EditorGUI.EndChangeCheck()) - m_Refresh = true; - - Rect r = GUILayoutUtility.GetAspectRect(2.5f, GUI.skin.textField); - r.xMin += EditorGUI.indent; - if (Event.current.type != EventType.Layout && Event.current.type != EventType.Used) - { - m_Editor.rect = new Rect(r.x, r.y, r.width, r.height); - } - - // Draw Curve Editor - if (m_Refresh) - { - m_Editor.animationCurves = new CurveWrapper[] { GetCurveWrapper(m_WidthCurve.animationCurveValue) }; - m_Refresh = false; - } - - GUI.Label(m_Editor.drawRect, GUIContent.none, "TextField"); - - m_Editor.hRangeLocked = Event.current.shift; - m_Editor.vRangeLocked = EditorGUI.actionKey; - - m_Editor.OnGUI(); - - // Apply curve changes - if ((m_Editor.GetCurveWrapperFromID(0) != null) && (m_Editor.GetCurveWrapperFromID(0).changed)) - { - AnimationCurve changedCurve = m_Editor.GetCurveWrapperFromID(0).curve; - - // Never save a curve with no keys - if (changedCurve.length > 0) - { - m_WidthCurve.animationCurveValue = changedCurve; - m_Editor.GetCurveWrapperFromID(0).changed = false; - } - } - } - } -} diff --git a/Editor/Mono/Inspector/LineRendererInspector.cs b/Editor/Mono/Inspector/LineRendererInspector.cs deleted file mode 100644 index 66f9c06cac..0000000000 --- a/Editor/Mono/Inspector/LineRendererInspector.cs +++ /dev/null @@ -1,91 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Experimental.Rendering; - -namespace UnityEditor -{ - [CustomEditor(typeof(LineRenderer))] - [CanEditMultipleObjects] - internal class LineRendererInspector : RendererEditorBase - { - private class Styles - { - public static GUIContent colorGradient = EditorGUIUtility.TrTextContent("Color", "The gradient describing the color along the line."); - public static GUIContent numCornerVertices = EditorGUIUtility.TrTextContent("Corner Vertices", "How many vertices to add for each corner."); - public static GUIContent numCapVertices = EditorGUIUtility.TrTextContent("End Cap Vertices", "How many vertices to add at each end."); - public static GUIContent alignment = EditorGUIUtility.TrTextContent("Alignment", "Lines can rotate to face their transform component or the camera. Note that when using Local mode, lines will face the XY plane of the Transform."); - public static GUIContent textureMode = EditorGUIUtility.TrTextContent("Texture Mode", "Should the U coordinate be stretched or tiled?"); - public static GUIContent generateLightingData = EditorGUIUtility.TrTextContent("Generate Lighting Data", "Toggle generation of normal and tangent data, for use in lit shaders."); - } - - private string[] m_ExcludedProperties; - - private LineRendererCurveEditor m_CurveEditor = new LineRendererCurveEditor(); - private SerializedProperty m_ColorGradient; - private SerializedProperty m_NumCornerVertices; - private SerializedProperty m_NumCapVertices; - private SerializedProperty m_Alignment; - private SerializedProperty m_TextureMode; - private SerializedProperty m_GenerateLightingData; - - public override void OnEnable() - { - base.OnEnable(); - - List excludedProperties = new List(); - excludedProperties.Add("m_Parameters"); - excludedProperties.AddRange(Probes.GetFieldsStringArray()); - if (!SupportedRenderingFeatures.active.rendererSupportsMotionVectors) - excludedProperties.Add("m_MotionVectors"); - if (!SupportedRenderingFeatures.active.rendererSupportsReceiveShadows) - excludedProperties.Add("m_ReceiveShadows"); - excludedProperties.Add("m_RenderingLayerMask"); - m_ExcludedProperties = excludedProperties.ToArray(); - - m_CurveEditor.OnEnable(serializedObject); - m_ColorGradient = serializedObject.FindProperty("m_Parameters.colorGradient"); - m_NumCornerVertices = serializedObject.FindProperty("m_Parameters.numCornerVertices"); - m_NumCapVertices = serializedObject.FindProperty("m_Parameters.numCapVertices"); - m_Alignment = serializedObject.FindProperty("m_Parameters.alignment"); - m_TextureMode = serializedObject.FindProperty("m_Parameters.textureMode"); - m_GenerateLightingData = serializedObject.FindProperty("m_Parameters.generateLightingData"); - - InitializeProbeFields(); - } - - public void OnDisable() - { - m_CurveEditor.OnDisable(); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - DrawPropertiesExcluding(m_SerializedObject, m_ExcludedProperties); - - m_CurveEditor.CheckCurveChangedExternally(); - m_CurveEditor.OnInspectorGUI(); - - EditorGUILayout.PropertyField(m_ColorGradient, Styles.colorGradient); - EditorGUILayout.PropertyField(m_NumCornerVertices, Styles.numCornerVertices); - EditorGUILayout.PropertyField(m_NumCapVertices, Styles.numCapVertices); - EditorGUILayout.PropertyField(m_Alignment, Styles.alignment); - EditorGUILayout.PropertyField(m_TextureMode, Styles.textureMode); - EditorGUILayout.PropertyField(m_GenerateLightingData, Styles.generateLightingData); - - EditorGUILayout.Space(); - - RenderSortingLayerFields(); - - m_Probes.OnGUI(targets, (Renderer)target, false); - - RenderRenderingLayer(); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/MaterialEditor.cs b/Editor/Mono/Inspector/MaterialEditor.cs deleted file mode 100644 index c23a58cd93..0000000000 --- a/Editor/Mono/Inspector/MaterialEditor.cs +++ /dev/null @@ -1,2062 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditorInternal; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [CustomEditor(typeof(Material))] - [CanEditMultipleObjects] - public partial class MaterialEditor : Editor - { - private static class Styles - { - public static readonly GUIStyle kReflectionProbePickerStyle = "PaneOptions"; - 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 uses realtime global illumination if enabled in the scene. Otherwise the emission won't light up other objects."); - public static GUIContent[] lightmapEmissiveStrings = { EditorGUIUtility.TextContent("Realtime"), EditorGUIUtility.TextContent("Baked"), EditorGUIUtility.TrTextContent("None") }; - public static int[] lightmapEmissiveValues = { (int)MaterialGlobalIlluminationFlags.RealtimeEmissive, (int)MaterialGlobalIlluminationFlags.BakedEmissive, (int)MaterialGlobalIlluminationFlags.None }; - public static string propBlockInfo = EditorGUIUtility.TrTextContent("MaterialPropertyBlock is used to modify these values").text; - - public const int kNewShaderQueueValue = -1; - public const int kCustomQueueIndex = 4; - public static readonly GUIContent queueLabel = EditorGUIUtility.TrTextContent("Render Queue"); - public static readonly GUIContent[] queueNames = - { - EditorGUIUtility.TrTextContent("From Shader"), - EditorGUIUtility.TrTextContent("Geometry", "Queue 2000"), - EditorGUIUtility.TrTextContent("AlphaTest", "Queue 2450"), - EditorGUIUtility.TrTextContent("Transparent", "Queue 3000"), - }; - public static readonly int[] queueValues = - { - kNewShaderQueueValue, - (int)UnityEngine.Rendering.RenderQueue.Geometry, - (int)UnityEngine.Rendering.RenderQueue.AlphaTest, - (int)UnityEngine.Rendering.RenderQueue.Transparent, - }; - public static GUIContent[] customQueueNames = - { - queueNames[0], - queueNames[1], - queueNames[2], - queueNames[3], - EditorGUIUtility.TextContent(""), // This name will be overriden during runtime - }; - public static int[] customQueueValues = - { - queueValues[0], - queueValues[1], - queueValues[2], - queueValues[3], - 0, // This value will be overriden during runtime - }; - - public static readonly GUIContent enableInstancingLabel = EditorGUIUtility.TrTextContent("Enable GPU Instancing"); - 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."); - public static readonly GUIContent emissionLabel = EditorGUIUtility.TrTextContent("Emission"); - } - - private static readonly List s_MaterialEditors = new List(4); - private bool m_IsVisible; - private bool m_CheckSetup; - internal bool forceVisible { get; set; } - private static int s_ControlHash = "EditorTextField".GetHashCode(); - const float kSpacingUnderTexture = 6f; - const float kMiniWarningMessageHeight = 27f; - - private MaterialPropertyBlock m_PropertyBlock; - - private enum PreviewType - { - Mesh = 0, - Plane = 1, - Skybox = 2 - } - - private static PreviewType GetPreviewType(Material mat) - { - if (mat == null) - return PreviewType.Mesh; - var tag = mat.GetTag("PreviewType", false, string.Empty).ToLower(); - if (tag == "plane") - return PreviewType.Plane; - if (tag == "skybox") - return PreviewType.Skybox; - if (mat.shader != null && mat.shader.name.Contains("Skybox")) - return PreviewType.Skybox; - return PreviewType.Mesh; - } - - private static bool DoesPreviewAllowRotation(PreviewType type) - { - return type != PreviewType.Plane; - } - - public bool isVisible { get { return forceVisible || m_IsVisible; } } - - private Shader m_Shader; - private SerializedProperty m_EnableInstancing; - private SerializedProperty m_DoubleSidedGI; - - private SerializedObject m_LightmapSettings; - private SerializedProperty m_EnabledRealtimeGI; - private SerializedProperty m_EnabledBakedGI; - - private string m_InfoMessage; - private Vector2 m_PreviewDir = new Vector2(0, -20); - private int m_SelectedMesh; - private int m_TimeUpdate; - private int m_LightMode = 1; - private static readonly GUIContent s_TilingText = EditorGUIUtility.TrTextContent("Tiling"); - private static readonly GUIContent s_OffsetText = EditorGUIUtility.TrTextContent("Offset"); - - ShaderGUI m_CustomShaderGUI; - string m_CustomEditorClassName; - - bool m_InsidePropertiesGUI; - Renderer[] m_RenderersForAnimationMode; - - private Renderer rendererForAnimationMode - { - get - { - if (m_RenderersForAnimationMode == null) - return null; - - if (m_RenderersForAnimationMode.Length == 0) - return null; - - return m_RenderersForAnimationMode[0]; - } - } - - private struct AnimatedCheckData - { - public MaterialProperty property; - public Rect totalPosition; - public Color color; - public AnimatedCheckData(MaterialProperty property, Rect totalPosition, Color color) - { - this.property = property; - this.totalPosition = totalPosition; - this.color = color; - } - } - - private static Stack s_AnimatedCheckStack = new Stack(); - - internal delegate void MaterialPropertyCallbackFunction(GenericMenu menu, MaterialProperty property, Renderer[] renderers); - internal static MaterialPropertyCallbackFunction contextualPropertyMenu; - - internal class ReflectionProbePicker : PopupWindowContent - { - ReflectionProbe m_SelectedReflectionProbe; - - public Transform Target - { - get { return m_SelectedReflectionProbe != null ? m_SelectedReflectionProbe.transform : null; } - } - - public override Vector2 GetWindowSize() - { - return new Vector2(170, EditorGUI.kSingleLineHeight * 3); - } - - public void OnEnable() - { - m_SelectedReflectionProbe = EditorUtility.InstanceIDToObject(SessionState.GetInt("PreviewReflectionProbe", 0)) as ReflectionProbe; - } - - public void OnDisable() - { - SessionState.SetInt("PreviewReflectionProbe", m_SelectedReflectionProbe ? m_SelectedReflectionProbe.GetInstanceID() : 0); - } - - public override void OnGUI(Rect rc) - { - EditorGUILayout.LabelField("Select Reflection Probe", EditorStyles.boldLabel); - EditorGUILayout.Space(); - m_SelectedReflectionProbe = EditorGUILayout.ObjectField("", m_SelectedReflectionProbe, typeof(ReflectionProbe), true) as ReflectionProbe; - } - } - - ReflectionProbePicker m_ReflectionProbePicker = new ReflectionProbePicker(); - - - public void SetShader(Shader shader) - { - SetShader(shader, true); - } - - public void SetShader(Shader newShader, bool registerUndo) - { - bool updateMaterialEditors = false; - ShaderGUI customEditor = m_CustomShaderGUI; - CreateCustomShaderEditorIfNeeded(newShader); - m_Shader = newShader; - if (customEditor != m_CustomShaderGUI) - { - if (customEditor != null) - { - foreach (Material material in targets) - customEditor.OnClosed(material); - } - - updateMaterialEditors = true; - } - - foreach (Material material in targets) - { - Shader oldShader = material.shader; - Undo.RecordObject(material, "Assign shader"); - if (m_CustomShaderGUI != null) - { - m_CustomShaderGUI.AssignNewShaderToMaterial(material, oldShader, newShader); - } - else - { - material.shader = newShader; - } - - EditorMaterialUtility.ResetDefaultTextures(material, false); - ApplyMaterialPropertyDrawers(material); - } - - if (updateMaterialEditors) - { - UpdateAllOpenMaterialEditors(); - } - else - { - // ensure e.g., correctly rebuilt textures (case 879446) - OnShaderChanged(); - } - } - - private void UpdateAllOpenMaterialEditors() - { - // copy current list contents to array in case it changes during iteration - foreach (var materialEditor in s_MaterialEditors.ToArray()) - materialEditor.DetectShaderEditorNeedsUpdate(); - } - - // Note: this is called from native code. - internal void OnSelectedShaderPopup(object shaderNameObj) - { - serializedObject.Update(); - var shaderName = (string)shaderNameObj; - if (!string.IsNullOrEmpty(shaderName)) - { - var shader = Shader.Find(shaderName); - if (shader != null) - SetShader(shader); - } - - PropertiesChanged(); - } - - private bool HasMultipleMixedShaderValues() - { - bool mixed = false; - Shader sh = (targets[0] as Material).shader; - for (int i = 1; i < targets.Length; ++i) - { - if (sh != (targets[i] as Material).shader) - { - mixed = true; - break; - } - } - return mixed; - } - - private void ShaderPopup(GUIStyle style) - { - bool wasEnabled = GUI.enabled; - - Rect position = EditorGUILayout.GetControlRect(); - position = EditorGUI.PrefixLabel(position, 47385, EditorGUIUtility.TempContent("Shader")); - EditorGUI.showMixedValue = HasMultipleMixedShaderValues(); - - var buttonContent = EditorGUIUtility.TempContent(m_Shader != null ? m_Shader.name : "No Shader Selected"); - if (EditorGUI.DropdownButton(position, buttonContent, FocusType.Keyboard, style)) - { - var menu = new GenericMenu(); - CreateShaderList(menu); - menu.DropDown(position); - } - - EditorGUI.showMixedValue = false; - GUI.enabled = wasEnabled; - } - - private void CreateShaderList(GenericMenu menu) - { - var shaders = ShaderUtil.GetAllShaderInfo(); - var noSubmenuList = new List(); - var submenuList = new List(); - var legacyList = new List(); - var notSupportedList = new List(); - var failedCompilationList = new List(); - - foreach (var shader in shaders) - { - if (shader.name.StartsWith("Deprecated") || shader.name.StartsWith("Hidden")) - { - continue; - } - if (shader.hasErrors) - { - failedCompilationList.Add(shader.name); - continue; - } - if (!shader.supported) - { - notSupportedList.Add(shader.name); - continue; - } - if (shader.name.StartsWith("Legacy Shaders/")) - { - legacyList.Add(shader.name); - continue; - } - if (shader.name.Contains("/")) - { - submenuList.Add(shader.name); - continue; - } - noSubmenuList.Add(shader.name); - } - - noSubmenuList.Sort(); - submenuList.Sort(); - legacyList.Sort(); - notSupportedList.Sort(); - failedCompilationList.Sort(); - - noSubmenuList.ForEach(s => AddShaderToMenu("", menu, s)); - submenuList.ForEach(s => AddShaderToMenu("", menu, s)); - if (legacyList.Any()) - menu.AddSeparator(""); - legacyList.ForEach(s => AddShaderToMenu("", menu, s)); - if (notSupportedList.Any()) - menu.AddSeparator(""); - notSupportedList.ForEach(s => AddShaderToMenu("Not supported/", menu, s)); - if (failedCompilationList.Any()) - menu.AddSeparator(""); - failedCompilationList.ForEach(s => AddShaderToMenu("Failed to compile/", menu, s)); - } - - private void AddShaderToMenu(string prefix, GenericMenu menu, string shaderName) - { - var selected = m_Shader != null ? m_Shader.name == shaderName : false; - menu.AddItem(new GUIContent(prefix + shaderName), selected, OnSelectedShaderPopup, shaderName); - } - - public virtual void Awake() - { - m_IsVisible = InternalEditorUtility.GetIsInspectorExpanded(target); - if (GetPreviewType(target as Material) == PreviewType.Skybox) - m_PreviewDir = new Vector2(0, 50); - } - - private void DetectShaderEditorNeedsUpdate() - { - var material = target as Material; - bool shaderChanged = material && material.shader != m_Shader; - bool customEditorChanged = material && material.shader && m_CustomEditorClassName != material.shader.customEditor; - if (shaderChanged || customEditorChanged) - { - CreateCustomShaderEditorIfNeeded(material.shader); - if (shaderChanged) - { - m_Shader = material.shader; - OnShaderChanged(); - } - InspectorWindow.RepaintAllInspectors(); - } - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - CheckSetup(); - DetectShaderEditorNeedsUpdate(); - - if (isVisible && m_Shader != null && !HasMultipleMixedShaderValues()) - { - // Show Material properties - if (PropertiesGUI()) - { - PropertiesChanged(); - } - } - } - - void CheckSetup() - { - if (!m_CheckSetup || m_Shader == null) - return; - - m_CheckSetup = false; - if (m_CustomShaderGUI == null && !IsMaterialEditor(m_Shader.customEditor)) - { - 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, m_Shader.customEditor); - } - } - - // A minimal list of settings to be shown in the Asset Store preview inspector - internal override void OnAssetStoreInspectorGUI() - { - OnInspectorGUI(); - } - - public void PropertiesChanged() - { - // @TODO: Show performance warnings for multi-selections too? - m_InfoMessage = null; - if (targets.Length == 1) - m_InfoMessage = Utils.PerformanceChecks.CheckMaterial(target as Material, EditorUserBuildSettings.activeBuildTarget); - } - - protected virtual void OnShaderChanged() - { - } - - protected override void OnHeaderGUI() - { - const float spaceForFoldoutArrow = 10f; - Rect titleRect = DrawHeaderGUI(this, targetTitle, forceVisible ? 0 : spaceForFoldoutArrow); - int id = GUIUtility.GetControlID(45678, FocusType.Passive); - - if (!forceVisible) - { - Rect renderRect = EditorGUI.GetInspectorTitleBarObjectFoldoutRenderRect(titleRect); - renderRect.y = titleRect.yMax - 17f; // align with bottom - bool newVisible = EditorGUI.DoObjectFoldout(m_IsVisible, titleRect, renderRect, targets, id); - - // Toggle visibility - if (newVisible != m_IsVisible) - { - m_IsVisible = newVisible; - InternalEditorUtility.SetIsInspectorExpanded(target, newVisible); - } - } - } - - internal override void OnHeaderControlsGUI() - { - serializedObject.Update(); - - using (new EditorGUI.DisabledScope(!IsEnabled())) - { - EditorGUIUtility.labelWidth = 50; - - // Shader selection dropdown - ShaderPopup("MiniPulldown"); - - // Edit button for custom shaders - if (m_Shader != null && HasMultipleMixedShaderValues() && (m_Shader.hideFlags & HideFlags.DontSave) == 0) - { - if (GUILayout.Button("Edit...", EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - AssetDatabase.OpenAsset(m_Shader); - } - } - } - - // -------- obsolete helper functions to get/set material values - - [System.Obsolete("Use GetMaterialProperty instead.")] - public float GetFloat(string propertyName, out bool hasMixedValue) - { - hasMixedValue = false; - float f = ((Material)targets[0]).GetFloat(propertyName); - for (int i = 1; i < targets.Length; i++) - { - if (((Material)targets[i]).GetFloat(propertyName) != f) - { - hasMixedValue = true; - break; - } - } - return f; - } - - [System.Obsolete("Use MaterialProperty instead.")] - public void SetFloat(string propertyName, float value) - { - foreach (Material material in targets) - material.SetFloat(propertyName, value); - } - - [System.Obsolete("Use GetMaterialProperty instead.")] - public Color GetColor(string propertyName, out bool hasMixedValue) - { - hasMixedValue = false; - Color f = ((Material)targets[0]).GetColor(propertyName); - for (int i = 1; i < targets.Length; i++) - if (((Material)targets[i]).GetColor(propertyName) != f) { hasMixedValue = true; break; } - return f; - } - - [System.Obsolete("Use MaterialProperty instead.")] - public void SetColor(string propertyName, Color value) - { - foreach (Material material in targets) - material.SetColor(propertyName, value); - } - - [System.Obsolete("Use GetMaterialProperty instead.")] - public Vector4 GetVector(string propertyName, out bool hasMixedValue) - { - hasMixedValue = false; - Vector4 f = ((Material)targets[0]).GetVector(propertyName); - for (int i = 1; i < targets.Length; i++) - if (((Material)targets[i]).GetVector(propertyName) != f) { hasMixedValue = true; break; } - return f; - } - - [System.Obsolete("Use MaterialProperty instead.")] - public void SetVector(string propertyName, Vector4 value) - { - foreach (Material material in targets) - material.SetVector(propertyName, value); - } - - [System.Obsolete("Use GetMaterialProperty instead.")] - public Texture GetTexture(string propertyName, out bool hasMixedValue) - { - hasMixedValue = false; - Texture f = ((Material)targets[0]).GetTexture(propertyName); - for (int i = 1; i < targets.Length; i++) - if (((Material)targets[i]).GetTexture(propertyName) != f) { hasMixedValue = true; break; } - return f; - } - - [System.Obsolete("Use MaterialProperty instead.")] - public void SetTexture(string propertyName, Texture value) - { - foreach (Material material in targets) - material.SetTexture(propertyName, value); - } - - [System.Obsolete("Use MaterialProperty instead.")] - public Vector2 GetTextureScale(string propertyName, out bool hasMixedValueX, out bool hasMixedValueY) - { - hasMixedValueX = false; - hasMixedValueY = false; - Vector2 f = ((Material)targets[0]).GetTextureScale(propertyName); - for (int i = 1; i < targets.Length; i++) - { - Vector2 f2 = ((Material)targets[i]).GetTextureScale(propertyName); - if (f2.x != f.x) { hasMixedValueX = true; } - if (f2.y != f.y) { hasMixedValueY = true; } - if (hasMixedValueX && hasMixedValueY) - break; - } - return f; - } - - [System.Obsolete("Use MaterialProperty instead.")] - public Vector2 GetTextureOffset(string propertyName, out bool hasMixedValueX, out bool hasMixedValueY) - { - hasMixedValueX = false; - hasMixedValueY = false; - Vector2 f = ((Material)targets[0]).GetTextureOffset(propertyName); - for (int i = 1; i < targets.Length; i++) - { - Vector2 f2 = ((Material)targets[i]).GetTextureOffset(propertyName); - if (f2.x != f.x) { hasMixedValueX = true; } - if (f2.y != f.y) { hasMixedValueY = true; } - if (hasMixedValueX && hasMixedValueY) - break; - } - return f; - } - - [System.Obsolete("Use MaterialProperty instead.")] - public void SetTextureScale(string propertyName, Vector2 value, int coord) - { - foreach (Material material in targets) - { - Vector2 f = material.GetTextureScale(propertyName); - f[coord] = value[coord]; - material.SetTextureScale(propertyName, f); - } - } - - [System.Obsolete("Use MaterialProperty instead.")] - public void SetTextureOffset(string propertyName, Vector2 value, int coord) - { - foreach (Material material in targets) - { - Vector2 f = material.GetTextureOffset(propertyName); - f[coord] = value[coord]; - material.SetTextureOffset(propertyName, f); - } - } - - // -------- helper functions to display common material controls - - // The 'Property' methods that accept GUIContent are internal with different name to avoid - // breaking backwards compatibility caused by adding overloads: - // 'RangeProperty(prop, null);' would cause a compile error because of ambigious overloads. - - public float RangeProperty(MaterialProperty prop, string label) - { - return RangePropertyInternal(prop, new GUIContent(label)); - } - - internal float RangePropertyInternal(MaterialProperty prop, GUIContent label) - { - Rect r = GetPropertyRect(prop, label, true); - return RangePropertyInternal(r, prop, label); - } - - public float RangeProperty(Rect position, MaterialProperty prop, string label) - { - return RangePropertyInternal(position, prop, new GUIContent(label)); - } - - internal float RangePropertyInternal(Rect position, MaterialProperty prop, GUIContent label) - { - float power = (prop.name == "_Shininess") ? 5f : 1f; - return DoPowerRangeProperty(position, prop, label, power); - } - - internal static float DoPowerRangeProperty(Rect position, MaterialProperty prop, GUIContent label, float power) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = prop.hasMixedValue; - - // For range properties we want to show the slider so we adjust label width to use default width (setting it to 0) - // See SetDefaultGUIWidths where we set: EditorGUIUtility.labelWidth = GUIClip.visibleRect.width - EditorGUIUtility.fieldWidth - 17; - float oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 0f; - - float newValue = EditorGUI.PowerSlider(position, label, prop.floatValue, prop.rangeLimits.x, prop.rangeLimits.y, power); - EditorGUI.showMixedValue = false; - - EditorGUIUtility.labelWidth = oldLabelWidth; - - if (EditorGUI.EndChangeCheck()) - prop.floatValue = newValue; - - return prop.floatValue; - } - - internal static int DoIntRangeProperty(Rect position, MaterialProperty prop, GUIContent label) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = prop.hasMixedValue; - - // For range properties we want to show the slider so we adjust label width to use default width (setting it to 0) - // See SetDefaultGUIWidths where we set: EditorGUIUtility.labelWidth = GUIClip.visibleRect.width - EditorGUIUtility.fieldWidth - 17; - float oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 0f; - - int newValue = EditorGUI.IntSlider(position, label, (int)prop.floatValue, (int)prop.rangeLimits.x, (int)prop.rangeLimits.y); - EditorGUI.showMixedValue = false; - - EditorGUIUtility.labelWidth = oldLabelWidth; - - if (EditorGUI.EndChangeCheck()) - prop.floatValue = (float)newValue; - - return (int)prop.floatValue; - } - - public float FloatProperty(MaterialProperty prop, string label) - { - return FloatPropertyInternal(prop, new GUIContent(label)); - } - - internal float FloatPropertyInternal(MaterialProperty prop, GUIContent label) - { - Rect r = GetPropertyRect(prop, label, true); - return FloatPropertyInternal(r, prop, label); - } - - public float FloatProperty(Rect position, MaterialProperty prop, string label) - { - return FloatPropertyInternal(position, prop, new GUIContent(label)); - } - - internal float FloatPropertyInternal(Rect position, MaterialProperty prop, GUIContent label) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = prop.hasMixedValue; - float newValue = EditorGUI.FloatField(position, label, prop.floatValue); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - prop.floatValue = newValue; - - return prop.floatValue; - } - - public Color ColorProperty(MaterialProperty prop, string label) - { - return ColorPropertyInternal(prop, new GUIContent(label)); - } - - internal Color ColorPropertyInternal(MaterialProperty prop, GUIContent label) - { - Rect r = GetPropertyRect(prop, label, true); - return ColorPropertyInternal(r, prop, label); - } - - public Color ColorProperty(Rect position, MaterialProperty prop, string label) - { - return ColorPropertyInternal(position, prop, new GUIContent(label)); - } - - internal Color ColorPropertyInternal(Rect position, MaterialProperty prop, GUIContent label) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = prop.hasMixedValue; - bool isHDR = ((prop.flags & MaterialProperty.PropFlags.HDR) != 0); - bool showAlpha = true; - Color newValue = EditorGUI.ColorField(position, label, prop.colorValue, true, showAlpha, isHDR); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - prop.colorValue = newValue; - - return prop.colorValue; - } - - public Vector4 VectorProperty(MaterialProperty prop, string label) - { - Rect r = GetPropertyRect(prop, label, true); - return VectorProperty(r, prop, label); - } - - public Vector4 VectorProperty(Rect position, MaterialProperty prop, string label) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = prop.hasMixedValue; - - // We want to make room for the field in case it's drawn on the same line as the label - // Set label width to default width (zero) temporarily - var oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 0f; - - Vector4 newValue = EditorGUI.Vector4Field(position, label, prop.vectorValue); - - EditorGUIUtility.labelWidth = oldLabelWidth; - - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - prop.vectorValue = newValue; - - return prop.vectorValue; - } - - // Using GUILayout - public void TextureScaleOffsetProperty(MaterialProperty property) - { - Rect rect = EditorGUILayout.GetControlRect(true, 2 * kLineHeight, EditorStyles.layerMaskField); - TextureScaleOffsetProperty(rect, property, false); - } - - // Returns height used - public float TextureScaleOffsetProperty(Rect position, MaterialProperty property) - { - return TextureScaleOffsetProperty(position, property, true); - } - - // Returns height used - public float TextureScaleOffsetProperty(Rect position, MaterialProperty property, bool partOfTexturePropertyControl) - { - BeginAnimatedCheck(position, property); - - EditorGUI.BeginChangeCheck(); - // Mixed value mask is 4 bits for the uv offset & scale (First bit is for the texture itself) - int mixedValuemask = property.mixedValueMask >> 1; - Vector4 scaleAndOffset = TextureScaleOffsetProperty(position, property.textureScaleAndOffset, mixedValuemask, partOfTexturePropertyControl); - - if (EditorGUI.EndChangeCheck()) - property.textureScaleAndOffset = scaleAndOffset; - - EndAnimatedCheck(); - return 2 * kLineHeight; - } - - private Texture TexturePropertyBody(Rect position, MaterialProperty prop) - { - if (prop.type != MaterialProperty.PropType.Texture) - { - throw new ArgumentException(string.Format("The MaterialProperty '{0}' should be of type 'Texture' (its type is '{1})'", prop.name, prop.type)); - } - - m_DesiredTexdim = prop.textureDimension; - System.Type t = MaterialEditor.GetTextureTypeFromDimension(m_DesiredTexdim); - - // Why are we disabling the GUI in Animation Mode here? - // If it's because object references can't be changed, shouldn't it be done in ObjectField instead? - bool wasEnabled = GUI.enabled; - - EditorGUI.BeginChangeCheck(); - if ((prop.flags & MaterialProperty.PropFlags.PerRendererData) != 0) - GUI.enabled = false; - if ((prop.flags & MaterialProperty.PropFlags.NonModifiableTextureData) != 0) - GUI.enabled = false; - - EditorGUI.showMixedValue = prop.hasMixedValue; - int controlID = GUIUtility.GetControlID(12354, FocusType.Keyboard, position); - var newValue = EditorGUI.DoObjectField(position, position, controlID, prop.textureValue, t, null, TextureValidator, false) as Texture; - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - prop.textureValue = newValue; - - GUI.enabled = wasEnabled; - - return prop.textureValue; - } - - public Texture TextureProperty(MaterialProperty prop, string label) - { - bool scaleOffset = ((prop.flags & MaterialProperty.PropFlags.NoScaleOffset) == 0); - return TextureProperty(prop, label, scaleOffset); - } - - public Texture TextureProperty(MaterialProperty prop, string label, bool scaleOffset) - { - Rect r = GetPropertyRect(prop, label, true); - return TextureProperty(r, prop, label, scaleOffset); - } - - public bool HelpBoxWithButton(GUIContent messageContent, GUIContent buttonContent) - { - const float kButtonWidth = 60f; - const float kSpacing = 5f; - const float kButtonHeight = 20f; - - // Reserve size of wrapped text - Rect contentRect = GUILayoutUtility.GetRect(messageContent, EditorStyles.helpBox); - // Reserve size of button - GUILayoutUtility.GetRect(1, kButtonHeight + kSpacing); - - // Render background box with text at full height - contentRect.height += kButtonHeight + kSpacing; - GUI.Label(contentRect, messageContent, EditorStyles.helpBox); - - // Button (align lower right) - Rect buttonRect = new Rect(contentRect.xMax - kButtonWidth - 4f, contentRect.yMax - kButtonHeight - 4f, kButtonWidth, kButtonHeight); - return GUI.Button(buttonRect, buttonContent); - } - - public void TextureCompatibilityWarning(MaterialProperty prop) - { - if (InternalEditorUtility.BumpMapTextureNeedsFixing(prop)) - { - if (HelpBoxWithButton( - EditorGUIUtility.TrTextContent("This texture is not marked as a normal map"), - EditorGUIUtility.TrTextContent("Fix Now"))) - { - InternalEditorUtility.FixNormalmapTexture(prop); - } - } - } - - public Texture TexturePropertyMiniThumbnail(Rect position, MaterialProperty prop, string label, string tooltip) - { - BeginAnimatedCheck(position, prop); - Rect thumbRect, labelRect; - EditorGUI.GetRectsForMiniThumbnailField(position, out thumbRect, out labelRect); - EditorGUI.HandlePrefixLabel(position, labelRect, new GUIContent(label, tooltip), 0, EditorStyles.label); - EndAnimatedCheck(); - - Texture retValue = TexturePropertyBody(thumbRect, prop); - - Rect warningPosition = position; - warningPosition.y += position.height; - warningPosition.height = kMiniWarningMessageHeight; - - TextureCompatibilityWarning(prop); - - return retValue; - } - - public Rect GetTexturePropertyCustomArea(Rect position) - { - EditorGUI.indentLevel++; - position.height = GetTextureFieldHeight(); - Rect scaleOffsetRect = position; - scaleOffsetRect.yMin += EditorGUI.kSingleLineHeight; - scaleOffsetRect.xMax -= EditorGUIUtility.fieldWidth + 2; - scaleOffsetRect = EditorGUI.IndentedRect(scaleOffsetRect); - EditorGUI.indentLevel--; - return scaleOffsetRect; - } - - public Texture TextureProperty(Rect position, MaterialProperty prop, string label) - { - bool scaleOffset = ((prop.flags & MaterialProperty.PropFlags.NoScaleOffset) == 0); - return TextureProperty(position, prop, label, scaleOffset); - } - - public Texture TextureProperty(Rect position, MaterialProperty prop, string label, bool scaleOffset) - { - return TextureProperty(position, prop, label, string.Empty, scaleOffset); - } - - public Texture TextureProperty(Rect position, MaterialProperty prop, string label, string tooltip, bool scaleOffset) - { - // Label - EditorGUI.PrefixLabel(position, new GUIContent(label, tooltip)); - - // Texture slot - position.height = GetTextureFieldHeight(); - Rect texPos = position; - texPos.xMin = texPos.xMax - EditorGUIUtility.fieldWidth; - Texture value = TexturePropertyBody(texPos, prop); - - // UV scale and offset - if (scaleOffset) - { - TextureScaleOffsetProperty(GetTexturePropertyCustomArea(position), prop); - } - - // Potential warning help boxes - { - GUILayout.Space(-kSpacingUnderTexture); - TextureCompatibilityWarning(prop); - GUILayout.Space(kSpacingUnderTexture); - } - return value; - } - - public static Vector4 TextureScaleOffsetProperty(Rect position, Vector4 scaleOffset) - { - return TextureScaleOffsetProperty(position, scaleOffset, 0, false); - } - - public static Vector4 TextureScaleOffsetProperty(Rect position, Vector4 scaleOffset, bool partOfTexturePropertyControl) - { - return TextureScaleOffsetProperty(position, scaleOffset, 0, partOfTexturePropertyControl); - } - - internal static Vector4 TextureScaleOffsetProperty(Rect position, Vector4 scaleOffset, int mixedValueMask, bool partOfTexturePropertyControl) - { - Vector2 tiling = new Vector2(scaleOffset.x, scaleOffset.y); - Vector2 offset = new Vector2(scaleOffset.z, scaleOffset.w); - - float labelWidth = EditorGUIUtility.labelWidth; - float controlStartX = position.x + labelWidth; - float labelStartX = position.x + EditorGUI.indent; - - // Temporarily reset the indent level as it was already used above to compute the positions of the label and control. See issue 946082. - int oldIndentLevel = EditorGUI.indentLevel; - - EditorGUI.indentLevel = 0; - - if (partOfTexturePropertyControl) - { - labelWidth = 65; - controlStartX = position.x + labelWidth; - labelStartX = position.x; - position.y = position.yMax - 2 * kLineHeight; // align with large texture thumb bottom - } - - // Tiling - Rect labelRect = new Rect(labelStartX, position.y, labelWidth, kLineHeight); - Rect valueRect = new Rect(controlStartX, position.y, position.width - labelWidth, kLineHeight); - EditorGUI.PrefixLabel(labelRect, s_TilingText); - tiling = EditorGUI.Vector2Field(valueRect, GUIContent.none, tiling); - - // Offset - labelRect.y += kLineHeight; - valueRect.y += kLineHeight; - EditorGUI.PrefixLabel(labelRect, s_OffsetText); - offset = EditorGUI.Vector2Field(valueRect, GUIContent.none, offset); - - // Restore the indent level - EditorGUI.indentLevel = oldIndentLevel; - - return new Vector4(tiling.x, tiling.y, offset.x, offset.y); - } - - public float GetPropertyHeight(MaterialProperty prop) - { - return GetPropertyHeight(prop, prop.displayName); - } - - public float GetPropertyHeight(MaterialProperty prop, string label) - { - // has custom drawers? - float handlerHeight = 0f; - MaterialPropertyHandler handler = MaterialPropertyHandler.GetHandler(((Material)target).shader, prop.name); - if (handler != null) - { - handlerHeight = handler.GetPropertyHeight(prop, label ?? prop.displayName, this); - // if we have a property drawer (and not just decorators), exit now and don't add default height - if (handler.propertyDrawer != null) - return handlerHeight; - } - - // otherwise, return default height - return handlerHeight + GetDefaultPropertyHeight(prop); - } - - private static float GetTextureFieldHeight() - { - return EditorGUI.kObjectFieldThumbnailHeight; - } - - public static float GetDefaultPropertyHeight(MaterialProperty prop) - { - if (prop.type == MaterialProperty.PropType.Vector) - return EditorGUI.kStructHeaderLineHeight + EditorGUI.kSingleLineHeight; - - if (prop.type == MaterialProperty.PropType.Texture) - return GetTextureFieldHeight() + kSpacingUnderTexture; - - return EditorGUI.kSingleLineHeight; - } - - private Rect GetPropertyRect(MaterialProperty prop, GUIContent label, bool ignoreDrawer) - { - return GetPropertyRect(prop, label.text, ignoreDrawer); - } - - private Rect GetPropertyRect(MaterialProperty prop, string label, bool ignoreDrawer) - { - float handlerHeight = 0f; - if (!ignoreDrawer) - { - MaterialPropertyHandler handler = MaterialPropertyHandler.GetHandler(((Material)target).shader, prop.name); - if (handler != null) - { - handlerHeight = handler.GetPropertyHeight(prop, label ?? prop.displayName, this); - // if we have a property drawer (and not just decorators), exit now and don't add default height - if (handler.propertyDrawer != null) - return EditorGUILayout.GetControlRect(true, handlerHeight, EditorStyles.layerMaskField); - } - } - - return EditorGUILayout.GetControlRect(true, handlerHeight + GetDefaultPropertyHeight(prop), EditorStyles.layerMaskField); - } - - public void BeginAnimatedCheck(Rect totalPosition, MaterialProperty prop) - { - if (rendererForAnimationMode == null) - return; - - s_AnimatedCheckStack.Push(new AnimatedCheckData(prop, totalPosition, GUI.backgroundColor)); - - Color overrideColor; - if (MaterialAnimationUtility.OverridePropertyColor(prop, rendererForAnimationMode, out overrideColor)) - GUI.backgroundColor = overrideColor; - } - - public void BeginAnimatedCheck(MaterialProperty prop) - { - BeginAnimatedCheck(Rect.zero, prop); - } - - public void EndAnimatedCheck() - { - if (rendererForAnimationMode == null) - return; - - AnimatedCheckData data = s_AnimatedCheckStack.Pop(); - if (Event.current.type == EventType.ContextClick && data.totalPosition.Contains(Event.current.mousePosition)) - { - DoPropertyContextMenu(data.property); - } - - GUI.backgroundColor = data.color; - } - - private void DoPropertyContextMenu(MaterialProperty prop) - { - if (contextualPropertyMenu != null) - { - GenericMenu pm = new GenericMenu(); - contextualPropertyMenu(pm, prop, m_RenderersForAnimationMode); - - if (pm.GetItemCount() > 0) - pm.ShowAsContext(); - } - } - - public void ShaderProperty(MaterialProperty prop, string label) - { - ShaderProperty(prop, new GUIContent(label)); - } - - public void ShaderProperty(MaterialProperty prop, GUIContent label) - { - ShaderProperty(prop, label, 0); - } - - public void ShaderProperty(MaterialProperty prop, string label, int labelIndent) - { - ShaderProperty(prop, new GUIContent(label), labelIndent); - } - - public void ShaderProperty(MaterialProperty prop, GUIContent label, int labelIndent) - { - Rect r = GetPropertyRect(prop, label, false); - ShaderProperty(r, prop, label, labelIndent); - } - - public void ShaderProperty(Rect position, MaterialProperty prop, string label) - { - ShaderProperty(position, prop, new GUIContent(label)); - } - - public void ShaderProperty(Rect position, MaterialProperty prop, GUIContent label) - { - ShaderProperty(position, prop, label, 0); - } - - public void ShaderProperty(Rect position, MaterialProperty prop, string label, int labelIndent) - { - ShaderProperty(position, prop, new GUIContent(label), labelIndent); - } - - public void ShaderProperty(Rect position, MaterialProperty prop, GUIContent label, int labelIndent) - { - BeginAnimatedCheck(position, prop); - EditorGUI.indentLevel += labelIndent; - - ShaderPropertyInternal(position, prop, label); - - EditorGUI.indentLevel -= labelIndent; - EndAnimatedCheck(); - } - - public void LightmapEmissionProperty() - { - LightmapEmissionProperty(0); - } - - public void LightmapEmissionProperty(int labelIndent) - { - Rect r = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.layerMaskField); - LightmapEmissionProperty(r, labelIndent); - } - - static MaterialGlobalIlluminationFlags GetGlobalIlluminationFlags(MaterialGlobalIlluminationFlags flags) - { - MaterialGlobalIlluminationFlags newFlags = MaterialGlobalIlluminationFlags.None; - if ((flags & MaterialGlobalIlluminationFlags.RealtimeEmissive) != 0) - newFlags = MaterialGlobalIlluminationFlags.RealtimeEmissive; - else if ((flags & MaterialGlobalIlluminationFlags.BakedEmissive) != 0) - newFlags = MaterialGlobalIlluminationFlags.BakedEmissive; - - return newFlags; - } - - public void LightmapEmissionProperty(Rect position, int labelIndent) - { - EditorGUI.indentLevel += labelIndent; - - Object[] materials = targets; - Material firstMaterial = (Material)target; - - // Calculate isMixed - MaterialGlobalIlluminationFlags giFlags = GetGlobalIlluminationFlags(firstMaterial.globalIlluminationFlags); - bool isMixed = false; - for (int i = 1; i < materials.Length; i++) - { - Material material = (Material)materials[i]; - - if (GetGlobalIlluminationFlags(material.globalIlluminationFlags) != giFlags) - isMixed = true; - } - - EditorGUI.BeginChangeCheck(); - - // Show popup - EditorGUI.showMixedValue = isMixed; - giFlags = (MaterialGlobalIlluminationFlags)EditorGUI.IntPopup(position, Styles.lightmapEmissiveLabel, (int)giFlags, Styles.lightmapEmissiveStrings, Styles.lightmapEmissiveValues); - EditorGUI.showMixedValue = false; - - // Apply flags. But only the part that this tool modifies (RealtimeEmissive, BakedEmissive, None) - if (EditorGUI.EndChangeCheck()) - { - foreach (Material material in materials) - { - MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags; - - flags &= ~(MaterialGlobalIlluminationFlags.RealtimeEmissive | MaterialGlobalIlluminationFlags.BakedEmissive); - flags |= giFlags; - - material.globalIlluminationFlags = flags; - } - } - - EditorGUI.indentLevel -= labelIndent; - } - - public bool EmissionEnabledProperty() - { - Material[] materials = Array.ConvertAll(targets, (Object o) => { return (Material)o; }); - - m_LightmapSettings.Update(); - - MaterialGlobalIlluminationFlags defaultEnabled = m_EnabledRealtimeGI.boolValue ? MaterialGlobalIlluminationFlags.RealtimeEmissive - : (m_EnabledBakedGI.boolValue ? MaterialGlobalIlluminationFlags.BakedEmissive : MaterialGlobalIlluminationFlags.None); - - // Calculate isMixed - bool enabled = materials[0].globalIlluminationFlags != MaterialGlobalIlluminationFlags.EmissiveIsBlack; - bool isMixed = false; - for (int i = 1; i < materials.Length; i++) - { - if ((materials[i].globalIlluminationFlags != MaterialGlobalIlluminationFlags.EmissiveIsBlack) != enabled) - { - isMixed = true; - break; - } - } - - // initial checkbox for enabling/disabling emission - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = isMixed; - enabled = EditorGUILayout.Toggle(Styles.emissionLabel, enabled); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - foreach (Material mat in materials) - { - mat.globalIlluminationFlags = enabled ? defaultEnabled : MaterialGlobalIlluminationFlags.EmissiveIsBlack; - } - return enabled; - } - return !isMixed && enabled; - } - - public static void FixupEmissiveFlag(Material mat) - { - if (mat == null) - throw new ArgumentNullException("mat"); - - mat.globalIlluminationFlags = FixupEmissiveFlag(mat.GetColor("_EmissionColor"), mat.globalIlluminationFlags); - } - - public static MaterialGlobalIlluminationFlags FixupEmissiveFlag(Color col, MaterialGlobalIlluminationFlags flags) - { - if ((flags & MaterialGlobalIlluminationFlags.BakedEmissive) != 0 && col.maxColorComponent == 0.0f) // flag black baked - flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack; - else if (flags != MaterialGlobalIlluminationFlags.EmissiveIsBlack) // clear baked flag on everything else, unless it's explicity disabled - flags &= MaterialGlobalIlluminationFlags.AnyEmissive; - return flags; - } - - public void LightmapEmissionFlagsProperty(int indent, bool enabled) - { - Material[] materials = Array.ConvertAll(targets, (Object o) => { return (Material)o; }); - - // Calculate isMixed - MaterialGlobalIlluminationFlags any_em = MaterialGlobalIlluminationFlags.AnyEmissive; - MaterialGlobalIlluminationFlags giFlags = materials[0].globalIlluminationFlags & any_em; - bool isMixed = false; - for (int i = 1; i < materials.Length; i++) - { - isMixed = isMixed || (materials[i].globalIlluminationFlags & any_em) != giFlags; - } - - EditorGUI.BeginChangeCheck(); - - // Show popup - EditorGUI.showMixedValue = isMixed; - EditorGUI.indentLevel += indent; - int[] shortvals = { Styles.lightmapEmissiveValues[0], Styles.lightmapEmissiveValues[1] }; - GUIContent[] shortstrings = { Styles.lightmapEmissiveStrings[0], Styles.lightmapEmissiveStrings[1] }; - giFlags = (MaterialGlobalIlluminationFlags)EditorGUILayout.IntPopup(Styles.lightmapEmissiveLabel, (int)giFlags, shortstrings, shortvals); - EditorGUI.indentLevel -= indent; - EditorGUI.showMixedValue = false; - - // Apply flags. But only the part that this tool modifies (RealtimeEmissive, BakedEmissive, None) - bool applyFlags = EditorGUI.EndChangeCheck(); - foreach (Material mat in materials) - { - mat.globalIlluminationFlags = applyFlags ? giFlags : mat.globalIlluminationFlags; - FixupEmissiveFlag(mat); - } - } - - void ShaderPropertyInternal(Rect position, MaterialProperty prop, GUIContent label) - { - // Use custom property drawers if needed - MaterialPropertyHandler handler = MaterialPropertyHandler.GetHandler(((Material)target).shader, prop.name); - if (handler != null) - { - handler.OnGUI(ref position, prop, label.text != null ? label : new GUIContent(prop.displayName), this); - // If we had a property drawer (and not just decorators), exit now and don't draw default UI. - if (handler.propertyDrawer != null) - return; - } - - DefaultShaderPropertyInternal(position, prop, label); - } - - public void DefaultShaderProperty(MaterialProperty prop, string label) - { - DefaultShaderPropertyInternal(prop, new GUIContent(label)); - } - - internal void DefaultShaderPropertyInternal(MaterialProperty prop, GUIContent label) - { - Rect r = GetPropertyRect(prop, label, true); - DefaultShaderPropertyInternal(r, prop, label); - } - - public void DefaultShaderProperty(Rect position, MaterialProperty prop, string label) - { - DefaultShaderPropertyInternal(position, prop, new GUIContent(label)); - } - - internal void DefaultShaderPropertyInternal(Rect position, MaterialProperty prop, GUIContent label) - { - switch (prop.type) - { - case MaterialProperty.PropType.Range: // float ranges - RangePropertyInternal(position, prop, label); - break; - case MaterialProperty.PropType.Float: // floats - FloatPropertyInternal(position, prop, label); - break; - case MaterialProperty.PropType.Color: // colors - ColorPropertyInternal(position, prop, label); - break; - case MaterialProperty.PropType.Texture: // textures - TextureProperty(position, prop, label.text); - break; - case MaterialProperty.PropType.Vector: // vectors - VectorProperty(position, prop, label.text); - break; - default: - GUI.Label(position, "Unknown property type: " + prop.name + ": " + (int)prop.type); - break; - } - } - - // -------- obsolete versions of common controls - - - [System.Obsolete("Use RangeProperty with MaterialProperty instead.")] - public float RangeProperty(string propertyName, string label, float v2, float v3) - { - MaterialProperty prop = GetMaterialProperty(targets, propertyName); - return RangeProperty(prop, label); - } - - [System.Obsolete("Use FloatProperty with MaterialProperty instead.")] - public float FloatProperty(string propertyName, string label) - { - MaterialProperty prop = GetMaterialProperty(targets, propertyName); - return FloatProperty(prop, label); - } - - [System.Obsolete("Use ColorProperty with MaterialProperty instead.")] - public Color ColorProperty(string propertyName, string label) - { - MaterialProperty prop = GetMaterialProperty(targets, propertyName); - return ColorProperty(prop, label); - } - - [System.Obsolete("Use VectorProperty with MaterialProperty instead.")] - public Vector4 VectorProperty(string propertyName, string label) - { - MaterialProperty prop = GetMaterialProperty(targets, propertyName); - return VectorProperty(prop, label); - } - - [System.Obsolete("Use TextureProperty with MaterialProperty instead.")] - public Texture TextureProperty(string propertyName, string label, ShaderUtil.ShaderPropertyTexDim texDim) - { - MaterialProperty prop = GetMaterialProperty(targets, propertyName); - return TextureProperty(prop, label); - } - - [System.Obsolete("Use TextureProperty with MaterialProperty instead.")] - public Texture TextureProperty(string propertyName, string label, ShaderUtil.ShaderPropertyTexDim texDim, bool scaleOffset) - { - MaterialProperty prop = GetMaterialProperty(targets, propertyName); - return TextureProperty(prop, label, scaleOffset); - } - - [System.Obsolete("Use ShaderProperty that takes MaterialProperty parameter instead.")] - public void ShaderProperty(Shader shader, int propertyIndex) - { - MaterialProperty prop = GetMaterialProperty(targets, propertyIndex); - ShaderProperty(prop, prop.displayName); - } - - // -------- other functionality - - public static MaterialProperty[] GetMaterialProperties(Object[] mats) - { - if (mats == null) - throw new ArgumentNullException("mats"); - if (Array.IndexOf(mats, null) >= 0) - throw new ArgumentException("List of materials contains null"); - return ShaderUtil.GetMaterialProperties(mats); - } - - public static MaterialProperty GetMaterialProperty(Object[] mats, string name) - { - if (mats == null) - throw new ArgumentNullException("mats"); - if (Array.IndexOf(mats, null) >= 0) - throw new ArgumentException("List of materials contains null"); - return ShaderUtil.GetMaterialProperty(mats, name); - } - - public static MaterialProperty GetMaterialProperty(Object[] mats, int propertyIndex) - { - if (mats == null) - throw new ArgumentNullException("mats"); - if (Array.IndexOf(mats, null) >= 0) - throw new ArgumentException("List of materials contains null"); - return ShaderUtil.GetMaterialProperty_Index(mats, propertyIndex); - } - - class ForwardApplyMaterialModification - { - readonly Renderer[] renderers; - bool isMaterialEditable; - - public ForwardApplyMaterialModification(Renderer[] r, bool inIsMaterialEditable) - { - renderers = r; - isMaterialEditable = inIsMaterialEditable; - } - - public bool DidModifyAnimationModeMaterialProperty(MaterialProperty property, int changedMask, object previousValue) - { - bool didModify = false; - foreach (Renderer renderer in renderers) - { - didModify = didModify | MaterialAnimationUtility.ApplyMaterialModificationToAnimationRecording(property, changedMask, renderer, previousValue); - } - - if (didModify) - return true; - - // If the material is not editable, - // then we explicitly make sure that things that these properties arecan not be recorded are not going to be applied to the material - return !isMaterialEditable; - } - } - - static Renderer[] GetAssociatedRenderersFromInspector() - { - List renderers = new List(); - if (InspectorWindow.s_CurrentInspectorWindow) - { - Editor[] editors = InspectorWindow.s_CurrentInspectorWindow.tracker.activeEditors; - foreach (var editor in editors) - { - foreach (Object target in editor.targets) - { - var renderer = target as Renderer; - if (renderer) - renderers.Add(renderer); - } - } - } - - return renderers.ToArray(); - } - - public static Renderer PrepareMaterialPropertiesForAnimationMode(MaterialProperty[] properties, bool isMaterialEditable) - { - Renderer[] renderers = PrepareMaterialPropertiesForAnimationMode(properties, GetAssociatedRenderersFromInspector(), isMaterialEditable); - return (renderers != null && renderers.Length > 0) ? renderers[0] : null; - } - - internal static Renderer PrepareMaterialPropertiesForAnimationMode(MaterialProperty[] properties, Renderer renderer, bool isMaterialEditable) - { - Renderer[] renderers = PrepareMaterialPropertiesForAnimationMode(properties, new Renderer[] {renderer}, isMaterialEditable); - return (renderers != null && renderers.Length > 0) ? renderers[0] : null; - } - - internal static Renderer[] PrepareMaterialPropertiesForAnimationMode(MaterialProperty[] properties, Renderer[] renderers, bool isMaterialEditable) - { - bool isInAnimationMode = AnimationMode.InAnimationMode(); - - if (renderers != null && renderers.Length > 0) - { - var callback = new ForwardApplyMaterialModification(renderers, isMaterialEditable); - var block = new MaterialPropertyBlock(); - - renderers[0].GetPropertyBlock(block); - foreach (MaterialProperty prop in properties) - { - prop.ReadFromMaterialPropertyBlock(block); - if (isInAnimationMode) - prop.applyPropertyCallback = callback.DidModifyAnimationModeMaterialProperty; - } - } - - if (isInAnimationMode) - return renderers; - else - return null; - } - - public void SetDefaultGUIWidths() - { - EditorGUIUtility.fieldWidth = EditorGUI.kObjectFieldThumbnailHeight; - EditorGUIUtility.labelWidth = GUIClip.visibleRect.width - EditorGUIUtility.fieldWidth - 17; - } - - private bool IsMaterialEditor(string customEditorName) - { - string unityEditorFullName = "UnityEditor." + customEditorName; // for convenience: adding UnityEditor namespace is not needed in the shader - - foreach (var assembly in EditorAssemblies.loadedAssemblies) - { - Type[] types = AssemblyHelper.GetTypesFromAssembly(assembly); - foreach (var type in types) - { - if (type.FullName.Equals(customEditorName, StringComparison.Ordinal) || - type.FullName.Equals(unityEditorFullName, StringComparison.Ordinal)) - { - if (typeof(MaterialEditor).IsAssignableFrom(type)) - return true; - } - } - } - return false; - } - - void CreateCustomShaderEditorIfNeeded(Shader shader) - { - if (shader == null || string.IsNullOrEmpty(shader.customEditor)) - { - m_CustomEditorClassName = ""; - m_CustomShaderGUI = null; - return; - } - if (m_CustomEditorClassName == shader.customEditor) - return; - - m_CustomEditorClassName = shader.customEditor; - m_CustomShaderGUI = ShaderGUIUtility.CreateShaderGUI(m_CustomEditorClassName); - // We need to delay checking setup because we need all loaded editor assemblies which is not ready - // during package import. During package import we create an Editor to generate a asset preview. (case 707328) - m_CheckSetup = true; - } - - public bool PropertiesGUI() - { - if (m_InsidePropertiesGUI) - { - Debug.LogWarning("PropertiesGUI() is being called recursively. If you want to render the default gui for shader properties then call PropertiesDefaultGUI() instead"); - return false; - } - - EditorGUI.BeginChangeCheck(); - - MaterialProperty[] props = GetMaterialProperties(targets); - - // In animation mode we are actually animating the Renderer instead of the material. - // Thus all properties are editable even if the material is not editable. - m_RenderersForAnimationMode = PrepareMaterialPropertiesForAnimationMode(props, GetAssociatedRenderersFromInspector(), GUI.enabled); - bool wasEnabled = GUI.enabled; - if (m_RenderersForAnimationMode != null) - GUI.enabled = true; - - m_InsidePropertiesGUI = true; - - // Since ExitGUI is called when showing the Object Picker we wrap - // properties gui in try/catch to catch the ExitGUIException thrown by ExitGUI() - // to ensure our m_InsidePropertiesGUI flag is reset - try - { - if (m_CustomShaderGUI != null) - m_CustomShaderGUI.OnGUI(this, props); - else - PropertiesDefaultGUI(props); - - Renderer[] renderers = GetAssociatedRenderersFromInspector(); - if (renderers != null && renderers.Length > 0) - { - if (Event.current.type == EventType.Layout) - { - renderers[0].GetPropertyBlock(m_PropertyBlock); - } - - if (m_PropertyBlock != null && !m_PropertyBlock.isEmpty) - EditorGUILayout.HelpBox(Styles.propBlockInfo, MessageType.Info); - } - } - catch (Exception) - { - GUI.enabled = wasEnabled; - m_InsidePropertiesGUI = false; - m_RenderersForAnimationMode = null; - throw; - } - - GUI.enabled = wasEnabled; - m_InsidePropertiesGUI = false; - m_RenderersForAnimationMode = null; - - return EditorGUI.EndChangeCheck(); - } - - public void PropertiesDefaultGUI(MaterialProperty[] props) - { - SetDefaultGUIWidths(); - - if (m_InfoMessage != null) - EditorGUILayout.HelpBox(m_InfoMessage, MessageType.Info); - else - // Hack to make sure that control IDs stay the same when the help box is there or is not there. - // Otherwise, open color picker windows will not keep synched to the same properties when the help box - // shows up or disappears (case 566958) - GUIUtility.GetControlID(s_ControlHash, FocusType.Passive, new Rect(0, 0, 0, 0)); - - for (var i = 0; i < props.Length; i++) - { - if ((props[i].flags & (MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData)) != 0) - continue; - - float h = GetPropertyHeight(props[i], props[i].displayName); - Rect r = EditorGUILayout.GetControlRect(true, h, EditorStyles.layerMaskField); - - ShaderProperty(r, props[i], props[i].displayName); - } - - EditorGUILayout.Space(); - EditorGUILayout.Space(); - - RenderQueueField(); - EnableInstancingField(); - DoubleSidedGIField(); - } - - public static void ApplyMaterialPropertyDrawers(Material material) - { - var objs = new Object[] { material }; - ApplyMaterialPropertyDrawers(objs); - } - - public static void ApplyMaterialPropertyDrawers(Object[] targets) - { - if (targets == null || targets.Length == 0) - return; - var target = targets[0] as Material; - if (target == null) - return; - - var shader = target.shader; - var props = GetMaterialProperties(targets); - for (var i = 0; i < props.Length; i++) - { - MaterialPropertyHandler handler = MaterialPropertyHandler.GetHandler(shader, props[i].name); - if (handler != null && handler.propertyDrawer != null) - handler.propertyDrawer.Apply(props[i]); - } - } - - public void RegisterPropertyChangeUndo(string label) - { - Undo.RecordObjects(targets, "Modify " + label + " of " + targetTitle); - } - - private UnityEngine.Rendering.TextureDimension m_DesiredTexdim; - - private Object TextureValidator(Object[] references, System.Type objType, SerializedProperty property, EditorGUI.ObjectFieldValidatorOptions options) - { - foreach (Object i in references) - { - var t = i as Texture; - if (t) - { - if (t.dimension == m_DesiredTexdim || m_DesiredTexdim == UnityEngine.Rendering.TextureDimension.Any) - return t; - } - } - return null; - } - - private PreviewRenderUtility m_PreviewUtility; - private static readonly Mesh[] s_Meshes = {null, null, null, null, null }; - private static Mesh s_PlaneMesh; - private static readonly GUIContent[] s_MeshIcons = { null, null, null, null, null }; - private static readonly GUIContent[] s_LightIcons = { null, null }; - private static readonly GUIContent[] s_TimeIcons = { null, null }; - - private void Init() - { - if (m_PreviewUtility == null) - { - m_PreviewUtility = new PreviewRenderUtility(); - EditorUtility.SetCameraAnimateMaterials(m_PreviewUtility.camera, true); - } - - if (s_Meshes[0] == null) - { - var handleGo = (GameObject)EditorGUIUtility.LoadRequired("Previews/PreviewMaterials.fbx"); - // @TODO: temp workaround to make it not render in the scene - handleGo.SetActive(false); - foreach (Transform t in handleGo.transform) - { - var meshFilter = t.GetComponent(); - switch (t.name) - { - case "sphere": - s_Meshes[0] = meshFilter.sharedMesh; - break; - case "cube": - s_Meshes[1] = meshFilter.sharedMesh; - break; - case "cylinder": - s_Meshes[2] = meshFilter.sharedMesh; - break; - case "torus": - s_Meshes[3] = meshFilter.sharedMesh; - break; - default: - Debug.Log("Something is wrong, weird object found: " + t.name); - break; - } - } - - s_MeshIcons[0] = EditorGUIUtility.IconContent("PreMatSphere"); - s_MeshIcons[1] = EditorGUIUtility.IconContent("PreMatCube"); - s_MeshIcons[2] = EditorGUIUtility.IconContent("PreMatCylinder"); - s_MeshIcons[3] = EditorGUIUtility.IconContent("PreMatTorus"); - s_MeshIcons[4] = EditorGUIUtility.IconContent("PreMatQuad"); - - s_LightIcons[0] = EditorGUIUtility.IconContent("PreMatLight0"); - s_LightIcons[1] = EditorGUIUtility.IconContent("PreMatLight1"); - - s_TimeIcons[0] = EditorGUIUtility.IconContent("PlayButton"); - s_TimeIcons[1] = EditorGUIUtility.IconContent("PauseButton"); - - Mesh quadMesh = Resources.GetBuiltinResource(typeof(Mesh), "Quad.fbx") as Mesh; - s_Meshes[4] = quadMesh; - s_PlaneMesh = quadMesh; - } - } - - public override void OnPreviewSettings() - { - if (m_CustomShaderGUI != null) - m_CustomShaderGUI.OnMaterialPreviewSettingsGUI(this); - else - DefaultPreviewSettingsGUI(); - } - - private bool PreviewSettingsMenuButton(out Rect buttonRect) - { - buttonRect = GUILayoutUtility.GetRect(14, 24, 14, 20); - - const float iconWidth = 16f; - const float iconHeight = 6f; - Rect iconRect = new Rect(buttonRect.x + (buttonRect.width - iconWidth) / 2, buttonRect.y + (buttonRect.height - iconHeight) / 2, iconWidth, iconHeight); - - if (Event.current.type == EventType.Repaint) - Styles.kReflectionProbePickerStyle.Draw(iconRect, false, false, false, false); - - if (EditorGUI.DropdownButton(buttonRect, GUIContent.none, FocusType.Passive, GUIStyle.none)) - return true; - - return false; - } - - public void DefaultPreviewSettingsGUI() - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - return; - - Init(); - - var mat = target as Material; - var viewType = GetPreviewType(mat); - if (targets.Length > 1 || viewType == PreviewType.Mesh) - { - m_TimeUpdate = PreviewGUI.CycleButton(m_TimeUpdate, s_TimeIcons); - m_SelectedMesh = PreviewGUI.CycleButton(m_SelectedMesh, s_MeshIcons); - m_LightMode = PreviewGUI.CycleButton(m_LightMode, s_LightIcons); - - Rect settingsButton; - if (PreviewSettingsMenuButton(out settingsButton)) - PopupWindow.Show(settingsButton, m_ReflectionProbePicker); - } - } - - public sealed override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - return null; - - Init(); - - m_PreviewUtility.BeginStaticPreview(new Rect(0, 0, width, height)); - - DoRenderPreview(); - - return m_PreviewUtility.EndStaticPreview(); - } - - private void DoRenderPreview() - { - if (m_PreviewUtility.renderTexture.width <= 0 || m_PreviewUtility.renderTexture.height <= 0) - return; - - var mat = target as Material; - var viewType = GetPreviewType(mat); - - m_PreviewUtility.camera.transform.position = -Vector3.forward * 5; - m_PreviewUtility.camera.transform.rotation = Quaternion.identity; - if (m_LightMode == 0) - { - m_PreviewUtility.lights[0].intensity = 1.0f; - m_PreviewUtility.lights[0].transform.rotation = Quaternion.Euler(30f, 30f, 0); - m_PreviewUtility.lights[1].intensity = 0; - } - else - { - m_PreviewUtility.lights[0].intensity = 1.0f; - m_PreviewUtility.lights[0].transform.rotation = Quaternion.Euler(50f, 50f, 0); - m_PreviewUtility.lights[1].intensity = 1.0f; - } - - m_PreviewUtility.ambientColor = new Color(.2f, .2f, .2f, 0); - - Quaternion rot = Quaternion.identity; - if (DoesPreviewAllowRotation(viewType)) - rot = Quaternion.Euler(m_PreviewDir.y, 0, 0) * Quaternion.Euler(0, m_PreviewDir.x, 0); - Mesh mesh = s_Meshes[m_SelectedMesh]; - - switch (viewType) - { - case PreviewType.Plane: - mesh = s_PlaneMesh; - break; - case PreviewType.Mesh: - // We need to rotate camera, so we can see different reflections from different angles - // If we would only rotate object, the reflections would stay the same - m_PreviewUtility.camera.transform.position = Quaternion.Inverse(rot) * m_PreviewUtility.camera.transform.position; - m_PreviewUtility.camera.transform.LookAt(Vector3.zero); - rot = Quaternion.identity; - break; - case PreviewType.Skybox: - mesh = null; - m_PreviewUtility.camera.transform.rotation = Quaternion.Inverse(rot); - m_PreviewUtility.camera.fieldOfView = 120.0f; - break; - } - - if (mesh != null) - { - m_PreviewUtility.DrawMesh(mesh, Vector3.zero, rot, mat, 0, null, m_ReflectionProbePicker.Target, false); - } - - m_PreviewUtility.Render(true); - if (viewType == PreviewType.Skybox) - { - InternalEditorUtility.DrawSkyboxMaterial(mat, m_PreviewUtility.camera); - } - } - - public sealed override bool HasPreviewGUI() - { - return true; - } - - public override bool RequiresConstantRepaint() - { - return m_TimeUpdate == 1; - } - - public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - if (m_CustomShaderGUI != null) - m_CustomShaderGUI.OnMaterialInteractivePreviewGUI(this, r, background); - else - base.OnInteractivePreviewGUI(r, background); - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (m_CustomShaderGUI != null) - m_CustomShaderGUI.OnMaterialPreviewGUI(this, r, background); - else - DefaultPreviewGUI(r, background); - } - - public void DefaultPreviewGUI(Rect r, GUIStyle background) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - { - if (Event.current.type == EventType.Repaint) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), "Material preview \nnot available"); - return; - } - - Init(); - - var mat = target as Material; - var viewType = GetPreviewType(mat); - - if (DoesPreviewAllowRotation(viewType)) - m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, r); - - if (Event.current.type != EventType.Repaint) - return; - - m_PreviewUtility.BeginPreview(r, background); - - DoRenderPreview(); - - m_PreviewUtility.EndAndDrawPreview(r); - } - - public virtual void OnEnable() - { - if (!target) - return; - m_Shader = serializedObject.FindProperty("m_Shader").objectReferenceValue as Shader; - m_CustomEditorClassName = ""; - CreateCustomShaderEditorIfNeeded(m_Shader); - - m_EnableInstancing = serializedObject.FindProperty("m_EnableInstancingVariants"); - m_DoubleSidedGI = serializedObject.FindProperty("m_DoubleSidedGI"); - - m_LightmapSettings = new SerializedObject(LightmapEditorSettings.GetLightmapSettings()); - m_EnabledRealtimeGI = m_LightmapSettings.FindProperty("m_GISettings.m_EnableRealtimeLightmaps"); - m_EnabledBakedGI = m_LightmapSettings.FindProperty("m_GISettings.m_EnableBakedLightmaps"); - - s_MaterialEditors.Add(this); - Undo.undoRedoPerformed += UndoRedoPerformed; - PropertiesChanged(); - - m_PropertyBlock = new MaterialPropertyBlock(); - - m_ReflectionProbePicker.OnEnable(); - } - - public virtual void UndoRedoPerformed() - { - // Undo could've restored old shader which might lead to change in custom editor class - // therefore we need to rebuild inspector - UpdateAllOpenMaterialEditors(); - - PropertiesChanged(); - } - - public virtual void OnDisable() - { - m_ReflectionProbePicker.OnDisable(); - if (m_PreviewUtility != null) - { - m_PreviewUtility.Cleanup(); - m_PreviewUtility = null; - } - - s_MaterialEditors.Remove(this); - Undo.undoRedoPerformed -= UndoRedoPerformed; - } - - // Handle dragging of material onto renderers - internal void OnSceneDrag(SceneView sceneView) - { - Event evt = Event.current; - - if (evt.type == EventType.Repaint) - return; - - var materialIndex = -1; - var go = HandleUtility.PickGameObject(evt.mousePosition, out materialIndex); - - if (EditorMaterialUtility.IsBackgroundMaterial((target as Material))) - { - HandleSkybox(go, evt); - } - else if (go && go.GetComponent()) - HandleRenderer(go.GetComponent(), materialIndex, evt); - } - - internal void HandleSkybox(GameObject go, Event evt) - { - bool draggingOverBackground = !go; - var applyAndConsumeEvent = false; - - if (!draggingOverBackground || evt.type == EventType.DragExited) - { - // cancel material assignment, if not hovering over background anymore - evt.Use(); - } - else - switch (evt.type) - { - case EventType.DragUpdated: - DragAndDrop.visualMode = DragAndDropVisualMode.Link; - applyAndConsumeEvent = true; - break; - - case EventType.DragPerform: - DragAndDrop.AcceptDrag(); - applyAndConsumeEvent = true; - break; - } - - if (applyAndConsumeEvent) - { - Undo.RecordObject(FindObjectOfType(), "Assign Skybox Material"); - - RenderSettings.skybox = target as Material; - - evt.Use(); - } - } - - internal void HandleRenderer(Renderer r, int materialIndex, Event evt) - { - if (r.GetType().GetCustomAttributes(typeof(RejectDragAndDropMaterial), true).Length > 0) - return; - - var applyAndConsumeEvent = false; - switch (evt.type) - { - case EventType.DragUpdated: - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - applyAndConsumeEvent = true; - break; - - case EventType.DragPerform: - DragAndDrop.AcceptDrag(); - applyAndConsumeEvent = true; - break; - } - - if (applyAndConsumeEvent) - { - Undo.RecordObject(r, "Assign Material"); - var materials = r.sharedMaterials; - - bool altIsDown = evt.alt; - bool isValidMaterialIndex = (materialIndex >= 0 && materialIndex < r.sharedMaterials.Length); - if (!altIsDown && isValidMaterialIndex) - { - materials[materialIndex] = target as Material; - } - else - { - for (int q = 0; q < materials.Length; ++q) - materials[q] = target as Material; - } - - r.sharedMaterials = materials; - evt.Use(); - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs b/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs deleted file mode 100644 index 48989f33c5..0000000000 --- a/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs +++ /dev/null @@ -1,368 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Rendering; -using System; - -namespace UnityEditor -{ - public partial class MaterialEditor - { - public const int kMiniTextureFieldLabelIndentLevel = 2; - const float kSpaceBetweenFlexibleAreaAndField = 5f; - const float kQueuePopupWidth = 100f; - const float kCustomQueuePopupWidth = kQueuePopupWidth + 15f; - - private bool isPrefabAsset - { - get - { - if (m_SerializedObject == null || m_SerializedObject.targetObject == null) - return false; - - PrefabType type = PrefabUtility.GetPrefabType(m_SerializedObject.targetObject); - return (type == PrefabType.Prefab || type == PrefabType.ModelPrefab); - } - } - - // Do currently edited materials have different render queue values? - private bool HasMultipleMixedQueueValues() - { - int queue = ShaderUtil.GetMaterialRawRenderQueue(targets[0] as Material); - for (int i = 1; i < targets.Length; ++i) - { - if (queue != ShaderUtil.GetMaterialRawRenderQueue(targets[i] as Material)) - { - return true; - } - } - return false; - } - - // Field for editing render queue value, with an automatically calculated rect - public void RenderQueueField() - { - Rect r = GetControlRectForSingleLine(); - RenderQueueField(r); - } - - // Field for editing render queue value, with an explicit rect - public void RenderQueueField(Rect r) - { - var mixedValue = HasMultipleMixedQueueValues(); - EditorGUI.showMixedValue = mixedValue; - - var mat = targets[0] as Material; - int curRawQueue = ShaderUtil.GetMaterialRawRenderQueue(mat); - int curDisplayQueue = mat.renderQueue; // this gets final queue value used for rendering, taking shader's queue into account - - // Figure out if we're using one of common queues, or a custom one - GUIContent[] queueNames = null; - int[] queueValues = null; - float labelWidth; - // If we use queue value that is not available, lets switch to the custom one - bool useCustomQueue = Array.IndexOf(Styles.queueValues, curRawQueue) < 0; - if (useCustomQueue) - { - // It is a big chance that we already have this custom queue value available - bool updateNewCustomQueueValue = Array.IndexOf(Styles.customQueueNames, curRawQueue) < 0; - if (updateNewCustomQueueValue) - { - int targetQueueIndex = CalculateClosestQueueIndexToValue(curRawQueue); - string targetQueueName = Styles.queueNames[targetQueueIndex].text; - int targetQueueValueOverflow = curRawQueue - Styles.queueValues[targetQueueIndex]; - - string newQueueName = string.Format( - targetQueueValueOverflow > 0 ? "{0}+{1}" : "{0}{1}", - targetQueueName, - targetQueueValueOverflow); - Styles.customQueueNames[Styles.kCustomQueueIndex].text = newQueueName; - Styles.customQueueValues[Styles.kCustomQueueIndex] = curRawQueue; - } - - queueNames = Styles.customQueueNames; - queueValues = Styles.customQueueValues; - labelWidth = kCustomQueuePopupWidth; - } - else - { - queueNames = Styles.queueNames; - queueValues = Styles.queueValues; - labelWidth = kQueuePopupWidth; - } - - // We want the custom queue number field to line up with thumbnails & other value fields - // (on the right side), and common queues popup to be on the left of that. - float oldLabelWidth = EditorGUIUtility.labelWidth; - float oldFieldWidth = EditorGUIUtility.fieldWidth; - SetDefaultGUIWidths(); - EditorGUIUtility.labelWidth -= labelWidth; - Rect popupRect = r; - popupRect.width -= EditorGUIUtility.fieldWidth + 2; - Rect numberRect = r; - numberRect.xMin = numberRect.xMax - EditorGUIUtility.fieldWidth; - - // Queues popup - int curPopupValue = curRawQueue; - int newPopupValue = EditorGUI.IntPopup(popupRect, Styles.queueLabel, curRawQueue, queueNames, queueValues); - - // Custom queue field - int newDisplayQueue = EditorGUI.DelayedIntField(numberRect, curDisplayQueue); - - // If popup or custom field changed, set the new queue - if (curPopupValue != newPopupValue || curDisplayQueue != newDisplayQueue) - { - RegisterPropertyChangeUndo("Render Queue"); - // Take the value from the number field, - int newQueue = newDisplayQueue; - // But if it's the popup that was changed - if (newPopupValue != curPopupValue) - newQueue = newPopupValue; - newQueue = Mathf.Clamp(newQueue, -1, 5000); // clamp to valid queue ranges - // Change the material queues - foreach (var m in targets) - { - ((Material)m).renderQueue = newQueue; - } - } - - EditorGUIUtility.labelWidth = oldLabelWidth; - EditorGUIUtility.fieldWidth = oldFieldWidth; - EditorGUI.showMixedValue = false; - } - - public bool EnableInstancingField() - { - if (!ShaderUtil.HasInstancing(m_Shader)) - return false; - Rect r = GetControlRectForSingleLine(); - EnableInstancingField(r); - return true; - } - - public void EnableInstancingField(Rect r) - { - EditorGUI.PropertyField(r, m_EnableInstancing, Styles.enableInstancingLabel); - serializedObject.ApplyModifiedProperties(); - } - - public bool DoubleSidedGIField() - { - Rect r = GetControlRectForSingleLine(); - if (isPrefabAsset || LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveCPU) - { - EditorGUI.PropertyField(r, m_DoubleSidedGI, Styles.doubleSidedGILabel); - serializedObject.ApplyModifiedProperties(); - return true; - } - else - { - using (new EditorGUI.DisabledScope(LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveCPU)) - EditorGUI.Toggle(r, Styles.doubleSidedGILabel, false); - } - return false; - } - - private int CalculateClosestQueueIndexToValue(int requestedValue) - { - int bestCloseByDiff = int.MaxValue; - int result = 1; - for (int i = 1; i < Styles.queueValues.Length; i++) - { - int queueValue = Styles.queueValues[i]; - int closeByDiff = Mathf.Abs(queueValue - requestedValue); - if (closeByDiff < bestCloseByDiff) - { - result = i; - bestCloseByDiff = closeByDiff; - } - } - return result; - } - - public Rect TexturePropertySingleLine(GUIContent label, MaterialProperty textureProp) - { - return TexturePropertySingleLine(label, textureProp, null, null); - } - - public Rect TexturePropertySingleLine(GUIContent label, MaterialProperty textureProp, MaterialProperty extraProperty1) - { - return TexturePropertySingleLine(label, textureProp, extraProperty1, null); - } - - // Mini texture slot, with two extra controls on the same line (allocates rect in GUILayout) - // Have up to 3 controls on one line - public Rect TexturePropertySingleLine(GUIContent label, MaterialProperty textureProp, MaterialProperty extraProperty1, MaterialProperty extraProperty2) - { - Rect r = GetControlRectForSingleLine(); - TexturePropertyMiniThumbnail(r, textureProp, label.text, label.tooltip); - - // No extra properties: early out - if (extraProperty1 == null && extraProperty2 == null) - return r; - - // Temporarily reset the indent level as it was already used earlier to compute the positions of the layout items. See issue 946082. - int oldIndentLevel = EditorGUI.indentLevel; - - EditorGUI.indentLevel = 0; - - // One extra property - if (extraProperty1 == null || extraProperty2 == null) - { - var prop = extraProperty1 ?? extraProperty2; - if (prop.type == MaterialProperty.PropType.Color) - { - ExtraPropertyAfterTexture(GetLeftAlignedFieldRect(r), prop); - } - else - { - ExtraPropertyAfterTexture(GetRectAfterLabelWidth(r), prop); - } - } - else // Two extra properties - { - if (extraProperty1.type == MaterialProperty.PropType.Color) - { - ExtraPropertyAfterTexture(GetFlexibleRectBetweenFieldAndRightEdge(r), extraProperty2); - ExtraPropertyAfterTexture(GetLeftAlignedFieldRect(r), extraProperty1); - } - else - { - ExtraPropertyAfterTexture(GetRightAlignedFieldRect(r), extraProperty2); - ExtraPropertyAfterTexture(GetFlexibleRectBetweenLabelAndField(r), extraProperty1); - } - } - // Restore the indent level - EditorGUI.indentLevel = oldIndentLevel; - return r; - } - - [Obsolete("Use TexturePropertyWithHDRColor(GUIContent label, MaterialProperty textureProp, MaterialProperty colorProperty, bool showAlpha)")] - public Rect TexturePropertyWithHDRColor( - GUIContent label, MaterialProperty textureProp, MaterialProperty colorProperty, ColorPickerHDRConfig hdrConfig, bool showAlpha - ) - { - return TexturePropertyWithHDRColor(label, textureProp, colorProperty, showAlpha); - } - - public Rect TexturePropertyWithHDRColor(GUIContent label, MaterialProperty textureProp, MaterialProperty colorProperty, bool showAlpha) - { - Rect r = GetControlRectForSingleLine(); - TexturePropertyMiniThumbnail(r, textureProp, label.text, label.tooltip); - - if (colorProperty.type != MaterialProperty.PropType.Color) - { - Debug.LogError("Assuming MaterialProperty.PropType.Color (was " + colorProperty.type + ")"); - return r; - } - - BeginAnimatedCheck(r, colorProperty); - - Rect leftRect = GetLeftAlignedFieldRect(r); - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = colorProperty.hasMixedValue; - Color newValue = EditorGUI.ColorField(leftRect, GUIContent.none, colorProperty.colorValue, true, showAlpha, true); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - colorProperty.colorValue = newValue; - - EndAnimatedCheck(); - - return r; - } - - public Rect TexturePropertyTwoLines(GUIContent label, MaterialProperty textureProp, MaterialProperty extraProperty1, GUIContent label2, MaterialProperty extraProperty2) - { - // If not using the second extra property then use the single line version as - // the first extra property is always inlined with the the texture slot - if (extraProperty2 == null) - { - return TexturePropertySingleLine(label, textureProp, extraProperty1); - } - - Rect r = GetControlRectForSingleLine(); - TexturePropertyMiniThumbnail(r, textureProp, label.text, label.tooltip); - - // First extra control on the same line as the texture - Rect r1 = GetRectAfterLabelWidth(r); - if (extraProperty1.type == MaterialProperty.PropType.Color) - r1 = GetLeftAlignedFieldRect(r); - ExtraPropertyAfterTexture(r1, extraProperty1); - - // New line for extraProperty2 - Rect r2 = GetControlRectForSingleLine(); - ShaderProperty(r2, extraProperty2, label2.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1); - - // Return total rect - r.height += r2.height; - return r; - } - - Rect GetControlRectForSingleLine() - { - const float extraSpacing = 2f; // The shader properties needs a little more vertical spacing due to the mini texture field (looks cramped without) - return EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight + extraSpacing, EditorStyles.layerMaskField); - } - - void ExtraPropertyAfterTexture(Rect r, MaterialProperty property) - { - if ((property.type == MaterialProperty.PropType.Float || property.type == MaterialProperty.PropType.Color) && r.width > EditorGUIUtility.fieldWidth) - { - // We want color fields and float fields to have same width as EditorGUIUtility.fieldWidth - // so controls aligns vertically. - // This also makes us able to have a draggable area in front of the float fields. We therefore ensures - // the property has a label (here we use a whitespace) and adjust label width. - float oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = r.width - EditorGUIUtility.fieldWidth; - ShaderProperty(r, property, " "); - EditorGUIUtility.labelWidth = oldLabelWidth; - return; - } - - ShaderProperty(r, property, string.Empty); - } - - static public Rect GetRightAlignedFieldRect(Rect r) - { - return new Rect(r.xMax - EditorGUIUtility.fieldWidth, r.y, EditorGUIUtility.fieldWidth, EditorGUIUtility.singleLineHeight); - } - - static public Rect GetLeftAlignedFieldRect(Rect r) - { - return new Rect(r.x + EditorGUIUtility.labelWidth, r.y, EditorGUIUtility.fieldWidth, EditorGUIUtility.singleLineHeight); - } - - static public Rect GetFlexibleRectBetweenLabelAndField(Rect r) - { - return new Rect(r.x + EditorGUIUtility.labelWidth, r.y, r.width - EditorGUIUtility.labelWidth - EditorGUIUtility.fieldWidth - kSpaceBetweenFlexibleAreaAndField, EditorGUIUtility.singleLineHeight); - } - - static public Rect GetFlexibleRectBetweenFieldAndRightEdge(Rect r) - { - Rect r2 = GetRectAfterLabelWidth(r); - r2.xMin += EditorGUIUtility.fieldWidth + kSpaceBetweenFlexibleAreaAndField; - return r2; - } - - static public Rect GetRectAfterLabelWidth(Rect r) - { - return new Rect(r.x + EditorGUIUtility.labelWidth, r.y, r.width - EditorGUIUtility.labelWidth, EditorGUIUtility.singleLineHeight); - } - - static internal System.Type GetTextureTypeFromDimension(TextureDimension dim) - { - switch (dim) - { - case TextureDimension.Tex2D: return typeof(Texture); // common use case is RenderTextures too, so return base class - case TextureDimension.Cube: return typeof(Cubemap); - case TextureDimension.Tex3D: return typeof(Texture3D); - case TextureDimension.Tex2DArray: return typeof(Texture2DArray); - case TextureDimension.CubeArray: return typeof(CubemapArray); - case TextureDimension.Any: return typeof(Texture); - default: return null; // Unknown, None etc. - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/Inspector/MaterialPropertyDrawer.cs b/Editor/Mono/Inspector/MaterialPropertyDrawer.cs deleted file mode 100644 index b31a148ca1..0000000000 --- a/Editor/Mono/Inspector/MaterialPropertyDrawer.cs +++ /dev/null @@ -1,647 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text.RegularExpressions; -using UnityEngine; - -namespace UnityEditor -{ - internal class MaterialPropertyHandler - { - private MaterialPropertyDrawer m_PropertyDrawer; - private List m_DecoratorDrawers; - - public MaterialPropertyDrawer propertyDrawer { get { return m_PropertyDrawer; } } - - public bool IsEmpty() - { - return m_PropertyDrawer == null && (m_DecoratorDrawers == null || m_DecoratorDrawers.Count == 0); - } - - public void OnGUI(ref Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - float oldLabelWidth, oldFieldWidth; - var propHeight = position.height; - position.height = 0; - if (m_DecoratorDrawers != null) - { - foreach (var decorator in m_DecoratorDrawers) - { - position.height = decorator.GetPropertyHeight(prop, label.text, editor); - - oldLabelWidth = EditorGUIUtility.labelWidth; - oldFieldWidth = EditorGUIUtility.fieldWidth; - decorator.OnGUI(position, prop, label, editor); - EditorGUIUtility.labelWidth = oldLabelWidth; - EditorGUIUtility.fieldWidth = oldFieldWidth; - - position.y += position.height; - propHeight -= position.height; - } - } - - position.height = propHeight; - if (m_PropertyDrawer != null) - { - oldLabelWidth = EditorGUIUtility.labelWidth; - oldFieldWidth = EditorGUIUtility.fieldWidth; - m_PropertyDrawer.OnGUI(position, prop, label, editor); - EditorGUIUtility.labelWidth = oldLabelWidth; - EditorGUIUtility.fieldWidth = oldFieldWidth; - } - } - - public float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) - { - var height = 0f; - if (m_DecoratorDrawers != null) - foreach (var drawer in m_DecoratorDrawers) - height += drawer.GetPropertyHeight(prop, label, editor); - if (m_PropertyDrawer != null) - height += m_PropertyDrawer.GetPropertyHeight(prop, label, editor); - return height; - } - - private static Dictionary s_PropertyHandlers = new Dictionary(); - - private static string GetPropertyString(Shader shader, string name) - { - if (shader == null) - return string.Empty; - return shader.GetInstanceID() + "_" + name; - } - - internal static void InvalidatePropertyCache(Shader shader) - { - if (shader == null) - return; - string keyStart = shader.GetInstanceID() + "_"; - var toDelete = new List(); - foreach (string key in s_PropertyHandlers.Keys) - { - if (key.StartsWith(keyStart)) - toDelete.Add(key); - } - foreach (string key in toDelete) - { - s_PropertyHandlers.Remove(key); - } - } - - private static MaterialPropertyDrawer CreatePropertyDrawer(Type klass, string argsText) - { - // no args -> default constructor - if (string.IsNullOrEmpty(argsText)) - return Activator.CreateInstance(klass) as MaterialPropertyDrawer; - - // split the argument list by commas - string[] argStrings = argsText.Split(','); - var args = new object[argStrings.Length]; - for (var i = 0; i < argStrings.Length; ++i) - { - float f; - string arg = argStrings[i].Trim(); - - // if can parse as a float, use the float; otherwise pass the string - if (float.TryParse(arg, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out f)) - { - args[i] = f; - } - else - { - args[i] = arg; - } - } - return Activator.CreateInstance(klass, args) as MaterialPropertyDrawer; - } - - private static MaterialPropertyDrawer GetShaderPropertyDrawer(string attrib, out bool isDecorator) - { - isDecorator = false; - - string className = attrib; - string args = string.Empty; - Match match = Regex.Match(attrib, @"(\w+)\s*\((.*)\)"); - if (match.Success) - { - className = match.Groups[1].Value; - args = match.Groups[2].Value.Trim(); - } - - //Debug.Log ("looking for class " + className + " args '" + args + "'"); - foreach (var klass in EditorAssemblies.SubclassesOf(typeof(MaterialPropertyDrawer))) - { - // When you write [Foo] in shader, get Foo, FooDrawer, MaterialFooDrawer, - // FooDecorator or MaterialFooDecorator class; - // "kind of" similar to how C# does attributes. - - //@TODO: namespaces? - if (klass.Name == className || - klass.Name == className + "Drawer" || - klass.Name == "Material" + className + "Drawer" || - klass.Name == className + "Decorator" || - klass.Name == "Material" + className + "Decorator") - { - try - { - isDecorator = klass.Name.EndsWith("Decorator"); - return CreatePropertyDrawer(klass, args); - } - catch (Exception) - { - Debug.LogWarningFormat("Failed to create material drawer {0} with arguments '{1}'", className, args); - return null; - } - } - } - - return null; - } - - private static MaterialPropertyHandler GetShaderPropertyHandler(Shader shader, string name) - { - string[] attribs = ShaderUtil.GetShaderPropertyAttributes(shader, name); - if (attribs == null || attribs.Length == 0) - return null; - - var handler = new MaterialPropertyHandler(); - foreach (var attr in attribs) - { - bool isDecorator; - MaterialPropertyDrawer drawer = GetShaderPropertyDrawer(attr, out isDecorator); - if (drawer != null) - { - if (isDecorator) - { - if (handler.m_DecoratorDrawers == null) - handler.m_DecoratorDrawers = new List(); - handler.m_DecoratorDrawers.Add(drawer); - } - else - { - if (handler.m_PropertyDrawer != null) - { - Debug.LogWarning(string.Format("Shader property {0} already has a property drawer", name), shader); - } - handler.m_PropertyDrawer = drawer; - } - } - } - - return handler; - } - - internal static MaterialPropertyHandler GetHandler(Shader shader, string name) - { - if (shader == null) - return null; - - // Use cached handler if available - MaterialPropertyHandler handler; - string key = GetPropertyString(shader, name); - if (s_PropertyHandlers.TryGetValue(key, out handler)) - return handler; - - // Get the handler for this shader property - handler = GetShaderPropertyHandler(shader, name); - if (handler != null && handler.IsEmpty()) - handler = null; - //Debug.Log ("drawer " + drawer); - - // Cache the handler and return. Cache even if it was null, so we can return - // later requests fast as well. - s_PropertyHandlers[key] = handler; - return handler; - } - } - - - public abstract class MaterialPropertyDrawer - { - public virtual void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - OnGUI(position, prop, label.text, editor); - } - - public virtual void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) - { - EditorGUI.LabelField(position, new GUIContent(label), EditorGUIUtility.TempContent("No GUI Implemented")); - } - - public virtual float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) - { - return EditorGUI.kSingleLineHeight; - } - - public virtual void Apply(MaterialProperty prop) - { - // empty base implementation - } - } - - - // -------------------------------------------------------------------------- - // Built-in drawers below. - // They aren't directly used by the code, but can be used by writing attribute-like - // syntax in shaders, e.g. [Toggle] in front of a shader property will - // end up using MaterialToggleDrawer to display it as a toggle. - - // Variant of the ToggleDrawer that defines no keyword (just UI) - internal class MaterialToggleUIDrawer : MaterialPropertyDrawer - { - public MaterialToggleUIDrawer() - { - } - - public MaterialToggleUIDrawer(string keyword) - { - } - - protected virtual void SetKeyword(MaterialProperty prop, bool on) - { - } - - static bool IsPropertyTypeSuitable(MaterialProperty prop) - { - return prop.type == MaterialProperty.PropType.Float || prop.type == MaterialProperty.PropType.Range; - } - - public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) - { - if (!IsPropertyTypeSuitable(prop)) - { - return EditorGUI.kSingleLineHeight * 2.5f; - } - return base.GetPropertyHeight(prop, label, editor); - } - - public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - if (!IsPropertyTypeSuitable(prop)) - { - GUIContent c = EditorGUIUtility.TempContent("Toggle used on a non-float property: " + prop.name, - EditorGUIUtility.GetHelpIcon(MessageType.Warning)); - EditorGUI.LabelField(position, c, EditorStyles.helpBox); - return; - } - - EditorGUI.BeginChangeCheck(); - - bool value = (Math.Abs(prop.floatValue) > 0.001f); - EditorGUI.showMixedValue = prop.hasMixedValue; - value = EditorGUI.Toggle(position, label, value); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - prop.floatValue = value ? 1.0f : 0.0f; - SetKeyword(prop, value); - } - } - - public override void Apply(MaterialProperty prop) - { - base.Apply(prop); - if (!IsPropertyTypeSuitable(prop)) - return; - - if (prop.hasMixedValue) - return; - - SetKeyword(prop, (Math.Abs(prop.floatValue) > 0.001f)); - } - } - - - internal class MaterialToggleDrawer : MaterialToggleUIDrawer - { - protected readonly string keyword; - public MaterialToggleDrawer() - { - } - - public MaterialToggleDrawer(string keyword) - { - this.keyword = keyword; - } - - protected override void SetKeyword(MaterialProperty prop, bool on) - { - SetKeywordInternal(prop, on, "_ON"); - } - - protected void SetKeywordInternal(MaterialProperty prop, bool on, string defaultKeywordSuffix) - { - // if no keyword is provided, use + defaultKeywordSuffix - string kw = string.IsNullOrEmpty(keyword) ? prop.name.ToUpperInvariant() + defaultKeywordSuffix : keyword; - // set or clear the keyword - foreach (Material material in prop.targets) - { - if (on) - material.EnableKeyword(kw); - else - material.DisableKeyword(kw); - } - } - } - - // Variant of the ToggleDrawer that defines a keyword when it's not on - // This is useful when adding Toggles to existing shaders while maintaining backwards compatibility - internal class MaterialToggleOffDrawer : MaterialToggleDrawer - { - public MaterialToggleOffDrawer() - { - } - - public MaterialToggleOffDrawer(string keyword) : base(keyword) - { - } - - protected override void SetKeyword(MaterialProperty prop, bool on) - { - SetKeywordInternal(prop, !on, "_OFF"); - } - } - - internal class MaterialPowerSliderDrawer : MaterialPropertyDrawer - { - private readonly float power; - - public MaterialPowerSliderDrawer(float power) - { - this.power = power; - } - - public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) - { - if (prop.type != MaterialProperty.PropType.Range) - { - return EditorGUI.kSingleLineHeight * 2.5f; - } - return base.GetPropertyHeight(prop, label, editor); - } - - public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - if (prop.type != MaterialProperty.PropType.Range) - { - GUIContent c = EditorGUIUtility.TempContent("PowerSlider used on a non-range property: " + prop.name, - EditorGUIUtility.GetHelpIcon(MessageType.Warning)); - EditorGUI.LabelField(position, c, EditorStyles.helpBox); - return; - } - - MaterialEditor.DoPowerRangeProperty(position, prop, label, power); - } - } - - internal class MaterialIntRangeDrawer : MaterialPropertyDrawer - { - public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - if (prop.type != MaterialProperty.PropType.Range) - { - GUIContent c = EditorGUIUtility.TempContent("IntRange used on a non-range property: " + prop.name, - EditorGUIUtility.GetHelpIcon(MessageType.Warning)); - EditorGUI.LabelField(position, c, EditorStyles.helpBox); - return; - } - - MaterialEditor.DoIntRangeProperty(position, prop, label); - } - } - - internal class MaterialKeywordEnumDrawer : MaterialPropertyDrawer - { - private readonly GUIContent[] keywords; - - public MaterialKeywordEnumDrawer(string kw1) : this(new[] { kw1 }) {} - public MaterialKeywordEnumDrawer(string kw1, string kw2) : this(new[] { kw1, kw2 }) {} - public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3) : this(new[] { kw1, kw2, kw3 }) {} - public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3, string kw4) : this(new[] { kw1, kw2, kw3, kw4 }) {} - public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3, string kw4, string kw5) : this(new[] { kw1, kw2, kw3, kw4, kw5 }) {} - public MaterialKeywordEnumDrawer(string kw1, string kw2, string kw3, string kw4, string kw5, string kw6) : this(new[] { kw1, kw2, kw3, kw4, kw5, kw6 }) {} - 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 }) {} - 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 }) {} - 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 }) {} - public MaterialKeywordEnumDrawer(params string[] keywords) - { - this.keywords = new GUIContent[keywords.Length]; - for (int i = 0; i < keywords.Length; ++i) - this.keywords[i] = new GUIContent(keywords[i]); - } - - static bool IsPropertyTypeSuitable(MaterialProperty prop) - { - return prop.type == MaterialProperty.PropType.Float || prop.type == MaterialProperty.PropType.Range; - } - - void SetKeyword(MaterialProperty prop, int index) - { - for (int i = 0; i < keywords.Length; ++i) - { - string keyword = GetKeywordName(prop.name, keywords[i].text); - foreach (Material material in prop.targets) - { - if (index == i) - material.EnableKeyword(keyword); - else - material.DisableKeyword(keyword); - } - } - } - - public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) - { - if (!IsPropertyTypeSuitable(prop)) - { - return EditorGUI.kSingleLineHeight * 2.5f; - } - return base.GetPropertyHeight(prop, label, editor); - } - - public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - if (!IsPropertyTypeSuitable(prop)) - { - GUIContent c = EditorGUIUtility.TempContent("KeywordEnum used on a non-float property: " + prop.name, - EditorGUIUtility.GetHelpIcon(MessageType.Warning)); - EditorGUI.LabelField(position, c, EditorStyles.helpBox); - return; - } - - EditorGUI.BeginChangeCheck(); - - EditorGUI.showMixedValue = prop.hasMixedValue; - var value = (int)prop.floatValue; - value = EditorGUI.Popup(position, label, value, keywords); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - prop.floatValue = value; - SetKeyword(prop, value); - } - } - - public override void Apply(MaterialProperty prop) - { - base.Apply(prop); - if (!IsPropertyTypeSuitable(prop)) - return; - - if (prop.hasMixedValue) - return; - - SetKeyword(prop, (int)prop.floatValue); - } - - // Final keyword name: property name + "_" + display name. Uppercased, - // and spaces replaced with underscores. - private static string GetKeywordName(string propName, string name) - { - string n = propName + "_" + name; - return n.Replace(' ', '_').ToUpperInvariant(); - } - } - - - internal class MaterialEnumDrawer : MaterialPropertyDrawer - { - private readonly GUIContent[] names; - private readonly int[] values; - - // Single argument: enum type name; entry names & values fetched via reflection - public MaterialEnumDrawer(string enumName) - { - var loadedTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => AssemblyHelper.GetTypesFromAssembly(x)).ToArray(); - try - { - var enumType = loadedTypes.FirstOrDefault( - x => x.IsSubclassOf(typeof(Enum)) && (x.Name == enumName || x.FullName == enumName) - ); - var enumNames = Enum.GetNames(enumType); - this.names = new GUIContent[enumNames.Length]; - for (int i = 0; i < enumNames.Length; ++i) - this.names[i] = new GUIContent(enumNames[i]); - - var enumVals = Enum.GetValues(enumType); - values = new int[enumVals.Length]; - for (var i = 0; i < enumVals.Length; ++i) - values[i] = (int)enumVals.GetValue(i); - } - catch (Exception) - { - Debug.LogWarningFormat("Failed to create MaterialEnum, enum {0} not found", enumName); - throw; - } - } - - // name,value,name,value,... pairs: explicit names & values - public MaterialEnumDrawer(string n1, float v1) : this(new[] {n1}, new[] {v1}) {} - public MaterialEnumDrawer(string n1, float v1, string n2, float v2) : this(new[] { n1, n2 }, new[] { v1, v2 }) {} - public MaterialEnumDrawer(string n1, float v1, string n2, float v2, string n3, float v3) : this(new[] { n1, n2, n3 }, new[] { v1, v2, v3 }) {} - 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 }) {} - 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 }) {} - 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 }) {} - 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 }) {} - public MaterialEnumDrawer(string[] enumNames, float[] vals) - { - this.names = new GUIContent[enumNames.Length]; - for (int i = 0; i < enumNames.Length; ++i) - this.names[i] = new GUIContent(enumNames[i]); - - values = new int[vals.Length]; - for (int i = 0; i < vals.Length; ++i) - values[i] = (int)vals[i]; - } - - public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) - { - if (prop.type != MaterialProperty.PropType.Float && prop.type != MaterialProperty.PropType.Range) - { - return EditorGUI.kSingleLineHeight * 2.5f; - } - return base.GetPropertyHeight(prop, label, editor); - } - - public override void OnGUI(Rect position, MaterialProperty prop, GUIContent label, MaterialEditor editor) - { - if (prop.type != MaterialProperty.PropType.Float && prop.type != MaterialProperty.PropType.Range) - { - GUIContent c = EditorGUIUtility.TempContent("Enum used on a non-float property: " + prop.name, - EditorGUIUtility.GetHelpIcon(MessageType.Warning)); - EditorGUI.LabelField(position, c, EditorStyles.helpBox); - return; - } - - EditorGUI.BeginChangeCheck(); - - EditorGUI.showMixedValue = prop.hasMixedValue; - var value = (int)prop.floatValue; - value = EditorGUI.IntPopup(position, label, value, names, values); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - prop.floatValue = value; - } - } - } - - // [Space] or [Space(height)] decorator creates a vertical space before shader property. - internal class MaterialSpaceDecorator : MaterialPropertyDrawer - { - private readonly float height; - - public MaterialSpaceDecorator() - { - height = 6f; - } - - public MaterialSpaceDecorator(float height) - { - this.height = height; - } - - public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) - { - return height; - } - - public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) - { - } - } - - // [Header(foobar)] decorator shows "foobar" header before shader property. - internal class MaterialHeaderDecorator : MaterialPropertyDrawer - { - private readonly string header; - - public MaterialHeaderDecorator(string header) - { - this.header = header; - } - - // so that we can accept Header(1) and display that as text - public MaterialHeaderDecorator(float headerAsNumber) - { - this.header = headerAsNumber.ToString(CultureInfo.InvariantCulture); - } - - public override float GetPropertyHeight(MaterialProperty prop, string label, MaterialEditor editor) - { - return 24f; - } - - public override void OnGUI(Rect position, MaterialProperty prop, string label, MaterialEditor editor) - { - position.y += 8; - position = EditorGUI.IndentedRect(position); - GUI.Label(position, header, EditorStyles.boldLabel); - } - } -} diff --git a/Editor/Mono/Inspector/MeshColliderEditor.cs b/Editor/Mono/Inspector/MeshColliderEditor.cs deleted file mode 100644 index fac62ecca6..0000000000 --- a/Editor/Mono/Inspector/MeshColliderEditor.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Net.Mime; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(MeshCollider))] - [CanEditMultipleObjects] - internal class MeshColliderEditor : Collider3DEditorBase - { - private SerializedProperty m_Mesh; - private SerializedProperty m_Convex; - private SerializedProperty m_CookingOptions; - private SerializedProperty m_SkinWidth; - - static class Texts - { - public static GUIContent isTriggerText = EditorGUIUtility.TrTextContent("Is Trigger", "Is this collider a trigger? Triggers are only supported on convex colliders."); - public static GUIContent convextText = EditorGUIUtility.TrTextContent("Convex", "Is this collider convex?"); - public static GUIContent skinWidthText = EditorGUIUtility.TrTextContent("Skin Width", "How far out to inflate the mesh when building collision mesh."); - public static GUIContent cookingOptionsText = EditorGUIUtility.TrTextContent("Cooking Options", "Options affecting the result of the mesh processing by the physics engine."); - } - - public override void OnEnable() - { - base.OnEnable(); - - m_Mesh = serializedObject.FindProperty("m_Mesh"); - m_Convex = serializedObject.FindProperty("m_Convex"); - m_CookingOptions = serializedObject.FindProperty("m_CookingOptions"); - m_SkinWidth = serializedObject.FindProperty("m_SkinWidth"); - } - - private MeshColliderCookingOptions GetCookingOptions() - { - return (MeshColliderCookingOptions)m_CookingOptions.intValue; - } - - private void SetCookingOptions(MeshColliderCookingOptions cookingOptions) - { - m_CookingOptions.intValue = (int)cookingOptions; - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_Convex, Texts.convextText); - - if (EditorGUI.EndChangeCheck() && m_Convex.boolValue == false) - { - m_IsTrigger.boolValue = false; - SetCookingOptions(GetCookingOptions() & (~MeshColliderCookingOptions.InflateConvexMesh)); - } - - EditorGUI.indentLevel++; - using (new EditorGUI.DisabledScope(!m_Convex.boolValue)) - { - EditorGUILayout.PropertyField(m_IsTrigger, Texts.isTriggerText); - } - EditorGUI.indentLevel--; - - if (m_Convex.boolValue && (GetCookingOptions() & MeshColliderCookingOptions.InflateConvexMesh) != 0) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_SkinWidth, Texts.skinWidthText); - EditorGUI.indentLevel--; - } - - SetCookingOptions((MeshColliderCookingOptions)EditorGUILayout.EnumFlagsField(Texts.cookingOptionsText, GetCookingOptions())); - - EditorGUILayout.PropertyField(m_Material); - - EditorGUILayout.PropertyField(m_Mesh); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/MeshRendererEditor.cs b/Editor/Mono/Inspector/MeshRendererEditor.cs deleted file mode 100644 index 817cc3bab4..0000000000 --- a/Editor/Mono/Inspector/MeshRendererEditor.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Linq; - -namespace UnityEditor -{ - [CustomEditor(typeof(MeshRenderer))] - [CanEditMultipleObjects] - internal class MeshRendererEditor : RendererEditorBase - { - class Styles - { - public static readonly string MaterialWarning = "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."; - public static readonly string StaticBatchingWarning = "This renderer is statically batched and uses an instanced shader at the same time. Instancing will be disabled in such a case. Consider disabling static batching if you want it to be instanced."; - } - - private SerializedProperty m_Materials; - private LightingSettingsInspector m_Lighting; - - private const string kDisplayLightingKey = "MeshRendererEditor.Lighting.ShowSettings"; - private const string kDisplayLightmapKey = "MeshRendererEditor.Lighting.ShowLightmapSettings"; - private const string kDisplayChartingKey = "MeshRendererEditor.Lighting.ShowChartingSettings"; - - private SerializedObject m_GameObjectsSerializedObject; - private SerializedProperty m_GameObjectStaticFlags; - - public override void OnEnable() - { - base.OnEnable(); - - m_Materials = serializedObject.FindProperty("m_Materials"); - - m_GameObjectsSerializedObject = new SerializedObject(targets.Select(t => ((MeshRenderer)t).gameObject).ToArray()); - m_GameObjectStaticFlags = m_GameObjectsSerializedObject.FindProperty("m_StaticEditorFlags"); - - InitializeProbeFields(); - InitializeLightingFields(); - } - - private void InitializeLightingFields() - { - m_Lighting = new LightingSettingsInspector(serializedObject); - - m_Lighting.showSettings = EditorPrefs.GetBool(kDisplayLightingKey, false); - m_Lighting.showChartingSettings = SessionState.GetBool(kDisplayChartingKey, true); - m_Lighting.showLightmapSettings = SessionState.GetBool(kDisplayLightmapKey, true); - } - - private void LightingFieldsGUI() - { - bool oldShowLighting = m_Lighting.showSettings; - bool oldShowCharting = m_Lighting.showChartingSettings; - bool oldShowLightmap = m_Lighting.showLightmapSettings; - - if (m_Lighting.Begin()) - { - RenderProbeFields(); - m_Lighting.RenderMeshSettings(true); - } - m_Lighting.End(); - - if (m_Lighting.showSettings != oldShowLighting) - EditorPrefs.SetBool(kDisplayLightingKey, m_Lighting.showSettings); - if (m_Lighting.showChartingSettings != oldShowCharting) - SessionState.SetBool(kDisplayChartingKey, m_Lighting.showChartingSettings); - if (m_Lighting.showLightmapSettings != oldShowLightmap) - SessionState.SetBool(kDisplayLightmapKey, m_Lighting.showLightmapSettings); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - LightingFieldsGUI(); - - RenderRenderingLayer(); - - // Evaluate displayMaterialWarning before drawing properties to avoid mismatched layout group - bool displayMaterialWarning = false; - - if (!m_Materials.hasMultipleDifferentValues) - { - MeshFilter mf = ((MeshRenderer)serializedObject.targetObject).GetComponent(); - displayMaterialWarning = mf != null && mf.sharedMesh != null && m_Materials.arraySize > mf.sharedMesh.subMeshCount; - } - - EditorGUILayout.PropertyField(m_Materials, true); - - if (!m_Materials.hasMultipleDifferentValues && displayMaterialWarning) - { - EditorGUILayout.HelpBox(Styles.MaterialWarning, MessageType.Warning, true); - } - - if (ShaderUtil.MaterialsUseInstancingShader(m_Materials)) - { - m_GameObjectsSerializedObject.Update(); - - if (!m_GameObjectStaticFlags.hasMultipleDifferentValues && ((StaticEditorFlags)m_GameObjectStaticFlags.intValue & StaticEditorFlags.BatchingStatic) != 0) - { - EditorGUILayout.HelpBox(Styles.StaticBatchingWarning, MessageType.Warning, true); - } - } - - CullDynamicFieldGUI(); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/ModelInspector.cs b/Editor/Mono/Inspector/ModelInspector.cs deleted file mode 100644 index 7ab7c105c1..0000000000 --- a/Editor/Mono/Inspector/ModelInspector.cs +++ /dev/null @@ -1,221 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - - -namespace UnityEditor -{ - [CustomEditor(typeof(Mesh))] - [CanEditMultipleObjects] - internal class ModelInspector : Editor - { - private PreviewRenderUtility m_PreviewUtility; - private Material m_Material; - private Material m_WireMaterial; - public Vector2 previewDir = new Vector2(-120, 20); - - - internal static Material CreateWireframeMaterial() - { - var shader = Shader.FindBuiltin("Internal-Colored.shader"); - if (!shader) - { - Debug.LogWarning("Could not find Colored builtin shader"); - return null; - } - var mat = new Material(shader); - mat.hideFlags = HideFlags.HideAndDontSave; - mat.SetColor("_Color", new Color(0, 0, 0, 0.3f)); - mat.SetInt("_ZWrite", 0); - mat.SetFloat("_ZBias", -1.0f); - return mat; - } - - void Init() - { - if (m_PreviewUtility == null) - { - m_PreviewUtility = new PreviewRenderUtility(); - m_PreviewUtility.camera.fieldOfView = 30.0f; - m_Material = Material.GetDefaultMaterial(); - m_WireMaterial = CreateWireframeMaterial(); - } - } - - public override void OnPreviewSettings() - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - return; - GUI.enabled = true; - Init(); - } - - internal static void RenderMeshPreview( - Mesh mesh, - PreviewRenderUtility previewUtility, - Material litMaterial, - Material wireMaterial, - Vector2 direction, - int meshSubset) - { - if (mesh == null || previewUtility == null) - return; - - Bounds bounds = mesh.bounds; - float halfSize = bounds.extents.magnitude; - float distance = 4.0f * halfSize; - - previewUtility.camera.transform.position = -Vector3.forward * distance; - previewUtility.camera.transform.rotation = Quaternion.identity; - previewUtility.camera.nearClipPlane = distance - halfSize * 1.1f; - previewUtility.camera.farClipPlane = distance + halfSize * 1.1f; - - previewUtility.lights[0].intensity = 1.4f; - previewUtility.lights[0].transform.rotation = Quaternion.Euler(40f, 40f, 0); - previewUtility.lights[1].intensity = 1.4f; - - previewUtility.ambientColor = new Color(.1f, .1f, .1f, 0); - RenderMeshPreviewSkipCameraAndLighting(mesh, bounds, previewUtility, litMaterial, wireMaterial, null, direction, meshSubset); - } - - internal static void RenderMeshPreviewSkipCameraAndLighting( - Mesh mesh, - Bounds bounds, - PreviewRenderUtility previewUtility, - Material litMaterial, - Material wireMaterial, - MaterialPropertyBlock customProperties, - Vector2 direction, - int meshSubset) // -1 for whole mesh - { - if (mesh == null || previewUtility == null) - return; - - Quaternion rot = Quaternion.Euler(direction.y, 0, 0) * Quaternion.Euler(0, direction.x, 0); - Vector3 pos = rot * (-bounds.center); - - bool oldFog = RenderSettings.fog; - Unsupported.SetRenderSettingsUseFogNoDirty(false); - - int submeshes = mesh.subMeshCount; - if (litMaterial != null) - { - previewUtility.camera.clearFlags = CameraClearFlags.Nothing; - if (meshSubset < 0 || meshSubset >= submeshes) - { - for (int i = 0; i < submeshes; ++i) - previewUtility.DrawMesh(mesh, pos, rot, litMaterial, i, customProperties); - } - else - previewUtility.DrawMesh(mesh, pos, rot, litMaterial, meshSubset, customProperties); - previewUtility.Render(); - } - - if (wireMaterial != null) - { - previewUtility.camera.clearFlags = CameraClearFlags.Nothing; - GL.wireframe = true; - if (meshSubset < 0 || meshSubset >= submeshes) - { - for (int i = 0; i < submeshes; ++i) - previewUtility.DrawMesh(mesh, pos, rot, wireMaterial, i, customProperties); - } - else - previewUtility.DrawMesh(mesh, pos, rot, wireMaterial, meshSubset, customProperties); - previewUtility.Render(); - GL.wireframe = false; - } - - Unsupported.SetRenderSettingsUseFogNoDirty(oldFog); - } - - private void DoRenderPreview() - { - RenderMeshPreview(target as Mesh, m_PreviewUtility, m_Material, m_WireMaterial, previewDir, -1); - } - - public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - { - //Debug.Log("Could not generate static preview. Render texture not supported by hardware."); - return null; - } - - Init(); - - m_PreviewUtility.BeginStaticPreview(new Rect(0, 0, width, height)); - - DoRenderPreview(); - - return m_PreviewUtility.EndStaticPreview(); - } - - public override bool HasPreviewGUI() - { - return (target != null); - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - { - if (Event.current.type == EventType.Repaint) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), "Mesh preview requires\nrender texture support"); - return; - } - - Init(); - - previewDir = PreviewGUI.Drag2D(previewDir, r); - - if (Event.current.type != EventType.Repaint) - return; - - m_PreviewUtility.BeginPreview(r, background); - - DoRenderPreview(); - - m_PreviewUtility.EndAndDrawPreview(r); - } - - // A minimal list of settings to be shown in the Asset Store preview inspector - internal override void OnAssetStoreInspectorGUI() - { - OnInspectorGUI(); - } - - public void OnDestroy() - { - if (m_PreviewUtility != null) - { - m_PreviewUtility.Cleanup(); - m_PreviewUtility = null; - } - if (m_WireMaterial) - { - DestroyImmediate(m_WireMaterial, true); - } - } - - public override string GetInfoString() - { - Mesh mesh = target as Mesh; - string info = mesh.vertexCount + " verts, " + InternalMeshUtil.GetPrimitiveCount(mesh) + " tris"; - int submeshes = mesh.subMeshCount; - if (submeshes > 1) - info += ", " + submeshes + " submeshes"; - - int blendShapeCount = mesh.blendShapeCount; - if (blendShapeCount > 1) - info += ", " + blendShapeCount + " blendShapes"; - - info += "\n" + InternalMeshUtil.GetVertexFormat(mesh); - return info; - } - } -} diff --git a/Editor/Mono/Inspector/MonoScriptInspector.cs b/Editor/Mono/Inspector/MonoScriptInspector.cs deleted file mode 100644 index c0f6912e41..0000000000 --- a/Editor/Mono/Inspector/MonoScriptInspector.cs +++ /dev/null @@ -1,230 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Reflection; -using System.Collections.Generic; -using System; -using UnityEditor.Experimental.AssetImporters; -using UnityEditorInternal; - -namespace UnityEditor -{ - [CustomEditor(typeof(MonoImporter))] - internal class MonoScriptImporterInspector : AssetImporterEditor - { - const int m_RowHeight = 16; - - private SerializedObject m_TargetObject; - private SerializedProperty m_Icon; - - internal override void OnHeaderControlsGUI() - { - TextAsset textAsset = assetTarget as TextAsset; - - GUILayout.FlexibleSpace(); - - using (new EditorGUI.DisabledScope(textAsset == null)) - { - if (GUILayout.Button("Open...", EditorStyles.miniButton)) - { - AssetDatabase.OpenAsset(textAsset); - GUIUtility.ExitGUI(); - } - - if (textAsset as MonoScript) - { - if (GUILayout.Button("Execution Order...", EditorStyles.miniButton))//GUILayout.Width(150))) - { - EditorApplication.ExecuteMenuItem("Edit/Project Settings/Script Execution Order"); - GUIUtility.ExitGUI(); - } - } - } - } - - internal override void OnHeaderIconGUI(Rect iconRect) - { - if (assetTargets != null) - { - if (m_Icon == null) - { - m_TargetObject = new SerializedObject(assetTargets); - m_Icon = m_TargetObject.FindProperty("m_Icon"); - } - EditorGUI.ObjectIconDropDown(iconRect, assetTargets, true, null, m_Icon); - } - else - { - base.OnHeaderIconGUI(iconRect); - } - } - - // Clear default references - [MenuItem("CONTEXT/MonoImporter/Reset")] - static void ResetDefaultReferences(MenuCommand command) - { - MonoImporter importer = command.context as MonoImporter; - importer.SetDefaultReferences(new string[0], new UnityEngine.Object[0]); - AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(importer)); - } - - static bool IsTypeCompatible(Type type) - { - if (type == null || !(type.IsSubclassOf(typeof(MonoBehaviour)) || type.IsSubclassOf(typeof(ScriptableObject)))) - return false; - return true; - } - - void ShowFieldInfo(Type type, MonoImporter importer, List names, List objects, ref bool didModify) - { - // Only show default properties for types that support it (so far only MonoBehaviour derived types) - if (!IsTypeCompatible(type)) - return; - - ShowFieldInfo(type.BaseType, importer, names, objects, ref didModify); - - FieldInfo[] infos = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - foreach (FieldInfo field in infos) - { - if (!field.IsPublic) - { - object[] attr = field.GetCustomAttributes(typeof(SerializeField), true); - if (attr == null || attr.Length == 0) - continue; - } - - if (field.FieldType.IsSubclassOf(typeof(UnityEngine.Object)) || field.FieldType == typeof(UnityEngine.Object)) - { - UnityEngine.Object oldTarget = importer.GetDefaultReference(field.Name); - UnityEngine.Object newTarget = EditorGUILayout.ObjectField(ObjectNames.NicifyVariableName(field.Name), oldTarget, field.FieldType, false); - - names.Add(field.Name); - objects.Add(newTarget); - - if (oldTarget != newTarget) - didModify = true; - } - } - } - - public override void OnInspectorGUI() - { - var importer = target as MonoImporter; - var script = importer.GetScript(); - - if (script) - { - Type type = script.GetClass(); - - // Ignore Editor scripts - if (!InternalEditorUtility.IsInEditorFolder(importer.assetPath)) - { - if (!IsTypeCompatible(type)) - { - EditorGUILayout.HelpBox( - "No MonoBehaviour scripts in the file, or their names do not match the file name.", - MessageType.Info); - } - } - - var names = new List(); - var objects = new List(); - var didModify = false; - - // Make default reference fields show small icons - using (new EditorGUIUtility.IconSizeScope(new Vector2(m_RowHeight, m_RowHeight))) - { - ShowFieldInfo(type, importer, names, objects, ref didModify); - } - - if (0 != objects.Count) - EditorGUILayout.HelpBox("Default references will only be applied in edit mode.", MessageType.Info); - - if (didModify) - { - importer.SetDefaultReferences(names.ToArray(), objects.ToArray()); - AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(importer)); - } - } - } - } - - [CustomEditor(typeof(TextAsset))] - [CanEditMultipleObjects] - internal class TextAssetInspector : Editor - { - private const int kMaxChars = 7000; - [NonSerialized] - private GUIStyle m_TextStyle; - - public override void OnInspectorGUI() - { - if (m_TextStyle == null) - m_TextStyle = "ScriptText"; - - bool enabledTemp = GUI.enabled; - GUI.enabled = true; - TextAsset textAsset = target as TextAsset; - if (textAsset != null) - { - string text; - if (targets.Length > 1) - { - text = targetTitle; - } - else - { - text = textAsset.ToString(); - if (text.Length > kMaxChars) - text = text.Substring(0, kMaxChars) + "...\n\n<...etc...>"; - } - Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.TempContent(text), m_TextStyle); - rect.x = 0; - rect.y -= 3; - rect.width = GUIClip.visibleRect.width + 1; - GUI.Box(rect, text, m_TextStyle); - } - GUI.enabled = enabledTemp; - } - } - - - [CustomEditor(typeof(MonoScript))] - [CanEditMultipleObjects] - internal class MonoScriptInspector : TextAssetInspector - { - public override void OnInspectorGUI() - { - if (targets.Length == 1) - { - var assetPath = AssetDatabase.GetAssetPath(target); - var assemblyName = Compilation.CompilationPipeline.GetAssemblyNameFromScriptPath(assetPath); - // assemblyName is null for MonoScript's inside assemblies. - if (assemblyName != null) - { - GUILayout.Label("Assembly Information", EditorStyles.boldLabel); - - EditorGUILayout.LabelField("Filename", assemblyName); - - var assemblyDefinitionFile = Compilation.CompilationPipeline.GetAssemblyDefinitionFilePathFromScriptPath(assetPath); - - if (assemblyDefinitionFile != null) - { - var assemblyDefintionFileAsset = AssetDatabase.LoadAssetAtPath(assemblyDefinitionFile); - - using (new EditorGUI.DisabledScope(true)) - { - EditorGUILayout.ObjectField("Definition File", assemblyDefintionFileAsset, typeof(TextAsset), false); - } - } - - EditorGUILayout.Space(); - } - } - - base.OnInspectorGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/MovieTextureInspector.cs b/Editor/Mono/Inspector/MovieTextureInspector.cs deleted file mode 100644 index 3baaaa580e..0000000000 --- a/Editor/Mono/Inspector/MovieTextureInspector.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - [CustomEditor(typeof(MovieTexture))] - [CanEditMultipleObjects] - internal class MovieTextureInspector : TextureInspector - { - static GUIContent[] s_PlayIcons = {null, null}; - - static void Init() - { - s_PlayIcons[0] = EditorGUIUtility.IconContent("preAudioPlayOff"); - s_PlayIcons[1] = EditorGUIUtility.IconContent("preAudioPlayOn"); - } - - protected override void OnEnable() {} - - public override void OnInspectorGUI() {} - - public override void OnPreviewSettings() - { - Init(); - - // Disallow playing movie previews in play mode. Better not to interfere - // with any playback the game does. - // Also disallow if more than one MovieClip selected (for now). - using (new EditorGUI.DisabledScope(Application.isPlaying || targets.Length > 1)) - { - MovieTexture t = target as MovieTexture; - AudioClip ac = t.audioClip; - bool isPlaying = PreviewGUI.CycleButton(t.isPlaying ? 1 : 0, s_PlayIcons) != 0; - if (isPlaying != t.isPlaying) - { - if (isPlaying) - { - t.Stop(); - t.Play(); - if (ac != null) - AudioUtil.PlayClip(ac); - } - else - { - t.Pause(); - if (ac != null) - AudioUtil.PauseClip(ac); - } - } - } - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (Event.current.type == EventType.Repaint) - background.Draw(r, false, false, false, false); - - // show texture - MovieTexture t = target as MovieTexture; - - float zoomLevel = Mathf.Min(Mathf.Min(r.width / t.width, r.height / t.height), 1); - Rect wantedRect = new Rect(r.x, r.y, t.width * zoomLevel, t.height * zoomLevel); - PreviewGUI.BeginScrollView(r, m_Pos, wantedRect, "PreHorizontalScrollbar", "PreHorizontalScrollbarThumb"); - EditorGUI.DrawPreviewTexture(wantedRect, t, null, ScaleMode.StretchToFill); - m_Pos = PreviewGUI.EndScrollView(); - - // force update GUI - if (t.isPlaying) - GUIView.current.Repaint(); - - if (Application.isPlaying) - { - if (t.isPlaying) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y + 10, r.width, 20), "Can't pause preview when in play mode"); - else - EditorGUI.DropShadowLabel(new Rect(r.x, r.y + 10, r.width, 20), "Can't start preview when in play mode"); - } - } - - protected override void OnDisable() - { - base.OnDisable(); - MovieTexture t = target as MovieTexture; - - //stop movies we started. - if (!Application.isPlaying && t != null) - { - AudioClip ac = t.audioClip; - t.Stop(); - if (ac != null) - AudioUtil.StopClip(ac); - } - } - - public override string GetInfoString() - { - string result = base.GetInfoString(); - - MovieTexture t = target as MovieTexture; - if (!t.isReadyToPlay) - result += "/nNot ready to play yet."; - - return result; - } - } -} diff --git a/Editor/Mono/Inspector/NavMeshAgentInspector.cs b/Editor/Mono/Inspector/NavMeshAgentInspector.cs deleted file mode 100644 index b51325eaa3..0000000000 --- a/Editor/Mono/Inspector/NavMeshAgentInspector.cs +++ /dev/null @@ -1,176 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.AI; - - -namespace UnityEditor -{ - [CanEditMultipleObjects] - [CustomEditor(typeof(NavMeshAgent))] - internal class NavMeshAgentInspector : Editor - { - private SerializedProperty m_AgentTypeID; - private SerializedProperty m_Radius; - private SerializedProperty m_Height; - private SerializedProperty m_WalkableMask; - private SerializedProperty m_Speed; - private SerializedProperty m_Acceleration; - private SerializedProperty m_AngularSpeed; - private SerializedProperty m_StoppingDistance; - private SerializedProperty m_AutoTraverseOffMeshLink; - private SerializedProperty m_AutoBraking; - private SerializedProperty m_AutoRepath; - private SerializedProperty m_BaseOffset; - private SerializedProperty m_ObstacleAvoidanceType; - private SerializedProperty m_AvoidancePriority; - - private class Styles - { - public readonly GUIContent m_AgentSteeringHeader = EditorGUIUtility.TrTextContent("Steering"); - public readonly GUIContent m_AgentAvoidanceHeader = EditorGUIUtility.TrTextContent("Obstacle Avoidance"); - public readonly GUIContent m_AgentPathFindingHeader = EditorGUIUtility.TrTextContent("Path Finding"); - }; - - static Styles s_Styles; - - void OnEnable() - { - m_AgentTypeID = serializedObject.FindProperty("m_AgentTypeID"); - m_Radius = serializedObject.FindProperty("m_Radius"); - m_Height = serializedObject.FindProperty("m_Height"); - m_WalkableMask = serializedObject.FindProperty("m_WalkableMask"); - m_Speed = serializedObject.FindProperty("m_Speed"); - m_Acceleration = serializedObject.FindProperty("m_Acceleration"); - m_AngularSpeed = serializedObject.FindProperty("m_AngularSpeed"); - m_StoppingDistance = serializedObject.FindProperty("m_StoppingDistance"); - m_AutoTraverseOffMeshLink = serializedObject.FindProperty("m_AutoTraverseOffMeshLink"); - m_AutoBraking = serializedObject.FindProperty("m_AutoBraking"); - m_AutoRepath = serializedObject.FindProperty("m_AutoRepath"); - m_BaseOffset = serializedObject.FindProperty("m_BaseOffset"); - m_ObstacleAvoidanceType = serializedObject.FindProperty("m_ObstacleAvoidanceType"); - m_AvoidancePriority = serializedObject.FindProperty("avoidancePriority"); - } - - public override void OnInspectorGUI() - { - if (s_Styles == null) - s_Styles = new Styles(); - - serializedObject.Update(); - - AgentTypePopupInternal("Agent Type", m_AgentTypeID); - EditorGUILayout.PropertyField(m_BaseOffset); - EditorGUILayout.Space(); - EditorGUILayout.LabelField(s_Styles.m_AgentSteeringHeader, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_Speed); - EditorGUILayout.PropertyField(m_AngularSpeed); - EditorGUILayout.PropertyField(m_Acceleration); - EditorGUILayout.PropertyField(m_StoppingDistance); - EditorGUILayout.PropertyField(m_AutoBraking); - - EditorGUILayout.Space(); - EditorGUILayout.LabelField(s_Styles.m_AgentAvoidanceHeader, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_Radius); - EditorGUILayout.PropertyField(m_Height); - EditorGUILayout.PropertyField(m_ObstacleAvoidanceType, GUIContent.Temp("Quality")); - EditorGUILayout.PropertyField(m_AvoidancePriority, GUIContent.Temp("Priority")); - - EditorGUILayout.Space(); - EditorGUILayout.LabelField(s_Styles.m_AgentPathFindingHeader, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_AutoTraverseOffMeshLink); - EditorGUILayout.PropertyField(m_AutoRepath); - - //Initially needed data - var areaNames = GameObjectUtility.GetNavMeshAreaNames(); - var currentMask = m_WalkableMask.longValue; - var compressedMask = 0; - - //Need to find the index as the list of names will compress out empty areas - for (var i = 0; i < areaNames.Length; i++) - { - var areaIndex = GameObjectUtility.GetNavMeshAreaFromName(areaNames[i]); - if (((1 << areaIndex) & currentMask) != 0) - compressedMask = compressedMask | (1 << i); - } - - //TODO: Refactor this to use the mask field that takes a label. - const float kH = EditorGUI.kSingleLineHeight; - var position = GUILayoutUtility.GetRect(EditorGUILayout.kLabelFloatMinW, EditorGUILayout.kLabelFloatMaxW, kH, kH, EditorStyles.layerMaskField); - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_WalkableMask.hasMultipleDifferentValues; - var areaMask = EditorGUI.MaskField(position, "Area Mask", compressedMask, areaNames, EditorStyles.layerMaskField); - EditorGUI.showMixedValue = false; - - if (EditorGUI.EndChangeCheck()) - { - if (areaMask == ~0) - { - m_WalkableMask.longValue = 0xffffffff; - } - else - { - uint newMask = 0; - for (var i = 0; i < areaNames.Length; i++) - { - //If the bit has been set in the compacted mask - if (((areaMask >> i) & 1) != 0) - { - //Find out the 'real' layer from the name, then set it in the new mask - newMask = newMask | (uint)(1 << GameObjectUtility.GetNavMeshAreaFromName(areaNames[i])); - } - } - m_WalkableMask.longValue = newMask; - } - } - - serializedObject.ApplyModifiedProperties(); - } - - private static void AgentTypePopupInternal(string labelName, SerializedProperty agentTypeID) - { - var index = -1; - var count = NavMesh.GetSettingsCount(); - var agentTypeNames = new string[count + 2]; - for (var i = 0; i < count; i++) - { - var id = NavMesh.GetSettingsByIndex(i).agentTypeID; - var name = NavMesh.GetSettingsNameFromID(id); - agentTypeNames[i] = name; - if (id == agentTypeID.intValue) - index = i; - } - agentTypeNames[count] = ""; - agentTypeNames[count + 1] = "Open Agent Settings..."; - - bool validAgentType = index != -1; - if (!validAgentType) - { - EditorGUILayout.HelpBox("Agent Type invalid.", MessageType.Warning); - } - - var rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight); - EditorGUI.BeginProperty(rect, GUIContent.none, agentTypeID); - - EditorGUI.BeginChangeCheck(); - index = EditorGUI.Popup(rect, labelName, index, agentTypeNames); - if (EditorGUI.EndChangeCheck()) - { - if (index >= 0 && index < count) - { - var id = NavMesh.GetSettingsByIndex(index).agentTypeID; - agentTypeID.intValue = id; - } - else if (index == count + 1) - { - UnityEditor.AI.NavMeshEditorHelpers.OpenAgentSettings(-1); - } - } - - EditorGUI.EndProperty(); - } - } -} diff --git a/Editor/Mono/Inspector/NavMeshEditorHelpers.cs b/Editor/Mono/Inspector/NavMeshEditorHelpers.cs deleted file mode 100644 index 07c8af8fe3..0000000000 --- a/Editor/Mono/Inspector/NavMeshEditorHelpers.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Collections.Generic; -using UnityEditor; -using UnityEditor.SceneManagement; -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.AI; - - -namespace UnityEditor.AI -{ - public static partial class NavMeshEditorHelpers - { - public static void OpenAgentSettings(int agentTypeID) - { - NavMeshEditorWindow.OpenAgentSettings(agentTypeID); - } - - public static void OpenAreaSettings() - { - NavMeshEditorWindow.OpenAreaSettings(); - } - - public static void DrawAgentDiagram(Rect rect, float agentRadius, float agentHeight, float agentClimb, float agentSlope) - { - if (Event.current.type != EventType.Repaint) - return; - - float cylinderRadius = agentRadius; - float cylinderHeight = agentHeight; - float stepHeight = agentClimb; - float scale = 1.0f; - float squash = 0.35f; - float paddingTop = 20.0f; - float paddingBottom = 10.0f; - - // Scale cylinder to fit to view. - // Find nice scale factor to fit the cylinder inside the view. - float viewSize = rect.height - (paddingTop + paddingBottom); - scale = Mathf.Min(viewSize / (cylinderHeight + cylinderRadius * 2.0f * squash), - viewSize / (cylinderRadius * 2.0f)); - - cylinderHeight *= scale; - cylinderRadius *= scale; - stepHeight *= scale; - stepHeight = Mathf.Min(stepHeight, viewSize - cylinderRadius * squash); - - // Position of the base of the cylinder. - float baseX = rect.xMin + rect.width * 0.5f; - float baseY = rect.yMax - paddingBottom - cylinderRadius * squash; - - const int kDivs = 20; - Vector3[] cylinderOutline = new Vector3[kDivs * 2]; - Vector3[] topRim = new Vector3[kDivs]; - Vector3[] climbRim = new Vector3[kDivs]; - - for (int i = 0; i < kDivs; i++) - { - float angle = (float)i / (float)(kDivs - 1) * Mathf.PI; // Half circle - float dx = Mathf.Cos(angle); - float dy = Mathf.Sin(angle); - cylinderOutline[i] = new Vector3(baseX + dx * cylinderRadius, baseY - cylinderHeight - dy * cylinderRadius * squash, 0); - cylinderOutline[i + kDivs] = new Vector3(baseX - dx * cylinderRadius, baseY + dy * cylinderRadius * squash, 0); - - topRim[i] = new Vector3(baseX - dx * cylinderRadius, baseY - cylinderHeight + dy * cylinderRadius * squash, 0); - climbRim[i] = new Vector3(baseX - dx * cylinderRadius, baseY - stepHeight + dy * cylinderRadius * squash, 0); - } - - Color oldColor = Handles.color; - - float startX = rect.xMin; - float startY = baseY - stepHeight; - float stepX = baseX - viewSize * 0.75f; - float stepY = baseY; - float slopeStartX = baseX + viewSize * 0.75f; - float slopeStartY = baseY; - float slopeEndX = slopeStartX; - float slopeEndY = slopeStartY; - float length = Mathf.Min(rect.xMax - slopeStartX, viewSize); - slopeEndX += Mathf.Cos(agentSlope * Mathf.Deg2Rad) * length; - slopeEndY -= Mathf.Sin(agentSlope * Mathf.Deg2Rad) * length; - - Vector3[] groundReference = new Vector3[2]; - groundReference[0] = new Vector3(startX, baseY, 0.0f); - groundReference[1] = new Vector3(slopeStartX + length, baseY, 0.0f); - - Vector3[] ground = new Vector3[5]; - ground[0] = new Vector3(startX, startY, 0.0f); - ground[1] = new Vector3(stepX, startY, 0.0f); - ground[2] = new Vector3(stepX, stepY, 0.0f); - ground[3] = new Vector3(slopeStartX, slopeStartY, 0.0f); - ground[4] = new Vector3(slopeEndX, slopeEndY, 0.0f); - - // Draw reference line on ground, used for measures - Handles.color = EditorGUIUtility.isProSkin ? new Color(0, 0, 0, 0.5f) : new Color(1, 1, 1, 0.5f); - Handles.DrawAAPolyLine(2.0f, groundReference); - - // Draw ground - Handles.color = EditorGUIUtility.isProSkin ? new Color(1, 1, 1, 0.5f) : new Color(0, 0, 0, 0.5f); - Handles.DrawAAPolyLine(3.0f, ground); - - // Draw cylinder background - Handles.color = Color.Lerp(new Color(0.0f, 0.75f, 1.0f, 1.0f), new Color(0.5f, 0.5f, 0.5f, 0.5f), 0.2f); - Handles.DrawAAConvexPolygon(cylinderOutline); - - // Draw step height on cylinder - if (agentClimb <= agentHeight) - { - Handles.color = new Color(0, 0, 0, 0.5f); - Handles.DrawAAPolyLine(2.0f, climbRim); - } - - // Draw cylinder outline - Handles.color = new Color(1, 1, 1, 0.4f); - Handles.DrawAAPolyLine(2.0f, topRim); - - // Draw line depicting the radius of the cylinder. - Vector3[] radiusLine = new Vector3[2]; - radiusLine[0] = new Vector3(baseX, baseY - cylinderHeight, 0); - radiusLine[1] = new Vector3(baseX + cylinderRadius, baseY - cylinderHeight, 0); - Handles.color = new Color(0, 0, 0, 0.5f); - Handles.DrawAAPolyLine(2.0f, radiusLine); - - // Labels - GUI.Label(new Rect(baseX + cylinderRadius + 5, baseY - cylinderHeight * 0.5f - 10, 150, 20), string.Format("H = {0}", agentHeight)); - GUI.Label(new Rect(baseX, baseY - cylinderHeight - cylinderRadius * squash - 15, 150, 20), string.Format("R = {0}", agentRadius)); - - GUI.Label(new Rect((startX + stepX) * 0.5f - 20, startY - 15, 150, 20), string.Format("{0}", agentClimb)); - GUI.Label(new Rect(slopeStartX + 20, slopeStartY - 15, 150, 20), string.Format("{0}\u00b0", agentSlope)); - - Handles.color = oldColor; - } - } -} diff --git a/Editor/Mono/Inspector/NavMeshObstacleInspector.cs b/Editor/Mono/Inspector/NavMeshObstacleInspector.cs deleted file mode 100644 index fa566680af..0000000000 --- a/Editor/Mono/Inspector/NavMeshObstacleInspector.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.AI; - -namespace UnityEditor -{ - [CanEditMultipleObjects] - [CustomEditor(typeof(NavMeshObstacle))] - internal class NavMeshObstacleInspector : Editor - { - private SerializedProperty m_Shape; - private SerializedProperty m_Center; - private SerializedProperty m_Extents; - private SerializedProperty m_Carve; - private SerializedProperty m_MoveThreshold; - private SerializedProperty m_TimeToStationary; - private SerializedProperty m_CarveOnlyStationary; - - void OnEnable() - { - m_Shape = serializedObject.FindProperty("m_Shape"); - m_Center = serializedObject.FindProperty("m_Center"); - m_Extents = serializedObject.FindProperty("m_Extents"); - m_Carve = serializedObject.FindProperty("m_Carve"); - m_MoveThreshold = serializedObject.FindProperty("m_MoveThreshold"); - m_TimeToStationary = serializedObject.FindProperty("m_TimeToStationary"); - m_CarveOnlyStationary = serializedObject.FindProperty("m_CarveOnlyStationary"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_Shape); - if (EditorGUI.EndChangeCheck()) - { - serializedObject.ApplyModifiedProperties(); - (target as NavMeshObstacle).FitExtents(); - serializedObject.Update(); - } - - EditorGUILayout.PropertyField(m_Center); - - if (m_Shape.enumValueIndex == 0) - { - // NavMeshObstacleShape : kObstacleShapeCapsule - EditorGUI.BeginChangeCheck(); - float radius = EditorGUILayout.FloatField("Radius", m_Extents.vector3Value.x); - float height = EditorGUILayout.FloatField("Height", m_Extents.vector3Value.y * 2.0f); - if (EditorGUI.EndChangeCheck()) - { - m_Extents.vector3Value = new Vector3(radius, height / 2.0f, radius); - } - } - else if (m_Shape.enumValueIndex == 1) - { - // NavMeshObstacleShape : kObstacleShapeBox - EditorGUI.BeginChangeCheck(); - Vector3 size = m_Extents.vector3Value * 2.0f; - size = EditorGUILayout.Vector3Field("Size", size); - if (EditorGUI.EndChangeCheck()) - { - m_Extents.vector3Value = size / 2.0f; - } - } - - EditorGUILayout.PropertyField(m_Carve); - - if (m_Carve.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_MoveThreshold); - EditorGUILayout.PropertyField(m_TimeToStationary); - EditorGUILayout.PropertyField(m_CarveOnlyStationary); - EditorGUI.indentLevel--; - } - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/OcclusionAreaEditor.cs b/Editor/Mono/Inspector/OcclusionAreaEditor.cs deleted file mode 100644 index 60ab6c25ae..0000000000 --- a/Editor/Mono/Inspector/OcclusionAreaEditor.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(OcclusionArea))] - class OcclusionAreaEditor : Editor - { - SerializedObject m_Object; - SerializedProperty m_Size; - SerializedProperty m_Center; - - void OnEnable() - { - m_Object = new SerializedObject(target); - m_Size = serializedObject.FindProperty("m_Size"); - m_Center = serializedObject.FindProperty("m_Center"); - } - - void OnDisable() - { - m_Object.Dispose(); - m_Object = null; - } - - void OnSceneGUI() - { - m_Object.Update(); - - OcclusionArea area = (OcclusionArea)target; - - - Color tempColor = Handles.color; - Handles.color = new Color(145f, 244f, 139f, 255f) / 255; - - Vector3 offset = area.transform.TransformPoint(m_Center.vector3Value); - - // Get min and max extends from center and size - Vector3 min = m_Size.vector3Value * 0.5f; - Vector3 max = m_Size.vector3Value * 0.5f; - - // Yes, it's weird to use lossyScale here, but that's what the occlusion volumes do - Vector3 scale = area.transform.lossyScale; - Vector3 inverseScale = new Vector3(1 / scale.x, 1 / scale.y, 1 / scale.z); - min = Vector3.Scale(min, scale); - max = Vector3.Scale(max, scale); - - // Handles - bool temp = GUI.changed; - min.x = SizeSlider(offset, -Vector3.right, min.x); - min.y = SizeSlider(offset, -Vector3.up, min.y); - min.z = SizeSlider(offset, -Vector3.forward, min.z); - max.x = SizeSlider(offset, Vector3.right, max.x); - max.y = SizeSlider(offset, Vector3.up, max.y); - max.z = SizeSlider(offset, Vector3.forward, max.z); - - // Apply cahnges if there were any - if (GUI.changed) - { - // Occlusion volumes can't be rotated but the center is still affected by rotation, so - // we need to rotate the offset (and apply the inverse lossyScale AFTER that) - m_Center.vector3Value = m_Center.vector3Value + Vector3.Scale(Quaternion.Inverse(area.transform.rotation) * (max - min) * 0.5f, inverseScale); - min = Vector3.Scale(min, inverseScale); - max = Vector3.Scale(max, inverseScale); - m_Size.vector3Value = (max + min); - - serializedObject.ApplyModifiedProperties(); - } - GUI.changed |= temp; - - Handles.color = tempColor; - } - - float SizeSlider(Vector3 p, Vector3 d, float r) - { - Vector3 position = p + d * r; - Color tempColor = Handles.color; - - if (Vector3.Dot((position - Camera.current.transform.position), d) >= 0) - Handles.color = new Color(Handles.color.r, Handles.color.g, Handles.color.b, Handles.color.a * Handles.backfaceAlphaMultiplier); - - float size = HandleUtility.GetHandleSize(position); - bool temp = GUI.changed; - GUI.changed = false; - position = Handles.Slider(position, d, size * 0.1f, Handles.CylinderHandleCap, 0f); - if (GUI.changed) - r = Vector3.Dot(position - p, d); - GUI.changed |= temp; - - Handles.color = tempColor; - return r; - } - } -} diff --git a/Editor/Mono/Inspector/OcclusionPortalEditor.cs b/Editor/Mono/Inspector/OcclusionPortalEditor.cs deleted file mode 100644 index 17807783ee..0000000000 --- a/Editor/Mono/Inspector/OcclusionPortalEditor.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEditor.IMGUI.Controls; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(OcclusionPortal)), CanEditMultipleObjects] - internal class OcclusionPortalEditor : Editor - { - private const string k_CenterPath = "m_Center"; - private const string k_SizePath = "m_Size"; - - private readonly BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle(); - - protected virtual void OnEnable() - { - m_BoundsHandle.SetColor(Handles.s_ColliderHandleColor); - } - - public override void OnInspectorGUI() - { - EditMode.DoEditModeInspectorModeButton( - EditMode.SceneViewEditMode.Collider, - "Edit Bounds", - PrimitiveBoundsHandle.editModeButton, - this - ); - - base.OnInspectorGUI(); - } - - protected virtual void OnSceneGUI() - { - if (EditMode.editMode != EditMode.SceneViewEditMode.Collider || !EditMode.IsOwner(this)) - return; - - OcclusionPortal portal = target as OcclusionPortal; - - // this.serializedObject will not work within OnSceneGUI if multiple targets are selected - SerializedObject so = new SerializedObject(portal); - so.Update(); - - using (new Handles.DrawingScope(portal.transform.localToWorldMatrix)) - { - SerializedProperty centerProperty = so.FindProperty(k_CenterPath); - SerializedProperty sizeProperty = so.FindProperty(k_SizePath); - m_BoundsHandle.center = centerProperty.vector3Value; - m_BoundsHandle.size = sizeProperty.vector3Value; - - EditorGUI.BeginChangeCheck(); - m_BoundsHandle.DrawHandle(); - if (EditorGUI.EndChangeCheck()) - { - centerProperty.vector3Value = m_BoundsHandle.center; - sizeProperty.vector3Value = m_BoundsHandle.size; - so.ApplyModifiedProperties(); - } - } - } - - internal override Bounds GetWorldBoundsOfTarget(Object targetObject) - { - var so = new SerializedObject(targetObject); - Vector3 center = so.FindProperty(k_CenterPath).vector3Value; - Vector3 size = so.FindProperty(k_SizePath).vector3Value; - - var localBounds = new Bounds(center, size); - Vector3 max = localBounds.max; - Vector3 min = localBounds.min; - Matrix4x4 portalTransformMatrix = ((OcclusionPortal)targetObject).transform.localToWorldMatrix; - var worldBounds = new Bounds(portalTransformMatrix.MultiplyPoint3x4(new Vector3(max.x, max.y, max.z)), Vector3.zero); - worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(max.x, max.y, max.z))); - worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(max.x, max.y, min.z))); - worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(max.x, min.y, max.z))); - worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(min.x, max.y, max.z))); - worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(max.x, min.y, min.z))); - worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(min.x, max.y, min.z))); - worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(min.x, min.y, max.z))); - worldBounds.Encapsulate(portalTransformMatrix.MultiplyPoint3x4(new Vector3(min.x, min.y, min.z))); - - return worldBounds; - } - } -} diff --git a/Editor/Mono/Inspector/OffMeshLinkInspector.cs b/Editor/Mono/Inspector/OffMeshLinkInspector.cs deleted file mode 100644 index cbc2a3f577..0000000000 --- a/Editor/Mono/Inspector/OffMeshLinkInspector.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.AI; - - -namespace UnityEditor -{ - [CanEditMultipleObjects] - [CustomEditor(typeof(OffMeshLink))] - internal class OffMeshLinkInspector : Editor - { - private SerializedProperty m_AreaIndex; - private SerializedProperty m_Start; - private SerializedProperty m_End; - private SerializedProperty m_CostOverride; - private SerializedProperty m_BiDirectional; - private SerializedProperty m_Activated; - private SerializedProperty m_AutoUpdatePositions; - - void OnEnable() - { - m_AreaIndex = serializedObject.FindProperty("m_AreaIndex"); - m_Start = serializedObject.FindProperty("m_Start"); - m_End = serializedObject.FindProperty("m_End"); - m_CostOverride = serializedObject.FindProperty("m_CostOverride"); - m_BiDirectional = serializedObject.FindProperty("m_BiDirectional"); - m_Activated = serializedObject.FindProperty("m_Activated"); - m_AutoUpdatePositions = serializedObject.FindProperty("m_AutoUpdatePositions"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_Start); - EditorGUILayout.PropertyField(m_End); - EditorGUILayout.PropertyField(m_CostOverride); - EditorGUILayout.PropertyField(m_BiDirectional); - EditorGUILayout.PropertyField(m_Activated); - EditorGUILayout.PropertyField(m_AutoUpdatePositions); - - SelectNavMeshArea(); - - serializedObject.ApplyModifiedProperties(); - } - - private void SelectNavMeshArea() - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_AreaIndex.hasMultipleDifferentValues; - var areaNames = GameObjectUtility.GetNavMeshAreaNames(); - var currentAbsoluteIndex = m_AreaIndex.intValue; - var areaIndex = -1; - - //Need to find the index as the list of names will compress out empty layers - for (var i = 0; i < areaNames.Length; i++) - { - if (GameObjectUtility.GetNavMeshAreaFromName(areaNames[i]) == currentAbsoluteIndex) - { - areaIndex = i; - break; - } - } - - var area = EditorGUILayout.Popup("Navigation Area", areaIndex, areaNames); - EditorGUI.showMixedValue = false; - - if (EditorGUI.EndChangeCheck()) - { - var newAreaIndex = GameObjectUtility.GetNavMeshAreaFromName(areaNames[area]); - m_AreaIndex.intValue = newAreaIndex; - } - } - } -} diff --git a/Editor/Mono/Inspector/ParentConstraintEditor.cs b/Editor/Mono/Inspector/ParentConstraintEditor.cs deleted file mode 100644 index 7a318180a8..0000000000 --- a/Editor/Mono/Inspector/ParentConstraintEditor.cs +++ /dev/null @@ -1,218 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.Animations; - -namespace UnityEditor -{ - [CustomEditor(typeof(ParentConstraint))] - [CanEditMultipleObjects] - internal class ParentConstraintEditor : ConstraintEditorBase - { - private SerializedProperty m_TranslationAtRest; - private SerializedProperty m_TranslationOffsets; - private SerializedProperty m_RotationAtRest; - private SerializedProperty m_RotationOffsets; - private SerializedProperty m_Weight; - private SerializedProperty m_IsContraintActive; - private SerializedProperty m_IsLocked; - private SerializedProperty m_Sources; - - private ReorderableList m_OffsetList; - - internal override SerializedProperty atRest { get { throw new NotImplementedException(); } } - internal override SerializedProperty offset { get { throw new NotImplementedException(); } } - internal override SerializedProperty weight { get { return m_Weight; } } - internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } } - internal override SerializedProperty isLocked { get { return m_IsLocked; } } - internal override SerializedProperty sources { get { return m_Sources; } } - - private class Styles : ConstraintStyleBase - { - GUIContent m_RestTranslation = EditorGUIUtility.TextContent("Position At Rest"); - GUIContent m_TranslationOffset = EditorGUIUtility.TextContent("Position Offset"); - - GUIContent m_RestRotation = EditorGUIUtility.TextContent("Rotation At Rest"); - GUIContent m_RotationOffset = EditorGUIUtility.TextContent("Rotation Offset"); - - GUIContent m_TranslationAxes = EditorGUIUtility.TextContent("Freeze Position Axes"); - GUIContent m_RotationAxes = EditorGUIUtility.TextContent("Freeze Rotation Axes"); - - GUIContent m_DefaultSourceName = EditorGUIUtility.TextContent("None"); - - GUIContent m_SourceOffsets = EditorGUIUtility.TextContent("Source Offsets"); - - public override GUIContent AtRest { get { throw new NotImplementedException(); } } - public override GUIContent Offset { get { throw new NotImplementedException(); } } - public GUIContent TranslationAtRest { get { return m_RestTranslation; } } - public GUIContent RotationAtRest { get { return m_RestRotation; } } - public GUIContent TranslationOffset { get { return m_TranslationOffset; } } - public GUIContent RotationOffset { get { return m_RotationOffset; } } - public GUIContent FreezeTranslationAxes { get { return m_TranslationAxes; } } - public GUIContent FreezeRotationAxes { get { return m_RotationAxes; } } - public GUIContent SourceOffsets { get { return m_SourceOffsets; } } - public GUIContent DefaultSourceName { get { return m_DefaultSourceName; } } - } - - private static Styles s_Style; - - public void OnEnable() - { - if (s_Style == null) - s_Style = new Styles(); - - m_TranslationAtRest = serializedObject.FindProperty("m_TranslationAtRest"); - m_TranslationOffsets = serializedObject.FindProperty("m_TranslationOffsets"); - m_RotationAtRest = serializedObject.FindProperty("m_RotationAtRest"); - m_RotationOffsets = serializedObject.FindProperty("m_RotationOffsets"); - m_Weight = serializedObject.FindProperty("m_Weight"); - m_IsContraintActive = serializedObject.FindProperty("m_IsContraintActive"); - m_IsLocked = serializedObject.FindProperty("m_IsLocked"); - m_Sources = serializedObject.FindProperty("m_Sources"); - - m_OffsetList = new ReorderableList(serializedObject, sources, false, false, false, false); - m_OffsetList.drawHeaderCallback += rect => EditorGUI.LabelField(rect, s_Style.SourceOffsets); - m_OffsetList.drawElementCallback += DrawOffsetElementCallback; - m_OffsetList.elementHeightCallback += OnElementHeightCallback; - - OnEnable(s_Style); - - m_OffsetList.index = base.selectedSourceIndex; - } - - private void DrawOffsetElementCallback(Rect rect, int index, bool isActive, bool isFocused) - { - var translationOffset = m_TranslationOffsets.GetArrayElementAtIndex(index); - var rotationOffset = m_RotationOffsets.GetArrayElementAtIndex(index); - var element = m_Sources.GetArrayElementAtIndex(index); - var sourceElement = element.FindPropertyRelative("sourceTransform"); - var sourceName = s_Style.DefaultSourceName; - if (sourceElement.objectReferenceValue != null) - { - sourceName = EditorGUIUtility.TextContent(sourceElement.objectReferenceValue.name); - } - - Rect drawRect = rect; - drawRect.height = EditorGUIUtility.singleLineHeight; - drawRect.y += EditorGUIUtility.standardVerticalSpacing; - - EditorGUI.LabelField(drawRect, sourceName); - - drawRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - EditorGUI.PropertyField(drawRect, translationOffset, s_Style.TranslationOffset); - drawRect.y += EditorGUIUtility.wideMode ? EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing : 2 * (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing); - EditorGUI.PropertyField(drawRect, rotationOffset, s_Style.RotationOffset); - } - - protected override void OnRemoveCallback(ReorderableList list) - { - int index = list.index; - ReorderableList.defaultBehaviours.DoRemoveButton(list); - m_TranslationOffsets.DeleteArrayElementAtIndex(index); - m_RotationOffsets.DeleteArrayElementAtIndex(index); - if (selectedSourceIndex >= list.serializedProperty.arraySize) - { - SelectSource(list.serializedProperty.arraySize - 1); - } - } - - protected override void OnAddCallback(ReorderableList list) - { - var index = list.serializedProperty.arraySize; - ReorderableList.defaultBehaviours.DoAddButton(list); - m_TranslationOffsets.arraySize++; - m_RotationOffsets.arraySize++; - - var source = list.serializedProperty.GetArrayElementAtIndex(index); - source.FindPropertyRelative("sourceTransform").objectReferenceValue = null; - source.FindPropertyRelative("weight").floatValue = 1.0f; - - SelectSource(index); - } - - protected override void OnReorderCallback(ReorderableList list, int oldActiveElement, int newActiveElement) - { - m_TranslationOffsets.MoveArrayElement(oldActiveElement, newActiveElement); - m_RotationOffsets.MoveArrayElement(oldActiveElement, newActiveElement); - m_SerializedObject.ApplyModifiedProperties(); - m_SerializedObject.Update(); - } - - protected override void OnSelectedCallback(ReorderableList list) - { - base.OnSelectedCallback(list); - m_OffsetList.index = list.index; - } - - static readonly float kListItemHeight = 3 * (EditorGUIUtility.singleLineHeight + 2 * EditorGUIUtility.standardVerticalSpacing); - static readonly float kListItemNarrowHeight = 5 * (EditorGUIUtility.singleLineHeight + 2 * EditorGUIUtility.standardVerticalSpacing); - private float OnElementHeightCallback(int index) - { - if (EditorGUIUtility.wideMode) - { - return kListItemHeight; - } - - return kListItemNarrowHeight; - } - - internal override void OnValueAtRestChanged() - { - foreach (var t in targets) - { - (t as IConstraintInternal).transform.localPosition = m_TranslationAtRest.vector3Value; - (t as IConstraintInternal).transform.SetLocalEulerAngles(m_RotationAtRest.vector3Value, RotationOrder.OrderZXY); - } - } - - internal override void ShowFreezeAxesControl() - { - Rect drawRectT = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeTranslationAxes), EditorStyles.toggle); - EditorGUI.MultiPropertyField(drawRectT, s_Style.Axes, serializedObject.FindProperty("m_AffectTranslationX"), s_Style.FreezeTranslationAxes); - - Rect drawRectR = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeRotationAxes), EditorStyles.toggle); - EditorGUI.MultiPropertyField(drawRectR, s_Style.Axes, serializedObject.FindProperty("m_AffectRotationX"), s_Style.FreezeRotationAxes); - } - - internal override void ShowValueAtRest(ConstraintStyleBase style) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_TranslationAtRest, (style as Styles).TranslationAtRest); - EditorGUILayout.PropertyField(m_RotationAtRest, (style as Styles).RotationAtRest); - if (EditorGUI.EndChangeCheck()) - { - OnValueAtRestChanged(); - } - } - - internal override void ShowOffset(ConstraintStyleBase style) - { - using (new EditorGUI.DisabledGroupScope(isLocked.boolValue)) - { - EditorGUI.BeginChangeCheck(); - m_OffsetList.DoLayoutList(); - if (EditorGUI.EndChangeCheck()) - { - foreach (var t in targets) - (t as IConstraintInternal).UserUpdateOffset(); - } - } - } - - public override void OnInspectorGUI() - { - if (s_Style == null) - s_Style = new Styles(); - - serializedObject.Update(); - - ShowConstraintEditor(s_Style); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/Physics2DSettingsInspector.cs b/Editor/Mono/Inspector/Physics2DSettingsInspector.cs deleted file mode 100644 index 542e3db74e..0000000000 --- a/Editor/Mono/Inspector/Physics2DSettingsInspector.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - [CustomEditor(typeof(Physics2DSettings))] - internal class Physics2DSettingsInspector : ProjectSettingsBaseEditor - { - private static class Styles - { - public static readonly GUIContent kJobOptionsLabel = EditorGUIUtility.TextContent("Job Options (Experimental)|Allows the configuration of multi-threaded physics using the job system."); - } - - SerializedProperty m_JobOptions; - - Vector2 m_LayerCollisionMatrixScrollPos; - bool m_ShowLayerCollisionMatrix = true; - - static bool s_ShowGizmoSettings; - readonly AnimBool m_GizmoSettingsFade = new AnimBool(); - SerializedProperty m_AlwaysShowColliders; - SerializedProperty m_ShowColliderSleep; - SerializedProperty m_ShowColliderContacts; - SerializedProperty m_ShowColliderAABB; - SerializedProperty m_ContactArrowScale; - SerializedProperty m_ColliderAwakeColor; - SerializedProperty m_ColliderAsleepColor; - SerializedProperty m_ColliderContactColor; - SerializedProperty m_ColliderAABBColor; - - public void OnEnable() - { - m_JobOptions = serializedObject.FindProperty("m_JobOptions"); - m_AlwaysShowColliders = serializedObject.FindProperty("m_AlwaysShowColliders"); - m_ShowColliderSleep = serializedObject.FindProperty("m_ShowColliderSleep"); - m_ShowColliderContacts = serializedObject.FindProperty("m_ShowColliderContacts"); - m_ShowColliderAABB = serializedObject.FindProperty("m_ShowColliderAABB"); - m_ContactArrowScale = serializedObject.FindProperty("m_ContactArrowScale"); - m_ColliderAwakeColor = serializedObject.FindProperty("m_ColliderAwakeColor"); - m_ColliderAsleepColor = serializedObject.FindProperty("m_ColliderAsleepColor"); - m_ColliderContactColor = serializedObject.FindProperty("m_ColliderContactColor"); - m_ColliderAABBColor = serializedObject.FindProperty("m_ColliderAABBColor"); - - m_GizmoSettingsFade.value = s_ShowGizmoSettings; - m_GizmoSettingsFade.valueChanged.AddListener(Repaint); - } - - public void OnDisable() - { - m_GizmoSettingsFade.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - DrawPropertiesExcluding(serializedObject, "m_JobOptions"); - EditorGUILayout.PropertyField(m_JobOptions, Styles.kJobOptionsLabel, true); - - s_ShowGizmoSettings = EditorGUILayout.Foldout(s_ShowGizmoSettings, "Gizmos", true); - m_GizmoSettingsFade.target = s_ShowGizmoSettings; - if (m_GizmoSettingsFade.value) - { - if (EditorGUILayout.BeginFadeGroup(m_GizmoSettingsFade.faded)) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_AlwaysShowColliders); - EditorGUILayout.PropertyField(m_ShowColliderSleep); - EditorGUILayout.PropertyField(m_ColliderAwakeColor); - EditorGUILayout.PropertyField(m_ColliderAsleepColor); - EditorGUILayout.PropertyField(m_ShowColliderContacts); - EditorGUILayout.Slider(m_ContactArrowScale, 0.1f, 1.0f, m_ContactArrowScale.displayName); - EditorGUILayout.PropertyField(m_ColliderContactColor); - EditorGUILayout.PropertyField(m_ShowColliderAABB); - EditorGUILayout.PropertyField(m_ColliderAABBColor); - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - } - serializedObject.ApplyModifiedProperties(); - - LayerMatrixGUI.DoGUI("Layer Collision Matrix", ref m_ShowLayerCollisionMatrix, ref m_LayerCollisionMatrixScrollPos, GetValue, SetValue); - } - - static bool GetValue(int layerA, int layerB) { return !Physics2D.GetIgnoreLayerCollision(layerA, layerB); } - static void SetValue(int layerA, int layerB, bool val) { Physics2D.IgnoreLayerCollision(layerA, layerB, !val); } - } -} diff --git a/Editor/Mono/Inspector/PhysicsManagerInspector.cs b/Editor/Mono/Inspector/PhysicsManagerInspector.cs deleted file mode 100644 index 52c7242550..0000000000 --- a/Editor/Mono/Inspector/PhysicsManagerInspector.cs +++ /dev/null @@ -1,164 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class LayerMatrixGUI - { - public delegate bool GetValueFunc(int layerA, int layerB); - public delegate void SetValueFunc(int layerA, int layerB, bool val); - - public static void DoGUI(string title, ref bool show, ref Vector2 scrollPos, GetValueFunc getValue, SetValueFunc setValue) - { - const int kMaxLayers = 32; - const int checkboxSize = 16; - int labelSize = 100; - const int indent = 30; - - int numLayers = 0; - for (int i = 0; i < kMaxLayers; i++) - if (LayerMask.LayerToName(i) != "") - numLayers++; - - // find the longest label - for (int i = 0; i < kMaxLayers; i++) - { - var textDimensions = GUI.skin.label.CalcSize(new GUIContent(LayerMask.LayerToName(i))); - if (labelSize < textDimensions.x) - labelSize = (int)textDimensions.x; - } - - GUILayout.BeginHorizontal(); - GUILayout.Space(0); - show = EditorGUILayout.Foldout(show, title, true); - GUILayout.EndHorizontal(); - if (show) - { - scrollPos = GUILayout.BeginScrollView(scrollPos, GUILayout.MinHeight(labelSize + 20), GUILayout.MaxHeight(labelSize + (numLayers + 1) * checkboxSize)); - Rect topLabelRect = GUILayoutUtility.GetRect(checkboxSize * numLayers + labelSize, labelSize); - Rect scrollArea = GUIClip.topmostRect; - Vector2 topLeft = GUIClip.Unclip(new Vector2(topLabelRect.x, topLabelRect.y)); - int y = 0; - for (int i = 0; i < kMaxLayers; i++) - { - if (LayerMask.LayerToName(i) != "") - { - // Need to do some shifting around here, so the rotated text will still clip correctly - float clipOffset = (labelSize + indent + (numLayers - y) * checkboxSize) - (scrollArea.width + scrollPos.x); - if (clipOffset < 0) - clipOffset = 0; - - Vector3 translate = new Vector3(labelSize + indent + checkboxSize * (numLayers - y) + topLeft.y + topLeft.x + scrollPos.y - clipOffset, topLeft.y + scrollPos.y, 0); - GUI.matrix = Matrix4x4.TRS(translate, Quaternion.identity, Vector3.one) * Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 0, 90), Vector3.one); - - GUI.Label(new Rect(2 - topLeft.x - scrollPos.y, scrollPos.y - clipOffset, labelSize, checkboxSize), LayerMask.LayerToName(i), "RightLabel"); - y++; - } - } - GUI.matrix = Matrix4x4.identity; - y = 0; - for (int i = 0; i < kMaxLayers; i++) - { - if (LayerMask.LayerToName(i) != "") - { - int x = 0; - Rect r = GUILayoutUtility.GetRect(indent + checkboxSize * numLayers + labelSize, checkboxSize); - GUI.Label(new Rect(r.x + indent, r.y, labelSize, checkboxSize), LayerMask.LayerToName(i), "RightLabel"); - for (int j = kMaxLayers - 1; j >= 0; j--) - { - if (LayerMask.LayerToName(j) != "") - { - if (x < numLayers - y) - { - GUIContent tooltip = new GUIContent("", LayerMask.LayerToName(i) + "/" + LayerMask.LayerToName(j)); - bool val = getValue(i, j); - bool toggle = GUI.Toggle(new Rect(labelSize + indent + r.x + x * checkboxSize, r.y, checkboxSize, checkboxSize), val, tooltip); - if (toggle != val) - setValue(i, j, toggle); - } - x++; - } - } - y++; - } - } - GUILayout.EndScrollView(); - } - } - } - - - [CustomEditor(typeof(PhysicsManager))] - internal class PhysicsManagerInspector : ProjectSettingsBaseEditor - { - Vector2 scrollPos; - bool show = true; - - bool GetValue(int layerA, int layerB) - { - return !Physics.GetIgnoreLayerCollision(layerA, layerB); - } - - void SetValue(int layerA, int layerB, bool val) - { - Physics.IgnoreLayerCollision(layerA, layerB, !val); - } - - private static class Styles - { - public static readonly GUIContent interCollisionPropertiesLabel = EditorGUIUtility.TrTextContent("Cloth Inter-Collision"); - public static readonly GUIContent interCollisionDistanceLabel = EditorGUIUtility.TrTextContent("Distance"); - public static readonly GUIContent interCollisionStiffnessLabel = EditorGUIUtility.TrTextContent("Stiffness"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - DrawPropertiesExcluding(serializedObject, "m_ClothInterCollisionDistance", "m_ClothInterCollisionStiffness", "m_ClothInterCollisionSettingsToggle"); - serializedObject.ApplyModifiedProperties(); - - LayerMatrixGUI.DoGUI("Layer Collision Matrix", ref show, ref scrollPos, GetValue, SetValue); - - EditorGUI.BeginChangeCheck(); - bool collisionSettings = EditorGUILayout.Toggle(Styles.interCollisionPropertiesLabel, Physics.interCollisionSettingsToggle); - bool settingsChanged = EditorGUI.EndChangeCheck(); - if (settingsChanged) - { - Undo.RecordObject(target, "Change inter collision settings"); - Physics.interCollisionSettingsToggle = collisionSettings; - } - - if (Physics.interCollisionSettingsToggle) - { - EditorGUI.indentLevel++; - EditorGUI.BeginChangeCheck(); - float distance = EditorGUILayout.FloatField(Styles.interCollisionDistanceLabel, Physics.interCollisionDistance); - bool distanceChanged = EditorGUI.EndChangeCheck(); - if (distanceChanged) - { - Undo.RecordObject(target, "Change inter collision distance"); - if (distance < 0.0f) - distance = 0.0f; - Physics.interCollisionDistance = distance; - } - - EditorGUI.BeginChangeCheck(); - float stiffness = EditorGUILayout.FloatField(Styles.interCollisionStiffnessLabel, Physics.interCollisionStiffness); - bool stiffnessChanged = EditorGUI.EndChangeCheck(); - if (stiffnessChanged) - { - Undo.RecordObject(target, "Change inter collision stiffness"); - if (stiffness < 0.0f) - stiffness = 0.0f; - Physics.interCollisionStiffness = stiffness; - } - EditorGUI.indentLevel--; - } - } - } -} diff --git a/Editor/Mono/Inspector/PlatformEffector2DEditor.cs b/Editor/Mono/Inspector/PlatformEffector2DEditor.cs deleted file mode 100644 index fc886be8da..0000000000 --- a/Editor/Mono/Inspector/PlatformEffector2DEditor.cs +++ /dev/null @@ -1,187 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - /// - /// An editor for the Platform Effector. - /// - [CustomEditor(typeof(PlatformEffector2D), true)] - [CanEditMultipleObjects] - internal class PlatformEffector2DEditor : Effector2DEditor - { - SerializedProperty m_RotationalOffset; - - readonly AnimBool m_ShowOneWayRollout = new AnimBool(); - SerializedProperty m_UseOneWay; - SerializedProperty m_UseOneWayGrouping; - SerializedProperty m_SurfaceArc; - - static readonly AnimBool m_ShowSidesRollout = new AnimBool(); - SerializedProperty m_UseSideFriction; - SerializedProperty m_UseSideBounce; - SerializedProperty m_SideArc; - - public override void OnEnable() - { - base.OnEnable(); - - m_RotationalOffset = serializedObject.FindProperty("m_RotationalOffset"); - - m_ShowOneWayRollout.value = true; - m_ShowOneWayRollout.valueChanged.AddListener(Repaint); - m_UseOneWay = serializedObject.FindProperty("m_UseOneWay"); - m_UseOneWayGrouping = serializedObject.FindProperty("m_UseOneWayGrouping"); - m_SurfaceArc = serializedObject.FindProperty("m_SurfaceArc"); - - m_ShowSidesRollout.valueChanged.AddListener(Repaint); - m_UseSideFriction = serializedObject.FindProperty("m_UseSideFriction"); - m_UseSideBounce = serializedObject.FindProperty("m_UseSideBounce"); - m_SideArc = serializedObject.FindProperty("m_SideArc"); - } - - public override void OnDisable() - { - base.OnDisable(); - - m_ShowOneWayRollout.valueChanged.RemoveListener(Repaint); - m_ShowSidesRollout.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_RotationalOffset); - - // One-Way. - m_ShowOneWayRollout.target = EditorGUILayout.Foldout(m_ShowOneWayRollout.target, "One Way", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowOneWayRollout.faded)) - { - EditorGUILayout.PropertyField(m_UseOneWay); - EditorGUILayout.PropertyField(m_UseOneWayGrouping); - EditorGUILayout.PropertyField(m_SurfaceArc); - EditorGUILayout.Space(); - } - EditorGUILayout.EndFadeGroup(); - - // Sides. - m_ShowSidesRollout.target = EditorGUILayout.Foldout(m_ShowSidesRollout.target, "Sides", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowSidesRollout.faded)) - { - EditorGUILayout.PropertyField(m_UseSideFriction); - EditorGUILayout.PropertyField(m_UseSideBounce); - EditorGUILayout.PropertyField(m_SideArc); - } - EditorGUILayout.EndFadeGroup(); - - serializedObject.ApplyModifiedProperties(); - } - - public void OnSceneGUI() - { - var effector = (PlatformEffector2D)target; - - // Ignore disabled effector. - if (!effector.enabled) - return; - - if (effector.useOneWay) - DrawSurfaceArc(effector); - - if (!effector.useSideBounce || !effector.useSideFriction) - DrawSideArc(effector); - } - - private static void DrawSurfaceArc(PlatformEffector2D effector) - { - // Calculate the surface angle in local-space. - var rotation = -Mathf.Deg2Rad * effector.rotationalOffset; - var localUp = effector.transform.TransformVector(new Vector3(Mathf.Sin(rotation), Mathf.Cos(rotation), 0.0f)).normalized; - - // If the transform has created a degenerate local then we cannot draw the gizmo! - if (localUp.sqrMagnitude < Mathf.Epsilon) - return; - - // Calculate the surface angle. - var surfaceAngle = Mathf.Atan2(localUp.x, localUp.y); - - // Fetch the surface arc. - var surfaceArc = Mathf.Clamp(effector.surfaceArc, 0.5f, 360.0f); - var halfSurfaceArcRadians = surfaceArc * 0.5f * Mathf.Deg2Rad; - - var fromAngle = new Vector3(Mathf.Sin(surfaceAngle - halfSurfaceArcRadians), Mathf.Cos(surfaceAngle - halfSurfaceArcRadians), 0.0f); - var toAngle = new Vector3(Mathf.Sin(surfaceAngle + halfSurfaceArcRadians), Mathf.Cos(surfaceAngle + halfSurfaceArcRadians), 0.0f); - - // Fetch all the effector-collider bounds. - foreach (var collider in effector.gameObject.GetComponents().Where(collider => collider.enabled && collider.usedByEffector)) - { - var center = collider.bounds.center; - var arcRadius = HandleUtility.GetHandleSize(center); - - // arc background - Handles.color = new Color(0, 1, 1, 0.07f); - Handles.DrawSolidArc(center, Vector3.back, fromAngle, surfaceArc, arcRadius); - - // arc frame - Handles.color = new Color(0, 1, 1, 0.7f); - Handles.DrawWireArc(center, Vector3.back, fromAngle, surfaceArc, arcRadius); - Handles.DrawDottedLine(center, center + fromAngle * arcRadius, 5.0f); - Handles.DrawDottedLine(center, center + toAngle * arcRadius, 5.0f); - } - } - - private static void DrawSideArc(PlatformEffector2D effector) - { - // Calculate the surface angle in local-space. - var rotation = -Mathf.Deg2Rad * (90.0f + effector.rotationalOffset); - var localSide = effector.transform.TransformVector(new Vector3(Mathf.Sin(rotation), Mathf.Cos(rotation), 0.0f)).normalized; - - // If the transform has created a degenerate local then we cannot draw the gizmo! - if (localSide.sqrMagnitude < Mathf.Epsilon) - return; - - // Calculate the side angles. - var sideAngleLeft = Mathf.Atan2(localSide.x, localSide.y); - var sideAngleRight = sideAngleLeft + Mathf.PI; - - // Fetch the side arc. - var sideArc = Mathf.Clamp(effector.sideArc, 0.5f, 180.0f); - var halfSideArcRadians = sideArc * 0.5f * Mathf.Deg2Rad; - - var fromAngleLeft = new Vector3(Mathf.Sin(sideAngleLeft - halfSideArcRadians), Mathf.Cos(sideAngleLeft - halfSideArcRadians), 0.0f); - var toAngleLeft = new Vector3(Mathf.Sin(sideAngleLeft + halfSideArcRadians), Mathf.Cos(sideAngleLeft + halfSideArcRadians), 0.0f); - var fromAngleRight = new Vector3(Mathf.Sin(sideAngleRight - halfSideArcRadians), Mathf.Cos(sideAngleRight - halfSideArcRadians), 0.0f); - var toAngleRight = new Vector3(Mathf.Sin(sideAngleRight + halfSideArcRadians), Mathf.Cos(sideAngleRight + halfSideArcRadians), 0.0f); - - // Fetch all the effector-collider bounds. - foreach (var collider in effector.gameObject.GetComponents().Where(collider => collider.enabled && collider.usedByEffector)) - { - var center = collider.bounds.center; - var arcRadius = HandleUtility.GetHandleSize(center) * 0.8f; - - // arc background - Handles.color = new Color(0, 1, 0.7f, 0.07f); - Handles.DrawSolidArc(center, Vector3.back, fromAngleLeft, sideArc, arcRadius); - Handles.DrawSolidArc(center, Vector3.back, fromAngleRight, sideArc, arcRadius); - - // arc frame - Handles.color = new Color(0, 1, 0.7f, 0.7f); - Handles.DrawWireArc(center, Vector3.back, fromAngleLeft, sideArc, arcRadius); - Handles.DrawWireArc(center, Vector3.back, fromAngleRight, sideArc, arcRadius); - Handles.DrawDottedLine(center, center + fromAngleLeft * arcRadius, 5.0f); - Handles.DrawDottedLine(center, center + toAngleLeft * arcRadius, 5.0f); - Handles.DrawDottedLine(center, center + fromAngleRight * arcRadius, 5.0f); - Handles.DrawDottedLine(center, center + toAngleRight * arcRadius, 5.0f); - } - } - } -} diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs deleted file mode 100644 index 6b1e458adc..0000000000 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ /dev/null @@ -1,2440 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEngine; -using UnityEditor.Build; -using UnityEditor.SceneManagement; -using UnityEditor.PlatformSupport; -using UnityEditor.Rendering; -using UnityEditorInternal; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using UnityEditor.Modules; -using UnityEditor.Scripting.ScriptCompilation; -using GraphicsDeviceType = UnityEngine.Rendering.GraphicsDeviceType; -using VR = UnityEditorInternal.VR; - -// ************************************* READ BEFORE EDITING ************************************** -// -// DO NOT COPY/PASTE! Please do not have the same setting more than once in the code. -// If a setting for one platform needs to be exposed to more platforms, -// change the if statements so the same lines of code are executed for both platforms, -// instead of copying the lines into multiple code blocks. -// This ensures that if we change labels, or headers, or the order of settings, it will remain -// consistent without having to remember to make the same change multiple places. THANK YOU! -// -// ADD_NEW_PLATFORM_HERE: review this file - -namespace UnityEditor -{ - [CustomEditor(typeof(PlayerSettings))] - internal partial class PlayerSettingsEditor : Editor - { - static class Styles - { - public static readonly GUIStyle categoryBox = new GUIStyle(EditorStyles.helpBox); - - public static readonly GUIContent colorSpaceAndroidWarning = EditorGUIUtility.TrTextContent("Linear colorspace requires OpenGL ES 3.0 or Vulkan, uncheck 'Automatic Graphics API' to remove OpenGL ES 2 API, Blit Type must be Always Blit or Auto and 'Minimum API Level' must be at least Android 4.3"); - public static readonly GUIContent colorSpaceWebGLWarning = EditorGUIUtility.TrTextContent("Linear colorspace requires WebGL 2.0, uncheck 'Automatic Graphics API' to remove WebGL 1.0 API. WARNING: If DXT sRGB is not supported by the browser, texture will be decompressed"); - public static readonly GUIContent colorSpaceIOSWarning = EditorGUIUtility.TrTextContent("Linear colorspace requires Metal API only. Uncheck 'Automatic Graphics API' and remove OpenGL ES 2 API. Additionally, 'minimum iOS version' set to 8.0 at least"); - public static readonly GUIContent colorSpaceTVOSWarning = EditorGUIUtility.TrTextContent("Linear colorspace requires Metal API only. Uncheck 'Automatic Graphics API' and remove OpenGL ES 2 API."); - public static readonly GUIContent recordingInfo = EditorGUIUtility.TrTextContent("Reordering the list will switch editor to the first available platform"); - public static readonly GUIContent notApplicableInfo = EditorGUIUtility.TrTextContent("Not applicable for this platform."); - public static readonly GUIContent sharedBetweenPlatformsInfo = EditorGUIUtility.TrTextContent("* Shared setting between multiple platforms."); - public static readonly GUIContent vrOrientationInfo = EditorGUIUtility.TrTextContent("Virtual Reality Support is enabled. Upon entering VR mode, landscape left orientation will be the default orientation unless only landscape right is available."); - public static readonly GUIContent IL2CPPAndroidExperimentalInfo = EditorGUIUtility.TrTextContent("IL2CPP on Android is experimental and unsupported"); - - public static readonly GUIContent cursorHotspot = EditorGUIUtility.TrTextContent("Cursor Hotspot"); - public static readonly GUIContent defaultCursor = EditorGUIUtility.TrTextContent("Default Cursor"); - public static readonly GUIContent defaultIcon = EditorGUIUtility.TrTextContent("Default Icon"); - 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."); - - public static readonly GUIContent iconTitle = EditorGUIUtility.TrTextContent("Icon"); - public static readonly GUIContent resolutionPresentationTitle = EditorGUIUtility.TrTextContent("Resolution and Presentation"); - public static readonly GUIContent resolutionTitle = EditorGUIUtility.TrTextContent("Resolution"); - public static readonly GUIContent orientationTitle = EditorGUIUtility.TrTextContent("Orientation"); - public static readonly GUIContent allowedOrientationTitle = EditorGUIUtility.TrTextContent("Allowed Orientations for Auto Rotation"); - public static readonly GUIContent multitaskingSupportTitle = EditorGUIUtility.TrTextContent("Multitasking Support"); - public static readonly GUIContent statusBarTitle = EditorGUIUtility.TrTextContent("Status Bar"); - public static readonly GUIContent standalonePlayerOptionsTitle = EditorGUIUtility.TrTextContent("Standalone Player Options"); - public static readonly GUIContent debuggingCrashReportingTitle = EditorGUIUtility.TrTextContent("Debugging and crash reporting"); - public static readonly GUIContent debuggingTitle = EditorGUIUtility.TrTextContent("Debugging"); - public static readonly GUIContent crashReportingTitle = EditorGUIUtility.TrTextContent("Crash Reporting"); - public static readonly GUIContent otherSettingsTitle = EditorGUIUtility.TrTextContent("Other Settings"); - public static readonly GUIContent renderingTitle = EditorGUIUtility.TrTextContent("Rendering"); - public static readonly GUIContent identificationTitle = EditorGUIUtility.TrTextContent("Identification"); - public static readonly GUIContent macAppStoreTitle = EditorGUIUtility.TrTextContent("Mac App Store Options"); - public static readonly GUIContent configurationTitle = EditorGUIUtility.TrTextContent("Configuration"); - public static readonly GUIContent optimizationTitle = EditorGUIUtility.TrTextContent("Optimization"); - public static readonly GUIContent loggingTitle = EditorGUIUtility.TrTextContent("Logging*"); - public static readonly GUIContent publishingSettingsTitle = EditorGUIUtility.TrTextContent("Publishing Settings"); - - public static readonly GUIContent bakeCollisionMeshes = EditorGUIUtility.TrTextContent("Prebake Collision Meshes*", "Bake collision data into the meshes on build time"); - public static readonly GUIContent keepLoadedShadersAlive = EditorGUIUtility.TrTextContent("Keep Loaded Shaders Alive*", "Prevents shaders from being unloaded"); - 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"); - 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."); - public static readonly GUIContent iPhoneStrippingLevel = EditorGUIUtility.TrTextContent("Stripping Level*"); - public static readonly GUIContent iPhoneScriptCallOptimization = EditorGUIUtility.TrTextContent("Script Call Optimization*"); - public static readonly GUIContent enableInternalProfiler = EditorGUIUtility.TrTextContent("Enable Internal Profiler* (Deprecated)", "Internal profiler counters should be accessed by scripts using UnityEngine.Profiling::Profiler API."); - public static readonly GUIContent stripUnusedMeshComponents = EditorGUIUtility.TrTextContent("Optimize Mesh Data*", "Remove unused mesh components"); - public static readonly GUIContent videoMemoryForVertexBuffers = EditorGUIUtility.TrTextContent("Mesh Video Mem*", "How many megabytes of video memory to use for mesh data before we use main memory"); - public static readonly GUIContent protectGraphicsMemory = EditorGUIUtility.TrTextContent("Protect Graphics Memory", "Protect GPU memory from being read (on supported devices). Will prevent user from taking screenshots"); - public static readonly GUIContent useOSAutoRotation = EditorGUIUtility.TrTextContent("Use Animated Autorotation", "If set OS native animated autorotation method will be used. Otherwise orientation will be changed immediately."); - public static readonly GUIContent UIPrerenderedIcon = EditorGUIUtility.TrTextContent("Prerendered Icon"); - public static readonly GUIContent defaultScreenWidth = EditorGUIUtility.TrTextContent("Default Screen Width"); - public static readonly GUIContent defaultScreenHeight = EditorGUIUtility.TrTextContent("Default Screen Height"); - public static readonly GUIContent macRetinaSupport = EditorGUIUtility.TrTextContent("Mac Retina Support"); - public static readonly GUIContent runInBackground = EditorGUIUtility.TrTextContent("Run In Background*"); - public static readonly GUIContent defaultScreenOrientation = EditorGUIUtility.TrTextContent("Default Orientation*"); - public static readonly GUIContent allowedAutoRotateToPortrait = EditorGUIUtility.TrTextContent("Portrait"); - public static readonly GUIContent allowedAutoRotateToPortraitUpsideDown = EditorGUIUtility.TrTextContent("Portrait Upside Down"); - public static readonly GUIContent allowedAutoRotateToLandscapeRight = EditorGUIUtility.TrTextContent("Landscape Right"); - public static readonly GUIContent allowedAutoRotateToLandscapeLeft = EditorGUIUtility.TrTextContent("Landscape Left"); - public static readonly GUIContent UIRequiresFullScreen = EditorGUIUtility.TrTextContent("Requires Fullscreen"); - public static readonly GUIContent UIStatusBarHidden = EditorGUIUtility.TrTextContent("Status Bar Hidden"); - public static readonly GUIContent UIStatusBarStyle = EditorGUIUtility.TrTextContent("Status Bar Style"); - public static readonly GUIContent useMacAppStoreValidation = EditorGUIUtility.TrTextContent("Mac App Store Validation"); - public static readonly GUIContent macAppStoreCategory = EditorGUIUtility.TrTextContent("Category", "'LSApplicationCategoryType'"); - public static readonly GUIContent fullscreenMode = EditorGUIUtility.TrTextContent("Fullscreen Mode ", " Not all platforms support all modes"); - public static readonly GUIContent exclusiveFullscreen = EditorGUIUtility.TrTextContent("Exclusive Fullscreen"); - public static readonly GUIContent fullscreenWindow = EditorGUIUtility.TrTextContent("Fullscreen Window"); - public static readonly GUIContent maximizedWindow = EditorGUIUtility.TrTextContent("Maximized Window"); - public static readonly GUIContent windowed = EditorGUIUtility.TrTextContent("Windowed"); - public static readonly GUIContent visibleInBackground = EditorGUIUtility.TrTextContent("Visible In Background"); - public static readonly GUIContent allowFullscreenSwitch = EditorGUIUtility.TrTextContent("Allow Fullscreen Switch"); - 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."); - public static readonly GUIContent disableDepthAndStencilBuffers = EditorGUIUtility.TrTextContent("Disable Depth and Stencil*"); - public static readonly GUIContent iosShowActivityIndicatorOnLoading = EditorGUIUtility.TrTextContent("Show Loading Indicator"); - public static readonly GUIContent androidShowActivityIndicatorOnLoading = EditorGUIUtility.TrTextContent("Show Loading Indicator"); - public static readonly GUIContent actionOnDotNetUnhandledException = EditorGUIUtility.TrTextContent("On .Net UnhandledException*"); - public static readonly GUIContent logObjCUncaughtExceptions = EditorGUIUtility.TrTextContent("Log Obj-C Uncaught Exceptions*"); - public static readonly GUIContent enableCrashReportAPI = EditorGUIUtility.TrTextContent("Enable CrashReport API*"); - public static readonly GUIContent activeColorSpace = EditorGUIUtility.TrTextContent("Color Space*"); - public static readonly GUIContent colorGamut = EditorGUIUtility.TrTextContent("Color Gamut*"); - public static readonly GUIContent colorGamutForMac = EditorGUIUtility.TrTextContent("Color Gamut For Mac*"); - public static readonly GUIContent metalForceHardShadows = EditorGUIUtility.TrTextContent("Force hard shadows on Metal*"); - public static readonly GUIContent metalEditorSupport = EditorGUIUtility.TextContent("Metal Editor Support*"); - public static readonly GUIContent metalAPIValidation = EditorGUIUtility.TrTextContent("Metal API Validation*"); - public static readonly GUIContent metalFramebufferOnly = EditorGUIUtility.TrTextContent("Metal Restricted Backbuffer Use", "Set framebufferOnly flag on backbuffer. This prevents readback from backbuffer but enables some driver optimizations."); - public static readonly GUIContent mTRendering = EditorGUIUtility.TrTextContent("Multithreaded Rendering*"); - public static readonly GUIContent staticBatching = EditorGUIUtility.TrTextContent("Static Batching"); - public static readonly GUIContent dynamicBatching = EditorGUIUtility.TrTextContent("Dynamic Batching"); - public static readonly GUIContent graphicsJobs = EditorGUIUtility.TrTextContent("Graphics Jobs (Experimental)*"); - public static readonly GUIContent graphicsJobsMode = EditorGUIUtility.TrTextContent("Graphics Jobs Mode*"); - public static readonly GUIContent applicationBuildNumber = EditorGUIUtility.TrTextContent("Build"); - 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."); - public static readonly GUIContent useOnDemandResources = EditorGUIUtility.TrTextContent("Use on demand resources*"); - public static readonly GUIContent accelerometerFrequency = EditorGUIUtility.TrTextContent("Accelerometer Frequency*"); - public static readonly GUIContent cameraUsageDescription = EditorGUIUtility.TrTextContent("Camera Usage Description*"); - public static readonly GUIContent locationUsageDescription = EditorGUIUtility.TrTextContent("Location Usage Description*"); - public static readonly GUIContent microphoneUsageDescription = EditorGUIUtility.TrTextContent("Microphone Usage Description*"); - public static readonly GUIContent muteOtherAudioSources = EditorGUIUtility.TrTextContent("Mute Other Audio Sources*"); - public static readonly GUIContent prepareIOSForRecording = EditorGUIUtility.TrTextContent("Prepare iOS for Recording"); - public static readonly GUIContent forceIOSSpeakersWhenRecording = EditorGUIUtility.TrTextContent("Force iOS Speakers when Recording"); - public static readonly GUIContent UIRequiresPersistentWiFi = EditorGUIUtility.TrTextContent("Requires Persistent WiFi*"); - public static readonly GUIContent iOSAllowHTTPDownload = EditorGUIUtility.TrTextContent("Allow downloads over HTTP (nonsecure)*"); - public static readonly GUIContent iOSURLSchemes = EditorGUIUtility.TrTextContent("Supported URL schemes*"); - public static readonly GUIContent aotOptions = EditorGUIUtility.TrTextContent("AOT Compilation Options*"); - public static readonly GUIContent require31 = EditorGUIUtility.TrTextContent("Require ES3.1"); - public static readonly GUIContent requireAEP = EditorGUIUtility.TrTextContent("Require ES3.1+AEP"); - public static readonly GUIContent skinOnGPU = EditorGUIUtility.TrTextContent("GPU Skinning*", "Use DX11/ES3 GPU Skinning"); - public static readonly GUIContent skinOnGPUPS4 = EditorGUIUtility.TrTextContent("Compute Skinning*", "Use Compute pipeline for Skinning"); - public static readonly GUIContent skinOnGPUAndroidWarning = EditorGUIUtility.TrTextContent("GPU skinning on Android devices is only enabled in VR builds, and is experimental. Be sure to validate behavior and performance on your target devices."); - public static readonly GUIContent disableStatistics = EditorGUIUtility.TrTextContent("Disable HW Statistics*", "Disables HW Statistics (Pro Only)"); - public static readonly GUIContent scriptingDefineSymbols = EditorGUIUtility.TrTextContent("Scripting Define Symbols*"); - public static readonly GUIContent scriptingRuntimeVersion = EditorGUIUtility.TrTextContent("Scripting Runtime Version*", "The scripting runtime version to be used. Unity uses different scripting backends based on platform, so these options are listed as equivalent expected behavior."); - public static readonly GUIContent scriptingRuntimeVersionLegacy = EditorGUIUtility.TrTextContent("Legacy (.NET 3.5 Equivalent)"); - public static readonly GUIContent scriptingRuntimeVersionLatest = EditorGUIUtility.TrTextContent("Stable (.NET 4.x Equivalent)"); - public static readonly GUIContent scriptingBackend = EditorGUIUtility.TrTextContent("Scripting Backend"); - public static readonly GUIContent il2cppCompilerConfiguration = EditorGUIUtility.TrTextContent("C++ Compiler Configuration"); - public static readonly GUIContent scriptingMono2x = EditorGUIUtility.TrTextContent("Mono"); - public static readonly GUIContent scriptingWinRTDotNET = EditorGUIUtility.TrTextContent(".NET"); - public static readonly GUIContent scriptingIL2CPP = EditorGUIUtility.TrTextContent("IL2CPP"); - public static readonly GUIContent scriptingDefault = EditorGUIUtility.TrTextContent("Default"); - public static readonly GUIContent apiCompatibilityLevel = EditorGUIUtility.TrTextContent("Api Compatibility Level*"); - public static readonly GUIContent apiCompatibilityLevel_NET_2_0 = EditorGUIUtility.TrTextContent(".NET 2.0"); - public static readonly GUIContent apiCompatibilityLevel_NET_2_0_Subset = EditorGUIUtility.TrTextContent(".NET 2.0 Subset"); - public static readonly GUIContent apiCompatibilityLevel_NET_4_6 = EditorGUIUtility.TrTextContent(".NET 4.x"); - public static readonly GUIContent apiCompatibilityLevel_NET_Standard_2_0 = EditorGUIUtility.TrTextContent(".NET Standard 2.0"); - public static readonly GUIContent allowUnsafeCode = EditorGUIUtility.TrTextContent("Allow 'unsafe' Code", "Allow compilation of unsafe code for predefined assemblies (Assembly-CSharp.dll, etc.)"); - public static readonly GUIContent activeInputHandling = EditorGUIUtility.TrTextContent("Active Input Handling*"); - public static readonly GUIContent[] activeInputHandlingOptions = new GUIContent[] { EditorGUIUtility.TrTextContent("Input Manager"), EditorGUIUtility.TrTextContent("Input System (Preview)"), EditorGUIUtility.TrTextContent("Both") }; - public static readonly GUIContent vrSettingsMoved = EditorGUIUtility.TrTextContent("Virtual Reality moved to XR Settings"); - public static readonly GUIContent lightmapEncodingLabel = EditorGUIUtility.TrTextContent("Lightmap Encoding", "Affects the encoding scheme and compression format of the lightmaps."); - public static readonly GUIContent[] lightmapEncodingNames = { EditorGUIUtility.TrTextContent("Normal Quality"), EditorGUIUtility.TrTextContent("High Quality")}; - public static readonly GUIContent monoNotSupportediOS11WarningGUIContent = EditorGUIUtility.TrTextContent("Mono is not supported on iOS11 and above."); - public static string undoChangedBundleIdentifierString { get { return LocalizationDatabase.GetLocalizedString("Changed macOS bundleIdentifier"); } } - public static string undoChangedBuildNumberString { get { return LocalizationDatabase.GetLocalizedString("Changed macOS build number"); } } - public static string undoChangedBatchingString { get { return LocalizationDatabase.GetLocalizedString("Changed Batching Settings"); } } - public static string undoChangedIconString { get { return LocalizationDatabase.GetLocalizedString("Changed Icon"); } } - public static string undoChangedGraphicsAPIString { get { return LocalizationDatabase.GetLocalizedString("Changed Graphics API Settings"); } } - - static Styles() - { - categoryBox.padding.left = 14; - } - } - - // Icon layout constants - const int kSlotSize = 64; - const int kMaxPreviewSize = 96; - const int kIconSpacing = 6; - - PlayerSettingsSplashScreenEditor m_SplashScreenEditor; - PlayerSettingsSplashScreenEditor splashScreenEditor - { - get - { - if (m_SplashScreenEditor == null) - m_SplashScreenEditor = new PlayerSettingsSplashScreenEditor(this); - return m_SplashScreenEditor; - } - } - - private static GraphicsJobMode[] m_GfxJobModeValues = new GraphicsJobMode[] { GraphicsJobMode.Native, GraphicsJobMode.Legacy }; - private static GUIContent[] m_GfxJobModeNames = new GUIContent[] { EditorGUIUtility.TrTextContent("Native"), EditorGUIUtility.TrTextContent("Legacy") }; - - // Section and tab selection state - - SavedInt m_SelectedSection = new SavedInt("PlayerSettings.ShownSection", -1); - - BuildPlatform[] validPlatforms; - - // il2cpp - SerializedProperty m_StripEngineCode; - - // macOS - SerializedProperty m_ApplicationBundleVersion; - SerializedProperty m_UseMacAppStoreValidation; - SerializedProperty m_MacAppStoreCategory; - - // iOS, tvOS -#pragma warning disable 169 - SerializedProperty m_IPhoneApplicationDisplayName; - - SerializedProperty m_CameraUsageDescription; - SerializedProperty m_LocationUsageDescription; - SerializedProperty m_MicrophoneUsageDescription; - - SerializedProperty m_IPhoneStrippingLevel; - SerializedProperty m_IPhoneScriptCallOptimization; - SerializedProperty m_AotOptions; - - SerializedProperty m_DefaultScreenOrientation; - SerializedProperty m_AllowedAutoRotateToPortrait; - SerializedProperty m_AllowedAutoRotateToPortraitUpsideDown; - SerializedProperty m_AllowedAutoRotateToLandscapeRight; - SerializedProperty m_AllowedAutoRotateToLandscapeLeft; - SerializedProperty m_UseOSAutoRotation; - SerializedProperty m_Use32BitDisplayBuffer; - SerializedProperty m_DisableDepthAndStencilBuffers; - SerializedProperty m_iosShowActivityIndicatorOnLoading; - SerializedProperty m_androidShowActivityIndicatorOnLoading; - SerializedProperty m_tizenShowActivityIndicatorOnLoading; - - SerializedProperty m_AndroidProfiler; - - SerializedProperty m_UIPrerenderedIcon; - SerializedProperty m_UIRequiresPersistentWiFi; - SerializedProperty m_UIStatusBarHidden; - SerializedProperty m_UIRequiresFullScreen; - SerializedProperty m_UIStatusBarStyle; - - SerializedProperty m_IOSAllowHTTPDownload; - SerializedProperty m_SubmitAnalytics; - - SerializedProperty m_IOSURLSchemes; - - SerializedProperty m_AccelerometerFrequency; - SerializedProperty m_useOnDemandResources; - SerializedProperty m_MuteOtherAudioSources; - SerializedProperty m_PrepareIOSForRecording; - SerializedProperty m_ForceIOSSpeakersWhenRecording; - - SerializedProperty m_EnableInternalProfiler; - SerializedProperty m_ActionOnDotNetUnhandledException; - SerializedProperty m_LogObjCUncaughtExceptions; - SerializedProperty m_EnableCrashReportAPI; - SerializedProperty m_EnableInputSystem; - SerializedProperty m_DisableInputManager; - - SerializedProperty m_AllowUnsafeCode; - - // vita - SerializedProperty m_VideoMemoryForVertexBuffers; - - // General - SerializedProperty m_CompanyName; - SerializedProperty m_ProductName; - - // Cursor - SerializedProperty m_DefaultCursor; - SerializedProperty m_CursorHotspot; - - // Screen - SerializedProperty m_DefaultScreenWidth; - SerializedProperty m_DefaultScreenHeight; - - SerializedProperty m_ActiveColorSpace; - SerializedProperty m_StripUnusedMeshComponents; - SerializedProperty m_VertexChannelCompressionMask; - SerializedProperty m_MetalEditorSupport; - SerializedProperty m_MetalAPIValidation; - SerializedProperty m_MetalFramebufferOnly; - SerializedProperty m_MetalForceHardShadows; - - SerializedProperty m_DisplayResolutionDialog; - SerializedProperty m_DefaultIsNativeResolution; - SerializedProperty m_MacRetinaSupport; - - SerializedProperty m_UsePlayerLog; - SerializedProperty m_KeepLoadedShadersAlive; - SerializedProperty m_PreloadedAssets; - SerializedProperty m_BakeCollisionMeshes; - SerializedProperty m_ResizableWindow; - SerializedProperty m_FullscreenMode; - SerializedProperty m_VisibleInBackground; - SerializedProperty m_AllowFullscreenSwitch; - SerializedProperty m_ForceSingleInstance; - - SerializedProperty m_RunInBackground; - SerializedProperty m_CaptureSingleScreen; - - SerializedProperty m_SupportedAspectRatios; - - SerializedProperty m_SkinOnGPU; - SerializedProperty m_GraphicsJobs; - - // OpenGL ES 3.1 - SerializedProperty m_RequireES31; - SerializedProperty m_RequireES31AEP; - - SerializedProperty m_LightmapEncodingQuality; - - // Localization Cache - string m_LocalizedTargetName; - - // reorderable lists of graphics devices, per platform - static Dictionary s_GraphicsDeviceLists = new Dictionary(); - - public static void SyncPlatformAPIsList(BuildTarget target) - { - if (!s_GraphicsDeviceLists.ContainsKey(target)) - return; - s_GraphicsDeviceLists[target].list = PlayerSettings.GetGraphicsAPIs(target).ToList(); - } - - static ReorderableList s_ColorGamutList; - - public static void SyncColorGamuts() - { - s_ColorGamutList.list = PlayerSettings.GetColorGamuts().ToList(); - } - - public VR.PlayerSettingsEditorVR m_VRSettings; - - int selectedPlatform = 0; - int scriptingDefinesControlID = 0; - ISettingEditorExtension[] m_SettingsExtensions; - - // Section animation state - const int kNumberGUISections = 7; - AnimBool[] m_SectionAnimators = new AnimBool[kNumberGUISections]; - readonly AnimBool m_ShowDefaultIsNativeResolution = new AnimBool(); - readonly AnimBool m_ShowResolution = new AnimBool(); - private static Texture2D s_WarningIcon; - - public bool IsMobileTarget(BuildTargetGroup targetGroup) - { - return targetGroup == BuildTargetGroup.iOS - || targetGroup == BuildTargetGroup.tvOS - || targetGroup == BuildTargetGroup.Android - || targetGroup == BuildTargetGroup.Tizen; - } - - public SerializedProperty FindPropertyAssert(string name) - { - SerializedProperty property = serializedObject.FindProperty(name); - if (property == null) - Debug.LogError("Failed to find:" + name); - return property; - } - - void OnEnable() - { - validPlatforms = BuildPlatforms.instance.GetValidPlatforms(true).ToArray(); - - m_IPhoneStrippingLevel = FindPropertyAssert("iPhoneStrippingLevel"); - m_StripEngineCode = FindPropertyAssert("stripEngineCode"); - - m_IPhoneScriptCallOptimization = FindPropertyAssert("iPhoneScriptCallOptimization"); - m_AndroidProfiler = FindPropertyAssert("AndroidProfiler"); - m_CompanyName = FindPropertyAssert("companyName"); - m_ProductName = FindPropertyAssert("productName"); - - m_DefaultCursor = FindPropertyAssert("defaultCursor"); - m_CursorHotspot = FindPropertyAssert("cursorHotspot"); - - - m_UIPrerenderedIcon = FindPropertyAssert("uIPrerenderedIcon"); - - m_UIRequiresFullScreen = FindPropertyAssert("uIRequiresFullScreen"); - - m_UIStatusBarHidden = FindPropertyAssert("uIStatusBarHidden"); - m_UIStatusBarStyle = FindPropertyAssert("uIStatusBarStyle"); - m_ActiveColorSpace = FindPropertyAssert("m_ActiveColorSpace"); - m_StripUnusedMeshComponents = FindPropertyAssert("StripUnusedMeshComponents"); - m_VertexChannelCompressionMask = FindPropertyAssert("VertexChannelCompressionMask"); - m_MetalEditorSupport = FindPropertyAssert("metalEditorSupport"); - m_MetalAPIValidation = FindPropertyAssert("metalAPIValidation"); - m_MetalFramebufferOnly = FindPropertyAssert("metalFramebufferOnly"); - m_MetalForceHardShadows = FindPropertyAssert("iOSMetalForceHardShadows"); - - m_ApplicationBundleVersion = serializedObject.FindProperty("bundleVersion"); - if (m_ApplicationBundleVersion == null) - m_ApplicationBundleVersion = FindPropertyAssert("iPhoneBundleVersion"); - - m_useOnDemandResources = FindPropertyAssert("useOnDemandResources"); - m_AccelerometerFrequency = FindPropertyAssert("accelerometerFrequency"); - - m_MuteOtherAudioSources = FindPropertyAssert("muteOtherAudioSources"); - m_PrepareIOSForRecording = FindPropertyAssert("Prepare IOS For Recording"); - m_ForceIOSSpeakersWhenRecording = FindPropertyAssert("Force IOS Speakers When Recording"); - m_UIRequiresPersistentWiFi = FindPropertyAssert("uIRequiresPersistentWiFi"); - m_IOSAllowHTTPDownload = FindPropertyAssert("iosAllowHTTPDownload"); - m_SubmitAnalytics = FindPropertyAssert("submitAnalytics"); - - m_IOSURLSchemes = FindPropertyAssert("iOSURLSchemes"); - - m_AotOptions = FindPropertyAssert("aotOptions"); - - m_CameraUsageDescription = FindPropertyAssert("cameraUsageDescription"); - m_LocationUsageDescription = FindPropertyAssert("locationUsageDescription"); - m_MicrophoneUsageDescription = FindPropertyAssert("microphoneUsageDescription"); - - m_EnableInternalProfiler = FindPropertyAssert("enableInternalProfiler"); - m_ActionOnDotNetUnhandledException = FindPropertyAssert("actionOnDotNetUnhandledException"); - m_LogObjCUncaughtExceptions = FindPropertyAssert("logObjCUncaughtExceptions"); - m_EnableCrashReportAPI = FindPropertyAssert("enableCrashReportAPI"); - m_EnableInputSystem = FindPropertyAssert("enableNativePlatformBackendsForNewInputSystem"); - m_DisableInputManager = FindPropertyAssert("disableOldInputManagerSupport"); - - m_AllowUnsafeCode = FindPropertyAssert("allowUnsafeCode"); - - m_DefaultScreenWidth = FindPropertyAssert("defaultScreenWidth"); - m_DefaultScreenHeight = FindPropertyAssert("defaultScreenHeight"); - m_RunInBackground = FindPropertyAssert("runInBackground"); - - m_DefaultScreenOrientation = FindPropertyAssert("defaultScreenOrientation"); - m_AllowedAutoRotateToPortrait = FindPropertyAssert("allowedAutorotateToPortrait"); - m_AllowedAutoRotateToPortraitUpsideDown = FindPropertyAssert("allowedAutorotateToPortraitUpsideDown"); - m_AllowedAutoRotateToLandscapeRight = FindPropertyAssert("allowedAutorotateToLandscapeRight"); - m_AllowedAutoRotateToLandscapeLeft = FindPropertyAssert("allowedAutorotateToLandscapeLeft"); - m_UseOSAutoRotation = FindPropertyAssert("useOSAutorotation"); - m_Use32BitDisplayBuffer = FindPropertyAssert("use32BitDisplayBuffer"); - m_DisableDepthAndStencilBuffers = FindPropertyAssert("disableDepthAndStencilBuffers"); - m_iosShowActivityIndicatorOnLoading = FindPropertyAssert("iosShowActivityIndicatorOnLoading"); - m_androidShowActivityIndicatorOnLoading = FindPropertyAssert("androidShowActivityIndicatorOnLoading"); - m_tizenShowActivityIndicatorOnLoading = FindPropertyAssert("tizenShowActivityIndicatorOnLoading"); - - m_DefaultIsNativeResolution = FindPropertyAssert("defaultIsNativeResolution"); - m_MacRetinaSupport = FindPropertyAssert("macRetinaSupport"); - m_CaptureSingleScreen = FindPropertyAssert("captureSingleScreen"); - m_DisplayResolutionDialog = FindPropertyAssert("displayResolutionDialog"); - m_SupportedAspectRatios = FindPropertyAssert("m_SupportedAspectRatios"); - m_UsePlayerLog = FindPropertyAssert("usePlayerLog"); - - m_KeepLoadedShadersAlive = FindPropertyAssert("keepLoadedShadersAlive"); - m_PreloadedAssets = FindPropertyAssert("preloadedAssets"); - m_BakeCollisionMeshes = FindPropertyAssert("bakeCollisionMeshes"); - m_ResizableWindow = FindPropertyAssert("resizableWindow"); - m_UseMacAppStoreValidation = FindPropertyAssert("useMacAppStoreValidation"); - m_MacAppStoreCategory = FindPropertyAssert("macAppStoreCategory"); - m_FullscreenMode = FindPropertyAssert("fullscreenMode"); - m_VisibleInBackground = FindPropertyAssert("visibleInBackground"); - m_AllowFullscreenSwitch = FindPropertyAssert("allowFullscreenSwitch"); - m_SkinOnGPU = FindPropertyAssert("gpuSkinning"); - m_GraphicsJobs = FindPropertyAssert("graphicsJobs"); - m_ForceSingleInstance = FindPropertyAssert("forceSingleInstance"); - - m_RequireES31 = FindPropertyAssert("openGLRequireES31"); - m_RequireES31AEP = FindPropertyAssert("openGLRequireES31AEP"); - - m_VideoMemoryForVertexBuffers = FindPropertyAssert("videoMemoryForVertexBuffers"); - - m_SettingsExtensions = new ISettingEditorExtension[validPlatforms.Length]; - for (int i = 0; i < validPlatforms.Length; i++) - { - string module = ModuleManager.GetTargetStringFromBuildTargetGroup(validPlatforms[i].targetGroup); - m_SettingsExtensions[i] = ModuleManager.GetEditorSettingsExtension(module); - if (m_SettingsExtensions[i] != null) - m_SettingsExtensions[i].OnEnable(this); - } - - for (int i = 0; i < m_SectionAnimators.Length; i++) - m_SectionAnimators[i] = new AnimBool(m_SelectedSection.value == i, Repaint); - - m_ShowDefaultIsNativeResolution.valueChanged.AddListener(Repaint); - m_ShowResolution.valueChanged.AddListener(Repaint); - - m_VRSettings = new VR.PlayerSettingsEditorVR(this); - - splashScreenEditor.OnEnable(); - - // we clear it just to be on the safe side: - // we access this cache both from player settings editor and script side when changing api - s_GraphicsDeviceLists.Clear(); - } - - public override bool UseDefaultMargins() - { - return false; - } - - internal override string targetTitle - { - get - { - if (m_LocalizedTargetName == null) - m_LocalizedTargetName = L10n.Tr(target.name); - return m_LocalizedTargetName; - } - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins); - { - CommonSettings(); - } - EditorGUILayout.EndVertical(); - - EditorGUILayout.Space(); - - EditorGUI.BeginChangeCheck(); - int oldPlatform = selectedPlatform; - selectedPlatform = EditorGUILayout.BeginPlatformGrouping(validPlatforms, null); - if (EditorGUI.EndChangeCheck()) - { - // Awesome hackery to get string from delayed textfield when switching platforms - if (EditorGUI.s_DelayedTextEditor.IsEditingControl(scriptingDefinesControlID)) - { - EditorGUI.EndEditingActiveTextField(); - GUIUtility.keyboardControl = 0; - PlayerSettings.SetScriptingDefineSymbolsForGroup(validPlatforms[oldPlatform].targetGroup, EditorGUI.s_DelayedTextEditor.text); - } - // Reset focus when changing between platforms. - // If we don't do this, the resolution width/height value will not update correctly when they have the focus - GUI.FocusControl(""); - } - GUILayout.Label(string.Format(L10n.Tr("Settings for {0}"), validPlatforms[selectedPlatform].title.text)); - - // Compensate so settings inside boxes line up with settings at the top, though keep a minimum of 150. - EditorGUIUtility.labelWidth = Mathf.Max(150, EditorGUIUtility.labelWidth - 8); - - BuildPlatform platform = validPlatforms[selectedPlatform]; - BuildTargetGroup targetGroup = platform.targetGroup; - - int sectionIndex = 0; - - IconSectionGUI(targetGroup, m_SettingsExtensions[selectedPlatform], sectionIndex++); - ResolutionSectionGUI(targetGroup, m_SettingsExtensions[selectedPlatform], sectionIndex++); - m_SplashScreenEditor.SplashSectionGUI(platform, targetGroup, m_SettingsExtensions[selectedPlatform], sectionIndex++); - DebugAndCrashReportingGUI(platform, targetGroup, m_SettingsExtensions[selectedPlatform], sectionIndex++); - OtherSectionGUI(platform, targetGroup, m_SettingsExtensions[selectedPlatform], sectionIndex++); - PublishSectionGUI(targetGroup, m_SettingsExtensions[selectedPlatform], sectionIndex++); - m_VRSettings.XRSectionGUI(targetGroup, sectionIndex++); - - if (sectionIndex != kNumberGUISections) - Debug.LogError("Mismatched number of GUI sections."); - - EditorGUILayout.EndPlatformGrouping(); - - serializedObject.ApplyModifiedProperties(); - } - - private void CommonSettings() - { - EditorGUILayout.PropertyField(m_CompanyName); - EditorGUILayout.PropertyField(m_ProductName); - EditorGUILayout.Space(); - - // Get icons and icon sizes for selected platform (or default) - GUI.changed = false; - string platformName = ""; - Texture2D[] icons = PlayerSettings.GetAllIconsForPlatform(platformName); - int[] widths = PlayerSettings.GetIconWidthsOfAllKindsForPlatform(platformName); - - // Ensure the default icon list is always populated correctly - if (icons.Length != widths.Length) - { - icons = new Texture2D[widths.Length]; - } - icons[0] = (Texture2D)EditorGUILayout.ObjectField(Styles.defaultIcon, icons[0], typeof(Texture2D), false); - // Save changes - if (GUI.changed) - { - Undo.RecordObject(this.target, Styles.undoChangedIconString); - PlayerSettings.SetIconsForPlatform(platformName, icons); - } - - GUILayout.Space(3); - - Rect cursorPropertyRect = EditorGUILayout.GetControlRect(true, EditorGUI.kObjectFieldThumbnailHeight); - EditorGUI.BeginProperty(cursorPropertyRect, Styles.defaultCursor, m_DefaultCursor); - m_DefaultCursor.objectReferenceValue = EditorGUI.ObjectField(cursorPropertyRect, Styles.defaultCursor, m_DefaultCursor.objectReferenceValue, typeof(Texture2D), false); - EditorGUI.EndProperty(); - - Rect rect = EditorGUILayout.GetControlRect(); - rect = EditorGUI.PrefixLabel(rect, 0, Styles.cursorHotspot); - EditorGUI.PropertyField(rect, m_CursorHotspot, GUIContent.none); - } - - public bool BeginSettingsBox(int nr, GUIContent header) - { - bool enabled = GUI.enabled; - GUI.enabled = true; // we don't want to disable the expand behavior - EditorGUILayout.BeginVertical(Styles.categoryBox); - Rect r = GUILayoutUtility.GetRect(20, 18); r.x += 3; r.width += 6; - EditorGUI.BeginChangeCheck(); - bool expanded = GUI.Toggle(r, m_SelectedSection.value == nr, header, EditorStyles.inspectorTitlebarText); - if (EditorGUI.EndChangeCheck()) - { - m_SelectedSection.value = (expanded ? nr : -1); - GUIUtility.keyboardControl = 0; - } - m_SectionAnimators[nr].target = expanded; - GUI.enabled = enabled; - return EditorGUILayout.BeginFadeGroup(m_SectionAnimators[nr].faded); - } - - public void EndSettingsBox() - { - EditorGUILayout.EndFadeGroup(); - EditorGUILayout.EndVertical(); - } - - private void ShowNoSettings() - { - GUILayout.Label(Styles.notApplicableInfo, EditorStyles.miniLabel); - } - - public void ShowSharedNote() - { - GUILayout.Label(Styles.sharedBetweenPlatformsInfo, EditorStyles.miniLabel); - } - - private void IconSectionGUI(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension, int sectionIndex) - { - if (BeginSettingsBox(sectionIndex, Styles.iconTitle)) - { - bool platformUsesStandardIcons = true; - if (settingsExtension != null) - platformUsesStandardIcons = settingsExtension.UsesStandardIcons(); - - if (platformUsesStandardIcons) - { - bool selectedDefault = (selectedPlatform < 0); - // Set default platform variables - BuildPlatform platform = null; - targetGroup = BuildTargetGroup.Standalone; - string platformName = ""; - - // Override if a platform is selected - if (!selectedDefault) - { - platform = validPlatforms[selectedPlatform]; - targetGroup = platform.targetGroup; - platformName = platform.name; - } - - bool enabled = GUI.enabled; - - if (targetGroup == BuildTargetGroup.WebGL) - { - ShowNoSettings(); - EditorGUILayout.Space(); - } - else if (targetGroup == BuildTargetGroup.WSA) - { - } - else - { - // Get icons and icon sizes for selected platform (or default) - Texture2D[] icons = PlayerSettings.GetAllIconsForPlatform(platformName); - int[] widths = PlayerSettings.GetIconWidthsOfAllKindsForPlatform(platformName); - int[] heights = PlayerSettings.GetIconHeightsOfAllKindsForPlatform(platformName); - IconKind[] kinds = PlayerSettings.GetIconKindsForPlatform(platformName); - - bool overrideIcons = true; - - if (!selectedDefault) - { - // If the list of icons for this platform is not empty (and has the correct size), - // consider the icon overridden for this platform - GUI.changed = false; - overrideIcons = (icons.Length == widths.Length); - overrideIcons = GUILayout.Toggle(overrideIcons, string.Format(L10n.Tr("Override for {0}"), platform.title.text)); - GUI.enabled = enabled && overrideIcons; - if (GUI.changed || (!overrideIcons && icons.Length > 0)) - { - // Set the list of icons to correct length if overridden, otherwise to an empty list - if (overrideIcons) - icons = new Texture2D[widths.Length]; - else - icons = new Texture2D[0]; - - if (GUI.changed) - PlayerSettings.SetIconsForPlatform(platformName, icons); - } - } - - // Show the icons for this platform (or default) - GUI.changed = false; - for (int i = 0; i < widths.Length; i++) - { - int previewWidth = Mathf.Min(kMaxPreviewSize, widths[i]); - int previewHeight = (int)((float)heights[i] * previewWidth / widths[i]); // take into account the aspect ratio - - if (targetGroup == BuildTargetGroup.iOS) - { - // Spotlight icons begin with 120 but there are two in the list. - // So check if the next one is 80. - if (kinds[i] == IconKind.Spotlight && kinds[i - 1] != IconKind.Spotlight) - { - Rect labelRect = GUILayoutUtility.GetRect(EditorGUIUtility.labelWidth, 20); - GUI.Label(new Rect(labelRect.x, labelRect.y, EditorGUIUtility.labelWidth, 20), "Spotlight icons", EditorStyles.boldLabel); - } - - if (kinds[i] == IconKind.Settings && kinds[i - 1] != IconKind.Settings) - { - Rect labelRect = GUILayoutUtility.GetRect(EditorGUIUtility.labelWidth, 20); - GUI.Label(new Rect(labelRect.x, labelRect.y, EditorGUIUtility.labelWidth, 20), "Settings icons", EditorStyles.boldLabel); - } - - if (kinds[i] == IconKind.Notification && kinds[i - 1] != IconKind.Notification) - { - Rect labelRect = GUILayoutUtility.GetRect(EditorGUIUtility.labelWidth, 20); - GUI.Label(new Rect(labelRect.x, labelRect.y, EditorGUIUtility.labelWidth, 20), "Notification icons", EditorStyles.boldLabel); - } - - if (kinds[i] == IconKind.Store && kinds[i - 1] != IconKind.Store) - { - Rect labelRect = GUILayoutUtility.GetRect(EditorGUIUtility.labelWidth, 20); - GUI.Label(new Rect(labelRect.x, labelRect.y, EditorGUIUtility.labelWidth, 20), "App Store icons", EditorStyles.boldLabel); - } - } - - Rect rect = GUILayoutUtility.GetRect(kSlotSize, Mathf.Max(kSlotSize, previewHeight) + kIconSpacing); - float width = Mathf.Min(rect.width, EditorGUIUtility.labelWidth + 4 + kSlotSize + kIconSpacing + kMaxPreviewSize); - - // Label - string label = widths[i] + "x" + heights[i]; - GUI.Label(new Rect(rect.x, rect.y, width - kMaxPreviewSize - kSlotSize - 2 * kIconSpacing, 20), label); - - // Texture slot - if (overrideIcons) - { - int slotWidth = kSlotSize; - int slotHeight = (int)((float)heights[i] / widths[i] * kSlotSize); // take into account the aspect ratio - icons[i] = (Texture2D)EditorGUI.ObjectField( - new Rect(rect.x + width - kMaxPreviewSize - kSlotSize - kIconSpacing, rect.y, slotWidth, slotHeight), - icons[i], - typeof(Texture2D), - false); - } - - // Preview - Rect previewRect = new Rect(rect.x + width - kMaxPreviewSize, rect.y, previewWidth, previewHeight); - Texture2D closestIcon = PlayerSettings.GetIconForPlatformAtSize(platformName, widths[i], heights[i], kinds[i]); - if (closestIcon != null) - GUI.DrawTexture(previewRect, closestIcon); - else - GUI.Box(previewRect, ""); - } - // Save changes - if (GUI.changed) - { - Undo.RecordObject(this.target, Styles.undoChangedIconString); - PlayerSettings.SetIconsForPlatform(platformName, icons); - } - GUI.enabled = enabled; - - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS) - { - EditorGUILayout.PropertyField(m_UIPrerenderedIcon, Styles.UIPrerenderedIcon); - EditorGUILayout.Space(); - } - } - } - - if (settingsExtension != null) - settingsExtension.IconSectionGUI(); - } - EndSettingsBox(); - } - - private static bool TargetSupportsOptionalBuiltinSplashScreen(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension) - { - if (settingsExtension != null) - return settingsExtension.CanShowUnitySplashScreen(); - - return targetGroup == BuildTargetGroup.Standalone; - } - - private static bool TargetSupportsProtectedGraphicsMem(BuildTargetGroup targetGroup) - { - return targetGroup == BuildTargetGroup.Android; - } - - public void ResolutionSectionGUI(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension, int sectionIndex = 0) - { - if (BeginSettingsBox(sectionIndex, Styles.resolutionPresentationTitle)) - { - // PLEASE DO NOT COPY SETTINGS TO APPEAR MULTIPLE PLACES IN THE CODE! See top of file for more info. - - { - // Resolution itself - - if (settingsExtension != null) - { - float h = EditorGUI.kSingleLineHeight; - float kLabelFloatMinW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; - float kLabelFloatMaxW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; - settingsExtension.ResolutionSectionGUI(h, kLabelFloatMinW, kLabelFloatMaxW); - } - - if (targetGroup == BuildTargetGroup.Standalone) - { - GUILayout.Label(Styles.resolutionTitle, EditorStyles.boldLabel); - - var fullscreenModes = new[] { FullScreenMode.FullScreenWindow, FullScreenMode.ExclusiveFullScreen, FullScreenMode.MaximizedWindow, FullScreenMode.Windowed }; - var fullscreenModeNames = new[] { Styles.fullscreenWindow, Styles.exclusiveFullscreen, Styles.maximizedWindow, Styles.windowed }; - var fullscreenModeNew = BuildEnumPopup(m_FullscreenMode, Styles.fullscreenMode, fullscreenModes, fullscreenModeNames); - - bool defaultIsFullScreen = fullscreenModeNew != FullScreenMode.Windowed; - m_ShowDefaultIsNativeResolution.target = defaultIsFullScreen; - if (EditorGUILayout.BeginFadeGroup(m_ShowDefaultIsNativeResolution.faded)) - EditorGUILayout.PropertyField(m_DefaultIsNativeResolution); - if (m_ShowDefaultIsNativeResolution.faded != 0 && m_ShowDefaultIsNativeResolution.faded != 1) - EditorGUILayout.EndFadeGroup(); - - m_ShowResolution.target = !(defaultIsFullScreen && m_DefaultIsNativeResolution.boolValue); - if (EditorGUILayout.BeginFadeGroup(m_ShowResolution.faded)) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_DefaultScreenWidth, Styles.defaultScreenWidth); - if (EditorGUI.EndChangeCheck() && m_DefaultScreenWidth.intValue < 1) - m_DefaultScreenWidth.intValue = 1; - - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_DefaultScreenHeight, Styles.defaultScreenHeight); - if (EditorGUI.EndChangeCheck() && m_DefaultScreenHeight.intValue < 1) - m_DefaultScreenHeight.intValue = 1; - } - if (m_ShowResolution.faded != 0 && m_ShowResolution.faded != 1) - EditorGUILayout.EndFadeGroup(); - } - if (targetGroup == BuildTargetGroup.Standalone) - { - EditorGUILayout.PropertyField(m_MacRetinaSupport, Styles.macRetinaSupport); - EditorGUILayout.PropertyField(m_RunInBackground, Styles.runInBackground); - } - - if (settingsExtension != null && settingsExtension.SupportsOrientation()) - { - GUILayout.Label(Styles.orientationTitle, EditorStyles.boldLabel); - - EditorGUILayout.PropertyField(m_DefaultScreenOrientation, Styles.defaultScreenOrientation); - - if (PlayerSettings.virtualRealitySupported) - { - EditorGUILayout.HelpBox(Styles.vrOrientationInfo.text, MessageType.Warning); - } - - if (m_DefaultScreenOrientation.enumValueIndex == (int)UIOrientation.AutoRotation) - { - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.Tizen) - EditorGUILayout.PropertyField(m_UseOSAutoRotation, Styles.useOSAutoRotation); - - EditorGUI.indentLevel++; - - GUILayout.Label(Styles.allowedOrientationTitle, EditorStyles.boldLabel); - - bool somethingAllowed = m_AllowedAutoRotateToPortrait.boolValue - || m_AllowedAutoRotateToPortraitUpsideDown.boolValue - || m_AllowedAutoRotateToLandscapeRight.boolValue - || m_AllowedAutoRotateToLandscapeLeft.boolValue; - - if (!somethingAllowed) - { - m_AllowedAutoRotateToPortrait.boolValue = true; - Debug.LogError("All orientations are disabled. Allowing portrait"); - } - - EditorGUILayout.PropertyField(m_AllowedAutoRotateToPortrait, Styles.allowedAutoRotateToPortrait); - EditorGUILayout.PropertyField(m_AllowedAutoRotateToPortraitUpsideDown, Styles.allowedAutoRotateToPortraitUpsideDown); - EditorGUILayout.PropertyField(m_AllowedAutoRotateToLandscapeRight, Styles.allowedAutoRotateToLandscapeRight); - EditorGUILayout.PropertyField(m_AllowedAutoRotateToLandscapeLeft, Styles.allowedAutoRotateToLandscapeLeft); - - EditorGUI.indentLevel--; - } - } - - if (targetGroup == BuildTargetGroup.iOS) - { - GUILayout.Label(Styles.multitaskingSupportTitle, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_UIRequiresFullScreen, Styles.UIRequiresFullScreen); - EditorGUILayout.Space(); - - GUILayout.Label(Styles.statusBarTitle, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_UIStatusBarHidden, Styles.UIStatusBarHidden); - EditorGUILayout.PropertyField(m_UIStatusBarStyle, Styles.UIStatusBarStyle); - EditorGUILayout.Space(); - } - - EditorGUILayout.Space(); - - // Standalone Player - if (targetGroup == BuildTargetGroup.Standalone) - { - GUILayout.Label(Styles.standalonePlayerOptionsTitle, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_CaptureSingleScreen); - EditorGUILayout.PropertyField(m_DisplayResolutionDialog); - EditorGUILayout.PropertyField(m_UsePlayerLog); - EditorGUILayout.PropertyField(m_ResizableWindow); - - EditorGUILayout.PropertyField(m_VisibleInBackground, Styles.visibleInBackground); - - EditorGUILayout.PropertyField(m_AllowFullscreenSwitch, Styles.allowFullscreenSwitch); - - EditorGUILayout.PropertyField(m_ForceSingleInstance); - EditorGUILayout.PropertyField(m_SupportedAspectRatios, true); - - EditorGUILayout.Space(); - } - - // mobiles color/depth bits setup - if (IsMobileTarget(targetGroup)) - { - // Tizen only supports 32 bit display buffers. - // iOS, while supports 16bit FB through GL interface, use 32bit in hardware, so there is no need in 16bit - if (targetGroup != BuildTargetGroup.Tizen && - targetGroup != BuildTargetGroup.iOS && - targetGroup != BuildTargetGroup.tvOS) - { - EditorGUILayout.PropertyField(m_Use32BitDisplayBuffer, Styles.use32BitDisplayBuffer); - } - - EditorGUILayout.PropertyField(m_DisableDepthAndStencilBuffers, Styles.disableDepthAndStencilBuffers); - } - // activity indicator on loading - if (targetGroup == BuildTargetGroup.iOS) - { - EditorGUILayout.PropertyField(m_iosShowActivityIndicatorOnLoading, Styles.iosShowActivityIndicatorOnLoading); - } - if (targetGroup == BuildTargetGroup.Android) - { - EditorGUILayout.PropertyField(m_androidShowActivityIndicatorOnLoading, Styles.androidShowActivityIndicatorOnLoading); - } - if (targetGroup == BuildTargetGroup.Tizen) - { - EditorGUILayout.PropertyField(m_tizenShowActivityIndicatorOnLoading, EditorGUIUtility.TrTextContent("Show Loading Indicator")); - } - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.Android || targetGroup == BuildTargetGroup.Tizen) - { - EditorGUILayout.Space(); - } - - ShowSharedNote(); - } - } - EndSettingsBox(); - } - - private void AddGraphicsDeviceMenuSelected(object userData, string[] options, int selected) - { - var target = (BuildTarget)userData; - var apis = PlayerSettings.GetGraphicsAPIs(target); - if (apis == null) - return; - var apiToAdd = (GraphicsDeviceType)Enum.Parse(typeof(GraphicsDeviceType), options[selected], true); - var apiList = apis.ToList(); - apiList.Add(apiToAdd); - apis = apiList.ToArray(); - PlayerSettings.SetGraphicsAPIs(target, apis); - } - - private void AddGraphicsDeviceElement(BuildTarget target, Rect rect, ReorderableList list) - { - GraphicsDeviceType[] availableDevices = PlayerSettings.GetSupportedGraphicsAPIs(target); - - if (availableDevices == null || availableDevices.Length == 0) - return; - - var names = new string[availableDevices.Length]; - var enabled = new bool[availableDevices.Length]; - for (int i = 0; i < availableDevices.Length; ++i) - { - names[i] = availableDevices[i].ToString(); - enabled[i] = !list.list.Contains(availableDevices[i]); - } - - EditorUtility.DisplayCustomMenu(rect, names, enabled, null, AddGraphicsDeviceMenuSelected, target); - } - - private bool CanRemoveGraphicsDeviceElement(ReorderableList list) - { - // don't allow removing the last API - return list.list.Count >= 2; - } - - private void RemoveGraphicsDeviceElement(BuildTarget target, ReorderableList list) - { - var apis = PlayerSettings.GetGraphicsAPIs(target); - if (apis == null) - return; - // don't allow removing the last API - if (apis.Length < 2) - { - EditorApplication.Beep(); - return; - } - - var apiList = apis.ToList(); - apiList.RemoveAt(list.index); - apis = apiList.ToArray(); - - ApplyChangedGraphicsAPIList(target, apis, list.index == 0); - } - - private void ReorderGraphicsDeviceElement(BuildTarget target, ReorderableList list) - { - var previousAPIs = PlayerSettings.GetGraphicsAPIs(target); - var apiList = (List)list.list; - var apis = apiList.ToArray(); - - var firstAPIDifferent = (previousAPIs[0] != apis[0]); - ApplyChangedGraphicsAPIList(target, apis, firstAPIDifferent); - } - - // these two methods are needed for cases when you want to take some action depending on user choice - // as changing graphics api will call GUIUtility.ExitGUI - - private struct ChangeGraphicsApiAction - { - public readonly bool changeList, reloadGfx; - public ChangeGraphicsApiAction(bool doChange, bool doReload) { changeList = doChange; reloadGfx = doReload; } - } - private ChangeGraphicsApiAction CheckApplyGraphicsAPIList(BuildTarget target, bool firstEntryChanged) - { - bool doChange = true, doReload = false; - // If we're changing the first API for relevant editor, this will cause editor to switch: ask for scene save & confirmation - if (firstEntryChanged && WillEditorUseFirstGraphicsAPI(target)) - { - doChange = false; - if (EditorUtility.DisplayDialog("Changing editor graphics device", - "Changing active graphics API requires reloading all graphics objects, it might take a while", - "Apply", "Cancel")) - { - if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) - doChange = doReload = true; - } - } - return new ChangeGraphicsApiAction(doChange, doReload); - } - - private void ApplyChangeGraphicsApiAction(BuildTarget target, GraphicsDeviceType[] apis, ChangeGraphicsApiAction action) - { - if (action.changeList) PlayerSettings.SetGraphicsAPIs(target, apis); - else s_GraphicsDeviceLists.Remove(target); // we cancelled the list change, so remove the cached one - - if (action.reloadGfx) - { - ShaderUtil.RecreateGfxDevice(); - GUIUtility.ExitGUI(); - } - } - - private void ApplyChangedGraphicsAPIList(BuildTarget target, GraphicsDeviceType[] apis, bool firstEntryChanged) - { - ChangeGraphicsApiAction action = CheckApplyGraphicsAPIList(target, firstEntryChanged); - ApplyChangeGraphicsApiAction(target, apis, action); - } - - private void DrawGraphicsDeviceElement(BuildTarget target, Rect rect, int index, bool selected, bool focused) - { - var device = s_GraphicsDeviceLists[target].list[index]; - var name = device.ToString(); - if (name == "Direct3D12") - name = "Direct3D12 (Experimental)"; - - if (name == "Vulkan" && target != BuildTarget.Android) - name = "Vulkan (Experimental)"; - - if (name == "XboxOneD3D12") - name = "XboxOneD3D12 (Experimental)"; - - // For WebGL, display the actual WebGL version names instead of corresponding GLES APIs for clarification. - if (target == BuildTarget.WebGL) - { - if (name == "OpenGLES3") - name = "WebGL 2.0"; - else if (name == "OpenGLES2") - name = "WebGL 1.0"; - } - - GUI.Label(rect, name, EditorStyles.label); - } - - private static bool WillEditorUseFirstGraphicsAPI(BuildTarget targetPlatform) - { - return - Application.platform == RuntimePlatform.WindowsEditor && targetPlatform == BuildTarget.StandaloneWindows || - Application.platform == RuntimePlatform.OSXEditor && targetPlatform == BuildTarget.StandaloneOSX; - } - - void OpenGLES31OptionsGUI(BuildTargetGroup targetGroup, BuildTarget targetPlatform) - { - // ES3.1 options only applicable on some platforms now - var hasES31Options = (targetGroup == BuildTargetGroup.Android); - if (!hasES31Options) - return; - - var apis = PlayerSettings.GetGraphicsAPIs(targetPlatform); - // only available if we include ES3, and not ES2 - var hasMinES3 = apis.Contains(GraphicsDeviceType.OpenGLES3) && !apis.Contains(GraphicsDeviceType.OpenGLES2); - if (!hasMinES3) - return; - - EditorGUILayout.PropertyField(m_RequireES31, Styles.require31); - EditorGUILayout.PropertyField(m_RequireES31AEP, Styles.requireAEP); - } - - void GraphicsAPIsGUIOnePlatform(BuildTargetGroup targetGroup, BuildTarget targetPlatform, string platformTitle) - { - GraphicsDeviceType[] availableDevices = PlayerSettings.GetSupportedGraphicsAPIs(targetPlatform); - // if no devices (e.g. no platform module), or we only have one possible choice, then no - // point in having any UI - if (availableDevices == null || availableDevices.Length < 2) - return; - - // toggle for automatic API selection - EditorGUI.BeginChangeCheck(); - var automatic = PlayerSettings.GetUseDefaultGraphicsAPIs(targetPlatform); - automatic = EditorGUILayout.Toggle(string.Format(L10n.Tr("Auto Graphics API {0}"), (platformTitle ?? string.Empty)), automatic); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(target, Styles.undoChangedGraphicsAPIString); - PlayerSettings.SetUseDefaultGraphicsAPIs(targetPlatform, automatic); - } - - // graphics API list if not automatic - if (!automatic) - { - // note that editor will use first item, when we're in standalone settings - if (WillEditorUseFirstGraphicsAPI(targetPlatform)) - { - EditorGUILayout.HelpBox(Styles.recordingInfo.text, MessageType.Info, true); - } - - var displayTitle = "Graphics APIs"; - if (platformTitle != null) - displayTitle += platformTitle; - - // create reorderable list for this target if needed - if (!s_GraphicsDeviceLists.ContainsKey(targetPlatform)) - { - GraphicsDeviceType[] devices = PlayerSettings.GetGraphicsAPIs(targetPlatform); - var devicesList = (devices != null) ? devices.ToList() : new List(); - var rlist = new ReorderableList(devicesList, typeof(GraphicsDeviceType), true, true, true, true); - rlist.onAddDropdownCallback = (rect, list) => AddGraphicsDeviceElement(targetPlatform, rect, list); - rlist.onCanRemoveCallback = CanRemoveGraphicsDeviceElement; - rlist.onRemoveCallback = (list) => RemoveGraphicsDeviceElement(targetPlatform, list); - rlist.onReorderCallback = (list) => ReorderGraphicsDeviceElement(targetPlatform, list); - rlist.drawElementCallback = (rect, index, isActive, isFocused) => DrawGraphicsDeviceElement(targetPlatform, rect, index, isActive, isFocused); - rlist.drawHeaderCallback = (rect) => GUI.Label(rect, displayTitle, EditorStyles.label); - rlist.elementHeight = 16; - - s_GraphicsDeviceLists.Add(targetPlatform, rlist); - } - s_GraphicsDeviceLists[targetPlatform].DoLayoutList(); - - // ES3.1 options - OpenGLES31OptionsGUI(targetGroup, targetPlatform); - - //@TODO: undo - } - } - - void GraphicsAPIsGUI(BuildTargetGroup targetGroup, BuildTarget target) - { - // "standalone" is a generic group; - // split it into win/mac/linux manually - if (targetGroup == BuildTargetGroup.Standalone) - { - GraphicsAPIsGUIOnePlatform(targetGroup, BuildTarget.StandaloneWindows, " for Windows"); - GraphicsAPIsGUIOnePlatform(targetGroup, BuildTarget.StandaloneOSX, " for Mac"); - GraphicsAPIsGUIOnePlatform(targetGroup, BuildTarget.StandaloneLinuxUniversal, " for Linux"); - } - else - { - GraphicsAPIsGUIOnePlatform(targetGroup, target, null); - } - } - - // Contains information about color gamuts supported by each platform. - // If platform group is not in the dictionary, then it's assumed it supports only sRGB. - // Color gamut player setting is not displayed for such platforms. - // - // This information might be useful for users that use the color gamut APIs, - // we could expose it somehow - private static Dictionary> s_SupportedColorGamuts = - new Dictionary> - { - { BuildTargetGroup.Standalone, new List{ ColorGamut.sRGB, ColorGamut.DisplayP3 } }, - { BuildTargetGroup.iOS, new List{ ColorGamut.sRGB, ColorGamut.DisplayP3 } } - }; - - private static bool IsColorGamutSupportedOnTargetGroup(BuildTargetGroup targetGroup, ColorGamut gamut) - { - if (gamut == ColorGamut.sRGB) - return true; - if (s_SupportedColorGamuts.ContainsKey(targetGroup) && - s_SupportedColorGamuts[targetGroup].Contains(gamut)) - return true; - return false; - } - - private static string GetColorGamutDisplayString(BuildTargetGroup targetGroup, ColorGamut gamut) - { - string name = gamut.ToString(); - if (!IsColorGamutSupportedOnTargetGroup(targetGroup, gamut)) - name += " (not supported on this platform)"; - return name; - } - - private void AddColorGamutElement(BuildTargetGroup targetGroup, Rect rect, ReorderableList list) - { - var availableColorGamuts = new ColorGamut[] - { - // Enable the gamuts when at least one platform supports them - ColorGamut.sRGB, - //ColorGamut.Rec709, - //ColorGamut.Rec2020, - ColorGamut.DisplayP3, - //ColorGamut.HDR10, - //ColorGamut.DolbyHDR - }; - - var names = new string[availableColorGamuts.Length]; - var enabled = new bool[availableColorGamuts.Length]; - for (int i = 0; i < availableColorGamuts.Length; ++i) - { - names[i] = GetColorGamutDisplayString(targetGroup, availableColorGamuts[i]); - enabled[i] = !list.list.Contains(availableColorGamuts[i]); - } - - EditorUtility.DisplayCustomMenu(rect, names, enabled, null, AddColorGamutMenuSelected, availableColorGamuts); - } - - private void AddColorGamutMenuSelected(object userData, string[] options, int selected) - { - var colorGamuts = (ColorGamut[])userData; - var colorGamutList = PlayerSettings.GetColorGamuts().ToList(); - colorGamutList.Add(colorGamuts[selected]); - PlayerSettings.SetColorGamuts(colorGamutList.ToArray()); - } - - private bool CanRemoveColorGamutElement(ReorderableList list) - { - // don't allow removing the sRGB - var colorGamutList = (List)list.list; - return colorGamutList[list.index] != ColorGamut.sRGB; - } - - private void RemoveColorGamutElement(ReorderableList list) - { - var colorGamutList = PlayerSettings.GetColorGamuts().ToList(); - // don't allow removing the last ColorGamut - if (colorGamutList.Count < 2) - { - EditorApplication.Beep(); - return; - } - colorGamutList.RemoveAt(list.index); - PlayerSettings.SetColorGamuts(colorGamutList.ToArray()); - } - - private void ReorderColorGamutElement(ReorderableList list) - { - var colorGamutList = (List)list.list; - PlayerSettings.SetColorGamuts(colorGamutList.ToArray()); - } - - private void DrawColorGamutElement(BuildTargetGroup targetGroup, Rect rect, int index, bool selected, bool focused) - { - var colorGamut = s_ColorGamutList.list[index]; - GUI.Label(rect, GetColorGamutDisplayString(targetGroup, (ColorGamut)colorGamut), EditorStyles.label); - } - - void ColorGamutGUI(BuildTargetGroup targetGroup) - { - if (!s_SupportedColorGamuts.ContainsKey(targetGroup)) - return; - - if (s_ColorGamutList == null) - { - ColorGamut[] colorGamuts = PlayerSettings.GetColorGamuts(); - var colorGamutsList = (colorGamuts != null) ? colorGamuts.ToList() : new List(); - var rlist = new ReorderableList(colorGamutsList, typeof(ColorGamut), true, true, true, true); - rlist.onCanRemoveCallback = CanRemoveColorGamutElement; - rlist.onRemoveCallback = RemoveColorGamutElement; - rlist.onReorderCallback = ReorderColorGamutElement; - rlist.elementHeight = 16; - - s_ColorGamutList = rlist; - } - - // On standalone inspector mention that the setting applies only to Mac - // (Temporarily until other standalones support this setting) - GUIContent header = targetGroup == BuildTargetGroup.Standalone ? Styles.colorGamutForMac : Styles.colorGamut; - s_ColorGamutList.drawHeaderCallback = (rect) => - GUI.Label(rect, header, EditorStyles.label); - - // we want to change the displayed text per platform, to indicate unsupported gamuts - s_ColorGamutList.onAddDropdownCallback = (rect, list) => - AddColorGamutElement(targetGroup, rect, list); - - s_ColorGamutList.drawElementCallback = (rect, index, selected, focused) => - DrawColorGamutElement(targetGroup, rect, index, selected, focused); - - s_ColorGamutList.DoLayoutList(); - } - - public void DebugAndCrashReportingGUI(BuildPlatform platform, BuildTargetGroup targetGroup, - ISettingEditorExtension settingsExtension, int sectionIndex = 3) - { - if (targetGroup != BuildTargetGroup.iOS && targetGroup != BuildTargetGroup.tvOS) - return; - - if (BeginSettingsBox(sectionIndex, Styles.debuggingCrashReportingTitle)) - { - // PLEASE DO NOT COPY SETTINGS TO APPEAR MULTIPLE PLACES IN THE CODE! See top of file for more info. - { - // Debugging - GUILayout.Label(Styles.debuggingTitle, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_EnableInternalProfiler, Styles.enableInternalProfiler); - EditorGUILayout.Space(); - } - - { - // Crash reporting - GUILayout.Label(Styles.crashReportingTitle, EditorStyles.boldLabel); - EditorGUILayout.PropertyField(m_ActionOnDotNetUnhandledException, Styles.actionOnDotNetUnhandledException); - EditorGUILayout.PropertyField(m_LogObjCUncaughtExceptions, Styles.logObjCUncaughtExceptions); - - GUIContent crashReportApiContent = Styles.enableCrashReportAPI; - - bool apiFieldDisabled = false; - - if (UnityEditor.CrashReporting.CrashReportingSettings.enabled) - { - // CrashReport API must be enabled if cloud crash reporting is enabled, - // so don't let them change the value of the checkbox - crashReportApiContent = new GUIContent(crashReportApiContent); // Create a copy so we don't alter the style definition - apiFieldDisabled = true; - crashReportApiContent.tooltip = "CrashReport API must be enabled for Performance Reporting service."; - m_EnableCrashReportAPI.boolValue = true; - } - - EditorGUI.BeginDisabledGroup(apiFieldDisabled); - EditorGUILayout.PropertyField(m_EnableCrashReportAPI, crashReportApiContent); - EditorGUI.EndDisabledGroup(); - - EditorGUILayout.Space(); - } - } - EndSettingsBox(); - } - - public static void BuildDisabledEnumPopup(GUIContent selected, GUIContent uiString) - { - using (new EditorGUI.DisabledScope(true)) - { - EditorGUI.Popup(EditorGUILayout.GetControlRect(true), uiString, 0, new GUIContent[] {selected}); - } - } - - public static T BuildEnumPopup(SerializedProperty prop, GUIContent uiString, T[] options, GUIContent[] optionNames) - { - T val = (T)(object)prop.intValue; - T newVal = BuildEnumPopup(uiString, val, options, optionNames); - - // Update property if the popup value has changed - if (!newVal.Equals(val)) - { - prop.intValue = (int)(object)newVal; - prop.serializedObject.ApplyModifiedProperties(); - } - - return newVal; - } - - public static T BuildEnumPopup(GUIContent uiString, T selected, T[] options, GUIContent[] optionNames) - { - // Display dropdown - int idx = 0; // pick the first property when not found - for (int i = 1; i < options.Length; ++i) - { - if (selected.Equals(options[i])) - { - idx = i; - break; - } - } - - int newIdx = EditorGUILayout.Popup(uiString, idx, optionNames); - return options[newIdx]; - } - - public void OtherSectionGUI(BuildPlatform platform, BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension, int sectionIndex = 4) - { - if (BeginSettingsBox(sectionIndex, Styles.otherSettingsTitle)) - { - // PLEASE DO NOT COPY SETTINGS TO APPEAR MULTIPLE PLACES IN THE CODE! See top of file for more info. - OtherSectionRenderingGUI(platform, targetGroup, settingsExtension); - OtherSectionIdentificationGUI(targetGroup, settingsExtension); - OtherSectionConfigurationGUI(targetGroup, settingsExtension); - OtherSectionOptimizationGUI(targetGroup); - OtherSectionLoggingGUI(); - ShowSharedNote(); - } - EndSettingsBox(); - } - - [Serializable] - private struct HwStatsServiceState { public bool hwstats; } - - private void OtherSectionRenderingGUI(BuildPlatform platform, BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension) - { - // Rendering related settings - GUILayout.Label(Styles.renderingTitle, EditorStyles.boldLabel); - - // Color space - if (targetGroup == BuildTargetGroup.Standalone - || targetGroup == BuildTargetGroup.iOS - || targetGroup == BuildTargetGroup.tvOS - || targetGroup == BuildTargetGroup.Android - || targetGroup == BuildTargetGroup.PS4 - || targetGroup == BuildTargetGroup.XboxOne - || targetGroup == BuildTargetGroup.WSA - || targetGroup == BuildTargetGroup.WebGL - || targetGroup == BuildTargetGroup.Switch) - { - using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) // switching color spaces in play mode is not supported - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_ActiveColorSpace, Styles.activeColorSpace); - if (EditorGUI.EndChangeCheck()) - { - serializedObject.ApplyModifiedProperties(); - GUIUtility.ExitGUI(); // Fixes case 690421 - } - } - - // Display a warning for platforms that some devices don't support linear rendering if the settings are not fine for linear colorspace - if (PlayerSettings.colorSpace == ColorSpace.Linear) - { - if (targetGroup == BuildTargetGroup.iOS) - { - var apis = PlayerSettings.GetGraphicsAPIs(BuildTarget.iOS); - var hasMinMetal = !apis.Contains(GraphicsDeviceType.OpenGLES3) && !apis.Contains(GraphicsDeviceType.OpenGLES2); - - Version requiredVersion = new Version(8, 0); - bool hasMinOSVersion = PlayerSettings.iOS.IsTargetVersionEqualOrHigher(requiredVersion); - - if (!hasMinMetal || !hasMinOSVersion) - EditorGUILayout.HelpBox(Styles.colorSpaceIOSWarning.text, MessageType.Warning); - } - - if (targetGroup == BuildTargetGroup.tvOS) - { - var apis = PlayerSettings.GetGraphicsAPIs(BuildTarget.tvOS); - var hasMinMetal = !apis.Contains(GraphicsDeviceType.OpenGLES3) && !apis.Contains(GraphicsDeviceType.OpenGLES2); - - if (!hasMinMetal) - EditorGUILayout.HelpBox(Styles.colorSpaceTVOSWarning.text, MessageType.Warning); - } - - if (targetGroup == BuildTargetGroup.Android) - { - var apis = PlayerSettings.GetGraphicsAPIs(BuildTarget.Android); - var hasMinAPI = (apis.Contains(GraphicsDeviceType.Vulkan) || apis.Contains(GraphicsDeviceType.OpenGLES3)) && !apis.Contains(GraphicsDeviceType.OpenGLES2); - - var hasBlitDisabled = PlayerSettings.Android.blitType == AndroidBlitType.Never; - if (hasBlitDisabled || !hasMinAPI || (int)PlayerSettings.Android.minSdkVersion < 18) - EditorGUILayout.HelpBox(Styles.colorSpaceAndroidWarning.text, MessageType.Warning); - } - - if (targetGroup == BuildTargetGroup.WebGL) - { - var apis = PlayerSettings.GetGraphicsAPIs(BuildTarget.WebGL); - var hasMinAPI = apis.Contains(GraphicsDeviceType.OpenGLES3) && !apis.Contains(GraphicsDeviceType.OpenGLES2); - - if (!hasMinAPI) - EditorGUILayout.HelpBox(Styles.colorSpaceWebGLWarning.text, MessageType.Error); - } - } - } - - // Graphics APIs - GraphicsAPIsGUI(targetGroup, platform.defaultTarget); - - // Output color spaces - ColorGamutGUI(targetGroup); - - // Metal - if (Application.platform == RuntimePlatform.OSXEditor && (targetGroup == BuildTargetGroup.Standalone || targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS)) - { - bool curMetalSupport = m_MetalEditorSupport.boolValue || SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal; - bool newMetalSupport = EditorGUILayout.Toggle(Styles.metalEditorSupport, curMetalSupport); - - if (newMetalSupport != curMetalSupport) - { - if (Application.platform == RuntimePlatform.OSXEditor) - { - GraphicsDeviceType[] api = PlayerSettings.GetGraphicsAPIs(BuildTarget.StandaloneOSX); - - bool updateCurrentAPI = api[0] != SystemInfo.graphicsDeviceType; - if (!newMetalSupport && SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal) - updateCurrentAPI = true; // running on metal and disabled it - if (newMetalSupport && api[0] == GraphicsDeviceType.Metal) - updateCurrentAPI = true; // just enabled metal so want to switch to it - - ChangeGraphicsApiAction action = CheckApplyGraphicsAPIList(BuildTarget.StandaloneOSX, updateCurrentAPI); - if (action.changeList) - { - m_MetalEditorSupport.boolValue = newMetalSupport; - serializedObject.ApplyModifiedProperties(); - // HACK: we pretended to change first api in list to trigger possible gfx device recreation - // HACK: but we dont really change api list (as we will simply set bool checked from native code) - action = new ChangeGraphicsApiAction(false, action.reloadGfx); - } - ApplyChangeGraphicsApiAction(BuildTarget.StandaloneOSX, api, action); - } - else - { - m_MetalEditorSupport.boolValue = newMetalSupport; - serializedObject.ApplyModifiedProperties(); - } - } - - if (m_MetalEditorSupport.boolValue) - { - using (new EditorGUI.IndentLevelScope()) - m_MetalAPIValidation.boolValue = EditorGUILayout.Toggle(Styles.metalAPIValidation, m_MetalAPIValidation.boolValue); - } - - EditorGUILayout.PropertyField(m_MetalFramebufferOnly, Styles.metalFramebufferOnly); - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS) - EditorGUILayout.PropertyField(m_MetalForceHardShadows, Styles.metalForceHardShadows); - } - - // Multithreaded rendering - if (settingsExtension != null && settingsExtension.SupportsMultithreadedRendering()) - settingsExtension.MultithreadedRenderingGUI(targetGroup); - - // Batching section - { - int staticBatching, dynamicBatching; - bool staticBatchingSupported = true; - bool dynamicBatchingSupported = true; - if (settingsExtension != null) - { - staticBatchingSupported = settingsExtension.SupportsStaticBatching(); - dynamicBatchingSupported = settingsExtension.SupportsDynamicBatching(); - } - PlayerSettings.GetBatchingForPlatform(platform.defaultTarget, out staticBatching, out dynamicBatching); - - bool reset = false; - if (staticBatchingSupported == false && staticBatching == 1) - { - staticBatching = 0; - reset = true; - } - - if (dynamicBatchingSupported == false && dynamicBatching == 1) - { - dynamicBatching = 0; - reset = true; - } - - if (reset) - { - PlayerSettings.SetBatchingForPlatform(platform.defaultTarget, staticBatching, dynamicBatching); - } - - EditorGUI.BeginChangeCheck(); - using (new EditorGUI.DisabledScope(!staticBatchingSupported)) - { - if (GUI.enabled) - staticBatching = EditorGUILayout.Toggle(Styles.staticBatching, staticBatching != 0) ? 1 : 0; - else - EditorGUILayout.Toggle(Styles.staticBatching, false); - } - - using (new EditorGUI.DisabledScope(!dynamicBatchingSupported)) - { - dynamicBatching = EditorGUILayout.Toggle(Styles.dynamicBatching, dynamicBatching != 0) ? 1 : 0; - } - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(target, Styles.undoChangedBatchingString); - PlayerSettings.SetBatchingForPlatform(platform.defaultTarget, staticBatching, dynamicBatching); - } - } - - - bool hdrSupported = false; - bool gfxJobModesSupported = false; - bool customLightmapEncodingSupported = (targetGroup == BuildTargetGroup.Standalone); - if (settingsExtension != null) - { - hdrSupported = settingsExtension.SupportsHighDynamicRangeDisplays(); - gfxJobModesSupported = settingsExtension.SupportsGfxJobModes(); - customLightmapEncodingSupported = customLightmapEncodingSupported || settingsExtension.SupportsCustomLightmapEncoding(); - } - - // GPU Skinning toggle (only show on relevant platforms) - if (targetGroup == BuildTargetGroup.Standalone || - targetGroup == BuildTargetGroup.iOS || - targetGroup == BuildTargetGroup.tvOS || - targetGroup == BuildTargetGroup.Android || - targetGroup == BuildTargetGroup.PSP2 || - targetGroup == BuildTargetGroup.PS4 || - targetGroup == BuildTargetGroup.XboxOne || - targetGroup == BuildTargetGroup.WSA || - targetGroup == BuildTargetGroup.Switch) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_SkinOnGPU, - targetGroup != BuildTargetGroup.PS4 && targetGroup != BuildTargetGroup.Switch ? Styles.skinOnGPU : Styles.skinOnGPUPS4); - if (EditorGUI.EndChangeCheck()) - { - ShaderUtil.RecreateSkinnedMeshResources(); - } - } - - if ((targetGroup == BuildTargetGroup.Android) && PlayerSettings.gpuSkinning) - { - EditorGUILayout.HelpBox(Styles.skinOnGPUAndroidWarning.text, MessageType.Warning); - } - - if (targetGroup == BuildTargetGroup.XboxOne) - { - // on XBoxOne, we only have kGfxJobModeNative active for Dx12 API and kGfxJobModeLegacy for the DX11 API - // no need for a drop down popup for XBoxOne - // also if XboxOneD3D12 is selected as GraphicsAPI, then we want to check the graphics jobs checkbox and disable it. - GraphicsDeviceType[] gfxAPIs = PlayerSettings.GetGraphicsAPIs(platform.defaultTarget); - - PlayerSettings.graphicsJobMode = gfxAPIs[0] == GraphicsDeviceType.XboxOneD3D12 ? GraphicsJobMode.Native : GraphicsJobMode.Legacy; - if (gfxAPIs[0] == GraphicsDeviceType.XboxOneD3D12) - PlayerSettings.graphicsJobs = true; - using (new EditorGUI.DisabledScope(gfxAPIs[0] == GraphicsDeviceType.XboxOneD3D12)) - { - EditorGUILayout.PropertyField(m_GraphicsJobs, Styles.graphicsJobs); - } - } - else - { - EditorGUILayout.PropertyField(m_GraphicsJobs, Styles.graphicsJobs); - if (gfxJobModesSupported) - { - using (new EditorGUI.DisabledScope(!m_GraphicsJobs.boolValue)) - { - GraphicsJobMode currGfxJobMode = PlayerSettings.graphicsJobMode; - - GraphicsJobMode newGfxJobMode = BuildEnumPopup(Styles.graphicsJobsMode, currGfxJobMode, m_GfxJobModeValues, m_GfxJobModeNames); - if (newGfxJobMode != currGfxJobMode) - { - PlayerSettings.graphicsJobMode = newGfxJobMode; - } - } - } - } - - // Show Lightmap Encoding quality option - if (customLightmapEncodingSupported) - { - using (new EditorGUI.DisabledScope(EditorApplication.isPlaying || Lightmapping.isRunning)) - { - EditorGUI.BeginChangeCheck(); - LightmapEncodingQuality encodingQuality = PlayerSettings.GetLightmapEncodingQualityForPlatformGroup(targetGroup); - LightmapEncodingQuality[] lightmapEncodingValues = {LightmapEncodingQuality.Normal, LightmapEncodingQuality.High}; - encodingQuality = BuildEnumPopup(Styles.lightmapEncodingLabel, encodingQuality, lightmapEncodingValues, Styles.lightmapEncodingNames); - if (EditorGUI.EndChangeCheck()) - { - PlayerSettings.SetLightmapEncodingQualityForPlatformGroup(targetGroup, encodingQuality); - - Lightmapping.OnUpdateLightmapEncoding(targetGroup); - - serializedObject.ApplyModifiedProperties(); - - GUIUtility.ExitGUI(); - } - } - } - - if (m_VRSettings.TargetGroupSupportsVirtualReality(targetGroup)) - { - if (EditorGUILayout.LinkLabel(Styles.vrSettingsMoved)) - { - m_SelectedSection.value = m_VRSettings.GUISectionIndex; - } - } - - if (TargetSupportsProtectedGraphicsMem(targetGroup)) - { - PlayerSettings.protectGraphicsMemory = EditorGUILayout.Toggle(Styles.protectGraphicsMemory, PlayerSettings.protectGraphicsMemory); - } - - if (hdrSupported) - { - PlayerSettings.useHDRDisplay = EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Use display in HDR mode", "Automatically switch the display to HDR output (on supported displays) at start of application."), PlayerSettings.useHDRDisplay); - } - - EditorGUILayout.Space(); - } - - private void OtherSectionIdentificationGUI(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension) - { - // Identification - - if (settingsExtension != null && settingsExtension.HasIdentificationGUI()) - { - GUILayout.Label(Styles.identificationTitle, EditorStyles.boldLabel); - settingsExtension.IdentificationSectionGUI(); - - EditorGUILayout.Space(); - } - else if (targetGroup == BuildTargetGroup.Standalone) - { - // TODO this should be move to an extension if we have one for MacOS or Standalone target at some point. - GUILayout.Label(Styles.macAppStoreTitle, EditorStyles.boldLabel); - - PlayerSettingsEditor.ShowApplicationIdentifierUI(serializedObject, BuildTargetGroup.Standalone, "Bundle Identifier", "'CFBundleIdentifier'", Styles.undoChangedBundleIdentifierString); - EditorGUILayout.PropertyField(m_ApplicationBundleVersion, EditorGUIUtility.TrTextContent("Version*", "'CFBundleShortVersionString'")); - PlayerSettingsEditor.ShowBuildNumberUI(serializedObject, BuildTargetGroup.Standalone, "Build", "'CFBundleVersion'", Styles.undoChangedBuildNumberString); - - EditorGUILayout.PropertyField(m_MacAppStoreCategory, Styles.macAppStoreCategory); - EditorGUILayout.PropertyField(m_UseMacAppStoreValidation, Styles.useMacAppStoreValidation); - - EditorGUILayout.Space(); - } - } - - internal static void ShowPlatformIconsByKind(PlatformIconFieldGroup iconFieldGroup, bool foldByKind = true, bool foldBySubkind = true) - { - int labelHeight = 20; - - if (iconFieldGroup.m_IconsFields.Count == 0) - { - foreach (var kind in PlayerSettings.GetSupportedIconKindsForPlatform(iconFieldGroup.targetGroup)) - { - iconFieldGroup.AddPlatformIcons(PlayerSettings.GetPlatformIcons( - iconFieldGroup.targetGroup, kind), kind - ); - } - } - foreach (var kindGroup in iconFieldGroup.m_IconsFields) - { - EditorGUI.BeginChangeCheck(); - - var key = kindGroup.Key; - - if (foldByKind) - { - string kindName = string.Format("{0} icons ({1}/{2})", key.m_Label, kindGroup.Key.m_SetIconSlots, kindGroup.Key.m_IconSlotCount); - Rect rectKindLabel = GUILayoutUtility.GetRect(kSlotSize, labelHeight); - rectKindLabel.x += 2; - key.m_State = EditorGUI.Foldout(rectKindLabel, key.m_State, kindName, EditorStyles.foldout); - } - else - key.m_State = true; - - if (key.m_State) - { - kindGroup.Key.m_SetIconSlots = 0; - foreach (var subKindGroup in kindGroup.Value) - { - subKindGroup.Key.m_SetIconSlots = - PlayerSettings.GetNonEmptyPlatformIconCount(subKindGroup.Value.Select(x => x.platformIcon) - .ToArray()); - kindGroup.Key.m_SetIconSlots += subKindGroup.Key.m_SetIconSlots; - - if (foldBySubkind) - { - string subKindName = string.Format("{0} icons ({1}/{2})", subKindGroup.Key.m_Label, subKindGroup.Key.m_SetIconSlots , subKindGroup.Value.Length); - Rect rectSubKindLabel = GUILayoutUtility.GetRect(kSlotSize, labelHeight); - rectSubKindLabel.x += 8; - - subKindGroup.Key.m_State = EditorGUI.Foldout(rectSubKindLabel, subKindGroup.Key.m_State, subKindName, EditorStyles.foldout); - } - else - subKindGroup.Key.m_State = true; - - if (subKindGroup.Key.m_State || !foldBySubkind) - { - foreach (var iconField in subKindGroup.Value) - { - iconField.DrawAt(); - } - } - } - } - if (EditorGUI.EndChangeCheck()) - PlayerSettings.SetPlatformIcons(iconFieldGroup.targetGroup, key.m_Kind , iconFieldGroup.m_PlatformIconsByKind[key.m_Kind]); - } - } - - internal static void ShowApplicationIdentifierUI(SerializedObject serializedObject, BuildTargetGroup targetGroup, string label, string tooltip, string undoText) - { - EditorGUI.BeginChangeCheck(); - string identifier = EditorGUILayout.TextField(EditorGUIUtility.TrTextContent(label, tooltip), PlayerSettings.GetApplicationIdentifier(targetGroup)); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(serializedObject.targetObject, undoText); - PlayerSettings.SetApplicationIdentifier(targetGroup, identifier); - } - } - - internal static void ShowBuildNumberUI(SerializedObject serializedObject, BuildTargetGroup targetGroup, string label, string tooltip, string undoText) - { - EditorGUI.BeginChangeCheck(); - string buildNumber = EditorGUILayout.TextField(EditorGUIUtility.TrTextContent(label, tooltip), PlayerSettings.GetBuildNumber(targetGroup)); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(serializedObject.targetObject, undoText); - PlayerSettings.SetBuildNumber(targetGroup, buildNumber); - } - } - - private void OtherSectionConfigurationGUI(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension) - { - // Configuration - GUILayout.Label(Styles.configurationTitle, EditorStyles.boldLabel); - - // Scripting Runtime Version - var scriptingRuntimeVersions = new[] {ScriptingRuntimeVersion.Legacy, ScriptingRuntimeVersion.Latest}; - var scriptingRuntimeVersionNames = new[] {Styles.scriptingRuntimeVersionLegacy, Styles.scriptingRuntimeVersionLatest}; - var newScriptingRuntimeVersions = PlayerSettings.scriptingRuntimeVersion; - if (EditorApplication.isPlaying) - { - var current = PlayerSettings.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy ? Styles.scriptingRuntimeVersionLegacy : Styles.scriptingRuntimeVersionLatest; - BuildDisabledEnumPopup(current, Styles.scriptingRuntimeVersion); - } - else - { - newScriptingRuntimeVersions = BuildEnumPopup(Styles.scriptingRuntimeVersion, PlayerSettings.scriptingRuntimeVersion, scriptingRuntimeVersions, scriptingRuntimeVersionNames); - } - - if (newScriptingRuntimeVersions != PlayerSettings.scriptingRuntimeVersion) - { - if (EditorUtility.DisplayDialog( - LocalizationDatabase.GetLocalizedString("Restart required"), - LocalizationDatabase.GetLocalizedString("Changing scripting runtime version requires a restart of the Editor to take effect. Do you wish to proceed?"), - LocalizationDatabase.GetLocalizedString("Restart"), - LocalizationDatabase.GetLocalizedString("Cancel"))) - { - PlayerSettings.scriptingRuntimeVersion = newScriptingRuntimeVersions; - EditorCompilationInterface.Instance.CleanScriptAssemblies(); - if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) - EditorApplication.OpenProject(Environment.CurrentDirectory); - } - } - - // Scripting back-end - IScriptingImplementations scripting = ModuleManager.GetScriptingImplementations(targetGroup); - bool targetGroupSupportsIl2Cpp = false; - bool currentBackendIsIl2Cpp = false; - - if (scripting == null) - { - BuildDisabledEnumPopup(Styles.scriptingDefault, Styles.scriptingBackend); - } - else - { - var backends = scripting.Enabled(); - - foreach (var backend in backends) - { - if (backend == ScriptingImplementation.IL2CPP) - { - targetGroupSupportsIl2Cpp = true; - break; - } - } - - ScriptingImplementation currBackend = PlayerSettings.GetScriptingBackend(targetGroup); - currentBackendIsIl2Cpp = currBackend == ScriptingImplementation.IL2CPP; - ScriptingImplementation newBackend; - - if (targetGroup == BuildTargetGroup.tvOS) - { - newBackend = ScriptingImplementation.IL2CPP; - PlayerSettingsEditor.BuildDisabledEnumPopup(Styles.scriptingIL2CPP, Styles.scriptingBackend); - } - else - { - newBackend = BuildEnumPopup(Styles.scriptingBackend, currBackend, backends, GetNiceScriptingBackendNames(backends)); - } - - if (targetGroup == BuildTargetGroup.iOS && newBackend == ScriptingImplementation.Mono2x) - { - EditorGUILayout.HelpBox(Styles.monoNotSupportediOS11WarningGUIContent.text, MessageType.Warning); - } - - if (newBackend != currBackend) - PlayerSettings.SetScriptingBackend(targetGroup, newBackend); - } - - // Api Compatibility Level - var currentCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(targetGroup); - var availableCompatibilityLevels = GetAvailableApiCompatibilityLevels(targetGroup); - - var newCompatibilityLevel = BuildEnumPopup(Styles.apiCompatibilityLevel, currentCompatibilityLevel, availableCompatibilityLevels, GetNiceApiCompatibilityLevelNames(availableCompatibilityLevels)); - - if (currentCompatibilityLevel != newCompatibilityLevel) - PlayerSettings.SetApiCompatibilityLevel(targetGroup, newCompatibilityLevel); - - if (targetGroupSupportsIl2Cpp) - { - using (new EditorGUI.DisabledScope(!currentBackendIsIl2Cpp || !scripting.AllowIL2CPPCompilerConfigurationSelection())) - { - var currentConfiguration = PlayerSettings.GetIl2CppCompilerConfiguration(targetGroup); - var configurations = GetIl2CppCompilerConfigurations(); - var configurationNames = GetIl2CppCompilerConfigurationNames(); - - var newConfiguration = BuildEnumPopup(Styles.il2cppCompilerConfiguration, currentConfiguration, configurations, configurationNames); - - if (currentConfiguration != newConfiguration) - PlayerSettings.SetIl2CppCompilerConfiguration(targetGroup, newConfiguration); - } - } - - bool showMobileSection = - targetGroup == BuildTargetGroup.iOS || - targetGroup == BuildTargetGroup.tvOS || - targetGroup == BuildTargetGroup.Android || - targetGroup == BuildTargetGroup.WSA; - - // mobile-only settings - if (showMobileSection) - { - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS) - EditorGUILayout.PropertyField(m_useOnDemandResources, Styles.useOnDemandResources); - - bool supportsAccelerometerFrequency = - targetGroup == BuildTargetGroup.iOS || - targetGroup == BuildTargetGroup.tvOS || - targetGroup == BuildTargetGroup.WSA; - if (supportsAccelerometerFrequency) - EditorGUILayout.PropertyField(m_AccelerometerFrequency, Styles.accelerometerFrequency); - - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS) - { - EditorGUILayout.PropertyField(m_CameraUsageDescription, Styles.cameraUsageDescription); - EditorGUILayout.PropertyField(m_LocationUsageDescription, Styles.locationUsageDescription); - EditorGUILayout.PropertyField(m_MicrophoneUsageDescription, Styles.microphoneUsageDescription); - } - - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS || targetGroup == BuildTargetGroup.Android) - { - EditorGUILayout.PropertyField(m_MuteOtherAudioSources, Styles.muteOtherAudioSources); - } - - // TVOS TODO: check what should stay or go - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS) - { - if (targetGroup == BuildTargetGroup.iOS) - { - EditorGUILayout.PropertyField(m_PrepareIOSForRecording, Styles.prepareIOSForRecording); - EditorGUILayout.PropertyField(m_ForceIOSSpeakersWhenRecording, Styles.forceIOSSpeakersWhenRecording); - } - EditorGUILayout.PropertyField(m_UIRequiresPersistentWiFi, Styles.UIRequiresPersistentWiFi); - EditorGUILayout.PropertyField(m_IOSAllowHTTPDownload, Styles.iOSAllowHTTPDownload); - EditorGUILayout.PropertyField(m_IOSURLSchemes, Styles.iOSURLSchemes, true); - } - } - - using (new EditorGUI.DisabledScope(!Application.HasProLicense())) - { - bool oldDisableAnalytics = !m_SubmitAnalytics.boolValue; - bool newDisableAnalytics = EditorGUILayout.Toggle(Styles.disableStatistics, oldDisableAnalytics); - if (oldDisableAnalytics != newDisableAnalytics) - { - m_SubmitAnalytics.boolValue = !newDisableAnalytics; - EditorAnalytics.SendEventServiceInfo(new HwStatsServiceState() { hwstats = !newDisableAnalytics }); - } - if (!Application.HasProLicense()) - m_SubmitAnalytics.boolValue = true; - } - - if (settingsExtension != null) - settingsExtension.ConfigurationSectionGUI(); - - - // User script defines - { - EditorGUILayout.LabelField(Styles.scriptingDefineSymbols); - EditorGUI.BeginChangeCheck(); - string scriptDefines = EditorGUILayout.DelayedTextField(PlayerSettings.GetScriptingDefineSymbolsForGroup(targetGroup), EditorStyles.textField); - scriptingDefinesControlID = EditorGUIUtility.s_LastControlID; - if (EditorGUI.EndChangeCheck()) - PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, scriptDefines); - } - - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_AllowUnsafeCode, Styles.allowUnsafeCode); - if (EditorGUI.EndChangeCheck()) - { - PlayerSettings.allowUnsafeCode = m_AllowUnsafeCode.boolValue; - } - } - - // Active input handling - int inputOption = (!m_EnableInputSystem.boolValue) ? 0 : m_DisableInputManager.boolValue ? 1 : 2; - int oldInputOption = inputOption; - EditorGUI.BeginChangeCheck(); - inputOption = EditorGUILayout.Popup(Styles.activeInputHandling, inputOption, Styles.activeInputHandlingOptions); - if (EditorGUI.EndChangeCheck()) - { - if (inputOption != oldInputOption) - { - EditorUtility.DisplayDialog("Unity editor restart required", "The Unity editor must be restarted for this change to take effect.", "OK"); - m_EnableInputSystem.boolValue = (inputOption == 1 || inputOption == 2); - m_DisableInputManager.boolValue = !(inputOption == 0 || inputOption == 2); - m_EnableInputSystem.serializedObject.ApplyModifiedProperties(); - } - EditorGUIUtility.ExitGUI(); - } - - EditorGUILayout.Space(); - } - - private void OtherSectionOptimizationGUI(BuildTargetGroup targetGroup) - { - // Optimization - GUILayout.Label(Styles.optimizationTitle, EditorStyles.boldLabel); - - EditorGUILayout.PropertyField(m_BakeCollisionMeshes, Styles.bakeCollisionMeshes); - EditorGUILayout.PropertyField(m_KeepLoadedShadersAlive, Styles.keepLoadedShadersAlive); - EditorGUILayout.PropertyField(m_PreloadedAssets, Styles.preloadedAssets, true); - - bool platformUsesAOT = - targetGroup == BuildTargetGroup.iOS || - targetGroup == BuildTargetGroup.tvOS || - targetGroup == BuildTargetGroup.XboxOne || - targetGroup == BuildTargetGroup.PS4 || - targetGroup == BuildTargetGroup.PSP2; - - if (platformUsesAOT) - EditorGUILayout.PropertyField(m_AotOptions, Styles.aotOptions); - - bool platformSupportsStripping = - targetGroup == BuildTargetGroup.iOS || - targetGroup == BuildTargetGroup.tvOS || - targetGroup == BuildTargetGroup.Android || - targetGroup == BuildTargetGroup.Tizen || - targetGroup == BuildTargetGroup.WebGL || - targetGroup == BuildTargetGroup.PSP2 || - targetGroup == BuildTargetGroup.PS4 || - targetGroup == BuildTargetGroup.XboxOne || - targetGroup == BuildTargetGroup.WSA; - - if (platformSupportsStripping) - { - ScriptingImplementation backend = PlayerSettings.GetScriptingBackend(targetGroup); - if (targetGroup == BuildTargetGroup.WebGL || backend == ScriptingImplementation.IL2CPP) - { - EditorGUILayout.PropertyField(m_StripEngineCode, Styles.stripEngineCode); - } - else if (backend != ScriptingImplementation.WinRTDotNET) - { - EditorGUILayout.PropertyField(m_IPhoneStrippingLevel, Styles.iPhoneStrippingLevel); - } - } - - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS) - { - EditorGUILayout.PropertyField(m_IPhoneScriptCallOptimization, Styles.iPhoneScriptCallOptimization); - } - if (targetGroup == BuildTargetGroup.Android) - { - EditorGUILayout.PropertyField(m_AndroidProfiler, Styles.enableInternalProfiler); - } - - EditorGUILayout.Space(); - - // Vertex compression flags dropdown - VertexChannelCompressionFlags vertexFlags = (VertexChannelCompressionFlags)m_VertexChannelCompressionMask.intValue; - vertexFlags = (VertexChannelCompressionFlags)EditorGUILayout.EnumFlagsField(Styles.vertexChannelCompressionMask, vertexFlags); - m_VertexChannelCompressionMask.intValue = (int)vertexFlags; - - EditorGUILayout.PropertyField(m_StripUnusedMeshComponents, Styles.stripUnusedMeshComponents); - - if (targetGroup == BuildTargetGroup.PSP2) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_VideoMemoryForVertexBuffers, Styles.videoMemoryForVertexBuffers); - if (EditorGUI.EndChangeCheck()) - { - const int minVidMemForMesh = 0; - const int maxVidMemForMesh = 192; - if (m_VideoMemoryForVertexBuffers.intValue < minVidMemForMesh) - { - m_VideoMemoryForVertexBuffers.intValue = minVidMemForMesh; - } - else if (m_VideoMemoryForVertexBuffers.intValue > maxVidMemForMesh) - { - m_VideoMemoryForVertexBuffers.intValue = maxVidMemForMesh; - } - } - } - - EditorGUILayout.Space(); - } - - static ApiCompatibilityLevel[] only_4_x_profiles = new ApiCompatibilityLevel[] { ApiCompatibilityLevel.NET_4_6, ApiCompatibilityLevel.NET_Standard_2_0 }; - static ApiCompatibilityLevel[] only_2_0_profiles = new ApiCompatibilityLevel[] { ApiCompatibilityLevel.NET_2_0, ApiCompatibilityLevel.NET_2_0_Subset }; - static ApiCompatibilityLevel[] wsa_profiles = new ApiCompatibilityLevel[] { ApiCompatibilityLevel.NET_2_0, ApiCompatibilityLevel.NET_2_0_Subset, ApiCompatibilityLevel.NET_4_6 }; - - private ApiCompatibilityLevel[] GetAvailableApiCompatibilityLevels(BuildTargetGroup activeBuildTargetGroup) - { - if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) - return only_4_x_profiles; - - if (activeBuildTargetGroup == BuildTargetGroup.WSA) - return wsa_profiles; - - return only_2_0_profiles; - } - - static Il2CppCompilerConfiguration[] m_Il2cppCompilerConfigurations; - static GUIContent[] m_Il2cppCompilerConfigurationNames; - - private Il2CppCompilerConfiguration[] GetIl2CppCompilerConfigurations() - { - if (m_Il2cppCompilerConfigurations == null) - { - m_Il2cppCompilerConfigurations = new Il2CppCompilerConfiguration[] - { - Il2CppCompilerConfiguration.Debug, - Il2CppCompilerConfiguration.Release, - }; - } - - return m_Il2cppCompilerConfigurations; - } - - private GUIContent[] GetIl2CppCompilerConfigurationNames() - { - if (m_Il2cppCompilerConfigurationNames == null) - { - var configurations = GetIl2CppCompilerConfigurations(); - m_Il2cppCompilerConfigurationNames = new GUIContent[configurations.Length]; - - for (int i = 0; i < configurations.Length; i++) - m_Il2cppCompilerConfigurationNames[i] = EditorGUIUtility.TextContent(configurations[i].ToString()); - } - - return m_Il2cppCompilerConfigurationNames; - } - - public static bool IsLatestApiCompatibility(ApiCompatibilityLevel level) - { - return (level == ApiCompatibilityLevel.NET_4_6 || level == ApiCompatibilityLevel.NET_Standard_2_0); - } - - private void OtherSectionLoggingGUI() - { - GUILayout.Label(Styles.loggingTitle, EditorStyles.boldLabel); - - GUILayout.BeginVertical(); - GUILayout.BeginHorizontal(); - GUILayout.Label("Log Type"); - foreach (StackTraceLogType stackTraceLogType in Enum.GetValues(typeof(StackTraceLogType))) - { - GUILayout.Label(stackTraceLogType.ToString(), GUILayout.Width(70)); - } - GUILayout.EndHorizontal(); - - foreach (LogType logType in Enum.GetValues(typeof(LogType))) - { - GUILayout.BeginHorizontal(); - GUILayout.Label(logType.ToString()); - foreach (StackTraceLogType stackTraceLogType in Enum.GetValues(typeof(StackTraceLogType))) - { - StackTraceLogType inStackTraceLogType = PlayerSettings.GetStackTraceLogType(logType); - EditorGUI.BeginChangeCheck(); - bool val = EditorGUILayout.ToggleLeft(" ", inStackTraceLogType == stackTraceLogType, GUILayout.Width(70)); - if (EditorGUI.EndChangeCheck() && val) - { - PlayerSettings.SetStackTraceLogType(logType, stackTraceLogType); - } - } - GUILayout.EndHorizontal(); - } - - GUILayout.EndVertical(); - } - - private static Dictionary m_NiceScriptingBackendNames; - private static Dictionary m_NiceApiCompatibilityLevelNames; - - private static GUIContent[] GetGUIContentsForValues(Dictionary contents, T[] values) - { - var names = new GUIContent[values.Length]; - - for (int i = 0; i < values.Length; i++) - { - if (contents.ContainsKey(values[i])) - names[i] = contents[values[i]]; - else - throw new NotImplementedException(string.Format("Missing name for {0}", values[i])); - } - return names; - } - - private static GUIContent[] GetNiceScriptingBackendNames(ScriptingImplementation[] scriptingBackends) - { - if (m_NiceScriptingBackendNames == null) - { - m_NiceScriptingBackendNames = new Dictionary - { - { ScriptingImplementation.Mono2x, Styles.scriptingMono2x }, - { ScriptingImplementation.WinRTDotNET, Styles.scriptingWinRTDotNET }, - { ScriptingImplementation.IL2CPP, Styles.scriptingIL2CPP } - }; - } - - return GetGUIContentsForValues(m_NiceScriptingBackendNames, scriptingBackends); - } - - private static GUIContent[] GetNiceApiCompatibilityLevelNames(ApiCompatibilityLevel[] apiCompatibilityLevels) - { - if (m_NiceApiCompatibilityLevelNames == null) - { - m_NiceApiCompatibilityLevelNames = new Dictionary - { - { ApiCompatibilityLevel.NET_2_0, Styles.apiCompatibilityLevel_NET_2_0 }, - { ApiCompatibilityLevel.NET_2_0_Subset, Styles.apiCompatibilityLevel_NET_2_0_Subset }, - { ApiCompatibilityLevel.NET_4_6, Styles.apiCompatibilityLevel_NET_4_6 }, - { ApiCompatibilityLevel.NET_Standard_2_0, Styles.apiCompatibilityLevel_NET_Standard_2_0 } - }; - } - - return GetGUIContentsForValues(m_NiceApiCompatibilityLevelNames, apiCompatibilityLevels); - } - - private void AutoAssignProperty(SerializedProperty property, string packageDir, string fileName) - { - if (property.stringValue.Length == 0 || !File.Exists(Path.Combine(packageDir, property.stringValue))) - { - string filePath = Path.Combine(packageDir, fileName); - if (File.Exists(filePath)) - property.stringValue = fileName; - } - } - - public void BrowseablePathProperty(string propertyLabel, SerializedProperty property, string browsePanelTitle, string extension, string dir) - { - EditorGUILayout.BeginHorizontal(); - - EditorGUILayout.PrefixLabel(EditorGUIUtility.TextContent(propertyLabel)); - - GUIContent browseBtnLabel = EditorGUIUtility.TrTextContent("..."); - Vector2 sizeOfLabel = GUI.skin.GetStyle("Button").CalcSize(browseBtnLabel); - - if (GUILayout.Button(browseBtnLabel, EditorStyles.miniButton, GUILayout.MaxWidth(sizeOfLabel.x))) - { - GUI.FocusControl(""); - - string title = EditorGUIUtility.TempContent(browsePanelTitle).text; - string currDirectory = string.IsNullOrEmpty(dir) ? Directory.GetCurrentDirectory().Replace('\\', '/') + "/" : dir.Replace('\\', '/') + "/"; - string newStringValue = ""; - - if (string.IsNullOrEmpty(extension)) - newStringValue = EditorUtility.OpenFolderPanel(title, currDirectory, ""); - else - newStringValue = EditorUtility.OpenFilePanel(title, currDirectory, extension); - - if (newStringValue.StartsWith(currDirectory)) - newStringValue = newStringValue.Substring(currDirectory.Length); - - if (!string.IsNullOrEmpty(newStringValue)) - { - property.stringValue = newStringValue; - serializedObject.ApplyModifiedProperties(); - } - } - - GUIContent gc = null; - bool emptyString = string.IsNullOrEmpty(property.stringValue); - using (new EditorGUI.DisabledScope(emptyString)) - { - if (emptyString) - { - gc = EditorGUIUtility.TrTextContent("Not selected."); - } - else - { - gc = EditorGUIUtility.TempContent(property.stringValue); - } - - EditorGUI.BeginChangeCheck(); - GUILayoutOption[] options = { GUILayout.Width(32), GUILayout.ExpandWidth(true) }; - string modifiedString = EditorGUILayout.TextArea(gc.text, options); - if (EditorGUI.EndChangeCheck()) - { - if (string.IsNullOrEmpty(modifiedString)) - { - property.stringValue = ""; - serializedObject.ApplyModifiedProperties(); - GUI.FocusControl(""); - } - } - } - - EditorGUILayout.EndHorizontal(); - EditorGUILayout.Space(); - } - - internal static bool BuildPathBoxButton(SerializedProperty prop, string uiString, string directory) - { - return BuildPathBoxButton(prop, uiString, directory, null); - } - - internal static bool BuildPathBoxButton(SerializedProperty prop, string uiString, string directory, Action onSelect) - { - float h = EditorGUI.kSingleLineHeight; - float kLabelFloatMinW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; - float kLabelFloatMaxW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; - Rect r = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, h, h, EditorStyles.layerMaskField, null); - - float labelWidth = EditorGUIUtility.labelWidth; - Rect buttonRect = new Rect(r.x + EditorGUI.indent, r.y, labelWidth - EditorGUI.indent, r.height); - Rect fieldRect = new Rect(r.x + labelWidth, r.y, r.width - labelWidth, r.height); - - string display = (prop.stringValue.Length == 0) ? "Not selected." : prop.stringValue; - EditorGUI.TextArea(fieldRect, display, EditorStyles.label); - - bool changed = false; - if (GUI.Button(buttonRect, EditorGUIUtility.TextContent(uiString))) - { - string prevVal = prop.stringValue; - string path = EditorUtility.OpenFolderPanel(EditorGUIUtility.TextContent(uiString).text, directory, ""); - - string relPath = FileUtil.GetProjectRelativePath(path); - prop.stringValue = (relPath != string.Empty) ? relPath : path; - changed = (prop.stringValue != prevVal); - - if (onSelect != null) - onSelect(); - - prop.serializedObject.ApplyModifiedProperties(); - } - - return changed; - } - - internal static bool BuildFileBoxButton(SerializedProperty prop, string uiString, string directory, string ext) - { - return BuildFileBoxButton(prop, uiString, directory, ext, null); - } - - internal static bool BuildFileBoxButton(SerializedProperty prop, string uiString, string directory, - string ext, Action onSelect) - { - float h = EditorGUI.kSingleLineHeight; - float kLabelFloatMinW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; - float kLabelFloatMaxW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; - Rect r = GUILayoutUtility.GetRect(kLabelFloatMinW, kLabelFloatMaxW, h, h, EditorStyles.layerMaskField, null); - - float labelWidth = EditorGUIUtility.labelWidth; - Rect buttonRect = new Rect(r.x + EditorGUI.indent, r.y, labelWidth - EditorGUI.indent, r.height); - Rect fieldRect = new Rect(r.x + labelWidth, r.y, r.width - labelWidth, r.height); - - string display = (prop.stringValue.Length == 0) ? "Not selected." : prop.stringValue; - EditorGUI.TextArea(fieldRect, display, EditorStyles.label); - - bool changed = false; - if (GUI.Button(buttonRect, EditorGUIUtility.TextContent(uiString))) - { - string prevVal = prop.stringValue; - string path = EditorUtility.OpenFilePanel(EditorGUIUtility.TextContent(uiString).text, directory, ext); - - string relPath = FileUtil.GetProjectRelativePath(path); - prop.stringValue = (relPath != string.Empty) ? relPath : path; - changed = (prop.stringValue != prevVal); - - if (onSelect != null) - onSelect(); - - prop.serializedObject.ApplyModifiedProperties(); - } - - return changed; - } - - public void PublishSectionGUI(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension, int sectionIndex = 5) - { - if (targetGroup != BuildTargetGroup.WSA && - targetGroup != BuildTargetGroup.PSP2 && - !(settingsExtension != null && settingsExtension.HasPublishSection())) - return; - - if (BeginSettingsBox(sectionIndex, Styles.publishingSettingsTitle)) - { - float h = EditorGUI.kSingleLineHeight; - float kLabelFloatMinW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; - float kLabelFloatMaxW = EditorGUI.kLabelW + EditorGUIUtility.fieldWidth + EditorGUI.kSpacing; - - if (settingsExtension != null) - { - settingsExtension.PublishSectionGUI(h, kLabelFloatMinW, kLabelFloatMaxW); - } - } - EndSettingsBox(); - } - - private static void ShowWarning(GUIContent warningMessage) - { - if (s_WarningIcon == null) - s_WarningIcon = EditorGUIUtility.LoadIcon("console.warnicon"); - - // var c = new GUIContent(error) { image = s_WarningIcon }; - warningMessage.image = s_WarningIcon; - - GUILayout.Space(5); - GUILayout.BeginVertical(EditorStyles.helpBox); - GUILayout.Label(warningMessage, EditorStyles.wordWrappedMiniLabel); - GUILayout.EndVertical(); - } - - protected override bool ShouldHideOpenButton() - { - return true; - } - } -} diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.bindings.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.bindings.cs deleted file mode 100644 index c640bc548a..0000000000 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.bindings.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace UnityEditor -{ - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - [NativeHeader("Runtime/Scripting/ScriptingExportUtility.h")] - [NativeHeader("Runtime/Graphics/DrawSplashScreenAndWatermarks.h")] - internal partial class PlayerSettingsSplashScreenEditor - { - internal static extern bool licenseAllowsDisabling - { - [FreeFunction("GetPlayerSettings().GetSplashScreenSettings().CanDisableSplashScreen")] - get; - } - - [FreeFunction("GetSplashScreenBackgroundColor")] - internal static extern Color GetSplashScreenActualBackgroundColor(); - - [FreeFunction("GetSplashScreenBackground")] - internal static extern Texture2D GetSplashScreenActualBackgroundImage(Rect windowRect); - - [FreeFunction("GetSplashScreenBackgroundUvs")] - internal static extern Rect GetSplashScreenActualUVs(Rect windowRect); - } -} diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.cs deleted file mode 100644 index bf2cc635cb..0000000000 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.cs +++ /dev/null @@ -1,399 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEditor.Modules; -using UnityEditorInternal; -using UnityEngine.Rendering; -using UnityEngine; -using UnityEditor.Build; - -namespace UnityEditor -{ - internal partial class PlayerSettingsSplashScreenEditor - { - PlayerSettingsEditor m_Owner; - - SerializedProperty m_ResolutionDialogBanner; - SerializedProperty m_ShowUnitySplashLogo; - SerializedProperty m_ShowUnitySplashScreen; - SerializedProperty m_SplashScreenAnimation; - SerializedProperty m_SplashScreenBackgroundAnimationZoom; - SerializedProperty m_SplashScreenBackgroundColor; - SerializedProperty m_SplashScreenBackgroundLandscape; - SerializedProperty m_SplashScreenBackgroundPortrait; - SerializedProperty m_SplashScreenDrawMode; - SerializedProperty m_SplashScreenLogoAnimationZoom; - SerializedProperty m_SplashScreenLogos; - SerializedProperty m_SplashScreenLogoStyle; - SerializedProperty m_SplashScreenOverlayOpacity; - SerializedProperty m_VirtualRealitySplashScreen; - - ReorderableList m_LogoList; - - float m_TotalLogosDuration; - - static readonly float k_MinLogoTime = 2; - static readonly float k_MaxLogoTime = 10.0f; - static readonly float k_DefaultLogoTime = 2.0f; - - static readonly float k_LogoListElementHeight = 72; - static readonly float k_LogoListLogoFieldHeight = 64; - static readonly float k_LogoListFooterHeight = 20; - static readonly float k_LogoListUnityLogoMinWidth = 64; - static readonly float k_LogoListUnityLogoMaxWidth = 220; - static readonly float k_LogoListPropertyMinWidth = 230; - static readonly float k_LogoListPropertyLabelWidth = 100; - static readonly float k_MinPersonalEditionOverlayOpacity = 0.5f; - static readonly float k_MinProEditionOverlayOpacity = 0.0f; - - static Sprite s_UnityLogo; - - readonly AnimBool m_ShowAnimationControlsAnimator = new AnimBool(); - readonly AnimBool m_ShowBackgroundColorAnimator = new AnimBool(); - readonly AnimBool m_ShowLogoControlsAnimator = new AnimBool(); - - class Texts - { - public GUIContent animate = EditorGUIUtility.TrTextContent("Animation"); - public GUIContent backgroundColor = EditorGUIUtility.TrTextContent("Background Color", "Background color when no background image is used."); - public GUIContent backgroundImage = EditorGUIUtility.TrTextContent("Background Image", "Image to be used in landscape and portrait(when portrait image is not set)."); - public GUIContent backgroundPortraitImage = EditorGUIUtility.TrTextContent("Alternate Portrait Image*", "Optional image to be used in portrait mode."); - public GUIContent backgroundTitle = EditorGUIUtility.TrTextContent("Background*"); - public GUIContent backgroundZoom = EditorGUIUtility.TrTextContent("Background Zoom"); - public GUIContent configDialogBanner = EditorGUIUtility.TrTextContent("Application Config Dialog Banner"); - public GUIContent drawMode = EditorGUIUtility.TrTextContent("Draw Mode"); - public GUIContent logoDuration = EditorGUIUtility.TrTextContent("Logo Duration", "The time the logo will be shown for."); - public GUIContent logosTitle = EditorGUIUtility.TrTextContent("Logos*"); - public GUIContent logoZoom = EditorGUIUtility.TrTextContent("Logo Zoom"); - public GUIContent overlayOpacity = EditorGUIUtility.TrTextContent("Overlay Opacity", "Overlay strength applied to improve logo visibility."); - public GUIContent previewSplash = EditorGUIUtility.TrTextContent("Preview", "Preview the splash screen in the game view."); - public GUIContent showLogo = EditorGUIUtility.TrTextContent("Show Unity Logo"); - public GUIContent showSplash = EditorGUIUtility.TrTextContent("Show Splash Screen"); - public GUIContent splashStyle = EditorGUIUtility.TrTextContent("Splash Style"); - public GUIContent splashTitle = EditorGUIUtility.TrTextContent("Splash Screen"); - public GUIContent title = EditorGUIUtility.TrTextContent("Splash Image"); - public GUIContent vrSplashScreen = EditorGUIUtility.TrTextContent("Virtual Reality Splash Image"); - } - static readonly Texts k_Texts = new Texts(); - - public PlayerSettingsSplashScreenEditor(PlayerSettingsEditor owner) - { - m_Owner = owner; - } - - public void OnEnable() - { - m_ResolutionDialogBanner = m_Owner.FindPropertyAssert("resolutionDialogBanner"); - m_ShowUnitySplashLogo = m_Owner.FindPropertyAssert("m_ShowUnitySplashLogo"); - m_ShowUnitySplashScreen = m_Owner.FindPropertyAssert("m_ShowUnitySplashScreen"); - m_SplashScreenAnimation = m_Owner.FindPropertyAssert("m_SplashScreenAnimation"); - m_SplashScreenBackgroundAnimationZoom = m_Owner.FindPropertyAssert("m_SplashScreenBackgroundAnimationZoom"); - m_SplashScreenBackgroundColor = m_Owner.FindPropertyAssert("m_SplashScreenBackgroundColor"); - m_SplashScreenBackgroundLandscape = m_Owner.FindPropertyAssert("splashScreenBackgroundSourceLandscape"); - m_SplashScreenBackgroundPortrait = m_Owner.FindPropertyAssert("splashScreenBackgroundSourcePortrait"); - m_SplashScreenDrawMode = m_Owner.FindPropertyAssert("m_SplashScreenDrawMode"); - m_SplashScreenLogoAnimationZoom = m_Owner.FindPropertyAssert("m_SplashScreenLogoAnimationZoom"); - m_SplashScreenLogos = m_Owner.FindPropertyAssert("m_SplashScreenLogos"); - m_SplashScreenLogoStyle = m_Owner.FindPropertyAssert("m_SplashScreenLogoStyle"); - m_SplashScreenOverlayOpacity = m_Owner.FindPropertyAssert("m_SplashScreenOverlayOpacity"); - m_VirtualRealitySplashScreen = m_Owner.FindPropertyAssert("m_VirtualRealitySplashScreen"); - - m_LogoList = new ReorderableList(m_Owner.serializedObject, m_SplashScreenLogos, true, true, true, true); - m_LogoList.elementHeight = k_LogoListElementHeight; - m_LogoList.footerHeight = k_LogoListFooterHeight; - m_LogoList.onAddCallback = OnLogoListAddCallback; - m_LogoList.drawHeaderCallback = DrawLogoListHeaderCallback; - m_LogoList.onCanRemoveCallback = OnLogoListCanRemoveCallback; - m_LogoList.drawElementCallback = DrawLogoListElementCallback; - m_LogoList.drawFooterCallback = DrawLogoListFooterCallback; - - // Set up animations - m_ShowAnimationControlsAnimator.value = m_SplashScreenAnimation.intValue == (int)PlayerSettings.SplashScreen.AnimationMode.Custom; - m_ShowAnimationControlsAnimator.valueChanged.AddListener(m_Owner.Repaint); - m_ShowBackgroundColorAnimator.value = m_SplashScreenBackgroundLandscape.objectReferenceValue == null; - m_ShowBackgroundColorAnimator.valueChanged.AddListener(m_Owner.Repaint); - m_ShowLogoControlsAnimator.value = m_ShowUnitySplashLogo.boolValue; - m_ShowLogoControlsAnimator.valueChanged.AddListener(m_Owner.Repaint); - - if (s_UnityLogo == null) - s_UnityLogo = Resources.GetBuiltinResource("UnitySplash-cube.png"); - } - - private void DrawLogoListHeaderCallback(Rect rect) - { - m_TotalLogosDuration = 0; // Calculated during logo list draw - EditorGUI.LabelField(rect, "Logos"); - } - - private void DrawElementUnityLogo(Rect rect, int index, bool isActive, bool isFocused) - { - var element = m_SplashScreenLogos.GetArrayElementAtIndex(index); - var duration = element.FindPropertyRelative("duration"); - - // Unity logo - float logoWidth = Mathf.Clamp(rect.width - k_LogoListPropertyMinWidth, k_LogoListUnityLogoMinWidth, k_LogoListUnityLogoMaxWidth); - float logoHeight = logoWidth / (s_UnityLogo.texture.width / (float)s_UnityLogo.texture.height); - var logoRect = new Rect(rect.x, rect.y + (rect.height - logoHeight) / 2.0f, k_LogoListUnityLogoMaxWidth, logoHeight); - var oldCol = GUI.color; - GUI.color = (m_SplashScreenLogoStyle.intValue == (int)PlayerSettings.SplashScreen.UnityLogoStyle.DarkOnLight ? Color.black : Color.white); - GUI.Label(logoRect, s_UnityLogo.texture); - GUI.color = oldCol; - - // Properties - var oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = k_LogoListPropertyLabelWidth; - var propertyRect = new Rect(rect.x + logoWidth, rect.y + EditorGUIUtility.standardVerticalSpacing + EditorGUIUtility.singleLineHeight, rect.width - logoWidth, EditorGUIUtility.singleLineHeight); - EditorGUI.BeginChangeCheck(); - var durationLabel = EditorGUI.BeginProperty(propertyRect, k_Texts.logoDuration, duration); - var newDurationVal = EditorGUI.Slider(propertyRect, durationLabel, duration.floatValue, k_MinLogoTime, k_MaxLogoTime); - if (EditorGUI.EndChangeCheck()) - duration.floatValue = newDurationVal; - EditorGUI.EndProperty(); - EditorGUIUtility.labelWidth = oldLabelWidth; - - m_TotalLogosDuration += duration.floatValue; - } - - private void DrawLogoListElementCallback(Rect rect, int index, bool isActive, bool isFocused) - { - rect.height -= EditorGUIUtility.standardVerticalSpacing; - - var element = m_SplashScreenLogos.GetArrayElementAtIndex(index); - var logo = element.FindPropertyRelative("logo"); - - if ((Sprite)logo.objectReferenceValue == s_UnityLogo) - { - DrawElementUnityLogo(rect, index, isActive, isFocused); - return; - } - - // Logo field - float unityLogoWidth = Mathf.Clamp(rect.width - k_LogoListPropertyMinWidth, k_LogoListUnityLogoMinWidth, k_LogoListUnityLogoMaxWidth); - var logoRect = new Rect(rect.x, rect.y + (rect.height - k_LogoListLogoFieldHeight) / 2.0f, k_LogoListUnityLogoMinWidth, k_LogoListLogoFieldHeight); - EditorGUI.BeginChangeCheck(); - var value = EditorGUI.ObjectField(logoRect, GUIContent.none, (Sprite)logo.objectReferenceValue, typeof(Sprite), false); - if (EditorGUI.EndChangeCheck()) - logo.objectReferenceValue = value; - - // Properties - var oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = k_LogoListPropertyLabelWidth; - var propertyRect = new Rect(rect.x + unityLogoWidth, rect.y + EditorGUIUtility.standardVerticalSpacing + EditorGUIUtility.singleLineHeight, rect.width - unityLogoWidth, EditorGUIUtility.singleLineHeight); - EditorGUI.BeginChangeCheck(); - var duration = element.FindPropertyRelative("duration"); - var newDurationVal = EditorGUI.Slider(propertyRect, k_Texts.logoDuration, duration.floatValue, k_MinLogoTime, k_MaxLogoTime); - if (EditorGUI.EndChangeCheck()) - duration.floatValue = newDurationVal; - - EditorGUIUtility.labelWidth = oldLabelWidth; - - m_TotalLogosDuration += duration.floatValue; - } - - private void DrawLogoListFooterCallback(Rect rect) - { - float totalDuration = Mathf.Max(k_MinLogoTime, m_TotalLogosDuration); - EditorGUI.LabelField(rect, "Splash Screen Duration: " + totalDuration.ToString(), EditorStyles.miniBoldLabel); - ReorderableList.defaultBehaviours.DrawFooter(rect, m_LogoList); - } - - private void OnLogoListAddCallback(ReorderableList list) - { - int index = m_SplashScreenLogos.arraySize; - m_SplashScreenLogos.InsertArrayElementAtIndex(m_SplashScreenLogos.arraySize); - var element = m_SplashScreenLogos.GetArrayElementAtIndex(index); - - // Set up default values. - var logo = element.FindPropertyRelative("logo"); - var duration = element.FindPropertyRelative("duration"); - logo.objectReferenceValue = null; - duration.floatValue = k_DefaultLogoTime; - } - - // Prevent users removing the unity logo. - private static bool OnLogoListCanRemoveCallback(ReorderableList list) - { - var element = list.serializedProperty.GetArrayElementAtIndex(list.index); - var logo = (Sprite)element.FindPropertyRelative("logo").objectReferenceValue; - return logo != s_UnityLogo; - } - - private void AddUnityLogoToLogosList() - { - // Only add a logo if one does not already exist. - for (int i = 0; i < m_SplashScreenLogos.arraySize; ++i) - { - var listElement = m_SplashScreenLogos.GetArrayElementAtIndex(i); - var listLogo = listElement.FindPropertyRelative("logo"); - if ((Sprite)listLogo.objectReferenceValue == s_UnityLogo) - return; - } - - m_SplashScreenLogos.InsertArrayElementAtIndex(0); - var element = m_SplashScreenLogos.GetArrayElementAtIndex(0); - var logo = element.FindPropertyRelative("logo"); - var duration = element.FindPropertyRelative("duration"); - logo.objectReferenceValue = s_UnityLogo; - duration.floatValue = k_DefaultLogoTime; - } - - private void RemoveUnityLogoFromLogosList() - { - for (int i = 0; i < m_SplashScreenLogos.arraySize; ++i) - { - var element = m_SplashScreenLogos.GetArrayElementAtIndex(i); - var logo = element.FindPropertyRelative("logo"); - if ((Sprite)logo.objectReferenceValue == s_UnityLogo) - { - m_SplashScreenLogos.DeleteArrayElementAtIndex(i); - --i; // Continue checking in case we have duplicates. - } - } - } - - private static bool TargetSupportsOptionalBuiltinSplashScreen(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension) - { - if (settingsExtension != null) - return settingsExtension.CanShowUnitySplashScreen(); - return targetGroup == BuildTargetGroup.Standalone; - } - - private static void ObjectReferencePropertyField(SerializedProperty property, GUIContent label) where T : UnityEngine.Object - { - EditorGUI.BeginChangeCheck(); - Rect r = EditorGUILayout.GetControlRect(true, 64, EditorStyles.objectFieldThumb); - label = EditorGUI.BeginProperty(r, label, property); - var value = EditorGUI.ObjectField(r, label, (T)property.objectReferenceValue, typeof(T), false); - if (EditorGUI.EndChangeCheck()) - { - property.objectReferenceValue = value; - GUI.changed = true; - } - EditorGUI.EndProperty(); - } - - public void SplashSectionGUI(BuildPlatform platform, BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension, int sectionIndex = 2) - { - GUI.changed = false; - if (m_Owner.BeginSettingsBox(sectionIndex, k_Texts.title)) - { - if (targetGroup == BuildTargetGroup.Standalone) - { - ObjectReferencePropertyField(m_ResolutionDialogBanner, k_Texts.configDialogBanner); - EditorGUILayout.Space(); - } - - if (m_Owner.m_VRSettings.TargetGroupSupportsVirtualReality(targetGroup)) - ObjectReferencePropertyField(m_VirtualRealitySplashScreen, k_Texts.vrSplashScreen); - - if (TargetSupportsOptionalBuiltinSplashScreen(targetGroup, settingsExtension)) - BuiltinCustomSplashScreenGUI(); - - if (settingsExtension != null) - settingsExtension.SplashSectionGUI(); - - if (m_ShowUnitySplashScreen.boolValue) - m_Owner.ShowSharedNote(); - } - m_Owner.EndSettingsBox(); - } - - private void BuiltinCustomSplashScreenGUI() - { - EditorGUILayout.LabelField(k_Texts.splashTitle, EditorStyles.boldLabel); - - using (new EditorGUI.DisabledScope(!licenseAllowsDisabling)) - { - EditorGUILayout.PropertyField(m_ShowUnitySplashScreen, k_Texts.showSplash); - if (!m_ShowUnitySplashScreen.boolValue) - return; - } - - Rect previewButtonRect = GUILayoutUtility.GetRect(k_Texts.previewSplash, "button"); - previewButtonRect = EditorGUI.PrefixLabel(previewButtonRect, new GUIContent(" ")); - if (GUI.Button(previewButtonRect, k_Texts.previewSplash)) - { - SplashScreen.Begin(); - - var gv = GameView.GetMainGameView(); - if (gv) - gv.Focus(); - - GameView.RepaintAll(); - } - - EditorGUILayout.PropertyField(m_SplashScreenLogoStyle, k_Texts.splashStyle); - - // Animation - EditorGUILayout.PropertyField(m_SplashScreenAnimation, k_Texts.animate); - m_ShowAnimationControlsAnimator.target = m_SplashScreenAnimation.intValue == (int)PlayerSettings.SplashScreen.AnimationMode.Custom; - - if (EditorGUILayout.BeginFadeGroup(m_ShowAnimationControlsAnimator.faded)) - { - EditorGUI.indentLevel++; - EditorGUILayout.Slider(m_SplashScreenLogoAnimationZoom, 0.0f, 1.0f, k_Texts.logoZoom); - EditorGUILayout.Slider(m_SplashScreenBackgroundAnimationZoom, 0.0f, 1.0f, k_Texts.backgroundZoom); - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - - EditorGUILayout.Space(); - - // Logos - EditorGUILayout.LabelField(k_Texts.logosTitle, EditorStyles.boldLabel); - using (new EditorGUI.DisabledScope(!Application.HasProLicense())) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_ShowUnitySplashLogo, k_Texts.showLogo); - if (EditorGUI.EndChangeCheck()) - { - if (!m_ShowUnitySplashLogo.boolValue) - RemoveUnityLogoFromLogosList(); - else if (m_SplashScreenDrawMode.intValue == (int)PlayerSettings.SplashScreen.DrawMode.AllSequential) - AddUnityLogoToLogosList(); - } - - m_ShowLogoControlsAnimator.target = m_ShowUnitySplashLogo.boolValue; - } - - if (EditorGUILayout.BeginFadeGroup(m_ShowLogoControlsAnimator.faded)) - { - EditorGUI.indentLevel++; - EditorGUI.BeginChangeCheck(); - var oldDrawmode = m_SplashScreenDrawMode.intValue; - EditorGUILayout.PropertyField(m_SplashScreenDrawMode, k_Texts.drawMode); - if (oldDrawmode != m_SplashScreenDrawMode.intValue) - { - if (m_SplashScreenDrawMode.intValue == (int)PlayerSettings.SplashScreen.DrawMode.UnityLogoBelow) - RemoveUnityLogoFromLogosList(); - else - AddUnityLogoToLogosList(); - } - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - - m_LogoList.DoLayoutList(); - EditorGUILayout.Space(); - - // Background - EditorGUILayout.LabelField(k_Texts.backgroundTitle, EditorStyles.boldLabel); - EditorGUILayout.Slider(m_SplashScreenOverlayOpacity, Application.HasProLicense() ? k_MinProEditionOverlayOpacity : k_MinPersonalEditionOverlayOpacity, 1.0f, k_Texts.overlayOpacity); - m_ShowBackgroundColorAnimator.target = m_SplashScreenBackgroundLandscape.objectReferenceValue == null; - if (EditorGUILayout.BeginFadeGroup(m_ShowBackgroundColorAnimator.faded)) - EditorGUILayout.PropertyField(m_SplashScreenBackgroundColor, k_Texts.backgroundColor); - EditorGUILayout.EndFadeGroup(); - - ObjectReferencePropertyField(m_SplashScreenBackgroundLandscape, k_Texts.backgroundImage); - if (GUI.changed && m_SplashScreenBackgroundLandscape.objectReferenceValue == null) - m_SplashScreenBackgroundPortrait.objectReferenceValue = null; - - using (new EditorGUI.DisabledScope(m_SplashScreenBackgroundLandscape.objectReferenceValue == null)) - { - ObjectReferencePropertyField(m_SplashScreenBackgroundPortrait, k_Texts.backgroundPortraitImage); - } - } - } -} diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/WebTemplate.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/WebTemplate.cs deleted file mode 100644 index a913b80955..0000000000 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/WebTemplate.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class WebTemplate - { - public string m_Path, m_Name; - public Texture2D m_Thumbnail; - public string[] m_CustomKeys; - - public string[] CustomKeys - { - get - { - return m_CustomKeys; - } - } - - public override bool Equals(System.Object other) - { - return other is WebTemplate && other.ToString().Equals(ToString()); - } - - public override int GetHashCode() - { - return base.GetHashCode() ^ m_Path.GetHashCode(); - } - - public override string ToString() - { - return m_Path; - } - - public GUIContent ToGUIContent(Texture2D defaultIcon) - { - return new GUIContent(m_Name, m_Thumbnail == null ? defaultIcon : m_Thumbnail); - } - } -} diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/WebTemplateManagerBase.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/WebTemplateManagerBase.cs deleted file mode 100644 index 8c5669e723..0000000000 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/WebTemplateManagerBase.cs +++ /dev/null @@ -1,290 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.IO; -using System.Text.RegularExpressions; - -namespace UnityEditor -{ - internal abstract class WebTemplateManagerBase - { - class Styles - { - public GUIStyle thumbnail = "IN ThumbnailShadow"; - public GUIStyle thumbnailLabel = "IN ThumbnailSelection"; - } - - private static Styles s_Styles; - - private WebTemplate[] s_Templates = null; - private GUIContent[] s_TemplateGUIThumbnails = null; - - // Template layout constants - const float kWebTemplateGridPadding = 15.0f; - const float kThumbnailSize = 80.0f; - const float kThumbnailLabelHeight = 20.0f; - const float kThumbnailPadding = 5.0f; - - public abstract string customTemplatesFolder - { - get; - } - - public abstract string builtinTemplatesFolder - { - get; - } - - public abstract Texture2D defaultIcon - { - get; - } - - public WebTemplate[] Templates - { - get - { - if (s_Templates == null || s_TemplateGUIThumbnails == null) - { - BuildTemplateList(); - } - - return s_Templates; - } - } - - public GUIContent[] TemplateGUIThumbnails - { - get - { - if (s_Templates == null || s_TemplateGUIThumbnails == null) - { - BuildTemplateList(); - } - - return s_TemplateGUIThumbnails; - } - } - - public int GetTemplateIndex(string path) - { - for (int i = 0; i < Templates.Length; i++) - { - if (path.Equals(Templates[i].ToString())) - { - return i; - } - } - return 0; - } - - public void ClearTemplates() - { - s_Templates = null; - s_TemplateGUIThumbnails = null; - } - - private void BuildTemplateList() - { - List templates = new List(); - - if (Directory.Exists(customTemplatesFolder)) - { - templates.AddRange(ListTemplates(customTemplatesFolder)); - } - - if (Directory.Exists(builtinTemplatesFolder)) - { - templates.AddRange(ListTemplates(builtinTemplatesFolder)); - } - else - { - Debug.LogError("Did not find built-in templates."); - } - - s_Templates = templates.ToArray(); - - s_TemplateGUIThumbnails = new GUIContent[s_Templates.Length]; - for (int i = 0; i < s_TemplateGUIThumbnails.Length; i++) - { - s_TemplateGUIThumbnails[i] = s_Templates[i].ToGUIContent(defaultIcon); - } - } - - private WebTemplate Load(string path) - { - if (!Directory.Exists(path) || Directory.GetFiles(path, "index.*").Length < 1) - { - return null; - } - - string[] splitPath = path.Split(new char[] {'/', '\\'}); - - WebTemplate template = new WebTemplate(); - - template.m_Name = splitPath[splitPath.Length - 1]; - if (splitPath.Length > 3 && splitPath[splitPath.Length - 3].Equals("Assets")) - { - template.m_Path = "PROJECT:" + template.m_Name; - } - else - { - template.m_Path = "APPLICATION:" + template.m_Name; - } - - string[] thumbFiles = Directory.GetFiles(path, "thumbnail.*"); - if (thumbFiles.Length > 0) - { - template.m_Thumbnail = new Texture2D(2, 2); - template.m_Thumbnail.LoadImage(File.ReadAllBytes(thumbFiles[0])); - } - - List keys = new List(); - Regex customKeyFinder = new Regex("\\%UNITY_CUSTOM_([A-Z_]+)\\%"); - MatchCollection matches = customKeyFinder.Matches(File.ReadAllText(Directory.GetFiles(path, "index.*")[0])); - foreach (Match match in matches) - { - string name = match.Value.Substring("%UNITY_CUSTOM_".Length); - name = name.Substring(0, name.Length - 1); - if (!keys.Contains(name)) - { - keys.Add(name); - } - } - template.m_CustomKeys = keys.ToArray(); - - return template; - } - - private List ListTemplates(string path) - { - List templates = new List(); - string[] directories = Directory.GetDirectories(path); - foreach (string directory in directories) - { - WebTemplate template = Load(directory); - if (template != null) - { - templates.Add(template); - } - } - return templates; - } - - public void SelectionUI(SerializedProperty templateProp) - { - if (s_Styles == null) - s_Styles = new Styles(); - - if (TemplateGUIThumbnails.Length < 1) - { - GUILayout.Label(EditorGUIUtility.TrTextContent("No templates found.")); - } - else - { - int numCols = Mathf.Min((int)Mathf.Max((Screen.width - kWebTemplateGridPadding * 2.0f) / kThumbnailSize, 1.0f), TemplateGUIThumbnails.Length); - int numRows = Mathf.Max((int)Mathf.Ceil((float)TemplateGUIThumbnails.Length / (float)numCols), 1); - - - bool wasChanged = GUI.changed; - - templateProp.stringValue = Templates[ - ThumbnailList( - GUILayoutUtility.GetRect(numCols * kThumbnailSize, numRows * (kThumbnailSize + kThumbnailLabelHeight), GUILayout.ExpandWidth(false)), - GetTemplateIndex(templateProp.stringValue), - TemplateGUIThumbnails, - numCols - )].ToString(); - - bool templateChanged = !wasChanged && GUI.changed; - - bool orgChanged = GUI.changed; - GUI.changed = false; - foreach (string key in PlayerSettings.templateCustomKeys) - { - string value = PlayerSettings.GetTemplateCustomValue(key); - value = EditorGUILayout.TextField(PrettyTemplateKeyName(key), value); - PlayerSettings.SetTemplateCustomValue(key, value); - } - if (GUI.changed) - templateProp.serializedObject.Update(); - GUI.changed |= orgChanged; - - if (templateChanged) - { - GUIUtility.hotControl = 0; - GUIUtility.keyboardControl = 0; - templateProp.serializedObject.ApplyModifiedProperties(); - PlayerSettings.templateCustomKeys = Templates[GetTemplateIndex(templateProp.stringValue)].CustomKeys; - templateProp.serializedObject.Update(); - } - } - } - - static int ThumbnailList(Rect rect, int selection, GUIContent[] thumbnails, int maxRowItems) - { - for (int y = 0, i = 0; i < thumbnails.Length; y++) - { - for (int x = 0; x < maxRowItems && i < thumbnails.Length; x++, i++) - { - if (ThumbnailListItem( - new Rect(rect.x + x * kThumbnailSize, rect.y + y * (kThumbnailSize + kThumbnailLabelHeight), kThumbnailSize, (kThumbnailSize + kThumbnailLabelHeight)), - i == selection, thumbnails[i])) - { - selection = i; - } - } - } - return selection; - } - - static bool ThumbnailListItem(Rect rect, bool selected, GUIContent content) - { - switch (Event.current.type) - { - case EventType.MouseDown: - if (rect.Contains(Event.current.mousePosition)) - { - if (!selected) - { - GUI.changed = true; - } - selected = true; - Event.current.Use(); - } - break; - case EventType.Repaint: - Rect thumbRect = new Rect(rect.x + kThumbnailPadding, rect.y + kThumbnailPadding, rect.width - kThumbnailPadding * 2.0f, rect.height - kThumbnailLabelHeight - kThumbnailPadding * 2.0f); - s_Styles.thumbnail.Draw(thumbRect, content.image, false, false, selected, selected); - s_Styles.thumbnailLabel.Draw(new Rect(rect.x, rect.y + rect.height - kThumbnailLabelHeight, rect.width, kThumbnailLabelHeight), content.text, false, false, selected, selected); - break; - } - return selected; - } - - static string PrettyTemplateKeyName(string name) - { - string[] elements = name.Split('_'); - - elements[0] = UppercaseFirst(elements[0].ToLower()); - for (int i = 1; i < elements.Length; i++) - { - elements[i] = elements[i].ToLower(); - } - - return string.Join(" ", elements); - } - - static string UppercaseFirst(string target) - { - if (string.IsNullOrEmpty(target)) - { - return string.Empty; - } - return char.ToUpper(target[0]) + target.Substring(1); - } - } -} diff --git a/Editor/Mono/Inspector/PointEffector2DEditor.cs b/Editor/Mono/Inspector/PointEffector2DEditor.cs deleted file mode 100644 index 6c875b2b7a..0000000000 --- a/Editor/Mono/Inspector/PointEffector2DEditor.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - /// - /// Prompts the end-user to add 2D colliders if non exist for 2D effector to work with. - /// - [CustomEditor(typeof(PointEffector2D), true)] - [CanEditMultipleObjects] - internal class PointEffector2DEditor : Effector2DEditor - { - readonly AnimBool m_ShowForceRollout = new AnimBool(); - SerializedProperty m_ForceMagnitude; - SerializedProperty m_ForceVariation; - SerializedProperty m_ForceSource; - SerializedProperty m_ForceTarget; - SerializedProperty m_ForceMode; - SerializedProperty m_DistanceScale; - - static readonly AnimBool m_ShowDampingRollout = new AnimBool(); - SerializedProperty m_Drag; - SerializedProperty m_AngularDrag; - - public override void OnEnable() - { - base.OnEnable(); - - m_ShowForceRollout.value = true; - m_ShowForceRollout.valueChanged.AddListener(Repaint); - m_ForceMagnitude = serializedObject.FindProperty("m_ForceMagnitude"); - m_ForceVariation = serializedObject.FindProperty("m_ForceVariation"); - m_ForceSource = serializedObject.FindProperty("m_ForceSource"); - m_ForceTarget = serializedObject.FindProperty("m_ForceTarget"); - m_ForceMode = serializedObject.FindProperty("m_ForceMode"); - m_DistanceScale = serializedObject.FindProperty("m_DistanceScale"); - - m_ShowDampingRollout.valueChanged.AddListener(Repaint); - m_Drag = serializedObject.FindProperty("m_Drag"); - m_AngularDrag = serializedObject.FindProperty("m_AngularDrag"); - } - - public override void OnDisable() - { - base.OnDisable(); - - m_ShowForceRollout.valueChanged.RemoveListener(Repaint); - m_ShowDampingRollout.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - - serializedObject.Update(); - - // Force. - m_ShowForceRollout.target = EditorGUILayout.Foldout(m_ShowForceRollout.target, "Force", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowForceRollout.faded)) - { - EditorGUILayout.PropertyField(m_ForceMagnitude); - EditorGUILayout.PropertyField(m_ForceVariation); - EditorGUILayout.PropertyField(m_DistanceScale); - EditorGUILayout.PropertyField(m_ForceSource); - EditorGUILayout.PropertyField(m_ForceTarget); - EditorGUILayout.PropertyField(m_ForceMode); - EditorGUILayout.Space(); - } - EditorGUILayout.EndFadeGroup(); - - // Drag. - m_ShowDampingRollout.target = EditorGUILayout.Foldout(m_ShowDampingRollout.target, "Damping", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowDampingRollout.faded)) - { - EditorGUILayout.PropertyField(m_Drag); - EditorGUILayout.PropertyField(m_AngularDrag); - } - EditorGUILayout.EndFadeGroup(); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/PolygonCollider2DEditor.cs b/Editor/Mono/Inspector/PolygonCollider2DEditor.cs deleted file mode 100644 index 66c0156e20..0000000000 --- a/Editor/Mono/Inspector/PolygonCollider2DEditor.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.Linq; -using UnityEditorInternal; - -namespace UnityEditor -{ - [CustomEditor(typeof(PolygonCollider2D))] - [CanEditMultipleObjects] - internal class PolygonCollider2DEditor : Collider2DEditorBase - { - private readonly PolygonEditorUtility m_PolyUtility = new PolygonEditorUtility(); - - private SerializedProperty m_Points; - - public override void OnEnable() - { - base.OnEnable(); - - m_Points = serializedObject.FindProperty("m_Points"); - m_AutoTiling = serializedObject.FindProperty("m_AutoTiling"); - m_Points.isExpanded = false; - } - - public override void OnInspectorGUI() - { - // Start a vertical group which we'll use to note the layout rect as a drag-drop target. - EditorGUILayout.BeginVertical(); - bool disableEditCollider = !CanEditCollider(); - if (disableEditCollider) - { - EditorGUILayout.HelpBox(Styles.s_ColliderEditDisableHelp.text, MessageType.Info); - if (editingCollider) - EditMode.QuitEditMode(); - } - else - BeginColliderInspector(); - - // Grab this as the offset to the top of the drag target. - base.OnInspectorGUI(); - - if (targets.Length == 1) - { - EditorGUI.BeginDisabledGroup(editingCollider); - EditorGUILayout.PropertyField(m_Points, true); - EditorGUI.EndDisabledGroup(); - } - - EndColliderInspector(); - - FinalizeInspectorGUI(); - - // End the vertical layout and use the layout rect as the drag-drop target. - EditorGUILayout.EndVertical(); - HandleDragAndDrop(GUILayoutUtility.GetLastRect()); - } - - // Copy collider from sprite if it is drag&dropped to the inspector - private void HandleDragAndDrop(Rect targetRect) - { - if (Event.current.type != EventType.DragPerform && Event.current.type != EventType.DragUpdated) - return; - - // Check we're dropping onto the polygon collider editor. - if (!targetRect.Contains(Event.current.mousePosition)) - return; - - foreach (var obj in DragAndDrop.objectReferences.Where(obj => obj is Sprite || obj is Texture2D)) - { - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - - if (Event.current.type == EventType.DragPerform) - { - var sprite = obj is Sprite ? obj as Sprite : SpriteUtility.TextureToSprite(obj as Texture2D); - - // Copy collider to all selected components - foreach (var collider in targets.Select(target => target as PolygonCollider2D)) - { - Vector2[][] paths; - UnityEditor.Sprites.SpriteUtility.GenerateOutlineFromSprite(sprite, 0.25f, 200, true, out paths); - collider.pathCount = paths.Length; - for (int i = 0; i < paths.Length; ++i) - collider.SetPath(i, paths[i]); - - // Stop editing - m_PolyUtility.StopEditing(); - - DragAndDrop.AcceptDrag(); - } - } - - return; - } - - DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; - } - - protected override void OnEditStart() - { - // We don't support multiselection editing - if (target == null) - return; - - m_PolyUtility.StartEditing(target as Collider2D); - } - - protected override void OnEditEnd() - { - m_PolyUtility.StopEditing(); - } - - public void OnSceneGUI() - { - if (!editingCollider) - return; - - m_PolyUtility.OnSceneGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/PolygonEditorUtility.cs b/Editor/Mono/Inspector/PolygonEditorUtility.cs deleted file mode 100644 index 32ce892069..0000000000 --- a/Editor/Mono/Inspector/PolygonEditorUtility.cs +++ /dev/null @@ -1,364 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - -namespace UnityEditor -{ - internal class PolygonEditorUtility - { - const float k_HandlePointSnap = 10f; - const float k_HandlePickDistance = 50f; - - private Collider2D m_ActiveCollider; - private bool m_LoopingCollider = false; - private int m_MinPathPoints = 3; - - private int m_SelectedPath = -1; - private int m_SelectedVertex = -1; - private int m_SelectedEdgePath = -1; - private int m_SelectedEdgeVertex0 = -1; - private int m_SelectedEdgeVertex1 = -1; - private bool m_LeftIntersect = false; - private bool m_RightIntersect = false; - private bool m_DeleteMode = false; - - private bool m_FirstOnSceneGUIAfterReset; - - private bool m_HandlePoint = false; - private bool m_HandleEdge = false; - - public void Reset() - { - m_SelectedPath = -1; - m_SelectedVertex = -1; - m_SelectedEdgePath = -1; - m_SelectedEdgeVertex0 = -1; - m_SelectedEdgeVertex1 = -1; - m_LeftIntersect = false; - m_RightIntersect = false; - m_FirstOnSceneGUIAfterReset = true; - m_HandlePoint = false; - m_HandleEdge = false; - } - - private void UndoRedoPerformed() - { - if (m_ActiveCollider != null) - { - Collider2D collider = m_ActiveCollider; - StopEditing(); - StartEditing(collider); - } - } - - public void StartEditing(Collider2D collider) - { - Undo.undoRedoPerformed += UndoRedoPerformed; - - Reset(); - - PolygonCollider2D polygon = collider as PolygonCollider2D; - if (polygon) - { - m_ActiveCollider = collider; - m_LoopingCollider = true; - m_MinPathPoints = 3; - PolygonEditor.StartEditing(polygon); - return; - } - - EdgeCollider2D edge = collider as EdgeCollider2D; - if (edge) - { - m_ActiveCollider = collider; - m_LoopingCollider = false; - m_MinPathPoints = 2; - PolygonEditor.StartEditing(edge); - return; - } - - throw new NotImplementedException(string.Format("PolygonEditorUtility does not support {0}", collider)); - } - - public void StopEditing() - { - PolygonEditor.StopEditing(); - m_ActiveCollider = null; - - Undo.undoRedoPerformed -= UndoRedoPerformed; - } - - public void OnSceneGUI() - { - if (m_ActiveCollider == null) - return; - - // Skip editing of polygon if view tool is active i.e. while panning the scene view - if (Tools.viewToolActive) - return; - - // Fetch the collider offset. - var colliderOffset = m_ActiveCollider.offset; - - Event evt = Event.current; - m_DeleteMode = evt.command || evt.control; - Transform transform = m_ActiveCollider.transform; - - // Handles.Slider2D will render active point as yellow if there is keyboardControl set. We don't want that happening. - GUIUtility.keyboardControl = 0; - - HandleUtility.s_CustomPickDistance = k_HandlePickDistance; - - // Find mouse positions in local and world space - Plane plane = new Plane(-transform.forward, Vector3.zero); - Ray mouseRay = HandleUtility.GUIPointToWorldRay(evt.mousePosition); - float dist; - plane.Raycast(mouseRay, out dist); - - Vector3 mouseWorldPos = mouseRay.GetPoint(dist); - Vector2 mouseLocalPos = transform.InverseTransformPoint(mouseWorldPos); - - // Select the active vertex and edge - if (evt.type == EventType.MouseMove || m_FirstOnSceneGUIAfterReset) - { - int pathIndex; - int pointIndex0, pointIndex1; - float distance; - if (PolygonEditor.GetNearestPoint(mouseLocalPos - colliderOffset, out pathIndex, out pointIndex0, out distance)) - { - m_SelectedPath = pathIndex; - m_SelectedVertex = pointIndex0; - } - else - { - m_SelectedPath = -1; - } - - if (PolygonEditor.GetNearestEdge(mouseLocalPos - colliderOffset, out pathIndex, out pointIndex0, out pointIndex1, out distance, m_LoopingCollider)) - { - m_SelectedEdgePath = pathIndex; - m_SelectedEdgeVertex0 = pointIndex0; - m_SelectedEdgeVertex1 = pointIndex1; - } - else - { - m_SelectedEdgePath = -1; - } - - if (evt.type == EventType.MouseMove) - evt.Use(); - } - else if (evt.type == EventType.MouseUp) - { - m_LeftIntersect = false; - m_RightIntersect = false; - } - - // Do we handle point or line? - // TODO: there probably isn't a case when selectedPath is valid and selectedEdge is invalid. This needs a refactor. - - - if (GUIUtility.hotControl == 0) - { - if (m_SelectedPath != -1 && m_SelectedEdgePath != -1) - { - // Calculate snapping distance - Vector2 point; - PolygonEditor.GetPoint(m_SelectedPath, m_SelectedVertex, out point); - point += colliderOffset; - Vector3 worldPos = transform.TransformPoint(point); - m_HandleEdge = (HandleUtility.WorldToGUIPoint(worldPos) - Event.current.mousePosition).sqrMagnitude > k_HandlePointSnap * k_HandlePointSnap; - m_HandlePoint = !m_HandleEdge; - } - else if (m_SelectedPath != -1) - m_HandlePoint = true; - else if (m_SelectedEdgePath != -1) - m_HandleEdge = true; - - if (m_DeleteMode && m_HandleEdge) - { - m_HandleEdge = false; - m_HandlePoint = true; - } - } - - bool applyToCollider = false; - - // Edge handle - if (m_HandleEdge && !m_DeleteMode) - { - Vector2 p0, p1; - PolygonEditor.GetPoint(m_SelectedEdgePath, m_SelectedEdgeVertex0, out p0); - PolygonEditor.GetPoint(m_SelectedEdgePath, m_SelectedEdgeVertex1, out p1); - p0 += colliderOffset; - p1 += colliderOffset; - Vector3 worldPosV0 = transform.TransformPoint(p0); - Vector3 worldPosV1 = transform.TransformPoint(p1); - worldPosV0.z = worldPosV1.z = 0; - - Handles.color = Color.green; - Handles.DrawAAPolyLine(4.0f, new Vector3[] { worldPosV0, worldPosV1 }); - Handles.color = Color.white; - - Vector2 newPoint = GetNearestPointOnEdge(transform.TransformPoint(mouseLocalPos), worldPosV0, worldPosV1); - - EditorGUI.BeginChangeCheck(); - float guiSize = HandleUtility.GetHandleSize(newPoint) * 0.04f; - Handles.color = Color.green; - - newPoint = Handles.Slider2D( - newPoint, - new Vector3(0, 0, 1), - new Vector3(1, 0, 0), - new Vector3(0, 1, 0), - guiSize, - Handles.DotHandleCap, - Vector3.zero); - Handles.color = Color.white; - if (EditorGUI.EndChangeCheck()) - { - PolygonEditor.InsertPoint(m_SelectedEdgePath, m_SelectedEdgeVertex1, ((p0 + p1) / 2) - colliderOffset); - m_SelectedPath = m_SelectedEdgePath; - m_SelectedVertex = m_SelectedEdgeVertex1; - m_HandleEdge = false; - m_HandlePoint = true; - applyToCollider = true; - } - } - - // Point handle - if (m_HandlePoint) - { - Vector2 point; - PolygonEditor.GetPoint(m_SelectedPath, m_SelectedVertex, out point); - point += colliderOffset; - Vector3 worldPos = transform.TransformPoint(point); - worldPos.z = 0; - Vector2 screenPos = HandleUtility.WorldToGUIPoint(worldPos); - - float guiSize = HandleUtility.GetHandleSize(worldPos) * 0.04f; - - if (m_DeleteMode && evt.type == EventType.MouseDown && - Vector2.Distance(screenPos, Event.current.mousePosition) < k_HandlePickDistance || - DeleteCommandEvent(evt)) - { - if (evt.type != EventType.ValidateCommand) - { - int pathPointCount = PolygonEditor.GetPointCount(m_SelectedPath); - if (pathPointCount > m_MinPathPoints) - { - PolygonEditor.RemovePoint(m_SelectedPath, m_SelectedVertex); - Reset(); - applyToCollider = true; - } - } - evt.Use(); - } - - EditorGUI.BeginChangeCheck(); - Handles.color = m_DeleteMode ? Color.red : Color.green; - Vector3 newWorldPos = Handles.Slider2D( - worldPos, - new Vector3(0, 0, 1), - new Vector3(1, 0, 0), - new Vector3(0, 1, 0), - guiSize, - Handles.DotHandleCap, - Vector3.zero); - Handles.color = Color.white; - if (EditorGUI.EndChangeCheck() && !m_DeleteMode) - { - point = transform.InverseTransformPoint(newWorldPos); - point -= colliderOffset; - PolygonEditor.TestPointMove(m_SelectedPath, m_SelectedVertex, point, out m_LeftIntersect, out m_RightIntersect, m_LoopingCollider); - PolygonEditor.SetPoint(m_SelectedPath, m_SelectedVertex, point); - applyToCollider = true; - } - - if (!applyToCollider) - DrawEdgesForSelectedPoint(newWorldPos, transform, m_LeftIntersect, m_RightIntersect, m_LoopingCollider); - } - - // Apply changes - if (applyToCollider) - { - Undo.RecordObject(m_ActiveCollider, "Edit Collider"); - PolygonEditor.ApplyEditing(m_ActiveCollider); - } - - if (DeleteCommandEvent(evt)) - Event.current.Use(); // If we don't use the delete event in all cases, it sceneview might delete the entire object - - m_FirstOnSceneGUIAfterReset = false; - } - - private bool DeleteCommandEvent(Event evt) - { - return (evt.type == EventType.ExecuteCommand || evt.type == EventType.ValidateCommand) && (evt.commandName == EventCommandNames.Delete || evt.commandName == EventCommandNames.SoftDelete); - } - - private void DrawEdgesForSelectedPoint(Vector3 worldPos, Transform transform, bool leftIntersect, bool rightIntersect, bool loop) - { - bool drawLeft = true; - bool drawRight = true; - - int pathPointCount = UnityEditor.PolygonEditor.GetPointCount(m_SelectedPath); - int v0 = m_SelectedVertex - 1; - if (v0 == -1) - { - v0 = pathPointCount - 1; - drawLeft = loop; - } - int v1 = m_SelectedVertex + 1; - if (v1 == pathPointCount) - { - v1 = 0; - drawRight = loop; - } - - // Fetch the collider offset. - var colliderOffset = m_ActiveCollider.offset; - - Vector2 p0, p1; - UnityEditor.PolygonEditor.GetPoint(m_SelectedPath, v0, out p0); - UnityEditor.PolygonEditor.GetPoint(m_SelectedPath, v1, out p1); - p0 += colliderOffset; - p1 += colliderOffset; - Vector3 worldPosV0 = transform.TransformPoint(p0); - Vector3 worldPosV1 = transform.TransformPoint(p1); - worldPosV0.z = worldPosV1.z = worldPos.z; - - float lineWidth = 4.0f; - if (drawLeft) - { - Handles.color = leftIntersect || m_DeleteMode ? Color.red : Color.green; - Handles.DrawAAPolyLine(lineWidth, new Vector3[] { worldPos, worldPosV0 }); - } - if (drawRight) - { - Handles.color = rightIntersect || m_DeleteMode ? Color.red : Color.green; - Handles.DrawAAPolyLine(lineWidth, new Vector3[] { worldPos, worldPosV1 }); - } - Handles.color = Color.white; - } - - Vector2 GetNearestPointOnEdge(Vector2 point, Vector2 start, Vector2 end) - { - Vector2 startToPoint = point - start; - Vector2 startToEnd = (end - start).normalized; - float dot = Vector2.Dot(startToEnd, startToPoint); - - if (dot <= 0) - return start; - - if (dot >= Vector2.Distance(start, end)) - return end; - - Vector2 offsetToPoint = startToEnd * dot; - return start + offsetToPoint; - } - } -} diff --git a/Editor/Mono/Inspector/PositionConstraintEditor.cs b/Editor/Mono/Inspector/PositionConstraintEditor.cs deleted file mode 100644 index 4d76744b2c..0000000000 --- a/Editor/Mono/Inspector/PositionConstraintEditor.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Animations; - -namespace UnityEditor -{ - [CustomEditor(typeof(PositionConstraint))] - [CanEditMultipleObjects] - internal class PositionConstraintEditor : ConstraintEditorBase - { - private SerializedProperty m_TranslationAtRest; - private SerializedProperty m_TranslationOffset; - private SerializedProperty m_Weight; - private SerializedProperty m_IsContraintActive; - private SerializedProperty m_IsLocked; - private SerializedProperty m_Sources; - - internal override SerializedProperty atRest { get { return m_TranslationAtRest; } } - internal override SerializedProperty offset { get { return m_TranslationOffset; } } - internal override SerializedProperty weight { get { return m_Weight; } } - internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } } - internal override SerializedProperty isLocked { get { return m_IsLocked; } } - internal override SerializedProperty sources { get { return m_Sources; } } - - private class Styles : ConstraintStyleBase - { - GUIContent m_RestTranslation = EditorGUIUtility.TrTextContent("Position At Rest"); - GUIContent m_TranslationOffset = EditorGUIUtility.TrTextContent("Position Offset"); - - GUIContent m_TranslationAxes = EditorGUIUtility.TrTextContent("Freeze Position Axes"); - - public override GUIContent AtRest { get { return m_RestTranslation; } } - public override GUIContent Offset { get { return m_TranslationOffset; } } - public GUIContent FreezeAxes { get { return m_TranslationAxes; } } - } - - private static Styles s_Style; - - public void OnEnable() - { - if (s_Style == null) - s_Style = new Styles(); - - m_TranslationAtRest = serializedObject.FindProperty("m_TranslationAtRest"); - m_TranslationOffset = serializedObject.FindProperty("m_TranslationOffset"); - m_Weight = serializedObject.FindProperty("m_Weight"); - m_IsContraintActive = serializedObject.FindProperty("m_IsContraintActive"); - m_IsLocked = serializedObject.FindProperty("m_IsLocked"); - m_Sources = serializedObject.FindProperty("m_Sources"); - - OnEnable(s_Style); - } - - internal override void OnValueAtRestChanged() - { - foreach (var t in targets) - (t as PositionConstraint).transform.localPosition = atRest.vector3Value; - } - - internal override void ShowFreezeAxesControl() - { - Rect drawRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeAxes), EditorStyles.toggle); - EditorGUI.MultiPropertyField(drawRect, s_Style.Axes, serializedObject.FindProperty("m_AffectTranslationX"), s_Style.FreezeAxes); - } - - public override void OnInspectorGUI() - { - if (s_Style == null) - s_Style = new Styles(); - - serializedObject.Update(); - - ShowConstraintEditor(s_Style); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/PrefabInspector.cs b/Editor/Mono/Inspector/PrefabInspector.cs deleted file mode 100644 index 1e5d718cd4..0000000000 --- a/Editor/Mono/Inspector/PrefabInspector.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; - -namespace UnityEditor -{ - internal class PrefabInspector - { - public static void OnOverridenPrefabsInspector(GameObject gameObject) - { - GUI.enabled = true; - - var prefab = PrefabUtility.GetPrefabObject(gameObject); - if (prefab == null) - return; - - EditorGUIUtility.labelWidth = 200; - - if (PrefabUtility.GetPrefabType(gameObject) == PrefabType.PrefabInstance) - { - PropertyModification[] modifications = PrefabUtility.GetPropertyModifications(gameObject); - if (modifications != null && modifications.Length != 0) - { - GUI.changed = false; - for (int i = 0; i < modifications.Length; i++) - { - modifications[i].value = EditorGUILayout.TextField(modifications[i].propertyPath, modifications[i].value); - } - - if (GUI.changed) - { - PrefabUtility.SetPropertyModifications(gameObject, modifications); - } - } - } - - AddComponentGUI(prefab); - } - - static void AddComponentGUI(Object prefab) - { - var serialized = new SerializedObject(prefab); - - var i = serialized.FindProperty("m_Modification"); - var end = i.GetEndProperty(); - while (true) - { - var expanded = EditorGUILayout.PropertyField(i); - - if (!i.NextVisible(expanded)) - break; - if (SerializedProperty.EqualContents(i, end)) - break; - } - - serialized.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/PreviewRenderUtility.cs b/Editor/Mono/Inspector/PreviewRenderUtility.cs deleted file mode 100644 index 6514d9fd6f..0000000000 --- a/Editor/Mono/Inspector/PreviewRenderUtility.cs +++ /dev/null @@ -1,485 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.SceneManagement; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEngine.SceneManagement; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class PreviewScene : IDisposable - { - private readonly Scene m_Scene; - private readonly List m_GameObjects = new List(); - private readonly Camera m_Camera; - - public PreviewScene(string sceneName) - { - m_Scene = EditorSceneManager.NewPreviewScene(); - m_Scene.name = sceneName; - - var camGO = EditorUtility.CreateGameObjectWithHideFlags("Preview Scene Camera", HideFlags.HideAndDontSave, typeof(Camera)); - AddGameObject(camGO); - m_Camera = camGO.GetComponent(); - camera.cameraType = CameraType.Preview; - camera.enabled = false; - camera.clearFlags = CameraClearFlags.Depth; - camera.fieldOfView = 15; - camera.farClipPlane = 10.0f; - camera.nearClipPlane = 2.0f; - - // Explicitly use forward rendering for all previews - // (deferred fails when generating some static previews at editor launch; and we never want - // vertex lit previews if that is chosen in the player settings) - camera.renderingPath = RenderingPath.Forward; - camera.useOcclusionCulling = false; - camera.scene = m_Scene; - } - - public Camera camera - { - get { return m_Camera; } - } - - public Scene scene - { - get { return m_Scene; } - } - - public void AddGameObject(GameObject go) - { - if (m_GameObjects.Contains(go)) - return; - - SceneManager.MoveGameObjectToScene(go, m_Scene); - m_GameObjects.Add(go); - } - - public void AddManagedGO(GameObject go) - { - SceneManager.MoveGameObjectToScene(go, m_Scene); - } - - public void Dispose() - { - EditorSceneManager.ClosePreviewScene(m_Scene); - - foreach (var go in m_GameObjects) - Object.DestroyImmediate(go); - - m_GameObjects.Clear(); - } - } - - public class PreviewRenderUtility - { - private readonly PreviewScene m_PreviewScene; - - private RenderTexture m_RenderTexture; - private Rect m_TargetRect; - private SavedRenderTargetState m_SavedState; - private bool m_PixelPerfect; - private Material m_InvisibleMaterial; - - public PreviewRenderUtility(bool renderFullScene) : this() - {} - - public PreviewRenderUtility(bool renderFullScene, bool pixelPerfect) : this() - { - m_PixelPerfect = pixelPerfect; - } - - public PreviewRenderUtility() - { - m_PreviewScene = new PreviewScene("Preview Scene"); - - var l0 = CreateLight(); - previewScene.AddGameObject(l0); - Light0 = l0.GetComponent(); - - var l1 = CreateLight(); - previewScene.AddGameObject(l1); - Light1 = l1.GetComponent(); - - Light0.color = SceneView.kSceneViewFrontLight; - Light1.transform.rotation = Quaternion.Euler(340, 218, 177); - Light1.color = new Color(.4f, .4f, .45f, 0f) * .7f; - - m_PixelPerfect = false; - } - - internal static void SetEnabledRecursive(GameObject go, bool enabled) - { - foreach (Renderer renderer in go.GetComponentsInChildren()) - renderer.enabled = enabled; - } - - [Obsolete("Use the property camera instead (UnityUpgradable) -> camera", false)] - public Camera m_Camera; - - public Camera camera - { - get { return previewScene.camera; } - } - - [Obsolete("Use the property cameraFieldOfView (UnityUpgradable) -> cameraFieldOfView", false)] - public float m_CameraFieldOfView; - - public float cameraFieldOfView - { - get { return camera.fieldOfView; } - set { camera.fieldOfView = value; } - } - - public Color ambientColor { get; set; } - - [Obsolete("Use the property lights (UnityUpgradable) -> lights", false)] - public Light[] m_Light; - - public Light[] lights - { - get - { - return new[] {Light0, Light1}; - } - } - - private Light Light0 { get; set; } - - private Light Light1 { get; set; } - - internal RenderTexture renderTexture - { - get { return m_RenderTexture; } - } - - internal PreviewScene previewScene - { - get { return m_PreviewScene; } - } - - public void Cleanup() - { - if (m_RenderTexture) - { - Object.DestroyImmediate(m_RenderTexture); - m_RenderTexture = null; - } - - if (m_InvisibleMaterial != null) - { - Object.DestroyImmediate(m_InvisibleMaterial); - m_InvisibleMaterial = null; - } - - previewScene.Dispose(); - } - - public void BeginPreview(Rect r, GUIStyle previewBackground) - { - InitPreview(r); - - if (previewBackground == null || previewBackground == GUIStyle.none) - return; - - Graphics.DrawTexture( - previewBackground.overflow.Add(new Rect(0, 0, m_RenderTexture.width, m_RenderTexture.height)), - previewBackground.normal.background, - new Rect(0, 0, 1, 1), - previewBackground.border.left, previewBackground.border.right, previewBackground.border.top, - previewBackground.border.bottom, - new Color(.5f, .5f, .5f, 1), - null - ); - - - if (Unsupported.SetOverrideRenderSettings(previewScene.scene)) - { - RenderSettings.ambientMode = AmbientMode.Flat; - RenderSettings.ambientLight = ambientColor; - } - } - - public void BeginStaticPreview(Rect r) - { - InitPreview(r); - var color = new Color(82 / 255f, 82 / 255f, 82 / 255f, 1.0f); - var darkGreyBackground = new Texture2D(1, 1, TextureFormat.RGBA32, true); - darkGreyBackground.SetPixel(0, 0, color); - darkGreyBackground.Apply(); - Graphics.DrawTexture(new Rect(0, 0, m_RenderTexture.width, m_RenderTexture.height), darkGreyBackground); - Object.DestroyImmediate(darkGreyBackground); - } - - private void InitPreview(Rect r) - { - camera.backgroundColor = new Color(49.0f / 255.0f, 49.0f / 255.0f, 49.0f / 255.0f, 1.0f); - if (QualitySettings.activeColorSpace == ColorSpace.Linear) - camera.backgroundColor = camera.backgroundColor.linear; - - m_TargetRect = r; - float scaleFac = GetScaleFactor(r.width, r.height); - - int rtWidth = (int)(r.width * scaleFac); - int rtHeight = (int)(r.height * scaleFac); - if (!m_RenderTexture || m_RenderTexture.width != rtWidth || m_RenderTexture.height != rtHeight) - { - if (m_RenderTexture) - { - Object.DestroyImmediate(m_RenderTexture); - m_RenderTexture = null; - } - - // Do not use GetTemporary to manage render textures. Temporary RTs are only - // garbage collected each N frames, and in the editor we might be wildly resizing - // the inspector, thus using up tons of memory. - RenderTextureFormat format = camera.allowHDR ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32; - m_RenderTexture = new RenderTexture(rtWidth, rtHeight, 16, format, RenderTextureReadWrite.Linear); - m_RenderTexture.hideFlags = HideFlags.HideAndDontSave; - - camera.targetTexture = m_RenderTexture; - - foreach (var light in lights) - light.enabled = true; - } - - m_SavedState = new SavedRenderTargetState(); - EditorGUIUtility.SetRenderTextureNoViewport(m_RenderTexture); - GL.LoadOrtho(); - GL.LoadPixelMatrix(0, m_RenderTexture.width, m_RenderTexture.height, 0); - ShaderUtil.rawViewportRect = new Rect(0, 0, m_RenderTexture.width, m_RenderTexture.height); - ShaderUtil.rawScissorRect = new Rect(0, 0, m_RenderTexture.width, m_RenderTexture.height); - GL.Clear(true, true, camera.backgroundColor); - - foreach (var light in lights) - light.enabled = true; - - var oldProbe = RenderSettings.ambientProbe; - Unsupported.SetOverrideRenderSettings(previewScene.scene); - // Most preview windows just want the light probe from the main scene so by default we copy it here. It can then be overridden if user wants. - RenderSettings.ambientProbe = oldProbe; - } - - public float GetScaleFactor(float width, float height) - { - float scaleFacX = Mathf.Max(Mathf.Min(width * 2, 1024), width) / width; - float scaleFacY = Mathf.Max(Mathf.Min(height * 2, 1024), height) / height; - float result = Mathf.Min(scaleFacX, scaleFacY) * EditorGUIUtility.pixelsPerPoint; - if (m_PixelPerfect) - result = Mathf.Max(Mathf.Round(result), 1f); - return result; - } - - [Obsolete("This method has been marked obsolete, use BeginStaticPreview() instead (UnityUpgradable) -> BeginStaticPreview(*)", false)] - public void BeginStaticPreviewHDR(Rect r) - { - BeginStaticPreview(r); - } - - [Obsolete("This method has been marked obsolete, use BeginPreview() instead (UnityUpgradable) -> BeginPreview(*)", false)] - public void BeginPreviewHDR(Rect r, GUIStyle previewBackground) - { - BeginPreview(r, previewBackground); - } - - public Texture EndPreview() - { - Unsupported.RestoreOverrideRenderSettings(); - - m_SavedState.Restore(); - FinishFrame(); - return m_RenderTexture; - } - - private void FinishFrame() - { - Unsupported.RestoreOverrideRenderSettings(); - foreach (var light in lights) - light.enabled = false; - } - - public void EndAndDrawPreview(Rect r) - { - Texture t = EndPreview(); - GUI.DrawTexture(r, t, ScaleMode.StretchToFill, false); - } - - public Texture2D EndStaticPreview() - { - Unsupported.RestoreOverrideRenderSettings(); - - var tmp = RenderTexture.GetTemporary((int)m_TargetRect.width, (int)m_TargetRect.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); - - Graphics.Blit(m_RenderTexture, tmp, EditorGUIUtility.GUITextureBlit2SRGBMaterial); - - RenderTexture.active = tmp; - var copy = new Texture2D((int)m_TargetRect.width, (int)m_TargetRect.height, TextureFormat.RGB24, false, false); - copy.ReadPixels(new Rect(0, 0, m_TargetRect.width, m_TargetRect.height), 0, 0); - copy.Apply(); - RenderTexture.ReleaseTemporary(tmp); - m_SavedState.Restore(); - FinishFrame(); - return copy; - } - - [Obsolete("AddSingleGO(GameObject go, bool instantiateAtZero) has been deprecated, use AddSingleGo(GameObject go) instead. instantiateAtZero has no effect and is not supported.")] - public void AddSingleGO(GameObject go, bool instantiateAtZero) - { - AddSingleGO(go); - } - - public void AddSingleGO(GameObject go) - { - previewScene.AddGameObject(go); - } - - public GameObject InstantiatePrefabInScene(GameObject prefab) - { - var instance = (GameObject)PrefabUtility.InstantiatePrefab(prefab, m_PreviewScene.scene); - return instance; - } - - private Material GetInvisibleMaterial() - { - if (m_InvisibleMaterial == null) - { - // A material intentionally draws nothing. Used to hide submeshes we don't want users to see. - m_InvisibleMaterial = new Material(Shader.FindBuiltin("Internal-Colored.shader")); - m_InvisibleMaterial.hideFlags = HideFlags.HideAndDontSave; - m_InvisibleMaterial.SetColor("_Color", Color.clear); - m_InvisibleMaterial.SetInt("_ZWrite", 0); - } - - return m_InvisibleMaterial; - } - - internal void AddManagedGO(GameObject go) - { - m_PreviewScene.AddManagedGO(go); - } - - public void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material mat, int subMeshIndex) - { - DrawMesh(mesh, matrix, mat, subMeshIndex, null, null, false); - } - - public void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties) - { - DrawMesh(mesh, matrix, mat, subMeshIndex, customProperties, null, false); - } - - public void DrawMesh(Mesh mesh, Matrix4x4 m, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties, Transform probeAnchor, bool useLightProbe) - { - var quat = Quaternion.LookRotation(m.GetColumn(2), m.GetColumn(1)); - var pos = m.GetColumn(3); - var scale = new Vector3( - m.GetColumn(0).magnitude, - m.GetColumn(1).magnitude, - m.GetColumn(2).magnitude - ); - - DrawMesh(mesh, pos, scale, quat, mat, subMeshIndex, customProperties, probeAnchor, useLightProbe); - } - - public void DrawMesh(Mesh mesh, Vector3 pos, Quaternion rot, Material mat, int subMeshIndex) - { - DrawMesh(mesh, pos, rot, mat, subMeshIndex, null, null, false); - } - - public void DrawMesh(Mesh mesh, Vector3 pos, Quaternion rot, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties) - { - DrawMesh(mesh, pos, rot, mat, subMeshIndex, customProperties, null, false); - } - - public void DrawMesh(Mesh mesh, Vector3 pos, Quaternion rot, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties, Transform probeAnchor) - { - DrawMesh(mesh, pos, rot, mat, subMeshIndex, customProperties, probeAnchor, false); - } - - public void DrawMesh(Mesh mesh, Vector3 pos, Quaternion rot, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties, Transform probeAnchor, bool useLightProbe) - { - DrawMesh(mesh, pos, Vector3.one, rot, mat, subMeshIndex, customProperties, probeAnchor, useLightProbe); - } - - public void DrawMesh(Mesh mesh, Vector3 pos, Vector3 scale, Quaternion rot, Material mat, int subMeshIndex, MaterialPropertyBlock customProperties, Transform probeAnchor, bool useLightProbe) - { - Graphics.DrawMesh(mesh, Matrix4x4.TRS(pos, rot, scale), mat, 1, camera, subMeshIndex, customProperties, ShadowCastingMode.Off, false, probeAnchor, useLightProbe); - } - - internal static Mesh GetPreviewSphere() - { - var handleGo = (GameObject)EditorGUIUtility.LoadRequired("Previews/PreviewMaterials.fbx"); - // Temp workaround to make it not render in the scene - handleGo.SetActive(false); - foreach (Transform t in handleGo.transform) - { - if (t.name == "sphere") - return t.GetComponent().sharedMesh; - } - return null; - } - - protected static GameObject CreateLight() - { - GameObject lightGO = EditorUtility.CreateGameObjectWithHideFlags("PreRenderLight", HideFlags.HideAndDontSave, typeof(Light)); - var light = lightGO.GetComponent(); - light.type = LightType.Directional; - light.intensity = 1.0f; - light.enabled = false; - return lightGO; - } - - public void Render(bool allowScriptableRenderPipeline = false, bool updatefov = true) - { - foreach (var light in lights) - light.enabled = true; - var oldAllowPipes = Unsupported.useScriptableRenderPipeline; - Unsupported.useScriptableRenderPipeline = allowScriptableRenderPipeline; - - float saveFieldOfView = camera.fieldOfView; - - if (updatefov) - { - // Calculate a view multiplier to avoid clipping when the preview width is smaller than the height. - float viewMultiplier = (m_RenderTexture.width <= 0 ? 1.0f : Mathf.Max(1.0f, (float)m_RenderTexture.height / m_RenderTexture.width)); - // Multiply the viewing area by the viewMultiplier - it requires some conversions since the camera view is expressed as an angle. - camera.fieldOfView = Mathf.Atan(viewMultiplier * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad)) * Mathf.Rad2Deg * 2.0f; - } - - camera.Render(); - - camera.fieldOfView = saveFieldOfView; - Unsupported.useScriptableRenderPipeline = oldAllowPipes; - } - } - - internal class SavedRenderTargetState - { - RenderTexture renderTexture; - Rect viewport; - Rect scissor; - - internal SavedRenderTargetState() - { - GL.PushMatrix(); - if (ShaderUtil.hardwareSupportsRectRenderTexture) - renderTexture = RenderTexture.active; - viewport = ShaderUtil.rawViewportRect; - scissor = ShaderUtil.rawScissorRect; - } - - internal void Restore() - { - if (ShaderUtil.hardwareSupportsRectRenderTexture) - EditorGUIUtility.SetRenderTextureNoViewport(renderTexture); - ShaderUtil.rawViewportRect = viewport; - ShaderUtil.rawScissorRect = scissor; - GL.PopMatrix(); - } - } -} diff --git a/Editor/Mono/Inspector/PreviewWindow.cs b/Editor/Mono/Inspector/PreviewWindow.cs deleted file mode 100644 index 2e0df95d37..0000000000 --- a/Editor/Mono/Inspector/PreviewWindow.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class PreviewWindow : InspectorWindow - { - [SerializeField] - private InspectorWindow m_ParentInspectorWindow; - - public void SetParentInspector(InspectorWindow inspector) - { - m_ParentInspectorWindow = inspector; - - // Create tracker after parent inspector window has been set (case 829182, 846156) - CreateTracker(); - } - - protected override void OnEnable() - { - base.OnEnable(); - titleContent = EditorGUIUtility.TrTextContent("Preview"); - minSize = new Vector2(260, 220); - } - - protected override void OnDisable() - { - base.OnDisable(); - m_ParentInspectorWindow.Repaint(); - } - - protected override void CreateTracker() - { - if (m_ParentInspectorWindow != null) - m_Tracker = m_ParentInspectorWindow.tracker; - } - - internal override Editor GetLastInteractedEditor() - { - return m_ParentInspectorWindow.GetLastInteractedEditor(); - } - - protected override void OnGUI() - { - if (!m_ParentInspectorWindow) - { - Close(); - EditorGUIUtility.ExitGUI(); - } - Editor.m_AllowMultiObjectAccess = true; - - CreatePreviewables(); - - // Do we have an editor that supports previews? Null if not. - IPreviewable[] editorsWithPreviews = GetEditorsWithPreviews(tracker.activeEditors); - IPreviewable editor = GetEditorThatControlsPreview(editorsWithPreviews); - - bool hasPreview = (editor != null) && editor.HasPreviewGUI(); - - // Toolbar - Rect labelRect; - Rect toolbarRect = EditorGUILayout.BeginHorizontal(GUIContent.none, styles.preToolbar, GUILayout.Height(17)); - { - GUILayout.FlexibleSpace(); - labelRect = GUILayoutUtility.GetLastRect(); - // Label - string label = string.Empty; - if ((editor != null)) - { - label = editor.GetPreviewTitle().text; - } - GUI.Label(labelRect, label, styles.preToolbar2); - if (hasPreview) - editor.OnPreviewSettings(); - } EditorGUILayout.EndHorizontal(); - - - Event evt = Event.current; - if (evt.type == EventType.MouseUp && evt.button == 1 && toolbarRect.Contains(evt.mousePosition)) - { - Close(); - evt.Use(); - // Don't draw preview if we just closed this window - return; - } - - // Preview - Rect previewPosition = GUILayoutUtility.GetRect(0, 10240, 64, 10240); - - // Draw background - if (Event.current.type == EventType.Repaint) - styles.preBackground.Draw(previewPosition, false, false, false, false); - - // Draw preview - if ((editor != null) && editor.HasPreviewGUI()) - editor.DrawPreview(previewPosition); - } - - public override void AddItemsToMenu(GenericMenu menu) {} - - protected override void ShowButton(Rect r) {} - } -} diff --git a/Editor/Mono/Inspector/PrimitiveCollider2DEditor.cs b/Editor/Mono/Inspector/PrimitiveCollider2DEditor.cs deleted file mode 100644 index d5cd5e0524..0000000000 --- a/Editor/Mono/Inspector/PrimitiveCollider2DEditor.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - internal abstract class PrimitiveCollider2DEditor : Collider2DEditorBase - { - protected abstract PrimitiveBoundsHandle boundsHandle { get; } - - protected abstract void CopyColliderSizeToHandle(); - - // only return true if the size has changed - protected abstract bool CopyHandleSizeToCollider(); - - protected override GUIContent editModeButton { get { return PrimitiveBoundsHandle.editModeButton; } } - - protected virtual Quaternion GetHandleRotation() - { - return Quaternion.identity; - } - - public override void OnEnable() - { - base.OnEnable(); - boundsHandle.axes = PrimitiveBoundsHandle.Axes.X | PrimitiveBoundsHandle.Axes.Y; - } - - protected virtual void OnSceneGUI() - { - if (!editingCollider) - return; - - Collider2D collider = (Collider2D)target; - - if (Mathf.Approximately(collider.transform.lossyScale.sqrMagnitude, 0f)) - return; - - // collider matrix is 2d projection of center multiplied by transform's matrix with custom postmultiplied lossy scale matrix - // only rotation of transform about z-axis should be considered, if at all - using (new Handles.DrawingScope(Matrix4x4.TRS(collider.transform.position, GetHandleRotation(), Vector3.one))) - { - Matrix4x4 colliderTransformMatrix = collider.transform.localToWorldMatrix; - boundsHandle.center = ProjectOntoWorldPlane(Handles.inverseMatrix * (colliderTransformMatrix * collider.offset)); - CopyColliderSizeToHandle(); - - boundsHandle.SetColor(collider.enabled ? Handles.s_ColliderHandleColor : Handles.s_ColliderHandleColorDisabled); - EditorGUI.BeginChangeCheck(); - boundsHandle.DrawHandle(); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(collider, string.Format("Modify {0}", ObjectNames.NicifyVariableName(target.GetType().Name))); - // because projection of offset is a lossy operation, only do it if the size has actually changed - // this check prevents drifting while dragging handle when size is zero (case 863949) - if (CopyHandleSizeToCollider()) - collider.offset = colliderTransformMatrix.inverse * ProjectOntoColliderPlane(Handles.matrix * boundsHandle.center, colliderTransformMatrix); - } - } - } - - // return specified world vector projected onto collider's x/y plane in world space - protected Vector3 ProjectOntoColliderPlane(Vector3 worldVector, Matrix4x4 colliderTransformMatrix) - { - Plane worldColliderPlane = new Plane( - Vector3.Cross(colliderTransformMatrix * Vector3.right, colliderTransformMatrix * Vector3.up), - Vector3.zero - ); - Ray ray = new Ray(worldVector, Vector3.forward); - float distance; - if (worldColliderPlane.Raycast(ray, out distance)) - return ray.GetPoint(distance); - ray.direction = Vector3.back; - worldColliderPlane.Raycast(ray, out distance); - return ray.GetPoint(distance); - } - - // return specified world vector projected onto world x/y plane - protected Vector3 ProjectOntoWorldPlane(Vector3 worldVector) - { - worldVector.z = 0f; - return worldVector; - } - } -} diff --git a/Editor/Mono/Inspector/PrimitiveCollider3DEditor.cs b/Editor/Mono/Inspector/PrimitiveCollider3DEditor.cs deleted file mode 100644 index da13f9bded..0000000000 --- a/Editor/Mono/Inspector/PrimitiveCollider3DEditor.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - internal abstract class PrimitiveCollider3DEditor : Collider3DEditorBase - { - protected abstract PrimitiveBoundsHandle boundsHandle { get; } - - protected abstract void CopyColliderPropertiesToHandle(); - - protected abstract void CopyHandlePropertiesToCollider(); - - protected override GUIContent editModeButton { get { return PrimitiveBoundsHandle.editModeButton; } } - - protected Vector3 InvertScaleVector(Vector3 scaleVector) - { - for (int axis = 0; axis < 3; ++axis) - scaleVector[axis] = scaleVector[axis] == 0f ? 0f : 1f / scaleVector[axis]; - return scaleVector; - } - - protected virtual void OnSceneGUI() - { - if (!editingCollider) - return; - - Collider collider = (Collider)target; - - if (Mathf.Approximately(collider.transform.lossyScale.sqrMagnitude, 0f)) - return; - - // collider matrix is center multiplied by transform's matrix with custom postmultiplied lossy scale matrix - using (new Handles.DrawingScope(Matrix4x4.TRS(collider.transform.position, collider.transform.rotation, Vector3.one))) - { - CopyColliderPropertiesToHandle(); - - boundsHandle.SetColor(collider.enabled ? Handles.s_ColliderHandleColor : Handles.s_ColliderHandleColorDisabled); - EditorGUI.BeginChangeCheck(); - boundsHandle.DrawHandle(); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(collider, string.Format("Modify {0}", ObjectNames.NicifyVariableName(target.GetType().Name))); - CopyHandlePropertiesToCollider(); - } - } - } - - protected Vector3 TransformColliderCenterToHandleSpace(Transform colliderTransform, Vector3 colliderCenter) - { - return Handles.inverseMatrix * (colliderTransform.localToWorldMatrix * colliderCenter); - } - - protected Vector3 TransformHandleCenterToColliderSpace(Transform colliderTransform, Vector3 handleCenter) - { - return colliderTransform.localToWorldMatrix.inverse * (Handles.matrix * handleCenter); - } - } -} diff --git a/Editor/Mono/Inspector/ProjectSettingsBaseEditor.cs b/Editor/Mono/Inspector/ProjectSettingsBaseEditor.cs deleted file mode 100644 index 73bf10b0d9..0000000000 --- a/Editor/Mono/Inspector/ProjectSettingsBaseEditor.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - [CustomEditor(typeof(ProjectSettingsBase), true)] - internal class ProjectSettingsBaseEditor : Editor - { - protected override bool ShouldHideOpenButton() - { - return true; - } - - private string m_LocalizedTargetName; - - internal override string targetTitle - { - get - { - if (m_LocalizedTargetName == null) - m_LocalizedTargetName = L10n.Tr(target.name); - return m_LocalizedTargetName; - } - } - } -} diff --git a/Editor/Mono/Inspector/PropertyDrawerCache.cs b/Editor/Mono/Inspector/PropertyDrawerCache.cs deleted file mode 100644 index 2a0a64eb61..0000000000 --- a/Editor/Mono/Inspector/PropertyDrawerCache.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class PropertyHandlerCache - { - protected Dictionary m_PropertyHandlers = new Dictionary(); - - internal PropertyHandler GetHandler(SerializedProperty property) - { - PropertyHandler handler; - int key = GetPropertyHash(property); - if (m_PropertyHandlers.TryGetValue(key, out handler)) - return handler; - - return null; - } - - internal void SetHandler(SerializedProperty property, PropertyHandler handler) - { - int key = GetPropertyHash(property); - m_PropertyHandlers[key] = handler; - } - - private static int GetPropertyHash(SerializedProperty property) - { - if (property.serializedObject.targetObject == null) - return 0; - - // For efficiency, ignore indices inside brackets [] in order to make array elements share handlers. - int key = property.serializedObject.targetObject.GetInstanceID() ^ property.hashCodeForPropertyPathWithoutArrayIndex; - if (property.propertyType == SerializedPropertyType.ObjectReference) - { - key ^= property.objectReferenceInstanceIDValue; - } - return key; - } - - public void Clear() - { - m_PropertyHandlers.Clear(); - } - } -} diff --git a/Editor/Mono/Inspector/QualitySettingsEditor.cs b/Editor/Mono/Inspector/QualitySettingsEditor.cs deleted file mode 100644 index 2f85962e6e..0000000000 --- a/Editor/Mono/Inspector/QualitySettingsEditor.cs +++ /dev/null @@ -1,585 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEditor.Build; -using System.Linq; -using UnityEditorInternal; -using UnityEngine.Experimental.Rendering; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - [CustomEditor(typeof(QualitySettings))] - internal class QualitySettingsEditor : ProjectSettingsBaseEditor - { - private static class Styles - { - public static readonly GUIStyle kToggle = "OL Toggle"; - public static readonly GUIStyle kDefaultToggle = "OL ToggleWhite"; - - public static readonly GUIContent kPlatformTooltip = new GUIContent("", "Allow quality setting on platform"); - public static readonly GUIContent kAddQualityLevel = EditorGUIUtility.TrTextContent("Add Quality Level"); - - public static readonly GUIContent kIconTrash = EditorGUIUtility.TrIconContent("TreeEditor.Trash", "Delete Level"); - public static readonly GUIContent kSoftParticlesHint = EditorGUIUtility.TrTextContent("Soft Particles require using Deferred Lighting or making camera render the depth texture."); - public static readonly GUIContent kBillboardsFaceCameraPos = EditorGUIUtility.TrTextContent("Billboards Face Camera Position", "Make billboards face towards camera position. Otherwise they face towards camera plane. This makes billboards look nicer when camera rotates but is more expensive to render."); - - public static readonly GUIStyle kListEvenBg = "ObjectPickerResultsOdd"; - public static readonly GUIStyle kListOddBg = "ObjectPickerResultsEven"; - public static readonly GUIStyle kDefaultDropdown = "QualitySettingsDefault"; - - public const int kMinToggleWidth = 15; - public const int kMaxToggleWidth = 20; - public const int kHeaderRowHeight = 20; - public const int kLabelWidth = 80; - } - - public const int kMinAsyncRingBufferSize = 2; - public const int kMaxAsyncRingBufferSize = 512; - public const int kMinAsyncUploadTimeSlice = 1; - public const int kMaxAsyncUploadTimeSlice = 33; - - private SerializedObject m_QualitySettings; - private SerializedProperty m_QualitySettingsProperty; - private SerializedProperty m_PerPlatformDefaultQualityProperty; - private List m_ValidPlatforms; - - public void OnEnable() - { - m_QualitySettings = new SerializedObject(target); - m_QualitySettingsProperty = m_QualitySettings.FindProperty("m_QualitySettings"); - m_PerPlatformDefaultQualityProperty = m_QualitySettings.FindProperty("m_PerPlatformDefaultQuality"); - m_ValidPlatforms = BuildPlatforms.instance.GetValidPlatforms(); - } - - private struct QualitySetting - { - public string m_Name; - public string m_PropertyPath; - public List m_ExcludedPlatforms; - } - - private readonly int m_QualityElementHash = "QualityElementHash".GetHashCode(); - private class Dragging - { - public int m_StartPosition; - public int m_Position; - } - - private Dragging m_Dragging; - private bool m_ShouldAddNewLevel; - private int m_DeleteLevel = -1; - private int DoQualityLevelSelection(int currentQualitylevel, IList qualitySettings, Dictionary platformDefaultQualitySettings) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - GUILayout.BeginVertical(); - var selectedLevel = currentQualitylevel; - - //Header row - GUILayout.BeginHorizontal(); - - Rect header = GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, GUILayout.ExpandWidth(false), GUILayout.Width(Styles.kLabelWidth), GUILayout.Height(Styles.kHeaderRowHeight)); - header.x += EditorGUI.indent; - header.width -= EditorGUI.indent; - GUI.Label(header, "Levels", EditorStyles.boldLabel); - - //Header row icons - foreach (var platform in m_ValidPlatforms) - { - var iconRect = GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, GUILayout.MinWidth(Styles.kMinToggleWidth), GUILayout.MaxWidth(Styles.kMaxToggleWidth), GUILayout.Height(Styles.kHeaderRowHeight)); - var temp = EditorGUIUtility.TempContent(platform.smallIcon); - temp.tooltip = platform.title.text; - GUI.Label(iconRect, temp); - temp.tooltip = ""; - } - - //Extra column for deleting setting button - GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, GUILayout.MinWidth(Styles.kMinToggleWidth), GUILayout.MaxWidth(Styles.kMaxToggleWidth), GUILayout.Height(Styles.kHeaderRowHeight)); - - GUILayout.EndHorizontal(); - - //Draw the row for each quality setting - var currentEvent = Event.current; - for (var i = 0; i < qualitySettings.Count; i++) - { - GUILayout.BeginHorizontal(); - var bgStyle = i % 2 == 0 ? Styles.kListEvenBg : Styles.kListOddBg; - bool selected = (selectedLevel == i); - - //Draw the selected icon if required - Rect r = GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, GUILayout.ExpandWidth(false), GUILayout.Width(Styles.kLabelWidth)); - - switch (currentEvent.type) - { - case EventType.Repaint: - bgStyle.Draw(r, GUIContent.none, false, false, selected, false); - GUI.Label(r, EditorGUIUtility.TempContent(qualitySettings[i].m_Name)); - break; - case EventType.MouseDown: - if (r.Contains(currentEvent.mousePosition)) - { - selectedLevel = i; - GUIUtility.keyboardControl = 0; - GUIUtility.hotControl = m_QualityElementHash; - GUI.changed = true; - m_Dragging = new Dragging {m_StartPosition = i, m_Position = i}; - currentEvent.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == m_QualityElementHash) - { - if (r.Contains(currentEvent.mousePosition)) - { - m_Dragging.m_Position = i; - currentEvent.Use(); - } - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == m_QualityElementHash) - { - GUIUtility.hotControl = 0; - currentEvent.Use(); - } - break; - case EventType.KeyDown: - if (currentEvent.keyCode == KeyCode.UpArrow || currentEvent.keyCode == KeyCode.DownArrow) - { - selectedLevel += currentEvent.keyCode == KeyCode.UpArrow ? -1 : 1; - selectedLevel = Mathf.Clamp(selectedLevel, 0, qualitySettings.Count - 1); - GUIUtility.keyboardControl = 0; - GUI.changed = true; - currentEvent.Use(); - } - break; - } - - //Build a list of the current platform selection and draw it. - foreach (var platform in m_ValidPlatforms) - { - bool isDefaultQuality = false; - if (platformDefaultQualitySettings.ContainsKey(platform.name) && platformDefaultQualitySettings[platform.name] == i) - isDefaultQuality = true; - - var toggleRect = GUILayoutUtility.GetRect(Styles.kPlatformTooltip, Styles.kToggle, GUILayout.MinWidth(Styles.kMinToggleWidth), GUILayout.MaxWidth(Styles.kMaxToggleWidth)); - if (Event.current.type == EventType.Repaint) - { - bgStyle.Draw(toggleRect, GUIContent.none, false, false, selected, false); - } - - var color = GUI.backgroundColor; - if (isDefaultQuality && !EditorApplication.isPlayingOrWillChangePlaymode) - GUI.backgroundColor = Color.green; - - var supported = !qualitySettings[i].m_ExcludedPlatforms.Contains(platform.name); - var newSupported = GUI.Toggle(toggleRect, supported, Styles.kPlatformTooltip, isDefaultQuality ? Styles.kDefaultToggle : Styles.kToggle); - if (supported != newSupported) - { - if (newSupported) - qualitySettings[i].m_ExcludedPlatforms.Remove(platform.name); - else - qualitySettings[i].m_ExcludedPlatforms.Add(platform.name); - } - - GUI.backgroundColor = color; - } - - //Extra column for deleting quality button - var deleteButton = GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, GUILayout.MinWidth(Styles.kMinToggleWidth), GUILayout.MaxWidth(Styles.kMaxToggleWidth)); - if (Event.current.type == EventType.Repaint) - { - bgStyle.Draw(deleteButton, GUIContent.none, false, false, selected, false); - } - if (GUI.Button(deleteButton, Styles.kIconTrash, GUIStyle.none)) - m_DeleteLevel = i; - GUILayout.EndHorizontal(); - } - - //Add a spacer line to separate the levels from the defaults - GUILayout.BeginHorizontal(); - GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, - GUILayout.MinWidth(Styles.kMinToggleWidth), - GUILayout.MaxWidth(Styles.kMaxToggleWidth), - GUILayout.Height(1)); - - DrawHorizontalDivider(); - GUILayout.EndHorizontal(); - - //Default platform selection dropdowns - GUILayout.BeginHorizontal(); - - var defaultQualityTitle = GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, GUILayout.ExpandWidth(false), GUILayout.Width(Styles.kLabelWidth), GUILayout.Height(Styles.kHeaderRowHeight)); - defaultQualityTitle.x += EditorGUI.indent; - defaultQualityTitle.width -= EditorGUI.indent; - GUI.Label(defaultQualityTitle, "Default", EditorStyles.boldLabel); - - // Draw default dropdown arrows - foreach (var platform in m_ValidPlatforms) - { - var iconRect = GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, - GUILayout.MinWidth(Styles.kMinToggleWidth), - GUILayout.MaxWidth(Styles.kMaxToggleWidth), - GUILayout.Height(Styles.kHeaderRowHeight)); - - int position; - if (!platformDefaultQualitySettings.TryGetValue(platform.name, out position)) - platformDefaultQualitySettings.Add(platform.name, 0); - - position = EditorGUI.Popup(iconRect, position, qualitySettings.Select(x => x.m_Name).ToArray(), Styles.kDefaultDropdown); - platformDefaultQualitySettings[platform.name] = position; - } - GUILayout.EndHorizontal(); - - GUILayout.Space(10); - - //Add an extra row for 'Add' button - GUILayout.BeginHorizontal(); - - GUILayoutUtility.GetRect(GUIContent.none, Styles.kToggle, - GUILayout.MinWidth(Styles.kMinToggleWidth), - GUILayout.MaxWidth(Styles.kMaxToggleWidth), - GUILayout.Height(Styles.kHeaderRowHeight)); - - var addButtonRect = GUILayoutUtility.GetRect(Styles.kAddQualityLevel, Styles.kToggle, GUILayout.ExpandWidth(true)); - - if (GUI.Button(addButtonRect, Styles.kAddQualityLevel)) - m_ShouldAddNewLevel = true; - - GUILayout.EndHorizontal(); - - GUILayout.EndVertical(); - - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - return selectedLevel; - } - - private List GetQualitySettings() - { - // Pull the quality settings from the runtime. - var qualitySettings = new List(); - - foreach (SerializedProperty prop in m_QualitySettingsProperty) - { - var qs = new QualitySetting - { - m_Name = prop.FindPropertyRelative("name").stringValue, - m_PropertyPath = prop.propertyPath - }; - - qs.m_PropertyPath = prop.propertyPath; - - var platforms = new List(); - var platformsProp = prop.FindPropertyRelative("excludedTargetPlatforms"); - foreach (SerializedProperty platformProp in platformsProp) - platforms.Add(platformProp.stringValue); - - qs.m_ExcludedPlatforms = platforms; - qualitySettings.Add(qs); - } - return qualitySettings; - } - - private void SetQualitySettings(IEnumerable settings) - { - foreach (var setting in settings) - { - var property = m_QualitySettings.FindProperty(setting.m_PropertyPath); - if (property == null) - continue; - - var platformsProp = property.FindPropertyRelative("excludedTargetPlatforms"); - if (platformsProp.arraySize != setting.m_ExcludedPlatforms.Count) - platformsProp.arraySize = setting.m_ExcludedPlatforms.Count; - - var count = 0; - foreach (SerializedProperty platform in platformsProp) - { - if (platform.stringValue != setting.m_ExcludedPlatforms[count]) - platform.stringValue = setting.m_ExcludedPlatforms[count]; - count++; - } - } - } - - private void HandleAddRemoveQualitySetting(ref int selectedLevel, Dictionary platformDefaults) - { - if (m_DeleteLevel >= 0) - { - if (m_DeleteLevel < selectedLevel || m_DeleteLevel == m_QualitySettingsProperty.arraySize - 1) - selectedLevel = Mathf.Max(0, selectedLevel - 1); - - //Always ensure there is one quality setting - if (m_QualitySettingsProperty.arraySize > 1 && m_DeleteLevel >= 0 && m_DeleteLevel < m_QualitySettingsProperty.arraySize) - { - m_QualitySettingsProperty.DeleteArrayElementAtIndex(m_DeleteLevel); - - // Fix defaults offset - List keys = new List(platformDefaults.Keys); - foreach (var key in keys) - { - int value = platformDefaults[key]; - if (value != 0 && value >= m_DeleteLevel) - platformDefaults[key]--; - } - } - - m_DeleteLevel = -1; - } - - if (m_ShouldAddNewLevel) - { - m_QualitySettingsProperty.arraySize++; - var addedSetting = m_QualitySettingsProperty.GetArrayElementAtIndex(m_QualitySettingsProperty.arraySize - 1); - var nameProperty = addedSetting.FindPropertyRelative("name"); - nameProperty.stringValue = "Level " + (m_QualitySettingsProperty.arraySize - 1); - - m_ShouldAddNewLevel = false; - } - } - - private Dictionary GetDefaultQualityForPlatforms() - { - var defaultPlatformQualities = new Dictionary(); - - foreach (SerializedProperty prop in m_PerPlatformDefaultQualityProperty) - { - defaultPlatformQualities.Add(prop.FindPropertyRelative("first").stringValue, prop.FindPropertyRelative("second").intValue); - } - return defaultPlatformQualities; - } - - private void SetDefaultQualityForPlatforms(Dictionary platformDefaults) - { - if (m_PerPlatformDefaultQualityProperty.arraySize != platformDefaults.Count) - m_PerPlatformDefaultQualityProperty.arraySize = platformDefaults.Count; - - var count = 0; - foreach (var def in platformDefaults) - { - var element = m_PerPlatformDefaultQualityProperty.GetArrayElementAtIndex(count); - var firstProperty = element.FindPropertyRelative("first"); - var secondProperty = element.FindPropertyRelative("second"); - - if (firstProperty.stringValue != def.Key || secondProperty.intValue != def.Value) - { - firstProperty.stringValue = def.Key; - secondProperty.intValue = def.Value; - } - count++; - } - } - - private static void DrawHorizontalDivider() - { - var spacerLine = GUILayoutUtility.GetRect(GUIContent.none, - GUIStyle.none, - GUILayout.ExpandWidth(true), - GUILayout.Height(1)); - var oldBgColor = GUI.backgroundColor; - if (EditorGUIUtility.isProSkin) - GUI.backgroundColor = oldBgColor * 0.7058f; - else - GUI.backgroundColor = Color.black; - - if (Event.current.type == EventType.Repaint) - EditorGUIUtility.whiteTextureStyle.Draw(spacerLine, GUIContent.none, false, false, false, false); - - GUI.backgroundColor = oldBgColor; - } - - void SoftParticlesHintGUI() - { - var mainCamera = Camera.main; - if (mainCamera == null) - return; - - RenderingPath renderPath = mainCamera.actualRenderingPath; - if (renderPath == RenderingPath.DeferredLighting || renderPath == RenderingPath.DeferredShading) - return; // using deferred, all is good - - if ((mainCamera.depthTextureMode & DepthTextureMode.Depth) != 0) - return; // already produces depth texture, all is good - - EditorGUILayout.HelpBox(Styles.kSoftParticlesHint.text, MessageType.Warning, false); - } - - /** - * Internal function that takes the shadow cascade splits property field, and dispatches a call to render the GUI. - * It also transfers the result back - */ - private void DrawCascadeSplitGUI(ref SerializedProperty shadowCascadeSplit) - { - float[] cascadePartitionSizes = null; - - System.Type type = typeof(T); - if (type == typeof(float)) - cascadePartitionSizes = new float[] { shadowCascadeSplit.floatValue }; - else if (type == typeof(Vector3)) - { - Vector3 splits = shadowCascadeSplit.vector3Value; - cascadePartitionSizes = new float[] { - Mathf.Clamp(splits[0], 0.0f, 1.0f), - Mathf.Clamp(splits[1] - splits[0], 0.0f, 1.0f), - Mathf.Clamp(splits[2] - splits[1], 0.0f, 1.0f) - }; - } - - if (cascadePartitionSizes != null) - { - EditorGUI.BeginChangeCheck(); - ShadowCascadeSplitGUI.HandleCascadeSliderGUI(ref cascadePartitionSizes); - if (EditorGUI.EndChangeCheck()) - { - if (type == typeof(float)) - shadowCascadeSplit.floatValue = cascadePartitionSizes[0]; - else - { - Vector3 updatedValue = new Vector3(); - updatedValue[0] = cascadePartitionSizes[0]; - updatedValue[1] = updatedValue[0] + cascadePartitionSizes[1]; - updatedValue[2] = updatedValue[1] + cascadePartitionSizes[2]; - shadowCascadeSplit.vector3Value = updatedValue; - } - } - } - } - - public override void OnInspectorGUI() - { - if (EditorApplication.isPlayingOrWillChangePlaymode) - { - EditorGUILayout.HelpBox("Changes made in play mode will not be saved.", MessageType.Warning, true); - } - - m_QualitySettings.Update(); - - var settings = GetQualitySettings(); - var defaults = GetDefaultQualityForPlatforms(); - var selectedLevel = QualitySettings.GetQualityLevel(); - - EditorGUI.BeginChangeCheck(); - selectedLevel = DoQualityLevelSelection(selectedLevel, settings, defaults); - if (EditorGUI.EndChangeCheck()) - QualitySettings.SetQualityLevel(selectedLevel); - - SetQualitySettings(settings); - HandleAddRemoveQualitySetting(ref selectedLevel, defaults); - SetDefaultQualityForPlatforms(defaults); - GUILayout.Space(10.0f); - DrawHorizontalDivider(); - GUILayout.Space(10.0f); - - var currentSettings = m_QualitySettingsProperty.GetArrayElementAtIndex(selectedLevel); - var nameProperty = currentSettings.FindPropertyRelative("name"); - var pixelLightCountProperty = currentSettings.FindPropertyRelative("pixelLightCount"); - var shadowsProperty = currentSettings.FindPropertyRelative("shadows"); - var shadowResolutionProperty = currentSettings.FindPropertyRelative("shadowResolution"); - var shadowProjectionProperty = currentSettings.FindPropertyRelative("shadowProjection"); - var shadowCascadesProperty = currentSettings.FindPropertyRelative("shadowCascades"); - var shadowDistanceProperty = currentSettings.FindPropertyRelative("shadowDistance"); - var shadowNearPlaneOffsetProperty = currentSettings.FindPropertyRelative("shadowNearPlaneOffset"); - var shadowCascade2SplitProperty = currentSettings.FindPropertyRelative("shadowCascade2Split"); - var shadowCascade4SplitProperty = currentSettings.FindPropertyRelative("shadowCascade4Split"); - var shadowMaskUsageProperty = currentSettings.FindPropertyRelative("shadowmaskMode"); - var blendWeightsProperty = currentSettings.FindPropertyRelative("blendWeights"); - var textureQualityProperty = currentSettings.FindPropertyRelative("textureQuality"); - var anisotropicTexturesProperty = currentSettings.FindPropertyRelative("anisotropicTextures"); - var antiAliasingProperty = currentSettings.FindPropertyRelative("antiAliasing"); - var softParticlesProperty = currentSettings.FindPropertyRelative("softParticles"); - var realtimeReflectionProbes = currentSettings.FindPropertyRelative("realtimeReflectionProbes"); - var billboardsFaceCameraPosition = currentSettings.FindPropertyRelative("billboardsFaceCameraPosition"); - var vSyncCountProperty = currentSettings.FindPropertyRelative("vSyncCount"); - var lodBiasProperty = currentSettings.FindPropertyRelative("lodBias"); - var maximumLODLevelProperty = currentSettings.FindPropertyRelative("maximumLODLevel"); - var particleRaycastBudgetProperty = currentSettings.FindPropertyRelative("particleRaycastBudget"); - var asyncUploadTimeSliceProperty = currentSettings.FindPropertyRelative("asyncUploadTimeSlice"); - var asyncUploadBufferSizeProperty = currentSettings.FindPropertyRelative("asyncUploadBufferSize"); - var resolutionScalingFixedDPIFactorProperty = currentSettings.FindPropertyRelative("resolutionScalingFixedDPIFactor"); - - bool usingSRP = GraphicsSettings.renderPipelineAsset != null; - - if (string.IsNullOrEmpty(nameProperty.stringValue)) - nameProperty.stringValue = "Level " + selectedLevel; - - EditorGUILayout.PropertyField(nameProperty); - - if (usingSRP) - EditorGUILayout.HelpBox("A Scriptable Render Pipeline is in use, some settings will not be used and are hidden", MessageType.Info); - - GUILayout.Space(10); - - GUILayout.Label(EditorGUIUtility.TempContent("Rendering"), EditorStyles.boldLabel); - if (!usingSRP) - EditorGUILayout.PropertyField(pixelLightCountProperty); - - // still valid with SRP - EditorGUILayout.PropertyField(textureQualityProperty); - EditorGUILayout.PropertyField(anisotropicTexturesProperty); - - if (!usingSRP) - { - EditorGUILayout.PropertyField(antiAliasingProperty); - EditorGUILayout.PropertyField(softParticlesProperty); - if (softParticlesProperty.boolValue) - SoftParticlesHintGUI(); - } - - EditorGUILayout.PropertyField(realtimeReflectionProbes); - EditorGUILayout.PropertyField(billboardsFaceCameraPosition, Styles.kBillboardsFaceCameraPos); - EditorGUILayout.PropertyField(resolutionScalingFixedDPIFactorProperty); - GUILayout.Space(10); - - GUILayout.Label(EditorGUIUtility.TempContent("Shadows"), EditorStyles.boldLabel); - if (SupportedRenderingFeatures.IsMixedLightingModeSupported(MixedLightingMode.Shadowmask)) - EditorGUILayout.PropertyField(shadowMaskUsageProperty); - - if (!usingSRP) - { - EditorGUILayout.PropertyField(shadowsProperty); - EditorGUILayout.PropertyField(shadowResolutionProperty); - EditorGUILayout.PropertyField(shadowProjectionProperty); - EditorGUILayout.PropertyField(shadowDistanceProperty); - EditorGUILayout.PropertyField(shadowNearPlaneOffsetProperty); - EditorGUILayout.PropertyField(shadowCascadesProperty); - - if (shadowCascadesProperty.intValue == 2) - DrawCascadeSplitGUI(ref shadowCascade2SplitProperty); - else if (shadowCascadesProperty.intValue == 4) - DrawCascadeSplitGUI(ref shadowCascade4SplitProperty); - - GUILayout.Space(10); - } - - GUILayout.Label(EditorGUIUtility.TempContent("Other"), EditorStyles.boldLabel); - EditorGUILayout.PropertyField(blendWeightsProperty); - EditorGUILayout.PropertyField(vSyncCountProperty); - EditorGUILayout.PropertyField(lodBiasProperty); - EditorGUILayout.PropertyField(maximumLODLevelProperty); - EditorGUILayout.PropertyField(particleRaycastBudgetProperty); - EditorGUILayout.PropertyField(asyncUploadTimeSliceProperty); - EditorGUILayout.PropertyField(asyncUploadBufferSizeProperty); - - asyncUploadTimeSliceProperty.intValue = Mathf.Clamp(asyncUploadTimeSliceProperty.intValue, kMinAsyncUploadTimeSlice, kMaxAsyncUploadTimeSlice); - asyncUploadBufferSizeProperty.intValue = Mathf.Clamp(asyncUploadBufferSizeProperty.intValue, kMinAsyncRingBufferSize, kMaxAsyncRingBufferSize); - - - if (m_Dragging != null && m_Dragging.m_Position != m_Dragging.m_StartPosition) - { - m_QualitySettingsProperty.MoveArrayElement(m_Dragging.m_StartPosition, m_Dragging.m_Position); - m_Dragging.m_StartPosition = m_Dragging.m_Position; - selectedLevel = m_Dragging.m_Position; - - m_QualitySettings.ApplyModifiedProperties(); - QualitySettings.SetQualityLevel(Mathf.Clamp(selectedLevel, 0, m_QualitySettingsProperty.arraySize - 1)); - } - - m_QualitySettings.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/RectHandles.cs b/Editor/Mono/Inspector/RectHandles.cs deleted file mode 100644 index f3f48c55d0..0000000000 --- a/Editor/Mono/Inspector/RectHandles.cs +++ /dev/null @@ -1,296 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class RectHandles - { - static Styles s_Styles; - class Styles - { - public readonly GUIStyle dragdot = "U2D.dragDot"; - public readonly GUIStyle pivotdot = "U2D.pivotDot"; - public readonly GUIStyle dragdotactive = "U2D.dragDotActive"; - public readonly GUIStyle pivotdotactive = "U2D.pivotDotActive"; - } - - private static int s_LastCursorId; - - internal static bool RaycastGUIPointToWorldHit(Vector2 guiPoint, Plane plane, out Vector3 hit) - { - Ray ray = HandleUtility.GUIPointToWorldRay(guiPoint); - float dist = 0f; - bool isHit = plane.Raycast(ray, out dist); - hit = isHit ? ray.GetPoint(dist) : Vector3.zero; - return isHit; - } - - internal static void DetectCursorChange(int id) - { - if (HandleUtility.nearestControl == id) - { - // Don't optimize this to only use event if s_LastCursorId wasn't already id. - // Cursor can sometimes change for the same handle. - s_LastCursorId = id; - Event.current.Use(); - } - else if (s_LastCursorId == id) - { - s_LastCursorId = 0; - Event.current.Use(); - } - } - - internal static Vector3 SideSlider(int id, Vector3 position, Vector3 sideVector, Vector3 direction, float size, Handles.CapFunction capFunction, float snap) - { - return SideSlider(id, position, sideVector, direction, size, capFunction, snap, 0); - } - - internal static Vector3 SideSlider(int id, Vector3 position, Vector3 sideVector, Vector3 direction, float size, Handles.CapFunction capFunction, float snap, float bias) - { - Event evt = Event.current; - Vector3 handleDir = Vector3.Cross(sideVector, direction).normalized; - Vector3 pos = Handles.Slider2D(id, position, handleDir, direction, sideVector, 0, capFunction, Vector2.one * snap); - pos = position + Vector3.Project(pos - position, direction); - - switch (evt.type) - { - case EventType.Layout: - Vector3 sideDir = sideVector.normalized; - HandleUtility.AddControl(id, HandleUtility.DistanceToLine(position + sideVector * 0.5f - sideDir * size * 2, position - sideVector * 0.5f + sideDir * size * 2) - bias); - break; - - case EventType.MouseMove: - DetectCursorChange(id); - break; - - case EventType.Repaint: - if ((HandleUtility.nearestControl == id && GUIUtility.hotControl == 0) || GUIUtility.hotControl == id) - HandleDirectionalCursor(position, handleDir, direction); - break; - } - - return pos; - } - - internal static Vector3 CornerSlider(int id, Vector3 cornerPos, Vector3 handleDir, Vector3 outwardsDir1, Vector3 outwardsDir2, float handleSize, Handles.CapFunction drawFunc, Vector2 snap) - { - Event evt = Event.current; - Vector3 pos = Handles.Slider2D(id, cornerPos, handleDir, outwardsDir1, outwardsDir2, handleSize, drawFunc, snap); - - switch (evt.type) - { - case EventType.MouseMove: - DetectCursorChange(id); - break; - - case EventType.Repaint: - if ((HandleUtility.nearestControl == id && GUIUtility.hotControl == 0) || GUIUtility.hotControl == id) - HandleDirectionalCursor(cornerPos, handleDir, outwardsDir1 + outwardsDir2); - break; - } - return pos; - } - - private static void HandleDirectionalCursor(Vector3 handlePosition, Vector3 handlePlaneNormal, Vector3 direction) - { - Vector2 mousePosition = Event.current.mousePosition; - - // Find cursor direction (supports perspective camera) - Plane guiPlane = new Plane(handlePlaneNormal, handlePosition); - Vector3 mousePosWorld; - if (RaycastGUIPointToWorldHit(mousePosition, guiPlane, out mousePosWorld)) - { - Vector2 cursorDir = WorldToScreenSpaceDir(mousePosWorld, direction); - // 200px x 200px rect around mousepos to switch cursor via fake cursorRect. - Rect mouseScreenRect = new Rect(mousePosition.x - 100f, mousePosition.y - 100f, 200f, 200f); - EditorGUIUtility.AddCursorRect(mouseScreenRect, GetScaleCursor(cursorDir)); - } - } - - public static float AngleAroundAxis(Vector3 dirA, Vector3 dirB, Vector3 axis) - { - // Project A and B onto the plane orthogonal target axis - dirA = Vector3.ProjectOnPlane(dirA, axis); - dirB = Vector3.ProjectOnPlane(dirB, axis); - - // Find (positive) angle between A and B - float angle = Vector3.Angle(dirA, dirB); - - // Return angle multiplied with 1 or -1 - return angle * (Vector3.Dot(axis, Vector3.Cross(dirA, dirB)) < 0 ? -1 : 1); - } - - 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) - { - Vector3 diagonal = (outwardsDir1 + outwardsDir2); - Vector2 screenCorner = HandleUtility.WorldToGUIPoint(cornerPos); - Vector2 screenOffset = HandleUtility.WorldToGUIPoint(cornerPos + diagonal) - screenCorner; - screenOffset = screenOffset.normalized * 15; - RaycastGUIPointToWorldHit(screenCorner + screenOffset, new Plane(handleDir, cornerPos), out cornerPos); - - Event evt = Event.current; - Vector3 pos = Handles.Slider2D(id, cornerPos, handleDir, outwardsDir1, outwardsDir2, handleSize, drawFunc, Vector2.zero); - - if (evt.type == EventType.MouseMove) - DetectCursorChange(id); - - if (evt.type == EventType.Repaint) - { - if ((HandleUtility.nearestControl == id && GUIUtility.hotControl == 0) || GUIUtility.hotControl == id) - { - Rect mouseScreenRect = new Rect(evt.mousePosition.x - 100f, evt.mousePosition.y - 100f, 200f, 200f); - EditorGUIUtility.AddCursorRect(mouseScreenRect, MouseCursor.RotateArrow); - } - } - - return rotation - AngleAroundAxis(pos - pivot, cornerPos - pivot, handleDir); - } - - static Vector2 WorldToScreenSpaceDir(Vector3 worldPos, Vector3 worldDir) - { - Vector3 screenPos = HandleUtility.WorldToGUIPoint(worldPos); - Vector3 screenPosPlusDirection = HandleUtility.WorldToGUIPoint(worldPos + worldDir); - Vector2 screenSpaceDir = screenPosPlusDirection - screenPos; - screenSpaceDir.y *= -1; - return screenSpaceDir; - } - - private static MouseCursor GetScaleCursor(Vector2 direction) - { - float angle = Mathf.Atan2(direction.x, direction.y) * Mathf.Rad2Deg; - - if (angle < 0f) - angle = 360f + angle; - - if (angle < 0f + 27.5f) - return MouseCursor.ResizeVertical; - if (angle < 45f + 27.5f) - return MouseCursor.ResizeUpRight; - if (angle < 90f + 27.5f) - return MouseCursor.ResizeHorizontal; - if (angle < 135f + 27.5f) - return MouseCursor.ResizeUpLeft; - if (angle < 180f + 27.5f) - return MouseCursor.ResizeVertical; - if (angle < 225f + 27.5f) - return MouseCursor.ResizeUpRight; - if (angle < 270f + 27.5f) - return MouseCursor.ResizeHorizontal; - if (angle < 315f + 27.5f) - return MouseCursor.ResizeUpLeft; - else - return MouseCursor.ResizeVertical; - } - - public static void RectScalingHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - if (s_Styles == null) - s_Styles = new Styles(); - - switch (eventType) - { - case EventType.Layout: - HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size * .5f)); - break; - case EventType.Repaint: - DrawImageBasedCap(controlID, position, rotation, size, s_Styles.dragdot, s_Styles.dragdotactive); - break; - } - } - - public static void PivotHandleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - if (s_Styles == null) - s_Styles = new Styles(); - - switch (eventType) - { - case EventType.Layout: - HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size * .5f)); - break; - case EventType.Repaint: - DrawImageBasedCap(controlID, position, rotation, size, s_Styles.pivotdot, s_Styles.pivotdotactive); - break; - } - } - - static void DrawImageBasedCap(int controlID, Vector3 position, Quaternion rotation, float size, GUIStyle normal, GUIStyle active) - { - // Don't draw positions behind the camera - if (Camera.current && Vector3.Dot(position - Camera.current.transform.position, Camera.current.transform.forward) < 0) - return; - - Vector3 screenPos = HandleUtility.WorldToGUIPoint(position); - - Handles.BeginGUI(); - float w = normal.fixedWidth; - float h = normal.fixedHeight; - Rect r = new Rect(screenPos.x - w / 2f, screenPos.y - h / 2f, w, h); - if (GUIUtility.hotControl == controlID) - active.Draw(r, GUIContent.none, controlID); - else - normal.Draw(r, GUIContent.none, controlID); - - Handles.EndGUI(); - } - - public static void RenderRectWithShadow(bool active, params Vector3[] corners) - { - Vector3[] verts = new Vector3[] { corners[0], corners[1], corners[2], corners[3], corners[0] }; - - Color oldColor = Handles.color; - Handles.color = new Color(1f, 1f, 1f, active ? 1f : 0.5f); - DrawPolyLineWithShadow(new Color(0f, 0f, 0f, active ? 1f : 0.5f), new Vector2(1f, -1f), verts); - Handles.color = oldColor; - } - - static Vector3[] s_TempVectors = new Vector3[0]; - public static void DrawPolyLineWithShadow(Color shadowColor, Vector2 screenOffset, params Vector3[] points) - { - Camera cam = Camera.current; - if (!cam || Event.current.type != EventType.Repaint) - return; - - if (s_TempVectors.Length != points.Length) - s_TempVectors = new Vector3[points.Length]; - - for (int i = 0; i < points.Length; i++) - s_TempVectors[i] = cam.ScreenToWorldPoint(cam.WorldToScreenPoint(points[i]) + (Vector3)screenOffset); - - Color oldColor = Handles.color; - - // shadow - shadowColor.a = shadowColor.a * oldColor.a; - Handles.color = shadowColor; - Handles.DrawPolyLine(s_TempVectors); - - // line itself - Handles.color = oldColor; - Handles.DrawPolyLine(points); - } - - public static void DrawDottedLineWithShadow(Color shadowColor, Vector2 screenOffset, Vector3 p1, Vector3 p2, float screenSpaceSize) - { - Camera cam = Camera.current; - if (!cam || Event.current.type != EventType.Repaint) - return; - - Color oldColor = Handles.color; - - // shadow - shadowColor.a = shadowColor.a * oldColor.a; - Handles.color = shadowColor; - Handles.DrawDottedLine( - cam.ScreenToWorldPoint(cam.WorldToScreenPoint(p1) + (Vector3)screenOffset), - cam.ScreenToWorldPoint(cam.WorldToScreenPoint(p2) + (Vector3)screenOffset), screenSpaceSize); - - // line itself - Handles.color = oldColor; - Handles.DrawDottedLine(p1, p2, screenSpaceSize); - } - } -} diff --git a/Editor/Mono/Inspector/RectTransformEditor.cs b/Editor/Mono/Inspector/RectTransformEditor.cs deleted file mode 100644 index 8433158e6b..0000000000 --- a/Editor/Mono/Inspector/RectTransformEditor.cs +++ /dev/null @@ -1,1386 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEditorInternal; -using System.Linq; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - [CustomEditor(typeof(RectTransform))] - [CanEditMultipleObjects] - internal class RectTransformEditor : Editor - { - // Consts - // (Some are technically statics, but still have k prefix because they're not meant to be changed.) - - private const string kShowAnchorPropsPrefName = "RectTransformEditor.showAnchorProperties"; - private const string kLockRectPrefName = "RectTransformEditor.lockRect"; - - private static Vector2 kShadowOffset = new Vector2(1, -1); - private static Color kShadowColor = new Color(0, 0, 0, 0.5f); - private const float kDottedLineSize = 5f; - private static float kDropdownSize = 49; - private static Color kRectInParentSpaceColor = new Color(1, 1, 1, 0.4f); - private static Color kParentColor = new Color(1, 1, 1, 0.6f); - private static Color kSiblingColor = new Color(1, 1, 1, 0.2f); - private static Color kAnchorColor = new Color(1, 1, 1, 1); - private static Color kAnchorLineColor = new Color(1, 1, 1, 0.6f); - private static Vector3[] s_Corners = new Vector3[4]; - - // Statics - - class Styles - { - public GUIStyle measuringLabelStyle = new GUIStyle("PreOverlayLabel"); - - public GUIContent anchorsContent = EditorGUIUtility.TrTextContent("Anchors"); - public GUIContent anchorMinContent = EditorGUIUtility.TrTextContent("Min", "The normalized position in the parent rectangle that the lower left corner is anchored to."); - public GUIContent anchorMaxContent = EditorGUIUtility.TrTextContent("Max", "The normalized position in the parent rectangle that the upper right corner is anchored to."); - 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 is around this point."); - 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."); - public GUIContent rawEditContent; - public GUIContent blueprintContent; - - public Styles() - { - 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."); - blueprintContent = EditorGUIUtility.IconContent(@"RectTransformBlueprint", "|Blueprint mode. Edit RectTransforms as if they were not rotated and scaled. This enables snapping too."); - } - } - static Styles s_Styles; - static Styles styles { get { if (s_Styles == null) { s_Styles = new Styles(); } return s_Styles; } } - - private static int s_FoldoutHash = "Foldout".GetHashCode(); - private static int s_FloatFieldHash = "EditorTextField".GetHashCode(); - private static int s_ParentRectPreviewHandlesHash = "ParentRectPreviewDragHandles".GetHashCode(); - private static GUIContent[] s_XYLabels = {new GUIContent("X"), new GUIContent("Y")}; - private static GUIContent[] s_XYZLabels = {new GUIContent("X"), new GUIContent("Y"), new GUIContent("Z")}; - private static bool[] s_ScaleDisabledMask = new bool[3]; - - private static bool s_DragAnchorsTogether; - private static Vector2 s_StartDragAnchorMin; - private static Vector2 s_StartDragAnchorMax; - - enum AnchorFusedState { None, All, Horizontal, Vertical } - private static AnchorFusedState s_AnchorFusedState = AnchorFusedState.None; - - // Instance members - - private SerializedProperty m_AnchorMin; - private SerializedProperty m_AnchorMax; - private SerializedProperty m_AnchoredPosition; - private SerializedProperty m_SizeDelta; - private SerializedProperty m_Pivot; - - private SerializedProperty m_LocalPositionZ; - private SerializedProperty m_LocalScale; - private TransformRotationGUI m_RotationGUI; - - private bool m_ShowLayoutOptions = false; - private bool m_RawEditMode = false; - private int m_TargetCount = 0; - - private Dictionary m_KeyboardControlIDs = new Dictionary(); - private AnimatedValues.AnimBool m_ChangingAnchors = new AnimatedValues.AnimBool(); - private AnimatedValues.AnimBool m_ChangingPivot = new AnimatedValues.AnimBool(); - private AnimatedValues.AnimBool m_ChangingWidth = new AnimatedValues.AnimBool(); - private AnimatedValues.AnimBool m_ChangingHeight = new AnimatedValues.AnimBool(); - private AnimatedValues.AnimBool m_ChangingPosX = new AnimatedValues.AnimBool(); - private AnimatedValues.AnimBool m_ChangingPosY = new AnimatedValues.AnimBool(); - private AnimatedValues.AnimBool m_ChangingLeft = new AnimatedValues.AnimBool(); - private AnimatedValues.AnimBool m_ChangingRight = new AnimatedValues.AnimBool(); - private AnimatedValues.AnimBool m_ChangingTop = new AnimatedValues.AnimBool(); - private AnimatedValues.AnimBool m_ChangingBottom = new AnimatedValues.AnimBool(); - - private delegate float FloatGetter(RectTransform rect); - private delegate void FloatSetter(RectTransform rect, float f); - - void OnEnable() - { - m_AnchorMin = serializedObject.FindProperty("m_AnchorMin"); - m_AnchorMax = serializedObject.FindProperty("m_AnchorMax"); - m_AnchoredPosition = serializedObject.FindProperty("m_AnchoredPosition"); - m_SizeDelta = serializedObject.FindProperty("m_SizeDelta"); - m_Pivot = serializedObject.FindProperty("m_Pivot"); - - m_TargetCount = targets.Length; - m_LocalPositionZ = serializedObject.FindProperty("m_LocalPosition.z"); - m_LocalScale = serializedObject.FindProperty("m_LocalScale"); - if (m_RotationGUI == null) - m_RotationGUI = new TransformRotationGUI(); - m_RotationGUI.OnEnable(serializedObject.FindProperty("m_LocalRotation"), EditorGUIUtility.TrTextContent("Rotation")); - - m_ShowLayoutOptions = EditorPrefs.GetBool(kShowAnchorPropsPrefName, false); - m_RawEditMode = EditorPrefs.GetBool(kLockRectPrefName, false); - - m_ChangingAnchors.valueChanged.AddListener(RepaintScene); - m_ChangingPivot.valueChanged.AddListener(RepaintScene); - m_ChangingWidth.valueChanged.AddListener(RepaintScene); - m_ChangingHeight.valueChanged.AddListener(RepaintScene); - m_ChangingPosX.valueChanged.AddListener(RepaintScene); - m_ChangingPosY.valueChanged.AddListener(RepaintScene); - m_ChangingLeft.valueChanged.AddListener(RepaintScene); - m_ChangingRight.valueChanged.AddListener(RepaintScene); - m_ChangingTop.valueChanged.AddListener(RepaintScene); - m_ChangingBottom.valueChanged.AddListener(RepaintScene); - - ManipulationToolUtility.handleDragChange += HandleDragChange; - } - - void OnDisable() - { - m_ChangingAnchors.valueChanged.RemoveListener(RepaintScene); - m_ChangingPivot.valueChanged.RemoveListener(RepaintScene); - m_ChangingWidth.valueChanged.RemoveListener(RepaintScene); - m_ChangingHeight.valueChanged.RemoveListener(RepaintScene); - m_ChangingPosX.valueChanged.RemoveListener(RepaintScene); - m_ChangingPosY.valueChanged.RemoveListener(RepaintScene); - m_ChangingLeft.valueChanged.RemoveListener(RepaintScene); - m_ChangingRight.valueChanged.RemoveListener(RepaintScene); - m_ChangingTop.valueChanged.RemoveListener(RepaintScene); - m_ChangingBottom.valueChanged.RemoveListener(RepaintScene); - - ManipulationToolUtility.handleDragChange -= HandleDragChange; - - if (m_DropdownWindow != null && m_DropdownWindow.editorWindow != null) - m_DropdownWindow.editorWindow.Close(); - } - - void HandleDragChange(string handleName, bool dragging) - { - AnimatedValues.AnimBool animBool; - switch (handleName) - { - case RectTool.kChangingLeft: animBool = m_ChangingLeft; break; - case RectTool.kChangingRight: animBool = m_ChangingRight; break; - case RectTool.kChangingPosY: animBool = m_ChangingPosY; break; - case RectTool.kChangingWidth: animBool = m_ChangingWidth; break; - case RectTool.kChangingBottom: animBool = m_ChangingBottom; break; - case RectTool.kChangingTop: animBool = m_ChangingTop; break; - case RectTool.kChangingPosX: animBool = m_ChangingPosX; break; - case RectTool.kChangingHeight: animBool = m_ChangingHeight; break; - case RectTool.kChangingPivot: animBool = m_ChangingPivot; break; - default: animBool = null; break; - } - if (animBool != null) - animBool.target = dragging; - } - - void SetFadingBasedOnMouseDownUp(ref AnimatedValues.AnimBool animBool, Event eventBefore) - { - if (eventBefore.type == EventType.MouseDrag && Event.current.type != EventType.MouseDrag) - animBool.value = true; - else if (eventBefore.type == EventType.MouseUp && Event.current.type != EventType.MouseUp) - animBool.target = false; - } - - void SetFadingBasedOnControlID(ref AnimatedValues.AnimBool animBool, int id) - { - GUIView focusedView = (EditorWindow.focusedWindow == null ? null : EditorWindow.focusedWindow.m_Parent); - if (GUIUtility.keyboardControl == id && GUIView.current == focusedView) - { - animBool.value = true; - m_KeyboardControlIDs[id] = animBool; - } - else if ((GUIUtility.keyboardControl != id || GUIView.current != focusedView) && m_KeyboardControlIDs.ContainsKey(id)) - { - m_KeyboardControlIDs.Remove(id); - if (!m_KeyboardControlIDs.ContainsValue(animBool)) - animBool.target = false; - } - } - - void RepaintScene() - { - SceneView.RepaintAll(); - } - - private static bool ShouldDoIntSnapping(RectTransform rect) - { - Canvas canvas = rect.gameObject.GetComponentInParent(); - return (canvas != null && canvas.renderMode != RenderMode.WorldSpace); - } - - public override void OnInspectorGUI() - { - if (!EditorGUIUtility.wideMode) - { - EditorGUIUtility.wideMode = true; - EditorGUIUtility.labelWidth = EditorGUIUtility.currentViewWidth - 212; - } - - bool anyDriven = false; - bool anyDrivenXPositionOrSize = false; - bool anyDrivenYPositionOrSize = false; - bool anyWithoutParent = false; - foreach (RectTransform gui in targets) - { - if (gui.drivenByObject != null) - { - anyDriven = true; - if ((gui.drivenProperties & (DrivenTransformProperties.AnchoredPositionX | DrivenTransformProperties.SizeDeltaX)) != 0) - anyDrivenXPositionOrSize = true; - if ((gui.drivenProperties & (DrivenTransformProperties.AnchoredPositionY | DrivenTransformProperties.SizeDeltaY)) != 0) - anyDrivenYPositionOrSize = true; - } - - PrefabType prefabType = PrefabUtility.GetPrefabType(gui.gameObject); - if ((gui.transform.parent == null || gui.transform.parent.GetComponent() == null) - && (prefabType != PrefabType.Prefab && prefabType != PrefabType.ModelPrefab)) - anyWithoutParent = true; - } - - if (anyDriven) - { - if (targets.Length == 1) - EditorGUILayout.HelpBox("Some values driven by " + (target as RectTransform).drivenByObject.GetType().Name + ".", MessageType.None); - else - EditorGUILayout.HelpBox("Some values in some or all objects are driven.", MessageType.None); - } - - serializedObject.Update(); - - LayoutDropdownButton(anyWithoutParent); - - // Position and Size Delta - SmartPositionAndSizeFields(anyWithoutParent, anyDrivenXPositionOrSize, anyDrivenYPositionOrSize); - - // Anchor and pivot fields - SmartAnchorFields(); - SmartPivotField(); - - EditorGUILayout.Space(); - - // Rotation - m_RotationGUI.RotationField(targets.Any(x => ((x as RectTransform).drivenProperties & DrivenTransformProperties.Rotation) != 0)); - - // Scale - s_ScaleDisabledMask[0] = targets.Any(x => ((x as RectTransform).drivenProperties & DrivenTransformProperties.ScaleX) != 0); - s_ScaleDisabledMask[1] = targets.Any(x => ((x as RectTransform).drivenProperties & DrivenTransformProperties.ScaleY) != 0); - s_ScaleDisabledMask[2] = targets.Any(x => ((x as RectTransform).drivenProperties & DrivenTransformProperties.ScaleZ) != 0); - Vector3FieldWithDisabledMash(EditorGUILayout.GetControlRect(), m_LocalScale, styles.transformScaleContent, s_ScaleDisabledMask); - - serializedObject.ApplyModifiedProperties(); - } - - // A Vector3 field where each of the x, y and z elements can be disabled. - static void Vector3FieldWithDisabledMash(Rect position, SerializedProperty property, GUIContent label, bool[] disabledMask) - { - EditorGUI.BeginProperty(position, label, property); - - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, position); - position = EditorGUI.MultiFieldPrefixLabel(position, id, label, 3); - position.height = EditorGUIUtility.singleLineHeight; - SerializedProperty cur = property.Copy(); - cur.NextVisible(true); - EditorGUI.MultiPropertyField(position, s_XYZLabels, cur, EditorGUI.PropertyVisibility.OnlyVisible, EditorGUI.kMiniLabelW, disabledMask); - - EditorGUI.EndProperty(); - } - - private LayoutDropdownWindow m_DropdownWindow; - void LayoutDropdownButton(bool anyWithoutParent) - { - Rect dropdownPosition = GUILayoutUtility.GetRect(0, 0); - dropdownPosition.x += 2; - dropdownPosition.y += 17; - dropdownPosition.height = kDropdownSize; - dropdownPosition.width = kDropdownSize; - - using (new EditorGUI.DisabledScope(anyWithoutParent)) - { - Color oldColor = GUI.color; - GUI.color = new Color(1, 1, 1, 0.6f) * oldColor; - if (EditorGUI.DropdownButton(dropdownPosition, GUIContent.none, FocusType.Passive, "box")) - { - GUIUtility.keyboardControl = 0; - m_DropdownWindow = new LayoutDropdownWindow(serializedObject); - PopupWindow.Show(dropdownPosition, m_DropdownWindow, null, ShowMode.PopupMenuWithKeyboardFocus); - } - GUI.color = oldColor; - } - - if (!anyWithoutParent) - { - LayoutDropdownWindow.DrawLayoutMode(new RectOffset(7, 7, 7, 7).Remove(dropdownPosition), m_AnchorMin, m_AnchorMax, m_AnchoredPosition, m_SizeDelta); - LayoutDropdownWindow.DrawLayoutModeHeadersOutsideRect(dropdownPosition, m_AnchorMin, m_AnchorMax, m_AnchoredPosition, m_SizeDelta); - } - } - - void SmartPositionAndSizeFields(bool anyWithoutParent, bool anyDrivenX, bool anyDrivenY) - { - Rect rect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * 4); - - rect.height = EditorGUIUtility.singleLineHeight * 2; - Rect rect2; - - bool anyStretchX = targets.Any(x => (x as RectTransform).anchorMin.x != (x as RectTransform).anchorMax.x); - bool anyStretchY = targets.Any(x => (x as RectTransform).anchorMin.y != (x as RectTransform).anchorMax.y); - bool anyNonStretchX = targets.Any(x => (x as RectTransform).anchorMin.x == (x as RectTransform).anchorMax.x); - bool anyNonStretchY = targets.Any(x => (x as RectTransform).anchorMin.y == (x as RectTransform).anchorMax.y); - - rect2 = GetColumnRect(rect, 0); - if (anyNonStretchX || anyWithoutParent || anyDrivenX) - { - EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative("x")); - FloatFieldLabelAbove(rect2, - rectTransform => rectTransform.anchoredPosition.x, - (rectTransform, val) => rectTransform.anchoredPosition = new Vector2(val, rectTransform.anchoredPosition.y), - DrivenTransformProperties.AnchoredPositionX, - EditorGUIUtility.TrTextContent("Pos X")); - SetFadingBasedOnControlID(ref m_ChangingPosX, EditorGUIUtility.s_LastControlID); - EditorGUI.EndProperty(); - } - else - { - // Affected by both anchored position and size delta so do property handling for both. (E.g. showing animated value, prefab override etc.) - EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative("x")); - EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative("x")); - FloatFieldLabelAbove(rect2, - rectTransform => rectTransform.offsetMin.x, - (rectTransform, val) => rectTransform.offsetMin = new Vector2(val, rectTransform.offsetMin.y), - DrivenTransformProperties.None, - EditorGUIUtility.TrTextContent("Left")); - SetFadingBasedOnControlID(ref m_ChangingLeft, EditorGUIUtility.s_LastControlID); - EditorGUI.EndProperty(); - EditorGUI.EndProperty(); - } - - rect2 = GetColumnRect(rect, 1); - if (anyNonStretchY || anyWithoutParent || anyDrivenY) - { - EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative("y")); - FloatFieldLabelAbove(rect2, - rectTransform => rectTransform.anchoredPosition.y, - (rectTransform, val) => rectTransform.anchoredPosition = new Vector2(rectTransform.anchoredPosition.x, val), - DrivenTransformProperties.AnchoredPositionY, - EditorGUIUtility.TrTextContent("Pos Y")); - SetFadingBasedOnControlID(ref m_ChangingPosY, EditorGUIUtility.s_LastControlID); - EditorGUI.EndProperty(); - } - else - { - // Affected by both anchored position and size delta so do property handling for both. (E.g. showing animated value, prefab override etc.) - EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative("y")); - EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative("y")); - FloatFieldLabelAbove(rect2, - rectTransform => - rectTransform.offsetMax.y, - (rectTransform, val) => rectTransform.offsetMax = new Vector2(rectTransform.offsetMax.x, -val), - DrivenTransformProperties.None, - EditorGUIUtility.TrTextContent("Top")); - SetFadingBasedOnControlID(ref m_ChangingTop, EditorGUIUtility.s_LastControlID); - EditorGUI.EndProperty(); - EditorGUI.EndProperty(); - } - - rect2 = GetColumnRect(rect, 2); - EditorGUI.BeginProperty(rect2, null, m_LocalPositionZ); - FloatFieldLabelAbove(rect2, - rectTransform => rectTransform.transform.localPosition.z, - (rectTransform, val) => rectTransform.transform.localPosition = new Vector3(rectTransform.transform.localPosition.x, rectTransform.transform.localPosition.y, val), - DrivenTransformProperties.AnchoredPositionZ, - EditorGUIUtility.TrTextContent("Pos Z")); - EditorGUI.EndProperty(); - - rect.y += EditorGUIUtility.singleLineHeight * 2; - - rect2 = GetColumnRect(rect, 0); - if (anyNonStretchX || anyWithoutParent || anyDrivenX) - { - EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative("x")); - FloatFieldLabelAbove(rect2, - rectTransform => rectTransform.sizeDelta.x, - (rectTransform, val) => rectTransform.sizeDelta = new Vector2(val, rectTransform.sizeDelta.y), - DrivenTransformProperties.SizeDeltaX, - anyStretchX ? EditorGUIUtility.TrTextContent("W Delta") : new GUIContent("Width")); - SetFadingBasedOnControlID(ref m_ChangingWidth, EditorGUIUtility.s_LastControlID); - EditorGUI.EndProperty(); - } - else - { - // Affected by both anchored position and size delta so do property handling for both. (E.g. showing animated value, prefab override etc.) - EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative("x")); - EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative("x")); - FloatFieldLabelAbove(rect2, - rectTransform => - rectTransform.offsetMax.x, - (rectTransform, val) => rectTransform.offsetMax = new Vector2(-val, rectTransform.offsetMax.y), - DrivenTransformProperties.None, - EditorGUIUtility.TrTextContent("Right")); - SetFadingBasedOnControlID(ref m_ChangingRight, EditorGUIUtility.s_LastControlID); - EditorGUI.EndProperty(); - EditorGUI.EndProperty(); - } - - rect2 = GetColumnRect(rect, 1); - if (anyNonStretchY || anyWithoutParent || anyDrivenY) - { - EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative("y")); - FloatFieldLabelAbove(rect2, - rectTransform => rectTransform.sizeDelta.y, - (rectTransform, val) => rectTransform.sizeDelta = new Vector2(rectTransform.sizeDelta.x, val), - DrivenTransformProperties.SizeDeltaY, - anyStretchY ? EditorGUIUtility.TrTextContent("H Delta") : new GUIContent("Height")); - SetFadingBasedOnControlID(ref m_ChangingHeight, EditorGUIUtility.s_LastControlID); - EditorGUI.EndProperty(); - } - else - { - // Affected by both anchored position and size delta so do property handling for both. (E.g. showing animated value, prefab override etc.) - EditorGUI.BeginProperty(rect2, null, m_AnchoredPosition.FindPropertyRelative("y")); - EditorGUI.BeginProperty(rect2, null, m_SizeDelta.FindPropertyRelative("y")); - FloatFieldLabelAbove(rect2, - rectTransform => rectTransform.offsetMin.y, - (rectTransform, val) => rectTransform.offsetMin = new Vector2(rectTransform.offsetMin.x, val), - DrivenTransformProperties.None, - EditorGUIUtility.TrTextContent("Bottom")); - SetFadingBasedOnControlID(ref m_ChangingBottom, EditorGUIUtility.s_LastControlID); - EditorGUI.EndProperty(); - EditorGUI.EndProperty(); - } - - rect2 = rect; - rect2.height = EditorGUIUtility.singleLineHeight; - rect2.y += EditorGUIUtility.singleLineHeight; - rect2.yMin -= 2; - rect2.xMin = rect2.xMax - 26; - rect2.x -= rect2.width; - BlueprintButton(rect2); - - rect2.x += rect2.width; - RawButton(rect2); - } - - void SmartAnchorFields() - { - Rect anchorRect = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * (m_ShowLayoutOptions ? 3 : 1)); - anchorRect.height = EditorGUIUtility.singleLineHeight; - - EditorGUI.BeginChangeCheck(); - m_ShowLayoutOptions = EditorGUI.Foldout(anchorRect, m_ShowLayoutOptions, styles.anchorsContent); - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetBool(kShowAnchorPropsPrefName, m_ShowLayoutOptions); - - if (!m_ShowLayoutOptions) - return; - - EditorGUI.indentLevel++; - - anchorRect.y += EditorGUIUtility.singleLineHeight; - Vector2Field(anchorRect, - rectTransform => rectTransform.anchorMin.x, - (rectTransform, val) => SetAnchorSmart(rectTransform, val, 0, false, !m_RawEditMode, true), - rectTransform => rectTransform.anchorMin.y, - (rectTransform, val) => SetAnchorSmart(rectTransform, val, 1, false, !m_RawEditMode, true), - DrivenTransformProperties.AnchorMinX, - DrivenTransformProperties.AnchorMinY, - m_AnchorMin, - styles.anchorMinContent); - - anchorRect.y += EditorGUIUtility.singleLineHeight; - Vector2Field(anchorRect, - rectTransform => rectTransform.anchorMax.x, - (rectTransform, val) => SetAnchorSmart(rectTransform, val, 0, true, !m_RawEditMode, true), - rectTransform => rectTransform.anchorMax.y, - (rectTransform, val) => SetAnchorSmart(rectTransform, val, 1, true, !m_RawEditMode, true), - DrivenTransformProperties.AnchorMaxX, - DrivenTransformProperties.AnchorMaxY, - m_AnchorMax, - styles.anchorMaxContent); - - EditorGUI.indentLevel--; - } - - void SmartPivotField() - { - Vector2Field(EditorGUILayout.GetControlRect(), - rectTransform => rectTransform.pivot.x, - (rectTransform, val) => SetPivotSmart(rectTransform, val, 0, !m_RawEditMode, false), - rectTransform => rectTransform.pivot.y, - (rectTransform, val) => SetPivotSmart(rectTransform, val, 1, !m_RawEditMode, false), - DrivenTransformProperties.PivotX, - DrivenTransformProperties.PivotY, - m_Pivot, - styles.pivotContent); - } - - void RawButton(Rect position) - { - EditorGUI.BeginChangeCheck(); - m_RawEditMode = GUI.Toggle(position, m_RawEditMode, styles.rawEditContent, "ButtonRight"); - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetBool(kLockRectPrefName, m_RawEditMode); - } - - void BlueprintButton(Rect position) - { - EditorGUI.BeginChangeCheck(); - bool newValue = GUI.Toggle(position, Tools.rectBlueprintMode, styles.blueprintContent, "ButtonLeft"); - if (EditorGUI.EndChangeCheck()) - { - Tools.rectBlueprintMode = newValue; - Tools.RepaintAllToolViews(); - } - } - - void FloatFieldLabelAbove(Rect position, FloatGetter getter, FloatSetter setter, DrivenTransformProperties driven, GUIContent label) - { - using (new EditorGUI.DisabledScope(targets.Any(x => ((x as RectTransform).drivenProperties & driven) != 0))) - { - float value = getter(target as RectTransform); - EditorGUI.showMixedValue = targets.Select(x => getter(x as RectTransform)).Distinct().Count() >= 2; - - EditorGUI.BeginChangeCheck(); - - int id = GUIUtility.GetControlID(s_FloatFieldHash, FocusType.Keyboard, position); - Rect positionLabel = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight); - Rect positionField = new Rect(position.x, position.y + EditorGUIUtility.singleLineHeight, position.width, EditorGUIUtility.singleLineHeight); - EditorGUI.HandlePrefixLabel(position, positionLabel, label, id); - float newValue = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, positionField, positionLabel, id, value, EditorGUI.kFloatFieldFormatString, EditorStyles.textField, true); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObjects(targets, "Inspector"); - foreach (RectTransform tr in targets) - setter(tr, newValue); - } - } - } - - void Vector2Field(Rect position, - FloatGetter xGetter, FloatSetter xSetter, - FloatGetter yGetter, FloatSetter ySetter, - DrivenTransformProperties xDriven, DrivenTransformProperties yDriven, - SerializedProperty vec2Property, GUIContent label) - { - EditorGUI.BeginProperty(position, label, vec2Property); - - SerializedProperty xProperty = vec2Property.FindPropertyRelative("x"); - SerializedProperty yProperty = vec2Property.FindPropertyRelative("y"); - - EditorGUI.PrefixLabel(position, -1, label); - float t = EditorGUIUtility.labelWidth; - int l = EditorGUI.indentLevel; - Rect r0 = GetColumnRect(position, 0); - Rect r1 = GetColumnRect(position, 1); - EditorGUIUtility.labelWidth = EditorGUI.kMiniLabelW; - EditorGUI.indentLevel = 0; - - EditorGUI.BeginProperty(r0, s_XYLabels[0], xProperty); - FloatField(r0, xGetter, xSetter, xDriven, s_XYLabels[0]); - EditorGUI.EndProperty(); - - EditorGUI.BeginProperty(r0, s_XYLabels[1], yProperty); - FloatField(r1, yGetter, ySetter, yDriven, s_XYLabels[1]); - EditorGUI.EndProperty(); - - EditorGUIUtility.labelWidth = t; - EditorGUI.indentLevel = l; - - EditorGUI.EndProperty(); - } - - void FloatField(Rect position, FloatGetter getter, FloatSetter setter, DrivenTransformProperties driven, GUIContent label) - { - using (new EditorGUI.DisabledScope(targets.Any(x => ((x as RectTransform).drivenProperties & driven) != 0))) - { - float value = getter(target as RectTransform); - EditorGUI.showMixedValue = targets.Select(x => getter(x as RectTransform)).Distinct().Count() >= 2; - - EditorGUI.BeginChangeCheck(); - float newValue = EditorGUI.FloatField(position, label, value); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObjects(targets, "Inspector"); - foreach (RectTransform tr in targets) - setter(tr, newValue); - } - } - } - - Rect GetColumnRect(Rect totalRect, int column) - { - totalRect.xMin += EditorGUIUtility.labelWidth - 1; - Rect rect = totalRect; - rect.xMin += (totalRect.width - 4) * (column / 3f) + column * 2; - rect.width = (totalRect.width - 4) / 3f; - return rect; - } - - void DrawRect(Rect rect, Transform space, bool dotted) - { - Vector3 p0 = space.TransformPoint(new Vector2(rect.x, rect.y)); - Vector3 p1 = space.TransformPoint(new Vector2(rect.x, rect.yMax)); - Vector3 p2 = space.TransformPoint(new Vector2(rect.xMax, rect.yMax)); - Vector3 p3 = space.TransformPoint(new Vector2(rect.xMax, rect.y)); - if (!dotted) - { - Handles.DrawLine(p0, p1); - Handles.DrawLine(p1, p2); - Handles.DrawLine(p2, p3); - Handles.DrawLine(p3, p0); - } - else - { - RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, p0, p1, kDottedLineSize); - RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, p1, p2, kDottedLineSize); - RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, p2, p3, kDottedLineSize); - RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, p3, p0, kDottedLineSize); - } - } - - void OnSceneGUI() - { - RectTransform gui = target as RectTransform; - - Rect rectInOwnSpace = gui.rect; - Rect rectInUserSpace = rectInOwnSpace; - Rect rectInParentSpace = rectInOwnSpace; - Transform ownSpace = gui.transform; - Transform userSpace = ownSpace; - Transform parentSpace = ownSpace; - RectTransform guiParent = null; - if (ownSpace.parent != null) - { - parentSpace = ownSpace.parent; - rectInParentSpace.x += ownSpace.localPosition.x; - rectInParentSpace.y += ownSpace.localPosition.y; - - guiParent = parentSpace.GetComponent(); - } - - if (Tools.rectBlueprintMode) - { - userSpace = parentSpace; - rectInUserSpace = rectInParentSpace; - } - - // Show unrotated/unscaled rect if moving anchor/pivot - float alpha = Mathf.Max(m_ChangingAnchors.faded, m_ChangingPivot.faded); - // Also show when moving or resizing rect if anchors are scaling on either axis - if (gui.anchorMin != gui.anchorMax) - { - alpha = Mathf.Max(alpha, - m_ChangingPosX.faded, - m_ChangingPosY.faded, - m_ChangingLeft.faded, - m_ChangingRight.faded, - m_ChangingTop.faded, - m_ChangingBottom.faded); - } - - Color rectInParentSpaceColor = kRectInParentSpaceColor; - rectInParentSpaceColor.a *= alpha; - Handles.color = rectInParentSpaceColor; - DrawRect(rectInParentSpace, parentSpace, true); - - if (m_TargetCount == 1) - { - RectTransformSnapping.OnGUI(); - - if (guiParent != null) - AllAnchorsSceneGUI(gui, guiParent, parentSpace, ownSpace); - - DrawSizes(rectInUserSpace, userSpace, rectInParentSpace, parentSpace, gui, guiParent); - - RectTransformSnapping.DrawGuides(); - - if (Tools.current == Tool.Rect) - ParentRectPreviewDragHandles(guiParent, parentSpace); - } - } - - void ParentRectPreviewDragHandles(RectTransform gui, Transform space) - { - if (gui == null) - return; - - float size = 0.05f * HandleUtility.GetHandleSize(space.position); - Rect rect = gui.rect; - for (int xHandle = 0; xHandle <= 2; xHandle++) - { - for (int yHandle = 0; yHandle <= 2; yHandle++) - { - // Exactly one of the axes should be 1 - if ((xHandle == 1) == (yHandle == 1)) - continue; - - Vector3 curPos = Vector2.zero; - for (int axis = 0; axis < 2; axis++) - curPos[axis] = Mathf.Lerp(rect.min[axis], rect.max[axis], (axis == 0 ? xHandle : yHandle) * 0.5f); - curPos = space.TransformPoint(curPos); - - int id = GUIUtility.GetControlID(s_ParentRectPreviewHandlesHash, FocusType.Passive); - - Vector3 sideDir = (xHandle == 1 ? space.right * rect.width : space.up * rect.height); - Vector3 slideDir = (xHandle == 1 ? space.up : space.right); - - // could happen if gui.rect.{width,height} == 0 - if (sideDir == Vector3.zero) - continue; - - EditorGUI.BeginChangeCheck(); - Vector3 newPos = RectHandles.SideSlider(id, curPos, sideDir, slideDir, size, null, 0, -3); - if (EditorGUI.EndChangeCheck()) - { - Vector2 curPosInSpace = space.InverseTransformPoint(curPos); - Vector2 newPosInSpace = space.InverseTransformPoint(newPos); - Rect newRect = rect; - Vector2 offset = newPosInSpace - curPosInSpace; - if (xHandle == 0) - newRect.min = new Vector2(newRect.min.x + offset.x, newRect.min.y); - if (xHandle == 2) - newRect.max = new Vector2(newRect.max.x + offset.x, newRect.max.y); - if (yHandle == 0) - newRect.min = new Vector2(newRect.min.x, newRect.min.y + offset.y); - if (yHandle == 2) - newRect.max = new Vector2(newRect.max.x, newRect.max.y + offset.y); - SetTemporaryRect(gui, newRect, id); - } - - if (EditorGUIUtility.hotControl == id) - { - Handles.BeginGUI(); - EditorGUI.DropShadowLabel(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 60, 16), "Preview"); - Handles.EndGUI(); - } - } - } - } - - private static float s_ParentDragTime = 0; - private static float s_ParentDragId = 0; - private static Rect s_ParentDragOrigRect = new Rect(); - private static Rect s_ParentDragPreviewRect = new Rect(); - private static RectTransform s_ParentDragRectTransform = null; - void SetTemporaryRect(RectTransform gui, Rect rect, int id) - { - if (s_ParentDragRectTransform == null) - { - s_ParentDragRectTransform = gui; - s_ParentDragOrigRect = gui.rect; - s_ParentDragId = id; - } - else if (s_ParentDragRectTransform != gui) - { - return; - } - - s_ParentDragPreviewRect = rect; - s_ParentDragTime = Time.realtimeSinceStartup; - - InternalEditorUtility.SetRectTransformTemporaryRect(gui, rect); - - // Remove if it was already added so it's not added more than once. - EditorApplication.update -= UpdateTemporaryRect; - EditorApplication.update += UpdateTemporaryRect; - } - - void UpdateTemporaryRect() - { - if (s_ParentDragRectTransform == null) - return; - - if (EditorGUIUtility.hotControl == s_ParentDragId) - { - s_ParentDragTime = Time.realtimeSinceStartup; - Canvas.ForceUpdateCanvases(); - GameView.RepaintAll(); - return; - } - - float elapsed = Time.realtimeSinceStartup - s_ParentDragTime; - float lerp = Mathf.Clamp01(1 - elapsed * 8); - if (lerp > 0) - { - Rect r = new Rect(); - r.position = Vector2.Lerp(s_ParentDragOrigRect.position, s_ParentDragPreviewRect.position, lerp); - r.size = Vector2.Lerp(s_ParentDragOrigRect.size, s_ParentDragPreviewRect.size, lerp); - InternalEditorUtility.SetRectTransformTemporaryRect(s_ParentDragRectTransform, r); - } - else - { - InternalEditorUtility.SetRectTransformTemporaryRect(s_ParentDragRectTransform, new Rect()); - EditorApplication.update -= UpdateTemporaryRect; - s_ParentDragRectTransform = null; - } - Canvas.ForceUpdateCanvases(); - SceneView.RepaintAll(); - GameView.RepaintAll(); - } - - void AllAnchorsSceneGUI(RectTransform gui, RectTransform guiParent, Transform parentSpace, Transform transform) - { - Handles.color = kParentColor; - // Draw parent rect - DrawRect(guiParent.rect, parentSpace, false); - - // Draw sibling rects and anchors - Handles.color = kSiblingColor; - foreach (Transform tr in parentSpace) - { - if (!tr.gameObject.activeInHierarchy) - continue; - RectTransform sibling = tr.GetComponent(); - if (sibling) - { - Rect siblingRect = sibling.rect; - siblingRect.x += sibling.transform.localPosition.x; - siblingRect.y += sibling.transform.localPosition.y; - DrawRect(sibling.rect, sibling, false); - if (sibling != transform) - AnchorsSceneGUI(sibling, guiParent, parentSpace, false); - } - } - - // Draw anchors for RectTransform itself - Handles.color = kAnchorColor; - AnchorsSceneGUI(gui, guiParent, parentSpace, true); - } - - Vector3 GetAnchorLocal(RectTransform guiParent, Vector2 anchor) - { - return NormalizedToPointUnclamped(guiParent.rect, anchor); - } - - static Vector2 NormalizedToPointUnclamped(Rect rectangle, Vector2 normalizedRectCoordinates) - { - return new Vector2( - Mathf.LerpUnclamped(rectangle.x, rectangle.xMax, normalizedRectCoordinates.x), - Mathf.LerpUnclamped(rectangle.y, rectangle.yMax, normalizedRectCoordinates.y) - ); - } - - static bool AnchorAllowedOutsideParent(int axis, int minmax) - { - // Allow dragging outside if action key is held down (same key that disables snapping). - // Also allow when not dragging at all - for e.g. typing values into the Inspector. - if (EditorGUI.actionKey || EditorGUIUtility.hotControl == 0) - return true; - // Also allow if drag started outside of range to begin with. - float value = (minmax == 0 ? s_StartDragAnchorMin[axis] : s_StartDragAnchorMax[axis]); - return (value < -0.001f || value > 1.001f); - } - - void AnchorsSceneGUI(RectTransform gui, RectTransform guiParent, Transform parentSpace, bool interactive) - { - if (Event.current.type == EventType.MouseDown) - { - s_AnchorFusedState = AnchorFusedState.None; - if (gui.anchorMin == gui.anchorMax) - s_AnchorFusedState = AnchorFusedState.All; - else if (gui.anchorMin.x == gui.anchorMax.x) - s_AnchorFusedState = AnchorFusedState.Horizontal; - else if (gui.anchorMin.y == gui.anchorMax.y) - s_AnchorFusedState = AnchorFusedState.Vertical; - } - - // Handles for the four corners - AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 0, 0, GUIUtility.GetControlID(FocusType.Passive)); - AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 0, 1, GUIUtility.GetControlID(FocusType.Passive)); - AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 1, 0, GUIUtility.GetControlID(FocusType.Passive)); - AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 1, 1, GUIUtility.GetControlID(FocusType.Passive)); - - if (!interactive) - return; - - // Aditional handles for dragging multiple of the corners simultaneously. - // These are not drawn, so don't need to be done for non-interactive handles. - - // Get all ids always, regardless of whether the handles are done or not, - // to prevent id mismatch issues. - int idAll = GUIUtility.GetControlID(FocusType.Passive); - int idH1 = GUIUtility.GetControlID(FocusType.Passive); - int idH2 = GUIUtility.GetControlID(FocusType.Passive); - int idV1 = GUIUtility.GetControlID(FocusType.Passive); - int idV2 = GUIUtility.GetControlID(FocusType.Passive); - - if (s_AnchorFusedState == AnchorFusedState.All) - { - AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 2, 2, idAll); - } - if (s_AnchorFusedState == AnchorFusedState.Horizontal) - { - AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 2, 0, idH1); - AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 2, 1, idH2); - } - if (s_AnchorFusedState == AnchorFusedState.Vertical) - { - AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 0, 2, idV1); - AnchorSceneGUI(gui, guiParent, parentSpace, interactive, 1, 2, idV2); - } - } - - // Minmax here means: 0 = min, 1 = max, 2 = both at once - void AnchorSceneGUI(RectTransform gui, RectTransform guiParent, Transform parentSpace, bool interactive, int minmaxX, int minmaxY, int id) - { - Vector3 curPos = new Vector2(); - curPos.x = (minmaxX == 0 ? gui.anchorMin.x : gui.anchorMax.x); - curPos.y = (minmaxY == 0 ? gui.anchorMin.y : gui.anchorMax.y); - curPos = GetAnchorLocal(guiParent, curPos); - curPos = parentSpace.TransformPoint(curPos); - - float size = 0.05f * HandleUtility.GetHandleSize(curPos); - - if (minmaxX < 2) - curPos += parentSpace.right * size * (minmaxX * 2 - 1); - if (minmaxY < 2) - curPos += parentSpace.up * size * (minmaxY * 2 - 1); - - if (minmaxX < 2 && minmaxY < 2) - DrawAnchor(curPos, parentSpace.right * size * 2 * (minmaxX * 2 - 1), parentSpace.up * size * 2 * (minmaxY * 2 - 1)); - - if (!interactive) - return; - - Event evtCopy = new Event(Event.current); - - EditorGUI.BeginChangeCheck(); - Vector3 newPos = Handles.Slider2D(id, curPos, parentSpace.forward, parentSpace.right, parentSpace.up, size, (Handles.CapFunction)null, Vector2.zero); - - if (evtCopy.type == EventType.MouseDown && GUIUtility.hotControl == id) - { - s_DragAnchorsTogether = EditorGUI.actionKey; - s_StartDragAnchorMin = gui.anchorMin; - s_StartDragAnchorMax = gui.anchorMax; - RectTransformSnapping.CalculateAnchorSnapValues(parentSpace, gui.transform, gui, minmaxX, minmaxY); - } - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(gui, "Move Rectangle Anchors"); - Vector2 offset = parentSpace.InverseTransformVector(newPos - curPos); - for (int axis = 0; axis <= 1; axis++) - { - offset[axis] /= guiParent.rect.size[axis]; - - int minmaxForAxis = (axis == 0 ? minmaxX : minmaxY); - bool isMax = (minmaxForAxis == 1); - float old = isMax ? gui.anchorMax[axis] : gui.anchorMin[axis]; - float newValue = old + offset[axis]; - - // Constraint to valid values - float snappedValue = newValue; - if (!AnchorAllowedOutsideParent(axis, minmaxForAxis)) - snappedValue = Mathf.Clamp01(snappedValue); - if (minmaxForAxis == 0) - snappedValue = Mathf.Min(snappedValue, gui.anchorMax[axis]); - if (minmaxForAxis == 1) - snappedValue = Mathf.Max(snappedValue, gui.anchorMin[axis]); - - // Snap to sibling anchors - float snapSize = HandleUtility.GetHandleSize(newPos) * RectTransformSnapping.kSnapThreshold / guiParent.rect.size[axis]; - snapSize *= parentSpace.InverseTransformVector(axis == 0 ? Vector3.right : Vector3.up)[axis]; - snappedValue = RectTransformSnapping.SnapToGuides(snappedValue, snapSize, axis); - - bool snap = snappedValue != newValue; - newValue = snappedValue; - - if (minmaxForAxis == 2) - { - SetAnchorSmart(gui, newValue, axis, false, !evtCopy.shift, snap, false, s_DragAnchorsTogether); - SetAnchorSmart(gui, newValue, axis, true, !evtCopy.shift, snap, false, s_DragAnchorsTogether); - } - else - { - SetAnchorSmart(gui, newValue, axis, isMax, !evtCopy.shift, snap, true, s_DragAnchorsTogether); - } - EditorUtility.SetDirty(gui); - if (gui.drivenByObject != null) - RectTransform.SendReapplyDrivenProperties(gui); - } - } - - SetFadingBasedOnMouseDownUp(ref m_ChangingAnchors, evtCopy); - } - - static float Round(float value) { return Mathf.Floor(0.5f + value); } - static int RoundToInt(float value) { return Mathf.FloorToInt(0.5f + value); } - - void DrawSizes(Rect rectInUserSpace, Transform userSpace, Rect rectInParentSpace, Transform parentSpace, RectTransform gui, RectTransform guiParent) - { - float size = 0.05f * HandleUtility.GetHandleSize(parentSpace.position); - float alpha; - - bool stretchW = (gui.anchorMin.x != gui.anchorMax.x); - bool stretchH = (gui.anchorMin.y != gui.anchorMax.y); - - alpha = Mathf.Max( - m_ChangingPosX.faded, - m_ChangingLeft.faded, - m_ChangingRight.faded, - m_ChangingAnchors.faded); - DrawAnchorRect(parentSpace, gui, guiParent, 0, alpha); - - alpha = Mathf.Max( - m_ChangingPosY.faded, - m_ChangingTop.faded, - m_ChangingBottom.faded, - m_ChangingAnchors.faded); - DrawAnchorRect(parentSpace, gui, guiParent, 1, alpha); - - DrawAnchorDistances(parentSpace, gui, guiParent, size, m_ChangingAnchors.faded); - - if (stretchW) - { - DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 0, 1, m_ChangingLeft.faded); - DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 0, 2, m_ChangingRight.faded); - } - else - { - DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 0, 0, m_ChangingPosX.faded); - DrawSizeDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 0, m_ChangingWidth.faded); - } - - if (stretchH) - { - DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 1, 1, m_ChangingBottom.faded); - DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 1, 2, m_ChangingTop.faded); - } - else - { - DrawPositionDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 1, 0, m_ChangingPosY.faded); - DrawSizeDistances(userSpace, rectInParentSpace, parentSpace, gui, guiParent, size, 1, m_ChangingHeight.faded); - } - } - - void DrawSizeDistances(Transform userSpace, Rect rectInParentSpace, Transform parentSpace, RectTransform gui, RectTransform guiParent, float size, int axis, float alpha) - { - if (alpha <= 0) - return; - - Color col = kAnchorColor; - col.a *= alpha; - GUI.color = col; - - if (userSpace == gui.transform) - { - gui.GetWorldCorners(s_Corners); - } - else - { - gui.GetLocalCorners(s_Corners); - for (int i = 0; i < 4; i++) - { - s_Corners[i] += gui.transform.localPosition; - s_Corners[i] = userSpace.TransformPoint(s_Corners[i]); - } - } - - string str = gui.sizeDelta[axis].ToString(); - GUIContent label = new GUIContent(str); - Vector3 dir = (axis == 0 ? userSpace.up : userSpace.right) * size * 2; - DrawLabelBetweenPoints(s_Corners[0] + dir, s_Corners[axis == 0 ? 3 : 1] + dir, label); - } - - void DrawPositionDistances(Transform userSpace, Rect rectInParentSpace, Transform parentSpace, RectTransform gui, RectTransform guiParent, float size, int axis, int side, float alpha) - { - if (guiParent == null || alpha <= 0) - return; - - Color col = kAnchorLineColor; - col.a *= alpha; - Handles.color = col; - col = kAnchorColor; - col.a *= alpha; - GUI.color = col; - - Vector3 posA; - Vector3 posB; - float value; - if (side == 0) - { - Vector2 pivot = Rect.NormalizedToPoint(rectInParentSpace, gui.pivot); - posA = pivot; - posB = pivot; - posA[axis] = Mathf.LerpUnclamped(guiParent.rect.min[axis], guiParent.rect.max[axis], gui.anchorMin[axis]); - value = gui.anchoredPosition[axis]; - } - else - { - Vector2 center = rectInParentSpace.center; - posA = center; - posB = center; - if (side == 1) - { - posA[axis] = Mathf.LerpUnclamped(guiParent.rect.min[axis], guiParent.rect.max[axis], gui.anchorMin[axis]); - posB[axis] = rectInParentSpace.min[axis]; - value = gui.offsetMin[axis]; - } - else - { - posA[axis] = Mathf.LerpUnclamped(guiParent.rect.min[axis], guiParent.rect.max[axis], gui.anchorMax[axis]); - posB[axis] = rectInParentSpace.max[axis]; - value = -gui.offsetMax[axis]; - } - } - - posA = parentSpace.TransformPoint(posA); - posB = parentSpace.TransformPoint(posB); - - RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, posA, posB, kDottedLineSize); - GUIContent label = new GUIContent(value.ToString()); - DrawLabelBetweenPoints(posA, posB, label); - } - - void DrawAnchorDistances(Transform parentSpace, RectTransform gui, RectTransform guiParent, float size, float alpha) - { - if (guiParent == null || alpha <= 0) - return; - - Color col = kAnchorColor; - col.a *= alpha; - GUI.color = col; - - // Show percentages in Scene View while dragging anchors. - Vector3[,] points = new Vector3[2, 4]; - for (int axis = 0; axis < 2; axis++) - { - for (int i = 0; i < 4; i++) - { - Vector3 p = Vector3.zero; - switch (i) - { - case 0: p = Vector3.zero; break; - case 1: p = gui.anchorMin; break; - case 2: p = gui.anchorMax; break; - case 3: p = Vector3.one; break; - } - p[axis] = gui.anchorMin[axis]; - p = parentSpace.TransformPoint(GetAnchorLocal(guiParent, p)); - points[axis, i] = p; - } - } - - for (int axis = 0; axis < 2; axis++) - { - Vector3 dir = (axis == 0 ? parentSpace.right : parentSpace.up) * size * 2; - int startValue = RoundToInt((gui.anchorMin[1 - axis]) * 100); - int midValue = RoundToInt((gui.anchorMax[1 - axis] - gui.anchorMin[1 - axis]) * 100); - int endValue = RoundToInt((1 - gui.anchorMax[1 - axis]) * 100); - if (startValue > 0) - DrawLabelBetweenPoints(points[axis, 0] - dir, points[axis, 1] - dir, GUIContent.Temp(startValue.ToString() + "%")); - if (midValue > 0) - DrawLabelBetweenPoints(points[axis, 1] - dir, points[axis, 2] - dir, GUIContent.Temp(midValue.ToString() + "%")); - if (endValue > 0) - DrawLabelBetweenPoints(points[axis, 2] - dir, points[axis, 3] - dir, GUIContent.Temp(endValue.ToString() + "%")); - } - } - - void DrawAnchorRect(Transform parentSpace, RectTransform gui, RectTransform guiParent, int axis, float alpha) - { - if (guiParent == null || alpha <= 0) - return; - - Color col = kAnchorLineColor; - col.a *= alpha; - Handles.color = col; - - Vector3[,] points = new Vector3[2, 2]; - for (int side = 0; side < 2; side++) - { - if (side == 1 && gui.anchorMin[axis] == gui.anchorMax[axis]) - continue; - - points[side, 0][1 - axis] = Mathf.Min(0, gui.anchorMin[1 - axis]); - points[side, 1][1 - axis] = Mathf.Max(1, gui.anchorMax[1 - axis]); - for (int endpoint = 0; endpoint < 2; endpoint++) - { - points[side, endpoint][axis] = (side == 0 ? gui.anchorMin[axis] : gui.anchorMax[axis]); - points[side, endpoint] = parentSpace.TransformPoint(GetAnchorLocal(guiParent, points[side, endpoint])); - } - RectHandles.DrawDottedLineWithShadow(kShadowColor, kShadowOffset, points[side, 0], points[side, 1], kDottedLineSize); - } - } - - void DrawLabelBetweenPoints(Vector3 pA, Vector3 pB, GUIContent label) - { - if (pA == pB) - return; - - Vector2 vA = HandleUtility.WorldToGUIPoint(pA); - Vector2 vB = HandleUtility.WorldToGUIPoint(pB); - Vector2 center = (vA + vB) * 0.5f; - center.x = Round(center.x); - center.y = Round(center.y); - float angle = Mathf.Atan2(vB.y - vA.y, vB.x - vA.x) * Mathf.Rad2Deg; - angle = Mathf.Repeat(angle + 89f, 180f) - 89f; - - Handles.BeginGUI(); - Matrix4x4 oldMatrix = GUI.matrix; - - GUIStyle style = styles.measuringLabelStyle; - style.alignment = TextAnchor.MiddleCenter; - - GUIUtility.RotateAroundPivot(angle, center); - EditorGUI.DropShadowLabel(new Rect(center.x - 50, center.y - 9, 100, 16), label, style); - - GUI.matrix = oldMatrix; - Handles.EndGUI(); - } - - static Vector3 GetRectReferenceCorner(RectTransform gui, bool worldSpace) - { - if (worldSpace) - { - Transform t = gui.transform; - gui.GetWorldCorners(s_Corners); - if (t.parent) - return t.parent.InverseTransformPoint(s_Corners[0]); - else - return s_Corners[0]; - } - return (Vector3)gui.rect.min + gui.transform.localPosition; - } - - void DrawAnchor(Vector3 pos, Vector3 right, Vector3 up) - { - pos -= up * 0.5f; - pos -= right * 0.5f; - up *= 1.4f; - right *= 1.4f; - RectHandles.DrawPolyLineWithShadow(kShadowColor, kShadowOffset, - pos, - pos + up + right * 0.5f, - pos + right + up * 0.5f, - pos); - } - - public static void SetPivotSmart(RectTransform rect, float value, int axis, bool smart, bool parentSpace) - { - Vector3 cornerBefore = GetRectReferenceCorner(rect, !parentSpace); - - Vector2 rectPivot = rect.pivot; - rectPivot[axis] = value; - rect.pivot = rectPivot; - - if (smart) - { - Vector3 cornerAfter = GetRectReferenceCorner(rect, !parentSpace); - Vector3 cornerOffset = cornerAfter - cornerBefore; - rect.anchoredPosition -= (Vector2)cornerOffset; - - Vector3 pos = rect.transform.position; - pos.z -= cornerOffset.z; - rect.transform.position = pos; - } - } - - public static void SetAnchorSmart(RectTransform rect, float value, int axis, bool isMax, bool smart) - { - SetAnchorSmart(rect, value, axis, isMax, smart, false, false, false); - } - - public static void SetAnchorSmart(RectTransform rect, float value, int axis, bool isMax, bool smart, bool enforceExactValue) - { - SetAnchorSmart(rect, value, axis, isMax, smart, enforceExactValue, false, false); - } - - public static void SetAnchorSmart(RectTransform rect, float value, int axis, bool isMax, bool smart, bool enforceExactValue, bool enforceMinNoLargerThanMax, bool moveTogether) - { - RectTransform parent = null; - if (rect.transform.parent == null) - { - smart = false; - } - else - { - parent = rect.transform.parent.GetComponent(); - if (parent == null) - smart = false; - } - - bool clampToParent = !AnchorAllowedOutsideParent(axis, isMax ? 1 : 0); - if (clampToParent) - value = Mathf.Clamp01(value); - if (enforceMinNoLargerThanMax) - { - if (isMax) - value = Mathf.Max(value, rect.anchorMin[axis]); - else - value = Mathf.Min(value, rect.anchorMax[axis]); - } - - float offsetSizePixels = 0; - float offsetPositionPixels = 0; - if (smart) - { - float oldValue = isMax ? rect.anchorMax[axis] : rect.anchorMin[axis]; - - offsetSizePixels = (value - oldValue) * parent.rect.size[axis]; - - // Ensure offset is in whole pixels. - // Note: In this particular instance we want to use Mathf.Round (which rounds towards nearest even number) - // instead of Round from this class which always rounds down. - // This makes the position of rect more stable when their anchors are changed. - float roundingDelta = 0; - if (ShouldDoIntSnapping(rect)) - roundingDelta = Mathf.Round(offsetSizePixels) - offsetSizePixels; - offsetSizePixels += roundingDelta; - - if (!enforceExactValue) - { - value += roundingDelta / parent.rect.size[axis]; - - // Snap value to whole percent if close - if (Mathf.Abs(Round(value * 1000) - value * 1000) < 0.1f) - value = Round(value * 1000) * 0.001f; - - if (clampToParent) - value = Mathf.Clamp01(value); - if (enforceMinNoLargerThanMax) - { - if (isMax) - value = Mathf.Max(value, rect.anchorMin[axis]); - else - value = Mathf.Min(value, rect.anchorMax[axis]); - } - } - - if (moveTogether) - offsetPositionPixels = offsetSizePixels; - else - offsetPositionPixels = (isMax ? offsetSizePixels * rect.pivot[axis] : (offsetSizePixels * (1 - rect.pivot[axis]))); - } - - if (isMax) - { - Vector2 rectAnchorMax = rect.anchorMax; - rectAnchorMax[axis] = value; - rect.anchorMax = rectAnchorMax; - - Vector2 other = rect.anchorMin; - if (moveTogether) - other[axis] = s_StartDragAnchorMin[axis] + rectAnchorMax[axis] - s_StartDragAnchorMax[axis]; - rect.anchorMin = other; - } - else - { - Vector2 rectAnchorMin = rect.anchorMin; - rectAnchorMin[axis] = value; - rect.anchorMin = rectAnchorMin; - - Vector2 other = rect.anchorMax; - if (moveTogether) - other[axis] = s_StartDragAnchorMax[axis] + rectAnchorMin[axis] - s_StartDragAnchorMin[axis]; - rect.anchorMax = other; - } - - if (smart) - { - Vector2 rectPosition = rect.anchoredPosition; - rectPosition[axis] -= offsetPositionPixels; - rect.anchoredPosition = rectPosition; - - if (!moveTogether) - { - Vector2 rectSizeDelta = rect.sizeDelta; - rectSizeDelta[axis] += offsetSizePixels * (isMax ? -1 : 1); - rect.sizeDelta = rectSizeDelta; - } - } - } - } -} diff --git a/Editor/Mono/Inspector/RectTransformSnapping.cs b/Editor/Mono/Inspector/RectTransformSnapping.cs deleted file mode 100644 index 17f74ead62..0000000000 --- a/Editor/Mono/Inspector/RectTransformSnapping.cs +++ /dev/null @@ -1,387 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class SnapGuideCollection - { - private List currentGuides = null; - - private Dictionary> guides = new Dictionary>(); - - public void Clear() - { - guides.Clear(); - } - - public void AddGuide(SnapGuide guide) - { - List guideList; - if (!guides.TryGetValue(guide.value, out guideList)) - { - guideList = new List(); - guides.Add(guide.value, guideList); - } - guideList.Add(guide); - } - - public float SnapToGuides(float value, float snapDistance) - { - if (guides.Count == 0) - return value; - - KeyValuePair> snapPair = new KeyValuePair>(); - float closestDistance = Mathf.Infinity; - foreach (var kvp in guides) - { - float distance = Mathf.Abs(value - kvp.Key); - if (distance < closestDistance) - { - snapPair = kvp; - closestDistance = distance; - } - } - if (closestDistance <= snapDistance) - { - value = snapPair.Key; - currentGuides = snapPair.Value; - } - else - { - currentGuides = null; - } - return value; - } - - public void OnGUI() - { - if (Event.current.type == EventType.MouseUp) - currentGuides = null; - } - - public void DrawGuides() - { - if (currentGuides != null) - foreach (SnapGuide guide in currentGuides) - guide.Draw(); - } - } - - internal class SnapGuide - { - public float value; - public List lineVertices = new List(); - public bool safe = true; - - public SnapGuide(float value, params Vector3[] vertices) : this(value, true, vertices) {} - - public SnapGuide(float value, bool safe, params Vector3[] vertices) - { - this.value = value; - this.lineVertices.AddRange(vertices); - this.safe = safe; - } - - public void Draw() - { - Handles.color = safe ? new Color(0.0f, 0.5f, 1.0f, 1.0f) : new Color(1.0f, 0.5f, 0.0f, 1.0f); - for (int i = 0; i < lineVertices.Count; i += 2) - { - Vector3 v1 = lineVertices[i]; - Vector3 v2 = lineVertices[i + 1]; - if (v1 == v2) - continue; - Vector3 dir = (v2 - v1).normalized * 0.05f; - v1 -= dir * HandleUtility.GetHandleSize(v1); - v2 += dir * HandleUtility.GetHandleSize(v2); - Handles.DrawLine(v1, v2); - } - } - } - - internal class RectTransformSnapping - { - internal const float kSnapThreshold = 0.05f; - private static SnapGuideCollection[] s_SnapGuides = new SnapGuideCollection[] { new SnapGuideCollection(), new SnapGuideCollection() }; - private static float[] kSidesAndMiddle = new float[] { 0, 0.5f, 1 }; - private static Vector3[] s_Corners = new Vector3[4]; - - internal static void OnGUI() - { - s_SnapGuides[0].OnGUI(); - s_SnapGuides[1].OnGUI(); - } - - internal static void DrawGuides() - { - if (EditorGUI.actionKey) - return; - - s_SnapGuides[0].DrawGuides(); - s_SnapGuides[1].DrawGuides(); - } - - static Vector3 GetInterpolatedCorner(Vector3[] corners, int mainAxis, float alongMainAxis, float alongOtherAxis) - { - if (mainAxis != 0) - { - float temp = alongMainAxis; - alongMainAxis = alongOtherAxis; - alongOtherAxis = temp; - } - return corners[0] * (1 - alongMainAxis) * (1 - alongOtherAxis) - + corners[1] * (1 - alongMainAxis) * (alongOtherAxis) - + corners[3] * (alongMainAxis) * (1 - alongOtherAxis) - + corners[2] * (alongMainAxis) * (alongOtherAxis); - } - - internal static void CalculatePivotSnapValues(Rect rect, Vector3 pivot, Quaternion rotation) - { - for (int axis = 0; axis < 2; axis++) - { - s_SnapGuides[axis].Clear(); - - // Snap to min, center, and max - for (int i = 0; i < kSidesAndMiddle.Length; i++) - s_SnapGuides[axis].AddGuide(new SnapGuide(kSidesAndMiddle[i], GetGuideLineForRect(rect, pivot, rotation, axis, kSidesAndMiddle[i]))); - } - } - - internal static void CalculateAnchorSnapValues(Transform parentSpace, Transform self, RectTransform gui, int minmaxX, int minmaxY) - { - for (int axis = 0; axis < 2; axis++) - { - s_SnapGuides[axis].Clear(); - - // Snap to edges of parent - RectTransform parentRect = parentSpace.GetComponent(); - parentRect.GetWorldCorners(s_Corners); - for (int i = 0; i < kSidesAndMiddle.Length; i++) - { - float val = kSidesAndMiddle[i]; - s_SnapGuides[axis].AddGuide(new SnapGuide(val, - GetInterpolatedCorner(s_Corners, axis, val, 0), - GetInterpolatedCorner(s_Corners, axis, val, 1))); - } - - // Snap to sibling anchor values - foreach (Transform tr in parentSpace) - { - if (tr == self) - continue; - RectTransform sibling = tr.GetComponent(); - if (sibling) - { - s_SnapGuides[axis].AddGuide(new SnapGuide(sibling.anchorMin[axis])); - s_SnapGuides[axis].AddGuide(new SnapGuide(sibling.anchorMax[axis])); - } - } - - // Snap to own opposite anchor values - int minmax = (axis == 0 ? minmaxX : minmaxY); - if (minmax == 0) - s_SnapGuides[axis].AddGuide(new SnapGuide(gui.anchorMax[axis])); - if (minmax == 1) - s_SnapGuides[axis].AddGuide(new SnapGuide(gui.anchorMin[axis])); - } - } - - // handle values are: 0 = min, 1 = middle, 2 = max - internal static void CalculateOffsetSnapValues(Transform parentSpace, Transform self, RectTransform parentRect, RectTransform rect, int xHandle, int yHandle) - { - for (int axis = 0; axis < 2; axis++) - s_SnapGuides[axis].Clear(); - - if (parentSpace == null) - return; - - List guides; - for (int axis = 0; axis < 2; axis++) - { - int handle = (axis == 0 ? xHandle : yHandle); - if (handle == 1) - continue; - - guides = GetSnapGuides(parentSpace, self, parentRect, rect, axis, handle); - foreach (SnapGuide guide in guides) - { - s_SnapGuides[axis].AddGuide(guide); - } - } - } - - internal static void CalculatePositionSnapValues(Transform parentSpace, Transform self, RectTransform parentRect, RectTransform rect) - { - for (int axis = 0; axis < 2; axis++) - s_SnapGuides[axis].Clear(); - - if (parentSpace == null) - return; - - List guides; - for (int axis = 0; axis < 2; axis++) - { - for (int side = 0; side < kSidesAndMiddle.Length; side++) - { - guides = GetSnapGuides(parentSpace, self, parentRect, rect, axis, side); - foreach (SnapGuide guide in guides) - { - guide.value = GetGuideValueForRect(rect, guide.value, axis, kSidesAndMiddle[side]); - s_SnapGuides[axis].AddGuide(guide); - } - } - } - } - - // side is: 0 = min, 1 = middle, 2 = max - private static List GetSnapGuides(Transform parentSpace, Transform self, RectTransform parentRect, RectTransform rect, int axis, int side) - { - List guides = new List(); - - // For snapping we have a concept of safe and unsafe snapping. - // - Safe snapping means the objects will remain aligned when the parent rect changes size. - // - Unsafe snapping means that the objects are aligned right now, but will no longer be aligned - // if the parent rect changes size because of different anchoring. - - if (parentRect != null) - { - float val = kSidesAndMiddle[side]; - - // Snap min side to min anchor, center to center point, max side to max anchor - this is always safe - float normalized = Mathf.Lerp(rect.anchorMin[axis], rect.anchorMax[axis], val); - guides.Add(new SnapGuide(normalized * parentRect.rect.size[axis], - GetGuideLineForRect(parentRect, axis, normalized))); - - // Snap to sides and center of the parent rect (if not the same as the anchor). - // This snapping is not safe. - float anchorVal = Mathf.Lerp(rect.anchorMin[axis], rect.anchorMax[axis], val); - if (val != anchorVal) - { - guides.Add(new SnapGuide(val * parentRect.rect.size[axis], false, - GetGuideLineForRect(parentRect, axis, val))); - } - } - - // Snap to siblings - foreach (Transform tr in parentSpace) - { - if (tr == self) - continue; - RectTransform sibling = tr.GetComponent(); - bool safe = true; - if (sibling) - { - if (side == 0) - { - // Snap min to min side - // This is safe if both objects have the same min anchor. - safe = (sibling.anchorMin[axis] == rect.anchorMin[axis]); - guides.Add(new SnapGuide(sibling.GetRectInParentSpace().min[axis], safe, - GetGuideLineForRect(sibling, axis, 0))); - - // Snap min to max side - // This is safe if min anchor of this object is equal to max anchor of the sibling. - safe = (sibling.anchorMax[axis] == rect.anchorMin[axis]); - guides.Add(new SnapGuide(sibling.GetRectInParentSpace().max[axis], safe, - GetGuideLineForRect(sibling, axis, 1))); - } - - if (side == 2) - { - // Snap max to max side - // This is safe if both objects have the same max anchor. - safe = (sibling.anchorMax[axis] == rect.anchorMax[axis]); - guides.Add(new SnapGuide(sibling.GetRectInParentSpace().max[axis], safe, - GetGuideLineForRect(sibling, axis, 1))); - - // Snap max to min side - // This is safe if max anchor of this object is equal to min anchor of the sibling. - safe = (sibling.anchorMin[axis] == rect.anchorMax[axis]); - guides.Add(new SnapGuide(sibling.GetRectInParentSpace().min[axis], safe, - GetGuideLineForRect(sibling, axis, 0))); - } - - if (side == 1) - { - // Snap middle to middle - // This is safe if the difference between the min anchors is the opposite of the difference between the max anchors. - // This also includes the case where both objects have the same min and max anchors. - safe = (sibling.anchorMin[axis] - rect.anchorMin[axis] == -(sibling.anchorMax[axis] - rect.anchorMax[axis])); - guides.Add(new SnapGuide(sibling.GetRectInParentSpace().center[axis], safe, - GetGuideLineForRect(sibling, axis, 0.5f))); - } - } - } - - return guides; - } - - private static Vector3[] GetGuideLineForRect(RectTransform rect, int axis, float side) - { - Vector3[] points = new Vector3[2]; - - // Set end points of line on other axis - points[0][1 - axis] = rect.rect.min[1 - axis]; - points[1][1 - axis] = rect.rect.max[1 - axis]; - - // Set position of line on axis - points[0][axis] = Mathf.Lerp(rect.rect.min[axis], rect.rect.max[axis], side); - points[1][axis] = points[0][axis]; - - // Transform to world space - points[0] = rect.transform.TransformPoint(points[0]); - points[1] = rect.transform.TransformPoint(points[1]); - - return points; - } - - private static Vector3[] GetGuideLineForRect(Rect rect, Vector3 pivot, Quaternion rotation, int axis, float side) - { - Vector3[] points = new Vector3[2]; - - // Set end points of line on other axis - points[0][1 - axis] = rect.min[1 - axis]; - points[1][1 - axis] = rect.max[1 - axis]; - - // Set position of line on axis - points[0][axis] = Mathf.Lerp(rect.min[axis], rect.max[axis], side); - points[1][axis] = points[0][axis]; - - // Transform to world space - points[0] = rotation * points[0] + pivot; - points[1] = rotation * points[1] + pivot; - - return points; - } - - private static float GetGuideValueForRect(RectTransform rect, float value, int axis, float side) - { - RectTransform parentRect = rect.transform.parent.GetComponent(); - float parentSize = parentRect ? parentRect.rect.size[axis] : 0; - float anchorReference = Mathf.Lerp(rect.anchorMin[axis], rect.anchorMax[axis], rect.pivot[axis]) * parentSize; - float positionRelativeToSide = rect.rect.size[axis] * (rect.pivot[axis] - side); - return value - anchorReference + positionRelativeToSide; - } - - internal static Vector2 SnapToGuides(Vector2 value, Vector2 snapDistance) - { - return new Vector2( - SnapToGuides(value.x, snapDistance.x, 0), - SnapToGuides(value.y, snapDistance.y, 1) - ); - } - - internal static float SnapToGuides(float value, float snapDistance, int axis) - { - if (EditorGUI.actionKey) - return value; - - SnapGuideCollection guides = (axis == 0 ? s_SnapGuides[0] : s_SnapGuides[1]); - return guides.SnapToGuides(value, snapDistance); - } - } -} diff --git a/Editor/Mono/Inspector/ReflectionProbeEditor.cs b/Editor/Mono/Inspector/ReflectionProbeEditor.cs deleted file mode 100644 index f6a85571f8..0000000000 --- a/Editor/Mono/Inspector/ReflectionProbeEditor.cs +++ /dev/null @@ -1,816 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.AnimatedValues; -using UnityEditor.IMGUI.Controls; -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.Experimental.Rendering; -using UnityEngine.Rendering; -using UnityEngine.SceneManagement; - -namespace UnityEditor -{ - [CustomEditor(typeof(ReflectionProbe))] - [CanEditMultipleObjects] - internal class ReflectionProbeEditor : Editor - { - static ReflectionProbeEditor s_LastInteractedEditor; - - SerializedProperty m_Mode; - SerializedProperty m_RefreshMode; - SerializedProperty m_TimeSlicingMode; - SerializedProperty m_Resolution; - SerializedProperty m_ShadowDistance; - SerializedProperty m_Importance; - SerializedProperty m_BoxSize; - SerializedProperty m_BoxOffset; - SerializedProperty m_CullingMask; - SerializedProperty m_ClearFlags; - SerializedProperty m_BackgroundColor; - SerializedProperty m_HDR; - SerializedProperty m_BoxProjection; - SerializedProperty m_IntensityMultiplier; - SerializedProperty m_BlendDistance; - SerializedProperty m_CustomBakedTexture; - SerializedProperty m_RenderDynamicObjects; - SerializedProperty m_UseOcclusionCulling; - - SerializedProperty[] m_NearAndFarProperties; - - private static Mesh s_SphereMesh; - private Material m_ReflectiveMaterial; - private Matrix4x4 m_OldLocalSpace = Matrix4x4.identity; - private float m_MipLevelPreview = 0.0F; - - private BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle(); - - private Hashtable m_CachedGizmoMaterials = new Hashtable(); - - public static void GetResolutionArray(ref int[] resolutionList, ref GUIContent[] resolutionStringList) - { - if (Styles.reflectionResolutionValuesArray == null && Styles.reflectionResolutionTextArray == null) - { - int cubemapResolution = Mathf.Max(1, ReflectionProbe.minBakedCubemapResolution); - - List envReflectionResolutionValues = new List(); - List envReflectionResolutionText = new List(); - - do - { - envReflectionResolutionValues.Add(cubemapResolution); - envReflectionResolutionText.Add(new GUIContent(cubemapResolution.ToString())); - cubemapResolution *= 2; - } - while (cubemapResolution <= ReflectionProbe.maxBakedCubemapResolution); - - Styles.reflectionResolutionValuesArray = envReflectionResolutionValues.ToArray(); - Styles.reflectionResolutionTextArray = envReflectionResolutionText.ToArray(); - } - - resolutionList = Styles.reflectionResolutionValuesArray; - resolutionStringList = Styles.reflectionResolutionTextArray; - } - - static internal class Styles - { - static Styles() - { - richTextMiniLabel.richText = true; - } - - public static GUIStyle richTextMiniLabel = new GUIStyle(EditorStyles.miniLabel); - - public static string bakeButtonText = "Bake"; - public static string[] bakeCustomOptionText = {"Bake as new Cubemap..."}; - public static string[] bakeButtonsText = {"Bake All Reflection Probes"}; - - public static GUIContent bakeCustomButtonText = EditorGUIUtility.TrTextContent("Bake", "Bakes Reflection Probe's cubemap, overwriting the existing cubemap texture asset (if any)."); - public static GUIContent runtimeSettingsHeader = EditorGUIUtility.TrTextContent("Runtime settings", "These settings are used by objects when they render with the cubemap of this probe"); - public static GUIContent backgroundColorText = EditorGUIUtility.TrTextContent("Background", "Camera clears the screen to this color before rendering."); - public static GUIContent clearFlagsText = EditorGUIUtility.TrTextContent("Clear Flags"); - public static GUIContent intensityText = EditorGUIUtility.TrTextContent("Intensity"); - public static GUIContent resolutionText = EditorGUIUtility.TrTextContent("Resolution"); - public static GUIContent captureCubemapHeaderText = EditorGUIUtility.TrTextContent("Cubemap capture settings"); - public static GUIContent boxProjectionText = EditorGUIUtility.TrTextContent("Box Projection", "Box projection causes reflections to appear to change based on the object's position within the probe's box, while still using a single probe as the source of the reflection. This works well for reflections on objects that are moving through enclosed spaces such as corridors and rooms. Setting box projection to False and the cubemap reflection will be treated as coming from infinitely far away. Note that this feature can be globally disabled from Graphics Settings -> Tier Settings"); - public static GUIContent blendDistanceText = EditorGUIUtility.TrTextContent("Blend Distance", "Area around the probe where it is blended with other probes. Only used in deferred probes."); - 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."); - 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."); - public static GUIContent customCubemapText = EditorGUIUtility.TrTextContent("Cubemap"); - public static GUIContent importanceText = EditorGUIUtility.TrTextContent("Importance"); - public static GUIContent renderDynamicObjects = EditorGUIUtility.TrTextContent("Dynamic Objects", "If enabled dynamic objects are also rendered into the cubemap"); - 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"); - public static GUIContent refreshMode = EditorGUIUtility.TrTextContent("Refresh Mode", "Controls how this probe refreshes in the Player"); - - public static GUIContent typeText = EditorGUIUtility.TrTextContent("Type", "'Baked Cubemap' uses the 'Auto Baking' mode from the Lighting window. If it is enabled then baking is automatic otherwise manual bake is needed (use the bake button below). \n'Custom' can be used if a custom cubemap is wanted. \n'Realtime' can be used to dynamically re-render the cubemap during runtime (via scripting)."); - public static GUIContent[] reflectionProbeMode = { EditorGUIUtility.TrTextContent("Baked"), EditorGUIUtility.TrTextContent("Custom"), EditorGUIUtility.TrTextContent("Realtime") }; - public static int[] reflectionProbeModeValues = { (int)ReflectionProbeMode.Baked, (int)ReflectionProbeMode.Custom, (int)ReflectionProbeMode.Realtime }; - - public static int[] reflectionResolutionValuesArray = null; - public static GUIContent[] reflectionResolutionTextArray = null; - - public static GUIContent[] clearFlags = - { - EditorGUIUtility.TrTextContent("Skybox"), - EditorGUIUtility.TrTextContent("Solid Color") - }; - public static int[] clearFlagsValues = { 1, 2 }; // taken from Camera.h - - public static GUIContent[] toolContents = - { - PrimitiveBoundsHandle.editModeButton, - EditorGUIUtility.TrIconContent("MoveTool", "Move the selected objects.") - }; - public static EditMode.SceneViewEditMode[] sceneViewEditModes = new[] - { - EditMode.SceneViewEditMode.ReflectionProbeBox, - EditMode.SceneViewEditMode.ReflectionProbeOrigin - }; - - public static string baseSceneEditingToolText = "Probe Scene Editing Mode: "; - public static GUIContent[] toolNames = - { - new GUIContent(baseSceneEditingToolText + "Box Projection Bounds", ""), - new GUIContent(baseSceneEditingToolText + "Probe Origin", "") - }; - } // end of class Styles - - // Should match reflection probe gizmo color in GizmoDrawers.cpp! - internal static Color kGizmoReflectionProbe = new Color(0xFF / 255f, 0xE5 / 255f, 0x94 / 255f, 0x80 / 255f); - internal static Color kGizmoReflectionProbeDisabled = new Color(0x99 / 255f, 0x89 / 255f, 0x59 / 255f, 0x60 / 255f); - internal static Color kGizmoHandleReflectionProbe = new Color(0xFF / 255f, 0xE5 / 255f, 0xAA / 255f, 0xFF / 255f); - - - readonly AnimBool m_ShowProbeModeRealtimeOptions = new AnimBool(); // p.mode == ReflectionProbeMode.Realtime; Will be brought back in 5.1 - readonly AnimBool m_ShowProbeModeCustomOptions = new AnimBool(); - readonly AnimBool m_ShowBoxOptions = new AnimBool(); - - private TextureInspector m_CubemapEditor = null; - - bool IsReflectionProbeEditMode(EditMode.SceneViewEditMode editMode) - { - return editMode == EditMode.SceneViewEditMode.ReflectionProbeBox || - editMode == EditMode.SceneViewEditMode.ReflectionProbeOrigin; - } - - bool sceneViewEditing - { - get { return IsReflectionProbeEditMode(EditMode.editMode) && EditMode.IsOwner(this); } - } - - public void OnEnable() - { - m_Mode = serializedObject.FindProperty("m_Mode"); - m_RefreshMode = serializedObject.FindProperty("m_RefreshMode"); - m_TimeSlicingMode = serializedObject.FindProperty("m_TimeSlicingMode"); - - m_Resolution = serializedObject.FindProperty("m_Resolution"); - m_NearAndFarProperties = new[] { serializedObject.FindProperty("m_NearClip"), serializedObject.FindProperty("m_FarClip") }; - m_ShadowDistance = serializedObject.FindProperty("m_ShadowDistance"); - m_Importance = serializedObject.FindProperty("m_Importance"); - m_BoxSize = serializedObject.FindProperty("m_BoxSize"); - m_BoxOffset = serializedObject.FindProperty("m_BoxOffset"); - m_CullingMask = serializedObject.FindProperty("m_CullingMask"); - m_ClearFlags = serializedObject.FindProperty("m_ClearFlags"); - m_BackgroundColor = serializedObject.FindProperty("m_BackGroundColor"); - m_HDR = serializedObject.FindProperty("m_HDR"); - m_BoxProjection = serializedObject.FindProperty("m_BoxProjection"); - m_IntensityMultiplier = serializedObject.FindProperty("m_IntensityMultiplier"); - m_BlendDistance = serializedObject.FindProperty("m_BlendDistance"); - m_CustomBakedTexture = serializedObject.FindProperty("m_CustomBakedTexture"); - m_RenderDynamicObjects = serializedObject.FindProperty("m_RenderDynamicObjects"); - m_UseOcclusionCulling = serializedObject.FindProperty("m_UseOcclusionCulling"); - - ReflectionProbe p = target as ReflectionProbe; - m_ShowProbeModeRealtimeOptions.valueChanged.AddListener(Repaint); - m_ShowProbeModeCustomOptions.valueChanged.AddListener(Repaint); - m_ShowBoxOptions.valueChanged.AddListener(Repaint); - m_ShowProbeModeRealtimeOptions.value = p.mode == ReflectionProbeMode.Realtime; - m_ShowProbeModeCustomOptions.value = p.mode == ReflectionProbeMode.Custom; - m_ShowBoxOptions.value = true; - - m_BoundsHandle.handleColor = kGizmoHandleReflectionProbe; - m_BoundsHandle.wireframeColor = Color.clear; - - UpdateOldLocalSpace(); - SceneView.onPreSceneGUIDelegate += OnPreSceneGUICallback; - } - - public void OnDisable() - { - SceneView.onPreSceneGUIDelegate -= OnPreSceneGUICallback; - - DestroyImmediate(m_ReflectiveMaterial); - DestroyImmediate(m_CubemapEditor); - - foreach (Material mat in m_CachedGizmoMaterials.Values) - DestroyImmediate(mat); - m_CachedGizmoMaterials.Clear(); - } - - private bool IsCollidingWithOtherProbes(string targetPath, ReflectionProbe targetProbe, out ReflectionProbe collidingProbe) - { - ReflectionProbe[] probes = FindObjectsOfType().ToArray(); - collidingProbe = null; - foreach (var probe in probes) - { - if (probe == targetProbe || probe.customBakedTexture == null) - continue; - string path = AssetDatabase.GetAssetPath(probe.customBakedTexture); - if (path == targetPath) - { - collidingProbe = probe; - return true; - } - } - return false; - } - - private void BakeCustomReflectionProbe(ReflectionProbe probe, bool usePreviousAssetPath) - { - string path = ""; - if (usePreviousAssetPath) - path = AssetDatabase.GetAssetPath(probe.customBakedTexture); - - string targetExtension = probe.hdr ? "exr" : "png"; - if (string.IsNullOrEmpty(path) || Path.GetExtension(path) != "." + targetExtension) - { - // We use the path of the active scene as the target path - string targetPath = FileUtil.GetPathWithoutExtension(SceneManager.GetActiveScene().path); - if (string.IsNullOrEmpty(targetPath)) - targetPath = "Assets"; - else if (Directory.Exists(targetPath) == false) - Directory.CreateDirectory(targetPath); - - string fileName = probe.name + (probe.hdr ? "-reflectionHDR" : "-reflection") + "." + targetExtension; - fileName = Path.GetFileNameWithoutExtension(AssetDatabase.GenerateUniqueAssetPath(Path.Combine(targetPath, fileName))); - - path = EditorUtility.SaveFilePanelInProject("Save reflection probe's cubemap.", fileName, targetExtension, "", targetPath); - if (string.IsNullOrEmpty(path)) - return; - - ReflectionProbe collidingProbe; - if (IsCollidingWithOtherProbes(path, probe, out collidingProbe)) - { - if (!EditorUtility.DisplayDialog("Cubemap is used by other reflection probe", - string.Format("'{0}' path is used by the game object '{1}', do you really want to overwrite it?", - path, collidingProbe.name), "Yes", "No")) - { - return; - } - } - } - - EditorUtility.DisplayProgressBar("Reflection Probes", "Baking " + path, 0.5f); - if (!Lightmapping.BakeReflectionProbe(probe, path)) - Debug.LogError("Failed to bake reflection probe to " + path); - EditorUtility.ClearProgressBar(); - } - - private void OnBakeCustomButton(object data) - { - int mode = (int)data; - - ReflectionProbe p = target as ReflectionProbe; - if (mode == 0) - BakeCustomReflectionProbe(p, false); - } - - private void OnBakeButton(object data) - { - int mode = (int)data; - if (mode == 0) - Lightmapping.BakeAllReflectionProbesSnapshots(); - } - - ReflectionProbe reflectionProbeTarget - { - get { return (ReflectionProbe)target; } - } - - void DoBakeButton() - { - if (reflectionProbeTarget.mode == ReflectionProbeMode.Realtime) - { - EditorGUILayout.HelpBox("Baking of this reflection probe should be initiated from the scripting API because the type is 'Realtime'", MessageType.Info); - - if (!QualitySettings.realtimeReflectionProbes) - EditorGUILayout.HelpBox("Realtime reflection probes are disabled in Quality Settings", MessageType.Warning); - return; - } - - if (reflectionProbeTarget.mode == ReflectionProbeMode.Baked && Lightmapping.giWorkflowMode != Lightmapping.GIWorkflowMode.OnDemand) - { - EditorGUILayout.HelpBox("Baking of this reflection probe is automatic because this probe's type is 'Baked' and the Lighting window is using 'Auto Baking'. The cubemap created is stored in the GI cache.", MessageType.Info); - return; - } - - GUILayout.BeginHorizontal(); - - GUILayout.Space(EditorGUIUtility.labelWidth); - switch (reflectionProbeMode) - { - case ReflectionProbeMode.Custom: - if (EditorGUI.ButtonWithDropdownList(Styles.bakeCustomButtonText, Styles.bakeCustomOptionText, OnBakeCustomButton)) - { - BakeCustomReflectionProbe(reflectionProbeTarget, true); - GUIUtility.ExitGUI(); - } - break; - - case ReflectionProbeMode.Baked: - using (new EditorGUI.DisabledScope(!reflectionProbeTarget.enabled)) - { - // Bake button in non-continous mode - if (EditorGUI.ButtonWithDropdownList(Styles.bakeButtonText, Styles.bakeButtonsText, OnBakeButton)) - { - Lightmapping.BakeReflectionProbeSnapshot(reflectionProbeTarget); - GUIUtility.ExitGUI(); - } - } - - break; - - case ReflectionProbeMode.Realtime: - // Not showing bake button in realtime - break; - } - - GUILayout.EndHorizontal(); - } - - void DoToolbar() - { - // Show the master tool selector - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - GUI.changed = false; - var oldEditMode = EditMode.editMode; - - EditorGUI.BeginChangeCheck(); - EditMode.DoInspectorToolbar(Styles.sceneViewEditModes, Styles.toolContents, this); - if (EditorGUI.EndChangeCheck()) - s_LastInteractedEditor = this; - - if (oldEditMode != EditMode.editMode) - { - switch (EditMode.editMode) - { - case EditMode.SceneViewEditMode.ReflectionProbeOrigin: - UpdateOldLocalSpace(); - break; - } - if (Toolbar.get != null) - Toolbar.get.Repaint(); - } - - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - - // Info box for tools - GUILayout.BeginVertical(EditorStyles.helpBox); - string helpText = Styles.baseSceneEditingToolText; - if (sceneViewEditing) - { - int index = ArrayUtility.IndexOf(Styles.sceneViewEditModes, EditMode.editMode); - if (index >= 0) - helpText = Styles.toolNames[index].text; - } - GUILayout.Label(helpText, Styles.richTextMiniLabel); - GUILayout.EndVertical(); - EditorGUILayout.Space(); - } - - ReflectionProbeMode reflectionProbeMode - { - get { return reflectionProbeTarget.mode; } - } - - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - if (targets.Length == 1) - DoToolbar(); - - m_ShowProbeModeRealtimeOptions.target = reflectionProbeMode == ReflectionProbeMode.Realtime; - m_ShowProbeModeCustomOptions.target = reflectionProbeMode == ReflectionProbeMode.Custom; - - // Bake/custom/realtime type - EditorGUILayout.IntPopup(m_Mode, Styles.reflectionProbeMode, Styles.reflectionProbeModeValues, Styles.typeText); - - // We cannot show multiple different type controls - if (!m_Mode.hasMultipleDifferentValues) - { - EditorGUI.indentLevel++; - { - // Custom cubemap UI (Bake button and manual cubemap assignment) - if (EditorGUILayout.BeginFadeGroup(m_ShowProbeModeCustomOptions.faded)) - { - EditorGUILayout.PropertyField(m_RenderDynamicObjects, Styles.renderDynamicObjects); - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_CustomBakedTexture.hasMultipleDifferentValues; - var newCubemap = EditorGUILayout.ObjectField(Styles.customCubemapText, m_CustomBakedTexture.objectReferenceValue, typeof(Cubemap), false); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - m_CustomBakedTexture.objectReferenceValue = newCubemap; - } - EditorGUILayout.EndFadeGroup(); - - // Realtime UI - if (EditorGUILayout.BeginFadeGroup(m_ShowProbeModeRealtimeOptions.faded)) - { - EditorGUILayout.PropertyField(m_RefreshMode, Styles.refreshMode); - EditorGUILayout.PropertyField(m_TimeSlicingMode, Styles.timeSlicing); - - EditorGUILayout.Space(); - } - EditorGUILayout.EndFadeGroup(); - } - EditorGUI.indentLevel--; - } - - EditorGUILayout.Space(); - GUILayout.Label(Styles.runtimeSettingsHeader); - - EditorGUI.indentLevel++; - { - EditorGUILayout.PropertyField(m_Importance, Styles.importanceText); - EditorGUILayout.PropertyField(m_IntensityMultiplier, Styles.intensityText); - - if (Rendering.EditorGraphicsSettings.GetCurrentTierSettings().reflectionProbeBoxProjection == false) - { - using (new EditorGUI.DisabledScope(true)) - { - EditorGUILayout.Toggle(Styles.boxProjectionText, false); - } - } - else - { - EditorGUILayout.PropertyField(m_BoxProjection, Styles.boxProjectionText); - } - - bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath(); - bool isDeferredReflections = isDeferredRenderingPath && (UnityEngine.Rendering.GraphicsSettings.GetShaderMode(BuiltinShaderType.DeferredReflections) != BuiltinShaderMode.Disabled); - using (new EditorGUI.DisabledScope(!isDeferredReflections)) - { - EditorGUILayout.PropertyField(m_BlendDistance, Styles.blendDistanceText); - } - - // Bounds editing (box projection bounds + the bounds that objects use to check if they should be affected by this reflection probe) - if (EditorGUILayout.BeginFadeGroup(m_ShowBoxOptions.faded)) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_BoxSize, Styles.sizeText); - EditorGUILayout.PropertyField(m_BoxOffset, Styles.centerText); - - if (EditorGUI.EndChangeCheck()) - { - Vector3 center = m_BoxOffset.vector3Value; - Vector3 size = m_BoxSize.vector3Value; - if (ValidateAABB(ref center, ref size)) - { - m_BoxOffset.vector3Value = center; - m_BoxSize.vector3Value = size; - } - } - } - EditorGUILayout.EndFadeGroup(); - } - EditorGUI.indentLevel--; - - EditorGUILayout.Space(); - GUILayout.Label(Styles.captureCubemapHeaderText); - - EditorGUI.indentLevel++; - { - int[] reflectionResolutionValuesArray = null; - GUIContent[] reflectionResolutionTextArray = null; - GetResolutionArray(ref reflectionResolutionValuesArray, ref reflectionResolutionTextArray); - - EditorGUILayout.IntPopup(m_Resolution, reflectionResolutionTextArray, reflectionResolutionValuesArray, Styles.resolutionText, GUILayout.MinWidth(40)); - EditorGUILayout.PropertyField(m_HDR); - EditorGUILayout.PropertyField(m_ShadowDistance); - EditorGUILayout.IntPopup(m_ClearFlags, Styles.clearFlags, Styles.clearFlagsValues, Styles.clearFlagsText); - EditorGUILayout.PropertyField(m_BackgroundColor, Styles.backgroundColorText); - EditorGUILayout.PropertyField(m_CullingMask); - EditorGUILayout.PropertyField(m_UseOcclusionCulling); - EditorGUILayout.PropertiesField(EditorGUI.s_ClipingPlanesLabel, m_NearAndFarProperties, EditorGUI.s_NearAndFarLabels, EditorGUI.kNearFarLabelsWidth); - } - EditorGUI.indentLevel--; - - EditorGUILayout.Space(); - - if (targets.Length == 1) - { - ReflectionProbe probe = (ReflectionProbe)target; - if (probe.mode == ReflectionProbeMode.Custom && probe.customBakedTexture != null) - { - Cubemap cubemap = probe.customBakedTexture as Cubemap; - if (cubemap && cubemap.mipmapCount == 1) - EditorGUILayout.HelpBox("No mipmaps in the cubemap, Smoothness value in Standard shader will be ignored.", MessageType.Warning); - } - } - - DoBakeButton(); - EditorGUILayout.Space(); - serializedObject.ApplyModifiedProperties(); - } - - internal override Bounds GetWorldBoundsOfTarget(Object targetObject) - { - return ((ReflectionProbe)targetObject).bounds; - } - - bool ValidPreviewSetup() - { - ReflectionProbe p = (ReflectionProbe)target; - return (p != null && p.texture != null); - } - - public override bool HasPreviewGUI() - { - if (targets.Length > 1) - return false; // We only handle one preview for reflection probes - - // Ensure valid cube map editor (if possible) - if (ValidPreviewSetup()) - { - Editor editor = m_CubemapEditor; - Editor.CreateCachedEditor(((ReflectionProbe)target).texture, null, ref editor); - m_CubemapEditor = editor as TextureInspector; - } - - // If having one probe selected we always want preview (to prevent preview window from popping) - return true; - } - - public override void OnPreviewSettings() - { - if (!ValidPreviewSetup()) - return; - - m_CubemapEditor.mipLevel = m_MipLevelPreview; - - EditorGUI.BeginChangeCheck(); - m_CubemapEditor.OnPreviewSettings(); - // Need to repaint, because mipmap value changes affect reflection probe preview in the scene - if (EditorGUI.EndChangeCheck()) - { - EditorApplication.SetSceneRepaintDirty(); - m_MipLevelPreview = m_CubemapEditor.mipLevel; - } - } - - public override void OnPreviewGUI(Rect position, GUIStyle style) - { - // Fix for case 939947 where we didn't get the Layout event if the texture was null when changing color - if (!ValidPreviewSetup() && Event.current.type != EventType.ExecuteCommand) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - Color prevColor = GUI.color; - GUI.color = new Color(1, 1, 1, 0.5f); - GUILayout.Label("Reflection Probe not baked/ready yet"); - GUI.color = prevColor; - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - return; - } - - ReflectionProbe p = target as ReflectionProbe; - if (p != null && p.texture != null && targets.Length == 1) - { - Editor editor = m_CubemapEditor; - Editor.CreateCachedEditor(p.texture, null, ref editor); - m_CubemapEditor = editor as TextureInspector; - } - - if (m_CubemapEditor != null) - { - m_CubemapEditor.SetCubemapIntensity(GetProbeIntensity((ReflectionProbe)target)); - m_CubemapEditor.OnPreviewGUI(position, style); - } - } - - private static Mesh sphereMesh - { - get { return s_SphereMesh ?? (s_SphereMesh = Resources.GetBuiltinResource(typeof(Mesh), "New-Sphere.fbx") as Mesh); } - } - - private Material reflectiveMaterial - { - get - { - if (m_ReflectiveMaterial == null) - { - m_ReflectiveMaterial = (Material)Instantiate(EditorGUIUtility.Load("Previews/PreviewCubemapMaterial.mat")); - m_ReflectiveMaterial.hideFlags = HideFlags.HideAndDontSave; - } - return m_ReflectiveMaterial; - } - } - - private float GetProbeIntensity(ReflectionProbe p) - { - if (p == null || p.texture == null) - return 1.0f; - - float intensity = p.intensity; - if (TextureUtil.GetTextureColorSpaceString(p.texture) == "Linear") - intensity = Mathf.LinearToGammaSpace(intensity); - return intensity; - } - - // Draw Reflection probe preview sphere - private void OnPreSceneGUICallback(SceneView sceneView) - { - if (Event.current.type != EventType.Repaint) - return; - - foreach (var t in targets) - { - ReflectionProbe p = (ReflectionProbe)t; - if (!reflectiveMaterial) - return; - - Matrix4x4 m = new Matrix4x4(); - - // @TODO: use MaterialPropertyBlock instead - once it actually works! - // Tried to use MaterialPropertyBlock in 5.4.0b2, but would get incorrectly set parameters when using with Graphics.DrawMesh - if (!m_CachedGizmoMaterials.ContainsKey(p)) - m_CachedGizmoMaterials.Add(p, Instantiate(reflectiveMaterial)); - Material mat = m_CachedGizmoMaterials[p] as Material; - if (!mat) - return; - { - // Get mip level - float mipLevel = 0.0F; - TextureInspector cubemapEditor = m_CubemapEditor as TextureInspector; - if (cubemapEditor) - mipLevel = cubemapEditor.GetMipLevelForRendering(); - - mat.SetTexture("_MainTex", p.texture); - mat.SetMatrix("_CubemapRotation", Matrix4x4.identity); - mat.SetFloat("_Mip", mipLevel); - mat.SetFloat("_Alpha", 0.0f); - mat.SetFloat("_Intensity", GetProbeIntensity(p)); - - // draw a preview sphere that scales with overall GO scale, but always uniformly - var scale = p.transform.lossyScale.magnitude * 0.5f; - m.SetTRS(p.transform.position, Quaternion.identity, new Vector3(scale, scale, scale)); - Graphics.DrawMesh(sphereMesh, m, mat, 0, SceneView.currentDrawingSceneView.camera, 0); - } - } - } - - // Ensures that probe's AABB encapsulates probe's position - // Returns true, if center or size was modified - private bool ValidateAABB(ref Vector3 center, ref Vector3 size) - { - ReflectionProbe p = (ReflectionProbe)target; - - Matrix4x4 localSpace = GetLocalSpace(p); - Vector3 localTransformPosition = localSpace.inverse.MultiplyPoint3x4(p.transform.position); - - Bounds b = new Bounds(center, size); - - if (b.Contains(localTransformPosition)) return false; - - b.Encapsulate(localTransformPosition); - - center = b.center; - size = b.size; - return true; - } - - [DrawGizmo(GizmoType.Active)] - static void RenderBoxGizmo(ReflectionProbe reflectionProbe, GizmoType gizmoType) - { - if (s_LastInteractedEditor == null) - return; - - if (s_LastInteractedEditor.sceneViewEditing && EditMode.editMode == EditMode.SceneViewEditMode.ReflectionProbeBox) - { - Color oldColor = Gizmos.color; - Gizmos.color = kGizmoReflectionProbe; - - Gizmos.matrix = GetLocalSpace(reflectionProbe); - Gizmos.DrawCube(reflectionProbe.center, -1f * reflectionProbe.size); - Gizmos.matrix = Matrix4x4.identity; - Gizmos.color = oldColor; - } - } - - [DrawGizmo(GizmoType.Selected)] - static void RenderBoxOutline(ReflectionProbe reflectionProbe, GizmoType gizmoType) - { - Color oldColor = Gizmos.color; - Gizmos.color = reflectionProbe.isActiveAndEnabled ? kGizmoReflectionProbe : kGizmoReflectionProbeDisabled; - - Gizmos.matrix = GetLocalSpace(reflectionProbe); - Gizmos.DrawWireCube(reflectionProbe.center, reflectionProbe.size); - Gizmos.matrix = Matrix4x4.identity; - Gizmos.color = oldColor; - } - - public void OnSceneGUI() - { - if (!sceneViewEditing) - return; - - switch (EditMode.editMode) - { - case EditMode.SceneViewEditMode.ReflectionProbeBox: - DoBoxEditing(); - break; - case EditMode.SceneViewEditMode.ReflectionProbeOrigin: - DoOriginEditing(); - break; - } - } - - void UpdateOldLocalSpace() - { - m_OldLocalSpace = GetLocalSpace((ReflectionProbe)target); - } - - void DoOriginEditing() - { - ReflectionProbe p = (ReflectionProbe)target; - Vector3 transformPosition = p.transform.position; - Vector3 size = p.size; - - EditorGUI.BeginChangeCheck(); - Vector3 newPostion = Handles.PositionHandle(transformPosition, GetLocalSpaceRotation(p)); - - bool changed = EditorGUI.EndChangeCheck(); - - if (changed || m_OldLocalSpace != GetLocalSpace((ReflectionProbe)target)) - { - Vector3 localNewPosition = m_OldLocalSpace.inverse.MultiplyPoint3x4(newPostion); - - Bounds b = new Bounds(p.center, size); - localNewPosition = b.ClosestPoint(localNewPosition); - - Undo.RecordObject(p.transform, "Modified Reflection Probe Origin"); - p.transform.position = m_OldLocalSpace.MultiplyPoint3x4(localNewPosition); - - Undo.RecordObject(p, "Modified Reflection Probe Origin"); - p.center = GetLocalSpace(p).inverse.MultiplyPoint3x4(m_OldLocalSpace.MultiplyPoint3x4(p.center)); - - EditorUtility.SetDirty(target); - - UpdateOldLocalSpace(); - } - } - - static Matrix4x4 GetLocalSpace(ReflectionProbe probe) - { - Vector3 t = probe.transform.position; - return Matrix4x4.TRS(t, GetLocalSpaceRotation(probe), Vector3.one); - } - - static Quaternion GetLocalSpaceRotation(ReflectionProbe probe) - { - bool supportsRotation = (SupportedRenderingFeatures.active.reflectionProbeSupportFlags & SupportedRenderingFeatures.ReflectionProbeSupportFlags.Rotation) != 0; - if (supportsRotation) - return probe.transform.rotation; - else - return Quaternion.identity; - } - - void DoBoxEditing() - { - // Drawing of the probe box is done from GizmoDrawers.cpp, - // here we only want to show the box editing handles when needed. - ReflectionProbe p = (ReflectionProbe)target; - - using (new Handles.DrawingScope(GetLocalSpace(p))) - { - m_BoundsHandle.center = p.center; - m_BoundsHandle.size = p.size; - - EditorGUI.BeginChangeCheck(); - m_BoundsHandle.DrawHandle(); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(p, "Modified Reflection Probe AABB"); - Vector3 center = m_BoundsHandle.center; - Vector3 size = m_BoundsHandle.size; - ValidateAABB(ref center, ref size); - p.center = center; - p.size = size; - EditorUtility.SetDirty(target); - } - } - } - } -} diff --git a/Editor/Mono/Inspector/RelativeJoint2DEditor.cs b/Editor/Mono/Inspector/RelativeJoint2DEditor.cs deleted file mode 100644 index e2a57cb780..0000000000 --- a/Editor/Mono/Inspector/RelativeJoint2DEditor.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(RelativeJoint2D))] - [CanEditMultipleObjects] - internal class RelativeJoint2DEditor : Joint2DEditor - { - public void OnSceneGUI() - { - var relativeJoint2D = (RelativeJoint2D)target; - - // Ignore disabled joint. - if (!relativeJoint2D.enabled) - return; - - // Fetch the anchors. - var anchor = (Vector3)relativeJoint2D.target; - var connectedAnchor = relativeJoint2D.connectedBody ? relativeJoint2D.connectedBody.transform.position : Vector3.zero; - - // Draw a line between the bodies. - Handles.color = Color.green; - DrawAALine(anchor, connectedAnchor); - - // Draw the source point. - var sourceScale = HandleUtility.GetHandleSize(connectedAnchor) * 0.16f; - var horzSource = Vector3.left * sourceScale; - var vertSource = Vector3.up * sourceScale; - DrawAALine(connectedAnchor - horzSource, connectedAnchor + horzSource); - DrawAALine(connectedAnchor - vertSource, connectedAnchor + vertSource); - - // Draw the target point. - var targetScale = HandleUtility.GetHandleSize(anchor) * 0.16f; - var horzTarget = Vector3.left * targetScale; - var vertTarget = Vector3.up * targetScale; - DrawAALine(anchor - horzTarget, anchor + horzTarget); - DrawAALine(anchor - vertTarget, anchor + vertTarget); - } - } -} diff --git a/Editor/Mono/Inspector/RenderSettingsInspector.cs b/Editor/Mono/Inspector/RenderSettingsInspector.cs deleted file mode 100644 index 3d0cc0efb1..0000000000 --- a/Editor/Mono/Inspector/RenderSettingsInspector.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEngine; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - [CustomEditor(typeof(RenderSettings))] - internal class RenderSettingsInspector : Editor - { - Editor m_LightingEditor; - Editor lightingEditor - { - get { return m_LightingEditor ?? (m_LightingEditor = Editor.CreateEditor(target, typeof(LightingEditor))); } - } - - - Editor m_FogEditor; - Editor fogEditor - { - get { return m_FogEditor ?? (m_FogEditor = Editor.CreateEditor(target, typeof(FogEditor))); } - } - - Editor m_OtherRenderingEditor; - Editor otherRenderingEditor - { - get { return m_OtherRenderingEditor ?? (m_OtherRenderingEditor = Editor.CreateEditor(target, typeof(OtherRenderingEditor))); } - } - - public virtual void OnEnable() - { - m_LightingEditor = null; - m_FogEditor = null; - m_OtherRenderingEditor = null; - } - - public override void OnInspectorGUI() - { - lightingEditor.OnInspectorGUI(); - fogEditor.OnInspectorGUI(); - otherRenderingEditor.OnInspectorGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/RenderTextureEditor.cs b/Editor/Mono/Inspector/RenderTextureEditor.cs deleted file mode 100644 index 5766147b8e..0000000000 --- a/Editor/Mono/Inspector/RenderTextureEditor.cs +++ /dev/null @@ -1,203 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - - -namespace UnityEditor -{ - [CustomEditor(typeof(RenderTexture))] - [CanEditMultipleObjects] - internal class RenderTextureEditor : TextureInspector - { - private class Styles - { - public readonly GUIContent size = EditorGUIUtility.TrTextContent("Size", "Size of the render texture in pixels."); - public readonly GUIContent cross = EditorGUIUtility.TextContent("x"); - public readonly GUIContent antiAliasing = EditorGUIUtility.TrTextContent("Anti-Aliasing", "Number of anti-aliasing samples."); - public readonly GUIContent colorFormat = EditorGUIUtility.TrTextContent("Color Format", "Format of the color buffer."); - public readonly GUIContent depthBuffer = EditorGUIUtility.TrTextContent("Depth Buffer", "Format of the depth buffer."); - public readonly GUIContent dimension = EditorGUIUtility.TrTextContent("Dimension", "Is the texture 2D, Cube or 3D?"); - public readonly GUIContent enableMipmaps = EditorGUIUtility.TrTextContent("Enable Mip Maps", "This render texture will have Mip Maps."); - public readonly GUIContent bindMS = EditorGUIUtility.TrTextContent("Bind multisampled", "If enabled, the texture will not go through an AA resolve if bound to a shader."); - public readonly GUIContent autoGeneratesMipmaps = EditorGUIUtility.TrTextContent("Auto generate Mip Maps", "This render texture automatically generate its Mip Maps."); - public readonly GUIContent sRGBTexture = EditorGUIUtility.TrTextContent("sRGB (Color RenderTexture)", "RenderTexture content is stored in gamma space. Non-HDR color textures should enable this flag."); - public readonly GUIContent useDynamicScale = EditorGUIUtility.TrTextContent("Dynamic Scaling", "Allow the texture to be automatically resized by ScalableBufferManager, to support dynamic resolution."); - - public readonly GUIContent[] renderTextureAntiAliasing = - { - EditorGUIUtility.TrTextContent("None"), - EditorGUIUtility.TrTextContent("2 samples"), - EditorGUIUtility.TrTextContent("4 samples"), - EditorGUIUtility.TrTextContent("8 samples") - }; - public readonly int[] renderTextureAntiAliasingValues = { 1, 2, 4, 8 }; - - public readonly GUIContent[] dimensionStrings = { EditorGUIUtility.TextContent("2D"), EditorGUIUtility.TextContent("Cube"), EditorGUIUtility.TrTextContent("3D") }; - public readonly int[] dimensionValues = { (int)UnityEngine.Rendering.TextureDimension.Tex2D, (int)UnityEngine.Rendering.TextureDimension.Cube, (int)UnityEngine.Rendering.TextureDimension.Tex3D }; - } - - static Styles s_Styles = null; - private static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - - - [Flags] - protected enum GUIElements - { - RenderTargetNoneGUI = 0, - RenderTargetDepthGUI = 1 << 1, - RenderTargetAAGUI = 1 << 2 - } - - const GUIElements s_AllGUIElements = GUIElements.RenderTargetDepthGUI | GUIElements.RenderTargetAAGUI; - - SerializedProperty m_Width; - SerializedProperty m_Height; - SerializedProperty m_Depth; - SerializedProperty m_ColorFormat; - SerializedProperty m_DepthFormat; - SerializedProperty m_AntiAliasing; - SerializedProperty m_EnableMipmaps; - SerializedProperty m_AutoGeneratesMipmaps; - SerializedProperty m_Dimension; - SerializedProperty m_sRGB; - SerializedProperty m_UseDynamicScale; - - protected override void OnEnable() - { - base.OnEnable(); - m_Width = serializedObject.FindProperty("m_Width"); - m_Height = serializedObject.FindProperty("m_Height"); - m_Depth = serializedObject.FindProperty("m_VolumeDepth"); - m_AntiAliasing = serializedObject.FindProperty("m_AntiAliasing"); - m_ColorFormat = serializedObject.FindProperty("m_ColorFormat"); - m_DepthFormat = serializedObject.FindProperty("m_DepthFormat"); - m_EnableMipmaps = serializedObject.FindProperty("m_MipMap"); - m_AutoGeneratesMipmaps = serializedObject.FindProperty("m_GenerateMips"); - m_Dimension = serializedObject.FindProperty("m_Dimension"); - m_sRGB = serializedObject.FindProperty("m_SRGB"); - m_UseDynamicScale = serializedObject.FindProperty("m_UseDynamicScale"); - } - - public static bool IsHDRFormat(RenderTextureFormat format) - { - return (format == RenderTextureFormat.ARGBHalf || format == RenderTextureFormat.RGB111110Float || format == RenderTextureFormat.RGFloat || - format == RenderTextureFormat.ARGBFloat || format == RenderTextureFormat.ARGBFloat || format == RenderTextureFormat.RFloat || - format == RenderTextureFormat.RGHalf || format == RenderTextureFormat.RHalf); - } - - protected void OnRenderTextureGUI(GUIElements guiElements) - { - GUI.changed = false; - - bool isTexture3D = (m_Dimension.intValue == (int)UnityEngine.Rendering.TextureDimension.Tex3D); - - EditorGUILayout.IntPopup(m_Dimension, styles.dimensionStrings, styles.dimensionValues, styles.dimension); - - GUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel(styles.size, EditorStyles.popup); - EditorGUILayout.DelayedIntField(m_Width, GUIContent.none, GUILayout.MinWidth(40)); - GUILayout.Label(styles.cross); - EditorGUILayout.DelayedIntField(m_Height, GUIContent.none, GUILayout.MinWidth(40)); - if (isTexture3D) - { - GUILayout.Label(styles.cross); - EditorGUILayout.DelayedIntField(m_Depth, GUIContent.none, GUILayout.MinWidth(40)); - } - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - - if ((guiElements & GUIElements.RenderTargetAAGUI) != 0) - EditorGUILayout.IntPopup(m_AntiAliasing, styles.renderTextureAntiAliasing, styles.renderTextureAntiAliasingValues, styles.antiAliasing); - EditorGUILayout.PropertyField(m_ColorFormat, styles.colorFormat); - if ((guiElements & GUIElements.RenderTargetDepthGUI) != 0) - EditorGUILayout.PropertyField(m_DepthFormat, styles.depthBuffer); - - bool isHDRRenderTexture = IsHDRFormat((RenderTextureFormat)m_ColorFormat.intValue); - using (new EditorGUI.DisabledScope(isHDRRenderTexture)) - { - EditorGUILayout.PropertyField(m_sRGB, styles.sRGBTexture); - } - - using (new EditorGUI.DisabledScope(isTexture3D)) - { - EditorGUILayout.PropertyField(m_EnableMipmaps, styles.enableMipmaps); - using (new EditorGUI.DisabledScope(!m_EnableMipmaps.boolValue)) - EditorGUILayout.PropertyField(m_AutoGeneratesMipmaps, styles.autoGeneratesMipmaps); - } - - if (isTexture3D) - { - // Mip map generation is not supported yet for 3D textures. - EditorGUILayout.HelpBox("3D RenderTextures do not support Mip Maps.", MessageType.Info); - } - - EditorGUILayout.PropertyField(m_UseDynamicScale, styles.useDynamicScale); - - var rt = target as RenderTexture; - if (GUI.changed && rt != null) - rt.Release(); - - EditorGUILayout.Space(); - - DoWrapModePopup(); - DoFilterModePopup(); - - using (new EditorGUI.DisabledScope(RenderTextureHasDepth())) // Render Textures with depth are forced to 0 Aniso Level - { - DoAnisoLevelSlider(); - } - if (RenderTextureHasDepth()) - { - // RenderTextures don't enforce this nicely. RenderTexture only forces Aniso to 0 if the gfx card - // supports depth, rather than forcing Aniso to zero depending on what the user asks of the RT. If the - // user requests any kind of depth then we will force aniso to zero here. - m_Aniso.intValue = 0; - EditorGUILayout.HelpBox("RenderTextures with depth must have an Aniso Level of 0.", MessageType.Info); - } - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - OnRenderTextureGUI(s_AllGUIElements); - - serializedObject.ApplyModifiedProperties(); - } - - private bool RenderTextureHasDepth() - { - if (TextureUtil.IsDepthRTFormat((RenderTextureFormat)m_ColorFormat.enumValueIndex)) - return true; - - return m_DepthFormat.enumValueIndex != 0; - } - - override public string GetInfoString() - { - RenderTexture t = target as RenderTexture; - - string info = t.width + "x" + t.height; - if (t.dimension == UnityEngine.Rendering.TextureDimension.Tex3D) - info += "x" + t.volumeDepth; - - if (!t.isPowerOfTwo) - info += "(NPOT)"; - - if (QualitySettings.desiredColorSpace == ColorSpace.Linear) - { - bool formatIsHDR = IsHDRFormat(t.format); - bool sRGB = t.sRGB && !formatIsHDR; - info += " " + (sRGB ? "sRGB" : "Linear"); - } - - info += " " + t.format; - info += " " + EditorUtility.FormatBytes(TextureUtil.GetRuntimeMemorySizeLong(t)); - - return info; - } - } -} diff --git a/Editor/Mono/Inspector/RendererEditorBase.cs b/Editor/Mono/Inspector/RendererEditorBase.cs deleted file mode 100644 index bfb86206c9..0000000000 --- a/Editor/Mono/Inspector/RendererEditorBase.cs +++ /dev/null @@ -1,416 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Rendering; -using System.Linq; -using UnityEngine.Experimental.Rendering; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class RendererEditorBase : Editor - { - private GUIContent m_DynamicOccludeeLabel = EditorGUIUtility.TrTextContent("Dynamic Occluded", "Controls if dynamic occlusion culling should be performed for this renderer."); - - - internal class Probes - { - private SerializedProperty m_LightProbeUsage; - private SerializedProperty m_LightProbeVolumeOverride; - private SerializedProperty m_ReflectionProbeUsage; - private SerializedProperty m_ProbeAnchor; - private SerializedProperty m_ReceiveShadows; - - 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 Lightmap Static."); - private GUIContent m_LightProbeVolumeOverrideStyle = EditorGUIUtility.TrTextContent("Proxy Volume Override", "If set, the Renderer will use the Light Probe Proxy Volume component from another GameObject."); - 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."); - private GUIContent m_ProbeAnchorStyle = EditorGUIUtility.TrTextContent("Anchor Override", "Specifies the Transform position that will be used for sampling the light probes and reflection probes."); - private GUIContent m_DeferredNote = EditorGUIUtility.TrTextContent("In Deferred Shading, all objects receive shadows and get per-pixel reflection probes."); - private GUIContent m_LightProbeVolumeNote = EditorGUIUtility.TrTextContent("A valid Light Probe Proxy Volume component could not be found."); - 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."); - 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."); - private GUIContent m_LightProbeCustomNote = EditorGUIUtility.TrTextContent("The Custom Provided mode requires SH properties to be sent via MaterialPropertyBlock."); - private GUIContent[] m_ReflectionProbeUsageOptions = (Enum.GetNames(typeof(ReflectionProbeUsage)).Select(x => ObjectNames.NicifyVariableName(x)).ToArray()).Select(x => new GUIContent(x)).ToArray(); - - private List m_BlendInfo = new List(); - - internal void Initialize(SerializedObject serializedObject) - { - m_LightProbeUsage = serializedObject.FindProperty("m_LightProbeUsage"); - m_LightProbeVolumeOverride = serializedObject.FindProperty("m_LightProbeVolumeOverride"); - m_ReflectionProbeUsage = serializedObject.FindProperty("m_ReflectionProbeUsage"); - m_ProbeAnchor = serializedObject.FindProperty("m_ProbeAnchor"); - m_ReceiveShadows = serializedObject.FindProperty("m_ReceiveShadows"); - } - - internal bool IsUsingLightProbeProxyVolume(int selectionCount) - { - bool isUsingLightProbeVolumes = - ((selectionCount == 1) && (m_LightProbeUsage.intValue == (int)LightProbeUsage.UseProxyVolume)) || - ((selectionCount > 1) && !m_LightProbeUsage.hasMultipleDifferentValues && (m_LightProbeUsage.intValue == (int)LightProbeUsage.UseProxyVolume)); - - return isUsingLightProbeVolumes; - } - - internal bool HasValidLightProbeProxyVolumeOverride(Renderer renderer, int selectionCount) - { - LightProbeProxyVolume proxyVolumeOverride = (renderer.lightProbeProxyVolumeOverride != null) ? - renderer.lightProbeProxyVolumeOverride.GetComponent() : - null; - - return IsUsingLightProbeProxyVolume(selectionCount) && ((proxyVolumeOverride == null) || (proxyVolumeOverride.boundingBoxMode != LightProbeProxyVolume.BoundingBoxMode.AutomaticLocal)); - } - - internal void RenderLightProbeProxyVolumeWarningNote(Renderer renderer, int selectionCount) - { - if (IsUsingLightProbeProxyVolume(selectionCount)) - { - if (LightProbeProxyVolume.isFeatureSupported && SupportedRenderingFeatures.active.rendererSupportsLightProbeProxyVolumes) - { - LightProbeProxyVolume lightProbeProxyVol = renderer.GetComponent(); - bool invalidProxyVolumeOverride = (renderer.lightProbeProxyVolumeOverride == null) || - (renderer.lightProbeProxyVolumeOverride.GetComponent() == null); - if (lightProbeProxyVol == null && invalidProxyVolumeOverride && LightProbes.AreLightProbesAllowed(renderer)) - { - EditorGUILayout.HelpBox(m_LightProbeVolumeNote.text, MessageType.Warning); - } - } - else - { - EditorGUILayout.HelpBox(m_LightProbeVolumeUnsupportedNote.text, MessageType.Warning); - } - } - } - - internal void RenderReflectionProbeUsage(bool useMiniStyle, bool isDeferredRenderingPath, bool isDeferredReflections) - { - if (!SupportedRenderingFeatures.active.rendererSupportsReflectionProbes) - return; - - using (new EditorGUI.DisabledScope(isDeferredRenderingPath)) - { - // reflection probe usage field; UI disabled when using deferred reflections - if (!useMiniStyle) - { - if (isDeferredReflections) - { - EditorGUILayout.EnumPopup(m_ReflectionProbeUsageStyle, (m_ReflectionProbeUsage.intValue != (int)ReflectionProbeUsage.Off) ? ReflectionProbeUsage.Simple : ReflectionProbeUsage.Off); - } - else - { - EditorGUILayout.Popup(m_ReflectionProbeUsage, m_ReflectionProbeUsageOptions, m_ReflectionProbeUsageStyle); - } - } - else - { - if (isDeferredReflections) - { - ModuleUI.GUIPopup(m_ReflectionProbeUsageStyle, (int)ReflectionProbeUsage.Simple, m_ReflectionProbeUsageOptions); - } - else - { - ModuleUI.GUIPopup(m_ReflectionProbeUsageStyle, m_ReflectionProbeUsage, m_ReflectionProbeUsageOptions); - } - } - } - } - - internal void RenderLightProbeUsage(int selectionCount, Renderer renderer, bool useMiniStyle, bool lightProbeAllowed) - { - using (new EditorGUI.DisabledScope(!lightProbeAllowed)) - { - if (lightProbeAllowed) - { - // LightProbeUsage has non-sequential enum values. Extra care is to be taken. - if (useMiniStyle) - { - EditorGUI.BeginChangeCheck(); - var newValue = ModuleUI.GUIEnumPopup(m_LightProbeUsageStyle, (LightProbeUsage)m_LightProbeUsage.intValue, m_LightProbeUsage); - if (EditorGUI.EndChangeCheck()) - m_LightProbeUsage.intValue = (int)(LightProbeUsage)newValue; - } - else - { - Rect r = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight, EditorStyles.popup); - EditorGUI.BeginProperty(r, m_LightProbeUsageStyle, m_LightProbeUsage); - EditorGUI.BeginChangeCheck(); - var newValue = EditorGUI.EnumPopup(r, m_LightProbeUsageStyle, (LightProbeUsage)m_LightProbeUsage.intValue); - if (EditorGUI.EndChangeCheck()) - m_LightProbeUsage.intValue = (int)(LightProbeUsage)newValue; - EditorGUI.EndProperty(); - } - - if (!m_LightProbeUsage.hasMultipleDifferentValues) - { - if (m_LightProbeUsage.intValue == (int)LightProbeUsage.UseProxyVolume - && SupportedRenderingFeatures.active.rendererSupportsLightProbeProxyVolumes) - { - EditorGUI.indentLevel++; - if (useMiniStyle) - ModuleUI.GUIObject(m_LightProbeVolumeOverrideStyle, m_LightProbeVolumeOverride); - else - EditorGUILayout.PropertyField(m_LightProbeVolumeOverride, m_LightProbeVolumeOverrideStyle); - EditorGUI.indentLevel--; - } - else if (m_LightProbeUsage.intValue == (int)LightProbeUsage.CustomProvided) - { - EditorGUI.indentLevel++; - if (!Application.isPlaying) - EditorGUILayout.HelpBox(m_LightProbeCustomNote.text, MessageType.Info); - else if (!renderer.HasPropertyBlock()) - EditorGUILayout.HelpBox(m_LightProbeCustomNote.text, MessageType.Error); - EditorGUI.indentLevel--; - } - } - } - else - { - if (useMiniStyle) - ModuleUI.GUIEnumPopup(m_LightProbeUsageStyle, LightProbeUsage.Off, m_LightProbeUsage); - else - EditorGUILayout.EnumPopup(m_LightProbeUsageStyle, LightProbeUsage.Off); - } - } - - var tree = renderer.GetComponent(); - if ((tree != null) && (m_LightProbeUsage.intValue == (int)LightProbeUsage.UseProxyVolume)) - { - EditorGUI.indentLevel++; - EditorGUILayout.HelpBox(m_LightProbeVolumeUnsupportedOnTreesNote.text, MessageType.Warning); - EditorGUI.indentLevel--; - } - } - - internal bool RenderProbeAnchor(bool useMiniStyle) - { - bool useReflectionProbes = !m_ReflectionProbeUsage.hasMultipleDifferentValues && (ReflectionProbeUsage)m_ReflectionProbeUsage.intValue != ReflectionProbeUsage.Off; - bool lightProbesEnabled = !m_LightProbeUsage.hasMultipleDifferentValues && (LightProbeUsage)m_LightProbeUsage.intValue != LightProbeUsage.Off; - bool needsRendering = useReflectionProbes || lightProbesEnabled; - - if (needsRendering) - { - // anchor field - if (!useMiniStyle) - EditorGUILayout.PropertyField(m_ProbeAnchor, m_ProbeAnchorStyle); - else - ModuleUI.GUIObject(m_ProbeAnchorStyle, m_ProbeAnchor); - } - - return needsRendering; - } - - // Set useMiniStyle to true to use smaller UI styles, - // like in particle system modules UI. - // - // The code does branches right now on that instead of just - // picking one or another style, since there are no UI - // functions, like EditorGUILayout.ObjectField that would take - // a style parameter :( - internal void OnGUI(UnityEngine.Object[] selection, Renderer renderer, bool useMiniStyle) - { - int selectionCount = 1; - bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath(); - bool isDeferredReflections = isDeferredRenderingPath && (UnityEngine.Rendering.GraphicsSettings.GetShaderMode(BuiltinShaderType.DeferredReflections) != BuiltinShaderMode.Disabled); - bool areLightProbesAllowed = true; - - if (selection != null) - { - foreach (UnityEngine.Object obj in selection) - { - if (LightProbes.AreLightProbesAllowed((Renderer)obj) == false) - { - areLightProbesAllowed = false; - break; - } - } - - selectionCount = selection.Length; - } - - RenderLightProbeUsage(selectionCount, renderer, useMiniStyle, areLightProbesAllowed); - - RenderLightProbeProxyVolumeWarningNote(renderer, selectionCount); - - RenderReflectionProbeUsage(useMiniStyle, isDeferredRenderingPath, isDeferredReflections); - - // anchor field - light probes and reflection probes share the same anchor - bool needsProbeAnchorField = RenderProbeAnchor(useMiniStyle); - - if (needsProbeAnchorField) - { - bool useReflectionProbes = !m_ReflectionProbeUsage.hasMultipleDifferentValues && (ReflectionProbeUsage)m_ReflectionProbeUsage.intValue != ReflectionProbeUsage.Off; - - if (useReflectionProbes) - { - if (!isDeferredReflections) - { - renderer.GetClosestReflectionProbes(m_BlendInfo); - ShowClosestReflectionProbes(m_BlendInfo); - } - } - } - - bool receivesShadow = !m_ReceiveShadows.hasMultipleDifferentValues && m_ReceiveShadows.boolValue; - - if ((isDeferredRenderingPath && receivesShadow) || (isDeferredReflections && needsProbeAnchorField)) - { - EditorGUILayout.HelpBox(m_DeferredNote.text, MessageType.Info); - } - } - - // Show an info list of probes affecting this object, and their weights. - internal static void ShowClosestReflectionProbes(List blendInfos) - { - float kProbeLabelWidth = 20; - float kWeightWidth = 70; - - // No UI interaction, so disable all controls. - using (new EditorGUI.DisabledScope(true)) - { - for (int i = 0; i < blendInfos.Count; i++) - { - var rowRect = GUILayoutUtility.GetRect(0, EditorGUI.kSingleLineHeight); - rowRect = EditorGUI.IndentedRect(rowRect); - float probeFieldWidth = rowRect.width - kProbeLabelWidth - kWeightWidth; - var rect = rowRect; - - rect.width = kProbeLabelWidth; - GUI.Label(rect, "#" + i, EditorStyles.miniLabel); - - rect.x += rect.width; - rect.width = probeFieldWidth; - EditorGUI.ObjectField(rect, blendInfos[i].probe, typeof(ReflectionProbe), true); - - rect.x += rect.width; - rect.width = kWeightWidth; - GUI.Label(rect, "Weight " + blendInfos[i].weight.ToString("f2"), EditorStyles.miniLabel); - } - } - } - - internal static string[] GetFieldsStringArray() - { - return new[] - { - "m_LightProbeUsage", - "m_LightProbeVolumeOverride", - "m_ReflectionProbeUsage", - "m_ProbeAnchor", - }; - } - } - - private static string[] m_LayerNames; - private static string[] layerNames - { - get - { - if (m_LayerNames == null) - { - m_LayerNames = new string[32]; - for (int i = 0; i < m_LayerNames.Length; ++i) - { - m_LayerNames[i] = string.Format("Layer{0}", i + 1); - } - } - return m_LayerNames; - } - } - - private SerializedProperty m_SortingOrder; - private SerializedProperty m_SortingLayerID; - private SerializedProperty m_DynamicOccludee; - private SerializedProperty m_RenderingLayerMask; - static GUIContent m_RenderingLayerMaskStyle = EditorGUIUtility.TrTextContent("Rendering Layer Mask", "Mask that can be used with SRP DrawRenderers command to filter renderers outside of the normal layering system."); - - protected Probes m_Probes; - - public virtual void OnEnable() - { - m_SortingOrder = serializedObject.FindProperty("m_SortingOrder"); - m_SortingLayerID = serializedObject.FindProperty("m_SortingLayerID"); - m_DynamicOccludee = serializedObject.FindProperty("m_DynamicOccludee"); - m_RenderingLayerMask = serializedObject.FindProperty("m_RenderingLayerMask"); - } - - protected void RenderSortingLayerFields() - { - EditorGUILayout.Space(); - SortingLayerEditorUtility.RenderSortingLayerFields(m_SortingOrder, m_SortingLayerID); - } - - protected void InitializeProbeFields() - { - m_Probes = new Probes(); - m_Probes.Initialize(serializedObject); - } - - protected void RenderProbeFields() - { - m_Probes.OnGUI(targets, (Renderer)target, false); - } - - protected void CullDynamicFieldGUI() - { - EditorGUILayout.PropertyField(m_DynamicOccludee, m_DynamicOccludeeLabel); - } - - protected void RenderRenderingLayer() - { - RenderRenderingLayer(m_RenderingLayerMask, target as Renderer, targets.ToArray()); - } - - internal static void RenderRenderingLayer(SerializedProperty layerMask, Renderer target, Object[] targets, bool useMiniStyle = false) - { - bool usingSRP = GraphicsSettings.renderPipelineAsset != null; - if (!usingSRP || target == null) - return; - - EditorGUI.showMixedValue = layerMask.hasMultipleDifferentValues; - - var renderer = target; - var mask = (int)renderer.renderingLayerMask; - - EditorGUI.BeginChangeCheck(); - - var rect = EditorGUILayout.GetControlRect(); - EditorGUI.BeginProperty(rect, m_RenderingLayerMaskStyle, layerMask); - if (useMiniStyle) - { - rect = ModuleUI.PrefixLabel(rect, m_RenderingLayerMaskStyle); - mask = EditorGUI.MaskField(rect, GUIContent.none, mask, layerNames, - ParticleSystemStyles.Get().popup); - } - else - mask = EditorGUI.MaskField(rect, m_RenderingLayerMaskStyle, mask, layerNames); - EditorGUI.EndProperty(); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObjects(targets, "Set rendering layer mask"); - foreach (var t in targets) - { - var r = t as Renderer; - if (r != null) - { - r.renderingLayerMask = (uint)mask; - EditorUtility.SetDirty(t); - } - } - } - EditorGUI.showMixedValue = false; - } - - protected void RenderCommonProbeFields(bool useMiniStyle) - { - bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath(); - bool isDeferredReflections = isDeferredRenderingPath && (GraphicsSettings.GetShaderMode(BuiltinShaderType.DeferredReflections) != BuiltinShaderMode.Disabled); - m_Probes.RenderReflectionProbeUsage(useMiniStyle, isDeferredRenderingPath, isDeferredReflections); - m_Probes.RenderProbeAnchor(useMiniStyle); - } - } -} diff --git a/Editor/Mono/Inspector/Rigidbody2DEditor.cs b/Editor/Mono/Inspector/Rigidbody2DEditor.cs deleted file mode 100644 index 58121460c6..0000000000 --- a/Editor/Mono/Inspector/Rigidbody2DEditor.cs +++ /dev/null @@ -1,291 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using UnityEditor; -using UnityEditorInternal; -using UnityEditor.AnimatedValues; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(Rigidbody2D))] - [CanEditMultipleObjects] - internal class Rigidbody2DEditor : Editor - { - SerializedProperty m_Simulated; - SerializedProperty m_BodyType; - SerializedProperty m_Material; - SerializedProperty m_UseFullKinematicContacts; - SerializedProperty m_UseAutoMass; - SerializedProperty m_Mass; - SerializedProperty m_LinearDrag; - SerializedProperty m_AngularDrag; - SerializedProperty m_GravityScale; - SerializedProperty m_Interpolate; - SerializedProperty m_SleepingMode; - SerializedProperty m_CollisionDetection; - SerializedProperty m_Constraints; - - readonly AnimBool m_ShowIsStatic = new AnimBool(); - readonly AnimBool m_ShowIsKinematic = new AnimBool(); - - readonly AnimBool m_ShowInfo = new AnimBool(); - readonly AnimBool m_ShowContacts = new AnimBool(); - Vector2 m_ContactScrollPosition; - - static readonly GUIContent m_FreezePositionLabel = EditorGUIUtility.TrTextContent("Freeze Position"); - static readonly GUIContent m_FreezeRotationLabel = EditorGUIUtility.TrTextContent("Freeze Rotation"); - - static ContactPoint2D[] m_Contacts = new ContactPoint2D[100]; - - const int k_ToggleOffset = 30; - - public void OnEnable() - { - var body = target as Rigidbody2D; - - m_Simulated = serializedObject.FindProperty("m_Simulated"); - m_BodyType = serializedObject.FindProperty("m_BodyType"); - m_Material = serializedObject.FindProperty("m_Material"); - m_UseFullKinematicContacts = serializedObject.FindProperty("m_UseFullKinematicContacts"); - m_UseAutoMass = serializedObject.FindProperty("m_UseAutoMass"); - m_Mass = serializedObject.FindProperty("m_Mass"); - m_LinearDrag = serializedObject.FindProperty("m_LinearDrag"); - m_AngularDrag = serializedObject.FindProperty("m_AngularDrag"); - m_GravityScale = serializedObject.FindProperty("m_GravityScale"); - m_Interpolate = serializedObject.FindProperty("m_Interpolate"); - m_SleepingMode = serializedObject.FindProperty("m_SleepingMode"); - m_CollisionDetection = serializedObject.FindProperty("m_CollisionDetection"); - m_Constraints = serializedObject.FindProperty("m_Constraints"); - - m_ShowIsStatic.value = body.bodyType != RigidbodyType2D.Static; - m_ShowIsStatic.valueChanged.AddListener(Repaint); - - m_ShowIsKinematic.value = body.bodyType != RigidbodyType2D.Kinematic; - m_ShowIsKinematic.valueChanged.AddListener(Repaint); - - m_ShowInfo.valueChanged.AddListener(Repaint); - m_ShowContacts.valueChanged.AddListener(Repaint); - m_ContactScrollPosition = Vector2.zero; - } - - public void OnDisable() - { - m_ShowIsStatic.valueChanged.RemoveListener(Repaint); - m_ShowIsKinematic.valueChanged.RemoveListener(Repaint); - m_ShowInfo.valueChanged.RemoveListener(Repaint); - m_ShowContacts.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - var body = target as Rigidbody2D; - - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_BodyType); - EditorGUILayout.PropertyField(m_Material); - - // Provide the user some information when simulation is turned off. - EditorGUILayout.PropertyField(m_Simulated); - if (!m_Simulated.boolValue && !m_Simulated.hasMultipleDifferentValues) - EditorGUILayout.HelpBox("The body has now been taken out of the simulation along with any attached colliders, joints or effectors.", MessageType.Info); - - - // Can only multi-edit if we have the same body-type. - if (m_BodyType.hasMultipleDifferentValues) - { - EditorGUILayout.HelpBox("Cannot edit properties that are body type specific when the selection contains different body types.", MessageType.Info); - } - else - { - // Non-static options. - m_ShowIsStatic.target = body.bodyType != RigidbodyType2D.Static; - if (EditorGUILayout.BeginFadeGroup(m_ShowIsStatic.faded)) - { - // Kinematic options. - m_ShowIsKinematic.target = body.bodyType != RigidbodyType2D.Kinematic; - if (EditorGUILayout.BeginFadeGroup(m_ShowIsKinematic.faded)) - { - // Collider Mass. - EditorGUILayout.PropertyField(m_UseAutoMass); - - // Only show mass property if selected objects have the same useAutoMass value. - if (!m_UseAutoMass.hasMultipleDifferentValues) - { - // If we're using auto-mass but either the object is part of a prefab parent or is not active then we cannot show the calculated mass value. - if (m_UseAutoMass.boolValue && targets.Any(x => PrefabUtility.GetPrefabType(x) == PrefabType.Prefab || !(x as Rigidbody2D).gameObject.activeInHierarchy)) - { - EditorGUILayout.HelpBox("The auto mass value cannot be displayed for a prefab or if the object is not active. The value will be calculated for a prefab instance and when the object is active.", MessageType.Info); - } - else - { - EditorGUI.BeginDisabledGroup(body.useAutoMass); - EditorGUILayout.PropertyField(m_Mass); - EditorGUI.EndDisabledGroup(); - } - } - - EditorGUILayout.PropertyField(m_LinearDrag); - EditorGUILayout.PropertyField(m_AngularDrag); - EditorGUILayout.PropertyField(m_GravityScale); - } - FixedEndFadeGroup(m_ShowIsKinematic.faded); - - if (!m_ShowIsKinematic.target) - EditorGUILayout.PropertyField(m_UseFullKinematicContacts); - - EditorGUILayout.PropertyField(m_CollisionDetection); - EditorGUILayout.PropertyField(m_SleepingMode); - EditorGUILayout.PropertyField(m_Interpolate); - - GUILayout.BeginHorizontal(); - m_Constraints.isExpanded = EditorGUILayout.Foldout(m_Constraints.isExpanded, "Constraints", true); - GUILayout.EndHorizontal(); - - var constraints = (RigidbodyConstraints2D)m_Constraints.intValue; - if (m_Constraints.isExpanded) - { - EditorGUI.indentLevel++; - ToggleFreezePosition(constraints, m_FreezePositionLabel, 0, 1); - ToggleFreezeRotation(constraints, m_FreezeRotationLabel, 2); - EditorGUI.indentLevel--; - } - - // Provide end-user warning about the equivalence of all constraints on versus no Rigidbody2D component. - if (constraints == RigidbodyConstraints2D.FreezeAll) - EditorGUILayout.HelpBox("Rather than turning on all constraints, you may want to consider removing the Rigidbody2D component which makes any colliders static. This gives far better performance overall.", MessageType.Info); - } - FixedEndFadeGroup(m_ShowIsStatic.faded); - } - - serializedObject.ApplyModifiedProperties(); - - ShowBodyInfoProperties(); - } - - private void ShowBodyInfoProperties() - { - m_ShowInfo.target = EditorGUILayout.Foldout(m_ShowInfo.target, "Info", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowInfo.faded)) - { - if (targets.Length == 1) - { - var body = targets[0] as Rigidbody2D; - EditorGUI.BeginDisabledGroup(true); - EditorGUILayout.Vector2Field("Position", body.position); - EditorGUILayout.FloatField("Rotation", body.rotation); - EditorGUILayout.Vector2Field("Velocity", body.velocity); - EditorGUILayout.FloatField("Angular Velocity", body.angularVelocity); - EditorGUILayout.FloatField("Inertia", body.inertia); - EditorGUILayout.Vector2Field("Local Center of Mass", body.centerOfMass); - EditorGUILayout.Vector2Field("World Center of Mass", body.worldCenterOfMass); - EditorGUILayout.LabelField("Sleep State", body.IsSleeping() ? "Asleep" : "Awake"); - EditorGUI.EndDisabledGroup(); - - ShowContacts(body); - - // We need to repaint as some of the above properties can change without causing a repaint. - Repaint(); - } - else - { - EditorGUILayout.HelpBox("Cannot show Info properties when multiple bodies are selected.", MessageType.Info); - } - } - FixedEndFadeGroup(m_ShowInfo.faded); - } - - void ShowContacts(Rigidbody2D body) - { - EditorGUI.indentLevel++; - m_ShowContacts.target = EditorGUILayout.Foldout(m_ShowContacts.target, "Contacts"); - if (EditorGUILayout.BeginFadeGroup(m_ShowContacts.faded)) - { - var contactCount = body.GetContacts(m_Contacts); - if (contactCount > 0) - { - m_ContactScrollPosition = EditorGUILayout.BeginScrollView(m_ContactScrollPosition, GUILayout.Height(180)); - EditorGUI.BeginDisabledGroup(true); - for (var i = 0; i < contactCount; ++i) - { - var contact = m_Contacts[i]; - EditorGUILayout.HelpBox(string.Format("Contact#{0}", i), MessageType.None); - EditorGUI.indentLevel++; - EditorGUILayout.Vector2Field("Point", contact.point); - EditorGUILayout.Vector2Field("Normal", contact.normal); - EditorGUILayout.Vector2Field("Relative Velocity", contact.relativeVelocity); - EditorGUILayout.FloatField("Normal Impulse", contact.normalImpulse); - EditorGUILayout.FloatField("Tangent Impulse", contact.tangentImpulse); - EditorGUILayout.ObjectField("Collider", contact.collider, typeof(Collider2D), true); - EditorGUILayout.ObjectField("Rigidbody", contact.rigidbody, typeof(Rigidbody2D), false); - EditorGUILayout.ObjectField("OtherCollider", contact.otherCollider, typeof(Collider2D), false); - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - EditorGUI.EndDisabledGroup(); - EditorGUILayout.EndScrollView(); - } - else - { - EditorGUILayout.HelpBox("No Contacts", MessageType.Info); - } - } - FixedEndFadeGroup(m_ShowContacts.faded); - EditorGUI.indentLevel--; - } - - // Fix for nested fade-groups as found here: - // http://answers.unity3d.com/questions/1096244/custom-editor-fade-group-inside-fade-group.html - static void FixedEndFadeGroup(float value) - { - if (value == 0.0f || value == 1.0f) - return; - - EditorGUILayout.EndFadeGroup(); - } - - void ConstraintToggle(Rect r, string label, RigidbodyConstraints2D value, int bit) - { - var toggle = ((int)value & (1 << bit)) != 0; - EditorGUI.showMixedValue = (m_Constraints.hasMultipleDifferentValuesBitwise & (1 << bit)) != 0; - EditorGUI.BeginChangeCheck(); - var oldIndent = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; - toggle = EditorGUI.ToggleLeft(r, label, toggle); - EditorGUI.indentLevel = oldIndent; - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObjects(targets, "Edit Constraints2D"); - m_Constraints.SetBitAtIndexForAllTargetsImmediate(bit, toggle); - } - EditorGUI.showMixedValue = false; - } - - void ToggleFreezePosition(RigidbodyConstraints2D constraints, GUIContent label, int x, int y) - { - GUILayout.BeginHorizontal(); - var r = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, EditorGUILayout.kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.numberField); - var id = GUIUtility.GetControlID(7231, FocusType.Keyboard, r); - r = EditorGUI.PrefixLabel(r, id, label); - r.width = k_ToggleOffset; - ConstraintToggle(r, "X", constraints, x); - r.x += k_ToggleOffset; - ConstraintToggle(r, "Y", constraints, y); - GUILayout.EndHorizontal(); - } - - void ToggleFreezeRotation(RigidbodyConstraints2D constraints, GUIContent label, int z) - { - GUILayout.BeginHorizontal(); - var r = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, EditorGUILayout.kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.numberField); - var id = GUIUtility.GetControlID(7231, FocusType.Keyboard, r); - r = EditorGUI.PrefixLabel(r, id, label); - r.width = k_ToggleOffset; - ConstraintToggle(r, "Z", constraints, z); - GUILayout.EndHorizontal(); - } - } -} diff --git a/Editor/Mono/Inspector/RigidbodyEditor.cs b/Editor/Mono/Inspector/RigidbodyEditor.cs deleted file mode 100644 index b735c29dee..0000000000 --- a/Editor/Mono/Inspector/RigidbodyEditor.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(Rigidbody))] - [CanEditMultipleObjects] - internal class RigidbodyEditor : Editor - { - SerializedProperty m_Constraints; - static GUIContent m_FreezePositionLabel = EditorGUIUtility.TrTextContent("Freeze Position"); - static GUIContent m_FreezeRotationLabel = EditorGUIUtility.TrTextContent("Freeze Rotation"); - - public void OnEnable() - { - m_Constraints = serializedObject.FindProperty("m_Constraints"); - } - - void ConstraintToggle(Rect r, string label, RigidbodyConstraints value, int bit) - { - bool toggle = ((int)value & (1 << bit)) != 0; - EditorGUI.showMixedValue = (m_Constraints.hasMultipleDifferentValuesBitwise & (1 << bit)) != 0; - EditorGUI.BeginChangeCheck(); - int oldIndent = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; - toggle = EditorGUI.ToggleLeft(r, label, toggle); - EditorGUI.indentLevel = oldIndent; - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObjects(targets, "Edit Constraints"); - m_Constraints.SetBitAtIndexForAllTargetsImmediate(bit, toggle); - } - EditorGUI.showMixedValue = false; - } - - void ToggleBlock(RigidbodyConstraints constraints, GUIContent label, int x, int y, int z) - { - const int toggleOffset = 30; - GUILayout.BeginHorizontal(); - Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, EditorGUILayout.kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.numberField); - int id = GUIUtility.GetControlID(7231, FocusType.Keyboard, r); - r = EditorGUI.PrefixLabel(r, id, label); - r.width = toggleOffset; - ConstraintToggle(r, "X", constraints, x); - r.x += toggleOffset; - ConstraintToggle(r, "Y", constraints, y); - r.x += toggleOffset; - ConstraintToggle(r, "Z", constraints, z); - GUILayout.EndHorizontal(); - } - - public override void OnInspectorGUI() - { - DrawDefaultInspector(); - GUILayout.BeginHorizontal(); - m_Constraints.isExpanded = EditorGUILayout.Foldout(m_Constraints.isExpanded, "Constraints", true); - GUILayout.EndHorizontal(); - - serializedObject.Update(); - RigidbodyConstraints constraints = (RigidbodyConstraints)m_Constraints.intValue; - if (m_Constraints.isExpanded) - { - EditorGUI.indentLevel++; - ToggleBlock(constraints, m_FreezePositionLabel, 1, 2, 3); - ToggleBlock(constraints, m_FreezeRotationLabel, 4, 5, 6); - EditorGUI.indentLevel--; - } - } - } -} diff --git a/Editor/Mono/Inspector/RotationConstraintEditor.cs b/Editor/Mono/Inspector/RotationConstraintEditor.cs deleted file mode 100644 index 647105e325..0000000000 --- a/Editor/Mono/Inspector/RotationConstraintEditor.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Animations; - -namespace UnityEditor -{ - [CustomEditor(typeof(RotationConstraint))] - [CanEditMultipleObjects] - internal class RotationConstraintEditor : ConstraintEditorBase - { - private SerializedProperty m_RotationAtRest; - private SerializedProperty m_RotationOffset; - private SerializedProperty m_Weight; - private SerializedProperty m_IsContraintActive; - private SerializedProperty m_IsLocked; - private SerializedProperty m_Sources; - - internal override SerializedProperty atRest { get { return m_RotationAtRest; } } - internal override SerializedProperty offset { get { return m_RotationOffset; } } - internal override SerializedProperty weight { get { return m_Weight; } } - internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } } - internal override SerializedProperty isLocked { get { return m_IsLocked; } } - internal override SerializedProperty sources { get { return m_Sources; } } - - private class Styles : ConstraintStyleBase - { - GUIContent m_RotationAtRest = EditorGUIUtility.TrTextContent("Rotation At Rest"); - GUIContent m_RotationOffset = EditorGUIUtility.TrTextContent("Rotation Offset"); - - GUIContent m_RotationAxes = EditorGUIUtility.TrTextContent("Freeze Rotation Axes"); - - public override GUIContent AtRest { get { return m_RotationAtRest; } } - public override GUIContent Offset { get { return m_RotationOffset; } } - public GUIContent FreezeAxes { get { return m_RotationAxes; } } - } - - private static Styles s_Style = null; - - public void OnEnable() - { - if (s_Style == null) - s_Style = new Styles(); - - m_RotationAtRest = serializedObject.FindProperty("m_RotationAtRest"); - m_RotationOffset = serializedObject.FindProperty("m_RotationOffset"); - m_Weight = serializedObject.FindProperty("m_Weight"); - m_IsContraintActive = serializedObject.FindProperty("m_IsContraintActive"); - m_IsLocked = serializedObject.FindProperty("m_IsLocked"); - m_Sources = serializedObject.FindProperty("m_Sources"); - - OnEnable(s_Style); - } - - internal override void OnValueAtRestChanged() - { - foreach (var t in targets) - (t as RotationConstraint).transform.SetLocalEulerAngles(atRest.vector3Value, RotationOrder.OrderZXY); - } - - internal override void ShowFreezeAxesControl() - { - Rect drawRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeAxes), EditorStyles.toggle); - EditorGUI.MultiPropertyField(drawRect, s_Style.Axes, serializedObject.FindProperty("m_AffectRotationX"), s_Style.FreezeAxes); - } - - public override void OnInspectorGUI() - { - if (s_Style == null) - s_Style = new Styles(); - - serializedObject.Update(); - - ShowConstraintEditor(s_Style); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/ScaleConstraintEditor.cs b/Editor/Mono/Inspector/ScaleConstraintEditor.cs deleted file mode 100644 index c286b8c2fe..0000000000 --- a/Editor/Mono/Inspector/ScaleConstraintEditor.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Animations; - -namespace UnityEditor -{ - [CustomEditor(typeof(ScaleConstraint))] - [CanEditMultipleObjects] - internal class ScaleConstraintEditor : ConstraintEditorBase - { - private SerializedProperty m_ScaleAtRest; - private SerializedProperty m_ScaleOffset; - private SerializedProperty m_Weight; - private SerializedProperty m_IsContraintActive; - private SerializedProperty m_IsLocked; - private SerializedProperty m_Sources; - - internal override SerializedProperty atRest { get { return m_ScaleAtRest; } } - internal override SerializedProperty offset { get { return m_ScaleOffset; } } - internal override SerializedProperty weight { get { return m_Weight; } } - internal override SerializedProperty isContraintActive { get { return m_IsContraintActive; } } - internal override SerializedProperty isLocked { get { return m_IsLocked; } } - internal override SerializedProperty sources { get { return m_Sources; } } - - private class Styles : ConstraintStyleBase - { - GUIContent m_ScaleAtRest = EditorGUIUtility.TrTextContent("Scale At Rest"); - GUIContent m_ScaleOffset = EditorGUIUtility.TrTextContent("Scale Offset"); - - GUIContent m_ScalingAxes = EditorGUIUtility.TrTextContent("Freeze Scaling Axes"); - - public override GUIContent AtRest { get { return m_ScaleAtRest; } } - public override GUIContent Offset { get { return m_ScaleOffset; } } - public GUIContent FreezeAxes { get { return m_ScalingAxes; } } - } - - private static Styles s_Style; - - public void OnEnable() - { - if (s_Style == null) - s_Style = new Styles(); - - m_ScaleAtRest = serializedObject.FindProperty("m_ScaleAtRest"); - m_ScaleOffset = serializedObject.FindProperty("m_ScaleOffset"); - m_Weight = serializedObject.FindProperty("m_Weight"); - m_IsContraintActive = serializedObject.FindProperty("m_IsContraintActive"); - m_IsLocked = serializedObject.FindProperty("m_IsLocked"); - m_Sources = serializedObject.FindProperty("m_Sources"); - - OnEnable(s_Style); - } - - internal override void OnValueAtRestChanged() - { - foreach (var t in targets) - (t as ScaleConstraint).transform.localScale = atRest.vector3Value; - } - - internal override void ShowFreezeAxesControl() - { - Rect drawRect = EditorGUILayout.GetControlRect(true, EditorGUI.GetPropertyHeight(SerializedPropertyType.Vector3, s_Style.FreezeAxes), EditorStyles.toggle); - EditorGUI.MultiPropertyField(drawRect, s_Style.Axes, serializedObject.FindProperty("m_AffectScalingX"), s_Style.FreezeAxes); - } - - public override void OnInspectorGUI() - { - if (s_Style == null) - s_Style = new Styles(); - - serializedObject.Update(); - - ShowConstraintEditor(s_Style); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs b/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs deleted file mode 100644 index 252497236f..0000000000 --- a/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs +++ /dev/null @@ -1,829 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.VersionControl; -using System.Collections.Generic; - -namespace UnityEditor -{ - [CustomEditor(typeof(MonoManager))] - internal class ScriptExecutionOrderInspector : Editor - { - /* - * @TODO - - Make it work with imported dll's + meta file serialization - */ - - internal override string targetTitle - { - get { return L10n.Tr("Script Execution Order"); } - } - - public class SortMonoScriptNameOrder : IComparer - { - public virtual int Compare(MonoScript x, MonoScript y) - { - if (x != null && y != null) - { - var xClass = x.GetClass(); - var yClass = y.GetClass(); - if (xClass != null && yClass != null) - return xClass.FullName.CompareTo(yClass.FullName); - - return x.name.CompareTo(y.name); - } - return -1; - } - } - - public class SortMonoScriptExecutionOrder : SortMonoScriptNameOrder - { - ScriptExecutionOrderInspector inspector; - - public SortMonoScriptExecutionOrder(ScriptExecutionOrderInspector inspector) - { - this.inspector = inspector; - } - - public override int Compare(MonoScript x, MonoScript y) - { - if (x != null && y != null) - { - int orderX = inspector.GetExecutionOrder(x); - int orderY = inspector.GetExecutionOrder(y); - if (orderX == orderY) - return base.Compare(x, y); - - return orderX.CompareTo(orderY); - } - return -1; - } - } - - private const int kOrderRangeMin = -32000; - private const int kOrderRangeMax = 32000; - private const int kListElementHeight = 21; - private const int kIntFieldWidth = 50; - private const int kPreferredSpacing = 100; - private int[] kRoundingAmounts = new int[] { 1000, 500, 100, 50, 10, 5, 1 }; - - private MonoScript m_Edited = null; - private List m_CustomTimeScripts; - private List m_DefaultTimeScripts; - private static MonoScript sDummyScript; - private Vector2 m_Scroll = Vector2.zero; - private static readonly List m_Instances = new List(); - - // Important that these 3 use data types that are serializable. - // That way we don't loose the unapplied reordering upon a script compile. - private MonoScript[] m_AllScripts; - private int[] m_AllOrders; - private bool m_DirtyOrders = false; - - private static int s_DropFieldHash = "DropField".GetHashCode(); - - public static Styles m_Styles; - - public class Styles - { - public 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.)"); - public GUIContent iconToolbarPlus = EditorGUIUtility.TrIconContent("Toolbar Plus", "Add script to custom order"); - public GUIContent iconToolbarMinus = EditorGUIUtility.TrIconContent("Toolbar Minus", "Remove script from custom order"); - public GUIContent defaultTimeContent = EditorGUIUtility.TrTextContent("Default Time", "All scripts not in the custom order are executed at the default time."); - public GUIStyle toolbar = "TE Toolbar"; - public GUIStyle toolbarDropDown = "TE ToolbarDropDown"; - public GUIStyle boxBackground = "TE NodeBackground"; - public GUIStyle removeButton = "InvisibleButton"; - public GUIStyle elementBackground = new GUIStyle("OL Box"); - public GUIStyle defaultTime = new GUIStyle(EditorStyles.inspectorBig); - public GUIStyle draggingHandle = "WindowBottomResize"; - public GUIStyle dropField = new GUIStyle(EditorStyles.objectFieldThumb); - - public Styles() - { - boxBackground.margin = new RectOffset(); - boxBackground.padding = new RectOffset(1, 1, 1, 0); - - elementBackground.overflow = new RectOffset(1, 1, 1, 0); - - defaultTime.alignment = TextAnchor.MiddleCenter; - defaultTime.overflow = new RectOffset(0, 0, 1, 0); - - // Drop field style that has extra overflow and is only visible when "on". - // Used to draw a blue glow when dragging scripts into the ordering to - // indicate that drag-and-drop is supported. - dropField.overflow = new RectOffset(2, 2, 2, 2); - dropField.normal.background = null; - dropField.hover.background = null; - dropField.active.background = null; - dropField.focused.background = null; - } - } - - [MenuItem("CONTEXT/MonoManager/Reset")] - private static void Reset(MenuCommand cmd) - { - var instances = ScriptExecutionOrderInspector.GetInstances(); - - foreach (var instance in instances) - { - for (var i = 0; i < instance.m_AllOrders.Length; i++) - instance.m_AllOrders[i] = 0; - - instance.Apply(); - } - } - - public void OnEnable() - { - if (sDummyScript == null) - sDummyScript = new MonoScript(); - - // Don't reload the order if an unapplied reordering exists - if (m_AllScripts == null || !m_DirtyOrders) - PopulateScriptArray(); - - if (!m_Instances.Contains(this)) - m_Instances.Add(this); - - EditorApplication.playModeStateChanged += OnPlayModeStateChanged; - } - - public void OnDisable() - { - EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; - } - - private void AskApplyRevertIfNecessary() - { - if (!m_DirtyOrders) - return; - - if (EditorUtility.DisplayDialog("Unapplied execution order", "Unapplied script execution order", "Apply", "Revert")) - Apply(); - } - - private void OnPlayModeStateChanged(PlayModeStateChange state) - { - if (state != PlayModeStateChange.ExitingEditMode) - return; - - AskApplyRevertIfNecessary(); - } - - static Object MonoScriptValidatorCallback(Object[] references, System.Type objType, SerializedProperty property, EditorGUI.ObjectFieldValidatorOptions options) - { - foreach (Object i in references) - { - var monoScript = i as MonoScript; - if (monoScript != null && IsValidScript(monoScript)) - { - return monoScript; - } - } - return null; - } - - static bool IsValidScript(MonoScript script) - { - if (script == null) - return false; - - // The user can only define the order of scripts that contains valid classes (see case 579536) - if (script.GetClass() == null) - return false; - - // Only allow MonoBehaviours and ScriptableObjects - bool isMonoBehaviour = typeof(MonoBehaviour).IsAssignableFrom(script.GetClass()); - bool isScriptableObject = typeof(ScriptableObject).IsAssignableFrom(script.GetClass()); - if (!isMonoBehaviour && !isScriptableObject) - { - return false; - } - - // The user can only define the order of scripts in the assets folder. - if (AssetDatabase.GetAssetPath(script).IndexOf("Assets/") != 0) - return false; - - return true; - } - - internal static List GetInstances() - { - return m_Instances; - } - - void PopulateScriptArray() - { - m_AllScripts = MonoImporter.GetAllRuntimeMonoScripts(); - m_AllOrders = new int[m_AllScripts.Length]; - - // Create cleaned up list of scripts - m_CustomTimeScripts = new List(); - m_DefaultTimeScripts = new List(); - for (int i = 0; i < m_AllScripts.Length; i++) - { - MonoScript script = m_AllScripts[i]; - m_AllOrders[i] = MonoImporter.GetExecutionOrder(script); - - if (!IsValidScript(script)) - continue; - - if (GetExecutionOrder(script) == 0) - m_DefaultTimeScripts.Add(script); - else - m_CustomTimeScripts.Add(script); - } - - // Add two dummy items used for the default time area - m_CustomTimeScripts.Add(sDummyScript); - m_CustomTimeScripts.Add(sDummyScript); - - // Assign and sort - m_CustomTimeScripts.Sort(new SortMonoScriptExecutionOrder(this)); - m_DefaultTimeScripts.Sort(new SortMonoScriptNameOrder()); - m_Edited = null; - - m_DirtyOrders = false; - } - - private int GetExecutionOrder(MonoScript script) - { - int index = System.Array.IndexOf(m_AllScripts, script); - if (index >= 0) - return m_AllOrders[index]; - return 0; - } - - private void SetExecutionOrder(MonoScript script, int order) - { - int index = System.Array.IndexOf(m_AllScripts, script); - if (index >= 0) - { - m_AllOrders[index] = Mathf.Clamp(order, kOrderRangeMin, kOrderRangeMax); - m_DirtyOrders = true; - } - } - - private void Apply() - { - var changedIndices = new List(); - var changedScripts = new List(); - for (int i = 0; i < m_AllScripts.Length; i++) - { - if (MonoImporter.GetExecutionOrder(m_AllScripts[i]) != m_AllOrders[i]) - { - changedIndices.Add(i); - changedScripts.Add(m_AllScripts[i]); - } - } - - bool editable = true; - - if (Provider.enabled) - { - var task = Provider.Checkout(changedScripts.ToArray(), CheckoutMode.Meta); - task.Wait(); - editable = task.success; - } - - if (editable) - { - foreach (int index in changedIndices) - MonoImporter.SetExecutionOrder(m_AllScripts[index], m_AllOrders[index]); - - PopulateScriptArray(); - } - else - { - Debug.LogError("Could not checkout scrips in version control for changing script execution order"); - } - } - - private void Revert() - { - PopulateScriptArray(); - } - - private void OnDestroy() - { - if (m_Instances.Contains(this)) - m_Instances.Remove(this); - - if (!Application.isPlaying) - AskApplyRevertIfNecessary(); - } - - private void ApplyRevertGUI() - { - EditorGUILayout.Space(); - bool wasEnabled = GUI.enabled; - GUI.enabled = m_DirtyOrders; - - GUILayout.BeginHorizontal(); - { - GUILayout.FlexibleSpace(); - - if (GUILayout.Button("Revert")) - Revert(); - - if (GUILayout.Button("Apply")) - Apply(); - } GUILayout.EndHorizontal(); - - GUI.enabled = wasEnabled; - } - - private void MenuSelection(object userData, string[] options, int selected) - { - AddScriptToCustomOrder(m_DefaultTimeScripts[selected]); - } - - private void AddScriptToCustomOrder(MonoScript script) - { - if (!IsValidScript(script)) - return; - - if (m_CustomTimeScripts.Contains(script)) - return; - - int orderOfAddedScript = RoundByAmount(GetExecutionOrderAtIndex(m_CustomTimeScripts.Count - 1) + kPreferredSpacing, kPreferredSpacing); - SetExecutionOrder(script, orderOfAddedScript); - m_CustomTimeScripts.Add(script); - m_DefaultTimeScripts.Remove(script); - } - - private void ShowScriptPopup(Rect r) - { - int length = m_DefaultTimeScripts.Count; - string[] names = new string[length]; - bool[] enabled = new bool[length]; - for (int c = 0; c < length; c++) - { - names[c] = m_DefaultTimeScripts[c].GetClass().FullName; - enabled[c] = true; - } - EditorUtility.DisplayCustomMenu(r, names, enabled, null, MenuSelection, null); - } - - private int RoundBasedOnContext(int val, int lowerBound, int upperBound) - { - // Make the bounds a bit closer to avoid the value ending up right next to one of the bounds - int fraction = Mathf.Max(0, (upperBound - lowerBound) / 6); - lowerBound += fraction; - upperBound -= fraction; - - // Round by smaller amounts until we find a value that fit within the bounds - for (int i = 0; i < kRoundingAmounts.Length; i++) - { - int roundedVal = RoundByAmount(val, kRoundingAmounts[i]); - if (roundedVal > lowerBound && roundedVal < upperBound) - return roundedVal; - } - - return val; - } - - private int RoundByAmount(int val, int rounding) - { - return Mathf.RoundToInt(val / (float)rounding) * rounding; - } - - private int GetAverageRoundedAwayFromZero(int a, int b) - { - if ((a + b) % 2 == 0) - return (a + b) / 2; - else - return (a + b + System.Math.Sign(a + b)) / 2; - } - - private void SetExecutionOrderAtIndexAccordingToNeighbors(int indexOfChangedItem, int pushDirection) - { - // Ignore invalid index - if (indexOfChangedItem < 0 || indexOfChangedItem >= m_CustomTimeScripts.Count) - return; - - // Set order if changed is first in list - if (indexOfChangedItem == 0) - { - SetExecutionOrderAtIndex( - indexOfChangedItem, - RoundByAmount(GetExecutionOrderAtIndex(indexOfChangedItem + 1) - kPreferredSpacing, kPreferredSpacing)); - return; - } - - // Set order if changed is last in list - if (indexOfChangedItem == m_CustomTimeScripts.Count - 1) - { - SetExecutionOrderAtIndex( - indexOfChangedItem, - RoundByAmount(GetExecutionOrderAtIndex(indexOfChangedItem - 1) + kPreferredSpacing, kPreferredSpacing)); - return; - } - - // Make nr average of prev and next script nr, but rounded to a nice round number - int prevOrder = GetExecutionOrderAtIndex(indexOfChangedItem - 1); - int nextOrder = GetExecutionOrderAtIndex(indexOfChangedItem + 1); - int newAverageExecutionOrder = RoundBasedOnContext(GetAverageRoundedAwayFromZero(prevOrder, nextOrder), prevOrder, nextOrder); - - if (newAverageExecutionOrder != 0) - { - if (pushDirection == 0) - pushDirection = GetBestPushDirectionForOrderValue(newAverageExecutionOrder); - - // Ensure new value is at least one higher/lower than the neighbor - if (pushDirection > 0) - newAverageExecutionOrder = Mathf.Max(newAverageExecutionOrder, prevOrder + 1); - else - newAverageExecutionOrder = Mathf.Min(newAverageExecutionOrder, nextOrder - 1); - } - - SetExecutionOrderAtIndex(indexOfChangedItem, newAverageExecutionOrder); - } - - private void UpdateOrder(MonoScript changedScript) - { - // Remove the script prior to reordering - // Remember to add later, either to custom or default time list - m_CustomTimeScripts.Remove(changedScript); - - int changedScriptOrder = GetExecutionOrder(changedScript); - - // If script order was set to zero, script gets removed from list, so no reordering needed - if (changedScriptOrder == 0) - { - m_DefaultTimeScripts.Add(changedScript); - m_DefaultTimeScripts.Sort(new SortMonoScriptNameOrder()); - return; - } - - // See if any other scripts have an order that conflicts with the one just moved - int conflictedIndex = -1; - for (int i = 0; i < m_CustomTimeScripts.Count; i++) - { - if (GetExecutionOrderAtIndex(i) == changedScriptOrder) - { - conflictedIndex = i; - break; - } - } - - // If not, add the changed script back and sort orders. - // This will also happen if there' only one script in the custom order, - // so we don't need to worry about that case further down. - if (conflictedIndex == -1) - { - m_CustomTimeScripts.Add(changedScript); - m_CustomTimeScripts.Sort(new SortMonoScriptExecutionOrder(this)); - return; - } - - int pushDirection = GetBestPushDirectionForOrderValue(changedScriptOrder); - if (pushDirection == 1) - { - m_CustomTimeScripts.Insert(conflictedIndex, changedScript); - conflictedIndex++; - } - else - { - m_CustomTimeScripts.Insert(conflictedIndex + 1, changedScript); - } - - PushAwayToAvoidConflicts(conflictedIndex, pushDirection); - } - - private void PushAwayToAvoidConflicts(int startIndex, int pushDirection) - { - int curIndex = startIndex; - while (curIndex >= 0 && curIndex < m_CustomTimeScripts.Count) - { - // Check if there's any conflict between the order at this index and the previous one. If not, stop here. - if ((GetExecutionOrderAtIndex(curIndex) - GetExecutionOrderAtIndex(curIndex - pushDirection)) * pushDirection >= 1) - break; - - SetExecutionOrderAtIndexAccordingToNeighbors(curIndex, pushDirection); - curIndex += pushDirection; - } - } - - private int GetBestPushDirectionForOrderValue(int order) - { - // If there's any conflicts we want to push neighboring scripts until the conflict has been resolved. - // However, we can't push the order of any script past 0 (from either direction) - // or past the minimum or maximum allowed order values. - // 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. - // This should only be able to fail if the user has more than 16000 scripts (a quarter of the total range). - int pushDirection = (int)Mathf.Sign(order); - if (order < kOrderRangeMin / 2 || order > kOrderRangeMax / 2) - pushDirection = -pushDirection; - return pushDirection; - } - - public override bool UseDefaultMargins() { return false; } - - public override void OnInspectorGUI() - { - if (m_Styles == null) - m_Styles = new Styles(); - - if (m_Edited) - { - UpdateOrder(m_Edited); - m_Edited = null; - } - - EditorGUILayout.BeginVertical(EditorStyles.inspectorFullWidthMargins); - { - GUILayout.Label(m_Styles.helpText, EditorStyles.helpBox); - - EditorGUILayout.Space(); - - // Vertical that contains box and the toolbar below it - Rect listRect = EditorGUILayout.BeginVertical(); - { - int dropFieldId = EditorGUIUtility.GetControlID(s_DropFieldHash, FocusType.Passive, listRect); - MonoScript dropped = EditorGUI.DoDropField(listRect, dropFieldId, typeof(MonoScript), MonoScriptValidatorCallback, false, m_Styles.dropField) as MonoScript; - if (dropped) - AddScriptToCustomOrder(dropped); - - // Vertical that is used as a border around the scrollview - EditorGUILayout.BeginVertical(m_Styles.boxBackground); - { - // The scrollview itself - m_Scroll = EditorGUILayout.BeginVerticalScrollView(m_Scroll); - { - // List - Rect r = GUILayoutUtility.GetRect(10, kListElementHeight * m_CustomTimeScripts.Count, GUILayout.ExpandWidth(true)); - int changed = DragReorderGUI.DragReorder(r, kListElementHeight, m_CustomTimeScripts, DrawElement); - if (changed >= 0) - { - // Give dragged item value in between neighbors - SetExecutionOrderAtIndexAccordingToNeighbors(changed, 0); - // Update neighbors if needed - UpdateOrder(m_CustomTimeScripts[changed]); - // Neighbors may have been moved so there's more space around dragged item, - // so set order again to get possible rounding benefits - SetExecutionOrderAtIndexAccordingToNeighbors(changed, 0); - } - } EditorGUILayout.EndScrollView(); - } EditorGUILayout.EndVertical(); - - // The toolbar below the box - GUILayout.BeginHorizontal(m_Styles.toolbar); - { - GUILayout.FlexibleSpace(); - Rect r2; - GUIContent content = m_Styles.iconToolbarPlus; - r2 = GUILayoutUtility.GetRect(content, m_Styles.toolbarDropDown); - if (EditorGUI.DropdownButton(r2, content, FocusType.Passive, m_Styles.toolbarDropDown)) - ShowScriptPopup(r2); - } GUILayout.EndHorizontal(); - } GUILayout.EndVertical(); - - ApplyRevertGUI(); - } GUILayout.EndVertical(); - - GUILayout.FlexibleSpace(); - } - - int GetExecutionOrderAtIndex(int idx) - { - return GetExecutionOrder(m_CustomTimeScripts[idx]); - } - - void SetExecutionOrderAtIndex(int idx, int order) - { - SetExecutionOrder(m_CustomTimeScripts[idx], order); - } - - private Rect GetButtonLabelRect(Rect r) - { - return new Rect(r.x + 20, r.y + 1, r.width - GetMinusButtonSize().x - 10 - 20 - (kIntFieldWidth + 5), r.height); - } - - private Rect GetAddRemoveButtonRect(Rect r) - { - var buttonSize = GetMinusButtonSize(); - - return new Rect(r.xMax - buttonSize.x - 5, r.y + 1, buttonSize.x, buttonSize.y); - } - - private Rect GetFieldRect(Rect r) - { - return new Rect(r.xMax - kIntFieldWidth - GetMinusButtonSize().x - 10, r.y + 2, kIntFieldWidth, r.height - 5); - } - - private Vector2 GetMinusButtonSize() - { - return m_Styles.removeButton.CalcSize(m_Styles.iconToolbarMinus); - } - - private Rect GetDraggingHandleRect(Rect r) - { - return new Rect(r.x + 5, r.y + 7, 10, r.height - 14); - } - - public void DrawElement(Rect r, object obj, bool dragging) - { - MonoScript script = obj as MonoScript; - - if (Event.current.type == EventType.Repaint) - { - m_Styles.elementBackground.Draw(r, false, false, false, false); - m_Styles.draggingHandle.Draw(GetDraggingHandleRect(r), false, false, false, false); - } - - GUI.Label(GetButtonLabelRect(r), script.GetClass().FullName); - - int oldNr = GetExecutionOrder(script); - Rect position = GetFieldRect(r); - // 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 - int id = GUIUtility.GetControlID(script.GetHashCode(), FocusType.Keyboard, position); - string intStr = EditorGUI.DelayedTextFieldInternal(position, id, GUIContent.none, oldNr.ToString(), "0123456789-", EditorStyles.textField); - int newNr = oldNr; - if (System.Int32.TryParse(intStr, out newNr) && newNr != oldNr) - { - SetExecutionOrder(script, newNr); - m_Edited = script; - } - - if (GUI.Button(GetAddRemoveButtonRect(r), m_Styles.iconToolbarMinus, m_Styles.removeButton)) - { - SetExecutionOrder(script, 0); - m_Edited = script; - } - } - - class DragReorderGUI - { - public delegate void DrawElementDelegate(Rect r, object obj, bool dragging); - - private static int s_ReorderingDraggedElement; - private static float[] s_ReorderingPositions; - private static int[] s_ReorderingGoals; - private static int s_DragReorderGUIHash = "DragReorderGUI".GetHashCode(); - - private static bool IsDefaultTimeElement(MonoScript element) - { - return (element.name == string.Empty); - } - - public static int DragReorder(Rect position, int elementHeight, List elements, DrawElementDelegate drawElementDelegate) - { - int id = GUIUtility.GetControlID(s_DragReorderGUIHash, FocusType.Passive); - - Rect elementRect = position; - elementRect.height = elementHeight; - - int defPos = 0; - Rect defRect; - - // If we're dragging, draw elements based on their animated reordering positions, - // but only for repainting. Control event handling does't like to suddenly change order, - // so things will screw up if we HANDLE the controls in a different order when dragging. - if (GUIUtility.hotControl == id && Event.current.type == EventType.Repaint) - { - for (int i = 0; i < elements.Count; i++) - { - // Don't draw the dragged element as part of loop - if (i == s_ReorderingDraggedElement) - continue; - if (IsDefaultTimeElement(elements[i])) - { - defPos = i; - i++; - continue; - } - elementRect.y = position.y + s_ReorderingPositions[i] * elementHeight; - drawElementDelegate(elementRect, elements[i], false); - } - defRect = new Rect(elementRect.x, position.y + s_ReorderingPositions[defPos] * elementHeight, elementRect.width, (s_ReorderingPositions[defPos + 1] - s_ReorderingPositions[defPos] + 1) * elementHeight); - } - // For everything else than repainting while dragging, - // draw controls based on their positions in the array. - else - { - for (int i = 0; i < elements.Count; i++) - { - elementRect.y = position.y + i * elementHeight; - if (IsDefaultTimeElement(elements[i])) - { - defPos = i; - i++; - continue; - } - drawElementDelegate(elementRect, elements[i], false); - } - defRect = new Rect(elementRect.x, position.y + defPos * elementHeight, elementRect.width, elementHeight * 2); - } - - GUI.Label(defRect, m_Styles.defaultTimeContent, m_Styles.defaultTime); - - bool isAddingToDefault = defRect.height > elementHeight * 2.5f; - - if (GUIUtility.hotControl == id) - { - if (isAddingToDefault) - GUI.color = new Color(1, 1, 1, 0.5f); - // Draw the dragged element after all the other ones - elementRect.y = position.y + s_ReorderingPositions[s_ReorderingDraggedElement] * elementHeight; - drawElementDelegate(elementRect, elements[s_ReorderingDraggedElement], true); - - GUI.color = Color.white; - } - - int changed = -1; - EventType type = Event.current.GetTypeForControl(id); - switch (type) - { - case EventType.MouseDown: - if (position.Contains(Event.current.mousePosition)) - { - GUIUtility.keyboardControl = 0; - EditorGUI.EndEditingActiveTextField(); - - s_ReorderingDraggedElement = Mathf.FloorToInt((Event.current.mousePosition.y - position.y) / elementHeight); - if (!IsDefaultTimeElement(elements[s_ReorderingDraggedElement])) - { - s_ReorderingPositions = new float[elements.Count]; - s_ReorderingGoals = new int[elements.Count]; - for (int i = 0; i < elements.Count; i++) - { - s_ReorderingGoals[i] = i; - s_ReorderingPositions[i] = i; - } - GUIUtility.hotControl = id; - Event.current.Use(); - } - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl != id) - break; - - // Set reordering position of dragged element based on mouse cursor - s_ReorderingPositions[s_ReorderingDraggedElement] = (Event.current.mousePosition.y - position.y) / elementHeight - 0.5f; - // Clamp to range of list - s_ReorderingPositions[s_ReorderingDraggedElement] = Mathf.Clamp(s_ReorderingPositions[s_ReorderingDraggedElement], 0, elements.Count - 1); - // Set draggedToPosition based on dragged position - int draggedToPosition = Mathf.RoundToInt(s_ReorderingPositions[s_ReorderingDraggedElement]); - - // if dragged to a new position, re-assign goals - if (draggedToPosition != s_ReorderingGoals[s_ReorderingDraggedElement]) - { - // Reset - for (int i = 0; i < elements.Count; i++) - s_ReorderingGoals[i] = i; - // Find direction that other elements must be moved in - int direction = (draggedToPosition > s_ReorderingDraggedElement ? -1 : 1); - - // Move goals of elements to make room for the dragged one - for (int i = s_ReorderingDraggedElement; i != draggedToPosition; i -= direction) - s_ReorderingGoals[i - direction] = i; - - // At last, move the goal of the dragged element - s_ReorderingGoals[s_ReorderingDraggedElement] = draggedToPosition; - } - Event.current.Use(); - break; - case EventType.MouseUp: - if (GUIUtility.hotControl != id) - break; - - if (s_ReorderingGoals[s_ReorderingDraggedElement] != s_ReorderingDraggedElement) - { - // Reorder array according to the reordering goals - List reorderedArray = new List(elements); - for (int i = 0; i < elements.Count; i++) - elements[s_ReorderingGoals[i]] = reorderedArray[i]; - - // Return which elements was just moved - changed = s_ReorderingGoals[s_ReorderingDraggedElement]; - } - - // Reset - s_ReorderingGoals = null; - s_ReorderingPositions = null; - s_ReorderingDraggedElement = -1; - GUIUtility.hotControl = 0; - Event.current.Use(); - break; - case EventType.Repaint: - // Animate elements to move towards their goals - if (GUIUtility.hotControl == id) - { - for (int i = 0; i < elements.Count; i++) - if (i != s_ReorderingDraggedElement) - s_ReorderingPositions[i] = Mathf.MoveTowards(s_ReorderingPositions[i], s_ReorderingGoals[i], 0.075f); - GUIView.current.Repaint(); - } - break; - } - - return changed; - } - } - } -} diff --git a/Editor/Mono/Inspector/ShaderGUI.cs b/Editor/Mono/Inspector/ShaderGUI.cs deleted file mode 100644 index a48ba6cbb5..0000000000 --- a/Editor/Mono/Inspector/ShaderGUI.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - public abstract class ShaderGUI - { - virtual public void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) - { - materialEditor.PropertiesDefaultGUI(properties); - } - - virtual public void OnMaterialPreviewGUI(MaterialEditor materialEditor, Rect r, GUIStyle background) - { - materialEditor.DefaultPreviewGUI(r, background); - } - - virtual public void OnMaterialInteractivePreviewGUI(MaterialEditor materialEditor, Rect r, GUIStyle background) - { - materialEditor.DefaultPreviewGUI(r, background); - } - - virtual public void OnMaterialPreviewSettingsGUI(MaterialEditor materialEditor) - { - materialEditor.DefaultPreviewSettingsGUI(); - } - - virtual public void OnClosed(Material material) - { - } - - virtual public void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) - { - material.shader = newShader; - } - - // Utility methods - protected static MaterialProperty FindProperty(string propertyName, MaterialProperty[] properties) - { - return FindProperty(propertyName, properties, true); - } - - protected static MaterialProperty FindProperty(string propertyName, MaterialProperty[] properties, bool propertyIsMandatory) - { - for (var i = 0; i < properties.Length; i++) - if (properties[i] != null && properties[i].name == propertyName) - return properties[i]; - - // We assume all required properties can be found, otherwise something is broken - if (propertyIsMandatory) - throw new ArgumentException("Could not find MaterialProperty: '" + propertyName + "', Num properties: " + properties.Length); - return null; - } - } - - internal static class ShaderGUIUtility - { - private static Type ExtractCustomEditorType(string customEditorName) - { - if (string.IsNullOrEmpty(customEditorName)) return null; - - // To allow users to implement their own ShaderGUI for the Standard shader we iterate in reverse order - // because the UnityEditor assembly is assumed first in the assembly list. - // Users can now place a copy of the StandardShaderGUI script in the project and start modifying that copy to make their own version. - - string unityEditorFullName = "UnityEditor." + customEditorName; // for convenience: adding UnityEditor namespace is not needed in the shader - - var editorAssemblies = EditorAssemblies.loadedAssemblies; - for (int i = editorAssemblies.Length - 1; i >= 0; i--) - { - foreach (var type in AssemblyHelper.GetTypesFromAssembly(editorAssemblies[i])) - { - if (type.FullName.Equals(customEditorName, StringComparison.Ordinal) || type.FullName.Equals(unityEditorFullName, StringComparison.Ordinal)) - return typeof(ShaderGUI).IsAssignableFrom(type) ? type : null; - } - } - return null; - } - - internal static ShaderGUI CreateShaderGUI(string customEditorName) - { - Type customEditorType = ExtractCustomEditorType(customEditorName); - return customEditorType != null ? (Activator.CreateInstance(customEditorType) as ShaderGUI) : null; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/Inspector/ShaderImporterInspector.cs b/Editor/Mono/Inspector/ShaderImporterInspector.cs deleted file mode 100644 index f44e2e258b..0000000000 --- a/Editor/Mono/Inspector/ShaderImporterInspector.cs +++ /dev/null @@ -1,235 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.Experimental.AssetImporters; -using System.Linq; -using System.Reflection; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - [CustomEditor(typeof(ShaderImporter))] - internal class ShaderImporterInspector : AssetImporterEditor - { - private class TextureProp - { - public string propertyName; - public string displayName; - public Texture texture; - public UnityEngine.Rendering.TextureDimension dimension; - public bool modifiable; - } - - private List m_Properties = new List(); - - internal override void OnHeaderControlsGUI() - { - GUILayout.FlexibleSpace(); - - if (GUILayout.Button("Open...", EditorStyles.miniButton)) - { - AssetDatabase.OpenAsset(assetTarget); - GUIUtility.ExitGUI(); - } - } - - public override void OnEnable() - { - ResetValues(); - } - - private void ShowTextures() - { - if (m_Properties.Count == 0) - return; - - EditorGUILayout.LabelField("Default Maps", EditorStyles.boldLabel); - for (var i = 0; i < m_Properties.Count; i++) - { - if (!m_Properties[i].modifiable) - continue; - - DrawTextureField(m_Properties[i]); - } - - EditorGUILayout.LabelField("NonModifiable Maps", EditorStyles.boldLabel); - for (var i = 0; i < m_Properties.Count; i++) - { - if (m_Properties[i].modifiable) - continue; - - DrawTextureField(m_Properties[i]); - } - } - - private void DrawTextureField(TextureProp prop) - { - var oldTexture = prop.texture; - Texture newTexture = null; - - EditorGUI.BeginChangeCheck(); - - System.Type textureType = MaterialEditor.GetTextureTypeFromDimension(prop.dimension); - - if (textureType != null) - { - // Require at least two character in display name to prevent names like "-" - var text = string.IsNullOrEmpty(prop.displayName) ? ObjectNames.NicifyVariableName(prop.propertyName) : prop.displayName; - newTexture = EditorGUILayout.MiniThumbnailObjectField(GUIContent.Temp(text), oldTexture, textureType) as Texture; - } - - if (EditorGUI.EndChangeCheck()) - prop.texture = newTexture; - } - - public override bool HasModified() - { - if (base.HasModified()) - return true; - - var importer = target as ShaderImporter; - if (importer == null) - return false; - - var shader = importer.GetShader(); - if (shader == null) - return false; - - var propertyCount = ShaderUtil.GetPropertyCount(shader); - for (var i = 0; i < propertyCount; i++) - { - var propertyName = ShaderUtil.GetPropertyName(shader, i); - for (var k = 0; k < m_Properties.Count; k++) - { - if (m_Properties[k].propertyName == propertyName) - { - var tex = m_Properties[k].modifiable ? importer.GetDefaultTexture(propertyName) : importer.GetNonModifiableTexture(propertyName); - if (m_Properties[k].texture != tex) - return true; - } - } - } - return false; - } - - protected override void ResetValues() - { - base.ResetValues(); - - m_Properties.Clear(); - - var importer = target as ShaderImporter; - if (importer == null) - return; - - var shader = importer.GetShader(); - if (shader == null) - return; - - var propertyCount = ShaderUtil.GetPropertyCount(shader); - - for (var i = 0; i < propertyCount; i++) - { - if (ShaderUtil.GetPropertyType(shader, i) != ShaderUtil.ShaderPropertyType.TexEnv) - continue; - - var propertyName = ShaderUtil.GetPropertyName(shader, i); - var displayName = ShaderUtil.GetPropertyDescription(shader, i); // might be empty - var modifiable = !ShaderUtil.IsShaderPropertyNonModifiableTexureProperty(shader, i); - - Texture tex; - if (!modifiable) - tex = importer.GetNonModifiableTexture(propertyName); - else - tex = importer.GetDefaultTexture(propertyName); - - var temp = new TextureProp - { - propertyName = propertyName, - texture = tex, - dimension = ShaderUtil.GetTexDim(shader, i), - displayName = displayName, - modifiable = modifiable - }; - m_Properties.Add(temp); - } - } - - protected override void Apply() - { - base.Apply(); - - var importer = target as ShaderImporter; - if (importer == null) - return; - - var defaultNames = m_Properties.Where(x => x.modifiable).Select(x => x.propertyName).ToArray(); - var defaultTextures = m_Properties.Where(x => x.modifiable).Select(x => x.texture).ToArray(); - importer.SetDefaultTextures(defaultNames, defaultTextures); - - var nonModNames = m_Properties.Where(x => !x.modifiable).Select(x => x.propertyName).ToArray(); - var nonModTextures = m_Properties.Where(x => !x.modifiable).Select(x => x.texture).ToArray(); - importer.SetNonModifiableTextures(nonModNames, nonModTextures); - - AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(importer)); - } - - private static int GetNumberOfTextures(Shader shader) - { - int numberOfTextures = 0; - var propertyCount = ShaderUtil.GetPropertyCount(shader); - - for (var i = 0; i < propertyCount; i++) - { - if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv) - numberOfTextures++; - } - return numberOfTextures; - } - - public override void OnInspectorGUI() - { - var importer = target as ShaderImporter; - if (importer == null) - return; - - var shader = importer.GetShader(); - if (shader == null) - return; - - if (GetNumberOfTextures(shader) != m_Properties.Count) - ResetValues(); - - ShowTextures(); - ApplyRevertGUI(); - } - - private static string[] s_ShaderIncludePaths = null; - [RequiredByNativeCode] - internal static string[] GetShaderIncludePaths() - { - if (s_ShaderIncludePaths == null) - { - List results = new List(); - var methods = AttributeHelper.GetMethodsWithAttribute(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly); - foreach (var method in methods.methodsWithAttributes) - { - if (method.info.ReturnType == typeof(string[]) && method.info.GetParameters().Length == 0) - { - var result = method.info.Invoke(null, new object[] {}) as string[]; - if (result != null) - results.AddRange(result); - } - } - // The paths appear in the list in random order. We sort the list here so that the same paths will always - // result into the exact same list. Otherwise the shader importer will think the paths have changed. - results.Sort(); - s_ShaderIncludePaths = results.ToArray(); - } - return s_ShaderIncludePaths; - } - } -} diff --git a/Editor/Mono/Inspector/ShaderIncludePathAttribute.cs b/Editor/Mono/Inspector/ShaderIncludePathAttribute.cs deleted file mode 100644 index 965696df1c..0000000000 --- a/Editor/Mono/Inspector/ShaderIncludePathAttribute.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor -{ - [AttributeUsage(AttributeTargets.Method)] - public class ShaderIncludePathAttribute : Attribute - { - [RequiredSignature] - static extern string[] GetIncludePaths(); - } -} diff --git a/Editor/Mono/Inspector/ShaderInspector.cs b/Editor/Mono/Inspector/ShaderInspector.cs deleted file mode 100644 index 7f3e7347b5..0000000000 --- a/Editor/Mono/Inspector/ShaderInspector.cs +++ /dev/null @@ -1,604 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Globalization; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [CustomEditor(typeof(Shader))] - internal class ShaderInspector : Editor - { - private static readonly string[] kPropertyTypes = - { - "Color: ", - "Vector: ", - "Float: ", - "Range: ", - "Texture: " - }; - private static readonly string[] kTextureTypes = - { - "No Texture?: ", - "Any texture: ", - "2D: ", - "3D: ", - "Cube: ", - "2DArray: ", - "CubeArray: " - }; - - private const float kSpace = 5f; - - internal class Styles - { - public static Texture2D errorIcon = EditorGUIUtility.LoadIcon("console.erroricon.sml"); - public static Texture2D warningIcon = EditorGUIUtility.LoadIcon("console.warnicon.sml"); - - public static GUIContent showSurface = EditorGUIUtility.TrTextContent("Show generated code", "Show generated code of a surface shader"); - public static GUIContent showFF = EditorGUIUtility.TrTextContent("Show generated code", "Show generated code of a fixed function shader"); - 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" - - public static GUIStyle messageStyle = "CN StatusInfo"; - public static GUIStyle evenBackground = "CN EntryBackEven"; - - public static GUIContent no = EditorGUIUtility.TrTextContent("no"); - public static GUIContent builtinShader = EditorGUIUtility.TrTextContent("Built-in shader"); - } - static readonly int kErrorViewHash = "ShaderErrorView".GetHashCode(); - - Vector2 m_ScrollPosition = Vector2.zero; - - public virtual void OnEnable() - { - var s = target as Shader; - ShaderUtil.FetchCachedErrors(s); - } - - private static string GetPropertyType(Shader s, int index) - { - ShaderUtil.ShaderPropertyType type = ShaderUtil.GetPropertyType(s, index); - if (type == ShaderUtil.ShaderPropertyType.TexEnv) - { - return kTextureTypes[(int)ShaderUtil.GetTexDim(s, index)]; - } - return kPropertyTypes[(int)type]; - } - - public override void OnInspectorGUI() - { - var s = target as Shader; - if (s == null) - return; - - GUI.enabled = true; - - EditorGUI.indentLevel = 0; - - ShowShaderCodeArea(s); - - if (s.isSupported) - { - EditorGUILayout.LabelField("Cast shadows", (ShaderUtil.HasShadowCasterPass(s)) ? "yes" : "no"); - EditorGUILayout.LabelField("Render queue", ShaderUtil.GetRenderQueue(s).ToString(CultureInfo.InvariantCulture)); - EditorGUILayout.LabelField("LOD", ShaderUtil.GetLOD(s).ToString(CultureInfo.InvariantCulture)); - EditorGUILayout.LabelField("Ignore projector", ShaderUtil.DoesIgnoreProjector(s) ? "yes" : "no"); - string disableBatchingString; - switch (s.disableBatching) - { - case DisableBatchingType.False: - disableBatchingString = "no"; - break; - case DisableBatchingType.True: - disableBatchingString = "yes"; - break; - case DisableBatchingType.WhenLODFading: - disableBatchingString = "when LOD fading is on"; - break; - default: - disableBatchingString = "unknown"; - break; - } - EditorGUILayout.LabelField("Disable batching", disableBatchingString); - ShowShaderProperties(s); - } - } - - private void ShowShaderCodeArea(Shader s) - { - ShowSurfaceShaderButton(s); - ShowFixedFunctionShaderButton(s); - ShowCompiledCodeButton(s); - ShowShaderErrors(s); - } - - private static void ShowShaderProperties(Shader s) - { - GUILayout.Space(kSpace); - GUILayout.Label("Properties:", EditorStyles.boldLabel); - int n = ShaderUtil.GetPropertyCount(s); - for (int i = 0; i < n; ++i) - { - string pname = ShaderUtil.GetPropertyName(s, i); - string pdesc = GetPropertyType(s, i) + ShaderUtil.GetPropertyDescription(s, i); - EditorGUILayout.LabelField(pname, pdesc); - } - } - - // shared by compute shader inspector too - internal static void ShaderErrorListUI(Object shader, ShaderError[] errors, ref Vector2 scrollPosition) - { - int n = errors.Length; - - GUILayout.Space(kSpace); - GUILayout.Label(string.Format("Errors ({0}):", n), EditorStyles.boldLabel); - int errorListID = GUIUtility.GetControlID(kErrorViewHash, FocusType.Passive); - float height = Mathf.Min(n * 20f + 40f, 150f); - scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUISkin.current.box, GUILayout.MinHeight(height)); - - EditorGUIUtility.SetIconSize(new Vector2(16.0f, 16.0f)); - float lineHeight = Styles.messageStyle.CalcHeight(EditorGUIUtility.TempContent(Styles.errorIcon), 100); - - Event e = Event.current; - - for (int i = 0; i < n; ++i) - { - Rect r = EditorGUILayout.GetControlRect(false, lineHeight); - - string err = errors[i].message; - string plat = errors[i].platform; - bool warn = errors[i].warning != 0; - string fileName = FileUtil.GetLastPathNameComponent(errors[i].file); - int line = errors[i].line; - - // Double click opens shader file at error line - if (e.type == EventType.MouseDown && e.button == 0 && r.Contains(e.mousePosition)) - { - GUIUtility.keyboardControl = errorListID; - if (e.clickCount == 2) - { - string filePath = errors[i].file; - Object asset = string.IsNullOrEmpty(filePath) ? null : AssetDatabase.LoadMainAssetAtPath(filePath); - - // if we don't have an asset and the filePath is an absolute path, it's an error in a system - // cginc - open that instead - if (asset == null && System.IO.Path.IsPathRooted(filePath)) - ShaderUtil.OpenSystemShaderIncludeError(filePath, line); - else - AssetDatabase.OpenAsset(asset ?? shader, line); - GUIUtility.ExitGUI(); - } - e.Use(); - } - - // Context menu, "Copy" - if (e.type == EventType.ContextClick && r.Contains(e.mousePosition)) - { - e.Use(); - var menu = new GenericMenu(); - // need to copy current value to be used in delegate - // (C# closures close over variables, not their values) - var errorIndex = i; - menu.AddItem(EditorGUIUtility.TrTextContent("Copy error text"), false, delegate { - string errMsg = errors[errorIndex].message; - if (!string.IsNullOrEmpty(errors[errorIndex].messageDetails)) - { - errMsg += '\n'; - errMsg += errors[errorIndex].messageDetails; - } - EditorGUIUtility.systemCopyBuffer = errMsg; - }); - menu.ShowAsContext(); - } - - // background - if (e.type == EventType.Repaint) - { - if ((i & 1) == 0) - { - GUIStyle st = Styles.evenBackground; - st.Draw(r, false, false, false, false); - } - } - - // error location on the right side - Rect locRect = r; - locRect.xMin = locRect.xMax; - if (line > 0) - { - GUIContent gc; - if (string.IsNullOrEmpty(fileName)) - gc = EditorGUIUtility.TempContent(line.ToString(CultureInfo.InvariantCulture)); - else - gc = EditorGUIUtility.TempContent(fileName + ":" + line.ToString(CultureInfo.InvariantCulture)); - - // calculate size so we can right-align it - Vector2 size = EditorStyles.miniLabel.CalcSize(gc); - locRect.xMin -= size.x; - GUI.Label(locRect, gc, EditorStyles.miniLabel); - locRect.xMin -= 2; - // ensure some minimum width so that platform field next will line up - if (locRect.width < 30) - locRect.xMin = locRect.xMax - 30; - } - - // platform to the left of it - Rect platRect = locRect; - platRect.width = 0; - if (plat.Length > 0) - { - GUIContent gc = EditorGUIUtility.TempContent(plat); - // calculate size so we can right-align it - Vector2 size = EditorStyles.miniLabel.CalcSize(gc); - platRect.xMin -= size.x; - - // draw platform in dimmer color; it's often not very important information - Color oldColor = GUI.contentColor; - GUI.contentColor = new Color(1, 1, 1, 0.5f); - GUI.Label(platRect, gc, EditorStyles.miniLabel); - GUI.contentColor = oldColor; - platRect.xMin -= 2; - } - - // error message - Rect msgRect = r; - msgRect.xMax = platRect.xMin; - GUI.Label(msgRect, EditorGUIUtility.TempContent(err, warn ? Styles.warningIcon : Styles.errorIcon), Styles.messageStyle); - } - EditorGUIUtility.SetIconSize(Vector2.zero); - GUILayout.EndScrollView(); - } - - private void ShowShaderErrors(Shader s) - { - int n = ShaderUtil.GetShaderErrorCount(s); - if (n < 1) - return; - ShaderErrorListUI(s, ShaderUtil.GetShaderErrors(s), ref m_ScrollPosition); - } - - // Compiled shader code button+dropdown - private void ShowCompiledCodeButton(Shader s) - { - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel("Compiled code", EditorStyles.miniButton); - - var hasCode = ShaderUtil.HasShaderSnippets(s) || ShaderUtil.HasSurfaceShaders(s) || ShaderUtil.HasFixedFunctionShaders(s); - if (hasCode) - { - // button with a drop-down part on the right - var modeContent = Styles.showCurrent; - var modeRect = GUILayoutUtility.GetRect(modeContent, EditorStyles.miniButton, GUILayout.ExpandWidth(false)); - var modeDropRect = new Rect(modeRect.xMax - 16, modeRect.y, 16, modeRect.height); - if (EditorGUI.DropdownButton(modeDropRect, GUIContent.none, FocusType.Passive, GUIStyle.none)) - { - Rect rect = GUILayoutUtility.topLevel.GetLast(); - PopupWindow.Show(rect, new ShaderInspectorPlatformsPopup(s)); - GUIUtility.ExitGUI(); - } - if (GUI.Button(modeRect, modeContent, EditorStyles.miniButton)) - { - ShaderUtil.OpenCompiledShader(s, ShaderInspectorPlatformsPopup.currentMode, ShaderInspectorPlatformsPopup.currentPlatformMask, ShaderInspectorPlatformsPopup.currentVariantStripping == 0); - GUIUtility.ExitGUI(); - } - } - else - { - // Note: PrefixLabel is sometimes buggy if followed by a non-control (like Label). - // We just want to show a label here, but have to pretend it's a button so it is treated like - // a control. - GUILayout.Button("none (precompiled shader)", GUI.skin.label); - } - - EditorGUILayout.EndHorizontal(); - } - - // "show surface shader" button - private static void ShowSurfaceShaderButton(Shader s) - { - var hasSurface = ShaderUtil.HasSurfaceShaders(s); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel("Surface shader", EditorStyles.miniButton); - if (hasSurface) - { - // check if this is a built-in shader (has no importer); - // we can't show generated code in that case - var builtinShader = (AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(s)) == null); - if (!builtinShader) - { - if (GUILayout.Button(Styles.showSurface, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - { - ShaderUtil.OpenParsedSurfaceShader(s); - GUIUtility.ExitGUI(); - } - } - else - { - // See comment below why this is a button. - GUILayout.Button(Styles.builtinShader, GUI.skin.label); - } - } - else - { - // Note: PrefixLabel is sometimes buggy if followed by a non-control (like Label). - // We just want to show a label here, but have to pretend it's a button so it is treated like - // a control. - GUILayout.Button(Styles.no, GUI.skin.label); - } - EditorGUILayout.EndHorizontal(); - } - - // "show fixed function shader" button - private static void ShowFixedFunctionShaderButton(Shader s) - { - var hasFF = ShaderUtil.HasFixedFunctionShaders(s); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel("Fixed function", EditorStyles.miniButton); - if (hasFF) - { - // check if this is a built-in shader (has no importer); - // we can't show generated code in that case - var builtinShader = (AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(s)) == null); - if (!builtinShader) - { - if (GUILayout.Button(Styles.showFF, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - { - ShaderUtil.OpenGeneratedFixedFunctionShader(s); - GUIUtility.ExitGUI(); - } - } - else - { - // See comment below why this is a button. - GUILayout.Button(Styles.builtinShader, GUI.skin.label); - } - } - else - { - // Note: PrefixLabel is sometimes buggy if followed by a non-control (like Label). - // We just want to show a label here, but have to pretend it's a button so it is treated like - // a control. - GUILayout.Button(Styles.no, GUI.skin.label); - } - EditorGUILayout.EndHorizontal(); - } - } - - - // Popup window to select which platforms to compile a shader for. - internal class ShaderInspectorPlatformsPopup : PopupWindowContent - { - private class Styles - { - static public readonly GUIStyle menuItem = "MenuItem"; - static public readonly GUIStyle separator = "sv_iconselector_sep"; - } - - static internal readonly string[] s_PlatformModes = - { - "Current graphics device", - "Current build platform", - "All platforms", - "Custom:" - }; - - private static string[] s_ShaderPlatformNames; - private static int[] s_ShaderPlatformIndices; - - const float kFrameWidth = 1f; - const float kSeparatorHeight = 6; - - private readonly Shader m_Shader; - - - public static int currentMode - { - get - { - if (s_CurrentMode < 0) - s_CurrentMode = EditorPrefs.GetInt("ShaderInspectorPlatformMode", 1); - return s_CurrentMode; - } - set - { - s_CurrentMode = value; - EditorPrefs.SetInt("ShaderInspectorPlatformMode", value); - } - } - static int s_CurrentMode = -1; - - public static int currentPlatformMask - { - get - { - if (s_CurrentPlatformMask < 0) - { - const int defaultMask = (1 << (int)ShaderUtil.ShaderCompilerPlatformType.Count) - 1; - s_CurrentPlatformMask = EditorPrefs.GetInt("ShaderInspectorPlatformMask", defaultMask); - } - return s_CurrentPlatformMask; - } - set - { - s_CurrentPlatformMask = value; - EditorPrefs.SetInt("ShaderInspectorPlatformMask", value); - } - } - static int s_CurrentPlatformMask = -1; - - public static int currentVariantStripping - { - get - { - if (s_CurrentVariantStripping < 0) - s_CurrentVariantStripping = EditorPrefs.GetInt("ShaderInspectorVariantStripping", 1); - return s_CurrentVariantStripping; - } - set - { - s_CurrentVariantStripping = value; - EditorPrefs.SetInt("ShaderInspectorVariantStripping", value); - } - } - static int s_CurrentVariantStripping = -1; - - - public ShaderInspectorPlatformsPopup(Shader shader) - { - m_Shader = shader; - InitializeShaderPlatforms(); - } - - static void InitializeShaderPlatforms() - { - if (s_ShaderPlatformNames != null) - return; - int platformMask = ShaderUtil.GetAvailableShaderCompilerPlatforms(); - var names = new List(); - var indices = new List(); - for (int i = 0; i < 32; ++i) - { - if ((platformMask & (1 << i)) == 0) - continue; - names.Add(((ShaderUtil.ShaderCompilerPlatformType)i).ToString()); - indices.Add(i); - } - s_ShaderPlatformNames = names.ToArray(); - s_ShaderPlatformIndices = indices.ToArray(); - } - - public override Vector2 GetWindowSize() - { - var rowCount = s_PlatformModes.Length + s_ShaderPlatformNames.Length + 2; - var windowHeight = rowCount * EditorGUI.kSingleLineHeight + kSeparatorHeight * 3; - windowHeight += 2 * kFrameWidth; - - var windowSize = new Vector2(210, windowHeight); - return windowSize; - } - - public override void OnGUI(Rect rect) - { - if (m_Shader == null) - return; - - // We do not use the layout event - if (Event.current.type == EventType.Layout) - return; - - Draw(editorWindow, rect.width); - - // Use mouse move so we get hover state correctly in the menu item rows - if (Event.current.type == EventType.MouseMove) - Event.current.Use(); - - // Escape closes the window - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - { - editorWindow.Close(); - GUIUtility.ExitGUI(); - } - } - - private void DrawSeparator(ref Rect rect) - { - GUI.Label(new Rect(rect.x + 5, rect.y + 3, rect.width - 10, 3), GUIContent.none, Styles.separator); - rect.y += kSeparatorHeight; - } - - private void Draw(EditorWindow caller, float listElementWidth) - { - var drawPos = new Rect(0, 0, listElementWidth, EditorGUI.kSingleLineHeight); - - // Generic platform modes - for (var i = 0; i < s_PlatformModes.Length; ++i) - { - DoOneMode(drawPos, i); - drawPos.y += EditorGUI.kSingleLineHeight; - } - - // Custom platform settings - Color oldColor = GUI.color; - if (currentMode != 3) // darker color when "Custom" is not selected - GUI.color *= new Color(1, 1, 1, 0.7f); - drawPos.xMin += 16.0f; - for (var i = 0; i < s_ShaderPlatformNames.Length; ++i) - { - DoCustomPlatformBit(drawPos, i); - drawPos.y += EditorGUI.kSingleLineHeight; - } - GUI.color = oldColor; - drawPos.xMin -= 16.0f; - DrawSeparator(ref drawPos); - - DoShaderVariants(caller, ref drawPos); - } - - void DoOneMode(Rect rect, int index) - { - EditorGUI.BeginChangeCheck(); - GUI.Toggle(rect, currentMode == index, EditorGUIUtility.TempContent(s_PlatformModes[index]), Styles.menuItem); - if (EditorGUI.EndChangeCheck()) - currentMode = index; - } - - void DoCustomPlatformBit(Rect rect, int index) - { - EditorGUI.BeginChangeCheck(); - int maskBit = 1 << s_ShaderPlatformIndices[index]; - bool on = (currentPlatformMask & maskBit) != 0; - on = GUI.Toggle(rect, on, EditorGUIUtility.TempContent(s_ShaderPlatformNames[index]), Styles.menuItem); - if (EditorGUI.EndChangeCheck()) - { - if (on) - currentPlatformMask |= maskBit; - else - currentPlatformMask &= ~maskBit; - currentMode = 3; // custom - } - } - - static string FormatCount(ulong count) - { - if (count > 1000 * 1000 * 1000) - return ((double)count / 1000000000.0).ToString("f2") + "B"; - if (count > 1000 * 1000) - return ((double)count / 1000000.0).ToString("f2") + "M"; - if (count > 1000) - return ((double)count / 1000.0).ToString("f2") + "k"; - return count.ToString(); - } - - void DoShaderVariants(EditorWindow caller, ref Rect drawPos) - { - // setting for whether shader variants should be stripped - EditorGUI.BeginChangeCheck(); - bool strip = GUI.Toggle(drawPos, currentVariantStripping == 1, EditorGUIUtility.TempContent("Skip unused shader_features"), Styles.menuItem); - drawPos.y += EditorGUI.kSingleLineHeight; - if (EditorGUI.EndChangeCheck()) - currentVariantStripping = strip ? 1 : 0; - - // display included variant count, and a button to show list of them - drawPos.y += kSeparatorHeight; - ulong variantCount = ShaderUtil.GetVariantCount(m_Shader, strip); - var variantText = FormatCount(variantCount) + - (strip ? - " variants included" : - " variants total"); - Rect buttonRect = drawPos; - buttonRect.x += Styles.menuItem.padding.left; - buttonRect.width -= Styles.menuItem.padding.left + 4; - GUI.Label(buttonRect, variantText); - buttonRect.xMin = buttonRect.xMax - 40; - if (GUI.Button(buttonRect, "Show", EditorStyles.miniButton)) - { - ShaderUtil.OpenShaderCombinations(m_Shader, strip); - caller.Close(); - GUIUtility.ExitGUI(); - } - } - } -} diff --git a/Editor/Mono/Inspector/ShaderVariantCollectionInspector.cs b/Editor/Mono/Inspector/ShaderVariantCollectionInspector.cs deleted file mode 100644 index 3b4b89c0b7..0000000000 --- a/Editor/Mono/Inspector/ShaderVariantCollectionInspector.cs +++ /dev/null @@ -1,402 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - [CustomEditor(typeof(ShaderVariantCollection))] - internal class ShaderVariantCollectionInspector : Editor - { - private class Styles - { - public static readonly GUIContent iconAdd = EditorGUIUtility.TrIconContent("Toolbar Plus", "Add variant"); - public static readonly GUIContent iconRemove = EditorGUIUtility.TrIconContent("Toolbar Minus", "Remove entry"); - public static readonly GUIStyle invisibleButton = "InvisibleButton"; - } - - SerializedProperty m_Shaders; - - - public virtual void OnEnable() - { - m_Shaders = serializedObject.FindProperty("m_Shaders"); - } - - static Rect GetAddRemoveButtonRect(Rect r) - { - var buttonSize = Styles.invisibleButton.CalcSize(Styles.iconRemove); - return new Rect(r.xMax - buttonSize.x, r.y + (int)(r.height / 2 - buttonSize.y / 2), buttonSize.x, buttonSize.y); - } - - // Show window to select shader variants - void DisplayAddVariantsWindow(Shader shader, ShaderVariantCollection collection) - { - var data = new AddShaderVariantWindow.PopupData(); - data.shader = shader; - data.collection = collection; - string[] keywordStrings; - ShaderUtil.GetShaderVariantEntries(shader, collection, out data.types, out keywordStrings); - if (keywordStrings.Length == 0) - { - // nothing available to add - EditorApplication.Beep(); - return; - } - - data.keywords = new string[keywordStrings.Length][]; - for (var i = 0; i < keywordStrings.Length; ++i) - { - data.keywords[i] = keywordStrings[i].Split(' '); - } - AddShaderVariantWindow.ShowAddVariantWindow(data); - GUIUtility.ExitGUI(); - } - - void DrawShaderEntry(int shaderIndex) - { - var entryProp = m_Shaders.GetArrayElementAtIndex(shaderIndex); - Shader shader = (Shader)entryProp.FindPropertyRelative("first").objectReferenceValue; - - // Shader name and button to remove it - var variantsProp = entryProp.FindPropertyRelative("second.variants"); - using (new GUILayout.HorizontalScope()) - { - Rect rowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.boldLabel); - Rect minusRect = GetAddRemoveButtonRect(rowRect); - rowRect.xMax = minusRect.x; - GUI.Label(rowRect, shader.name, EditorStyles.boldLabel); - if (GUI.Button(minusRect, Styles.iconRemove, Styles.invisibleButton)) - { - m_Shaders.DeleteArrayElementAtIndex(shaderIndex); - return; - } - } - - // Variants for this shader - for (var i = 0; i < variantsProp.arraySize; ++i) - { - var prop = variantsProp.GetArrayElementAtIndex(i); - var keywords = prop.FindPropertyRelative("keywords").stringValue; - if (string.IsNullOrEmpty(keywords)) - keywords = ""; - var passType = (UnityEngine.Rendering.PassType)prop.FindPropertyRelative("passType").intValue; - Rect rowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.miniLabel); - Rect minusRect = GetAddRemoveButtonRect(rowRect); - - - // Variant entry with button to remove it - rowRect.xMax = minusRect.x; - GUI.Label(rowRect, passType + " " + keywords, EditorStyles.miniLabel); - if (GUI.Button(minusRect, Styles.iconRemove, Styles.invisibleButton)) - { - variantsProp.DeleteArrayElementAtIndex(i); - } - } - // Add variant button - Rect addRowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.miniLabel); - Rect plusRect = GetAddRemoveButtonRect(addRowRect); - if (GUI.Button(plusRect, Styles.iconAdd, Styles.invisibleButton)) - { - DisplayAddVariantsWindow(shader, target as ShaderVariantCollection); - } - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - for (var i = 0; i < m_Shaders.arraySize; ++i) - { - DrawShaderEntry(i); - } - - // Button to add a new shader to collection - if (GUILayout.Button("Add shader")) - { - // Show object selector - ObjectSelector.get.Show(null, typeof(Shader), null, false); - ObjectSelector.get.objectSelectorID = "ShaderVariantSelector".GetHashCode(); - GUIUtility.ExitGUI(); - } - if (Event.current.type == EventType.ExecuteCommand) - { - // New shader picked in object selector; add it to the collection - if (Event.current.commandName == ObjectSelector.ObjectSelectorClosedCommand && ObjectSelector.get.objectSelectorID == "ShaderVariantSelector".GetHashCode()) - { - var newShader = ObjectSelector.GetCurrentObject() as Shader; - if (newShader != null) - { - ShaderUtil.AddNewShaderToCollection(newShader, target as ShaderVariantCollection); - } - Event.current.Use(); - GUIUtility.ExitGUI(); - } - } - - serializedObject.ApplyModifiedProperties(); - } - } - - - // Utility window for selecting shader variants to add. - // Some shaders (Standard, SpeedTree etc.) have massive amounts of variants - // (e.g. about 30000), and approaches like "display a popup menu with all of them" - // don't work. - internal class AddShaderVariantWindow : EditorWindow - { - internal class PopupData - { - public Shader shader; - public ShaderVariantCollection collection; - // list of all shader variants that are in the shader but not in collection yet - // (for each: pass type and shader keywords) - public int[] types; - public string[][] keywords; - } - - class Styles - { - public static readonly GUIStyle sMenuItem = "MenuItem"; - public static readonly GUIStyle sSeparator = "sv_iconselector_sep"; - } - - const float kMargin = 2; - const float kSpaceHeight = 6; - const float kSeparatorHeight = 3; - - private const float kMinWindowWidth = 400; - const float kMiscUIHeight = - 5 * EditorGUI.kSingleLineHeight + - kSeparatorHeight * 2 + - kSpaceHeight * 5 + - kMargin * 2; - - private const float kMinWindowHeight = 9 * EditorGUI.kSingleLineHeight + kMiscUIHeight; - - PopupData m_Data; - List m_SelectedKeywords; - List m_AvailableKeywords; // Other keywords still available in the currently filtered variants for further narrowing down - List m_FilteredVariants; // Indices of variants that pass the keyword filter - List m_SelectedVariants; // Indices of variants currently selected for adding - - public AddShaderVariantWindow() - { - position = new Rect(100, 100, kMinWindowWidth * 1.5f, kMinWindowHeight * 1.5f); - minSize = new Vector2(kMinWindowWidth, kMinWindowHeight); - wantsMouseMove = true; - } - - private void Initialize(PopupData data) - { - m_Data = data; - m_SelectedKeywords = new List(); - m_AvailableKeywords = new List(); - m_SelectedVariants = new List(); - m_AvailableKeywords.Sort(); - m_FilteredVariants = new List(); - ApplyKeywordFilter(); - } - - public static void ShowAddVariantWindow(PopupData data) - { - var w = EditorWindow.GetWindow(true, "Add shader " + data.shader.name + " variants to collection"); - w.Initialize(data); - w.m_Parent.window.m_DontSaveToLayout = true; - } - - void ApplyKeywordFilter() - { - m_FilteredVariants.Clear(); - m_AvailableKeywords.Clear(); - - // Go over all variants and see which ones pass the selected keywords filter - for (var i = 0; i < m_Data.keywords.Length; ++i) - { - bool containsAll = true; - for (var j = 0; j < m_SelectedKeywords.Count; ++j) - { - if (!m_Data.keywords[i].Contains(m_SelectedKeywords[j])) - { - containsAll = false; - break; - } - } - if (containsAll) - { - // Contains all keywords -> passed the filter - m_FilteredVariants.Add(i); - // Add keywords in this variant that aren't selected yet into "available" set - foreach (var k in m_Data.keywords[i]) - { - if (!m_AvailableKeywords.Contains(k) && !m_SelectedKeywords.Contains(k)) - m_AvailableKeywords.Add(k); - } - } - } - - m_AvailableKeywords.Sort(); - } - - public void OnGUI() - { - // Objects became deleted while our window was showing? Close. - if (m_Data == null || m_Data.shader == null || m_Data.collection == null) - { - Close(); - return; - } - - // We do not use the layout event - if (Event.current.type == EventType.Layout) - return; - - Rect rect = new Rect(0, 0, position.width, position.height); - Draw(rect); - - // Repaint on mouse move so we get hover highlights in menu item rows - if (Event.current.type == EventType.MouseMove) - Repaint(); - } - - private bool KeywordButton(Rect buttonRect, string k, Vector2 areaSize) - { - // If we can't fit all buttons (shader has *a lot* of keywords) and would start clipping, - // do display the partially clipped ones with some transparency. - var oldColor = GUI.color; - if (buttonRect.yMax > areaSize.y) - GUI.color = new Color(1, 1, 1, 0.4f); - - var result = GUI.Button(buttonRect, EditorGUIUtility.TempContent(k), EditorStyles.miniButton); - GUI.color = oldColor; - return result; - } - - float CalcVerticalSpaceForKeywords() - { - return Mathf.Floor((position.height - kMiscUIHeight) / 4); - } - - float CalcVerticalSpaceForVariants() - { - return (position.height - kMiscUIHeight) / 2; - } - - void DrawKeywordsList(ref Rect rect, List keywords, bool clickingAddsToSelected) - { - rect.height = CalcVerticalSpaceForKeywords(); - var displayKeywords = keywords.Select(k => string.IsNullOrEmpty(k) ? "" : k.ToLowerInvariant()).ToList(); - - GUI.BeginGroup(rect); - Rect indentRect = new Rect(4, 0, rect.width, rect.height); - var layoutRects = EditorGUIUtility.GetFlowLayoutedRects(indentRect, EditorStyles.miniButton, 2, 2, displayKeywords); - for (var i = 0; i < displayKeywords.Count; ++i) - { - if (KeywordButton(layoutRects[i], displayKeywords[i], rect.size)) - { - if (clickingAddsToSelected) - { - m_SelectedKeywords.Add(keywords[i]); - m_SelectedKeywords.Sort(); - } - else - { - m_SelectedKeywords.Remove(keywords[i]); - } - ApplyKeywordFilter(); - GUIUtility.ExitGUI(); - } - } - GUI.EndGroup(); - rect.y += rect.height; - } - - void DrawSectionHeader(ref Rect rect, string titleString, bool separator) - { - // space - rect.y += kSpaceHeight; - // separator - if (separator) - { - rect.height = kSeparatorHeight; - GUI.Label(rect, GUIContent.none, Styles.sSeparator); - rect.y += rect.height; - } - // label - rect.height = EditorGUI.kSingleLineHeight; - GUI.Label(rect, titleString); - rect.y += rect.height; - } - - private void Draw(Rect windowRect) - { - var rect = new Rect(kMargin, kMargin, windowRect.width - kMargin * 2, EditorGUI.kSingleLineHeight); - - DrawSectionHeader(ref rect, "Pick shader keywords to narrow down variant list:", false); - DrawKeywordsList(ref rect, m_AvailableKeywords, true); - - DrawSectionHeader(ref rect, "Selected keywords:", true); - DrawKeywordsList(ref rect, m_SelectedKeywords, false); - - DrawSectionHeader(ref rect, "Shader variants with these keywords (click to select):", true); - - if (m_FilteredVariants.Count > 0) - { - int maxFilteredLength = (int)(CalcVerticalSpaceForVariants() / EditorGUI.kSingleLineHeight); - - // Display first N variants (don't want to display thousands of them if filter is not narrow) - for (var i = 0; i < Mathf.Min(m_FilteredVariants.Count, maxFilteredLength); ++i) - { - var index = m_FilteredVariants[i]; - var passType = (UnityEngine.Rendering.PassType)m_Data.types[index]; - var wasSelected = m_SelectedVariants.Contains(index); - var displayString = passType.ToString() + " " + string.Join(" ", m_Data.keywords[index]).ToLowerInvariant(); - var isSelected = GUI.Toggle(rect, wasSelected, displayString, Styles.sMenuItem); - rect.y += rect.height; - - if (isSelected && !wasSelected) - m_SelectedVariants.Add(index); - else if (!isSelected && wasSelected) - m_SelectedVariants.Remove(index); - } - - // show how many variants we skipped due to filter not being narrow enough - if (m_FilteredVariants.Count > maxFilteredLength) - { - GUI.Label(rect, string.Format("[{0} more variants skipped]", m_FilteredVariants.Count - maxFilteredLength), EditorStyles.miniLabel); - rect.y += rect.height; - } - } - else - { - GUI.Label(rect, "No variants with these keywords"); - rect.y += rect.height; - } - - // Button to add them at the bottom of popup - rect.y = windowRect.height - kMargin - kSpaceHeight - EditorGUI.kSingleLineHeight; - rect.height = EditorGUI.kSingleLineHeight; - // Disable button if no variants selected - using (new EditorGUI.DisabledScope(m_SelectedVariants.Count == 0)) - { - if (GUI.Button(rect, string.Format("Add {0} selected variants", m_SelectedVariants.Count))) - { - // Add the selected variants - Undo.RecordObject(m_Data.collection, "Add variant"); - for (var i = 0; i < m_SelectedVariants.Count; ++i) - { - var index = m_SelectedVariants[i]; - var variant = new ShaderVariantCollection.ShaderVariant(m_Data.shader, (UnityEngine.Rendering.PassType)m_Data.types[index], m_Data.keywords[index]); - m_Data.collection.Add(variant); - } - // Close our popup - Close(); - GUIUtility.ExitGUI(); - } - } - } - } -} diff --git a/Editor/Mono/Inspector/ShadowCascadeSplitGUI.cs b/Editor/Mono/Inspector/ShadowCascadeSplitGUI.cs deleted file mode 100644 index f6f0408fec..0000000000 --- a/Editor/Mono/Inspector/ShadowCascadeSplitGUI.cs +++ /dev/null @@ -1,216 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Linq; - -namespace UnityEditor -{ - /** - * Internal class for handling the drawing of ShadowCascade splits GUI and user interaction. - */ - internal static class ShadowCascadeSplitGUI - { - private const int kSliderbarTopMargin = 2; - private const int kSliderbarHeight = 24; - private const int kSliderbarBottomMargin = 2; - private const int kPartitionHandleWidth = 2; - private const int kPartitionHandleExtraHitAreaWidth = 2; - - private static readonly Color[] kCascadeColors = - { - new Color(0.5f, 0.5f, 0.6f, 1.0f), - new Color(0.5f, 0.6f, 0.5f, 1.0f), - new Color(0.6f, 0.6f, 0.5f, 1.0f), - new Color(0.6f, 0.5f, 0.5f, 1.0f), - }; - - // using a LODGroup skin - private static readonly GUIStyle s_CascadeSliderBG = "LODSliderRange"; - private static readonly GUIStyle s_TextCenteredStyle = new GUIStyle(EditorStyles.whiteMiniLabel) - { - alignment = TextAnchor.MiddleCenter - }; - - // Internal struct to bundle drag information - private class DragCache - { - public int m_ActivePartition; // the cascade partition that we are currently dragging/resizing - public float m_NormalizedPartitionSize; // the normalized size of the partition (0.0f < size < 1.0f) - public Vector2 m_LastCachedMousePosition; // mouse position the last time we registered a drag or mouse down. - - public DragCache(int activePartition, float normalizedPartitionSize, Vector2 currentMousePos) - { - m_ActivePartition = activePartition; - m_NormalizedPartitionSize = normalizedPartitionSize; - m_LastCachedMousePosition = currentMousePos; - } - }; - private static DragCache s_DragCache; - - private static readonly int s_CascadeSliderId = "s_CascadeSliderId".GetHashCode(); - - private static SceneView s_RestoreSceneView; - private static SceneView.CameraMode s_OldSceneDrawMode; - private static bool s_OldSceneLightingMode; - - - /** - * Static function to handle the GUI and User input related to the cascade slider. - * - * @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 - * The last entry will be automatically determined by summing up the array, and doing 1.0f - sum - */ - public static void HandleCascadeSliderGUI(ref float[] normalizedCascadePartitions) - { - GUILayout.Label("Cascade splits"); - - // get the inspector width since we need it while drawing the partition rects. - // Only way currently is to reserve the block in the layout using GetRect(), and then immediately drawing the empty box - // to match the call to GetRect. - // From this point on, we move to non-layout based code. - var sliderRect = GUILayoutUtility.GetRect(GUIContent.none - , s_CascadeSliderBG - , GUILayout.Height(kSliderbarTopMargin + kSliderbarHeight + kSliderbarBottomMargin) - , GUILayout.ExpandWidth(true)); - GUI.Box(sliderRect, GUIContent.none); - - float currentX = sliderRect.x; - float cascadeBoxStartY = sliderRect.y + kSliderbarTopMargin; - float cascadeSliderWidth = sliderRect.width - (normalizedCascadePartitions.Length * kPartitionHandleWidth); - Color origTextColor = GUI.color; - Color origBackgroundColor = GUI.backgroundColor; - int colorIndex = -1; - - // setup the array locally with the last partition - float[] adjustedCascadePartitions = new float[normalizedCascadePartitions.Length + 1]; - Array.Copy(normalizedCascadePartitions, adjustedCascadePartitions, normalizedCascadePartitions.Length); - adjustedCascadePartitions[adjustedCascadePartitions.Length - 1] = 1.0f - normalizedCascadePartitions.Sum(); - - - // check for user input on any of the partition handles - // this mechanism gets the current event in the queue... make sure that the mouse is over our control before consuming the event - int sliderControlId = GUIUtility.GetControlID(s_CascadeSliderId, FocusType.Passive); - Event currentEvent = Event.current; - int hotPartitionHandleIndex = -1; // the index of any partition handle that we are hovering over or dragging - - // draw each cascade partition - for (int i = 0; i < adjustedCascadePartitions.Length; ++i) - { - float currentPartition = adjustedCascadePartitions[i]; - - colorIndex = (colorIndex + 1) % kCascadeColors.Length; - GUI.backgroundColor = kCascadeColors[colorIndex]; - float boxLength = (cascadeSliderWidth * currentPartition); - - // main cascade box - Rect partitionRect = new Rect(currentX, cascadeBoxStartY, boxLength, kSliderbarHeight); - GUI.Box(partitionRect, GUIContent.none, s_CascadeSliderBG); - currentX += boxLength; - - // cascade box percentage text - GUI.color = Color.white; - Rect textRect = partitionRect; - var cascadeText = string.Format("{0}\n{1:F1}%", i, currentPartition * 100.0f); - - GUI.Label(textRect, GUIContent.Temp(cascadeText, cascadeText), s_TextCenteredStyle); - - // no need to draw the partition handle for last box - if (i == adjustedCascadePartitions.Length - 1) - break; - - // partition handle - GUI.backgroundColor = Color.black; - Rect handleRect = partitionRect; - handleRect.x = currentX; - handleRect.width = kPartitionHandleWidth; - GUI.Box(handleRect, GUIContent.none, s_CascadeSliderBG); - // we want a thin handle visually (since wide black bar looks bad), but a slightly larger - // hit area for easier manipulation - Rect handleHitRect = handleRect; - handleHitRect.xMin -= kPartitionHandleExtraHitAreaWidth; - handleHitRect.xMax += kPartitionHandleExtraHitAreaWidth; - if (handleHitRect.Contains(currentEvent.mousePosition)) - hotPartitionHandleIndex = i; - - // add regions to slider where the cursor changes to Resize-Horizontal - if (s_DragCache == null) - { - EditorGUIUtility.AddCursorRect(handleHitRect, MouseCursor.ResizeHorizontal, sliderControlId); - } - - currentX += kPartitionHandleWidth; - } - - GUI.color = origTextColor; - GUI.backgroundColor = origBackgroundColor; - - EventType eventType = currentEvent.GetTypeForControl(sliderControlId); - switch (eventType) - { - case EventType.MouseDown: - if (hotPartitionHandleIndex >= 0) - { - s_DragCache = new DragCache(hotPartitionHandleIndex, normalizedCascadePartitions[hotPartitionHandleIndex], currentEvent.mousePosition); - if (GUIUtility.hotControl == 0) - GUIUtility.hotControl = sliderControlId; - currentEvent.Use(); - - // Switch active scene view into shadow cascades visualization mode, once we start - // tweaking cascade splits. - if (s_RestoreSceneView == null) - { - s_RestoreSceneView = SceneView.lastActiveSceneView; - if (s_RestoreSceneView != null) - { - s_OldSceneDrawMode = s_RestoreSceneView.cameraMode; - s_OldSceneLightingMode = s_RestoreSceneView.m_SceneLighting; - s_RestoreSceneView.cameraMode = SceneView.GetBuiltinCameraMode(DrawCameraMode.ShadowCascades); - } - } - } - break; - - case EventType.MouseUp: - // mouseUp event anywhere should release the hotcontrol (if it belongs to us), drags (if any) - if (GUIUtility.hotControl == sliderControlId) - { - GUIUtility.hotControl = 0; - currentEvent.Use(); - } - s_DragCache = null; - - // Restore previous scene view drawing mode once we stop tweaking cascade splits. - if (s_RestoreSceneView != null) - { - s_RestoreSceneView.cameraMode = s_OldSceneDrawMode; - s_RestoreSceneView.m_SceneLighting = s_OldSceneLightingMode; - s_RestoreSceneView = null; - } - break; - - case EventType.MouseDrag: - if (GUIUtility.hotControl != sliderControlId) - break; - - // convert the mouse movement to normalized cascade width. Make sure that we are safe to apply the delta before using it. - float delta = (currentEvent.mousePosition - s_DragCache.m_LastCachedMousePosition).x / cascadeSliderWidth; - bool isLeftPartitionHappy = ((adjustedCascadePartitions[s_DragCache.m_ActivePartition] + delta) > 0.0f); - bool isRightPartitionHappy = ((adjustedCascadePartitions[s_DragCache.m_ActivePartition + 1] - delta) > 0.0f); - if (isLeftPartitionHappy && isRightPartitionHappy) - { - s_DragCache.m_NormalizedPartitionSize += delta; - normalizedCascadePartitions[s_DragCache.m_ActivePartition] = s_DragCache.m_NormalizedPartitionSize; - if (s_DragCache.m_ActivePartition < normalizedCascadePartitions.Length - 1) - normalizedCascadePartitions[s_DragCache.m_ActivePartition + 1] -= delta; - GUI.changed = true; - } - s_DragCache.m_LastCachedMousePosition = currentEvent.mousePosition; - currentEvent.Use(); - break; - } - } - } -} diff --git a/Editor/Mono/Inspector/SkinnedMeshRendererEditor.cs b/Editor/Mono/Inspector/SkinnedMeshRendererEditor.cs deleted file mode 100644 index 2e4220289a..0000000000 --- a/Editor/Mono/Inspector/SkinnedMeshRendererEditor.cs +++ /dev/null @@ -1,197 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEditor.IMGUI.Controls; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(SkinnedMeshRenderer))] - [CanEditMultipleObjects] - internal class SkinnedMeshRendererEditor : RendererEditorBase - { - private const string kDisplayLightingKey = "SkinnedMeshRendererEditor.Lighting.ShowSettings"; - - private SerializedProperty m_Materials; - private SerializedProperty m_AABB; - private SerializedProperty m_DirtyAABB; - private SerializedProperty m_BlendShapeWeights; - private LightingSettingsInspector m_Lighting; - - private BoxBoundsHandle m_BoundsHandle = new BoxBoundsHandle(); - private string[] m_ExcludedProperties; - - public override void OnEnable() - { - base.OnEnable(); - - m_Materials = serializedObject.FindProperty("m_Materials"); - m_BlendShapeWeights = serializedObject.FindProperty("m_BlendShapeWeights"); - m_AABB = serializedObject.FindProperty("m_AABB"); - m_DirtyAABB = serializedObject.FindProperty("m_DirtyAABB"); - - m_BoundsHandle.SetColor(Handles.s_BoundingBoxHandleColor); - - InitializeProbeFields(); - InitializeLightingFields(); - - List excludedProperties = new List(); - excludedProperties.AddRange(new[] - { - "m_CastShadows", - "m_ReceiveShadows", - "m_MotionVectors", - "m_Materials", - "m_BlendShapeWeights", - "m_AABB", - "m_LightmapParameters", - "m_DynamicOccludee" - }); - excludedProperties.AddRange(Probes.GetFieldsStringArray()); - m_ExcludedProperties = excludedProperties.ToArray(); - } - - private void InitializeLightingFields() - { - m_Lighting = new LightingSettingsInspector(serializedObject); - - m_Lighting.showSettings = EditorPrefs.GetBool(kDisplayLightingKey, false); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - OnBlendShapeUI(); - - DrawPropertiesExcluding(serializedObject, m_ExcludedProperties); - - EditMode.DoEditModeInspectorModeButton( - EditMode.SceneViewEditMode.Collider, - "Edit Bounds", - PrimitiveBoundsHandle.editModeButton, - this - ); - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_AABB, EditorGUIUtility.TrTextContent("Bounds")); - // If we set m_AABB then we need to set m_DirtyAABB to false - if (EditorGUI.EndChangeCheck()) - m_DirtyAABB.boolValue = false; - - LightingFieldsGUI(); - - RenderRenderingLayer(); - - EditorGUILayout.PropertyField(m_Materials, true); - - CullDynamicFieldGUI(); - - serializedObject.ApplyModifiedProperties(); - } - - internal override Bounds GetWorldBoundsOfTarget(Object targetObject) - { - return ((SkinnedMeshRenderer)targetObject).bounds; - } - - private void LightingFieldsGUI() - { - bool oldShowLighting = m_Lighting.showSettings; - - if (m_Lighting.Begin()) - { - RenderProbeFields(); - m_Lighting.RenderMeshSettings(false); - } - m_Lighting.End(); - - if (m_Lighting.showSettings != oldShowLighting) - EditorPrefs.SetBool(kDisplayLightingKey, m_Lighting.showSettings); - } - - public void OnBlendShapeUI() - { - SkinnedMeshRenderer renderer = (SkinnedMeshRenderer)target; - int blendShapeCount = renderer.sharedMesh == null ? 0 : renderer.sharedMesh.blendShapeCount; - if (blendShapeCount == 0) - return; - - GUIContent content = new GUIContent(); - content.text = "BlendShapes"; - - EditorGUILayout.PropertyField(m_BlendShapeWeights, content, false); - if (!m_BlendShapeWeights.isExpanded) - return; - - EditorGUI.indentLevel++; - Mesh m = renderer.sharedMesh; - - int arraySize = m_BlendShapeWeights.arraySize; - for (int i = 0; i < blendShapeCount; i++) - { - content.text = m.GetBlendShapeName(i); - - // The SkinnedMeshRenderer blendshape weights array size can be out of sync with the size defined in the mesh - // (default values in that case are 0) - // The desired behaviour is to resize the blendshape array on edit. - - // Default path when the blend shape array size is big enough. - if (i < arraySize) - EditorGUILayout.PropertyField(m_BlendShapeWeights.GetArrayElementAtIndex(i), content); - // Fall back to 0 based editing & - else - { - EditorGUI.BeginChangeCheck(); - - float value = EditorGUILayout.FloatField(content, 0.0F); - if (EditorGUI.EndChangeCheck()) - { - m_BlendShapeWeights.arraySize = blendShapeCount; - arraySize = blendShapeCount; - m_BlendShapeWeights.GetArrayElementAtIndex(i).floatValue = value; - } - } - } - - EditorGUI.indentLevel--; - } - - public void OnSceneGUI() - { - SkinnedMeshRenderer renderer = (SkinnedMeshRenderer)target; - - if (renderer.updateWhenOffscreen) - { - Bounds bounds = renderer.bounds; - Vector3 center = bounds.center; - Vector3 size = bounds.size; - - Handles.DrawWireCube(center, size); - } - else - { - using (new Handles.DrawingScope(renderer.actualRootBone.localToWorldMatrix)) - { - Bounds bounds = renderer.localBounds; - m_BoundsHandle.center = bounds.center; - m_BoundsHandle.size = bounds.size; - - // only display interactive handles if edit mode is active - m_BoundsHandle.handleColor = EditMode.editMode == EditMode.SceneViewEditMode.Collider && EditMode.IsOwner(this) ? - m_BoundsHandle.wireframeColor : Color.clear; - - EditorGUI.BeginChangeCheck(); - m_BoundsHandle.DrawHandle(); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(renderer, "Resize Bounds"); - renderer.localBounds = new Bounds(m_BoundsHandle.center, m_BoundsHandle.size); - } - } - } - } - } -} diff --git a/Editor/Mono/Inspector/SkyboxPanoramicShaderGUI.cs b/Editor/Mono/Inspector/SkyboxPanoramicShaderGUI.cs deleted file mode 100644 index 641d047221..0000000000 --- a/Editor/Mono/Inspector/SkyboxPanoramicShaderGUI.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditor.AnimatedValues; -using UnityEditorInternal; -using UnityEditor.Build; - -namespace UnityEditor -{ - internal class SkyboxPanoramicShaderGUI : ShaderGUI - { - readonly AnimBool m_ShowLatLongLayout = new AnimBool(); - readonly AnimBool m_ShowMirrorOnBack = new AnimBool(); - readonly AnimBool m_Show3DControl = new AnimBool(); - - bool m_Initialized = false; - - public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) - { - if (!m_Initialized) - { - m_ShowLatLongLayout.valueChanged.AddListener(materialEditor.Repaint); - m_ShowMirrorOnBack.valueChanged.AddListener(materialEditor.Repaint); - m_Show3DControl.valueChanged.AddListener(materialEditor.Repaint); - m_Initialized = true; - } - - // Allow the default implementation to set widths for consistency for common properties. - float lw = EditorGUIUtility.labelWidth; - materialEditor.SetDefaultGUIWidths(); - ShowProp(materialEditor, FindProperty("_Tint", props)); - ShowProp(materialEditor, FindProperty("_Exposure", props)); - ShowProp(materialEditor, FindProperty("_Rotation", props)); - ShowProp(materialEditor, FindProperty("_MainTex", props)); - EditorGUIUtility.labelWidth = lw; - - m_ShowLatLongLayout.target = ShowProp(materialEditor, FindProperty("_Mapping", props)) == 1; - if (EditorGUILayout.BeginFadeGroup(m_ShowLatLongLayout.faded)) - { - m_ShowMirrorOnBack.target = ShowProp(materialEditor, FindProperty("_ImageType", props)) == 1; - if (EditorGUILayout.BeginFadeGroup(m_ShowMirrorOnBack.faded)) - { - EditorGUI.indentLevel++; - ShowProp(materialEditor, FindProperty("_MirrorOnBack", props)); - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - - // Show 3D settings if VR support is enabled on ANY platform. - m_Show3DControl.value = false; - foreach (BuildPlatform cur in BuildPlatforms.instance.buildPlatforms) - { - if (UnityEditorInternal.VR.VREditor.GetVREnabledOnTargetGroup(cur.targetGroup)) - { - m_Show3DControl.value = true; - break; - } - } - if (EditorGUILayout.BeginFadeGroup(m_Show3DControl.faded)) - ShowProp(materialEditor, FindProperty("_Layout", props)); - EditorGUILayout.EndFadeGroup(); - } - EditorGUILayout.EndFadeGroup(); - - // Let the default implementation add the extra shader properties at the bottom. - materialEditor.PropertiesDefaultGUI(new MaterialProperty[0]); - } - - private float ShowProp(MaterialEditor materialEditor, MaterialProperty prop) - { - materialEditor.ShaderProperty(prop, prop.displayName); - return prop.floatValue; - } - } -} diff --git a/Editor/Mono/Inspector/SkyboxProceduralShaderGUI.cs b/Editor/Mono/Inspector/SkyboxProceduralShaderGUI.cs deleted file mode 100644 index ce67c8da95..0000000000 --- a/Editor/Mono/Inspector/SkyboxProceduralShaderGUI.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal class SkyboxProceduralShaderGUI : ShaderGUI - { - private enum SunDiskMode - { - None, - Simple, - HighQuality - } - - public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) - { - materialEditor.SetDefaultGUIWidths(); - - MaterialProperty sunDiskModeProp = FindProperty("_SunDisk", props); - SunDiskMode sunDiskMode = (SunDiskMode)sunDiskModeProp.floatValue; - - for (var i = 0; i < props.Length; i++) - { - if ((props[i].flags & (MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData)) != 0) - continue; - - //_SunSizeConvergence is only used with the HighQuality sun disk. - if ((props[i].name == "_SunSizeConvergence") && (sunDiskMode != SunDiskMode.HighQuality)) - continue; - - float h = materialEditor.GetPropertyHeight(props[i], props[i].displayName); - Rect r = EditorGUILayout.GetControlRect(true, h, EditorStyles.layerMaskField); - - materialEditor.ShaderProperty(r, props[i], props[i].displayName); - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/Inspector/SliderJoint2DEditor.cs b/Editor/Mono/Inspector/SliderJoint2DEditor.cs deleted file mode 100644 index ffdf26624b..0000000000 --- a/Editor/Mono/Inspector/SliderJoint2DEditor.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(SliderJoint2D))] - [CanEditMultipleObjects] - internal class SliderJoint2DEditor : AnchoredJoint2DEditor - { - new public void OnSceneGUI() - { - var sliderJoint2D = (SliderJoint2D)target; - - // Ignore disabled joint. - if (!sliderJoint2D.enabled) - return; - - var anchor = TransformPoint(sliderJoint2D.transform, sliderJoint2D.anchor); - - // Draw lines for slider angle and limits - Vector3 upper = anchor; - Vector3 lower = anchor; - Vector3 direction = RotateVector2(Vector3.right, -sliderJoint2D.angle - sliderJoint2D.transform.eulerAngles.z); - - Handles.color = Color.green; - - if (sliderJoint2D.useLimits) - { - upper = anchor + direction * sliderJoint2D.limits.max; - lower = anchor + direction * sliderJoint2D.limits.min; - - Vector3 normal = Vector3.Cross(direction, Vector3.forward); - float upperSize = HandleUtility.GetHandleSize(upper) * 0.16f; - float lowerSize = HandleUtility.GetHandleSize(lower) * 0.16f; - - DrawAALine(upper + normal * upperSize, upper - normal * upperSize); - DrawAALine(lower + normal * lowerSize, lower - normal * lowerSize); - } - else - { - direction *= HandleUtility.GetHandleSize(anchor) * 0.3f; - upper += direction; - lower -= direction; - } - - DrawAALine(upper, lower); - - base.OnSceneGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/SortingGroupEditor.cs b/Editor/Mono/Inspector/SortingGroupEditor.cs deleted file mode 100644 index abb39e0716..0000000000 --- a/Editor/Mono/Inspector/SortingGroupEditor.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - [CustomEditor(typeof(UnityEngine.Rendering.SortingGroup))] - [CanEditMultipleObjects] - internal class SortingGroupEditor : Editor - { - private SerializedProperty m_SortingOrder; - private SerializedProperty m_SortingLayerID; - - public virtual void OnEnable() - { - m_SortingOrder = serializedObject.FindProperty("m_SortingOrder"); - m_SortingLayerID = serializedObject.FindProperty("m_SortingLayerID"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - SortingLayerEditorUtility.RenderSortingLayerFields(m_SortingOrder, m_SortingLayerID); - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/SortingLayerEditorUtility.cs b/Editor/Mono/Inspector/SortingLayerEditorUtility.cs deleted file mode 100644 index 079b0dd800..0000000000 --- a/Editor/Mono/Inspector/SortingLayerEditorUtility.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class SortingLayerEditorUtility - { - private static class Styles - { - public static GUIContent m_SortingLayerStyle = EditorGUIUtility.TrTextContent("Sorting Layer", "Name of the Renderer's sorting layer"); - public static GUIContent m_SortingOrderStyle = EditorGUIUtility.TrTextContent("Order in Layer", "Renderer's order within a sorting layer"); - } - - public static void RenderSortingLayerFields(SerializedProperty sortingOrder, SerializedProperty sortingLayer) - { - EditorGUILayout.SortingLayerField(Styles.m_SortingLayerStyle, sortingLayer, EditorStyles.popup, EditorStyles.label); - EditorGUILayout.PropertyField(sortingOrder, Styles.m_SortingOrderStyle); - } - - public static void RenderSortingLayerFields(Rect r, SerializedProperty sortingOrder, SerializedProperty sortingLayer) - { - EditorGUI.SortingLayerField(r, Styles.m_SortingLayerStyle, sortingLayer, EditorStyles.popup, EditorStyles.label); - r.y += EditorGUIUtility.singleLineHeight; - EditorGUI.PropertyField(r, sortingOrder, Styles.m_SortingOrderStyle); - } - } -} diff --git a/Editor/Mono/Inspector/SpeedTreeMaterialInspector.cs b/Editor/Mono/Inspector/SpeedTreeMaterialInspector.cs deleted file mode 100644 index 4a75a69585..0000000000 --- a/Editor/Mono/Inspector/SpeedTreeMaterialInspector.cs +++ /dev/null @@ -1,187 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - [CanEditMultipleObjects] - internal class SpeedTreeMaterialInspector : MaterialEditor - { - private enum SpeedTreeGeometryType - { - Branch = 0, - BranchDetail, - Frond, - Leaf, - Mesh // mapped with GEOM_TYPE_MESH in SpeedTreeImporter - } - - private string[] speedTreeGeometryTypeString = - { - "GEOM_TYPE_BRANCH", - "GEOM_TYPE_BRANCH_DETAIL", - "GEOM_TYPE_FROND", - "GEOM_TYPE_LEAF", - "GEOM_TYPE_MESH" - }; - - private bool ShouldEnableAlphaTest(SpeedTreeGeometryType geomType) - { - return geomType == SpeedTreeGeometryType.Frond - || geomType == SpeedTreeGeometryType.Leaf; - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - var theShader = serializedObject.FindProperty("m_Shader"); - - // if we are not visible... return - if (!isVisible || theShader.hasMultipleDifferentValues || theShader.objectReferenceValue == null) - return; - - List props = new List(GetMaterialProperties(targets)); - - SetDefaultGUIWidths(); - - // Geometry type choice - //--------------------------------------------------------------- - var geomTypes = new SpeedTreeGeometryType[targets.Length]; - for (int i = 0; i < targets.Length; ++i) - { - geomTypes[i] = SpeedTreeGeometryType.Branch; - for (int j = 0; j < speedTreeGeometryTypeString.Length; ++j) - { - if (((Material)targets[i]).shaderKeywords.Contains(speedTreeGeometryTypeString[j])) - { - geomTypes[i] = (SpeedTreeGeometryType)j; - break; - } - } - } - EditorGUI.showMixedValue = geomTypes.Distinct().Count() > 1; - EditorGUI.BeginChangeCheck(); - var setGeomType = (SpeedTreeGeometryType)EditorGUILayout.EnumPopup("Geometry Type", geomTypes[0]); - if (EditorGUI.EndChangeCheck()) - { - bool shouldEnableAlphaTest = ShouldEnableAlphaTest(setGeomType); - UnityEngine.Rendering.CullMode cullMode = shouldEnableAlphaTest ? UnityEngine.Rendering.CullMode.Off : UnityEngine.Rendering.CullMode.Back; - - foreach (var m in targets.Cast()) - { - if (shouldEnableAlphaTest) - m.SetOverrideTag("RenderType", "treeTransparentCutout"); - for (int i = 0; i < speedTreeGeometryTypeString.Length; ++i) - m.DisableKeyword(speedTreeGeometryTypeString[i]); - m.EnableKeyword(speedTreeGeometryTypeString[(int)setGeomType]); - m.renderQueue = shouldEnableAlphaTest ? (int)UnityEngine.Rendering.RenderQueue.AlphaTest : (int)UnityEngine.Rendering.RenderQueue.Geometry; - m.SetInt("_Cull", (int)cullMode); - } - } - EditorGUI.showMixedValue = false; - - //--------------------------------------------------------------- - var mainTex = props.Find(prop => prop.name == "_MainTex"); - if (mainTex != null) - { - props.Remove(mainTex); - ShaderProperty(mainTex, mainTex.displayName); - } - - //--------------------------------------------------------------- - var bumpMap = props.Find(prop => prop.name == "_BumpMap"); - if (bumpMap != null) - { - props.Remove(bumpMap); - - var enableBump = targets.Select(t => ((Material)t).shaderKeywords.Contains("EFFECT_BUMP")); - bool? enable = ToggleShaderProperty(bumpMap, enableBump.First(), enableBump.Distinct().Count() > 1); - if (enable != null) - { - foreach (var m in targets.Cast()) - { - if (enable.Value) - m.EnableKeyword("EFFECT_BUMP"); - else - m.DisableKeyword("EFFECT_BUMP"); - } - } - } - - //--------------------------------------------------------------- - var detailTex = props.Find(prop => prop.name == "_DetailTex"); - if (detailTex != null) - { - props.Remove(detailTex); - if (geomTypes.Contains(SpeedTreeGeometryType.BranchDetail)) - ShaderProperty(detailTex, detailTex.displayName); - } - - //--------------------------------------------------------------- - var enableHueVariation = targets.Select(t => ((Material)t).shaderKeywords.Contains("EFFECT_HUE_VARIATION")); - var hueVariation = props.Find(prop => prop.name == "_HueVariation"); - if (enableHueVariation != null && hueVariation != null) - { - props.Remove(hueVariation); - bool? enable = ToggleShaderProperty(hueVariation, enableHueVariation.First(), enableHueVariation.Distinct().Count() > 1); - if (enable != null) - { - foreach (var m in targets.Cast()) - { - if (enable.Value) - m.EnableKeyword("EFFECT_HUE_VARIATION"); - else - m.DisableKeyword("EFFECT_HUE_VARIATION"); - } - } - } - - //--------------------------------------------------------------- - var alphaCutoff = props.Find(prop => prop.name == "_Cutoff"); - if (alphaCutoff != null) - { - props.Remove(alphaCutoff); - if (geomTypes.Any(t => ShouldEnableAlphaTest(t))) - ShaderProperty(alphaCutoff, alphaCutoff.displayName); - } - - //--------------------------------------------------------------- - foreach (var prop in props) - { - if ((prop.flags & (MaterialProperty.PropFlags.HideInInspector | MaterialProperty.PropFlags.PerRendererData)) != 0) - continue; - ShaderProperty(prop, prop.displayName); - } - - EditorGUILayout.Space(); - EditorGUILayout.Space(); - - RenderQueueField(); - EnableInstancingField(); - DoubleSidedGIField(); - } - - private bool? ToggleShaderProperty(MaterialProperty prop, bool enable, bool hasMixedEnable) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = hasMixedEnable; - enable = EditorGUI.ToggleLeft(EditorGUILayout.GetControlRect(false, GUILayout.ExpandWidth(false)), prop.displayName, enable); - EditorGUI.showMixedValue = false; - bool? retValue = EditorGUI.EndChangeCheck() ? (bool?)enable : null; - - GUILayout.Space(-EditorGUIUtility.singleLineHeight); - using (new EditorGUI.DisabledScope(!enable && !hasMixedEnable)) - { - EditorGUI.showMixedValue = prop.hasMixedValue; - ShaderProperty(prop, " "); - EditorGUI.showMixedValue = false; - } - return retValue; - } - } -} diff --git a/Editor/Mono/Inspector/SphereColliderEditor.cs b/Editor/Mono/Inspector/SphereColliderEditor.cs deleted file mode 100644 index c178da3b70..0000000000 --- a/Editor/Mono/Inspector/SphereColliderEditor.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(SphereCollider))] - [CanEditMultipleObjects] - internal class SphereColliderEditor : PrimitiveCollider3DEditor - { - SerializedProperty m_Center; - SerializedProperty m_Radius; - private readonly SphereBoundsHandle m_BoundsHandle = new SphereBoundsHandle(); - - public override void OnEnable() - { - base.OnEnable(); - - m_Center = serializedObject.FindProperty("m_Center"); - m_Radius = serializedObject.FindProperty("m_Radius"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - InspectorEditButtonGUI(); - EditorGUILayout.PropertyField(m_IsTrigger); - EditorGUILayout.PropertyField(m_Material); - EditorGUILayout.PropertyField(m_Center); - EditorGUILayout.PropertyField(m_Radius); - - serializedObject.ApplyModifiedProperties(); - } - - protected override PrimitiveBoundsHandle boundsHandle { get { return m_BoundsHandle; } } - - protected override void CopyColliderPropertiesToHandle() - { - SphereCollider collider = (SphereCollider)target; - m_BoundsHandle.center = TransformColliderCenterToHandleSpace(collider.transform, collider.center); - m_BoundsHandle.radius = collider.radius * GetRadiusScaleFactor(); - } - - protected override void CopyHandlePropertiesToCollider() - { - SphereCollider collider = (SphereCollider)target; - collider.center = TransformHandleCenterToColliderSpace(collider.transform, m_BoundsHandle.center); - float scaleFactor = GetRadiusScaleFactor(); - collider.radius = - Mathf.Approximately(scaleFactor, 0f) ? 0f : m_BoundsHandle.radius / GetRadiusScaleFactor(); - } - - private float GetRadiusScaleFactor() - { - float result = 0f; - Vector3 lossyScale = ((SphereCollider)target).transform.lossyScale; - for (int axis = 0; axis < 3; ++axis) - { - result = Mathf.Max(result, Mathf.Abs(lossyScale[axis])); - } - return result; - } - } -} diff --git a/Editor/Mono/Inspector/SpringJoint2DEditor.cs b/Editor/Mono/Inspector/SpringJoint2DEditor.cs deleted file mode 100644 index 07ddc6ed01..0000000000 --- a/Editor/Mono/Inspector/SpringJoint2DEditor.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(SpringJoint2D))] - [CanEditMultipleObjects] - internal class SpringJoint2DEditor : AnchoredJoint2DEditor - { - new public void OnSceneGUI() - { - var springJoint2D = (SpringJoint2D)target; - - // Ignore disabled joint. - if (!springJoint2D.enabled) - return; - - // Start and end points for distance gizmo - Vector3 anchor = TransformPoint(springJoint2D.transform, springJoint2D.anchor); - Vector3 connectedAnchor = springJoint2D.connectedAnchor; - - // If connectedBody present, convert the position to match that - if (springJoint2D.connectedBody) - connectedAnchor = TransformPoint(springJoint2D.connectedBody.transform, connectedAnchor); - - DrawDistanceGizmo(anchor, connectedAnchor, springJoint2D.distance); - - base.OnSceneGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/SpriteFrameInspector.cs b/Editor/Mono/Inspector/SpriteFrameInspector.cs deleted file mode 100644 index ab53b3d2da..0000000000 --- a/Editor/Mono/Inspector/SpriteFrameInspector.cs +++ /dev/null @@ -1,374 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using Unity.Collections; -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.Experimental.U2D; -using UnityEditor.Experimental.U2D; -using UnityEngine.Experimental.Rendering; - -namespace UnityEditor -{ - [CustomEditor(typeof(Sprite))] - [CanEditMultipleObjects] - internal class SpriteInspector : Editor - { - private static class Styles - { - public static readonly GUIContent[] spriteAlignmentOptions = - { - EditorGUIUtility.TrTextContent("Center"), - EditorGUIUtility.TrTextContent("Top Left"), - EditorGUIUtility.TrTextContent("Top"), - EditorGUIUtility.TrTextContent("Top Right"), - EditorGUIUtility.TrTextContent("Left"), - EditorGUIUtility.TrTextContent("Right"), - EditorGUIUtility.TrTextContent("Bottom Left"), - EditorGUIUtility.TrTextContent("Bottom"), - EditorGUIUtility.TrTextContent("Bottom Right"), - EditorGUIUtility.TrTextContent("Custom"), - }; - - public static readonly GUIContent spriteAlignment = EditorGUIUtility.TrTextContent("Pivot", "Sprite pivot point in its localspace. May be used for syncing animation frames of different sizes."); - } - - private Sprite sprite - { - get { return target as Sprite; } - } - - private SpriteMetaData GetMetaData(string name) - { - string path = AssetDatabase.GetAssetPath(sprite); - TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter; - if (textureImporter != null) - { - if (textureImporter.spriteImportMode == SpriteImportMode.Single) - { - return GetMetaDataInSingleMode(name, textureImporter); - } - else - { - return GetMetaDataInMultipleMode(name, textureImporter); - } - } - - return new SpriteMetaData(); - } - - private static SpriteMetaData GetMetaDataInMultipleMode(string name, TextureImporter textureImporter) - { - SpriteMetaData[] spritesheet = textureImporter.spritesheet; - for (int i = 0; i < spritesheet.Length; i++) - { - if (spritesheet[i].name.Equals(name)) - { - return spritesheet[i]; - } - } - return new SpriteMetaData(); - } - - private static SpriteMetaData GetMetaDataInSingleMode(string name, TextureImporter textureImporter) - { - SpriteMetaData metaData = new SpriteMetaData(); - metaData.border = textureImporter.spriteBorder; - metaData.name = name; - metaData.pivot = textureImporter.spritePivot; - metaData.rect = new Rect(0, 0, 1, 1); - TextureImporterSettings textureImporterSettings = new TextureImporterSettings(); - textureImporter.ReadTextureSettings(textureImporterSettings); - metaData.alignment = textureImporterSettings.spriteAlignment; - return metaData; - } - - public override void OnInspectorGUI() - { - bool nameM; - bool alignM; - bool borderM; - UnifiedValues(out nameM, out alignM, out borderM); - - if (nameM) - EditorGUILayout.LabelField("Name", sprite.name); - else - EditorGUILayout.LabelField("Name", "-"); - - if (alignM) - { - int align = GetMetaData(sprite.name).alignment; - EditorGUILayout.LabelField(Styles.spriteAlignment, Styles.spriteAlignmentOptions[align]); - } - else - EditorGUILayout.LabelField(Styles.spriteAlignment.text, "-"); - - if (borderM) - { - Vector4 border = GetMetaData(sprite.name).border; - EditorGUILayout.LabelField("Border", string.Format("L:{0} B:{1} R:{2} T:{3}", border.x, border.y, border.z, border.w)); - } - else - EditorGUILayout.LabelField("Border", "-"); - } - - private void UnifiedValues(out bool name, out bool alignment, out bool border) - { - name = true; - alignment = true; - border = true; - if (targets.Length < 2) - return; - - string path = AssetDatabase.GetAssetPath(sprite); - var spriteDataProvider = AssetImporter.GetAtPath(path) as ISpriteEditorDataProvider; - if (spriteDataProvider == null) - return; - - spriteDataProvider.InitSpriteEditorDataProvider(); - var spritesheet = spriteDataProvider.GetSpriteRects(); - - string previousName = null; - int previousAligment = -1; - Vector4? previousBorder = null; - - for (int targetsIndex = 0; targetsIndex < targets.Length; targetsIndex++) - { - Sprite curSprite = targets[targetsIndex] as Sprite; - for (int spritesIndex = 0; spritesIndex < spritesheet.Length; spritesIndex++) - { - if (spritesheet[spritesIndex].name.Equals(curSprite.name)) - { - if ((int)spritesheet[spritesIndex].alignment != previousAligment && previousAligment > 0) - alignment = false; - else - previousAligment = (int)spritesheet[spritesIndex].alignment; - - if (spritesheet[spritesIndex].name != previousName && previousName != null) - name = false; - else - previousName = spritesheet[spritesIndex].name; - - if (spritesheet[spritesIndex].border != previousBorder && previousBorder != null) - border = false; - else - previousBorder = spritesheet[spritesIndex].border; - } - } - } - } - - public static Texture2D BuildPreviewTexture(int width, int height, Sprite sprite, Material spriteRendererMaterial, bool isPolygon) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - { - return null; - } - - float spriteWidth = sprite.rect.width; - float spriteHeight = sprite.rect.height; - - Texture2D texture = UnityEditor.Sprites.SpriteUtility.GetSpriteTexture(sprite, false); - - // only adjust the preview texture size if the sprite is not in polygon mode. - // In polygon mode, we are looking at a 4x4 texture will detailed mesh. It's better to maximize the display of it. - if (!isPolygon) - { - PreviewHelpers.AdjustWidthAndHeightForStaticPreview((int)spriteWidth, (int)spriteHeight, ref width, ref height); - } - - SavedRenderTargetState savedRTState = new SavedRenderTargetState(); - - RenderTexture tmp = RenderTexture.GetTemporary( - width, - height, - 0, - RenderTextureFormat.Default, - RenderTextureReadWrite.Linear); - - RenderTexture.active = tmp; - - GL.Clear(true, true, new Color(0f, 0f, 0f, 0f)); - - Texture _oldTexture = null; - Vector4 _oldTexelSize = new Vector4(0, 0, 0, 0); - bool _matHasTexture = false; - bool _matHasTexelSize = false; - if (spriteRendererMaterial != null) - { - _matHasTexture = spriteRendererMaterial.HasProperty("_MainTex"); - _matHasTexelSize = spriteRendererMaterial.HasProperty("_MainTex_TexelSize"); - } - - bool hasColors = sprite.HasVertexAttribute(VertexAttribute.Color); - - Material copyMaterial = null; - if (spriteRendererMaterial != null) - { - if (_matHasTexture) - { - _oldTexture = spriteRendererMaterial.GetTexture("_MainTex"); - spriteRendererMaterial.SetTexture("_MainTex", texture); - } - - if (_matHasTexelSize) - { - _oldTexelSize = spriteRendererMaterial.GetVector("_MainTex_TexelSize"); - spriteRendererMaterial.SetVector("_MainTex_TexelSize", TextureUtil.GetTexelSizeVector(texture)); - } - - spriteRendererMaterial.SetPass(0); - } - else - { - if (hasColors) - { - SpriteUtility.previewSpriteDefaultMaterial.SetPass(0); - } - else if (texture != null) - { - copyMaterial = new Material(Shader.Find("Hidden/BlitCopy")); - copyMaterial.mainTexture = texture; - copyMaterial.mainTextureScale = Vector2.one; - copyMaterial.mainTextureOffset = Vector2.zero; - copyMaterial.SetPass(0); - } - } - - float pixelsToUnits = sprite.rect.width / sprite.bounds.size.x; - Vector2[] vertices = sprite.vertices; - Vector2[] uvs = sprite.uv; - ushort[] triangles = sprite.triangles; - Vector2 pivot = sprite.pivot; - - NativeSlice? colors = null; - if (hasColors) - colors = sprite.GetVertexAttribute(VertexAttribute.Color); - - GL.PushMatrix(); - GL.LoadOrtho(); - GL.Color(new Color(1, 1, 1, 1)); - GL.Begin(GL.TRIANGLES); - for (int i = 0; i < triangles.Length; ++i) - { - ushort index = triangles[i]; - Vector2 vertex = vertices[index]; - Vector2 uv = uvs[index]; - GL.TexCoord(new Vector3(uv.x, uv.y, 0)); - if (colors != null) - GL.Color(colors.Value[index]); - GL.Vertex3((vertex.x * pixelsToUnits + pivot.x) / spriteWidth, (vertex.y * pixelsToUnits + pivot.y) / spriteHeight, 0); - } - GL.End(); - GL.PopMatrix(); - - - if (spriteRendererMaterial != null) - { - if (_matHasTexture) - spriteRendererMaterial.SetTexture("_MainTex", _oldTexture); - if (_matHasTexelSize) - spriteRendererMaterial.SetVector("_MainTex_TexelSize", _oldTexelSize); - } - - var tmp2 = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); - Graphics.Blit(tmp, tmp2, EditorGUIUtility.GUITextureBlit2SRGBMaterial); - - RenderTexture.active = tmp2; - - Texture2D copy = new Texture2D(width, height, TextureFormat.RGBA32, false); - copy.hideFlags = HideFlags.HideAndDontSave; - copy.filterMode = texture != null ? texture.filterMode : FilterMode.Point; - copy.anisoLevel = texture != null ? texture.anisoLevel : 0; - copy.wrapMode = texture != null ? texture.wrapMode : TextureWrapMode.Clamp; - copy.ReadPixels(new Rect(0, 0, width, height), 0, 0); - copy.Apply(); - RenderTexture.ReleaseTemporary(tmp); - RenderTexture.ReleaseTemporary(tmp2); - - savedRTState.Restore(); - - if (copyMaterial != null) - DestroyImmediate(copyMaterial); - - return copy; - } - - public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) - { - // Determine is sprite in assetpath a polygon sprite - bool isPolygonSpriteAsset = false; - TextureImporter textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter; - if (textureImporter != null) - { - isPolygonSpriteAsset = textureImporter.spriteImportMode == SpriteImportMode.Polygon; - } - - return BuildPreviewTexture(width, height, sprite, null, isPolygonSpriteAsset); - } - - public override bool HasPreviewGUI() - { - var sprite = target as Sprite; - return (sprite != null) && UnityEditor.Sprites.SpriteUtility.GetSpriteTexture(sprite, false) != null; - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (target == null) - return; - - if (Event.current.type != EventType.Repaint) - return; - - bool isPolygon = false; - string path = AssetDatabase.GetAssetPath(sprite); - TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter; - if (textureImporter != null) - { - isPolygon = textureImporter.spriteImportMode == SpriteImportMode.Polygon; - } - - DrawPreview(r, sprite, null, isPolygon); - } - - public static void DrawPreview(Rect r, Sprite frame, Material spriteRendererMaterial, bool isPolygon) - { - if (frame == null) - return; - - float zoomLevel = Mathf.Min(r.width / frame.rect.width, r.height / frame.rect.height); - Rect wantedRect = new Rect(r.x, r.y, frame.rect.width * zoomLevel, frame.rect.height * zoomLevel); - wantedRect.center = r.center; - - Texture2D previewTexture = BuildPreviewTexture((int)wantedRect.width, (int)wantedRect.height, frame, spriteRendererMaterial, isPolygon); - EditorGUI.DrawTextureTransparent(wantedRect, previewTexture, ScaleMode.ScaleToFit); - - var border = frame.border; - border *= zoomLevel; - if (!Mathf.Approximately(border.sqrMagnitude, 0)) - { - SpriteEditorUtility.BeginLines(new Color(0f, 1f, 0f, 0.7f)); - //TODO: this - //SpriteEditorUtility.DrawBorder (wantedRect, border); - SpriteEditorUtility.EndLines(); - } - - DestroyImmediate(previewTexture); - } - - public override string GetInfoString() - { - if (target == null) - return ""; - - Sprite sprite = target as Sprite; - - return string.Format("({0}x{1})", - (int)sprite.rect.width, - (int)sprite.rect.height - ); - } - } -} diff --git a/Editor/Mono/Inspector/SpriteRendererEditor.cs b/Editor/Mono/Inspector/SpriteRendererEditor.cs deleted file mode 100644 index 3356d4dddb..0000000000 --- a/Editor/Mono/Inspector/SpriteRendererEditor.cs +++ /dev/null @@ -1,289 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - [CustomEditor(typeof(SpriteRenderer))] - [CanEditMultipleObjects] - internal class SpriteRendererEditor : RendererEditorBase - { - private SerializedProperty m_Sprite; - private SerializedProperty m_Color; - private SerializedProperty m_Material; - - private static class Contents - { - public static readonly GUIContent flipLabel = EditorGUIUtility.TrTextContent("Flip", "Sprite flipping"); - public static readonly GUIContent flipXLabel = EditorGUIUtility.TrTextContent("X", "Sprite horizontal flipping"); - public static readonly GUIContent flipYLabel = EditorGUIUtility.TrTextContent("Y", "Sprite vertical flipping"); - public static readonly int flipToggleHash = "FlipToggleHash".GetHashCode(); - - public static readonly GUIContent fullTileLabel = EditorGUIUtility.TrTextContent("Tile Mode", "Specify the 9 slice tiling behaviour"); - public static readonly GUIContent fullTileThresholdLabel = EditorGUIUtility.TrTextContent("Stretch Value", "This value defines how much the center portion will stretch before it tiles."); - public static readonly GUIContent drawModeLabel = EditorGUIUtility.TrTextContent("Draw Mode", "Specify the draw mode for the sprite"); - public static readonly GUIContent widthLabel = EditorGUIUtility.TrTextContent("Width", "The width dimension value for the sprite"); - public static readonly GUIContent heightLabel = EditorGUIUtility.TrTextContent("Height", "The height dimension value for the sprite"); - public static readonly GUIContent sizeLabel = EditorGUIUtility.TrTextContent("Size", "The rendering dimension for the sprite"); - 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"); - 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"); - public static readonly int sizeFieldHash = "SpriteRendererSizeField".GetHashCode(); - public static readonly GUIContent materialLabel = EditorGUIUtility.TrTextContent("Material", "Material to be used by SpriteRenderer"); - public static readonly GUIContent spriteLabel = EditorGUIUtility.TrTextContent("Sprite", "The Sprite to render"); - public static readonly GUIContent colorLabel = EditorGUIUtility.TrTextContent("Color", "Rendering color for the Sprite graphic"); - public static readonly GUIContent maskInteractionLabel = EditorGUIUtility.TextContent("Mask Interaction|SpriteRenderer's interaction with a Sprite Mask"); - public static readonly Texture2D warningIcon = EditorGUIUtility.LoadIcon("console.warnicon"); - } - - private SerializedProperty m_FlipX; - private SerializedProperty m_FlipY; - - private SerializedProperty m_DrawMode; - private SerializedProperty m_SpriteTileMode; - private SerializedProperty m_AdaptiveModeThreshold; - private SerializedProperty m_Size; - private AnimBool m_ShowDrawMode; - private AnimBool m_ShowTileMode; - private AnimBool m_ShowAdaptiveThreshold; - private SerializedProperty m_MaskInteraction; - - public override void OnEnable() - { - base.OnEnable(); - - m_Sprite = serializedObject.FindProperty("m_Sprite"); - m_Color = serializedObject.FindProperty("m_Color"); - m_FlipX = serializedObject.FindProperty("m_FlipX"); - m_FlipY = serializedObject.FindProperty("m_FlipY"); - m_Material = serializedObject.FindProperty("m_Materials.Array"); // Only allow to edit one material - m_DrawMode = serializedObject.FindProperty("m_DrawMode"); - m_Size = serializedObject.FindProperty("m_Size"); - m_SpriteTileMode = serializedObject.FindProperty("m_SpriteTileMode"); - m_AdaptiveModeThreshold = serializedObject.FindProperty("m_AdaptiveModeThreshold"); - m_ShowDrawMode = new AnimBool(ShouldShowDrawMode()); - m_ShowTileMode = new AnimBool(ShouldShowTileMode()); - m_ShowAdaptiveThreshold = new AnimBool(ShouldShowAdaptiveThreshold()); - - m_ShowDrawMode.valueChanged.AddListener(Repaint); - m_ShowTileMode.valueChanged.AddListener(Repaint); - m_ShowAdaptiveThreshold.valueChanged.AddListener(Repaint); - m_MaskInteraction = serializedObject.FindProperty("m_MaskInteraction"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_Sprite, Contents.spriteLabel); - - EditorGUILayout.PropertyField(m_Color, Contents.colorLabel, true); - - FlipToggles(); - - Rect r = GUILayoutUtility.GetRect( - EditorGUILayout.kLabelFloatMinW, EditorGUILayout.kLabelFloatMaxW, - EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight); - - EditorGUI.showMixedValue = m_Material.hasMultipleDifferentValues; - Object currentMaterialRef = m_Material.GetArrayElementAtIndex(0).objectReferenceValue; - Object returnedMaterialRef = EditorGUI.ObjectField(r, Contents.materialLabel, currentMaterialRef, typeof(Material), false); - if (returnedMaterialRef != currentMaterialRef) - { - m_Material.GetArrayElementAtIndex(0).objectReferenceValue = returnedMaterialRef; - } - EditorGUI.showMixedValue = false; - - EditorGUILayout.PropertyField(m_DrawMode, Contents.drawModeLabel); - - m_ShowDrawMode.target = ShouldShowDrawMode(); - if (EditorGUILayout.BeginFadeGroup(m_ShowDrawMode.faded)) - { - string notFullRectWarning = GetSpriteNotFullRectWarning(); - if (notFullRectWarning != null) - EditorGUILayout.HelpBox(notFullRectWarning, MessageType.Warning); - - EditorGUI.indentLevel++; - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel(Contents.sizeLabel); - EditorGUI.showMixedValue = m_Size.hasMultipleDifferentValues; - FloatFieldLabelAbove(Contents.widthLabel, m_Size.FindPropertyRelative("x")); - FloatFieldLabelAbove(Contents.heightLabel, m_Size.FindPropertyRelative("y")); - EditorGUI.showMixedValue = false; - EditorGUILayout.EndHorizontal(); - - m_ShowTileMode.target = ShouldShowTileMode(); - if (EditorGUILayout.BeginFadeGroup(m_ShowTileMode.faded)) - { - EditorGUILayout.PropertyField(m_SpriteTileMode, Contents.fullTileLabel); - - m_ShowAdaptiveThreshold.target = ShouldShowAdaptiveThreshold(); - if (EditorGUILayout.BeginFadeGroup(m_ShowAdaptiveThreshold.faded)) - { - EditorGUI.indentLevel++; - EditorGUILayout.Slider(m_AdaptiveModeThreshold, 0.0f, 1.0f, Contents.fullTileThresholdLabel); - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - } - EditorGUILayout.EndFadeGroup(); - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - - RenderSortingLayerFields(); - - EditorGUILayout.PropertyField(m_MaskInteraction, Contents.maskInteractionLabel); - - RenderRenderingLayer(); - - CheckForErrors(); - - serializedObject.ApplyModifiedProperties(); - } - - void FloatFieldLabelAbove(GUIContent contentLabel, SerializedProperty sp) - { - EditorGUILayout.BeginVertical(); - Rect rtLabel = GUILayoutUtility.GetRect(contentLabel, EditorStyles.label); - GUIContent label = EditorGUI.BeginProperty(rtLabel, contentLabel, sp); - int id = GUIUtility.GetControlID(Contents.sizeFieldHash, FocusType.Keyboard, rtLabel); - EditorGUI.HandlePrefixLabel(rtLabel, rtLabel, label, id); - Rect rt = GUILayoutUtility.GetRect(contentLabel, EditorStyles.textField); - EditorGUI.BeginChangeCheck(); - float value = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, rt, rtLabel, id, sp.floatValue, EditorGUI.kFloatFieldFormatString, EditorStyles.textField, true); - if (EditorGUI.EndChangeCheck()) - sp.floatValue = value; - EditorGUI.EndProperty(); - EditorGUILayout.EndVertical(); - } - - string GetSpriteNotFullRectWarning() - { - foreach (var t in targets) - { - if (!(t as SpriteRenderer).shouldSupportTiling) - return targets.Length == 1 ? Contents.notFullRectWarningLabel.text : Contents.notFullRectMultiEditWarningLabel.text; - } - return null; - } - - bool ShouldShowDrawMode() - { - return m_DrawMode.intValue != (int)SpriteDrawMode.Simple && !m_DrawMode.hasMultipleDifferentValues; - } - - bool ShouldShowAdaptiveThreshold() - { - return m_SpriteTileMode.intValue == (int)SpriteTileMode.Adaptive && !m_SpriteTileMode.hasMultipleDifferentValues; - } - - bool ShouldShowTileMode() - { - return m_DrawMode.intValue == (int)SpriteDrawMode.Tiled && !m_DrawMode.hasMultipleDifferentValues; - } - - void FlipToggles() - { - const int toggleOffset = 30; - GUILayout.BeginHorizontal(); - Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.fieldWidth, EditorGUILayout.kLabelFloatMaxW, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.numberField); - int id = GUIUtility.GetControlID(Contents.flipToggleHash, FocusType.Keyboard, r); - r = EditorGUI.PrefixLabel(r, id, Contents.flipLabel); - r.width = toggleOffset; - FlipToggle(r, Contents.flipXLabel, m_FlipX); - r.x += toggleOffset; - FlipToggle(r, Contents.flipYLabel, m_FlipY); - GUILayout.EndHorizontal(); - } - - void FlipToggle(Rect r, GUIContent label, SerializedProperty property) - { - EditorGUI.BeginProperty(r, label, property); - - bool toggle = property.boolValue; - EditorGUI.BeginChangeCheck(); - int oldIndent = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; - toggle = EditorGUI.ToggleLeft(r, label, toggle); - EditorGUI.indentLevel = oldIndent; - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObjects(targets, "Edit Constraints"); - property.boolValue = toggle; - } - - EditorGUI.EndProperty(); - } - - - private void CheckForErrors() - { - if (IsMaterialTextureAtlasConflict()) - ShowError("Material has CanUseSpriteAtlas=False tag. Sprite texture has atlasHint set. Rendering artifacts possible."); - - bool isTextureTiled; - if (!DoesMaterialHaveSpriteTexture(out isTextureTiled)) - ShowError("Material does not have a _MainTex texture property. It is required for SpriteRenderer."); - else - { - if (isTextureTiled) - ShowError("Material texture property _MainTex has offset/scale set. It is incompatible with SpriteRenderer."); - } - } - - private bool IsMaterialTextureAtlasConflict() - { - Material material = (target as SpriteRenderer).sharedMaterial; - if (material == null) - return false; - string tag = material.GetTag("CanUseSpriteAtlas", false); - if (tag.ToLower() == "false") - { - Sprite frame = m_Sprite.objectReferenceValue as Sprite; - TextureImporter ti = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(frame)) as TextureImporter; - if (ti != null && ti.spritePackingTag != null && ti.spritePackingTag.Length > 0) - { - return true; - } - } - - return false; - } - - private bool DoesMaterialHaveSpriteTexture(out bool tiled) - { - tiled = false; - - Material material = (target as SpriteRenderer).sharedMaterial; - if (material == null) - return true; - - - bool has = material.HasProperty("_MainTex"); - if (has) - { - Vector2 offset = material.GetTextureOffset("_MainTex"); - Vector2 scale = material.GetTextureScale("_MainTex"); - if (offset.x != 0 || offset.y != 0 || scale.x != 1 || scale.y != 1) - tiled = true; - } - - return material.HasProperty("_MainTex"); - } - - private static void ShowError(string error) - { - var c = new GUIContent(error) {image = Contents.warningIcon}; - - GUILayout.Space(5); - GUILayout.BeginVertical(EditorStyles.helpBox); - GUILayout.Label(c, EditorStyles.wordWrappedMiniLabel); - GUILayout.EndVertical(); - } - } -} diff --git a/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs b/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs deleted file mode 100644 index e13ac1cb2c..0000000000 --- a/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs +++ /dev/null @@ -1,794 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace UnityEditor -{ - internal class StandardParticlesShaderGUI : ShaderGUI - { - public enum BlendMode - { - Opaque, - Cutout, - Fade, // Old school alpha-blending mode, fresnel does not affect amount of transparency - Transparent, // Physically plausible transparency mode, implemented as alpha pre-multiply - Additive, - Subtractive, - Modulate - } - - public enum FlipbookMode - { - Simple, - Blended - } - - public enum ColorMode - { - Multiply, - Additive, - Subtractive, - Overlay, - Color, - Difference - } - - private static class Styles - { - public static GUIContent albedoText = EditorGUIUtility.TrTextContent("Albedo", "Albedo (RGB) and Transparency (A)."); - public static GUIContent alphaCutoffText = EditorGUIUtility.TrTextContent("Alpha Cutoff", "Threshold for alpha cutoff."); - public static GUIContent metallicMapText = EditorGUIUtility.TrTextContent("Metallic", "Metallic (R) and Smoothness (A)."); - public static GUIContent smoothnessText = EditorGUIUtility.TrTextContent("Smoothness", "Smoothness value."); - public static GUIContent smoothnessScaleText = EditorGUIUtility.TrTextContent("Smoothness", "Smoothness scale factor."); - public static GUIContent normalMapText = EditorGUIUtility.TrTextContent("Normal Map", "Normal Map."); - public static GUIContent emissionText = EditorGUIUtility.TrTextContent("Color", "Emission (RGB)."); - - public static GUIContent renderingMode = EditorGUIUtility.TrTextContent("Rendering Mode", "Determines the transparency and blending method for drawing the object to the screen."); - public static GUIContent[] blendNames = Array.ConvertAll(Enum.GetNames(typeof(BlendMode)), item => new GUIContent(item)); - - public static GUIContent colorMode = EditorGUIUtility.TrTextContent("Color Mode", "Determines the blending mode between the particle color and the texture albedo."); - public static GUIContent[] colorNames = Array.ConvertAll(Enum.GetNames(typeof(ColorMode)), item => new GUIContent(item)); - - public static GUIContent flipbookMode = EditorGUIUtility.TrTextContent("Flip-Book Mode", "Determines the blending mode used for animated texture sheets."); - public static GUIContent[] flipbookNames = Array.ConvertAll(Enum.GetNames(typeof(FlipbookMode)), item => new GUIContent(item)); - - public static GUIContent twoSidedEnabled = EditorGUIUtility.TrTextContent("Two Sided", "Render both front and back faces of the particle geometry."); - - public static GUIContent distortionEnabled = EditorGUIUtility.TrTextContent("Enable Distortion", "Use a grab pass and normal map to simulate refraction."); - public static GUIContent distortionStrengthText = EditorGUIUtility.TrTextContent("Strength", "Distortion Strength."); - public static GUIContent distortionBlendText = EditorGUIUtility.TrTextContent("Blend", "Weighting between albedo and grab pass."); - - public static GUIContent softParticlesEnabled = EditorGUIUtility.TrTextContent("Enable Soft Particles", "Fade out particle geometry when it gets close to the surface of objects written into the depth buffer."); - public static GUIContent softParticlesNearFadeDistanceText = EditorGUIUtility.TrTextContent("Near fade", "Soft Particles near fade distance."); - public static GUIContent softParticlesFarFadeDistanceText = EditorGUIUtility.TrTextContent("Far fade", "Soft Particles far fade distance."); - - public static GUIContent cameraFadingEnabled = EditorGUIUtility.TrTextContent("Enable Camera Fading", "Fade out particle geometry when it gets close to the camera."); - public static GUIContent cameraNearFadeDistanceText = EditorGUIUtility.TrTextContent("Near fade", "Camera near fade distance."); - public static GUIContent cameraFarFadeDistanceText = EditorGUIUtility.TrTextContent("Far fade", "Camera far fade distance."); - - public static GUIContent emissionEnabled = EditorGUIUtility.TrTextContent("Emission"); - - public static string blendingOptionsText = "Blending Options"; - public static string mainOptionsText = "Main Options"; - public static string mapsOptionsText = "Maps"; - public static string requiredVertexStreamsText = "Required Vertex Streams"; - - public static string streamPositionText = "Position (POSITION.xyz)"; - public static string streamNormalText = "Normal (NORMAL.xyz)"; - public static string streamColorText = "Color (COLOR.xyzw)"; - public static string streamUVText = "UV (TEXCOORD0.xy)"; - public static string streamUV2Text = "UV2 (TEXCOORD0.zw)"; - public static string streamAnimBlendText = "AnimBlend (TEXCOORD1.x)"; - public static string streamAnimFrameText = "AnimFrame (INSTANCED0.x)"; - public static string streamTangentText = "Tangent (TANGENT.xyzw)"; - - public static GUIContent streamApplyToAllSystemsText = EditorGUIUtility.TrTextContent("Apply to Systems", "Apply the vertex stream layout to all Particle Systems using this material"); - } - - MaterialProperty blendMode = null; - MaterialProperty colorMode = null; - MaterialProperty flipbookMode = null; - MaterialProperty cullMode = null; - MaterialProperty distortionEnabled = null; - MaterialProperty distortionStrength = null; - MaterialProperty distortionBlend = null; - MaterialProperty albedoMap = null; - MaterialProperty albedoColor = null; - MaterialProperty alphaCutoff = null; - MaterialProperty metallicMap = null; - MaterialProperty metallic = null; - MaterialProperty smoothness = null; - MaterialProperty bumpScale = null; - MaterialProperty bumpMap = null; - MaterialProperty emissionEnabled = null; - MaterialProperty emissionColorForRendering = null; - MaterialProperty emissionMap = null; - MaterialProperty softParticlesEnabled = null; - MaterialProperty cameraFadingEnabled = null; - MaterialProperty softParticlesNearFadeDistance = null; - MaterialProperty softParticlesFarFadeDistance = null; - MaterialProperty cameraNearFadeDistance = null; - MaterialProperty cameraFarFadeDistance = null; - - MaterialEditor m_MaterialEditor; - - List m_RenderersUsingThisMaterial = new List(); - - bool m_FirstTimeApply = true; - - public void FindProperties(MaterialProperty[] props) - { - blendMode = FindProperty("_Mode", props); - colorMode = FindProperty("_ColorMode", props, false); - flipbookMode = FindProperty("_FlipbookMode", props); - cullMode = FindProperty("_Cull", props); - distortionEnabled = FindProperty("_DistortionEnabled", props); - distortionStrength = FindProperty("_DistortionStrength", props); - distortionBlend = FindProperty("_DistortionBlend", props); - albedoMap = FindProperty("_MainTex", props); - albedoColor = FindProperty("_Color", props); - alphaCutoff = FindProperty("_Cutoff", props); - metallicMap = FindProperty("_MetallicGlossMap", props, false); - metallic = FindProperty("_Metallic", props, false); - smoothness = FindProperty("_Glossiness", props, false); - bumpScale = FindProperty("_BumpScale", props); - bumpMap = FindProperty("_BumpMap", props); - emissionEnabled = FindProperty("_EmissionEnabled", props); - emissionColorForRendering = FindProperty("_EmissionColor", props); - emissionMap = FindProperty("_EmissionMap", props); - softParticlesEnabled = FindProperty("_SoftParticlesEnabled", props); - cameraFadingEnabled = FindProperty("_CameraFadingEnabled", props); - softParticlesNearFadeDistance = FindProperty("_SoftParticlesNearFadeDistance", props); - softParticlesFarFadeDistance = FindProperty("_SoftParticlesFarFadeDistance", props); - cameraNearFadeDistance = FindProperty("_CameraNearFadeDistance", props); - cameraFarFadeDistance = FindProperty("_CameraFarFadeDistance", props); - } - - public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) - { - FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly - m_MaterialEditor = materialEditor; - Material material = materialEditor.target as Material; - - // Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing - // material to a standard shader. - // Do this before any GUI code has been issued to prevent layout issues in subsequent GUILayout statements (case 780071) - if (m_FirstTimeApply) - { - MaterialChanged(material); - CacheRenderersUsingThisMaterial(material); - m_FirstTimeApply = false; - } - - ShaderPropertiesGUI(material); - } - - public void ShaderPropertiesGUI(Material material) - { - // Use default labelWidth - EditorGUIUtility.labelWidth = 0f; - - // Detect any changes to the material - EditorGUI.BeginChangeCheck(); - { - GUILayout.Label(Styles.blendingOptionsText, EditorStyles.boldLabel); - - BlendModePopup(); - ColorModePopup(); - - EditorGUILayout.Space(); - GUILayout.Label(Styles.mainOptionsText, EditorStyles.boldLabel); - - FlipbookModePopup(); - TwoSidedPopup(material); - FadingPopup(material); - DistortionPopup(material); - - EditorGUILayout.Space(); - GUILayout.Label(Styles.mapsOptionsText, EditorStyles.boldLabel); - - DoAlbedoArea(material); - DoSpecularMetallicArea(material); - DoNormalMapArea(material); - DoEmissionArea(material); - - if (!flipbookMode.hasMixedValue && (FlipbookMode)flipbookMode.floatValue != FlipbookMode.Blended) - { - EditorGUI.BeginChangeCheck(); - m_MaterialEditor.TextureScaleOffsetProperty(albedoMap); - if (EditorGUI.EndChangeCheck()) - emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake - } - } - if (EditorGUI.EndChangeCheck()) - { - foreach (var obj in blendMode.targets) - MaterialChanged((Material)obj); - } - - EditorGUILayout.Space(); - - GUILayout.Label(Styles.requiredVertexStreamsText, EditorStyles.boldLabel); - DoVertexStreamsArea(material); - } - - public override void OnClosed(Material material) - { - material.SetShaderPassEnabled("Always", true); - } - - public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) - { - // Sync the lighting flag for the unlit shader - if (newShader.name.Contains("Unlit")) - material.SetFloat("_LightingEnabled", 0.0f); - else - material.SetFloat("_LightingEnabled", 1.0f); - - // _Emission property is lost after assigning Standard shader to the material - // thus transfer it before assigning the new shader - if (material.HasProperty("_Emission")) - { - material.SetColor("_EmissionColor", material.GetColor("_Emission")); - } - - base.AssignNewShaderToMaterial(material, oldShader, newShader); - - if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/")) - { - SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode")); - return; - } - - BlendMode blendMode = BlendMode.Opaque; - if (oldShader.name.Contains("/Transparent/Cutout/")) - { - blendMode = BlendMode.Cutout; - } - else if (oldShader.name.Contains("/Transparent/")) - { - // NOTE: legacy shaders did not provide physically based transparency - // therefore Fade mode - blendMode = BlendMode.Fade; - } - material.SetFloat("_Mode", (float)blendMode); - - MaterialChanged(material); - } - - void BlendModePopup() - { - EditorGUI.showMixedValue = blendMode.hasMixedValue; - var mode = (BlendMode)blendMode.floatValue; - - EditorGUI.BeginChangeCheck(); - mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames); - if (EditorGUI.EndChangeCheck()) - { - m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode"); - blendMode.floatValue = (float)mode; - } - - EditorGUI.showMixedValue = false; - } - - void ColorModePopup() - { - if (colorMode != null) - { - EditorGUI.showMixedValue = colorMode.hasMixedValue; - var mode = (ColorMode)colorMode.floatValue; - - EditorGUI.BeginChangeCheck(); - mode = (ColorMode)EditorGUILayout.Popup(Styles.colorMode, (int)mode, Styles.colorNames); - if (EditorGUI.EndChangeCheck()) - { - m_MaterialEditor.RegisterPropertyChangeUndo("Color Mode"); - colorMode.floatValue = (float)mode; - } - - EditorGUI.showMixedValue = false; - } - } - - void FlipbookModePopup() - { - EditorGUI.showMixedValue = flipbookMode.hasMixedValue; - var mode = (FlipbookMode)flipbookMode.floatValue; - - EditorGUI.BeginChangeCheck(); - mode = (FlipbookMode)EditorGUILayout.Popup(Styles.flipbookMode, (int)mode, Styles.flipbookNames); - if (EditorGUI.EndChangeCheck()) - { - m_MaterialEditor.RegisterPropertyChangeUndo("Flip-Book Mode"); - flipbookMode.floatValue = (float)mode; - } - - EditorGUI.showMixedValue = false; - } - - void TwoSidedPopup(Material material) - { - EditorGUI.showMixedValue = cullMode.hasMixedValue; - var enabled = (cullMode.floatValue == (float)UnityEngine.Rendering.CullMode.Off); - - EditorGUI.BeginChangeCheck(); - enabled = EditorGUILayout.Toggle(Styles.twoSidedEnabled, enabled); - if (EditorGUI.EndChangeCheck()) - { - m_MaterialEditor.RegisterPropertyChangeUndo("Two Sided Enabled"); - cullMode.floatValue = enabled ? (float)UnityEngine.Rendering.CullMode.Off : (float)UnityEngine.Rendering.CullMode.Back; - } - - EditorGUI.showMixedValue = false; - } - - void FadingPopup(Material material) - { - // Z write doesn't work with fading - bool hasZWrite = (material.GetInt("_ZWrite") != 0); - if (!hasZWrite) - { - // Soft Particles - { - EditorGUI.showMixedValue = softParticlesEnabled.hasMixedValue; - var enabled = softParticlesEnabled.floatValue; - - EditorGUI.BeginChangeCheck(); - enabled = EditorGUILayout.Toggle(Styles.softParticlesEnabled, enabled != 0.0f) ? 1.0f : 0.0f; - if (EditorGUI.EndChangeCheck()) - { - m_MaterialEditor.RegisterPropertyChangeUndo("Soft Particles Enabled"); - softParticlesEnabled.floatValue = enabled; - } - - if (enabled != 0.0f) - { - int indentation = 2; - m_MaterialEditor.ShaderProperty(softParticlesNearFadeDistance, Styles.softParticlesNearFadeDistanceText, indentation); - m_MaterialEditor.ShaderProperty(softParticlesFarFadeDistance, Styles.softParticlesFarFadeDistanceText, indentation); - } - } - - // Camera Fading - { - EditorGUI.showMixedValue = cameraFadingEnabled.hasMixedValue; - var enabled = cameraFadingEnabled.floatValue; - - EditorGUI.BeginChangeCheck(); - enabled = EditorGUILayout.Toggle(Styles.cameraFadingEnabled, enabled != 0.0f) ? 1.0f : 0.0f; - if (EditorGUI.EndChangeCheck()) - { - m_MaterialEditor.RegisterPropertyChangeUndo("Camera Fading Enabled"); - cameraFadingEnabled.floatValue = enabled; - } - - if (enabled != 0.0f) - { - int indentation = 2; - m_MaterialEditor.ShaderProperty(cameraNearFadeDistance, Styles.cameraNearFadeDistanceText, indentation); - m_MaterialEditor.ShaderProperty(cameraFarFadeDistance, Styles.cameraFarFadeDistanceText, indentation); - } - } - - EditorGUI.showMixedValue = false; - } - } - - void DistortionPopup(Material material) - { - // Z write doesn't work with distortion - bool hasZWrite = (material.GetInt("_ZWrite") != 0); - if (!hasZWrite) - { - EditorGUI.showMixedValue = distortionEnabled.hasMixedValue; - var enabled = (distortionEnabled.floatValue != 0.0f); - - EditorGUI.BeginChangeCheck(); - enabled = EditorGUILayout.Toggle(Styles.distortionEnabled, enabled); - if (EditorGUI.EndChangeCheck()) - { - m_MaterialEditor.RegisterPropertyChangeUndo("Distortion Enabled"); - distortionEnabled.floatValue = enabled ? 1.0f : 0.0f; - } - - if (enabled) - { - int indentation = 2; - m_MaterialEditor.ShaderProperty(distortionStrength, Styles.distortionStrengthText, indentation); - m_MaterialEditor.ShaderProperty(distortionBlend, Styles.distortionBlendText, indentation); - } - - EditorGUI.showMixedValue = false; - } - } - - void DoAlbedoArea(Material material) - { - m_MaterialEditor.TexturePropertyWithHDRColor(Styles.albedoText, albedoMap, albedoColor, true); - if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout)) - { - m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText, MaterialEditor.kMiniTextureFieldLabelIndentLevel); - } - } - - void DoEmissionArea(Material material) - { - // Emission - EditorGUI.showMixedValue = emissionEnabled.hasMixedValue; - var enabled = (emissionEnabled.floatValue != 0.0f); - - EditorGUI.BeginChangeCheck(); - enabled = EditorGUILayout.Toggle(Styles.emissionEnabled, enabled); - if (EditorGUI.EndChangeCheck()) - { - m_MaterialEditor.RegisterPropertyChangeUndo("Emission Enabled"); - emissionEnabled.floatValue = enabled ? 1.0f : 0.0f; - } - - if (enabled) - { - bool hadEmissionTexture = emissionMap.textureValue != null; - - // Texture and HDR color controls - m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, false); - - // If texture was assigned and color was black set color to white - float brightness = emissionColorForRendering.colorValue.maxColorComponent; - if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f) - emissionColorForRendering.colorValue = Color.white; - } - } - - void DoSpecularMetallicArea(Material material) - { - if (metallicMap == null) - return; - - bool useLighting = (material.GetFloat("_LightingEnabled") > 0.0f); - if (useLighting) - { - bool hasGlossMap = metallicMap.textureValue != null; - m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, hasGlossMap ? null : metallic); - - int indentation = 2; // align with labels of texture properties - bool showSmoothnessScale = hasGlossMap; - m_MaterialEditor.ShaderProperty(smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation); - } - } - - void DoNormalMapArea(Material material) - { - bool hasZWrite = (material.GetInt("_ZWrite") != 0); - bool useLighting = (material.GetFloat("_LightingEnabled") > 0.0f); - bool useDistortion = (material.GetFloat("_DistortionEnabled") > 0.0f) && !hasZWrite; - if (useLighting || useDistortion) - { - m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null); - } - } - - void DoVertexStreamsArea(Material material) - { - // Display list of streams required to make this shader work - bool useLighting = (material.GetFloat("_LightingEnabled") > 0.0f); - bool useFlipbookBlending = (material.GetFloat("_FlipbookMode") > 0.0f); - bool useTangents = material.GetTexture("_BumpMap") && useLighting; - bool useGPUInstancing = ShaderUtil.HasProceduralInstancing(material.shader); - - GUILayout.Label(Styles.streamPositionText, EditorStyles.label); - - if (useLighting) - GUILayout.Label(Styles.streamNormalText, EditorStyles.label); - - GUILayout.Label(Styles.streamColorText, EditorStyles.label); - GUILayout.Label(Styles.streamUVText, EditorStyles.label); - - if (useTangents) - GUILayout.Label(Styles.streamTangentText, EditorStyles.label); - - if (useGPUInstancing) - { - GUILayout.Label(Styles.streamAnimFrameText, EditorStyles.label); - } - else if (useFlipbookBlending && !useGPUInstancing) - { - GUILayout.Label(Styles.streamUV2Text, EditorStyles.label); - GUILayout.Label(Styles.streamAnimBlendText, EditorStyles.label); - } - - // Build the list of expected vertex streams - List streams = new List(); - streams.Add(ParticleSystemVertexStream.Position); - - if (useLighting) - streams.Add(ParticleSystemVertexStream.Normal); - - streams.Add(ParticleSystemVertexStream.Color); - streams.Add(ParticleSystemVertexStream.UV); - - if (useTangents) - streams.Add(ParticleSystemVertexStream.Tangent); - - List instancedStreams = new List(streams); - - if (useGPUInstancing) - { - instancedStreams.Add(ParticleSystemVertexStream.AnimFrame); - } - if (useFlipbookBlending) - { - streams.Add(ParticleSystemVertexStream.UV2); - streams.Add(ParticleSystemVertexStream.AnimBlend); - } - - // Set the streams on all systems using this material - if (GUILayout.Button(Styles.streamApplyToAllSystemsText, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - { - foreach (ParticleSystemRenderer renderer in m_RenderersUsingThisMaterial) - { - if (useGPUInstancing && renderer.renderMode == ParticleSystemRenderMode.Mesh && renderer.supportsMeshInstancing) - renderer.SetActiveVertexStreams(instancedStreams); - else - renderer.SetActiveVertexStreams(streams); - } - } - - // Display a warning if any renderers have incorrect vertex streams - string Warnings = ""; - List rendererStreams = new List(); - foreach (ParticleSystemRenderer renderer in m_RenderersUsingThisMaterial) - { - renderer.GetActiveVertexStreams(rendererStreams); - - bool streamsValid; - if (useGPUInstancing && renderer.renderMode == ParticleSystemRenderMode.Mesh && renderer.supportsMeshInstancing) - streamsValid = rendererStreams.SequenceEqual(instancedStreams); - else - streamsValid = rendererStreams.SequenceEqual(streams); - - if (!streamsValid) - Warnings += " " + renderer.name + "\n"; - } - if (Warnings != "") - { - 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); - } - - EditorGUILayout.Space(); - } - - public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode) - { - switch (blendMode) - { - case BlendMode.Opaque: - material.SetOverrideTag("RenderType", ""); - material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); - material.SetInt("_ZWrite", 1); - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.DisableKeyword("_ALPHAMODULATE_ON"); - material.renderQueue = -1; - break; - case BlendMode.Cutout: - material.SetOverrideTag("RenderType", "TransparentCutout"); - material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); - material.SetInt("_ZWrite", 1); - material.EnableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.DisableKeyword("_ALPHAMODULATE_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest; - break; - case BlendMode.Fade: - material.SetOverrideTag("RenderType", "Transparent"); - material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetInt("_ZWrite", 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.DisableKeyword("_ALPHAMODULATE_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; - break; - case BlendMode.Transparent: - material.SetOverrideTag("RenderType", "Transparent"); - material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetInt("_ZWrite", 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); - material.DisableKeyword("_ALPHAMODULATE_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; - break; - case BlendMode.Additive: - material.SetOverrideTag("RenderType", "Transparent"); - material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_ZWrite", 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.DisableKeyword("_ALPHAMODULATE_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; - break; - case BlendMode.Subtractive: - material.SetOverrideTag("RenderType", "Transparent"); - material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.ReverseSubtract); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_ZWrite", 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.DisableKeyword("_ALPHAMODULATE_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; - break; - case BlendMode.Modulate: - material.SetOverrideTag("RenderType", "Transparent"); - material.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.DstColor); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetInt("_ZWrite", 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.EnableKeyword("_ALPHAMODULATE_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; - break; - } - } - - public static void SetupMaterialWithColorMode(Material material, ColorMode colorMode) - { - switch (colorMode) - { - case ColorMode.Multiply: - material.DisableKeyword("_COLOROVERLAY_ON"); - material.DisableKeyword("_COLORCOLOR_ON"); - material.DisableKeyword("_COLORADDSUBDIFF_ON"); - break; - case ColorMode.Overlay: - material.DisableKeyword("_COLORCOLOR_ON"); - material.DisableKeyword("_COLORADDSUBDIFF_ON"); - material.EnableKeyword("_COLOROVERLAY_ON"); - break; - case ColorMode.Color: - material.DisableKeyword("_COLOROVERLAY_ON"); - material.DisableKeyword("_COLORADDSUBDIFF_ON"); - material.EnableKeyword("_COLORCOLOR_ON"); - break; - case ColorMode.Difference: - material.DisableKeyword("_COLOROVERLAY_ON"); - material.DisableKeyword("_COLORCOLOR_ON"); - material.EnableKeyword("_COLORADDSUBDIFF_ON"); - material.SetVector("_ColorAddSubDiff", new Vector4(-1.0f, 1.0f, 0.0f, 0.0f)); - break; - case ColorMode.Additive: - material.DisableKeyword("_COLOROVERLAY_ON"); - material.DisableKeyword("_COLORCOLOR_ON"); - material.EnableKeyword("_COLORADDSUBDIFF_ON"); - material.SetVector("_ColorAddSubDiff", new Vector4(1.0f, 0.0f, 0.0f, 0.0f)); - break; - case ColorMode.Subtractive: - material.DisableKeyword("_COLOROVERLAY_ON"); - material.DisableKeyword("_COLORCOLOR_ON"); - material.EnableKeyword("_COLORADDSUBDIFF_ON"); - material.SetVector("_ColorAddSubDiff", new Vector4(-1.0f, 0.0f, 0.0f, 0.0f)); - break; - } - } - - void SetMaterialKeywords(Material material) - { - // Z write doesn't work with distortion/fading - bool hasZWrite = (material.GetInt("_ZWrite") != 0); - - // Lit shader? - bool useLighting = (material.GetFloat("_LightingEnabled") > 0.0f); - - // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation - // (MaterialProperty value might come from renderer material property block) - bool useDistortion = (material.GetFloat("_DistortionEnabled") > 0.0f) && !hasZWrite; - SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap") && (useLighting || useDistortion)); - SetKeyword(material, "_METALLICGLOSSMAP", (material.GetTexture("_MetallicGlossMap") != null) && useLighting); - - material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.None; - SetKeyword(material, "_EMISSION", material.GetFloat("_EmissionEnabled") > 0.0f); - - // Set the define for flipbook blending - bool useFlipbookBlending = (material.GetFloat("_FlipbookMode") > 0.0f); - SetKeyword(material, "_REQUIRE_UV2", useFlipbookBlending); - - // Clamp fade distances - bool useSoftParticles = (material.GetFloat("_SoftParticlesEnabled") > 0.0f); - bool useCameraFading = (material.GetFloat("_CameraFadingEnabled") > 0.0f); - float softParticlesNearFadeDistance = material.GetFloat("_SoftParticlesNearFadeDistance"); - float softParticlesFarFadeDistance = material.GetFloat("_SoftParticlesFarFadeDistance"); - float cameraNearFadeDistance = material.GetFloat("_CameraNearFadeDistance"); - float cameraFarFadeDistance = material.GetFloat("_CameraFarFadeDistance"); - - if (softParticlesNearFadeDistance < 0.0f) - { - softParticlesNearFadeDistance = 0.0f; - material.SetFloat("_SoftParticlesNearFadeDistance", 0.0f); - } - if (softParticlesFarFadeDistance < 0.0f) - { - softParticlesFarFadeDistance = 0.0f; - material.SetFloat("_SoftParticlesFarFadeDistance", 0.0f); - } - if (cameraNearFadeDistance < 0.0f) - { - cameraNearFadeDistance = 0.0f; - material.SetFloat("_CameraNearFadeDistance", 0.0f); - } - if (cameraFarFadeDistance < 0.0f) - { - cameraFarFadeDistance = 0.0f; - material.SetFloat("_CameraFarFadeDistance", 0.0f); - } - - // Set the define for fading - bool useFading = (useSoftParticles || useCameraFading) && !hasZWrite; - SetKeyword(material, "_FADING_ON", useFading); - if (useSoftParticles) - material.SetVector("_SoftParticleFadeParams", new Vector4(softParticlesNearFadeDistance, 1.0f / (softParticlesFarFadeDistance - softParticlesNearFadeDistance), 0.0f, 0.0f)); - else - material.SetVector("_SoftParticleFadeParams", new Vector4(0.0f, 0.0f, 0.0f, 0.0f)); - if (useCameraFading) - material.SetVector("_CameraFadeParams", new Vector4(cameraNearFadeDistance, 1.0f / (cameraFarFadeDistance - cameraNearFadeDistance), 0.0f, 0.0f)); - else - material.SetVector("_CameraFadeParams", new Vector4(0.0f, Mathf.Infinity, 0.0f, 0.0f)); - - // Set the define for distortion + grabpass - SetKeyword(material, "EFFECT_BUMP", useDistortion); - material.SetShaderPassEnabled("Always", useDistortion); - if (useDistortion) - material.SetFloat("_DistortionStrengthScaled", material.GetFloat("_DistortionStrength") * 0.1f); // more friendly number scale than 1 unit per size of the screen - } - - void MaterialChanged(Material material) - { - SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode")); - if (colorMode != null) - SetupMaterialWithColorMode(material, (ColorMode)material.GetFloat("_ColorMode")); - SetMaterialKeywords(material); - } - - void CacheRenderersUsingThisMaterial(Material material) - { - m_RenderersUsingThisMaterial.Clear(); - - ParticleSystemRenderer[] renderers = UnityEngine.Object.FindObjectsOfType(typeof(ParticleSystemRenderer)) as ParticleSystemRenderer[]; - foreach (ParticleSystemRenderer renderer in renderers) - { - if (renderer.sharedMaterial == material) - m_RenderersUsingThisMaterial.Add(renderer); - } - } - - static void SetKeyword(Material m, string keyword, bool state) - { - if (state) - m.EnableKeyword(keyword); - else - m.DisableKeyword(keyword); - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/Inspector/StandardRoughnessShaderGUI.cs b/Editor/Mono/Inspector/StandardRoughnessShaderGUI.cs deleted file mode 100644 index 1d5c3a134f..0000000000 --- a/Editor/Mono/Inspector/StandardRoughnessShaderGUI.cs +++ /dev/null @@ -1,332 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal class StandardRoughnessShaderGUI : ShaderGUI - { - public enum BlendMode - { - Opaque, - Cutout, - Fade, // Old school alpha-blending mode, fresnel does not affect amount of transparency - Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply - } - - private static class Styles - { - public static GUIContent uvSetLabel = EditorGUIUtility.TrTextContent("UV Set"); - - public static GUIContent albedoText = EditorGUIUtility.TrTextContent("Albedo", "Albedo (RGB) and Transparency (A)"); - public static GUIContent alphaCutoffText = EditorGUIUtility.TrTextContent("Alpha Cutoff", "Threshold for alpha cutoff"); - public static GUIContent metallicMapText = EditorGUIUtility.TrTextContent("Metallic", "Metallic (R) and Smoothness (A)"); - public static GUIContent roughnessText = EditorGUIUtility.TrTextContent("Roughness", "Roughness value"); - public static GUIContent highlightsText = EditorGUIUtility.TrTextContent("Specular Highlights", "Specular Highlights"); - public static GUIContent reflectionsText = EditorGUIUtility.TrTextContent("Reflections", "Glossy Reflections"); - public static GUIContent normalMapText = EditorGUIUtility.TrTextContent("Normal Map", "Normal Map"); - public static GUIContent heightMapText = EditorGUIUtility.TrTextContent("Height Map", "Height Map (G)"); - public static GUIContent occlusionText = EditorGUIUtility.TrTextContent("Occlusion", "Occlusion (G)"); - public static GUIContent emissionText = EditorGUIUtility.TrTextContent("Color", "Emission (RGB)"); - public static GUIContent detailMaskText = EditorGUIUtility.TrTextContent("Detail Mask", "Mask for Secondary Maps (A)"); - public static GUIContent detailAlbedoText = EditorGUIUtility.TrTextContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2"); - public static GUIContent detailNormalMapText = EditorGUIUtility.TrTextContent("Normal Map", "Normal Map"); - - public static string primaryMapsText = "Main Maps"; - public static string secondaryMapsText = "Secondary Maps"; - public static string forwardText = "Forward Rendering Options"; - public static string renderingMode = "Rendering Mode"; - public static string advancedText = "Advanced Options"; - public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode)); - } - - MaterialProperty blendMode = null; - MaterialProperty albedoMap = null; - MaterialProperty albedoColor = null; - MaterialProperty alphaCutoff = null; - MaterialProperty metallicMap = null; - MaterialProperty metallic = null; - MaterialProperty roughness = null; - MaterialProperty roughnessMap = null; - MaterialProperty highlights = null; - MaterialProperty reflections = null; - MaterialProperty bumpScale = null; - MaterialProperty bumpMap = null; - MaterialProperty occlusionStrength = null; - MaterialProperty occlusionMap = null; - MaterialProperty heigtMapScale = null; - MaterialProperty heightMap = null; - MaterialProperty emissionColorForRendering = null; - MaterialProperty emissionMap = null; - MaterialProperty detailMask = null; - MaterialProperty detailAlbedoMap = null; - MaterialProperty detailNormalMapScale = null; - MaterialProperty detailNormalMap = null; - MaterialProperty uvSetSecondary = null; - - MaterialEditor m_MaterialEditor; - - bool m_FirstTimeApply = true; - - public void FindProperties(MaterialProperty[] props) - { - blendMode = FindProperty("_Mode", props); - albedoMap = FindProperty("_MainTex", props); - albedoColor = FindProperty("_Color", props); - alphaCutoff = FindProperty("_Cutoff", props); - metallicMap = FindProperty("_MetallicGlossMap", props, false); - metallic = FindProperty("_Metallic", props, false); - roughness = FindProperty("_Glossiness", props); - roughnessMap = FindProperty("_SpecGlossMap", props); - highlights = FindProperty("_SpecularHighlights", props, false); - reflections = FindProperty("_GlossyReflections", props, false); - bumpScale = FindProperty("_BumpScale", props); - bumpMap = FindProperty("_BumpMap", props); - heigtMapScale = FindProperty("_Parallax", props); - heightMap = FindProperty("_ParallaxMap", props); - occlusionStrength = FindProperty("_OcclusionStrength", props); - occlusionMap = FindProperty("_OcclusionMap", props); - emissionColorForRendering = FindProperty("_EmissionColor", props); - emissionMap = FindProperty("_EmissionMap", props); - detailMask = FindProperty("_DetailMask", props); - detailAlbedoMap = FindProperty("_DetailAlbedoMap", props); - detailNormalMapScale = FindProperty("_DetailNormalMapScale", props); - detailNormalMap = FindProperty("_DetailNormalMap", props); - uvSetSecondary = FindProperty("_UVSec", props); - } - - public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) - { - FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly - m_MaterialEditor = materialEditor; - Material material = materialEditor.target as Material; - - // Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing - // material to a standard shader. - // Do this before any GUI code has been issued to prevent layout issues in subsequent GUILayout statements (case 780071) - if (m_FirstTimeApply) - { - MaterialChanged(material); - m_FirstTimeApply = false; - } - - ShaderPropertiesGUI(material); - } - - public void ShaderPropertiesGUI(Material material) - { - // Use default labelWidth - EditorGUIUtility.labelWidth = 0f; - - // Detect any changes to the material - EditorGUI.BeginChangeCheck(); - { - BlendModePopup(); - - // Primary properties - GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel); - DoAlbedoArea(material); - m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, metallicMap.textureValue != null ? null : metallic); - m_MaterialEditor.TexturePropertySingleLine(Styles.roughnessText, roughnessMap, roughnessMap.textureValue != null ? null : roughness); - m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null); - m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null); - m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null); - m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask); - DoEmissionArea(material); - EditorGUI.BeginChangeCheck(); - m_MaterialEditor.TextureScaleOffsetProperty(albedoMap); - if (EditorGUI.EndChangeCheck()) - emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake - - EditorGUILayout.Space(); - - // Secondary properties - GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel); - m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap); - m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale); - m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap); - m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text); - - // Third properties - GUILayout.Label(Styles.forwardText, EditorStyles.boldLabel); - if (highlights != null) - m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText); - if (reflections != null) - m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText); - } - if (EditorGUI.EndChangeCheck()) - { - foreach (var obj in blendMode.targets) - MaterialChanged((Material)obj); - } - - EditorGUILayout.Space(); - - // NB renderqueue editor is not shown on purpose: we want to override it based on blend mode - GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel); - m_MaterialEditor.EnableInstancingField(); - m_MaterialEditor.DoubleSidedGIField(); - } - - public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) - { - // _Emission property is lost after assigning Standard shader to the material - // thus transfer it before assigning the new shader - if (material.HasProperty("_Emission")) - { - material.SetColor("_EmissionColor", material.GetColor("_Emission")); - } - - base.AssignNewShaderToMaterial(material, oldShader, newShader); - - if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/")) - { - SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode")); - return; - } - - BlendMode blendMode = BlendMode.Opaque; - if (oldShader.name.Contains("/Transparent/Cutout/")) - { - blendMode = BlendMode.Cutout; - } - else if (oldShader.name.Contains("/Transparent/")) - { - // NOTE: legacy shaders did not provide physically based transparency - // therefore Fade mode - blendMode = BlendMode.Fade; - } - material.SetFloat("_Mode", (float)blendMode); - - MaterialChanged(material); - } - - void BlendModePopup() - { - EditorGUI.showMixedValue = blendMode.hasMixedValue; - var mode = (BlendMode)blendMode.floatValue; - - EditorGUI.BeginChangeCheck(); - mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames); - if (EditorGUI.EndChangeCheck()) - { - m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode"); - blendMode.floatValue = (float)mode; - } - - EditorGUI.showMixedValue = false; - } - - void DoAlbedoArea(Material material) - { - m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor); - if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout)) - { - m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1); - } - } - - void DoEmissionArea(Material material) - { - // Emission for GI? - if (m_MaterialEditor.EmissionEnabledProperty()) - { - bool hadEmissionTexture = emissionMap.textureValue != null; - - // Texture and HDR color controls - m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, false); - - // If texture was assigned and color was black set color to white - float brightness = emissionColorForRendering.colorValue.maxColorComponent; - if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f) - emissionColorForRendering.colorValue = Color.white; - - // change the GI flag and fix it up with emissive as black if necessary - m_MaterialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true); - } - } - - public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode) - { - switch (blendMode) - { - case BlendMode.Opaque: - material.SetOverrideTag("RenderType", ""); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); - material.SetInt("_ZWrite", 1); - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = -1; - break; - case BlendMode.Cutout: - material.SetOverrideTag("RenderType", "TransparentCutout"); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); - material.SetInt("_ZWrite", 1); - material.EnableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest; - break; - case BlendMode.Fade: - material.SetOverrideTag("RenderType", "Transparent"); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetInt("_ZWrite", 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; - break; - case BlendMode.Transparent: - material.SetOverrideTag("RenderType", "Transparent"); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetInt("_ZWrite", 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; - break; - } - } - - static void SetMaterialKeywords(Material material) - { - // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation - // (MaterialProperty value might come from renderer material property block) - SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap") || material.GetTexture("_DetailNormalMap")); - SetKeyword(material, "_SPECGLOSSMAP", material.GetTexture("_SpecGlossMap")); - SetKeyword(material, "_METALLICGLOSSMAP", material.GetTexture("_MetallicGlossMap")); - SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap")); - SetKeyword(material, "_DETAIL_MULX2", material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap")); - - // A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect - // or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color. - // The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color. - MaterialEditor.FixupEmissiveFlag(material); - bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0; - SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled); - } - - static void MaterialChanged(Material material) - { - SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode")); - - SetMaterialKeywords(material); - } - - static void SetKeyword(Material m, string keyword, bool state) - { - if (state) - m.EnableKeyword(keyword); - else - m.DisableKeyword(keyword); - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/Inspector/StandardShaderGUI.cs b/Editor/Mono/Inspector/StandardShaderGUI.cs deleted file mode 100644 index 9ae686314c..0000000000 --- a/Editor/Mono/Inspector/StandardShaderGUI.cs +++ /dev/null @@ -1,429 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - internal class StandardShaderGUI : ShaderGUI - { - private enum WorkflowMode - { - Specular, - Metallic, - Dielectric - } - - public enum BlendMode - { - Opaque, - Cutout, - Fade, // Old school alpha-blending mode, fresnel does not affect amount of transparency - Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply - } - - public enum SmoothnessMapChannel - { - SpecularMetallicAlpha, - AlbedoAlpha, - } - - private static class Styles - { - public static GUIContent uvSetLabel = EditorGUIUtility.TrTextContent("UV Set"); - - public static GUIContent albedoText = EditorGUIUtility.TrTextContent("Albedo", "Albedo (RGB) and Transparency (A)"); - public static GUIContent alphaCutoffText = EditorGUIUtility.TrTextContent("Alpha Cutoff", "Threshold for alpha cutoff"); - public static GUIContent specularMapText = EditorGUIUtility.TrTextContent("Specular", "Specular (RGB) and Smoothness (A)"); - public static GUIContent metallicMapText = EditorGUIUtility.TrTextContent("Metallic", "Metallic (R) and Smoothness (A)"); - public static GUIContent smoothnessText = EditorGUIUtility.TrTextContent("Smoothness", "Smoothness value"); - public static GUIContent smoothnessScaleText = EditorGUIUtility.TrTextContent("Smoothness", "Smoothness scale factor"); - public static GUIContent smoothnessMapChannelText = EditorGUIUtility.TrTextContent("Source", "Smoothness texture and channel"); - public static GUIContent highlightsText = EditorGUIUtility.TrTextContent("Specular Highlights", "Specular Highlights"); - public static GUIContent reflectionsText = EditorGUIUtility.TrTextContent("Reflections", "Glossy Reflections"); - public static GUIContent normalMapText = EditorGUIUtility.TrTextContent("Normal Map", "Normal Map"); - public static GUIContent heightMapText = EditorGUIUtility.TrTextContent("Height Map", "Height Map (G)"); - public static GUIContent occlusionText = EditorGUIUtility.TrTextContent("Occlusion", "Occlusion (G)"); - public static GUIContent emissionText = EditorGUIUtility.TrTextContent("Color", "Emission (RGB)"); - public static GUIContent detailMaskText = EditorGUIUtility.TrTextContent("Detail Mask", "Mask for Secondary Maps (A)"); - public static GUIContent detailAlbedoText = EditorGUIUtility.TrTextContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2"); - public static GUIContent detailNormalMapText = EditorGUIUtility.TrTextContent("Normal Map", "Normal Map"); - - public static string primaryMapsText = "Main Maps"; - public static string secondaryMapsText = "Secondary Maps"; - public static string forwardText = "Forward Rendering Options"; - public static string renderingMode = "Rendering Mode"; - public static string advancedText = "Advanced Options"; - public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode)); - } - - MaterialProperty blendMode = null; - MaterialProperty albedoMap = null; - MaterialProperty albedoColor = null; - MaterialProperty alphaCutoff = null; - MaterialProperty specularMap = null; - MaterialProperty specularColor = null; - MaterialProperty metallicMap = null; - MaterialProperty metallic = null; - MaterialProperty smoothness = null; - MaterialProperty smoothnessScale = null; - MaterialProperty smoothnessMapChannel = null; - MaterialProperty highlights = null; - MaterialProperty reflections = null; - MaterialProperty bumpScale = null; - MaterialProperty bumpMap = null; - MaterialProperty occlusionStrength = null; - MaterialProperty occlusionMap = null; - MaterialProperty heigtMapScale = null; - MaterialProperty heightMap = null; - MaterialProperty emissionColorForRendering = null; - MaterialProperty emissionMap = null; - MaterialProperty detailMask = null; - MaterialProperty detailAlbedoMap = null; - MaterialProperty detailNormalMapScale = null; - MaterialProperty detailNormalMap = null; - MaterialProperty uvSetSecondary = null; - - MaterialEditor m_MaterialEditor; - WorkflowMode m_WorkflowMode = WorkflowMode.Specular; - - bool m_FirstTimeApply = true; - - public void FindProperties(MaterialProperty[] props) - { - blendMode = FindProperty("_Mode", props); - albedoMap = FindProperty("_MainTex", props); - albedoColor = FindProperty("_Color", props); - alphaCutoff = FindProperty("_Cutoff", props); - specularMap = FindProperty("_SpecGlossMap", props, false); - specularColor = FindProperty("_SpecColor", props, false); - metallicMap = FindProperty("_MetallicGlossMap", props, false); - metallic = FindProperty("_Metallic", props, false); - if (specularMap != null && specularColor != null) - m_WorkflowMode = WorkflowMode.Specular; - else if (metallicMap != null && metallic != null) - m_WorkflowMode = WorkflowMode.Metallic; - else - m_WorkflowMode = WorkflowMode.Dielectric; - smoothness = FindProperty("_Glossiness", props); - smoothnessScale = FindProperty("_GlossMapScale", props, false); - smoothnessMapChannel = FindProperty("_SmoothnessTextureChannel", props, false); - highlights = FindProperty("_SpecularHighlights", props, false); - reflections = FindProperty("_GlossyReflections", props, false); - bumpScale = FindProperty("_BumpScale", props); - bumpMap = FindProperty("_BumpMap", props); - heigtMapScale = FindProperty("_Parallax", props); - heightMap = FindProperty("_ParallaxMap", props); - occlusionStrength = FindProperty("_OcclusionStrength", props); - occlusionMap = FindProperty("_OcclusionMap", props); - emissionColorForRendering = FindProperty("_EmissionColor", props); - emissionMap = FindProperty("_EmissionMap", props); - detailMask = FindProperty("_DetailMask", props); - detailAlbedoMap = FindProperty("_DetailAlbedoMap", props); - detailNormalMapScale = FindProperty("_DetailNormalMapScale", props); - detailNormalMap = FindProperty("_DetailNormalMap", props); - uvSetSecondary = FindProperty("_UVSec", props); - } - - public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) - { - FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly - m_MaterialEditor = materialEditor; - Material material = materialEditor.target as Material; - - // Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing - // material to a standard shader. - // Do this before any GUI code has been issued to prevent layout issues in subsequent GUILayout statements (case 780071) - if (m_FirstTimeApply) - { - MaterialChanged(material, m_WorkflowMode); - m_FirstTimeApply = false; - } - - ShaderPropertiesGUI(material); - } - - public void ShaderPropertiesGUI(Material material) - { - // Use default labelWidth - EditorGUIUtility.labelWidth = 0f; - - // Detect any changes to the material - EditorGUI.BeginChangeCheck(); - { - BlendModePopup(); - - // Primary properties - GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel); - DoAlbedoArea(material); - DoSpecularMetallicArea(); - DoNormalArea(); - m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightMap.textureValue != null ? heigtMapScale : null); - m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null); - m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask); - DoEmissionArea(material); - EditorGUI.BeginChangeCheck(); - m_MaterialEditor.TextureScaleOffsetProperty(albedoMap); - if (EditorGUI.EndChangeCheck()) - emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake - - EditorGUILayout.Space(); - - // Secondary properties - GUILayout.Label(Styles.secondaryMapsText, EditorStyles.boldLabel); - m_MaterialEditor.TexturePropertySingleLine(Styles.detailAlbedoText, detailAlbedoMap); - m_MaterialEditor.TexturePropertySingleLine(Styles.detailNormalMapText, detailNormalMap, detailNormalMapScale); - m_MaterialEditor.TextureScaleOffsetProperty(detailAlbedoMap); - m_MaterialEditor.ShaderProperty(uvSetSecondary, Styles.uvSetLabel.text); - - // Third properties - GUILayout.Label(Styles.forwardText, EditorStyles.boldLabel); - if (highlights != null) - m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText); - if (reflections != null) - m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText); - } - if (EditorGUI.EndChangeCheck()) - { - foreach (var obj in blendMode.targets) - MaterialChanged((Material)obj, m_WorkflowMode); - } - - EditorGUILayout.Space(); - - // NB renderqueue editor is not shown on purpose: we want to override it based on blend mode - GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel); - m_MaterialEditor.EnableInstancingField(); - m_MaterialEditor.DoubleSidedGIField(); - } - - internal void DetermineWorkflow(MaterialProperty[] props) - { - if (FindProperty("_SpecGlossMap", props, false) != null && FindProperty("_SpecColor", props, false) != null) - m_WorkflowMode = WorkflowMode.Specular; - else if (FindProperty("_MetallicGlossMap", props, false) != null && FindProperty("_Metallic", props, false) != null) - m_WorkflowMode = WorkflowMode.Metallic; - else - m_WorkflowMode = WorkflowMode.Dielectric; - } - - public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) - { - // _Emission property is lost after assigning Standard shader to the material - // thus transfer it before assigning the new shader - if (material.HasProperty("_Emission")) - { - material.SetColor("_EmissionColor", material.GetColor("_Emission")); - } - - base.AssignNewShaderToMaterial(material, oldShader, newShader); - - if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/")) - { - SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode")); - return; - } - - BlendMode blendMode = BlendMode.Opaque; - if (oldShader.name.Contains("/Transparent/Cutout/")) - { - blendMode = BlendMode.Cutout; - } - else if (oldShader.name.Contains("/Transparent/")) - { - // NOTE: legacy shaders did not provide physically based transparency - // therefore Fade mode - blendMode = BlendMode.Fade; - } - material.SetFloat("_Mode", (float)blendMode); - - DetermineWorkflow(MaterialEditor.GetMaterialProperties(new Material[] { material })); - MaterialChanged(material, m_WorkflowMode); - } - - void BlendModePopup() - { - EditorGUI.showMixedValue = blendMode.hasMixedValue; - var mode = (BlendMode)blendMode.floatValue; - - EditorGUI.BeginChangeCheck(); - mode = (BlendMode)EditorGUILayout.Popup(Styles.renderingMode, (int)mode, Styles.blendNames); - if (EditorGUI.EndChangeCheck()) - { - m_MaterialEditor.RegisterPropertyChangeUndo("Rendering Mode"); - blendMode.floatValue = (float)mode; - } - - EditorGUI.showMixedValue = false; - } - - void DoNormalArea() - { - m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap, bumpMap.textureValue != null ? bumpScale : null); - if (bumpScale.floatValue != 1 && UnityEditorInternal.InternalEditorUtility.IsMobilePlatform(EditorUserBuildSettings.activeBuildTarget)) - if (m_MaterialEditor.HelpBoxWithButton( - EditorGUIUtility.TrTextContent("Bump scale is not supported on mobile platforms"), - EditorGUIUtility.TrTextContent("Fix Now"))) - { - bumpScale.floatValue = 1; - } - } - - void DoAlbedoArea(Material material) - { - m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor); - if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout)) - { - m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1); - } - } - - void DoEmissionArea(Material material) - { - // Emission for GI? - if (m_MaterialEditor.EmissionEnabledProperty()) - { - bool hadEmissionTexture = emissionMap.textureValue != null; - - // Texture and HDR color controls - m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, false); - - // If texture was assigned and color was black set color to white - float brightness = emissionColorForRendering.colorValue.maxColorComponent; - if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f) - emissionColorForRendering.colorValue = Color.white; - - // change the GI flag and fix it up with emissive as black if necessary - m_MaterialEditor.LightmapEmissionFlagsProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel, true); - } - } - - void DoSpecularMetallicArea() - { - bool hasGlossMap = false; - if (m_WorkflowMode == WorkflowMode.Specular) - { - hasGlossMap = specularMap.textureValue != null; - m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specularMap, hasGlossMap ? null : specularColor); - } - else if (m_WorkflowMode == WorkflowMode.Metallic) - { - hasGlossMap = metallicMap.textureValue != null; - m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicMap, hasGlossMap ? null : metallic); - } - - bool showSmoothnessScale = hasGlossMap; - if (smoothnessMapChannel != null) - { - int smoothnessChannel = (int)smoothnessMapChannel.floatValue; - if (smoothnessChannel == (int)SmoothnessMapChannel.AlbedoAlpha) - showSmoothnessScale = true; - } - - int indentation = 2; // align with labels of texture properties - m_MaterialEditor.ShaderProperty(showSmoothnessScale ? smoothnessScale : smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation); - - ++indentation; - if (smoothnessMapChannel != null) - m_MaterialEditor.ShaderProperty(smoothnessMapChannel, Styles.smoothnessMapChannelText, indentation); - } - - public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode) - { - switch (blendMode) - { - case BlendMode.Opaque: - material.SetOverrideTag("RenderType", ""); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); - material.SetInt("_ZWrite", 1); - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = -1; - break; - case BlendMode.Cutout: - material.SetOverrideTag("RenderType", "TransparentCutout"); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); - material.SetInt("_ZWrite", 1); - material.EnableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest; - break; - case BlendMode.Fade: - material.SetOverrideTag("RenderType", "Transparent"); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetInt("_ZWrite", 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.EnableKeyword("_ALPHABLEND_ON"); - material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; - break; - case BlendMode.Transparent: - material.SetOverrideTag("RenderType", "Transparent"); - material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); - material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - material.SetInt("_ZWrite", 0); - material.DisableKeyword("_ALPHATEST_ON"); - material.DisableKeyword("_ALPHABLEND_ON"); - material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); - material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; - break; - } - } - - static SmoothnessMapChannel GetSmoothnessMapChannel(Material material) - { - int ch = (int)material.GetFloat("_SmoothnessTextureChannel"); - if (ch == (int)SmoothnessMapChannel.AlbedoAlpha) - return SmoothnessMapChannel.AlbedoAlpha; - else - return SmoothnessMapChannel.SpecularMetallicAlpha; - } - - static void SetMaterialKeywords(Material material, WorkflowMode workflowMode) - { - // Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation - // (MaterialProperty value might come from renderer material property block) - SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap") || material.GetTexture("_DetailNormalMap")); - if (workflowMode == WorkflowMode.Specular) - SetKeyword(material, "_SPECGLOSSMAP", material.GetTexture("_SpecGlossMap")); - else if (workflowMode == WorkflowMode.Metallic) - SetKeyword(material, "_METALLICGLOSSMAP", material.GetTexture("_MetallicGlossMap")); - SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap")); - SetKeyword(material, "_DETAIL_MULX2", material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap")); - - // A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect - // or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color. - // The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color. - MaterialEditor.FixupEmissiveFlag(material); - bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0; - SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled); - - if (material.HasProperty("_SmoothnessTextureChannel")) - { - SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha); - } - } - - static void MaterialChanged(Material material, WorkflowMode workflowMode) - { - SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode")); - - SetMaterialKeywords(material, workflowMode); - } - - static void SetKeyword(Material m, string keyword, bool state) - { - if (state) - m.EnableKeyword(keyword); - else - m.DisableKeyword(keyword); - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/Inspector/SurfaceEffector2DEditor.cs b/Editor/Mono/Inspector/SurfaceEffector2DEditor.cs deleted file mode 100644 index e2e1d2c4cd..0000000000 --- a/Editor/Mono/Inspector/SurfaceEffector2DEditor.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditor.AnimatedValues; - -namespace UnityEditor -{ - /// - /// Prompts the end-user to add 2D colliders if non exist for 2D effector to work with. - /// - [CustomEditor(typeof(SurfaceEffector2D), true)] - [CanEditMultipleObjects] - internal class SurfaceEffector2DEditor : Effector2DEditor - { - readonly AnimBool m_ShowForceRollout = new AnimBool(); - SerializedProperty m_Speed; - SerializedProperty m_SpeedVariation; - SerializedProperty m_ForceScale; - - static readonly AnimBool m_ShowOptionsRollout = new AnimBool(); - SerializedProperty m_UseContactForce; - SerializedProperty m_UseFriction; - SerializedProperty m_UseBounce; - - public override void OnEnable() - { - base.OnEnable(); - - - m_ShowForceRollout.value = true; - m_ShowForceRollout.valueChanged.AddListener(Repaint); - m_Speed = serializedObject.FindProperty("m_Speed"); - m_SpeedVariation = serializedObject.FindProperty("m_SpeedVariation"); - m_ForceScale = serializedObject.FindProperty("m_ForceScale"); - - m_ShowOptionsRollout.valueChanged.AddListener(Repaint); - m_UseContactForce = serializedObject.FindProperty("m_UseContactForce"); - m_UseFriction = serializedObject.FindProperty("m_UseFriction"); - m_UseBounce = serializedObject.FindProperty("m_UseBounce"); - } - - public override void OnDisable() - { - base.OnDisable(); - - m_ShowForceRollout.valueChanged.RemoveListener(Repaint); - m_ShowOptionsRollout.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - - serializedObject.Update(); - - // Force. - m_ShowForceRollout.target = EditorGUILayout.Foldout(m_ShowForceRollout.target, "Force", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowForceRollout.faded)) - { - EditorGUILayout.PropertyField(m_Speed); - EditorGUILayout.PropertyField(m_SpeedVariation); - EditorGUILayout.PropertyField(m_ForceScale); - EditorGUILayout.Space(); - } - EditorGUILayout.EndFadeGroup(); - - // Options. - m_ShowOptionsRollout.target = EditorGUILayout.Foldout(m_ShowOptionsRollout.target, "Options", true); - if (EditorGUILayout.BeginFadeGroup(m_ShowOptionsRollout.faded)) - { - EditorGUILayout.PropertyField(m_UseContactForce); - EditorGUILayout.PropertyField(m_UseFriction); - EditorGUILayout.PropertyField(m_UseBounce); - } - EditorGUILayout.EndFadeGroup(); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/TabbedEditor.cs b/Editor/Mono/Inspector/TabbedEditor.cs deleted file mode 100644 index 8a29df03f1..0000000000 --- a/Editor/Mono/Inspector/TabbedEditor.cs +++ /dev/null @@ -1,200 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Experimental.AssetImporters; -using UnityEngine; - -namespace UnityEditor -{ - // Version for editors not derived from AssetImporterEditor - internal abstract class TabbedEditor : Editor - { - protected System.Type[] m_SubEditorTypes = null; - protected string[] m_SubEditorNames = null; - private int m_ActiveEditorIndex = 0; - private Editor m_ActiveEditor; - public Editor activeEditor { get { return m_ActiveEditor; } } - - internal virtual void OnEnable() - { - m_ActiveEditorIndex = EditorPrefs.GetInt(GetType().Name + "ActiveEditorIndex", 0); - if (m_ActiveEditor == null) - m_ActiveEditor = CreateEditor(targets, m_SubEditorTypes[m_ActiveEditorIndex]); - } - - void OnDestroy() - { - DestroyImmediate(activeEditor); - } - - public override void OnInspectorGUI() - { - using (new GUILayout.HorizontalScope()) - { - GUILayout.FlexibleSpace(); - using (var check = new EditorGUI.ChangeCheckScope()) - { - m_ActiveEditorIndex = GUILayout.Toolbar(m_ActiveEditorIndex, m_SubEditorNames, "LargeButton", GUI.ToolbarButtonSize.FitToContents); - if (check.changed) - { - EditorPrefs.SetInt(GetType().Name + "ActiveEditorIndex", m_ActiveEditorIndex); - var oldEditor = activeEditor; - m_ActiveEditor = null; - DestroyImmediate(oldEditor); - m_ActiveEditor = CreateEditor(targets, m_SubEditorTypes[m_ActiveEditorIndex]); - } - } - GUILayout.FlexibleSpace(); - } - - activeEditor.OnInspectorGUI(); - } - - public override void OnPreviewSettings() - { - activeEditor.OnPreviewSettings(); - } - - public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - activeEditor.OnInteractivePreviewGUI(r, background); - } - - public override bool HasPreviewGUI() - { - return activeEditor.HasPreviewGUI(); - } - } - - // Version for AssetImporterInspector derived editors - internal abstract class AssetImporterTabbedEditor : AssetImporterEditor - { - protected string[] m_TabNames = null; - private int m_ActiveEditorIndex = 0; - - /// - /// The list of child inspectors. - /// - private BaseAssetImporterTabUI[] m_Tabs = null; - public BaseAssetImporterTabUI activeTab { get; private set; } - protected BaseAssetImporterTabUI[] tabs { get { return m_Tabs; } set { m_Tabs = value; } } - - public override void OnEnable() - { - foreach (var tab in m_Tabs) - { - tab.OnEnable(); - } - - m_ActiveEditorIndex = EditorPrefs.GetInt(this.GetType().Name + "ActiveEditorIndex", 0); - if (activeTab == null) - activeTab = m_Tabs[m_ActiveEditorIndex]; - } - - void OnDestroy() - { - if (m_Tabs != null) - { - foreach (var tab in m_Tabs) - { - tab.OnDestroy(); - } - - // destroy all the child tabs - m_Tabs = null; - activeTab = null; - } - } - - protected override void ResetValues() - { - base.ResetValues(); - - if (m_Tabs != null) - { - foreach (var tab in m_Tabs) - { - tab.ResetValues(); - } - } - } - - public override void OnInspectorGUI() - { - // Always allow user to switch between tabs even when the editor is disabled, so they can look at all parts - // of read-only assets - using (new EditorGUI.DisabledScope(false)) // this doesn't enable the UI, but it seems correct to push the stack - { - GUI.enabled = true; - using (new GUILayout.HorizontalScope()) - { - GUILayout.FlexibleSpace(); - using (var check = new EditorGUI.ChangeCheckScope()) - { - m_ActiveEditorIndex = GUILayout.Toolbar(m_ActiveEditorIndex, m_TabNames, "LargeButton", GUI.ToolbarButtonSize.FitToContents); - if (check.changed) - { - EditorPrefs.SetInt(GetType().Name + "ActiveEditorIndex", m_ActiveEditorIndex); - activeTab = m_Tabs[m_ActiveEditorIndex]; - - activeTab.OnInspectorGUI(); - } - } - GUILayout.FlexibleSpace(); - } - } - - // the activeTab can get destroyed when opening particular sub-editors (such as the Avatar configuration editor on the Rig tab) - if (activeTab != null) - { - activeTab.OnInspectorGUI(); - } - - // show a single Apply/Revert set of buttons for all the tabs - ApplyRevertGUI(); - } - - public override void OnPreviewSettings() - { - if (activeTab != null) - { - activeTab.OnPreviewSettings(); - } - } - - public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) - { - if (activeTab != null) - { - activeTab.OnInteractivePreviewGUI(r, background); - } - } - - public override bool HasPreviewGUI() - { - if (activeTab == null) - return false; - return activeTab.HasPreviewGUI(); - } - - protected override void Apply() - { - if (m_Tabs != null) - { - // tabs can do work before or after the application of changes in the serialization object - foreach (var tab in m_Tabs) - { - tab.PreApply(); - } - - base.Apply(); - - foreach (var tab in m_Tabs) - { - tab.PostApply(); - } - } - } - } -} diff --git a/Editor/Mono/Inspector/TagManagerInspector.cs b/Editor/Mono/Inspector/TagManagerInspector.cs deleted file mode 100644 index bb14478bcd..0000000000 --- a/Editor/Mono/Inspector/TagManagerInspector.cs +++ /dev/null @@ -1,341 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - [CustomEditor(typeof(TagManager))] - internal class TagManagerInspector : ProjectSettingsBaseEditor - { - protected SerializedProperty m_Tags; - protected SerializedProperty m_SortingLayers; - protected SerializedProperty m_Layers; - ReorderableList m_TagsList; - ReorderableList m_SortLayersList; - ReorderableList m_LayersList; - - protected bool m_IsEditable = false; - - private bool m_HaveRemovedTag = false; - - private static InitialExpansionState s_InitialExpansionState = InitialExpansionState.None; - internal enum InitialExpansionState - { - None = 0, - Tags = 1, - Layers = 2, - SortingLayers = 3 - } - - public TagManager tagManager - { - get { return target as TagManager; } - } - - public virtual void OnEnable() - { - // Tags. - m_Tags = serializedObject.FindProperty("tags"); - - CheckForRemovedTags(); - - if (m_TagsList == null) - { - m_TagsList = new ReorderableList(serializedObject, m_Tags, false, false, true, true); - m_TagsList.onAddDropdownCallback = NewElement; - m_TagsList.onRemoveCallback = RemoveFromTagsList; - m_TagsList.drawElementCallback = DrawTagListElement; - m_TagsList.elementHeight = EditorGUIUtility.singleLineHeight + 2; - m_TagsList.headerHeight = 3; - } - - // Sorting layers. - m_SortingLayers = serializedObject.FindProperty("m_SortingLayers"); - if (m_SortLayersList == null) - { - m_SortLayersList = new ReorderableList(serializedObject, m_SortingLayers, true, false, true, true); - m_SortLayersList.onReorderCallback = ReorderSortLayerList; - m_SortLayersList.onAddCallback = AddToSortLayerList; - m_SortLayersList.onRemoveCallback = RemoveFromSortLayerList; - m_SortLayersList.onCanRemoveCallback = CanRemoveSortLayerEntry; - m_SortLayersList.drawElementCallback = DrawSortLayerListElement; - m_SortLayersList.elementHeight = EditorGUIUtility.singleLineHeight + 2; - m_SortLayersList.headerHeight = 3; - } - // Layers. - m_Layers = serializedObject.FindProperty("layers"); - System.Diagnostics.Debug.Assert(m_Layers.arraySize == 32); - if (m_LayersList == null) - { - m_LayersList = new ReorderableList(serializedObject, m_Layers, false, false, false, false); - m_LayersList.drawElementCallback = DrawLayerListElement; - m_LayersList.elementHeight = EditorGUIUtility.singleLineHeight + 2; - m_LayersList.headerHeight = 3; - } - - if (s_InitialExpansionState != InitialExpansionState.None) - { - m_Tags.isExpanded = false; - m_SortingLayers.isExpanded = false; - m_Layers.isExpanded = false; - switch (s_InitialExpansionState) - { - case InitialExpansionState.Tags: - m_Tags.isExpanded = true; - break; - case InitialExpansionState.Layers: - m_Layers.isExpanded = true; - break; - case InitialExpansionState.SortingLayers: - m_SortingLayers.isExpanded = true; - break; - } - s_InitialExpansionState = InitialExpansionState.None; - } - } - - internal static void ShowWithInitialExpansion(InitialExpansionState initialExpansionState) - { - s_InitialExpansionState = initialExpansionState; - Selection.activeObject = EditorApplication.tagManager; - } - - private void CheckForRemovedTags() - { - for (int i = 0; i < m_Tags.arraySize; i++) - { - if (string.IsNullOrEmpty(m_Tags.GetArrayElementAtIndex(i).stringValue)) - m_HaveRemovedTag = true; - } - } - - class EnterNamePopup : PopupWindowContent - { - public delegate void EnterDelegate(string str); - readonly EnterDelegate EnterCB; - private string m_NewTagName = "New tag"; - private bool m_NeedsFocus = true; - - public EnterNamePopup(SerializedProperty tags, EnterDelegate cb) - { - EnterCB = cb; - - - List existingTagNames = new List(); - for (int i = 0; i < tags.arraySize; i++) - { - string tagName = tags.GetArrayElementAtIndex(i).stringValue; - if (!string.IsNullOrEmpty(tagName)) - existingTagNames.Add(tagName); - } - m_NewTagName = ObjectNames.GetUniqueName(existingTagNames.ToArray(), m_NewTagName); - } - - public override Vector2 GetWindowSize() - { - return new Vector2(400, EditorGUI.kSingleLineHeight * 2 + EditorGUI.kControlVerticalSpacing + 14); - } - - public override void OnGUI(Rect windowRect) - { - GUILayout.Space(5); - Event evt = Event.current; - bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter); - GUI.SetNextControlName("TagName"); - m_NewTagName = EditorGUILayout.TextField("New Tag Name", m_NewTagName); - - if (m_NeedsFocus) - { - m_NeedsFocus = false; - EditorGUI.FocusTextInControl("TagName"); - } - - GUI.enabled = m_NewTagName.Length != 0; - if (GUILayout.Button("Save") || hitEnter) - { - EnterCB(m_NewTagName); - editorWindow.Close(); - } - } - } - - void NewElement(Rect buttonRect, ReorderableList list) - { - buttonRect.x -= 400; - buttonRect.y -= 13; - PopupWindow.Show(buttonRect, new EnterNamePopup(m_Tags, s => { InternalEditorUtility.AddTag(s); }), null, ShowMode.PopupMenuWithKeyboardFocus); - } - - private void RemoveFromTagsList(ReorderableList list) - { - SerializedProperty tag = m_Tags.GetArrayElementAtIndex(list.index); - if (tag.stringValue == "") return; - GameObject go = GameObject.FindWithTag(tag.stringValue); - if (go != null) - { - EditorUtility.DisplayDialog("Error", "Can't remove this tag because it is being used by " + go.name, "OK"); - } - else - { - InternalEditorUtility.RemoveTag(tag.stringValue); - m_HaveRemovedTag = true; - } - } - - private void DrawTagListElement(Rect rect, int index, bool selected, bool focused) - { - rect.height -= 2; // nicer looking with selected list row and a text field in it - - // De-indent by the drag handle width, so the text field lines up with others in the inspector. - // Will have space in front of label for more space between it and the drag handle. - rect.xMin -= ReorderableList.Defaults.dragHandleWidth; - - string oldName = m_Tags.GetArrayElementAtIndex(index).stringValue; - if (string.IsNullOrEmpty(oldName)) - oldName = "(Removed)"; - EditorGUI.LabelField(rect, " Tag " + index, oldName); - } - - void AddToSortLayerList(ReorderableList list) - { - serializedObject.ApplyModifiedProperties(); - InternalEditorUtility.AddSortingLayer(); - serializedObject.Update(); - list.index = list.serializedProperty.arraySize - 1; // select just added one - } - - public void ReorderSortLayerList(ReorderableList list) - { - InternalEditorUtility.UpdateSortingLayersOrder(); - } - - private void RemoveFromSortLayerList(ReorderableList list) - { - ReorderableList.defaultBehaviours.DoRemoveButton(list); - serializedObject.ApplyModifiedProperties(); - serializedObject.Update(); - InternalEditorUtility.UpdateSortingLayersOrder(); - } - - private bool CanEditSortLayerEntry(int index) - { - if (index < 0 || index >= InternalEditorUtility.GetSortingLayerCount()) - return false; - return !InternalEditorUtility.IsSortingLayerDefault(index); - } - - private bool CanRemoveSortLayerEntry(ReorderableList list) - { - return CanEditSortLayerEntry(list.index); - } - - private void DrawSortLayerListElement(Rect rect, int index, bool selected, bool focused) - { - rect.height -= 2; // nicer looking with selected list row and a text field in it - - // De-indent by the drag handle width, so the text field lines up with others in the inspector. - // Will have space in front of label for more space between it and the drag handle. - rect.xMin -= ReorderableList.Defaults.dragHandleWidth; - - bool oldEnabled = GUI.enabled; - GUI.enabled = m_IsEditable && CanEditSortLayerEntry(index); - - string oldName = InternalEditorUtility.GetSortingLayerName(index); - string newName = EditorGUI.TextField(rect, " Layer ", oldName); - if (newName != oldName) - { - serializedObject.ApplyModifiedProperties(); - InternalEditorUtility.SetSortingLayerName(index, newName); - serializedObject.Update(); - } - - GUI.enabled = oldEnabled; - } - - private void DrawLayerListElement(Rect rect, int index, bool selected, bool focused) - { - rect.height -= 2; // nicer looking with selected list row and a text field in it - - // De-indent by the drag handle width, so the text field lines up with others in the inspector. - // Will have space in front of label for more space between it and the drag handle. - rect.xMin -= ReorderableList.Defaults.dragHandleWidth; - - bool isUserLayer = index >= 8; - - bool oldEnabled = GUI.enabled; - GUI.enabled = m_IsEditable && isUserLayer; - - string oldName = m_Layers.GetArrayElementAtIndex(index).stringValue; - string newName; - if (isUserLayer) - { - newName = EditorGUI.TextField(rect, " User Layer " + index, oldName); - } - else - { - newName = EditorGUI.TextField(rect, " Builtin Layer " + index, oldName); - } - - if (newName != oldName) - { - m_Layers.GetArrayElementAtIndex(index).stringValue = newName; - } - - GUI.enabled = oldEnabled; - } - - // Want something better than "TagManager" - internal override string targetTitle - { - get { return "Tags & Layers"; } - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - m_IsEditable = AssetDatabase.IsOpenForEdit("ProjectSettings/TagManager.asset", StatusQueryOptions.UseCachedIfPossible); - - bool oldEnabled = GUI.enabled; - GUI.enabled = m_IsEditable; - - // Tags - m_Tags.isExpanded = EditorGUILayout.Foldout(m_Tags.isExpanded, "Tags", true); - if (m_Tags.isExpanded) - { - EditorGUI.indentLevel++; - m_TagsList.DoLayoutList(); - EditorGUI.indentLevel--; - if (m_HaveRemovedTag) - EditorGUILayout.HelpBox("There are removed tags. They will be removed from this list the next time the project is loaded.", MessageType.Info, true); - } - - // Sorting layers - m_SortingLayers.isExpanded = EditorGUILayout.Foldout(m_SortingLayers.isExpanded, "Sorting Layers", true); - if (m_SortingLayers.isExpanded) - { - EditorGUI.indentLevel++; - m_SortLayersList.DoLayoutList(); - EditorGUI.indentLevel--; - } - - // Layers - m_Layers.isExpanded = EditorGUILayout.Foldout(m_Layers.isExpanded, "Layers", true); - if (m_Layers.isExpanded) - { - EditorGUI.indentLevel++; - m_LayersList.DoLayoutList(); - EditorGUI.indentLevel--; - } - - GUI.enabled = oldEnabled; - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/TargetJoint2DEditor.cs b/Editor/Mono/Inspector/TargetJoint2DEditor.cs deleted file mode 100644 index 3872d74017..0000000000 --- a/Editor/Mono/Inspector/TargetJoint2DEditor.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(TargetJoint2D))] - [CanEditMultipleObjects] - internal class TargetJoint2DEditor : Joint2DEditor - { - public void OnSceneGUI() - { - var targetJoint2D = (TargetJoint2D)target; - - // Ignore disabled joint. - if (!targetJoint2D.enabled) - return; - - // Fetch the anchor/target. - var jointAnchor = TransformPoint(targetJoint2D.transform, targetJoint2D.anchor); - var jointTarget = (Vector3)targetJoint2D.target; - - // Draw a line between the bodies. - Handles.color = Color.green; - Handles.DrawDottedLine(jointAnchor, jointTarget, 5.0f); - - // Draw the anchor point. - if (HandleAnchor(ref jointAnchor, false)) - { - Undo.RecordObject(targetJoint2D, "Move Anchor"); - targetJoint2D.anchor = InverseTransformPoint(targetJoint2D.transform, jointAnchor); - } - - // Draw the target point. - var targetScale = HandleUtility.GetHandleSize(jointTarget) * 0.3f; - var horzTarget = Vector3.left * targetScale; - var vertTarget = Vector3.up * targetScale; - DrawAALine(jointTarget - horzTarget, jointTarget + horzTarget); - DrawAALine(jointTarget - vertTarget, jointTarget + vertTarget); - if (HandleAnchor(ref jointTarget, true)) - { - Undo.RecordObject(targetJoint2D, "Move Target"); - targetJoint2D.target = jointTarget; - } - } - } -} diff --git a/Editor/Mono/Inspector/TerrainColliderEditor.cs b/Editor/Mono/Inspector/TerrainColliderEditor.cs deleted file mode 100644 index 5dfcd77277..0000000000 --- a/Editor/Mono/Inspector/TerrainColliderEditor.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(TerrainCollider))] - [CanEditMultipleObjects] - internal class TerrainColliderEditor : Collider3DEditorBase - { - SerializedProperty m_TerrainData; - SerializedProperty m_EnableTreeColliders; - - protected GUIContent terrainContent = EditorGUIUtility.TrTextContent("Terrain Data", "The TerrainData asset that stores heightmaps, terrain textures, detail meshes and trees."); - protected GUIContent treeColliderContent = EditorGUIUtility.TrTextContent("Enable Tree Colliders", "When selected, Tree Colliders will be enabled."); - - public override void OnEnable() - { - base.OnEnable(); - - m_TerrainData = serializedObject.FindProperty("m_TerrainData"); - m_EnableTreeColliders = serializedObject.FindProperty("m_EnableTreeColliders"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_Material, materialContent); - EditorGUILayout.PropertyField(m_TerrainData, terrainContent); - EditorGUILayout.PropertyField(m_EnableTreeColliders, treeColliderContent); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/TextMeshInspector.cs b/Editor/Mono/Inspector/TextMeshInspector.cs deleted file mode 100644 index d7d2fcf7c0..0000000000 --- a/Editor/Mono/Inspector/TextMeshInspector.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - - -namespace UnityEditor -{ - [CustomEditor(typeof(TextMesh))] - [CanEditMultipleObjects] - internal class TextMeshInspector : Editor - { - SerializedProperty m_Font; - - void OnEnable() - { - m_Font = serializedObject.FindProperty("m_Font"); - } - - public override void OnInspectorGUI() - { - Font oldFont = m_Font.hasMultipleDifferentValues ? null : (m_Font.objectReferenceValue as Font); - DrawDefaultInspector(); - Font newFont = m_Font.hasMultipleDifferentValues ? null : (m_Font.objectReferenceValue as Font); - if (newFont != null && newFont != oldFont) - { - foreach (TextMesh textMesh in targets) - { - var renderer = textMesh.GetComponent(); - if (renderer) - renderer.sharedMaterial = newFont.material; - } - } - } - } -} diff --git a/Editor/Mono/Inspector/Texture3DInspector.cs b/Editor/Mono/Inspector/Texture3DInspector.cs deleted file mode 100644 index a532b3a179..0000000000 --- a/Editor/Mono/Inspector/Texture3DInspector.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - - -namespace UnityEditor -{ - [CustomEditor(typeof(Texture3D))] - [CanEditMultipleObjects] - internal class Texture3DInspector : TextureInspector - { - private PreviewRenderUtility m_PreviewUtility; - private Material m_Material; - private Mesh m_Mesh; - public Vector2 m_PreviewDir = new Vector2(0, 0); - - public override void OnInspectorGUI() - { - base.OnInspectorGUI(); - } - - public override string GetInfoString() - { - Texture3D tex = target as Texture3D; - - string info = string.Format("{0}x{1}x{2} {3} {4}", - tex.width, tex.height, tex.depth, - TextureUtil.GetTextureFormatString(tex.format), - EditorUtility.FormatBytes(TextureUtil.GetRuntimeMemorySizeLong(tex))); - - return info; - } - - protected override void OnDisable() - { - base.OnDisable(); - if (m_PreviewUtility != null) - { - m_PreviewUtility.Cleanup(); - m_PreviewUtility = null; - } - } - - public override void OnPreviewSettings() - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture || !SystemInfo.supports3DTextures) - return; - GUI.enabled = true; - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture || !SystemInfo.supports3DTextures) - { - if (Event.current.type == EventType.Repaint) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 40), "3D texture preview not supported"); - return; - } - - m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, r); - - if (Event.current.type != EventType.Repaint) - return; - - InitPreview(); - m_Material.mainTexture = target as Texture; - - m_PreviewUtility.BeginPreview(r, background); - bool oldFog = RenderSettings.fog; - Unsupported.SetRenderSettingsUseFogNoDirty(false); - - m_PreviewUtility.camera.transform.position = -Vector3.forward * 3.0f; - m_PreviewUtility.camera.transform.rotation = Quaternion.identity; - Quaternion rot = Quaternion.Euler(m_PreviewDir.y, 0, 0) * Quaternion.Euler(0, m_PreviewDir.x, 0); - m_PreviewUtility.DrawMesh(m_Mesh, Vector3.zero, rot, m_Material, 0); - m_PreviewUtility.Render(); - - Unsupported.SetRenderSettingsUseFogNoDirty(oldFog); - m_PreviewUtility.EndAndDrawPreview(r); - } - - void InitPreview() - { - if (m_PreviewUtility == null) - { - m_PreviewUtility = new PreviewRenderUtility(); - m_PreviewUtility.camera.fieldOfView = 30.0f; - } - - if (m_Mesh == null) - { - m_Mesh = PreviewRenderUtility.GetPreviewSphere(); - } - if (m_Material == null) - { - m_Material = EditorGUIUtility.LoadRequired("Previews/Preview3DTextureMaterial.mat") as Material; - } - } - } -} diff --git a/Editor/Mono/Inspector/TextureInspector.cs b/Editor/Mono/Inspector/TextureInspector.cs deleted file mode 100644 index 1dcf82cf5e..0000000000 --- a/Editor/Mono/Inspector/TextureInspector.cs +++ /dev/null @@ -1,804 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - - -namespace UnityEditor -{ - internal class PreviewHelpers - { - //This assumes NPOT RenderTextures since Unity 4.3 has this as a requirment already. - internal static void AdjustWidthAndHeightForStaticPreview(int textureWidth, int textureHeight, ref int width, ref int height) - { - int orgWidth = width; - int orgHeight = height; - - if (textureWidth <= width && textureHeight <= height) - { - // For textures smaller than our wanted width and height we use the textures size - // to prevent excessive magnification artifacts (as seen in the Asset Store). - width = textureWidth; - height = textureHeight; - } - else - { - // For textures larger than our wanted width and height we ensure to - // keep aspect ratio of the texture and fit it to best match our wanted width and height. - float relWidth = height / (float)textureWidth; - float relHeight = width / (float)textureHeight; - - float scale = Mathf.Min(relHeight, relWidth); - - width = Mathf.RoundToInt(textureWidth * scale); - height = Mathf.RoundToInt(textureHeight * scale); - } - - // Ensure we have not scaled size below 2 pixels - width = Mathf.Clamp(width, 2, orgWidth); - height = Mathf.Clamp(height, 2, orgHeight); - } - } - - [CustomEditor(typeof(Texture2D))] - [CanEditMultipleObjects] - internal class TextureInspector : Editor - { - class Styles - { - public GUIContent smallZoom, largeZoom, alphaIcon, RGBIcon; - public GUIStyle previewButton, previewSlider, previewSliderThumb, previewLabel; - - public readonly GUIContent wrapModeLabel = EditorGUIUtility.TrTextContent("Wrap Mode"); - public readonly GUIContent wrapU = EditorGUIUtility.TrTextContent("U axis"); - public readonly GUIContent wrapV = EditorGUIUtility.TrTextContent("V axis"); - public readonly GUIContent wrapW = EditorGUIUtility.TrTextContent("W axis"); - - public readonly GUIContent[] wrapModeContents = - { - EditorGUIUtility.TrTextContent("Repeat"), - EditorGUIUtility.TrTextContent("Clamp"), - EditorGUIUtility.TrTextContent("Mirror"), - EditorGUIUtility.TrTextContent("Mirror Once"), - EditorGUIUtility.TrTextContent("Per-axis") - }; - public readonly int[] wrapModeValues = - { - (int)TextureWrapMode.Repeat, - (int)TextureWrapMode.Clamp, - (int)TextureWrapMode.Mirror, - (int)TextureWrapMode.MirrorOnce, - -1 - }; - - public Styles() - { - smallZoom = EditorGUIUtility.IconContent("PreTextureMipMapLow"); - largeZoom = EditorGUIUtility.IconContent("PreTextureMipMapHigh"); - alphaIcon = EditorGUIUtility.IconContent("PreTextureAlpha"); - RGBIcon = EditorGUIUtility.IconContent("PreTextureRGB"); - previewButton = "preButton"; - previewSlider = "preSlider"; - previewSliderThumb = "preSliderThumb"; - previewLabel = new GUIStyle("preLabel"); - previewLabel.alignment = TextAnchor.UpperCenter; // UpperCenter centers the mip icons vertically better than MiddleCenter - } - } - static Styles s_Styles; - - private bool m_ShowAlpha; - - // Plain Texture - protected SerializedProperty m_WrapU; - protected SerializedProperty m_WrapV; - protected SerializedProperty m_WrapW; - protected SerializedProperty m_FilterMode; - protected SerializedProperty m_Aniso; - - [SerializeField] - protected Vector2 m_Pos; - - [SerializeField] - float m_MipLevel = 0; - - CubemapPreview m_CubemapPreview = new CubemapPreview(); - - public static bool IsNormalMap(Texture t) - { - TextureUsageMode mode = TextureUtil.GetUsageMode(t); - return mode == TextureUsageMode.NormalmapPlain || mode == TextureUsageMode.NormalmapDXT5nm; - } - - protected virtual void OnEnable() - { - m_WrapU = serializedObject.FindProperty("m_TextureSettings.m_WrapU"); - m_WrapV = serializedObject.FindProperty("m_TextureSettings.m_WrapV"); - m_WrapW = serializedObject.FindProperty("m_TextureSettings.m_WrapW"); - m_FilterMode = serializedObject.FindProperty("m_TextureSettings.m_FilterMode"); - m_Aniso = serializedObject.FindProperty("m_TextureSettings.m_Aniso"); - } - - protected virtual void OnDisable() - { - m_CubemapPreview.OnDisable(); - } - - internal void SetCubemapIntensity(float intensity) - { - if (m_CubemapPreview != null) - m_CubemapPreview.SetIntensity(intensity); - } - - public float GetMipLevelForRendering() - { - if (target == null) - return 0.0f; - - if (IsCubemap()) - return m_CubemapPreview.GetMipLevelForRendering(target as Texture); - else - return Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(target as Texture) - 1); - } - - public float mipLevel - { - get - { - if (IsCubemap()) - return m_CubemapPreview.mipLevel; - else - return m_MipLevel; - } - set - { - m_CubemapPreview.mipLevel = value; - m_MipLevel = value; - } - } - - // Note: Even though this is a custom editor for Texture2D, the target may not be a Texture2D, - // since other editors inherit from this one, such as ProceduralTextureInspector. - public override void OnInspectorGUI() - { - serializedObject.Update(); - - DoWrapModePopup(); - DoFilterModePopup(); - DoAnisoLevelSlider(); - - serializedObject.ApplyModifiedProperties(); - } - - static void WrapModeAxisPopup(GUIContent label, SerializedProperty wrapProperty) - { - // In texture importer settings, serialized properties for wrap modes can contain -1, which means "use default". - var wrap = (TextureWrapMode)Mathf.Max(wrapProperty.intValue, 0); - Rect rect = EditorGUILayout.GetControlRect(); - EditorGUI.BeginChangeCheck(); - EditorGUI.BeginProperty(rect, label, wrapProperty); - wrap = (TextureWrapMode)EditorGUI.EnumPopup(rect, label, wrap); - EditorGUI.EndProperty(); - if (EditorGUI.EndChangeCheck()) - { - wrapProperty.intValue = (int)wrap; - } - } - - private static bool IsAnyTextureObjectUsingPerAxisWrapMode(Object[] objects, bool isVolumeTexture) - { - foreach (var o in objects) - { - int u = 0, v = 0, w = 0; - // the objects can be Textures themselves, or texture-related importers - if (o is Texture) - { - var ti = (Texture)o; - u = (int)ti.wrapModeU; - v = (int)ti.wrapModeV; - w = (int)ti.wrapModeW; - } - if (o is TextureImporter) - { - var ti = (TextureImporter)o; - u = (int)ti.wrapModeU; - v = (int)ti.wrapModeV; - w = (int)ti.wrapModeW; - } - if (o is IHVImageFormatImporter) - { - var ti = (IHVImageFormatImporter)o; - u = (int)ti.wrapModeU; - v = (int)ti.wrapModeV; - w = (int)ti.wrapModeW; - } - u = Mathf.Max(0, u); - v = Mathf.Max(0, v); - w = Mathf.Max(0, w); - if (u != v) - { - return true; - } - if (isVolumeTexture) - { - if (u != w || v != w) - { - return true; - } - } - } - return false; - } - - // showPerAxisWrapModes is state of whether "Per-Axis" mode should be active in the main dropdown. - // It is set automatically if wrap modes in UVW are different, or if user explicitly picks "Per-Axis" option -- when that one is picked, - // then it should stay true even if UVW wrap modes will initially be the same. - // - // Note: W wrapping mode is only shown when isVolumeTexture is true. - internal static void WrapModePopup(SerializedProperty wrapU, SerializedProperty wrapV, SerializedProperty wrapW, bool isVolumeTexture, ref bool showPerAxisWrapModes) - { - if (s_Styles == null) - s_Styles = new Styles(); - - // In texture importer settings, serialized properties for things like wrap modes can contain -1; - // that seems to indicate "use defaults, user has not changed them to anything" but not totally sure. - // Show them as Repeat wrap modes in the popups. - var wu = (TextureWrapMode)Mathf.Max(wrapU.intValue, 0); - var wv = (TextureWrapMode)Mathf.Max(wrapV.intValue, 0); - var ww = (TextureWrapMode)Mathf.Max(wrapW.intValue, 0); - - // automatically go into per-axis mode if values are already different - if (wu != wv) showPerAxisWrapModes = true; - if (isVolumeTexture) - { - if (wu != ww || wv != ww) showPerAxisWrapModes = true; - } - - // It's not possible to determine whether any single texture in the whole selection is using per-axis wrap modes - // just from SerializedProperty values. They can only tell if "some values in whole selection are different" (e.g. - // wrap value on U axis is not the same among all textures), and can return value of "some" object in the selection - // (typically based on object loading order). So in order for more intuitive behavior with multi-selection, - // we go over the actual objects when there's >1 object selected and some wrap modes are different. - if (!showPerAxisWrapModes) - { - if (wrapU.hasMultipleDifferentValues || wrapV.hasMultipleDifferentValues || (isVolumeTexture && wrapW.hasMultipleDifferentValues)) - { - if (IsAnyTextureObjectUsingPerAxisWrapMode(wrapU.serializedObject.targetObjects, isVolumeTexture)) - { - showPerAxisWrapModes = true; - } - } - } - - int value = showPerAxisWrapModes ? -1 : (int)wu; - - // main wrap mode popup - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = !showPerAxisWrapModes && (wrapU.hasMultipleDifferentValues || wrapV.hasMultipleDifferentValues || (isVolumeTexture && wrapW.hasMultipleDifferentValues)); - value = EditorGUILayout.IntPopup(s_Styles.wrapModeLabel, value, s_Styles.wrapModeContents, s_Styles.wrapModeValues); - if (EditorGUI.EndChangeCheck() && value != -1) - { - // assign the same wrap mode to all axes, and hide per-axis popups - wrapU.intValue = value; - wrapV.intValue = value; - wrapW.intValue = value; - showPerAxisWrapModes = false; - } - - // show per-axis popups if needed - if (value == -1) - { - showPerAxisWrapModes = true; - EditorGUI.indentLevel++; - WrapModeAxisPopup(s_Styles.wrapU, wrapU); - WrapModeAxisPopup(s_Styles.wrapV, wrapV); - if (isVolumeTexture) - { - WrapModeAxisPopup(s_Styles.wrapW, wrapW); - } - EditorGUI.indentLevel--; - } - EditorGUI.showMixedValue = false; - } - - bool m_ShowPerAxisWrapModes = false; - protected void DoWrapModePopup() - { - WrapModePopup(m_WrapU, m_WrapV, m_WrapW, IsVolume(), ref m_ShowPerAxisWrapModes); - } - - protected void DoFilterModePopup() - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_FilterMode.hasMultipleDifferentValues; - FilterMode filter = (FilterMode)m_FilterMode.intValue; - filter = (FilterMode)EditorGUILayout.EnumPopup(EditorGUIUtility.TempContent("Filter Mode"), filter); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - m_FilterMode.intValue = (int)filter; - } - - protected void DoAnisoLevelSlider() - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = m_Aniso.hasMultipleDifferentValues; - int aniso = m_Aniso.intValue; - aniso = EditorGUILayout.IntSlider("Aniso Level", aniso, 0, 16); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - m_Aniso.intValue = aniso; - DoAnisoGlobalSettingNote(aniso); - } - - internal static void DoAnisoGlobalSettingNote(int anisoLevel) - { - if (anisoLevel > 1) - { - if (QualitySettings.anisotropicFiltering == AnisotropicFiltering.Disable) - EditorGUILayout.HelpBox("Anisotropic filtering is disabled for all textures in Quality Settings.", MessageType.Info); - else if (QualitySettings.anisotropicFiltering == AnisotropicFiltering.ForceEnable) - EditorGUILayout.HelpBox("Anisotropic filtering is enabled for all textures in Quality Settings.", MessageType.Info); - } - } - - bool IsCubemap() - { - var t = target as Texture; - return t != null && t.dimension == UnityEngine.Rendering.TextureDimension.Cube; - } - - bool IsVolume() - { - var t = target as Texture; - return t != null && t.dimension == UnityEngine.Rendering.TextureDimension.Tex3D; - } - - public override void OnPreviewSettings() - { - if (IsCubemap()) - { - m_CubemapPreview.OnPreviewSettings(targets); - return; - } - - - if (s_Styles == null) - s_Styles = new Styles(); - - - // TextureInspector code is reused for RenderTexture and Cubemap inspectors. - // Make sure we can handle the situation where target is just a Texture and - // not a Texture2D. It's also used for large popups for mini texture fields, - // and while it's being shown the actual texture object might disappear -- - // make sure to handle null targets. - Texture tex = target as Texture; - bool showMode = true; - bool alphaOnly = false; - bool hasAlpha = true; - int mipCount = 1; - - if (target is Texture2D) - { - alphaOnly = true; - hasAlpha = false; - } - - foreach (Texture t in targets) - { - if (t == null) // texture might have disappeared while we're showing this in a preview popup - continue; - TextureFormat format = 0; - bool checkFormat = false; - if (t is Texture2D) - { - format = (t as Texture2D).format; - checkFormat = true; - } - - if (checkFormat) - { - if (!TextureUtil.IsAlphaOnlyTextureFormat(format)) - alphaOnly = false; - if (TextureUtil.HasAlphaTextureFormat(format)) - { - TextureUsageMode mode = TextureUtil.GetUsageMode(t); - if (mode == TextureUsageMode.Default) // all other texture usage modes don't displayable alpha - hasAlpha = true; - } - } - - mipCount = Mathf.Max(mipCount, TextureUtil.GetMipmapCount(t)); - } - - if (alphaOnly) - { - m_ShowAlpha = true; - showMode = false; - } - else if (!hasAlpha) - { - m_ShowAlpha = false; - showMode = false; - } - - if (showMode && tex != null && !IsNormalMap(tex)) - m_ShowAlpha = GUILayout.Toggle(m_ShowAlpha, m_ShowAlpha ? s_Styles.alphaIcon : s_Styles.RGBIcon, s_Styles.previewButton); - - if (mipCount > 1) - { - GUILayout.Box(s_Styles.smallZoom, s_Styles.previewLabel); - GUI.changed = false; - m_MipLevel = Mathf.Round(GUILayout.HorizontalSlider(m_MipLevel, mipCount - 1, 0, s_Styles.previewSlider, s_Styles.previewSliderThumb, GUILayout.MaxWidth(64))); - GUILayout.Box(s_Styles.largeZoom, s_Styles.previewLabel); - } - } - - public override bool HasPreviewGUI() - { - return (target != null); - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (Event.current.type == EventType.Repaint) - background.Draw(r, false, false, false, false); - - // show texture - Texture t = target as Texture; - if (t == null) // texture might be gone by now, in case this code is used for floating texture preview - return; - - // Render target must be created before we can display it (case 491797) - RenderTexture rt = t as RenderTexture; - if (rt != null) - { - if (!SystemInfo.SupportsRenderTextureFormat(rt.format)) - return; // can't do this RT format - rt.Create(); - } - - if (IsCubemap()) - { - m_CubemapPreview.OnPreviewGUI(t, r, background); - return; - } - - // target can report zero sizes in some cases just after a parameter change; - // guard against that. - int texWidth = Mathf.Max(t.width, 1); - int texHeight = Mathf.Max(t.height, 1); - - float mipLevel = GetMipLevelForRendering(); - float zoomLevel = Mathf.Min(Mathf.Min(r.width / texWidth, r.height / texHeight), 1); - Rect wantedRect = new Rect(r.x, r.y, texWidth * zoomLevel, texHeight * zoomLevel); - PreviewGUI.BeginScrollView(r, m_Pos, wantedRect, "PreHorizontalScrollbar", "PreHorizontalScrollbarThumb"); - FilterMode oldFilter = t.filterMode; - TextureUtil.SetFilterModeNoDirty(t, FilterMode.Point); - - Texture2D t2d = t as Texture2D; - if (m_ShowAlpha) - EditorGUI.DrawTextureAlpha(wantedRect, t, ScaleMode.StretchToFill, 0, mipLevel); - else if (t2d != null && t2d.alphaIsTransparency) - EditorGUI.DrawTextureTransparent(wantedRect, t, ScaleMode.StretchToFill, 0, mipLevel); - else - EditorGUI.DrawPreviewTexture(wantedRect, t, null, ScaleMode.StretchToFill, 0, mipLevel); - - // TODO: Less hacky way to prevent sprite rects to not appear in smaller previews like icons. - if (wantedRect.width > 32 && wantedRect.height > 32) - { - string path = AssetDatabase.GetAssetPath(t); - TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter; - SpriteMetaData[] spritesheet = textureImporter != null ? textureImporter.spritesheet : null; - - if (spritesheet != null && textureImporter.spriteImportMode == SpriteImportMode.Multiple) - { - Rect screenRect = new Rect(); - Rect sourceRect = new Rect(); - GUI.CalculateScaledTextureRects(wantedRect, ScaleMode.StretchToFill, (float)t.width / (float)t.height, ref screenRect, ref sourceRect); - - int origWidth = t.width; - int origHeight = t.height; - textureImporter.GetWidthAndHeight(ref origWidth, ref origHeight); - float definitionScale = (float)t.width / (float)origWidth; - - HandleUtility.ApplyWireMaterial(); - GL.PushMatrix(); - GL.MultMatrix(Handles.matrix); - GL.Begin(GL.LINES); - GL.Color(new Color(1f, 1f, 1f, 0.5f)); - foreach (SpriteMetaData sprite in spritesheet) - { - Rect spriteRect = sprite.rect; - Rect spriteScreenRect = new Rect(); - spriteScreenRect.xMin = screenRect.xMin + screenRect.width * (spriteRect.xMin / t.width * definitionScale); - spriteScreenRect.xMax = screenRect.xMin + screenRect.width * (spriteRect.xMax / t.width * definitionScale); - spriteScreenRect.yMin = screenRect.yMin + screenRect.height * (1f - spriteRect.yMin / t.height * definitionScale); - spriteScreenRect.yMax = screenRect.yMin + screenRect.height * (1f - spriteRect.yMax / t.height * definitionScale); - DrawRect(spriteScreenRect); - } - GL.End(); - GL.PopMatrix(); - } - } - - TextureUtil.SetFilterModeNoDirty(t, oldFilter); - - m_Pos = PreviewGUI.EndScrollView(); - if (mipLevel != 0) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y, r.width, 20), "Mip " + mipLevel); - } - - private void DrawRect(Rect rect) - { - GL.Vertex(new Vector3(rect.xMin, rect.yMin, 0f)); - GL.Vertex(new Vector3(rect.xMax, rect.yMin, 0f)); - GL.Vertex(new Vector3(rect.xMax, rect.yMin, 0f)); - GL.Vertex(new Vector3(rect.xMax, rect.yMax, 0f)); - GL.Vertex(new Vector3(rect.xMax, rect.yMax, 0f)); - GL.Vertex(new Vector3(rect.xMin, rect.yMax, 0f)); - GL.Vertex(new Vector3(rect.xMin, rect.yMax, 0f)); - GL.Vertex(new Vector3(rect.xMin, rect.yMin, 0f)); - } - - public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture) - { - return null; - } - - Texture texture = target as Texture; - - if (IsCubemap()) - { - return m_CubemapPreview.RenderStaticPreview(texture, width, height); - } - - TextureImporter textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter; - if (textureImporter != null && textureImporter.textureType == TextureImporterType.Sprite && textureImporter.spriteImportMode == SpriteImportMode.Polygon) - { - // If the texture importer is a Sprite of primitive, use the sprite inspector for generating preview/icon. - if (subAssets.Length > 0) - { - Sprite sprite = subAssets[0] as Sprite; - if (sprite) - return SpriteInspector.BuildPreviewTexture(width, height, sprite, null, true); - } - else - return null; - } - - PreviewHelpers.AdjustWidthAndHeightForStaticPreview(texture.width, texture.height, ref width, ref height); - - RenderTexture savedRT = RenderTexture.active; - Rect savedViewport = ShaderUtil.rawViewportRect; - - RenderTexture tmp = RenderTexture.GetTemporary( - width, - height, - 0, - RenderTextureFormat.Default, - RenderTextureReadWrite.Linear); - - Graphics.Blit(texture, tmp, EditorGUI.GetMaterialForSpecialTexture(texture, EditorGUIUtility.GUITextureBlit2SRGBMaterial)); - - RenderTexture.active = tmp; - Texture2D copy; - Texture2D tex2d = target as Texture2D; - if (tex2d != null && tex2d.alphaIsTransparency) - { - copy = new Texture2D(width, height, TextureFormat.RGBA32, false); - } - else - { - copy = new Texture2D(width, height, TextureFormat.RGB24, false); - } - copy.ReadPixels(new Rect(0, 0, width, height), 0, 0); - copy.Apply(); - RenderTexture.ReleaseTemporary(tmp); - - EditorGUIUtility.SetRenderTextureNoViewport(savedRT); - ShaderUtil.rawViewportRect = savedViewport; - - return copy; - } - - float Log2(float x) - { - return (float)(System.Math.Log(x) / System.Math.Log(2)); - } - - public override string GetInfoString() - { - // TextureInspector code is reused for RenderTexture and Cubemap inspectors. - // Make sure we can handle the situation where target is just a Texture and - // not a Texture2D. - Texture t = target as Texture; - Texture2D t2 = target as Texture2D; - TextureImporter textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(t)) as TextureImporter; - string info = t.width.ToString() + "x" + t.height.ToString(); - - if (QualitySettings.desiredColorSpace == ColorSpace.Linear) - info += " " + TextureUtil.GetTextureColorSpaceString(t); - - bool showSize = true; - bool isPackedSprite = textureImporter && textureImporter.qualifiesForSpritePacking; - bool isNormalmap = IsNormalMap(t); - bool stillNeedsCompression = TextureUtil.DoesTextureStillNeedToBeCompressed(AssetDatabase.GetAssetPath(t)); - bool isNPOT = t2 != null && TextureUtil.IsNonPowerOfTwo(t2); - TextureFormat format = TextureUtil.GetTextureFormat(t); - - showSize = !stillNeedsCompression; - if (isNPOT) - info += " (NPOT)"; - if (stillNeedsCompression) - info += " (Not yet compressed)"; - else - { - if (isNormalmap) - { - switch (format) - { - case TextureFormat.DXT5: - info += " DXTnm"; - break; - case TextureFormat.RGBA32: - case TextureFormat.ARGB32: - info += " Nm 32 bit"; - break; - case TextureFormat.ARGB4444: - info += " Nm 16 bit"; - break; - default: - info += " " + TextureUtil.GetTextureFormatString(format); - break; - } - } - else if (isPackedSprite) - { - TextureFormat desiredFormat; - ColorSpace dummyColorSpace; - int dummyComressionQuality; - textureImporter.ReadTextureImportInstructions(EditorUserBuildSettings.activeBuildTarget, out desiredFormat, out dummyColorSpace, out dummyComressionQuality); - - info += "\n " + TextureUtil.GetTextureFormatString(format) + "(Original) " + TextureUtil.GetTextureFormatString(desiredFormat) + "(Atlas)"; - } - else - info += " " + TextureUtil.GetTextureFormatString(format); - } - - if (showSize) - info += "\n" + EditorUtility.FormatBytes(TextureUtil.GetStorageMemorySizeLong(t)); - - if (TextureUtil.GetUsageMode(t) == TextureUsageMode.AlwaysPadded) - { - var glWidth = TextureUtil.GetGPUWidth(t); - var glHeight = TextureUtil.GetGPUHeight(t); - if (t.width != glWidth || t.height != glHeight) - info += string.Format("\nPadded to {0}x{1}", glWidth, glHeight); - } - - return info; - } - } -} - - -class PreviewGUI -{ - static int sliderHash = "Slider".GetHashCode(); - static Rect s_ViewRect, s_Position; - static Vector2 s_ScrollPos; - - internal static void BeginScrollView(Rect position, Vector2 scrollPosition, Rect viewRect, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar) - { - s_ScrollPos = scrollPosition; - s_ViewRect = viewRect; - s_Position = position; - 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); - } - - internal class Styles - { - public static GUIStyle preButton; - public static void Init() - { - preButton = "preButton"; - } - } - - public static int CycleButton(int selected, GUIContent[] options) - { - Styles.Init(); - return EditorGUILayout.CycleButton(selected, options, Styles.preButton); - } - - public static Vector2 EndScrollView() - { - GUIClip.Pop(); - - Rect clipRect = s_Position, position = s_Position, viewRect = s_ViewRect; - - Vector2 scrollPosition = s_ScrollPos; - switch (Event.current.type) - { - case EventType.Layout: - GUIUtility.GetControlID(sliderHash, FocusType.Passive); - GUIUtility.GetControlID(sliderHash, FocusType.Passive); - break; - case EventType.Used: - break; - default: - bool needsVerticalScrollbar = ((int)viewRect.width > (int)clipRect.width); - bool needsHorizontalScrollbar = ((int)viewRect.height > (int)clipRect.height); - int id = GUIUtility.GetControlID(sliderHash, FocusType.Passive); - - if (needsHorizontalScrollbar) - { - GUIStyle horizontalScrollbar = "PreHorizontalScrollbar"; - GUIStyle horizontalScrollbarThumb = "PreHorizontalScrollbarThumb"; - float offset = (viewRect.width - clipRect.width) * .5f; - scrollPosition.x = GUI.Slider(new Rect(position.x, position.yMax - horizontalScrollbar.fixedHeight, clipRect.width - (needsVerticalScrollbar ? horizontalScrollbar.fixedHeight : 0) , horizontalScrollbar.fixedHeight), - scrollPosition.x, clipRect.width + offset, -offset, viewRect.width, - horizontalScrollbar, horizontalScrollbarThumb, true, id); - } - else - { - // Get the same number of Control IDs so the ID generation for childrent don't depend on number of things above - scrollPosition.x = 0; - } - - id = GUIUtility.GetControlID(sliderHash, FocusType.Passive); - - if (needsVerticalScrollbar) - { - GUIStyle verticalScrollbar = "PreVerticalScrollbar"; - GUIStyle verticalScrollbarThumb = "PreVerticalScrollbarThumb"; - float offset = (viewRect.height - clipRect.height) * .5f; - scrollPosition.y = GUI.Slider(new Rect(clipRect.xMax - verticalScrollbar.fixedWidth, clipRect.y, verticalScrollbar.fixedWidth, clipRect.height), - scrollPosition.y, clipRect.height + offset, -offset, viewRect.height, - verticalScrollbar, verticalScrollbarThumb, false, id); - } - else - { - scrollPosition.y = 0; - } - break; - } - - return scrollPosition; - } - - public static Vector2 Drag2D(Vector2 scrollPosition, Rect position) - { - int id = GUIUtility.GetControlID(sliderHash, FocusType.Passive); - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (position.Contains(evt.mousePosition) && position.width > 50) - { - GUIUtility.hotControl = id; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - scrollPosition -= evt.delta * (evt.shift ? 3 : 1) / Mathf.Min(position.width, position.height) * 140.0f; - scrollPosition.y = Mathf.Clamp(scrollPosition.y, -90, 90); - evt.Use(); - GUI.changed = true; - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - GUIUtility.hotControl = 0; - EditorGUIUtility.SetWantsMouseJumping(0); - break; - } - return scrollPosition; - } -} diff --git a/Editor/Mono/Inspector/TimeControl.cs b/Editor/Mono/Inspector/TimeControl.cs deleted file mode 100644 index 707cea4774..0000000000 --- a/Editor/Mono/Inspector/TimeControl.cs +++ /dev/null @@ -1,230 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class TimeControl - { - // currentTime will be clamped to preview range. - // Make sure it's initially at the beginning, even if the clip start is negative. - public float currentTime = Mathf.NegativeInfinity; - public float nextCurrentTime - { - set { deltaTime = value - currentTime; m_NextCurrentTimeSet = true; } - } - private bool m_NextCurrentTimeSet = false; - public float startTime = 0.0f; - public float stopTime = 1.0f; - public bool playSelection = false; - public bool loop = true; - public float playbackSpeed = 1.0f; - private float m_DeltaTime = 0.0f; - private bool m_DeltaTimeSet = false; - public float deltaTime - { - get { return m_DeltaTime; } - set { m_DeltaTime = value; m_DeltaTimeSet = true; } - } - public float normalizedTime - { - // Don't use InverseLerp and Lerp since they clamp between 0 and 1 - get { return (stopTime == startTime) ? 0 : ((currentTime - startTime) / (stopTime - startTime)); } - set { currentTime = startTime * (1 - value) + stopTime * value; } - } - public bool playing - { - get { return m_Playing; } - set - { - if (m_Playing != value) - { - // Start Playing - if (value) - { - EditorApplication.update += InspectorWindow.RepaintAllInspectors; - m_LastFrameEditorTime = EditorApplication.timeSinceStartup; - - if (m_ResetOnPlay) - { - nextCurrentTime = startTime; - m_ResetOnPlay = false; - } - } - // Stop Playing - else - { - EditorApplication.update -= InspectorWindow.RepaintAllInspectors; - } - } - - m_Playing = value; - } - } - - private double m_LastFrameEditorTime = 0.0f; - private bool m_Playing = false; - private bool m_ResetOnPlay = false; - private float m_MouseDrag = 0.0f; - private bool m_WrapForwardDrag = false; - - private const float kStepTime = 0.01f; - private const float kScrubberHeight = 21; - private const float kPlayButtonWidth = 33; - - private class Styles - { - public GUIContent playIcon = EditorGUIUtility.IconContent("PlayButton"); - public GUIContent pauseIcon = EditorGUIUtility.IconContent("PauseButton"); - - public GUIStyle playButton = "TimeScrubberButton"; - public GUIStyle timeScrubber = "TimeScrubber"; - } - private static Styles s_Styles; - - private static readonly int kScrubberIDHash = "ScrubberIDHash".GetHashCode(); - public void DoTimeControl(Rect rect) - { - if (s_Styles == null) - s_Styles = new Styles(); - - var evt = Event.current; - int id = EditorGUIUtility.GetControlID(kScrubberIDHash, FocusType.Keyboard); - - // Play/Pause Button + Scrubber - Rect timelineRect = rect; - timelineRect.height = kScrubberHeight; - // Only Scrubber - Rect scrubberRect = timelineRect; - scrubberRect.xMin += kPlayButtonWidth; - - // Handle Input - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (rect.Contains(evt.mousePosition)) - { - EditorGUIUtility.keyboardControl = id; - } - if (scrubberRect.Contains(evt.mousePosition)) - { - EditorGUIUtility.SetWantsMouseJumping(1); - EditorGUIUtility.hotControl = id; - m_MouseDrag = evt.mousePosition.x - scrubberRect.xMin; - nextCurrentTime = (m_MouseDrag * (stopTime - startTime) / scrubberRect.width + startTime); - m_WrapForwardDrag = false; - evt.Use(); - } - break; - case EventType.MouseDrag: - if (EditorGUIUtility.hotControl == id) - { - m_MouseDrag += evt.delta.x * playbackSpeed; - // We want to not wrap if we immediately drag to the beginning, but we do want to wrap if we drag past the end. - if (loop && ((m_MouseDrag < 0.0f && m_WrapForwardDrag) || (m_MouseDrag > scrubberRect.width))) - { - // scrubing out of range was generating a big deltaTime in wrong time direction - // this new code prevent this and it is compliant with new and more robust v5.0 root motion looping of animation clip - if (m_MouseDrag > scrubberRect.width) - { - currentTime -= (stopTime - startTime); - } - else if (m_MouseDrag < 0) - { - currentTime += (stopTime - startTime); - } - - m_WrapForwardDrag = true; - m_MouseDrag = Mathf.Repeat(m_MouseDrag, scrubberRect.width); - } - nextCurrentTime = (Mathf.Clamp(m_MouseDrag, 0.0f, scrubberRect.width) * (stopTime - startTime) / scrubberRect.width + startTime); - evt.Use(); - } - break; - case EventType.MouseUp: - if (EditorGUIUtility.hotControl == id) - { - EditorGUIUtility.SetWantsMouseJumping(0); - EditorGUIUtility.hotControl = 0; - evt.Use(); - } - break; - case EventType.KeyDown: - if (EditorGUIUtility.keyboardControl == id) - { - // TODO: loop? - if (evt.keyCode == KeyCode.LeftArrow) - { - if (currentTime - startTime > kStepTime) - deltaTime = -kStepTime; - evt.Use(); - } - if (evt.keyCode == KeyCode.RightArrow) - { - if (stopTime - currentTime > kStepTime) - deltaTime = kStepTime; - evt.Use(); - } - } - break; - } - - // background - GUI.Box(timelineRect, GUIContent.none, s_Styles.timeScrubber); - - // Play/Pause Button - playing = GUI.Toggle(timelineRect, playing, playing ? s_Styles.pauseIcon : s_Styles.playIcon, s_Styles.playButton); - - // Current time indicator - float normalizedPosition = Mathf.Lerp(scrubberRect.x, scrubberRect.xMax, normalizedTime); - TimeArea.DrawPlayhead(normalizedPosition, scrubberRect.yMin, scrubberRect.yMax, 2f, (EditorGUIUtility.keyboardControl == id) ? 1f : 0.5f); - } - - public void OnDisable() - { - playing = false; - } - - public void Update() - { - // If the deltaTime was not set, update it when playing - if (!m_DeltaTimeSet) - { - if (playing) - { - double timeSinceStartup = EditorApplication.timeSinceStartup; - deltaTime = (float)(timeSinceStartup - m_LastFrameEditorTime) * playbackSpeed; - m_LastFrameEditorTime = timeSinceStartup; - } - else - deltaTime = 0; - } - - - currentTime += deltaTime; - - // If the nextCurrentTime was set explicitly, we don't want to loop - bool wrap = loop && playing && !m_NextCurrentTimeSet; - if (wrap) - { - normalizedTime = Mathf.Repeat(normalizedTime, 1.0f); - } - else - { - if (normalizedTime > 1) - { - playing = false; - m_ResetOnPlay = true; - } - normalizedTime = Mathf.Clamp01(normalizedTime); - } - - m_DeltaTimeSet = false; - m_NextCurrentTimeSet = false; - } - }//class TimeControl -}//namespace UnityEditor diff --git a/Editor/Mono/Inspector/TimeManagerInspector.cs b/Editor/Mono/Inspector/TimeManagerInspector.cs deleted file mode 100644 index e3d7ef81b7..0000000000 --- a/Editor/Mono/Inspector/TimeManagerInspector.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections; - -namespace UnityEditor -{ - [CustomEditor(typeof(TimeManager))] - internal class TimeManagerEditor : Editor - { - SerializedProperty m_FixedTimestepProperty; - SerializedProperty m_MaxAllowedTimestepProperty; - SerializedProperty m_TimeScaleProperty; - SerializedProperty m_MaxParticleTimestepProperty; - - GUIContent m_FixedTimestepLabel; - GUIContent m_MaxAllowedTimestepLabel; - GUIContent m_TimeScaleLabel; - GUIContent m_MaxParticleTimestepLabel; - - public void OnEnable() - { - m_FixedTimestepProperty = serializedObject.FindProperty("Fixed Timestep"); - m_MaxAllowedTimestepProperty = serializedObject.FindProperty("Maximum Allowed Timestep"); - m_TimeScaleProperty = serializedObject.FindProperty("m_TimeScale"); - m_MaxParticleTimestepProperty = serializedObject.FindProperty("Maximum Particle Timestep"); - - m_FixedTimestepLabel = EditorGUIUtility.TrTextContent("Fixed Timestep", "A framerate-independent interval that dictates when physics calculations and FixedUpdate() events are performed."); - m_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."); - m_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."); - m_MaxParticleTimestepLabel = EditorGUIUtility.TrTextContent("Maximum Particle Timestep", "The maximum time that should be allowed to process particles for a frame."); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_FixedTimestepProperty, m_FixedTimestepLabel); - EditorGUILayout.PropertyField(m_MaxAllowedTimestepProperty, m_MaxAllowedTimestepLabel); - EditorGUILayout.PropertyField(m_TimeScaleProperty, m_TimeScaleLabel); - EditorGUILayout.PropertyField(m_MaxParticleTimestepProperty, m_MaxParticleTimestepLabel); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/TimelineControl.cs b/Editor/Mono/Inspector/TimelineControl.cs deleted file mode 100644 index 57cdf19a19..0000000000 --- a/Editor/Mono/Inspector/TimelineControl.cs +++ /dev/null @@ -1,787 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System; - - -namespace UnityEditor -{ - internal class TimelineControl - { - private TimeArea m_TimeArea; - - private float m_Time = Mathf.Infinity; - - private float m_StartTime = 0; - private float m_StopTime = 1; - - private string m_SrcName = "Left"; - private string m_DstName = "Right"; - - private bool m_SrcLoop = false; - private bool m_DstLoop = false; - - private float m_SrcStartTime = 0; - private float m_SrcStopTime = 0.75f; - - private float m_DstStartTime = 0.25f; - private float m_DstStopTime = 1; - - private bool m_HasExitTime = false; - private float m_TransitionStartTime = Mathf.Infinity; - private float m_TransitionStopTime = Mathf.Infinity; - - private float m_SampleStopTime = Mathf.Infinity; - - - private float m_DstDragOffset = 0f; - private float m_LeftThumbOffset = 0f; - private float m_RightThumbOffset = 0f; - - private float m_TimeStartDrag = 0f; - private float m_TimeOffset = 0f; - - private enum DragStates { None, LeftSelection, RightSelection, FullSelection, Destination, Source, Playhead, TimeArea }; - private DragStates m_DragState = DragStates.None; - - private int id = -1; - private Rect m_Rect = new Rect(0, 0, 0, 0); - - private Vector3[] m_SrcPivotVectors; - private Vector3[] m_DstPivotVectors; - - private List m_SrcPivotList = new List(); - private List m_DstPivotList = new List(); - - public List SrcPivotList - { - get { return m_SrcPivotList; } - set { m_SrcPivotList = value; m_SrcPivotVectors = null; } - } - - public List DstPivotList - { - get { return m_DstPivotList; } - set { m_DstPivotList = value; m_DstPivotVectors = null; } - } - - - class Styles - { - public readonly GUIStyle block = new GUIStyle("MeTransitionBlock"); - public GUIStyle leftBlock = new GUIStyle("MeTransitionBlock"); - public GUIStyle rightBlock = new GUIStyle("MeTransitionBlock"); - public GUIStyle timeBlockRight = new GUIStyle("MeTimeLabel"); - public GUIStyle timeBlockLeft = new GUIStyle("MeTimeLabel"); - - public readonly GUIStyle offLeft = new GUIStyle("MeTransOffLeft"); - public readonly GUIStyle offRight = new GUIStyle("MeTransOffRight"); - public readonly GUIStyle onLeft = new GUIStyle("MeTransOnLeft"); - public readonly GUIStyle onRight = new GUIStyle("MeTransOnRight"); - public readonly GUIStyle offOn = new GUIStyle("MeTransOff2On"); - public readonly GUIStyle onOff = new GUIStyle("MeTransOn2Off"); - public readonly GUIStyle background = new GUIStyle("MeTransitionBack"); - public readonly GUIStyle header = new GUIStyle("MeTransitionHead"); - - public readonly GUIStyle handLeft = new GUIStyle("MeTransitionHandleLeft"); - public readonly GUIStyle handRight = new GUIStyle("MeTransitionHandleRight"); - public readonly GUIStyle handLeftPrev = new GUIStyle("MeTransitionHandleLeftPrev"); - - public readonly GUIStyle playhead = new GUIStyle("MeTransPlayhead"); - - public readonly GUIStyle selectHead = new GUIStyle("MeTransitionSelectHead"); - public readonly GUIStyle select = new GUIStyle("MeTransitionSelect"); - - public Styles() - { - timeBlockRight.alignment = TextAnchor.MiddleRight; - timeBlockRight.normal.background = null; - timeBlockLeft.normal.background = null; - } - } - private Styles styles; - - internal class PivotSample - { - public float m_Time; - public float m_Weight; - } - - - public bool srcLoop - { - get { return m_SrcLoop; } - set { m_SrcLoop = value; } - } - - public bool dstLoop - { - get { return m_DstLoop; } - set { m_DstLoop = value; } - } - - - public float Time - { - get { return m_Time; } - set { m_Time = value; } - } - - public float StartTime - { - get { return m_StartTime; } - set { m_StartTime = value; } - } - - public float StopTime - { - get { return m_StopTime; } - set { m_StopTime = value; } - } - - public string SrcName - { - get { return m_SrcName; } - set { m_SrcName = value; } - } - - public string DstName - { - get { return m_DstName; } - set { m_DstName = value; } - } - - public float SrcStartTime - { - get { return m_SrcStartTime; } - set { m_SrcStartTime = value; } - } - - public float SrcStopTime - { - get { return m_SrcStopTime; } - set { m_SrcStopTime = value; } - } - - public float SrcDuration - { - get { return SrcStopTime - SrcStartTime; } - } - - public float DstStartTime - { - get { return m_DstStartTime; } - set { m_DstStartTime = value; } - } - - public float DstStopTime - { - get { return m_DstStopTime; } - set { m_DstStopTime = value; } - } - - public float DstDuration - { - get { return DstStopTime - DstStartTime; } - } - - public float TransitionStartTime - { - get { return m_TransitionStartTime; } - set { m_TransitionStartTime = value; } - } - - public float TransitionStopTime - { - get { return m_TransitionStopTime; } - set { m_TransitionStopTime = value; } - } - - public bool HasExitTime - { - get { return m_HasExitTime; } - set { m_HasExitTime = value; } - } - - public float TransitionDuration - { - get { return TransitionStopTime - TransitionStartTime; } - } - - public float SampleStopTime - { - get { return m_SampleStopTime; } - set { m_SampleStopTime = value; } - } - - - public void ResetRange() - { - m_TimeArea.SetShownHRangeInsideMargins(0, StopTime); - } - - private void Init() - { - if (id == -1) - id = GUIUtility.GetPermanentControlID(); - - if (m_TimeArea == null) - { - m_TimeArea = new TimeArea(false); - m_TimeArea.hRangeLocked = false; - m_TimeArea.vRangeLocked = true; - m_TimeArea.hSlider = false; - m_TimeArea.vSlider = false; - m_TimeArea.margin = 10; - m_TimeArea.scaleWithWindow = true; - m_TimeArea.hTicks.SetTickModulosForFrameRate(30); - } - - if (styles == null) - styles = new Styles(); - } - - public TimelineControl() - { - Init(); - } - - private List GetControls(List segmentPoints, float scale) - { - List controlPoints = new List(); - if (segmentPoints.Count < 2) - return controlPoints; - for (int i = 0; i < segmentPoints.Count; i++) - { - if (i == 0) - { - Vector3 p1 = segmentPoints[i]; - Vector3 p2 = segmentPoints[i + 1]; - Vector3 tangent = (p2 - p1); - Vector3 q1 = p1 + scale * tangent; - controlPoints.Add(p1); - controlPoints.Add(q1); - } - else if (i == segmentPoints.Count - 1) - { - Vector3 p0 = segmentPoints[i - 1]; - Vector3 p1 = segmentPoints[i]; - Vector3 tangent = (p1 - p0); - Vector3 q0 = p1 - scale * tangent; - controlPoints.Add(q0); - controlPoints.Add(p1); - } - else - { - Vector3 p0 = segmentPoints[i - 1]; - Vector3 p1 = segmentPoints[i]; - Vector3 p2 = segmentPoints[i + 1]; - Vector3 tangent = (p2 - p0).normalized; - Vector3 q0 = p1 - scale * tangent * (p1 - p0).magnitude; - Vector3 q1 = p1 + scale * tangent * (p2 - p1).magnitude; - controlPoints.Add(q0); - controlPoints.Add(p1); - controlPoints.Add(q1); - } - } - return controlPoints; - } - - private Vector3 CalculatePoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) - { - float u = 1 - t; - float tt = t * t; - float uu = u * u; - float uuu = uu * u; - float ttt = tt * t; - Vector3 p = uuu * p0; - p += 3 * uu * t * p1; - p += 3 * u * tt * p2; - p += ttt * p3; - return p; - } - - private Color[] GetPivotColors(Vector3[] vectors, float motionStart, float motionStop, Color fromColor, Color toColor, Color loopColor, float offset) - { - Color[] colors = new Color[vectors.Length]; - - float transStart = m_TimeArea.TimeToPixel(m_TransitionStartTime, m_Rect) + m_LeftThumbOffset; - float transStop = m_TimeArea.TimeToPixel(m_TransitionStopTime, m_Rect) + m_RightThumbOffset; - float transWidth = transStop - transStart; - - for (int i = 0; i < colors.Length; i++) - { - if (vectors[i].x >= transStart && vectors[i].x <= transStop) - colors[i] = Color.Lerp(fromColor, toColor, (vectors[i].x - transStart) / transWidth); - else if (vectors[i].x < transStart && vectors[i].x >= motionStart + offset) - colors[i] = fromColor; - else if (vectors[i].x > transStop && vectors[i].x <= motionStop + offset) - colors[i] = toColor; - else - colors[i] = loopColor; - } - return colors; - } - - private Vector3[] GetPivotVectors(PivotSample[] samples, float width, Rect rect, float height, bool loop) - { - if (samples.Length == 0 || width < 0.33f) // not pivots for super small anims - return new Vector3[0]; - - List vectorList = new List(); - for (int i = 0; i < samples.Length; i++) - { - PivotSample s = samples[i]; - Vector3 point = Vector3.zero; - point.x = m_TimeArea.TimeToPixel(s.m_Time, rect); - point.y = height / 16 + s.m_Weight * 12 * height / 16; - vectorList.Add(point); - } - if (loop && vectorList[vectorList.Count - 1].x <= rect.width) - { - float pos = vectorList[vectorList.Count - 1].x; - int iterator = 0; - int multiplier = 1; - List loopVectors = new List(); - while (pos < rect.width) - { - if (iterator > vectorList.Count - 1) - { - iterator = 0; - multiplier++; - } - Vector3 point = vectorList[iterator]; - point.x += (multiplier * width); - pos = point.x; - loopVectors.Add(point); - iterator++; - } - vectorList.AddRange(loopVectors); - } - List controls = GetControls(vectorList, .5f); - vectorList.Clear(); - for (int i = 0; i < controls.Count - 3; i += 3) - { - Vector3 p0 = controls[i]; - Vector3 p1 = controls[i + 1]; - Vector3 p2 = controls[i + 2]; - Vector3 p3 = controls[i + 3]; - if (i == 0) - vectorList.Add(CalculatePoint(0, p0, p1, p2, p3)); - for (int j = 1; j <= 10; j++) - vectorList.Add(CalculatePoint(j / 10f, p0, p1, p2, p3)); - } - return vectorList.ToArray(); - } - - private Vector3[] OffsetPivotVectors(Vector3[] vectors, float offset) - { - for (int i = 0; i < vectors.Length; i++) - vectors[i].x += offset; - return vectors; - } - - private void DoPivotCurves() - { - Color srcFull = Color.white; - Color dstFull = Color.white; - Color srcNone = new Color(1f, 1f, 1f, 0.1f); - Color dstNone = new Color(1f, 1f, 1f, 0.1f); - Color srcLoopColor = new Color(0.75f, 0.75f, 0.75f, 0.2f); - Color dstLoopColor = new Color(0.75f, 0.75f, 0.75f, 0.2f); - - Rect rect = new Rect(0, 18, m_Rect.width, 66); - GUI.BeginGroup(rect); - // build vectors lists if needed - float srcStart = m_TimeArea.TimeToPixel(SrcStartTime, rect); - float srcStop = m_TimeArea.TimeToPixel(SrcStopTime, rect); - float dstStart = m_TimeArea.TimeToPixel(DstStartTime, rect); - float dstStop = m_TimeArea.TimeToPixel(DstStopTime, rect); - if (m_SrcPivotVectors == null) - m_SrcPivotVectors = GetPivotVectors(m_SrcPivotList.ToArray(), srcStop - srcStart, rect, rect.height, srcLoop); - if (m_DstPivotVectors == null) - m_DstPivotVectors = GetPivotVectors(m_DstPivotList.ToArray(), dstStop - dstStart, rect, rect.height, dstLoop); - - m_DstPivotVectors = OffsetPivotVectors(m_DstPivotVectors, m_DstDragOffset + dstStart - srcStart); - - Color[] srcColors = GetPivotColors(m_SrcPivotVectors, srcStart, srcStop, srcFull, srcNone, srcLoopColor, 0f); - Color[] dstColors = GetPivotColors(m_DstPivotVectors, dstStart, dstStop, dstNone, dstFull, dstLoopColor, m_DstDragOffset); - - Handles.DrawAAPolyLine(srcColors, m_SrcPivotVectors); - Handles.DrawAAPolyLine(dstColors, m_DstPivotVectors); - GUI.EndGroup(); - } - - private void EnforceConstraints() - { - Rect r = new Rect(0, 0, m_Rect.width, 150); - if (m_DragState == DragStates.LeftSelection) - { - float minLimit = m_TimeArea.TimeToPixel(SrcStartTime, r) - m_TimeArea.TimeToPixel(TransitionStartTime, r); - float maxLimit = m_TimeArea.TimeToPixel(TransitionStopTime, r) - m_TimeArea.TimeToPixel(TransitionStartTime, r); - - m_LeftThumbOffset = Mathf.Clamp(m_LeftThumbOffset, minLimit, maxLimit); - } - - if (m_DragState == DragStates.RightSelection) - { - float minLimit = m_TimeArea.TimeToPixel(TransitionStartTime, r) - m_TimeArea.TimeToPixel(TransitionStopTime, r); - if (m_RightThumbOffset < minLimit) - m_RightThumbOffset = minLimit; - } - } - - private bool WasDraggingData() - { - return m_DstDragOffset != 0 || - m_LeftThumbOffset != 0 || - m_RightThumbOffset != 0; - } - - public bool DoTimeline(Rect timeRect) - { - bool hasModifiedData = false; - - Init(); - m_Rect = timeRect; - - float timeAreaStart = m_TimeArea.PixelToTime(timeRect.xMin, timeRect); - float timeAreaStop = m_TimeArea.PixelToTime(timeRect.xMax, timeRect); - - if (!Mathf.Approximately(timeAreaStart, StartTime)) - { - StartTime = timeAreaStart; - GUI.changed = true; - } - if (!Mathf.Approximately(timeAreaStop, StopTime)) - { - StopTime = timeAreaStop; - GUI.changed = true; - } - - Time = Mathf.Max(Time, 0f); - - if (Event.current.type == EventType.Repaint) - m_TimeArea.rect = timeRect; - - m_TimeArea.BeginViewGUI(); - m_TimeArea.EndViewGUI(); - - GUI.BeginGroup(timeRect); - { - Event evt = Event.current; - Rect r = new Rect(0, 0, timeRect.width, timeRect.height); - Rect headerRect = new Rect(0, 0, timeRect.width, 18); - Rect bodyRect = new Rect(0, 18, timeRect.width, 132); - - // get the relevant positions in pixels - float srcStart = m_TimeArea.TimeToPixel(SrcStartTime, r); - float srcStop = m_TimeArea.TimeToPixel(SrcStopTime, r); - float dstStart = m_TimeArea.TimeToPixel(DstStartTime, r) + m_DstDragOffset; - float dstStop = m_TimeArea.TimeToPixel(DstStopTime, r) + m_DstDragOffset; - float transStart = m_TimeArea.TimeToPixel(TransitionStartTime, r) + m_LeftThumbOffset; - float transStop = m_TimeArea.TimeToPixel(TransitionStopTime, r) + m_RightThumbOffset; - float playPoint = m_TimeArea.TimeToPixel(Time, r); - - // get the relevant Rects - - Rect srcRect = new Rect(srcStart, 85, srcStop - srcStart, 32); - Rect dstRect = new Rect(dstStart, 117, dstStop - dstStart, 32); - Rect transHeaderRect = new Rect(transStart, 0, transStop - transStart, 18); - Rect transRect = new Rect(transStart, 18, transStop - transStart, r.height - 18); - Rect leftThumbRect = new Rect(transStart - 9, 5, 9, 15); - Rect rightThumbRect = new Rect(transStop, 5, 9, 15); - Rect playHeadRect = new Rect(playPoint - 7, 4, 15, 15); - - - // handle keyboard - if (evt.type == EventType.KeyDown) - { - if (EditorGUIUtility.keyboardControl == id) - if (m_DragState == DragStates.Destination) - m_DstDragOffset = 0f; - if (m_DragState == DragStates.LeftSelection) - m_LeftThumbOffset = 0f; - if (m_DragState == DragStates.RightSelection) - m_RightThumbOffset = 0f; - if (m_DragState == DragStates.Playhead) - m_TimeOffset = 0f; - if (m_DragState == DragStates.FullSelection) - { - m_LeftThumbOffset = 0f; - m_RightThumbOffset = 0f; - } - } - - // handle mouse down - if (evt.type == EventType.MouseDown) - { - if (r.Contains(evt.mousePosition)) - { - EditorGUIUtility.hotControl = id; - EditorGUIUtility.keyboardControl = id; - if (playHeadRect.Contains(evt.mousePosition)) - { - m_DragState = DragStates.Playhead; - m_TimeStartDrag = m_TimeArea.TimeToPixel(Time, r); - } - else if (srcRect.Contains(evt.mousePosition)) - m_DragState = DragStates.Source; - else if (dstRect.Contains(evt.mousePosition)) - m_DragState = DragStates.Destination; - else if (leftThumbRect.Contains(evt.mousePosition)) - m_DragState = DragStates.LeftSelection; - else if (rightThumbRect.Contains(evt.mousePosition)) - m_DragState = DragStates.RightSelection; - else if (transHeaderRect.Contains(evt.mousePosition)) - m_DragState = DragStates.FullSelection; - else if (headerRect.Contains(evt.mousePosition)) - m_DragState = DragStates.TimeArea; - else if (bodyRect.Contains(evt.mousePosition)) - m_DragState = DragStates.TimeArea; - else - m_DragState = DragStates.None; - evt.Use(); - } - } - - // handle mouse drag - if (evt.type == EventType.MouseDrag) - { - if (EditorGUIUtility.hotControl == id) - { - switch (m_DragState) - { - case DragStates.Source: - case DragStates.TimeArea: - m_TimeArea.m_Translation.x += evt.delta.x; - break; - case DragStates.Destination: - m_DstDragOffset += evt.delta.x; - EnforceConstraints(); - break; - case DragStates.LeftSelection: - // clamp the delta when off range - if ((evt.delta.x > 0 && evt.mousePosition.x > srcStart) || - (evt.delta.x < 0 && evt.mousePosition.x < transStop)) - m_LeftThumbOffset += evt.delta.x; - EnforceConstraints(); - break; - case DragStates.RightSelection: - // clamp the delta when off range - if (evt.delta.x > 0 && evt.mousePosition.x > transStart || evt.delta.x < 0) - m_RightThumbOffset += evt.delta.x; - EnforceConstraints(); - break; - case DragStates.FullSelection: - m_RightThumbOffset += evt.delta.x; - m_LeftThumbOffset += evt.delta.x; - EnforceConstraints(); - break; - case DragStates.Playhead: - if ((evt.delta.x > 0 && evt.mousePosition.x > srcStart) || - (evt.delta.x < 0 && evt.mousePosition.x <= m_TimeArea.TimeToPixel(SampleStopTime, r))) - m_TimeOffset += evt.delta.x; - Time = m_TimeArea.PixelToTime(m_TimeStartDrag + m_TimeOffset, r); - - break; - case DragStates.None: - break; - } - evt.Use(); - GUI.changed = true; - } - } - - - // handle mouse up both when it happens over the control area and outside control area (case 834214) - if (Event.current.GetTypeForControl(id) == EventType.MouseUp) - { - SrcStartTime = m_TimeArea.PixelToTime(srcStart, r); - SrcStopTime = m_TimeArea.PixelToTime(srcStop, r); - DstStartTime = m_TimeArea.PixelToTime(dstStart, r); - DstStopTime = m_TimeArea.PixelToTime(dstStop, r); - TransitionStartTime = m_TimeArea.PixelToTime(transStart, r); - TransitionStopTime = m_TimeArea.PixelToTime(transStop, r); - GUI.changed = true; - m_DragState = DragStates.None; - - hasModifiedData = WasDraggingData(); - m_LeftThumbOffset = 0f; - m_RightThumbOffset = 0f; - m_TimeOffset = 0f; - m_DstDragOffset = 0f; - EditorGUIUtility.hotControl = 0; - evt.Use(); - } - - - // draw the background boxes - GUI.Box(headerRect, GUIContent.none, styles.header); - GUI.Box(bodyRect, GUIContent.none, styles.background); - - // draw ticks and curves on top of background boxes - m_TimeArea.DrawMajorTicks(bodyRect, 30); - - - GUIContent srcContent = EditorGUIUtility.TempContent(SrcName); - - // draw src Loop - int srcLoopCount = srcLoop ? (1 + (int)((transStop - srcRect.xMin) / (srcRect.xMax - srcRect.xMin))) : 1; - Rect loopRect = srcRect; - if (srcRect.width < 10) // if smaller than 10 pixel, group - { - loopRect = new Rect(srcRect.x, srcRect.y, (srcRect.xMax - srcRect.xMin) * srcLoopCount, srcRect.height); - srcLoopCount = 1; - } - - for (int loopSrcIt = 0; loopSrcIt < srcLoopCount; loopSrcIt++) - { - GUI.BeginGroup(loopRect, GUIContent.none, styles.leftBlock); - float widthBefore = transStart - loopRect.xMin; - float widthDuring = transStop - transStart; - float widthAfter = (loopRect.xMax - loopRect.xMin) - (widthBefore + widthDuring); - if (widthBefore > 0) - GUI.Box(new Rect(0, 0, widthBefore, srcRect.height), GUIContent.none, styles.onLeft); - if (widthDuring > 0) - GUI.Box(new Rect(widthBefore, 0, widthDuring, srcRect.height), GUIContent.none, styles.onOff); - if (widthAfter > 0) - GUI.Box(new Rect(widthBefore + widthDuring, 0, widthAfter, srcRect.height), GUIContent.none, styles.offRight); - float srcAlphaTarget = 1f; - float srcLabelRight = styles.block.CalcSize(srcContent).x; - float srcPercentLeft = Mathf.Max(0, widthBefore) - 20; - float srcPercentRight = srcPercentLeft + 15; - if (srcPercentLeft < srcLabelRight && srcPercentRight > 0f && m_DragState == DragStates.LeftSelection) - srcAlphaTarget = 0f; - GUI.EndGroup(); - - float srcAlpha = styles.leftBlock.normal.textColor.a; - if (!Mathf.Approximately(srcAlpha, srcAlphaTarget) && Event.current.type == EventType.Repaint) - { - srcAlpha = Mathf.Lerp(srcAlpha, srcAlphaTarget, 0.1f); - styles.leftBlock.normal.textColor = new Color(styles.leftBlock.normal.textColor.r, styles.leftBlock.normal.textColor.g, styles.leftBlock.normal.textColor.b, srcAlpha); - HandleUtility.Repaint(); - } - GUI.Box(loopRect, srcContent, styles.leftBlock); - loopRect = new Rect(loopRect.xMax, 85, loopRect.xMax - loopRect.xMin, 32); - } - - - GUIContent dstContent = EditorGUIUtility.TempContent(DstName); - int dstLoopCount = dstLoop ? (1 + (int)((transStop - dstRect.xMin) / (dstRect.xMax - dstRect.xMin))) : 1; - loopRect = dstRect; - if (dstRect.width < 10) // if smaller than 10 pixel, group - { - loopRect = new Rect(dstRect.x, dstRect.y, (dstRect.xMax - dstRect.xMin) * dstLoopCount, dstRect.height); - dstLoopCount = 1; - } - - for (int loopDstIt = 0; loopDstIt < dstLoopCount; loopDstIt++) - { - // draw the DST box - GUI.BeginGroup(loopRect, GUIContent.none, styles.rightBlock); - float widthBefore = transStart - loopRect.xMin; - float widthDuring = transStop - transStart; - float widthAfter = (loopRect.xMax - loopRect.xMin) - (widthBefore + widthDuring); - if (widthBefore > 0) - GUI.Box(new Rect(0, 0, widthBefore, dstRect.height), GUIContent.none, styles.offLeft); - if (widthDuring > 0) - GUI.Box(new Rect(widthBefore, 0, widthDuring, dstRect.height), GUIContent.none, styles.offOn); - if (widthAfter > 0) - GUI.Box(new Rect(widthBefore + widthDuring, 0, widthAfter, dstRect.height), GUIContent.none, styles.onRight); - float dstAlphaTarget = 1f; - float dstLabelRight = styles.block.CalcSize(dstContent).x; - float dstPercentLeft = Mathf.Max(0, widthBefore) - 20; - float dstPercentRight = dstPercentLeft + 15; - if (dstPercentLeft < dstLabelRight && dstPercentRight > 0f && (m_DragState == DragStates.LeftSelection || m_DragState == DragStates.Destination)) - dstAlphaTarget = 0f; - GUI.EndGroup(); - float dstAlpha = styles.rightBlock.normal.textColor.a; - if (!Mathf.Approximately(dstAlpha, dstAlphaTarget) && Event.current.type == EventType.Repaint) - { - dstAlpha = Mathf.Lerp(dstAlpha, dstAlphaTarget, 0.1f); - styles.rightBlock.normal.textColor = new Color(styles.rightBlock.normal.textColor.r, styles.rightBlock.normal.textColor.g, styles.rightBlock.normal.textColor.b, dstAlpha); - HandleUtility.Repaint(); - } - GUI.Box(loopRect, dstContent, styles.rightBlock); - - loopRect = new Rect(loopRect.xMax, loopRect.yMin, loopRect.xMax - loopRect.xMin, 32); - } - - // draw the transition selection box in the body - GUI.Box(transRect, GUIContent.none, styles.select); - - // draw the transition selection box in the header - GUI.Box(transHeaderRect, GUIContent.none, styles.selectHead); - - m_TimeArea.TimeRuler(headerRect, 30); - - // draw the thumbs - GUI.Box(leftThumbRect, GUIContent.none, (m_HasExitTime) ? styles.handLeft : styles.handLeftPrev); - GUI.Box(rightThumbRect, GUIContent.none, styles.handRight); - - // playhead and bar - GUI.Box(playHeadRect, GUIContent.none, styles.playhead); - Color oldColor = Handles.color; - Handles.color = Color.white; - Handles.DrawLine(new Vector3(playPoint, 19, 0), new Vector3(playPoint, r.height, 0)); - Handles.color = oldColor; - - - bool oneFrameSrc = (SrcStopTime - SrcStartTime) < 1.0f / 30.0f; - bool oneFrameDst = (DstStopTime - DstStartTime) < 1.0f / 30.0f; - // show normalized time label when moving destination state - if (m_DragState == DragStates.Destination && !oneFrameDst) - { - Rect transLabelRect = new Rect(transStart - 50, dstRect.y, 45, dstRect.height); - string transLabel = String.Format("{0:0%}", (transStart - dstStart) / (dstStop - dstStart)); - GUI.Box(transLabelRect, EditorGUIUtility.TempContent(transLabel), styles.timeBlockRight); - } - - // show normalized time label on left side when moving left edge of transition - if (m_DragState == DragStates.LeftSelection) - { - if (!oneFrameSrc) - { - Rect srcLabelRect = new Rect(transStart - 50, srcRect.y, 45, srcRect.height); - string srcLabel = String.Format("{0:0%}", (transStart - srcStart) / (srcStop - srcStart)); - GUI.Box(srcLabelRect, EditorGUIUtility.TempContent(srcLabel), styles.timeBlockRight); - } - - if (!oneFrameDst) - { - Rect dstLabelRect = new Rect(transStart - 50, dstRect.y, 45, dstRect.height); - string dstLabel = String.Format("{0:0%}", (transStart - dstStart) / (dstStop - dstStart)); - GUI.Box(dstLabelRect, EditorGUIUtility.TempContent(dstLabel), styles.timeBlockRight); - } - } - - // show normalized time label on right side when moving right edge of transition - if (m_DragState == DragStates.RightSelection) - { - if (!oneFrameSrc) - { - Rect srcLabelRect = new Rect(transStop + 5, srcRect.y, 45, srcRect.height); - string srcLabel = String.Format("{0:0%}", (transStop - srcStart) / (srcStop - srcStart)); - GUI.Box(srcLabelRect, EditorGUIUtility.TempContent(srcLabel), styles.timeBlockLeft); - } - - if (!oneFrameDst) - { - Rect dstLabelRect = new Rect(transStop + 5, dstRect.y, 45, dstRect.height); - string dstLabel = String.Format("{0:0%}", (transStop - dstStart) / (dstStop - dstStart)); - GUI.Box(dstLabelRect, EditorGUIUtility.TempContent(dstLabel), styles.timeBlockLeft); - } - } - - DoPivotCurves(); - } - GUI.EndGroup(); - - return hasModifiedData; - } - }//class Timeline -}//namespace UnityEditor diff --git a/Editor/Mono/Inspector/TrailRendererInspector.cs b/Editor/Mono/Inspector/TrailRendererInspector.cs deleted file mode 100644 index 32f231e4e3..0000000000 --- a/Editor/Mono/Inspector/TrailRendererInspector.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Experimental.Rendering; - -namespace UnityEditor -{ - [CustomEditor(typeof(TrailRenderer))] - [CanEditMultipleObjects] - internal class TrailRendererInspector : RendererEditorBase - { - private class Styles - { - public static GUIContent colorGradient = EditorGUIUtility.TrTextContent("Color", "The gradient describing the color along the trail."); - public static GUIContent numCornerVertices = EditorGUIUtility.TrTextContent("Corner Vertices", "How many vertices to add for each corner."); - public static GUIContent numCapVertices = EditorGUIUtility.TrTextContent("End Cap Vertices", "How many vertices to add at each end."); - public static GUIContent alignment = EditorGUIUtility.TrTextContent("Alignment", "Trails can rotate to face their transform component or the camera. Note that when using Local mode, trails will face the XY plane of the Transform."); - public static GUIContent textureMode = EditorGUIUtility.TrTextContent("Texture Mode", "Should the U coordinate be stretched or tiled?"); - public static GUIContent generateLightingData = EditorGUIUtility.TrTextContent("Generate Lighting Data", "Toggle generation of normal and tangent data, for use in lit shaders."); - } - - private string[] m_ExcludedProperties; - - private LineRendererCurveEditor m_CurveEditor = new LineRendererCurveEditor(); - private SerializedProperty m_ColorGradient; - private SerializedProperty m_NumCornerVertices; - private SerializedProperty m_NumCapVertices; - private SerializedProperty m_Alignment; - private SerializedProperty m_TextureMode; - private SerializedProperty m_GenerateLightingData; - - public override void OnEnable() - { - base.OnEnable(); - - List excludedProperties = new List(); - excludedProperties.Add("m_LightProbeUsage"); - excludedProperties.Add("m_LightProbeVolumeOverride"); - excludedProperties.Add("m_ReflectionProbeUsage"); - excludedProperties.Add("m_ProbeAnchor"); - excludedProperties.Add("m_Parameters"); - excludedProperties.Add("m_RenderingLayerMask"); - m_ExcludedProperties = excludedProperties.ToArray(); - - m_CurveEditor.OnEnable(serializedObject); - m_ColorGradient = serializedObject.FindProperty("m_Parameters.colorGradient"); - m_NumCornerVertices = serializedObject.FindProperty("m_Parameters.numCornerVertices"); - m_NumCapVertices = serializedObject.FindProperty("m_Parameters.numCapVertices"); - m_Alignment = serializedObject.FindProperty("m_Parameters.alignment"); - m_TextureMode = serializedObject.FindProperty("m_Parameters.textureMode"); - m_GenerateLightingData = serializedObject.FindProperty("m_Parameters.generateLightingData"); - - InitializeProbeFields(); - } - - public void OnDisable() - { - m_CurveEditor.OnDisable(); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - List excludedProperties = new List(); - if (!SupportedRenderingFeatures.active.rendererSupportsMotionVectors) - excludedProperties.Add("m_MotionVectors"); - if (!SupportedRenderingFeatures.active.rendererSupportsReceiveShadows) - excludedProperties.Add("m_ReceiveShadows"); - excludedProperties.AddRange(m_ExcludedProperties); - - DrawPropertiesExcluding(m_SerializedObject, excludedProperties.ToArray()); - - m_CurveEditor.CheckCurveChangedExternally(); - m_CurveEditor.OnInspectorGUI(); - - EditorGUILayout.PropertyField(m_ColorGradient, Styles.colorGradient); - EditorGUILayout.PropertyField(m_NumCornerVertices, Styles.numCornerVertices); - EditorGUILayout.PropertyField(m_NumCapVertices, Styles.numCapVertices); - EditorGUILayout.PropertyField(m_Alignment, Styles.alignment); - EditorGUILayout.PropertyField(m_TextureMode, Styles.textureMode); - EditorGUILayout.PropertyField(m_GenerateLightingData, Styles.generateLightingData); - - EditorGUILayout.Space(); - - RenderSortingLayerFields(); - - m_Probes.OnGUI(targets, (Renderer)target, false); - RenderRenderingLayer(); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/TransformInspector.cs b/Editor/Mono/Inspector/TransformInspector.cs deleted file mode 100644 index 6d3b16bccb..0000000000 --- a/Editor/Mono/Inspector/TransformInspector.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(Transform))] - [CanEditMultipleObjects] - internal class TransformInspector : Editor - { - SerializedProperty m_Position; - SerializedProperty m_Scale; - TransformRotationGUI m_RotationGUI; - - class Contents - { - public GUIContent positionContent = EditorGUIUtility.TrTextContent("Position", "The local position of this GameObject relative to the parent."); - public GUIContent scaleContent = EditorGUIUtility.TrTextContent("Scale", "The local scaling of this GameObject relative to the parent."); - 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."); - } - static Contents s_Contents; - - public void OnEnable() - { - m_Position = serializedObject.FindProperty("m_LocalPosition"); - m_Scale = serializedObject.FindProperty("m_LocalScale"); - - if (m_RotationGUI == null) - m_RotationGUI = new TransformRotationGUI(); - m_RotationGUI.OnEnable(serializedObject.FindProperty("m_LocalRotation"), EditorGUIUtility.TrTextContent("Rotation", "The local rotation of this GameObject relative to the parent.")); - } - - public override void OnInspectorGUI() - { - if (s_Contents == null) - s_Contents = new Contents(); - - if (!EditorGUIUtility.wideMode) - { - EditorGUIUtility.wideMode = true; - EditorGUIUtility.labelWidth = EditorGUIUtility.currentViewWidth - 212; - } - - serializedObject.Update(); - - Inspector3D(); - // Warning if global position is too large for floating point errors. - // SanitizeBounds function doesn't even support values beyond 100000 - Transform t = target as Transform; - Vector3 pos = t.position; - if (Mathf.Abs(pos.x) > 100000 || Mathf.Abs(pos.y) > 100000 || Mathf.Abs(pos.z) > 100000) - EditorGUILayout.HelpBox(s_Contents.floatingPointWarning, MessageType.Warning); - - serializedObject.ApplyModifiedProperties(); - } - - private void Inspector3D() - { - EditorGUILayout.PropertyField(m_Position, s_Contents.positionContent); - m_RotationGUI.RotationField(); - EditorGUILayout.PropertyField(m_Scale, s_Contents.scaleContent); - } - } -} diff --git a/Editor/Mono/Inspector/TransformRotationGUI.cs b/Editor/Mono/Inspector/TransformRotationGUI.cs deleted file mode 100644 index 2762b6e475..0000000000 --- a/Editor/Mono/Inspector/TransformRotationGUI.cs +++ /dev/null @@ -1,118 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - [System.Serializable] - internal class TransformRotationGUI - { - private GUIContent rotationContent = EditorGUIUtility.TrTextContent("Rotation", "The local rotation of this Game Object relative to the parent."); - - private Vector3 m_EulerAngles; - // Some random rotation that will never be the same as the current one - private Vector3 m_OldEulerAngles = new Vector3(1000000, 10000000, 1000000); - private RotationOrder m_OldRotationOrder = RotationOrder.OrderZXY; - - SerializedProperty m_Rotation; - Object[] targets; - - private static int s_FoldoutHash = "Foldout".GetHashCode(); - - public void OnEnable(SerializedProperty m_Rotation, GUIContent label) - { - this.m_Rotation = m_Rotation; - this.targets = m_Rotation.serializedObject.targetObjects; - this.m_OldRotationOrder = (targets[0] as Transform).rotationOrder; - rotationContent = label; - } - - public void RotationField() - { - RotationField(false); - } - - public void RotationField(bool disabled) - { - Transform t = targets[0] as Transform; - Vector3 localEuler = t.GetLocalEulerAngles(t.rotationOrder); - if ( - m_OldEulerAngles.x != localEuler.x || - m_OldEulerAngles.y != localEuler.y || - m_OldEulerAngles.z != localEuler.z || - m_OldRotationOrder != t.rotationOrder - ) - { - m_EulerAngles = t.GetLocalEulerAngles(t.rotationOrder); - m_OldRotationOrder = t.rotationOrder; - } - bool differentRotation = false; - bool differentRotationOrder = false; - for (int i = 1; i < targets.Length; i++) - { - Transform otherTransform = (targets[i] as Transform); - Vector3 otherLocalEuler = otherTransform.GetLocalEulerAngles(otherTransform.rotationOrder); - differentRotation |= (otherLocalEuler.x != localEuler.x || - otherLocalEuler.y != localEuler.y || - otherLocalEuler.z != localEuler.z); - - differentRotationOrder |= otherTransform.rotationOrder != t.rotationOrder; - } - - Rect r = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight * (EditorGUIUtility.wideMode ? 1 : 2)); - GUIContent label = EditorGUI.BeginProperty(r, rotationContent, m_Rotation); - - EditorGUI.showMixedValue = differentRotation; - - EditorGUI.BeginChangeCheck(); - - int id = GUIUtility.GetControlID(s_FoldoutHash, FocusType.Keyboard, r); - string rotationLabel = ""; - if (AnimationMode.InAnimationMode() && t.rotationOrder != RotationOrder.OrderZXY) - { - if (differentRotationOrder) - { - rotationLabel = "Mixed"; - } - else - { - rotationLabel = (t.rotationOrder).ToString(); - rotationLabel = rotationLabel.Substring(rotationLabel.Length - 3); - } - - label.text = label.text + " (" + rotationLabel + ")"; - } - - r = EditorGUI.MultiFieldPrefixLabel(r, id, label, 3); - r.height = EditorGUIUtility.singleLineHeight; - using (new EditorGUI.DisabledScope(disabled)) - { - m_EulerAngles = EditorGUI.Vector3Field(r, GUIContent.none, m_EulerAngles); - } - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObjects(targets, "Inspector"); // Generic undo title to be consistent with Position and Scale changes. - foreach (Transform tr in targets) - { - tr.SetLocalEulerAngles(m_EulerAngles, tr.rotationOrder); - if (tr.parent != null) - tr.SendTransformChangedScale(); // force scale update, needed if tr has non-uniformly scaled parent. - } - m_Rotation.serializedObject.SetIsDifferentCacheDirty(); - } - - EditorGUI.showMixedValue = false; - - if (differentRotationOrder) - { - EditorGUILayout.HelpBox("Transforms have different rotation orders, keyframes saved will have the same value but not the same local rotation", MessageType.Warning); - } - - EditorGUI.EndProperty(); - } - } -} diff --git a/Editor/Mono/Inspector/TransformUtils.cs b/Editor/Mono/Inspector/TransformUtils.cs deleted file mode 100644 index 6238ea9153..0000000000 --- a/Editor/Mono/Inspector/TransformUtils.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - public static class TransformUtils - { - public static Vector3 GetInspectorRotation(Transform t) - { - return t.GetLocalEulerAngles(t.rotationOrder); - } - - public static void SetInspectorRotation(Transform t, Vector3 r) - { - t.SetLocalEulerAngles(r, t.rotationOrder); - } - } -} diff --git a/Editor/Mono/Inspector/UNetBehaviourInspector.cs b/Editor/Mono/Inspector/UNetBehaviourInspector.cs deleted file mode 100644 index aa57e50446..0000000000 --- a/Editor/Mono/Inspector/UNetBehaviourInspector.cs +++ /dev/null @@ -1,5 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -// gone diff --git a/Editor/Mono/Inspector/UnityEventDrawer.cs b/Editor/Mono/Inspector/UnityEventDrawer.cs deleted file mode 100644 index e43400f725..0000000000 --- a/Editor/Mono/Inspector/UnityEventDrawer.cs +++ /dev/null @@ -1,713 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using UnityEngine; -using UnityEditor; -using UnityEngine.Events; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - [CustomPropertyDrawer(typeof(UnityEventBase), true)] - public class UnityEventDrawer : PropertyDrawer - { - protected class State - { - internal ReorderableList m_ReorderableList; - public int lastSelectedIndex; - } - - private const string kNoFunctionString = "No Function"; - - //Persistent Listener Paths - private const string kInstancePath = "m_Target"; - private const string kCallStatePath = "m_CallState"; - private const string kArgumentsPath = "m_Arguments"; - private const string kModePath = "m_Mode"; - private const string kMethodNamePath = "m_MethodName"; - - //ArgumentCache paths - private const string kFloatArgument = "m_FloatArgument"; - private const string kIntArgument = "m_IntArgument"; - private const string kObjectArgument = "m_ObjectArgument"; - private const string kStringArgument = "m_StringArgument"; - private const string kBoolArgument = "m_BoolArgument"; - private const string kObjectArgumentAssemblyTypeName = "m_ObjectArgumentAssemblyTypeName"; - - string m_Text; - UnityEventBase m_DummyEvent; - SerializedProperty m_Prop; - SerializedProperty m_ListenersArray; - - const int kExtraSpacing = 9; - - //State: - ReorderableList m_ReorderableList; - int m_LastSelectedIndex; - Dictionary m_States = new Dictionary(); - - static string GetEventParams(UnityEventBase evt) - { - var methodInfo = evt.FindMethod("Invoke", evt, PersistentListenerMode.EventDefined, null); - - var sb = new StringBuilder(); - sb.Append(" ("); - - var types = methodInfo.GetParameters().Select(x => x.ParameterType).ToArray(); - for (int i = 0; i < types.Length; i++) - { - sb.Append(types[i].Name); - if (i < types.Length - 1) - { - sb.Append(", "); - } - } - sb.Append(")"); - return sb.ToString(); - } - - private State GetState(SerializedProperty prop) - { - State state; - string key = prop.propertyPath; - m_States.TryGetValue(key, out state); - // ensure the cached SerializedProperty is synchronized (case 974069) - if (state == null || state.m_ReorderableList.serializedProperty.serializedObject != prop.serializedObject) - { - if (state == null) - state = new State(); - - SerializedProperty listenersArray = prop.FindPropertyRelative("m_PersistentCalls.m_Calls"); - state.m_ReorderableList = new ReorderableList(prop.serializedObject, listenersArray, false, true, true, true); - state.m_ReorderableList.drawHeaderCallback = DrawEventHeader; - state.m_ReorderableList.drawElementCallback = DrawEventListener; - state.m_ReorderableList.onSelectCallback = SelectEventListener; - state.m_ReorderableList.onReorderCallback = EndDragChild; - state.m_ReorderableList.onAddCallback = AddEventListener; - state.m_ReorderableList.onRemoveCallback = RemoveButton; - // Two standard lines with standard spacing between and extra spacing below to better separate items visually. - state.m_ReorderableList.elementHeight = EditorGUI.kSingleLineHeight * 2 + EditorGUI.kControlVerticalSpacing + kExtraSpacing; - - m_States[key] = state; - } - return state; - } - - private State RestoreState(SerializedProperty property) - { - State state = GetState(property); - - m_ListenersArray = state.m_ReorderableList.serializedProperty; - m_ReorderableList = state.m_ReorderableList; - m_LastSelectedIndex = state.lastSelectedIndex; - m_ReorderableList.index = m_LastSelectedIndex; - - return state; - } - - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - m_Prop = property; - m_Text = label.text; - - State state = RestoreState(property); - - OnGUI(position); - state.lastSelectedIndex = m_LastSelectedIndex; - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - //TODO: Also we need to have a constructor or initializer called for this property Drawer, before OnGUI or GetPropertyHeight - //otherwise, we get Restore the State twice, once here and agai in OnGUI. Maybe we should only do it here? - RestoreState(property); - - float height = 0f; - if (m_ReorderableList != null) - { - height = m_ReorderableList.GetHeight(); - } - return height; - } - - public void OnGUI(Rect position) - { - if (m_ListenersArray == null || !m_ListenersArray.isArray) - return; - - m_DummyEvent = GetDummyEvent(m_Prop); - if (m_DummyEvent == null) - return; - - if (m_ReorderableList != null) - { - var oldIdentLevel = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; - m_ReorderableList.DoList(position); - EditorGUI.indentLevel = oldIdentLevel; - } - } - - protected virtual void DrawEventHeader(Rect headerRect) - { - headerRect.height = 16; - - string text = (string.IsNullOrEmpty(m_Text) ? "Event" : m_Text) + GetEventParams(m_DummyEvent); - GUI.Label(headerRect, text); - } - - static PersistentListenerMode GetMode(SerializedProperty mode) - { - return (PersistentListenerMode)mode.enumValueIndex; - } - - void DrawEventListener(Rect rect, int index, bool isactive, bool isfocused) - { - var pListener = m_ListenersArray.GetArrayElementAtIndex(index); - - rect.y++; - Rect[] subRects = GetRowRects(rect); - Rect enabledRect = subRects[0]; - Rect goRect = subRects[1]; - Rect functionRect = subRects[2]; - Rect argRect = subRects[3]; - - // find the current event target... - var callState = pListener.FindPropertyRelative(kCallStatePath); - var mode = pListener.FindPropertyRelative(kModePath); - var arguments = pListener.FindPropertyRelative(kArgumentsPath); - var listenerTarget = pListener.FindPropertyRelative(kInstancePath); - var methodName = pListener.FindPropertyRelative(kMethodNamePath); - - Color c = GUI.backgroundColor; - GUI.backgroundColor = Color.white; - - EditorGUI.PropertyField(enabledRect, callState, GUIContent.none); - - EditorGUI.BeginChangeCheck(); - { - GUI.Box(goRect, GUIContent.none); - EditorGUI.PropertyField(goRect, listenerTarget, GUIContent.none); - if (EditorGUI.EndChangeCheck()) - methodName.stringValue = null; - } - - SerializedProperty argument; - var modeEnum = GetMode(mode); - //only allow argument if we have a valid target / method - if (listenerTarget.objectReferenceValue == null || string.IsNullOrEmpty(methodName.stringValue)) - modeEnum = PersistentListenerMode.Void; - - switch (modeEnum) - { - case PersistentListenerMode.Float: - argument = arguments.FindPropertyRelative(kFloatArgument); - break; - case PersistentListenerMode.Int: - argument = arguments.FindPropertyRelative(kIntArgument); - break; - case PersistentListenerMode.Object: - argument = arguments.FindPropertyRelative(kObjectArgument); - break; - case PersistentListenerMode.String: - argument = arguments.FindPropertyRelative(kStringArgument); - break; - case PersistentListenerMode.Bool: - argument = arguments.FindPropertyRelative(kBoolArgument); - break; - default: - argument = arguments.FindPropertyRelative(kIntArgument); - break; - } - - var desiredArgTypeName = arguments.FindPropertyRelative(kObjectArgumentAssemblyTypeName).stringValue; - var desiredType = typeof(Object); - if (!string.IsNullOrEmpty(desiredArgTypeName)) - desiredType = Type.GetType(desiredArgTypeName, false) ?? typeof(Object); - - if (modeEnum == PersistentListenerMode.Object) - { - EditorGUI.BeginChangeCheck(); - var result = EditorGUI.ObjectField(argRect, GUIContent.none, argument.objectReferenceValue, desiredType, true); - if (EditorGUI.EndChangeCheck()) - argument.objectReferenceValue = result; - } - else if (modeEnum != PersistentListenerMode.Void && modeEnum != PersistentListenerMode.EventDefined) - EditorGUI.PropertyField(argRect, argument, GUIContent.none); - - using (new EditorGUI.DisabledScope(listenerTarget.objectReferenceValue == null)) - { - EditorGUI.BeginProperty(functionRect, GUIContent.none, methodName); - { - GUIContent buttonContent; - if (EditorGUI.showMixedValue) - { - buttonContent = EditorGUI.mixedValueContent; - } - else - { - var buttonLabel = new StringBuilder(); - if (listenerTarget.objectReferenceValue == null || string.IsNullOrEmpty(methodName.stringValue)) - { - buttonLabel.Append(kNoFunctionString); - } - else if (!IsPersistantListenerValid(m_DummyEvent, methodName.stringValue, listenerTarget.objectReferenceValue, GetMode(mode), desiredType)) - { - var instanceString = "UnknownComponent"; - var instance = listenerTarget.objectReferenceValue; - if (instance != null) - instanceString = instance.GetType().Name; - - buttonLabel.Append(string.Format("", instanceString, methodName.stringValue)); - } - else - { - buttonLabel.Append(listenerTarget.objectReferenceValue.GetType().Name); - - if (!string.IsNullOrEmpty(methodName.stringValue)) - { - buttonLabel.Append("."); - if (methodName.stringValue.StartsWith("set_")) - buttonLabel.Append(methodName.stringValue.Substring(4)); - else - buttonLabel.Append(methodName.stringValue); - } - } - buttonContent = GUIContent.Temp(buttonLabel.ToString()); - } - - if (GUI.Button(functionRect, buttonContent, EditorStyles.popup)) - BuildPopupList(listenerTarget.objectReferenceValue, m_DummyEvent, pListener).DropDown(functionRect); - } - EditorGUI.EndProperty(); - } - GUI.backgroundColor = c; - } - - Rect[] GetRowRects(Rect rect) - { - Rect[] rects = new Rect[4]; - - rect.height = EditorGUI.kSingleLineHeight; - rect.y += 2; - - Rect enabledRect = rect; - enabledRect.width *= 0.3f; - - Rect goRect = enabledRect; - goRect.y += EditorGUIUtility.singleLineHeight + EditorGUI.kControlVerticalSpacing; - - Rect functionRect = rect; - functionRect.xMin = goRect.xMax + EditorGUI.kSpacing; - - Rect argRect = functionRect; - argRect.y += EditorGUIUtility.singleLineHeight + EditorGUI.kControlVerticalSpacing; - - rects[0] = enabledRect; - rects[1] = goRect; - rects[2] = functionRect; - rects[3] = argRect; - return rects; - } - - void RemoveButton(ReorderableList list) - { - ReorderableList.defaultBehaviours.DoRemoveButton(list); - m_LastSelectedIndex = list.index; - } - - private void AddEventListener(ReorderableList list) - { - if (m_ListenersArray.hasMultipleDifferentValues) - { - //When increasing a multi-selection array using Serialized Property - //Data can be overwritten if there is mixed values. - //The Serialization system applies the Serialized data of one object, to all other objects in the selection. - //We handle this case here, by creating a SerializedObject for each object. - //Case 639025. - foreach (var targetObject in m_ListenersArray.serializedObject.targetObjects) - { - var temSerialziedObject = new SerializedObject(targetObject); - var listenerArrayProperty = temSerialziedObject.FindProperty(m_ListenersArray.propertyPath); - listenerArrayProperty.arraySize += 1; - temSerialziedObject.ApplyModifiedProperties(); - } - m_ListenersArray.serializedObject.SetIsDifferentCacheDirty(); - m_ListenersArray.serializedObject.Update(); - list.index = list.serializedProperty.arraySize - 1; - } - else - { - ReorderableList.defaultBehaviours.DoAddButton(list); - } - - m_LastSelectedIndex = list.index; - var pListener = m_ListenersArray.GetArrayElementAtIndex(list.index); - - var callState = pListener.FindPropertyRelative(kCallStatePath); - var listenerTarget = pListener.FindPropertyRelative(kInstancePath); - var methodName = pListener.FindPropertyRelative(kMethodNamePath); - var mode = pListener.FindPropertyRelative(kModePath); - var arguments = pListener.FindPropertyRelative(kArgumentsPath); - - callState.enumValueIndex = (int)UnityEventCallState.RuntimeOnly; - listenerTarget.objectReferenceValue = null; - methodName.stringValue = null; - mode.enumValueIndex = (int)PersistentListenerMode.Void; - arguments.FindPropertyRelative(kFloatArgument).floatValue = 0; - arguments.FindPropertyRelative(kIntArgument).intValue = 0; - arguments.FindPropertyRelative(kObjectArgument).objectReferenceValue = null; - arguments.FindPropertyRelative(kStringArgument).stringValue = null; - arguments.FindPropertyRelative(kObjectArgumentAssemblyTypeName).stringValue = null; - } - - void SelectEventListener(ReorderableList list) - { - m_LastSelectedIndex = list.index; - } - - void EndDragChild(ReorderableList list) - { - m_LastSelectedIndex = list.index; - } - - static UnityEventBase GetDummyEvent(SerializedProperty prop) - { - // Create dummy instance of this type... we need it for function validation ect - var typeName = prop.FindPropertyRelative("m_TypeName").stringValue; - Type type = Type.GetType(typeName, false); - if (type == null) - return new UnityEvent(); - return Activator.CreateInstance(type) as UnityEventBase; - } - - struct ValidMethodMap - { - public Object target; - public MethodInfo methodInfo; - public PersistentListenerMode mode; - } - - static IEnumerable CalculateMethodMap(Object target, Type[] t, bool allowSubclasses) - { - var validMethods = new List(); - if (target == null || t == null) - return validMethods; - - // find the methods on the behaviour that match the signature - Type componentType = target.GetType(); - var componentMethods = componentType.GetMethods().Where(x => !x.IsSpecialName).ToList(); - - var wantedProperties = componentType.GetProperties().AsEnumerable(); - wantedProperties = wantedProperties.Where(x => x.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length == 0 && x.GetSetMethod() != null); - componentMethods.AddRange(wantedProperties.Select(x => x.GetSetMethod())); - - foreach (var componentMethod in componentMethods) - { - //Debug.Log ("Method: " + componentMethod); - // if the argument length is not the same, no match - var componentParamaters = componentMethod.GetParameters(); - if (componentParamaters.Length != t.Length) - continue; - - // Don't show obsolete methods. - if (componentMethod.GetCustomAttributes(typeof(ObsoleteAttribute), true).Length > 0) - continue; - - if (componentMethod.ReturnType != typeof(void)) - continue; - - // if the argument types do not match, no match - bool paramatersMatch = true; - for (int i = 0; i < t.Length; i++) - { - if (!componentParamaters[i].ParameterType.IsAssignableFrom(t[i])) - paramatersMatch = false; - - if (allowSubclasses && t[i].IsAssignableFrom(componentParamaters[i].ParameterType)) - paramatersMatch = true; - } - - // valid method - if (paramatersMatch) - { - var vmm = new ValidMethodMap(); - vmm.target = target; - vmm.methodInfo = componentMethod; - validMethods.Add(vmm); - } - } - return validMethods; - } - - public static bool IsPersistantListenerValid(UnityEventBase dummyEvent, string methodName, Object uObject, PersistentListenerMode modeEnum, Type argumentType) - { - if (uObject == null || string.IsNullOrEmpty(methodName)) - return false; - - return dummyEvent.FindMethod(methodName, uObject, modeEnum, argumentType) != null; - } - - static GenericMenu BuildPopupList(Object target, UnityEventBase dummyEvent, SerializedProperty listener) - { - //special case for components... we want all the game objects targets there! - var targetToUse = target; - if (targetToUse is Component) - targetToUse = (target as Component).gameObject; - - // find the current event target... - var methodName = listener.FindPropertyRelative(kMethodNamePath); - - var menu = new GenericMenu(); - menu.AddItem(new GUIContent(kNoFunctionString), - string.IsNullOrEmpty(methodName.stringValue), - ClearEventFunction, - new UnityEventFunction(listener, null, null, PersistentListenerMode.EventDefined)); - - if (targetToUse == null) - return menu; - - menu.AddSeparator(""); - - // figure out the signature of this delegate... - // The property at this stage points to the 'container' and has the field name - Type delegateType = dummyEvent.GetType(); - - // check out the signature of invoke as this is the callback! - MethodInfo delegateMethod = delegateType.GetMethod("Invoke"); - var delegateArgumentsTypes = delegateMethod.GetParameters().Select(x => x.ParameterType).ToArray(); - - GeneratePopUpForType(menu, targetToUse, false, listener, delegateArgumentsTypes); - if (targetToUse is GameObject) - { - Component[] comps = (targetToUse as GameObject).GetComponents(); - var duplicateNames = comps.Where(c => c != null).Select(c => c.GetType().Name).GroupBy(x => x).Where(g => g.Count() > 1).Select(g => g.Key).ToList(); - foreach (Component comp in comps) - { - if (comp == null) - continue; - - GeneratePopUpForType(menu, comp, duplicateNames.Contains(comp.GetType().Name), listener, delegateArgumentsTypes); - } - } - - return menu; - } - - private static void GeneratePopUpForType(GenericMenu menu, Object target, bool useFullTargetName, SerializedProperty listener, Type[] delegateArgumentsTypes) - { - var methods = new List(); - string targetName = useFullTargetName ? target.GetType().FullName : target.GetType().Name; - - bool didAddDynamic = false; - - // skip 'void' event defined on the GUI as we have a void prebuilt type! - if (delegateArgumentsTypes.Length != 0) - { - GetMethodsForTargetAndMode(target, delegateArgumentsTypes, methods, PersistentListenerMode.EventDefined); - if (methods.Count > 0) - { - menu.AddDisabledItem(new GUIContent(targetName + "/Dynamic " + string.Join(", ", delegateArgumentsTypes.Select(e => GetTypeName(e)).ToArray()))); - AddMethodsToMenu(menu, listener, methods, targetName); - didAddDynamic = true; - } - } - - methods.Clear(); - GetMethodsForTargetAndMode(target, new[] {typeof(float)}, methods, PersistentListenerMode.Float); - GetMethodsForTargetAndMode(target, new[] {typeof(int)}, methods, PersistentListenerMode.Int); - GetMethodsForTargetAndMode(target, new[] {typeof(string)}, methods, PersistentListenerMode.String); - GetMethodsForTargetAndMode(target, new[] {typeof(bool)}, methods, PersistentListenerMode.Bool); - GetMethodsForTargetAndMode(target, new[] {typeof(Object)}, methods, PersistentListenerMode.Object); - GetMethodsForTargetAndMode(target, new Type[] {}, methods, PersistentListenerMode.Void); - if (methods.Count > 0) - { - if (didAddDynamic) - // AddSeperator doesn't seem to work for sub-menus, so we have to use this workaround instead of a proper separator for now. - menu.AddItem(new GUIContent(targetName + "/ "), false, null); - if (delegateArgumentsTypes.Length != 0) - menu.AddDisabledItem(new GUIContent(targetName + "/Static Parameters")); - AddMethodsToMenu(menu, listener, methods, targetName); - } - } - - private static void AddMethodsToMenu(GenericMenu menu, SerializedProperty listener, List methods, string targetName) - { - // Note: sorting by a bool in OrderBy doesn't seem to work for some reason, so using numbers explicitly. - IEnumerable orderedMethods = methods.OrderBy(e => e.methodInfo.Name.StartsWith("set_") ? 0 : 1).ThenBy(e => e.methodInfo.Name); - foreach (var validMethod in orderedMethods) - AddFunctionsForScript(menu, listener, validMethod, targetName); - } - - private static void GetMethodsForTargetAndMode(Object target, Type[] delegateArgumentsTypes, List methods, PersistentListenerMode mode) - { - IEnumerable newMethods = CalculateMethodMap(target, delegateArgumentsTypes, mode == PersistentListenerMode.Object); - foreach (var m in newMethods) - { - var method = m; - method.mode = mode; - methods.Add(method); - } - } - - static void AddFunctionsForScript(GenericMenu menu, SerializedProperty listener, ValidMethodMap method, string targetName) - { - PersistentListenerMode mode = method.mode; - - // find the current event target... - var listenerTarget = listener.FindPropertyRelative(kInstancePath).objectReferenceValue; - var methodName = listener.FindPropertyRelative(kMethodNamePath).stringValue; - var setMode = GetMode(listener.FindPropertyRelative(kModePath)); - var typeName = listener.FindPropertyRelative(kArgumentsPath).FindPropertyRelative(kObjectArgumentAssemblyTypeName); - - var args = new StringBuilder(); - var count = method.methodInfo.GetParameters().Length; - for (int index = 0; index < count; index++) - { - var methodArg = method.methodInfo.GetParameters()[index]; - args.Append(string.Format("{0}", GetTypeName(methodArg.ParameterType))); - - if (index < count - 1) - args.Append(", "); - } - - var isCurrentlySet = listenerTarget == method.target - && methodName == method.methodInfo.Name - && mode == setMode; - - if (isCurrentlySet && mode == PersistentListenerMode.Object && method.methodInfo.GetParameters().Length == 1) - { - isCurrentlySet &= (method.methodInfo.GetParameters()[0].ParameterType.AssemblyQualifiedName == typeName.stringValue); - } - - string path = GetFormattedMethodName(targetName, method.methodInfo.Name, args.ToString(), mode == PersistentListenerMode.EventDefined); - menu.AddItem(new GUIContent(path), - isCurrentlySet, - SetEventFunction, - new UnityEventFunction(listener, method.target, method.methodInfo, mode)); - } - - private static string GetTypeName(Type t) - { - if (t == typeof(int)) - return "int"; - if (t == typeof(float)) - return "float"; - if (t == typeof(string)) - return "string"; - if (t == typeof(bool)) - return "bool"; - return t.Name; - } - - static string GetFormattedMethodName(string targetName, string methodName, string args, bool dynamic) - { - if (dynamic) - { - if (methodName.StartsWith("set_")) - return string.Format("{0}/{1}", targetName, methodName.Substring(4)); - else - return string.Format("{0}/{1}", targetName, methodName); - } - else - { - if (methodName.StartsWith("set_")) - return string.Format("{0}/{2} {1}", targetName, methodName.Substring(4), args); - else - return string.Format("{0}/{1} ({2})", targetName, methodName, args); - } - } - - static void SetEventFunction(object source) - { - ((UnityEventFunction)source).Assign(); - } - - static void ClearEventFunction(object source) - { - ((UnityEventFunction)source).Clear(); - } - - struct UnityEventFunction - { - readonly SerializedProperty m_Listener; - readonly Object m_Target; - readonly MethodInfo m_Method; - readonly PersistentListenerMode m_Mode; - - public UnityEventFunction(SerializedProperty listener, Object target, MethodInfo method, PersistentListenerMode mode) - { - m_Listener = listener; - m_Target = target; - m_Method = method; - m_Mode = mode; - } - - public void Assign() - { - // find the current event target... - var listenerTarget = m_Listener.FindPropertyRelative(kInstancePath); - var methodName = m_Listener.FindPropertyRelative(kMethodNamePath); - var mode = m_Listener.FindPropertyRelative(kModePath); - var arguments = m_Listener.FindPropertyRelative(kArgumentsPath); - - listenerTarget.objectReferenceValue = m_Target; - methodName.stringValue = m_Method.Name; - mode.enumValueIndex = (int)m_Mode; - - if (m_Mode == PersistentListenerMode.Object) - { - var fullArgumentType = arguments.FindPropertyRelative(kObjectArgumentAssemblyTypeName); - var argParams = m_Method.GetParameters(); - if (argParams.Length == 1 && typeof(Object).IsAssignableFrom(argParams[0].ParameterType)) - fullArgumentType.stringValue = argParams[0].ParameterType.AssemblyQualifiedName; - else - fullArgumentType.stringValue = typeof(Object).AssemblyQualifiedName; - } - - ValidateObjectParamater(arguments, m_Mode); - - m_Listener.m_SerializedObject.ApplyModifiedProperties(); - } - - private void ValidateObjectParamater(SerializedProperty arguments, PersistentListenerMode mode) - { - var fullArgumentType = arguments.FindPropertyRelative(kObjectArgumentAssemblyTypeName); - var argument = arguments.FindPropertyRelative(kObjectArgument); - var argumentObj = argument.objectReferenceValue; - - if (mode != PersistentListenerMode.Object) - { - fullArgumentType.stringValue = typeof(Object).AssemblyQualifiedName; - argument.objectReferenceValue = null; - return; - } - - if (argumentObj == null) - return; - - Type t = Type.GetType(fullArgumentType.stringValue, false); - if (!typeof(Object).IsAssignableFrom(t) || !t.IsInstanceOfType(argumentObj)) - argument.objectReferenceValue = null; - } - - public void Clear() - { - // find the current event target... - var methodName = m_Listener.FindPropertyRelative(kMethodNamePath); - methodName.stringValue = null; - - var mode = m_Listener.FindPropertyRelative(kModePath); - mode.enumValueIndex = (int)PersistentListenerMode.Void; - - m_Listener.m_SerializedObject.ApplyModifiedProperties(); - } - } - } -} diff --git a/Editor/Mono/Inspector/VideoClipInspector.cs b/Editor/Mono/Inspector/VideoClipInspector.cs deleted file mode 100644 index 8185b74a71..0000000000 --- a/Editor/Mono/Inspector/VideoClipInspector.cs +++ /dev/null @@ -1,199 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Video; -using System; - -namespace UnityEditor -{ - [CustomEditor(typeof(VideoClip))] - [CanEditMultipleObjects] - internal class VideoClipInspector : Editor - { -#pragma warning disable 649 - static readonly GUID kEmptyGUID; - - private VideoClip m_PlayingClip; - private GUID m_PreviewID; - Vector2 m_Position = Vector2.zero; - - override public void OnInspectorGUI() - { - // Override with inspector that doesn't show anything - } - - static void Init() - { - } - - public void OnDisable() - { - } - - public void OnEnable() - { - } - - public void OnDestroy() - { - StopPreview(); - } - - public override bool HasPreviewGUI() - { - return (targets != null); - } - - private void PlayPreview() - { - m_PreviewID = VideoUtil.StartPreview(m_PlayingClip); - VideoUtil.PlayPreview(m_PreviewID, true); - } - - private void StopPreview() - { - if (!m_PreviewID.Empty()) - VideoUtil.StopPreview(m_PreviewID); - m_PlayingClip = null; - m_PreviewID = kEmptyGUID; - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - VideoClip clip = target as VideoClip; - - Event evt = Event.current; - if (evt.type != EventType.Repaint && - evt.type != EventType.Layout && - evt.type != EventType.Used) - { - switch (evt.type) - { - case EventType.MouseDown: - { - if (r.Contains(evt.mousePosition)) - { - if (m_PlayingClip != null) - { - if (m_PreviewID.Empty() || !VideoUtil.IsPreviewPlaying(m_PreviewID)) - { - PlayPreview(); - } - else - { - StopPreview(); - } - } - evt.Use(); - } - } - break; - } - return; - } - - bool useVideoTexture = true; - - bool needRepaint = clip != m_PlayingClip || - (!m_PreviewID.Empty() && - VideoUtil.IsPreviewPlaying(m_PreviewID)); - - if (clip != m_PlayingClip) - { - StopPreview(); - m_PlayingClip = clip; - } - - Texture image = null; - - if (!m_PreviewID.Empty()) - image = VideoUtil.GetPreviewTexture(m_PreviewID); - - if (image == null || image.width == 0 || image.height == 0) - { - image = GetAssetPreviewTexture(); - useVideoTexture = false; - } - - if (image == null || image.width == 0 || image.height == 0) - return; - - if (Event.current.type == EventType.Repaint) - background.Draw(r, false, false, false, false); - - float previewWidth = image.width; - float previewHeight = image.height; - - if (m_PlayingClip.pixelAspectRatioDenominator > 0) - previewWidth *= (float)m_PlayingClip.pixelAspectRatioNumerator / - (float)m_PlayingClip.pixelAspectRatioDenominator; - - float zoomLevel = 1.0f; - - if ((r.width / previewWidth * previewHeight) > r.height) - zoomLevel = r.height / previewHeight; - else - zoomLevel = r.width / previewWidth; - - zoomLevel = Mathf.Clamp01(zoomLevel); - - Rect wantedRect = useVideoTexture ? new Rect(r.x, r.y, previewWidth * zoomLevel, image.height * zoomLevel) : r; - - PreviewGUI.BeginScrollView( - r, m_Position, wantedRect, "PreHorizontalScrollbar", "PreHorizontalScrollbarThumb"); - - if (useVideoTexture) - EditorGUI.DrawTextureTransparent(wantedRect, image, ScaleMode.StretchToFill); - else - GUI.DrawTexture(wantedRect, image, ScaleMode.ScaleToFit); - - m_Position = PreviewGUI.EndScrollView(); - - if (needRepaint) - GUIView.current.Repaint(); - } - - Texture GetAssetPreviewTexture() - { - Texture tex = null; - bool isLoadingAssetPreview = AssetPreview.IsLoadingAssetPreview(target.GetInstanceID()); - tex = AssetPreview.GetAssetPreview(target); - if (!tex) - { - // We have a static preview it just hasn't been loaded yet. Repaint until we have it loaded. - if (isLoadingAssetPreview) - GUIView.current.Repaint(); - tex = AssetPreview.GetMiniThumbnail(target); - } - return tex; - } - - internal override void OnHeaderIconGUI(Rect iconRect) - { - GUI.DrawTexture(iconRect, GetAssetPreviewTexture(), ScaleMode.StretchToFill); - } - - public override string GetInfoString() - { - VideoClip clip = target as VideoClip; - var frameCount = clip.frameCount; - var frameRate = clip.frameRate; - - var duration = frameRate > 0 - ? TimeSpan.FromSeconds(frameCount / frameRate).ToString() - : new TimeSpan(0).ToString(); - - // TimeSpan uses 7 digits for fractional seconds. Limit this to 3 digits. - if (duration.IndexOf('.') != -1) - duration = duration.Substring(0, duration.Length - 4); - - string s = duration; - s += ", " + frameCount.ToString() + " frames"; - s += ", " + frameRate.ToString("F2") + " FPS"; - s += ", " + clip.width.ToString() + "x" + clip.height.ToString(); - return s; - } - } -} diff --git a/Editor/Mono/Inspector/VideoPlayerEditor.cs b/Editor/Mono/Inspector/VideoPlayerEditor.cs deleted file mode 100644 index 19a1cb31de..0000000000 --- a/Editor/Mono/Inspector/VideoPlayerEditor.cs +++ /dev/null @@ -1,683 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using UnityEditor.AnimatedValues; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text.RegularExpressions; -using UnityEngine.Video; -using UnityEditor.Build; - -namespace UnityEditor -{ - [CustomEditor(typeof(VideoPlayer))] - [CanEditMultipleObjects] - internal class VideoPlayerEditor : Editor - { - class Styles - { - public GUIContent dataSourceContent = - EditorGUIUtility.TrTextContent("Source", "Type of source the movie will be read from."); - public GUIContent videoClipContent = - EditorGUIUtility.TrTextContent("Video Clip", "VideoClips can be imported using the asset pipeline."); - public GUIContent urlContent = - EditorGUIUtility.TrTextContent("URL", "URLs can be http:// or file://. File URLs can be relative [file://] or absolute [file:///]. For file URLs, the prefix is optional."); - public GUIContent browseContent = EditorGUIUtility.TrTextContent("Browse...", "Click to set a file:// URL. http:// URLs have to be written or copy-pasted manually."); - public GUIContent playOnAwakeContent = - EditorGUIUtility.TrTextContent("Play On Awake", "Start playback as soon as the game is started."); - public GUIContent waitForFirstFrameContent = - EditorGUIUtility.TrTextContent("Wait For First Frame", "Wait for first frame to be ready before starting playback. When on, player time will only start increasing when the first image is ready. When off, the first few frames may be skipped while clip preparation is ongoing."); - public GUIContent loopContent = - EditorGUIUtility.TrTextContent("Loop", "Start playback at the beginning when end is reached."); - public GUIContent playbackSpeedContent = - EditorGUIUtility.TrTextContent("Playback Speed", "Increase or decrease the playback speed. 1.0 is the normal speed."); - public GUIContent renderModeContent = - EditorGUIUtility.TrTextContent("Render Mode", "Type of object on which the played images will be drawn."); - public GUIContent cameraContent = - EditorGUIUtility.TrTextContent("Camera", "Camera where the images will be drawn, behind (Back Plane) or in front of (Front Plane) of the scene."); - public GUIContent textureContent = - EditorGUIUtility.TrTextContent("Target Texture", "RenderTexture where the images will be drawn. RenderTextures can be created under the Assets folder and the used on other objects."); - public GUIContent alphaContent = - EditorGUIUtility.TrTextContent("Alpha", "A value less than 1.0 will reveal the content behind the video."); - public GUIContent camera3DLayout = - EditorGUIUtility.TrTextContent("3D Layout", "Layout of 3D content in the source video."); - public GUIContent audioOutputModeContent = - EditorGUIUtility.TrTextContent("Audio Output Mode", "Where the audio in the movie will be output."); - public GUIContent audioSourceContent = - EditorGUIUtility.TrTextContent("Audio Source", "AudioSource component that will receive this track's audio samples."); - public GUIContent aspectRatioLabel = EditorGUIUtility.TrTextContent("Aspect Ratio"); - public GUIContent muteLabel = EditorGUIUtility.TrTextContent("Mute"); - public GUIContent volumeLabel = EditorGUIUtility.TrTextContent("Volume"); - public GUIContent controlledAudioTrackCountContent = EditorGUIUtility.TextContent( - "Controlled Tracks|How many audio tracks will the player control. The actual number of tracks is only known during playback when the source is a URL."); - public GUIContent materialRendererContent = EditorGUIUtility.TextContent( - "Renderer|Renderer that will receive the images. Defaults to the first renderer on the game object."); - public GUIContent materialPropertyContent = EditorGUIUtility.TextContent( - "Material Property|Texture property of the current Material that will receive the images."); - - public string selectUniformVideoSourceHelp = - "Select a uniform video source type before a video clip or URL can be selected."; - public string rendererMaterialsHaveNoTexPropsHelp = - "Renderer materials have no texture properties."; - public string someRendererMaterialsHaveNoTexPropsHelp = - "Some selected renderers have materials with no texture properties."; - public string invalidTexPropSelectionHelp = - "Invalid texture property selection."; - public string oneInvalidTexPropSelectionHelp = - "1 selected object has an invalid texture property selection."; - public string someInvalidTexPropSelectionsHelp = - "{0} selected objects have invalid texture property selections."; - public string texPropInAllMaterialsHelp = - "Texture property appears in all renderer materials."; - public string texPropInSomeMaterialsHelp = - "Texture property appears in {0} out of {1} renderer materials."; - public string selectUniformVideoRenderModeHelp = - "Select a uniform video render mode type before a target camera, render texture or material parameter can be selected."; - public string selectUniformAudioOutputModeHelp = - "Select a uniform audio target before audio settings can be edited."; - public string selectUniformAudioTracksHelp = - "Only sources with the same number of audio tracks can be edited during multi-selection."; - public string selectMovieFile = "Select movie file."; - public string audioControlsNotEditableHelp = - "Audio controls not editable when using muliple selection."; - public string enableDecodingTooltip = - "Enable decoding for this track. Only effective when not playing. When playing from a URL, track details are shown only while playing back."; - } - - internal class AudioTrackInfo - { - public AudioTrackInfo() - { - language = ""; - channelCount = 0; - } - - public string language; - public ushort channelCount; - public GUIContent content; - } - - static Styles s_Styles; - - SerializedProperty m_DataSource; - SerializedProperty m_VideoClip; - SerializedProperty m_Url; - SerializedProperty m_PlayOnAwake; - SerializedProperty m_WaitForFirstFrame; - SerializedProperty m_Looping; - SerializedProperty m_PlaybackSpeed; - SerializedProperty m_RenderMode; - SerializedProperty m_TargetTexture; - SerializedProperty m_TargetCamera; - SerializedProperty m_TargetMaterialRenderer; - SerializedProperty m_TargetMaterialProperty; - SerializedProperty m_AspectRatio; - SerializedProperty m_TargetCameraAlpha; - SerializedProperty m_TargetCamera3DLayout; - SerializedProperty m_AudioOutputMode; - SerializedProperty m_ControlledAudioTrackCount; - SerializedProperty m_EnabledAudioTracks; - SerializedProperty m_TargetAudioSources; - SerializedProperty m_DirectAudioVolumes; - SerializedProperty m_DirectAudioMutes; - - readonly AnimBool m_ShowRenderTexture = new AnimBool(); - readonly AnimBool m_ShowTargetCamera = new AnimBool(); - readonly AnimBool m_ShowRenderer = new AnimBool(); - readonly AnimBool m_ShowMaterialProperty = new AnimBool(); - readonly AnimBool m_DataSourceIsClip = new AnimBool(); - readonly AnimBool m_ShowAspectRatio = new AnimBool(); - readonly AnimBool m_ShowAudioControls = new AnimBool(); - - ushort m_AudioTrackCountCached = 0; - GUIContent m_ControlledAudioTrackCountContent; - List m_AudioTrackInfos; - - int m_MaterialPropertyPopupContentHash; - GUIContent[] m_MaterialPropertyPopupContent; - int m_MaterialPropertyPopupSelection, m_MaterialPropertyPopupInvalidSelections; - string m_MultiMaterialInfo = null; - - void OnEnable() - { - m_ShowRenderTexture.valueChanged.AddListener(Repaint); - m_ShowTargetCamera.valueChanged.AddListener(Repaint); - m_ShowRenderer.valueChanged.AddListener(Repaint); - m_ShowMaterialProperty.valueChanged.AddListener(Repaint); - m_DataSourceIsClip.valueChanged.AddListener(Repaint); - m_ShowAspectRatio.valueChanged.AddListener(Repaint); - m_ShowAudioControls.valueChanged.AddListener(Repaint); - - m_DataSource = serializedObject.FindProperty("m_DataSource"); - m_VideoClip = serializedObject.FindProperty("m_VideoClip"); - m_Url = serializedObject.FindProperty("m_Url"); - m_PlayOnAwake = serializedObject.FindProperty("m_PlayOnAwake"); - m_WaitForFirstFrame = serializedObject.FindProperty("m_WaitForFirstFrame"); - m_Looping = serializedObject.FindProperty("m_Looping"); - m_PlaybackSpeed = serializedObject.FindProperty("m_PlaybackSpeed"); - m_RenderMode = serializedObject.FindProperty("m_RenderMode"); - m_TargetTexture = serializedObject.FindProperty("m_TargetTexture"); - m_TargetCamera = serializedObject.FindProperty("m_TargetCamera"); - m_TargetMaterialRenderer = serializedObject.FindProperty("m_TargetMaterialRenderer"); - m_TargetMaterialProperty = serializedObject.FindProperty("m_TargetMaterialProperty"); - m_AspectRatio = serializedObject.FindProperty("m_AspectRatio"); - m_TargetCameraAlpha = serializedObject.FindProperty("m_TargetCameraAlpha"); - m_TargetCamera3DLayout = serializedObject.FindProperty("m_TargetCamera3DLayout"); - m_AudioOutputMode = serializedObject.FindProperty("m_AudioOutputMode"); - m_ControlledAudioTrackCount = serializedObject.FindProperty("m_ControlledAudioTrackCount"); - m_EnabledAudioTracks = serializedObject.FindProperty("m_EnabledAudioTracks"); - m_TargetAudioSources = serializedObject.FindProperty("m_TargetAudioSources"); - m_DirectAudioVolumes = serializedObject.FindProperty("m_DirectAudioVolumes"); - m_DirectAudioMutes = serializedObject.FindProperty("m_DirectAudioMutes"); - - m_ShowRenderTexture.value = m_RenderMode.intValue == (int)VideoRenderMode.RenderTexture; - m_ShowTargetCamera.value = - m_RenderMode.intValue == (int)VideoRenderMode.CameraFarPlane || - m_RenderMode.intValue == (int)VideoRenderMode.CameraNearPlane; - - m_ShowRenderer.value = m_RenderMode.intValue == (int)VideoRenderMode.MaterialOverride; - m_MaterialPropertyPopupContent = BuildPopupEntries(targets, GetMaterialPropertyNames, out m_MaterialPropertyPopupSelection, out m_MaterialPropertyPopupInvalidSelections); - m_MaterialPropertyPopupContentHash = GetMaterialPropertyPopupHash(targets); - m_ShowMaterialProperty.value = - targets.Count() > 1 || (m_MaterialPropertyPopupSelection >= 0 && m_MaterialPropertyPopupContent.Length > 0); - - m_DataSourceIsClip.value = m_DataSource.intValue == (int)VideoSource.VideoClip; - m_ShowAspectRatio.value = (m_RenderMode.intValue != (int)VideoRenderMode.MaterialOverride) && - (m_RenderMode.intValue != (int)VideoRenderMode.APIOnly); - m_ShowAudioControls.value = m_AudioOutputMode.intValue != (int)VideoAudioOutputMode.None; - VideoPlayer vp = target as VideoPlayer; - vp.prepareCompleted += PrepareCompleted; - - m_AudioTrackInfos = new List(); - } - - void OnDisable() - { - m_ShowRenderTexture.valueChanged.RemoveListener(Repaint); - m_ShowTargetCamera.valueChanged.RemoveListener(Repaint); - m_ShowRenderer.valueChanged.RemoveListener(Repaint); - m_ShowMaterialProperty.valueChanged.RemoveListener(Repaint); - m_DataSourceIsClip.valueChanged.RemoveListener(Repaint); - m_ShowAspectRatio.valueChanged.RemoveListener(Repaint); - m_ShowAudioControls.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - if (s_Styles == null) - s_Styles = new Styles(); - - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_DataSource, s_Styles.dataSourceContent); - HandleDataSourceField(); - EditorGUILayout.PropertyField(m_PlayOnAwake, s_Styles.playOnAwakeContent); - EditorGUILayout.PropertyField(m_WaitForFirstFrame, s_Styles.waitForFirstFrameContent); - EditorGUILayout.PropertyField(m_Looping, s_Styles.loopContent); - EditorGUILayout.Slider(m_PlaybackSpeed, 0.0f, 10.0f, s_Styles.playbackSpeedContent); - EditorGUILayout.Space(); - - EditorGUILayout.PropertyField(m_RenderMode, s_Styles.renderModeContent); - if (m_RenderMode.hasMultipleDifferentValues) - { - EditorGUILayout.HelpBox(s_Styles.selectUniformVideoRenderModeHelp, MessageType.Warning, false); - } - else - { - VideoRenderMode currentRenderMode = (VideoRenderMode)m_RenderMode.intValue; - HandleTargetField(currentRenderMode); - } - HandleAudio(); - - serializedObject.ApplyModifiedProperties(); - } - - private void HandleDataSourceField() - { - m_DataSourceIsClip.target = m_DataSource.intValue == (int)VideoSource.VideoClip; - if (m_DataSource.hasMultipleDifferentValues) - EditorGUILayout.HelpBox(s_Styles.selectUniformVideoSourceHelp, MessageType.Warning, false); - else if (EditorGUILayout.BeginFadeGroup(m_DataSourceIsClip.faded)) - EditorGUILayout.PropertyField(m_VideoClip, s_Styles.videoClipContent); - else - { - EditorGUILayout.PropertyField(m_Url, s_Styles.urlContent); - Rect browseRect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight); - browseRect.xMin += EditorGUIUtility.labelWidth; - browseRect.xMax = browseRect.xMin + GUI.skin.label.CalcSize(s_Styles.browseContent).x + 10; - if (EditorGUI.DropdownButton( - browseRect, s_Styles.browseContent, FocusType.Passive, GUISkin.current.button)) - { - string[] filter = - { - // FIXME: Array should come from the player. - "Movie files", "dv,mp4,mpg,mpeg,m4v,ogv,vp8,webm", - "All files", "*" - }; - - string path = EditorUtility.OpenFilePanelWithFilters( - s_Styles.selectMovieFile, "", filter); - if (!string.IsNullOrEmpty(path)) - m_Url.stringValue = "file://" + path; - } - } - - EditorGUILayout.EndFadeGroup(); - } - - private static int GetMaterialPropertyPopupHash(UnityEngine.Object[] objects) - { - int hash = 0; - foreach (VideoPlayer vp in objects) - { - if (!vp) - continue; - Renderer renderer = GetTargetRenderer(vp); - if (!renderer) - continue; - - hash ^= vp.targetMaterialProperty.GetHashCode(); - foreach (Material material in renderer.sharedMaterials) - { - if (!material) - continue; - hash ^= material.name.GetHashCode(); - for (int i = 0, e = ShaderUtil.GetPropertyCount(material.shader); i < e; ++i) - { - if (ShaderUtil.GetPropertyType(material.shader, i) == ShaderUtil.ShaderPropertyType.TexEnv) - hash ^= ShaderUtil.GetPropertyName(material.shader, i).GetHashCode(); - } - } - } - return hash; - } - - private static List GetMaterialPropertyNames(UnityEngine.Object obj, bool multiSelect, out int selection, out bool invalidSelection) - { - selection = -1; - invalidSelection = true; - List properties = new List(); - VideoPlayer vp = obj as VideoPlayer; - if (!vp) - return properties; - - Renderer renderer = GetTargetRenderer(vp); - if (!renderer) - return properties; - - foreach (Material material in renderer.sharedMaterials) - { - if (material) - { - for (int i = 0, e = ShaderUtil.GetPropertyCount(material.shader); i < e; ++i) - { - if (ShaderUtil.GetPropertyType(material.shader, i) == ShaderUtil.ShaderPropertyType.TexEnv) - { - string propertyName = ShaderUtil.GetPropertyName(material.shader, i); - if (!properties.Contains(propertyName)) - properties.Add(propertyName); - } - } - selection = properties.IndexOf(vp.targetMaterialProperty); - invalidSelection = selection < 0 && properties.Count() > 0; - if (invalidSelection && !multiSelect) - { - selection = properties.Count(); - properties.Add(vp.targetMaterialProperty); - } - } - } - return properties; - } - - private delegate List EntryGenerator(UnityEngine.Object obj, bool multiSelect, out int selection, out bool invalidSelection); - private static GUIContent[] BuildPopupEntries(UnityEngine.Object[] objects, EntryGenerator func, out int selection, out int invalidSelections) - { - selection = -1; - invalidSelections = 0; - List entries = null; - foreach (UnityEngine.Object o in objects) - { - int newSelection; - bool invalidSelection; - List newEntries = func(o, objects.Count() > 1, out newSelection, out invalidSelection); - if (newEntries != null) - { - if (invalidSelection) - ++invalidSelections; - List mergedEntries = - entries == null ? newEntries : new List(entries.Intersect(newEntries)); - selection = entries == null ? newSelection : selection < 0 || newSelection < 0 || entries[selection] != newEntries[newSelection] ? -1 : mergedEntries.IndexOf(entries[selection]); - entries = mergedEntries; - } - } - if (entries == null) - entries = new List(); - return entries.Select(x => new GUIContent(x)).ToArray(); - } - - private static void HandlePopup(GUIContent content, SerializedProperty property, GUIContent[] entries, int selection) - { - Rect pos = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight); - GUIContent label = EditorGUI.BeginProperty(pos, content, property); - EditorGUI.BeginChangeCheck(); - EditorGUI.BeginDisabledGroup(entries.Count() == 0); - selection = EditorGUI.Popup(pos, label, selection, entries); - EditorGUI.EndDisabledGroup(); - if (EditorGUI.EndChangeCheck()) - property.stringValue = entries[selection].text; - EditorGUI.EndProperty(); - } - - private void HandleTargetField(VideoRenderMode currentRenderMode) - { - m_ShowRenderTexture.target = currentRenderMode == VideoRenderMode.RenderTexture; - if (EditorGUILayout.BeginFadeGroup(m_ShowRenderTexture.faded)) - EditorGUILayout.PropertyField(m_TargetTexture, s_Styles.textureContent); - EditorGUILayout.EndFadeGroup(); - - m_ShowTargetCamera.target = (currentRenderMode == VideoRenderMode.CameraFarPlane) || - (currentRenderMode == VideoRenderMode.CameraNearPlane); - if (EditorGUILayout.BeginFadeGroup(m_ShowTargetCamera.faded)) - { - EditorGUILayout.PropertyField(m_TargetCamera, s_Styles.cameraContent); - EditorGUILayout.Slider(m_TargetCameraAlpha, 0.0f, 1.0f, s_Styles.alphaContent); - // If VR is enabled in PlayerSettings on ANY platform, show the 3D layout option - foreach (BuildPlatform cur in BuildPlatforms.instance.buildPlatforms) - { - if (UnityEditorInternal.VR.VREditor.GetVREnabledOnTargetGroup(cur.targetGroup)) - { - EditorGUILayout.PropertyField(m_TargetCamera3DLayout, s_Styles.camera3DLayout); - break; - } - } - } - EditorGUILayout.EndFadeGroup(); - - m_ShowRenderer.target = currentRenderMode == VideoRenderMode.MaterialOverride; - if (EditorGUILayout.BeginFadeGroup(m_ShowRenderer.faded)) - { - bool hasMultipleSelection = targets.Count() > 1; - if (hasMultipleSelection) - EditorGUILayout.PropertyField(m_TargetMaterialRenderer, s_Styles.materialRendererContent); - else - { - Rect rect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight); - GUIContent label = EditorGUI.BeginProperty( - rect, s_Styles.materialRendererContent, m_TargetMaterialRenderer); - EditorGUI.BeginChangeCheck(); - var newRenderer = EditorGUI.ObjectField( - rect, label, GetTargetRenderer((VideoPlayer)target), typeof(Renderer), true); - if (EditorGUI.EndChangeCheck()) - m_TargetMaterialRenderer.objectReferenceValue = newRenderer; - EditorGUI.EndProperty(); - } - - int curHash = GetMaterialPropertyPopupHash(targets); - if (m_MaterialPropertyPopupContentHash != curHash) - m_MaterialPropertyPopupContent = BuildPopupEntries( - targets, GetMaterialPropertyNames, out m_MaterialPropertyPopupSelection, - out m_MaterialPropertyPopupInvalidSelections); - HandlePopup(s_Styles.materialPropertyContent, m_TargetMaterialProperty, m_MaterialPropertyPopupContent, m_MaterialPropertyPopupSelection); - if (m_MaterialPropertyPopupInvalidSelections > 0 || m_MaterialPropertyPopupContent.Length == 0) - { - GUILayout.BeginHorizontal(); - GUILayout.Space(EditorGUIUtility.labelWidth); - if (m_MaterialPropertyPopupContent.Length == 0) - { - if (!hasMultipleSelection) - EditorGUILayout.HelpBox(s_Styles.rendererMaterialsHaveNoTexPropsHelp, MessageType.Warning); - else - EditorGUILayout.HelpBox(s_Styles.someRendererMaterialsHaveNoTexPropsHelp, MessageType.Warning); - } - else if (!hasMultipleSelection) - EditorGUILayout.HelpBox(s_Styles.invalidTexPropSelectionHelp, MessageType.Warning); - else if (m_MaterialPropertyPopupInvalidSelections == 1) - EditorGUILayout.HelpBox(s_Styles.oneInvalidTexPropSelectionHelp, MessageType.Warning); - else - EditorGUILayout.HelpBox( - string.Format(s_Styles.someInvalidTexPropSelectionsHelp, m_MaterialPropertyPopupInvalidSelections), - MessageType.Warning); - GUILayout.EndHorizontal(); - } - else - DisplayMultiMaterialInformation(m_MaterialPropertyPopupContentHash != curHash); - - m_MaterialPropertyPopupContentHash = curHash; - } - EditorGUILayout.EndFadeGroup(); - - m_ShowAspectRatio.target = - currentRenderMode != VideoRenderMode.MaterialOverride && - currentRenderMode != VideoRenderMode.APIOnly; - if (EditorGUILayout.BeginFadeGroup(m_ShowAspectRatio.faded)) - EditorGUILayout.PropertyField(m_AspectRatio, s_Styles.aspectRatioLabel); - EditorGUILayout.EndFadeGroup(); - } - - private void DisplayMultiMaterialInformation(bool refreshInfo) - { - if (refreshInfo || m_MultiMaterialInfo == null) - m_MultiMaterialInfo = GenerateMultiMaterialinformation(); - - if (string.IsNullOrEmpty(m_MultiMaterialInfo)) - return; - - GUILayout.BeginHorizontal(); - GUILayout.Space(EditorGUIUtility.labelWidth); - EditorGUILayout.HelpBox(m_MultiMaterialInfo, MessageType.Info); - GUILayout.EndHorizontal(); - } - - private string GenerateMultiMaterialinformation() - { - if (targets.Count() > 1) - return ""; - - VideoPlayer vp = target as VideoPlayer; - if (!vp) - return ""; - - Renderer renderer = GetTargetRenderer(vp); - if (!renderer) - return ""; - - var sharedMaterials = renderer.sharedMaterials; - if (sharedMaterials == null || sharedMaterials.Count() <= 1) - return ""; - - var targetMaterials = new List(); - - foreach (Material material in sharedMaterials) - { - if (!material) - continue; - for (int i = 0, e = ShaderUtil.GetPropertyCount(material.shader); i < e; ++i) - { - if ((ShaderUtil.GetPropertyType(material.shader, i) == - ShaderUtil.ShaderPropertyType.TexEnv) && - (ShaderUtil.GetPropertyName(material.shader, i) == - m_TargetMaterialProperty.stringValue)) - { - targetMaterials.Add(material.name); - break; - } - } - } - - if (targetMaterials.Count() == sharedMaterials.Count()) - return s_Styles.texPropInAllMaterialsHelp; - - return string.Format( - s_Styles.texPropInSomeMaterialsHelp, - targetMaterials.Count(), sharedMaterials.Count()) + ": " + - string.Join(", ", targetMaterials.ToArray()); - } - - private void HandleAudio() - { - EditorGUILayout.Space(); - EditorGUILayout.PropertyField(m_AudioOutputMode, s_Styles.audioOutputModeContent); - - m_ShowAudioControls.target = (VideoAudioOutputMode)m_AudioOutputMode.intValue != VideoAudioOutputMode.None; - if (EditorGUILayout.BeginFadeGroup(m_ShowAudioControls.faded)) - { - // FIXME: Due to a bug in the behaviour of the widgets used in - // this multi-selection-capable code, we are disabling - // multi-select editing for now. The array of widgets being - // constructed ends up being garbled (no crash, just incorrect - // content). After discussing with @shawn, it was agreed to - // handle this bug separately and disable multi-editing here for - // the time being. - if (serializedObject.isEditingMultipleObjects) - EditorGUILayout.HelpBox(s_Styles.audioControlsNotEditableHelp, MessageType.Warning, false); - else if (m_AudioOutputMode.hasMultipleDifferentValues) - EditorGUILayout.HelpBox(s_Styles.selectUniformAudioOutputModeHelp, MessageType.Warning, false); - else - { - ushort trackCountBefore = (ushort)m_ControlledAudioTrackCount.intValue; - HandleControlledAudioTrackCount(); - if (m_ControlledAudioTrackCount.hasMultipleDifferentValues) - EditorGUILayout.HelpBox(s_Styles.selectUniformAudioTracksHelp, MessageType.Warning, false); - else - { - VideoAudioOutputMode audioOutputMode = (VideoAudioOutputMode)m_AudioOutputMode.intValue; - - // VideoPlayer::CheckConsistency keeps the array sizes in - // sync with the (possible) change done in - // HandleControlledAudioTrackCount(). But this adjustment is - // only done later so we conservatively only iterate over the - // smallest known number of tracks we know are initialized. - ushort trackCount = (ushort)Math.Min( - (ushort)m_ControlledAudioTrackCount.intValue, trackCountBefore); - trackCount = (ushort)Math.Min(trackCount, m_EnabledAudioTracks.arraySize); - - for (ushort trackIdx = 0; trackIdx < trackCount; ++trackIdx) - { - EditorGUILayout.PropertyField( - m_EnabledAudioTracks.GetArrayElementAtIndex(trackIdx), - GetAudioTrackEnabledContent(trackIdx)); - - EditorGUI.indentLevel++; - if (audioOutputMode == VideoAudioOutputMode.AudioSource) - { - EditorGUILayout.PropertyField( - m_TargetAudioSources.GetArrayElementAtIndex(trackIdx), - s_Styles.audioSourceContent); - } - else if (audioOutputMode == VideoAudioOutputMode.Direct) - { - EditorGUILayout.PropertyField( - m_DirectAudioMutes.GetArrayElementAtIndex(trackIdx), - s_Styles.muteLabel); - EditorGUILayout.Slider( - m_DirectAudioVolumes.GetArrayElementAtIndex(trackIdx), 0.0f, 1.0f, - s_Styles.volumeLabel); - } - EditorGUI.indentLevel--; - } - } - } - } - EditorGUILayout.EndFadeGroup(); - } - - GUIContent GetAudioTrackEnabledContent(ushort trackIdx) - { - while (m_AudioTrackInfos.Count <= trackIdx) - m_AudioTrackInfos.Add(new AudioTrackInfo()); - - AudioTrackInfo info = m_AudioTrackInfos[trackIdx]; - - VideoPlayer player = null; - if (!serializedObject.isEditingMultipleObjects) - player = (VideoPlayer)target; - - // Only produce a decorated track label with single-selection. No - // point trying to come up with a label that makes the average of - // the current track params... - string language = player ? player.GetAudioLanguageCode(trackIdx) : ""; - ushort channelCount = player ? player.GetAudioChannelCount(trackIdx) : (ushort)0; - - if (language != info.language || channelCount != info.channelCount || info.content == null) - { - string trackDetails = ""; - if (language.Length > 0) - trackDetails += language; - - if (channelCount > 0) - { - if (trackDetails.Length > 0) - trackDetails += ", "; - trackDetails += channelCount.ToString() + " ch"; - } - - if (trackDetails.Length > 0) - trackDetails = " [" + trackDetails + "]"; - - info.content = EditorGUIUtility.TextContent("Track " + trackIdx + trackDetails); - info.content.tooltip = s_Styles.enableDecodingTooltip; - } - - return info.content; - } - - private void HandleControlledAudioTrackCount() - { - // Won't show the widget for number of controlled tracks if we're - // just using VideoClips (for which editing this property doesn't - // make sense) or mixing VideoClips and URLs. - if (m_DataSourceIsClip.value || m_DataSource.hasMultipleDifferentValues) - return; - - VideoPlayer player = (VideoPlayer)target; - ushort audioTrackCount = serializedObject.isEditingMultipleObjects ? (ushort)0 : player.audioTrackCount; - GUIContent controlledAudioTrackCountContent; - if (audioTrackCount == 0) - { - // Use the simple undecorated label (without number of existing tracks) - // when editing multiple objects so we don't need fancy logic - // to explain that the number of discovered tracks is not uniform - // across multi-selection. - controlledAudioTrackCountContent = s_Styles.controlledAudioTrackCountContent; - } - else - { - // Manage a cached decorated GUIContent where we show how many - // existing tracks there are in the URL being played. Doing - // this to avoid repeatedly construct this string. - if (audioTrackCount != m_AudioTrackCountCached) - { - m_AudioTrackCountCached = audioTrackCount; - m_ControlledAudioTrackCountContent = EditorGUIUtility.TextContent( - s_Styles.controlledAudioTrackCountContent.text + " [" + audioTrackCount + " found]"); - m_ControlledAudioTrackCountContent.tooltip = s_Styles.controlledAudioTrackCountContent.tooltip; - } - controlledAudioTrackCountContent = m_ControlledAudioTrackCountContent; - } - - EditorGUILayout.PropertyField(m_ControlledAudioTrackCount, controlledAudioTrackCountContent); - } - - private void PrepareCompleted(VideoPlayer vp) - { - Repaint(); - } - - static private Renderer GetTargetRenderer(VideoPlayer vp) - { - Renderer renderer = vp.targetMaterialRenderer; - if (renderer) - return renderer; - return vp.gameObject.GetComponent(); - } - } -} - diff --git a/Editor/Mono/Inspector/WebCamTextureInspector.cs b/Editor/Mono/Inspector/WebCamTextureInspector.cs deleted file mode 100644 index b1a8334e4a..0000000000 --- a/Editor/Mono/Inspector/WebCamTextureInspector.cs +++ /dev/null @@ -1,107 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - [CustomEditor(typeof(WebCamTexture))] - internal class WebCamTextureInspector : Editor - { - static GUIContent[] s_PlayIcons = {null, null}; - Vector2 m_Pos; - - public override void OnInspectorGUI() - { - WebCamTexture t = target as WebCamTexture; - EditorGUILayout.LabelField("Requested FPS", t.requestedFPS.ToString()); - EditorGUILayout.LabelField("Requested Width", t.requestedWidth.ToString()); - EditorGUILayout.LabelField("Requested Height", t.requestedHeight.ToString()); - EditorGUILayout.LabelField("Device Name", t.deviceName); - } - - static void Init() - { - s_PlayIcons[0] = EditorGUIUtility.IconContent("preAudioPlayOff"); - s_PlayIcons[1] = EditorGUIUtility.IconContent("preAudioPlayOn"); - } - - public override bool HasPreviewGUI() - { - return (target != null); - } - - public override void OnPreviewSettings() - { - Init(); - - // Disallow playing movie previews in play mode. Better not to interfere - // with any playback the game does. - GUI.enabled = !Application.isPlaying; - WebCamTexture t = target as WebCamTexture; - bool isPlaying = PreviewGUI.CycleButton(t.isPlaying ? 1 : 0, s_PlayIcons) != 0; - if (isPlaying != t.isPlaying) - { - if (isPlaying) - { - t.Stop(); - t.Play(); - } - else - { - t.Pause(); - } - } - GUI.enabled = true; - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (Event.current.type == EventType.Repaint) - background.Draw(r, false, false, false, false); - - // show texture - WebCamTexture t = target as WebCamTexture; - - float zoomLevel = Mathf.Min(Mathf.Min(r.width / t.width, r.height / t.height), 1); - Rect wantedRect = new Rect(r.x, r.y, t.width * zoomLevel, t.height * zoomLevel); - PreviewGUI.BeginScrollView(r, m_Pos, wantedRect, "PreHorizontalScrollbar", "PreHorizontalScrollbarThumb"); - GUI.DrawTexture(wantedRect, t, ScaleMode.StretchToFill, false); - m_Pos = PreviewGUI.EndScrollView(); - - // force update GUI - if (t.isPlaying) - GUIView.current.Repaint(); - - if (Application.isPlaying) - { - if (t.isPlaying) - EditorGUI.DropShadowLabel(new Rect(r.x, r.y + 10, r.width, 20), "Can't pause preview when in play mode"); - else - EditorGUI.DropShadowLabel(new Rect(r.x, r.y + 10, r.width, 20), "Can't start preview when in play mode"); - } - } - - public void OnDisable() - { - WebCamTexture t = target as WebCamTexture; - - //stop the camera if we started it - if (!Application.isPlaying && t != null) - { - t.Stop(); - } - } - - public override string GetInfoString() - { - Texture t = target as Texture; - string info = t.width.ToString() + "x" + t.height.ToString(); - TextureFormat format = TextureUtil.GetTextureFormat(t); - info += " " + TextureUtil.GetTextureFormatString(format); - return info; - } - } -} diff --git a/Editor/Mono/Inspector/WheelColliderEditor.cs b/Editor/Mono/Inspector/WheelColliderEditor.cs deleted file mode 100644 index 9a8876b770..0000000000 --- a/Editor/Mono/Inspector/WheelColliderEditor.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(WheelCollider))] - [CanEditMultipleObjects] - internal class WheelColliderEditor : Editor - { - SerializedProperty m_Center; - SerializedProperty m_Radius; - SerializedProperty m_SuspensionDistance; - SerializedProperty m_SuspensionSpring; - SerializedProperty m_ForceAppPointDistance; - SerializedProperty m_Mass; - SerializedProperty m_WheelDampingRate; - SerializedProperty m_ForwardFriction; - SerializedProperty m_SidewaysFriction; - - public void OnEnable() - { - // Wheel Collider does not serialize Collider properties, so we don't use base OnEnable like other collider types - m_Center = serializedObject.FindProperty("m_Center"); - m_Radius = serializedObject.FindProperty("m_Radius"); - m_SuspensionDistance = serializedObject.FindProperty("m_SuspensionDistance"); - m_SuspensionSpring = serializedObject.FindProperty("m_SuspensionSpring"); - m_Mass = serializedObject.FindProperty("m_Mass"); - m_ForceAppPointDistance = serializedObject.FindProperty("m_ForceAppPointDistance"); - m_WheelDampingRate = serializedObject.FindProperty("m_WheelDampingRate"); - m_ForwardFriction = serializedObject.FindProperty("m_ForwardFriction"); - m_SidewaysFriction = serializedObject.FindProperty("m_SidewaysFriction"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_Mass); - EditorGUILayout.PropertyField(m_Radius); - EditorGUILayout.PropertyField(m_WheelDampingRate); - EditorGUILayout.PropertyField(m_SuspensionDistance); - EditorGUILayout.PropertyField(m_ForceAppPointDistance); - EditorGUILayout.Space(); - EditorGUILayout.PropertyField(m_Center); - EditorGUILayout.Space(); - StructPropertyGUILayout.GenericStruct(m_SuspensionSpring); - StructPropertyGUILayout.GenericStruct(m_ForwardFriction); - StructPropertyGUILayout.GenericStruct(m_SidewaysFriction); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Inspector/WheelJoint2DEditor.cs b/Editor/Mono/Inspector/WheelJoint2DEditor.cs deleted file mode 100644 index 65dbf3cd9e..0000000000 --- a/Editor/Mono/Inspector/WheelJoint2DEditor.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(WheelJoint2D))] - [CanEditMultipleObjects] - internal class WheelJoint2DEditor : AnchoredJoint2DEditor - { - new public void OnSceneGUI() - { - var wheelJoint2D = (WheelJoint2D)target; - - // Ignore disabled joint. - if (!wheelJoint2D.enabled) - return; - - var anchor = TransformPoint(wheelJoint2D.transform, wheelJoint2D.anchor); - - // Draw lines for slider angle and limits - Vector3 upper = anchor; - Vector3 lower = anchor; - Vector3 direction = RotateVector2(Vector3.right, -wheelJoint2D.suspension.angle - wheelJoint2D.transform.eulerAngles.z); - - Handles.color = Color.green; - - direction *= HandleUtility.GetHandleSize(anchor) * 0.3f; - upper += direction; - lower -= direction; - - DrawAALine(upper, lower); - - base.OnSceneGUI(); - } - } -} diff --git a/Editor/Mono/Inspector/WindInspector.cs b/Editor/Mono/Inspector/WindInspector.cs deleted file mode 100644 index bc4d2cf190..0000000000 --- a/Editor/Mono/Inspector/WindInspector.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; -using UnityEditor; -using UnityEditor.AnimatedValues; - - -namespace UnityEditor -{ - [CustomEditor(typeof(WindZone))] - [CanEditMultipleObjects] - internal class WindInspector : Editor - { - private class Styles - { - public static GUIContent Mode = EditorGUIUtility.TrTextContent("Mode", "The wind blows towards a direction or outwards within a sphere"); - public static GUIContent Radius = EditorGUIUtility.TrTextContent("Radius", "The radius of the spherical area"); - public static GUIContent WindMain = EditorGUIUtility.TrTextContent("Main", "Overall strength of the wind"); - public static GUIContent WindTurbulence = EditorGUIUtility.TrTextContent("Turbulence", "Randomness in strength"); - public static GUIContent WindPulseMagnitude = EditorGUIUtility.TrTextContent("Pulse Magnitude", "Strength of the wind pulses"); - public static GUIContent WindPulseFrequency = EditorGUIUtility.TrTextContent("Pulse Frequency", "Frequency of the wind pulses"); - } - - private SerializedProperty m_Mode; - private SerializedProperty m_Radius; - private SerializedProperty m_WindMain; - private SerializedProperty m_WindTurbulence; - private SerializedProperty m_WindPulseMagnitude; - private SerializedProperty m_WindPulseFrequency; - - private readonly AnimBool m_ShowRadius = new AnimBool(); - - private void OnEnable() - { - m_Mode = serializedObject.FindProperty("m_Mode"); - m_Radius = serializedObject.FindProperty("m_Radius"); - m_WindMain = serializedObject.FindProperty("m_WindMain"); - m_WindTurbulence = serializedObject.FindProperty("m_WindTurbulence"); - m_WindPulseMagnitude = serializedObject.FindProperty("m_WindPulseMagnitude"); - m_WindPulseFrequency = serializedObject.FindProperty("m_WindPulseFrequency"); - - m_ShowRadius.value = !m_Mode.hasMultipleDifferentValues && m_Mode.intValue == (int)WindZoneMode.Spherical; - m_ShowRadius.valueChanged.AddListener(Repaint); - } - - private void OnDisable() - { - m_ShowRadius.valueChanged.RemoveListener(Repaint); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_Mode, Styles.Mode); - - m_ShowRadius.target = !m_Mode.hasMultipleDifferentValues && m_Mode.intValue == (int)WindZoneMode.Spherical; - if (EditorGUILayout.BeginFadeGroup(m_ShowRadius.faded)) - EditorGUILayout.PropertyField(m_Radius, Styles.Radius); - EditorGUILayout.EndFadeGroup(); - - EditorGUILayout.PropertyField(m_WindMain, Styles.WindMain); - EditorGUILayout.PropertyField(m_WindTurbulence, Styles.WindTurbulence); - EditorGUILayout.PropertyField(m_WindPulseMagnitude, Styles.WindPulseMagnitude); - EditorGUILayout.PropertyField(m_WindPulseFrequency, Styles.WindPulseFrequency); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/Internal/MonoScripts.cs b/Editor/Mono/Internal/MonoScripts.cs deleted file mode 100644 index bde203fa3d..0000000000 --- a/Editor/Mono/Internal/MonoScripts.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -namespace UnityEditorInternal -{ - /// - /// Helper factory for instances. - /// - public static class MonoScripts - { - public static MonoScript CreateMonoScript(string scriptContents, string className, string nameSpace, string assemblyName, bool isEditorScript) - { - var script = new MonoScript(); - script.Init(scriptContents, className, nameSpace, assemblyName, isEditorScript); - return script; - } - } -} diff --git a/Editor/Mono/InternalEditorUtility.cs b/Editor/Mono/InternalEditorUtility.cs deleted file mode 100644 index 3d410b94ee..0000000000 --- a/Editor/Mono/InternalEditorUtility.cs +++ /dev/null @@ -1,426 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -using System.IO; -using System.Linq; -using System.Collections; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using UnityEditor.Utils; -using UnityEditor.Scripting.ScriptCompilation; - -namespace UnityEditorInternal -{ - partial class InternalEditorUtility - { - public static Texture2D FindIconForFile(string fileName) - { - int i = fileName.LastIndexOf('.'); - string extension = i == -1 ? "" : fileName.Substring(i + 1).ToLower(); - - switch (extension) - { - // Most .asset files use their scriptable object defined icon instead of a default one. - case "asset": return AssetDatabase.GetCachedIcon(fileName) as Texture2D ?? EditorGUIUtility.FindTexture("GameManager Icon"); - - case "boo": return EditorGUIUtility.FindTexture("boo Script Icon"); - case "cginc": return EditorGUIUtility.FindTexture("CGProgram Icon"); - case "cs": return EditorGUIUtility.FindTexture("cs Script Icon"); - case "guiskin": return EditorGUIUtility.FindTexture("GUISkin Icon"); - case "js": return EditorGUIUtility.FindTexture("Js Script Icon"); - case "dll": return EditorGUIUtility.FindTexture("Assembly Icon"); - case "asmdef": return EditorGUIUtility.FindTexture("AssemblyDefinitionAsset Icon"); - case "mat": return EditorGUIUtility.FindTexture(typeof(Material)); - case "physicmaterial": return EditorGUIUtility.FindTexture(typeof(PhysicMaterial)); - case "prefab": return EditorGUIUtility.FindTexture("PrefabNormal Icon"); - case "shader": return EditorGUIUtility.FindTexture(typeof(Shader)); - case "txt": return EditorGUIUtility.FindTexture(typeof(TextAsset)); - case "unity": return EditorGUIUtility.FindTexture(typeof(SceneAsset)); - case "prefs": return EditorGUIUtility.FindTexture(typeof(EditorSettings)); - case "anim": return EditorGUIUtility.FindTexture(typeof(Animation)); - case "meta": return EditorGUIUtility.FindTexture("MetaFile Icon"); - case "mixer": return EditorGUIUtility.FindTexture(typeof(UnityEditor.Audio.AudioMixerController)); - case "uxml": return EditorGUIUtility.FindTexture("UxmlScript Icon"); - case "uss": return EditorGUIUtility.FindTexture("UssScript Icon"); - - case "ttf": case "otf": case "fon": case "fnt": - return EditorGUIUtility.FindTexture(typeof(Font)); - - case "aac": case "aif": case "aiff": case "au": case "mid": case "midi": case "mp3": case "mpa": - case "ra": case "ram": case "wma": case "wav": case "wave": case "ogg": - return EditorGUIUtility.FindTexture(typeof(AudioClip)); - - case "ai": case "apng": case "png": case "bmp": case "cdr": case "dib": case "eps": case "exif": - case "gif": case "ico": case "icon": case "j": case "j2c": case "j2k": case "jas": - case "jiff": case "jng": case "jp2": case "jpc": case "jpe": case "jpeg": case "jpf": case "jpg": - case "jpw": case "jpx": case "jtf": case "mac": case "omf": case "qif": case "qti": case "qtif": - case "tex": case "tfw": case "tga": case "tif": case "tiff": case "wmf": case "psd": case "exr": - case "hdr": - return EditorGUIUtility.FindTexture(typeof(Texture)); - - case "3df": case "3dm": case "3dmf": case "3ds": case "3dv": case "3dx": case "blend": case "c4d": - case "lwo": case "lws": case "ma": case "max": case "mb": case "mesh": case "obj": case "vrl": - case "wrl": case "wrz": case "fbx": - return EditorGUIUtility.FindTexture(typeof(Mesh)); - - case "dv": case "mp4": case "mpg": case "mpeg": case "m4v": case "ogv": case "vp8": case "webm": - case "asf": case "asx": case "avi": case "dat": case "divx": case "dvx": case "mlv": case "m2l": - case "m2t": case "m2ts": case "m2v": case "m4e": case "mjp": case "mov": case "movie": - case "mp21": case "mpe": case "mpv2": case "ogm": case "qt": case "rm": case "rmvb": case "wmw": case "xvid": - return AssetDatabase.GetCachedIcon(fileName) as Texture2D ?? EditorGUIUtility.FindTexture(typeof(MovieTexture)); - - case "colors": case "gradients": - case "curves": case "curvesnormalized": case "particlecurves": case "particlecurvessigned": case "particledoublecurves": case "particledoublecurvessigned": - return EditorGUIUtility.FindTexture(typeof(ScriptableObject)); - - default: return null; - } - } - - public static Texture2D GetIconForFile(string fileName) - { - return FindIconForFile(fileName) ?? EditorGUIUtility.FindTexture(typeof(DefaultAsset)); - } - - public static string[] GetEditorSettingsList(string prefix, int count) - { - ArrayList aList = new ArrayList(); - - for (int i = 1; i <= count; i++) - { - string str = EditorPrefs.GetString(prefix + i, "defaultValue"); - - if (str == "defaultValue") - break; - - aList.Add(str); - } - - return aList.ToArray(typeof(string)) as string[]; - } - - public static void SaveEditorSettingsList(string prefix, string[] aList, int count) - { - int i; - - for (i = 0; i < aList.Length; i++) - EditorPrefs.SetString(prefix + (i + 1), (string)aList[i]); - - for (i = aList.Length + 1; i <= count; i++) - EditorPrefs.DeleteKey(prefix + i); - } - - public static string TextAreaForDocBrowser(Rect position, string text, GUIStyle style) - { - int id = EditorGUIUtility.GetControlID("TextAreaWithTabHandling".GetHashCode(), FocusType.Keyboard, position); - var editor = EditorGUI.s_RecycledEditor; - var evt = Event.current; - if (editor.IsEditingControl(id) && evt.type == EventType.KeyDown) - { - if (evt.character == '\t') - { - editor.Insert('\t'); - evt.Use(); - GUI.changed = true; - text = editor.text; - } - if (evt.character == '\n') - { - editor.Insert('\n'); - evt.Use(); - GUI.changed = true; - text = editor.text; - } - } - bool dummy; - text = EditorGUI.DoTextField(editor, id, EditorGUI.IndentedRect(position), text, style, null, out dummy, false, true, false); - return text; - } - - public static Camera[] GetSceneViewCameras() - { - return SceneView.GetAllSceneCameras(); - } - - public static void ShowGameView() - { - WindowLayout.ShowAppropriateViewOnEnterExitPlaymode(true); - } - - // Multi selection handling. Returns new list of selected instanceIDs - public static List GetNewSelection(int clickedInstanceID, List allInstanceIDs, List selectedInstanceIDs, int lastClickedInstanceID, bool keepMultiSelection, bool useShiftAsActionKey, bool allowMultiSelection) - { - List newSelection = new List(); - - bool useShift = Event.current.shift || (EditorGUI.actionKey && useShiftAsActionKey); - bool useActionKey = EditorGUI.actionKey && !useShiftAsActionKey; - if (!allowMultiSelection) - useShift = useActionKey = false; - - // Toggle selected node from selection - if (useActionKey) - { - newSelection.AddRange(selectedInstanceIDs); - if (newSelection.Contains(clickedInstanceID)) - newSelection.Remove(clickedInstanceID); - else - newSelection.Add(clickedInstanceID); - } - // Select everything between the first selected object and the selected - else if (useShift) - { - if (clickedInstanceID == lastClickedInstanceID) - { - newSelection.AddRange(selectedInstanceIDs); - return newSelection; - } - - int firstIndex; - int lastIndex; - if (!GetFirstAndLastSelected(allInstanceIDs, selectedInstanceIDs, out firstIndex, out lastIndex)) - { - // We had no selection - newSelection.Add(clickedInstanceID); - return newSelection; - } - - int newIndex = -1; - int prevIndex = -1; - for (int i = 0; i < allInstanceIDs.Count; ++i) - { - if (allInstanceIDs[i] == clickedInstanceID) - newIndex = i; - if (lastClickedInstanceID != 0) - if (allInstanceIDs[i] == lastClickedInstanceID) - prevIndex = i; - } - - System.Diagnostics.Debug.Assert(newIndex != -1); // new item should be part of visible folder set - int dir = 0; - if (prevIndex != -1) - dir = (newIndex > prevIndex) ? 1 : -1; - - int from, to; - if (newIndex > lastIndex) - { - from = firstIndex; - to = newIndex; - } - else if (newIndex >= firstIndex && newIndex < lastIndex) - { - if (dir > 0) - { - from = newIndex; - to = lastIndex; - } - else - { - from = firstIndex; - to = newIndex; - } - } - else - { - from = newIndex; - to = lastIndex; - } - - // Outcomment to debug - //Debug.Log (clickedInstanceID + ", firstIndex " + firstIndex + ", lastIndex " + lastIndex + ", newIndex " + newIndex + " " + ", lastClickedIndex " + prevIndex + ", from " + from + ", to " + to); - - for (int i = from; i <= to; ++i) - newSelection.Add(allInstanceIDs[i]); - } - // Just set the selection to the clicked object - else - { - if (keepMultiSelection) - { - // Don't change selection on mouse down when clicking on selected item. - // This is for dragging in case with multiple items selected or right click (mouse down should not unselect the rest). - if (selectedInstanceIDs.Contains(clickedInstanceID)) - { - newSelection.AddRange(selectedInstanceIDs); - return newSelection; - } - } - - newSelection.Add(clickedInstanceID); - } - - return newSelection; - } - - static bool GetFirstAndLastSelected(List allInstanceIDs, List selectedInstanceIDs, out int firstIndex, out int lastIndex) - { - firstIndex = -1; - lastIndex = -1; - for (int i = 0; i < allInstanceIDs.Count; ++i) - { - if (selectedInstanceIDs.Contains(allInstanceIDs[i])) - { - if (firstIndex == -1) - firstIndex = i; - lastIndex = i; // just overwrite and we will have the last in the end... - } - } - return firstIndex != -1 && lastIndex != -1; - } - - internal static string GetApplicationExtensionForRuntimePlatform(RuntimePlatform platform) - { - switch (platform) - { - case RuntimePlatform.OSXEditor: - return "app"; - case RuntimePlatform.WindowsEditor: - return "exe"; - default: - break; - } - return string.Empty; - } - - public static bool IsValidFileName(string filename) - { - string validFileName = RemoveInvalidCharsFromFileName(filename, false); - if (validFileName != filename || string.IsNullOrEmpty(validFileName)) - return false; - return true; - } - - public static string RemoveInvalidCharsFromFileName(string filename, bool logIfInvalidChars) - { - if (string.IsNullOrEmpty(filename)) - return filename; - - filename = filename.Trim(); // remove leading and trailing white spaces - if (string.IsNullOrEmpty(filename)) - return filename; - - string invalidChars = new string(System.IO.Path.GetInvalidFileNameChars()); - string legal = ""; - bool hasInvalidChar = false; - foreach (char c in filename) - { - if (invalidChars.IndexOf(c) == -1) - legal += c; - else - hasInvalidChar = true; - } - if (hasInvalidChar && logIfInvalidChars) - { - string invalid = GetDisplayStringOfInvalidCharsOfFileName(filename); - if (invalid.Length > 0) - Debug.LogWarningFormat("A filename cannot contain the following character{0}: {1}", invalid.Length > 1 ? "s" : "", invalid); - } - - return legal; - } - - public static string GetDisplayStringOfInvalidCharsOfFileName(string filename) - { - if (string.IsNullOrEmpty(filename)) - return ""; - - string invalid = new string(System.IO.Path.GetInvalidFileNameChars()); - - string illegal = ""; - foreach (char c in filename) - { - if (invalid.IndexOf(c) >= 0) - { - if (illegal.IndexOf(c) == -1) - { - if (illegal.Length > 0) - illegal += " "; - illegal += c; - } - } - } - return illegal; - } - - internal static bool IsScriptOrAssembly(string filename) - { - if (string.IsNullOrEmpty(filename)) - return false; - - switch (System.IO.Path.GetExtension(filename).ToLower()) - { - case ".cs": - case ".js": - case ".boo": - return true; - case ".dll": - case ".exe": - return AssemblyHelper.IsManagedAssembly(filename); - default: - return false; - } - } - - internal static T ParentHasComponent(Transform trans) where T : Component - { - if (trans != null) - { - T comp = trans.GetComponent(); - if (comp) - return comp; - - return ParentHasComponent(trans.parent); - } - return null; - } - - internal static IEnumerable GetAllScriptGUIDs() - { - return AssetDatabase.GetAllAssetPaths() - .Where(asset => (IsScriptOrAssembly(asset) && !AssetDatabase.IsPackagedAssetPath(asset))) - .Select(asset => AssetDatabase.AssetPathToGUID(asset)); - } - - // Do not remove. Called through reflection by Visual Studio Tools for Unity. - internal static UnityEditor.Scripting.MonoIsland[] GetMonoIslandsForPlayer() - { - var group = EditorUserBuildSettings.activeBuildTargetGroup; - var target = EditorUserBuildSettings.activeBuildTarget; - - PrecompiledAssembly[] unityAssemblies = GetUnityAssemblies(false, group, target); - - PrecompiledAssembly[] allPrecompiledAssemblies = GetPrecompiledAssemblies(false, @group, target); - return EditorCompilationInterface.Instance.GetAllMonoIslands(unityAssemblies, allPrecompiledAssemblies, EditorScriptCompilationOptions.BuildingEmpty | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies); - } - - // Do not remove. Called through reflection by Visual Studio Tools for Unity. - // Use EditorCompilationInterface.GetAllMonoIslands internally instead of this method. - internal static UnityEditor.Scripting.MonoIsland[] GetMonoIslands() - { - return EditorCompilationInterface.GetAllMonoIslands(); - } - - internal static string[] GetCompilationDefinesForPlayer() - { - var group = EditorUserBuildSettings.activeBuildTargetGroup; - var target = EditorUserBuildSettings.activeBuildTarget; - return GetCompilationDefines(EditorScriptCompilationOptions.BuildingEmpty, group, target); - } - - internal static string GetMonolithicEngineAssemblyPath() - { - // We still build a monolithic UnityEngine.dll as a compilation target for user projects. - // It lives next to the editor dll. - var dir = Path.GetDirectoryName(GetEditorAssemblyPath()); - return Path.Combine(dir, "UnityEngine.dll"); - } - - internal static string[] GetCompilationDefines(EditorScriptCompilationOptions options, BuildTargetGroup targetGroup, BuildTarget target) - { - return GetCompilationDefines(options, targetGroup, target, PlayerSettings.GetApiCompatibilityLevel(targetGroup)); - } - } -} diff --git a/Editor/Mono/JSProxy/ClipboardAccess.cs b/Editor/Mono/JSProxy/ClipboardAccess.cs deleted file mode 100644 index 52fc2cd3b7..0000000000 --- a/Editor/Mono/JSProxy/ClipboardAccess.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal class ClipboardAccess - { - private ClipboardAccess() - { - // Nothing to do - } - - public void CopyToClipboard(string value) - { - TextEditor te = new TextEditor(); - te.text = value; - te.SelectAll(); - te.Copy(); - } - - public string PasteFromClipboard() - { - TextEditor te = new TextEditor(); - te.Paste(); - return te.text; - } - - static ClipboardAccess() - { - JSProxyMgr.GetInstance().AddGlobalObject("unity/ClipboardAccess", new ClipboardAccess()); - } - } -} - diff --git a/Editor/Mono/JSProxy/JSProxyMgr.cs b/Editor/Mono/JSProxy/JSProxyMgr.cs deleted file mode 100644 index 2833d4d6c9..0000000000 --- a/Editor/Mono/JSProxy/JSProxyMgr.cs +++ /dev/null @@ -1,652 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -/** - * JSONServer class implementation - * Open a websocket channel, listen to remote call requests, execute the request and returns a result - * - * -- INVOKE Exchange -- - * - * Request format: - * { - * version: x.xx, - * messageID: xxxx, - * type: , - * destination: , - * method: - * params: [ - * , - * , - * ... - * - * ] - * } - * - * Reply format: - * { - * version: x.xx, - * messageID: xxxx, - * status: , - * result: - * } - * - * - * -- GETSTUBINFO Exchange -- - * - * Request format: - * { - * version: x.xx, - * messageID: xxxx, - * type: , - * reference: - * } - * - * Reply format: - * - * { - * version: x.xx, - * messageID: xxxx, - * status: , - * reference: , - * result: { - * properties: [ - * { - * name: , - * value: - * }, - * ... - * ], - * - * methods: [ - * { - * name: , - * parameters: [ - * , - * ... - * ] - * } - * ] - * } - * } - * - * - **/ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.Reflection; -using System.Linq; -using UnityEditor.Collaboration; -namespace UnityEditor.Web -{ - internal class JspmPropertyInfo - { - public string name; - public object value = null; - - public JspmPropertyInfo(string name, object value) - { - this.name = name; - this.value = value; - } - } - - internal class JspmMethodInfo - { - public string name; - public string[] parameters = null; - - public JspmMethodInfo(string name, string[] parameters) - { - this.name = name; - this.parameters = parameters; - } - }; - - internal class JspmStubInfo - { - public JspmPropertyInfo[] properties = null; - public JspmMethodInfo[] methods = null; - public string[] events = null; - - public JspmStubInfo(JspmPropertyInfo[] properties, JspmMethodInfo[] methods, string[] events) - { - this.methods = methods; - this.properties = properties; - this.events = events; - } - }; - - internal class JspmResult - { - public double version; - public long messageID; - public int status; - - public JspmResult() - { - version = JSProxyMgr.kProtocolVersion; - messageID = JSProxyMgr.kInvalidMessageID; - status = JSProxyMgr.kErrNone; - } - - public JspmResult(long messageID, int status) - { - version = JSProxyMgr.kProtocolVersion; - this.messageID = messageID; - this.status = status; - } - }; - - internal class JspmError : JspmResult - { - public JspmError(long messageID, int status, string errorClass, string message) : base(messageID, status) - { - this.errorClass = errorClass; - this.message = message; - } - - public string errorClass; - public string message; - }; - - internal class JspmSuccess : JspmResult - { - public object result; - public string type; - - public JspmSuccess(long messageID, object result, string type) - : base(messageID, JSProxyMgr.kErrNone) - { - this.result = result; - this.type = type; - } - }; - - internal class JspmStubInfoSuccess : JspmSuccess - { - public string reference; - - public JspmStubInfoSuccess(long messageID, string reference, JspmPropertyInfo[] properties, JspmMethodInfo[] methods, string[] events) - : base(messageID, new JspmStubInfo(properties, methods, events), JSProxyMgr.kTypeGetStubInfo) - { - this.reference = reference; - } - }; - - [InitializeOnLoad] - internal class JSProxyMgr - { - // current protocol version - public const double kProtocolVersion = 1.0; - - // class constants - public const long kInvalidMessageID = -1; - - // error code definitions - public const int kErrNone = 0; - public const int kErrInvalidMessageFormat = -1000; - public const int kErrUnknownObject = -1001; - public const int kErrUnknownMethod = -1002; - public const int kErrInvocationFailed = -1003; - public const int kErrUnsupportedProtocol = -1004; - public const int kErrUnknownEvent = -1005; - - // messages types - public const string kTypeInvoke = "INVOKE"; - public const string kTypeGetStubInfo = "GETSTUBINFO"; - public const string kTypeOnEvent = "ONEVENT"; - - // task list - private Queue m_TaskList = null; - - // global object list - private Dictionary m_GlobalObjects = null; - - // singleton - private static JSProxyMgr s_Instance = null; - - // ignored methods - private static readonly string[] s_IgnoredMethods = { "Equals", "GetHashCode", "GetType", "ToString"}; - - public static JSProxyMgr GetInstance() - { - if (s_Instance == null) - { - s_Instance = new JSProxyMgr(); - } - - return s_Instance; - } - - static JSProxyMgr() - { - WebView.OnDomainReload(); - } - - public static void DoTasks() - { - GetInstance().ProcessTasks(); - } - - ~JSProxyMgr() - { - m_GlobalObjects.Clear(); - m_GlobalObjects = null; - } - - protected JSProxyMgr() - { - m_TaskList = new Queue(); - m_GlobalObjects = new Dictionary(); - AddGlobalObject("unity/collab", Collab.instance); - } - - protected delegate void TaskCallback(); - - public void AddGlobalObject(string referenceName, object obj) - { - if (m_GlobalObjects == null) - { - m_GlobalObjects = new Dictionary(); - } - - RemoveGlobalObject(referenceName); - m_GlobalObjects.Add(referenceName, obj); - } - - public void RemoveGlobalObject(string referenceName) - { - if (m_GlobalObjects == null) - return; - - if (m_GlobalObjects.ContainsKey(referenceName)) - { - m_GlobalObjects.Remove(referenceName); - } - } - - private void AddTask(TaskCallback task) - { - if (m_TaskList == null) - { - m_TaskList = new Queue(); - } - - m_TaskList.Enqueue(task); - } - - private void ProcessTasks() - { - if (m_TaskList == null || m_TaskList.Count == 0) - return; - - // Deque and call maximum of 10 tasks - var maxTasks = 10; - while (m_TaskList.Count > 0 && maxTasks > 0) - { - TaskCallback callback = m_TaskList.Dequeue(); - callback(); - maxTasks--; - } - } - - public delegate void ExecCallback(object result); - - public bool DoMessage(string jsonRequest, ExecCallback callback, WebView webView) - { - long messageID = kInvalidMessageID; - - try - { - var jsonData = Json.Deserialize(jsonRequest) as Dictionary; - if (jsonData == null || !jsonData.ContainsKey("messageID") || !jsonData.ContainsKey("version") || !jsonData.ContainsKey("type")) - { - callback(FormatError(messageID, kErrInvalidMessageFormat, "errInvalidMessageFormat", jsonRequest)); - return false; - } - - messageID = (long)jsonData["messageID"]; - double versionNumber = double.Parse((string)jsonData["version"], System.Globalization.CultureInfo.InvariantCulture); - string type = (string)jsonData["type"]; - - if (versionNumber > kProtocolVersion) - { - callback(FormatError(messageID, kErrUnsupportedProtocol, "errUnsupportedProtocol", "The protocol version <" + versionNumber + "> is not supported by this verison of the code")); - return false; - } - - if (type == kTypeInvoke) - { - return DoInvokeMessage(messageID, callback, jsonData); - } - - if (type == kTypeGetStubInfo) - { - return DoGetStubInfoMessage(messageID, callback, jsonData); - } - - if (type == kTypeOnEvent) - { - return DoOnEventMessage(messageID, callback, jsonData, webView); - } - } - catch (Exception ex) - { - callback(FormatError(messageID, kErrInvalidMessageFormat, "errInvalidMessageFormat", ex.Message)); - } - - return false; - } - - private bool DoGetStubInfoMessage(long messageID, ExecCallback callback, Dictionary jsonData) - { - if (!jsonData.ContainsKey("reference")) - { - callback(FormatError(messageID, kErrUnknownObject, "errUnknownObject", "object reference missing")); - return false; - } - - string reference = (string)jsonData["reference"]; - object destObject = GetDestinationObject(reference); - - if (destObject == null) - { - callback(FormatError(messageID, kErrUnknownObject, "errUnknownObject", "cannot find object with reference <" + reference + ">")); - return false; - } - - //Add the public functions and static methods - List methods = (destObject.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public)).ToList(); - methods.AddRange((destObject.GetType().GetMethods(BindingFlags.Public | BindingFlags.Static)).ToList()); - - ArrayList methodList = new ArrayList(); - foreach (MethodInfo method in methods) - { - if (Array.IndexOf(s_IgnoredMethods, method.Name) >= 0) - continue; - - if (method.IsSpecialName && (method.Name.StartsWith("set_") || method.Name.StartsWith("get_"))) - continue; - - ParameterInfo[] parameters = method.GetParameters(); - ArrayList parameterList = new ArrayList(); - foreach (ParameterInfo parameter in parameters) - { - parameterList.Add(parameter.Name); - } - - JspmMethodInfo info = new JspmMethodInfo(method.Name, (string[])parameterList.ToArray(typeof(string))); - methodList.Add(info); - } - - List properties = destObject.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).ToList(); - ArrayList propertyList = new ArrayList(); - foreach (PropertyInfo property in properties) - { - propertyList.Add(new JspmPropertyInfo(property.Name, property.GetValue(destObject, null))); - } - - List fields = destObject.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public).ToList(); - foreach (FieldInfo field in fields) - { - propertyList.Add(new JspmPropertyInfo(field.Name, field.GetValue(destObject))); - } - - List events = destObject.GetType().GetEvents(BindingFlags.Instance | BindingFlags.Public).ToList(); - ArrayList eventList = new ArrayList(); - foreach (EventInfo evt in events) - { - eventList.Add(evt.Name); - } - - callback(new JspmStubInfoSuccess(messageID, reference, - (JspmPropertyInfo[])propertyList.ToArray(typeof(JspmPropertyInfo)), - (JspmMethodInfo[])methodList.ToArray(typeof(JspmMethodInfo)), - (string[])eventList.ToArray(typeof(string)))); - - return true; - } - - private bool DoOnEventMessage(long messageID, ExecCallback callback, Dictionary jsonData, WebView webView) - { - callback(FormatError(messageID, kErrUnknownMethod, "errUnknownMethod", "method DoOnEventMessage is deprecated")); - return false; - } - - private bool DoInvokeMessage(long messageID, ExecCallback callback, Dictionary jsonData) - { - if (!jsonData.ContainsKey("destination") || !jsonData.ContainsKey("method") || !jsonData.ContainsKey("params")) - { - callback(FormatError(messageID, kErrUnknownObject, "errUnknownObject", "object reference, method name or parameters missing")); - return false; - } - - string destination = (string)jsonData["destination"]; - string methodName = (string)jsonData["method"]; - List paramList = (List)jsonData["params"]; - - object destObject = GetDestinationObject(destination); - if (destObject == null) - { - callback(FormatError(messageID, kErrUnknownObject, "errUnknownObject", "cannot find object with reference <" + destination + ">")); - return false; - } - - Type type = destObject.GetType(); - MethodInfo[] methods = type.GetMethods(); - MethodInfo foundMethod = null; - object[] parameters = null; - string err = ""; - - foreach (MethodInfo method in methods) - { - if (method.Name != methodName) - continue; - - try - { - parameters = ParseParams(method, paramList); - foundMethod = method; - break; - } - catch (Exception e) - { - err = e.Message; - } - } - - if (foundMethod == null) - { - callback(FormatError(messageID, kErrUnknownMethod, "errUnknownMethod", "cannot find method <" + methodName + "> for object <" + destination + ">, reason:" + err)); - return false; - } - - AddTask(() => - { - try - { - object res = foundMethod.Invoke(destObject, parameters); - callback(FormatSuccess(messageID, res)); - } - catch (TargetInvocationException tiex) - { - if (tiex.InnerException != null) - { - callback(FormatError(messageID, kErrInvocationFailed, tiex.InnerException.GetType().Name, tiex.InnerException.Message)); - } - else - { - callback(FormatError(messageID, kErrInvocationFailed, tiex.GetType().Name, tiex.Message)); - } - } - catch (Exception ex) - { - callback(FormatError(messageID, kErrInvocationFailed, ex.GetType().Name, ex.Message)); - } - }); - - return true; - } - - public static JspmError FormatError(long messageID, int status, string errorClass, string message) - { - return new JspmError(messageID, status, errorClass, message); - } - - public static JspmSuccess FormatSuccess(long messageID, object result) - { - return new JspmSuccess(messageID, result, kTypeInvoke); - } - - public object GetDestinationObject(string reference) - { - object destination; - m_GlobalObjects.TryGetValue(reference, out destination); - return destination; - } - - public object[] ParseParams(MethodInfo method, List data) - { - ParameterInfo[] parameters = method.GetParameters(); - if (parameters.Length != data.Count) - return null; - - List result = new List(data.Count); - for (int i = 0; i < data.Count; i++) - { - object val = InternalParseParam(parameters[i].ParameterType, data[i]); - result.Add(val); - } - return result.ToArray(); - } - - private object InternalParseParam(Type type, object data) - { - IList asList; - IDictionary asDict; - string asStr; - - if (data == null) - { - return null; - } - - if ((asList = data as IList) != null) - { - if (!type.IsArray) - throw new InvalidOperationException("Not an array " + type.FullName); - - Type elemType = type.GetElementType(); - ArrayList res = new ArrayList(); - for (int i = 0; i < asList.Count; i++) - { - object val = InternalParseParam(elemType, asList[i]); - res.Add(val); - } - return res.ToArray(elemType); - } - - if ((asDict = data as IDictionary) != null) - { - if (!type.IsClass) - throw new InvalidOperationException("Not a class " + type.FullName); - - ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.Any, new Type[0], null); - if (constructor == null) - throw new InvalidOperationException("Cannot find a default constructor for " + type.FullName); - - object obj = constructor.Invoke(new object[0]); - List fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public).ToList(); - foreach (FieldInfo field in fields) - { - try - { - object val = InternalParseParam(field.FieldType, asDict[field.Name]); - field.SetValue(obj, val); - } - catch (KeyNotFoundException) - { - // For now, do nothing - } - } - List properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList(); - foreach (PropertyInfo property in properties) - { - try - { - object val = InternalParseParam(property.PropertyType, asDict[property.Name]); - MethodInfo method = property.GetSetMethod(); - if (method != null) - { - method.Invoke(obj, new[] { val }); - } - } - catch (KeyNotFoundException) - { - // For now, do nothing - } - catch (TargetInvocationException) - { - // For now, do nothing - } - } - - return Convert.ChangeType(obj, type); - } - - if ((asStr = data as string) != null) - { - return asStr; - } - - if (data is bool) - { - return (bool)data; - } - - if (data is double) - { - return (double)data; - } - - if (data is int || data is Int16 || data is Int32 || data is Int64 || data is long) - { - return Convert.ChangeType(data, type); - } - - throw new InvalidOperationException("Cannot parse " + Json.Serialize(data)); - } - - public string Stringify(object target) - { - string res = Json.Serialize(target); - return res; - } - - protected object GetMemberValue(MemberInfo member, object target) - { - switch (member.MemberType) - { - case MemberTypes.Field: - return ((FieldInfo)member).GetValue(target); - - case MemberTypes.Property: - try - { - return ((PropertyInfo)member).GetValue(target, null); - } - catch (TargetParameterCountException e) - { - throw new ArgumentException("MemberInfo has index parameters", "member", e); - } - - default: - throw new ArgumentException("MemberInfo is not of type FieldInfo or PropertyInfo", "member"); - } - } - } -} diff --git a/Editor/Mono/JSProxy/PreviewGenerator.cs b/Editor/Mono/JSProxy/PreviewGenerator.cs deleted file mode 100644 index edec441abe..0000000000 --- a/Editor/Mono/JSProxy/PreviewGenerator.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; - -namespace UnityEditor.Web -{ - internal class PreviewGenerator - { - const string kPreviewBuildFolder = "builds"; - - static protected PreviewGenerator s_Instance = null; - - public static PreviewGenerator GetInstance() - { - if (s_Instance == null) - { - return new PreviewGenerator(); - } - return s_Instance; - } - - public byte[] GeneratePreview(string assetPath, int width, int height) - { - UnityEngine.Object obj = AssetDatabase.LoadMainAssetAtPath(assetPath); - if (obj == null) - return null; - - Editor editor = Editor.CreateEditor(obj); - if (editor == null) - return null; - - Texture2D tex = editor.RenderStaticPreview(assetPath, null, width, height); - if (tex == null) - { - UnityEngine.Object.DestroyImmediate(editor); - return null; - } - - byte[] bytes = tex.EncodeToPNG(); - UnityEngine.Object.DestroyImmediate(tex); - UnityEngine.Object.DestroyImmediate(editor); - return bytes; - } - } -} diff --git a/Editor/Mono/JSProxy/TroubleshooterAccess.cs b/Editor/Mono/JSProxy/TroubleshooterAccess.cs deleted file mode 100644 index b20e25dd1a..0000000000 --- a/Editor/Mono/JSProxy/TroubleshooterAccess.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; -using UnityEditor; -using UnityEditor.Connect; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal class TroubleshooterAccess - { - private TroubleshooterAccess() - { - // Nothing to do - } - - public string GetUserName() - { - var uc = UnityConnect.instance; - if (!uc.GetConnectInfo().loggedIn) - { - return "Anonymous"; - } - return uc.GetUserName(); - } - - public string GetUserId() - { - var uc = UnityConnect.instance; - if (!uc.GetConnectInfo().loggedIn) - { - return string.Empty; - } - return uc.GetUserInfo().userId; - } - - public void SignIn() - { - UnityConnect.instance.ShowLogin(); - } - - public void SignOut() - { - UnityConnect.instance.Logout(); - } - - public void StartBugReporter() - { - EditorUtility.LaunchBugReporter(); - } - - static TroubleshooterAccess() - { - JSProxyMgr.GetInstance().AddGlobalObject("/unity/editor/troubleshooter", new TroubleshooterAccess()); - } - } -} - diff --git a/Editor/Mono/JSProxy/WebScriptObject.cs b/Editor/Mono/JSProxy/WebScriptObject.cs deleted file mode 100644 index 767dabce3c..0000000000 --- a/Editor/Mono/JSProxy/WebScriptObject.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngineInternal; - -namespace UnityEditor.Web -{ - internal class WebScriptObject : ScriptableObject - { - public WebView webView - { - get - { - return m_WebView; - } - set - { - m_WebView = value; - } - } - - private WebView m_WebView; - - private WebScriptObject() - { - m_WebView = null; - } - - public bool ProcessMessage(string jsonRequest, WebViewV8CallbackCSharp callback) - { - if (m_WebView != null) - { - return JSProxyMgr.GetInstance().DoMessage(jsonRequest, (object result) => - { - string res = JSProxyMgr.GetInstance().Stringify(result); - callback.Callback(res); - }, m_WebView - ); - } - return false; - } - - // For legacy external website JS invocation like AssetStore - public bool processMessage(string jsonRequest, WebViewV8CallbackCSharp callback) - { - return ProcessMessage(jsonRequest, callback); - } - }; -} diff --git a/Editor/Mono/LicenseManagementWindow.cs b/Editor/Mono/LicenseManagementWindow.cs deleted file mode 100644 index bbd3b86b42..0000000000 --- a/Editor/Mono/LicenseManagementWindow.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - internal partial class LicenseManagementWindow : EditorWindow - { - static private int width = 600; - static private int height = 350; - static private int left = 0; - static private int top = 0; - static private int offsetX = 50; - static private int offsetY = 25; - static private int buttonWidth = 140; - - static private Rect windowArea; - static private Rect rectArea = new Rect(offsetX, offsetY, width - offsetX * 2, height - offsetY * 2); - static LicenseManagementWindow win = null; - - private static LicenseManagementWindow Window - { - get - { - if (win == null) - win = EditorWindow.GetWindowWithRect(windowArea, true, "License Management"); - - return win; - } - } - - static void ShowWindow() - { - Resolution res = Screen.currentResolution; - left = (res.width - width) / 2; - top = (res.height - height) / 2; - windowArea = new Rect(left, top, width, height); - win = Window; - win.position = windowArea; - win.Show(); - } - - void OnGUI() - { - GUILayout.BeginArea(rectArea); - GUILayout.FlexibleSpace(); - - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Check for updates", GUILayout.ExpandHeight(true), GUILayout.Width(buttonWidth))) - CheckForUpdates(); - GUI.skin.label.wordWrap = true; - GUILayout.Label("Checks for updates to the currently installed license. If you have purchased " - + "addons you can install them by pressing this button (Internet access required)"); - GUILayout.EndHorizontal(); - - GUILayout.Space(15); - - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Activate new license", GUILayout.ExpandHeight(true), GUILayout.Width(buttonWidth))) - { - ActivateNewLicense(); - Window.Close(); - } - GUILayout.Label("Activate Unity with a different serial number, switch to a free serial or start " - + "a trial period if you are eligible for it (Internet access required)."); - GUILayout.EndHorizontal(); - - GUILayout.Space(15); - - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Return license", GUILayout.ExpandHeight(true), GUILayout.Width(buttonWidth))) - ReturnLicense(); - GUILayout.Label("Return this license and free an activation for the serial it is using. You can then" - + " reuse the activation on another machine (Internet access required)."); - GUILayout.EndHorizontal(); - - GUILayout.Space(15); - - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Manual activation", GUILayout.ExpandHeight(true), GUILayout.Width(buttonWidth))) - ManualActivation(); - GUILayout.Label("Start the manual activation process, you can save this machines license activation " - + "request file or deploy a license file you have already activated manually."); - GUILayout.EndHorizontal(); - - GUILayout.Space(15); - - GUILayout.BeginHorizontal(); - if (GUILayout.Button("Unity FAQ", GUILayout.ExpandHeight(true), GUILayout.Width(buttonWidth))) - Application.OpenURL("http://unity3d.com/unity/faq"); - GUILayout.Label("Open the Unity FAQ web page, where you can find information about Unity's license system."); - GUILayout.EndHorizontal(); - - GUILayout.FlexibleSpace(); - GUILayout.EndArea(); - } - } -} diff --git a/Editor/Mono/Localization/LocalizationDatabase.bindings.cs b/Editor/Mono/Localization/LocalizationDatabase.bindings.cs deleted file mode 100644 index c8314c7526..0000000000 --- a/Editor/Mono/Localization/LocalizationDatabase.bindings.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; - -using UnityEngine; -using System; - -namespace UnityEditor -{ - [NativeHeader("UnityPrefix.h")] - [NativeHeader("Runtime/Scripting/ScriptingUtility.h")] - [NativeHeader("Runtime/Mono/MonoUtility.h")] - [NativeHeader("Editor/Src/Utility/LocalizationDatabase.h")] - [NativeHeader("Runtime/Misc/SystemInfo.h")] - [NativeHeader("Runtime/Scripting/ScriptingUtility.h")] - [NativeHeader("Runtime/Scripting/ScriptingExportUtility.h")] - - internal class LocalizationDatabase - { - extern public static SystemLanguage GetDefaultEditorLanguage(); - extern public static SystemLanguage currentEditorLanguage { get; set; } - - [NativeMethod("GetAvailableEditorLanguagesIF")] - extern public static SystemLanguage[] GetAvailableEditorLanguages(); - - [NativeMethod(Name = "GetLocalizedStringIF", IsThreadSafe = true)] - extern public static string GetLocalizedString(string original); - - [NativeMethod("GetLocalizationResourceFolderIF")] - extern public static string GetLocalizationResourceFolder(); - - extern public static bool enableEditorLocalization { get; set; } - - // The "MarkForTranslation" method is used as a marker for xgettext and similar tools. - // It shouldn't perform translation, just returns the value. - public static string MarkForTranslation(string value) - { - return value; - } - } -} diff --git a/Editor/Mono/Localization/LocalizationDatabase.cs b/Editor/Mono/Localization/LocalizationDatabase.cs deleted file mode 100644 index 773347b1a5..0000000000 --- a/Editor/Mono/Localization/LocalizationDatabase.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -using System; -using System.Threading; -using System.Collections; -using System.Collections.Generic; -using System.Security; -using System.Security.Cryptography; - -namespace UnityEditor -{ - /// *undocumented* - internal class L10n - { - private L10n() {} - - public static string Tr(string str) - { - var new_str = LocalizationDatabase.GetLocalizedString(str); - return new_str; - } - - public static string[] Tr(string[] str_list) - { - var res = new string[str_list.Length]; - for (var i = 0; i < res.Length; ++i) - res[i] = Tr(str_list[i]); - return res; - } - - public static string TrPath(string path) - { - string[] separatingChars = { "/" }; - var result = new System.Text.StringBuilder(256); - var items = path.Split(separatingChars, System.StringSplitOptions.RemoveEmptyEntries); - for (var i = 0; i < items.Length; ++i) - { - result.Append(Tr(items[i])); - if (i < items.Length - 1) - result.Append("/"); - } - return result.ToString(); - } - } -} diff --git a/Editor/Mono/Localization/LocalizedEditorFontManager.cs b/Editor/Mono/Localization/LocalizedEditorFontManager.cs deleted file mode 100644 index bffe172a2b..0000000000 --- a/Editor/Mono/Localization/LocalizedEditorFontManager.cs +++ /dev/null @@ -1,162 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; - -using System; -using System.Threading; -using System.Collections; -using System.Collections.Generic; -using System.Security; -using System.Security.Cryptography; - -namespace UnityEditor -{ - // internal class to manage localized editor fonts - internal class LocalizedEditorFontManager - { - private class FontSetting - { - private string[] m_fontNames; - public FontSetting(string[] fontNames) - { - m_fontNames = fontNames; - } - - public string[] fontNames { get { return m_fontNames; } } - } - - private class FontDictionary - { - private Dictionary m_dictionary; - public FontDictionary() - { - m_dictionary = new Dictionary(); - } - - public void Add(string key, FontSetting value) - { - m_dictionary.Add(key, value); - } - - public bool ContainsKey(string key) - { - return m_dictionary.ContainsKey(key); - } - - public FontSetting this[string key] - { - get { return m_dictionary[key]; } - } - } - - private static Dictionary m_fontDictionaries; - - private static FontDictionary GetFontDictionary(SystemLanguage language) - { - if (!m_fontDictionaries.ContainsKey(language)) - { - // Debug.LogErrorFormat("no settings for the language [{0}].", language); - return null; - } - return m_fontDictionaries[language]; - } - - private static void ReadFontSettings() - { - // init and reload - if (m_fontDictionaries == null) - { - m_fontDictionaries = new Dictionary(); - } - m_fontDictionaries.Clear(); - - string filepath = null; - if (filepath == null || !System.IO.File.Exists(filepath)) - { - filepath = EditorApplication.applicationContentsPath + "/Resources/fontsettings.txt"; - } - if (!System.IO.File.Exists(filepath)) - { - // Debug.LogError("no [" + filepath + "] found."); - return; - } - - // load setting from file and initialize - byte[] data = System.IO.File.ReadAllBytes(filepath); - - string dataStr = System.Text.Encoding.UTF8.GetString(data); - string[] lines = dataStr.Split('\n'); - foreach (var line0 in lines) - { - var line = line0; - line = line.Split('#')[0]; - line = line.Trim(); - if (line.Length <= 0) - { - continue; - } - string[] cols = line.Split('|'); - if (cols.Length != 2) - { - Debug.LogError("wrong format for the fontsettings.txt."); - continue; - } - var lang = (SystemLanguage)System.Enum.Parse(typeof(SystemLanguage), cols[0].Trim()); - string[] pair = cols[1].Split('='); - if (pair.Length != 2) - { - Debug.LogError("wrong format for the fontsettings.txt."); - continue; - } - - string baseFontName = pair[0].Trim(); - string[] fontNames = pair[1].Split(','); - - for (int i = 0; i < fontNames.Length; ++i) - { - fontNames[i] = fontNames[i].Trim(); - } - if (!m_fontDictionaries.ContainsKey(lang)) - { - m_fontDictionaries.Add(lang, new FontDictionary()); - } - m_fontDictionaries[lang].Add(baseFontName, new FontSetting(fontNames)); - } - } - - public static void LocalizeEditorFonts() - { - ReadFontSettings(); - - var dict = GetFontDictionary(LocalizationDatabase.currentEditorLanguage); - if (dict == null) - return; - - /* - We have the Lucida Grande ttf asset which was always the font we used in the editor. - But on windows we call ReplaceFontForWindows to override the font used for that asset. - It would probably make sense to rename the asset to something generic, such as "EditorFont" instead, - though that might possibly break some things. - */ - ReplaceFontForLocalization(dict, (Font)EditorGUIUtility.LoadRequired(EditorResourcesUtility.fontsPath + "Lucida Grande.ttf")); - ReplaceFontForLocalization(dict, (Font)EditorGUIUtility.LoadRequired(EditorResourcesUtility.fontsPath + "Lucida Grande Bold.ttf")); - ReplaceFontForLocalization(dict, (Font)EditorGUIUtility.LoadRequired(EditorResourcesUtility.fontsPath + "Lucida Grande Small.ttf")); - ReplaceFontForLocalization(dict, (Font)EditorGUIUtility.LoadRequired(EditorResourcesUtility.fontsPath + "Lucida Grande Small Bold.ttf")); - ReplaceFontForLocalization(dict, (Font)EditorGUIUtility.LoadRequired(EditorResourcesUtility.fontsPath + "Lucida Grande Big.ttf")); - } - - static void ReplaceFontForLocalization(FontDictionary dict, Font font) - { - if (dict.ContainsKey(font.name)) - { - font.fontNames = dict[font.name].fontNames; - // Avoid the font to be unloaded in EditorUtility.UnloadUnusedAssetsIgnoreManagedReferences and lose the font name information. - font.hideFlags = HideFlags.HideAndDontSave; - } - } - } -} diff --git a/Editor/Mono/LogEntries.bindings.cs b/Editor/Mono/LogEntries.bindings.cs deleted file mode 100644 index bec1218fb4..0000000000 --- a/Editor/Mono/LogEntries.bindings.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/EditorMonoConsole.h")] - [NativeAsStruct] - internal partial class LogEntry - { - internal static extern void LogToConsoleEx(LogEntry outputEntry); - internal static extern void RemoveLogEntriesByMode(int mode); - } -} diff --git a/Editor/Mono/LookDevView/CameraController.cs b/Editor/Mono/LookDevView/CameraController.cs deleted file mode 100644 index c4605f95b1..0000000000 --- a/Editor/Mono/LookDevView/CameraController.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor -{ - abstract class CameraController - { - // Actual API to be defined - // Passing the associated Camera as a parameter should not be needed (only CameraState should be important). See how we can break that dependency when doing the proper refactoring. - public abstract void Update(CameraState cameraState, Camera cam); - } -} diff --git a/Editor/Mono/LookDevView/CameraControllerStandard.cs b/Editor/Mono/LookDevView/CameraControllerStandard.cs deleted file mode 100644 index 7b4f1574f2..0000000000 --- a/Editor/Mono/LookDevView/CameraControllerStandard.cs +++ /dev/null @@ -1,274 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class CameraControllerStandard : CameraController - { - static PrefKey kFPSForward = new PrefKey("View/FPS Forward", "w"); - static PrefKey kFPSBack = new PrefKey("View/FPS Back", "s"); - static PrefKey kFPSLeft = new PrefKey("View/FPS Strafe Left", "a"); - static PrefKey kFPSRight = new PrefKey("View/FPS Strafe Right", "d"); - static PrefKey kFPSUp = new PrefKey("View/FPS Strafe Up", "e"); - static PrefKey kFPSDown = new PrefKey("View/FPS Strafe Down", "q"); - - private ViewTool m_CurrentViewTool = ViewTool.None; - private float m_StartZoom = 0.0f; - private float m_ZoomSpeed = 0.0f; - private float m_TotalMotion = 0.0f; - private Vector3 m_Motion = new Vector3(); - private float m_FlySpeed = 0; - const float kFlyAcceleration = 1.1f; - static TimeHelper m_FPSTiming = new TimeHelper(); - - public ViewTool currentViewTool - { - get { return m_CurrentViewTool; } - } - - private void ResetCameraControl() - { - m_CurrentViewTool = ViewTool.None; - m_Motion = Vector3.zero; - } - - private void HandleCameraScrollWheel(CameraState cameraState) - { - float zoomDelta = Event.current.delta.y; - - float relativeDelta = Mathf.Abs(cameraState.viewSize.value) * zoomDelta * .015f; - const float deltaCutoff = .3f; - if (relativeDelta > 0 && relativeDelta < deltaCutoff) - relativeDelta = deltaCutoff; - else if (relativeDelta < 0 && relativeDelta > -deltaCutoff) - relativeDelta = -deltaCutoff; - - cameraState.viewSize.value += relativeDelta; - Event.current.Use(); - } - - private void OrbitCameraBehavior(CameraState cameraState, Camera cam) - { - Event evt = Event.current; - - cameraState.FixNegativeSize(); - Quaternion rotation = cameraState.rotation.target; - rotation = Quaternion.AngleAxis(evt.delta.y * .003f * Mathf.Rad2Deg, rotation * Vector3.right) * rotation; - rotation = Quaternion.AngleAxis(evt.delta.x * .003f * Mathf.Rad2Deg, Vector3.up) * rotation; - if (cameraState.viewSize.value < 0) - { - cameraState.pivot.value = cam.transform.position; - cameraState.viewSize.value = 0; - } - cameraState.rotation.value = rotation; - } - - private void HandleCameraMouseDrag(CameraState cameraState, Camera cam) - { - Event evt = Event.current; - switch (m_CurrentViewTool) - { - case ViewTool.Orbit: - { - OrbitCameraBehavior(cameraState, cam); - } - break; - case ViewTool.FPS: - { - Vector3 camPos = cameraState.pivot.value - cameraState.rotation.value * Vector3.forward * cameraState.GetCameraDistance(); - - // Normal FPS camera behavior - Quaternion rotation = cameraState.rotation.value; - rotation = Quaternion.AngleAxis(evt.delta.y * .003f * Mathf.Rad2Deg, rotation * Vector3.right) * rotation; - rotation = Quaternion.AngleAxis(evt.delta.x * .003f * Mathf.Rad2Deg, Vector3.up) * rotation; - cameraState.rotation.value = rotation; - cameraState.pivot.value = camPos + rotation * Vector3.forward * cameraState.GetCameraDistance(); - } - break; - case ViewTool.Pan: - { - cameraState.FixNegativeSize(); - Vector3 screenPos = cam.WorldToScreenPoint(cameraState.pivot.value); - screenPos += new Vector3(-Event.current.delta.x, Event.current.delta.y, 0); - Vector3 worldDelta = cam.ScreenToWorldPoint(screenPos) - cameraState.pivot.value; - if (evt.shift) - worldDelta *= 4; - cameraState.pivot.value += worldDelta; - } - break; - case ViewTool.Zoom: - { - float zoomDelta = HandleUtility.niceMouseDeltaZoom * (evt.shift ? 9 : 3); - m_TotalMotion += zoomDelta; - if (m_TotalMotion < 0) - cameraState.viewSize.value = m_StartZoom * (1 + m_TotalMotion * .001f); - else - cameraState.viewSize.value = cameraState.viewSize.value + zoomDelta * m_ZoomSpeed * .003f; - } - break; - - default: - break; - } - evt.Use(); - } - - private void HandleCameraKeyDown() - { - if (Event.current.keyCode == KeyCode.Escape) - { - ResetCameraControl(); - } - - if (m_CurrentViewTool == ViewTool.FPS) - { - Event evt = Event.current; - Vector3 lastMotion = m_Motion; - if (evt.keyCode == ((Event)kFPSForward).keyCode) - { - m_Motion.z = 1; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSBack).keyCode) - { - m_Motion.z = -1; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSLeft).keyCode) - { - m_Motion.x = -1; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSRight).keyCode) - { - m_Motion.x = 1; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSUp).keyCode) - { - m_Motion.y = 1; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSDown).keyCode) - { - m_Motion.y = -1; - evt.Use(); - } - - if (evt.type != EventType.KeyDown && lastMotion.sqrMagnitude == 0) - m_FPSTiming.Begin(); - } - } - - private void HandleCameraKeyUp() - { - if (m_CurrentViewTool == ViewTool.FPS) - { - Event evt = Event.current; - if (evt.keyCode == ((Event)kFPSForward).keyCode || evt.keyCode == ((Event)kFPSBack).keyCode) - { - m_Motion.z = 0; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSLeft).keyCode || evt.keyCode == ((Event)kFPSRight).keyCode) - { - m_Motion.x = 0; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSUp).keyCode || evt.keyCode == ((Event)kFPSDown).keyCode) - { - m_Motion.y = 0; - evt.Use(); - } - } - } - - private void HandleCameraMouseUp() - { - ResetCameraControl(); - Event.current.Use(); - } - - private Vector3 GetMovementDirection() - { - float deltaTime = m_FPSTiming.Update(); - if (m_Motion.sqrMagnitude == 0) - { - m_FlySpeed = 0; - return Vector3.zero; - } - else - { - float speed = Event.current.shift ? 5 : 1; - if (m_FlySpeed == 0) - m_FlySpeed = 9; - else - m_FlySpeed = m_FlySpeed * Mathf.Pow(kFlyAcceleration, deltaTime); - return m_Motion.normalized * m_FlySpeed * speed * deltaTime; - } - } - - public override void Update(CameraState cameraState, Camera cam) - { - Event evt = Event.current; - - if (evt.type == EventType.MouseUp) - { - m_CurrentViewTool = ViewTool.None; - } - - if (evt.type == EventType.MouseDown) - { - int button = evt.button; - - bool controlKeyOnMac = (evt.control && Application.platform == RuntimePlatform.OSXEditor); - - if (button == 2) - { - m_CurrentViewTool = ViewTool.Pan; - } - else if ((button <= 0 && controlKeyOnMac) - || (button == 1 && evt.alt)) - { - m_CurrentViewTool = ViewTool.Zoom; - - m_StartZoom = cameraState.viewSize.value; - m_ZoomSpeed = Mathf.Max(Mathf.Abs(m_StartZoom), .3f); - m_TotalMotion = 0; - } - else if (button <= 0) - { - m_CurrentViewTool = ViewTool.Orbit; - } - else if (button == 1 && !evt.alt) - { - m_CurrentViewTool = ViewTool.FPS; - } - } - - switch (evt.type) - { - case EventType.ScrollWheel: HandleCameraScrollWheel(cameraState); break; - case EventType.MouseUp: HandleCameraMouseUp(); break; - case EventType.MouseDrag: HandleCameraMouseDrag(cameraState, cam); break; - case EventType.KeyDown: HandleCameraKeyDown(); break; - case EventType.KeyUp: HandleCameraKeyUp(); break; - case EventType.Layout: - { - Vector3 motion = GetMovementDirection(); - if (motion.sqrMagnitude != 0) - { - cameraState.pivot.value = cameraState.pivot.value + cameraState.rotation.value * motion; - } - } - break; - } - } - } -} diff --git a/Editor/Mono/LookDevView/CameraState.cs b/Editor/Mono/LookDevView/CameraState.cs deleted file mode 100644 index d7e0aad601..0000000000 --- a/Editor/Mono/LookDevView/CameraState.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using System; -using UnityEngine; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor -{ - [Serializable] - internal class CameraState - { - private static readonly Quaternion kDefaultRotation = Quaternion.LookRotation(new Vector3(0.0f, 0.0f, 1.0f)); - private const float kDefaultViewSize = 10f; - private static readonly Vector3 kDefaultPivot = Vector3.zero; - private const float kDefaultFoV = 90f; - - [SerializeField] private AnimVector3 m_Pivot = new AnimVector3(kDefaultPivot); - [SerializeField] private AnimQuaternion m_Rotation = new AnimQuaternion(kDefaultRotation); - [SerializeField] private AnimFloat m_ViewSize = new AnimFloat(kDefaultViewSize); - - public float GetCameraDistance() - { - float fov = kDefaultFoV; - return m_ViewSize.value / Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad); - } - - public void FixNegativeSize() - { - float fov = kDefaultFoV; - if (m_ViewSize.value < 0) - { - float distance = m_ViewSize.value / Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad); - Vector3 p = m_Pivot.value + m_Rotation.value * new Vector3(0, 0, -distance); - m_ViewSize.value = -m_ViewSize.value; - distance = m_ViewSize.value / Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad); - m_Pivot.value = p + m_Rotation.value * new Vector3(0, 0, distance); - } - } - - public void UpdateCamera(Camera camera) - { - camera.transform.rotation = m_Rotation.value; - camera.transform.position = m_Pivot.value + camera.transform.rotation * new Vector3(0, 0, -GetCameraDistance()); - - float farClip = Mathf.Max(1000f, 2000f * m_ViewSize.value); - camera.nearClipPlane = farClip * 0.000005f; - camera.farClipPlane = farClip; - } - - public CameraState Clone() - { - CameraState newState = new CameraState(); - newState.pivot.value = pivot.value; - newState.rotation.value = rotation.value; - newState.viewSize.value = viewSize.value; - - return newState; - } - - public void Copy(CameraState cameraStateIn) - { - pivot.value = cameraStateIn.pivot.value; - rotation.value = cameraStateIn.rotation.value; - viewSize.value = cameraStateIn.viewSize.value; - } - - public AnimVector3 pivot { get { return m_Pivot; } set { m_Pivot = value; } } - public AnimQuaternion rotation { get { return m_Rotation; } set { m_Rotation = value; } } - public AnimFloat viewSize { get { return m_ViewSize; } set { m_ViewSize = value; } } - } -} diff --git a/Editor/Mono/LookDevView/LookDevConfig.cs b/Editor/Mono/LookDevView/LookDevConfig.cs deleted file mode 100644 index c4e60b9a83..0000000000 --- a/Editor/Mono/LookDevView/LookDevConfig.cs +++ /dev/null @@ -1,500 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Collections.Generic; -using UnityEngine.Rendering; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class LookDevConfig - : ScriptableObject - { - [SerializeField] private LookDevContext[] m_LookDevContexts = new LookDevContext[2]; - [SerializeField] private LookDevPropertyInfo[] m_LookDevProperties = new LookDevPropertyInfo[(int)LookDevProperty.Count]; - [SerializeField] private GizmoInfo m_Gizmo = new GizmoInfo(); - [SerializeField] private LookDevMode m_LookDevMode = LookDevMode.Single1; - [SerializeField] private bool m_EnableToneMap = true; - [SerializeField] private bool m_EnableShadowCubemap = true; - [SerializeField] private float m_ExposureRange = 8.0f; - [SerializeField] private float m_ShadowDistance = 0.0f; - [SerializeField] private bool m_ShowBalls = false; - [SerializeField] private bool m_ShowControlWindows = true; - [SerializeField] private bool m_RotateObjectMode = false; - [SerializeField] private float m_EnvRotationSpeed = 1.0f; - [SerializeField] private bool m_RotateEnvMode = false; - [SerializeField] private float m_ObjRotationSpeed = 1.0f; - [SerializeField] private bool m_AllowDifferentObjects = false; - [SerializeField] private GameObject[][] m_PreviewObjects = - { - new GameObject[(int)LookDevView.PreviewContext.PreviewContextPass.kCount], - new GameObject[(int)LookDevView.PreviewContext.PreviewContextPass.kCount], - };// Those are the actual preview objects - [SerializeField] private LookDevEditionContext m_CurrentContextEdition = LookDevEditionContext.Left; - [SerializeField] private int m_CurrentEditionContextIndex = 0; - [SerializeField] private float m_DualViewBlendFactor = 0.0f; - [SerializeField] private GameObject[] m_OriginalGameObject = new GameObject[2]; - [SerializeField] private CameraState[] m_CameraState = new CameraState[2]; - [SerializeField] private bool m_SideBySideCameraLinked = false; - [SerializeField] private CameraState m_CameraStateCommon = new CameraState(); - [SerializeField] private CameraState m_CameraStateLeft = new CameraState(); - [SerializeField] private CameraState m_CameraStateRight = new CameraState(); - GameObject[][] m_CurrentObjectInstances = - { - new GameObject[(int)LookDevView.PreviewContext.PreviewContextPass.kCount], - new GameObject[(int)LookDevView.PreviewContext.PreviewContextPass.kCount], - }; - - private LookDevView m_LookDevView = null; - - public bool enableShadowCubemap - { - get { return m_EnableShadowCubemap; } - set { m_EnableShadowCubemap = value; m_LookDevView.Repaint(); } - } - - public bool sideBySideCameraLinked - { - get { return m_SideBySideCameraLinked; } - set { m_SideBySideCameraLinked = value; } - } - - public int currentEditionContextIndex - { - get { return m_CurrentEditionContextIndex; } - } - - - public LookDevEditionContext currentEditionContext - { - get { return m_CurrentContextEdition; } - } - - public float dualViewBlendFactor - { - get { return m_DualViewBlendFactor; } - set { m_DualViewBlendFactor = value; } - } - - public GizmoInfo gizmo - { - get { return m_Gizmo; } - set { m_Gizmo = value; } - } - - public LookDevContext[] lookDevContexts - { - get { return m_LookDevContexts; } - } - - public LookDevContext currentLookDevContext - { - get { return m_LookDevContexts[m_CurrentEditionContextIndex]; } - } - - public GameObject[][] currentObjectInstances - { - get { return m_CurrentObjectInstances; } - } - public GameObject[][] previewObjects - { - get { return m_PreviewObjects; } - } - - public CameraState[] cameraState - { - get { return m_CameraState; } - } - - public CameraState cameraStateCommon - { - get { return m_CameraStateCommon; } - set { m_CameraStateCommon = value; } - } - public CameraState cameraStateLeft - { - get { return m_CameraStateLeft; } - set { m_CameraStateLeft = value; } - } - public CameraState cameraStateRight - { - get { return m_CameraStateRight; } - set { m_CameraStateRight = value; } - } - - public LookDevMode lookDevMode - { - get { return m_LookDevMode; } - set - { - m_LookDevMode = value; - UpdateCameraArray(); - UpdateCurrentObjectArray(); - } - } - - public bool enableToneMap - { - get { return m_EnableToneMap; } - set { m_EnableToneMap = value; m_LookDevView.Repaint(); } - } - - public bool allowDifferentObjects - { - get { return m_AllowDifferentObjects; } - set { m_AllowDifferentObjects = value; ResynchronizeObjects(); m_LookDevView.Repaint(); } - } - - public float exposureRange - { - get { return m_ExposureRange; } - set { m_ExposureRange = value; m_LookDevView.Repaint(); } - } - - public float shadowDistance - { - get { return m_ShadowDistance; } - set { m_ShadowDistance = value; m_LookDevView.Repaint(); } - } - - public bool showBalls - { - get { return m_ShowBalls; } - set - { - m_ShowBalls = value; - m_LookDevView.Repaint(); - } - } - - public bool showControlWindows - { - get { return m_ShowControlWindows; } - set - { - m_ShowControlWindows = value; - m_LookDevView.Repaint(); - } - } - - public bool rotateObjectMode - { - get { return m_RotateObjectMode; } - set { m_RotateObjectMode = value; } - } - - public float objRotationSpeed - { - get { return m_ObjRotationSpeed; } - set { m_ObjRotationSpeed = value; m_LookDevView.Repaint(); } - } - - public bool rotateEnvMode - { - get { return m_RotateEnvMode; } - set { m_RotateEnvMode = value; } - } - - public float envRotationSpeed - { - get { return m_EnvRotationSpeed; } - set { m_EnvRotationSpeed = value; m_LookDevView.Repaint(); } - } - - public LookDevConfig() - { - m_LookDevProperties[(int)LookDevProperty.ExposureValue] = new LookDevPropertyInfo(LookDevPropertyType.Float); - m_LookDevProperties[(int)LookDevProperty.EnvRotation] = new LookDevPropertyInfo(LookDevPropertyType.Float); - m_LookDevProperties[(int)LookDevProperty.HDRI] = new LookDevPropertyInfo(LookDevPropertyType.Int); - m_LookDevProperties[(int)LookDevProperty.LoDIndex] = new LookDevPropertyInfo(LookDevPropertyType.Int); - m_LookDevProperties[(int)LookDevProperty.ShadingMode] = new LookDevPropertyInfo(LookDevPropertyType.Int); - } - - // Can't use generics properly for the life of me... if anyone has a better suggestion than copy/paste...I'll take it! - public void UpdateFloatProperty(LookDevProperty type, float value) - { - UpdateFloatProperty(type, value, true, false); - } - - public void UpdateFloatProperty(LookDevProperty type, float value, bool recordUndo) - { - UpdateFloatProperty(type, value, recordUndo, false); - } - - public void UpdateIntProperty(LookDevProperty property, int value) - { - UpdateIntProperty(property, value, true, false); - } - - public void UpdateIntProperty(LookDevProperty property, int value, bool recordUndo) - { - UpdateIntProperty(property, value, recordUndo, false); - } - - public float GetFloatProperty(LookDevProperty property, LookDevEditionContext context) - { - return m_LookDevContexts[(int)context].GetProperty(property).floatValue; - } - - public int GetIntProperty(LookDevProperty property, LookDevEditionContext context) - { - return m_LookDevContexts[(int)context].GetProperty(property).intValue; - } - - public void UpdateFloatProperty(LookDevProperty property, float value, bool recordUndo, bool forceLinked) - { - if (recordUndo) - { - Undo.RecordObject(this, "Update Float property for " + property + " with value " + value); - } - - lookDevContexts[m_CurrentEditionContextIndex].UpdateProperty(property, value); - - if (m_LookDevProperties[(int)property].linked || forceLinked) - { - lookDevContexts[(m_CurrentEditionContextIndex + 1) % 2].UpdateProperty(property, value); - } - m_LookDevView.Repaint(); - } - - public void UpdateIntProperty(LookDevProperty property, int value, bool recordUndo, bool forceLinked) - { - if (recordUndo) - { - Undo.RecordObject(this, "Update Int property for " + property + " with value " + value); - } - - lookDevContexts[m_CurrentEditionContextIndex].UpdateProperty(property, value); - - if (m_LookDevProperties[(int)property].linked || forceLinked) - { - lookDevContexts[(m_CurrentEditionContextIndex + 1) % 2].UpdateProperty(property, value); - } - m_LookDevView.Repaint(); - } - - public bool IsPropertyLinked(LookDevProperty type) - { - return m_LookDevProperties[(int)type].linked; - } - - public void UpdatePropertyLink(LookDevProperty property, bool value) - { - Undo.RecordObject(this, "Update Link for property " + property); - - m_LookDevProperties[(int)property].linked = value; - - switch (m_LookDevProperties[(int)property].propertyType) - { - case LookDevPropertyType.Int: - UpdateIntProperty(property, lookDevContexts[m_CurrentEditionContextIndex].GetProperty(property).intValue, true, false); - break; - case LookDevPropertyType.Float: - UpdateFloatProperty(property, lookDevContexts[m_CurrentEditionContextIndex].GetProperty(property).floatValue, true, false); - break; - } - m_LookDevView.Repaint(); - } - - public int GetObjectLoDCount(LookDevEditionContext context) - { - if (m_CurrentObjectInstances[(int)context][0] != null) - { - LODGroup lodGroup = m_CurrentObjectInstances[(int)context][0].GetComponent(typeof(LODGroup)) as LODGroup; - if (lodGroup != null) - { - return lodGroup.lodCount; - } - } - - return 1; - } - - public void UpdateFocus(LookDevEditionContext context) - { - // Caution: m_CurrentContextEditionMode should never be set to ContextEditionMode.kNone it is used only for drag context. - Debug.Assert(context != LookDevEditionContext.None); - - if (context != LookDevEditionContext.None) - { - m_CurrentContextEdition = context; - m_CurrentEditionContextIndex = (int)m_CurrentContextEdition; - m_LookDevView.Repaint(); - } - } - - private void DestroyCurrentPreviewObject(LookDevEditionContext context) - { - var index = (int)context; - for (var j = 0; j < m_PreviewObjects[index].Length; j++) - { - if (m_PreviewObjects[index][j] != null) - { - DestroyImmediate(m_PreviewObjects[index][j]); - m_PreviewObjects[index][j] = null; - } - } - } - - internal static void DisableRendererProperties(GameObject go) - { - foreach (Renderer renderer in go.GetComponentsInChildren()) - { - renderer.lightProbeUsage = LightProbeUsage.Off; - renderer.allowOcclusionWhenDynamic = false; - } - } - - public void ResynchronizeObjects() - { - Undo.RecordObject(this, "Resync objects"); - for (int i = 0; i < 2; i++) - SetCurrentPreviewObject(m_OriginalGameObject[m_CurrentEditionContextIndex], (LookDevEditionContext)i); - m_LookDevView.Frame(false); - } - - private void UpdateCameraArray() - { - // When we go from side by side or single view to zone or split, we want to copy the last selected camera as common. - if (m_LookDevMode == LookDevMode.SideBySide || m_LookDevMode == LookDevMode.Single1 || m_LookDevMode == LookDevMode.Single2) - { - m_CameraState[0] = m_CameraStateLeft; - m_CameraState[1] = m_CameraStateRight; - } - else - { - m_CameraState[0] = m_CameraStateCommon; - m_CameraState[1] = m_CameraStateCommon; - - CameraState currentState = m_CurrentContextEdition == LookDevEditionContext.Left ? m_CameraStateLeft : m_CameraStateRight; - m_CameraStateCommon.Copy(currentState); - } - } - - public void UpdateCurrentObjectArray() - { - if (allowDifferentObjects) - { - for (var i = 0; i < m_PreviewObjects[0].Length; ++i) - { - m_CurrentObjectInstances[(int)LookDevEditionContext.Left][i] = m_PreviewObjects[(int)LookDevEditionContext.Left][i]; - m_CurrentObjectInstances[(int)LookDevEditionContext.Right][i] = m_PreviewObjects[(int)LookDevEditionContext.Right][i]; - } - } - else - { - for (var i = 0; i < m_PreviewObjects[0].Length; ++i) - { - m_CurrentObjectInstances[m_CurrentEditionContextIndex][i] = m_PreviewObjects[m_CurrentEditionContextIndex][i]; - m_CurrentObjectInstances[(m_CurrentEditionContextIndex + 1) % 2][i] = m_PreviewObjects[m_CurrentEditionContextIndex][i]; - } - } - } - - // return true if both view have been updated (i.e the object is loaded in both view) - public bool SetCurrentPreviewObject(GameObject go) - { - SetCurrentPreviewObject(go, m_CurrentContextEdition); - // Set other window to the same objects if there isn't one already - int otherIndex = (m_CurrentEditionContextIndex + 1) % 2; - if (m_PreviewObjects[otherIndex][0] == null || !m_AllowDifferentObjects) - { - SetCurrentPreviewObject(go, (LookDevEditionContext)otherIndex); - return true; - } - - return false; - } - - public void SetCurrentPreviewObject(GameObject go, LookDevEditionContext context) - { - DestroyCurrentPreviewObject(context); - - if (go != null) - { - int index = (int)context; - if (m_LookDevView == null - || m_LookDevView.previewUtilityContexts == null - || m_LookDevView.previewUtilityContexts[index] == null) - return; - - m_OriginalGameObject[index] = go; - - for (var i = 0; i < m_PreviewObjects[index].Length; ++i) - { - m_PreviewObjects[index][i] = m_LookDevView.previewUtilityContexts[index].m_PreviewUtility[i].InstantiatePrefabInScene(m_OriginalGameObject[index]); - m_PreviewObjects[index][i].transform.position = new Vector3(0.0f, 0.0f, 0.0f); - m_PreviewObjects[index][i].transform.rotation = Quaternion.identity; - EditorUtility.InitInstantiatedPreviewRecursive(m_PreviewObjects[index][i]); - DisableRendererProperties(m_PreviewObjects[index][i]); // Avoid light probe influence from the main scene (but still have the default probe lighting) - PreviewRenderUtility.SetEnabledRecursive(m_PreviewObjects[index][i], false); - } - - UpdateCurrentObjectArray(); - } - } - - public void OnEnable() - { - if (m_LookDevContexts[0] == null) - { - for (int i = 0; i < 2; ++i) - { - m_LookDevContexts[i] = new LookDevContext(); - } - } - - InitializeCurrentObjects(); - - UpdateCameraArray(); - - Undo.undoRedoPerformed += OnUndoRedo; - } - - void InitializeCurrentObjects() - { - for (int i = 0; i < 2; ++i) - { - if (m_OriginalGameObject[i] != null) - SetCurrentPreviewObject(m_OriginalGameObject[i], (LookDevEditionContext)i); - } - } - - void OnUndoRedo() - { - for (int i = 0; i < 2; ++i) - { - if (m_OriginalGameObject[i] != null) - { - SetCurrentPreviewObject(m_OriginalGameObject[i], (LookDevEditionContext)i); - } - } - } - - public void OnDestroy() - { - DestroyCurrentPreviewObject(LookDevEditionContext.Left); - DestroyCurrentPreviewObject(LookDevEditionContext.Right); - } - - public void Cleanup() - { - m_CurrentEditionContextIndex = 0; - - DestroyCurrentPreviewObject(LookDevEditionContext.Left); - DestroyCurrentPreviewObject(LookDevEditionContext.Right); - } - - public void SetLookDevView(LookDevView lookDevView) - { - if (m_LookDevView != lookDevView) - { - m_LookDevView = lookDevView; - InitializeCurrentObjects(); - } - } - } -} diff --git a/Editor/Mono/LookDevView/LookDevContext.cs b/Editor/Mono/LookDevView/LookDevContext.cs deleted file mode 100644 index 9fbbb22236..0000000000 --- a/Editor/Mono/LookDevView/LookDevContext.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - [Serializable] - internal class LookDevContext - { - [Serializable] - public class LookDevPropertyValue - { - public float floatValue = 0.0f; - public int intValue = 0; - } - - [SerializeField] - private LookDevPropertyValue[] m_Properties = new LookDevPropertyValue[(int)LookDevProperty.Count]; - - public float exposureValue - { - get { return m_Properties[(int)LookDevProperty.ExposureValue].floatValue; } - } - - public float envRotation - { - get { return m_Properties[(int)LookDevProperty.EnvRotation].floatValue; } - set { m_Properties[(int)LookDevProperty.EnvRotation].floatValue = value; } - } - - public int currentHDRIIndex - { - get { return m_Properties[(int)LookDevProperty.HDRI].intValue; } - set { m_Properties[(int)LookDevProperty.HDRI].intValue = value; } - } - - public int shadingMode - { - get { return m_Properties[(int)LookDevProperty.ShadingMode].intValue; } - } - - public int lodIndex - { - get { return m_Properties[(int)LookDevProperty.LoDIndex].intValue; } - } - - public LookDevContext() - { - for (int i = 0; i < (int)LookDevProperty.Count; ++i) - { - m_Properties[i] = new LookDevPropertyValue(); - } - - m_Properties[(int)LookDevProperty.ExposureValue].floatValue = 0.0f; - m_Properties[(int)LookDevProperty.HDRI].intValue = 0; - m_Properties[(int)LookDevProperty.ShadingMode].intValue = (int)DrawCameraMode.Normal; - m_Properties[(int)LookDevProperty.LoDIndex].intValue = -1; - m_Properties[(int)LookDevProperty.EnvRotation].floatValue = 0.0f; - } - - public LookDevPropertyValue GetProperty(LookDevProperty property) - { - return m_Properties[(int)property]; - } - - public void UpdateProperty(LookDevProperty property, float value) - { - m_Properties[(int)property].floatValue = value; - } - - public void UpdateProperty(LookDevProperty property, int value) - { - m_Properties[(int)property].intValue = value; - } - } -} diff --git a/Editor/Mono/LookDevView/LookDevEnvironmentLibrary.cs b/Editor/Mono/LookDevView/LookDevEnvironmentLibrary.cs deleted file mode 100644 index 1640b96854..0000000000 --- a/Editor/Mono/LookDevView/LookDevEnvironmentLibrary.cs +++ /dev/null @@ -1,227 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.Experimental.AssetImporters; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - internal class LookDevEnvironmentLibrary - : ScriptableObject, ISerializationCallbackReceiver - { - [SerializeField] private List m_HDRIList = new List(); - [SerializeField] private List m_SerialShadowMapHDRIList = new List(); // Dedicated to save shadow cubemap info for serialization purpose - - private LookDevView m_LookDevView = null; - private bool m_Dirty = false; - - public bool dirty - { - get { return m_Dirty; } - set { m_Dirty = value; } - } - - public List hdriList - { - get { return m_HDRIList; } - } - - public int hdriCount - { - get { return hdriList.Count; } - } - - public void InsertHDRI(Cubemap cubemap) - { - InsertHDRI(cubemap, -1); - } - - // If insertionIndex is -1 it mean we insert at the end of the list - public void InsertHDRI(Cubemap cubemap, int insertionIndex) - { - Undo.RecordObject(m_LookDevView.envLibrary, "Insert HDRI"); - Undo.RecordObject(m_LookDevView.config, "Insert HDRI"); - - // Handle cubemap index remapping for both context. Simply do it brute force in all cases. - // Save the cubemap info before any modification to m_HDRIList. - // Also if we are inserting m_DefaultHDRI, it mean we have an empty m_HDRIList - Cubemap cubemap0 = null; - Cubemap cubemap1 = null; - - if (cubemap == LookDevResources.m_DefaultHDRI) - { - cubemap0 = LookDevResources.m_DefaultHDRI; - cubemap1 = LookDevResources.m_DefaultHDRI; - } - else - { - cubemap0 = m_HDRIList[m_LookDevView.config.lookDevContexts[0].currentHDRIIndex].cubemap; - cubemap1 = m_HDRIList[m_LookDevView.config.lookDevContexts[1].currentHDRIIndex].cubemap; - } - - // Check if the cubemap already exist - int iIndex = m_HDRIList.FindIndex(x => x.cubemap == cubemap); - - // Create cubemap if it doesn't exist - if (iIndex == -1) - { - m_Dirty = true; - - CubemapInfo newInfo = null; - - // Check if the cubemap exist but as a shadow cubemap only - // in this case we don't recreate the CubemapInfo, but we still insert it as a new one. - for (int i = 0; i < m_HDRIList.Count; ++i) - { - if (m_HDRIList[i].cubemapShadowInfo.cubemap == cubemap) - { - newInfo = m_HDRIList[i].cubemapShadowInfo; - // Prevent recursion with shadow cubemap info - newInfo.SetCubemapShadowInfo(newInfo); - break; - } - } - - if (newInfo == null) - { - newInfo = new CubemapInfo(); - newInfo.cubemap = cubemap; - newInfo.ambientProbe.Clear(); - newInfo.alreadyComputed = false; - newInfo.SetCubemapShadowInfo(newInfo); // By default we use the same cubemap for the version without sun. - } - - int newCubemapIndex = m_HDRIList.Count; - // Add the cubemap to the specified location or last if no location provide - m_HDRIList.Insert(insertionIndex == -1 ? newCubemapIndex : insertionIndex, newInfo); - - // When inserting the default HDRI the first time, the lookdev env is not yet ready. - // But as we default the latlong light position of ShadowInfo to brightest location of default HDRI this is not a problem to not call the function. - if (newInfo.cubemap != LookDevResources.m_DefaultHDRI) - LookDevResources.UpdateShadowInfoWithBrightestSpot(newInfo); - } - - // If we haven't inserted at end of the list, if it is not a new cubemap and if we do not insert at the same place, we need to shift current cubemap position in the list - if (iIndex != insertionIndex && iIndex != -1 && insertionIndex != -1) - { - // Get cubemap info before modifying m_LookDevSetup.m_HDRIList; - CubemapInfo infos = m_HDRIList[iIndex]; - - m_HDRIList.RemoveAt(iIndex); - // If we insert after the removed cubemap we need to increase the index - m_HDRIList.Insert(iIndex > insertionIndex ? insertionIndex : insertionIndex - 1, infos); - } - - m_LookDevView.config.lookDevContexts[0].UpdateProperty(LookDevProperty.HDRI, m_HDRIList.FindIndex(x => x.cubemap == cubemap0)); - m_LookDevView.config.lookDevContexts[1].UpdateProperty(LookDevProperty.HDRI, m_HDRIList.FindIndex(x => x.cubemap == cubemap1)); - - m_LookDevView.Repaint(); - } - - public bool RemoveHDRI(Cubemap cubemap) - { - if (cubemap != null) - { - Undo.RecordObject(m_LookDevView.envLibrary, "Remove HDRI"); - Undo.RecordObject(m_LookDevView.config, "Remove HDRI"); - } - - if (cubemap == LookDevResources.m_DefaultHDRI) - { - Debug.LogWarning("Cannot remove default HDRI from the library"); - return false; - } - - int iIndex = m_HDRIList.FindIndex(x => x.cubemap == cubemap); - if (iIndex != -1) - { - Cubemap cubemap0 = m_HDRIList[m_LookDevView.config.lookDevContexts[0].currentHDRIIndex].cubemap; - Cubemap cubemap1 = m_HDRIList[m_LookDevView.config.lookDevContexts[1].currentHDRIIndex].cubemap; - - m_HDRIList.RemoveAt(iIndex); - - int defaultIndex = m_HDRIList.Count == 0 ? -1 : 0; - - // If not the one removed, restore the right indices for both views - m_LookDevView.config.lookDevContexts[0].UpdateProperty(LookDevProperty.HDRI, cubemap0 == cubemap ? defaultIndex : m_HDRIList.FindIndex(x => x.cubemap == cubemap0)); - m_LookDevView.config.lookDevContexts[1].UpdateProperty(LookDevProperty.HDRI, cubemap1 == cubemap ? defaultIndex : m_HDRIList.FindIndex(x => x.cubemap == cubemap1)); - - m_LookDevView.Repaint(); - m_Dirty = true; - return true; - } - - return false; - } - - public void CleanupDeletedHDRI() - { - while (RemoveHDRI(null)) - { - // When we suppress HDRI we will have null reference, so keep the list clean and delete in the list - } - } - - ShadowInfo GetCurrentShadowInfo() - { - return m_HDRIList[m_LookDevView.config.lookDevContexts[(int)m_LookDevView.config.currentEditionContext].currentHDRIIndex].shadowInfo; - } - - public void SetLookDevView(LookDevView lookDevView) - { - m_LookDevView = lookDevView; - } - - public void OnBeforeSerialize() - { - m_SerialShadowMapHDRIList.Clear(); - - // We need to 'convert' all shadow cubemap to index before saving, any shadow cubemap without matching HDRI in the main list - // will be added to the HDRI list for serialization. - for (int i = 0; i < m_HDRIList.Count; ++i) - { - CubemapInfo shadowCubemapInfo = m_HDRIList[i].cubemapShadowInfo; - - // Check if we have already added it to shadow cubemap list - m_HDRIList[i].serialIndexMain = m_HDRIList.FindIndex(x => x == shadowCubemapInfo); - if (m_HDRIList[i].serialIndexMain == -1) - { - m_HDRIList[i].serialIndexShadow = m_SerialShadowMapHDRIList.FindIndex(x => x == shadowCubemapInfo); - if (m_HDRIList[i].serialIndexShadow == -1) - { - m_SerialShadowMapHDRIList.Add(shadowCubemapInfo); - m_HDRIList[i].serialIndexShadow = m_SerialShadowMapHDRIList.Count - 1; - } - } - } - } - - public void OnAfterDeserialize() - { - for (int i = 0; i < m_HDRIList.Count; ++i) - { - if (m_HDRIList[i].serialIndexMain != -1) - { - m_HDRIList[i].cubemapShadowInfo = m_HDRIList[hdriList[i].serialIndexMain]; - } - else - { - m_HDRIList[i].cubemapShadowInfo = m_SerialShadowMapHDRIList[m_HDRIList[i].serialIndexShadow]; - } - } - } - } - - [CustomEditor(typeof(LookDevEnvironmentLibrary))] - internal class LookDevEnvironmentLibraryInspector : AssetImporterEditor - { - // We don't want users to edit these in the inspector - public override void OnInspectorGUI() - { - } - } -} diff --git a/Editor/Mono/LookDevView/LookDevEnvironmentWindow.cs b/Editor/Mono/LookDevView/LookDevEnvironmentWindow.cs deleted file mode 100644 index d52a4ab14e..0000000000 --- a/Editor/Mono/LookDevView/LookDevEnvironmentWindow.cs +++ /dev/null @@ -1,860 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Text; -using System.Collections.Generic; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class LookDevEnvironmentWindow - { - internal class EnvSettingsWindow - : PopupWindowContent - { - public class Styles - { - public readonly GUIStyle sMenuItem = "MenuItem"; - public readonly GUIStyle sSeparator = "sv_iconselector_sep"; - public readonly GUIContent sEnvironment = EditorGUIUtility.TrTextContent("Environment"); - public readonly GUIContent sAngleOffset = EditorGUIUtility.TrTextContent("Angle offset", "Rotate the environment"); - public readonly GUIContent sResetEnv = EditorGUIUtility.TrTextContent("Reset Environment", "Reset environment settings"); - public readonly GUIContent sShadows = EditorGUIUtility.TrTextContent("Shadows"); - public readonly GUIContent sShadowIntensity = EditorGUIUtility.TrTextContent("Shadow brightness", "Shadow brightness"); - public readonly GUIContent sShadowColor = EditorGUIUtility.TrTextContent("Color", "Shadow color"); - public readonly GUIContent sBrightest = EditorGUIUtility.TrTextContent("Set position to brightest point", "Set the shadow direction to the brightest (higher value) point of the latLong map"); - public readonly GUIContent sResetShadow = EditorGUIUtility.TrTextContent("Reset Shadows", "Reset shadow properties"); - } - - static Styles s_Styles = null; - public static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - - - private CubemapInfo m_CubemapInfo; - private LookDevView m_LookDevView; - private float kShadowSettingWidth = 200.0f; - private float kShadowSettingHeight = EditorGUI.kSingleLineHeight * 10 - 3; - - public EnvSettingsWindow(LookDevView lookDevView, CubemapInfo infos) - { - m_LookDevView = lookDevView; - m_CubemapInfo = infos; - } - - public override Vector2 GetWindowSize() - { - return new Vector2(kShadowSettingWidth, kShadowSettingHeight); - } - - private void DrawSeparator() - { - GUILayout.Space(3.0f); - GUILayout.Label(GUIContent.none, styles.sSeparator); - } - - public override void OnGUI(Rect rect) - { - GUILayout.BeginVertical(); - { - GUILayout.Label(styles.sEnvironment, EditorStyles.miniLabel); - EditorGUI.BeginChangeCheck(); - float angleOffset = EditorGUILayout.Slider(styles.sAngleOffset, m_CubemapInfo.angleOffset % 360.0f, -360.0f, 360.0f); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(m_LookDevView.envLibrary, "Changed environment settings"); - m_CubemapInfo.angleOffset = angleOffset; - m_LookDevView.envLibrary.dirty = true; - m_LookDevView.Repaint(); - } - - if (GUILayout.Button(styles.sResetEnv, EditorStyles.toolbarButton)) - { - Undo.RecordObject(m_LookDevView.envLibrary, "Changed environment settings"); - m_CubemapInfo.ResetEnvInfos(); - m_LookDevView.envLibrary.dirty = true; - m_LookDevView.Repaint(); - } - - using (new EditorGUI.DisabledScope(!m_LookDevView.config.enableShadowCubemap)) - { - DrawSeparator(); - GUILayout.Label(styles.sShadows, EditorStyles.miniLabel); - - EditorGUI.BeginChangeCheck(); - float shadowIntensity = EditorGUILayout.Slider(styles.sShadowIntensity, m_CubemapInfo.shadowInfo.shadowIntensity, 0.0f, 5.0f); - Color shadowColor = EditorGUILayout.ColorField(styles.sShadowColor, m_CubemapInfo.shadowInfo.shadowColor); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(m_LookDevView.envLibrary, "Changed shadow settings"); - m_CubemapInfo.shadowInfo.shadowIntensity = shadowIntensity; - m_CubemapInfo.shadowInfo.shadowColor = shadowColor; - m_LookDevView.envLibrary.dirty = true; - m_LookDevView.Repaint(); - } - - if (GUILayout.Button(styles.sBrightest, EditorStyles.toolbarButton)) - { - Undo.RecordObject(m_LookDevView.envLibrary, "Changed shadow settings"); - LookDevResources.UpdateShadowInfoWithBrightestSpot(m_CubemapInfo); - m_LookDevView.envLibrary.dirty = true; - m_LookDevView.Repaint(); - } - - if (GUILayout.Button(styles.sResetShadow, EditorStyles.toolbarButton)) - { - Undo.RecordObject(m_LookDevView.envLibrary, "Changed shadow settings"); - m_CubemapInfo.SetCubemapShadowInfo(m_CubemapInfo); - m_LookDevView.envLibrary.dirty = true; - m_LookDevView.Repaint(); - } - } - } - GUILayout.EndVertical(); - } - } - - public class Styles - { - public readonly GUIContent sTitle = EditorGUIUtility.TrTextContent("HDRI View", "Manage your list of HDRI environments."); - public readonly GUIContent sCloseIcon = new GUIContent(EditorGUIUtility.IconContent("LookDevClose")); - public readonly GUIStyle sSeparatorStyle = "sv_iconselector_sep"; - public readonly GUIStyle sLabelStyleFirstContext = new GUIStyle(EditorStyles.miniLabel); - public readonly GUIStyle sLabelStyleSecondContext = new GUIStyle(EditorStyles.miniLabel); - public readonly GUIStyle sLabelStyleBothContext = new GUIStyle(EditorStyles.miniLabel); - public readonly Texture sLightTexture = EditorGUIUtility.FindTexture("LookDevLight"); - public readonly Texture sLatlongFrameTexture = EditorGUIUtility.FindTexture("LookDevShadowFrame"); - public readonly GUIContent sEnvControlIcon = new GUIContent(EditorGUIUtility.IconContent("LookDevPaneOption")); - public readonly GUIContent sDragAndDropHDRIText = EditorGUIUtility.TrTextContent("Drag and drop HDR panorama here."); - - public Styles() - { - sLabelStyleFirstContext.normal.textColor = LookDevView.m_FirstViewGizmoColor; - sLabelStyleSecondContext.normal.textColor = LookDevView.m_SecondViewGizmoColor; - sLabelStyleBothContext.normal.textColor = EditorGUIUtility.isProSkin ? Color.white : Color.black; - - sEnvControlIcon.tooltip = "Environment parameters"; - } - } - - static Styles s_Styles = new Styles(); - public static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - - private LookDevView m_LookDevView; - - private Vector2 m_ScrollPosition = new Vector2(0.0f, 0.0f); - private Rect m_PositionInLookDev; - private Cubemap m_SelectedCubemap = null; - private CubemapInfo m_SelectedCubemapInfo = null; - private CubemapInfo m_SelectedShadowCubemapOwnerInfo = null; - private int m_SelectedLightIconIndex = -1; - private ShadowInfo m_SelectedShadowInfo = null; - private bool m_RenderOverlayThumbnailOnce = false; - private int m_SelectedCubeMapOffsetIndex = -1; - private int m_HoveringCubeMapIndex = -1; - private float m_SelectedCubeMapOffsetValue = 0.0f; - private Vector2 m_SelectedPositionOffset = new Vector2(0.0f, 0.0f); - private Rect m_GUIRect; - private Rect m_displayRect; - private bool m_DragBeingPerformed = false; - - public const float m_latLongHeight = 125.0f; - public const float m_HDRIHeaderHeight = 18.0f; // Careful, labels/button are 16 but toggle is 18 so we put everyone at 18 - public const float m_HDRIHeight = m_HDRIHeaderHeight + m_latLongHeight + 3.0f; // Separator height - public const float m_HDRIWidth = 250.0f; - const float kButtonWidth = 16, kButtonHeight = 16; - - public LookDevEnvironmentWindow(LookDevView lookDevView) - { - m_LookDevView = lookDevView; - } - - public void SetRects(Rect positionInLookDev, Rect GUIRect, Rect displayRect) - { - m_PositionInLookDev = positionInLookDev; - m_GUIRect = GUIRect; - m_displayRect = displayRect; - } - - public Cubemap GetCurrentSelection() - { - return m_SelectedCubemap; - } - - public Vector2 GetSelectedPositionOffset() - { - return m_SelectedPositionOffset; - } - - public void CancelSelection() - { - m_SelectedCubemap = null; - m_SelectedCubemapInfo = null; - m_SelectedShadowCubemapOwnerInfo = null; - m_SelectedLightIconIndex = -1; - m_SelectedShadowInfo = null; - m_HoveringCubeMapIndex = -1; - m_DragBeingPerformed = false; - } - - private float ComputeAngleOffsetFromMouseCoord(Vector2 mousePosition) - { - return mousePosition.x / m_HDRIWidth * 360.0f; - } - - // Returns normalized coord [-1..1] from latitude/longitude ([-90..90]/[0..360]) - private Vector2 LatLongToPosition(float latitude, float longitude) - { - latitude = (latitude + 90.0f) % 180.0f - 90.0f; - if (latitude < -90.0f) latitude = -90.0f; - if (latitude > 89.0f) latitude = 89.0f; - - longitude = longitude % 360.0f; - if (longitude < 0.0) - longitude = 360.0f + longitude; - - Vector2 result = new Vector2(longitude * Mathf.Deg2Rad / (2.0f * Mathf.PI) * 2.0f - 1.0f, latitude * Mathf.Deg2Rad / (Mathf.PI * 0.5f)); - return result; - } - - // Returns latitude/longtitude ([-90..90]/[0..360]) from normalized coord [-1..1] - static public Vector2 PositionToLatLong(Vector2 position) - { - Vector2 result = new Vector2(); - result.x = position.y * Mathf.PI * 0.5f * Mathf.Rad2Deg; - result.y = ((position.x * 0.5f + 0.5f) * 2.0f * Mathf.PI * Mathf.Rad2Deg); - - if (result.x < -90.0f) result.x = -90.0f; - if (result.x > 89.0f) result.x = 89.0f; - - return result; - } - - private Rect GetInsertionRect(int envIndex) - { - // Rect between each environment. - // Used to know if user wants to insert an environment between two other. - Rect insertionRect = m_GUIRect; - insertionRect.height = m_HDRIHeight - m_latLongHeight; - insertionRect.y = m_HDRIHeight * envIndex; - return insertionRect; - } - - private int IsPositionInInsertionArea(Vector2 pos) - { - // A HDRI can be insert in last position, so i goes up to count (<=) - for (int i = 0; i <= m_LookDevView.envLibrary.hdriCount; ++i) - { - Rect insertionRect = GetInsertionRect(i); - if (insertionRect.Contains(pos)) - { - return i; - } - } - - return -1; - } - - private Rect GetThumbnailRect(int envIndex) - { - Rect thumbnailRect = m_GUIRect; - - thumbnailRect.height = m_latLongHeight; - thumbnailRect.y = envIndex * m_HDRIHeight + m_HDRIHeaderHeight; - return thumbnailRect; - } - - private int IsPositionInThumbnailArea(Vector2 pos) - { - for (int i = 0; i < m_LookDevView.envLibrary.hdriCount; ++i) - { - Rect thumbnailRect = GetThumbnailRect(i); - if (thumbnailRect.Contains(pos)) - { - return i; - } - } - - return -1; - } - - private void RenderOverlayThumbnailIfNeeded() - { - // An environment was selected, stores the corresponding latlong texture for later overlay rendering - if (m_RenderOverlayThumbnailOnce && Event.current.type == EventType.Repaint && m_SelectedCubemapInfo != null) - { - m_SelectedCubemap = m_SelectedCubemapInfo.cubemap; - - RenderTexture oldActive = RenderTexture.active; - RenderTexture.active = LookDevResources.m_SelectionTexture; - LookDevResources.m_LookDevCubeToLatlong.SetTexture("_MainTex", m_SelectedCubemap); - LookDevResources.m_LookDevCubeToLatlong.SetVector("_WindowParams", new Vector4(m_displayRect.height, -1000.0f, 2, 1.0f)); // Doesn't matter but let's match DrawLatLongThumbnail settings,-1000.0f to be sure to not have clipping issue (we should not clip normally but don't want to create a new shader) - LookDevResources.m_LookDevCubeToLatlong.SetVector("_CubeToLatLongParams", new Vector4(Mathf.Deg2Rad * m_SelectedCubemapInfo.angleOffset, 0.5f, 1.0f, 0.0f)); - LookDevResources.m_LookDevCubeToLatlong.SetPass(0); - LookDevView.DrawFullScreenQuad(new Rect(0, 0, m_HDRIWidth, m_latLongHeight)); - RenderTexture.active = oldActive; - - m_RenderOverlayThumbnailOnce = false; - } - } - - private void DrawLatLongThumbnail(CubemapInfo infos, float angleOffset, float intensity, float alpha, Rect textureRect) - { - // We need texture rect to clip correctly the Graphics.DrawTexture done for library GUI (otherwise it goes out the window) - // But we can't use scissor rect here to clip the texture when outside the draw area because SetScissorRect in script only work if we are - // in C++ code that have scissor enable, which is not the case here. We will clip in shader instead. - // For this we will use the VPOS register and the y position of the widget to clip (see LookDevCubeToLatlong.shader). - // To get current position y we need to take into account the tab panel + the menu panel. Menu panel size is in m_PositionInLookDev.y - // But tabsize panel is in DockAreas.cs: BeginOffsetArea (new Rect (r.x + 2, r.y + kTabHeight, r.width - 4, r.height - kTabHeight - 2), GUIContent.none, "TabWindowBackground"); - // This part exactly: r.y + kTabHeight. r.y seems to always be 2 so use that for now (setup in z) and is store in ((GUIStyle)("dockarea"))overlay.margin.top - GUIStyle overlay = "dockarea"; - LookDevResources.m_LookDevCubeToLatlong.SetVector("_WindowParams", new Vector4(m_displayRect.height, m_PositionInLookDev.y + DockArea.kTabHeight, overlay.margin.top, EditorGUIUtility.pixelsPerPoint)); - LookDevResources.m_LookDevCubeToLatlong.SetVector("_CubeToLatLongParams", new Vector4(Mathf.Deg2Rad * angleOffset, alpha, intensity, 0.0f)); - - Graphics.DrawTexture(textureRect, infos.cubemap, LookDevResources.m_LookDevCubeToLatlong, 1); - } - - private void DrawSelectionFeedback(Rect textureRect, Color selectionColor1, Color selectionColor2) - { - // In case the environment is currently used in the look dev view - // Draw a feedback rectangle around the image. - // Two half rectangle : blue + blue / orange + orange / blue + orange depending on which side the environment is on. - float xMin = 0.5f; - float xMax = textureRect.width - 0.5f; - float yMin = textureRect.y + 0.5f; - float yMax = textureRect.y + textureRect.height - 1.0f; - float xHalf = textureRect.width * 0.5f; - - Vector3[] points = - { - new Vector3(xHalf, yMin, 0.0f), new Vector3(xMin, yMin, 0.0f), - new Vector3(xMin, yMin, 0.0f), new Vector3(xMin, yMax, 0.0f), - new Vector3(xMin, yMax, 0.0f), new Vector3(xHalf, yMax, 0.0f) - }; - - Vector3[] points2 = - { - new Vector3(xHalf, yMin, 0.0f), new Vector3(xMax, yMin, 0.0f), - new Vector3(xMax, yMin, 0.0f), new Vector3(xMax, yMax, 0.0f), - new Vector3(xMax, yMax, 0.0f), new Vector3(xHalf, yMax, 0.0f) - }; - - Handles.color = selectionColor1; - Handles.DrawLines(points); - - Handles.color = selectionColor2; - Handles.DrawLines(points2); - } - - // If there is a currently active selection drag and drop move that originate from a shadow cubemap this call will remove the reference - // Public to be call by LookDevView - // Must be call before any insertion or modification of HDRI list - public void ResetShadowCubemap() - { - if (m_SelectedShadowCubemapOwnerInfo != null) - { - m_SelectedShadowCubemapOwnerInfo.SetCubemapShadowInfo(m_SelectedShadowCubemapOwnerInfo); - } - } - - private void HandleMouseInput() - { - List cubemapList = m_LookDevView.envLibrary.hdriList; - - Vector2 scrollFixedPosition = new Vector2(Event.current.mousePosition.x, Event.current.mousePosition.y + m_ScrollPosition.y); - - Event evt = Event.current; - switch (evt.GetTypeForControl(m_LookDevView.hotControl)) - { - // Update overlay position for next repaint event - case EventType.MouseDrag: - { - if (m_SelectedCubeMapOffsetIndex != -1) - { - Undo.RecordObject(m_LookDevView.envLibrary, ""); - CubemapInfo info = cubemapList[m_SelectedCubeMapOffsetIndex]; - info.angleOffset = ComputeAngleOffsetFromMouseCoord(scrollFixedPosition) + m_SelectedCubeMapOffsetValue; - m_LookDevView.envLibrary.dirty = true; - Event.current.Use(); - } - - if (m_SelectedCubemapInfo != null) - { - if (IsPositionInInsertionArea(scrollFixedPosition) == -1) - m_HoveringCubeMapIndex = IsPositionInThumbnailArea(scrollFixedPosition); - else - m_HoveringCubeMapIndex = -1; - } - - m_LookDevView.Repaint(); - break; - } - - // Handles environment drop - case EventType.MouseUp: - { - if (m_SelectedCubemap != null) - { - // The rect needs to include an extra slot when moving to last position - Rect extendedGUIRect = m_GUIRect; - extendedGUIRect.yMax += EditorGUI.kSingleLineHeight; - - if (extendedGUIRect.Contains(Event.current.mousePosition)) - { - int insertionRectIndex = IsPositionInInsertionArea(scrollFixedPosition); - if (insertionRectIndex != -1) - { - // Must be called before we do any modification to HDRI list - ResetShadowCubemap(); - - m_LookDevView.envLibrary.InsertHDRI(m_SelectedCubemap, insertionRectIndex); - } - else - { - int thumbnailRectIndex = IsPositionInThumbnailArea(scrollFixedPosition); - if (thumbnailRectIndex != -1 && m_LookDevView.config.enableShadowCubemap) - { - Undo.RecordObject(m_LookDevView.envLibrary, "Update shadow cubemap"); - CubemapInfo cubemapInfo = m_LookDevView.envLibrary.hdriList[thumbnailRectIndex]; - - // We don't want the user to drop a cubemap on itself and reset the shadows (it would happen all the time by mistake) - if (cubemapInfo != m_SelectedCubemapInfo) - { - cubemapInfo.SetCubemapShadowInfo(m_SelectedCubemapInfo); - } - m_LookDevView.envLibrary.dirty = true; - } - } - CancelSelection(); - } - } - - m_LookDevView.Repaint(); - - if (m_SelectedCubeMapOffsetIndex != -1) - { - // Fall back to zero when near the center - if (Mathf.Abs(cubemapList[m_SelectedCubeMapOffsetIndex].angleOffset) <= 10.0f) - { - Undo.RecordObject(m_LookDevView.envLibrary, ""); - cubemapList[m_SelectedCubeMapOffsetIndex].angleOffset = 0.0f; - m_LookDevView.envLibrary.dirty = true; - } - } - m_SelectedCubemapInfo = null; - m_SelectedShadowCubemapOwnerInfo = null; - m_SelectedLightIconIndex = -1; - m_SelectedShadowInfo = null; - m_SelectedCubeMapOffsetIndex = -1; - m_HoveringCubeMapIndex = -1; - m_SelectedCubeMapOffsetValue = 0.0f; - - GUIUtility.hotControl = 0; - - break; - } - - // Escape closes the window - case EventType.KeyDown: - { - if (Event.current.keyCode == KeyCode.Escape) - { - CancelSelection(); - m_LookDevView.Repaint(); - } - break; - } - - case EventType.DragPerform: - { - int insertionIndex = IsPositionInInsertionArea(scrollFixedPosition); - - foreach (UnityEngine.Object o in DragAndDrop.objectReferences) - { - Cubemap cubemap = o as Cubemap; - if (cubemap) - { - // When insertion outside the list the index is -1 which mean in InsertHDRI that it will be add at the end - m_LookDevView.envLibrary.InsertHDRI(cubemap, insertionIndex); - } - } - - DragAndDrop.AcceptDrag(); - m_DragBeingPerformed = false; - evt.Use(); - break; - } - case EventType.DragUpdated: - { - bool hasCubemap = false; - foreach (UnityEngine.Object o in DragAndDrop.objectReferences) - { - Cubemap cubemap = o as Cubemap; - if (cubemap) - { - hasCubemap = true; - } - } - DragAndDrop.visualMode = hasCubemap ? DragAndDropVisualMode.Link : DragAndDropVisualMode.Rejected; - if (hasCubemap) - { - m_DragBeingPerformed = true; - } - evt.Use(); - } - break; - case EventType.DragExited: - break; - case EventType.Repaint: - - if (m_SelectedCubeMapOffsetIndex != -1) - { - EditorGUIUtility.AddCursorRect(m_displayRect, MouseCursor.SlideArrow); - } - break; - } - } - - void GetFrameAndShadowTextureRect(Rect textureRect, out Rect frameTextureRect, out Rect shadowTextureRect) - { - frameTextureRect = textureRect; - frameTextureRect.x += (textureRect.width - styles.sLatlongFrameTexture.width); - frameTextureRect.y += (textureRect.height - styles.sLatlongFrameTexture.height * 1.05f); - frameTextureRect.width = styles.sLatlongFrameTexture.width; - frameTextureRect.height = styles.sLatlongFrameTexture.height; - - // These are hard coded values depending on the LatLongFrame texture and provided by the artist. - shadowTextureRect = frameTextureRect; - shadowTextureRect.x += 6.0f; - shadowTextureRect.y += 4.0f; - shadowTextureRect.width = 105.0f; - shadowTextureRect.height = 52.0f; - } - - public void OnGUI(int windowID) - { - if (m_LookDevView == null) - return; - - List cubemapList = m_LookDevView.envLibrary.hdriList; - - // Enable the ScrollView component only if there is enough HDRI (else HDRI will display on top of a scrollbar when moved) - bool drawScrollBar = LookDevEnvironmentWindow.m_HDRIHeight * cubemapList.Count > m_PositionInLookDev.height; - - if (drawScrollBar) - { - m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition); - } - else - { - m_ScrollPosition = new Vector2(0.0f, 0.0f); - } - - if (cubemapList.Count == 1) - { - // Draw text - Color oldColor = GUI.color; - GUI.color = Color.gray; - Vector2 textSize = GUI.skin.label.CalcSize(styles.sDragAndDropHDRIText); - Rect labelRect = new Rect(m_PositionInLookDev.width * .5f - textSize.x * .5f, m_PositionInLookDev.height * .5f - textSize.y * .5f, textSize.x, textSize.y); - GUI.Label(labelRect, styles.sDragAndDropHDRIText); - GUI.color = oldColor; - } - - { - for (int i = 0; i < cubemapList.Count; ++i) - { - CubemapInfo infos = cubemapList[i]; - ShadowInfo shadowInfos = infos.shadowInfo; - - int firstSelectionIndex = m_LookDevView.config.GetIntProperty(LookDevProperty.HDRI, LookDevEditionContext.Left); - int secondSelectionIndex = m_LookDevView.config.GetIntProperty(LookDevProperty.HDRI, LookDevEditionContext.Right); - - // Disable the drawing of second selection if we are in single view - if (m_LookDevView.config.lookDevMode == LookDevMode.Single1 || m_LookDevView.config.lookDevMode == LookDevMode.Single2) - { - secondSelectionIndex = -1; - } - - bool isSelection = (i == firstSelectionIndex || i == secondSelectionIndex); - - Color selectionColor1 = Color.black; - Color selectionColor2 = Color.black; - GUIStyle selectionLabelStyle = EditorStyles.miniLabel; - - if (isSelection) - { - if (i == firstSelectionIndex) - { - selectionColor1 = LookDevView.m_FirstViewGizmoColor; - selectionColor2 = LookDevView.m_FirstViewGizmoColor; - selectionLabelStyle = styles.sLabelStyleFirstContext; - } - else if (i == secondSelectionIndex) - { - selectionColor1 = LookDevView.m_SecondViewGizmoColor; - selectionColor2 = LookDevView.m_SecondViewGizmoColor; - selectionLabelStyle = styles.sLabelStyleSecondContext; - } - if (firstSelectionIndex == secondSelectionIndex) - { - selectionColor1 = LookDevView.m_FirstViewGizmoColor; - selectionColor2 = LookDevView.m_SecondViewGizmoColor; - selectionLabelStyle = styles.sLabelStyleBothContext; - } - } - - Rect textureRect; - Rect lightIconRect; - Rect lightIconSelectionRect; - Rect frameTextureRect; - Rect shadowTextureRect; - GUILayout.BeginVertical(GUILayout.Width(m_HDRIWidth)); - { - // Find index of current selection if it exist - int selectedCubeMapIndex = cubemapList.FindIndex(x => x == m_SelectedCubemapInfo); - - // User is dragging another environment, we need to show the space for insertion - if ((m_SelectedCubemap != null || m_DragBeingPerformed) && GetInsertionRect(i).Contains(Event.current.mousePosition) - // Following test allow to not propose a slot that is neutral, i.e current position or next one - && (((selectedCubeMapIndex - i) != 0 && (selectedCubeMapIndex - i) != -1) || selectedCubeMapIndex == -1) - ) - { - GUILayout.Label(GUIContent.none, styles.sSeparatorStyle); - GUILayoutUtility.GetRect(m_HDRIWidth, EditorGUI.kSingleLineHeight); - } - - // Header for one HDRI: label + remove button - GUILayout.Label(GUIContent.none, styles.sSeparatorStyle); - GUILayout.BeginHorizontal(GUILayout.Width(m_HDRIWidth), GUILayout.Height(m_HDRIHeaderHeight)); - { - StringBuilder sb = new StringBuilder(); - sb.Append(i.ToString()); - sb.Append(" - "); - sb.Append(infos.cubemap.name); - - GUILayout.Label(sb.ToString(), selectionLabelStyle, GUILayout.Height(m_HDRIHeaderHeight), GUILayout.MaxWidth(m_HDRIWidth - 75)); - - GUILayout.FlexibleSpace(); - - if (GUILayout.Button(styles.sEnvControlIcon, LookDevView.styles.sToolBarButton)) - { - Rect rect = GUILayoutUtility.topLevel.GetLast(); - PopupWindow.Show(rect, new EnvSettingsWindow(m_LookDevView, infos)); - GUIUtility.ExitGUI(); - } - - using (new EditorGUI.DisabledScope(infos.cubemap == LookDevResources.m_DefaultHDRI)) - { - if (GUILayout.Button(styles.sCloseIcon, LookDevView.styles.sToolBarButton)) - { - m_LookDevView.envLibrary.RemoveHDRI(infos.cubemap); - } - } - } - GUILayout.EndHorizontal(); - - // We don't want to handle any control inside the label, following code disable mouseDown event in this case. - Rect lastRect = GUILayoutUtility.GetLastRect(); - if (Event.current.type == EventType.MouseDown && lastRect.Contains(Event.current.mousePosition)) - { - Event.current.Use(); // Avoid camera movement and focus change in main view - } - - textureRect = GUILayoutUtility.GetRect(m_HDRIWidth, m_latLongHeight); - textureRect.width = m_HDRIWidth + 3; // Sometimes GUILayoutUtility.GetRect returns width as m_HDRIWidth, sometimes at m_HDRIWidth + 3 ... - - float iconSize = 24.0f; - float iconHalfSize = iconSize * 0.5f; - - // Convert from latlong to normalized coordinate to pixel coordinates. - float latitude = shadowInfos.latitude; - float longitude = shadowInfos.longitude; - Vector2 iconPosition = LatLongToPosition(latitude, longitude + infos.angleOffset) * 0.5f + new Vector2(0.5f, 0.5f); - - lightIconRect = textureRect; - lightIconRect.x = lightIconRect.x + iconPosition.x * textureRect.width - iconHalfSize; - lightIconRect.y = lightIconRect.y + (1.0f - iconPosition.y) * textureRect.height - iconHalfSize; // Coordinates start from the bottom - lightIconRect.width = iconSize; - lightIconRect.height = iconSize; - - // Selection rect of light is a bit smaller than the texture - lightIconSelectionRect = textureRect; - lightIconSelectionRect.x = lightIconSelectionRect.x + iconPosition.x * textureRect.width - iconHalfSize * 0.5f; - lightIconSelectionRect.y = lightIconSelectionRect.y + (1.0f - iconPosition.y) * textureRect.height - iconHalfSize * 0.5f; // Coordinates start from the bottom - lightIconSelectionRect.width = iconSize * 0.5f; - lightIconSelectionRect.height = iconSize * 0.5f; - - GetFrameAndShadowTextureRect(textureRect, out frameTextureRect, out shadowTextureRect); - - if (m_LookDevView.config.enableShadowCubemap) - { - EditorGUIUtility.AddCursorRect(lightIconSelectionRect, MouseCursor.Pan); - } - - if (Event.current.type == EventType.MouseDown && textureRect.Contains(Event.current.mousePosition)) - { - // Left Button - if ((!Event.current.control && Event.current.button == 0) && m_SelectedCubeMapOffsetIndex == -1) - { - // Light icon handling - it is higher priority then shadowTexture thumbnail selection - if (m_LookDevView.config.enableShadowCubemap && lightIconSelectionRect.Contains(Event.current.mousePosition)) - { - m_SelectedLightIconIndex = i; - m_SelectedShadowInfo = shadowInfos; - - // We want to avoid to record object when draging the light icon, so save location here. - // However the record need to be aware about what will change, so we perform an insignificant modification - // to the lat/long position so it is record by the undo - Undo.RecordObject(m_LookDevView.envLibrary, "Light Icon selection"); - m_SelectedShadowInfo.latitude = m_SelectedShadowInfo.latitude + 0.0001f; - m_SelectedShadowInfo.longitude = m_SelectedShadowInfo.longitude + 0.0001f; - } - - // Environment selection handling - if (m_SelectedShadowInfo == null) - { - Rect resetShadowIconRect; - // All values are taken from the LookDevShadowFrame.png (hard coded) - resetShadowIconRect = frameTextureRect; - resetShadowIconRect.x = resetShadowIconRect.x + 100.0f; - resetShadowIconRect.y = resetShadowIconRect.y + 4.0f; - resetShadowIconRect.width = 11; - resetShadowIconRect.height = 11f; - - // Close icon handling - if (m_LookDevView.config.enableShadowCubemap && resetShadowIconRect.Contains(Event.current.mousePosition)) - { - // Reset Shadow Cubemap - Undo.RecordObject(m_LookDevView.envLibrary, "Update shadow cubemap"); - cubemapList[i].SetCubemapShadowInfo(cubemapList[i]); - m_LookDevView.envLibrary.dirty = true; - } - else - { - // If we have selected the shadowTexture, let's swap the index of the current selected map - if (m_LookDevView.config.enableShadowCubemap && shadowTextureRect.Contains(Event.current.mousePosition)) - { - m_SelectedShadowCubemapOwnerInfo = cubemapList[i]; - // Current selected cubemap is the one without sun - m_SelectedCubemapInfo = m_SelectedShadowCubemapOwnerInfo.cubemapShadowInfo; - } - else - { - m_SelectedCubemapInfo = cubemapList[i]; - } - m_SelectedPositionOffset = Event.current.mousePosition - new Vector2(textureRect.x, textureRect.y); - m_RenderOverlayThumbnailOnce = true; - } - } - } - // Left button with Ctrl - Rotate environment - else if ((Event.current.control && Event.current.button == 0) && m_SelectedCubemapInfo == null && m_SelectedShadowInfo == null) - { - m_SelectedCubeMapOffsetIndex = i; - m_SelectedCubeMapOffsetValue = infos.angleOffset - ComputeAngleOffsetFromMouseCoord(Event.current.mousePosition); - } - - GUIUtility.hotControl = m_LookDevView.hotControl; - - Event.current.Use(); // Avoid camera movement and focus change in main view - } - - - if (Event.current.GetTypeForControl(m_LookDevView.hotControl) == EventType.MouseDrag) - { - if (m_SelectedShadowInfo == shadowInfos && m_SelectedLightIconIndex == i) - { - Vector2 newLightPosition = Event.current.mousePosition; - newLightPosition.x = (newLightPosition.x - textureRect.x) / textureRect.width * 2.0f - 1.0f; - newLightPosition.y = (1.0f - (newLightPosition.y - textureRect.y) / textureRect.height) * 2.0f - 1.0f; - - Vector2 newLatLongPos = PositionToLatLong(newLightPosition); - m_SelectedShadowInfo.latitude = newLatLongPos.x; - m_SelectedShadowInfo.longitude = newLatLongPos.y - infos.angleOffset; - - m_LookDevView.envLibrary.dirty = true; - } - } - - if (Event.current.type == EventType.Repaint) - { - // Draw the latlong thumbnail - DrawLatLongThumbnail(infos, infos.angleOffset, 1.0f, 1.0f, textureRect); - - if (m_LookDevView.config.enableShadowCubemap) - { - // Draw the shadow cubemap thumbnail if either: - if ((infos.cubemapShadowInfo != infos) || // Shadows are enabled on this environment and shadow cubemap is not self - (m_HoveringCubeMapIndex == i && m_SelectedCubemapInfo != infos) // user is dragging over the environment that is not itself - ) - { - // By default, we want to display the shadow cubemap associated with the current environment - CubemapInfo cubemapShadowInfo = infos.cubemapShadowInfo; - // If we are dragging another environment we want to display instead of the current one unless we are dragging a cubemap over itself - if (m_HoveringCubeMapIndex == i && m_SelectedCubemapInfo != infos) - { - cubemapShadowInfo = m_SelectedCubemapInfo; - } - - float alpha = 1.0f; - if (m_SelectedShadowInfo == shadowInfos) // We need to fade the thumbnail almost completely to see where we move the light - { - alpha = 0.1f; - } - else if (m_HoveringCubeMapIndex == i && m_SelectedCubemapInfo != infos && infos.cubemapShadowInfo != m_SelectedCubemapInfo) // Visual transparent feedback to show where you are going to drop your cubemap - { - alpha = 0.5f; - } - - DrawLatLongThumbnail(cubemapShadowInfo, infos.angleOffset, 0.3f, alpha, shadowTextureRect); - - GUI.DrawTexture(frameTextureRect, styles.sLatlongFrameTexture); - } - - GUI.DrawTexture(lightIconRect, styles.sLightTexture); - } - - if (isSelection) - { - DrawSelectionFeedback(textureRect, selectionColor1, selectionColor2); - } - } - } - GUILayout.EndVertical(); - } - - // Last vertical slot when drag and drop HDRI - GUILayout.BeginVertical(GUILayout.Width(m_HDRIWidth)); - { - // User is dragging another environment, we need to show the space for insertion - if ((m_SelectedCubemap != null || m_DragBeingPerformed) && GetInsertionRect(cubemapList.Count).Contains(Event.current.mousePosition)) - { - GUILayout.Label(GUIContent.none, styles.sSeparatorStyle); - GUILayoutUtility.GetRect(m_HDRIWidth, EditorGUI.kSingleLineHeight); - GUILayout.Label(GUIContent.none, styles.sSeparatorStyle); - } - } - GUILayout.EndVertical(); - } - - if (drawScrollBar) - { - EditorGUILayout.EndScrollView(); - } - - HandleMouseInput(); - RenderOverlayThumbnailIfNeeded(); - - if (Event.current.type == EventType.Repaint) - { - if (m_SelectedCubemap != null) - { - m_LookDevView.Repaint(); - } - } - } - } -} diff --git a/Editor/Mono/LookDevView/LookDevInc.cs b/Editor/Mono/LookDevView/LookDevInc.cs deleted file mode 100644 index 4ef3a62b9d..0000000000 --- a/Editor/Mono/LookDevView/LookDevInc.cs +++ /dev/null @@ -1,428 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEditor.AnimatedValues; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal enum LookDevPropertyType - { - Int = 0, - Float, - } - - internal enum LookDevProperty - { - ExposureValue = 0, - HDRI, - ShadingMode, - EnvRotation, - LoDIndex, - Count - } - - internal enum LookDevMode - { - Single1 = 0, - Single2, - SideBySide, - Split, - Zone, - Count - } - - internal enum LookDevEditionContext - { - Left = 0, - Right = 1, - None = 2 - } - - enum LookDevOperationType - { - None = 0, - GizmoTranslation, - GizmoRotationZone1, - GizmoRotationZone2, - GizmoAll, // Used in shader to highlight all gizmo parts - BlendFactor, - RotateLight, - RotateEnvironment - } - - [Serializable] - internal class GizmoInfo - { - [SerializeField] - private Vector2 m_Point1; - [SerializeField] - private Vector2 m_Point2; - [SerializeField] - private Vector2 m_Center = new Vector2(0.0f, 0.0f); - [SerializeField] - private float m_Angle = 0.0f; - [SerializeField] - private float m_Length = 0.2f; - [SerializeField] - private Vector4 m_Plane; - [SerializeField] - private Vector4 m_PlaneOrtho; - - public GizmoInfo() - { - Update(m_Center, m_Length, m_Angle); - } - - public Vector2 point1 - { - get { return m_Point1; } - } - - public Vector2 point2 - { - get { return m_Point2; } - } - - public Vector2 center - { - get { return m_Center; } - } - - public float angle - { - get { return m_Angle; } - } - - public float length - { - get { return m_Length; } - } - - public Vector4 plane - { - get { return m_Plane; } - } - - public Vector4 planeOrtho - { - get { return m_PlaneOrtho; } - } - - private Vector4 Get2DPlane(Vector2 firstPoint, float angle) - { - Vector4 result = new Vector4(); - angle = angle % (2.0f * (float)Math.PI); - Vector2 secondPoint = new Vector2(firstPoint.x + Mathf.Sin(angle), firstPoint.y + Mathf.Cos(angle)); - Vector2 diff = secondPoint - firstPoint; - if (Mathf.Abs(diff.x) < 1e-5) - { - result.Set(-1.0f, 0.0f, firstPoint.x, 0.0f); - float sign = Mathf.Cos(angle) > 0.0f ? 1.0f : -1.0f; - result *= sign; - } - else - { - float slope = diff.y / diff.x; - result.Set(-slope, 1.0f, -(firstPoint.y - slope * firstPoint.x), 0.0f); - } - - if (angle > Mathf.PI) - result = -result; - - float length = Mathf.Sqrt(result.x * result.x + result.y * result.y); - result = result / length; - return result; - } - - public void Update(Vector2 point1, Vector2 point2) - { - m_Point1 = point1; - m_Point2 = point2; - m_Center = (point1 + point2) * 0.5f; - m_Length = (point2 - point1).magnitude * 0.5f; - - Vector3 verticalPlane = Get2DPlane(m_Center, 0.0f); - float side = Vector3.Dot(new Vector3(point1.x, point1.y, 1.0f), verticalPlane); - m_Angle = (Mathf.Deg2Rad * Vector2.Angle(new Vector2(0.0f, 1.0f), (point1 - point2).normalized)); - if (side > 0.0f) - m_Angle = 2.0f * Mathf.PI - m_Angle; - - m_Plane = Get2DPlane(m_Center, m_Angle); - m_PlaneOrtho = Get2DPlane(m_Center, m_Angle + 0.5f * (float)Mathf.PI); - } - - public void Update(Vector2 center, float length, float angle) - { - m_Center = center; - m_Length = length; - m_Angle = angle; - - m_Plane = Get2DPlane(m_Center, m_Angle); - m_PlaneOrtho = Get2DPlane(m_Center, m_Angle + 0.5f * (float)Mathf.PI); - - Vector2 dir = new Vector2(m_PlaneOrtho.x, m_PlaneOrtho.y); - m_Point1 = m_Center + dir * m_Length; - m_Point2 = m_Center - dir * m_Length; - } - } - - [Serializable] - internal class LookDevPropertyInfo - { - [SerializeField] - private bool m_Linked = false; - [SerializeField] - private LookDevPropertyType m_PropertyType; - - public LookDevPropertyType propertyType - { - get { return m_PropertyType; } - } - public bool linked - { - get { return m_Linked; } - set { m_Linked = value; } - } - - public LookDevPropertyInfo(LookDevPropertyType type) - { - m_PropertyType = type; - } - } - - [Serializable] - internal class ShadowInfo - { - // Setup default position to be on the sun in the default HDRI. - // This is important as the defaultHDRI don't call the set brightest spot funciton on first call. - [SerializeField] - private float m_Latitude = 60.0f; // [-90..90] - [SerializeField] - private float m_Longitude = 299.0f; // [0..360] - [SerializeField] - private float m_ShadowIntensity = 1.0f; - [SerializeField] - private Color m_ShadowColor = Color.white; - - public float shadowIntensity - { - get { return m_ShadowIntensity; } - set { m_ShadowIntensity = value; } - } - - public Color shadowColor - { - get { return m_ShadowColor; } - set { m_ShadowColor = value; } - } - - public float latitude - { - get { return m_Latitude; } - set { m_Latitude = value; ConformLatLong(); } - } - - public float longitude - { - get { return m_Longitude; } - set { m_Longitude = value; ConformLatLong(); } - } - - private void ConformLatLong() - { - // Clamp latitude to [-90..90] - if (m_Latitude < -90.0f) - m_Latitude = -90.0f; - if (m_Latitude > 89.0f) - m_Latitude = 89.0f; - - // wrap longitude around - m_Longitude = m_Longitude % 360.0f; - if (m_Longitude < 0.0) - m_Longitude = 360.0f + m_Longitude; - } - } - - [Serializable] - internal class CubemapInfo - { - const float kDefaultShadowIntensity = 0.3f; - - public void SetCubemapShadowInfo(CubemapInfo newCubemapShadowInfo) - { - cubemapShadowInfo = newCubemapShadowInfo; - shadowInfo.shadowIntensity = newCubemapShadowInfo == this ? kDefaultShadowIntensity : 1.0f; - shadowInfo.shadowColor = Color.white; - } - - public void ResetEnvInfos() - { - angleOffset = 0.0f; - } - - public Cubemap cubemap; - public CubemapInfo cubemapShadowInfo; - public float angleOffset = 0.0f; - public SphericalHarmonicsL2 ambientProbe; - public ShadowInfo shadowInfo = new ShadowInfo(); - - // Dedicated to serialization workaround - // We can't serialize CubemapInfo inside a CubemapInfo, so before serializing we will 'flatten' the shadow cubemap in a new list and save index into this list. - // THis also allow to manage case of sahdow cubemap without matching HDRI in the main list. - public int serialIndexMain; - public int serialIndexShadow; - - [NonSerialized] - public bool alreadyComputed; // this is not serialized because SH are not serialized so we need to compute them again after deserialization - } - - internal class LookDevResources - { - static public SphericalHarmonicsL2 m_ZeroAmbientProbe; - static public Material m_SkyboxMaterial = null; - static public Material m_GBufferPatchMaterial = null; - static public Material m_DrawBallsMaterial = null; - static public Mesh m_ScreenQuadMesh = null; - static public Material m_LookDevCompositing = null; - static public Material m_DeferredOverlayMaterial = null; - static public Cubemap m_DefaultHDRI = null; - static public Material m_LookDevCubeToLatlong = null; - static public RenderTexture m_SelectionTexture = null; - static public RenderTexture m_BrightestPointRT = null; - static public Texture2D m_BrightestPointTexture = null; - - static public void Initialize() - { - m_ZeroAmbientProbe.Clear(); - - // For some reason, a few frames after LoadRenderDoc reset the gfx device, the pointers turn null. Is there a better way to handle that? - if (m_SkyboxMaterial == null) - m_SkyboxMaterial = new Material(Shader.Find("Skybox/Cubemap")); - - if (m_ScreenQuadMesh == null) - { - // Draw a full screen quad with GBuffer patch material - m_ScreenQuadMesh = new Mesh(); - m_ScreenQuadMesh.vertices = new Vector3[] - { - // Note: Invert Z or not should not have influence here. - new Vector3(-1, -1, 0), - new Vector3(1, 1, 0), - new Vector3(1, -1, 0), - new Vector3(-1, 1, 0) - }; - - m_ScreenQuadMesh.triangles = new int[] - { - 0, 1, 2, 1, 0, 3 - }; - } - - // Material can be null if we switch API device or when we init the first time. We can safely re-allocate everything if this is null - if (m_GBufferPatchMaterial == null) - { - m_GBufferPatchMaterial = new Material(EditorGUIUtility.LoadRequired("LookDevView/GBufferWhitePatch.shader") as Shader); - m_DrawBallsMaterial = new Material(EditorGUIUtility.LoadRequired("LookDevView/GBufferBalls.shader") as Shader); - } - - if (m_LookDevCompositing == null) - m_LookDevCompositing = new Material(EditorGUIUtility.LoadRequired("LookDevView/LookDevCompositing.shader") as Shader); - - if (m_DeferredOverlayMaterial == null) - m_DeferredOverlayMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewDeferredMaterial.mat") as Material; - - if (m_DefaultHDRI == null) - { - m_DefaultHDRI = EditorGUIUtility.Load("LookDevView/DefaultHDRI.exr") as Cubemap; - if (m_DefaultHDRI == null) - { - m_DefaultHDRI = EditorGUIUtility.Load("LookDevView/DefaultHDRI.asset") as Cubemap; - } - } - - if (m_LookDevCubeToLatlong == null) - { - m_LookDevCubeToLatlong = new Material(EditorGUIUtility.LoadRequired("LookDevView/LookDevCubeToLatlong.shader") as Shader); - } - - /* - // Debug code to remove - bool tutu = false; - if (tutu) - { - Shader devShader = Shader.Find("Custom/DevShader2") as Shader; - if (devShader != null) - m_LookDevCubeToLatlong = new Material(devShader); - } - */ - - - if (m_SelectionTexture == null) - m_SelectionTexture = new RenderTexture((int)LookDevEnvironmentWindow.m_HDRIWidth, (int)LookDevEnvironmentWindow.m_latLongHeight, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default); - - if (m_BrightestPointRT == null) - m_BrightestPointRT = new RenderTexture((int)LookDevEnvironmentWindow.m_HDRIWidth, (int)LookDevEnvironmentWindow.m_latLongHeight, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Default); - - if (m_BrightestPointTexture == null) - m_BrightestPointTexture = new Texture2D((int)LookDevEnvironmentWindow.m_HDRIWidth, (int)LookDevEnvironmentWindow.m_latLongHeight, TextureFormat.RGBAHalf, false); - } - - static public void Cleanup() - { - m_SkyboxMaterial = null; - - if (m_LookDevCompositing) - { - UnityEngine.Object.DestroyImmediate(m_LookDevCompositing); - m_LookDevCompositing = null; - } - } - - // Find brightest spot of the cubemap - static public void UpdateShadowInfoWithBrightestSpot(CubemapInfo cubemapInfo) - { - m_LookDevCubeToLatlong.SetTexture("_MainTex", cubemapInfo.cubemap); - m_LookDevCubeToLatlong.SetVector("_WindowParams", new Vector4(10000, -1000.0f, 2, 0.0f)); // Neutral value to not clip - m_LookDevCubeToLatlong.SetVector("_CubeToLatLongParams", new Vector4(Mathf.Deg2Rad * cubemapInfo.angleOffset, 0.5f, 1.0f, 3.0f)); // We use LOD 3 to take a region rather than a single pixel in the map - m_LookDevCubeToLatlong.SetPass(0); - - int width = (int)LookDevEnvironmentWindow.m_HDRIWidth; - int height = (int)LookDevEnvironmentWindow.m_latLongHeight; - - // Convert cubemap to a 2D LatLong to read on CPU - Graphics.Blit(cubemapInfo.cubemap, m_BrightestPointRT, m_LookDevCubeToLatlong); - m_BrightestPointTexture.ReadPixels(new Rect(0, 0, width, height), 0, 0, false); - m_BrightestPointTexture.Apply(); - - // CPU read back - // From Doc: The returned array is a flattened 2D array, where pixels are laid out left to right, bottom to top (i.e. row after row) - Color[] color = m_BrightestPointTexture.GetPixels(); - - float maxLum = 0.0f; - for (int y = 0; y < height; ++y) - { - for (int x = 0; x < width; ++x) - { - Vector3 rgb = new Vector3(color[y * width + x].r, color[y * width + x].g, color[y * width + x].b); - - float lum = rgb.x * 0.2126729f + rgb.y * 0.7151522f + rgb.z * 0.0721750f; - - if (maxLum < lum) - { - Vector2 vec = LookDevEnvironmentWindow.PositionToLatLong(new Vector2(((float)x / (float)(width - 1)) * 2.0f - 1.0f, ((float)y / (float)(height - 1)) * 2.0f - 1.0f)); - cubemapInfo.shadowInfo.latitude = vec.x; - cubemapInfo.shadowInfo.longitude = vec.y - cubemapInfo.angleOffset; - - maxLum = lum; - } - } - } - } - } -} diff --git a/Editor/Mono/LookDevView/LookDevSettingsWindow.cs b/Editor/Mono/LookDevView/LookDevSettingsWindow.cs deleted file mode 100644 index 959801e206..0000000000 --- a/Editor/Mono/LookDevView/LookDevSettingsWindow.cs +++ /dev/null @@ -1,278 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class LookDevSettingsWindow - : PopupWindowContent - { - public class Styles - { - public readonly GUIStyle sMenuItem = "MenuItem"; - public readonly GUIStyle sSeparator = "sv_iconselector_sep"; - - public readonly GUIContent sTitle = EditorGUIUtility.TrTextContent("Settings"); - public readonly GUIContent sMultiView = EditorGUIUtility.TrTextContent("Multi-view"); - public readonly GUIContent sCamera = EditorGUIUtility.TrTextContent("Camera"); - public readonly GUIContent sLighting = EditorGUIUtility.TrTextContent("Lighting"); - public readonly GUIContent sAnimation = EditorGUIUtility.TrTextContent("Animation"); - public readonly GUIContent sViewport = EditorGUIUtility.TrTextContent("Viewport"); - public readonly GUIContent sEnvLibrary = EditorGUIUtility.TrTextContent("Environment Library"); - public readonly GUIContent sMisc = EditorGUIUtility.TrTextContent("Misc"); - - public readonly GUIContent sResetCamera = EditorGUIUtility.TrTextContent("Fit View F"); - public readonly GUIContent sCreateNewLibrary = EditorGUIUtility.TrTextContent("Save as new library"); - public readonly GUIContent sSaveCurrentLibrary = EditorGUIUtility.TrTextContent("Save current library"); - public readonly GUIContent sResetView = EditorGUIUtility.TrTextContent("Reset View"); - public readonly GUIContent sEnableToneMap = EditorGUIUtility.TrTextContent("Enable Tone Mapping"); - public readonly GUIContent sEnableAutoExp = EditorGUIUtility.TrTextContent("Enable Auto Exposure"); - public readonly GUIContent sExposureRange = EditorGUIUtility.TrTextContent("Exposure Range"); - public readonly GUIContent sEnableShadows = EditorGUIUtility.TrTextContent("Enable Shadows"); - public readonly GUIContent sShadowDistance = EditorGUIUtility.TrTextContent("Shadow distance"); - public readonly GUIContent sShowBalls = EditorGUIUtility.TrTextContent("Show Chrome/grey balls"); - public readonly GUIContent sShowControlWindows = EditorGUIUtility.TrTextContent("Show Controls"); - public readonly GUIContent sAllowDifferentObjects = EditorGUIUtility.TrTextContent("Allow Different Objects"); - public readonly GUIContent sResyncObjects = EditorGUIUtility.TrTextContent("Resynchronize Objects"); - public readonly GUIContent sRotateObjectMode = EditorGUIUtility.TrTextContent("Rotate Objects"); - public readonly GUIContent sObjRotationSpeed = EditorGUIUtility.TrTextContent("Rotate Objects speed"); - public readonly GUIContent sRotateEnvMode = EditorGUIUtility.TrTextContent("Rotate environment"); - public readonly GUIContent sEnvRotationSpeed = EditorGUIUtility.TrTextContent("Rotate Env. speed"); - public readonly GUIContent sEnableShadowIcon = EditorGUIUtility.TrIconContent("LookDevShadow", "Toggles shadows on and off"); - public readonly GUIContent sEnableObjRotationIcon = EditorGUIUtility.IconContent("LookDevObjRotation", "ObjRotation|Toggles object rotation (turntable) on and off"); - public readonly GUIContent sEnableEnvRotationIcon = EditorGUIUtility.TrIconContent("LookDevEnvRotation", "Toggles environment rotation on and off"); - public readonly Texture sEnableShadowTexture = EditorGUIUtility.FindTexture("LookDevShadow"); - public readonly Texture sEnableObjRotationTexture = EditorGUIUtility.FindTexture("LookDevObjRotation"); - public readonly Texture sEnableEnvRotationTexture = EditorGUIUtility.FindTexture("LookDevEnvRotation"); - - public readonly GUIContent[] sMultiViewMode = - { - EditorGUIUtility.TrTextContent("Single1"), - EditorGUIUtility.TrTextContent("Single2"), - EditorGUIUtility.TrTextContent("Side by side"), - EditorGUIUtility.TrTextContent("Split-screen"), - EditorGUIUtility.TrTextContent("Zone"), - }; - - - public readonly Texture[] sMultiViewTextures = - { - EditorGUIUtility.FindTexture("LookDevSingle1"), - EditorGUIUtility.FindTexture("LookDevSingle2"), - EditorGUIUtility.FindTexture("LookDevSideBySide"), - EditorGUIUtility.FindTexture("LookDevSplit"), - EditorGUIUtility.FindTexture("LookDevZone"), - }; - } - - static Styles s_Styles = null; - public static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - - // This enum is only to calculate the size of the windows for settings. - // Below are listed the number of label, separator, checkbox, button and slider use in the menu. - // Keep in sync with the code below that generate the menu to have a correct windows size. - enum UINumElement - { - UINumDrawHeader = 6, - UINumToggle = (int)LookDevMode.Count + 7, - UINumSlider = 4, - UINumSeparator = 7, - UINumButton = 6, - - UITotalElement = UINumDrawHeader + UINumToggle + UINumSlider + UINumSeparator + UINumButton - } - - readonly float m_WindowHeight = (int)(UINumElement.UITotalElement) * EditorGUI.kSingleLineHeight; - const float m_WindowWidth = 180; - - const float kIconSize = 16.0f; - const float kIconHorizontalPadding = 3.0f; - - readonly LookDevView m_LookDevView; - - public LookDevSettingsWindow(LookDevView lookDevView) - { - m_LookDevView = lookDevView; - } - - public override Vector2 GetWindowSize() - { - return new Vector2(m_WindowWidth, m_WindowHeight); - } - - public override void OnGUI(Rect rect) - { - if (m_LookDevView == null) - return; - - GUILayout.BeginVertical(); - { - // We need to have a sufficient size to display negative float number - EditorGUIUtility.labelWidth = 130; - EditorGUIUtility.fieldWidth = 35; - - // Look Dev view mode - DrawHeader(styles.sMultiView); - - for (int i = 0; i < (int)LookDevMode.Count; ++i) - { - EditorGUI.BeginChangeCheck(); - bool value = GUILayout.Toggle(m_LookDevView.config.lookDevMode == (LookDevMode)i, styles.sMultiViewMode[i], styles.sMenuItem); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevView.UpdateLookDevModeToggle((LookDevMode)i, value); - m_LookDevView.Repaint(); - GUIUtility.ExitGUI(); - } - } - - // Camera settings - DrawSeparator(); - DrawHeader(styles.sCamera); - - if (GUILayout.Button(styles.sResetCamera, styles.sMenuItem)) - { - m_LookDevView.Frame(); - } - - m_LookDevView.config.enableToneMap = GUILayout.Toggle(m_LookDevView.config.enableToneMap, styles.sEnableToneMap, styles.sMenuItem); - EditorGUI.BeginChangeCheck(); - // Cast to int to have integer step - float newExposureRange = (float)EditorGUILayout.IntSlider(styles.sExposureRange, (int)m_LookDevView.config.exposureRange, 1, 32); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(m_LookDevView.config, "Change exposure range"); - m_LookDevView.config.exposureRange = newExposureRange; - } - - DrawSeparator(); - DrawHeader(styles.sLighting); - - EditorGUI.BeginChangeCheck(); - - GUILayout.BeginHorizontal(); - m_LookDevView.config.enableShadowCubemap = GUILayout.Toggle(m_LookDevView.config.enableShadowCubemap, styles.sEnableShadows, styles.sMenuItem); - GUILayout.EndHorizontal(); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevView.Repaint(); - } - - EditorGUI.BeginChangeCheck(); - float newShadowDistance = EditorGUILayout.Slider(styles.sShadowDistance, m_LookDevView.config.shadowDistance, 0.0f, 1000.0f); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(m_LookDevView.config, "Change shadow distance"); - m_LookDevView.config.shadowDistance = newShadowDistance; - } - - DrawSeparator(); - DrawHeader(styles.sAnimation); - - GUILayout.BeginHorizontal(); - m_LookDevView.config.rotateObjectMode = GUILayout.Toggle(m_LookDevView.config.rotateObjectMode, styles.sRotateObjectMode, styles.sMenuItem); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - m_LookDevView.config.rotateEnvMode = GUILayout.Toggle(m_LookDevView.config.rotateEnvMode, styles.sRotateEnvMode, styles.sMenuItem); - GUILayout.EndHorizontal(); - - EditorGUI.BeginChangeCheck(); - float newObjRotationSpeed = EditorGUILayout.Slider(styles.sObjRotationSpeed, m_LookDevView.config.objRotationSpeed, -5.0f, 5.0f); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(m_LookDevView.config, "Change rotation speed"); - m_LookDevView.config.objRotationSpeed = newObjRotationSpeed; - } - - EditorGUI.BeginChangeCheck(); - float newEnvRotationSpeed = EditorGUILayout.Slider(styles.sEnvRotationSpeed, m_LookDevView.config.envRotationSpeed, -5.0f, 5.0f); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(m_LookDevView.config, "Change env speed"); - m_LookDevView.config.envRotationSpeed = newEnvRotationSpeed; - } - - DrawSeparator(); - DrawHeader(styles.sViewport); - if (GUILayout.Button(styles.sResetView, styles.sMenuItem)) - { - m_LookDevView.ResetView(); - } - - DrawSeparator(); - DrawHeader(styles.sEnvLibrary); - using (new EditorGUI.DisabledScope(!m_LookDevView.envLibrary.dirty)) - { - if (GUILayout.Button(styles.sSaveCurrentLibrary, styles.sMenuItem)) - { - editorWindow.Close(); - if (m_LookDevView.SaveLookDevLibrary()) - m_LookDevView.envLibrary.dirty = false; - GUIUtility.ExitGUI(); - } - } - if (GUILayout.Button(styles.sCreateNewLibrary, styles.sMenuItem)) - { - editorWindow.Close(); - string assetPath = EditorUtility.SaveFilePanelInProject("Save New Environment Library", "New Env Library", "asset", ""); - if (!string.IsNullOrEmpty(assetPath)) - { - m_LookDevView.CreateNewLibrary(assetPath); - } - - GUIUtility.ExitGUI(); - } - EditorGUI.BeginChangeCheck(); - LookDevEnvironmentLibrary library = EditorGUILayout.ObjectField(m_LookDevView.userEnvLibrary, typeof(LookDevEnvironmentLibrary), false) as LookDevEnvironmentLibrary; - if (EditorGUI.EndChangeCheck()) - { - m_LookDevView.envLibrary = library; - } - - DrawSeparator(); - DrawHeader(styles.sMisc); - m_LookDevView.config.showBalls = GUILayout.Toggle(m_LookDevView.config.showBalls, styles.sShowBalls, styles.sMenuItem); - m_LookDevView.config.showControlWindows = GUILayout.Toggle(m_LookDevView.config.showControlWindows, styles.sShowControlWindows, styles.sMenuItem); - EditorGUI.BeginChangeCheck(); - bool allowDifferentObjects = GUILayout.Toggle(m_LookDevView.config.allowDifferentObjects, styles.sAllowDifferentObjects, styles.sMenuItem); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevView.config.allowDifferentObjects = allowDifferentObjects; - } - if (GUILayout.Button(styles.sResyncObjects, styles.sMenuItem)) - { - m_LookDevView.config.ResynchronizeObjects(); - } - } - GUILayout.EndVertical(); - - // Use mouse move so we get hover state correctly in the menu item rows - if (Event.current.type == EventType.MouseMove) - Event.current.Use(); - - // Escape closes the window - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - { - editorWindow.Close(); - GUIUtility.ExitGUI(); - } - } - - private void DrawSeparator() - { - GUILayout.Space(3.0f); - GUILayout.Label(GUIContent.none, styles.sSeparator); - } - - private void DrawHeader(GUIContent label) - { - GUILayout.Label(label, EditorStyles.miniLabel); - } - } -} diff --git a/Editor/Mono/LookDevView/LookDevView.cs b/Editor/Mono/LookDevView/LookDevView.cs deleted file mode 100644 index f0a0984717..0000000000 --- a/Editor/Mono/LookDevView/LookDevView.cs +++ /dev/null @@ -1,2116 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Collections.Generic; -using UnityEditorInternal; -using UnityEditor.SceneManagement; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Look Dev", useTypeNameAsIconName = true)] - internal class LookDevView : EditorWindow, IHasCustomMenu - { - static readonly Vector2 s_MinWindowSize = new Vector2(300, 60); - - // Note: Color init in OnEnable - public static Color32 m_FirstViewGizmoColor; - public static Color32 m_SecondViewGizmoColor; - - private static string m_configAssetPath = "Library/LookDevConfig.asset"; - - bool m_IsSaveRegistered = false; - - public class Styles - { - public readonly GUIStyle sBigTitleInnerStyle = "IN BigTitle inner"; - public readonly GUIStyle sToolBarButton = "toolbarbutton"; - - public readonly GUIContent sSingleMode1 = EditorGUIUtility.TrIconContent("LookDevSingle1", "Single1 object view"); - public readonly GUIContent sSingleMode2 = EditorGUIUtility.TrIconContent("LookDevSingle2", "Single2 object view"); - public readonly GUIContent sSideBySideMode = EditorGUIUtility.TrIconContent("LookDevSideBySide", "Side by side comparison view"); - public readonly GUIContent sSplitMode = EditorGUIUtility.TrIconContent("LookDevSplit", "Single object split comparison view"); - public readonly GUIContent sZoneMode = EditorGUIUtility.TrIconContent("LookDevZone", "Single object zone comparison view"); - public readonly GUIContent sLinkActive = EditorGUIUtility.TrIconContent("LookDevMirrorViewsActive", "Links the property between the different views"); - public readonly GUIContent sLinkInactive = EditorGUIUtility.TrIconContent("LookDevMirrorViewsInactive", "Links the property between the different views"); - public readonly GUIContent sDragAndDropObjsText = EditorGUIUtility.TrTextContent("Drag and drop Prefabs here."); - - - public readonly GUIStyle[] sPropertyLabelStyle = - { - new GUIStyle(EditorStyles.miniLabel), - new GUIStyle(EditorStyles.miniLabel), - new GUIStyle(EditorStyles.miniLabel) - }; - - public Styles() - { - sPropertyLabelStyle[0].normal.textColor = LookDevView.m_FirstViewGizmoColor; - sPropertyLabelStyle[1].normal.textColor = LookDevView.m_SecondViewGizmoColor; - } - } - - static Styles s_Styles = null; - public static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - - internal class PreviewContextCB - { - public CommandBuffer m_drawBallCB; - public CommandBuffer m_patchGBufferCB; - public MaterialPropertyBlock m_drawBallPB; - - public PreviewContextCB() - { - m_drawBallCB = new CommandBuffer(); - m_drawBallCB.name = "draw ball"; - m_patchGBufferCB = new CommandBuffer(); - m_patchGBufferCB.name = "patch gbuffer"; - m_drawBallPB = new MaterialPropertyBlock(); - } - }; - - internal class PreviewContext - { - public enum PreviewContextPass - { - kView = 0, - kViewWithShadow, - kShadow, - kCount - }; - - public PreviewRenderUtility[] m_PreviewUtility = new PreviewRenderUtility[(int)PreviewContextPass.kCount]; - public Texture[] m_PreviewResult = new Texture[(int)PreviewContextPass.kCount]; - public PreviewContextCB[] m_PreviewCB = new PreviewContextCB[(int)PreviewContextPass.kCount]; - - - public PreviewContext() - { - for (int i = 0; i < (int)PreviewContextPass.kCount; ++i) - { - m_PreviewUtility[i] = new PreviewRenderUtility(); - m_PreviewUtility[i].camera.fieldOfView = 30.0f; - m_PreviewUtility[i].camera.cullingMask = 1 << Camera.PreviewCullingLayer; - m_PreviewCB[i] = new PreviewContextCB(); - } - } - - public void Cleanup() - { - for (int contextIndex = 0; contextIndex < (int)PreviewContext.PreviewContextPass.kCount; ++contextIndex) - { - if (m_PreviewUtility[contextIndex] != null) - { - m_PreviewUtility[contextIndex].Cleanup(); - m_PreviewUtility[contextIndex] = null; - } - } - } - } - - public static void DrawFullScreenQuad(Rect previewRect) - { - GL.PushMatrix(); - GL.LoadOrtho(); - GL.Viewport(previewRect); - - GL.Begin(GL.QUADS); - GL.TexCoord2(0, 0); - GL.Vertex3(0.0F, 0.0F, 0); - GL.TexCoord2(0, 1); - GL.Vertex3(0.0F, 1.0F, 0); - GL.TexCoord2(1, 1); - GL.Vertex3(1.0F, 1.0F, 0); - GL.TexCoord2(1, 0); - GL.Vertex3(1.0F, 0.0F, 0); - GL.End(); - GL.PopMatrix(); - } - - private PreviewContext[] m_PreviewUtilityContexts = new PreviewContext[2]; - private GUIContent m_RenderdocContent; - private GUIContent m_SyncLightVertical; - private GUIContent m_ResetEnvironment; - private Rect[] m_PreviewRects = new Rect[3]; - private Rect m_DisplayRect; - private Vector4 m_ScreenRatio; - private Vector2 m_OnMouseDownOffsetToGizmo; - private LookDevEditionContext m_CurrentDragContext = LookDevEditionContext.None; - private LookDevOperationType m_LookDevOperationType = LookDevOperationType.None; - private RenderTexture m_FinalCompositionTexture = null; - private LookDevEnvironmentWindow m_LookDevEnvWindow = null; - private bool m_ShowLookDevEnvWindow = false; - private bool m_CaptureRD = false; - - private bool[] m_LookDevModeToggles = new bool[(int)LookDevMode.Count]; - - private float m_GizmoThickness = 0.0028f; - private float m_GizmoThicknessSelected = 0.015f; - private float m_GizmoCircleRadius = 0.014f; - private float m_GizmoCircleRadiusSelected = 0.03f; - private bool m_ForceGizmoRenderSelector = false; - private LookDevOperationType m_GizmoRenderMode = LookDevOperationType.None; - private float m_BlendFactorCircleSelectionRadius = 0.03f; - private float m_BlendFactorCircleRadius = 0.01f; - - private Rect m_ControlWindowRect; - private float kLineHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - - private LookDevConfig m_LookDevConfig = null;// Configuration of the 3D view. This will be saved in the library folder (it should not be versionned) - private LookDevEnvironmentLibrary m_LookDevEnvLibrary = null;// This is the working copy of the library in use. It's always an instance of the chosen library in order not to alter the original one. - [SerializeField] - private LookDevEnvironmentLibrary m_LookDevUserEnvLibrary = null;// Current user library. This is the asset we are going to serialize in the end. - - private bool m_DisplayDebugGizmo = false; - private float kReferenceScale = 1080.0f; - - private int m_hotControlID = 0; - - private float m_DirBias = 0.01f; - private float m_DirNormalBias = 0.4f; - private float m_CurrentObjRotationOffset = 0.0f; - private float m_ObjRotationAcc = 0.0f; - private float m_EnvRotationAcc = 0.0f; - - // This a workaround: Currently the edition scene and any preview scenes are not distinct. They share the same world space - // So if there are reflection probes in the main edition scene, they will affect the lookdev. - // Since there is now good way yet to separate the two scenes properly, we just render far under ground and hope that no reflections probes are there... - private float kDefaultSceneHeight = -500.0f; - - - private CameraControllerStandard m_CameraController = new CameraControllerStandard(); - internal PreviewContext[] previewUtilityContexts { get { return m_PreviewUtilityContexts; } } - - - public int hotControl - { - get { return m_hotControlID; } - } - - public LookDevConfig config - { - get { return m_LookDevConfig; } - } - - public LookDevEnvironmentLibrary envLibrary - { - get { return m_LookDevEnvLibrary; } - set - { - if (value == null) - { - // "None" is selected, we have to reset to the default library - m_LookDevEnvLibrary = ScriptableObject.CreateInstance(); - m_LookDevUserEnvLibrary = null; - } - else - { - // Update the current user library - if (value != m_LookDevUserEnvLibrary) - { - m_LookDevUserEnvLibrary = value; - m_LookDevEnvLibrary = ScriptableObject.Instantiate(value); - m_LookDevEnvLibrary.SetLookDevView(this); - } - } - - int hdriCount = m_LookDevEnvLibrary.hdriCount; - if (m_LookDevConfig.GetIntProperty(LookDevProperty.HDRI, LookDevEditionContext.Left) >= hdriCount || m_LookDevConfig.GetIntProperty(LookDevProperty.HDRI, LookDevEditionContext.Right) >= hdriCount) - { - // When switching library, the new one can have fewer HDRIs so we reset the HDRI property to zero to make sure we don't get out of range. - m_LookDevConfig.UpdatePropertyLink(LookDevProperty.HDRI, true); - m_LookDevConfig.UpdateIntProperty(LookDevProperty.HDRI, 0); - } - } - } - public LookDevEnvironmentLibrary userEnvLibrary - { - get { return m_LookDevUserEnvLibrary; } - } - - public void CreateNewLibrary(string assetPath) - { - // Create a new library based on the state of the current one. - LookDevEnvironmentLibrary newLibrary = ScriptableObject.Instantiate(envLibrary) as LookDevEnvironmentLibrary; - AssetDatabase.CreateAsset(newLibrary, assetPath); - envLibrary = AssetDatabase.LoadAssetAtPath(assetPath, typeof(LookDevEnvironmentLibrary)) as LookDevEnvironmentLibrary; - } - - public static void OpenInLookDevTool(UnityEngine.Object go) - { - LookDevView lookDev = EditorWindow.GetWindow(); - lookDev.m_LookDevConfig.SetCurrentPreviewObject(go as GameObject, LookDevEditionContext.Left); - lookDev.m_LookDevConfig.SetCurrentPreviewObject(go as GameObject, LookDevEditionContext.Right); - lookDev.Frame(LookDevEditionContext.Left, false); - lookDev.Repaint(); - } - - public LookDevView() - { - for (int i = 0; i < (int)LookDevMode.Count; ++i) - { - m_LookDevModeToggles[i] = false; - } - - wantsMouseMove = true; - - minSize = s_MinWindowSize; - } - - private void Initialize() - { - LookDevResources.Initialize(); - - InitializePreviewUtilities(); - - LoadLookDevConfig(); - - // When we reload the scene the pointer like m_DefaultHDRI can become null but the list of HDRI is not null - // so test it to be sure we don't add two time default HDRI. - if (m_LookDevEnvLibrary.hdriList.Count == 0) - { - UpdateContextWithCurrentHDRI(LookDevResources.m_DefaultHDRI); - } - - if (m_LookDevEnvWindow == null) - { - m_LookDevEnvWindow = new LookDevEnvironmentWindow(this); - } - } - - void InitializePreviewUtilities() - { - if (m_PreviewUtilityContexts[0] == null) - { - // Do this check only the first time - if (QualitySettings.activeColorSpace == ColorSpace.Gamma) - Debug.LogWarning("Look Dev is designed for linear color space. Currently project is set to gamma color space. This can be changed in player settings."); - if (Rendering.EditorGraphicsSettings.GetCurrentTierSettings().renderingPath != RenderingPath.DeferredShading) - Debug.LogWarning("Look Dev switched rendering mode to deferred shading for display."); - if (Camera.main.allowHDR == false) - Debug.LogWarning("Look Dev switched HDR mode on for display."); - - for (int i = 0; i < 2; ++i) - m_PreviewUtilityContexts[i] = new PreviewContext(); - } - } - - private void Cleanup() - { - LookDevResources.Cleanup(); - - m_LookDevConfig.Cleanup(); - - for (int i = 0; i < 2; ++i) - { - if (m_PreviewUtilityContexts[i] != null) - m_PreviewUtilityContexts[i].Cleanup(); - m_PreviewUtilityContexts[i] = null; - } - - if (m_FinalCompositionTexture) - { - UnityEngine.Object.DestroyImmediate(m_FinalCompositionTexture); - m_FinalCompositionTexture = null; - } - } - - public void OnDestroy() - { - SaveLookDevConfig(); - Cleanup(); - } - - private void UpdateRenderTexture(Rect rect) - { - int rtWidth = (int)rect.width; - int rtHeight = (int)rect.height; - if (!m_FinalCompositionTexture || m_FinalCompositionTexture.width != rtWidth || m_FinalCompositionTexture.height != rtHeight) - { - if (m_FinalCompositionTexture) - { - UnityEngine.Object.DestroyImmediate(m_FinalCompositionTexture); - m_FinalCompositionTexture = null; - } - - m_FinalCompositionTexture = new RenderTexture(rtWidth, rtHeight, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default); - m_FinalCompositionTexture.hideFlags = HideFlags.HideAndDontSave; - } - } - - private void GetRenderableBoundsRecurse(ref Bounds bounds, GameObject go) - { - // Do we have a mesh? - MeshRenderer renderer = go.GetComponent(typeof(MeshRenderer)) as MeshRenderer; - MeshFilter filter = go.GetComponent(typeof(MeshFilter)) as MeshFilter; - if (renderer && filter && filter.sharedMesh) - { - // To prevent origo from always being included in bounds we initialize it - // with renderer.bounds. This ensures correct bounds for meshes with origo outside the mesh. - if (bounds.extents == Vector3.zero) - bounds = renderer.bounds; - else - bounds.Encapsulate(renderer.bounds); - } - - // Do we have a skinned mesh? - SkinnedMeshRenderer skin = go.GetComponent(typeof(SkinnedMeshRenderer)) as SkinnedMeshRenderer; - if (skin && skin.sharedMesh) - { - if (bounds.extents == Vector3.zero) - bounds = skin.bounds; - else - bounds.Encapsulate(skin.bounds); - } - - // Do we have a Sprite? - SpriteRenderer sprite = go.GetComponent(typeof(SpriteRenderer)) as SpriteRenderer; - if (sprite && sprite.sprite) - { - if (bounds.extents == Vector3.zero) - bounds = sprite.bounds; - else - bounds.Encapsulate(sprite.bounds); - } - - // Recurse into children - foreach (Transform t in go.transform) - { - GetRenderableBoundsRecurse(ref bounds, t.gameObject); - } - } - - private void RenderScene(Rect previewRect, LookDevContext lookDevContext, PreviewContext previewUtilityContext, GameObject[] currentObjectByPasses, CameraState originalCameraState, bool secondView) - { - // Explanation of how this work: - // To simulate the shadow of a directional light, we want to interpolate between two environments. One with a skybox without sun for shadowed area and the other with the sun. - // To create the lerp mask we render the scene with a white diffuse material (by patching the GBuffer so object can used their regular material) and a single shadow casting directional light. - // This will create a mask where the shadowed area is 0 and the lit area is 1 with a smooth NDotL transition in-between. - // Then we render the scene twice, once with the sunless environment and once with the original environment. - // At last we composite everything in the lookdev compositing pass. - - // Do a render with a white material and no GI at all. This will result in a shadow mask - // If shadows are disabled or if we need a debug view mode, we don't send an object to be rendered so that the mask stays neutral white. - bool needNeutralMask = !m_LookDevConfig.enableShadowCubemap || (m_LookDevConfig.enableShadowCubemap && ((DrawCameraMode)lookDevContext.shadingMode != DrawCameraMode.Normal) && ((DrawCameraMode)lookDevContext.shadingMode != DrawCameraMode.TexturedWire)); - previewUtilityContext.m_PreviewResult[(int)PreviewContext.PreviewContextPass.kShadow] = needNeutralMask ? - Texture2D.whiteTexture : - RenderScene(previewRect, lookDevContext, previewUtilityContext, currentObjectByPasses[(int)PreviewContext.PreviewContextPass.kShadow], originalCameraState, null, PreviewContext.PreviewContextPass.kShadow, secondView); - // Render the scene normally. - CubemapInfo cubemapInfo = m_LookDevEnvLibrary.hdriList[lookDevContext.currentHDRIIndex]; - previewUtilityContext.m_PreviewResult[(int)PreviewContext.PreviewContextPass.kView] = RenderScene(previewRect, lookDevContext, previewUtilityContext, currentObjectByPasses[(int)PreviewContext.PreviewContextPass.kView], originalCameraState, cubemapInfo, PreviewContext.PreviewContextPass.kView, secondView); - // Render the scene with the environment without the sun - previewUtilityContext.m_PreviewResult[(int)PreviewContext.PreviewContextPass.kViewWithShadow] = RenderScene(previewRect, lookDevContext, previewUtilityContext, currentObjectByPasses[(int)PreviewContext.PreviewContextPass.kViewWithShadow], originalCameraState, cubemapInfo.cubemapShadowInfo, PreviewContext.PreviewContextPass.kViewWithShadow, secondView); - } - - private Texture RenderScene(Rect previewRect, LookDevContext lookDevContext, PreviewContext previewUtilityContext, GameObject currentObject, CameraState originalCameraState, CubemapInfo cubemapInfo, PreviewContext.PreviewContextPass contextPass, bool secondView) - { - PreviewRenderUtility previewUtility = previewUtilityContext.m_PreviewUtility[(int)contextPass]; - PreviewContextCB contextCB = previewUtilityContext.m_PreviewCB[(int)contextPass]; - - // Save several lighting panel parameter as they are not unique to our lookdev but share with the scene view :( - UnityEngine.Rendering.DefaultReflectionMode oldReflectionMode = RenderSettings.defaultReflectionMode; - UnityEngine.Rendering.AmbientMode oldAmbientMode = RenderSettings.ambientMode; - Cubemap oldCubeMap = RenderSettings.customReflection; - Material oldSkybox = RenderSettings.skybox; - float oldAmbientIntensity = RenderSettings.ambientIntensity; - SphericalHarmonicsL2 oldAmbientProbe = RenderSettings.ambientProbe; - float oldReflectionIntensity = RenderSettings.reflectionIntensity; - - previewUtility.BeginPreview(previewRect, styles.sBigTitleInnerStyle); - bool shadowPass = contextPass == PreviewContext.PreviewContextPass.kShadow; - - DrawCameraMode shadingMode = (DrawCameraMode)lookDevContext.shadingMode; - bool needDebugMode = shadingMode != DrawCameraMode.Normal && shadingMode != DrawCameraMode.TexturedWire; - - float oldShadowDistance = QualitySettings.shadowDistance; - Vector3 oldShadowCascade4Split = QualitySettings.shadowCascade4Split; - - float cubemapOffset = m_LookDevEnvLibrary.hdriList[lookDevContext.currentHDRIIndex].angleOffset; - // We need to invert the sign of the envRotation because we move the camera and not the cubemap itself - float envRotation = -(lookDevContext.envRotation + cubemapOffset); - - // Here is a little trick. The lookdev allows us to rotate the environment. - // The problem is that we can't properly rotate it in the engine right now. - // So to simulate this, we always rotate the camera around the center of the world and compensate by rotating and moving the observed object by the inverse transform. - CameraState cameraState = originalCameraState.Clone(); - Vector3 angles = cameraState.rotation.value.eulerAngles; - - cameraState.rotation.value = Quaternion.Euler(angles + new Vector3(0.0f, envRotation, 0.0f)); // Add environment rotation to current camera orientation - cameraState.pivot.value = new Vector3(0.0f, kDefaultSceneHeight, 0.0f); // Look at the center of the world - cameraState.UpdateCamera(previewUtility.camera); - - previewUtility.camera.renderingPath = RenderingPath.DeferredShading; - previewUtility.camera.clearFlags = shadowPass ? CameraClearFlags.Color : CameraClearFlags.Skybox; // We need to clear to white for the shadow mask to work properly - previewUtility.camera.backgroundColor = Color.white; - previewUtility.camera.allowHDR = true; - - for (int lightIndex = 0; lightIndex < 2; lightIndex++) - { - previewUtility.lights[lightIndex].enabled = false; - previewUtility.lights[lightIndex].intensity = 0.0f; - previewUtility.lights[lightIndex].shadows = LightShadows.None; - } - - // If shadows are disable or if we are in a Debug view mode (albedo, normal, etc) we don't want to have shadows in the mask - if (currentObject != null && shadowPass && m_LookDevConfig.enableShadowCubemap && !needDebugMode) // The default shadow flag serves as a switch to completely remove the shadows, even those specific to different environments. - { - Bounds bounds = new Bounds(currentObject.transform.position, Vector3.zero); - GetRenderableBoundsRecurse(ref bounds, currentObject); - - float maxBound = Mathf.Max(bounds.max.x, Mathf.Max(bounds.max.y, bounds.max.z)); // Compute the approximate size of the object - float shadowMaxDistance = m_LookDevConfig.shadowDistance > 0.0f ? m_LookDevConfig.shadowDistance : 25.0f * maxBound; // We want to see shadows until a distance of 25 times the size of the object. - float splitBaseDistance = Mathf.Min(maxBound * 2.0f, 20.0f) / shadowMaxDistance; // Try to conserve a bit of shadow precision for big objects - - QualitySettings.shadowDistance = shadowMaxDistance; - QualitySettings.shadowCascade4Split = new Vector3(Mathf.Clamp(splitBaseDistance, 0.0f, 1.0f), Mathf.Clamp(splitBaseDistance * 2.0f, 0.0f, 1.0f), Mathf.Clamp(splitBaseDistance * 6.0f, 0.0f, 1.0f)); - - ShadowInfo shadowInfo = m_LookDevEnvLibrary.hdriList[lookDevContext.currentHDRIIndex].shadowInfo; - // previewUtility.m_Light[0].enabled = true; // Apparently doing this will add the light to the global manager, making it visible in the scene view... so don't do that. - previewUtility.lights[0].intensity = 1.0f; - previewUtility.lights[0].color = Color.white; - previewUtility.lights[0].shadows = LightShadows.Soft; - previewUtility.lights[0].shadowBias = m_DirBias; - previewUtility.lights[0].shadowNormalBias = m_DirNormalBias; - previewUtility.lights[0].transform.rotation = Quaternion.Euler(shadowInfo.latitude, shadowInfo.longitude, 0.0f); - - // Can't pre-record the command buffer :( because to make MaterialPropertyBlock working, it need to be setup each frame with DrawMesh. Calling DrawMesh mean we need to call clear - // else DrawMesh accumulate each frame. Calling clear mean we can't pre-record command buffer. - - // We need a command buffer to patch the Gbuffer to generate the 'fake' screen space shadow map - // Patch diffuse+specular+smoothness into two MRTs - contextCB.m_patchGBufferCB.Clear(); - RenderTargetIdentifier[] mrt = { BuiltinRenderTextureType.GBuffer0, BuiltinRenderTextureType.GBuffer1 }; - contextCB.m_patchGBufferCB.SetRenderTarget(mrt, BuiltinRenderTextureType.CameraTarget); - contextCB.m_patchGBufferCB.DrawMesh(LookDevResources.m_ScreenQuadMesh, Matrix4x4.identity, LookDevResources.m_GBufferPatchMaterial); - - // set this command buffer to be executed just before deferred lighting pass - previewUtility.camera.AddCommandBuffer(CameraEvent.AfterGBuffer, contextCB.m_patchGBufferCB); - - if (m_LookDevConfig.showBalls) - { - // We need to draw the balls in order that they are not shadowed - contextCB.m_drawBallCB.Clear(); - // Patch lighting buffer - This will write the shape of the screen space balls after the render of the shadow map to be sure we display only the normal view 0 - RenderTargetIdentifier[] lightingBuffer = { BuiltinRenderTextureType.CameraTarget }; - contextCB.m_drawBallCB.SetRenderTarget(lightingBuffer, BuiltinRenderTextureType.CameraTarget); - contextCB.m_drawBallPB.SetVector("_WindowsSize", new Vector4(previewUtility.camera.pixelWidth, previewUtility.camera.pixelHeight, secondView ? 1.0f : 0.0f, 0)); - contextCB.m_drawBallCB.DrawMesh(LookDevResources.m_ScreenQuadMesh, Matrix4x4.identity, LookDevResources.m_DrawBallsMaterial, 0, 1, contextCB.m_drawBallPB); - - // Draw ball in screen space by patching the GBuffer - previewUtility.camera.AddCommandBuffer(CameraEvent.AfterLighting, contextCB.m_drawBallCB); - } - } - - previewUtility.ambientColor = new Color(0.0f, 0.0f, 0.0f, 0.0f); - - RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Custom; - - Cubemap skyboxCubemap = cubemapInfo != null ? cubemapInfo.cubemap : null; - LookDevResources.m_SkyboxMaterial.SetTexture("_Tex", skyboxCubemap); - LookDevResources.m_SkyboxMaterial.SetFloat("_Exposure", 1.0f); // Exposure handled in the compositing shader - - RenderSettings.customReflection = skyboxCubemap; - - // Cache computation of ambient probe - if (cubemapInfo != null && !cubemapInfo.alreadyComputed && !shadowPass) - { - RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Skybox; // Force skybox for our HDRI - RenderSettings.skybox = LookDevResources.m_SkyboxMaterial; - DynamicGI.UpdateEnvironment(); - cubemapInfo.ambientProbe = RenderSettings.ambientProbe; - RenderSettings.skybox = oldSkybox; - cubemapInfo.alreadyComputed = true; - } - - RenderSettings.ambientProbe = cubemapInfo != null ? cubemapInfo.ambientProbe : LookDevResources.m_ZeroAmbientProbe; - RenderSettings.skybox = LookDevResources.m_SkyboxMaterial; - RenderSettings.ambientIntensity = 1.0f; // fix this to 1, this parameter should not exist! - RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Skybox; // Force skybox for our HDRI - RenderSettings.reflectionIntensity = 1.0f; - - // Note: This test must be all after the setup of the RenderSettings.ambientProbe - if (contextPass == PreviewContext.PreviewContextPass.kView && m_LookDevConfig.showBalls) - { - // To display greyball we need ambient probe information - - // Copy/paste from SHContantCache.cpp and convert to C#. Yes we should expose C++ impl to c # - const int kSHCoefficients = 7; - Vector4[] shaderConstants = new Vector4[kSHCoefficients]; - - GetShaderConstantsFromNormalizedSH(RenderSettings.ambientProbe, shaderConstants); - - // Can't pre-record the command buffer :( because to make MaterialPropertyBlock working, it need to be setup each frame with DrawMesh. Calling DrawMesh mean we need to call clear - // else DrawMesh accumulate each frame. Calling clear mean we can't pre-record command buffer. - - // We modify the Gbuffer to draw chrome/Grey balls - contextCB.m_drawBallCB.Clear(); - // Patch diffuse+occlusion+specular+smoothness into three MRTs - // See https://issuetracker.unity3d.com/issues/camera-slash-commandbuffer-commandbuffer-dot-blit-texture2d-dot-blacktexture-builtinrendertexturetype-dot-gbuffer3-fails-when-hdr-is-enabled - // for why we do not use BuiltinRenderTextureType.GBuffer3 but the camera target instead (LookDev is always HDR) - RenderTargetIdentifier[] mrt2 = { BuiltinRenderTextureType.GBuffer0, BuiltinRenderTextureType.GBuffer1, BuiltinRenderTextureType.GBuffer2, BuiltinRenderTextureType.CameraTarget }; - contextCB.m_drawBallCB.SetRenderTarget(mrt2, BuiltinRenderTextureType.CameraTarget); - - contextCB.m_drawBallPB.SetVector("_SHAr", shaderConstants[0]); - contextCB.m_drawBallPB.SetVector("_SHAg", shaderConstants[1]); - contextCB.m_drawBallPB.SetVector("_SHAb", shaderConstants[2]); - contextCB.m_drawBallPB.SetVector("_SHBr", shaderConstants[3]); - contextCB.m_drawBallPB.SetVector("_SHBg", shaderConstants[4]); - contextCB.m_drawBallPB.SetVector("_SHBb", shaderConstants[5]); - contextCB.m_drawBallPB.SetVector("_SHC", shaderConstants[6]); - - contextCB.m_drawBallPB.SetVector("_WindowsSize", new Vector4(previewUtility.camera.pixelWidth, previewUtility.camera.pixelHeight, secondView ? 1.0f : 0.0f, 0)); - contextCB.m_drawBallCB.DrawMesh(LookDevResources.m_ScreenQuadMesh, Matrix4x4.identity, LookDevResources.m_DrawBallsMaterial, 0, 0, contextCB.m_drawBallPB); - - // Draw ball in screen space by patching the GBuffer - previewUtility.camera.AddCommandBuffer(CameraEvent.AfterGBuffer, contextCB.m_drawBallCB); - } - - Vector3 oldAngles = Vector3.zero; - Vector3 oldTranslation = Vector3.zero; - - if (currentObject != null) - { - // Setup object property - LODGroup lodGroup = currentObject.GetComponent(typeof(LODGroup)) as LODGroup; - if (lodGroup != null) - { - lodGroup.ForceLOD(lookDevContext.lodIndex); - } - - PreviewRenderUtility.SetEnabledRecursive(currentObject, true); - oldAngles = currentObject.transform.eulerAngles; - oldTranslation = currentObject.transform.localPosition; - - currentObject.transform.position = new Vector3(0.0f, kDefaultSceneHeight, 0.0f); - currentObject.transform.rotation = Quaternion.identity; - - // Applies inverse transform from camera pivot + environment rotation. - currentObject.transform.Rotate(0.0f, envRotation, 0.0f); - currentObject.transform.Translate(-originalCameraState.pivot.value); - currentObject.transform.Rotate(0.0f, m_CurrentObjRotationOffset, 0.0f); - } - - // Specific drawing pass for TexturedWire - if (shadingMode == DrawCameraMode.TexturedWire && !shadowPass) - { - Handles.ClearCamera(previewRect, previewUtility.camera); - Handles.DrawCamera(previewRect, previewUtility.camera, shadingMode); - } - else - { - previewUtility.Render(true, false); - } - - if (currentObject != null) - { - // restore initial transform - currentObject.transform.eulerAngles = oldAngles; - currentObject.transform.position = oldTranslation; - PreviewRenderUtility.SetEnabledRecursive(currentObject, false); - } - - if (needDebugMode && !shadowPass) // Even with the debug modes we need to keep the shadow mask white. - { - if (Event.current.type == EventType.Repaint) - { - float scaleFac = previewUtility.GetScaleFactor(previewRect.width, previewRect.height); - LookDevResources.m_DeferredOverlayMaterial.SetInt("_DisplayMode", (int)shadingMode - (int)DrawCameraMode.DeferredDiffuse); - Graphics.DrawTexture(new Rect(0, 0, previewRect.width * scaleFac, previewRect.height * scaleFac), EditorGUIUtility.whiteTexture, LookDevResources.m_DeferredOverlayMaterial); - } - } - - if (shadowPass) - { - previewUtility.camera.RemoveCommandBuffer(CameraEvent.AfterGBuffer, contextCB.m_patchGBufferCB); - if (m_LookDevConfig.showBalls) - { - previewUtility.camera.RemoveCommandBuffer(CameraEvent.AfterLighting, contextCB.m_drawBallCB); - } - } - else if (contextPass == PreviewContext.PreviewContextPass.kView && m_LookDevConfig.showBalls) - { - // Draw ball in screen space by patching the GBuffer - previewUtility.camera.RemoveCommandBuffer(CameraEvent.AfterGBuffer, contextCB.m_drawBallCB); - } - - QualitySettings.shadowCascade4Split = oldShadowCascade4Split; - QualitySettings.shadowDistance = oldShadowDistance; - - // Restore saved render settings - RenderSettings.defaultReflectionMode = oldReflectionMode; - RenderSettings.ambientMode = oldAmbientMode; - RenderSettings.customReflection = oldCubeMap; - RenderSettings.skybox = oldSkybox; - RenderSettings.ambientIntensity = oldAmbientIntensity; - RenderSettings.reflectionIntensity = oldReflectionIntensity; - RenderSettings.ambientProbe = oldAmbientProbe; - - return previewUtility.EndPreview(); - } - - public void UpdateLookDevModeToggle(LookDevMode lookDevMode, bool value) - { - LookDevMode newLookDevMode = lookDevMode; - - if (value) - { - m_LookDevModeToggles[(int)lookDevMode] = value; - - // Disable all others - for (int i = 0; i < (int)LookDevMode.Count; ++i) - { - if (i != (int)lookDevMode) - { - m_LookDevModeToggles[i] = false; - } - } - - newLookDevMode = lookDevMode; - } - else - { - for (int i = 0; i < (int)LookDevMode.Count; ++i) - { - if (m_LookDevModeToggles[i]) - { - newLookDevMode = (LookDevMode)i; - } - } - - // all are false, keep current mode - m_LookDevModeToggles[(int)lookDevMode] = true; - newLookDevMode = lookDevMode; - } - - m_LookDevConfig.lookDevMode = newLookDevMode; - Repaint(); - } - - void OnUndoRedo() - { - Repaint(); - } - - private void DoAdditionalGUI() - { - if (m_LookDevConfig.lookDevMode == LookDevMode.SideBySide) - { - // Camera link icon - int linkIconSize = 32; - GUILayout.BeginArea(new Rect((m_PreviewRects[2].width - linkIconSize) / 2, (m_PreviewRects[2].height - linkIconSize) / 2, linkIconSize, linkIconSize)); - { - EditorGUI.BeginChangeCheck(); - bool isLink = m_LookDevConfig.sideBySideCameraLinked; - bool linked = GUILayout.Toggle(isLink, GetGUIContentLink(isLink), styles.sToolBarButton); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevConfig.sideBySideCameraLinked = linked; - - // When re-linking camera we need to copy the current context into the other one - if (linked) - { - CameraState currentState = m_LookDevConfig.currentEditionContext == LookDevEditionContext.Left ? m_LookDevConfig.cameraStateLeft : m_LookDevConfig.cameraStateRight; - CameraState otherState = m_LookDevConfig.currentEditionContext == LookDevEditionContext.Left ? m_LookDevConfig.cameraStateRight : m_LookDevConfig.cameraStateLeft; - - otherState.Copy(currentState); - } - } - } - GUILayout.EndArea(); - } - } - - GUIStyle GetPropertyLabelStyle(LookDevProperty property) - { - if (m_LookDevConfig.IsPropertyLinked(property) || m_LookDevConfig.lookDevMode == LookDevMode.Single1 || m_LookDevConfig.lookDevMode == LookDevMode.Single2) - return styles.sPropertyLabelStyle[2]; - else - return styles.sPropertyLabelStyle[m_LookDevConfig.currentEditionContextIndex]; - } - - GUIContent GetGUIContentLink(bool active) - { - return active ? styles.sLinkActive : styles.sLinkInactive; - } - - private void DoControlWindow() - { - if (!m_LookDevConfig.showControlWindows) - return; - - float sliderLabelWidth = 68.0f; - float sliderWidth = 150.0f; - float fieldWidth = 30.0f; - - - GUILayout.BeginArea(m_ControlWindowRect, styles.sBigTitleInnerStyle); - { - GUILayout.BeginVertical(); - { - GUILayout.BeginHorizontal(GUILayout.Height(kLineHeight)); - { - GUILayout.FlexibleSpace(); - - bool value = false; - - EditorGUI.BeginChangeCheck(); - value = GUILayout.Toggle(m_LookDevModeToggles[(int)LookDevMode.Single1], styles.sSingleMode1, styles.sToolBarButton); - if (EditorGUI.EndChangeCheck()) - { - UpdateLookDevModeToggle(LookDevMode.Single1, value); - m_LookDevConfig.UpdateFocus(LookDevEditionContext.Left); - Repaint(); - } - - EditorGUI.BeginChangeCheck(); - value = GUILayout.Toggle(m_LookDevModeToggles[(int)LookDevMode.Single2], styles.sSingleMode2, styles.sToolBarButton); - if (EditorGUI.EndChangeCheck()) - { - UpdateLookDevModeToggle(LookDevMode.Single2, value); - m_LookDevConfig.UpdateFocus(LookDevEditionContext.Right); - Repaint(); - } - - EditorGUI.BeginChangeCheck(); - value = GUILayout.Toggle(m_LookDevModeToggles[(int)LookDevMode.SideBySide], styles.sSideBySideMode, styles.sToolBarButton); - if (EditorGUI.EndChangeCheck()) - { - UpdateLookDevModeToggle(LookDevMode.SideBySide, value); - } - - EditorGUI.BeginChangeCheck(); - value = GUILayout.Toggle(m_LookDevModeToggles[(int)LookDevMode.Split], styles.sSplitMode, styles.sToolBarButton); - if (EditorGUI.EndChangeCheck()) - { - UpdateLookDevModeToggle(LookDevMode.Split, value); - } - - EditorGUI.BeginChangeCheck(); - value = GUILayout.Toggle(m_LookDevModeToggles[(int)LookDevMode.Zone], styles.sZoneMode, styles.sToolBarButton); - if (EditorGUI.EndChangeCheck()) - { - UpdateLookDevModeToggle(LookDevMode.Zone, value); - } - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.Height(kLineHeight)); - { - GUILayout.Label(LookDevViewsWindow.styles.sExposure, GetPropertyLabelStyle(LookDevProperty.ExposureValue), GUILayout.Width(sliderLabelWidth)); - - float fExposureValue = m_LookDevConfig.currentLookDevContext.exposureValue; - EditorGUI.BeginChangeCheck(); - // Display in the float field is rounded for display. To 1 decimal in case of negative number to account for the '-' character. - float roundedExposureRange = Mathf.Round(m_LookDevConfig.exposureRange); - fExposureValue = Mathf.Clamp(GUILayout.HorizontalSlider((float)Math.Round(fExposureValue, fExposureValue < 0.0f ? 1 : 2), -roundedExposureRange, roundedExposureRange, GUILayout.Width(sliderWidth)), -roundedExposureRange, roundedExposureRange); - fExposureValue = Mathf.Clamp(EditorGUILayout.FloatField(fExposureValue, GUILayout.Width(fieldWidth)), -roundedExposureRange, roundedExposureRange); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevConfig.UpdateFloatProperty(LookDevProperty.ExposureValue, fExposureValue); - } - bool linked = false; - EditorGUI.BeginChangeCheck(); - bool isLink = m_LookDevConfig.IsPropertyLinked(LookDevProperty.ExposureValue); - linked = GUILayout.Toggle(isLink, GetGUIContentLink(isLink), styles.sToolBarButton); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevConfig.UpdatePropertyLink(LookDevProperty.ExposureValue, linked); - } - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.Height(kLineHeight)); - { - using (new EditorGUI.DisabledScope(m_LookDevEnvLibrary.hdriList.Count <= 1)) - { - GUILayout.Label(LookDevViewsWindow.styles.sEnvironment, GetPropertyLabelStyle(LookDevProperty.HDRI), GUILayout.Width(sliderLabelWidth)); - - int iHDRIIndex = -1; - if (m_LookDevEnvLibrary.hdriList.Count > 1) - { - int maxHDRIIndex = m_LookDevEnvLibrary.hdriList.Count - 1; - iHDRIIndex = m_LookDevConfig.currentLookDevContext.currentHDRIIndex; - EditorGUI.BeginChangeCheck(); - iHDRIIndex = (int)GUILayout.HorizontalSlider(iHDRIIndex, 0.0f, (float)maxHDRIIndex, GUILayout.Width(sliderWidth)); - iHDRIIndex = Mathf.Clamp(EditorGUILayout.IntField(iHDRIIndex, GUILayout.Width(fieldWidth)), 0, maxHDRIIndex); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevConfig.UpdateIntProperty(LookDevProperty.HDRI, iHDRIIndex); - } - } - else - { - GUILayout.HorizontalSlider(0.0f, 0.0f, 0.0f, GUILayout.Width(sliderWidth)); - GUILayout.Label(LookDevViewsWindow.styles.sZero, EditorStyles.miniLabel, GUILayout.Width(fieldWidth)); - } - } - - bool linked = false; - EditorGUI.BeginChangeCheck(); - bool isLink = m_LookDevConfig.IsPropertyLinked(LookDevProperty.HDRI); - linked = GUILayout.Toggle(isLink, GetGUIContentLink(isLink), styles.sToolBarButton); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevConfig.UpdatePropertyLink(LookDevProperty.HDRI, linked); - } - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.Height(kLineHeight)); - { - GUILayout.Label(LookDevViewsWindow.styles.sShadingMode, GetPropertyLabelStyle(LookDevProperty.ShadingMode), GUILayout.Width(sliderLabelWidth)); - - int shadingMode = m_LookDevConfig.currentLookDevContext.shadingMode; - EditorGUI.BeginChangeCheck(); - shadingMode = EditorGUILayout.IntPopup("", shadingMode, LookDevViewsWindow.styles.sShadingModeStrings, LookDevViewsWindow.styles.sShadingModeValues, GUILayout.Width(fieldWidth + sliderWidth + 4.0f)); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevConfig.UpdateIntProperty(LookDevProperty.ShadingMode, shadingMode); - } - - bool linked = false; - EditorGUI.BeginChangeCheck(); - bool isLink = m_LookDevConfig.IsPropertyLinked(LookDevProperty.ShadingMode); - linked = GUILayout.Toggle(isLink, GetGUIContentLink(isLink), styles.sToolBarButton); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevConfig.UpdatePropertyLink(LookDevProperty.ShadingMode, linked); - } - } - GUILayout.EndHorizontal(); - - /* - GUILayout.BeginHorizontal(); - { - GUILayout.Label(LookDevViewsWindow.styles.sRotation, GetPropertyLabelStyle(LookDevProperty.kEnvRotation), GUILayout.Width(sliderLabelWidth)); - - float envRotation = m_LookDevConfig.lookDevContexts[m_LookDevConfig.lookDevContextIndex].envRotation; - EditorGUI.BeginChangeCheck(); - envRotation = GUILayout.HorizontalSlider(envRotation, 0.0f, 720.0f, GUILayout.Width(sliderWidth)); - envRotation = Mathf.Clamp(EditorGUILayout.FloatField(float.Parse(envRotation.ToString("F0")), GUILayout.Width(fieldWidth)), 0.0f, 720.0f); - if (EditorGUI.EndChangeCheck()) - { - UpdateFloatProperty(LookDevProperty.kEnvRotation, envRotation); - } - bool linked = false; - EditorGUI.BeginChangeCheck(); - bool isLink = m_LookDevConfig.IsPropertyLinked(LookDevProperty.kEnvRotation); - linked = GUILayout.Toggle(isLink, GetGUIContentLink(isLink), styles.sToolBarButton); - if (EditorGUI.EndChangeCheck()) - { - UpdatePropertyLink(LookDevProperty.kEnvRotation, linked); - } - } - GUILayout.EndHorizontal(); - */ - } - GUILayout.EndVertical(); - } - GUILayout.EndArea(); - } - - public void Update() - { - // Force refresh of the frame to make the object turn - if (m_ObjRotationAcc > 0.0f || m_EnvRotationAcc > 0.0f) - { - // This is necessary to make the framerate normal for the editor window. - Repaint(); - } - } - - private void LoadRenderDoc() - { - if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) - { - RenderDoc.Load(); - ShaderUtil.RecreateGfxDevice(); - } - } - - private float ComputeLookDevEnvWindowWidth() - { - bool needVerticalScrollBar = (m_DisplayRect.height - 5.0f) < LookDevEnvironmentWindow.m_HDRIHeight * m_LookDevEnvLibrary.hdriCount; - return LookDevEnvironmentWindow.m_HDRIWidth + (needVerticalScrollBar ? 19.0f : 5.0f); - } - - private float ComputeLookDevEnvWindowHeight() - { - return m_DisplayRect.height; - } - - private void DoToolbarGUI() - { - GUILayout.BeginHorizontal(EditorStyles.toolbar); - { - Rect settingsRect = GUILayoutUtility.GetRect(LookDevSettingsWindow.styles.sTitle, EditorStyles.toolbarDropDown, GUILayout.Width(120)); - if (EditorGUI.DropdownButton(settingsRect, LookDevSettingsWindow.styles.sTitle, FocusType.Passive, EditorStyles.toolbarDropDown)) - { - Rect rect = GUILayoutUtility.topLevel.GetLast(); - PopupWindow.Show(rect, new LookDevSettingsWindow(this)); - GUIUtility.ExitGUI(); - } - - settingsRect = GUILayoutUtility.GetRect(LookDevViewsWindow.styles.sTitle, EditorStyles.toolbarDropDown, GUILayout.Width(120)); - if (EditorGUI.DropdownButton(settingsRect, LookDevViewsWindow.styles.sTitle, FocusType.Passive, EditorStyles.toolbarDropDown)) - { - Rect rect = GUILayoutUtility.topLevel.GetLast(); - PopupWindow.Show(rect, new LookDevViewsWindow(this)); - GUIUtility.ExitGUI(); - } - - m_LookDevConfig.enableShadowCubemap = GUILayout.Toggle(m_LookDevConfig.enableShadowCubemap, LookDevSettingsWindow.styles.sEnableShadowIcon, styles.sToolBarButton); - m_LookDevConfig.rotateObjectMode = GUILayout.Toggle(m_LookDevConfig.rotateObjectMode, LookDevSettingsWindow.styles.sEnableObjRotationIcon, styles.sToolBarButton); - m_LookDevConfig.rotateEnvMode = GUILayout.Toggle(m_LookDevConfig.rotateEnvMode, LookDevSettingsWindow.styles.sEnableEnvRotationIcon, styles.sToolBarButton); - - GUILayout.FlexibleSpace(); - - if (m_ShowLookDevEnvWindow) - { - if (GUILayout.Button(m_SyncLightVertical, EditorStyles.toolbarButton)) - { - Undo.RecordObject(m_LookDevEnvLibrary, "Synchronize lights"); - - int currentHDRIIndex = m_LookDevConfig.currentLookDevContext.currentHDRIIndex; - - for (int i = 0; i < m_LookDevEnvLibrary.hdriList.Count; ++i) - { - // Get offset to apply to cubemap to align (offset will be -360..360, so can be apply directly on cubemap angleOffset). - // code in PositionToLatLong / LatLongToPosition ensure that we are 0..360 for longitude. - m_LookDevEnvLibrary.hdriList[i].angleOffset += (m_LookDevEnvLibrary.hdriList[currentHDRIIndex].shadowInfo.longitude + m_LookDevEnvLibrary.hdriList[currentHDRIIndex].angleOffset) - (m_LookDevEnvLibrary.hdriList[i].shadowInfo.longitude + m_LookDevEnvLibrary.hdriList[i].angleOffset); - m_LookDevEnvLibrary.hdriList[i].angleOffset = (m_LookDevEnvLibrary.hdriList[i].angleOffset + 360.0f) % 360.0f; - } - - m_LookDevEnvLibrary.dirty = true; - - GUIUtility.ExitGUI(); - } - - if (GUILayout.Button(m_ResetEnvironment, EditorStyles.toolbarButton)) - { - Undo.RecordObject(m_LookDevEnvLibrary, "Reset environment"); - - for (int i = 0; i < m_LookDevEnvLibrary.hdriList.Count; ++i) - { - m_LookDevEnvLibrary.hdriList[i].angleOffset = 0; - } - - m_LookDevEnvLibrary.dirty = true; - - GUIUtility.ExitGUI(); - } - } - - if (RenderDoc.IsLoaded()) - { - using (new EditorGUI.DisabledScope(!RenderDoc.IsSupported())) - { - if (GUILayout.Button(m_RenderdocContent, EditorStyles.toolbarButton)) - { - m_CaptureRD = true; - GUIUtility.ExitGUI(); - } - } - } - - settingsRect = GUILayoutUtility.GetRect(LookDevEnvironmentWindow.styles.sTitle, EditorStyles.iconButton); - if (EditorGUI.DropdownButton(settingsRect, LookDevEnvironmentWindow.styles.sTitle, FocusType.Passive, EditorStyles.iconButton)) - { - m_ShowLookDevEnvWindow = !m_ShowLookDevEnvWindow; - } - - if (m_ShowLookDevEnvWindow) - { - Rect rect = new Rect(); - rect.x = 0; - rect.y = 0; - rect.width = ComputeLookDevEnvWindowWidth(); - rect.height = ComputeLookDevEnvWindowHeight(); - - Rect lookDevEnvWindowPos = new Rect(); - lookDevEnvWindowPos.x = m_DisplayRect.width - ComputeLookDevEnvWindowWidth(); - lookDevEnvWindowPos.y = m_DisplayRect.y; - lookDevEnvWindowPos.width = ComputeLookDevEnvWindowWidth(); - lookDevEnvWindowPos.height = ComputeLookDevEnvWindowHeight(); - - m_LookDevEnvWindow.SetRects(lookDevEnvWindowPos, rect, m_DisplayRect); - GUILayout.Window(0, lookDevEnvWindowPos, m_LookDevEnvWindow.OnGUI, "", styles.sBigTitleInnerStyle); - } - } - GUILayout.EndHorizontal(); - } - - void UpdateContextWithCurrentHDRI(Cubemap cubemap) - { - bool recordUndo = cubemap != LookDevResources.m_DefaultHDRI; - int iIndex = m_LookDevEnvLibrary.hdriList.FindIndex(x => x.cubemap == cubemap); - if (iIndex == -1) - { - // if the HDRI is not in the list insert it (allow to handle both drag and drop from explorer and from ShadowCubemap - m_LookDevEnvLibrary.InsertHDRI(cubemap); - iIndex = m_LookDevEnvLibrary.hdriList.Count - 1; - } - - m_LookDevConfig.UpdateIntProperty(LookDevProperty.HDRI, iIndex, recordUndo); - } - - public virtual void AddItemsToMenu(GenericMenu menu) - { - if (RenderDoc.IsInstalled() && !RenderDoc.IsLoaded()) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Load RenderDoc"), false, LoadRenderDoc); - } - } - - public void ResetView() - { - Undo.RecordObject(m_LookDevConfig, "Reset View"); - ScriptableObject.DestroyImmediate(m_LookDevConfig); - m_LookDevConfig = ScriptableObject.CreateInstance(); - m_LookDevConfig.SetLookDevView(this); - UpdateLookDevModeToggle(m_LookDevConfig.lookDevMode, true); - } - - private void LoadLookDevConfig() - { - if (m_LookDevConfig == null) - { - var saveLoadHelper = new ScriptableObjectSaveLoadHelper("asset", SaveType.Text); - LookDevConfig config = saveLoadHelper.Load(m_configAssetPath); - if (config == null) - { - m_LookDevConfig = ScriptableObject.CreateInstance(); - } - else - { - m_LookDevConfig = config; - } - m_IsSaveRegistered = false; - } - - m_LookDevConfig.SetLookDevView(this); - m_LookDevConfig.UpdateCurrentObjectArray(); - - if (m_LookDevEnvLibrary == null) - { - if (m_LookDevUserEnvLibrary != null) - { - m_LookDevEnvLibrary = ScriptableObject.Instantiate(m_LookDevUserEnvLibrary); - } - else - { - envLibrary = null; // Will create and initialize properly the library - } - } - - m_LookDevEnvLibrary.SetLookDevView(this); - } - - public void SaveLookDevConfig() - { - // Save view config - var saveLoadHelperConfig = new ScriptableObjectSaveLoadHelper("asset", SaveType.Text); - if (m_LookDevConfig != null) - { - saveLoadHelperConfig.Save(m_LookDevConfig, m_configAssetPath); - } - } - - public bool SaveLookDevLibrary() - { - // Save current library - if (m_LookDevUserEnvLibrary != null) - { - // Copy the current working library into the actual asset object and set it to dirty for saving. - EditorUtility.CopySerialized(m_LookDevEnvLibrary, m_LookDevUserEnvLibrary); - EditorUtility.SetDirty(m_LookDevEnvLibrary); - return true; - } - else - { - string assetPath = EditorUtility.SaveFilePanelInProject("Save New Environment Library", "New Env Library", "asset", ""); - if (!string.IsNullOrEmpty(assetPath)) - { - CreateNewLibrary(assetPath); - return true; - } - } - - return false; - } - - public void OnEnable() - { - InitializePreviewUtilities(); - - m_FirstViewGizmoColor = EditorGUIUtility.isProSkin ? new Color32(0, 204, 204, 255) : new Color32(0, 127, 255, 255); - m_SecondViewGizmoColor = EditorGUIUtility.isProSkin ? new Color32(255, 107, 33, 255) : new Color32(255, 127, 0, 255); - - LoadLookDevConfig(); - - // Required as we want that our material force a refresh update in the Lookdev - autoRepaintOnSceneChange = true; - - titleContent = GetLocalizedTitleContent(); - m_RenderdocContent = EditorGUIUtility.TrIconContent("renderdoc", "Capture the current view and open in RenderDoc"); - m_SyncLightVertical = EditorGUIUtility.TrIconContent("LookDevCenterLight", "Sync all light vertically with current light position in current selected HDRI"); - m_ResetEnvironment = EditorGUIUtility.TrIconContent("LookDevResetEnv", "Reset all environment"); - - UpdateLookDevModeToggle(m_LookDevConfig.lookDevMode, true); - - m_LookDevConfig.cameraStateCommon.rotation.valueChanged.AddListener(Repaint); - m_LookDevConfig.cameraStateCommon.pivot.valueChanged.AddListener(Repaint); - m_LookDevConfig.cameraStateCommon.viewSize.valueChanged.AddListener(Repaint); - - m_LookDevConfig.cameraStateLeft.rotation.valueChanged.AddListener(Repaint); - m_LookDevConfig.cameraStateLeft.pivot.valueChanged.AddListener(Repaint); - m_LookDevConfig.cameraStateLeft.viewSize.valueChanged.AddListener(Repaint); - - m_LookDevConfig.cameraStateRight.rotation.valueChanged.AddListener(Repaint); - m_LookDevConfig.cameraStateRight.pivot.valueChanged.AddListener(Repaint); - m_LookDevConfig.cameraStateRight.viewSize.valueChanged.AddListener(Repaint); - - Undo.undoRedoPerformed += OnUndoRedo; - EditorApplication.editorApplicationQuit += OnQuit; - EditorApplication.update += EditorUpdate; - } - - public void OnDisable() - { - SaveLookDevConfig(); - - Undo.undoRedoPerformed -= OnUndoRedo; - EditorApplication.editorApplicationQuit -= OnQuit; - EditorApplication.update -= EditorUpdate; - } - - void OnQuit() - { - SaveLookDevConfig(); - } - - void DelayedSaveLookDevConfig() - { - if (!m_IsSaveRegistered) - { - m_IsSaveRegistered = true; - EditorApplication.delayCall += DoDelayedSaveLookDevConfig; - } - } - - void DoDelayedSaveLookDevConfig() - { - m_IsSaveRegistered = false; - SaveLookDevConfig(); - } - - private void RenderPreviewSingle() - { - int index = m_LookDevConfig.lookDevMode == LookDevMode.Single1 ? 0 : 1; - - UpdateRenderTexture(m_PreviewRects[2]); - - RenderScene(m_PreviewRects[2], m_LookDevConfig.lookDevContexts[index], m_PreviewUtilityContexts[index], m_LookDevConfig.currentObjectInstances[index], m_LookDevConfig.cameraState[index], false); - RenderCompositing(m_PreviewRects[2], m_PreviewUtilityContexts[index], m_PreviewUtilityContexts[index], false); - } - - private void RenderPreviewSideBySide() - { - UpdateRenderTexture(m_PreviewRects[2]); - - RenderScene(m_PreviewRects[0], m_LookDevConfig.lookDevContexts[0], m_PreviewUtilityContexts[0], m_LookDevConfig.currentObjectInstances[0], m_LookDevConfig.cameraState[0], false); - RenderScene(m_PreviewRects[1], m_LookDevConfig.lookDevContexts[1], m_PreviewUtilityContexts[1], m_LookDevConfig.currentObjectInstances[1], m_LookDevConfig.cameraState[1], true); - - RenderCompositing(m_PreviewRects[2], m_PreviewUtilityContexts[0], m_PreviewUtilityContexts[1], true); - } - - private void RenderPreviewDualView() - { - UpdateRenderTexture(m_PreviewRects[2]); - - RenderScene(m_PreviewRects[2], m_LookDevConfig.lookDevContexts[0], m_PreviewUtilityContexts[0], m_LookDevConfig.currentObjectInstances[0], m_LookDevConfig.cameraState[0], false); - RenderScene(m_PreviewRects[2], m_LookDevConfig.lookDevContexts[1], m_PreviewUtilityContexts[1], m_LookDevConfig.currentObjectInstances[1], m_LookDevConfig.cameraState[1], false); - - RenderCompositing(m_PreviewRects[2], m_PreviewUtilityContexts[0], m_PreviewUtilityContexts[1], true); - } - - void RenderCompositing(Rect previewRect, PreviewContext previewContext0, PreviewContext previewContext1, bool dualView) - { - if (m_FinalCompositionTexture.width < 1 || m_FinalCompositionTexture.height < 1) - return; - - Vector4 gizmoPosition = new Vector4(m_LookDevConfig.gizmo.center.x, m_LookDevConfig.gizmo.center.y, 0.0f, 0.0f); - Vector4 gizmoZoneCenter = new Vector4(m_LookDevConfig.gizmo.point2.x, m_LookDevConfig.gizmo.point2.y, 0.0f, 0.0f); - Vector4 gizmoThickness = new Vector4(m_GizmoThickness, m_GizmoThicknessSelected, 0.0f, 0.0f); - Vector4 gizmoCircleRadius = new Vector4(m_GizmoCircleRadius, m_GizmoCircleRadiusSelected, 0.0f, 0.0f); - - // When we render in single view, map the parameters on same context. - int index0 = (m_LookDevConfig.lookDevMode == LookDevMode.Single2) ? 1 : 0; - int index1 = (m_LookDevConfig.lookDevMode == LookDevMode.Single1) ? 0 : 1; - - float exposureValue0 = (DrawCameraMode)m_LookDevConfig.lookDevContexts[index0].shadingMode == DrawCameraMode.Normal || (DrawCameraMode)m_LookDevConfig.lookDevContexts[index0].shadingMode == DrawCameraMode.TexturedWire ? m_LookDevConfig.lookDevContexts[index0].exposureValue : 0.0f; - float exposureValue1 = (DrawCameraMode)m_LookDevConfig.lookDevContexts[index1].shadingMode == DrawCameraMode.Normal || (DrawCameraMode)m_LookDevConfig.lookDevContexts[index1].shadingMode == DrawCameraMode.TexturedWire ? m_LookDevConfig.lookDevContexts[index1].exposureValue : 0.0f; - - float dragAndDropContext = m_CurrentDragContext == LookDevEditionContext.Left ? 1.0f : (m_CurrentDragContext == LookDevEditionContext.Right ? -1.0f : 0.0f); - - CubemapInfo envInfo0 = m_LookDevEnvLibrary.hdriList[m_LookDevConfig.lookDevContexts[index0].currentHDRIIndex]; - CubemapInfo envInfo1 = m_LookDevEnvLibrary.hdriList[m_LookDevConfig.lookDevContexts[index1].currentHDRIIndex]; - - // Prepare shadow information - float shadowMultiplier0 = envInfo0.shadowInfo.shadowIntensity; - float shadowMultiplier1 = envInfo1.shadowInfo.shadowIntensity; - Color shadowColor0 = envInfo0.shadowInfo.shadowColor; - Color shadowColor1 = envInfo1.shadowInfo.shadowColor; - - Texture texNormal0 = previewContext0.m_PreviewResult[(int)PreviewContext.PreviewContextPass.kView]; - Texture texWithoutSun0 = previewContext0.m_PreviewResult[(int)PreviewContext.PreviewContextPass.kViewWithShadow]; - Texture texShadows0 = previewContext0.m_PreviewResult[(int)PreviewContext.PreviewContextPass.kShadow]; - - Texture texNormal1 = previewContext1.m_PreviewResult[(int)PreviewContext.PreviewContextPass.kView]; - Texture texWithoutSun1 = previewContext1.m_PreviewResult[(int)PreviewContext.PreviewContextPass.kViewWithShadow]; - Texture texShadows1 = previewContext1.m_PreviewResult[(int)PreviewContext.PreviewContextPass.kShadow]; - - Vector4 compositingParams = new Vector4(m_LookDevConfig.dualViewBlendFactor, exposureValue0, exposureValue1, m_LookDevConfig.currentEditionContext == LookDevEditionContext.Left ? 1.0f : -1.0f); - Vector4 compositingParams2 = new Vector4(dragAndDropContext, m_LookDevConfig.enableToneMap ? 1.0f : -1.0f, shadowMultiplier0, shadowMultiplier1); - - // Those could be tweakable for the neutral tonemapper, but in the case of the LookDev we don't need that - const float BlackIn = 0.02f; - const float WhiteIn = 10.0f; - const float BlackOut = 0.0f; - const float WhiteOut = 10.0f; - const float WhiteLevel = 5.3f; - const float WhiteClip = 10.0f; - const float DialUnits = 20.0f; - const float HalfDialUnits = DialUnits * 0.5f; - - // converting from artist dial units to easy shader-lerps (0-1) - Vector4 tonemapCoeff1 = new Vector4((BlackIn * DialUnits) + 1.0f, (BlackOut * HalfDialUnits) + 1.0f, (WhiteIn / DialUnits), (1.0f - (WhiteOut / DialUnits))); - Vector4 tonemapCoeff2 = new Vector4(0.0f, 0.0f, WhiteLevel, WhiteClip / HalfDialUnits); - - RenderTexture oldActive = RenderTexture.active; - RenderTexture.active = m_FinalCompositionTexture; - LookDevResources.m_LookDevCompositing.SetTexture("_Tex0Normal", texNormal0); - LookDevResources.m_LookDevCompositing.SetTexture("_Tex0WithoutSun", texWithoutSun0); - LookDevResources.m_LookDevCompositing.SetTexture("_Tex0Shadows", texShadows0); - LookDevResources.m_LookDevCompositing.SetColor("_ShadowColor0", shadowColor0); - LookDevResources.m_LookDevCompositing.SetTexture("_Tex1Normal", texNormal1); - LookDevResources.m_LookDevCompositing.SetTexture("_Tex1WithoutSun", texWithoutSun1); - LookDevResources.m_LookDevCompositing.SetTexture("_Tex1Shadows", texShadows1); - LookDevResources.m_LookDevCompositing.SetColor("_ShadowColor1", shadowColor1); - LookDevResources.m_LookDevCompositing.SetVector("_CompositingParams", compositingParams); - LookDevResources.m_LookDevCompositing.SetVector("_CompositingParams2", compositingParams2); - LookDevResources.m_LookDevCompositing.SetColor("_FirstViewColor", m_FirstViewGizmoColor); - LookDevResources.m_LookDevCompositing.SetColor("_SecondViewColor", m_SecondViewGizmoColor); - LookDevResources.m_LookDevCompositing.SetVector("_GizmoPosition", gizmoPosition); - LookDevResources.m_LookDevCompositing.SetVector("_GizmoZoneCenter", gizmoZoneCenter); - LookDevResources.m_LookDevCompositing.SetVector("_GizmoSplitPlane", m_LookDevConfig.gizmo.plane); - LookDevResources.m_LookDevCompositing.SetVector("_GizmoSplitPlaneOrtho", m_LookDevConfig.gizmo.planeOrtho); - LookDevResources.m_LookDevCompositing.SetFloat("_GizmoLength", m_LookDevConfig.gizmo.length); - LookDevResources.m_LookDevCompositing.SetVector("_GizmoThickness", gizmoThickness); - LookDevResources.m_LookDevCompositing.SetVector("_GizmoCircleRadius", gizmoCircleRadius); - LookDevResources.m_LookDevCompositing.SetFloat("_BlendFactorCircleRadius", m_BlendFactorCircleRadius); - LookDevResources.m_LookDevCompositing.SetFloat("_GetBlendFactorMaxGizmoDistance", GetBlendFactorMaxGizmoDistance()); - LookDevResources.m_LookDevCompositing.SetFloat("_GizmoRenderMode", m_ForceGizmoRenderSelector ? (float)LookDevOperationType.GizmoAll : (float)m_GizmoRenderMode); - LookDevResources.m_LookDevCompositing.SetVector("_ScreenRatio", m_ScreenRatio); - LookDevResources.m_LookDevCompositing.SetVector("_ToneMapCoeffs1", tonemapCoeff1); - LookDevResources.m_LookDevCompositing.SetVector("_ToneMapCoeffs2", tonemapCoeff2); - LookDevResources.m_LookDevCompositing.SetPass((int)m_LookDevConfig.lookDevMode); - - DrawFullScreenQuad(new Rect(0, 0, previewRect.width, previewRect.height)); - - GL.sRGBWrite = false; - RenderTexture.active = oldActive; - - GUI.DrawTexture(previewRect, m_FinalCompositionTexture, ScaleMode.StretchToFill, false); - } - - void EditorUpdate() - { - for (var i = 0; i < 2; ++i) - { - for (var j = 0; j < m_LookDevConfig.previewObjects[i].Length; j++) - { - var currentObject = m_LookDevConfig.previewObjects[i][j]; - if (currentObject == null) - continue; - - EditorUtility.InitInstantiatedPreviewRecursive(currentObject); // hide objects in hierarchy - LookDevConfig.DisableRendererProperties(currentObject); - PreviewRenderUtility.SetEnabledRecursive(currentObject, false); - } - } - } - - private void RenderPreview() - { - if (Event.current.type == EventType.Repaint) - { - if (m_LookDevConfig.rotateObjectMode) - m_ObjRotationAcc = Math.Min(m_ObjRotationAcc + Time.deltaTime * 0.5f, 1.0f); - else - // Do brutal stop because weoften want to stop at a particular position - m_ObjRotationAcc = 0.0f; // Math.Max(m_ObjRotationAcc - Time.deltaTime * 0.5f, 0.0f); - - if (m_LookDevConfig.rotateEnvMode) - m_EnvRotationAcc = Math.Min(m_EnvRotationAcc + Time.deltaTime * 0.5f, 1.0f); - else - // Do brutal stop because weoften want to stop at a particular position - m_EnvRotationAcc = 0.0f; // Math.Max(m_EnvRotationAcc - Time.deltaTime * 0.5f, 0.0f); - - // Handle objects/env rotation - // speed control (in degree) - Time.deltaTime is in seconds - m_CurrentObjRotationOffset = (m_CurrentObjRotationOffset + Time.deltaTime * 360.0f * 0.3f * m_LookDevConfig.objRotationSpeed * m_ObjRotationAcc) % 360.0f; - m_LookDevConfig.lookDevContexts[0].envRotation = (m_LookDevConfig.lookDevContexts[0].envRotation + Time.deltaTime * 360.0f * 0.03f * m_LookDevConfig.envRotationSpeed * m_EnvRotationAcc) % 720.0f; // 720 to match GUI - m_LookDevConfig.lookDevContexts[1].envRotation = (m_LookDevConfig.lookDevContexts[1].envRotation + Time.deltaTime * 360.0f * 0.03f * m_LookDevConfig.envRotationSpeed * m_EnvRotationAcc) % 720.0f; // 720 to match GUI - - GL.sRGBWrite = QualitySettings.activeColorSpace == ColorSpace.Linear; - switch (m_LookDevConfig.lookDevMode) - { - case LookDevMode.Single1: - case LookDevMode.Single2: - RenderPreviewSingle(); - break; - case LookDevMode.SideBySide: - RenderPreviewSideBySide(); - break; - case LookDevMode.Zone: - case LookDevMode.Split: - RenderPreviewDualView(); - break; - } - GL.sRGBWrite = false; - } - } - - private void DoGizmoDebug() - { - if (m_DisplayDebugGizmo) - { - int lineCount = 7; - float controlWindowWith = 150; - float controlWindowHeight = kLineHeight * lineCount; - float fieldWidth = 60.0f; - float labelWidth = 90.0f; - - GUILayout.BeginArea(new Rect(position.width - controlWindowWith - 10, position.height - controlWindowHeight - 10, controlWindowWith, controlWindowHeight), styles.sBigTitleInnerStyle); - { - GUILayout.BeginVertical(); - { - GUILayout.BeginHorizontal(); - { - GUILayout.Label("Thickness", EditorStyles.miniLabel, GUILayout.Width(labelWidth)); - m_GizmoThickness = Mathf.Clamp(EditorGUILayout.FloatField(m_GizmoThickness, GUILayout.Width(fieldWidth)), 0.0f, 1.0f); - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - { - GUILayout.Label("ThicknessSelected", EditorStyles.miniLabel, GUILayout.Width(labelWidth)); - m_GizmoThicknessSelected = Mathf.Clamp(EditorGUILayout.FloatField(m_GizmoThicknessSelected, GUILayout.Width(fieldWidth)), 0.0f, 1.0f); - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - { - GUILayout.Label("Radius", EditorStyles.miniLabel, GUILayout.Width(labelWidth)); - m_GizmoCircleRadius = Mathf.Clamp(EditorGUILayout.FloatField(m_GizmoCircleRadius, GUILayout.Width(fieldWidth)), 0.0f, 1.0f); - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - { - GUILayout.Label("RadiusSelected", EditorStyles.miniLabel, GUILayout.Width(labelWidth)); - m_GizmoCircleRadiusSelected = Mathf.Clamp(EditorGUILayout.FloatField(m_GizmoCircleRadiusSelected, GUILayout.Width(fieldWidth)), 0.0f, 1.0f); - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - { - GUILayout.Label("BlendRadius", EditorStyles.miniLabel, GUILayout.Width(labelWidth)); - m_BlendFactorCircleRadius = Mathf.Clamp(EditorGUILayout.FloatField(m_BlendFactorCircleRadius, GUILayout.Width(fieldWidth)), 0.0f, 1.0f); - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - { - GUILayout.Label("Selected", EditorStyles.miniLabel, GUILayout.Width(labelWidth)); - m_ForceGizmoRenderSelector = GUILayout.Toggle(m_ForceGizmoRenderSelector, ""); - } - GUILayout.EndHorizontal(); - - if (GUILayout.Button("Reset Gizmo")) - { - m_LookDevConfig.gizmo.Update(new Vector2(0.0f, 0.0f), 0.2f, 0.0f); - } - } - GUILayout.EndVertical(); - } - GUILayout.EndArea(); - } - } - - private void UpdateViewSpecific() - { - UpdatePreviewRects(m_DisplayRect); - - // The reference scale is here to give the gizmo a fix scale regardless of LookDev window size. - // 1080 is arbitrary but it may be good to tie it somehow to the desktop resolution? (Should not be a problem in practice as the LookDev is an edition tool that should be used with enough screen real estate anyway) - m_ScreenRatio.Set(m_PreviewRects[2].width / kReferenceScale, m_PreviewRects[2].height / kReferenceScale, m_PreviewRects[2].width, m_PreviewRects[2].height); - - int lineCount = 4; // Title - Exposure - Environment - Rotation - float controlWindowWith = 292.0f; - float controlWindowHeight = kLineHeight * lineCount + EditorGUIUtility.standardVerticalSpacing; - - m_ControlWindowRect = new Rect(m_PreviewRects[2].width / 2 - controlWindowWith / 2, m_PreviewRects[2].height - controlWindowHeight - 10, controlWindowWith, controlWindowHeight); - } - - private void UpdatePreviewRects(Rect previewRect) - { - m_PreviewRects[2] = new Rect(previewRect); - if (m_ShowLookDevEnvWindow) - { - m_PreviewRects[2].width = m_PreviewRects[2].width - ComputeLookDevEnvWindowWidth(); - } - m_PreviewRects[(int)LookDevEditionContext.Left] = new Rect(m_PreviewRects[2].x, m_PreviewRects[2].y, m_PreviewRects[2].width / 2, m_PreviewRects[2].height); - m_PreviewRects[(int)LookDevEditionContext.Right] = new Rect(m_PreviewRects[2].width / 2, m_PreviewRects[2].y, m_PreviewRects[2].width / 2, m_PreviewRects[2].height); - } - - private void HandleCamera() - { - if (m_LookDevOperationType == LookDevOperationType.None && !m_ControlWindowRect.Contains(Event.current.mousePosition)) - { - int currentContextIndex = m_LookDevConfig.currentEditionContextIndex; - int otherContextIndex = (currentContextIndex + 1) % 2; - - // Camera controller updates Camera States according to inputs - m_CameraController.Update(m_LookDevConfig.cameraState[currentContextIndex], m_PreviewUtilityContexts[m_LookDevConfig.currentEditionContextIndex].m_PreviewUtility[0].camera); // We can use m_PreviewUtility[0] because all of them should be always synchronized anyway - - // If single or side by side mode and camera are linked we need to update both cameras - if ((m_LookDevConfig.lookDevMode == LookDevMode.Single1 || m_LookDevConfig.lookDevMode == LookDevMode.Single2 || m_LookDevConfig.lookDevMode == LookDevMode.SideBySide) && m_LookDevConfig.sideBySideCameraLinked) - { - m_LookDevConfig.cameraState[otherContextIndex].Copy(m_LookDevConfig.cameraState[currentContextIndex]); - } - - if (m_CameraController.currentViewTool == ViewTool.None) - { - if (Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.F) - { - if (!EditorGUIUtility.editingTextField) - { - Frame(m_LookDevConfig.currentEditionContext, true); - Event.current.Use(); - } - } - } - - // Update the actual Cameras with CameraState infos - for (int i = 0; i < (int)PreviewContext.PreviewContextPass.kCount; ++i) - { - m_LookDevConfig.cameraState[0].UpdateCamera(m_PreviewUtilityContexts[0].m_PreviewUtility[i].camera); - m_LookDevConfig.cameraState[1].UpdateCamera(m_PreviewUtilityContexts[1].m_PreviewUtility[i].camera); - } - - m_LookDevConfig.cameraStateLeft.Copy(m_LookDevConfig.cameraState[0]); - m_LookDevConfig.cameraStateRight.Copy(m_LookDevConfig.cameraState[1]); - - DelayedSaveLookDevConfig(); - } - } - - public void HandleKeyboardShortcut() - { - // Only query camera when no in Layout event - if (Event.current.type == EventType.Layout || EditorGUIUtility.editingTextField) - return; - - if (Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.RightArrow) - { - m_LookDevConfig.UpdateIntProperty(LookDevProperty.HDRI, Math.Min(m_LookDevConfig.currentLookDevContext.currentHDRIIndex + 1, m_LookDevEnvLibrary.hdriList.Count - 1)); - Event.current.Use(); - } - else if (Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.LeftArrow) - { - m_LookDevConfig.UpdateIntProperty(LookDevProperty.HDRI, Math.Max(m_LookDevConfig.currentLookDevContext.currentHDRIIndex - 1, 0)); - Event.current.Use(); - } - - if (Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.R) - { - m_LookDevConfig.ResynchronizeObjects(); - Event.current.Use(); - } - } - - public void Frame() - { - Frame(true); - } - - public void Frame(bool animate) - { - Frame(LookDevEditionContext.Left, animate); - Frame(LookDevEditionContext.Right, animate); - } - - private void Frame(LookDevEditionContext context, bool animate) - { - GameObject currentObject = m_LookDevConfig.currentObjectInstances[(int)context][0]; - if (currentObject != null) - { - Bounds bounds = new Bounds(currentObject.transform.position, Vector3.zero); - GetRenderableBoundsRecurse(ref bounds, currentObject); - - float newSize = bounds.extents.magnitude * 1.5f; - if (newSize == 0) - newSize = 10; - - CameraState cameraState = m_LookDevConfig.cameraState[(int)context]; - if (animate) - { - cameraState.pivot.target = bounds.center; - cameraState.viewSize.target = Mathf.Abs(newSize * 2.2f); - } - else - { - cameraState.pivot.value = bounds.center; - cameraState.viewSize.value = Mathf.Abs(newSize * 2.2f); - } - } - m_CurrentObjRotationOffset = 0.0f; - } - - private void HandleDragging() - { - Event evt = Event.current; - - switch (evt.type) - { - case EventType.DragPerform: - bool hasAddedRenderableObject = false; - if (m_PreviewRects[2].Contains(evt.mousePosition)) - { - foreach (UnityEngine.Object o in DragAndDrop.objectReferences) - { - Cubemap cubemap = o as Cubemap; - if (cubemap) - { - UpdateFocus(Event.current.mousePosition); - UpdateContextWithCurrentHDRI(cubemap); - } - - // If we have a skybox material, then try to get the cubemap texture. - Material material = o as Material; - if (material && material.shader.name.Contains("Skybox/Cubemap")) - { - Cubemap cubemap2 = material.GetTexture("_Tex") as Cubemap; - if (cubemap2) - { - UpdateFocus(Event.current.mousePosition); - UpdateContextWithCurrentHDRI(cubemap2); - } - } - - GameObject go = o as GameObject; - if (go) - { - if (!hasAddedRenderableObject && GameObjectInspector.HasRenderableParts(go)) - { - UpdateFocus(Event.current.mousePosition); - Undo.RecordObject(m_LookDevConfig, "Set current preview object"); - - // Set current window - bool bothViewUpdated = m_LookDevConfig.SetCurrentPreviewObject(go); - DelayedSaveLookDevConfig(); - - Frame(m_LookDevConfig.currentEditionContext, false); - // Frame the other view if required - if (bothViewUpdated) - { - Frame(m_LookDevConfig.currentEditionContext == LookDevEditionContext.Left ? LookDevEditionContext.Right : LookDevEditionContext.Left, false); - } - hasAddedRenderableObject = true; - } - } - - LookDevEnvironmentLibrary lib = o as LookDevEnvironmentLibrary; - if (lib) - { - envLibrary = lib; - } - } - } - DragAndDrop.AcceptDrag(); - m_CurrentDragContext = LookDevEditionContext.None; - m_LookDevEnvWindow.CancelSelection(); - evt.Use(); - break; - case EventType.DragUpdated: - { - bool canDrag = false; - foreach (UnityEngine.Object o in DragAndDrop.objectReferences) - { - Cubemap cubemap = o as Cubemap; - if (cubemap) - { - canDrag = true; - } - - // If we have a skybox material, then try to get the cubemap texture. - Material material = o as Material; - if (material && material.shader.name.Contains("Skybox/Cubemap")) - { - canDrag = true; - } - - GameObject go = o as GameObject; - if (go && EditorUtility.IsPersistent(go) && PrefabUtility.GetPrefabObject(go) != null) - { - if (GameObjectInspector.HasRenderableParts(go)) - { - canDrag = true; - } - } - - LookDevEnvironmentLibrary lib = o as LookDevEnvironmentLibrary; - if (lib) - { - canDrag = true; - } - } - DragAndDrop.visualMode = canDrag ? DragAndDropVisualMode.Link : DragAndDropVisualMode.Rejected; - m_CurrentDragContext = GetEditionContext(Event.current.mousePosition); - - evt.Use(); - } - break; - case EventType.DragExited: - m_CurrentDragContext = LookDevEditionContext.None; - break; - case EventType.Repaint: - break; - } - } - - private Vector2 GetNormalizedCoordinates(Vector2 mousePosition, Rect previewRect) - { - Vector2 normalizedCoord = new Vector3((mousePosition.x - previewRect.x) / previewRect.width, (mousePosition.y - previewRect.y) / previewRect.height); - normalizedCoord.x = (normalizedCoord.x * 2.0f - 1.0f) * m_ScreenRatio.x; - normalizedCoord.y = -(normalizedCoord.y * 2.0f - 1.0f) * m_ScreenRatio.y; - - return normalizedCoord; - } - - LookDevEditionContext GetEditionContext(Vector2 position) - { - if (!m_PreviewRects[2].Contains(position)) // This may happen if the library is open - { - return LookDevEditionContext.None; - } - - LookDevEditionContext context; - switch (m_LookDevConfig.lookDevMode) - { - case LookDevMode.Single1: - { - context = LookDevEditionContext.Left; - break; - } - case LookDevMode.Single2: - { - context = LookDevEditionContext.Right; - break; - } - case LookDevMode.SideBySide: - { - if (m_PreviewRects[(int)LookDevEditionContext.Left].Contains(position)) - context = LookDevEditionContext.Left; - else - context = LookDevEditionContext.Right; - break; - } - case LookDevMode.Split: - { - Vector2 normalizedCoord = GetNormalizedCoordinates(position, m_PreviewRects[2]); - - if (Vector3.Dot(new Vector3(normalizedCoord.x, normalizedCoord.y, 1.0f), m_LookDevConfig.gizmo.plane) > 0.0f) - context = LookDevEditionContext.Left; - else - context = LookDevEditionContext.Right; - break; - } - case LookDevMode.Zone: - { - Vector2 normalizedCoord = GetNormalizedCoordinates(position, m_PreviewRects[2]); - - if ((Vector2.Distance(normalizedCoord, m_LookDevConfig.gizmo.point2) - m_LookDevConfig.gizmo.length * 2.0f) > 0.0f) - context = LookDevEditionContext.Left; - else - context = LookDevEditionContext.Right; - break; - } - default: - context = LookDevEditionContext.Left; - break; - } - - return context; - } - - public void UpdateFocus(Vector2 position) - { - m_LookDevConfig.UpdateFocus(GetEditionContext(position)); - } - - private LookDevOperationType GetGizmoZoneOperation(Vector2 mousePosition, Rect previewRect) - { - Vector2 normalizedCoord = GetNormalizedCoordinates(mousePosition, previewRect); - Vector3 normalizedCoordZ1 = new Vector3(normalizedCoord.x, normalizedCoord.y, 1.0f); - - float distanceToPlane = Vector3.Dot(normalizedCoordZ1, m_LookDevConfig.gizmo.plane); - float absDistanceToPlane = Mathf.Abs(distanceToPlane); - float distanceFromCenter = Vector2.Distance(normalizedCoord, m_LookDevConfig.gizmo.center); - float distanceToOrtho = Vector3.Dot(normalizedCoordZ1, m_LookDevConfig.gizmo.planeOrtho); - float side = (distanceToOrtho > 0.0f) ? 1.0f : -1.0f; - Vector2 orthoPlaneNormal = new Vector2(m_LookDevConfig.gizmo.planeOrtho.x, m_LookDevConfig.gizmo.planeOrtho.y); - - LookDevOperationType result = LookDevOperationType.None; - if (absDistanceToPlane < m_GizmoCircleRadiusSelected && (distanceFromCenter < (m_LookDevConfig.gizmo.length + m_GizmoCircleRadiusSelected))) - { - if (absDistanceToPlane < m_GizmoThicknessSelected) - { - result = LookDevOperationType.GizmoTranslation; - } - - Vector2 circleCenter = m_LookDevConfig.gizmo.center + side * orthoPlaneNormal * m_LookDevConfig.gizmo.length; - float d = Vector2.Distance(normalizedCoord, circleCenter); - if (d <= m_GizmoCircleRadiusSelected) - { - result = side > 0.0f ? LookDevOperationType.GizmoRotationZone1 : LookDevOperationType.GizmoRotationZone2; - } - - float maxBlendCircleDistanceToCenter = GetBlendFactorMaxGizmoDistance(); - float minBlendCircleDistanceToCenter = GetBlendFactorMaxGizmoDistance() + m_BlendFactorCircleRadius - m_BlendFactorCircleSelectionRadius; - - float blendCircleDistanceToCenter = m_LookDevConfig.dualViewBlendFactor * GetBlendFactorMaxGizmoDistance(); - Vector2 blendCircleCenter = m_LookDevConfig.gizmo.center - orthoPlaneNormal * blendCircleDistanceToCenter; - float blendCircleSelectionRadius = Mathf.Lerp(m_BlendFactorCircleRadius, m_BlendFactorCircleSelectionRadius, Mathf.Clamp((maxBlendCircleDistanceToCenter - Mathf.Abs(blendCircleDistanceToCenter)) / (maxBlendCircleDistanceToCenter - minBlendCircleDistanceToCenter), 0.0f, 1.0f)); - if ((normalizedCoord - blendCircleCenter).magnitude < blendCircleSelectionRadius) - { - result = LookDevOperationType.BlendFactor; - } - } - - return result; - } - - bool IsOperatingGizmo() - { - return m_LookDevOperationType == LookDevOperationType.BlendFactor || - m_LookDevOperationType == LookDevOperationType.GizmoRotationZone1 || - m_LookDevOperationType == LookDevOperationType.GizmoRotationZone2 || - m_LookDevOperationType == LookDevOperationType.GizmoTranslation; - } - - private void HandleMouseInput() - { - Event evt = Event.current; - - m_hotControlID = GUIUtility.GetControlID(FocusType.Passive); - - switch (evt.GetTypeForControl(m_hotControlID)) - { - case EventType.MouseDown: - { - if ((m_LookDevConfig.lookDevMode == LookDevMode.Split || m_LookDevConfig.lookDevMode == LookDevMode.Zone) && evt.button == 0) - { - m_LookDevOperationType = GetGizmoZoneOperation(Event.current.mousePosition, m_PreviewRects[2]); - m_OnMouseDownOffsetToGizmo = GetNormalizedCoordinates(Event.current.mousePosition, m_PreviewRects[2]) - m_LookDevConfig.gizmo.center; - } - - // Gizmo manipulation takes precedence over other types of operations - if (m_LookDevOperationType == LookDevOperationType.None) - { - if (evt.shift && evt.button == 0) - { - m_LookDevOperationType = LookDevOperationType.RotateLight; - } - else if (evt.control && evt.button == 0) - { - m_LookDevOperationType = LookDevOperationType.RotateEnvironment; - } - } - - if (!IsOperatingGizmo() && !m_ControlWindowRect.Contains(Event.current.mousePosition)) - { - UpdateFocus(Event.current.mousePosition); - } - - GUIUtility.hotControl = m_hotControlID; - break; - } - case EventType.MouseMove: - { - m_GizmoRenderMode = GetGizmoZoneOperation(Event.current.mousePosition, m_PreviewRects[2]); - Repaint(); - break; - } - case EventType.MouseUp: - { - // Snap back to 0 when close to the center - if (m_LookDevOperationType == LookDevOperationType.BlendFactor) - { - if (Mathf.Abs(m_LookDevConfig.dualViewBlendFactor) < m_GizmoCircleRadiusSelected / (m_LookDevConfig.gizmo.length - m_GizmoCircleRadius)) - { - m_LookDevConfig.dualViewBlendFactor = 0.0f; - } - } - - m_LookDevOperationType = LookDevOperationType.None; - - if (m_LookDevEnvWindow != null) - { - Cubemap currentEnvSelection = m_LookDevEnvWindow.GetCurrentSelection(); - if (currentEnvSelection != null) - { - UpdateFocus(Event.current.mousePosition); - UpdateContextWithCurrentHDRI(currentEnvSelection); - m_LookDevEnvWindow.CancelSelection(); - m_CurrentDragContext = LookDevEditionContext.None; - Repaint(); - } - } - - GUIUtility.hotControl = 0; - - break; - } - case EventType.MouseDrag: - { - if (m_LookDevOperationType == LookDevOperationType.RotateEnvironment) - { - float currentRotation = m_LookDevConfig.currentLookDevContext.envRotation; - currentRotation = (currentRotation + evt.delta.x / Mathf.Min(position.width, position.height) * 140.0f + 720.0f) % 720.0f; // 720 to match GUI in main control panel - m_LookDevConfig.UpdateFloatProperty(LookDevProperty.EnvRotation, currentRotation); - Event.current.Use(); - } - else if (m_LookDevOperationType == LookDevOperationType.RotateLight && m_LookDevConfig.enableShadowCubemap) - { - ShadowInfo shadowInfo = m_LookDevEnvLibrary.hdriList[m_LookDevConfig.currentLookDevContext.currentHDRIIndex].shadowInfo; - shadowInfo.latitude = shadowInfo.latitude - (evt.delta.y * 0.6f); - shadowInfo.longitude = shadowInfo.longitude - (evt.delta.x * 0.6f); - - Repaint(); - } - break; - } - } - - // Mouse Up outside the window: we need to cancel the selection - if (Event.current.rawType == EventType.MouseUp) - { - if (m_LookDevEnvWindow.GetCurrentSelection() != null) - { - m_LookDevEnvWindow.CancelSelection(); - } - } - - if (m_LookDevOperationType == LookDevOperationType.GizmoTranslation) - { - Vector2 newPosition = GetNormalizedCoordinates(Event.current.mousePosition, m_PreviewRects[2]) - m_OnMouseDownOffsetToGizmo; - - Vector2 minXY = GetNormalizedCoordinates(new Vector2(m_DisplayRect.x, m_PreviewRects[2].y + m_DisplayRect.height), m_PreviewRects[2]); - Vector2 maxXY = GetNormalizedCoordinates(new Vector2(m_DisplayRect.x + m_DisplayRect.width, m_PreviewRects[2].y), m_PreviewRects[2]); - - // We clamp the center of the gizmo to the border of the screen in order to avoid being able to put it out of the screen. - // The safe band is here to ensure that you always see at least part of the gizmo in order to be able to grab it again. - float fSafeBand = 0.05f; - newPosition.x = Mathf.Clamp(newPosition.x, minXY.x + fSafeBand, maxXY.x - fSafeBand); - newPosition.y = Mathf.Clamp(newPosition.y, minXY.y + fSafeBand, maxXY.y - fSafeBand); - - m_LookDevConfig.gizmo.Update(newPosition, m_LookDevConfig.gizmo.length, m_LookDevConfig.gizmo.angle); - Repaint(); - } - - if (m_LookDevOperationType == LookDevOperationType.GizmoRotationZone1 || m_LookDevOperationType == LookDevOperationType.GizmoRotationZone2) - { - Vector2 normalizedCoord = GetNormalizedCoordinates(Event.current.mousePosition, m_PreviewRects[2]); - Vector2 basePoint, newPoint; - float angleSnapping = Mathf.Deg2Rad * 45.0f * 0.5f; - - if (m_LookDevOperationType == LookDevOperationType.GizmoRotationZone1) - { - newPoint = normalizedCoord; - basePoint = m_LookDevConfig.gizmo.point2; - } - else - { - newPoint = normalizedCoord; - basePoint = m_LookDevConfig.gizmo.point1; - } - - // Clamp the gizmo size to the smaller window dimension to avoid an out of window unresizable gizmo - float gizmoLength = (basePoint - newPoint).magnitude; - float minWindowSize = Mathf.Min(position.width, position.height); - float smallestNormalizedWindowSize = minWindowSize / kReferenceScale * 2.0f * 0.9f;// Mathf.Min(position.width / minWindowSize, position.height / minWindowSize) * 2.0f * 0.9f; - if (gizmoLength > smallestNormalizedWindowSize) - { - Vector2 direction = newPoint - basePoint; - direction.Normalize(); - newPoint = basePoint + direction * smallestNormalizedWindowSize; - } - - // Snap to a multiple of "angleSnapping" - if (Event.current.shift) - { - Vector3 verticalPlane = new Vector3(-1.0f, 0.0f, basePoint.x); - float side = Vector3.Dot(new Vector3(normalizedCoord.x, normalizedCoord.y, 1.0f), verticalPlane); - - float angle = Mathf.Deg2Rad * Vector2.Angle(new Vector2(0.0f, 1.0f), normalizedCoord - basePoint); - if (side > 0.0f) - angle = 2.0f * Mathf.PI - angle; - angle = (int)(angle / angleSnapping) * angleSnapping; - Vector2 dir = normalizedCoord - basePoint; - float length = dir.magnitude; // we want to keep the length of the gizmo where it should be given the mouse position - newPoint = basePoint + new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)) * length; - } - - if (m_LookDevOperationType == LookDevOperationType.GizmoRotationZone1) - { - m_LookDevConfig.gizmo.Update(newPoint, basePoint); - } - else - { - m_LookDevConfig.gizmo.Update(basePoint, newPoint); - } - - Repaint(); - } - - if (m_LookDevOperationType == LookDevOperationType.BlendFactor) - { - Vector2 mousePosition = GetNormalizedCoordinates(Event.current.mousePosition, m_PreviewRects[2]); - float distanceToOrthoPlane = -Vector3.Dot(new Vector3(mousePosition.x, mousePosition.y, 1.0f), m_LookDevConfig.gizmo.planeOrtho) / GetBlendFactorMaxGizmoDistance(); - m_LookDevConfig.dualViewBlendFactor = Mathf.Clamp(distanceToOrthoPlane, -1.0f, 1.0f); - Repaint(); - } - } - - private float GetBlendFactorMaxGizmoDistance() - { - return m_LookDevConfig.gizmo.length - m_GizmoCircleRadius - m_BlendFactorCircleRadius; - } - - void CleanupDeletedHDRI() - { - m_LookDevEnvLibrary.CleanupDeletedHDRI(); - } - - private void OnGUI() - { - // Debug code to load a custom shader for development - /* - bool toto = false; - - if (toto) - { - Shader devShader = Shader.Find("Custom/DevShader") as Shader; - if( devShader != null) - LookDevResources.m_LookDevCompositing = new Material(devShader); - } - */ - - - // To enable renderdoc in lookdev it require to expose BeginCaptureRenderDoc and EndCaptureRenderDoc to script. - if (Event.current.type == EventType.Repaint && m_CaptureRD) - { - //m_Parent.BeginCaptureRenderDoc(); - } - - Initialize(); - CleanupDeletedHDRI(); - BeginWindows(); - m_DisplayRect = new Rect(0, kLineHeight, position.width, (position.height - kLineHeight)); - - UpdateViewSpecific(); - - DoToolbarGUI(); - - HandleDragging(); - - RenderPreview(); - - DoControlWindow(); - DoAdditionalGUI(); - DoGizmoDebug(); - - HandleMouseInput(); - HandleCamera(); - HandleKeyboardShortcut(); - - // Draw text to say that we need to drag and drop an object - if (m_LookDevConfig.currentObjectInstances[0][0] == null && m_LookDevConfig.currentObjectInstances[1][0] == null) - { - Color oldColor = GUI.color; - GUI.color = Color.gray; - Vector2 textSize = GUI.skin.label.CalcSize(styles.sDragAndDropObjsText); - Rect labelRect = new Rect(m_DisplayRect.width * .5f - textSize.x * .5f, m_DisplayRect.height * .2f - textSize.y * .5f, textSize.x, textSize.y); - GUI.Label(labelRect, styles.sDragAndDropObjsText); - GUI.color = oldColor; - } - - EndWindows(); - - // this is a bit tricky and actually depends heavily on the LookDevEnvironmentWindow - // When the user drags an HDRI from the libray, we display it half transparent where the mouse cursor is. - // The problem is that we can't render that in the LookDevEnvironmentWindow outsite of its Rect, so we render it once more here from the main LookDev window - if (Event.current.type == EventType.Repaint) - { - if (m_LookDevEnvWindow != null && m_LookDevEnvWindow.GetCurrentSelection() != null) - { - m_CurrentDragContext = GetEditionContext(Event.current.mousePosition); - GUI.DrawTexture(new Rect(Event.current.mousePosition.x - m_LookDevEnvWindow.GetSelectedPositionOffset().x, Event.current.mousePosition.y - m_LookDevEnvWindow.GetSelectedPositionOffset().y, LookDevEnvironmentWindow.m_HDRIWidth, LookDevEnvironmentWindow.m_latLongHeight), LookDevResources.m_SelectionTexture, ScaleMode.ScaleToFit, true); - } - else - { - m_CurrentDragContext = LookDevEditionContext.None; - } - } - - - if (Event.current.type == EventType.Repaint && m_CaptureRD) - { - //m_Parent.EndCaptureRenderDoc(); - m_CaptureRD = false; - } - } - - void GetShaderConstantsFromNormalizedSH(SphericalHarmonicsL2 ambientProbe, Vector4[] outCoefficients) - { - for (int channelIdx = 0; channelIdx < 3; ++channelIdx) - { - // Constant + Linear - // In the shader we multiply the normal is not swizzled, so it's normal.xyz. - // Swizzle the coefficients to be in { x, y, z, DC } order. - outCoefficients[channelIdx].x = ambientProbe[channelIdx, 3]; - outCoefficients[channelIdx].y = ambientProbe[channelIdx, 1]; - outCoefficients[channelIdx].z = ambientProbe[channelIdx, 2]; - outCoefficients[channelIdx].w = ambientProbe[channelIdx, 0] - ambientProbe[channelIdx, 6]; - - // Quadratic polynomials - outCoefficients[channelIdx + 3].x = ambientProbe[channelIdx, 4]; - outCoefficients[channelIdx + 3].y = ambientProbe[channelIdx, 5]; - outCoefficients[channelIdx + 3].z = ambientProbe[channelIdx, 6] * 3.0f; - outCoefficients[channelIdx + 3].w = ambientProbe[channelIdx, 7]; - } - - // Final quadratic polynomial - outCoefficients[6].x = ambientProbe[0, 8]; - outCoefficients[6].y = ambientProbe[1, 8]; - outCoefficients[6].z = ambientProbe[2, 8]; - outCoefficients[6].w = 1.0f; - } - } -} diff --git a/Editor/Mono/LookDevView/LookDevViewsWindow.cs b/Editor/Mono/LookDevView/LookDevViewsWindow.cs deleted file mode 100644 index 3a80ef6856..0000000000 --- a/Editor/Mono/LookDevView/LookDevViewsWindow.cs +++ /dev/null @@ -1,284 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class LookDevViewsWindow - : PopupWindowContent - { - public class Styles - { - public readonly GUIStyle sMenuItem = "MenuItem"; - public readonly GUIStyle sHeaderStyle = EditorStyles.miniLabel; - public readonly GUIStyle sToolBarButton = "toolbarbutton"; - - public readonly GUIContent sTitle = EditorGUIUtility.TrTextContent("Views"); - public readonly GUIContent sExposure = EditorGUIUtility.TrTextContent("EV", "Exposure value: control the brightness of the environment."); - public readonly GUIContent sEnvironment = EditorGUIUtility.TrTextContent("Environment", "Select an environment from the list of currently available environments"); - public readonly GUIContent sRotation = EditorGUIUtility.TrTextContent("Rotation", "Change the rotation of the environment"); - public readonly GUIContent sZero = EditorGUIUtility.TextContent("0"); - public readonly GUIContent sLoD = EditorGUIUtility.TrTextContent("LoD", "Choose displayed LoD"); - public readonly GUIContent sLoDAuto = EditorGUIUtility.TrTextContent("LoD (auto)", "Choose displayed LoD"); - public readonly GUIContent sShadingMode = EditorGUIUtility.TrTextContent("Shading", "Select shading mode"); - - public readonly GUIContent[] sViewTitle = - { - EditorGUIUtility.TrTextContent("Main View (1)"), - EditorGUIUtility.TrTextContent("Second View (2)"), - }; - - public readonly GUIStyle[] sViewTitleStyles = - { - new GUIStyle(EditorStyles.miniLabel), - new GUIStyle(EditorStyles.miniLabel) - }; - - public readonly string[] sShadingModeStrings = { "Shaded", "Shaded Wireframe", "Albedo", "Specular", "Smoothness", "Normal" }; - public readonly int[] sShadingModeValues = { (int)DrawCameraMode.Normal, (int)DrawCameraMode.TexturedWire, (int)DrawCameraMode.DeferredDiffuse, (int)DrawCameraMode.DeferredSpecular, (int)DrawCameraMode.DeferredSmoothness, (int)DrawCameraMode.DeferredNormal }; - - public readonly GUIContent sLinkActive = EditorGUIUtility.TrIconContent("LookDevMirrorViewsActive", "Links the property between the different views"); - public readonly GUIContent sLinkInactive = EditorGUIUtility.TrIconContent("LookDevMirrorViewsInactive", "Links the property between the different views"); - - - public Styles() - { - sViewTitleStyles[0].normal.textColor = LookDevView.m_FirstViewGizmoColor; - sViewTitleStyles[1].normal.textColor = LookDevView.m_SecondViewGizmoColor; - } - } - - GUIContent GetGUIContentLink(bool active) - { - return active ? styles.sLinkActive : styles.sLinkInactive; - } - - static Styles s_Styles = new Styles(); - public static Styles styles { get { return s_Styles; } } - - static float kIconSize = 32; - static float kLabelWidth = 120.0f; - static float kSliderWidth = 100.0f; - static float kSliderFieldWidth = 30.0f; - static float kSliderFieldPadding = 5.0f; - static float kLineHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - - float m_WindowHeight = 5 * kLineHeight + EditorGUIUtility.standardVerticalSpacing; - float m_WindowWidth = kLabelWidth + kSliderWidth + kSliderFieldWidth + kSliderFieldPadding + 5.0f; - - - private readonly LookDevView m_LookDevView; - - public LookDevViewsWindow(LookDevView lookDevView) - { - m_LookDevView = lookDevView; - } - - private bool NeedLoD() - { - return m_LookDevView.config.GetObjectLoDCount(LookDevEditionContext.Left) > 1 || m_LookDevView.config.GetObjectLoDCount(LookDevEditionContext.Right) > 1; - } - - private float GetHeight() - { - float height = m_WindowHeight; - if (NeedLoD()) - { - height += kLineHeight; - } - - return height; - } - - public override Vector2 GetWindowSize() - { - float width = m_WindowWidth + ((m_LookDevView.config.lookDevMode == LookDevMode.Single1 || m_LookDevView.config.lookDevMode == LookDevMode.Single2) ? 0 : (m_WindowWidth + kIconSize)); - return new Vector2(width, GetHeight()); - } - - public override void OnGUI(Rect rect) - { - if (m_LookDevView.config == null) - return; - - Rect drawPos = new Rect(0, 0, rect.width, GetHeight()); - - DrawOneView(drawPos, (m_LookDevView.config.lookDevMode == LookDevMode.Single2) ? LookDevEditionContext.Right : LookDevEditionContext.Left); - - drawPos.x += m_WindowWidth; - - drawPos.x += kIconSize; - DrawOneView(drawPos, LookDevEditionContext.Right); - - // Use mouse move so we get hover state correctly in the menu item rows - if (Event.current.type == EventType.MouseMove) - Event.current.Use(); - - // Escape closes the window - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - { - editorWindow.Close(); - GUIUtility.ExitGUI(); - } - } - - private void DrawOneView(Rect drawPos, LookDevEditionContext context) - { - int i = (int)context; - bool drawLinks = ((m_LookDevView.config.lookDevMode != LookDevMode.Single1) && (context == LookDevEditionContext.Left)) || ((m_LookDevView.config.lookDevMode != LookDevMode.Single2) && (context == LookDevEditionContext.Right)); - - GUILayout.BeginArea(drawPos); - - GUILayout.Label(styles.sViewTitle[i], styles.sViewTitleStyles[i]); - - GUILayout.BeginHorizontal(); - { - GUILayout.BeginVertical(GUILayout.Width(m_WindowWidth)); - { - GUILayout.BeginHorizontal(GUILayout.Height(kLineHeight)); - { - GUILayout.Label(styles.sExposure, styles.sMenuItem, GUILayout.Width(kLabelWidth)); - - float fExposureValue = m_LookDevView.config.GetFloatProperty(LookDevProperty.ExposureValue, context); - EditorGUI.BeginChangeCheck(); - float roundedExposureRange = Mathf.Round(m_LookDevView.config.exposureRange); - fExposureValue = Mathf.Clamp(GUILayout.HorizontalSlider(fExposureValue, -roundedExposureRange, roundedExposureRange, GUILayout.Width(kSliderWidth)), -roundedExposureRange, roundedExposureRange); // Clamp is here to return value to the right range if the user decrease the exposure range - // Display in the float field is rounded for display. To 1 decimal in case of negative number to account for the '-' character. - fExposureValue = Mathf.Clamp(EditorGUILayout.FloatField((float)Math.Round(fExposureValue, fExposureValue < 0.0f ? 1 : 2), GUILayout.Width(kSliderFieldWidth)), -roundedExposureRange, roundedExposureRange); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevView.config.UpdateFocus(context); - m_LookDevView.config.UpdateFloatProperty(LookDevProperty.ExposureValue, fExposureValue); - } - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.Height(kLineHeight)); - { - int iHDRIIndex = -1; - int iHDRICount = m_LookDevView.envLibrary.hdriCount; - - using (new EditorGUI.DisabledScope(iHDRICount <= 1)) - { - GUILayout.Label(styles.sEnvironment, styles.sMenuItem, GUILayout.Width(kLabelWidth)); - - if (iHDRICount > 1) - { - int maxHDRIIndex = iHDRICount - 1; - iHDRIIndex = m_LookDevView.config.GetIntProperty(LookDevProperty.HDRI, context); - EditorGUI.BeginChangeCheck(); - iHDRIIndex = (int)GUILayout.HorizontalSlider(iHDRIIndex, 0.0f, (float)maxHDRIIndex, GUILayout.Width(kSliderWidth)); - iHDRIIndex = Mathf.Clamp(EditorGUILayout.IntField(iHDRIIndex, GUILayout.Width(kSliderFieldWidth)), 0, maxHDRIIndex); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevView.config.UpdateFocus(context); - m_LookDevView.config.UpdateIntProperty(LookDevProperty.HDRI, iHDRIIndex); - } - } - else - { - GUILayout.HorizontalSlider(0.0f, 0.0f, 0.0f, GUILayout.Width(kSliderWidth)); - GUILayout.Label(styles.sZero, styles.sMenuItem); - } - } - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.Height(kLineHeight)); - { - GUILayout.Label(styles.sShadingMode, styles.sMenuItem, GUILayout.Width(kLabelWidth)); - - int shadingMode = m_LookDevView.config.GetIntProperty(LookDevProperty.ShadingMode, context); - EditorGUI.BeginChangeCheck(); - shadingMode = EditorGUILayout.IntPopup("", shadingMode, styles.sShadingModeStrings, styles.sShadingModeValues, GUILayout.Width(kSliderFieldWidth + kSliderWidth + 4.0f)); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevView.config.UpdateFocus(context); - m_LookDevView.config.UpdateIntProperty(LookDevProperty.ShadingMode, shadingMode); - } - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(GUILayout.Height(kLineHeight)); - { - GUILayout.Label(styles.sRotation, styles.sMenuItem, GUILayout.Width(kLabelWidth)); - - float envRotation = m_LookDevView.config.GetFloatProperty(LookDevProperty.EnvRotation, context); - EditorGUI.BeginChangeCheck(); - envRotation = GUILayout.HorizontalSlider(envRotation, 0.0f, 720.0f, GUILayout.Width(kSliderWidth)); - envRotation = Mathf.Clamp(EditorGUILayout.FloatField((float)Math.Round(envRotation, 0), GUILayout.Width(kSliderFieldWidth)), 0.0f, 720.0f); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevView.config.UpdateFocus(context); - m_LookDevView.config.UpdateFloatProperty(LookDevProperty.EnvRotation, envRotation); - } - } - GUILayout.EndHorizontal(); - - if (NeedLoD()) - { - GUILayout.BeginHorizontal(GUILayout.Height(kLineHeight)); - { - if (m_LookDevView.config.GetObjectLoDCount(context) > 1) - { - int lodIndex = m_LookDevView.config.GetIntProperty(LookDevProperty.LoDIndex, context); - - GUILayout.Label(lodIndex == -1 ? styles.sLoDAuto : styles.sLoD, styles.sMenuItem, GUILayout.Width(kLabelWidth)); - - EditorGUI.BeginChangeCheck(); - - int maxLoDIndex = m_LookDevView.config.GetObjectLoDCount(context) - 1; - - // We need a specific handling here in case of linked property, because even if it is linked the two meshes can have different number of LOD - // We handle that by taking the min of the number of mesh if the property is link - if ((m_LookDevView.config.lookDevMode != LookDevMode.Single1 && m_LookDevView.config.lookDevMode != LookDevMode.Single2) && m_LookDevView.config.IsPropertyLinked(LookDevProperty.LoDIndex)) - { - maxLoDIndex = Math.Min(m_LookDevView.config.GetObjectLoDCount(LookDevEditionContext.Left), m_LookDevView.config.GetObjectLoDCount(LookDevEditionContext.Right)) - 1; - } - - lodIndex = Mathf.Clamp(lodIndex, -1, maxLoDIndex); - - lodIndex = (int)GUILayout.HorizontalSlider(lodIndex, -1, maxLoDIndex, GUILayout.Width(kSliderWidth)); - lodIndex = EditorGUILayout.IntField(lodIndex, GUILayout.Width(kSliderFieldWidth)); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevView.config.UpdateFocus(context); - m_LookDevView.config.UpdateIntProperty(LookDevProperty.LoDIndex, lodIndex); - } - } - } - GUILayout.EndHorizontal(); - } - } - GUILayout.EndVertical(); - - if (drawLinks) - { - GUILayout.BeginVertical(GUILayout.Width(kIconSize)); - { - LookDevProperty[] properties = { LookDevProperty.ExposureValue, LookDevProperty.HDRI, LookDevProperty.ShadingMode, LookDevProperty.EnvRotation, LookDevProperty.LoDIndex }; - int propertyCount = 4 + (NeedLoD() ? 1 : 0); - for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) - { - bool linked = false; - EditorGUI.BeginChangeCheck(); - bool isLink = m_LookDevView.config.IsPropertyLinked(properties[propertyIndex]); - linked = GUILayout.Toggle(isLink, GetGUIContentLink(isLink), styles.sToolBarButton, GUILayout.Height(kLineHeight)); - if (EditorGUI.EndChangeCheck()) - { - m_LookDevView.config.UpdatePropertyLink(properties[propertyIndex], linked); - } - } - } - GUILayout.EndVertical(); - } - } - GUILayout.EndHorizontal(); - GUILayout.EndArea(); - } - } -} diff --git a/Editor/Mono/Macros/MacroEvaluator.cs b/Editor/Mono/Macros/MacroEvaluator.cs deleted file mode 100644 index a1884f570c..0000000000 --- a/Editor/Mono/Macros/MacroEvaluator.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Reflection; -using System.Text.RegularExpressions; -using UnityScript.Scripting; - -namespace UnityEditor.Macros -{ - public static class MacroEvaluator - { - public static string Eval(string macro) - { - if (macro.StartsWith("ExecuteMethod: ")) - return ExecuteMethodThroughReflection(macro); - - - var value = Evaluator.Eval(EditorEvaluationContext, macro); - return value == null ? "Null" : value.ToString(); - } - - private static string ExecuteMethodThroughReflection(string macro) - { - var regex = new Regex("ExecuteMethod: (?.*)\\.(?.*)"); - var match = regex.Match(macro); - var typename = match.Groups["type"].ToString(); - var methodname = match.Groups["method"].ToString(); - - var type = EditorAssemblies.loadedAssemblies.Select(a => a.GetType(typename, false)).Where(t => t != null).First(); - var method = type.GetMethod(methodname, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - if (method == null) - throw new ArgumentException(String.Format("cannot find method {0} in type {1}", methodname, typename)); - if (method.GetParameters().Length > 0) - throw new ArgumentException("You can only invoke static methods with no arguments"); - var result = method.Invoke(null, new object[0]); - return result == null ? "Null" : result.ToString(); - } - - private static readonly EvaluationContext EditorEvaluationContext = new EvaluationContext(new EditorEvaluationDomainProvider()); - - private class EditorEvaluationDomainProvider : SimpleEvaluationDomainProvider - { - private static readonly string[] DefaultImports = new[] { "UnityEditor", "UnityEngine" }; - - public EditorEvaluationDomainProvider() : base(DefaultImports) - { - } - - public override Assembly[] GetAssemblyReferences() - { - var editorAssemblies = EditorAssemblies.loadedAssemblies; - var referencedAssemblies = editorAssemblies.SelectMany(a => a.GetReferencedAssemblies()).Select(a => TryToLoad(a)).Where(a => a != null); - return editorAssemblies.Concat(referencedAssemblies).ToArray(); - } - - private static Assembly TryToLoad(AssemblyName a) - { - try - { - return Assembly.Load(a); - } - catch (Exception) - { - return null; - } - } - } - } -} diff --git a/Editor/Mono/Macros/MethodEvaluator.cs b/Editor/Mono/Macros/MethodEvaluator.cs deleted file mode 100644 index 683e1596a2..0000000000 --- a/Editor/Mono/Macros/MethodEvaluator.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.Serialization.Formatters; -using System.Runtime.Serialization.Formatters.Binary; - -namespace UnityEditor.Macros -{ - public static class MethodEvaluator - { - private static readonly BinaryFormatter s_Formatter = - new BinaryFormatter { AssemblyFormat = FormatterAssemblyStyle.Simple }; - - private class AssemblyResolver - { - private readonly string m_AssemblyDirectory; - - public AssemblyResolver(string assemblyDirectory) - { - m_AssemblyDirectory = assemblyDirectory; - } - - public Assembly AssemblyResolve(object sender, ResolveEventArgs args) - { - var simpleName = args.Name.Split(',')[0]; - var assemblyFile = Path.Combine(m_AssemblyDirectory, simpleName + ".dll"); - if (File.Exists(assemblyFile)) - return Assembly.LoadFrom(assemblyFile); - return null; - } - } - - public static object Eval(string assemblyFile, string typeName, - string methodName, Type[] paramTypes, object[] args) - { - var assemblyDirectory = Path.GetDirectoryName(assemblyFile); - var resolver = new AssemblyResolver(assemblyDirectory); - AppDomain.CurrentDomain.AssemblyResolve += resolver.AssemblyResolve; - try - { - var assembly = Assembly.LoadFrom(assemblyFile); - var method = assembly.GetType(typeName, true).GetMethod(methodName, - BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, - null, paramTypes, null); - if (method == null) - throw new ArgumentException(string.Format( - "Method {0}.{1}({2}) not found in assembly {3}!", typeName, - methodName, ToCommaSeparatedString(paramTypes), - assembly.FullName)); - return method.Invoke(null, args); - } - finally - { - AppDomain.CurrentDomain.AssemblyResolve -= resolver.AssemblyResolve; - } - } - - public static object ExecuteExternalCode(string parcel) - { - using (var stream = new MemoryStream(Convert.FromBase64String(parcel))) - { - var header = (string)s_Formatter.Deserialize(stream); - if (header != "com.unity3d.automation") - throw new Exception("Invalid parcel for external code execution."); - var assemblyPath = (string)s_Formatter.Deserialize(stream); - var resolver = new AssemblyResolver(Path.GetDirectoryName(assemblyPath)); - AppDomain.CurrentDomain.AssemblyResolve += resolver.AssemblyResolve; - var assembly = Assembly.LoadFrom(assemblyPath); - try - { - var type = (Type)s_Formatter.Deserialize(stream); - var methodName = (string)s_Formatter.Deserialize(stream); - const BindingFlags methodVisibility = BindingFlags.Public | - BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; - var methodParametersTypes = (Type[])s_Formatter.Deserialize(stream); - var method = type.GetMethod(methodName, methodVisibility, null, - methodParametersTypes, null); - if (method == null) - throw new Exception(string.Format( - "Could not find method {0}.{1} in assembly {2} located in {3}.", - type.FullName, methodName, assembly.GetName().Name, assemblyPath)); - var arguments = (object[])s_Formatter.Deserialize(stream); - return ExecuteCode(type, method, arguments); - } - finally - { - AppDomain.CurrentDomain.AssemblyResolve -= resolver.AssemblyResolve; - } - } - } - - private static object ExecuteCode(Type target, MethodInfo method, object[] args) - { - return method.Invoke(method.IsStatic ? null : GetActor(target), args); - } - - private static object GetActor(Type type) - { - var ctorInfo = type.GetConstructor(new Type[] {}); - return ctorInfo != null ? ctorInfo.Invoke(new object[] {}) : null; - } - - private static string ToCommaSeparatedString(IEnumerable items) - { - return string.Join(", ", items.Select(o => o.ToString()).ToArray()); - } - } -} diff --git a/Editor/Mono/MaterialProperty.cs b/Editor/Mono/MaterialProperty.cs deleted file mode 100644 index 65abf1352c..0000000000 --- a/Editor/Mono/MaterialProperty.cs +++ /dev/null @@ -1,229 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Runtime.InteropServices; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - // match MonoMaterialProperty layout! - [StructLayout(LayoutKind.Sequential)] - public sealed class MaterialProperty - { - public enum PropType - { - Color, - Vector, - Float, - Range, - Texture, - } - - [Obsolete("Use UnityEngine.Rendering.TextureDimension instead", false)] - public enum TexDim - { - Unknown = -1, - None = 0, - Tex2D = 2, - Tex3D = 3, - Cube = 4, - Any = 6, - } - - [Flags] - public enum PropFlags - { - None = 0, - HideInInspector = (1 << 0), - PerRendererData = (1 << 1), - NoScaleOffset = (1 << 2), - Normal = (1 << 3), - HDR = (1 << 4), - Gamma = (1 << 5), - NonModifiableTextureData = (1 << 6), - } - - public delegate bool ApplyPropertyCallback(MaterialProperty prop, int changeMask, object previousValue); - - private Object[] m_Targets; - private ApplyPropertyCallback m_ApplyPropertyCallback; - private string m_Name; - private string m_DisplayName; - private System.Object m_Value; - private Vector4 m_TextureScaleAndOffset; - private Vector2 m_RangeLimits; - private PropType m_Type; - private PropFlags m_Flags; - private UnityEngine.Rendering.TextureDimension m_TextureDimension; - private int m_MixedValueMask; - - - public Object[] targets { get { return m_Targets; } } - public PropType type { get { return m_Type; } } - public string name { get { return m_Name; } } - public string displayName { get { return m_DisplayName; } } - public PropFlags flags { get { return m_Flags; } } - public UnityEngine.Rendering.TextureDimension textureDimension { get { return m_TextureDimension; } } - public Vector2 rangeLimits { get { return m_RangeLimits; } } - public bool hasMixedValue { get { return (m_MixedValueMask & 1) != 0; } } - public ApplyPropertyCallback applyPropertyCallback { get { return m_ApplyPropertyCallback; } set { m_ApplyPropertyCallback = value; } } - - // Textures have 5 different mixed values for texture + UV scale/offset - internal int mixedValueMask { get { return m_MixedValueMask; } } - - public void ReadFromMaterialPropertyBlock(MaterialPropertyBlock block) - { - ShaderUtil.ApplyMaterialPropertyBlockToMaterialProperty(block, this); - } - - public void WriteToMaterialPropertyBlock(MaterialPropertyBlock materialblock, int changedPropertyMask) - { - ShaderUtil.ApplyMaterialPropertyToMaterialPropertyBlock(this, changedPropertyMask, materialblock); - } - - public Color colorValue - { - get - { - if (m_Type == PropType.Color) - return (Color)m_Value; - return Color.black; - } - set - { - if (m_Type != PropType.Color) - return; - if (!hasMixedValue && value == (Color)m_Value) - return; - - ApplyProperty(value); - } - } - - public Vector4 vectorValue - { - get - { - if (m_Type == PropType.Vector) - return (Vector4)m_Value; - return Vector4.zero; - } - set - { - if (m_Type != PropType.Vector) - return; - if (!hasMixedValue && value == (Vector4)m_Value) - return; - - ApplyProperty(value); - } - } - - internal static bool IsTextureOffsetAndScaleChangedMask(int changedMask) - { - changedMask >>= 1; - return changedMask != 0; - } - - public float floatValue - { - get - { - if (m_Type == PropType.Float || m_Type == PropType.Range) - return (float)m_Value; - return 0.0f; - } - set - { - if (m_Type != PropType.Float && m_Type != PropType.Range) - return; - if (!hasMixedValue && value == (float)m_Value) - return; - - ApplyProperty(value); - } - } - - public Texture textureValue - { - get - { - if (m_Type == PropType.Texture) - return (Texture)m_Value; - return null; - } - set - { - if (m_Type != PropType.Texture) - return; - if (!hasMixedValue && value == (Texture)m_Value) - return; - - m_MixedValueMask &= ~1; - object previousValue = m_Value; - m_Value = value; - - ApplyProperty(previousValue, 1); - } - } - - public Vector4 textureScaleAndOffset - { - get - { - if (m_Type == PropType.Texture) - return m_TextureScaleAndOffset; - return Vector4.zero; - } - set - { - if (m_Type != PropType.Texture) - return; - if (!hasMixedValue && value == m_TextureScaleAndOffset) - return; - - m_MixedValueMask &= 1; - int changedMask = 0; - for (int c = 1; c < 5; c++) - changedMask |= 1 << c; - - object previousValue = m_TextureScaleAndOffset; - m_TextureScaleAndOffset = value; - ApplyProperty(previousValue, changedMask); - } - } - - private void ApplyProperty(object newValue) - { - m_MixedValueMask = 0; - object previousValue = m_Value; - m_Value = newValue; - ApplyProperty(previousValue, 1); - } - - private void ApplyProperty(object previousValue, int changedPropertyMask) - { - if (targets == null || targets.Length == 0) - throw new ArgumentException("No material targets provided"); - - Object[] mats = targets; - string targetTitle; - if (mats.Length == 1) - targetTitle = mats[0].name; - else - targetTitle = mats.Length + " " + ObjectNames.NicifyVariableName(ObjectNames.GetClassName(mats[0])) + "s"; - - //@TODO: Maybe all this logic should be moved to C++ - // reduces api surface... - bool didApply = false; - if (m_ApplyPropertyCallback != null) - didApply = m_ApplyPropertyCallback(this, changedPropertyMask, previousValue); - - if (!didApply) - ShaderUtil.ApplyProperty(this, changedPropertyMask, "Modify " + displayName + " of " + targetTitle); - } - } -} // namespace UnityEngine.Rendering diff --git a/Editor/Mono/Media/Bindings/MediaEncoder.bindings.cs b/Editor/Mono/Media/Bindings/MediaEncoder.bindings.cs deleted file mode 100644 index 00f29847ce..0000000000 --- a/Editor/Mono/Media/Bindings/MediaEncoder.bindings.cs +++ /dev/null @@ -1,132 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; -using UnityEngine.Bindings; -using Unity.Collections; -using Unity.Collections.LowLevel.Unsafe; -using Object = UnityEngine.Object; - -namespace UnityEditor.Media -{ - [NativeHeader("Editor/Mono/Media/Bindings/MediaEncoder.bindings.h")] - - public struct MediaRational - { - public MediaRational(int num) - { - numerator = num; - denominator = 1; - } - - public int numerator; - public int denominator; - } - - public struct VideoTrackAttributes - { - public MediaRational frameRate; - public uint width; - public uint height; - public bool includeAlpha; // For webm only; not applicable to mp4. - public VideoBitrateMode bitRateMode; - } - - public struct AudioTrackAttributes - { - public MediaRational sampleRate; - public ushort channelCount; - public string language; - //Future work: - //public string format; // E.g.: "Stereo", "5.1", "Ambisonic 1st order", ... - //public string layout[]; // E.g.: ["Left", "Right", "Center"] - } - - public class MediaEncoder : IDisposable - { - public IntPtr m_Ptr; - - public MediaEncoder( - string filePath, VideoTrackAttributes videoAttrs, AudioTrackAttributes[] audioAttrs) - { - m_Ptr = Create(filePath, new[] {videoAttrs}, audioAttrs); - } - - public MediaEncoder( - string filePath, VideoTrackAttributes videoAttrs, AudioTrackAttributes audioAttrs) - : this(filePath, videoAttrs, new[] {audioAttrs}) - {} - - public MediaEncoder(string filePath, VideoTrackAttributes videoAttrs) - : this(filePath, videoAttrs, new AudioTrackAttributes[0]) - {} - - public MediaEncoder(string filePath, AudioTrackAttributes[] audioAttrs) - { - m_Ptr = Create(filePath, new VideoTrackAttributes[0], audioAttrs); - } - - public MediaEncoder(string filePath, AudioTrackAttributes audioAttrs) - : this(filePath, new[] {audioAttrs}) - {} - - ~MediaEncoder() - { - Dispose(); - } - - public bool AddFrame(Texture2D texture) - { - return Internal_AddFrame(m_Ptr, texture); - } - - unsafe public bool AddSamples(ushort trackIndex, NativeArray interleavedSamples) - { - return Internal_AddSamples( - m_Ptr, trackIndex, interleavedSamples.GetUnsafeReadOnlyPtr(), - interleavedSamples.Length); - } - - public bool AddSamples(NativeArray interleavedSamples) - { - return AddSamples(0, interleavedSamples); - } - - public void Dispose() - { - if (m_Ptr != IntPtr.Zero) - { - Internal_Release(m_Ptr); - m_Ptr = IntPtr.Zero; - } - GC.SuppressFinalize(this); - } - - private IntPtr Create( - string filePath, VideoTrackAttributes[] videoAttrs, AudioTrackAttributes[] audioAttrs) - { - IntPtr ptr = Internal_Create(filePath, videoAttrs, audioAttrs); - if (ptr == IntPtr.Zero) - throw new InvalidOperationException( - "MediaEncoder: Output file creation failed for " + filePath); - return ptr; - } - - [FreeFunction] - extern private static IntPtr Internal_Create( - string filePath, VideoTrackAttributes[] videoAttrs, AudioTrackAttributes[] audioAttrs); - - [FreeFunction] - extern private static void Internal_Release(IntPtr encoder); - - [FreeFunction] - extern private static bool Internal_AddFrame(IntPtr encoder, Texture2D texture); - - [FreeFunction] - unsafe extern private static bool Internal_AddSamples( - IntPtr encoder, ushort trackIndex, void* buffer, int sampleCount); - } -} diff --git a/Editor/Mono/Menu.bindings.cs b/Editor/Mono/Menu.bindings.cs deleted file mode 100644 index 2553d313cf..0000000000 --- a/Editor/Mono/Menu.bindings.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/MenuController.h")] - public sealed class Menu - { - [NativeMethod("MenuController::SetChecked", true)] - public static extern void SetChecked(string menuPath, bool isChecked); - - [NativeMethod("MenuController::GetChecked", true)] - public static extern bool GetChecked(string menuPath); - } -} diff --git a/Editor/Mono/MenuCommand.cs b/Editor/Mono/MenuCommand.cs deleted file mode 100644 index c7c2b8eb6d..0000000000 --- a/Editor/Mono/MenuCommand.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Runtime.InteropServices; -using UnityEngine; -using UnityEngine.Scripting; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - // Used to extract the context for a [[MenuItem]]. MenuCommand objects are passed to custom menu item functions defined using the [[MenuItem]] attribute. - // Keep in sync with MenuCommandBinding in Runtime\Scripting\ManagedAttributeManager.h - [StructLayout(LayoutKind.Sequential)] - [RequiredByNativeCode] - public sealed class MenuCommand - { - // Context is the object that is the target of a menu command. - public Object context; - // An integer for passing custom information to a menu item. - public int userData; - - // Creates a new MenuCommand object. - public MenuCommand(Object inContext, int inUserData) { context = inContext; userData = inUserData; } - // Creates a new MenuCommand object. - public MenuCommand(Object inContext) { context = inContext; userData = 0; } - } -} diff --git a/Editor/Mono/MenuItem.cs b/Editor/Mono/MenuItem.cs deleted file mode 100644 index 1951b37469..0000000000 --- a/Editor/Mono/MenuItem.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - // The MenuItem attribute allows you to add menu items to the main menu and inspector context menus. - [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] - [RequiredByNativeCode] - public sealed class MenuItem : Attribute - { - // Creates a menu item and invokes the static function following it, when the menu item is selected. - public MenuItem(string itemName) : this(itemName, false) {} - - // Creates a menu item and invokes the static function following it, when the menu item is selected. - public MenuItem(string itemName, bool isValidateFunction) : this(itemName, isValidateFunction, itemName.StartsWith("GameObject/Create Other") ? 10 : 1000) {} - // The special treatment of "GameObject/Other" is to ensure that legacy scripts that don't set a priority don't create a - // "Create Other" menu at the very bottom of the GameObject menu (thus preventing the items from being propagated to the - // scene hierarchy dropdown and context menu). - - // Creates a menu item and invokes the static function following it, when the menu item is selected. - public MenuItem(string itemName, bool isValidateFunction, int priority) : this(itemName, isValidateFunction, priority, false) {} - - // Creates a menu item and invokes the static function following it, when the menu item is selected. - internal MenuItem(string itemName, bool isValidateFunction, int priority, bool internalMenu) - { - if (internalMenu) - menuItem = "internal:" + itemName; - else - menuItem = itemName; - validate = isValidateFunction; - this.priority = priority; - } - - public string menuItem; - public bool validate; - public int priority; - } -} diff --git a/Editor/Mono/Modules/DefaultBuildPostprocessor.cs b/Editor/Mono/Modules/DefaultBuildPostprocessor.cs deleted file mode 100644 index 06821179d2..0000000000 --- a/Editor/Mono/Modules/DefaultBuildPostprocessor.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -using UnityEngine; - -namespace UnityEditor.Modules -{ - internal class DefaultBuildProperties : BuildProperties - { - public override DeploymentTargetRequirements GetTargetRequirements() { return null; } - } - - internal abstract class DefaultBuildPostprocessor - : IBuildPostprocessor - { - public virtual void LaunchPlayer(BuildLaunchPlayerArgs args) - { - throw new NotSupportedException(); - } - - // Supports legacy interface before BuildProperties was introduced - public virtual void PostProcess(BuildPostProcessArgs args) - { - } - - public virtual void PostProcess(BuildPostProcessArgs args, out BuildProperties outProperties) - { - PostProcess(args); - - // NOTE: For some reason, calling PostProcess seems like it can trigger this object to be GC'd - // so create is just before returning - outProperties = ScriptableObject.CreateInstance(); - } - - public virtual bool SupportsInstallInBuildFolder() - { - return false; - } - - public virtual bool SupportsLz4Compression() - { - return false; - } - - public virtual bool SupportsScriptsOnlyBuild() - { - return true; - } - - public virtual string PrepareForBuild(BuildOptions options, BuildTarget target) - { - return null; - } - - public virtual void UpdateBootConfig(BuildTarget target, BootConfigData config, BuildOptions options) - { - config.Set("wait-for-native-debugger", "0"); - if (config.Get("player-connection-debug") == "1") - { - if (EditorUserBuildSettings.GetPlatformSettings(BuildPipeline.GetBuildTargetName(target), - BuildPlayerWindow.kSettingDebuggingWaitForManagedDebugger) == "true") - { - config.Set("wait-for-managed-debugger", "1"); - } - else - { - config.Set("wait-for-managed-debugger", "0"); - } - } - } - - public virtual string GetExtension(BuildTarget target, BuildOptions options) - { - return string.Empty; - } - } -} diff --git a/Editor/Mono/Modules/DefaultBuildWindowExtension.cs b/Editor/Mono/Modules/DefaultBuildWindowExtension.cs deleted file mode 100644 index 83e9a93a3c..0000000000 --- a/Editor/Mono/Modules/DefaultBuildWindowExtension.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor.Modules -{ - internal class DefaultBuildWindowExtension : IBuildWindowExtension - { - public virtual void ShowPlatformBuildOptions() {} - public virtual void ShowPlatformBuildWarnings() {} - public virtual void ShowInternalPlatformBuildOptions() {} - public virtual bool EnabledBuildButton() { return true; } - public virtual bool EnabledBuildAndRunButton() { return true; } - public virtual void GetBuildButtonTitles(out GUIContent buildButtonTitle, out GUIContent buildAndRunButtonTitle) - { - buildButtonTitle = null; - buildAndRunButtonTitle = null; - } - - public virtual bool ShouldDrawScriptDebuggingCheckbox() { return true; } - public virtual bool ShouldDrawProfilerCheckbox() { return true; } - public virtual bool ShouldDrawDevelopmentPlayerCheckbox() { return true; } - public virtual bool ShouldDrawExplicitNullCheckbox() { return false; } - public virtual bool ShouldDrawExplicitDivideByZeroCheckbox() { return false; } - public virtual bool ShouldDrawExplicitArrayBoundsCheckbox() { return false; } - public virtual bool ShouldDrawForceOptimizeScriptsCheckbox() { return false; } - } -} diff --git a/Editor/Mono/Modules/DefaultCompilationExtension.cs b/Editor/Mono/Modules/DefaultCompilationExtension.cs deleted file mode 100644 index 5d1853c0fc..0000000000 --- a/Editor/Mono/Modules/DefaultCompilationExtension.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using Mono.Cecil; - -namespace UnityEditor.Modules -{ - internal class DefaultCompilationExtension - : ICompilationExtension - { - public virtual CSharpCompiler GetCsCompiler(bool buildingForEditor, string assemblyName) - { - return CSharpCompiler.Mono; - } - - public virtual string[] GetCompilerExtraAssemblyPaths(bool isEditor, string assemblyPathName) - { - return new string[] {}; - } - - public virtual IAssemblyResolver GetAssemblyResolver(bool buildingForEditor, string assemblyPath, string[] searchDirectories) - { - return null; - } - - public virtual IEnumerable GetWindowsMetadataReferences() - { - return new string[0]; - } - - public virtual IEnumerable GetAdditionalAssemblyReferences() - { - return new string[0]; - } - - public virtual IEnumerable GetAdditionalDefines() - { - return new string[0]; - } - - public virtual IEnumerable GetAdditionalSourceFiles() - { - return new string[0]; - } - } -} diff --git a/Editor/Mono/Modules/DefaultPlatformSupportModule.cs b/Editor/Mono/Modules/DefaultPlatformSupportModule.cs deleted file mode 100644 index 31b863a2f0..0000000000 --- a/Editor/Mono/Modules/DefaultPlatformSupportModule.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor.DeploymentTargets; - -namespace UnityEditor.Modules -{ - internal abstract class DefaultPlatformSupportModule : IPlatformSupportModule - { - protected ICompilationExtension compilationExtension; - - protected ITextureImportSettingsExtension textureSettingsExtension; - - public abstract string TargetName { get; } - - public abstract string JamTarget { get; } - - public virtual string ExtensionVersion { get { return null; } } - - public virtual GUIContent[] GetDisplayNames() { return null; } - - public virtual string[] NativeLibraries { get { return new string[0]; } } - - public virtual string[] AssemblyReferencesForUserScripts { get { return new string[0]; } } - - public virtual string[] AssemblyReferencesForEditorCsharpProject { get { return new string[0]; } } - - public virtual IBuildAnalyzer CreateBuildAnalyzer() { return null; } - - public abstract IBuildPostprocessor CreateBuildPostprocessor(); - - public virtual IScriptingImplementations CreateScriptingImplementations() { return null; } - - public virtual ISettingEditorExtension CreateSettingsEditorExtension() { return null; } - - public virtual IPreferenceWindowExtension CreatePreferenceWindowExtension() { return null; } - - public virtual ITextureImportSettingsExtension CreateTextureImportSettingsExtension() { return textureSettingsExtension != null ? textureSettingsExtension : textureSettingsExtension = new DefaultTextureImportSettingsExtension(); } - - public virtual IBuildWindowExtension CreateBuildWindowExtension() { return null; } - - public virtual ICompilationExtension CreateCompilationExtension() { return compilationExtension != null ? compilationExtension : compilationExtension = new DefaultCompilationExtension(); } - - public virtual IPluginImporterExtension CreatePluginImporterExtension() { return null; } - - public virtual IUserAssembliesValidator CreateUserAssembliesValidatorExtension() { return null; } - - public virtual IProjectGeneratorExtension CreateProjectGeneratorExtension() { return null; } - - public virtual IDeploymentTargetsExtension CreateDeploymentTargetsExtension() { return null; } - - public virtual void RegisterAdditionalUnityExtensions() {} - - public virtual IDevice CreateDevice(string id) { throw new NotSupportedException(); } - - public virtual void OnActivate() {} - - public virtual void OnDeactivate() {} - - public virtual void OnLoad() {} - - public virtual void OnUnload() {} - } -} diff --git a/Editor/Mono/Modules/DefaultPlayerSettingsEditorExtension.cs b/Editor/Mono/Modules/DefaultPlayerSettingsEditorExtension.cs deleted file mode 100644 index 8d2c0e9477..0000000000 --- a/Editor/Mono/Modules/DefaultPlayerSettingsEditorExtension.cs +++ /dev/null @@ -1,125 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Linq; - -namespace UnityEditor.Modules -{ - internal abstract class DefaultPlayerSettingsEditorExtension : ISettingEditorExtension - { - protected PlayerSettingsEditor m_playerSettingsEditor; - - protected PlayerSettingsEditor playerSettingsEditor - { - get { return m_playerSettingsEditor; } - } - - public virtual void OnEnable(PlayerSettingsEditor settingsEditor) - { - m_playerSettingsEditor = settingsEditor; - - m_MTRendering = playerSettingsEditor.FindPropertyAssert("m_MTRendering"); - } - - public virtual bool HasPublishSection() - { - return true; - } - - public virtual void PublishSectionGUI(float h, float midWidth, float maxWidth) {} - - public virtual bool HasIdentificationGUI() - { - return false; - } - - public virtual void IdentificationSectionGUI() {} - - public virtual void ConfigurationSectionGUI() {} - - public virtual bool SupportsOrientation() - { - return false; - } - - public virtual bool CanShowUnitySplashScreen() - { - return false; - } - - public virtual void SplashSectionGUI() {} - - public virtual bool UsesStandardIcons() - { - return true; - } - - public virtual void IconSectionGUI() {} - - public virtual bool HasResolutionSection() - { - return false; - } - - public virtual bool SupportsStaticBatching() - { - return true; - } - - public virtual bool SupportsDynamicBatching() - { - return true; - } - - public virtual void ResolutionSectionGUI(float h, float midWidth, float maxWidth) {} - - public virtual bool HasBundleIdentifier() - { - return true; - } - - public virtual bool SupportsHighDynamicRangeDisplays() - { - return false; - } - - public virtual bool SupportsGfxJobModes() - { - return false; - } - - public virtual bool SupportsMultithreadedRendering() - { - return false; - } - - protected SerializedProperty m_MTRendering; - private static readonly GUIContent m_MTRenderingTooltip = EditorGUIUtility.TrTextContent("Multithreaded Rendering*"); - - protected virtual GUIContent MultithreadedRenderingGUITooltip() - { - return m_MTRenderingTooltip; - } - - public virtual void MultithreadedRenderingGUI(BuildTargetGroup targetGroup) - { - if (playerSettingsEditor.IsMobileTarget(targetGroup)) - { - bool oldValue = PlayerSettings.GetMobileMTRendering(targetGroup); - bool newValue = EditorGUILayout.Toggle(MultithreadedRenderingGUITooltip(), oldValue); - if (oldValue != newValue) - PlayerSettings.SetMobileMTRendering(targetGroup, newValue); - } - else EditorGUILayout.PropertyField(m_MTRendering, m_MTRenderingTooltip); - } - - public virtual bool SupportsCustomLightmapEncoding() - { - return false; - } - } -} diff --git a/Editor/Mono/Modules/DefaultPluginImporterExtension.cs b/Editor/Mono/Modules/DefaultPluginImporterExtension.cs deleted file mode 100644 index 4e27dd1fb8..0000000000 --- a/Editor/Mono/Modules/DefaultPluginImporterExtension.cs +++ /dev/null @@ -1,218 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.ComponentModel; -using System.Text; -using UnityEngine; -using System.Linq; -using System.IO; -using System.Collections.Generic; - -namespace UnityEditor.Modules -{ - internal class DefaultPluginImporterExtension : IPluginImporterExtension - { - protected bool hasModified = false; - protected Property[] properties = null; - - internal class Property - { - internal GUIContent name { get; set; } - internal string key { get; set; } - internal object defaultValue { get; set; } - internal Type type { get; set; } - internal string platformName { get; set; } - internal object value { get; set; } - - internal Property(string name, string key, object defaultValue, string platformName) - : this(new GUIContent(name), key, defaultValue, platformName) - { - } - - internal Property(GUIContent name, string key, object defaultValue, string platformName) - { - this.name = name; - this.key = key; - this.defaultValue = defaultValue; - this.type = defaultValue.GetType(); - this.platformName = platformName; - } - - internal virtual void Reset(PluginImporterInspector inspector) - { - string valueString = inspector.importer.GetPlatformData(platformName, key); - ParseStringValue(inspector, valueString); - } - - protected void ParseStringValue(PluginImporterInspector inspector, string valueString, bool muteWarnings = false) - { - try - { - value = TypeDescriptor.GetConverter(type).ConvertFromString(valueString); - } - catch - { - value = defaultValue; - - if (!muteWarnings && !string.IsNullOrEmpty(valueString)) - { - // We mute warnings for properties that are on disabled platforms to avoid unnecessary spam for deprecated values, case 909247 - if (inspector.importer.GetCompatibleWithPlatform(platformName)) - Debug.LogWarning("Failed to parse value ('" + valueString + "') for " + key + ", platform: " + platformName + ", type: " + type + ". Default value will be set '" + defaultValue + "'"); - } - } - } - - internal virtual void Apply(PluginImporterInspector inspector) - { - string valueString = type == typeof(bool) ? value.ToString().ToLower() : value.ToString(); - inspector.importer.SetPlatformData(platformName, key, valueString); - } - - internal virtual void OnGUI(PluginImporterInspector inspector) - { - if (type == typeof(bool)) value = EditorGUILayout.Toggle(name, (bool)value); - else if (type.IsEnum) value = EditorGUILayout.EnumPopup(name, (Enum)value); - else if (type == typeof(string)) value = EditorGUILayout.TextField(name, (string)value); - else throw new NotImplementedException("Don't know how to display value."); - } - } - - internal bool propertiesRefreshed = false; - - public DefaultPluginImporterExtension(Property[] properties) - { - this.properties = properties; - } - - public virtual void ResetValues(PluginImporterInspector inspector) - { - hasModified = false; - RefreshProperties(inspector); - } - - public virtual bool HasModified(PluginImporterInspector inspector) - { - return hasModified; - } - - public virtual void Apply(PluginImporterInspector inspector) - { - if (!propertiesRefreshed) return; - - foreach (var p in properties) - { - p.Apply(inspector); - } - } - - public virtual void OnEnable(PluginImporterInspector inspector) - { - RefreshProperties(inspector); - } - - public virtual void OnDisable(PluginImporterInspector inspector) - { - } - - public virtual void OnPlatformSettingsGUI(PluginImporterInspector inspector) - { - if (!propertiesRefreshed) RefreshProperties(inspector); - - EditorGUI.BeginChangeCheck(); - foreach (var p in properties) - { - p.OnGUI(inspector); - } - if (EditorGUI.EndChangeCheck()) hasModified = true; - } - - protected virtual void RefreshProperties(PluginImporterInspector inspector) - { - foreach (var p in properties) - { - p.Reset(inspector); - } - propertiesRefreshed = true; - } - - public virtual string CalculateFinalPluginPath(string platformName, PluginImporter imp) - { - string cpu = imp.GetPlatformData(platformName, "CPU"); - - if (!string.IsNullOrEmpty(cpu) && (string.Compare(cpu, "AnyCPU", true) != 0) && (string.Compare(cpu, "None", true) != 0)) - return Path.Combine(cpu, Path.GetFileName(imp.assetPath)); - - return Path.GetFileName(imp.assetPath); - } - - protected Dictionary> GetCompatiblePlugins(string buildTargetName) - { - IEnumerable plugins = PluginImporter.GetAllImporters().Where(imp => imp.GetCompatibleWithPlatformOrAnyPlatformBuildTarget(buildTargetName)); - Dictionary> matchingPlugins = new Dictionary>(); - - foreach (var plugin in plugins) - { - string finalPluginPath = CalculateFinalPluginPath(buildTargetName, plugin); - if (string.IsNullOrEmpty(finalPluginPath)) - continue; - - List temp = null; - if (matchingPlugins.TryGetValue(finalPluginPath, out temp) == false) - { - temp = new List(); - matchingPlugins[finalPluginPath] = temp; - } - temp.Add(plugin); - } - return matchingPlugins; - } - - public virtual bool CheckFileCollisions(string buildTargetName) - { - Dictionary> matchingPlugins = GetCompatiblePlugins(buildTargetName); - - bool foundCollisions = false; - - StringBuilder errorMessage = new StringBuilder(); - foreach (KeyValuePair> pair in matchingPlugins) - { - List plugins = pair.Value; - // If we have only one plugin with specified final path, that means everything is ok, and no overwrite will occur - if (plugins.Count == 1) continue; - - // Project plugins are those found inside of the User's project folder. - int projectPluginCount = 0; - foreach (PluginImporter importer in plugins) - { - if (!importer.GetIsOverridable()) - { - projectPluginCount++; - } - } - - // If we have a single user project plugin, it will take precedence and overwrite the others. - // Anything else should throw errors if there are multiple. - if (projectPluginCount == 1) - continue; - - foundCollisions = true; - // Two or more plugins are being copied to the same path, create an error message - errorMessage.AppendLine(string.Format("Plugin '{0}' is used from several locations:", Path.GetFileName(pair.Key))); - foreach (PluginImporter importer in plugins) - { - errorMessage.AppendLine(" " + importer.assetPath + " would be copied to /" + pair.Key.Replace("\\", "/")); - } - } - if (foundCollisions) - { - errorMessage.AppendLine("Please fix plugin settings and try again."); - Debug.LogError(errorMessage.ToString()); - } - - return foundCollisions; - } - } -} diff --git a/Editor/Mono/Modules/DefaultProjectGeneratorExtension.cs b/Editor/Mono/Modules/DefaultProjectGeneratorExtension.cs deleted file mode 100644 index 84400deba8..0000000000 --- a/Editor/Mono/Modules/DefaultProjectGeneratorExtension.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; - -namespace UnityEditor.Modules -{ - internal abstract class DefaultProjectGeneratorExtension : IProjectGeneratorExtension - { - public virtual void GenerateCSharpProject(CSharpProject project, string assemblyName, IEnumerable sourceFiles, IEnumerable defines, IEnumerable additionalProjectReferences) - { - } - } -} diff --git a/Editor/Mono/Modules/DefaultTextureImportSettingsExtension.cs b/Editor/Mono/Modules/DefaultTextureImportSettingsExtension.cs deleted file mode 100644 index 0b01f6d467..0000000000 --- a/Editor/Mono/Modules/DefaultTextureImportSettingsExtension.cs +++ /dev/null @@ -1,297 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEditor.Modules; -using UnityEngine; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System; - -namespace UnityEditor.Modules -{ - //everything happening here in this default extension used to happen in TextureImporterInspector. - //now, platforms that want to have their own texture import settings can subclass this class, - //and put the platform-specific stuff (either new, or down below) into the new subclass. - internal class DefaultTextureImportSettingsExtension : ITextureImportSettingsExtension - { - static readonly string[] kMaxTextureSizeStrings = { "32", "64", "128", "256", "512", "1024", "2048", "4096", "8192" }; - static readonly int[] kMaxTextureSizeValues = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; - static readonly GUIContent maxSize = EditorGUIUtility.TrTextContent("Max Size", "Textures larger than this will be scaled down."); - - static readonly string[] kResizeAlgorithmStrings = { "Mitchell", "Bilinear" }; - static readonly int[] kResizeAlgorithmValues = { (int)TextureResizeAlgorithm.Mitchell, (int)TextureResizeAlgorithm.Bilinear }; - static readonly GUIContent resizeAlgorithm = EditorGUIUtility.TrTextContent("Resize Algorithm", "Select algorithm to apply for textures when scaled down."); - - static readonly GUIContent kTextureCompression = EditorGUIUtility.TrTextContent("Compression", "How will this texture be compressed?"); - static readonly GUIContent[] kTextureCompressionOptions = - { - EditorGUIUtility.TrTextContent("None", "Texture is not compressed."), - EditorGUIUtility.TrTextContent("Low Quality", "Texture compressed with low quality but high performance, high compression format."), - EditorGUIUtility.TrTextContent("Normal Quality", "Texture is compressed with a standard format."), - EditorGUIUtility.TrTextContent("High Quality", "Texture compressed with a high quality format."), - }; - static readonly int[] kTextureCompressionValues = - { - (int)TextureImporterCompression.Uncompressed, - (int)TextureImporterCompression.CompressedLQ, - (int)TextureImporterCompression.Compressed, - (int)TextureImporterCompression.CompressedHQ - }; - - public virtual void ShowImportSettings(Editor baseEditor, TextureImportPlatformSettings platformSettings) - { - TextureImporterInspector editor = baseEditor as TextureImporterInspector; - - // Max texture size - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = platformSettings.overriddenIsDifferent || platformSettings.maxTextureSizeIsDifferent; - int maxTextureSize = EditorGUILayout.IntPopup(maxSize.text, platformSettings.maxTextureSize, kMaxTextureSizeStrings, kMaxTextureSizeValues); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - platformSettings.SetMaxTextureSizeForAll(maxTextureSize); - } - - // Resize Algorithm - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = platformSettings.overriddenIsDifferent || platformSettings.resizeAlgorithmIsDifferent; - int resizeAlgorithmVal = EditorGUILayout.IntPopup(resizeAlgorithm.text, (int)platformSettings.resizeAlgorithm, kResizeAlgorithmStrings, kResizeAlgorithmValues); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - platformSettings.SetResizeAlgorithmForAll((TextureResizeAlgorithm)resizeAlgorithmVal); - } - - // Texture Compression - using (new EditorGUI.DisabledScope(platformSettings.overridden && !platformSettings.isDefault)) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = platformSettings.overriddenIsDifferent || platformSettings.textureCompressionIsDifferent || (platformSettings.overridden && !platformSettings.isDefault); - TextureImporterCompression textureCompression = (TextureImporterCompression)EditorGUILayout.IntPopup(kTextureCompression, (int)platformSettings.textureCompression, kTextureCompressionOptions, kTextureCompressionValues); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - platformSettings.SetTextureCompressionForAll(textureCompression); - } - } - - // Texture format - int[] formatValuesForAll = null; - string[] formatStringsForAll = null; - bool formatOptionsAreDifferent = false; - - int formatForAll = 0; - - - for (int i = 0; i < editor.targets.Length; i++) - { - TextureImporter imp = editor.targets[i] as TextureImporter; - TextureImporterSettings settings = platformSettings.GetSettings(imp); - TextureImporterType textureTypeForThis = editor.textureTypeHasMultipleDifferentValues ? settings.textureType : editor.textureType; - int format = (int)platformSettings.format; - - int[] formatValues = null; - string[] formatStrings = null; - - if (platformSettings.isDefault) - { - format = (int)TextureImporterFormat.Automatic; - formatValues = new int[] { (int)TextureImporterFormat.Automatic }; - formatStrings = new string[] { "Auto" }; - } - else - { - // If not overriden, show what the auto format is going to be - if (!platformSettings.overridden) - { - format = (int)TextureImporter.FormatFromTextureParameters(settings, - platformSettings.platformTextureSettings, - editor.assetTarget && imp.DoesSourceTextureHaveAlpha(), - editor.assetTarget && imp.IsSourceTextureHDR(), - platformSettings.m_Target); - - formatValues = new int[] { format }; - formatStrings = new string[] { TextureUtil.GetTextureFormatString((TextureFormat)format) }; - } - // else show the format choice filtered by platform. - else - { - // Single channel format is the same for all platform at the moment - if (textureTypeForThis == TextureImporterType.Cookie || textureTypeForThis == TextureImporterType.SingleChannel) - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueSingleChannel; - formatStrings = TextureImporterInspector.s_TextureFormatStringsSingleChannel; - } - else - { - // on gles targets we use rgb normal maps so no need to split formats - if (TextureImporterInspector.IsGLESMobileTargetPlatform(platformSettings.m_Target)) - { - if (platformSettings.m_Target == BuildTarget.iOS || platformSettings.m_Target == BuildTarget.tvOS) - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueApplePVR; - formatStrings = TextureImporterInspector.s_TextureFormatStringsApplePVR; - } - else - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueAndroid; - formatStrings = TextureImporterInspector.s_TextureFormatStringsAndroid; - } - } - else if (textureTypeForThis == TextureImporterType.NormalMap) - { - formatValues = TextureImportPlatformSettings.kNormalFormatsValueDefault; - formatStrings = TextureImporterInspector.s_NormalFormatStringsDefault; - } - else - { - if (platformSettings.m_Target == BuildTarget.WebGL) - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueWebGL; - formatStrings = TextureImporterInspector.s_TextureFormatStringsWebGL; - } - else if (platformSettings.m_Target == BuildTarget.PSP2) - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValuePSP2; - formatStrings = TextureImporterInspector.s_TextureFormatStringsPSP2; - } - else if (platformSettings.m_Target == BuildTarget.Switch) - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueSwitch; - formatStrings = TextureImporterInspector.s_TextureFormatStringsSwitch; - } - else - { - formatValues = TextureImportPlatformSettings.kTextureFormatsValueDefault; - formatStrings = TextureImporterInspector.s_TextureFormatStringsDefault; - } - } - } - } - } - - // Check if values are the same - if (i == 0) - { - formatValuesForAll = formatValues; - formatStringsForAll = formatStrings; - formatForAll = format; - } - else - { - if (!formatValues.SequenceEqual(formatValuesForAll) || !formatStrings.SequenceEqual(formatStringsForAll)) - { - formatOptionsAreDifferent = true; - break; - } - } - } - - using (new EditorGUI.DisabledScope(formatOptionsAreDifferent || formatStringsForAll.Length == 1)) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = formatOptionsAreDifferent || platformSettings.textureFormatIsDifferent; - formatForAll = EditorGUILayout.IntPopup(TextureImporterInspector.s_Styles.textureFormat, formatForAll, EditorGUIUtility.TempContent(formatStringsForAll), formatValuesForAll); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - platformSettings.SetTextureFormatForAll((TextureImporterFormat)formatForAll); - } - - // In case the platform is overriden, the chosen format can become invalid when changing texture type (example: Switching from "Default" overridden with RGBAHalf to "Single Channel" where only Alpha8 is available) - if (Array.IndexOf(formatValuesForAll, formatForAll) == -1) - { - platformSettings.SetTextureFormatForAll((TextureImporterFormat)formatValuesForAll[0]); - } - } - - if (platformSettings.isDefault && platformSettings.textureCompression != TextureImporterCompression.Uncompressed) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = platformSettings.overriddenIsDifferent || platformSettings.crunchedCompressionIsDifferent; - bool crunchedCompression = EditorGUILayout.Toggle(TextureImporterInspector.s_Styles.crunchedCompression, platformSettings.crunchedCompression); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - platformSettings.SetCrunchedCompressionForAll(crunchedCompression); - } - } - - // compression quality - bool isCrunchedFormat = false - || (TextureImporterFormat)formatForAll == TextureImporterFormat.DXT1Crunched - || (TextureImporterFormat)formatForAll == TextureImporterFormat.DXT5Crunched - || (TextureImporterFormat)formatForAll == TextureImporterFormat.ETC_RGB4Crunched - || (TextureImporterFormat)formatForAll == TextureImporterFormat.ETC2_RGBA8Crunched - ; - - if ( - (platformSettings.isDefault && platformSettings.textureCompression != TextureImporterCompression.Uncompressed && platformSettings.crunchedCompression) || - (!platformSettings.isDefault && isCrunchedFormat) || - (!platformSettings.textureFormatIsDifferent && ArrayUtility.Contains(TextureImporterInspector.kFormatsWithCompressionSettings, (TextureImporterFormat)formatForAll))) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = platformSettings.overriddenIsDifferent || platformSettings.compressionQualityIsDifferent; - int compressionQuality = EditCompressionQuality(platformSettings.m_Target, platformSettings.compressionQuality, isCrunchedFormat); - EditorGUI.showMixedValue = false; - if (EditorGUI.EndChangeCheck()) - { - platformSettings.SetCompressionQualityForAll(compressionQuality); - //SyncPlatformSettings (); - } - } - - // show the ETC1 split option only for sprites on platforms supporting ETC. - bool isETCPlatform = TextureImporter.IsETC1SupportedByBuildTarget(BuildPipeline.GetBuildTargetByName(platformSettings.name)); - bool isDealingWithSprite = (editor.spriteImportMode != SpriteImportMode.None); - bool isETCFormatSelected = TextureImporter.IsTextureFormatETC1Compression((TextureFormat)formatForAll); - if (isETCPlatform && isDealingWithSprite && isETCFormatSelected) - { - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = platformSettings.overriddenIsDifferent || platformSettings.allowsAlphaSplitIsDifferent; - bool allowsAlphaSplit = GUILayout.Toggle(platformSettings.allowsAlphaSplitting, TextureImporterInspector.s_Styles.etc1Compression); - if (EditorGUI.EndChangeCheck()) - { - platformSettings.SetAllowsAlphaSplitForAll(allowsAlphaSplit); - } - } - } - - private int EditCompressionQuality(BuildTarget target, int compression, bool isCrunchedFormat) - { - bool showAsEnum = !isCrunchedFormat && ( - target == BuildTarget.iOS || - target == BuildTarget.tvOS || - target == BuildTarget.Android || - target == BuildTarget.Tizen - ); - - if (showAsEnum) - { - int compressionMode = 1; - if (compression == (int)TextureCompressionQuality.Fast) - compressionMode = 0; - else if (compression == (int)TextureCompressionQuality.Best) - compressionMode = 2; - - int ret = EditorGUILayout.Popup(TextureImporterInspector.s_Styles.compressionQuality, compressionMode, TextureImporterInspector.s_Styles.mobileCompressionQualityOptions); - - switch (ret) - { - case 0: return (int)TextureCompressionQuality.Fast; - case 1: return (int)TextureCompressionQuality.Normal; - case 2: return (int)TextureCompressionQuality.Best; - - default: return (int)TextureCompressionQuality.Normal; - } - } - else - compression = EditorGUILayout.IntSlider(TextureImporterInspector.s_Styles.compressionQualitySlider, compression, 0, 100); - - return compression; - } - } -} diff --git a/Editor/Mono/Modules/ModuleManager.cs b/Editor/Mono/Modules/ModuleManager.cs deleted file mode 100644 index 1e430f88a3..0000000000 --- a/Editor/Mono/Modules/ModuleManager.cs +++ /dev/null @@ -1,850 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Collections.Generic; -using System.Text; -using UnityEditor; -using UnityEditor.Hardware; -using UnityEditorInternal; -using UnityEngine; -using Unity.DataContract; -using UnityEditor.Callbacks; -using UnityEditor.Utils; -using UnityEditor.DeploymentTargets; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; - -namespace UnityEditor.Modules -{ - internal static class ModuleManager - { - [NonSerialized] - static List s_PlatformModules; - - [NonSerialized] - static bool s_PlatformModulesInitialized; - - [NonSerialized] - static List s_EditorModules; - - [NonSerialized] - static IPackageManagerModule s_PackageManager; - - [NonSerialized] - static IPlatformSupportModule s_ActivePlatformModule; - - internal static bool EnableLogging - { - get - { - return (bool)(Debug.GetDiagnosticSwitch("ModuleManagerLogging") ?? false); - } - } - - internal static IPackageManagerModule packageManager - { - get - { - InitializeModuleManager(); - return s_PackageManager; - } - } - - internal static IEnumerable platformSupportModules - { - get - { - InitializeModuleManager(); - if (s_PlatformModules == null) - RegisterPlatformSupportModules(); - return s_PlatformModules; - } - } - - // Accesses the list of currently known platformSupportModules without forcing platform - // support module registration. Use this API from all code which may run during the initial - // domain reloading phase instead of accessing platformSupportModules. Platform support - // modules will be registered automatically when it is safe to do so. - internal static IEnumerable platformSupportModulesDontRegister - { - get - { - if (s_PlatformModules == null) - return new List(); - return s_PlatformModules; - } - } - - static List editorModules - { - get - { - if (s_EditorModules == null) - return new List(); - return s_EditorModules; - } - } - - - class BuildTargetChangedHandler : Build.IActiveBuildTargetChanged - { - public int callbackOrder { get { return 0; } } - - public void OnActiveBuildTargetChanged(BuildTarget oldTarget, BuildTarget newTarget) - { - ModuleManager.OnActiveBuildTargetChanged(oldTarget, newTarget); - } - } - - static void OnActiveBuildTargetChanged(BuildTarget oldTarget, BuildTarget newTarget) - { - string target = GetTargetStringFromBuildTarget(newTarget); - ChangeActivePlatformModuleTo(target); - } - - static void DeactivateActivePlatformModule() - { - if (s_ActivePlatformModule != null) - { - s_ActivePlatformModule.OnDeactivate(); - s_ActivePlatformModule = null; - } - } - - static void ChangeActivePlatformModuleTo(string target) - { - DeactivateActivePlatformModule(); - - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - { - s_ActivePlatformModule = module; - module.OnActivate(); - return; - } - } - - // There are still some unmodularized platforms, so we can't throw yet - //throw new ApplicationException("Couldn't find platform module for target: " + target); - } - - internal static bool IsRegisteredModule(string file) - { - return (s_PackageManager != null && s_PackageManager.GetType().Assembly.Location.NormalizePath() == file.NormalizePath()); - } - - // entry point from native - [RequiredByNativeCode] - internal static bool IsPlatformSupportLoaded(string target) - { - foreach (var module in platformSupportModules) - if (module.TargetName == target) - return true; - - return false; - } - - // entry point from native - [RequiredByNativeCode] - internal static void RegisterAdditionalUnityExtensions() - { - foreach (var module in platformSupportModules) - { - module.RegisterAdditionalUnityExtensions(); - } - } - - // entry point from native - [RequiredByNativeCode] - internal static void InitializeModuleManager() - { - if (s_PackageManager == null) - { - RegisterPackageManager(); - if (s_PackageManager != null) - LoadUnityExtensions(); - else - Debug.LogError("Failed to load package manager"); - } - } - - static string CombinePaths(params string[] paths) - { - if (null == paths) - throw new ArgumentNullException("paths"); - if (1 == paths.Length) - return paths[0]; - - StringBuilder builder = new StringBuilder(paths[0]); - for (int i = 1; i < paths.Length; ++i) - builder.AppendFormat("{0}{1}", "/", paths[i]); - return builder.ToString(); - } - - private static void LoadUnityExtensions() - { - foreach (Unity.DataContract.PackageInfo extension in s_PackageManager.unityExtensions) - { - if (EnableLogging) - Console.WriteLine("Setting {0} v{1} for Unity v{2} to {3}", extension.name, extension.version, extension.unityVersion, extension.basePath); - foreach (var file in extension.files.Where(f => f.Value.type == PackageFileType.Dll)) - { - string fullPath = Paths.NormalizePath(Path.Combine(extension.basePath, file.Key)); - if (!File.Exists(fullPath)) - Debug.LogWarningFormat("Missing assembly \t{0} for {1}. Extension support may be incomplete.", file.Key, extension.name); - else - { - bool isExtension = !String.IsNullOrEmpty(file.Value.guid); - if (EnableLogging) - Console.WriteLine(" {0} ({1}) GUID: {2}", - file.Key, - isExtension ? "Extension" : "Custom", - file.Value.guid); - if (isExtension) - InternalEditorUtility.RegisterExtensionDll(fullPath.Replace('\\', '/'), file.Value.guid); - else - InternalEditorUtility.RegisterPrecompiledAssembly(Path.GetFileName(fullPath), fullPath); - } - } - s_PackageManager.LoadPackage(extension); - } - } - - // entry point from native - // Note that in order for this function to work properly, it must be called between two domain - // reloads. The first domain reload is needed because RegisterPlatformSupportModules() - // investigates the currently loaded set of assemblies. The second reload is needed so that - // assemblies returned by module.AssemblyReferencesForUserScripts are actually loaded in the - // current domain and user code may use it. - [RequiredByNativeCode] - internal static void InitializePlatformSupportModules() - { - if (s_PlatformModulesInitialized) - { - Console.WriteLine("Platform modules already initialized, skipping"); - return; - } - - InitializeModuleManager(); - RegisterPlatformSupportModules(); - - foreach (var module in platformSupportModules) - { - foreach (var library in module.NativeLibraries) - EditorUtility.LoadPlatformSupportNativeLibrary(library); - foreach (var fullPath in module.AssemblyReferencesForUserScripts) - InternalEditorUtility.RegisterPrecompiledAssembly(Path.GetFileName(fullPath), fullPath); - - EditorUtility.LoadPlatformSupportModuleNativeDllInternal(module.TargetName); - - module.OnLoad(); - } - - // Setup active build target and call OnActivate() for current platform module - OnActiveBuildTargetChanged(BuildTarget.NoTarget, EditorUserBuildSettings.activeBuildTarget); - - s_PlatformModulesInitialized = true; - } - - // entry point from native - [RequiredByNativeCode] - internal static void ShutdownPlatformSupportModules() - { - DeactivateActivePlatformModule(); - - if (s_PlatformModules != null) - { - foreach (var module in s_PlatformModules) - module.OnUnload(); - } - } - - // entry point from native - [RequiredByNativeCode(true)] - internal static void ShutdownModuleManager() - { - if (s_PackageManager != null) - s_PackageManager.Shutdown(true); - - s_PackageManager = null; - s_PlatformModules = null; - s_EditorModules = null; - } - - static void RegisterPackageManager() - { - s_EditorModules = new List(); // TODO: no editor modules support for now, so just cache this - - // if this is a domain reload after unity is already running, then package manager should already be loaded from - // the native land, so we don't go looking for it again and just use the assembly already loaded - try - { - Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => null != a.GetType("Unity.PackageManager.PackageManager")); - if (assembly != null) - { - if (InitializePackageManager(assembly, null)) - return; - } - } - catch (Exception ex) - { - Console.WriteLine("Error enumerating assemblies looking for package manager. {0}", ex); - } - - - // check if locator assembly is in the domain (it should be loaded along with UnityEditor/UnityEngine at this point) - Type locatorType = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.GetName().Name == "Unity.Locator").Select(a => a.GetType("Unity.PackageManager.Locator")).FirstOrDefault(); - try - { - string playbackEngineFolders = FileUtil.CombinePaths(Directory.GetParent(EditorApplication.applicationPath).ToString(), "PlaybackEngines"); - locatorType.InvokeMember("Scan", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, - new object[] { - new string[] { - FileUtil.NiceWinPath(EditorApplication.applicationContentsPath), - FileUtil.NiceWinPath(playbackEngineFolders) - }, - Application.unityVersion - }); - } - catch (Exception ex) - { - Console.WriteLine("Error scanning for packages. {0}", ex); - return; - } - - Unity.DataContract.PackageInfo package; - // get the package manager package - try - { - package = locatorType.InvokeMember("GetPackageManager", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, new[] { Application.unityVersion }) as Unity.DataContract.PackageInfo; - if (package == null) - { - Console.WriteLine("No package manager found!"); - return; - } - } - catch (Exception ex) - { - Console.WriteLine("Error scanning for packages. {0}", ex); - return; - } - - try - { - InitializePackageManager(package); - } - catch (Exception ex) - { - Console.WriteLine("Error initializing package manager. {0}", ex); - } - - - // this will only happen when unity first starts up - if (s_PackageManager != null) - s_PackageManager.CheckForUpdates(); - } - - // instantiate package manager and add it to the native assembly list for automatic loading at domain reloads (play mode start, etc) - static bool InitializePackageManager(Unity.DataContract.PackageInfo package) - { - string dll = package.files.Where(x => x.Value.type == PackageFileType.Dll).Select(x => x.Key).FirstOrDefault(); - if (dll == null || !File.Exists(Path.Combine(package.basePath, dll))) - return false; - InternalEditorUtility.SetPlatformPath(package.basePath); - Assembly assembly = InternalEditorUtility.LoadAssemblyWrapper(Path.GetFileName(dll), Path.Combine(package.basePath, dll)); - return InitializePackageManager(assembly, package); - } - - static bool InitializePackageManager(Assembly assembly, Unity.DataContract.PackageInfo package) - { - s_PackageManager = AssemblyHelper.FindImplementors(assembly).FirstOrDefault(); - - if (s_PackageManager == null) - return false; - - string dllpath = assembly.Location; - - // if we have a package, it's because it came from the locator, which means we need to setup the dll - // for loading on the next domain reloads - if (package != null) - InternalEditorUtility.RegisterPrecompiledAssembly(Path.GetFileName(dllpath), dllpath); - - else // just set the package with the path to the loaded assembly so package manager can get its information from there - package = new Unity.DataContract.PackageInfo() { basePath = Path.GetDirectoryName(dllpath) }; - - s_PackageManager.moduleInfo = package; - s_PackageManager.editorInstallPath = EditorApplication.applicationContentsPath; - s_PackageManager.unityVersion = new PackageVersion(Application.unityVersion); - - s_PackageManager.Initialize(); - foreach (Unity.DataContract.PackageInfo engine in s_PackageManager.playbackEngines) - { - BuildTargetGroup buildTargetGroup; - BuildTarget target; - if (!TryParseBuildTarget(engine.name, out buildTargetGroup, out target)) - continue; - - if (EnableLogging) - Console.WriteLine("Setting {4}:{0} v{1} for Unity v{2} to {3}", target, engine.version, engine.unityVersion, engine.basePath, buildTargetGroup); - foreach (var file in engine.files.Where(f => f.Value.type == PackageFileType.Dll)) - { - string fullPath = Paths.NormalizePath(Path.Combine(engine.basePath, file.Key)); - if (!File.Exists(fullPath)) - Debug.LogWarningFormat("Missing assembly \t{0} for {1}. Player support may be incomplete.", engine.basePath, engine.name); - else - InternalEditorUtility.RegisterPrecompiledAssembly(Path.GetFileName(dllpath), dllpath); - } - BuildPipeline.SetPlaybackEngineDirectory(target, BuildOptions.None /* TODO */, engine.basePath); - InternalEditorUtility.SetPlatformPath(engine.basePath); - s_PackageManager.LoadPackage(engine); - } - return true; - } - - static bool TryParseBuildTarget(string targetString, out BuildTargetGroup buildTargetGroup, out BuildTarget target) - { - buildTargetGroup = BuildTargetGroup.Standalone; - target = BuildTarget.StandaloneWindows; - try - { - if (targetString == BuildTargetGroup.Facebook.ToString()) - { - buildTargetGroup = BuildTargetGroup.Facebook; - target = BuildTarget.StandaloneWindows; - } - else - { - target = (BuildTarget)Enum.Parse(typeof(BuildTarget), targetString); - buildTargetGroup = BuildPipeline.GetBuildTargetGroup(target); - } - return true; - } - catch - { - Debug.LogWarning(string.Format("Couldn't find build target for {0}", targetString)); - } - return false; - } - - static void RegisterPlatformSupportModules() - { - if (s_PlatformModules != null) - { - Console.WriteLine("Modules already registered, not loading"); - return; - } - Console.WriteLine("Registering platform support modules:"); - var stopwatch = System.Diagnostics.Stopwatch.StartNew(); - s_PlatformModules = RegisterModulesFromLoadedAssemblies(RegisterPlatformSupportModulesFromAssembly).ToList(); - - stopwatch.Stop(); - Console.WriteLine("Registered platform support modules in: " + stopwatch.Elapsed.TotalSeconds + "s."); - } - - static IEnumerable RegisterModulesFromLoadedAssemblies(Func> processAssembly) - { - if (processAssembly == null) - throw new ArgumentNullException("processAssembly"); - - return AppDomain.CurrentDomain.GetAssemblies().Aggregate(new List(), - delegate(List list, Assembly assembly) { - try - { - var modules = processAssembly(assembly); - if (modules != null && modules.Any()) - list.AddRange(modules); - } - catch (Exception ex) - { - Console.WriteLine("Error while registering modules from " + assembly.FullName + ": " + ex.Message); - } - return list; - }); - } - - internal static IEnumerable RegisterPlatformSupportModulesFromAssembly(Assembly assembly) - { - return AssemblyHelper.FindImplementors(assembly); - } - - static IEnumerable RegisterEditorModulesFromAssembly(Assembly assembly) - { - return AssemblyHelper.FindImplementors(assembly); - } - - internal static List GetJamTargets() - { - List jamTargets = new List(); - - foreach (var module in platformSupportModules) - { - jamTargets.Add(module.JamTarget); - } - - return jamTargets; - } - - internal static IPlatformSupportModule FindPlatformSupportModule(string moduleName) - { - foreach (var module in platformSupportModules) - if (module.TargetName == moduleName) - return module; - - return null; - } - - internal static IDevice GetDevice(string deviceId) - { - DevDevice device; - if (DevDeviceList.FindDevice(deviceId, out device)) - { - IPlatformSupportModule module = FindPlatformSupportModule(device.module); - if (module != null) - return module.CreateDevice(deviceId); - else - throw new ApplicationException("Couldn't find module for target: " + device.module); - } - - throw new ApplicationException("Couldn't create device API for device: " + deviceId); - } - - internal static IUserAssembliesValidator GetUserAssembliesValidator(string target) - { - if (target == null) - return null; - - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.CreateUserAssembliesValidatorExtension(); - } - - return null; - } - - internal static IBuildPostprocessor GetBuildPostProcessor(string target) - { - if (target == null) - return null; - - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.CreateBuildPostprocessor(); - } - - return null; - } - - internal static IBuildPostprocessor GetBuildPostProcessor(BuildTargetGroup targetGroup, BuildTarget target) - { - return GetBuildPostProcessor(GetTargetStringFrom(targetGroup, target)); - } - - internal static IDeploymentTargetsExtension GetDeploymentTargetsExtension(string target) - { - if (target == null) - return null; - - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.CreateDeploymentTargetsExtension(); - } - - return null; - } - - internal static IDeploymentTargetsExtension GetDeploymentTargetsExtension(BuildTargetGroup targetGroup, BuildTarget target) - { - return GetDeploymentTargetsExtension(GetTargetStringFrom(targetGroup, target)); - } - - internal static IBuildAnalyzer GetBuildAnalyzer(string target) - { - if (target == null) return null; - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.CreateBuildAnalyzer(); - } - return null; - } - - internal static IBuildAnalyzer GetBuildAnalyzer(BuildTarget target) - { - return GetBuildAnalyzer(GetTargetStringFromBuildTarget(target)); - } - - internal static ISettingEditorExtension GetEditorSettingsExtension(string target) - { - if (string.IsNullOrEmpty(target)) - return null; - - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.CreateSettingsEditorExtension(); - } - - return null; - } - - internal static ITextureImportSettingsExtension GetTextureImportSettingsExtension(BuildTarget target) - { - return GetTextureImportSettingsExtension(GetTargetStringFromBuildTarget(target)); - } - - internal static ITextureImportSettingsExtension GetTextureImportSettingsExtension(string targetName) - { - foreach (var module in platformSupportModules) - { - if (module.TargetName == targetName) - return module.CreateTextureImportSettingsExtension(); - } - - return new DefaultTextureImportSettingsExtension(); - } - - internal static List GetPreferenceWindowExtensions() - { - List prefWindExtensions = new List(); - - foreach (var module in platformSupportModules) - { - IPreferenceWindowExtension prefWindowExtension = module.CreatePreferenceWindowExtension(); - - if (prefWindowExtension != null) - prefWindExtensions.Add(prefWindowExtension); - } - - return prefWindExtensions; - } - - internal static IBuildWindowExtension GetBuildWindowExtension(string target) - { - if (string.IsNullOrEmpty(target)) - return null; - - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.CreateBuildWindowExtension(); - } - - return null; - } - - internal static ICompilationExtension GetCompilationExtension(string target) - { - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.CreateCompilationExtension(); - } - - return new DefaultCompilationExtension(); - } - - private static IScriptingImplementations GetScriptingImplementations(string target) - { - if (string.IsNullOrEmpty(target)) - return null; - - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.CreateScriptingImplementations(); - } - - return null; - } - - internal static IScriptingImplementations GetScriptingImplementations(BuildTargetGroup target) - { - // Standalone Windows, Linux and OS X share player settings between each other, so they share scripting implementations too - // However, since we can't pin BuildTargetGroup to any single platform support module, we have to explicitly check for this case - if (target == BuildTargetGroup.Standalone) - return new DesktopStandalonePostProcessor.ScriptingImplementations(); - - return GetScriptingImplementations(GetTargetStringFromBuildTargetGroup(target)); - } - - internal static IPluginImporterExtension GetPluginImporterExtension(string target) - { - if (target == null) - return null; - - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.CreatePluginImporterExtension(); - } - - return null; - } - - internal static IPluginImporterExtension GetPluginImporterExtension(BuildTarget target) - { - return GetPluginImporterExtension(GetTargetStringFromBuildTarget(target)); - } - - internal static IPluginImporterExtension GetPluginImporterExtension(BuildTargetGroup target) - { - return GetPluginImporterExtension(GetTargetStringFromBuildTargetGroup(target)); - } - - // This is for the smooth transition to future generic target names without subtargets - // This has to match IPlatformSupportModule.TargetName - not sure how this improves modularity... - // ADD_NEW_PLATFORM_HERE - internal static string GetTargetStringFromBuildTarget(BuildTarget target) - { - switch (target) - { - case BuildTarget.iOS: return "iOS"; - case BuildTarget.tvOS: return "tvOS"; - case BuildTarget.XboxOne: return "XboxOne"; - case BuildTarget.WSAPlayer: return "Metro"; - case BuildTarget.Tizen: return "Tizen"; - case BuildTarget.PSP2: return "PSP2"; - case BuildTarget.PS4: return "PS4"; - case BuildTarget.WebGL: return "WebGL"; - case BuildTarget.Android: return "Android"; - case BuildTarget.N3DS: return "N3DS"; - case BuildTarget.Switch: return "Switch"; - case BuildTarget.StandaloneLinux: - case BuildTarget.StandaloneLinux64: - case BuildTarget.StandaloneLinuxUniversal: - return "LinuxStandalone"; - case BuildTarget.StandaloneWindows: - case BuildTarget.StandaloneWindows64: - return "WindowsStandalone"; - case BuildTarget.StandaloneOSX: - // Deprecated -#pragma warning disable 612, 618 - case BuildTarget.StandaloneOSXIntel: - case BuildTarget.StandaloneOSXIntel64: -#pragma warning restore 612, 618 - return "OSXStandalone"; - default: return null; - } - } - - // This is for the smooth transition to future generic target names without subtargets - internal static string GetTargetStringFromBuildTargetGroup(BuildTargetGroup target) - { - // ADD_NEW_PLATFORM_HERE - switch (target) - { - case BuildTargetGroup.iOS: return "iOS"; - case BuildTargetGroup.tvOS: return "tvOS"; - case BuildTargetGroup.XboxOne: return "XboxOne"; - case BuildTargetGroup.WSA: return "Metro"; - case BuildTargetGroup.Tizen: return "Tizen"; - case BuildTargetGroup.PSP2: return "PSP2"; - case BuildTargetGroup.PS4: return "PS4"; - case BuildTargetGroup.WebGL: return "WebGL"; - case BuildTargetGroup.Android: return "Android"; - case BuildTargetGroup.N3DS: return "N3DS"; - case BuildTargetGroup.Facebook: return "Facebook"; - case BuildTargetGroup.Switch: return "Switch"; - default: return null; - } - } - - // This function returns module name depending on the combination of targetGroup x target - internal static string GetTargetStringFrom(BuildTargetGroup targetGroup, BuildTarget target) - { - if (targetGroup == BuildTargetGroup.Unknown) - throw new ArgumentException("targetGroup must be valid"); - switch (targetGroup) - { - case BuildTargetGroup.Facebook: - return "Facebook"; - case BuildTargetGroup.Standalone: - return GetTargetStringFromBuildTarget(target); - default: - return GetTargetStringFromBuildTargetGroup(targetGroup); - } - } - - internal static bool IsPlatformSupported(BuildTarget target) - { - return GetTargetStringFromBuildTarget(target) != null; - } - - internal static bool HaveLicenseForBuildTarget(string targetString) - { - BuildTargetGroup buildTargetGroup; - BuildTarget target; - if (!TryParseBuildTarget(targetString, out buildTargetGroup, out target)) - return false; - return BuildPipeline.LicenseCheck(target); - } - - internal static string GetExtensionVersion(string target) - { - if (string.IsNullOrEmpty(target)) - return null; - - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.ExtensionVersion; - } - - return null; - } - - internal static bool ShouldShowMultiDisplayOption() - { - GUIContent[] platformDisplayNames = Modules.ModuleManager.GetDisplayNames(EditorUserBuildSettings.activeBuildTarget.ToString()); - return (BuildTargetGroup.Standalone == BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget)) || - (BuildTargetGroup.WSA == BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget)) || (platformDisplayNames != null); - } - - internal static GUIContent[] GetDisplayNames(string target) - { - if (string.IsNullOrEmpty(target)) - return null; - - foreach (var module in platformSupportModules) - { - if (module.TargetName == target) - return module.GetDisplayNames(); - } - - return null; - } - } - - internal static class ModuleUtils - { - // entry point from native - internal static string[] GetAdditionalReferencesForUserScripts() - { - var references = new List(); - - foreach (var module in ModuleManager.platformSupportModulesDontRegister) - references.AddRange(module.AssemblyReferencesForUserScripts); - - return references.ToArray(); - } - - internal static string[] GetAdditionalReferencesForEditorCsharpProject() - { - var references = new List(); - - foreach (var module in ModuleManager.platformSupportModulesDontRegister) - references.AddRange(module.AssemblyReferencesForEditorCsharpProject); - - return references.ToArray(); - } - } -} diff --git a/Editor/Mono/Modules/PlatformSupportModule.cs b/Editor/Mono/Modules/PlatformSupportModule.cs deleted file mode 100644 index b874731cca..0000000000 --- a/Editor/Mono/Modules/PlatformSupportModule.cs +++ /dev/null @@ -1,429 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.DeploymentTargets; -using UnityEngine; -using Mono.Cecil; - -namespace UnityEditor.Modules -{ - internal interface IPlatformSupportModule - { - /// Returns name identifying a target, for ex., Metro, note this name should match prefix - /// for extension module UnityEditor.Metro.Extensions.dll, UnityEditor.Metro.Extensions.Native.dll - string TargetName { get; } - - /// Returns the filename of jam which should be executed when you're recompiling extensions - /// from Editor using CTRL + L shortcut, for ex., WP8EditorExtensions, MetroEditorExtensions, etc - string JamTarget { get; } - - /// Returns an array of native libraries that are required by the extension and must be loaded - /// by the editor. - /// - /// NOTE: If two different platform extensions return a native library with a same file name - /// (regardless of the path), then only first one will be loaded. This is due to the fact that - /// some platforms may require same native library, but we must ship a copy with both platforms, - /// since our modularization and platform installers don't support shared stuff. - string[] NativeLibraries { get; } - - /// Returns an array of assemblies that should be referenced by user's scripts. These will be - /// referenced by editor scripts, and game scripts running in editor. Used to export additional - /// platform specific editor API. - string[] AssemblyReferencesForUserScripts { get; } - - // Returns an array of assemblies that should be included into C# project as references. - // This is different from AssemblyReferencesForUserScripts by that most assembly references - // are internal and not added to the C# project. On the other hand, certain assemblies - // contain public API, and thus should be added to C# project. - string[] AssemblyReferencesForEditorCsharpProject { get; } - - /// A human friendly version (eg. an incrementing number on each release) of the platform extension. Null/Empty if none available - string ExtensionVersion { get; } - - // Names of displays to show in GameView and Camera inspector if the platform supports multiple displays. Return null if default names should be used. - GUIContent[] GetDisplayNames(); - - IBuildPostprocessor CreateBuildPostprocessor(); - - // Returns an instance of IDeploymentTargetsExtension or null if not supported - IDeploymentTargetsExtension CreateDeploymentTargetsExtension(); - - // Returns an instance of IScriptingImplementations or null if only one scripting backend is supported - IScriptingImplementations CreateScriptingImplementations(); - - // Return an instance of ISettingEditorExtension or null if not used - // See DefaultPlayerSettingsEditorExtension.cs for abstract implementation - ISettingEditorExtension CreateSettingsEditorExtension(); - - // Return an instance of IPreferenceWindowExtension or null if not used - IPreferenceWindowExtension CreatePreferenceWindowExtension(); - - // Return an instance of IBuildWindowExtension or null if not used - IBuildWindowExtension CreateBuildWindowExtension(); - - ICompilationExtension CreateCompilationExtension(); - - // Rather than null above, this returns a default extension if not used - ITextureImportSettingsExtension CreateTextureImportSettingsExtension(); - - IPluginImporterExtension CreatePluginImporterExtension(); - - IBuildAnalyzer CreateBuildAnalyzer(); - - // Return an instance of IUserAssembliesValidator or null if not used - IUserAssembliesValidator CreateUserAssembliesValidatorExtension(); - - IProjectGeneratorExtension CreateProjectGeneratorExtension(); - - // Register platform specific Unity extensions - // For ex., Metro specifc UnityEngine.Networking.dll which is different from the generic UnityEngine.Networking.dll - void RegisterAdditionalUnityExtensions(); - - // return valid object for this device. This ensures that API for certain operations is - // still available even if device was removed, for example stopping remote support. - IDevice CreateDevice(string id); - - // Called when build target supplied by this module is activated in the editor. - // - // NOTE: Keep in mind that due domain reloads and the way unity builds, calls on OnActive - // and OnDeactivate will be forced even if current build target isn't being changed. - // - // PERFORMANCE: This method will be called each time user starts the game, so use this - // only for lightweight code, like registering to events, etc. - // - // Currently (de)activation happens when: - // * User switches build target. - // * User runs build for current target. - // * Build is run through scripting API. - // * Scripts are recompiled and reloaded (due user's change, forced reimport, etc). - // * User clicks play in editor. - // * ... and possibly more I'm not aware of. - void OnActivate(); - - // Called when build target supplied by this module is deactivated in the editor. - // - // NOTE: Keep in mind that due domain reloads and the way unity builds, calls on OnActive - // and OnDeactivate will be forced even if current build target isn't being changed. - // - // PERFORMANCE: This method will be called each time user starts the game, so use this - // only for lightweight code, like unregistering from events, etc. - // - // For more info see OnActivate(). - void OnDeactivate(); - - // Called when extension is loaded, on editor start or domain reload. - // - // PERFORMANCE: This will be called for all available platform extensions during each - // domain reload, including each time user starts the game, so use this only for - // lightweight code. - void OnLoad(); - - // Called when extension is unloaded, when editor is exited or before domain reload. - // - // PERFORMANCE: This will be called for all available platform extensions during each - // domain reload, including each time user starts the game, so use this only for - // lightweight code. - void OnUnload(); - } - - internal interface IBuildPostprocessor - { - void LaunchPlayer(BuildLaunchPlayerArgs args); - - void PostProcess(BuildPostProcessArgs args, out BuildProperties outProperties); - - bool SupportsInstallInBuildFolder(); - - bool SupportsLz4Compression(); - - bool SupportsScriptsOnlyBuild(); - - // This is the place to make sure platform has everything it needs for the build. - // Use EditorUtility.Display(Cancelable)ProgressBar when running long tasks (e.g. downloading SDK from internet). - // Return non-empty string indicating error message to stop the build. - string PrepareForBuild(BuildOptions options, BuildTarget target); - - void UpdateBootConfig(BuildTarget target, BootConfigData config, BuildOptions options); - - // Return string.Empty if targeting a folder. - string GetExtension(BuildTarget target, BuildOptions options); - } - - internal interface IScriptingImplementations - { - // All supported scripting implementations. First is the default one. - ScriptingImplementation[] Supported(); - - // Scripting implementations exposed to the user. - ScriptingImplementation[] Enabled(); - bool AllowIL2CPPCompilerConfigurationSelection(); - } - - internal class DefaultScriptingImplementations : IScriptingImplementations - { - public virtual ScriptingImplementation[] Supported() - { - return new[] { ScriptingImplementation.Mono2x, ScriptingImplementation.IL2CPP }; - } - - public virtual ScriptingImplementation[] Enabled() - { - return new[] { ScriptingImplementation.Mono2x, ScriptingImplementation.IL2CPP }; - } - - public virtual bool AllowIL2CPPCompilerConfigurationSelection() - { - return true; - } - } - - // Extension point to add/alter the SettingsEditorWindow class - // If you are creating a new extension you should probably inherit from DefaultPlayerSettingsEditorExtension - internal interface ISettingEditorExtension - { - void OnEnable(PlayerSettingsEditor settingsEditor); - - bool HasPublishSection(); - - // Leave blank if no contribution - void PublishSectionGUI(float h, float midWidth, float maxWidth); - - bool HasIdentificationGUI(); - - // Leave blank if no contribution - void IdentificationSectionGUI(); - - // Leave blank if no contribution - void ConfigurationSectionGUI(); - - bool SupportsOrientation(); - - bool SupportsStaticBatching(); - bool SupportsDynamicBatching(); - bool SupportsHighDynamicRangeDisplays(); - bool SupportsGfxJobModes(); - - bool CanShowUnitySplashScreen(); - - void SplashSectionGUI(); - - bool UsesStandardIcons(); - - void IconSectionGUI(); - - bool HasResolutionSection(); - - void ResolutionSectionGUI(float h, float midWidth, float maxWidth); - - bool HasBundleIdentifier(); - - bool SupportsMultithreadedRendering(); - - void MultithreadedRenderingGUI(BuildTargetGroup targetGroup); - - bool SupportsCustomLightmapEncoding(); - } - - - // Extension point to add preferences to the PreferenceWindow class - internal interface IPreferenceWindowExtension - { - // Called from PreferenceWindow whenever preferences should be read - void ReadPreferences(); - - // Called from PreferenceWindow whenever preferences should be written - void WritePreferences(); - - // True is this extension contributes an external application/tool preference(s) - bool HasExternalApplications(); - - // Called from OnGui - this function should draw any contributing UI components - void ShowExternalApplications(); - } - - // NOTE: You probably want to inherit from DefaultBuildWindowExtension class - internal interface IBuildWindowExtension - { - void ShowPlatformBuildOptions(); - - void ShowPlatformBuildWarnings(); - - // Use this for "developer" Unity builds - void ShowInternalPlatformBuildOptions(); - - bool EnabledBuildButton(); - - bool EnabledBuildAndRunButton(); - - void GetBuildButtonTitles(out GUIContent buildButtonTitle, out GUIContent buildAndRunButtonTitle); - - bool ShouldDrawScriptDebuggingCheckbox(); - - bool ShouldDrawProfilerCheckbox(); - - bool ShouldDrawDevelopmentPlayerCheckbox(); - - bool ShouldDrawExplicitNullCheckbox(); - - bool ShouldDrawExplicitDivideByZeroCheckbox(); - - bool ShouldDrawExplicitArrayBoundsCheckbox(); - - // Force full optimisations for script complilation in Development builds. - // Useful for forcing optimized compiler for IL2CPP when profiling. - bool ShouldDrawForceOptimizeScriptsCheckbox(); - } - - internal interface IBuildAnalyzer - { - void OnAddedExecutable(Build.Reporting.BuildReport report, int fileIndex); - } - - // Extension point to add platform-specific texture import settings. - // You probably want to inherit from DefaultTextureImportSettingsExtension - internal interface ITextureImportSettingsExtension - { - void ShowImportSettings(Editor baseEditor, TextureImportPlatformSettings platformSettings); - } - - // Interface for target device related operations - internal interface IDevice - { - // Start remote support for this device - RemoteAddress StartRemoteSupport(); - - // Stop remote support for this device - void StopRemoteSupport(); - - // Start player connection support for this device. This only sets up ability to connect, - // like setting up TCP tunneling over USB, getting remote device's IP, but it doesn't - // actually make the connection. Only available if SupportsPlayerConnection is true. - // Otherwise throws NotSupportedException. - RemoteAddress StartPlayerConnectionSupport(); - - // Stop player connection support for this device. Only available if SupportsPlayerConnection - // is true. Otherwise throws NotSupportedException. - void StopPlayerConnectionSupport(); - } - - internal struct RemoteAddress - { - public string ip; - public int port; - - public RemoteAddress(string ip, int port) - { - this.ip = ip; - this.port = port; - } - } - - internal interface IPluginImporterExtension - { - // Functions use by PluginImporterInspector - void ResetValues(PluginImporterInspector inspector); - bool HasModified(PluginImporterInspector inspector); - void Apply(PluginImporterInspector inspector); - void OnEnable(PluginImporterInspector inspector); - void OnDisable(PluginImporterInspector inspector); - void OnPlatformSettingsGUI(PluginImporterInspector inspector); - - // Called before building the player, checks if plugins don't overwrite each other - string CalculateFinalPluginPath(string buildTargetName, PluginImporter imp); - bool CheckFileCollisions(string buildTargetName); - } - - internal struct BuildLaunchPlayerArgs - { - public BuildTarget target; - public string playerPackage; - public string installPath; - public string productName; - public BuildOptions options; - public Build.Reporting.BuildReport report; - } - - internal struct BuildPostProcessArgs - { - public BuildTarget target; - public string stagingArea; - public string stagingAreaData; - public string stagingAreaDataManaged; - public string playerPackage; - public string installPath; - public string companyName; - public string productName; - public Guid productGUID; - public BuildOptions options; - public Build.Reporting.BuildReport report; - internal RuntimeClassRegistry usedClassRegistry; - } - - // An 'IUserAssembliesValidator' is responsible of validating the assemblies - // generated after a successful recompilation of the scripts. - // For performance reason, and to keep the Editor responsive, the validation is - // allowed to run in background. - internal interface IUserAssembliesValidator - { - // If true, it allow the Editor to run the validation in a background Thread - bool canRunInBackground { get; } - - // Invoked by the Editor after the user assemblies have been rebuilt, to allow the - // validator to validate the generated assemblies. - // - // This method is invoked only in case rebuilding the scripts was successful. - // The method might be run in a separate thread in case canRunInBackground was true. - void Validate(string[] userAssemblies); - - // Invoked by the Editor in case the validation has just been killed, usually due to - // script rebuilds being triggered when the Validate method has not been terminated yet. - void Cleanup(); - } - - internal enum CSharpCompiler - { - Mono, - Microsoft, - } - - internal interface ICompilationExtension - { - CSharpCompiler GetCsCompiler(bool buildingForEditor, string assemblyName); - string[] GetCompilerExtraAssemblyPaths(bool isEditor, string assemblyPathName); - IAssemblyResolver GetAssemblyResolver(bool buildingForEditor, string assemblyPath, string[] searchDirectories); - - // Returns an array of windows metadata files (.winmd) that should be referenced when compiling scripts. - // Only WinRT based platforms need these references. - IEnumerable GetWindowsMetadataReferences(); - - // Returns an array of managed assemblies that should be referenced when compiling scripts - // Currently, only .NET scripting backend uses it to include WinRTLegacy.dll into compilation - IEnumerable GetAdditionalAssemblyReferences(); - - // Returns an array of defines that should be used when compiling scripts - IEnumerable GetAdditionalDefines(); - - // Returns an array of C# source files that should be included into the assembly when compiling scripts - IEnumerable GetAdditionalSourceFiles(); - } - - - internal class CSharpProject - { - public string Path { get; set; } - public Guid Guid { get; set; } - } - - /// - /// Generates platform dependent projects - /// For ex., Windows Store Apps would generate Assembly-CSharp* projects targeting .NET Core which. - /// Currently this interface is used by Visual Studio Unity Tools project generator, which includes these projects into their main solution - /// - internal interface IProjectGeneratorExtension - { - void GenerateCSharpProject(CSharpProject project, string assemblyName, IEnumerable sourceFiles, IEnumerable defines, IEnumerable additionalProjectReferences); - } -} diff --git a/Editor/Mono/MonoScript.bindings.cs b/Editor/Mono/MonoScript.bindings.cs deleted file mode 100644 index d8a223131a..0000000000 --- a/Editor/Mono/MonoScript.bindings.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; -using System.Collections.Generic; -using UnityEditor.Animations; - -namespace UnityEditor -{ - // Representation of Script assets. - [NativeClass(null)] - [NativeType("Editor/Mono/MonoScript.bindings.h")] - public class MonoScript : TextAsset - { - // Returns the System.Type object of the class implemented by this script - public extern System.Type GetClass(); - - // Returns the MonoScript object containing specified MonoBehaviour - [FreeFunction] - public extern static MonoScript FromMonoBehaviour(MonoBehaviour behaviour); - - // Returns the MonoScript object containing specified ScriptableObject - [FreeFunction] - public extern static MonoScript FromScriptableObject(ScriptableObject scriptableObject); - - internal extern bool GetScriptTypeWasJustCreatedFromComponentMenu(); - - internal extern void SetScriptTypeWasJustCreatedFromComponentMenu(); - - // *undocumented* - public MonoScript() - { - Init_Internal(this); - } - - [FreeFunction("MonoScript_Init_Internal")] - private static extern void Init_Internal([Writable] MonoScript script); - - // *undocumented* - [NativeName("InitializeAndRegisterScript")] - internal extern void Init(string scriptContents, string className, string nameSpace, string assemblyName, bool isEditorScript); - - // *undocumented* - [NativeName("GetNameSpace")] - internal extern string GetNamespace(); - } -} diff --git a/Editor/Mono/MuscleClipUtility.bindings.cs b/Editor/Mono/MuscleClipUtility.bindings.cs deleted file mode 100644 index c553a16c37..0000000000 --- a/Editor/Mono/MuscleClipUtility.bindings.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using System.Runtime.InteropServices; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/Animation/MuscleClipQualityInfo.h")] - [RequiredByNativeCode] - [NativeAsStruct] - [StructLayout(LayoutKind.Sequential)] - internal class MuscleClipQualityInfo - { - [NativeName("m_Loop")] - public float loop = 0; - [NativeName("m_LoopOrientation")] - public float loopOrientation = 0; - [NativeName("m_LoopPositionY")] - public float loopPositionY = 0; - [NativeName("m_LoopPositionXZ")] - public float loopPositionXZ = 0; - } - - internal struct QualityCurvesTime - { - public float fixedTime; - public float variableEndStart; - public float variableEndEnd; - public int q; - } - - [NativeHeader("Editor/Src/Animation/MuscleClipQualityInfo.h")] - internal class MuscleClipUtility - { - [FreeFunction] - extern internal static MuscleClipQualityInfo GetMuscleClipQualityInfo(AnimationClip clip, float startTime, float stopTime); - - internal static void CalculateQualityCurves(AnimationClip clip, QualityCurvesTime time, Vector2[] poseCurve, Vector2[] rotationCurve, Vector2[] heightCurve, Vector2[] positionCurve) - { - if (poseCurve.Length != rotationCurve.Length || rotationCurve.Length != heightCurve.Length || heightCurve.Length != positionCurve.Length) - { - throw new ArgumentException(string.Format( - "poseCurve '{0}', rotationCurve '{1}', heightCurve '{2}' and positionCurve '{3}' Length must be equals.", - poseCurve.Length, rotationCurve.Length, heightCurve.Length, positionCurve.Length)); - } - - CalculateQualityCurves(clip, time.fixedTime, time.variableEndStart, time.variableEndEnd, time.q, poseCurve, rotationCurve, heightCurve, positionCurve); - } - - [FreeFunction] - extern protected static void CalculateQualityCurves(AnimationClip clip, float fixedTime, float variableEndStart, float variableEndEnd, int q, [Out] Vector2[] poseCurve, [Out] Vector2[] rotationCurve, [Out] Vector2[] heightCurve, [Out] Vector2[] positionCurve); - } -} diff --git a/Editor/Mono/Networking/PlayerConnection/EditorConnection.cs b/Editor/Mono/Networking/PlayerConnection/EditorConnection.cs deleted file mode 100644 index 1b35d190d9..0000000000 --- a/Editor/Mono/Networking/PlayerConnection/EditorConnection.cs +++ /dev/null @@ -1,185 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using UnityEngine; -using UnityEngine.Events; -using UnityEngine.Networking.PlayerConnection; -using UnityEngine.Scripting; - -namespace UnityEditor.Networking.PlayerConnection -{ - [Serializable] - public class ConnectedPlayer - { - public ConnectedPlayer() - { - } - - public ConnectedPlayer(int playerId) - { - m_PlayerId = playerId; - } - - public ConnectedPlayer(int playerId, string name) - { - m_PlayerId = playerId; - m_PlayerName = name; - } - - [SerializeField] - private int m_PlayerId; - - [SerializeField] - private string m_PlayerName; - - [Obsolete("Use playerId instead (UnityUpgradable) -> playerId", true)] - public int PlayerId - { - get { return m_PlayerId; } - } - - public int playerId - { - get { return m_PlayerId; } - } - - public string name - { - get { return m_PlayerName; } - } - } - - [Serializable] - public class EditorConnection : ScriptableSingleton, IEditorPlayerConnection - { - internal static IPlayerEditorConnectionNative connectionNative; - - [SerializeField] - private PlayerEditorConnectionEvents m_PlayerEditorConnectionEvents = new PlayerEditorConnectionEvents(); - - [SerializeField] - private List m_connectedPlayers = new List(); - - public List ConnectedPlayers - { - get { return m_connectedPlayers; } - } - - public void Initialize() - { - GetEditorConnectionNativeApi().Initialize(); - } - - private void Cleanup() - { - UnregisterAllPersistedListeners(m_PlayerEditorConnectionEvents.connectionEvent); - UnregisterAllPersistedListeners(m_PlayerEditorConnectionEvents.disconnectionEvent); - m_PlayerEditorConnectionEvents.messageTypeSubscribers.Clear(); - } - - private void UnregisterAllPersistedListeners(UnityEventBase connectionEvent) - { - var persistentEventCount = connectionEvent.GetPersistentEventCount(); - for (int i = 0; i < persistentEventCount; i++) - { - connectionEvent.UnregisterPersistentListener(i); - } - } - - private IPlayerEditorConnectionNative GetEditorConnectionNativeApi() - { - return connectionNative ?? new EditorConnectionInternal(); - } - - public void Register(Guid messageId, UnityAction callback) - { - if (messageId == Guid.Empty) - { - throw new ArgumentException("Cant be Guid.Empty", "messageId"); - } - - if (!m_PlayerEditorConnectionEvents.messageTypeSubscribers.Any(x => x.MessageTypeId == messageId)) - { - GetEditorConnectionNativeApi().RegisterInternal(messageId); - } - - m_PlayerEditorConnectionEvents.AddAndCreate(messageId) - .AddPersistentListener(callback, UnityEventCallState.EditorAndRuntime); - } - - public void Unregister(Guid messageId, UnityAction callback) - { - m_PlayerEditorConnectionEvents.UnregisterManagedCallback(messageId, callback); - if (!m_PlayerEditorConnectionEvents.messageTypeSubscribers.Any(x => x.MessageTypeId == messageId)) - { - GetEditorConnectionNativeApi().UnregisterInternal(messageId); - } - } - - public void RegisterConnection(UnityAction callback) - { - foreach (var players in m_connectedPlayers) - { - callback.Invoke(players.playerId); - } - m_PlayerEditorConnectionEvents.connectionEvent.AddPersistentListener(callback, UnityEventCallState.EditorAndRuntime); - } - - public void RegisterDisconnection(UnityAction callback) - { - m_PlayerEditorConnectionEvents.disconnectionEvent.AddPersistentListener(callback, UnityEventCallState.EditorAndRuntime); - } - - public void Send(Guid messageId, byte[] data, int playerId) - { - if (messageId == Guid.Empty) - { - throw new ArgumentException("Cant be Guid.Empty", "messageId"); - } - - GetEditorConnectionNativeApi().SendMessage(messageId, data, playerId); - } - - public void Send(Guid messageId, byte[] data) - { - Send(messageId, data, 0); - } - - public void DisconnectAll() - { - GetEditorConnectionNativeApi().DisconnectAll(); - } - - [RequiredByNativeCode] - private static void MessageCallbackInternal(IntPtr data, UInt64 size, UInt64 guid, string messageId) - { - byte[] bytes = null; - if (size > 0) - { - bytes = new byte[size]; - Marshal.Copy(data, bytes, 0, unchecked((int)size)); - } - - instance.m_PlayerEditorConnectionEvents.InvokeMessageIdSubscribers(new Guid(messageId), bytes, (int)guid); - } - - [RequiredByNativeCode] - private static void ConnectedCallbackInternal(int playerId, string playerName) - { - instance.m_connectedPlayers.Add(new ConnectedPlayer(playerId, playerName)); - instance.m_PlayerEditorConnectionEvents.connectionEvent.Invoke(playerId); - } - - [RequiredByNativeCode] - private static void DisconnectedCallback(int playerId) - { - instance.m_connectedPlayers.RemoveAll(c => c.playerId == playerId); - instance.m_PlayerEditorConnectionEvents.disconnectionEvent.Invoke(playerId); - } - } -} diff --git a/Editor/Mono/NumericFieldDraggerUtility.cs b/Editor/Mono/NumericFieldDraggerUtility.cs deleted file mode 100644 index 87ec27bbe0..0000000000 --- a/Editor/Mono/NumericFieldDraggerUtility.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - class NumericFieldDraggerUtility - { - internal static float Acceleration(bool shiftPressed, bool altPressed) - { - return (shiftPressed ? 4 : 1) * (altPressed ? .25f : 1); - } - - static bool s_UseYSign = false; - - internal static float NiceDelta(Vector2 deviceDelta, float acceleration) - { - deviceDelta.y = -deviceDelta.y; - - if (Mathf.Abs(Mathf.Abs(deviceDelta.x) - Mathf.Abs(deviceDelta.y)) / Mathf.Max(Mathf.Abs(deviceDelta.x), Mathf.Abs(deviceDelta.y)) > .1f) - { - if (Mathf.Abs(deviceDelta.x) > Mathf.Abs(deviceDelta.y)) - s_UseYSign = false; - else - s_UseYSign = true; - } - - if (s_UseYSign) - return Mathf.Sign(deviceDelta.y) * deviceDelta.magnitude * acceleration; - else - return Mathf.Sign(deviceDelta.x) * deviceDelta.magnitude * acceleration; - } - - const float kDragSensitivity = .03f; - - internal static double CalculateFloatDragSensitivity(double value) - { - if (double.IsInfinity(value) || double.IsNaN(value)) - { - return 0.0; - } - return Math.Max(1, Math.Pow(Math.Abs(value), 0.5)) * kDragSensitivity; - } - - internal static long CalculateIntDragSensitivity(long value) - { - return (long)Math.Max(1, Math.Pow(Math.Abs((double)value), 0.5) * kDragSensitivity); - } - } -} diff --git a/Editor/Mono/ObjectFactory.bindings.cs b/Editor/Mono/ObjectFactory.bindings.cs deleted file mode 100644 index d7521b8920..0000000000 --- a/Editor/Mono/ObjectFactory.bindings.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Reflection; -using UnityEngine; -using UnityEngine.Bindings; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/ObjectFactory.h")] - public static class ObjectFactory - { - [FreeFunction(ThrowsException = true)] - static extern Object CreateDefaultInstance([NotNull] Type type); - - [FreeFunction(ThrowsException = true)] - static extern Component AddDefaultComponent([NotNull] GameObject gameObject, [NotNull] Type type); - - [FreeFunction] - static extern GameObject CreateDefaultGameObject(string name); - - static void CheckTypeValidity(Type type) - { - if (type.IsAbstract) - { - throw new ArgumentException("Abstract types can't be used in the ObjectFactory : " + type.FullName); - } - if (Attribute.GetCustomAttribute(type, typeof(ExcludeFromObjectFactoryAttribute)) != null) - { - throw new ArgumentException("The type " + type.FullName + " is not supported by the ObjectFactory."); - } - } - - public static T CreateInstance() where T : Object - { - return (T)CreateInstance(typeof(T)); - } - - public static Object CreateInstance(Type type) - { - CheckTypeValidity(type); - if (type == typeof(GameObject)) - { - throw new ArgumentException("GameObject type must be created using ObjectFactory.CreateGameObject instead : " + type.FullName); - } - if (type.IsSubclassOf(typeof(Component))) - { - throw new ArgumentException("Component type must be created using ObjectFactory.AddComponent instead : " + type.FullName); - } - if (type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null) != null) - { - throw new ArgumentException(type.FullName + " constructor is not accessible which prevent this type from being used in ObjectFactory."); - } - var obj = CreateDefaultInstance(type); - return obj; - } - - public static T AddComponent(GameObject gameObject) where T : Component - { - return (T)AddComponent(gameObject, typeof(T)); - } - - public static Component AddComponent(GameObject gameObject, Type type) - { - CheckTypeValidity(type); - if (!type.IsSubclassOf(typeof(Component))) - { - throw new ArgumentException("Non-Component type must use ObjectFactory.CreateInstance instead : " + type.FullName); - } - return AddDefaultComponent(gameObject, type); - } - - public static GameObject CreateGameObject(string name, params Type[] types) - { - var go = CreateDefaultGameObject(name); - go.SetActive(false); - foreach (var type in types) - { - AddComponent(go, type); - } - go.SetActive(true); - return go; - } - - public static GameObject CreatePrimitive(PrimitiveType type) - { - var go = CreateGameObject(type.ToString(), typeof(MeshFilter), typeof(MeshRenderer)); - go.SetActive(false); - switch (type) - { - case PrimitiveType.Sphere: - go.GetComponent().sharedMesh = Resources.GetBuiltinResource("New-Sphere.fbx"); - AddComponent(go); - break; - case PrimitiveType.Capsule: - go.GetComponent().sharedMesh = Resources.GetBuiltinResource("New-Capsule.fbx"); - var capsule = AddComponent(go); - capsule.height = 2f; - break; - case PrimitiveType.Cylinder: - go.GetComponent().sharedMesh = Resources.GetBuiltinResource("New-Cylinder.fbx"); - var cylinder = AddComponent(go); - cylinder.height = 2f; - break; - case PrimitiveType.Cube: - go.GetComponent().sharedMesh = Resources.GetBuiltinResource("Cube.fbx"); - AddComponent(go); - break; - case PrimitiveType.Plane: - go.GetComponent().sharedMesh = Resources.GetBuiltinResource("New-Plane.fbx"); - AddComponent(go); - break; - case PrimitiveType.Quad: - go.GetComponent().sharedMesh = Resources.GetBuiltinResource("Quad.fbx"); - AddComponent(go); - break; - } - - var renderer = go.GetComponent(); - renderer.material = Material.GetDefaultMaterial(); - //go->GetComponent().SetPreserveUVs(true); - go.SetActive(true); - return go; - } - } -} diff --git a/Editor/Mono/ObjectListArea.cs b/Editor/Mono/ObjectListArea.cs deleted file mode 100644 index c08f55f69f..0000000000 --- a/Editor/Mono/ObjectListArea.cs +++ /dev/null @@ -1,1735 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.VersionControl; -using System.Collections.Generic; -using System.Linq; -using UnityEditorInternal; -using UnityEngine.Assertions; -using Math = System.Math; -using IndexOutOfRangeException = System.IndexOutOfRangeException; - - -namespace UnityEditor -{ - [System.Serializable] - internal class ObjectListAreaState - { - // Selection state - public List m_SelectedInstanceIDs = new List(); - public int m_LastClickedInstanceID; // Used for navigation - public bool m_HadKeyboardFocusLastEvent; // Needs to survive domain reloads to prevent setting selection on got keyboard focus - - // Expanded instanceIDs - public List m_ExpandedInstanceIDs = new List(); - - // Rename state - public RenameOverlay m_RenameOverlay = new RenameOverlay(); - - // Create new asset state - public CreateAssetUtility m_CreateAssetUtility = new CreateAssetUtility(); - public int m_NewAssetIndexInList = -1; - - // Misc state - public Vector2 m_ScrollPosition; - public int m_GridSize = 64; - - public void OnAwake() - { - // Clear state that should not survive closing/starting Unity - m_NewAssetIndexInList = -1; - m_RenameOverlay.Clear(); - m_CreateAssetUtility = new CreateAssetUtility(); - } - } - - - internal partial class ObjectListArea - { - class Styles - { - public GUIStyle resultsLabel = new GUIStyle("PR Label"); - public GUIStyle resultsGridLabel = GetStyle("ProjectBrowserGridLabel"); - public GUIStyle resultsGrid = "ObjectPickerResultsGrid"; - public GUIStyle background = "ObjectPickerBackground"; - public GUIStyle previewTextureBackground = "ObjectPickerPreviewBackground"; - public GUIStyle groupHeaderMiddle = GetStyle("ProjectBrowserHeaderBgMiddle"); - public GUIStyle groupHeaderTop = GetStyle("ProjectBrowserHeaderBgTop"); - public GUIStyle groupHeaderLabel = "Label"; - public GUIStyle groupHeaderLabelCount = "MiniLabel"; - public GUIStyle groupFoldout = "IN Foldout"; - public GUIStyle toolbarBack = "ObjectPickerToolbar"; - public GUIStyle resultsFocusMarker; - public GUIStyle miniRenameField = new GUIStyle("PR TextField"); - public GUIStyle ping = new GUIStyle("PR Ping"); - public GUIStyle miniPing = new GUIStyle("PR Ping"); - public GUIStyle iconDropShadow = GetStyle("ProjectBrowserIconDropShadow"); - public GUIStyle textureIconDropShadow = GetStyle("ProjectBrowserTextureIconDropShadow"); - public GUIStyle iconAreaBg = GetStyle("ProjectBrowserIconAreaBg"); - public GUIStyle previewBg = GetStyle("ProjectBrowserPreviewBg"); - public GUIStyle subAssetBg = GetStyle("ProjectBrowserSubAssetBg"); - public GUIStyle subAssetBgOpenEnded = GetStyle("ProjectBrowserSubAssetBgOpenEnded"); - public GUIStyle subAssetBgCloseEnded = GetStyle("ProjectBrowserSubAssetBgCloseEnded"); - public GUIStyle subAssetBgMiddle = GetStyle("ProjectBrowserSubAssetBgMiddle"); - public GUIStyle subAssetBgDivider = GetStyle("ProjectBrowserSubAssetBgDivider"); - public GUIStyle subAssetExpandButton = GetStyle("ProjectBrowserSubAssetExpandBtn"); - - public GUIContent m_AssetStoreNotAvailableText = EditorGUIUtility.TrTextContent("The Asset Store is not available"); - - public Styles() - { - // Use same colors as resultsGridLabel but with flexible size - resultsFocusMarker = new GUIStyle(resultsGridLabel); - resultsFocusMarker.fixedHeight = resultsFocusMarker.fixedWidth = 0; - - // Mini-label version for icon view - miniRenameField.font = EditorStyles.miniLabel.font; - miniRenameField.alignment = TextAnchor.LowerCenter; - - ping.fixedHeight = 16f; - ping.padding.right = 10; - - // Mini-ping version for icon view - miniPing.font = EditorStyles.miniLabel.font; - miniPing.alignment = TextAnchor.MiddleCenter; - - resultsLabel.alignment = TextAnchor.MiddleLeft; - } - - static GUIStyle GetStyle(string styleName) - { - return styleName; // Implicit construction of GUIStyle - - // For fast testing in editor resources - //GUISkin skin = EditorGUIUtility.LoadRequired ("Builtin Skins/DarkSkin/Skins/ProjectBrowserSkin.guiSkin") as GUISkin; - //return skin.GetStyle (styleName); - } - } - static Styles s_Styles; - - // State persisted across assembly reloads - ObjectListAreaState m_State; - - // Key navigation - const int kHome = int.MinValue; - const int kEnd = int.MaxValue; - const int kPageDown = int.MaxValue - 1; - const int kPageUp = int.MinValue + 1; - int m_SelectionOffset = 0; - - const float k_ListModeVersionControlOverlayPadding = 14f; - static bool s_VCEnabled = false; - - PingData m_Ping = new PingData(); - - EditorWindow m_Owner; - - public bool allowDragging { get; set; } - public bool allowRenaming { get; set; } - public bool allowMultiSelect { get; set; } - public bool allowDeselection { get; set; } - public bool allowFocusRendering { get; set; } - public bool allowBuiltinResources { get; set; } - public bool allowUserRenderingHook { get; set; } - public bool allowFindNextShortcut { get; set; } - public bool foldersFirst { get; set; } - int m_KeyboardControlID; - - Dictionary m_InstanceIDToCroppedNameMap = new Dictionary(); - int m_WidthUsedForCroppingName; - bool m_AllowRenameOnMouseUp = true; - - - Vector2 m_LastScrollPosition = new Vector2(0, 0); - double LastScrollTime = 0; - - - const double kDelayQueryAfterScroll = 0.0; - - - public bool selectedAssetStoreAsset; - - - internal Texture m_SelectedObjectIcon = null; - - LocalGroup m_LocalAssets; - - List m_StoreAssets; - string m_AssetStoreError = ""; - - - // List of all available groups - List m_Groups; - - // Layout - Rect m_TotalRect; - Rect m_VisibleRect; - const int kListLineHeight = 16; - private int m_pingIndex; - - int m_MinIconSize = 32; - int m_MinGridSize = 16; - int m_MaxGridSize = 96; - bool m_AllowThumbnails = true; - const int kSpaceForScrollBar = 16; - int m_LeftPaddingForPinging = 0; - bool m_FrameLastClickedItem = false; - - bool m_ShowLocalAssetsOnly = true; - - - // Asset store resources - const double kQueryDelay = 0.2; - public bool m_RequeryAssetStore; - - bool m_QueryInProgress = false; - int m_ResizePreviewCacheTo = 0; - - string m_LastAssetStoreQuerySearchFilter = ""; - string[] m_LastAssetStoreQueryClassName = new string[0]; - string[] m_LastAssetStoreQueryLabels = new string[0]; - double m_LastAssetStoreQueryChangeTime = 0.0; - - double m_NextDirtyCheck = 0; - - - // Callbacks - System.Action m_RepaintWantedCallback; - System.Action m_ItemSelectedCallback; - System.Action m_KeyboardInputCallback; - System.Action m_GotKeyboardFocus; - System.Func m_DrawLocalAssetHeader; - System.Action m_AssetStoreSearchEnded; - - public System.Action repaintCallback { get {return m_RepaintWantedCallback; } set {m_RepaintWantedCallback = value; }} - public System.Action itemSelectedCallback { get {return m_ItemSelectedCallback; } set {m_ItemSelectedCallback = value; }} - public System.Action keyboardCallback { get {return m_KeyboardInputCallback; } set {m_KeyboardInputCallback = value; }} - public System.Action gotKeyboardFocus { get {return m_GotKeyboardFocus; } set {m_GotKeyboardFocus = value; }} - public System.Action assetStoreSearchEnded { get {return m_AssetStoreSearchEnded; } set {m_AssetStoreSearchEnded = value; }} - public System.Func drawLocalAssetHeader { get {return m_DrawLocalAssetHeader; } set {m_DrawLocalAssetHeader = value; }} - - // Debug - static internal bool s_Debug = false; - - public ObjectListArea(ObjectListAreaState state, EditorWindow owner, bool showNoneItem) - { - m_State = state; - m_Owner = owner; - - AssetStorePreviewManager.MaxCachedImages = 72; // Magic number. Will be reset on first layout. - - m_StoreAssets = new List(); - m_RequeryAssetStore = false; - - m_LocalAssets = new LocalGroup(this, "", showNoneItem); - - m_Groups = new List(); - m_Groups.Add(m_LocalAssets); - } - - public void ShowObjectsInList(int[] instanceIDs) - { - // Clear asset store search etc. - Init(m_TotalRect, HierarchyType.Assets, new SearchFilter(), false); - - // Set list manually - m_LocalAssets.ShowObjectsInList(instanceIDs); - } - - // This method is being used by the EditorTests/Searching tests - public string[] GetCurrentVisibleNames() - { - var list = m_LocalAssets.GetVisibleNameAndInstanceIDs(); - return list.Select(x => x.Key).ToArray(); - } - - public void Init(Rect rect, HierarchyType hierarchyType, SearchFilter searchFilter, bool checkThumbnails) - { - // Keep for debugging - //Debug.Log ("Init ObjectListArea: " + searchFilter); - - m_TotalRect = m_VisibleRect = rect; - - m_LocalAssets.UpdateFilter(hierarchyType, searchFilter, foldersFirst); - m_LocalAssets.UpdateAssets(); - - foreach (AssetStoreGroup g in m_StoreAssets) - g.UpdateFilter(hierarchyType, searchFilter, foldersFirst); - - bool isFolderBrowsing = (searchFilter.GetState() == SearchFilter.State.FolderBrowsing); - if (isFolderBrowsing) - { - // Do not allow asset store searching when we have folder filtering - m_LastAssetStoreQuerySearchFilter = ""; - m_LastAssetStoreQueryClassName = new string[0]; - m_LastAssetStoreQueryLabels = new string[0]; - } - else - { - m_LastAssetStoreQuerySearchFilter = searchFilter.nameFilter == null ? "" : searchFilter.nameFilter; - bool disableClassConstraint = searchFilter.classNames == null || - System.Array.IndexOf(searchFilter.classNames, "Object") >= 0; - m_LastAssetStoreQueryClassName = disableClassConstraint ? new string[0] : searchFilter.classNames; - m_LastAssetStoreQueryLabels = searchFilter.assetLabels == null ? new string[0] : searchFilter.assetLabels; - } - - m_LastAssetStoreQueryChangeTime = EditorApplication.timeSinceStartup; - m_RequeryAssetStore = true; - - m_ShowLocalAssetsOnly = isFolderBrowsing || (searchFilter.GetState() != SearchFilter.State.SearchingInAssetStore); - m_AssetStoreError = ""; - - - if (checkThumbnails) - m_AllowThumbnails = ObjectsHaveThumbnails(hierarchyType, searchFilter); - else - m_AllowThumbnails = true; - - Repaint(); - - // Clear instanceID to cropped name cache on init - ClearCroppedLabelCache(); - - // Prepare data - SetupData(true); - } - - bool HasFocus() - { - if (!allowFocusRendering) - return true; - return m_KeyboardControlID == GUIUtility.keyboardControl && m_Owner.m_Parent.hasFocus; - } - - void QueryAssetStore() - { - bool searchChanged = m_RequeryAssetStore; - m_RequeryAssetStore = false; - - // We disable Asset Store searching here. Note that we still query to get hits when searching local assets - if (m_ShowLocalAssetsOnly && !ShowAssetStoreHitsWhileSearchingLocalAssets()) - { - return; - } - - bool hasValidFilter = m_LastAssetStoreQuerySearchFilter != "" || m_LastAssetStoreQueryClassName.Length != 0 || m_LastAssetStoreQueryLabels.Length != 0; - - // Make sure that we have only one pending asset store query - // No need to call Repaint() to recheck this condition later because the - // query callback will call that for us. - if (m_QueryInProgress) - return; - - if (!hasValidFilter) - { - ClearAssetStoreGroups(); - return; - } - - // In order not to query prematurely we delay the query a bit to let the user type - // more characters in the search input box if needed. - if ((m_LastAssetStoreQueryChangeTime + kQueryDelay) > EditorApplication.timeSinceStartup) - { - m_RequeryAssetStore = true; - Repaint(); - return; - } - - m_QueryInProgress = true; - - // Remember the filter to check for changes after we have received the reply from asset store - string queryFilter = m_LastAssetStoreQuerySearchFilter + m_LastAssetStoreQueryClassName + m_LastAssetStoreQueryLabels; - - AssetStoreSearchResults.Callback dg = delegate(AssetStoreSearchResults results) { - m_QueryInProgress = false; - - // If filter changed while fetching the result then requery using the new filter. - if (queryFilter != m_LastAssetStoreQuerySearchFilter + m_LastAssetStoreQueryClassName + m_LastAssetStoreQueryLabels) - m_RequeryAssetStore = true; - - if (results.error != null && results.error != "") - { - if (s_Debug) - Debug.LogError("Error performing Asset Store search: " + results.error); - else - System.Console.Write("Error performing Asset Store search: " + results.error); - m_AssetStoreError = results.error; - m_Groups.Clear(); - m_Groups.Add(m_LocalAssets); - Repaint(); - - if (assetStoreSearchEnded != null) - assetStoreSearchEnded(); - - return; - } - - m_AssetStoreError = ""; - - // Clear groups and use the ones from server - List existingGroupNames = new List(); - foreach (AssetStoreGroup g in m_StoreAssets) - existingGroupNames.Add(g.Name); - - m_Groups.Clear(); - m_Groups.Add(m_LocalAssets); - - foreach (AssetStoreSearchResults.Group inGroup in results.groups) - { - existingGroupNames.Remove(inGroup.name); - AssetStoreGroup group = m_StoreAssets.Find(g => g.Name == inGroup.name); - - if (group == null) - { - group = new AssetStoreGroup(this, inGroup.label, inGroup.name); - m_StoreAssets.Add(group); - } - m_Groups.Add(group); - - // Set total found if initial request or different from 0 - if (inGroup.limit != 0) - { - group.ItemsAvailable = inGroup.totalFound; - } - - if (inGroup.offset == 0 && inGroup.limit != 0) - group.Assets = inGroup.assets; - else - group.Assets.AddRange(inGroup.assets); - } - - // Remove groups not valid for this request - foreach (string k in existingGroupNames) - m_StoreAssets.RemoveAll(g => g.Name == k); - - EnsureAssetStoreGroupsAreOpenIfAllClosed(); - - Repaint(); - - if (assetStoreSearchEnded != null) - assetStoreSearchEnded(); - }; - - List groupsQuery = new List(); - - if (!searchChanged) - { - // More items for the same search criteria. Just apply offsets and limits. - foreach (AssetStoreGroup v in m_StoreAssets) - { - AssetStoreClient.SearchCount t = new AssetStoreClient.SearchCount(); - if (v.Visible && v.NeedItems) - { - t.offset = v.Assets.Count; - t.limit = v.ItemsWantedShown - t.offset; - } - t.name = v.Name; - groupsQuery.Add(t); - } - } - - AssetStoreClient.SearchAssets(m_LastAssetStoreQuerySearchFilter, - m_LastAssetStoreQueryClassName, - m_LastAssetStoreQueryLabels, - groupsQuery, dg); - } - - void EnsureAssetStoreGroupsAreOpenIfAllClosed() - { - if (m_StoreAssets.Count > 0) - { - int numExpanded = 0; - foreach (var group in m_StoreAssets) - if (group.Visible) - numExpanded++; - if (numExpanded == 0) - foreach (var group in m_StoreAssets) - group.Visible = group.visiblePreference = true; - } - } - - void RequeryAssetStore() - { - m_RequeryAssetStore = true; - } - - void ClearAssetStoreGroups() - { - m_Groups.Clear(); - m_Groups.Add(m_LocalAssets); - m_StoreAssets.Clear(); - Repaint(); - } - - public string GetAssetStoreButtonText() - { - string buttonText = "Asset Store"; - if (ShowAssetStoreHitsWhileSearchingLocalAssets()) - { - for (int i = 0; i < m_StoreAssets.Count; ++i) - { - if (i == 0) - buttonText += ": "; - else - buttonText += " \u2215 "; // forward slash - AssetStoreGroup group = m_StoreAssets[i]; - buttonText += (group.ItemsAvailable > 999 ? "999+" : group.ItemsAvailable.ToString()); - } - } - return buttonText; - } - - bool ShowAssetStoreHitsWhileSearchingLocalAssets() - { - return EditorPrefs.GetBool("ShowAssetStoreSearchHits", true); // See PreferencesWindow - } - - public void ShowAssetStoreHitCountWhileSearchingLocalAssetsChanged() - { - if (ShowAssetStoreHitsWhileSearchingLocalAssets()) - { - RequeryAssetStore(); - } - else - { - if (m_ShowLocalAssetsOnly) - ClearAssetStoreGroups(); // do not clear if we are wathcing asset store results - } - Repaint(); - } - - internal float GetVisibleWidth() - { - return m_VisibleRect.width; - } - - public float m_SpaceBetween = 6f; - public float m_TopMargin = 10f; - public float m_BottomMargin = 10f; - public float m_RightMargin = 10f; - public float m_LeftMargin = 10f; - - public void OnGUI(Rect position, int keyboardControlID) - { - if (s_Styles == null) - s_Styles = new Styles(); - - s_VCEnabled = Provider.isActive; - - Event evt = Event.current; - - m_TotalRect = position; - - FrameLastClickedItemIfWanted(); - - // Background - GUI.Label(m_TotalRect, GUIContent.none, s_Styles.iconAreaBg); - - // For keyboard focus handling (for Tab support and rendering of keyboard focus state) - m_KeyboardControlID = keyboardControlID; - - // Grab keyboard focus on mousedown in entire rect - if (evt.type == EventType.MouseDown && position.Contains(Event.current.mousePosition)) - { - GUIUtility.keyboardControl = m_KeyboardControlID; - m_AllowRenameOnMouseUp = true; // Reset on mouse down - - Repaint(); // Ensure repaint so we can show we have keyboard focus - } - - bool hasKeyboardFocus = m_KeyboardControlID == GUIUtility.keyboardControl; - if (hasKeyboardFocus != m_State.m_HadKeyboardFocusLastEvent) - { - m_State.m_HadKeyboardFocusLastEvent = hasKeyboardFocus; - - // We got focus - if (hasKeyboardFocus) - { - if (evt.type == EventType.MouseDown) - 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 - - if (m_GotKeyboardFocus != null) - m_GotKeyboardFocus(); - } - } - - // For key navigation: Auto set selection to first element if selection is not shown currently when tabbing - if (evt.keyCode == KeyCode.Tab && evt.type == EventType.KeyDown && !hasKeyboardFocus && !IsShowingAny(GetSelection())) - { - int firstInstanceID; - if (m_LocalAssets.InstanceIdAtIndex(0, out firstInstanceID)) - Selection.activeInstanceID = firstInstanceID; - } - - - HandleKeyboard(true); - HandleZoomScrolling(); - HandleListArea(); - DoOffsetSelection(); - HandleUnusedEvents(); - // GUI.Label(position, new GUIContent(AssetStorePreviewManager.StatsString())); - } - - void FrameLastClickedItemIfWanted() - { - if (m_FrameLastClickedItem && Event.current.type == EventType.Repaint) - { - m_FrameLastClickedItem = false; - double timeSinceLastDraw = EditorApplication.timeSinceStartup - m_LocalAssets.m_LastClickedDrawTime; - if (m_State.m_SelectedInstanceIDs.Count > 0 && timeSinceLastDraw < 0.2) - Frame(m_State.m_LastClickedInstanceID, true, false); - } - } - - void HandleUnusedEvents() - { - if (allowDeselection && Event.current.type == EventType.MouseDown && Event.current.button == 0 && m_TotalRect.Contains(Event.current.mousePosition)) - SetSelection(new int[0], false); - } - - public bool CanShowThumbnails() - { - // - // return m_AllowThumbnails || m_StoreAssets.Find( g => g.ItemsAvailable > 0) != null; - // #else - return m_AllowThumbnails; - // - } - - public int gridSize - { - get { return m_State.m_GridSize; } - set - { - if (m_State.m_GridSize != value) - { - m_State.m_GridSize = value; - m_FrameLastClickedItem = true; - } - } - } - - public int minGridSize - { - get { return m_MinGridSize; } - } - public int maxGridSize - { - get { return m_MaxGridSize; } - } - - - public int numItemsDisplayed - { - get { return m_LocalAssets.ItemCount; } - } - - static string CreateFilterString(string searchString, string requiredClassName) - { - string filter = searchString; - - if (!string.IsNullOrEmpty(requiredClassName)) - { - filter += " t:" + requiredClassName; - } - - return filter; - } - - bool ObjectsHaveThumbnails(HierarchyType type, SearchFilter searchFilter) - { - // Check if we have any built-ins, if so we have thumbs since all builtins have thumbs - if (m_LocalAssets.HasBuiltinResources) - return true; - - // Check if current hierarchy have thumbs - FilteredHierarchy hierarchy = new FilteredHierarchy(type); - hierarchy.searchFilter = searchFilter; - IHierarchyProperty assetProperty = FilteredHierarchyProperty.CreateHierarchyPropertyForFilter(hierarchy); - int[] empty = new int[0]; - if (assetProperty.CountRemaining(empty) == 0) - return true; // allow thumbnails: we prefer asset-store results as icons over list - - assetProperty.Reset(); - while (assetProperty.Next(empty)) - { - if (assetProperty.hasFullPreviewImage) - return true; - } - - return false; - } - - internal void OnDestroy() - { - AssetPreview.DeletePreviewTextureManagerByID(GetAssetPreviewManagerID()); - } - - void Repaint() - { - if (m_RepaintWantedCallback != null) - m_RepaintWantedCallback(); - } - - public void OnEvent() - { - GetRenameOverlay().OnEvent(); - } - - CreateAssetUtility GetCreateAssetUtility() - { - return m_State.m_CreateAssetUtility; - } - - RenameOverlay GetRenameOverlay() - { - return m_State.m_RenameOverlay; - } - - internal void BeginNamingNewAsset(string newAssetName, int instanceID, bool isCreatingNewFolder) - { - m_State.m_NewAssetIndexInList = m_LocalAssets.IndexOfNewText(newAssetName, isCreatingNewFolder, foldersFirst); - if (m_State.m_NewAssetIndexInList != -1) - { - Frame(instanceID, true, false); - GetRenameOverlay().BeginRename(newAssetName, instanceID, 0f); - } - else - { - Debug.LogError("Failed to insert new asset into list"); - } - - Repaint(); - } - - public bool BeginRename(float delay) - { - if (!allowRenaming) - return false; - - // Only allow renaming when one item is selected - if (m_State.m_SelectedInstanceIDs.Count != 1) - return false; - int instanceID = m_State.m_SelectedInstanceIDs[0]; - if (!InternalEditorUtility.CanRenameAsset(instanceID)) - return false; - - string name = m_LocalAssets.GetNameOfLocalAsset(instanceID); - - return GetRenameOverlay().BeginRename(name, instanceID, delay); - } - - public void EndRename(bool acceptChanges) - { - if (GetRenameOverlay().IsRenaming()) - { - GetRenameOverlay().EndRename(acceptChanges); - RenameEnded(); - } - } - - void RenameEnded() - { - // We are done renaming (user accepted/rejected, we lost focus etc, other grabbed renameOverlay etc.) - string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name; - int instanceID = GetRenameOverlay().userData; // we passed in an instanceID as userData - - // Are we creating new asset? - if (GetCreateAssetUtility().IsCreatingNewAsset()) - { - if (GetRenameOverlay().userAcceptedRename) - GetCreateAssetUtility().EndNewAssetCreation(name); - } - else // renaming existing asset - { - if (GetRenameOverlay().userAcceptedRename) - { - ObjectNames.SetNameSmartWithInstanceID(instanceID, name); - } - } - - if (GetRenameOverlay().HasKeyboardFocus()) - GUIUtility.keyboardControl = m_KeyboardControlID; - - if (GetRenameOverlay().userAcceptedRename) - { - Frame(instanceID, true, false); // frames existing assets (new ones could have instanceID 0) - } - - ClearRenameState(); - } - - void ClearRenameState() - { - // Cleanup - GetRenameOverlay().Clear(); - GetCreateAssetUtility().Clear(); - m_State.m_NewAssetIndexInList = -1; - } - - internal void HandleRenameOverlay() - { - if (GetRenameOverlay().IsRenaming()) - { - GUIStyle renameStyle = (IsListMode() ? null : s_Styles.miniRenameField); - if (!GetRenameOverlay().OnGUI(renameStyle)) - { - RenameEnded(); - 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. - } - } - } - - public bool IsSelected(int instanceID) - { - return m_State.m_SelectedInstanceIDs.Contains(instanceID); - } - - public int[] GetSelection() - { - return m_State.m_SelectedInstanceIDs.ToArray(); - } - - public bool IsLastClickedItemVisible() - { - return GetSelectedAssetIdx() >= 0; - } - - public void SelectAll() - { - List list = m_LocalAssets.GetInstanceIDs(); - SetSelection(list.ToArray(), false); - } - - void SetSelection(int[] selectedInstanceIDs, bool doubleClicked) - { - InitSelection(selectedInstanceIDs); - - if (m_ItemSelectedCallback != null) - { - Repaint(); - m_ItemSelectedCallback(doubleClicked); - } - } - - public void InitSelection(int[] selectedInstanceIDs) - { - // Note that selectedInstanceIDs can be gameObjects - m_State.m_SelectedInstanceIDs = new List(selectedInstanceIDs); - - // Keep for debugging - //Debug.Log ("InitSelection (ObjectListArea): new selection " + DebugUtils.ListToString(m_State.m_SelectedInstanceIDs)); - - if (m_State.m_SelectedInstanceIDs.Count > 0) - { - // Only init last clicked instance if it is NOT part of our selection (we need it for navigation) - if (!m_State.m_SelectedInstanceIDs.Contains(m_State.m_LastClickedInstanceID)) - m_State.m_LastClickedInstanceID = m_State.m_SelectedInstanceIDs[m_State.m_SelectedInstanceIDs.Count - 1]; - } - else - { - m_State.m_LastClickedInstanceID = 0; - } - - - if (Selection.activeObject == null || Selection.activeObject.GetType() != typeof(AssetStoreAssetInspector)) - { - // Debug.Log("type is " + (Selection.activeObject == null ? "null " : Selection.activeObject.name) + " instance IDS "); - // foreach (int i in selectedInstanceIDs) - // { - // Debug.Log("selected instance ID " + i.ToString()); - // } - selectedAssetStoreAsset = false; - AssetStoreAssetSelection.Clear(); - } - } - - void SetSelection(AssetStoreAsset assetStoreResult, bool doubleClicked) - { - m_State.m_SelectedInstanceIDs.Clear(); - - selectedAssetStoreAsset = true; - AssetStoreAssetSelection.Clear(); // TODO: remove when multiselect is to be supported - AssetStorePreviewManager.CachedAssetStoreImage item = AssetStorePreviewManager.TextureFromUrl(assetStoreResult.staticPreviewURL, assetStoreResult.name, gridSize, s_Styles.resultsGridLabel, s_Styles.resultsGrid, true); - Texture2D lowresPreview = item.image; - AssetStoreAssetSelection.AddAsset(assetStoreResult, lowresPreview); - if (m_ItemSelectedCallback != null) - { - Repaint(); - m_ItemSelectedCallback(doubleClicked); - } - } - - void HandleZoomScrolling() - { - if (EditorGUI.actionKey && Event.current.type == EventType.ScrollWheel && m_TotalRect.Contains(Event.current.mousePosition)) - { - int sign = Event.current.delta.y > 0 ? -1 : 1; - gridSize = Mathf.Clamp(gridSize + sign * 7, minGridSize, maxGridSize); - - if (sign < 0 && gridSize < m_MinIconSize) - gridSize = m_MinGridSize; - if (sign > 0 && gridSize < m_MinIconSize) - gridSize = m_MinIconSize; - - Event.current.Use(); - GUI.changed = true; - } - } - - bool IsPreviewIconExpansionModifierPressed() - { - return Event.current.alt; - } - - bool AllowLeftRightArrowNavigation() - { - bool gridMode = !m_LocalAssets.ListMode && !IsPreviewIconExpansionModifierPressed(); - bool validItemCount = !m_ShowLocalAssetsOnly || (m_LocalAssets.ItemCount > 1); - return gridMode && validItemCount; - } - - public void HandleKeyboard(bool checkKeyboardControl) - { - // Are we allowed to handle keyboard events? - if (checkKeyboardControl && GUIUtility.keyboardControl != m_KeyboardControlID || !GUI.enabled) - return; - - // Let client handle keyboard first - if (m_KeyboardInputCallback != null) - m_KeyboardInputCallback(); - - // Now default list area handling - if (Event.current.type == EventType.KeyDown) - { - int offset = 0; - - if (IsLastClickedItemVisible()) - { - switch (Event.current.keyCode) - { - case KeyCode.UpArrow: - offset = -m_LocalAssets.m_Grid.columns; // we assume that all groups have same number of columns - break; - case KeyCode.DownArrow: - offset = m_LocalAssets.m_Grid.columns; - break; - case KeyCode.LeftArrow: - if (AllowLeftRightArrowNavigation()) - offset = -1; - break; - case KeyCode.RightArrow: - if (AllowLeftRightArrowNavigation()) - offset = 1; - break; - case KeyCode.PageUp: - offset = kPageUp; - break; - case KeyCode.PageDown: - offset = kPageDown; - break; - } - } - else - { - // Select first on any key navigation events if not selection is present - bool validNavigationKey = false; - switch (Event.current.keyCode) - { - case KeyCode.LeftArrow: - case KeyCode.RightArrow: - validNavigationKey = AllowLeftRightArrowNavigation(); - break; - - case KeyCode.UpArrow: - case KeyCode.DownArrow: - case KeyCode.PageUp: - case KeyCode.PageDown: - validNavigationKey = true; - break; - } - - if (validNavigationKey) - { - SelectFirst(); - Event.current.Use(); - } - } - - if (offset != 0) - { - // If nothing is selected then select first object and ignore the offset (when showing none GetSelectedAssetIdx return -1) - if (GetSelectedAssetIdx() < 0 && !m_LocalAssets.ShowNone) - SetSelectedAssetByIdx(0); - else - m_SelectionOffset = offset; - - Event.current.Use(); - GUI.changed = true; - } - else - { - if (allowFindNextShortcut && m_LocalAssets.DoCharacterOffsetSelection()) - Event.current.Use(); - } - } - } - - void DoOffsetSelectionSpecialKeys(int idx, int maxIndex) - { - float itemHeight = m_LocalAssets.m_Grid.itemSize.y + m_LocalAssets.m_Grid.verticalSpacing; - int columns = m_LocalAssets.m_Grid.columns; - - switch (m_SelectionOffset) - { - case kPageUp: - // on OSX paging only scrolls the scrollbar - if (Application.platform == RuntimePlatform.OSXEditor) - { - m_State.m_ScrollPosition.y -= m_TotalRect.height; - m_SelectionOffset = 0; - return; - } - else - { - m_SelectionOffset = -Mathf.RoundToInt(m_TotalRect.height / itemHeight) * columns; - // we want it to go to the very top row, but stay on same column - m_SelectionOffset = Mathf.Max(-Mathf.FloorToInt(idx / (float)columns) * columns, m_SelectionOffset); - } - break; - case kPageDown: - // on OSX paging only scrolls the scrollbar - if (Application.platform == RuntimePlatform.OSXEditor) - { - m_State.m_ScrollPosition.y += m_TotalRect.height; - m_SelectionOffset = 0; - return; - } - else - { - m_SelectionOffset = Mathf.RoundToInt(m_TotalRect.height / itemHeight) * columns; - // we want it to go to the very bottom row, but stay on same column - int remainingItems = maxIndex - idx; - m_SelectionOffset = Mathf.Min(Mathf.FloorToInt(remainingItems / (float)columns) * columns, m_SelectionOffset); - } - break; - case kHome: - m_SelectionOffset = 0; - SetSelectedAssetByIdx(0); // assumes that 'none' is the first item - return; - case kEnd: - m_SelectionOffset = maxIndex - idx; - break; - } - } - - void DoOffsetSelection() - { - if (m_SelectionOffset == 0) - return; - - int maxGridIndex = GetMaxIdx(); - if (maxGridSize == -1) - return; // no items - - int selectedAssetIdx = GetSelectedAssetIdx(); - selectedAssetIdx = selectedAssetIdx < 0 ? 0 : selectedAssetIdx; // default to first item - - DoOffsetSelectionSpecialKeys(selectedAssetIdx, maxGridIndex); - - // Special keys on some OSs will simply scroll and not change selection - if (m_SelectionOffset == 0) - return; - - int newGridIdx = selectedAssetIdx + m_SelectionOffset; - m_SelectionOffset = 0; - - // We ignore the offset if newIdx is less than 0 or clamp to item list length. - // This ensures that we stay on the same column at top or jump to the last item when navigating with keys. - if (newGridIdx < 0) - newGridIdx = selectedAssetIdx; - else - newGridIdx = Mathf.Min(newGridIdx, maxGridIndex); - - // If newIdx is on one of the two bottom rows we scroll to the bottom row because we might jump to another row - // when navigating (because the last row is half empty). This is a usability decision and can be removed. - int scrollGridIdx = newGridIdx; - //if (newGridIdx >= m_Columns * m_Rows - m_Columns * 2) - // scrollGridIdx = maxGridIndex + 2 * m_Columns; - - SetSelectedAssetByIdx(scrollGridIdx); - } - - public void OffsetSelection(int selectionOffset) - { - m_SelectionOffset = selectionOffset; - } - - public void SelectFirst() - { - int startIndex = 0; - if (m_ShowLocalAssetsOnly && m_LocalAssets.ShowNone && m_LocalAssets.ItemCount > 1) - startIndex = 1; - SetSelectedAssetByIdx(startIndex); - } - - public int GetInstanceIDByIndex(int index) - { - int instanceID; - if (m_LocalAssets.InstanceIdAtIndex(index, out instanceID)) - return instanceID; - return 0; - } - - void SetSelectedAssetByIdx(int selectedIdx) - { - // instanceID can be 0 if 'None' item is at index - int instanceID; - if (m_LocalAssets.InstanceIdAtIndex(selectedIdx, out instanceID)) - { - Rect r = m_LocalAssets.m_Grid.CalcRect(selectedIdx, 0f); - ScrollToPosition(AdjustRectForFraming(r)); - Repaint(); - - int[] newSelection; - if (IsLocalAssetsCurrentlySelected()) - newSelection = m_LocalAssets.GetNewSelection(instanceID, false, true).ToArray(); // Handle multi selection - else - newSelection = new[] {instanceID}; // If current selection is asset store asset do not allow multiselection - - SetSelection(newSelection, false); - m_State.m_LastClickedInstanceID = instanceID; - return; - } - - - selectedIdx -= m_LocalAssets.m_Grid.rows * m_LocalAssets.m_Grid.columns; - float offset = m_LocalAssets.Height; - - foreach (AssetStoreGroup g in m_StoreAssets) - { - if (!g.Visible) - { - offset += g.Height; - continue; - } - - AssetStoreAsset asset = g.AssetAtIndex(selectedIdx); - if (asset != null) - { - Rect r = g.m_Grid.CalcRect(selectedIdx, offset); - ScrollToPosition(AdjustRectForFraming(r)); - Repaint(); - SetSelection(asset, false); - break; - } - selectedIdx -= g.m_Grid.rows * g.m_Grid.columns; - offset += g.Height; - } - } - - void Reveal(int instanceID) - { - if (!AssetDatabase.Contains(instanceID)) - return; - - // We only show one level of subassets so just expand parent asset - int mainAssetInstanceID = AssetDatabase.GetMainAssetInstanceID(AssetDatabase.GetAssetPath(instanceID)); - bool isSubAsset = mainAssetInstanceID != instanceID; - if (isSubAsset) - m_LocalAssets.ChangeExpandedState(mainAssetInstanceID, true); - } - - // Frames only local assets - public bool Frame(int instanceID, bool frame, bool ping) - { - if (s_Styles == null) - s_Styles = new Styles(); - - int index = -1; - - // Check if it is an asset we are creating - if (GetCreateAssetUtility().IsCreatingNewAsset() && m_State.m_NewAssetIndexInList != -1) - if (GetCreateAssetUtility().instanceID == instanceID) - index = m_State.m_NewAssetIndexInList; - - // Ensure instanceID is visible - if (frame) - Reveal(instanceID); - - // Check local assets - if (index == -1) - index = m_LocalAssets.IndexOf(instanceID); - - if (index != -1) - { - if (frame) - { - float yOffset = 0f; - Rect r = m_LocalAssets.m_Grid.CalcRect(index, yOffset); - CenterRect(AdjustRectForFraming(r)); - Repaint(); - } - - if (ping) - BeginPing(instanceID); - return true; - } - - return false; - } - - int GetSelectedAssetIdx() - { - // Find index of selection - int offsetIdx = m_LocalAssets.IndexOf(m_State.m_LastClickedInstanceID); - if (offsetIdx != -1) - return offsetIdx; - - offsetIdx = m_LocalAssets.m_Grid.rows * m_LocalAssets.m_Grid.columns; - - // Project or builtin asset not selected. Check asset store asset. - if (AssetStoreAssetSelection.Count == 0) - return -1; - - AssetStoreAsset asset = AssetStoreAssetSelection.GetFirstAsset(); - if (asset == null) - return -1; - int assetID = asset.id; - - foreach (AssetStoreGroup g in m_StoreAssets) - { - if (!g.Visible) - continue; - - int idx = g.IndexOf(assetID); - if (idx != -1) - return offsetIdx + idx; - - offsetIdx += g.m_Grid.rows * g.m_Grid.columns; - } - - return -1; - } - - bool SkipGroup(Group group) - { - // We either show local assets or asset store results here - if (m_ShowLocalAssetsOnly) - { - if (group is AssetStoreGroup) - return true; - } - else - { - if (group is LocalGroup) - return true; - } - - return false; - } - - int GetMaxIdx() - { - int groupLastIdx = 0; - int groupSizesAccumulated = 0; - int lastGroupSize = 0; - - foreach (Group g in m_Groups) - { - if (SkipGroup(g)) - continue; - - if (!g.Visible) - continue; - - groupSizesAccumulated += lastGroupSize; - lastGroupSize = g.m_Grid.rows * g.m_Grid.columns; - groupLastIdx = g.ItemCount - 1; - } - int max = groupSizesAccumulated + groupLastIdx; - return (lastGroupSize + max) == 0 ? -1 : max; - } - - bool IsLocalAssetsCurrentlySelected() - { - int currentSelectedInstanceID = m_State.m_SelectedInstanceIDs.FirstOrDefault(); - if (currentSelectedInstanceID != 0) - { - int index = m_LocalAssets.IndexOf(currentSelectedInstanceID); - return index != -1; - } - - return false; - } - - private void SetupData(bool forceReflow) - { - // Make sure the groups contains the correct assets to show - foreach (Group g in m_Groups) - { - if (SkipGroup(g)) - continue; - g.UpdateAssets(); - } - - if (forceReflow || Event.current.type == EventType.Repaint) - { - // Reflow according to number of items, scrollbar presence, item dims etc. - Reflow(); - } - } - - bool IsObjectSelector() - { - // ShowNone is only used in object select window - return m_LocalAssets.ShowNone; - } - - void HandleListArea() - { - SetupData(false); - - // Requery the Asset Store to get more assets if content area has changed size - // so that more assets fits in there. - - // We don't want asset store asset in the object selector - if (!IsObjectSelector() && !m_QueryInProgress) - { - bool needItems = m_StoreAssets.Exists(g => g.NeedItems); - if (needItems || m_RequeryAssetStore) - { - QueryAssetStore(); // need more data to fill required rows with asset store assets - } - } - - // Figure out height needed to contain all assets - float totalContentsHeight = 0f; - foreach (Group g in m_Groups) - { - if (SkipGroup(g)) - continue; - - totalContentsHeight += g.Height; - - // ShowNone is only used in object select window and we don't want asset store asset there - if (m_LocalAssets.ShowNone) - break; - } - - Rect scrollRect = m_TotalRect; - Rect contentRect = new Rect(0, 0, 1, totalContentsHeight); - bool scrollBarVisible = totalContentsHeight > m_TotalRect.height; - - m_VisibleRect = m_TotalRect; - if (scrollBarVisible) - m_VisibleRect.width -= kSpaceForScrollBar; - - - double timeNow = EditorApplication.timeSinceStartup; - m_LastScrollPosition = m_State.m_ScrollPosition; - - bool needRepaint = false; - m_State.m_ScrollPosition = GUI.BeginScrollView(scrollRect, m_State.m_ScrollPosition, contentRect); - { - Vector2 scrollPos = m_State.m_ScrollPosition; // Copy scroll pos since the draw calls may change it - - if (m_LastScrollPosition != m_State.m_ScrollPosition) - LastScrollTime = timeNow; - - float yOffset = 0f; - int rowsBeingUsed = 0; - foreach (Group g in m_Groups) - { - if (SkipGroup(g)) - continue; - - // rect contains the offset rect where the group should draw - g.Draw(yOffset, scrollPos, ref rowsBeingUsed); - needRepaint = needRepaint || g.NeedsRepaint; - yOffset += g.Height; - - // ShowNone is only used in object select window and we don't want asset store asset there - if (m_LocalAssets.ShowNone) - break; - } - - HandlePing(); - if (needRepaint) - Repaint(); - } GUI.EndScrollView(); - - - // We delay this resizing of cache until after the resized grid has been - // draw in order to let the cache have the correct lastUsed timestamps on the - // cached images. This is important when the cache is decreased in order not - // to dispose the wrong cache entries - if (m_ResizePreviewCacheTo > 0 && AssetStorePreviewManager.MaxCachedImages != m_ResizePreviewCacheTo) - AssetStorePreviewManager.MaxCachedImages = m_ResizePreviewCacheTo; - - if (Event.current.type == EventType.Repaint) - AssetStorePreviewManager.AbortOlderThan(timeNow); - - if (!m_ShowLocalAssetsOnly && !string.IsNullOrEmpty(m_AssetStoreError)) - { - Vector2 size = EditorStyles.label.CalcSize(s_Styles.m_AssetStoreNotAvailableText); - Rect textRect = new Rect(m_TotalRect.x + 2f + Mathf.Max(0, (m_TotalRect.width - size.x) * 0.5f), m_TotalRect.y + 10f, size.x, 20f); - using (new EditorGUI.DisabledScope(true)) - { - GUI.Label(textRect, s_Styles.m_AssetStoreNotAvailableText, EditorStyles.label); - } - } - } - - bool IsListMode() - { - if (allowMultiSelect) - return (gridSize == kListLineHeight); // ProjectBrowser (should auto change layout on content but entirely user controlled) - else - return (gridSize == kListLineHeight) || !CanShowThumbnails(); // ObjectSelector - } - - void Reflow() - { - if (gridSize < 20) - gridSize = m_MinGridSize; - else if (gridSize < m_MinIconSize) - gridSize = m_MinIconSize; - - // We're in list mode. - if (IsListMode()) - { - foreach (Group g in m_Groups) - { - if (SkipGroup(g)) - continue; - - g.ListMode = true; - UpdateGroupSizes(g); - - // ShowNone is only used in object select window and we don't want aiy sset store asset there - if (m_LocalAssets.ShowNone) - break; - } - - m_ResizePreviewCacheTo = Mathf.CeilToInt((float)m_TotalRect.height / kListLineHeight) + 10; - } - // we're in thumbnail mode - else - { - // Grid without scrollbar - float totalHeight = 0; - foreach (Group g in m_Groups) - { - if (SkipGroup(g)) - continue; - - g.ListMode = false; - UpdateGroupSizes(g); - - totalHeight += g.Height; - - // ShowNone is only used in object select window and we don't want asset store asset there - if (m_LocalAssets.ShowNone) - break; - } - - // Grid with scrollbar - bool scrollbarVisible = m_TotalRect.height < totalHeight; - if (scrollbarVisible) - { - // Make room for the scrollbar - foreach (Group g in m_Groups) - { - if (SkipGroup(g)) - continue; - - g.m_Grid.fixedWidth = m_TotalRect.width - kSpaceForScrollBar; - g.m_Grid.InitNumRowsAndColumns(g.ItemCount, g.m_Grid.CalcRows(g.ItemsWantedShown)); - g.UpdateHeight(); - - // ShowNone is only used in object select window and we don't want asset store asset there - if (m_LocalAssets.ShowNone) - break; - } - } - - int maxVisibleItems = GetMaxNumVisibleItems(); - - m_ResizePreviewCacheTo = maxVisibleItems * 2; - - AssetPreview.SetPreviewTextureCacheSize(maxVisibleItems * 2 + 30, GetAssetPreviewManagerID()); - } - } - - void UpdateGroupSizes(Group g) - { - if (g.ListMode) - { - g.m_Grid.fixedWidth = m_VisibleRect.width; - g.m_Grid.itemSize = new Vector2(m_VisibleRect.width, kListLineHeight); - g.m_Grid.topMargin = 0f; - g.m_Grid.bottomMargin = 0f; - g.m_Grid.leftMargin = 0f; - g.m_Grid.rightMargin = 0f; - g.m_Grid.verticalSpacing = 0f; - g.m_Grid.minHorizontalSpacing = 0f; - g.m_Grid.InitNumRowsAndColumns(g.ItemCount, g.ItemsWantedShown); - - g.UpdateHeight(); - } - else - { - g.m_Grid.fixedWidth = m_TotalRect.width; - g.m_Grid.itemSize = new Vector2(gridSize, gridSize + 14); - g.m_Grid.topMargin = 10f; - g.m_Grid.bottomMargin = 10f; - g.m_Grid.leftMargin = 10f; - g.m_Grid.rightMargin = 10f; - g.m_Grid.verticalSpacing = 15f; - g.m_Grid.minHorizontalSpacing = 12f; - g.m_Grid.InitNumRowsAndColumns(g.ItemCount, g.m_Grid.CalcRows(g.ItemsWantedShown)); - - g.UpdateHeight(); - } - } - - int GetMaxNumVisibleItems() - { - foreach (Group g in m_Groups) - { - if (SkipGroup(g)) - continue; - - return g.m_Grid.GetMaxVisibleItems(m_TotalRect.height); - } - - Assert.IsTrue(false, "Unhandled group"); - return 0; - } - - static Rect AdjustRectForFraming(Rect r) - { - r.height += (s_Styles.resultsGridLabel.fixedHeight * 2); - r.y -= s_Styles.resultsGridLabel.fixedHeight; - return r; - } - - void CenterRect(Rect r) - { - float middle = (r.yMax + r.yMin) / 2; - float middleVisibleRect = m_TotalRect.height / 2; - - m_State.m_ScrollPosition.y = middle - middleVisibleRect; - - // Ensure clamped - ScrollToPosition(r); - } - - void ScrollToPosition(Rect r) - { - float top = r.y; - float bottom = r.yMax; - float viewHeight = m_TotalRect.height; - - if (bottom > viewHeight + m_State.m_ScrollPosition.y) - { - m_State.m_ScrollPosition.y = bottom - viewHeight; - } - if (top < m_State.m_ScrollPosition.y) - { - m_State.m_ScrollPosition.y = top; - } - - m_State.m_ScrollPosition.y = Mathf.Max(m_State.m_ScrollPosition.y, 0f); - } - - public void OnInspectorUpdate() - { - if (EditorApplication.timeSinceStartup > m_NextDirtyCheck && m_LocalAssets.IsAnyLastRenderedAssetsDirty()) - { - // If an asset is dirty we ensure to get a updated preview by clearing cache of temporary previews - AssetPreview.ClearTemporaryAssetPreviews(); - Repaint(); - m_NextDirtyCheck = EditorApplication.timeSinceStartup + 0.77; - } - - if (AssetStorePreviewManager.CheckRepaint()) - Repaint(); - } - - void ClearCroppedLabelCache() - { - m_InstanceIDToCroppedNameMap.Clear(); - } - - protected string GetCroppedLabelText(int instanceID, string fullText, float cropWidth) - { - // Clear when width changes - if (m_WidthUsedForCroppingName != (int)cropWidth) - ClearCroppedLabelCache(); - - string croppedText; - if (!m_InstanceIDToCroppedNameMap.TryGetValue(instanceID, out croppedText)) - { - // Ensure to clean up once in a while - if (m_InstanceIDToCroppedNameMap.Count > GetMaxNumVisibleItems() * 2 + 30) - ClearCroppedLabelCache(); - - // Check if we need to crop - int characterCountVisible = s_Styles.resultsGridLabel.GetNumCharactersThatFitWithinWidth(fullText, cropWidth); - if (characterCountVisible == -1) - { - Repaint(); - return fullText; // failed: do not cache result - } - - if (characterCountVisible > 1 && characterCountVisible != fullText.Length) - croppedText = fullText.Substring(0, characterCountVisible - 1) + ("\u2026"); // 'horizontal ellipsis' (U+2026) is: ... - else - croppedText = fullText; - - m_InstanceIDToCroppedNameMap[instanceID] = croppedText; - m_WidthUsedForCroppingName = (int)cropWidth; - } - return croppedText; - } - - public bool IsShowing(int instanceID) - { - return m_LocalAssets.IndexOf(instanceID) >= 0; - } - - public bool IsShowingAny(int[] instanceIDs) - { - if (instanceIDs.Length == 0) - return false; - - foreach (int instanceID in instanceIDs) - if (IsShowing(instanceID)) - return true; - - return false; - } - - protected Texture GetIconByInstanceID(int instanceID) - { - Texture icon = null; - if (instanceID != 0) - { - string path = AssetDatabase.GetAssetPath(instanceID); - icon = AssetDatabase.GetCachedIcon(path); - } - return icon; - } - - internal int GetAssetPreviewManagerID() - { - return m_Owner.GetInstanceID(); - } - - // Pings only local assets - public void BeginPing(int instanceID) - { - if (s_Styles == null) - s_Styles = new Styles(); - - // Check local assets - int index = m_LocalAssets.IndexOf(instanceID); - - if (index != -1) - { - string name = null; - HierarchyProperty hierarchyProperty = new HierarchyProperty(HierarchyType.Assets); - if (hierarchyProperty.Find(instanceID, null)) - { - name = hierarchyProperty.name; - } - if (name == null) - return; - - m_Ping.m_TimeStart = Time.realtimeSinceStartup; - m_Ping.m_AvailableWidth = m_VisibleRect.width; - m_pingIndex = index; - - float vcPadding = s_VCEnabled ? k_ListModeVersionControlOverlayPadding : 0f; - - GUIContent cont = new GUIContent(m_LocalAssets.ListMode ? name : GetCroppedLabelText(instanceID, name, m_WidthUsedForCroppingName)); - string label = cont.text; - - if (m_LocalAssets.ListMode) - { - const float iconWidth = 16; - m_Ping.m_PingStyle = s_Styles.ping; - Vector2 pingLabelSize = m_Ping.m_PingStyle.CalcSize(cont); - m_Ping.m_ContentRect.width = pingLabelSize.x + vcPadding + iconWidth; - m_Ping.m_ContentRect.height = pingLabelSize.y; - m_LeftPaddingForPinging = hierarchyProperty.isMainRepresentation ? LocalGroup.k_ListModeLeftPadding : LocalGroup.k_ListModeLeftPaddingForSubAssets; - FilteredHierarchy.FilterResult res = m_LocalAssets.LookupByInstanceID(instanceID); - m_Ping.m_ContentDraw = (Rect r) => - { - ObjectListArea.LocalGroup.DrawIconAndLabel(r, res, label, hierarchyProperty.icon, false, false); - }; - } - else - { - m_Ping.m_PingStyle = s_Styles.miniPing; - Vector2 pingLabelSize = m_Ping.m_PingStyle.CalcSize(cont); - m_Ping.m_ContentRect.width = pingLabelSize.x; - m_Ping.m_ContentRect.height = pingLabelSize.y; - m_Ping.m_ContentDraw = (Rect r) => - { - // We need to temporary adjust style to render into content rect (org anchor is middle-centered) - TextAnchor orgAnchor = s_Styles.resultsGridLabel.alignment; - s_Styles.resultsGridLabel.alignment = TextAnchor.UpperLeft; - s_Styles.resultsGridLabel.Draw(r, label, false, false, false, false); - s_Styles.resultsGridLabel.alignment = orgAnchor; - }; - } - Vector2 pos = CalculatePingPosition(); - m_Ping.m_ContentRect.x = pos.x; - m_Ping.m_ContentRect.y = pos.y; - - Repaint(); - } - } - - public void EndPing() - { - m_Ping.m_TimeStart = -1f; - } - - void HandlePing() - { - // We need to update m_Ping.m_ContentTopLeft in icon mode. The position might change if user resizes the window while pinging - if (m_Ping.isPinging && !m_LocalAssets.ListMode) - { - Vector2 pos = CalculatePingPosition(); - m_Ping.m_ContentRect.x = pos.x; - m_Ping.m_ContentRect.y = pos.y; - } - m_Ping.HandlePing(); - - if (m_Ping.isPinging) - Repaint(); - } - - Vector2 CalculatePingPosition() - { - Rect gridRect = m_LocalAssets.m_Grid.CalcRect(m_pingIndex, 0f); - - if (m_LocalAssets.ListMode) - { - return new Vector2(m_LeftPaddingForPinging, gridRect.y); - } - else - { - // TODO: Find out why Y offset 3 is needed - float width = m_Ping.m_ContentRect.width; - return new Vector2(gridRect.center.x - width / 2f + m_Ping.m_PingStyle.padding.left, gridRect.yMax - s_Styles.resultsGridLabel.fixedHeight + 3); - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ObjectListAssetStoreGroup.cs b/Editor/Mono/ObjectListAssetStoreGroup.cs deleted file mode 100644 index b1cc0b238e..0000000000 --- a/Editor/Mono/ObjectListAssetStoreGroup.cs +++ /dev/null @@ -1,353 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Math = System.Math; -using IndexOutOfRangeException = System.IndexOutOfRangeException; - - -namespace UnityEditor -{ - internal partial class ObjectListArea - { - class AssetStoreGroup : Group - { - public const int kDefaultRowsShown = 3; - public const int kDefaultRowsShownListMode = 10; - const int kMoreButtonOffset = 3; - const int kMoreRowsAdded = 10; - const int kMoreRowsAddedListMode = 75; - const int kMaxQueryItems = 1000; // Max items allowed to query for by backend - - GUIContent m_Content = new GUIContent(); - List m_Assets; - string m_Name; - bool m_ListMode; - Vector3 m_ShowMoreDims; - - public string Name { get { return m_Name; } } - public List Assets { get { return m_Assets; } set { m_Assets = value; } } - public override int ItemCount { get { return Math.Min(m_Assets.Count, ItemsWantedShown); } } - public override bool ListMode - { - get { return m_ListMode; } - set { m_ListMode = value; } - } - - public bool NeedItems - { - get - { - // Clamp to 1000 items since that is what the backend supports - int wantedItems = Math.Min(kMaxQueryItems, ItemsWantedShown); - int gotItems = Assets.Count; - return (ItemsAvailable >= wantedItems && gotItems < wantedItems) || - (ItemsAvailable < wantedItems && gotItems < ItemsAvailable); - } - } - - public override bool NeedsRepaint { get; protected set; } - - public AssetStoreGroup(ObjectListArea owner, string groupTitle, string groupName) : base(owner, groupTitle) - { - m_Assets = new List(); - m_Name = groupName; - m_ListMode = false; - m_ShowMoreDims = EditorStyles.miniButton.CalcSize(EditorGUIUtility.TrTextContent("Show more")); - m_Owner.UpdateGroupSizes(this); - ItemsWantedShown = kDefaultRowsShown * m_Grid.columns; - } - - public override void UpdateAssets() - { - } - - protected override void DrawInternal(int itemIdx, int endItem, float yOffset) - { - int endContainerItem = m_Assets.Count; - int startItemIdx = itemIdx; - - // The seperator bar is drawn before all items - yOffset += kGroupSeparatorHeight; - - bool isRepaintEvent = Event.current.type == EventType.Repaint; - - Rect r; - - if (ListMode) - { - // Draw row - //position.width = Mathf.Max (position.width, 500); // For some reason the icon is clipped if the rect cannot contain both the text and icon so make sure its large - for (; itemIdx < endItem && itemIdx < endContainerItem; itemIdx++) - { - r = m_Grid.CalcRect(itemIdx, yOffset); - // Mouse event handling - int clicks = HandleMouse(r); - if (clicks != 0) - m_Owner.SetSelection(m_Assets[itemIdx], clicks == 2); - - if (isRepaintEvent) - { - bool selected = !AssetStoreAssetSelection.Empty && AssetStoreAssetSelection.ContainsAsset(m_Assets[itemIdx].id); - DrawLabel(r, m_Assets[itemIdx], selected); - } - } - } - else - { - // First loop over assets to draw icons and the loop again to - // draw labels. Two loops in order to get rid of too many - // expensive setShader calls. - for (; itemIdx < endItem && itemIdx < endContainerItem; itemIdx++) - { - r = m_Grid.CalcRect(itemIdx, yOffset); - - // Label has selection visuals now (keep below) - // bool selected = !AssetStoreAssetSelection.Empty && AssetStoreAssetSelection.ContainsAsset (m_Assets[itemIdx].id); - // bool selected = false; - - // Mouse event handling - int clicks = HandleMouse(r); - if (clicks != 0) - m_Owner.SetSelection(m_Assets[itemIdx], clicks == 2); - - if (isRepaintEvent) - { - Rect position = new Rect(r.x, r.y, r.width, r.height - s_Styles.resultsGridLabel.fixedHeight); - DrawIcon(position, m_Assets[itemIdx]); - } - } - itemIdx = startItemIdx; - - // Labels - if (isRepaintEvent) - { - for (; itemIdx < endItem && itemIdx < endContainerItem; itemIdx++) - { - r = m_Grid.CalcRect(itemIdx, yOffset); - bool selected = !AssetStoreAssetSelection.Empty && AssetStoreAssetSelection.ContainsAsset(m_Assets[itemIdx].id); - DrawLabel(r, m_Assets[itemIdx], selected); - } - } - } - - // "Show more" button if more asset can by found in asset store - if (ItemsAvailable <= (m_Grid.rows * m_Grid.columns)) - return; // no more items to fetch from A$ server - - r = new Rect(m_Owner.GetVisibleWidth() - m_ShowMoreDims.x - 6, - yOffset + m_Grid.height + kMoreButtonOffset, - m_ShowMoreDims.x, - m_ShowMoreDims.y); - - if (ItemsAvailable > (m_Grid.rows * m_Grid.columns) && - ItemsAvailable >= Assets.Count && - Assets.Count < kMaxQueryItems) - { - Event evt = Event.current; - switch (evt.type) - { - case EventType.MouseDown: - if (evt.button == 0 && r.Contains(evt.mousePosition)) - { - if (ListMode) - { - ItemsWantedShown += kMoreRowsAddedListMode; - } - else - { - // Try to make sure that we have full rows of preview - // after the update. Partly filled rows can occur when resizing the - // listarea or when we reached the limit of results from server. - int itemsNeededToFillLastRow = m_Grid.columns - (ItemCount % m_Grid.columns); - itemsNeededToFillLastRow = itemsNeededToFillLastRow % m_Grid.columns; - ItemsWantedShown += (kMoreRowsAdded * m_Grid.columns) + itemsNeededToFillLastRow; - } - if (NeedItems) // Check that we need to fetch it since we might already have it prefetched - m_Owner.QueryAssetStore(); - evt.Use(); - } - break; - case EventType.Repaint: - { - EditorStyles.miniButton.Draw(r, "More", false, false, false, false); - } - break; - } - } - } - - AssetStorePreviewManager.CachedAssetStoreImage GetIconForAssetStoreAsset(AssetStoreAsset assetStoreResource) - { - if (!string.IsNullOrEmpty(assetStoreResource.staticPreviewURL)) - { - m_Owner.LastScrollTime++; - AssetStorePreviewManager.CachedAssetStoreImage item = AssetStorePreviewManager.TextureFromUrl(assetStoreResource.staticPreviewURL, assetStoreResource.name, m_Owner.gridSize, s_Styles.resultsGridLabel, s_Styles.previewBg, false); - return item; - } - - return null; - } - - void DrawIcon(Rect position, AssetStoreAsset assetStoreResource) - { - // bool selected = !AssetStoreAssetSelection.Empty && AssetStoreAssetSelection.ContainsAsset (assetStoreResource.id); - bool selected = false; // labels have selection rendering only - - m_Content.text = null; - - AssetStorePreviewManager.CachedAssetStoreImage icon = GetIconForAssetStoreAsset(assetStoreResource); - - if (icon == null) - { - // Draw static preview bg color as bg for icons that do not fill the entire rect (mini icons and non-square textures) - // s_Styles.previewBg.Draw (position, GUIContent.none, false, false, false, false); - - // Use builtin type icon - Texture2D iconImage = InternalEditorUtility.GetIconForFile(assetStoreResource.name); - s_Styles.resultsGrid.Draw(position, iconImage, false, false, selected, selected); - } - else - { - // Fade in - m_Content.image = icon.image; - Color c = icon.color; - Color oldColor = GUI.color; - if (c.a != 1.0f) - GUI.color = c; - s_Styles.resultsGrid.Draw(position, m_Content, false, false, selected, selected); - if (c.a != 1.0f) - { - GUI.color = oldColor; - // The icon is not entirely faded in yet. Schedule a repaint - NeedsRepaint = true; - } - - DrawDropShadowOverlay(position, selected, false, false); - } - } - - void DrawLabel(Rect position, AssetStoreAsset assetStoreResource, bool selected) - { - if (ListMode) - { - position.width = Mathf.Max(position.width, 500); // For some reason the icon is clipped if the rect cannot contain both the text and icon so make sure its large - m_Content.text = assetStoreResource.displayName; - - // For now disable drawing preview icons in list mode since it looks wrong because of the dark background on - // preview images. - m_Content.image = InternalEditorUtility.GetIconForFile(assetStoreResource.name); - - s_Styles.resultsLabel.Draw(position, m_Content, false, false, selected, selected); - } - else - { - // We crop the text in Preview mode - int pseudoInstanceID = assetStoreResource.id + 10000000; // we add a large offset to the asset store id to ensure there is no overlap with instanceIDs - string labeltext = m_Owner.GetCroppedLabelText(pseudoInstanceID, assetStoreResource.displayName, position.width); - position.height -= s_Styles.resultsGridLabel.fixedHeight; - // The -1 is to ensure the label has same width as the image and that it aligns with the bottom of the image - s_Styles.resultsGridLabel.Draw(new Rect(position.x, position.yMax + 1, position.width - 1, - s_Styles.resultsGridLabel.fixedHeight), labeltext, - false, false, selected, m_Owner.HasFocus()); - } - } - - public override void UpdateFilter(HierarchyType hierarchyType, SearchFilter searchFilter, bool showFoldersFirst) - { - ItemsWantedShown = ListMode ? kDefaultRowsShownListMode : (kDefaultRowsShown * m_Grid.columns); - Assets.Clear(); - } - - public override void UpdateHeight() - { - // We always show the seperator bar - m_Height = (int)kGroupSeparatorHeight; - - if (!Visible) - return; - - m_Height += m_Grid.height; - - if (ItemsAvailable <= (m_Grid.rows * m_Grid.columns)) - return; // no more items to fetch from A$ server - - m_Height += kMoreButtonOffset * 2 + (int)m_ShowMoreDims.y; - } - - public int IndexOf(int assetID) - { - int idx = 0; - foreach (AssetStoreAsset a in m_Assets) - { - if (a.id == assetID) - return idx; - idx++; - } - return -1; - } - - public AssetStoreAsset AssetAtIndex(int selectedIdx) - { - if (selectedIdx >= m_Grid.rows * m_Grid.columns) - return null; - if (selectedIdx < m_Grid.rows * m_Grid.columns && selectedIdx > ItemCount) - return m_Assets.Last(); - - int idx = 0; - foreach (AssetStoreAsset a in m_Assets) - { - if (selectedIdx == idx) - return a; - idx++; - } - - return null; - } - - // Handle mouse events for rect and return number of clicks - protected int HandleMouse(Rect position) - { - Event evt = Event.current; - - switch (evt.type) - { - case EventType.MouseDown: - // handle selection of the item - if (evt.button == 0 && position.Contains(evt.mousePosition)) - { - // we've actually clicked the item - m_Owner.Repaint(); - - if (evt.clickCount == 2) - { - evt.Use(); - return 2; - } - else - { - m_Owner.ScrollToPosition(ObjectListArea.AdjustRectForFraming(position)); - evt.Use(); - return 1; - } - } - break; - case EventType.ContextClick: - if (position.Contains(evt.mousePosition)) - { - //evt.Use(); // We do not use the event this should be handled by client - return 1; - } - break; - } - return 0; - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ObjectListGroup.cs b/Editor/Mono/ObjectListGroup.cs deleted file mode 100644 index 62b19915ce..0000000000 --- a/Editor/Mono/ObjectListGroup.cs +++ /dev/null @@ -1,283 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Math = System.Math; -using IndexOutOfRangeException = System.IndexOutOfRangeException; - - -namespace UnityEditor -{ - internal partial class ObjectListArea - { - /* Abstract base class for each group of assets (e.g. Local, AssetStore) used in the ObjectListArea - */ - abstract class Group - { - readonly protected float kGroupSeparatorHeight = EditorStyles.toolbar.fixedHeight; - protected string m_GroupSeparatorTitle; - - protected static int[] s_Empty; - public ObjectListArea m_Owner; - public VerticalGrid m_Grid = new VerticalGrid(); - public float m_Height; - - public float Height { get { return m_Height; } } - abstract public int ItemCount { get; } - abstract public bool ListMode { get; set; } - abstract public bool NeedsRepaint { get; protected set; } - - public bool Visible = true; // Visibility toggled in GUI - public int ItemsAvailable = 0; // Calculated from total asset count - public int ItemsWantedShown = 0; // Rows requested to be displayed - protected bool m_Collapsable = true; - public double m_LastClickedDrawTime = 0; - - public Group(ObjectListArea owner, string groupTitle) - { - m_GroupSeparatorTitle = groupTitle; - if (s_Empty == null) - s_Empty = new int[0]; - m_Owner = owner; - Visible = visiblePreference; - } - - public bool visiblePreference - { - get - { - if (string.IsNullOrEmpty(m_GroupSeparatorTitle)) - return true; - return EditorPrefs.GetBool(m_GroupSeparatorTitle, true); - } - set - { - if (string.IsNullOrEmpty(m_GroupSeparatorTitle)) - return; - EditorPrefs.SetBool(m_GroupSeparatorTitle, value); - } - } - - - // Called before repaints in order to prepare internal assets for rendering - abstract public void UpdateAssets(); - - // Called when height of this group should be recalculated - abstract public void UpdateHeight(); - - abstract protected void DrawInternal(int itemIdx, int endItem, float yOffset); - - // Called when the filter has changed - abstract public void UpdateFilter(HierarchyType hierarchyType, SearchFilter searchFilter, bool showFoldersFirst); - - protected virtual float GetHeaderHeight() - { - return kGroupSeparatorHeight; - } - - protected virtual void HandleUnusedDragEvents(float yOffset) {} - - int FirstVisibleRow(float yOffset, Vector2 scrollPos) - { - if (!Visible) - return -1; - - // Skip rows that is outside the offset rect - float yRelOffset = scrollPos.y - (yOffset + GetHeaderHeight()); - - int invisibleRows = 0; - if (yRelOffset > 0f) - { - // Initial rows hidden - float itemHeight = m_Grid.itemSize.y + m_Grid.verticalSpacing; - invisibleRows = (int)Mathf.Max(0, Mathf.Floor(yRelOffset / itemHeight)); - } - return invisibleRows; - } - - bool IsInView(float yOffset, Vector2 scrollPos, float scrollViewHeight) - { - if ((scrollPos.y + scrollViewHeight) < yOffset) - return false; // after visible area - - if ((yOffset + Height) < scrollPos.y) - return false; // before visible area - - return true; - } - - // Main draw method of a group that is called from outside - public void Draw(float yOffset, Vector2 scrollPos, ref int rowsInUse) - { - NeedsRepaint = false; - - // We need to always draw the header as it uses controlIDs (and we cannot cull gui elements using controlID) - bool isRepaint = Event.current.type == EventType.Repaint || Event.current.type == EventType.Layout; - - if (!isRepaint) - DrawHeader(yOffset, m_Collapsable); // logic here, draw on top below - - if (!IsInView(yOffset, scrollPos, m_Owner.m_VisibleRect.height)) - return; - - int invisibleRows = FirstVisibleRow(yOffset, scrollPos); - int beginItem = invisibleRows * m_Grid.columns; - int totalItemCount = ItemCount; - if (beginItem >= 0 && beginItem < totalItemCount) - { - int itemIdx = beginItem; - // Limit by items avail and max items to show - // (plus an extra row to allow half a row in top and bottom at the same time) - int endItem = Math.Min(totalItemCount, m_Grid.rows * m_Grid.columns); - - // Also limit to what can possible be in view in order to limit draws - float itemHeight = m_Grid.itemSize.y + m_Grid.verticalSpacing; - int rowsInVisibleRect = (int)Math.Ceiling(m_Owner.m_VisibleRect.height / itemHeight); - - //When a row is hidden behind the header, it is still counted as visible, therefore to avoid - //weird popping in and out for the icons, we make sure that a new row will be rendered even if one - //is considered visible, even though it cannot be seen in the window - rowsInVisibleRect += 1; - - int rowsNotInUse = rowsInVisibleRect - rowsInUse; - if (rowsNotInUse < 0) - rowsNotInUse = 0; - - rowsInUse = Math.Min(rowsInVisibleRect, Mathf.CeilToInt((endItem - beginItem) / (float)m_Grid.columns)); - - endItem = rowsNotInUse * m_Grid.columns + beginItem; - if (endItem > totalItemCount) - endItem = totalItemCount; - - DrawInternal(itemIdx, endItem, yOffset); - } - - if (isRepaint) - DrawHeader(yOffset, m_Collapsable); - - // Always handle drag events in the case where we have no items we still want to be able to drag into the group. - HandleUnusedDragEvents(yOffset); - } - - protected void DrawObjectIcon(Rect position, Texture icon) - { - if (icon == null) - return; - - int size = icon.width; - - FilterMode temp = icon.filterMode; - icon.filterMode = FilterMode.Point; - GUI.DrawTexture(new Rect(position.x + ((int)position.width - size) / 2, position.y + ((int)position.height - size) / 2, size, size), icon, ScaleMode.ScaleToFit); - icon.filterMode = temp; - } - - protected void DrawDropShadowOverlay(Rect position, bool selected, bool isDropTarget, bool isRenaming) - { - // Draw dropshadow overlay - float fraction = position.width / 128f; - Rect dropShadowRect = new Rect(position.x - 4 * fraction, position.y - 2 * fraction, position.width + 8 * fraction, position.height + 12 * fraction - 0.5f); - s_Styles.iconDropShadow.Draw(dropShadowRect, GUIContent.none, false, false, selected || isDropTarget, m_Owner.HasFocus() || isRenaming || isDropTarget); - } - - protected void DrawHeaderBackground(Rect rect, bool firstHeader) - { - if (Event.current.type != EventType.Repaint) - return; - - // Draw the group bar background - GUI.Label(rect, GUIContent.none, firstHeader ? s_Styles.groupHeaderTop : s_Styles.groupHeaderMiddle); - } - - protected float GetHeaderYPosInScrollArea(float yOffset) - { - float y = yOffset; - float yScrollPos = m_Owner.m_State.m_ScrollPosition.y; - if (yScrollPos > yOffset) - { - y = Mathf.Min(yScrollPos, yOffset + Height - kGroupSeparatorHeight); - } - return y; - } - - virtual protected void DrawHeader(float yOffset, bool collapsable) - { - const int foldoutSpacing = 3; - Rect rect = new Rect(0, GetHeaderYPosInScrollArea(yOffset), m_Owner.GetVisibleWidth(), kGroupSeparatorHeight - 1); - - DrawHeaderBackground(rect, yOffset == 0); - - // Draw the group toggle - rect.x += 7; - if (collapsable) - { - bool oldVisible = Visible; - Visible = GUI.Toggle(rect, Visible, GUIContent.none, s_Styles.groupFoldout); - if (oldVisible ^ Visible) - visiblePreference = Visible; - } - - // Draw title - GUIStyle textStyle = s_Styles.groupHeaderLabel; - if (collapsable) - rect.x += s_Styles.groupFoldout.fixedWidth + foldoutSpacing; - rect.y += 1; - if (!string.IsNullOrEmpty(m_GroupSeparatorTitle)) - GUI.Label(rect, m_GroupSeparatorTitle, textStyle); - - if (s_Debug) - { - Rect r2 = rect; - r2.x += 120; - GUI.Label(r2, AssetStorePreviewManager.StatsString()); - } - - rect.y -= 1; - - // Only draw counts if we have room for it - if (m_Owner.GetVisibleWidth() > 150) - DrawItemCount(rect); - } - - protected void DrawItemCount(Rect rect) - { - // Draw item count in group - const float rightMargin = 4f; - - string label = ItemsAvailable.ToString() + " Total"; - Vector2 labelDims = s_Styles.groupHeaderLabelCount.CalcSize(new GUIContent(label)); - if (labelDims.x < rect.width) - rect.x = m_Owner.GetVisibleWidth() - labelDims.x - rightMargin; // right align if room - rect.width = labelDims.x; - rect.y += 2; // better y pos for minilabel - GUI.Label(rect, label, s_Styles.groupHeaderLabelCount); - } - - Object[] GetSelectedReferences() - { - return Selection.objects; - } - - static string[] GetMainSelectedPaths() - { - List paths = new List(); - foreach (int instanceID in Selection.instanceIDs) - { - if (AssetDatabase.IsMainAsset(instanceID)) - { - string path = AssetDatabase.GetAssetPath(instanceID); - paths.Add(path); - } - } - - return paths.ToArray(); - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ObjectListLocalGroup.cs b/Editor/Mono/ObjectListLocalGroup.cs deleted file mode 100644 index 4fcb9b279d..0000000000 --- a/Editor/Mono/ObjectListLocalGroup.cs +++ /dev/null @@ -1,1411 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.VersionControl; -using UnityEditorInternal; -using UnityEditorInternal.VersionControl; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Math = System.Math; -using IndexOutOfRangeException = System.IndexOutOfRangeException; - -namespace UnityEditor -{ - internal partial class ObjectListArea - { - // Enable external source(s) to draw in the project browser. - // 'iconRect' frame for the asset icon. - // 'guid' asset being drawn. - internal delegate void OnAssetIconDrawDelegate(Rect iconRect, string guid, bool isListMode); - internal static event OnAssetIconDrawDelegate postAssetIconDrawCallback = null; - - // 'drawRect' prescribed draw area after the asset label. - // 'guid' asset being drawn. - // return whether drawing occured (space will be redistributed if false) - internal delegate bool OnAssetLabelDrawDelegate(Rect drawRect, string guid, bool isListMode); - internal static event OnAssetLabelDrawDelegate postAssetLabelDrawCallback = null; - - // Asset on local disk in project - class LocalGroup : Group - { - BuiltinResource[] m_NoneList; - - GUIContent m_Content = new GUIContent(); - - List m_DragSelection = new List(); // Temp instanceID state while dragging (not serialized) - int m_DropTargetControlID = 0; - - // Type name if resource is the key - Dictionary m_BuiltinResourceMap; - BuiltinResource[] m_CurrentBuiltinResources; - bool m_ShowNoneItem; - public bool ShowNone { get { return m_ShowNoneItem; } } - public override bool NeedsRepaint { get { return false; } protected set {} } - List m_LastRenderedAssetInstanceIDs = new List(); - List m_LastRenderedAssetDirtyIDs = new List(); - - public bool m_ListMode = false; - FilteredHierarchy m_FilteredHierarchy; - BuiltinResource[] m_ActiveBuiltinList; - - public const int k_ListModeLeftPadding = 13; - public const int k_ListModeLeftPaddingForSubAssets = 28; - public const int k_ListModeVersionControlOverlayPadding = 14; - const int k_ListModeExternalIconPadding = 6; - const float k_IconWidth = 16f; - const float k_SpaceBetweenIconAndText = 2f; - - - public SearchFilter searchFilter { get {return m_FilteredHierarchy.searchFilter; }} - public override bool ListMode { get { return m_ListMode; } set { m_ListMode = value; } } - public bool HasBuiltinResources { get { return m_CurrentBuiltinResources.Length > 0; } } - - ItemFader m_ItemFader = new ItemFader(); - - public override int ItemCount - { - get - { - int projectItemCount = m_FilteredHierarchy.results.Length; - int totalItemCount = projectItemCount + m_ActiveBuiltinList.Length; - int noneItem = m_ShowNoneItem ? 1 : 0; - int newItem = m_Owner.m_State.m_NewAssetIndexInList != -1 ? 1 : 0; - return totalItemCount + noneItem + newItem; - } - } - - public LocalGroup(ObjectListArea owner, string groupTitle, bool showNone) : base(owner, groupTitle) - { - m_ShowNoneItem = showNone; - m_ListMode = false; - InitBuiltinResources(); - ItemsWantedShown = int.MaxValue; - m_Collapsable = false; - } - - public override void UpdateAssets() - { - // Set up our builtin list - if (m_FilteredHierarchy.hierarchyType == HierarchyType.Assets) - m_ActiveBuiltinList = m_CurrentBuiltinResources; - else - m_ActiveBuiltinList = new BuiltinResource[0]; // The Scene tab does not display builtin resources - - ItemsAvailable = m_FilteredHierarchy.results.Length + m_ActiveBuiltinList.Length; - } - - protected override float GetHeaderHeight() - { - return 0f; - } - - override protected void DrawHeader(float yOffset, bool collapsable) - { - if (GetHeaderHeight() > 0f) - { - Rect rect = new Rect(0, GetHeaderYPosInScrollArea(yOffset), m_Owner.GetVisibleWidth(), kGroupSeparatorHeight); - - base.DrawHeaderBackground(rect, true); - - // Draw the group toggle - if (collapsable) - { - rect.x += 7; - bool oldVisible = Visible; - Visible = GUI.Toggle(new Rect(rect.x, rect.y, 14, rect.height), Visible, GUIContent.none, s_Styles.groupFoldout); - if (oldVisible ^ Visible) - EditorPrefs.SetBool(m_GroupSeparatorTitle, Visible); - - rect.x += 7; - } - - float usedWidth = 0f; - if (m_Owner.drawLocalAssetHeader != null) - usedWidth = m_Owner.drawLocalAssetHeader(rect) + 10f; // add space between arrow and count - - rect.x += usedWidth; - rect.width -= usedWidth; - if (rect.width > 0) - base.DrawItemCount(rect); - } - } - - public override void UpdateHeight() - { - // Ensure that m_Grid is setup before calling UpdateHeight - m_Height = GetHeaderHeight(); - - if (!Visible) - return; - - m_Height += m_Grid.height; - } - - bool IsCreatingAtThisIndex(int itemIdx) - { - return m_Owner.m_State.m_NewAssetIndexInList == itemIdx; - } - - protected override void DrawInternal(int beginIndex, int endIndex, float yOffset) - { - int itemIndex = beginIndex; - int itemCount = 0; - - FilteredHierarchy.FilterResult[] results = m_FilteredHierarchy.results; - - bool isFolderBrowsing = m_FilteredHierarchy.searchFilter.GetState() == SearchFilter.State.FolderBrowsing; - - // The seperator bar is drawn before all items - yOffset += GetHeaderHeight(); - - // 1. None item - Rect itemRect; - if (m_NoneList.Length > 0) - { - if (beginIndex < 1) - { - itemRect = m_Grid.CalcRect(itemIndex, yOffset); - DrawItem(itemRect, null, m_NoneList[0], isFolderBrowsing); - itemIndex++; - } - itemCount++; - } - - // 2. Project Assets - if (!ListMode && isFolderBrowsing) - DrawSubAssetBackground(beginIndex, endIndex, yOffset); // only show sub asset bg when not searching i.e. folder browsing - - if (Event.current.type == EventType.Repaint) - ClearDirtyStateTracking(); - int resultsIdx = itemIndex - itemCount; - while (true) - { - // Insert new asset item here - if (IsCreatingAtThisIndex(itemIndex)) - { - BuiltinResource newAsset = new BuiltinResource(); - newAsset.m_Name = m_Owner.GetCreateAssetUtility().originalName; - newAsset.m_InstanceID = m_Owner.GetCreateAssetUtility().instanceID; - - DrawItem(m_Grid.CalcRect(itemIndex, yOffset), null, newAsset, isFolderBrowsing); - itemIndex++; // Push following items forward - itemCount++; - } - - // Stop conditions - if (itemIndex > endIndex) - break; - if (resultsIdx >= results.Length) - break; - - // Draw item - FilteredHierarchy.FilterResult result = results[resultsIdx]; - itemRect = m_Grid.CalcRect(itemIndex, yOffset); - DrawItem(itemRect, result, null, isFolderBrowsing); - itemIndex++; - resultsIdx++; - } - itemCount += results.Length; - - // 3. Builtin - if (m_ActiveBuiltinList.Length > 0) - { - int builtinStartIdx = beginIndex - itemCount; - builtinStartIdx = Math.Max(builtinStartIdx, 0); - for (int builtinIdx = builtinStartIdx; builtinIdx < m_ActiveBuiltinList.Length && itemIndex <= endIndex; itemIndex++, builtinIdx++) - { - DrawItem(m_Grid.CalcRect(itemIndex, yOffset), null, m_ActiveBuiltinList[builtinIdx], isFolderBrowsing); - } - } - - // Repaint again if we are in preview icon mode and previews are being loaded - if (!ListMode && AssetPreview.IsLoadingAssetPreviews(m_Owner.GetAssetPreviewManagerID())) - m_Owner.Repaint(); - } - - void ClearDirtyStateTracking() - { - m_LastRenderedAssetInstanceIDs.Clear(); - m_LastRenderedAssetDirtyIDs.Clear(); - } - - void AddDirtyStateFor(int instanceID) - { - m_LastRenderedAssetInstanceIDs.Add(instanceID); - m_LastRenderedAssetDirtyIDs.Add(EditorUtility.GetDirtyIndex(instanceID)); - } - - public bool IsAnyLastRenderedAssetsDirty() - { - for (int i = 0; i < m_LastRenderedAssetInstanceIDs.Count; ++i) - { - int dirtyIndex = EditorUtility.GetDirtyIndex(m_LastRenderedAssetInstanceIDs[i]); - if (dirtyIndex != m_LastRenderedAssetDirtyIDs[i]) - { - m_LastRenderedAssetDirtyIDs[i] = dirtyIndex; - return true; - } - } - return false; - } - - protected override void HandleUnusedDragEvents(float yOffset) - { - if (!m_Owner.allowDragging) - return; - Event evt = Event.current; - switch (evt.type) - { - case EventType.DragUpdated: - case EventType.DragPerform: - Rect localGroupRect = new Rect(0, yOffset, m_Owner.m_TotalRect.width, m_Owner.m_TotalRect.height > Height ? m_Owner.m_TotalRect.height : Height); - if (localGroupRect.Contains(evt.mousePosition)) - { - DragAndDropVisualMode mode; - bool isFolderBrowsing = (m_FilteredHierarchy.searchFilter.GetState() == SearchFilter.State.FolderBrowsing); - if (isFolderBrowsing && m_FilteredHierarchy.searchFilter.folders.Length == 1) - { - string folder = m_FilteredHierarchy.searchFilter.folders[0]; - int instanceID = AssetDatabase.GetMainAssetInstanceID(folder); - bool perform = evt.type == EventType.DragPerform; - mode = DoDrag(instanceID, perform); - if (perform && mode != DragAndDropVisualMode.None) - DragAndDrop.AcceptDrag(); - } - else - { - // Disallow drop: more than one folder or search is active, since dropping would be ambiguous. - mode = DragAndDropVisualMode.None; - } - DragAndDrop.visualMode = mode; - evt.Use(); - } - break; - case EventType.DragExited: - m_DragSelection.Clear(); - break; - } - } - - void HandleMouseWithDragging(int instanceID, int controlID, Rect rect) - { - // Handle mouse down on entire line - Event evt = Event.current; - - switch (evt.GetTypeForControl(controlID)) - { - case EventType.MouseDown: - if (Event.current.button == 0 && rect.Contains(Event.current.mousePosition)) - { - if (evt.clickCount == 2) - { - // Double clicked - m_Owner.SetSelection(new[] {instanceID}, true); - m_DragSelection.Clear(); - } - else - { - // Begin drag - m_DragSelection = GetNewSelection(instanceID, true, false); - GUIUtility.hotControl = controlID; - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), controlID); - delay.mouseDownPosition = Event.current.mousePosition; - m_Owner.ScrollToPosition(ObjectListArea.AdjustRectForFraming(rect)); - } - - evt.Use(); - } - else if (Event.current.button == 1 && rect.Contains(Event.current.mousePosition)) - { - // Right mouse down selection (do NOT use event since we need ContextClick event, which is not fired if right click is used) - m_Owner.SetSelection(GetNewSelection(instanceID, true, false).ToArray(), false); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == controlID) - { - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), controlID); - if (delay.CanStartDrag()) - { - StartDrag(instanceID, m_DragSelection); - GUIUtility.hotControl = 0; - } - - evt.Use(); - } - break; - case EventType.DragUpdated: - case EventType.DragPerform: - { - bool perform = evt.type == EventType.DragPerform; - if (rect.Contains(evt.mousePosition)) - { - DragAndDropVisualMode mode = DoDrag(instanceID, perform); - if (mode != DragAndDropVisualMode.None) - { - if (perform) - DragAndDrop.AcceptDrag(); - - m_DropTargetControlID = controlID; - DragAndDrop.visualMode = mode; - evt.Use(); - } - - if (perform) - m_DropTargetControlID = 0; - } - - if (perform) - m_DragSelection.Clear(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == controlID) - { - if (rect.Contains(evt.mousePosition)) - { - bool clickedOnText; - if (ListMode) - { - rect.x += 28; - rect.width += 28; - clickedOnText = rect.Contains(evt.mousePosition); - } - else - { - rect.y = rect.y + rect.height - s_Styles.resultsGridLabel.fixedHeight; - rect.height = s_Styles.resultsGridLabel.fixedHeight; - clickedOnText = rect.Contains(evt.mousePosition); - } - - List selected = m_Owner.m_State.m_SelectedInstanceIDs; - if (clickedOnText && m_Owner.allowRenaming && m_Owner.m_AllowRenameOnMouseUp && selected.Count == 1 && selected[0] == instanceID && !EditorGUIUtility.HasHolddownKeyModifiers(evt)) - { - m_Owner.BeginRename(0.5f); - } - else - { - List newSelection = GetNewSelection(instanceID, false, false); - m_Owner.SetSelection(newSelection.ToArray(), false); - } - - GUIUtility.hotControl = 0; - evt.Use(); - } - - m_DragSelection.Clear(); - } - break; - - case EventType.ContextClick: - Rect overlayPos = rect; - overlayPos.x += 2; - overlayPos = ProjectHooks.GetOverlayRect(overlayPos); - if (overlayPos.width != rect.width && Provider.isActive && overlayPos.Contains(evt.mousePosition)) - { - EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), "Assets/Version Control", new MenuCommand(null, 0)); - evt.Use(); - } - break; - } - } - - void HandleMouseWithoutDragging(int instanceID, int controlID, Rect position) - { - Event evt = Event.current; - - switch (evt.GetTypeForControl(controlID)) - { - case EventType.MouseDown: - if (evt.button == 0 && position.Contains(evt.mousePosition)) - { - m_Owner.Repaint(); - - if (evt.clickCount == 1) - { - m_Owner.ScrollToPosition(ObjectListArea.AdjustRectForFraming(position)); - } - - evt.Use(); - List newSelection = GetNewSelection(instanceID, false, false); - m_Owner.SetSelection(newSelection.ToArray(), evt.clickCount == 2); - } - break; - - case EventType.ContextClick: - if (position.Contains(evt.mousePosition)) - { - // Select it - m_Owner.SetSelection(new[] {instanceID}, false); - - Rect overlayPos = position; - overlayPos.x += 2; - overlayPos = ProjectHooks.GetOverlayRect(overlayPos); - if (overlayPos.width != position.width && Provider.isActive && overlayPos.Contains(evt.mousePosition)) - { - EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), "Assets/Version Control", new MenuCommand(null, 0)); - evt.Use(); - } - } - break; - } - } - - public void ChangeExpandedState(int instanceID, bool expanded) - { - m_Owner.m_State.m_ExpandedInstanceIDs.Remove(instanceID); - if (expanded) - m_Owner.m_State.m_ExpandedInstanceIDs.Add(instanceID); - m_FilteredHierarchy.RefreshVisibleItems(m_Owner.m_State.m_ExpandedInstanceIDs); - } - - bool IsExpanded(int instanceID) - { - return (m_Owner.m_State.m_ExpandedInstanceIDs.IndexOf(instanceID) >= 0); - } - - void SelectAndFrameParentOf(int instanceID) - { - int parentInstanceID = 0; - FilteredHierarchy.FilterResult[] results = m_FilteredHierarchy.results; - for (int i = 0; i < results.Length; ++i) - { - if (results[i].instanceID == instanceID) - { - if (results[i].isMainRepresentation) - parentInstanceID = 0; - break; - } - - if (results[i].isMainRepresentation) - parentInstanceID = results[i].instanceID; - } - - if (parentInstanceID != 0) - { - m_Owner.SetSelection(new int[] {parentInstanceID}, false); - m_Owner.Frame(parentInstanceID, true, false); - } - } - - bool IsRenaming(int instanceID) - { - RenameOverlay renameOverlay = m_Owner.GetRenameOverlay(); - return renameOverlay.IsRenaming() && renameOverlay.userData == instanceID && !renameOverlay.isWaitingForDelay; - } - - protected void DrawSubAssetRowBg(int startSubAssetIndex, int endSubAssetIndex, bool continued, float yOffset) - { - Rect startRect = m_Grid.CalcRect(startSubAssetIndex, yOffset); - Rect endRect = m_Grid.CalcRect(endSubAssetIndex, yOffset); - - float texWidth = 30f; - float texHeight = 128f; - float fraction = startRect.width / texHeight; - float overflowHeight = 9f * fraction; - float shrinkHeight = 4f; - - // Start - bool startIsOnFirstColumn = (startSubAssetIndex % m_Grid.columns) == 0; - float adjustStart = startIsOnFirstColumn ? 18f * fraction : m_Grid.horizontalSpacing + fraction * 10f; - Rect rect = new Rect(startRect.x - adjustStart, startRect.y + shrinkHeight, texWidth * fraction, startRect.width - shrinkHeight * 2 + overflowHeight - 1); - rect.y = Mathf.Round(rect.y); - rect.height = Mathf.Ceil(rect.height); - s_Styles.subAssetBg.Draw(rect, GUIContent.none, false, false, false, false); - - // End - float scaledWidth = texWidth * fraction; - bool endIsOnLastColumn = (endSubAssetIndex % m_Grid.columns) == (m_Grid.columns - 1); - float extendEnd = (continued || endIsOnLastColumn) ? 16 * fraction : 8 * fraction; - Rect rect2 = new Rect(endRect.xMax - scaledWidth + extendEnd, endRect.y + shrinkHeight, scaledWidth, rect.height); - rect2.y = Mathf.Round(rect2.y); - rect2.height = Mathf.Ceil(rect2.height); - GUIStyle endStyle = continued ? s_Styles.subAssetBgOpenEnded : s_Styles.subAssetBgCloseEnded; - endStyle.Draw(rect2, GUIContent.none, false, false, false, false); - - // Middle - rect = new Rect(rect.xMax, rect.y, rect2.xMin - rect.xMax, rect.height); - rect.y = Mathf.Round(rect.y); - rect.height = Mathf.Ceil(rect.height); - s_Styles.subAssetBgMiddle.Draw(rect, GUIContent.none, false, false, false, false); - } - - void DrawSubAssetBackground(int beginIndex, int endIndex, float yOffset) - { - if (Event.current.type != EventType.Repaint) - return; - - FilteredHierarchy.FilterResult[] results = m_FilteredHierarchy.results; - - int columns = m_Grid.columns; - int rows = (endIndex - beginIndex) / columns + 1; - - for (int y = 0; y < rows; ++y) - { - int startSubAssetIndex = -1; - int endSubAssetIndex = -1; - for (int x = 0; x < columns; ++x) - { - int index = beginIndex + (x + y * columns); - if (index >= results.Length) - break; - - FilteredHierarchy.FilterResult result = results[index]; - if (!result.isMainRepresentation) - { - if (startSubAssetIndex == -1) - startSubAssetIndex = index; - endSubAssetIndex = index; - } - else - { - // Check if a section was ended - if (startSubAssetIndex != -1) - { - DrawSubAssetRowBg(startSubAssetIndex, endSubAssetIndex, false, yOffset); - startSubAssetIndex = -1; - endSubAssetIndex = -1; - } - } - } - - if (startSubAssetIndex != -1) - { - bool continued = false; - if (y < rows - 1) - { - int indexFirstColumnNextRow = beginIndex + (y + 1) * columns; - if (indexFirstColumnNextRow < results.Length) - continued = !results[indexFirstColumnNextRow].isMainRepresentation; - } - - DrawSubAssetRowBg(startSubAssetIndex, endSubAssetIndex, continued, yOffset); - } - } - } - - void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinResource builtinResource, bool isFolderBrowsing) - { - System.Diagnostics.Debug.Assert((filterItem != null && builtinResource == null) || - (builtinResource != null && filterItem == null)); // only one should be valid - - Event evt = Event.current; - Rect itemRect = position; - - int instanceID = 0; - bool showFoldout = false; - if (filterItem != null) - { - instanceID = filterItem.instanceID; - showFoldout = filterItem.hasChildren && !filterItem.isFolder && isFolderBrowsing; // we do not want to be able to expand folders - } - else if (builtinResource != null) - { - instanceID = builtinResource.m_InstanceID; - } - - int controlID = GetControlIDFromInstanceID(instanceID); - - bool selected; - if (m_Owner.allowDragging) - selected = m_DragSelection.Count > 0 ? m_DragSelection.Contains(instanceID) : m_Owner.IsSelected(instanceID); - else - selected = m_Owner.IsSelected(instanceID); - - if (selected && instanceID == m_Owner.m_State.m_LastClickedInstanceID) - m_LastClickedDrawTime = EditorApplication.timeSinceStartup; - - Rect foldoutRect = new Rect(position.x + s_Styles.groupFoldout.margin.left, position.y, s_Styles.groupFoldout.padding.left, position.height); // ListMode foldout - if (showFoldout && !ListMode) - { - float fraction = position.height / 128f; - float buttonWidth = 28f * fraction; - float buttonHeight = 32f * fraction; - foldoutRect = new Rect(position.xMax - buttonWidth * 0.5f, position.y + (position.height - s_Styles.resultsGridLabel.fixedHeight) * 0.5f - buttonWidth * 0.5f, buttonWidth, buttonHeight); - //foldoutRect = new Rect(position.xMax - 16, position.yMax - 16 - s_Styles.resultsGridLabel.fixedHeight, 16, 16); // bottom right corner - } - - bool toggleState = false; - 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) - { - switch (evt.keyCode) - { - // Fold in - case KeyCode.LeftArrow: - if (ListMode || m_Owner.IsPreviewIconExpansionModifierPressed()) - { - if (IsExpanded(instanceID)) - toggleState = true; - else - SelectAndFrameParentOf(instanceID); - evt.Use(); - } - break; - - // Fold out - case KeyCode.RightArrow: - if (ListMode || m_Owner.IsPreviewIconExpansionModifierPressed()) - { - if (!IsExpanded(instanceID)) - toggleState = true; - evt.Use(); - } - break; - } - } - - // Foldout mouse button logic (rendering the item itself can be found below) - if (showFoldout && evt.type == EventType.MouseDown && evt.button == 0 && foldoutRect.Contains(evt.mousePosition)) - toggleState = true; - - if (toggleState) - { - bool expanded = !IsExpanded(instanceID); - if (expanded) - m_ItemFader.Start(m_FilteredHierarchy.GetSubAssetInstanceIDs(instanceID)); - ChangeExpandedState(instanceID, expanded); - evt.Use(); - GUIUtility.ExitGUI(); - } - - bool isRenaming = IsRenaming(instanceID); - - Rect labelRect = position; - if (!ListMode) - labelRect = new Rect(position.x, position.yMax + 1 - s_Styles.resultsGridLabel.fixedHeight, position.width - 1, s_Styles.resultsGridLabel.fixedHeight); - - int vcPadding = Provider.isActive && ListMode ? k_ListModeVersionControlOverlayPadding : 0; - - float contentStartX = foldoutRect.xMax; - if (ListMode) - { - itemRect.x = contentStartX; - if (filterItem != null && !filterItem.isMainRepresentation && isFolderBrowsing) - { - contentStartX = k_ListModeLeftPaddingForSubAssets; - itemRect.x = k_ListModeLeftPaddingForSubAssets + vcPadding * 0.5f; - } - itemRect.width -= itemRect.x; - } - - // Draw section - if (Event.current.type == EventType.Repaint) - { - if (m_DropTargetControlID == controlID && !position.Contains(evt.mousePosition)) - m_DropTargetControlID = 0; - bool isDropTarget = controlID == m_DropTargetControlID && m_DragSelection.IndexOf(m_DropTargetControlID) == -1; - - string labeltext = filterItem != null ? filterItem.name : builtinResource.m_Name; - if (ListMode) - { - if (isRenaming) - { - selected = false; - labeltext = ""; - } - - m_Content.text = labeltext; - m_Content.image = null; - Texture2D icon = filterItem != null ? filterItem.icon : AssetPreview.GetAssetPreview(instanceID, m_Owner.GetAssetPreviewManagerID()); - - if (icon == null && m_Owner.GetCreateAssetUtility().icon != null) - icon = m_Owner.GetCreateAssetUtility().icon; - - if (selected) - s_Styles.resultsLabel.Draw(position, GUIContent.none, false, false, selected, m_Owner.HasFocus()); - - if (isDropTarget) - s_Styles.resultsLabel.Draw(position, GUIContent.none, true, true, false, false); - - DrawIconAndLabel(new Rect(contentStartX, position.y, position.width - contentStartX, position.height), - filterItem, labeltext, icon, selected, m_Owner.HasFocus()); - - // Foldout - if (showFoldout) - s_Styles.groupFoldout.Draw(foldoutRect, !ListMode, !ListMode, IsExpanded(instanceID), false); - } - else // Icon grid - { - // Get icon - bool drawDropShadow = false; - if (m_Owner.GetCreateAssetUtility().instanceID == instanceID && m_Owner.GetCreateAssetUtility().icon != null) - { - // If we are creating a new asset we might have an icon to use - m_Content.image = m_Owner.GetCreateAssetUtility().icon; - } - else - { - // Check for asset preview - m_Content.image = AssetPreview.GetAssetPreview(instanceID, m_Owner.GetAssetPreviewManagerID()); - if (m_Content.image != null) - drawDropShadow = true; - - if (filterItem != null) - { - // Otherwise use cached icon - if (m_Content.image == null) - m_Content.image = filterItem.icon; - - // When folder browsing sub assets are shown on a background slate and do not need rounded corner overlay - if (isFolderBrowsing && !filterItem.isMainRepresentation) - drawDropShadow = false; - } - } - - 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) - position.height -= s_Styles.resultsGridLabel.fixedHeight + 2 * padding; // get icon rect (remove label height which is included in the position rect) - position.y += padding; - - Rect actualImageDrawPosition = (m_Content.image == null) ? new Rect() : ActualImageDrawPosition(position, m_Content.image.width, m_Content.image.height); - m_Content.text = null; - float alpha = 1f; - if (filterItem != null) - { - AddDirtyStateFor(filterItem.instanceID); - - if (!filterItem.isMainRepresentation && isFolderBrowsing) - { - position.x += 4f; - position.y += 4f; - position.width -= 8f; - position.height -= 8f; - - actualImageDrawPosition = (m_Content.image == null) ? new Rect() : ActualImageDrawPosition(position, m_Content.image.width, m_Content.image.height); - - alpha = m_ItemFader.GetAlpha(filterItem.instanceID); - if (alpha < 1f) - m_Owner.Repaint(); - } - - // Draw static preview bg color as bg for small textures and non-square textures - if (drawDropShadow && filterItem.iconDrawStyle == IconDrawStyle.NonTexture) - s_Styles.previewBg.Draw(actualImageDrawPosition, GUIContent.none, false, false, false, false); - } - - Color orgColor = GUI.color; - if (selected) - GUI.color = GUI.color * new Color(0.85f, 0.9f, 1f); - - if (m_Content.image != null) - { - Color orgColor2 = GUI.color; - if (alpha < 1f) - GUI.color = new Color(GUI.color.r, GUI.color.g, GUI.color.b, alpha); - - s_Styles.resultsGrid.Draw(actualImageDrawPosition, m_Content, false, false, selected, m_Owner.HasFocus()); - - if (alpha < 1f) - GUI.color = orgColor2; - } - - if (selected) - GUI.color = orgColor; - - if (drawDropShadow) - { - Rect borderPosition = new RectOffset(1, 1, 1, 1).Remove(s_Styles.textureIconDropShadow.border.Add(actualImageDrawPosition)); - s_Styles.textureIconDropShadow.Draw(borderPosition, GUIContent.none, false, false, selected || isDropTarget, m_Owner.HasFocus() || isRenaming || isDropTarget); - } - - - // Draw label - if (!isRenaming) - { - if (isDropTarget) - s_Styles.resultsLabel.Draw(new Rect(labelRect.x - 10, labelRect.y, labelRect.width + 20, labelRect.height), GUIContent.none, true, true, false, false); - - labeltext = m_Owner.GetCroppedLabelText(instanceID, labeltext, position.width); - s_Styles.resultsGridLabel.Draw(labelRect, labeltext, false, false, selected, m_Owner.HasFocus()); - } - - if (showFoldout) - { - s_Styles.subAssetExpandButton.Draw(foldoutRect, !ListMode, !ListMode, IsExpanded(instanceID), false); - } - - if (filterItem != null && filterItem.isMainRepresentation) - { - if (null != postAssetIconDrawCallback) - { - postAssetIconDrawCallback(position, filterItem.guid, false); - } - - ProjectHooks.OnProjectWindowItem(filterItem.guid, position); - } - } - } - // Adjust edit field if needed - if (isRenaming) - { - if (ListMode) - { - float iconOffset = vcPadding + k_IconWidth + k_SpaceBetweenIconAndText + s_Styles.resultsLabel.margin.left; - labelRect.x = itemRect.x + iconOffset; - labelRect.width -= labelRect.x; - } - else - { - labelRect.x -= 4; - labelRect.width += 8f; - } - m_Owner.GetRenameOverlay().editFieldRect = labelRect; - m_Owner.HandleRenameOverlay(); - } - - // 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) - if (EditorApplication.projectWindowItemOnGUI != null && filterItem != null && m_Owner.allowUserRenderingHook) - EditorApplication.projectWindowItemOnGUI(filterItem.guid, itemRect); - - // Mouse handling (must be after rename overlay to ensure overlay get mouseevents) - if (m_Owner.allowDragging) - HandleMouseWithDragging(instanceID, controlID, position); - else - HandleMouseWithoutDragging(instanceID, controlID, position); - } - - private static Rect ActualImageDrawPosition(Rect position, float imageWidth, float imageHeight) - { - if (imageWidth > position.width || imageHeight > position.height) - { - Rect screenRect = new Rect(); - Rect sourceRect = new Rect(); - float imageAspect = imageWidth / imageHeight; - GUI.CalculateScaledTextureRects(position, ScaleMode.ScaleToFit, imageAspect, ref screenRect, ref sourceRect); - return screenRect; - } - else - { - float x = position.x + Mathf.Round((position.width - imageWidth) / 2.0f); - float y = position.y + Mathf.Round((position.height - imageHeight) / 2.0f); - return new Rect(x, y, imageWidth, imageHeight); - } - } - - public List> GetVisibleNameAndInstanceIDs() - { - List> result = new List>(); - - // 1. None item - if (m_NoneList.Length > 0) - result.Add(new KeyValuePair(m_NoneList[0].m_Name, m_NoneList[0].m_InstanceID)); // 0 - - // 2. Project Assets - foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results) - result.Add(new KeyValuePair(r.name, r.instanceID)); - - // 3. Builtin - for (int i = 0; i < m_ActiveBuiltinList.Length; ++i) - result.Add(new KeyValuePair(m_ActiveBuiltinList[i].m_Name, m_ActiveBuiltinList[i].m_InstanceID)); - - return result; - } - - private void BeginPing(int instanceID) - { - } - - public List GetInstanceIDs() - { - List result = new List(); - - // 1. None item - if (m_NoneList.Length > 0) - result.Add(m_NoneList[0].m_InstanceID); // 0 - - // 2. Project Assets - foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results) - result.Add(r.instanceID); - if (m_Owner.m_State.m_NewAssetIndexInList >= 0) - result.Add(m_Owner.GetCreateAssetUtility().instanceID); - - // 3. Builtin - for (int i = 0; i < m_ActiveBuiltinList.Length; ++i) - result.Add(m_ActiveBuiltinList[i].m_InstanceID); - - return result; - } - - // Returns list of selected instanceIDs - public List GetNewSelection(int clickedInstanceID, bool beginOfDrag, bool useShiftAsActionKey) - { - // Flatten grid - List allInstanceIDs = GetInstanceIDs(); - List selectedInstanceIDs = m_Owner.m_State.m_SelectedInstanceIDs; - int lastClickedInstanceID = m_Owner.m_State.m_LastClickedInstanceID; - bool allowMultiselection = m_Owner.allowMultiSelect; - - return InternalEditorUtility.GetNewSelection(clickedInstanceID, allInstanceIDs, selectedInstanceIDs, lastClickedInstanceID, beginOfDrag, useShiftAsActionKey, allowMultiselection); - } - - public override void UpdateFilter(HierarchyType hierarchyType, SearchFilter searchFilter, bool foldersFirst) - { - // Filtered hierarchy list - RefreshHierarchy(hierarchyType, searchFilter, foldersFirst); - - // Filtered builtin list - RefreshBuiltinResourceList(searchFilter); - } - - private void RefreshHierarchy(HierarchyType hierarchyType, SearchFilter searchFilter, bool foldersFirst) - { - m_FilteredHierarchy = new FilteredHierarchy(hierarchyType); - m_FilteredHierarchy.foldersFirst = foldersFirst; - m_FilteredHierarchy.searchFilter = searchFilter; - m_FilteredHierarchy.RefreshVisibleItems(m_Owner.m_State.m_ExpandedInstanceIDs); - } - - void RefreshBuiltinResourceList(SearchFilter searchFilter) - { - // Early out if we do not want to show builtin resources - if (!m_Owner.allowBuiltinResources || (searchFilter.GetState() == SearchFilter.State.FolderBrowsing) || (searchFilter.GetState() == SearchFilter.State.EmptySearchFilter)) - { - m_CurrentBuiltinResources = new BuiltinResource[0]; - return; - } - - List currentBuiltinResources = new List(); - - // Filter by assets labels (Builtins have no asset labels currently) - if (searchFilter.assetLabels != null && searchFilter.assetLabels.Length > 0) - { - m_CurrentBuiltinResources = currentBuiltinResources.ToArray(); - return; - } - - // Filter by class/type - List requiredClassIDs = new List(); - foreach (string className in searchFilter.classNames) - { - var unityType = UnityType.FindTypeByNameCaseInsensitive(className); - if (unityType != null) - requiredClassIDs.Add(unityType.persistentTypeID); - } - if (requiredClassIDs.Count > 0) - { - foreach (KeyValuePair kvp in m_BuiltinResourceMap) - { - UnityType classType = UnityType.FindTypeByName(kvp.Key); - if (classType == null) - continue; - - foreach (int requiredClassID in requiredClassIDs) - { - if (classType.IsDerivedFrom(UnityType.FindTypeByPersistentTypeID(requiredClassID))) - currentBuiltinResources.AddRange(kvp.Value); - } - } - } - - // Filter by name - BuiltinResource[] builtinList = currentBuiltinResources.ToArray(); - if (builtinList.Length > 0 && !string.IsNullOrEmpty(searchFilter.nameFilter)) - { - List filtered = new List(); // allocated here to prevent from allocating on every event. - string nameFilter = searchFilter.nameFilter.ToLower(); - foreach (BuiltinResource br in builtinList) - if (br.m_Name.ToLower().Contains(nameFilter)) - filtered.Add(br); - - builtinList = filtered.ToArray(); - } - - m_CurrentBuiltinResources = builtinList; - } - - public string GetNameOfLocalAsset(int instanceID) - { - foreach (var r in m_FilteredHierarchy.results) - { - if (r.instanceID == instanceID) - return r.name; - } - return null; - } - - public bool IsBuiltinAsset(int instanceID) - { - foreach (KeyValuePair kvp in m_BuiltinResourceMap) - { - BuiltinResource[] list = kvp.Value; - for (int i = 0; i < list.Length; ++i) - if (list[i].m_InstanceID == instanceID) - return true; - } - return false; - } - - private void InitBuiltinAssetType(System.Type type) - { - if (type == null) - { - Debug.LogWarning("ObjectSelector::InitBuiltinAssetType: type is null!"); - return; - } - string typeName = type.ToString().Substring(type.Namespace.ToString().Length + 1); - - var unityType = UnityType.FindTypeByName(typeName); - if (unityType == null) - { - Debug.LogWarning("ObjectSelector::InitBuiltinAssetType: class '" + typeName + "' not found"); - return; - } - - BuiltinResource[] resourceList = EditorGUIUtility.GetBuiltinResourceList(unityType.persistentTypeID); - if (resourceList != null) - m_BuiltinResourceMap.Add(typeName, resourceList); - } - - public void InitBuiltinResources() - { - if (m_BuiltinResourceMap != null) - return; - - m_BuiltinResourceMap = new Dictionary(); - - if (m_ShowNoneItem) - { - m_NoneList = new BuiltinResource[1]; - m_NoneList[0] = new BuiltinResource(); - m_NoneList[0].m_InstanceID = 0; - m_NoneList[0].m_Name = "None"; - } - else - { - m_NoneList = new BuiltinResource[0]; - } - - // We don't show all built-in resources; just the ones where their type - // makes sense. The actual lists are in ResourceManager.cpp, - // GetBuiltinResourcesOfClass - InitBuiltinAssetType(typeof(Mesh)); - InitBuiltinAssetType(typeof(Material)); - InitBuiltinAssetType(typeof(Texture2D)); - InitBuiltinAssetType(typeof(Font)); - InitBuiltinAssetType(typeof(Shader)); - InitBuiltinAssetType(typeof(Sprite)); - InitBuiltinAssetType(typeof(LightmapParameters)); - - // PrintBuiltinResourcesAvailable(); - } - - public void PrintBuiltinResourcesAvailable() - { - string text = ""; - text += "ObjectSelector -Builtin Assets Available:\n"; - foreach (KeyValuePair kvp in m_BuiltinResourceMap) - { - BuiltinResource[] list = kvp.Value; - text += " " + kvp.Key + ": "; - for (int i = 0; i < list.Length; ++i) - { - if (i != 0) - text += ", "; - text += list[i].m_Name; - } - text += "\n"; - } - Debug.Log(text); - } - - // Can return an index 1 past end of existing items (if newText is last in sort) - public int IndexOfNewText(string newText, bool isCreatingNewFolder, bool foldersFirst) - { - int idx = 0; - if (m_ShowNoneItem) - idx++; - - for (; idx < m_FilteredHierarchy.results.Length; ++idx) - { - FilteredHierarchy.FilterResult r = m_FilteredHierarchy.results[idx]; - - // Skip folders when inserting a normal asset if folders is sorted first - if (foldersFirst && r.isFolder && !isCreatingNewFolder) - continue; - - // When inserting a folder in folders first list break when we reach normal assets - if (foldersFirst && !r.isFolder && isCreatingNewFolder) - break; - - // Use same name compare as when we sort in the backend: See AssetDatabase.cpp: SortChildren - string propertyPath = AssetDatabase.GetAssetPath(r.instanceID); - if (EditorUtility.NaturalCompare(System.IO.Path.GetFileNameWithoutExtension(propertyPath), newText) > 0) - { - return idx; - } - } - return idx; - } - - public int IndexOf(int instanceID) - { - int idx = 0; - - // 1. 'none' first (has instanceID 0) - if (m_ShowNoneItem) - { - if (instanceID == 0) - return 0; - else - idx++; - } - else if (instanceID == 0) - return -1; - - // 2. Project assets - foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results) - { - // When creating new asset we jump over that item (assuming we do not search for that new asset) - if (m_Owner.m_State.m_NewAssetIndexInList == idx) - idx++; - - if (r.instanceID == instanceID) - return idx; - idx++; - } - - // 3. Builtin resources - foreach (BuiltinResource b in m_ActiveBuiltinList) - { - if (instanceID == b.m_InstanceID) - return idx; - idx++; - } - return -1; - } - - public FilteredHierarchy.FilterResult LookupByInstanceID(int instanceID) - { - if (instanceID == 0) - return null; - - int idx = 0; - foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results) - { - // When creating new asset we jump over that item (assuming we do not search for that new asset) - if (m_Owner.m_State.m_NewAssetIndexInList == idx) - idx++; - - if (r.instanceID == instanceID) - return r; - idx++; - } - return null; - } - - // Returns true if index was valid. Note that instance can be 0 if 'None' item was found at index - public bool InstanceIdAtIndex(int index, out int instanceID) - { - instanceID = 0; - if (index >= m_Grid.rows * m_Grid.columns) - return false; - - int idx = 0; - - // 1. 'none' first (has instanceID 0) - if (m_ShowNoneItem) - { - if (index == 0) - return true; - else - idx++; - } - - // 2. Project assets - foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results) - { - instanceID = r.instanceID; - if (idx == index) - return true; - idx++; - } - - // 3. Builtin resources - foreach (BuiltinResource b in m_ActiveBuiltinList) - { - instanceID = b.m_InstanceID; - if (idx == index) - return true; - idx++; - } - - // If last row and the row is not entirely filled - // we just use the last item on that row - if (index < m_Grid.rows * m_Grid.columns) - return true; - - return false; - } - - public virtual void StartDrag(int draggedInstanceID, List selectedInstanceIDs) - { - ProjectWindowUtil.StartDrag(draggedInstanceID, selectedInstanceIDs); - } - - public DragAndDropVisualMode DoDrag(int dragToInstanceID, bool perform) - { - // Need to get a real HierarchyProperty class, which can be casted in C++. - HierarchyProperty search = new HierarchyProperty(HierarchyType.Assets); - if (!search.Find(dragToInstanceID, null)) - search = null; - - return InternalEditorUtility.ProjectWindowDrag(search, perform); - } - - static internal int GetControlIDFromInstanceID(int instanceID) - { - return instanceID + 100000000; - } - - public bool DoCharacterOffsetSelection() - { - if (Event.current.type == EventType.KeyDown && Event.current.shift) - { - System.StringComparison ignoreCase = System.StringComparison.CurrentCultureIgnoreCase; - string startName = ""; - if (Selection.activeObject != null) - startName = Selection.activeObject.name; - - string c = new string(new[] {Event.current.character}); - List> list = GetVisibleNameAndInstanceIDs(); - if (list.Count == 0) - return false; - - - // If same c is same start char as current selected then find current selected index - int startIndex = 0; - if (startName.StartsWith(c, ignoreCase)) - { - // Iterate from there until next char is found - for (int i = 0; i < list.Count; ++i) - { - if (list[i].Key == startName) - { - startIndex = i + 1; - } - } - } - - // Check all items starting with startIndex - for (int i = 0; i < list.Count; i++) - { - int index = (i + startIndex) % list.Count; - - if (list[index].Key.StartsWith(c, ignoreCase)) - { - Selection.activeInstanceID = list[index].Value; - m_Owner.Repaint(); - return true; - } - } - } - - return false; - } - - public void ShowObjectsInList(int[] instanceIDs) - { - m_FilteredHierarchy = new FilteredHierarchy(HierarchyType.Assets); - m_FilteredHierarchy.SetResults(instanceIDs); - } - - public static void DrawIconAndLabel(Rect rect, FilteredHierarchy.FilterResult filterItem, string label, Texture2D icon, bool selected, bool focus) - { - float vcPadding = s_VCEnabled ? k_ListModeVersionControlOverlayPadding : 0f; - rect.xMin += s_Styles.resultsLabel.margin.left; - - // Reduce the label width to allow delegate drawing on the right. - float delegateDrawWidth = (k_ListModeExternalIconPadding * 2) + k_IconWidth; - Rect delegateDrawRect = new Rect(rect.xMax - delegateDrawWidth, rect.y, delegateDrawWidth, rect.height); - Rect labelRect = new Rect(rect); - if (DrawExternalPostLabelInList(delegateDrawRect, filterItem)) - { - labelRect.width = (rect.width - delegateDrawWidth); - } - - s_Styles.resultsLabel.padding.left = (int)(vcPadding + k_IconWidth + k_SpaceBetweenIconAndText); - s_Styles.resultsLabel.Draw(labelRect, label, false, false, selected, focus); - - Rect iconRect = rect; - iconRect.width = k_IconWidth; - iconRect.x += vcPadding * 0.5f; - - if (icon != null) - GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit); - - if (filterItem != null && filterItem.guid != null && filterItem.isMainRepresentation) - { - Rect overlayRect = rect; - overlayRect.width = vcPadding + k_IconWidth; - - if (null != postAssetIconDrawCallback) - { - postAssetIconDrawCallback(overlayRect, filterItem.guid, true); - } - ProjectHooks.OnProjectWindowItem(filterItem.guid, overlayRect); - } - } - - private static bool DrawExternalPostLabelInList(Rect drawRect, FilteredHierarchy.FilterResult filterItem) - { - bool didDraw = false; - if (filterItem != null && filterItem.guid != null && filterItem.isMainRepresentation) - { - if (null != postAssetLabelDrawCallback) - { - didDraw = postAssetLabelDrawCallback(drawRect, filterItem.guid, true); - } - } - return didDraw; - } - - class ItemFader - { - double m_FadeDuration = 0.3; - double m_FirstToLastDuration = 0.3; - double m_FadeStartTime; - double m_TimeBetweenEachItem; - List m_InstanceIDs; - - public void Start(List instanceIDs) - { - m_InstanceIDs = instanceIDs; - m_FadeStartTime = EditorApplication.timeSinceStartup; - m_FirstToLastDuration = Math.Min(0.5, instanceIDs.Count * 0.03); - m_TimeBetweenEachItem = 0; - if (m_InstanceIDs.Count > 1) - m_TimeBetweenEachItem = m_FirstToLastDuration / (m_InstanceIDs.Count - 1); - } - - public float GetAlpha(int instanceID) - { - if (m_InstanceIDs == null) - return 1f; - - if (EditorApplication.timeSinceStartup > m_FadeStartTime + m_FadeDuration + m_FirstToLastDuration) - { - m_InstanceIDs = null; // reset - return 1f; - } - - int index = m_InstanceIDs.IndexOf(instanceID); - if (index >= 0) - { - double elapsed = EditorApplication.timeSinceStartup - m_FadeStartTime; - double itemStartTime = m_TimeBetweenEachItem * index; - - float alpha = 0f; - if (itemStartTime < elapsed) - { - alpha = Mathf.Clamp((float)((elapsed - itemStartTime) / m_FadeDuration), 0f, 1f); - } - return alpha; - } - return 1f; - } - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ObjectNames.cs b/Editor/Mono/ObjectNames.cs deleted file mode 100644 index bbac0243ad..0000000000 --- a/Editor/Mono/ObjectNames.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - public sealed partial class ObjectNames - { - // *undocumented* - private static string GetObjectTypeName(Object o) - { - if (o == null) - return "Nothing Selected"; - - if (o is GameObject) - return o.name; - - // Show "Tags & Layers" instead of "TagManager" - if (o is TagManager) - return "Tags & Layers"; - - if (o is Component) - { - var behaviour = o as MonoBehaviour; - if (behaviour) - { - var scriptClassName = behaviour.GetScriptClassName(); - if (scriptClassName == "InvalidStateMachineBehaviour") - return behaviour.name + " (Script)"; - return scriptClassName + " (Script)"; - } - - var meshfilter = o as MeshFilter; - if (meshfilter) - { - var mesh = meshfilter.sharedMesh; - return (mesh ? mesh.name : "[none]") + " (MeshFilter)"; - } - - return o.GetType().Name; - } - - // Importers don't have names. Just show the type without parenthesis (like we do for components). - if (o is AssetImporter) - { - var monoImporter = o as MonoImporter; - if (monoImporter) - { - var script = monoImporter.GetScript(); - return "Default References (" + (script ? script.name : string.Empty) + ")"; - } - - return o.GetType().Name; - } - - return o.name + " (" + o.GetType().Name + ")"; - } - - // Inspector title for an object. - public static string GetInspectorTitle(Object obj) - { - if (obj == null && (object)obj != null && (obj is MonoBehaviour || obj is ScriptableObject)) - return " (Script)"; - - if (obj == null) - return "Nothing Selected"; - - var title = ObjectNames.NicifyVariableName(GetObjectTypeName(obj)); - - if (Attribute.IsDefined(obj.GetType(), typeof(ObsoleteAttribute))) - title += " (Deprecated)"; - - return title; - } - } -} diff --git a/Editor/Mono/ObjectSelector.cs b/Editor/Mono/ObjectSelector.cs deleted file mode 100644 index dba9e4e717..0000000000 --- a/Editor/Mono/ObjectSelector.cs +++ /dev/null @@ -1,816 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using UnityEditor.AnimatedValues; -using UnityEditor.IMGUI.Controls; -using UnityEditor.SceneManagement; -using UnityEngine; -using UnityEngine.Audio; -using UnityEngine.SceneManagement; -using UnityObject = UnityEngine.Object; - -namespace UnityEditor -{ - internal abstract class ObjectSelectorReceiver : ScriptableObject - { - public abstract void OnSelectionChanged(UnityObject selection); - public abstract void OnSelectionClosed(UnityObject selection); - } - - internal class ObjectSelector : EditorWindow - { - // Styles used in the object selector - class Styles - { - public GUIStyle smallStatus = "ObjectPickerSmallStatus"; - public GUIStyle largeStatus = "ObjectPickerLargeStatus"; - public GUIStyle toolbarBack = "ObjectPickerToolbar"; - public GUIStyle tab = "ObjectPickerTab"; - public GUIStyle bottomResize = "WindowBottomResize"; - public GUIStyle previewBackground = "PopupCurveSwatchBackground"; // TODO: Make dedicated style - public GUIStyle previewTextureBackground = "ObjectPickerPreviewBackground"; // TODO: Make dedicated style - } - Styles m_Styles; - - public const string ObjectSelectorClosedCommand = "ObjectSelectorClosed"; - public const string ObjectSelectorUpdatedCommand = "ObjectSelectorUpdated"; - - // Filters - string m_RequiredType; - string m_SearchFilter; - - // Display state - bool m_FocusSearchFilter; - bool m_AllowSceneObjects; - bool m_IsShowingAssets; - SavedInt m_StartGridSize = new SavedInt("ObjectSelector.GridSize", 64); - - // Misc - internal int objectSelectorID = 0; - ObjectSelectorReceiver m_ObjectSelectorReceiver; - int m_ModalUndoGroup = -1; - UnityObject m_OriginalSelection; - EditorCache m_EditorCache; - GUIView m_DelegateView; - PreviewResizer m_PreviewResizer = new PreviewResizer(); - List m_AllowedIDs; - - // Callbacks - Action m_OnObjectSelectorClosed; - Action m_OnObjectSelectorUpdated; - - ObjectListAreaState m_ListAreaState; - ObjectListArea m_ListArea; - ObjectTreeForSelector m_ObjectTreeWithSearch = new ObjectTreeForSelector(); - UnityObject m_ObjectBeingEdited; - - // Layout - const float kMinTopSize = 250; - const float kMinWidth = 200; - const float kPreviewMargin = 5; - const float kPreviewExpandedAreaHeight = 75; - float m_ToolbarHeight = 44; - float m_PreviewSize = 0; - float m_TopSize = 0; - AnimBool m_ShowWidePreview = new AnimBool(); - AnimBool m_ShowOverlapPreview = new AnimBool(); - - Rect listPosition - { - get - { - return new Rect(0, m_ToolbarHeight, position.width, Mathf.Max(0f, m_TopSize - m_ToolbarHeight)); - } - } - - public List allowedInstanceIDs - { - get { return m_AllowedIDs; } - } - - // get an existing ObjectSelector or create one - static ObjectSelector s_SharedObjectSelector = null; - public static ObjectSelector get - { - get - { - if (s_SharedObjectSelector == null) - { - UnityObject[] objs = Resources.FindObjectsOfTypeAll(typeof(ObjectSelector)); - if (objs != null && objs.Length > 0) - s_SharedObjectSelector = (ObjectSelector)objs[0]; - if (s_SharedObjectSelector == null) - s_SharedObjectSelector = ScriptableObject.CreateInstance(); - } - return s_SharedObjectSelector; - } - } - - public static bool isVisible - { - get - { - return s_SharedObjectSelector != null; - } - } - - bool IsUsingTreeView() - { - return m_ObjectTreeWithSearch.IsInitialized(); - } - - int GetSelectedInstanceID() - { - int[] selection = IsUsingTreeView() ? m_ObjectTreeWithSearch.GetSelection() : m_ListArea.GetSelection(); - if (selection.Length >= 1) - return selection[0]; - return 0; - } - - void OnEnable() - { - hideFlags = HideFlags.DontSave; - m_ShowOverlapPreview.valueChanged.AddListener(Repaint); - m_ShowOverlapPreview.speed = 1.5f; - m_ShowWidePreview.valueChanged.AddListener(Repaint); - m_ShowWidePreview.speed = 1.5f; - - m_PreviewResizer.Init("ObjectPickerPreview"); - m_PreviewSize = m_PreviewResizer.GetPreviewSize(); // Init size - - AssetPreview.ClearTemporaryAssetPreviews(); - - SetupPreview(); - } - - void OnDisable() - { - if (m_ObjectSelectorReceiver != null) - { - m_ObjectSelectorReceiver.OnSelectionClosed(GetCurrentObject()); - } - - if (m_OnObjectSelectorClosed != null) - { - m_OnObjectSelectorClosed(GetCurrentObject()); - } - - SendEvent(ObjectSelectorClosedCommand, false); - if (m_ListArea != null) - m_StartGridSize.value = m_ListArea.gridSize; - - Undo.CollapseUndoOperations(m_ModalUndoGroup); - - if (s_SharedObjectSelector == this) - s_SharedObjectSelector = null; - if (m_EditorCache != null) - m_EditorCache.Dispose(); - - AssetPreview.ClearTemporaryAssetPreviews(); - } - - public void SetupPreview() - { - bool open = PreviewIsOpen(); - bool wide = PreviewIsWide(); - m_ShowOverlapPreview.target = m_ShowOverlapPreview.value = (open && !wide); - m_ShowWidePreview.target = m_ShowWidePreview.value = (open && wide); - } - - void ListAreaItemSelectedCallback(bool doubleClicked) - { - if (doubleClicked) - { - ItemWasDoubleClicked(); - } - else - { - m_FocusSearchFilter = false; - if (m_ObjectSelectorReceiver != null) - { - m_ObjectSelectorReceiver.OnSelectionChanged(GetCurrentObject()); - } - - if (m_OnObjectSelectorUpdated != null) - { - m_OnObjectSelectorUpdated(GetCurrentObject()); - } - - SendEvent(ObjectSelectorUpdatedCommand, true); - } - } - - internal string searchFilter - { - get { return m_SearchFilter; } - set - { - m_SearchFilter = value; - FilterSettingsChanged(); - } - } - - public ObjectSelectorReceiver objectSelectorReceiver - { - get { return m_ObjectSelectorReceiver; } - set { m_ObjectSelectorReceiver = value; } - } - - Scene GetSceneFromObject(UnityObject obj) - { - var go = obj as GameObject; - if (go != null) - return go.scene; - - var component = obj as Component; - if (component != null) - return component.gameObject.scene; - - return new Scene(); - } - - void FilterSettingsChanged() - { - SearchFilter filter = new SearchFilter(); - filter.SearchFieldStringToFilter(m_SearchFilter); - if (!String.IsNullOrEmpty(m_RequiredType) && filter.classNames.Length == 0) - { - filter.classNames = new[] { m_RequiredType }; - } - - var hierarchyType = m_IsShowingAssets ? HierarchyType.Assets : HierarchyType.GameObjects; - - // We do not support cross scene references so ensure we only show game objects - // from the same scene as the object being edited is part of. - if (EditorSceneManager.preventCrossSceneReferences && hierarchyType == HierarchyType.GameObjects && m_ObjectBeingEdited != null) - { - var scene = GetSceneFromObject(m_ObjectBeingEdited); - if (scene.IsValid()) - filter.scenePaths = new[] { scene.path }; - } - - m_ListArea.Init(listPosition, hierarchyType, filter, true); - } - - static bool ShouldTreeViewBeUsed(Type type) - { - return type == typeof(AudioMixerGroup); - } - - public void Show(UnityObject obj, Type requiredType, SerializedProperty property, bool allowSceneObjects) - { - Show(obj, requiredType, property, allowSceneObjects, null); - } - - private readonly Regex s_MatchPPtrTypeName = new Regex(@"PPtr\<(\w+)\>"); - - internal void Show(UnityObject obj, Type requiredType, SerializedProperty property, bool allowSceneObjects, List allowedInstanceIDs) - { - Show(obj, requiredType, property, allowSceneObjects, allowedInstanceIDs, null, null); - } - - internal void Show(UnityObject obj, Type requiredType, SerializedProperty property, bool allowSceneObjects, List allowedInstanceIDs, Action onObjectSelectorClosed, Action onObjectSelectedUpdated) - { - m_ObjectSelectorReceiver = null; - m_AllowSceneObjects = allowSceneObjects; - m_IsShowingAssets = true; - m_AllowedIDs = allowedInstanceIDs; - - m_OnObjectSelectorClosed = onObjectSelectorClosed; - m_OnObjectSelectorUpdated = onObjectSelectedUpdated; - - if (property != null) - { - if (requiredType == null) - { - ScriptAttributeUtility.GetFieldInfoFromProperty(property, out requiredType); - // case 951876: built-in types do not actually have reflectable fields, so their object types must be extracted from the type string - // 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 - if (requiredType == null) - m_RequiredType = s_MatchPPtrTypeName.Match(property.type).Groups[1].Value; - } - - obj = property.objectReferenceValue; - m_ObjectBeingEdited = property.serializedObject.targetObject; - - // Do not allow to show scene objects if the object being edited is persistent - if (m_ObjectBeingEdited != null && EditorUtility.IsPersistent(m_ObjectBeingEdited)) - m_AllowSceneObjects = false; - } - - // Set which tab should be visible at startup - if (m_AllowSceneObjects) - { - if (obj != null) - { - if (typeof(Component).IsAssignableFrom(obj.GetType())) - { - obj = ((Component)obj).gameObject; - } - // Set the right tab visible (so we can see our selection) - m_IsShowingAssets = EditorUtility.IsPersistent(obj); - } - else - { - m_IsShowingAssets = (requiredType != typeof(GameObject) && !typeof(Component).IsAssignableFrom(requiredType)); - } - } - else - { - m_IsShowingAssets = true; - } - - // Set member variables - m_DelegateView = GUIView.current; - // type filter requires unqualified names for built-in types, but will prioritize them over user types, so ensure user types are namespace-qualified - if (requiredType != null) - m_RequiredType = typeof(ScriptableObject).IsAssignableFrom(requiredType) || typeof(MonoBehaviour).IsAssignableFrom(requiredType) ? requiredType.FullName : requiredType.Name; - m_SearchFilter = ""; - m_OriginalSelection = obj; - m_ModalUndoGroup = Undo.GetCurrentGroup(); - - // Freeze to prevent flicker on OSX. - // Screen will be updated again when calling - // SetFreezeDisplay(false) further down. - ContainerWindow.SetFreezeDisplay(true); - - ShowWithMode(ShowMode.AuxWindow); - titleContent = EditorGUIUtility.TrTextContent("Select " + (requiredType == null ? m_RequiredType : requiredType.Name)); - - // Deal with window size - Rect p = m_Parent.window.position; - p.width = EditorPrefs.GetFloat("ObjectSelectorWidth", 200); - p.height = EditorPrefs.GetFloat("ObjectSelectorHeight", 390); - position = p; - minSize = new Vector2(kMinWidth, kMinTopSize + kPreviewExpandedAreaHeight + 2 * kPreviewMargin); - maxSize = new Vector2(10000, 10000); - SetupPreview(); - - // Focus - Focus(); - ContainerWindow.SetFreezeDisplay(false); - - m_FocusSearchFilter = true; - - // Add after unfreezing display because AuxWindowManager.cpp assumes that aux windows are added after we get 'got/lost'- focus calls. - m_Parent.AddToAuxWindowList(); - - // Initial selection - int initialSelection = obj != null ? obj.GetInstanceID() : 0; - if (property != null && property.hasMultipleDifferentValues) - initialSelection = 0; // don't select anything on multi selection - - if (ShouldTreeViewBeUsed(requiredType)) - { - m_ObjectTreeWithSearch.Init(position, this, CreateAndSetTreeView, TreeViewSelection, ItemWasDoubleClicked, initialSelection, 0); - } - else - { - // To frame the selected item we need to wait to initialize the search until our window has been setup - InitIfNeeded(); - m_ListArea.InitSelection(new[] { initialSelection }); - if (initialSelection != 0) - m_ListArea.Frame(initialSelection, true, false); - } - } - - void ItemWasDoubleClicked() - { - Close(); - GUIUtility.ExitGUI(); - } - - // TreeView Section - - void CreateAndSetTreeView(ObjectTreeForSelector.TreeSelectorData data) - { - TreeViewForAudioMixerGroup.CreateAndSetTreeView(data); - } - - void TreeViewSelection(TreeViewItem item) - { - if (m_ObjectSelectorReceiver != null) - { - m_ObjectSelectorReceiver.OnSelectionChanged(GetCurrentObject()); - } - - if (m_OnObjectSelectorUpdated != null) - { - m_OnObjectSelectorUpdated(GetCurrentObject()); - } - - SendEvent(ObjectSelectorUpdatedCommand, true); - } - - // Grid Section - - void InitIfNeeded() - { - if (m_ListAreaState == null) - m_ListAreaState = new ObjectListAreaState(); // is serialized - - if (m_ListArea == null) - { - m_ListArea = new ObjectListArea(m_ListAreaState, this, true); - m_ListArea.allowDeselection = false; - m_ListArea.allowDragging = false; - m_ListArea.allowFocusRendering = false; - m_ListArea.allowMultiSelect = false; - m_ListArea.allowRenaming = false; - m_ListArea.allowBuiltinResources = true; - m_ListArea.repaintCallback += Repaint; - m_ListArea.itemSelectedCallback += ListAreaItemSelectedCallback; - m_ListArea.gridSize = m_StartGridSize.value; - - FilterSettingsChanged(); - } - } - - public static UnityObject GetCurrentObject() - { - return EditorUtility.InstanceIDToObject(ObjectSelector.get.GetSelectedInstanceID()); - } - - // This is the public Object that the inspector might revert to - public static UnityObject GetInitialObject() - { - return ObjectSelector.get.m_OriginalSelection; - } - - // This is our search field - void SearchArea() - { - GUI.Label(new Rect(0, 0, position.width, m_ToolbarHeight), GUIContent.none, m_Styles.toolbarBack); - - // ESC clears search field and removes it's focus. But if we get an esc event we only want to clear search field. - // So we need special handling afterwards. - bool wasEscape = Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape; - - GUI.SetNextControlName("SearchFilter"); - string searchFilter = EditorGUI.SearchField(new Rect(5, 5, position.width - 10, 15), m_SearchFilter); - - if (wasEscape && Event.current.type == EventType.Used) - { - // If we hit esc and the string WAS empty, it's an actual cancel event. - if (m_SearchFilter == "") - Cancel(); - - // Otherwise the string has been cleared and focus has been lost. We don't have anything else to recieve focus, so we want to refocus the search field. - m_FocusSearchFilter = true; - } - - if (searchFilter != m_SearchFilter || m_FocusSearchFilter) - { - m_SearchFilter = searchFilter; - FilterSettingsChanged(); - Repaint(); - } - - if (m_FocusSearchFilter) - { - EditorGUI.FocusTextInControl("SearchFilter"); - m_FocusSearchFilter = false; - } - - GUI.changed = false; - - // TAB BAR - GUILayout.BeginArea(new Rect(0, 26, position.width, m_ToolbarHeight - 26)); - GUILayout.BeginHorizontal(); - - // Asset Tab - bool showAssets = GUILayout.Toggle(m_IsShowingAssets, "Assets", m_Styles.tab); - if (!m_IsShowingAssets && showAssets) - m_IsShowingAssets = true; - - - // The Scene Tab - if (!m_AllowSceneObjects) - { - GUI.enabled = false; - GUI.color = new Color(1, 1, 1, 0); - } - - bool showingSceneTab = !m_IsShowingAssets; - showingSceneTab = GUILayout.Toggle(showingSceneTab, "Scene", m_Styles.tab); - if (m_IsShowingAssets && showingSceneTab) - m_IsShowingAssets = false; - - - if (!m_AllowSceneObjects) - { - GUI.color = new Color(1, 1, 1, 1); - GUI.enabled = true; - } - - GUILayout.EndHorizontal(); - GUILayout.EndArea(); - - if (GUI.changed) - FilterSettingsChanged(); - - if (m_ListArea.CanShowThumbnails()) - { - EditorGUI.BeginChangeCheck(); - int newGridSize = (int)GUI.HorizontalSlider(new Rect(position.width - 60, 26, 55, m_ToolbarHeight - 28), m_ListArea.gridSize, m_ListArea.minGridSize, m_ListArea.maxGridSize); - if (EditorGUI.EndChangeCheck()) - { - m_ListArea.gridSize = newGridSize; - } - } - } - - void OnInspectorUpdate() - { - if (m_ListArea != null && AssetPreview.HasAnyNewPreviewTexturesAvailable(m_ListArea.GetAssetPreviewManagerID())) - Repaint(); - } - - // This is the preview area at the bottom of the screen - void PreviewArea() - { - GUI.Box(new Rect(0, m_TopSize, position.width, m_PreviewSize), "", m_Styles.previewBackground); - - if (m_ListArea.GetSelection().Length == 0) - return; - - EditorWrapper p = null; - UnityObject selectedObject = GetCurrentObject(); - if (m_PreviewSize < kPreviewExpandedAreaHeight) - { - // Get info string - string s; - if (selectedObject != null) - { - p = m_EditorCache[selectedObject]; - string typeName = ObjectNames.NicifyVariableName(selectedObject.GetType().Name); - if (p != null) - s = p.name + " (" + typeName + ")"; - else - s = selectedObject.name + " (" + typeName + ")"; - - s += " " + AssetDatabase.GetAssetPath(selectedObject); - } - else - s = "None"; - - LinePreview(s, selectedObject, p); - } - else - { - if (m_EditorCache == null) - m_EditorCache = new EditorCache(EditorFeatures.PreviewGUI); - - // Get info string - string s; - if (selectedObject != null) - { - p = m_EditorCache[selectedObject]; - string typeName = ObjectNames.NicifyVariableName(selectedObject.GetType().Name); - if (p != null) - { - s = p.GetInfoString(); - if (s != "") - s = p.name + "\n" + typeName + "\n" + s; - else - s = p.name + "\n" + typeName; - } - else - { - s = selectedObject.name + "\n" + typeName; - } - - s += "\n" + AssetDatabase.GetAssetPath(selectedObject); - } - else - s = "None"; - - // Make previews - if (m_ShowWidePreview.faded != 0.0f) - { - GUI.color = new Color(1, 1, 1, m_ShowWidePreview.faded); - WidePreview(m_PreviewSize, s, selectedObject, p); - } - if (m_ShowOverlapPreview.faded != 0.0f) - { - GUI.color = new Color(1, 1, 1, m_ShowOverlapPreview.faded); - OverlapPreview(m_PreviewSize, s, selectedObject, p); - } - GUI.color = Color.white; - m_EditorCache.CleanupUntouchedEditors(); - } - } - - void WidePreview(float actualSize, string s, UnityObject o, EditorWrapper p) - { - float margin = kPreviewMargin; - Rect previewRect = new Rect(margin, m_TopSize + margin, actualSize - margin * 2, actualSize - margin * 2); - - Rect labelRect = new Rect(m_PreviewSize + 3, m_TopSize + (m_PreviewSize - kPreviewExpandedAreaHeight) * 0.5f, m_Parent.window.position.width - m_PreviewSize - 3 - margin, kPreviewExpandedAreaHeight); - - if (p != null && p.HasPreviewGUI()) - p.OnPreviewGUI(previewRect, m_Styles.previewTextureBackground); - else if (o != null) - DrawObjectIcon(previewRect, m_ListArea.m_SelectedObjectIcon); - - if (EditorGUIUtility.isProSkin) - EditorGUI.DropShadowLabel(labelRect, s, m_Styles.smallStatus); - else - GUI.Label(labelRect, s, m_Styles.smallStatus); - } - - void OverlapPreview(float actualSize, string s, UnityObject o, EditorWrapper p) - { - float margin = kPreviewMargin; - Rect previewRect = new Rect(margin, m_TopSize + margin, position.width - margin * 2, actualSize - margin * 2); - - if (p != null && p.HasPreviewGUI()) - p.OnPreviewGUI(previewRect, m_Styles.previewTextureBackground); - else if (o != null) - DrawObjectIcon(previewRect, m_ListArea.m_SelectedObjectIcon); - - if (EditorGUIUtility.isProSkin) - EditorGUI.DropShadowLabel(previewRect, s, m_Styles.largeStatus); - else - EditorGUI.DoDropShadowLabel(previewRect, EditorGUIUtility.TempContent(s), m_Styles.largeStatus, .3f); - } - - void LinePreview(string s, UnityObject o, EditorWrapper p) - { - if (m_ListArea.m_SelectedObjectIcon != null) - GUI.DrawTexture(new Rect(2, (int)(m_TopSize + 2), 16, 16), m_ListArea.m_SelectedObjectIcon, ScaleMode.StretchToFill); - Rect labelRect = new Rect(20, m_TopSize + 1, position.width - 22, 18); - if (EditorGUIUtility.isProSkin) - EditorGUI.DropShadowLabel(labelRect, s, m_Styles.smallStatus); - else - GUI.Label(labelRect, s, m_Styles.smallStatus); - } - - void DrawObjectIcon(Rect position, Texture icon) - { - if (icon == null) - return; - int size = Mathf.Min((int)position.width, (int)position.height); - if (size >= icon.width * 2) - size = icon.width * 2; - - FilterMode temp = icon.filterMode; - icon.filterMode = FilterMode.Point; - GUI.DrawTexture(new Rect(position.x + ((int)position.width - size) / 2, position.y + ((int)position.height - size) / 2, size, size), icon, ScaleMode.ScaleToFit); - icon.filterMode = temp; - } - - // Resize the preview area - void ResizeBottomPartOfWindow() - { - GUI.changed = false; - - // Handle preview size - m_PreviewSize = m_PreviewResizer.ResizeHandle(position, kPreviewExpandedAreaHeight + kPreviewMargin * 2 - 20, kMinTopSize + 20, 20) + 20; - m_TopSize = position.height - m_PreviewSize; - - bool open = PreviewIsOpen(); - bool wide = PreviewIsWide(); - m_ShowOverlapPreview.target = open && !wide; - m_ShowWidePreview.target = open && wide; - } - - bool PreviewIsOpen() - { - return m_PreviewSize >= 32 + kPreviewMargin; - } - - bool PreviewIsWide() - { - return position.width - m_PreviewSize - kPreviewMargin > Mathf.Min(m_PreviewSize * 2 - 20, 256); - } - - // send an event to the delegate view (the view that called us) - void SendEvent(string eventName, bool exitGUI) - { - if (m_DelegateView) - { - Event e = EditorGUIUtility.CommandEvent(eventName); - - try - { - m_DelegateView.SendEvent(e); - } - finally - { - } - if (exitGUI) - GUIUtility.ExitGUI(); - } - } - - void HandleKeyboard() - { - // Handle events on the object selector window - if (Event.current.type != EventType.KeyDown) - return; - - switch (Event.current.keyCode) - { - case KeyCode.Return: - case KeyCode.KeypadEnter: - Close(); - GUI.changed = true; - GUIUtility.ExitGUI(); - break; - default: - //Debug.Log ("Unhandled " + Event.current.keyCode); - return; - } - Event.current.Use(); - GUI.changed = true; - } - - void Cancel() - { - // Undo changes we have done in the ObjectSelector - Undo.RevertAllDownToGroup(m_ModalUndoGroup); - - // Clear selection so that object field doesn't grab it - m_ListArea.InitSelection(new int[0]); - m_ObjectTreeWithSearch.Clear(); - - Close(); - GUI.changed = true; - GUIUtility.ExitGUI(); - } - - void OnDestroy() - { - if (m_ListArea != null) - m_ListArea.OnDestroy(); - - m_ObjectTreeWithSearch.Clear(); - } - - void OnGUI() - { - HandleKeyboard(); - - if (m_ObjectTreeWithSearch.IsInitialized()) - OnObjectTreeGUI(); - else - OnObjectGridGUI(); - - // Must be after gui so search field can use the Escape event if it has focus - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) - Cancel(); - } - - void OnObjectTreeGUI() - { - m_ObjectTreeWithSearch.OnGUI(new Rect(0, 0, position.width, position.height)); - } - - void OnObjectGridGUI() - { - InitIfNeeded(); - - // Initialize m_Styles - if (m_Styles == null) - m_Styles = new Styles(); - - if (m_EditorCache == null) - m_EditorCache = new EditorCache(EditorFeatures.PreviewGUI); - - // Handle window/preview stuff - ResizeBottomPartOfWindow(); - - Rect p = position; - EditorPrefs.SetFloat("ObjectSelectorWidth", p.width); - EditorPrefs.SetFloat("ObjectSelectorHeight", p.height); - - GUI.BeginGroup(new Rect(0, 0, position.width, position.height), GUIContent.none); - - // We want to check for arrow key presses first of all to allow arrow navigation - // of grid/list even when search field has focus (which it has when the window opens). - // That means arrows won't affect the cursor position in the text field - // but that's by design (was the same in 3.4). - m_ListArea.HandleKeyboard(false); - - SearchArea(); - GridListArea(); - PreviewArea(); - - GUI.EndGroup(); - - // overlay preview resize widget - GUI.Label(new Rect(position.width * .5f - 16, position.height - m_PreviewSize + 2, 32, m_Styles.bottomResize.fixedHeight), GUIContent.none, m_Styles.bottomResize); - } - - void GridListArea() - { - int listKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard); - m_ListArea.OnGUI(listPosition, listKeyboardControlID); - } - } -} diff --git a/Editor/Mono/ObjectTreeForSelector.cs b/Editor/Mono/ObjectTreeForSelector.cs deleted file mode 100644 index 87b9bd47c5..0000000000 --- a/Editor/Mono/ObjectTreeForSelector.cs +++ /dev/null @@ -1,375 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Text; -using UnityEditor.IMGUI.Controls; -using UnityEngine; -using UnityEngine.Events; - -namespace UnityEditor -{ - // Description: Since TreeView is not serialized the client should set the tree view when requested - // by ObjectTreeSelector. Requested by calling treeViewNeededCallback provided by the client, - // use SetTreeView() to set tree view. - - [Serializable] - internal class ObjectTreeForSelector - { - internal class TreeSelectorData - { - public ObjectTreeForSelector objectTreeForSelector; - public EditorWindow editorWindow; - public TreeViewState state; - public Rect treeViewRect; - public int userData; - } - - EditorWindow m_Owner; - TreeViewController m_TreeView; - TreeViewState m_TreeViewState; - bool m_FocusSearchFilter; - int m_ErrorCounter; - int m_OriginalSelectedID; - int m_UserData; - int m_LastSelectedID = -1; - string m_SelectedPath = ""; - const string kSearchFieldTag = "TreeSearchField"; - const float kBottomBarHeight = 17f; - const float kTopBarHeight = 27f; - SelectionEvent m_SelectionEvent; - TreeViewNeededEvent m_TreeViewNeededEvent; - DoubleClickedEvent m_DoubleClickedEvent; - - [Serializable] public class SelectionEvent : UnityEvent {} - [Serializable] public class TreeViewNeededEvent : UnityEvent {} - [Serializable] public class DoubleClickedEvent : UnityEvent {} - - class Styles - { - public GUIStyle searchBg = new GUIStyle("ProjectBrowserTopBarBg"); - public GUIStyle bottomBarBg = new GUIStyle("ProjectBrowserBottomBarBg"); - public Styles() - { - searchBg.border = new RectOffset(0, 0, 2, 2); - searchBg.fixedHeight = 0; - - bottomBarBg.alignment = TextAnchor.MiddleLeft; - bottomBarBg.fontSize = EditorStyles.label.fontSize; - bottomBarBg.padding = new RectOffset(5, 5, 0, 0); - } - } - static Styles s_Styles; - - public bool IsInitialized() - { - return m_Owner != null; - } - - public void Init( - Rect position, - EditorWindow owner, - UnityAction treeViewNeededCallback, - UnityAction selectionCallback, - UnityAction doubleClickedCallback, - int initialSelectedTreeViewItemID, - int userData) - { - Clear(); - - m_Owner = owner; - - m_TreeViewNeededEvent = new TreeViewNeededEvent(); - m_TreeViewNeededEvent.AddPersistentListener(treeViewNeededCallback, UnityEventCallState.EditorAndRuntime); - - m_SelectionEvent = new SelectionEvent(); - m_SelectionEvent.AddPersistentListener(selectionCallback, UnityEventCallState.EditorAndRuntime); - - m_DoubleClickedEvent = new DoubleClickedEvent(); - m_DoubleClickedEvent.AddPersistentListener(doubleClickedCallback, UnityEventCallState.EditorAndRuntime); - - m_OriginalSelectedID = initialSelectedTreeViewItemID; - m_UserData = userData; - - m_FocusSearchFilter = true; // start by focusing search field - - // Initial setup - EnsureTreeViewIsValid(GetTreeViewRect(position)); - if (m_TreeView != null) - { - m_TreeView.SetSelection(new[] { m_OriginalSelectedID }, true); - // If nothing is selected we expand all to better start overview. If we have a selection it has been revealed in SetSelection above - if (m_OriginalSelectedID == 0) - m_TreeView.data.SetExpandedWithChildren(m_TreeView.data.root, true); - } - } - - public void Clear() - { - m_Owner = null; - m_TreeViewNeededEvent = null; - m_SelectionEvent = null; - - m_DoubleClickedEvent = null; - m_OriginalSelectedID = 0; - m_UserData = 0; - - m_TreeView = null; - m_TreeViewState = null; - m_ErrorCounter = 0; - m_FocusSearchFilter = false; - } - - public int[] GetSelection() - { - if (m_TreeView != null) - return m_TreeView.GetSelection(); - - return new int[0]; - } - - // Call this when requested by ObjectTreeSelector (it calls treeViewNeededCallback) - public void SetTreeView(TreeViewController treeView) - { - m_TreeView = treeView; - - // Hook up to tree view events - m_TreeView.selectionChangedCallback -= OnItemSelectionChanged; - m_TreeView.selectionChangedCallback += OnItemSelectionChanged; - m_TreeView.itemDoubleClickedCallback -= OnItemDoubleClicked; - m_TreeView.itemDoubleClickedCallback += OnItemDoubleClicked; - } - - bool EnsureTreeViewIsValid(Rect treeViewRect) - { - if (m_TreeViewState == null) - m_TreeViewState = new TreeViewState(); - - if (m_TreeView == null) - { - var input = new TreeSelectorData() - { - state = m_TreeViewState, - treeViewRect = treeViewRect, - userData = m_UserData, - objectTreeForSelector = this, - editorWindow = m_Owner - }; - - m_TreeViewNeededEvent.Invoke(input); - if (m_TreeView != null) - { - if (m_TreeView.data.root == null) - { - m_TreeView.ReloadData(); - } - } - - if (m_TreeView == null) - { - if (m_ErrorCounter == 0) - { - Debug.LogError("ObjectTreeSelector is missing its tree view. Ensure to call 'SetTreeView()' when the treeViewNeededCallback is invoked!"); - m_ErrorCounter++; - } - return false; - } - } - return true; - } - - Rect GetTreeViewRect(Rect position) - { - return new Rect(0, kTopBarHeight, position.width, position.height - kBottomBarHeight - kTopBarHeight); - } - - public void OnGUI(Rect position) - { - if (s_Styles == null) - s_Styles = new Styles(); - - Rect rect = new Rect(0, 0, position.width, position.height); - Rect toolbarRect = new Rect(rect.x, rect.y, rect.width, kTopBarHeight); - Rect bottomRect = new Rect(rect.x, rect.yMax - kBottomBarHeight, rect.width, kBottomBarHeight); - Rect treeViewRect = GetTreeViewRect(position); - - if (!EnsureTreeViewIsValid(treeViewRect)) - return; - - int treeViewControlID = GUIUtility.GetControlID("Tree".GetHashCode(), FocusType.Keyboard); - - HandleCommandEvents(); - HandleKeyboard(treeViewControlID); - SearchArea(toolbarRect); - TreeViewArea(treeViewRect, treeViewControlID); - BottomBar(bottomRect); - } - - void BottomBar(Rect bottomRect) - { - int currentID = m_TreeView.GetSelection().FirstOrDefault(); // 0 is none selected - - // Refresh cached string - if (currentID != m_LastSelectedID) - { - m_LastSelectedID = currentID; - m_SelectedPath = ""; - var selected = m_TreeView.FindItem(currentID); - if (selected != null) - { - StringBuilder sb = new StringBuilder(); - var item = selected; - while (item != null && item != m_TreeView.data.root) - { - if (item != selected) - sb.Insert(0, "/"); - sb.Insert(0, item.displayName); - item = item.parent; - } - m_SelectedPath = sb.ToString(); - } - } - - GUI.Label(bottomRect, GUIContent.none, s_Styles.bottomBarBg); - if (!string.IsNullOrEmpty(m_SelectedPath)) - GUI.Label(bottomRect, GUIContent.Temp(m_SelectedPath), EditorStyles.miniLabel); - } - - private void OnItemDoubleClicked(int id) - { - if (m_DoubleClickedEvent != null) - m_DoubleClickedEvent.Invoke(); - } - - private void OnItemSelectionChanged(int[] selection) - { - if (m_SelectionEvent != null) - { - TreeViewItem item = null; - if (selection.Length > 0) - { - item = m_TreeView.FindItem(selection[0]); - } - FireSelectionEvent(item); - } - } - - void HandleKeyboard(int treeViewControlID) - { - if (Event.current.type != EventType.KeyDown) - return; - - switch (Event.current.keyCode) - { - case KeyCode.DownArrow: - case KeyCode.UpArrow: - { - // When searchfield has focus give keyboard focus to the tree view on Down/UpArrow - bool hasSearchFilterFocus = GUI.GetNameOfFocusedControl() == kSearchFieldTag; - if (hasSearchFilterFocus) - { - GUIUtility.keyboardControl = treeViewControlID; - - // If nothing is selected ensure first item is selected, otherwise ensure current - // selection is visible (we just gave focus to the tree) - if (m_TreeView.IsLastClickedPartOfRows()) - FrameSelectedTreeViewItem(); - else - m_TreeView.OffsetSelection(1); // Selects first item - - Event.current.Use(); - } - } - break; - default: - return; - } - } - - void FrameSelectedTreeViewItem() - { - m_TreeView.Frame(m_TreeView.state.lastClickedID, true, false); - } - - void HandleCommandEvents() - { - Event evt = Event.current; - - if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand) - return; - - if (evt.commandName == EventCommandNames.FrameSelected) - { - if (evt.type == EventType.ExecuteCommand && m_TreeView.HasSelection()) - { - m_TreeView.searchString = string.Empty; - FrameSelectedTreeViewItem(); - } - evt.Use(); - GUIUtility.ExitGUI(); - } - if (evt.commandName == EventCommandNames.Find) - { - if (evt.type == EventType.ExecuteCommand) - { - FocusSearchField(); - } - evt.Use(); - } - } - - void FireSelectionEvent(TreeViewItem item) - { - if (m_SelectionEvent != null) - m_SelectionEvent.Invoke(item); - } - - void TreeViewArea(Rect treeViewRect, int treeViewControlID) - { - bool hasRows = m_TreeView.data.rowCount > 0; - if (hasRows) - { - m_TreeView.OnGUI(treeViewRect, treeViewControlID); - } - } - - void SearchArea(Rect toolbarRect) - { - GUI.Label(toolbarRect, GUIContent.none, s_Styles.searchBg); - - // ESC clears search field and removes it's focus. But if we get an esc event we only want to clear search field. - // So we need special handling afterwards. - bool wasEscape = Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape; - GUI.SetNextControlName(kSearchFieldTag); - string newSearchFilter = EditorGUI.SearchField(new Rect(5, 5, toolbarRect.width - 10, 15), m_TreeView.searchString); - - if (wasEscape && Event.current.type == EventType.Used) - { - // If we hit esc and the string WAS empty, it's an actual cancel event. - if (m_TreeView.searchString != string.Empty) - // Otherwise the string has been cleared and focus has been lost. We don't have anything else to recieve focus, so we want to refocus the search field. - m_FocusSearchFilter = true; - } - - if (newSearchFilter != m_TreeView.searchString || m_FocusSearchFilter) - { - m_TreeView.searchString = newSearchFilter; - HandleUtility.Repaint(); - } - - if (m_FocusSearchFilter) - { - EditorGUI.FocusTextInControl(kSearchFieldTag); - if (Event.current.type == EventType.Repaint) - m_FocusSearchFilter = false; - } - } - - internal void FocusSearchField() - { - m_FocusSearchFilter = true; - } - } -} // namespace diff --git a/Editor/Mono/PackageUtility.bindings.cs b/Editor/Mono/PackageUtility.bindings.cs deleted file mode 100644 index ae732e0e95..0000000000 --- a/Editor/Mono/PackageUtility.bindings.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; -using System; -using System.Runtime.InteropServices; - -namespace UnityEditor -{ -#pragma warning disable 649 - [StructLayout(LayoutKind.Sequential)] - [Serializable] - [NativeType(CodegenOptions.Custom, "MonoImportPackageItem", Header = "Editor/Mono/PackageUtility.bindings.h")] - [NativeAsStruct] - internal class ImportPackageItem - { - public string exportedAssetPath; - public string destinationAssetPath; - public string sourceFolder; - public string previewPath; - public string guid; - public int enabledStatus; - public bool isFolder; - public bool exists; - public bool assetChanged; - public bool pathConflict; - public bool projectAsset; - } - - [StructLayout(LayoutKind.Sequential)] - [Serializable] - [NativeAsStruct] - [NativeType(CodegenOptions.Custom, "MonoExportPackageItem", Header = "Editor/Mono/PackageUtility.bindings.h")] - internal class ExportPackageItem - { - public string assetPath; - public string guid; - public bool isFolder; - public int enabledStatus; - } - - //*undocumented* - [StructLayout(LayoutKind.Sequential)] - [NativeType(CodegenOptions.Custom, "MonoPackageInfo", Header = "Editor/Src/PackageUtility.h")] - public struct PackageInfo - { - public string packagePath; - public string jsonInfo; - public string iconURL; - - [FreeFunction] - internal static extern PackageInfo[] GetPackageList(); - } - - [NativeHeader("Editor/Mono/PackageUtility.bindings.h")] - internal class PackageUtility - { - [NativeThrows] - public static extern ExportPackageItem[] BuildExportPackageItemsList(string[] guids, bool dependencies); - [NativeThrows] - public static extern void ExportPackage(string[] guids, string fileName); - public static extern ImportPackageItem[] ExtractAndPrepareAssetList(string packagePath, out string packageIconPath, out bool canPerformReInstall); - - [FreeFunction("DelayedImportPackageAssets")] - public static extern void ImportPackageAssets(string packageName, ImportPackageItem[] items, bool performReInstall); - [FreeFunction("ImportPackageAssets")] - public static extern void ImportPackageAssetsImmediately(string packageName, ImportPackageItem[] items, bool performReInstall); - } -} diff --git a/Editor/Mono/ParticleSystemEditor/ParticleEffectUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleEffectUI.cs deleted file mode 100644 index 9425309739..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleEffectUI.cs +++ /dev/null @@ -1,1083 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.Rendering; - -// The ParticleEffectUI displays one or more ParticleSystemUIs. - -namespace UnityEditor -{ - internal interface ParticleEffectUIOwner - { - void Repaint(); - - Editor customEditor { get; } - } - - - internal class ParticleEffectUI - { - public ParticleEffectUIOwner m_Owner; // Can be InspectorWindow or ParticleSystemWindow - public ParticleSystemUI[] m_Emitters; // Contains UI for all ParticleSystem children of the root ParticleSystem for this effect - bool m_EmittersActiveInHierarchy; - ParticleSystemCurveEditor m_ParticleSystemCurveEditor; // The curve editor used by ParticleSystem modules - List m_SelectedParticleSystems; // This is the array of selected particle systems and used to find the root ParticleSystem and for the inspector - bool m_ShowOnlySelectedMode; - TimeHelper m_TimeHelper = new TimeHelper(); - public static ParticleSystem m_MainPlaybackSystem; - public static bool m_ShowBounds = false; - public static bool m_VerticalLayout; - const string k_SimulationStateId = "SimulationState"; - const string k_ShowSelectedId = "ShowSelected"; - enum PlayState { Stopped = 0, Playing = 1, Paused = 2 }; - - // ParticleSystemWindow Layout - static readonly Vector2 k_MinEmitterAreaSize = new Vector2(125f, 100); - static readonly Vector2 k_MinCurveAreaSize = new Vector2(100, 100); - float m_EmitterAreaWidth = 230; // Only used in ParticleSystemWindow for horizontal layout - float m_CurveEditorAreaHeight = 330; // Only used in ParticleSystemWindow for vertical layout - Vector2 m_EmitterAreaScrollPos = Vector2.zero; - static readonly Color k_DarkSkinDisabledColor = new Color(0.66f, 0.66f, 0.66f, 0.95f); - static readonly Color k_LightSkinDisabledColor = new Color(0.84f, 0.84f, 0.84f, 0.95f); - - private enum OwnerType { Inspector, ParticleSystemWindow }; - - internal class Texts - { - public GUIContent previewSpeed = EditorGUIUtility.TrTextContent("Playback Speed", "Playback Speed is also affected by the Time Scale setting in the Time Manager."); - public GUIContent previewSpeedDisabled = EditorGUIUtility.TrTextContent("Playback Speed", "Playback Speed is locked to 0.0, because the Time Scale in the Time Manager is set to 0.0."); - public GUIContent previewTime = EditorGUIUtility.TrTextContent("Playback Time"); - public GUIContent particleCount = EditorGUIUtility.TrTextContent("Particles"); - public GUIContent subEmitterParticleCount = EditorGUIUtility.TrTextContent("Sub Emitter Particles"); - public GUIContent particleSpeeds = EditorGUIUtility.TrTextContent("Speed Range"); - public GUIContent play = EditorGUIUtility.TrTextContent("Play"); - public GUIContent playDisabled = EditorGUIUtility.TrTextContent("Play", "Play is disabled, because the Time Scale in the Time Manager is set to 0.0."); - public GUIContent stop = EditorGUIUtility.TrTextContent("Stop"); - public GUIContent pause = EditorGUIUtility.TrTextContent("Pause"); - public GUIContent restart = EditorGUIUtility.TrTextContent("Restart"); - public GUIContent addParticleSystem = EditorGUIUtility.TrTextContent("", "Create Particle System"); - public GUIContent showBounds = EditorGUIUtility.TrTextContent("Show Bounds", "Show world space bounding boxes."); - public GUIContent resimulation = EditorGUIUtility.TrTextContent("Resimulate", "If resimulate is enabled, the Particle System will show changes made to the system immediately (including changes made to the Particle System Transform)."); - public GUIContent previewLayers = EditorGUIUtility.TrTextContent("Simulate Layers", "Automatically preview all looping Particle Systems on the chosen layers, in addition to the selected Game Objects."); - public string secondsFloatFieldFormatString = "f2"; - public string speedFloatFieldFormatString = "f1"; - } - private static Texts s_Texts; - internal static Texts texts - { - get - { - if (s_Texts == null) - s_Texts = new Texts(); - return s_Texts; - } - } - - static PrefKey kPlay = new PrefKey("ParticleSystem/Play", ","); - static PrefKey kStop = new PrefKey("ParticleSystem/Stop", "."); - static PrefKey kForward = new PrefKey("ParticleSystem/Forward", "m"); - static PrefKey kReverse = new PrefKey("ParticleSystem/Reverse", "n"); - - public ParticleEffectUI(ParticleEffectUIOwner owner) - { - m_Owner = owner; - System.Diagnostics.Debug.Assert(m_Owner is ParticleSystemInspector || m_Owner is ParticleSystemWindow); - } - - public bool multiEdit { get { return (m_SelectedParticleSystems != null) && (m_SelectedParticleSystems.Count > 1); } } - - private bool ShouldManagePlaybackState(ParticleSystem root) - { - bool active = false; - if (root != null) - active = root.gameObject.activeInHierarchy; - return !EditorApplication.isPlaying && active; - } - - static Color GetDisabledColor() - { - return (!EditorGUIUtility.isProSkin) ? k_LightSkinDisabledColor : k_DarkSkinDisabledColor; - } - - // Returns a list with 'root' and all its direct children. - static internal ParticleSystem[] GetParticleSystems(ParticleSystem root) - { - List particleSystems = new List(); - particleSystems.Add(root); - GetDirectParticleSystemChildrenRecursive(root.transform, particleSystems); - return particleSystems.ToArray(); - } - - // Adds only active Particle Systems - static private void GetDirectParticleSystemChildrenRecursive(Transform transform, List particleSystems) - { - foreach (Transform childTransform in transform) - { - ParticleSystem ps = childTransform.gameObject.GetComponent(); - if (ps != null) - { - // Note: we do not check for if the gameobject is active (we want inactive particle systems as well due prefabs) - particleSystems.Add(ps); - GetDirectParticleSystemChildrenRecursive(childTransform, particleSystems); - } - } - } - - // Should be called often to ensure we catch if selected Particle System is dragged in/out of root hierarchy - public bool InitializeIfNeeded(IEnumerable systems) - { - bool anyAdded = false; - - ParticleSystem[] allSystems = systems.ToArray(); - bool usingMultiEdit = (allSystems.Count() > 1); - - bool initializeRequired = false; - ParticleSystem mainSystem = null; - - foreach (ParticleSystem shuriken in allSystems) - { - ParticleSystem[] shurikens; - if (!usingMultiEdit) - { - ParticleSystem root = ParticleSystemEditorUtils.GetRoot(shuriken); - if (root == null) - continue; - - shurikens = GetParticleSystems(root); - mainSystem = root; - - // Check if we need to re-initialize? - if (m_SelectedParticleSystems != null && m_SelectedParticleSystems.Count > 0) - { - if (root == ParticleSystemEditorUtils.GetRoot(m_SelectedParticleSystems[0])) - { - if (m_ParticleSystemCurveEditor != null && m_Emitters != null && shurikens.Length == m_Emitters.Length && shuriken.gameObject.activeInHierarchy == m_EmittersActiveInHierarchy) - { - m_SelectedParticleSystems = new List(); - m_SelectedParticleSystems.Add(shuriken); - - if (IsShowOnlySelectedMode()) - RefreshShowOnlySelected(); // always refresh - - continue; - } - } - } - } - else - { - // in multi-edit mode, we explicitly choose the systems to edit, so don't automatically add child systems or search for the root - shurikens = new ParticleSystem[] { shuriken }; - mainSystem = shuriken; - } - - // Cleanup before initializing - if (m_ParticleSystemCurveEditor != null) - Clear(); - - // Now initialize - initializeRequired = true; - if (!anyAdded) - { - m_SelectedParticleSystems = new List(); - anyAdded = true; - } - m_SelectedParticleSystems.Add(shuriken); - - // Single edit emitter setup - if (!usingMultiEdit) - { - // Init CurveEditor before modules (they may add curves during construction) - m_ParticleSystemCurveEditor = new ParticleSystemCurveEditor(); - m_ParticleSystemCurveEditor.Init(); - - int numEmitters = shurikens.Length; - if (numEmitters > 0) - { - m_Emitters = new ParticleSystemUI[numEmitters]; - - for (int i = 0; i < numEmitters; ++i) - { - m_Emitters[i] = new ParticleSystemUI(); - m_Emitters[i].Init(this, new ParticleSystem[] { shurikens[i] }); - } - - m_EmittersActiveInHierarchy = shuriken.gameObject.activeInHierarchy; - } - } - } - - if (initializeRequired) - { - // Multi-edit emitter setup - if (usingMultiEdit) - { - // Init CurveEditor before modules (they may add curves during construction) - m_ParticleSystemCurveEditor = new ParticleSystemCurveEditor(); - m_ParticleSystemCurveEditor.Init(); - - int numEmitters = m_SelectedParticleSystems.Count; - if (numEmitters > 0) - { - m_Emitters = new ParticleSystemUI[1]; - m_Emitters[0] = new ParticleSystemUI(); - m_Emitters[0].Init(this, m_SelectedParticleSystems.ToArray()); - m_EmittersActiveInHierarchy = m_SelectedParticleSystems[0].gameObject.activeInHierarchy; - } - } - - // Allow modules to validate their state (the user can have moved emitters around in the hierarchy) - foreach (ParticleSystemUI e in m_Emitters) - foreach (ModuleUI m in e.m_Modules) - if (m != null) - m.Validate(); - - // Sync to state - if (GetAllModulesVisible()) - SetAllModulesVisible(true); - - m_EmitterAreaWidth = EditorPrefs.GetFloat("ParticleSystemEmitterAreaWidth", k_MinEmitterAreaSize.x); - m_CurveEditorAreaHeight = EditorPrefs.GetFloat("ParticleSystemCurveEditorAreaHeight", k_MinCurveAreaSize.y); - - // For now only allow ShowOnlySelectedMode for ParticleSystemWindow - SetShowOnlySelectedMode((m_Owner is ParticleSystemWindow) ? SessionState.GetBool(k_ShowSelectedId + mainSystem.GetInstanceID(), false) : false); - - m_EmitterAreaScrollPos.x = SessionState.GetFloat("CurrentEmitterAreaScroll", 0.0f); - - if (ShouldManagePlaybackState(mainSystem)) - { - // Restore lastPlayBackTime if available in session cache - Vector3 simulationState = SessionState.GetVector3(k_SimulationStateId + mainSystem.GetInstanceID(), Vector3.zero); - if (mainSystem.GetInstanceID() == (int)simulationState.x) - { - float lastPlayBackTime = simulationState.z; - if (lastPlayBackTime > 0f) - { - ParticleSystemEditorUtils.playbackTime = lastPlayBackTime; - ParticleSystemEditorUtils.PerformCompleteResimulation(); - } - } - - // Play when selecting a new particle effect - if (m_MainPlaybackSystem != mainSystem) - Play(); - } - } - - m_MainPlaybackSystem = mainSystem; - - return initializeRequired; - } - - internal void UndoRedoPerformed() - { - Refresh(); - foreach (ParticleSystemUI e in m_Emitters) - { - foreach (ModuleUI moduleUI in e.m_Modules) - { - if (moduleUI != null) - { - moduleUI.CheckVisibilityState(); - - if (moduleUI.foldout) - moduleUI.UndoRedoPerformed(); - } - } - } - - m_Owner.Repaint(); - } - - public void Clear() - { - ParticleSystem root = ParticleSystemEditorUtils.GetRoot(m_SelectedParticleSystems[0]); // root can have been deleted - if (ShouldManagePlaybackState(root)) - { - // Store simulation state of current effect as Vector3 (rootInstanceID, isPlaying, playBackTime) - if (root != null) - { - PlayState playState; - if (IsPlaying()) - playState = PlayState.Playing; - else if (IsPaused()) - playState = PlayState.Paused; - else - playState = PlayState.Stopped; - int rootInstanceId = root.GetInstanceID(); - SessionState.SetVector3(k_SimulationStateId + rootInstanceId, new Vector3(rootInstanceId, (int)playState, ParticleSystemEditorUtils.playbackTime)); - } - - // Stop the ParticleSystem here (prevents it being frozen on screen) - //Stop(); - } - - m_ParticleSystemCurveEditor.OnDisable(); - Tools.s_Hidden = false; // The collisionmodule might have hidden the tools - - if (root != null) - SessionState.SetBool(k_ShowSelectedId + root.GetInstanceID(), m_ShowOnlySelectedMode); - SetShowOnlySelectedMode(false); - - GameView.RepaintAll(); - SceneView.RepaintAll(); - } - - static public Vector2 GetMinSize() - { - return k_MinEmitterAreaSize + k_MinCurveAreaSize; - } - - public void Refresh() - { - UpdateProperties(); - m_ParticleSystemCurveEditor.Refresh(); - } - - public string GetNextParticleSystemName() - { - string nextName = ""; - for (int i = 2; i < 50; ++i) - { - nextName = L10n.Tr("Particle System ") + i; - bool found = false; - foreach (ParticleSystemUI e in m_Emitters) - { - if (e.m_ParticleSystems.FirstOrDefault(o => o.name == nextName) != null) - { - found = true; - break; - } - } - if (!found) - return nextName; - } - return L10n.Tr("Particle System"); - } - - public bool IsParticleSystemUIVisible(ParticleSystemUI psUI) - { - OwnerType ownerType = m_Owner is ParticleSystemInspector ? OwnerType.Inspector : OwnerType.ParticleSystemWindow; - if (ownerType == OwnerType.ParticleSystemWindow) - return true; - - // ownerType == OwnerType.Inspector - foreach (ParticleSystem ps in psUI.m_ParticleSystems) - { - if (m_SelectedParticleSystems.FirstOrDefault(o => o == ps) != null) - return true; - } - - return false; - } - - public void PlayOnAwakeChanged(bool newPlayOnAwake) - { - foreach (ParticleSystemUI psUI in m_Emitters) - { - InitialModuleUI initialModule = psUI.m_Modules[0] as InitialModuleUI; - System.Diagnostics.Debug.Assert(initialModule != null); - initialModule.m_PlayOnAwake.boolValue = newPlayOnAwake; - psUI.ApplyProperties(); - } - } - - public GameObject CreateParticleSystem(ParticleSystem parentOfNewParticleSystem, SubModuleUI.SubEmitterType defaultType) - { - string name = GetNextParticleSystemName(); - GameObject go = new GameObject(name, typeof(ParticleSystem)); - if (go) - { - if (parentOfNewParticleSystem) - go.transform.parent = parentOfNewParticleSystem.transform; - go.transform.localPosition = Vector3.zero; - go.transform.localRotation = Quaternion.identity; - - // Setup particle system based on type - ParticleSystem ps = go.GetComponent(); - if (defaultType != SubModuleUI.SubEmitterType.None) - ps.SetupDefaultType((int)defaultType); - - SessionState.SetFloat("CurrentEmitterAreaScroll", m_EmitterAreaScrollPos.x); - - // Assign default material - ParticleSystemRenderer renderer = go.GetComponent(); - Material particleMat = null; - if (GraphicsSettings.renderPipelineAsset != null) - particleMat = GraphicsSettings.renderPipelineAsset.GetDefaultParticleMaterial(); - - if (particleMat == null) - particleMat = AssetDatabase.GetBuiltinExtraResource("Default-Particle.mat"); - renderer.materials = new[] {particleMat, null}; - - Undo.RegisterCreatedObjectUndo(go, "Create ParticleSystem"); - return go; - } - return null; - } - - public ParticleSystemCurveEditor GetParticleSystemCurveEditor() - { - return m_ParticleSystemCurveEditor; - } - - private void SceneViewGUICallback(Object target, SceneView sceneView) - { - PlayStopGUI(); - } - - public void OnSceneViewGUI() - { - ParticleSystem root = ParticleSystemEditorUtils.GetRoot(m_SelectedParticleSystems[0]); - if (root && root.gameObject.activeInHierarchy) - SceneViewOverlay.Window(ParticleSystemInspector.playBackTitle, SceneViewGUICallback, (int)SceneViewOverlay.Ordering.ParticleEffect, SceneViewOverlay.WindowDisplayOption.OneWindowPerTitle); - - foreach (ParticleSystemUI e in m_Emitters) - e.OnSceneViewGUI(); - } - - int m_IsDraggingTimeHotControlID = -1; - - internal void PlayBackInfoGUI(bool isPlayMode) - { - EventType oldEventType = Event.current.type; - int oldHotControl = GUIUtility.hotControl; - string oldFormat = EditorGUI.kFloatFieldFormatString; - - EditorGUIUtility.labelWidth = 110.0f; - - if (!isPlayMode) - { - EditorGUI.kFloatFieldFormatString = s_Texts.secondsFloatFieldFormatString; - if (Time.timeScale == 0.0f) - { - using (new EditorGUI.DisabledScope(true)) - { - EditorGUILayout.FloatField(s_Texts.previewSpeedDisabled, 0.0f); - } - } - else - { - ParticleSystemEditorUtils.simulationSpeed = Mathf.Clamp(EditorGUILayout.FloatField(s_Texts.previewSpeed, ParticleSystemEditorUtils.simulationSpeed), 0f, 10f); - } - EditorGUI.kFloatFieldFormatString = oldFormat; - - EditorGUI.BeginChangeCheck(); - EditorGUI.kFloatFieldFormatString = s_Texts.secondsFloatFieldFormatString; - float playbackTime = EditorGUILayout.FloatField(s_Texts.previewTime, ParticleSystemEditorUtils.playbackTime); - EditorGUI.kFloatFieldFormatString = oldFormat; - if (EditorGUI.EndChangeCheck()) - { - if (oldEventType == EventType.MouseDrag) - { - ParticleSystemEditorUtils.playbackIsScrubbing = true; - float previewSpeed = ParticleSystemEditorUtils.simulationSpeed; - float oldplaybackTime = ParticleSystemEditorUtils.playbackTime; - float timeDiff = playbackTime - oldplaybackTime; - playbackTime = oldplaybackTime + timeDiff * (0.05F * previewSpeed); - } - - playbackTime = Mathf.Max(playbackTime, 0.0F); - ParticleSystemEditorUtils.playbackTime = playbackTime; - - foreach (ParticleSystem ps in m_SelectedParticleSystems) - { - ParticleSystem root = ParticleSystemEditorUtils.GetRoot(ps); - if (root.isStopped) - { - root.Play(); - root.Pause(); - } - } - - ParticleSystemEditorUtils.PerformCompleteResimulation(); - } - - // Detect start dragging - if (oldEventType == EventType.MouseDown && GUIUtility.hotControl != oldHotControl) - { - m_IsDraggingTimeHotControlID = GUIUtility.hotControl; - ParticleSystemEditorUtils.playbackIsScrubbing = true; - } - - // Detect stop dragging - if (m_IsDraggingTimeHotControlID != -1 && GUIUtility.hotControl != m_IsDraggingTimeHotControlID) - { - m_IsDraggingTimeHotControlID = -1; - ParticleSystemEditorUtils.playbackIsScrubbing = false; - } - } - - int particleCount = 0; - float fastestParticle = 0.0f; - float slowestParticle = Mathf.Infinity; - foreach (ParticleSystem ps in m_SelectedParticleSystems) - { - ps.CalculateEffectUIData(ref particleCount, ref fastestParticle, ref slowestParticle); - } - EditorGUILayout.LabelField(s_Texts.particleCount, GUIContent.Temp(particleCount.ToString())); - - bool hasSubEmitters = false; - int subEmitterParticles = 0; - foreach (ParticleSystem ps in m_SelectedParticleSystems) - { - int subEmitterParticlesCurrent = 0; - if (ps.CalculateEffectUISubEmitterData(ref subEmitterParticlesCurrent, ref fastestParticle, ref slowestParticle)) - { - hasSubEmitters = true; - subEmitterParticles += subEmitterParticlesCurrent; - } - } - if (hasSubEmitters) - EditorGUILayout.LabelField(s_Texts.subEmitterParticleCount, GUIContent.Temp(subEmitterParticles.ToString())); - - if (fastestParticle >= slowestParticle) - EditorGUILayout.LabelField(s_Texts.particleSpeeds, GUIContent.Temp(slowestParticle.ToString(s_Texts.speedFloatFieldFormatString) + " - " + fastestParticle.ToString(s_Texts.speedFloatFieldFormatString))); - else - EditorGUILayout.LabelField(s_Texts.particleSpeeds, GUIContent.Temp("0.0 - 0.0")); - - if (!EditorApplication.isPlaying) - { - EditorGUILayout.LayerMaskField(ParticleSystemEditorUtils.previewLayers, s_Texts.previewLayers, SetPreviewLayersDelegate); - ParticleSystemEditorUtils.resimulation = GUILayout.Toggle(ParticleSystemEditorUtils.resimulation, s_Texts.resimulation, EditorStyles.toggle); - } - - ParticleEffectUI.m_ShowBounds = GUILayout.Toggle(ParticleEffectUI.m_ShowBounds, ParticleEffectUI.texts.showBounds, EditorStyles.toggle); - - EditorGUIUtility.labelWidth = 0.0f; - } - - internal static void SetPreviewLayersDelegate(object userData, string[] options, int selected) - { - var data = (System.Tuple)userData; - ParticleSystemEditorUtils.previewLayers = SerializedProperty.ToggleLayerMask(data.Item2, selected); - } - - private void HandleKeyboardShortcuts() - { - Event evt = Event.current; - - if (evt.type == EventType.KeyDown) - { - int changeTime = 0; - if (evt.keyCode == ((Event)kPlay).keyCode) - { - if (EditorApplication.isPlaying) - { - // If world is playing Pause is not handled, just restart instead - Stop(); - Play(); - } - else - { - // In Edit mode we have full play/pause functionality - if (!ParticleSystemEditorUtils.playbackIsPlaying) - Play(); - else - Pause(); - } - evt.Use(); - } - else if (evt.keyCode == ((Event)kStop).keyCode) - { - Stop(); - evt.Use(); - } - else if (evt.keyCode == ((Event)kReverse).keyCode) - { - changeTime = -1; - } - else if (evt.keyCode == ((Event)kForward).keyCode) - { - changeTime = 1; - } - - if (changeTime != 0) - { - ParticleSystemEditorUtils.playbackIsScrubbing = true; - float previewSpeed = ParticleSystemEditorUtils.simulationSpeed; - float timeDiff = (evt.shift ? 3f : 1f) * m_TimeHelper.deltaTime * (changeTime > 0 ? 3f : -3f); - ParticleSystemEditorUtils.playbackTime = Mathf.Max(0f, ParticleSystemEditorUtils.playbackTime + timeDiff * (previewSpeed)); - - foreach (ParticleSystem ps in m_SelectedParticleSystems) - { - ParticleSystem root = ParticleSystemEditorUtils.GetRoot(ps); - if (root.isStopped) - { - root.Play(); - root.Pause(); - } - } - - ParticleSystemEditorUtils.PerformCompleteResimulation(); - evt.Use(); - } - } - - if (evt.type == EventType.KeyUp) - if (evt.keyCode == ((Event)kReverse).keyCode || evt.keyCode == ((Event)kForward).keyCode) - ParticleSystemEditorUtils.playbackIsScrubbing = false; - } - - internal static bool IsStopped(ParticleSystem root) - { - return (!ParticleSystemEditorUtils.playbackIsPlaying && !ParticleSystemEditorUtils.playbackIsPaused) && !ParticleSystemEditorUtils.playbackIsScrubbing; - } - - internal bool IsPaused() - { - return !IsPlaying() && !IsStopped(ParticleSystemEditorUtils.GetRoot(m_SelectedParticleSystems[0])); - } - - internal bool IsPlaying() - { - return ParticleSystemEditorUtils.playbackIsPlaying; - } - - internal void Play() - { - bool anyPlayed = false; - - foreach (ParticleSystem ps in m_SelectedParticleSystems) - { - ParticleSystem root = ParticleSystemEditorUtils.GetRoot(ps); - if (root) - { - root.Play(); - anyPlayed = true; - } - } - - if (anyPlayed) - { - ParticleSystemEditorUtils.playbackIsScrubbing = false; - m_Owner.Repaint(); - } - } - - internal void Pause() - { - bool anyPaused = false; - - foreach (ParticleSystem ps in m_SelectedParticleSystems) - { - ParticleSystem root = ParticleSystemEditorUtils.GetRoot(ps); - if (root) - { - root.Pause(); - anyPaused = true; - } - } - - if (anyPaused) - { - ParticleSystemEditorUtils.playbackIsScrubbing = true; - m_Owner.Repaint(); - } - } - - internal void Stop() - { - ParticleSystemEditorUtils.playbackIsScrubbing = false; - ParticleSystemEditorUtils.playbackTime = 0.0F; - ParticleSystemEffectUtils.StopEffect(); - m_Owner.Repaint(); - } - - internal void PlayStopGUI() - { - if (s_Texts == null) - s_Texts = new Texts(); - - Event evt = Event.current; - if (evt.type == EventType.Layout) - m_TimeHelper.Update(); - - bool disablePlayButton = (Time.timeScale == 0.0f); - GUIContent playText = disablePlayButton ? s_Texts.playDisabled : s_Texts.play; - - if (!EditorApplication.isPlaying) - { - // Edit Mode: Play/Stop buttons - GUILayout.BeginHorizontal(GUILayout.Width(210.0f)); - { - using (new EditorGUI.DisabledScope(disablePlayButton)) - { - bool isPlaying = ParticleSystemEditorUtils.playbackIsPlaying && !ParticleSystemEditorUtils.playbackIsPaused && !disablePlayButton; - if (GUILayout.Button(isPlaying ? s_Texts.pause : playText, "ButtonLeft")) - { - if (isPlaying) - Pause(); - else - Play(); - } - } - - if (GUILayout.Button(s_Texts.restart, "ButtonMid")) - { - Stop(); - Play(); - } - - if (GUILayout.Button(s_Texts.stop, "ButtonRight")) - { - Stop(); - } - } - GUILayout.EndHorizontal(); - } - else - { - // Play mode: we only handle play/stop (due to problems with determining if a system with subemitters is playing we cannot pause) - GUILayout.BeginHorizontal(); - { - using (new EditorGUI.DisabledScope(disablePlayButton)) - { - if (GUILayout.Button(playText)) - { - Stop(); - Play(); - } - } - if (GUILayout.Button(s_Texts.stop)) - { - Stop(); - } - } - GUILayout.EndHorizontal(); - } - - // Playback info - PlayBackInfoGUI(EditorApplication.isPlaying); - - // Handle shortcut keys last so we do not activate them if inputfield has used the event - HandleKeyboardShortcuts(); - } - - private void InspectorParticleSystemGUI() - { - GUILayout.BeginVertical(ParticleSystemStyles.Get().effectBgStyle); - { - ParticleSystem selectedSystem = (m_SelectedParticleSystems.Count > 0) ? m_SelectedParticleSystems[0] : null; - if (selectedSystem != null) - { - ParticleSystemUI psUI = m_Emitters.FirstOrDefault(o => o.m_ParticleSystems[0] == selectedSystem); - if (psUI != null) - { - float width = GUIClip.visibleRect.width - 18; // -10 is effect_bg padding, -8 is inspector padding - psUI.OnGUI(width, false); - } - } - } - - GUILayout.EndVertical(); - GUILayout.FlexibleSpace(); - - HandleKeyboardShortcuts(); - } - - private void DrawSelectionMarker(Rect rect) - { - rect.x += 1; rect.y += 1; rect.width -= 2; rect.height -= 2; - ParticleSystemStyles.Get().selectionMarker.Draw(rect, GUIContent.none, false, true, true, false); - } - - private List GetSelectedParticleSystemUIs() - { - List result = new List(); - int[] selectedInstanceIDs = Selection.instanceIDs; - foreach (ParticleSystemUI psUI in m_Emitters) - { - if (selectedInstanceIDs.Contains(psUI.m_ParticleSystems[0].gameObject.GetInstanceID())) - result.Add(psUI); - } - return result; - } - - private void MultiParticleSystemGUI(bool verticalLayout) - { - // Background - GUILayout.BeginVertical(ParticleSystemStyles.Get().effectBgStyle); - m_EmitterAreaScrollPos = EditorGUILayout.BeginScrollView(m_EmitterAreaScrollPos); - { - Rect emitterAreaRect = EditorGUILayout.BeginVertical(); - { - // Click-Drag with Alt pressed in entire area - m_EmitterAreaScrollPos -= EditorGUI.MouseDeltaReader(emitterAreaRect, Event.current.alt); - // Top padding - GUILayout.Space(3); - - GUILayout.BeginHorizontal(); - // Left padding - GUILayout.Space(3); // added because cannot use padding due to clippling - - // Draw Emitters - Color orgColor = GUI.color; - bool isRepaintEvent = Event.current.type == EventType.Repaint; - bool isShowOnlySelected = IsShowOnlySelectedMode(); - List selectedSystems = GetSelectedParticleSystemUIs(); - - for (int i = 0; i < m_Emitters.Length; ++i) - { - if (i != 0) - GUILayout.Space(ModuleUI.k_SpaceBetweenModules); - - bool isSelected = selectedSystems.Contains(m_Emitters[i]); - - ModuleUI rendererModuleUI = m_Emitters[i].GetParticleSystemRendererModuleUI(); - if (isRepaintEvent && rendererModuleUI != null && !rendererModuleUI.enabled) - GUI.color = GetDisabledColor(); - - if (isRepaintEvent && isShowOnlySelected && !isSelected) - GUI.color = GetDisabledColor(); - - Rect psRect = EditorGUILayout.BeginVertical(); - { - if (isRepaintEvent && isSelected && m_Emitters.Length > 1) - DrawSelectionMarker(psRect); - - m_Emitters[i].OnGUI(ModuleUI.k_CompactFixedModuleWidth, true); - } - EditorGUILayout.EndVertical(); - - GUI.color = orgColor; - } - - GUILayout.Space(5); - if (GUILayout.Button(s_Texts.addParticleSystem, "OL Plus", GUILayout.Width(20))) - { - // Store state of inspector before creating new particle system that will reload the inspector (new selected object) - //SessionState.SetFloat("CurrentEmitterAreaScroll", m_EmitterAreaScrollPos.x); - CreateParticleSystem(ParticleSystemEditorUtils.GetRoot(m_SelectedParticleSystems[0]), SubModuleUI.SubEmitterType.None); - } - - GUILayout.FlexibleSpace(); // prevent centering - GUILayout.EndHorizontal(); - GUILayout.Space(4); - - // Click-Drag in background (does not require Alt pressed) - m_EmitterAreaScrollPos -= EditorGUI.MouseDeltaReader(emitterAreaRect, true); - - GUILayout.FlexibleSpace(); // Makes the emitter area background extend to bottom - } - EditorGUILayout.EndVertical(); // EmitterAreaRect - } - EditorGUILayout.EndScrollView(); - - GUILayout.EndVertical(); // Background - - //GUILayout.FlexibleSpace(); // Makes the emitter area background align to bottom of highest emitter - - // Handle shortcut keys last so we do not activate them if inputfield has used the event - HandleKeyboardShortcuts(); - } - - private void WindowCurveEditorGUI(bool verticalLayout) - { - Rect rect; - if (verticalLayout) - { - rect = GUILayoutUtility.GetRect(13, m_CurveEditorAreaHeight, GUILayout.MinHeight(m_CurveEditorAreaHeight)); - } - else - { - EditorWindow win = (EditorWindow)m_Owner; - System.Diagnostics.Debug.Assert(win != null); - rect = GUILayoutUtility.GetRect(win.position.width - m_EmitterAreaWidth, win.position.height - 17); - } - - // Get mouse down event before curve editor - ResizeHandling(verticalLayout); - - m_ParticleSystemCurveEditor.OnGUI(rect); - } - - void ResizeHandling(bool verticalLayout) - { - Rect dragRect; - const float dragWidth = 5f; - if (verticalLayout) - { - dragRect = GUILayoutUtility.GetLastRect(); - dragRect.y += -dragWidth; - dragRect.height = dragWidth; - - // For horizontal layout we add a vertical size controller to adjust emitter area width - float deltaY = EditorGUI.MouseDeltaReader(dragRect, true).y; - if (deltaY != 0f) - { - m_CurveEditorAreaHeight -= deltaY; - ClampWindowContentSizes(); - EditorPrefs.SetFloat("ParticleSystemCurveEditorAreaHeight", m_CurveEditorAreaHeight); - } - - if (Event.current.type == EventType.Repaint) - EditorGUIUtility.AddCursorRect(dragRect, MouseCursor.SplitResizeUpDown); - } - else - { - // For horizontal layout we add a vertical size controller to adjust emitter area width - dragRect = new Rect(m_EmitterAreaWidth - dragWidth, 0, dragWidth, GUIClip.visibleRect.height); - float deltaX = EditorGUI.MouseDeltaReader(dragRect, true).x; - if (deltaX != 0f) - { - m_EmitterAreaWidth += deltaX; - ClampWindowContentSizes(); - EditorPrefs.SetFloat("ParticleSystemEmitterAreaWidth", m_EmitterAreaWidth); - } - - if (Event.current.type == EventType.Repaint) - EditorGUIUtility.AddCursorRect(dragRect, MouseCursor.SplitResizeLeftRight); - } - } - - void ClampWindowContentSizes() - { - EventType type = Event.current.type; - if (type != EventType.Layout) - { - float width = GUIClip.visibleRect.width; - float height = GUIClip.visibleRect.height; - bool verticalLayout = m_VerticalLayout; - - - if (verticalLayout) - m_CurveEditorAreaHeight = Mathf.Clamp(m_CurveEditorAreaHeight, k_MinCurveAreaSize.y, height - k_MinEmitterAreaSize.y); - else - m_EmitterAreaWidth = Mathf.Clamp(m_EmitterAreaWidth, k_MinEmitterAreaSize.x, width - k_MinCurveAreaSize.x); - } - } - - public void OnGUI() - { - // Init (if needed) - if (s_Texts == null) - s_Texts = new Texts(); - - if (m_Emitters == null) - { - return; - } - - // Grab the latest data from the object - UpdateProperties(); - - OwnerType ownerType = m_Owner is ParticleSystemInspector ? OwnerType.Inspector : OwnerType.ParticleSystemWindow; - switch (ownerType) - { - case OwnerType.ParticleSystemWindow: - { - ClampWindowContentSizes(); - bool verticalLayout = m_VerticalLayout; // GUIClip.visibleRect.width < GUIClip.visibleRect.height; - - if (verticalLayout) - { - MultiParticleSystemGUI(verticalLayout); - WindowCurveEditorGUI(verticalLayout); - } - else - { - GUILayout.BeginHorizontal(); - MultiParticleSystemGUI(verticalLayout); - WindowCurveEditorGUI(verticalLayout); - GUILayout.EndHorizontal(); - } - } - break; - case OwnerType.Inspector: - // The inspector window already has added a vertical scrollview so no need to do it here - InspectorParticleSystemGUI(); - break; - default: - Debug.LogError("Unhandled enum"); - break; - } - // Apply the property, handle undo - ApplyModifiedProperties(); - } - - void ApplyModifiedProperties() - { - // Apply the properties, handles undo - for (int i = 0; i < m_Emitters.Length; ++i) - m_Emitters[i].ApplyProperties(); - } - - internal void UpdateProperties() - { - for (int i = 0; i < m_Emitters.Length; ++i) - m_Emitters[i].UpdateProperties(); - } - - static internal bool GetAllModulesVisible() - { - return EditorPrefs.GetBool("ParticleSystemShowAllModules", true); - } - - internal void SetAllModulesVisible(bool showAll) - { - EditorPrefs.SetBool("ParticleSystemShowAllModules", showAll); - foreach (var particleSystemUI in m_Emitters) - { - for (int i = 0; i < particleSystemUI.m_Modules.Length; ++i) - { - ModuleUI moduleUi = particleSystemUI.m_Modules[i]; - if (moduleUi != null) - { - if (showAll) - { - if (!moduleUi.visibleUI) - moduleUi.visibleUI = true; - } - else - { - bool allowHiding = true; - if (moduleUi as RendererModuleUI != null) - { - if (particleSystemUI.m_ParticleSystems.FirstOrDefault(o => o.GetComponent() == null) == null) - allowHiding = false; - } - - if (allowHiding && !moduleUi.enabled) - moduleUi.visibleUI = false; - } - } - } - } - } - - internal bool IsShowOnlySelectedMode() - { - return m_ShowOnlySelectedMode; - } - - internal void SetShowOnlySelectedMode(bool enable) - { - m_ShowOnlySelectedMode = enable; - RefreshShowOnlySelected(); - } - - internal void RefreshShowOnlySelected() - { - int[] selectedInstanceIDs = Selection.instanceIDs; - foreach (ParticleSystemUI psUI in m_Emitters) - { - if (psUI.m_ParticleSystems[0] != null) - { - ParticleSystemRenderer psRenderer = psUI.m_ParticleSystems[0].GetComponent(); - if (psRenderer != null) - { - if (IsShowOnlySelectedMode()) - psRenderer.editorEnabled = selectedInstanceIDs.Contains(psRenderer.gameObject.GetInstanceID()); - else - psRenderer.editorEnabled = true; - } - } - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleRendererEditor.cs b/Editor/Mono/ParticleSystemEditor/ParticleRendererEditor.cs deleted file mode 100644 index 72a8ab3915..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleRendererEditor.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Experimental.Rendering; - -#pragma warning disable 612, 618 - -namespace UnityEditor -{ - [CustomEditor(typeof(ParticleRenderer))] - [CanEditMultipleObjects] - internal class ParticleRendererEditor : RendererEditorBase - { - private string[] m_ExcludedProperties; - - public override void OnEnable() - { - base.OnEnable(); - - InitializeProbeFields(); - - List excludedProperties = new List(); - if (!SupportedRenderingFeatures.active.rendererSupportsMotionVectors) - excludedProperties.Add("m_MotionVectors"); - if (!SupportedRenderingFeatures.active.rendererSupportsReceiveShadows) - excludedProperties.Add("m_ReceiveShadows"); - excludedProperties.AddRange(Probes.GetFieldsStringArray()); - - m_ExcludedProperties = excludedProperties.ToArray(); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - DrawPropertiesExcluding(serializedObject, m_ExcludedProperties); - - m_Probes.OnGUI(targets, (Renderer)target, false); - - RenderRenderingLayer(); - - serializedObject.ApplyModifiedProperties(); - } - } -} - -#pragma warning restore 612, 618 diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemClipboard.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemClipboard.cs deleted file mode 100644 index 076586d287..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemClipboard.cs +++ /dev/null @@ -1,202 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - internal class ParticleSystemClipboard - { - static AnimationCurve m_AnimationCurve1; - static AnimationCurve m_AnimationCurve2; - static float m_AnimationCurveScalar; - static Gradient m_Gradient1; - static Gradient m_Gradient2; - - - // Gradient section - - static public bool HasSingleGradient() - { - return m_Gradient1 != null && m_Gradient2 == null; - } - - static public bool HasDoubleGradient() - { - return m_Gradient1 != null && m_Gradient2 != null; - } - - static public void CopyGradient(Gradient gradient1, Gradient gradient2) - { - m_Gradient1 = gradient1; - m_Gradient2 = gradient2; - } - - static public void PasteGradient(SerializedProperty gradientProperty, SerializedProperty gradientProperty2) - { - if (gradientProperty != null && m_Gradient1 != null) - gradientProperty.gradientValue = m_Gradient1; - - if (gradientProperty2 != null && m_Gradient2 != null) - gradientProperty2.gradientValue = m_Gradient2; - } - - // AnimationCurve section - - static public bool HasSingleAnimationCurve() - { - return m_AnimationCurve1 != null && m_AnimationCurve2 == null; - } - - static public bool HasDoubleAnimationCurve() - { - return m_AnimationCurve1 != null && m_AnimationCurve2 != null; - } - - static public void CopyAnimationCurves(AnimationCurve animCurve, AnimationCurve animCurve2, float scalar) - { - m_AnimationCurve1 = animCurve; - m_AnimationCurve2 = animCurve2; - m_AnimationCurveScalar = scalar; - } - - static private void ClampCurve(SerializedProperty animCurveProperty, Rect curveRanges) - { - AnimationCurve clampedCurve = animCurveProperty.animationCurveValue; - Keyframe[] keys = clampedCurve.keys; - for (int i = 0; i < keys.Length; ++i) - { - keys[i].time = Mathf.Clamp(keys[i].time, curveRanges.xMin, curveRanges.xMax); - keys[i].value = Mathf.Clamp(keys[i].value, curveRanges.yMin, curveRanges.yMax); - } - clampedCurve.keys = keys; - animCurveProperty.animationCurveValue = clampedCurve; - } - - static public void PasteAnimationCurves(SerializedProperty animCurveProperty, SerializedProperty animCurveProperty2, SerializedProperty scalarProperty, Rect curveRanges, ParticleSystemCurveEditor particleSystemCurveEditor) - { - if (animCurveProperty != null && m_AnimationCurve1 != null) - { - animCurveProperty.animationCurveValue = m_AnimationCurve1; - ClampCurve(animCurveProperty, curveRanges); - } - - if (animCurveProperty2 != null && m_AnimationCurve2 != null) - { - animCurveProperty2.animationCurveValue = m_AnimationCurve2; - ClampCurve(animCurveProperty2, curveRanges); - } - - if (scalarProperty != null) - scalarProperty.floatValue = m_AnimationCurveScalar; - - // Ensure refresh of systems that uses curves - if (particleSystemCurveEditor != null) - particleSystemCurveEditor.Refresh(); - } - } - - - internal class GradientContextMenu - { - readonly SerializedProperty m_Prop1; - - - static internal void Show(SerializedProperty prop) - { - // Curve context menu - GUIContent copy = EditorGUIUtility.TrTextContent("Copy"); - GUIContent paste = EditorGUIUtility.TrTextContent("Paste"); - - GenericMenu menu = new GenericMenu(); - var gradientMenu = new GradientContextMenu(prop); - menu.AddItem(copy, false, gradientMenu.Copy); - if (ParticleSystemClipboard.HasSingleGradient()) - menu.AddItem(paste, false, gradientMenu.Paste); - else - menu.AddDisabledItem(paste); - - menu.ShowAsContext(); - } - - private GradientContextMenu(SerializedProperty prop1) - { - m_Prop1 = prop1; - } - - private void Copy() - { - Gradient gradient1 = m_Prop1 != null ? m_Prop1.gradientValue : null; - ParticleSystemClipboard.CopyGradient(gradient1, null); - } - - private void Paste() - { - ParticleSystemClipboard.PasteGradient(m_Prop1, null); - if (m_Prop1 != null) - m_Prop1.serializedObject.ApplyModifiedProperties(); - UnityEditorInternal.GradientPreviewCache.ClearCache(); - } - } - - - internal class AnimationCurveContextMenu - { - readonly SerializedProperty m_Prop1; - readonly SerializedProperty m_Prop2; - readonly SerializedProperty m_Scalar; - readonly ParticleSystemCurveEditor m_ParticleSystemCurveEditor; - readonly Rect m_CurveRanges; - - static internal void Show(Rect position, SerializedProperty property, SerializedProperty property2, SerializedProperty scalar, Rect curveRanges, ParticleSystemCurveEditor curveEditor) - { - // Curve context menu - GUIContent copy = EditorGUIUtility.TrTextContent("Copy"); - GUIContent paste = EditorGUIUtility.TrTextContent("Paste"); - - GenericMenu menu = new GenericMenu(); - - bool isRegion = property != null && property2 != null; - bool validPaste = (isRegion && ParticleSystemClipboard.HasDoubleAnimationCurve()) || (!isRegion && ParticleSystemClipboard.HasSingleAnimationCurve()); - - AnimationCurveContextMenu obj = new AnimationCurveContextMenu(property, property2, scalar, curveRanges, curveEditor); - menu.AddItem(copy, false, obj.Copy); - if (validPaste) - menu.AddItem(paste, false, obj.Paste); - else - menu.AddDisabledItem(paste); - - menu.DropDown(position); - } - - private AnimationCurveContextMenu(SerializedProperty prop1, SerializedProperty prop2, SerializedProperty scalar, Rect curveRanges, ParticleSystemCurveEditor owner) - { - m_Prop1 = prop1; - m_Prop2 = prop2; - m_Scalar = scalar; - m_ParticleSystemCurveEditor = owner; - m_CurveRanges = curveRanges; - } - - private void Copy() - { - AnimationCurve animCurve1 = m_Prop1 != null ? m_Prop1.animationCurveValue : null; - AnimationCurve animCurve2 = m_Prop2 != null ? m_Prop2.animationCurveValue : null; - float scalar = m_Scalar != null ? m_Scalar.floatValue : 1.0f; - ParticleSystemClipboard.CopyAnimationCurves(animCurve1, animCurve2, scalar); - } - - private void Paste() - { - ParticleSystemClipboard.PasteAnimationCurves(m_Prop1, m_Prop2, m_Scalar, m_CurveRanges, m_ParticleSystemCurveEditor); - if (m_Prop1 != null) - m_Prop1.serializedObject.ApplyModifiedProperties(); - if (m_Prop2 != null) - m_Prop2.serializedObject.ApplyModifiedProperties(); - if (m_Scalar != null) - m_Scalar.serializedObject.ApplyModifiedProperties(); - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemCurveEditor.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemCurveEditor.cs deleted file mode 100644 index e25d78c39a..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemCurveEditor.cs +++ /dev/null @@ -1,839 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; - -internal class ParticleSystemCurveEditor -{ - private List m_AddedCurves; - private CurveEditor m_CurveEditor; - static CurveEditorSettings m_CurveEditorSettings = new CurveEditorSettings(); - private Color[] m_Colors; - private List m_AvailableColors; - private DoubleCurvePresetsContentsForPopupWindow m_DoubleCurvePresets; - - // Presets - public const float k_PresetsHeight = 30f; - - internal class Styles - { - public GUIStyle curveEditorBackground = "CurveEditorBackground"; - public GUIStyle curveSwatch = "PopupCurveEditorSwatch"; - public GUIStyle curveSwatchArea = "PopupCurveSwatchBackground"; - public GUIStyle yAxisHeader = new GUIStyle(ParticleSystemStyles.Get().label); - public GUIContent optimizeCurveText = EditorGUIUtility.TrTextContent("Optimize", "Click to optimize curve. Optimized curves are defined by having at most 3 keys, with a key at both ends, and do not support loop or ping pong wrapping."); - public GUIContent removeCurveText = EditorGUIUtility.TrTextContent("Remove", "Remove selected curve(s)"); - public GUIContent curveLibraryPopup = new GUIContent("", "Open curve library"); - public GUIContent presetTooltip = new GUIContent(); - } - internal static Styles s_Styles; - - - public class CurveData - { - // Can be single curve (using m_Max) or a region (using m_Min and m_Max) - public SerializedProperty m_Max, m_Min; - public bool m_SignedRange; - public Color m_Color; - public string m_UniqueName; - public GUIContent m_DisplayName; - public CurveWrapper.GetAxisScalarsCallback m_GetAxisScalarsCallback; - public CurveWrapper.SetAxisScalarsCallback m_SetAxisScalarsCallback; - public int m_MaxId, m_MinId; - public bool m_Visible; - private static int s_IdCounter; - - // Region if min and max is valid, Curve if min is null - public CurveData(string name, GUIContent displayName, SerializedProperty min, SerializedProperty max, Color color, bool signedRange, - CurveWrapper.GetAxisScalarsCallback getAxisScalars, CurveWrapper.SetAxisScalarsCallback setAxisScalars, bool visible) - { - m_UniqueName = name; - m_DisplayName = displayName; - m_SignedRange = signedRange; - - m_Min = min; - m_Max = max; - if (m_Min != null) - m_MinId = ++s_IdCounter; - if (m_Max != null) - m_MaxId = ++s_IdCounter; - m_Color = color; - m_GetAxisScalarsCallback = getAxisScalars; - m_SetAxisScalarsCallback = setAxisScalars; - m_Visible = visible; - - if (m_Max == null || m_MaxId == 0) - { - Debug.LogError("Max curve should always be valid! (Min curve can be null)"); - } - } - - public bool IsRegion() - { - return m_Min != null; - } - } - - public void OnDisable() - { - m_CurveEditor.OnDisable(); - Undo.undoRedoPerformed -= UndoRedoPerformed; - } - - public void OnDestroy() - { - m_DoubleCurvePresets.GetPresetLibraryEditor().UnloadUsedLibraries(); - } - - public void Refresh() - { - ContentChanged(); - UnityEditorInternal.AnimationCurvePreviewCache.ClearCache(); - } - - public void Init() - { - if (m_AddedCurves != null) - return; - - m_AddedCurves = new List(); - - // Colors - m_Colors = new Color[] - { - new Color(255 / 255f, 158 / 255f, 33 / 255f), // orange - new Color(223 / 255f, 54 / 255f, 148 / 255f), // purple - new Color(0f, 175 / 255f, 255 / 255f), // blue - new Color(255 / 255f, 235 / 255f, 0), // yellow - new Color(50 / 255f, 255 / 255f, 68 / 255f), // green - new Color(250 / 255f, 0f, 0f), // red (this is the first color used) - }; - m_AvailableColors = new List(m_Colors); - - // Curve Editor - m_CurveEditorSettings.useFocusColors = true; - m_CurveEditorSettings.showAxisLabels = false; - m_CurveEditorSettings.hRangeMin = 0.0f; - m_CurveEditorSettings.vRangeMin = 0.0F; - m_CurveEditorSettings.vRangeMax = 1.0f; - m_CurveEditorSettings.hRangeMax = 1.0F; - m_CurveEditorSettings.vSlider = false; - m_CurveEditorSettings.hSlider = false; - m_CurveEditorSettings.showWrapperPopups = true; - m_CurveEditorSettings.rectangleToolFlags = CurveEditorSettings.RectangleToolFlags.MiniRectangleTool; - m_CurveEditorSettings.hTickLabelOffset = 5; - m_CurveEditorSettings.allowDraggingCurvesAndRegions = true; - m_CurveEditorSettings.allowDeleteLastKeyInCurve = false; - - TickStyle hTS = new TickStyle(); - hTS.tickColor.color = new Color(0.0f, 0.0f, 0.0f, 0.2f); - hTS.distLabel = 30; - hTS.stubs = false; - hTS.centerLabel = true; - m_CurveEditorSettings.hTickStyle = hTS; - - TickStyle vTS = new TickStyle(); - vTS.tickColor.color = new Color(0.0f, 0.0f, 0.0f, 0.2f); - vTS.distLabel = 20; - vTS.stubs = false; - vTS.centerLabel = true; - m_CurveEditorSettings.vTickStyle = vTS; - - m_CurveEditor = new CurveEditor(new Rect(0, 0, 1000, 100), CreateCurveWrapperArray(), false); - m_CurveEditor.settings = m_CurveEditorSettings; - m_CurveEditor.leftmargin = 40; - m_CurveEditor.rightmargin = m_CurveEditor.topmargin = m_CurveEditor.bottommargin = 25; - m_CurveEditor.SetShownHRangeInsideMargins(m_CurveEditorSettings.hRangeMin, m_CurveEditorSettings.hRangeMax); - m_CurveEditor.SetShownVRangeInsideMargins(m_CurveEditorSettings.vRangeMin, m_CurveEditorSettings.hRangeMax); - m_CurveEditor.ignoreScrollWheelUntilClicked = false; - - Undo.undoRedoPerformed += UndoRedoPerformed; - } - - void UndoRedoPerformed() - { - ContentChanged(); - } - - void UpdateRangeBasedOnShownCurves() - { - bool hasSignedRange = false; - for (int i = 0; i < m_AddedCurves.Count; i++) - hasSignedRange |= m_AddedCurves[i].m_SignedRange; - - float newMinRange = hasSignedRange ? -1.0F : 0.0F; - if (newMinRange != m_CurveEditorSettings.vRangeMin) - { - m_CurveEditorSettings.vRangeMin = newMinRange; - m_CurveEditor.settings = m_CurveEditorSettings; - m_CurveEditor.SetShownVRangeInsideMargins(m_CurveEditorSettings.vRangeMin, m_CurveEditorSettings.hRangeMax); - } - } - - // Public interface - - public bool IsAdded(SerializedProperty min, SerializedProperty max) - { - return FindIndex(min, max) != -1; - } - - public bool IsAdded(SerializedProperty max) - { - return FindIndex(null, max) != -1; - } - - public void AddCurve(CurveData curveData) - { - Add(curveData); - } - - public void RemoveCurve(SerializedProperty max) - { - RemoveCurve(null, max); - } - - public void RemoveCurve(SerializedProperty min, SerializedProperty max) - { - if (Remove(FindIndex(min, max))) - { - ContentChanged(); - UpdateRangeBasedOnShownCurves(); - } - } - - public Color GetCurveColor(SerializedProperty max) - { - int index = FindIndex(max); - if (index >= 0 && index < m_AddedCurves.Count) - { - return m_AddedCurves[index].m_Color; - } - return new Color(0.8f, 0.8f, 0.8f, 0.7f); - } - - public void AddCurveDataIfNeeded(string curveName, CurveData curveData) - { - // We check if a curve was added by checking our inspector state if a color was set for curveName - Vector3 c = SessionState.GetVector3(curveName, Vector3.zero); - - if (c != Vector3.zero) - { - Color color = new Color(c.x, c.y, c.z); - curveData.m_Color = color; - AddCurve(curveData); - - // Remove color from available list - for (int i = 0; i < m_AvailableColors.Count; ++i) - { - if (SameColor(m_AvailableColors[i], color)) - { - m_AvailableColors.RemoveAt(i); - break; - } - } - } - } - - public void SetVisible(SerializedProperty curveProp, bool visible) - { - int index = FindIndex(curveProp); - if (index >= 0) - { - m_AddedCurves[index].m_Visible = visible; - } - } - - static bool SameColor(Color c1, Color c2) - { - return Mathf.Abs(c1.r - c2.r) < 0.01f && - Mathf.Abs(c1.g - c2.g) < 0.01f && - Mathf.Abs(c1.b - c2.b) < 0.01f; - } - - // Private - //--------- - private int FindIndex(SerializedProperty prop) - { - return FindIndex(null, prop); - } - - private int FindIndex(SerializedProperty min, SerializedProperty max) - { - if (max == null) - return -1; - - if (min == null) - { - // Just check max - for (int i = 0; i < m_AddedCurves.Count; ++i) - if (m_AddedCurves[i].m_Max == max) - return i; - } - else - { - for (int i = 0; i < m_AddedCurves.Count; ++i) - if (m_AddedCurves[i].m_Max == max && m_AddedCurves[i].m_Min == min) - return i; - } - - return -1; - } - - private void Add(CurveData cd) - { - m_CurveEditor.SelectNone(); // ensures that newly added curves are moved to front (selected keys will stay on top) - - m_AddedCurves.Add(cd); - ContentChanged(); - - // Cache info - SessionState.SetVector3(cd.m_UniqueName, new Vector3(cd.m_Color.r, cd.m_Color.g, cd.m_Color.b)); - - UpdateRangeBasedOnShownCurves(); - } - - private bool Remove(int index) - { - if (index >= 0 && index < m_AddedCurves.Count) - { - // Make color available again - Color color = m_AddedCurves[index].m_Color; - m_AvailableColors.Add(color); - - // Remove from inspector state - string curveName = m_AddedCurves[index].m_UniqueName; - SessionState.EraseVector3(curveName); - - // Remove from list - m_AddedCurves.RemoveAt(index); - - // When no added curves reset available colors - if (m_AddedCurves.Count == 0) - { - //if (m_AvailableColors.Count != m_Colors.Length) - // Debug.LogError ("Color count mismatch : " + m_AvailableColors.Count + " != " + m_Colors.Length); - - m_AvailableColors = new List(m_Colors); - } - - return true; - } - - Debug.Log("Invalid index in ParticleSystemCurveEditor::Remove"); - return false; - } - - private void RemoveTopMost() - { - int topMostCurveID; - if (m_CurveEditor.GetTopMostCurveID(out topMostCurveID)) - { - for (int j = 0; j < m_AddedCurves.Count; ++j) - { - CurveData cd = m_AddedCurves[j]; - if (cd.m_MaxId == topMostCurveID || cd.m_MinId == topMostCurveID) - { - Remove(j); - ContentChanged(); - UpdateRangeBasedOnShownCurves(); - return; - } - } - } - } - - private void RemoveSelected() - { - bool anyRemoved = false; - List selection = m_CurveEditor.selectedCurves; - for (int i = 0; i < selection.Count; ++i) - { - int curveId = selection[i].curveID; - for (int j = 0; j < m_AddedCurves.Count; ++j) - { - CurveData cd = m_AddedCurves[j]; - if (cd.m_MaxId == curveId || cd.m_MinId == curveId) - { - anyRemoved |= Remove(j); - break; - } - } - } - if (anyRemoved) - { - ContentChanged(); - UpdateRangeBasedOnShownCurves(); - } - m_CurveEditor.SelectNone(); - } - - private void RemoveAll() - { - bool anyRemoved = false; - while (m_AddedCurves.Count > 0) - anyRemoved |= Remove(0); - - if (anyRemoved) - { - ContentChanged(); - UpdateRangeBasedOnShownCurves(); - } - } - - public Color GetAvailableColor() - { - // If no available colors left just use same colors again... - if (m_AvailableColors.Count == 0) - m_AvailableColors = new List(m_Colors); - - int i = m_AvailableColors.Count - 1; - Color color = m_AvailableColors[i]; - m_AvailableColors.RemoveAt(i); - return color; - } - - public void OnGUI(Rect rect) - { - Init(); - if (s_Styles == null) - s_Styles = new Styles(); - - // Sizes - Rect curveEditorRect = new Rect(rect.x, rect.y, rect.width, rect.height - k_PresetsHeight); - Rect presetRect = new Rect(rect.x, rect.y + curveEditorRect.height, rect.width, k_PresetsHeight); - - // Background - GUI.Label(curveEditorRect, GUIContent.none, s_Styles.curveEditorBackground); - - // Setup curve editor - if (Event.current.type == EventType.Repaint) - m_CurveEditor.rect = curveEditorRect; - - // Clamp the y axis to 1,000,000 for the particle curve. - foreach (CurveWrapper cw in m_CurveEditor.animationCurves) - { - if (cw.getAxisUiScalarsCallback != null && cw.setAxisUiScalarsCallback != null) - { - Vector2 axisUiScalar = cw.getAxisUiScalarsCallback(); - if (axisUiScalar.y > 1000000) - { - axisUiScalar.y = 1000000; - cw.setAxisUiScalarsCallback(axisUiScalar); - } - } - } - - DoLabelForTopMostCurve(new Rect(rect.x + 4, rect.y, rect.width - 160, 20)); - DoRemoveSelectedButton(new Rect(curveEditorRect.x, curveEditorRect.y, curveEditorRect.width, 24)); - DoOptimizeCurveButton(new Rect(curveEditorRect.x, curveEditorRect.y, curveEditorRect.width, 24)); - presetRect.x += 30; - presetRect.width -= 2 * 30; - PresetCurveButtons(presetRect, rect); - - m_CurveEditor.OnGUI(); - - SaveChangedCurves(); - } - - void DoLabelForTopMostCurve(Rect rect) - { - if (m_CurveEditor.IsDraggingCurveOrRegion() || m_CurveEditor.selectedCurves.Count <= 1) - { - int curveID; - - if (m_CurveEditor.GetTopMostCurveID(out curveID)) - { - for (int i = 0; i < m_AddedCurves.Count; ++i) - { - if (m_AddedCurves[i].m_MaxId == curveID || m_AddedCurves[i].m_MinId == curveID) - { - s_Styles.yAxisHeader.normal.textColor = m_AddedCurves[i].m_Color; - GUI.Label(rect, m_AddedCurves[i].m_DisplayName, s_Styles.yAxisHeader); - return; - } - } - } - } - } - - void SetConstantCurve(CurveWrapper cw, float constantValue) - { - Keyframe[] keys = new Keyframe[1]; - keys[0].time = 0.0f; - keys[0].value = constantValue; - cw.curve.keys = keys; - cw.changed = true; // Used in SaveChangedCurves () later in OnGUI - } - - void SetCurve(CurveWrapper cw, AnimationCurve curve) - { - Keyframe[] keys = new Keyframe[curve.keys.Length]; - System.Array.Copy(curve.keys, keys, keys.Length); - cw.curve.keys = keys; - cw.changed = true; // Used in SaveChangedCurves () later in OnGUI - } - - void SetTopMostCurve(DoubleCurve doubleCurve) - { - int topMostCurveID; - if (m_CurveEditor.GetTopMostCurveID(out topMostCurveID)) - { - for (int j = 0; j < m_AddedCurves.Count; ++j) - { - CurveData cd = m_AddedCurves[j]; - if (cd.m_MaxId == topMostCurveID || cd.m_MinId == topMostCurveID) - { - if (doubleCurve.signedRange == cd.m_SignedRange) - { - if (cd.m_MaxId > 0) - { - SetCurve(m_CurveEditor.GetCurveWrapperFromID(cd.m_MaxId), doubleCurve.maxCurve); - } - - if (cd.m_MinId > 0) - { - SetCurve(m_CurveEditor.GetCurveWrapperFromID(cd.m_MinId), doubleCurve.minCurve); - } - } - else - { - Debug.LogWarning("Cannot assign a curves with different signed range"); - } - } - } - } - } - - DoubleCurve CreateDoubleCurveFromTopMostCurve() - { - int topMostCurveID; - if (m_CurveEditor.GetTopMostCurveID(out topMostCurveID)) - { - for (int j = 0; j < m_AddedCurves.Count; ++j) - { - CurveData cd = m_AddedCurves[j]; - if (cd.m_MaxId == topMostCurveID || cd.m_MinId == topMostCurveID) - { - AnimationCurve maxCurve = null, minCurve = null; - if (cd.m_Min != null) - minCurve = cd.m_Min.animationCurveValue; - if (cd.m_Max != null) - maxCurve = cd.m_Max.animationCurveValue; - return new DoubleCurve(minCurve, maxCurve, cd.m_SignedRange); - } - } - } - return null; - } - - void PresetDropDown(Rect rect) - { - if (EditorGUI.DropdownButton(rect, EditorGUI.GUIContents.titleSettingsIcon, FocusType.Passive, EditorStyles.inspectorTitlebarText)) - { - DoubleCurve doubleCurveToSaveAsPreset = CreateDoubleCurveFromTopMostCurve(); - if (doubleCurveToSaveAsPreset != null) - { - InitDoubleCurvePresets(); - if (m_DoubleCurvePresets != null) - { - m_DoubleCurvePresets.doubleCurveToSave = CreateDoubleCurveFromTopMostCurve(); - // We prioritize left first for normal inspector layout (where the inspector is on the right) - PopupWindow.Show(rect, m_DoubleCurvePresets); - } - } - } - } - - int m_LastTopMostCurveID = -1; - void InitDoubleCurvePresets() - { - int topMostCurveID; - if (m_CurveEditor.GetTopMostCurveID(out topMostCurveID)) - { - if (m_DoubleCurvePresets == null || m_LastTopMostCurveID != topMostCurveID) - { - m_LastTopMostCurveID = topMostCurveID; - // Selection callback for library window - System.Action presetSelectedCallback = delegate(DoubleCurve presetDoubleCurve) - { - SetTopMostCurve(presetDoubleCurve); - UnityEditorInternal.InternalEditorUtility.RepaintAllViews(); - }; - DoubleCurve doubleCurveToSaveAsPreset = CreateDoubleCurveFromTopMostCurve(); - m_DoubleCurvePresets = new DoubleCurvePresetsContentsForPopupWindow(doubleCurveToSaveAsPreset, presetSelectedCallback); - m_DoubleCurvePresets.InitIfNeeded(); - } - } - } - - void PresetCurveButtons(Rect position, Rect curveEditorRect) - { - if (m_CurveEditor.animationCurves.Length == 0) - return; - - InitDoubleCurvePresets(); - if (m_DoubleCurvePresets == null) - return; - - DoubleCurvePresetLibrary curveLibrary = m_DoubleCurvePresets.GetPresetLibraryEditor().GetCurrentLib(); - const int maxNumPresets = 9; - int numPresets = (curveLibrary != null) ? curveLibrary.Count() : 0; - int showNumPresets = Mathf.Min(numPresets, maxNumPresets); - - float swatchWidth = 30; - float swatchHeight = 15; - float spaceBetweenSwatches = 10; - float presetButtonsWidth = showNumPresets * swatchWidth + (showNumPresets - 1) * spaceBetweenSwatches; - float flexWidth = (position.width - presetButtonsWidth) * 0.5f; - - // Preset swatch area - float curY = (position.height - swatchHeight) * 0.5f; - float curX = 3.0f; - if (flexWidth > 0) - curX = flexWidth; - - PresetDropDown(new Rect(curX - 20 + position.x, curY + position.y, 16, 16)); - - GUI.BeginGroup(position); - - Color curveColor = Color.white; - curveColor.a *= 0.6f; - for (int i = 0; i < showNumPresets; i++) - { - if (i > 0) - curX += spaceBetweenSwatches; - - Rect swatchRect = new Rect(curX, curY, swatchWidth, swatchHeight); - - if (swatchRect.xMax > position.width) - break; - - s_Styles.presetTooltip.tooltip = curveLibrary.GetName(i); - if (GUI.Button(swatchRect, s_Styles.presetTooltip, GUIStyle.none)) - { - DoubleCurve presetDoubleCurve = curveLibrary.GetPreset(i) as DoubleCurve; - if (presetDoubleCurve != null) - { - SetTopMostCurve(presetDoubleCurve); - m_CurveEditor.ClearSelection(); - } - } - if (Event.current.type == EventType.Repaint) - curveLibrary.Draw(swatchRect, i); - - curX += swatchWidth; - } - GUI.EndGroup(); - } - - // Polynomial curves have limitations on how they have to be authored. - // Since we don't enforce the layout, we have a button that enforces the curve layout instead. - void DoOptimizeCurveButton(Rect rect) - { - bool optimizeButtonShown = false; - Vector2 buttonSize = new Vector2(64, 14); - Rect buttonRect = new Rect(rect.xMax - 80 - buttonSize.x, rect.y + (rect.height - buttonSize.y) * 0.5f, buttonSize.x, buttonSize.y); - - if (!m_CurveEditor.IsDraggingCurveOrRegion()) - { - int numValidPolynomialCurve = 0; - List selection = m_CurveEditor.selectedCurves; - if (selection.Count > 0) - { - for (int j = 0; j < selection.Count; ++j) - { - CurveWrapper cw = m_CurveEditor.GetCurveWrapperFromSelection(selection[j]); - numValidPolynomialCurve += AnimationUtility.IsValidOptimizedPolynomialCurve(cw.curve) ? 1 : 0; - } - - if (selection.Count != numValidPolynomialCurve) - { - optimizeButtonShown = true; - if (GUI.Button(buttonRect, s_Styles.optimizeCurveText)) - { - for (int j = 0; j < selection.Count; ++j) - { - CurveWrapper cw = m_CurveEditor.GetCurveWrapperFromSelection(selection[j]); - if (!AnimationUtility.IsValidOptimizedPolynomialCurve(cw.curve)) - { - // Reset wrap mode - cw.curve.preWrapMode = WrapMode.Clamp; - cw.curve.postWrapMode = WrapMode.Clamp; - cw.renderer.SetWrap(WrapMode.Clamp, WrapMode.Clamp); - - AnimationUtility.ConstrainToPolynomialCurve(cw.curve); - cw.changed = true; // Used in SaveChangedCurves () later in OnGUI - } - } - m_CurveEditor.SelectNone(); - } - } - } - else - { - // Check if top most curve can be optimized - int topMostCurveID; - if (m_CurveEditor.GetTopMostCurveID(out topMostCurveID)) - { - CurveWrapper cw = m_CurveEditor.GetCurveWrapperFromID(topMostCurveID); - if (!AnimationUtility.IsValidOptimizedPolynomialCurve(cw.curve)) - { - optimizeButtonShown = true; - if (GUI.Button(buttonRect, s_Styles.optimizeCurveText)) - { - // Reset wrap mode - cw.curve.preWrapMode = WrapMode.Clamp; - cw.curve.postWrapMode = WrapMode.Clamp; - cw.renderer.SetWrap(WrapMode.Clamp, WrapMode.Clamp); - - AnimationUtility.ConstrainToPolynomialCurve(cw.curve); - cw.changed = true; // Used in SaveChangedCurves () later in OnGUI - } - } - } - } - } - - if (!optimizeButtonShown) - { - using (new EditorGUI.DisabledScope(true)) - { - GUI.Button(buttonRect, s_Styles.optimizeCurveText); - } - } - } - - void DoRemoveSelectedButton(Rect rect) - { - using (new EditorGUI.DisabledScope(m_CurveEditor.animationCurves.Length == 0)) - { - Vector2 buttonSize = new Vector2(64, 14); - Rect clearCurvesRect = new Rect(rect.x + rect.width - buttonSize.x - 10, rect.y + (rect.height - buttonSize.y) * 0.5f, buttonSize.x, buttonSize.y); - if (GUI.Button(clearCurvesRect, s_Styles.removeCurveText)) - { - if (m_CurveEditor.selectedCurves.Count > 0) - RemoveSelected(); - else - RemoveTopMost(); - } - } - } - - void SaveCurve(SerializedProperty prop, CurveWrapper cw) - { - if (cw.curve.keys.Length == 1) - { - cw.renderer.SetCustomRange(0.0f, 1.0f); - cw.wrapColorMultiplier = Color.clear; // Hide wrapping when we only have 1 key - } - else - { - cw.renderer.SetCustomRange(0.0f, 0.0f); - cw.wrapColorMultiplier = cw.color; - } - - prop.animationCurveValue = cw.curve; - cw.changed = false; - } - - void SaveChangedCurves() - { - CurveWrapper[] curves = m_CurveEditor.animationCurves; - - bool refreshPreviews = false; - for (int i = 0; i < curves.Length; ++i) - { - CurveWrapper cw = curves[i]; - if (cw.changed) - { - for (int j = 0; j < m_AddedCurves.Count; ++j) - { - if (m_AddedCurves[j].m_MaxId == cw.id) - { - SaveCurve(m_AddedCurves[j].m_Max, cw); - break; - } - - if (m_AddedCurves[j].IsRegion() && m_AddedCurves[j].m_MinId == cw.id) - { - SaveCurve(m_AddedCurves[j].m_Min, cw); - break; - } - } - refreshPreviews = true; - } - } - - if (refreshPreviews) - { - UnityEditorInternal.AnimationCurvePreviewCache.ClearCache(); - HandleUtility.Repaint(); - } - } - - CurveWrapper CreateCurveWrapper(SerializedProperty curve, int id, int regionId, Color color, bool signedRange, - CurveWrapper.GetAxisScalarsCallback getAxisScalarsCallback, CurveWrapper.SetAxisScalarsCallback setAxisScalarsCallback) - { - CurveWrapper cw = new CurveWrapper(); - cw.id = id; - cw.regionId = regionId; - cw.color = color; - cw.renderer = new NormalCurveRenderer(curve.animationCurveValue); - cw.renderer.SetWrap(curve.animationCurveValue.preWrapMode, curve.animationCurveValue.postWrapMode); - if (cw.curve.keys.Length == 1) - { - cw.renderer.SetCustomRange(0.0f, 1.0f); - cw.wrapColorMultiplier = Color.clear; // Hide wrapping when we only have 1 key - } - else - { - cw.renderer.SetCustomRange(0.0f, 0.0f); - cw.wrapColorMultiplier = color; - } - cw.vRangeMin = signedRange ? -1.0F : 0.0F; - cw.getAxisUiScalarsCallback = getAxisScalarsCallback; - cw.setAxisUiScalarsCallback = setAxisScalarsCallback; - return cw; - } - - CurveWrapper[] CreateCurveWrapperArray() - { - List curveWrappers = new List(); - int regionCounter = 0; - for (int i = 0; i < m_AddedCurves.Count; i++) - { - CurveData cd = m_AddedCurves[i]; - if (cd.m_Visible) - { - if (cd.m_Max != null && cd.m_Max.hasMultipleDifferentValues) - continue; - if (cd.m_Min != null && cd.m_Min.hasMultipleDifferentValues) - continue; - - int regionId = -1; - if (cd.IsRegion()) - regionId = ++regionCounter; - - if (cd.m_Max != null) - { - curveWrappers.Add(CreateCurveWrapper(cd.m_Max, cd.m_MaxId, regionId, cd.m_Color, cd.m_SignedRange, cd.m_GetAxisScalarsCallback, cd.m_SetAxisScalarsCallback)); - } - - if (cd.m_Min != null) - { - curveWrappers.Add(CreateCurveWrapper(cd.m_Min, cd.m_MinId, regionId, cd.m_Color, cd.m_SignedRange, cd.m_GetAxisScalarsCallback, cd.m_SetAxisScalarsCallback)); - } - } - } - return curveWrappers.ToArray(); - } - - void ContentChanged() - { - m_CurveEditor.animationCurves = CreateCurveWrapperArray(); - m_CurveEditorSettings.showAxisLabels = m_CurveEditor.animationCurves.Length > 0; - } -} diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemEditor.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemEditor.cs deleted file mode 100644 index 5a4f99a9cc..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemEditor.cs +++ /dev/null @@ -1,255 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Linq; -using System.Collections.Generic; - -namespace UnityEditor -{ - [CustomEditor(typeof(ParticleSystem))] - [CanEditMultipleObjects] - internal class ParticleSystemInspector : Editor, ParticleEffectUIOwner - { - ParticleEffectUI m_ParticleEffectUI; - GUIContent m_PreviewTitle = EditorGUIUtility.TrTextContent("Particle System Curves"); - GUIContent showWindowText = EditorGUIUtility.TrTextContent("Open Editor..."); - GUIContent closeWindowText = EditorGUIUtility.TrTextContent("Close Editor"); - GUIContent hideWindowText = EditorGUIUtility.TrTextContent("Hide Editor"); - static GUIContent m_PlayBackTitle; - - - public static GUIContent playBackTitle - { - get - { - if (m_PlayBackTitle == null) - m_PlayBackTitle = EditorGUIUtility.TrTextContent("Particle Effect"); - return m_PlayBackTitle; - } - } - - private bool selectedInParticleSystemWindow - { - get - { - GameObject targetGameObject = (target as ParticleSystem).gameObject; - GameObject currentGameObject; - - if (ParticleSystemEditorUtils.lockedParticleSystem == null) - currentGameObject = Selection.activeGameObject; - else - currentGameObject = ParticleSystemEditorUtils.lockedParticleSystem.gameObject; - - return currentGameObject == targetGameObject; - } - } - - public Editor customEditor { get { return this; } } - - public void OnEnable() - { - // Get notified when hierarchy- or project window has changes so we can detect if particle systems have been dragged in or out. - EditorApplication.hierarchyChanged += HierarchyOrProjectWindowWasChanged; - EditorApplication.projectChanged += HierarchyOrProjectWindowWasChanged; - SceneView.onSceneGUIDelegate += OnSceneViewGUI; - Undo.undoRedoPerformed += UndoRedoPerformed; - } - - public void OnDisable() - { - SceneView.onSceneGUIDelegate -= OnSceneViewGUI; - EditorApplication.projectChanged -= HierarchyOrProjectWindowWasChanged; - EditorApplication.hierarchyChanged -= HierarchyOrProjectWindowWasChanged; - Undo.undoRedoPerformed -= UndoRedoPerformed; - - if (m_ParticleEffectUI != null) - m_ParticleEffectUI.Clear(); - } - - private void HierarchyOrProjectWindowWasChanged() - { - // target can be null if child particle system was deleted when ParticleSystemWindow is open - if (target != null && ShouldShowInspector()) - Init(true); - } - - void UndoRedoPerformed() - { - Init(true); - if (m_ParticleEffectUI != null) - m_ParticleEffectUI.UndoRedoPerformed(); - } - - private void Init(bool forceInit) - { - IEnumerable systems = from p in targets.OfType() where (p != null) select p; - if (systems == null || !systems.Any()) - { - m_ParticleEffectUI = null; - return; - } - - if (m_ParticleEffectUI == null) - { - m_ParticleEffectUI = new ParticleEffectUI(this); - m_ParticleEffectUI.InitializeIfNeeded(systems); - } - else if (forceInit) - { - m_ParticleEffectUI.InitializeIfNeeded(systems); - } - } - - void ShowEdiorButtonGUI() - { - GUILayout.BeginHorizontal(); - { - GUILayout.FlexibleSpace(); - - if (m_ParticleEffectUI == null || !m_ParticleEffectUI.multiEdit) - { - bool alreadySelected = selectedInParticleSystemWindow; - GameObject targetGameObject = (target as ParticleSystem).gameObject; - - GUIContent text = null; - ParticleSystemWindow window = ParticleSystemWindow.GetInstance(); - if (window) - window.customEditor = this; // window can be created by LoadWindowLayout, when Editor starts up, so always make sure the custom editor member is set up (case 930005) - - if (window && window.IsVisible() && alreadySelected) - { - if (window.GetNumTabs() > 1) - text = hideWindowText; - else - text = closeWindowText; - } - else - { - text = showWindowText; - } - - if (GUILayout.Button(text, EditorStyles.miniButton, GUILayout.Width(110))) - { - if (window && window.IsVisible() && alreadySelected) - { - // Hide window (close instead if not possible) - if (!window.ShowNextTabIfPossible()) - window.Close(); - } - else - { - if (!alreadySelected) - { - ParticleSystemEditorUtils.lockedParticleSystem = null; - Selection.activeGameObject = targetGameObject; - } - - if (window) - { - if (!alreadySelected) - window.Clear(); - - // Show window - window.Focus(); - } - else - { - // Kill inspector gui first to ensure playback time is cached properly - Clear(); - - // Create new window - ParticleSystemWindow.CreateWindow(); - window = ParticleSystemWindow.GetInstance(); - window.customEditor = this; - GUIUtility.ExitGUI(); - } - } - } - } - } - GUILayout.EndHorizontal(); - } - - public override bool UseDefaultMargins() { return false; } - - public override void OnInspectorGUI() - { - EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins); - - ShowEdiorButtonGUI(); - - if (ShouldShowInspector()) - { - if (m_ParticleEffectUI == null) - Init(true); - - EditorGUILayout.EndVertical(); - EditorGUILayout.BeginVertical(EditorStyles.inspectorFullWidthMargins); - - m_ParticleEffectUI.OnGUI(); - - EditorGUILayout.EndVertical(); - EditorGUILayout.BeginVertical(EditorStyles.inspectorDefaultMargins); - } - else - { - Clear(); - } - - EditorGUILayout.EndVertical(); - } - - void Clear() - { - if (m_ParticleEffectUI != null) - m_ParticleEffectUI.Clear(); - m_ParticleEffectUI = null; - } - - private bool ShouldShowInspector() - { - // Only show the inspector GUI if we are not showing the ParticleSystemWindow - ParticleSystemWindow window = ParticleSystemWindow.GetInstance(); - return !window || !window.IsVisible() || !selectedInParticleSystemWindow; - } - - public void OnSceneViewGUI(SceneView sceneView) - { - if (ShouldShowInspector()) - { - Init(false); // Here because can be called before inspector GUI so to prevent blinking GUI when selecting ps. - if (m_ParticleEffectUI != null) - { - m_ParticleEffectUI.OnSceneViewGUI(); - } - } - } - - public override bool HasPreviewGUI() - { - return ShouldShowInspector(); - } - - public override void DrawPreview(Rect previewArea) - { - ObjectPreview.DrawPreview(this, previewArea, new Object[] { targets[0] }); // only draw the first preview - all the selected systems share it - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - if (m_ParticleEffectUI != null) - m_ParticleEffectUI.GetParticleSystemCurveEditor().OnGUI(r); - } - - public override GUIContent GetPreviewTitle() - { - return m_PreviewTitle; - } - - public override void OnPreviewSettings() - { - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ClampVelocityModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ClampVelocityModuleUI.cs deleted file mode 100644 index c85b21d202..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ClampVelocityModuleUI.cs +++ /dev/null @@ -1,120 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class ClampVelocityModuleUI : ModuleUI - { - SerializedMinMaxCurve m_X; - SerializedMinMaxCurve m_Y; - SerializedMinMaxCurve m_Z; - SerializedMinMaxCurve m_Magnitude; - SerializedProperty m_SeparateAxes; - SerializedProperty m_InWorldSpace; - SerializedProperty m_Dampen; - SerializedMinMaxCurve m_Drag; - SerializedProperty m_MultiplyDragByParticleSize; - SerializedProperty m_MultiplyDragByParticleVelocity; - - class Texts - { - public GUIContent x = EditorGUIUtility.TextContent("X"); - public GUIContent y = EditorGUIUtility.TextContent("Y"); - public GUIContent z = EditorGUIUtility.TextContent("Z"); - public GUIContent dampen = EditorGUIUtility.TrTextContent("Dampen", "Controls how much the velocity that exceeds the velocity limit should be dampened. A value of 0.5 will dampen the exceeding velocity by 50%."); - public GUIContent magnitude = EditorGUIUtility.TrTextContent("Speed", "The speed limit of particles over the particle lifetime."); - public GUIContent separateAxes = EditorGUIUtility.TrTextContent("Separate Axes", "If enabled, you can control the velocity limit separately for each axis."); - public GUIContent space = EditorGUIUtility.TrTextContent("Space", "Specifies if the velocity values are in local space (rotated with the transform) or world space."); - public string[] spaces = { "Local", "World" }; - public GUIContent drag = EditorGUIUtility.TrTextContent("Drag", "Control the amount of drag applied to each particle during its lifetime."); - public GUIContent multiplyDragByParticleSize = EditorGUIUtility.TrTextContent("Multiply by Size", "Adjust the drag based on the size of the particles."); - public GUIContent multiplyDragByParticleVelocity = EditorGUIUtility.TrTextContent("Multiply by Velocity", "Adjust the drag based on the velocity of the particles."); - } - static Texts s_Texts; - - - public ClampVelocityModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "ClampVelocityModule", displayName) - { - m_ToolTip = "Controls the velocity limit and damping of each particle during its lifetime."; - } - - protected override void Init() - { - // Already initialized? - if (m_X != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_X = new SerializedMinMaxCurve(this, s_Texts.x, "x"); - m_Y = new SerializedMinMaxCurve(this, s_Texts.y, "y"); - m_Z = new SerializedMinMaxCurve(this, s_Texts.z, "z"); - m_Magnitude = new SerializedMinMaxCurve(this, s_Texts.magnitude, "magnitude"); - m_SeparateAxes = GetProperty("separateAxis"); - m_InWorldSpace = GetProperty("inWorldSpace"); - m_Dampen = GetProperty("dampen"); - m_Drag = new SerializedMinMaxCurve(this, s_Texts.drag, "drag"); - m_MultiplyDragByParticleSize = GetProperty("multiplyDragByParticleSize"); - m_MultiplyDragByParticleVelocity = GetProperty("multiplyDragByParticleVelocity"); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - EditorGUI.BeginChangeCheck(); - bool separateAxes = GUIToggle(s_Texts.separateAxes, m_SeparateAxes); - if (EditorGUI.EndChangeCheck()) - { - // Remove old curves from curve editor - if (separateAxes) - { - m_Magnitude.RemoveCurveFromEditor(); - } - else - { - m_X.RemoveCurveFromEditor(); - m_Y.RemoveCurveFromEditor(); - m_Z.RemoveCurveFromEditor(); - } - } - - // Keep states in sync - if (!m_X.stateHasMultipleDifferentValues) - { - m_Y.SetMinMaxState(m_X.state, separateAxes); - m_Z.SetMinMaxState(m_X.state, separateAxes); - } - - if (separateAxes) - { - GUITripleMinMaxCurve(GUIContent.none, s_Texts.x, m_X, s_Texts.y, m_Y, s_Texts.z, m_Z, null); - EditorGUI.indentLevel++; - GUIBoolAsPopup(s_Texts.space, m_InWorldSpace, s_Texts.spaces); - EditorGUI.indentLevel--; - } - else - { - GUIMinMaxCurve(s_Texts.magnitude, m_Magnitude); - } - - EditorGUI.indentLevel++; - GUIFloat(s_Texts.dampen, m_Dampen); - EditorGUI.indentLevel--; - - GUIMinMaxCurve(s_Texts.drag, m_Drag); - EditorGUI.indentLevel++; - GUIToggle(s_Texts.multiplyDragByParticleSize, m_MultiplyDragByParticleSize); - GUIToggle(s_Texts.multiplyDragByParticleVelocity, m_MultiplyDragByParticleVelocity); - EditorGUI.indentLevel--; - } - - override public void UpdateCullingSupportedString(ref string text) - { - text += "\nLimit Velocity over Lifetime module is enabled."; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/CollisionModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/CollisionModuleUI.cs deleted file mode 100644 index 0e27873603..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/CollisionModuleUI.cs +++ /dev/null @@ -1,665 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor -{ - class CollisionModuleUI : ModuleUI - { - // Keep in sync with CollisionModule.h - const int k_MaxNumPlanes = 6; - enum CollisionTypes { Plane = 0, World = 1 }; - enum CollisionModes { Mode3D = 0, Mode2D = 1 }; - enum ForceModes { None = 0, Constant = 1, SizeBased = 2 }; - enum PlaneVizType { Grid, Solid }; - - SerializedProperty m_Type; - SerializedProperty[] m_Planes = new SerializedProperty[k_MaxNumPlanes]; - SerializedMinMaxCurve m_Dampen; - SerializedMinMaxCurve m_Bounce; - SerializedMinMaxCurve m_LifetimeLossOnCollision; - SerializedProperty m_MinKillSpeed; - SerializedProperty m_MaxKillSpeed; - SerializedProperty m_RadiusScale; - SerializedProperty m_CollidesWith; - SerializedProperty m_CollidesWithDynamic; - SerializedProperty m_MaxCollisionShapes; - SerializedProperty m_Quality; - SerializedProperty m_VoxelSize; - SerializedProperty m_CollisionMessages; - SerializedProperty m_CollisionMode; - SerializedProperty m_ColliderForce; - SerializedProperty m_MultiplyColliderForceByCollisionAngle; - SerializedProperty m_MultiplyColliderForceByParticleSpeed; - SerializedProperty m_MultiplyColliderForceByParticleSize; - - SerializedProperty[] m_ShownPlanes; - - List m_ScenePlanes = new List(); - static PlaneVizType m_PlaneVisualizationType = PlaneVizType.Solid; - static float m_ScaleGrid = 1.0f; - static bool s_VisualizeBounds = false; - static Transform s_SelectedTransform; // static so to ensure only one selected Transform across multiple particle systems - - class Texts - { - public GUIContent lifetimeLoss = EditorGUIUtility.TrTextContent("Lifetime Loss", "When particle collides, it will lose this fraction of its Start Lifetime"); - public GUIContent planes = EditorGUIUtility.TrTextContent("Planes", "Planes are defined by assigning a reference to a transform. This transform can be any transform in the scene and can be animated. Multiple planes can be used. Note: the Y-axis is used as the plane normal."); - public GUIContent createPlane = EditorGUIUtility.TrTextContent("", "Create an empty GameObject and assign it as a plane."); - public GUIContent minKillSpeed = EditorGUIUtility.TrTextContent("Min Kill Speed", "When particles collide and their speed is lower than this value, they are killed."); - public GUIContent maxKillSpeed = EditorGUIUtility.TrTextContent("Max Kill Speed", "When particles collide and their speed is higher than this value, they are killed."); - public GUIContent dampen = EditorGUIUtility.TrTextContent("Dampen", "When particle collides, it will lose this fraction of its speed. Unless this is set to 0.0, particle will become slower after collision."); - public GUIContent bounce = EditorGUIUtility.TrTextContent("Bounce", "When particle collides, the bounce is scaled with this value. The bounce is the upwards motion in the plane normal direction."); - public GUIContent radiusScale = EditorGUIUtility.TrTextContent("Radius Scale", "Scale particle bounds by this amount to get more precise collisions."); - public GUIContent visualization = EditorGUIUtility.TrTextContent("Visualization", "Only used for visualizing the planes: Wireframe or Solid."); - public GUIContent scalePlane = EditorGUIUtility.TrTextContent("Scale Plane", "Resizes the visualization planes."); - public GUIContent visualizeBounds = EditorGUIUtility.TrTextContent("Visualize Bounds", "Render the collision bounds of the particles."); - public GUIContent collidesWith = EditorGUIUtility.TrTextContent("Collides With", "Collides the particles with colliders included in the layermask."); - public GUIContent collidesWithDynamic = EditorGUIUtility.TrTextContent("Enable Dynamic Colliders", "Should particles collide with dynamic objects?"); - public GUIContent maxCollisionShapes = EditorGUIUtility.TrTextContent("Max Collision Shapes", "How many collision shapes can be considered for particle collisions. Excess shapes will be ignored. Terrains take priority."); - public GUIContent quality = EditorGUIUtility.TrTextContent("Collision Quality", "Quality of world collisions. Medium and low quality are approximate and may leak particles."); - public GUIContent voxelSize = EditorGUIUtility.TrTextContent("Voxel Size", "Size of voxels in the collision cache. Smaller values improve accuracy, but require higher memory usage and are less efficient."); - public GUIContent collisionMessages = EditorGUIUtility.TrTextContent("Send Collision Messages", "Send collision callback messages."); - public GUIContent collisionType = EditorGUIUtility.TrTextContent("Type", "Collide with a list of Planes, or the Physics World."); - public GUIContent collisionMode = EditorGUIUtility.TrTextContent("Mode", "Use 3D Physics or 2D Physics."); - public GUIContent colliderForce = EditorGUIUtility.TrTextContent("Collider Force", "Control the strength of particle forces on colliders."); - public GUIContent multiplyColliderForceByCollisionAngle = EditorGUIUtility.TrTextContent("Multiply by Collision Angle", "Should the force be proportional to the angle of the particle collision? A particle collision directly along the collision normal produces all the specified force whilst collisions away from the collision normal produce less force."); - public GUIContent multiplyColliderForceByParticleSpeed = EditorGUIUtility.TrTextContent("Multiply by Particle Speed", "Should the force be proportional to the particle speed?"); - public GUIContent multiplyColliderForceByParticleSize = EditorGUIUtility.TrTextContent("Multiply by Particle Size", "Should the force be proportional to the particle size?"); - - public GUIContent[] collisionTypes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Planes"), - EditorGUIUtility.TrTextContent("World") - }; - - public GUIContent[] collisionModes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("3D"), - EditorGUIUtility.TrTextContent("2D") - }; - - public GUIContent[] qualitySettings = new GUIContent[] - { - EditorGUIUtility.TrTextContent("High"), - EditorGUIUtility.TrTextContent("Medium (Static Colliders)"), - EditorGUIUtility.TrTextContent("Low (Static Colliders)") - }; - - public GUIContent[] planeVizTypes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Grid"), - EditorGUIUtility.TrTextContent("Solid") - }; - - public GUIContent[] toolContents = - { - EditorGUIUtility.TrIconContent("MoveTool", "Move plane editing mode."), - EditorGUIUtility.TrIconContent("RotateTool", "Rotate plane editing mode.") - }; - - public EditMode.SceneViewEditMode[] sceneViewEditModes = new[] - { - EditMode.SceneViewEditMode.ParticleSystemCollisionModulePlanesMove, - EditMode.SceneViewEditMode.ParticleSystemCollisionModulePlanesRotate - }; - } - private static Texts s_Texts; - - public CollisionModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "CollisionModule", displayName) - { - m_ToolTip = "Allows you to specify multiple collision planes that the particle can collide with."; - } - - private bool editingPlanes - { - get - { - return ((EditMode.editMode == EditMode.SceneViewEditMode.ParticleSystemCollisionModulePlanesMove || - EditMode.editMode == EditMode.SceneViewEditMode.ParticleSystemCollisionModulePlanesRotate) && - EditMode.IsOwner(m_ParticleSystemUI.m_ParticleEffectUI.m_Owner.customEditor)); - } - set - { - if (!value && editingPlanes) - { - EditMode.QuitEditMode(); - } - SceneView.RepaintAll(); - } - } - - protected override void Init() - { - // Already initialized? - if (m_Type != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_Type = GetProperty("type"); - - List shownPlanes = new List(); - for (int i = 0; i < m_Planes.Length; ++i) - { - m_Planes[i] = GetProperty("plane" + i); // Keep name in sync with transfer func in CollisionModule.h - System.Diagnostics.Debug.Assert(m_Planes[i] != null); - - // Always show the first plane - if (i == 0 || m_Planes[i].objectReferenceValue != null) - shownPlanes.Add(m_Planes[i]); - } - - m_ShownPlanes = shownPlanes.ToArray(); - - m_Dampen = new SerializedMinMaxCurve(this, s_Texts.dampen, "m_Dampen"); - m_Dampen.m_AllowCurves = false; - - m_Bounce = new SerializedMinMaxCurve(this, s_Texts.bounce, "m_Bounce"); - m_Bounce.m_AllowCurves = false; - - m_LifetimeLossOnCollision = new SerializedMinMaxCurve(this, s_Texts.lifetimeLoss, "m_EnergyLossOnCollision"); - m_LifetimeLossOnCollision.m_AllowCurves = false; - - m_MinKillSpeed = GetProperty("minKillSpeed"); - m_MaxKillSpeed = GetProperty("maxKillSpeed"); - m_RadiusScale = GetProperty("radiusScale"); - - m_PlaneVisualizationType = (PlaneVizType)EditorPrefs.GetInt("PlaneColisionVizType", (int)PlaneVizType.Solid); - m_ScaleGrid = EditorPrefs.GetFloat("ScalePlaneColision", 1f); - s_VisualizeBounds = EditorPrefs.GetBool("VisualizeBounds", false); - - m_CollidesWith = GetProperty("collidesWith"); - m_CollidesWithDynamic = GetProperty("collidesWithDynamic"); - m_MaxCollisionShapes = GetProperty("maxCollisionShapes"); - - m_Quality = GetProperty("quality"); - - m_VoxelSize = GetProperty("voxelSize"); - - m_CollisionMessages = GetProperty("collisionMessages"); - m_CollisionMode = GetProperty("collisionMode"); - - m_ColliderForce = GetProperty("colliderForce"); - m_MultiplyColliderForceByCollisionAngle = GetProperty("multiplyColliderForceByCollisionAngle"); - m_MultiplyColliderForceByParticleSpeed = GetProperty("multiplyColliderForceByParticleSpeed"); - m_MultiplyColliderForceByParticleSize = GetProperty("multiplyColliderForceByParticleSize"); - - SyncVisualization(); - } - - public override void UndoRedoPerformed() - { - base.UndoRedoPerformed(); - SyncVisualization(); - } - - protected override void SetVisibilityState(VisibilityState newState) - { - base.SetVisibilityState(newState); - - // Show tools again when module is not visible - if (newState != VisibilityState.VisibleAndFoldedOut) - { - s_SelectedTransform = null; - editingPlanes = false; - } - else - { - SyncVisualization(); - } - } - - private Bounds GetBounds() - { - var combinedBounds = new Bounds(); - bool initialized = false; - - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - ParticleSystemRenderer particleSystemRenderer = ps.GetComponent(); - if (!initialized) - combinedBounds = particleSystemRenderer.bounds; - combinedBounds.Encapsulate(particleSystemRenderer.bounds); - - initialized = true; - } - - return combinedBounds; - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - EditorGUI.BeginChangeCheck(); - CollisionTypes type = (CollisionTypes)GUIPopup(s_Texts.collisionType, m_Type, s_Texts.collisionTypes); - if (EditorGUI.EndChangeCheck()) - SyncVisualization(); - - if (type == CollisionTypes.Plane) - { - DoListOfPlanesGUI(); - - EditorGUI.BeginChangeCheck(); - m_PlaneVisualizationType = (PlaneVizType)GUIPopup(s_Texts.visualization, (int)m_PlaneVisualizationType, s_Texts.planeVizTypes); - if (EditorGUI.EndChangeCheck()) - { - EditorPrefs.SetInt("PlaneColisionVizType", (int)m_PlaneVisualizationType); - } - - EditorGUI.BeginChangeCheck(); - m_ScaleGrid = GUIFloat(s_Texts.scalePlane, m_ScaleGrid, "f2"); - if (EditorGUI.EndChangeCheck()) - { - m_ScaleGrid = Mathf.Max(0f, m_ScaleGrid); - EditorPrefs.SetFloat("ScalePlaneColision", m_ScaleGrid); - } - - GUIButtonGroup(s_Texts.sceneViewEditModes, s_Texts.toolContents, GetBounds, m_ParticleSystemUI.m_ParticleEffectUI.m_Owner.customEditor); - } - else - { - GUIPopup(s_Texts.collisionMode, m_CollisionMode, s_Texts.collisionModes); - } - - GUIMinMaxCurve(s_Texts.dampen, m_Dampen); - GUIMinMaxCurve(s_Texts.bounce, m_Bounce); - GUIMinMaxCurve(s_Texts.lifetimeLoss, m_LifetimeLossOnCollision); - GUIFloat(s_Texts.minKillSpeed, m_MinKillSpeed); - GUIFloat(s_Texts.maxKillSpeed, m_MaxKillSpeed); - GUIFloat(s_Texts.radiusScale, m_RadiusScale); - - if (type == CollisionTypes.World) - { - GUIPopup(s_Texts.quality, m_Quality, s_Texts.qualitySettings); - EditorGUI.indentLevel++; - GUILayerMask(s_Texts.collidesWith, m_CollidesWith); - GUIInt(s_Texts.maxCollisionShapes, m_MaxCollisionShapes); - - if (m_Quality.intValue == 0) - GUIToggle(s_Texts.collidesWithDynamic, m_CollidesWithDynamic); - else - GUIFloat(s_Texts.voxelSize, m_VoxelSize); - - EditorGUI.indentLevel--; - - GUIFloat(s_Texts.colliderForce, m_ColliderForce); - EditorGUI.indentLevel++; - GUIToggle(s_Texts.multiplyColliderForceByCollisionAngle, m_MultiplyColliderForceByCollisionAngle); - GUIToggle(s_Texts.multiplyColliderForceByParticleSpeed, m_MultiplyColliderForceByParticleSpeed); - GUIToggle(s_Texts.multiplyColliderForceByParticleSize, m_MultiplyColliderForceByParticleSize); - EditorGUI.indentLevel--; - } - - GUIToggle(s_Texts.collisionMessages, m_CollisionMessages); - - EditorGUI.BeginChangeCheck(); - s_VisualizeBounds = GUIToggle(s_Texts.visualizeBounds, s_VisualizeBounds); - if (EditorGUI.EndChangeCheck()) - { - EditorPrefs.SetBool("VisualizeBounds", s_VisualizeBounds); - } - } - - protected override void OnModuleEnable() - { - base.OnModuleEnable(); - SyncVisualization(); - } - - protected override void OnModuleDisable() - { - base.OnModuleDisable(); - editingPlanes = false; - } - - private void SyncVisualization() - { - m_ScenePlanes.Clear(); - - if (m_ParticleSystemUI.multiEdit) - { - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - if (ps.collision.type != ParticleSystemCollisionType.Planes) - continue; - - for (int planeIndex = 0; planeIndex < k_MaxNumPlanes; planeIndex++) - { - var transform = ps.collision.GetPlane(planeIndex); - if (transform != null && !m_ScenePlanes.Contains(transform)) - m_ScenePlanes.Add(transform); - } - } - } - else - { - CollisionTypes type = (CollisionTypes)m_Type.intValue; - if (type != CollisionTypes.Plane) - { - editingPlanes = false; - return; - } - for (int i = 0; i < m_ShownPlanes.Length; ++i) - { - Transform transform = m_ShownPlanes[i].objectReferenceValue as Transform; - if (transform != null && !m_ScenePlanes.Contains(transform)) - m_ScenePlanes.Add(transform); - } - } - } - - private static GameObject CreateEmptyGameObject(string name, ParticleSystem parentOfGameObject) - { - GameObject go = new GameObject(name); - if (go) - { - if (parentOfGameObject) - go.transform.parent = parentOfGameObject.transform; - Undo.RegisterCreatedObjectUndo(go, "Created `" + name + "`"); - return go; - } - return null; - } - - private bool IsListOfPlanesValid() - { - if (m_ParticleSystemUI.multiEdit) - { - for (int planeIndex = 0; planeIndex < k_MaxNumPlanes; planeIndex++) - { - int hasPlane = -1; - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - int planeValue = (ps.collision.GetPlane(planeIndex) != null) ? 1 : 0; - if (hasPlane == -1) - { - hasPlane = planeValue; - } - else if (planeValue != hasPlane) - { - return false; - } - } - } - } - - return true; - } - - private void DoListOfPlanesGUI() - { - // only show the list of planes when we can edit them safely - if (!IsListOfPlanesValid()) - { - EditorGUILayout.HelpBox("Plane list editing is only available when all selected systems contain the same number of planes", MessageType.Info, true); - return; - } - - EditorGUI.BeginChangeCheck(); - int buttonPressedIndex = GUIListOfFloatObjectToggleFields(s_Texts.planes, m_ShownPlanes, null, s_Texts.createPlane, !m_ParticleSystemUI.multiEdit); - bool listChanged = EditorGUI.EndChangeCheck(); - - if (buttonPressedIndex >= 0 && !m_ParticleSystemUI.multiEdit) - { - GameObject go = CreateEmptyGameObject("Plane Transform " + (buttonPressedIndex + 1), m_ParticleSystemUI.m_ParticleSystems[0]); - go.transform.localPosition = new Vector3(0, 0, 10 + buttonPressedIndex); // ensure each plane is not at same pos - go.transform.localEulerAngles = (new Vector3(-90, 0, 0)); // make the plane normal point towards the forward axis of the particle system - - m_ShownPlanes[buttonPressedIndex].objectReferenceValue = go; - listChanged = true; - } - - // Minus button - Rect rect = GUILayoutUtility.GetRect(0, EditorGUI.kSingleLineHeight); //GUILayoutUtility.GetLastRect(); - rect.x = rect.xMax - kPlusAddRemoveButtonWidth * 2 - kPlusAddRemoveButtonSpacing; - rect.width = kPlusAddRemoveButtonWidth; - if (m_ShownPlanes.Length > 1) - { - if (MinusButton(rect)) - { - m_ShownPlanes[m_ShownPlanes.Length - 1].objectReferenceValue = null; - List shownPlanes = new List(m_ShownPlanes); - shownPlanes.RemoveAt(shownPlanes.Count - 1); - m_ShownPlanes = shownPlanes.ToArray(); - listChanged = true; - } - } - - // Plus button - if (m_ShownPlanes.Length < k_MaxNumPlanes && !m_ParticleSystemUI.multiEdit) - { - rect.x += kPlusAddRemoveButtonWidth + kPlusAddRemoveButtonSpacing; - if (PlusButton(rect)) - { - List shownPlanes = new List(m_ShownPlanes); - shownPlanes.Add(m_Planes[shownPlanes.Count]); - m_ShownPlanes = shownPlanes.ToArray(); - } - } - - if (listChanged) - SyncVisualization(); - } - - override public void OnSceneViewGUI() - { - RenderCollisionBounds(); - CollisionPlanesSceneGUI(); - } - - private void CollisionPlanesSceneGUI() - { - if (m_ScenePlanes.Count == 0) - return; - - Event evt = Event.current; - - Color origCol = Handles.color; - Color col = new Color(1, 1, 1, 0.5F); - - for (int i = 0; i < m_ScenePlanes.Count; ++i) - { - if (m_ScenePlanes[i] == null) - continue; - - Transform transform = m_ScenePlanes[i]; - Vector3 position = transform.position; - Quaternion rotation = transform.rotation; - Vector3 right = rotation * Vector3.right; - Vector3 up = rotation * Vector3.up; - Vector3 forward = rotation * Vector3.forward; - bool isPlayingAndStatic = EditorApplication.isPlaying && transform.gameObject.isStatic; - if (editingPlanes) - { - if (Object.ReferenceEquals(s_SelectedTransform, transform)) - { - EditorGUI.BeginChangeCheck(); - var newPosition = transform.position; - var newRotation = transform.rotation; - - using (new EditorGUI.DisabledScope(isPlayingAndStatic)) - { - if (isPlayingAndStatic) - Handles.ShowStaticLabel(position); - if (EditMode.editMode == EditMode.SceneViewEditMode.ParticleSystemCollisionModulePlanesMove) - newPosition = Handles.PositionHandle(position, rotation); - else if (EditMode.editMode == EditMode.SceneViewEditMode.ParticleSystemCollisionModulePlanesRotate) - newRotation = Handles.RotationHandle(rotation, position); - } - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(transform, "Modified Collision Plane Transform"); - transform.position = newPosition; - transform.rotation = newRotation; - ParticleSystemEditorUtils.PerformCompleteResimulation(); - } - } - else - { - float handleSize = HandleUtility.GetHandleSize(position) * 0.6f; - - EventType oldEventType = evt.type; - - // we want ignored mouse up events to check for dragging off of scene view - if (evt.type == EventType.Ignore && evt.rawType == EventType.MouseUp) - oldEventType = evt.rawType; - - Handles.FreeMoveHandle(position, Quaternion.identity, handleSize, Vector3.zero, Handles.RectangleHandleCap); - - // Detect selected plane (similar to TreeEditor) - if (oldEventType == EventType.MouseDown && evt.type == EventType.Used) - { - s_SelectedTransform = transform; - oldEventType = EventType.Used; - GUIUtility.hotControl = 0; // Reset hot control or the FreeMoveHandle will prevent input to the new Handles. (case 873514) - } - } - } - - Handles.color = col; - Color color = Handles.s_ColliderHandleColor * 0.9f; - if (isPlayingAndStatic) - color.a *= 0.2f; - - if (m_PlaneVisualizationType == PlaneVizType.Grid) - { - DrawGrid(position, right, forward, up, color); - } - else - { - DrawSolidPlane(position, rotation, color, Color.yellow); - } - } - - Handles.color = origCol; - } - - void RenderCollisionBounds() - { - if (s_VisualizeBounds == false) - return; - - Color oldColor = Handles.color; - Handles.color = Color.green; - Matrix4x4 oldMatrix = Handles.matrix; - - Vector3[] points0 = new Vector3[20]; - Vector3[] points1 = new Vector3[20]; - Vector3[] points2 = new Vector3[20]; - - Handles.SetDiscSectionPoints(points0, Vector3.zero, Vector3.forward, Vector3.right, 360, 1.0f); - Handles.SetDiscSectionPoints(points1, Vector3.zero, Vector3.up, -Vector3.right, 360, 1.0f); - Handles.SetDiscSectionPoints(points2, Vector3.zero, Vector3.right, Vector3.up, 360, 1.0f); - - Vector3[] points = new Vector3[points0.Length + points1.Length + points2.Length]; - points0.CopyTo(points, 0); - points1.CopyTo(points, 20); - points2.CopyTo(points, 40); - - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - if (!ps.collision.enabled) - continue; - - ParticleSystem.Particle[] particles = new ParticleSystem.Particle[ps.particleCount]; - int count = ps.GetParticles(particles); - - Matrix4x4 transform = Matrix4x4.identity; - if (ps.main.simulationSpace == ParticleSystemSimulationSpace.Local) - { - transform = ps.GetLocalToWorldMatrix(); - } - - for (int i = 0; i < count; i++) - { - ParticleSystem.Particle particle = particles[i]; - Vector3 size = particle.GetCurrentSize3D(ps); - - float radius = System.Math.Max(size.x, System.Math.Max(size.y, size.z)) * 0.5f * ps.collision.radiusScale; - Handles.matrix = transform * Matrix4x4.TRS(particle.position, Quaternion.identity, new Vector3(radius, radius, radius)); - Handles.DrawPolyLine(points); - } - } - - Handles.color = oldColor; - Handles.matrix = oldMatrix; - } - - private static void DrawSolidPlane(Vector3 pos, Quaternion rot, Color faceColor, Color edgeColor) - { - if (Event.current.type != EventType.Repaint) - return; - - var oldMatrix = Handles.matrix; - float scale = 10 * m_ScaleGrid; - Handles.matrix = Matrix4x4.TRS(pos, rot, new Vector3(scale, scale, scale)) * Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(90, 0, 0), Vector3.one); // Rotate plane by 90 - Handles.DrawSolidRectangleWithOutline(new Rect(-0.5f, -0.5f, 1, 1), faceColor, edgeColor); - Handles.DrawLine(Vector3.zero, Vector3.back / scale); - Handles.matrix = oldMatrix; - } - - private static void DrawGrid(Vector3 pos, Vector3 axis1, Vector3 axis2, Vector3 normal, Color color) - { - if (Event.current.type != EventType.Repaint) - return; - - HandleUtility.ApplyWireMaterial(); - - if (color.a > 0) - { - GL.Begin(GL.LINES); - - float lineLength = 10f; - int numLines = 11; - - lineLength *= m_ScaleGrid; - numLines = (int)lineLength; - numLines = Mathf.Clamp(numLines, 10, 40); - if (numLines % 2 == 0) - numLines++; - - float halfLength = lineLength * 0.5f; - - float distBetweenLines = lineLength / (numLines - 1); - Vector3 v1 = axis1 * lineLength; - Vector3 v2 = axis2 * lineLength; - Vector3 dist1 = axis1 * distBetweenLines; - Vector3 dist2 = axis2 * distBetweenLines; - Vector3 startPos = pos - axis1 * halfLength - axis2 * halfLength; - - for (int i = 0; i < numLines; i++) - { - if (i % 2 == 0) - GL.Color(color * 0.7f); - else - GL.Color(color); - - // Axis1 - GL.Vertex(startPos + i * dist1); - GL.Vertex(startPos + i * dist1 + v2); - - // Axis2 - GL.Vertex(startPos + i * dist2); - GL.Vertex(startPos + i * dist2 + v1); - } - - GL.Color(color); - GL.Vertex(pos); - GL.Vertex(pos + normal); - - - GL.End(); - } - } - - override public void UpdateCullingSupportedString(ref string text) - { - text += "\nCollision module is enabled."; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ColorByVelocityModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ColorByVelocityModuleUI.cs deleted file mode 100644 index b37f5d39c9..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ColorByVelocityModuleUI.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class ColorByVelocityModuleUI : ModuleUI - { - class Texts - { - public GUIContent color = EditorGUIUtility.TrTextContent("Color", "Controls the color of each particle based on its speed."); - public GUIContent velocityRange = EditorGUIUtility.TrTextContent("Speed Range", "Remaps speed in the defined range to a color."); - } - static Texts s_Texts; - SerializedMinMaxGradient m_Gradient; - SerializedProperty m_Range; - - public ColorByVelocityModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "ColorBySpeedModule", displayName) - { - m_ToolTip = "Controls the color of each particle based on its speed."; - } - - protected override void Init() - { - // Already initialized? - if (m_Gradient != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_Gradient = new SerializedMinMaxGradient(this); - m_Gradient.m_AllowColor = false; - m_Gradient.m_AllowRandomBetweenTwoColors = false; - - m_Range = GetProperty("range"); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - GUIMinMaxGradient(s_Texts.color, m_Gradient, false); - GUIMinMaxRange(s_Texts.velocityRange, m_Range); - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ColorModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ColorModuleUI.cs deleted file mode 100644 index 9aaafdf557..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ColorModuleUI.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class ColorModuleUI : ModuleUI - { - class Texts - { - public GUIContent color = EditorGUIUtility.TrTextContent("Color", "Controls the color of each particle during its lifetime."); - } - static Texts s_Texts; - SerializedMinMaxGradient m_Gradient; - - public ColorModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "ColorModule", displayName) - { - m_ToolTip = "Controls the color of each particle during its lifetime."; - } - - protected override void Init() - { - // Already initialized? - if (m_Gradient != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_Gradient = new SerializedMinMaxGradient(this); - m_Gradient.m_AllowColor = false; - m_Gradient.m_AllowRandomBetweenTwoColors = false; - } - - public override void OnInspectorGUI(InitialModuleUI initial) - { - GUIMinMaxGradient(s_Texts.color, m_Gradient, false); - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/CustomDataModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/CustomDataModuleUI.cs deleted file mode 100644 index 5fa82a7b8d..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/CustomDataModuleUI.cs +++ /dev/null @@ -1,89 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class CustomDataModuleUI : ModuleUI - { - enum Mode { Disabled = 0, Vector = 1, Color = 2 }; - const int k_NumCustomDataStreams = 2; - const int k_NumChannelsPerStream = 4; - - SerializedProperty[] m_Modes = new SerializedProperty[k_NumCustomDataStreams]; - SerializedProperty[] m_VectorComponentCount = new SerializedProperty[k_NumCustomDataStreams]; - SerializedMinMaxCurve[,] m_Vectors = new SerializedMinMaxCurve[k_NumCustomDataStreams, k_NumChannelsPerStream]; - SerializedMinMaxGradient[] m_Colors = new SerializedMinMaxGradient[k_NumCustomDataStreams]; - SerializedProperty[,] m_VectorLabels = new SerializedProperty[k_NumCustomDataStreams, k_NumChannelsPerStream]; - SerializedProperty[] m_ColorLabels = new SerializedProperty[k_NumCustomDataStreams]; - - class Texts - { - public GUIContent mode = EditorGUIUtility.TrTextContent("Mode", "Select the type of data to populate this stream with."); - public GUIContent vectorComponentCount = EditorGUIUtility.TrTextContent("Number of Components", "How many of the components (XYZW) to fill."); - - public GUIContent[] modes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Disabled"), - EditorGUIUtility.TrTextContent("Vector"), - EditorGUIUtility.TrTextContent("Color") - }; - } - static Texts s_Texts; - - public CustomDataModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "CustomDataModule", displayName) - { - m_ToolTip = "Configure custom data to be read in scripts or shaders. Use GetCustomParticleData from script, or send to shaders using the Custom Vertex Streams."; - } - - protected override void Init() - { - // Already initialized? - if (m_Modes[0] != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - for (int i = 0; i < k_NumCustomDataStreams; i++) - { - m_Modes[i] = GetProperty("mode" + i); - m_VectorComponentCount[i] = GetProperty("vectorComponentCount" + i); - m_Colors[i] = new SerializedMinMaxGradient(this, "color" + i); - m_ColorLabels[i] = GetProperty("colorLabel" + i); - for (int j = 0; j < k_NumChannelsPerStream; j++) - { - m_Vectors[i, j] = new SerializedMinMaxCurve(this, GUIContent.none, "vector" + i + "_" + j, kUseSignedRange); - m_VectorLabels[i, j] = GetProperty("vectorLabel" + i + "_" + j); - } - } - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - for (int i = 0; i < k_NumCustomDataStreams; i++) - { - GUILayout.BeginVertical("Custom" + (i + 1), GUI.skin.window); - - Mode mode = (Mode)GUIPopup(s_Texts.mode, m_Modes[i], s_Texts.modes); - if (mode == Mode.Vector) - { - int vectorComponentCount = Mathf.Min(GUIInt(s_Texts.vectorComponentCount, m_VectorComponentCount[i]), k_NumChannelsPerStream); - for (int j = 0; j < vectorComponentCount; j++) - { - GUIMinMaxCurve(m_VectorLabels[i, j], m_Vectors[i, j]); - } - } - else if (mode == Mode.Color) - { - GUIMinMaxGradient(m_ColorLabels[i], m_Colors[i], true); - } - - GUILayout.EndVertical(); - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/EmissionModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/EmissionModuleUI.cs deleted file mode 100644 index d657246e26..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/EmissionModuleUI.cs +++ /dev/null @@ -1,233 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using System.Collections.Generic; - -namespace UnityEditor -{ - class EmissionModuleUI : ModuleUI - { - public SerializedMinMaxCurve m_Time; - public SerializedMinMaxCurve m_Distance; - - // Keep in sync with EmissionModule.h - const int k_MaxNumBursts = 8; - const float k_BurstDragWidth = 15.0f; - SerializedProperty m_BurstCount; - SerializedProperty m_Bursts; - List m_BurstCountCurves = new List(); - - ReorderableList m_BurstList; - - class Texts - { - public GUIContent rateOverTime = EditorGUIUtility.TrTextContent("Rate over Time", "The number of particles emitted per second."); - public GUIContent rateOverDistance = EditorGUIUtility.TrTextContent("Rate over Distance", "The number of particles emitted per distance unit."); - public GUIContent burst = EditorGUIUtility.TrTextContent("Bursts", "Emission of extra particles at specific times during the duration of the system."); - public GUIContent burstTime = EditorGUIUtility.TrTextContent("Time", "When the burst will trigger."); - public GUIContent burstCount = EditorGUIUtility.TrTextContent("Count", "The number of particles to emit."); - public GUIContent burstCycleCount = EditorGUIUtility.TrTextContent("Cycles", "How many times to emit the burst. Use the dropdown to repeat infinitely."); - public GUIContent burstCycleCountInfinite = EditorGUIUtility.TrTextContent("Infinite"); - public GUIContent burstRepeatInterval = EditorGUIUtility.TrTextContent("Interval", "Repeat the burst every N seconds."); - } - private static Texts s_Texts; - - public EmissionModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "EmissionModule", displayName) - { - m_ToolTip = "Emission of the emitter. This controls the rate at which particles are emitted as well as burst emissions."; - } - - protected override void Init() - { - // Already initialized? - if (m_BurstCount != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_Time = new SerializedMinMaxCurve(this, s_Texts.rateOverTime, "rateOverTime"); - m_Distance = new SerializedMinMaxCurve(this, s_Texts.rateOverDistance, "rateOverDistance"); - - m_BurstCount = GetProperty("m_BurstCount"); - m_Bursts = GetProperty("m_Bursts"); - - m_BurstList = new ReorderableList(serializedObject, m_Bursts, false, true, true, true); - m_BurstList.elementHeight = kReorderableListElementHeight; - m_BurstList.onAddCallback = OnBurstListAddCallback; - m_BurstList.onCanAddCallback = OnBurstListCanAddCallback; - m_BurstList.onRemoveCallback = OnBurstListRemoveCallback; - m_BurstList.drawHeaderCallback = DrawBurstListHeaderCallback; - m_BurstList.drawElementCallback = DrawBurstListElementCallback; - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - GUIMinMaxCurve(s_Texts.rateOverTime, m_Time); - GUIMinMaxCurve(s_Texts.rateOverDistance, m_Distance); - - DoBurstGUI(initial); - } - - private void DoBurstGUI(InitialModuleUI initial) - { - while (m_BurstList.count > m_BurstCountCurves.Count) - { - SerializedProperty burst = m_Bursts.GetArrayElementAtIndex(m_BurstCountCurves.Count); - m_BurstCountCurves.Add(new SerializedMinMaxCurve(this, s_Texts.burstCount, burst.propertyPath + ".countCurve", false, true)); - } - - EditorGUILayout.Space(); - - Rect rect = GetControlRect(kSingleLineHeight); - GUI.Label(rect, s_Texts.burst, ParticleSystemStyles.Get().label); - - m_BurstList.displayAdd = (m_Bursts.arraySize < k_MaxNumBursts); - m_BurstList.DoLayoutList(); - } - - private void OnBurstListAddCallback(ReorderableList list) - { - ReorderableList.defaultBehaviours.DoAddButton(list); - m_BurstCount.intValue++; - - SerializedProperty burst = m_Bursts.GetArrayElementAtIndex(list.index); - SerializedProperty burstCountState = burst.FindPropertyRelative("countCurve.minMaxState"); - SerializedProperty burstCount = burst.FindPropertyRelative("countCurve.scalar"); - SerializedProperty burstCycleCount = burst.FindPropertyRelative("cycleCount"); - burstCountState.intValue = (int)ParticleSystemCurveMode.Constant; - burstCount.floatValue = 30.0f; - burstCycleCount.intValue = 1; - - SerializedProperty burstCountMinCurve = burst.FindPropertyRelative("countCurve.minCurve"); - SerializedProperty burstCountMaxCurve = burst.FindPropertyRelative("countCurve.maxCurve"); - burstCountMinCurve.animationCurveValue = AnimationCurve.Linear(0.0f, 1.0f, 1.0f, 1.0f); - burstCountMaxCurve.animationCurveValue = AnimationCurve.Linear(0.0f, 1.0f, 1.0f, 1.0f); - - m_BurstCountCurves.Add(new SerializedMinMaxCurve(this, s_Texts.burstCount, burst.propertyPath + ".countCurve", false, true)); - } - - private bool OnBurstListCanAddCallback(ReorderableList list) - { - return !m_ParticleSystemUI.multiEdit; - } - - private void OnBurstListRemoveCallback(ReorderableList list) - { - // All subsequent curves must be removed from the curve editor, as their indices will change, which means their SerializedProperty paths will also change - for (int i = list.index; i < m_BurstCountCurves.Count; i++) - m_BurstCountCurves[i].RemoveCurveFromEditor(); - m_BurstCountCurves.RemoveRange(list.index, m_BurstCountCurves.Count - list.index); - AnimationCurvePreviewCache.ClearCache(); - - // Default remove behavior - ReorderableList.defaultBehaviours.DoRemoveButton(list); - m_BurstCount.intValue--; - } - - private void DrawBurstListHeaderCallback(Rect rect) - { - rect.width -= k_BurstDragWidth; - rect.width /= 4; - rect.x += k_BurstDragWidth; - - EditorGUI.LabelField(rect, s_Texts.burstTime, ParticleSystemStyles.Get().label); - rect.x += rect.width; - - EditorGUI.LabelField(rect, s_Texts.burstCount, ParticleSystemStyles.Get().label); - rect.x += rect.width; - - EditorGUI.LabelField(rect, s_Texts.burstCycleCount, ParticleSystemStyles.Get().label); - rect.x += rect.width; - - EditorGUI.LabelField(rect, s_Texts.burstRepeatInterval, ParticleSystemStyles.Get().label); - rect.x += rect.width; - } - - private void DrawBurstListElementCallback(Rect rect, int index, bool isActive, bool isFocused) - { - SerializedProperty burst = m_Bursts.GetArrayElementAtIndex(index); - SerializedProperty burstTime = burst.FindPropertyRelative("time"); - SerializedProperty burstCycleCount = burst.FindPropertyRelative("cycleCount"); - SerializedProperty burstRepeatInterval = burst.FindPropertyRelative("repeatInterval"); - - rect.width -= (k_BurstDragWidth * 3); - rect.width /= 4; - - // Time - FloatDraggable(rect, burstTime, 1.0f, k_BurstDragWidth, "n3"); - rect.x += rect.width; - - // Count - rect = GUIMinMaxCurveInline(rect, m_BurstCountCurves[index], k_BurstDragWidth); - rect.x += rect.width; - - // Cycle Count - rect.width -= k_minMaxToggleWidth; - if (!burstCycleCount.hasMultipleDifferentValues && burstCycleCount.intValue == 0) - { - rect.x += k_BurstDragWidth; - rect.width -= k_BurstDragWidth; - EditorGUI.LabelField(rect, s_Texts.burstCycleCountInfinite, ParticleSystemStyles.Get().label); - } - else - { - IntDraggable(rect, null, burstCycleCount, k_BurstDragWidth); - } - rect.width += k_minMaxToggleWidth; - Rect popupRect = GetPopupRect(rect); - GUIMMModePopUp(popupRect, burstCycleCount); - rect.x += rect.width; - - // Repeat Interval - FloatDraggable(rect, burstRepeatInterval, 1.0f, k_BurstDragWidth, "n3"); - rect.x += rect.width; - } - - private class ModeCallbackData - { - public ModeCallbackData(int i, SerializedProperty p) - { - modeProp = p; - selectedState = i; - } - - public SerializedProperty modeProp; - public int selectedState; - } - - private static void SelectModeCallback(object obj) - { - ModeCallbackData data = (ModeCallbackData)obj; - data.modeProp.intValue = (int)data.selectedState; - } - - private static void GUIMMModePopUp(Rect rect, SerializedProperty modeProp) - { - if (EditorGUI.DropdownButton(rect, GUIContent.none, FocusType.Passive, ParticleSystemStyles.Get().minMaxCurveStateDropDown)) - { - GUIContent[] texts = { EditorGUIUtility.TrTextContent("Infinite"), EditorGUIUtility.TrTextContent("Count") }; - - GenericMenu menu = new GenericMenu(); - for (int i = 0; i < texts.Length; ++i) - { - menu.AddItem(texts[i], (modeProp.intValue == i), SelectModeCallback, new ModeCallbackData(i, modeProp)); - } - - menu.ShowAsContext(); - Event.current.Use(); - } - } - - override public void UpdateCullingSupportedString(ref string text) - { - Init(); - - if (m_Distance.scalar.hasMultipleDifferentValues || m_Distance.scalar.floatValue > 0.0f) - text += "\nDistance-based emission is being used in the Emission module."; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ExternalForcesModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ExternalForcesModuleUI.cs deleted file mode 100644 index 910f73935d..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ExternalForcesModuleUI.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class ExternalForcesModuleUI : ModuleUI - { - SerializedProperty m_Multiplier; - - class Texts - { - public GUIContent multiplier = EditorGUIUtility.TrTextContent("Multiplier", "Used to scale the force applied to this particle system."); - } - static Texts s_Texts; - - public ExternalForcesModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "ExternalForcesModule", displayName) - { - m_ToolTip = "Controls the wind zones that each particle is affected by."; - } - - protected override void Init() - { - // Already initialized? - if (m_Multiplier != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_Multiplier = GetProperty("multiplier"); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - GUIFloat(s_Texts.multiplier, m_Multiplier); - } - - override public void UpdateCullingSupportedString(ref string text) - { - text += "\nExternal Forces module is enabled."; - } - } // namespace UnityEditor -} diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ForceModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ForceModuleUI.cs deleted file mode 100644 index 74add0163f..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ForceModuleUI.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class ForceModuleUI : ModuleUI - { - SerializedMinMaxCurve m_X; - SerializedMinMaxCurve m_Y; - SerializedMinMaxCurve m_Z; - SerializedProperty m_RandomizePerFrame; - SerializedProperty m_InWorldSpace; - - - class Texts - { - public GUIContent x = EditorGUIUtility.TextContent("X"); - public GUIContent y = EditorGUIUtility.TextContent("Y"); - public GUIContent z = EditorGUIUtility.TextContent("Z"); - public GUIContent randomizePerFrame = EditorGUIUtility.TrTextContent("Randomize", "Randomize force every frame. Only available when using random between two constants or random between two curves."); - public GUIContent space = EditorGUIUtility.TrTextContent("Space", "Specifies if the force values are in local space (rotated with the transform) or world space."); - public string[] spaces = {"Local", "World"}; - } - static Texts s_Texts; - - public ForceModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "ForceModule", displayName) - { - m_ToolTip = "Controls the force of each particle during its lifetime."; - } - - protected override void Init() - { - // Already initialized? - if (m_X != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_X = new SerializedMinMaxCurve(this, s_Texts.x, "x", kUseSignedRange); - m_Y = new SerializedMinMaxCurve(this, s_Texts.y, "y", kUseSignedRange); - m_Z = new SerializedMinMaxCurve(this, s_Texts.z, "z", kUseSignedRange); - m_RandomizePerFrame = GetProperty("randomizePerFrame"); - m_InWorldSpace = GetProperty("inWorldSpace"); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - MinMaxCurveState state = m_X.state; - GUITripleMinMaxCurve(GUIContent.none, s_Texts.x, m_X, s_Texts.y, m_Y, s_Texts.z, m_Z, m_RandomizePerFrame); - - GUIBoolAsPopup(s_Texts.space, m_InWorldSpace, s_Texts.spaces); - - using (new EditorGUI.DisabledScope((state != MinMaxCurveState.k_TwoScalars) && (state != MinMaxCurveState.k_TwoCurves))) - { - GUIToggle(s_Texts.randomizePerFrame, m_RandomizePerFrame); - } - } - - override public void UpdateCullingSupportedString(ref string text) - { - Init(); - - string failureReason = string.Empty; - if (!m_X.SupportsProcedural(ref failureReason)) - text += "\nForce over Lifetime module curve X: " + failureReason; - - failureReason = string.Empty; - if (!m_Y.SupportsProcedural(ref failureReason)) - text += "\nForce over Lifetime module curve Y: " + failureReason; - - failureReason = string.Empty; - if (!m_Z.SupportsProcedural(ref failureReason)) - text += "\nForce over Lifetime module curve Z: " + failureReason; - - if (m_RandomizePerFrame.boolValue) - text += "\nRandomize is enabled in the Force over Lifetime module."; - } - } // namespace UnityEditor -} diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InheritVelocityModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InheritVelocityModuleUI.cs deleted file mode 100644 index 2a05a8e4e6..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InheritVelocityModuleUI.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - class InheritVelocityModuleUI : ModuleUI - { - // Keep in sync with InheritVelocityModule.h - enum Modes { Initial = 0, Current = 1 }; - - SerializedProperty m_Mode; - SerializedMinMaxCurve m_Curve; - - class Texts - { - public GUIContent mode = EditorGUIUtility.TrTextContent("Mode", "Specifies whether the emitter velocity is inherited as a one-shot when a particle is born, always using the current emitter velocity, or using the emitter velocity when the particle was born."); - public GUIContent velocity = EditorGUIUtility.TrTextContent("Multiplier", "Controls the amount of emitter velocity inherited during each particle's lifetime."); - - public GUIContent[] modes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Initial"), - EditorGUIUtility.TrTextContent("Current") - }; - } - static Texts s_Texts; - - public InheritVelocityModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "InheritVelocityModule", displayName) - { - m_ToolTip = "Controls the velocity inherited from the emitter, for each particle."; - } - - protected override void Init() - { - // Already initialized? - if (m_Curve != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_Mode = GetProperty("m_Mode"); - m_Curve = new SerializedMinMaxCurve(this, GUIContent.none, "m_Curve", kUseSignedRange); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - GUIPopup(s_Texts.mode, m_Mode, s_Texts.modes); - GUIMinMaxCurve(s_Texts.velocity, m_Curve); - } - - override public void UpdateCullingSupportedString(ref string text) - { - Init(); - - string failureReason = string.Empty; - if (!m_Curve.SupportsProcedural(ref failureReason)) - text += "\nInherit Velocity module curve: " + failureReason; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs deleted file mode 100644 index 3c031ce472..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs +++ /dev/null @@ -1,312 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Linq; - -namespace UnityEditor -{ - internal class InitialModuleUI : ModuleUI - { - public SerializedProperty m_LengthInSec; - public SerializedProperty m_Looping; - public SerializedProperty m_Prewarm; - public SerializedMinMaxCurve m_StartDelay; - public SerializedProperty m_PlayOnAwake; - public SerializedProperty m_SimulationSpace; - public SerializedProperty m_CustomSimulationSpace; - public SerializedProperty m_SimulationSpeed; - public SerializedProperty m_UseUnscaledTime; - public SerializedProperty m_ScalingMode; - - public SerializedMinMaxCurve m_LifeTime; - public SerializedMinMaxCurve m_Speed; - public SerializedMinMaxGradient m_Color; - public SerializedProperty m_Size3D; - public SerializedMinMaxCurve m_SizeX; - public SerializedMinMaxCurve m_SizeY; - public SerializedMinMaxCurve m_SizeZ; - public SerializedProperty m_Rotation3D; - public SerializedMinMaxCurve m_RotationX; - public SerializedMinMaxCurve m_RotationY; - public SerializedMinMaxCurve m_RotationZ; - public SerializedProperty m_RandomizeRotationDirection; - public SerializedMinMaxCurve m_GravityModifier; - public SerializedProperty m_EmitterVelocity; - public SerializedProperty m_MaxNumParticles; - public SerializedProperty m_AutoRandomSeed; - public SerializedProperty m_RandomSeed; - public SerializedProperty m_StopAction; - - class Texts - { - public GUIContent duration = EditorGUIUtility.TrTextContent("Duration", "The length of time the Particle System is emitting particles. If the system is looping, this indicates the length of one cycle."); - public GUIContent looping = EditorGUIUtility.TrTextContent("Looping", "If true, the emission cycle will repeat after the duration."); - public GUIContent prewarm = EditorGUIUtility.TrTextContent("Prewarm", "When played a prewarmed system will be in a state as if it had emitted one loop cycle. Can only be used if the system is looping."); - public GUIContent startDelay = EditorGUIUtility.TrTextContent("Start Delay", "Delay in seconds that this Particle System will wait before emitting particles. Cannot be used together with a prewarmed looping system."); - public GUIContent maxParticles = EditorGUIUtility.TrTextContent("Max Particles", "The number of particles in the system will be limited by this number. Emission will be temporarily halted if this is reached."); - public GUIContent lifetime = EditorGUIUtility.TrTextContent("Start Lifetime", "Start lifetime in seconds, particle will die when its lifetime reaches 0."); - public GUIContent speed = EditorGUIUtility.TrTextContent("Start Speed", "The start speed of particles, applied in the starting direction."); - public GUIContent color = EditorGUIUtility.TrTextContent("Start Color", "The start color of particles."); - public GUIContent size3D = EditorGUIUtility.TrTextContent("3D Start Size", "If enabled, you can control the size separately for each axis."); - public GUIContent size = EditorGUIUtility.TrTextContent("Start Size", "The start size of particles."); - public GUIContent rotation3D = EditorGUIUtility.TrTextContent("3D Start Rotation", "If enabled, you can control the rotation separately for each axis."); - public GUIContent rotation = EditorGUIUtility.TrTextContent("Start Rotation", "The start rotation of particles in degrees."); - public GUIContent randomizeRotationDirection = EditorGUIUtility.TrTextContent("Flip Rotation", "Cause some particles to spin in the opposite direction. (Set between 0 and 1, where a higher value causes more to flip)"); - public GUIContent autoplay = EditorGUIUtility.TrTextContent("Play On Awake*", "If enabled, the system will start playing automatically. Note that this setting is shared between all Particle Systems in the current particle effect."); - public GUIContent gravity = EditorGUIUtility.TrTextContent("Gravity Modifier", "Scales the gravity defined in Physics Manager"); - public GUIContent scalingMode = EditorGUIUtility.TrTextContent("Scaling Mode", "Use the combined scale from our entire hierarchy, just this local particle node, or only apply scale to the shape module."); - public GUIContent simulationSpace = EditorGUIUtility.TrTextContent("Simulation Space", "Makes particle positions simulate in world, local or custom space. In local space they stay relative to their own Transform, and in custom space they are relative to the custom Transform."); - public GUIContent customSimulationSpace = EditorGUIUtility.TrTextContent("Custom Simulation Space", "Makes particle positions simulate relative to a custom Transform component."); - public GUIContent simulationSpeed = EditorGUIUtility.TrTextContent("Simulation Speed", "Scale the playback speed of the Particle System."); - public GUIContent deltaTime = EditorGUIUtility.TrTextContent("Delta Time", "Use either the Delta Time or the Unscaled Delta Time. Useful for playing effects whilst paused."); - public GUIContent autoRandomSeed = EditorGUIUtility.TrTextContent("Auto Random Seed", "Simulate differently each time the effect is played."); - public GUIContent randomSeed = EditorGUIUtility.TrTextContent("Random Seed", "Randomize the look of the Particle System. Using the same seed will make the Particle System play identically each time. After changing this value, restart the Particle System to see the changes, or check the Resimulate box."); - public GUIContent emitterVelocity = EditorGUIUtility.TrTextContent("Emitter Velocity", "When the Particle System is moving, should we use its Transform, or Rigidbody Component, to calculate its velocity?"); - public GUIContent stopAction = EditorGUIUtility.TrTextContent("Stop Action", "When the Particle System is stopped and all particles have died, should the GameObject automatically disable/destroy itself?"); - public GUIContent x = EditorGUIUtility.TextContent("X"); - public GUIContent y = EditorGUIUtility.TextContent("Y"); - public GUIContent z = EditorGUIUtility.TextContent("Z"); - - public GUIContent[] simulationSpaces = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Local"), - EditorGUIUtility.TrTextContent("World"), - EditorGUIUtility.TrTextContent("Custom") - }; - - public GUIContent[] scalingModes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Hierarchy"), - EditorGUIUtility.TrTextContent("Local"), - EditorGUIUtility.TrTextContent("Shape") - }; - - public GUIContent[] stopActions = new GUIContent[] - { - EditorGUIUtility.TrTextContent("None"), - EditorGUIUtility.TrTextContent("Disable"), - EditorGUIUtility.TrTextContent("Destroy"), - EditorGUIUtility.TrTextContent("Callback") - }; - } - private static Texts s_Texts; - - public InitialModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "InitialModule", displayName, VisibilityState.VisibleAndFoldedOut) - { - Init(); // Should always be initialized since it is used by other modules (see ShapeModule) - } - - public override bool DrawHeader(Rect rect, GUIContent label) - { - label = EditorGUI.BeginProperty(rect, label, m_ModuleRootProperty); - var toggleState = GUI.Toggle(rect, foldout, label, ParticleSystemStyles.Get().emitterHeaderStyle); - EditorGUI.EndProperty(); - return toggleState; - } - - public override float GetXAxisScalar() - { - return m_ParticleSystemUI.GetEmitterDuration(); - } - - protected override void Init() - { - // Already initialized? - if (m_LengthInSec != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - // general emitter state - m_LengthInSec = GetProperty0("lengthInSec"); - m_Looping = GetProperty0("looping"); - m_Prewarm = GetProperty0("prewarm"); - m_StartDelay = new SerializedMinMaxCurve(this, s_Texts.startDelay, "startDelay", false, true); - m_StartDelay.m_AllowCurves = false; - m_PlayOnAwake = GetProperty0("playOnAwake"); - m_SimulationSpace = GetProperty0("moveWithTransform"); - m_CustomSimulationSpace = GetProperty0("moveWithCustomTransform"); - m_SimulationSpeed = GetProperty0("simulationSpeed"); - m_UseUnscaledTime = GetProperty0("useUnscaledTime"); - m_ScalingMode = GetProperty0("scalingMode"); - m_EmitterVelocity = GetProperty0("useRigidbodyForVelocity"); - m_AutoRandomSeed = GetProperty0("autoRandomSeed"); - m_RandomSeed = GetProperty0("randomSeed"); - m_StopAction = GetProperty0("stopAction"); - - // module properties - m_LifeTime = new SerializedMinMaxCurve(this, s_Texts.lifetime, "startLifetime"); - m_Speed = new SerializedMinMaxCurve(this, s_Texts.speed, "startSpeed", kUseSignedRange); - m_Color = new SerializedMinMaxGradient(this, "startColor"); - m_Color.m_AllowRandomColor = true; - m_Size3D = GetProperty("size3D"); - m_SizeX = new SerializedMinMaxCurve(this, s_Texts.x, "startSize"); - m_SizeY = new SerializedMinMaxCurve(this, s_Texts.y, "startSizeY", false, false, m_Size3D.boolValue); - m_SizeZ = new SerializedMinMaxCurve(this, s_Texts.z, "startSizeZ", false, false, m_Size3D.boolValue); - m_Rotation3D = GetProperty("rotation3D"); - m_RotationX = new SerializedMinMaxCurve(this, s_Texts.x, "startRotationX", kUseSignedRange, false, m_Rotation3D.boolValue); - m_RotationY = new SerializedMinMaxCurve(this, s_Texts.y, "startRotationY", kUseSignedRange, false, m_Rotation3D.boolValue); - m_RotationZ = new SerializedMinMaxCurve(this, s_Texts.z, "startRotation", kUseSignedRange); - m_RotationX.m_RemapValue = Mathf.Rad2Deg; - m_RotationY.m_RemapValue = Mathf.Rad2Deg; - m_RotationZ.m_RemapValue = Mathf.Rad2Deg; - m_RotationX.m_DefaultCurveScalar = Mathf.PI; - m_RotationY.m_DefaultCurveScalar = Mathf.PI; - m_RotationZ.m_DefaultCurveScalar = Mathf.PI; - m_RandomizeRotationDirection = GetProperty("randomizeRotationDirection"); - m_GravityModifier = new SerializedMinMaxCurve(this, s_Texts.gravity, "gravityModifier", kUseSignedRange); - m_MaxNumParticles = GetProperty("maxNumParticles"); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - GUIFloat(s_Texts.duration, m_LengthInSec, "f2"); - - EditorGUI.BeginChangeCheck(); - bool looping = GUIToggle(s_Texts.looping, m_Looping); - if (EditorGUI.EndChangeCheck() && looping) - { - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - if (ps.time >= ps.main.duration) - ps.time = 0.0f; - } - } - - using (new EditorGUI.DisabledScope(!m_Looping.boolValue)) - { - GUIToggle(s_Texts.prewarm, m_Prewarm); - } - - using (new EditorGUI.DisabledScope(m_Prewarm.boolValue && m_Looping.boolValue)) - { - GUIMinMaxCurve(s_Texts.startDelay, m_StartDelay); - } - - GUIMinMaxCurve(s_Texts.lifetime, m_LifeTime); - GUIMinMaxCurve(s_Texts.speed, m_Speed); - - // Size - EditorGUI.BeginChangeCheck(); - bool size3D = GUIToggle(s_Texts.size3D, m_Size3D); - if (EditorGUI.EndChangeCheck()) - { - // Remove old curves from curve editor - if (!size3D) - { - m_SizeY.RemoveCurveFromEditor(); - m_SizeZ.RemoveCurveFromEditor(); - } - } - - // Keep states in sync - if (!m_SizeX.stateHasMultipleDifferentValues) - { - m_SizeZ.SetMinMaxState(m_SizeX.state, size3D); - m_SizeY.SetMinMaxState(m_SizeX.state, size3D); - } - - if (size3D) - { - m_SizeX.m_DisplayName = s_Texts.x; - GUITripleMinMaxCurve(GUIContent.none, s_Texts.x, m_SizeX, s_Texts.y, m_SizeY, s_Texts.z, m_SizeZ, null); - } - else - { - m_SizeX.m_DisplayName = s_Texts.size; - GUIMinMaxCurve(s_Texts.size, m_SizeX); - } - - // Rotation - EditorGUI.BeginChangeCheck(); - bool rotation3D = GUIToggle(s_Texts.rotation3D, m_Rotation3D); - if (EditorGUI.EndChangeCheck()) - { - // Remove old curves from curve editor - if (!rotation3D) - { - m_RotationX.RemoveCurveFromEditor(); - m_RotationY.RemoveCurveFromEditor(); - } - } - - // Keep states in sync - if (!m_RotationZ.stateHasMultipleDifferentValues) - { - m_RotationX.SetMinMaxState(m_RotationZ.state, rotation3D); - m_RotationY.SetMinMaxState(m_RotationZ.state, rotation3D); - } - - if (rotation3D) - { - m_RotationZ.m_DisplayName = s_Texts.z; - GUITripleMinMaxCurve(GUIContent.none, s_Texts.x, m_RotationX, s_Texts.y, m_RotationY, s_Texts.z, m_RotationZ, null); - } - else - { - m_RotationZ.m_DisplayName = s_Texts.rotation; - GUIMinMaxCurve(s_Texts.rotation, m_RotationZ); - } - - GUIFloat(s_Texts.randomizeRotationDirection, m_RandomizeRotationDirection); - GUIMinMaxGradient(s_Texts.color, m_Color, false); - - GUIMinMaxCurve(s_Texts.gravity, m_GravityModifier); - int space = GUIPopup(s_Texts.simulationSpace, m_SimulationSpace, s_Texts.simulationSpaces); - if (space == 2 && m_CustomSimulationSpace != null) - GUIObject(s_Texts.customSimulationSpace, m_CustomSimulationSpace); - GUIFloat(s_Texts.simulationSpeed, m_SimulationSpeed); - GUIBoolAsPopup(s_Texts.deltaTime, m_UseUnscaledTime, new string[] { "Scaled", "Unscaled" }); - - bool anyNonMesh = m_ParticleSystemUI.m_ParticleSystems.FirstOrDefault(o => !o.shape.enabled || (o.shape.shapeType != ParticleSystemShapeType.SkinnedMeshRenderer && o.shape.shapeType != ParticleSystemShapeType.MeshRenderer)) != null; - if (anyNonMesh) - GUIPopup(s_Texts.scalingMode, m_ScalingMode, s_Texts.scalingModes); - - bool oldPlayOnAwake = m_PlayOnAwake.boolValue; - bool newPlayOnAwake = GUIToggle(s_Texts.autoplay, m_PlayOnAwake); - if (oldPlayOnAwake != newPlayOnAwake) - m_ParticleSystemUI.m_ParticleEffectUI.PlayOnAwakeChanged(newPlayOnAwake); - - GUIBoolAsPopup(s_Texts.emitterVelocity, m_EmitterVelocity, new string[] { "Transform", "Rigidbody" }); - - GUIInt(s_Texts.maxParticles, m_MaxNumParticles); - - bool autoRandomSeed = GUIToggle(s_Texts.autoRandomSeed, m_AutoRandomSeed); - if (!autoRandomSeed) - { - bool isInspectorView = m_ParticleSystemUI.m_ParticleEffectUI.m_Owner is ParticleSystemInspector; - if (isInspectorView) - { - GUILayout.BeginHorizontal(); - GUIInt(s_Texts.randomSeed, m_RandomSeed); - if (!m_ParticleSystemUI.multiEdit && GUILayout.Button("Reseed", EditorStyles.miniButton, GUILayout.Width(60))) - m_RandomSeed.intValue = (int)m_ParticleSystemUI.m_ParticleSystems[0].GenerateRandomSeed(); - GUILayout.EndHorizontal(); - } - else - { - GUIInt(s_Texts.randomSeed, m_RandomSeed); - if (!m_ParticleSystemUI.multiEdit && GUILayout.Button("Reseed", EditorStyles.miniButton)) - m_RandomSeed.intValue = (int)m_ParticleSystemUI.m_ParticleSystems[0].GenerateRandomSeed(); - } - } - - GUIPopup(s_Texts.stopAction, m_StopAction, s_Texts.stopActions); - } - - override public void UpdateCullingSupportedString(ref string text) - { - if (m_SimulationSpace.intValue != 0) - text += "\nLocal space simulation is not being used."; - - if (m_GravityModifier.state != MinMaxCurveState.k_Scalar) - text += "\nGravity modifier is not constant."; - - if (m_StopAction.intValue != 0) - text += "\nStop Action is being used."; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/LightsModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/LightsModuleUI.cs deleted file mode 100644 index 60920208d0..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/LightsModuleUI.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class LightsModuleUI : ModuleUI - { - class Texts - { - public GUIContent ratio = EditorGUIUtility.TrTextContent("Ratio", "Amount of particles that have a light source attached to them."); - public GUIContent randomDistribution = EditorGUIUtility.TrTextContent("Random Distribution", "Emit lights randomly, or at regular intervals."); - public GUIContent light = EditorGUIUtility.TrTextContent("Light", "Light prefab to be used for spawning particle lights."); - public GUIContent color = EditorGUIUtility.TrTextContent("Use Particle Color", "Check the option to multiply the particle color by the light color. Otherwise, only the color of the light is used."); - public GUIContent range = EditorGUIUtility.TrTextContent("Size Affects Range", "Multiply the range of the light with the size of the particle."); - public GUIContent intensity = EditorGUIUtility.TrTextContent("Alpha Affects Intensity", "Multiply the intensity of the light with the alpha of the particle."); - public GUIContent rangeCurve = EditorGUIUtility.TrTextContent("Range Multiplier", "Apply a custom multiplier to the range of the lights."); - public GUIContent intensityCurve = EditorGUIUtility.TrTextContent("Intensity Multiplier", "Apply a custom multiplier to the intensity of the lights."); - public GUIContent maxLights = EditorGUIUtility.TrTextContent("Maximum Lights", "Limit the amount of lights the system can create. This module makes it very easy to create lots of lights, which can hurt performance."); - } - static Texts s_Texts; - - SerializedProperty m_Ratio; - SerializedProperty m_RandomDistribution; - SerializedProperty m_Light; - SerializedProperty m_UseParticleColor; - SerializedProperty m_SizeAffectsRange; - SerializedProperty m_AlphaAffectsIntensity; - SerializedMinMaxCurve m_Range; - SerializedMinMaxCurve m_Intensity; - SerializedProperty m_MaxLights; - - public LightsModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "LightsModule", displayName) - { - m_ToolTip = "Controls light sources attached to particles."; - } - - protected override void Init() - { - // Already initialized? - if (m_Ratio != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_Ratio = GetProperty("ratio"); - m_RandomDistribution = GetProperty("randomDistribution"); - m_Light = GetProperty("light"); - m_UseParticleColor = GetProperty("color"); - m_SizeAffectsRange = GetProperty("range"); - m_AlphaAffectsIntensity = GetProperty("intensity"); - m_MaxLights = GetProperty("maxLights"); - - m_Range = new SerializedMinMaxCurve(this, s_Texts.rangeCurve, "rangeCurve"); - m_Intensity = new SerializedMinMaxCurve(this, s_Texts.intensityCurve, "intensityCurve"); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - GUIObject(s_Texts.light, m_Light); - GUIFloat(s_Texts.ratio, m_Ratio); - GUIToggle(s_Texts.randomDistribution, m_RandomDistribution); - GUIToggle(s_Texts.color, m_UseParticleColor); - GUIToggle(s_Texts.range, m_SizeAffectsRange); - GUIToggle(s_Texts.intensity, m_AlphaAffectsIntensity); - GUIMinMaxCurve(s_Texts.rangeCurve, m_Range); - GUIMinMaxCurve(s_Texts.intensityCurve, m_Intensity); - GUIInt(s_Texts.maxLights, m_MaxLights); - - if (m_Light.objectReferenceValue) - { - Light light = (Light)m_Light.objectReferenceValue; - if (light.type != LightType.Point && light.type != LightType.Spot) - { - GUIContent warning = EditorGUIUtility.TrTextContent("Only point and spot lights are supported on particles."); - EditorGUILayout.HelpBox(warning.text, MessageType.Warning, true); - } - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ModuleUI.cs deleted file mode 100644 index 39d56275bd..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ModuleUI.cs +++ /dev/null @@ -1,225 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - - -namespace UnityEditor -{ - abstract partial class ModuleUI : SerializedModule - { - public ParticleSystemUI m_ParticleSystemUI; // owner - private string m_DisplayName; - protected string m_ToolTip = ""; - private SerializedProperty m_Enabled; - private VisibilityState m_VisibilityState; - public List m_ModuleCurves = new List(); - private List m_CurvesRemovedWhenFolded = new List(); - - public enum VisibilityState - { - NotVisible = 0, - VisibleAndFolded = 1, - VisibleAndFoldedOut = 2 - }; - - public bool visibleUI - { - get { return m_VisibilityState != VisibilityState.NotVisible; } - set { SetVisibilityState(value ? VisibilityState.VisibleAndFolded : VisibilityState.NotVisible); } - } - public bool foldout - { - get { return m_VisibilityState == VisibilityState.VisibleAndFoldedOut; } - set { SetVisibilityState(value ? VisibilityState.VisibleAndFoldedOut : VisibilityState.VisibleAndFolded); } - } - - public bool enabled - { - get - { - return m_Enabled.boolValue; - } - set - { - if (m_Enabled.boolValue != value) - { - m_Enabled.boolValue = value; - if (value) - OnModuleEnable(); - else - OnModuleDisable(); - } - } - } - - public bool enabledHasMultipleDifferentValues - { - get { return m_Enabled.hasMultipleDifferentValues; } - } - - public string displayName - { - get { return m_DisplayName; } - } - - public string toolTip - { - get { return m_ToolTip; } - } - - public bool isWindowView - { - get { return m_ParticleSystemUI.m_ParticleEffectUI.m_Owner is ParticleSystemWindow; } - } - - public ModuleUI(ParticleSystemUI owner, SerializedObject o, string name, string displayName) - : base(o, name) - { - Setup(owner, o, displayName, VisibilityState.NotVisible); - } - - public ModuleUI(ParticleSystemUI owner, SerializedObject o, string name, string displayName, VisibilityState initialVisibilityState) - : base(o, name) - { - Setup(owner, o, displayName, initialVisibilityState); - } - - private void Setup(ParticleSystemUI owner, SerializedObject o, string displayName, VisibilityState defaultVisibilityState) - { - m_ParticleSystemUI = owner; - m_DisplayName = displayName; - - if (this is RendererModuleUI) - m_Enabled = GetProperty0("m_Enabled"); - else - m_Enabled = GetProperty("enabled"); - - m_VisibilityState = VisibilityState.NotVisible; - foreach (Object obj in o.targetObjects) - { - VisibilityState state = (VisibilityState)SessionState.GetInt(GetUniqueModuleName(obj), (int)defaultVisibilityState); - m_VisibilityState = (VisibilityState)Mathf.Max((int)state, (int)m_VisibilityState); // use most visible state - } - - CheckVisibilityState(); - - if (foldout) - Init(); - } - - protected abstract void Init(); - public virtual void Validate() {} - public virtual float GetXAxisScalar() {return 1f; } - public abstract void OnInspectorGUI(InitialModuleUI initial); - public virtual void OnSceneViewGUI() {} // Like OnSceneGUI but only called once when in multi edit mode where OnSceneGUI is called for each target. - public virtual void UpdateCullingSupportedString(ref string text) {} - - protected virtual void OnModuleEnable() - { - Undo.undoRedoPerformed += UndoRedoPerformed; - Init(); // ensure initialized - } - - public virtual void UndoRedoPerformed() - { - // If the undo operation has changed the module to now be disabled then we should remove any of its curves from the curve editor. (case 861424) - if (!enabled) - OnModuleDisable(); - } - - protected virtual void OnModuleDisable() - { - Undo.undoRedoPerformed -= UndoRedoPerformed; - ParticleSystemCurveEditor psce = m_ParticleSystemUI.m_ParticleEffectUI.GetParticleSystemCurveEditor(); - foreach (SerializedProperty curveProp in m_ModuleCurves) - { - if (psce.IsAdded(curveProp)) - psce.RemoveCurve(curveProp); - } - } - - internal void CheckVisibilityState() - { - bool isRendererModule = this is RendererModuleUI; - - // Ensure disabled modules are only visible if show all modules is true. Except the renderer module, we want that - // to be shown always if the module is there which means that we have a ParticleSystemRenderer - if (!isRendererModule && !m_Enabled.boolValue && !ParticleEffectUI.GetAllModulesVisible()) - SetVisibilityState(VisibilityState.NotVisible); - - // Ensure enabled modules are visible - if (m_Enabled.boolValue && !visibleUI) - SetVisibilityState(VisibilityState.VisibleAndFolded); - } - - protected virtual void SetVisibilityState(VisibilityState newState) - { - if (newState != m_VisibilityState) - { - if (newState == VisibilityState.VisibleAndFolded) - { - // Remove curves from the curveeditor when closing modules (and put them back when folding out again) - ParticleSystemCurveEditor psce = m_ParticleSystemUI.m_ParticleEffectUI.GetParticleSystemCurveEditor(); - foreach (SerializedProperty curveProp in m_ModuleCurves) - { - if (psce.IsAdded(curveProp)) - { - m_CurvesRemovedWhenFolded.Add(curveProp); - psce.SetVisible(curveProp, false); - } - } - psce.Refresh(); - } - else if (newState == VisibilityState.VisibleAndFoldedOut) - { - ParticleSystemCurveEditor psce = m_ParticleSystemUI.m_ParticleEffectUI.GetParticleSystemCurveEditor(); - foreach (SerializedProperty curveProp in m_CurvesRemovedWhenFolded) - { - psce.SetVisible(curveProp, true); - } - m_CurvesRemovedWhenFolded.Clear(); - psce.Refresh(); - } - - m_VisibilityState = newState; - foreach (Object obj in serializedObject.targetObjects) - { - SessionState.SetInt(GetUniqueModuleName(obj), (int)m_VisibilityState); - } - - if (newState == VisibilityState.VisibleAndFoldedOut) - Init(); - } - } - - protected ParticleSystem GetParticleSystem() - { - return m_Enabled.serializedObject.targetObject as ParticleSystem; - } - - public ParticleSystemCurveEditor GetParticleSystemCurveEditor() - { - return m_ParticleSystemUI.m_ParticleEffectUI.GetParticleSystemCurveEditor(); - } - - public virtual bool DrawHeader(Rect rect, GUIContent label) - { - label = EditorGUI.BeginProperty(rect, label, m_ModuleRootProperty); - var toggleState = GUI.Toggle(rect, foldout, label, ParticleSystemStyles.Get().moduleHeaderStyle); - EditorGUI.EndProperty(); - return toggleState; - } - - public void AddToModuleCurves(SerializedProperty curveProp) - { - m_ModuleCurves.Add(curveProp); - if (!foldout) - m_CurvesRemovedWhenFolded.Add(curveProp); - } - - // See ParticleSystemGUI.cs for more ModuleUI GUI helper functions... - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ModuleUIHelpers.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ModuleUIHelpers.cs deleted file mode 100644 index 3b3cd6e896..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ModuleUIHelpers.cs +++ /dev/null @@ -1,1168 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using UnityEngine.Rendering; -using Enum = System.Enum; -using GetBoundsFunc = System.Func; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - partial class ModuleUI - { - protected static readonly bool kUseSignedRange = true; - protected static readonly Rect kUnsignedRange = new Rect(0, 0, 1, 1); // Vertical range 0...1 - protected static readonly Rect kSignedRange = new Rect(0, -1, 1, 2); // Vertical range -1...1 - protected const int kSingleLineHeight = 13; - protected const float k_minMaxToggleWidth = 13; - protected const float k_toggleWidth = 9; - protected const float kDragSpace = 20; - protected const int kPlusAddRemoveButtonWidth = 12; - protected const int kPlusAddRemoveButtonSpacing = 5; - protected const int kSpacingSubLabel = 4; - protected const int kSubLabelWidth = 10; - protected const string kFormatString = "g7"; - protected const float kReorderableListElementHeight = 16; - - // Module rulers that are fixed - static public float k_CompactFixedModuleWidth = 295f; - static public float k_SpaceBetweenModules = 5; - - public static readonly GUIStyle s_ControlRectStyle = new GUIStyle { margin = new RectOffset(0, 0, 2, 2) }; - - // Alternative to BeginProperty when dealing with properties that should be logically combined but are not parent child properties. - public class PropertyGroupScope : GUI.Scope - { - bool wasBoldFont; - - public PropertyGroupScope(params SerializedProperty[] properties) - { - wasBoldFont = EditorGUIUtility.GetBoldDefaultFont(); - - bool bold = false; - foreach (var serializedProperty in properties) - { - if (serializedProperty.serializedObject.targetObjects.Length == 1 && serializedProperty.isInstantiatedPrefab) - { - if (serializedProperty.prefabOverride) - { - bold = true; - break; - } - } - } - EditorGUIUtility.SetBoldDefaultFont(bold); - } - - protected override void CloseScope() - { - EditorGUIUtility.SetBoldDefaultFont(wasBoldFont); - } - } - - private static void Label(Rect rect, GUIContent guiContent) - { - GUI.Label(rect, guiContent, ParticleSystemStyles.Get().label); - } - - protected static Rect GetControlRect(int height, params GUILayoutOption[] layoutOptions) - { - return GUILayoutUtility.GetRect(0, height, s_ControlRectStyle, layoutOptions); - } - - protected static Rect FieldPosition(Rect totalPosition, out Rect labelPosition) - { - labelPosition = new Rect(totalPosition.x + EditorGUI.indent, totalPosition.y, EditorGUIUtility.labelWidth - EditorGUI.indent, kSingleLineHeight); - return new Rect(totalPosition.x + EditorGUIUtility.labelWidth, totalPosition.y, totalPosition.width - EditorGUIUtility.labelWidth, totalPosition.height); - } - - internal static Rect PrefixLabel(Rect totalPosition, GUIContent label) - { - if (!EditorGUI.LabelHasContent(label)) - return EditorGUI.IndentedRect(totalPosition); - - Rect labelPosition; - Rect fieldPosition = FieldPosition(totalPosition, out labelPosition); - EditorGUI.HandlePrefixLabel(totalPosition, labelPosition, label, 0, ParticleSystemStyles.Get().label); - return fieldPosition; - } - - protected static Rect SubtractPopupWidth(Rect position) - { - position.width -= 1 + k_minMaxToggleWidth; - return position; - } - - protected static Rect GetPopupRect(Rect position) - { - position.xMin = position.xMax - k_minMaxToggleWidth; - return position; - } - - protected static bool PlusButton(Rect position) - { - return GUI.Button(new Rect(position.x - 2, position.y - 2, 12, 13), GUIContent.none, "OL Plus"); - } - - protected static bool MinusButton(Rect position) - { - return GUI.Button(new Rect(position.x - 2, position.y - 2, 12, 13), GUIContent.none, "OL Minus"); - } - - private static float FloatDraggable(Rect rect, SerializedProperty floatProp, float remap, float dragWidth) - { - return FloatDraggable(rect, floatProp, remap, dragWidth, kFormatString); - } - - public static float FloatDraggable(Rect rect, float floatValue, float remap, float dragWidth, string formatString) - { - int id = EditorGUIUtility.GetControlID(1658656233, FocusType.Keyboard, rect); - - Rect dragZoneRect = rect; - dragZoneRect.width = dragWidth; - - Rect floatFieldRect = rect; - floatFieldRect.xMin += dragWidth; - - return EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, floatFieldRect, dragZoneRect, id, floatValue * remap, formatString, ParticleSystemStyles.Get().numberField, true) / remap; - } - - public static float FloatDraggable(Rect rect, SerializedProperty floatProp, float remap, float dragWidth, string formatString) - { - EditorGUI.BeginProperty(rect, GUIContent.none, floatProp); - - EditorGUI.BeginChangeCheck(); - float floatValue = FloatDraggable(rect, floatProp.floatValue, remap, dragWidth, formatString); - if (EditorGUI.EndChangeCheck()) - floatProp.floatValue = floatValue; - - EditorGUI.EndProperty(); - - return floatValue; - } - - public static Vector3 GUIVector3Field(GUIContent guiContent, SerializedProperty vecProp, params GUILayoutOption[] layoutOptions) - { - Rect r = GetControlRect(kSingleLineHeight, layoutOptions); - guiContent = EditorGUI.BeginProperty(r, guiContent, vecProp); - r = PrefixLabel(r, guiContent); - - GUIContent[] labels = { new GUIContent("X"), new GUIContent("Y"), new GUIContent("Z") }; - float elementWidth = (r.width - 2 * kSpacingSubLabel) / 3f; - r.width = elementWidth; - - SerializedProperty cur = vecProp.Copy(); - cur.Next(true); - - Vector3 vec = vecProp.vector3Value; - - for (int i = 0; i < 3; ++i) - { - EditorGUI.BeginProperty(r, GUIContent.none, cur); - Label(r, labels[i]); - EditorGUI.BeginChangeCheck(); - float newValue = FloatDraggable(r, cur.floatValue, 1.0f, 25.0f, "g5"); - if (EditorGUI.EndChangeCheck()) - cur.floatValue = newValue; - EditorGUI.EndProperty(); - cur.Next(false); - r.x += elementWidth + kSpacingSubLabel; - } - - EditorGUI.EndProperty(); - return vec; - } - - public static float GUIFloat(string label, SerializedProperty floatProp, params GUILayoutOption[] layoutOptions) - { - return GUIFloat(GUIContent.Temp(label), floatProp, layoutOptions); - } - - public static float GUIFloat(GUIContent guiContent, SerializedProperty floatProp, params GUILayoutOption[] layoutOptions) - { - return GUIFloat(guiContent, floatProp, kFormatString, layoutOptions); - } - - public static float GUIFloat(GUIContent guiContent, SerializedProperty floatProp, string formatString, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - guiContent = EditorGUI.BeginProperty(rect, guiContent, floatProp); - PrefixLabel(rect, guiContent); - float val = FloatDraggable(rect, floatProp, 1f, EditorGUIUtility.labelWidth, formatString); - EditorGUI.EndProperty(); - return val; - } - - public static float GUIFloat(GUIContent guiContent, float floatValue, string formatString, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - PrefixLabel(rect, guiContent); - return FloatDraggable(rect, floatValue, 1f, EditorGUIUtility.labelWidth, formatString); - } - - public static void GUIButtonGroup(EditMode.SceneViewEditMode[] modes, GUIContent[] guiContents, GetBoundsFunc getBoundsOfTargets, Editor caller) - { - GUILayout.BeginHorizontal(); - GUILayout.Space(EditorGUIUtility.labelWidth); - EditMode.DoInspectorToolbar(modes, guiContents, getBoundsOfTargets, caller); - GUILayout.EndHorizontal(); - } - - public static void GUISortingLayerField(GUIContent guiContent, SerializedProperty sortProperty, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - var label = EditorGUI.BeginProperty(rect, guiContent, sortProperty); - EditorGUI.SortingLayerField(rect, label, sortProperty, ParticleSystemStyles.Get().popup, ParticleSystemStyles.Get().label); - EditorGUI.EndProperty(); - } - - private static bool Toggle(Rect rect, SerializedProperty boolProp) - { - EditorGUIInternal.mixedToggleStyle = ParticleSystemStyles.Get().toggleMixed; - EditorGUI.BeginProperty(rect, GUIContent.none, boolProp); - - EditorGUI.BeginChangeCheck(); - bool newValue = EditorGUI.Toggle(rect, boolProp.boolValue, ParticleSystemStyles.Get().toggle); - if (EditorGUI.EndChangeCheck()) - boolProp.boolValue = newValue; - - EditorGUI.EndProperty(); - EditorGUIInternal.mixedToggleStyle = EditorStyles.toggleMixed; - - return newValue; - } - - public static bool GUIToggle(string label, SerializedProperty boolProp, params GUILayoutOption[] layoutOptions) - { - return GUIToggle(GUIContent.Temp(label), boolProp, layoutOptions); - } - - public static bool GUIToggle(GUIContent guiContent, SerializedProperty boolProp, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - guiContent = EditorGUI.BeginProperty(rect, guiContent, boolProp); - rect = PrefixLabel(rect, guiContent); - bool toggleValue = Toggle(rect, boolProp); - EditorGUI.EndProperty(); - return toggleValue; - } - - public static void GUILayerMask(GUIContent guiContent, SerializedProperty boolProp, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - guiContent = EditorGUI.BeginProperty(rect, guiContent, boolProp); - rect = PrefixLabel(rect, guiContent); - EditorGUI.LayerMaskField(rect, boolProp, null, ParticleSystemStyles.Get().popup); - EditorGUI.EndProperty(); - } - - public static bool GUIToggle(GUIContent guiContent, bool boolValue, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - rect = PrefixLabel(rect, guiContent); - boolValue = EditorGUI.Toggle(rect, boolValue, ParticleSystemStyles.Get().toggle); - return boolValue; - } - - public static void GUIToggleWithFloatField(string name, SerializedProperty boolProp, SerializedProperty floatProp, bool invertToggle, params GUILayoutOption[] layoutOptions) - { - GUIToggleWithFloatField(EditorGUIUtility.TempContent(name), boolProp, floatProp, invertToggle, layoutOptions); - } - - public static void GUIToggleWithFloatField(GUIContent guiContent, SerializedProperty boolProp, SerializedProperty floatProp, bool invertToggle, params GUILayoutOption[] layoutOptions) - { - Rect rect = GUILayoutUtility.GetRect(0, kSingleLineHeight, layoutOptions); - guiContent = EditorGUI.BeginProperty(rect, guiContent, boolProp); - rect = PrefixLabel(rect, guiContent); - - Rect toggleRect = rect; - toggleRect.xMax = toggleRect.x + k_toggleWidth; - bool toggleValue = Toggle(toggleRect, boolProp); - toggleValue = invertToggle ? !toggleValue : toggleValue; - - if (toggleValue) - { - float dragWidth = 25f; - Rect floatDragRect = new Rect(rect.x + EditorGUIUtility.labelWidth + k_toggleWidth, rect.y, rect.width - k_toggleWidth, rect.height); - FloatDraggable(floatDragRect, floatProp, 1f, dragWidth); - } - EditorGUI.EndProperty(); - } - - public static void GUIToggleWithIntField(string name, SerializedProperty boolProp, SerializedProperty floatProp, bool invertToggle, params GUILayoutOption[] layoutOptions) - { - GUIToggleWithIntField(EditorGUIUtility.TempContent(name), boolProp, floatProp, invertToggle, layoutOptions); - } - - public static void GUIToggleWithIntField(GUIContent guiContent, SerializedProperty boolProp, SerializedProperty intProp, bool invertToggle, params GUILayoutOption[] layoutOptions) - { - Rect lineRect = GetControlRect(kSingleLineHeight, layoutOptions); - guiContent = EditorGUI.BeginProperty(lineRect, guiContent, boolProp); - Rect labelRect = PrefixLabel(lineRect, guiContent); - - Rect toggleRect = labelRect; - toggleRect.xMax = toggleRect.x + k_toggleWidth; - bool toggleValue = Toggle(toggleRect, boolProp); - toggleValue = invertToggle ? !toggleValue : toggleValue; - - if (toggleValue) - { - float dragWidth = 25f; - Rect intDragRect = new Rect(toggleRect.xMax, lineRect.y, lineRect.width - toggleRect.xMax + k_toggleWidth, lineRect.height); - EditorGUI.BeginChangeCheck(); - int newValue = IntDraggable(intDragRect, null, intProp.intValue, dragWidth); - if (EditorGUI.EndChangeCheck()) - intProp.intValue = newValue; - } - EditorGUI.EndProperty(); - } - - public static void GUIObject(GUIContent label, SerializedProperty objectProp, params GUILayoutOption[] layoutOptions) - { - GUIObject(label, objectProp, null, layoutOptions); - } - - public static void GUIObject(GUIContent label, SerializedProperty objectProp, System.Type objType, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, objectProp); - rect = PrefixLabel(rect, label); - EditorGUI.ObjectField(rect, objectProp, objType, GUIContent.none, ParticleSystemStyles.Get().objectField); - EditorGUI.EndProperty(); - } - - public static void GUIObjectFieldAndToggle(GUIContent label, SerializedProperty objectProp, SerializedProperty boolProp, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, objectProp); - rect = PrefixLabel(rect, label); - - rect.xMax -= k_toggleWidth + 10; - EditorGUI.ObjectField(rect, objectProp, GUIContent.none); - - if (boolProp != null) - { - rect.x += rect.width + 10; - rect.width = k_toggleWidth; - Toggle(rect, boolProp); - } - - EditorGUI.EndProperty(); - } - - internal Object ParticleSystemValidator(Object[] references, System.Type objType, SerializedProperty property) - { - foreach (Object obj in references) - { - if (obj != null) - { - GameObject gameObj = obj as GameObject; - if (gameObj != null) - { - ParticleSystem s = gameObj.GetComponent(); - if (s) - { - return s; - } - } - } - } - return null; - } - - // returns the index of the button that was pressed otherwise -1 - public int GUIListOfFloatObjectToggleFields(GUIContent label, SerializedProperty[] objectProps, EditorGUI.ObjectFieldValidator validator, GUIContent buttonTooltip, bool allowCreation, params GUILayoutOption[] layoutOptions) - { - int buttonPressed = -1; - int numObjects = objectProps.Length; - Rect rect = GUILayoutUtility.GetRect(0, (kSingleLineHeight + 2) * numObjects, layoutOptions); // the +1 is that label is on it own line - rect.height = kSingleLineHeight; - - float indent = 10f; - float floatFieldWidth = 35f; - float space = 10f; - float objectFieldWidth = rect.width - indent - floatFieldWidth - space * 2 - k_toggleWidth; - - using (new PropertyGroupScope(objectProps)) - { - PrefixLabel(rect, label); - - for (int i = 0; i < numObjects; ++i) - { - SerializedProperty objectProp = objectProps[i]; - - Rect r2 = new Rect(rect.x + indent + floatFieldWidth + space, rect.y, objectFieldWidth, rect.height); - int id = EditorGUIUtility.GetControlID(1235498, FocusType.Keyboard, r2); - - EditorGUI.BeginProperty(r2, GUIContent.none, objectProp); - EditorGUI.DoObjectField(r2, r2, id, null, null, objectProp, validator, true, ParticleSystemStyles.Get().objectField); - EditorGUI.EndProperty(); - - if (objectProp.objectReferenceValue == null) - { - r2 = new Rect(rect.xMax - k_toggleWidth, rect.y + 3, k_toggleWidth, k_toggleWidth); - if (!allowCreation || GUI.Button(r2, buttonTooltip ?? GUIContent.none, ParticleSystemStyles.Get().plus)) - buttonPressed = i; - } - - rect.y += kSingleLineHeight + 2; - } - } - return buttonPressed; - } - - public static void GUIIntDraggableX2(GUIContent mainLabel, GUIContent label1, SerializedProperty intProp1, GUIContent label2, SerializedProperty intProp2, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - - using (new PropertyGroupScope(intProp1, intProp2)) - { - rect = PrefixLabel(rect, mainLabel); - } - - float room = (rect.width - kSpacingSubLabel) * 0.5f; - Rect rectProp = new Rect(rect.x, rect.y, room, rect.height); - IntDraggable(rectProp, label1, intProp1, kSubLabelWidth); - rectProp.x += room + kSpacingSubLabel; - IntDraggable(rectProp, label2, intProp2, kSubLabelWidth); - } - - public static int IntDraggable(Rect rect, GUIContent label, SerializedProperty intProp, float dragWidth) - { - EditorGUI.BeginProperty(rect, GUIContent.none, intProp); - - EditorGUI.BeginChangeCheck(); - int newValue = IntDraggable(rect, label, intProp.intValue, dragWidth); - if (EditorGUI.EndChangeCheck()) - intProp.intValue = newValue; - - EditorGUI.EndProperty(); - - return intProp.intValue; - } - - public static int GUIInt(GUIContent guiContent, SerializedProperty intProp, params GUILayoutOption[] layoutOptions) - { - Rect rect = GUILayoutUtility.GetRect(0, kSingleLineHeight, layoutOptions); - - EditorGUI.BeginProperty(rect, GUIContent.none, intProp); - PrefixLabel(rect, guiContent); - - EditorGUI.BeginChangeCheck(); - int newValue = IntDraggable(rect, null, intProp.intValue, EditorGUIUtility.labelWidth); - if (EditorGUI.EndChangeCheck()) - intProp.intValue = newValue; - - EditorGUI.EndProperty(); - - return intProp.intValue; - } - - public static int IntDraggable(Rect rect, GUIContent label, int value, float dragWidth) - { - float width = rect.width; - Rect r = rect; - r.width = width; - int id = EditorGUIUtility.GetControlID(16586232, FocusType.Keyboard, r); - - Rect dragZoneRect = r; - dragZoneRect.width = dragWidth; - if (label != null && !string.IsNullOrEmpty(label.text)) - Label(dragZoneRect, label); - - Rect intFieldRect = r; - intFieldRect.x += dragWidth; - intFieldRect.width = width - dragWidth; - - // copied - float dragSensitity = Mathf.Max(1, Mathf.Pow(Mathf.Abs((float)value), 0.5f) * .03f); - //float dragSensitity = Mathf.Clamp01(Mathf.Max(1, Mathf.Pow(Mathf.Abs((float)value), 0.5f)) * 0.03f ); - return (int)EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor, intFieldRect, dragZoneRect, id, value, EditorGUI.kIntFieldFormatString, ParticleSystemStyles.Get().numberField, true, dragSensitity); - } - - public static void GUIMinMaxRange(GUIContent label, SerializedProperty vec2Prop, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, vec2Prop); - rect = SubtractPopupWidth(rect); // There is actually no popup in this control but the layout is nicer if the fields line up. - rect = PrefixLabel(rect, label); - - float floatFieldWidth = (rect.width - kDragSpace) * 0.5f; - - SerializedProperty cur = vec2Prop.Copy(); - cur.Next(true); - - EditorGUI.BeginChangeCheck(); - - rect.width = floatFieldWidth; - rect.xMin -= kDragSpace; - FloatDraggable(rect, cur, 1f, kDragSpace, kFormatString); - cur.Next(true); - - rect.x += floatFieldWidth + kDragSpace; - FloatDraggable(rect, cur, 1f, kDragSpace, kFormatString); - cur.Next(true); - - EditorGUI.EndProperty(); - } - - public static bool GUIBoolAsPopup(GUIContent label, SerializedProperty boolProp, string[] options, params GUILayoutOption[] layoutOptions) - { - System.Diagnostics.Debug.Assert(options.Length == 2); - - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, boolProp); - rect = PrefixLabel(rect, label); - - EditorGUI.BeginChangeCheck(); - int newValue = EditorGUI.Popup(rect, null, boolProp.boolValue ? 1 : 0, EditorGUIUtility.TempContent(options), ParticleSystemStyles.Get().popup); - if (EditorGUI.EndChangeCheck()) - boolProp.boolValue = newValue > 0 ? true : false; - - EditorGUI.EndProperty(); - return newValue > 0 ? true : false; - } - - public static void GUIEnumMaskUVChannelFlags(GUIContent label, SerializedProperty enumProperty, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, enumProperty); - rect = PrefixLabel(rect, label); - EditorGUI.BeginChangeCheck(); - int enumVal = (int)(UVChannelFlags)EditorGUI.EnumFlagsField(rect, (UVChannelFlags)enumProperty.intValue, ParticleSystemStyles.Get().popup); - if (EditorGUI.EndChangeCheck()) - enumProperty.intValue = enumVal; - EditorGUI.EndProperty(); - } - - public static void GUIMask(GUIContent label, SerializedProperty intProp, string[] options, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, intProp); - rect = PrefixLabel(rect, label); - - EditorGUI.BeginChangeCheck(); - int newValue = EditorGUI.MaskField(rect, label, intProp.intValue, options, ParticleSystemStyles.Get().popup); - if (EditorGUI.EndChangeCheck()) - intProp.intValue = newValue; - - EditorGUI.EndProperty(); - } - - public static int GUIPopup(GUIContent label, SerializedProperty intProp, GUIContent[] options, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, intProp); - rect = PrefixLabel(rect, label); - - EditorGUI.BeginChangeCheck(); - int newValue = EditorGUI.Popup(rect, null, intProp.intValue, options, ParticleSystemStyles.Get().popup); - if (EditorGUI.EndChangeCheck()) - intProp.intValue = newValue; - - EditorGUI.EndProperty(); - return intProp.intValue; - } - - public static int GUIPopup(GUIContent label, int intValue, GUIContent[] options, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - rect = PrefixLabel(rect, label); - var index = EditorGUI.Popup(rect, intValue, options, ParticleSystemStyles.Get().popup); - return index; - } - - public static int GUIPopup(GUIContent label, int intValue, GUIContent[] options, SerializedProperty property, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, property); - rect = PrefixLabel(rect, label); - var index = EditorGUI.Popup(rect, intValue, options, ParticleSystemStyles.Get().popup); - EditorGUI.EndProperty(); - return index; - } - - public static Enum GUIEnumPopup(GUIContent label, Enum selected, SerializedProperty property, params GUILayoutOption[] layoutOptions) - { - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, property); - rect = PrefixLabel(rect, label); - var e = EditorGUI.EnumPopup(rect, selected, ParticleSystemStyles.Get().popup); - EditorGUI.EndProperty(); - return e; - } - - private static Color GetColor(SerializedMinMaxCurve mmCurve) - { - return mmCurve.m_Module.m_ParticleSystemUI.m_ParticleEffectUI.GetParticleSystemCurveEditor().GetCurveColor(mmCurve.maxCurve); - } - - // Should return true to use the mousedown event - public delegate bool CurveFieldMouseDownCallback(int button, Rect drawRect, Rect curveRanges); - - // returns buttonID if clicked otherwise -1 - private static void GUICurveField(Rect position, SerializedProperty maxCurve, SerializedProperty minCurve, Color color, Rect ranges, CurveFieldMouseDownCallback mouseDownCallback) - { - int id = EditorGUIUtility.GetControlID(1321321231, FocusType.Keyboard, position); - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Repaint: - { - Rect position2 = position; - if (minCurve == null) - { - EditorGUIUtility.DrawCurveSwatch(position2, null, maxCurve, color, EditorGUI.kCurveBGColor, ranges); - } - else - { - EditorGUIUtility.DrawRegionSwatch(position2, maxCurve, minCurve, color, EditorGUI.kCurveBGColor, ranges); - } - EditorStyles.colorPickerBox.Draw(position2, GUIContent.none, id, false); - } - break; - case EventType.ValidateCommand: - if (evt.commandName == EventCommandNames.UndoRedoPerformed) - AnimationCurvePreviewCache.ClearCache(); - break; - case EventType.MouseDown: - if (position.Contains(evt.mousePosition)) - { - if (mouseDownCallback != null && mouseDownCallback(evt.button, position, ranges)) - evt.Use(); - } - break; - } - } - - public static void GUIMinMaxCurve(string label, SerializedMinMaxCurve mmCurve, params GUILayoutOption[] layoutOptions) - { - GUIMinMaxCurve(GUIContent.Temp(label), mmCurve, layoutOptions); - } - - public static void GUIMinMaxCurve(GUIContent label, SerializedMinMaxCurve mmCurve, params GUILayoutOption[] layoutOptions) - { - GUIMinMaxCurve(label, mmCurve, null, layoutOptions); - } - - public static void GUIMinMaxCurve(SerializedProperty editableLabel, SerializedMinMaxCurve mmCurve, params GUILayoutOption[] layoutOptions) - { - GUIMinMaxCurve(null, mmCurve, editableLabel, layoutOptions); - } - - internal static void GUIMinMaxCurve(GUIContent label, SerializedMinMaxCurve mmCurve, SerializedProperty editableLabel, params GUILayoutOption[] layoutOptions) - { - bool mixedState = mmCurve.stateHasMultipleDifferentValues; - - Rect rect = GetControlRect(kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, mmCurve.rootProperty); - Rect popupRect = GetPopupRect(rect); - rect = SubtractPopupWidth(rect); - Rect controlRect; - - if (editableLabel != null) - { - Rect labelPosition; - controlRect = FieldPosition(rect, out labelPosition); - labelPosition.width -= kSpacingSubLabel; - - // Draw with the minimum width so we don't lose the draggable functionality to the left of the float field - float textWidth = ParticleSystemStyles.Get().editableLabel.CalcSize(GUIContent.Temp(editableLabel.stringValue)).x; - labelPosition.width = Mathf.Min(labelPosition.width, textWidth + kSpacingSubLabel); - - EditorGUI.BeginProperty(labelPosition, GUIContent.none, editableLabel); - - EditorGUI.BeginChangeCheck(); - string newString = EditorGUI.TextFieldInternal(GUIUtility.GetControlID(FocusType.Passive, labelPosition), labelPosition, editableLabel.stringValue, ParticleSystemStyles.Get().editableLabel); - if (EditorGUI.EndChangeCheck()) - editableLabel.stringValue = newString; - - EditorGUI.EndProperty(); - } - else - { - controlRect = PrefixLabel(rect, label); - } - - if (mixedState) - { - Label(controlRect, GUIContent.Temp("-")); - } - else - { - MinMaxCurveState state = mmCurve.state; - - // Scalar field - if (state == MinMaxCurveState.k_Scalar) - { - EditorGUI.BeginChangeCheck(); - float newValue = FloatDraggable(rect, mmCurve.scalar, mmCurve.m_RemapValue, EditorGUIUtility.labelWidth); - if (EditorGUI.EndChangeCheck() && !mmCurve.signedRange) - mmCurve.scalar.floatValue = Mathf.Max(newValue, 0f); - } - else if (state == MinMaxCurveState.k_TwoScalars) - { - Rect halfRect = controlRect; - halfRect.width = (controlRect.width - kDragSpace) * 0.5f; - - Rect halfRectWithDragger = halfRect; - halfRectWithDragger.xMin -= kDragSpace; - - EditorGUI.BeginChangeCheck(); - float newMinValue = FloatDraggable(halfRectWithDragger, mmCurve.minScalar, mmCurve.m_RemapValue, kDragSpace, "g5"); - if (EditorGUI.EndChangeCheck() && !mmCurve.signedRange) - mmCurve.minScalar.floatValue = Mathf.Max(newMinValue, 0f); - - halfRectWithDragger.x += halfRect.width + kDragSpace; - - EditorGUI.BeginChangeCheck(); - float newMaxValue = FloatDraggable(halfRectWithDragger, mmCurve.scalar, mmCurve.m_RemapValue, kDragSpace, "g5"); - if (EditorGUI.EndChangeCheck() && !mmCurve.signedRange) - mmCurve.scalar.floatValue = Mathf.Max(newMaxValue, 0f); - } - else - { - // Curve field - Rect previewRange = mmCurve.signedRange ? kSignedRange : kUnsignedRange; - SerializedProperty minCurve = (state == MinMaxCurveState.k_TwoCurves) ? mmCurve.minCurve : null; - GUICurveField(controlRect, mmCurve.maxCurve, minCurve, GetColor(mmCurve), previewRange, mmCurve.OnCurveAreaMouseDown); - } - } - - // PopUp minmaxState menu - GUIMMCurveStateList(popupRect, mmCurve); - EditorGUI.EndProperty(); - } - - public static Rect GUIMinMaxCurveInline(Rect rect, SerializedMinMaxCurve mmCurve, float dragWidth) - { - EditorGUI.BeginProperty(rect, GUIContent.none, mmCurve.rootProperty); - bool mixedState = mmCurve.stateHasMultipleDifferentValues; - - if (mixedState) - { - Label(rect, GUIContent.Temp("-")); - } - else - { - MinMaxCurveState state = mmCurve.state; - - // Scalar field - if (state == MinMaxCurveState.k_Scalar) - { - EditorGUI.BeginChangeCheck(); - float newValue = FloatDraggable(rect, mmCurve.scalar, mmCurve.m_RemapValue, dragWidth, "n0"); - if (EditorGUI.EndChangeCheck() && !mmCurve.signedRange) - mmCurve.scalar.floatValue = Mathf.Max(newValue, 0f); - } - else if (state == MinMaxCurveState.k_TwoScalars) - { - Rect halfRect = rect; - halfRect.width = (rect.width * 0.5f); - - Rect halfRectWithDragger = halfRect; - - EditorGUI.BeginChangeCheck(); - float newMinValue = FloatDraggable(halfRectWithDragger, mmCurve.minScalar, mmCurve.m_RemapValue, dragWidth, "n0"); - if (EditorGUI.EndChangeCheck() && !mmCurve.signedRange) - mmCurve.minScalar.floatValue = Mathf.Max(newMinValue, 0f); - - halfRectWithDragger.x += halfRect.width; - - EditorGUI.BeginChangeCheck(); - float newMaxValue = FloatDraggable(halfRectWithDragger, mmCurve.scalar, mmCurve.m_RemapValue, dragWidth, "n0"); - if (EditorGUI.EndChangeCheck() && !mmCurve.signedRange) - mmCurve.scalar.floatValue = Mathf.Max(newMaxValue, 0f); - } - else - { - // Curve field - Rect previewRange = mmCurve.signedRange ? kSignedRange : kUnsignedRange; - SerializedProperty minCurve = (state == MinMaxCurveState.k_TwoCurves) ? mmCurve.minCurve : null; - GUICurveField(rect, mmCurve.maxCurve, minCurve, GetColor(mmCurve), previewRange, mmCurve.OnCurveAreaMouseDown); - } - } - - // PopUp minmaxState menu - rect.width += k_minMaxToggleWidth; - Rect popupRect = GetPopupRect(rect); - GUIMMCurveStateList(popupRect, mmCurve); - EditorGUI.EndProperty(); - - return rect; - } - - public void GUIMinMaxGradient(GUIContent label, SerializedMinMaxGradient minMaxGradient, bool hdr, params GUILayoutOption[] layoutOptions) - { - GUIMinMaxGradient(label, minMaxGradient, null, hdr, layoutOptions); - } - - public void GUIMinMaxGradient(SerializedProperty editableLabel, SerializedMinMaxGradient minMaxGradient, bool hdr, params GUILayoutOption[] layoutOptions) - { - GUIMinMaxGradient(null, minMaxGradient, editableLabel, hdr, layoutOptions); - } - - internal void GUIMinMaxGradient(GUIContent label, SerializedMinMaxGradient minMaxGradient, SerializedProperty editableLabel, bool hdr, params GUILayoutOption[] layoutOptions) - { - bool mixedState = minMaxGradient.stateHasMultipleDifferentValues; - - MinMaxGradientState state = minMaxGradient.state; - bool useRandomness = !mixedState && ((state == MinMaxGradientState.k_RandomBetweenTwoColors) || (state == MinMaxGradientState.k_RandomBetweenTwoGradients)); - - Rect rect = GUILayoutUtility.GetRect(0, useRandomness ? 2 * kSingleLineHeight : kSingleLineHeight, layoutOptions); - label = EditorGUI.BeginProperty(rect, label, minMaxGradient.m_RootProperty); - Rect popupRect = GetPopupRect(rect); - rect = SubtractPopupWidth(rect); - - Rect gradientRect; - if (editableLabel != null) - { - Rect labelPosition; - gradientRect = FieldPosition(rect, out labelPosition); - labelPosition.width -= kSpacingSubLabel; - - EditorGUI.BeginProperty(labelPosition, GUIContent.none, editableLabel); - - EditorGUI.BeginChangeCheck(); - string newString = EditorGUI.TextFieldInternal(GUIUtility.GetControlID(FocusType.Passive, labelPosition), labelPosition, editableLabel.stringValue, ParticleSystemStyles.Get().editableLabel); - if (EditorGUI.EndChangeCheck()) - editableLabel.stringValue = newString; - - EditorGUI.EndProperty(); - } - else - { - gradientRect = PrefixLabel(rect, label); - } - - gradientRect.height = kSingleLineHeight; - - if (mixedState) - { - Label(gradientRect, GUIContent.Temp("-")); - } - else - { - switch (state) - { - case MinMaxGradientState.k_Color: - GUIColor(gradientRect, minMaxGradient.m_MaxColor, hdr); - break; - - case MinMaxGradientState.k_RandomBetweenTwoColors: - GUIColor(gradientRect, minMaxGradient.m_MaxColor, hdr); - - gradientRect.y += gradientRect.height; - - GUIColor(gradientRect, minMaxGradient.m_MinColor, hdr); - break; - - case MinMaxGradientState.k_Gradient: - case MinMaxGradientState.k_RandomColor: - EditorGUI.BeginProperty(gradientRect, GUIContent.none, minMaxGradient.m_MaxGradient); - EditorGUI.GradientField(gradientRect, minMaxGradient.m_MaxGradient, hdr); - EditorGUI.EndProperty(); - break; - - case MinMaxGradientState.k_RandomBetweenTwoGradients: - EditorGUI.BeginProperty(gradientRect, GUIContent.none, minMaxGradient.m_MaxGradient); - EditorGUI.GradientField(gradientRect, minMaxGradient.m_MaxGradient, hdr); - EditorGUI.EndProperty(); - - gradientRect.y += gradientRect.height; - - EditorGUI.BeginProperty(gradientRect, GUIContent.none, minMaxGradient.m_MinGradient); - EditorGUI.GradientField(gradientRect, minMaxGradient.m_MinGradient, hdr); - EditorGUI.EndProperty(); - break; - } - } - GUIMMGradientPopUp(popupRect, minMaxGradient); - EditorGUI.EndProperty(); - } - - private static void GUIColor(Rect rect, SerializedProperty colorProp) - { - GUIColor(rect, colorProp, false); - } - - private static void GUIColor(Rect rect, SerializedProperty colorProp, bool hdr) - { - EditorGUI.BeginProperty(rect, GUIContent.none, colorProp); - EditorGUI.BeginChangeCheck(); - Color newValue = EditorGUI.ColorField(rect, GUIContent.none, colorProp.colorValue, false, true, hdr); - if (EditorGUI.EndChangeCheck()) - colorProp.colorValue = newValue; - EditorGUI.EndProperty(); - } - - public void GUITripleMinMaxCurve(GUIContent label, GUIContent x, SerializedMinMaxCurve xCurve, GUIContent y, SerializedMinMaxCurve yCurve, GUIContent z, SerializedMinMaxCurve zCurve, SerializedProperty randomizePerFrame, params GUILayoutOption[] layoutOptions) - { - using (new PropertyGroupScope(xCurve.rootProperty, yCurve.rootProperty, zCurve.rootProperty)) - { - bool mixedState = xCurve.stateHasMultipleDifferentValues; - - MinMaxCurveState state = xCurve.state; // just use xCurve state for all - bool showMainLabel = label != GUIContent.none; - int numLines = (showMainLabel) ? 2 : 1; - if (state == MinMaxCurveState.k_TwoScalars) - numLines++; - Rect rect = GetControlRect(kSingleLineHeight * numLines, layoutOptions); - Rect popupRect = GetPopupRect(rect); - rect = SubtractPopupWidth(rect); - Rect r = rect; - - float labelBorder = 2; - float[] labelWidth = new float[3] - { - ParticleSystemStyles.Get().label.CalcSize(GUIContent.Temp(x.text)).x + labelBorder, - ParticleSystemStyles.Get().label.CalcSize(GUIContent.Temp(y.text)).x + labelBorder, - ParticleSystemStyles.Get().label.CalcSize(GUIContent.Temp(z.text)).x + labelBorder - }; - - float fieldWidth = (rect.width - labelWidth[0] - labelWidth[1] - labelWidth[2]) / 3.0f; - - if (numLines > 1) - { - r.height = kSingleLineHeight; - } - if (showMainLabel) - { - PrefixLabel(rect, label); - r.y += r.height; - } - - // Scalar fields - GUIContent[] labels = { x, y, z }; - SerializedMinMaxCurve[] curves = { xCurve, yCurve, zCurve }; - - if (mixedState) - { - r.width = fieldWidth + labelWidth[0]; - Label(r, GUIContent.Temp("-")); - } - else - { - if (state == MinMaxCurveState.k_Scalar) - { - for (int i = 0; i < curves.Length; ++i) - { - r.width = fieldWidth + labelWidth[i] - labelBorder * 2; - - EditorGUI.BeginProperty(r, labels[i], curves[i].scalar); - Label(r, labels[i]); - EditorGUI.BeginChangeCheck(); - float newValue = FloatDraggable(r, curves[i].scalar, curves[i].m_RemapValue, labelWidth[i]); - if (EditorGUI.EndChangeCheck() && !curves[i].signedRange) - curves[i].scalar.floatValue = Mathf.Max(newValue, 0f); - - r.x += fieldWidth + labelWidth[i] + labelBorder; - EditorGUI.EndProperty(); - } - } - else if (state == MinMaxCurveState.k_TwoScalars) - { - for (int i = 0; i < curves.Length; ++i) - { - r.width = fieldWidth + labelWidth[i] - labelBorder * 2; - - Label(r, labels[i]); - - float minConstant = curves[i].minConstant; - float maxConstant = curves[i].maxConstant; - - EditorGUI.BeginChangeCheck(); - maxConstant = FloatDraggable(r, maxConstant, curves[i].m_RemapValue, labelWidth[i], "g5"); - if (EditorGUI.EndChangeCheck()) - { - curves[i].maxConstant = maxConstant; - } - - r.y += kSingleLineHeight; - - EditorGUI.BeginChangeCheck(); - minConstant = FloatDraggable(r, minConstant, curves[i].m_RemapValue, labelWidth[i], "g5"); - if (EditorGUI.EndChangeCheck()) - { - curves[i].minConstant = minConstant; - } - - r.x += fieldWidth + labelWidth[i] + labelBorder; - r.y -= kSingleLineHeight; - } - } - else - { - Rect previewRange = xCurve.signedRange ? kSignedRange : kUnsignedRange; - for (int i = 0; i < curves.Length; ++i) - { - r.width = fieldWidth + labelWidth[i] - labelBorder * 2; - SerializedProperty minCurve = (state == MinMaxCurveState.k_TwoCurves) ? curves[i].minCurve : null; - - using (minCurve == null ? new EditorGUI.PropertyScope(r, labels[i], curves[i].maxCurve) : (GUI.Scope) new PropertyGroupScope(curves[i].maxCurve, minCurve)) - { - Label(r, labels[i]); - Rect r2 = r; - r2.xMin += labelWidth[i]; - - GUICurveField(r2, curves[i].maxCurve, minCurve, GetColor(curves[i]), previewRange, curves[i].OnCurveAreaMouseDown); - r.x += fieldWidth + labelWidth[i] + labelBorder; - } - } - } - } - - // Toggle minmax - GUIMMCurveStateList(popupRect, curves); - } - } - - private class CurveStateCallbackData - { - public CurveStateCallbackData(MinMaxCurveState state, SerializedMinMaxCurve[] curves) - { - minMaxCurves = curves; - selectedState = state; - } - - public SerializedMinMaxCurve[] minMaxCurves; - public MinMaxCurveState selectedState; - } - - static void SelectMinMaxCurveStateCallback(object obj) - { - CurveStateCallbackData data = (CurveStateCallbackData)obj; - foreach (SerializedMinMaxCurve curve in data.minMaxCurves) - { - curve.state = data.selectedState; - } - } - - public static void GUIMMCurveStateList(Rect rect, SerializedMinMaxCurve minMaxCurves) - { - SerializedMinMaxCurve[] curve = { minMaxCurves }; - GUIMMCurveStateList(rect, curve); - } - - public static void GUIMMCurveStateList(Rect rect, SerializedMinMaxCurve[] minMaxCurves) - { - if (EditorGUI.DropdownButton(rect, GUIContent.none, FocusType.Passive, ParticleSystemStyles.Get().minMaxCurveStateDropDown)) - { - if (minMaxCurves.Length == 0) - return; - - GUIContent[] texts = { EditorGUIUtility.TrTextContent("Constant"), - EditorGUIUtility.TrTextContent("Curve"), - EditorGUIUtility.TrTextContent("Random Between Two Constants"), - EditorGUIUtility.TrTextContent("Random Between Two Curves") }; - MinMaxCurveState[] states = { MinMaxCurveState.k_Scalar, - MinMaxCurveState.k_Curve, - MinMaxCurveState.k_TwoScalars, - MinMaxCurveState.k_TwoCurves }; - bool[] allowState = { minMaxCurves[0].m_AllowConstant, - minMaxCurves[0].m_AllowCurves, - minMaxCurves[0].m_AllowRandom, - minMaxCurves[0].m_AllowRandom && minMaxCurves[0].m_AllowCurves }; - - bool allowHighlight = !minMaxCurves[0].stateHasMultipleDifferentValues; - GenericMenu menu = new GenericMenu(); - for (int i = 0; i < texts.Length; ++i) - { - if (allowState[i]) - menu.AddItem(texts[i], allowHighlight && (minMaxCurves[0].state == states[i]), SelectMinMaxCurveStateCallback, new CurveStateCallbackData(states[i], minMaxCurves)); - } - menu.DropDown(rect); - Event.current.Use(); - } - } - - private class GradientCallbackData - { - public GradientCallbackData(MinMaxGradientState state, SerializedMinMaxGradient p) - { - gradientProp = p; - selectedState = state; - } - - public SerializedMinMaxGradient gradientProp; - public MinMaxGradientState selectedState; - } - - static void SelectMinMaxGradientStateCallback(object obj) - { - GradientCallbackData data = (GradientCallbackData)obj; - data.gradientProp.state = data.selectedState; - } - - public static void GUIMMGradientPopUp(Rect rect, SerializedMinMaxGradient gradientProp) - { - if (EditorGUI.DropdownButton(rect, GUIContent.none, FocusType.Passive, ParticleSystemStyles.Get().minMaxCurveStateDropDown)) - { - GUIContent[] texts = { EditorGUIUtility.TrTextContent("Color"), - EditorGUIUtility.TrTextContent("Gradient"), - EditorGUIUtility.TrTextContent("Random Between Two Colors"), - EditorGUIUtility.TrTextContent("Random Between Two Gradients"), - EditorGUIUtility.TrTextContent("Random Color")}; - MinMaxGradientState[] states = { MinMaxGradientState.k_Color, - MinMaxGradientState.k_Gradient, - MinMaxGradientState.k_RandomBetweenTwoColors, - MinMaxGradientState.k_RandomBetweenTwoGradients, - MinMaxGradientState.k_RandomColor}; - bool[] allowState = { gradientProp.m_AllowColor, - gradientProp.m_AllowGradient, - gradientProp.m_AllowRandomBetweenTwoColors, - gradientProp.m_AllowRandomBetweenTwoGradients, - gradientProp.m_AllowRandomColor}; - - bool allowHighlight = !gradientProp.stateHasMultipleDifferentValues; - GenericMenu menu = new GenericMenu(); - for (int i = 0; i < texts.Length; ++i) - { - if (allowState[i]) - menu.AddItem(texts[i], allowHighlight && (gradientProp.state == states[i]), SelectMinMaxGradientStateCallback, new GradientCallbackData(states[i], gradientProp)); - } - menu.ShowAsContext(); - Event.current.Use(); - } - } - - private class ColorCallbackData - { - public ColorCallbackData(bool state, SerializedProperty bp) - { - boolProp = bp; - selectedState = state; - } - - public SerializedProperty boolProp; - public bool selectedState; - } - - static void SelectMinMaxColorStateCallback(object obj) - { - ColorCallbackData data = (ColorCallbackData)obj; - data.boolProp.boolValue = data.selectedState; - } - - public static void GUIMMColorPopUp(Rect rect, SerializedProperty boolProp) - { - if (EditorGUI.DropdownButton(rect, GUIContent.none, FocusType.Passive, ParticleSystemStyles.Get().minMaxCurveStateDropDown)) - { - GenericMenu menu = new GenericMenu(); - GUIContent[] texts = { EditorGUIUtility.TrTextContent("Constant Color"), EditorGUIUtility.TrTextContent("Random Between Two Colors") }; - bool[] states = { false, true }; - - for (int i = 0; i < texts.Length; ++i) - { - menu.AddItem(texts[i], (boolProp.boolValue == states[i]), SelectMinMaxColorStateCallback, new ColorCallbackData(states[i], boolProp)); - } - menu.ShowAsContext(); - Event.current.Use(); - } - } - } // end class ModuleUI -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/NoiseModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/NoiseModuleUI.cs deleted file mode 100644 index 17952a77e8..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/NoiseModuleUI.cs +++ /dev/null @@ -1,255 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - - -namespace UnityEditor -{ - class NoiseModuleUI : ModuleUI - { - SerializedMinMaxCurve m_StrengthX; - SerializedMinMaxCurve m_StrengthY; - SerializedMinMaxCurve m_StrengthZ; - SerializedProperty m_SeparateAxes; - SerializedProperty m_Frequency; - SerializedProperty m_Damping; - SerializedProperty m_Octaves; - SerializedProperty m_OctaveMultiplier; - SerializedProperty m_OctaveScale; - SerializedProperty m_Quality; - SerializedMinMaxCurve m_ScrollSpeed; - SerializedMinMaxCurve m_RemapX; - SerializedMinMaxCurve m_RemapY; - SerializedMinMaxCurve m_RemapZ; - SerializedProperty m_RemapEnabled; - SerializedMinMaxCurve m_PositionAmount; - SerializedMinMaxCurve m_RotationAmount; - SerializedMinMaxCurve m_SizeAmount; - - const int k_PreviewSize = 96; - static Texture2D s_PreviewTexture; - static bool s_PreviewTextureDirty = true; - - GUIStyle previewTextureStyle; - - class Texts - { - public GUIContent separateAxes = EditorGUIUtility.TrTextContent("Separate Axes", "If enabled, you can control the noise separately for each axis."); - public GUIContent strength = EditorGUIUtility.TrTextContent("Strength", "How strong the overall noise effect is."); - public GUIContent frequency = EditorGUIUtility.TrTextContent("Frequency", "Low values create soft, smooth noise, and high values create rapidly changing noise."); - public GUIContent damping = EditorGUIUtility.TrTextContent("Damping", "If enabled, strength is proportional to frequency."); - public GUIContent octaves = EditorGUIUtility.TrTextContent("Octaves", "Layers of noise that combine to produce final noise (Adding octaves increases the performance cost substantially!)"); - public GUIContent octaveMultiplier = EditorGUIUtility.TrTextContent("Octave Multiplier", "When combining each octave, scale the intensity by this amount."); - public GUIContent octaveScale = EditorGUIUtility.TrTextContent("Octave Scale", "When combining each octave, zoom in by this amount."); - public GUIContent quality = EditorGUIUtility.TrTextContent("Quality", "Generate 1D, 2D or 3D noise."); - public GUIContent scrollSpeed = EditorGUIUtility.TrTextContent("Scroll Speed", "Scroll the noise map over the particle system."); - public GUIContent remap = EditorGUIUtility.TrTextContent("Remap", "Remap the final noise values into a new range."); - public GUIContent remapCurve = EditorGUIUtility.TrTextContent("Remap Curve"); - public GUIContent positionAmount = EditorGUIUtility.TrTextContent("Position Amount", "What proportion of the noise is applied to the particle positions."); - public GUIContent rotationAmount = EditorGUIUtility.TrTextContent("Rotation Amount", "What proportion of the noise is applied to the particle rotations, in degrees per second."); - public GUIContent sizeAmount = EditorGUIUtility.TrTextContent("Size Amount", "Multiply the size of the particle by a proportion of the noise."); - public GUIContent x = EditorGUIUtility.TextContent("X"); - public GUIContent y = EditorGUIUtility.TextContent("Y"); - public GUIContent z = EditorGUIUtility.TextContent("Z"); - public GUIContent previewTexture = EditorGUIUtility.TrTextContent("Preview", "Preview the noise as a texture."); - public GUIContent previewTextureMultiEdit = EditorGUIUtility.TrTextContent("Preview (Disabled)", "Preview is disabled in multi-object editing mode."); - - public GUIContent[] qualityDropdown = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Low (1D)"), - EditorGUIUtility.TrTextContent("Medium (2D)"), - EditorGUIUtility.TrTextContent("High (3D)") - }; - } - private static Texts s_Texts; - - public NoiseModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "NoiseModule", displayName) - { - m_ToolTip = "Add noise/turbulence to particle movement."; - } - - protected override void Init() - { - // Already initialized? - if (m_StrengthX != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_StrengthX = new SerializedMinMaxCurve(this, s_Texts.x, "strength", kUseSignedRange); - m_StrengthY = new SerializedMinMaxCurve(this, s_Texts.y, "strengthY", kUseSignedRange); - m_StrengthZ = new SerializedMinMaxCurve(this, s_Texts.z, "strengthZ", kUseSignedRange); - m_SeparateAxes = GetProperty("separateAxes"); - m_Damping = GetProperty("damping"); - m_Frequency = GetProperty("frequency"); - m_Octaves = GetProperty("octaves"); - m_OctaveMultiplier = GetProperty("octaveMultiplier"); - m_OctaveScale = GetProperty("octaveScale"); - m_Quality = GetProperty("quality"); - m_ScrollSpeed = new SerializedMinMaxCurve(this, s_Texts.scrollSpeed, "scrollSpeed", kUseSignedRange); - m_ScrollSpeed.m_AllowRandom = false; - m_RemapX = new SerializedMinMaxCurve(this, s_Texts.x, "remap", kUseSignedRange); - m_RemapY = new SerializedMinMaxCurve(this, s_Texts.y, "remapY", kUseSignedRange); - m_RemapZ = new SerializedMinMaxCurve(this, s_Texts.z, "remapZ", kUseSignedRange); - m_RemapX.m_AllowRandom = false; - m_RemapY.m_AllowRandom = false; - m_RemapZ.m_AllowRandom = false; - m_RemapX.m_AllowConstant = false; - m_RemapY.m_AllowConstant = false; - m_RemapZ.m_AllowConstant = false; - m_RemapEnabled = GetProperty("remapEnabled"); - m_PositionAmount = new SerializedMinMaxCurve(this, s_Texts.positionAmount, "positionAmount", kUseSignedRange); - m_RotationAmount = new SerializedMinMaxCurve(this, s_Texts.rotationAmount, "rotationAmount", kUseSignedRange); - m_SizeAmount = new SerializedMinMaxCurve(this, s_Texts.sizeAmount, "sizeAmount", kUseSignedRange); - - if (s_PreviewTexture == null) - { - s_PreviewTexture = new Texture2D(k_PreviewSize, k_PreviewSize, TextureFormat.RGBA32, false, true); - s_PreviewTexture.name = "ParticleNoisePreview"; - s_PreviewTexture.filterMode = FilterMode.Bilinear; - s_PreviewTexture.hideFlags = HideFlags.HideAndDontSave; - s_Texts.previewTexture.image = s_PreviewTexture; - s_Texts.previewTextureMultiEdit.image = s_PreviewTexture; - } - s_PreviewTextureDirty = true; - - previewTextureStyle = new GUIStyle(ParticleSystemStyles.Get().label); - previewTextureStyle.alignment = TextAnchor.LowerCenter; - previewTextureStyle.imagePosition = ImagePosition.ImageAbove; - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - // values take 1 frame to appear in the module, so delay our generation of the preview texture using this bool - if (s_PreviewTextureDirty) - { - if (m_ParticleSystemUI.multiEdit) - { - Color32[] pixels = new Color32[s_PreviewTexture.width * s_PreviewTexture.height]; - for (int i = 0; i < pixels.Length; i++) - pixels[i] = new Color32(120, 120, 120, 255); - s_PreviewTexture.SetPixels32(pixels); - s_PreviewTexture.Apply(false); - } - else - { - m_ParticleSystemUI.m_ParticleSystems[0].GenerateNoisePreviewTexture(s_PreviewTexture); - } - s_PreviewTextureDirty = false; - } - - if (!isWindowView) - { - GUILayout.BeginHorizontal(); - GUILayout.BeginVertical(); - } - - EditorGUI.BeginChangeCheck(); - bool separateAxes = GUIToggle(s_Texts.separateAxes, m_SeparateAxes); - bool separateAxesChanged = EditorGUI.EndChangeCheck(); - - EditorGUI.BeginChangeCheck(); - - // Remove old curves from curve editor - if (separateAxesChanged && !separateAxes) - { - m_StrengthY.RemoveCurveFromEditor(); - m_StrengthZ.RemoveCurveFromEditor(); - m_RemapY.RemoveCurveFromEditor(); - m_RemapZ.RemoveCurveFromEditor(); - } - - // Keep states in sync - if (!m_StrengthX.stateHasMultipleDifferentValues) - { - m_StrengthZ.SetMinMaxState(m_StrengthX.state, separateAxes); - m_StrengthY.SetMinMaxState(m_StrengthX.state, separateAxes); - } - if (!m_RemapX.stateHasMultipleDifferentValues) - { - m_RemapZ.SetMinMaxState(m_RemapX.state, separateAxes); - m_RemapY.SetMinMaxState(m_RemapX.state, separateAxes); - } - - if (separateAxes) - { - m_StrengthX.m_DisplayName = s_Texts.x; - GUITripleMinMaxCurve(GUIContent.none, s_Texts.x, m_StrengthX, s_Texts.y, m_StrengthY, s_Texts.z, m_StrengthZ, null); - } - else - { - m_StrengthX.m_DisplayName = s_Texts.strength; - GUIMinMaxCurve(s_Texts.strength, m_StrengthX); - } - - GUIFloat(s_Texts.frequency, m_Frequency); - GUIMinMaxCurve(s_Texts.scrollSpeed, m_ScrollSpeed); - GUIToggle(s_Texts.damping, m_Damping); - - int numOctaves = GUIInt(s_Texts.octaves, m_Octaves); - using (new EditorGUI.DisabledScope(numOctaves == 1)) - { - GUIFloat(s_Texts.octaveMultiplier, m_OctaveMultiplier); - GUIFloat(s_Texts.octaveScale, m_OctaveScale); - } - - GUIPopup(s_Texts.quality, m_Quality, s_Texts.qualityDropdown); - - EditorGUI.BeginChangeCheck(); - bool remapEnabled = GUIToggle(s_Texts.remap, m_RemapEnabled); - bool remapEnabledChanged = EditorGUI.EndChangeCheck(); - - // Remove old curves from curve editor - if (remapEnabledChanged && !remapEnabled) - { - m_RemapX.RemoveCurveFromEditor(); - m_RemapY.RemoveCurveFromEditor(); - m_RemapZ.RemoveCurveFromEditor(); - } - - using (new EditorGUI.DisabledScope(remapEnabled == false)) - { - if (separateAxes) - { - m_RemapX.m_DisplayName = s_Texts.x; - GUITripleMinMaxCurve(GUIContent.none, s_Texts.x, m_RemapX, s_Texts.y, m_RemapY, s_Texts.z, m_RemapZ, null); - } - else - { - m_RemapX.m_DisplayName = s_Texts.remap; - GUIMinMaxCurve(s_Texts.remapCurve, m_RemapX); - } - } - - GUIMinMaxCurve(s_Texts.positionAmount, m_PositionAmount); - GUIMinMaxCurve(s_Texts.rotationAmount, m_RotationAmount); - GUIMinMaxCurve(s_Texts.sizeAmount, m_SizeAmount); - - if (!isWindowView) - GUILayout.EndVertical(); - - if (EditorGUI.EndChangeCheck() || m_ScrollSpeed.scalar.floatValue != 0.0f || remapEnabled || separateAxesChanged) - { - s_PreviewTextureDirty = true; - m_ParticleSystemUI.m_ParticleEffectUI.m_Owner.Repaint(); - } - - if (m_ParticleSystemUI.multiEdit) - GUILayout.Label(s_Texts.previewTextureMultiEdit, previewTextureStyle, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(false)); - else - GUILayout.Label(s_Texts.previewTexture, previewTextureStyle, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(false)); - - if (!isWindowView) - GUILayout.EndHorizontal(); - } - - public override void UpdateCullingSupportedString(ref string text) - { - text += "\nNoise module is enabled."; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs deleted file mode 100644 index 79603d0ac0..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs +++ /dev/null @@ -1,624 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using System.Collections.Generic; -using System.Linq; -using UnityEngine.Experimental.Rendering; - -namespace UnityEditor -{ - internal class RendererModuleUI : ModuleUI - { - // Keep in sync with the one in ParticleSystemRenderer.h - const int k_MaxNumMeshes = 4; - - // BaseRenderer and Renderer - SerializedProperty m_CastShadows; - SerializedProperty m_ReceiveShadows; - SerializedProperty m_MotionVectors; - SerializedProperty m_Material; - SerializedProperty m_TrailMaterial; - SerializedProperty m_SortingOrder; - SerializedProperty m_SortingLayerID; - SerializedProperty m_RenderingLayerMask; - - // From ParticleSystemRenderer - SerializedProperty m_RenderMode; - SerializedProperty[] m_Meshes = new SerializedProperty[k_MaxNumMeshes]; - SerializedProperty[] m_ShownMeshes; - - SerializedProperty m_MinParticleSize; //< How small is a particle allowed to be on screen at least? 1 is entire viewport. 0.5 is half viewport. - SerializedProperty m_MaxParticleSize; //< How large is a particle allowed to be on screen at most? 1 is entire viewport. 0.5 is half viewport. - SerializedProperty m_CameraVelocityScale; //< How much the camera motion is factored in when determining particle stretching. - SerializedProperty m_VelocityScale; //< When Stretch Particles is enabled, defines the length of the particle compared to its velocity. - SerializedProperty m_LengthScale; //< When Stretch Particles is enabled, defines the length of the particle compared to its width. - SerializedProperty m_SortMode; //< What method of particle sorting to use. If none is specified, no sorting will occur. - SerializedProperty m_SortingFudge; //< Lower the number, most likely that these particles will appear in front of other transparent objects, including other particles. - SerializedProperty m_NormalDirection; - RendererEditorBase.Probes m_Probes; - - SerializedProperty m_RenderAlignment; - SerializedProperty m_Pivot; - SerializedProperty m_UseCustomVertexStreams; - SerializedProperty m_VertexStreams; - SerializedProperty m_MaskInteraction; - SerializedProperty m_EnableGPUInstancing; - - - ReorderableList m_VertexStreamsList; - int m_NumTexCoords; - int m_TexCoordChannelIndex; - int m_NumInstancedStreams; - bool m_HasTangent; - bool m_HasColor; - bool m_HasGPUInstancing; - - static bool s_VisualizePivot = false; - - // Keep in sync with ParticleSystemRenderMode in ParticleSystemRenderer.h - enum RenderMode - { - Billboard = 0, - Stretch3D = 1, - BillboardFixedHorizontal = 2, - BillboardFixedVertical = 3, - Mesh = 4, - None = 5 - }; - - class Texts - { - public GUIContent renderMode = EditorGUIUtility.TrTextContent("Render Mode", "Defines the render mode of the particle renderer."); - public GUIContent material = EditorGUIUtility.TrTextContent("Material", "Defines the material used to render particles."); - public GUIContent trailMaterial = EditorGUIUtility.TrTextContent("Trail Material", "Defines the material used to render particle trails."); - public GUIContent mesh = EditorGUIUtility.TrTextContent("Mesh", "Defines the mesh that will be rendered as particle."); - public GUIContent minParticleSize = EditorGUIUtility.TrTextContent("Min Particle Size", "How small is a particle allowed to be on screen at least? 1 is entire viewport. 0.5 is half viewport."); - public GUIContent maxParticleSize = EditorGUIUtility.TrTextContent("Max Particle Size", "How large is a particle allowed to be on screen at most? 1 is entire viewport. 0.5 is half viewport."); - public GUIContent cameraSpeedScale = EditorGUIUtility.TrTextContent("Camera Scale", "How much the camera speed is factored in when determining particle stretching."); - public GUIContent speedScale = EditorGUIUtility.TrTextContent("Speed Scale", "Defines the length of the particle compared to its speed."); - public GUIContent lengthScale = EditorGUIUtility.TrTextContent("Length Scale", "Defines the length of the particle compared to its width."); - public GUIContent sortingFudge = EditorGUIUtility.TrTextContent("Sorting Fudge", "Lower the number and most likely these particles will appear in front of other transparent objects, including other particles."); - public GUIContent sortMode = EditorGUIUtility.TrTextContent("Sort Mode", "The draw order of particles can be sorted by distance, oldest in front, or youngest in front."); - public GUIContent rotation = EditorGUIUtility.TrTextContent("Rotation", "Set whether the rotation of the particles is defined in Screen or World space."); - public GUIContent castShadows = EditorGUIUtility.TrTextContent("Cast Shadows", "Only opaque materials cast shadows"); - public GUIContent receiveShadows = EditorGUIUtility.TrTextContent("Receive Shadows", "Only opaque materials receive shadows. When using deferred rendering, all opaque objects receive shadows."); - public GUIContent motionVectors = EditorGUIUtility.TrTextContent("Motion Vectors", "Specifies whether the Particle System renders 'Per Object Motion', 'Camera Motion', or 'No Motion' vectors to the Camera Motion Vector Texture. Note that there is no built-in support for Per-Particle Motion."); - public GUIContent normalDirection = EditorGUIUtility.TrTextContent("Normal Direction", "Value between 0.0 and 1.0. If 1.0 is used, normals will point towards camera. If 0.0 is used, normals will point out in the corner direction of the particle."); - - public GUIContent sortingLayer = EditorGUIUtility.TrTextContent("Sorting Layer", "Name of the Renderer's sorting layer."); - public GUIContent sortingOrder = EditorGUIUtility.TrTextContent("Order in Layer", "Renderer's order within a sorting layer"); - public GUIContent space = EditorGUIUtility.TrTextContent("Render Alignment", "Specifies if the particles will face the camera, align to world axes, or stay local to the system's transform."); - public GUIContent pivot = EditorGUIUtility.TrTextContent("Pivot", "Applies an offset to the pivot of particles, as a multiplier of its size."); - public GUIContent visualizePivot = EditorGUIUtility.TrTextContent("Visualize Pivot", "Render the pivot positions of the particles."); - public GUIContent useCustomVertexStreams = EditorGUIUtility.TrTextContent("Custom Vertex Streams", "Choose whether to send custom particle data to the shader."); - public GUIContent enableGPUInstancing = EditorGUIUtility.TrTextContent("Enable GPU Instancing", "Use GPU Instancing on platforms where it is supported, and when using shaders that contain a Procedural Instancing pass (#pragma instancing_options procedural)."); - - // Keep in sync with enum in ParticleSystemRenderer.h - public GUIContent[] particleTypes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Billboard"), - EditorGUIUtility.TrTextContent("Stretched Billboard"), - EditorGUIUtility.TrTextContent("Horizontal Billboard"), - EditorGUIUtility.TrTextContent("Vertical Billboard"), - EditorGUIUtility.TrTextContent("Mesh"), - EditorGUIUtility.TrTextContent("None") - }; - - public GUIContent[] sortTypes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("None"), - EditorGUIUtility.TrTextContent("By Distance"), - EditorGUIUtility.TrTextContent("Oldest in Front"), - EditorGUIUtility.TrTextContent("Youngest in Front") - }; - - public GUIContent[] spaces = new GUIContent[] - { - EditorGUIUtility.TrTextContent("View"), - EditorGUIUtility.TrTextContent("World"), - EditorGUIUtility.TrTextContent("Local"), - EditorGUIUtility.TrTextContent("Facing"), - EditorGUIUtility.TrTextContent("Velocity") - }; - - public GUIContent[] localSpace = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Local") - }; - - public GUIContent[] motionVectorOptions = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Camera Motion Only"), - EditorGUIUtility.TrTextContent("Per Object Motion"), - EditorGUIUtility.TrTextContent("Force No Motion") - }; - - public GUIContent maskingMode = EditorGUIUtility.TrTextContent("Masking", "Defines the masking behavior of the particles. See Sprite Masking documentation for more details."); - public GUIContent[] maskInteractions = new GUIContent[] - { - EditorGUIUtility.TrTextContent("No Masking"), - EditorGUIUtility.TrTextContent("Visible Inside Mask"), - EditorGUIUtility.TrTextContent("Visible Outside Mask") - }; - - private string[] vertexStreamsMenu = { "Position", "Normal", "Tangent", "Color", "UV/UV1", "UV/UV2", "UV/UV3", "UV/UV4", "UV/AnimBlend", "UV/AnimFrame", "Center", "VertexID", "Size/Size.x", "Size/Size.xy", "Size/Size.xyz", "Rotation/Rotation", "Rotation/Rotation3D", "Rotation/RotationSpeed", "Rotation/RotationSpeed3D", "Velocity", "Speed", "Lifetime/AgePercent", "Lifetime/InverseStartLifetime", "Random/Stable.x", "Random/Stable.xy", "Random/Stable.xyz", "Random/Stable.xyzw", "Random/Varying.x", "Random/Varying.xy", "Random/Varying.xyz", "Random/Varying.xyzw", "Custom/Custom1.x", "Custom/Custom1.xy", "Custom/Custom1.xyz", "Custom/Custom1.xyzw", "Custom/Custom2.x", "Custom/Custom2.xy", "Custom/Custom2.xyz", "Custom/Custom2.xyzw", "Noise/Sum.x", "Noise/Sum.xy", "Noise/Sum.xyz", "Noise/Impulse.x", "Noise/Impulse.xy", "Noise/Impulse.xyz" }; - public string[] vertexStreamsPacked = { "Position", "Normal", "Tangent", "Color", "UV", "UV2", "UV3", "UV4", "AnimBlend", "AnimFrame", "Center", "VertexID", "Size", "Size.xy", "Size.xyz", "Rotation", "Rotation3D", "RotationSpeed", "RotationSpeed3D", "Velocity", "Speed", "AgePercent", "InverseStartLifetime", "StableRandom.x", "StableRandom.xy", "StableRandom.xyz", "StableRandom.xyzw", "VariableRandom.x", "VariableRandom.xy", "VariableRandom.xyz", "VariableRandom.xyzw", "Custom1.x", "Custom1.xy", "Custom1.xyz", "Custom1.xyzw", "Custom2.x", "Custom2.xy", "Custom2.xyz", "Custom2.xyzw", "NoiseSum.x", "NoiseSum.xy", "NoiseSum.xyz", "NoiseImpulse.x", "NoiseImpulse.xy", "NoiseImpulse.xyz" }; // Keep in sync with enums in ParticleSystemRenderer.h and ParticleSystem.bindings - public string[] vertexStreamPackedTypes = { "POSITION.xyz", "NORMAL.xyz", "TANGENT.xyzw", "COLOR.xyzw" }; // all other types are floats - public int[] vertexStreamTexCoordChannels = { 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 3, 1, 1, 2, 3, 1, 3, 1, 3, 3, 1, 1, 1, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 1, 2, 3 }; - public string channels = "xyzw|xyz"; - public int vertexStreamsInstancedStart = 8; - - public GUIContent[] vertexStreamsMenuContent; - - public Texts() - { - vertexStreamsMenuContent = vertexStreamsMenu.Select(x => new GUIContent(x)).ToArray(); - } - } - private static Texts s_Texts; - - public RendererModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "ParticleSystemRenderer", displayName, VisibilityState.VisibleAndFolded) - { - m_ToolTip = "Specifies how the particles are rendered."; - } - - public override bool DrawHeader(Rect rect, GUIContent label) - { - var wasBold = EditorGUIUtility.GetBoldDefaultFont(); - SerializedProperty itr = m_Object.GetIterator(); - bool useBold = false; - if (m_Object.targetObjects.Length == 1) - { - bool validItr = itr.Next(true); - while (validItr) - { - if (itr.isInstantiatedPrefab && itr.prefabOverride) - { - useBold = true; - break; - } - validItr = itr.Next(false); - } - } - EditorGUIUtility.SetBoldDefaultFont(useBold); - var toggleState = GUI.Toggle(rect, foldout, label, ParticleSystemStyles.Get().moduleHeaderStyle); - EditorGUIUtility.SetBoldDefaultFont(wasBold); - return toggleState; - } - - protected override void Init() - { - if (m_CastShadows != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_CastShadows = GetProperty0("m_CastShadows"); - m_ReceiveShadows = GetProperty0("m_ReceiveShadows"); - m_MotionVectors = GetProperty0("m_MotionVectors"); - m_Material = GetProperty0("m_Materials.Array.data[0]"); - m_TrailMaterial = GetProperty0("m_Materials.Array.data[1]"); - m_SortingOrder = GetProperty0("m_SortingOrder"); - m_RenderingLayerMask = GetProperty0("m_RenderingLayerMask"); - m_SortingLayerID = GetProperty0("m_SortingLayerID"); - - m_RenderMode = GetProperty0("m_RenderMode"); - m_MinParticleSize = GetProperty0("m_MinParticleSize"); - m_MaxParticleSize = GetProperty0("m_MaxParticleSize"); - m_CameraVelocityScale = GetProperty0("m_CameraVelocityScale"); - m_VelocityScale = GetProperty0("m_VelocityScale"); - m_LengthScale = GetProperty0("m_LengthScale"); - m_SortingFudge = GetProperty0("m_SortingFudge"); - m_SortMode = GetProperty0("m_SortMode"); - m_NormalDirection = GetProperty0("m_NormalDirection"); - - m_Probes = new RendererEditorBase.Probes(); - m_Probes.Initialize(serializedObject); - - m_RenderAlignment = GetProperty0("m_RenderAlignment"); - m_Pivot = GetProperty0("m_Pivot"); - - m_Meshes[0] = GetProperty0("m_Mesh"); - m_Meshes[1] = GetProperty0("m_Mesh1"); - m_Meshes[2] = GetProperty0("m_Mesh2"); - m_Meshes[3] = GetProperty0("m_Mesh3"); - List shownMeshes = new List(); - for (int i = 0; i < m_Meshes.Length; ++i) - { - // Always show the first mesh - if (i == 0 || m_Meshes[i].objectReferenceValue != null) - shownMeshes.Add(m_Meshes[i]); - } - m_ShownMeshes = shownMeshes.ToArray(); - - m_MaskInteraction = GetProperty0("m_MaskInteraction"); - - m_EnableGPUInstancing = GetProperty0("m_EnableGPUInstancing"); - - m_UseCustomVertexStreams = GetProperty0("m_UseCustomVertexStreams"); - m_VertexStreams = GetProperty0("m_VertexStreams"); - m_VertexStreamsList = new ReorderableList(serializedObject, m_VertexStreams, true, true, true, true); - m_VertexStreamsList.elementHeight = kReorderableListElementHeight; - m_VertexStreamsList.headerHeight = 0; - m_VertexStreamsList.onAddDropdownCallback = OnVertexStreamListAddDropdownCallback; - m_VertexStreamsList.onCanRemoveCallback = OnVertexStreamListCanRemoveCallback; - m_VertexStreamsList.drawElementCallback = DrawVertexStreamListElementCallback; - - s_VisualizePivot = EditorPrefs.GetBool("VisualizePivot", false); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - EditorGUI.BeginChangeCheck(); - RenderMode renderMode = (RenderMode)GUIPopup(s_Texts.renderMode, m_RenderMode, s_Texts.particleTypes); - bool renderModeChanged = EditorGUI.EndChangeCheck(); - - if (!m_RenderMode.hasMultipleDifferentValues) - { - if (renderMode == RenderMode.Mesh) - { - EditorGUI.indentLevel++; - DoListOfMeshesGUI(); - EditorGUI.indentLevel--; - - if (renderModeChanged && m_Meshes[0].objectReferenceInstanceIDValue == 0 && !m_Meshes[0].hasMultipleDifferentValues) - m_Meshes[0].objectReferenceValue = Resources.GetBuiltinResource(typeof(Mesh), "Cube.fbx"); - } - else if (renderMode == RenderMode.Stretch3D) - { - EditorGUI.indentLevel++; - GUIFloat(s_Texts.cameraSpeedScale, m_CameraVelocityScale); - GUIFloat(s_Texts.speedScale, m_VelocityScale); - GUIFloat(s_Texts.lengthScale, m_LengthScale); - EditorGUI.indentLevel--; - } - - if (renderMode != RenderMode.None) - { - if (renderMode != RenderMode.Mesh) - GUIFloat(s_Texts.normalDirection, m_NormalDirection); - - if (m_Material != null) // The renderer's material list could be empty - GUIObject(s_Texts.material, m_Material); - } - } - - if (m_TrailMaterial != null) // The renderer's material list could be empty - GUIObject(s_Texts.trailMaterial, m_TrailMaterial); - - if (renderMode != RenderMode.None) - { - if (!m_RenderMode.hasMultipleDifferentValues) - { - GUIPopup(s_Texts.sortMode, m_SortMode, s_Texts.sortTypes); - GUIFloat(s_Texts.sortingFudge, m_SortingFudge); - - if (renderMode != RenderMode.Mesh) - { - GUIFloat(s_Texts.minParticleSize, m_MinParticleSize); - GUIFloat(s_Texts.maxParticleSize, m_MaxParticleSize); - } - - if (renderMode == RenderMode.Billboard || renderMode == RenderMode.Mesh) - { - bool anyAligntoDirection = m_ParticleSystemUI.m_ParticleSystems.FirstOrDefault(o => o.shape.alignToDirection) != null; - if (anyAligntoDirection) - { - using (new EditorGUI.DisabledScope(true)) - { - GUIPopup(s_Texts.space, 0, s_Texts.localSpace); // force to "Local" - } - - GUIContent info = EditorGUIUtility.TrTextContent("Using Align to Direction in the Shape Module forces the system to be rendered using Local Render Alignment."); - EditorGUILayout.HelpBox(info.text, MessageType.Info, true); - } - else - { - GUIPopup(s_Texts.space, m_RenderAlignment, s_Texts.spaces); - } - } - - if (renderMode == RenderMode.Mesh) - { - GUIToggle(s_Texts.enableGPUInstancing, m_EnableGPUInstancing); - } - } - - GUIVector3Field(s_Texts.pivot, m_Pivot); - - EditorGUI.BeginChangeCheck(); - s_VisualizePivot = GUIToggle(s_Texts.visualizePivot, s_VisualizePivot); - if (EditorGUI.EndChangeCheck()) - { - EditorPrefs.SetBool("VisualizePivot", s_VisualizePivot); - } - - GUIPopup(s_Texts.maskingMode, m_MaskInteraction, s_Texts.maskInteractions); - - if (GUIToggle(s_Texts.useCustomVertexStreams, m_UseCustomVertexStreams)) - DoVertexStreamsGUI(renderMode); - } - - EditorGUILayout.Space(); - - GUIPopup(s_Texts.castShadows, m_CastShadows, EditorGUIUtility.TempContent(m_CastShadows.enumDisplayNames)); - - if (SupportedRenderingFeatures.active.rendererSupportsReceiveShadows) - { - // Disable ReceiveShadows options for Deferred rendering path - if (SceneView.IsUsingDeferredRenderingPath()) - { - using (new EditorGUI.DisabledScope(true)) { GUIToggle(s_Texts.receiveShadows, true); } - } - else - { - GUIToggle(s_Texts.receiveShadows, m_ReceiveShadows); - } - } - - if (SupportedRenderingFeatures.active.rendererSupportsMotionVectors) - GUIPopup(s_Texts.motionVectors, m_MotionVectors, s_Texts.motionVectorOptions); - - GUISortingLayerField(s_Texts.sortingLayer, m_SortingLayerID); - GUIInt(s_Texts.sortingOrder, m_SortingOrder); - - List renderers = new List(); - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - renderers.Add(ps.GetComponent()); - } - var renderersArray = renderers.ToArray(); - m_Probes.OnGUI(renderersArray, renderers.FirstOrDefault(), true); - - RendererEditorBase.RenderRenderingLayer(m_RenderingLayerMask, serializedObject.targetObject as Renderer, renderersArray, true); - } - - private void DoListOfMeshesGUI() - { - GUIListOfFloatObjectToggleFields(s_Texts.mesh, m_ShownMeshes, null, null, false); - - // Minus button - Rect rect = GUILayoutUtility.GetRect(0, kSingleLineHeight); //GUILayoutUtility.GetLastRect(); - rect.x = rect.xMax - kPlusAddRemoveButtonWidth * 2 - kPlusAddRemoveButtonSpacing; - rect.width = kPlusAddRemoveButtonWidth; - if (m_ShownMeshes.Length > 1) - { - if (MinusButton(rect)) - { - m_ShownMeshes[m_ShownMeshes.Length - 1].objectReferenceValue = null; - - List shownMeshes = new List(m_ShownMeshes); - shownMeshes.RemoveAt(shownMeshes.Count - 1); - m_ShownMeshes = shownMeshes.ToArray(); - } - } - - // Plus button - if (m_ShownMeshes.Length < k_MaxNumMeshes && !m_ParticleSystemUI.multiEdit) - { - rect.x += kPlusAddRemoveButtonWidth + kPlusAddRemoveButtonSpacing; - if (PlusButton(rect)) - { - List shownMeshes = new List(m_ShownMeshes); - shownMeshes.Add(m_Meshes[shownMeshes.Count]); - m_ShownMeshes = shownMeshes.ToArray(); - } - } - } - - private class StreamCallbackData - { - public StreamCallbackData(UnityEditorInternal.ReorderableList l, SerializedProperty prop, int s) - { - list = l; - streamProp = prop; - stream = s; - } - - public UnityEditorInternal.ReorderableList list; - public SerializedProperty streamProp; - public int stream; - } - - void SelectVertexStreamCallback(object obj) - { - StreamCallbackData data = (StreamCallbackData)obj; - - ReorderableList.defaultBehaviours.DoAddButton(data.list); - - var element = data.streamProp.GetArrayElementAtIndex(data.list.index); - element.intValue = data.stream; - - m_ParticleSystemUI.m_RendererSerializedObject.ApplyModifiedProperties(); - } - - private void DoVertexStreamsGUI(RenderMode renderMode) - { - ParticleSystemRenderer renderer = m_ParticleSystemUI.m_ParticleSystems[0].GetComponent(); - - // render list - m_NumTexCoords = 0; - m_TexCoordChannelIndex = 0; - m_NumInstancedStreams = 0; - m_HasTangent = false; - m_HasColor = false; - m_HasGPUInstancing = (renderMode == RenderMode.Mesh) ? renderer.supportsMeshInstancing : false; - m_VertexStreamsList.DoLayoutList(); - - if (!m_ParticleSystemUI.multiEdit) - { - // error messages - string errors = ""; - - // check we have the same streams as the assigned shader - if (m_Material != null) - { - Material material = m_Material.objectReferenceValue as Material; - int totalChannelCount = m_NumTexCoords * 4 + m_TexCoordChannelIndex; - bool tangentError = false, colorError = false, uvError = false; - bool anyErrors = m_ParticleSystemUI.m_ParticleSystems[0].CheckVertexStreamsMatchShader(m_HasTangent, m_HasColor, totalChannelCount, material, ref tangentError, ref colorError, ref uvError); - if (anyErrors) - { - errors += "Vertex streams do not match the shader inputs. Particle systems may not render correctly. Ensure your streams match and are used by the shader."; - if (tangentError) - errors += "\n- TANGENT stream does not match."; - if (colorError) - errors += "\n- COLOR stream does not match."; - if (uvError) - errors += "\n- TEXCOORD streams do not match."; - } - } - - // check we aren't using too many texcoords - int maxTexCoords = m_ParticleSystemUI.m_ParticleSystems[0].GetMaxTexCoordStreams(); - if (m_NumTexCoords > maxTexCoords || (m_NumTexCoords == maxTexCoords && m_TexCoordChannelIndex > 0)) - { - if (errors != "") - errors += "\n\n"; - errors += "Only " + maxTexCoords + " TEXCOORD streams are supported."; - } - - // check input meshes aren't using too many UV streams - if (renderMode == RenderMode.Mesh) - { - Mesh[] meshes = new Mesh[k_MaxNumMeshes]; - int numMeshes = renderer.GetMeshes(meshes); - for (int i = 0; i < numMeshes; i++) - { - if (meshes[i].HasChannel(Mesh.InternalShaderChannel.TexCoord2)) - { - if (errors != "") - errors += "\n\n"; - errors += "Meshes may only use a maximum of 2 input UV streams."; - } - } - } - - if (errors != "") - { - GUIContent warning = EditorGUIUtility.TextContent(errors); - EditorGUILayout.HelpBox(warning.text, MessageType.Error, true); - } - } - } - - private void OnVertexStreamListAddDropdownCallback(Rect rect, UnityEditorInternal.ReorderableList list) - { - List notEnabled = new List(); - for (int i = 0; i < s_Texts.vertexStreamsPacked.Length; ++i) - { - bool exists = false; - for (int j = 0; j < m_VertexStreams.arraySize; ++j) - { - if (m_VertexStreams.GetArrayElementAtIndex(j).intValue == i) - { - exists = true; - break; - } - } - - if (!exists) - notEnabled.Add(i); - } - - GenericMenu menu = new GenericMenu(); - for (int i = 0; i < notEnabled.Count; ++i) - menu.AddItem(s_Texts.vertexStreamsMenuContent[notEnabled[i]], false, SelectVertexStreamCallback, new StreamCallbackData(list, m_VertexStreams, notEnabled[i])); - menu.ShowAsContext(); - Event.current.Use(); - } - - private bool OnVertexStreamListCanRemoveCallback(ReorderableList list) - { - // dont allow position stream to be removed - SerializedProperty vertexStream = m_VertexStreams.GetArrayElementAtIndex(list.index); - return (s_Texts.vertexStreamsPacked[vertexStream.intValue] != "Position"); - } - - private void DrawVertexStreamListElementCallback(Rect rect, int index, bool isActive, bool isFocused) - { - SerializedProperty vertexStream = m_VertexStreams.GetArrayElementAtIndex(index); - int vertexStreamValue = vertexStream.intValue; - string tcName = isWindowView ? "TEX" : "TEXCOORD"; - string instancedName = isWindowView ? "INST" : "INSTANCED"; - - int numChannels = s_Texts.vertexStreamTexCoordChannels[vertexStreamValue]; - if (m_HasGPUInstancing && vertexStreamValue >= s_Texts.vertexStreamsInstancedStart) - { - string swizzle = s_Texts.channels.Substring(0, numChannels); - GUI.Label(rect, s_Texts.vertexStreamsPacked[vertexStreamValue] + " (" + instancedName + m_NumInstancedStreams + "." + swizzle + ")", ParticleSystemStyles.Get().label); - m_NumInstancedStreams++; - } - else if (numChannels != 0) - { - int swizzleLength = (m_TexCoordChannelIndex + numChannels > 4) ? numChannels + 1 : numChannels; - string swizzle = s_Texts.channels.Substring(m_TexCoordChannelIndex, swizzleLength); - GUI.Label(rect, s_Texts.vertexStreamsPacked[vertexStreamValue] + " (" + tcName + m_NumTexCoords + "." + swizzle + ")", ParticleSystemStyles.Get().label); - m_TexCoordChannelIndex += numChannels; - if (m_TexCoordChannelIndex >= 4) - { - m_TexCoordChannelIndex -= 4; - m_NumTexCoords++; - } - } - else - { - GUI.Label(rect, s_Texts.vertexStreamsPacked[vertexStreamValue] + " (" + s_Texts.vertexStreamPackedTypes[vertexStreamValue] + ")", ParticleSystemStyles.Get().label); - if (s_Texts.vertexStreamsPacked[vertexStreamValue] == "Tangent") - m_HasTangent = true; - if (s_Texts.vertexStreamsPacked[vertexStreamValue] == "Color") - m_HasColor = true; - } - } - - // render pivots - override public void OnSceneViewGUI() - { - if (s_VisualizePivot == false) - return; - - Color oldColor = Handles.color; - Handles.color = Color.green; - Matrix4x4 oldMatrix = Handles.matrix; - - Vector3[] lineSegments = new Vector3[6]; - - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - ParticleSystem.Particle[] particles = new ParticleSystem.Particle[ps.particleCount]; - int count = ps.GetParticles(particles); - - Matrix4x4 transform = Matrix4x4.identity; - if (ps.main.simulationSpace == ParticleSystemSimulationSpace.Local) - { - transform = ps.GetLocalToWorldMatrix(); - } - Handles.matrix = transform; - - for (int i = 0; i < count; i++) - { - ParticleSystem.Particle particle = particles[i]; - Vector3 size = particle.GetCurrentSize3D(ps) * 0.05f; - - lineSegments[0] = particle.position - (Vector3.right * size.x); - lineSegments[1] = particle.position + (Vector3.right * size.x); - - lineSegments[2] = particle.position - (Vector3.up * size.y); - lineSegments[3] = particle.position + (Vector3.up * size.y); - - lineSegments[4] = particle.position - (Vector3.forward * size.z); - lineSegments[5] = particle.position + (Vector3.forward * size.z); - - Handles.DrawLines(lineSegments); - } - } - - Handles.color = oldColor; - Handles.matrix = oldMatrix; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RotationByVelocityModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RotationByVelocityModuleUI.cs deleted file mode 100644 index 445608bb81..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RotationByVelocityModuleUI.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class RotationByVelocityModuleUI : ModuleUI - { - class Texts - { - public GUIContent velocityRange = EditorGUIUtility.TrTextContent("Speed Range", "Maps the speed to a value along the curve, when using one of the curve modes."); - public GUIContent rotation = EditorGUIUtility.TrTextContent("Angular Velocity", "Controls the angular velocity of each particle based on its speed."); - public GUIContent separateAxes = EditorGUIUtility.TrTextContent("Separate Axes", "If enabled, you can control the angular velocity limit separately for each axis."); - public GUIContent x = EditorGUIUtility.TextContent("X"); - public GUIContent y = EditorGUIUtility.TextContent("Y"); - public GUIContent z = EditorGUIUtility.TextContent("Z"); - } - static Texts s_Texts; - SerializedMinMaxCurve m_X; - SerializedMinMaxCurve m_Y; - SerializedMinMaxCurve m_Z; - SerializedProperty m_SeparateAxes; - SerializedProperty m_Range; - - public RotationByVelocityModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "RotationBySpeedModule", displayName) - { - m_ToolTip = "Controls the angular velocity of each particle based on its speed."; - } - - protected override void Init() - { - // Already initialized? - if (m_Z != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_SeparateAxes = GetProperty("separateAxes"); - m_Range = GetProperty("range"); - m_X = new SerializedMinMaxCurve(this, s_Texts.x, "x", kUseSignedRange, false, m_SeparateAxes.boolValue); - m_Y = new SerializedMinMaxCurve(this, s_Texts.y, "y", kUseSignedRange, false, m_SeparateAxes.boolValue); - m_Z = new SerializedMinMaxCurve(this, s_Texts.z, "curve", kUseSignedRange); - m_X.m_RemapValue = Mathf.Rad2Deg; - m_Y.m_RemapValue = Mathf.Rad2Deg; - m_Z.m_RemapValue = Mathf.Rad2Deg; - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - EditorGUI.BeginChangeCheck(); - bool separateAxes = GUIToggle(s_Texts.separateAxes, m_SeparateAxes); - if (EditorGUI.EndChangeCheck()) - { - // Remove old curves from curve editor - if (!separateAxes) - { - m_X.RemoveCurveFromEditor(); - m_Y.RemoveCurveFromEditor(); - } - } - - // Keep states in sync - if (!m_Z.stateHasMultipleDifferentValues) - { - m_X.SetMinMaxState(m_Z.state, separateAxes); - m_Y.SetMinMaxState(m_Z.state, separateAxes); - } - - MinMaxCurveState state = m_Z.state; - - if (separateAxes) - { - m_Z.m_DisplayName = s_Texts.z; - GUITripleMinMaxCurve(GUIContent.none, s_Texts.x, m_X, s_Texts.y, m_Y, s_Texts.z, m_Z, null); - } - else - { - m_Z.m_DisplayName = s_Texts.rotation; - GUIMinMaxCurve(s_Texts.rotation, m_Z); - } - - using (new EditorGUI.DisabledScope((state == MinMaxCurveState.k_Scalar) || (state == MinMaxCurveState.k_TwoScalars))) - { - GUIMinMaxRange(s_Texts.velocityRange, m_Range); - } - } - - override public void UpdateCullingSupportedString(ref string text) - { - text += "\nRotation by Speed module is enabled."; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RotationModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RotationModuleUI.cs deleted file mode 100644 index 4108baa854..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RotationModuleUI.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class RotationModuleUI : ModuleUI - { - SerializedMinMaxCurve m_X; - SerializedMinMaxCurve m_Y; - SerializedMinMaxCurve m_Z; - SerializedProperty m_SeparateAxes; - - class Texts - { - public GUIContent rotation = EditorGUIUtility.TrTextContent("Angular Velocity", "Controls the angular velocity of each particle during its lifetime."); - public GUIContent separateAxes = EditorGUIUtility.TrTextContent("Separate Axes", "If enabled, you can control the angular velocity limit separately for each axis."); - public GUIContent x = EditorGUIUtility.TextContent("X"); - public GUIContent y = EditorGUIUtility.TextContent("Y"); - public GUIContent z = EditorGUIUtility.TextContent("Z"); - } - static Texts s_Texts; - - - public RotationModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "RotationModule", displayName) - { - m_ToolTip = "Controls the angular velocity of each particle during its lifetime."; - } - - protected override void Init() - { - // Already initialized? - if (m_Z != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_SeparateAxes = GetProperty("separateAxes"); - m_X = new SerializedMinMaxCurve(this, s_Texts.x, "x", kUseSignedRange, false, m_SeparateAxes.boolValue); - m_Y = new SerializedMinMaxCurve(this, s_Texts.y, "y", kUseSignedRange, false, m_SeparateAxes.boolValue); - m_Z = new SerializedMinMaxCurve(this, s_Texts.z, "curve", kUseSignedRange); - m_X.m_RemapValue = Mathf.Rad2Deg; - m_Y.m_RemapValue = Mathf.Rad2Deg; - m_Z.m_RemapValue = Mathf.Rad2Deg; - } - - public override void OnInspectorGUI(InitialModuleUI initial) - { - EditorGUI.BeginChangeCheck(); - bool separateAxes = GUIToggle(s_Texts.separateAxes, m_SeparateAxes); - if (EditorGUI.EndChangeCheck()) - { - // Remove old curves from curve editor - if (!separateAxes) - { - m_X.RemoveCurveFromEditor(); - m_Y.RemoveCurveFromEditor(); - } - } - - // Keep states in sync - if (!m_Z.stateHasMultipleDifferentValues) - { - m_X.SetMinMaxState(m_Z.state, separateAxes); - m_Y.SetMinMaxState(m_Z.state, separateAxes); - } - - if (separateAxes) - { - m_Z.m_DisplayName = s_Texts.z; - GUITripleMinMaxCurve(GUIContent.none, s_Texts.x, m_X, s_Texts.y, m_Y, s_Texts.z, m_Z, null); - } - else - { - m_Z.m_DisplayName = s_Texts.rotation; - GUIMinMaxCurve(s_Texts.rotation, m_Z); - } - } - - override public void UpdateCullingSupportedString(ref string text) - { - Init(); - - string failureReason = string.Empty; - if (!m_X.SupportsProcedural(ref failureReason)) - text += "\nRotation over Lifetime module curve X: " + failureReason; - - failureReason = string.Empty; - if (!m_Y.SupportsProcedural(ref failureReason)) - text += "\nRotation over Lifetime module curve Y: " + failureReason; - - failureReason = string.Empty; - if (!m_Z.SupportsProcedural(ref failureReason)) - text += "\nRotation over Lifetime module curve Z: " + failureReason; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SerializedModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SerializedModuleUI.cs deleted file mode 100644 index 7440f68f68..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SerializedModuleUI.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEditor; -using System.Collections; - -namespace UnityEditor -{ - internal class SerializedModule - { - protected string m_ModuleName; - protected SerializedObject m_Object; - protected SerializedProperty m_ModuleRootProperty; - - public SerializedModule(SerializedObject o, string name) - { - m_Object = o; - m_ModuleName = name; - m_ModuleRootProperty = m_Object.FindProperty(name); - } - - public SerializedProperty GetProperty0(string name) - { - SerializedProperty prop = m_Object.FindProperty(name); - if (prop == null) - Debug.LogError("GetProperty0: not found: " + name); - return prop; - } - - public SerializedProperty GetProperty(string name) - { - SerializedProperty prop = m_Object.FindProperty(Concat(m_ModuleName, name)); - if (prop == null) - Debug.LogError("GetProperty: not found: " + Concat(m_ModuleName, name)); - return prop; - } - - public SerializedProperty GetProperty0(string structName, string propName) - { - SerializedProperty prop = m_Object.FindProperty(Concat(structName, propName)); - if (prop == null) - Debug.LogError("GetProperty: not found: " + Concat(structName, propName)); - return prop; - } - - public SerializedProperty GetProperty(string structName, string propName) - { - SerializedProperty prop = m_Object.FindProperty(Concat(Concat(m_ModuleName, structName), propName)); - if (prop == null) - Debug.LogError("GetProperty: not found: " + Concat(Concat(m_ModuleName, structName), propName)); - return prop; - } - - public static string Concat(string a, string b) - { - return a + "." + b; - } - - public string GetUniqueModuleName(Object o) - { - return Concat("" + o.GetInstanceID(), m_ModuleName); - } - - internal SerializedObject serializedObject - { - get { return m_Object; } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ShapeModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ShapeModuleUI.cs deleted file mode 100644 index 8e81c8618f..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/ShapeModuleUI.cs +++ /dev/null @@ -1,777 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.IMGUI.Controls; -using UnityEngine; - -namespace UnityEditor -{ - class ShapeModuleUI : ModuleUI - { - struct MultiModeParameter - { - public SerializedProperty m_Value; - public SerializedProperty m_Mode; - public SerializedProperty m_Spread; - public SerializedMinMaxCurve m_Speed; - - public enum ValueMode { Random, Loop, PingPong, BurstSpread }; - - public static MultiModeParameter GetProperty(ModuleUI ui, string name, GUIContent speed) - { - MultiModeParameter result = new MultiModeParameter(); - result.m_Value = ui.GetProperty(name + ".value"); - result.m_Mode = ui.GetProperty(name + ".mode"); - result.m_Spread = ui.GetProperty(name + ".spread"); - result.m_Speed = new SerializedMinMaxCurve(ui, speed, name + ".speed", kUseSignedRange); - result.m_Speed.m_AllowRandom = false; - return result; - } - - public void OnInspectorGUI(MultiModeTexts text) - { - GUIFloat(text.value, m_Value); - - EditorGUI.indentLevel++; - - GUIPopup(text.mode, m_Mode, s_Texts.emissionModes); - GUIFloat(text.spread, m_Spread); - - if (!m_Mode.hasMultipleDifferentValues) - { - ValueMode mode = (ValueMode)m_Mode.intValue; - if (mode == ValueMode.Loop || mode == ValueMode.PingPong) - { - GUIMinMaxCurve(text.speed, m_Speed); - } - } - - EditorGUI.indentLevel--; - } - }; - - SerializedProperty m_Type; - SerializedProperty m_RandomDirectionAmount; - SerializedProperty m_SphericalDirectionAmount; - SerializedProperty m_RandomPositionAmount; - SerializedProperty m_AlignToDirection; - - SerializedProperty m_Position; - SerializedProperty m_Scale; - SerializedProperty m_Rotation; - - // primitive properties - MultiModeParameter m_Radius; - SerializedProperty m_RadiusThickness; - SerializedProperty m_Angle; - SerializedProperty m_Length; - SerializedProperty m_BoxThickness; - MultiModeParameter m_Arc; - SerializedProperty m_DonutRadius; - - // mesh properties - SerializedProperty m_PlacementMode; - SerializedProperty m_Mesh; - SerializedProperty m_MeshRenderer; - SerializedProperty m_SkinnedMeshRenderer; - SerializedProperty m_MeshMaterialIndex; - SerializedProperty m_UseMeshMaterialIndex; - SerializedProperty m_UseMeshColors; - SerializedProperty m_MeshNormalOffset; - - // texture properties - SerializedProperty m_Texture; - SerializedProperty m_TextureClipChannel; - SerializedProperty m_TextureClipThreshold; - SerializedProperty m_TextureColorAffectsParticles; - SerializedProperty m_TextureAlphaAffectsParticles; - SerializedProperty m_TextureBilinearFiltering; - SerializedProperty m_TextureUVChannel; - - // internal - private static Material s_Material; - private static Material s_TextureMaterial; - private static Material s_SphereTextureMaterial; - private static Mesh s_CircleMesh; - private static Mesh s_QuadMesh; - private static Mesh s_SphereMesh; - private static Mesh s_HemisphereMesh; - private static readonly Matrix4x4 s_ArcHandleOffsetMatrix = Matrix4x4.TRS( - Vector3.zero, Quaternion.AngleAxis(90f, Vector3.right) * Quaternion.AngleAxis(90f, Vector3.up), Vector3.one - ); - private ArcHandle m_ArcHandle = new ArcHandle(); - private BoxBoundsHandle m_BoxBoundsHandle = new BoxBoundsHandle(); - private SphereBoundsHandle m_SphereBoundsHandle = new SphereBoundsHandle(); - private static Color s_ShapeGizmoColor = new Color(148f / 255f, 229f / 255f, 1f, 0.9f); - - private readonly ParticleSystemShapeType[] m_GuiTypes = new[] { ParticleSystemShapeType.Sphere, ParticleSystemShapeType.Hemisphere, ParticleSystemShapeType.Cone, ParticleSystemShapeType.Donut, ParticleSystemShapeType.Box, ParticleSystemShapeType.Mesh, ParticleSystemShapeType.MeshRenderer, ParticleSystemShapeType.SkinnedMeshRenderer, ParticleSystemShapeType.Circle, ParticleSystemShapeType.SingleSidedEdge, ParticleSystemShapeType.Rectangle }; - private readonly int[] m_TypeToGuiTypeIndex = new[] { 0, 0, 1, 1, 2, 4, 5, 2, 2, 2, 8, 8, 9, 6, 7, 4, 4, 3, 10 }; - - private readonly ParticleSystemShapeType[] boxShapes = new ParticleSystemShapeType[] { ParticleSystemShapeType.Box, ParticleSystemShapeType.BoxShell, ParticleSystemShapeType.BoxEdge }; - private readonly ParticleSystemShapeType[] coneShapes = new ParticleSystemShapeType[] { ParticleSystemShapeType.Cone, ParticleSystemShapeType.ConeVolume }; - - class Texts - { - public GUIContent shape = EditorGUIUtility.TrTextContent("Shape", "Defines the shape of the volume from which particles can be emitted, and the direction of the start velocity."); - public GUIContent radius = EditorGUIUtility.TrTextContent("Radius", "Radius of the shape."); - public GUIContent radiusThickness = EditorGUIUtility.TrTextContent("Radius Thickness", "Control the thickness of the spawn volume, from 0 to 1."); - public GUIContent coneAngle = EditorGUIUtility.TrTextContent("Angle", "Angle of the cone."); - public GUIContent coneLength = EditorGUIUtility.TrTextContent("Length", "Length of the cone."); - public GUIContent boxThickness = EditorGUIUtility.TrTextContent("Box Thickness", "When using shell/edge modes, control the thickness of the spawn volume, from 0 to 1."); - public GUIContent meshType = EditorGUIUtility.TrTextContent("Type", "Generate particles from vertices, edges or triangles."); - public GUIContent mesh = EditorGUIUtility.TrTextContent("Mesh", "Mesh that the particle system will emit from."); - public GUIContent meshRenderer = EditorGUIUtility.TrTextContent("Mesh", "MeshRenderer that the particle system will emit from."); - public GUIContent skinnedMeshRenderer = EditorGUIUtility.TrTextContent("Mesh", "SkinnedMeshRenderer that the particle system will emit from."); - public GUIContent meshMaterialIndex = EditorGUIUtility.TrTextContent("Single Material", "Only emit from a specific material of the mesh."); - public GUIContent useMeshColors = EditorGUIUtility.TrTextContent("Use Mesh Colors", "Modulate particle color with mesh vertex colors, or if they don't exist, use the shader color property \"_Color\" or \"_TintColor\" from the material. Does not read texture colors."); - public GUIContent meshNormalOffset = EditorGUIUtility.TrTextContent("Normal Offset", "Offset particle spawn positions along the mesh normal."); - public GUIContent texture = EditorGUIUtility.TrTextContent("Texture", "Texture that the particles will sample their color from."); - public GUIContent textureClipChannel = EditorGUIUtility.TrTextContent("Clip Channel", "Select a channel to use for discarding particles."); - public GUIContent textureClipThreshold = EditorGUIUtility.TrTextContent("Clip Threshold", "Only emit from parts of the texture where the Clip Channel is greater than or equal to this value."); - public GUIContent textureColorAffectsParticles = EditorGUIUtility.TrTextContent("Color affects Particles", "Multiply the particle color by the texture RGB value."); - public GUIContent textureAlphaAffectsParticles = EditorGUIUtility.TrTextContent("Alpha affects Particles", "Multiply the particle alpha by the texture alpha value."); - public GUIContent textureBilinearFiltering = EditorGUIUtility.TrTextContent("Bilinear Filtering", "Blend between pixels on the texture."); - public GUIContent textureUVChannel = EditorGUIUtility.TrTextContent("UV Channel", "Use the selected UV channel from the source mesh, for reading the texture."); - public GUIContent alignToDirection = EditorGUIUtility.TrTextContent("Align To Direction", "Automatically align particles based on their initial direction of travel."); - public GUIContent randomDirectionAmount = EditorGUIUtility.TrTextContent("Randomize Direction", "Randomize the emission direction."); - public GUIContent sphericalDirectionAmount = EditorGUIUtility.TrTextContent("Spherize Direction", "Spherize the emission direction."); - public GUIContent randomPositionAmount = EditorGUIUtility.TrTextContent("Randomize Position", "Randomize the starting positions."); - public GUIContent emitFrom = EditorGUIUtility.TrTextContent("Emit from:", "Specifies from where particles are emitted."); - public GUIContent donutRadius = EditorGUIUtility.TrTextContent("Donut Radius", "The radius of the donut. Used to control the thickness of the ring."); - public GUIContent position = EditorGUIUtility.TrTextContent("Position", "Translate the emission shape."); - public GUIContent rotation = EditorGUIUtility.TrTextContent("Rotation", "Rotate the emission shape."); - public GUIContent scale = EditorGUIUtility.TrTextContent("Scale", "Scale the emission shape."); - - public GUIContent[] shapeTypes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Sphere"), - EditorGUIUtility.TrTextContent("Hemisphere"), - EditorGUIUtility.TrTextContent("Cone"), - EditorGUIUtility.TrTextContent("Donut"), - EditorGUIUtility.TrTextContent("Box"), - EditorGUIUtility.TrTextContent("Mesh"), - EditorGUIUtility.TrTextContent("Mesh Renderer"), - EditorGUIUtility.TrTextContent("Skinned Mesh Renderer"), - EditorGUIUtility.TrTextContent("Circle"), - EditorGUIUtility.TrTextContent("Edge"), - EditorGUIUtility.TextContent("Rectangle") - }; - - public GUIContent[] boxTypes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Volume"), - EditorGUIUtility.TrTextContent("Shell"), - EditorGUIUtility.TrTextContent("Edge") - }; - - public GUIContent[] coneTypes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Base"), - EditorGUIUtility.TrTextContent("Volume") - }; - - public GUIContent[] meshTypes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Vertex"), - EditorGUIUtility.TrTextContent("Edge"), - EditorGUIUtility.TrTextContent("Triangle") - }; - - public GUIContent[] emissionModes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Random"), - EditorGUIUtility.TrTextContent("Loop"), - EditorGUIUtility.TrTextContent("Ping-Pong"), - EditorGUIUtility.TrTextContent("Burst Spread") - }; - - public GUIContent[] textureClipChannels = new GUIContent[] - { - EditorGUIUtility.TextContent("Red"), - EditorGUIUtility.TextContent("Green"), - EditorGUIUtility.TextContent("Blue"), - EditorGUIUtility.TextContent("Alpha") - }; - } - - static Texts s_Texts; - - class MultiModeTexts - { - public MultiModeTexts(string _value, string _mode, string _spread, string _speed) - { - value = EditorGUIUtility.TextContent(_value); - mode = EditorGUIUtility.TextContent(_mode); - spread = EditorGUIUtility.TextContent(_spread); - speed = EditorGUIUtility.TextContent(_speed); - } - - public GUIContent value; - public GUIContent mode; - public GUIContent spread; - public GUIContent speed; - } - - static MultiModeTexts s_RadiusTexts = new MultiModeTexts( - /*_value:*/ "Radius|New particles are spawned along the radius.", - /*_mode:*/ "Mode|Control how particles are spawned along the radius.", - /*_spread:*/ "Spread|Spawn particles only at specific positions along the radius (0 to disable).", - /*_speed:*/ "Speed|Control the speed that the emission position moves along the radius."); - - static MultiModeTexts s_ArcTexts = new MultiModeTexts( - /*_value:*/ "Arc|New particles are spawned around the arc.", - /*_mode:*/ "Mode|Control how particles are spawned around the arc.", - /*_spread:*/ "Spread|Spawn particles only at specific angles around the arc (0 to disable).", - /*_speed:*/ "Speed|Control the speed that the emission position moves around the arc."); - - public ShapeModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "ShapeModule", displayName, VisibilityState.VisibleAndFolded) - { - m_ToolTip = "Shape of the emitter volume, which controls where particles are emitted and their initial direction."; - } - - protected override void Init() - { - if (m_Type != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_Type = GetProperty("type"); - m_Radius = MultiModeParameter.GetProperty(this, "radius", s_RadiusTexts.speed); - m_RadiusThickness = GetProperty("radiusThickness"); - m_Angle = GetProperty("angle"); - m_Length = GetProperty("length"); - m_BoxThickness = GetProperty("boxThickness"); - m_Arc = MultiModeParameter.GetProperty(this, "arc", s_ArcTexts.speed); - m_DonutRadius = GetProperty("donutRadius"); - - m_PlacementMode = GetProperty("placementMode"); - m_Mesh = GetProperty("m_Mesh"); - m_MeshRenderer = GetProperty("m_MeshRenderer"); - m_SkinnedMeshRenderer = GetProperty("m_SkinnedMeshRenderer"); - m_MeshMaterialIndex = GetProperty("m_MeshMaterialIndex"); - m_UseMeshMaterialIndex = GetProperty("m_UseMeshMaterialIndex"); - m_UseMeshColors = GetProperty("m_UseMeshColors"); - m_MeshNormalOffset = GetProperty("m_MeshNormalOffset"); - m_Texture = GetProperty("m_Texture"); - m_TextureClipChannel = GetProperty("m_TextureClipChannel"); - m_TextureClipThreshold = GetProperty("m_TextureClipThreshold"); - m_TextureColorAffectsParticles = GetProperty("m_TextureColorAffectsParticles"); - m_TextureAlphaAffectsParticles = GetProperty("m_TextureAlphaAffectsParticles"); - m_TextureBilinearFiltering = GetProperty("m_TextureBilinearFiltering"); - m_TextureUVChannel = GetProperty("m_TextureUVChannel"); - m_RandomDirectionAmount = GetProperty("randomDirectionAmount"); - m_SphericalDirectionAmount = GetProperty("sphericalDirectionAmount"); - m_RandomPositionAmount = GetProperty("randomPositionAmount"); - m_AlignToDirection = GetProperty("alignToDirection"); - - m_Position = GetProperty("m_Position"); - m_Scale = GetProperty("m_Scale"); - m_Rotation = GetProperty("m_Rotation"); - - if (!s_Material) - s_Material = Material.GetDefaultMaterial(); - if (!s_TextureMaterial) - s_TextureMaterial = new Material((Shader)EditorGUIUtility.Load("SceneView/ParticleShapeGizmo.shader")); - if (!s_SphereTextureMaterial) - s_SphereTextureMaterial = new Material((Shader)EditorGUIUtility.Load("SceneView/ParticleShapeGizmoSphere.shader")); - if (!s_CircleMesh) - s_CircleMesh = ((GameObject)EditorGUIUtility.Load("SceneView/Circle.fbx")).transform.GetComponent().sharedMesh; - if (!s_QuadMesh) - s_QuadMesh = Resources.GetBuiltinResource(typeof(Mesh), "Quad.fbx") as Mesh; - if (!s_SphereMesh) - s_SphereMesh = Resources.GetBuiltinResource(typeof(Mesh), "New-Sphere.fbx") as Mesh; - if (!s_HemisphereMesh) - s_HemisphereMesh = ((GameObject)EditorGUIUtility.Load("SceneView/Hemisphere.fbx")).transform.GetComponent().sharedMesh; - } - - public override float GetXAxisScalar() - { - return m_ParticleSystemUI.GetEmitterDuration(); - } - - private ParticleSystemShapeType ConvertConeEmitFromToConeType(int emitFrom) - { - return coneShapes[emitFrom]; - } - - private int ConvertConeTypeToConeEmitFrom(ParticleSystemShapeType shapeType) - { - return System.Array.IndexOf(coneShapes, shapeType); - } - - private ParticleSystemShapeType ConvertBoxEmitFromToBoxType(int emitFrom) - { - return boxShapes[emitFrom]; - } - - private int ConvertBoxTypeToBoxEmitFrom(ParticleSystemShapeType shapeType) - { - return System.Array.IndexOf(boxShapes, shapeType); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - EditorGUI.showMixedValue = m_Type.hasMultipleDifferentValues; - int type = m_Type.intValue; - int index = m_TypeToGuiTypeIndex[type]; - - EditorGUI.BeginChangeCheck(); - int index2 = GUIPopup(s_Texts.shape, index, s_Texts.shapeTypes, m_Type); - bool shapeTypeChanged = EditorGUI.EndChangeCheck(); - - EditorGUI.showMixedValue = false; - - ParticleSystemShapeType guiType = m_GuiTypes[index2]; - if (index2 != index) - { - type = (int)guiType; - } - - if (!m_Type.hasMultipleDifferentValues) - { - switch (guiType) - { - case ParticleSystemShapeType.Box: - { - int emitFrom = ConvertBoxTypeToBoxEmitFrom((ParticleSystemShapeType)type); - emitFrom = GUIPopup(s_Texts.emitFrom, emitFrom, s_Texts.boxTypes, m_Type); - type = (int)ConvertBoxEmitFromToBoxType(emitFrom); - - if (type == (int)ParticleSystemShapeType.BoxShell || type == (int)ParticleSystemShapeType.BoxEdge) - GUIVector3Field(s_Texts.boxThickness, m_BoxThickness); - } - break; - - case ParticleSystemShapeType.Cone: - { - GUIFloat(s_Texts.coneAngle, m_Angle); - GUIFloat(s_Texts.radius, m_Radius.m_Value); - GUIFloat(s_Texts.radiusThickness, m_RadiusThickness); - - m_Arc.OnInspectorGUI(s_ArcTexts); - - bool showLength = (type != (int)ParticleSystemShapeType.ConeVolume); - using (new EditorGUI.DisabledScope(showLength)) - { - GUIFloat(s_Texts.coneLength, m_Length); - } - - int emitFrom = ConvertConeTypeToConeEmitFrom((ParticleSystemShapeType)type); - emitFrom = GUIPopup(s_Texts.emitFrom, emitFrom, s_Texts.coneTypes, m_Type); - type = (int)ConvertConeEmitFromToConeType(emitFrom); - } - break; - - case ParticleSystemShapeType.Donut: - { - GUIFloat(s_Texts.radius, m_Radius.m_Value); - GUIFloat(s_Texts.donutRadius, m_DonutRadius); - GUIFloat(s_Texts.radiusThickness, m_RadiusThickness); - - m_Arc.OnInspectorGUI(s_ArcTexts); - } - break; - - case ParticleSystemShapeType.Mesh: - case ParticleSystemShapeType.MeshRenderer: - case ParticleSystemShapeType.SkinnedMeshRenderer: - { - GUIPopup(s_Texts.meshType, m_PlacementMode, s_Texts.meshTypes); - - Material material = null; - Mesh srcMesh = null; - if (guiType == ParticleSystemShapeType.Mesh) - { - GUIObject(s_Texts.mesh, m_Mesh); - srcMesh = (Mesh)m_Mesh.objectReferenceValue; - } - else if (guiType == ParticleSystemShapeType.MeshRenderer) - { - GUIObject(s_Texts.meshRenderer, m_MeshRenderer); - MeshRenderer mesh = (MeshRenderer)m_MeshRenderer.objectReferenceValue; - if (mesh) - { - material = mesh.sharedMaterial; - if (mesh.GetComponent()) - srcMesh = mesh.GetComponent().sharedMesh; - } - } - else - { - GUIObject(s_Texts.skinnedMeshRenderer, m_SkinnedMeshRenderer); - SkinnedMeshRenderer mesh = (SkinnedMeshRenderer)m_SkinnedMeshRenderer.objectReferenceValue; - if (mesh) - { - material = mesh.sharedMaterial; - srcMesh = mesh.sharedMesh; - } - } - - GUIToggleWithIntField(s_Texts.meshMaterialIndex, m_UseMeshMaterialIndex, m_MeshMaterialIndex, false); - bool useMeshColors = GUIToggle(s_Texts.useMeshColors, m_UseMeshColors); - if (useMeshColors) - { - if (material != null && srcMesh != null) - { - int colorName = Shader.PropertyToID("_Color"); - int tintColorName = Shader.PropertyToID("_TintColor"); - if (!material.HasProperty(colorName) && !material.HasProperty(tintColorName) && !srcMesh.HasChannel(Mesh.InternalShaderChannel.Color)) - { - GUIContent warning = EditorGUIUtility.TrTextContent("To use mesh colors, your source mesh must either provide vertex colors, or its shader must contain a color property named \"_Color\" or \"_TintColor\"."); - EditorGUILayout.HelpBox(warning.text, MessageType.Warning, true); - } - } - } - - GUIFloat(s_Texts.meshNormalOffset, m_MeshNormalOffset); - } - break; - - case ParticleSystemShapeType.Sphere: - case ParticleSystemShapeType.Hemisphere: - { - GUIFloat(s_Texts.radius, m_Radius.m_Value); - GUIFloat(s_Texts.radiusThickness, m_RadiusThickness); - } - break; - - case ParticleSystemShapeType.Circle: - { - GUIFloat(s_Texts.radius, m_Radius.m_Value); - GUIFloat(s_Texts.radiusThickness, m_RadiusThickness); - - m_Arc.OnInspectorGUI(s_ArcTexts); - } - break; - - case ParticleSystemShapeType.SingleSidedEdge: - { - m_Radius.OnInspectorGUI(s_RadiusTexts); - } - break; - - case ParticleSystemShapeType.Rectangle: - break; - } - } - - if (shapeTypeChanged || !m_Type.hasMultipleDifferentValues) - m_Type.intValue = type; - - OnTextureInspectorGUI(); - OnTransformInspectorGUI(); - OnMiscInspectorGUI(); - } - - private void OnTextureInspectorGUI() - { - EditorGUILayout.Space(); - GUIObject(s_Texts.texture, m_Texture); - GUIPopup(s_Texts.textureClipChannel, m_TextureClipChannel, s_Texts.textureClipChannels); - GUIFloat(s_Texts.textureClipThreshold, m_TextureClipThreshold); - GUIToggle(s_Texts.textureColorAffectsParticles, m_TextureColorAffectsParticles); - GUIToggle(s_Texts.textureAlphaAffectsParticles, m_TextureAlphaAffectsParticles); - GUIToggle(s_Texts.textureBilinearFiltering, m_TextureBilinearFiltering); - - if (!m_Type.hasMultipleDifferentValues) - { - if ((m_Type.intValue == (int)ParticleSystemShapeType.Mesh) || (m_Type.intValue == (int)ParticleSystemShapeType.MeshRenderer) || (m_Type.intValue == (int)ParticleSystemShapeType.SkinnedMeshRenderer)) - GUIInt(s_Texts.textureUVChannel, m_TextureUVChannel); - } - } - - private void OnTransformInspectorGUI() - { - EditorGUILayout.Space(); - GUIVector3Field(s_Texts.position, m_Position); - GUIVector3Field(s_Texts.rotation, m_Rotation); - GUIVector3Field(s_Texts.scale, m_Scale); - } - - private void OnMiscInspectorGUI() - { - EditorGUILayout.Space(); - GUIToggle(s_Texts.alignToDirection, m_AlignToDirection); - GUIFloat(s_Texts.randomDirectionAmount, m_RandomDirectionAmount); - GUIFloat(s_Texts.sphericalDirectionAmount, m_SphericalDirectionAmount); - GUIFloat(s_Texts.randomPositionAmount, m_RandomPositionAmount); - } - - override public void OnSceneViewGUI() - { - Color origCol = Handles.color; - Handles.color = s_ShapeGizmoColor; - - Matrix4x4 orgMatrix = Handles.matrix; - - EditorGUI.BeginChangeCheck(); - - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - var shapeModule = ps.shape; - var mainModule = ps.main; - - ParticleSystemShapeType type = shapeModule.shapeType; - - Matrix4x4 transformMatrix = new Matrix4x4(); - if (mainModule.scalingMode == ParticleSystemScalingMode.Local) - { - transformMatrix.SetTRS(ps.transform.position, ps.transform.rotation, ps.transform.localScale); - } - else if (mainModule.scalingMode == ParticleSystemScalingMode.Hierarchy) - { - transformMatrix = ps.transform.localToWorldMatrix; - } - else - { - transformMatrix.SetTRS(ps.transform.position, ps.transform.rotation, ps.transform.lossyScale); - } - - bool isBox = (type == ParticleSystemShapeType.Box || type == ParticleSystemShapeType.BoxShell || type == ParticleSystemShapeType.BoxEdge || type == ParticleSystemShapeType.Rectangle); - - Vector3 emitterScale = isBox ? Vector3.one : shapeModule.scale; - Matrix4x4 emitterMatrix = Matrix4x4.TRS(shapeModule.position, Quaternion.Euler(shapeModule.rotation), emitterScale); - transformMatrix *= emitterMatrix; - Handles.matrix = transformMatrix; - - if (type == ParticleSystemShapeType.Sphere) - { - EditorGUI.BeginChangeCheck(); - float radius = Handles.DoSimpleRadiusHandle(Quaternion.identity, Vector3.zero, shapeModule.radius, false); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(ps, "Sphere Handle Change"); - shapeModule.radius = radius; - } - - Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one * shapeModule.radius * 2.0f); - OnSceneViewTextureGUI(shapeModule, s_SphereMesh, false, s_SphereTextureMaterial, textureTransform); - } - else if (type == ParticleSystemShapeType.Circle) - { - EditorGUI.BeginChangeCheck(); - - m_ArcHandle.radius = shapeModule.radius; - m_ArcHandle.angle = shapeModule.arc; - m_ArcHandle.SetColorWithRadiusHandle(Color.white, 0f); - - using (new Handles.DrawingScope(Handles.matrix * s_ArcHandleOffsetMatrix)) - m_ArcHandle.DrawHandle(); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(ps, "Circle Handle Change"); - shapeModule.radius = m_ArcHandle.radius; - shapeModule.arc = m_ArcHandle.angle; - } - - Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(90.0f, 0.0f, 180.0f), Vector3.one * shapeModule.radius * 2.0f); - OnSceneViewTextureGUI(shapeModule, s_CircleMesh, true, s_TextureMaterial, textureTransform); - } - else if (type == ParticleSystemShapeType.Hemisphere) - { - EditorGUI.BeginChangeCheck(); - float radius = Handles.DoSimpleRadiusHandle(Quaternion.identity, Vector3.zero, shapeModule.radius, true); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(ps, "Hemisphere Handle Change"); - shapeModule.radius = radius; - } - - Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one * shapeModule.radius * 2.0f); - OnSceneViewTextureGUI(shapeModule, s_HemisphereMesh, false, s_SphereTextureMaterial, textureTransform); - } - else if (type == ParticleSystemShapeType.Cone) - { - EditorGUI.BeginChangeCheck(); - - Vector3 radiusAngleRange = new Vector3(shapeModule.radius, shapeModule.angle, mainModule.startSpeedMultiplier); - radiusAngleRange = Handles.ConeFrustrumHandle(Quaternion.identity, Vector3.zero, radiusAngleRange); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(ps, "Cone Handle Change"); - shapeModule.radius = radiusAngleRange.x; - shapeModule.angle = radiusAngleRange.y; - mainModule.startSpeedMultiplier = radiusAngleRange.z; - } - - Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(90.0f, 0.0f, 180.0f), Vector3.one * shapeModule.radius * 2.0f); - OnSceneViewTextureGUI(shapeModule, s_CircleMesh, true, s_TextureMaterial, textureTransform); - } - else if (type == ParticleSystemShapeType.ConeVolume) - { - EditorGUI.BeginChangeCheck(); - - Vector3 radiusAngleLength = new Vector3(shapeModule.radius, shapeModule.angle, shapeModule.length); - radiusAngleLength = Handles.ConeFrustrumHandle(Quaternion.identity, Vector3.zero, radiusAngleLength); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(ps, "Cone Volume Handle Change"); - shapeModule.radius = radiusAngleLength.x; - shapeModule.angle = radiusAngleLength.y; - shapeModule.length = radiusAngleLength.z; - } - - Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(90.0f, 0.0f, 180.0f), Vector3.one * shapeModule.radius * 2.0f); - OnSceneViewTextureGUI(shapeModule, s_CircleMesh, true, s_TextureMaterial, textureTransform); - } - else if (type == ParticleSystemShapeType.Box || type == ParticleSystemShapeType.BoxShell || type == ParticleSystemShapeType.BoxEdge) - { - EditorGUI.BeginChangeCheck(); - - m_BoxBoundsHandle.center = Vector3.zero; - m_BoxBoundsHandle.size = shapeModule.scale; - m_BoxBoundsHandle.DrawHandle(); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(ps, "Box Handle Change"); - shapeModule.scale = m_BoxBoundsHandle.size; - } - - Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS(new Vector3(0.0f, 0.0f, -m_BoxBoundsHandle.size.z * 0.5f), Quaternion.identity, m_BoxBoundsHandle.size); - OnSceneViewTextureGUI(shapeModule, s_QuadMesh, true, s_TextureMaterial, textureTransform); - } - else if (type == ParticleSystemShapeType.Donut) - { - // radius - EditorGUI.BeginChangeCheck(); - - m_ArcHandle.radius = shapeModule.radius; - m_ArcHandle.angle = shapeModule.arc; - m_ArcHandle.SetColorWithRadiusHandle(Color.white, 0f); - m_ArcHandle.wireframeColor = Color.clear; - - using (new Handles.DrawingScope(Handles.matrix * s_ArcHandleOffsetMatrix)) - m_ArcHandle.DrawHandle(); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(ps, "Donut Handle Change"); - shapeModule.radius = m_ArcHandle.radius; - shapeModule.arc = m_ArcHandle.angle; - } - - // donut extents - using (new Handles.DrawingScope(Handles.matrix * s_ArcHandleOffsetMatrix)) - { - float excessAngle = shapeModule.arc % 360f; - float angle = Mathf.Abs(shapeModule.arc) >= 360f ? 360f : excessAngle; - - Handles.DrawWireArc(new Vector3(0.0f, shapeModule.donutRadius, 0.0f), Vector3.up, Vector3.forward, angle, shapeModule.radius); - Handles.DrawWireArc(new Vector3(0.0f, -shapeModule.donutRadius, 0.0f), Vector3.up, Vector3.forward, angle, shapeModule.radius); - Handles.DrawWireArc(Vector3.zero, Vector3.up, Vector3.forward, angle, shapeModule.radius + shapeModule.donutRadius); - Handles.DrawWireArc(Vector3.zero, Vector3.up, Vector3.forward, angle, shapeModule.radius - shapeModule.donutRadius); - - if (shapeModule.arc != 360.0f) - { - Quaternion arcRotation = Quaternion.AngleAxis(shapeModule.arc, Vector3.up); - Vector3 capCenter = arcRotation * Vector3.forward * shapeModule.radius; - Handles.DrawWireDisc(capCenter, arcRotation * Vector3.right, shapeModule.donutRadius); - } - } - - // donut radius - m_SphereBoundsHandle.axes = PrimitiveBoundsHandle.Axes.X | PrimitiveBoundsHandle.Axes.Y; - m_SphereBoundsHandle.radius = shapeModule.donutRadius; - m_SphereBoundsHandle.center = Vector3.zero; - m_SphereBoundsHandle.SetColor(Color.white); - - float handleInterval = 90.0f; - int numOuterRadii = Mathf.Max(1, (int)Mathf.Ceil(shapeModule.arc / handleInterval)); - Matrix4x4 donutRadiusStartMatrix = Matrix4x4.TRS(new Vector3(shapeModule.radius, 0.0f, 0.0f), Quaternion.Euler(90.0f, 0.0f, 0.0f), Vector3.one); - for (int i = 0; i < numOuterRadii; i++) - { - EditorGUI.BeginChangeCheck(); - using (new Handles.DrawingScope(Handles.matrix * (Matrix4x4.Rotate(Quaternion.Euler(0.0f, 0.0f, handleInterval * i)) * donutRadiusStartMatrix))) - m_SphereBoundsHandle.DrawHandle(); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(ps, "Donut Radius Handle Change"); - shapeModule.donutRadius = m_SphereBoundsHandle.radius; - } - } - - // texture - Matrix4x4 textureTransform = transformMatrix * Matrix4x4.TRS(new Vector3(shapeModule.radius, 0.0f, 0.0f), Quaternion.Euler(180.0f, 0.0f, 180.0f), Vector3.one * shapeModule.donutRadius * 2.0f); - OnSceneViewTextureGUI(shapeModule, s_CircleMesh, true, s_TextureMaterial, textureTransform); - } - else if (type == ParticleSystemShapeType.SingleSidedEdge) - { - EditorGUI.BeginChangeCheck(); - float radius = Handles.DoSimpleEdgeHandle(Quaternion.identity, Vector3.zero, shapeModule.radius); - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(ps, "Edge Handle Change"); - shapeModule.radius = radius; - } - } - else if (type == ParticleSystemShapeType.Mesh) - { - Mesh mesh = shapeModule.mesh; - if (mesh) - { - bool orgWireframeMode = GL.wireframe; - GL.wireframe = true; - s_Material.SetPass(0); - Graphics.DrawMeshNow(mesh, transformMatrix); - GL.wireframe = orgWireframeMode; - - OnSceneViewTextureGUI(shapeModule, mesh, false, s_TextureMaterial, transformMatrix); - } - } - else if (type == ParticleSystemShapeType.Rectangle) - { - EditorGUI.BeginChangeCheck(); - - m_BoxBoundsHandle.center = Vector3.zero; - m_BoxBoundsHandle.size = new Vector3(shapeModule.scale.x, shapeModule.scale.y, 0.0f); - m_BoxBoundsHandle.DrawHandle(); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObject(ps, "Rectangle Handle Change"); - shapeModule.scale = new Vector3(m_BoxBoundsHandle.size.x, m_BoxBoundsHandle.size.y, 0.0f); - } - - OnSceneViewTextureGUI(shapeModule, s_QuadMesh, true, s_TextureMaterial, transformMatrix * Matrix4x4.Scale(m_BoxBoundsHandle.size)); - } - } - - if (EditorGUI.EndChangeCheck()) - m_ParticleSystemUI.m_ParticleEffectUI.m_Owner.Repaint(); - - Handles.color = origCol; - Handles.matrix = orgMatrix; - } - - private void OnSceneViewTextureGUI(ParticleSystem.ShapeModule shapeModule, Mesh mesh, bool twoSided, Material mat, Matrix4x4 transform) - { - Texture texture = shapeModule.texture; - if (texture) - { - mat.SetPass(0); - mat.SetTexture("_MainTex", texture); - mat.SetColor("_Color", new Color(1.0f, 1.0f, 1.0f, 0.4f)); - mat.SetFloat("_ClipChannel", (float)(int)shapeModule.textureClipChannel); - mat.SetFloat("_ClipThreshold", shapeModule.textureClipThreshold); - mat.SetFloat("_Cull", twoSided ? (float)UnityEngine.Rendering.CullMode.Off : (float)UnityEngine.Rendering.CullMode.Back); - mat.SetFloat("_UVChannel", (float)shapeModule.textureUVChannel); - Graphics.DrawMeshNow(mesh, transform); - } - } - - override public void UpdateCullingSupportedString(ref string text) - { - Init(); - - if (m_Arc.m_Mode.intValue != (int)MultiModeParameter.ValueMode.Random || m_Radius.m_Mode.intValue != (int)MultiModeParameter.ValueMode.Random) - text += "\n\tAnimated shape emission is enabled."; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SizeByVelocityModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SizeByVelocityModuleUI.cs deleted file mode 100644 index bdd04329a0..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SizeByVelocityModuleUI.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class SizeByVelocityModuleUI : ModuleUI - { - class Texts - { - public GUIContent velocityRange = EditorGUIUtility.TrTextContent("Speed Range", "Remaps speed in the defined range to a size."); - public GUIContent size = EditorGUIUtility.TrTextContent("Size", "Controls the size of each particle based on its speed."); - public GUIContent separateAxes = EditorGUIUtility.TrTextContent("Separate Axes", "If enabled, you can control the angular velocity limit separately for each axis."); - public GUIContent x = new GUIContent("X"); - public GUIContent y = new GUIContent("Y"); - public GUIContent z = new GUIContent("Z"); - } - static Texts s_Texts; - - SerializedMinMaxCurve m_X; - SerializedMinMaxCurve m_Y; - SerializedMinMaxCurve m_Z; - SerializedProperty m_SeparateAxes; - SerializedProperty m_Range; - - public SizeByVelocityModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "SizeBySpeedModule", displayName) - { - m_ToolTip = "Controls the size of each particle based on its speed."; - } - - protected override void Init() - { - // Already initialized? - if (m_X != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_SeparateAxes = GetProperty("separateAxes"); - m_Range = GetProperty("range"); - - m_X = new SerializedMinMaxCurve(this, s_Texts.x, "curve"); // use "curve" instead of "x" for backwards compatibility reasons: the old system used to only support one axis, and this was its name - m_X.m_AllowConstant = false; - m_Y = new SerializedMinMaxCurve(this, s_Texts.y, "y", false, false, m_SeparateAxes.boolValue); - m_Y.m_AllowConstant = false; - m_Z = new SerializedMinMaxCurve(this, s_Texts.z, "z", false, false, m_SeparateAxes.boolValue); - m_Z.m_AllowConstant = false; - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - EditorGUI.BeginChangeCheck(); - bool separateAxes = GUIToggle(s_Texts.separateAxes, m_SeparateAxes); - if (EditorGUI.EndChangeCheck()) - { - // Remove old curves from curve editor - if (!separateAxes) - { - m_Y.RemoveCurveFromEditor(); - m_Z.RemoveCurveFromEditor(); - } - } - - // Keep states in sync - if (!m_X.stateHasMultipleDifferentValues) - { - m_Z.SetMinMaxState(m_X.state, separateAxes); - m_Y.SetMinMaxState(m_X.state, separateAxes); - } - - MinMaxCurveState state = m_Z.state; - - if (separateAxes) - { - m_X.m_DisplayName = s_Texts.x; - GUITripleMinMaxCurve(GUIContent.none, s_Texts.x, m_X, s_Texts.y, m_Y, s_Texts.z, m_Z, null); - } - else - { - m_X.m_DisplayName = s_Texts.size; - GUIMinMaxCurve(s_Texts.size, m_X); - } - - using (new EditorGUI.DisabledScope((state == MinMaxCurveState.k_Scalar) || (state == MinMaxCurveState.k_TwoScalars))) - { - GUIMinMaxRange(s_Texts.velocityRange, m_Range); - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SizeModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SizeModuleUI.cs deleted file mode 100644 index dc650cdb85..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SizeModuleUI.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class SizeModuleUI : ModuleUI - { - SerializedMinMaxCurve m_X; - SerializedMinMaxCurve m_Y; - SerializedMinMaxCurve m_Z; - SerializedProperty m_SeparateAxes; - - class Texts - { - public GUIContent size = EditorGUIUtility.TrTextContent("Size", "Controls the size of each particle during its lifetime."); - public GUIContent separateAxes = EditorGUIUtility.TrTextContent("Separate Axes", "If enabled, you can control the angular velocity limit separately for each axis."); - public GUIContent x = EditorGUIUtility.TextContent("X"); - public GUIContent y = EditorGUIUtility.TextContent("Y"); - public GUIContent z = EditorGUIUtility.TextContent("Z"); - } - static Texts s_Texts; - - public SizeModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "SizeModule", displayName) - { - m_ToolTip = "Controls the size of each particle during its lifetime."; - } - - protected override void Init() - { - // Already initialized? - if (m_X != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_SeparateAxes = GetProperty("separateAxes"); - m_X = new SerializedMinMaxCurve(this, s_Texts.x, "curve"); - m_Y = new SerializedMinMaxCurve(this, s_Texts.y, "y", false, false, m_SeparateAxes.boolValue); - m_Z = new SerializedMinMaxCurve(this, s_Texts.z, "z", false, false, m_SeparateAxes.boolValue); - m_X.m_AllowConstant = false; - m_Y.m_AllowConstant = false; - m_Z.m_AllowConstant = false; - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - EditorGUI.BeginChangeCheck(); - bool separateAxes = GUIToggle(s_Texts.separateAxes, m_SeparateAxes); - if (EditorGUI.EndChangeCheck()) - { - // Remove old curves from curve editor - if (!separateAxes) - { - m_Y.RemoveCurveFromEditor(); - m_Z.RemoveCurveFromEditor(); - } - } - - // Keep states in sync - if (!m_X.stateHasMultipleDifferentValues) - { - m_Z.SetMinMaxState(m_X.state, separateAxes); - m_Y.SetMinMaxState(m_X.state, separateAxes); - } - - if (separateAxes) - { - m_X.m_DisplayName = s_Texts.x; - GUITripleMinMaxCurve(GUIContent.none, s_Texts.x, m_X, s_Texts.y, m_Y, s_Texts.z, m_Z, null); - } - else - { - m_X.m_DisplayName = s_Texts.size; - GUIMinMaxCurve(s_Texts.size, m_X); - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SubModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SubModuleUI.cs deleted file mode 100644 index 38efe03b59..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SubModuleUI.cs +++ /dev/null @@ -1,326 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - class SubModuleUI : ModuleUI - { - SerializedProperty m_SubEmitters; - - private int m_CheckObjectIndex = -1; - - // Keep in sync with enum in ParticleSystemCommmon.h - public enum SubEmitterType - { - None = -1, - Birth = 0, - Collision, - Death, - Trigger, - Manual, - TypesMax, - }; - - class Texts - { - public GUIContent create = EditorGUIUtility.TrTextContent("", "Create and assign a Particle System as sub emitter"); - public GUIContent inherit = EditorGUIUtility.TrTextContent("Inherit"); - - public GUIContent[] subEmitterTypes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Birth"), - EditorGUIUtility.TrTextContent("Collision"), - EditorGUIUtility.TrTextContent("Death"), - EditorGUIUtility.TrTextContent("Trigger"), - EditorGUIUtility.TrTextContent("Manual") - }; - - // Keep in sync with SubModule::InheritedProperties - public string[] propertyTypes = - { - "Color", - "Size", - "Rotation", - "Lifetime" - }; - } - private static Texts s_Texts; - - - public SubModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "SubModule", displayName) - { - m_ToolTip = L10n.Tr("Sub emission of particles. This allows each particle to emit particles in another system."); - Init(); // Init when created because we need to query if we have any subemitters referenced - } - - protected override void Init() - { - // Already initialized? - if (m_SubEmitters != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_SubEmitters = GetProperty("subEmitters"); - } - - void CreateSubEmitter(SerializedProperty objectRefProp, int index, SubEmitterType type) - { - GameObject subEmitter = m_ParticleSystemUI.m_ParticleEffectUI.CreateParticleSystem(m_ParticleSystemUI.m_ParticleSystems[0], type); - subEmitter.name = "SubEmitter" + index; - objectRefProp.objectReferenceValue = subEmitter.GetComponent(); - } - - void Update() - { - if (m_CheckObjectIndex >= 0) - { - // Wait until the ObjectSelector is closed before checking object - if (!ObjectSelector.isVisible) - { - SerializedProperty subEmitterData = m_SubEmitters.GetArrayElementAtIndex(m_CheckObjectIndex); - SerializedProperty subEmitter = subEmitterData.FindPropertyRelative("emitter"); - Object obj = subEmitter.objectReferenceValue; - ParticleSystem newSubEmitter = obj as ParticleSystem; - if (newSubEmitter != null) - { - bool validSubemitter = true; - - if (ValidateSubemitter(newSubEmitter)) - { - string errorMsg = ParticleSystemEffectUtils.CheckCircularReferences(newSubEmitter); - if (errorMsg.Length == 0) - { - // Ok there is no circular references, now check if its a child - if (!CheckIfChild(obj)) - validSubemitter = false; - } - else - { - // Circular references detected - string circularRefErrorMsg = string.Format("'{0}' could not be assigned as subemitter on '{1}' due to circular referencing!\nBacktrace: {2} \n\nReference will be removed.", newSubEmitter.gameObject.name, m_ParticleSystemUI.m_ParticleSystems[0].gameObject.name, errorMsg); - EditorUtility.DisplayDialog("Circular References Detected", circularRefErrorMsg, "Ok"); - validSubemitter = false; - } - } - else - { - validSubemitter = false; - } - - if (!validSubemitter) - { - subEmitter.objectReferenceValue = null; // remove invalid reference - m_ParticleSystemUI.ApplyProperties(); - m_ParticleSystemUI.m_ParticleEffectUI.m_Owner.Repaint(); - } - } - - // Cleanup - m_CheckObjectIndex = -1; - EditorApplication.update -= Update; - } - } - } - - internal static bool IsChild(ParticleSystem subEmitter, ParticleSystem root) - { - if (subEmitter == null || root == null) - return false; - - ParticleSystem subRoot = ParticleSystemEditorUtils.GetRoot(subEmitter); - return subRoot == root; - } - - private bool ValidateSubemitter(ParticleSystem subEmitter) - { - if (subEmitter == null) - return false; - - ParticleSystem root = ParticleSystemEditorUtils.GetRoot(m_ParticleSystemUI.m_ParticleSystems[0]); - if (root.gameObject.activeInHierarchy && !subEmitter.gameObject.activeInHierarchy) - { - string kReparentText = "The assigned sub emitter is part of a prefab and can therefore not be assigned."; - EditorUtility.DisplayDialog("Invalid Sub Emitter", kReparentText, "Ok"); - return false; - } - - if (!root.gameObject.activeInHierarchy && subEmitter.gameObject.activeInHierarchy) - { - string kReparentText = "The assigned sub emitter is part of a scene object and can therefore not be assigned to a prefab."; - EditorUtility.DisplayDialog("Invalid Sub Emitter", kReparentText, "Ok"); - return false; - } - - - return true; - } - - private bool CheckIfChild(Object subEmitter) - { - ParticleSystem root = ParticleSystemEditorUtils.GetRoot(m_ParticleSystemUI.m_ParticleSystems[0]); - ParticleSystem ps = subEmitter as ParticleSystem; - if (IsChild(ps, root)) - { - return true; - } - - string kReparentText = string.Format("The assigned sub emitter is not a child of the current root particle system GameObject: '{0}' and is therefore NOT considered a part of the current effect. Do you want to reparent it?", root.gameObject.name); - if (EditorUtility.DisplayDialog( - "Reparent GameObjects", - kReparentText, - "Yes, Reparent", - "No, Remove")) - { - if (EditorUtility.IsPersistent(subEmitter)) - { - var newGo = Object.Instantiate(subEmitter) as GameObject; - if (newGo != null) - { - newGo.transform.parent = m_ParticleSystemUI.m_ParticleSystems[0].transform; - newGo.transform.localPosition = Vector3.zero; - newGo.transform.localRotation = Quaternion.identity; - } - } - else - { - if (ps != null) - { - Undo.SetTransformParent(ps.gameObject.transform.transform, m_ParticleSystemUI.m_ParticleSystems[0].transform, "Reparent sub emitter"); - } - } - - return true; - } - else if (ps != null) - { - // Clear sub-emitters that have been deselected, to avoid having their particles left paused in the Scene View (case 946999) - ps.Clear(true); - } - - return false; - } - - private List GetSubEmitterProperties() - { - List props = new List(); - var enumerator = m_SubEmitters.GetEnumerator(); - - while (enumerator.MoveNext()) - { - SerializedProperty subEmitterData = (SerializedProperty)enumerator.Current; - props.Add(subEmitterData.FindPropertyRelative("emitter").objectReferenceValue); - } - - return props; - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - // only allow sub-emitter editing in single edit mode - if (m_ParticleSystemUI.multiEdit) - { - EditorGUILayout.HelpBox("Sub Emitter editing is only available when editing a single Particle System", MessageType.Info, true); - return; - } - - // get array of subemitters - List props = GetSubEmitterProperties(); - - // update gui - GUILayout.BeginHorizontal(GUILayout.Height(EditorGUI.kSingleLineHeight)); - GUILayout.Label("", ParticleSystemStyles.Get().label, GUILayout.ExpandWidth(true)); - GUILayout.Label(s_Texts.inherit, ParticleSystemStyles.Get().label, GUILayout.Width(120)); - GUILayout.EndHorizontal(); - for (int i = 0; i < m_SubEmitters.arraySize; i++) - { - ShowSubEmitter(i); - } - - // get new list of subemitters, so we can check for changes - List props2 = GetSubEmitterProperties(); - - // validate any new subemitters we assigned - for (int i = 0; i < Mathf.Min(props.Count, props2.Count); i++) - { - if (props[i] != props2[i]) - { - if (m_CheckObjectIndex == -1) - EditorApplication.update += Update; // ensure its not added more than once - - // We need to let the ObjectSelector finish its SendEvent and therefore delay showing dialog - m_CheckObjectIndex = i; - - // Clear sub-emitters that have been deselected, to avoid having their particles left paused in the Scene View (case 946999) - ParticleSystem ps = props[i] as ParticleSystem; - if (ps) - ps.Clear(true); - } - } - } - - private void ShowSubEmitter(int index) - { - GUILayout.BeginHorizontal(GUILayout.Height(EditorGUI.kSingleLineHeight)); - - SerializedProperty subEmitterData = m_SubEmitters.GetArrayElementAtIndex(index); - SerializedProperty subEmitter = subEmitterData.FindPropertyRelative("emitter"); - SerializedProperty type = subEmitterData.FindPropertyRelative("type"); - SerializedProperty properties = subEmitterData.FindPropertyRelative("properties"); - - GUIPopup(GUIContent.none, type, s_Texts.subEmitterTypes, GUILayout.MaxWidth(80)); - GUILayout.Label("", ParticleSystemStyles.Get().label, GUILayout.Width(4)); - GUIObject(GUIContent.none, subEmitter); - var olPlusStyle = new GUIStyle("OL Plus"); - if (subEmitter.objectReferenceValue == null) - { - GUILayout.Label("", ParticleSystemStyles.Get().label, GUILayout.Width(8)); - GUILayout.BeginVertical(GUILayout.Width(16), GUILayout.Height(olPlusStyle.fixedHeight)); - GUILayout.FlexibleSpace(); - if (GUILayout.Button(GUIContent.none, ParticleSystemStyles.Get().plus)) - { - CreateSubEmitter(subEmitter, index, (SubEmitterType)type.intValue); - } - GUILayout.FlexibleSpace(); - GUILayout.EndVertical(); - } - else - { - GUILayout.Label("", ParticleSystemStyles.Get().label, GUILayout.Width(24)); - } - GUIMask(GUIContent.none, properties, s_Texts.propertyTypes, GUILayout.Width(100)); - GUILayout.Label("", ParticleSystemStyles.Get().label, GUILayout.Width(8)); - - // add plus button to first element - if (index == 0) - { - if (GUILayout.Button(GUIContent.none, olPlusStyle, GUILayout.Width(16))) - { - m_SubEmitters.InsertArrayElementAtIndex(m_SubEmitters.arraySize); - SerializedProperty newSubEmitterData = m_SubEmitters.GetArrayElementAtIndex(m_SubEmitters.arraySize - 1); - SerializedProperty newSubEmitter = newSubEmitterData.FindPropertyRelative("emitter"); - newSubEmitter.objectReferenceValue = null; - } - } - // add minus button to all other elements - else - { - if (GUILayout.Button(GUIContent.none, new GUIStyle("OL Minus"), GUILayout.Width(16))) - m_SubEmitters.DeleteArrayElementAtIndex(index); - } - - GUILayout.EndHorizontal(); - } - - override public void UpdateCullingSupportedString(ref string text) - { - text += "\nSub Emitters module is enabled."; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs deleted file mode 100644 index 93fc7ffd3c..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs +++ /dev/null @@ -1,156 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - class TrailModuleUI : ModuleUI - { - class Texts - { - public GUIContent mode = EditorGUIUtility.TrTextContent("Mode", "Select how trails are generated on the particles."); - public GUIContent ratio = EditorGUIUtility.TrTextContent("Ratio", "Choose what proportion of particles will receive a trail."); - public GUIContent lifetime = EditorGUIUtility.TrTextContent("Lifetime", "How long each trail will last, relative to the life of the particle."); - public GUIContent minVertexDistance = EditorGUIUtility.TrTextContent("Minimum Vertex Distance", "The minimum distance each trail can travel before adding a new vertex."); - public GUIContent textureMode = EditorGUIUtility.TrTextContent("Texture Mode", "Should the U coordinate be stretched or tiled?"); - public GUIContent worldSpace = EditorGUIUtility.TrTextContent("World Space", "Trail points will be dropped in world space, even if the particle system is simulating in local space."); - public GUIContent dieWithParticles = EditorGUIUtility.TrTextContent("Die with Particles", "The trails will disappear when their owning particles die."); - public GUIContent sizeAffectsWidth = EditorGUIUtility.TrTextContent("Size affects Width", "The trails will use the particle size to control their width."); - public GUIContent sizeAffectsLifetime = EditorGUIUtility.TrTextContent("Size affects Lifetime", "The trails will use the particle size to control their lifetime."); - public GUIContent inheritParticleColor = EditorGUIUtility.TrTextContent("Inherit Particle Color", "The trails will use the particle color as their base color."); - public GUIContent colorOverLifetime = EditorGUIUtility.TrTextContent("Color over Lifetime", "The color of the trails during the lifetime of the particle they are attached to."); - public GUIContent widthOverTrail = EditorGUIUtility.TrTextContent("Width over Trail", "Select a width for the trail from its start to end vertex."); - public GUIContent colorOverTrail = EditorGUIUtility.TrTextContent("Color over Trail", "Select a color for the trail from its start to end vertex."); - public GUIContent generateLightingData = EditorGUIUtility.TrTextContent("Generate Lighting Data", "Toggle generation of normal and tangent data, for use in lit shaders."); - public GUIContent ribbonCount = EditorGUIUtility.TrTextContent("Ribbon Count", "Select how many ribbons to render throughout the Particle System."); - public GUIContent splitSubEmitterRibbons = EditorGUIUtility.TrTextContent("Split Sub Emitter Ribbons", "When used on a sub emitter, ribbons will connect particles from each parent particle independently."); - - public GUIContent[] trailModeOptions = - { - EditorGUIUtility.TrTextContent("Particles"), - EditorGUIUtility.TrTextContent("Ribbon") - }; - - public GUIContent[] textureModeOptions = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Stretch"), - EditorGUIUtility.TrTextContent("Tile"), - EditorGUIUtility.TrTextContent("DistributePerSegment"), - EditorGUIUtility.TrTextContent("RepeatPerSegment") - }; - } - private static Texts s_Texts; - - SerializedProperty m_Mode; - SerializedProperty m_Ratio; - SerializedMinMaxCurve m_Lifetime; - SerializedProperty m_MinVertexDistance; - SerializedProperty m_TextureMode; - SerializedProperty m_WorldSpace; - SerializedProperty m_DieWithParticles; - SerializedProperty m_SizeAffectsWidth; - SerializedProperty m_SizeAffectsLifetime; - SerializedProperty m_InheritParticleColor; - SerializedMinMaxGradient m_ColorOverLifetime; - SerializedMinMaxCurve m_WidthOverTrail; - SerializedMinMaxGradient m_ColorOverTrail; - SerializedProperty m_GenerateLightingData; - SerializedProperty m_RibbonCount; - SerializedProperty m_SplitSubEmitterRibbons; - - public TrailModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "TrailModule", displayName) - { - m_ToolTip = "Attach trails to the particles."; - } - - protected override void Init() - { - // Already initialized? - if (m_Ratio != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_Mode = GetProperty("mode"); - m_Ratio = GetProperty("ratio"); - m_Lifetime = new SerializedMinMaxCurve(this, s_Texts.lifetime, "lifetime"); - m_MinVertexDistance = GetProperty("minVertexDistance"); - m_TextureMode = GetProperty("textureMode"); - m_WorldSpace = GetProperty("worldSpace"); - m_DieWithParticles = GetProperty("dieWithParticles"); - m_SizeAffectsWidth = GetProperty("sizeAffectsWidth"); - m_SizeAffectsLifetime = GetProperty("sizeAffectsLifetime"); - m_InheritParticleColor = GetProperty("inheritParticleColor"); - m_ColorOverLifetime = new SerializedMinMaxGradient(this, "colorOverLifetime"); - m_WidthOverTrail = new SerializedMinMaxCurve(this, s_Texts.widthOverTrail, "widthOverTrail"); - m_ColorOverTrail = new SerializedMinMaxGradient(this, "colorOverTrail"); - m_GenerateLightingData = GetProperty("generateLightingData"); - m_RibbonCount = GetProperty("ribbonCount"); - m_SplitSubEmitterRibbons = GetProperty("splitSubEmitterRibbons"); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - ParticleSystemTrailMode mode = (ParticleSystemTrailMode)GUIPopup(s_Texts.mode, m_Mode, s_Texts.trailModeOptions); - if (!m_Mode.hasMultipleDifferentValues) - { - if (mode == ParticleSystemTrailMode.PerParticle) - { - GUIFloat(s_Texts.ratio, m_Ratio); - GUIMinMaxCurve(s_Texts.lifetime, m_Lifetime); - GUIFloat(s_Texts.minVertexDistance, m_MinVertexDistance); - GUIToggle(s_Texts.worldSpace, m_WorldSpace); - GUIToggle(s_Texts.dieWithParticles, m_DieWithParticles); - } - else - { - GUIInt(s_Texts.ribbonCount, m_RibbonCount); - GUIToggle(s_Texts.splitSubEmitterRibbons, m_SplitSubEmitterRibbons); - } - } - - GUIPopup(s_Texts.textureMode, m_TextureMode, s_Texts.textureModeOptions); - GUIToggle(s_Texts.sizeAffectsWidth, m_SizeAffectsWidth); - - if (!m_Mode.hasMultipleDifferentValues) - { - if (mode == ParticleSystemTrailMode.PerParticle) - { - GUIToggle(s_Texts.sizeAffectsLifetime, m_SizeAffectsLifetime); - } - } - - GUIToggle(s_Texts.inheritParticleColor, m_InheritParticleColor); - GUIMinMaxGradient(s_Texts.colorOverLifetime, m_ColorOverLifetime, false); - GUIMinMaxCurve(s_Texts.widthOverTrail, m_WidthOverTrail); - GUIMinMaxGradient(s_Texts.colorOverTrail, m_ColorOverTrail, false); - GUIToggle(s_Texts.generateLightingData, m_GenerateLightingData); - - // Add a warning message when no trail material is assigned, telling users where to find it - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - if (ps.trails.enabled) - { - ParticleSystemRenderer renderer = ps.GetComponent(); - if ((renderer != null) && (renderer.trailMaterial == null)) - { - EditorGUILayout.HelpBox("Assign a Trail Material in the Renderer Module", MessageType.Warning, true); - break; - } - } - } - } - - public override void UpdateCullingSupportedString(ref string text) - { - Init(); - - if (m_Mode.intValue == (int)ParticleSystemTrailMode.PerParticle) - text += "\nTrails module is enabled."; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TriggerModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TriggerModuleUI.cs deleted file mode 100644 index 702163ef90..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TriggerModuleUI.cs +++ /dev/null @@ -1,231 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - - -namespace UnityEditor -{ - class TriggerModuleUI : ModuleUI - { - // Keep in sync with TriggerModule.h - const int k_MaxNumCollisionShapes = 6; - enum OverlapOptions { Ignore = 0, Kill = 1, Callback = 2 }; - - SerializedProperty[] m_CollisionShapes = new SerializedProperty[k_MaxNumCollisionShapes]; - SerializedProperty m_Inside; - SerializedProperty m_Outside; - SerializedProperty m_Enter; - SerializedProperty m_Exit; - SerializedProperty m_RadiusScale; - SerializedProperty[] m_ShownCollisionShapes; - - static bool s_VisualizeBounds = false; - - class Texts - { - public GUIContent collisionShapes = EditorGUIUtility.TrTextContent("Colliders", "The list of collision shapes to use for the trigger."); - public GUIContent createCollisionShape = EditorGUIUtility.TrTextContent("", "Create a GameObject containing a sphere collider and assigns it to the list."); - public GUIContent inside = EditorGUIUtility.TrTextContent("Inside", "What to do for particles that are inside the collision volume."); - public GUIContent outside = EditorGUIUtility.TrTextContent("Outside", "What to do for particles that are outside the collision volume."); - public GUIContent enter = EditorGUIUtility.TrTextContent("Enter", "Triggered once when particles enter the collison volume."); - public GUIContent exit = EditorGUIUtility.TrTextContent("Exit", "Triggered once when particles leave the collison volume."); - public GUIContent radiusScale = EditorGUIUtility.TrTextContent("Radius Scale", "Scale particle bounds by this amount to get more precise collisions."); - public GUIContent visualizeBounds = EditorGUIUtility.TrTextContent("Visualize Bounds", "Render the collision bounds of the particles."); - - public GUIContent[] overlapOptions = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Ignore"), - EditorGUIUtility.TrTextContent("Kill"), - EditorGUIUtility.TrTextContent("Callback") - }; - } - private static Texts s_Texts; - - public TriggerModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "TriggerModule", displayName) - { - m_ToolTip = "Allows you to execute script code based on whether particles are inside or outside the collision shapes."; - } - - protected override void Init() - { - // Already initialized? - if (m_Inside != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - List shownCollisionShapes = new List(); - for (int i = 0; i < m_CollisionShapes.Length; ++i) - { - m_CollisionShapes[i] = GetProperty("collisionShape" + i); // Keep name in sync with transfer func in TriggerModule.h - System.Diagnostics.Debug.Assert(m_CollisionShapes[i] != null); - - // Always show the first collision shape - if (i == 0 || m_CollisionShapes[i].objectReferenceValue != null) - shownCollisionShapes.Add(m_CollisionShapes[i]); - } - - m_ShownCollisionShapes = shownCollisionShapes.ToArray(); - - m_Inside = GetProperty("inside"); - m_Outside = GetProperty("outside"); - m_Enter = GetProperty("enter"); - m_Exit = GetProperty("exit"); - m_RadiusScale = GetProperty("radiusScale"); - - s_VisualizeBounds = EditorPrefs.GetBool("VisualizeTriggerBounds", false); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - DoListOfCollisionShapesGUI(); - - GUIPopup(s_Texts.inside, m_Inside, s_Texts.overlapOptions); - GUIPopup(s_Texts.outside, m_Outside, s_Texts.overlapOptions); - GUIPopup(s_Texts.enter, m_Enter, s_Texts.overlapOptions); - GUIPopup(s_Texts.exit, m_Exit, s_Texts.overlapOptions); - GUIFloat(s_Texts.radiusScale, m_RadiusScale); - - EditorGUI.BeginChangeCheck(); - s_VisualizeBounds = GUIToggle(s_Texts.visualizeBounds, s_VisualizeBounds); - if (EditorGUI.EndChangeCheck()) - { - EditorPrefs.SetBool("VisualizeTriggerBounds", s_VisualizeBounds); - } - } - - private static GameObject CreateDefaultCollider(string name, ParticleSystem parentOfGameObject) - { - GameObject go = new GameObject(name); - if (go) - { - if (parentOfGameObject) - go.transform.parent = parentOfGameObject.transform; - go.AddComponent(); - return go; - } - return null; - } - - private void DoListOfCollisionShapesGUI() - { - // only show the list of colliders when we can edit them safely - if (m_ParticleSystemUI.multiEdit) - { - for (int shapeIndex = 0; shapeIndex < k_MaxNumCollisionShapes; shapeIndex++) - { - int hasShape = -1; - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - int shapeValue = (ps.trigger.GetCollider(shapeIndex) != null) ? 1 : 0; - if (hasShape == -1) - { - hasShape = shapeValue; - } - else if (shapeValue != hasShape) - { - EditorGUILayout.HelpBox("Collider list editing is only available when all selected systems contain the same number of colliders", MessageType.Info, true); - return; - } - } - } - } - - int buttonPressedIndex = GUIListOfFloatObjectToggleFields(s_Texts.collisionShapes, m_ShownCollisionShapes, null, s_Texts.createCollisionShape, !m_ParticleSystemUI.multiEdit); - if (buttonPressedIndex >= 0 && !m_ParticleSystemUI.multiEdit) - { - GameObject go = CreateDefaultCollider("Collider " + (buttonPressedIndex + 1), m_ParticleSystemUI.m_ParticleSystems[0]); - go.transform.localPosition = new Vector3(0, 0, 10 + buttonPressedIndex); // ensure each collider is not at same pos - m_ShownCollisionShapes[buttonPressedIndex].objectReferenceValue = go; - } - - // Minus button - Rect rect = GUILayoutUtility.GetRect(0, EditorGUI.kSingleLineHeight); //GUILayoutUtility.GetLastRect(); - rect.x = rect.xMax - kPlusAddRemoveButtonWidth * 2 - kPlusAddRemoveButtonSpacing; - rect.width = kPlusAddRemoveButtonWidth; - if (m_ShownCollisionShapes.Length > 1) - { - if (MinusButton(rect)) - { - m_ShownCollisionShapes[m_ShownCollisionShapes.Length - 1].objectReferenceValue = null; - - List shownCollisionShapes = new List(m_ShownCollisionShapes); - shownCollisionShapes.RemoveAt(shownCollisionShapes.Count - 1); - m_ShownCollisionShapes = shownCollisionShapes.ToArray(); - } - } - - // Plus button - if (m_ShownCollisionShapes.Length < k_MaxNumCollisionShapes && !m_ParticleSystemUI.multiEdit) - { - rect.x += kPlusAddRemoveButtonWidth + kPlusAddRemoveButtonSpacing; - if (PlusButton(rect)) - { - List shownCollisionShapes = new List(m_ShownCollisionShapes); - shownCollisionShapes.Add(m_CollisionShapes[shownCollisionShapes.Count]); - m_ShownCollisionShapes = shownCollisionShapes.ToArray(); - } - } - } - - override public void OnSceneViewGUI() - { - if (s_VisualizeBounds == false) - return; - - Color oldColor = Handles.color; - Handles.color = Color.green; - Matrix4x4 oldMatrix = Handles.matrix; - - Vector3[] points0 = new Vector3[20]; - Vector3[] points1 = new Vector3[20]; - Vector3[] points2 = new Vector3[20]; - - Handles.SetDiscSectionPoints(points0, Vector3.zero, Vector3.forward, Vector3.right, 360, 1.0f); - Handles.SetDiscSectionPoints(points1, Vector3.zero, Vector3.up, -Vector3.right, 360, 1.0f); - Handles.SetDiscSectionPoints(points2, Vector3.zero, Vector3.right, Vector3.up, 360, 1.0f); - - Vector3[] points = new Vector3[points0.Length + points1.Length + points2.Length]; - points0.CopyTo(points, 0); - points1.CopyTo(points, 20); - points2.CopyTo(points, 40); - - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - if (!ps.trigger.enabled) - continue; - - ParticleSystem.Particle[] particles = new ParticleSystem.Particle[ps.particleCount]; - int count = ps.GetParticles(particles); - - Matrix4x4 transform = Matrix4x4.identity; - if (ps.main.simulationSpace == ParticleSystemSimulationSpace.Local) - { - transform = ps.GetLocalToWorldMatrix(); - } - - for (int i = 0; i < count; i++) - { - ParticleSystem.Particle particle = particles[i]; - Vector3 size = particle.GetCurrentSize3D(ps); - - float radius = System.Math.Max(size.x, System.Math.Max(size.y, size.z)) * 0.5f * ps.trigger.radiusScale; - Handles.matrix = transform * Matrix4x4.TRS(particle.position, Quaternion.identity, new Vector3(radius, radius, radius)); - Handles.DrawPolyLine(points); - } - } - - Handles.color = oldColor; - Handles.matrix = oldMatrix; - } - - public override void UpdateCullingSupportedString(ref string text) - { - text += "\nTriggers module is enabled."; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/UVModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/UVModuleUI.cs deleted file mode 100644 index 02cb3bfd9b..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/UVModuleUI.cs +++ /dev/null @@ -1,215 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - class UVModuleUI : ModuleUI - { - // Keep in sync with enum in UVModule.h - enum AnimationMode { Grid = 0, Sprites = 1 }; - enum AnimationType { WholeSheet = 0, SingleRow = 1 }; - - SerializedProperty m_Mode; - SerializedMinMaxCurve m_FrameOverTime; - SerializedMinMaxCurve m_StartFrame; - SerializedProperty m_TilesX; - SerializedProperty m_TilesY; - SerializedProperty m_AnimationType; - SerializedProperty m_RandomRow; - SerializedProperty m_RowIndex; - SerializedProperty m_Sprites; - SerializedProperty m_Cycles; - SerializedProperty m_UVChannelMask; - SerializedProperty m_FlipU; - SerializedProperty m_FlipV; - - class Texts - { - public GUIContent mode = EditorGUIUtility.TrTextContent("Mode", "Animation frames can either be specified on a regular grid texture, or as a list of Sprites."); - public GUIContent frameOverTime = EditorGUIUtility.TrTextContent("Frame over Time", "Controls the uv animation frame of each particle over its lifetime. On the horisontal axis you will find the lifetime. On the vertical axis you will find the sheet index."); - public GUIContent startFrame = EditorGUIUtility.TrTextContent("Start Frame", "Phase the animation, so it starts on a frame other than 0."); - public GUIContent tiles = EditorGUIUtility.TrTextContent("Tiles", "Defines the tiling of the texture."); - public GUIContent tilesX = EditorGUIUtility.TextContent("X"); - public GUIContent tilesY = EditorGUIUtility.TextContent("Y"); - public GUIContent animation = EditorGUIUtility.TrTextContent("Animation", "Specifies the animation type: Whole Sheet or Single Row. Whole Sheet will animate over the whole texture sheet from left to right, top to bottom. Single Row will animate a single row in the sheet from left to right."); - public GUIContent randomRow = EditorGUIUtility.TrTextContent("Random Row", "If enabled, the animated row will be chosen randomly."); - public GUIContent row = EditorGUIUtility.TrTextContent("Row", "The row in the sheet which will be played."); - public GUIContent sprites = EditorGUIUtility.TrTextContent("Sprites", "The list of Sprites to be played."); - public GUIContent frame = EditorGUIUtility.TrTextContent("Frame", "The frame in the sheet which will be used."); - public GUIContent cycles = EditorGUIUtility.TrTextContent("Cycles", "Specifies how many times the animation will loop during the lifetime of the particle."); - public GUIContent uvChannelMask = EditorGUIUtility.TrTextContent("Enabled UV Channels", "Specifies which UV channels will be animated."); - public GUIContent flipU = EditorGUIUtility.TrTextContent("Flip U", "Cause some particle texture mapping to be flipped horizontally. (Set between 0 and 1, where a higher value causes more to flip)"); - public GUIContent flipV = EditorGUIUtility.TrTextContent("Flip V", "Cause some particle texture mapping to be flipped vertically. (Set between 0 and 1, where a higher value causes more to flip)"); - - public GUIContent[] modes = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Grid"), - EditorGUIUtility.TrTextContent("Sprites") - }; - - public GUIContent[] types = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Whole Sheet"), - EditorGUIUtility.TrTextContent("Single Row") - }; - } - private static Texts s_Texts; - - - public UVModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "UVModule", displayName) - { - m_ToolTip = "Particle UV animation. This allows you to specify a texture sheet (a texture with multiple tiles/sub frames) and animate or randomize over it per particle."; - } - - protected override void Init() - { - // Already initialized? - if (m_TilesX != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_Mode = GetProperty("mode"); - m_FrameOverTime = new SerializedMinMaxCurve(this, s_Texts.frameOverTime, "frameOverTime"); - m_StartFrame = new SerializedMinMaxCurve(this, s_Texts.startFrame, "startFrame"); - m_StartFrame.m_AllowCurves = false; - m_TilesX = GetProperty("tilesX"); - m_TilesY = GetProperty("tilesY"); - m_AnimationType = GetProperty("animationType"); - m_RandomRow = GetProperty("randomRow"); - m_RowIndex = GetProperty("rowIndex"); - m_Sprites = GetProperty("sprites"); - m_Cycles = GetProperty("cycles"); - m_UVChannelMask = GetProperty("uvChannelMask"); - m_FlipU = GetProperty("flipU"); - m_FlipV = GetProperty("flipV"); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - int mode = GUIPopup(s_Texts.mode, m_Mode, s_Texts.modes); - if (!m_Mode.hasMultipleDifferentValues) - { - if (mode == (int)AnimationMode.Grid) - { - GUIIntDraggableX2(s_Texts.tiles, s_Texts.tilesX, m_TilesX, s_Texts.tilesY, m_TilesY); - - int type = GUIPopup(s_Texts.animation, m_AnimationType, s_Texts.types); - if (type == (int)AnimationType.SingleRow) - { - GUIToggle(s_Texts.randomRow, m_RandomRow); - if (!m_RandomRow.boolValue) - GUIInt(s_Texts.row, m_RowIndex); - - m_FrameOverTime.m_RemapValue = (float)(m_TilesX.intValue); - m_StartFrame.m_RemapValue = (float)(m_TilesX.intValue); - } - else - { - m_FrameOverTime.m_RemapValue = (float)(m_TilesX.intValue * m_TilesY.intValue); - m_StartFrame.m_RemapValue = (float)(m_TilesX.intValue * m_TilesY.intValue); - } - } - else - { - DoListOfSpritesGUI(); - ValidateSpriteList(); - - m_FrameOverTime.m_RemapValue = (float)(m_Sprites.arraySize); - m_StartFrame.m_RemapValue = (float)(m_Sprites.arraySize); - } - - GUIMinMaxCurve(s_Texts.frameOverTime, m_FrameOverTime); - GUIMinMaxCurve(s_Texts.startFrame, m_StartFrame); - } - - GUIFloat(s_Texts.cycles, m_Cycles); - - bool disableFlipping = false; - foreach (ParticleSystem ps in m_ParticleSystemUI.m_ParticleSystems) - { - ParticleSystemRenderer renderer = ps.GetComponent(); - if ((renderer != null) && (renderer.renderMode == ParticleSystemRenderMode.Mesh)) - { - disableFlipping = true; - break; - } - } - using (new EditorGUI.DisabledScope(disableFlipping)) - { - GUIFloat(s_Texts.flipU, m_FlipU); - GUIFloat(s_Texts.flipV, m_FlipV); - } - - GUIEnumMaskUVChannelFlags(s_Texts.uvChannelMask, m_UVChannelMask); - } - - private void DoListOfSpritesGUI() - { - for (int i = 0; i < m_Sprites.arraySize; i++) - { - GUILayout.BeginHorizontal(); - - SerializedProperty spriteData = m_Sprites.GetArrayElementAtIndex(i); - SerializedProperty sprite = spriteData.FindPropertyRelative("sprite"); - GUIObject(new GUIContent(" "), sprite, typeof(Sprite)); - - // add plus button to first element - if (i == 0) - { - if (GUILayout.Button(GUIContent.none, new GUIStyle("OL Plus"), GUILayout.Width(16))) - { - m_Sprites.InsertArrayElementAtIndex(m_Sprites.arraySize); - SerializedProperty newSpriteData = m_Sprites.GetArrayElementAtIndex(m_Sprites.arraySize - 1); - SerializedProperty newSprite = newSpriteData.FindPropertyRelative("sprite"); - newSprite.objectReferenceValue = null; - } - } - // add minus button to all other elements - else - { - if (GUILayout.Button(GUIContent.none, new GUIStyle("OL Minus"), GUILayout.Width(16))) - m_Sprites.DeleteArrayElementAtIndex(i); - } - - GUILayout.EndHorizontal(); - } - } - - private void ValidateSpriteList() - { - if (m_Sprites.arraySize <= 1) - return; - - Texture texture = null; - for (int i = 0; i < m_Sprites.arraySize; i++) - { - SerializedProperty spriteData = m_Sprites.GetArrayElementAtIndex(i); - SerializedProperty prop = spriteData.FindPropertyRelative("sprite"); - Sprite sprite = prop.objectReferenceValue as Sprite; - if (sprite != null) - { - if (texture == null) - { - texture = sprite.GetTextureForPlayMode(); - } - else if (texture != sprite.GetTextureForPlayMode()) - { - EditorGUILayout.HelpBox("All Sprites must share the same texture. Either pack all Sprites into one Texture by setting the Packing Tag, or use a Multiple Mode Sprite.", MessageType.Error, true); - break; - } - else if (sprite.border != Vector4.zero) - { - EditorGUILayout.HelpBox("Sprite borders are not supported. They will be ignored.", MessageType.Warning, true); - break; - } - } - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/VelocityModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/VelocityModuleUI.cs deleted file mode 100644 index 0e287ce112..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/VelocityModuleUI.cs +++ /dev/null @@ -1,113 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class VelocityModuleUI : ModuleUI - { - SerializedMinMaxCurve m_X; - SerializedMinMaxCurve m_Y; - SerializedMinMaxCurve m_Z; - SerializedMinMaxCurve m_OrbitalX; - SerializedMinMaxCurve m_OrbitalY; - SerializedMinMaxCurve m_OrbitalZ; - SerializedMinMaxCurve m_OrbitalOffsetX; - SerializedMinMaxCurve m_OrbitalOffsetY; - SerializedMinMaxCurve m_OrbitalOffsetZ; - SerializedMinMaxCurve m_Radial; - SerializedProperty m_InWorldSpace; - SerializedMinMaxCurve m_SpeedModifier; - - class Texts - { - public GUIContent linearX = EditorGUIUtility.TextContent("Linear X|Apply linear velocity to particles."); - public GUIContent orbitalX = EditorGUIUtility.TextContent("Orbital X|Apply orbital velocity to particles, which will rotate them around the center of the system."); - public GUIContent orbitalOffsetX = EditorGUIUtility.TextContent("Offset X|Apply an offset to the center of rotation."); - public GUIContent y = EditorGUIUtility.TextContent("Y"); - public GUIContent z = EditorGUIUtility.TextContent("Z"); - public GUIContent space = EditorGUIUtility.TrTextContent("Space", "Specifies if the velocity values are in local space (rotated with the transform) or world space."); - public GUIContent speedMultiplier = EditorGUIUtility.TrTextContent("Speed Modifier", "Multiply the particle speed by this value"); - public GUIContent radial = EditorGUIUtility.TrTextContent("Radial", "Apply radial velocity to particles, which will project them out from the center of the system."); - public GUIContent linearSpace = EditorGUIUtility.TrTextContent("Space", "Specifies if the velocity values are in local space (rotated with the transform) or world space."); - public string[] spaces = { "Local", "World" }; - } - static Texts s_Texts; - - public VelocityModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) - : base(owner, o, "VelocityModule", displayName) - { - m_ToolTip = "Controls the velocity of each particle during its lifetime."; - } - - protected override void Init() - { - // Already initialized? - if (m_X != null) - return; - if (s_Texts == null) - s_Texts = new Texts(); - - m_X = new SerializedMinMaxCurve(this, s_Texts.linearX, "x", kUseSignedRange); - m_Y = new SerializedMinMaxCurve(this, s_Texts.y, "y", kUseSignedRange); - m_Z = new SerializedMinMaxCurve(this, s_Texts.z, "z", kUseSignedRange); - m_OrbitalX = new SerializedMinMaxCurve(this, s_Texts.orbitalX, "orbitalX", kUseSignedRange); - m_OrbitalY = new SerializedMinMaxCurve(this, s_Texts.y, "orbitalY", kUseSignedRange); - m_OrbitalZ = new SerializedMinMaxCurve(this, s_Texts.z, "orbitalZ", kUseSignedRange); - m_OrbitalOffsetX = new SerializedMinMaxCurve(this, s_Texts.orbitalOffsetX, "orbitalOffsetX", kUseSignedRange); - m_OrbitalOffsetY = new SerializedMinMaxCurve(this, s_Texts.y, "orbitalOffsetY", kUseSignedRange); - m_OrbitalOffsetZ = new SerializedMinMaxCurve(this, s_Texts.z, "orbitalOffsetZ", kUseSignedRange); - m_Radial = new SerializedMinMaxCurve(this, s_Texts.radial, "radial", kUseSignedRange); - m_InWorldSpace = GetProperty("inWorldSpace"); - m_SpeedModifier = new SerializedMinMaxCurve(this, s_Texts.speedMultiplier, "speedModifier", kUseSignedRange); - } - - override public void OnInspectorGUI(InitialModuleUI initial) - { - GUITripleMinMaxCurve(GUIContent.none, s_Texts.linearX, m_X, s_Texts.y, m_Y, s_Texts.z, m_Z, null); - EditorGUI.indentLevel++; - GUIBoolAsPopup(s_Texts.linearSpace, m_InWorldSpace, s_Texts.spaces); - EditorGUI.indentLevel--; - - GUITripleMinMaxCurve(GUIContent.none, s_Texts.orbitalX, m_OrbitalX, s_Texts.y, m_OrbitalY, s_Texts.z, m_OrbitalZ, null); - GUITripleMinMaxCurve(GUIContent.none, s_Texts.orbitalOffsetX, m_OrbitalOffsetX, s_Texts.y, m_OrbitalOffsetY, s_Texts.z, m_OrbitalOffsetZ, null); - EditorGUI.indentLevel++; - GUIMinMaxCurve(s_Texts.radial, m_Radial); - EditorGUI.indentLevel--; - - GUIMinMaxCurve(s_Texts.speedMultiplier, m_SpeedModifier); - } - - override public void UpdateCullingSupportedString(ref string text) - { - Init(); - - string failureReason = string.Empty; - if (!m_X.SupportsProcedural(ref failureReason)) - text += "\nVelocity over Lifetime module curve X: " + failureReason; - - failureReason = string.Empty; - if (!m_Y.SupportsProcedural(ref failureReason)) - text += "\nVelocity over Lifetime module curve Y: " + failureReason; - - failureReason = string.Empty; - if (!m_Z.SupportsProcedural(ref failureReason)) - text += "\nVelocity over Lifetime module curve Z: " + failureReason; - - failureReason = string.Empty; - if (m_SpeedModifier.state != MinMaxCurveState.k_Scalar || m_SpeedModifier.maxConstant != 1.0f) - text += "\nVelocity over Lifetime module curve Speed Multiplier is being used"; - - failureReason = string.Empty; - if (m_OrbitalX.maxConstant != 0.0f || m_OrbitalY.maxConstant != 0.0f || m_OrbitalZ.maxConstant != 0.0f) - text += "\nVelocity over Lifetime module orbital velocity is being used"; - - failureReason = string.Empty; - if (m_Radial.maxConstant != 0.0f) - text += "\nVelocity over Lifetime module radial velocity is being used"; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemStyles.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemStyles.cs deleted file mode 100644 index fde06f05b4..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemStyles.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - class ParticleSystemStyles - { - GUIStyle m_Label; - GUIStyle m_LabelBold; - GUIStyle m_EditableLabel; - GUIStyle m_EditableLabelBold; - GUIStyle m_ObjectField; - GUIStyle m_ObjectFieldBold; - GUIStyle m_NumberField; - GUIStyle m_NumberFieldBold; - GUIStyle m_ModuleHeaderStyle; - GUIStyle m_ModuleHeaderStyleBold; - GUIStyle m_PopupStyle; - GUIStyle m_PopupStyleBold; - GUIStyle m_EmitterHeaderStyle; - GUIStyle m_EffectBgStyle; - GUIStyle m_ModuleBgStyle; - GUIStyle m_Plus; - GUIStyle m_Minus; - GUIStyle m_Checkmark; - GUIStyle m_CheckmarkMixed; - GUIStyle m_MinMaxCurveStateDropDown; - GUIStyle m_Toggle; - GUIStyle m_ToggleMixed; - GUIStyle m_SelectionMarker; - GUIStyle m_ToolbarButtonLeftAlignText; - GUIStyle m_ModulePadding; - Texture2D m_WarningIcon; - - private static ParticleSystemStyles s_ParticleSystemStyles; - public static ParticleSystemStyles Get() - { - if (s_ParticleSystemStyles == null) - s_ParticleSystemStyles = new ParticleSystemStyles(); - return s_ParticleSystemStyles; - } - - public GUIStyle label { get { return EditorGUIUtility.GetBoldDefaultFont() ? m_LabelBold : m_Label; } } - public GUIStyle editableLabel { get { return EditorGUIUtility.GetBoldDefaultFont() ? m_EditableLabelBold : m_EditableLabel; } } - public GUIStyle objectField { get { return EditorGUIUtility.GetBoldDefaultFont() ? m_ObjectFieldBold : m_ObjectField; } } - public GUIStyle numberField { get { return EditorGUIUtility.GetBoldDefaultFont() ? m_NumberFieldBold : m_NumberField; } } - public GUIStyle moduleHeaderStyle { get { return EditorGUIUtility.GetBoldDefaultFont() ? m_ModuleHeaderStyleBold : m_ModuleHeaderStyle; } } - public GUIStyle popup { get { return EditorGUIUtility.GetBoldDefaultFont() ? m_PopupStyleBold : m_PopupStyle; } } - public GUIStyle emitterHeaderStyle { get { return m_EmitterHeaderStyle; } } - public GUIStyle effectBgStyle { get { return m_EffectBgStyle; } } - public GUIStyle moduleBgStyle { get { return m_ModuleBgStyle; } } - public GUIStyle plus { get { return m_Plus; } } - public GUIStyle minus { get { return m_Minus; } } - public GUIStyle checkmark { get { return m_Checkmark; } } - public GUIStyle checkmarkMixed { get { return m_CheckmarkMixed; } } - public GUIStyle minMaxCurveStateDropDown { get { return m_MinMaxCurveStateDropDown; } } - public GUIStyle toggle { get { return m_Toggle; } } - public GUIStyle toggleMixed { get { return m_ToggleMixed; } } - public GUIStyle selectionMarker { get { return m_SelectionMarker; } } - public GUIStyle toolbarButtonLeftAlignText { get { return m_ToolbarButtonLeftAlignText; } } - public GUIStyle modulePadding { get { return m_ModulePadding; } } - public Texture2D warningIcon { get { return m_WarningIcon; } } - - ParticleSystemStyles() - { - InitStyle(out m_Label, out m_LabelBold, "ShurikenLabel"); - InitStyle(out m_EditableLabel, out m_EditableLabelBold, "ShurikenEditableLabel"); - InitStyle(out m_ObjectField, out m_ObjectFieldBold, "ShurikenObjectField"); - InitStyle(out m_NumberField, out m_NumberFieldBold, "ShurikenValue"); - InitStyle(out m_ModuleHeaderStyle, out m_ModuleHeaderStyleBold, "ShurikenModuleTitle"); - InitStyle(out m_PopupStyle, out m_PopupStyleBold, "ShurikenPopUp"); - InitStyle(out m_EmitterHeaderStyle, "ShurikenEmitterTitle"); - InitStyle(out m_EmitterHeaderStyle, "ShurikenEmitterTitle"); - InitStyle(out m_EffectBgStyle, "ShurikenEffectBg"); - InitStyle(out m_ModuleBgStyle, "ShurikenModuleBg"); - InitStyle(out m_Plus, "ShurikenPlus"); - InitStyle(out m_Minus, "ShurikenMinus"); - InitStyle(out m_Checkmark, "ShurikenCheckMark"); - InitStyle(out m_CheckmarkMixed, "ShurikenCheckMarkMixed"); - InitStyle(out m_MinMaxCurveStateDropDown, "ShurikenDropdown"); - InitStyle(out m_Toggle, "ShurikenToggle"); - InitStyle(out m_ToggleMixed, "ShurikenToggleMixed"); - InitStyle(out m_SelectionMarker, "IN ThumbnailShadow"); - InitStyle(out m_ToolbarButtonLeftAlignText, "ToolbarButton"); - - // Todo: Fix in editor resources - m_EmitterHeaderStyle.clipping = TextClipping.Clip; - m_EmitterHeaderStyle.padding.right = 45; - - m_WarningIcon = EditorGUIUtility.LoadIcon("console.infoicon.sml"); - // Don't change the original as it is used in areas other than particles. - m_ToolbarButtonLeftAlignText = new GUIStyle(m_ToolbarButtonLeftAlignText); - m_ToolbarButtonLeftAlignText.alignment = TextAnchor.MiddleLeft; - - m_ModulePadding = new GUIStyle(); - m_ModulePadding.padding = new RectOffset(3, 3, 4, 2); - } - - static void InitStyle(out GUIStyle normal, string name) - { - normal = FindStyle(name); - } - - static void InitStyle(out GUIStyle normal, out GUIStyle bold, string name) - { - InitStyle(out normal, name); - bold = new GUIStyle(normal); - bold.font = EditorStyles.miniBoldFont; - } - - static GUIStyle FindStyle(string styleName) - { - // Outcomment for testing in EditorResources project - //GUISkin skin = EditorGUIUtility.LoadRequired("Builtin Skins/DarkSkin/Skins/ShurikenSkin.guiSkin") as GUISkin; - //return skin.GetStyle(styleName); - - return styleName; - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs deleted file mode 100644 index fc359c68c5..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs +++ /dev/null @@ -1,647 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -// The ParticleSystemUI displays and manages the modules of a particle system. - -namespace UnityEditor -{ - internal class ParticleSystemUI - { - public ParticleEffectUI m_ParticleEffectUI; // owner - public ModuleUI[] m_Modules; - public ParticleSystem[] m_ParticleSystems; - public SerializedObject m_ParticleSystemSerializedObject; - public SerializedObject m_RendererSerializedObject; - private static string[] s_ModuleNames; - private string m_SupportsCullingText; - private string m_SupportsCullingTextLabel; // Cached version including bullet points - - protected class Texts - { - public GUIContent addModules = new GUIContent("", "Show/Hide Modules"); - public string bulletPoint = "\u2022 "; - } - private static Texts s_Texts; - - public bool multiEdit { get { return (m_ParticleSystems != null) && (m_ParticleSystems.Length > 1); } } - - public void Init(ParticleEffectUI owner, ParticleSystem[] systems) - { - if (s_ModuleNames == null) - s_ModuleNames = GetUIModuleNames(); - if (s_Texts == null) - s_Texts = new Texts(); - - m_ParticleEffectUI = owner; - m_ParticleSystems = systems; - m_ParticleSystemSerializedObject = new SerializedObject(m_ParticleSystems); - m_RendererSerializedObject = null; - - m_SupportsCullingText = null; - - m_Modules = CreateUIModules(this, m_ParticleSystemSerializedObject); - - bool anyWithoutRenderers = m_ParticleSystems.FirstOrDefault(o => o.GetComponent() == null) != null; - if (!anyWithoutRenderers) - InitRendererUI(); - - UpdateParticleSystemInfoString(); - } - - internal ModuleUI GetParticleSystemRendererModuleUI() - { - return m_Modules.Last(); - } - - private void InitRendererUI() - { - List renderers = new List(); - foreach (ParticleSystem ps in m_ParticleSystems) - { - // Ensure we have a renderer - ParticleSystemRenderer psRenderer = ps.GetComponent(); - if (psRenderer == null) - { - ps.gameObject.AddComponent(); - } - renderers.Add(ps.GetComponent()); - } - - // Create RendererModuleUI - if (renderers.Count > 0) - { - System.Diagnostics.Debug.Assert(m_Modules.Last() == null); // If hitting this assert we have either not cleaned up the previous renderer or hitting another module - - m_RendererSerializedObject = new SerializedObject(renderers.ToArray()); - m_Modules[m_Modules.Length - 1] = new RendererModuleUI(this, m_RendererSerializedObject, s_ModuleNames.Last()); - } - } - - private void ClearRenderers() - { - // Remove renderer components - m_RendererSerializedObject = null; - foreach (ParticleSystem ps in m_ParticleSystems) - { - ParticleSystemRenderer psRenderer = ps.GetComponent(); - if (psRenderer != null) - { - Undo.DestroyObjectImmediate(psRenderer); - } - } - m_Modules[m_Modules.Length - 1] = null; - } - - public float GetEmitterDuration() - { - InitialModuleUI m = m_Modules[0] as InitialModuleUI; - if (m != null) - return m.m_LengthInSec.floatValue; - return -1.0f; - } - - public void OnGUI(float width, bool fixedWidth) - { - bool isRepaintEvent = Event.current.type == EventType.Repaint; - - // Name of current emitter - string selectedEmitterName = null; - if (m_ParticleSystems.Length > 1) - { - selectedEmitterName = "Multiple Particle Systems"; - } - else if (m_ParticleSystems.Length > 0) - { - selectedEmitterName = m_ParticleSystems[0].gameObject.name; - } - - if (fixedWidth) - { - EditorGUIUtility.labelWidth = width * 0.4f; - EditorGUILayout.BeginVertical(GUILayout.Width(width)); - } - else - { - // First make sure labelWidth is at default width, then subtract - EditorGUIUtility.labelWidth = 0; - EditorGUIUtility.labelWidth = EditorGUIUtility.labelWidth - 4; - - EditorGUILayout.BeginVertical(); - } - - { - InitialModuleUI initial = (InitialModuleUI)m_Modules[0]; - for (int i = 0; i < m_Modules.Length; ++i) - { - ModuleUI module = m_Modules[i]; - if (module == null) - continue; - - bool initialModule = (module == m_Modules[0]); - - // Skip if not visible (except initial module which should always be visible) - if (!module.visibleUI && !initialModule) - continue; - - // Module header size - GUIContent headerLabel = new GUIContent(); - Rect moduleHeaderRect; - if (initialModule) - moduleHeaderRect = GUILayoutUtility.GetRect(width, 25); - else - moduleHeaderRect = GUILayoutUtility.GetRect(width, 15); - - // Module content here to render it below the the header - if (module.foldout) - { - using (new EditorGUI.DisabledScope(!module.enabled)) - { - Rect moduleSize = EditorGUILayout.BeginVertical(ParticleSystemStyles.Get().modulePadding); - { - moduleSize.y -= 4; // pull background 'up' behind title to fill rounded corners. - moduleSize.height += 4; - GUI.Label(moduleSize, GUIContent.none, ParticleSystemStyles.Get().moduleBgStyle); - module.OnInspectorGUI(initial); - } - EditorGUILayout.EndVertical(); - } - } - - // TODO: Get Texture instead of static preview. Render Icon (below titlebar due to rounded corners) - if (initialModule) - { - // Get preview of material or mesh - ParticleSystemRenderer renderer = m_ParticleSystems[0].GetComponent(); - float iconSize = 21; - Rect iconRect = new Rect(moduleHeaderRect.x + 4, moduleHeaderRect.y + 2, iconSize, iconSize); - - if (isRepaintEvent && renderer != null) - { - bool iconRendered = false; - int instanceID = 0; - - if (!multiEdit) - { - if (renderer.renderMode == ParticleSystemRenderMode.Mesh) - { - if (renderer.mesh != null) - instanceID = renderer.mesh.GetInstanceID(); - } - else if (renderer.sharedMaterial != null) - { - instanceID = renderer.sharedMaterial.GetInstanceID(); - } - - // If the asset is dirty we ensure to get a updated one by clearing cache of temporary previews - if (EditorUtility.IsDirty(instanceID)) - AssetPreview.ClearTemporaryAssetPreviews(); - - if (instanceID != 0) - { - Texture2D icon = AssetPreview.GetAssetPreview(instanceID); - if (icon != null) - { - GUI.DrawTexture(iconRect, icon, ScaleMode.StretchToFill, true); - iconRendered = true; - } - } - } - - // Fill so we do not see the background when we have no icon (eg multi-edit) - if (!iconRendered) - { - GUI.Label(iconRect, GUIContent.none, ParticleSystemStyles.Get().moduleBgStyle); - } - } - - // Select gameObject when clicking on icon - if (!multiEdit && EditorGUI.DropdownButton(iconRect, GUIContent.none, FocusType.Passive, GUIStyle.none)) - { - // Toggle selected particle system from selection - if (EditorGUI.actionKey) - { - List newSelection = new List(); - int instanceID = m_ParticleSystems[0].gameObject.GetInstanceID(); - newSelection.AddRange(Selection.instanceIDs); - if (!newSelection.Contains(instanceID) || newSelection.Count != 1) - { - if (newSelection.Contains(instanceID)) - newSelection.Remove(instanceID); - else - newSelection.Add(instanceID); - } - - Selection.instanceIDs = newSelection.ToArray(); - } - else - { - Selection.instanceIDs = new int[0]; - Selection.activeInstanceID = m_ParticleSystems[0].gameObject.GetInstanceID(); - } - } - } - - // Button logic for enabledness (see below for UI) - Rect checkMarkRect = new Rect(moduleHeaderRect.x + 2, moduleHeaderRect.y + 1, 13, 13); - if (!initialModule && GUI.Button(checkMarkRect, GUIContent.none, GUIStyle.none)) - module.enabled = !module.enabled; - - // Button logic for plus/minus (see below for UI) - Rect plusRect = new Rect(moduleHeaderRect.x + moduleHeaderRect.width - 10, moduleHeaderRect.y + moduleHeaderRect.height - 10, 10, 10); - Rect plusRectInteract = new Rect(plusRect.x - 4, plusRect.y - 4, plusRect.width + 4, plusRect.height + 4); - Rect infoRect = new Rect(plusRect.x - 23, plusRect.y - 8, 20, 20); - - if (initialModule && EditorGUI.DropdownButton(plusRectInteract, s_Texts.addModules, FocusType.Passive, GUIStyle.none)) - ShowAddModuleMenu(); - - // Module header (last to become top most renderered) - if (!string.IsNullOrEmpty(selectedEmitterName)) - headerLabel.text = initialModule ? selectedEmitterName : module.displayName; - else - headerLabel.text = module.displayName; - headerLabel.tooltip = module.toolTip; - - bool newToggleState = module.DrawHeader(moduleHeaderRect, headerLabel); - - if (newToggleState != module.foldout) - { - switch (Event.current.button) - { - case 0: - bool newFoldoutState = !module.foldout; - if (Event.current.control) - { - foreach (var moduleUi in m_Modules) - if (moduleUi != null && moduleUi.visibleUI) - moduleUi.foldout = newFoldoutState; - } - else - { - module.foldout = newFoldoutState; - } - break; - case 1: - if (initialModule) - ShowEmitterMenu(); - else - ShowModuleMenu(i); - break; - } - } - - // Render checkmark on top (logic: see above) - if (!initialModule) - { - EditorGUI.showMixedValue = module.enabledHasMultipleDifferentValues; - GUIStyle style = EditorGUI.showMixedValue ? ParticleSystemStyles.Get().checkmarkMixed : ParticleSystemStyles.Get().checkmark; - GUI.Toggle(checkMarkRect, module.enabled, GUIContent.none, style); - EditorGUI.showMixedValue = false; - } - - // Render plus/minus on top - if (isRepaintEvent && initialModule) - GUI.Label(plusRect, GUIContent.none, ParticleSystemStyles.Get().plus); - - if (initialModule && !string.IsNullOrEmpty(m_SupportsCullingTextLabel)) - { - var supportsCullingText = new GUIContent("", ParticleSystemStyles.Get().warningIcon, m_SupportsCullingTextLabel); - GUI.Label(infoRect, supportsCullingText); - } - - GUILayout.Space(1); // dist to next module - } // foreach module - GUILayout.Space(-1); - } - EditorGUILayout.EndVertical(); // end fixed moduleWidth - - // Apply the property, handle undo - ApplyProperties(); - } - - public void OnSceneViewGUI() - { - if (m_Modules == null) - return; - - // Render bounds - if (ParticleEffectUI.m_ShowBounds) - { - foreach (ParticleSystem ps in m_ParticleSystems) - { - if (multiEdit) - ShowBounds(ParticleSystemEditorUtils.GetRoot(ps)); - else - ShowBounds(ps); - } - } - - UpdateProperties(); - - foreach (var module in m_Modules) - { - if (module == null || !module.visibleUI || !module.enabled) - continue; - - if (module.foldout) - { - module.OnSceneViewGUI(); - } - } - // Apply the property, handle undo - ApplyProperties(); - } - - private void ShowBounds(ParticleSystem ps) - { - if (ps.particleCount > 0) - { - ParticleSystemRenderer particleSystemRenderer = ps.GetComponent(); - - var oldCol = Handles.color; - Handles.color = Color.yellow; - var worldBounds = particleSystemRenderer.bounds; - Handles.DrawWireCube(worldBounds.center, worldBounds.size); - Handles.color = oldCol; - } - - // In multi-edit, children are not stored, so render thir bounds manually - if (multiEdit) - { - ParticleSystem[] children = ps.transform.GetComponentsInChildren(); - foreach (ParticleSystem child in children) - { - if (child != ps) - { - bool alreadySelected = m_ParticleSystems.FirstOrDefault(o => ParticleSystemEditorUtils.GetRoot(o) == child) != null; - if (!alreadySelected) - ShowBounds(child); - } - } - } - } - - public void ApplyProperties() - { - bool hasModifiedProperties = m_ParticleSystemSerializedObject.hasModifiedProperties; - - // Check the system was not destroyed such as by an Undo operation. - if (m_ParticleSystemSerializedObject.targetObject != null) - m_ParticleSystemSerializedObject.ApplyModifiedProperties(); - if (hasModifiedProperties) - { - // Resimulate - foreach (ParticleSystem ps in m_ParticleSystems) - { - ParticleSystem root = ParticleSystemEditorUtils.GetRoot(ps); - if (!ParticleEffectUI.IsStopped(root) && ParticleSystemEditorUtils.resimulation) - ParticleSystemEditorUtils.PerformCompleteResimulation(); - } - - // Refresh procedural supported string - UpdateParticleSystemInfoString(); - } - if (m_RendererSerializedObject != null && m_RendererSerializedObject.targetObject != null) - m_RendererSerializedObject.ApplyModifiedProperties(); - } - - void UpdateParticleSystemInfoString() - { - string supportsCullingText = ""; - foreach (var module in m_Modules) - { - if (module == null || !module.visibleUI || !module.enabled) - continue; - - module.UpdateCullingSupportedString(ref supportsCullingText); - } - - if (supportsCullingText != string.Empty) - { - if (supportsCullingText != m_SupportsCullingText || m_SupportsCullingTextLabel == null) - { - m_SupportsCullingText = supportsCullingText; - m_SupportsCullingTextLabel = "Automatic culling is disabled because: " + supportsCullingText.Replace("\n", "\n" + s_Texts.bulletPoint); - } - } - else - { - m_SupportsCullingText = null; - m_SupportsCullingTextLabel = null; - } - } - - public void UpdateProperties() - { - // Check the system was not destroyed such as by an Undo operation. - if (m_ParticleSystemSerializedObject.targetObject != null) - m_ParticleSystemSerializedObject.UpdateIfRequiredOrScript(); - if (m_RendererSerializedObject != null && m_RendererSerializedObject.targetObject != null) - m_RendererSerializedObject.UpdateIfRequiredOrScript(); - } - - void ResetModules() - { - // Reset all - foreach (var module in m_Modules) - if (module != null) - { - module.enabled = false; - if (!ParticleEffectUI.GetAllModulesVisible()) - module.visibleUI = false; - } - - // Default setup has a renderer - if (m_Modules.Last() == null) - InitRendererUI(); - - // Default setup has shape, emission and renderer - int[] defaultEnabledModulesIndicies = { 1, 2, m_Modules.Length - 1 }; - for (int i = 0; i < defaultEnabledModulesIndicies.Length; ++i) - { - int moduleIndex = defaultEnabledModulesIndicies[i]; - if (m_Modules[moduleIndex] != null) - { - m_Modules[moduleIndex].enabled = true; - m_Modules[moduleIndex].visibleUI = true; - } - } - } - - void ShowAddModuleMenu() - { - // Now create the menu, add items and show it - GenericMenu menu = new GenericMenu(); - for (int i = 0; i < s_ModuleNames.Length; ++i) - { - if (m_Modules[i] == null || !m_Modules[i].visibleUI) - menu.AddItem(new GUIContent(s_ModuleNames[i]), false, AddModuleCallback, i); - else - menu.AddDisabledItem(new GUIContent(s_ModuleNames[i])); - } - - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Show All Modules"), ParticleEffectUI.GetAllModulesVisible(), AddModuleCallback, 10000); - menu.ShowAsContext(); - Event.current.Use(); - } - - void AddModuleCallback(object obj) - { - int index = (int)obj; - if (index >= 0 && index < m_Modules.Length) - { - if (index == m_Modules.Length - 1) - { - InitRendererUI(); - } - else - { - m_Modules[index].enabled = true; - m_Modules[index].foldout = true; - } - } - else - { - m_ParticleEffectUI.SetAllModulesVisible(!ParticleEffectUI.GetAllModulesVisible()); - } - ApplyProperties(); - } - - void ModuleMenuCallback(object obj) - { - int moduleIndex = (int)obj; - bool isRendererModule = (moduleIndex == m_Modules.Length - 1); - if (isRendererModule) - { - ClearRenderers(); - } - else - { - if (!ParticleEffectUI.GetAllModulesVisible()) - m_Modules[moduleIndex].visibleUI = false; - - m_Modules[moduleIndex].enabled = false; - } - } - - void ShowModuleMenu(int moduleIndex) - { - // Now create the menu, add items and show it - GenericMenu menu = new GenericMenu(); - - if (!ParticleEffectUI.GetAllModulesVisible()) - menu.AddItem(EditorGUIUtility.TrTextContent("Remove"), false, ModuleMenuCallback, moduleIndex); - else - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Remove")); // Do not allow remove module when always show modules is enabled - menu.ShowAsContext(); - Event.current.Use(); - } - - void EmitterMenuCallback(object obj) - { - int userData = (int)obj; - switch (userData) - { - case 0: - m_ParticleEffectUI.CreateParticleSystem(m_ParticleSystems[0], SubModuleUI.SubEmitterType.None); - break; - - case 1: - ResetModules(); - break; - - case 2: - EditorGUIUtility.PingObject(m_ParticleSystems[0]); - break; - - default: - System.Diagnostics.Debug.Assert("Enum not handled!".Length == 0); - break; - } - } - - void ShowEmitterMenu() - { - // Now create the menu, add items and show it - GenericMenu menu = new GenericMenu(); - - menu.AddItem(EditorGUIUtility.TrTextContent("Show Location"), false, EmitterMenuCallback, 2); - menu.AddSeparator(""); - if (m_ParticleSystems[0].gameObject.activeInHierarchy) - menu.AddItem(EditorGUIUtility.TrTextContent("Create Particle System"), false, EmitterMenuCallback, 0); - else - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Create new Particle System")); - - menu.AddItem(EditorGUIUtility.TrTextContent("Reset"), false, EmitterMenuCallback, 1); - menu.ShowAsContext(); - Event.current.Use(); - } - - private static ModuleUI[] CreateUIModules(ParticleSystemUI e, SerializedObject so) - { - int index = 0; - // Order should match GetUIModuleNames - return new ModuleUI[] { - new InitialModuleUI(e, so, s_ModuleNames[index++]), - new EmissionModuleUI(e, so, s_ModuleNames[index++]), - new ShapeModuleUI(e, so, s_ModuleNames[index++]), - new VelocityModuleUI(e, so, s_ModuleNames[index++]), - new ClampVelocityModuleUI(e, so, s_ModuleNames[index++]), - new InheritVelocityModuleUI(e, so, s_ModuleNames[index++]), - new ForceModuleUI(e, so, s_ModuleNames[index++]), - new ColorModuleUI(e, so, s_ModuleNames[index++]), - new ColorByVelocityModuleUI(e, so, s_ModuleNames[index++]), - new SizeModuleUI(e, so, s_ModuleNames[index++]), - new SizeByVelocityModuleUI(e, so, s_ModuleNames[index++]), - new RotationModuleUI(e, so, s_ModuleNames[index++]), - new RotationByVelocityModuleUI(e, so, s_ModuleNames[index++]), - new ExternalForcesModuleUI(e, so, s_ModuleNames[index++]), - new NoiseModuleUI(e, so, s_ModuleNames[index++]), - new CollisionModuleUI(e, so, s_ModuleNames[index++]), - new TriggerModuleUI(e, so, s_ModuleNames[index++]), - new SubModuleUI(e, so, s_ModuleNames[index++]), - new UVModuleUI(e, so, s_ModuleNames[index++]), - new LightsModuleUI(e, so, s_ModuleNames[index++]), - new TrailModuleUI(e, so, s_ModuleNames[index++]), - new CustomDataModuleUI(e, so, s_ModuleNames[index++]), - null, // RendererModule is created separately in InitRendererUI (it can be added/removed) - }; - } - - // Names used when adding modules from a drop list - public static string[] GetUIModuleNames() - { - // Order should match GetUIModules - return new string[] { - "", - L10n.Tr("Emission"), - L10n.Tr("Shape"), - L10n.Tr("Velocity over Lifetime"), - L10n.Tr("Limit Velocity over Lifetime"), - L10n.Tr("Inherit Velocity"), - L10n.Tr("Force over Lifetime"), - L10n.Tr("Color over Lifetime"), - L10n.Tr("Color by Speed"), - L10n.Tr("Size over Lifetime"), - L10n.Tr("Size by Speed"), - L10n.Tr("Rotation over Lifetime"), - L10n.Tr("Rotation by Speed"), - L10n.Tr("External Forces"), - L10n.Tr("Noise"), - L10n.Tr("Collision"), - L10n.Tr("Triggers"), - L10n.Tr("Sub Emitters"), - L10n.Tr("Texture Sheet Animation"), - L10n.Tr("Lights"), - L10n.Tr("Trails"), - L10n.Tr("Custom Data"), - L10n.Tr("Renderer") - }; - } - } // class ParticleSystemUI -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemWindow.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemWindow.cs deleted file mode 100644 index 414fe0686f..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemWindow.cs +++ /dev/null @@ -1,312 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using System.IO; - -namespace UnityEditor -{ - internal class ParticleSystemWindow : EditorWindow, ParticleEffectUIOwner - { - static ParticleSystemWindow s_Instance; - - ParticleSystem m_Target; - ParticleEffectUI m_ParticleEffectUI; - bool m_IsVisible; - - private static GUIContent[] s_Icons; - - class Texts - { - public GUIContent lockParticleSystem = new GUIContent("", "Lock the current selected Particle System"); - public GUIContent previewAll = EditorGUIUtility.TrTextContent("Simulate All", "Simulate all particle systems that have Play On Awake set"); - } - static Texts s_Texts; - - public Editor customEditor { get; set; } - - static public void CreateWindow() - { - s_Instance = EditorWindow.GetWindow(); - s_Instance.titleContent = EditorGUIUtility.TrTextContent("Particle Effect"); - s_Instance.minSize = ParticleEffectUI.GetMinSize(); - } - - internal static ParticleSystemWindow GetInstance() - { - return s_Instance; - } - - internal bool IsVisible() - { - return m_IsVisible; - } - - // Prevent created from outside - private ParticleSystemWindow() - { - } - - void OnEnable() - { - s_Instance = this; - - m_Target = null; // Ensure we recreate EffectUI after script reloads - ParticleEffectUI.m_VerticalLayout = EditorPrefs.GetBool("ShurikenVerticalLayout", false); - - // Get notified when hierarchy- or project window has changes so we can detect if particle systems have been dragged in or out. - EditorApplication.hierarchyChanged += OnHierarchyOrProjectWindowWasChanged; - EditorApplication.projectChanged += OnHierarchyOrProjectWindowWasChanged; - SceneView.onSceneGUIDelegate += OnSceneViewGUI; - EditorApplication.pauseStateChanged += OnPauseStateChanged; - EditorApplication.playModeStateChanged += OnPlayModeStateChanged; - Undo.undoRedoPerformed += UndoRedoPerformed; - - autoRepaintOnSceneChange = false; - } - - void OnDisable() - { - SceneView.onSceneGUIDelegate -= OnSceneViewGUI; - EditorApplication.projectChanged -= OnHierarchyOrProjectWindowWasChanged; - EditorApplication.hierarchyChanged -= OnHierarchyOrProjectWindowWasChanged; - EditorApplication.pauseStateChanged -= OnPauseStateChanged; - EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; - Undo.undoRedoPerformed -= UndoRedoPerformed; - - - Clear(); - - if (s_Instance == this) - s_Instance = null; - } - - internal void Clear() - { - m_Target = null; - if (m_ParticleEffectUI != null) - { - m_ParticleEffectUI.Clear(); - m_ParticleEffectUI = null; - } - } - - void OnPauseStateChanged(PauseState state) - { - Repaint(); - } - - void OnPlayModeStateChanged(PlayModeStateChange state) - { - // Need to refresh because UpdateAll changes state - Repaint(); - } - - void UndoRedoPerformed() - { - if (m_ParticleEffectUI != null) - m_ParticleEffectUI.UndoRedoPerformed(); - Repaint(); - } - - private void OnHierarchyOrProjectWindowWasChanged() - { - InitEffectUI(); - } - - void OnBecameVisible() - { - if (m_IsVisible) - return; - - m_IsVisible = true; - - InitEffectUI(); - - SceneView.RepaintAll(); - InspectorWindow.RepaintAllInspectors(); - } - - void OnBecameInvisible() - { - m_IsVisible = false; - - Clear(); - - SceneView.RepaintAll(); - InspectorWindow.RepaintAllInspectors(); - } - - void OnSelectionChange() - { - InitEffectUI(); - Repaint(); - } - - void InitEffectUI() - { - if (!m_IsVisible) - return; - - // Use locked particle system if set otherwise check selected gameobject - ParticleSystem target = ParticleSystemEditorUtils.lockedParticleSystem; - if (target == null && Selection.activeGameObject != null) - target = Selection.activeGameObject.GetComponent(); - - m_Target = target; - if (m_Target != null) - { - if (m_ParticleEffectUI == null) - m_ParticleEffectUI = new ParticleEffectUI(this); - - if (m_ParticleEffectUI.InitializeIfNeeded(new ParticleSystem[] { m_Target })) - Repaint(); - } - - // Cleanup if needed - if (m_Target == null && m_ParticleEffectUI != null) - { - Clear(); - Repaint(); - SceneView.RepaintAll(); - GameView.RepaintAll(); - } - } - - void Awake() - { - } - - void DoToolbarGUI() - { - GUILayout.BeginHorizontal("Toolbar"); - - using (new EditorGUI.DisabledScope(m_ParticleEffectUI == null)) - { - if (!EditorApplication.isPlaying) - { - bool isPlaying = false; - - if (m_ParticleEffectUI != null) - { - isPlaying = m_ParticleEffectUI.IsPlaying(); - } - - if (GUILayout.Button(isPlaying ? ParticleEffectUI.texts.pause : ParticleEffectUI.texts.play, "ToolbarButton", GUILayout.Width(65))) - { - if (m_ParticleEffectUI != null) - { - if (isPlaying) - m_ParticleEffectUI.Pause(); - else - m_ParticleEffectUI.Play(); - } - Repaint(); // we switch texts - } - - if (GUILayout.Button(ParticleEffectUI.texts.stop, "ToolbarButton")) - if (m_ParticleEffectUI != null) - m_ParticleEffectUI.Stop(); - } - else - { - // In play mode we have pulse play behavior - if (GUILayout.Button(ParticleEffectUI.texts.play, "ToolbarButton", GUILayout.Width(65))) - { - if (m_ParticleEffectUI != null) - { - m_ParticleEffectUI.Stop(); - m_ParticleEffectUI.Play(); - } - } - if (GUILayout.Button(ParticleEffectUI.texts.stop, "ToolbarButton")) - { - if (m_ParticleEffectUI != null) - m_ParticleEffectUI.Stop(); - } - } - - GUILayout.FlexibleSpace(); - - bool isShowOnlySelected = m_ParticleEffectUI != null ? m_ParticleEffectUI.IsShowOnlySelectedMode() : false; - bool newState = GUILayout.Toggle(isShowOnlySelected, isShowOnlySelected ? "Show: Selected" : "Show: All", ParticleSystemStyles.Get().toolbarButtonLeftAlignText, GUILayout.Width(100)); - if (newState != isShowOnlySelected && m_ParticleEffectUI != null) - m_ParticleEffectUI.SetShowOnlySelectedMode(newState); - - // Resimulation toggle - ParticleSystemEditorUtils.resimulation = GUILayout.Toggle(ParticleSystemEditorUtils.resimulation, ParticleEffectUI.texts.resimulation, "ToolbarButton"); - - // Bounds toggle - ParticleEffectUI.m_ShowBounds = GUILayout.Toggle(ParticleEffectUI.m_ShowBounds, ParticleEffectUI.texts.showBounds, "ToolbarButton"); - - // Editor layout - if (GUILayout.Button(ParticleEffectUI.m_VerticalLayout ? s_Icons[0] : s_Icons[1], "ToolbarButton")) - { - ParticleEffectUI.m_VerticalLayout = !ParticleEffectUI.m_VerticalLayout; - EditorPrefs.SetBool("ShurikenVerticalLayout", ParticleEffectUI.m_VerticalLayout); - { - Clear(); - } - } - - // Lock toggle - GUILayout.BeginVertical(); - GUILayout.Space(3); - ParticleSystem lockedParticleSystem = ParticleSystemEditorUtils.lockedParticleSystem; - bool isLocked = lockedParticleSystem != null; - bool newLocked = GUILayout.Toggle(isLocked, s_Texts.lockParticleSystem, "IN LockButton"); - if (isLocked != newLocked) - { - if (m_ParticleEffectUI != null && m_Target != null) - { - if (newLocked) - ParticleSystemEditorUtils.lockedParticleSystem = m_Target; - else - ParticleSystemEditorUtils.lockedParticleSystem = null; - } - } - GUILayout.EndVertical(); - } - - GUILayout.EndHorizontal(); - } - - void OnGUI() - { - if (s_Texts == null) - s_Texts = new Texts(); - - if (s_Icons == null) - s_Icons = new GUIContent[] { EditorGUIUtility.IconContent("HorizontalSplit"), EditorGUIUtility.IconContent("VerticalSplit") }; - - if (m_Target == null && (Selection.activeGameObject != null || ParticleSystemEditorUtils.lockedParticleSystem != null)) - { - InitEffectUI(); - } - - DoToolbarGUI(); - - if (m_Target != null && m_ParticleEffectUI != null) - m_ParticleEffectUI.OnGUI(); - } - - public void OnSceneViewGUI(SceneView sceneView) - { - if (!m_IsVisible) - return; - - if (m_ParticleEffectUI != null) - { - m_ParticleEffectUI.OnSceneViewGUI(); - } - } - - void OnDidOpenScene() - { - Repaint(); - } - } // ParticleSystemWindow -} // UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/ScriptBindings/ParticleSystemEditor.bindings.cs b/Editor/Mono/ParticleSystemEditor/ScriptBindings/ParticleSystemEditor.bindings.cs deleted file mode 100644 index 3d2aca1d8c..0000000000 --- a/Editor/Mono/ParticleSystemEditor/ScriptBindings/ParticleSystemEditor.bindings.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [NativeHeader("Runtime/ParticleSystem/ParticleSystem.h")] - [NativeHeader("Editor/Src/ParticleSystem/ParticleSystemEditor.h")] - [NativeHeader("ParticleSystemScriptingClasses.h")] - [StaticAccessor("ParticleSystemEditor", StaticAccessorType.DoubleColon)] - internal static class ParticleSystemEditorUtils - { - internal extern static float simulationSpeed { get; set; } - internal extern static float playbackTime { get; set; } - internal extern static bool playbackIsScrubbing { get; set; } - internal extern static bool playbackIsPlaying { get; set; } - internal extern static bool playbackIsPaused { get; set; } - internal extern static bool resimulation { get; set; } - internal extern static UInt32 previewLayers { get; set; } - internal extern static bool renderInSceneView { get; set; } - internal extern static ParticleSystem lockedParticleSystem { get; set; } - - [NativeName("SetPerformCompleteResimulation")] - extern internal static void PerformCompleteResimulation(); - - // Returns the root of the hierarchy of Particle Systems starting from 'ps'. - public static ParticleSystem GetRoot(ParticleSystem ps) - { - if (ps == null) - return null; - - Transform rootTransform = ps.transform; - while (rootTransform.parent && rootTransform.parent.gameObject.GetComponent() != null) - rootTransform = rootTransform.parent; - - return rootTransform.gameObject.GetComponent(); - } - } - - [NativeHeader("Runtime/ParticleSystem/ParticleSystem.h")] - [NativeHeader("Editor/Src/ParticleSystem/ParticleSystemEffect.h")] - [StaticAccessor("ParticleSystemEffect", StaticAccessorType.DoubleColon)] - internal static class ParticleSystemEffectUtils - { - extern internal static string CheckCircularReferences(ParticleSystem subEmitter); - - [NativeName("StopAndClearActive")] - extern internal static void StopEffect(); - } -} diff --git a/Editor/Mono/ParticleSystemEditor/SerializedMinMaxColor.cs b/Editor/Mono/ParticleSystemEditor/SerializedMinMaxColor.cs deleted file mode 100644 index 607fd4f501..0000000000 --- a/Editor/Mono/ParticleSystemEditor/SerializedMinMaxColor.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - class SerializedMinMaxColor - { - public SerializedProperty maxColor; - public SerializedProperty minColor; - public SerializedProperty minMax; - - public SerializedMinMaxColor(SerializedModule m) - { - Init(m, "curve"); - } - - public SerializedMinMaxColor(SerializedModule m, string name) - { - Init(m, name); - } - - void Init(SerializedModule m, string name) - { - maxColor = m.GetProperty(name, "maxColor"); - minColor = m.GetProperty(name, "minColor"); - minMax = m.GetProperty(name, "minMax"); - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/SerializedMinMaxCurve.cs b/Editor/Mono/ParticleSystemEditor/SerializedMinMaxCurve.cs deleted file mode 100644 index 79a6d7d05a..0000000000 --- a/Editor/Mono/ParticleSystemEditor/SerializedMinMaxCurve.cs +++ /dev/null @@ -1,316 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor -{ - // Must be in sync with ParticleSystemCurves.h - internal enum MinMaxCurveState - { - k_Scalar = 0, - k_Curve = 1, - k_TwoCurves = 2, - k_TwoScalars = 3 - }; - - internal class SerializedMinMaxCurve - { - public SerializedProperty rootProperty; - public SerializedProperty scalar; - public SerializedProperty minScalar; - public SerializedProperty maxCurve; - public SerializedProperty minCurve; - private SerializedProperty minMaxState; - - public ModuleUI m_Module; // Module that owns this SerializedMinMaxCurve - private string m_Name; // Curve name. Used for creating unique name based on ParticleSystem name + Module name + m_Name - public GUIContent m_DisplayName; - private bool m_SignedRange; // True if curve can have negative values - public float m_DefaultCurveScalar; // Used when switching to curve from scalar and scalar is 0. Ensures a valid y axis range (must be positive) - public float m_RemapValue; // Used for remap UI values e.g for rotation: state is in radians but we want UI to show it in degrees - public bool m_AllowConstant; - public bool m_AllowRandom; - public bool m_AllowCurves; - - public SerializedMinMaxCurve(ModuleUI m, GUIContent displayName) - { - Init(m, displayName, "curve", false, false, true); - } - - public SerializedMinMaxCurve(ModuleUI m, GUIContent displayName, string name) - { - Init(m, displayName, name, false, false, true); - } - - public SerializedMinMaxCurve(ModuleUI m, GUIContent displayName, bool signedRange) - { - Init(m, displayName, "curve", signedRange, false, true); - } - - public SerializedMinMaxCurve(ModuleUI m, GUIContent displayName, string name, bool signedRange) - { - Init(m, displayName, name, signedRange, false, true); - } - - public SerializedMinMaxCurve(ModuleUI m, GUIContent displayName, string name, bool signedRange, bool useProp0) - { - Init(m, displayName, name, signedRange, useProp0, true); - } - - public SerializedMinMaxCurve(ModuleUI m, GUIContent displayName, string name, bool signedRange, bool useProp0, bool addCurveIfNeeded) - { - Init(m, displayName, name, signedRange, useProp0, addCurveIfNeeded); - } - - void Init(ModuleUI m, GUIContent displayName, string uniqueName, bool signedRange, bool useProp0, bool addCurveIfNeeded) - { - m_Module = m; - m_DisplayName = displayName; - m_Name = uniqueName; - m_SignedRange = signedRange; - m_RemapValue = 1.0f; - m_DefaultCurveScalar = 1.0f; - m_AllowConstant = true; - m_AllowRandom = true; - m_AllowCurves = true; - - rootProperty = useProp0 ? m.GetProperty0(m_Name) : m.GetProperty(m_Name); - scalar = useProp0 ? m.GetProperty0(m_Name, "scalar") : m.GetProperty(m_Name, "scalar"); - minScalar = useProp0 ? m.GetProperty0(m_Name, "minScalar") : m.GetProperty(m_Name, "minScalar"); - maxCurve = useProp0 ? m.GetProperty0(m_Name, "maxCurve") : m.GetProperty(m_Name, "maxCurve"); - minCurve = useProp0 ? m.GetProperty0(m_Name, "minCurve") : m.GetProperty(m_Name, "minCurve"); - minMaxState = useProp0 ? m.GetProperty0(m_Name, "minMaxState") : m.GetProperty(m_Name, "minMaxState"); - - // Reconstruct added curves when we initialize - if (addCurveIfNeeded) - { - if (state == MinMaxCurveState.k_Curve || state == MinMaxCurveState.k_TwoCurves) - { - if (m_Module.m_ParticleSystemUI.m_ParticleEffectUI.IsParticleSystemUIVisible(m_Module.m_ParticleSystemUI)) - m.GetParticleSystemCurveEditor().AddCurveDataIfNeeded(GetUniqueCurveName(), CreateCurveData(Color.black)); - } - } - m.AddToModuleCurves(maxCurve); // It is enough just to add max - } - - public MinMaxCurveState state - { - get { return (MinMaxCurveState)minMaxState.intValue; } - set { SetMinMaxState(value, true); } - } - - public bool stateHasMultipleDifferentValues - { - get { return minMaxState.hasMultipleDifferentValues; } - } - - public bool signedRange - { - get { return m_SignedRange; } - } - - public float maxConstant - { - get - { - return scalar.floatValue; - } - - set - { - if (!signedRange) - value = Mathf.Max(value, 0f); - - scalar.floatValue = value; - } - } - - public float minConstant - { - get - { - return minScalar.floatValue; - } - - set - { - if (!signedRange) - value = Mathf.Max(value, 0f); - - minScalar.floatValue = value; - } - } - - // Callback for Curve Editor to get axis labels - public Vector2 GetAxisScalars() - { - return new Vector2(m_Module.GetXAxisScalar(), scalar.floatValue * m_RemapValue); - } - - // Callback for Curve Editor to set axis labels back - public void SetAxisScalars(Vector2 axisScalars) - { - // X axis: TODO: We do not support changing the X values in the curve editor yet - //m_Module.SetXAxisScalar (axisScalars.x); - - // Y axis: - float remap = (m_RemapValue == 0.0f) ? 1.0f : m_RemapValue; - scalar.floatValue = (axisScalars.y / remap); - } - - public void RemoveCurveFromEditor() - { - ParticleSystemCurveEditor sce = m_Module.GetParticleSystemCurveEditor(); - if (sce.IsAdded(GetMinCurve(), maxCurve)) - sce.RemoveCurve(GetMinCurve(), maxCurve); - } - - public bool OnCurveAreaMouseDown(int button, Rect drawRect, Rect curveRanges) - { - if (button == 0) - { - ToggleCurveInEditor(); - return true; - } - - if (button == 1) - { - SerializedProperty minCurve = GetMinCurve(); - AnimationCurveContextMenu.Show(drawRect, - maxCurve != null ? maxCurve.Copy() : null, - minCurve != null ? minCurve.Copy() : null, - scalar != null ? scalar.Copy() : null, - curveRanges, m_Module.GetParticleSystemCurveEditor()); - return true; - } - - return false; - } - - public ParticleSystemCurveEditor.CurveData CreateCurveData(Color color) - { - System.Diagnostics.Debug.Assert(state != MinMaxCurveState.k_Scalar); // We should not create curve data for scalars - - return new ParticleSystemCurveEditor.CurveData(GetUniqueCurveName(), m_DisplayName, GetMinCurve(), maxCurve, color, m_SignedRange, GetAxisScalars, SetAxisScalars, m_Module.foldout); - } - - SerializedProperty GetMinCurve() - { - return state == MinMaxCurveState.k_TwoCurves ? minCurve : null; - } - - public void ToggleCurveInEditor() - { - ParticleSystemCurveEditor sce = m_Module.GetParticleSystemCurveEditor(); - if (sce.IsAdded(GetMinCurve(), maxCurve)) - sce.RemoveCurve(GetMinCurve(), maxCurve); - else - sce.AddCurve(CreateCurveData(sce.GetAvailableColor())); - } - - public void SetMinMaxState(MinMaxCurveState newState, bool addToCurveEditor) - { - if (newState == state) - return; - - MinMaxCurveState oldState = state; - ParticleSystemCurveEditor sce = m_Module.GetParticleSystemCurveEditor(); - - if (sce.IsAdded(GetMinCurve(), maxCurve)) - { - sce.RemoveCurve(GetMinCurve(), maxCurve); - } - - switch (newState) - { - case MinMaxCurveState.k_Curve: SetCurveRequirements(); break; - case MinMaxCurveState.k_TwoCurves: SetCurveRequirements(); break; - } - - // Assign state AFTER matching data to new state AND removing curve from curveEditor since it uses current 'state' - minMaxState.intValue = (int)newState; - - if (addToCurveEditor) - { - // Add curve to CurveEditor if needed - // Keep added to the editor if it was added before - switch (newState) - { - case MinMaxCurveState.k_TwoCurves: - case MinMaxCurveState.k_Curve: - sce.AddCurve(CreateCurveData(sce.GetAvailableColor())); - break; - case MinMaxCurveState.k_Scalar: - case MinMaxCurveState.k_TwoScalars: - // Scalar do not add anything to the curve editor - break; - default: - Debug.LogError("Unhandled enum value"); - break; - } - } - - // Ensure we draw new icons for properties - UnityEditorInternal.AnimationCurvePreviewCache.ClearCache(); - } - - void SetCurveRequirements() - { - // Abs negative values if we change to curve mode (in curve mode the sign is transfered to the curve) - scalar.floatValue = Mathf.Abs(scalar.floatValue); - - // Ensure proper y-axis value (0 does not create a valid range) - if (scalar.floatValue == 0) - scalar.floatValue = m_DefaultCurveScalar; - } - - public string GetUniqueCurveName() - { - return SerializedModule.Concat(m_Module.GetUniqueModuleName(m_Module.serializedObject.targetObject), m_Name); - } - - static bool AnimationCurveSupportsProcedural(AnimationCurve curve, ref string failureReason) - { - switch (AnimationUtility.IsValidPolynomialCurve(curve)) - { - case AnimationUtility.PolynomialValid.Valid: - return true; - case AnimationUtility.PolynomialValid.InvalidPreWrapMode: - failureReason = "Unsupported curve pre-wrap mode. Loop and ping-pong do not support procedural mode."; - break; - case AnimationUtility.PolynomialValid.InvalidPostWrapMode: - failureReason = "Unsupported curve post-wrap mode. Loop and ping-pong do not support procedural mode."; - break; - case AnimationUtility.PolynomialValid.TooManySegments: - failureReason = "Curve uses too many keys. Procedural mode does not support more than " + AnimationUtility.GetMaxNumPolynomialSegmentsSupported() + " keys"; - if (curve.keys[0].time != 0.0f || curve.keys[curve.keys.Length - 1].time != 1.0f) - failureReason += " (Additional keys are added to curves that do not start at 0, or do not end at 1)"; - failureReason += "."; - break; - } - return false; - } - - public bool SupportsProcedural(ref string failureReason) - { - string maxCurveFailureReason = "Max Curve: "; - bool isMaxCurveValid = AnimationCurveSupportsProcedural(maxCurve.animationCurveValue, ref maxCurveFailureReason); - if (!isMaxCurveValid) - failureReason = maxCurveFailureReason; - - if ((state != MinMaxCurveState.k_TwoCurves) && (state != MinMaxCurveState.k_TwoScalars)) - return isMaxCurveValid; - else - { - string minCurveFailureReason = "Min Curve: "; - bool isMinCurveValid = AnimationCurveSupportsProcedural(minCurve.animationCurveValue, ref minCurveFailureReason); - if (isMinCurveValid) - failureReason += minCurveFailureReason; - return isMaxCurveValid && isMinCurveValid; - } - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/ParticleSystemEditor/SerializedMinMaxGradient.cs b/Editor/Mono/ParticleSystemEditor/SerializedMinMaxGradient.cs deleted file mode 100644 index 46af69c0ce..0000000000 --- a/Editor/Mono/ParticleSystemEditor/SerializedMinMaxGradient.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - - -namespace UnityEditor -{ - // Must be in sync with enum in ParticleSystemCurves.h - internal enum MinMaxGradientState - { - k_Color = 0, - k_Gradient = 1, - k_RandomBetweenTwoColors = 2, - k_RandomBetweenTwoGradients = 3, - k_RandomColor = 4 - }; - - internal class SerializedMinMaxGradient - { - public SerializedProperty m_RootProperty; - public SerializedProperty m_MaxGradient; - public SerializedProperty m_MinGradient; - public SerializedProperty m_MaxColor; - public SerializedProperty m_MinColor; - private SerializedProperty m_MinMaxState; - - public bool m_AllowColor; - public bool m_AllowGradient; - public bool m_AllowRandomBetweenTwoColors; - public bool m_AllowRandomBetweenTwoGradients; - public bool m_AllowRandomColor; - - public MinMaxGradientState state - { - get { return (MinMaxGradientState)m_MinMaxState.intValue; } - set { SetMinMaxState(value); } - } - - public bool stateHasMultipleDifferentValues - { - get { return m_MinMaxState.hasMultipleDifferentValues; } - } - - public SerializedMinMaxGradient(SerializedModule m) - { - Init(m, "gradient"); - } - - public SerializedMinMaxGradient(SerializedModule m, string name) - { - Init(m, name); - } - - void Init(SerializedModule m, string name) - { - m_RootProperty = m.GetProperty(name); - m_MaxGradient = m.GetProperty(name, "maxGradient"); - m_MinGradient = m.GetProperty(name, "minGradient"); - m_MaxColor = m.GetProperty(name, "maxColor"); - m_MinColor = m.GetProperty(name, "minColor"); - m_MinMaxState = m.GetProperty(name, "minMaxState"); - - m_AllowColor = true; - m_AllowGradient = true; - m_AllowRandomBetweenTwoColors = true; - m_AllowRandomBetweenTwoGradients = true; - m_AllowRandomColor = false; - } - - private void SetMinMaxState(MinMaxGradientState newState) - { - if (newState == state) - return; - - m_MinMaxState.intValue = (int)newState; - } - - public static Color GetGradientAsColor(SerializedProperty gradientProp) - { - Gradient gradient = gradientProp.gradientValue; - return gradient.constantColor; - } - - public static void SetGradientAsColor(SerializedProperty gradientProp, Color color) - { - Gradient gradient = gradientProp.gradientValue; - gradient.constantColor = color; - - // We have changed a gradient so clear preview cache - UnityEditorInternal.GradientPreviewCache.ClearCache(); - } - } -} // namespace UnityEditor diff --git a/Editor/Mono/PerceptionRemoting/HolographicEmulation/HolographicEmulationWindow.cs b/Editor/Mono/PerceptionRemoting/HolographicEmulation/HolographicEmulationWindow.cs deleted file mode 100644 index 0558393e22..0000000000 --- a/Editor/Mono/PerceptionRemoting/HolographicEmulation/HolographicEmulationWindow.cs +++ /dev/null @@ -1,418 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using UnityEditor; -using UnityEditorInternal.VR; -using UnityEngine; -using UnityEngine.XR; - -namespace UnityEditorInternal.VR -{ - public class HolographicEmulationWindow : EditorWindow - { - private bool m_InPlayMode = false; - private bool m_OperatingSystemChecked = false; - private bool m_OperatingSystemValid = false; - private HolographicStreamerConnectionState m_LastConnectionState = HolographicStreamerConnectionState.Disconnected; - - [SerializeField] - private EmulationMode m_Mode = EmulationMode.None; - [SerializeField] - private int m_RoomIndex = 0; - [SerializeField] - private GestureHand m_Hand = GestureHand.Right; - [SerializeField] - private string m_RemoteMachineAddress = ""; - [SerializeField] - private bool m_EnableVideo = true; - [SerializeField] - private bool m_EnableAudio = true; - [SerializeField] - private int m_MaxBitrateKbps = 99999; - - // history is saved in editor prefs so it is usable across projects - private string[] m_RemoteMachineHistory; - private static int s_MaxHistoryLength = 4; - - private static GUIContent s_ConnectionStatusText = EditorGUIUtility.TrTextContent("Connection Status"); - private static GUIContent s_EmulationModeText = EditorGUIUtility.TrTextContent("Emulation Mode"); - private static GUIContent s_RoomText = EditorGUIUtility.TrTextContent("Room"); - private static GUIContent s_HandText = EditorGUIUtility.TrTextContent("Gesture Hand"); - private static GUIContent s_RemoteMachineText = EditorGUIUtility.TrTextContent("Remote Machine"); - private static GUIContent s_EnableVideoText = EditorGUIUtility.TrTextContent("Enable Video"); - private static GUIContent s_EnableAudioText = EditorGUIUtility.TrTextContent("Enable Audio"); - private static GUIContent s_MaxBitrateText = EditorGUIUtility.TrTextContent("Max Bitrate (kbps)"); - private static GUIContent s_ConnectionButtonConnectText = EditorGUIUtility.TrTextContent("Connect"); - private static GUIContent s_ConnectionButtonDisconnectText = EditorGUIUtility.TrTextContent("Disconnect"); - private static GUIContent s_ConnectionStateDisconnectedText = EditorGUIUtility.TrTextContent("Disconnected"); - private static GUIContent s_ConnectionStateConnectingText = EditorGUIUtility.TrTextContent("Connecting"); - private static GUIContent s_ConnectionStateConnectedText = EditorGUIUtility.TrTextContent("Connected"); - private static Texture2D s_ConnectedTexture = null; - private static Texture2D s_ConnectingTexture = null; - private static Texture2D s_DisconnectedTexture = null; - private static GUIContent[] s_ModeStrings = new GUIContent[] - { - EditorGUIUtility.TrTextContent("None"), - EditorGUIUtility.TrTextContent("Remote to Device"), - EditorGUIUtility.TrTextContent("Simulate in Editor") - }; - - private static GUIContent[] s_RoomStrings = new GUIContent[] - { - EditorGUIUtility.TrTextContent("None"), - EditorGUIUtility.TrTextContent("DefaultRoom"), - EditorGUIUtility.TrTextContent("Bedroom1"), - EditorGUIUtility.TrTextContent("Bedroom2"), - EditorGUIUtility.TrTextContent("GreatRoom"), - EditorGUIUtility.TrTextContent("LivingRoom") - }; - - private static GUIContent[] s_HandStrings = new GUIContent[] - { - EditorGUIUtility.TrTextContent("Left Hand"), - EditorGUIUtility.TrTextContent("Right Hand"), - }; - - public EmulationMode emulationMode - { - get { return m_Mode; } - set { m_Mode = value; Repaint(); } - } - - internal static void Init() - { - EditorWindow.GetWindow(false); - } - - private bool RemoteMachineNameSpecified { get { return !String.IsNullOrEmpty(m_RemoteMachineAddress); } } - - private void OnEnable() - { - titleContent = EditorGUIUtility.TrTextContent("Holographic"); - EditorApplication.playModeStateChanged += OnPlayModeStateChanged; - m_InPlayMode = EditorApplication.isPlayingOrWillChangePlaymode; - - m_RemoteMachineHistory = EditorPrefs.GetString("HolographicRemoting.RemoteMachineHistory").Split(','); - } - - private void OnDisable() - { - EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; - } - - private void LoadCurrentRoom() - { - if (m_RoomIndex == 0) - return; - - string roomPath = EditorApplication.applicationContentsPath + "/UnityExtensions/Unity/VR/HolographicSimulation/Rooms/"; - HolographicEmulation.LoadRoom(roomPath + s_RoomStrings[m_RoomIndex].text + ".xef"); - } - - private void InitializeSimulation() - { - Disconnect(); - - HolographicEmulation.Initialize(); - - LoadCurrentRoom(); - } - - private void OnPlayModeStateChanged(PlayModeStateChange state) - { - if (!IsWindowsMixedRealityCurrentTarget()) - return; - - bool wasPlaying = m_InPlayMode; - m_InPlayMode = EditorApplication.isPlayingOrWillChangePlaymode; - - if (m_InPlayMode && !wasPlaying) - { - HolographicEmulation.SetEmulationMode(m_Mode); - switch (m_Mode) - { - case EmulationMode.Simulated: - InitializeSimulation(); - break; - case EmulationMode.RemoteDevice: - break; - } - } - else if (!m_InPlayMode && wasPlaying) - { - switch (m_Mode) - { - case EmulationMode.Simulated: - HolographicEmulation.Shutdown(); - break; - - case EmulationMode.RemoteDevice: - break; - } - } - } - - private void Connect() - { - PerceptionRemotingPlugin.SetVideoEncodingParameters(m_MaxBitrateKbps); - PerceptionRemotingPlugin.SetEnableVideo(m_EnableVideo); - PerceptionRemotingPlugin.SetEnableAudio(m_EnableAudio); - PerceptionRemotingPlugin.Connect(m_RemoteMachineAddress); - } - - private void Disconnect() - { - if (PerceptionRemotingPlugin.GetConnectionState() != HolographicStreamerConnectionState.Disconnected) - PerceptionRemotingPlugin.Disconnect(); - } - - private bool IsConnectedToRemoteDevice() - { - return PerceptionRemotingPlugin.GetConnectionState() == HolographicStreamerConnectionState.Connected; - } - - private void HandleButtonPress() - { - if (EditorApplication.isPlayingOrWillChangePlaymode) - { - Debug.LogError("Unable to connect / disconnect remoting while playing."); - return; - } - - HolographicStreamerConnectionState connectionState = PerceptionRemotingPlugin.GetConnectionState(); - if (connectionState == HolographicStreamerConnectionState.Connecting || - connectionState == HolographicStreamerConnectionState.Connected) - { - Disconnect(); - } - else if (RemoteMachineNameSpecified) - { - Connect(); - } - else - { - Debug.LogError("Cannot connect without a remote machine address specified"); - } - } - - private void UpdateRemoteMachineHistory() - { - List history = new List(m_RemoteMachineHistory); - - // check for existing item in history - for (int i = 0; i < m_RemoteMachineHistory.Length; ++i) - { - if (m_RemoteMachineHistory[i].Equals(m_RemoteMachineAddress, StringComparison.CurrentCultureIgnoreCase)) - { - if (i == 0) - return; - - // remove it so it can be re-added as the first element - history.RemoveAt(i); - break; - } - } - - // add to history - history.Insert(0, m_RemoteMachineAddress); - - // cull list down to MaxHistoryLength - if (history.Count > s_MaxHistoryLength) - { - history.RemoveRange(s_MaxHistoryLength, history.Count - s_MaxHistoryLength); - } - - m_RemoteMachineHistory = history.ToArray(); - EditorPrefs.SetString("HolographicRemoting.RemoteMachineHistory", String.Join(",", m_RemoteMachineHistory)); - } - - private void RemotingPreferencesOnGUI() - { - EditorGUI.BeginChangeCheck(); - m_RemoteMachineAddress = EditorGUILayout.DelayedTextFieldDropDown(s_RemoteMachineText, m_RemoteMachineAddress, m_RemoteMachineHistory); - if (EditorGUI.EndChangeCheck()) - { - UpdateRemoteMachineHistory(); - } - m_EnableVideo = EditorGUILayout.Toggle(s_EnableVideoText, m_EnableVideo); - m_EnableAudio = EditorGUILayout.Toggle(s_EnableAudioText, m_EnableAudio); - m_MaxBitrateKbps = EditorGUILayout.IntSlider(s_MaxBitrateText, m_MaxBitrateKbps, 1024, 99999); - } - - void ConnectionStateGUI() - { - if (s_ConnectedTexture == null) - { - s_ConnectedTexture = EditorGUIUtility.LoadIconRequired("sv_icon_dot3_sml"); - s_ConnectingTexture = EditorGUIUtility.LoadIconRequired("sv_icon_dot4_sml"); - s_DisconnectedTexture = EditorGUIUtility.LoadIconRequired("sv_icon_dot6_sml"); - } - - Texture2D iconTexture; - GUIContent labelContent; - GUIContent buttonContent; - HolographicStreamerConnectionState connectionState = PerceptionRemotingPlugin.GetConnectionState(); - switch (connectionState) - { - case HolographicStreamerConnectionState.Disconnected: - default: - iconTexture = s_DisconnectedTexture; - labelContent = s_ConnectionStateDisconnectedText; - buttonContent = s_ConnectionButtonConnectText; - break; - - case HolographicStreamerConnectionState.Connecting: - iconTexture = s_ConnectingTexture; - labelContent = s_ConnectionStateConnectingText; - buttonContent = s_ConnectionButtonDisconnectText; - break; - - case HolographicStreamerConnectionState.Connected: - iconTexture = s_ConnectedTexture; - labelContent = s_ConnectionStateConnectedText; - buttonContent = s_ConnectionButtonDisconnectText; - break; - } - - EditorGUILayout.BeginHorizontal(); - - EditorGUILayout.PrefixLabel(s_ConnectionStatusText, "Button"); - float iconSize = EditorGUIUtility.singleLineHeight; - Rect iconRect = GUILayoutUtility.GetRect(iconSize, iconSize, GUILayout.ExpandWidth(false)); - GUI.DrawTexture(iconRect, iconTexture); - EditorGUILayout.LabelField(labelContent); - - EditorGUILayout.EndHorizontal(); - - EditorGUI.BeginDisabledGroup(m_InPlayMode); - bool pressed = EditorGUILayout.DropdownButton(buttonContent, FocusType.Passive, EditorStyles.miniButton); - EditorGUI.EndDisabledGroup(); - - if (pressed) - { - if (EditorGUIUtility.editingTextField) - { - EditorGUIUtility.editingTextField = false; - GUIUtility.keyboardControl = 0; - } - //we delay the call to let the RemoteMachineAddress control commit the value - EditorApplication.CallDelayed(() => - { - HandleButtonPress(); - }, 0f); - } - } - - private bool IsWindowsMixedRealityCurrentTarget() - { - if (!VREditor.GetVREnabledOnTargetGroup(BuildTargetGroup.WSA)) - return false; - - if (Array.IndexOf(XRSettings.supportedDevices, "WindowsMR") < 0) - return false; - - return true; - } - - private void DrawRemotingMode() - { - EditorGUI.BeginChangeCheck(); - m_Mode = (EmulationMode)EditorGUILayout.Popup(s_EmulationModeText, (int)m_Mode, s_ModeStrings); - if (EditorGUI.EndChangeCheck() && m_Mode != EmulationMode.RemoteDevice) - { - Disconnect(); - } - } - - private bool CheckOperatingSystem() - { - if (!m_OperatingSystemChecked) - { - m_OperatingSystemValid = System.Environment.OSVersion.Version.Build >= 14318; - m_OperatingSystemChecked = true; - } - return m_OperatingSystemValid; - } - - void OnGUI() - { - if (!CheckOperatingSystem()) - { - EditorGUILayout.HelpBox("You must be running Windows build 14318 or later to use Holographic Simulation or Remoting.", MessageType.Warning); - return; - } - - if (!IsWindowsMixedRealityCurrentTarget()) - { - EditorGUILayout.HelpBox("You must enable Virtual Reality support in settings and add Windows Mixed Reality to the devices to use Holographic Emulation.", MessageType.Warning); - return; - } - - EditorGUILayout.Space(); - - EditorGUI.BeginDisabledGroup(m_InPlayMode); - DrawRemotingMode(); - EditorGUI.EndDisabledGroup(); - - switch (m_Mode) - { - case EmulationMode.RemoteDevice: - EditorGUI.BeginDisabledGroup(IsConnectedToRemoteDevice()); - RemotingPreferencesOnGUI(); - EditorGUI.EndDisabledGroup(); - ConnectionStateGUI(); - break; - - case EmulationMode.Simulated: - EditorGUI.BeginChangeCheck(); - m_RoomIndex = EditorGUILayout.Popup(s_RoomText, m_RoomIndex, s_RoomStrings); - if (EditorGUI.EndChangeCheck() && m_InPlayMode) - LoadCurrentRoom(); - - - EditorGUI.BeginChangeCheck(); - m_Hand = (GestureHand)EditorGUILayout.Popup(s_HandText, (int)m_Hand, s_HandStrings); - if (EditorGUI.EndChangeCheck()) - HolographicEmulation.SetGestureHand(m_Hand); - - break; - } - } - - void Update() - { - switch (m_Mode) - { - case EmulationMode.Simulated: - HolographicEmulation.SetGestureHand(m_Hand); - break; - - case EmulationMode.RemoteDevice: - HolographicStreamerConnectionState connectionState = PerceptionRemotingPlugin.GetConnectionState(); - if (connectionState != m_LastConnectionState) - { - Repaint(); - } - var lastConnectionFailureReason = PerceptionRemotingPlugin.CheckForDisconnect(); - if (lastConnectionFailureReason == HolographicStreamerConnectionFailureReason.Unreachable - || lastConnectionFailureReason == HolographicStreamerConnectionFailureReason.ConnectionLost) - { - Debug.LogWarning("Disconnected with failure reason " + lastConnectionFailureReason + ", attempting to reconnect."); - Connect(); - } - else if (lastConnectionFailureReason != HolographicStreamerConnectionFailureReason.None) - { - Debug.LogError("Disconnected with error " + lastConnectionFailureReason); - } - m_LastConnectionState = connectionState; - break; - } - } - } -} diff --git a/Editor/Mono/PerformanceTools/FrameDebugger.cs b/Editor/Mono/PerformanceTools/FrameDebugger.cs deleted file mode 100644 index 55d8a3c391..0000000000 --- a/Editor/Mono/PerformanceTools/FrameDebugger.cs +++ /dev/null @@ -1,1534 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; -using UnityEngine; -using UnityEngine.Rendering; -using UnityEditorInternal; -using System.Runtime.InteropServices; -using UnityEditor; -using UnityEditor.IMGUI.Controls; - -namespace UnityEditorInternal -{ - // match enum FrameEventType on C++ side! - // match kFrameEventTypeNames names array! - internal enum FrameEventType - { - // ReSharper disable InconsistentNaming - ClearNone = 0, - ClearColor, - ClearDepth, - ClearColorDepth, - ClearStencil, - ClearColorStencil, - ClearDepthStencil, - ClearAll, - SetRenderTarget, - ResolveRT, - ResolveDepth, - GrabIntoRT, - StaticBatch, - DynamicBatch, - Mesh, - DynamicGeometry, - GLDraw, - SkinOnGPU, - DrawProcedural, - ComputeDispatch, - PluginEvent, - InstancedMesh, - BeginRenderpass, - NextSubpass, - EndSubpass - // ReSharper restore InconsistentNaming - }; - - internal enum ShowAdditionalInfo - { - Preview, - ShaderProperties - }; - - // Match C++ ScriptingShaderFloatInfo memory layout! - [StructLayout(LayoutKind.Sequential)] - internal struct ShaderFloatInfo - { - public string name; - public int flags; - public float value; - } - - // Match C++ ScriptingShaderVectorInfo memory layout! - [StructLayout(LayoutKind.Sequential)] - internal struct ShaderVectorInfo - { - public string name; - public int flags; - public Vector4 value; - } - - // Match C++ ScriptingShaderMatrixInfo memory layout! - [StructLayout(LayoutKind.Sequential)] - internal struct ShaderMatrixInfo - { - public string name; - public int flags; - public Matrix4x4 value; - } - - // Match C++ ScriptingShaderTextureInfo memory layout! - [StructLayout(LayoutKind.Sequential)] - internal struct ShaderTextureInfo - { - public string name; - public int flags; - public string textureName; - public Texture value; - } - - // Match C++ ScriptingShaderBufferInfo memory layout! - [StructLayout(LayoutKind.Sequential)] - internal struct ShaderBufferInfo - { - public string name; - public int flags; - } - - // Match C++ ScriptingShaderProperties memory layout! - [StructLayout(LayoutKind.Sequential)] - internal struct ShaderProperties - { - public ShaderFloatInfo[] floats; - public ShaderVectorInfo[] vectors; - public ShaderMatrixInfo[] matrices; - public ShaderTextureInfo[] textures; - public ShaderBufferInfo[] buffers; - } - - // Match C++ ScriptingFrameDebuggerEventData memory layout! - [StructLayout(LayoutKind.Sequential)] - internal struct FrameDebuggerEventData - { - public int frameEventIndex; - public int vertexCount; - public int indexCount; - public int instanceCount; - public int drawCallCount; - public string shaderName; - public string passName; - public string passLightMode; - public int shaderInstanceID; - public int subShaderIndex; - public int shaderPassIndex; - public string shaderKeywords; - public int rendererInstanceID; - public Mesh mesh; - public int meshInstanceID; - public int meshSubset; - - // state for compute shader dispatches - public int csInstanceID; - public string csName; - public string csKernel; - public int csThreadGroupsX; - public int csThreadGroupsY; - public int csThreadGroupsZ; - - // active render target info - public string rtName; - public int rtWidth; - public int rtHeight; - public int rtFormat; - public int rtDim; - public int rtFace; - public short rtCount; - public short rtHasDepthTexture; - - // shader state and properties - public FrameDebuggerBlendState blendState; - public FrameDebuggerRasterState rasterState; - public FrameDebuggerDepthState depthState; - public FrameDebuggerStencilState stencilState; - public int stencilRef; - public int batchBreakCause; - - public ShaderProperties shaderProperties; - } - - // Match C++ MonoFrameDebuggerEvent memory layout! - [StructLayout(LayoutKind.Sequential)] - internal struct FrameDebuggerEvent - { - public FrameEventType type; - public GameObject gameObject; - } - - // Match C++ ScriptingFrameDebuggerBlendState memory layout! - [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] - internal struct FrameDebuggerBlendState - { - public uint writeMask; - public BlendMode srcBlend; - public BlendMode dstBlend; - public BlendMode srcBlendAlpha; - public BlendMode dstBlendAlpha; - public BlendOp blendOp; - public BlendOp blendOpAlpha; - } - - // Match C++ ScriptingFrameDebuggerRasterState memory layout! - [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] - struct FrameDebuggerRasterState - { - public CullMode cullMode; - public int depthBias; - public bool depthClip; - public float slopeScaledDepthBias; - }; - - // Match C++ ScriptingFrameDebuggerDepthState memory layout! - [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] - struct FrameDebuggerDepthState - { - public int depthWrite; - public CompareFunction depthFunc; - }; - - // Match C++ ScriptingFrameDebuggerStencilState memory layout! - [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] - struct FrameDebuggerStencilState - { - public bool stencilEnable; - public byte readMask; - public byte writeMask; - public byte padding; - public CompareFunction stencilFuncFront; - public StencilOp stencilPassOpFront; - public StencilOp stencilFailOpFront; - public StencilOp stencilZFailOpFront; - public CompareFunction stencilFuncBack; - public StencilOp stencilPassOpBack; - public StencilOp stencilFailOpBack; - public StencilOp stencilZFailOpBack; - }; -} - -namespace UnityEditor -{ - internal class FrameDebuggerWindow : EditorWindow - { - // match enum FrameEventType on C++ side! - static public readonly string[] s_FrameEventTypeNames = new[] - { - "Clear (nothing)", - "Clear (color)", - "Clear (Z)", - "Clear (color+Z)", - "Clear (stencil)", - "Clear (color+stencil)", - "Clear (Z+stencil)", - "Clear (color+Z+stencil)", - "SetRenderTarget", - "Resolve Color", - "Resolve Depth", - "Grab RenderTexture", - "Static Batch", - "Dynamic Batch", - "Draw Mesh", - "Draw Dynamic", - "Draw GL", - "GPU Skinning", - "Draw Procedural", - "Compute Shader", - "Plugin Event", - "Draw Mesh (instanced)", - "Begin Renderpass", - "Next Subpass", - "End Renderpass" - }; - - // Cached strings built from FrameDebuggerEventData. - // Only need to rebuild them when event data actually changes. - private struct EventDataStrings - { - public string drawCallCount; - - public string shader; - public string pass; - - public string stencilRef; - public string stencilReadMask; - public string stencilWriteMask; - public string stencilComp; - public string stencilPass; - public string stencilFail; - public string stencilZFail; - - public string[] texturePropertyTooltips; - } - - const float kScrollbarWidth = 16; - const float kResizerWidth = 5f; - const float kMinListWidth = 200f; - const float kMinDetailsWidth = 200f; - const float kMinWindowWidth = 240f; - const float kDetailsMargin = 4f; - const float kMinPreviewSize = 64f; - - const string kFloatFormat = "g2"; - const string kFloatDetailedFormat = "g7"; - - const float kShaderPropertiesIndention = 15.0f; - const float kNameFieldWidth = 200.0f; - const float kValueFieldWidth = 200.0f; - const float kArrayValuePopupBtnWidth = 25.0f; - - // See the comments for BaseParamInfo in FrameDebuggerInternal.h - const int kShaderTypeBits = 6; - const int kArraySizeBitMask = 0x3FF; - - // Sometimes when disabling the frame debugger, the UI does not update automatically - - // the repaint happens, but we still think there's zero events present - // (on Mac at least). Haven't figured out why, so whenever changing the - // enable/limit state, just repaint a couple of times. Yeah... - const int kNeedToRepaintFrames = 4; - - - [SerializeField] - float m_ListWidth = kMinListWidth * 1.5f; - - private int m_RepaintFrames = kNeedToRepaintFrames; - - // Mesh preview - PreviewRenderUtility m_PreviewUtility; - public Vector2 m_PreviewDir = new Vector2(120, -20); - private Material m_Material; - private Material m_WireMaterial; - - // Frame events tree view - [SerializeField] - TreeViewState m_TreeViewState; - [NonSerialized] - FrameDebuggerTreeView m_Tree; - [NonSerialized] private int m_FrameEventsHash; - - // Render target view options - [NonSerialized] int m_RTIndex; - [NonSerialized] int m_RTChannel; - - [NonSerialized] private float m_RTBlackLevel; - [NonSerialized] private float m_RTWhiteLevel = 1.0f; - - private int m_PrevEventsLimit = 0; - private int m_PrevEventsCount = 0; - - private FrameDebuggerEventData m_CurEventData; - private uint m_CurEventDataHash = 0; - private EventDataStrings m_CurEventDataStrings; - - // Shader Properties - private Vector2 m_ScrollViewShaderProps = Vector2.zero; - - private ShowAdditionalInfo m_AdditionalInfo = ShowAdditionalInfo.ShaderProperties; - private GUIContent[] m_AdditionalInfoGuiContents = Enum.GetNames(typeof(ShowAdditionalInfo)).Select(m => new GUIContent(m)).ToArray(); - - static List s_FrameDebuggers = new List(); - - private AttachProfilerUI m_AttachProfilerUI = new AttachProfilerUI(); - - [MenuItem("Window/Frame Debugger", false, 2100)] - public static FrameDebuggerWindow ShowFrameDebuggerWindow() - { - var wnd = GetWindow(typeof(FrameDebuggerWindow)) as FrameDebuggerWindow; - if (wnd != null) - { - wnd.titleContent = EditorGUIUtility.TrTextContent("Frame Debug"); - } - return wnd; - } - - internal static void RepaintAll() - { - foreach (var fd in s_FrameDebuggers) - { - fd.Repaint(); - } - } - - public FrameDebuggerWindow() - { - position = new Rect(50, 50, (kMinListWidth + kMinDetailsWidth) * 1.5f, 350f); - minSize = new Vector2(kMinListWidth + kMinDetailsWidth, 200); - } - - internal void ChangeFrameEventLimit(int newLimit) - { - if (newLimit <= 0 || newLimit > FrameDebuggerUtility.count) - { - return; - } - - if (newLimit != FrameDebuggerUtility.limit && newLimit > 0) - { - GameObject go = FrameDebuggerUtility.GetFrameEventGameObject(newLimit - 1); - if (go != null) - EditorGUIUtility.PingObject(go); - } - - FrameDebuggerUtility.limit = newLimit; - if (m_Tree != null) - m_Tree.SelectFrameEventIndex(newLimit); - } - - static void DisableFrameDebugger() - { - if (FrameDebuggerUtility.IsLocalEnabled()) - { - // if it was true before, we disabled and ask the game scene to repaint - EditorApplication.SetSceneRepaintDirty(); - } - - FrameDebuggerUtility.SetEnabled(false, FrameDebuggerUtility.GetRemotePlayerGUID()); - } - - internal void OnDidOpenScene() - { - DisableFrameDebugger(); - } - - void OnPauseStateChanged(PauseState state) - { - RepaintOnLimitChange(); - } - - void OnPlayModeStateChanged(PlayModeStateChange state) - { - RepaintOnLimitChange(); - } - - internal void OnEnable() - { - autoRepaintOnSceneChange = true; - s_FrameDebuggers.Add(this); - EditorApplication.pauseStateChanged += OnPauseStateChanged; - EditorApplication.playModeStateChanged += OnPlayModeStateChanged; - m_RepaintFrames = kNeedToRepaintFrames; - } - - internal void OnDisable() - { - if (m_WireMaterial != null) - { - DestroyImmediate(m_WireMaterial, true); - } - if (m_PreviewUtility != null) - { - m_PreviewUtility.Cleanup(); - m_PreviewUtility = null; - } - - s_FrameDebuggers.Remove(this); - EditorApplication.pauseStateChanged -= OnPauseStateChanged; - EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; - - DisableFrameDebugger(); - } - - public void EnableIfNeeded() - { - if (FrameDebuggerUtility.IsLocalEnabled() || FrameDebuggerUtility.IsRemoteEnabled()) - return; - m_RTChannel = 0; - m_RTIndex = 0; - m_RTBlackLevel = 0.0f; - m_RTWhiteLevel = 1.0f; - ClickEnableFrameDebugger(); - RepaintOnLimitChange(); - } - - private void ClickEnableFrameDebugger() - { - bool isEnabled = FrameDebuggerUtility.IsLocalEnabled() || FrameDebuggerUtility.IsRemoteEnabled(); - - bool enablingLocally = !isEnabled && m_AttachProfilerUI.IsEditor(); - - if (enablingLocally && !FrameDebuggerUtility.locallySupported) - return; - - if (enablingLocally) - { - // pause play mode if needed - if (EditorApplication.isPlaying && !EditorApplication.isPaused) - EditorApplication.isPaused = true; - } - - if (!isEnabled) - FrameDebuggerUtility.SetEnabled(true, ProfilerDriver.connectedProfiler); - else - FrameDebuggerUtility.SetEnabled(false, FrameDebuggerUtility.GetRemotePlayerGUID()); - - // Make sure game view is visible when enabling frame debugger locally - if (FrameDebuggerUtility.IsLocalEnabled()) - { - GameView gameView = (GameView)WindowLayout.FindEditorWindowOfType(typeof(GameView)); - if (gameView) - { - gameView.ShowTab(); - } - } - - m_PrevEventsLimit = FrameDebuggerUtility.limit; - m_PrevEventsCount = FrameDebuggerUtility.count; - } - - // Only call this when m_CurEventData changes. - void BuildCurEventDataStrings() - { - // we will show that only if drawcall count is bigger than one so update unconditionally - m_CurEventDataStrings.drawCallCount = string.Format("{0}", m_CurEventData.drawCallCount); - - // shader name & subshader index - m_CurEventDataStrings.shader = string.Format("{0}, SubShader #{1}", m_CurEventData.shaderName, m_CurEventData.subShaderIndex.ToString()); - - // pass name & LightMode tag - string passName = string.IsNullOrEmpty(m_CurEventData.passName) ? "#" + m_CurEventData.shaderPassIndex.ToString() : m_CurEventData.passName; - string lightMode = string.IsNullOrEmpty(m_CurEventData.passLightMode) ? "" : string.Format(" ({0})", m_CurEventData.passLightMode); - m_CurEventDataStrings.pass = passName + lightMode; - - // stencil states - if (m_CurEventData.stencilState.stencilEnable) - { - m_CurEventDataStrings.stencilRef = m_CurEventData.stencilRef.ToString(); - - if (m_CurEventData.stencilState.readMask != 255) - m_CurEventDataStrings.stencilReadMask = m_CurEventData.stencilState.readMask.ToString(); - - if (m_CurEventData.stencilState.writeMask != 255) - m_CurEventDataStrings.stencilWriteMask = m_CurEventData.stencilState.writeMask.ToString(); - - // Only show *Front states when CullMode is set to Back. - // Only show *Back states when CullMode is set to Front. - // Show both *Front and *Back states for two-sided geometry. - if (m_CurEventData.rasterState.cullMode == CullMode.Back) - { - m_CurEventDataStrings.stencilComp = m_CurEventData.stencilState.stencilFuncFront.ToString(); - m_CurEventDataStrings.stencilPass = m_CurEventData.stencilState.stencilPassOpFront.ToString(); - m_CurEventDataStrings.stencilFail = m_CurEventData.stencilState.stencilFailOpFront.ToString(); - m_CurEventDataStrings.stencilZFail = m_CurEventData.stencilState.stencilZFailOpFront.ToString(); - } - else if (m_CurEventData.rasterState.cullMode == CullMode.Front) - { - m_CurEventDataStrings.stencilComp = m_CurEventData.stencilState.stencilFuncBack.ToString(); - m_CurEventDataStrings.stencilPass = m_CurEventData.stencilState.stencilPassOpBack.ToString(); - m_CurEventDataStrings.stencilFail = m_CurEventData.stencilState.stencilFailOpBack.ToString(); - m_CurEventDataStrings.stencilZFail = m_CurEventData.stencilState.stencilZFailOpBack.ToString(); - } - else - { - m_CurEventDataStrings.stencilComp = - string.Format("{0} {1}", m_CurEventData.stencilState.stencilFuncFront.ToString(), m_CurEventData.stencilState.stencilFuncBack.ToString()); - - m_CurEventDataStrings.stencilPass = - string.Format("{0} {1}", m_CurEventData.stencilState.stencilPassOpFront.ToString(), m_CurEventData.stencilState.stencilPassOpBack.ToString()); - - m_CurEventDataStrings.stencilFail = - string.Format("{0} {1}", m_CurEventData.stencilState.stencilFailOpFront.ToString(), m_CurEventData.stencilState.stencilFailOpBack.ToString()); - - m_CurEventDataStrings.stencilZFail = - string.Format("{0} {1}", m_CurEventData.stencilState.stencilZFailOpFront.ToString(), m_CurEventData.stencilState.stencilZFailOpBack.ToString()); - } - } - - // texture property tooltips - ShaderTextureInfo[] textureInfoArray = m_CurEventData.shaderProperties.textures; - m_CurEventDataStrings.texturePropertyTooltips = new string[textureInfoArray.Length]; - StringBuilder tooltip = new StringBuilder(); - - for (int i = 0; i < textureInfoArray.Length; ++i) - { - Texture texture = textureInfoArray[i].value; - if (texture == null) - continue; - - tooltip.Clear(); - tooltip.AppendFormat("Size: {0} x {1}", texture.width.ToString(), texture.height.ToString()); - tooltip.AppendFormat("\nDimension: {0}", texture.dimension.ToString()); - - string formatFormat = "\nFormat: {0}"; - string depthFormat = "\nDepth: {0}"; - - if (texture is Texture2D) - tooltip.AppendFormat(formatFormat, (texture as Texture2D).format.ToString()); - else if (texture is Cubemap) - tooltip.AppendFormat(formatFormat, (texture as Cubemap).format.ToString()); - else if (texture is Texture2DArray) - { - tooltip.AppendFormat(formatFormat, (texture as Texture2DArray).format.ToString()); - tooltip.AppendFormat(depthFormat, (texture as Texture2DArray).depth.ToString()); - } - else if (texture is Texture3D) - { - tooltip.AppendFormat(formatFormat, (texture as Texture3D).format.ToString()); - tooltip.AppendFormat(depthFormat, (texture as Texture3D).depth.ToString()); - } - else if (texture is CubemapArray) - { - tooltip.AppendFormat(formatFormat, (texture as CubemapArray).format.ToString()); - tooltip.AppendFormat("\nCubemap Count: {0}", (texture as CubemapArray).cubemapCount.ToString()); - } - else if (texture is RenderTexture) - { - tooltip.AppendFormat("\nRT Format: {0}", (texture as RenderTexture).format.ToString()); - } - - tooltip.Append("\n\nCtrl + Click to show preview"); - - m_CurEventDataStrings.texturePropertyTooltips[i] = tooltip.ToString(); - } - } - - // Return true if should repaint - private bool DrawToolbar(FrameDebuggerEvent[] descs) - { - bool repaint = false; - - bool isSupported = !m_AttachProfilerUI.IsEditor() || FrameDebuggerUtility.locallySupported; - - GUILayout.BeginHorizontal(EditorStyles.toolbar); - // enable toggle - EditorGUI.BeginChangeCheck(); - using (new EditorGUI.DisabledScope(!isSupported)) - { - GUILayout.Toggle(FrameDebuggerUtility.IsLocalEnabled() || FrameDebuggerUtility.IsRemoteEnabled(), styles.recordButton, EditorStyles.toolbarButton, GUILayout.MinWidth(80)); - } - if (EditorGUI.EndChangeCheck()) - { - ClickEnableFrameDebugger(); - repaint = true; - } - - m_AttachProfilerUI.OnGUILayout(this); - - bool isAnyEnabled = FrameDebuggerUtility.IsLocalEnabled() || FrameDebuggerUtility.IsRemoteEnabled(); - if (isAnyEnabled && ProfilerDriver.connectedProfiler != FrameDebuggerUtility.GetRemotePlayerGUID()) - { - // Switch from local to remote debugger or vice versa - FrameDebuggerUtility.SetEnabled(false, FrameDebuggerUtility.GetRemotePlayerGUID()); - FrameDebuggerUtility.SetEnabled(true, ProfilerDriver.connectedProfiler); - } - - GUI.enabled = isAnyEnabled; - - // event limit slider - EditorGUI.BeginChangeCheck(); - int newLimit; - using (new EditorGUI.DisabledScope(FrameDebuggerUtility.count <= 1)) - { - newLimit = EditorGUILayout.IntSlider(FrameDebuggerUtility.limit, 1, FrameDebuggerUtility.count); - } - if (EditorGUI.EndChangeCheck()) - { - ChangeFrameEventLimit(newLimit); - } - GUILayout.Label(" of " + FrameDebuggerUtility.count, EditorStyles.miniLabel); - // prev/next buttons - using (new EditorGUI.DisabledScope(newLimit <= 1)) - { - if (GUILayout.Button(styles.prevFrame, EditorStyles.toolbarButton)) - { - ChangeFrameEventLimit(newLimit - 1); - } - } - using (new EditorGUI.DisabledScope(newLimit >= FrameDebuggerUtility.count)) - { - if (GUILayout.Button(styles.nextFrame, EditorStyles.toolbarButton)) - { - ChangeFrameEventLimit(newLimit + 1); - } - // If we had last event selected, and something changed in the scene so that - // number of events is different - then try to keep the last event selected. - if (m_PrevEventsLimit == m_PrevEventsCount) - { - if (FrameDebuggerUtility.count != m_PrevEventsCount && FrameDebuggerUtility.limit == m_PrevEventsLimit) - { - ChangeFrameEventLimit(FrameDebuggerUtility.count); - } - } - m_PrevEventsLimit = FrameDebuggerUtility.limit; - m_PrevEventsCount = FrameDebuggerUtility.count; - } - - GUILayout.EndHorizontal(); - - return repaint; - } - - private void DrawMeshPreview(Rect previewRect, Rect meshInfoRect, Mesh mesh, int meshSubset) - { - if (m_PreviewUtility == null) - { - m_PreviewUtility = new PreviewRenderUtility(); - m_PreviewUtility.camera.fieldOfView = 30.0f; - } - if (m_Material == null) - m_Material = Material.GetDefaultMaterial(); - if (m_WireMaterial == null) - { - m_WireMaterial = ModelInspector.CreateWireframeMaterial(); - } - - m_PreviewUtility.BeginPreview(previewRect, "preBackground"); - - ModelInspector.RenderMeshPreview(mesh, m_PreviewUtility, m_Material, m_WireMaterial, m_PreviewDir, meshSubset); - - m_PreviewUtility.EndAndDrawPreview(previewRect); - - // mesh info - string meshName = mesh.name; - if (string.IsNullOrEmpty(meshName)) - meshName = ""; - string info = meshName + " subset " + meshSubset + "\n" + m_CurEventData.vertexCount + " verts, " + m_CurEventData.indexCount + " indices"; - if (m_CurEventData.instanceCount > 1) - info += ", " + m_CurEventData.instanceCount + " instances"; - - EditorGUI.DropShadowLabel(meshInfoRect, info); - } - - // Draw any mesh associated with the draw event - // Return false if no mesh. - private bool DrawEventMesh() - { - Mesh mesh = m_CurEventData.mesh; - if (mesh == null) - return false; - - Rect previewRect = GUILayoutUtility.GetRect(10, 10, GUILayout.ExpandHeight(true)); - if (previewRect.width < kMinPreviewSize || previewRect.height < kMinPreviewSize) - return true; - - GameObject go = FrameDebuggerUtility.GetFrameEventGameObject(m_CurEventData.frameEventIndex); - - // Info display at bottom (and pings object when clicked) - Rect meshInfoRect = previewRect; - meshInfoRect.yMin = meshInfoRect.yMax - EditorGUIUtility.singleLineHeight * 2; - Rect goInfoRect = meshInfoRect; - - meshInfoRect.xMin = meshInfoRect.center.x; - goInfoRect.xMax = goInfoRect.center.x; - if (Event.current.type == EventType.MouseDown) - { - if (meshInfoRect.Contains(Event.current.mousePosition)) - { - EditorGUIUtility.PingObject(mesh); - Event.current.Use(); - } - if (go != null && goInfoRect.Contains(Event.current.mousePosition)) - { - EditorGUIUtility.PingObject(go.GetInstanceID()); - Event.current.Use(); - } - } - - m_PreviewDir = PreviewGUI.Drag2D(m_PreviewDir, previewRect); - - if (Event.current.type == EventType.Repaint) - { - int meshSubset = m_CurEventData.meshSubset; - DrawMeshPreview(previewRect, meshInfoRect, mesh, meshSubset); - if (go != null) - { - EditorGUI.DropShadowLabel(goInfoRect, go.name); - } - } - - return true; - } - - private void DrawRenderTargetControls() - { - FrameDebuggerEventData cur = m_CurEventData; - - if (cur.rtWidth <= 0 || cur.rtHeight <= 0) - return; - - var isDepthOnlyRT = (cur.rtFormat == (int)RenderTextureFormat.Depth || cur.rtFormat == (int)RenderTextureFormat.Shadowmap); - var hasShowableDepth = (cur.rtHasDepthTexture != 0); - var showableRTCount = cur.rtCount; - if (hasShowableDepth) - showableRTCount++; - - EditorGUILayout.LabelField("RenderTarget", cur.rtName); - - GUILayout.BeginHorizontal(EditorStyles.toolbar); - - // MRT to show - bool rtWasClamped; - EditorGUI.BeginChangeCheck(); - using (new EditorGUI.DisabledScope(showableRTCount <= 1)) - { - var rtNames = new GUIContent[showableRTCount]; - for (var i = 0; i < cur.rtCount; ++i) - { - rtNames[i] = Styles.mrtLabels[i]; - } - if (hasShowableDepth) - rtNames[cur.rtCount] = Styles.depthLabel; - - var clampedIndex = Mathf.Clamp(m_RTIndex, 0, showableRTCount - 1); - rtWasClamped = (clampedIndex != m_RTIndex); - m_RTIndex = clampedIndex; - m_RTIndex = EditorGUILayout.Popup(m_RTIndex, rtNames, EditorStyles.toolbarPopup, GUILayout.Width(70)); - } - - // color channels - GUILayout.Space(10); - - using (new EditorGUI.DisabledScope(isDepthOnlyRT)) - { - GUILayout.Label(Styles.channelHeader, EditorStyles.miniLabel); - m_RTChannel = GUILayout.Toolbar(m_RTChannel, Styles.channelLabels, EditorStyles.toolbarButton); - } - - // levels - GUILayout.Space(10); - GUILayout.Label(Styles.levelsHeader, EditorStyles.miniLabel); - EditorGUILayout.MinMaxSlider(ref m_RTBlackLevel, ref m_RTWhiteLevel, 0.0f, 1.0f, GUILayout.MaxWidth(200.0f)); - if (EditorGUI.EndChangeCheck() || rtWasClamped) - { - Vector4 mask = Vector4.zero; - if (m_RTChannel == 1) - mask.x = 1f; - else if (m_RTChannel == 2) - mask.y = 1f; - else if (m_RTChannel == 3) - mask.z = 1f; - else if (m_RTChannel == 4) - mask.w = 1f; - else - mask = Vector4.one; - int rtIndexToSet = m_RTIndex; - if (rtIndexToSet >= cur.rtCount) - rtIndexToSet = -1; - FrameDebuggerUtility.SetRenderTargetDisplayOptions(rtIndexToSet, mask, m_RTBlackLevel, m_RTWhiteLevel); - RepaintAllNeededThings(); - } - - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - - GUILayout.Label(string.Format("{0}x{1} {2}", - cur.rtWidth, - cur.rtHeight, - (RenderTextureFormat)cur.rtFormat)); - if (cur.rtDim == (int)UnityEngine.Rendering.TextureDimension.Cube) - GUILayout.Label("Rendering into cubemap"); - } - - private void DrawEventDrawCallInfo() - { - if (m_CurEventData.drawCallCount > 1) - EditorGUILayout.LabelField("Draw Calls", m_CurEventDataStrings.drawCallCount); - - // shader, pass & keyword information - EditorGUILayout.LabelField("Shader", m_CurEventDataStrings.shader); - - if (GUI.Button(GUILayoutUtility.GetLastRect(), Styles.selectShaderTooltip, GUI.skin.label)) - { - EditorGUIUtility.PingObject(m_CurEventData.shaderInstanceID); - Event.current.Use(); - } - - EditorGUILayout.LabelField("Pass", m_CurEventDataStrings.pass); - - if (!string.IsNullOrEmpty(m_CurEventData.shaderKeywords)) - { - EditorGUILayout.LabelField("Keywords", m_CurEventData.shaderKeywords); - - if (GUI.Button(GUILayoutUtility.GetLastRect(), Styles.copyToClipboardTooltip, GUI.skin.label)) - EditorGUIUtility.systemCopyBuffer = m_CurEventDataStrings.shader + System.Environment.NewLine + m_CurEventData.shaderKeywords; - } - - DrawStates(); - - // Show why this draw call can't batch with the previous one. - if (m_CurEventData.batchBreakCause > 1) // Valid batch break cause enum value on the C++ side starts at 2. - { - GUILayout.Space(10.0f); - GUILayout.Label(Styles.causeOfNewDrawCallLabel, EditorStyles.boldLabel); - GUILayout.Label(styles.batchBreakCauses[m_CurEventData.batchBreakCause], EditorStyles.wordWrappedLabel); - } - - GUILayout.Space(15.0f); - - // preview / properties - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - m_AdditionalInfo = (ShowAdditionalInfo)GUILayout.Toolbar((int)m_AdditionalInfo, m_AdditionalInfoGuiContents, "LargeButton", GUI.ToolbarButtonSize.FitToContents); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - switch (m_AdditionalInfo) - { - case ShowAdditionalInfo.Preview: - // Show mesh preview if possible - if (!DrawEventMesh()) - { - // If no mesh preview, then show vertex/index count at least - EditorGUILayout.LabelField("Vertices", m_CurEventData.vertexCount.ToString()); - EditorGUILayout.LabelField("Indices", m_CurEventData.indexCount.ToString()); - } - break; - case ShowAdditionalInfo.ShaderProperties: - DrawShaderProperties(m_CurEventData.shaderProperties); - break; - } - } - - private void DrawEventComputeDispatchInfo() - { - // compute shader & kernel information - EditorGUILayout.LabelField("Compute Shader", m_CurEventData.csName); - if (GUI.Button(GUILayoutUtility.GetLastRect(), GUIContent.none, GUI.skin.label)) - { - EditorGUIUtility.PingObject(m_CurEventData.csInstanceID); - Event.current.Use(); - } - - EditorGUILayout.LabelField("Kernel", m_CurEventData.csKernel); - - // dispatch size - string threadGroupsText; - if (m_CurEventData.csThreadGroupsX != 0 || m_CurEventData.csThreadGroupsY != 0 || m_CurEventData.csThreadGroupsZ != 0) - threadGroupsText = string.Format("{0}x{1}x{2}", m_CurEventData.csThreadGroupsX, m_CurEventData.csThreadGroupsY, m_CurEventData.csThreadGroupsZ); - else - threadGroupsText = "indirect dispatch"; - - EditorGUILayout.LabelField("Thread Groups", threadGroupsText); - } - - private void DrawCurrentEvent(Rect rect, FrameDebuggerEvent[] descs) - { - int curEventIndex = FrameDebuggerUtility.limit - 1; - if (curEventIndex < 0 || curEventIndex >= descs.Length) - return; - - GUILayout.BeginArea(rect); - - uint eventDataHash = FrameDebuggerUtility.eventDataHash; - bool isFrameEventDataValid = curEventIndex == m_CurEventData.frameEventIndex; - - if (eventDataHash != 0 && m_CurEventDataHash != eventDataHash) - { - isFrameEventDataValid = FrameDebuggerUtility.GetFrameEventData(curEventIndex, out m_CurEventData); - m_CurEventDataHash = eventDataHash; - BuildCurEventDataStrings(); - } - - // render target - if (isFrameEventDataValid) - DrawRenderTargetControls(); - - // event type and draw call info - FrameDebuggerEvent cur = descs[curEventIndex]; - GUILayout.Label(string.Format("Event #{0}: {1}", (curEventIndex + 1), s_FrameEventTypeNames[(int)cur.type]), EditorStyles.boldLabel); - - if (FrameDebuggerUtility.IsRemoteEnabled() && FrameDebuggerUtility.receivingRemoteFrameEventData) - { - GUILayout.Label("Receiving frame event data..."); - } - else if (isFrameEventDataValid) // Is this a draw call? - { - if (m_CurEventData.vertexCount > 0 || m_CurEventData.indexCount > 0) - { - // a draw call, display extra info - DrawEventDrawCallInfo(); - } - else if (cur.type == FrameEventType.ComputeDispatch) - { - // a compute dispatch, display extra info - DrawEventComputeDispatchInfo(); - } - } - - GUILayout.EndArea(); - } - - void DrawShaderPropertyFlags(int flags) - { - // lowest bits of flags are set for each shader stage that property is used in; matching ShaderType C++ enum - var str = string.Empty; - if ((flags & (1 << 1)) != 0) - str += 'v'; - if ((flags & (1 << 2)) != 0) - str += 'f'; - if ((flags & (1 << 3)) != 0) - str += 'g'; - if ((flags & (1 << 4)) != 0) - str += 'h'; - if ((flags & (1 << 5)) != 0) - str += 'd'; - - GUILayout.Label(str, EditorStyles.miniLabel, GUILayout.MinWidth(20.0f)); - } - - void ShaderPropertyCopyValueMenu(Rect valueRect, System.Object value) - { - var e = Event.current; - if (e.type == EventType.ContextClick && valueRect.Contains(e.mousePosition)) - { - e.Use(); - var menu = new GenericMenu(); - menu.AddItem(EditorGUIUtility.TrTextContent("Copy value"), false, delegate - { - var str = string.Empty; - if (value is Vector4) - str = ((Vector4)value).ToString(kFloatDetailedFormat); - else if (value is Matrix4x4) - str = ((Matrix4x4)value).ToString(kFloatDetailedFormat); - else if (value is System.Single) - str = ((System.Single)value).ToString(kFloatDetailedFormat); - else - str = value.ToString(); - EditorGUIUtility.systemCopyBuffer = str; - }); - menu.ShowAsContext(); - } - } - - private void OnGUIShaderPropFloats(ShaderFloatInfo[] floats, int startIndex, int numValues) - { - GUILayout.BeginHorizontal(); - GUILayout.Space(kShaderPropertiesIndention); - - ShaderFloatInfo t = floats[startIndex]; - - if (numValues == 1) - { - GUILayout.Label(t.name, EditorStyles.miniLabel, GUILayout.MinWidth(kNameFieldWidth)); - DrawShaderPropertyFlags(t.flags); - GUILayout.Label(t.value.ToString(kFloatFormat), EditorStyles.miniLabel, GUILayout.MinWidth(kValueFieldWidth)); - ShaderPropertyCopyValueMenu(GUILayoutUtility.GetLastRect(), t.value); - } - else - { - string arrayName = String.Format("{0} [{1}]", t.name, numValues); - GUILayout.Label(arrayName, EditorStyles.miniLabel, GUILayout.MinWidth(kNameFieldWidth)); - DrawShaderPropertyFlags(t.flags); - - Rect buttonRect = GUILayoutUtility.GetRect(Styles.arrayValuePopupButton, GUI.skin.button, GUILayout.MinWidth(kValueFieldWidth)); - buttonRect.width = kArrayValuePopupBtnWidth; - if (GUI.Button(buttonRect, Styles.arrayValuePopupButton)) - { - ArrayValuePopup.GetValueStringDelegate getValueString = - (int index, bool highPrecision) => floats[index].value.ToString(highPrecision ? kFloatDetailedFormat : kFloatFormat); - - PopupWindowWithoutFocus.Show( - buttonRect, - new ArrayValuePopup(startIndex, numValues, 100.0f, getValueString), - new[] { PopupLocationHelper.PopupLocation.Left, PopupLocationHelper.PopupLocation.Below, PopupLocationHelper.PopupLocation.Right }); - } - } - - GUILayout.EndHorizontal(); - } - - private void OnGUIShaderPropVectors(ShaderVectorInfo[] vectors, int startIndex, int numValues) - { - GUILayout.BeginHorizontal(); - GUILayout.Space(kShaderPropertiesIndention); - - ShaderVectorInfo t = vectors[startIndex]; - - if (numValues == 1) - { - GUILayout.Label(t.name, EditorStyles.miniLabel, GUILayout.MinWidth(kNameFieldWidth)); - DrawShaderPropertyFlags(t.flags); - GUILayout.Label(t.value.ToString(kFloatFormat), EditorStyles.miniLabel, GUILayout.MinWidth(kValueFieldWidth)); - ShaderPropertyCopyValueMenu(GUILayoutUtility.GetLastRect(), t.value); - } - else - { - string arrayName = String.Format("{0} [{1}]", t.name, numValues); - GUILayout.Label(arrayName, EditorStyles.miniLabel, GUILayout.MinWidth(kNameFieldWidth)); - DrawShaderPropertyFlags(t.flags); - - Rect buttonRect = GUILayoutUtility.GetRect(Styles.arrayValuePopupButton, GUI.skin.button, GUILayout.MinWidth(kValueFieldWidth)); - buttonRect.width = kArrayValuePopupBtnWidth; - if (GUI.Button(buttonRect, Styles.arrayValuePopupButton)) - { - ArrayValuePopup.GetValueStringDelegate getValueString = - (int index, bool highPrecision) => vectors[index].value.ToString(highPrecision ? kFloatDetailedFormat : kFloatFormat); - - PopupWindowWithoutFocus.Show( - buttonRect, - new ArrayValuePopup(startIndex, numValues, 200.0f, getValueString), - new[] { PopupLocationHelper.PopupLocation.Left, PopupLocationHelper.PopupLocation.Below, PopupLocationHelper.PopupLocation.Right }); - } - } - - GUILayout.EndHorizontal(); - } - - private void OnGUIShaderPropMatrices(ShaderMatrixInfo[] matrices, int startIndex, int numValues) - { - GUILayout.BeginHorizontal(); - GUILayout.Space(kShaderPropertiesIndention); - - ShaderMatrixInfo t = matrices[startIndex]; - - if (numValues == 1) - { - GUILayout.Label(t.name, EditorStyles.miniLabel, GUILayout.MinWidth(kNameFieldWidth)); - DrawShaderPropertyFlags(t.flags); - GUILayout.Label(t.value.ToString(kFloatFormat), EditorStyles.miniLabel, GUILayout.MinWidth(kValueFieldWidth)); - ShaderPropertyCopyValueMenu(GUILayoutUtility.GetLastRect(), t.value); - } - else - { - string arrayName = String.Format("{0} [{1}]", t.name, numValues); - GUILayout.Label(arrayName, EditorStyles.miniLabel, GUILayout.MinWidth(kNameFieldWidth)); - DrawShaderPropertyFlags(t.flags); - - Rect buttonRect = GUILayoutUtility.GetRect(Styles.arrayValuePopupButton, GUI.skin.button, GUILayout.MinWidth(kValueFieldWidth)); - buttonRect.width = kArrayValuePopupBtnWidth; - if (GUI.Button(buttonRect, Styles.arrayValuePopupButton)) - { - ArrayValuePopup.GetValueStringDelegate getValueString = - (int index, bool highPrecision) => '\n' + matrices[index].value.ToString(highPrecision ? kFloatDetailedFormat : kFloatFormat); - - PopupWindowWithoutFocus.Show( - buttonRect, - new ArrayValuePopup(startIndex, numValues, 200.0f, getValueString), - new[] { PopupLocationHelper.PopupLocation.Left, PopupLocationHelper.PopupLocation.Below, PopupLocationHelper.PopupLocation.Right }); - } - } - - GUILayout.EndHorizontal(); - } - - private void OnGUIShaderPropBuffer(ShaderBufferInfo t) - { - GUILayout.BeginHorizontal(); - GUILayout.Space(kShaderPropertiesIndention); - - GUILayout.Label(t.name, EditorStyles.miniLabel, GUILayout.MinWidth(kNameFieldWidth)); - DrawShaderPropertyFlags(t.flags); - GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.miniLabel, GUILayout.MinWidth(kValueFieldWidth)); - - GUILayout.EndHorizontal(); - } - - private void OnGUIShaderPropTexture(int idx, ShaderTextureInfo t) - { - GUILayout.BeginHorizontal(); - GUILayout.Space(kShaderPropertiesIndention); - - GUILayout.Label(t.name, EditorStyles.miniLabel, GUILayout.MinWidth(kNameFieldWidth)); - DrawShaderPropertyFlags(t.flags); - - Rect valueRect = GUILayoutUtility.GetRect(GUIContent.none, GUI.skin.label, GUILayout.MinWidth(kValueFieldWidth)); - - // display texture similar to ObjectField, just without much of interaction or styling: - Event evt = Event.current; - Rect previewRect = valueRect; - previewRect.width = previewRect.height; - - // Tooltip - if (t.value != null && previewRect.Contains(evt.mousePosition)) - GUI.Label(previewRect, GUIContent.Temp(string.Empty, m_CurEventDataStrings.texturePropertyTooltips[idx])); - - if (evt.type == EventType.Repaint) - { - // preview and a label - Rect textRect = valueRect; - textRect.xMin += previewRect.width; - - if (t.value != null) - { - // for 2D textures, we want to display them directly as a preview (this will make render textures display their contents); - // but for cube maps and other non-2D types DrawPreview does not do anything useful right now, so get their asset type - // icon at least - Texture previewTexture = t.value; - if (previewTexture.dimension != TextureDimension.Tex2D) - previewTexture = AssetPreview.GetMiniThumbnail(previewTexture); - EditorGUI.DrawPreviewTexture(previewRect, previewTexture); - } - - GUI.Label(textRect, t.value != null ? t.value.name : t.textureName); - } - else if (evt.type == EventType.MouseDown) - { - // ping or show preview of texture when clicked - if (valueRect.Contains(evt.mousePosition)) - { - EditorGUI.PingObjectOrShowPreviewOnClick(t.value, valueRect); - evt.Use(); - } - } - - GUILayout.EndHorizontal(); - } - - void DrawShaderProperties(ShaderProperties props) - { - m_ScrollViewShaderProps = GUILayout.BeginScrollView(m_ScrollViewShaderProps); - - if (props.textures.Count() > 0) - { - GUILayout.Label("Textures", EditorStyles.boldLabel); - - for (int i = 0; i < props.textures.Length; ++i) - { - OnGUIShaderPropTexture(i, props.textures[i]); - } - } - - if (props.floats.Count() > 0) - { - GUILayout.Label("Floats", EditorStyles.boldLabel); - - for (int i = 0; i < props.floats.Length;) - { - int arraySize = (props.floats[i].flags >> kShaderTypeBits) & kArraySizeBitMask; - OnGUIShaderPropFloats(props.floats, i, arraySize); - i += arraySize; - } - } - - if (props.vectors.Count() > 0) - { - GUILayout.Label("Vectors", EditorStyles.boldLabel); - - for (int i = 0; i < props.vectors.Length;) - { - int arraySize = (props.vectors[i].flags >> kShaderTypeBits) & kArraySizeBitMask; - OnGUIShaderPropVectors(props.vectors, i, arraySize); - i += arraySize; - } - } - - if (props.matrices.Count() > 0) - { - GUILayout.Label("Matrices", EditorStyles.boldLabel); - - for (int i = 0; i < props.matrices.Length;) - { - int arraySize = (props.matrices[i].flags >> kShaderTypeBits) & kArraySizeBitMask; - OnGUIShaderPropMatrices(props.matrices, i, arraySize); - i += arraySize; - } - } - - if (props.buffers.Count() > 0) - { - GUILayout.Label("Buffers", EditorStyles.boldLabel); - - foreach (var d in props.buffers) - { - OnGUIShaderPropBuffer(d); - } - } - - GUILayout.EndScrollView(); - } - - void DrawStates() - { - FrameDebuggerBlendState blendState = m_CurEventData.blendState; - FrameDebuggerRasterState rasterState = m_CurEventData.rasterState; - FrameDebuggerDepthState depthState = m_CurEventData.depthState; - - // blend state - string blendText = string.Format("{0} {1}", blendState.srcBlend, blendState.dstBlend); - // only add alpha blend mode if different from RGB one - if (blendState.srcBlendAlpha != blendState.srcBlend || blendState.dstBlendAlpha != blendState.dstBlend) - blendText += string.Format(", {0} {1}", blendState.srcBlendAlpha, blendState.dstBlendAlpha); - - EditorGUILayout.LabelField("Blend", blendText); - - // only add blend op if non-Add - if (blendState.blendOp != BlendOp.Add || blendState.blendOpAlpha != BlendOp.Add) - { - string blendOpText; - if (blendState.blendOp == blendState.blendOpAlpha) - blendOpText = blendState.blendOp.ToString(); - else - blendOpText = string.Format("{0}, {1}", blendState.blendOp, blendState.blendOpAlpha); - - EditorGUILayout.LabelField("BlendOp", blendOpText); - } - - // only add color mask if non-RGBA - if (blendState.writeMask != 15) - { - string colorMaskText = ""; - if (blendState.writeMask == 0) - colorMaskText += '0'; - else - { - if ((blendState.writeMask & 2) != 0) - colorMaskText += 'R'; - if ((blendState.writeMask & 4) != 0) - colorMaskText += 'G'; - if ((blendState.writeMask & 8) != 0) - colorMaskText += 'B'; - if ((blendState.writeMask & 1) != 0) - colorMaskText += 'A'; - } - - EditorGUILayout.LabelField("ColorMask", colorMaskText); - } - - // depth state - EditorGUILayout.LabelField("ZClip", rasterState.depthClip.ToString()); - EditorGUILayout.LabelField("ZTest", depthState.depthFunc.ToString()); - EditorGUILayout.LabelField("ZWrite", depthState.depthWrite == 0 ? "Off" : "On"); - EditorGUILayout.LabelField("Cull", rasterState.cullMode.ToString()); - - // only add depth offset if non zero - if (rasterState.slopeScaledDepthBias != 0 || rasterState.depthBias != 0) - { - string offsetText = string.Format("{0}, {1}", rasterState.slopeScaledDepthBias, rasterState.depthBias); - EditorGUILayout.LabelField("Offset", offsetText); - } - - // Stencil state - if (m_CurEventData.stencilState.stencilEnable) - { - EditorGUILayout.LabelField("Stencil Ref", m_CurEventDataStrings.stencilRef); - - if (m_CurEventData.stencilState.readMask != 255) - EditorGUILayout.LabelField("Stencil ReadMask", m_CurEventDataStrings.stencilReadMask); - - if (m_CurEventData.stencilState.writeMask != 255) - EditorGUILayout.LabelField("Stencil WriteMask", m_CurEventDataStrings.stencilWriteMask); - - EditorGUILayout.LabelField("Stencil Comp", m_CurEventDataStrings.stencilComp); - EditorGUILayout.LabelField("Stencil Pass", m_CurEventDataStrings.stencilPass); - EditorGUILayout.LabelField("Stencil Fail", m_CurEventDataStrings.stencilFail); - EditorGUILayout.LabelField("Stencil ZFail", m_CurEventDataStrings.stencilZFail); - } - } - - internal void OnGUI() - { - FrameDebuggerEvent[] descs = FrameDebuggerUtility.GetFrameEvents(); - if (m_TreeViewState == null) - m_TreeViewState = new TreeViewState(); - if (m_Tree == null) - { - m_Tree = new FrameDebuggerTreeView(descs, m_TreeViewState, this, new Rect()); - m_FrameEventsHash = FrameDebuggerUtility.eventsHash; - m_Tree.m_DataSource.SetExpandedWithChildren(m_Tree.m_DataSource.root, true); - } - - // captured frame event contents have changed, rebuild the tree data - if (FrameDebuggerUtility.eventsHash != m_FrameEventsHash) - { - m_Tree.m_DataSource.SetEvents(descs); - m_FrameEventsHash = FrameDebuggerUtility.eventsHash; - } - - - int oldLimit = FrameDebuggerUtility.limit; - bool repaint = DrawToolbar(descs); - - if (!FrameDebuggerUtility.IsLocalEnabled() && !FrameDebuggerUtility.IsRemoteEnabled() && m_AttachProfilerUI.IsEditor()) - { - GUI.enabled = true; - - if (!FrameDebuggerUtility.locallySupported) - { - EditorGUILayout.HelpBox("Frame Debugger requires multi-threaded renderer. Usually Unity uses that; if it does not, try starting with -force-gfx-mt command line argument.", MessageType.Warning, true); - } - - // info box - EditorGUILayout.HelpBox("Frame Debugger lets you step through draw calls and see how exactly frame is rendered. Click Enable!", MessageType.Info, true); - } - else - { - float toolbarHeight = EditorStyles.toolbar.fixedHeight; - - var dragRect = new Rect(m_ListWidth, toolbarHeight, kResizerWidth, position.height - toolbarHeight); - dragRect = EditorGUIUtility.HandleHorizontalSplitter(dragRect, position.width, kMinListWidth, kMinDetailsWidth); - m_ListWidth = dragRect.x; - - var listRect = new Rect( - 0, - toolbarHeight, - m_ListWidth, - position.height - toolbarHeight); - var currentEventRect = new Rect( - m_ListWidth + kDetailsMargin, - toolbarHeight + kDetailsMargin, - position.width - m_ListWidth - kDetailsMargin * 2, - position.height - toolbarHeight - kDetailsMargin * 2); - - - DrawEventsTree(listRect); - EditorGUIUtility.DrawHorizontalSplitter(dragRect); - DrawCurrentEvent(currentEventRect, descs); - } - - if (repaint || oldLimit != FrameDebuggerUtility.limit) - RepaintOnLimitChange(); - - if (m_RepaintFrames > 0) - { - m_Tree.SelectFrameEventIndex(FrameDebuggerUtility.limit); - RepaintAllNeededThings(); - --m_RepaintFrames; - } - } - - private void RepaintOnLimitChange() - { - m_RepaintFrames = kNeedToRepaintFrames; - RepaintAllNeededThings(); - } - - private void RepaintAllNeededThings() - { - // indicate that editor needs a redraw (mostly to get offscreen cameras rendered) - EditorApplication.SetSceneRepaintDirty(); - // Note: do NOT add GameView.RepaintAll here; that would cause really confusing - // behaviors when there are offscreen (rendering into RTs) cameras. - - // redraw ourselves - Repaint(); - } - - void DrawEventsTree(Rect rect) - { - m_Tree.OnGUI(rect); - } - - internal class Styles - { - public GUIStyle header = "OL title"; - public GUIStyle entryEven = "OL EntryBackEven"; - public GUIStyle entryOdd = "OL EntryBackOdd"; - public GUIStyle rowText = "OL Label"; - public GUIStyle rowTextRight = new GUIStyle("OL Label"); - public GUIContent recordButton = new GUIContent(EditorGUIUtility.TrTextContent("Record", "Record profiling information")); - public GUIContent prevFrame = new GUIContent(EditorGUIUtility.TrIconContent("Profiler.PrevFrame", "Go back one frame")); - public GUIContent nextFrame = new GUIContent(EditorGUIUtility.TrIconContent("Profiler.NextFrame", "Go one frame forwards")); - - public GUIContent[] headerContent; - public readonly string[] batchBreakCauses; - - public static readonly string[] s_ColumnNames = new[] { "#", "Type", "Vertices", "Indices" }; - public static readonly GUIContent[] mrtLabels = new[] - { - EditorGUIUtility.TrTextContent("RT 0", "Show render target #0"), - EditorGUIUtility.TrTextContent("RT 1", "Show render target #1"), - EditorGUIUtility.TrTextContent("RT 2", "Show render target #2"), - EditorGUIUtility.TrTextContent("RT 3", "Show render target #3"), - EditorGUIUtility.TrTextContent("RT 4", "Show render target #4"), - EditorGUIUtility.TrTextContent("RT 5", "Show render target #5"), - EditorGUIUtility.TrTextContent("RT 6", "Show render target #6"), - EditorGUIUtility.TrTextContent("RT 7", "Show render target #7") - }; - public static readonly GUIContent depthLabel = EditorGUIUtility.TrTextContent("Depth", "Show depth buffer"); - public static readonly GUIContent[] channelLabels = new[] - { - EditorGUIUtility.TrTextContent("All", "Show all (RGB) color channels"), - EditorGUIUtility.TrTextContent("R", "Show red channel only"), - EditorGUIUtility.TrTextContent("G", "Show green channel only"), - EditorGUIUtility.TrTextContent("B", "Show blue channel only"), - EditorGUIUtility.TrTextContent("A", "Show alpha channel only") - }; - public static readonly GUIContent channelHeader = EditorGUIUtility.TrTextContent("Channels", "Which render target color channels to show"); - public static readonly GUIContent levelsHeader = EditorGUIUtility.TrTextContent("Levels", "Render target display black/white intensity levels"); - public static readonly GUIContent causeOfNewDrawCallLabel = EditorGUIUtility.TrTextContent("Why this draw call can't be batched with the previous one"); - public static readonly GUIContent selectShaderTooltip = EditorGUIUtility.TrTextContent("", "Click to select shader"); - public static readonly GUIContent copyToClipboardTooltip = EditorGUIUtility.TrTextContent("", "Click to copy shader and keywords text to clipboard."); - public static readonly GUIContent arrayValuePopupButton = EditorGUIUtility.TrTextContent("..."); - - public Styles() - { - rowTextRight.alignment = TextAnchor.MiddleRight; - recordButton.text = "Enable"; - recordButton.tooltip = "Enable Frame Debugging"; - prevFrame.tooltip = "Previous event"; - nextFrame.tooltip = "Next event"; - headerContent = new GUIContent[s_ColumnNames.Length]; - for (int i = 0; i < headerContent.Length; i++) - headerContent[i] = EditorGUIUtility.TextContent(s_ColumnNames[i]); - - batchBreakCauses = FrameDebuggerUtility.GetBatchBreakCauseStrings(); - } - } - - private static Styles ms_Styles; - public static Styles styles - { - get { return ms_Styles ?? (ms_Styles = new Styles()); } - } - - private class ArrayValuePopup : PopupWindowContent - { - public delegate string GetValueStringDelegate(int index, bool highPrecision); - private GetValueStringDelegate GetValueString; - - private Vector2 m_ScrollPos = Vector2.zero; - private int m_StartIndex; - private int m_NumValues; - private float m_WindowWidth; - - private static readonly GUIStyle m_Style = EditorStyles.miniLabel; - - public ArrayValuePopup(int startIndex, int numValues, float windowWidth, GetValueStringDelegate getValueString) - { - m_StartIndex = startIndex; - m_NumValues = numValues; - m_WindowWidth = windowWidth; - GetValueString = getValueString; - } - - public override Vector2 GetWindowSize() - { - float lineHeight = m_Style.lineHeight + m_Style.padding.vertical + m_Style.margin.top; - return new Vector2(m_WindowWidth, Math.Min(lineHeight * m_NumValues, 250.0f)); - } - - public override void OnGUI(Rect rect) - { - m_ScrollPos = EditorGUILayout.BeginScrollView(m_ScrollPos); - - for (int i = 0; i < m_NumValues; ++i) - { - string text = String.Format("[{0}]\t{1}", i, GetValueString(m_StartIndex + i, false)); - GUILayout.Label(text, m_Style); - } - - EditorGUILayout.EndScrollView(); - - // Right click to copy the values to clipboard. - var e = Event.current; - if (e.type == EventType.ContextClick && rect.Contains(e.mousePosition)) - { - e.Use(); - - string allText = string.Empty; - for (int i = 0; i < m_NumValues; ++i) - { - allText += String.Format("[{0}]\t{1}\n", i, GetValueString(m_StartIndex + i, true)); - } - - var menu = new GenericMenu(); - menu.AddItem(EditorGUIUtility.TrTextContent("Copy value"), false, delegate - { - EditorGUIUtility.systemCopyBuffer = allText; - }); - menu.ShowAsContext(); - } - } - } - } -} diff --git a/Editor/Mono/PerformanceTools/FrameDebuggerTreeView.cs b/Editor/Mono/PerformanceTools/FrameDebuggerTreeView.cs deleted file mode 100644 index 6236993bb5..0000000000 --- a/Editor/Mono/PerformanceTools/FrameDebuggerTreeView.cs +++ /dev/null @@ -1,272 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; -using System.Globalization; -using UnityEditor.IMGUI.Controls; - - -namespace UnityEditorInternal -{ - internal class FrameDebuggerTreeView - { - internal readonly TreeViewController m_TreeView; - internal FDTreeViewDataSource m_DataSource; - private readonly FrameDebuggerWindow m_FrameDebugger; - - public FrameDebuggerTreeView(FrameDebuggerEvent[] frameEvents, TreeViewState treeViewState, FrameDebuggerWindow window, Rect startRect) - { - m_FrameDebugger = window; - m_TreeView = new TreeViewController(window, treeViewState); - m_DataSource = new FDTreeViewDataSource(m_TreeView, frameEvents); - var gui = new FDTreeViewGUI(m_TreeView); - m_TreeView.Init(startRect, m_DataSource, gui, null); - m_TreeView.ReloadData(); - m_TreeView.selectionChangedCallback += SelectionChanged; - } - - void SelectionChanged(int[] selectedIDs) - { - if (selectedIDs.Length < 1) - return; - int id = selectedIDs[0]; - int eventIndex = id; - - // For tree hierarchy nodes, their IDs are not the frame event indices; - // fetch the ID from the node itself in that case. - // IDs for hierarchy nodes are negative and need to stay consistently ordered so - // that tree expanded state behaves well when something in the scene changes. - // - // When selecting a hierarchy node, we want it's last child event to be set as the limit, - // so that rendered state corresponds to "everything up to and including this whole sub-tree". - if (eventIndex <= 0) - { - var item = m_TreeView.FindItem(id) as FDTreeViewItem; - if (item != null) - eventIndex = item.m_EventIndex; - } - // If still has no valid ID, do nothing. - if (eventIndex <= 0) - return; - m_FrameDebugger.ChangeFrameEventLimit(eventIndex); - } - - public void SelectFrameEventIndex(int eventIndex) - { - // Check if we'd end up selecting same "frame event": - // different tree nodes could result in the same frame debugger event - // limit, e.g. a hierarchy node sets last child event as the limit. - // If the limit event is the same, then do not change the currently selected item. - int[] selection = m_TreeView.GetSelection(); - if (selection.Length > 0) - { - var item = m_TreeView.FindItem(selection[0]) as FDTreeViewItem; - if (item != null && eventIndex == item.m_EventIndex) - return; - } - - m_TreeView.SetSelection(new[] { eventIndex }, true); - } - - public void OnGUI(Rect rect) - { - var keyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard); - m_TreeView.OnGUI(rect, keyboardControlID); - } - - // Item for TreeView - // ID is different for leaf nodes (actual frame events) vs hierarchy nodes (parent profiler nodes): - // - leaf node IDs are frame event indices (always > 0). - // - 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. - private class FDTreeViewItem : TreeViewItem - { - public FrameDebuggerEvent m_FrameEvent; - public int m_ChildEventCount; - public int m_EventIndex; - public FDTreeViewItem(int id, int depth, FDTreeViewItem parent, string displayName) - : base(id, depth, parent, displayName) - { - m_EventIndex = id; - } - } - - // GUI for TreeView - - private class FDTreeViewGUI : TreeViewGUI - { - const float kSmallMargin = 4; - - public FDTreeViewGUI(TreeViewController treeView) - : base(treeView) - { - } - - protected override Texture GetIconForItem(TreeViewItem item) - { - return null; - } - - protected override void OnContentGUI(Rect rect, int row, TreeViewItem itemRaw, string label, bool selected, bool focused, bool useBoldFont, bool isPinging) - { - if (Event.current.type != EventType.Repaint) - return; - - var item = (FDTreeViewItem)itemRaw; - - // indent - float indent = GetContentIndent(item); - rect.x += indent; - rect.width -= indent; - - string text; - GUIContent gc; - GUIStyle style; - - // child event count - if (item.m_ChildEventCount > 0) - { - Rect r = rect; - r.width -= kSmallMargin; - text = item.m_ChildEventCount.ToString(CultureInfo.InvariantCulture); - gc = EditorGUIUtility.TempContent(text); - style = FrameDebuggerWindow.styles.rowTextRight; - style.Draw(r, gc, false, false, false, false); - // reduce width of available space for the name, so that it does not overlap event count - rect.width -= style.CalcSize(gc).x + kSmallMargin * 2; - } - - // draw event name - if (item.id <= 0) - text = item.displayName; // hierarchy item - else - text = FrameDebuggerWindow.s_FrameEventTypeNames[(int)item.m_FrameEvent.type] + item.displayName; // leaf event - if (string.IsNullOrEmpty(text)) - text = ""; - gc = EditorGUIUtility.TempContent(text); - style = FrameDebuggerWindow.styles.rowText; - style.Draw(rect, gc, false, false, false, selected && focused); - } - - protected override void RenameEnded() - { - } - } - - // Data source for TreeView - - internal class FDTreeViewDataSource : TreeViewDataSource - { - private FrameDebuggerEvent[] m_FrameEvents; - - public FDTreeViewDataSource(TreeViewController treeView, FrameDebuggerEvent[] frameEvents) - : base(treeView) - { - m_FrameEvents = frameEvents; - rootIsCollapsable = false; - showRootItem = false; - } - - public void SetEvents(FrameDebuggerEvent[] frameEvents) - { - var wasEmpty = m_FrameEvents == null || m_FrameEvents.Length < 1; - - m_FrameEvents = frameEvents; - m_NeedRefreshRows = true; - ReloadData(); - - // Only expand whole events tree if it was empty before. - // If we already had something in there, we want to preserve user's expanded items. - if (wasEmpty) - SetExpandedWithChildren(m_RootItem, true); - } - - public override bool IsRenamingItemAllowed(TreeViewItem item) - { - return false; - } - - public override bool CanBeMultiSelected(TreeViewItem item) - { - return false; - } - - // Used while building the tree data source; represents current tree hierarchy level - private class FDTreeHierarchyLevel - { - internal readonly FDTreeViewItem item; - internal readonly List children; - internal FDTreeHierarchyLevel(int depth, int id, string name, FDTreeViewItem parent) - { - item = new FDTreeViewItem(id, depth, parent, name); - children = new List(); - } - } - private static void CloseLastHierarchyLevel(List eventStack, int prevFrameEventIndex) - { - var idx = eventStack.Count - 1; - eventStack[idx].item.children = eventStack[idx].children; - eventStack[idx].item.m_EventIndex = prevFrameEventIndex; - if (eventStack[idx].item.parent != null) - ((FDTreeViewItem)eventStack[idx].item.parent).m_ChildEventCount += eventStack[idx].item.m_ChildEventCount; - eventStack.RemoveAt(idx); - } - - public override void FetchData() - { - var rootLevel = new FDTreeHierarchyLevel(0, 0, string.Empty, null); - - // Hierarchy levels of a tree being built - var eventStack = new List(); - eventStack.Add(rootLevel); - - int hierarchyIDCounter = -1; - for (var i = 0; i < m_FrameEvents.Length; ++i) - { - // This will be a slash-delimited string, e.g. Foo/Bar/Baz. - // Add "/" in front to account for the single (invisible) root item - // that the TreeView always has. - string context = "/" + (FrameDebuggerUtility.GetFrameEventInfoName(i) ?? string.Empty); - string[] names = context.Split('/'); - // find matching hierarchy level - int level = 0; - while (level < eventStack.Count && level < names.Length) - { - if (names[level] != eventStack[level].item.displayName) - break; - ++level; - } - // close all the further levels from previous events in the stack - while (eventStack.Count > 0 && eventStack.Count > level) - { - CloseLastHierarchyLevel(eventStack, i); - } - // add all further levels for current event - for (var j = level; j < names.Length; ++j) - { - var parent = eventStack[eventStack.Count - 1]; - var newLevel = new FDTreeHierarchyLevel(eventStack.Count - 1, --hierarchyIDCounter, names[j], parent.item); - parent.children.Add(newLevel.item); - eventStack.Add(newLevel); - } - // add leaf event to current level - var eventGo = FrameDebuggerUtility.GetFrameEventGameObject(i); - var displayName = eventGo ? " " + eventGo.name : string.Empty; - FDTreeHierarchyLevel parentEvent = eventStack[eventStack.Count - 1]; - var leafEventID = i + 1; - var item = new FDTreeViewItem(leafEventID, eventStack.Count - 1, parentEvent.item, displayName); - item.m_FrameEvent = m_FrameEvents[i]; - parentEvent.children.Add(item); - ++parentEvent.item.m_ChildEventCount; - } - while (eventStack.Count > 0) - { - CloseLastHierarchyLevel(eventStack, m_FrameEvents.Length); - } - m_RootItem = rootLevel.item; - } - } - } -} diff --git a/Editor/Mono/PlatformSupport/PlatformIconField.cs b/Editor/Mono/PlatformSupport/PlatformIconField.cs deleted file mode 100644 index 9660fea1b3..0000000000 --- a/Editor/Mono/PlatformSupport/PlatformIconField.cs +++ /dev/null @@ -1,270 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Linq; -using System.Collections; -using System.Collections.Generic; -using Object = UnityEngine.Object; -using UnityEditorInternal; - -namespace UnityEditor.PlatformSupport -{ - internal class PlatformIconFieldGroup - { - internal class IconFieldGroupInfo - { - public PlatformIconKind m_Kind; - public string m_Label; - public bool m_State; - public int m_SetIconSlots; - public int m_IconSlotCount; - - public override bool Equals(object obj) - { - return ((IconFieldGroupInfo)obj).m_Label == this.m_Label; - } - - public override int GetHashCode() - { - return this.m_Label.GetHashCode(); - } - } - - public BuildTargetGroup targetGroup { get; protected set; } - internal Dictionary> m_IconsFields = - new Dictionary>(); - - internal Dictionary m_PlatformIconsByKind = new Dictionary(); - - internal PlatformIconFieldGroup(BuildTargetGroup targetGroup) - { - this.targetGroup = targetGroup; - } - - internal PlatformIconField CreatePlatformIconField(PlatformIcon icon) - { - if (icon.maxLayerCount > 1) - return new PlatformIconFieldMultiLayer(icon, targetGroup); - - return new PlatformIconFieldSingleLayer(icon, targetGroup); - } - - public bool IsEmpty() - { - return !(m_IconsFields.Count > 0); - } - - public void AddPlatformIcons(PlatformIcon[] icons, PlatformIconKind kind) - { - m_PlatformIconsByKind[kind] = icons; - - IconFieldGroupInfo kindKey = new IconFieldGroupInfo(); - kindKey.m_Kind = kind; - kindKey.m_Label = kind.ToString(); - - Dictionary kindDictionary; - - if (!m_IconsFields.ContainsKey(kindKey)) - { - kindKey.m_State = false; - kindDictionary = new Dictionary(); - } - else - { - kindDictionary = m_IconsFields[kindKey]; - } - - var groupedBySubKind = icons.GroupBy(i => i.iconSubKind); - - foreach (var subKindGroup in groupedBySubKind) - { - var subKindIcons = subKindGroup.ToArray().Select(i => CreatePlatformIconField(i)).ToArray(); - - IconFieldGroupInfo subKindKey = new IconFieldGroupInfo(); - subKindKey.m_Kind = null; - subKindKey.m_Label = subKindGroup.Key; - subKindKey.m_IconSlotCount = subKindIcons.Length; - subKindKey.m_SetIconSlots = PlayerSettings.GetNonEmptyPlatformIconCount(subKindGroup.ToArray()); - - if (!kindDictionary.ContainsKey(subKindKey)) - subKindKey.m_State = false; - - kindKey.m_IconSlotCount += subKindKey.m_IconSlotCount; - kindKey.m_SetIconSlots += subKindKey.m_SetIconSlots; - - kindDictionary[subKindKey] = subKindIcons; - } - - m_IconsFields[kindKey] = kindDictionary; - } - } - - abstract class PlatformIconField - { - protected const int kSlotSize = 64; - protected const float kHeaderHeight = 18; - protected const int kMaxElementHeight = 116; - protected const int kMaxPreviewSize = 86; - protected const int kIconSpacing = 8; - - public PlatformIcon platformIcon { get; protected set; } - protected BuildTargetGroup m_TargetGroup; - protected string m_HeaderString; - protected string m_SizeLabel; - - // TODO move the styles to an uinified location for this & ReorderableList. - internal ReorderableList.Defaults s_Defaults = new ReorderableList.Defaults(); - - internal PlatformIconField(PlatformIcon platformIcon, BuildTargetGroup targetGroup) - { - this.platformIcon = platformIcon; - m_TargetGroup = targetGroup; - m_HeaderString = this.platformIcon.description; - m_SizeLabel = string.Format("{0}x{1}px", platformIcon.width, platformIcon.height); - } - - public static Rect GetContentRect(Rect rect, float paddingVertical = 0, float paddingHorizontal = 0) - { - Rect r = rect; - - r.yMin += paddingVertical; - r.yMax -= paddingVertical; - r.xMin += paddingHorizontal; - r.xMax -= paddingHorizontal; - return r; - } - - internal abstract void DrawAt(); - } - - class PlatformIconFieldSingleLayer : PlatformIconField - { - private bool m_ShowSizeLabel = true; - private string m_PlatformName; - - internal PlatformIconFieldSingleLayer(PlatformIcon platformIcon, BuildTargetGroup targetGroup) : base(platformIcon, targetGroup) - { - m_PlatformName = PlayerSettings.GetPlatformName(m_TargetGroup); - } - - void DrawHeader(Rect headerRect) - { - // draw the background on repaint - if (Event.current.type == EventType.Repaint) - s_Defaults.DrawHeaderBackground(headerRect); - - // apply the padding to get the internal rect - headerRect.xMin += ReorderableList.Defaults.padding; - headerRect.xMax -= ReorderableList.Defaults.padding; - headerRect.height -= 2; - headerRect.y += 1; - - m_ShowSizeLabel = headerRect.width > (EditorGUIUtility.labelWidth + kSlotSize + kIconSpacing + 24); - - - string sizeLabelString = m_HeaderString; - if (!m_ShowSizeLabel) - sizeLabelString += string.Format("({0})", m_SizeLabel); - - GUI.Label(headerRect, LocalizationDatabase.GetLocalizedString(sizeLabelString), EditorStyles.label); - } - - void DrawElement(Rect elementRect) - { - int slotWidth = kMaxPreviewSize; - int slotHeight = (int)((float)platformIcon.height / platformIcon.height * slotWidth); // take into account the aspect ratio - int previewWidth = Mathf.Min(slotWidth, platformIcon.width); - int previewHeight = (int)((float)platformIcon.height * previewWidth / platformIcon.width); // take into account the aspect ratio - - if (Event.current.type == EventType.Repaint) - s_Defaults.boxBackground.Draw(elementRect, false, false, false, false); - - float width = Mathf.Min(elementRect.width, EditorGUIUtility.labelWidth + 4 + kSlotSize + kIconSpacing + kMaxPreviewSize); - Rect elementContentRect = GetContentRect(elementRect, 6f, 12f); - Rect textureRect = - new Rect(elementContentRect.x + elementContentRect.width - kMaxPreviewSize - slotWidth - kIconSpacing, - elementContentRect.y, slotWidth, slotHeight); - - Texture2D texture = (Texture2D)EditorGUI.ObjectField( - textureRect, - platformIcon.GetTexture(0), - typeof(Texture2D), - false); - - platformIcon.SetTexture(texture, 0); - - // Preview - Rect previewRect = new Rect(elementContentRect.x + elementContentRect.width - kMaxPreviewSize, elementContentRect.y, previewWidth, previewHeight); - - GUI.Box(previewRect, ""); - Texture2D closestIcon = PlayerSettings.GetPlatformIconAtSize(m_PlatformName, platformIcon.width, platformIcon.height, platformIcon.kind.kind, platformIcon.iconSubKind); - if (closestIcon != null) - GUI.DrawTexture(GetContentRect(previewRect, 1, 1), closestIcon); - - //Do not show size label if there is not enough space for it in the body. - if (m_ShowSizeLabel) - { - GUI.Label(new Rect(elementContentRect.x, elementContentRect.y, width - kSlotSize - kIconSpacing, 20), - m_SizeLabel); - } - } - - internal override void DrawAt() - { - Rect rect = GUILayoutUtility.GetRect(0, kMaxElementHeight + kIconSpacing, GUILayout.ExpandWidth(true)); - - Rect headerRect = new Rect(rect.x, rect.y, rect.width, kHeaderHeight); - Rect elementRect = new Rect(rect.x, rect.y + kHeaderHeight, rect.width, rect.height - kHeaderHeight - kIconSpacing); - - DrawHeader(headerRect); - DrawElement(elementRect); - } - } - - class PlatformIconFieldMultiLayer : PlatformIconField - { - ReorderableIconLayerList m_IconLayers; - - void EnsureMinimumNumberOfTextures() - { - while (m_IconLayers.textures.Count < m_IconLayers.minItems) - m_IconLayers.textures.Add(null); - } - - internal PlatformIconFieldMultiLayer(PlatformIcon platformIcon, BuildTargetGroup targetGroup) : base(platformIcon, targetGroup) - { - bool showControls = this.platformIcon.minLayerCount != this.platformIcon.maxLayerCount; - - m_IconLayers = new ReorderableIconLayerList(showControls: showControls); - m_IconLayers.headerString = string.Format("{0} ({1})", this.platformIcon.description, m_SizeLabel); - m_IconLayers.minItems = this.platformIcon.minLayerCount; - m_IconLayers.maxItems = this.platformIcon.maxLayerCount; - - string[] customLayerLabels = platformIcon.kind.customLayerLabels; - if (customLayerLabels != null && customLayerLabels.Length > 0) - m_IconLayers.SetElementLabels(platformIcon.kind.customLayerLabels); - - int slotWidth = kMaxPreviewSize; - int slotHeight = (int)((float)platformIcon.height / platformIcon.height * slotWidth); - m_IconLayers.SetImageSize(slotWidth, slotHeight); - - m_IconLayers.textures = platformIcon.GetTextures().ToList(); - EnsureMinimumNumberOfTextures(); - } - - internal override void DrawAt() - { - m_IconLayers.textures = platformIcon.GetTextures().ToList(); - m_IconLayers.previewTextures = platformIcon.GetPreviewTextures().ToList(); - EnsureMinimumNumberOfTextures(); - - m_IconLayers.DoLayoutList(); - - platformIcon.SetTextures(m_IconLayers.textures.ToArray()); - } - } -} diff --git a/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs b/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs deleted file mode 100644 index 3b512404c0..0000000000 --- a/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs +++ /dev/null @@ -1,478 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -using UnityEngine.Bindings; -using UnityEngine; -using UnityEditor; -using UnityEditor.Build; - -namespace UnityEditor -{ - internal struct PlatformIconStruct - { - public int m_Width; - public int m_Height; - public int m_Kind; - public string m_SubKind; - public Texture2D[] m_Textures; - } - - public class PlatformIcon - { - internal List m_Textures; - - private PlatformIconKind m_Kind; - - private int m_MaxLayerCount; - private int m_MinLayerCount; - private string m_Description; - - private string m_iconSubKind; - private int m_Width; - private int m_Height; - - public int layerCount - { - get - { - return m_Textures.Count; - } - set - { - value = value > m_MaxLayerCount ? m_MaxLayerCount : value; - value = value < m_MinLayerCount ? m_MinLayerCount : value; - - if (value < m_Textures.Count) - m_Textures.RemoveRange(value, m_Textures.Count - 1); - else if (value > m_Textures.Count) - m_Textures.AddRange(new Texture2D[value - m_Textures.Count]); - } - } - - public int maxLayerCount { get { return m_MaxLayerCount; } private set { m_MaxLayerCount = value; } } - public int minLayerCount { get { return m_MinLayerCount; } private set { m_MinLayerCount = value; } } - internal string description { get { return m_Description; } private set { m_Description = value; } } - - internal string iconSubKind { get { return m_iconSubKind; } private set { m_iconSubKind = value; } } - public int width { get { return m_Width; } private set { m_Width = value; } } - public int height { get { return m_Height; } private set { m_Height = value; } } - - public PlatformIconKind kind - { - get { return m_Kind; } - private set - { - m_Kind = value; - // m_KindValue = value.kind; - } - } - internal PlatformIconStruct GetPlatformIconStruct() - { - PlatformIconStruct platformIconStruct = new PlatformIconStruct(); - platformIconStruct.m_Textures = m_Textures.ToArray(); - platformIconStruct.m_Width = m_Width; - platformIconStruct.m_Height = m_Height; - platformIconStruct.m_Kind = m_Kind.kind; - platformIconStruct.m_SubKind = m_iconSubKind; - - return platformIconStruct; - } - - internal bool IsEmpty() - { - return m_Textures.Count(t => t != null) == 0; - } - - internal static PlatformIcon[] GetRequiredPlatformIconsByType(IPlatformIconProvider platformIcons, PlatformIconKind kind) - { - Dictionary requiredIcons = platformIcons.GetRequiredPlatformIcons(); - - if (kind != PlatformIconKind.Any) - return requiredIcons[kind]; - - return requiredIcons.Values.SelectMany(i => i).ToArray(); - } - - internal PlatformIcon(int width, int height, int minLayerCount, int maxLayerCount, string iconSubKind, string description, PlatformIconKind kind) - { - this.width = width; - this.height = height; - this.iconSubKind = iconSubKind; - this.description = description; - this.minLayerCount = minLayerCount; - this.maxLayerCount = maxLayerCount; - this.kind = kind; - - m_Textures = new List(); - } - - public Texture2D GetTexture(int layer = 0) - { - if (layer < 0 || layer >= m_MaxLayerCount) - throw new ArgumentOutOfRangeException(string.Format("Attempting to retrieve icon layer {0}, while the icon only contains {1} layers!", layer, layerCount)); - else if (layer < layerCount) - return m_Textures[layer]; - return null; - } - - public Texture2D[] GetTextures() - { - return m_Textures.ToArray(); - } - - internal Texture2D[] GetPreviewTextures() - { - Texture2D[] previewTextures = new Texture2D[maxLayerCount]; - - for (int i = 0; i < maxLayerCount; i++) - { - previewTextures[i] = PlayerSettings.GetPlatformIconAtSize(m_Kind.platform, m_Width, m_Height, m_Kind.kind, m_iconSubKind, i); - } - - return previewTextures; - } - - public void SetTexture(Texture2D texture, int layer = 0) - { - if (layer < 0 || layer >= maxLayerCount) - { - throw new ArgumentOutOfRangeException(string.Format("Attempting to set icon layer {0}, while icon only supports {1} layers!", layer, maxLayerCount)); - } - else if (layer > m_Textures.Count - 1) - { - for (int i = m_Textures.Count; i <= layer; i++) - m_Textures.Add(null); - } - - m_Textures[layer] = texture; - } - - public void SetTextures(params Texture2D[] textures) - { - if (textures == null || textures.Length == 0 || textures.Count(t => t != null) == 0) - { - m_Textures.Clear(); - return; - } - else if (textures.Length > maxLayerCount || textures.Length < minLayerCount) - { - throw new InvalidOperationException(string.Format("Attempting to assign an incorrect amount of layers to an PlatformIcon, trying to assign {0} textures while the Icon requires atleast {1} but no more than {2} layers", - textures.Length, - minLayerCount, - maxLayerCount - ) - ); - } - - m_Textures = textures.ToList(); - } - - public override string ToString() { return string.Format("({0}x{1}) {2}", width, height, description); } - } - - public class PlatformIconKind - { - internal static readonly PlatformIconKind Any = new PlatformIconKind(-1, "Any", BuildTargetGroup.Unknown); - - internal int kind { get; private set; } - internal string platform { get; private set; } - internal string[] customLayerLabels { get; private set; } - private string kindString { get; set; } - - internal PlatformIconKind(int kind, string kindString, BuildTargetGroup platform, string[] customLayerLabels = null) - { - this.kind = kind; - this.platform = PlayerSettings.GetPlatformName(platform); - this.kindString = kindString; - this.customLayerLabels = customLayerLabels; - } - - public override bool Equals(object obj) - { - if (obj == null || GetType() != obj.GetType()) - return false; - - return kind == ((PlatformIconKind)obj).kind; - } - - public override int GetHashCode() - { - return kind.GetHashCode(); - } - - public override string ToString() { return kindString; } - } - - internal interface IPlatformIconProvider - { - Dictionary GetRequiredPlatformIcons(); - PlatformIconKind GetPlatformIconKindFromEnumValue(IconKind kind); - } - - - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - public partial class PlayerSettings : UnityEngine.Object - { - internal static Dictionary platformIconProviders = new Dictionary(); - - internal static IPlatformIconProvider GetPlatformIconProvider(BuildTargetGroup platform) - { - if (!platformIconProviders.ContainsKey(platform)) - return null; - return platformIconProviders[platform]; - } - - internal static bool HasPlatformIconProvider(BuildTargetGroup platform) - { - return platformIconProviders.ContainsKey(platform); - } - - internal static void RegisterPlatformIconProvider(BuildTargetGroup platform, IPlatformIconProvider platformIconProvider) - { - if (platformIconProviders.ContainsKey(platform)) - return; - platformIconProviders[platform] = platformIconProvider; - } - - // Loops through 'requiredIconSlots' and fills it with icons that are already serialized. - public static PlatformIcon[] GetPlatformIcons(BuildTargetGroup platform, PlatformIconKind kind) - { - IPlatformIconProvider platformIconProvider = GetPlatformIconProvider(platform); - if (platformIconProvider == null) - return new PlatformIcon[] {}; - - string platformName = PlayerSettings.GetPlatformName(platform); - - PlatformIconStruct[] serializedIcons = GetPlatformIconsInternal(platformName, kind.kind); - PlatformIcon[] icons = PlatformIcon.GetRequiredPlatformIconsByType(platformIconProvider, kind); - - if (serializedIcons.Length <= 0) - { - ImportLegacyIcons(platform, kind, icons); - SetPlatformIcons(platform, kind, icons); - } - - if (serializedIcons.Length <= 0) - { - foreach (var icon in icons) - if (icon.IsEmpty()) - icon.SetTextures(null); - } - else - { - foreach (PlatformIcon icon in icons) - { - foreach (PlatformIconStruct serializedIcon in serializedIcons) - { - int requiredKind = kind.Equals(PlatformIconKind.Any) ? serializedIcon.m_Kind : kind.kind; - if (icon.kind.kind == requiredKind && icon.iconSubKind == serializedIcon.m_SubKind) - { - if (icon.width == serializedIcon.m_Width && icon.height == serializedIcon.m_Height) - { - Texture2D[] serializedTextures = - serializedIcon.m_Textures.Take(icon.maxLayerCount).ToArray(); - Texture2D[] textures = new Texture2D[serializedTextures.Length > icon.minLayerCount - ? serializedTextures.Length - : icon.minLayerCount]; - - for (int i = 0; i < serializedTextures.Length; i++) - textures[i] = serializedTextures[i]; - - icon.SetTextures(textures); - break; - } - } - } - } - } - return icons; - } - - public static void SetPlatformIcons(BuildTargetGroup platform, PlatformIconKind kind, PlatformIcon[] icons) - { - string platformName = GetPlatformName(platform); - IPlatformIconProvider platformIconProvider = GetPlatformIconProvider(platform); - if (platformIconProvider == null) - return; - - int requiredIconCount = PlatformIcon.GetRequiredPlatformIconsByType(platformIconProvider, kind).Length; - - PlatformIconStruct[] iconStructs; - if (icons == null) - iconStructs = new PlatformIconStruct[0]; - else if (requiredIconCount != icons.Length) - { - throw new InvalidOperationException(string.Format("Attempting to set an incorrect number of icons for {0} {1} kind, it requires {2} icons but trying to assign {3}.", platform.ToString(), - kind.ToString(), - requiredIconCount, - icons.Length) - ); - } - else - { - iconStructs = icons.Select( - i => i.GetPlatformIconStruct() - ).ToArray(); - } - - SetPlatformIconsInternal(platformName, iconStructs, kind.kind); - } - - public static PlatformIconKind[] GetSupportedIconKindsForPlatform(BuildTargetGroup platform) - { - IPlatformIconProvider platformIconProvider = GetPlatformIconProvider(platform); - - if (platformIconProvider == null) - return new PlatformIconKind[] {}; - - return platformIconProvider.GetRequiredPlatformIcons().Keys.ToArray(); - } - - internal static int GetNonEmptyPlatformIconCount(PlatformIcon[] icons) - { - return icons.Count(i => !i.IsEmpty()); - } - - internal static int GetValidPlatformIconCount(PlatformIcon[] icons) - { - return icons.Count( - i => i.GetTextures().Count(t => t != null) >= i.minLayerCount && i.layerCount <= i.maxLayerCount - ); - } - - [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] - [NativeMethod(Name = "SetIconsForPlatform")] - extern internal static void SetPlatformIconsInternal(string platform, PlatformIconStruct[] icons, int kind); - - [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] - [NativeMethod(Name = "GetIconsForPlatform")] - extern internal static PlatformIconStruct[] GetPlatformIconsInternal(string platform, int kind); - - // Get the texture that will be used as the display icon at a specified size for the specified platform. - [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] - extern internal static Texture2D GetPlatformIconAtSize(string platform, int width, int height, int kind, string subKind = "", int layer = 0); - - internal static void ClearSetIconsForPlatform(BuildTargetGroup target) - { - SetPlatformIcons(target, PlatformIconKind.Any, null); - } - - // Old API methods, will be made obsolete when the new API is implemented for all platforms, - // currently it functions as a wrapper for the new API for all platforms that support it (iOS, Android & tvOS). - public static void SetIconsForTargetGroup(BuildTargetGroup platform, Texture2D[] icons, IconKind kind) - { - if (platform == BuildTargetGroup.iOS || platform == BuildTargetGroup.tvOS || platform == BuildTargetGroup.Android) - { - IPlatformIconProvider iconProvider = GetPlatformIconProvider(platform); - - if (iconProvider == null) - return; - - PlatformIconKind platformIconKind = iconProvider.GetPlatformIconKindFromEnumValue(kind); - - PlatformIcon[] platformIcons = GetPlatformIcons(platform, platformIconKind); - - for (var i = 0; i < icons.Length; i++) - platformIcons[i].SetTexture(icons[i], 0); - - SetPlatformIcons(platform, platformIconKind, platformIcons); - } - else - SetIconsForPlatform(GetPlatformName(platform), icons, kind); - } - - // Assign a list of icons for the specified platform. - public static void SetIconsForTargetGroup(BuildTargetGroup platform, Texture2D[] icons) - { - SetIconsForTargetGroup(platform, icons, IconKind.Any); - } - - // Returns the list of assigned icons for the specified platform of a specific kind. - public static Texture2D[] GetIconsForTargetGroup(BuildTargetGroup platform, IconKind kind) - { - if (platform == BuildTargetGroup.iOS || platform == BuildTargetGroup.tvOS || platform == BuildTargetGroup.Android) - { - IPlatformIconProvider iconProvider = GetPlatformIconProvider(platform); - - if (iconProvider == null) - return new Texture2D[] {}; - - PlatformIconKind platformIconKind = iconProvider.GetPlatformIconKindFromEnumValue(kind); - - return GetPlatformIcons(platform, platformIconKind).Select(t => t.GetTexture(0)).ToArray(); - } - else - { - Texture2D[] icons = GetIconsForPlatform(GetPlatformName(platform), kind); - return icons; - } - } - - internal static void ImportLegacyIcons(string platform, PlatformIconKind kind, PlatformIcon[] platformIcons) - { - if (!Enum.IsDefined(typeof(IconKind), kind.kind)) - return; - - IconKind iconKind = (IconKind)kind.kind; - - Texture2D[] legacyIcons = GetIconsForPlatform(platform, iconKind); - int[] legacyIconWidths = GetIconWidthsForPlatform(platform, iconKind); - int[] legacyIconHeights = GetIconHeightsForPlatform(platform, iconKind); - - for (var i = 0; i < legacyIcons.Length; i++) - { - List selectedIcons = new List(); - foreach (var icon in platformIcons) - { - if (icon.width == legacyIconWidths[i] && icon.height == legacyIconHeights[i]) - { - selectedIcons.Add(icon); - } - } - foreach (var selectedIcon in selectedIcons) - selectedIcon.SetTextures(legacyIcons[i]); - } - } - - internal static void ImportLegacyIcons(BuildTargetGroup platform, PlatformIconKind kind, PlatformIcon[] platformIcons) - { - ImportLegacyIcons(GetPlatformName(platform), kind, platformIcons); - } - - // Returns the list of assigned icons for the specified platform. - public static Texture2D[] GetIconsForTargetGroup(BuildTargetGroup platform) - { - return GetIconsForTargetGroup(platform, IconKind.Any); - } - - // Returns a list of icon sizes for the specified platform of a specific kind. - public static int[] GetIconSizesForTargetGroup(BuildTargetGroup platform, IconKind kind) - { - if (platform == BuildTargetGroup.iOS || platform == BuildTargetGroup.tvOS || platform == BuildTargetGroup.Android) - { - IPlatformIconProvider iconProvider = GetPlatformIconProvider(platform); - - if (iconProvider == null) - return new int[] {}; - - PlatformIconKind platformIconKind = iconProvider.GetPlatformIconKindFromEnumValue(kind); - - return GetPlatformIcons(platform, platformIconKind).Select(s => s.width).ToArray(); - } - else - return GetIconWidthsForPlatform(GetPlatformName(platform), kind); - } - - // Returns a list of icon sizes for the specified platform. - public static int[] GetIconSizesForTargetGroup(BuildTargetGroup platform) - { - return GetIconSizesForTargetGroup(platform, IconKind.Any); - } - } -} diff --git a/Editor/Mono/PlatformSupport/ReorderableTextureList.cs b/Editor/Mono/PlatformSupport/ReorderableTextureList.cs deleted file mode 100644 index 1f09c608d9..0000000000 --- a/Editor/Mono/PlatformSupport/ReorderableTextureList.cs +++ /dev/null @@ -1,159 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor.PlatformSupport -{ - class ReorderableIconLayerList - { - UnityEditorInternal.ReorderableList m_List; - - public delegate void ChangedCallbackDelegate(ReorderableIconLayerList list); - - // Used to notify about element order and content changes. The textures list - // must not be changed during the execution of the callback. - public ChangedCallbackDelegate onChangedCallback = null; - - public List textures - { - get { return (List)m_List.list; } - set { m_List.list = value; } - } - - public List previewTextures { get; set; } - - public string headerString = ""; - - const int kSlotSize = 86; - const int kIconSpacing = 6; - - public int m_ImageWidth = 20; - public int m_ImageHeight = 20; - public int minItems = 1; - public int maxItems = 5; - - - public void SetElementLabels(params string[] labels) - { - m_useCustomLayerLabel = true; - m_layerLabels = labels; - } - - private bool m_useCustomLayerLabel; - private string[] m_layerLabels; - - string GetElementLabel(int index) - { - if (m_useCustomLayerLabel) - return m_layerLabels[index]; - - string namestr = LocalizationDatabase.GetLocalizedString("Layer {0}"); - string label = String.Format(namestr, index); - - return label; - } - - public ReorderableIconLayerList(bool draggable = true, bool showControls = true) - { - m_List = new UnityEditorInternal.ReorderableList(new List(), typeof(Texture2D), draggable, true, showControls, showControls); - m_List.onAddCallback = OnAdd; - m_List.onRemoveCallback = OnRemove; - m_List.onReorderCallback = OnChange; - m_List.drawElementCallback = OnElementDraw; - m_List.drawHeaderCallback = OnHeaderDraw; - m_List.onCanAddCallback = OnCanAdd; - m_List.onCanRemoveCallback = OnCanRemove; - - UpdateElementHeight(); - } - - public void SetImageSize(int width, int height) - { - m_ImageWidth = width; - m_ImageHeight = height; - UpdateElementHeight(); - } - - void UpdateElementHeight() - { - m_List.elementHeight = kSlotSize * ((float)m_ImageHeight / m_ImageWidth); - } - - bool OnCanAdd(UnityEditorInternal.ReorderableList list) - { - return list.count < maxItems; - } - - bool OnCanRemove(UnityEditorInternal.ReorderableList list) - { - if (list.count <= minItems) - return false; - return true; - } - - void OnAdd(UnityEditorInternal.ReorderableList list) - { - textures.Add(null); - m_List.index = textures.Count - 1; - OnChange(list); - } - - void OnRemove(UnityEditorInternal.ReorderableList list) - { - textures.RemoveAt(list.index); - list.index = 0; - OnChange(list); - } - - void OnChange(UnityEditorInternal.ReorderableList list) - { - if (onChangedCallback != null) - onChangedCallback(this); - } - - void OnElementDraw(Rect rect, int index, bool isActive, bool isFocused) - { - string label = GetElementLabel(index); - - float width = Mathf.Min(rect.width, EditorGUIUtility.labelWidth + 4 + kSlotSize + kIconSpacing); - GUI.Label(new Rect(rect.x, rect.y, width - kSlotSize - kIconSpacing, 20), label); - - // Texture slot - int slotWidth = kSlotSize; - int slotHeight = (int)((float)m_ImageHeight / m_ImageWidth * kSlotSize); // take into account the aspect ratio - var textureRect = new Rect(rect.x + rect.width - slotWidth - slotWidth - kIconSpacing, rect.y, slotWidth, slotHeight); - - EditorGUI.BeginChangeCheck(); - textures[index] = (Texture2D)EditorGUI.ObjectField(textureRect, textures[index], typeof(Texture2D), false); - if (EditorGUI.EndChangeCheck()) - OnChange(m_List); - - // Preview - Rect previewRect = new Rect(rect.x + rect.width - slotWidth, rect.y, slotWidth, slotHeight); - - GUI.Box(previewRect, ""); - - Texture2D closestIcon = previewTextures[index]; - - if (closestIcon != null) - GUI.DrawTexture(PlatformIconField.GetContentRect(previewRect, 1, 1), previewTextures[index]); - } - - void OnHeaderDraw(Rect rect) - { - GUI.Label(rect, LocalizationDatabase.GetLocalizedString(headerString), EditorStyles.label); - } - - public void DoLayoutList() - { - m_List.DoLayoutList(); - } - } -} // namespace UnityEditor.AppleTV diff --git a/Editor/Mono/Playables/Playables.bindings.cs b/Editor/Mono/Playables/Playables.bindings.cs deleted file mode 100644 index c34fc288d1..0000000000 --- a/Editor/Mono/Playables/Playables.bindings.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Bindings; -using UnityEngine.Playables; -using UnityEngine.Scripting; - -namespace UnityEditor.Playables -{ - [NativeHeader("Editor/Src/Playables/Playables.bindings.h")] - static public class Utility - { - static public event Action graphCreated; - static public event Action destroyingGraph; - - [RequiredByNativeCode] - static private void OnPlayableGraphCreated(PlayableGraph graph) - { - if (graphCreated != null) - graphCreated(graph); - } - - [RequiredByNativeCode] - static private void OnDestroyingPlayableGraph(PlayableGraph graph) - { - if (destroyingGraph != null) - destroyingGraph(graph); - } - - extern static public PlayableGraph[] GetAllGraphs(); - } -} diff --git a/Editor/Mono/PlayerConnectionLogReceiver.cs b/Editor/Mono/PlayerConnectionLogReceiver.cs deleted file mode 100644 index 8631666802..0000000000 --- a/Editor/Mono/PlayerConnectionLogReceiver.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Linq; -using UnityEngine.Networking.PlayerConnection; -using UnityEditor.Networking.PlayerConnection; - -namespace UnityEditor -{ - internal class PlayerConnectionLogReceiver : ScriptableSingleton - { - static Guid logMessageId { get { return new Guid("394ada03-8ba0-4f26-b001-1a6cdeb05a62"); } } - static Guid cleanLogMessageId { get { return new Guid("3ded2dda-cdf2-46d8-a3f6-01741741e7a9"); } } - const string prefsKey = "PlayerConnectionLoggingState"; - - internal enum ConnectionState - { - Disconnected, - CleanLog, - FullLog - } - - [SerializeField] - ConnectionState state = ConnectionState.Disconnected; - - void OnEnable() - { - State = (ConnectionState)EditorPrefs.GetInt(prefsKey, (int)ConnectionState.CleanLog); - } - - internal ConnectionState State - { - get - { - return state; - } - set - { - if (state == value) - return; - - switch (state) - { - case ConnectionState.CleanLog: - EditorConnection.instance.Unregister(cleanLogMessageId, LogMessage); - break; - - case ConnectionState.FullLog: - EditorConnection.instance.Unregister(logMessageId, LogMessage); - break; - } - state = value; - switch (state) - { - case ConnectionState.CleanLog: - EditorConnection.instance.Register(cleanLogMessageId, LogMessage); - break; - - case ConnectionState.FullLog: - EditorConnection.instance.Register(logMessageId, LogMessage); - break; - } - EditorPrefs.SetInt(prefsKey, (int)state); - } - } - - void LogMessage(MessageEventArgs messageEventArgs) - { - var body = messageEventArgs.data.Skip(4).ToArray(); - string text = System.Text.Encoding.UTF8.GetString(body); - - var logType = (LogType)messageEventArgs.data[0]; - if (!Enum.IsDefined(typeof(LogType), logType)) - logType = LogType.Log; - var oldStackTraceType = Application.GetStackTraceLogType(logType); - - // We don't want stack traces from editor code in player log messages. - Application.SetStackTraceLogType(logType, StackTraceLogType.None); - - string name = ProfilerDriver.GetConnectionIdentifier(messageEventArgs.playerId); - - text = "" + name + " " + text; - Debug.unityLogger.Log(logType, text); - Application.SetStackTraceLogType(logType, oldStackTraceType); - } - } -} diff --git a/Editor/Mono/PlayerSettings.deprecated.cs b/Editor/Mono/PlayerSettings.deprecated.cs deleted file mode 100644 index e5d06349b9..0000000000 --- a/Editor/Mono/PlayerSettings.deprecated.cs +++ /dev/null @@ -1,171 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -using EditorGraphicsSettings = UnityEditor.Rendering.EditorGraphicsSettings; - -namespace UnityEditor -{ - // deprecated in 2018.1 - [Obsolete("Use AndroidArchitecture instead. (UnityUpgradable) -> AndroidArchitecture", false)] - public enum AndroidTargetDevice - { - [Obsolete("Use AndroidArchitecture.All instead. (UnityUpgradable) -> AndroidArchitecture.All", false)] - FAT = 0, - //ARMv6 = 1, - //Emulator = 2, - [Obsolete("Use AndroidArchitecture.ARMv7 instead. (UnityUpgradable) -> AndroidArchitecture.ARMv7", false)] - ARMv7 = 3, - [Obsolete("Use AndroidArchitecture.X86 instead. (UnityUpgradable) -> AndroidArchitecture.X86", false)] - x86 = 4, - } - // deprecated in 5.1. - [Obsolete("TargetGlesGraphics is ignored, use SetGraphicsAPIs/GetGraphicsAPIs APIs", false)] - public enum TargetGlesGraphics - { - OpenGLES_1_x = 0, - OpenGLES_2_0 = 1, - OpenGLES_3_0 = 2, - Automatic = -1, - } - [Obsolete("TargetIOSGraphics is ignored, use SetGraphicsAPIs/GetGraphicsAPIs APIs", false)] - public enum TargetIOSGraphics - { - OpenGLES_2_0 = 2, - OpenGLES_3_0 = 3, - Metal = 4, - Automatic = -1, - } - // deprecated in 5.3 - [Obsolete("Use Screen.SetResolution APIs", true)] - public enum iOSTargetResolution - { - Native = 0, - ResolutionAutoPerformance = 3, - ResolutionAutoQuality = 4, - Resolution320p = 5, - Resolution640p = 6, - Resolution768p = 7 - } - // deprecated in 5.5 - [Obsolete("targetOSVersion is obsolete, use targetOSVersionString", false)] - public enum iOSTargetOSVersion - { - iOS_4_0 = 10, - iOS_4_1 = 12, - iOS_4_2 = 14, - iOS_4_3 = 16, - iOS_5_0 = 18, - iOS_5_1 = 20, - iOS_6_0 = 22, - iOS_7_0 = 24, - iOS_7_1 = 26, - iOS_8_0 = 28, - iOS_8_1 = 30, - Unknown = 999, - } - - // deprecated in 5.6 - [Flags] - [Obsolete("Use UnityEngine.iOS.SystemGestureDeferMode instead. (UnityUpgradable) -> [UnityEngine] UnityEngine.iOS.SystemGestureDeferMode", true)] - public enum iOSSystemGestureDeferMode: uint - { - None = 0, - TopEdge = 1 << 0, - LeftEdge = 1 << 1, - BottomEdge = 1 << 2, - RightEdge = 1 << 3, - All = TopEdge | LeftEdge | BottomEdge | RightEdge - } - - partial class PlayerSettings - { - // deprecated since forever - [Obsolete("The option alwaysDisplayWatermark is deprecated and is always false", true)] - public static bool alwaysDisplayWatermark { get { return false; } set {} } - [Obsolete("Use AssetBundles instead for streaming data", true)] - public static int firstStreamedLevelWithResources { get { return 0; } set {} } - - // deprecated in 5.1. - [Obsolete("targetGlesGraphics is ignored, use SetGraphicsAPIs/GetGraphicsAPIs APIs", false)] - public static TargetGlesGraphics targetGlesGraphics { get { return TargetGlesGraphics.Automatic; } set {} } - [Obsolete("targetIOSGraphics is ignored, use SetGraphicsAPIs/GetGraphicsAPIs APIs", false)] - public static TargetIOSGraphics targetIOSGraphics { get { return TargetIOSGraphics.Automatic; } set {} } - - // deprecated in 5.5 - [Obsolete("Use PlayerSettings.iOS.locationUsageDescription instead (UnityUpgradable) -> UnityEditor.PlayerSettings/iOS.locationUsageDescription", false)] - public static string locationUsageDescription { get { return iOS.locationUsageDescription; } set { iOS.locationUsageDescription = value; } } - - // deprecated in 5.5 - [Obsolete("renderingPath is ignored, use UnityEditor.Rendering.TierSettings with UnityEditor.Rendering.SetTierSettings/GetTierSettings instead", false)] - public static RenderingPath renderingPath { get { return EditorGraphicsSettings.GetCurrentTierSettings().renderingPath; } set {} } - [Obsolete("mobileRenderingPath is ignored, use UnityEditor.Rendering.TierSettings with UnityEditor.Rendering.SetTierSettings/GetTierSettings instead", false)] - public static RenderingPath mobileRenderingPath { get { return EditorGraphicsSettings.GetCurrentTierSettings().renderingPath; } set {} } - - // deprecated in 5.6 - [Obsolete("Use PlayerSettings.applicationIdentifier instead (UnityUpgradable) -> UnityEditor.PlayerSettings.applicationIdentifier", true)] - public static string bundleIdentifier { get { return applicationIdentifier; } set { applicationIdentifier = value; } } - } - - partial class PlayerSettings - { - partial class Android - { - // deprecated in 2018.1 - [Obsolete("Use targetArchitectures instead. (UnityUpgradable) -> targetArchitectures", false)] - public static AndroidTargetDevice targetDevice - { - get - { - switch (targetArchitectures) - { - case AndroidArchitecture.ARMv7: - return AndroidTargetDevice.ARMv7; - case AndroidArchitecture.X86: - return AndroidTargetDevice.x86; - default: - return AndroidTargetDevice.FAT; - } - } - set - { - switch (value) - { - case AndroidTargetDevice.ARMv7: - targetArchitectures = AndroidArchitecture.ARMv7; - break; - case AndroidTargetDevice.x86: - targetArchitectures = AndroidArchitecture.X86; - break; - default: - targetArchitectures = AndroidArchitecture.ARMv7 | AndroidArchitecture.X86; - break; - } - } - } - } - - partial class iOS - { - // deprecated in 5.0 - [Obsolete("exitOnSuspend is deprecated, use appInBackgroundBehavior", false)] - public static bool exitOnSuspend - { - get { return appInBackgroundBehavior == iOSAppInBackgroundBehavior.Exit; } - set { appInBackgroundBehavior = iOSAppInBackgroundBehavior.Exit; } - } - - // deprecated in 5.3 - [Obsolete("Use Screen.SetResolution at runtime", true)] - public static iOSTargetResolution targetResolution { get { return 0; } set {} } - - // deprecated in 5.5 - [Obsolete("Use PlayerSettings.muteOtherAudioSources instead (UnityUpgradable) -> UnityEditor.PlayerSettings.muteOtherAudioSources", false)] - public static bool overrideIPodMusic { get { return PlayerSettings.muteOtherAudioSources; } set { PlayerSettings.muteOtherAudioSources = value; } } - } - } -} - diff --git a/Editor/Mono/PlayerSettingsIOS.bindings.cs b/Editor/Mono/PlayerSettingsIOS.bindings.cs deleted file mode 100644 index 4be67cb24d..0000000000 --- a/Editor/Mono/PlayerSettingsIOS.bindings.cs +++ /dev/null @@ -1,571 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Text.RegularExpressions; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections.Generic; -using UnityEditorInternal; -using UnityEngine.Bindings; - -using UnityEngine; - -namespace UnityEditor -{ - // Supported iOS SDK versions - public enum iOSSdkVersion - { - // Device SDK - DeviceSDK = 988, - // Simulator SDK - SimulatorSDK = 989 - } - - // Target iOS device - public enum iOSTargetDevice - { - // iPhone/iPod Only - iPhoneOnly = 0, - - // iPad Only - iPadOnly = 1, - - // Universal : iPhone/iPod + iPad - iPhoneAndiPad = 2, - } - - // Activity Indicator on loading - public enum iOSShowActivityIndicatorOnLoading - { - // White Large - WhiteLarge = 0, - - // White - White = 1, - - // Gray - Gray = 2, - - // Don't Show - DontShow = -1 - } - - // iOS status bar style - public enum iOSStatusBarStyle - { - // A dark status bar, intended for use on light backgrounds - Default = 0, - - // A light status bar, intended for use on dark backgrounds - LightContent = 1, - - [Obsolete("BlackTranslucent has no effect, use LightContent instead (UnityUpgradable) -> LightContent", true)] - BlackTranslucent = -1, - - [Obsolete("BlackOpaque has no effect, use LightContent instead (UnityUpgradable) -> LightContent", true)] - BlackOpaque = -1, - } - - public enum iOSAppInBackgroundBehavior - { - Custom = -1, - Suspend = 0, - Exit = 1, - } - - [Flags] - public enum iOSBackgroundMode: uint - { - None = 0, - Audio = 1 << 0, - Location = 1 << 1, - VOIP = 1 << 2, - NewsstandContent = 1 << 3, - ExternalAccessory = 1 << 4, - BluetoothCentral = 1 << 5, - BluetoothPeripheral = 1 << 6, - Fetch = 1 << 7, - RemoteNotification = 1 << 8, - } - - public enum iOSLaunchScreenImageType - { - iPhonePortraitImage = 0, - iPhoneLandscapeImage = 1, - iPadImage = 2, - } - - // extern splash screen type (on iOS) - public enum iOSLaunchScreenType - { - // Default - Default = 0, - - // Image and background (relative size) - ImageAndBackgroundRelative = 1, - - // extern XIB file - CustomXib = 2, - - // None - None = 3, - - // Image and background (constant size) - ImageAndBackgroundConstant = 4 - } - - internal enum iOSAutomaticallySignValue - { - AutomaticallySignValueNotSet = 0, - AutomaticallySignValueTrue = 1, - AutomaticallySignValueFalse = 2 - } - - public class iOSDeviceRequirement - { - SortedDictionary m_Values = new SortedDictionary(); - public IDictionary values { get { return m_Values; } } - } - - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - [NativeHeader("Editor/Src/PlayerSettingsIOS.bindings.h")] - internal partial class iOSDeviceRequirementGroup - { - private string m_VariantName; - - [FreeFunction("PlayerSettingsIOSBindings::SetOrAddDeviceRequirementForVariantNameImpl")] - extern private static void SetOrAddDeviceRequirementForVariantNameImpl(string name, int index, string[] keys, string[] values); - - [NativeMethod(Name = "GetIOSDeviceRequirementCountForVariantName")] - [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] - extern private static int GetCountForVariantImpl(string name); - - //[NativeMethod("RemoveIOSDeviceRequirementForVariantName")] - [NativeMethod(Name = "RemoveIOSDeviceRequirementForVariantName")] - [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] - extern private static void RemoveAtImpl(string name, int index); - - internal iOSDeviceRequirementGroup(string variantName) - { - m_VariantName = variantName; - } - - public int count { get { return GetCountForVariantImpl(m_VariantName); } } - - public iOSDeviceRequirement this[int index] - { - get - { - string[] keys; - string[] values; - GetDeviceRequirementForVariantNameImpl(m_VariantName, index, out keys, out values); - var result = new iOSDeviceRequirement(); - for (int i = 0; i < keys.Length; ++i) - { - result.values.Add(keys[i], values[i]); - } - return result; - } - set - { - SetOrAddDeviceRequirementForVariantNameImpl(m_VariantName, index, value.values.Keys.ToArray(), - value.values.Values.ToArray()); - } - } - - public void RemoveAt(int index) - { - RemoveAtImpl(m_VariantName, index); - } - - public void Add(iOSDeviceRequirement requirement) - { - SetOrAddDeviceRequirementForVariantNameImpl(m_VariantName, -1, requirement.values.Keys.ToArray(), - requirement.values.Values.ToArray()); - } - } - - - // 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. - public partial class PlayerSettings : UnityEngine.Object - { - // iOS specific player settings - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - [NativeHeader("Editor/Src/EditorUserBuildSettings.h")] - [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] - public partial class iOS - { - // iOS application display name - [NativeProperty("ProductName")] - public extern static string applicationDisplayName { get; set; } - - // iOS bundle build number - public static string buildNumber - { - get { return PlayerSettings.GetBuildNumber(BuildTargetGroup.iOS); } - set { PlayerSettings.SetBuildNumber(BuildTargetGroup.iOS, value); } - } - public extern static bool disableDepthAndStencilBuffers { get; set; } - - // Script calling optimization - private extern static int scriptCallOptimizationInternal - { - [NativeMethod("GetiPhoneScriptCallOptimization")] - get; - [NativeMethod("SetiPhoneScriptCallOptimization")] - set; - } - - public static ScriptCallOptimizationLevel scriptCallOptimization - { - get { return (ScriptCallOptimizationLevel)scriptCallOptimizationInternal; } - set { scriptCallOptimizationInternal = (int)value; } - } - private extern static int sdkVersionInternal - { - [NativeMethod("GetiPhoneSdkVersion")] - get; - [NativeMethod("SetiPhoneSdkVersion")] - set; - } - - // Active iOS SDK version used for build - public static iOSSdkVersion sdkVersion - { - get { return (iOSSdkVersion)sdkVersionInternal; } - set { sdkVersionInternal = (int)value; } - } - - [FreeFunction] - private extern static string iOSTargetOSVersionObsoleteEnumToString(int val); - - [FreeFunction] - private extern static int iOSTargetOSVersionStringToObsoleteEnum(string val); - - // Deployment minimal version of iOS - [Obsolete("OBSOLETE warning targetOSVersion is obsolete, use targetOSVersionString")] - public static iOSTargetOSVersion targetOSVersion - { - get - { - return (iOSTargetOSVersion)iOSTargetOSVersionStringToObsoleteEnum(targetOSVersionString); - } - set - { - targetOSVersionString = iOSTargetOSVersionObsoleteEnumToString((int)value); - } - } - - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - [NativeMethod("GetiOSMinimumVersionString")] - static extern string GetMinimumVersionString(); - - internal static readonly Version minimumOsVersion = new Version(GetMinimumVersionString()); - - [NativeProperty("iOSTargetOSVersion")] - public extern static string targetOSVersionString - { - [NativeMethod("GetiOSTargetOSVersion")] - get; - [NativeMethod("SetiOSTargetOSVersion")] - set; - } - - // Targeted device - [NativeProperty("TargetDevice")] - private extern static int targetDeviceInternal { get; set; } - - - // Active iOS SDK version used for build - public static iOSTargetDevice targetDevice - { - get { return (iOSTargetDevice)targetDeviceInternal; } - set { targetDeviceInternal = (int)value; } - } - - // Icon is prerendered - [NativeProperty("UIPrerenderedIcon")] - public extern static bool prerenderedIcon { get; set; } - - // Application requires persistent WiFi - [NativeProperty("UIRequiresPersistentWiFi")] - public extern static bool requiresPersistentWiFi { get; set; } - - // Require Full Screen on iOS for iOS 9.0 Multitasking support - [NativeProperty("UIRequiresFullScreen")] - public extern static bool requiresFullScreen { get; set; } - - // Status bar style - [NativeProperty("UIStatusBarStyle")] - private extern static int statusBarStyleInternal { get; set; } - - - [NativeProperty("UIStatusBarStyle")] - public static iOSStatusBarStyle statusBarStyle - { - get { return (iOSStatusBarStyle)statusBarStyleInternal; } - set { statusBarStyleInternal = (int)value; } - } - - // On iPhone 10 the home button is implemented as a system gesture. (swipe up - // from the lower edge). This might interfere with games that use swipes as - // an interaction method. iOS provides a way to reduce the chance of unwanted - // interaction by marking edges as "protected" edges, so the system gesture - // is not recognized on the first swipe, but on the second if it comes - // immediately afterwards. - [NativeProperty("DeferSystemGesturesMode")] - private extern static int deferSystemGesturesModeInternal { get; set; } - - public static UnityEngine.iOS.SystemGestureDeferMode deferSystemGesturesMode - { - get { return (UnityEngine.iOS.SystemGestureDeferMode)deferSystemGesturesModeInternal; } - set { deferSystemGesturesModeInternal = (int)value; } - } - - [NativeProperty("HideHomeButton")] - public static bool hideHomeButton { get; set; } - - [NativeProperty("IOSAppInBackgroundBehavior")] - private extern static int appInBackgroundBehaviorInternal { get; set; } - - [NativeProperty("IOSAppInBackgroundBehavior")] - public static iOSAppInBackgroundBehavior appInBackgroundBehavior - { - get { return (iOSAppInBackgroundBehavior)appInBackgroundBehaviorInternal; } - set { appInBackgroundBehaviorInternal = (int)value; } - } - - [NativeProperty("IOSBackgroundModes")] - private extern static int backgroundModesInternal { get; set; } - - [NativeProperty("IOSAppInBackgroundBehavior")] - public static iOSBackgroundMode backgroundModes - { - get { return (iOSBackgroundMode)backgroundModesInternal; } - set { backgroundModesInternal = (int)value; } - } - - [NativeProperty("IOSMetalForceHardShadows")] - public extern static bool forceHardShadowsOnMetal - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - [NativeProperty("IOSAllowHTTPDownload")] - public extern static bool allowHTTPDownload { get; set; } - - [NativeProperty("AppleDeveloperTeamID")] - private extern static string appleDeveloperTeamIDInternal - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - public static string appleDeveloperTeamID - { - get - { - return appleDeveloperTeamIDInternal.Length < 1 ? - EditorPrefs.GetString("DefaultiOSAutomaticSignTeamId") : appleDeveloperTeamIDInternal; - } - set { appleDeveloperTeamIDInternal = value; } - } - - - [NativeProperty("iOSManualProvisioningProfileID")] - private extern static string iOSManualProvisioningProfileIDInternal - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - public static string iOSManualProvisioningProfileID - { - get - { - return String.IsNullOrEmpty(iOSManualProvisioningProfileIDInternal) ? - EditorPrefs.GetString("DefaultiOSProvisioningProfileUUID") : iOSManualProvisioningProfileIDInternal; - } - set { iOSManualProvisioningProfileIDInternal = value; } - } - - - [NativeProperty("tvOSManualProvisioningProfileID")] - private extern static string tvOSManualProvisioningProfileIDInternal - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - public static string tvOSManualProvisioningProfileID - { - get - { - return String.IsNullOrEmpty(tvOSManualProvisioningProfileIDInternal) ? - EditorPrefs.GetString("DefaulttvOSProvisioningProfileUUID") : tvOSManualProvisioningProfileIDInternal; - } - set { tvOSManualProvisioningProfileIDInternal = value; } - } - - - [NativeProperty("AppleEnableAutomaticSigning")] - private extern static int appleEnableAutomaticSigningInternal - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - public static bool appleEnableAutomaticSigning - { - get - { - return appleEnableAutomaticSigningInternal == (int)iOSAutomaticallySignValue.AutomaticallySignValueNotSet ? - EditorPrefs.GetBool("DefaultiOSAutomaticallySignBuild") : - (iOSAutomaticallySignValue)appleEnableAutomaticSigningInternal == iOSAutomaticallySignValue.AutomaticallySignValueTrue; - } - set - { - appleEnableAutomaticSigningInternal = value ? - (int)iOSAutomaticallySignValue.AutomaticallySignValueTrue : - (int)iOSAutomaticallySignValue.AutomaticallySignValueFalse; - } - } - - - [NativeProperty("CameraUsageDescription")] - public extern static string cameraUsageDescription { get; set; } - - [NativeProperty("LocationUsageDescription")] - public extern static string locationUsageDescription { get; set; } - - [NativeProperty("MicrophoneUsageDescription")] - public extern static string microphoneUsageDescription { get; set; } - - [NativeProperty("IOSShowActivityIndicatorOnLoading")] - private extern static int showActivityIndicatorOnLoadingInternal { get; set; } - - // Application should show ActivityIndicator when loading - [NativeProperty("IOSAppInBackgroundBehavior")] - public static iOSShowActivityIndicatorOnLoading showActivityIndicatorOnLoading - { - get { return (iOSShowActivityIndicatorOnLoading)showActivityIndicatorOnLoadingInternal; } - set { showActivityIndicatorOnLoadingInternal = (int)value; } - } - - [NativeProperty("UseOnDemandResources")] - public extern static bool useOnDemandResources { get; set; } - - // will be public - [NativeMethod(Name = "GetIOSVariantsWithDeviceRequirements")] - extern internal static string[] GetAssetBundleVariantsWithDeviceRequirements(); - - private static extern int GetIOSDeviceRequirementCountForVariantName(string name); - - private static bool CheckAssetBundleVariantHasDeviceRequirements(string name) - { - return GetIOSDeviceRequirementCountForVariantName(name) > 0; - } - - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - [NativeMethod(Name = "SetiOSLaunchScreenImage")] - private extern static void SetLaunchScreenImageInternal(Texture2D image, int type); - - public static void SetLaunchScreenImage(Texture2D image, iOSLaunchScreenImageType type) - { - SetLaunchScreenImageInternal(image, (int)type); - } - - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - private extern static void SetiOSLaunchScreenType(int type, int device); - - public static void SetiPhoneLaunchScreenType(iOSLaunchScreenType type) - { - SetiOSLaunchScreenType((int)type, 0); - } - - public static void SetiPadLaunchScreenType(iOSLaunchScreenType type) - { - SetiOSLaunchScreenType((int)type, 1); - } - - // will be public - internal static iOSDeviceRequirementGroup GetDeviceRequirementsForAssetBundleVariant(string name) - { - if (!CheckAssetBundleVariantHasDeviceRequirements(name)) - return null; - return new iOSDeviceRequirementGroup(name); - } - - // will be public - internal static void RemoveDeviceRequirementsForAssetBundleVariant(string name) - { - var group = GetDeviceRequirementsForAssetBundleVariant(name); - for (int i = 0; i < group.count; ++i) - group.RemoveAt(0); - } - - // will be public - internal static iOSDeviceRequirementGroup AddDeviceRequirementsForAssetBundleVariant(string name) - { - return new iOSDeviceRequirementGroup(name); - } - - [NativeProperty("iOSURLSchemes", false, TargetType.Field)] - private extern static string[] iOSURLSchemes - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - } - - [NativeProperty("iOSRequireARKit")] - internal extern static bool requiresARKitSupport - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - internal extern static bool appleEnableProMotion - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - internal static bool IsTargetVersionEqualOrHigher(Version requiredVersion) - { - Version requestedVersion; - try - { - requestedVersion = new Version(targetOSVersionString); - } - catch (Exception) - { - requestedVersion = minimumOsVersion; - } - return requestedVersion >= requiredVersion; - } - - internal static string[] GetURLSchemes() - { - return iOSURLSchemes; - } - } - } -} diff --git a/Editor/Mono/PlayerSettingsMacOS.bindings.cs b/Editor/Mono/PlayerSettingsMacOS.bindings.cs deleted file mode 100644 index cae03b1091..0000000000 --- a/Editor/Mono/PlayerSettingsMacOS.bindings.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - public partial class PlayerSettings : UnityEngine.Object - { - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] - public class macOS - { - public static string buildNumber - { - get { return PlayerSettings.GetBuildNumber(BuildTargetGroup.Standalone); } - set { PlayerSettings.SetBuildNumber(BuildTargetGroup.Standalone, value); } - } - - [NativeProperty("MacAppStoreCategory")] - extern internal static string applicationCategoryType { get; set; } - } - } -} diff --git a/Editor/Mono/PlayerSettingsPS4.bindings.cs b/Editor/Mono/PlayerSettingsPS4.bindings.cs deleted file mode 100644 index 4558a08db7..0000000000 --- a/Editor/Mono/PlayerSettingsPS4.bindings.cs +++ /dev/null @@ -1,190 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; -using System; -using System.Runtime.CompilerServices; - -namespace UnityEditor -{ - public sealed partial class PlayerSettings - { - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - public sealed partial class PS4 - { - public enum PS4AppCategory - { - Application = 0, // Application package. - Patch = 1, // Patch - Remaster = 2, // Remaster package - } - - public enum PS4RemotePlayKeyAssignment - { - None = -1, - PatternA = 0, - PatternB = 1, - PatternC = 2, - PatternD = 3, - PatternE = 4, - PatternF = 5, - PatternG = 6, - PatternH = 7, - } - - public enum PS4EnterButtonAssignment - { - CircleButton = 0, - CrossButton = 1, - } - - public enum PlayStationVREyeToEyeDistanceSettings - { - PerUser = 0, - ForceDefault = 1, - DynamicModeAtRuntime = 2, - } - - [NativeProperty("ps4NPTrophyPackPath")] extern public static string npTrophyPackPath { get; set; } - [NativeProperty("ps4NPAgeRating", false, TargetType.Field)] extern public static int npAgeRating { get; set; } - [NativeProperty("ps4NPTitleSecret", false, TargetType.Function)] extern public static string npTitleSecret { get; set; } - [NativeProperty("ps4ParentalLevel", false, TargetType.Field)] extern public static int parentalLevel { get; set; } - [NativeProperty("ps4ApplicationParam1", false, TargetType.Field)] extern public static int applicationParameter1 { get; set; } - [NativeProperty("ps4ApplicationParam2", false, TargetType.Field)] extern public static int applicationParameter2 { get; set; } - [NativeProperty("ps4ApplicationParam3", false, TargetType.Field)] extern public static int applicationParameter3 { get; set; } - [NativeProperty("ps4ApplicationParam4", false, TargetType.Field)] extern public static int applicationParameter4 { get; set; } - [NativeProperty("ps4Passcode", false, TargetType.Function)] extern public static string passcode { get; set; } - [NativeProperty("monoEnv", false, TargetType.Function)] extern public static string monoEnv { get; set; } - [NativeProperty(TargetType = TargetType.Field)] extern public static bool playerPrefsSupport { get; set; } - [NativeProperty(TargetType = TargetType.Field)] extern public static bool restrictedAudioUsageRights { get; set; } - [NativeProperty("ps4UseResolutionFallback", false, TargetType.Field)] extern public static bool useResolutionFallback { get; set; } - [NativeProperty("ps4ContentID", false, TargetType.Function)] extern public static string contentID { get; set; } - [NativeProperty("ps4Category", false, TargetType.Field)] extern public static PS4AppCategory category { get; set; } - [NativeProperty("ps4AppType", false, TargetType.Field)] extern public static int appType { get; set; } - [NativeProperty("ps4MasterVersion", false, TargetType.Function)] extern public static string masterVersion { get; set; } - [NativeProperty("ps4AppVersion", false, TargetType.Function)] extern public static string appVersion { get; set; } - [NativeProperty("ps4RemotePlayKeyAssignment", false, TargetType.Field)] extern public static PS4RemotePlayKeyAssignment remotePlayKeyAssignment { get; set; } - [NativeProperty("ps4RemotePlayKeyMappingDir", false, TargetType.Function)] extern public static string remotePlayKeyMappingDir { get; set; } - [NativeProperty("ps4PlayTogetherPlayerCount", false, TargetType.Field)] extern public static int playTogetherPlayerCount { get; set; } - [NativeProperty("ps4EnterButtonAssignment", false, TargetType.Field)] extern public static PS4EnterButtonAssignment enterButtonAssignment { get; set; } - [NativeProperty("ps4ParamSfxPath", false, TargetType.Function)] extern public static string paramSfxPath { get; set; } - [NativeProperty("ps4VideoOutPixelFormat", false, TargetType.Field)] extern public static int videoOutPixelFormat { get; set; } - [NativeProperty("ps4VideoOutInitialWidth", false, TargetType.Field)] extern public static int videoOutInitialWidth { get; set; } - - [Obsolete("videoOutResolution is deprecated. Use PlayerSettings.PS4.videoOutInitialWidth and PlayerSettings.PS4.videoOutReprojectionRate to control initial display resolution and reprojection rate.")] - public static int videoOutResolution - { - get - { - int reprojectionRate = videoOutReprojectionRate; - int initialWidth = videoOutInitialWidth; - switch (reprojectionRate) - { // if we have any projection rates then assume we have 1920x1080 res - case 60: - return 5; // 1920By1080_VR60 - case 90: - return 6; // 1920By1080_VR90 - case 120: - return 7; // 1920By1080_VR120 - default: - switch (initialWidth) - { - case 1280: - return 0; // 1280By720 - case 1440: - return 1; // 1440By810 - case 1600: - return 2; // 1660By900 - case 1760: - return 3; // 1760By990 - default: - case 1920: - return 4; // 1920By1080 - } - } - } - set - { - int reprojectionRate = 0; - int initialWidth = 1920; - switch (value) - { - case 0: - initialWidth = 1280; - break; - case 1: - initialWidth = 1440; - break; - case 2: - initialWidth = 1600; - break; - case 3: - initialWidth = 1760; - break; - case 4: - initialWidth = 1920; - break; - case 5: - reprojectionRate = 60; - break; - case 6: - reprojectionRate = 90; - break; - case 7: - reprojectionRate = 120; - break; - } - videoOutInitialWidth = initialWidth; - videoOutReprojectionRate = reprojectionRate; - } - } - - [NativeProperty("ps4VideoOutBaseModeInitialWidth", false, TargetType.Field)] extern public static int videoOutBaseModeInitialWidth { get; set; } - [NativeProperty("ps4VideoOutReprojectionRate", false, TargetType.Field)] extern public static int videoOutReprojectionRate { get; set; } - [NativeProperty("ps4PronunciationXMLPath", false, TargetType.Function)] extern public static string PronunciationXMLPath { get; set; } - [NativeProperty("ps4PronunciationSIGPath", false, TargetType.Function)] extern public static string PronunciationSIGPath { get; set; } - [NativeProperty("ps4BackgroundImagePath", false, TargetType.Function)] extern public static string BackgroundImagePath { get; set; } - [NativeProperty("ps4StartupImagePath", false, TargetType.Function)] extern public static string StartupImagePath { get; set; } - [NativeProperty("ps4StartupImagesFolder", false, TargetType.Function)] extern public static string startupImagesFolder { get; set; } - [NativeProperty("ps4IconImagesFolder", false, TargetType.Function)] extern public static string iconImagesFolder { get; set; } - [NativeProperty("ps4SaveDataImagePath", false, TargetType.Function)] extern public static string SaveDataImagePath { get; set; } - [NativeProperty("ps4SdkOverride", false, TargetType.Function)] extern public static string SdkOverride { get; set; } - [NativeProperty("ps4BGMPath", false, TargetType.Function)] extern public static string BGMPath { get; set; } - [NativeProperty("ps4ShareFilePath", false, TargetType.Function)] extern public static string ShareFilePath { get; set; } - [NativeProperty("ps4ShareOverlayImagePath", false, TargetType.Function)] extern public static string ShareOverlayImagePath { get; set; } - [NativeProperty("ps4PrivacyGuardImagePath", false, TargetType.Function)] extern public static string PrivacyGuardImagePath { get; set; } - [NativeProperty("ps4PatchDayOne", false, TargetType.Field)] extern public static bool patchDayOne { get; set; } - [NativeProperty("ps4PatchPkgPath", false, TargetType.Function)] extern public static string PatchPkgPath { get; set; } - [NativeProperty("ps4PatchLatestPkgPath", false, TargetType.Function)] extern public static string PatchLatestPkgPath { get; set; } - [NativeProperty("ps4PatchChangeinfoPath", false, TargetType.Function)] extern public static string PatchChangeinfoPath { get; set; } - [NativeProperty("ps4NPtitleDatPath", false, TargetType.Function)] extern public static string NPtitleDatPath { get; set; } - [NativeProperty("ps4pnSessions", false, TargetType.Field)] extern public static bool pnSessions { get; set; } - [NativeProperty("ps4pnPresence", false, TargetType.Field)] extern public static bool pnPresence { get; set; } - [NativeProperty("ps4pnFriends", false, TargetType.Field)] extern public static bool pnFriends { get; set; } - [NativeProperty("ps4pnGameCustomData", false, TargetType.Field)] extern public static bool pnGameCustomData { get; set; } - [NativeProperty("ps4DownloadDataSize", false, TargetType.Field)] extern public static int downloadDataSize { get; set; } - [NativeProperty("ps4GarlicHeapSize", false, TargetType.Field)] extern public static int garlicHeapSize { get; set; } - [NativeProperty("ps4ProGarlicHeapSize", false, TargetType.Field)] extern public static int proGarlicHeapSize { get; set; } - [NativeProperty("ps4ReprojectionSupport", false, TargetType.Field)] extern public static bool reprojectionSupport { get; set; } - [NativeProperty("ps4UseAudio3dBackend", false, TargetType.Field)] extern public static bool useAudio3dBackend { get; set; } - [NativeProperty("ps4Audio3dVirtualSpeakerCount", false, TargetType.Field)] extern public static int audio3dVirtualSpeakerCount { get; set; } - [NativeProperty("ps4ScriptOptimizationLevel", false, TargetType.Field)] extern public static int scriptOptimizationLevel { get; set; } - [NativeProperty("ps4SocialScreenEnabled", false, TargetType.Field)] extern public static int socialScreenEnabled { get; set; } - [NativeProperty("ps4attribUserManagement", false, TargetType.Field)] extern public static bool attribUserManagement { get; set; } - [NativeProperty("ps4attribMoveSupport", false, TargetType.Field)] extern public static bool attribMoveSupport { get; set; } - [NativeProperty("ps4attrib3DSupport", false, TargetType.Field)] extern public static bool attrib3DSupport { get; set; } - [NativeProperty("ps4attribShareSupport", false, TargetType.Field)] extern public static bool attribShareSupport { get; set; } - [NativeProperty("ps4attribExclusiveVR", false, TargetType.Field)] extern public static bool attribExclusiveVR { get; set; } - [NativeProperty("ps4disableAutoHideSplash", false, TargetType.Field)] extern public static bool disableAutoHideSplash { get; set; } - [NativeProperty("ps4attribCpuUsage", false, TargetType.Field)] extern public static int attribCpuUsage { get; set; } - [NativeProperty("ps4videoRecordingFeaturesUsed", false, TargetType.Field)] extern public static bool videoRecordingFeaturesUsed { get; set; } - [NativeProperty("ps4contentSearchFeaturesUsed", false, TargetType.Field)] extern public static bool contentSearchFeaturesUsed { get; set; } - [NativeProperty("ps4attribEyeToEyeDistanceSettingVR", false, TargetType.Field)] extern public static PlayStationVREyeToEyeDistanceSettings attribEyeToEyeDistanceSettingVR { get; set; } - [NativeProperty("ps4IncludedModules", false, TargetType.Field)] extern public static string[] includedModules { get; set; } - [NativeProperty(TargetType = TargetType.Field)] extern public static bool enableApplicationExit { get; set; } - } - } -} diff --git a/Editor/Mono/PlayerSettingsPSVita.bindings.cs b/Editor/Mono/PlayerSettingsPSVita.bindings.cs deleted file mode 100644 index fed9541baa..0000000000 --- a/Editor/Mono/PlayerSettingsPSVita.bindings.cs +++ /dev/null @@ -1,102 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; -using System; -using System.Runtime.CompilerServices; - -namespace UnityEditor -{ - public sealed partial class PlayerSettings - { - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - public sealed partial class PSVita - { - public enum PSVitaPowerMode - { - ModeA = 0, - ModeB = 1, - ModeC = 2, - } - - public enum PSVitaTvBootMode - { - Default = 0, - PSVitaBootablePSVitaTvBootable = 1, - PSVitaBootablePSVitaTvNotBootable = 2, - } - - public enum PSVitaEnterButtonAssignment - { - Default = 0, - CircleButton = 1, - CrossButton = 2, - } - - public enum PSVitaAppCategory - { - Application = 0, // Application package. - ApplicationPatch = 1, // Application patch package. - } - - public enum PSVitaMemoryExpansionMode - { - None = 0, - ExpandBy29MB = 1, - ExpandBy77MB = 2, - ExpandBy109MB = 3, - } - - public enum PSVitaDRMType - { - PaidFor = 0, // Paid for content. - Free = 1, // Free content. - } - - [NativeProperty("psp2NPTrophyPackPath")] extern public static string npTrophyPackPath { get; set; } - [NativeProperty("psp2PowerMode", false, TargetType.Field)] extern public static PSVitaPowerMode powerMode { get; set; } - [NativeProperty("psp2AcquireBGM", false, TargetType.Field)] extern public static bool acquireBGM { get; set; } - [NativeProperty("psp2NPSupportGBMorGJP", false, TargetType.Field)] extern public static bool npSupportGBMorGJP { get; set; } - [NativeProperty("psp2TVBootMode", false, TargetType.Field)] extern public static PSVitaTvBootMode tvBootMode { get; set; } - [NativeProperty("psp2TVDisableEmu", false, TargetType.Field)] extern public static bool tvDisableEmu { get; set; } - [NativeProperty("psp2Upgradable", false, TargetType.Field)] extern public static bool upgradable { get; set; } - [NativeProperty("psp2HealthWarning", false, TargetType.Field)] extern public static bool healthWarning { get; set; } - [NativeProperty("psp2UseLibLocation", false, TargetType.Field)] extern public static bool useLibLocation { get; set; } - [NativeProperty("psp2InfoBarOnStartup", false, TargetType.Field)] extern public static bool infoBarOnStartup { get; set; } - [NativeProperty("psp2InfoBarColor", false, TargetType.Field)] extern public static bool infoBarColor { get; set; } - [NativeProperty("psp2ScriptOptimizationLevel", false, TargetType.Field)] extern public static int scriptOptimizationLevel { get; set; } - [NativeProperty("psp2EnterButtonAssignment", false, TargetType.Field)] extern public static PSVitaEnterButtonAssignment enterButtonAssignment { get; set; } - [NativeProperty("psp2SaveDataQuota", false, TargetType.Field)] extern public static int saveDataQuota { get; set; } - [NativeProperty("psp2ParentalLevel", false, TargetType.Field)] extern public static int parentalLevel { get; set; } - [NativeProperty("psp2ShortTitle")] extern public static string shortTitle { get; set; } - [NativeProperty("psp2ContentID")] extern public static string contentID { get; set; } - [NativeProperty("psp2Category", false, TargetType.Field)] extern public static PSVitaAppCategory category { get; set; } - [NativeProperty("psp2MasterVersion")] extern public static string masterVersion { get; set; } - [NativeProperty("psp2AppVersion")] extern public static string appVersion { get; set; } - [Obsolete("AllowTwitterDialog has no effect as of SDK 3.570")] - [NativeProperty("psp2AllowTwitterDialog", false, TargetType.Field)] extern public static bool AllowTwitterDialog { get; set; } - [NativeProperty("psp2NPAgeRating", false, TargetType.Field)] extern public static int npAgeRating { get; set; } - [NativeProperty("psp2NPTitleDatPath")] extern public static string npTitleDatPath { get; set; } - [NativeProperty("psp2NPCommunicationsID")] extern public static string npCommunicationsID { get; set; } - [NativeProperty("psp2NPCommsPassphrase")] extern public static string npCommsPassphrase { get; set; } - [NativeProperty("psp2NPCommsSig")] extern public static string npCommsSig { get; set; } - [NativeProperty("psp2ParamSfxPath")] extern public static string paramSfxPath { get; set; } - [NativeProperty("psp2ManualPath")] extern public static string manualPath { get; set; } - [NativeProperty("psp2LiveAreaGatePath")] extern public static string liveAreaGatePath { get; set; } - [NativeProperty("psp2LiveAreaBackroundPath")] extern public static string liveAreaBackroundPath { get; set; } - [NativeProperty("psp2LiveAreaPath")] extern public static string liveAreaPath { get; set; } - [NativeProperty("psp2LiveAreaTrialPath")] extern public static string liveAreaTrialPath { get; set; } - [NativeProperty("psp2PatchChangeInfoPath")] extern public static string patchChangeInfoPath { get; set; } - [NativeProperty("psp2PatchOriginalPackage")] extern public static string patchOriginalPackage { get; set; } - [NativeProperty("psp2PackagePassword")] extern public static string packagePassword { get; set; } - [NativeProperty("psp2KeystoneFile")] extern public static string keystoneFile { get; set; } - [NativeProperty("psp2MemoryExpansionMode", false, TargetType.Field)] extern public static PSVitaMemoryExpansionMode memoryExpansionMode { get; set; } - [NativeProperty("psp2DRMType", false, TargetType.Field)] extern public static PSVitaDRMType drmType { get; set; } - [NativeProperty("psp2StorageType", false, TargetType.Field)] extern public static int storageType { get; set; } - [NativeProperty("psp2MediaCapacity", false, TargetType.Field)] extern public static int mediaCapacity { get; set; } - } - } -} diff --git a/Editor/Mono/PlayerSettingsSplashScreen.cs b/Editor/Mono/PlayerSettingsSplashScreen.cs deleted file mode 100644 index 8cf3e3b99d..0000000000 --- a/Editor/Mono/PlayerSettingsSplashScreen.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor -{ - public partial class PlayerSettings : UnityEngine.Object - { - public partial class SplashScreen - { - public enum AnimationMode - { - Static = 0, - Dolly = 1, - Custom = 2 - } - - public enum DrawMode - { - UnityLogoBelow = 0, - AllSequential = 1 - } - - public enum UnityLogoStyle - { - DarkOnLight = 0, - LightOnDark = 1 - } - } - } -} diff --git a/Editor/Mono/PlayerSettingsTVOS.bindings.cs b/Editor/Mono/PlayerSettingsTVOS.bindings.cs deleted file mode 100644 index ac15c9101f..0000000000 --- a/Editor/Mono/PlayerSettingsTVOS.bindings.cs +++ /dev/null @@ -1,206 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - public enum tvOSSdkVersion - { - Device = 0, - Simulator = 1 - } - - [System.Obsolete("targetOSVersion is obsolete. Use targetOSVersionString instead.", false)] - public enum tvOSTargetOSVersion - { - Unknown = 0, - tvOS_9_0 = 900, - tvOS_9_1 = 901, - } - - // 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. - public partial class PlayerSettings : UnityEngine.Object - { - // tvOS specific player settings - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - [NativeHeader("Editor/Src/EditorUserBuildSettings.h")] - [StaticAccessor("GetPlayerSettings()")] - public partial class tvOS - { - private static extern int sdkVersionInt - { - [NativeMethod("GettvOSSdkVersion")] - get; - [NativeMethod("SettvOSSdkVersion")] - set; - } - - public static tvOSSdkVersion sdkVersion - { - get { return (tvOSSdkVersion)sdkVersionInt; } - set { sdkVersionInt = (int)value; } - } - - // tvOS bundle build number - public static string buildNumber - { - get { return PlayerSettings.GetBuildNumber(BuildTargetGroup.tvOS); } - set { PlayerSettings.SetBuildNumber(BuildTargetGroup.tvOS, value); } - } - - [System.Obsolete("targetOSVersion is obsolete. Use targetOSVersionString instead.", false)] - public static tvOSTargetOSVersion targetOSVersion - { - get - { - string version = targetOSVersionString; - if (version == "9.0") - return tvOSTargetOSVersion.tvOS_9_0; - else if (version == "9.1") - return tvOSTargetOSVersion.tvOS_9_1; - return tvOSTargetOSVersion.Unknown; - } - set - { - string version = ""; - if (value == tvOSTargetOSVersion.tvOS_9_0) - version = "9.0"; - else if (value == tvOSTargetOSVersion.tvOS_9_1) - version = "9.1"; - - targetOSVersionString = version; - } - } - - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - [NativeMethod("GettvOSMinimumVersionString")] - static extern string GetMinimumVersionString(); - - internal static readonly Version minimumOsVersion = new Version(GetMinimumVersionString()); - - public static extern string targetOSVersionString - { - [NativeMethod("GettvOSTargetOSVersion")] - get; - [NativeMethod("SettvOSTargetOSVersion")] - set; - } - - [NativeProperty("tvOSSmallIconLayers", TargetType.Field)] - private static extern Texture2D[] smallIconLayers - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - internal static Texture2D[] GetSmallIconLayers() { return smallIconLayers; } - internal static void SetSmallIconLayers(Texture2D[] layers) { smallIconLayers = layers; } - - - [NativeProperty("tvOSSmallIconLayers2x", TargetType.Field)] - private static extern Texture2D[] smallIconLayers2x - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - internal static Texture2D[] GetSmallIconLayers2x() { return smallIconLayers2x; } - internal static void SetSmallIconLayers2x(Texture2D[] layers) { smallIconLayers2x = layers; } - - - [NativeProperty("tvOSLargeIconLayers", TargetType.Field)] - private static extern Texture2D[] largeIconLayers - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - internal static Texture2D[] GetLargeIconLayers() { return largeIconLayers; } - internal static void SetLargeIconLayers(Texture2D[] layers) { largeIconLayers = layers; } - - - [NativeProperty("tvOSLargeIconLayers2x", TargetType.Field)] - private static extern Texture2D[] largeIconLayers2x - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - internal static Texture2D[] GetLargeIconLayers2x() { return largeIconLayers2x; } - internal static void SetLargeIconLayers2x(Texture2D[] layers) { largeIconLayers2x = layers; } - - - [NativeProperty("tvOSTopShelfImageLayers", TargetType.Field)] - private static extern Texture2D[] topShelfImageLayers - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - internal static Texture2D[] GetTopShelfImageLayers() { return topShelfImageLayers; } - internal static void SetTopShelfImageLayers(Texture2D[] layers) { topShelfImageLayers = layers; } - - - [NativeProperty("tvOSTopShelfImageLayers2x", TargetType.Field)] - private static extern Texture2D[] topShelfImageLayers2x - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - internal static Texture2D[] GetTopShelfImageLayers2x() { return topShelfImageLayers2x; } - internal static void SetTopShelfImageLayers2x(Texture2D[] layers) { topShelfImageLayers2x = layers; } - - [NativeProperty("tvOSTopShelfImageWideLayers", TargetType.Field)] - private static extern Texture2D[] topShelfImageWideLayers - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - internal static Texture2D[] GetTopShelfImageWideLayers() { return topShelfImageWideLayers; } - internal static void SetTopShelfImageWideLayers(Texture2D[] layers) { topShelfImageWideLayers = layers; } - - - [NativeProperty("tvOSTopShelfImageWideLayers2x", TargetType.Field)] - private static extern Texture2D[] topShelfImageWideLayers2x - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - - internal static Texture2D[] GetTopShelfImageWideLayers2x() { return topShelfImageWideLayers2x; } - internal static void SetTopShelfImageWideLayers2x(Texture2D[] layers) { topShelfImageWideLayers2x = layers; } - - // AppleTV Enable extended game controller - public static extern bool requireExtendedGameController - { - [NativeMethod("GettvOSRequireExtendedGameController")] - get; - [NativeMethod("SettvOSRequireExtendedGameController")] - set; - } - } - } -} diff --git a/Editor/Mono/PlayerSettingsTizen.bindings.cs b/Editor/Mono/PlayerSettingsTizen.bindings.cs deleted file mode 100644 index 0b71e6499a..0000000000 --- a/Editor/Mono/PlayerSettingsTizen.bindings.cs +++ /dev/null @@ -1,135 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - // Supported Tizen OS versions - public enum TizenOSVersion - { - // Tizen 2.3 - //Version23 = 0, Removed in 5.5 for store compatibility - - // Tizen 2.4 - Version24 = 1 - } - - public enum TizenShowActivityIndicatorOnLoading - { - // Large == progressBarStyleLarge - Large = 0, - - // Inversed Large == progressBarStyleLargeInverse - InversedLarge = 1, - - // Small == progressBarStyleSmall - Small = 2, - - // Inversed Small == progressBarStyleSmallInverse - InversedSmall = 3, - - // Don't Show - DontShow = -1 - } - - // 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. - public sealed partial class PlayerSettings : UnityEngine.Object - { - public enum TizenCapability - { - Location = 0, - DataSharing = 1, - NetworkGet = 2, - WifiDirect = 3, - CallHistoryRead = 4, - Power = 5, - ContactWrite = 6, - MessageWrite = 7, - ContentWrite = 8, - Push = 9, - AccountRead = 10, - ExternalStorage = 11, - Recorder = 12, - PackageManagerInfo = 13, - NFCCardEmulation = 14, - CalendarWrite = 15, - WindowPrioritySet = 16, - VolumeSet = 17, - CallHistoryWrite = 18, - AlarmSet = 19, - Call = 20, - Email = 21, - ContactRead = 22, - Shortcut = 23, - KeyManager = 24, - LED = 25, - NetworkProfile = 26, - AlarmGet = 27, - Display = 28, - CalendarRead = 29, - NFC = 30, - AccountWrite = 31, - Bluetooth = 32, - Notification = 33, - NetworkSet = 34, - ExternalStorageAppData = 35, - Download = 36, - Telephony = 37, - MessageRead = 38, - MediaStorage = 39, - Internet = 40, - Camera = 41, - Haptic = 42, - AppManagerLaunch = 43, - SystemSettings = 44 - } - - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - [NativeHeader("Editor/Src/PlayerSettingsTizen.bindings.h")] - [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] - public sealed partial class Tizen - { - [NativeProperty("TizenProductDescription")] extern public static string productDescription { get; set; } - [NativeProperty("TizenProductURL")] extern public static string productURL { get; set; } - [NativeProperty("TizenSigningProfileName")] extern public static string signingProfileName { get; set; } - [NativeProperty("TizenDeploymentTarget")] extern public static string deploymentTarget { get; set; } - [NativeProperty("TizenDeploymentTargetType")] extern public static int deploymentTargetType { get; set; } - [NativeProperty("TizenMinOSVersion")] extern public static TizenOSVersion minOSVersion { get; set; } - [NativeProperty("TizenShowActivityIndicatorOnLoading")] extern public static TizenShowActivityIndicatorOnLoading showActivityIndicatorOnLoading { get; set; } - - [FreeFunction("PlayerSettingsTizenBindings::SetCapability")] - private static extern void SetCapability(string name, string value); - - [FreeFunction("PlayerSettingsTizenBindings::GetCapability")] - private static extern string GetCapability(string name); - - public static void SetCapability(TizenCapability capability, bool value) - { - SetCapability(capability.ToString(), value.ToString()); - } - - public static bool GetCapability(TizenCapability capability) - { - string stringValue = GetCapability(capability.ToString()); - - if (string.IsNullOrEmpty(stringValue)) - return false; - - try - { - return (bool)System.ComponentModel.TypeDescriptor.GetConverter(typeof(bool)).ConvertFromString(stringValue); - } - catch - { - Debug.LogError("Failed to parse value ('" + capability.ToString() + "," + stringValue + "') to bool type."); - return false; - } - } - } - } -} diff --git a/Editor/Mono/PlayerSettingsWSA.cs b/Editor/Mono/PlayerSettingsWSA.cs deleted file mode 100644 index 8f3aec3b26..0000000000 --- a/Editor/Mono/PlayerSettingsWSA.cs +++ /dev/null @@ -1,699 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Text.RegularExpressions; - -using UnityEngine; - -namespace UnityEditor -{ - public sealed partial class PlayerSettings : UnityEngine.Object - { - public sealed partial class WSA - { - internal static string ValidatePackageVersion(string value) - { - Regex metroPackageVersionRegex = new Regex(@"^(\d+)\.(\d+)\.(\d+)\.(\d+)$", (RegexOptions.Compiled | RegexOptions.CultureInvariant)); - - if (metroPackageVersionRegex.IsMatch(value)) - { - return value; - } - else - { - return "1.0.0.0"; - } - } - - private static void ValidateWSAImageType(WSAImageType type) - { - switch (type) - { - case WSAImageType.PackageLogo: - case WSAImageType.SplashScreenImage: - case WSAImageType.UWPSquare44x44Logo: - case WSAImageType.UWPSquare71x71Logo: - case WSAImageType.UWPSquare150x150Logo: - case WSAImageType.UWPSquare310x310Logo: - case WSAImageType.UWPWide310x150Logo: - return; - default: - throw new Exception("Unknown WSA image type: " + type); - } - } - - private static void ValidateWSAImageScale(WSAImageScale scale) - { - switch (scale) - { - case WSAImageScale._80: - case WSAImageScale._100: - case WSAImageScale._125: - case WSAImageScale._140: - case WSAImageScale._150: - case WSAImageScale._180: - case WSAImageScale._200: - case WSAImageScale._240: - case WSAImageScale._400: - case WSAImageScale.Target16: - case WSAImageScale.Target24: - case WSAImageScale.Target32: - case WSAImageScale.Target48: - case WSAImageScale.Target256: - return; - default: - throw new Exception("Unknown image scale: " + scale); - } - } - - public static string GetVisualAssetsImage(WSAImageType type, WSAImageScale scale) - { - ValidateWSAImageType(type); - ValidateWSAImageScale(scale); - return GetWSAImage(type, scale); - } - - public static void SetVisualAssetsImage(string image, WSAImageType type, WSAImageScale scale) - { - ValidateWSAImageType(type); - ValidateWSAImageScale(scale); - SetWSAImage(image, type, scale); - } - - public static System.Version packageVersion - { - get - { - try - { - return new System.Version(ValidatePackageVersion(packageVersionRaw)); - } - catch (Exception ex) - { - throw new Exception(string.Format("{0}, the raw string was {1}", ex.Message, packageVersionRaw)); - } - } - set { packageVersionRaw = value.ToString(); } - } - - - public static System.DateTime? certificateNotAfter - { - get - { - long value = certificateNotAfterRaw; - if (value != 0) - return System.DateTime.FromFileTime(value); - else - return null; - } - } - - public static Color? splashScreenBackgroundColor - { - get - { - if (splashScreenUseBackgroundColor) - return splashScreenBackgroundColorRaw; - else - return null; - } - set - { - splashScreenUseBackgroundColor = value.HasValue; - if (value.HasValue) - splashScreenBackgroundColorRaw = value.Value; - } - } - - public static void SetCapability(WSACapability capability, bool value) - { - InternalSetCapability(capability.ToString(), value.ToString()); - } - - public static bool GetCapability(WSACapability capability) - { - string stringValue = InternalGetCapability(capability.ToString()); - - if (string.IsNullOrEmpty(stringValue)) return false; - - try - { - return (bool)System.ComponentModel.TypeDescriptor.GetConverter(typeof(bool)).ConvertFromString(stringValue); - } - catch - { - Debug.LogError("Failed to parse value ('" + capability.ToString() + "," + stringValue + "') to bool type."); - return false; - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileLogo80 - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileLogo80 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileLogo80 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileLogo - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileLogo is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileLogo is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileLogo140 - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileLogo140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileLogo140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileLogo180 - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileLogo180 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileLogo180 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileWideLogo80 - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileWideLogo80 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileWideLogo80 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileWideLogo - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileWideLogo is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileWideLogo is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileWideLogo140 - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileWideLogo140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileWideLogo140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileWideLogo180 - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileWideLogo180 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileWideLogo180 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileSmallLogo80 - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileSmallLogo80 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileSmallLogo80 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileSmallLogo - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileSmallLogo is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileSmallLogo is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileSmallLogo140 - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileSmallLogo140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileSmallLogo140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeTileSmallLogo180 - { - get - { - throw new NotSupportedException("PlayerSettings.storeTileSmallLogo180 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeTileSmallLogo180 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeSmallTile80 - { - get - { - throw new NotSupportedException("PlayerSettings.storeSmallTile80 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeSmallTile80 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeSmallTile - { - get - { - throw new NotSupportedException("PlayerSettings.storeSmallTile is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeSmallTile is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeSmallTile140 - { - get - { - throw new NotSupportedException("PlayerSettings.storeSmallTile140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeSmallTile140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeSmallTile180 - { - get - { - throw new NotSupportedException("PlayerSettings.storeSmallTile180 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeSmallTile180 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeLargeTile80 - { - get - { - throw new NotSupportedException("PlayerSettings.storeLargeTile80 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeLargeTile80 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeLargeTile - { - get - { - throw new NotSupportedException("PlayerSettings.storeLargeTile is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeLargeTile is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeLargeTile140 - { - get - { - throw new NotSupportedException("PlayerSettings.storeLargeTile140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeLargeTile140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeLargeTile180 - { - get - { - throw new NotSupportedException("PlayerSettings.storeLargeTile180 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeLargeTile180 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeSplashScreenImage - { - get - { - throw new NotSupportedException("PlayerSettings.storeSplashScreenImage is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeSplashScreenImage is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeSplashScreenImageScale140 - { - get - { - throw new NotSupportedException("PlayerSettings.storeSplashScreenImageScale140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeSplashScreenImageScale140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string storeSplashScreenImageScale180 - { - get - { - throw new NotSupportedException("PlayerSettings.storeSplashScreenImageScale180 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.storeSplashScreenImageScale180 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneAppIcon - { - get - { - throw new NotSupportedException("PlayerSettings.phoneAppIcon is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneAppIcon is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneAppIcon140 - { - get - { - throw new NotSupportedException("PlayerSettings.phoneAppIcon140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneAppIcon140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneAppIcon240 - { - get - { - throw new NotSupportedException("PlayerSettings.phoneAppIcon240 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneAppIcon240 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneSmallTile - { - get - { - throw new NotSupportedException("PlayerSettings.phoneSmallTile is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneSmallTile is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneSmallTile140 - { - get - { - throw new NotSupportedException("PlayerSettings.phoneSmallTile140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneSmallTile140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneSmallTile240 - { - get - { - throw new NotSupportedException("PlayerSettings.phoneSmallTile240 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneSmallTile240 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneMediumTile - { - get - { - throw new NotSupportedException("PlayerSettings.phoneMediumTile is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneMediumTile is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneMediumTile140 - { - get - { - throw new NotSupportedException("PlayerSettings.phoneMediumTile140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneMediumTile140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneMediumTile240 - { - get - { - throw new NotSupportedException("PlayerSettings.phoneMediumTile240 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneMediumTile240 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneWideTile - { - get - { - throw new NotSupportedException("PlayerSettings.phoneWideTile is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneWideTile is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneWideTile140 - { - get - { - throw new NotSupportedException("PlayerSettings.phoneWideTile140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneWideTile140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneWideTile240 - { - get - { - throw new NotSupportedException("PlayerSettings.phoneWideTile240 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneWideTile240 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneSplashScreenImage - { - get - { - throw new NotSupportedException("PlayerSettings.phoneSplashScreenImage is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneSplashScreenImage is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneSplashScreenImageScale140 - { - get - { - throw new NotSupportedException("PlayerSettings.phoneSplashScreenImageScale140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneSplashScreenImageScale140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string phoneSplashScreenImageScale240 - { - get - { - throw new NotSupportedException("PlayerSettings.phoneSplashScreenImageScale240 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.phoneSplashScreenImageScale240 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string packageLogo140 - { - get - { - throw new NotSupportedException("PlayerSettings.packageLogo140 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.packageLogo140 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string packageLogo180 - { - get - { - throw new NotSupportedException("PlayerSettings.packageLogo180 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.packageLogo180 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("Use GetVisualAssetsImage()/SetVisualAssetsImage()", true)] - public static string packageLogo240 - { - get - { - throw new NotSupportedException("PlayerSettings.packageLogo240 is deprecated. Use GetVisualAssetsImage() instead."); - } - set - { - throw new NotSupportedException("PlayerSettings.packageLogo240 is deprecated. Use SetVisualAssetsImage() instead."); - } - } - - [Obsolete("PlayerSettings.enableLowLatencyPresentationAPI is deprecated. It is now always enabled.", true)] - public static bool enableLowLatencyPresentationAPI - { - get - { - return true; - } - set - { - } - } - } - } -} diff --git a/Editor/Mono/PlayerSettingsXboxOne.bindings.cs b/Editor/Mono/PlayerSettingsXboxOne.bindings.cs deleted file mode 100644 index 4748358727..0000000000 --- a/Editor/Mono/PlayerSettingsXboxOne.bindings.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; -using System.Runtime.CompilerServices; - -namespace UnityEditor -{ - public sealed partial class PlayerSettings - { - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - public sealed partial class XboxOne - { - [NativeProperty("XboxOneXTitleMemory", TargetType.Field)] - extern public static int XTitleMemory - { - [StaticAccessor("GetPlayerSettings().GetEditorOnly()", StaticAccessorType.Dot)] - get; - [StaticAccessor("GetPlayerSettings().GetEditorOnlyForUpdate()", StaticAccessorType.Dot)] - set; - } - } - } -} diff --git a/Editor/Mono/PluginDesc.cs b/Editor/Mono/PluginDesc.cs deleted file mode 100644 index 6d859b998d..0000000000 --- a/Editor/Mono/PluginDesc.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -namespace UnityEditorInternal -{ - internal struct PluginDesc - { - public string pluginPath; - public CPUArch architecture; - } - - internal enum CPUArch - { - Any, - x86, - ARMv7 - } -} diff --git a/Editor/Mono/PluginImporter.bindings.cs b/Editor/Mono/PluginImporter.bindings.cs deleted file mode 100644 index eddd97dd1d..0000000000 --- a/Editor/Mono/PluginImporter.bindings.cs +++ /dev/null @@ -1,295 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Callbacks; -using UnityEditor.Modules; -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using Mono.Cecil; - -namespace UnityEditor -{ - [NativeHeader("Editor/Src/AssetPipeline/PluginImporter.h")] - [ExcludeFromPreset] - public sealed partial class PluginImporter : AssetImporter - { - [NativeMethod("GetCompatibleWithPlatformOrAnyPlatform")] - extern internal bool GetCompatibleWithPlatformOrAnyPlatformBuildTarget(string buildTarget); - - [NativeMethod("GetCompatibleWithPlatformOrAnyPlatform")] - extern private bool GetCompatibleWithPlatformOrAnyPlatformBuildGroupAndTarget(string buildTargetGroup, string buildTarget); - - public static PluginImporter[] GetImporters(string platformName) - { - // The final list of importers that will be returned - List finalImporters = new List(); - - // Contains all unique finalPaths. Used to remove overridable plugins from the finalImporters list - Dictionary uniqueFinalPathToImporterMap = new Dictionary(); - - PluginImporter[] allImporters = GetAllImporters().Where(imp => imp.GetCompatibleWithPlatformOrAnyPlatformBuildTarget(platformName)).ToArray(); - IPluginImporterExtension pluginImporterExtension = ModuleManager.GetPluginImporterExtension(platformName); - - if (pluginImporterExtension == null) - pluginImporterExtension = ModuleManager.GetPluginImporterExtension(BuildPipeline.GetBuildTargetByName(platformName)); - - if (pluginImporterExtension == null) - return allImporters; - - // Go through all of the Importers for the specified platform and determine if any of the natively included Unity Plugins should be removed. - // Removal should only happen if the user has included a plugin of the same name and they are copying to the same finalPath - for (int i = 0; i < allImporters.Length; ++i) - { - PluginImporter currentImporter = allImporters[i]; - string finalPluginPath = pluginImporterExtension.CalculateFinalPluginPath(platformName, currentImporter); - - // Only compare overridables if the plugin has a calculated finalPluginPath - if (!string.IsNullOrEmpty(finalPluginPath)) - { - PluginImporter tempImporter; - if (!uniqueFinalPathToImporterMap.TryGetValue(finalPluginPath, out tempImporter)) - { - // Unique Plugin found, add it to the list for comparing overridable plugins - // The first overridable plugin of it's kind should be added to the return list here. - uniqueFinalPathToImporterMap.Add(finalPluginPath, currentImporter); - } - else if (tempImporter.GetIsOverridable() && !currentImporter.GetIsOverridable()) - { - // finalPluginPath isn't unique and the finalImporter already in the list is overriden by the new one, - // remove the overridable one. - uniqueFinalPathToImporterMap[finalPluginPath] = currentImporter; - finalImporters.Remove(tempImporter); - } - else if (currentImporter.GetIsOverridable()) - { - // The current importer is going to the same final location as another, but - // this plugin is overridable, so don't include it. - continue; - } - } - - finalImporters.Add(currentImporter); - } - - return finalImporters.ToArray(); - } - - internal string HasDiscouragedReferences() - { - if (!isNativePlugin) - { - var assemblyDefinition = AssemblyDefinition.ReadAssembly(assetPath, new ReaderParameters()); - - foreach (var reference in assemblyDefinition.MainModule.AssemblyReferences) - { - // We don't use AssemblyHelper.IsUnityEngineModule here, because that would require loading the assembly, which may not even be present. - if (reference.Name.StartsWith("UnityEngine.") && reference.Name.EndsWith("Module")) - return reference.Name; - } - } - return null; - } - - public static PluginImporter[] GetImporters(BuildTarget platform) - { - return GetImporters(BuildPipeline.GetBuildTargetName(platform)); - } - - public static PluginImporter[] GetImporters(string buildTargetGroup, string buildTarget) - { - return GetAllImporters().Where(imp => imp.GetCompatibleWithPlatformOrAnyPlatformBuildGroupAndTarget(buildTargetGroup, buildTarget)).ToArray(); - } - - public static PluginImporter[] GetImporters(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget) - { - return GetImporters(BuildPipeline.GetBuildTargetGroupName(buildTargetGroup), BuildPipeline.GetBuildTargetName(buildTarget)); - } - - // TODO: Move plugins that use this to GetImporters, and Remove this function - internal static IEnumerable GetExtensionPlugins(BuildTarget target) - { - IEnumerable> pluginDescriptions = - AttributeHelper.CallMethodsWithAttribute, RegisterPluginsAttribute>(target); - foreach (IEnumerable extensionPlugins in pluginDescriptions) - { - foreach (PluginDesc pluginDesc in extensionPlugins) - { - yield return pluginDesc; - } - } - } - - [NativeMethod("ClearPlatformData")] - extern public void ClearSettings(); - - extern public void SetCompatibleWithAnyPlatform(bool enable); - - extern public bool GetCompatibleWithAnyPlatform(); - - extern public void SetExcludeFromAnyPlatform(string platformName, bool excludedFromAny); - - extern public bool GetExcludeFromAnyPlatform(string platformName); - - public delegate bool IncludeInBuildDelegate(string path); - - // this is implemented as a static map so that it can survive a garbage collection on the PluginImporter and not get lost - private static Dictionary s_includeInBuildDelegateMap = new Dictionary(); - public void SetIncludeInBuildDelegate(IncludeInBuildDelegate includeInBuildDelegate) - { - s_includeInBuildDelegateMap[assetPath] = includeInBuildDelegate; - } - - [RequiredByNativeCode] - private bool InvokeIncludeInBuildDelegate() - { - if (s_includeInBuildDelegateMap.ContainsKey(assetPath)) - { - return s_includeInBuildDelegateMap[assetPath](assetPath); - } - - return true; - } - - // this is implemented as a static map so that it can survive a garbage collection on the PluginImporter and not get lost - private static Dictionary> s_shouldOverridePredicateMap = new Dictionary>(); - internal void SetShouldOverridePredicate(System.Predicate shouldOverridePredicate) - { - if (shouldOverridePredicate != null) - { - s_shouldOverridePredicateMap[assetPath] = shouldOverridePredicate; - } - else - { - if (s_shouldOverridePredicateMap.ContainsKey(assetPath)) - s_shouldOverridePredicateMap.Remove(assetPath); - } - } - - [RequiredByNativeCode] - private bool InvokeShouldOverridePredicate() - { - if (s_shouldOverridePredicateMap.ContainsKey(assetPath)) - { - try - { - return s_shouldOverridePredicateMap[assetPath](assetPath); - } - catch (System.Exception) - { - UnityEngine.Debug.LogWarning("Exception occurred while invoking ShouldOverridePredicate for " + assetPath); - } - } - - return false; - } - - public void SetExcludeFromAnyPlatform(BuildTarget platform, bool excludedFromAny) - { - SetExcludeFromAnyPlatform(BuildPipeline.GetBuildTargetName(platform), excludedFromAny); - } - - public bool GetExcludeFromAnyPlatform(BuildTarget platform) - { - return GetExcludeFromAnyPlatform(BuildPipeline.GetBuildTargetName(platform)); - } - - extern public void SetExcludeEditorFromAnyPlatform(bool excludedFromAny); - - extern public bool GetExcludeEditorFromAnyPlatform(); - - extern public void SetCompatibleWithEditor(bool enable); - - [NativeMethod("SetCompatibleWithEditor")] - extern internal void SetCompatibleWithEditorWithBuildTargetsInternal(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, bool enable); - - internal void SetCompatibleWithEditor(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, bool enable) - { - SetCompatibleWithEditorWithBuildTargetsInternal(buildTargetGroup, buildTarget, enable); - } - - public bool GetCompatibleWithEditor() - { - return GetCompatibleWithEditor("", ""); - } - - extern public bool GetCompatibleWithEditor(string buildTargetGroup, string buildTarget); - - extern internal void SetIsPreloaded(bool isPreloaded); - - extern internal bool GetIsPreloaded(); - - extern public bool GetIsOverridable(); - - extern public bool ShouldIncludeInBuild(); - - public void SetCompatibleWithPlatform(BuildTarget platform, bool enable) - { - SetCompatibleWithPlatform(BuildPipeline.GetBuildTargetName(platform), enable); - } - - internal void SetCompatibleWithPlatform(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, bool enable) - { - SetCompatibleWithPlatform(BuildPipeline.GetBuildTargetGroupName(buildTargetGroup), BuildPipeline.GetBuildTargetName(buildTarget), enable); - } - - public bool GetCompatibleWithPlatform(BuildTarget platform) - { - return GetCompatibleWithPlatform(BuildPipeline.GetBuildTargetName(platform)); - } - - internal bool GetCompatibleWithPlatform(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget) - { - return GetCompatibleWithPlatform(BuildPipeline.GetBuildTargetGroupName(buildTargetGroup), BuildPipeline.GetBuildTargetName(buildTarget)); - } - - public void SetCompatibleWithPlatform(string platformName, bool enable) - { - SetCompatibleWithPlatform(BuildPipeline.GetBuildTargetGroupName(BuildPipeline.GetBuildTargetByName(platformName)), platformName, enable); - } - - public bool GetCompatibleWithPlatform(string platformName) - { - return GetCompatibleWithPlatform(BuildPipeline.GetBuildTargetGroupName(BuildPipeline.GetBuildTargetByName(platformName)), platformName); - } - - extern internal void SetCompatibleWithPlatform(string buildTargetGroup, string buildTarget, bool enable); - - extern internal bool GetCompatibleWithPlatform(string buildTargetGroup, string buildTarget); - - public void SetPlatformData(BuildTarget platform, string key, string value) - { - SetPlatformData(BuildPipeline.GetBuildTargetName(platform), key, value); - } - - public string GetPlatformData(BuildTarget platform, string key) - { - return GetPlatformData(BuildPipeline.GetBuildTargetName(platform), key); - } - - extern public void SetPlatformData(string platformName, string key, string value); - - extern public string GetPlatformData(string platformName, string key); - - extern public void SetEditorData(string key, string value); - - extern public string GetEditorData(string key); - - public extern bool isNativePlugin - { - [NativeMethod("IsNativePlugin")] - get; - } - - internal extern DllType dllType - { - get; - } - - extern public static PluginImporter[] GetAllImporters(); - } -} diff --git a/Editor/Mono/Plugins/PluginsHelper.cs b/Editor/Mono/Plugins/PluginsHelper.cs deleted file mode 100644 index 764f85c5e5..0000000000 --- a/Editor/Mono/Plugins/PluginsHelper.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor.Modules; -using UnityEngine; -using UnityEditor; - -namespace UnityEditorInternal -{ - internal class PluginsHelper - { - public static bool CheckFileCollisions(BuildTarget buildTarget) - { - // Checks that plugins don't collide with each other - IPluginImporterExtension pluginImporterExtension = null; - if (ModuleManager.IsPlatformSupported(buildTarget)) - pluginImporterExtension = ModuleManager.GetPluginImporterExtension(buildTarget); - if (pluginImporterExtension == null) - { - // Some platforms don't have platform specific settings for plugins, but we still wan't to check that plugins don't collide, use default path in this case - if (BuildPipeline.GetBuildTargetGroup(buildTarget) == BuildTargetGroup.Standalone) - pluginImporterExtension = new DesktopPluginImporterExtension(); - else - pluginImporterExtension = new DefaultPluginImporterExtension(null); - } - - if (pluginImporterExtension.CheckFileCollisions(BuildPipeline.GetBuildTargetName(buildTarget))) - return true; - - return false; - } - } -} diff --git a/Editor/Mono/PointEditor.cs b/Editor/Mono/PointEditor.cs deleted file mode 100644 index 491d0c56c0..0000000000 --- a/Editor/Mono/PointEditor.cs +++ /dev/null @@ -1,289 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - /// Semi-Generic point editor. - /// A Point editor basically let you drag around an array of Vector3 points in the scene view. - - /// In order to maximize flexibility, all communication goes through the IEditablePoint interface. - /// The point editor uses this to make callbacks to your editor so no assumptions about your data structure is made. - internal interface IEditablePoint - { - /// Get the world-space position of a specifc point - Vector3 GetPosition(int idx); - /// Set the world-space position of a specific point - void SetPosition(int idx, Vector3 position); - /// Get the default color for points - Color GetDefaultColor(); - /// Get tje selected color for points - Color GetSelectedColor(); - /// Scale of the spheres to draw - float GetPointScale(); - /// Get the positions of the points - IEnumerable GetPositions(); - - Vector3[] GetUnselectedPositions(); - Vector3[] GetSelectedPositions(); - - int Count { get; } - } - - internal class PointEditor - { - // Various variables to keep track of the state of selection rects. - // Since the user can not be dragging inside more than one thing (they only have one mouse), we can - // just have these be static. - // - // The point on screen that the user started dragging a selection rect from. - private static Vector2 s_StartMouseDragPosition; - // The selection at the start of the drag. Using this and the start mousepos, - // we can reconstruct the selection live during the drag so the user will always see the drag. - private static List s_StartDragSelection; - - private static bool s_DidDrag; - - /// Move the selected points using standard handles. returns true if point moved - public static bool MovePoints(IEditablePoint points, Transform cloudTransform, List selection) - { - if (selection.Count == 0) - return false; - - // Editing for the case where we're in a 3D sceneview - if (Camera.current) - { - var handlePos = Vector3.zero; - handlePos = Tools.pivotMode == PivotMode.Pivot ? - points.GetPosition(selection[0]) : - selection.Aggregate(handlePos, (current, index) => current + points.GetPosition(index)) / selection.Count; - - handlePos = cloudTransform.TransformPoint(handlePos); - - - var newPos = Handles.PositionHandle(handlePos, - Tools.pivotRotation == PivotRotation.Local ? cloudTransform.rotation : Quaternion.identity); - if (GUI.changed) - { - Vector3 delta = cloudTransform.InverseTransformPoint(newPos) - cloudTransform.InverseTransformPoint(handlePos); - foreach (int i in selection) - points.SetPosition(i, points.GetPosition(i) + delta); - return true; - } - } - return false; - } - - public static int FindNearest(Vector2 point, Transform cloudTransform, IEditablePoint points) - { - var r = HandleUtility.GUIPointToWorldRay(point); - - var found = new Dictionary(); - for (var i = 0; i < points.Count; i++) - { - float distance = 0; - Vector3 collisionPoint = Vector3.zero; - - if (MathUtils.IntersectRaySphere(r, cloudTransform.TransformPoint(points.GetPosition(i)), points.GetPointScale() * 0.5f, ref distance, ref collisionPoint)) - { - //Only care if we start outside a probe - if (distance > 0) - { - found.Add(i, distance); - } - } - } - - if (found.Count <= 0) return -1; - - var sorted = found.OrderBy(x => x.Value); - return sorted.First().Key; - } - - private static List s_SelectionStart; - // This function implements selection of points. Returns true is selection changes - public static bool SelectPoints(IEditablePoint points, Transform cloudTransform, ref List selection, bool firstSelect) - { - int id = GUIUtility.GetControlID(FocusType.Passive); - - if (Event.current.alt && Event.current.type != EventType.Repaint) - return false; - - bool selectionChanged = false; - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - // Tell the handles system that we're the default tool (the one that should get focus when user clicks on nothing else.) - HandleUtility.AddDefaultControl(id); - break; - - case EventType.MouseDown: - // If we got a left-mouse down (HandleUtility.nearestControl== id is only true when the user clicked outside any handles), - // we should begin selecting. - if ((HandleUtility.nearestControl == id || firstSelect) && evt.button == 0) - { - // If neither shift nor control is held down, we'll clear the selection as the fist thing. - if (!evt.shift && !EditorGUI.actionKey) - { - selection.Clear(); - selectionChanged = true; - } - - s_SelectionStart = new List(selection); - // Grab focus so that we can do a rect selection. - GUIUtility.hotControl = id; - // And remember where the drag was from. - s_StartMouseDragPosition = evt.mousePosition; - - // Also remember the selection at the start so additive rect selection will work correctly - s_StartDragSelection = new List(selection); - - // Use the mouse down event so no other controls get them - evt.Use(); - } - break; - - case EventType.MouseDrag: - // The user dragged the mouse (and we have the focus from MouseDown). We have a rect selection here - if (GUIUtility.hotControl == id && evt.button == 0) - { - s_DidDrag = true; - // Start by resetting the selection to what it was when the drag began. - selection.Clear(); - selection.AddRange(s_StartDragSelection); - - // now, we'll go over every point and see if it's inside the Rect defined by the mouse position and - // the start drag position - Rect r = FromToRect(s_StartMouseDragPosition, evt.mousePosition); - - var oldMatrix = Handles.matrix; - Handles.matrix = cloudTransform.localToWorldMatrix; - // Go over all the points and add them if they are inside the rect - for (int i = 0; i < points.Count; i++) - { - var point = HandleUtility.WorldToGUIPoint(points.GetPosition(i)); - if (r.Contains(point)) - { - if (EditorGUI.actionKey) - { - if (s_SelectionStart.Contains(i)) - { - selection.Remove(i); - } - } - else - { - if (!s_SelectionStart.Contains(i)) - { - selection.Add(i); - } - } - } - } - Handles.matrix = oldMatrix; - - // We'll assume the selection has changed and set GUI.changed to true. - // Worst case, somebody will validate a bit too much, but oh well. - GUI.changed = true; - evt.Use(); - } - break; - - case EventType.MouseUp: - // If we got the mousedown event, the mouseup is ours as well - this is where we clean up. - if (GUIUtility.hotControl == id && evt.button == 0) - { - //Dragging vs clicking - if (!s_DidDrag) - { - // Find out if it was on top of a point. - int selectedPoint = FindNearest(s_StartMouseDragPosition, cloudTransform, points); - - // We found a point. We either need to make it selected or add it to an existing selection. - if (selectedPoint != -1) - { - // If neither shift nor action is held down, simply set selection to the picked point. - if (!evt.shift && !EditorGUI.actionKey) - { - selection.Add(selectedPoint); - } - else - { - // Shift was held down. This means we need to add/remove the point - int alreadyInSelection = selection.IndexOf(selectedPoint); - if (alreadyInSelection != -1) selection.RemoveAt(alreadyInSelection); - else selection.Add(selectedPoint); - } - } - - // Selection has changed. set GUI.changed to true so caller can react (e.g. repaint inspector). - GUI.changed = true; - selectionChanged = true; - } - - - // Clean up various stuff. - s_StartDragSelection = null; - s_StartMouseDragPosition = Vector2.zero; - s_DidDrag = false; - - // Release the mouse focus - GUIUtility.hotControl = 0; - - // use the event - evt.Use(); - } - break; - case EventType.Repaint: - // If we have focus and the mouse has been moved, we'll the draw selection rect. - if (GUIUtility.hotControl == id && evt.mousePosition != s_StartMouseDragPosition) - { - GUIStyle gs = "SelectionRect"; - Handles.BeginGUI(); - gs.Draw(FromToRect(s_StartMouseDragPosition, evt.mousePosition), false, false, false, false); - Handles.EndGUI(); - } - break; - } - if (selectionChanged) - selection = selection.Distinct().ToList(); - return selectionChanged; - } - - /// Draw the points in points array. All selected points will be drawn blue, for unselected, - /// points.GetColor will be called to get the color of each point - public static void Draw(IEditablePoint points, Transform cloudTransform, List selection, bool twoPassDrawing) - { - LightProbeVisualization.DrawPointCloud( - points.GetUnselectedPositions(), - points.GetSelectedPositions(), - points.GetDefaultColor(), - points.GetSelectedColor(), - points.GetPointScale(), - cloudTransform); - } - - // Small helper: Build a rect and make sure that rect has positive size so Rect.Contains works correctly. - static Rect FromToRect(Vector2 from, Vector2 to) - { - var r = new Rect(from.x, from.y, to.x - from.x, to.y - from.y); - - if (r.width < 0) - { - r.x += r.width; - r.width = -r.width; - } - if (r.height < 0) - { - r.y += r.height; - r.height = -r.height; - } - return r; - } - } -} diff --git a/Editor/Mono/PostprocessScene.cs b/Editor/Mono/PostprocessScene.cs deleted file mode 100644 index 71891c4fc0..0000000000 --- a/Editor/Mono/PostprocessScene.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.Build; - -namespace UnityEditor -{ - internal class UnityBuildPostprocessor : IProcessSceneWithReport - { - public int callbackOrder { get { return 0; } } - public void OnProcessScene(UnityEngine.SceneManagement.Scene scene, Build.Reporting.BuildReport report) - { - int staticBatching, dynamicBatching; - PlayerSettings.GetBatchingForPlatform(EditorUserBuildSettings.activeBuildTarget, out staticBatching, out dynamicBatching); - if (staticBatching != 0) - { - InternalStaticBatchingUtility.Combine(null, true, true); - } - } - } -} diff --git a/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs b/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs deleted file mode 100644 index 3038449f89..0000000000 --- a/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs +++ /dev/null @@ -1,298 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using Microsoft.Win32; -using UnityEngine; -using UnityEditor; -using UnityEditor.Collaboration; -using UnityEditorInternal; -using System.Collections.Generic; -using System; -using System.IO; - -namespace UnityEditor -{ - internal class CacheServerPreferences - { - internal class Styles - { - public static readonly GUIContent browse = EditorGUIUtility.TrTextContent("Browse..."); - public static readonly GUIContent maxCacheSize = EditorGUIUtility.TrTextContent("Maximum Cache Size (GB)", "The size of the local asset cache server folder will be kept below this maximum value."); - public static readonly GUIContent customCacheLocation = EditorGUIUtility.TrTextContent("Custom cache location", "Specify the local asset cache server folder location."); - public static readonly GUIContent cacheFolderLocation = EditorGUIUtility.TrTextContent("Cache Folder Location", "The local asset cache server folder is shared between all projects."); - public static readonly GUIContent cleanCache = EditorGUIUtility.TrTextContent("Clean Cache"); - public static readonly GUIContent enumerateCache = EditorGUIUtility.TrTextContent("Check Cache Size", "Check the size of the local asset cache server - can take a while"); - public static readonly GUIContent browseCacheLocation = EditorGUIUtility.TrTextContent("Browse for local asset cache server location"); - } - - internal class Constants - { - public GUIStyle cacheFolderLocation = new GUIStyle(GUI.skin.label); - - public Constants() - { - cacheFolderLocation.wordWrap = true; - } - } - - const string kIPAddressKey = "CacheServerIPAddress"; - const string kIpAddressKeyArgs = "-" + kIPAddressKey; - const string kModeKey = "CacheServerMode"; - const string kDeprecatedEnabledKey = "CacheServerEnabled"; - - private static bool s_PrefsLoaded; - private static bool s_HasPendingChanges = false; - enum ConnectionState { Unknown, Success, Failure }; - private static ConnectionState s_ConnectionState; - public enum CacheServerMode { Local, Remote, Disabled } - private static CacheServerMode s_CacheServerMode; - private static string s_CacheServerIPAddress; - private static int s_LocalCacheServerSize; - private static long s_LocalCacheServerUsedSize = -1; - private static bool s_EnableCustomPath; - private static string s_CachePath; - - static Constants s_Constants = null; - - public static void ReadPreferences() - { - s_CacheServerIPAddress = EditorPrefs.GetString(kIPAddressKey, s_CacheServerIPAddress); - s_CacheServerMode = (CacheServerMode)EditorPrefs.GetInt(kModeKey, (int)(EditorPrefs.GetBool(kDeprecatedEnabledKey) ? CacheServerMode.Remote : CacheServerMode.Disabled)); - s_LocalCacheServerSize = EditorPrefs.GetInt(LocalCacheServer.SizeKey, 10); - s_CachePath = EditorPrefs.GetString(LocalCacheServer.PathKey); - s_EnableCustomPath = EditorPrefs.GetBool(LocalCacheServer.CustomPathKey); - } - - public static void WritePreferences() - { - // Don't change anything if there's a command line override - if (GetCommandLineRemoteAddressOverride() != null) - return; - - CacheServerMode oldMode = (CacheServerMode)EditorPrefs.GetInt(kModeKey); - var oldPath = EditorPrefs.GetString(LocalCacheServer.PathKey); - var oldCustomPath = EditorPrefs.GetBool(LocalCacheServer.CustomPathKey); - bool changedDir = false; - if (oldMode != s_CacheServerMode && oldMode == CacheServerMode.Local) - changedDir = true; - if (s_EnableCustomPath && oldPath != s_CachePath) - changedDir = true; - if (s_EnableCustomPath != oldCustomPath && s_CachePath != LocalCacheServer.GetCacheLocation() && s_CachePath != "") - changedDir = true; - if (changedDir) - { - s_LocalCacheServerUsedSize = -1; - var message = s_CacheServerMode == CacheServerMode.Local ? - "You have changed the location of the local cache storage." : - "You have disabled the local cache."; - message += " Do you want to delete the old locally cached data at " + LocalCacheServer.GetCacheLocation() + "?"; - if (EditorUtility.DisplayDialog("Delete old Cache", message, "Delete", "Don't Delete")) - { - LocalCacheServer.Clear(); - s_LocalCacheServerUsedSize = -1; - } - } - - EditorPrefs.SetString(kIPAddressKey, s_CacheServerIPAddress); - EditorPrefs.SetInt(kModeKey, (int)s_CacheServerMode); - EditorPrefs.SetInt(LocalCacheServer.SizeKey, s_LocalCacheServerSize); - EditorPrefs.SetString(LocalCacheServer.PathKey, s_CachePath); - EditorPrefs.SetBool(LocalCacheServer.CustomPathKey, s_EnableCustomPath); - LocalCacheServer.Setup(); - - if (changedDir) - { - //Call ExitGUI after bringing up a dialog to avoid an exception - EditorGUIUtility.ExitGUI(); - } - } - - private static string GetCommandLineRemoteAddressOverride() - { - string address = null; - var argv = Environment.GetCommandLineArgs(); - var index = Array.IndexOf(argv, kIpAddressKeyArgs); - if (index >= 0 && argv.Length > index + 1) - address = argv[index + 1]; - - return address; - } - - [PreferenceItem("Cache Server")] - private static void OnGUI() - { - // Get event type before the event is used. - var eventType = Event.current.type; - if (s_Constants == null) - { - s_Constants = new Constants(); - } - - if (!InternalEditorUtility.HasTeamLicense()) - GUILayout.Label(EditorGUIUtility.TempContent("You need to have a Pro or Team license to use the cache server.", EditorGUIUtility.GetHelpIcon(MessageType.Warning)), EditorStyles.helpBox); - - using (new EditorGUI.DisabledScope(!InternalEditorUtility.HasTeamLicense())) - { - if (!s_PrefsLoaded) - { - ReadPreferences(); - - if (s_CacheServerMode != CacheServerMode.Disabled && s_ConnectionState == ConnectionState.Unknown) - { - if (InternalEditorUtility.CanConnectToCacheServer()) - s_ConnectionState = ConnectionState.Success; - else - s_ConnectionState = ConnectionState.Failure; - } - - s_PrefsLoaded = true; - } - - EditorGUI.BeginChangeCheck(); - - var overrideAddress = GetCommandLineRemoteAddressOverride(); - - if (overrideAddress != null) - { - EditorGUILayout.HelpBox("Cache Server preferences cannot be modified because a remote address was specified via command line argument. To modify Cache Server preferences, restart Unity without the " + kIpAddressKeyArgs + " command line argument.", MessageType.Info, true); - } - - using (new EditorGUI.DisabledScope(overrideAddress != null)) - { - var displayMode = overrideAddress != null ? CacheServerMode.Remote : s_CacheServerMode; - s_CacheServerMode = (CacheServerMode)EditorGUILayout.EnumPopup("Cache Server Mode", displayMode); - } - - if (s_CacheServerMode == CacheServerMode.Remote) - { - using (new EditorGUI.DisabledScope(overrideAddress != null)) - { - var displayAddress = overrideAddress != null ? overrideAddress : s_CacheServerIPAddress; - s_CacheServerIPAddress = EditorGUILayout.DelayedTextField("IP Address", displayAddress); - if (GUI.changed) - { - s_ConnectionState = ConnectionState.Unknown; - } - } - - GUILayout.Space(5); - - if (GUILayout.Button("Check Connection", GUILayout.Width(150))) - { - if (InternalEditorUtility.CanConnectToCacheServer()) - s_ConnectionState = ConnectionState.Success; - else - s_ConnectionState = ConnectionState.Failure; - } - - GUILayout.Space(-25); - switch (s_ConnectionState) - { - case ConnectionState.Success: - EditorGUILayout.HelpBox("Connection successful.", MessageType.Info, false); - break; - - case ConnectionState.Failure: - EditorGUILayout.HelpBox("Connection failed.", MessageType.Warning, false); - break; - - case ConnectionState.Unknown: - GUILayout.Space(44); - break; - } - } - else if (s_CacheServerMode == CacheServerMode.Local) - { - const int kMinSizeInGigabytes = 1; - const int kMaxSizeInGigabytes = 200; - - // Write size in GigaBytes. - s_LocalCacheServerSize = EditorGUILayout.IntSlider(Styles.maxCacheSize, s_LocalCacheServerSize, kMinSizeInGigabytes, kMaxSizeInGigabytes); - - s_EnableCustomPath = EditorGUILayout.Toggle(Styles.customCacheLocation, s_EnableCustomPath); - // browse for cache folder if not per project - if (s_EnableCustomPath) - { - GUIStyle style = EditorStyles.miniButton; - GUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel(Styles.cacheFolderLocation, style); - Rect r = GUILayoutUtility.GetRect(GUIContent.none, style); - GUIContent guiText = string.IsNullOrEmpty(s_CachePath) ? Styles.browse : new GUIContent(s_CachePath); - if (EditorGUI.DropdownButton(r, guiText, FocusType.Passive, style)) - { - string pathToOpen = s_CachePath; - string path = EditorUtility.OpenFolderPanel(Styles.browseCacheLocation.text, pathToOpen, ""); - if (!string.IsNullOrEmpty(path)) - { - if (LocalCacheServer.CheckValidCacheLocation(path)) - { - s_CachePath = path; - WritePreferences(); - } - else - EditorUtility.DisplayDialog("Invalid Cache Location", string.Format("The directory {0} contains some files which don't look like Unity Cache server files. Please delete the directory contents or choose another directory.", path), "OK"); - EditorGUIUtility.ExitGUI(); - } - } - GUILayout.EndHorizontal(); - } - else - s_CachePath = ""; - - bool locationExists = LocalCacheServer.CheckCacheLocationExists(); - if (locationExists == true) - { - GUIContent cacheSizeIs = EditorGUIUtility.TrTextContent("Cache size is unknown"); - if (s_LocalCacheServerUsedSize != -1) - { - cacheSizeIs = EditorGUIUtility.TextContent("Cache size is " + EditorUtility.FormatBytes(s_LocalCacheServerUsedSize)); - } - - GUILayout.BeginHorizontal(); - GUIStyle style = EditorStyles.miniButton; - EditorGUILayout.PrefixLabel(cacheSizeIs, style); - Rect r = GUILayoutUtility.GetRect(GUIContent.none, style); - if (EditorGUI.Button(r, Styles.enumerateCache, style)) - { - s_LocalCacheServerUsedSize = LocalCacheServer.CheckCacheLocationExists() ? FileUtil.GetDirectorySize(LocalCacheServer.GetCacheLocation()) : 0; - } - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - GUIContent spacerContent = EditorGUIUtility.blankContent; - EditorGUILayout.PrefixLabel(spacerContent, style); - Rect r2 = GUILayoutUtility.GetRect(GUIContent.none, style); - if (EditorGUI.Button(r2, Styles.cleanCache, style)) - { - LocalCacheServer.Clear(); - s_LocalCacheServerUsedSize = 0; - } - GUILayout.EndHorizontal(); - } - else - { - EditorGUILayout.HelpBox("Local cache directory does not exist - please check that you can access the cache folder and are able to write to it", MessageType.Warning, false); - //If the cache server was on an external HDD or on a temporarily unavailable network drive, set the size to unknown so that the user re-queries it when they've reconnected - s_LocalCacheServerUsedSize = -1; - } - - GUILayout.Label(Styles.cacheFolderLocation.text + ":"); - GUILayout.Label(LocalCacheServer.GetCacheLocation(), s_Constants.cacheFolderLocation); - } - - if (EditorGUI.EndChangeCheck()) - s_HasPendingChanges = true; - - // 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. - if (s_HasPendingChanges && GUIUtility.hotControl == 0) - { - s_HasPendingChanges = false; - WritePreferences(); - ReadPreferences(); - } - } - - } - } -} diff --git a/Editor/Mono/PreferencesWindow/DiagnosticsSwitchPreferences.cs b/Editor/Mono/PreferencesWindow/DiagnosticsSwitchPreferences.cs deleted file mode 100644 index 9b26b68bd3..0000000000 --- a/Editor/Mono/PreferencesWindow/DiagnosticsSwitchPreferences.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - internal static class DiagnosticSwitchPreferences - { - private static Vector2 s_ScrollOffset; - private static string s_FilterString = string.Empty; - - private const uint kMaxRangeForSlider = 10; - - private class Resources - { - public GUIStyle title = "OL Title"; - public GUIStyle scrollArea = "OL Box"; - public Texture2D smallWarningIcon; - public GUIContent restartNeededWarning = EditorGUIUtility.TrTextContent("Some settings will not take effect until you restart Unity."); - - public Resources() - { - smallWarningIcon = EditorGUIUtility.LoadIconRequired("console.warnicon.sml"); - } - } - - private static readonly Resources s_Resources; - - static DiagnosticSwitchPreferences() - { - s_Resources = new Resources(); - } - - private static void DoTopBar() - { - using (new EditorGUILayout.HorizontalScope(s_Resources.title)) - { - GUILayout.FlexibleSpace(); - - s_FilterString = GUILayout.TextField(s_FilterString, EditorStyles.toolbarSearchField, GUILayout.Width(200)); - - if (GUILayout.Button(GUIContent.none, - string.IsNullOrEmpty(s_FilterString) - ? EditorStyles.toolbarSearchFieldCancelButtonEmpty - : EditorStyles.toolbarSearchFieldCancelButton)) - s_FilterString = string.Empty; - } - } - - private static bool PassesFilter(DiagnosticSwitch diagnosticSwitch, string filterString) - { - return string.IsNullOrEmpty(s_FilterString) - || diagnosticSwitch.name.ToLowerInvariant().Contains(filterString) - || diagnosticSwitch.description.ToLowerInvariant().Contains(filterString); - } - - private static bool DisplaySwitch(DiagnosticSwitch diagnosticSwitch) - { - var labelText = new GUIContent(diagnosticSwitch.name, diagnosticSwitch.name + "\n\n" + diagnosticSwitch.description); - bool hasUnappliedValue = !System.Object.Equals(diagnosticSwitch.value, diagnosticSwitch.persistentValue); - - EditorGUI.BeginChangeCheck(); - using (new EditorGUILayout.HorizontalScope()) - { - var rowRect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.label, GUILayout.ExpandWidth(true)); - - var warningRect = new Rect(rowRect.x, rowRect.y, rowRect.height, rowRect.height); - rowRect.xMin += warningRect.width + 3; - - if (hasUnappliedValue && Event.current.type == EventType.Repaint) - GUI.DrawTexture(warningRect, s_Resources.smallWarningIcon); - - if (diagnosticSwitch.value is bool) - { - diagnosticSwitch.persistentValue = EditorGUI.Toggle(rowRect, labelText, (bool)diagnosticSwitch.persistentValue); - } - else if (diagnosticSwitch.enumInfo != null) - { - if (diagnosticSwitch.enumInfo.isFlags) - { - // MaskField's "Everything" entry will set the value to 0xffffffff, but that might mean that it has set bits that - // are not actually valid in the enum. Correct for it by masking the value against the bit patterns that are actually valid. - int validMask = 0; - foreach (int value in diagnosticSwitch.enumInfo.values) - validMask |= value; - - // Also, many enums will provide a 'Nothing' entry at the bottom. If so we need to chop it off, because MaskField can't cope with there being two 'Nothing' entries. - string[] names = diagnosticSwitch.enumInfo.names; - int[] values = diagnosticSwitch.enumInfo.values; - if (diagnosticSwitch.enumInfo.values[0] == 0) - { - names = new string[names.Length - 1]; - values = new int[values.Length - 1]; - Array.Copy(diagnosticSwitch.enumInfo.names, 1, names, 0, names.Length); - Array.Copy(diagnosticSwitch.enumInfo.values, 1, values, 0, values.Length); - } - - diagnosticSwitch.persistentValue = EditorGUI.MaskFieldInternal(rowRect, labelText, (int)diagnosticSwitch.persistentValue, names, values, EditorStyles.popup) & validMask; - } - else - { - var guiNames = new GUIContent[diagnosticSwitch.enumInfo.names.Length]; - for (int i = 0; i < diagnosticSwitch.enumInfo.names.Length; ++i) - guiNames[i] = new GUIContent(diagnosticSwitch.enumInfo.names[i], diagnosticSwitch.enumInfo.annotations[i]); - diagnosticSwitch.persistentValue = EditorGUI.IntPopup(rowRect, labelText, (int)diagnosticSwitch.persistentValue, guiNames, diagnosticSwitch.enumInfo.values); - } - } - else if (diagnosticSwitch.value is UInt32) - { - UInt32 minValue = (UInt32)diagnosticSwitch.minValue; - UInt32 maxValue = (UInt32)diagnosticSwitch.maxValue; - if ((maxValue - minValue <= kMaxRangeForSlider) && - (maxValue - minValue > 0) && - (minValue < int.MaxValue && maxValue < int.MaxValue)) - { - diagnosticSwitch.persistentValue = (UInt32)EditorGUI.IntSlider(rowRect, labelText, (int)(UInt32)diagnosticSwitch.persistentValue, (int)minValue, (int)maxValue); - } - else - { - diagnosticSwitch.persistentValue = (UInt32)EditorGUI.IntField(rowRect, labelText, (int)(UInt32)diagnosticSwitch.persistentValue); - } - } - else if (diagnosticSwitch.value is int) - { - int minValue = (int)diagnosticSwitch.minValue; - int maxValue = (int)diagnosticSwitch.maxValue; - if ((maxValue - minValue <= kMaxRangeForSlider) && - (maxValue - minValue > 0) && - (minValue < int.MaxValue && maxValue < int.MaxValue)) - { - diagnosticSwitch.persistentValue = EditorGUI.IntSlider(rowRect, labelText, (int)diagnosticSwitch.persistentValue, minValue, maxValue); - } - else - { - diagnosticSwitch.persistentValue = EditorGUI.IntField(rowRect, labelText, (int)diagnosticSwitch.persistentValue); - } - } - else if (diagnosticSwitch.value is string) - { - diagnosticSwitch.persistentValue = EditorGUI.TextField(rowRect, labelText, (string)diagnosticSwitch.persistentValue); - } - else - { - var redStyle = new GUIStyle(); - redStyle.normal.textColor = Color.red; - EditorGUI.LabelField(rowRect, labelText, EditorGUIUtility.TrTextContent("Unsupported type: " + diagnosticSwitch.value.GetType().Name), redStyle); - } - } - - if (EditorGUI.EndChangeCheck()) - Debug.SetDiagnosticSwitch(diagnosticSwitch.name, diagnosticSwitch.persistentValue, true); - - return hasUnappliedValue; - } - - [PreferenceItem("Diagnostics")] - private static void OnGUI() - { - List switches = new List(); - Debug.GetDiagnosticSwitches(switches); - switches.Sort((a, b) => Comparer.Default.Compare(a.name, b.name)); - - DoTopBar(); - - bool hasAnyUnappliedSwitches = false; - - using (var scrollScope = new EditorGUILayout.VerticalScrollViewScope(s_ScrollOffset, false, GUI.skin.verticalScrollbar, s_Resources.scrollArea)) - { - var sanitisedFilter = s_FilterString.ToLowerInvariant().Trim(); - - for (int i = 0; i < switches.Count; ++i) - { - if (!PassesFilter(switches[i], sanitisedFilter)) - continue; - - hasAnyUnappliedSwitches |= DisplaySwitch(switches[i]); - } - - s_ScrollOffset = scrollScope.scrollPosition; - } - - var helpBox = GUILayoutUtility.GetRect(s_Resources.restartNeededWarning, EditorStyles.helpBox, GUILayout.MinHeight(40)); - if (hasAnyUnappliedSwitches) - EditorGUI.HelpBox(helpBox, s_Resources.restartNeededWarning.text, MessageType.Warning); - } - } -} diff --git a/Editor/Mono/PreferencesWindow/PreferencesWindow.cs b/Editor/Mono/PreferencesWindow/PreferencesWindow.cs deleted file mode 100644 index 01901c281b..0000000000 --- a/Editor/Mono/PreferencesWindow/PreferencesWindow.cs +++ /dev/null @@ -1,1281 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.VersionControl; -using UnityEditor.Modules; -using UnityEditorInternal; -using System.Collections.Generic; -using System; -using System.IO; -using System.Reflection; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using UnityEditor.Connect; -using UnityEditor.Collaboration; -using UnityEditor.Web; - -namespace UnityEditor -{ - internal class PreferencesWindow : EditorWindow - { - internal class Constants - { - public GUIStyle sectionScrollView = "PreferencesSectionBox"; - public GUIStyle settingsBoxTitle = "OL Title"; - public GUIStyle settingsBox = "OL Box"; - public GUIStyle errorLabel = "WordWrappedLabel"; - public GUIStyle sectionElement = "PreferencesSection"; - public GUIStyle evenRow = "CN EntryBackEven"; - public GUIStyle oddRow = "CN EntryBackOdd"; - public GUIStyle selected = "OL SelectedRow"; - public GUIStyle keysElement = "PreferencesKeysElement"; - public GUIStyle warningIcon = "CN EntryWarn"; - public GUIStyle sectionHeader = new GUIStyle(EditorStyles.largeLabel); - public GUIStyle cacheFolderLocation = new GUIStyle(GUI.skin.label); - - public Constants() - { - sectionScrollView = new GUIStyle(sectionScrollView); - sectionScrollView.overflow.bottom += 1; - - sectionHeader.fontStyle = FontStyle.Bold; - sectionHeader.fontSize = 18; - sectionHeader.margin.top = 10; - sectionHeader.margin.left += 1; - if (!EditorGUIUtility.isProSkin) - sectionHeader.normal.textColor = new Color(0.4f, 0.4f, 0.4f, 1.0f); - else - sectionHeader.normal.textColor = new Color(0.7f, 0.7f, 0.7f, 1.0f); - - cacheFolderLocation.wordWrap = true; - } - } - - internal class Styles - { - // Common - public static readonly GUIContent browse = EditorGUIUtility.TrTextContent("Browse..."); - - // General - public static readonly GUIContent autoRefresh = EditorGUIUtility.TrTextContent("Auto Refresh"); - public static readonly GUIContent autoRefreshHelpBox = EditorGUIUtility.TrTextContent("Auto Refresh must be set when using Collaboration feature.", EditorGUIUtility.GetHelpIcon(MessageType.Warning)); - public static readonly GUIContent loadPreviousProjectOnStartup = EditorGUIUtility.TrTextContent("Load Previous Project on Startup"); - public static readonly GUIContent compressAssetsOnImport = EditorGUIUtility.TrTextContent("Compress Assets on Import"); - public static readonly GUIContent osxColorPicker = EditorGUIUtility.TrTextContent("macOS Color Picker"); - public static readonly GUIContent disableEditorAnalytics = EditorGUIUtility.TrTextContent("Disable Editor Analytics (Pro Only)"); - public static readonly GUIContent showAssetStoreSearchHits = EditorGUIUtility.TrTextContent("Show Asset Store search hits"); - public static readonly GUIContent verifySavingAssets = EditorGUIUtility.TrTextContent("Verify Saving Assets"); - public static readonly GUIContent editorSkin = EditorGUIUtility.TrTextContent("Editor Skin"); - public static readonly GUIContent[] editorSkinOptions = new GUIContent[] { EditorGUIUtility.TrTextContent("Personal"), EditorGUIUtility.TrTextContent("Professional"), }; - public static readonly GUIContent enableAlphaNumericSorting = EditorGUIUtility.TrTextContent("Enable Alpha Numeric Sorting"); - - // External Tools - public static readonly GUIContent downloadMonoDevelopInstaller = EditorGUIUtility.TrTextContent("Download MonoDevelop Installer"); - public static readonly GUIContent addUnityProjeToSln = EditorGUIUtility.TrTextContent("Add .unityproj's to .sln"); - public static readonly GUIContent editorAttaching = EditorGUIUtility.TrTextContent("Editor Attaching"); - public static readonly GUIContent changingThisSettingRequiresRestart = EditorGUIUtility.TrTextContent("Changing this setting requires a restart to take effect."); - public static readonly GUIContent revisionControlDiffMerge = EditorGUIUtility.TrTextContent("Revision Control Diff/Merge"); - public static readonly GUIContent externalScriptEditor = EditorGUIUtility.TrTextContent("External Script Editor"); - public static readonly GUIContent imageApplication = EditorGUIUtility.TrTextContent("Image application"); - - // Colors - public static readonly GUIContent userDefaults = EditorGUIUtility.TrTextContent("Use Defaults"); - - // GI Cache - 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."); - public static readonly GUIContent customCacheLocation = EditorGUIUtility.TrTextContent("Custom cache location", "Specify the GI Cache folder location."); - public static readonly GUIContent cacheFolderLocation = EditorGUIUtility.TrTextContent("Cache Folder Location", "The GI Cache folder is shared between all projects."); - 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."); - public static readonly GUIContent cantChangeCacheSettings = EditorGUIUtility.TrTextContent("Cache settings can't be changed while lightmapping is being computed."); - public static readonly GUIContent cleanCache = EditorGUIUtility.TrTextContent("Clean Cache"); - public static readonly GUIContent browseGICacheLocation = EditorGUIUtility.TrTextContent("Browse for GI Cache location"); - public static readonly GUIContent cacheSizeIs = EditorGUIUtility.TrTextContent("Cache size is"); - public static readonly GUIContent pleaseWait = EditorGUIUtility.TrTextContent("Please wait..."); - - // 2D - public static readonly GUIContent spriteMaxCacheSize = EditorGUIUtility.TrTextContent("Max Sprite Atlas Cache Size (GB)", "The size of the Sprite Atlas Cache folder will be kept below this maximum value when possible. Change requires Editor restart"); - - // Language - public static readonly GUIContent editorLanguageExperimental = EditorGUIUtility.TrTextContent("Editor Language(Experimental)"); - public static readonly GUIContent editorLanguage = EditorGUIUtility.TrTextContent("Editor language"); - } - - private delegate void OnGUIDelegate(); - private class Section - { - public GUIContent content; - public OnGUIDelegate guiFunc; - - public Section(string name, OnGUIDelegate guiFunc) - { - this.content = EditorGUIUtility.TrTextContent(name); - this.guiFunc = guiFunc; - } - - public Section(string name, Texture2D icon, OnGUIDelegate guiFunc) - { - this.content = EditorGUIUtility.TrTextContent(name, icon); - this.guiFunc = guiFunc; - } - - public Section(GUIContent content, OnGUIDelegate guiFunc) - { - this.content = content; - this.guiFunc = guiFunc; - } - } - - private List
m_Sections; - private int m_SelectedSectionIndex; - private int selectedSectionIndex - { - get { return m_SelectedSectionIndex; } - set - { - if (m_SelectedSectionIndex != value) - { - // Reset the valid key indicator when changing section - m_ValidKeyChange = true; - } - m_SelectedSectionIndex = value; - if (m_SelectedSectionIndex >= m_Sections.Count) - m_SelectedSectionIndex = 0; - else if (m_SelectedSectionIndex < 0) - m_SelectedSectionIndex = m_Sections.Count - 1; - } - } - private Section selectedSection { get { return m_Sections[m_SelectedSectionIndex]; } } - - static Constants constants = null; - - private List prefWinExtensions; - private bool m_AutoRefresh; - - private bool m_ReopenLastUsedProjectOnStartup; - private bool m_CompressAssetsOnImport; - private bool m_UseOSColorPicker; - private bool m_EnableEditorAnalytics; - private bool m_ShowAssetStoreSearchHits; - private bool m_VerifySavingAssets; - private bool m_DeveloperMode; - private bool m_DeveloperModeDirty; - private bool m_AllowAttachedDebuggingOfEditor; - private bool m_AllowAttachedDebuggingOfEditorStateChangedThisSession; - private string m_GpuDevice; - private string[] m_CachedGpuDevices; - - private struct GICacheSettings - { - public bool m_EnableCustomPath; - public int m_MaximumSize; - public string m_CachePath; - public int m_CompressionLevel; // GICache compression level, corresponds to CompressionLevel in Compression.h - } - private GICacheSettings m_GICacheSettings; - - private RefString m_ScriptEditorPath = new RefString(""); - private string m_ScriptEditorArgs = ""; - private bool m_ExternalEditorSupportsUnityProj; - private RefString m_ImageAppPath = new RefString(""); - private int m_DiffToolIndex; - - // how many menu items come before the actual list of languages - // (Default + separator) - private const int k_LangListMenuOffset = 2; - - private string m_SelectedLanguage; - private GUIContent[] m_EditorLanguageNames; - private bool m_EnableEditorLocalization; - private SystemLanguage[] m_stableLanguages = { SystemLanguage.English }; - - private bool m_AllowAlphaNumericHierarchy = false; - - private string[] m_ScriptApps; - private string[] m_ScriptAppsEditions; - private string[] m_ImageApps; - private string[] m_DiffTools; - - private string m_noDiffToolsMessage = string.Empty; - - private bool m_RefreshCustomPreferences; - private string[] m_ScriptAppDisplayNames; - private string[] m_ImageAppDisplayNames; - Vector2 m_KeyScrollPos; - Vector2 m_SectionScrollPos; - PrefKey m_SelectedKey = null; - private const string kRecentScriptAppsKey = "RecentlyUsedScriptApp"; - private const string kRecentImageAppsKey = "RecentlyUsedImageApp"; - - private const string m_ExpressNotSupportedMessage = - "Unfortunately Visual Studio Express does not allow itself to be controlled by external applications. " + - "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(This does work with Visual Studio Pro)"; - - private const int kRecentAppsCount = 10; - - SortedDictionary>> s_CachedColors = null; - private static Vector2 s_ScrollPosition = Vector2.zero; - - private int m_SpriteAtlasCacheSize; - private static int kMinSpriteCacheSizeInGigabytes = 1; - private static int kMaxSpriteCacheSizeInGigabytes = 200; - - private bool m_ValidKeyChange = true; - private string m_InvalidKeyMessage = string.Empty; - - class RefString - { - public RefString(string s) { str = s; } - public string str; - public static implicit operator string(RefString s) { return s.str; } - public override string ToString() - { - return str; - } - } - - static void ShowPreferencesWindow() - { - EditorWindow w = EditorWindow.GetWindow(true, L10n.Tr("Unity Preferences")); - w.minSize = new Vector2(540, 400); - w.maxSize = new Vector2(w.minSize.x, w.maxSize.y); // Limit to only changing the height. - w.position = new Rect(new Vector2(100, 100), w.minSize); - w.m_Parent.window.m_DontSaveToLayout = true; - } - - void OnEnable() - { - prefWinExtensions = ModuleManager.GetPreferenceWindowExtensions(); - - ReadPreferences(); - - m_Sections = new List
(); - - //@TODO Move these to custom sections - m_Sections.Add(new Section("General", ShowGeneral)); - m_Sections.Add(new Section("External Tools", ShowExternalApplications)); - m_Sections.Add(new Section("Colors", ShowColors)); - m_Sections.Add(new Section("Keys", ShowKeys)); - m_Sections.Add(new Section("GI Cache", ShowGICache)); - m_Sections.Add(new Section("2D", Show2D)); - SystemLanguage[] editorLanguages = LocalizationDatabase.GetAvailableEditorLanguages(); - if (m_EditorLanguageNames == null || m_EditorLanguageNames.Length != editorLanguages.Length) - { - m_EditorLanguageNames = new GUIContent[editorLanguages.Length]; - - for (int i = 0; i < editorLanguages.Length; ++i) - { - // not in stable languages list - display it as experimental language - if (ArrayUtility.FindIndex(m_stableLanguages, delegate(SystemLanguage v) { return v == editorLanguages[i]; }) < 0) - { - m_EditorLanguageNames[i] = EditorGUIUtility.TextContent(string.Format("{0} (Experimental)", editorLanguages[i].ToString())); - } - else - { - m_EditorLanguageNames[i] = EditorGUIUtility.TextContent(editorLanguages[i].ToString()); - } - } - ArrayUtility.Insert(ref m_EditorLanguageNames, 0, EditorGUIUtility.TextContent("")); - GUIContent defaultLanguage = EditorGUIUtility.TextContent(string.Format("Default ( {0} )", LocalizationDatabase.GetDefaultEditorLanguage().ToString())); - ArrayUtility.Insert(ref m_EditorLanguageNames, 0, defaultLanguage); - } - if (editorLanguages.Length > 1) - { - m_Sections.Add(new Section("Language", ShowLanguage)); - } - - if (Unsupported.IsDeveloperMode() || UnityConnect.preferencesEnabled) - { - m_Sections.Add(new Section("Unity Services", ShowUnityConnectPrefs)); - } - // Workaround for EditorAssemblies not loaded yet during mono assembly reload. - m_RefreshCustomPreferences = true; - } - - private void AddCustomSections() - { - AttributeHelper.MethodInfoSorter methods = AttributeHelper.GetMethodsWithAttribute(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); - foreach (var method in methods.methodsWithAttributes) - { - OnGUIDelegate callback = Delegate.CreateDelegate(typeof(OnGUIDelegate), method.info) as OnGUIDelegate; - if (callback != null) - { - var attributeName = (method.attribute as PreferenceItem).name; - // Group Preference sections with the same name - int idx = m_Sections.FindIndex(section => section.content.text.Equals(attributeName)); - if (idx >= 0) - { - m_Sections[idx].guiFunc += callback; - } - else - { - m_Sections.Add(new Section(attributeName, callback)); - } - } - } - } - - private void OnGUI() - { - // Workaround for EditorAssemblies not loaded yet during mono assembly reload. - if (m_RefreshCustomPreferences) - { - AddCustomSections(); - m_RefreshCustomPreferences = false; - } - - EditorGUIUtility.labelWidth = 200f; - - if (constants == null) - { - constants = new Constants(); - } - - HandleKeys(); - - GUILayout.BeginHorizontal(); - { - m_SectionScrollPos = GUILayout.BeginScrollView(m_SectionScrollPos, constants.sectionScrollView, GUILayout.Width(140f)); - { - GUILayout.Space(40f); - for (int i = 0; i < m_Sections.Count; i++) - { - var section = m_Sections[i]; - - Rect elementRect = GUILayoutUtility.GetRect(section.content, constants.sectionElement, GUILayout.ExpandWidth(true)); - - if (section == selectedSection && Event.current.type == EventType.Repaint) - constants.selected.Draw(elementRect, false, false, false, false); - - EditorGUI.BeginChangeCheck(); - if (GUI.Toggle(elementRect, selectedSectionIndex == i, section.content, constants.sectionElement)) - selectedSectionIndex = i; - if (EditorGUI.EndChangeCheck()) - GUIUtility.keyboardControl = 0; - } - } - GUILayout.EndScrollView(); - - GUILayout.Space(10.0f); - - GUILayout.BeginVertical(); - { - GUILayout.Label(selectedSection.content, constants.sectionHeader); - GUILayout.Space(10f); - s_ScrollPosition = EditorGUILayout.BeginScrollView(s_ScrollPosition); - selectedSection.guiFunc(); - EditorGUILayout.EndScrollView(); - } - GUILayout.EndVertical(); - } - GUILayout.EndHorizontal(); - } - - private void HandleKeys() - { - if (Event.current.type != EventType.KeyDown || GUIUtility.keyboardControl != 0) - return; - - switch (Event.current.keyCode) - { - case KeyCode.UpArrow: - selectedSectionIndex--; - Event.current.Use(); - break; - case KeyCode.DownArrow: - selectedSectionIndex++; - Event.current.Use(); - break; - } - } - - private void ShowExternalApplications() - { - // Applications - FilePopup(Styles.externalScriptEditor, m_ScriptEditorPath, ref m_ScriptAppDisplayNames, ref m_ScriptApps, m_ScriptEditorPath, "internal", OnScriptEditorChanged); - - var scriptEditor = GetSelectedScriptEditor(); - - if (scriptEditor == ScriptEditorUtility.ScriptEditor.Other) - { - string oldEditorArgs = m_ScriptEditorArgs; - m_ScriptEditorArgs = EditorGUILayout.TextField("External Script Editor Args", m_ScriptEditorArgs); - if (oldEditorArgs != m_ScriptEditorArgs) - OnScriptEditorArgsChanged(); - } - - DoUnityProjCheckbox(); - - bool oldValue = m_AllowAttachedDebuggingOfEditor; - m_AllowAttachedDebuggingOfEditor = EditorGUILayout.Toggle(Styles.editorAttaching, m_AllowAttachedDebuggingOfEditor); - - if (oldValue != m_AllowAttachedDebuggingOfEditor) - m_AllowAttachedDebuggingOfEditorStateChangedThisSession = true; - - if (m_AllowAttachedDebuggingOfEditorStateChangedThisSession) - GUILayout.Label(Styles.changingThisSettingRequiresRestart, EditorStyles.helpBox); - - if (GetSelectedScriptEditor() == ScriptEditorUtility.ScriptEditor.VisualStudioExpress) - { - GUILayout.BeginHorizontal(EditorStyles.helpBox); - GUILayout.Label("", constants.warningIcon); - GUILayout.Label(m_ExpressNotSupportedMessage, constants.errorLabel); - GUILayout.EndHorizontal(); - } - - GUILayout.Space(10f); - - FilePopup(Styles.imageApplication, m_ImageAppPath, ref m_ImageAppDisplayNames, ref m_ImageApps, m_ImageAppPath, "internal", null); - - GUILayout.Space(10f); - - using (new EditorGUI.DisabledScope(!InternalEditorUtility.HasTeamLicense())) - { - m_DiffToolIndex = EditorGUILayout.Popup(Styles.revisionControlDiffMerge, m_DiffToolIndex, m_DiffTools); - } - - if (m_noDiffToolsMessage != string.Empty) - { - GUILayout.BeginHorizontal(EditorStyles.helpBox); - GUILayout.Label("", constants.warningIcon); - GUILayout.Label(m_noDiffToolsMessage, constants.errorLabel); - GUILayout.EndHorizontal(); - } - - GUILayout.Space(10f); - - foreach (IPreferenceWindowExtension extension in prefWinExtensions) - { - if (extension.HasExternalApplications()) - { - GUILayout.Space(10f); - extension.ShowExternalApplications(); - } - } - - ApplyChangesToPrefs(); - } - - private void DoUnityProjCheckbox() - { - bool isConfigurable = false; - bool value = false; - - ScriptEditorUtility.ScriptEditor scriptEditor = GetSelectedScriptEditor(); - - if (scriptEditor == ScriptEditorUtility.ScriptEditor.MonoDevelop) - { - isConfigurable = true; - value = m_ExternalEditorSupportsUnityProj; - } - - using (new EditorGUI.DisabledScope(!isConfigurable)) - { - value = EditorGUILayout.Toggle(Styles.addUnityProjeToSln, value); - } - - if (isConfigurable) - m_ExternalEditorSupportsUnityProj = value; - } - - private ScriptEditorUtility.ScriptEditor GetSelectedScriptEditor() - { - return ScriptEditorUtility.GetScriptEditorFromPath(m_ScriptEditorPath.str); - } - - private void OnScriptEditorChanged() - { - ScriptEditorUtility.SetExternalScriptEditor(m_ScriptEditorPath); - m_ScriptEditorArgs = ScriptEditorUtility.GetExternalScriptEditorArgs(); - UnityEditor.VisualStudioIntegration.UnityVSSupport.ScriptEditorChanged(m_ScriptEditorPath.str); - } - - private void OnScriptEditorArgsChanged() - { - ScriptEditorUtility.SetExternalScriptEditorArgs(m_ScriptEditorArgs); - } - - private void ShowUnityConnectPrefs() - { - UnityConnectPrefs.ShowPanelPrefUI(); - ApplyChangesToPrefs(); - } - - private void ShowGeneral() - { - // Options - bool collabEnabled = Collab.instance.IsCollabEnabledForCurrentProject(); - using (new EditorGUI.DisabledScope(collabEnabled)) - { - if (collabEnabled) - { - EditorGUILayout.Toggle(Styles.autoRefresh, true); // Don't keep toggle value in m_AutoRefresh since we don't want to save the overwritten value - EditorGUILayout.HelpBox(Styles.autoRefreshHelpBox); - } - else - m_AutoRefresh = EditorGUILayout.Toggle(Styles.autoRefresh, m_AutoRefresh); - } - - m_ReopenLastUsedProjectOnStartup = EditorGUILayout.Toggle(Styles.loadPreviousProjectOnStartup, m_ReopenLastUsedProjectOnStartup); - - bool oldCompressOnImport = m_CompressAssetsOnImport; - m_CompressAssetsOnImport = EditorGUILayout.Toggle(Styles.compressAssetsOnImport, oldCompressOnImport); - - if (GUI.changed && m_CompressAssetsOnImport != oldCompressOnImport) - Unsupported.SetApplicationSettingCompressAssetsOnImport(m_CompressAssetsOnImport); - - if (Application.platform == RuntimePlatform.OSXEditor) - m_UseOSColorPicker = EditorGUILayout.Toggle(Styles.osxColorPicker, m_UseOSColorPicker); - - bool pro = UnityEngine.Application.HasProLicense(); - using (new EditorGUI.DisabledScope(!pro)) - { - m_EnableEditorAnalytics = !EditorGUILayout.Toggle(Styles.disableEditorAnalytics, !m_EnableEditorAnalytics); - if (!pro && !m_EnableEditorAnalytics) - m_EnableEditorAnalytics = true; - } - - bool assetStoreSearchChanged = false; - EditorGUI.BeginChangeCheck(); - m_ShowAssetStoreSearchHits = EditorGUILayout.Toggle(Styles.showAssetStoreSearchHits, m_ShowAssetStoreSearchHits); - if (EditorGUI.EndChangeCheck()) - assetStoreSearchChanged = true; - - m_VerifySavingAssets = EditorGUILayout.Toggle(Styles.verifySavingAssets, m_VerifySavingAssets); - - // Only show this toggle if this is a source build or we're already in developer mode. - // We don't want to show this to users yet. - if (Unsupported.IsSourceBuild() || m_DeveloperMode) - { - EditorGUI.BeginChangeCheck(); - m_DeveloperMode = EditorGUILayout.Toggle("Developer Mode", m_DeveloperMode); - if (EditorGUI.EndChangeCheck()) - m_DeveloperModeDirty = true; - } - - using (new EditorGUI.DisabledScope(!pro)) - { - int newSkin = EditorGUILayout.Popup(Styles.editorSkin, !EditorGUIUtility.isProSkin ? 0 : 1, Styles.editorSkinOptions); - if ((!EditorGUIUtility.isProSkin ? 0 : 1) != newSkin) - InternalEditorUtility.SwitchSkinAndRepaintAllViews(); - } - - bool oldAlphaNumeric = m_AllowAlphaNumericHierarchy; - m_AllowAlphaNumericHierarchy = EditorGUILayout.Toggle(Styles.enableAlphaNumericSorting, m_AllowAlphaNumericHierarchy); - - if (InternalEditorUtility.IsGpuDeviceSelectionSupported()) - { - // Cache gpu devices - if (m_CachedGpuDevices == null) - { - var devices = InternalEditorUtility.GetGpuDevices(); - m_CachedGpuDevices = new string[devices.Length + 1]; - m_CachedGpuDevices[0] = "Automatic"; - Array.Copy(devices, 0, m_CachedGpuDevices, 1, devices.Length); - } - - // Try to find selected gpu device - var currentGpuDeviceIndex = Array.FindIndex(m_CachedGpuDevices, (string gpuDevice) => m_GpuDevice == gpuDevice); - if (currentGpuDeviceIndex == -1) - currentGpuDeviceIndex = 0; - - var newGpuDeviceIndex = EditorGUILayout.Popup("Device To Use", currentGpuDeviceIndex, m_CachedGpuDevices); - if (currentGpuDeviceIndex != newGpuDeviceIndex) - { - m_GpuDevice = m_CachedGpuDevices[newGpuDeviceIndex]; - InternalEditorUtility.SetGpuDeviceAndRecreateGraphics(newGpuDeviceIndex - 1, m_GpuDevice); - } - } - ApplyChangesToPrefs(); - - if (oldAlphaNumeric != m_AllowAlphaNumericHierarchy) - EditorApplication.DirtyHierarchyWindowSorting(); - - if (assetStoreSearchChanged) - { - ProjectBrowser.ShowAssetStoreHitsWhileSearchingLocalAssetsChanged(); - } - } - - public void ApplyChangesToPrefs(bool force = false) - { - if (GUI.changed || force) - { - WritePreferences(); - ReadPreferences(); - Repaint(); - } - } - - private void RevertKeys() - { - foreach (KeyValuePair kvp in Settings.Prefs()) - { - kvp.Value.ResetToDefault(); - EditorPrefs.SetString(kvp.Value.Name, kvp.Value.ToUniqueString()); - } - } - - private SortedDictionary>> OrderPrefs(IEnumerable> input) - where T : IPrefType - { - SortedDictionary>> retval = new SortedDictionary>>(); - - foreach (KeyValuePair kvp in input) - { - int idx = kvp.Key.IndexOf('/'); - string first, second; - if (idx == -1) - { - first = "General"; - second = kvp.Key; - } - else - { - first = kvp.Key.Substring(0, idx); - second = kvp.Key.Substring(idx + 1); - } - if (!retval.ContainsKey(first)) - { - List> inner = new List>(); - inner.Add(new KeyValuePair(second, kvp.Value)); - retval.Add(first, new List>(inner)); - } - else - { - retval[first].Add(new KeyValuePair(second, kvp.Value)); - } - } - - return retval; - } - - static int s_KeysControlHash = "KeysControlHash".GetHashCode(); - private void ShowKeys() - { - int id = GUIUtility.GetControlID(s_KeysControlHash, FocusType.Keyboard); - - GUILayout.BeginHorizontal(); - GUILayout.BeginVertical(GUILayout.Width(185f)); - GUILayout.Label("Actions", constants.settingsBoxTitle, GUILayout.ExpandWidth(true)); - m_KeyScrollPos = GUILayout.BeginScrollView(m_KeyScrollPos, constants.settingsBox); - - PrefKey prevKey = null; - PrefKey nextKey = null; - bool foundSelectedKey = false; - - foreach (KeyValuePair kvp in Settings.Prefs()) - { - if (!foundSelectedKey) - { - if (kvp.Value == m_SelectedKey) - { - foundSelectedKey = true; - } - else - { - prevKey = kvp.Value; - } - } - else - { - if (nextKey == null) nextKey = kvp.Value; - } - - EditorGUI.BeginChangeCheck(); - if (GUILayout.Toggle(kvp.Value == m_SelectedKey, kvp.Key, constants.keysElement)) - { - if (m_SelectedKey != kvp.Value) - { - m_ValidKeyChange = true; - } - m_SelectedKey = kvp.Value; - } - if (EditorGUI.EndChangeCheck()) - GUIUtility.keyboardControl = id; - } - GUILayout.EndScrollView(); - GUILayout.EndVertical(); - - GUILayout.Space(10.0f); - - GUILayout.BeginVertical(); - - if (m_SelectedKey != null) - { - Event e = m_SelectedKey.KeyboardEvent; - GUI.changed = false; - var splitKey = m_SelectedKey.Name.Split('/'); - System.Diagnostics.Debug.Assert(splitKey.Length == 2, "Unexpected Split: " + m_SelectedKey.Name); - GUILayout.Label(splitKey[0], "boldLabel"); - GUILayout.Label(splitKey[1], "boldLabel"); - - GUILayout.BeginHorizontal(); - GUILayout.Label("Key:"); - e = EditorGUILayout.KeyEventField(e); - GUILayout.EndHorizontal(); - - GUILayout.BeginHorizontal(); - GUILayout.Label("Modifiers:"); - GUILayout.BeginVertical(); - if (Application.platform == RuntimePlatform.OSXEditor) - e.command = GUILayout.Toggle(e.command, "Command"); - e.control = GUILayout.Toggle(e.control, "Control"); - e.shift = GUILayout.Toggle(e.shift, "Shift"); - e.alt = GUILayout.Toggle(e.alt, "Alt"); - - if (GUI.changed) - { - m_ValidKeyChange = true; - string selectedToolName = m_SelectedKey.Name.Split('/')[0]; - - foreach (KeyValuePair kvp in Settings.Prefs()) - { - // Setting the same key to the same action is ok. - // Setting the same key to a different action from a different tool is ok too. - string toolName = kvp.Key.Split('/')[0]; - if (kvp.Value.KeyboardEvent.Equals(e) && (toolName == selectedToolName && kvp.Key != m_SelectedKey.Name)) - { - m_ValidKeyChange = false; - StringBuilder sb = new StringBuilder(); - if (Application.platform == RuntimePlatform.OSXEditor && e.command) - sb.Append("Command+"); - if (e.control) - sb.Append("Ctrl+"); - if (e.shift) - sb.Append("Shift+"); - if (e.alt) - sb.Append("Alt+"); - sb.Append(e.keyCode); - - m_InvalidKeyMessage = string.Format("Key {0} can't be used for action \"{1}\" because it's already used for action \"{2}\"", - sb, m_SelectedKey.Name, kvp.Key); - break; - } - } - - if (m_ValidKeyChange) - { - m_SelectedKey.KeyboardEvent = e; - Settings.Set(m_SelectedKey.Name, m_SelectedKey); - } - } - else - { - if (GUIUtility.keyboardControl == id && Event.current.type == EventType.KeyDown) - { - switch (Event.current.keyCode) - { - case KeyCode.UpArrow: - if (prevKey != null && prevKey != m_SelectedKey) - { - m_SelectedKey = prevKey; - m_ValidKeyChange = true; - } - Event.current.Use(); - break; - case KeyCode.DownArrow: - if (nextKey != null && nextKey != m_SelectedKey) - { - m_SelectedKey = nextKey; - m_ValidKeyChange = true; - } - Event.current.Use(); - break; - } - } - } - - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - - if (!m_ValidKeyChange) - { - GUILayout.BeginHorizontal(); - GUILayout.Label("", constants.warningIcon); - GUILayout.Label(m_InvalidKeyMessage, constants.errorLabel); - GUILayout.EndHorizontal(); - } - } - - GUILayout.EndVertical(); - GUILayout.Space(10f); - - GUILayout.EndHorizontal(); - GUILayout.Space(5f); - - if (GUILayout.Button(Styles.userDefaults, GUILayout.Width(120))) - { - m_ValidKeyChange = true; - RevertKeys(); - } - } - - private void RevertColors() - { - foreach (KeyValuePair kvp in Settings.Prefs()) - { - kvp.Value.ResetToDefault(); - EditorPrefs.SetString(kvp.Value.Name, kvp.Value.ToUniqueString()); - } - } - - private void ShowColors() - { - if (s_CachedColors == null) - { - s_CachedColors = OrderPrefs(Settings.Prefs()); - } - - var changedColor = false; - PrefColor ccolor = null; - foreach (KeyValuePair>> category in s_CachedColors) - { - GUILayout.Label(category.Key, EditorStyles.boldLabel); - foreach (KeyValuePair kvp in category.Value) - { - EditorGUI.BeginChangeCheck(); - Color c = EditorGUILayout.ColorField(kvp.Key, kvp.Value.Color); - if (EditorGUI.EndChangeCheck()) - { - ccolor = kvp.Value; - ccolor.Color = c; - changedColor = true; - } - } - if (ccolor != null) - Settings.Set(ccolor.Name, ccolor); - } - GUILayout.Space(5f); - - if (GUILayout.Button(Styles.userDefaults, GUILayout.Width(120))) - { - RevertColors(); - changedColor = true; - } - - if (changedColor) - EditorApplication.RequestRepaintAllViews(); - } - - private void Show2D() - { - // 2D Settings. - EditorGUI.BeginChangeCheck(); - - m_SpriteAtlasCacheSize = EditorGUILayout.IntSlider(Styles.spriteMaxCacheSize, m_SpriteAtlasCacheSize, kMinSpriteCacheSizeInGigabytes, kMaxSpriteCacheSizeInGigabytes); - if (EditorGUI.EndChangeCheck()) - WritePreferences(); - } - - private void ShowGICache() - { - { - // Show Gigabytes to the user. - const int kMinSizeInGigabytes = 5; - const int kMaxSizeInGigabytes = 200; - - // Write size in GigaBytes. - m_GICacheSettings.m_MaximumSize = EditorGUILayout.IntSlider(Styles.maxCacheSize, m_GICacheSettings.m_MaximumSize, kMinSizeInGigabytes, kMaxSizeInGigabytes); - WritePreferences(); - } - GUILayout.BeginHorizontal(); - { - if (Lightmapping.isRunning) - { - GUIContent warning = EditorGUIUtility.TextContent(Styles.cantChangeCacheSettings.text); - EditorGUILayout.HelpBox(warning.text, MessageType.Warning, true); - } - } - GUILayout.EndHorizontal(); - - using (new EditorGUI.DisabledScope(Lightmapping.isRunning)) - { - m_GICacheSettings.m_EnableCustomPath = EditorGUILayout.Toggle(Styles.customCacheLocation, m_GICacheSettings.m_EnableCustomPath); - - // browse for cache folder if not per project - if (m_GICacheSettings.m_EnableCustomPath) - { - GUIStyle style = EditorStyles.miniButton; - GUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel(Styles.cacheFolderLocation, style); - Rect r = GUILayoutUtility.GetRect(GUIContent.none, style); - GUIContent guiText = string.IsNullOrEmpty(m_GICacheSettings.m_CachePath) ? Styles.browse : new GUIContent(m_GICacheSettings.m_CachePath); - if (EditorGUI.DropdownButton(r, guiText, FocusType.Passive, style)) - { - string pathToOpen = m_GICacheSettings.m_CachePath; - string path = EditorUtility.OpenFolderPanel(Styles.browseGICacheLocation.text, pathToOpen, ""); - if (!string.IsNullOrEmpty(path)) - { - m_GICacheSettings.m_CachePath = path; - WritePreferences(); - } - } - GUILayout.EndHorizontal(); - } - else - m_GICacheSettings.m_CachePath = ""; - - // We use toggle for now, 0 means kCompressionLevelNone, 1 - kCompressionLevelFastest. - m_GICacheSettings.m_CompressionLevel = EditorGUILayout.Toggle(Styles.cacheCompression, m_GICacheSettings.m_CompressionLevel == 1) ? 1 : 0; - - if (GUILayout.Button(Styles.cleanCache, GUILayout.Width(120))) - { - EditorUtility.DisplayProgressBar(Styles.cleanCache.text, Styles.pleaseWait.text, 0.0F); - Lightmapping.Clear(); - EditorUtility.DisplayProgressBar(Styles.cleanCache.text, Styles.pleaseWait.text, 0.5F); - UnityEditor.Lightmapping.ClearDiskCache(); - EditorUtility.ClearProgressBar(); - } - - if (UnityEditor.Lightmapping.diskCacheSize >= 0) - GUILayout.Label(Styles.cacheSizeIs.text + " " + EditorUtility.FormatBytes(UnityEditor.Lightmapping.diskCacheSize)); - else - GUILayout.Label(Styles.cacheSizeIs.text + " is being calculated..."); - - GUILayout.Label(Styles.cacheFolderLocation.text + ":"); - GUILayout.Label(UnityEditor.Lightmapping.diskCachePath, constants.cacheFolderLocation); - } - } - - private void ShowLanguage() - { - var enable_localization = EditorGUILayout.Toggle(Styles.editorLanguageExperimental, m_EnableEditorLocalization); - if (enable_localization != m_EnableEditorLocalization) - { - m_EnableEditorLocalization = enable_localization; - m_SelectedLanguage = LocalizationDatabase.GetDefaultEditorLanguage().ToString(); - } - - EditorGUI.BeginDisabledGroup(!m_EnableEditorLocalization); - { - SystemLanguage[] editorLanguages = LocalizationDatabase.GetAvailableEditorLanguages(); - - int idx = 0; - for (int i = 0; i < editorLanguages.Length; i++) - { - if (editorLanguages[i].ToString().Equals(m_SelectedLanguage)) - { - idx = k_LangListMenuOffset + i; - break; - } - } - - int sel = EditorGUILayout.Popup(Styles.editorLanguage, idx, m_EditorLanguageNames); - m_SelectedLanguage = (sel == 0) ? LocalizationDatabase.GetDefaultEditorLanguage().ToString() : - editorLanguages[sel - k_LangListMenuOffset].ToString(); - } - EditorGUI.EndDisabledGroup(); - - if (!m_SelectedLanguage.Equals(LocalizationDatabase.currentEditorLanguage.ToString())) - { - SystemLanguage lang = (SystemLanguage)Enum.Parse(typeof(SystemLanguage), m_SelectedLanguage); - EditorGUIUtility.NotifyLanguageChanged(lang); - InternalEditorUtility.RequestScriptReload(); - } - - ApplyChangesToPrefs(); - } - - - private void WriteRecentAppsList(string[] paths, string path, string prefsKey) - { - int appIndex = 0; - // first write the selected app (if it's not a built-in one) - if (path.Length != 0) - { - EditorPrefs.SetString(prefsKey + appIndex, path); - ++appIndex; - } - // write the other apps - for (int i = 0; i < paths.Length; ++i) - { - if (appIndex >= kRecentAppsCount) - break; // stop when we wrote up to the limit - if (paths[i].Length == 0) - continue; // do not write built-in app into recently used list - if (paths[i] == path) - continue; // this is a selected app, do not write it twice - EditorPrefs.SetString(prefsKey + appIndex, paths[i]); - ++appIndex; - } - } - - private void WritePreferences() - { - ScriptEditorUtility.SetExternalScriptEditor(m_ScriptEditorPath); - ScriptEditorUtility.SetExternalScriptEditorArgs(m_ScriptEditorArgs); - EditorPrefs.SetBool("kExternalEditorSupportsUnityProj", m_ExternalEditorSupportsUnityProj); - - EditorPrefs.SetString("kImagesDefaultApp", m_ImageAppPath); - EditorPrefs.SetString("kDiffsDefaultApp", m_DiffTools.Length == 0 ? "" : m_DiffTools[m_DiffToolIndex]); - - WriteRecentAppsList(m_ScriptApps, m_ScriptEditorPath, kRecentScriptAppsKey); - WriteRecentAppsList(m_ImageApps, m_ImageAppPath, kRecentImageAppsKey); - - EditorPrefs.SetBool("kAutoRefresh", m_AutoRefresh); - - if (Unsupported.IsDeveloperMode() || UnityConnect.preferencesEnabled) - UnityConnectPrefs.StorePanelPrefs(); - - EditorPrefs.SetBool("ReopenLastUsedProjectOnStartup", m_ReopenLastUsedProjectOnStartup); - EditorPrefs.SetBool("UseOSColorPicker", m_UseOSColorPicker); - EditorPrefs.SetBool("EnableEditorAnalytics", m_EnableEditorAnalytics); - EditorPrefs.SetBool("ShowAssetStoreSearchHits", m_ShowAssetStoreSearchHits); - EditorPrefs.SetBool("VerifySavingAssets", m_VerifySavingAssets); - - // The Preferences window always writes all preferences, we don't want this behavior since we - // want the default value to just match "IsSourceBuild" until the developer has explicitly changed it. - if (m_DeveloperModeDirty) - { - EditorPrefs.SetBool("DeveloperMode", m_DeveloperMode); - - // Repaint all views to show/hide debug repaint indicator - InternalEditorUtility.RepaintAllViews(); - } - - EditorPrefs.SetBool("AllowAttachedDebuggingOfEditor", m_AllowAttachedDebuggingOfEditor); - - EditorPrefs.SetBool("Editor.kEnableEditorLocalization", m_EnableEditorLocalization); - EditorPrefs.SetString("Editor.kEditorLocale", m_SelectedLanguage.ToString()); - - EditorPrefs.SetBool("AllowAlphaNumericHierarchy", m_AllowAlphaNumericHierarchy); - EditorPrefs.SetString("GpuDevice", m_GpuDevice); - - EditorPrefs.SetBool("GICacheEnableCustomPath", m_GICacheSettings.m_EnableCustomPath); - EditorPrefs.SetInt("GICacheMaximumSizeGB", m_GICacheSettings.m_MaximumSize); - EditorPrefs.SetString("GICacheFolder", m_GICacheSettings.m_CachePath); - EditorPrefs.SetInt("GICacheCompressionLevel", m_GICacheSettings.m_CompressionLevel); - - EditorPrefs.SetInt("SpritePackerCacheMaximumSizeGB", m_SpriteAtlasCacheSize); - - foreach (IPreferenceWindowExtension extension in prefWinExtensions) - { - extension.WritePreferences(); - } - UnityEditor.Lightmapping.UpdateCachePath(); - } - - static private void SetupDefaultPreferences() - { - } - - static private string GetProgramFilesFolder() - { - string result = Environment.GetEnvironmentVariable("ProgramFiles(x86)"); - if (result != null) return result; - return Environment.GetEnvironmentVariable("ProgramFiles"); - } - - private void ReadPreferences() - { - m_ScriptEditorPath.str = ScriptEditorUtility.GetExternalScriptEditor(); - m_ScriptEditorArgs = ScriptEditorUtility.GetExternalScriptEditorArgs(); - - m_ExternalEditorSupportsUnityProj = EditorPrefs.GetBool("kExternalEditorSupportsUnityProj", false); - m_ImageAppPath.str = EditorPrefs.GetString("kImagesDefaultApp"); - - m_ScriptApps = BuildAppPathList(m_ScriptEditorPath, kRecentScriptAppsKey, "internal"); - m_ScriptAppsEditions = new string[m_ScriptApps.Length]; - - if (Application.platform == RuntimePlatform.WindowsEditor) - { - foreach (var vsPaths in SyncVS.InstalledVisualStudios.Values) - foreach (var vsPath in vsPaths) - { - int index = Array.IndexOf(m_ScriptApps, vsPath.Path); - if (index == -1) - { - ArrayUtility.Add(ref m_ScriptApps, vsPath.Path); - ArrayUtility.Add(ref m_ScriptAppsEditions, vsPath.Edition); - } - else - { - m_ScriptAppsEditions[index] = vsPath.Edition; - } - } - } - - var foundScriptEditorPaths = ScriptEditorUtility.GetFoundScriptEditorPaths(Application.platform); - - foreach (var scriptEditorPath in foundScriptEditorPaths) - { - ArrayUtility.Add(ref m_ScriptApps, scriptEditorPath); - ArrayUtility.Add(ref m_ScriptAppsEditions, null); - } - - m_ImageApps = BuildAppPathList(m_ImageAppPath, kRecentImageAppsKey, ""); - - m_ScriptAppDisplayNames = BuildFriendlyAppNameList(m_ScriptApps, m_ScriptAppsEditions, - "Open by file extension"); - - m_ImageAppDisplayNames = BuildFriendlyAppNameList(m_ImageApps, null, - L10n.Tr("Open by file extension")); - - m_DiffTools = InternalEditorUtility.GetAvailableDiffTools(); - - // only show warning if has team license - if ((m_DiffTools == null || m_DiffTools.Length == 0) && InternalEditorUtility.HasTeamLicense()) - { - m_noDiffToolsMessage = InternalEditorUtility.GetNoDiffToolsDetectedMessage(); - } - - string diffTool = EditorPrefs.GetString("kDiffsDefaultApp"); - m_DiffToolIndex = ArrayUtility.IndexOf(m_DiffTools, diffTool); - if (m_DiffToolIndex == -1) - m_DiffToolIndex = 0; - - m_AutoRefresh = EditorPrefs.GetBool("kAutoRefresh"); - - m_ReopenLastUsedProjectOnStartup = EditorPrefs.GetBool("ReopenLastUsedProjectOnStartup"); - - m_UseOSColorPicker = EditorPrefs.GetBool("UseOSColorPicker"); - m_EnableEditorAnalytics = EditorPrefs.GetBool("EnableEditorAnalytics", true); - m_ShowAssetStoreSearchHits = EditorPrefs.GetBool("ShowAssetStoreSearchHits", true); - m_VerifySavingAssets = EditorPrefs.GetBool("VerifySavingAssets", false); - m_DeveloperMode = Unsupported.IsDeveloperMode(); - - m_GICacheSettings.m_EnableCustomPath = EditorPrefs.GetBool("GICacheEnableCustomPath"); - m_GICacheSettings.m_CachePath = EditorPrefs.GetString("GICacheFolder"); - m_GICacheSettings.m_MaximumSize = EditorPrefs.GetInt("GICacheMaximumSizeGB", 10); - m_GICacheSettings.m_CompressionLevel = EditorPrefs.GetInt("GICacheCompressionLevel"); - - m_SpriteAtlasCacheSize = EditorPrefs.GetInt("SpritePackerCacheMaximumSizeGB"); - - m_AllowAttachedDebuggingOfEditor = EditorPrefs.GetBool("AllowAttachedDebuggingOfEditor", true); - m_EnableEditorLocalization = EditorPrefs.GetBool("Editor.kEnableEditorLocalization", true); - m_SelectedLanguage = EditorPrefs.GetString("Editor.kEditorLocale", LocalizationDatabase.GetDefaultEditorLanguage().ToString()); - m_AllowAlphaNumericHierarchy = EditorPrefs.GetBool("AllowAlphaNumericHierarchy", false); - - m_CompressAssetsOnImport = Unsupported.GetApplicationSettingCompressAssetsOnImport(); - m_GpuDevice = EditorPrefs.GetString("GpuDevice"); - - foreach (IPreferenceWindowExtension extension in prefWinExtensions) - { - extension.ReadPreferences(); - } - } - - private string StripMicrosoftFromVisualStudioName(string arg) - { - if (!arg.Contains("Visual Studio")) - return arg; - if (!arg.StartsWith("Microsoft")) - return arg; - return arg.Substring("Microsoft ".Length); - } - - class AppsListUserData - { - public AppsListUserData(string[] paths, RefString str, Action onChanged) - { - this.paths = paths; - this.str = str; - this.onChanged = onChanged; - } - - public string[] paths; - public RefString str; - public Action onChanged; - } - - void AppsListClick(object userData, string[] options, int selected) - { - AppsListUserData ud = (AppsListUserData)userData; - if (options[selected] == "Browse...") - { - string path = EditorUtility.OpenFilePanel("Browse for application", "", InternalEditorUtility.GetApplicationExtensionForRuntimePlatform(Application.platform)); - if (path.Length != 0) - { - // browsed to new application - ud.str.str = path; - if (ud.onChanged != null) - ud.onChanged(); - } - } - else - { - // value comes from the list - ud.str.str = ud.paths[selected]; - if (ud.onChanged != null) - ud.onChanged(); - } - - WritePreferences(); - ReadPreferences(); - } - - private void FilePopup(GUIContent label, string selectedString, ref string[] names, ref string[] paths, RefString outString, string defaultString, Action onChanged) - { - GUIStyle style = EditorStyles.popup; - GUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel(label, style); - - int[] selected = new int[0]; - if (paths.Contains(selectedString)) - selected = new[] { Array.IndexOf(paths, selectedString) }; - GUIContent text = new GUIContent(selected.Length == 0 ? defaultString : names[selected[0]]); - Rect r = GUILayoutUtility.GetRect(GUIContent.none, style); - AppsListUserData ud = new AppsListUserData(paths, outString, onChanged); - if (EditorGUI.DropdownButton(r, text, FocusType.Passive, style)) - { - ArrayUtility.Add(ref names, Styles.browse.text); - EditorUtility.DisplayCustomMenu(r, names, selected, AppsListClick, ud, false); - } - GUILayout.EndHorizontal(); - } - - private string[] BuildAppPathList(string userAppPath, string recentAppsKey, string stringForInternalEditor) - { - // built-in (internal) is always the first - string[] apps = new string[1]; - apps[0] = stringForInternalEditor; - - // current user setting - if (userAppPath != null && userAppPath.Length != 0 && Array.IndexOf(apps, userAppPath) == -1) - ArrayUtility.Add(ref apps, userAppPath); - - // add any recently used apps - for (int i = 0; i < kRecentAppsCount; ++i) - { - string path = EditorPrefs.GetString(recentAppsKey + i); - if (!File.Exists(path)) - { - path = ""; - EditorPrefs.SetString(recentAppsKey + i, path); - } - - if (path.Length != 0 && Array.IndexOf(apps, path) == -1) - ArrayUtility.Add(ref apps, path); - } - - return apps; - } - - private string[] BuildFriendlyAppNameList(string[] appPathList, string[] appEditionList, string defaultBuiltIn) - { - var list = new List(); - for (int i = 0; i < appPathList.Length; ++i) - { - var appPath = appPathList[i]; - - if (appPath == "internal" || appPath == "") // use built-in - list.Add(defaultBuiltIn); - else - { - var friendlyName = StripMicrosoftFromVisualStudioName(OSUtil.GetAppFriendlyName(appPath)); - - if (appEditionList != null && !string.IsNullOrEmpty(appEditionList[i])) - friendlyName = string.Format("{0} ({1})", friendlyName, appEditionList[i]); - - list.Add(friendlyName); - } - } - - return list.ToArray(); - } - } -} diff --git a/Editor/Mono/PresetLibraries/ColorPresetLibrary.cs b/Editor/Mono/PresetLibraries/ColorPresetLibrary.cs deleted file mode 100644 index c4c19d56c2..0000000000 --- a/Editor/Mono/PresetLibraries/ColorPresetLibrary.cs +++ /dev/null @@ -1,241 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - [AssetFileNameExtension("colors")] - class ColorPresetLibrary : PresetLibrary - { - [SerializeField] - List m_Presets = new List(); - Texture2D m_ColorSwatch; - Texture2D m_ColorSwatchTriangular; - Texture2D m_MiniColorSwatchTriangular; - Texture2D m_CheckerBoard; - public const int kSwatchSize = 14; - public const int kMiniSwatchSize = 8; - - void OnDestroy() - { - if (m_ColorSwatch != null) - DestroyImmediate(m_ColorSwatch); - - if (m_ColorSwatchTriangular != null) - DestroyImmediate(m_ColorSwatchTriangular); - - if (m_MiniColorSwatchTriangular != null) - DestroyImmediate(m_MiniColorSwatchTriangular); - - if (m_CheckerBoard != null) - DestroyImmediate(m_CheckerBoard); - } - - public override int Count() - { - return m_Presets.Count; - } - - public override object GetPreset(int index) - { - return m_Presets[index].color; - } - - public override void Add(object presetObject, string presetName) - { - Color color = (Color)presetObject; - m_Presets.Add(new ColorPreset(color, presetName)); - } - - public override void Replace(int index, object newPresetObject) - { - Color color = (Color)newPresetObject; - m_Presets[index].color = color; - } - - public override void Remove(int index) - { - m_Presets.RemoveAt(index); - } - - public override void Move(int index, int destIndex, bool insertAfterDestIndex) - { - PresetLibraryHelpers.MoveListItem(m_Presets, index, destIndex, insertAfterDestIndex); - } - - public override void Draw(Rect rect, int index) - { - DrawInternal(rect, m_Presets[index].color); - } - - public override void Draw(Rect rect, object presetObject) - { - DrawInternal(rect, (Color)presetObject); - } - - private void Init() - { - if (m_ColorSwatch == null) - m_ColorSwatch = CreateColorSwatchWithBorder(kSwatchSize, kSwatchSize, false); - - if (m_ColorSwatchTriangular == null) - m_ColorSwatchTriangular = CreateColorSwatchWithBorder(kSwatchSize, kSwatchSize, true); - - if (m_MiniColorSwatchTriangular == null) - m_MiniColorSwatchTriangular = CreateColorSwatchWithBorder(kMiniSwatchSize, kMiniSwatchSize, true); - - if (m_CheckerBoard == null) - m_CheckerBoard = GradientEditor.CreateCheckerTexture(2, 2, 3, new Color(0.8f, 0.8f, 0.8f), new Color(0.5f, 0.5f, 0.5f)); - } - - private void DrawInternal(Rect rect, Color preset) - { - Init(); - - bool isHDR = preset.maxColorComponent > 1f; - - // Normalize color if HDR to give some color hint (otherwise it likely is just white) - if (isHDR) - preset = preset.RGBMultiplied(1f / preset.maxColorComponent); - - Color orgColor = GUI.color; - if ((int)rect.height == kSwatchSize) - { - if (preset.a > 0.97f) - RenderSolidSwatch(rect, preset); - else - RenderSwatchWithAlpha(rect, preset, m_ColorSwatchTriangular); - - if (isHDR) - GUI.Label(rect, "h"); - } - else - { - // The Add preset button swatch - RenderSwatchWithAlpha(rect, preset, m_MiniColorSwatchTriangular); - } - GUI.color = orgColor; - } - - private void RenderSolidSwatch(Rect rect, Color preset) - { - GUI.color = preset; - GUI.DrawTexture(rect, m_ColorSwatch); - } - - private void RenderSwatchWithAlpha(Rect rect, Color preset, Texture2D swatchTexture) - { - Rect r2 = new Rect(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2); - - // Background checkers - GUI.color = Color.white; - Rect texCoordsRect = new Rect(0, 0, r2.width / m_CheckerBoard.width, r2.height / m_CheckerBoard.height); - GUI.DrawTextureWithTexCoords(r2, m_CheckerBoard, texCoordsRect, false); - - // Alpha color - GUI.color = preset; - GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture); - - // Solid color in half triangle - GUI.color = new Color(preset.r, preset.g, preset.b, 1f); - GUI.DrawTexture(rect, swatchTexture); - } - - public override string GetName(int index) - { - return m_Presets[index].name; - } - - public override void SetName(int index, string presetName) - { - m_Presets[index].name = presetName; - } - - public void CreateDebugColors() - { - for (int i = 0; i < 2000; ++i) - 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)); - } - - private static Texture2D CreateColorSwatchWithBorder(int width, int height, bool triangular) - { - Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false); - texture.hideFlags = HideFlags.HideAndDontSave; - Color[] pixels = new Color[width * height]; - Color transparent = new Color(1, 1, 1, 0f); - if (triangular) - { - for (int i = 0; i < height; i++) - for (int j = 0; j < width; j++) - { - if (i < width - j) - pixels[j + i * width] = Color.white; - else - pixels[j + i * width] = transparent; - } - } - else - { - for (int i = 0; i < height * width; i++) - pixels[i] = Color.white; - } - - // first row - for (int i = 0; i < width; i++) - pixels[i] = Color.black; - - // last row - for (int i = 0; i < width; i++) - pixels[(height - 1) * width + i] = Color.black; - - // first col - for (int i = 0; i < height; i++) - pixels[i * width] = Color.black; - - // last col - for (int i = 0; i < height; i++) - pixels[i * width + width - 1] = Color.black; - - texture.SetPixels(pixels); - texture.Apply(); - return texture; - } - - [System.Serializable] - class ColorPreset - { - [SerializeField] - string m_Name; - - [SerializeField] - Color m_Color; - - public ColorPreset(Color preset, string presetName) - { - color = preset; - name = presetName; - } - - public ColorPreset(Color preset, Color preset2, string presetName) - { - color = preset; - name = presetName; - } - - public Color color - { - get { return m_Color; } - set { m_Color = value; } - } - - public string name - { - get { return m_Name; } - set { m_Name = value; } - } - } - } -} diff --git a/Editor/Mono/PresetLibraries/CurvePresetLibrary.cs b/Editor/Mono/PresetLibraries/CurvePresetLibrary.cs deleted file mode 100644 index 3d7d64dd57..0000000000 --- a/Editor/Mono/PresetLibraries/CurvePresetLibrary.cs +++ /dev/null @@ -1,128 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - [AssetFileNameExtension("curves", "curvesNormalized", "particleCurves", "particleCurvesSigned", "particleDoubleCurves", "particleDoubleCurvesSigned")] - class CurvePresetLibrary : PresetLibrary - { - [SerializeField] - List m_Presets = new List(); - - public override int Count() - { - return m_Presets.Count; - } - - public override object GetPreset(int index) - { - return m_Presets[index].curve; - } - - public override void Add(object presetObject, string presetName) - { - AnimationCurve curve = presetObject as AnimationCurve; - if (curve == null) - { - Debug.LogError("Wrong type used in CurvePresetLibrary"); - return; - } - - AnimationCurve copy = new AnimationCurve(curve.keys); - copy.preWrapMode = curve.preWrapMode; - copy.postWrapMode = curve.postWrapMode; - m_Presets.Add(new CurvePreset(copy, presetName)); - } - - public override void Replace(int index, object newPresetObject) - { - AnimationCurve curve = newPresetObject as AnimationCurve; - if (curve == null) - { - Debug.LogError("Wrong type used in CurvePresetLibrary"); - return; - } - AnimationCurve copy = new AnimationCurve(curve.keys); - copy.preWrapMode = curve.preWrapMode; - copy.postWrapMode = curve.postWrapMode; - - m_Presets[index].curve = copy; - } - - public override void Remove(int index) - { - m_Presets.RemoveAt(index); - } - - public override void Move(int index, int destIndex, bool insertAfterDestIndex) - { - PresetLibraryHelpers.MoveListItem(m_Presets, index, destIndex, insertAfterDestIndex); - } - - public override void Draw(Rect rect, int index) - { - DrawInternal(rect, m_Presets[index].curve); - } - - public override void Draw(Rect rect, object presetObject) - { - DrawInternal(rect, presetObject as AnimationCurve); - } - - private void DrawInternal(Rect rect, AnimationCurve animCurve) - { - if (animCurve == null) - return; - EditorGUIUtility.DrawCurveSwatch(rect, animCurve, null, new Color(0.8f, 0.8f, 0.8f, 1.0f), EditorGUI.kCurveBGColor); - } - - public override string GetName(int index) - { - return m_Presets[index].name; - } - - public override void SetName(int index, string presetName) - { - m_Presets[index].name = presetName; - } - - [System.Serializable] - class CurvePreset - { - [SerializeField] - string m_Name; - - [SerializeField] - AnimationCurve m_Curve; - - public CurvePreset(AnimationCurve preset, string presetName) - { - curve = preset; - name = presetName; - } - - public CurvePreset(AnimationCurve preset, AnimationCurve preset2, string presetName) - { - curve = preset; - name = presetName; - } - - public AnimationCurve curve - { - get { return m_Curve; } - set { m_Curve = value; } - } - - public string name - { - get { return m_Name; } - set { m_Name = value; } - } - } - } -} diff --git a/Editor/Mono/PresetLibraries/CurvePresetsContentsForPopupWindow.cs b/Editor/Mono/PresetLibraries/CurvePresetsContentsForPopupWindow.cs deleted file mode 100644 index 3ee2cdba01..0000000000 --- a/Editor/Mono/PresetLibraries/CurvePresetsContentsForPopupWindow.cs +++ /dev/null @@ -1,147 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - internal enum CurveLibraryType - { - Unbounded, - NormalizedZeroToOne - } - - - internal class CurvePresetsContentsForPopupWindow : PopupWindowContent - { - PresetLibraryEditor m_CurveLibraryEditor; - PresetLibraryEditorState m_CurveLibraryEditorState; - AnimationCurve m_Curve; - CurveLibraryType m_CurveLibraryType; - bool m_WantsToClose = false; - System.Action m_PresetSelectedCallback; - - public AnimationCurve curveToSaveAsPreset {get {return m_Curve; } set {m_Curve = value; }} - - public CurvePresetsContentsForPopupWindow(AnimationCurve animCurve, CurveLibraryType curveLibraryType, System.Action presetSelectedCallback) - { - m_CurveLibraryType = curveLibraryType; - m_Curve = animCurve; - m_PresetSelectedCallback = presetSelectedCallback; - } - - public static string GetBasePrefText(CurveLibraryType curveLibraryType) - { - return GetExtension(curveLibraryType); - } - - public string currentPresetLibrary - { - get - { - InitIfNeeded(); - return m_CurveLibraryEditor.currentLibraryWithoutExtension; - } - set - { - InitIfNeeded(); - m_CurveLibraryEditor.currentLibraryWithoutExtension = value; - } - } - - static string GetExtension(CurveLibraryType curveLibraryType) - { - switch (curveLibraryType) - { - case CurveLibraryType.NormalizedZeroToOne: return PresetLibraryLocations.GetCurveLibraryExtension(true); - case CurveLibraryType.Unbounded: return PresetLibraryLocations.GetCurveLibraryExtension(false); - default: - Debug.LogError("Enum not handled!"); - return "curves"; - } - } - - public override void OnClose() - { - m_CurveLibraryEditorState.TransferEditorPrefsState(false); - } - - public PresetLibraryEditor GetPresetLibraryEditor() - { - return m_CurveLibraryEditor; - } - - public void InitIfNeeded() - { - if (m_CurveLibraryEditorState == null) - { - m_CurveLibraryEditorState = new PresetLibraryEditorState(GetBasePrefText(m_CurveLibraryType)); - m_CurveLibraryEditorState.TransferEditorPrefsState(true); - } - - if (m_CurveLibraryEditor == null) - { - var saveLoadHelper = new ScriptableObjectSaveLoadHelper(GetExtension(m_CurveLibraryType), SaveType.Text); - m_CurveLibraryEditor = new PresetLibraryEditor(saveLoadHelper, m_CurveLibraryEditorState, ItemClickedCallback); - m_CurveLibraryEditor.addDefaultPresets += AddDefaultPresetsToLibrary; - m_CurveLibraryEditor.presetsWasReordered += OnPresetsWasReordered; - m_CurveLibraryEditor.previewAspect = 4f; - m_CurveLibraryEditor.minMaxPreviewHeight = new Vector2(24f, 24f); - m_CurveLibraryEditor.showHeader = true; - } - } - - void OnPresetsWasReordered() - { - InternalEditorUtility.RepaintAllViews(); - } - - public override void OnGUI(Rect rect) - { - InitIfNeeded(); - - m_CurveLibraryEditor.OnGUI(rect, m_Curve); - - if (m_WantsToClose) - editorWindow.Close(); - } - - void ItemClickedCallback(int clickCount, object presetObject) - { - AnimationCurve curve = presetObject as AnimationCurve; - if (curve == null) - Debug.LogError("Incorrect object passed " + presetObject); - - m_PresetSelectedCallback(curve); - } - - public override Vector2 GetWindowSize() - { - return new Vector2(240, 330); - } - - void AddDefaultPresetsToLibrary(PresetLibrary presetLibrary) - { - CurvePresetLibrary curveDefaultLib = presetLibrary as CurvePresetLibrary; - if (curveDefaultLib == null) - { - Debug.Log("Incorrect preset library, should be a CurvePresetLibrary but was a " + presetLibrary.GetType()); - return; - } - - List defaults = new List(); - defaults.Add(new AnimationCurve(CurveEditorWindow.GetConstantKeys(1f))); - defaults.Add(new AnimationCurve(CurveEditorWindow.GetLinearKeys())); - defaults.Add(new AnimationCurve(CurveEditorWindow.GetEaseInKeys())); - defaults.Add(new AnimationCurve(CurveEditorWindow.GetEaseOutKeys())); - defaults.Add(new AnimationCurve(CurveEditorWindow.GetEaseInOutKeys())); - - foreach (AnimationCurve preset in defaults) - curveDefaultLib.Add(preset, ""); - } - } -} diff --git a/Editor/Mono/PresetLibraries/DoubleCurvePresetLibrary.cs b/Editor/Mono/PresetLibraries/DoubleCurvePresetLibrary.cs deleted file mode 100644 index c91fb38be7..0000000000 --- a/Editor/Mono/PresetLibraries/DoubleCurvePresetLibrary.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - [System.Serializable] - class DoubleCurve - { - [SerializeField] - AnimationCurve m_MinCurve; - - [SerializeField] - AnimationCurve m_MaxCurve; - - [SerializeField] - bool m_SignedRange; - - - public DoubleCurve(AnimationCurve minCurve, AnimationCurve maxCurve, bool signedRange) - { - // Ensure not to hold references to other curves - AnimationCurve copy; - if (minCurve != null) - { - copy = new AnimationCurve(minCurve.keys); - m_MinCurve = copy; - } - - if (maxCurve != null) - { - copy = new AnimationCurve(maxCurve.keys); - m_MaxCurve = copy; - } - else - { - Debug.LogError("Ensure that maxCurve is not null when creating a double curve. The minCurve can be null for single curves"); - } - - m_SignedRange = signedRange; - } - - public AnimationCurve minCurve - { - get { return m_MinCurve; } - set { m_MinCurve = value; } - } - - public AnimationCurve maxCurve - { - get { return m_MaxCurve; } - set { m_MaxCurve = value; } - } - - public bool signedRange - { - get { return m_SignedRange; } - set { m_SignedRange = value; } - } - - public bool IsSingleCurve() - { - return minCurve == null || minCurve.length == 0; - } - } - - class DoubleCurvePresetLibrary : PresetLibrary - { - [SerializeField] - List m_Presets = new List(); - - readonly Rect kUnsignedRange = new Rect(0, 0, 1, 1); // Vertical range 0...1 - readonly Rect kSignedRange = new Rect(0, -1, 1, 2); // Vertical range -1...1 - - public override int Count() - { - return m_Presets.Count; - } - - public override object GetPreset(int index) - { - return m_Presets[index].doubleCurve; - } - - public override void Add(object presetObject, string presetName) - { - DoubleCurve doubleCurve = presetObject as DoubleCurve; - if (doubleCurve == null) - { - Debug.LogError("Wrong type used in DoubleCurvePresetLibrary: Should be a DoubleCurve"); - return; - } - m_Presets.Add(new DoubleCurvePreset(doubleCurve, presetName)); - } - - public override void Replace(int index, object newPresetObject) - { - DoubleCurve doubleCurve = newPresetObject as DoubleCurve; - if (doubleCurve == null) - { - Debug.LogError("Wrong type used in DoubleCurvePresetLibrary"); - return; - } - m_Presets[index].doubleCurve = doubleCurve; - } - - public override void Remove(int index) - { - m_Presets.RemoveAt(index); - } - - public override void Move(int index, int destIndex, bool insertAfterDestIndex) - { - PresetLibraryHelpers.MoveListItem(m_Presets, index, destIndex, insertAfterDestIndex); - } - - public override void Draw(Rect rect, int index) - { - DrawInternal(rect, m_Presets[index].doubleCurve); - } - - public override void Draw(Rect rect, object presetObject) - { - DrawInternal(rect, presetObject as DoubleCurve); - } - - private void DrawInternal(Rect rect, DoubleCurve doubleCurve) - { - if (doubleCurve == null) - { - Debug.Log("DoubleCurve is null"); - return; - } - EditorGUIUtility.DrawRegionSwatch(rect, doubleCurve.maxCurve, doubleCurve.minCurve, new Color(0.8f, 0.8f, 0.8f, 1.0f), EditorGUI.kCurveBGColor, doubleCurve.signedRange ? kSignedRange : kUnsignedRange); - } - - public override string GetName(int index) - { - return m_Presets[index].name; - } - - public override void SetName(int index, string presetName) - { - m_Presets[index].name = presetName; - } - - [System.Serializable] - class DoubleCurvePreset - { - [SerializeField] - string m_Name; - - [SerializeField] - DoubleCurve m_DoubleCurve; - - public DoubleCurvePreset(DoubleCurve doubleCurvePreset, string presetName) - { - doubleCurve = doubleCurvePreset; - name = presetName; - } - - public DoubleCurve doubleCurve - { - get { return m_DoubleCurve; } - set { m_DoubleCurve = value; } - } - - public string name - { - get { return m_Name; } - set { m_Name = value; } - } - } - } -} diff --git a/Editor/Mono/PresetLibraries/DoubleCurvePresetsContentsForPopupWindow.cs b/Editor/Mono/PresetLibraries/DoubleCurvePresetsContentsForPopupWindow.cs deleted file mode 100644 index 57c1b70d37..0000000000 --- a/Editor/Mono/PresetLibraries/DoubleCurvePresetsContentsForPopupWindow.cs +++ /dev/null @@ -1,163 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - class DoubleCurvePresetsContentsForPopupWindow : PopupWindowContent - { - PresetLibraryEditor m_CurveLibraryEditor; - PresetLibraryEditorState m_CurveLibraryEditorState; - DoubleCurve m_DoubleCurve; - bool m_WantsToClose = false; - - public DoubleCurve doubleCurveToSave - { - get {return m_DoubleCurve; } - set {m_DoubleCurve = value; } - } - - System.Action m_PresetSelectedCallback; - - public DoubleCurvePresetsContentsForPopupWindow(DoubleCurve doubleCurveToSave, System.Action presetSelectedCallback) - { - m_DoubleCurve = doubleCurveToSave; - m_PresetSelectedCallback = presetSelectedCallback; - } - - public override void OnClose() - { - m_CurveLibraryEditorState.TransferEditorPrefsState(false); - } - - public PresetLibraryEditor GetPresetLibraryEditor() - { - return m_CurveLibraryEditor; - } - - bool IsSingleCurve(DoubleCurve doubleCurve) - { - return doubleCurve.minCurve == null || doubleCurve.minCurve.length == 0; - } - - string GetEditorPrefBaseName() - { - return PresetLibraryLocations.GetParticleCurveLibraryExtension(m_DoubleCurve.IsSingleCurve(), m_DoubleCurve.signedRange); - } - - public void InitIfNeeded() - { - if (m_CurveLibraryEditorState == null) - { - m_CurveLibraryEditorState = new PresetLibraryEditorState(GetEditorPrefBaseName()); - m_CurveLibraryEditorState.TransferEditorPrefsState(true); - } - - if (m_CurveLibraryEditor == null) - { - var extension = PresetLibraryLocations.GetParticleCurveLibraryExtension(m_DoubleCurve.IsSingleCurve(), m_DoubleCurve.signedRange); - var saveLoadHelper = new ScriptableObjectSaveLoadHelper(extension, SaveType.Text); - m_CurveLibraryEditor = new PresetLibraryEditor(saveLoadHelper, m_CurveLibraryEditorState, ItemClickedCallback); - m_CurveLibraryEditor.addDefaultPresets += AddDefaultPresetsToLibrary; - m_CurveLibraryEditor.presetsWasReordered = PresetsWasReordered; - m_CurveLibraryEditor.previewAspect = 4f; - m_CurveLibraryEditor.minMaxPreviewHeight = new Vector2(24f, 24f); - m_CurveLibraryEditor.showHeader = true; - } - } - - void PresetsWasReordered() - { - InspectorWindow.RepaintAllInspectors(); - } - - public override void OnGUI(Rect rect) - { - InitIfNeeded(); - - m_CurveLibraryEditor.OnGUI(rect, m_DoubleCurve); - - if (m_WantsToClose) - editorWindow.Close(); - } - - void ItemClickedCallback(int clickCount, object presetObject) - { - DoubleCurve doubleCurve = presetObject as DoubleCurve; - if (doubleCurve == null) - Debug.LogError("Incorrect object passed " + presetObject); - - m_PresetSelectedCallback(doubleCurve); - } - - public override Vector2 GetWindowSize() - { - return new Vector2(240, 330); - } - - void AddDefaultPresetsToLibrary(PresetLibrary presetLibrary) - { - DoubleCurvePresetLibrary doubleCurveDefaultLib = presetLibrary as DoubleCurvePresetLibrary; - if (doubleCurveDefaultLib == null) - { - Debug.Log("Incorrect preset library, should be a DoubleCurvePresetLibrary but was a " + presetLibrary.GetType()); - return; - } - - bool signedRange = m_DoubleCurve.signedRange; - List defaults = new List(); - if (IsSingleCurve(m_DoubleCurve)) - { - defaults = GetUnsignedSingleCurveDefaults(signedRange); - } - else - { - if (signedRange) - { - defaults = GetSignedDoubleCurveDefaults(); - } - else - { - defaults = GetUnsignedDoubleCurveDefaults(); - } - } - - foreach (DoubleCurve preset in defaults) - { - doubleCurveDefaultLib.Add(preset, ""); - } - } - - static List GetUnsignedSingleCurveDefaults(bool signedRange) - { - List defaults = new List(); - defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetConstantKeys(1f)), signedRange)); - defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetLinearKeys()), signedRange)); - defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetLinearMirrorKeys()), signedRange)); - defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseInKeys()), signedRange)); - defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseInMirrorKeys()), signedRange)); - defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseOutKeys()), signedRange)); - defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseOutMirrorKeys()), signedRange)); - defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseInOutKeys()), signedRange)); - defaults.Add(new DoubleCurve(null, new AnimationCurve(CurveEditorWindow.GetEaseInOutMirrorKeys()), signedRange)); - return defaults; - } - - static List GetUnsignedDoubleCurveDefaults() - { - List defaults = new List(); - defaults.Add(new DoubleCurve(new AnimationCurve(CurveEditorWindow.GetConstantKeys(0f)), new AnimationCurve(CurveEditorWindow.GetConstantKeys(1f)), false)); - return defaults; - } - - static List GetSignedDoubleCurveDefaults() - { - List defaults = new List(); - defaults.Add(new DoubleCurve(new AnimationCurve(CurveEditorWindow.GetConstantKeys(-1f)), new AnimationCurve(CurveEditorWindow.GetConstantKeys(1f)), true)); - return defaults; - } - } -} diff --git a/Editor/Mono/PresetLibraries/GradientPresetLibrary.cs b/Editor/Mono/PresetLibraries/GradientPresetLibrary.cs deleted file mode 100644 index 4d4f0d3bae..0000000000 --- a/Editor/Mono/PresetLibraries/GradientPresetLibrary.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - [AssetFileNameExtension("gradients")] - class GradientPresetLibrary : PresetLibrary - { - [SerializeField] - List m_Presets = new List(); - - public override int Count() - { - return m_Presets.Count; - } - - public override object GetPreset(int index) - { - return m_Presets[index].gradient; - } - - public override void Add(object presetObject, string presetName) - { - Gradient gradient = presetObject as Gradient; - if (gradient == null) - { - Debug.LogError("Wrong type used in GradientPresetLibrary"); - return; - } - - Gradient copy = new Gradient(); - copy.alphaKeys = gradient.alphaKeys; - copy.colorKeys = gradient.colorKeys; - copy.mode = gradient.mode; - m_Presets.Add(new GradientPreset(copy, presetName)); - } - - public override void Replace(int index, object newPresetObject) - { - Gradient gradient = newPresetObject as Gradient; - if (gradient == null) - { - Debug.LogError("Wrong type used in GradientPresetLibrary"); - return; - } - - Gradient copy = new Gradient(); - copy.alphaKeys = gradient.alphaKeys; - copy.colorKeys = gradient.colorKeys; - copy.mode = gradient.mode; - m_Presets[index].gradient = copy; - } - - public override void Remove(int index) - { - m_Presets.RemoveAt(index); - } - - public override void Move(int index, int destIndex, bool insertAfterDestIndex) - { - PresetLibraryHelpers.MoveListItem(m_Presets, index, destIndex, insertAfterDestIndex); - } - - public override void Draw(Rect rect, int index) - { - DrawInternal(rect, m_Presets[index].gradient); - } - - public override void Draw(Rect rect, object presetObject) - { - DrawInternal(rect, presetObject as Gradient); - } - - private void DrawInternal(Rect rect, Gradient gradient) - { - if (gradient == null) - return; - GradientEditor.DrawGradientWithBackground(rect, gradient); - } - - public override string GetName(int index) - { - return m_Presets[index].name; - } - - public override void SetName(int index, string presetName) - { - m_Presets[index].name = presetName; - } - - public void DebugCreateTonsOfPresets() - { - int count = 150; // well not a ton, but.. - string autoName = "Preset_"; - for (int i = 0; i < count; ++i) - { - List cols = new List(); - int numColors = (int)Random.Range(3, 8); - for (int j = 0; j < numColors; ++j) - cols.Add(new GradientColorKey(new Color(Random.value, Random.value, Random.value), Random.value)); - - List alps = new List(); - int numAlphas = (int)Random.Range(3, 8); - for (int j = 0; j < numAlphas; ++j) - alps.Add(new GradientAlphaKey(Random.value, Random.value)); - - Gradient g = new Gradient(); - g.colorKeys = cols.ToArray(); - g.alphaKeys = alps.ToArray(); - Add(g, autoName + (i + 1)); - } - } - - [System.Serializable] - class GradientPreset - { - [SerializeField] - string m_Name; - - [SerializeField] - Gradient m_Gradient; - - public GradientPreset(Gradient preset, string presetName) - { - gradient = preset; - name = presetName; - } - - public Gradient gradient - { - get { return m_Gradient; } - set { m_Gradient = value; } - } - - public string name - { - get { return m_Name; } - set { m_Name = value; } - } - } - } -} diff --git a/Editor/Mono/PresetLibraries/PopupWindowContentForNewLibrary.cs b/Editor/Mono/PresetLibraries/PopupWindowContentForNewLibrary.cs deleted file mode 100644 index 092c4948c8..0000000000 --- a/Editor/Mono/PresetLibraries/PopupWindowContentForNewLibrary.cs +++ /dev/null @@ -1,133 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor -{ - class PopupWindowContentForNewLibrary : PopupWindowContent - { - string m_NewLibraryName = ""; - int m_SelectedIndexInPopup = 0; - string m_ErrorString = null; - Rect m_WantedSize; - - Func m_CreateLibraryCallback; - - class Texts - { - public GUIContent header = EditorGUIUtility.TrTextContent("Create New Library"); - public GUIContent name = EditorGUIUtility.TrTextContent("Name"); - public GUIContent location = EditorGUIUtility.TrTextContent("Location"); - public GUIContent[] fileLocations = new[] {EditorGUIUtility.TrTextContent("Preferences Folder"), EditorGUIUtility.TrTextContent("Project Folder")}; - public PresetFileLocation[] fileLocationOrder = new[] { PresetFileLocation.PreferencesFolder, PresetFileLocation.ProjectFolder }; // must match order of fileLocations above - } - static Texts s_Texts; - - public PopupWindowContentForNewLibrary(Func createLibraryCallback) - { - m_CreateLibraryCallback = createLibraryCallback; - } - - public override void OnGUI(Rect rect) - { - if (s_Texts == null) - s_Texts = new Texts(); - - KeyboardHandling(editorWindow); - - float labelWidth = 80f; - - Rect size = EditorGUILayout.BeginVertical(); - if (Event.current.type != EventType.Layout) - m_WantedSize = size; - - // Header - GUILayout.BeginHorizontal(); - { - GUILayout.Label(s_Texts.header, EditorStyles.boldLabel); - } GUILayout.EndHorizontal(); - - EditorGUI.BeginChangeCheck(); - { - // Name - GUILayout.BeginHorizontal(); - { - GUILayout.Label(s_Texts.name, GUILayout.Width(labelWidth)); - - EditorGUI.FocusTextInControl("NewLibraryName"); - GUI.SetNextControlName("NewLibraryName"); - m_NewLibraryName = GUILayout.TextField(m_NewLibraryName); - } GUILayout.EndHorizontal(); - - // Location - GUILayout.BeginHorizontal(); - { - GUILayout.Label(s_Texts.location, GUILayout.Width(labelWidth)); - m_SelectedIndexInPopup = EditorGUILayout.Popup(m_SelectedIndexInPopup, s_Texts.fileLocations); - } - GUILayout.EndHorizontal(); - } - if (EditorGUI.EndChangeCheck()) - m_ErrorString = null; - - // Create - GUILayout.BeginHorizontal(); - { - if (!string.IsNullOrEmpty(m_ErrorString)) - { - Color orgColor = GUI.color; - GUI.color = new Color(1, 0.8f, 0.8f); - GUILayout.Label(GUIContent.Temp(m_ErrorString), EditorStyles.helpBox); - GUI.color = orgColor; - } - - GUILayout.FlexibleSpace(); - if (GUILayout.Button(GUIContent.Temp("Create"))) - { - CreateLibraryAndCloseWindow(editorWindow); - } - } GUILayout.EndHorizontal(); - - GUILayout.Space(15); - - EditorGUILayout.EndVertical(); - } - - public override Vector2 GetWindowSize() - { - return new Vector2(350, m_WantedSize.height > 0 ? m_WantedSize.height : 90); - } - - void KeyboardHandling(EditorWindow editorWindow) - { - Event evt = Event.current; - switch (evt.type) - { - case EventType.KeyDown: - switch (evt.keyCode) - { - case KeyCode.KeypadEnter: - case KeyCode.Return: - CreateLibraryAndCloseWindow(editorWindow); - break; - case KeyCode.Escape: - editorWindow.Close(); - break; - } - break; - } - } - - void CreateLibraryAndCloseWindow(EditorWindow editorWindow) - { - PresetFileLocation fileLocation = s_Texts.fileLocationOrder[m_SelectedIndexInPopup]; - m_ErrorString = m_CreateLibraryCallback(m_NewLibraryName, fileLocation); - if (string.IsNullOrEmpty(m_ErrorString)) - editorWindow.Close(); - } - } -} diff --git a/Editor/Mono/PresetLibraries/PresetLibrary.cs b/Editor/Mono/PresetLibraries/PresetLibrary.cs deleted file mode 100644 index ec4d8de16a..0000000000 --- a/Editor/Mono/PresetLibraries/PresetLibrary.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor -{ - // Derive and implement interface for your own preset library. See GradientPresetLibrary.cs for example. - internal abstract class PresetLibrary : ScriptableObject - { - public abstract int Count(); - public abstract object GetPreset(int index); - public abstract void Add(object presetObject, string presetName); - public abstract void Replace(int index, object newPresetObject); - public abstract void Remove(int index); - public abstract void Move(int index, int destIndex, bool insertAfterDestIndex); - public abstract void Draw(Rect rect, int index); - public abstract void Draw(Rect rect, object presetObject); - public abstract string GetName(int index); - public abstract void SetName(int index, string name); - } - - - internal static class PresetLibraryHelpers - { - public static void MoveListItem(List list, int index, int destIndex, bool insertAfterDestIndex) - { - if (index < 0 || destIndex < 0) - { - Debug.LogError("Invalid preset move"); - return; - } - - if (index == destIndex) - return; - - if (destIndex > index) - destIndex--; - if (insertAfterDestIndex && destIndex < list.Count - 1) - destIndex++; - - var item = list[index]; - list.RemoveAt(index); - list.Insert(destIndex, item); - } - } -} // UnityEditor diff --git a/Editor/Mono/PresetLibraries/PresetLibraryEditor.cs b/Editor/Mono/PresetLibraries/PresetLibraryEditor.cs deleted file mode 100644 index d00be76f29..0000000000 --- a/Editor/Mono/PresetLibraries/PresetLibraryEditor.cs +++ /dev/null @@ -1,969 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using UnityEditor.VersionControl; -using UnityEngine; -using UnityEditorInternal; -using System.Collections.Generic; - -namespace UnityEditor -{ - // Client code should allocate and ensure its being serialized (e.g as a field in an EditorWindow) - [System.Serializable] - internal class PresetLibraryEditorState - { - public enum ItemViewMode { Grid, List } - - [SerializeField] - private ItemViewMode m_ItemViewMode; - public float m_PreviewHeight = 32f; - public Vector2 m_ScrollPosition; - public string m_CurrrentLibrary = PresetLibraryLocations.defaultPresetLibraryPath; - public int m_HoverIndex = -1; - public RenameOverlay m_RenameOverlay = new RenameOverlay(); - public string m_Prefix; - - static public ItemViewMode GetItemViewMode(string prefix) - { - return (ItemViewMode)EditorPrefs.GetInt(prefix + "ViewMode", (int)ItemViewMode.Grid); - } - - public PresetLibraryEditorState(string prefix) - { - m_Prefix = prefix; - } - - public ItemViewMode itemViewMode - { - get { return m_ItemViewMode; } - set - { - if (m_ItemViewMode != value) - { - m_ItemViewMode = value; - InspectorWindow.RepaintAllInspectors(); // if inspector is showing a preset library we want it to follow the state - EditorPrefs.SetInt(m_Prefix + "ViewMode", (int)m_ItemViewMode); - } - } - } - - public void TransferEditorPrefsState(bool load) - { - if (load) - { - m_ItemViewMode = (ItemViewMode)EditorPrefs.GetInt(m_Prefix + "ViewMode", (int)m_ItemViewMode); - m_PreviewHeight = EditorPrefs.GetFloat(m_Prefix + "ItemHeight", m_PreviewHeight); - m_ScrollPosition.y = EditorPrefs.GetFloat(m_Prefix + "Scroll", m_ScrollPosition.y); - m_CurrrentLibrary = EditorPrefs.GetString(m_Prefix + "CurrentLib", m_CurrrentLibrary); - } - else // save - { - EditorPrefs.SetInt(m_Prefix + "ViewMode", (int)m_ItemViewMode); - EditorPrefs.SetFloat(m_Prefix + "ItemHeight", m_PreviewHeight); - EditorPrefs.SetFloat(m_Prefix + "Scroll", m_ScrollPosition.y); - EditorPrefs.SetString(m_Prefix + "CurrentLib", m_CurrrentLibrary); - } - } - } - - - internal partial class PresetLibraryEditor where T : PresetLibrary - { - class Styles - { - public GUIStyle innerShadowBg = GetStyle("InnerShadowBg"); - public GUIStyle optionsButton = GetStyle("PaneOptions"); - public GUIStyle newPresetStyle = new GUIStyle(EditorStyles.boldLabel); - public GUIContent plusButtonText = new GUIContent("", "Add new preset"); - public GUIContent plusButtonTextNotCheckedOut = new GUIContent("", "To add presets you need to press the 'Check out' button below"); - public GUIContent header = EditorGUIUtility.TrTextContent("Presets"); - public GUIContent newPreset = EditorGUIUtility.TrTextContent("New"); - - public Styles() - { - newPresetStyle.alignment = TextAnchor.MiddleCenter; - newPresetStyle.normal.textColor = Color.white; - } - - static GUIStyle GetStyle(string styleName) - { - return styleName; // Implicit construction of GUIStyle - - // For faster testing of GUISkin changes in editor resources load directly from skin - //GUISkin skin = EditorGUIUtility.LoadRequired ("Builtin Skins/DarkSkin/Skins/Presets.guiSkin") as GUISkin; - //return skin.GetStyle (styleName); - } - } - static Styles s_Styles; - - class DragState - { - public int dragUponIndex { get; set; } - public int draggingIndex { get; set; } - public bool insertAfterIndex { get; set; } - public Rect dragUponRect { get; set; } - public bool IsDragging() {return draggingIndex != -1; } - public DragState() {dragUponIndex = -1; draggingIndex = -1; } - } - DragState m_DragState = new DragState(); - - readonly VerticalGrid m_Grid = new VerticalGrid(); - readonly PresetLibraryEditorState m_State; - readonly ScriptableObjectSaveLoadHelper m_SaveLoadHelper; - readonly System.Action m_ItemClickedCallback; // - - public System.Action addDefaultPresets; - public System.Action presetsWasReordered; - - // layout - const float kGridLabelHeight = 16f; - const float kCheckoutButtonMaxWidth = 100f; - const float kCheckoutButtonMargin = 2f; - Vector2 m_MinMaxPreviewHeight = new Vector2(14, 64); - float m_PreviewAspect = 8f; - bool m_ShowAddNewPresetItem = true; - bool m_ShowedScrollBarLastFrame = false; - bool m_IsOpenForEdit = true; - PresetFileLocation m_PresetLibraryFileLocation; - public float contentHeight { get; private set; } - float topAreaHeight { get { return 20f; } } - float versionControlAreaHeight { get { return 20f; } } - float gridWidth { get; set; } - - public bool wantsToCreateLibrary { get; set; } - public bool showHeader { get; set; } - public float settingsMenuRightMargin { get; set; } - public bool alwaysShowScrollAreaHorizontalLines {get; set; } - public bool useOnePixelOverlappedGrid {get; set; } - public RectOffset marginsForList {get; set; } - public RectOffset marginsForGrid {get; set; } - - public PresetLibraryEditor(ScriptableObjectSaveLoadHelper helper, - PresetLibraryEditorState state, - System.Action itemClickedCallback - ) - { - m_SaveLoadHelper = helper; - m_State = state; - m_ItemClickedCallback = itemClickedCallback; - settingsMenuRightMargin = 10; - useOnePixelOverlappedGrid = false; - alwaysShowScrollAreaHorizontalLines = true; - marginsForList = new RectOffset(10, 10, 5, 5); - marginsForGrid = new RectOffset(5, 5, 5, 5); - m_PresetLibraryFileLocation = PresetLibraryLocations.GetFileLocationFromPath(currentLibraryWithoutExtension); - } - - public void InitializeGrid(float availableWidth) - { - T lib = GetCurrentLib(); - if (lib != null) - { - if (availableWidth > 0f) - SetupGrid(availableWidth, lib.Count()); - } - else - Debug.LogError("Could not load preset library " + currentLibraryWithoutExtension); - } - - void Repaint() - { - // Repaints current view - HandleUtility.Repaint(); - } - - void ValidateNoExtension(string value) - { - if (Path.HasExtension(value)) - Debug.LogError("currentLibraryWithoutExtension should not have an extension: " + value); - } - - public string currentLibraryWithoutExtension - { - get - { - return m_State.m_CurrrentLibrary; - } - set - { - m_State.m_CurrrentLibrary = Path.ChangeExtension(value, null); // ensure no extension - m_PresetLibraryFileLocation = PresetLibraryLocations.GetFileLocationFromPath(m_State.m_CurrrentLibrary); - OnLayoutChanged(); - Repaint(); - } - } - - public float previewAspect - { - get { return m_PreviewAspect; } - set { m_PreviewAspect = value; } - } - - public Vector2 minMaxPreviewHeight - { - get { return m_MinMaxPreviewHeight; } - set - { - m_MinMaxPreviewHeight = value; - previewHeight = previewHeight; // clamps to min max - } - } - - public float previewHeight - { - get { return m_State.m_PreviewHeight; } - set - { - m_State.m_PreviewHeight = Mathf.Clamp(value, minMaxPreviewHeight.x, minMaxPreviewHeight.y); - Repaint(); - } - } - - public PresetLibraryEditorState.ItemViewMode itemViewMode - { - get { return m_State.itemViewMode; } - set - { - m_State.itemViewMode = value; - OnLayoutChanged(); - Repaint(); - } - } - - bool drawLabels {get {return m_State.itemViewMode == PresetLibraryEditorState.ItemViewMode.List; }} - - // Returns an error string. If no errors occured then null is returned - string CreateNewLibraryCallback(string libraryName, PresetFileLocation fileLocation) - { - string defaultPath = PresetLibraryLocations.GetDefaultFilePathForFileLocation(fileLocation); - string pathWithoutExtension = Path.Combine(defaultPath, libraryName); - if (CreateNewLibrary(pathWithoutExtension) != null) - currentLibraryWithoutExtension = pathWithoutExtension; - return PresetLibraryManager.instance.GetLastError(); - } - - static bool IsItemVisible(float scrollHeight, float itemYMin, float itemYMax, float scrollPos) - { - float yMin = itemYMin - scrollPos; - float yMax = itemYMax - scrollPos; - if (yMax < 0f) - return false; - if (yMin > scrollHeight) - return false; - - return true; - } - - void OnLayoutChanged() - { - T lib = GetCurrentLib(); - if (lib == null || gridWidth <= 0f) - return; - - SetupGrid(gridWidth, lib.Count()); - } - - void SetupGrid(float width, int itemCount) - { - if (width < 1f) - { - Debug.LogError("Invalid width " + width + ", " + Event.current.type); - return; - } - - if (m_ShowAddNewPresetItem) - itemCount++; - - m_Grid.useFixedHorizontalSpacing = useOnePixelOverlappedGrid; - m_Grid.fixedHorizontalSpacing = useOnePixelOverlappedGrid ? -1 : 0; - - switch (m_State.itemViewMode) - { - case PresetLibraryEditorState.ItemViewMode.Grid: - - m_Grid.fixedWidth = width; - m_Grid.topMargin = marginsForGrid.top; - m_Grid.bottomMargin = marginsForGrid.bottom; - m_Grid.leftMargin = marginsForGrid.left; - m_Grid.rightMargin = marginsForGrid.right; - m_Grid.verticalSpacing = useOnePixelOverlappedGrid ? -1 : 2; - m_Grid.minHorizontalSpacing = 1f; - m_Grid.itemSize = new Vector2(m_State.m_PreviewHeight * m_PreviewAspect, m_State.m_PreviewHeight); // no text - m_Grid.InitNumRowsAndColumns(itemCount, int.MaxValue); - break; - case PresetLibraryEditorState.ItemViewMode.List: - m_Grid.fixedWidth = width; - m_Grid.topMargin = marginsForList.top; - m_Grid.bottomMargin = marginsForList.bottom; - m_Grid.leftMargin = marginsForList.left; - m_Grid.rightMargin = marginsForList.right; - m_Grid.verticalSpacing = 2f; - m_Grid.minHorizontalSpacing = 0f; - m_Grid.itemSize = new Vector2(width - m_Grid.leftMargin, m_State.m_PreviewHeight); - m_Grid.InitNumRowsAndColumns(itemCount, int.MaxValue); - break; - } - - - float gridHeight = m_Grid.CalcRect(itemCount - 1, 0f).yMax + m_Grid.bottomMargin; - contentHeight = topAreaHeight + gridHeight + (m_IsOpenForEdit ? 0 : versionControlAreaHeight); - } - - public void OnGUI(Rect rect, object presetObject) - { - // If removing this early out grid setup needs to be ignored for layout and used events - if (rect.width < 2f) - return; - - m_State.m_RenameOverlay.OnEvent(); - - T lib = GetCurrentLib(); - - if (s_Styles == null) - s_Styles = new Styles(); - - Rect topArea = new Rect(rect.x, rect.y, rect.width, topAreaHeight); - Rect presetRect = new Rect(rect.x, topArea.yMax, rect.width, rect.height - topAreaHeight); - - TopArea(topArea); - ListArea(presetRect, lib, presetObject); - } - - void TopArea(Rect rect) - { - GUI.BeginGroup(rect); - { - if (showHeader) - GUI.Label(new Rect(10, 2, rect.width - 20, rect.height), s_Styles.header); - - const float optionsButtonWidth = 16f; - const float optionsButtonHeight = 6f; - Rect buttonRect = new Rect(rect.width - optionsButtonWidth - settingsMenuRightMargin, (rect.height - optionsButtonHeight) * 0.5f, optionsButtonWidth, rect.height); - if (Event.current.type == EventType.Repaint) - s_Styles.optionsButton.Draw(buttonRect, false, false, false, false); - - // We want larger click area than the button icon - buttonRect.y = 0f; - buttonRect.height = rect.height; - buttonRect.width = 24f; - if (GUI.Button(buttonRect, GUIContent.none, GUIStyle.none)) - SettingsMenu.Show(buttonRect, this); - - if (wantsToCreateLibrary) - { - wantsToCreateLibrary = false; - PopupWindow.Show(buttonRect, new PopupWindowContentForNewLibrary(CreateNewLibraryCallback)); - EditorGUIUtility.ExitGUI(); - } - } GUI.EndGroup(); - } - - Rect GetDragRect(Rect itemRect) - { - int extraHorz = Mathf.FloorToInt(m_Grid.horizontalSpacing * 0.5f + 0.5f); - int extraVert = Mathf.FloorToInt(m_Grid.verticalSpacing * 0.5f + 0.5f); - return new RectOffset(extraHorz, extraHorz, extraVert, extraVert).Add(itemRect); - } - - void ClearDragState() - { - m_DragState.dragUponIndex = -1; - m_DragState.draggingIndex = -1; - } - - void DrawHoverEffect(Rect itemRect, bool drawAsSelection) - { - Color orgColor = GUI.color; - GUI.color = new Color(0, 0, 0.4f, drawAsSelection ? 0.8f : 0.3f); - Rect hoverRect = new RectOffset(3, 3, 3, 3).Add(itemRect); - GUI.Label(hoverRect, GUIContent.none, EditorStyles.helpBox); - GUI.color = orgColor; - } - - private string pathWithExtension - { - get { return currentLibraryWithoutExtension + "." + m_SaveLoadHelper.fileExtensionWithoutDot; } - } - - void VersionControlArea(Rect rect) - { - if (rect.width > kCheckoutButtonMaxWidth) - rect = new Rect(rect.xMax - kCheckoutButtonMaxWidth - kCheckoutButtonMargin, rect.y + kCheckoutButtonMargin, kCheckoutButtonMaxWidth, rect.height - kCheckoutButtonMargin * 2); - - if (GUI.Button(rect, "Check out", EditorStyles.miniButton)) - { - Provider.Checkout(new[] { pathWithExtension }, CheckoutMode.Asset); - } - } - - void ListArea(Rect rect, PresetLibrary lib, object newPresetObject) - { - if (lib == null) - return; - - Event evt = Event.current; - - if (m_PresetLibraryFileLocation == PresetFileLocation.ProjectFolder && evt.type == EventType.Repaint) - m_IsOpenForEdit = AssetDatabase.IsOpenForEdit(pathWithExtension, StatusQueryOptions.UseCachedIfPossible); - else if (m_PresetLibraryFileLocation == PresetFileLocation.PreferencesFolder) - m_IsOpenForEdit = true; - - if (!m_IsOpenForEdit) - { - Rect versionControlRect = new Rect(rect.x, rect.yMax - versionControlAreaHeight, rect.width, versionControlAreaHeight); - VersionControlArea(versionControlRect); - rect.height -= versionControlAreaHeight; - } - - // To ensure we setup grid to visible rect we need to run once to check if scrollbar is taking up screen estate. - // To optimize the first width is based on the last frame and we therefore most likely will only run once. - for (int i = 0; i < 2; i++) - { - gridWidth = m_ShowedScrollBarLastFrame ? rect.width - 17 : rect.width; - SetupGrid(gridWidth, lib.Count()); - bool isShowingScrollBar = m_Grid.height > rect.height; - if (isShowingScrollBar == m_ShowedScrollBarLastFrame) - break; - else - m_ShowedScrollBarLastFrame = isShowingScrollBar; - } - - // Draw horizontal lines for scrollview content to clip against - if ((m_ShowedScrollBarLastFrame || alwaysShowScrollAreaHorizontalLines) && Event.current.type == EventType.Repaint) - { - Rect scrollEdgeRect = new RectOffset(1, 1, 1, 1).Add(rect); - scrollEdgeRect.height = 1; - EditorGUI.DrawRect(scrollEdgeRect, new Color(0, 0, 0, 0.3f)); - scrollEdgeRect.y += rect.height + 1; - EditorGUI.DrawRect(scrollEdgeRect, new Color(0, 0, 0, 0.3f)); - } - - Rect contentRect = new Rect(0, 0, 1, m_Grid.height); - m_State.m_ScrollPosition = GUI.BeginScrollView(rect, m_State.m_ScrollPosition, contentRect); - { - int startIndex, endIndex; - float yOffset = 0f; - int maxIndex = m_ShowAddNewPresetItem ? lib.Count() : lib.Count() - 1; - bool isGridVisible = m_Grid.IsVisibleInScrollView(rect.height, m_State.m_ScrollPosition.y, yOffset, maxIndex, out startIndex, out endIndex); - bool drawDragInsertionMarker = false; - if (isGridVisible) - { - // Handle renaming overlay before item handling because its needs mouse input first to end renaming if clicked outside - if (GetRenameOverlay().IsRenaming() && !GetRenameOverlay().isWaitingForDelay) - { - if (!m_State.m_RenameOverlay.OnGUI()) - { - EndRename(); - evt.Use(); - } - Repaint(); - } - - for (int i = startIndex; i <= endIndex; ++i) - { - int itemControlID = i + 1000000; - - Rect itemRect = m_Grid.CalcRect(i, yOffset); - Rect previewRect = itemRect; - Rect labelRect = itemRect; - switch (m_State.itemViewMode) - { - case PresetLibraryEditorState.ItemViewMode.List: - previewRect.width = m_State.m_PreviewHeight * m_PreviewAspect; - labelRect.x += previewRect.width + 8f; - labelRect.width -= previewRect.width + 10f; - labelRect.height = kGridLabelHeight; - labelRect.y = itemRect.yMin + (itemRect.height - kGridLabelHeight) * 0.5f; - break; - - case PresetLibraryEditorState.ItemViewMode.Grid: - // only preview is shown: no label - break; - } - - // Add new preset button - if (m_ShowAddNewPresetItem && i == lib.Count()) - { - CreateNewPresetButton(previewRect, newPresetObject, lib, m_IsOpenForEdit); - continue; - } - - // Rename overlay - bool isRenamingThisItem = IsRenaming(i); - if (isRenamingThisItem) - { - Rect renameRect = labelRect; - renameRect.y -= 1f; renameRect.x -= 1f; // adjustment to fit perfectly - m_State.m_RenameOverlay.editFieldRect = renameRect; - } - - // Handle event - switch (evt.type) - { - case EventType.Repaint: - if (m_State.m_HoverIndex == i) - { - if (itemRect.Contains(evt.mousePosition)) - { - // TODO: We need a better hover effect so disabling for now... - //if (!GetRenameOverlay().IsRenaming ()) - // DrawHoverEffect (itemRect, false); - } - else - m_State.m_HoverIndex = -1; - } - - if (m_DragState.draggingIndex == i || GUIUtility.hotControl == itemControlID) - DrawHoverEffect(itemRect, false); - - lib.Draw(previewRect, i); - if (!isRenamingThisItem && drawLabels) - GUI.Label(labelRect, GUIContent.Temp(lib.GetName(i))); - - if (m_DragState.dragUponIndex == i && m_DragState.draggingIndex != m_DragState.dragUponIndex) - drawDragInsertionMarker = true; - - // We delete presets on alt-click - if (GUIUtility.hotControl == 0 && Event.current.alt && m_IsOpenForEdit) - EditorGUIUtility.AddCursorRect(itemRect, MouseCursor.ArrowMinus); - - break; - case EventType.MouseDown: - if (evt.button == 0 && itemRect.Contains(evt.mousePosition)) - { - GUIUtility.hotControl = itemControlID; - if (evt.clickCount == 1) - { - m_ItemClickedCallback(evt.clickCount, lib.GetPreset(i)); - evt.Use(); - } - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == itemControlID && m_IsOpenForEdit) - { - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), itemControlID); - if (delay.CanStartDrag()) - { - // Start drag - DragAndDrop.PrepareStartDrag(); - DragAndDrop.SetGenericData("DraggingPreset", i); - DragAndDrop.StartDrag(""); - m_DragState.draggingIndex = i; - m_DragState.dragUponIndex = i; - GUIUtility.hotControl = 0; - } - evt.Use(); - } - break; - - case EventType.DragUpdated: - case EventType.DragPerform: - { - Rect dragRect = GetDragRect(itemRect); - if (dragRect.Contains(evt.mousePosition)) - { - m_DragState.dragUponIndex = i; - m_DragState.dragUponRect = itemRect; - - if (m_State.itemViewMode == PresetLibraryEditorState.ItemViewMode.List) - m_DragState.insertAfterIndex = ((evt.mousePosition.y - dragRect.y) / dragRect.height) > 0.5f; - else - m_DragState.insertAfterIndex = ((evt.mousePosition.x - dragRect.x) / dragRect.width) > 0.5f; - - bool perform = evt.type == EventType.DragPerform; - if (perform) - { - if (m_DragState.draggingIndex >= 0) - { - MovePreset(m_DragState.draggingIndex, m_DragState.dragUponIndex, m_DragState.insertAfterIndex); - DragAndDrop.AcceptDrag(); - } - ClearDragState(); - } - DragAndDrop.visualMode = DragAndDropVisualMode.Move; - evt.Use(); - } - } - break; - case EventType.DragExited: - if (m_DragState.IsDragging()) - { - ClearDragState(); - evt.Use(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == itemControlID) - { - GUIUtility.hotControl = 0; - if (evt.button == 0 && itemRect.Contains(evt.mousePosition)) - { - if (Event.current.alt && m_IsOpenForEdit) - { - DeletePreset(i); - evt.Use(); - } - } - } - break; - case EventType.ContextClick: - if (itemRect.Contains(evt.mousePosition)) - { - PresetContextMenu.Show(m_IsOpenForEdit, i, newPresetObject, this); - evt.Use(); - } - break; - case EventType.MouseMove: - if (itemRect.Contains(evt.mousePosition)) - { - if (m_State.m_HoverIndex != i) - { - m_State.m_HoverIndex = i; - Repaint(); - } - } - else if (m_State.m_HoverIndex == i) - { - m_State.m_HoverIndex = -1; - Repaint(); - } - - break; - } - } // end foreach item - - // Draw above all items - if (drawDragInsertionMarker) - DrawDragInsertionMarker(); - } - } GUI.EndScrollView(); - } - - void DrawDragInsertionMarker() - { - if (!m_DragState.IsDragging()) - return; - - Rect dragRect = GetDragRect(m_DragState.dragUponRect); - Rect insertRect; - const float inserterThickness = 2f; - const float halfInserter = inserterThickness * 0.5f; - if (m_State.itemViewMode == PresetLibraryEditorState.ItemViewMode.List) - { - if (m_DragState.insertAfterIndex) - insertRect = new Rect(dragRect.xMin, dragRect.yMax - halfInserter, dragRect.width, inserterThickness); - else - insertRect = new Rect(dragRect.xMin, dragRect.yMin - halfInserter, dragRect.width, inserterThickness); - } - else // grid - { - if (m_DragState.insertAfterIndex) - insertRect = new Rect(dragRect.xMax - halfInserter, dragRect.yMin, inserterThickness, dragRect.height); - else - insertRect = new Rect(dragRect.xMin - halfInserter, dragRect.yMin, inserterThickness, dragRect.height); - } - EditorGUI.DrawRect(insertRect, new Color(0.3f, 0.3f, 1.0f)); - } - - void CreateNewPresetButton(Rect buttonRect, object newPresetObject, PresetLibrary lib, bool isOpenForEdit) - { - using (new EditorGUI.DisabledScope(!isOpenForEdit)) - { - if (GUI.Button(buttonRect, isOpenForEdit ? s_Styles.plusButtonText : s_Styles.plusButtonTextNotCheckedOut)) - { - int newIndex = CreateNewPreset(newPresetObject, ""); - if (drawLabels) - BeginRenaming("", newIndex, 0f); - InspectorWindow.RepaintAllInspectors(); // If inspecting a preset libarary we want to show the new preset there as well - } - - if (Event.current.type == EventType.Repaint) - { - Rect rect2 = new RectOffset(-3, -3, -3, -3).Add(buttonRect); - lib.Draw(rect2, newPresetObject); - - if (buttonRect.width > 30) - { - LabelWithOutline(buttonRect, s_Styles.newPreset, new Color(0.1f, 0.1f, 0.1f), s_Styles.newPresetStyle); - } - else - { - if (lib.Count() == 0 && isOpenForEdit) - { - buttonRect.x = buttonRect.xMax + 5f; - buttonRect.width = 200; - buttonRect.height = EditorGUI.kSingleLineHeight; - using (new EditorGUI.DisabledScope(true)) - { - GUI.Label(buttonRect, "Click to add new preset"); - } - } - } - } - } - } - - static void LabelWithOutline(Rect rect, GUIContent content, Color outlineColor, GUIStyle style) - { - const int outlineWidth = 1; - - Color orgColor = GUI.color; - GUI.color = outlineColor; - for (int i = -outlineWidth; i <= outlineWidth; ++i) - { - for (int j = -outlineWidth; j <= outlineWidth; ++j) - { - if (i == 0 && j == 0) - continue; - - Rect outlineRect = rect; - outlineRect.x += j; - outlineRect.y += i; - GUI.Label(outlineRect, content, style); - } - } - GUI.color = orgColor; - - GUI.Label(rect, content, style); - } - - bool IsRenaming(int itemID) - { - return GetRenameOverlay().IsRenaming() && GetRenameOverlay().userData == itemID && !GetRenameOverlay().isWaitingForDelay; - } - - RenameOverlay GetRenameOverlay() - { - return m_State.m_RenameOverlay; - } - - void BeginRenaming(string name, int itemIndex, float delay) - { - GetRenameOverlay().BeginRename(name, itemIndex, delay); - } - - void EndRename() - { - if (!GetRenameOverlay().userAcceptedRename) - return; - - // We are done renaming (user accepted/rejected, we lost focus etc, other grabbed renameOverlay etc.) - string name = string.IsNullOrEmpty(GetRenameOverlay().name) ? GetRenameOverlay().originalName : GetRenameOverlay().name; - int itemIndex = GetRenameOverlay().userData; // we passed in an instanceID as userData - - T lib = GetCurrentLib(); - if (itemIndex >= 0 && itemIndex < lib.Count()) - { - lib.SetName(itemIndex, name); - SaveCurrentLib(); - } - - // Ensure cleanup - GetRenameOverlay().EndRename(true); - } - - public T GetCurrentLib() - { - T lib = PresetLibraryManager.instance.GetLibrary(m_SaveLoadHelper, currentLibraryWithoutExtension); - if (lib == null) - { - // If current library not found then get the default library (or create the default library if not present) - lib = PresetLibraryManager.instance.GetLibrary(m_SaveLoadHelper, PresetLibraryLocations.defaultPresetLibraryPath); - if (lib == null) - { - lib = CreateNewLibrary(PresetLibraryLocations.defaultPresetLibraryPath); - if (lib != null) - { - // Add default set of presets - if (addDefaultPresets != null) - { - addDefaultPresets(lib); - PresetLibraryManager.instance.SaveLibrary(m_SaveLoadHelper, lib, PresetLibraryLocations.defaultPresetLibraryPath); - } - } - else - { - Debug.LogError("Could not create Default preset library " + PresetLibraryManager.instance.GetLastError()); - } - } - - currentLibraryWithoutExtension = PresetLibraryLocations.defaultPresetLibraryPath; - } - return lib; - } - - public void UnloadUsedLibraries() - { - PresetLibraryManager.instance.UnloadAllLibrariesFor(m_SaveLoadHelper); - } - - public void DeletePreset(int presetIndex) - { - T lib = GetCurrentLib(); - if (lib == null) - return; - - if (presetIndex < 0 || presetIndex >= lib.Count()) - { - Debug.LogError("DeletePreset: Invalid index: out of bounds"); - return; - } - - lib.Remove(presetIndex); - SaveCurrentLib(); - if (presetsWasReordered != null) - presetsWasReordered(); - - OnLayoutChanged(); - } - - public void ReplacePreset(int presetIndex, object presetObject) - { - T lib = GetCurrentLib(); - if (lib == null) - return; - - if (presetIndex < 0 || presetIndex >= lib.Count()) - { - Debug.LogError("ReplacePreset: Invalid index: out of bounds"); - return; - } - - lib.Replace(presetIndex, presetObject); - SaveCurrentLib(); - if (presetsWasReordered != null) - presetsWasReordered(); - } - - public void MovePreset(int presetIndex, int destPresetIndex, bool insertAfterDestIndex) - { - T lib = GetCurrentLib(); - if (lib == null) - return; - - if (presetIndex < 0 || presetIndex >= lib.Count()) - { - Debug.LogError("ReplacePreset: Invalid index: out of bounds"); - return; - } - - lib.Move(presetIndex, destPresetIndex, insertAfterDestIndex); - SaveCurrentLib(); - if (presetsWasReordered != null) - presetsWasReordered(); - } - - // returns index of newly created preset. -1 if no library to add to. - public int CreateNewPreset(object presetObject, string presetName) - { - T lib = GetCurrentLib(); - if (lib == null) - { - Debug.Log("No current library selected!"); - return -1; - } - - lib.Add(presetObject, presetName); - SaveCurrentLib(); - if (presetsWasReordered != null) - presetsWasReordered(); - - Repaint(); - OnLayoutChanged(); - return lib.Count() - 1; - } - - public void SaveCurrentLib() - { - T lib = GetCurrentLib(); - if (lib == null) - { - Debug.Log("No current library selected!"); - return; - } - PresetLibraryManager.instance.SaveLibrary(m_SaveLoadHelper, lib, currentLibraryWithoutExtension); - InternalEditorUtility.RepaintAllViews(); - } - - public T CreateNewLibrary(string presetLibraryPathWithoutExtension) - { - T newLib = PresetLibraryManager.instance.CreateLibrary(m_SaveLoadHelper, presetLibraryPathWithoutExtension); - if (newLib != null) - { - PresetLibraryManager.instance.SaveLibrary(m_SaveLoadHelper, newLib, presetLibraryPathWithoutExtension); - InternalEditorUtility.RepaintAllViews(); // Needed because we call this function from another window - } - return newLib; - } - - public void RevealCurrentLibrary() - { - if (m_PresetLibraryFileLocation == PresetFileLocation.PreferencesFolder) - EditorUtility.RevealInFinder(Path.GetFullPath(pathWithExtension)); - else - EditorGUIUtility.PingObject(AssetDatabase.GetMainAssetInstanceID(pathWithExtension)); - } - - internal class PresetContextMenu - { - static PresetLibraryEditor s_Caller; - static int s_PresetIndex; - - static internal void Show(bool isOpenForEdit, int presetIndex, object newPresetObject, PresetLibraryEditor caller) - { - s_Caller = caller; - s_PresetIndex = presetIndex; - - GUIContent replaceText = EditorGUIUtility.TrTextContent("Replace"); - GUIContent deleteText = EditorGUIUtility.TrTextContent("Delete"); - GUIContent renameText = EditorGUIUtility.TrTextContent("Rename"); - GUIContent moveToText = EditorGUIUtility.TrTextContent("Move To First"); - - GenericMenu menu = new GenericMenu(); - if (isOpenForEdit) - { - menu.AddItem(replaceText, false, new PresetContextMenu().Replace, newPresetObject); - menu.AddItem(deleteText, false, new PresetContextMenu().Delete, 0); - if (caller.drawLabels) - menu.AddItem(renameText, false, new PresetContextMenu().Rename, 0); - menu.AddItem(moveToText, false, new PresetContextMenu().MoveToTop, 0); - } - else - { - menu.AddDisabledItem(replaceText); - menu.AddDisabledItem(deleteText); - if (caller.drawLabels) - menu.AddDisabledItem(renameText); - menu.AddDisabledItem(moveToText); - } - menu.ShowAsContext(); - } - - private void Delete(object userData) - { - s_Caller.DeletePreset(s_PresetIndex); - } - - private void Replace(object userData) - { - object newPresetObject = userData; - s_Caller.ReplacePreset(s_PresetIndex, newPresetObject); - } - - private void Rename(object userData) - { - string name = s_Caller.GetCurrentLib().GetName(s_PresetIndex); - s_Caller.BeginRenaming(name, s_PresetIndex, 0.0f); - } - - private void MoveToTop(object userData) - { - s_Caller.MovePreset(s_PresetIndex, 0, false); - } - } - } -} // UnityEditor diff --git a/Editor/Mono/PresetLibraries/PresetLibraryEditorMenu.cs b/Editor/Mono/PresetLibraries/PresetLibraryEditorMenu.cs deleted file mode 100644 index 60151030b2..0000000000 --- a/Editor/Mono/PresetLibraries/PresetLibraryEditorMenu.cs +++ /dev/null @@ -1,130 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using UnityEngine; -using UnityEditorInternal; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal partial class PresetLibraryEditor where T : PresetLibrary - { - class SettingsMenu - { - static PresetLibraryEditor s_Owner; - - class ViewModeData - { - public GUIContent text; - public int itemHeight; - public PresetLibraryEditorState.ItemViewMode viewmode; - } - - public static void Show(Rect activatorRect, PresetLibraryEditor owner) - { - s_Owner = owner; - - GenericMenu menu = new GenericMenu(); - - // View modes - int minItemHeight = (int)s_Owner.minMaxPreviewHeight.x; - int maxItemHeight = (int)s_Owner.minMaxPreviewHeight.y; - List viewModeData; - if (minItemHeight == maxItemHeight) - { - viewModeData = new List - { - new ViewModeData {text = EditorGUIUtility.TrTextContent("Grid"), itemHeight = minItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.Grid}, - new ViewModeData {text = EditorGUIUtility.TrTextContent("List"), itemHeight = minItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.List}, - }; - } - else - { - viewModeData = new List - { - new ViewModeData {text = EditorGUIUtility.TrTextContent("Small Grid"), itemHeight = minItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.Grid}, - new ViewModeData {text = EditorGUIUtility.TrTextContent("Large Grid"), itemHeight = maxItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.Grid}, - new ViewModeData {text = EditorGUIUtility.TrTextContent("Small List"), itemHeight = minItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.List}, - new ViewModeData {text = EditorGUIUtility.TrTextContent("Large List"), itemHeight = maxItemHeight, viewmode = PresetLibraryEditorState.ItemViewMode.List} - }; - } - - for (int i = 0; i < viewModeData.Count; ++i) - { - bool currentSelected = s_Owner.itemViewMode == viewModeData[i].viewmode && (int)s_Owner.previewHeight == viewModeData[i].itemHeight; - menu.AddItem(viewModeData[i].text, currentSelected, ViewModeChange, viewModeData[i]); - } - menu.AddSeparator(""); - - // Available libraries (show user libraries first then project libraries) - List preferencesLibs; - List projectLibs; - PresetLibraryManager.instance.GetAvailableLibraries(s_Owner.m_SaveLoadHelper, out preferencesLibs, out projectLibs); - preferencesLibs.Sort(); - projectLibs.Sort(); - - string currentLibWithExtension = s_Owner.currentLibraryWithoutExtension + "." + s_Owner.m_SaveLoadHelper.fileExtensionWithoutDot; - - string projectFolderTag = " (Project)"; - foreach (string libPath in preferencesLibs) - { - string libName = Path.GetFileNameWithoutExtension(libPath); - menu.AddItem(new GUIContent(libName), currentLibWithExtension == libPath, LibraryModeChange, libPath); - } - foreach (string libPath in projectLibs) - { - string libName = Path.GetFileNameWithoutExtension(libPath); - menu.AddItem(new GUIContent(libName + projectFolderTag), currentLibWithExtension == libPath, LibraryModeChange, libPath); - } - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Create New Library..."), false, CreateLibrary, 0); - if (HasDefaultPresets()) - { - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Add Factory Presets To Current Library"), false, AddDefaultPresetsToCurrentLibrary, 0); - } - menu.AddSeparator(""); - menu.AddItem(EditorGUIUtility.TrTextContent("Reveal Current Library Location"), false, RevealCurrentLibrary, 0); - menu.DropDown(activatorRect); - } - - static void ViewModeChange(object userData) - { - ViewModeData viewModeData = (ViewModeData)userData; - s_Owner.itemViewMode = viewModeData.viewmode; - s_Owner.previewHeight = viewModeData.itemHeight; - } - - static void LibraryModeChange(object userData) - { - string libPath = (string)userData; - s_Owner.currentLibraryWithoutExtension = libPath; - } - - static void CreateLibrary(object userData) - { - s_Owner.wantsToCreateLibrary = true; - } - - static void RevealCurrentLibrary(object userData) - { - s_Owner.RevealCurrentLibrary(); - } - - static bool HasDefaultPresets() - { - return s_Owner.addDefaultPresets != null; - } - - static void AddDefaultPresetsToCurrentLibrary(object userData) - { - if (s_Owner.addDefaultPresets != null) - s_Owner.addDefaultPresets(s_Owner.GetCurrentLib()); - - s_Owner.SaveCurrentLib(); - } - } - } -} // UnityEditor diff --git a/Editor/Mono/PresetLibraries/PresetLibraryManager.cs b/Editor/Mono/PresetLibraries/PresetLibraryManager.cs deleted file mode 100644 index 606c0fdcf7..0000000000 --- a/Editor/Mono/PresetLibraries/PresetLibraryManager.cs +++ /dev/null @@ -1,289 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using UnityEngine; -using System.Collections.Generic; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal enum PresetFileLocation { PreferencesFolder, ProjectFolder } // ProjectFolder: We look in all Editor folders in Assets - - internal static class PresetLibraryLocations - { - public static string defaultLibraryLocation - { - get { return GetDefaultFilePathForFileLocation(PresetFileLocation.PreferencesFolder); } - } - - public static string defaultPresetLibraryPath - { - get { return Path.Combine(defaultLibraryLocation, defaultLibraryName); } - } - - public static string defaultLibraryName - { - get { return "Default"; } - } - - public static List GetAvailableFilesWithExtensionOnTheHDD(PresetFileLocation fileLocation, string fileExtensionWithoutDot) - { - List folderPaths = GetDirectoryPaths(fileLocation); - List files = GetFilesWithExentionFromFolders(folderPaths, fileExtensionWithoutDot); - for (int i = 0; i < files.Count; ++i) - files[i] = ConvertToUnitySeperators(files[i]); - return files; - } - - public static string GetDefaultFilePathForFileLocation(PresetFileLocation fileLocation) - { - switch (fileLocation) - { - case PresetFileLocation.PreferencesFolder: - return InternalEditorUtility.unityPreferencesFolder + "/Presets/"; - - case PresetFileLocation.ProjectFolder: - return "Assets/Editor/"; - - default: - Debug.LogError("Enum not handled!"); - return ""; - } - } - - static List GetDirectoryPaths(PresetFileLocation fileLocation) - { - List folderPaths = new List(); - switch (fileLocation) - { - case PresetFileLocation.PreferencesFolder: - folderPaths.Add(GetDefaultFilePathForFileLocation(PresetFileLocation.PreferencesFolder)); - break; - - case PresetFileLocation.ProjectFolder: - string[] editorFolders = Directory.GetDirectories("Assets/", "Editor", SearchOption.AllDirectories); - folderPaths.AddRange(editorFolders); - break; - - default: - Debug.LogError("Enum not handled!"); - break; - } - - return folderPaths; - } - - static List GetFilesWithExentionFromFolders(List folderPaths, string fileExtensionWithoutDot) - { - // First get all potential files - var files = new List(); - foreach (string editorFolder in folderPaths) - { - string[] filePaths = Directory.GetFiles(editorFolder, "*." + fileExtensionWithoutDot); - files.AddRange(filePaths); - } - return files; - } - - public static PresetFileLocation GetFileLocationFromPath(string path) - { - if (path.Contains(InternalEditorUtility.unityPreferencesFolder)) - return PresetFileLocation.PreferencesFolder; - if (path.Contains("Assets/")) - return PresetFileLocation.ProjectFolder; - - Debug.LogError("Could not determine preset file location type " + path); - return PresetFileLocation.ProjectFolder; - } - - static string ConvertToUnitySeperators(string path) - { - return path.Replace('\\', '/'); - } - - static public string GetParticleCurveLibraryExtension(bool singleCurve, bool signedRange) - { - string extension = "particle"; - if (singleCurve) - extension += "Curves"; - else - extension += "DoubleCurves"; - - if (signedRange) - extension += "Signed"; - else - extension += ""; - - return extension; - } - - static public string GetCurveLibraryExtension(bool normalized) - { - if (normalized) - return "curvesNormalized"; - return "curves"; - } - } - - - internal class PresetLibraryManager : ScriptableSingleton - { - static string s_LastError = null; - private List m_LibraryCaches = new List(); - - private HideFlags libraryHideFlag - { - get { return HideFlags.DontSave; } // Use of DontSave prevents library from being nulled when going out of playmode - } - - // Returns lists of filepaths for libraries with a given extension found on the HDD - public void GetAvailableLibraries(ScriptableObjectSaveLoadHelper helper, out List preferencesLibs, out List projectLibs) where T : ScriptableObject - { - preferencesLibs = PresetLibraryLocations.GetAvailableFilesWithExtensionOnTheHDD(PresetFileLocation.PreferencesFolder, helper.fileExtensionWithoutDot); - projectLibs = PresetLibraryLocations.GetAvailableFilesWithExtensionOnTheHDD(PresetFileLocation.ProjectFolder, helper.fileExtensionWithoutDot); - } - - string GetLibaryNameFromPath(string filePath) - { - return Path.GetFileNameWithoutExtension(filePath); - } - - public T CreateLibrary(ScriptableObjectSaveLoadHelper helper, string presetLibraryPathWithoutExtension) where T : ScriptableObject - { - string libraryName = GetLibaryNameFromPath(presetLibraryPathWithoutExtension); - if (!InternalEditorUtility.IsValidFileName(libraryName)) - { - string invalid = InternalEditorUtility.GetDisplayStringOfInvalidCharsOfFileName(libraryName); - if (invalid.Length > 0) - s_LastError = string.Format("A library filename cannot contain the following character{0}: {1}", invalid.Length > 1 ? "s" : "", invalid); - else - s_LastError = "Invalid filename"; - return null; - } - - if (GetLibrary(helper, presetLibraryPathWithoutExtension) != null) - { - s_LastError = "Library '" + libraryName + "' already exists! Ensure a unique name."; - return null; - } - - T library = helper.Create(); - library.hideFlags = libraryHideFlag; - LibraryCache set = GetPresetLibraryCache(helper.fileExtensionWithoutDot); - set.loadedLibraries.Add(library); - set.loadedLibraryIDs.Add(presetLibraryPathWithoutExtension); - s_LastError = null; - return library; - } - - public T GetLibrary(ScriptableObjectSaveLoadHelper helper, string presetLibraryPathWithoutExtension) where T : ScriptableObject - { - LibraryCache set = GetPresetLibraryCache(helper.fileExtensionWithoutDot); - - // Did we already load the lib - for (int i = 0; i < set.loadedLibraryIDs.Count; ++i) - { - if (set.loadedLibraryIDs[i] == presetLibraryPathWithoutExtension) - { - if (set.loadedLibraries[i] != null) - return set.loadedLibraries[i] as T; - else - { - // The library has been destroyed. Remove it from the lists so it can be reloaded - set.loadedLibraries.RemoveAt(i); - set.loadedLibraryIDs.RemoveAt(i); - Debug.LogError("Invalid library detected: Reload " + set.loadedLibraryIDs[i] + " from HDD"); - break; - } - } - } - - // Debug.Log ("Not loaded yet " + typeof(T)); - - // Can we find on the hdd - T library = helper.Load(presetLibraryPathWithoutExtension); - - if (library != null) - { - library.hideFlags = libraryHideFlag; // ensure correct hideflag with pre 4.3 versions - set.loadedLibraries.Add(library); - set.loadedLibraryIDs.Add(presetLibraryPathWithoutExtension); - return library; - } - - // Debug.Log ("Not found on hdd"); - - return null; - } - - public void UnloadAllLibrariesFor(ScriptableObjectSaveLoadHelper helper) where T : ScriptableObject - { - for (int i = 0; i < m_LibraryCaches.Count; ++i) - { - if (m_LibraryCaches[i].identifier == helper.fileExtensionWithoutDot) - { - m_LibraryCaches[i].UnloadScriptableObjects(); - m_LibraryCaches.RemoveAt(i); - break; - } - } - } - - public void SaveLibrary(ScriptableObjectSaveLoadHelper helper, T library, string presetLibraryPathWithoutExtension) where T : ScriptableObject - { - bool fileExistedBeforeSaving = File.Exists(presetLibraryPathWithoutExtension + "." + helper.fileExtensionWithoutDot); - - helper.Save(library, presetLibraryPathWithoutExtension); - - if (!fileExistedBeforeSaving) - AssetDatabase.Refresh(); - } - - public string GetLastError() - { - string errorString = s_LastError; - s_LastError = null; - return errorString; - } - - private LibraryCache GetPresetLibraryCache(string identifier) - { - foreach (LibraryCache libraryCache in m_LibraryCaches) - if (libraryCache.identifier == identifier) - return libraryCache; - - // Add if not found - LibraryCache set = new LibraryCache(identifier); - m_LibraryCaches.Add(set); - return set; - } - - private class LibraryCache - { - string m_Identifier; // Identifier for a group of libraries. For now its the file extension - - // Should have been a Dictonary but we cannot serialize those properly yet... - List m_LoadedLibraries = new List(); // 1:1 with m_LoadedLibraryIDs - List m_LoadedLibraryIDs = new List(); // 1:1 with m_LoadedLibraries - - // Interface - public string identifier { get { return m_Identifier; } } - public List loadedLibraries { get { return m_LoadedLibraries; } } - public List loadedLibraryIDs { get { return m_LoadedLibraryIDs; } } // List of paths without extension - public void UnloadScriptableObjects() - { - foreach (ScriptableObject sobj in m_LoadedLibraries) - ScriptableObject.DestroyImmediate(sobj); - m_LoadedLibraries.Clear(); - m_LoadedLibraryIDs.Clear(); - } - - public LibraryCache(string identifier) - { - m_Identifier = identifier; - } - } - } -} diff --git a/Editor/Mono/PresetLibraries/ScriptableObjectSaveLoadHelper.cs b/Editor/Mono/PresetLibraries/ScriptableObjectSaveLoadHelper.cs deleted file mode 100644 index 42eaeab8b9..0000000000 --- a/Editor/Mono/PresetLibraries/ScriptableObjectSaveLoadHelper.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using System.IO; - -namespace UnityEditor -{ - public enum SaveType { Binary, Text } - - - // Class for making it easy to save and load ScriptableObjects manually (i.e without using the AssetDatabase) - - class ScriptableObjectSaveLoadHelper where T : ScriptableObject - { - public string fileExtensionWithoutDot { get; private set; } - private SaveType saveType { get; set; } - - public ScriptableObjectSaveLoadHelper(string fileExtensionWithoutDot, SaveType saveType) - { - this.saveType = saveType; - this.fileExtensionWithoutDot = fileExtensionWithoutDot.TrimStart('.'); // Ensure no dot - } - - // If 'filePath' does not include an extension the local 'fileExtensionWithoutDot' is used. - public T Load(string filePath) - { - filePath = AppendFileExtensionIfNeeded(filePath); - - // Try to load - if (!string.IsNullOrEmpty(filePath)) - { - Object[] objects = InternalEditorUtility.LoadSerializedFileAndForget(filePath); - if (objects != null && objects.Length > 0) - return objects[0] as T; - } - - return null; - } - - public T Create() - { - T t = ScriptableObject.CreateInstance(); - return t; - } - - // If 'filePath' does not include an extension the local 'fileExtensionWithoutDot' is used. - public void Save(T t, string filePath) - { - if (t == null) - { - Debug.LogError("Cannot save scriptableObject: its null!"); - return; - } - - if (string.IsNullOrEmpty(filePath)) - { - Debug.LogError("Invalid path: '" + filePath + "'"); - return; - } - - // Ensure folder exists - string folderPath = Path.GetDirectoryName(filePath); - if (!Directory.Exists(folderPath)) - { - Directory.CreateDirectory(folderPath); - } - - filePath = AppendFileExtensionIfNeeded(filePath); - - InternalEditorUtility.SaveToSerializedFileAndForget(new[] { t }, filePath, saveType == SaveType.Text); - } - - public override string ToString() - { - return string.Format("{0}, {1}", fileExtensionWithoutDot, saveType); - } - - string AppendFileExtensionIfNeeded(string path) - { - if (!Path.HasExtension(path) && !string.IsNullOrEmpty(fileExtensionWithoutDot)) - return path + "." + fileExtensionWithoutDot; - return path; - } - } -} diff --git a/Editor/Mono/ProjectBrowser.cs b/Editor/Mono/ProjectBrowser.cs deleted file mode 100644 index b1c0b859e2..0000000000 --- a/Editor/Mono/ProjectBrowser.cs +++ /dev/null @@ -1,2726 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor.ProjectWindowCallback; -using UnityEngine; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System.Text.RegularExpressions; -using UnityEditor.IMGUI.Controls; -using UnityEditor.TreeViewExamples; -using UnityEditorInternal; -using UnityEngine.Scripting; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - // The title is also used for fetching the project window tab icon: Project.png - [EditorWindowTitle(title = "Project", icon = "Project")] - internal class ProjectBrowser : EditorWindow, IHasCustomMenu - { - // Alive ProjectBrowsers - private static List s_ProjectBrowsers = new List(); - public static List GetAllProjectBrowsers() - { - return s_ProjectBrowsers; - } - - public static ProjectBrowser s_LastInteractedProjectBrowser; - - internal enum ItemType - { - Asset, - SavedFilter, - } - - enum ViewMode - { - OneColumn, - TwoColumns - } - - public enum SearchViewState - { - NotSearching, - AllAssets, - SubFolders, - AssetStore - } - - // Styles used in the object selector - class Styles - { - public GUIStyle bottomBarBg = "ProjectBrowserBottomBarBg"; - public GUIStyle topBarBg = "ProjectBrowserTopBarBg"; - public GUIStyle selectedPathLabel = "Label"; - public GUIStyle exposablePopup = GetStyle("ExposablePopupMenu"); - public GUIStyle lockButton = "IN LockButton"; - public GUIStyle foldout = "AC RightArrow"; - - public GUIContent m_FilterByLabel = new GUIContent(EditorGUIUtility.FindTexture("FilterByLabel"), "Search by Label"); - public GUIContent m_FilterByType = new GUIContent(EditorGUIUtility.FindTexture("FilterByType"), "Search by Type"); - public GUIContent m_CreateDropdownContent = EditorGUIUtility.TrTextContent("Create"); - public GUIContent m_SaveFilterContent = new GUIContent(EditorGUIUtility.FindTexture("Favorite"), "Save search"); - public GUIContent m_EmptyFolderText = EditorGUIUtility.TrTextContent("This folder is empty"); - public GUIContent m_SearchIn = EditorGUIUtility.TrTextContent("Search:"); - - static GUIStyle GetStyle(string styleName) - { - return styleName; // Implicit construction of GUIStyle - - // For fast testing in editor resources grab the style directly from the skin - //GUISkin skin = EditorGUIUtility.LoadRequired ("Builtin Skins/DarkSkin/Skins/ProjectBrowserSkin.guiSkin") as GUISkin; - //return skin.GetStyle (styleName); - } - } - static Styles s_Styles; - static int s_HashForSearchField = "ProjectBrowserSearchField".GetHashCode(); - - // Search filter - [SerializeField] - SearchFilter m_SearchFilter; - - [NonSerialized] - string m_SearchFieldText = ""; - - // Display state - [SerializeField] - ViewMode m_ViewMode = ViewMode.TwoColumns; - [SerializeField] - int m_StartGridSize = 64; - [SerializeField] - string[] m_LastFolders = new string[0]; - [SerializeField] - float m_LastFoldersGridSize = -1f; - [SerializeField] - string m_LastProjectPath; - [SerializeField] - EditorGUIUtility.EditorLockTracker m_LockTracker = new EditorGUIUtility.EditorLockTracker(); - - internal bool isLocked - { - get { return m_LockTracker.isLocked; } - set { m_LockTracker.isLocked = value; } - } - - bool m_EnableOldAssetTree = true; - bool m_FocusSearchField; - string m_SelectedPath; - List m_SelectedPathSplitted = new List(); - float m_LastListWidth; - bool m_DidSelectSearchResult = false; - bool m_ItemSelectedByRightClickThisEvent = false; - bool m_InternalSelectionChange = false; // to know when selection change originated in project view itself - SearchFilter.SearchArea m_LastLocalAssetsSearchArea = SearchFilter.SearchArea.AllAssets; - PopupList.InputData m_AssetLabels; - PopupList.InputData m_ObjectTypes; - bool m_UseTreeViewSelectionInsteadOfMainSelection; - bool useTreeViewSelectionInsteadOfMainSelection - { - get {return m_UseTreeViewSelectionInsteadOfMainSelection; } - set {m_UseTreeViewSelectionInsteadOfMainSelection = value; } - } - - - // Folder TreeView - [SerializeField] - TreeViewStateWithAssetUtility m_FolderTreeState; - TreeViewController m_FolderTree; - int m_TreeViewKeyboardControlID; - - // Full Asset TreeViewState - [SerializeField] - TreeViewStateWithAssetUtility m_AssetTreeState; - TreeViewController m_AssetTree; - - // Icon/List area - [SerializeField] - ObjectListAreaState m_ListAreaState; // state that survives assembly reloads - ObjectListArea m_ListArea; - int m_ListKeyboardControlID; - bool m_GrabKeyboardFocusForListArea = false; - - // List area header: breadcrumbs or search area menu - List> m_BreadCrumbs = new List>(); - bool m_BreadCrumbLastFolderHasSubFolders = false; - ExposablePopupMenu m_SearchAreaMenu; - - // Layout - const float k_MinHeight = 250; - const float k_MinWidthOneColumn = 230f;// could be 205 with special handling - const float k_MinWidthTwoColumns = 230f; - float m_ToolbarHeight; - const float k_BottomBarHeight = EditorGUI.kWindowToolbarHeight; - float k_MinDirectoriesAreaWidth = 110; - [SerializeField] - float m_DirectoriesAreaWidth = k_MinWidthTwoColumns / 2; - const float k_ResizerWidth = 5f; - const float k_SliderWidth = 55f; - [NonSerialized] - float m_SearchAreaMenuOffset = -1f; - [NonSerialized] - Rect m_ListAreaRect; - [NonSerialized] - Rect m_TreeViewRect; - [NonSerialized] - Rect m_BottomBarRect; - [NonSerialized] - Rect m_ListHeaderRect; - [NonSerialized] - private int m_LastFramedID = -1; - - // Used by search menu bar - [NonSerialized] - public GUIContent m_SearchAllAssets = EditorGUIUtility.TrTextContent("Assets"); // do not localize this: Assets=folder name - [NonSerialized] - public GUIContent m_SearchInFolders = new GUIContent(""); // updated when needed - [NonSerialized] - public GUIContent m_SearchAssetStore = EditorGUIUtility.TrTextContent("Asset Store"); // updated when needed - - ProjectBrowser() - { - } - - /* Keep for debugging - void TestProjectItemOverlayCallback (string guid, Rect selectionRect) - { - GUI.Label (selectionRect, GUIContent.none, EditorStyles.helpBox); - }*/ - - void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - s_ProjectBrowsers.Add(this); - EditorApplication.projectChanged += OnProjectChanged; - EditorApplication.pauseStateChanged += OnPauseStateChanged; - EditorApplication.playModeStateChanged += OnPlayModeStateChanged; - EditorApplication.assetLabelsChanged += OnAssetLabelsChanged; - EditorApplication.assetBundleNameChanged += OnAssetBundleNameChanged; - AssemblyReloadEvents.afterAssemblyReload += OnAfterAssemblyReload; - s_LastInteractedProjectBrowser = this; - - // Keep for debugging - //EditorApplication.projectWindowItemOnGUI += TestProjectItemOverlayCallback; - } - - void OnAfterAssemblyReload() - { - // Repaint to ensure ProjectBrowser UI is initialized. This fixes the issue where a new script is created from the application menu - // bar while the project browser ui was not initialized. - Repaint(); - } - - void OnDisable() - { - EditorApplication.pauseStateChanged -= OnPauseStateChanged; - EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; - EditorApplication.projectChanged -= OnProjectChanged; - EditorApplication.assetLabelsChanged -= OnAssetLabelsChanged; - EditorApplication.assetBundleNameChanged -= OnAssetBundleNameChanged; - AssemblyReloadEvents.afterAssemblyReload -= OnAfterAssemblyReload; - s_ProjectBrowsers.Remove(this); - } - - void OnPauseStateChanged(PauseState state) - { - EndRenaming(); - } - - void OnPlayModeStateChanged(PlayModeStateChange state) - { - EndRenaming(); - } - - void OnAssetLabelsChanged() - { - if (Initialized()) // Otherwise Init will handle this - { - SetupAssetLabelList(); - if (m_SearchFilter.IsSearching()) - InitListArea(); // Ensure to refresh search results: we could have results based on previous label settings - } - } - - void OnAssetBundleNameChanged() - { - if (m_ListArea != null) - InitListArea(); - } - - void Awake() - { - if (m_ListAreaState != null) - { - m_ListAreaState.OnAwake(); - } - - if (m_FolderTreeState != null) - { - m_FolderTreeState.OnAwake(); - m_FolderTreeState.expandedIDs = new List(InternalEditorUtility.expandedProjectWindowItems); - } - - if (m_AssetTreeState != null) - { - m_AssetTreeState.OnAwake(); - m_AssetTreeState.expandedIDs = new List(InternalEditorUtility.expandedProjectWindowItems); - } - - if (m_SearchFilter != null) - { - EnsureValidFolders(); - } - } - - string GetAnalyticsSizeLabel(float size) - { - if (size > 600) - return "Larger than 600 pix"; - if (size < 240) - return "Less than 240 pix"; - return "240 - 600 pix"; - } - - static internal ItemType GetItemType(int instanceID) - { - if (SavedSearchFilters.IsSavedFilter(instanceID)) - return ItemType.SavedFilter; - - return ItemType.Asset; - } - - // Return the logical path that user has active. Used when you need to create new assets from outside the project browser. - internal string GetActiveFolderPath() - { - if (m_ViewMode == ViewMode.TwoColumns && m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing && m_SearchFilter.folders.Length > 0) - return m_SearchFilter.folders[0]; - - return "Assets"; - } - - void EnsureValidFolders() - { - HashSet validFolders = new HashSet(); - foreach (string folder in m_SearchFilter.folders) - { - if (AssetDatabase.IsValidFolder(folder)) - { - validFolders.Add(folder); - } - else - { - // The folder does not exist (could have been deleted) now find first valid parent folder - string parentFolder = folder; - for (int i = 0; i < 30; ++i) - { - if (String.IsNullOrEmpty(parentFolder)) - break; - - parentFolder = ProjectWindowUtil.GetContainingFolder(parentFolder); - if (!String.IsNullOrEmpty(parentFolder) && AssetDatabase.IsValidFolder(parentFolder)) - { - validFolders.Add(parentFolder); - break; - } - } - } - } - - m_SearchFilter.folders = validFolders.ToArray(); - } - - private void OnProjectChanged() - { - if (m_AssetTree != null) - { - m_AssetTree.ReloadData(); - SetSearchFoldersFromCurrentSelection(); // We could have moved, deleted or renamed a folder so ensure we get folder paths by instanceID - } - - if (m_FolderTree != null) - { - m_FolderTree.ReloadData(); - SetSearchFolderFromFolderTreeSelection(); // We could have moved, deleted or renamed a folder so ensure we get folders paths by instanceID - } - - EnsureValidFolders(); - if (m_ListArea != null) - InitListArea(); - - RefreshSelectedPath(); - - m_BreadCrumbs.Clear(); - } - - public bool Initialized() - { - return m_ListArea != null; - } - - public void Init() - { - if (Initialized()) - return; - - m_FocusSearchField = false; - - bool firstTimeInit = m_SearchFilter == null; - if (firstTimeInit) - m_DirectoriesAreaWidth = Mathf.Min(position.width / 2, 200); - - // m_SearchFilter is serialized - if (m_SearchFilter == null) - m_SearchFilter = new SearchFilter(); - - m_SearchFieldText = m_SearchFilter.FilterToSearchFieldString(); - - CalculateRects(); // setup m_TreeViewRect and m_ListAreaRect before calling InitListArea and TreeViews - RefreshSelectedPath(); - SetupDroplists(); - - // m_ListAreaState is serialized - - if (m_ListAreaState == null) - m_ListAreaState = new ObjectListAreaState(); - m_ListAreaState.m_RenameOverlay.isRenamingFilename = true; - - m_ListArea = new ObjectListArea(m_ListAreaState, this, false); - m_ListArea.allowDeselection = true; - m_ListArea.allowDragging = true; - m_ListArea.allowFocusRendering = true; - m_ListArea.allowMultiSelect = true; - m_ListArea.allowRenaming = true; - m_ListArea.allowBuiltinResources = false; - m_ListArea.allowUserRenderingHook = true; - m_ListArea.allowFindNextShortcut = true; - m_ListArea.foldersFirst = GetShouldShowFoldersFirst(); - m_ListArea.repaintCallback += Repaint; - m_ListArea.itemSelectedCallback += ListAreaItemSelectedCallback; - m_ListArea.keyboardCallback += ListAreaKeyboardCallback; - m_ListArea.gotKeyboardFocus += ListGotKeyboardFocus; - m_ListArea.drawLocalAssetHeader += DrawLocalAssetHeader; - m_ListArea.assetStoreSearchEnded += AssetStoreSearchEndedCallback; - m_ListArea.gridSize = m_StartGridSize; - - m_StartGridSize = Mathf.Clamp(m_StartGridSize, m_ListArea.minGridSize, m_ListArea.maxGridSize); - m_LastFoldersGridSize = Mathf.Min(m_LastFoldersGridSize, m_ListArea.maxGridSize); - - m_SearchAreaMenu = new ExposablePopupMenu(); - - // m_FolderTreeState is our serialized state (ensure not to reassign it if our serialization system has created it for us) - if (m_FolderTreeState == null) - m_FolderTreeState = new TreeViewStateWithAssetUtility(); - m_FolderTreeState.renameOverlay.isRenamingFilename = true; - - // Full asset treeview - if (m_AssetTreeState == null) - m_AssetTreeState = new TreeViewStateWithAssetUtility(); - m_AssetTreeState.renameOverlay.isRenamingFilename = true; - - InitViewMode(m_ViewMode); - - EnsureValidSetup(); - - RefreshSearchText(); - SyncFilterGUI(); - InitListArea(); - } - - public void SetSearch(string searchString) - { - SetSearch(SearchFilter.CreateSearchFilterFromString(searchString)); - } - - public void SetSearch(SearchFilter searchFilter) - { - if (!Initialized()) - Init(); - - m_SearchFilter = searchFilter; - m_SearchFieldText = searchFilter.FilterToSearchFieldString(); - - TopBarSearchSettingsChanged(); - } - - internal void RefreshSearchIfFilterContains(string searchString) - { - if (!Initialized() || !m_SearchFilter.IsSearching()) - return; - - if (m_SearchFieldText.IndexOf(searchString) >= 0) - { - InitListArea(); - } - } - - void SetSearchViewState(SearchViewState state) - { - switch (state) - { - case SearchViewState.AllAssets: - m_SearchFilter.searchArea = SearchFilter.SearchArea.AllAssets; - break; - case SearchViewState.SubFolders: - m_SearchFilter.searchArea = SearchFilter.SearchArea.SelectedFolders; - break; - case SearchViewState.AssetStore: - m_SearchFilter.searchArea = SearchFilter.SearchArea.AssetStore; - break; - case SearchViewState.NotSearching: - Debug.LogError("Invalid search mode as setter"); - break; - } - - // Sync gui to state - InitSearchMenu(); - InitListArea(); - } - - SearchViewState GetSearchViewState() - { - switch (m_SearchFilter.GetState()) - { - case SearchFilter.State.SearchingInAllAssets: return SearchViewState.AllAssets; - case SearchFilter.State.SearchingInFolders: return SearchViewState.SubFolders; - case SearchFilter.State.SearchingInAssetStore: return SearchViewState.AssetStore; - } - return SearchViewState.NotSearching; - } - - void SearchButtonClickedCallback(ExposablePopupMenu.ItemData itemClicked) - { - if (!itemClicked.m_On) // Behave like radio buttons: a button that is on cannot be turned off - { - SetSearchViewState((SearchViewState)itemClicked.m_UserData); - - if (m_SearchFilter.searchArea == SearchFilter.SearchArea.AllAssets || m_SearchFilter.searchArea == SearchFilter.SearchArea.SelectedFolders) - m_LastLocalAssetsSearchArea = m_SearchFilter.searchArea; - } - } - - void InitSearchMenu() - { - SearchViewState state = GetSearchViewState(); - if (state == SearchViewState.NotSearching) - return; - - List buttonData = new List(); - - GUIStyle onStyle = "ExposablePopupItem"; - GUIStyle offStyle = "ExposablePopupItem"; - bool hasFolderSelected = m_SearchFilter.folders.Length > 0; - m_SearchAssetStore.text = m_ListArea.GetAssetStoreButtonText(); - - bool on = state == SearchViewState.AllAssets; - buttonData.Add(new ExposablePopupMenu.ItemData(m_SearchAllAssets, on ? onStyle : offStyle, on, true, (int)SearchViewState.AllAssets)); - on = state == SearchViewState.SubFolders; - buttonData.Add(new ExposablePopupMenu.ItemData(m_SearchInFolders, on ? onStyle : offStyle, on, hasFolderSelected, (int)SearchViewState.SubFolders)); - on = state == SearchViewState.AssetStore; - buttonData.Add(new ExposablePopupMenu.ItemData(m_SearchAssetStore, on ? onStyle : offStyle, on, true, (int)SearchViewState.AssetStore)); - - GUIContent popupButtonContent = m_SearchAllAssets; - switch (state) - { - case SearchViewState.AllAssets: - popupButtonContent = m_SearchAllAssets; - break; - case SearchViewState.SubFolders: - popupButtonContent = m_SearchInFolders; - break; - case SearchViewState.AssetStore: - case SearchViewState.NotSearching: - popupButtonContent = m_SearchAssetStore; - break; - default: - Debug.LogError("Unhandled enum"); - break; - } - - ExposablePopupMenu.PopupButtonData popListData = new ExposablePopupMenu.PopupButtonData(popupButtonContent, s_Styles.exposablePopup); - m_SearchAreaMenu.Init(buttonData, 10f, 450f, popListData, SearchButtonClickedCallback); - } - - void AssetStoreSearchEndedCallback() - { - InitSearchMenu(); - } - - static public void ShowAssetStoreHitsWhileSearchingLocalAssetsChanged() - { - foreach (var ob in s_ProjectBrowsers) - { - ob.m_ListArea.ShowAssetStoreHitCountWhileSearchingLocalAssetsChanged(); - ob.InitSearchMenu(); - } - } - - void RefreshSearchText() - { - if (m_SearchFilter.folders.Length > 0) - { - string[] baseFolders = ProjectWindowUtil.GetBaseFolders(m_SearchFilter.folders); - - string folderText = ""; - string toolTip = ""; - int maxShow = 3; - for (int i = 0; i < baseFolders.Length && i < maxShow; ++i) - { - if (i > 0) - folderText += ", "; - string folderName = Path.GetFileNameWithoutExtension(baseFolders[i]); - folderText += "'" + folderName + "'"; - - if (i == 0 && folderName != "Assets") // We dont show tooltip for the root folder: Assets - toolTip = baseFolders[i]; - } - if (baseFolders.Length > maxShow) - folderText += " +"; - - m_SearchInFolders.text = folderText; - m_SearchInFolders.tooltip = toolTip; - } - else - { - m_SearchInFolders.text = "Selected folder"; - m_SearchInFolders.tooltip = ""; - } - - m_BreadCrumbs.Clear(); - InitSearchMenu(); - } - - void EnsureValidSetup() - { - if (m_LastProjectPath != Directory.GetCurrentDirectory()) - { - // Clear project specific serialized state - m_SearchFilter = new SearchFilter(); - m_LastFolders = new string[0]; - SyncFilterGUI(); - - // If we have a selection try to frame it (could be a non asset object) - if (Selection.activeInstanceID != 0) - FrameObjectPrivate(Selection.activeInstanceID, !m_LockTracker.isLocked, false); - - // If we did not frame anything above ensure to show Assets folder in two column mode - if (m_ViewMode == ViewMode.TwoColumns && !IsShowingFolderContents()) - SelectAssetsFolder(); - - m_LastProjectPath = Directory.GetCurrentDirectory(); - } - - // In two column do not allow empty search filter, at least show the Assets folders - if (m_ViewMode == ViewMode.TwoColumns && m_SearchFilter.GetState() == SearchFilter.State.EmptySearchFilter) - { - SelectAssetsFolder(); - } - } - - void OnGUIAssetCallback(int instanceID, Rect rect) - { - // User hook for rendering stuff on top of assets - if (EditorApplication.projectWindowItemOnGUI != null) - { - string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(instanceID)); - EditorApplication.projectWindowItemOnGUI(guid, rect); - } - } - - void InitViewMode(ViewMode viewMode) - { - m_ViewMode = viewMode; - - // Reset - m_FolderTree = null; - m_AssetTree = null; - - useTreeViewSelectionInsteadOfMainSelection = false; - - if (m_ViewMode == ViewMode.OneColumn) - { - m_AssetTree = new TreeViewController(this, m_AssetTreeState); - m_AssetTree.deselectOnUnhandledMouseDown = true; - m_AssetTree.selectionChangedCallback += AssetTreeSelectionCallback; - m_AssetTree.keyboardInputCallback += AssetTreeKeyboardInputCallback; - m_AssetTree.contextClickItemCallback += AssetTreeViewContextClick; - m_AssetTree.contextClickOutsideItemsCallback += AssetTreeViewContextClickOutsideItems; - m_AssetTree.itemDoubleClickedCallback += AssetTreeItemDoubleClickedCallback; - m_AssetTree.onGUIRowCallback += OnGUIAssetCallback; - m_AssetTree.dragEndedCallback += AssetTreeDragEnded; - - var data = new AssetsTreeViewDataSource(m_AssetTree, AssetDatabase.GetMainAssetOrInProgressProxyInstanceID("Assets"), false, false); - data.foldersFirst = GetShouldShowFoldersFirst(); - - m_AssetTree.Init(m_TreeViewRect, - data, - new AssetsTreeViewGUI(m_AssetTree), - new AssetsTreeViewDragging(m_AssetTree) - ); - m_AssetTree.ReloadData(); - } - else if (m_ViewMode == ViewMode.TwoColumns) - { - m_FolderTree = new TreeViewController(this, m_FolderTreeState); - m_FolderTree.deselectOnUnhandledMouseDown = false; - m_FolderTree.selectionChangedCallback += FolderTreeSelectionCallback; - m_FolderTree.contextClickItemCallback += FolderTreeViewContextClick; - m_FolderTree.onGUIRowCallback += OnGUIAssetCallback; - m_FolderTree.dragEndedCallback += FolderTreeDragEnded; - m_FolderTree.Init(m_TreeViewRect, - new ProjectBrowserColumnOneTreeViewDataSource(m_FolderTree), - new ProjectBrowserColumnOneTreeViewGUI(m_FolderTree), - new ProjectBrowserColumnOneTreeViewDragging(m_FolderTree) - ); - m_FolderTree.ReloadData(); - } - - float minWidth = (m_ViewMode == ViewMode.OneColumn) ? k_MinWidthOneColumn : k_MinWidthTwoColumns; - //if (position.width < minWidth) - // Debug.LogError ("ProjectBrowser: Ensure that mode cannot be changed resulting in an invalid min width: " + minWidth + " (cur width " + position.width + ")"); - - minSize = new Vector2(minWidth, k_MinHeight); - maxSize = new Vector2(10000, 10000); - } - - private bool GetShouldShowFoldersFirst() - { - return Application.platform != RuntimePlatform.OSXEditor; - } - - // Called when user changes view mode - void SetViewMode(ViewMode newViewMode) - { - if (m_ViewMode == newViewMode) - return; - - EndRenaming(); - InitViewMode(m_ViewMode == ViewMode.OneColumn ? ViewMode.TwoColumns : ViewMode.OneColumn); - - // Ensure same selection is framed in new view mode - if (Selection.activeInstanceID != 0) - FrameObjectPrivate(Selection.activeInstanceID, !m_LockTracker.isLocked, false); - - RepaintImmediately(); - } - - void EndRenaming() - { - if (m_AssetTree != null) - m_AssetTree.EndNameEditing(true); - - if (m_FolderTree != null) - m_FolderTree.EndNameEditing(true); - - if (m_ListArea != null) - m_ListArea.EndRename(true); - } - - string[] GetTypesDisplayNames() - { - return new[] - { - "AnimationClip", - "AudioClip", - "AudioMixer", - "Font", - "GUISkin", - "Material", - "Mesh", - "Model", - "PhysicMaterial", - "Prefab", - "Scene", - "Script", - "Shader", - "Sprite", - "Texture", - "VideoClip", - - // "Texture2D", - // "RenderTexture", - // "Cubemap", - // "MovieTexture", - }; - } - - public void TypeListCallback(PopupList.ListElement element) - { - if (!Event.current.control) - { - // Clear all selection except for clicked element - foreach (var item in m_ObjectTypes.m_ListElements) - if (item != element) - item.selected = false; - } - - // Toggle clicked element - element.selected = !element.selected; - string[] selectedDisplayNames = (from item in m_ObjectTypes.m_ListElements where item.selected select item.text).ToArray(); - - m_SearchFilter.classNames = selectedDisplayNames; - m_SearchFieldText = m_SearchFilter.FilterToSearchFieldString(); - - TopBarSearchSettingsChanged(); - Repaint(); - } - - public void AssetLabelListCallback(PopupList.ListElement element) - { - if (!Event.current.control) - { - // Clear all selection except for clicked element - foreach (var item in m_AssetLabels.m_ListElements) - if (item != element) - item.selected = false; - } - - // Toggle clicked element - element.selected = !element.selected; - m_SearchFilter.assetLabels = (from item in m_AssetLabels.m_ListElements where item.selected select item.text).ToArray(); - - m_SearchFieldText = m_SearchFilter.FilterToSearchFieldString(); - - TopBarSearchSettingsChanged(); - Repaint(); - } - - void SetupDroplists() - { - SetupAssetLabelList(); - - // Types - m_ObjectTypes = new PopupList.InputData(); - m_ObjectTypes.m_CloseOnSelection = false; - m_ObjectTypes.m_AllowCustom = false; - m_ObjectTypes.m_OnSelectCallback = TypeListCallback; - m_ObjectTypes.m_SortAlphabetically = false; - m_ObjectTypes.m_MaxCount = 0; - string[] types = GetTypesDisplayNames(); - for (int i = 0; i < types.Length; ++i) - { - PopupList.ListElement element = m_ObjectTypes.NewOrMatchingElement(types[i]); - if (i == 0) - element.selected = true; - } - } - - void SetupAssetLabelList() - { - // List of predefined asset labels (and in the future also user defined ones) - Dictionary tags = AssetDatabase.GetAllLabels(); - - // AssetLabels - m_AssetLabels = new PopupList.InputData(); - m_AssetLabels.m_CloseOnSelection = false; - m_AssetLabels.m_AllowCustom = true; - m_AssetLabels.m_OnSelectCallback = AssetLabelListCallback; - m_AssetLabels.m_MaxCount = 15; - m_AssetLabels.m_SortAlphabetically = true; - - foreach (var pair in tags) - { - PopupList.ListElement element = m_AssetLabels.NewOrMatchingElement(pair.Key); - if (element.filterScore < pair.Value) - element.filterScore = pair.Value; - } - } - - void SyncFilterGUI() - { - // Sync Labels - List assetLabels = new List(m_SearchFilter.assetLabels); - foreach (PopupList.ListElement item in m_AssetLabels.m_ListElements) - item.selected = assetLabels.Contains(item.text); - - // Sync Type - List classNames = new List(m_SearchFilter.classNames); - foreach (PopupList.ListElement item in m_ObjectTypes.m_ListElements) - item.selected = classNames.Contains(item.text); - - // Sync Text field - m_SearchFieldText = m_SearchFilter.FilterToSearchFieldString(); - } - - static int GetParentInstanceID(int objectInstanceID) - { - string propertyPath = AssetDatabase.GetAssetPath(objectInstanceID); - int pos = propertyPath.LastIndexOf("/"); - if (pos >= 0) - { - string folderPath = propertyPath.Substring(0, pos); - Object obj = AssetDatabase.LoadAssetAtPath(folderPath, typeof(Object)); - if (obj != null) - return obj.GetInstanceID(); - } - else - { - Debug.LogError("Invalid path: " + propertyPath); - } - return -1; - } - - bool IsShowingFolder(int folderInstanceID) - { - string folderPath = AssetDatabase.GetAssetPath(folderInstanceID); - bool contains = new List(m_SearchFilter.folders).Contains(folderPath); - return contains; - } - - void ShowFolderContents(int folderInstanceID, bool revealAndFrameInFolderTree) - { - if (m_ViewMode != ViewMode.TwoColumns) - Debug.LogError("ShowFolderContents should only be called in two column mode"); - - if (folderInstanceID == 0) - return; - - string folderPath = AssetDatabase.GetAssetPath(folderInstanceID); - m_SearchFilter.ClearSearch(); - m_SearchFilter.folders = new[] {folderPath}; - m_FolderTree.SetSelection(new[] {folderInstanceID}, revealAndFrameInFolderTree); - FolderTreeSelectionChanged(true); - } - - bool IsShowingFolderContents() - { - return m_SearchFilter.folders.Length > 0; - } - - void ListGotKeyboardFocus() - { - } - - void ListAreaKeyboardCallback() - { - if (Event.current.type == EventType.KeyDown) - { - switch (Event.current.keyCode) - { - case KeyCode.Return: - case KeyCode.KeypadEnter: - if (Application.platform == RuntimePlatform.OSXEditor) - { - if (m_ListArea.BeginRename(0f)) - Event.current.Use(); - } - else // WindowsEditor - { - Event.current.Use(); - OpenListAreaSelection(); - } - break; - - case KeyCode.DownArrow: - if (Application.platform == RuntimePlatform.OSXEditor && Event.current.command) - { - Event.current.Use(); - OpenListAreaSelection(); - } - break; - case KeyCode.UpArrow: - if (Application.platform == RuntimePlatform.OSXEditor && Event.current.command && m_ViewMode == ViewMode.TwoColumns) - { - ShowParentFolderOfCurrentlySelected(); - Event.current.Use(); - } - break; - case KeyCode.Backspace: - if (Application.platform != RuntimePlatform.OSXEditor && m_ViewMode == ViewMode.TwoColumns) - { - ShowParentFolderOfCurrentlySelected(); - Event.current.Use(); - } - break; - case KeyCode.F2: - if (Application.platform != RuntimePlatform.OSXEditor) - { - if (m_ListArea.BeginRename(0f)) - Event.current.Use(); - } - break; - } - } - } - - void ShowParentFolderOfCurrentlySelected() - { - if (IsShowingFolderContents()) - { - int[] selectedFolderInstanceIDs = m_FolderTree.GetSelection(); - if (selectedFolderInstanceIDs.Length == 1) - { - TreeViewItem item = m_FolderTree.FindItem(selectedFolderInstanceIDs[0]); - if (item != null && item.parent != null && item.id != ProjectBrowserColumnOneTreeViewDataSource.GetAssetsFolderInstanceID()) - { - SetFolderSelection(new[] {item.parent.id}, true); - m_ListArea.Frame(item.id, true, false); - Selection.activeInstanceID = item.id; - } - } - } - } - - void OpenListAreaSelection() - { - int[] selectedInstanceIDs = m_ListArea.GetSelection(); - int selectionCount = selectedInstanceIDs.Length; - if (selectionCount > 0) - { - int numFolders = 0; - foreach (int instanceID in selectedInstanceIDs) - if (ProjectWindowUtil.IsFolder(instanceID)) - numFolders++; - - bool allFolders = numFolders == selectionCount; - if (allFolders) - { - if (m_ViewMode == ViewMode.TwoColumns) - { - SetFolderSelection(selectedInstanceIDs, false); - } - else if (m_ViewMode == ViewMode.OneColumn) - { - ClearSearch(); // shows tree instead of search - m_AssetTree.Frame(selectedInstanceIDs[0], true, false); - } - - Repaint(); - GUIUtility.ExitGUI(); // Exit because if we are mouse clicking to open we are in the middle of iterating list area items.. - } - else - { - // If any assets in selection open them instead of opening folder - OpenAssetSelection(selectedInstanceIDs); - - Repaint(); - GUIUtility.ExitGUI(); // Exit because if we are mouse clicking to open we are in the middle of iterating list area items.. - } - } - } - - static void OpenAssetSelection(int[] selectedInstanceIDs) - { - foreach (int id in selectedInstanceIDs) - { - if (AssetDatabase.Contains(id)) - AssetDatabase.OpenAsset(id); - } - GUIUtility.ExitGUI(); - } - - void SetAsLastInteractedProjectBrowser() - { - s_LastInteractedProjectBrowser = this; - } - - void RefreshSelectedPath() - { - if (Selection.activeObject != null) - m_SelectedPath = AssetDatabase.GetAssetPath(Selection.activeObject); - else - m_SelectedPath = ""; - - // By clearing we auto refresh it when needed (in an OnGUI code path because we need Styles) - m_SelectedPathSplitted.Clear(); - } - - // Also called from list when navigating by keys - void ListAreaItemSelectedCallback(bool doubleClicked) - { - SetAsLastInteractedProjectBrowser(); - - Selection.activeObject = null; - int[] instanceIDs = m_ListArea.GetSelection(); - if (instanceIDs.Length > 0) - { - Selection.instanceIDs = instanceIDs; - m_SearchFilter.searchArea = m_LastLocalAssetsSearchArea; // local asset was selected - m_InternalSelectionChange = true; - } - else if (AssetStoreAssetSelection.Count > 0) - Selection.activeObject = AssetStoreAssetInspector.Instance; - - m_FocusSearchField = false; - - if (Event.current.button == 1 && Event.current.type == EventType.MouseDown) - m_ItemSelectedByRightClickThisEvent = true; - - RefreshSelectedPath(); - - m_DidSelectSearchResult = m_SearchFilter.IsSearching(); - - if (doubleClicked) - OpenListAreaSelection(); - } - - void OnGotFocus() - { - } - - void OnLostFocus() - { - // Added because this window uses RenameOverlay - EndRenaming(); - } - - bool ShouldFrameAsset(int instanceID) - { - HierarchyProperty h = new HierarchyProperty(HierarchyType.Assets, false); - return h.Find(instanceID, null); - } - - void OnSelectionChange() - { - // We do not want to init our UI on OnSelectionChange because EditorStyles might not be allocated yet (at play/stop) - if (m_ListArea == null) - return; - - // Keep for debugging - //Debug.Log ("OnSelectionChange (ProjectBrowser): " + DebugUtils.ListToString(new List(Selection.instanceIDs))); - - // The list area selection state is based on the main selection (both in search mode and folderbrowsing) - m_ListArea.InitSelection(Selection.instanceIDs); - - int instanceID = Selection.instanceIDs.Length > 0 ? Selection.instanceIDs[Selection.instanceIDs.Length - 1] : 0; - if (m_ViewMode == ViewMode.OneColumn) - { - // If searching we are not showing the asset tree but we set selection anyways to ensure its - // setup when clearing search - bool revealSelectionAndFrameLast = !m_LockTracker.isLocked && ShouldFrameAsset(instanceID) && Selection.instanceIDs.Length <= 1; - m_AssetTree.SetSelection(Selection.instanceIDs, revealSelectionAndFrameLast); - } - else if (m_ViewMode == ViewMode.TwoColumns) - { - if (!m_InternalSelectionChange) - { - bool frame = !m_LockTracker.isLocked && Selection.instanceIDs.Length > 0 && ShouldFrameAsset(instanceID); - if (frame) - { - // If searching we keep the search when framing. If folder browsing we change folder - // and frame current selection in its folder - if (m_SearchFilter.IsSearching()) - { - m_ListArea.Frame(instanceID, true, false); - } - else - { - FrameObjectInTwoColumnMode(instanceID, true, false); - } - } - } - } - - m_InternalSelectionChange = false; - - // Clear asset store asset selection - if (Selection.activeObject != null && Selection.activeObject.GetType() != typeof(AssetStoreAssetInspector)) - { - m_ListArea.selectedAssetStoreAsset = false; - AssetStoreAssetSelection.Clear(); - } - - RefreshSelectedPath(); - - Repaint(); - } - - void SetFoldersInSearchFilter(int[] selectedInstanceIDs) - { - m_SearchFilter.folders = GetFolderPathsFromInstanceIDs(selectedInstanceIDs); - EnsureValidFolders(); - - if (selectedInstanceIDs.Length > 0) - { - if (m_LastFoldersGridSize > 0) - m_ListArea.gridSize = (int)m_LastFoldersGridSize; - } - } - - internal void SetFolderSelection(int[] selectedInstanceIDs, bool revealSelectionAndFrameLastSelected) - { - m_FolderTree.SetSelection(selectedInstanceIDs, revealSelectionAndFrameLastSelected); - SetFoldersInSearchFilter(selectedInstanceIDs); - FolderTreeSelectionChanged(true); - } - - void AssetTreeItemDoubleClickedCallback(int instanceID) - { - OpenAssetSelection(Selection.instanceIDs); - } - - void AssetTreeKeyboardInputCallback() - { - if (Event.current.type == EventType.KeyDown) - { - switch (Event.current.keyCode) - { - case KeyCode.Return: - case KeyCode.KeypadEnter: - if (Application.platform == RuntimePlatform.WindowsEditor) - { - Event.current.Use(); - OpenAssetSelection(Selection.instanceIDs); - } - break; - - case KeyCode.DownArrow: - if (Application.platform == RuntimePlatform.OSXEditor && Event.current.command) - { - Event.current.Use(); - OpenAssetSelection(Selection.instanceIDs); - } - break; - } - } - } - - void AssetTreeSelectionCallback(int[] selectedTreeViewInstanceIDs) - { - SetAsLastInteractedProjectBrowser(); - - Selection.activeObject = null; - if (selectedTreeViewInstanceIDs.Length > 0) - Selection.instanceIDs = selectedTreeViewInstanceIDs; - - RefreshSelectedPath(); - SetSearchFoldersFromCurrentSelection(); - RefreshSearchText(); - } - - void SetSearchFoldersFromCurrentSelection() - { - HashSet folders = new HashSet(); - - foreach (int instanceID in Selection.instanceIDs) - { - if (!AssetDatabase.Contains(instanceID)) - continue; - - string path = AssetDatabase.GetAssetPath(instanceID); - if (AssetDatabase.IsValidFolder(path)) - { - folders.Add(path); - } - else - { - // Add containing folder of the selected asset - string folderPath = ProjectWindowUtil.GetContainingFolder(path); - if (!String.IsNullOrEmpty(folderPath)) - folders.Add(folderPath); - } - } - - // Set them as folders in search filter (so search in folder works correctly) - m_SearchFilter.folders = ProjectWindowUtil.GetBaseFolders(folders.ToArray()); - - // Keep for debugging - // Debug.Log ("Search folders: " + DebugUtils.ListToString(new List(m_SearchFilter.folders))); - } - - void SetSearchFolderFromFolderTreeSelection() - { - if (m_FolderTree != null) - m_SearchFilter.folders = GetFolderPathsFromInstanceIDs(m_FolderTree.GetSelection()); - } - - void FolderTreeSelectionCallback(int[] selectedTreeViewInstanceIDs) - { - SetAsLastInteractedProjectBrowser(); - - // Assumes only asset folders can be multi selected - int firstTreeViewInstanceID = 0; - if (selectedTreeViewInstanceIDs.Length > 0) - firstTreeViewInstanceID = selectedTreeViewInstanceIDs[0]; - - bool folderWasSelected = false; - if (firstTreeViewInstanceID != 0) - { - ItemType type = GetItemType(firstTreeViewInstanceID); - - if (type == ItemType.Asset) - { - SetFoldersInSearchFilter(selectedTreeViewInstanceIDs); - - folderWasSelected = true; - } - - if (type == ItemType.SavedFilter) - { - SearchFilter filter = SavedSearchFilters.GetFilter(firstTreeViewInstanceID); - - // Check if the filter is valid (the root of filters are not an actual filter) - if (ValidateFilter(firstTreeViewInstanceID, filter)) - { - m_SearchFilter = filter; - EnsureValidFolders(); - float previewSize = SavedSearchFilters.GetPreviewSize(firstTreeViewInstanceID); - if (previewSize > 0f) - m_ListArea.gridSize = Mathf.Clamp((int)previewSize, m_ListArea.minGridSize, m_ListArea.maxGridSize); - SyncFilterGUI(); - } - } - } - - FolderTreeSelectionChanged(folderWasSelected); - } - - bool ValidateFilter(int savedFilterID, SearchFilter filter) - { - if (filter == null) - return false; - - // Folder validation - SearchFilter.State state = filter.GetState(); - if (state == SearchFilter.State.FolderBrowsing || state == SearchFilter.State.SearchingInFolders) - { - foreach (string folderPath in filter.folders) - { - int instanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(folderPath); - if (instanceID == 0) - { - 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")) - SavedSearchFilters.RemoveSavedFilter(savedFilterID); - - return false; - } - } - } - return true; - } - - void ShowAndHideFolderTreeSelectionAsNeeded() - { - if (m_ViewMode == ViewMode.TwoColumns && m_FolderTree != null) - { - bool isSavedFilterSelected = false; - int[] selection = m_FolderTree.GetSelection(); - if (selection.Length > 0) - { - isSavedFilterSelected = GetItemType(selection[0]) == ItemType.SavedFilter; - } - - SearchViewState state = GetSearchViewState(); - switch (state) - { - case SearchViewState.AllAssets: - case SearchViewState.AssetStore: - { - if (!isSavedFilterSelected) - m_FolderTree.SetSelection(new int[0], false); - } - break; - - case SearchViewState.SubFolders: - case SearchViewState.NotSearching: - { - if (!isSavedFilterSelected) - m_FolderTree.SetSelection(GetFolderInstanceIDs(m_SearchFilter.folders), true); - } - break; - } - } - } - - // This method is being used by the EditorTests/Searching tests - public string[] GetCurrentVisibleNames() - { - return m_ListArea.GetCurrentVisibleNames(); - } - - void InitListArea() - { - ShowAndHideFolderTreeSelectionAsNeeded(); - - var hierarchyType = HierarchyType.Assets; - if (m_SearchFilter.folders.Any(AssetDatabase.IsPackagedAssetPath)) - hierarchyType = HierarchyType.Packages; - m_ListArea.Init(m_ListAreaRect, hierarchyType, m_SearchFilter, false); - m_ListArea.InitSelection(Selection.instanceIDs); - } - - void OnInspectorUpdate() - { - if (m_ListArea != null) - m_ListArea.OnInspectorUpdate(); - } - - void OnDestroy() - { - if (m_ListArea != null) - m_ListArea.OnDestroy(); - - if (this == s_LastInteractedProjectBrowser) - s_LastInteractedProjectBrowser = null; - } - - // Returns list of duplicated instanceIDs - static internal int[] DuplicateFolders(int[] instanceIDs) - { - AssetDatabase.Refresh(); - - List copiedPaths = new List(); - bool failed = false; - int asssetsFolderInstanceID = ProjectBrowserColumnOneTreeViewDataSource.GetAssetsFolderInstanceID(); - - foreach (int instanceID in instanceIDs) - { - if (instanceID == asssetsFolderInstanceID) - continue; - - string assetPath = AssetDatabase.GetAssetPath(InternalEditorUtility.GetObjectFromInstanceID(instanceID)); - string newPath = AssetDatabase.GenerateUniqueAssetPath(assetPath); - - // Copy - if (newPath.Length != 0) - failed |= !AssetDatabase.CopyAsset(assetPath, newPath); - else - failed |= true; - - if (!failed) - { - copiedPaths.Add(newPath); - } - } - - AssetDatabase.Refresh(); - - int[] copiedAssets = new int[copiedPaths.Count]; - for (int i = 0; i < copiedPaths.Count; i++) - { - copiedAssets[i] = AssetDatabase.LoadMainAssetAtPath(copiedPaths[i]).GetInstanceID(); - } - - return copiedAssets; - } - - static void DeleteFilter(int filterInstanceID) - { - if (SavedSearchFilters.GetRootInstanceID() == filterInstanceID) - { - string title = "Cannot Delete"; - EditorUtility.DisplayDialog(title, "Deleting the 'Filters' root is not allowed", "Ok"); - } - else - { - string title = "Delete selected favorite?"; - if (EditorUtility.DisplayDialog(title, "You cannot undo this action.", "Delete", "Cancel")) - { - SavedSearchFilters.RemoveSavedFilter(filterInstanceID); - } - } - } - - // Returns true if we should early out of OnGUI - bool HandleCommandEventsForTreeView() - { - // Handle all event for tree view - EventType eventType = Event.current.type; - if (eventType == EventType.ExecuteCommand || eventType == EventType.ValidateCommand) - { - bool execute = eventType == EventType.ExecuteCommand; - - int[] instanceIDs = m_FolderTree.GetSelection(); - if (instanceIDs.Length == 0) - return false; - - // Only one type can be selected at a time (and savedfilters can only be single-selected) - ItemType itemType = GetItemType(instanceIDs[0]); - - if (Event.current.commandName == EventCommandNames.Delete || Event.current.commandName == EventCommandNames.SoftDelete) - { - Event.current.Use(); - if (execute) - { - if (itemType == ItemType.SavedFilter) - { - System.Diagnostics.Debug.Assert(instanceIDs.Length == 1); //We do not support multiselection for filters - DeleteFilter(instanceIDs[0]); - EditorGUIUtility.ExitGUI(); // exit gui since we are iterating items we just reloaded - } - else if (itemType == ItemType.Asset) - { - bool askIfSure = Event.current.commandName == EventCommandNames.SoftDelete; - DeleteSelectedAssets(askIfSure); - if (askIfSure) - Focus(); // Workaround that we do not get focus back when dialog is closed - } - } - GUIUtility.ExitGUI(); - } - else if (Event.current.commandName == EventCommandNames.Duplicate) - { - if (execute) - { - if (itemType == ItemType.SavedFilter) - { - // TODO copy filter (get new name as assets) - } - else if (itemType == ItemType.Asset) - { - Event.current.Use(); - int[] copiedFolders = DuplicateFolders(instanceIDs); - SetFolderSelection(copiedFolders, true); - GUIUtility.ExitGUI(); - } - } - else - { - Event.current.Use(); - } - } - } - - return false; - } - - public const string FocusProjectWindowCommand = "FocusProjectWindow"; - - // Returns true if we should early out of OnGUI - bool HandleCommandEvents() - { - EventType eventType = Event.current.type; - if (eventType == EventType.ExecuteCommand || eventType == EventType.ValidateCommand) - { - bool execute = eventType == EventType.ExecuteCommand; - - if (Event.current.commandName == EventCommandNames.Delete || Event.current.commandName == EventCommandNames.SoftDelete) - { - Event.current.Use(); - if (execute) - { - bool askIfSure = Event.current.commandName == EventCommandNames.SoftDelete; - DeleteSelectedAssets(askIfSure); - if (askIfSure) - Focus(); // Workaround that we do not get focus back when dialog is closed - } - GUIUtility.ExitGUI(); - } - else if (Event.current.commandName == EventCommandNames.Duplicate) - { - if (execute) - { - Event.current.Use(); - ProjectWindowUtil.DuplicateSelectedAssets(); - GUIUtility.ExitGUI(); - } - else - { - Object[] selectedAssets = Selection.GetFiltered(typeof(Object), SelectionMode.Assets); - if (selectedAssets.Length != 0) - Event.current.Use(); - } - } - else if (Event.current.commandName == FocusProjectWindowCommand) - { - if (execute) - { - FrameObjectPrivate(Selection.activeInstanceID, true, false); - Event.current.Use(); - Focus(); - GUIUtility.ExitGUI(); - } - else - { - Event.current.Use(); - } - } - else if (Event.current.commandName == EventCommandNames.SelectAll) - { - if (execute) - SelectAll(); - Event.current.Use(); - } - // Frame selected assets - else if (Event.current.commandName == EventCommandNames.FrameSelected) - { - if (execute) - { - FrameObjectPrivate(Selection.activeInstanceID, true, false); - Event.current.Use(); - GUIUtility.ExitGUI(); - } - Event.current.Use(); - } - else if (Event.current.commandName == EventCommandNames.Find) - { - if (execute) - m_FocusSearchField = true; - Event.current.Use(); - } - } - return false; - } - - void SelectAll() - { - if (m_ViewMode == ViewMode.OneColumn) - { - if (m_SearchFilter.IsSearching()) - { - m_ListArea.SelectAll(); - } - else - { - int[] instanceIDs = m_AssetTree.GetRowIDs(); - m_AssetTree.SetSelection(instanceIDs, false); - AssetTreeSelectionCallback(instanceIDs); - } - } - else if (m_ViewMode == ViewMode.TwoColumns) - { - m_ListArea.SelectAll(); - } - else - { - Debug.LogError("Missing implementation for ViewMode " + m_ViewMode); - } - } - - void RefreshSplittedSelectedPath() - { - if (s_Styles == null) - s_Styles = new Styles(); - - m_SelectedPathSplitted.Clear(); - - if (String.IsNullOrEmpty(m_SelectedPath)) - { - m_SelectedPathSplitted.Add(new GUIContent()); - } - else - { - string displayPath = m_SelectedPath; - if (m_SelectedPath.StartsWith("assets/", StringComparison.CurrentCultureIgnoreCase)) - displayPath = m_SelectedPath.Substring("assets/".Length); - - if (m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing) - { - m_SelectedPathSplitted.Add(new GUIContent(Path.GetFileName(m_SelectedPath), AssetDatabase.GetCachedIcon(m_SelectedPath))); - } - else - { - float availableWidth = position.width - m_DirectoriesAreaWidth - k_SliderWidth - 16f; - Vector2 stringSize = s_Styles.selectedPathLabel.CalcSize(GUIContent.Temp(displayPath)); - if (stringSize.x + 25f > availableWidth) - { - /* - // Full path to subassets - IHierarchyProperty activeSelectedInHierachy = new HierarchyProperty (HierarchyType.Assets); - activeSelectedInHierachy.Find (m_ListAreaState.m_LastClickedInstanceID, null); - do - { - m_SelectedPathSplitted.Add (new GUIContent (activeSelectedInHierachy.name, activeSelectedInHierachy.icon)); - } - while (activeSelectedInHierachy.Parent()); - m_SelectedPathSplitted.Reverse (); - */ - - string[] split = displayPath.Split('/'); - string curPath = "Assets/"; - for (int i = 0; i < split.Length; ++i) - { - curPath += split[i]; - Texture icon = AssetDatabase.GetCachedIcon(curPath); - - m_SelectedPathSplitted.Add(new GUIContent(split[i], icon)); - curPath += "/"; - } - } - else - { - m_SelectedPathSplitted.Add(new GUIContent(displayPath, AssetDatabase.GetCachedIcon(m_SelectedPath))); - } - } - } - } - - float GetBottomBarHeight() - { - if (m_SelectedPathSplitted.Count == 0) - RefreshSplittedSelectedPath(); - - // Only show bottom bar in one column mode when searching - if (m_ViewMode == ViewMode.OneColumn && !m_SearchFilter.IsSearching()) - return 0f; - - return k_BottomBarHeight * m_SelectedPathSplitted.Count; - } - - float GetListHeaderHeight() - { - return m_SearchFilter.GetState() == SearchFilter.State.EmptySearchFilter ? 0f : EditorGUI.kWindowToolbarHeight + 1; - } - - void CalculateRects() - { - float bottomBarHeight = GetBottomBarHeight(); - float listHeaderHeight = GetListHeaderHeight(); - if (m_ViewMode == ViewMode.OneColumn) - { - m_ListAreaRect = new Rect(0, m_ToolbarHeight + listHeaderHeight, position.width, position.height - m_ToolbarHeight - listHeaderHeight - bottomBarHeight); - m_TreeViewRect = new Rect(0, m_ToolbarHeight, position.width, position.height - m_ToolbarHeight - bottomBarHeight); - m_BottomBarRect = new Rect(0, position.height - bottomBarHeight, position.width, bottomBarHeight); - m_ListHeaderRect = new Rect(0, m_ToolbarHeight, position.width, listHeaderHeight); - } - else //if (m_ViewMode == ViewMode.TwoColumns) - { - float listWidth = position.width - m_DirectoriesAreaWidth; - - m_ListAreaRect = new Rect(m_DirectoriesAreaWidth, m_ToolbarHeight + listHeaderHeight, listWidth, position.height - m_ToolbarHeight - listHeaderHeight - bottomBarHeight); - m_TreeViewRect = new Rect(0, m_ToolbarHeight, m_DirectoriesAreaWidth, position.height - m_ToolbarHeight); - m_BottomBarRect = new Rect(m_DirectoriesAreaWidth, position.height - bottomBarHeight, listWidth, bottomBarHeight); - m_ListHeaderRect = new Rect(m_ListAreaRect.x, m_ToolbarHeight, m_ListAreaRect.width, listHeaderHeight); - } - } - - void EndPing() - { - if (m_ViewMode == ViewMode.OneColumn) - { - m_AssetTree.EndPing(); - } - else - { - m_FolderTree.EndPing(); - m_ListArea.EndPing(); - } - } - - void OnEvent() - { - // Let components handle new event - if (m_AssetTree != null) - m_AssetTree.OnEvent(); - - if (m_FolderTree != null) - m_FolderTree.OnEvent(); - - if (m_ListArea != null) - m_ListArea.OnEvent(); - } - - void OnGUI() - { - // Initialize m_Styles - if (s_Styles == null) - s_Styles = new Styles(); - - if (!Initialized()) - Init(); - - // We grab keyboard control ids early to ensure consistency (for focus rendering) - m_ListKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard); - m_TreeViewKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard); - - OnEvent(); - - m_ToolbarHeight = EditorGUI.kWindowToolbarHeight + 1; - m_ItemSelectedByRightClickThisEvent = false; - - // Size splitterRects for different areas of the browser - ResizeHandling(position.width, position.height - m_ToolbarHeight); - CalculateRects(); - - Event evt = Event.current; - - Rect ProjectBrowserRect = new Rect(0, 0, position.width, position.height); - if (evt.type == EventType.MouseDown && ProjectBrowserRect.Contains(evt.mousePosition)) - { - EndPing(); - SetAsLastInteractedProjectBrowser(); - } - - if (m_GrabKeyboardFocusForListArea) - { - m_GrabKeyboardFocusForListArea = false; - GUIUtility.keyboardControl = m_ListKeyboardControlID; - } - - GUI.BeginGroup(ProjectBrowserRect, GUIContent.none); - - TopToolbar(); - BottomBar(); - - if (m_ViewMode == ViewMode.OneColumn) - { - if (m_SearchFilter.IsSearching()) - { - SearchAreaBar(); - if (GUIUtility.keyboardControl == m_TreeViewKeyboardControlID) - GUIUtility.keyboardControl = m_ListKeyboardControlID; // AssetTree is not shown so we can steal keyboard control - m_ListArea.OnGUI(m_ListAreaRect, m_ListKeyboardControlID); - } - else - { - if (GUIUtility.keyboardControl == m_ListKeyboardControlID) - GUIUtility.keyboardControl = m_TreeViewKeyboardControlID; // List is not shown so we can steal keyboard control - m_AssetTree.OnGUI(m_TreeViewRect, m_TreeViewKeyboardControlID); - } - } - else // ViewMode.TwoColumns - { - if (m_SearchFilter.IsSearching()) - SearchAreaBar(); - else - BreadCrumbBar(); - - // Folders - m_FolderTree.OnGUI(m_TreeViewRect, m_TreeViewKeyboardControlID); - - // Vertical splitter line between folders and content (drawn before listarea so listarea ping is drawn on top of line) - EditorGUIUtility.DrawHorizontalSplitter(new Rect(m_ListAreaRect.x, m_ToolbarHeight, 1, m_TreeViewRect.height)); - - // List Content - m_ListArea.OnGUI(m_ListAreaRect, m_ListKeyboardControlID); - - if (m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing && m_ListArea.numItemsDisplayed == 0) - { - Vector2 size = EditorStyles.label.CalcSize(s_Styles.m_EmptyFolderText); - 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); - using (new EditorGUI.DisabledScope(true)) - { - GUI.Label(textRect, s_Styles.m_EmptyFolderText, EditorStyles.label); - } - } - } - - // Handle ListArea context click after ListArea.OnGUI - HandleContextClickInListArea(m_ListAreaRect); - - // Ensure we save current grid size - if (m_ListArea.gridSize != m_StartGridSize) - { - m_StartGridSize = m_ListArea.gridSize; - if (m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing) - m_LastFoldersGridSize = m_ListArea.gridSize; - } - - GUI.EndGroup(); - - if (m_ViewMode == ViewMode.TwoColumns) - useTreeViewSelectionInsteadOfMainSelection = GUIUtility.keyboardControl == m_TreeViewKeyboardControlID; - - // Handle command events AFTER tree and list view since commands events should be handled by text fields first (rename overlay + search field) - // Let folder/filters tree view try to handle command events first if it has keyboard focus - if (m_ViewMode == ViewMode.TwoColumns && GUIUtility.keyboardControl == m_TreeViewKeyboardControlID) - HandleCommandEventsForTreeView(); - HandleCommandEvents(); - } - - void HandleContextClickInListArea(Rect listRect) - { - Event evt = Event.current; - - switch (evt.type) - { - case EventType.MouseDown: - // This section handles selecting the folders showing their content, if right clicked outside items. - // We do this to ensure our assets context menu is operating on the active folder(s) - if (m_ViewMode == ViewMode.TwoColumns && m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing && evt.button == 1 && !m_ItemSelectedByRightClickThisEvent) - { - if (m_SearchFilter.folders.Length > 0 && listRect.Contains(evt.mousePosition)) - { - m_InternalSelectionChange = true; - Selection.instanceIDs = GetFolderInstanceIDs(m_SearchFilter.folders); - } - } - break; - - case EventType.ContextClick: - if (listRect.Contains(evt.mousePosition)) - { - GUIUtility.hotControl = 0; - // Context click in list area (can be an asset store asset or a local asset) - if (AssetStoreAssetSelection.GetFirstAsset() != null) - AssetStoreItemContextMenu.Show(); - else - EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), "Assets/", null); - - evt.Use(); - } - break; - } - } - - void AssetTreeViewContextClick(int clickedItemID) - { - Event evt = Event.current; - - // Context click with a selected Asset - EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), "Assets/", null); - - evt.Use(); - } - - void AssetTreeViewContextClickOutsideItems() - { - Event evt = Event.current; - - // Deselect all - if (m_AssetTree.GetSelection().Length > 0) - { - int[] newSelection = new int[0]; - m_AssetTree.SetSelection(newSelection, false); - AssetTreeSelectionCallback(newSelection); - } - - // Context click with no selected assets - EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), "Assets/", null); - - evt.Use(); - } - - void FolderTreeViewContextClick(int clickedItemID) - { - Event evt = Event.current; - System.Diagnostics.Debug.Assert(evt.type == EventType.ContextClick); - if (SavedSearchFilters.IsSavedFilter(clickedItemID)) - { - // Context click with a selected Filter - if (clickedItemID != SavedSearchFilters.GetRootInstanceID()) - SavedFiltersContextMenu.Show(clickedItemID); - } - else - { - // Context click on a folder (asset) - EditorUtility.DisplayPopupMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), "Assets/", null); - } - evt.Use(); - } - - void AssetTreeDragEnded(int[] draggedInstanceIds, bool draggedItemsFromOwnTreeView) - { - // We only change selection if 'draggedItemsFromOwnTreeView' == true. - // This ensures that we do not override the selection that might have been set before - // calling this callback when dragging e.g a gameobject to the projectbrowser (case 628939) - if (draggedInstanceIds != null && draggedItemsFromOwnTreeView) - { - m_AssetTree.SetSelection(draggedInstanceIds, true); - m_AssetTree.NotifyListenersThatSelectionChanged(); // behave as if selection was performed in treeview - Repaint(); - GUIUtility.ExitGUI(); - } - } - - void FolderTreeDragEnded(int[] draggedInstanceIds, bool draggedItemsFromOwnTreeView) - { - // In the folder tree we do not want to change selection as we do in the full asset tree when dragging is performed. - // We do not want to change folder when dragging assets to folders (convention of both OSX and Win) - } - - // This is our search field - void TopToolbar() - { - GUILayout.BeginArea(new Rect(0, 0, position.width, m_ToolbarHeight)); - - GUILayout.BeginHorizontal(EditorStyles.toolbar); - { - float listWidth = position.width - m_DirectoriesAreaWidth; - float spaceBetween = 4f; - bool compactMode = listWidth < 500; // We need quite some space for filtering text - if (!compactMode) - { - spaceBetween = 10f; - } - - CreateDropdown(); - GUILayout.FlexibleSpace(); - - GUILayout.Space(spaceBetween * 2f); - SearchField(); - GUILayout.Space(spaceBetween); - TypeDropDown(); - AssetLabelsDropDown(); - if (m_ViewMode == ViewMode.TwoColumns) - { - ButtonSaveFilter(); - } - } - GUILayout.EndHorizontal(); - GUILayout.EndArea(); - } - - void SetOneColumn() - { - SetViewMode(ViewMode.OneColumn); - } - - void SetTwoColumns() - { - SetViewMode(ViewMode.TwoColumns); - EnsureValidSetup(); - } - - internal bool IsTwoColumns() - { - return m_ViewMode == ViewMode.TwoColumns; - } - - void OpenTreeViewTestWindow() - { - GetWindow(); - } - - void ToggleExpansionAnimationPreference() - { - bool oldValue = EditorPrefs.GetBool(TreeViewController.kExpansionAnimationPrefKey, false); - EditorPrefs.SetBool(TreeViewController.kExpansionAnimationPrefKey, !oldValue); - InternalEditorUtility.RequestScriptReload(); - } - - void ToggleShowPackagesInAssetsFolder() - { - bool showPackagesInAssetsFolder = EditorPrefs.GetBool("ShowPackagesFolder", false); - EditorPrefs.SetBool("ShowPackagesFolder", !showPackagesInAssetsFolder); - OnProjectChanged(); - } - - - public virtual void AddItemsToMenu(GenericMenu menu) - { - if (m_EnableOldAssetTree) - { - GUIContent assetTreeText = EditorGUIUtility.TrTextContent("One Column Layout"); - GUIContent assetBrowserText = EditorGUIUtility.TrTextContent("Two Column Layout"); - - menu.AddItem(assetTreeText, m_ViewMode == ViewMode.OneColumn, SetOneColumn); - if (position.width >= k_MinWidthTwoColumns) - menu.AddItem(assetBrowserText, m_ViewMode == ViewMode.TwoColumns, SetTwoColumns); - else - menu.AddDisabledItem(assetBrowserText); - - m_LockTracker.AddItemsToMenu(menu); - - if (Unsupported.IsDeveloperMode()) - { - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Show Packages in Project Window"), EditorPrefs.GetBool("ShowPackagesFolder", false), ToggleShowPackagesInAssetsFolder); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Open TreeView Test Window..."), false, OpenTreeViewTestWindow); - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Use TreeView Expansion Animation"), EditorPrefs.GetBool(TreeViewController.kExpansionAnimationPrefKey, false), ToggleExpansionAnimationPreference); - } - } - } - - float DrawLocalAssetHeader(Rect r) - { - return 0; - } - - void ResizeHandling(float width, float height) - { - if (m_ViewMode == ViewMode.OneColumn) - return; - - // Handle folders vs. items splitter - Rect dragRect = new Rect(m_DirectoriesAreaWidth, m_ToolbarHeight, k_ResizerWidth, height); - dragRect = EditorGUIUtility.HandleHorizontalSplitter(dragRect, position.width, k_MinDirectoriesAreaWidth, k_MinWidthTwoColumns - k_MinDirectoriesAreaWidth); - m_DirectoriesAreaWidth = dragRect.x; - - // Refresh selected path indicator for new width - float listWidth = position.width - m_DirectoriesAreaWidth; - if (listWidth != m_LastListWidth) - RefreshSplittedSelectedPath(); - m_LastListWidth = listWidth; - } - - void ButtonSaveFilter() - { - // Only show when we have a active filter - using (new EditorGUI.DisabledScope(!m_SearchFilter.IsSearching())) - { - if (GUILayout.Button(s_Styles.m_SaveFilterContent, EditorStyles.toolbarButton)) - { - ProjectBrowserColumnOneTreeViewGUI ProjectBrowserTreeViewGUI = m_FolderTree.gui as ProjectBrowserColumnOneTreeViewGUI; - if (ProjectBrowserTreeViewGUI != null) - { - bool createNewFilter = true; - // If a filter is selected save to that filter - int[] treeViewSelection = m_FolderTree.GetSelection(); - if (treeViewSelection.Length == 1) - { - int instanceID = treeViewSelection[0]; - bool isRootFilter = SavedSearchFilters.GetRootInstanceID() == instanceID; - - // Ask if filter should be overwritten - if (SavedSearchFilters.IsSavedFilter(instanceID) && !isRootFilter) - { - createNewFilter = false; - string title = "Overwrite Filter?"; - string text = "Do you want to overwrite '" + SavedSearchFilters.GetName(instanceID) + "' or create a new filter?"; - int result = 2; // cancel - result = EditorUtility.DisplayDialogComplex(title, text, "Overwrite", "Create", "Cancel"); - if (result == 0) - SavedSearchFilters.UpdateExistingSavedFilter(instanceID, m_SearchFilter, listAreaGridSize); - else if (result == 1) - createNewFilter = true; - } - } - - // Otherwise create new item in tree - if (createNewFilter) - { - // 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) - Focus(); - ProjectBrowserTreeViewGUI.BeginCreateSavedFilter(m_SearchFilter); - } - } - } - } - } - - void CreateDropdown() - { - Rect r = GUILayoutUtility.GetRect(s_Styles.m_CreateDropdownContent, EditorStyles.toolbarDropDown); - if (EditorGUI.DropdownButton(r, s_Styles.m_CreateDropdownContent, FocusType.Passive, EditorStyles.toolbarDropDown)) - { - GUIUtility.hotControl = 0; - EditorUtility.DisplayPopupMenu(r, "Assets/Create", null); - } - } - - void AssetLabelsDropDown() - { - // Labels button - Rect r = GUILayoutUtility.GetRect(s_Styles.m_FilterByLabel, EditorStyles.toolbarButton); - if (EditorGUI.DropdownButton(r, s_Styles.m_FilterByLabel, FocusType.Passive, EditorStyles.toolbarButton)) - { - PopupWindow.Show(r, new PopupList(m_AssetLabels), null, ShowMode.PopupMenuWithKeyboardFocus); - } - } - - void TypeDropDown() - { - // Object type button - Rect r = GUILayoutUtility.GetRect(s_Styles.m_FilterByType, EditorStyles.toolbarButton); - if (EditorGUI.DropdownButton(r, s_Styles.m_FilterByType, FocusType.Passive, EditorStyles.toolbarButton)) - { - PopupWindow.Show(r, new PopupList(m_ObjectTypes)); - } - } - - void SearchField() - { - Rect rect = GUILayoutUtility.GetRect(0, EditorGUILayout.kLabelFloatMaxW * 1.5f, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchField, GUILayout.MinWidth(65), GUILayout.MaxWidth(300)); - 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. - - if (m_FocusSearchField) - { - GUIUtility.keyboardControl = searchFieldControlID; - EditorGUIUtility.editingTextField = true; - if (Event.current.type == EventType.Repaint) - m_FocusSearchField = false; - } - - // On arrow down/up swicth to control selection in list area - Event evt = Event.current; - if (evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.DownArrow || evt.keyCode == KeyCode.UpArrow)) - { - if (GUIUtility.keyboardControl == searchFieldControlID) - { - if (!m_ListArea.IsLastClickedItemVisible()) - m_ListArea.SelectFirst(); - - GUIUtility.keyboardControl = m_ListKeyboardControlID; - evt.Use(); - } - } - - string searchFilter = EditorGUI.ToolbarSearchField(searchFieldControlID, rect, m_SearchFieldText, false); - if (searchFilter != m_SearchFieldText || m_FocusSearchField) - { - // Update filter with string - m_SearchFieldText = searchFilter; - m_SearchFilter.SearchFieldStringToFilter(m_SearchFieldText); - SyncFilterGUI(); - TopBarSearchSettingsChanged(); - Repaint(); - } - } - - void TopBarSearchSettingsChanged() - { - if (!m_SearchFilter.IsSearching()) - { - if (m_DidSelectSearchResult) - { - m_DidSelectSearchResult = false; - FrameObjectPrivate(Selection.activeInstanceID, true, false); - if (GUIUtility.keyboardControl == 0) - { - // Ensure item has focus for visual feedback and instant key navigation - if (m_ViewMode == ViewMode.OneColumn) - GUIUtility.keyboardControl = m_TreeViewKeyboardControlID; - else if (m_ViewMode == ViewMode.TwoColumns) - GUIUtility.keyboardControl = m_ListKeyboardControlID; - } - } - else if (m_ViewMode == ViewMode.TwoColumns) - { - // Revert to last selected folders - if (GUIUtility.keyboardControl == 0 && m_LastFolders != null && m_LastFolders.Length > 0) - { - m_SearchFilter.folders = m_LastFolders; - SetFolderSelection(GetFolderInstanceIDs(m_LastFolders), true); - } - } - } - else - { - InitSearchMenu(); - } - - InitListArea(); - } - - static int[] GetFolderInstanceIDs(string[] folders) - { - int[] folderInstanceIDs = new int[folders.Length]; - for (int i = 0; i < folders.Length; ++i) - folderInstanceIDs[i] = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(folders[i]); - return folderInstanceIDs; - } - - static string[] GetFolderPathsFromInstanceIDs(int[] instanceIDs) - { - List paths = new List(); - foreach (int instanceID in instanceIDs) - { - string path = AssetDatabase.GetAssetPath(instanceID); - if (!String.IsNullOrEmpty(path)) - paths.Add(path); - } - return paths.ToArray(); - } - - void ClearSearch() - { - m_SearchFilter.ClearSearch(); - - // Clear GUI - m_SearchFieldText = ""; - m_AssetLabels.DeselectAll(); - m_ObjectTypes.DeselectAll(); - m_DidSelectSearchResult = false; - } - - void FolderTreeSelectionChanged(bool folderWasSelected) - { - if (folderWasSelected) - { - SearchViewState state = GetSearchViewState(); - if (state == SearchViewState.AllAssets || state == SearchViewState.AssetStore) - { - // Clear all except folders if folder is set - string[] folders = m_SearchFilter.folders; - ClearSearch(); - m_SearchFilter.folders = folders; - - // Ensures that when selecting folders we start local asset search next time we search - m_SearchFilter.searchArea = m_LastLocalAssetsSearchArea; - } - - m_LastFolders = m_SearchFilter.folders; - } - - RefreshSearchText(); - InitListArea(); - } - - void IconSizeSlider(Rect r) - { - // Slider - EditorGUI.BeginChangeCheck(); - int newGridSize = (int)GUI.HorizontalSlider(r, m_ListArea.gridSize, m_ListArea.minGridSize, m_ListArea.maxGridSize); - if (EditorGUI.EndChangeCheck()) - { - AssetStorePreviewManager.AbortSize(m_ListArea.gridSize); - m_ListArea.gridSize = newGridSize; - } - } - - void SearchAreaBar() - { - // Background - GUI.Label(m_ListHeaderRect, GUIContent.none, s_Styles.topBarBg); - - const float kMargin = 5f; - Rect rect = m_ListHeaderRect; - rect.x += kMargin; - rect.width -= 2 * kMargin; - rect.y += 1; - - GUIStyle style = EditorStyles.boldLabel; - - GUI.Label(rect, s_Styles.m_SearchIn, style); - if (m_SearchAreaMenuOffset < 0f) - m_SearchAreaMenuOffset = style.CalcSize(s_Styles.m_SearchIn).x; - - rect.x += m_SearchAreaMenuOffset + 7f; - rect.width -= m_SearchAreaMenuOffset + 7f; - - rect.width = m_SearchAreaMenu.OnGUI(rect); - } - - void BreadCrumbBar() - { - if (m_ListHeaderRect.height <= 0f) - return; - - if (m_SearchFilter.folders.Length == 0) - return; - - Event evt = Event.current; - - // Give keyboard focus to list area if we mouse down in breadcrumbs - if (evt.type == EventType.MouseDown && m_ListHeaderRect.Contains(evt.mousePosition)) - { - GUIUtility.keyboardControl = m_ListKeyboardControlID; - Repaint(); - } - - if (m_BreadCrumbs.Count == 0) - { - string path = m_SearchFilter.folders[0]; - - string[] folderNames = path.Split('/'); - var packagesRoot = AssetDatabase.GetPackagesMountPoint(); - if (path.StartsWith(packagesRoot)) - { - // Translate the packages root mount point - folderNames = Regex.Replace(path, "^" + packagesRoot, AssetDatabase.GetPackagesMountPoint()).Split('/'); - } - string folderPath = ""; - - foreach (string folderName in folderNames) - { - if (!String.IsNullOrEmpty(folderPath)) - folderPath += "/"; - folderPath += folderName; - - m_BreadCrumbs.Add(new KeyValuePair(new GUIContent(folderName), folderPath)); - } - - m_BreadCrumbLastFolderHasSubFolders = AssetDatabase.GetSubFolders(path).Length > 0; - } - - // Background - GUI.Label(m_ListHeaderRect, GUIContent.none, s_Styles.topBarBg); - - // Folders - Rect rect = m_ListHeaderRect; - rect.y += 1; - rect.x += 4; - if (m_SearchFilter.folders.Length == 1) - { - for (int i = 0; i < m_BreadCrumbs.Count; ++i) - { - bool lastElement = i == m_BreadCrumbs.Count - 1; - GUIStyle style = lastElement ? EditorStyles.boldLabel : EditorStyles.label; //EditorStyles.miniBoldLabel : EditorStyles.miniLabel;// - GUIContent folderContent = m_BreadCrumbs[i].Key; - string folderPath = m_BreadCrumbs[i].Value; - Vector2 size = style.CalcSize(folderContent); - rect.width = size.x; - if (GUI.Button(rect, folderContent, style)) - { - ShowFolderContents(AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(folderPath), false); - } - - rect.x += size.x + 3f; - if (!lastElement || m_BreadCrumbLastFolderHasSubFolders) - { - Rect buttonRect = new Rect(rect.x, rect.y + 2, 13, 13); - if (EditorGUI.DropdownButton(buttonRect, GUIContent.none, FocusType.Passive, s_Styles.foldout)) - { - string currentSubFolder = ""; - if (!lastElement) - currentSubFolder = m_BreadCrumbs[i + 1].Value; - BreadCrumbListMenu.Show(folderPath, currentSubFolder, buttonRect, this); - } - } - rect.x += 11f; - } - } - else if (m_SearchFilter.folders.Length > 1) - { - GUI.Label(rect, GUIContent.Temp("Showing multiple folders..."), EditorStyles.miniLabel); - } - } - - void BottomBar() - { - if (m_BottomBarRect.height == 0f) - return; - - Rect rect = m_BottomBarRect; - - // Background - GUI.Label(rect, GUIContent.none, s_Styles.bottomBarBg); - - Rect sliderRect = new Rect(rect.x + rect.width - k_SliderWidth - 16f, rect.y + rect.height - 17f, k_SliderWidth, 17f); - IconSizeSlider(sliderRect); - - // File path - EditorGUIUtility.SetIconSize(new Vector2(16, 16)); // If not set we see icons scaling down if text is being cropped - const float k_Margin = 2; - rect.width -= k_Margin * 2; - rect.x += k_Margin; - rect.height = k_BottomBarHeight; - for (int i = m_SelectedPathSplitted.Count - 1; i >= 0; --i) - { - if (i == 0) - rect.width = rect.width - k_SliderWidth - 14f; - GUI.Label(rect, m_SelectedPathSplitted[i], s_Styles.selectedPathLabel); - rect.y += k_BottomBarHeight; - } - EditorGUIUtility.SetIconSize(new Vector2(0, 0)); - } - - void SelectAssetsFolder() - { - ShowFolderContents(ProjectBrowserColumnOneTreeViewDataSource.GetAssetsFolderInstanceID(), true); - } - - string ValidateCreateNewAssetPath(string pathName) - { - // Normally we create assets relative to current selected asset. If no asset is selected we normally create the asset in the root folder (Assets) - // but in two column mode we want to create the asset in the currently shown folder if no asset is selected. (fix case 550484) - if (m_ViewMode == ViewMode.TwoColumns && m_SearchFilter.GetState() == SearchFilter.State.FolderBrowsing && m_SearchFilter.folders.Length > 0) - { - // Ensure pathName is not already a full asset path - if (!pathName.StartsWith("assets/", StringComparison.CurrentCultureIgnoreCase)) - { - // If no assets are selected we use first currently shown folder path - if (Selection.GetFiltered(typeof(Object), SelectionMode.Assets).Length == 0) - { - pathName = Path.Combine(m_SearchFilter.folders[0], pathName); - pathName = pathName.Replace("\\", "/"); - } - } - } - return pathName; - } - - internal void BeginPreimportedNameEditing(int instanceID, EndNameEditAction endAction, string pathName, Texture2D icon, string resourceFile) - { - if (!Initialized()) - Init(); - - // End any rename that might be active, this will also end any asset currently being created - EndRenaming(); - - bool isCreatingNewFolder = endAction is DoCreateFolder; - - if (m_ViewMode == ViewMode.TwoColumns) - { - if (m_SearchFilter.GetState() != SearchFilter.State.FolderBrowsing) - { - // Force select the Assets folder as default when no folders are selected - SelectAssetsFolder(); - } - - pathName = ValidateCreateNewAssetPath(pathName); - - if (m_ListAreaState.m_CreateAssetUtility.BeginNewAssetCreation(instanceID, endAction, pathName, icon, resourceFile)) - { - ShowFolderContents(AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(m_ListAreaState.m_CreateAssetUtility.folder), true); - m_ListArea.BeginNamingNewAsset(m_ListAreaState.m_CreateAssetUtility.originalName, instanceID, isCreatingNewFolder); - } - } - else if (m_ViewMode == ViewMode.OneColumn) - { - // If search is active put new asset under selected folder otherwise in Assets - if (m_SearchFilter.IsSearching()) - { - ClearSearch(); - } - - // Create in tree - AssetsTreeViewGUI defaultTreeViewGUI = m_AssetTree.gui as AssetsTreeViewGUI; - if (defaultTreeViewGUI != null) - defaultTreeViewGUI.BeginCreateNewAsset(instanceID, endAction, pathName, icon, resourceFile); - else - Debug.LogError("Not valid defaultTreeViewGUI!"); - } - } - - public void FrameObject(int instanceID, bool ping) - { - bool frame = !m_LockTracker.isLocked && (ping || ShouldFrameAsset(instanceID)); - FrameObjectPrivate(instanceID, frame, ping); - if (s_LastInteractedProjectBrowser == this) - { - m_GrabKeyboardFocusForListArea = true; - } - } - - private void FrameObjectPrivate(int instanceID, bool frame, bool ping) - { - if (instanceID == 0 || m_ListArea == null) - return; - - // If framing the same instance as the last one we do not remove the ping - // since issuing first a ping and then a framing should still show the ping. - if (m_LastFramedID != instanceID) - EndPing(); - m_LastFramedID = instanceID; - - ClearSearch(); - - if (m_ViewMode == ViewMode.TwoColumns) - { - FrameObjectInTwoColumnMode(instanceID, frame, ping); - } - else if (m_ViewMode == ViewMode.OneColumn) - { - // Clear search to switch back to tree view - m_AssetTree.Frame(instanceID, frame, ping); - } - } - - private void FrameObjectInTwoColumnMode(int instanceID, bool frame, bool ping) - { - int folderInstanceID = 0; - - string assetPath = AssetDatabase.GetAssetPath(instanceID); - if (!String.IsNullOrEmpty(assetPath)) - { - string containingFolder = ProjectWindowUtil.GetContainingFolder(assetPath); - if (!String.IsNullOrEmpty(containingFolder)) - folderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(containingFolder); - - if (folderInstanceID == 0) - folderInstanceID = ProjectBrowserColumnOneTreeViewDataSource.GetAssetsFolderInstanceID(); - } - - // Could be a scene gameobject - if (folderInstanceID != 0) - { - m_FolderTree.Frame(folderInstanceID, frame, ping); - if (frame) - ShowFolderContents(folderInstanceID, true); - m_ListArea.Frame(instanceID, frame, ping); - } - } - - // Also called from C++ (used for AssetSelection overriding) - static int[] GetTreeViewFolderSelection() - { - // Since we can delete entire folder hierarchies with the returned selection we need to be very careful. We therefore require the following: - // - The folder/favorite tree view must have keyboard focus - // Note we cannot require window focus (focusedWindow) since on OSX window focus is lost to popup window when right clicking - ProjectBrowser ob = s_LastInteractedProjectBrowser; - - if (ob != null && ob.useTreeViewSelectionInsteadOfMainSelection && ob.m_FolderTree != null) - { - return s_LastInteractedProjectBrowser.m_FolderTree.GetSelection(); - } - - return new int[0]; - } - - public float listAreaGridSize - { - get { return m_ListArea.gridSize; } - } - - int GetProjectBrowserDebugID() - { - for (int i = 0; i < s_ProjectBrowsers.Count; ++i) - if (s_ProjectBrowsers[i] == this) - return i; - return -1; - } - - // FIXME: The validation logic is duplicated on the C++ side in CanDeleteSelectedAssets - // Keep these in sync for now - [UsedByNativeCode] - internal static void DeleteSelectedAssets(bool askIfSure) - { - int[] treeViewSelection = GetTreeViewFolderSelection(); - - List instanceIDs; - if (treeViewSelection.Length > 0) - instanceIDs = new List(treeViewSelection); - else - instanceIDs = new List(Selection.instanceIDs); - - if (instanceIDs.Count == 0) - return; - - ProjectWindowUtil.DeleteAssets(instanceIDs, askIfSure); - - // Ensure selection is cleared since StopAssetEditing() will restore selection from a backup saved in StartAssetEditing. - Selection.instanceIDs = new int[0]; - } - - [UsedByNativeCode] - internal static void RenameSelectedAssets() - { - ProjectBrowser ob = s_LastInteractedProjectBrowser; - if (ob != null) - { - if (ob.useTreeViewSelectionInsteadOfMainSelection && ob.m_FolderTree != null) - { - ob.m_FolderTree.BeginNameEditing(0f); - } - else if (ob.m_ViewMode == ViewMode.OneColumn && ob.m_AssetTree != null) - { - ob.m_AssetTree.BeginNameEditing(0f); - } - else if (ob.m_ViewMode == ViewMode.TwoColumns && ob.m_ListArea != null) - { - ob.m_ListArea.BeginRename(0f); - } - else - { - return; - } - - ob.Repaint(); - } - } - - internal IHierarchyProperty GetHierarchyPropertyUsingFilter(string textFilter) - { - FilteredHierarchy filteredHierarchy = new FilteredHierarchy(HierarchyType.Assets); - filteredHierarchy.searchFilter = SearchFilter.CreateSearchFilterFromString(textFilter); - IHierarchyProperty property = FilteredHierarchyProperty.CreateHierarchyPropertyForFilter(filteredHierarchy); - return property; - } - - internal void ShowObjectsInList(int[] instanceIDs) - { - if (!Initialized()) - Init(); - - if (m_ViewMode == ViewMode.TwoColumns) - { - m_ListArea.ShowObjectsInList(instanceIDs); - m_FolderTree.SetSelection(new int[0], false); // Remove selection from folder tree since we show custom list (press F to focus) - } - else if (m_ViewMode == ViewMode.OneColumn) - { - foreach (int instanceID in Selection.instanceIDs) - m_AssetTree.Frame(instanceID, true, false); - } - } - - static void ShowSelectedObjectsInLastInteractedProjectBrowser() - { - // Only one ProjectBrowser can have focus at a time so if we find one just return that one - if (s_LastInteractedProjectBrowser != null) - { - int[] instanceIDs = Selection.instanceIDs; - s_LastInteractedProjectBrowser.ShowObjectsInList(instanceIDs); - } - } - - // Called from DockArea - protected virtual void ShowButton(Rect r) - { - if (s_Styles == null) - s_Styles = new Styles(); - - m_LockTracker.ShowButton(r, s_Styles.lockButton); - } - - internal class SavedFiltersContextMenu - { - int m_SavedFilterInstanceID; - - static internal void Show(int savedFilterInstanceID) - { - // Curve context menu - GUIContent delete = EditorGUIUtility.TrTextContent("Delete"); - - GenericMenu menu = new GenericMenu(); - menu.AddItem(delete, false, new SavedFiltersContextMenu(savedFilterInstanceID).Delete); - - menu.ShowAsContext(); - } - - private SavedFiltersContextMenu(int savedFilterInstanceID) - { - m_SavedFilterInstanceID = savedFilterInstanceID; - } - - private void Delete() - { - DeleteFilter(m_SavedFilterInstanceID); - } - } - - internal class BreadCrumbListMenu - { - static ProjectBrowser m_Caller; - string m_SubFolder; - - static internal void Show(string folder, string currentSubFolder, Rect activatorRect, ProjectBrowser caller) - { - m_Caller = caller; - - // List of sub folders - string[] subFolders = AssetDatabase.GetSubFolders(folder); - GenericMenu menu = new GenericMenu(); - if (subFolders.Length >= 0) - { - currentSubFolder = Path.GetFileName(currentSubFolder); - foreach (string subFolderPath in subFolders) - { - string subFolderName = Path.GetFileName(subFolderPath); - menu.AddItem(new GUIContent(subFolderName), subFolderName == currentSubFolder, new BreadCrumbListMenu(subFolderPath).SelectSubFolder); - menu.ShowAsContext(); - } - } - else - { - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("No sub folders...")); - } - - menu.DropDown(activatorRect); - } - - private BreadCrumbListMenu(string subFolder) - { - m_SubFolder = subFolder; - } - - private void SelectSubFolder() - { - int folderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(m_SubFolder); - if (folderInstanceID != 0) - m_Caller.ShowFolderContents(folderInstanceID, false); - } - } - - internal class AssetStoreItemContextMenu - { - static internal void Show() - { - GenericMenu menu = new GenericMenu(); - - GUIContent assetStoreWindow = EditorGUIUtility.TrTextContent("Show in Asset Store window"); - AssetStoreAsset activeAsset = AssetStoreAssetSelection.GetFirstAsset(); - if (activeAsset != null && activeAsset.id != 0) - menu.AddItem(assetStoreWindow, false, new AssetStoreItemContextMenu().OpenAssetStoreWindow); - else - menu.AddDisabledItem(assetStoreWindow); - - menu.ShowAsContext(); - } - - private void OpenAssetStoreWindow() - { - AssetStoreAsset activeAsset = AssetStoreAssetSelection.GetFirstAsset(); - if (activeAsset != null) - AssetStoreAssetInspector.OpenItemInAssetStore(activeAsset); - } - - private AssetStoreItemContextMenu() - { - } - } - } -} diff --git a/Editor/Mono/ProjectBrowser/SavedSearchFilter.cs b/Editor/Mono/ProjectBrowser/SavedSearchFilter.cs deleted file mode 100644 index 7e3a610641..0000000000 --- a/Editor/Mono/ProjectBrowser/SavedSearchFilter.cs +++ /dev/null @@ -1,547 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using UnityEditor.IMGUI.Controls; -using UnityEngine; -using UnityEditorInternal; -using UnityEditor.Collaboration; -using Object = UnityEngine.Object; - - -namespace UnityEditor -{ - [System.Serializable] - internal class SavedFilter - { - public string m_Name; - public int m_Depth; // Can be used for tree view representation - public float m_PreviewSize = -1f; // if -1f then preview size is not applied when set - public int m_ID; - public SearchFilter m_Filter; - - public SavedFilter(string name, SearchFilter filter, int depth, float previewSize) - { - m_Name = name; - m_Depth = depth; - m_Filter = filter; - m_PreviewSize = previewSize; - } - } - - - [FilePathAttribute("SearchFilters", FilePathAttribute.Location.PreferencesFolder)] - internal class SavedSearchFilters : ScriptableSingleton - { - // The order if this list is the order they will be shown in the UI - [SerializeField] - List m_SavedFilters; - - // Callback when saved filters have changed - System.Action m_SavedFiltersChanged; - // Callback when saved filters have been initialized - System.Action m_SavedFiltersInitialized; - bool m_AllowHierarchy = false; - - // -------------------- - // Static interface - - // returns is instanceID given to the SavedFilter - public static int AddSavedFilter(string displayName, SearchFilter filter, float previewSize) - { - int instanceID = instance.Add(displayName, filter, previewSize, GetRootInstanceID(), true); // using 0 adds filter after the root - return instanceID; - } - - public static int AddSavedFilterAfterInstanceID(string displayName, SearchFilter filter, float previewSize, int insertAfterID, bool addAsChild) - { - int instanceID = instance.Add(displayName, filter, previewSize, insertAfterID, addAsChild); - return instanceID; - } - - public static void RemoveSavedFilter(int instanceID) - { - instance.Remove(instanceID); - } - - public static bool IsSavedFilter(int instanceID) - { - return instance.IndexOf(instanceID) >= 0; - } - - public static int GetRootInstanceID() - { - return instance.GetRoot(); - } - - public static SearchFilter GetFilter(int instanceID) - { - SavedFilter sf = instance.Find(instanceID); - if (sf != null && sf.m_Filter != null) - return ObjectCopier.DeepClone(sf.m_Filter); - return null; - } - - public static int GetFilterInstanceID(string name, string searchFieldString) - { - if (instance.m_SavedFilters != null && instance.m_SavedFilters.Count > 0) - { - foreach (SavedFilter sf in instance.m_SavedFilters) - { - if ((string.IsNullOrEmpty(name) || sf.m_Name == name) && sf.m_Filter.FilterToSearchFieldString() == searchFieldString) - { - return sf.m_ID; - } - } - } - - return 0; - } - - public static float GetPreviewSize(int instanceID) - { - SavedFilter sf = instance.Find(instanceID); - if (sf != null) - return sf.m_PreviewSize; - return -1f; - } - - public static string GetName(int instanceID) - { - SavedFilter filter = instance.Find(instanceID); - if (filter != null) - return filter.m_Name; - - Debug.LogError("Could not find saved filter " + instanceID + " " + instance.ToString()); - return ""; - } - - public static void SetName(int instanceID, string name) - { - SavedFilter filter = instance.Find(instanceID); - if (filter != null) - { - filter.m_Name = name; - instance.Changed(); - } - else - Debug.LogError("Could not set name of saved filter " + instanceID + " " + instance.ToString()); - } - - public static void UpdateExistingSavedFilter(int instanceID, SearchFilter filter, float previewSize) - { - instance.UpdateFilter(instanceID, filter, previewSize); - } - - public static TreeViewItem ConvertToTreeView() - { - return instance.BuildTreeView(); - } - - public static void RefreshSavedFilters() - { - instance.Changed(); - } - - public static void AddChangeListener(System.Action callback) - { - instance.m_SavedFiltersChanged -= callback; // ensures its not added twice - instance.m_SavedFiltersChanged += callback; - } - - internal static void AddInitializedListener(System.Action callback) - { - instance.m_SavedFiltersInitialized -= callback; // ensures its not added twice - instance.m_SavedFiltersInitialized += callback; - } - - internal static void RemoveInitializedListener(System.Action callback) - { - instance.m_SavedFiltersInitialized -= callback; - } - - public static void MoveSavedFilter(int instanceID, int parentInstanceID, int targetInstanceID, bool after) - { - instance.Move(instanceID, parentInstanceID, targetInstanceID, after); - } - - public static bool CanMoveSavedFilter(int instanceID, int parentInstanceID, int targetInstanceID, bool after) - { - return instance.IsValidMove(instanceID, parentInstanceID, targetInstanceID, after); - } - - public static bool AllowsHierarchy() - { - return instance.m_AllowHierarchy; - } - - // ------------ - // Impl - - bool IsValidMove(int instanceID, int parentInstanceID, int targetInstanceID, bool after) - { - int index = IndexOf(instanceID); - int parentIndex = IndexOf(parentInstanceID); - int targetIndex = IndexOf(targetInstanceID); - - if (index < 0 || parentIndex < 0 || targetIndex < 0) - { - Debug.LogError("Move of a SavedFilter has invalid input: " + index + " " + parentIndex + " " + targetIndex); - return false; - } - - if (instanceID == targetInstanceID) - { - //Debug.LogError ("Cannot move to same position"); - return false; - } - - // Remove range from list (there could be children that is also moved) - for (int i = index + 1; i < m_SavedFilters.Count; ++i) - { - if (m_SavedFilters[i].m_Depth > m_SavedFilters[index].m_Depth) - { - if (i == targetIndex || i == parentIndex) - { - //Debug.LogError ("Cannot move filter to a child location "); - return false; - } - } - else - break; - } - - // Valid move - return true; - } - - void Move(int instanceID, int parentInstanceID, int targetInstanceID, bool after) - { - if (!IsValidMove(instanceID, parentInstanceID, targetInstanceID, after)) - return; - - int index = IndexOf(instanceID); - int parentIndex = IndexOf(parentInstanceID); - int targetIndex = IndexOf(targetInstanceID); - - SavedFilter filter = m_SavedFilters[index]; - SavedFilter parent = m_SavedFilters[parentIndex]; - - - int depthChange = 0; - if (m_AllowHierarchy) - depthChange = (parent.m_Depth + 1) - filter.m_Depth; - - // Remove range from list (there could be children that is also moved) - List moveList = GetSavedFilterAndChildren(instanceID); - m_SavedFilters.RemoveRange(index, moveList.Count); - - // Update depth - foreach (SavedFilter s in moveList) - s.m_Depth += depthChange; - - // Insert after target - targetIndex = IndexOf(targetInstanceID); - if (targetIndex != -1) - { - if (after) - targetIndex += 1; - m_SavedFilters.InsertRange(targetIndex, moveList); - } - Changed(); - } - - void UpdateFilter(int instanceID, SearchFilter filter, float previewSize) - { - SavedFilter savedFilter = Find(instanceID); - if (savedFilter != null) - { - SearchFilter copiedFilter = null; - if (filter != null) - { - copiedFilter = ObjectCopier.DeepClone(filter); - savedFilter.m_Filter = copiedFilter; - } - - savedFilter.m_PreviewSize = previewSize; - Changed(); - } - else - { - Debug.LogError("Could not find saved filter " + instanceID + " " + instance.ToString()); - } - } - - int GetNextAvailableID() - { - List allIDs = new List(); - foreach (SavedFilter sf in m_SavedFilters) - if (sf.m_ID >= ProjectWindowUtil.k_FavoritesStartInstanceID) - allIDs.Add(sf.m_ID); - allIDs.Sort(); - - // Now try find - int result = ProjectWindowUtil.k_FavoritesStartInstanceID; - int i = 0; - while (i < 1000) - { - if (allIDs.BinarySearch(result) < 0) - return result; - - result++; - i++; - } - - Debug.LogError("Could not assign valid ID to saved filter " + DebugUtils.ListToString(allIDs) + " " + result); - return ProjectWindowUtil.k_FavoritesStartInstanceID + 1000; - } - - int Add(string displayName, SearchFilter filter, float previewSize, int insertAfterInstanceID, bool addAsChild) - { - SearchFilter filterCopy = null; - if (filter != null) - filterCopy = ObjectCopier.DeepClone(filter); - - // Clear unused data before saving - if (filterCopy.GetState() == SearchFilter.State.SearchingInAllAssets || - filterCopy.GetState() == SearchFilter.State.SearchingInAssetStore) - { - filterCopy.folders = new string[0]; - } - - int afterIndex = 0; // add after root index - if (insertAfterInstanceID != 0) - { - afterIndex = IndexOf(insertAfterInstanceID); - if (afterIndex == -1) - { - Debug.LogError("Invalid insert position"); - return 0; - } - } - - int depth = m_SavedFilters[afterIndex].m_Depth + (addAsChild ? 1 : 0); - - SavedFilter savedFilter = new SavedFilter(displayName, filterCopy, depth, previewSize); - savedFilter.m_ID = GetNextAvailableID(); - - if (m_SavedFilters.Count == 0) - { - m_SavedFilters.Add(savedFilter); - } - else - { - m_SavedFilters.Insert(afterIndex + 1, savedFilter); // insert after wanted index - } - - // Select new Saved filter - //Selection.activeInstanceID = savedFilter.m_ID; - - Changed(); - return savedFilter.m_ID; - } - - List GetSavedFilterAndChildren(int instanceID) - { - List result = new List(); - int index = IndexOf(instanceID); - if (index >= 0) - { - result.Add(m_SavedFilters[index]); - for (int i = index + 1; i < m_SavedFilters.Count; ++i) - { - if (m_SavedFilters[i].m_Depth > m_SavedFilters[index].m_Depth) - result.Add(m_SavedFilters[i]); - else - break; - } - } - - return result; - } - - void Remove(int instanceID) - { - int index = IndexOf(instanceID); - if (index >= 1) - { - List deleteList = GetSavedFilterAndChildren(instanceID); - if (deleteList.Count > 0) - { - m_SavedFilters.RemoveRange(index, deleteList.Count); - Changed(); - } - } - } - - int IndexOf(int instanceID) - { - for (int i = 0; i < m_SavedFilters.Count; ++i) - if (m_SavedFilters[i].m_ID == instanceID) - return i; - - return -1; - } - - SavedFilter Find(int instanceID) - { - int index = IndexOf(instanceID); - if (index >= 0) - return m_SavedFilters[index]; - return null; - } - - void Init() - { - // Data is serialized to hdd so this code is only run first time (if we did not provide a default set of saved filters) - if (m_SavedFilters == null || m_SavedFilters.Count == 0) - { - m_SavedFilters = new List(); - - // Ensure we have a root at depth 0 - m_SavedFilters.Add(new SavedFilter("Favorites", null, 0, -1f)); - } - - // Always set root filter data (is serialized so we need to set it here to affect serialized data) - SearchFilter filter = new SearchFilter(); - filter.classNames = new string[0]; - m_SavedFilters[0].m_Name = "Favorites"; - m_SavedFilters[0].m_Filter = filter; - m_SavedFilters[0].m_Depth = 0; - m_SavedFilters[0].m_ID = ProjectWindowUtil.k_FavoritesStartInstanceID; - - // At init check if all have valid ids (for patching up ids old saved filters) - for (int i = 0; i < m_SavedFilters.Count; ++i) - if (m_SavedFilters[i].m_ID < ProjectWindowUtil.k_FavoritesStartInstanceID) - m_SavedFilters[i].m_ID = GetNextAvailableID(); - - // Ensure depth is valid - if (!m_AllowHierarchy) - for (int i = 1; i < m_SavedFilters.Count; ++i) - m_SavedFilters[i].m_Depth = 1; - - if (m_SavedFiltersInitialized != null && m_SavedFilters.Count > 1) - { - m_SavedFiltersInitialized(); - } - } - - int GetRoot() - { - if (m_SavedFilters != null && m_SavedFilters.Count > 0) - return m_SavedFilters[0].m_ID; - return 0; - } - - // Utility function for building a tree view from saved filter state. Returns root of tree - TreeViewItem BuildTreeView() - { - Init(); - - if (m_SavedFilters.Count == 0) - { - Debug.LogError("BuildTreeView: No saved filters! We should at least have a root"); - return null; - } - - TreeViewItem root = null; - - // Create rest of nodes - List items = new List(); - for (int i = 0; i < m_SavedFilters.Count; ++i) - { - SavedFilter savedFilter = m_SavedFilters[i]; - int instanceID = savedFilter.m_ID; - int depth = savedFilter.m_Depth; - bool isFolder = savedFilter.m_Filter.GetState() == SearchFilter.State.FolderBrowsing; - TreeViewItem item = new SearchFilterTreeItem(instanceID, depth, null, savedFilter.m_Name, isFolder); - if (i == 0) - root = item; - else - { - if (Collab.instance.collabFilters.ContainsSearchFilter(savedFilter.m_Name, savedFilter.m_Filter.FilterToSearchFieldString())) - { - if (!Collab.instance.IsCollabEnabledForCurrentProject()) - continue; - } - - if (SoftlockViewController.Instance.softLockFilters.ContainsSearchFilter(savedFilter.m_Name, savedFilter.m_Filter.FilterToSearchFieldString())) - { - if (CollabSettingsManager.IsAvailable(CollabSettingType.InProgressEnabled)) - { - if (!Collab.instance.IsCollabEnabledForCurrentProject() || !CollabSettingsManager.inProgressEnabled) - continue; - } - else - continue; - } - items.Add(item); - } - } - - // Fix child/parent references - TreeViewUtility.SetChildParentReferences(items, root); - - return root; - } - - void Changed() - { - bool saveAsText = true; - Save(saveAsText); - - // Notify listeners of change - if (m_SavedFiltersChanged != null) - m_SavedFiltersChanged(); - } - - public override string ToString() - { - string text = "Saved Filters "; - for (int i = 0; i < m_SavedFilters.Count; ++i) - { - int instanceID = m_SavedFilters[i].m_ID; - SavedFilter s = m_SavedFilters[i]; - text += string.Format(": {0} ({1})({2})({3}) ", s.m_Name, instanceID, s.m_Depth, s.m_PreviewSize); - } - return text; - } - } - - - // Provides a method for performing a deep copy of an object. - // Binary Serialization is used to perform the copy. - // Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx - internal static class ObjectCopier - { - // Perform a deep Copy of the source object. - public static T DeepClone(T source) - { - if (!typeof(T).IsSerializable) - { - throw new ArgumentException("The type must be serializable.", "source"); - } - - // Don't serialize a null object, simply return the default for that object - if (Object.ReferenceEquals(source, null)) - { - return default(T); - } - - System.Runtime.Serialization.IFormatter formatter = - new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); - Stream stream = new MemoryStream(); - using (stream) - { - formatter.Serialize(stream, source); - stream.Seek(0, SeekOrigin.Begin); - return (T)formatter.Deserialize(stream); - } - } - } -} diff --git a/Editor/Mono/ProjectBrowserColumnOne.cs b/Editor/Mono/ProjectBrowserColumnOne.cs deleted file mode 100644 index e342041c37..0000000000 --- a/Editor/Mono/ProjectBrowserColumnOne.cs +++ /dev/null @@ -1,416 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Collections.Generic; -using UnityEditor.IMGUI.Controls; -using UnityEngine; -using UnityEditorInternal; -using Object = UnityEngine.Object; - - -namespace UnityEditor -{ - // Used for type check - class SearchFilterTreeItem : TreeViewItem - { - bool m_IsFolder; - public SearchFilterTreeItem(int id, int depth, TreeViewItem parent, string displayName, bool isFolder) - : base(id, depth, parent, displayName) - { - m_IsFolder = isFolder; - } - - public bool isFolder {get {return m_IsFolder; }} - } - - //------------------------------------------------ - // GUI section - - internal class ProjectBrowserColumnOneTreeViewGUI : AssetsTreeViewGUI - { - const float k_DistBetweenRootTypes = 15f; - Texture2D k_FavoritesIcon = EditorGUIUtility.FindTexture("Favorite Icon"); - Texture2D k_FavoriteFolderIcon = EditorGUIUtility.FindTexture("FolderFavorite Icon"); - Texture2D k_FavoriteFilterIcon = EditorGUIUtility.FindTexture("Search Icon"); - bool m_IsCreatingSavedFilter = false; - - public ProjectBrowserColumnOneTreeViewGUI(TreeViewController treeView) : base(treeView) - { - } - - // ------------------ - // Size section - - - override public Vector2 GetTotalSize() - { - Vector2 totalSize = base.GetTotalSize(); - - totalSize.y += k_DistBetweenRootTypes * 1; // assumes that we have two root - - return totalSize; - } - - public override Rect GetRowRect(int row, float rowWidth) - { - var rows = m_TreeView.data.GetRows(); - return new Rect(0, GetTopPixelOfRow(row, rows), rowWidth, k_LineHeight); - } - - float GetTopPixelOfRow(int row, IList rows) - { - float topPixel = row * k_LineHeight; - - // Assumes Saved filter are second root - TreeViewItem item = rows[row]; - ProjectBrowser.ItemType type = ProjectBrowser.GetItemType(item.id); - if (type == ProjectBrowser.ItemType.Asset) - topPixel += k_DistBetweenRootTypes; - - return topPixel; - } - - override public int GetNumRowsOnPageUpDown(TreeViewItem fromItem, bool pageUp, float heightOfTreeView) - { - return (int)Mathf.Floor(heightOfTreeView / k_LineHeight) - 1; // -1 is fast fix for space between roots - } - - // Should return the row number of the first and last row thats fits in the pixel rect defined by top and height - override public void GetFirstAndLastRowVisible(out int firstRowVisible, out int lastRowVisible) - { - float topPixel = m_TreeView.state.scrollPos.y; - float heightInPixels = m_TreeView.GetTotalRect().height; - - firstRowVisible = (int)Mathf.Floor(topPixel / k_LineHeight); - lastRowVisible = firstRowVisible + (int)Mathf.Ceil(heightInPixels / k_LineHeight); - - float rowsPerSpaceBetween = k_DistBetweenRootTypes / k_LineHeight; - firstRowVisible -= (int)Mathf.Ceil(2 * rowsPerSpaceBetween); // for now we just add extra rows to ensure all rows are visible - lastRowVisible += (int)Mathf.Ceil(2 * rowsPerSpaceBetween); - - firstRowVisible = Mathf.Max(firstRowVisible, 0); - lastRowVisible = Mathf.Min(lastRowVisible, m_TreeView.data.rowCount - 1); - } - - // ------------------ - // Row Gui section - - override public void OnRowGUI(Rect rowRect, TreeViewItem item, int row, bool selected, bool focused) - { - bool useBoldFont = IsVisibleRootNode(item); - DoItemGUI(rowRect, row, item, selected, focused, useBoldFont); - } - - bool IsVisibleRootNode(TreeViewItem item) - { - return (m_TreeView.data as ProjectBrowserColumnOneTreeViewDataSource).IsVisibleRootNode(item); - } - - protected override Texture GetIconForItem(TreeViewItem item) - { - if (item != null && item.icon != null) - return item.icon; - - SearchFilterTreeItem searchFilterItem = item as SearchFilterTreeItem; - if (searchFilterItem != null) - { - if (IsVisibleRootNode(item)) - return k_FavoritesIcon; - if (searchFilterItem.isFolder) - return k_FavoriteFolderIcon; - else - return k_FavoriteFilterIcon; - } - return base.GetIconForItem(item); - } - - public static float GetListAreaGridSize() - { - float previewSize = -1f; - if (ProjectBrowser.s_LastInteractedProjectBrowser != null) - previewSize = ProjectBrowser.s_LastInteractedProjectBrowser.listAreaGridSize; - return previewSize; - } - - virtual internal void BeginCreateSavedFilter(SearchFilter filter) - { - string savedFilterName = "New Saved Search"; - - m_IsCreatingSavedFilter = true; - int instanceID = SavedSearchFilters.AddSavedFilter(savedFilterName, filter, GetListAreaGridSize()); - m_TreeView.Frame(instanceID, true, false); - - // Start naming the asset - m_TreeView.state.renameOverlay.BeginRename(savedFilterName, instanceID, 0f); - } - - override protected void RenameEnded() - { - int instanceID = GetRenameOverlay().userData; - ProjectBrowser.ItemType type = ProjectBrowser.GetItemType(instanceID); - - if (m_IsCreatingSavedFilter) - { - // Create saved filter - m_IsCreatingSavedFilter = false; - - if (GetRenameOverlay().userAcceptedRename) - { - SavedSearchFilters.SetName(instanceID, GetRenameOverlay().name); - m_TreeView.SetSelection(new[] { instanceID }, true); - } - else - SavedSearchFilters.RemoveSavedFilter(instanceID); - } - else if (type == ProjectBrowser.ItemType.SavedFilter) - { - // Renamed saved filter - if (GetRenameOverlay().userAcceptedRename) - { - SavedSearchFilters.SetName(instanceID, GetRenameOverlay().name); - } - } - else - { - // Let base handle renaming of folders - base.RenameEnded(); - - // Ensure to sync filter to new folder name (so we still show the contents of the folder) - if (GetRenameOverlay().userAcceptedRename) - m_TreeView.NotifyListenersThatSelectionChanged(); - } - } - } - - - //------------------------------------------------ - // DataSource section - - internal class ProjectBrowserColumnOneTreeViewDataSource : TreeViewDataSource - { - static string kProjectBrowserString = "ProjectBrowser"; - - public ProjectBrowserColumnOneTreeViewDataSource(TreeViewController treeView) : base(treeView) - { - showRootItem = false; - rootIsCollapsable = false; - SavedSearchFilters.AddChangeListener(ReloadData); // We reload on change - } - - public override bool SetExpanded(int id, bool expand) - { - if (base.SetExpanded(id, expand)) - { - // Persist expanded state for ProjectBrowsers - InternalEditorUtility.expandedProjectWindowItems = expandedIDs.ToArray(); - - if (m_RootItem.hasChildren) - { - // Set global expanded state of roots (Assets folder and Favorites root) - foreach (TreeViewItem item in m_RootItem.children) - if (item.id == id) - EditorPrefs.SetBool(kProjectBrowserString + item.displayName, expand); - } - return true; - } - return false; - } - - public override bool IsExpandable(TreeViewItem item) - { - return item.hasChildren && (item != m_RootItem || rootIsCollapsable); - } - - public override bool CanBeMultiSelected(TreeViewItem item) - { - return ProjectBrowser.GetItemType(item.id) != ProjectBrowser.ItemType.SavedFilter; - } - - public override bool CanBeParent(TreeViewItem item) - { - return !(item is SearchFilterTreeItem) || SavedSearchFilters.AllowsHierarchy(); - } - - public bool IsVisibleRootNode(TreeViewItem item) - { - // The main root Item is invisible the next level is visible root items - return (item.parent != null && item.parent.parent == null); - } - - public override bool IsRenamingItemAllowed(TreeViewItem item) - { - // The 'Assets' root and 'Filters' roots are not allowed to be renamed - if (IsVisibleRootNode(item)) - return false; - - return base.IsRenamingItemAllowed(item); - } - - public static int GetAssetsFolderInstanceID() - { - int instanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID("Assets"); - return instanceID; - } - - public override void FetchData() - { - m_RootItem = new TreeViewItem(System.Int32.MaxValue, 0, null, "Invisible Root Item"); - SetExpanded(m_RootItem, true); // ensure always visible - - // We want three roots: Favorites, Assets, and Saved Filters - List visibleRoots = new List(); - - // Fetch asset folders - int assetsFolderInstanceID = GetAssetsFolderInstanceID(); - int depth = 0; - string displayName = "Assets"; //CreateDisplayName (assetsFolderInstanceID); - TreeViewItem assetRootItem = new TreeViewItem(assetsFolderInstanceID, depth, m_RootItem, displayName); - ReadAssetDatabase(HierarchyType.Assets, assetRootItem, depth + 1); - - // Fetch packages - TreeViewItem packagesRootItem = null; - if (Unsupported.IsDeveloperMode() && EditorPrefs.GetBool("ShowPackagesFolder")) - { - var packagesFolderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(AssetDatabase.GetPackagesMountPoint()); - string packagesDisplayName = AssetDatabase.GetPackagesMountPoint(); - packagesRootItem = new TreeViewItem(packagesFolderInstanceID, depth, m_RootItem, packagesDisplayName); - ReadAssetDatabase(HierarchyType.Packages, packagesRootItem, depth + 1); - } - - // Fetch saved filters - TreeViewItem savedFiltersRootItem = SavedSearchFilters.ConvertToTreeView(); - savedFiltersRootItem.parent = m_RootItem; - - // Order - visibleRoots.Add(savedFiltersRootItem); - visibleRoots.Add(assetRootItem); - - if (packagesRootItem != null) - visibleRoots.Add(packagesRootItem); - - m_RootItem.children = visibleRoots; - - // Get global expanded state of roots - foreach (TreeViewItem item in m_RootItem.children) - { - bool expanded = EditorPrefs.GetBool(kProjectBrowserString + item.displayName, true); - SetExpanded(item, expanded); - } - - m_NeedRefreshRows = true; - } - - private void ReadAssetDatabase(HierarchyType htype, TreeViewItem parent, int baseDepth) - { - // Read from Assets directory - IHierarchyProperty property = new HierarchyProperty(htype, false); - property.Reset(); - - Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResourcesUtility.folderIconName); - Texture2D emptyFolderIcon = EditorGUIUtility.FindTexture(EditorResourcesUtility.emptyFolderIconName); - - List allFolders = new List(); - while (property.Next(null)) - { - if (property.isFolder) - { - TreeViewItem folderItem = new TreeViewItem(property.instanceID, baseDepth + property.depth, null, property.name); - folderItem.icon = property.hasChildren ? folderIcon : emptyFolderIcon; - allFolders.Add(folderItem); - } - } - - // Fix references - TreeViewUtility.SetChildParentReferences(allFolders, parent); - } - } - - internal class ProjectBrowserColumnOneTreeViewDragging : AssetsTreeViewDragging - { - public ProjectBrowserColumnOneTreeViewDragging(TreeViewController treeView) : base(treeView) - { - } - - public override void StartDrag(TreeViewItem draggedItem, List draggedItemIDs) - { - if (SavedSearchFilters.IsSavedFilter(draggedItem.id)) - { - // Root Filters Item is not allowed to be dragged - if (draggedItem.id == SavedSearchFilters.GetRootInstanceID()) - return; - } - - ProjectWindowUtil.StartDrag(draggedItem.id, draggedItemIDs); - } - - public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPos) - { - if (targetItem == null) - return DragAndDropVisualMode.None; - - object savedFilterData = DragAndDrop.GetGenericData(ProjectWindowUtil.k_DraggingFavoriteGenericData); - - // Dragging saved filter - if (savedFilterData != null) - { - int instanceID = (int)savedFilterData; - if (targetItem is SearchFilterTreeItem && parentItem is SearchFilterTreeItem)// && targetItem.id != draggedInstanceID && parentItem.id != draggedInstanceID) - { - bool validMove = SavedSearchFilters.CanMoveSavedFilter(instanceID, parentItem.id, targetItem.id, dropPos == DropPosition.Below); - if (validMove && perform) - { - SavedSearchFilters.MoveSavedFilter(instanceID, parentItem.id, targetItem.id, dropPos == DropPosition.Below); - m_TreeView.SetSelection(new[] { instanceID }, false); - m_TreeView.NotifyListenersThatSelectionChanged(); - } - return validMove ? DragAndDropVisualMode.Copy : DragAndDropVisualMode.None; - } - return DragAndDropVisualMode.None; - } - // Dragging of folders into filters - else - { - // Check if we are dragging a single folder - if (targetItem is SearchFilterTreeItem && parentItem is SearchFilterTreeItem) - { - string genericData = DragAndDrop.GetGenericData(ProjectWindowUtil.k_IsFolderGenericData) as string; - if (genericData == "isFolder") - { - if (perform) - { - Object[] objs = DragAndDrop.objectReferences; - if (objs.Length > 0) - { - string path = AssetDatabase.GetAssetPath(objs[0].GetInstanceID()); - if (!string.IsNullOrEmpty(path)) - { - // TODO: Fix with new AssetDatabase API when it is ready (GetName) - string folderName = new DirectoryInfo(path).Name; - SearchFilter searchFilter = new SearchFilter(); - searchFilter.folders = new[] {path}; - bool addAsChild = targetItem == parentItem; - - float previewSize = ProjectBrowserColumnOneTreeViewGUI.GetListAreaGridSize(); - int instanceID = SavedSearchFilters.AddSavedFilterAfterInstanceID(folderName, searchFilter, previewSize, targetItem.id, addAsChild); - m_TreeView.SetSelection(new[] { instanceID }, false); - m_TreeView.NotifyListenersThatSelectionChanged(); - } - else - { - Debug.Log("Could not get asset path from id " + objs[0].GetInstanceID()); - } - } - } - return DragAndDropVisualMode.Copy; // Allow dragging folders to filters - } - return DragAndDropVisualMode.None; // Assets that are not folders are not allowed to be dragged to filters - } - } - // Assets are handled by base - return base.DoDrag(parentItem, targetItem, perform, dropPos); - } - } -} diff --git a/Editor/Mono/ProjectBrowserPopups.cs b/Editor/Mono/ProjectBrowserPopups.cs deleted file mode 100644 index c006d1b7ac..0000000000 --- a/Editor/Mono/ProjectBrowserPopups.cs +++ /dev/null @@ -1,532 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditorInternal; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - internal class PopupList : PopupWindowContent - { - public delegate void OnSelectCallback(ListElement element); - static EditorGUI.RecycledTextEditor s_RecycledEditor = new EditorGUI.RecycledTextEditor(); - static string s_TextFieldName = "ProjectBrowserPopupsTextField"; - static int s_TextFieldHash = s_TextFieldName.GetHashCode(); - public enum Gravity - { - Top, - Bottom - } - - public class ListElement - { - public GUIContent m_Content; - private float m_FilterScore; - private bool m_Selected; - private bool m_WasSelected; - private bool m_PartiallySelected; - private bool m_Enabled; - - public ListElement(string text, bool selected, float score) - { - m_Content = new GUIContent(text); - if (!string.IsNullOrEmpty(m_Content.text)) - { - char[] a = m_Content.text.ToCharArray(); - a[0] = char.ToUpper(a[0]); - m_Content.text = new string(a); - } - m_Selected = selected; - filterScore = score; - m_PartiallySelected = false; - m_Enabled = true; - } - - public ListElement(string text, bool selected) - { - m_Content = new GUIContent(text); - m_Selected = selected; - filterScore = 0; - m_PartiallySelected = false; - m_Enabled = true; - } - - public ListElement(string text) : this(text, false) - { - } - - public float filterScore - { - get - { - return m_WasSelected ? float.MaxValue : m_FilterScore; - } - set - { - m_FilterScore = value; - ResetScore(); - } - } - - public bool selected - { - get - { - return m_Selected; - } - set - { - m_Selected = value; - if (m_Selected) - m_WasSelected = true; - } - } - - public bool enabled - { - get - { - return m_Enabled; - } - set - { - m_Enabled = value; - } - } - - public bool partiallySelected - { - get - { - return m_PartiallySelected; - } - set - { - m_PartiallySelected = value; - if (m_PartiallySelected) - m_WasSelected = true; - } - } - - public string text - { - get - { - return m_Content.text; - } - set - { - m_Content.text = value; - } - } - - public void ResetScore() - { - m_WasSelected = m_Selected || m_PartiallySelected; - } - } - - public class InputData - { - public List m_ListElements; - public bool m_CloseOnSelection; - public bool m_AllowCustom; - public bool m_EnableAutoCompletion = true; - public bool m_SortAlphabetically; - public OnSelectCallback m_OnSelectCallback; - public int m_MaxCount; - - public InputData() - { - m_ListElements = new List(); - } - - public void DeselectAll() - { - foreach (ListElement element in m_ListElements) - { - element.selected = false; - element.partiallySelected = false; - } - } - - public void ResetScores() - { - foreach (var element in m_ListElements) - element.ResetScore(); - } - - public virtual IEnumerable BuildQuery(string prefix) - { - if (prefix == "") - return m_ListElements; - else - return m_ListElements.Where( - element => element.m_Content.text.StartsWith(prefix, System.StringComparison.OrdinalIgnoreCase) - ); - } - - public IEnumerable GetFilteredList(string prefix) - { - IEnumerable res = BuildQuery(prefix); - if (m_MaxCount > 0) - res = res.OrderByDescending(element => element.filterScore).Take(m_MaxCount); - if (m_SortAlphabetically) - return res.OrderBy(element => element.text.ToLower()); - else - return res; - } - - public int GetFilteredCount(string prefix) - { - IEnumerable res = BuildQuery(prefix); - if (m_MaxCount > 0) - res = res.Take(m_MaxCount); - return res.Count(); - } - - public ListElement NewOrMatchingElement(string label) - { - foreach (var element in m_ListElements) - { - if (element.text.Equals(label, StringComparison.OrdinalIgnoreCase)) - return element; - } - - var res = new ListElement(label, false, -1); - m_ListElements.Add(res); - return res; - } - } - - private class Styles - { - public GUIStyle menuItem = "MenuItem"; - public GUIStyle menuItemMixed = "MenuItemMixed"; - public GUIStyle background = "grey_border"; - public GUIStyle customTextField; - public GUIStyle customTextFieldCancelButton; - public GUIStyle customTextFieldCancelButtonEmpty; - public Styles() - { - customTextField = new GUIStyle(EditorStyles.toolbarSearchField); - customTextFieldCancelButton = new GUIStyle(EditorStyles.toolbarSearchFieldCancelButton); - customTextFieldCancelButtonEmpty = new GUIStyle(EditorStyles.toolbarSearchFieldCancelButtonEmpty); - } - } - - // Static - static Styles s_Styles; - - // State - private InputData m_Data; - - // Layout - const float k_LineHeight = 16; - const float k_TextFieldHeight = 16; - const float k_Margin = 10; - Gravity m_Gravity; - - string m_EnteredTextCompletion = ""; - string m_EnteredText = ""; - int m_SelectedCompletionIndex = 0; - - public PopupList(InputData inputData) : this(inputData, null) {} - - public PopupList(InputData inputData, string initialSelectionLabel) - { - m_Data = inputData; - m_Data.ResetScores(); - SelectNoCompletion(); - m_Gravity = Gravity.Top; - if (initialSelectionLabel != null) - { - m_EnteredTextCompletion = initialSelectionLabel; - UpdateCompletion(); - } - } - - public override void OnClose() - { - if (m_Data != null) - m_Data.ResetScores(); - } - - public virtual float GetWindowHeight() - { - int count = (m_Data.m_MaxCount == 0) ? m_Data.GetFilteredCount(m_EnteredText) : m_Data.m_MaxCount; - return count * k_LineHeight + 2 * k_Margin + (m_Data.m_AllowCustom ? k_TextFieldHeight : 0); - } - - public virtual float GetWindowWidth() - { - return 150f; - } - - public override Vector2 GetWindowSize() - { - return new Vector2(GetWindowWidth(), GetWindowHeight()); - } - - public override void OnGUI(Rect windowRect) - { - Event evt = Event.current; - // We do not use the layout event - if (evt.type == EventType.Layout) - return; - - if (s_Styles == null) - s_Styles = new Styles(); - - if (evt.type == EventType.KeyDown && evt.keyCode == KeyCode.Escape) - { - editorWindow.Close(); - GUIUtility.ExitGUI(); - } - - if (m_Gravity == Gravity.Bottom) - { - DrawList(editorWindow, windowRect); - DrawCustomTextField(editorWindow, windowRect); - } - else - { - DrawCustomTextField(editorWindow, windowRect); - DrawList(editorWindow, windowRect); - } - - // Background with 1 pixel border (rendered above content) - if (evt.type == EventType.Repaint) - s_Styles.background.Draw(new Rect(windowRect.x, windowRect.y, windowRect.width, windowRect.height), false, false, false, false); - } - - private void DrawCustomTextField(EditorWindow editorWindow, Rect windowRect) - { - if (!m_Data.m_AllowCustom) - return; - - Event evt = Event.current; - bool enableAutoCompletion = m_Data.m_EnableAutoCompletion; - bool closeWindow = false; - bool useEventBeforeTextField = false; - bool clearText = false; - - string textBeforeEdit = CurrentDisplayedText(); - - // Handle "special" keyboard input - if (evt.type == EventType.KeyDown) - { - switch (evt.keyCode) - { - case KeyCode.Comma: - case KeyCode.Space: - case KeyCode.Tab: - case KeyCode.Return: - if (textBeforeEdit != "") - { - // Toggle state - if (m_Data.m_OnSelectCallback != null) - m_Data.m_OnSelectCallback(m_Data.NewOrMatchingElement(textBeforeEdit)); - - if (evt.keyCode == KeyCode.Tab || evt.keyCode == KeyCode.Comma) - clearText = true; // to ease multiple entries (it is unlikely that the same filter is used more than once) - - // Auto close - if (m_Data.m_CloseOnSelection || evt.keyCode == KeyCode.Return) - closeWindow = true; - } - useEventBeforeTextField = true; - break; - case KeyCode.Delete: - case KeyCode.Backspace: - enableAutoCompletion = false; - // Don't use the event yet, so the textfield below can get it and delete the selection - break; - - case KeyCode.DownArrow: - ChangeSelectedCompletion(1); - useEventBeforeTextField = true; - break; - - case KeyCode.UpArrow: - ChangeSelectedCompletion(-1); - useEventBeforeTextField = true; - break; - case KeyCode.None: - if (evt.character == ' ' || evt.character == ',') - useEventBeforeTextField = true; - break; - } - } - - string textFieldText; - // Draw textfield - { - bool dummy = false; - 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); - - GUI.SetNextControlName(s_TextFieldName); - EditorGUI.FocusTextInControl(s_TextFieldName); - int id = EditorGUIUtility.GetControlID(s_TextFieldHash, FocusType.Keyboard, pos); - - if (useEventBeforeTextField) - evt.Use(); // We have to delay this until after we get the control id, otherwise the id we get is just -1 - - if (GUIUtility.keyboardControl == 0) - GUIUtility.keyboardControl = id; - - textFieldText = EditorGUI.DoTextField(s_RecycledEditor, id, pos, textBeforeEdit, s_Styles.customTextField, null, out dummy, false, false, false); - Rect buttonRect = pos; - buttonRect.x += pos.width; - buttonRect.width = 14; - // Draw "clear textfield" button (X) - if ((GUI.Button(buttonRect, GUIContent.none, textFieldText != "" ? s_Styles.customTextFieldCancelButton : s_Styles.customTextFieldCancelButtonEmpty) && textFieldText != "") - || clearText) - { - textFieldText = EditorGUI.s_OriginalText = s_RecycledEditor.text = ""; - s_RecycledEditor.cursorIndex = 0; - s_RecycledEditor.selectIndex = 0; - enableAutoCompletion = false; - } - } - - // Handle autocompletion - if (textBeforeEdit != textFieldText) - { - m_EnteredText = (0 <= s_RecycledEditor.cursorIndex && s_RecycledEditor.cursorIndex < textFieldText.Length) ? textFieldText.Substring(0, s_RecycledEditor.cursorIndex) : textFieldText; - - if (enableAutoCompletion) - UpdateCompletion(); - else - SelectNoCompletion(); - } - - if (closeWindow) - editorWindow.Close(); - } - - private string CurrentDisplayedText() - { - return m_EnteredTextCompletion != "" ? m_EnteredTextCompletion : m_EnteredText; - } - - private void UpdateCompletion() - { - if (!m_Data.m_EnableAutoCompletion) - return; - IEnumerable query = m_Data.GetFilteredList(m_EnteredText).Select(element => element.text); - - if (m_EnteredTextCompletion != "" && m_EnteredTextCompletion.StartsWith(m_EnteredText, System.StringComparison.OrdinalIgnoreCase)) - { - m_SelectedCompletionIndex = query.TakeWhile(element => element != m_EnteredTextCompletion).Count(); - // m_EnteredTextCompletion is already correct - } - else - { - // Clamp m_SelectedCompletionIndex to 0..query.Count () - 1 - if (m_SelectedCompletionIndex < 0) - m_SelectedCompletionIndex = 0; - else if (m_SelectedCompletionIndex >= query.Count()) - m_SelectedCompletionIndex = query.Count() - 1; - - m_EnteredTextCompletion = query.Skip(m_SelectedCompletionIndex).DefaultIfEmpty("").FirstOrDefault(); - } - AdjustRecycledEditorSelectionToCompletion(); - } - - private void ChangeSelectedCompletion(int change) - { - int count = m_Data.GetFilteredCount(m_EnteredText); - if (m_SelectedCompletionIndex == -1 && change < 0) // specal case for initial selection - m_SelectedCompletionIndex = count; - - int index = count > 0 ? (m_SelectedCompletionIndex + change + count) % count : 0; - SelectCompletionWithIndex(index); - } - - private void SelectCompletionWithIndex(int index) - { - m_SelectedCompletionIndex = index; - m_EnteredTextCompletion = ""; - UpdateCompletion(); - } - - private void SelectNoCompletion() - { - m_SelectedCompletionIndex = -1; - m_EnteredTextCompletion = ""; - AdjustRecycledEditorSelectionToCompletion(); - } - - private void AdjustRecycledEditorSelectionToCompletion() - { - if (m_EnteredTextCompletion != "") - { - s_RecycledEditor.text = m_EnteredTextCompletion; - EditorGUI.s_OriginalText = m_EnteredTextCompletion; - s_RecycledEditor.cursorIndex = m_EnteredText.Length; - s_RecycledEditor.selectIndex = m_EnteredTextCompletion.Length; //the selection goes from s_RecycledEditor.cursorIndex (already set by DoTextField) to s_RecycledEditor.selectIndex - } - } - - private void DrawList(EditorWindow editorWindow, Rect windowRect) - { - Event evt = Event.current; - - int i = -1; - foreach (var element in m_Data.GetFilteredList(m_EnteredText)) - { - i++; - 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); - - switch (evt.type) - { - case EventType.Repaint: - { - GUIStyle style = element.partiallySelected ? s_Styles.menuItemMixed : s_Styles.menuItem; - bool selected = element.selected || element.partiallySelected; - bool focused = false; - bool isHover = i == m_SelectedCompletionIndex; - bool isActive = selected; - - using (new EditorGUI.DisabledScope(!element.enabled)) - { - GUIContent content = element.m_Content; - style.Draw(rect, content, isHover, isActive, selected, focused); - } - } - break; - case EventType.MouseDown: - { - if (Event.current.button == 0 && rect.Contains(Event.current.mousePosition) && element.enabled) - { - // Toggle state - if (m_Data.m_OnSelectCallback != null) - m_Data.m_OnSelectCallback(element); - - evt.Use(); - - // Auto close - if (m_Data.m_CloseOnSelection) - editorWindow.Close(); - } - } - break; - case EventType.MouseMove: - { - if (rect.Contains(Event.current.mousePosition)) - { - SelectCompletionWithIndex(i); - evt.Use(); - } - } - break; - } - } - } - } -} diff --git a/Editor/Mono/ProjectTemplateWindow.cs b/Editor/Mono/ProjectTemplateWindow.cs deleted file mode 100644 index 4262bb0cfc..0000000000 --- a/Editor/Mono/ProjectTemplateWindow.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - internal class ProjectTemplateWindow : EditorWindow - { - string m_Name; - string m_DisplayName; - string m_Description; - string m_DefaultScene; - string m_Version; - - [MenuItem("internal:Project/Save As Template...")] - internal static void SaveAsTemplate() - { - var window = EditorWindow.GetWindow(); - window.Show(); - } - - void OnEnable() - { - titleContent = EditorGUIUtility.TrTextContent("Save Template"); - } - - void OnGUI() - { - m_Name = EditorGUILayout.TextField("Name:", m_Name); - m_DisplayName = EditorGUILayout.TextField("Display name:", m_DisplayName); - m_Description = EditorGUILayout.TextField("Description:", m_Description); - m_DefaultScene = EditorGUILayout.TextField("Default scene:", m_DefaultScene); - m_Version = EditorGUILayout.TextField("Version:", m_Version); - - if (GUILayout.Button("Save As...", GUILayout.Width(100))) - { - string path = EditorUtility.SaveFolderPanel("Save template to folder", "", ""); - if (path.Length > 0) - { - AssetDatabase.SaveAssets(); - EditorUtility.SaveProjectAsTemplate(path, m_Name, m_DisplayName, m_Description, m_DefaultScene, m_Version); - } - } - } - } -} diff --git a/Editor/Mono/ProjectWindow/CachedFilteredHierachy.cs b/Editor/Mono/ProjectWindow/CachedFilteredHierachy.cs deleted file mode 100644 index 4b746ccb23..0000000000 --- a/Editor/Mono/ProjectWindow/CachedFilteredHierachy.cs +++ /dev/null @@ -1,500 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.IO; -using System.Collections.Generic; -using UnityEditorInternal; -using UnityEngine.Assertions; - -namespace UnityEditor -{ - internal partial class FilteredHierarchy - { - public class FilterResult - { - public int instanceID; - public string name; - public bool hasChildren; - public int colorCode; - public bool isMainRepresentation; - public bool hasFullPreviewImage; - public IconDrawStyle iconDrawStyle; - public bool isFolder; - public HierarchyType type; - public Texture2D icon - { - get - { - if (m_Icon == null) - { - if (type == HierarchyType.Assets || type == HierarchyType.Packages) - { - // Note: Do not set m_Icon as GetCachedIcon uses its own cache that is cleared on reaching a max limit. - // This is because when having e.g very large projects (1000s of textures with unique icons) we do not want all icons loaded - // at the same time so don't keep a reference in m_Icon here - string path = AssetDatabase.GetAssetPath(instanceID); - if (path != null) - return AssetDatabase.GetCachedIcon(path) as Texture2D; - } - else if (type == HierarchyType.GameObjects) - { - // GameObject thumbnail can be set to m_Icon since its an actual icon which means we have a limited set of them - Object go = EditorUtility.InstanceIDToObject(instanceID); - m_Icon = AssetPreview.GetMiniThumbnail(go); - } - else - { - Assert.IsTrue(false, "Unhandled HierarchyType"); - } - } - return m_Icon; - } - set - { - m_Icon = value; - } - } - private Texture2D m_Icon; - - public string guid - { - get - { - if (type == HierarchyType.Assets || type == HierarchyType.Packages) - { - string path = AssetDatabase.GetAssetPath(instanceID); - if (path != null) - return AssetDatabase.AssetPathToGUID(path); - } - return null; - } - } - } - - SearchFilter m_SearchFilter = new SearchFilter(); - FilterResult[] m_Results = new FilterResult[0]; // When filtering of folder we have all sub assets here - FilterResult[] m_VisibleItems = new FilterResult[0]; // Subset of m_Results used for showing/hiding sub assets - - HierarchyType m_HierarchyType; - - public FilteredHierarchy(HierarchyType type) - { - m_HierarchyType = type; - } - - public HierarchyType hierarchyType - { - get { return m_HierarchyType; } - } - - public FilterResult[] results - { - get - { - if (m_VisibleItems.Length > 0) - return m_VisibleItems; - return m_Results; - } - } - public SearchFilter searchFilter - { - get { return m_SearchFilter; } - set - { - if (m_SearchFilter.SetNewFilter(value)) - ResultsChanged(); - } - } - - public bool foldersFirst { get; set; } - - public void SetResults(int[] instanceIDs) - { - HierarchyProperty property = new HierarchyProperty(m_HierarchyType, false); - property.Reset(); - - System.Array.Resize(ref m_Results, instanceIDs.Length); - for (int i = 0; i < instanceIDs.Length; ++i) - { - if (property.Find(instanceIDs[i], null)) - CopyPropertyData(ref m_Results[i], property); - } - } - - void CopyPropertyData(ref FilterResult result, HierarchyProperty property) - { - if (result == null) - result = new FilterResult(); - - result.instanceID = property.instanceID; - result.name = property.name; - result.hasChildren = property.hasChildren; - result.colorCode = property.colorCode; - result.isMainRepresentation = property.isMainRepresentation; - result.hasFullPreviewImage = property.hasFullPreviewImage; - result.iconDrawStyle = property.iconDrawStyle; - result.isFolder = property.isFolder; - result.type = hierarchyType; - - // If this is not the main representation, cache the icon, as we don't have an API to access it later. - // 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) - if (!property.isMainRepresentation) - result.icon = property.icon; - else if (property.isFolder && !property.hasChildren) - result.icon = EditorGUIUtility.FindTexture(EditorResourcesUtility.emptyFolderIconName); - else - result.icon = null; - } - - void SearchAllAssets(HierarchyProperty property) - { - const int k_MaxAddCount = 3000; - int elements = property.CountRemaining(null); - elements = Mathf.Min(elements, k_MaxAddCount); - property.Reset(); - - int i = m_Results.Length; - System.Array.Resize(ref m_Results, m_Results.Length + elements); - while (property.Next(null) && i < m_Results.Length) - { - CopyPropertyData(ref m_Results[i], property); - i++; - } - } - - void SearchInFolders(HierarchyProperty property) - { - List list = new List(); - string[] baseFolders = ProjectWindowUtil.GetBaseFolders(m_SearchFilter.folders); - - foreach (string folderPath in baseFolders) - { - // Ensure we do not have a filter when finding folder - property.SetSearchFilter(new SearchFilter()); - - int folderInstanceID = AssetDatabase.GetMainAssetInstanceID(folderPath); - if (property.Find(folderInstanceID, null)) - { - // Set filter after we found the folder - property.SetSearchFilter(m_SearchFilter); - int folderDepth = property.depth; - int[] expanded = null; // enter all children of folder - while (property.NextWithDepthCheck(expanded, folderDepth + 1)) - { - FilterResult result = new FilterResult(); - CopyPropertyData(ref result, property); - list.Add(result); - } - } - } - m_Results = list.ToArray(); - } - - void FolderBrowsing(HierarchyProperty property) - { - // We are not concerned with assets being added multiple times as we only show the contents - // of each selected folder. This is an issue when searching recursively into child folders. - List list = new List(); - foreach (string folderPath in m_SearchFilter.folders) - { - int folderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(folderPath); - if (property.Find(folderInstanceID, null)) - { - int folderDepth = property.depth; - int[] expanded = { folderInstanceID }; - while (property.Next(expanded)) - { - if (property.depth <= folderDepth) - break; // current property is outside folder - - FilterResult result = new FilterResult(); - CopyPropertyData(ref result, property); - list.Add(result); - - // Fetch sub assets by expanding the main asset (ignore folders) - if (property.hasChildren && !property.isFolder) - { - System.Array.Resize(ref expanded, expanded.Length + 1); - expanded[expanded.Length - 1] = property.instanceID; - } - } - } - } - m_Results = list.ToArray(); - } - - void AddResults(HierarchyProperty property) - { - switch (m_SearchFilter.GetState()) - { - case SearchFilter.State.FolderBrowsing: FolderBrowsing(property); break; - case SearchFilter.State.SearchingInAllAssets: SearchAllAssets(property); break; - case SearchFilter.State.SearchingInFolders: SearchInFolders(property); break; - case SearchFilter.State.SearchingInAssetStore: /*do nothing*/ break; - case SearchFilter.State.EmptySearchFilter: /*do nothing*/ break; - default: Debug.LogError("Unhandled enum!"); break; - } - } - - public void ResultsChanged() - { - m_Results = new FilterResult[0]; - if (m_SearchFilter.GetState() != SearchFilter.State.EmptySearchFilter) - { - HierarchyProperty hierarchyProperty = new HierarchyProperty(m_HierarchyType, false); - hierarchyProperty.SetSearchFilter(m_SearchFilter); - AddResults(hierarchyProperty); - - // When filtering on folder we use the order we get from BaseHiearchyProperty.cpp (to keep indented children under parent) otherwise we sort - if (m_SearchFilter.IsSearching()) - { - System.Array.Sort(m_Results, (result1, result2) => EditorUtility.NaturalCompare(result1.name, result2.name)); - } - - if (foldersFirst) - { - for (int nonFolderPos = 0; nonFolderPos < m_Results.Length; ++nonFolderPos) - { - if (m_Results[nonFolderPos].isFolder) - continue; - - for (int folderPos = nonFolderPos + 1; folderPos < m_Results.Length; ++folderPos) - { - if (!m_Results[folderPos].isFolder) - continue; - - FilterResult folder = m_Results[folderPos]; - int length = folderPos - nonFolderPos; - System.Array.Copy(m_Results, nonFolderPos, m_Results, nonFolderPos + 1, length); - m_Results[nonFolderPos] = folder; - break; - } - } - } - } - else - { - // Reset visible flags if filter string is empty (see BaseHiearchyProperty::SetSearchFilter) - if (m_HierarchyType == HierarchyType.GameObjects) - { - HierarchyProperty gameObjects = new HierarchyProperty(HierarchyType.GameObjects, false); - gameObjects.SetSearchFilter(m_SearchFilter); - } - } - } - - public void RefreshVisibleItems(List expandedInstanceIDs) - { - bool isSearching = m_SearchFilter.IsSearching(); - List visibleItems = new List(); - for (int i = 0; i < m_Results.Length; ++i) - { - visibleItems.Add(m_Results[i]); - if (m_Results[i].isMainRepresentation && m_Results[i].hasChildren && !m_Results[i].isFolder) - { - bool isParentExpanded = expandedInstanceIDs.IndexOf(m_Results[i].instanceID) >= 0; - bool addSubItems = isParentExpanded || isSearching; - int numSubItems = AddSubItemsOfMainRepresentation(i, addSubItems ? visibleItems : null); - i += numSubItems; - } - } - - m_VisibleItems = visibleItems.ToArray(); - } - - public List GetSubAssetInstanceIDs(int mainAssetInstanceID) - { - for (int i = 0; i < m_Results.Length; ++i) - { - if (m_Results[i].instanceID == mainAssetInstanceID) - { - List subAssetInstanceIDs = new List(); - int index = i + 1; // Start after the main representation - while (index < m_Results.Length && !m_Results[index].isMainRepresentation) - { - subAssetInstanceIDs.Add(m_Results[index].instanceID); - index++; - } - return subAssetInstanceIDs; - } - } - Debug.LogError("Not main rep " + mainAssetInstanceID); - return new List(); - } - - public int AddSubItemsOfMainRepresentation(int mainRepresentionIndex, List visibleItems) - { - int count = 0; - int index = mainRepresentionIndex + 1; // Start after the main representation - while (index < m_Results.Length && !m_Results[index].isMainRepresentation) - { - if (visibleItems != null) - visibleItems.Add(m_Results[index]); - index++; - count++; - } - return count; - } - } - - internal class FilteredHierarchyProperty : IHierarchyProperty - { - FilteredHierarchy m_Hierarchy; - int m_Position = -1; - - public static IHierarchyProperty CreateHierarchyPropertyForFilter(FilteredHierarchy filteredHierarchy) - { - if (filteredHierarchy.searchFilter.GetState() != SearchFilter.State.EmptySearchFilter) - return new FilteredHierarchyProperty(filteredHierarchy); - else - return new HierarchyProperty(filteredHierarchy.hierarchyType, false); - } - - public FilteredHierarchyProperty(FilteredHierarchy filter) - { - m_Hierarchy = filter; - } - - public void Reset() - { - m_Position = -1; - } - - public int instanceID - { - get { return m_Hierarchy.results[m_Position].instanceID; } - } - - public Object pptrValue - { - get { return EditorUtility.InstanceIDToObject(instanceID); } - } - - public string name - { - get { return m_Hierarchy.results[m_Position].name; } - } - - public bool hasChildren - { - get { return m_Hierarchy.results[m_Position].hasChildren; } - } - - public bool isMainRepresentation - { - get { return m_Hierarchy.results[m_Position].isMainRepresentation; } - } - - public bool hasFullPreviewImage - { - get { return m_Hierarchy.results[m_Position].hasFullPreviewImage; } - } - - public IconDrawStyle iconDrawStyle - { - get { return m_Hierarchy.results[m_Position].iconDrawStyle; } - } - - public bool isFolder - { - get { return m_Hierarchy.results[m_Position].isFolder; } - } - - public int depth - { - get { return 0; } - } - - public int row - { - get { return m_Position; } - } - - public int colorCode - { - get { return m_Hierarchy.results[m_Position].colorCode; } - } - - public bool IsExpanded(int[] expanded) - { - return false; - } - - public string guid - { - get { return m_Hierarchy.results[m_Position].guid; } - } - - public bool isValid - { - get { return m_Hierarchy.results != null && m_Position < m_Hierarchy.results.Length && m_Position >= 0; } - } - - public Texture2D icon - { - get { return m_Hierarchy.results[m_Position].icon; } - } - - public bool Next(int[] expanded) - { - m_Position++; - return m_Position < m_Hierarchy.results.Length; - } - - public bool NextWithDepthCheck(int[] expanded, int minDepth) - { - // Depth check does not make sense for filtered properties as tree info is lost - return Next(expanded); - } - - public bool Previous(int[] expanded) - { - m_Position--; - return m_Position >= 0; - } - - public bool Parent() - { - return false; - } - - public int[] ancestors - { - get - { - return new int[0]; - } - } - - public bool Find(int _instanceID, int[] expanded) - { - Reset(); - while (Next(expanded)) - { - if (instanceID == _instanceID) - return true; - } - return false; - } - - public int[] FindAllAncestors(int[] instanceIDs) - { - return new int[0]; - } - - public bool Skip(int count, int[] expanded) - { - m_Position += count; - return m_Position < m_Hierarchy.results.Length; - } - - public int CountRemaining(int[] expanded) - { - return m_Hierarchy.results.Length - m_Position - 1; - } - } -} diff --git a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs deleted file mode 100644 index b1ae653853..0000000000 --- a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs +++ /dev/null @@ -1,793 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using UnityEditor.Audio; -using UnityEditor.ProjectWindowCallback; -using UnityEditor.SceneManagement; -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.Internal; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class DragAndDropDelay - { - public Vector2 mouseDownPosition; - - public bool CanStartDrag() - { - return Vector2.Distance(mouseDownPosition, Event.current.mousePosition) > 6; - } - } - - // Callbacks to be used when creating assets via the project window - // You can extend the EndNameEditAction and write your own callback - // It is done this way instead of via a delegate because the action - // needs to survive an assembly reload. - namespace ProjectWindowCallback - { - public abstract class EndNameEditAction : ScriptableObject - { - public virtual void OnEnable() - { - hideFlags = HideFlags.HideAndDontSave; - } - - public abstract void Action(int instanceId, string pathName, string resourceFile); - - public virtual void CleanUp() - { - DestroyImmediate(this); - } - } - - internal class DoCreateNewAsset : EndNameEditAction - { - public override void Action(int instanceId, string pathName, string resourceFile) - { - AssetDatabase.CreateAsset(EditorUtility.InstanceIDToObject(instanceId), - AssetDatabase.GenerateUniqueAssetPath(pathName)); - ProjectWindowUtil.FrameObjectInProjectWindow(instanceId); - } - } - - internal class DoCreateFolder : EndNameEditAction - { - public override void Action(int instanceId, string pathName, string resourceFile) - { - string guid = AssetDatabase.CreateFolder(Path.GetDirectoryName(pathName), Path.GetFileName(pathName)); - Object o = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid), typeof(Object)); - ProjectWindowUtil.ShowCreatedAsset(o); - } - } - - internal class DoCreateScene : EndNameEditAction - { - public override void Action(int instanceId, string pathName, string resourceFile) - { - bool createDefaultGameObjects = true; - if (EditorSceneManager.CreateSceneAsset(pathName, createDefaultGameObjects)) - { - Object sceneAsset = AssetDatabase.LoadAssetAtPath(pathName, typeof(SceneAsset)); - ProjectWindowUtil.ShowCreatedAsset(sceneAsset); - } - } - } - - internal class DoCreateFolderWithTemplates : EndNameEditAction - { - private const string kResourcesTemplatePath = "Resources/ScriptTemplates"; - - public IList templates { get; set; } - - public override void Action(int instanceId, string pathName, string resourceFile) - { - var fileName = Path.GetFileName(pathName); - string guid = AssetDatabase.CreateFolder(Path.GetDirectoryName(pathName), fileName); - string basePath = Path.Combine(EditorApplication.applicationContentsPath, kResourcesTemplatePath); - - foreach (var template in templates ?? Enumerable.Empty()) - { - var templateNameWithoutTxt = template.Replace(".txt", string.Empty); - var templateExtension = Path.GetExtension(templateNameWithoutTxt); - - ProjectWindowUtil.CreateScriptAssetFromTemplate(Path.Combine(pathName, fileName + templateExtension), Path.Combine(basePath, template)); - } - - UnityEngine.Object o = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid), typeof(UnityEngine.Object)); - ProjectWindowUtil.ShowCreatedAsset(o); - } - } - - internal class DoCreatePrefab : EndNameEditAction - { - public override void Action(int instanceId, string pathName, string resourceFile) - { - Object o = PrefabUtility.CreateEmptyPrefab(pathName); - ProjectWindowUtil.ShowCreatedAsset(o); - } - } - - internal class DoCreateScriptAsset : EndNameEditAction - { - public override void Action(int instanceId, string pathName, string resourceFile) - { - Object o = ProjectWindowUtil.CreateScriptAssetFromTemplate(pathName, resourceFile); - ProjectWindowUtil.ShowCreatedAsset(o); - } - } - - internal class DoCreateAssetWithContent : EndNameEditAction - { - public string filecontent; - public override void Action(int instanceId, string pathName, string resourceFile) - { - Object o = ProjectWindowUtil.CreateScriptAssetWithContent(pathName, filecontent); - ProjectWindowUtil.ShowCreatedAsset(o); - } - } - - internal class DoCreateAnimatorController : EndNameEditAction - { - public override void Action(int instanceId, string pathName, string resourceFile) - { - Animations.AnimatorController controller = Animations.AnimatorController.CreateAnimatorControllerAtPath(pathName); - ProjectWindowUtil.ShowCreatedAsset(controller); - } - } - - internal class DoCreateAudioMixer : EndNameEditAction - { - public override void Action(int instanceId, string pathName, string resourceFile) - { - AudioMixerController controller = AudioMixerController.CreateMixerControllerAtPath(pathName); - - // 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 - if (!string.IsNullOrEmpty(resourceFile)) - { - int outputInstanceID; - if (System.Int32.TryParse(resourceFile, out outputInstanceID)) - { - var outputGroup = InternalEditorUtility.GetObjectFromInstanceID(outputInstanceID) as AudioMixerGroupController; - if (outputGroup != null) - controller.outputAudioMixerGroup = outputGroup; - } - } - ProjectWindowUtil.ShowCreatedAsset(controller); - } - } - - internal class DoCreateSpritePolygon : EndNameEditAction - { - public int sides; - public override void Action(int instanceId, string pathName, string resourceFile) - { - bool showSpriteEditorAfter = false; - if (sides < 0) - { - sides = 5; - showSpriteEditorAfter = true; - } - - Sprites.SpriteUtility.CreateSpritePolygonAssetAtPath(pathName, sides); - if (showSpriteEditorAfter) - { - Selection.activeObject = AssetDatabase.LoadMainAssetAtPath(pathName); - SpriteEditorWindow.GetWindow(); - } - } - } - } - - public class ProjectWindowUtil - { - [MenuItem("Assets/Create/GUI Skin", false, 601)] - public static void CreateNewGUISkin() - { - GUISkin skin = ScriptableObject.CreateInstance(); - GUISkin original = Resources.GetBuiltinResource(typeof(GUISkin), "GameSkin/GameSkin.guiskin") as GUISkin; - if (original) - EditorUtility.CopySerialized(original, skin); - else - Debug.LogError("Internal error: unable to load builtin GUIskin"); - - CreateAsset(skin, "New GUISkin.guiskin"); - } - - // Returns the path of currently selected folder. If multiple are selected, returns the first one. - internal static string GetActiveFolderPath() - { - ProjectBrowser projectBrowser = GetProjectBrowserIfExists(); - - if (projectBrowser == null) - return "Assets"; - - return projectBrowser.GetActiveFolderPath(); - } - - internal static void EndNameEditAction(EndNameEditAction action, int instanceId, string pathName, string resourceFile) - { - pathName = AssetDatabase.GenerateUniqueAssetPath(pathName); - if (action != null) - { - action.Action(instanceId, pathName, resourceFile); - action.CleanUp(); - } - } - - // Create a standard Object-derived asset. - public static void CreateAsset(Object asset, string pathName) - { - StartNameEditingIfProjectWindowExists(asset.GetInstanceID(), ScriptableObject.CreateInstance(), pathName, AssetPreview.GetMiniThumbnail(asset), null); - } - - // Create a folder - public static void CreateFolder() - { - StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Folder", EditorGUIUtility.IconContent(EditorResourcesUtility.emptyFolderIconName).image as Texture2D, null); - } - - internal static void CreateFolderWithTemplates(string defaultName, params string[] templates) - { - var endNameEditAction = ScriptableObject.CreateInstance(); - endNameEditAction.templates = templates; - ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, endNameEditAction, defaultName, EditorGUIUtility.IconContent(EditorResourcesUtility.emptyFolderIconName).image as Texture2D, null); - } - - public static void CreateScene() - { - StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Scene.unity", EditorGUIUtility.FindTexture(typeof(SceneAsset)), null); - } - - // Create a prefab - public static void CreatePrefab() - { - StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Prefab.prefab", EditorGUIUtility.IconContent("Prefab Icon").image as Texture2D, null); - } - - internal static void CreateAssetWithContent(string filename, string content, Texture2D icon = null, string resourceFile = null) - { - var action = ScriptableObject.CreateInstance(); - action.filecontent = content; - StartNameEditingIfProjectWindowExists(0, action, filename, icon, resourceFile); - } - - static void CreateScriptAsset(string templatePath, string destName) - { - var templateFilename = Path.GetFileName(templatePath); - if (templateFilename.ToLower().Contains("editortest") || templateFilename.ToLower().Contains("editmode")) - { - var tempPath = AssetDatabase.GetUniquePathNameAtSelectedPath(destName); - if (!tempPath.ToLower().Contains("/editor/")) - { - tempPath = tempPath.Substring(0, tempPath.Length - destName.Length - 1); - var editorDirPath = Path.Combine(tempPath, "Editor"); - if (!Directory.Exists(editorDirPath)) - AssetDatabase.CreateFolder(tempPath, "Editor"); - tempPath = Path.Combine(editorDirPath, destName); - tempPath = tempPath.Replace("\\", "/"); - } - destName = tempPath; - } - - Texture2D icon = null; - switch (Path.GetExtension(destName)) - { - case ".js": - icon = EditorGUIUtility.IconContent("js Script Icon").image as Texture2D; - break; - case ".cs": - icon = EditorGUIUtility.IconContent("cs Script Icon").image as Texture2D; - break; - case ".boo": - icon = EditorGUIUtility.IconContent("boo Script Icon").image as Texture2D; - break; - case ".shader": - icon = EditorGUIUtility.IconContent("Shader Icon").image as Texture2D; - break; - case ".asmdef": - icon = EditorGUIUtility.IconContent("AssemblyDefinitionAsset Icon").image as Texture2D; - break; - default: - icon = EditorGUIUtility.IconContent("TextAsset Icon").image as Texture2D; - break; - } - StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), destName, icon, templatePath); - } - - public static void ShowCreatedAsset(Object o) - { - // Show it - Selection.activeObject = o; - if (o) - FrameObjectInProjectWindow(o.GetInstanceID()); - } - - static private void CreateAnimatorController() - { - var icon = EditorGUIUtility.IconContent("AnimatorController Icon").image as Texture2D; - StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Animator Controller.controller", icon, null); - } - - static private void CreateAudioMixer() - { - var icon = EditorGUIUtility.IconContent("AudioMixerController Icon").image as Texture2D; - StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "NewAudioMixer.mixer", icon, null); - } - - static private void CreateSpritePolygon(int sides) - { - string assetName = ""; - switch (sides) - { - case 0: - assetName = "Square"; - break; - case 3: - assetName = "Triangle"; - break; - case 4: - assetName = "Diamond"; - break; - case 6: - assetName = "Hexagon"; - break; - case 42: - // http://hitchhikers.wikia.com/wiki/42 - assetName = "Everythingon"; - break; - case 128: - assetName = "Circle"; - break; - default: - assetName = "Polygon"; - break; - } - - var icon = EditorGUIUtility.IconContent("Sprite Icon").image as Texture2D; - DoCreateSpritePolygon action = ScriptableObject.CreateInstance(); - action.sides = sides; - StartNameEditingIfProjectWindowExists(0, action, assetName + ".png", icon, null); - } - - internal static string SetLineEndings(string content, LineEndingsMode lineEndingsMode) - { - const string windowsLineEndings = "\r\n"; - const string unixLineEndings = "\n"; - - string preferredLineEndings; - - switch (lineEndingsMode) - { - case LineEndingsMode.OSNative: - if (Application.platform == RuntimePlatform.WindowsEditor) - preferredLineEndings = windowsLineEndings; - else - preferredLineEndings = unixLineEndings; - break; - case LineEndingsMode.Unix: - preferredLineEndings = unixLineEndings; - break; - case LineEndingsMode.Windows: - preferredLineEndings = windowsLineEndings; - break; - default: - preferredLineEndings = unixLineEndings; - break; - } - - content = Regex.Replace(content, @"\r\n?|\n", preferredLineEndings); - - return content; - } - - internal static Object CreateScriptAssetWithContent(string pathName, string templateContent) - { - templateContent = SetLineEndings(templateContent, EditorSettings.lineEndingsForNewScripts); - - string fullPath = Path.GetFullPath(pathName); - - // utf8-bom encoding was added for case 510374 in 2012. i think this was the wrong solution. BOM's are - // problematic for diff tools, naive readers and writers (of which we have many!), and generally not - // something most people think about. you wouldn't believe how many unity source files have BOM's embedded - // in the middle of them for no reason. copy paste problem? bad tool? unity should instead have been fixed - // to read all files that have no BOM as utf8 by default, and then we just strip them all, always, from - // files we control. perhaps we'll do this one day and this next line can be removed. -scobi - var encoding = new System.Text.UTF8Encoding(/*encoderShouldEmitUTF8Identifier:*/ true); - - File.WriteAllText(fullPath, templateContent, encoding); - - // Import the asset - AssetDatabase.ImportAsset(pathName); - - return AssetDatabase.LoadAssetAtPath(pathName, typeof(Object)); - } - - internal static Object CreateScriptAssetFromTemplate(string pathName, string resourceFile) - { - string content = File.ReadAllText(resourceFile); - - // #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. - content = content.Replace("#NOTRIM#", ""); - - // macro replacement - string baseFile = Path.GetFileNameWithoutExtension(pathName); - - content = content.Replace("#NAME#", baseFile); - string baseFileNoSpaces = baseFile.Replace(" ", ""); - content = content.Replace("#SCRIPTNAME#", baseFileNoSpaces); - - // if the script name begins with an uppercase character we support a lowercase substitution variant - if (char.IsUpper(baseFileNoSpaces, 0)) - { - baseFileNoSpaces = char.ToLower(baseFileNoSpaces[0]) + baseFileNoSpaces.Substring(1); - content = content.Replace("#SCRIPTNAME_LOWER#", baseFileNoSpaces); - } - else - { - // still allow the variant, but change the first character to upper and prefix with "my" - baseFileNoSpaces = "my" + char.ToUpper(baseFileNoSpaces[0]) + baseFileNoSpaces.Substring(1); - content = content.Replace("#SCRIPTNAME_LOWER#", baseFileNoSpaces); - } - - return CreateScriptAssetWithContent(pathName, content); - } - - public static void StartNameEditingIfProjectWindowExists(int instanceID, EndNameEditAction endAction, string pathName, Texture2D icon, string resourceFile) - { - ProjectBrowser pb = GetProjectBrowserIfExists(); - if (pb) - { - pb.Focus(); - pb.BeginPreimportedNameEditing(instanceID, endAction, pathName, icon, resourceFile); - pb.Repaint(); - } - else - { - if (!pathName.StartsWith("assets/", System.StringComparison.CurrentCultureIgnoreCase)) - pathName = "Assets/" + pathName; - EndNameEditAction(endAction, instanceID, pathName, resourceFile); - Selection.activeObject = EditorUtility.InstanceIDToObject(instanceID); - } - } - - static ProjectBrowser GetProjectBrowserIfExists() - { - return ProjectBrowser.s_LastInteractedProjectBrowser; - } - - internal static void FrameObjectInProjectWindow(int instanceID) - { - ProjectBrowser pb = GetProjectBrowserIfExists(); - if (pb) - { - pb.FrameObject(instanceID, false); - } - } - - // InstanceIDs larger than this is considered a favorite by the projectwindows - internal static int k_FavoritesStartInstanceID = 1000000000; - internal static string k_DraggingFavoriteGenericData = "DraggingFavorite"; - internal static string k_IsFolderGenericData = "IsFolder"; - - internal static bool IsFavoritesItem(int instanceID) - { - return instanceID >= k_FavoritesStartInstanceID; - } - - internal static void StartDrag(int draggedInstanceID, List selectedInstanceIDs) - { - DragAndDrop.PrepareStartDrag(); - - string title = ""; - if (IsFavoritesItem(draggedInstanceID)) - { - DragAndDrop.SetGenericData(k_DraggingFavoriteGenericData, draggedInstanceID); - } - else - { - // Normal assets dragging - bool isFolder = IsFolder(draggedInstanceID); - DragAndDrop.objectReferences = GetDragAndDropObjects(draggedInstanceID, selectedInstanceIDs); - DragAndDrop.SetGenericData(k_IsFolderGenericData, isFolder ? "isFolder" : ""); - string[] paths = GetDragAndDropPaths(draggedInstanceID, selectedInstanceIDs); - if (paths.Length > 0) - DragAndDrop.paths = paths; - - if (DragAndDrop.objectReferences.Length > 1) - title = ""; - else - title = ObjectNames.GetDragAndDropTitle(InternalEditorUtility.GetObjectFromInstanceID(draggedInstanceID)); - } - - DragAndDrop.StartDrag(title); - } - - internal static Object[] GetDragAndDropObjects(int draggedInstanceID, List selectedInstanceIDs) - { - List outList = new List(selectedInstanceIDs.Count); - if ((Event.current.control || Event.current.command) && !selectedInstanceIDs.Contains(draggedInstanceID)) - { - selectedInstanceIDs.Add(draggedInstanceID); - } - if (selectedInstanceIDs.Contains(draggedInstanceID)) - { - for (int i = 0; i < selectedInstanceIDs.Count; ++i) - { - Object obj = InternalEditorUtility.GetObjectFromInstanceID(selectedInstanceIDs[i]); - if (obj != null) - outList.Add(obj); - } - } - else - { - Object obj = InternalEditorUtility.GetObjectFromInstanceID(draggedInstanceID); - if (obj != null) - outList.Add(obj); - } - return outList.ToArray(); - } - - internal static string[] GetDragAndDropPaths(int draggedInstanceID, List selectedInstanceIDs) - { - // Assets - List paths = new List(); - foreach (int instanceID in selectedInstanceIDs) - { - if (AssetDatabase.IsMainAsset(instanceID)) - { - string path = AssetDatabase.GetAssetPath(instanceID); - paths.Add(path); - } - } - - string dragPath = AssetDatabase.GetAssetPath(draggedInstanceID); - if (!string.IsNullOrEmpty(dragPath)) - { - if (paths.Contains(dragPath)) - { - return paths.ToArray(); - } - else if (Event.current.control || Event.current.command) - { - paths.Add(dragPath); - return paths.ToArray(); - } - else - { - return new[] { dragPath }; - } - } - return new string[0]; - } - - // Returns instanceID of folders (and main asset if input is a subasset) up until and including the Assets folder - public static int[] GetAncestors(int instanceID) - { - List ancestors = new List(); - - // Ensure we add the main asset as ancestor if input is a subasset - int mainAssetInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(AssetDatabase.GetAssetPath(instanceID)); - bool isSubAsset = mainAssetInstanceID != instanceID; - if (isSubAsset) - ancestors.Add(mainAssetInstanceID); - - // Find ancestors of main aset - string currentFolderPath = GetContainingFolder(AssetDatabase.GetAssetPath(mainAssetInstanceID)); - while (!string.IsNullOrEmpty(currentFolderPath)) - { - int currentInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(currentFolderPath); - ancestors.Add(currentInstanceID); - currentFolderPath = GetContainingFolder(AssetDatabase.GetAssetPath(currentInstanceID)); - } - - return ancestors.ToArray(); - } - - public static bool IsFolder(int instanceID) - { - return AssetDatabase.IsValidFolder(AssetDatabase.GetAssetPath(instanceID)); - } - - // Returns containing folder if possible otherwise null. - // Trims any trailing forward slashes - public static string GetContainingFolder(string path) - { - if (string.IsNullOrEmpty(path)) - return null; - - path = path.Trim('/'); - int pos = path.LastIndexOf("/", StringComparison.Ordinal); - if (pos != -1) - { - return path.Substring(0, pos); - } - - // Could not determine containing folder - return null; - } - - // Input the following list: - // assets/flesh/big - // assets/icons/duke - // assets/icons/duke/snake - // assets/icons/duke/zoo - // - // ... And the returned list becomes: - // assets/flesh/big - // assets/icons/duke - - // Returned paths are trimmed for ending slashes - public static string[] GetBaseFolders(string[] folders) - { - if (folders.Length <= 1) - return folders; - - List result = new List(); - List sortedFolders = new List(folders); - - // Remove forward slashes before sorting otherwise will "Assets 1/" come before "Assets/" - // which we do not want in the find base folders section below - for (int i = 0; i < sortedFolders.Count; ++i) - sortedFolders[i] = sortedFolders[i].Trim('/'); - - sortedFolders.Sort(); - - // Ensure folder paths are ending with '/' so e.g: "assets/" is not found in "assets 1/". - // If we did not end with '/' then "assets" could be found in "assets 1" - // which is not what we want when finding base folders - for (int i = 0; i < sortedFolders.Count; ++i) - if (!sortedFolders[i].EndsWith("/")) - sortedFolders[i] = sortedFolders[i] + "/"; - - // Find base folders - // We assume sortedFolders is sorted with less first. E.g: {assets/, assets/icons/} - string curPath = sortedFolders[0]; - result.Add(curPath); - for (int i = 1; i < sortedFolders.Count; ++i) - { - // Ensure path matches from start of curPath (to ensure "assets/monkey" and "npc/assets/monkey" both are returned as base folders) - bool startOfPathMatches = sortedFolders[i].IndexOf(curPath, StringComparison.Ordinal) == 0; - if (!startOfPathMatches) - { - // Add tested path if not part of current path and use tested path as new base - result.Add(sortedFolders[i]); - curPath = sortedFolders[i]; - } - } - - // Remove forward slashes again (added above) - for (int i = 0; i < result.Count; ++i) - result[i] = result[i].Trim('/'); - - return result.ToArray(); - } - - internal static void DuplicateSelectedAssets() - { - Selection.objects = DuplicateAssets(Selection.objects).ToArray(); - } - - // Deletes the assets of the instance IDs, with an optional user confirmation dialog. - // Returns true if the delete operation was successfully performed on all assets. - // Note: Zero input assets always returns true. - // Also note that the operation cannot be undone even if some operations failed. - internal static bool DeleteAssets(List instanceIDs, bool askIfSure) - { - if (instanceIDs.Count == 0) - return true; - - bool foundAssetsFolder = instanceIDs.IndexOf(ProjectBrowserColumnOneTreeViewDataSource.GetAssetsFolderInstanceID()) >= 0; - if (foundAssetsFolder) - { - string title = "Cannot Delete"; - EditorUtility.DisplayDialog(title, "Deleting the 'Assets' folder is not allowed", "Ok"); - return false; - } - - var paths = GetMainPathsOfAssets(instanceIDs).ToList(); - - if (paths.Count == 0) - return false; - - if (askIfSure) - { - string title = "Delete selected asset"; - if (paths.Count > 1) - title = title + "s"; - title = title + "?"; - - int maxCount = 3; - string infotext = ""; - for (int i = 0; i < paths.Count && i < maxCount; ++i) - infotext += " " + paths[i] + "\n"; - if (paths.Count > maxCount) - infotext += " ...\n"; - infotext += "\nYou cannot undo this action."; - if (!EditorUtility.DisplayDialog(title, infotext, "Delete", "Cancel")) - { - return false; - } - } - - bool success = true; - - AssetDatabase.StartAssetEditing(); - foreach (string path in paths) - { - if (!AssetDatabase.MoveAssetToTrash(path)) - success = false; - } - AssetDatabase.StopAssetEditing(); - - return success; - } - - internal static IEnumerable DuplicateAssets(IEnumerable assets) - { - AssetDatabase.Refresh(); - - var copiedPaths = new List(); - Object firstDuplicatedObjectToFail = null; - - foreach (var asset in assets) - { - var assetPath = AssetDatabase.GetAssetPath(asset); - - // if duplicating a sub-asset, then create a copy next to the main asset file - if (AssetDatabase.IsSubAsset(asset)) - { - if (asset is ISubAssetNotDuplicatable) - { - firstDuplicatedObjectToFail = firstDuplicatedObjectToFail ? firstDuplicatedObjectToFail : asset; - continue; - } - - var extension = NativeFormatImporterUtility.GetExtensionForAsset(asset); - var newPath = AssetDatabase.GenerateUniqueAssetPath( - Path.Combine(Path.GetDirectoryName(assetPath), string.Format("{0}.{1}", asset.name, extension)) - ); - AssetDatabase.CreateAsset(Object.Instantiate(asset), newPath); - copiedPaths.Add(newPath); - } - // otherwise duplicate the main asset file - else if (EditorUtility.IsPersistent(asset)) - { - var newPath = AssetDatabase.GenerateUniqueAssetPath(assetPath); - if (newPath.Length > 0 && AssetDatabase.CopyAsset(assetPath, newPath)) - copiedPaths.Add(newPath); - } - } - - if (firstDuplicatedObjectToFail != null) - Debug.LogError("Duplication error: One or more sub assets could not be duplicated directly, use the appropriate editor instead", firstDuplicatedObjectToFail); - - AssetDatabase.Refresh(); - - return copiedPaths.Select(AssetDatabase.LoadMainAssetAtPath); - } - - internal static IEnumerable DuplicateAssets(IEnumerable instanceIDs) - { - return DuplicateAssets(instanceIDs.Select(id => EditorUtility.InstanceIDToObject(id))); - } - - internal static IEnumerable GetMainPathsOfAssets(IEnumerable instanceIDs) - { - foreach (var instanceID in instanceIDs) - { - if (AssetDatabase.IsMainAsset(instanceID)) - { - yield return AssetDatabase.GetAssetPath(instanceID); - } - } - } - } -} diff --git a/Editor/Mono/ProjectWindow/SearchFilter.cs b/Editor/Mono/ProjectWindow/SearchFilter.cs deleted file mode 100644 index 47ae8995fb..0000000000 --- a/Editor/Mono/ProjectWindow/SearchFilter.cs +++ /dev/null @@ -1,295 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using UnityEditor.Collaboration; -using UnityEditor.Connect; - -namespace UnityEditor -{ - [System.Serializable] - internal class SearchFilter - { - public enum SearchArea - { - AllAssets, - SelectedFolders, - AssetStore - } - - public enum State - { - EmptySearchFilter, - FolderBrowsing, - SearchingInAllAssets, - SearchingInFolders, - SearchingInAssetStore - } - - // Searching - [SerializeField] - private string m_NameFilter = ""; - [SerializeField] - private string[] m_ClassNames = new string[0]; - [SerializeField] - private string[] m_AssetLabels = new string[0]; - [SerializeField] - private string[] m_AssetBundleNames = new string[0]; - [SerializeField] - private string[] m_VersionControlStates = new string[0]; - [SerializeField] - private string[] m_SoftLockControlStates = new string[0]; - [SerializeField] - private int[] m_ReferencingInstanceIDs = new int[0]; - [SerializeField] - private string[] m_ScenePaths; - [SerializeField] - 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 - [SerializeField] - SearchArea m_SearchArea = SearchArea.AllAssets; - - // Folder browsing - [SerializeField] - private string[] m_Folders = new string[0]; - - // Interface - public string nameFilter {get {return m_NameFilter; } set { m_NameFilter = value; } } - public string[] classNames { get {return m_ClassNames; } set {m_ClassNames = value; }} - public string[] assetLabels {get {return m_AssetLabels; } set {m_AssetLabels = value; }} - public string[] versionControlStates { get { return m_VersionControlStates; } set { m_VersionControlStates = value; } } - public string[] softLockControlStates { get { return m_SoftLockControlStates; } set { m_SoftLockControlStates = value; } } - public string[] assetBundleNames {get {return m_AssetBundleNames; } set {m_AssetBundleNames = value; }} - public int[] referencingInstanceIDs { get { return m_ReferencingInstanceIDs; } set { m_ReferencingInstanceIDs = value; } } - public string[] scenePaths { get { return m_ScenePaths; } set { m_ScenePaths = value; } } - public bool showAllHits { get { return m_ShowAllHits; } set { m_ShowAllHits = value; }} - public string[] folders { get {return m_Folders; } set {m_Folders = value; }} - public SearchArea searchArea { get { return m_SearchArea; } set { m_SearchArea = value; }} - - public void ClearSearch() - { - m_NameFilter = ""; - m_ClassNames = new string[0]; - m_AssetLabels = new string[0]; - m_AssetBundleNames = new string[0]; - m_ReferencingInstanceIDs = new int[0]; - m_ScenePaths = new string[0]; - m_VersionControlStates = new string[0]; - m_SoftLockControlStates = new string[0]; - m_ShowAllHits = false; - } - - bool IsNullOrEmpty(T[] list) - { - return (list == null || list.Length == 0); - } - - public State GetState() - { - bool isSearchActive = !string.IsNullOrEmpty(m_NameFilter) || - !IsNullOrEmpty(m_AssetLabels) || - !IsNullOrEmpty(m_ClassNames) || - !IsNullOrEmpty(m_AssetBundleNames) || - !IsNullOrEmpty(m_ReferencingInstanceIDs); - - isSearchActive = isSearchActive || !IsNullOrEmpty(m_VersionControlStates); - isSearchActive = isSearchActive || !IsNullOrEmpty(m_SoftLockControlStates); - - - bool foldersActive = !IsNullOrEmpty(m_Folders); - - if (isSearchActive) - { - if (m_SearchArea == SearchArea.AssetStore) - return State.SearchingInAssetStore; - - if (foldersActive && m_SearchArea == SearchArea.SelectedFolders) - return State.SearchingInFolders; - - return State.SearchingInAllAssets; - } - else if (foldersActive) - { - return State.FolderBrowsing; - } - - return State.EmptySearchFilter; - } - - public bool IsSearching() - { - State state = GetState(); - return (state == State.SearchingInAllAssets || state == State.SearchingInFolders || state == State.SearchingInAssetStore); - } - - public bool SetNewFilter(SearchFilter newFilter) - { - bool changed = false; - - if (newFilter.m_NameFilter != m_NameFilter) - { - m_NameFilter = newFilter.m_NameFilter; - changed = true; - } - - if (newFilter.m_ClassNames != m_ClassNames) - { - m_ClassNames = newFilter.m_ClassNames; - changed = true; - } - - if (newFilter.m_Folders != m_Folders) - { - m_Folders = newFilter.m_Folders; - changed = true; - } - if (newFilter.m_VersionControlStates != m_VersionControlStates) - { - m_VersionControlStates = newFilter.m_VersionControlStates; - changed = true; - } - if (newFilter.m_SoftLockControlStates != m_SoftLockControlStates) - { - m_SoftLockControlStates = newFilter.m_SoftLockControlStates; - changed = true; - } - if (newFilter.m_AssetLabels != m_AssetLabels) - { - m_AssetLabels = newFilter.m_AssetLabels; - changed = true; - } - - if (newFilter.m_AssetBundleNames != m_AssetBundleNames) - { - m_AssetBundleNames = newFilter.m_AssetBundleNames; - changed = true; - } - - if (newFilter.m_ReferencingInstanceIDs != m_ReferencingInstanceIDs) - { - m_ReferencingInstanceIDs = newFilter.m_ReferencingInstanceIDs; - changed = true; - } - - if (newFilter.m_ScenePaths != m_ScenePaths) - { - m_ScenePaths = newFilter.m_ScenePaths; - changed = true; - } - - if (newFilter.m_SearchArea != m_SearchArea) - { - m_SearchArea = newFilter.m_SearchArea; - changed = true; - } - - m_ShowAllHits = newFilter.m_ShowAllHits; - - - return changed; - } - - // Debug - public override string ToString() - { - string result = "SearchFilter: "; - - result += string.Format("[Area: {0}, State: {1}]", m_SearchArea, GetState()); - - if (!string.IsNullOrEmpty(m_NameFilter)) - result += "[Name: " + m_NameFilter + "]"; - - if (m_AssetLabels != null && m_AssetLabels.Length > 0) - result += "[Labels: " + m_AssetLabels[0] + "]"; - - if (m_VersionControlStates != null && m_VersionControlStates.Length > 0) - result += "[VersionStates: " + m_VersionControlStates[0] + "]"; - - if (m_SoftLockControlStates != null && m_SoftLockControlStates.Length > 0) - result += "[SoftLockStates: " + m_SoftLockControlStates[0] + "]"; - - if (m_AssetBundleNames != null && m_AssetBundleNames.Length > 0) - result += "[AssetBundleNames: " + m_AssetBundleNames[0] + "]"; - - if (m_ClassNames != null && m_ClassNames.Length > 0) - result += "[Types: " + m_ClassNames[0] + " (" + m_ClassNames.Length + ")]"; - - if (m_ReferencingInstanceIDs != null && m_ReferencingInstanceIDs.Length > 0) - result += "[RefIDs: " + m_ReferencingInstanceIDs[0] + "]"; - - if (m_Folders != null && m_Folders.Length > 0) - result += "[Folders: " + m_Folders[0] + "]"; - - result += "[ShowAllHits: " + showAllHits + "]"; - return result; - } - - internal string FilterToSearchFieldString() - { - string result = ""; - if (!string.IsNullOrEmpty(m_NameFilter)) - result += m_NameFilter; - - // See SearchUtility.cs for search tokens - AddToString("t:", m_ClassNames, ref result); - AddToString("l:", m_AssetLabels, ref result); - AddToString("v:", m_VersionControlStates, ref result); - AddToString("s:", m_SoftLockControlStates, ref result); - AddToString("b:", m_AssetBundleNames, ref result); - return result; - } - - void AddToString(string prefix, T[] list, ref string result) - { - if (list == null) - return; - if (result == null) - result = ""; - - foreach (T item in list) - { - if (!string.IsNullOrEmpty(result)) - result += " "; - result += prefix + item; - } - } - - // Keeps current SearchArea - internal void SearchFieldStringToFilter(string searchString) - { - ClearSearch(); - - if (string.IsNullOrEmpty(searchString)) - return; - - SearchUtility.ParseSearchString(searchString, this); - } - - internal static SearchFilter CreateSearchFilterFromString(string searchText) - { - SearchFilter searchFilter = new SearchFilter(); - SearchUtility.ParseSearchString(searchText, searchFilter); - return searchFilter; - } - - // Split text into words separated by whitespace but handle quotes - // E.g 'one man' becomes: 'one', 'man' - // E.g '"one man' becomes: 'one', 'man' - // E.g '"one man"' becomes: 'one man' - public static string[] Split(string text) - { - if (string.IsNullOrEmpty(text)) - return new string[0]; - - List words = new List(); - foreach (Match m in Regex.Matches(text, "\".+?\"|\\S+")) - { - words.Add(m.Value.Replace("\"", "")); // remove quotes - } - - return words.ToArray(); - } - } // end of class SearchFilter -} diff --git a/Editor/Mono/ProjectWindow/SearchableEditorWindow.cs b/Editor/Mono/ProjectWindow/SearchableEditorWindow.cs deleted file mode 100644 index 8a5d6179e9..0000000000 --- a/Editor/Mono/ProjectWindow/SearchableEditorWindow.cs +++ /dev/null @@ -1,241 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections.Generic; - -namespace UnityEditor -{ - public class SearchableEditorWindow : EditorWindow - { - public enum SearchMode { All, Name, Type, Label, AssetBundleName }; - public enum SearchModeHierarchyWindow { All, Name, Type }; - - internal static SearchFilter CreateFilter(string searchString, SearchMode searchMode) - { - SearchFilter filter = new SearchFilter(); - if (string.IsNullOrEmpty(searchString)) - return filter; - - switch (searchMode) - { - case SearchMode.All: - if (!SearchUtility.ParseSearchString(searchString, filter)) - { - // Use search string for all SearchModes: name, types and labels - filter.nameFilter = searchString; - filter.classNames = new[] { searchString }; - filter.assetLabels = new[] { searchString }; - filter.assetBundleNames = new[] { searchString }; - filter.showAllHits = true; - } - break; - case SearchMode.Name: - filter.nameFilter = searchString; - break; - case SearchMode.Type: - filter.classNames = new[] { searchString }; - break; - case SearchMode.Label: - filter.assetLabels = new[] { searchString }; - break; - case SearchMode.AssetBundleName: - filter.assetBundleNames = new[] { searchString }; - break; - } - - return filter; - } - - static List searchableWindows = new List(); - private static int s_SearchableEditorWindowSearchField = "SearchableEditorWindowSearchField".GetHashCode(); - - internal HierarchyType m_HierarchyType = HierarchyType.Assets; - internal string m_SearchFilter = ""; - internal SearchMode m_SearchMode = SearchMode.All; - bool m_FocusSearchField = false; - bool m_HasSearchFilterFocus = false; - - [MenuItem("Assets/Find References In Scene", false, 25)] - private static void OnSearchForReferences() - { - SearchForReferencesToInstanceID(Selection.activeInstanceID); - } - - [MenuItem("Assets/Find References In Scene", true)] - private static bool OnSearchForReferencesValidate() - { - Object obj = Selection.activeObject; - if (obj != null) - { - if (AssetDatabase.Contains(obj)) - { - string path = AssetDatabase.GetAssetPath(obj); - return !System.IO.Directory.Exists(path); - } - } - - return false; - } - - virtual public void OnEnable() - { - searchableWindows.Add(this); - } - - virtual public void OnDisable() - { - searchableWindows.Remove(this); - } - - internal bool hasSearchFilter - { - get { return m_SearchFilter != ""; } - } - - internal bool hasSearchFilterFocus - { - get { return m_HasSearchFilterFocus; } - set { m_HasSearchFilterFocus = value; } - } - - internal SearchMode searchMode - { - get { return m_SearchMode; } - set { m_SearchMode = value; } - } - - internal static void SearchForReferencesToInstanceID(int instanceID) - { - string searchFilter; - - // only main assets have unique paths (remove "Assets" to make string simpler) - string path = AssetDatabase.GetAssetPath(instanceID).Substring(7); - if (path.IndexOf(' ') != -1) - path = '"' + path + '"'; - - if (AssetDatabase.IsMainAsset(instanceID)) - searchFilter = "ref:" + path; - else - searchFilter = "ref:" + instanceID + ":" + path; - - foreach (SearchableEditorWindow sw in searchableWindows) - { - if (sw.m_HierarchyType == HierarchyType.GameObjects) - { - sw.SetSearchFilter(searchFilter, SearchMode.All, false); - sw.m_HasSearchFilterFocus = true; - sw.Repaint(); - } - } - } - - internal void FocusSearchField() - { - m_FocusSearchField = true; - } - - internal void ClearSearchFilter() - { - SetSearchFilter("", m_SearchMode, true); - // Reset current editor. This is needed, so if the user types into a search field, and then - // a new object is selected, which is not in the filter, with the editor still having keyboard focus, - // the search field gets properly cleared. - - if (EditorGUI.s_RecycledEditor != null) - EditorGUI.s_RecycledEditor.EndEditing(); - } - - internal void SelectPreviousSearchResult() - { - foreach (SearchableEditorWindow sw in searchableWindows) - { - if (sw is SceneHierarchyWindow) - { - ((SceneHierarchyWindow)sw).SelectPrevious(); - return; - } - } - } - - internal void SelectNextSearchResult() - { - foreach (SearchableEditorWindow sw in searchableWindows) - { - if (sw is SceneHierarchyWindow) - { - ((SceneHierarchyWindow)sw).SelectNext(); - return; - } - } - } - - internal virtual void SetSearchFilter(string searchFilter, SearchMode mode, bool setAll) - { - m_SearchMode = mode; - m_SearchFilter = searchFilter; - - if (setAll) - { - foreach (SearchableEditorWindow sw in searchableWindows) - { - if (sw != this && sw.m_HierarchyType == m_HierarchyType && sw.m_HierarchyType != HierarchyType.Assets) - sw.SetSearchFilter(m_SearchFilter, m_SearchMode, false); - } - } - Repaint(); - EditorApplication.Internal_CallSearchHasChanged(); - } - - internal virtual void ClickedSearchField() - { - } - - internal void SearchFieldGUI() - { - SearchFieldGUI(EditorGUILayout.kLabelFloatMaxW * 1.5f); - } - - internal void SearchFieldGUI(float maxWidth) - { - Rect rect = GUILayoutUtility.GetRect(EditorGUILayout.kLabelFloatMaxW * 0.2f, maxWidth, EditorGUI.kSingleLineHeight, EditorGUI.kSingleLineHeight, EditorStyles.toolbarSearchField); - - if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) - ClickedSearchField(); - - GUI.SetNextControlName("SearchFilter"); - if (m_FocusSearchField) - { - EditorGUI.FocusTextInControl("SearchFilter"); - if (Event.current.type == EventType.Repaint) - m_FocusSearchField = false; - } - - int searchMode = (int)m_SearchMode; - - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape && GUI.GetNameOfFocusedControl() == "SearchFilter") - SetSearchFilter("", (SearchMode)searchMode, true); - - string[] enumStrings = System.Enum.GetNames(m_HierarchyType == HierarchyType.GameObjects ? typeof(SearchModeHierarchyWindow) : typeof(SearchMode)); - int searchFieldControlId = GUIUtility.GetControlID(s_SearchableEditorWindowSearchField, FocusType.Keyboard, rect); - - EditorGUI.BeginChangeCheck(); - string searchFilter = EditorGUI.ToolbarSearchField(searchFieldControlId, rect, enumStrings, ref searchMode, m_SearchFilter); - if (EditorGUI.EndChangeCheck()) - SetSearchFilter(searchFilter, (SearchMode)searchMode, true); - - m_HasSearchFilterFocus = GUIUtility.keyboardControl == searchFieldControlId; - - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape && m_SearchFilter != "" && GUIUtility.hotControl == 0) - { - m_SearchFilter = ""; - SetSearchFilter(searchFilter, (SearchMode)searchMode, true); - Event.current.Use(); - m_HasSearchFilterFocus = false; - } - } - } -} diff --git a/Editor/Mono/ProvisioningProfile.cs b/Editor/Mono/ProvisioningProfile.cs deleted file mode 100644 index 22822a3966..0000000000 --- a/Editor/Mono/ProvisioningProfile.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Text.RegularExpressions; -using System.IO; - -namespace UnityEditorInternal -{ - internal class iOSEditorPrefKeys - { - public readonly static string kDefaultiOSAutomaticallySignBuild = "DefaultiOSAutomaticallySignBuild"; - public readonly static string kDefaultiOSAutomaticSignTeamId = "DefaultiOSAutomaticSignTeamId"; - public readonly static string kDefaultiOSProvisioningProfileUUID = "DefaultiOSProvisioningProfileUUID"; - public readonly static string kDefaulttvOSProvisioningProfileUUID = "DefaulttvOSProvisioningProfileUUID"; - } - - internal class ProvisioningProfile - { - private string m_UUID = string.Empty; - - public string UUID { get { return m_UUID; } set { m_UUID = value; } } - - // regex patterns used for finding specific parts of data from a provisioning profile - static readonly string s_FirstLinePattern = "UUID<\\/key>"; - static readonly string s_SecondLinePattern = "((\\w*\\-?){5})"; - - internal static ProvisioningProfile ParseProvisioningProfileAtPath(string pathToFile) - { - ProvisioningProfile profile = new ProvisioningProfile(); - parseFile(pathToFile, profile); - return profile; - } - - internal ProvisioningProfile() {} - internal ProvisioningProfile(string UUID) { m_UUID = UUID; } - - private static void parseFile(string filePath, ProvisioningProfile profile) - { - System.IO.StreamReader file = new System.IO.StreamReader(filePath); - string line; - while ((line = file.ReadLine()) != null) - { - Match match = Regex.Match(line, s_FirstLinePattern); - if (match.Success) - { - // get the next line immediately and check it - if ((line = file.ReadLine()) != null) - { - Match secondMatch = Regex.Match(line, s_SecondLinePattern); - if (secondMatch.Success) - { - profile.UUID = secondMatch.Groups[1].Value; - break; - } - } - } - if (!string.IsNullOrEmpty(profile.UUID)) - { - break; - } - } - file.Close(); - } - } -} diff --git a/Editor/Mono/ProvisioningProfileGUI.cs b/Editor/Mono/ProvisioningProfileGUI.cs deleted file mode 100644 index 2376fdb6d2..0000000000 --- a/Editor/Mono/ProvisioningProfileGUI.cs +++ /dev/null @@ -1,194 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using UnityEditor.Modules; -using UnityEditorInternal; - -namespace UnityEditorInternal -{ - internal class ProvisioningProfileGUI - { - internal delegate void ProvisioningProfileChangedDelegate(ProvisioningProfile profile); - - internal static void ShowProvisioningProfileUIWithProperty(GUIContent titleWithToolTip, ProvisioningProfile profile, SerializedProperty prop) - { - GUILayout.BeginHorizontal(); - GUILayout.Label(titleWithToolTip, EditorStyles.label); - - Rect controlRect = EditorGUILayout.GetControlRect(false, 0); - GUIContent label = EditorGUIUtility.TrTextContent("Profile ID:"); - EditorGUI.BeginProperty(controlRect, label, prop); - - if (GUILayout.Button("Browse", EditorStyles.miniButton)) - { - ProvisioningProfile provisioningProfile = Browse(""); - if (provisioningProfile != null && !string.IsNullOrEmpty(provisioningProfile.UUID)) - { - profile = provisioningProfile; - prop.stringValue = profile.UUID; - prop.serializedObject.ApplyModifiedProperties(); - GUI.FocusControl(""); - } - GUIUtility.ExitGUI(); - } - - EditorGUI.EndProperty(); - GUILayout.EndHorizontal(); - - EditorGUI.BeginChangeCheck(); - EditorGUI.indentLevel++; - - controlRect = EditorGUILayout.GetControlRect(true, 0); - label = EditorGUIUtility.TrTextContent("Profile ID:"); - - EditorGUI.BeginProperty(controlRect, label, prop); - profile.UUID = EditorGUILayout.TextField(label, profile.UUID); - - if (EditorGUI.EndChangeCheck()) - prop.stringValue = profile.UUID; - - EditorGUI.EndProperty(); - EditorGUI.indentLevel--; - } - - internal static void ShowProvisioningProfileUIWithCallback(GUIContent titleWithToolTip, ProvisioningProfile profile, ProvisioningProfileChangedDelegate callback) - { - GUILayout.BeginHorizontal(); - GUILayout.Label(titleWithToolTip, EditorStyles.label); - - if (GUILayout.Button("Browse", EditorStyles.miniButton)) - { - ProvisioningProfile provisioningProfile = Browse(""); - if (provisioningProfile != null && !string.IsNullOrEmpty(provisioningProfile.UUID)) - { - profile = provisioningProfile; - callback(profile); - - GUI.FocusControl(""); - } - GUIUtility.ExitGUI(); - } - - GUILayout.EndHorizontal(); - - EditorGUI.BeginChangeCheck(); - EditorGUI.indentLevel++; - - GUIContent label = EditorGUIUtility.TrTextContent("Profile ID:"); - profile.UUID = EditorGUILayout.TextField(label, profile.UUID); - EditorGUI.indentLevel--; - if (EditorGUI.EndChangeCheck()) - { - callback(profile); - } - } - - internal static ProvisioningProfile Browse(string path) - { - var msg = "Select the Provising Profile used for Manual Signing"; - - var defaultFolder = path; - - if (InternalEditorUtility.inBatchMode) - { - return null; - } - - ProvisioningProfile provisioningProfile = null; - do - { - path = EditorUtility.OpenFilePanel(msg, defaultFolder, "mobileprovision"); - - // user pressed cancel? - if (path.Length == 0) - return null; - } - while (!GetProvisioningProfileId(path, out provisioningProfile)); - - return provisioningProfile; - } - - internal static bool GetProvisioningProfileId(string filePath, out ProvisioningProfile provisioningProfile) - { - ProvisioningProfile profile = ProvisioningProfile.ParseProvisioningProfileAtPath(filePath); - provisioningProfile = profile; - return profile.UUID != null; - } - - internal static void ShowUIWithDefaults(string provisioningPrefKey, SerializedProperty enableAutomaticSigningProp, GUIContent automaticSigningGUI, SerializedProperty manualSigningIDProp, GUIContent manualSigningProfileGUI, SerializedProperty appleDevIDProp, GUIContent teamIDGUIContent) - { - string oldTeamID = GetDefaultStringValue(appleDevIDProp, iOSEditorPrefKeys.kDefaultiOSAutomaticSignTeamId); - string newTeamID = null; - Rect controlRect = EditorGUILayout.GetControlRect(true, 0); - EditorGUI.BeginProperty(controlRect, teamIDGUIContent, appleDevIDProp); - EditorGUI.BeginChangeCheck(); - newTeamID = EditorGUILayout.TextField(teamIDGUIContent, oldTeamID); - if (EditorGUI.EndChangeCheck()) - { - appleDevIDProp.stringValue = newTeamID; - } - EditorGUI.EndProperty(); - - int signingValue = GetDefaultAutomaticSigningValue(enableAutomaticSigningProp, iOSEditorPrefKeys.kDefaultiOSAutomaticallySignBuild); - bool oldValue = GetBoolForAutomaticSigningValue(signingValue); - Rect toggleRect = EditorGUILayout.GetControlRect(true, 0); - EditorGUI.BeginProperty(toggleRect, automaticSigningGUI, enableAutomaticSigningProp); - bool newValue = EditorGUILayout.Toggle(automaticSigningGUI, oldValue); - - if (newValue != oldValue) - { - enableAutomaticSigningProp.intValue = GetIntValueForAutomaticSigningBool(newValue); - } - EditorGUI.EndProperty(); - - if (!newValue) - { - ShowProvisioningProfileUIWithDefaults(provisioningPrefKey, manualSigningIDProp, manualSigningProfileGUI); - } - } - - private static void ShowProvisioningProfileUIWithDefaults(string defaultPreferenceKey, SerializedProperty uuidProp, GUIContent title) - { - string val = uuidProp.stringValue; - if (string.IsNullOrEmpty(val)) - { - val = EditorPrefs.GetString(defaultPreferenceKey); - } - ProvisioningProfileGUI.ShowProvisioningProfileUIWithProperty(title, new ProvisioningProfile(val), uuidProp); - } - - private static bool GetBoolForAutomaticSigningValue(int signingValue) - { - return signingValue == (int)iOSAutomaticallySignValue.AutomaticallySignValueTrue; - } - - private static int GetIntValueForAutomaticSigningBool(bool automaticallySign) - { - return (int)(automaticallySign ? iOSAutomaticallySignValue.AutomaticallySignValueTrue : iOSAutomaticallySignValue.AutomaticallySignValueFalse); - } - - private static int GetDefaultAutomaticSigningValue(SerializedProperty prop, string editorPropKey) - { - int val = prop.intValue; - if (val == (int)iOSAutomaticallySignValue.AutomaticallySignValueNotSet) - { - val = (int)(EditorPrefs.GetBool(editorPropKey, true) ? iOSAutomaticallySignValue.AutomaticallySignValueTrue : iOSAutomaticallySignValue.AutomaticallySignValueFalse); - } - return val; - } - - private static string GetDefaultStringValue(SerializedProperty prop, string editorPrefKey) - { - string val = prop.stringValue; - if (string.IsNullOrEmpty(val)) - { - val = EditorPrefs.GetString(editorPrefKey, ""); - } - return val; - } - } -} diff --git a/Editor/Mono/RagdollBuilder.cs b/Editor/Mono/RagdollBuilder.cs deleted file mode 100644 index 785a2c58b7..0000000000 --- a/Editor/Mono/RagdollBuilder.cs +++ /dev/null @@ -1,531 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System; - -#pragma warning disable 649 - -namespace UnityEditor -{ - class RagdollBuilder : ScriptableWizard - { - public Transform pelvis; - - public Transform leftHips = null; - public Transform leftKnee = null; - public Transform leftFoot = null; - - public Transform rightHips = null; - public Transform rightKnee = null; - public Transform rightFoot = null; - - public Transform leftArm = null; - public Transform leftElbow = null; - - public Transform rightArm = null; - public Transform rightElbow = null; - - public Transform middleSpine = null; - public Transform head = null; - - - public float totalMass = 20; - public float strength = 0.0F; - - Vector3 right = Vector3.right; - Vector3 up = Vector3.up; - Vector3 forward = Vector3.forward; - - Vector3 worldRight = Vector3.right; - Vector3 worldUp = Vector3.up; - Vector3 worldForward = Vector3.forward; - public bool flipForward = false; - - class BoneInfo - { - public string name; - - public Transform anchor; - public CharacterJoint joint; - public BoneInfo parent; - - public float minLimit; - public float maxLimit; - public float swingLimit; - - public Vector3 axis; - public Vector3 normalAxis; - - public float radiusScale; - public Type colliderType; - - public ArrayList children = new ArrayList(); - public float density; - public float summedMass;// The mass of this and all children bodies - } - - ArrayList bones; - BoneInfo rootBone; - - string CheckConsistency() - { - PrepareBones(); - Hashtable map = new Hashtable(); - foreach (BoneInfo bone in bones) - { - if (bone.anchor) - { - if (map[bone.anchor] != null) - { - BoneInfo oldBone = (BoneInfo)map[bone.anchor]; - return String.Format("{0} and {1} may not be assigned to the same bone.", bone.name, oldBone.name); - } - map[bone.anchor] = bone; - } - } - - foreach (BoneInfo bone in bones) - { - if (bone.anchor == null) - return String.Format("{0} has not been assigned yet.\n", bone.name); - } - - return ""; - } - - void OnDrawGizmos() - { - if (pelvis) - { - Gizmos.color = Color.red; Gizmos.DrawRay(pelvis.position, pelvis.TransformDirection(right)); - Gizmos.color = Color.green; Gizmos.DrawRay(pelvis.position, pelvis.TransformDirection(up)); - Gizmos.color = Color.blue; Gizmos.DrawRay(pelvis.position, pelvis.TransformDirection(forward)); - } - } - - [MenuItem("GameObject/3D Object/Ragdoll...", false, 2000)] - static void CreateWizard() - { - ScriptableWizard.DisplayWizard("Create Ragdoll"); - } - - void DecomposeVector(out Vector3 normalCompo, out Vector3 tangentCompo, Vector3 outwardDir, Vector3 outwardNormal) - { - outwardNormal = outwardNormal.normalized; - normalCompo = outwardNormal * Vector3.Dot(outwardDir, outwardNormal); - tangentCompo = outwardDir - normalCompo; - } - - void CalculateAxes() - { - if (head != null && pelvis != null) - up = CalculateDirectionAxis(pelvis.InverseTransformPoint(head.position)); - if (rightElbow != null && pelvis != null) - { - Vector3 removed, temp; - DecomposeVector(out temp, out removed, pelvis.InverseTransformPoint(rightElbow.position), up); - right = CalculateDirectionAxis(removed); - } - - forward = Vector3.Cross(right, up); - if (flipForward) - forward = -forward; - } - - void OnWizardUpdate() - { - errorString = CheckConsistency(); - CalculateAxes(); - - if (errorString.Length != 0) - { - helpString = "Drag all bones from the hierarchy into their slots.\nMake sure your character is in T-Stand.\n"; - } - else - { - helpString = "Make sure your character is in T-Stand.\nMake sure the blue axis faces in the same direction the chracter is looking.\nUse flipForward to flip the direction"; - } - - isValid = errorString.Length == 0; - } - - void PrepareBones() - { - if (pelvis) - { - worldRight = pelvis.TransformDirection(right); - worldUp = pelvis.TransformDirection(up); - worldForward = pelvis.TransformDirection(forward); - } - - bones = new ArrayList(); - - rootBone = new BoneInfo(); - rootBone.name = "Pelvis"; - rootBone.anchor = pelvis; - rootBone.parent = null; - rootBone.density = 2.5F; - bones.Add(rootBone); - - AddMirroredJoint("Hips", leftHips, rightHips, "Pelvis", worldRight, worldForward, -20, 70, 30, typeof(CapsuleCollider), 0.3F, 1.5F); - AddMirroredJoint("Knee", leftKnee, rightKnee, "Hips", worldRight, worldForward, -80, 0, 0, typeof(CapsuleCollider), 0.25F, 1.5F); - - AddJoint("Middle Spine", middleSpine, "Pelvis", worldRight, worldForward, -20, 20, 10, null, 1, 2.5F); - - AddMirroredJoint("Arm", leftArm, rightArm, "Middle Spine", worldUp, worldForward, -70, 10, 50, typeof(CapsuleCollider), 0.25F, 1.0F); - AddMirroredJoint("Elbow", leftElbow, rightElbow, "Arm", worldForward, worldUp, -90, 0, 0, typeof(CapsuleCollider), 0.20F, 1.0F); - - AddJoint("Head", head, "Middle Spine", worldRight, worldForward, -40, 25, 25, null, 1, 1.0F); - } - - void OnWizardCreate() - { - Cleanup(); - BuildCapsules(); - AddBreastColliders(); - AddHeadCollider(); - - BuildBodies(); - BuildJoints(); - CalculateMass(); - } - - BoneInfo FindBone(string name) - { - foreach (BoneInfo bone in bones) - { - if (bone.name == name) - return bone; - } - return null; - } - - void AddMirroredJoint(string name, Transform leftAnchor, Transform rightAnchor, string parent, Vector3 worldTwistAxis, Vector3 worldSwingAxis, float minLimit, float maxLimit, float swingLimit, Type colliderType, float radiusScale, float density) - { - AddJoint("Left " + name, leftAnchor, parent, worldTwistAxis, worldSwingAxis, minLimit, maxLimit, swingLimit, colliderType, radiusScale, density); - AddJoint("Right " + name, rightAnchor, parent, worldTwistAxis, worldSwingAxis, minLimit, maxLimit, swingLimit, colliderType, radiusScale, density); - } - - void AddJoint(string name, Transform anchor, string parent, Vector3 worldTwistAxis, Vector3 worldSwingAxis, float minLimit, float maxLimit, float swingLimit, Type colliderType, float radiusScale, float density) - { - BoneInfo bone = new BoneInfo(); - bone.name = name; - bone.anchor = anchor; - bone.axis = worldTwistAxis; - bone.normalAxis = worldSwingAxis; - bone.minLimit = minLimit; - bone.maxLimit = maxLimit; - bone.swingLimit = swingLimit; - bone.density = density; - bone.colliderType = colliderType; - bone.radiusScale = radiusScale; - - if (FindBone(parent) != null) - bone.parent = FindBone(parent); - else if (name.StartsWith("Left")) - bone.parent = FindBone("Left " + parent); - else if (name.StartsWith("Right")) - bone.parent = FindBone("Right " + parent); - - - bone.parent.children.Add(bone); - bones.Add(bone); - } - - void BuildCapsules() - { - foreach (BoneInfo bone in bones) - { - if (bone.colliderType != typeof(CapsuleCollider)) - continue; - - int direction; - float distance; - if (bone.children.Count == 1) - { - BoneInfo childBone = (BoneInfo)bone.children[0]; - Vector3 endPoint = childBone.anchor.position; - CalculateDirection(bone.anchor.InverseTransformPoint(endPoint), out direction, out distance); - } - else - { - Vector3 endPoint = (bone.anchor.position - bone.parent.anchor.position) + bone.anchor.position; - CalculateDirection(bone.anchor.InverseTransformPoint(endPoint), out direction, out distance); - - if (bone.anchor.GetComponentsInChildren(typeof(Transform)).Length > 1) - { - Bounds bounds = new Bounds(); - foreach (Transform child in bone.anchor.GetComponentsInChildren(typeof(Transform))) - { - bounds.Encapsulate(bone.anchor.InverseTransformPoint(child.position)); - } - - if (distance > 0) - distance = bounds.max[direction]; - else - distance = bounds.min[direction]; - } - } - - CapsuleCollider collider = (CapsuleCollider)bone.anchor.gameObject.AddComponent(); - collider.direction = direction; - - Vector3 center = Vector3.zero; - center[direction] = distance * 0.5F; - collider.center = center; - collider.height = Mathf.Abs(distance); - collider.radius = Mathf.Abs(distance * bone.radiusScale); - } - } - - void Cleanup() - { - foreach (BoneInfo bone in bones) - { - if (!bone.anchor) - continue; - - Component[] joints = bone.anchor.GetComponentsInChildren(typeof(Joint)); - foreach (Joint joint in joints) - DestroyImmediate(joint); - - Component[] bodies = bone.anchor.GetComponentsInChildren(typeof(Rigidbody)); - foreach (Rigidbody body in bodies) - DestroyImmediate(body); - - Component[] colliders = bone.anchor.GetComponentsInChildren(typeof(Collider)); - foreach (Collider collider in colliders) - DestroyImmediate(collider); - } - } - - void BuildBodies() - { - foreach (BoneInfo bone in bones) - { - bone.anchor.gameObject.AddComponent(); - bone.anchor.GetComponent().mass = bone.density; - } - } - - void BuildJoints() - { - foreach (BoneInfo bone in bones) - { - if (bone.parent == null) - continue; - - CharacterJoint joint = bone.anchor.gameObject.AddComponent(); - bone.joint = joint; - - // Setup connection and axis - joint.axis = CalculateDirectionAxis(bone.anchor.InverseTransformDirection(bone.axis)); - joint.swingAxis = CalculateDirectionAxis(bone.anchor.InverseTransformDirection(bone.normalAxis)); - joint.anchor = Vector3.zero; - joint.connectedBody = bone.parent.anchor.GetComponent(); - joint.enablePreprocessing = false; // turn off to handle degenerated scenarios, like spawning inside geometry. - - // Setup limits - SoftJointLimit limit = new SoftJointLimit(); - limit.contactDistance = 0; // default to zero, which automatically sets contact distance. - - limit.limit = bone.minLimit; - joint.lowTwistLimit = limit; - - limit.limit = bone.maxLimit; - joint.highTwistLimit = limit; - - limit.limit = bone.swingLimit; - joint.swing1Limit = limit; - - limit.limit = 0; - joint.swing2Limit = limit; - } - } - - void CalculateMassRecurse(BoneInfo bone) - { - float mass = bone.anchor.GetComponent().mass; - foreach (BoneInfo child in bone.children) - { - CalculateMassRecurse(child); - mass += child.summedMass; - } - bone.summedMass = mass; - } - - void CalculateMass() - { - // Calculate allChildMass by summing all bodies - CalculateMassRecurse(rootBone); - - // Rescale the mass so that the whole character weights totalMass - float massScale = totalMass / rootBone.summedMass; - foreach (BoneInfo bone in bones) - bone.anchor.GetComponent().mass *= massScale; - - // Recalculate allChildMass by summing all bodies - CalculateMassRecurse(rootBone); - } - - static void CalculateDirection(Vector3 point, out int direction, out float distance) - { - // Calculate longest axis - direction = 0; - if (Mathf.Abs(point[1]) > Mathf.Abs(point[0])) - direction = 1; - if (Mathf.Abs(point[2]) > Mathf.Abs(point[direction])) - direction = 2; - - distance = point[direction]; - } - - static Vector3 CalculateDirectionAxis(Vector3 point) - { - int direction = 0; - float distance; - CalculateDirection(point, out direction, out distance); - Vector3 axis = Vector3.zero; - if (distance > 0) - axis[direction] = 1.0F; - else - axis[direction] = -1.0F; - return axis; - } - - static int SmallestComponent(Vector3 point) - { - int direction = 0; - if (Mathf.Abs(point[1]) < Mathf.Abs(point[0])) - direction = 1; - if (Mathf.Abs(point[2]) < Mathf.Abs(point[direction])) - direction = 2; - return direction; - } - - static int LargestComponent(Vector3 point) - { - int direction = 0; - if (Mathf.Abs(point[1]) > Mathf.Abs(point[0])) - direction = 1; - if (Mathf.Abs(point[2]) > Mathf.Abs(point[direction])) - direction = 2; - return direction; - } - - static int SecondLargestComponent(Vector3 point) - { - int smallest = SmallestComponent(point); - int largest = LargestComponent(point); - if (smallest < largest) - { - int temp = largest; - largest = smallest; - smallest = temp; - } - - if (smallest == 0 && largest == 1) - return 2; - else if (smallest == 0 && largest == 2) - return 1; - else - return 0; - } - - Bounds Clip(Bounds bounds, Transform relativeTo, Transform clipTransform, bool below) - { - int axis = LargestComponent(bounds.size); - - if (Vector3.Dot(worldUp, relativeTo.TransformPoint(bounds.max)) > Vector3.Dot(worldUp, relativeTo.TransformPoint(bounds.min)) == below) - { - Vector3 min = bounds.min; - min[axis] = relativeTo.InverseTransformPoint(clipTransform.position)[axis]; - bounds.min = min; - } - else - { - Vector3 max = bounds.max; - max[axis] = relativeTo.InverseTransformPoint(clipTransform.position)[axis]; - bounds.max = max; - } - return bounds; - } - - Bounds GetBreastBounds(Transform relativeTo) - { - // Pelvis bounds - Bounds bounds = new Bounds(); - bounds.Encapsulate(relativeTo.InverseTransformPoint(leftHips.position)); - bounds.Encapsulate(relativeTo.InverseTransformPoint(rightHips.position)); - bounds.Encapsulate(relativeTo.InverseTransformPoint(leftArm.position)); - bounds.Encapsulate(relativeTo.InverseTransformPoint(rightArm.position)); - Vector3 size = bounds.size; - size[SmallestComponent(bounds.size)] = size[LargestComponent(bounds.size)] / 2.0F; - bounds.size = size; - return bounds; - } - - void AddBreastColliders() - { - // Middle spine and pelvis - if (middleSpine != null && pelvis != null) - { - Bounds bounds; - BoxCollider box; - - // Middle spine bounds - bounds = Clip(GetBreastBounds(pelvis), pelvis, middleSpine, false); - box = (BoxCollider)pelvis.gameObject.AddComponent(); - box.center = bounds.center; - box.size = bounds.size; - - bounds = Clip(GetBreastBounds(middleSpine), middleSpine, middleSpine, true); - box = (BoxCollider)middleSpine.gameObject.AddComponent(); - box.center = bounds.center; - box.size = bounds.size; - } - // Only pelvis - else - { - Bounds bounds = new Bounds(); - bounds.Encapsulate(pelvis.InverseTransformPoint(leftHips.position)); - bounds.Encapsulate(pelvis.InverseTransformPoint(rightHips.position)); - bounds.Encapsulate(pelvis.InverseTransformPoint(leftArm.position)); - bounds.Encapsulate(pelvis.InverseTransformPoint(rightArm.position)); - - Vector3 size = bounds.size; - size[SmallestComponent(bounds.size)] = size[LargestComponent(bounds.size)] / 2.0F; - - BoxCollider box = pelvis.gameObject.AddComponent(); - box.center = bounds.center; - box.size = size; - } - } - - void AddHeadCollider() - { - if (head.GetComponent()) - Destroy(head.GetComponent()); - - float radius = Vector3.Distance(leftArm.transform.position, rightArm.transform.position); - radius /= 4; - - SphereCollider sphere = head.gameObject.AddComponent(); - sphere.radius = radius; - Vector3 center = Vector3.zero; - - int direction; - float distance; - CalculateDirection(head.InverseTransformPoint(pelvis.position), out direction, out distance); - if (distance > 0) - center[direction] = -radius; - else - center[direction] = radius; - sphere.center = center; - } - } -} diff --git a/Editor/Mono/RetainedMode.cs b/Editor/Mono/RetainedMode.cs deleted file mode 100644 index d9f33038b9..0000000000 --- a/Editor/Mono/RetainedMode.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.Experimental.UIElements; -using UnityEngine; -using Object = UnityEngine.Object; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleSheets; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - class RetainedMode : AssetPostprocessor - { - private const string k_UielementsUxmllivereloadPrefsKey = "UIElements_UXMLLiveReload"; - - internal static bool UxmlLiveReloadIsEnabled - { - get { return EditorPrefs.GetBool(k_UielementsUxmllivereloadPrefsKey, false); } - set { EditorPrefs.SetBool(k_UielementsUxmllivereloadPrefsKey, value); } - } - - static HashSet s_TmpDirtySet = new HashSet(); - static bool s_FontInitialized = false; - static RetainedMode() - { - UIElementsUtility.s_BeginContainerCallback = OnBeginContainer; - UIElementsUtility.s_EndContainerCallback = OnEndContainer; - } - - static void OnBeginContainer(IMGUIContainer c) - { - if (!s_FontInitialized) - { - s_FontInitialized = true; - LocalizedEditorFontManager.LocalizeEditorFonts(); - } - HandleUtility.BeginHandles(); - } - - static void OnEndContainer(IMGUIContainer c) - { - HandleUtility.EndHandles(); - } - - [RequiredByNativeCode] - static void UpdateSchedulers() - { - Debug.Assert(s_TmpDirtySet.Count == 0); - try - { - UpdateSchedulersInternal(s_TmpDirtySet); - } - finally - { - s_TmpDirtySet.Clear(); - } - } - - static void UpdateSchedulersInternal(HashSet tmpDirtySet) - { - DataWatchService.sharedInstance.PollNativeData(); - - var iterator = UIElementsUtility.GetPanelsIterator(); - while (iterator.MoveNext()) - { - var panel = iterator.Current.Value; - - // Game panels' scheduler are ticked by the engine - if (panel.contextType != ContextType.Editor) - continue; - - var timerEventScheduler = panel.scheduler; - - // Dispatch all timer update messages to each scheduled item - panel.timerEventScheduler.UpdateScheduledEvents(); - - // Dispatch might have triggered a repaint request. - if (panel.visualTree.IsDirty(ChangeType.Repaint)) - { - var guiView = panel.ownerObject as GUIView; - if (guiView != null) - guiView.Repaint(); - } - } - } - - static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) - { - bool anyUxmlImported = false; - bool anyUssImported = false; - foreach (string assetPath in importedAssets) - { - if (assetPath.EndsWith("uss")) - { - if (!anyUssImported) - { - anyUssImported = true; - FlagStyleSheetChange(); - } - } - else if (assetPath.EndsWith("uxml")) - { - if (!anyUxmlImported) - { - anyUxmlImported = true; - UIElementsViewImporter.logger.FinishImport(); - - // the inline stylesheet cache might get out of date. - // Usually called by the USS importer, which might not get called here - StyleSheetCache.ClearCaches(); - - if (UxmlLiveReloadIsEnabled && Unsupported.IsDeveloperMode()) - { - // Delay the view reloading so we do not try to reload the view that - // is currently active in the current callstack (i.e. ProjectView). - EditorApplication.update += OneShotUxmlLiveReload; - } - } - } - - // no need to continue, as we found both extensions we were looking for - if (anyUxmlImported && anyUssImported) - break; - } - } - - private static void OneShotUxmlLiveReload() - { - try - { - var it = UIElementsUtility.GetPanelsIterator(); - while (it.MoveNext()) - { - var view = it.Current.Value.ownerObject as HostView; - if (view != null && view.actualView != null) - { - view.Reload(view.actualView); - } - } - } - catch (Exception e) - { - Debug.LogException(e); - } - - // Make sure to unregister ourself to prevent any infinit updates. - EditorApplication.update -= OneShotUxmlLiveReload; - } - - public static void FlagStyleSheetChange() - { - // clear caches that depend on loaded style sheets - StyleSheetCache.ClearCaches(); - - // for now we don't bother tracking which panel depends on which style sheet - var iterator = UIElementsUtility.GetPanelsIterator(); - while (iterator.MoveNext()) - { - var panel = iterator.Current.Value; - - // In-game doesn't support styling - if (panel.contextType != ContextType.Editor) - continue; - - panel.styleContext.DirtyStyleSheets(); - panel.visualTree.Dirty(ChangeType.Styles); // dirty all styles - - var guiView = panel.ownerObject as GUIView; - if (guiView != null) - guiView.Repaint(); - } - } - } -} diff --git a/Editor/Mono/RuntimeInitializeOnLoadManager.bindings.cs b/Editor/Mono/RuntimeInitializeOnLoadManager.bindings.cs deleted file mode 100644 index 47cb74b788..0000000000 --- a/Editor/Mono/RuntimeInitializeOnLoadManager.bindings.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Runtime.InteropServices; -using UnityEngine.Bindings; - -namespace UnityEngine -{ - [StructLayout(LayoutKind.Sequential)] - internal sealed partial class RuntimeInitializeMethodInfo - { - string m_FullClassName; - string m_MethodName; - int m_OrderNumber = 0; - bool m_IsUnityClass = false; - - internal string fullClassName { get { return m_FullClassName; } set { m_FullClassName = value; } } - internal string methodName { get { return m_MethodName; } set { m_MethodName = value; } } - internal int orderNumber { get { return m_OrderNumber; } set { m_OrderNumber = value; } } - internal bool isUnityClass { get { return m_IsUnityClass; } set { m_IsUnityClass = value; } } - } - - [StructLayout(LayoutKind.Sequential)] - internal sealed partial class RuntimeInitializeClassInfo - { - string m_AssemblyName; - string m_ClassName; - string[] m_MethodNames; - RuntimeInitializeLoadType[] m_LoadTypes; - - internal string assemblyName { get { return m_AssemblyName; } set { m_AssemblyName = value; } } - internal string className { get { return m_ClassName; } set { m_ClassName = value; } } - internal string[] methodNames { get { return m_MethodNames; } set { m_MethodNames = value; } } - internal RuntimeInitializeLoadType[] loadTypes { get { return m_LoadTypes; } set { m_LoadTypes = value; } } - } - - [NativeHeader("Runtime/Misc/RuntimeInitializeOnLoadManager.h")] - [StaticAccessorAttribute("GetRuntimeInitializeOnLoadManager()")] - internal sealed partial class RuntimeInitializeOnLoadManager - { - extern internal static string[] dontStripClassNames { get; } - - [NativeProperty("RuntimeInitializeClassMethodInfos")] - extern internal static RuntimeInitializeMethodInfo[] methodInfos { get; } - - [NativeMethod("UpdateExecutionOrderNumber")] - extern internal static void UpdateMethodExecutionOrders(int[] changedIndices, int[] changedOrder); - } -} diff --git a/Editor/Mono/SceneHierarchySortingWindow.cs b/Editor/Mono/SceneHierarchySortingWindow.cs deleted file mode 100644 index 9a6f30a01a..0000000000 --- a/Editor/Mono/SceneHierarchySortingWindow.cs +++ /dev/null @@ -1,150 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - internal class SceneHierarchySortingWindow : EditorWindow - { - public delegate void OnSelectCallback(InputData element); - - private class Styles - { - public GUIStyle background = "grey_border"; - public GUIStyle menuItem = "MenuItem"; - } - - public class InputData - { - public string m_TypeName; - public string m_Name; - public bool m_Selected; - } - - private static SceneHierarchySortingWindow s_SceneHierarchySortingWindow; - private static long s_LastClosedTime; - private static Styles s_Styles; - - private List m_Data; - private OnSelectCallback m_Callback; - - const float kFrameWidth = 1f; - - private float GetHeight() - { - return EditorGUI.kSingleLineHeight * m_Data.Count; - } - - private float GetWidth() - { - float width = 0f; - - foreach (InputData item in m_Data) - { - float itemWidth = 0; - itemWidth = s_Styles.menuItem.CalcSize(GUIContent.Temp(item.m_Name)).x; - - if (itemWidth > width) - width = itemWidth; - } - return width; - } - - private void OnEnable() - { - AssemblyReloadEvents.beforeAssemblyReload += Close; - hideFlags = HideFlags.DontSave; - wantsMouseMove = true; - } - - private void OnDisable() - { - AssemblyReloadEvents.beforeAssemblyReload -= Close; - s_LastClosedTime = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - } - - internal static bool ShowAtPosition(Vector2 pos, List data, OnSelectCallback callback) - { - // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time. - long nowMilliSeconds = System.DateTime.Now.Ticks / System.TimeSpan.TicksPerMillisecond; - bool justClosed = nowMilliSeconds < s_LastClosedTime + 50; - if (!justClosed) - { - Event.current.Use(); - if (s_SceneHierarchySortingWindow == null) - s_SceneHierarchySortingWindow = CreateInstance(); - s_SceneHierarchySortingWindow.Init(pos, data, callback); - return true; - } - return false; - } - - private void Init(Vector2 pos, List data, OnSelectCallback callback) - { - // Has to be done before calling Show / ShowWithMode - //pos = GUIUtility.GUIToScreenPoint(pos); - - - 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 - buttonRect = GUIUtility.GUIToScreenRect(buttonRect); - data.Sort( - delegate(InputData lhs, InputData rhs) - { - return lhs.m_Name.CompareTo(rhs.m_Name); - }); - m_Data = data; - m_Callback = callback; - - if (s_Styles == null) - s_Styles = new Styles(); - - var windowHeight = 2f * kFrameWidth + GetHeight(); - var windowWidth = 2f * kFrameWidth + GetWidth(); - var windowSize = new Vector2(windowWidth, windowHeight); - - ShowAsDropDown(buttonRect, windowSize); - } - - internal void OnGUI() - { - // We do not use the layout event - if (Event.current.type == EventType.Layout) - return; - - if (Event.current.type == EventType.MouseMove) - Event.current.Use(); - - // Content - Draw(); - - // Background with 1 pixel border - GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, s_Styles.background); - } - - private void Draw() - { - var drawPos = new Rect(kFrameWidth, kFrameWidth, position.width - 2 * kFrameWidth, EditorGUI.kSingleLineHeight); - - foreach (InputData data in m_Data) - { - DrawListElement(drawPos, data); - drawPos.y += EditorGUI.kSingleLineHeight; - } - } - - void DrawListElement(Rect rect, InputData data) - { - EditorGUI.BeginChangeCheck(); - GUI.Toggle(rect, data.m_Selected, EditorGUIUtility.TempContent(data.m_Name), s_Styles.menuItem); - if (EditorGUI.EndChangeCheck()) - { - m_Callback(data); - Close(); - } - } - } -} diff --git a/Editor/Mono/SceneHierarchyWindow.cs b/Editor/Mono/SceneHierarchyWindow.cs deleted file mode 100644 index 5ef4551b83..0000000000 --- a/Editor/Mono/SceneHierarchyWindow.cs +++ /dev/null @@ -1,1359 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEditor.SceneManagement; -using System.Collections.Generic; -using System.Linq; -using System; -using UnityEditor.IMGUI.Controls; -using UnityEditorInternal; - - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Hierarchy", useTypeNameAsIconName = true)] - class SceneHierarchyWindow : SearchableEditorWindow, IHasCustomMenu - { - static SceneHierarchyWindow s_LastInteractedHierarchy; - public static SceneHierarchyWindow lastInteractedHierarchyWindow { get { return s_LastInteractedHierarchy; } } - - class Styles - { - const string kCustomSorting = "CustomSorting"; - const string kWarningSymbol = "console.warnicon.sml"; - const string kWarningMessage = "The current sorting method is taking a lot of time. Consider using 'Transform Sort' in playmode for better performance."; - - public GUIContent defaultSortingContent = new GUIContent(EditorGUIUtility.FindTexture(kCustomSorting)); - public GUIContent createContent = EditorGUIUtility.TrTextContent("Create"); - public GUIContent fetchWarning = new GUIContent("", EditorGUIUtility.FindTexture(kWarningSymbol), kWarningMessage); - - public GUIStyle MiniButton; - public GUIStyle lockButton = "IN LockButton"; - - public Styles() - { - MiniButton = "ToolbarButton"; - } - } - static Styles s_Styles; - - private static List s_SceneHierarchyWindow = new List(); - public static List GetAllSceneHierarchyWindows() - { - return s_SceneHierarchyWindow; - } - - const int kInvalidSceneHandle = 0; - TreeViewController m_TreeView; - [SerializeField] - TreeViewState m_TreeViewState; - [SerializeField] - List m_ExpandedScenes = new List(); // saved in layout so we can expand on next Unity session (expanded state is saved per window) - int m_TreeViewKeyboardControlID; - - [SerializeField] - private int m_CurrenRootInstanceID = 0; - [SerializeField] - EditorGUIUtility.EditorLockTracker m_LockTracker = new EditorGUIUtility.EditorLockTracker(); - - internal bool isLocked - { - get { return m_LockTracker.isLocked; } - set { m_LockTracker.isLocked = value; } - } - - [SerializeField] - string m_CurrentSortingName = ""; // serialize as string - [NonSerialized] - private int m_LastFramedID = -1; - [NonSerialized] - bool m_TreeViewReloadNeeded; - [NonSerialized] - bool m_SelectionSyncNeeded; - [NonSerialized] - bool m_FrameOnSelectionSync; - [NonSerialized] - bool m_DidSelectSearchResult; - Dictionary m_SortingObjects = null; - bool m_AllowAlphaNumericalSort; - [NonSerialized] - double m_LastUserInteractionTime; - - bool m_Debug; - - internal static bool debug - { - get { return lastInteractedHierarchyWindow.m_Debug; } - set { lastInteractedHierarchyWindow.m_Debug = value; } - } - - public static bool s_Debug - { - get { return SessionState.GetBool("HierarchyWindowDebug", false); } - set { SessionState.SetBool("HierarchyWindowDebug", value); } - } - - bool treeViewReloadNeeded - { - get { return m_TreeViewReloadNeeded; } - set - { - m_TreeViewReloadNeeded = value; - if (value) - { - Repaint(); - if (s_Debug) - Debug.Log("Reload treeview on next event"); - } - } - } - - bool selectionSyncNeeded - { - get { return m_SelectionSyncNeeded; } - set - { - m_SelectionSyncNeeded = value; - if (value) - { - Repaint(); - if (s_Debug) - Debug.Log("Selection sync and frameing on next event"); - } - } - } - - string currentSortingName - { - get { return m_CurrentSortingName; } - set - { - m_CurrentSortingName = value; - - // Ensure backwards compability (if current sort is not found, default to transform sort) - if (!m_SortingObjects.ContainsKey(m_CurrentSortingName)) - { - m_CurrentSortingName = GetNameForType(typeof(TransformSorting)); - } - - // Sync treeview with new sort state - var dataSource = (GameObjectTreeViewDataSource)treeView.data; - dataSource.sortingState = m_SortingObjects[m_CurrentSortingName]; - } - } - - bool hasSortMethods { get { return m_SortingObjects.Count > 1; } } - - Rect treeViewRect - { - get { return new Rect(0, EditorGUI.kWindowToolbarHeight, position.width, position.height - EditorGUI.kWindowToolbarHeight); } - } - - private TreeViewController treeView - { - get - { - if (m_TreeView == null) - Init(); - return m_TreeView; - } - } - - void Init() - { - if (m_TreeViewState == null) - m_TreeViewState = new TreeViewState(); - - m_TreeView = new TreeViewController(this, m_TreeViewState); - m_TreeView.itemDoubleClickedCallback += TreeViewItemDoubleClicked; - m_TreeView.selectionChangedCallback += TreeViewSelectionChanged; - m_TreeView.onGUIRowCallback += OnGUIAssetCallback; - m_TreeView.dragEndedCallback += OnDragEndedCallback; - m_TreeView.contextClickItemCallback += ItemContextClick; - m_TreeView.contextClickOutsideItemsCallback += ContextClickOutsideItems; - m_TreeView.deselectOnUnhandledMouseDown = true; - - // Both when showing all gos and a sub tree we hide the root - bool showRootItem = false; - bool rootItemIsCollapsable = false; - - var dataSource = new GameObjectTreeViewDataSource(m_TreeView, m_CurrenRootInstanceID, showRootItem, rootItemIsCollapsable); - var dragging = new GameObjectsTreeViewDragging(m_TreeView); - var gui = new GameObjectTreeViewGUI(m_TreeView, false); - m_TreeView.Init(treeViewRect, dataSource, gui, dragging); - - dataSource.searchMode = (int)searchMode; - dataSource.searchString = m_SearchFilter; - - m_AllowAlphaNumericalSort = EditorPrefs.GetBool("AllowAlphaNumericHierarchy", false) || !InternalEditorUtility.isHumanControllingUs; // Always allow alphasorting when running automated tests so we can test alpha sorting - - SetUpSortMethodLists(); - - m_TreeView.ReloadData(); - } - - internal void SetupForTesting() - { - m_AllowAlphaNumericalSort = true; - SetUpSortMethodLists(); - } - - public void SetCurrentRootInstanceID(int instanceID) - { - m_CurrenRootInstanceID = instanceID; - Init(); - EditorGUIUtility.ExitGUI(); // exit gui since this can be called while iterating items - } - - // This method is being used by the EditorTests/Searching tests - public string[] GetCurrentVisibleObjects() - { - var rows = m_TreeView.data.GetRows(); - var result = new string[rows.Count]; - - for (int i = 0; i < rows.Count; ++i) - result[i] = rows[i].displayName; - return result; - } - - internal void SelectPrevious() - { - m_TreeView.OffsetSelection(-1); - } - - internal void SelectNext() - { - m_TreeView.OffsetSelection(1); - } - - void OnProjectWasLoaded() - { - // Game objects will have new instanceIDs in a new Unity session, so clear - // the expanded state on project start up. - m_TreeViewState.expandedIDs.Clear(); - - // If only one scene ensure it is expanded (new project) - if (SceneManager.sceneCount == 1) - { - treeView.data.SetExpanded(SceneManager.GetSceneAt(0).handle, true); - } - - // Ensure scenes are expanded from last session - SetScenesExpanded(m_ExpandedScenes); - } - - IEnumerable GetExpandedSceneNames() - { - List expandedScenes = new List(); - for (int i = 0; i < SceneManager.sceneCount; ++i) - { - Scene scene = SceneManager.GetSceneAt(i); - if (treeView.data.IsExpanded(scene.handle)) - { - expandedScenes.Add(scene.name); - } - } - return expandedScenes; - } - - void SetScenesExpanded(List sceneNames) - { - List sceneHandles = new List(); - foreach (string sceneName in sceneNames) - { - Scene scene = SceneManager.GetSceneByName(sceneName); - if (scene.IsValid()) - { - sceneHandles.Add(scene.handle); - } - } - if (sceneHandles.Count > 0) - treeView.data.SetExpandedIDs(sceneHandles.ToArray()); - } - - void OnSceneCreated(Scene scene, NewSceneSetup setup, NewSceneMode mode) - { - ExpandTreeViewItem(scene.handle, true); - } - - void OnSceneOpened(Scene scene, OpenSceneMode mode) - { - ExpandTreeViewItem(scene.handle, true); - } - - void ExpandTreeViewItem(int id, bool expand) - { - var dataSource = treeView.data as TreeViewDataSource; - if (dataSource != null) - dataSource.SetExpanded(id, expand); - } - - void Awake() - { - m_HierarchyType = HierarchyType.GameObjects; - if (m_TreeViewState != null) - { - // Clear states that should not survive between restarts of Unity - m_TreeViewState.OnAwake(); - } - } - - private void OnBecameVisible() - { - // We need to ensure Hierarchy window is reloaded when becoming visible because - // while it is hidden it does not receive OnHierarchyChanged callbacks (case 611409) - // During assembly reload editor windows are recreated, at that point scene count is 0 so ignore that event - if (SceneManager.sceneCount > 0) - treeViewReloadNeeded = true; - } - - public override void OnEnable() - { - base.OnEnable(); - titleContent = GetLocalizedTitleContent(); - s_SceneHierarchyWindow.Add(this); - EditorApplication.projectChanged += ReloadData; // Required to know if a prefab gets deleted. Better way of doing this? - EditorApplication.editorApplicationQuit += OnQuit; - EditorApplication.searchChanged += SearchChanged; - EditorApplication.projectWasLoaded += OnProjectWasLoaded; - EditorSceneManager.newSceneCreated += OnSceneCreated; - EditorSceneManager.sceneOpened += OnSceneOpened; - s_LastInteractedHierarchy = this; - } - - public override void OnDisable() - { - EditorApplication.projectChanged -= ReloadData; - EditorApplication.editorApplicationQuit -= OnQuit; - EditorApplication.searchChanged -= SearchChanged; - EditorApplication.projectWasLoaded -= OnProjectWasLoaded; - EditorSceneManager.newSceneCreated -= OnSceneCreated; - EditorSceneManager.sceneOpened -= OnSceneOpened; - s_SceneHierarchyWindow.Remove(this); - } - - void OnQuit() - { - m_ExpandedScenes = GetExpandedSceneNames().ToList(); - } - - public void OnDestroy() - { - if (s_LastInteractedHierarchy == this) - { - s_LastInteractedHierarchy = null; - - // Set another existing hierarchy as last interacted if available - foreach (var hierarchy in s_SceneHierarchyWindow) - if (hierarchy != this) - s_LastInteractedHierarchy = hierarchy; - } - } - - void SetAsLastInteractedHierarchy() - { - s_LastInteractedHierarchy = this; - } - - void SyncIfNeeded() - { - if (treeViewReloadNeeded) - { - treeViewReloadNeeded = false; - ReloadData(); - } - - if (selectionSyncNeeded) - { - selectionSyncNeeded = false; - - bool userJustInteracted = (EditorApplication.timeSinceStartup - m_LastUserInteractionTime) < 0.2; - bool frame = !m_LockTracker.isLocked || m_FrameOnSelectionSync || userJustInteracted; - bool animatedFraming = userJustInteracted && frame; - m_FrameOnSelectionSync = false; - - treeView.SetSelection(Selection.instanceIDs, frame, animatedFraming); - } - } - - void DetectUserInteraction() - { - Event evt = Event.current; - if (evt.type != EventType.Layout && evt.type != EventType.Repaint) - { - m_LastUserInteractionTime = EditorApplication.timeSinceStartup; - } - } - - void OnGUI() - { - if (s_Styles == null) - s_Styles = new Styles(); - - DetectUserInteraction(); - SyncIfNeeded(); - - m_TreeViewKeyboardControlID = GUIUtility.GetControlID(FocusType.Keyboard); - - OnEvent(); - - Rect SceneHierarchyRect = new Rect(0, 0, position.width, position.height); - Event evt = Event.current; - if (evt.type == EventType.MouseDown && SceneHierarchyRect.Contains(evt.mousePosition)) - { - treeView.EndPing(); - SetAsLastInteractedHierarchy(); - } - - DoToolbar(); - float searchPathHeight = DoSearchResultPathGUI(); - DoTreeView(searchPathHeight); - ExecuteCommands(); - } - - void OnLostFocus() - { - // Added because this window uses RenameOverlay - treeView.EndNameEditing(true); - } - - public static bool IsSceneHeaderInHierarchyWindow(Scene scene) - { - return scene.IsValid(); - } - - void TreeViewItemDoubleClicked(int instanceID) - { - Scene scene = EditorSceneManager.GetSceneByHandle(instanceID); - - if (IsSceneHeaderInHierarchyWindow(scene)) - { - // scene header selected - if (scene.isLoaded) - EditorSceneManager.SetActiveScene(scene); - } - else - // GameObject selected - SceneView.FrameLastActiveSceneView(); - } - - public void SetExpandedRecursive(int id, bool expand) - { - TreeViewItem item = treeView.data.FindItem(id); - - // If the item is null reload the data as the scene might have changed. - if (item == null) - { - ReloadData(); - item = treeView.data.FindItem(id); - } - - if (item != null) - treeView.data.SetExpandedWithChildren(item, expand); - } - - void OnGUIAssetCallback(int instanceID, Rect rect) - { - // User hook for rendering stuff on top of assets - if (EditorApplication.hierarchyWindowItemOnGUI != null) - { - EditorApplication.hierarchyWindowItemOnGUI(instanceID, rect); - } - } - - void OnDragEndedCallback(int[] draggedInstanceIds, bool draggedItemsFromOwnTreeView) - { - // We only change selection if 'draggedItemsFromOwnTreeView' == true. - // This ensures that we do not override the selection that might have been set before - // calling this callback when dragging e.g a prefab to the hierarchy (case 628939) - if (draggedInstanceIds != null && draggedItemsFromOwnTreeView) - { - ReloadData(); - treeView.SetSelection(draggedInstanceIds, true); - treeView.NotifyListenersThatSelectionChanged(); // behave as if selection was performed in treeview - Repaint(); - GUIUtility.ExitGUI(); - } - } - - public void ReloadData() - { - if (m_TreeView == null) - Init(); - else - m_TreeView.ReloadData(); - } - - public void SearchChanged() - { - var data = (GameObjectTreeViewDataSource)treeView.data; - - // Search didnt change do nothing. - if (data.searchMode == (int)searchMode && data.searchString == m_SearchFilter) - return; - - data.searchMode = (int)searchMode; - data.searchString = m_SearchFilter; - - if (m_SearchFilter == "") - { - treeView.Frame(Selection.activeInstanceID, true, false); - } - - ReloadData(); - } - - void TreeViewSelectionChanged(int[] ids) - { - Selection.instanceIDs = ids; - - m_DidSelectSearchResult = !string.IsNullOrEmpty(m_SearchFilter); - } - - bool IsTreeViewSelectionInSyncWithBackend() - { - if (m_TreeView != null) - return m_TreeView.state.selectedIDs.SequenceEqual(Selection.instanceIDs); - return false; - } - - void OnSelectionChange() - { - if (!IsTreeViewSelectionInSyncWithBackend()) - { - selectionSyncNeeded = true; - } - else - { - if (s_Debug) - Debug.Log("OnSelectionChange: Selection is already in sync so no framing will happen"); - } - } - - void OnHierarchyChange() - { - if (m_TreeView != null) - m_TreeView.EndNameEditing(false); - treeViewReloadNeeded = true; - } - - float DoSearchResultPathGUI() - { - if (!hasSearchFilter) - return 0; - - GUILayout.FlexibleSpace(); - Rect verticalRect = EditorGUILayout.BeginVertical(EditorStyles.inspectorBig); - GUILayout.Label("Path:"); - - if (m_TreeView.HasSelection()) - { - int selectedID = m_TreeView.GetSelection()[0]; - - IHierarchyProperty activeSelectedInHierachy = new HierarchyProperty(HierarchyType.GameObjects); - activeSelectedInHierachy.Find(selectedID, null); - if (activeSelectedInHierachy.isValid) - { - // We have a valid game object: now show its path - do - { - EditorGUILayout.BeginHorizontal(); - GUILayout.Label(activeSelectedInHierachy.icon); - GUILayout.Label(activeSelectedInHierachy.name); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - } - while (activeSelectedInHierachy.Parent()); - } - } - EditorGUILayout.EndVertical(); - GUILayout.Space(0); - return verticalRect.height; - } - - void OnEvent() - { - treeView.OnEvent(); - } - - void DoTreeView(float searchPathHeight) - { - // subtract the search path height from the available height. - Rect rect = treeViewRect; - rect.height -= searchPathHeight; - treeView.OnGUI(rect, m_TreeViewKeyboardControlID); - } - - void DoToolbar() - { - // Gameobject popup dropdown - GUILayout.BeginHorizontal(EditorStyles.toolbar); - CreateGameObjectPopup(); - - //Search field GUI - GUILayout.Space(6); - - if (s_Debug) - { - int firstRow, lastRow; - m_TreeView.gui.GetFirstAndLastRowVisible(out firstRow, out lastRow); - GUILayout.Label(string.Format("{0} ({1}, {2})", m_TreeView.data.rowCount, firstRow, lastRow), EditorStyles.miniLabel); - GUILayout.Space((6)); - } - - GUILayout.FlexibleSpace(); - Event evt = Event.current; - - // When searchfield has focus give keyboard focus to the tree view on Down/UpArrow - if (hasSearchFilterFocus && evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.DownArrow || evt.keyCode == KeyCode.UpArrow)) - { - GUIUtility.keyboardControl = m_TreeViewKeyboardControlID; - - // If nothing is selected ensure first item is selected, otherwise ensure current - // selection is visible (we just gave focus to the tree) - if (treeView.IsLastClickedPartOfRows()) - { - treeView.Frame(treeView.state.lastClickedID, true, false); - m_DidSelectSearchResult = !string.IsNullOrEmpty(m_SearchFilter); - } - else - treeView.OffsetSelection(1); // Selects first item - - evt.Use(); - } - - SearchFieldGUI(); - - // Sortmethod GUI - GUILayout.Space(6); - - if (hasSortMethods) - { - if (Application.isPlaying && ((GameObjectTreeViewDataSource)treeView.data).isFetchAIssue) - { - GUILayout.Toggle(false, s_Styles.fetchWarning, s_Styles.MiniButton); - } - - SortMethodsDropDown(); - } - - - GUILayout.EndHorizontal(); - } - - internal override void SetSearchFilter(string searchFilter, SearchableEditorWindow.SearchMode searchMode, bool setAll) - { - base.SetSearchFilter(searchFilter, searchMode, setAll); - - // If the user clears the search we frame the last selection he made during the search - if (m_DidSelectSearchResult && string.IsNullOrEmpty(searchFilter)) - { - m_DidSelectSearchResult = false; - FrameObjectPrivate(Selection.activeInstanceID, true, false, false); - - // Ensure item has focus for visual feedback and instant key navigation - if (GUIUtility.keyboardControl == 0) - GUIUtility.keyboardControl = m_TreeViewKeyboardControlID; - } - } - - /* - * NOTE: AddCreateGameObjectItemsToMenu() cooks existing menu, so that make sure menu entries are added to - * localization entry. - * @Localization("Create Empty", "MenuItem") - * @Localization("Create Empty Child", "MenuItem") - */ - void AddCreateGameObjectItemsToMenu(GenericMenu menu, UnityEngine.Object[] context, bool includeCreateEmptyChild, bool includeGameObjectInPath, int targetSceneHandle) - { - string[] menus = Unsupported.GetSubmenus("GameObject"); - foreach (string path in menus) - { - UnityEngine.Object[] tempContext = context; - if (!includeCreateEmptyChild && path.ToLower() == "GameObject/Create Empty Child".ToLower()) - continue; - // Don't include context for Wizards (item ends with ...), since reparenting doesn't work here anyway, but a multiselection - // would cause multiple wizards to be opened simultaneously - if (path.EndsWith("...")) - tempContext = null; - // The first item after the GameObject creation menu items - if (path.ToLower() == "GameObject/Center On Children".ToLower()) - return; - - string menupath = path; - if (!includeGameObjectInPath) - menupath = path.Substring(11); // cut away "GameObject/" - MenuUtils.ExtractMenuItemWithPath(path, menu, menupath, tempContext, targetSceneHandle, BeforeCreateGameObjectMenuItemWasExecuted, AfterCreateGameObjectMenuItemWasExecuted); - } - } - - void BeforeCreateGameObjectMenuItemWasExecuted(string menuPath, UnityEngine.Object[] contextObjects, int userData) - { - int sceneHandle = userData; - EditorSceneManager.SetTargetSceneForNewGameObjects(sceneHandle); - } - - void AfterCreateGameObjectMenuItemWasExecuted(string menuPath, UnityEngine.Object[] contextObjects, int userData) - { - EditorSceneManager.SetTargetSceneForNewGameObjects(kInvalidSceneHandle); - - // Ensure framing when creating game objects even if we are locked - if (m_LockTracker.isLocked) - m_FrameOnSelectionSync = true; - } - - void CreateGameObjectPopup() - { - Rect rect = GUILayoutUtility.GetRect(s_Styles.createContent, EditorStyles.toolbarDropDown, null); - if (Event.current.type == EventType.Repaint) - EditorStyles.toolbarDropDown.Draw(rect, s_Styles.createContent, false, false, false, false); - - if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) - { - GUIUtility.hotControl = 0; - - GenericMenu menu = new GenericMenu(); - AddCreateGameObjectItemsToMenu(menu, null, true, false, kInvalidSceneHandle); - menu.DropDown(rect); - - Event.current.Use(); - } - } - - void SortMethodsDropDown() - { - if (hasSortMethods) - { - // Labels button - GUIContent content = m_SortingObjects[currentSortingName].content; - if (content == null) - { - content = s_Styles.defaultSortingContent; - content.tooltip = currentSortingName; - } - - Rect r = GUILayoutUtility.GetRect(content, EditorStyles.toolbarButton); - if (EditorGUI.DropdownButton(r, content, FocusType.Passive, EditorStyles.toolbarButton)) - { - // Build list items - var sortFunctionItems = new List(); - foreach (var entry in m_SortingObjects) - { - var data = new SceneHierarchySortingWindow.InputData(); - data.m_TypeName = entry.Key; - data.m_Name = ObjectNames.NicifyVariableName(entry.Key); //entry.Key == class name; - data.m_Selected = entry.Key == m_CurrentSortingName; - sortFunctionItems.Add(data); - } - - // Show popup - if (SceneHierarchySortingWindow.ShowAtPosition(new Vector2(r.x, r.y + r.height), sortFunctionItems, SortFunctionCallback)) - { - GUIUtility.ExitGUI(); - } - } - } - } - - void SetUpSortMethodLists() - { - m_SortingObjects = new Dictionary(); - - var transformSorting = new TransformSorting(); - m_SortingObjects.Add(GetNameForType(transformSorting.GetType()), transformSorting); - - // The user have to activate AlphabeticalSorting in the preferences (we ensure AlphabeticalSorting is added for integration tests) - if (m_AllowAlphaNumericalSort || !InternalEditorUtility.isHumanControllingUs) - { - var alphabeticalSorting = new AlphabeticalSorting(); - m_SortingObjects.Add(GetNameForType(alphabeticalSorting.GetType()), alphabeticalSorting); - } - - // Ensure to reconstruct state setup when setting sorting name - currentSortingName = m_CurrentSortingName; - } - - string GetNameForType(Type type) - { - return type.Name; - } - - void SortFunctionCallback(SceneHierarchySortingWindow.InputData data) - { - SetSortFunction(data.m_TypeName); - } - - public void SetSortFunction(Type sortType) - { - SetSortFunction(GetNameForType(sortType)); - } - - void SetSortFunction(string sortTypeName) - { - if (!m_SortingObjects.ContainsKey(sortTypeName)) - { - Debug.LogError("Invalid search type name: " + sortTypeName); - return; - } - - currentSortingName = sortTypeName; - if (treeView.GetSelection().Any()) - treeView.Frame(treeView.GetSelection().First(), true, false); - treeView.ReloadData(); - } - - public void DirtySortingMethods() - { - m_AllowAlphaNumericalSort = EditorPrefs.GetBool("AllowAlphaNumericHierarchy", false); - SetUpSortMethodLists(); - treeView.SetSelection(treeView.GetSelection(), true); - treeView.ReloadData(); - } - - void ExecuteCommands() - { - Event evt = Event.current; - - if (evt.type != EventType.ExecuteCommand && evt.type != EventType.ValidateCommand) - return; - - bool execute = evt.type == EventType.ExecuteCommand; - - if (evt.commandName == EventCommandNames.Delete || evt.commandName == EventCommandNames.SoftDelete) - { - if (execute) - DeleteGO(); - evt.Use(); - GUIUtility.ExitGUI(); - } - else if (evt.commandName == EventCommandNames.Duplicate) - { - if (execute) - DuplicateGO(); - evt.Use(); - GUIUtility.ExitGUI(); - } - else if (evt.commandName == EventCommandNames.Copy) - { - if (execute) - CopyGO(); - evt.Use(); - GUIUtility.ExitGUI(); - } - else if (evt.commandName == EventCommandNames.Paste) - { - if (execute) - PasteGO(); - evt.Use(); - GUIUtility.ExitGUI(); - } - else if (evt.commandName == EventCommandNames.SelectAll) - { - if (execute) - SelectAll(); - evt.Use(); - GUIUtility.ExitGUI(); - } - else if (evt.commandName == EventCommandNames.FrameSelected) - { - if (evt.type == EventType.ExecuteCommand) - FrameObjectPrivate(Selection.activeInstanceID, true, true, true); - evt.Use(); - GUIUtility.ExitGUI(); - } - else if (evt.commandName == EventCommandNames.Find) - { - if (evt.type == EventType.ExecuteCommand) - FocusSearchField(); - evt.Use(); - } - } - - void CreateGameObjectContextClick(GenericMenu menu, int contextClickedItemID) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Copy"), false, CopyGO); - menu.AddItem(EditorGUIUtility.TrTextContent("Paste"), false, PasteGO); - - menu.AddSeparator(""); - // TODO: Add this back in. - if (!hasSearchFilter && m_TreeViewState.selectedIDs.Count == 1) - menu.AddItem(EditorGUIUtility.TrTextContent("Rename"), false, RenameGO); - else - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Rename")); - menu.AddItem(EditorGUIUtility.TrTextContent("Duplicate"), false, DuplicateGO); - menu.AddItem(EditorGUIUtility.TrTextContent("Delete"), false, DeleteGO); - - menu.AddSeparator(""); - bool hasPrefabParent = false; - - if (m_TreeViewState.selectedIDs.Count == 1) - { - GameObjectTreeViewItem item = treeView.FindItem(m_TreeViewState.selectedIDs[0]) as GameObjectTreeViewItem; - if (item != null) - { - UnityEngine.Object prefab = PrefabUtility.GetPrefabParent(item.objectPPTR); - if (prefab != null) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Select Prefab"), false, () => - { - Selection.activeObject = prefab; - EditorGUIUtility.PingObject(prefab.GetInstanceID()); - }); - - hasPrefabParent = true; - } - } - } - - if (!hasPrefabParent) - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Select Prefab")); - - menu.AddSeparator(""); - - // Set the context of each MenuItem to the current selection, so the created gameobjects will be added as children - // Sets includeCreateEmptyChild to false, since that item is superfluous here (the normal "Create Empty" is added as a child anyway) - AddCreateGameObjectItemsToMenu(menu, Selection.transforms.Select(t => t.gameObject).ToArray(), false, false, kInvalidSceneHandle); - menu.ShowAsContext(); - } - - void CreateMultiSceneHeaderContextClick(GenericMenu menu, int contextClickedItemID) - { - Scene scene = EditorSceneManager.GetSceneByHandle(contextClickedItemID); - if (!IsSceneHeaderInHierarchyWindow(scene)) - { - Debug.LogError("Context clicked item is not a scene"); - return; - } - - bool hasMultipleScenes = EditorSceneManager.sceneCount > 1; - - // Set active - if (scene.isLoaded) - { - var content = EditorGUIUtility.TrTextContent("Set Active Scene"); - if (hasMultipleScenes && SceneManager.GetActiveScene() != scene) - menu.AddItem(content, false, SetSceneActive, contextClickedItemID); - else - menu.AddDisabledItem(content); - menu.AddSeparator(""); - } - - // Save - if (scene.isLoaded) - { - if (!EditorApplication.isPlaying) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Save Scene"), false, SaveSelectedScenes, contextClickedItemID); - menu.AddItem(EditorGUIUtility.TrTextContent("Save Scene As"), false, SaveSceneAs, contextClickedItemID); - if (hasMultipleScenes) - menu.AddItem(EditorGUIUtility.TrTextContent("Save All"), false, SaveAllScenes, contextClickedItemID); - else - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Save All")); - } - else - { - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Save Scene")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Save Scene As")); - menu.AddDisabledItem(EditorGUIUtility.TrTextContent("Save All")); - } - menu.AddSeparator(""); - } - - bool isUnloadOrRemoveValid = EditorSceneManager.loadedSceneCount != GetNumLoadedScenesInSelection(); - - if (scene.isLoaded) - { - // Unload - var content = EditorGUIUtility.TrTextContent("Unload Scene"); - bool canUnloadScenes = isUnloadOrRemoveValid && !EditorApplication.isPlaying && !string.IsNullOrEmpty(scene.path); - if (canUnloadScenes) - menu.AddItem(content, false, UnloadSelectedScenes, contextClickedItemID); - else - menu.AddDisabledItem(content); - } - else - { - // Load - var content = EditorGUIUtility.TrTextContent("Load Scene"); - bool canLoadScenes = !EditorApplication.isPlaying; - if (canLoadScenes) - menu.AddItem(content, false, LoadSelectedScenes, contextClickedItemID); - else - menu.AddDisabledItem(content); - } - - // Remove - var removeContent = EditorGUIUtility.TrTextContent("Remove Scene"); - bool selectedAllScenes = GetSelectedScenes().Count == EditorSceneManager.sceneCount; - bool canRemoveScenes = isUnloadOrRemoveValid && !selectedAllScenes && !EditorApplication.isPlaying; - if (canRemoveScenes) - menu.AddItem(removeContent, false, RemoveSelectedScenes, contextClickedItemID); - else - menu.AddDisabledItem(removeContent); - - // Discard changes - if (scene.isLoaded) - { - var content = EditorGUIUtility.TrTextContent("Discard changes"); - var selectedSceneHandles = GetSelectedScenes(); - var modifiedScenes = GetModifiedScenes(selectedSceneHandles); - bool canDiscardChanges = !EditorApplication.isPlaying && modifiedScenes.Length > 0; - if (canDiscardChanges) - menu.AddItem(content, false, DiscardChangesInSelectedScenes, contextClickedItemID); - else - menu.AddDisabledItem(content); - } - - // Ping Scene Asset - menu.AddSeparator(""); - var selectAssetContent = EditorGUIUtility.TrTextContent("Select Scene Asset"); - if (!string.IsNullOrEmpty(scene.path)) - menu.AddItem(selectAssetContent, false, SelectSceneAsset, contextClickedItemID); - else - menu.AddDisabledItem(selectAssetContent); - - var addSceneContent = EditorGUIUtility.TrTextContent("Add New Scene"); - if (!EditorApplication.isPlaying) - menu.AddItem(addSceneContent, false, AddNewScene, contextClickedItemID); - else - menu.AddDisabledItem(addSceneContent); - - // Set the context of each MenuItem to the current selection, so the created gameobjects will be added as children - // Sets includeCreateEmptyChild to false, since that item is superfluous here (the normal "Create Empty" is added as a child anyway) - if (scene.isLoaded) - { - menu.AddSeparator(""); - AddCreateGameObjectItemsToMenu(menu, Selection.transforms.Select(t => t.gameObject).ToArray(), false, true, scene.handle); - } - } - - int GetNumLoadedScenesInSelection() - { - int loadedScenes = 0; - foreach (int handle in GetSelectedScenes()) - { - if (EditorSceneManager.GetSceneByHandle(handle).isLoaded) - loadedScenes++; - } - return loadedScenes; - } - - // returns selected scene handles - List GetSelectedScenes() - { - var selectedSceneHandles = new List(); - int[] instanceIDs = m_TreeView.GetSelection(); - foreach (int id in instanceIDs) - { - if (IsSceneHeaderInHierarchyWindow(EditorSceneManager.GetSceneByHandle(id))) - { - selectedSceneHandles.Add(id); - } - } - return selectedSceneHandles; - } - - void ContextClickOutsideItems() - { - Event evt = Event.current; - evt.Use(); - - var menu = new GenericMenu(); - CreateGameObjectContextClick(menu, kInvalidSceneHandle); - - menu.ShowAsContext(); - } - - void ItemContextClick(int contextClickedItemID) - { - Event evt = Event.current; - - evt.Use(); - var menu = new GenericMenu(); - - bool clickedSceneHeader = IsSceneHeaderInHierarchyWindow(EditorSceneManager.GetSceneByHandle(contextClickedItemID)); - - if (clickedSceneHeader) - CreateMultiSceneHeaderContextClick(menu, contextClickedItemID); - else - CreateGameObjectContextClick(menu, contextClickedItemID); - - menu.ShowAsContext(); - } - - void CopyGO() - { - Unsupported.CopyGameObjectsToPasteboard(); - } - - void PasteGO() - { - Unsupported.PasteGameObjectsFromPasteboard(); - } - - void DuplicateGO() - { - Unsupported.DuplicateGameObjectsUsingPasteboard(); - } - - void RenameGO() - { - treeView.BeginNameEditing(0f); - } - - void DeleteGO() - { - Unsupported.DeleteGameObjectSelection(); - } - - void SetSceneActive(object userData) - { - int itemID = (int)userData; - EditorSceneManager.SetActiveScene(EditorSceneManager.GetSceneByHandle(itemID)); - } - - private void LoadSelectedScenes(object userdata) - { - List selectedScenes = GetSelectedScenes(); - foreach (var id in selectedScenes) - { - var scene = EditorSceneManager.GetSceneByHandle(id); - if (!scene.isLoaded) - EditorSceneManager.OpenScene(scene.path, OpenSceneMode.Additive); - } - - EditorApplication.RequestRepaintAllViews(); - } - - private void SaveSceneAs(object userdata) - { - int itemID = (int)userdata; - - var scene = EditorSceneManager.GetSceneByHandle(itemID); - if (scene.isLoaded) - { - EditorSceneManager.SaveSceneAs(scene); - } - } - - private void SaveAllScenes(object userdata) - { - EditorSceneManager.SaveOpenScenes(); - } - - void SaveSelectedScenes(object userdata) - { - List selectedScenes = GetSelectedScenes(); - foreach (var id in selectedScenes) - { - var scene = EditorSceneManager.GetSceneByHandle(id); - if (scene.isLoaded) - EditorSceneManager.SaveScene(scene); - } - } - - void UnloadSelectedScenes(object userdata) - { - const bool removeScenesFromHierarchy = false; - CloseSelectedScenes(removeScenesFromHierarchy); - } - - void RemoveSelectedScenes(object userData) - { - const bool removeScenesFromHierarchy = true; - CloseSelectedScenes(removeScenesFromHierarchy); - } - - bool UserAllowedDiscardingChanges(Scene[] modifiedScenes) - { - string title = "Discard Changes"; - string message = "Are you sure you want to discard the changes in the following scenes:\n\n {0}\n\nYour changes will be lost."; - - string sceneNames = string.Join("\n ", modifiedScenes.Select(scene => scene.name).ToArray()); - message = string.Format(message, sceneNames); - - return EditorUtility.DisplayDialog(title, message, "OK", "Cancel"); - } - - void DiscardChangesInSelectedScenes(object userData) - { - var expandedSceneNames = GetExpandedSceneNames(); - var selectedSceneHandles = GetSelectedScenes(); - var modifiedScenes = GetModifiedScenes(selectedSceneHandles); - var modifiedScenesWithSavePath = modifiedScenes.Where(scene => !string.IsNullOrEmpty(scene.path)).ToArray(); - - if (!UserAllowedDiscardingChanges(modifiedScenesWithSavePath)) - return; - - if (modifiedScenesWithSavePath.Length != modifiedScenes.Length) - 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."); - - foreach (var scene in modifiedScenesWithSavePath) - { - EditorSceneManager.ReloadScene(scene); - } - - // When reloading a single scene it will be given a new scene handle which will collapse it in the Hierarchy. - // Here we ensure same scene are expanded - if (SceneManager.sceneCount == 1) - SetScenesExpanded(expandedSceneNames.ToList()); - - EditorApplication.RequestRepaintAllViews(); - } - - Scene[] GetModifiedScenes(List handles) - { - return handles.Select(handle => EditorSceneManager.GetSceneByHandle(handle)).Where(scene => scene.isDirty).ToArray(); - } - - void CloseSelectedScenes(bool removeScenes) - { - var selectedSceneHandles = GetSelectedScenes(); - - var modifiedScenes = GetModifiedScenes(selectedSceneHandles); - bool userCancelled = !EditorSceneManager.SaveModifiedScenesIfUserWantsTo(modifiedScenes); - if (userCancelled) - return; - - foreach (var id in selectedSceneHandles) - EditorSceneManager.CloseScene(EditorSceneManager.GetSceneByHandle(id), removeScenes); - - EditorApplication.RequestRepaintAllViews(); - } - - void AddNewScene(object userData) - { - // Check for existing untitled scene - Scene untitledScene = EditorSceneManager.GetSceneByPath(""); - if (untitledScene.IsValid()) - { - var title = EditorGUIUtility.TrTextContent("Save Untitled Scene").text; - 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; - if (EditorUtility.DisplayDialog(title, subTitle, "Save", "Cancel")) - { - if (!EditorSceneManager.SaveScene(untitledScene)) - return; - } - else - return; - } - - Scene newScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects, NewSceneMode.Additive); - - // Move new scene after context clicked scene - int itemID = (int)userData; - var scene = EditorSceneManager.GetSceneByHandle(itemID); - if (scene.IsValid()) - EditorSceneManager.MoveSceneAfter(newScene, scene); - } - - void SelectSceneAsset(object userData) - { - int itemID = (int)userData; - var scene = EditorSceneManager.GetSceneByHandle(itemID); - var sceneObject = AssetDatabase.LoadMainAssetAtPath(scene.path); - Selection.activeObject = sceneObject; - EditorGUIUtility.PingObject(sceneObject); - } - - private void SelectAll() - { - int[] instanceIDs = treeView.GetRowIDs(); - treeView.SetSelection(instanceIDs, false); - TreeViewSelectionChanged(instanceIDs); - } - - static void ToggleDebugMode() - { - s_Debug = !s_Debug; - } - - public virtual void AddItemsToMenu(GenericMenu menu) - { - m_LockTracker.AddItemsToMenu(menu); - if (Unsupported.IsDeveloperMode()) - { - menu.AddItem(EditorGUIUtility.TrTextContent("DEVELOPER/Toggle DebugMode"), false, ToggleDebugMode); - } - } - - public void FrameObject(int instanceID, bool ping) - { - const bool animatedFraming = true; - FrameObjectPrivate(instanceID, true, ping, animatedFraming); - } - - private void FrameObjectPrivate(int instanceID, bool frame, bool ping, bool animatedFraming) - { - if (instanceID == 0) - return; - - // If framing the same instance as the last one we do not remove the ping - // since issuing first a ping and then a framing should still show the ping. - if (m_LastFramedID != instanceID) - treeView.EndPing(); - - SetSearchFilter("", SearchableEditorWindow.SearchMode.All, true); - - m_LastFramedID = instanceID; - - treeView.Frame(instanceID, frame, ping, animatedFraming); - - FrameObjectPrivate(InternalEditorUtility.GetGameObjectInstanceIDFromComponent(instanceID), frame, ping, animatedFraming); - } - - // Called from DockArea - protected virtual void ShowButton(Rect r) - { - if (s_Styles == null) - s_Styles = new Styles(); - - m_LockTracker.ShowButton(r, s_Styles.lockButton); - } - } - - // Used for type checking and text and icon for sort dropdown in the Hierarchy - internal abstract class HierarchySorting - { - public virtual GUIContent content { get { return null; } } - } - - internal class TransformSorting : HierarchySorting - { - readonly GUIContent m_Content = new GUIContent(EditorGUIUtility.FindTexture("DefaultSorting"), "Transform Child Order"); - public override GUIContent content { get { return m_Content; } } - } - - internal class AlphabeticalSorting : HierarchySorting - { - readonly GUIContent m_Content = new GUIContent(EditorGUIUtility.FindTexture("AlphabeticalSorting"), "Alphabetical Order"); - public override GUIContent content { get { return m_Content; } } - } - - // User defined sorting was disabled for 5.4 because of performance reasons. We cannot ensure sorting - // that is fast enough. So to prevent killing framerate in playmode we have removed BaseHierarchySort and friends - - [Obsolete("BaseHierarchySort is no longer supported because of performance reasons")] - public class TransformSort : BaseHierarchySort - { - readonly GUIContent m_Content = new GUIContent(EditorGUIUtility.FindTexture("DefaultSorting"), "Transform Child Order"); - public override GUIContent content { get { return m_Content; } } - } - - [Obsolete("BaseHierarchySort is no longer supported because of performance reasons")] - public class AlphabeticalSort : BaseHierarchySort - { - readonly GUIContent m_Content = new GUIContent(EditorGUIUtility.FindTexture("AlphabeticalSorting"), "Alphabetical Order"); - public override GUIContent content { get { return m_Content; } } - } - - - [Obsolete("BaseHierarchySort is no longer supported because of performance reasons")] - public abstract class BaseHierarchySort : IComparer - { - public virtual GUIContent content { get { return null; } } - public virtual int Compare(GameObject lhs, GameObject rhs) { return 0; } - } -} diff --git a/Editor/Mono/SceneManagement/EditorSceneManager.cs b/Editor/Mono/SceneManagement/EditorSceneManager.cs deleted file mode 100644 index eefe94b243..0000000000 --- a/Editor/Mono/SceneManagement/EditorSceneManager.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Scripting; -using UnityEngine.SceneManagement; - -namespace UnityEditor.SceneManagement -{ - public sealed partial class EditorSceneManager - { - public delegate void NewSceneCreatedCallback(Scene scene, NewSceneSetup setup, NewSceneMode mode); - public delegate void SceneOpeningCallback(string path, OpenSceneMode mode); - public delegate void SceneOpenedCallback(Scene scene, OpenSceneMode mode); - public delegate void SceneClosingCallback(Scene scene, bool removingScene); - public delegate void SceneClosedCallback(Scene scene); - public delegate void SceneSavingCallback(Scene scene, string path); - public delegate void SceneSavedCallback(Scene scene); - - public static event NewSceneCreatedCallback newSceneCreated; - public static event SceneOpeningCallback sceneOpening; - public static event SceneOpenedCallback sceneOpened; - public static event SceneClosingCallback sceneClosing; - public static event SceneClosedCallback sceneClosed; - public static event SceneSavingCallback sceneSaving; - public static event SceneSavedCallback sceneSaved; - - [RequiredByNativeCode] - private static void Internal_NewSceneCreated(Scene scene, NewSceneSetup setup, NewSceneMode mode) - { - if (newSceneCreated != null) - newSceneCreated(scene, setup, mode); - } - - [RequiredByNativeCode] - private static void Internal_SceneOpening(string path, OpenSceneMode mode) - { - if (sceneOpening != null) - sceneOpening(path, mode); - } - - [RequiredByNativeCode] - private static void Internal_SceneOpened(Scene scene, OpenSceneMode mode) - { - if (sceneOpened != null) - sceneOpened(scene, mode); - } - - [RequiredByNativeCode] - private static void Internal_SceneClosing(Scene scene, bool removingScene) - { - if (sceneClosing != null) - sceneClosing(scene, removingScene); - } - - [RequiredByNativeCode] - private static void Internal_SceneClosed(Scene scene) - { - if (sceneClosed != null) - sceneClosed(scene); - } - - [RequiredByNativeCode] - private static void Internal_SceneSaving(Scene scene, string path) - { - if (sceneSaving != null) - sceneSaving(scene, path); - } - - [RequiredByNativeCode] - private static void Internal_SceneSaved(Scene scene) - { - if (sceneSaved != null) - sceneSaved(scene); - } - } -} diff --git a/Editor/Mono/SceneManagement/SceneSetup.cs b/Editor/Mono/SceneManagement/SceneSetup.cs deleted file mode 100644 index 857c8c5f9e..0000000000 --- a/Editor/Mono/SceneManagement/SceneSetup.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Runtime.InteropServices; -using UnityEngine; - -// The setup information for a scene in the SceneManager. - -namespace UnityEditor.SceneManagement -{ - [StructLayout(LayoutKind.Sequential)] - [Serializable] - public class SceneSetup - { - [SerializeField] - private string m_Path = null; - [SerializeField] - private bool m_IsLoaded = false; - [SerializeField] - private bool m_IsActive = false; - - public string path - { - get { return m_Path; } - set { m_Path = value; } - } - - public bool isLoaded - { - get { return m_IsLoaded; } - set { m_IsLoaded = value; } - } - - public bool isActive - { - get { return m_IsActive; } - set { m_IsActive = value; } - } - } -} diff --git a/Editor/Mono/SceneModeWindows/LightTable.cs b/Editor/Mono/SceneModeWindows/LightTable.cs deleted file mode 100644 index 8930ff7997..0000000000 --- a/Editor/Mono/SceneModeWindows/LightTable.cs +++ /dev/null @@ -1,513 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Linq; - -namespace UnityEditor -{ - internal class LightTableColumns - { - static class Styles - { - public static readonly GUIContent[] ProjectionStrings = { EditorGUIUtility.TextContent("Infinite"), EditorGUIUtility.TrTextContent("Box") }; - public static readonly GUIContent[] LightmapEmissiveStrings = { EditorGUIUtility.TextContent("Realtime"), EditorGUIUtility.TrTextContent("Baked") }; - public static readonly GUIContent Name = EditorGUIUtility.TrTextContent("Name"); - public static readonly GUIContent On = EditorGUIUtility.TrTextContent("On"); - public static readonly GUIContent Type = EditorGUIUtility.TrTextContent("Type"); - public static readonly GUIContent Mode = EditorGUIUtility.TrTextContent("Mode"); - public static readonly GUIContent Color = EditorGUIUtility.TrTextContent("Color"); - public static readonly GUIContent Intensity = EditorGUIUtility.TrTextContent("Intensity"); - public static readonly GUIContent IndirectMultiplier = EditorGUIUtility.TrTextContent("Indirect Multiplier"); - public static readonly GUIContent ShadowType = EditorGUIUtility.TrTextContent("Shadow Type"); - public static readonly GUIContent Projection = EditorGUIUtility.TrTextContent("Projection"); - public static readonly GUIContent HDR = EditorGUIUtility.TrTextContent("HDR"); - public static readonly GUIContent ShadowDistance = EditorGUIUtility.TrTextContent("Shadow Distance"); - public static readonly GUIContent NearPlane = EditorGUIUtility.TrTextContent("Near Plane"); - public static readonly GUIContent FarPlane = EditorGUIUtility.TrTextContent("Far Plane"); - public static readonly GUIContent GlobalIllumination = EditorGUIUtility.TrTextContent("Global Illumination"); - public static readonly GUIContent SelectObjects = EditorGUIUtility.TextContent(""); - public static readonly GUIContent SelectObjectsButton = EditorGUIUtility.TrTextContentWithIcon("", "Find References in Scene", "UnityEditor.FindDependencies"); - - public static readonly GUIContent[] LightmapBakeTypeTitles = { EditorGUIUtility.TrTextContent("Realtime"), EditorGUIUtility.TrTextContent("Mixed"), EditorGUIUtility.TrTextContent("Baked") }; - public static readonly int[] LightmapBakeTypeValues = { (int)LightmapBakeType.Realtime, (int)LightmapBakeType.Mixed, (int)LightmapBakeType.Baked }; - } - - private static SerializedPropertyTreeView.Column[] FinalizeColumns(SerializedPropertyTreeView.Column[] columns, out string[] propNames) - { - propNames = new string[columns.Length]; - - for (int i = 0; i < columns.Length; i++) - propNames[i] = columns[i].propertyName; - - return columns; - } - - private static bool IsEditable(Object target) - { - return ((target.hideFlags & HideFlags.NotEditable) == 0); - } - - public static SerializedPropertyTreeView.Column[] CreateLightColumns(out string[] propNames) - { - var columns = new[] - { - new SerializedPropertyTreeView.Column // 0: Name - { - headerContent = Styles.Name, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 200, - minWidth = 100, - autoResize = false, - allowToggleVisibility = true, - propertyName = null, - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareName, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawName, - filter = new SerializedPropertyFilters.Name() - }, - new SerializedPropertyTreeView.Column // 1: Enabled - { - headerContent = Styles.On, - headerTextAlignment = TextAlignment.Center, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 25, - minWidth = 25, - maxWidth = 25, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_Enabled", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareCheckbox, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawCheckbox - }, - new SerializedPropertyTreeView.Column // 2: Type - { - headerContent = Styles.Type, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 120, - minWidth = 60, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_Type", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareEnum, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawDefault - }, - new SerializedPropertyTreeView.Column // 3: Mode - { - headerContent = Styles.Mode, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 70, - minWidth = 40, - maxWidth = 70, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_Lightmapping", - dependencyIndices = new int[] { 2 }, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareEnum, - drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) => - { - bool areaLight = dep.Length > 1 && dep[0].enumValueIndex == (int)LightType.Area; - - using (new EditorGUI.DisabledScope(areaLight)) - { - EditorGUI.BeginChangeCheck(); - int newval = EditorGUI.IntPopup(r, prop.intValue, Styles.LightmapBakeTypeTitles, Styles.LightmapBakeTypeValues); - if (EditorGUI.EndChangeCheck()) - { - prop.intValue = newval; - } - } - } - }, - new SerializedPropertyTreeView.Column // 4: Color - { - headerContent = Styles.Color, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 70, - minWidth = 40, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_Color", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareColor, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawDefault - }, - new SerializedPropertyTreeView.Column // 5: Intensity - { - headerContent = Styles.Intensity, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 60, - minWidth = 30, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_Intensity", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareFloat, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawDefault - }, - new SerializedPropertyTreeView.Column // 6: Indirect Multiplier - { - headerContent = Styles.IndirectMultiplier, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 110, - minWidth = 60, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_BounceIntensity", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareFloat, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawDefault - }, - new SerializedPropertyTreeView.Column // 7: Shadow Type - { - headerContent = Styles.ShadowType, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 100, - minWidth = 60, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_Shadows.m_Type", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareEnum, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawDefault - }, - }; - - return FinalizeColumns(columns, out propNames); - } - - public static SerializedPropertyTreeView.Column[] CreateReflectionColumns(out string[] propNames) - { - var columns = new[] - { - new SerializedPropertyTreeView.Column // 0: Name - { - headerContent = Styles.Name, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 200, - minWidth = 100, - autoResize = false, - allowToggleVisibility = true, - propertyName = null, - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareName, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawName, - filter = new SerializedPropertyFilters.Name() - }, - new SerializedPropertyTreeView.Column // 1: Enabled - { - headerContent = Styles.On, - headerTextAlignment = TextAlignment.Center, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 25, - minWidth = 25, - maxWidth = 25, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_Enabled", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareCheckbox, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawCheckbox - }, - new SerializedPropertyTreeView.Column // 2: Mode - { - headerContent = Styles.Mode, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 70, - minWidth = 40, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_Mode", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareInt, - drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) => - { - EditorGUI.IntPopup(r, prop, ReflectionProbeEditor.Styles.reflectionProbeMode, ReflectionProbeEditor.Styles.reflectionProbeModeValues, GUIContent.none); - } - }, - new SerializedPropertyTreeView.Column // 3: Projection - { - headerContent = Styles.Projection, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 80, - minWidth = 40, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_BoxProjection", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareCheckbox, - drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) => - { - int[] opts = { 0, 1 }; - prop.boolValue = EditorGUI.IntPopup(r, prop.boolValue ? 1 : 0, Styles.ProjectionStrings, opts) == 1; - } - }, - new SerializedPropertyTreeView.Column // 4: HDR - { - headerContent = Styles.HDR, - headerTextAlignment = TextAlignment.Center, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 35, - minWidth = 35, - maxWidth = 35, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_HDR", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareCheckbox, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawCheckbox - }, - new SerializedPropertyTreeView.Column // 5: Shadow Distance - { - headerContent = Styles.ShadowDistance, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 110, - minWidth = 50, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_ShadowDistance", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareFloat, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawDefault - }, - new SerializedPropertyTreeView.Column // 6: Near Plane - { - headerContent = Styles.NearPlane, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 70, - minWidth = 30, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_NearClip", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareFloat, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawDefault - }, - new SerializedPropertyTreeView.Column // 7: Far Plane - { - headerContent = Styles.FarPlane, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 70, - minWidth = 30, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_FarClip", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareFloat, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawDefault - }, - }; - - return FinalizeColumns(columns, out propNames); - } - - public static SerializedPropertyTreeView.Column[] CreateLightProbeColumns(out string[] propNames) - { - var columns = new[] - { - new SerializedPropertyTreeView.Column // 0: Name - { - headerContent = Styles.Name, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 200, - minWidth = 100, - autoResize = false, - allowToggleVisibility = true, - propertyName = null, - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareName, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawName, - filter = new SerializedPropertyFilters.Name() - }, - new SerializedPropertyTreeView.Column // 1: Enabled - { - headerContent = Styles.On, - headerTextAlignment = TextAlignment.Center, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 25, - minWidth = 25, - maxWidth = 25, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_Enabled", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareCheckbox, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawCheckbox - } - }; - - return FinalizeColumns(columns, out propNames); - } - - public static SerializedPropertyTreeView.Column[] CreateEmissivesColumns(out string[] propNames) - { - var columns = new[] - { - new SerializedPropertyTreeView.Column // 0: Icon - { - headerContent = Styles.SelectObjects, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 20, - minWidth = 20, - maxWidth = 20, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_LightmapFlags", - dependencyIndices = null, - compareDelegate = null, - drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) => - { - if (GUI.Button(r, Styles.SelectObjectsButton, "label")) - { - SearchableEditorWindow.SearchForReferencesToInstanceID(prop.serializedObject.targetObject.GetInstanceID()); - } - } - }, - new SerializedPropertyTreeView.Column // 1: Name - { - headerContent = Styles.Name, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 200, - minWidth = 100, - autoResize = false, - allowToggleVisibility = true, - propertyName = null, - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareName, - drawDelegate = SerializedPropertyTreeView.DefaultDelegates.s_DrawName, - filter = new SerializedPropertyFilters.Name() - }, - new SerializedPropertyTreeView.Column // 2: GI - { - headerContent = Styles.GlobalIllumination, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 120, - minWidth = 70, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_LightmapFlags", - dependencyIndices = null, - compareDelegate = SerializedPropertyTreeView.DefaultDelegates.s_CompareInt, - drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) => - { - if (!prop.serializedObject.targetObject.GetType().Equals(typeof(Material))) - return; - - using (new EditorGUI.DisabledScope(!IsEditable(prop.serializedObject.targetObject))) - { - MaterialGlobalIlluminationFlags giFlags = ((prop.intValue & (int)MaterialGlobalIlluminationFlags.BakedEmissive) != 0) ? MaterialGlobalIlluminationFlags.BakedEmissive : MaterialGlobalIlluminationFlags.RealtimeEmissive; - - int[] lightmapEmissiveValues = { (int)MaterialGlobalIlluminationFlags.RealtimeEmissive, (int)MaterialGlobalIlluminationFlags.BakedEmissive }; - - EditorGUI.BeginChangeCheck(); - - giFlags = (MaterialGlobalIlluminationFlags)EditorGUI.IntPopup(r, (int)giFlags, Styles.LightmapEmissiveStrings, lightmapEmissiveValues); - - if (EditorGUI.EndChangeCheck()) - { - Material material = (Material)prop.serializedObject.targetObject; - Undo.RecordObjects(new Material[] { material } , "Modify GI Settings of " + material.name); - - material.globalIlluminationFlags = giFlags; - - prop.serializedObject.Update(); - } - } - } - }, - new SerializedPropertyTreeView.Column // 3: Color - { - headerContent = Styles.Color, - headerTextAlignment = TextAlignment.Left, - sortedAscending = true, - sortingArrowAlignment = TextAlignment.Center, - width = 70, - minWidth = 40, - autoResize = false, - allowToggleVisibility = true, - propertyName = "m_Shader", - dependencyIndices = null, - compareDelegate = (SerializedProperty lhs, SerializedProperty rhs) => - { - float lh, ls, lv, rh, rs, rv; - Color.RGBToHSV(((Material)lhs.serializedObject.targetObject).GetColor("_EmissionColor"), out lh, out ls, out lv); - Color.RGBToHSV(((Material)rhs.serializedObject.targetObject).GetColor("_EmissionColor"), out rh, out rs, out rv); - return lv.CompareTo(rv); - }, - drawDelegate = (Rect r, SerializedProperty prop, SerializedProperty[] dep) => - { - if (!prop.serializedObject.targetObject.GetType().Equals(typeof(Material))) - return; - - using (new EditorGUI.DisabledScope(!IsEditable(prop.serializedObject.targetObject))) - { - Material material = (Material)prop.serializedObject.targetObject; - - Color color = material.GetColor("_EmissionColor"); - - EditorGUI.BeginChangeCheck(); - Color newValue = EditorGUI.ColorField(r, GUIContent.Temp(""), color, true, false, true); - - if (EditorGUI.EndChangeCheck()) - { - Undo.RecordObjects(new Material[] { material }, "Modify Emission Color of " + material.name); - material.SetColor("_EmissionColor", newValue); - } - } - }, - copyDelegate = (SerializedProperty target, SerializedProperty source) => - { - Material sourceMaterial = (Material)source.serializedObject.targetObject; - Color color = sourceMaterial.GetColor("_EmissionColor"); - - Material targetMaterial = (Material)target.serializedObject.targetObject; - targetMaterial.SetColor("_EmissionColor", color); - } - } - }; - - return FinalizeColumns(columns, out propNames); - } - } -} diff --git a/Editor/Mono/SceneModeWindows/LightingExplorerWindow.cs b/Editor/Mono/SceneModeWindows/LightingExplorerWindow.cs deleted file mode 100644 index f241c82fb9..0000000000 --- a/Editor/Mono/SceneModeWindows/LightingExplorerWindow.cs +++ /dev/null @@ -1,181 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Light Explorer", icon = "Lighting")] - internal class LightingExplorerWindow : EditorWindow - { - static class Styles - { - public static readonly GUIContent[] TabTypes = - { - EditorGUIUtility.TrTextContent("Lights"), - EditorGUIUtility.TrTextContent("Reflection Probes"), - EditorGUIUtility.TrTextContent("Light Probes"), - EditorGUIUtility.TrTextContent("Static Emissives") - }; - } - - List m_TableTabs; - - float m_ToolbarPadding = -1; - TabType m_SelectedTab = TabType.Lights; - - enum TabType - { - Lights, - Reflections, - LightProbes, - Emissives, - Count - } - - [MenuItem("Window/Lighting/Light Explorer", false, 2099)] - static void CreateLightingExplorerWindow() - { - LightingExplorerWindow window = EditorWindow.GetWindow(); - window.minSize = new Vector2(500, 250); - window.Show(); - } - - private float toolbarPadding - { - get - { - if (m_ToolbarPadding == -1) - { - var iconsSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.helpIcon); - m_ToolbarPadding = (iconsSize.x * 2) + (EditorGUI.kControlVerticalSpacing * 3); - } - return m_ToolbarPadding; - } - } - - void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - - if (m_TableTabs == null || m_TableTabs.Count != (int)TabType.Count) - { - m_TableTabs = new List - { - new LightingExplorerWindowTab(new SerializedPropertyTable("LightTable", () => { - return UnityEngine.Object.FindObjectsOfType(); - }, LightTableColumns.CreateLightColumns)), - new LightingExplorerWindowTab(new SerializedPropertyTable("ReflectionTable", () => { - return UnityEngine.Object.FindObjectsOfType(); - }, LightTableColumns.CreateReflectionColumns)), - new LightingExplorerWindowTab(new SerializedPropertyTable("LightProbeTable", () => { - return UnityEngine.Object.FindObjectsOfType(); - }, LightTableColumns.CreateLightProbeColumns)), - new LightingExplorerWindowTab(new SerializedPropertyTable("EmissiveMaterialTable", - StaticEmissivesGatherDelegate(), LightTableColumns.CreateEmissivesColumns)) - }; - } - - for (int i = 0; i < m_TableTabs.Count; i++) - { - m_TableTabs[i].OnEnable(); - } - - EditorApplication.searchChanged += Repaint; - Repaint(); - } - - void OnDisable() - { - if (m_TableTabs != null) - { - for (int i = 0; i < m_TableTabs.Count; i++) - { - m_TableTabs[i].OnDisable(); - } - } - - EditorApplication.searchChanged -= Repaint; - } - - void OnInspectorUpdate() - { - if (m_TableTabs != null && (int)m_SelectedTab >= 0 && (int)m_SelectedTab < m_TableTabs.Count) - { - m_TableTabs[(int)m_SelectedTab].OnInspectorUpdate(); - } - } - - void OnSelectionChange() - { - if (m_TableTabs != null) - { - for (int i = 0; i < m_TableTabs.Count; i++) - { - if (i == (m_TableTabs.Count - 1)) // last tab containing materials - { - int[] selectedIds = Object.FindObjectsOfType().Where((MeshRenderer mr) => { - return Selection.instanceIDs.Contains(mr.gameObject.GetInstanceID()); - }).SelectMany(meshRenderer => meshRenderer.sharedMaterials).Where((Material m) => { - return m != null && (m.globalIlluminationFlags & MaterialGlobalIlluminationFlags.AnyEmissive) != 0; - }).Select(m => m.GetInstanceID()).Union(Selection.instanceIDs).Distinct().ToArray(); - - m_TableTabs[i].OnSelectionChange(selectedIds); - } - else - m_TableTabs[i].OnSelectionChange(); - } - } - - Repaint(); - } - - void OnHierarchyChange() - { - if (m_TableTabs != null) - { - for (int i = 0; i < m_TableTabs.Count; i++) - { - m_TableTabs[i].OnHierarchyChange(); - } - } - } - - void OnGUI() - { - EditorGUIUtility.labelWidth = 130; - - EditorGUILayout.Space(); - EditorGUILayout.BeginHorizontal(); - - GUILayout.FlexibleSpace(); - m_SelectedTab = (TabType)GUILayout.Toolbar((int)m_SelectedTab, Styles.TabTypes, "LargeButton", GUI.ToolbarButtonSize.FitToContents); - GUILayout.FlexibleSpace(); - - EditorGUILayout.EndHorizontal(); - EditorGUILayout.Space(); - - EditorGUILayout.BeginHorizontal(); - if (m_TableTabs != null && (int)m_SelectedTab >= 0 && (int)m_SelectedTab < m_TableTabs.Count) - m_TableTabs[(int)m_SelectedTab].OnGUI(); - EditorGUILayout.Space(); - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.Space(); - } - - private SerializedPropertyDataStore.GatherDelegate StaticEmissivesGatherDelegate() - { - return () => { - return Object.FindObjectsOfType().Where((MeshRenderer mr) => { - return (GameObjectUtility.AreStaticEditorFlagsSet(mr.gameObject, StaticEditorFlags.LightmapStatic)); - }).SelectMany(meshRenderer => meshRenderer.sharedMaterials).Where((Material m) => { - return m != null && ((m.globalIlluminationFlags & MaterialGlobalIlluminationFlags.AnyEmissive) != 0) && m.HasProperty("_EmissionColor"); - }).Distinct().ToArray(); - }; - } - } -} diff --git a/Editor/Mono/SceneModeWindows/LightingExplorerWindowTableTab.cs b/Editor/Mono/SceneModeWindows/LightingExplorerWindowTableTab.cs deleted file mode 100644 index 0c9ad15afd..0000000000 --- a/Editor/Mono/SceneModeWindows/LightingExplorerWindowTableTab.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class LightingExplorerWindowTab - { - SerializedPropertyTable m_LightTable; - - public LightingExplorerWindowTab(SerializedPropertyTable lightTable) - { - m_LightTable = lightTable; - } - - public void OnEnable() - { - if (m_LightTable != null) - m_LightTable.OnEnable(); - } - - public void OnDisable() - { - if (m_LightTable != null) - m_LightTable.OnDisable(); - } - - public void OnInspectorUpdate() - { - if (m_LightTable != null) - m_LightTable.OnInspectorUpdate(); - } - - public void OnSelectionChange(int[] instanceIDs) - { - if (m_LightTable != null) - m_LightTable.OnSelectionChange(instanceIDs); - } - - public void OnSelectionChange() - { - if (m_LightTable != null) - m_LightTable.OnSelectionChange(); - } - - public void OnHierarchyChange() - { - if (m_LightTable != null) - m_LightTable.OnHierarchyChange(); - } - - public void OnGUI() - { - EditorGUI.indentLevel += 1; - - int cur_indent = EditorGUI.indentLevel; - float cur_indent_px = EditorGUI.indent; - EditorGUI.indentLevel = 0; - - EditorGUILayout.BeginHorizontal(); - GUILayout.Space(cur_indent_px); - - using (new EditorGUILayout.VerticalScope()) - { - if (m_LightTable != null) - m_LightTable.OnGUI(); - } - - EditorGUILayout.EndHorizontal(); - EditorGUILayout.Space(); - EditorGUI.indentLevel = cur_indent; - - EditorGUI.indentLevel -= 1; - } - } -} diff --git a/Editor/Mono/SceneModeWindows/LightingWindow.cs b/Editor/Mono/SceneModeWindows/LightingWindow.cs deleted file mode 100644 index 250a7bf1d9..0000000000 --- a/Editor/Mono/SceneModeWindows/LightingWindow.cs +++ /dev/null @@ -1,553 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Collections; -using System.Linq; -using System.Text; -using UnityEditor.AnimatedValues; -using UnityEditor.SceneManagement; -using UnityEditorInternal; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEngineInternal; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Lighting", icon = "Lighting")] - internal class LightingWindow : EditorWindow - { - public const float kButtonWidth = 150; - - enum Mode - { - LightingSettings, - OutputMaps, - ObjectSettings, - } - - enum BakeMode - { - BakeReflectionProbes = 0, - Clear = 1 - } - - static string[] s_BakeModeOptions = - { - "Bake Reflection Probes", - "Clear Baked Data" - }; - - const string kGlobalIlluminationUnityManualPage = "file:///unity/Manual/GlobalIllumination.html"; - - Mode m_Mode = Mode.LightingSettings; - Vector2 m_ScrollPositionLighting = Vector2.zero; - Vector2 m_ScrollPositionOutputMaps = Vector2.zero; - - LightingWindowObjectTab m_ObjectTab; - public LightingWindowLightingTab m_LightingTab; - LightingWindowLightmapPreviewTab m_LightmapPreviewTab; - - SerializedObject m_LightmapSettings; - SerializedProperty m_WorkflowMode; - SerializedProperty m_EnabledBakedGI; - - PreviewResizer m_PreviewResizer = new PreviewResizer(); - - static bool s_IsVisible = false; - float m_ToolbarPadding = -1; - - private float toolbarPadding - { - get - { - if (m_ToolbarPadding == -1) - { - var iconsSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.helpIcon); - m_ToolbarPadding = (iconsSize.x * 2) + (EditorGUI.kControlVerticalSpacing * 3); - } - return m_ToolbarPadding; - } - } - - void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - - m_LightingTab = new LightingWindowLightingTab(); - m_LightingTab.OnEnable(); - m_LightmapPreviewTab = new LightingWindowLightmapPreviewTab(); - m_ObjectTab = new LightingWindowObjectTab(); - m_ObjectTab.OnEnable(this); - - InitLightmapSettings(); - - autoRepaintOnSceneChange = false; - m_PreviewResizer.Init("LightmappingPreview"); - EditorApplication.searchChanged += Repaint; - Repaint(); - } - - void OnDisable() - { - m_LightingTab.OnDisable(); - m_ObjectTab.OnDisable(); - EditorApplication.searchChanged -= Repaint; - } - - void OnBecameVisible() - { - if (s_IsVisible == true) return; - s_IsVisible = true; - RepaintSceneAndGameViews(); - } - - void OnBecameInvisible() - { - s_IsVisible = false; - RepaintSceneAndGameViews(); - } - - void OnSelectionChange() - { - m_LightmapPreviewTab.UpdateLightmapSelection(); - - Repaint(); - } - - static internal void RepaintSceneAndGameViews() - { - SceneView.RepaintAll(); - GameView.RepaintAll(); - } - - void OnGUI() - { - InitLightmapSettings(); - - m_LightmapSettings.Update(); - - EditorGUILayout.Space(); - EditorGUILayout.BeginHorizontal(); - - GUILayout.Space(toolbarPadding); - ModeToggle(); - DrawHelpGUI(); - if (m_Mode == Mode.LightingSettings) - DrawSettingsGUI(); - - EditorGUILayout.EndHorizontal(); - EditorGUILayout.Space(); - - switch (m_Mode) - { - case Mode.LightingSettings: - m_ScrollPositionLighting = EditorGUILayout.BeginScrollView(m_ScrollPositionLighting); - m_LightingTab.OnGUI(); - EditorGUILayout.EndScrollView(); - EditorGUILayout.Space(); - break; - case Mode.OutputMaps: - m_ScrollPositionOutputMaps = EditorGUILayout.BeginScrollView(m_ScrollPositionOutputMaps); - m_LightmapPreviewTab.Maps(); - EditorGUILayout.EndScrollView(); - EditorGUILayout.Space(); - break; - - case Mode.ObjectSettings: - break; - } - - Buttons(); - Summary(); - PreviewSection(); - - m_LightmapSettings.ApplyModifiedProperties(); - } - - void InitLightmapSettings() - { - if (m_LightmapSettings == null || m_LightmapSettings.targetObject != LightmapEditorSettings.GetLightmapSettings()) - { - m_LightmapSettings = new SerializedObject(LightmapEditorSettings.GetLightmapSettings()); - m_EnabledBakedGI = m_LightmapSettings.FindProperty("m_GISettings.m_EnableBakedLightmaps"); - m_WorkflowMode = m_LightmapSettings.FindProperty("m_GIWorkflowMode"); - } - } - - void DrawHelpGUI() - { - var iconSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.helpIcon); - var rect = GUILayoutUtility.GetRect(iconSize.x, iconSize.y); - - if (GUI.Button(rect, EditorGUI.GUIContents.helpIcon, EditorStyles.iconButton)) - { - Help.ShowHelpPage(kGlobalIlluminationUnityManualPage); - } - } - - void DrawSettingsGUI() - { - var iconSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.titleSettingsIcon); - var rect = GUILayoutUtility.GetRect(iconSize.x, iconSize.y); - if (EditorGUI.DropdownButton(rect, EditorGUI.GUIContents.titleSettingsIcon, FocusType.Passive, EditorStyles.iconButton)) - { - //@TODO: Split... - EditorUtility.DisplayCustomMenu(rect, new[] { EditorGUIUtility.TrTextContent("Reset") }, -1, ResetSettings, null); - } - } - - void ResetSettings(object userData, string[] options, int selected) - { - RenderSettings.Reset(); - LightmapEditorSettings.Reset(); - LightmapSettings.Reset(); - } - - void PreviewSection() - { - if (m_Mode == Mode.OutputMaps) - { - EditorGUILayout.BeginHorizontal(GUIContent.none, Styles.ToolbarStyle, GUILayout.Height(17)); - { - GUILayout.FlexibleSpace(); - GUI.Label(GUILayoutUtility.GetLastRect(), "Preview", Styles.ToolbarTitleStyle); - } - EditorGUILayout.EndHorizontal(); - } - - switch (m_Mode) - { - case Mode.OutputMaps: - { - float previewSize = m_PreviewResizer.ResizeHandle(position, 100, 250, 17); - Rect previewRect = new Rect(0, position.height - previewSize, position.width, previewSize); - - if (previewSize > 0) - m_LightmapPreviewTab.LightmapPreview(previewRect); - } break; - case Mode.ObjectSettings: - { - //@TODO use gui layout to display ObjectPreview or deduct rect from previous window. - int height = LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveCPU ? 185 : 115; - - Rect fullRect = new Rect(0, height, position.width, position.height - height); - if (Selection.activeGameObject) - m_ObjectTab.ObjectPreview(fullRect); - } break; - } - } - - void ModeToggle() - { - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - m_Mode = (Mode)GUILayout.Toolbar((int)m_Mode, Styles.ModeToggles, Styles.ButtonStyle, GUI.ToolbarButtonSize.FitToContents); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - } - - void BakeDropDownCallback(object data) - { - BakeMode mode = (BakeMode)data; - - switch (mode) - { - case BakeMode.Clear: - DoClear(); - break; - case BakeMode.BakeReflectionProbes: - DoBakeReflectionProbes(); - break; - } - } - - void Buttons() - { - bool wasGUIEnabled = GUI.enabled; - GUI.enabled &= !EditorApplication.isPlayingOrWillChangePlaymode; - - if (Lightmapping.lightingDataAsset && !Lightmapping.lightingDataAsset.isValid) - { - EditorGUILayout.HelpBox(Lightmapping.lightingDataAsset.validityErrorMessage, MessageType.Warning); - } - - EditorGUILayout.Space(); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - Rect rect = GUILayoutUtility.GetRect(Styles.ContinuousBakeLabel, GUIStyle.none); - EditorGUI.BeginProperty(rect, Styles.ContinuousBakeLabel, m_WorkflowMode); - - bool iterative = m_WorkflowMode.intValue == (int)Lightmapping.GIWorkflowMode.Iterative; - - EditorGUI.BeginChangeCheck(); - iterative = GUILayout.Toggle(iterative, Styles.ContinuousBakeLabel); - - if (EditorGUI.EndChangeCheck()) - { - m_WorkflowMode.intValue = (int)(iterative ? Lightmapping.GIWorkflowMode.Iterative : Lightmapping.GIWorkflowMode.OnDemand); - } - - EditorGUI.EndProperty(); - - using (new EditorGUI.DisabledScope(iterative)) - { - // Bake button if we are not currently baking - bool showBakeButton = iterative || !Lightmapping.isRunning; - if (showBakeButton) - { - if (EditorGUI.ButtonWithDropdownList(Styles.BuildLabel, s_BakeModeOptions, BakeDropDownCallback, GUILayout.Width(170))) - { - DoBake(); - - // DoBake could've spawned a save scene dialog. This breaks GUI on mac (Case 490388). - // We work around this with an ExitGUI here. - GUIUtility.ExitGUI(); - } - } - // Cancel button if we are currently baking - else - { - // Only show Force Stop when using the PathTracer backend - if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveCPU && - m_EnabledBakedGI.boolValue && - GUILayout.Button("Force Stop", GUILayout.Width(kButtonWidth))) - { - Lightmapping.ForceStop(); - } - if (GUILayout.Button("Cancel", GUILayout.Width(kButtonWidth))) - { - Lightmapping.Cancel(); - UsabilityAnalytics.Track("/LightMapper/Cancel"); - } - } - } - - GUILayout.EndHorizontal(); - EditorGUILayout.Space(); - GUI.enabled = wasGUIEnabled; - } - - private void DoBake() - { - UsabilityAnalytics.Track("/LightMapper/Start"); - UsabilityAnalytics.Event("LightMapper", "Mode", LightmapSettings.lightmapsMode.ToString(), 1); - - UsabilityAnalytics.Event("LightMapper", "Button", "BakeScene", 1); - Lightmapping.BakeAsync(); - } - - private void DoClear() - { - Lightmapping.ClearLightingDataAsset(); - Lightmapping.Clear(); - UsabilityAnalytics.Track("/LightMapper/Clear"); - } - - private void DoBakeReflectionProbes() - { - Lightmapping.BakeAllReflectionProbesSnapshots(); - UsabilityAnalytics.Track("/LightMapper/BakeAllReflectionProbesSnapshots"); - } - - void Summary() - { - GUILayout.BeginVertical(EditorStyles.helpBox); - - long totalMemorySize = 0; - int lightmapCount = 0; - Dictionary sizes = new Dictionary(); - bool directionalLightmapsMode = false; - bool shadowmaskMode = false; - foreach (LightmapData ld in LightmapSettings.lightmaps) - { - if (ld.lightmapColor == null) - continue; - lightmapCount++; - - Vector2 texSize = new Vector2(ld.lightmapColor.width, ld.lightmapColor.height); - if (sizes.ContainsKey(texSize)) - sizes[texSize]++; - else - sizes.Add(texSize, 1); - - totalMemorySize += TextureUtil.GetStorageMemorySizeLong(ld.lightmapColor); - if (ld.lightmapDir) - { - totalMemorySize += TextureUtil.GetStorageMemorySizeLong(ld.lightmapDir); - directionalLightmapsMode = true; - } - if (ld.shadowMask) - { - totalMemorySize += TextureUtil.GetStorageMemorySizeLong(ld.shadowMask); - shadowmaskMode = true; - } - } - StringBuilder sizesString = new StringBuilder(); - sizesString.Append(lightmapCount); - sizesString.Append((directionalLightmapsMode ? " Directional" : " Non-Directional")); - sizesString.Append(" Lightmap"); - if (lightmapCount != 1) sizesString.Append("s"); - if (shadowmaskMode) - { - sizesString.Append(" with Shadowmask"); - if (lightmapCount != 1) sizesString.Append("s"); - } - - bool first = true; - foreach (var s in sizes) - { - sizesString.Append(first ? ": " : ", "); - first = false; - if (s.Value > 1) - { - sizesString.Append(s.Value); - sizesString.Append("x"); - } - sizesString.Append(s.Key.x); - sizesString.Append("x"); - sizesString.Append(s.Key.y); - sizesString.Append("px"); - } - sizesString.Append(" "); - - GUILayout.BeginHorizontal(); - - GUILayout.BeginVertical(); - GUILayout.Label(sizesString.ToString(), Styles.LabelStyle); - GUILayout.EndVertical(); - - GUILayout.BeginVertical(); - GUILayout.Label(EditorUtility.FormatBytes(totalMemorySize), Styles.LabelStyle); - GUILayout.Label((lightmapCount == 0 ? "No Lightmaps" : ""), Styles.LabelStyle); - GUILayout.EndVertical(); - - GUILayout.EndHorizontal(); - - if (LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.Enlighten) - { - GUILayout.BeginVertical(); - GUILayout.Label("Memory Usage: " + Lightmapping.ComputeTotalMemoryUsageInMB().ToString("0.0") + " MB", Styles.LabelStyle); - GUILayout.Label("Occupied Texels: " + InternalEditorUtility.CountToString(Lightmapping.occupiedTexelCount), Styles.LabelStyle); - if (Lightmapping.isRunning) - { - int numLightmapsInView = 0; - int numConvergedLightmapsInView = 0; - int numNotConvergedLightmapsInView = 0; - - int numLightmapsNotInView = 0; - int numConvergedLightmapsNotInView = 0; - int numNotConvergedLightmapsNotInView = 0; - - int numInvalidConvergenceLightmaps = 0; - int numLightmaps = LightmapSettings.lightmaps.Length; - for (int i = 0; i < numLightmaps; ++i) - { - LightmapConvergence lc = Lightmapping.GetLightmapConvergence(i); - if (!lc.IsValid()) - { - numInvalidConvergenceLightmaps++; - continue; - } - - if (Lightmapping.GetVisibleTexelCount(i) > 0) - { - numLightmapsInView++; - if (lc.IsConverged()) - numConvergedLightmapsInView++; - else - numNotConvergedLightmapsInView++; - } - else - { - numLightmapsNotInView++; - if (lc.IsConverged()) - numConvergedLightmapsNotInView++; - else - numNotConvergedLightmapsNotInView++; - } - } - EditorGUILayout.LabelField("Lightmaps in view: " + numLightmapsInView, Styles.LabelStyle); - EditorGUI.indentLevel += 1; - EditorGUILayout.LabelField("Converged: " + numConvergedLightmapsInView, Styles.LabelStyle); - EditorGUILayout.LabelField("Not Converged: " + numNotConvergedLightmapsInView, Styles.LabelStyle); - EditorGUI.indentLevel -= 1; - EditorGUILayout.LabelField("Lightmaps not in view: " + numLightmapsNotInView, Styles.LabelStyle); - EditorGUI.indentLevel += 1; - EditorGUILayout.LabelField("Converged: " + numConvergedLightmapsNotInView, Styles.LabelStyle); - EditorGUILayout.LabelField("Not Converged: " + numNotConvergedLightmapsNotInView, Styles.LabelStyle); - EditorGUI.indentLevel -= 1; - } - float bakeTime = Lightmapping.GetLightmapBakeTimeTotal(); - float mraysPerSec = Lightmapping.GetLightmapBakePerformanceTotal(); - if (mraysPerSec >= 0.0) - GUILayout.Label("Bake Performance: " + mraysPerSec.ToString("0.00") + " mrays/sec", Styles.LabelStyle); - if (!Lightmapping.isRunning) - { - float bakeTimeRaw = Lightmapping.GetLightmapBakeTimeRaw(); - if (bakeTime >= 0.0) - { - int time = (int)bakeTime; - int timeH = time / 3600; - time -= 3600 * timeH; - int timeM = time / 60; - time -= 60 * timeM; - int timeS = time; - - int timeRaw = (int)bakeTimeRaw; - int timeRawH = timeRaw / 3600; - timeRaw -= 3600 * timeRawH; - int timeRawM = timeRaw / 60; - timeRaw -= 60 * timeRawM; - int timeRawS = timeRaw; - - int oHeadTime = Math.Max(0, (int)(bakeTime - bakeTimeRaw)); - int oHeadTimeH = oHeadTime / 3600; - oHeadTime -= 3600 * oHeadTimeH; - int oHeadTimeM = oHeadTime / 60; - oHeadTime -= 60 * oHeadTimeM; - int oHeadTimeS = oHeadTime; - - - GUILayout.Label("Total Bake Time: " + timeH.ToString("0") + ":" + timeM.ToString("00") + ":" + timeS.ToString("00"), Styles.LabelStyle); - if (Unsupported.IsDeveloperMode()) - GUILayout.Label("(Raw Bake Time: " + timeRawH.ToString("0") + ":" + timeRawM.ToString("00") + ":" + timeRawS.ToString("00") + ", Overhead: " + oHeadTimeH.ToString("0") + ":" + oHeadTimeM.ToString("00") + ":" + oHeadTimeS.ToString("00") + ")", Styles.LabelStyle); - } - } - GUILayout.EndVertical(); - } - - GUILayout.EndVertical(); - } - - [MenuItem("Window/Lighting/Settings", false, 2098)] - static void CreateLightingWindow() - { - LightingWindow window = EditorWindow.GetWindow(); - window.minSize = new Vector2(360, 390); - window.Show(); - } - - static class Styles - { - public static readonly GUIContent[] ModeToggles = - { - EditorGUIUtility.TrTextContent("Scene"), - EditorGUIUtility.TrTextContent("Global Maps"), - EditorGUIUtility.TrTextContent("Object Maps") - }; - - public static readonly GUIContent ContinuousBakeLabel = EditorGUIUtility.TrTextContent("Auto Generate", "Automatically generates lighting data in the Scene when any changes are made to the lighting systems."); - public static readonly GUIContent BuildLabel = EditorGUIUtility.TrTextContent("Generate Lighting", "Generates the lightmap data for the current master scene. This lightmap data (for realtime and baked global illumination) is stored in the GI Cache. For GI Cache settings see the Preferences panel."); - - public static readonly GUIStyle LabelStyle = EditorStyles.wordWrappedMiniLabel; - public static readonly GUIStyle ToolbarStyle = "preToolbar"; - public static readonly GUIStyle ToolbarTitleStyle = "preToolbar"; - public static readonly GUIStyle ButtonStyle = "LargeButton"; - } - } -} // namespace diff --git a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs deleted file mode 100644 index d357809e46..0000000000 --- a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs +++ /dev/null @@ -1,643 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Collections; -using System.Linq; -using UnityEditor.AnimatedValues; -using UnityEngine.Experimental.Rendering; -using UnityEditorInternal; -using UnityEngine; -using UnityEngineInternal; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class LightingWindowBakeSettings - { - // light modes - private bool m_ShowRealtimeLightsSettings = true; - private bool m_ShowMixedLightsSettings = true; - private bool m_ShowGeneralLightmapSettings = true; - private const string kShowRealtimeLightsSettingsKey = "ShowRealtimeLightsSettings"; - private const string kShowMixedLightsSettingsKey = "ShowMixedLightsSettings"; - private const string kShowGeneralLightmapSettingsKey = "ShowGeneralLightmapSettings"; - - SerializedObject m_LightmapSettingsSO; - Object m_LightmapSettings; - - SerializedObject m_RenderSettingsSO; - - //realtime GI - SerializedProperty m_EnableRealtimeGI; - SerializedProperty m_Resolution; - - //baked - SerializedProperty m_MixedBakeMode; - SerializedProperty m_EnabledBakedGI; - SerializedProperty m_AlbedoBoost; - SerializedProperty m_IndirectOutputScale; - SerializedProperty m_LightmapParameters; - SerializedProperty m_LightmapDirectionalMode; - SerializedProperty m_BakeResolution; - SerializedProperty m_Padding; - SerializedProperty m_AmbientOcclusion; - SerializedProperty m_AOMaxDistance; - SerializedProperty m_CompAOExponent; - SerializedProperty m_CompAOExponentDirect; - SerializedProperty m_TextureCompression; - SerializedProperty m_FinalGather; - SerializedProperty m_FinalGatherRayCount; - SerializedProperty m_FinalGatherFiltering; - SerializedProperty m_LightmapSize; - SerializedProperty m_SubtractiveShadowColor; - SerializedProperty m_BakeBackend; - //SerializedProperty m_PVRSampling; // TODO(PVR): make non-fixed sampling modes work. - SerializedProperty m_PVRSampleCount; - SerializedProperty m_PVRDirectSampleCount; - SerializedProperty m_PVRBounces; - SerializedProperty m_PVRCulling; - SerializedProperty m_PVRFilteringMode; - SerializedProperty m_PVRFilterTypeDirect; - SerializedProperty m_PVRFilterTypeIndirect; - SerializedProperty m_PVRFilterTypeAO; - SerializedProperty m_PVRFilteringGaussRadiusDirect; - SerializedProperty m_PVRFilteringGaussRadiusIndirect; - SerializedProperty m_PVRFilteringGaussRadiusAO; - SerializedProperty m_PVRFilteringAtrousPositionSigmaDirect; - SerializedProperty m_PVRFilteringAtrousPositionSigmaIndirect; - SerializedProperty m_PVRFilteringAtrousPositionSigmaAO; - - SerializedProperty m_BounceScale; - SerializedProperty m_UpdateThreshold; - - static bool PlayerHasSM20Support() - { - var apis = PlayerSettings.GetGraphicsAPIs(EditorUserBuildSettings.activeBuildTarget); - bool hasSM20Api = apis.Contains(UnityEngine.Rendering.GraphicsDeviceType.OpenGLES2) || apis.Contains(UnityEngine.Rendering.GraphicsDeviceType.N3DS); - return hasSM20Api; - } - - private void InitSettings() - { - Object renderSettings = RenderSettings.GetRenderSettings(); - SerializedObject rso = m_RenderSettingsSO = new SerializedObject(renderSettings); - - m_SubtractiveShadowColor = rso.FindProperty("m_SubtractiveShadowColor"); - - m_LightmapSettings = LightmapEditorSettings.GetLightmapSettings(); - SerializedObject so = m_LightmapSettingsSO = new SerializedObject(m_LightmapSettings); - - //realtime GI - m_EnableRealtimeGI = so.FindProperty("m_GISettings.m_EnableRealtimeLightmaps"); - m_Resolution = so.FindProperty("m_LightmapEditorSettings.m_Resolution"); - - //baked - m_MixedBakeMode = so.FindProperty("m_LightmapEditorSettings.m_MixedBakeMode"); - m_EnabledBakedGI = so.FindProperty("m_GISettings.m_EnableBakedLightmaps"); - m_AlbedoBoost = so.FindProperty("m_GISettings.m_AlbedoBoost"); - m_IndirectOutputScale = so.FindProperty("m_GISettings.m_IndirectOutputScale"); - m_LightmapParameters = so.FindProperty("m_LightmapEditorSettings.m_LightmapParameters"); - m_LightmapDirectionalMode = so.FindProperty("m_LightmapEditorSettings.m_LightmapsBakeMode"); - m_BakeResolution = so.FindProperty("m_LightmapEditorSettings.m_BakeResolution"); - m_Padding = so.FindProperty("m_LightmapEditorSettings.m_Padding"); - m_AmbientOcclusion = so.FindProperty("m_LightmapEditorSettings.m_AO"); - m_AOMaxDistance = so.FindProperty("m_LightmapEditorSettings.m_AOMaxDistance"); - m_CompAOExponent = so.FindProperty("m_LightmapEditorSettings.m_CompAOExponent"); - m_CompAOExponentDirect = so.FindProperty("m_LightmapEditorSettings.m_CompAOExponentDirect"); - m_TextureCompression = so.FindProperty("m_LightmapEditorSettings.m_TextureCompression"); - m_FinalGather = so.FindProperty("m_LightmapEditorSettings.m_FinalGather"); - m_FinalGatherRayCount = so.FindProperty("m_LightmapEditorSettings.m_FinalGatherRayCount"); - m_FinalGatherFiltering = so.FindProperty("m_LightmapEditorSettings.m_FinalGatherFiltering"); - m_LightmapSize = so.FindProperty("m_LightmapEditorSettings.m_AtlasSize"); - m_BakeBackend = so.FindProperty("m_LightmapEditorSettings.m_BakeBackend"); - //m_PVRSampling = so.FindProperty("m_LightmapEditorSettings.m_PVRSampling"); // TODO(PVR): make non-fixed sampling modes work. - m_PVRSampleCount = so.FindProperty("m_LightmapEditorSettings.m_PVRSampleCount"); - m_PVRDirectSampleCount = so.FindProperty("m_LightmapEditorSettings.m_PVRDirectSampleCount"); - m_PVRBounces = so.FindProperty("m_LightmapEditorSettings.m_PVRBounces"); - m_PVRCulling = so.FindProperty("m_LightmapEditorSettings.m_PVRCulling"); - m_PVRFilteringMode = so.FindProperty("m_LightmapEditorSettings.m_PVRFilteringMode"); - m_PVRFilterTypeDirect = so.FindProperty("m_LightmapEditorSettings.m_PVRFilterTypeDirect"); - m_PVRFilterTypeIndirect = so.FindProperty("m_LightmapEditorSettings.m_PVRFilterTypeIndirect"); - m_PVRFilterTypeAO = so.FindProperty("m_LightmapEditorSettings.m_PVRFilterTypeAO"); - m_PVRFilteringGaussRadiusDirect = so.FindProperty("m_LightmapEditorSettings.m_PVRFilteringGaussRadiusDirect"); - m_PVRFilteringGaussRadiusIndirect = so.FindProperty("m_LightmapEditorSettings.m_PVRFilteringGaussRadiusIndirect"); - m_PVRFilteringGaussRadiusAO = so.FindProperty("m_LightmapEditorSettings.m_PVRFilteringGaussRadiusAO"); - m_PVRFilteringAtrousPositionSigmaDirect = so.FindProperty("m_LightmapEditorSettings.m_PVRFilteringAtrousPositionSigmaDirect"); - m_PVRFilteringAtrousPositionSigmaIndirect = so.FindProperty("m_LightmapEditorSettings.m_PVRFilteringAtrousPositionSigmaIndirect"); - m_PVRFilteringAtrousPositionSigmaAO = so.FindProperty("m_LightmapEditorSettings.m_PVRFilteringAtrousPositionSigmaAO"); - - //dev debug properties - m_BounceScale = so.FindProperty("m_GISettings.m_BounceScale"); - m_UpdateThreshold = so.FindProperty("m_GISettings.m_TemporalCoherenceThreshold"); - } - - public void OnEnable() - { - InitSettings(); - - m_ShowGeneralLightmapSettings = SessionState.GetBool(kShowGeneralLightmapSettingsKey, true); - m_ShowRealtimeLightsSettings = SessionState.GetBool(kShowRealtimeLightsSettingsKey, true); - m_ShowMixedLightsSettings = SessionState.GetBool(kShowMixedLightsSettingsKey, true); - } - - public void OnDisable() - { - SessionState.SetBool(kShowGeneralLightmapSettingsKey, m_ShowGeneralLightmapSettings); - SessionState.SetBool(kShowRealtimeLightsSettingsKey, m_ShowRealtimeLightsSettings); - SessionState.SetBool(kShowMixedLightsSettingsKey, m_ShowMixedLightsSettings); - - m_LightmapSettingsSO.Dispose(); - m_LightmapSettings = null; - m_RenderSettingsSO.Dispose(); - } - - void Repaint() { InspectorWindow.RepaintAllInspectors(); } - - static void DrawResolutionField(SerializedProperty resolution, GUIContent label) - { - GUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(resolution, label); - - GUILayout.Label(" texels per unit", Styles.LabelStyle); - GUILayout.EndHorizontal(); - } - - static void DrawFilterSettingField(SerializedProperty gaussSetting, - SerializedProperty atrousSetting, - GUIContent gaussLabel, - GUIContent atrousLabel, - LightmapEditorSettings.FilterType type) - { - if (type == LightmapEditorSettings.FilterType.None) - return; - - GUILayout.BeginHorizontal(); - - if (type == LightmapEditorSettings.FilterType.Gaussian) - { - EditorGUILayout.IntSlider(gaussSetting, 0, 5, gaussLabel); - GUILayout.Label(" texels", Styles.LabelStyle); - } - else if (type == LightmapEditorSettings.FilterType.ATrous) - { - EditorGUILayout.Slider(atrousSetting, 0.0f, 2.0f, atrousLabel); - GUILayout.Label(" sigma", Styles.LabelStyle); - } - - GUILayout.EndHorizontal(); - } - - static private bool isBuiltIn(SerializedProperty prop) - { - if (prop.objectReferenceValue != null) - { - var parameters = prop.objectReferenceValue as LightmapParameters; - return (parameters.hideFlags == HideFlags.NotEditable); - } - - return true; - } - - static private bool LightmapParametersGUI(SerializedProperty prop, GUIContent content) - { - EditorGUILayout.BeginHorizontal(); - - EditorGUIInternal.AssetPopup(prop, content, "giparams", "Default-Medium"); - - string label = "Edit..."; - - if (isBuiltIn(prop)) - label = "View"; - - bool editClicked = false; - - if (prop.objectReferenceValue == null) - { - using (new EditorGUI.DisabledScope(true)) - { - if (GUILayout.Button(label, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - { - Selection.activeObject = null; - editClicked = true; - } - } - } - else - { - if (GUILayout.Button(label, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - { - Selection.activeObject = prop.objectReferenceValue; - editClicked = true; - } - } - - EditorGUILayout.EndHorizontal(); - - return editClicked; - } - - void RealtimeLightingGUI() - { - if (!SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime)) - return; - - m_ShowRealtimeLightsSettings = EditorGUILayout.FoldoutTitlebar(m_ShowRealtimeLightsSettings, Styles.RealtimeLightsLabel, true); - - if (m_ShowRealtimeLightsSettings) - { - EditorGUI.indentLevel++; - - EditorGUILayout.PropertyField(m_EnableRealtimeGI, Styles.UseRealtimeGI); - - if (m_EnableRealtimeGI.boolValue && PlayerHasSM20Support()) - { - EditorGUILayout.HelpBox(Styles.NoRealtimeGIInSM2AndGLES2.text, MessageType.Warning); - } - - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - } - - void MixedLightingGUI() - { - if (!SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Baked)) - return; - - m_ShowMixedLightsSettings = EditorGUILayout.FoldoutTitlebar(m_ShowMixedLightsSettings, Styles.MixedLightsLabel, true); - - if (m_ShowMixedLightsSettings) - { - EditorGUI.indentLevel++; - - EditorGUILayout.PropertyField(m_EnabledBakedGI, Styles.EnableBaked); - - if (!m_EnabledBakedGI.boolValue) - { - EditorGUILayout.HelpBox(Styles.BakedGIDisabledInfo.text, MessageType.Info); - } - - using (new EditorGUI.DisabledScope(!m_EnabledBakedGI.boolValue)) - { - bool mixedGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Mixed); - - if (mixedGISupported) - { - EditorGUILayout.IntPopup(m_MixedBakeMode, Styles.MixedModeStrings, Styles.MixedModeValues, Styles.MixedLightMode); - - if (!SupportedRenderingFeatures.IsMixedLightingModeSupported((MixedLightingMode)m_MixedBakeMode.intValue)) - { - string fallbackMode = Styles.MixedModeStrings[(int)SupportedRenderingFeatures.FallbackMixedLightingMode()].text; - - EditorGUILayout.HelpBox("The Mixed Mode is not supported by the current render pipline. Fallback mode is " + fallbackMode, MessageType.Warning); - } - else if (m_EnabledBakedGI.boolValue) - { - EditorGUILayout.HelpBox(Styles.HelpStringsMixed[m_MixedBakeMode.intValue].text, MessageType.Info); - } - - if (m_MixedBakeMode.intValue == (int)MixedLightingMode.Subtractive) - { - EditorGUILayout.PropertyField(m_SubtractiveShadowColor, Styles.SubtractiveShadowColor); - m_RenderSettingsSO.ApplyModifiedProperties(); - EditorGUILayout.Space(); - } - } - } - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - } - - public void DeveloperBuildSettingsGUI() - { - if (!Unsupported.IsDeveloperMode()) - return; - - Lightmapping.concurrentJobsType = (Lightmapping.ConcurrentJobsType)EditorGUILayout.IntPopup(Styles.ConcurrentJobs, (int)Lightmapping.concurrentJobsType, Styles.ConcurrentJobsTypeStrings, Styles.ConcurrentJobsTypeValues); - Lightmapping.enlightenForceUpdates = EditorGUILayout.Toggle(Styles.ForceUpdates, Lightmapping.enlightenForceUpdates); - Lightmapping.enlightenForceWhiteAlbedo = EditorGUILayout.Toggle(Styles.ForceWhiteAlbedo, Lightmapping.enlightenForceWhiteAlbedo); - Lightmapping.filterMode = (FilterMode)EditorGUILayout.EnumPopup(EditorGUIUtility.TempContent("Filter Mode"), Lightmapping.filterMode); - - EditorGUILayout.Slider(m_BounceScale, 0.0f, 10.0f, Styles.BounceScale); - EditorGUILayout.Slider(m_UpdateThreshold, 0.0f, 1.0f, Styles.UpdateThreshold); - - if (GUILayout.Button("Clear disk cache", GUILayout.Width(LightingWindow.kButtonWidth))) - { - Lightmapping.Clear(); - Lightmapping.ClearDiskCache(); - } - - if (GUILayout.Button("Print state to console", GUILayout.Width(LightingWindow.kButtonWidth))) - { - Lightmapping.PrintStateToConsole(); - } - - if (GUILayout.Button("Reset albedo/emissive", GUILayout.Width(LightingWindow.kButtonWidth))) - GIDebugVisualisation.ResetRuntimeInputTextures(); - - if (GUILayout.Button("Reset environment", GUILayout.Width(LightingWindow.kButtonWidth))) - DynamicGI.UpdateEnvironment(); - } - - void GeneralLightmapSettingsGUI() - { - bool bakedGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Baked); - - if (!bakedGISupported && !SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime)) - return; - - m_ShowGeneralLightmapSettings = EditorGUILayout.FoldoutTitlebar(m_ShowGeneralLightmapSettings, Styles.GeneralLightmapLabel, true); - if (m_ShowGeneralLightmapSettings) - { - EditorGUI.indentLevel++; - using (new EditorGUI.DisabledScope(!m_EnabledBakedGI.boolValue && !m_EnableRealtimeGI.boolValue)) - { - if (bakedGISupported) - { - using (new EditorGUI.DisabledScope(!m_EnabledBakedGI.boolValue)) - { - EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(m_BakeBackend, Styles.BakeBackend); - if (EditorGUI.EndChangeCheck()) - InspectorWindow.RepaintAllInspectors(); // We need to repaint other inspectors that might need to update based on the selected backend. - if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveCPU) - { - EditorGUI.indentLevel++; - - EditorGUILayout.PropertyField(m_PVRCulling, Styles.PVRCulling); - - // Sampling type - //EditorGUILayout.PropertyField(m_PvrSampling, Styles.m_PVRSampling); // TODO(PVR): make non-fixed sampling modes work. - - if (LightmapEditorSettings.sampling != LightmapEditorSettings.Sampling.Auto) - { - // Update those constants also in LightmapBake.cpp UpdateSamples(). - const int kMinSamples = 10; - const int kMaxSamples = 100000; - - // Sample count - // TODO(PVR): make non-fixed sampling modes work. - //EditorGUI.indentLevel++; - //if (LightmapEditorSettings.giPathTracerSampling == LightmapEditorSettings.PathTracerSampling.PathTracerSamplingAdaptive) - // EditorGUILayout.PropertyField(m_PVRSampleCount, Styles.PVRSampleCountAdaptive); - //else - - EditorGUILayout.PropertyField(m_PVRDirectSampleCount, Styles.PVRDirectSampleCount); - EditorGUILayout.PropertyField(m_PVRSampleCount, Styles.PVRIndirectSampleCount); - - if (m_PVRSampleCount.intValue < kMinSamples || - m_PVRSampleCount.intValue > kMaxSamples) - { - m_PVRSampleCount.intValue = Math.Max(Math.Min(m_PVRSampleCount.intValue, kMaxSamples), kMinSamples); - } - - // TODO(PVR): make non-fixed sampling modes work. - //EditorGUI.indentLevel--; - } - - EditorGUILayout.IntPopup(m_PVRBounces, Styles.BouncesStrings, Styles.BouncesValues, Styles.PVRBounces); - - // Filtering - EditorGUILayout.PropertyField(m_PVRFilteringMode, Styles.PVRFilteringMode); - - if (m_PVRFilteringMode.enumValueIndex == (int)LightmapEditorSettings.FilterMode.Advanced) - { - EditorGUI.indentLevel++; - - EditorGUILayout.PropertyField(m_PVRFilterTypeDirect, Styles.PVRFilterTypeDirect); - DrawFilterSettingField(m_PVRFilteringGaussRadiusDirect, - m_PVRFilteringAtrousPositionSigmaDirect, - Styles.PVRFilteringGaussRadiusDirect, - Styles.PVRFilteringAtrousPositionSigmaDirect, - LightmapEditorSettings.filterTypeDirect); - - EditorGUILayout.Space(); - - EditorGUILayout.PropertyField(m_PVRFilterTypeIndirect, Styles.PVRFilterTypeIndirect); - DrawFilterSettingField(m_PVRFilteringGaussRadiusIndirect, - m_PVRFilteringAtrousPositionSigmaIndirect, - Styles.PVRFilteringGaussRadiusIndirect, - Styles.PVRFilteringAtrousPositionSigmaIndirect, - LightmapEditorSettings.filterTypeIndirect); - - using (new EditorGUI.DisabledScope(!m_AmbientOcclusion.boolValue)) - { - EditorGUILayout.Space(); - - EditorGUILayout.PropertyField(m_PVRFilterTypeAO, Styles.PVRFilterTypeAO); - DrawFilterSettingField(m_PVRFilteringGaussRadiusAO, - m_PVRFilteringAtrousPositionSigmaAO, - Styles.PVRFilteringGaussRadiusAO, Styles.PVRFilteringAtrousPositionSigmaAO, - LightmapEditorSettings.filterTypeAO); - } - - EditorGUI.indentLevel--; - } - - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - } - } - - using (new EditorGUI.DisabledScope((LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveCPU) && !m_EnableRealtimeGI.boolValue)) - { - DrawResolutionField(m_Resolution, Styles.IndirectResolution); - } - - if (bakedGISupported) - { - using (new EditorGUI.DisabledScope(!m_EnabledBakedGI.boolValue)) - { - DrawResolutionField(m_BakeResolution, Styles.LightmapResolution); - - GUILayout.BeginHorizontal(); - EditorGUILayout.PropertyField(m_Padding, Styles.Padding); - GUILayout.Label(" texels", Styles.LabelStyle); - GUILayout.EndHorizontal(); - - EditorGUILayout.IntPopup(m_LightmapSize, Styles.LightmapSizeStrings, Styles.LightmapSizeValues, Styles.LightmapSize); - - EditorGUILayout.PropertyField(m_TextureCompression, Styles.TextureCompression); - - EditorGUILayout.PropertyField(m_AmbientOcclusion, Styles.AmbientOcclusion); - if (m_AmbientOcclusion.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_AOMaxDistance, Styles.AOMaxDistance); - if (m_AOMaxDistance.floatValue < 0.0f) - m_AOMaxDistance.floatValue = 0.0f; - EditorGUILayout.Slider(m_CompAOExponent, 0.0f, 10.0f, Styles.AmbientOcclusionContribution); - EditorGUILayout.Slider(m_CompAOExponentDirect, 0.0f, 10.0f, Styles.AmbientOcclusionContributionDirect); - EditorGUI.indentLevel--; - } - - if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.Enlighten) - { - EditorGUILayout.PropertyField(m_FinalGather, Styles.FinalGather); - if (m_FinalGather.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_FinalGatherRayCount, Styles.FinalGatherRayCount); - EditorGUILayout.PropertyField(m_FinalGatherFiltering, Styles.FinalGatherFiltering); - EditorGUI.indentLevel--; - } - } - } - } - - bool directionalSupported = SupportedRenderingFeatures.IsLightmapsModeSupported(LightmapsMode.CombinedDirectional); - - if (directionalSupported || (m_LightmapDirectionalMode.intValue == (int)LightmapsMode.CombinedDirectional)) - { - EditorGUILayout.IntPopup(m_LightmapDirectionalMode, Styles.LightmapDirectionalModeStrings, Styles.LightmapDirectionalModeValues, Styles.LightmapDirectionalMode); - - if (!directionalSupported) - { - EditorGUILayout.HelpBox("Directional Mode is not supported. Fallback will be Non-Directional.", MessageType.Warning); - } - } - else - { - using (new EditorGUI.DisabledScope(true)) - { - EditorGUILayout.IntPopup(Styles.LightmapDirectionalMode, 0, Styles.LightmapDirectionalModeStrings, Styles.LightmapDirectionalModeValues); - } - } - - EditorGUILayout.Slider(m_IndirectOutputScale, 0.0f, 5.0f, Styles.IndirectOutputScale); - - // albedo boost, push the albedo value towards one in order to get more bounce - EditorGUILayout.Slider(m_AlbedoBoost, 1.0f, 10.0f, Styles.AlbedoBoost); - - if (LightmapParametersGUI(m_LightmapParameters, Styles.DefaultLightmapParameters)) - { - EditorWindow.FocusWindowIfItsOpen(); - } - - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - } - } - - public void OnGUI() - { - if (m_LightmapSettings == null || m_LightmapSettings != LightmapEditorSettings.GetLightmapSettings()) - { - InitSettings(); - } - - m_LightmapSettingsSO.UpdateIfRequiredOrScript(); - - RealtimeLightingGUI(); - MixedLightingGUI(); - GeneralLightmapSettingsGUI(); - - m_LightmapSettingsSO.ApplyModifiedProperties(); - } - - static class Styles - { - public static readonly int[] LightmapDirectionalModeValues = { (int)LightmapsMode.NonDirectional, (int)LightmapsMode.CombinedDirectional }; - public static readonly GUIContent[] LightmapDirectionalModeStrings = - { - EditorGUIUtility.TrTextContent("Non-Directional"), - EditorGUIUtility.TrTextContent("Directional"), - }; - - public static readonly int[] LightmapSizeValues = { 32, 64, 128, 256, 512, 1024, 2048, 4096 }; - public static readonly GUIContent[] LightmapSizeStrings = Array.ConvertAll(LightmapSizeValues, (x) => new GUIContent(x.ToString())); - - public static readonly int[] ConcurrentJobsTypeValues = { (int)Lightmapping.ConcurrentJobsType.Min, (int)Lightmapping.ConcurrentJobsType.Low, (int)Lightmapping.ConcurrentJobsType.High }; - public static readonly GUIContent[] ConcurrentJobsTypeStrings = - { - EditorGUIUtility.TrTextContent("Min"), - EditorGUIUtility.TrTextContent("Low"), - EditorGUIUtility.TrTextContent("High") - }; - - // must match LightmapMixedBakeMode - public static readonly int[] MixedModeValues = { 0, 1, 2 }; - public static readonly GUIContent[] MixedModeStrings = - { - EditorGUIUtility.TrTextContent("Baked Indirect"), - EditorGUIUtility.TrTextContent("Subtractive"), - EditorGUIUtility.TrTextContent("Shadowmask") - }; - - public static readonly int[] BouncesValues = { 0, 1, 2, 3, 4 }; - public static readonly GUIContent[] BouncesStrings = - { - EditorGUIUtility.TrTextContent("None"), - EditorGUIUtility.TextContent("1"), - EditorGUIUtility.TextContent("2"), - EditorGUIUtility.TextContent("3"), - EditorGUIUtility.TextContent("4") - }; - - public static readonly GUIContent[] HelpStringsMixed = - { - EditorGUIUtility.TrTextContent("Mixed lights provide realtime direct lighting while indirect light is baked into lightmaps and light probes."), - EditorGUIUtility.TrTextContent("Mixed lights provide baked direct and indirect lighting for static objects. Dynamic objects receive realtime direct lighting and cast shadows on static objects using the main directional light in the scene."), - EditorGUIUtility.TrTextContent("Mixed lights provide realtime direct lighting. Indirect lighting gets baked into lightmaps and light probes. Shadowmasks and light probes occlusion get generated for baked shadows. The Shadowmask Mode used at run time can be set in the Quality Settings panel.") - }; - - public static readonly GUIContent EnableBaked = EditorGUIUtility.TextContent("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."); - public static readonly GUIContent BounceScale = EditorGUIUtility.TextContent("Bounce Scale|Multiplier for indirect lighting. Use with care."); - public static readonly GUIContent UpdateThreshold = EditorGUIUtility.TextContent("Update Threshold|Threshold for updating realtime GI. A lower value causes more frequent updates (default 1.0)."); - public static readonly GUIContent AlbedoBoost = EditorGUIUtility.TextContent("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."); - public static readonly GUIContent IndirectOutputScale = EditorGUIUtility.TextContent("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."); - public static readonly GUIContent LightmapDirectionalMode = EditorGUIUtility.TextContent("Directional Mode|Controls whether baked and realtime lightmaps will store directional lighting information from the lighting environment. Options are Directional and Non-Directional."); - public static readonly GUIContent DefaultLightmapParameters = EditorGUIUtility.TextContent("Lightmap Parameters|Allows the adjustment of advanced parameters that affect the process of generating a lightmap for an object using global illumination."); - public static readonly GUIContent RealtimeLightsLabel = EditorGUIUtility.TextContent("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."); - public static readonly GUIContent MixedLightsLabel = EditorGUIUtility.TextContent("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."); - public static readonly GUIContent GeneralLightmapLabel = EditorGUIUtility.TextContent("Lightmapping Settings|Settings that apply to both Global Illumination modes (Precomputed Realtime and Baked)."); - public static readonly GUIContent NoRealtimeGIInSM2AndGLES2 = EditorGUIUtility.TextContent("Realtime Global Illumination is not supported on SM2.0 hardware nor when using GLES2.0."); - public static readonly GUIContent ConcurrentJobs = EditorGUIUtility.TextContent("Concurrent Jobs|The amount of simultaneously scheduled jobs."); - public static readonly GUIContent ForceWhiteAlbedo = EditorGUIUtility.TextContent("Force White Albedo|Force white albedo during lighting calculations."); - public static readonly GUIContent ForceUpdates = EditorGUIUtility.TextContent("Force Updates|Force continuous updates of runtime indirect lighting calculations."); - public static readonly GUIStyle LabelStyle = EditorStyles.wordWrappedMiniLabel; - 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 larger the value, the more significant the impact will be on the time it takes to bake the lighting."); - public static readonly GUIContent LightmapResolution = EditorGUIUtility.TrTextContent("Lightmap Resolution", "Sets the resolution in texels that are used per unit for objects being lit by baked global illumination. Larger values will result in increased time to calculate the baked lighting."); - public static readonly GUIContent Padding = EditorGUIUtility.TrTextContent("Lightmap Padding", "Sets the separation in texels between shapes in the baked lightmap."); - public static readonly GUIContent LightmapSize = EditorGUIUtility.TrTextContent("Lightmap Size", "Sets the resolution of the full lightmap Texture in pixels. Values are squared, so a setting of 1024 will produce a 1024x1024 pixel sized lightmap."); - public static readonly GUIContent TextureCompression = EditorGUIUtility.TrTextContent("Compress Lightmaps", "Controls whether the baked lightmap is compressed or not. When enabled, baked lightmaps are compressed to reduce required storage space but some artifacting may be present due to compression."); - 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."); - 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."); - 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."); - 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."); - public static readonly GUIContent FinalGather = EditorGUIUtility.TrTextContent("Final Gather", "Specifies whether the final light bounce of the global illumination calculation is calculated at the same resolution as the baked lightmap. When enabled, visual quality is improved at the cost of additional time required to bake the lighting."); - public static readonly GUIContent FinalGatherRayCount = EditorGUIUtility.TrTextContent("Ray Count", "Controls the number of rays emitted for every final gather point."); - public static readonly GUIContent FinalGatherFiltering = EditorGUIUtility.TrTextContent("Denoising", "Controls whether a denoising filter is applied to the final gather output."); - public static readonly GUIContent SubtractiveShadowColor = 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."); - public static readonly GUIContent MixedLightMode = EditorGUIUtility.TrTextContent("Lighting Mode", "Specifies which Scene lighting mode will be used for all Mixed lights in the Scene. Options are Baked Indirect, Shadowmask and Subtractive."); - public static readonly GUIContent UseRealtimeGI = EditorGUIUtility.TrTextContent("Realtime Global Illumination", "Controls whether Realtime lights in the Scene contribute indirect light. If enabled, Realtime lights contribute both direct and indirect light. If disabled, Realtime lights only contribute direct light. This can be disabled on a per-light basis in the light component Inspector by setting Indirect Multiplier to 0."); - 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."); - public static readonly GUIContent BakeBackend = EditorGUIUtility.TrTextContent("Lightmapper", "Specifies which baking system will be used to generate baked lightmaps."); - //public static readonly GUIContent PVRSampling = EditorGUIUtility.TrTextContent("Sampling", "How to sample the lightmaps. Auto and adaptive automatically tests for convergence. Auto uses a maximum of 16K samples. Adaptive uses a configurable maximum number of samples. Fixed always uses the set number of samples and does not test for convergence."); - //public static readonly GUIContent PVRDirectSampleCountAdaptive = EditorGUIUtility.TrTextContent("Max Direct Samples", "Maximum number of samples to use for direct lighting."); - public static readonly GUIContent PVRDirectSampleCount = 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."); - //public static readonly GUIContent PVRSampleCountAdaptive = EditorGUIUtility.TrTextContent("Max Indirect Samples", "Maximum number of samples to use for indirect lighting."); - public static readonly GUIContent PVRIndirectSampleCount = 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."); - public static readonly GUIContent PVRBounces = EditorGUIUtility.TrTextContent("Bounces", "Controls the maximum number of bounces the lightmapper will compute for indirect light."); - public static readonly GUIContent PVRFilteringMode = EditorGUIUtility.TrTextContent("Filtering", "Specifies the method used to reduce noise in baked lightmaps. Options are None, Automatic, or Advanced."); - public static readonly GUIContent PVRFiltering = EditorGUIUtility.TrTextContent("Filtering", "Specifies the filter kernel used to reduce the amount of noise in baked lightmaps."); - public static readonly GUIContent PVRFilteringAdvanced = EditorGUIUtility.TrTextContent("Advanced Filter Settings", "Show advanced settings to configure filtering on lightmaps."); - public static readonly GUIContent PVRFilterTypeDirect = EditorGUIUtility.TrTextContent("Direct Filter", "Specifies the filter kernel applied to the direct light stored in the lightmap. Gaussian will blur the lightmap with some loss of detail. A-Trous will reduce noise based on a threshold while maintaining edge detail."); - public static readonly GUIContent PVRFilterTypeIndirect = EditorGUIUtility.TrTextContent("Indirect Filter", "Specifies the filter kernel applied to the indirect light stored in the lightmap. Gaussian will blur the lightmap with some loss of detail. A-Trous will reduce noise based on a threshold while maintaining edge detail."); - public static readonly GUIContent PVRFilterTypeAO = EditorGUIUtility.TrTextContent("Ambient Occlusion Filter", "Specifies the filter kernel applied to the ambient occlusion stored in the lightmap. Gaussian will blur the lightmap with some loss of detail. A-Trous will reduce noise based on a threshold while maintaining edge detail."); - public static readonly GUIContent PVRFilteringGaussRadiusDirect = EditorGUIUtility.TrTextContent("Direct Radius", "Controls the radius of the filter for direct light stored in the lightmap. A higher value will increase the strength of the blur, reducing noise from direct light in the lightmap."); - public static readonly GUIContent PVRFilteringGaussRadiusIndirect = EditorGUIUtility.TrTextContent("Indirect Radius", "Controls the radius of the filter for indirect light stored in the lightmap. A higher value will increase the strength of the blur, reducing noise from indirect light in the lightmap."); - public static readonly GUIContent PVRFilteringGaussRadiusAO = EditorGUIUtility.TrTextContent("Ambient Occlusion Radius", "The radius of the filter for ambient occlusion in the lightmap. A higher radius will increase the blur strength, reducing sampling noise from ambient occlusion in the lightmap."); - public static readonly GUIContent PVRFilteringAtrousPositionSigmaDirect = EditorGUIUtility.TrTextContent("Direct Sigma", "Controls the threshold of the filter for direct light stored in the lightmap. A higher value will increase the threshold, reducing noise in the direct layer of the lightmap. Too high of a value can cause a loss of detail in the lightmap."); - public static readonly GUIContent PVRFilteringAtrousPositionSigmaIndirect = EditorGUIUtility.TrTextContent("Indirect Sigma", "Controls the threshold of the filter for indirect light stored in the lightmap. A higher value will increase the threshold, reducing noise in the indirect layer of the lightmap. Too high of a value can cause a loss of detail in the lightmap."); - public static readonly GUIContent PVRFilteringAtrousPositionSigmaAO = EditorGUIUtility.TrTextContent("Ambient Occlusion Sigma", "Controls the threshold of the filter for ambient occlusion stored in the lightmap. A higher value will increase the threshold, reducing noise in the ambient occlusion layer of the lightmap. Too high of a value can cause a loss of detail in the lightmap."); - public static readonly GUIContent PVRCulling = EditorGUIUtility.TrTextContent("Prioritize View", "Specifies whether the lightmapper should prioritize baking texels within the scene view. When disabled, objects outside the scene view will have the same priority as those in the scene view."); - } - } -} // namespace diff --git a/Editor/Mono/SceneModeWindows/LightingWindowLightingTab.cs b/Editor/Mono/SceneModeWindows/LightingWindowLightingTab.cs deleted file mode 100644 index 8ba97d79fc..0000000000 --- a/Editor/Mono/SceneModeWindows/LightingWindowLightingTab.cs +++ /dev/null @@ -1,189 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Collections; -using System.Linq; -using UnityEditor.AnimatedValues; -using UnityEditorInternal; -using UnityEngine; -using UnityEngineInternal; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class LightingWindowLightingTab - { - static class Styles - { - public static readonly GUIContent OtherSettings = EditorGUIUtility.TrTextContent("Other Settings"); - public static readonly GUIContent DebugSettings = EditorGUIUtility.TrTextContent("Debug Settings"); - public static readonly GUIContent LightProbeVisualization = EditorGUIUtility.TrTextContent("Light Probe Visualization"); - } - - Editor m_LightingEditor; - Editor m_FogEditor; - Editor m_OtherRenderingEditor; - bool m_ShowOtherSettings = true; - bool m_ShowDebugSettings = false; - bool m_ShowProbeDebugSettings = false; - bool m_ShouldUpdateStatistics = true; - const string kShowOtherSettings = "kShowOtherSettings"; - const string kShowDebugSettings = "kShowDebugSettings"; - const string kUpdateStatistics = "kUpdateStatistics"; - Object m_RenderSettings = null; - - LightingWindowBakeSettings m_BakeSettings; - - Object renderSettings - { - get - { - if (m_RenderSettings == null) - m_RenderSettings = RenderSettings.GetRenderSettings(); - - return m_RenderSettings; - } - } - - Editor lightingEditor - { - get - { - if (m_LightingEditor == null || m_LightingEditor.target == null) - { - Editor.CreateCachedEditor(renderSettings, typeof(LightingEditor), ref m_LightingEditor); - } - - return m_LightingEditor; - } - } - - Editor fogEditor - { - get - { - if (m_FogEditor == null || m_FogEditor.target == null) - { - Editor.CreateCachedEditor(renderSettings, typeof(FogEditor), ref m_FogEditor); - } - - return m_FogEditor; - } - } - - Editor otherRenderingEditor - { - get - { - if (m_OtherRenderingEditor == null || m_OtherRenderingEditor.target == null) - { - Editor.CreateCachedEditor(renderSettings, typeof(OtherRenderingEditor), ref m_OtherRenderingEditor); - } - - return m_OtherRenderingEditor; - } - } - - public void OnEnable() - { - m_BakeSettings = new LightingWindowBakeSettings(); - m_BakeSettings.OnEnable(); - - m_ShowOtherSettings = SessionState.GetBool(kShowOtherSettings, true); - m_ShowDebugSettings = SessionState.GetBool(kShowDebugSettings, false); - m_ShouldUpdateStatistics = SessionState.GetBool(kUpdateStatistics, false); - } - - public void OnDisable() - { - m_BakeSettings.OnDisable(); - - SessionState.SetBool(kShowOtherSettings, m_ShowOtherSettings); - SessionState.SetBool(kShowDebugSettings, m_ShowDebugSettings); - SessionState.SetBool(kUpdateStatistics, m_ShouldUpdateStatistics); - - ClearCachedProperties(); - } - - void ClearCachedProperties() - { - if (m_LightingEditor != null) - { - Object.DestroyImmediate(m_LightingEditor); - m_LightingEditor = null; - } - if (m_FogEditor != null) - { - Object.DestroyImmediate(m_FogEditor); - m_FogEditor = null; - } - if (m_OtherRenderingEditor != null) - { - Object.DestroyImmediate(m_OtherRenderingEditor); - m_OtherRenderingEditor = null; - } - } - - void DebugSettingsGUI() - { - m_ShowDebugSettings = EditorGUILayout.FoldoutTitlebar(m_ShowDebugSettings, Styles.DebugSettings, true); - - if (m_ShowDebugSettings) - { - EditorGUI.indentLevel++; - - m_ShowProbeDebugSettings = EditorGUILayout.Foldout(m_ShowProbeDebugSettings, Styles.LightProbeVisualization, true); - - if (m_ShowProbeDebugSettings) - { - EditorGUI.BeginChangeCheck(); - - EditorGUI.indentLevel++; - LightProbeVisualization.lightProbeVisualizationMode = (LightProbeVisualization.LightProbeVisualizationMode)EditorGUILayout.EnumPopup(LightProbeVisualization.lightProbeVisualizationMode); - LightProbeVisualization.showInterpolationWeights = EditorGUILayout.Toggle("Display Weights", LightProbeVisualization.showInterpolationWeights); - LightProbeVisualization.showOcclusions = EditorGUILayout.Toggle("Display Occlusion", LightProbeVisualization.showOcclusions); - EditorGUI.indentLevel--; - - if (EditorGUI.EndChangeCheck()) - EditorApplication.SetSceneRepaintDirty(); - } - EditorGUILayout.Space(); - - m_BakeSettings.DeveloperBuildSettingsGUI(); - - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - } - - void OtherSettingsGUI() - { - m_ShowOtherSettings = EditorGUILayout.FoldoutTitlebar(m_ShowOtherSettings, Styles.OtherSettings, true); - - if (m_ShowOtherSettings) - { - EditorGUI.indentLevel++; - - fogEditor.OnInspectorGUI(); - otherRenderingEditor.OnInspectorGUI(); - - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - } - - public void OnGUI() - { - EditorGUIUtility.hierarchyMode = true; - - lightingEditor.OnInspectorGUI(); - m_BakeSettings.OnGUI(); - - OtherSettingsGUI(); - DebugSettingsGUI(); - } - } -} // namespace diff --git a/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs b/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs deleted file mode 100644 index d04c392137..0000000000 --- a/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs +++ /dev/null @@ -1,568 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Collections; -using System.Linq; -using UnityEditor.AnimatedValues; -using UnityEditorInternal; -using UnityEngine; -using UnityEngineInternal; -using Object = UnityEngine.Object; - - -namespace UnityEditor -{ - internal class LightingWindowLightmapPreviewTab - { - const string kEditorPrefsGBuffersLightmapsAlbedoEmissive = "LightingWindowGlobalMapsGLAE"; - const string kEditorPrefsTransmissionTextures = "LightingWindowGlobalMapsTT"; - const string kEditorPrefsGeometryData = "LightingWindowGlobalMapsGD"; - const string kEditorPrefsInFlight = "LightingWindowGlobalMapsIF"; - - Vector2 m_ScrollPositionLightmaps = Vector2.zero; - Vector2 m_ScrollPositionMaps = Vector2.zero; - int m_SelectedLightmap = -1; - - static Styles s_Styles; - class Styles - { - public Styles() - { - boldFoldout.fontStyle = FontStyle.Bold; - } - - public GUIStyle selectedLightmapHighlight = "LightmapEditorSelectedHighlight"; - public GUIStyle boldFoldout = new GUIStyle(EditorStyles.foldout); - - public GUIContent LightProbes = EditorGUIUtility.TrTextContent("Light Probes", "A different LightProbes.asset can be assigned here. These assets are generated by baking a scene containing light probes."); - public 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."); - public GUIContent MapsArraySize = EditorGUIUtility.TrTextContent("Array Size", "The length of the array of lightmaps."); - } - - static void DrawHeader(Rect rect, bool showdrawDirectionalityHeader, bool showShadowMaskHeader, float maxLightmaps) - { - // we first needed to get the amount of space that the first texture would get - // as that's done now, let's request the rect for the header - rect.width = rect.width / maxLightmaps; - - // display the header - EditorGUI.DropShadowLabel(rect, "Intensity"); - rect.x += rect.width; - if (showdrawDirectionalityHeader) - { - EditorGUI.DropShadowLabel(rect, "Directionality"); - rect.x += rect.width; - } - - if (showShadowMaskHeader) - { - EditorGUI.DropShadowLabel(rect, "Shadowmask"); - } - } - - void MenuSelectLightmapUsers(Rect rect, int lightmapIndex) - { - if (Event.current.type == EventType.ContextClick && rect.Contains(Event.current.mousePosition)) - { - string[] menuText = { "Select Lightmap Users" }; - Rect r = new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 1, 1); - EditorUtility.DisplayCustomMenu(r, EditorGUIUtility.TempContent(menuText), -1, SelectLightmapUsers, lightmapIndex); - Event.current.Use(); - } - } - - void SelectLightmapUsers(object userData, string[] options, int selected) - { - int lightmapIndex = (int)userData; - ArrayList newSelection = new ArrayList(); - MeshRenderer[] renderers = Object.FindObjectsOfType(typeof(MeshRenderer)) as MeshRenderer[]; - foreach (MeshRenderer renderer in renderers) - { - if (renderer != null && renderer.lightmapIndex == lightmapIndex) - newSelection.Add(renderer.gameObject); - } - Terrain[] terrains = Object.FindObjectsOfType(typeof(Terrain)) as Terrain[]; - foreach (Terrain terrain in terrains) - { - if (terrain != null && terrain.lightmapIndex == lightmapIndex) - newSelection.Add(terrain.gameObject); - } - Selection.objects = newSelection.ToArray(typeof(Object)) as Object[]; - } - - public void LightmapPreview(Rect r) - { - if (s_Styles == null) - s_Styles = new Styles(); - - const float headerHeight = 20; - const float spacing = 10; - GUI.Box(r, "", "PreBackground"); - m_ScrollPositionLightmaps = EditorGUILayout.BeginScrollView(m_ScrollPositionLightmaps, GUILayout.Height(r.height)); - int lightmapIndex = 0; - bool haveDirectionalityLightMaps = false; - bool haveShadowMaskLightMaps = false; - - foreach (LightmapData li in LightmapSettings.lightmaps) - { - if (li.lightmapDir != null) haveDirectionalityLightMaps = true; - if (li.shadowMask != null) haveShadowMaskLightMaps = true; - } - - float maxLightmaps = 1.0f; - if (haveDirectionalityLightMaps) ++maxLightmaps; - if (haveShadowMaskLightMaps) ++maxLightmaps; - - // display the header - Rect headerRect = GUILayoutUtility.GetRect(r.width, r.width, headerHeight, headerHeight); - DrawHeader(headerRect, haveDirectionalityLightMaps, haveShadowMaskLightMaps, maxLightmaps); - - foreach (LightmapData li in LightmapSettings.lightmaps) - { - if (li.lightmapColor == null && li.lightmapDir == null && li.shadowMask == null) - { - lightmapIndex++; - continue; - } - - int lightmapColorMaxSize = li.lightmapColor ? Math.Max(li.lightmapColor.width, li.lightmapColor.height) : -1; - int lightmapDirMaxSize = li.lightmapDir ? Math.Max(li.lightmapDir.width, li.lightmapDir.height) : -1; - int lightMaskMaxSize = li.shadowMask ? Math.Max(li.shadowMask.width, li.shadowMask.height) : -1; - - Texture2D biggerLightmap; - if (lightmapColorMaxSize > lightmapDirMaxSize) - { - biggerLightmap = lightmapColorMaxSize > lightMaskMaxSize ? li.lightmapColor : li.shadowMask; - } - else - { - biggerLightmap = lightmapDirMaxSize > lightMaskMaxSize ? li.lightmapDir : li.shadowMask; - } - - // get rect for textures in this row - GUILayoutOption[] layout = { GUILayout.MaxWidth(r.width), GUILayout.MaxHeight(biggerLightmap.height)}; - Rect rect = GUILayoutUtility.GetAspectRect(maxLightmaps, layout); - - // display the textures - float rowSpacing = spacing * 0.5f; - rect.width /= maxLightmaps; - rect.width -= rowSpacing; - rect.x += rowSpacing / 2; - EditorGUI.DrawPreviewTexture(rect, li.lightmapColor); - MenuSelectLightmapUsers(rect, lightmapIndex); - - if (li.lightmapDir) - { - rect.x += rect.width + rowSpacing; - EditorGUI.DrawPreviewTexture(rect, li.lightmapDir); - MenuSelectLightmapUsers(rect, lightmapIndex); - } - if (li.shadowMask) - { - rect.x += rect.width + rowSpacing; - EditorGUI.DrawPreviewTexture(rect, li.shadowMask); - MenuSelectLightmapUsers(rect, lightmapIndex); - } - GUILayout.Space(spacing); - lightmapIndex++; - } - - EditorGUILayout.EndScrollView(); - } - - public void UpdateLightmapSelection() - { - MeshRenderer renderer; - Terrain terrain = null; - // if the active object in the selection is a renderer or a terrain, we're interested in it's lightmapIndex - if (Selection.activeGameObject == null || - ((renderer = Selection.activeGameObject.GetComponent()) == null && - (terrain = Selection.activeGameObject.GetComponent()) == null)) - { - m_SelectedLightmap = -1; - return; - } - m_SelectedLightmap = renderer != null ? renderer.lightmapIndex : terrain.lightmapIndex; - } - - enum GlobalMapsViewType - { - Performance, - Memory - } - - string SizeString(float size) - { - return size.ToString("0.0") + " MB"; - } - - float SumSizes(float[] sizes) - { - float sum = 0.0f; - foreach (var size in sizes) - sum += size; - - return sum; - } - - System.UInt64 SumCounts(System.UInt64[] counts) - { - System.UInt64 sum = 0; - foreach (var count in counts) - sum += count; - - return sum; - } - - enum Precision { Tenths, Hundredths } - - private void ShowObjectNamesSizesAndCounts(string foldoutName, string editorPrefsName, string[] objectNames, float[] sizes, System.UInt64[] counts, Precision precision) - { - Debug.Assert(objectNames.Length == sizes.Length); - - if (objectNames.Length == 0) - return; - - const bool toggleOnLabelClick = true; - string countString = counts.Length > 0 ? (SumCounts(counts).ToString() + " tris, ") : ""; - string sizeString = SizeString(SumSizes(sizes)); - string foldoutNameFull = foldoutName + " (" + countString + sizeString + ")"; - bool showDetailsOld = EditorPrefs.GetBool(editorPrefsName, true); - - bool showDetails = EditorGUILayout.Foldout(showDetailsOld, foldoutNameFull, toggleOnLabelClick, s_Styles.boldFoldout); - - if (showDetails != showDetailsOld) - EditorPrefs.SetBool(editorPrefsName, showDetails); - - if (!showDetails) - return; - - GUILayout.BeginHorizontal(); - { - string[] stringSeparators = new string[] { " | " }; - - GUILayout.Space(20); - - GUILayout.BeginVertical(); - for (int i = 0; i < objectNames.Length; ++i) - { - string fullName = objectNames[i]; - string[] result = fullName.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries); - Debug.Assert(result.Length > 0); - string objectName = result[0]; - string tooltip = ""; - if (result.Length > 1) - tooltip = result[1]; - - GUILayout.Label(new GUIContent(objectName, tooltip), EditorStyles.miniLabel); - } - GUILayout.EndVertical(); - - GUILayout.BeginVertical(); - for (int i = 0; i < counts.Length; ++i) - { - GUILayout.Label(counts[i].ToString(), EditorStyles.miniLabel); - } - GUILayout.EndVertical(); - - GUILayout.BeginVertical(); - string format = (precision == Precision.Tenths) ? "0.0" : "0.00"; - for (int i = 0; i < sizes.Length; ++i) - { - GUILayout.Label(sizes[i].ToString(format) + " MB", EditorStyles.miniLabel); - } - GUILayout.EndVertical(); - - GUILayout.FlexibleSpace(); - } - GUILayout.EndHorizontal(); - GUILayout.Space(10); - } - - public void Maps() - { - if (s_Styles == null) - s_Styles = new Styles(); - - GUI.changed = false; - - if (Lightmapping.giWorkflowMode == Lightmapping.GIWorkflowMode.OnDemand) - { - SerializedObject so = new SerializedObject(LightmapEditorSettings.GetLightmapSettings()); - SerializedProperty LightingDataAsset = so.FindProperty("m_LightingDataAsset"); - EditorGUILayout.PropertyField(LightingDataAsset, s_Styles.LightingDataAsset); - so.ApplyModifiedProperties(); - } - - GUILayout.Space(10); - - GlobalMapsViewType viewType = GlobalMapsViewType.Performance; - - if (EditorPrefs.GetBool("DeveloperMode", false)) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - viewType = (GlobalMapsViewType)EditorPrefs.GetInt("LightingWindowGlobalMapsViewType", (int)viewType); - - EditorGUI.BeginChangeCheck(); - { - viewType = (GlobalMapsViewType)GUILayout.Toolbar((int)viewType, new string[] { "Performance", "Memory" }, EditorStyles.miniButton, GUILayout.ExpandWidth(false)); - } - if (EditorGUI.EndChangeCheck()) - EditorPrefs.SetInt("LightingWindowGlobalMapsViewType", (int)viewType); - - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - } - - LightmapData[] lightmaps = LightmapSettings.lightmaps; - - m_ScrollPositionMaps = GUILayout.BeginScrollView(m_ScrollPositionMaps); - { - bool showDirLightmap = false; - bool showShadowMask = false; - foreach (LightmapData lightmapData in lightmaps) - { - if (lightmapData.lightmapDir != null) - showDirLightmap = true; - if (lightmapData.shadowMask != null) - showShadowMask = true; - } - - if (viewType == GlobalMapsViewType.Performance) - PerformanceCentricView(lightmaps, showDirLightmap, showShadowMask, viewType); - else - MemoryCentricView(lightmaps, showDirLightmap, showShadowMask, viewType); - } - GUILayout.EndScrollView(); - } - - void MemoryCentricView(LightmapData[] lightmaps, bool showDirLightmap, bool showShadowMask, GlobalMapsViewType viewType) - { - Lightmapping.ResetExplicitlyShownMemLabels(); - - Dictionary> gbufferHashToLightmapIndices = new Dictionary>(); - for (int i = 0; i < lightmaps.Length; i++) - { - Hash128 gbufferHash; - if (Lightmapping.GetGBufferHash(i, out gbufferHash)) - { - if (!gbufferHashToLightmapIndices.ContainsKey(gbufferHash)) - gbufferHashToLightmapIndices.Add(gbufferHash, new SortedList()); - - gbufferHashToLightmapIndices[gbufferHash].Add(i, i); - } - } - - float totalGBuffersSize = 0.0f; - float totalLightmapsSize = 0.0f; - float totalAlbedoEmissiveSize = 0.0f; - foreach (var entry in gbufferHashToLightmapIndices) - { - Hash128 gbufferHash = entry.Key; - float gbufferDataSize = Lightmapping.GetGBufferMemory(ref gbufferHash); - totalGBuffersSize += gbufferDataSize; - - SortedList lightmapIndices = entry.Value; - foreach (var i in lightmapIndices) - { - LightmapMemory lightmapMemory = Lightmapping.GetLightmapMemory(i.Value); - totalLightmapsSize += lightmapMemory.lightmapDataSize; - totalLightmapsSize += lightmapMemory.lightmapTexturesSize; - totalAlbedoEmissiveSize += lightmapMemory.albedoDataSize; - totalAlbedoEmissiveSize += lightmapMemory.albedoTextureSize; - totalAlbedoEmissiveSize += lightmapMemory.emissiveDataSize; - totalAlbedoEmissiveSize += lightmapMemory.emissiveTextureSize; - } - } - - if (gbufferHashToLightmapIndices.Count > 0) - { - const bool toggleOnLabelClick = true; - string foldoutNameFull = String.Format( - "G-buffers ({0}) | Lightmaps ({1}) | Albedo/Emissive ({2})", - SizeString(totalGBuffersSize), - SizeString(totalLightmapsSize), - SizeString(totalAlbedoEmissiveSize)); - bool showDetailsOld = EditorPrefs.GetBool(kEditorPrefsGBuffersLightmapsAlbedoEmissive, true); - - bool showDetails = EditorGUILayout.Foldout(showDetailsOld, foldoutNameFull, toggleOnLabelClick, s_Styles.boldFoldout); - - if (showDetails != showDetailsOld) - EditorPrefs.SetBool(kEditorPrefsGBuffersLightmapsAlbedoEmissive, showDetails); - - if (showDetails) - { - foreach (var entry in gbufferHashToLightmapIndices) - { - GUILayout.BeginHorizontal(); - { - GUILayout.Space(15); - GUILayout.BeginVertical(); - { - Hash128 gbufferHash = entry.Key; - float gbufferDataSize = Lightmapping.GetGBufferMemory(ref gbufferHash); - GUILayout.Label(EditorGUIUtility.TrTextContent("G-buffer: " + gbufferDataSize.ToString("0.0") + " MB", gbufferHash.ToString()), EditorStyles.miniLabel, GUILayout.ExpandWidth(false)); - - SortedList lightmapIndices = entry.Value; - foreach (var i in lightmapIndices) - { - LightmapRow(i.Value, lightmaps, showDirLightmap, showShadowMask, viewType); - } - } - GUILayout.EndVertical(); - } - GUILayout.EndHorizontal(); - GUILayout.Space(10); - } - } - } - - System.UInt64[] dummyCounts = new System.UInt64[0]; - { - string[] objectNames; - float[] sizes; - Lightmapping.GetTransmissionTexturesMemLabels(out objectNames, out sizes); - ShowObjectNamesSizesAndCounts("Transmission textures", kEditorPrefsTransmissionTextures, objectNames, sizes, dummyCounts, Precision.Tenths); - } - - { - string[] objectNames; - float[] sizes; - System.UInt64[] triCounts; - Lightmapping.GetGeometryMemory(out objectNames, out sizes, out triCounts); - ShowObjectNamesSizesAndCounts("Geometry data", kEditorPrefsGeometryData, objectNames, sizes, triCounts, Precision.Hundredths); - } - - { - string[] objectNames; - float[] sizes; - Lightmapping.GetNotShownMemLabels(out objectNames, out sizes); - string remainingEntriesFoldoutName = Lightmapping.isProgressiveLightmapperDone ? "Leaks" : "In-flight"; - ShowObjectNamesSizesAndCounts(remainingEntriesFoldoutName, kEditorPrefsInFlight, objectNames, sizes, dummyCounts, Precision.Tenths); - } - } - - void PerformanceCentricView(LightmapData[] lightmaps, bool showDirLightmap, bool showShadowMask, GlobalMapsViewType viewType) - { - for (int i = 0; i < lightmaps.Length; i++) - { - LightmapRow(i, lightmaps, showDirLightmap, showShadowMask, viewType); - } - } - - void LightmapRow(int index, LightmapData[] lightmaps, bool showDirLightmap, bool showShadowMask, GlobalMapsViewType viewType) - { - int statsLineCount = (viewType == GlobalMapsViewType.Performance) ? 5 : 7; - float lightmapFieldSize = - 2 * EditorStyles.miniLabel.margin.top + - (statsLineCount - 1) * Mathf.Max(EditorStyles.miniLabel.margin.top, EditorStyles.miniLabel.margin.bottom) + - 2 * EditorStyles.miniLabel.padding.top + - (statsLineCount - 1) * EditorStyles.miniLabel.padding.vertical + - (statsLineCount - 1) * EditorStyles.miniLabel.lineHeight + - EditorStyles.miniLabel.font.fontSize; - - GUILayout.Space(5); - - GUILayout.BeginHorizontal(); - - GUILayout.Space(20); - lightmaps[index].lightmapColor = LightmapField(lightmaps[index].lightmapColor, index, lightmapFieldSize); - - if (showDirLightmap) - { - GUILayout.Space(5); - lightmaps[index].lightmapDir = LightmapField(lightmaps[index].lightmapDir, index, lightmapFieldSize); - } - - if (showShadowMask) - { - GUILayout.Space(5); - lightmaps[index].shadowMask = LightmapField(lightmaps[index].shadowMask, index, lightmapFieldSize); - } - - GUILayout.Space(5); - if (viewType == GlobalMapsViewType.Performance) - LightmapPerformanceStats(index); - else - LightmapMemoryStats(index); - - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - } - - Texture2D LightmapField(Texture2D lightmap, int index, float size) - { - Rect rect = GUILayoutUtility.GetRect(size, size, EditorStyles.objectField); - - MenuSelectLightmapUsers(rect, index); - Texture2D retval = null; - using (new EditorGUI.DisabledScope(true)) - { - retval = EditorGUI.ObjectField(rect, lightmap, typeof(Texture2D), false) as Texture2D; - } - if (index == m_SelectedLightmap && Event.current.type == EventType.Repaint) - s_Styles.selectedLightmapHighlight.Draw(rect, false, false, false, false); - - return retval; - } - - void LightmapPerformanceStats(int index) - { - GUILayout.BeginVertical(); - - GUILayout.Label("Index: " + index, EditorStyles.miniLabel); - - LightmapConvergence lc = Lightmapping.GetLightmapConvergence(index); - if (lc.IsValid()) - { - GUILayout.Label("Occupied: " + InternalEditorUtility.CountToString((ulong)lc.occupiedTexelCount), EditorStyles.miniLabel); - - GUIContent direct = EditorGUIUtility.TrTextContent("Direct: " + lc.minDirectSamples + " / " + lc.maxDirectSamples + " / " + lc.avgDirectSamples + "", "min / max / avg samples per texel"); - GUILayout.Label(direct, EditorStyles.miniLabel); - - GUIContent gi = EditorGUIUtility.TrTextContent("GI: " + lc.minGISamples + " / " + lc.maxGISamples + " / " + lc.avgGISamples + "", "min / max / avg samples per texel"); - GUILayout.Label(gi, EditorStyles.miniLabel); - } - else - { - GUILayout.Label("Occupied: N/A", EditorStyles.miniLabel); - GUILayout.Label("Direct: N/A", EditorStyles.miniLabel); - GUILayout.Label("GI: N/A", EditorStyles.miniLabel); - } - float mraysPerSec = Lightmapping.GetLightmapBakePerformance(index); - if (mraysPerSec >= 0.0) - GUILayout.Label(mraysPerSec.ToString("0.00") + " mrays/sec", EditorStyles.miniLabel); - else - GUILayout.Label("N/A mrays/sec", EditorStyles.miniLabel); - - GUILayout.EndVertical(); - } - - void LightmapMemoryStats(int index) - { - GUILayout.BeginVertical(); - - GUILayout.Label("Index: " + index, EditorStyles.miniLabel); - - LightmapMemory lightmapMemory = Lightmapping.GetLightmapMemory(index); - GUILayout.Label("Lightmap data: " + lightmapMemory.lightmapDataSize.ToString("0.0") + " MB", EditorStyles.miniLabel); - GUIContent lightmapTexturesSizeContent = null; - if (lightmapMemory.lightmapTexturesSize > 0.0f) - lightmapTexturesSizeContent = EditorGUIUtility.TrTextContent("Lightmap textures: " + SizeString(lightmapMemory.lightmapTexturesSize)); - else - lightmapTexturesSizeContent = EditorGUIUtility.TrTextContent("Lightmap textures: N/A", "This lightmap has converged and is not owned by the Progressive Lightmapper anymore."); - GUILayout.Label(lightmapTexturesSizeContent, EditorStyles.miniLabel); - GUILayout.Label("Albedo data: " + lightmapMemory.albedoDataSize.ToString("0.0") + " MB", EditorStyles.miniLabel); - GUILayout.Label("Albedo texture: " + lightmapMemory.albedoTextureSize.ToString("0.0") + " MB", EditorStyles.miniLabel); - GUILayout.Label("Emissive data: " + lightmapMemory.emissiveDataSize.ToString("0.0") + " MB", EditorStyles.miniLabel); - GUILayout.Label("Emissive texture: " + lightmapMemory.emissiveTextureSize.ToString("0.0") + " MB", EditorStyles.miniLabel); - - GUILayout.EndVertical(); - } - } -} // namespace diff --git a/Editor/Mono/SceneModeWindows/LightingWindowObjectTab.cs b/Editor/Mono/SceneModeWindows/LightingWindowObjectTab.cs deleted file mode 100644 index 5cfb6b10e5..0000000000 --- a/Editor/Mono/SceneModeWindows/LightingWindowObjectTab.cs +++ /dev/null @@ -1,299 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Collections; -using System.Linq; -using UnityEditor.AnimatedValues; -using UnityEditorInternal; -using UnityEngine; -using UnityEngineInternal; -using Object = UnityEngine.Object; - - -namespace UnityEditor -{ - internal class LightingWindowObjectTab - { - class Styles - { - public static readonly GUIContent[] ObjectPreviewTextureOptions = - { - EditorGUIUtility.TrTextContent("UV Charts"), - EditorGUIUtility.TrTextContent("Realtime Albedo"), - EditorGUIUtility.TrTextContent("Realtime Emissive"), - EditorGUIUtility.TrTextContent("Realtime Indirect"), - EditorGUIUtility.TrTextContent("Realtime Directionality"), - EditorGUIUtility.TrTextContent("Baked Lightmap"), - EditorGUIUtility.TrTextContent("Baked Directionality"), - EditorGUIUtility.TrTextContent("Baked Shadowmask"), - EditorGUIUtility.TrTextContent("Baked Albedo"), - EditorGUIUtility.TrTextContent("Baked Emissive"), - EditorGUIUtility.TrTextContent("Baked UV Charts"), - EditorGUIUtility.TrTextContent("Baked Texel Validity"), - EditorGUIUtility.TrTextContent("Baked UV Overlap"), - }; - - public static readonly GUIContent TextureNotAvailableRealtime = EditorGUIUtility.TrTextContent("The texture is not available at the moment."); - public static readonly GUIContent TextureNotAvailableBaked = EditorGUIUtility.TrTextContent("The texture is not available at the moment.\nPlease try to rebake the current scene or turn on Auto, and make sure that this object is set to Lightmap Static if it's meant to be baked."); - 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 Lightmap Static."); - public static readonly GUIContent TextureLoading = EditorGUIUtility.TrTextContent("Loading..."); - } - - GITextureType[] kObjectPreviewTextureTypes = - { - GITextureType.Charting, - GITextureType.Albedo, - GITextureType.Emissive, - GITextureType.Irradiance, - GITextureType.Directionality, - GITextureType.Baked, - GITextureType.BakedDirectional, - GITextureType.BakedShadowMask, - GITextureType.BakedAlbedo, - GITextureType.BakedEmissive, - GITextureType.BakedCharting, - GITextureType.BakedTexelValidity, - GITextureType.BakedUVOverlap - }; - - ZoomableArea m_ZoomablePreview; - GUIContent m_SelectedObjectPreviewTexture; - int m_PreviousSelection; - AnimBool m_ShowClampedSize = new AnimBool(); - - VisualisationGITexture m_CachedTexture; - - public void OnEnable(EditorWindow window) - { - m_ShowClampedSize.value = false; - m_ShowClampedSize.valueChanged.AddListener(window.Repaint); - } - - public void OnDisable() {} - - public void ObjectPreview(Rect r) - { - if (r.height <= 0) - return; - - if (m_ZoomablePreview == null) - { - m_ZoomablePreview = new ZoomableArea(true); - - m_ZoomablePreview.hRangeMin = 0.0f; - m_ZoomablePreview.vRangeMin = 0.0f; - - m_ZoomablePreview.hRangeMax = 1.0f; - m_ZoomablePreview.vRangeMax = 1.0f; - - m_ZoomablePreview.SetShownHRange(0, 1); - m_ZoomablePreview.SetShownVRange(0, 1); - - m_ZoomablePreview.uniformScale = true; - m_ZoomablePreview.scaleWithWindow = true; - } - - // Draw background - GUI.Box(r, "", "PreBackground"); - - // Top menu rect - Rect menuRect = new Rect(r); - menuRect.y += 1; - menuRect.height = 18; - GUI.Box(menuRect, "", EditorStyles.toolbar); - - // Top menu dropdown - Rect dropRect = new Rect(r); - dropRect.y += 1; - dropRect.height = 18; - dropRect.width = 120; - - // Drawable area - Rect drawableArea = new Rect(r); - drawableArea.yMin += dropRect.height; - drawableArea.yMax -= 14; - drawableArea.width -= 11; - - int index = Array.IndexOf(Styles.ObjectPreviewTextureOptions, m_SelectedObjectPreviewTexture); - - if (index < 0 || !LightmapVisualizationUtility.IsTextureTypeEnabled(kObjectPreviewTextureTypes[index])) - { - index = 0; - m_SelectedObjectPreviewTexture = Styles.ObjectPreviewTextureOptions[index]; - } - - if (EditorGUI.DropdownButton(dropRect, m_SelectedObjectPreviewTexture, FocusType.Passive, EditorStyles.toolbarPopup)) - { - GenericMenu menu = new GenericMenu(); - - for (int i = 0; i < Styles.ObjectPreviewTextureOptions.Length; i++) - { - if (LightmapVisualizationUtility.IsTextureTypeEnabled(kObjectPreviewTextureTypes[i])) - menu.AddItem(Styles.ObjectPreviewTextureOptions[i], index == i, SelectPreviewTextureOption, Styles.ObjectPreviewTextureOptions.ElementAt(i)); - else - menu.AddDisabledItem(Styles.ObjectPreviewTextureOptions.ElementAt(i)); - } - menu.DropDown(dropRect); - } - - GITextureType textureType = kObjectPreviewTextureTypes[Array.IndexOf(Styles.ObjectPreviewTextureOptions, m_SelectedObjectPreviewTexture)]; - - if (m_CachedTexture.type != textureType || m_CachedTexture.contentHash != LightmapVisualizationUtility.GetSelectedObjectGITextureHash(textureType) || m_CachedTexture.contentHash == new Hash128()) - { - m_CachedTexture = LightmapVisualizationUtility.GetSelectedObjectGITexture(textureType); - } - - if (m_CachedTexture.textureAvailability == GITextureAvailability.GITextureNotAvailable || m_CachedTexture.textureAvailability == GITextureAvailability.GITextureUnknown) - { - if (LightmapVisualizationUtility.IsBakedTextureType(textureType)) - { - if (textureType == GITextureType.BakedShadowMask) - GUI.Label(drawableArea, Styles.TextureNotAvailableBakedShadowmask); - else - GUI.Label(drawableArea, Styles.TextureNotAvailableBaked); - } - else - GUI.Label(drawableArea, Styles.TextureNotAvailableRealtime); - - return; - } - - if (m_CachedTexture.textureAvailability == GITextureAvailability.GITextureLoading && m_CachedTexture.texture == null) - { - GUI.Label(drawableArea, Styles.TextureLoading); - - return; - } - - LightmapType lightmapType = LightmapVisualizationUtility.GetLightmapType(textureType); - - // Framing and drawing - var evt = Event.current; - switch (evt.type) - { - // 'F' will zoom to uv bounds - case EventType.ValidateCommand: - case EventType.ExecuteCommand: - - if (Event.current.commandName == EventCommandNames.FrameSelected) - { - Vector4 lightmapTilingOffset = LightmapVisualizationUtility.GetLightmapTilingOffset(lightmapType); - - Vector2 min = new Vector2(lightmapTilingOffset.z, lightmapTilingOffset.w); - Vector2 max = min + new Vector2(lightmapTilingOffset.x, lightmapTilingOffset.y); - - min = Vector2.Max(min, Vector2.zero); - max = Vector2.Min(max, Vector2.one); - - float swap = 1f - min.y; - min.y = 1f - max.y; - max.y = swap; - - // Make sure that the focus rectangle is a even square - Rect rect = new Rect(min.x, min.y, max.x - min.x, max.y - min.y); - rect.x -= Mathf.Clamp(rect.height - rect.width, 0, float.MaxValue) / 2; - rect.y -= Mathf.Clamp(rect.width - rect.height, 0, float.MaxValue) / 2; - rect.width = rect.height = Mathf.Max(rect.width, rect.height); - - m_ZoomablePreview.shownArea = rect; - Event.current.Use(); - } - break; - - // Scale and draw texture and uv's - case EventType.Repaint: - - Texture2D texture = m_CachedTexture.texture; - if (texture && Event.current.type == EventType.Repaint) - { - Rect textureRect = new Rect(0, 0, texture.width, texture.height); - textureRect = ResizeRectToFit(textureRect, drawableArea); - //textureRect.x = -textureRect.width / 2; - //textureRect.y = -textureRect.height / 2; - textureRect = CenterToRect(textureRect, drawableArea); - textureRect = ScaleRectByZoomableArea(textureRect, m_ZoomablePreview); - - // Draw texture and UV - Rect uvRect = new Rect(textureRect); - uvRect.x += 3; - uvRect.y += drawableArea.y + 20; - - Rect clipRect = new Rect(drawableArea); - clipRect.y += dropRect.height + 3; - - // fix 635838 - We need to offset the rects for rendering. - { - float offset = clipRect.y - 14; - uvRect.y -= offset; - clipRect.y -= offset; - } - - // Texture shouldn't be filtered since it will make previewing really blurry - FilterMode prevMode = texture.filterMode; - texture.filterMode = FilterMode.Point; - - LightmapVisualizationUtility.DrawTextureWithUVOverlay(texture, Selection.activeGameObject, clipRect, uvRect, textureType); - texture.filterMode = prevMode; - } - break; - } - - // Reset zoom if selection is changed - if (m_PreviousSelection != Selection.activeInstanceID) - { - m_PreviousSelection = Selection.activeInstanceID; - m_ZoomablePreview.SetShownHRange(0, 1); - m_ZoomablePreview.SetShownVRange(0, 1); - } - - // Handle zoomable area - Rect zoomRect = new Rect(r); - zoomRect.yMin += dropRect.height; - m_ZoomablePreview.rect = zoomRect; - - m_ZoomablePreview.BeginViewGUI(); - m_ZoomablePreview.EndViewGUI(); - - GUILayoutUtility.GetRect(r.width, r.height); - } - - private void SelectPreviewTextureOption(object textureOption) - { - m_SelectedObjectPreviewTexture = (GUIContent)textureOption; - } - - Rect ResizeRectToFit(Rect rect, Rect to) - { - float widthScale = to.width / rect.width; - float heightScale = to.height / rect.height; - float scale = Mathf.Min(widthScale, heightScale); - - float width = (int)Mathf.Round((rect.width * scale)); - float height = (int)Mathf.Round((rect.height * scale)); - - return new Rect(rect.x, rect.y, width, height); - } - - Rect CenterToRect(Rect rect, Rect to) - { - float x = Mathf.Clamp((int)(to.width - rect.width) / 2f, 0, int.MaxValue); - float y = Mathf.Clamp((int)(to.height - rect.height) / 2f, 0, int.MaxValue); - - return new Rect(rect.x + x, rect.y + y, rect.width, rect.height); - } - - Rect ScaleRectByZoomableArea(Rect rect, ZoomableArea zoomableArea) - { - float x = -(zoomableArea.shownArea.x / zoomableArea.shownArea.width) * rect.width; - float y = ((zoomableArea.shownArea.y - (1f - zoomableArea.shownArea.height)) / zoomableArea.shownArea.height) * rect.height; - - float width = rect.width / zoomableArea.shownArea.width; - float height = rect.height / zoomableArea.shownArea.height; - - return new Rect(rect.x + x, rect.y + y, width, height); - } - } -} // namespace diff --git a/Editor/Mono/SceneModeWindows/NavigationWindow.cs b/Editor/Mono/SceneModeWindows/NavigationWindow.cs deleted file mode 100644 index 9c5df147dd..0000000000 --- a/Editor/Mono/SceneModeWindows/NavigationWindow.cs +++ /dev/null @@ -1,1045 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.AI; -using UnityEditor.AI; -using UnityEditorInternal; -using EditorNavMeshBuilder = UnityEditor.AI.NavMeshBuilder; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Navigation", icon = "Navigation")] - internal class NavMeshEditorWindow : EditorWindow, IHasCustomMenu - { - private static NavMeshEditorWindow s_NavMeshEditorWindow; - - // Scene based bake configuration - private SerializedObject m_SettingsObject; - private SerializedProperty m_AgentRadius; - private SerializedProperty m_AgentHeight; - private SerializedProperty m_AgentSlope; - private SerializedProperty m_AgentClimb; - private SerializedProperty m_LedgeDropHeight; - private SerializedProperty m_MaxJumpAcrossDistance; - - // .. advanced - private SerializedProperty m_MinRegionArea; - private SerializedProperty m_ManualCellSize; - private SerializedProperty m_CellSize; - private SerializedProperty m_AccuratePlacement; - - // Project based configuration - private SerializedObject m_NavMeshProjectSettingsObject; - private SerializedProperty m_Areas; - - private SerializedProperty m_Agents; - private SerializedProperty m_SettingNames; - - private const string kRootPath = "m_BuildSettings."; - - static Styles s_Styles; - - private Vector2 m_ScrollPos = Vector2.zero; - private int m_SelectedNavMeshAgentCount = 0; - private int m_SelectedNavMeshObstacleCount = 0; - private bool m_Advanced; - private bool m_HasPendingAgentDebugInfo = false; - private bool m_HasRepaintedForPendingAgentDebugInfo = false; - - private ReorderableList m_AreasList = null; - private ReorderableList m_AgentsList = null; - - enum Mode - { - AgentSettings = 0, - AreaSettings = 1, - SceneBakeSettings = 2, - ObjectSettings = 3 - } - - Mode m_Mode = Mode.ObjectSettings; - bool m_BecameVisibleCalled = false; - - private class Styles - { - public readonly GUIContent m_AgentRadiusContent = EditorGUIUtility.TrTextContent("Agent Radius", "How close to the walls navigation mesh exist."); - public readonly GUIContent m_AgentHeightContent = EditorGUIUtility.TrTextContent("Agent Height", "How much vertical clearance space must exist."); - public readonly GUIContent m_AgentSlopeContent = EditorGUIUtility.TrTextContent("Max Slope", "Maximum slope the agent can walk up."); - public readonly GUIContent m_AgentDropContent = EditorGUIUtility.TrTextContent("Drop Height", "Maximum agent drop height."); - public readonly GUIContent m_AgentClimbContent = EditorGUIUtility.TrTextContent("Step Height", "The height of discontinuities in the level the agent can climb over (i.e. steps and stairs)."); - public readonly GUIContent m_AgentJumpContent = EditorGUIUtility.TrTextContent("Jump Distance", "Maximum agent jump distance."); - public readonly GUIContent m_AgentPlacementContent = EditorGUIUtility.TrTextContent("Height Mesh", "Generate an accurate height mesh for precise agent placement (slower)."); - public readonly GUIContent m_MinRegionAreaContent = EditorGUIUtility.TrTextContent("Min Region Area", "Minimum area that a navmesh region can be."); - public readonly GUIContent m_ManualCellSizeContent = EditorGUIUtility.TrTextContent("Manual Voxel Size", "Enable to set voxel size manually."); - public readonly GUIContent m_CellSizeContent = EditorGUIUtility.TrTextContent("Voxel Size", "Specifies at the voxelization resolution at which the NavMesh is build."); - public readonly GUIContent m_LearnAboutComponent = EditorGUIUtility.TrTextContent("Learn instead about the component workflow.", "Components available for building and using navmesh data for different agent types."); - - public readonly GUIContent m_AgentSizeHeader = EditorGUIUtility.TrTextContent("Baked Agent Size"); - public readonly GUIContent m_OffmeshHeader = EditorGUIUtility.TrTextContent("Generated Off Mesh Links"); - public readonly GUIContent m_AdvancedHeader = EditorGUIUtility.TrTextContent("Advanced"); - public readonly GUIContent m_AgentTypesHeader = EditorGUIUtility.TrTextContent("Agent Types"); - - public readonly GUIContent m_NameLabel = EditorGUIUtility.TrTextContent("Name"); - public readonly GUIContent m_CostLabel = EditorGUIUtility.TrTextContent("Cost"); - - public readonly GUIContent[] m_ModeToggles = - { - EditorGUIUtility.TrTextContent("Agents", "Navmesh agent settings."), - EditorGUIUtility.TrTextContent("Areas", "Navmesh area settings."), - EditorGUIUtility.TrTextContent("Bake", "Navmesh bake settings."), - EditorGUIUtility.TrTextContent("Object", "Bake settings for the currently selected object."), - }; - }; - - [MenuItem("Window/Navigation", false, 2100)] - public static void SetupWindow() - { - var window = GetWindow(typeof(InspectorWindow)); - window.minSize = new Vector2(300, 360); - } - - public static void OpenAreaSettings() - { - SetupWindow(); - if (s_NavMeshEditorWindow == null) - return; - - s_NavMeshEditorWindow.m_Mode = Mode.AreaSettings; - s_NavMeshEditorWindow.InitProjectSettings(); - s_NavMeshEditorWindow.InitAgents(); - } - - public static void OpenAgentSettings(int agentTypeID) - { - SetupWindow(); - if (s_NavMeshEditorWindow == null) - return; - - s_NavMeshEditorWindow.m_Mode = Mode.AgentSettings; - s_NavMeshEditorWindow.InitProjectSettings(); - s_NavMeshEditorWindow.InitAgents(); - - s_NavMeshEditorWindow.m_AgentsList.index = -1; - for (int i = 0; i < s_NavMeshEditorWindow.m_Agents.arraySize; i++) - { - SerializedProperty agent = s_NavMeshEditorWindow.m_Agents.GetArrayElementAtIndex(i); - SerializedProperty idProp = agent.FindPropertyRelative("agentTypeID"); - if (idProp.intValue == agentTypeID) - { - s_NavMeshEditorWindow.m_AgentsList.index = i; - break; - } - } - } - - public void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - s_NavMeshEditorWindow = this; - EditorApplication.searchChanged += Repaint; - SceneView.onSceneGUIDelegate += OnSceneViewGUI; - - UpdateSelectedAgentAndObstacleState(); - - Repaint(); - } - - private void InitProjectSettings() - { - if (m_NavMeshProjectSettingsObject == null) - { - Object obj = Unsupported.GetSerializedAssetInterfaceSingleton("NavMeshProjectSettings"); - m_NavMeshProjectSettingsObject = new SerializedObject(obj); - } - } - - private void InitSceneBakeSettings() - { - // Scene based agent bake settings - m_SettingsObject = new SerializedObject(EditorNavMeshBuilder.navMeshSettingsObject); - - m_AgentRadius = m_SettingsObject.FindProperty(kRootPath + "agentRadius"); - m_AgentHeight = m_SettingsObject.FindProperty(kRootPath + "agentHeight"); - m_AgentSlope = m_SettingsObject.FindProperty(kRootPath + "agentSlope"); - m_LedgeDropHeight = m_SettingsObject.FindProperty(kRootPath + "ledgeDropHeight"); - m_AgentClimb = m_SettingsObject.FindProperty(kRootPath + "agentClimb"); - m_MaxJumpAcrossDistance = m_SettingsObject.FindProperty(kRootPath + "maxJumpAcrossDistance"); - - //Advanced Settings - m_MinRegionArea = m_SettingsObject.FindProperty(kRootPath + "minRegionArea"); - m_ManualCellSize = m_SettingsObject.FindProperty(kRootPath + "manualCellSize"); - m_CellSize = m_SettingsObject.FindProperty(kRootPath + "cellSize"); - m_AccuratePlacement = m_SettingsObject.FindProperty(kRootPath + "accuratePlacement"); - } - - private void InitAreas() - { - if (m_Areas == null) - { - m_Areas = m_NavMeshProjectSettingsObject.FindProperty("areas"); - } - if (m_AreasList == null) - { - m_AreasList = new ReorderableList(m_NavMeshProjectSettingsObject, m_Areas, false, false, false, false); - m_AreasList.drawElementCallback = DrawAreaListElement; - m_AreasList.drawHeaderCallback = DrawAreaListHeader; - m_AreasList.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - } - } - - private void InitAgents() - { - if (m_Agents == null) - { - m_Agents = m_NavMeshProjectSettingsObject.FindProperty("m_Settings"); - m_SettingNames = m_NavMeshProjectSettingsObject.FindProperty("m_SettingNames"); - } - if (m_AgentsList == null) - { - m_AgentsList = new ReorderableList(m_NavMeshProjectSettingsObject, m_Agents, false, false, true, true); - m_AgentsList.drawElementCallback = DrawAgentListElement; - m_AgentsList.drawHeaderCallback = DrawAgentListHeader; - m_AgentsList.onAddCallback = AddAgent; - m_AgentsList.onRemoveCallback = RemoveAgent; - m_AgentsList.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - } - } - - // This code is replicated from the navmesh debug draw code. - private int Bit(int a, int b) - { - return (a & (1 << b)) >> b; - } - - private Color GetAreaColor(int i) - { - if (i == 0) - return new Color(0, 0.75f, 1.0f, 0.5f); - int r = (Bit(i, 4) + Bit(i, 1) * 2 + 1) * 63; - int g = (Bit(i, 3) + Bit(i, 2) * 2 + 1) * 63; - int b = (Bit(i, 5) + Bit(i, 0) * 2 + 1) * 63; - return new Color((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, 0.5f); - } - - public void OnDisable() - { - s_NavMeshEditorWindow = null; - EditorApplication.searchChanged -= Repaint; - SceneView.onSceneGUIDelegate -= OnSceneViewGUI; - } - - void UpdateSelectedAgentAndObstacleState() - { - Object[] selectedAgents = Selection.GetFiltered(typeof(NavMeshAgent), SelectionMode.ExcludePrefab | SelectionMode.Editable); - Object[] selectedObstacles = Selection.GetFiltered(typeof(NavMeshObstacle), SelectionMode.ExcludePrefab | SelectionMode.Editable); - m_SelectedNavMeshAgentCount = selectedAgents.Length; - m_SelectedNavMeshObstacleCount = selectedObstacles.Length; - } - - void OnSelectionChange() - { - UpdateSelectedAgentAndObstacleState(); - m_ScrollPos = Vector2.zero; - if (m_Mode == Mode.ObjectSettings) - Repaint(); - } - - void ModeToggle() - { - if (s_Styles == null) - s_Styles = new Styles(); - - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - m_Mode = (Mode)GUILayout.Toolbar((int)m_Mode, s_Styles.m_ModeToggles, "LargeButton", GUI.ToolbarButtonSize.FitToContents); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - } - - private void GetAreaListRects(Rect rect, out Rect stripeRect, out Rect labelRect, out Rect nameRect, out Rect costRect) - { - float stripeWidth = EditorGUIUtility.singleLineHeight * 0.8f; - float labelWidth = EditorGUIUtility.singleLineHeight * 5; - float costWidth = EditorGUIUtility.singleLineHeight * 4; - float nameWidth = rect.width - stripeWidth - labelWidth - costWidth; - float x = rect.x; - stripeRect = new Rect(x, rect.y, stripeWidth - 4, rect.height); - x += stripeWidth; - labelRect = new Rect(x, rect.y, labelWidth - 4, rect.height); - x += labelWidth; - nameRect = new Rect(x, rect.y, nameWidth - 4, rect.height); - x += nameWidth; - costRect = new Rect(x, rect.y, costWidth, rect.height); - } - - private void DrawAreaListHeader(Rect rect) - { - Rect stripeRect, labelRect, nameRect, costRect; - GetAreaListRects(rect, out stripeRect, out labelRect, out nameRect, out costRect); - GUI.Label(nameRect, s_Styles.m_NameLabel); - GUI.Label(costRect, s_Styles.m_CostLabel); - } - - private void DrawAreaListElement(Rect rect, int index, bool selected, bool focused) - { - SerializedProperty areaProp = m_Areas.GetArrayElementAtIndex(index); - if (areaProp == null) - return; - SerializedProperty nameProp = areaProp.FindPropertyRelative("name"); - SerializedProperty costProp = areaProp.FindPropertyRelative("cost"); - if (nameProp == null || costProp == null) - return; - - rect.height -= 2; // nicer looking with selected list row and a text field in it - - bool builtInLayer = false; - bool allowChangeName = true; - bool allowChangeCost = true; - switch (index) - { - case 0: // Default - builtInLayer = true; - allowChangeName = false; - allowChangeCost = true; - break; - case 1: // NonWalkable - builtInLayer = true; - allowChangeName = false; - allowChangeCost = false; - break; - case 2: // Jump - builtInLayer = true; - allowChangeName = false; - allowChangeCost = true; - break; - default: - builtInLayer = false; - allowChangeName = true; - allowChangeCost = true; - break; - } - - Rect stripeRect, labelRect, nameRect, costRect; - GetAreaListRects(rect, out stripeRect, out labelRect, out nameRect, out costRect); - - bool oldEnabled = GUI.enabled; - Color color = GetAreaColor(index); - Color dimmed = new Color(color.r * 0.1f, color.g * 0.1f, color.b * 0.1f, 0.6f); - EditorGUI.DrawRect(stripeRect, color); - - EditorGUI.DrawRect(new Rect(stripeRect.x, stripeRect.y, 1, stripeRect.height), dimmed); - EditorGUI.DrawRect(new Rect(stripeRect.x + stripeRect.width - 1, stripeRect.y, 1, stripeRect.height), dimmed); - EditorGUI.DrawRect(new Rect(stripeRect.x + 1, stripeRect.y, stripeRect.width - 2, 1), dimmed); - EditorGUI.DrawRect(new Rect(stripeRect.x + 1, stripeRect.y + stripeRect.height - 1, stripeRect.width - 2, 1), dimmed); - - if (builtInLayer) - GUI.Label(labelRect, EditorGUIUtility.TempContent("Built-in " + index)); - else - GUI.Label(labelRect, EditorGUIUtility.TempContent("User " + index)); - - int oldIndent = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; - - GUI.enabled = oldEnabled && allowChangeName; - EditorGUI.PropertyField(nameRect, nameProp, GUIContent.none); - - GUI.enabled = oldEnabled && allowChangeCost; - EditorGUI.PropertyField(costRect, costProp, GUIContent.none); - - GUI.enabled = oldEnabled; - - EditorGUI.indentLevel = oldIndent; - } - - private void AddAgent(ReorderableList list) - { - UnityEngine.AI.NavMesh.CreateSettings(); - list.index = UnityEngine.AI.NavMesh.GetSettingsCount() - 1; - } - - private void RemoveAgent(ReorderableList list) - { - SerializedProperty agentProp = m_Agents.GetArrayElementAtIndex(list.index); - if (agentProp == null) - return; - SerializedProperty idProp = agentProp.FindPropertyRelative("agentTypeID"); - if (idProp == null) - return; - // Cannot delete default. - if (idProp.intValue == 0) - return; - - m_SettingNames.DeleteArrayElementAtIndex(list.index); - ReorderableList.defaultBehaviours.DoRemoveButton(list); - } - - private void DrawAgentListHeader(Rect rect) - { - GUI.Label(rect, s_Styles.m_AgentTypesHeader); - } - - private void DrawAgentListElement(Rect rect, int index, bool selected, bool focused) - { - SerializedProperty agentProp = m_Agents.GetArrayElementAtIndex(index); - if (agentProp == null) - return; - SerializedProperty idProp = agentProp.FindPropertyRelative("agentTypeID"); - if (idProp == null) - return; - - rect.height -= 2; // nicer looking with selected list row and a text field in it - - bool isDefault = idProp.intValue == 0; - using (new EditorGUI.DisabledScope(isDefault)) - { - var sname = UnityEngine.AI.NavMesh.GetSettingsNameFromID(idProp.intValue); - GUI.Label(rect, EditorGUIUtility.TempContent(sname)); - } - } - - public void OnGUI() - { - EditorGUILayout.Space(); - ModeToggle(); - EditorGUILayout.Space(); - - InitProjectSettings(); - - m_ScrollPos = EditorGUILayout.BeginScrollView(m_ScrollPos); - switch (m_Mode) - { - case Mode.ObjectSettings: - ObjectSettings(); - break; - case Mode.SceneBakeSettings: - SceneBakeSettings(); - break; - case Mode.AreaSettings: - AreaSettings(); - break; - case Mode.AgentSettings: - AgentSettings(); - break; - } - EditorGUILayout.EndScrollView(); - } - - public void OnBecameVisible() - { - // Make sure OnBecameVisible/OnBecameInvisible pair is called correctly. - if (m_BecameVisibleCalled) - return; - var shouldRepaint = NavMeshVisualizationSettings.showNavigation == 0; - NavMeshVisualizationSettings.showNavigation++; - if (shouldRepaint) - RepaintSceneAndGameViews(); - m_BecameVisibleCalled = true; - } - - public void OnBecameInvisible() - { - if (!m_BecameVisibleCalled) - return; - NavMeshVisualizationSettings.showNavigation--; - RepaintSceneAndGameViews(); - m_BecameVisibleCalled = false; - } - - static void RepaintSceneAndGameViews() - { - SceneView.RepaintAll(); - foreach (GameView gv in Resources.FindObjectsOfTypeAll(typeof(GameView))) - gv.Repaint(); - } - - public void OnSceneViewGUI(SceneView sceneView) - { - if (NavMeshVisualizationSettings.showNavigation == 0) - return; - - SceneViewOverlay.Window(EditorGUIUtility.TrTextContent("Navmesh Display"), DisplayControls, (int)SceneViewOverlay.Ordering.NavMesh, SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget); - - // Display Agent display only if there are selected NavMeshAgents. - if (m_SelectedNavMeshAgentCount > 0) - { - SceneViewOverlay.Window(EditorGUIUtility.TrTextContent("Agent Display"), DisplayAgentControls, (int)SceneViewOverlay.Ordering.NavMesh, SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget); - } - - // Display Obstacle display only if there are selected NavMeshObstacles. - if (m_SelectedNavMeshObstacleCount > 0) - { - SceneViewOverlay.Window(EditorGUIUtility.TrTextContent("Obstacle Display"), DisplayObstacleControls, (int)SceneViewOverlay.Ordering.NavMesh, SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget); - } - } - - static void DisplayControls(Object target, SceneView sceneView) - { - EditorGUIUtility.labelWidth = 150; - var bRepaint = false; - var showNavMesh = NavMeshVisualizationSettings.showNavMesh; - if (showNavMesh != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show NavMesh"), showNavMesh)) - { - NavMeshVisualizationSettings.showNavMesh = !showNavMesh; - bRepaint = true; - } - - using (new EditorGUI.DisabledScope(!NavMeshVisualizationSettings.hasHeightMesh)) - { - bool showHeightMesh = NavMeshVisualizationSettings.showHeightMesh; - if (showHeightMesh != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show HeightMesh"), showHeightMesh)) - { - NavMeshVisualizationSettings.showHeightMesh = !showHeightMesh; - bRepaint = true; - } - } - - if (Unsupported.IsDeveloperMode()) - { - GUILayout.Label("Internal"); - - var showNavMeshPortals = NavMeshVisualizationSettings.showNavMeshPortals; - if (showNavMeshPortals != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show NavMesh Portals"), showNavMeshPortals)) - { - NavMeshVisualizationSettings.showNavMeshPortals = !showNavMeshPortals; - bRepaint = true; - } - - var showNavMeshLinks = NavMeshVisualizationSettings.showNavMeshLinks; - if (showNavMeshLinks != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show NavMesh Links"), showNavMeshLinks)) - { - NavMeshVisualizationSettings.showNavMeshLinks = !showNavMeshLinks; - bRepaint = true; - } - - var showProximityGrid = NavMeshVisualizationSettings.showProximityGrid; - if (showProximityGrid != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show Proximity Grid"), showProximityGrid)) - { - NavMeshVisualizationSettings.showProximityGrid = !showProximityGrid; - bRepaint = true; - } - - var showHeightMeshBVTree = NavMeshVisualizationSettings.showHeightMeshBVTree; - if (showHeightMeshBVTree != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show HeightMesh BV-Tree"), showHeightMeshBVTree)) - { - NavMeshVisualizationSettings.showHeightMeshBVTree = !showHeightMeshBVTree; - bRepaint = true; - } - } - - if (bRepaint) - RepaintSceneAndGameViews(); - } - - void OnInspectorUpdate() - { - // This is a bit hacky. - // The value of the hasPendingAgentDebugInfo is updated during scene draw, - // which means that value may not be correctly set when entering game mode. - // The value is cache during EventType.Layout, in case they are different - // try to fix it by redrawing the scene and UI. - if (m_SelectedNavMeshAgentCount > 0) - { - if (m_HasPendingAgentDebugInfo != NavMeshVisualizationSettings.hasPendingAgentDebugInfo) - { - if (!m_HasRepaintedForPendingAgentDebugInfo) - { - m_HasRepaintedForPendingAgentDebugInfo = true; - RepaintSceneAndGameViews(); - } - } - else - { - m_HasRepaintedForPendingAgentDebugInfo = false; - } - } - } - - static void DisplayAgentControls(Object target, SceneView sceneView) - { - EditorGUIUtility.labelWidth = 150; - var bRepaint = false; - - // NavMeshVisualizationSettings.hasPendingAgentDebugInfo can change between events, - // capture the value on Layout event. - if (Event.current.type == EventType.Layout) - { - s_NavMeshEditorWindow.m_HasPendingAgentDebugInfo = NavMeshVisualizationSettings.hasPendingAgentDebugInfo; - } - - var showAgentPath = NavMeshVisualizationSettings.showAgentPath; - if (showAgentPath != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show Path Polygons", "Shows the polygons leading to goal."), showAgentPath)) - { - NavMeshVisualizationSettings.showAgentPath = !showAgentPath; - bRepaint = true; - } - - var showAgentPathInfo = NavMeshVisualizationSettings.showAgentPathInfo; - if (showAgentPathInfo != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show Path Query Nodes", "Shows the nodes expanded during last path query."), showAgentPathInfo)) - { - NavMeshVisualizationSettings.showAgentPathInfo = !showAgentPathInfo; - bRepaint = true; - } - - var showAgentNeighbours = NavMeshVisualizationSettings.showAgentNeighbours; - if (showAgentNeighbours != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show Neighbours", "Show the agent neighbours cosidered during simulation."), showAgentNeighbours)) - { - NavMeshVisualizationSettings.showAgentNeighbours = !showAgentNeighbours; - bRepaint = true; - } - - var showAgentWalls = NavMeshVisualizationSettings.showAgentWalls; - if (showAgentWalls != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show Walls", "Shows the wall segments handled during simulation."), showAgentWalls)) - { - NavMeshVisualizationSettings.showAgentWalls = !showAgentWalls; - bRepaint = true; - } - - var showAgentAvoidance = NavMeshVisualizationSettings.showAgentAvoidance; - if (showAgentAvoidance != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show Avoidance", "Shows the processed avoidance geometry from simulation."), showAgentAvoidance)) - { - NavMeshVisualizationSettings.showAgentAvoidance = !showAgentAvoidance; - bRepaint = true; - } - - if (showAgentAvoidance) - { - if (s_NavMeshEditorWindow.m_HasPendingAgentDebugInfo) - { - EditorGUILayout.BeginVertical(GUILayout.MaxWidth(165)); - EditorGUILayout.HelpBox("Avoidance display is not valid until after next game update.", MessageType.Warning); - EditorGUILayout.EndVertical(); - } - // Should match NavMeshManager::kDebugAgentCount - const int kDebugAgentCount = 10; - if (s_NavMeshEditorWindow.m_SelectedNavMeshAgentCount > kDebugAgentCount) - { - EditorGUILayout.BeginVertical(GUILayout.MaxWidth(165)); - EditorGUILayout.HelpBox(string.Format("Avoidance visualization can be drawn for {0} agents ({1} selected).", kDebugAgentCount, s_NavMeshEditorWindow.m_SelectedNavMeshAgentCount), MessageType.Warning); - EditorGUILayout.EndVertical(); - } - } - - if (bRepaint) - RepaintSceneAndGameViews(); - } - - static void DisplayObstacleControls(Object target, SceneView sceneView) - { - EditorGUIUtility.labelWidth = 150; - var bRepaint = false; - - var showObstacleCarveHull = NavMeshVisualizationSettings.showObstacleCarveHull; - if (showObstacleCarveHull != EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Show Carve Hull", "Shows the hull used to carve the obstacle from navmesh."), showObstacleCarveHull)) - { - NavMeshVisualizationSettings.showObstacleCarveHull = !showObstacleCarveHull; - bRepaint = true; - } - - if (bRepaint) - RepaintSceneAndGameViews(); - } - - public virtual void AddItemsToMenu(GenericMenu menu) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Reset Legacy Bake Settings"), false, ResetBakeSettings); - } - - void ResetBakeSettings() - { - Unsupported.SmartReset(EditorNavMeshBuilder.navMeshSettingsObject); - } - - public static void BackgroundTaskStatusChanged() - { - if (s_NavMeshEditorWindow != null) - s_NavMeshEditorWindow.Repaint(); - } - - static IEnumerable GetObjectsRecurse(GameObject root) - { - var objects = new List {root}; - foreach (Transform t in root.transform) - objects.AddRange(GetObjectsRecurse(t.gameObject)); - return objects; - } - - static List GetObjects(bool includeChildren) - { - if (includeChildren) - { - var objects = new List(); - foreach (var selected in Selection.gameObjects) - { - objects.AddRange(GetObjectsRecurse(selected)); - } - return objects; - } - return new List(Selection.gameObjects); - } - - static bool SelectionHasChildren() - { - return Selection.gameObjects.Any(obj => obj.transform.childCount > 0); - } - - static void SetNavMeshArea(int area, bool includeChildren) - { - var objects = GetObjects(includeChildren); - if (objects.Count <= 0) return; - - Undo.RecordObjects(objects.ToArray(), "Change NavMesh area"); - foreach (var go in objects) - GameObjectUtility.SetNavMeshArea(go, area); - } - - private static void ObjectSettings() - { - bool emptySelection = true; - GameObject[] gos; - SceneModeUtility.SearchBar(typeof(MeshRenderer), typeof(Terrain)); - EditorGUILayout.Space(); - - MeshRenderer[] renderers = SceneModeUtility.GetSelectedObjectsOfType(out gos); - if (gos.Length > 0) - { - emptySelection = false; - ObjectSettings(renderers, gos); - } - - Terrain[] terrains = SceneModeUtility.GetSelectedObjectsOfType(out gos); - if (gos.Length > 0) - { - emptySelection = false; - ObjectSettings(terrains, gos); - } - - if (emptySelection) - GUILayout.Label("Select a MeshRenderer or a Terrain from the scene.", EditorStyles.helpBox); - } - - private static void ComponentBasedWorkflowButton() - { - GUILayout.BeginHorizontal(); - if (EditorGUILayout.LinkLabel(s_Styles.m_LearnAboutComponent)) - Help.BrowseURL("https://github.com/Unity-Technologies/NavMeshComponents"); - GUILayout.EndHorizontal(); - } - - private static void ObjectSettings(Object[] components, GameObject[] gos) - { - ComponentBasedWorkflowButton(); - - EditorGUILayout.MultiSelectionObjectTitleBar(components); - - var so = new SerializedObject(gos); - - using (new EditorGUI.DisabledScope(!SceneModeUtility.StaticFlagField("Navigation Static", so.FindProperty("m_StaticEditorFlags"), (int)StaticEditorFlags.NavigationStatic))) - { - SceneModeUtility.StaticFlagField("Generate OffMeshLinks", so.FindProperty("m_StaticEditorFlags"), (int)StaticEditorFlags.OffMeshLinkGeneration); - - var property = so.FindProperty("m_NavMeshLayer"); - - EditorGUI.BeginChangeCheck(); - EditorGUI.showMixedValue = property.hasMultipleDifferentValues; - var navAreaNames = GameObjectUtility.GetNavMeshAreaNames(); - var currentAbsoluteIndex = GameObjectUtility.GetNavMeshArea(gos[0]); - - var navAreaIndex = -1; - - // Need to find the index as the list of names will compress out empty area - for (var i = 0; i < navAreaNames.Length; i++) - { - if (GameObjectUtility.GetNavMeshAreaFromName(navAreaNames[i]) == currentAbsoluteIndex) - { - navAreaIndex = i; - break; - } - } - - var navMeshArea = EditorGUILayout.Popup("Navigation Area", navAreaIndex, navAreaNames); - EditorGUI.showMixedValue = false; - - if (EditorGUI.EndChangeCheck()) - { - //Convert the selected index into absolute index... - var newNavAreaIndex = GameObjectUtility.GetNavMeshAreaFromName(navAreaNames[navMeshArea]); - - GameObjectUtility.ShouldIncludeChildren includeChildren = GameObjectUtility.DisplayUpdateChildrenDialogIfNeeded(Selection.gameObjects, - "Change Navigation Area", "Do you want change the navigation area to " + navAreaNames[navMeshArea] + " for all the child objects as well?"); - if (includeChildren != GameObjectUtility.ShouldIncludeChildren.Cancel) - { - property.intValue = newNavAreaIndex; - SetNavMeshArea(newNavAreaIndex, includeChildren == 0); - } - } - } - - so.ApplyModifiedProperties(); - } - - private void SceneBakeSettings() - { - ComponentBasedWorkflowButton(); - - if (m_SettingsObject == null || m_SettingsObject.targetObject == null) - InitSceneBakeSettings(); - - m_SettingsObject.Update(); - - EditorGUILayout.LabelField(s_Styles.m_AgentSizeHeader, EditorStyles.boldLabel); - - // Draw image - const float kDiagramHeight = 120.0f; - Rect agentDiagramRect = EditorGUILayout.GetControlRect(false, kDiagramHeight); - NavMeshEditorHelpers.DrawAgentDiagram(agentDiagramRect, m_AgentRadius.floatValue, m_AgentHeight.floatValue, m_AgentClimb.floatValue, m_AgentSlope.floatValue); - - //Agent Settings - var radius = EditorGUILayout.FloatField(s_Styles.m_AgentRadiusContent, m_AgentRadius.floatValue); - if (radius >= 0.001f && !Mathf.Approximately(radius - m_AgentRadius.floatValue, 0.0f)) - { - m_AgentRadius.floatValue = radius; - // Update cellsize based on radius unless cellsize is set manually. - if (m_ManualCellSize.boolValue == false) - m_CellSize.floatValue = (2.0f * m_AgentRadius.floatValue) / 6.0f; - } - // If radius is really small warn the user about it and instruct common use case for small radius. - if (m_AgentRadius.floatValue < 0.05f && m_ManualCellSize.boolValue == false) - { - EditorGUILayout.HelpBox("The agent radius you've set is really small, this can slow down the build.\nIf you intended to allow the agent to move close to the borders and walls, please adjust voxel size in advaced settings to ensure correct bake.", MessageType.Warning); - } - - var height = EditorGUILayout.FloatField(s_Styles.m_AgentHeightContent, m_AgentHeight.floatValue); - if (height >= 0.001f && !Mathf.Approximately(height - m_AgentHeight.floatValue, 0.0f)) - m_AgentHeight.floatValue = height; - - const float kMaxSlopeAngle = 60.0f; - EditorGUILayout.Slider(m_AgentSlope, 0.0f, kMaxSlopeAngle, s_Styles.m_AgentSlopeContent); - if (m_AgentSlope.floatValue > kMaxSlopeAngle) - { - EditorGUILayout.HelpBox("The maximum slope should be set to less than " + kMaxSlopeAngle + " degrees to prevent NavMesh build artifacts on slopes. ", MessageType.Warning); - } - - //Step height - var newClimb = EditorGUILayout.FloatField(s_Styles.m_AgentClimbContent, m_AgentClimb.floatValue); - if (newClimb >= 0.0f && !Mathf.Approximately(m_AgentClimb.floatValue - newClimb, 0.0f)) - m_AgentClimb.floatValue = newClimb; - - if (m_AgentClimb.floatValue > m_AgentHeight.floatValue) - { - // Actual clamping happens in NavMeshBuilder.cpp ConfigureConfig() - EditorGUILayout.HelpBox("Step height should be less than agent height.\nClamping step height to " + m_AgentHeight.floatValue + " internally when baking.", MessageType.Warning); - } - - // Detect when agent slope and step height conflict. - float cs = m_CellSize.floatValue; - float ch = cs * 0.5f; // From NavMeshBuilder.cpp:ConfigureConfig() - int walkableClimbVx = (int)Mathf.Ceil(m_AgentClimb.floatValue / ch); - - // Recast treats voxels whose neighbours min/max height difference is more than step height. - float slopeHeightPerVoxel = Mathf.Tan(m_AgentSlope.floatValue / 180.0f * Mathf.PI) * cs; - int slopeVx = (int)Mathf.Ceil(slopeHeightPerVoxel * 2.0f / ch); - if (slopeVx > walkableClimbVx) - { - // Recommend new values. - float betterSlope = (walkableClimbVx * ch) / (cs * 2.0f); - float betterSlopeAngle = Mathf.Atan(betterSlope) / Mathf.PI * 180.0f; - float betterStep = (slopeVx - 1) * ch; - EditorGUILayout.HelpBox("Step Height conflicts with Max Slope. This makes some slopes unwalkable.\nConsider decreasing Max Slope to < " + betterSlopeAngle.ToString("0.0") + " degrees.\nOr, increase Step Height to > " + betterStep.ToString("0.00") + ".", MessageType.Warning); - } - - EditorGUILayout.Space(); - - EditorGUILayout.LabelField(s_Styles.m_OffmeshHeader, EditorStyles.boldLabel); - - //Drop height - var newDropHeight = EditorGUILayout.FloatField(s_Styles.m_AgentDropContent, m_LedgeDropHeight.floatValue); - if (newDropHeight >= 0.0f && !Mathf.Approximately(newDropHeight - m_LedgeDropHeight.floatValue, 0.0f)) - m_LedgeDropHeight.floatValue = newDropHeight; - - //Jump distance - var newJumpDistance = EditorGUILayout.FloatField(s_Styles.m_AgentJumpContent, m_MaxJumpAcrossDistance.floatValue); - if (newJumpDistance >= 0.0f && !Mathf.Approximately(newJumpDistance - m_MaxJumpAcrossDistance.floatValue, 0.0f)) - m_MaxJumpAcrossDistance.floatValue = newJumpDistance; - - EditorGUILayout.Space(); - - //Advanced Settings - m_Advanced = GUILayout.Toggle(m_Advanced, s_Styles.m_AdvancedHeader, EditorStyles.foldout); - - if (m_Advanced) - { - EditorGUI.indentLevel++; - - // Cell size - var manualCellSize = EditorGUILayout.Toggle(s_Styles.m_ManualCellSizeContent, m_ManualCellSize.boolValue); - if (manualCellSize != m_ManualCellSize.boolValue) - { - m_ManualCellSize.boolValue = manualCellSize; - // When unchecking the manual control, revert to automatic value. - if (!manualCellSize) - { - m_CellSize.floatValue = (2.0f * m_AgentRadius.floatValue) / 6.0f; - } - } - - EditorGUI.indentLevel++; - using (new EditorGUI.DisabledScope(!m_ManualCellSize.boolValue)) - { - var cellSize = EditorGUILayout.FloatField(s_Styles.m_CellSizeContent, m_CellSize.floatValue); - if (cellSize > 0.0f && !Mathf.Approximately(cellSize - m_CellSize.floatValue, 0.0f)) - { - m_CellSize.floatValue = Math.Max(0.01f, cellSize); - } - if (cellSize < 0.01f) - { - EditorGUILayout.HelpBox("The voxel size should be larger than 0.01.", MessageType.Warning); - } - - float voxelsPerRadius = m_CellSize.floatValue > 0 ? (m_AgentRadius.floatValue / m_CellSize.floatValue) : 0.0f; - EditorGUILayout.LabelField(" ", voxelsPerRadius.ToString("0.00") + " voxels per agent radius", EditorStyles.miniLabel); - - if (m_ManualCellSize.boolValue) - { - // Make sure these calculations match the ones in NavMeshBuilder.cpp ConfigureConfig() - const float kCellSizeToHeightRatio = 0.5f; - float cellheight = m_CellSize.floatValue * kCellSizeToHeightRatio; - // Some places inside Recast store height as a byte, make sure the ratio between - // the agent height and cell height does not exceed this limit. - if ((int)Mathf.Floor(m_AgentHeight.floatValue / cellheight) > 250) - { - float goodValue = (m_AgentHeight.floatValue / 250.0f) / kCellSizeToHeightRatio; - EditorGUILayout.HelpBox("The number of voxels per agent height is too high. This will reduce the accuracy of the navmesh. Consider using voxel size of at least " + goodValue.ToString("0.000") + ".", MessageType.Warning); - } - - if (voxelsPerRadius < 1.0f) - { - float goodValue = m_AgentRadius.floatValue / 2.0f; - EditorGUILayout.HelpBox("The number of voxels per agent radius is too small. The agent may not avoid walls and ledges properly. Consider using a voxel size less than " + goodValue.ToString("0.000") + " (2 voxels per agent radius).", MessageType.Warning); - } - else if (voxelsPerRadius > 8.0f) - { - float goodValue = m_AgentRadius.floatValue / 8.0f; - EditorGUILayout.HelpBox("The number of voxels per agent radius is too high. It can cause excessive build times. Consider using voxel size closer to " + goodValue.ToString("0.000") + " (8 voxels per radius).", MessageType.Warning); - } - } - - if (m_ManualCellSize.boolValue) - { - EditorGUILayout.HelpBox("Voxel size controls how accurately the navigation mesh is generated from the level geometry. A good voxel size is 2-4 voxels per agent radius. Making voxel size smaller will increase build time.", MessageType.None); - } - } - EditorGUI.indentLevel--; - - EditorGUILayout.Space(); - - // Min region area - var minRegionArea = EditorGUILayout.FloatField(s_Styles.m_MinRegionAreaContent, m_MinRegionArea.floatValue); - if (minRegionArea >= 0.0f && minRegionArea != m_MinRegionArea.floatValue) - m_MinRegionArea.floatValue = minRegionArea; - - EditorGUILayout.Space(); - - //Height mesh - var accurate = EditorGUILayout.Toggle(s_Styles.m_AgentPlacementContent, m_AccuratePlacement.boolValue); - if (accurate != m_AccuratePlacement.boolValue) m_AccuratePlacement.boolValue = accurate; - - EditorGUI.indentLevel--; - } - - m_SettingsObject.ApplyModifiedProperties(); - BakeButtons(); - } - - private void AreaSettings() - { - if (m_Areas == null) - InitAreas(); - m_NavMeshProjectSettingsObject.Update(); - - m_AreasList.DoLayoutList(); - - m_NavMeshProjectSettingsObject.ApplyModifiedProperties(); - } - - private void AgentSettings() - { - if (m_Agents == null) - InitAgents(); - m_NavMeshProjectSettingsObject.Update(); - - if (m_AgentsList.index < 0) - m_AgentsList.index = 0; - - m_AgentsList.DoLayoutList(); - - if (m_AgentsList.index >= 0 && m_AgentsList.index < m_Agents.arraySize) - { - SerializedProperty nameProp = m_SettingNames.GetArrayElementAtIndex(m_AgentsList.index); - SerializedProperty selectedAgent = m_Agents.GetArrayElementAtIndex(m_AgentsList.index); - - SerializedProperty radiusProp = selectedAgent.FindPropertyRelative("agentRadius"); - SerializedProperty heightProp = selectedAgent.FindPropertyRelative("agentHeight"); - SerializedProperty stepHeightProp = selectedAgent.FindPropertyRelative("agentClimb"); - SerializedProperty maxSlopeProp = selectedAgent.FindPropertyRelative("agentSlope"); - - const float kDiagramHeight = 120.0f; - Rect agentDiagramRect = EditorGUILayout.GetControlRect(false, kDiagramHeight); - NavMeshEditorHelpers.DrawAgentDiagram(agentDiagramRect, radiusProp.floatValue, heightProp.floatValue, stepHeightProp.floatValue, maxSlopeProp.floatValue); - - EditorGUILayout.PropertyField(nameProp, EditorGUIUtility.TempContent("Name")); - EditorGUILayout.PropertyField(radiusProp, EditorGUIUtility.TempContent("Radius")); - EditorGUILayout.PropertyField(heightProp, EditorGUIUtility.TempContent("Height")); - EditorGUILayout.PropertyField(stepHeightProp, EditorGUIUtility.TempContent("Step Height")); - - const float kMaxSlopeAngle = 60.0f; - EditorGUILayout.Slider(maxSlopeProp, 0.0f, kMaxSlopeAngle, EditorGUIUtility.TempContent("Max Slope")); - } - - EditorGUILayout.Space(); - - m_NavMeshProjectSettingsObject.ApplyModifiedProperties(); - } - - static void BakeButtons() - { - const float kButtonWidth = 95; - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - bool wasEnabled = GUI.enabled; - GUI.enabled &= !Application.isPlaying; - if (GUILayout.Button("Clear", GUILayout.Width(kButtonWidth))) - { - EditorNavMeshBuilder.ClearAllNavMeshes(); - } - GUI.enabled = wasEnabled; - - if (EditorNavMeshBuilder.isRunning) - { - if (GUILayout.Button("Cancel", GUILayout.Width(kButtonWidth))) - EditorNavMeshBuilder.Cancel(); - } - else - { - wasEnabled = GUI.enabled; - GUI.enabled &= !Application.isPlaying; - if (GUILayout.Button("Bake", GUILayout.Width(kButtonWidth))) - { - EditorNavMeshBuilder.BuildNavMeshAsync(); - } - GUI.enabled = wasEnabled; - } - - GUILayout.EndHorizontal(); - - EditorGUILayout.Space(); - } - } -} diff --git a/Editor/Mono/SceneModeWindows/OcclusionCullingWindow.cs b/Editor/Mono/SceneModeWindows/OcclusionCullingWindow.cs deleted file mode 100644 index 702447d84a..0000000000 --- a/Editor/Mono/SceneModeWindows/OcclusionCullingWindow.cs +++ /dev/null @@ -1,521 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEditorInternal; -using UnityEngine; -using System.IO; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Occlusion", icon = "Occlusion")] - internal class OcclusionCullingWindow : EditorWindow - { - static bool s_IsVisible = false; - - private bool m_PreVis; - private string m_Warning; - - static OcclusionCullingWindow ms_OcclusionCullingWindow; - Vector2 m_ScrollPosition = Vector2.zero; - Mode m_Mode = Mode.AreaSettings; - - static Styles s_Styles; - - class Styles - { - public GUIContent[] ModeToggles = - { - EditorGUIUtility.TrTextContent("Object"), - EditorGUIUtility.TrTextContent("Bake"), - EditorGUIUtility.TrTextContent("Visualization") - }; - public GUIStyle labelStyle = EditorStyles.wordWrappedMiniLabel; - public GUIContent emptyAreaSelection = EditorGUIUtility.TrTextContent("Select a Mesh Renderer or an Occlusion Area from the scene."); - public GUIContent emptyCameraSelection = EditorGUIUtility.TrTextContent("Select a Camera from the scene."); - 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."); - public GUIContent seeVisualizationInScene = EditorGUIUtility.TrTextContent("See the occlusion culling visualization in the Scene View based on the selected Camera."); - public GUIContent noOcclusionData = EditorGUIUtility.TrTextContent("No occlusion data has been baked."); - 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."); - 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."); - 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."); - 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."); - 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."); - }; - - enum Mode - { - AreaSettings = 0, - BakeSettings = 1, - Visualization = 2 - } - - void OnBecameVisible() - { - if (s_IsVisible == true) return; - - s_IsVisible = true; - - SceneView.onSceneGUIDelegate += OnSceneViewGUI; - StaticOcclusionCullingVisualization.showOcclusionCulling = true; - SceneView.RepaintAll(); - } - - void OnBecameInvisible() - { - s_IsVisible = false; - - SceneView.onSceneGUIDelegate -= OnSceneViewGUI; - StaticOcclusionCullingVisualization.showOcclusionCulling = false; - SceneView.RepaintAll(); - } - - void OnSelectionChange() - { - if (m_Mode == Mode.AreaSettings || m_Mode == Mode.Visualization) - Repaint(); - } - - void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - ms_OcclusionCullingWindow = this; - autoRepaintOnSceneChange = true; - EditorApplication.searchChanged += Repaint; - Repaint(); - } - - void OnDisable() - { - ms_OcclusionCullingWindow = null; - EditorApplication.searchChanged -= Repaint; - } - - static void BackgroundTaskStatusChanged() - { - if (ms_OcclusionCullingWindow) - ms_OcclusionCullingWindow.Repaint(); - } - - [MenuItem("Window/Occlusion Culling", false, 2099)] - static void GenerateWindow() - { - var window = GetWindow(typeof(InspectorWindow)); - window.minSize = new Vector2(300, 250); - } - - void SummaryGUI() - { - GUILayout.BeginVertical(EditorStyles.helpBox); - - if (StaticOcclusionCulling.umbraDataSize == 0) - { - GUILayout.Label(s_Styles.noOcclusionData, s_Styles.labelStyle); - } - else - { - GUILayout.Label("Last bake:", s_Styles.labelStyle); - - GUILayout.BeginHorizontal(); - - GUILayout.BeginVertical(); - GUILayout.Label("Occlusion data size ", s_Styles.labelStyle); - GUILayout.EndVertical(); - - GUILayout.BeginVertical(); - GUILayout.Label(EditorUtility.FormatBytes(StaticOcclusionCulling.umbraDataSize), s_Styles.labelStyle); - GUILayout.EndVertical(); - - GUILayout.EndHorizontal(); - } - - GUILayout.EndVertical(); - } - - OcclusionArea CreateNewArea() - { - GameObject go = new GameObject("Occlusion Area"); - OcclusionArea oa = go.AddComponent(); - Selection.activeGameObject = go; - return oa; - } - - void AreaSelectionGUI() - { - bool emptySelection = true; - GameObject[] gos; - Type focusType = SceneModeUtility.SearchBar(typeof(Renderer), typeof(OcclusionArea)); - EditorGUILayout.Space(); - - // Occlusion Areas - OcclusionArea[] oas = SceneModeUtility.GetSelectedObjectsOfType(out gos); - if (gos.Length > 0) - { - emptySelection = false; - EditorGUILayout.MultiSelectionObjectTitleBar(oas); - SerializedObject so = new SerializedObject(oas); - EditorGUILayout.PropertyField(so.FindProperty("m_IsViewVolume")); - so.ApplyModifiedProperties(); - } - - // Renderers - Renderer[] renderers = SceneModeUtility.GetSelectedObjectsOfType(out gos, typeof(MeshRenderer), typeof(SkinnedMeshRenderer)); - if (gos.Length > 0) - { - emptySelection = false; - EditorGUILayout.MultiSelectionObjectTitleBar(renderers); - SerializedObject goso = new SerializedObject(gos); - SceneModeUtility.StaticFlagField("Occluder Static", goso.FindProperty("m_StaticEditorFlags"), (int)StaticEditorFlags.OccluderStatic); - SceneModeUtility.StaticFlagField("Occludee Static", goso.FindProperty("m_StaticEditorFlags"), (int)StaticEditorFlags.OccludeeStatic); - goso.ApplyModifiedProperties(); - } - - if (emptySelection) - { - GUILayout.Label(s_Styles.emptyAreaSelection, EditorStyles.helpBox); - if (focusType == typeof(OcclusionArea)) - { - EditorGUIUtility.labelWidth = 80; - EditorGUILayout.Space(); - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel("Create New"); - if (GUILayout.Button("Occlusion Area", EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - CreateNewArea(); - EditorGUILayout.EndHorizontal(); - } - } - } - - void CameraSelectionGUI() - { - SceneModeUtility.SearchBar(typeof(Camera)); - EditorGUILayout.Space(); - - Camera cam = null; - if (Selection.activeGameObject) - cam = Selection.activeGameObject.GetComponent(); - - // Camera - if (cam) - { - Camera[] cameras = new Camera[] { cam }; - EditorGUILayout.MultiSelectionObjectTitleBar(cameras); - EditorGUILayout.HelpBox(s_Styles.seeVisualizationInScene.text, MessageType.Info); - } - else - { - GUILayout.Label(s_Styles.emptyCameraSelection, EditorStyles.helpBox); - } - } - - void BakeSettings() - { - // Button for setting default values - float buttonWidth = 150; - if (GUILayout.Button("Set default parameters", GUILayout.Width(buttonWidth))) - { - GUIUtility.keyboardControl = 0; // Force focus out from potentially selected field for default parameters setting - StaticOcclusionCulling.SetDefaultOcclusionBakeSettings(); - } - - // Label for default parameter setting - GUILayout.Label(s_Styles.defaultParameterText.tooltip, EditorStyles.helpBox); - - // Edit Smallest Occluder - EditorGUI.BeginChangeCheck(); - float smallestOccluder = EditorGUILayout.FloatField(s_Styles.smallestOccluder, StaticOcclusionCulling.smallestOccluder); - if (EditorGUI.EndChangeCheck()) - { - StaticOcclusionCulling.smallestOccluder = smallestOccluder; - } - - // Edit smallest hole - EditorGUI.BeginChangeCheck(); - float smallestHole = EditorGUILayout.FloatField(s_Styles.smallestHole, StaticOcclusionCulling.smallestHole); - if (EditorGUI.EndChangeCheck()) - { - StaticOcclusionCulling.smallestHole = smallestHole; - } - - // Edit backface threshold - EditorGUI.BeginChangeCheck(); - float backfaceThreshold = EditorGUILayout.Slider(s_Styles.backfaceThreshold, StaticOcclusionCulling.backfaceThreshold, 5.0F, 100.0F); - if (EditorGUI.EndChangeCheck()) - { - StaticOcclusionCulling.backfaceThreshold = backfaceThreshold; - } - } - - void BakeButtons() - { - float buttonWidth = 95; - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - bool allowBaking = !EditorApplication.isPlayingOrWillChangePlaymode; - - // Clear Tome button - GUI.enabled = StaticOcclusionCulling.umbraDataSize != 0 && allowBaking; - if (GUILayout.Button("Clear", GUILayout.Width(buttonWidth))) - StaticOcclusionCulling.Clear(); - GUI.enabled = allowBaking; - - // Is occlusion culling running - if (StaticOcclusionCulling.isRunning) - { - if (GUILayout.Button("Cancel", GUILayout.Width(buttonWidth))) - StaticOcclusionCulling.Cancel(); - } - else - { - if (GUILayout.Button("Bake", GUILayout.Width(buttonWidth))) - { - StaticOcclusionCulling.GenerateInBackground(); - } - } - - GUILayout.EndHorizontal(); - - GUI.enabled = true; - } - - void ModeToggle() - { - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - using (var check = new EditorGUI.ChangeCheckScope()) - { - m_Mode = (Mode)GUILayout.Toolbar((int)m_Mode, s_Styles.ModeToggles, "LargeButton", GUI.ToolbarButtonSize.FitToContents); - if (check.changed) - { - if (m_Mode == Mode.Visualization && StaticOcclusionCulling.umbraDataSize > 0) - StaticOcclusionCullingVisualization.showPreVisualization = false; - else - StaticOcclusionCullingVisualization.showPreVisualization = true; - SceneView.RepaintAll(); - } - } - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - } - - void OnGUI() - { - if (s_Styles == null) - s_Styles = new Styles(); - - // Make sure the tab jumps to visualization if we're in visualize mode. - // (Don't do the reverse. Since tabs can't be marked disabled, the user - // will be confused if the visualization tab can't be clicked, and that - // would be the result if we changed the tab away from visualization - // whenever showPreVisualization is false.) - if (m_Mode != Mode.Visualization && StaticOcclusionCullingVisualization.showPreVisualization == false) - m_Mode = Mode.Visualization; - - EditorGUILayout.Space(); - ModeToggle(); - EditorGUILayout.Space(); - - m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition); - switch (m_Mode) - { - case Mode.AreaSettings: - AreaSelectionGUI(); - break; - case Mode.BakeSettings: - BakeSettings(); - break; - case Mode.Visualization: - if (StaticOcclusionCulling.umbraDataSize > 0) - { - CameraSelectionGUI(); - GUILayout.FlexibleSpace(); - GUILayout.Label(s_Styles.visualizationNote, EditorStyles.helpBox); - } - else - { - GUILayout.Label(s_Styles.noOcclusionData, EditorStyles.helpBox); - } - break; - } - EditorGUILayout.EndScrollView(); - - EditorGUILayout.Space(); - - BakeButtons(); - - EditorGUILayout.Space(); - - // Info GUI - SummaryGUI(); - } - - public void OnSceneViewGUI(SceneView sceneView) - { - if (!s_IsVisible) - return; - - SceneViewOverlay.Window(EditorGUIUtility.TrTextContent("Occlusion Culling"), DisplayControls, (int)SceneViewOverlay.Ordering.OcclusionCulling, SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget); - } - - void OnDidOpenScene() - { - StaticOcclusionCulling.InvalidatePrevisualisationData(); - Repaint(); - } - - void SetShowVolumePreVis() - { - StaticOcclusionCullingVisualization.showPreVisualization = true; - if (m_Mode == Mode.Visualization) - m_Mode = Mode.AreaSettings; - if (ms_OcclusionCullingWindow) - ms_OcclusionCullingWindow.Repaint(); - SceneView.RepaintAll(); - } - - void SetShowVolumeCulling() - { - StaticOcclusionCullingVisualization.showPreVisualization = false; - m_Mode = Mode.Visualization; - if (ms_OcclusionCullingWindow) - ms_OcclusionCullingWindow.Repaint(); - SceneView.RepaintAll(); - } - - bool ShowModePopup(Rect popupRect) - { - // Visualization mode popup - int tomeSize = StaticOcclusionCulling.umbraDataSize; - - // We can only change the preVis state during layout mode. However, the Tome data could be emptied at anytime, which will immediately disable preVis. - // We need to detect this and force a repaint, so we can change the state. - if (m_PreVis != StaticOcclusionCullingVisualization.showPreVisualization) - SceneView.RepaintAll(); - - if (Event.current.type == EventType.Layout) - m_PreVis = StaticOcclusionCullingVisualization.showPreVisualization; - - string[] options = new string[] { "Edit", "Visualize" }; - int selected = m_PreVis ? 0 : 1; - if (EditorGUI.DropdownButton(popupRect, new GUIContent(options[selected]), FocusType.Passive, EditorStyles.popup)) - { - GenericMenu menu = new GenericMenu(); - menu.AddItem(new GUIContent(options[0]), selected == 0, SetShowVolumePreVis); - if (tomeSize > 0) - menu.AddItem(new GUIContent(options[1]), selected == 1, SetShowVolumeCulling); - else - menu.AddDisabledItem(new GUIContent(options[1])); - - menu.Popup(popupRect, selected); - } - return m_PreVis; - } - - void DisplayControls(Object target, SceneView sceneView) - { - if (!sceneView) - return; - - if (!s_IsVisible) - return; - - bool temp; - - // See if pre-vis is set to true. - // If we don't have any Tome data, act as if pvs is true, but don't actually set it to true - // - that way it will act like it switches to false (the default value) by itself as soon as pvs data has been build, - // which better leads to discovery of this feature. - - bool preVis = ShowModePopup(GUILayoutUtility.GetRect(170, EditorGUIUtility.singleLineHeight)); - - if (Event.current.type == EventType.Layout) - { - m_Warning = ""; - - if (!preVis) - { - if (StaticOcclusionCullingVisualization.previewOcclucionCamera == null) - m_Warning = "No camera selected for occlusion preview."; - else if (!StaticOcclusionCullingVisualization.isPreviewOcclusionCullingCameraInPVS) - m_Warning = "Camera is not inside an Occlusion View Area."; - } - } - - int legendHeight = 12; - - if (!string.IsNullOrEmpty(m_Warning)) - { - Rect warningRect = GUILayoutUtility.GetRect(100, legendHeight + 19); - warningRect.x += EditorGUI.indent; - warningRect.width -= EditorGUI.indent; - GUI.Label(warningRect, m_Warning, EditorStyles.helpBox); - } - else - { - // Show legend / volume toggles - Rect legendRect = GUILayoutUtility.GetRect(200, legendHeight); - legendRect.x += EditorGUI.indent; - legendRect.width -= EditorGUI.indent; - Rect viewLegendRect = new Rect(legendRect.x, legendRect.y, legendRect.width, legendRect.height); - - if (preVis) - EditorGUI.DrawLegend(viewLegendRect, Color.white, "View Volumes", StaticOcclusionCullingVisualization.showViewVolumes); - else - EditorGUI.DrawLegend(viewLegendRect, Color.white, "Camera Volumes", StaticOcclusionCullingVisualization.showViewVolumes); - - temp = GUI.Toggle(viewLegendRect, StaticOcclusionCullingVisualization.showViewVolumes, "", GUIStyle.none); - if (temp != StaticOcclusionCullingVisualization.showViewVolumes) - { - StaticOcclusionCullingVisualization.showViewVolumes = temp; - SceneView.RepaintAll(); - } - - if (!preVis) - { - // TODO: FORE REALS cleanup this bad code BUG: 496650 - legendRect = GUILayoutUtility.GetRect(100, legendHeight); - legendRect.x += EditorGUI.indent; - legendRect.width -= EditorGUI.indent; - viewLegendRect = new Rect(legendRect.x, legendRect.y, legendRect.width, legendRect.height); - EditorGUI.DrawLegend(viewLegendRect, Color.green, "Visibility Lines", StaticOcclusionCullingVisualization.showVisibilityLines); - - temp = GUI.Toggle(viewLegendRect, StaticOcclusionCullingVisualization.showVisibilityLines, "", GUIStyle.none); - if (temp != StaticOcclusionCullingVisualization.showVisibilityLines) - { - StaticOcclusionCullingVisualization.showVisibilityLines = temp; - SceneView.RepaintAll(); - } - - legendRect = GUILayoutUtility.GetRect(100, legendHeight); - legendRect.x += EditorGUI.indent; - legendRect.width -= EditorGUI.indent; - viewLegendRect = new Rect(legendRect.x, legendRect.y, legendRect.width, legendRect.height); - EditorGUI.DrawLegend(viewLegendRect, Color.grey, "Portals", StaticOcclusionCullingVisualization.showPortals); - - temp = GUI.Toggle(viewLegendRect, StaticOcclusionCullingVisualization.showPortals, "", GUIStyle.none); - if (temp != StaticOcclusionCullingVisualization.showPortals) - { - StaticOcclusionCullingVisualization.showPortals = temp; - SceneView.RepaintAll(); - } - } - - // Geometry culling toggle - if (!preVis) - { - temp = GUILayout.Toggle(StaticOcclusionCullingVisualization.showGeometryCulling, "Occlusion culling"); - if (temp != StaticOcclusionCullingVisualization.showGeometryCulling) - { - StaticOcclusionCullingVisualization.showGeometryCulling = temp; - SceneView.RepaintAll(); - } - } - } - } - } -} diff --git a/Editor/Mono/SceneModeWindows/PhysicsDebugWindow.cs b/Editor/Mono/SceneModeWindows/PhysicsDebugWindow.cs deleted file mode 100644 index cb5e345ddc..0000000000 --- a/Editor/Mono/SceneModeWindows/PhysicsDebugWindow.cs +++ /dev/null @@ -1,343 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditorInternal; -using UnityEngine; - -using System; -using System.Collections.Generic; - -namespace UnityEditor -{ - public class PhysicsDebugWindow : EditorWindow - { - [SerializeField] bool m_FilterColliderTypesFoldout = false; - [SerializeField] bool m_ColorFoldout = false; - [SerializeField] bool m_RenderingFoldout = false; - [SerializeField] Vector2 m_MainScrollPos = Vector2.zero; - - bool m_PickAdded = false; - bool m_MouseLeaveListenerAdded = false; - - private static class Contents - { - public static readonly GUIContent physicsDebug = EditorGUIUtility.TrTextContent("Physics Debug"); - public static readonly GUIContent workflow = EditorGUIUtility.TrTextContent("Workflow", "The \"Hide\" mode is useful for fast discovery while the \"Show\" mode is useful for finding specific items."); - public static readonly GUIContent staticColor = EditorGUIUtility.TrTextContent("Static Colliders"); - public static readonly GUIContent triggerColor = EditorGUIUtility.TrTextContent("Triggers"); - public static readonly GUIContent rigidbodyColor = EditorGUIUtility.TrTextContent("Rigidbodies"); - public static readonly GUIContent kinematicColor = EditorGUIUtility.TrTextContent("Kinematic Bodies"); - public static readonly GUIContent sleepingBodyColor = EditorGUIUtility.TrTextContent("Sleeping Bodies"); - public static readonly GUIContent forceOverdraw = EditorGUIUtility.TrTextContent("Force Overdraw", "Draws Collider geometry on top of render geometry"); - public static readonly GUIContent viewDistance = EditorGUIUtility.TrTextContent("View Distance", "Lower bound on distance from camera to physics geometry."); - public static readonly GUIContent terrainTilesMax = EditorGUIUtility.TrTextContent("Terrain Tiles Max", "Number of mesh tiles to drawn."); - public static readonly GUIContent devOptions = EditorGUIUtility.TrTextContent("devOptions"); - public static readonly GUIContent forceDot = EditorGUIUtility.TrTextContent("Force Dot"); - public static readonly GUIContent toolsHidden = EditorGUIUtility.TrTextContent("Hide tools"); - public static readonly GUIContent showCollisionGeometry = EditorGUIUtility.TrTextContent("Collision Geometry"); - public static readonly GUIContent enableMouseSelect = EditorGUIUtility.TrTextContent("Mouse Select"); - public static readonly GUIContent useSceneCam = EditorGUIUtility.TrTextContent("Use Scene Cam"); - } - - //--------------------------------------------------------------------- - - [MenuItem("Window/Physics Debugger", false, 2101)] - public static PhysicsDebugWindow ShowWindow() - { - var window = GetWindow(typeof(PhysicsDebugWindow)) as PhysicsDebugWindow; - if (window != null) - { - window.titleContent.text = "Physics Debug"; - } - return window; - } - - void AddPicker() - { - if (!m_PickAdded || HandleUtility.pickClosestGameObjectDelegate == null) - HandleUtility.pickClosestGameObjectDelegate += PhysicsVisualizationSettings.PickClosestGameObject; - m_PickAdded = true; - } - - void RemovePicker() - { - if (m_PickAdded && HandleUtility.pickClosestGameObjectDelegate != null) - HandleUtility.pickClosestGameObjectDelegate -= PhysicsVisualizationSettings.PickClosestGameObject; - m_PickAdded = false; - } - - void OnBecameVisible() - { - PhysicsVisualizationSettings.InitDebugDraw(); - SceneView.onSceneGUIDelegate += OnSceneViewGUI; - RepaintSceneAndGameViews(); - } - - void OnBecameInvisible() - { - RemovePicker(); - SceneView.onSceneGUIDelegate -= OnSceneViewGUI; - PhysicsVisualizationSettings.DeinitDebugDraw(); - RepaintSceneAndGameViews(); - } - - static void RepaintSceneAndGameViews() - { - SceneView.RepaintAll(); - } - - void OnSceneViewGUI(SceneView view) - { - SceneViewOverlay.Window(Contents.physicsDebug, DisplayControls, (int)SceneViewOverlay.Ordering.PhysicsDebug, - SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget); - } - - void AddMouseLeaveListener() - { - if (!m_MouseLeaveListenerAdded) - { - EditorApplication.update += OnMouseLeaveCheck; - m_MouseLeaveListenerAdded = true; - } - } - - void OnMouseLeaveCheck() - { - if (m_MouseLeaveListenerAdded && EditorWindow.mouseOverWindow as SceneView == null) - { - EditorApplication.update -= OnMouseLeaveCheck; - m_MouseLeaveListenerAdded = false; - - if (PhysicsVisualizationSettings.HasMouseHighlight()) - { - PhysicsVisualizationSettings.ClearMouseHighlight(); - } - } - } - - void OnGUI() - { - var dirtyCount = PhysicsVisualizationSettings.dirtyCount; - - EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); - - // Workflow - PhysicsVisualizationSettings.filterWorkflow = (PhysicsVisualizationSettings.FilterWorkflow)EditorGUILayout.EnumPopup( - PhysicsVisualizationSettings.filterWorkflow, EditorStyles.toolbarPopup, GUILayout.Width(130)); - - GUILayout.FlexibleSpace(); - - if (GUILayout.Button("Reset", EditorStyles.toolbarButton)) - PhysicsVisualizationSettings.Reset(); - - EditorGUILayout.EndHorizontal(); - - m_MainScrollPos = GUILayout.BeginScrollView(m_MainScrollPos); - - PhysicsVisualizationSettings.FilterWorkflow filterMode = PhysicsVisualizationSettings.filterWorkflow; - string action = (filterMode == PhysicsVisualizationSettings.FilterWorkflow.ShowSelectedItems) ? "Show " : "Hide "; - - // Layers - int oldConcatenatedMask = InternalEditorUtility.LayerMaskToConcatenatedLayersMask( - PhysicsVisualizationSettings.GetShowCollisionLayerMask(filterMode)); - - int newConcatenatedMask = EditorGUILayout.MaskField( - GUIContent.Temp(action + "Layers", action + "selected layers"), oldConcatenatedMask, InternalEditorUtility.layers); - - PhysicsVisualizationSettings.SetShowCollisionLayerMask( - filterMode, (int)InternalEditorUtility.ConcatenatedLayersMaskToLayerMask(newConcatenatedMask)); - - // Static Colliders - PhysicsVisualizationSettings.SetShowStaticColliders(filterMode, EditorGUILayout.Toggle( - GUIContent.Temp(action + "Static Colliders", action + "collision geometry from Colliders that do not have a Rigidbody") - , PhysicsVisualizationSettings.GetShowStaticColliders(filterMode))); - - // Triggers - PhysicsVisualizationSettings.SetShowTriggers(filterMode, EditorGUILayout.Toggle( - GUIContent.Temp(action + "Triggers", action + "collision geometry from Colliders that have 'isTrigger' enabled") - , PhysicsVisualizationSettings.GetShowTriggers(filterMode))); - - // Rigidbodies - PhysicsVisualizationSettings.SetShowRigidbodies(filterMode, EditorGUILayout.Toggle( - GUIContent.Temp(action + "Rigidbodies", action + "collision geometry from Rigidbodies") - , PhysicsVisualizationSettings.GetShowRigidbodies(filterMode))); - - // Kinematic Bodies - PhysicsVisualizationSettings.SetShowKinematicBodies(filterMode, EditorGUILayout.Toggle( - GUIContent.Temp(action + "Kinematic Bodies", action + "collision geometry from Kinematic Rigidbodies") - , PhysicsVisualizationSettings.GetShowKinematicBodies(filterMode))); - - // Sleeping Bodies - PhysicsVisualizationSettings.SetShowSleepingBodies(filterMode, EditorGUILayout.Toggle( - GUIContent.Temp(action + "Sleeping Bodies", action + "collision geometry from Sleeping Rigidbodies") - , PhysicsVisualizationSettings.GetShowSleepingBodies(filterMode))); - - m_FilterColliderTypesFoldout = EditorGUILayout.Foldout(m_FilterColliderTypesFoldout, "Collider Types"); - if (m_FilterColliderTypesFoldout) - { - EditorGUI.indentLevel++; - float oldWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 200; - - // BoxCollider - PhysicsVisualizationSettings.SetShowBoxColliders(filterMode, EditorGUILayout.Toggle( - GUIContent.Temp(action + "BoxColliders", action + "collision geometry from BoxColliders") - , PhysicsVisualizationSettings.GetShowBoxColliders(filterMode))); - - // SphereCollider - PhysicsVisualizationSettings.SetShowSphereColliders(filterMode, EditorGUILayout.Toggle( - GUIContent.Temp(action + "SphereColliders", action + "collision geometry from SphereColliders") - , PhysicsVisualizationSettings.GetShowSphereColliders(filterMode))); - - // CapsuleCollider - PhysicsVisualizationSettings.SetShowCapsuleColliders(filterMode, EditorGUILayout.Toggle( - GUIContent.Temp(action + "CapsuleColliders", action + "collision geometry from CapsuleColliders") - , PhysicsVisualizationSettings.GetShowCapsuleColliders(filterMode))); - - // MeshCollider convex - PhysicsVisualizationSettings.SetShowMeshColliders(filterMode, PhysicsVisualizationSettings.MeshColliderType.Convex, EditorGUILayout.Toggle( - GUIContent.Temp(action + "MeshColliders (convex)", action + "collision geometry from convex MeshColliders") - , PhysicsVisualizationSettings.GetShowMeshColliders(filterMode, PhysicsVisualizationSettings.MeshColliderType.Convex))); - - // MeshCollider non-convex - PhysicsVisualizationSettings.SetShowMeshColliders(filterMode, PhysicsVisualizationSettings.MeshColliderType.NonConvex, EditorGUILayout.Toggle( - GUIContent.Temp(action + "MeshColliders (concave)", action + "collision geometry from non-convex MeshColliders") - , PhysicsVisualizationSettings.GetShowMeshColliders(filterMode, PhysicsVisualizationSettings.MeshColliderType.NonConvex))); - - // TerrainCollider - PhysicsVisualizationSettings.SetShowTerrainColliders(filterMode, EditorGUILayout.Toggle( - GUIContent.Temp(action + "TerrainColliders", action + "collision geometry from TerrainColliders") - , PhysicsVisualizationSettings.GetShowTerrainColliders(filterMode))); - - EditorGUIUtility.labelWidth = oldWidth; - EditorGUI.indentLevel--; - } - - GUILayout.Space(4); - - // Selection buttons - GUILayout.BeginHorizontal(); - - bool selectNone = GUILayout.Button(action + "None", "MiniButton"); - bool selectAll = GUILayout.Button(action + "All", "MiniButton"); - if (selectNone || selectAll) - PhysicsVisualizationSettings.SetShowForAllFilters(filterMode, selectAll); - - GUILayout.EndHorizontal(); - - m_ColorFoldout = EditorGUILayout.Foldout(m_ColorFoldout, "Colors"); - if (m_ColorFoldout) - { - EditorGUI.indentLevel++; - - PhysicsVisualizationSettings.staticColor = - EditorGUILayout.ColorField(Contents.staticColor, PhysicsVisualizationSettings.staticColor); - - PhysicsVisualizationSettings.triggerColor = - EditorGUILayout.ColorField(Contents.triggerColor, PhysicsVisualizationSettings.triggerColor); - - PhysicsVisualizationSettings.rigidbodyColor = - EditorGUILayout.ColorField(Contents.rigidbodyColor, PhysicsVisualizationSettings.rigidbodyColor); - - PhysicsVisualizationSettings.kinematicColor = - EditorGUILayout.ColorField(Contents.kinematicColor, PhysicsVisualizationSettings.kinematicColor); - - PhysicsVisualizationSettings.sleepingBodyColor = - EditorGUILayout.ColorField(Contents.sleepingBodyColor, PhysicsVisualizationSettings.sleepingBodyColor); - - PhysicsVisualizationSettings.colorVariance = - EditorGUILayout.Slider("Variation", PhysicsVisualizationSettings.colorVariance, 0f, 1f); - - EditorGUI.indentLevel--; - } - - m_RenderingFoldout = EditorGUILayout.Foldout(m_RenderingFoldout, "Rendering"); - if (m_RenderingFoldout) - { - EditorGUI.indentLevel++; - - PhysicsVisualizationSettings.baseAlpha = 1f - EditorGUILayout.Slider("Transparency" - , 1f - PhysicsVisualizationSettings.baseAlpha, 0f, 1f); - - PhysicsVisualizationSettings.forceOverdraw = EditorGUILayout.Toggle(Contents.forceOverdraw - , PhysicsVisualizationSettings.forceOverdraw); - - PhysicsVisualizationSettings.viewDistance = EditorGUILayout.FloatField(Contents.viewDistance - , PhysicsVisualizationSettings.viewDistance); - - PhysicsVisualizationSettings.terrainTilesMax = EditorGUILayout.IntField(Contents.terrainTilesMax - , PhysicsVisualizationSettings.terrainTilesMax); - - EditorGUI.indentLevel--; - } - - if (Unsupported.IsDeveloperMode() || PhysicsVisualizationSettings.devOptions) - { - PhysicsVisualizationSettings.devOptions = EditorGUILayout.Toggle(Contents.devOptions - , PhysicsVisualizationSettings.devOptions); - } - - if (PhysicsVisualizationSettings.devOptions) - { - PhysicsVisualizationSettings.dotAlpha = EditorGUILayout.Slider("dotAlpha" - , PhysicsVisualizationSettings.dotAlpha, -1f, 1f); - - PhysicsVisualizationSettings.forceDot = EditorGUILayout.Toggle(Contents.forceDot - , PhysicsVisualizationSettings.forceDot); - - Tools.hidden = EditorGUILayout.Toggle(Contents.toolsHidden - , Tools.hidden); - } - - GUILayout.EndScrollView(); - - if (dirtyCount != PhysicsVisualizationSettings.dirtyCount) - RepaintSceneAndGameViews(); - } - - void DisplayControls(UnityEngine.Object o, SceneView view) - { - var dirtyCount = PhysicsVisualizationSettings.dirtyCount; - - PhysicsVisualizationSettings.showCollisionGeometry = EditorGUILayout.Toggle(Contents.showCollisionGeometry - , PhysicsVisualizationSettings.showCollisionGeometry); - - PhysicsVisualizationSettings.enableMouseSelect = EditorGUILayout.Toggle(Contents.enableMouseSelect - , PhysicsVisualizationSettings.enableMouseSelect); - - if (PhysicsVisualizationSettings.devOptions) - { - PhysicsVisualizationSettings.useSceneCam = EditorGUILayout.Toggle(Contents.useSceneCam - , PhysicsVisualizationSettings.useSceneCam); - } - - Vector2 mousePos = Event.current.mousePosition; - Rect sceneViewOnly = new Rect(0, EditorGUI.kWindowToolbarHeight, view.position.width, view.position.height - EditorGUI.kWindowToolbarHeight); - bool mouseInSceneView = sceneViewOnly.Contains(Event.current.mousePosition); - - bool allowInteraction = PhysicsVisualizationSettings.showCollisionGeometry && PhysicsVisualizationSettings.enableMouseSelect && mouseInSceneView; - - if (allowInteraction) - { - AddPicker(); - AddMouseLeaveListener(); - - // mouse-over highlight - if (Event.current.type == EventType.MouseMove) - PhysicsVisualizationSettings.UpdateMouseHighlight(HandleUtility.GUIPointToScreenPixelCoordinate(mousePos)); - - if (Event.current.type == EventType.MouseDrag) - PhysicsVisualizationSettings.ClearMouseHighlight(); - } - else - { - RemovePicker(); - PhysicsVisualizationSettings.ClearMouseHighlight(); - } - - if (dirtyCount != PhysicsVisualizationSettings.dirtyCount) - RepaintSceneAndGameViews(); - } - } -} diff --git a/Editor/Mono/SceneModeWindows/SceneModeUtility.cs b/Editor/Mono/SceneModeWindows/SceneModeUtility.cs deleted file mode 100644 index 8c99951717..0000000000 --- a/Editor/Mono/SceneModeWindows/SceneModeUtility.cs +++ /dev/null @@ -1,219 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using System.Collections.Generic; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - public static class SceneModeUtility - { - private static Type s_FocusType = null; - private static SceneHierarchyWindow s_HierarchyWindow = null; - private static GUIContent s_NoneButtonContent = null; - - private class Styles - { - public GUIStyle typeButton = "SearchModeFilter"; - } - private static Styles s_Styles; - private static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } } - - public static T[] GetSelectedObjectsOfType(out GameObject[] gameObjects, params Type[] types) where T : Object - { - if (types.Length == 0) - types = new Type[] { typeof(T) }; - - List gameObjectList = new List(); - List components = new List(); - - Transform[] selectedTransforms = Selection.GetTransforms(SelectionMode.ExcludePrefab | SelectionMode.Editable); - foreach (Transform t in selectedTransforms) - { - foreach (Type type in types) - { - Object comp = t.gameObject.GetComponent(type); - if (comp != null) - { - gameObjectList.Add(t.gameObject); - components.Add((T)comp); - break; - } - } - } - gameObjects = gameObjectList.ToArray(); - return components.ToArray(); - } - - public static void SearchForType(Type type) - { - Object[] wins = Resources.FindObjectsOfTypeAll(typeof(SceneHierarchyWindow)); - SceneHierarchyWindow win = wins.Length > 0 ? (wins[0] as SceneHierarchyWindow) : null; - - if (win) - { - s_HierarchyWindow = win; - if (type == null || type == typeof(GameObject)) - { - s_FocusType = null; - win.ClearSearchFilter(); - } - else - { - s_FocusType = type; - if (win.searchMode == SearchableEditorWindow.SearchMode.Name) - win.searchMode = SearchableEditorWindow.SearchMode.All; - win.SetSearchFilter("t:" + type.Name, win.searchMode, false); - win.hasSearchFilterFocus = true; - } - } - else - s_FocusType = null; - } - - public static Type SearchBar(params Type[] types) - { - if (s_NoneButtonContent == null) - { - s_NoneButtonContent = EditorGUIUtility.IconContent("sv_icon_none"); - s_NoneButtonContent.text = "None"; - } - - if (s_FocusType != null && (s_HierarchyWindow == null || s_HierarchyWindow.m_SearchFilter != "t:" + s_FocusType.Name)) - s_FocusType = null; - - GUILayout.Label("Scene Filter:"); - - EditorGUILayout.BeginHorizontal(); - - { - GUIContent label = EditorGUIUtility.TempContent( - "All", - AssetPreview.GetMiniTypeThumbnail(typeof(GameObject))); - if (TypeButton(label, s_FocusType == null, styles.typeButton)) - SceneModeUtility.SearchForType(null); - } - - for (int i = 0; i < types.Length; i++) - { - Type type = types[i]; - Texture2D icon = null; - if (type == typeof(Renderer)) - icon = EditorGUIUtility.IconContent("MeshRenderer Icon").image as Texture2D; - else if (type == typeof(Terrain)) - icon = EditorGUIUtility.IconContent("Terrain Icon").image as Texture2D; - else - icon = AssetPreview.GetMiniTypeThumbnail(type); - string name = ObjectNames.NicifyVariableName(type.Name) + "s"; - GUIContent label = EditorGUIUtility.TempContent(name, icon); - if (TypeButton(label, type == s_FocusType, styles.typeButton)) - SceneModeUtility.SearchForType(type); - } - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - - return s_FocusType; - } - - private static bool TypeButton(GUIContent label, bool selected, GUIStyle style) - { - EditorGUIUtility.SetIconSize(new Vector2(16f, 16f)); - bool newSelected = GUILayout.Toggle(selected, label, style); - EditorGUIUtility.SetIconSize(Vector2.zero); - return newSelected && (newSelected != selected); - } - - public static bool StaticFlagField(string label, SerializedProperty property, int flag) - { - bool oldToggle = (property.intValue & flag) != 0; - bool oldDifferent = (property.hasMultipleDifferentValuesBitwise & flag) != 0; - EditorGUI.showMixedValue = oldDifferent; - EditorGUI.BeginChangeCheck(); - var toggle = EditorGUILayout.Toggle(label, oldToggle); - if (EditorGUI.EndChangeCheck()) - { - if (!SetStaticFlags(property.serializedObject.targetObjects, flag, toggle)) - return oldToggle && !oldDifferent; - return toggle; - } - EditorGUI.showMixedValue = false; - return toggle && !oldDifferent; - } - - public static bool SetStaticFlags(Object[] targetObjects, int changedFlags, bool flagValue) - { - bool allFlagsAreChanged = (changedFlags == ~0); - var msgChangedFlags = changedFlags; - if (msgChangedFlags < 0 && !allFlagsAreChanged) - { - //In order to have a list of human readable list of changed flags, - //we need to filter out bits that does not correspont to any option. - int allPossibleValues = 0; - var values = Enum.GetValues(typeof(StaticEditorFlags)); - foreach (var value in values) - { - allPossibleValues |= (int)value; - } - - msgChangedFlags = msgChangedFlags & allPossibleValues; - } - StaticEditorFlags flag = allFlagsAreChanged ? - (StaticEditorFlags)0 : - (StaticEditorFlags)Enum.Parse(typeof(StaticEditorFlags), msgChangedFlags.ToString()); - - - // Should we include child objects? - GameObjectUtility.ShouldIncludeChildren includeChildren = GameObjectUtility.DisplayUpdateChildrenDialogIfNeeded(targetObjects.OfType(), "Change Static Flags", - allFlagsAreChanged ? - "Do you want to " + (flagValue ? "enable" : "disable") + " the static flags for all the child objects as well?" : - "Do you want to " + (flagValue ? "enable" : "disable") + " the " + ObjectNames.NicifyVariableName(flag.ToString()) + " flag for all the child objects as well?"); - - if (includeChildren == GameObjectUtility.ShouldIncludeChildren.Cancel) - { - EditorGUIUtility.ExitGUI(); - return false; - } - var objects = GetObjects(targetObjects, includeChildren == GameObjectUtility.ShouldIncludeChildren.IncludeChildren); - Undo.RecordObjects(objects, "Change Static Flags"); - - // Calculate new flags value separately for each object so other flags are not affected. - foreach (GameObject go in objects) - { - int goFlags = (int)GameObjectUtility.GetStaticEditorFlags(go); - goFlags = flagValue ? - goFlags | changedFlags : - goFlags & ~changedFlags; - GameObjectUtility.SetStaticEditorFlags(go, (StaticEditorFlags)goFlags); - } - - return true; - } - - static void GetObjectsRecurse(Transform root, List arr) - { - arr.Add(root.gameObject); - foreach (Transform t in root) - GetObjectsRecurse(t, arr); - } - - public static GameObject[] GetObjects(Object[] gameObjects, bool includeChildren) - { - List allObjects = new List(); - if (!includeChildren) - { - foreach (GameObject go in gameObjects) - allObjects.Add(go); - } - else - { - foreach (GameObject go in gameObjects) - GetObjectsRecurse(go.transform, allObjects); - } - return allObjects.ToArray(); - } - } -} diff --git a/Editor/Mono/SceneModeWindows/TierSettingsWindow.cs b/Editor/Mono/SceneModeWindows/TierSettingsWindow.cs deleted file mode 100644 index c7d0776e5e..0000000000 --- a/Editor/Mono/SceneModeWindows/TierSettingsWindow.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -using Object = UnityEngine.Object; -using EditorGraphicsSettings = UnityEditor.Rendering.EditorGraphicsSettings; -using TierSettingsEditor = UnityEditor.GraphicsSettingsWindow.TierSettingsEditor; - -namespace UnityEditor -{ - internal partial class TierSettingsWindow : EditorWindow - { - static TierSettingsWindow s_Instance; - static public void CreateWindow() - { - s_Instance = EditorWindow.GetWindow(); - s_Instance.minSize = new Vector2(600, 300); - s_Instance.titleContent = EditorGUIUtility.TrTextContent("Tier Settings"); - } - - internal static TierSettingsWindow GetInstance() - { - return s_Instance; - } - - Editor m_TierSettingsEditor; - - void OnEnable() - { - s_Instance = this; - } - - void OnDisable() - { - DestroyImmediate(m_TierSettingsEditor); m_TierSettingsEditor = null; - if (s_Instance == this) - s_Instance = null; - } - - Object graphicsSettings - { - get { return UnityEngine.Rendering.GraphicsSettings.GetGraphicsSettings(); } - } - Editor tierSettingsEditor - { - get - { - Editor.CreateCachedEditor(graphicsSettings, typeof(TierSettingsEditor), ref m_TierSettingsEditor); - ((TierSettingsEditor)m_TierSettingsEditor).verticalLayout = false; - return m_TierSettingsEditor; - } - } - - void OnGUI() - { - tierSettingsEditor.OnInspectorGUI(); - } - } -} diff --git a/Editor/Mono/SceneView/RectSelection.cs b/Editor/Mono/SceneView/RectSelection.cs deleted file mode 100644 index e835c961e7..0000000000 --- a/Editor/Mono/SceneView/RectSelection.cs +++ /dev/null @@ -1,237 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Linq; - -namespace UnityEditor -{ - internal class RectSelection - { - Vector2 m_SelectStartPoint; - Vector2 m_SelectMousePoint; - Object[] m_SelectionStart; - bool m_RectSelecting; - Dictionary m_LastSelection; - enum SelectionType { Normal, Additive, Subtractive } - Object[] m_CurrentSelection = null; - EditorWindow m_Window; - - static int s_RectSelectionID = GUIUtility.GetPermanentControlID(); - - public RectSelection(EditorWindow window) - { - m_Window = window; - } - - public void OnGUI() - { - Event evt = Event.current; - - Handles.BeginGUI(); - - Vector2 mousePos = evt.mousePosition; - int id = s_RectSelectionID; - - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - if (!Tools.viewToolActive) - HandleUtility.AddDefaultControl(id); - break; - - case EventType.MouseDown: - if (HandleUtility.nearestControl == id && evt.button == 0) - { - GUIUtility.hotControl = id; - m_SelectStartPoint = mousePos; - m_SelectionStart = Selection.objects; - m_RectSelecting = false; - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - if (!m_RectSelecting && (mousePos - m_SelectStartPoint).magnitude > 6f) - { - EditorApplication.modifierKeysChanged += SendCommandsOnModifierKeys; - m_RectSelecting = true; - m_LastSelection = null; - m_CurrentSelection = null; - } - if (m_RectSelecting) - { - m_SelectMousePoint = new Vector2(Mathf.Max(mousePos.x, 0), Mathf.Max(mousePos.y, 0)); - GameObject[] rectObjs = HandleUtility.PickRectObjects(EditorGUIExt.FromToRect(m_SelectStartPoint, m_SelectMousePoint)); - m_CurrentSelection = rectObjs; - bool setIt = false; - if (m_LastSelection == null) - { - m_LastSelection = new Dictionary(); - setIt = true; - } - setIt |= m_LastSelection.Count != rectObjs.Length; - if (!setIt) - { - Dictionary set = new Dictionary(rectObjs.Length); - foreach (GameObject g in rectObjs) - set.Add(g, false); - foreach (GameObject g in m_LastSelection.Keys) - { - if (!set.ContainsKey(g)) - { - setIt = true; - break; - } - } - } - if (setIt) - { - m_LastSelection = new Dictionary(rectObjs.Length); - foreach (GameObject g in rectObjs) - m_LastSelection.Add(g, false); - if (rectObjs != null) - { - if (evt.shift) - UpdateSelection(m_SelectionStart, rectObjs, SelectionType.Additive, m_RectSelecting); - else if (EditorGUI.actionKey) - UpdateSelection(m_SelectionStart, rectObjs, SelectionType.Subtractive, m_RectSelecting); - else - UpdateSelection(m_SelectionStart, rectObjs, SelectionType.Normal, m_RectSelecting); - } - } - } - evt.Use(); - } - break; - - case EventType.Repaint: - if (GUIUtility.hotControl == id && m_RectSelecting) - EditorStyles.selectionRect.Draw(EditorGUIExt.FromToRect(m_SelectStartPoint, m_SelectMousePoint), GUIContent.none, false, false, false, false); - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == id && evt.button == 0) - { - GUIUtility.hotControl = 0; - if (m_RectSelecting) - { - EditorApplication.modifierKeysChanged -= SendCommandsOnModifierKeys; - m_RectSelecting = false; - m_SelectionStart = new Object[0]; - evt.Use(); - } - else - { - if (evt.shift || EditorGUI.actionKey) - { - // For shift, we check if EXACTLY the active GO is hovered by mouse and then subtract. Otherwise additive. - // For control/cmd, we check if ANY of the selected GO is hovered by mouse and then subtract. Otherwise additive. - // Control/cmd takes priority over shift. - GameObject hovered = HandleUtility.PickGameObject(evt.mousePosition, false); - if (EditorGUI.actionKey ? Selection.gameObjects.Contains(hovered) : Selection.activeGameObject == hovered) - UpdateSelection(m_SelectionStart, hovered, SelectionType.Subtractive, m_RectSelecting); - else - UpdateSelection(m_SelectionStart, HandleUtility.PickGameObject(evt.mousePosition, true), SelectionType.Additive, m_RectSelecting); - } - else // With no modifier keys, we do the "cycle through overlapped" picking logic in SceneViewPicking.cs - { - GameObject picked = SceneViewPicking.PickGameObject(evt.mousePosition); - UpdateSelection(m_SelectionStart, picked, SelectionType.Normal, m_RectSelecting); - } - - evt.Use(); - } - } - break; - case EventType.ExecuteCommand: - if (id == GUIUtility.hotControl && evt.commandName == EventCommandNames.ModifierKeysChanged) - { - if (evt.shift) - UpdateSelection(m_SelectionStart, m_CurrentSelection, SelectionType.Additive, m_RectSelecting); - else if (EditorGUI.actionKey) - UpdateSelection(m_SelectionStart, m_CurrentSelection, SelectionType.Subtractive, m_RectSelecting); - else - UpdateSelection(m_SelectionStart, m_CurrentSelection, SelectionType.Normal, m_RectSelecting); - evt.Use(); - } - break; - } - - Handles.EndGUI(); - } - - private static void UpdateSelection(Object[] existingSelection, Object newObject, SelectionType type, bool isRectSelection) - { - Object[] objs; - if (newObject == null) - { - objs = new Object[0]; - } - else - { - objs = new Object[1]; - objs[0] = newObject; - } - - UpdateSelection(existingSelection, objs, type, isRectSelection); - } - - private static void UpdateSelection(Object[] existingSelection, Object[] newObjects, SelectionType type, bool isRectSelection) - { - Object[] newSelection; - switch (type) - { - case SelectionType.Additive: - if (newObjects.Length > 0) - { - newSelection = new Object[existingSelection.Length + newObjects.Length]; - System.Array.Copy(existingSelection, newSelection, existingSelection.Length); - for (int i = 0; i < newObjects.Length; i++) - newSelection[existingSelection.Length + i] = newObjects[i]; - if (!isRectSelection) - Selection.activeObject = newObjects[0]; - else - Selection.activeObject = newSelection[0]; - - Selection.objects = newSelection; - } - else - { - Selection.objects = existingSelection; - } - break; - case SelectionType.Subtractive: - Dictionary set = new Dictionary(existingSelection.Length); - foreach (Object g in existingSelection) - set.Add(g, false); - foreach (Object g in newObjects) - { - if (set.ContainsKey(g)) - set.Remove(g); - } - newSelection = new Object[set.Keys.Count]; - set.Keys.CopyTo(newSelection, 0); - Selection.objects = newSelection; - break; - case SelectionType.Normal: - default: - Selection.objects = newObjects; - break; - } - } - - // When rect selecting, we update the selected objects based on which modifier keys are currently held down, - // so the window needs to repaint. - internal void SendCommandsOnModifierKeys() - { - m_Window.SendEvent(EditorGUIUtility.CommandEvent(EventCommandNames.ModifierKeysChanged)); - } - } -} // namespace diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs deleted file mode 100644 index 93a1f6ce4c..0000000000 --- a/Editor/Mono/SceneView/SceneView.cs +++ /dev/null @@ -1,2784 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor.AnimatedValues; -using UnityEditor.SceneManagement; -using UnityEngine; -using UnityEditorInternal; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEngine.Profiling; -using Object = UnityEngine.Object; -using UnityEngine.Rendering; -using UnityEditor.Rendering; -using UnityEngine.Experimental.Rendering; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; - -namespace UnityEditor -{ - [EditorWindowTitle(title = "Scene", useTypeNameAsIconName = true)] - public class SceneView : SearchableEditorWindow, IHasCustomMenu - { - [Serializable] - public struct CameraMode - { - internal CameraMode(DrawCameraMode drawMode, string name, string section) - { - this.drawMode = drawMode; - this.name = name; - this.section = section; - } - - public DrawCameraMode drawMode; - public string name; - public string section; - - public static bool operator==(CameraMode a, CameraMode z) - { - return a.drawMode == z.drawMode && a.name == z.name && a.section == z.section; - } - - public static bool operator!=(CameraMode a, CameraMode z) - { - return !(a == z); - } - - public override bool Equals(System.Object otherObject) - { - if (ReferenceEquals(otherObject, null)) - return false; - if (!(otherObject is CameraMode)) - return false; - return this == (CameraMode)otherObject; - } - - public override int GetHashCode() - { - return ToString().GetHashCode(); - } - - public override string ToString() - { - return string.Format("{0}||{1}||{2}", drawMode, name, section); - } - } - - private static SceneView s_LastActiveSceneView; - private static SceneView s_CurrentDrawingSceneView; - - public static SceneView lastActiveSceneView { get { return s_LastActiveSceneView; } } - public static SceneView currentDrawingSceneView { get { return s_CurrentDrawingSceneView; } } - - static readonly PrefColor kSceneViewBackground = new PrefColor("Scene/Background", 0.278431f, 0.278431f, 0.278431f, 0); - static readonly PrefColor kSceneViewWire = new PrefColor("Scene/Wireframe", 0.0f, 0.0f, 0.0f, 0.5f); - static readonly PrefColor kSceneViewWireOverlay = new PrefColor("Scene/Wireframe Overlay", 0.0f, 0.0f, 0.0f, 0.25f); - 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); - 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); - - static readonly PrefColor kSceneViewMaterialValidateLow = new PrefColor("Scene/Material Validator Value Too Low", 255.0f / 255.0f, 0.0f, 0.0f, 1.0f); - static readonly PrefColor kSceneViewMaterialValidateHigh = new PrefColor("Scene/Material Validator Value Too High", 0.0f, 0.0f, 255.0f / 255.0f, 1.0f); - static readonly PrefColor kSceneViewMaterialValidatePureMetal = new PrefColor("Scene/Material Validator Pure Metal", 255.0f / 255.0f, 255.0f / 255.0f, 0.0f, 1.0f); - - internal static Color kSceneViewFrontLight = new Color(0.769f, 0.769f, 0.769f, 1); - internal static Color kSceneViewUpLight = new Color(0.212f, 0.227f, 0.259f, 1); - internal static Color kSceneViewMidLight = new Color(0.114f, 0.125f, 0.133f, 1); - internal static Color kSceneViewDownLight = new Color(0.047f, 0.043f, 0.035f, 1); - - [NonSerialized] - static readonly Quaternion kDefaultRotation = Quaternion.LookRotation(new Vector3(-1, -.7f, -1)); - - private const float kDefaultViewSize = 10f; - - private const CameraEvent kCommandBufferCameraEvent = CameraEvent.AfterImageEffectsOpaque; - - [NonSerialized] - static readonly Vector3 kDefaultPivot = Vector3.zero; - - const float kOrthoThresholdAngle = 3f; - const float kOneOverSqrt2 = 0.707106781f; - - [NonSerialized] - ActiveEditorTracker m_Tracker; - - [SerializeField] - public bool m_SceneLighting = true; - - public double lastFramingTime = 0; - private const double k_MaxDoubleKeypressTime = 0.5; - - public event Func onValidateCameraMode; - public event Action onCameraModeChanged; - - [Serializable] - public class SceneViewState - { - public bool showFog = true; - public bool showMaterialUpdate = false; - public bool showSkybox = true; - public bool showFlares = true; - public bool showImageEffects = true; - public bool showParticleSystems = true; - - public SceneViewState() - { - } - - public SceneViewState(SceneViewState other) - { - showFog = other.showFog; - showMaterialUpdate = other.showMaterialUpdate; - showSkybox = other.showSkybox; - showFlares = other.showFlares; - showImageEffects = other.showImageEffects; - showParticleSystems = other.showParticleSystems; - } - - public bool IsAllOn() - { - return showFog && showMaterialUpdate && showSkybox && showFlares && showImageEffects && showParticleSystems; - } - - public void Toggle(bool value) - { - showFog = value; - showMaterialUpdate = value; - showSkybox = value; - showFlares = value; - showImageEffects = value; - showParticleSystems = value; - } - } - - static readonly PrefKey k2DMode = new PrefKey("Tools/2D Mode", "2"); - private static bool waitingFor2DModeKeyUp; - - [SerializeField] - private bool m_2DMode; - public bool in2DMode - { - get { return m_2DMode; } - set - { - if (m_2DMode != value && Tools.viewTool != ViewTool.FPS && Tools.viewTool != ViewTool.Orbit) - { - m_2DMode = value; - On2DModeChange(); - } - } - } - - [SerializeField] - bool m_isRotationLocked = false; - public bool isRotationLocked - { - get - { - return m_isRotationLocked; - } - set - { - if (m_isRotationLocked != value) - { - m_isRotationLocked = value; - } - } - } - - private static List s_UserDefinedModes = new List(); - - internal static List userDefinedModes - { - get { return s_UserDefinedModes; } - } - - internal Object m_OneClickDragObject; - - public bool m_AudioPlay = false; - static SceneView s_AudioSceneView; - - [SerializeField] - AnimVector3 m_Position = new AnimVector3(kDefaultPivot); - - public delegate void OnSceneFunc(SceneView sceneView); - public static OnSceneFunc onSceneGUIDelegate; - - //TODO: we want to expose this callback to the users, so they have - //the ability to draw custom things to the SceneView, without the need - //for a CustomEditor. - //We are waiting for some public API guidelines regarding delegates - //to be able to expose this in a good way. - //While exposing this one, we should also document onSceneGUIDelegate - //And if possible AutoUpgrade it to the new way of doing this. - internal static OnSceneFunc onPreSceneGUIDelegate; - - [Obsolete("Use cameraMode instead", false)] - public DrawCameraMode m_RenderMode = 0; - - [SerializeField] - CameraMode m_CameraMode; - - [Obsolete("Use cameraMode instead", false)] - public DrawCameraMode renderMode - { - get { return m_CameraMode.drawMode; } - set - { - if (value == DrawCameraMode.UserDefined) - throw new ArgumentException("Use cameraMode to set user-defined modes"); - cameraMode = SceneRenderModeWindow.GetBuiltinCameraMode(value); - } - } - - public CameraMode cameraMode - { - get - { - // fix for case 969889 where the toolbar is empty when we havent fully initialized the value - if (string.IsNullOrEmpty(m_CameraMode.name)) - { - m_CameraMode = SceneRenderModeWindow.GetBuiltinCameraMode(m_CameraMode.drawMode); - } - return m_CameraMode; - } - set - { - m_CameraMode = value; - #pragma warning disable 618 - m_RenderMode = value.drawMode; - #pragma warning restore 618 - SetupPBRValidation(); - if (onCameraModeChanged != null) - onCameraModeChanged(m_CameraMode); - } - } - - private DrawCameraMode lastRenderMode = 0; - - public bool m_ValidateTrueMetals = false; - - [SerializeField] - private SceneViewState m_SceneViewState; - - public SceneViewState sceneViewState - { - get { return m_SceneViewState; } - } - - [SerializeField] - SceneViewGrid grid; - [SerializeField] - internal SceneViewRotation svRot; - [SerializeField] - internal AnimQuaternion m_Rotation = new AnimQuaternion(kDefaultRotation); - - /// How large an area the scene view covers (measured diagonally). Modify this for immediate effect, or use LookAt to animate it nicely. - [SerializeField] - AnimFloat m_Size = new AnimFloat(kDefaultViewSize); - - [SerializeField] - internal AnimBool m_Ortho = new AnimBool(); - - [NonSerialized] - Camera m_Camera; - - [SerializeField] - bool m_ShowGlobalGrid = true; - internal bool showGlobalGrid { get { return m_ShowGlobalGrid; } set { m_ShowGlobalGrid = value; } } - internal bool drawGlobalGrid { get { return AnnotationUtility.showGrid && showGlobalGrid; } } - - [SerializeField] - private Quaternion m_LastSceneViewRotation; - public Quaternion lastSceneViewRotation - { - get - { - if (m_LastSceneViewRotation == new Quaternion(0f, 0f, 0f, 0f)) - m_LastSceneViewRotation = Quaternion.identity; - return m_LastSceneViewRotation; - } - set { m_LastSceneViewRotation = value; } - } - [SerializeField] - private bool m_LastSceneViewOrtho; - - // Cursor rect handling - private struct CursorRect - { - public Rect rect; - public MouseCursor cursor; - public CursorRect(Rect rect, MouseCursor cursor) - { - this.rect = rect; - this.cursor = cursor; - } - } - private static MouseCursor s_LastCursor = MouseCursor.Arrow; - private static readonly List s_MouseRects = new List(); - private bool s_DraggingCursorIsCached; - internal static void AddCursorRect(Rect rect, MouseCursor cursor) - { - if (Event.current.type == EventType.Repaint) - s_MouseRects.Add(new CursorRect(rect, cursor)); - } - - public float cameraDistance - { - get - { - float fov = m_Ortho.Fade(kPerspectiveFov, 0); - - if (!camera.orthographic) - { - return size / Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad); - } - return size * 2f; - } - } - - [System.NonSerialized] - Light[] m_Light = new Light[3]; - - RectSelection m_RectSelection; - - const float kPerspectiveFov = 90; - - static ArrayList s_SceneViews = new ArrayList(); - public static ArrayList sceneViews { get {return s_SceneViews; }} - - static Material s_AlphaOverlayMaterial; - static Material s_DeferredOverlayMaterial; - static Shader s_ShowOverdrawShader; - static Shader s_ShowMipsShader; - static Shader s_AuraShader; - static Texture2D s_MipColorsTexture; - - // Handle Dragging of stuff over scene view - //static ArrayList s_DraggedEditors = null; - //static GameObject[] s_PickedObject = { null }; - GUIContent m_Lighting; - GUIContent m_Fx; - GUIContent m_AudioPlayContent; - GUIContent m_GizmosContent; - GUIContent m_2DModeContent; - GUIContent m_RenderDocContent; - - // Which tool are we currently editing with. - // This gets updated whenever hotControl == 0, so once the user has started sth, they can't change it mid-drag by e.g. pressing alt - static Tool s_CurrentTool; - - double m_StartSearchFilterTime = -1; - RenderTexture m_SceneTargetTexture; - int m_MainViewControlID; - - public Camera camera { get { return m_Camera; } } - - [SerializeField] - private Shader m_ReplacementShader; - [SerializeField] - private string m_ReplacementString; - - public void SetSceneViewShaderReplace(Shader shader, string replaceString) - { - m_ReplacementShader = shader; - m_ReplacementString = replaceString; - } - - internal bool m_ShowSceneViewWindows = false; - SceneViewOverlay m_SceneViewOverlay; - EditorCache m_DragEditorCache; - - // While Locking the view to object, we have different behaviour for different scenarios: - // Smooth camera behaviour: User dragging the handles - // Instant camera behaviour: Position changed externally (via inspector, physics or scripts etc.) - internal enum DraggingLockedState - { - NotDragging, // Default state. Scene view camera is snapped to selected object instantly - Dragging, // User is dragging from handles. Scene view camera holds still. - LookAt // Temporary state after dragging or selection change, where we return scene view camera smoothly to selected object - } - DraggingLockedState m_DraggingLockedState; - internal DraggingLockedState draggingLocked { set { m_DraggingLockedState = value; } get { return m_DraggingLockedState; } } - - [SerializeField] - private Object m_LastLockedObject; - - [SerializeField] - bool m_ViewIsLockedToObject; - internal bool viewIsLockedToObject - { - get { return m_ViewIsLockedToObject; } - set - { - if (value) - m_LastLockedObject = Selection.activeObject; - else - m_LastLockedObject = null; - - m_ViewIsLockedToObject = value; - draggingLocked = DraggingLockedState.LookAt; - } - } - - - [RequiredByNativeCode] - public static bool FrameLastActiveSceneView() - { - if (lastActiveSceneView == null) - return false; - return lastActiveSceneView.SendEvent(EditorGUIUtility.CommandEvent(EventCommandNames.FrameSelected)); - } - - [RequiredByNativeCode] - public static bool FrameLastActiveSceneViewWithLock() - { - if (lastActiveSceneView == null) - return false; - return lastActiveSceneView.SendEvent(EditorGUIUtility.CommandEvent(EventCommandNames.FrameSelectedWithLock)); - } - - Editor[] GetActiveEditors() - { - if (m_Tracker == null) - m_Tracker = ActiveEditorTracker.sharedTracker; - return m_Tracker.activeEditors; - } - - public static Camera[] GetAllSceneCameras() - { - ArrayList array = new ArrayList(); - for (int i = 0; i < s_SceneViews.Count; ++i) - { - Camera cam = ((SceneView)s_SceneViews[i]).m_Camera; - if (cam != null) - array.Add(cam); - } - return (Camera[])array.ToArray(typeof(Camera)); - } - - public static void RepaintAll() - { - foreach (SceneView sv in s_SceneViews) - { - sv.Repaint(); - } - } - - internal override void SetSearchFilter(string searchFilter, SearchMode mode, bool setAll) - { - if (m_SearchFilter == "" || searchFilter == "") - m_StartSearchFilterTime = EditorApplication.timeSinceStartup; - - base.SetSearchFilter(searchFilter, mode, setAll); - } - - internal void OnLostFocus() - { - // don't bleed our scene view rendering into game view - GameView gameView = (GameView)WindowLayout.FindEditorWindowOfType(typeof(GameView)); - if (gameView && gameView.m_Parent != null && m_Parent != null && gameView.m_Parent == m_Parent) - { - gameView.m_Parent.backgroundValid = false; - } - - if (s_LastActiveSceneView == this) - SceneViewMotion.ResetMotion(); - } - - override public void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - m_RectSelection = new RectSelection(this); - if (grid == null) - grid = new SceneViewGrid(); - grid.Register(this); - if (svRot == null) - svRot = new SceneViewRotation(); - svRot.Register(this); - - autoRepaintOnSceneChange = true; - - m_Rotation.valueChanged.AddListener(Repaint); - m_Position.valueChanged.AddListener(Repaint); - m_Size.valueChanged.AddListener(Repaint); - m_Ortho.valueChanged.AddListener(Repaint); - - wantsMouseMove = true; - wantsMouseEnterLeaveWindow = true; - dontClearBackground = true; - s_SceneViews.Add(this); - - m_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."); - m_Fx = EditorGUIUtility.TrIconContent("SceneviewFx", "Toggle skybox, fog, and various other effects."); - m_AudioPlayContent = EditorGUIUtility.TrIconContent("SceneviewAudio", "Toggle audio on or off."); - m_GizmosContent = EditorGUIUtility.TrTextContent("Gizmos", "Toggle the visibility of different Gizmos in the Scene view."); - m_2DModeContent = EditorGUIUtility.TrTextContent("2D", "When togggled on, the Scene is in 2D view. When toggled off, the Scene is in 3D view."); - m_RenderDocContent = EditorGUIUtility.TrIconContent("renderdoc", "Capture the current view and open in RenderDoc."); - - m_SceneViewOverlay = new SceneViewOverlay(this); - - EditorApplication.playModeStateChanged += OnPlayModeStateChanged; - - EditorApplication.modifierKeysChanged += RepaintAll; // Because we show handles on shift - m_DraggingLockedState = DraggingLockedState.NotDragging; - - CreateSceneCameraAndLights(); - - if (m_2DMode) - LookAt(pivot, Quaternion.identity, size, true, true); - - if (m_CameraMode.drawMode == DrawCameraMode.UserDefined && !s_UserDefinedModes.Contains(m_CameraMode)) - AddCameraMode(m_CameraMode.name, m_CameraMode.section); - - base.OnEnable(); - } - - public SceneView() - { - m_HierarchyType = HierarchyType.GameObjects; - - // Note: Rendering for Scene view picking depends on the depth buffer of the window - depthBufferBits = 32; - } - - internal void Awake() - { - if (sceneViewState == null) - m_SceneViewState = new SceneViewState(); - - if (m_2DMode || EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D) - { - m_LastSceneViewRotation = Quaternion.LookRotation(new Vector3(-1, -.7f, -1)); - m_LastSceneViewOrtho = false; - m_Rotation.value = Quaternion.identity; - m_Ortho.value = true; - m_2DMode = true; - - // Enforcing Rect tool as the default in 2D mode. - if (Tools.current == Tool.Move) - Tools.current = Tool.Rect; - } - } - - internal static void PlaceGameObjectInFrontOfSceneView(GameObject go) - { - if (s_SceneViews.Count >= 1) - { - SceneView view = s_LastActiveSceneView; - if (!view) - view = s_SceneViews[0] as SceneView; - if (view) - { - view.MoveToView(go.transform); - } - } - } - - internal static Camera GetLastActiveSceneViewCamera() - { - SceneView view = s_LastActiveSceneView; - return view ? view.camera : null; - } - - override public void OnDisable() - { - EditorApplication.modifierKeysChanged -= RepaintAll; - - EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; - - if (m_Camera) - DestroyImmediate(m_Camera.gameObject, true); - if (m_Light[0]) - DestroyImmediate(m_Light[0].gameObject, true); - if (m_Light[1]) - DestroyImmediate(m_Light[1].gameObject, true); - if (m_Light[2]) - DestroyImmediate(m_Light[2].gameObject, true); - if (s_MipColorsTexture) - DestroyImmediate(s_MipColorsTexture, true); - s_SceneViews.Remove(this); - if (s_LastActiveSceneView == this) - { - if (s_SceneViews.Count > 0) - s_LastActiveSceneView = s_SceneViews[0] as SceneView; - else - s_LastActiveSceneView = null; - } - - CleanupEditorDragFunctions(); - base.OnDisable(); - } - - public void OnDestroy() - { - if (m_AudioPlay) - { - m_AudioPlay = false; - RefreshAudioPlay(); - } - } - - internal void OnPlayModeStateChanged(PlayModeStateChange state) - { - if (m_AudioPlay) - { - m_AudioPlay = false; - RefreshAudioPlay(); - } - } - - private static GUIStyle s_DropDownStyle; - private GUIStyle effectsDropDownStyle - { - get - { - if (s_DropDownStyle == null) - s_DropDownStyle = "GV Gizmo DropDown"; - return s_DropDownStyle; - } - } - - void DoToolbarGUI() - { - GUILayout.BeginHorizontal("toolbar"); - { - // render mode popup - GUIContent modeContent = EditorGUIUtility.TextContent(m_CameraMode.name); - modeContent.tooltip = L10n.Tr("The Draw Mode used to display the Scene."); - Rect modeRect = GUILayoutUtility.GetRect(modeContent, EditorStyles.toolbarDropDown, GUILayout.Width(120)); - if (EditorGUI.DropdownButton(modeRect, modeContent, FocusType.Passive, EditorStyles.toolbarDropDown)) - { - Rect rect = GUILayoutUtility.topLevel.GetLast(); - PopupWindow.Show(rect, new SceneRenderModeWindow(this), null, ShowMode.PopupMenuWithKeyboardFocus); - GUIUtility.ExitGUI(); - } - - EditorGUILayout.Space(); - - in2DMode = GUILayout.Toggle(in2DMode, m_2DModeContent, "toolbarbutton"); - - EditorGUILayout.Space(); - - m_SceneLighting = GUILayout.Toggle(m_SceneLighting, m_Lighting, "toolbarbutton"); - if (cameraMode.drawMode == DrawCameraMode.ShadowCascades) // cascade visualization requires actual lights with shadows - m_SceneLighting = true; - - GUI.enabled = !Application.isPlaying; - GUI.changed = false; - m_AudioPlay = GUILayout.Toggle(m_AudioPlay, m_AudioPlayContent, EditorStyles.toolbarButton); - if (GUI.changed) - RefreshAudioPlay(); - - GUI.enabled = true; - - Rect fxRect = GUILayoutUtility.GetRect(m_Fx, effectsDropDownStyle); - Rect fxRightRect = new Rect(fxRect.xMax - effectsDropDownStyle.border.right, fxRect.y, effectsDropDownStyle.border.right, fxRect.height); - if (EditorGUI.DropdownButton(fxRightRect, GUIContent.none, FocusType.Passive, GUIStyle.none)) - { - Rect rect = GUILayoutUtility.topLevel.GetLast(); - PopupWindow.Show(rect, new SceneFXWindow(this), null, ShowMode.PopupMenuWithKeyboardFocus); - GUIUtility.ExitGUI(); - } - - var allOn = GUI.Toggle(fxRect, sceneViewState.IsAllOn(), m_Fx, effectsDropDownStyle); - if (allOn != sceneViewState.IsAllOn()) - sceneViewState.Toggle(allOn); - - EditorGUILayout.Space(); - GUILayout.FlexibleSpace(); - - if (m_MainViewControlID != GUIUtility.keyboardControl - && Event.current.type == EventType.KeyDown - && !string.IsNullOrEmpty(m_SearchFilter) - ) - { - switch (Event.current.keyCode) - { - case KeyCode.UpArrow: - case KeyCode.DownArrow: - if (Event.current.keyCode == KeyCode.UpArrow) - SelectPreviousSearchResult(); - else - SelectNextSearchResult(); - - FrameSelected(false); - Event.current.Use(); - GUIUtility.ExitGUI(); - return; - } - } - - if (RenderDoc.IsLoaded()) - { - using (new EditorGUI.DisabledScope(!RenderDoc.IsSupported())) - { - if (GUILayout.Button(m_RenderDocContent, EditorStyles.toolbarButton)) - { - m_Parent.CaptureRenderDoc(); - GUIUtility.ExitGUI(); - } - } - } - - Rect r = GUILayoutUtility.GetRect(m_GizmosContent, EditorStyles.toolbarDropDown); - if (EditorGUI.DropdownButton(r, m_GizmosContent, FocusType.Passive, EditorStyles.toolbarDropDown)) - { - Rect rect = GUILayoutUtility.topLevel.GetLast(); - if (AnnotationWindow.ShowAtPosition(rect, false)) - { - GUIUtility.ExitGUI(); - } - } - GUILayout.Space(6); - - SearchFieldGUI(EditorGUILayout.kLabelFloatMaxW); - } - GUILayout.EndHorizontal(); - } - - // This method should be called after the audio play button has been toggled, - // and after other events that require a refresh. - void RefreshAudioPlay() - { - if ((s_AudioSceneView != null) && (s_AudioSceneView != this)) - { - // turn *other* sceneview off - if (s_AudioSceneView.m_AudioPlay) - { - s_AudioSceneView.m_AudioPlay = false; - s_AudioSceneView.Repaint(); - } - } - - var sources = (AudioSource[])FindObjectsOfType(typeof(AudioSource)); - foreach (AudioSource source in sources) - { - if (source.playOnAwake) - { - if (!m_AudioPlay) - { - source.Stop(); - } - else - { - if (!source.isPlaying) - source.Play(); - } - } - } - AudioUtil.SetListenerTransform(m_AudioPlay ? m_Camera.transform : null); - - s_AudioSceneView = this; - } - - /// TODO: Don't repaint sceneview unless either old or new selection is a scene object - public void OnSelectionChange() - { - if (Selection.activeObject != null && m_LastLockedObject != Selection.activeObject) - { - viewIsLockedToObject = false; - } - Repaint(); - } - - private void LoadRenderDoc() - { - if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) - { - RenderDoc.Load(); - ShaderUtil.RecreateGfxDevice(); - } - } - - public virtual void AddItemsToMenu(GenericMenu menu) - { - if (RenderDoc.IsInstalled() && !RenderDoc.IsLoaded()) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Load RenderDoc"), false, LoadRenderDoc); - } - } - - [MenuItem("GameObject/Set as first sibling %=")] - static internal void MenuMoveToFront() - { - foreach (Transform t in Selection.transforms) - { - Undo.SetTransformParent(t, t.parent, "Set as first sibling"); - t.SetAsFirstSibling(); - } - } - - [MenuItem("GameObject/Set as first sibling %=", true)] - static internal bool ValidateMenuMoveToFront() - { - if (Selection.activeTransform != null) - { - Transform parent = Selection.activeTransform.parent; - return (parent != null && parent.GetChild(0) != Selection.activeTransform); - } - return false; - } - - [MenuItem("GameObject/Set as last sibling %-")] - static internal void MenuMoveToBack() - { - foreach (Transform t in Selection.transforms) - { - Undo.SetTransformParent(t, t.parent, "Set as last sibling"); - t.SetAsLastSibling(); - } - } - - [MenuItem("GameObject/Set as last sibling %-", true)] - static internal bool ValidateMenuMoveToBack() - { - if (Selection.activeTransform != null) - { - Transform parent = Selection.activeTransform.parent; - return (parent != null && parent.GetChild(parent.childCount - 1) != Selection.activeTransform); - } - return false; - } - - [MenuItem("GameObject/Move To View %&f")] - static internal void MenuMoveToView() - { - if (ValidateMoveToView()) - s_LastActiveSceneView.MoveToView(); - } - - [MenuItem("GameObject/Move To View %&f", true)] - static bool ValidateMoveToView() - { - return s_LastActiveSceneView != null && (Selection.transforms.Length != 0); - } - - [MenuItem("GameObject/Align With View %#f")] - static internal void MenuAlignWithView() - { - if (ValidateAlignWithView()) - s_LastActiveSceneView.AlignWithView(); - } - - [MenuItem("GameObject/Align With View %#f", true)] - static internal bool ValidateAlignWithView() - { - return s_LastActiveSceneView != null && (Selection.activeTransform != null); - } - - [MenuItem("GameObject/Align View to Selected")] - static internal void MenuAlignViewToSelected() - { - if (ValidateAlignViewToSelected()) - s_LastActiveSceneView.AlignViewToObject(Selection.activeTransform); - } - - [MenuItem("GameObject/Align View to Selected", true)] - static internal bool ValidateAlignViewToSelected() - { - return s_LastActiveSceneView != null && (Selection.activeTransform != null); - } - - [MenuItem("GameObject/Toggle Active State &#a")] - static internal void ActivateSelection() - { - if (Selection.activeTransform != null) - { - GameObject[] gos = Selection.gameObjects; - Undo.RecordObjects(gos, "Toggle Active State"); - bool val = !Selection.activeGameObject.activeSelf; - foreach (GameObject go in gos) - go.SetActive(val); - } - } - - [MenuItem("GameObject/Toggle Active State &#a", true)] - static internal bool ValidateActivateSelection() - { - return (Selection.activeTransform != null); - } - - static private void CreateMipColorsTexture() - { - if (s_MipColorsTexture) - return; - s_MipColorsTexture = new Texture2D(32, 32, TextureFormat.RGBA32, true); - s_MipColorsTexture.hideFlags = HideFlags.HideAndDontSave; - Color[] colors = new Color[6]; - colors[0] = new Color(0.0f, 0.0f, 1.0f, 0.8f); - colors[1] = new Color(0.0f, 0.5f, 1.0f, 0.4f); - colors[2] = new Color(1.0f, 1.0f, 1.0f, 0.0f); // optimal level - colors[3] = new Color(1.0f, 0.7f, 0.0f, 0.2f); - colors[4] = new Color(1.0f, 0.3f, 0.0f, 0.6f); - colors[5] = new Color(1.0f, 0.0f, 0.0f, 0.8f); - int mipCount = Mathf.Min(6, s_MipColorsTexture.mipmapCount); - for (int mip = 0; mip < mipCount; ++mip) - { - int width = Mathf.Max(s_MipColorsTexture.width >> mip, 1); - int height = Mathf.Max(s_MipColorsTexture.height >> mip, 1); - Color[] cols = new Color[width * height]; - for (int i = 0; i < cols.Length; ++i) - cols[i] = colors[mip]; - s_MipColorsTexture.SetPixels(cols, mip); - } - s_MipColorsTexture.filterMode = FilterMode.Trilinear; - s_MipColorsTexture.Apply(false); - Shader.SetGlobalTexture("_SceneViewMipcolorsTexture", s_MipColorsTexture); - } - - private bool m_RequestedSceneViewFiltering; - private double m_lastRenderedTime; - - public void SetSceneViewFiltering(bool enable) - { - m_RequestedSceneViewFiltering = enable; - } - - private bool UseSceneFiltering() - { - return !string.IsNullOrEmpty(m_SearchFilter) || m_RequestedSceneViewFiltering; - } - - internal bool SceneViewIsRenderingHDR() - { - return m_Camera != null && m_Camera.allowHDR; - } - - private void HandleClickAndDragToFocus() - { - Event evt = Event.current; - if (evt.type == EventType.MouseDown || evt.type == EventType.MouseDrag) - s_LastActiveSceneView = this; - else if (s_LastActiveSceneView == null) - s_LastActiveSceneView = this; - - if (evt.type == EventType.MouseDrag) - draggingLocked = DraggingLockedState.Dragging; - else if (GUIUtility.hotControl == 0 && draggingLocked == DraggingLockedState.Dragging) - draggingLocked = DraggingLockedState.LookAt; - - if (evt.type == EventType.MouseDown) - { - Tools.s_ButtonDown = evt.button; - if (evt.button == 1 && Application.platform == RuntimePlatform.OSXEditor) - Focus(); - } - // this is necessary because FPS tool won't get is cleanup logic - // executed if another control uses the Event (i.e OnSceneGUI) (case 777346) - else if (evt.type == EventType.MouseUp && Tools.s_ButtonDown == evt.button) - { - Tools.s_ButtonDown = -1; - } - } - - private void SetupFogAndShadowDistance(out bool oldFog, out float oldShadowDistance) - { - oldFog = RenderSettings.fog; - oldShadowDistance = QualitySettings.shadowDistance; - if (Event.current.type == EventType.Repaint) - { - if (!sceneViewState.showFog) - Unsupported.SetRenderSettingsUseFogNoDirty(false); - if (m_Camera.orthographic) - Unsupported.SetQualitySettingsShadowDistanceTemporarily(QualitySettings.shadowDistance + 0.5f * cameraDistance); - } - } - - private void RestoreFogAndShadowDistance(bool oldFog, float oldShadowDistance) - { - if (Event.current.type == EventType.Repaint) - { - Unsupported.SetRenderSettingsUseFogNoDirty(oldFog); - Unsupported.SetQualitySettingsShadowDistanceTemporarily(oldShadowDistance); - } - } - - private void CreateCameraTargetTexture(Rect cameraRect, bool hdr) - { - int msaa = Mathf.Max(1, QualitySettings.antiAliasing); - // deferred does not support MSAA now, so not point in using it - if (IsSceneCameraDeferred()) - msaa = 1; - - // TODO: 1st gen OSX Metal drivers (El Capitan) do not support - // MSAA store+resolve action flag or deferred store action flags, - // this can be lead to undefined behaviour depending on GPU driver - // used. Some may work with multiple load/store passes or survive - // setting the depth store action to DontCare with MSAA depth buffers - // - // MSAA should be ok with game view, but SceneView RT handling is - // a bit more complicated that needs improvements later - if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal) - msaa = 1; - - // make sure we actually support ARGBHalf (ShaderModel20 emulation doesn't) - RenderTextureFormat format = (hdr && SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf)) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32; - if (m_SceneTargetTexture != null) - { - if (m_SceneTargetTexture.format != format || m_SceneTargetTexture.antiAliasing != msaa) - { - Object.DestroyImmediate(m_SceneTargetTexture); - m_SceneTargetTexture = null; - } - } - - Rect actualCameraRect = Handles.GetCameraRect(cameraRect); - int width = (int)actualCameraRect.width; - int height = (int)actualCameraRect.height; - - if (m_SceneTargetTexture == null) - { - m_SceneTargetTexture = new RenderTexture(0, 0, 24, format, RenderTextureReadWrite.sRGB); - m_SceneTargetTexture.name = "SceneView RT"; - m_SceneTargetTexture.antiAliasing = msaa; - m_SceneTargetTexture.hideFlags = HideFlags.HideAndDontSave; - } - if (m_SceneTargetTexture.width != width || m_SceneTargetTexture.height != height) - { - m_SceneTargetTexture.Release(); - m_SceneTargetTexture.width = width; - m_SceneTargetTexture.height = height; - } - m_SceneTargetTexture.Create(); - } - - public bool IsCameraDrawModeEnabled(CameraMode mode) - { - if (!Handles.IsCameraDrawModeEnabled(m_Camera, mode.drawMode)) - return false; - return (onValidateCameraMode == null || - onValidateCameraMode.GetInvocationList().All(validate => ((Func)validate)(mode))); - } - - internal bool IsSceneCameraDeferred() - { - bool usingScriptableRenderPipeline = (GraphicsSettings.renderPipelineAsset != null); - if (m_Camera == null || usingScriptableRenderPipeline) - return false; - if (m_Camera.actualRenderingPath == RenderingPath.DeferredLighting || m_Camera.actualRenderingPath == RenderingPath.DeferredShading) - return true; - return false; - } - - internal static bool DoesCameraDrawModeSupportDeferred(DrawCameraMode mode) - { - // many of special visualization modes don't support deferred shading/lighting - // overdraw/mipmaps visualizations need special forward shader - // various lightmaps/visualization modes, don't use deferred for safety (previous code also did not use deferred) - return - mode == DrawCameraMode.Normal || - mode == DrawCameraMode.Textured || - mode == DrawCameraMode.TexturedWire || - mode == DrawCameraMode.ShadowCascades || - mode == DrawCameraMode.RenderPaths || - mode == DrawCameraMode.AlphaChannel || - mode == DrawCameraMode.DeferredDiffuse || - mode == DrawCameraMode.DeferredSpecular || - mode == DrawCameraMode.DeferredSmoothness || - mode == DrawCameraMode.DeferredNormal || - mode == DrawCameraMode.RealtimeCharting || - mode == DrawCameraMode.Systems || - mode == DrawCameraMode.Clustering || - mode == DrawCameraMode.LitClustering || - mode == DrawCameraMode.RealtimeAlbedo || - mode == DrawCameraMode.RealtimeEmissive || - mode == DrawCameraMode.RealtimeIndirect || - mode == DrawCameraMode.RealtimeDirectionality || - mode == DrawCameraMode.BakedLightmap || - mode == DrawCameraMode.ValidateAlbedo || - mode == DrawCameraMode.ValidateMetalSpecular; - } - - internal static bool DoesCameraDrawModeSupportHDR(DrawCameraMode mode) - { - // HDR/Tonemap only supported on regular views, and not on any special visualizations - return - mode == DrawCameraMode.Textured || mode == DrawCameraMode.TexturedWire; - } - - private void PrepareCameraTargetTexture(Rect cameraRect) - { - // Always render camera into a RT - bool hdr = SceneViewIsRenderingHDR(); - CreateCameraTargetTexture(cameraRect, hdr); - m_Camera.targetTexture = m_SceneTargetTexture; - - // Do not use deferred rendering when using search filtering or wireframe/overdraw/mipmaps rendering modes. - if (UseSceneFiltering() || !DoesCameraDrawModeSupportDeferred(m_CameraMode.drawMode)) - { - if (IsSceneCameraDeferred()) - m_Camera.renderingPath = RenderingPath.Forward; - } - } - - private void PrepareCameraReplacementShader() - { - if (Event.current.type != EventType.Repaint) - return; - - // Set scene view colors - Handles.SetSceneViewColors(kSceneViewWire, kSceneViewWireOverlay, kSceneViewSelectedOutline, kSceneViewSelectedWire); - - // Setup shader replacement if needed by overlay mode - if (m_CameraMode.drawMode == DrawCameraMode.Overdraw) - { - // show overdraw - if (!s_ShowOverdrawShader) - s_ShowOverdrawShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewShowOverdraw.shader") as Shader; - m_Camera.SetReplacementShader(s_ShowOverdrawShader, "RenderType"); - } - else if (m_CameraMode.drawMode == DrawCameraMode.Mipmaps) - { - // show mip levels - if (!s_ShowMipsShader) - s_ShowMipsShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewShowMips.shader") as Shader; - if (s_ShowMipsShader != null && s_ShowMipsShader.isSupported) - { - CreateMipColorsTexture(); - m_Camera.SetReplacementShader(s_ShowMipsShader, "RenderType"); - } - else - { - m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString); - } - } - /* - else if (m_RenderMode == DrawCameraMode.Lightmaps) - { - // show lightmaps - if (!s_ShowLightmapsShader) - s_ShowLightmapsShader = EditorGUIUtility.LoadRequired ("SceneView/SceneViewShowLightmap.shader") as Shader; - if (s_ShowLightmapsShader.isSupported) - m_Camera.SetReplacementShader (s_ShowLightmapsShader, "RenderType"); - else - m_Camera.SetReplacementShader (m_ReplacementShader, m_ReplacementString); - }*/ - else - { - m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString); - } - } - - bool SceneCameraRendersIntoRT() - { - return m_Camera.targetTexture != null; - } - - private void DoDrawCamera(Rect cameraRect, out bool pushedGUIClip) - { - pushedGUIClip = false; - if (!m_Camera.gameObject.activeInHierarchy) - return; - - DrawGridParameters gridParam = grid.PrepareGridRender(camera, pivot, m_Rotation.target, m_Size.value, m_Ortho.target, drawGlobalGrid); - - Event evt = Event.current; - if (UseSceneFiltering()) - { - if (evt.type == EventType.Repaint) - { - // First pass: Draw objects which do not meet the search filter with grayscale image effect. - Handles.EnableCameraFx(m_Camera, true); - - Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowRest); - - float fade = Mathf.Clamp01((float)(EditorApplication.timeSinceStartup - m_StartSearchFilterTime)); - Handles.DrawCamera(cameraRect, m_Camera, m_CameraMode.drawMode); - Handles.DrawCameraFade(m_Camera, fade); - - // Second pass: Draw aura for objects which do meet search filter, but are occluded. - Handles.EnableCameraFx(m_Camera, false); - Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowFiltered); - if (!s_AuraShader) - s_AuraShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewAura.shader") as Shader; - m_Camera.SetReplacementShader(s_AuraShader, ""); - Handles.DrawCamera(cameraRect, m_Camera, m_CameraMode.drawMode); - - // Third pass: Draw objects which do meet filter normally - m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString); - Handles.DrawCamera(cameraRect, m_Camera, m_CameraMode.drawMode, gridParam); - - if (fade < 1) - Repaint(); - } - Rect r = cameraRect; - if (evt.type == EventType.Repaint) - RenderTexture.active = null; - GUI.EndGroup(); - GUI.BeginGroup(new Rect(0, EditorGUI.kWindowToolbarHeight, position.width, position.height - EditorGUI.kWindowToolbarHeight)); - if (evt.type == EventType.Repaint) - { - Graphics.DrawTexture(r, m_SceneTargetTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, GUI.blitMaterial); - } - Handles.SetCamera(cameraRect, m_Camera); - - HandleSelectionAndOnSceneGUI(); - } - else - { - // If the camera is rendering into a Render Texture we need to reset the offsets of the GUIClip stack - // otherwise all GUI drawing after here will get offset incorrectly. - if (SceneCameraRendersIntoRT()) - { - GUIClip.Push(new Rect(0f, 0f, position.width, position.height), Vector2.zero, Vector2.zero, true); - pushedGUIClip = true; - } - Handles.DrawCameraStep1(cameraRect, m_Camera, m_CameraMode.drawMode, gridParam); - DrawRenderModeOverlay(cameraRect); - } - } - - void SetupPBRValidation() - { - DrawCameraMode renderMode = m_CameraMode.drawMode; - if (renderMode == DrawCameraMode.ValidateAlbedo) - { - CreateAlbedoSwatchData(); - UpdateAlbedoSwatch(); - } - - if ((renderMode == DrawCameraMode.ValidateAlbedo || renderMode == DrawCameraMode.ValidateMetalSpecular) && - lastRenderMode != DrawCameraMode.ValidateAlbedo && lastRenderMode != DrawCameraMode.ValidateMetalSpecular) - { - SceneView.onSceneGUIDelegate += DrawValidateAlbedoSwatches; - } - else if ((renderMode != DrawCameraMode.ValidateAlbedo && renderMode != DrawCameraMode.ValidateMetalSpecular) && - (lastRenderMode == DrawCameraMode.ValidateAlbedo || lastRenderMode == DrawCameraMode.ValidateMetalSpecular)) - { - SceneView.onSceneGUIDelegate -= DrawValidateAlbedoSwatches; - } - - lastRenderMode = renderMode; - } - - void DoClearCamera(Rect cameraRect) - { - // Clear (color/skybox) - // We do funky FOV interpolation when switching between ortho and perspective. However, - // for the skybox we always want to use the same FOV. - float skyboxFOV = GetVerticalFOV(kPerspectiveFov); - float realFOV = m_Camera.fieldOfView; - m_Camera.fieldOfView = skyboxFOV; - Handles.ClearCamera(cameraRect, m_Camera); - m_Camera.fieldOfView = realFOV; - } - - void SetupCustomSceneLighting() - { - if (m_SceneLighting) - return; - m_Light[0].transform.rotation = m_Camera.transform.rotation; - if (Event.current.type == EventType.Repaint) - InternalEditorUtility.SetCustomLighting(m_Light, kSceneViewMidLight); - } - - void CleanupCustomSceneLighting() - { - if (m_SceneLighting) - return; - if (Event.current.type == EventType.Repaint) - InternalEditorUtility.RemoveCustomLighting(); - } - - // Give editors a chance to kick in. Disable in search mode, editors rendering to the scene - void HandleViewToolCursor() - { - if (!Tools.viewToolActive || Event.current.type != EventType.Repaint) - return; - - var cursor = MouseCursor.Arrow; - switch (Tools.viewTool) - { - case ViewTool.Pan: cursor = MouseCursor.Pan; break; - case ViewTool.Orbit: cursor = MouseCursor.Orbit; break; - case ViewTool.FPS: cursor = MouseCursor.FPS; break; - case ViewTool.Zoom: cursor = MouseCursor.Zoom; break; - } - if (cursor != MouseCursor.Arrow) - AddCursorRect(new Rect(0, EditorGUI.kWindowToolbarHeight, position.width, position.height - EditorGUI.kWindowToolbarHeight), cursor); - } - - private static bool ComponentHasImageEffectAttribute(Component c) - { - if (c == null) - return false; - return Attribute.IsDefined(c.GetType(), typeof(ImageEffectAllowedInSceneView)); - } - - void UpdateImageEffects(bool enable) - { - if (Event.current.type != EventType.Repaint) - return; - - Camera mainCam = GetMainCamera(); - if (!enable || mainCam == null) - { - ComponentUtility.DestroyComponentsMatching(m_Camera.gameObject, ComponentHasImageEffectAttribute); - return; - } - - ComponentUtility.ReplaceComponentsIfDifferent(mainCam.gameObject, m_Camera.gameObject, ComponentHasImageEffectAttribute); - } - - void DoOnPreSceneGUICallbacks(Rect cameraRect) - { - // Don't do callbacks in search mode, as editors calling Handles.BeginGUI - // will break camera setup. - if (UseSceneFiltering()) - return; - - Handles.SetCamera(cameraRect, m_Camera); - CallOnPreSceneGUI(); - } - - private AlbedoSwatchInfo[] m_AlbedoSwatchInfos; - private GUIStyle[] m_AlbedoSwatchColorStyles; - private String[] m_AlbedoSwatchDescriptions; - private GUIContent[] m_AlbedoSwatchGUIContent; - private String[] m_AlbedoSwatchLuminanceStrings; - - private GUIStyle m_TooLowColorStyle = null; - private GUIStyle m_TooHighColorStyle = null; - private GUIStyle m_PureMetalColorStyle = null; - - private int m_SelectedAlbedoSwatchIndex = 0; - private float m_AlbedoSwatchHueTolerance = 0.1f; - private float m_AlbedoSwatchSaturationTolerance = 0.2f; - private ColorSpace m_LastKnownColorSpace = ColorSpace.Uninitialized; - - GUIStyle CreateSwatchStyleForColor(Color c) - { - Texture2D t = new Texture2D(1, 1); - if (PlayerSettings.colorSpace == ColorSpace.Linear) - { - c = c.gamma; // offset linear to gamma correction that happens in IMGUI, by doing the inverse beforehand - } - t.SetPixel(0, 0, c); - t.Apply(); - GUIStyle s = new GUIStyle(); - s.normal.background = t; - return s; - } - - String CreateSwatchDescriptionForName(float minLum, float maxLum) - { - return "Luminance (" + minLum.ToString("F2") + " - " + maxLum.ToString("F2") + ")"; - } - - void CreateAlbedoSwatchData() - { - AlbedoSwatchInfo[] graphicsSettingsSwatches = EditorGraphicsSettings.albedoSwatches; - - if (graphicsSettingsSwatches.Length != 0) - { - m_AlbedoSwatchInfos = graphicsSettingsSwatches; - } - else - { - m_AlbedoSwatchInfos = new AlbedoSwatchInfo[] - { - // colors taken from http://www.babelcolor.com/index_htm_files/ColorChecker_RGB_and_spectra.xls - new AlbedoSwatchInfo() - { - name = "Black Acrylic Paint", - color = new Color(56f / 255f, 56f / 255f, 56f / 255f), - minLuminance = 0.03f, - maxLuminance = 0.07f - }, - new AlbedoSwatchInfo() - { - name = "Dark Soil", - color = new Color(85f / 255f, 61f / 255f, 49f / 255f), - minLuminance = 0.05f, - maxLuminance = 0.14f - }, - - new AlbedoSwatchInfo() - { - name = "Worn Asphalt", - color = new Color(91f / 255f, 91f / 255f, 91f / 255f), - minLuminance = 0.10f, - maxLuminance = 0.15f - }, - new AlbedoSwatchInfo() - { - name = "Dry Clay Soil", - color = new Color(137f / 255f, 120f / 255f, 102f / 255f), - minLuminance = 0.15f, - maxLuminance = 0.35f - }, - new AlbedoSwatchInfo() - { - name = "Green Grass", - color = new Color(123f / 255f, 131f / 255f, 74f / 255f), - minLuminance = 0.16f, - maxLuminance = 0.26f - }, - new AlbedoSwatchInfo() - { - name = "Old Concrete", - color = new Color(135f / 255f, 136f / 255f, 131f / 255f), - minLuminance = 0.17f, - maxLuminance = 0.30f - }, - new AlbedoSwatchInfo() - { - name = "Red Clay Tile", - color = new Color(197f / 255f, 125f / 255f, 100f / 255f), - minLuminance = 0.23f, - maxLuminance = 0.33f - }, - new AlbedoSwatchInfo() - { - name = "Dry Sand", - color = new Color(177f / 255f, 167f / 255f, 132f / 255f), - minLuminance = 0.20f, - maxLuminance = 0.45f - }, - new AlbedoSwatchInfo() - { - name = "New Concrete", - color = new Color(185f / 255f, 182f / 255f, 175f / 255f), - minLuminance = 0.32f, - maxLuminance = 0.55f - }, - new AlbedoSwatchInfo() - { - name = "White Acrylic Paint", - color = new Color(227f / 255f, 227f / 255f, 227f / 255f), - minLuminance = 0.75f, - maxLuminance = 0.85f - }, - new AlbedoSwatchInfo() - { - name = "Fresh Snow", - color = new Color(243f / 255f, 243f / 255f, 243f / 255f), - minLuminance = 0.85f, - maxLuminance = 0.95f - }, - new AlbedoSwatchInfo() - { - name = "Blue Sky", - color = new Color(93f / 255f, 123f / 255f, 157f / 255f), - minLuminance = new Color(93f / 255f, 123f / 255f, 157f / 255f).linear.maxColorComponent - 0.05f, - maxLuminance = new Color(93f / 255f, 123f / 255f, 157f / 255f).linear.maxColorComponent + 0.05f - }, - new AlbedoSwatchInfo() - { - name = "Foliage", - color = new Color(91f / 255f, 108f / 255f, 65f / 255f), - minLuminance = new Color(91f / 255f, 108f / 255f, 65f / 255f).linear.maxColorComponent - 0.05f, - maxLuminance = new Color(91f / 255f, 108f / 255f, 65f / 255f).linear.maxColorComponent + 0.05f - }, - }; - } - UpdateAlbedoSwatchGUI(); - } - - void UpdateAlbedoSwatchGUI() - { - m_LastKnownColorSpace = PlayerSettings.colorSpace; - m_AlbedoSwatchColorStyles = new GUIStyle[m_AlbedoSwatchInfos.Length + 1]; - m_AlbedoSwatchGUIContent = new GUIContent[m_AlbedoSwatchInfos.Length + 1]; - m_AlbedoSwatchDescriptions = new String[m_AlbedoSwatchInfos.Length + 1]; - m_AlbedoSwatchLuminanceStrings = new String[m_AlbedoSwatchInfos.Length + 1]; - - m_AlbedoSwatchColorStyles[0] = CreateSwatchStyleForColor(Color.gray); - m_AlbedoSwatchDescriptions[0] = "Default Luminance"; - m_AlbedoSwatchGUIContent[0] = new GUIContent(m_AlbedoSwatchDescriptions[0]); - m_AlbedoSwatchLuminanceStrings[0] = CreateSwatchDescriptionForName(0.012f, 0.9f); - for (int i = 1; i < m_AlbedoSwatchInfos.Length + 1; i++) - { - m_AlbedoSwatchColorStyles[i] = CreateSwatchStyleForColor(m_AlbedoSwatchInfos[i - 1].color); - m_AlbedoSwatchDescriptions[i] = m_AlbedoSwatchInfos[i - 1].name; - m_AlbedoSwatchGUIContent[i] = new GUIContent(m_AlbedoSwatchDescriptions[i]); - m_AlbedoSwatchLuminanceStrings[i] = CreateSwatchDescriptionForName(m_AlbedoSwatchInfos[i - 1].minLuminance, m_AlbedoSwatchInfos[i - 1].maxLuminance); - } - } - - void UpdatePBRColorLegend() - { - m_TooLowColorStyle = CreateSwatchStyleForColor(kSceneViewMaterialValidateLow.Color); - m_TooHighColorStyle = CreateSwatchStyleForColor(kSceneViewMaterialValidateHigh.Color); - m_PureMetalColorStyle = CreateSwatchStyleForColor(kSceneViewMaterialValidatePureMetal.Color); - Shader.SetGlobalColor("unity_MaterialValidateLowColor", kSceneViewMaterialValidateLow.Color.linear); - Shader.SetGlobalColor("unity_MaterialValidateHighColor", kSceneViewMaterialValidateHigh.Color.linear); - Shader.SetGlobalColor("unity_MaterialValidatePureMetalColor", kSceneViewMaterialValidatePureMetal.Color.linear); - } - - void UpdateAlbedoSwatch() - { - Color color = Color.gray; - if (m_SelectedAlbedoSwatchIndex != 0) - { - color = m_AlbedoSwatchInfos[m_SelectedAlbedoSwatchIndex - 1].color; - Shader.SetGlobalFloat("_AlbedoMinLuminance", m_AlbedoSwatchInfos[m_SelectedAlbedoSwatchIndex - 1].minLuminance); - Shader.SetGlobalFloat("_AlbedoMaxLuminance", m_AlbedoSwatchInfos[m_SelectedAlbedoSwatchIndex - 1].maxLuminance); - Shader.SetGlobalFloat("_AlbedoHueTolerance", m_AlbedoSwatchHueTolerance); - Shader.SetGlobalFloat("_AlbedoSaturationTolerance", m_AlbedoSwatchSaturationTolerance); - } - Shader.SetGlobalColor("_AlbedoCompareColor", color.linear); - Shader.SetGlobalInt("_CheckAlbedo", (m_SelectedAlbedoSwatchIndex != 0) ? 1 : 0); - Shader.SetGlobalInt("_CheckPureMetal", m_ValidateTrueMetals ? 1 : 0); - } - - internal void DrawTrueMetalCheckbox() - { - EditorGUI.BeginChangeCheck(); - m_ValidateTrueMetals = EditorGUILayout.ToggleLeft(EditorGUIUtility.TrTextContent("Check Pure Metals", "Check if albedo is black for materials with an average specular color above 0.45"), m_ValidateTrueMetals); - if (EditorGUI.EndChangeCheck()) - { - Shader.SetGlobalInt("_CheckPureMetal", m_ValidateTrueMetals ? 1 : 0); - } - } - - internal void DrawPBRSettingsForScene() - { - if (m_CameraMode.drawMode == DrawCameraMode.ValidateAlbedo) - { - if (PlayerSettings.colorSpace == ColorSpace.Gamma) - { - EditorGUILayout.HelpBox("Albedo Validation doesn't work when Color Space is set to gamma space", MessageType.Warning); - } - - EditorGUIUtility.labelWidth = 140; - - m_SelectedAlbedoSwatchIndex = EditorGUILayout.Popup(EditorGUIUtility.TrTextContent("Luminance Validation:", "Select default luminance validation or validate against a configured albedo swatch"), m_SelectedAlbedoSwatchIndex, m_AlbedoSwatchGUIContent); - EditorGUI.indentLevel++; - using (new EditorGUILayout.HorizontalScope()) - { - EditorGUIUtility.labelWidth = 5; - EditorGUILayout.LabelField(" ", m_AlbedoSwatchColorStyles[m_SelectedAlbedoSwatchIndex]); - EditorGUIUtility.labelWidth = 140; - EditorGUILayout.LabelField(m_AlbedoSwatchLuminanceStrings[m_SelectedAlbedoSwatchIndex]); - } - - UpdateAlbedoSwatch(); - - EditorGUI.indentLevel--; - using (new EditorGUI.DisabledScope(m_SelectedAlbedoSwatchIndex == 0)) - { - EditorGUI.BeginChangeCheck(); - using (new EditorGUI.DisabledScope(m_SelectedAlbedoSwatchIndex == 0)) - { - m_AlbedoSwatchHueTolerance = EditorGUILayout.Slider(EditorGUIUtility.TrTextContent("Hue Tolerance:", "Check that the hue of the albedo value of a material is within the tolerance of the hue of the albedo swatch being validated against"), m_AlbedoSwatchHueTolerance, 0f, 0.5f); - - m_AlbedoSwatchSaturationTolerance = EditorGUILayout.Slider(EditorGUIUtility.TrTextContent("Saturation Tolerance:", "Check that the saturation of the albedo value of a material is within the tolerance of the saturation of the albedo swatch being validated against"), m_AlbedoSwatchSaturationTolerance, 0f, 0.5f); - } - - if (EditorGUI.EndChangeCheck()) - { - UpdateAlbedoSwatch(); - } - } - } - - UpdatePBRColorLegend(); - EditorGUILayout.LabelField("Color Legend:"); - EditorGUI.indentLevel++; - string modeString; - - if (m_CameraMode.drawMode == DrawCameraMode.ValidateAlbedo) - { - modeString = "Luminance"; - } - else - { - modeString = "Specular"; - } - - using (new EditorGUILayout.HorizontalScope()) - { - EditorGUIUtility.labelWidth = 2; - EditorGUILayout.LabelField("", m_TooLowColorStyle); - EditorGUIUtility.labelWidth = 200; - EditorGUILayout.LabelField("Below Minimum " + modeString + " Value"); - } - using (new EditorGUILayout.HorizontalScope()) - { - EditorGUIUtility.labelWidth = 2; - EditorGUILayout.LabelField("", m_TooHighColorStyle); - EditorGUIUtility.labelWidth = 200; - EditorGUILayout.LabelField("Above Maximum " + modeString + " Value"); - } - using (new EditorGUILayout.HorizontalScope()) - { - EditorGUIUtility.labelWidth = 2; - EditorGUILayout.LabelField("", m_PureMetalColorStyle); - EditorGUIUtility.labelWidth = 200; - EditorGUILayout.LabelField("Not A Pure Metal"); - } - } - - internal void PrepareValidationUI() - { - if (m_AlbedoSwatchInfos == null) - CreateAlbedoSwatchData(); - - if (PlayerSettings.colorSpace != m_LastKnownColorSpace) - { - UpdateAlbedoSwatchGUI(); - UpdateAlbedoSwatch(); - } - } - - static void DrawPBRSettings(Object target, SceneView sceneView) - { - sceneView.DrawTrueMetalCheckbox(); - sceneView.DrawPBRSettingsForScene(); - } - - void DrawValidateAlbedoSwatches(SceneView sceneView) - { - if (sceneView.cameraMode.drawMode == DrawCameraMode.ValidateAlbedo || sceneView.cameraMode.drawMode == DrawCameraMode.ValidateMetalSpecular) - { - sceneView.PrepareValidationUI(); - SceneViewOverlay.Window(EditorGUIUtility.TrTextContent("PBR Validation Settings"), DrawPBRSettings, (int)SceneViewOverlay.Ordering.PhysicsDebug, sceneView, SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget); - } - } - - void RepaintGizmosThatAreRenderedOnTopOfSceneView() - { - svRot.OnGUI(this); - } - - void InputForGizmosThatAreRenderedOnTopOfSceneView() - { - if (Event.current.type != EventType.Repaint) - { - svRot.OnGUI(this); - } - } - - internal void OnGUI() - { - s_CurrentDrawingSceneView = this; - - Event evt = Event.current; - if (evt.type == EventType.Repaint) - { - s_MouseRects.Clear(); - Profiler.BeginSample("SceneView.Repaint"); - } - - Color origColor = GUI.color; - Rect origCameraRect = m_Camera.rect; - - HandleClickAndDragToFocus(); - - if (evt.type == EventType.Layout) - m_ShowSceneViewWindows = (lastActiveSceneView == this); - - m_SceneViewOverlay.Begin(); - - bool oldFog; - float oldShadowDistance; - SetupFogAndShadowDistance(out oldFog, out oldShadowDistance); - - DoToolbarGUI(); - GUI.skin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Scene); - - // Don't apply any playmode tinting to scene views - GUI.color = Color.white; - - EditorGUIUtility.labelWidth = 100; - - SetupCamera(); - RenderingPath oldRenderingPath = m_Camera.renderingPath; - if (evt.type == EventType.Repaint) - GL.sRGBWrite = QualitySettings.activeColorSpace == ColorSpace.Linear; - - SetupCustomSceneLighting(); - - GUI.BeginGroup(new Rect(0, EditorGUI.kWindowToolbarHeight, position.width, position.height - EditorGUI.kWindowToolbarHeight)); - Rect guiRect = new Rect(0, 0, position.width, (position.height - EditorGUI.kWindowToolbarHeight)); - Rect cameraRect = EditorGUIUtility.PointsToPixels(guiRect); - - HandleViewToolCursor(); - - PrepareCameraTargetTexture(cameraRect); - DoClearCamera(cameraRect); - - m_Camera.cullingMask = Tools.visibleLayers; - - InputForGizmosThatAreRenderedOnTopOfSceneView(); - - DoOnPreSceneGUICallbacks(cameraRect); - - PrepareCameraReplacementShader(); - - // Unfocus search field on mouse clicks into content, so that key presses work to navigate. - m_MainViewControlID = GUIUtility.GetControlID(FocusType.Keyboard); - if (evt.GetTypeForControl(m_MainViewControlID) == EventType.MouseDown) - GUIUtility.keyboardControl = m_MainViewControlID; - - // Draw camera - bool pushedGUIClip; - DoDrawCamera(guiRect, out pushedGUIClip); - - CleanupCustomSceneLighting(); - - - //Ensure that the target texture is clamped [0-1] - //This is needed because otherwise gizmo rendering gets all - //messed up (think HDR target with value of 50 + alpha blend gizmo... gonna be white!) - if (!UseSceneFiltering() && evt.type == EventType.Repaint && RenderTextureEditor.IsHDRFormat(m_SceneTargetTexture.format)) - { - var rtDesc = m_SceneTargetTexture.descriptor; - rtDesc.colorFormat = RenderTextureFormat.ARGB32; - rtDesc.depthBufferBits = 0; - RenderTexture ldrSceneTargetTexture = RenderTexture.GetTemporary(rtDesc); - Graphics.Blit(m_SceneTargetTexture, ldrSceneTargetTexture); - Graphics.Blit(ldrSceneTargetTexture, m_SceneTargetTexture); - Graphics.SetRenderTarget(m_SceneTargetTexture.colorBuffer, m_SceneTargetTexture.depthBuffer); - RenderTexture.ReleaseTemporary(ldrSceneTargetTexture); - } - - if (!UseSceneFiltering()) - { - // Blit to final target RT in deferred mode - Handles.DrawCameraStep2(m_Camera, m_CameraMode.drawMode); - - // Give editors a chance to kick in. Disable in search mode, editors rendering to the scene - // view won't be able to properly render to the rendertexture as needed. - // Calling OnSceneGUI before DefaultHandles, so users can use events before the Default Handles - HandleSelectionAndOnSceneGUI(); - } - - // Handle commands - if (evt.type == EventType.ExecuteCommand || evt.type == EventType.ValidateCommand) - CommandsGUI(); - - RestoreFogAndShadowDistance(oldFog, oldShadowDistance); - - m_Camera.renderingPath = oldRenderingPath; - - if (UseSceneFiltering()) - Handles.SetCameraFilterMode(Camera.current, Handles.CameraFilterMode.ShowFiltered); - else - Handles.SetCameraFilterMode(Camera.current, Handles.CameraFilterMode.Off); - - // Draw default scene manipulation tools (Move/Rotate/...) - DefaultHandles(); - - if (evt.type == EventType.Repaint) - GL.sRGBWrite = false; - - if (!UseSceneFiltering()) - { - if (evt.type == EventType.Repaint) - { - Profiler.BeginSample("SceneView.BlitRT"); - Graphics.SetRenderTarget(null); - } - // If we reset the offsets pop that clip off now. - if (pushedGUIClip) - GUIClip.Pop(); - if (evt.type == EventType.Repaint) - { - Graphics.DrawTexture(guiRect, m_SceneTargetTexture, new Rect(0, 0, 1, 1), 0, 0, 0, 0, GUI.color, EditorGUIUtility.GUITextureBlit2SRGBMaterial); - Profiler.EndSample(); - } - } - - Handles.SetCameraFilterMode(Camera.current, Handles.CameraFilterMode.Off); - Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.Off); - - // Handle Dragging of stuff over scene view - HandleDragging(); - - RepaintGizmosThatAreRenderedOnTopOfSceneView(); - - // Handle scene view motion when this scene view is active - if (s_LastActiveSceneView == this) - { - // Do not pass the camera transform to the SceneViewMotion calculations. - // The camera transform is calculation *output* not *input*. - // Avoiding using it as input too avoids errors accumulating. - SceneViewMotion.ArrowKeys(this); - SceneViewMotion.DoViewTool(this); - } - - Handle2DModeSwitch(); - - GUI.EndGroup(); - GUI.color = origColor; - - m_SceneViewOverlay.End(); - - HandleMouseCursor(); - - if (evt.type == EventType.Repaint) - { - Profiler.EndSample(); - } - - s_CurrentDrawingSceneView = null; - m_Camera.rect = origCameraRect; - } - - void Handle2DModeSwitch() - { - Event evt = Event.current; - if (k2DMode.activated && !waitingFor2DModeKeyUp) - { - waitingFor2DModeKeyUp = true; - in2DMode = !in2DMode; - evt.Use(); - } - else - { - if (evt.type == EventType.KeyUp && evt.keyCode == k2DMode.KeyboardEvent.keyCode) - waitingFor2DModeKeyUp = false; - } - } - - void HandleMouseCursor() - { - Event evt = Event.current; - if (GUIUtility.hotControl == 0) - s_DraggingCursorIsCached = false; - Rect cursorRect = new Rect(0, 0, position.width, position.height); - if (!s_DraggingCursorIsCached) - { - // Determine if mouse is inside a new cursor rect - MouseCursor cursor = MouseCursor.Arrow; - if (evt.type == EventType.MouseMove || evt.type == EventType.Repaint) - { - foreach (CursorRect r in s_MouseRects) - { - if (r.rect.Contains(evt.mousePosition)) - { - cursor = r.cursor; - cursorRect = r.rect; - } - } - if (GUIUtility.hotControl != 0) - s_DraggingCursorIsCached = true; - if (cursor != s_LastCursor) - { - s_LastCursor = cursor; - InternalEditorUtility.ResetCursor(); - Repaint(); - } - } - } - // Apply the one relevant cursor rect - if (evt.type == EventType.Repaint && s_LastCursor != MouseCursor.Arrow) - { - EditorGUIUtility.AddCursorRect(cursorRect, s_LastCursor); - // GUI.color = Color.magenta; GUI.Box (rect, ""); EditorGUI.DropShadowLabel (rect, ""+s_LastCursor); GUI.color = Color.white; - } - } - - void DrawRenderModeOverlay(Rect cameraRect) - { - // show destination alpha channel - if (m_CameraMode.drawMode == DrawCameraMode.AlphaChannel) - { - if (!s_AlphaOverlayMaterial) - s_AlphaOverlayMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewAlphaMaterial.mat") as Material; - Handles.BeginGUI(); - if (Event.current.type == EventType.Repaint) - Graphics.DrawTexture(cameraRect, EditorGUIUtility.whiteTexture, s_AlphaOverlayMaterial); - Handles.EndGUI(); - } - - // show one of deferred buffers - if (m_CameraMode.drawMode == DrawCameraMode.DeferredDiffuse || - m_CameraMode.drawMode == DrawCameraMode.DeferredSpecular || - m_CameraMode.drawMode == DrawCameraMode.DeferredSmoothness || - m_CameraMode.drawMode == DrawCameraMode.DeferredNormal) - { - if (!s_DeferredOverlayMaterial) - s_DeferredOverlayMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewDeferredMaterial.mat") as Material; - Handles.BeginGUI(); - if (Event.current.type == EventType.Repaint) - { - s_DeferredOverlayMaterial.SetInt("_DisplayMode", (int)m_CameraMode.drawMode - (int)DrawCameraMode.DeferredDiffuse); - Graphics.DrawTexture(cameraRect, EditorGUIUtility.whiteTexture, s_DeferredOverlayMaterial); - } - Handles.EndGUI(); - } - } - - private void HandleSelectionAndOnSceneGUI() - { - m_RectSelection.OnGUI(); - CallOnSceneGUI(); - } - - /// Center point of the scene view. Modify it to move the sceneview immediately, or use LookAt to animate it nicely. - public Vector3 pivot { get { return m_Position.value; } set { m_Position.value = value; } } - - /// The direction of the scene view. - public Quaternion rotation { get { return m_Rotation.value; } set { m_Rotation.value = value; } } - - public float size - { - get { return m_Size.value; } - set - { - if (value > 40000f) - value = 40000; - m_Size.value = value; - } - } - - - /// Is the scene view ortho. - public bool orthographic - { - get { return m_Ortho.value; } - set - { - m_Ortho.value = value; - svRot.UpdateGizmoLabel(this, m_Rotation.target * Vector3.forward, m_Ortho.target); - } - } - - public void FixNegativeSize() - { - float fov = kPerspectiveFov; - if (size < 0) - { - float distance = size / Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad); - Vector3 p = m_Position.value + rotation * new Vector3(0, 0, -distance); - size = -size; - distance = size / Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad); - m_Position.value = p + rotation * new Vector3(0, 0, distance); - } - } - - float CalcCameraDist() - { - float fov = m_Ortho.Fade(kPerspectiveFov, 0); - if (fov > kOrthoThresholdAngle) - { - m_Camera.orthographic = false; - return size / Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad); - } - return 0; - } - - void ResetIfNaN() - { - // If you zoom out enough, m_Position would get corrupted with no way to reset it, - // even after restarting Unity. Crude hack to at least get the scene view working again! - if (Single.IsInfinity(m_Position.value.x) || Single.IsNaN(m_Position.value.x)) - m_Position.value = Vector3.zero; - if (Single.IsInfinity(m_Rotation.value.x) || Single.IsNaN(m_Rotation.value.x)) - m_Rotation.value = Quaternion.identity; - } - - static internal Camera GetMainCamera() - { - // main camera, if we have any - var mainCamera = Camera.main; - if (mainCamera != null) - return mainCamera; - - // if we have one camera, return it - Camera[] allCameras = Camera.allCameras; - if (allCameras != null && allCameras.Length == 1) - return allCameras[0]; - - // otherwise no "main" camera - return null; - } - - // Note: this can return "use player settings" value too! - // In order to check things like "is using deferred", use IsUsingDeferredRenderingPath - static internal RenderingPath GetSceneViewRenderingPath() - { - var mainCamera = GetMainCamera(); - if (mainCamera != null) - return mainCamera.renderingPath; - return RenderingPath.UsePlayerSettings; - } - - static internal bool IsUsingDeferredRenderingPath() - { - RenderingPath renderingPath = GetSceneViewRenderingPath(); - return (renderingPath == RenderingPath.DeferredShading) || - (renderingPath == RenderingPath.UsePlayerSettings && Rendering.EditorGraphicsSettings.GetCurrentTierSettings().renderingPath == RenderingPath.DeferredShading); - } - - internal bool CheckDrawModeForRenderingPath(DrawCameraMode mode) - { - RenderingPath path = m_Camera.actualRenderingPath; - if (mode == DrawCameraMode.DeferredDiffuse || - mode == DrawCameraMode.DeferredSpecular || - mode == DrawCameraMode.DeferredSmoothness || - mode == DrawCameraMode.DeferredNormal) - { - return path == RenderingPath.DeferredShading; - } - return true; - } - - private void SetSceneCameraHDRAndDepthModes() - { - if (!m_SceneLighting || !DoesCameraDrawModeSupportHDR(m_CameraMode.drawMode)) - { - m_Camera.allowHDR = false; - m_Camera.depthTextureMode = DepthTextureMode.None; - m_Camera.clearStencilAfterLightingPass = false; - return; - } - var mainCamera = GetMainCamera(); - if (mainCamera == null) - { - m_Camera.allowHDR = false; - m_Camera.depthTextureMode = DepthTextureMode.None; - m_Camera.clearStencilAfterLightingPass = false; - return; - } - m_Camera.allowHDR = mainCamera.allowHDR; - m_Camera.depthTextureMode = mainCamera.depthTextureMode; - m_Camera.clearStencilAfterLightingPass = mainCamera.clearStencilAfterLightingPass; - } - - void SetupCamera() - { - if (m_CameraMode.drawMode == DrawCameraMode.Overdraw) - { - // overdraw - m_Camera.backgroundColor = Color.black; - } - else - { - m_Camera.backgroundColor = kSceneViewBackground; - } - - if (Event.current.type == EventType.Repaint) - { - bool enableImageEffects = false; - if (!UseSceneFiltering()) - enableImageEffects = m_CameraMode.drawMode == DrawCameraMode.Textured && sceneViewState.showImageEffects; - UpdateImageEffects(enableImageEffects); - } - - EditorUtility.SetCameraAnimateMaterials(m_Camera, sceneViewState.showMaterialUpdate); - ParticleSystemEditorUtils.renderInSceneView = m_SceneViewState.showParticleSystems; - - ResetIfNaN(); - - m_Camera.transform.rotation = m_Rotation.value; - - float fov = m_Ortho.Fade(kPerspectiveFov, 0); - if (fov > kOrthoThresholdAngle) - { - m_Camera.orthographic = false; - - // Old calculations were strange and were more zoomed in for tall aspect ratios than for wide ones. - //m_Camera.fieldOfView = Mathf.Sqrt((fov * fov) / (1 + aspect)); - // 1:1: Sqrt((90*90) / (1+1)) = 63.63 degrees = atan(0.6204) - means we have 0.6204 x 0.6204 in tangents - // 2:1: Sqrt((90*90) / (1+2)) = 51.96 degrees = atan(0.4873) - means we have 0.9746 x 0.4873 in tangents - // 1:2: Sqrt((90*90) / (1+0.5)) = 73.48 degrees = atan(0.7465) - means we have 0.3732 x 0.7465 in tangents - 25% more zoomed in! - - m_Camera.fieldOfView = GetVerticalFOV(fov); - } - else - { - m_Camera.orthographic = true; - - //m_Camera.orthographicSize = Mathf.Sqrt((size * size) / (1 + aspect)); - m_Camera.orthographicSize = GetVerticalOrthoSize(); - } - m_Camera.transform.position = m_Position.value + m_Camera.transform.rotation * new Vector3(0, 0, -cameraDistance); - - float farClip = Mathf.Max(1000f, 2000f * size); - m_Camera.nearClipPlane = farClip * 0.000005f; - m_Camera.farClipPlane = farClip; - - m_Camera.renderingPath = GetSceneViewRenderingPath(); - if (!CheckDrawModeForRenderingPath(m_CameraMode.drawMode)) - m_CameraMode = GetBuiltinCameraMode(DrawCameraMode.Textured); - SetSceneCameraHDRAndDepthModes(); - - if (m_CameraMode.drawMode == DrawCameraMode.Textured || - m_CameraMode.drawMode == DrawCameraMode.TexturedWire || - m_CameraMode.drawMode == DrawCameraMode.UserDefined) - { - Handles.EnableCameraFlares(m_Camera, sceneViewState.showFlares); - Handles.EnableCameraSkybox(m_Camera, sceneViewState.showSkybox); - } - else - { - Handles.EnableCameraFlares(m_Camera, false); - Handles.EnableCameraSkybox(m_Camera, false); - } - - // Update the light - m_Light[0].transform.position = m_Camera.transform.position; - m_Light[0].transform.rotation = m_Camera.transform.rotation; - - // Update audio engine - if (m_AudioPlay) - { - AudioUtil.SetListenerTransform(m_Camera.transform); - AudioUtil.UpdateAudio(); - } - - if (m_ViewIsLockedToObject && Selection.gameObjects.Length > 0) - { - var bounds = InternalEditorUtility.CalculateSelectionBounds(false, Tools.pivotMode == PivotMode.Pivot); - switch (draggingLocked) - { - case (DraggingLockedState.Dragging): - // While dragging via handles, we don't want to move the camera - break; - case (DraggingLockedState.LookAt): - if (!m_Position.value.Equals(m_Position.target)) - Frame(bounds, EditorApplication.isPlaying); - else - draggingLocked = DraggingLockedState.NotDragging; - break; - case (DraggingLockedState.NotDragging): - // Once framed, we only need to lock position rather than all the parameters Frame() sets - m_Position.value = bounds.center; - break; - } - } - } - - void OnBecameVisible() - { - EditorApplication.update += UpdateAnimatedMaterials; - } - - void OnBecameInvisible() - { - EditorApplication.update -= UpdateAnimatedMaterials; - } - - void UpdateAnimatedMaterials() - { - if (sceneViewState.showMaterialUpdate && m_lastRenderedTime + 0.033f < EditorApplication.timeSinceStartup) - { - m_lastRenderedTime = EditorApplication.timeSinceStartup; - Repaint(); - } - } - - internal Quaternion cameraTargetRotation { get { return m_Rotation.target; } } - - internal Vector3 cameraTargetPosition { get { return m_Position.target + m_Rotation.target * new Vector3(0, 0, cameraDistance); } } - - internal float GetVerticalFOV(float aspectNeutralFOV) - { - float verticalHalfFovTangent = Mathf.Tan(aspectNeutralFOV * 0.5f * Mathf.Deg2Rad) * kOneOverSqrt2 / Mathf.Sqrt(m_Camera.aspect); - return Mathf.Atan(verticalHalfFovTangent) * 2 * Mathf.Rad2Deg; - } - - internal float GetVerticalOrthoSize() - { - return size * kOneOverSqrt2 / Mathf.Sqrt(m_Camera.aspect); - } - - // Look at a specific point. - public void LookAt(Vector3 pos) - { - FixNegativeSize(); - m_Position.target = pos; - } - - // Look at a specific point from a given direction. - public void LookAt(Vector3 pos, Quaternion rot) - { - FixNegativeSize(); - m_Position.target = pos; - m_Rotation.target = rot; - // Update name in the top-right handle - svRot.UpdateGizmoLabel(this, rot * Vector3.forward, m_Ortho.target); - } - - // Look directly at a specific point from a given direction. - public void LookAtDirect(Vector3 pos, Quaternion rot) - { - FixNegativeSize(); - m_Position.value = pos; - m_Rotation.value = rot; - // Update name in the top-right handle - svRot.UpdateGizmoLabel(this, rot * Vector3.forward, m_Ortho.target); - } - - // Look at a specific point from a given direction with a given zoom level. - public void LookAt(Vector3 pos, Quaternion rot, float newSize) - { - FixNegativeSize(); - m_Position.target = pos; - m_Rotation.target = rot; - m_Size.target = Mathf.Abs(newSize); - // Update name in the top-right handle - svRot.UpdateGizmoLabel(this, rot * Vector3.forward, m_Ortho.target); - } - - // Look directally at a specific point from a given direction with a given zoom level. - public void LookAtDirect(Vector3 pos, Quaternion rot, float newSize) - { - FixNegativeSize(); - m_Position.value = pos; - m_Rotation.value = rot; - m_Size.value = Mathf.Abs(newSize); - // Update name in the top-right handle - svRot.UpdateGizmoLabel(this, rot * Vector3.forward, m_Ortho.target); - } - - // Look at a specific point from a given direction with a given zoom level, enabling and disabling perspective - public void LookAt(Vector3 pos, Quaternion rot, float newSize, bool ortho) - { - LookAt(pos, rot, newSize, ortho, false); - } - - // Look at a specific point from a given direction with a given zoom level, enabling and disabling perspective - public void LookAt(Vector3 pos, Quaternion rot, float newSize, bool ortho, bool instant) - { - FixNegativeSize(); - if (instant) - { - m_Position.value = pos; - m_Rotation.value = rot; - m_Size.value = Mathf.Abs(newSize); - m_Ortho.value = ortho; - draggingLocked = DraggingLockedState.NotDragging; - } - else - { - m_Position.target = pos; - m_Rotation.target = rot; - m_Size.target = Mathf.Abs(newSize); - m_Ortho.target = ortho; - } - // Update name in the top-right handle - svRot.UpdateGizmoLabel(this, rot * Vector3.forward, m_Ortho.target); - } - - void DefaultHandles() - { - // Note event state. - EditorGUI.BeginChangeCheck(); - bool IsDragEvent = Event.current.GetTypeForControl(GUIUtility.hotControl) == EventType.MouseDrag; - bool IsMouseUpEvent = Event.current.GetTypeForControl(GUIUtility.hotControl) == EventType.MouseUp; - - // Only switch tools when we don't have a hot control. - if (GUIUtility.hotControl == 0) - s_CurrentTool = Tools.viewToolActive ? 0 : Tools.current; - - Tool tool = (Event.current.type == EventType.Repaint ? Tools.current : s_CurrentTool); - - switch (tool) - { - case Tool.None: - case Tool.View: - break; - case Tool.Move: - MoveTool.OnGUI(this); - break; - case Tool.Rotate: - RotateTool.OnGUI(this); - break; - case Tool.Scale: - ScaleTool.OnGUI(this); - break; - case Tool.Rect: - RectTool.OnGUI(this); - break; - case Tool.Transform: - TransformTool.OnGUI(this); - break; - } - - // If we are actually dragging the object(s) then disable 2D physics movement. - if (EditorGUI.EndChangeCheck() && EditorApplication.isPlaying && IsDragEvent) - Physics2D.SetEditorDragMovement(true, Selection.gameObjects); - - // If we have finished dragging the object(s) then enable 2D physics movement. - if (EditorApplication.isPlaying && IsMouseUpEvent) - Physics2D.SetEditorDragMovement(false, Selection.gameObjects); - } - - void CleanupEditorDragFunctions() - { - if (m_DragEditorCache != null) - m_DragEditorCache.Dispose(); - m_DragEditorCache = null; - } - - void CallEditorDragFunctions() - { - Event evt = Event.current; - - SpriteUtility.OnSceneDrag(this); - - if (evt.type == EventType.Used) - return; - - if (DragAndDrop.objectReferences.Length == 0) - return; - - if (m_DragEditorCache == null) - m_DragEditorCache = new EditorCache(EditorFeatures.OnSceneDrag); - - foreach (Object o in DragAndDrop.objectReferences) - { - if (o == null) - continue; - - EditorWrapper w = m_DragEditorCache[o]; - if (w != null) - w.OnSceneDrag(this); - - if (evt.type == EventType.Used) - return; - } - } - - void HandleDragging() - { - Event evt = Event.current; - - switch (evt.type) - { - case EventType.DragPerform: - case EventType.DragUpdated: - CallEditorDragFunctions(); - - if (evt.type == EventType.Used) - break; - - bool isPerform = evt.type == EventType.DragPerform; - // call old-style C++ dragging handlers - if (DragAndDrop.visualMode != DragAndDropVisualMode.Copy) - { - GameObject go = HandleUtility.PickGameObject(Event.current.mousePosition, true); - DragAndDrop.visualMode = InternalEditorUtility.SceneViewDrag(go, pivot, Event.current.mousePosition, isPerform); - } - - if (isPerform && DragAndDrop.visualMode != DragAndDropVisualMode.None) - { - DragAndDrop.AcceptDrag(); - evt.Use(); - // Bail out as state can be messed up by now. - GUIUtility.ExitGUI(); - } - - evt.Use(); - break; - case EventType.DragExited: - CallEditorDragFunctions(); - CleanupEditorDragFunctions(); - break; - } - } - - void CommandsGUI() - { - // @TODO: Validation should be more accurate based on what the view supports - - bool execute = Event.current.type == EventType.ExecuteCommand; - switch (Event.current.commandName) - { - case EventCommandNames.Find: - if (execute) - FocusSearchField(); - Event.current.Use(); - break; - case EventCommandNames.FrameSelected: - if (execute) - { - bool useLocking = EditorApplication.timeSinceStartup - lastFramingTime < k_MaxDoubleKeypressTime; - - FrameSelected(useLocking); - - lastFramingTime = EditorApplication.timeSinceStartup; - } - Event.current.Use(); - break; - case EventCommandNames.FrameSelectedWithLock: - if (execute) - FrameSelected(true); - Event.current.Use(); - break; - case EventCommandNames.SoftDelete: - case EventCommandNames.Delete: - if (execute) - Unsupported.DeleteGameObjectSelection(); - Event.current.Use(); - break; - case EventCommandNames.Duplicate: - if (execute) - Unsupported.DuplicateGameObjectsUsingPasteboard(); - Event.current.Use(); - break; - case EventCommandNames.Copy: - if (execute) - Unsupported.CopyGameObjectsToPasteboard(); - Event.current.Use(); - break; - case EventCommandNames.Paste: - if (execute) - Unsupported.PasteGameObjectsFromPasteboard(); - Event.current.Use(); - break; - case EventCommandNames.SelectAll: - if (execute) - Selection.objects = FindObjectsOfType(typeof(GameObject)); - Event.current.Use(); - break; - } - } - - public void AlignViewToObject(Transform t) - { - FixNegativeSize(); - size = 10; - LookAt(t.position + t.forward * CalcCameraDist(), t.rotation); - } - - public void AlignWithView() - { - FixNegativeSize(); - Vector3 center = camera.transform.position; - Vector3 dif = center - Tools.handlePosition; - Quaternion delta = Quaternion.Inverse(Selection.activeTransform.rotation) * camera.transform.rotation; - float angle; - Vector3 axis; - delta.ToAngleAxis(out angle, out axis); - axis = Selection.activeTransform.TransformDirection(axis); - - Undo.RecordObjects(Selection.transforms, "Align with view"); - - foreach (Transform t in Selection.transforms) - { - t.position += dif; - t.RotateAround(center, axis, angle); - } - } - - public void MoveToView() - { - FixNegativeSize(); - Vector3 dif = pivot - Tools.handlePosition; - - Undo.RecordObjects(Selection.transforms, "Move to view"); - - foreach (Transform t in Selection.transforms) - { - t.position += dif; - } - } - - public void MoveToView(Transform target) - { - target.position = pivot; - } - - public bool FrameSelected() - { - return FrameSelected(false); - } - - public bool FrameSelected(bool lockView) - { - viewIsLockedToObject = lockView; - FixNegativeSize(); - - Bounds bounds = InternalEditorUtility.CalculateSelectionBounds(false, Tools.pivotMode == PivotMode.Pivot); - - // Check active editor for OnGetFrameBounds - foreach (Editor editor in GetActiveEditors()) - { - MethodInfo hasBoundsMethod = editor.GetType().GetMethod("HasFrameBounds", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); - - if (hasBoundsMethod != null) - { - object hasBounds = hasBoundsMethod.Invoke(editor, null); - if (hasBounds is bool && (bool)hasBounds) - { - MethodInfo getBoundsMethod = editor.GetType().GetMethod("OnGetFrameBounds", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); - - if (getBoundsMethod != null) - { - object obj = getBoundsMethod.Invoke(editor, null); - if (obj is Bounds) - bounds = (Bounds)obj; - } - } - } - } - - return Frame(bounds, EditorApplication.isPlaying); - } - - public bool Frame(Bounds bounds, bool instant = true) - { - float newSize = bounds.extents.magnitude * 1.5f; - if (newSize == Mathf.Infinity) - return false; - if (newSize == 0) - newSize = 10; - - // We snap instantly into target on playmode, because things might be moving fast and lerping lags behind - LookAt(bounds.center, m_Rotation.target, newSize * 2.2f, m_Ortho.value, instant); - - return true; - } - - void CreateSceneCameraAndLights() - { - GameObject cameraGO = EditorUtility.CreateGameObjectWithHideFlags("SceneCamera", HideFlags.HideAndDontSave, typeof(Camera)); - cameraGO.AddComponentInternal("FlareLayer"); - cameraGO.AddComponentInternal("HaloLayer"); - - m_Camera = cameraGO.GetComponent(); - m_Camera.enabled = false; - m_Camera.cameraType = CameraType.SceneView; - - for (int i = 0; i < 3; i++) - { - GameObject lightGO = EditorUtility.CreateGameObjectWithHideFlags("SceneLight", HideFlags.HideAndDontSave, typeof(Light)); - m_Light[i] = lightGO.GetComponent(); - m_Light[i].type = LightType.Directional; - m_Light[i].intensity = 1.0f; - m_Light[i].enabled = false; - } - m_Light[0].color = kSceneViewFrontLight; - - m_Light[1].color = kSceneViewUpLight - kSceneViewMidLight; - m_Light[1].transform.LookAt(Vector3.down); - m_Light[1].renderMode = LightRenderMode.ForceVertex; - - m_Light[2].color = kSceneViewDownLight - kSceneViewMidLight; - m_Light[2].transform.LookAt(Vector3.up); - m_Light[2].renderMode = LightRenderMode.ForceVertex; - - HandleUtility.handleMaterial.SetColor("_SkyColor", kSceneViewUpLight * 1.5f); - HandleUtility.handleMaterial.SetColor("_GroundColor", kSceneViewDownLight * 1.5f); - HandleUtility.handleMaterial.SetColor("_Color", kSceneViewFrontLight * 1.5f); - - SetupPBRValidation(); - } - - void CallOnSceneGUI() - { - foreach (Editor editor in GetActiveEditors()) - { - if (!EditorGUIUtility.IsGizmosAllowedForObject(editor.target)) - continue; - /* - // Don't call function for editors whose target's GameObject is not active. - Component comp = editor.target as Component; - if (comp && !comp.gameObject.activeInHierarchy) - continue; - - // No gizmo if component state is disabled - if (!InternalEditorUtility.GetIsInspectorExpanded(comp)) - continue; - * */ - - MethodInfo method = editor.GetType().GetMethod("OnSceneGUI", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); - - if (method != null) - { - Editor.m_AllowMultiObjectAccess = true; - for (int n = 0; n < editor.targets.Length; n++) - { - ResetOnSceneGUIState(); - editor.referenceTargetIndex = n; - - EditorGUI.BeginChangeCheck(); - // Ironically, only allow multi object access inside OnSceneGUI if editor does NOT support multi-object editing. - // since there's no harm in going through the serializedObject there if there's always only one target. - Editor.m_AllowMultiObjectAccess = !editor.canEditMultipleObjects; - method.Invoke(editor, null); - Editor.m_AllowMultiObjectAccess = true; - if (EditorGUI.EndChangeCheck()) - editor.serializedObject.SetIsDifferentCacheDirty(); - } - ResetOnSceneGUIState(); - } - } - - if (onSceneGUIDelegate != null) - { - onSceneGUIDelegate(this); - ResetOnSceneGUIState(); - } - } - - void ResetOnSceneGUIState() - { - Handles.ClearHandles(); - HandleUtility.s_CustomPickDistance = HandleUtility.kPickDistance; - EditorGUIUtility.ResetGUIState(); - - // Don't apply any playmode tinting to scene views - GUI.color = Color.white; - } - - void CallOnPreSceneGUI() - { - foreach (Editor editor in GetActiveEditors()) - { - // reset the handles matrix, OnPreSceneGUI calls may change it. - Handles.ClearHandles(); - - // Don't call function for editors whose target's GameObject is not active. - Component comp = editor.target as Component; - if (comp && !comp.gameObject.activeInHierarchy) - continue; - - MethodInfo method = editor.GetType().GetMethod("OnPreSceneGUI", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy); - - if (method != null) - { - Editor.m_AllowMultiObjectAccess = true; - for (int n = 0; n < editor.targets.Length; n++) - { - editor.referenceTargetIndex = n; - // Ironically, only allow multi object access inside OnPreSceneGUI if editor does NOT support multi-object editing. - // since there's no harm in going through the serializedObject there if there's always only one target. - Editor.m_AllowMultiObjectAccess = !editor.canEditMultipleObjects; - method.Invoke(editor, null); - Editor.m_AllowMultiObjectAccess = true; - } - } - } - - if (onPreSceneGUIDelegate != null) - { - onPreSceneGUIDelegate(this); - } - - // reset the handles matrix, calls above calls might have changed it - Handles.ClearHandles(); - } - - internal static void ShowNotification(string notificationText) - { - Object[] allSceneViews = Resources.FindObjectsOfTypeAll(typeof(SceneView)); - var notificationViews = new List(); - foreach (SceneView sceneView in allSceneViews) - { - if (sceneView.m_Parent is DockArea) - { - var dock = (DockArea)sceneView.m_Parent; - if (dock) - { - if (dock.actualView == sceneView) - { - notificationViews.Add(sceneView); - } - } - } - } - - if (notificationViews.Count > 0) - { - foreach (EditorWindow notificationView in notificationViews) - notificationView.ShowNotification(GUIContent.Temp(notificationText)); - } - else - { - Debug.LogError(notificationText); - } - } - - public static void ShowCompileErrorNotification() - { - ShowNotification("All compiler errors have to be fixed before you can enter playmode!"); - } - - internal static void ShowSceneViewPlayModeSaveWarning() - { - // In this case, we wan't to explicitely try the GameView before passing it on to whatever notificationView we have - var gameView = (GameView)WindowLayout.FindEditorWindowOfType(typeof(GameView)); - if (gameView != null && gameView.hasFocus) - gameView.ShowNotification(EditorGUIUtility.TrTextContent("You must exit play mode to save the scene!")); - else - ShowNotification("You must exit play mode to save the scene!"); - } - - void ResetToDefaults(EditorBehaviorMode behaviorMode) - { - switch (behaviorMode) - { - case EditorBehaviorMode.Mode2D: - m_2DMode = true; - m_Rotation.value = Quaternion.identity; - m_Position.value = kDefaultPivot; - m_Size.value = kDefaultViewSize; - m_Ortho.value = true; - - m_LastSceneViewRotation = kDefaultRotation; - m_LastSceneViewOrtho = false; - break; - - default: // Default to 3D mode (BUGFIX:569204) - case EditorBehaviorMode.Mode3D: - m_2DMode = false; - m_Rotation.value = kDefaultRotation; - m_Position.value = kDefaultPivot; - m_Size.value = kDefaultViewSize; - m_Ortho.value = false; - break; - } - } - - internal void OnNewProjectLayoutWasCreated() - { - ResetToDefaults(EditorSettings.defaultBehaviorMode); - } - - private void On2DModeChange() - { - if (m_2DMode) - { - lastSceneViewRotation = rotation; - m_LastSceneViewOrtho = orthographic; - LookAt(pivot, Quaternion.identity, size, true); - if (Tools.current == Tool.Move) - Tools.current = Tool.Rect; - } - else - { - LookAt(pivot, lastSceneViewRotation, size, m_LastSceneViewOrtho); - if (Tools.current == Tool.Rect) - Tools.current = Tool.Move; - } - - // Let's not persist the vertex snapping mode on 2D/3D mode change - HandleUtility.ignoreRaySnapObjects = null; - Tools.vertexDragging = false; - Tools.handleOffset = Vector3.zero; - } - - public static CameraMode AddCameraMode(string name, string section) - { - if (string.IsNullOrEmpty(name)) - throw new ArgumentException("Cannot be null or empty", "name"); - if (string.IsNullOrEmpty(section)) - throw new ArgumentException("Cannot be null or empty", "section"); - var newMode = new CameraMode(DrawCameraMode.UserDefined, name, section); - if (s_UserDefinedModes.Contains(newMode)) - throw new InvalidOperationException(string.Format("A mode named {0} already exists in section {1}", name, section)); - s_UserDefinedModes.Add(newMode); - return newMode; - } - - public static void ClearUserDefinedCameraModes() - { - s_UserDefinedModes.Clear(); - } - - public static CameraMode GetBuiltinCameraMode(DrawCameraMode cameraMode) - { - return SceneRenderModeWindow.GetBuiltinCameraMode(cameraMode); - } - } -} // namespace diff --git a/Editor/Mono/SceneView/SceneViewGrid.cs b/Editor/Mono/SceneView/SceneViewGrid.cs deleted file mode 100644 index 60ff07941e..0000000000 --- a/Editor/Mono/SceneView/SceneViewGrid.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEngine; -using UnityEditor; -using System.Collections; - -namespace UnityEditor -{ - [System.Serializable] - internal class SceneViewGrid - { - static PrefColor kViewGridColor = new PrefColor("Scene/Grid", .5f, .5f, .5f, .4f); - - public void Register(SceneView source) - { - // hook up the anims, so repainting can work correctly - xGrid.valueChanged.AddListener(source.Repaint); - yGrid.valueChanged.AddListener(source.Repaint); - zGrid.valueChanged.AddListener(source.Repaint); - } - - [SerializeField] - AnimBool xGrid = new AnimBool(); - [SerializeField] - AnimBool yGrid = new AnimBool(); - [SerializeField] - AnimBool zGrid = new AnimBool(); - - public DrawGridParameters PrepareGridRender(Camera camera, Vector3 pivot, Quaternion rotation, - float size, bool orthoMode, bool gridVisible - ) - { - bool _xGrid = false, _yGrid = false, _zGrid = false; - if (gridVisible) - { - if (orthoMode) - { - Vector3 fwd = rotation * Vector3.forward; - // Show horizontal grid as long as angle is not too small - if (Mathf.Abs(fwd.y) > 0.2f) - _yGrid = true; - // Show xy and zy planes only when straight on - else if (fwd == Vector3.left || fwd == Vector3.right) - _xGrid = true; - else if (fwd == Vector3.forward || fwd == Vector3.back) - _zGrid = true; - } - else - { - _yGrid = true; - } - } - - xGrid.target = _xGrid; - yGrid.target = _yGrid; - zGrid.target = _zGrid; - - DrawGridParameters parameters; - parameters.pivot = pivot; - parameters.color = kViewGridColor; - parameters.size = size; - parameters.alphaX = xGrid.faded; - parameters.alphaY = yGrid.faded; - parameters.alphaZ = zGrid.faded; - - - return parameters; - } - } -} // namespace diff --git a/Editor/Mono/SceneView/SceneViewMotion.cs b/Editor/Mono/SceneView/SceneViewMotion.cs deleted file mode 100644 index fcb1ba1ba1..0000000000 --- a/Editor/Mono/SceneView/SceneViewMotion.cs +++ /dev/null @@ -1,1143 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.AnimatedValues; -using UnityEngine; -using UnityEngine.Profiling; - -namespace UnityEditor -{ - internal class SceneViewMotion - { - static Vector3 s_Motion; - static float s_FlySpeed = 0; - const float kFlyAcceleration = 1.8f; - static float s_StartZoom = 0, s_ZoomSpeed = 0f; - static float s_TotalMotion = 0; - - enum MotionState - { - kInactive, - kActive, - kDragging - } - private static MotionState s_CurrentState; - - static int s_ViewToolID = GUIUtility.GetPermanentControlID(); - - static PrefKey kFPSForward = new PrefKey("View/FPS Forward", "w"); - static PrefKey kFPSBack = new PrefKey("View/FPS Back", "s"); - static PrefKey kFPSLeft = new PrefKey("View/FPS Strafe Left", "a"); - static PrefKey kFPSRight = new PrefKey("View/FPS Strafe Right", "d"); - static PrefKey kFPSUp = new PrefKey("View/FPS Strafe Up", "e"); - static PrefKey kFPSDown = new PrefKey("View/FPS Strafe Down", "q"); - - static TimeHelper s_FPSTiming = new TimeHelper(); - - // CURSOR KEYS - public static void ArrowKeys(SceneView sv) - { - Event evt = Event.current; - int id = GUIUtility.GetControlID(FocusType.Passive); - if (GUIUtility.hotControl == 0 || GUIUtility.hotControl == id) - { - if (EditorGUI.actionKey) - return; - switch (evt.GetTypeForControl(id)) - { - case EventType.KeyDown: - switch (evt.keyCode) - { - case KeyCode.UpArrow: - sv.viewIsLockedToObject = false; - if (sv.m_Ortho.value) - s_Motion.y = 1; - else - s_Motion.z = 1; - GUIUtility.hotControl = id; - evt.Use(); - break; - case KeyCode.DownArrow: - sv.viewIsLockedToObject = false; - if (sv.m_Ortho.value) - s_Motion.y = -1; - else - s_Motion.z = -1; - GUIUtility.hotControl = id; - evt.Use(); - break; - case KeyCode.LeftArrow: - sv.viewIsLockedToObject = false; - s_Motion.x = -1; - GUIUtility.hotControl = id; - evt.Use(); - break; - case KeyCode.RightArrow: - sv.viewIsLockedToObject = false; - s_Motion.x = 1; - GUIUtility.hotControl = id; - evt.Use(); - break; - } - break; - - case EventType.KeyUp: - if (GUIUtility.hotControl == id) - { - switch (evt.keyCode) - { - case KeyCode.UpArrow: - case KeyCode.DownArrow: - s_Motion.z = 0; - s_Motion.y = 0; - evt.Use(); - break; - case KeyCode.LeftArrow: - case KeyCode.RightArrow: - s_Motion.x = 0; - evt.Use(); - break; - } - } - - break; - - case EventType.Layout: - if (GUIUtility.hotControl == id) - { - Vector3 fwd; - if (!sv.m_Ortho.value) - { - fwd = Camera.current.transform.forward + Camera.current.transform.up * .3f; - fwd.y = 0; - fwd.Normalize(); - } - else - { - fwd = Camera.current.transform.forward; - } - Vector3 motion = GetMovementDirection(); - sv.LookAtDirect(sv.pivot + Quaternion.LookRotation(fwd) * motion, sv.rotation); - - // If we're done, stop animating - if (s_Motion.sqrMagnitude == 0) - { - sv.pivot = sv.pivot; - s_FlySpeed = 0; - GUIUtility.hotControl = 0; - } - else - { - sv.Repaint(); - } - } - break; - } - } - } - - // HANDLE THE VIEW TOOL & ALT COMBOS - public static void DoViewTool(SceneView view) - { - Event evt = Event.current; - - // Ensure we always call the GetControlID the same number of times - int id = s_ViewToolID; - - EventType eventType = evt.GetTypeForControl(id); - - // In FPS mode we update the pivot for Orbit mode (see below and inside HandleMouseDrag) - if (view && Tools.s_LockedViewTool == ViewTool.FPS) - { - view.FixNegativeSize(); - } - - switch (eventType) - { - case EventType.ScrollWheel: HandleScrollWheel(view, view.in2DMode == evt.alt); break; // Default to zooming to mouse position in 2D mode without alt - case EventType.MouseDown: HandleMouseDown(view, id, evt.button); break; - case EventType.MouseUp: HandleMouseUp(view, id, evt.button, evt.clickCount); break; - case EventType.MouseDrag: HandleMouseDrag(view, id); break; - case EventType.KeyDown: HandleKeyDown(view); break; - case EventType.KeyUp: HandleKeyUp(); break; - case EventType.Layout: - { - Vector3 motion = GetMovementDirection(); - // This seems to be the best way to have a continuously repeating event - if (GUIUtility.hotControl == id && motion.sqrMagnitude != 0) - { - view.pivot = view.pivot + view.rotation * motion; - view.Repaint(); - } - } - break; - case EventType.Used: - // since FPS tool acts on right click, nothing prevents a regular control - // from taking the control ID on left click, so some cleanup is necessary - // to not get locked into FPS mode (case 777346) - if (GUIUtility.hotControl != id && s_CurrentState != MotionState.kInactive) - { - ResetDragState(); - } - break; - } - } - - static Vector3 GetMovementDirection() - { - float deltaTime = s_FPSTiming.Update(); - if (s_Motion.sqrMagnitude == 0) - { - s_FlySpeed = 0; - return Vector3.zero; - } - else - { - float speed = Event.current.shift ? 5 : 1; - if (s_FlySpeed == 0) - s_FlySpeed = 9; - else - s_FlySpeed = s_FlySpeed * Mathf.Pow(kFlyAcceleration, deltaTime); - return s_Motion.normalized * s_FlySpeed * speed * deltaTime; - } - } - - private static void HandleMouseDown(SceneView view, int id, int button) - { - s_CurrentState = MotionState.kInactive; - - if (Tools.viewToolActive) - { - ViewTool wantedViewTool = Tools.viewTool; - - // Check if we want to lock a view tool - if (Tools.s_LockedViewTool != wantedViewTool) - { - Event evt = Event.current; - - // Set the hotcontrol and then lock the viewTool (important to set the hotControl AFTER the Tools.viewTool has been evaluated) - GUIUtility.hotControl = id; - Tools.s_LockedViewTool = wantedViewTool; - - // Set up zoom parameters - s_StartZoom = view.size; - s_ZoomSpeed = Mathf.Max(Mathf.Abs(s_StartZoom), .3f); - s_TotalMotion = 0; - - if (view) - view.Focus(); - - if (Toolbar.get) - Toolbar.get.Repaint(); - EditorGUIUtility.SetWantsMouseJumping(1); - - evt.Use(); - - // we're not dragging yet, but enter this state so we can cleanup correctly - s_CurrentState = MotionState.kActive; - - // This prevents camera from moving back on mousedown... find out why... and write a comment - GUIUtility.ExitGUI(); - } - } - } - - private static void ResetDragState() - { - s_CurrentState = MotionState.kInactive; - Tools.s_LockedViewTool = ViewTool.None; - Tools.s_ButtonDown = -1; - s_Motion = Vector3.zero; - if (Toolbar.get) - Toolbar.get.Repaint(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - - private static void HandleMouseUp(SceneView view, int id, int button, int clickCount) - { - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - - // Move pivot to clicked point. - if (button == 2 && s_CurrentState != MotionState.kDragging) - { - RaycastHit hit; - if (RaycastWorld(Event.current.mousePosition, out hit)) - { - Vector3 currentPosition = view.pivot - view.rotation * Vector3.forward * view.cameraDistance; - float targetSize = view.size; - if (!view.orthographic) - targetSize = view.size * Vector3.Dot(hit.point - currentPosition, view.rotation * Vector3.forward) / view.cameraDistance; - view.LookAt(hit.point, view.rotation, targetSize); - } - } - - ResetDragState(); - - Event.current.Use(); - } - } - - static bool RaycastWorld(Vector2 position, out RaycastHit hit) - { - hit = new RaycastHit(); - GameObject picked = HandleUtility.PickGameObject(position, false); - if (!picked) - return false; - - Ray mouseRay = HandleUtility.GUIPointToWorldRay(position); - - // Loop through all meshes and find the RaycastHit closest to the ray origin. - MeshFilter[] meshFil = picked.GetComponentsInChildren(); - float minT = Mathf.Infinity; - foreach (MeshFilter mf in meshFil) - { - Mesh mesh = mf.sharedMesh; - if (!mesh) - continue; - RaycastHit localHit; - if (HandleUtility.IntersectRayMesh(mouseRay, mesh, mf.transform.localToWorldMatrix, out localHit)) - { - if (localHit.distance < minT) - { - hit = localHit; - minT = hit.distance; - } - } - } - - if (minT == Mathf.Infinity) - { - // If we didn't find any surface based on meshes, try with colliders. - Collider[] colliders = picked.GetComponentsInChildren(); - foreach (Collider col in colliders) - { - RaycastHit localHit; - if (col.Raycast(mouseRay, out localHit, Mathf.Infinity)) - { - if (localHit.distance < minT) - { - hit = localHit; - minT = hit.distance; - } - } - } - } - - if (minT == Mathf.Infinity) - { - // If we didn't hit any mesh or collider surface, then use the transform position projected onto the ray. - hit.point = Vector3.Project(picked.transform.position - mouseRay.origin, mouseRay.direction) + mouseRay.origin; - } - return true; - } - - private static void OrbitCameraBehavior(SceneView view) - { - Event evt = Event.current; - - view.FixNegativeSize(); - Quaternion rotation = view.m_Rotation.target; - rotation = Quaternion.AngleAxis(evt.delta.y * .003f * Mathf.Rad2Deg, rotation * Vector3.right) * rotation; - rotation = Quaternion.AngleAxis(evt.delta.x * .003f * Mathf.Rad2Deg, Vector3.up) * rotation; - if (view.size < 0) - { - view.pivot = view.camera.transform.position; - view.size = 0; - } - view.rotation = rotation; - } - - private static void HandleMouseDrag(SceneView view, int id) - { - // we now are dragging for real - s_CurrentState = MotionState.kDragging; - - if (GUIUtility.hotControl == id) - { - Event evt = Event.current; - switch (Tools.s_LockedViewTool) - { - case ViewTool.Orbit: - { - if (!view.in2DMode && !view.isRotationLocked) - { - OrbitCameraBehavior(view); - view.svRot.UpdateGizmoLabel(view, view.rotation * Vector3.forward, view.m_Ortho.target); - } - } - break; - case ViewTool.FPS: - { - if (!view.in2DMode && !view.isRotationLocked) - { - if (!view.orthographic) - { - view.viewIsLockedToObject = false; - - // The reason we calculate the camera position from the pivot, rotation and distance, - // rather than just getting it from the camera transform is that the camera transform - // is the *output* of camera motion calculations. It shouldn't be input and putput at the same time, - // otherwise we easily get accumulated error. - // We did get accumulated error before when we did this - the camera would continuously move slightly in FPS mode - // even when not holding down any arrow/ASDW keys or moving the mouse. - Vector3 camPos = view.pivot - view.rotation * Vector3.forward * view.cameraDistance; - - // Normal FPS camera behavior - Quaternion rotation = view.rotation; - rotation = Quaternion.AngleAxis(evt.delta.y * .003f * Mathf.Rad2Deg, rotation * Vector3.right) * rotation; - rotation = Quaternion.AngleAxis(evt.delta.x * .003f * Mathf.Rad2Deg, Vector3.up) * rotation; - view.rotation = rotation; - - view.pivot = camPos + rotation * Vector3.forward * view.cameraDistance; - } - else - { - // We want orbit behavior in orthograpic when using FPS - OrbitCameraBehavior(view); - } - view.svRot.UpdateGizmoLabel(view, view.rotation * Vector3.forward, view.m_Ortho.target); - } - } - break; - case ViewTool.Pan: - { - view.viewIsLockedToObject = false; - view.FixNegativeSize(); - Camera cam = view.camera; - Vector3 screenPos = cam.WorldToScreenPoint(view.pivot); - screenPos += new Vector3(-Event.current.delta.x, Event.current.delta.y, 0); - Vector3 worldDelta = Camera.current.ScreenToWorldPoint(screenPos) - view.pivot; - worldDelta *= EditorGUIUtility.pixelsPerPoint; - if (evt.shift) - worldDelta *= 4; - view.pivot += worldDelta; - } - break; - case ViewTool.Zoom: - { - float zoomDelta = HandleUtility.niceMouseDeltaZoom * (evt.shift ? 9 : 3); - if (view.orthographic) - { - view.size = Mathf.Max(.0001f, view.size * (1 + zoomDelta * .001f)); - } - else - { - s_TotalMotion += zoomDelta; - if (s_TotalMotion < 0) - view.size = s_StartZoom * (1 + s_TotalMotion * .001f); - else - view.size = view.size + zoomDelta * s_ZoomSpeed * .003f; - } - } - break; - - default: - Debug.Log("Enum value Tools.s_LockViewTool not handled"); - break; - } - evt.Use(); - } - } - - private static void HandleKeyDown(SceneView sceneView) - { - if (Event.current.keyCode == KeyCode.Escape && GUIUtility.hotControl == s_ViewToolID) - { - GUIUtility.hotControl = 0; - ResetDragState(); - } - - if (Tools.s_LockedViewTool == ViewTool.FPS) - { - Event evt = Event.current; - Vector3 lastMotion = s_Motion; - if (evt.keyCode == ((Event)kFPSForward).keyCode) - { - sceneView.viewIsLockedToObject = false; - s_Motion.z = 1; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSBack).keyCode) - { - sceneView.viewIsLockedToObject = false; - s_Motion.z = -1; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSLeft).keyCode) - { - sceneView.viewIsLockedToObject = false; - s_Motion.x = -1; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSRight).keyCode) - { - sceneView.viewIsLockedToObject = false; - s_Motion.x = 1; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSUp).keyCode) - { - sceneView.viewIsLockedToObject = false; - s_Motion.y = 1; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSDown).keyCode) - { - sceneView.viewIsLockedToObject = false; - s_Motion.y = -1; - evt.Use(); - } - - if (evt.type != EventType.KeyDown && lastMotion.sqrMagnitude == 0) - s_FPSTiming.Begin(); - } - } - - private static void HandleKeyUp() - { - if (Tools.s_LockedViewTool == ViewTool.FPS) - { - Event evt = Event.current; - if (evt.keyCode == ((Event)kFPSForward).keyCode || evt.keyCode == ((Event)kFPSBack).keyCode) - { - s_Motion.z = 0; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSLeft).keyCode || evt.keyCode == ((Event)kFPSRight).keyCode) - { - s_Motion.x = 0; - evt.Use(); - } - else if (evt.keyCode == ((Event)kFPSUp).keyCode || evt.keyCode == ((Event)kFPSDown).keyCode) - { - s_Motion.y = 0; - evt.Use(); - } - } - } - - private static void HandleScrollWheel(SceneView view, bool zoomTowardsCenter) - { - var initialDistance = view.cameraDistance; - var mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); - var mousePivot = mouseRay.origin + mouseRay.direction * view.cameraDistance; - var pivotVector = mousePivot - view.pivot; - - float zoomDelta = Event.current.delta.y; - if (!view.orthographic) - { - float relativeDelta = Mathf.Abs(view.size) * zoomDelta * .015f; - const float deltaCutoff = .3f; - if (relativeDelta > 0 && relativeDelta < deltaCutoff) - relativeDelta = deltaCutoff; - else if (relativeDelta < 0 && relativeDelta > -deltaCutoff) - relativeDelta = -deltaCutoff; - - view.size += relativeDelta; - } - else - { - view.size = Mathf.Abs(view.size) * (zoomDelta * .015f + 1.0f); - } - - var percentage = 1f - (view.cameraDistance / initialDistance); - if (!zoomTowardsCenter) - view.pivot += pivotVector * percentage; - - Event.current.Use(); - } - - public static void ResetMotion() - { - s_Motion = Vector3.zero; - } - } - - [System.Serializable] - internal class SceneViewRotation - { - private const int kRotationSize = 100; - private const int kRotationMenuInset = 22; - private const float kRotationLockedAlpha = 0.4f; - - static Quaternion[] kDirectionRotations = - { - Quaternion.LookRotation(new Vector3(-1, 0, 0)), - Quaternion.LookRotation(new Vector3(0, -1, 0)), - Quaternion.LookRotation(new Vector3(0, 0, -1)), - Quaternion.LookRotation(new Vector3(1, 0, 0)), - Quaternion.LookRotation(new Vector3(0, 1, 0)), - Quaternion.LookRotation(new Vector3(0, 0, 1)), - }; - - internal static string[] kDirNames = { "Right", "Top", "Front", "Left", "Bottom", "Back", "Iso", "Persp", "2D" }; - internal static string[] kMenuDirNames = { "Free", "Right", "Top", "Front", "Left", "Bottom", "Back", "", "Perspective" }; - - private static readonly GUIContent[] s_HandleAxisLabels = - { - new GUIContent("x"), new GUIContent("y"), new GUIContent("z") - }; - - private int[] m_ViewDirectionControlIDs; - private int m_CenterButtonControlID; - - - int currentDir = 7; - internal AnimBool[] dirVisible = { new AnimBool(true), new AnimBool(true), new AnimBool(true) }; - internal AnimBool[] dirNameVisible = { new AnimBool(), new AnimBool(), new AnimBool(), new AnimBool(), new AnimBool(), new AnimBool(), new AnimBool(), new AnimBool(), new AnimBool() }; - float faded2Dgray { get { return dirNameVisible[8].faded; } } - float fadedRotationLock { get { return Mathf.Lerp(kRotationLockedAlpha, 1.0f, m_RotationLocked.faded); } } - - AnimBool m_RotationLocked = new AnimBool(); - AnimBool m_Visible = new AnimBool(); - float fadedVisibility - { - get - { - return m_Visible.faded * fadedRotationLock; - } - } - - private class Styles - { - public GUIStyle viewLabelStyleLeftAligned; - public GUIStyle viewLabelStyleCentered; - public GUIStyle viewAxisLabelStyle; - public GUIStyle lockStyle; - public GUIContent unlockedRotationIcon; - public GUIContent lockedRotationIcon; - - public Styles() - { - viewLabelStyleLeftAligned = new GUIStyle("SC ViewLabel"); - viewLabelStyleCentered = new GUIStyle("SC ViewLabel"); - unlockedRotationIcon = EditorGUIUtility.TrIconContent("LockIcon", "Click to lock the rotation in the current direction."); - lockedRotationIcon = EditorGUIUtility.TrIconContent("LockIcon-On", "Click to unlock the rotation."); - lockStyle = new GUIStyle("label"); - lockStyle.alignment = TextAnchor.MiddleCenter; - viewLabelStyleLeftAligned.alignment = TextAnchor.MiddleLeft; - viewLabelStyleCentered.alignment = TextAnchor.MiddleCenter; - viewAxisLabelStyle = "SC ViewAxisLabel"; - } - } - private static Styles s_Styles; - private static Styles styles - { - get - { - if (s_Styles == null) - s_Styles = new Styles(); - return s_Styles; - } - } - - public void Register(SceneView view) - { - // Register fade animators for cones - for (int i = 0; i < dirVisible.Length; i++) - dirVisible[i].valueChanged.AddListener(view.Repaint); - for (int i = 0; i < dirNameVisible.Length; i++) - dirNameVisible[i].valueChanged.AddListener(view.Repaint); - - m_RotationLocked.valueChanged.AddListener(view.Repaint); - m_Visible.valueChanged.AddListener(view.Repaint); - - // Set correct label to be enabled from beginning - int labelIndex = GetLabelIndexForView(view, view.rotation * Vector3.forward, view.orthographic); - for (int i = 0; i < dirNameVisible.Length; i++) - dirNameVisible[i].value = (i == labelIndex); - m_RotationLocked.value = !view.isRotationLocked; - m_Visible.value = (labelIndex != 8); - - SwitchDirNameVisible(labelIndex); - - if (m_ViewDirectionControlIDs == null) - { - m_ViewDirectionControlIDs = new int[kDirectionRotations.Length]; - for (int i = 0; i < m_ViewDirectionControlIDs.Length; ++i) - { - m_ViewDirectionControlIDs[i] = GUIUtility.GetPermanentControlID(); - } - - m_CenterButtonControlID = GUIUtility.GetPermanentControlID(); - } - } - - private void AxisSelectors(SceneView view, Camera cam, float size, float sgn, GUIStyle viewAxisLabelStyle) - { - for (int h = kDirectionRotations.Length - 1; h >= 0; h--) - { - Quaternion q1 = kDirectionRotations[h]; - float a = dirVisible[h % 3].faded; - Vector3 direction = kDirectionRotations[h] * Vector3.forward; - float dot = Vector3.Dot(view.camera.transform.forward, direction); - - if (dot <= 0.0 && sgn > 0.0f) - continue; - - if (dot > 0.0 && sgn < 0.0f) - continue; - - Color c; - switch (h) - { - case 0: c = Handles.xAxisColor; break; - case 1: c = Handles.yAxisColor; break; - case 2: c = Handles.zAxisColor; break; - default: c = Handles.centerColor; break; - } - - if (view.in2DMode) - { - c = Color.Lerp(c, Color.gray, faded2Dgray); - } - c.a *= a * fadedVisibility; - - if (QualitySettings.activeColorSpace == ColorSpace.Linear) - c = c.linear; - - Handles.color = c; - - if (c.a <= 0.1f || view.isRotationLocked) - GUI.enabled = false; - - // axis widget when drawn behind label - if (sgn > 0 && Handles.Button(m_ViewDirectionControlIDs[h], q1 * Vector3.forward * size * -1.2f, q1, size, size * 0.7f, Handles.ConeHandleCap)) - { - if (!view.in2DMode && !view.isRotationLocked) - ViewAxisDirection(view, h); - } - - // primary axes have text labels - if (h < 3) - { - GUI.color = new Color(1, 1, 1, dirVisible[h].faded * fadedVisibility); - - // Label pos is a bit further out than the end of the cone - Vector3 pos = direction; - // Remove some of the perspective to avoid labels in front - // being much further away from the gizmo due to perspective - pos += dot * view.camera.transform.forward * -0.5f; - // Also remove some of the spacing difference caused by rotation - pos = (pos * 0.7f + pos.normalized * 1.5f) * size; - Handles.Label(-pos, s_HandleAxisLabels[h], styles.viewAxisLabelStyle); - } - - // axis widget when drawn in front of label - if (sgn < 0 && Handles.Button(m_ViewDirectionControlIDs[h], q1 * Vector3.forward * size * -1.2f, q1, size, size * 0.7f, Handles.ConeHandleCap)) - { - if (!view.in2DMode && !view.isRotationLocked) - ViewAxisDirection(view, h); - } - - - Handles.color = Color.white; - GUI.color = Color.white; - GUI.enabled = true; - } - } - - internal void HandleContextClick(SceneView view) - { - if (!view.in2DMode && !view.isRotationLocked) - { - Event evt = Event.current; - if (evt.type == EventType.MouseDown && evt.button == 1) - { - float screenSize = Mathf.Min(view.position.width, view.position.height); - if (screenSize < kRotationSize) - return; - - Rect rotationRect = new Rect(view.position.width - kRotationSize + kRotationMenuInset, kRotationMenuInset, kRotationSize - kRotationMenuInset * 2, kRotationSize - kRotationMenuInset * 2); - - if (rotationRect.Contains(evt.mousePosition)) - { - DisplayContextMenu(new Rect(evt.mousePosition.x, evt.mousePosition.y, 0, 0), view); - evt.Use(); - } - } - } - } - - private void DisplayContextMenu(Rect buttonOrCursorRect, SceneView view) - { - int[] selectedItems = new int[view.orthographic ? 1 : 2]; - selectedItems[0] = currentDir >= 6 ? 0 : currentDir + 1; - if (!view.orthographic) - selectedItems[1] = 8; - EditorUtility.DisplayCustomMenu(buttonOrCursorRect, kMenuDirNames, selectedItems, ContextMenuDelegate, view); - GUIUtility.ExitGUI(); - } - - private void ContextMenuDelegate(object userData, string[] options, int selected) - { - SceneView view = userData as SceneView; - if (view == null) - return; - - if (selected == 0) - { - // "free" selected - ViewFromNiceAngle(view, false); - } - else if (selected >= 1 && selected <= 6) - { - // one of axes was selected - int axis = selected - 1; - ViewAxisDirection(view, axis); - } - else if (selected == 8) - { - // perspective / ortho toggled - ViewSetOrtho(view, !view.orthographic); - } - else if (selected == 10) - { - // Unity default point of view - view.LookAt(view.pivot, Quaternion.LookRotation(new Vector3(-1, -.7f, -1)), view.size, view.orthographic); - } - else if (selected == 11) - { - // Maya default point of view - view.LookAt(view.pivot, Quaternion.LookRotation(new Vector3(1, -.7f, -1)), view.size, view.orthographic); - } - else if (selected == 12) - { - // 3DSMax default point of view - view.LookAt(view.pivot, Quaternion.LookRotation(new Vector3(1, -.7f, 1)), view.size, view.orthographic); - } - } - - private void DrawIsoStatusSymbol(Vector3 center, SceneView view, float alpha) - { - float persp = 1 - Mathf.Clamp01(view.m_Ortho.faded * 1.2f - 0.1f); - Vector3 up = Vector3.up * 3; - Vector3 right = Vector3.right * 10; - Vector3 pos = center - right * 0.5f; - - Handles.color = new Color(1, 1, 1, 0.6f * alpha); - Handles.DrawAAPolyLine(pos + up * (1 - persp), pos + right + up * (1 + persp * 0.5f)); - Handles.DrawAAPolyLine(pos , pos + right); - Handles.DrawAAPolyLine(pos - up * (1 - persp), pos + right - up * (1 + persp * 0.5f)); - } - - void DrawRotationLock(SceneView view) - { - const float clickWidth = 24; - const float clickHeight = 24; - float lockCenterX = view.position.width - 16; - float lockCenterY = 17; - Rect lockRect = new Rect(lockCenterX - (clickWidth / 2), lockCenterY - (clickHeight / 2), clickWidth, clickHeight); - Color c = Handles.centerColor; - c.a *= m_Visible.faded; - if (c.a > 0.0f) - { - var prevColor = GUI.color; - GUI.color = c; - var content = (view.isRotationLocked) ? styles.lockedRotationIcon : styles.unlockedRotationIcon; - if (GUI.Button(lockRect, content, styles.lockStyle) && !view.in2DMode) - { - view.isRotationLocked = !view.isRotationLocked; - m_RotationLocked.target = !view.isRotationLocked; - } - GUI.color = prevColor; - } - } - - void DrawLabels(SceneView view) - { - Rect labelRect = new Rect(view.position.width - kRotationSize + 17, kRotationSize - 8, kRotationSize - 17 * 2, 16); - - // Button (overlayed over the labels) to toggle between iso and perspective - if (!view.in2DMode && !view.isRotationLocked) - { - if (GUI.Button(labelRect, string.Empty, styles.viewLabelStyleLeftAligned)) - { - if (Event.current.button == 1) - DisplayContextMenu(labelRect, view); - else - ViewSetOrtho(view, !view.orthographic); - } - } - - // Labels - if (Event.current.type == EventType.Repaint) - { - int index2D = 8; - - // Calculate the weighted average width of the labels so we can do smart centering of the labels. - Rect slidingLabelRect = labelRect; - float width = 0; - float weightSum = 0; - for (int i = 0; i < kDirNames.Length; i++) - { - if (i == index2D) // Future proof even if we add more labels after the 2D one - continue; - weightSum += dirNameVisible[i].faded; - if (dirNameVisible[i].faded > 0) - width += styles.viewLabelStyleLeftAligned.CalcSize(EditorGUIUtility.TempContent(kDirNames[i])).x * dirNameVisible[i].faded; - } - if (weightSum > 0) - width /= weightSum; - - // Offset the label rect based on the label width - slidingLabelRect.x += 37 - width * 0.5f; - - // Round to int AFTER the floating point calculations - slidingLabelRect.x = Mathf.RoundToInt(slidingLabelRect.x); - - // Currently selected axis label. Since they cross-fade upon selection, - // more than one might be drawn at the same time. - // First draw the regular ones - all except the 2D label. They use the slidingLabelRect. - for (int i = 0; i < dirNameVisible.Length && i < kDirNames.Length; i++) - { - if (i == index2D) // Future proof even if we add more labels after the 2D one - continue; - Color c = Handles.centerColor; - c.a *= dirNameVisible[i].faded * fadedRotationLock; - if (c.a > 0.0f) - { - GUI.color = c; - GUI.Label(slidingLabelRect, kDirNames[i], styles.viewLabelStyleLeftAligned); - } - } - // Then draw just the label for 2D. It uses the original labelRect, and with a style where the text is horizontally centered. - { - Color c = Handles.centerColor; - c.a *= faded2Dgray * fadedVisibility; - if (c.a > 0.0f) - { - GUI.color = c; - GUI.Label(labelRect, kDirNames[index2D], styles.viewLabelStyleCentered); - } - } - - // Draw the iso status symbol - the passed Vector3 is the center - if (faded2Dgray < 1) - { - DrawIsoStatusSymbol(new Vector3(slidingLabelRect.x - 8, slidingLabelRect.y + 8.5f, 0), view, (1 - faded2Dgray) * fadedRotationLock); - } - } - } - - // Ensure all controlIDs used in this OnGUI are permanent controlIDs so this method can be called - // in different places for handling input early and rendering late. - internal void OnGUI(SceneView view) - { - float screenSize = Mathf.Min(view.position.width, view.position.height); - if (screenSize < kRotationSize) - return; - - if (Event.current.type == EventType.Repaint) - Profiler.BeginSample("SceneView.AxisSelector"); - - HandleContextClick(view); - - // This is a pretty weird way of doing things, but it works, so... - Camera cam = view.camera; - - HandleUtility.PushCamera(cam); - if (cam.orthographic) - cam.orthographicSize = .5f; - - cam.cullingMask = 0; - cam.transform.position = cam.transform.rotation * new Vector3(0, 0, -5); - cam.clearFlags = CameraClearFlags.Nothing; - cam.nearClipPlane = .1f; - cam.farClipPlane = 10; - cam.fieldOfView = view.m_Ortho.Fade(70, 0); - - SceneView.AddCursorRect(new Rect(view.position.width - kRotationSize + kRotationMenuInset, kRotationMenuInset, kRotationSize - 2 * kRotationMenuInset, kRotationSize + 24 - kRotationMenuInset), MouseCursor.Arrow); - - Handles.SetCamera(new Rect(view.position.width - kRotationSize, 0, kRotationSize, kRotationSize), cam); - - Handles.BeginGUI(); - - DrawRotationLock(view); - DrawLabels(view); - - Handles.EndGUI(); - - // animate visibility of three axis widgets - for (int i = 0; i < 3; ++i) - { - Vector3 direction = kDirectionRotations[i] * Vector3.forward; - dirVisible[i].target = Mathf.Abs(Vector3.Dot(cam.transform.forward, direction)) < 0.9f; - } - - float size = HandleUtility.GetHandleSize(Vector3.zero) * .2f; - - // Do axes behind the center one - AxisSelectors(view, cam, size, -1.0f, styles.viewAxisLabelStyle); - - // Do center handle - - Color centerColor = Handles.centerColor; - centerColor = Color.Lerp(centerColor, Color.gray, faded2Dgray); - centerColor.a *= fadedVisibility; - if (centerColor.a <= 0.1f || view.isRotationLocked) - GUI.enabled = false; - - Handles.color = centerColor; - if (Handles.Button(m_CenterButtonControlID, Vector3.zero, Quaternion.identity, size * 0.8f, size, Handles.CubeHandleCap) && !view.in2DMode && !view.isRotationLocked) - { - if (Event.current.clickCount == 2) - view.FrameSelected(); - else - { - // If middle-click or shift-click, choose a perspective view from a nice angle, - // similar to in Unity 3.5. - if (Event.current.shift || Event.current.button == 2) - ViewFromNiceAngle(view, true); - // Else, toggle perspective - else - ViewSetOrtho(view, !view.orthographic); - } - } - - // Do axes in front of the center one - AxisSelectors(view, cam, size, 1.0f, styles.viewAxisLabelStyle); - - GUI.enabled = true; - - if (!view.in2DMode && !view.isRotationLocked) - { - // Swipe handling - if (Event.current.type == EditorGUIUtility.swipeGestureEventType) - { - // Get swipe dir as Vector3 - Event evt = Event.current; - Vector3 swipeDir; - if (evt.delta.y > 0) - swipeDir = Vector3.up; - else if (evt.delta.y < 0) - swipeDir = -Vector3.up; - else if (evt.delta.x < 0) // delta x inverted for some reason - swipeDir = Vector3.right; - else - swipeDir = -Vector3.right; - - // Inverse swipe dir, so swiping down will go to top view etc. - // This is consistent with how we do orbiting, where moving the mouse down sees the object more from above etc. - // Also, make swipe dir point almost 45 degrees in towards the camera. - // This means the swipe will pick the closest axis in the swiped direction, - // instead of picking the one closest to being 90 degrees away. - Vector3 goalVector = -swipeDir - Vector3.forward * 0.9f; - - // Transform swipe dir by camera transform, so up is camera's local up, etc. - goalVector = view.camera.transform.TransformDirection(goalVector); - - // Get global axis that's closest to the swipe dir vector - float bestDotProduct = 0; - int dir = 0; - for (int i = 0; i < 6; i++) - { - // Note that kDirectionRotations are not the forward direction of each dir; - // it's the back direction *towards* the camera. - float dotProduct = Vector3.Dot(kDirectionRotations[i] * -Vector3.forward, goalVector); - if (dotProduct > bestDotProduct) - { - bestDotProduct = dotProduct; - dir = i; - } - } - - // Look along chosen axis - ViewAxisDirection(view, dir); - Event.current.Use(); - } - } - - HandleUtility.PopCamera(cam); - Handles.SetCamera(cam); - - if (Event.current.type == EventType.Repaint) - Profiler.EndSample(); - } - - private void ViewAxisDirection(SceneView view, int dir) - { - // If holding shift or clicking with middle mouse button, orthographic is enforced, otherwise not altered. - // Note: This function can also be called from a context menu where Event.current is null. - bool ortho = view.orthographic; - if (Event.current != null && (Event.current.shift || Event.current.button == 2)) - ortho = true; - - view.LookAt(view.pivot, kDirectionRotations[dir] , view.size, ortho); - // Set label to according direction - SwitchDirNameVisible(dir); - } - - private void ViewSetOrtho(SceneView view, bool ortho) - { - view.LookAt(view.pivot, view.rotation, view.size, ortho); - } - - internal void UpdateGizmoLabel(SceneView view, Vector3 direction, bool ortho) - { - SwitchDirNameVisible(GetLabelIndexForView(view, direction, ortho)); - } - - internal int GetLabelIndexForView(SceneView view, Vector3 direction, bool ortho) - { - if (!view.in2DMode) - { - // If the view is axis aligned, find the correct axis. - if (IsAxisAligned(direction)) - for (int i = 0; i < 6; i++) - if (Vector3.Dot(kDirectionRotations[i] * Vector3.forward, direction) > 0.9f) - return i; - - // If the view is not axis aligned, set label to Iso or Persp. - return ortho ? 6 : 7; - } - return 8; // 2D mode - } - - private void ViewFromNiceAngle(SceneView view, bool forcePerspective) - { - // Use dir that's the same as the current one in the x-z plane, but placed a bit above middle vertically. - // (Same as old dir except it had the x-z dir fixed.) - Vector3 dir = view.rotation * Vector3.forward; - dir.y = 0; - if (dir == Vector3.zero) - // When the view is top or bottom, the closest nice view is to look approx. towards z. - dir = Vector3.forward; - else - // Otherwise pick dir based on existing dir. - dir = dir.normalized; - // Look at object a bit from above. - dir.y = -0.5f; - - bool ortho = forcePerspective ? false : view.orthographic; - view.LookAt(view.pivot, Quaternion.LookRotation(dir), view.size, ortho); - SwitchDirNameVisible(ortho ? 6 : 7); - } - - private bool IsAxisAligned(Vector3 v) - { - 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); - } - - private void SwitchDirNameVisible(int newVisible) - { - if (newVisible == currentDir) - return; - - dirNameVisible[currentDir].target = false; - currentDir = newVisible; - dirNameVisible[currentDir].target = true; - - // Fade whole Scene View Gizmo in / out when switching 2D mode. - if (newVisible == 8) - m_Visible.speed = 0.3f; - else - m_Visible.speed = 2f; - - m_Visible.target = (newVisible != 8); - } - } -} //namespace diff --git a/Editor/Mono/SceneView/SceneViewOverlay.cs b/Editor/Mono/SceneView/SceneViewOverlay.cs deleted file mode 100644 index 1474cbb773..0000000000 --- a/Editor/Mono/SceneView/SceneViewOverlay.cs +++ /dev/null @@ -1,188 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; - -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class SceneViewOverlay - { - // This enum is for better overview of the ordering of our builtin overlays - public enum Ordering - { - // Lower order is below high order when showed together - Camera = -100, - ClothConstraints = 0, - ClothSelfAndInterCollision = 100, - OcclusionCulling = 200, - Lightmapping = 300, - NavMesh = 400, - PhysicsDebug = 450, - TilemapRenderer = 500, - ParticleEffect = 600 - } - - public enum WindowDisplayOption - { - MultipleWindowsPerTarget, - OneWindowPerTarget, - OneWindowPerTitle - } - - private class OverlayWindow : IComparable - { - public GUIContent m_Title; - public SceneViewOverlay.WindowFunction m_SceneViewFunc; - public int m_PrimaryOrder; // lower order is below high order - public int m_SecondaryOrder; // used for primary order that are equal (should be unique) - public Object m_Target; - - public int CompareTo(OverlayWindow other) - { - int result = other.m_PrimaryOrder.CompareTo(m_PrimaryOrder); - if (result == 0) - result = other.m_SecondaryOrder.CompareTo(m_SecondaryOrder); - return result; - } - }; - public delegate void WindowFunction(Object target, SceneView sceneView); - - static List m_Windows; - - Rect m_WindowRect = new Rect(0, 0, 0, 0); - - SceneView m_SceneView; - - float k_WindowPadding = 9f; - - public SceneViewOverlay(SceneView sceneView) - { - m_SceneView = sceneView; - m_Windows = new List(); - } - - public void Begin() - { - if (!m_SceneView.m_ShowSceneViewWindows) - return; - - if (Event.current.type == EventType.Layout) - m_Windows.Clear(); - - m_SceneView.BeginWindows(); - } - - public void End() - { - if (!m_SceneView.m_ShowSceneViewWindows) - return; - - m_Windows.Sort(); - - if (m_Windows.Count > 0) - { - m_WindowRect.x = 0; - m_WindowRect.y = 0; - m_WindowRect.width = m_SceneView.position.width; - m_WindowRect.height = m_SceneView.position.height; - m_WindowRect = GUILayout.Window("SceneViewOverlay".GetHashCode(), m_WindowRect, WindowTrampoline, "", "SceneViewOverlayTransparentBackground"); - } - - m_SceneView.EndWindows(); - } - - private void WindowTrampoline(int id) - { - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - GUILayout.BeginVertical(); - GUILayout.FlexibleSpace(); - GUILayout.BeginVertical(); - float paddingOffset = -k_WindowPadding; - foreach (OverlayWindow win in m_Windows) - { - GUILayout.Space(k_WindowPadding + paddingOffset); - paddingOffset = 0f; - EditorGUIUtility.ResetGUIState(); - GUI.skin = EditorGUIUtility.GetBuiltinSkin(EditorSkin.Scene); - EditorStyles.UpdateSkinCache(1); // EditorResources.h defines this as the index for the dark skin - GUILayout.BeginVertical(win.m_Title, GUI.skin.window); - win.m_SceneViewFunc(win.m_Target, m_SceneView); - GUILayout.EndVertical(); - } - EditorStyles.UpdateSkinCache(); // Sets the cache back according to the user selected skin - GUILayout.EndVertical(); - Rect inputEaterRect = GUILayoutUtility.GetLastRect(); - EatMouseInput(inputEaterRect); - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - } - - private void EatMouseInput(Rect position) - { - SceneView.AddCursorRect(position, MouseCursor.Arrow); - - int id = GUIUtility.GetControlID("SceneViewOverlay".GetHashCode(), FocusType.Passive, position); - switch (Event.current.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (position.Contains(Event.current.mousePosition)) - { - GUIUtility.hotControl = id; - Event.current.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id) - { - GUIUtility.hotControl = 0; - Event.current.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - Event.current.Use(); - break; - case EventType.ScrollWheel: - if (position.Contains(Event.current.mousePosition)) - Event.current.Use(); - break; - } - } - - public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, WindowDisplayOption option) - { - Window(title, sceneViewFunc, order, null, option); - } - - public static void Window(GUIContent title, WindowFunction sceneViewFunc, int order, Object target, WindowDisplayOption option) - { - if (Event.current.type != EventType.Layout) - return; - - foreach (OverlayWindow overlayWindow in m_Windows) - { - if (option == WindowDisplayOption.OneWindowPerTarget && overlayWindow.m_Target == target && target != null) - return; - - if (option == WindowDisplayOption.OneWindowPerTitle && (overlayWindow.m_Title == title || overlayWindow.m_Title.text == title.text)) - return; - } - - OverlayWindow newWindow = new OverlayWindow(); - newWindow.m_Title = title; - newWindow.m_SceneViewFunc = sceneViewFunc; - newWindow.m_PrimaryOrder = order; - newWindow.m_SecondaryOrder = m_Windows.Count; // just use a value that is unique across overlays - newWindow.m_Target = target; - - m_Windows.Add(newWindow); - } - } -} diff --git a/Editor/Mono/SceneView/SceneViewPicking.cs b/Editor/Mono/SceneView/SceneViewPicking.cs deleted file mode 100644 index 9c83d61c48..0000000000 --- a/Editor/Mono/SceneView/SceneViewPicking.cs +++ /dev/null @@ -1,169 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace UnityEditor -{ - // No BaseSelection available: - // 1. Just cycle through the selection from topmost to bottom - - // SelectionBase available for topmost object: - // 1. First click selects the base - // 2. Second click selects the topmost - // 3. All subsequent clicks cycle through the stack of overlapping objects from top to bottom, regardless of their SelectionBase status - // 4. When we hit the bottom, we goto 1 - - // Example: Scene from back to front (visually): Panel(base), Label, Image, Button(base), Image2, Label2 - // Selection order: Button, Label2, Image2, Image, Label, Panel, goto start - - internal class SceneViewPicking - { - private static bool s_RetainHashes = false; - private static int s_PreviousTopmostHash = 0; - private static int s_PreviousPrefixHash = 0; - - static SceneViewPicking() - { - Selection.selectionChanged += ResetHashes; - } - - private static void ResetHashes() - { - if (!s_RetainHashes) - { - s_PreviousTopmostHash = 0; - s_PreviousPrefixHash = 0; - } - - s_RetainHashes = false; - } - - public static GameObject PickGameObject(Vector2 mousePosition) - { - s_RetainHashes = true; - - var enumerator = GetAllOverlapping(mousePosition).GetEnumerator(); - if (!enumerator.MoveNext()) - return null; - - var topmost = enumerator.Current; - var selectionBase = HandleUtility.FindSelectionBase(topmost); - var first = (selectionBase == null ? topmost : selectionBase); - int topmostHash = topmost.GetHashCode(); - int prefixHash = topmostHash; - - if (Selection.activeGameObject == null) - { - // Nothing selected - // Return selection base if it exists, otherwise topmost game object - s_PreviousTopmostHash = topmostHash; - s_PreviousPrefixHash = prefixHash; - return first; - } - - if (topmostHash != s_PreviousTopmostHash) - { - // Topmost game object changed - // Return selection base if exists and is not already selected, otherwise topmost game object - s_PreviousTopmostHash = topmostHash; - s_PreviousPrefixHash = prefixHash; - return (Selection.activeGameObject == selectionBase ? topmost : first); - } - - s_PreviousTopmostHash = topmostHash; - - // Pick potential selection base before topmost game object - if (Selection.activeGameObject == selectionBase) - { - if (prefixHash == s_PreviousPrefixHash) - return topmost; - else - { - s_PreviousPrefixHash = prefixHash; - return selectionBase; - } - } - - // Check if active game object will appear in selection stack - var picked = HandleUtility.PickGameObject(mousePosition, false, null, new GameObject[] { Selection.activeGameObject }); - if (picked == Selection.activeGameObject) - { - // Advance enumerator to active game object - while (enumerator.Current != Selection.activeGameObject) - { - if (!enumerator.MoveNext()) - { - s_PreviousPrefixHash = topmostHash; - return first; // Should not occur - } - - UpdateHash(ref prefixHash, enumerator.Current); - } - } - - if (prefixHash != s_PreviousPrefixHash) - { - // Prefix hash changed, start over - s_PreviousPrefixHash = topmostHash; - return first; - } - - // Move on to next game object - if (!enumerator.MoveNext()) - { - s_PreviousPrefixHash = topmostHash; - return first; // End reached, start over - } - - UpdateHash(ref prefixHash, enumerator.Current); - - if (enumerator.Current == selectionBase) - { - // Skip selection base - if (!enumerator.MoveNext()) - { - s_PreviousPrefixHash = topmostHash; - return first; // End reached, start over - } - - UpdateHash(ref prefixHash, enumerator.Current); - } - - s_PreviousPrefixHash = prefixHash; - return enumerator.Current; - } - - // Use picking system to get us ordered list of all visually overlapping gameobjects in screen position from top to bottom - private static IEnumerable GetAllOverlapping(Vector2 position) - { - var allOverlapping = new List(); - - while (true) - { - var go = HandleUtility.PickGameObject(position, false, allOverlapping.ToArray()); - if (go == null) - break; - - // Prevent infinite loop if game object cannot be ignored when picking (This needs to fixed so print an error) - if (allOverlapping.Count > 0 && go == allOverlapping.Last()) - { - Debug.LogError("GetAllOverlapping failed, could not ignore game object '" + go.name + "' when picking"); - break; - } - - yield return go; - - allOverlapping.Add(go); - } - } - - private static void UpdateHash(ref int hash, object obj) - { - hash = unchecked(hash * 33 + obj.GetHashCode()); - } - } -} diff --git a/Editor/Mono/ScriptAttributeGUI/CustomPropertyDrawerAttribute.cs b/Editor/Mono/ScriptAttributeGUI/CustomPropertyDrawerAttribute.cs deleted file mode 100644 index c021401405..0000000000 --- a/Editor/Mono/ScriptAttributeGUI/CustomPropertyDrawerAttribute.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor -{ - // Tells a custom [[PropertyDrawer]] which run-time [[Serializable]] class or [[PropertyAttribute]] it's a drawer for. - [System.AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] - public sealed class CustomPropertyDrawer : Attribute - { - internal Type m_Type; - internal bool m_UseForChildren; - - // Tells a PropertyDrawer class which run-time class or attribute it's a drawer for. - public CustomPropertyDrawer(Type type) - { - m_Type = type; - } - - // Tells a PropertyDrawer class which run-time class or attribute it's a drawer for. - public CustomPropertyDrawer(Type type, bool useForChildren) - { - m_Type = type; - m_UseForChildren = useForChildren; - } - } -} diff --git a/Editor/Mono/ScriptAttributeGUI/DecoratorDrawer.cs b/Editor/Mono/ScriptAttributeGUI/DecoratorDrawer.cs deleted file mode 100644 index 58767403d4..0000000000 --- a/Editor/Mono/ScriptAttributeGUI/DecoratorDrawer.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - // Base class to derive custom decorator drawers from. - public abstract class DecoratorDrawer : GUIDrawer - { - internal PropertyAttribute m_Attribute; - - // The [[PropertyAttribute]] for the property. - public PropertyAttribute attribute { get { return m_Attribute; } } - - // Override this method to make your own GUI for the property. - public virtual void OnGUI(Rect position) - { - } - - // Override this method to specify how tall the GUI for this field is in pixels. - public virtual float GetHeight() - { - return EditorGUI.kSingleLineHeight; - } - - public virtual bool CanCacheInspectorGUI() - { - return true; - } - } -} diff --git a/Editor/Mono/ScriptAttributeGUI/GUIDrawer.cs b/Editor/Mono/ScriptAttributeGUI/GUIDrawer.cs deleted file mode 100644 index cd87d0003d..0000000000 --- a/Editor/Mono/ScriptAttributeGUI/GUIDrawer.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor -{ - // Base class for both PropertyDrawer and DecoratorDrawer. - public abstract class GUIDrawer {} -} diff --git a/Editor/Mono/ScriptAttributeGUI/Implementations/DecoratorDrawers.cs b/Editor/Mono/ScriptAttributeGUI/Implementations/DecoratorDrawers.cs deleted file mode 100644 index d15df0fdbc..0000000000 --- a/Editor/Mono/ScriptAttributeGUI/Implementations/DecoratorDrawers.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - // Built-in DecoratorDrawers. See matching attributes in PropertyAttribute.cs - - [CustomPropertyDrawer(typeof(SpaceAttribute))] - internal sealed class SpaceDrawer : DecoratorDrawer - { - public override float GetHeight() - { - return (attribute as SpaceAttribute).height; - } - } - - [CustomPropertyDrawer(typeof(HeaderAttribute))] - internal sealed class HeaderDrawer : DecoratorDrawer - { - public override void OnGUI(Rect position) - { - position.y += 8; - position = EditorGUI.IndentedRect(position); - GUI.Label(position, (attribute as HeaderAttribute).header, EditorStyles.boldLabel); - } - - public override float GetHeight() - { - return 24; - } - } -} diff --git a/Editor/Mono/ScriptAttributeGUI/Implementations/ExposedReferenceDrawer.cs b/Editor/Mono/ScriptAttributeGUI/Implementations/ExposedReferenceDrawer.cs deleted file mode 100644 index 395867e4fb..0000000000 --- a/Editor/Mono/ScriptAttributeGUI/Implementations/ExposedReferenceDrawer.cs +++ /dev/null @@ -1,279 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; - -abstract class BaseExposedPropertyDrawer : UnityEditor.PropertyDrawer -{ - private static float kDriveWidgetWidth = 18.0f; - private static GUIStyle kDropDownStyle = null; - private static Color kMissingOverrideColor = new Color(1.0f, 0.11f, 0.11f, 1.0f); - - protected readonly GUIContent ExposePropertyContent = EditorGUIUtility.TrTextContent("Expose Property"); - protected readonly GUIContent UnexposePropertyContent = EditorGUIUtility.TrTextContent("Unexpose Property"); - protected readonly GUIContent NotFoundOn = EditorGUIUtility.TrTextContent("not found on"); - protected readonly GUIContent OverridenByContent = EditorGUIUtility.TrTextContent("Overriden by "); - - private GUIContent m_ModifiedLabel = new GUIContent(); - - protected enum ExposedPropertyMode - { - DefaultValue, - Named, - NamedGUID - } - - protected enum OverrideState - { - DefaultValue, - MissingOverride, - Overridden - } - - public BaseExposedPropertyDrawer() - { - if (kDropDownStyle == null) - kDropDownStyle = new GUIStyle("ShurikenDropdown"); - } - - static ExposedPropertyMode GetExposedPropertyMode(string propertyName) - { - if (string.IsNullOrEmpty(propertyName)) - return ExposedPropertyMode.DefaultValue; - else - { - GUID guid; - if (GUID.TryParse(propertyName, out guid)) - return ExposedPropertyMode.NamedGUID; - else - return ExposedPropertyMode.Named; - } - } - - protected IExposedPropertyTable GetExposedPropertyTable(SerializedProperty property) - { - var t = property.serializedObject.context; - return t as IExposedPropertyTable; - } - - protected abstract void OnRenderProperty(Rect position, - PropertyName exposedPropertyNameString, - Object currentReferenceValue, - UnityEditor.SerializedProperty exposedPropertyDefault, - UnityEditor.SerializedProperty exposedPropertyName, - ExposedPropertyMode mode, - IExposedPropertyTable exposedProperties); - - public override void OnGUI(Rect position, - UnityEditor.SerializedProperty prop, - GUIContent label) - { - SerializedProperty defaultValue = prop.FindPropertyRelative("defaultValue"); - SerializedProperty exposedName = prop.FindPropertyRelative("exposedName"); - var exposedNameStr = exposedName.stringValue; - var propertyMode = GetExposedPropertyMode(exposedNameStr); - - Rect propertyFieldPosition = position; - propertyFieldPosition.xMax = propertyFieldPosition.xMax - ExposedReferencePropertyDrawer.kDriveWidgetWidth; - - Rect driveFieldPosition = position; - driveFieldPosition.x = propertyFieldPosition.xMax; - driveFieldPosition.width = ExposedReferencePropertyDrawer.kDriveWidgetWidth; - - var exposedPropertyTable = GetExposedPropertyTable(prop); - - bool showContextMenu = exposedPropertyTable != null; - var propertyName = new PropertyName(exposedNameStr); - - OverrideState currentOverrideState = OverrideState.DefaultValue; - var currentReferenceValue = Resolve(propertyName, exposedPropertyTable, defaultValue.objectReferenceValue, out currentOverrideState); - - var previousColor = GUI.color; - var wasBoldDefaultFont = EditorGUIUtility.GetBoldDefaultFont(); - - var valuePosition = DrawLabel(showContextMenu, currentOverrideState, label, position, exposedPropertyTable, exposedNameStr, exposedName, defaultValue); - - EditorGUI.BeginChangeCheck(); - if (propertyMode == ExposedPropertyMode.DefaultValue || propertyMode == ExposedPropertyMode.NamedGUID) - { - OnRenderProperty(valuePosition, propertyName, currentReferenceValue, defaultValue, exposedName, propertyMode, exposedPropertyTable); - } - else - { - valuePosition.width /= 2; - EditorGUI.BeginChangeCheck(); - exposedNameStr = EditorGUI.TextField(valuePosition, exposedNameStr); - if (EditorGUI.EndChangeCheck()) - exposedName.stringValue = exposedNameStr; - - valuePosition.x += valuePosition.width; - OnRenderProperty(valuePosition, new PropertyName(exposedNameStr), currentReferenceValue, defaultValue, exposedName, propertyMode, exposedPropertyTable); - } - - EditorGUI.EndDisabledGroup(); - - GUI.color = previousColor; - EditorGUIUtility.SetBoldDefaultFont(wasBoldDefaultFont); - - - if (showContextMenu && GUI.Button(driveFieldPosition, GUIContent.none, kDropDownStyle)) - { - GenericMenu menu = new GenericMenu(); - PopulateContextMenu(menu, currentOverrideState, exposedPropertyTable, exposedName, defaultValue); - menu.ShowAsContext(); - Event.current.Use(); - } - } - - Rect DrawLabel(bool showContextMenu, OverrideState currentOverrideState, GUIContent label, Rect position, IExposedPropertyTable exposedPropertyTable, string exposedNameStr, SerializedProperty exposedName, SerializedProperty defaultValue) - { - if (showContextMenu) - { - position.xMax = position.xMax - ExposedReferencePropertyDrawer.kDriveWidgetWidth; - } - - EditorGUIUtility.SetBoldDefaultFont(currentOverrideState != OverrideState.DefaultValue); - - m_ModifiedLabel.text = label.text; - m_ModifiedLabel.tooltip = label.tooltip; - m_ModifiedLabel.image = label.image; - - if (!string.IsNullOrEmpty(m_ModifiedLabel.tooltip)) - { - m_ModifiedLabel.tooltip += "\n"; - } - if (currentOverrideState == OverrideState.MissingOverride) - { - GUI.color = kMissingOverrideColor; - m_ModifiedLabel.tooltip += label.text + " " + NotFoundOn.text + " " + exposedPropertyTable.ToString() + "."; - } - else if (currentOverrideState == OverrideState.Overridden && exposedPropertyTable != null) - { - m_ModifiedLabel.tooltip += OverridenByContent.text + exposedPropertyTable.ToString() + "."; - } - - var prefixRect = EditorGUI.PrefixLabel(position, m_ModifiedLabel); - - // Show contextual menu - if (exposedPropertyTable != null && Event.current.type == EventType.ContextClick) - { - if (position.Contains(Event.current.mousePosition)) - { - GenericMenu menu = new GenericMenu(); - PopulateContextMenu(menu, string.IsNullOrEmpty(exposedNameStr) ? OverrideState.DefaultValue : OverrideState.Overridden, exposedPropertyTable, exposedName, defaultValue); - menu.ShowAsContext(); - } - } - - return prefixRect; - } - - protected Object Resolve(PropertyName exposedPropertyName, IExposedPropertyTable exposedPropertyTable, Object defaultValue, out OverrideState currentOverrideState) - { - Object objReference = null; - bool propertyFoundInTable = false; - var propertyIsNamed = !PropertyName.IsNullOrEmpty(exposedPropertyName); - currentOverrideState = OverrideState.DefaultValue; - - if (exposedPropertyTable != null) - { - objReference = exposedPropertyTable.GetReferenceValue(exposedPropertyName, out propertyFoundInTable); - - if (propertyFoundInTable) - currentOverrideState = OverrideState.Overridden; - else if (propertyIsNamed) - currentOverrideState = OverrideState.MissingOverride; - } - - return currentOverrideState == OverrideState.Overridden ? objReference : defaultValue; - } - - protected abstract void PopulateContextMenu(GenericMenu menu, OverrideState overrideState, IExposedPropertyTable exposedPropertyTable, SerializedProperty exposedName, SerializedProperty defaultValue); -} - - -[CustomPropertyDrawer(typeof(ExposedReference < >))] -class ExposedReferencePropertyDrawer : BaseExposedPropertyDrawer -{ - protected override void OnRenderProperty(Rect position, - PropertyName exposedPropertyNameString, - Object currentReferenceValue, - UnityEditor.SerializedProperty exposedPropertyDefault, - UnityEditor.SerializedProperty exposedPropertyName, - ExposedPropertyMode mode, - IExposedPropertyTable exposedPropertyTable) - { - var typeOfExposedReference = fieldInfo.FieldType.GetGenericArguments()[0]; - - EditorGUI.BeginChangeCheck(); - var newValue = EditorGUI.ObjectField(position, currentReferenceValue, typeOfExposedReference, exposedPropertyTable != null); - - if (EditorGUI.EndChangeCheck()) - { - if (mode == ExposedPropertyMode.DefaultValue) - { - // We can directly assign to the exposed property default value if - // * asset we are modifying is in the scene - // * object we are assigning to the property is also an asset - if (!EditorUtility.IsPersistent(exposedPropertyDefault.serializedObject.targetObject) || newValue == null || EditorUtility.IsPersistent(newValue)) - { - if (!EditorGUI.CheckForCrossSceneReferencing(exposedPropertyDefault.serializedObject.targetObject, newValue)) - { - exposedPropertyDefault.objectReferenceValue = newValue; - } - } - else - { - var guid = UnityEditor.GUID.Generate(); - var str = guid.ToString(); - exposedPropertyNameString = new PropertyName(str); - exposedPropertyName.stringValue = str; - - Undo.RecordObject(exposedPropertyTable as UnityEngine.Object, "Set Exposed Property"); - exposedPropertyTable.SetReferenceValue(exposedPropertyNameString, newValue); - } - } - else - { - Undo.RecordObject(exposedPropertyTable as UnityEngine.Object, "Set Exposed Property"); - exposedPropertyTable.SetReferenceValue(exposedPropertyNameString, newValue); - } - } - } - - protected override void PopulateContextMenu(GenericMenu menu, OverrideState overrideState, IExposedPropertyTable exposedPropertyTable, SerializedProperty exposedName, SerializedProperty defaultValue) - { - var propertyName = new PropertyName(exposedName.stringValue); - OverrideState currentOverrideState; - UnityEngine.Object currentValue = Resolve(new PropertyName(exposedName.stringValue), exposedPropertyTable, defaultValue.objectReferenceValue, out currentOverrideState); - - if (overrideState == OverrideState.DefaultValue) - { - menu.AddItem(new GUIContent(ExposePropertyContent.text), false, (userData) => - { - var guid = UnityEditor.GUID.Generate(); - exposedName.stringValue = guid.ToString(); - exposedName.serializedObject.ApplyModifiedProperties(); - var newPropertyName = new PropertyName(exposedName.stringValue); - - Undo.RecordObject(exposedPropertyTable as Object, "Set Exposed Property"); - exposedPropertyTable.SetReferenceValue(newPropertyName, currentValue); - } , null); - } - else - { - menu.AddItem(UnexposePropertyContent, false, (userData) => - { - exposedName.stringValue = ""; - exposedName.serializedObject.ApplyModifiedProperties(); - - Undo.RecordObject(exposedPropertyTable as Object, "Clear Exposed Property"); - exposedPropertyTable.ClearReferenceValue(propertyName); - }, null); - } - } -} diff --git a/Editor/Mono/ScriptAttributeGUI/Implementations/PropertyDrawers.cs b/Editor/Mono/ScriptAttributeGUI/Implementations/PropertyDrawers.cs deleted file mode 100644 index e7b3681ccc..0000000000 --- a/Editor/Mono/ScriptAttributeGUI/Implementations/PropertyDrawers.cs +++ /dev/null @@ -1,136 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - // Built-in PropertyDrawers. See matching attributes in PropertyAttribute.cs - - [CustomPropertyDrawer(typeof(RangeAttribute))] - internal sealed class RangeDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - RangeAttribute range = (RangeAttribute)attribute; - if (property.propertyType == SerializedPropertyType.Float) - EditorGUI.Slider(position, property, range.min, range.max, label); - else if (property.propertyType == SerializedPropertyType.Integer) - EditorGUI.IntSlider(position, property, (int)range.min, (int)range.max, label); - else - EditorGUI.LabelField(position, label.text, "Use Range with float or int."); - } - } - - [CustomPropertyDrawer(typeof(MultilineAttribute))] - internal sealed class MultilineDrawer : PropertyDrawer - { - private const int kLineHeight = 13; - - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - if (property.propertyType == SerializedPropertyType.String) - { - label = EditorGUI.BeginProperty(position, label, property); - - position = EditorGUI.MultiFieldPrefixLabel(position, 0, label, 1); - - EditorGUI.BeginChangeCheck(); - int oldIndent = EditorGUI.indentLevel; - EditorGUI.indentLevel = 0; // The MultiFieldPrefixLabel already applied indent, so avoid indent of TextArea itself. - string newValue = EditorGUI.TextArea(position, property.stringValue); - EditorGUI.indentLevel = oldIndent; - if (EditorGUI.EndChangeCheck()) - property.stringValue = newValue; - - EditorGUI.EndProperty(); - } - else - EditorGUI.LabelField(position, label.text, "Use Multiline with string."); - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - return (EditorGUIUtility.wideMode ? 0 : EditorGUI.kSingleLineHeight) // header - + EditorGUI.kSingleLineHeight // first line - + (((MultilineAttribute)attribute).lines - 1) * kLineHeight; // remaining lines - } - } - - [CustomPropertyDrawer(typeof(TextAreaAttribute))] - internal sealed class TextAreaDrawer : PropertyDrawer - { - private const int kLineHeight = 13; - - private Vector2 m_ScrollPosition = new Vector2(); - - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - if (property.propertyType == SerializedPropertyType.String) - { - label = EditorGUI.BeginProperty(position, label, property); - Rect labelPosition = EditorGUI.IndentedRect(position); - labelPosition.height = EditorGUI.kSingleLineHeight; - position.yMin += labelPosition.height; - EditorGUI.HandlePrefixLabel(position, labelPosition, label); - - EditorGUI.BeginChangeCheck(); - string newValue = EditorGUI.ScrollableTextAreaInternal(position, property.stringValue, ref m_ScrollPosition, EditorStyles.textArea); - if (EditorGUI.EndChangeCheck()) - property.stringValue = newValue; - - EditorGUI.EndProperty(); - } - else - EditorGUI.LabelField(position, label.text, "Use TextAreaDrawer with string."); - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - TextAreaAttribute textAreaAttribute = attribute as TextAreaAttribute; - string text = property.stringValue; - - float fullTextHeight = EditorStyles.textArea.CalcHeight(GUIContent.Temp(text), EditorGUIUtility.contextWidth); - int lines = Mathf.CeilToInt(fullTextHeight / kLineHeight); - - lines = Mathf.Clamp(lines, textAreaAttribute.minLines, textAreaAttribute.maxLines); - - return EditorGUI.kSingleLineHeight // header - + EditorGUI.kSingleLineHeight // first line - + (lines - 1) * kLineHeight; // remaining lines - } - } - - [CustomPropertyDrawer(typeof(ColorUsageAttribute))] - internal sealed class ColorUsageDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - var colorUsage = (ColorUsageAttribute)attribute; - - EditorGUI.BeginChangeCheck(); - Color newColor = EditorGUI.ColorField(position, label, property.colorValue, true, colorUsage.showAlpha, colorUsage.hdr); - if (EditorGUI.EndChangeCheck()) - { - property.colorValue = newColor; - } - } - } - - [CustomPropertyDrawer(typeof(DelayedAttribute))] - internal sealed class DelayedDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - if (property.propertyType == SerializedPropertyType.Float) - EditorGUI.DelayedFloatField(position, property, label); - else if (property.propertyType == SerializedPropertyType.Integer) - EditorGUI.DelayedIntField(position, property, label); - else if (property.propertyType == SerializedPropertyType.String) - EditorGUI.DelayedTextField(position, property, label); - else - EditorGUI.LabelField(position, label.text, "Use Delayed with float, int, or string."); - } - } -} diff --git a/Editor/Mono/ScriptAttributeGUI/PropertyDrawer.cs b/Editor/Mono/ScriptAttributeGUI/PropertyDrawer.cs deleted file mode 100644 index 2ee02dddc8..0000000000 --- a/Editor/Mono/ScriptAttributeGUI/PropertyDrawer.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Reflection; -using UnityEngine; - -namespace UnityEditor -{ - // Base class to derive custom property drawers from. Use this to create custom drawers - // for your own [[Serializable]] classes or for script variables with custom [[PropertyAttribute]]s. - public abstract class PropertyDrawer : GUIDrawer - { - internal PropertyAttribute m_Attribute; - internal FieldInfo m_FieldInfo; - - // The [[PropertyAttribute]] for the property. Not applicable for custom class drawers. (RO) - public PropertyAttribute attribute { get { return m_Attribute; } } - - // The reflection FieldInfo for the member this property represents. (RO) - public FieldInfo fieldInfo { get { return m_FieldInfo; } } - - internal void OnGUISafe(Rect position, SerializedProperty property, GUIContent label) - { - ScriptAttributeUtility.s_DrawerStack.Push(this); - OnGUI(position, property, label); - ScriptAttributeUtility.s_DrawerStack.Pop(); - } - - // Override this method to make your own GUI for the property. - public virtual void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - EditorGUI.DefaultPropertyField(position, property, label); - EditorGUI.LabelField(position, label, EditorGUIUtility.TempContent("No GUI Implemented")); - } - - internal float GetPropertyHeightSafe(SerializedProperty property, GUIContent label) - { - ScriptAttributeUtility.s_DrawerStack.Push(this); - float height = GetPropertyHeight(property, label); - ScriptAttributeUtility.s_DrawerStack.Pop(); - return height; - } - - // Override this method to specify how tall the GUI for this field is in pixels. - public virtual float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - return EditorGUI.kSingleLineHeight; - } - - internal bool CanCacheInspectorGUISafe(SerializedProperty property) - { - ScriptAttributeUtility.s_DrawerStack.Push(this); - bool canCache = CanCacheInspectorGUI(property); - ScriptAttributeUtility.s_DrawerStack.Pop(); - return canCache; - } - - public virtual bool CanCacheInspectorGUI(SerializedProperty property) - { - return true; - } - } -} diff --git a/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs b/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs deleted file mode 100644 index fe1039077d..0000000000 --- a/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs +++ /dev/null @@ -1,293 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using System.Reflection; -using UnityEngine; - -namespace UnityEditor -{ - internal class PropertyHandler - { - //private int m_Hash = 0; - - private PropertyDrawer m_PropertyDrawer = null; - - private List m_DecoratorDrawers = null; - public string tooltip = null; - - public bool hasPropertyDrawer { get { return propertyDrawer != null; } } - private PropertyDrawer propertyDrawer { get { return isCurrentlyNested ? null : m_PropertyDrawer; } } - - private bool isCurrentlyNested - { - get - { - return (m_PropertyDrawer != null - && ScriptAttributeUtility.s_DrawerStack.Count > 0 - && m_PropertyDrawer == ScriptAttributeUtility.s_DrawerStack.Peek()); - } - } - - public List contextMenuItems = null; - - public bool empty - { - get - { - return m_DecoratorDrawers == null - && tooltip == null - && propertyDrawer == null - && contextMenuItems == null; - } - } - - public void HandleAttribute(PropertyAttribute attribute, FieldInfo field, Type propertyType) - { - if (attribute is TooltipAttribute) - { - tooltip = (attribute as TooltipAttribute).tooltip; - return; - } - - if (attribute is ContextMenuItemAttribute) - { - // Use context menu items on array elements, not on array itself - if (propertyType.IsArrayOrList()) - return; - if (contextMenuItems == null) - contextMenuItems = new List(); - contextMenuItems.Add(attribute as ContextMenuItemAttribute); - return; - } - - // Look for its drawer type of this attribute - HandleDrawnType(attribute.GetType(), propertyType, field, attribute); - } - - public void HandleDrawnType(Type drawnType, Type propertyType, FieldInfo field, PropertyAttribute attribute) - { - Type drawerType = ScriptAttributeUtility.GetDrawerTypeForType(drawnType); - - // If we found a drawer type, instantiate the drawer, cache it, and return it. - if (drawerType != null) - { - if (typeof(PropertyDrawer).IsAssignableFrom(drawerType)) - { - // Use PropertyDrawer on array elements, not on array itself. - // If there's a PropertyAttribute on an array, we want to apply it to the individual array elements instead. - // This is the only convenient way we can let the user apply PropertyDrawer attributes to elements inside an array. - if (propertyType != null && propertyType.IsArrayOrList()) - return; - - m_PropertyDrawer = (PropertyDrawer)System.Activator.CreateInstance(drawerType); - m_PropertyDrawer.m_FieldInfo = field; - - // Will be null by design if default type drawer! - m_PropertyDrawer.m_Attribute = attribute; - } - else if (typeof(DecoratorDrawer).IsAssignableFrom(drawerType)) - { - // Draw decorators on array itself, not on each array elements - if (field != null && field.FieldType.IsArrayOrList() && !propertyType.IsArrayOrList()) - return; - - DecoratorDrawer decorator = (DecoratorDrawer)System.Activator.CreateInstance(drawerType); - decorator.m_Attribute = attribute; - - if (m_DecoratorDrawers == null) - m_DecoratorDrawers = new List(); - m_DecoratorDrawers.Add(decorator); - } - } - } - - // returns true if children needs to be drawn separately - public bool OnGUI(Rect position, SerializedProperty property, GUIContent label, bool includeChildren) - { - // We can consider making controlIDs robust to support culling optimizations. - // Works well - downside is that you can't use PrefixLabel before a PropertyField, - // but PropertyField has build-in label argument anyway. - //if (m_Hash == 0) - // m_Hash = property.serializedObject.targetObject.GetInstanceID () ^ property.propertyPath.GetHashCode (); - //EditorGUIUtility.GetControlID (m_Hash, FocusType.Passive); - - float oldLabelWidth, oldFieldWidth; - - float propHeight = position.height; - position.height = 0; - if (m_DecoratorDrawers != null && !isCurrentlyNested) - { - foreach (DecoratorDrawer decorator in m_DecoratorDrawers) - { - position.height = decorator.GetHeight(); - - oldLabelWidth = EditorGUIUtility.labelWidth; - oldFieldWidth = EditorGUIUtility.fieldWidth; - decorator.OnGUI(position); - EditorGUIUtility.labelWidth = oldLabelWidth; - EditorGUIUtility.fieldWidth = oldFieldWidth; - - position.y += position.height; - propHeight -= position.height; - } - } - - position.height = propHeight; - if (propertyDrawer != null) - { - // Remember widths - oldLabelWidth = EditorGUIUtility.labelWidth; - oldFieldWidth = EditorGUIUtility.fieldWidth; - // Draw with custom drawer - propertyDrawer.OnGUISafe(position, property.Copy(), label ?? EditorGUIUtility.TempContent(property.localizedDisplayName)); - // Restore widths - EditorGUIUtility.labelWidth = oldLabelWidth; - EditorGUIUtility.fieldWidth = oldFieldWidth; - - return false; - } - else - { - if (!includeChildren) - return EditorGUI.DefaultPropertyField(position, property, label); - - // Remember state - Vector2 oldIconSize = EditorGUIUtility.GetIconSize(); - bool wasEnabled = GUI.enabled; - int origIndent = EditorGUI.indentLevel; - - int relIndent = origIndent - property.depth; - - SerializedProperty prop = property.Copy(); - SerializedProperty endProperty = prop.GetEndProperty(); - - position.height = EditorGUI.GetSinglePropertyHeight(prop, label); - - // First property with custom label - EditorGUI.indentLevel = prop.depth + relIndent; - bool childrenAreExpanded = EditorGUI.DefaultPropertyField(position, prop, label) && EditorGUI.HasVisibleChildFields(prop); - position.y += position.height + EditorGUI.kControlVerticalSpacing; - - // Loop through all child properties - while (prop.NextVisible(childrenAreExpanded) && !SerializedProperty.EqualContents(prop, endProperty)) - { - EditorGUI.indentLevel = prop.depth + relIndent; - position.height = EditorGUI.GetPropertyHeight(prop, null, false); - EditorGUI.BeginChangeCheck(); - childrenAreExpanded = ScriptAttributeUtility.GetHandler(prop).OnGUI(position, prop, null, false) && EditorGUI.HasVisibleChildFields(prop); - // Changing child properties (like array size) may invalidate the iterator, - // so stop now, or we may get errors. - if (EditorGUI.EndChangeCheck()) - break; - - position.y += position.height + EditorGUI.kControlVerticalSpacing; - } - - // Restore state - GUI.enabled = wasEnabled; - EditorGUIUtility.SetIconSize(oldIconSize); - EditorGUI.indentLevel = origIndent; - - return false; - } - } - - public bool OnGUILayout(SerializedProperty property, GUIContent label, bool includeChildren, params GUILayoutOption[] options) - { - Rect r; - if (property.propertyType == SerializedPropertyType.Boolean && propertyDrawer == null && (m_DecoratorDrawers == null || m_DecoratorDrawers.Count == 0)) - r = EditorGUILayout.GetToggleRect(true, options); - else - r = EditorGUILayout.GetControlRect(EditorGUI.LabelHasContent(label), GetHeight(property, label, includeChildren), options); - EditorGUILayout.s_LastRect = r; - return OnGUI(r, property, label, includeChildren); - } - - public float GetHeight(SerializedProperty property, GUIContent label, bool includeChildren) - { - float height = 0; - - if (m_DecoratorDrawers != null && !isCurrentlyNested) - foreach (DecoratorDrawer drawer in m_DecoratorDrawers) - height += drawer.GetHeight(); - - if (propertyDrawer != null) - { - height += propertyDrawer.GetPropertyHeightSafe(property.Copy(), label ?? EditorGUIUtility.TempContent(property.displayName)); - } - else if (!includeChildren) - { - height += EditorGUI.GetSinglePropertyHeight(property, label); - } - else - { - property = property.Copy(); - SerializedProperty endProperty = property.GetEndProperty(); - - // First property with custom label - height += EditorGUI.GetSinglePropertyHeight(property, label); - bool childrenAreExpanded = property.isExpanded && EditorGUI.HasVisibleChildFields(property); - - // Loop through all child properties - while (property.NextVisible(childrenAreExpanded) && !SerializedProperty.EqualContents(property, endProperty)) - { - height += ScriptAttributeUtility.GetHandler(property).GetHeight(property, EditorGUIUtility.TempContent(property.displayName), true); - childrenAreExpanded = false; - height += EditorGUI.kControlVerticalSpacing; - } - } - - return height; - } - - public bool CanCacheInspectorGUI(SerializedProperty property) - { - if (m_DecoratorDrawers != null && - !isCurrentlyNested && - m_DecoratorDrawers.Any(decorator => !decorator.CanCacheInspectorGUI())) - return false; - - if (propertyDrawer != null) - return propertyDrawer.CanCacheInspectorGUISafe(property.Copy()); - - property = property.Copy(); - SerializedProperty endProperty = property.GetEndProperty(); - bool childrenAreExpanded = property.isExpanded && EditorGUI.HasVisibleChildFields(property); - - // Loop through all child properties - while (property.NextVisible(childrenAreExpanded) && !SerializedProperty.EqualContents(property, endProperty)) - { - if (!ScriptAttributeUtility.GetHandler(property).CanCacheInspectorGUI(property)) - return false; - childrenAreExpanded = false; - } - - return true; - } - - public void AddMenuItems(SerializedProperty property, GenericMenu menu) - { - if (contextMenuItems == null) - return; - - Type scriptType = property.serializedObject.targetObject.GetType(); - foreach (ContextMenuItemAttribute attribute in contextMenuItems) - { - MethodInfo method = scriptType.GetMethod(attribute.function, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - if (method == null) - continue; - menu.AddItem(new GUIContent(attribute.name), false, () => CallMenuCallback(property.serializedObject.targetObjects, method)); - } - } - - public void CallMenuCallback(object[] targets, MethodInfo method) - { - foreach (object target in targets) - method.Invoke(target, new object[] {}); - } - } -} diff --git a/Editor/Mono/ScriptAttributeGUI/ScriptAttributeUtility.cs b/Editor/Mono/ScriptAttributeGUI/ScriptAttributeUtility.cs deleted file mode 100644 index c7e1373374..0000000000 --- a/Editor/Mono/ScriptAttributeGUI/ScriptAttributeUtility.cs +++ /dev/null @@ -1,284 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using System.Reflection; -using UnityEngine; - -namespace UnityEditor -{ - internal class ScriptAttributeUtility - { - private struct DrawerKeySet - { - public Type drawer; - public Type type; - } - - // Internal API members - internal static Stack s_DrawerStack = new Stack(); - private static Dictionary s_DrawerTypeForType = null; - private static Dictionary> s_BuiltinAttributes = null; - private static PropertyHandler s_SharedNullHandler = new PropertyHandler(); - private static PropertyHandler s_NextHandler = new PropertyHandler(); - - private static PropertyHandlerCache s_GlobalCache = new PropertyHandlerCache(); - private static PropertyHandlerCache s_CurrentCache = null; - - internal static PropertyHandlerCache propertyHandlerCache - { - get - { - return s_CurrentCache ?? s_GlobalCache; - } - set { s_CurrentCache = value; } - } - - internal static void ClearGlobalCache() - { - s_GlobalCache.Clear(); - } - - private static void PopulateBuiltinAttributes() - { - s_BuiltinAttributes = new Dictionary>(); - - AddBuiltinAttribute("GUIText", "m_Text", new MultilineAttribute()); - AddBuiltinAttribute("TextMesh", "m_Text", new MultilineAttribute()); - // Example: Make Orthographic Size in Camera component be in range between 0 and 1000 - //AddBuiltinAttribute ("Camera", "m_OrthographicSize", new RangeAttribute (0, 1000)); - } - - private static void AddBuiltinAttribute(string componentTypeName, string propertyPath, PropertyAttribute attr) - { - string key = componentTypeName + "_" + propertyPath; - if (!s_BuiltinAttributes.ContainsKey(key)) - s_BuiltinAttributes.Add(key, new List()); - s_BuiltinAttributes[key].Add(attr); - } - - private static List GetBuiltinAttributes(SerializedProperty property) - { - if (property.serializedObject.targetObject == null) - return null; - Type t = property.serializedObject.targetObject.GetType(); - if (t == null) - return null; - string attrKey = t.Name + "_" + property.propertyPath; - List attr = null; - s_BuiltinAttributes.TryGetValue(attrKey, out attr); - return attr; - } - - // Called on demand - private static void BuildDrawerTypeForTypeDictionary() - { - s_DrawerTypeForType = new Dictionary(); - - var loadedTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => AssemblyHelper.GetTypesFromAssembly(x)).ToArray(); - - foreach (var type in EditorAssemblies.SubclassesOf(typeof(GUIDrawer))) - { - //Debug.Log("Drawer: " + type); - object[] attrs = type.GetCustomAttributes(typeof(CustomPropertyDrawer), true); - foreach (CustomPropertyDrawer editor in attrs) - { - //Debug.Log("Base type: " + editor.type); - s_DrawerTypeForType[editor.m_Type] = new DrawerKeySet() - { - drawer = type, - type = editor.m_Type - }; - - if (!editor.m_UseForChildren) - continue; - - var candidateTypes = loadedTypes.Where(x => x.IsSubclassOf(editor.m_Type)); - foreach (var candidateType in candidateTypes) - { - //Debug.Log("Candidate Type: "+ candidateType); - if (s_DrawerTypeForType.ContainsKey(candidateType) - && (editor.m_Type.IsAssignableFrom(s_DrawerTypeForType[candidateType].type))) - { - // Debug.Log("skipping"); - continue; - } - - //Debug.Log("Setting"); - s_DrawerTypeForType[candidateType] = new DrawerKeySet() - { - drawer = type, - type = editor.m_Type - }; - } - } - } - } - - internal static Type GetDrawerTypeForType(Type type) - { - if (s_DrawerTypeForType == null) - BuildDrawerTypeForTypeDictionary(); - - DrawerKeySet drawerType; - s_DrawerTypeForType.TryGetValue(type, out drawerType); - if (drawerType.drawer != null) - return drawerType.drawer; - - // now check for base generic versions of the drawers... - if (type.IsGenericType) - s_DrawerTypeForType.TryGetValue(type.GetGenericTypeDefinition(), out drawerType); - - return drawerType.drawer; - } - - private static List GetFieldAttributes(FieldInfo field) - { - if (field == null) - return null; - - object[] attrs = field.GetCustomAttributes(typeof(PropertyAttribute), true); - if (attrs != null && attrs.Length > 0) - return new List(attrs.Select(e => e as PropertyAttribute).OrderBy(e => - e.order)); - - return null; - } - - internal static FieldInfo GetFieldInfoFromProperty(SerializedProperty property, out Type type) - { - var classType = GetScriptTypeFromProperty(property); - if (classType == null) - { - type = null; - return null; - } - return GetFieldInfoFromPropertyPath(classType, property.propertyPath, out type); - } - - private static Type GetScriptTypeFromProperty(SerializedProperty property) - { - SerializedProperty scriptProp = property.serializedObject.FindProperty("m_Script"); - - if (scriptProp == null) - return null; - - MonoScript script = scriptProp.objectReferenceValue as MonoScript; - - if (script == null) - return null; - - return script.GetClass(); - } - - private static FieldInfo GetFieldInfoFromPropertyPath(Type host, string path, out Type type) - { - FieldInfo field = null; - type = host; - string[] parts = path.Split('.'); - for (int i = 0; i < parts.Length; i++) - { - string member = parts[i]; - - // Special handling of array elements. - // The "Array" and "data[x]" parts of the propertyPath don't correspond to any types, - // so they should be skipped by the code that drills down into the types. - // However, we want to change the type from the type of the array to the type of the array element before we do the skipping. - if (i < parts.Length - 1 && member == "Array" && parts[i + 1].StartsWith("data[")) - { - if (type.IsArrayOrList()) - type = type.GetArrayOrListElementType(); - - // Skip rest of handling for this part ("Array") and the next part ("data[x]"). - i++; - continue; - } - - // GetField on class A will not find private fields in base classes to A, - // so we have to iterate through the base classes and look there too. - // Private fields are relevant because they can still be shown in the Inspector, - // and that applies to private fields in base classes too. - FieldInfo foundField = null; - for (Type currentType = type; foundField == null && currentType != null; currentType = currentType.BaseType) - foundField = currentType.GetField(member, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - - if (foundField == null) - { - type = null; - return null; - } - - field = foundField; - type = field.FieldType; - } - return field; - } - - internal static PropertyHandler GetHandler(SerializedProperty property) - { - if (property == null) - return s_SharedNullHandler; - - // Don't use custom drawers in debug mode - if (property.serializedObject.inspectorMode != InspectorMode.Normal) - return s_SharedNullHandler; - - // If the drawer is cached, use the cached drawer - PropertyHandler handler = propertyHandlerCache.GetHandler(property); - if (handler != null) - return handler; - - Type propertyType = null; - List attributes = null; - FieldInfo field = null; - - // Determine if SerializedObject target is a script or a builtin type - UnityEngine.Object target = property.serializedObject.targetObject; - if ((target is MonoBehaviour) || (target is ScriptableObject)) - { - // For scripts, use reflection to get FieldInfo for the member the property represents - field = GetFieldInfoFromProperty(property, out propertyType); - - // Use reflection to see if this member has an attribute - attributes = GetFieldAttributes(field); - } - else - { - // For builtin types, look if we hardcoded an attribute for this property - // First initialize the hardcoded properties if not already done - if (s_BuiltinAttributes == null) - PopulateBuiltinAttributes(); - - if (attributes == null) - attributes = GetBuiltinAttributes(property); - } - - handler = s_NextHandler; - - if (attributes != null) - { - for (int i = attributes.Count - 1; i >= 0; i--) - handler.HandleAttribute(attributes[i], field, propertyType); - } - - // Field has no CustomPropertyDrawer attribute with matching drawer so look for default drawer for field type - if (!handler.hasPropertyDrawer && propertyType != null) - handler.HandleDrawnType(propertyType, propertyType, field, null); - - if (handler.empty) - { - propertyHandlerCache.SetHandler(property, s_SharedNullHandler); - handler = s_SharedNullHandler; - } - else - { - propertyHandlerCache.SetHandler(property, handler); - s_NextHandler = new PropertyHandler(); - } - - return handler; - } - } -} diff --git a/Editor/Mono/ScriptEditorUtility.cs b/Editor/Mono/ScriptEditorUtility.cs deleted file mode 100644 index 293a1f2364..0000000000 --- a/Editor/Mono/ScriptEditorUtility.cs +++ /dev/null @@ -1,144 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -using System.IO; -using System.Collections.Generic; -using UnityEditor.Utils; -using UnityEditor.Scripting.ScriptCompilation; - -namespace UnityEditorInternal -{ - public class ScriptEditorUtility - { - // Keep in sync with enum ScriptEditorType in ExternalEditor.h - public enum ScriptEditor { SystemDefault = 0, MonoDevelop = 1, VisualStudio = 2, VisualStudioExpress = 3, VisualStudioCode = 4, Rider = 5, Other = 32 } - - public static ScriptEditor GetScriptEditorFromPath(string path) - { - string lowerCasePath = path.ToLower(); - - if (lowerCasePath == "internal") - return ScriptEditor.SystemDefault; - - if (lowerCasePath.Contains("monodevelop") || lowerCasePath.Contains("xamarinstudio") || lowerCasePath.Contains("xamarin studio")) - return ScriptEditor.MonoDevelop; - - if (lowerCasePath.EndsWith("devenv.exe")) - return ScriptEditor.VisualStudio; - - if (lowerCasePath.EndsWith("vcsexpress.exe")) - return ScriptEditor.VisualStudioExpress; - - string filename = Path.GetFileName(Paths.UnifyDirectorySeparator(lowerCasePath)).Replace(" ", ""); - - // Visual Studio for Mac is based on MonoDevelop - if (filename == "visualstudio.app") - return ScriptEditor.MonoDevelop; - - if (filename == "code.exe" || filename == "visualstudiocode.app" || filename == "vscode.app" || filename == "code.app" || filename == "code") - return ScriptEditor.VisualStudioCode; - - if (filename == "rider.exe" || filename == "rider64.exe" || filename == "rider32.exe" - || (filename.StartsWith("rider") && filename.EndsWith(".app")) || filename == "rider.sh") - return ScriptEditor.Rider; - - return ScriptEditor.Other; - } - - public static string GetExternalScriptEditor() - { - var editor = EditorPrefs.GetString("kScriptsDefaultApp"); - - if (!string.IsNullOrEmpty(editor)) - return editor; - - // If no script editor is set, try to use first found supported one. - var editorPaths = GetFoundScriptEditorPaths(Application.platform); - - if (editorPaths.Length > 0) - return editorPaths[0]; - - return string.Empty; - } - - public static void SetExternalScriptEditor(string path) - { - EditorPrefs.SetString("kScriptsDefaultApp", path); - } - - static string GetScriptEditorArgsKey(string path) - { - // Starting in Unity 5.5, we support setting script editor arguments on OSX and - // use then when opening the script editor. - // Before Unity 5.5, we would still save the default script editor args in EditorPrefs, - // even though we never used them. This means that the user potentially has some - // script editor args saved and once he upgrades to 5.5, they will be used when - // open the script editor. Which unintended and causes a regression in behaviour. - // So on OSX we change the key for per application for script editor args, - // to avoid reading the one from previous versions. - if (Application.platform == RuntimePlatform.OSXEditor) - return "kScriptEditorArgs_" + path; - - return "kScriptEditorArgs" + path; - } - - static string GetDefaultStringEditorArgs() - { - // On OSX there is a built-in mechanism for opening files in apps. - // We use this mechanism when the external script editor args are not set. - // Which was the only support behaviour before Unity 5.5. We therefor - // default to this behavior. - // If the script editor args are set, we only launch the script editor with args - // specified and do not use the built-in mechanism for opening script files. - if (Application.platform == RuntimePlatform.OSXEditor) - return ""; - - return "\"$(File)\""; - } - - public static string GetExternalScriptEditorArgs() - { - string editor = GetExternalScriptEditor(); - var scriptEditor = GetScriptEditorFromPath(editor); - - if (scriptEditor != ScriptEditor.Other) - return ""; - - return EditorPrefs.GetString(GetScriptEditorArgsKey(editor), GetDefaultStringEditorArgs()); - } - - public static void SetExternalScriptEditorArgs(string args) - { - string editor = GetExternalScriptEditor(); - - EditorPrefs.SetString(GetScriptEditorArgsKey(editor), args); - } - - public static ScriptEditor GetScriptEditorFromPreferences() - { - return GetScriptEditorFromPath(GetExternalScriptEditor()); - } - - public static string[] GetFoundScriptEditorPaths(RuntimePlatform platform) - { - var result = new List(); - - if (platform == RuntimePlatform.OSXEditor) - { - AddIfDirectoryExists("/Applications/Visual Studio.app", result); - } - - return result.ToArray(); - } - - static void AddIfDirectoryExists(string path, List list) - { - if (Directory.Exists(path)) - list.Add(path); - } - } -} diff --git a/Editor/Mono/ScriptableSingleton.cs b/Editor/Mono/ScriptableSingleton.cs deleted file mode 100644 index c9dc59db13..0000000000 --- a/Editor/Mono/ScriptableSingleton.cs +++ /dev/null @@ -1,128 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.IO; -using UnityEditorInternal; -using Object = UnityEngine.Object; - - -namespace UnityEditor -{ - // Use the FilePathAttribute when you want to have your scriptable singleton to persist between unity sessions. - // Example: [FilePathAttribute("Library/SearchFilters.ssf", FilePathAttribute.Location.ProjectFolder)] - // Ensure to call Save() from client code (derived instance) - [AttributeUsage(AttributeTargets.Class)] - class FilePathAttribute : Attribute - { - public enum Location { PreferencesFolder, ProjectFolder } - public string filepath {get; set; } - public FilePathAttribute(string relativePath, Location location) - { - if (string.IsNullOrEmpty(relativePath)) - { - Debug.LogError("Invalid relative path! (its null or empty)"); - return; - } - - // We do not want a slash as first char - if (relativePath[0] == '/') - relativePath = relativePath.Substring(1); - - if (location == Location.PreferencesFolder) - filepath = InternalEditorUtility.unityPreferencesFolder + "/" + relativePath; - else //location == Location.ProjectFolder - filepath = relativePath; - } - } - - - public class ScriptableSingleton : ScriptableObject where T : ScriptableObject - { - static T s_Instance; - - public static T instance - { - get - { - if (s_Instance == null) - CreateAndLoad(); - - return s_Instance; - } - } - - // On domain reload ScriptableObject objects gets reconstructed from a backup. We therefore set the s_Instance here - protected ScriptableSingleton() - { - if (s_Instance != null) - { - Debug.LogError("ScriptableSingleton already exists. Did you query the singleton in a constructor?"); - } - else - { - object casted = this; - s_Instance = casted as T; - System.Diagnostics.Debug.Assert(s_Instance != null); - } - } - - private static void CreateAndLoad() - { - System.Diagnostics.Debug.Assert(s_Instance == null); - - // Load - string filePath = GetFilePath(); - if (!string.IsNullOrEmpty(filePath)) - { - // If a file exists the - InternalEditorUtility.LoadSerializedFileAndForget(filePath); - } - - if (s_Instance == null) - { - // Create - T t = CreateInstance(); - t.hideFlags = HideFlags.HideAndDontSave; - } - - System.Diagnostics.Debug.Assert(s_Instance != null); - } - - protected virtual void Save(bool saveAsText) - { - if (s_Instance == null) - { - Debug.Log("Cannot save ScriptableSingleton: no instance!"); - return; - } - - string filePath = GetFilePath(); - if (!string.IsNullOrEmpty(filePath)) - { - string folderPath = Path.GetDirectoryName(filePath); - if (!Directory.Exists(folderPath)) - Directory.CreateDirectory(folderPath); - - InternalEditorUtility.SaveToSerializedFileAndForget(new[] { s_Instance }, filePath, saveAsText); - } - } - - private static string GetFilePath() - { - Type type = typeof(T); - object[] atributes = type.GetCustomAttributes(true); - foreach (object attr in atributes) - { - if (attr is FilePathAttribute) - { - FilePathAttribute f = attr as FilePathAttribute; - return f.filepath; - } - } - return null; - } - } -} diff --git a/Editor/Mono/ScriptableSingletonDictionary.cs b/Editor/Mono/ScriptableSingletonDictionary.cs deleted file mode 100644 index 7e0a0e2cff..0000000000 --- a/Editor/Mono/ScriptableSingletonDictionary.cs +++ /dev/null @@ -1,147 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.IO; -using UnityEditorInternal; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - // Use the LibraryFolderPathAttribute when you want to have your scriptable singleton dictionary - // to persist between unity sessions. - // Example: [LibraryFolderPathAttribute("EditorWindows")] - [AttributeUsage(AttributeTargets.Class)] - class LibraryFolderPathAttribute : Attribute - { - public string folderPath { get; set; } - public LibraryFolderPathAttribute(string relativePath) - { - if (string.IsNullOrEmpty(relativePath)) - { - Debug.LogError("Invalid relative path! (its null or empty)"); - return; - } - - // We do not want a slash as first char. - if (relativePath[0] == '/') - throw new ArgumentException("Folder relative path cannot start with a slash."); - - folderPath = "Library/" + relativePath; - } - } - - internal abstract class ScriptableSingletonDictionary : ScriptableObject - where TDerived : ScriptableObject - where TValue : ScriptableObject - { - private static TDerived s_Instance; - static readonly string k_Extension = ".pref"; - - protected string m_PreferencesFileName; - - public static TDerived instance - { - get - { - if (s_Instance == null) - { - s_Instance = ScriptableObject.CreateInstance(); - s_Instance.hideFlags = HideFlags.HideAndDontSave; - } - return s_Instance; - } - } - - public TValue this[string preferencesFileName] - { - get - { - return Load(preferencesFileName); - } - } - - private TValue CreateNewValue() - { - TValue value = ScriptableObject.CreateInstance(); - value.hideFlags |= HideFlags.HideAndDontSave; - return value; - } - - private string GetProjectRelativePath(string file) - { - return GetFolderPath() + "/" + file + k_Extension; - } - - // Save() should be called whenever the user of this data store - // believes the data might have changed and needs to be updated - // in the pref file. Otherwise, Save() will only be called when - // switching between pref files by accessing with different keys. - public void Save(string preferencesFileName, TValue value) - { - const bool saveAsText = true; - - Debug.Assert(preferencesFileName != null && value != null, "Should always have valid key/values."); - if (string.IsNullOrEmpty(preferencesFileName) || value == null) - return; - - // if there is no key the object does not exist on disk, - // so there is no guid associated with it - string file = preferencesFileName; - if (string.IsNullOrEmpty(file)) - return; - - // make sure the path exists or file write will fail - string fullPath = Application.dataPath + "/../" + GetFolderPath(); - if (!System.IO.Directory.Exists(fullPath)) - System.IO.Directory.CreateDirectory(fullPath); - - InternalEditorUtility.SaveToSerializedFileAndForget(new[] { value }, GetProjectRelativePath(file), saveAsText); - } - - public void Clear(string preferencesFileName) - { - string fullPath = Application.dataPath + "/../" + GetProjectRelativePath(preferencesFileName); - if (System.IO.File.Exists(fullPath)) - System.IO.File.Delete(fullPath); - } - - private TValue Load(string preferencesFileName) - { - TValue value = null; - string file = preferencesFileName; - if (!string.IsNullOrEmpty(file)) - { - var objects = InternalEditorUtility.LoadSerializedFileAndForget(GetProjectRelativePath(file)); - if (objects != null && objects.Length > 0) - { - value = objects[0] as TValue; - if (value != null) - value.hideFlags |= HideFlags.HideAndDontSave; - } - } - - m_PreferencesFileName = preferencesFileName; - return value ?? CreateNewValue(); - } - - private string GetFolderPath() - { - Type type = this.GetType(); - object[] attributes = type.GetCustomAttributes(true); - foreach (object attr in attributes) - { - if (attr is LibraryFolderPathAttribute) - { - LibraryFolderPathAttribute f = attr as LibraryFolderPathAttribute; - return f.folderPath; - } - } - - // The folder path attribute is required. - throw new ArgumentException("The LibraryFolderPathAttribute[] attribute is required for this class."); - } - } -} diff --git a/Editor/Mono/Scripting/APIUpdaterHelper.cs b/Editor/Mono/Scripting/APIUpdaterHelper.cs deleted file mode 100644 index 4aa6fce237..0000000000 --- a/Editor/Mono/Scripting/APIUpdaterHelper.cs +++ /dev/null @@ -1,365 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using UnityEditor.Utils; -using UnityEngine; -using UnityEngine.Scripting.APIUpdating; -using System.Linq; - -using System.Diagnostics; -using System.Text; -using System.Text.RegularExpressions; -using ICSharpCode.NRefactory; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.NRefactory.Visitors; -using Mono.Cecil; -using Unity.DataContract; -using UnityEditor.Modules; -using UnityEditor.Scripting.Compilers; -using Debug = UnityEngine.Debug; -using SupportedLanguage = ICSharpCode.NRefactory.SupportedLanguage; -using TypeReference = ICSharpCode.NRefactory.Ast.TypeReference; - -namespace UnityEditor.Scripting -{ - internal class APIUpdaterHelper - { - public static bool IsReferenceToMissingObsoleteMember(string namespaceName, string className) - { - try - { - var found = FindTypeInLoadedAssemblies(t => t.Name == className && t.Namespace == namespaceName && IsUpdateable(t)); - return found != null; - } - catch (ReflectionTypeLoadException ex) - { - throw new Exception(ex.Message + ex.LoaderExceptions.Aggregate("", (acc, curr) => acc + "\r\n\t" + curr.Message)); - } - } - - public static bool IsReferenceToTypeWithChangedNamespace(string normalizedErrorMessage) - { - try - { - var lines = normalizedErrorMessage.Split('\n'); - var simpleOrQualifiedName = GetValueFromNormalizedMessage(lines, "EntityName="); - - var found = FindExactTypeMatchingMovedType(simpleOrQualifiedName) ?? FindTypeMatchingMovedTypeBasedOnNamespaceFromError(lines); - return found != null; - } - catch (ReflectionTypeLoadException ex) - { - throw new Exception(ex.Message + ex.LoaderExceptions.Aggregate("", (acc, curr) => acc + "\r\n\t" + curr.Message)); - } - } - - public static void Run(string commaSeparatedListOfAssemblies) - { - var assemblies = commaSeparatedListOfAssemblies.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries); - APIUpdaterLogger.WriteToFile("Started to update {0} assemblie(s)", assemblies.Count()); - - var sw = new Stopwatch(); - sw.Start(); - - foreach (var assemblyPath in assemblies) - { - if (!AssemblyHelper.IsManagedAssembly(assemblyPath)) - continue; - - string stdOut, stdErr; - var assemblyFullPath = ResolveAssemblyPath(assemblyPath); - var exitCode = RunUpdatingProgram("AssemblyUpdater.exe", "-u -a " + assemblyFullPath + APIVersionArgument() + AssemblySearchPathArgument() + ConfigurationProviderAssembliesPathArgument(), out stdOut, out stdErr); - if (stdOut.Length > 0) - APIUpdaterLogger.WriteToFile("Assembly update output ({0})\r\n{1}", assemblyFullPath, stdOut); - - if (IsError(exitCode)) - APIUpdaterLogger.WriteErrorToConsole("Error {0} running AssemblyUpdater. Its output is: `{1}`", exitCode, stdErr); - } - - APIUpdaterLogger.WriteToFile("Update finished in {0}s", sw.Elapsed.TotalSeconds); - } - - private static bool IsError(int exitCode) - { - return (exitCode & (1 << 7)) != 0; - } - - private static string ResolveAssemblyPath(string assemblyPath) - { - return CommandLineFormatter.PrepareFileName(assemblyPath); - } - - public static bool DoesAssemblyRequireUpgrade(string assemblyFullPath) - { - if (!File.Exists(assemblyFullPath)) - return false; - - if (!AssemblyHelper.IsManagedAssembly(assemblyFullPath)) - return false; - - if (!MayContainUpdatableReferences(assemblyFullPath)) - return false; - - string stdOut, stdErr; - var ret = RunUpdatingProgram("AssemblyUpdater.exe", TimeStampArgument() + APIVersionArgument() + "--check-update-required -a " + CommandLineFormatter.PrepareFileName(assemblyFullPath) + AssemblySearchPathArgument() + ConfigurationProviderAssembliesPathArgument(), out stdOut, out stdErr); - { - Console.WriteLine("{0}{1}", stdOut, stdErr); - switch (ret) - { - // See AssemblyUpdater/Program.cs - case 0: - case 1: return false; - case 2: return true; - - default: - Debug.LogError(stdOut + Environment.NewLine + stdErr); - return false; - } - } - } - - private static string AssemblySearchPathArgument() - { - var searchPath = Path.Combine(MonoInstallationFinder.GetFrameWorksFolder(), "Managed") + "," - + "+" + Path.Combine(EditorApplication.applicationContentsPath, "UnityExtensions/Unity") + "," - + "+" + Application.dataPath; - - return " -s \"" + searchPath + "\""; - } - - private static string ConfigurationProviderAssembliesPathArgument() - { - var paths = new StringBuilder(); - foreach (var ext in ModuleManager.packageManager.unityExtensions) - { - foreach (var dllPath in ext.files.Where(f => f.Value.type == PackageFileType.Dll).Select(pi => pi.Key)) - { - paths.AppendFormat(" {0}", CommandLineFormatter.PrepareFileName(Path.Combine(ext.basePath, dllPath))); - } - } - - var editorManagedPath = GetUnityEditorManagedPath(); - paths.AppendFormat(" {0}", CommandLineFormatter.PrepareFileName(Path.Combine(editorManagedPath, "UnityEngine.dll"))); - paths.AppendFormat(" {0}", CommandLineFormatter.PrepareFileName(Path.Combine(editorManagedPath, "UnityEditor.dll"))); - - return paths.ToString(); - } - - private static string GetUnityEditorManagedPath() - { - return Path.Combine(MonoInstallationFinder.GetFrameWorksFolder(), "Managed"); - } - - private static int RunUpdatingProgram(string executable, string arguments, out string stdOut, out string stdErr) - { - var scriptUpdater = EditorApplication.applicationContentsPath + "/Tools/ScriptUpdater/" + executable; - var program = new ManagedProgram(MonoInstallationFinder.GetMonoInstallation("MonoBleedingEdge"), null, scriptUpdater, arguments, false, null); - - program.LogProcessStartInfo(); - program.Start(); - program.WaitForExit(); - - stdOut = program.GetStandardOutputAsString(); - stdErr = string.Join("\r\n", program.GetErrorOutput()); - - return program.ExitCode; - } - - private static string APIVersionArgument() - { - return " --api-version " + Application.unityVersion + " "; - } - - private static string TimeStampArgument() - { - return " --timestamp " + DateTime.Now.Ticks + " "; - } - - private static bool IsUpdateable(Type type) - { - var attrs = type.GetCustomAttributes(typeof(ObsoleteAttribute), false); - if (attrs.Length != 1) - return false; - - var oa = (ObsoleteAttribute)attrs[0]; - return oa.Message.Contains("UnityUpgradable"); - } - - private static bool NamespaceHasChanged(Type type, string namespaceName) - { - var attrs = type.GetCustomAttributes(typeof(MovedFromAttribute), false); - if (attrs.Length != 1) - return false; - - if (string.IsNullOrEmpty(namespaceName)) - return true; - - var from = (MovedFromAttribute)attrs[0]; - return from.Namespace == namespaceName; - } - - private static Type FindTypeInLoadedAssemblies(Func predicate) - { - var found = AppDomain.CurrentDomain.GetAssemblies() - .Where(assembly => !IsIgnoredAssembly(assembly.GetName())) - .SelectMany(a => GetValidTypesIn(a)) - .FirstOrDefault(predicate); - - return found; - } - - private static IEnumerable GetValidTypesIn(Assembly a) - { - Type[] types; - try - { - types = a.GetTypes(); - } - catch (ReflectionTypeLoadException e) - { - types = e.Types; - } - - return types.Where(t => t != null); - } - - private static bool IsIgnoredAssembly(AssemblyName assemblyName) - { - var name = assemblyName.Name; - return _ignoredAssemblies.Any(candidate => Regex.IsMatch(name, candidate)); - } - - internal static bool MayContainUpdatableReferences(string assemblyPath) - { - using (var assembly = AssemblyDefinition.ReadAssembly(assemblyPath)) - { - if (assembly.Name.IsWindowsRuntime) - return false; - - if (!IsTargetFrameworkValidOnCurrentOS(assembly)) - return false; - } - - return true; - } - - private static bool IsTargetFrameworkValidOnCurrentOS(AssemblyDefinition assembly) - { - return Environment.OSVersion.Platform == PlatformID.Win32NT - || !(assembly.HasCustomAttributes && assembly.CustomAttributes.Any(attr => TargetsWindowsSpecificFramework(attr))); - } - - private static bool TargetsWindowsSpecificFramework(CustomAttribute targetFrameworkAttr) - { - if (!targetFrameworkAttr.AttributeType.FullName.Contains("System.Runtime.Versioning.TargetFrameworkAttribute")) - return false; - - var regex = new Regex("\\.NETCore|\\.NETPortable"); - var targetsNetCoreOrPCL = targetFrameworkAttr.ConstructorArguments.Any(arg => arg.Type.FullName == typeof(string).FullName && regex.IsMatch((string)arg.Value)); - - return targetsNetCoreOrPCL; - } - - private static Type FindExactTypeMatchingMovedType(string simpleOrQualifiedName) - { - var match = Regex.Match(simpleOrQualifiedName, @"^(?:(?.*)(?=\.)\.)?(?[a-zA-Z_0-9]+)$"); - if (!match.Success) - return null; - - var typename = match.Groups["typename"].Value; - var namespaceName = match.Groups["namespace"].Value; - - return FindTypeInLoadedAssemblies(t => t.Name == typename && NamespaceHasChanged(t, namespaceName)); - } - - // C# compiler does not emmit the full qualified type name when it fails to resolve a 'theorically', fully qualified type reference - // for instance, if 'NSBar', a namespace gets renamed to 'NSBar2', a refernce to 'NSFoo.NSBar.TypeBaz' will emit an error - // with only NSBar and NSFoo in the message. In this case we use NRefactory to dive in to the code, looking for type references - // in the reported error line/column - private static Type FindTypeMatchingMovedTypeBasedOnNamespaceFromError(IEnumerable lines) - { - var value = GetValueFromNormalizedMessage(lines, "Line="); - var line = (value != null) ? Int32.Parse(value) : -1; - - value = GetValueFromNormalizedMessage(lines, "Column="); - var column = (value != null) ? Int32.Parse(value) : -1; - - var script = GetValueFromNormalizedMessage(lines, "Script="); - if (line == -1 || column == -1 || script == null) - { - return null; - } - - try - { - using (var scriptStream = File.Open(script, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - { - var parser = ParserFactory.CreateParser(SupportedLanguage.CSharp, new StreamReader(scriptStream)); - parser.Lexer.EvaluateConditionalCompilation = false; - parser.Parse(); - - var typeNotFound = InvalidTypeOrNamespaceErrorTypeMapper.IsTypeMovedToNamespaceError(parser.CompilationUnit, line, column); - if (typeNotFound == null) - return null; - - return FindExactTypeMatchingMovedType(typeNotFound); - } - } - catch (FileNotFoundException) - { - return null; - } - } - - private static string GetValueFromNormalizedMessage(IEnumerable lines, string marker) - { - string value = null; - var foundLine = lines.FirstOrDefault(l => l.StartsWith(marker)); - if (foundLine != null) - { - value = foundLine.Substring(marker.Length).Trim(); - } - return value; - } - - private static string[] _ignoredAssemblies = { "^UnityScript$", "^System\\..*", "^mscorlib$" }; - } - - internal class InvalidTypeOrNamespaceErrorTypeMapper : AbstractAstVisitor - { - public static string IsTypeMovedToNamespaceError(CompilationUnit cu, int line, int column) - { - var self = new InvalidTypeOrNamespaceErrorTypeMapper(line, column); - cu.AcceptVisitor(self, null); - - return self.Found; - } - - public string Found { get; private set; } - - private readonly int _line; - private readonly int _column; - - public override object VisitTypeReference(TypeReference typeReference, object data) - { - var withinRange = _column >= typeReference.StartLocation.Column && _column < typeReference.StartLocation.Column + typeReference.Type.Length; - if (typeReference.StartLocation.Line == _line && withinRange) - { - Found = typeReference.Type; - return true; - } - return base.VisitTypeReference(typeReference, data); - } - - private InvalidTypeOrNamespaceErrorTypeMapper(int line, int column) - { - _line = line; - _column = column; - } - } -} diff --git a/Editor/Mono/Scripting/APIUpdaterLogger.cs b/Editor/Mono/Scripting/APIUpdaterLogger.cs deleted file mode 100644 index 4c94d1b9ed..0000000000 --- a/Editor/Mono/Scripting/APIUpdaterLogger.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor.Scripting -{ - internal class APIUpdaterLogger - { - public static void WriteToFile(string msg, params object[] args) - { - Console.WriteLine("[Script API Updater] {0}", string.Format(msg, args)); - } - - public static void WriteErrorToConsole(string msg, params object[] args) - { - Debug.LogErrorFormat(msg, args); - } - - public static void WriteInfoToConsole(string line) - { - Debug.Log(line); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/APIUpdater.cs b/Editor/Mono/Scripting/Compilers/APIUpdater.cs deleted file mode 100644 index 39e80361c6..0000000000 --- a/Editor/Mono/Scripting/Compilers/APIUpdater.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.Utils; -using UnityEditor.VersionControl; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor.Scripting.Compilers -{ - internal class APIUpdaterHelper - { - public static void UpdateScripts(string responseFile, string sourceExtension) - { - if (!ScriptUpdatingManager.WaitForVCSServerConnection(true)) - { - return; - } - - var outputPath = Provider.enabled ? tempOutputPath : "."; - RunUpdatingProgram( - "ScriptUpdater.exe", - sourceExtension - + " " - + CommandLineFormatter.PrepareFileName(MonoInstallationFinder.GetFrameWorksFolder()) - + " " - + outputPath - + " " - + responseFile); - } - - private static void RunUpdatingProgram(string executable, string arguments) - { - var scriptUpdater = EditorApplication.applicationContentsPath + "/Tools/ScriptUpdater/" + executable; - var program = new ManagedProgram(MonoInstallationFinder.GetMonoInstallation("MonoBleedingEdge"), null, scriptUpdater, arguments, false, null); - program.LogProcessStartInfo(); - program.Start(); - program.WaitForExit(); - - Console.WriteLine(string.Join(Environment.NewLine, program.GetStandardOutput())); - - HandleUpdaterReturnValue(program); - } - - private static void HandleUpdaterReturnValue(ManagedProgram program) - { - if (program.ExitCode == 0) - { - Console.WriteLine(string.Join(Environment.NewLine, program.GetErrorOutput())); - UpdateFilesInVCIfNeeded(); - return; - } - - ScriptUpdatingManager.ReportExpectedUpdateFailure(); - if (program.ExitCode > 0) - ReportAPIUpdaterFailure(program.GetErrorOutput()); - else - ReportAPIUpdaterCrash(program.GetErrorOutput()); - } - - private static void ReportAPIUpdaterCrash(IEnumerable errorOutput) - { - Debug.LogErrorFormat("Failed to run script updater.{0}Please, report a bug to Unity with these details{0}{1}", Environment.NewLine, errorOutput.Aggregate("", (acc, curr) => acc + Environment.NewLine + "\t" + curr)); - } - - private static void ReportAPIUpdaterFailure(IEnumerable errorOutput) - { - var msg = string.Format("APIUpdater encountered some issues and was not able to finish.{0}{1}", Environment.NewLine, errorOutput.Aggregate("", (acc, curr) => acc + Environment.NewLine + "\t" + curr)); - ScriptUpdatingManager.ReportGroupedAPIUpdaterFailure(msg); - } - - private static void UpdateFilesInVCIfNeeded() - { - if (!Provider.enabled) - return; - - var files = Directory.GetFiles(tempOutputPath, "*.*", SearchOption.AllDirectories); - - var assetList = new AssetList(); - foreach (string f in files) - assetList.Add(Provider.GetAssetByPath(f.Replace(tempOutputPath, ""))); - - var checkoutTask = Provider.Checkout(assetList, CheckoutMode.Exact); - checkoutTask.Wait(); - - var failedToCheckout = checkoutTask.assetList.Where(a => (a.state & Asset.States.ReadOnly) == Asset.States.ReadOnly); - if (!checkoutTask.success || failedToCheckout.Any()) - { - Debug.LogErrorFormat("[API Updater] Files cannot be updated (failed to check out): {0}", failedToCheckout.Select(a => a.fullName + " (" + a.state + ")").Aggregate((acc, curr) => acc + Environment.NewLine + "\t" + curr)); - ScriptUpdatingManager.ReportExpectedUpdateFailure(); - return; - } - - FileUtil.CopyDirectoryRecursive(tempOutputPath, ".", true); - FileUtil.DeleteFileOrDirectory(tempOutputPath); - } - - private const string tempOutputPath = "Temp/ScriptUpdater/"; - } -} diff --git a/Editor/Mono/Scripting/Compilers/BooCompiler.cs b/Editor/Mono/Scripting/Compilers/BooCompiler.cs deleted file mode 100644 index 2db899a741..0000000000 --- a/Editor/Mono/Scripting/Compilers/BooCompiler.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using System.Linq; -using System.Collections.Generic; -using UnityEditor.Utils; - -namespace UnityEditor.Scripting.Compilers -{ - class BooCompiler : MonoScriptCompilerBase - { - public BooCompiler(MonoIsland island, bool runUpdater) : base(island, runUpdater) - { - } - - override protected Program StartCompiler() - { - var arguments = new List - { - "-debug", - "-target:library", - "-out:" + _island._output, - "-x-type-inference-rule-attribute:" + typeof(UnityEngineInternal.TypeInferenceRuleAttribute) - }; - - foreach (string dll in _island._references) - arguments.Add("-r:" + PrepareFileName(dll)); - foreach (string define in _island._defines.Distinct()) - arguments.Add("-define:" + define); - foreach (string source in _island._files) - arguments.Add(PrepareFileName(source)); - - string compilerPath = Path.Combine(GetMonoProfileLibDirectory(), "booc.exe"); - return StartCompiler(_island._target, compilerPath, arguments); - } - - protected override CompilerOutputParserBase CreateOutputParser() - { - return new BooCompilerOutputParser(); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/BooCompilerOutputParser.cs b/Editor/Mono/Scripting/Compilers/BooCompilerOutputParser.cs deleted file mode 100644 index fef008d186..0000000000 --- a/Editor/Mono/Scripting/Compilers/BooCompilerOutputParser.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Text.RegularExpressions; - -namespace UnityEditor.Scripting.Compilers -{ - class BooCompilerOutputParser : CompilerOutputParserBase - { - private static Regex sCompilerOutput = new Regex(@"\s*(?.*)\((?\d+),(?\d+)\):\s*[BU]C(?W|E)(?[^:]*):\s*(?.*)", RegexOptions.ExplicitCapture); - private static Regex sMissingMember = new Regex(@"[^']*'(?[^']+)'[^']+'(?[^']+)'", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - private static Regex sUnknownTypeOrNamespace = new Regex(@"[^']*'(?[^']+)'.*", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - - protected override string GetErrorIdentifier() - { - return "E"; - } - - protected override Regex GetOutputRegex() - { - return sCompilerOutput; - } - - protected override NormalizedCompilerStatus NormalizedStatusFor(Match match) - { - var status = TryNormalizeCompilerStatus(match, "0019", sMissingMember, NormalizeMemberNotFoundError); - if (status.code != NormalizedCompilerStatusCode.NotNormalized) - return status; - - return TryNormalizeCompilerStatus(match, "0018", sUnknownTypeOrNamespace, NormalizeSimpleUnknownTypeOfNamespaceError); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/BooLanguage.cs b/Editor/Mono/Scripting/Compilers/BooLanguage.cs deleted file mode 100644 index 36f8f30817..0000000000 --- a/Editor/Mono/Scripting/Compilers/BooLanguage.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using Boo.Lang.Parser; - -using System.Linq; - -namespace UnityEditor.Scripting.Compilers -{ - internal class BooLanguage : SupportedLanguage - { - public override string GetExtensionICanCompile() - { - return "boo"; - } - - public override string GetLanguageName() - { - return "Boo"; - } - - public override ScriptCompilerBase CreateCompiler(MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) - { - return new BooCompiler(island, runUpdater); - } - - public override string GetNamespace(string fileName, string definedSymbols) - { - try - { - return BooParser.ParseFile(fileName).Modules.First().Namespace.Name; - } - catch {} - - return base.GetNamespace(fileName, definedSymbols); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs b/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs deleted file mode 100644 index 76c83f9930..0000000000 --- a/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs +++ /dev/null @@ -1,141 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using ICSharpCode.NRefactory; -using ICSharpCode.NRefactory.Visitors; -using System.IO; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using UnityEditor.Modules; - -namespace UnityEditor.Scripting.Compilers -{ - internal class CSharpLanguage : SupportedLanguage - { - private static Regex _crOnlyRegex = new Regex("\r(?!\n)", RegexOptions.Compiled); - private static Regex _lfOnlyRegex = new Regex("(?(definedSymbols.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)); - foreach (var symbol in uniqueSymbols) - { - parser.Lexer.ConditionalCompilationSymbols.Add(symbol, string.Empty); - } - parser.Lexer.EvaluateConditionalCompilation = true; - - parser.Parse(); - try - { - var visitor = new NamespaceVisitor(); - VisitorData data = new VisitorData() {TargetClassName = Path.GetFileNameWithoutExtension(fileName)}; - parser.CompilationUnit.AcceptVisitor(visitor, data); - return string.IsNullOrEmpty(data.DiscoveredNamespace) ? string.Empty : data.DiscoveredNamespace; - } - catch - { - // Don't care; all we want is the namespace - } - } - return string.Empty; - } - - // TODO: Revisit this code and switch to version 5.5.1 (or Roslyn if possible) when Editor switches to newer runtime version (on going work expected - // to finish around 2017.2 or 2017.3 release. - // - // This is a workaround for a bug in version 3.2.1 of NRefactory in which it fails to parse sources with a combination of LF / #if / #else - // Version 5.5.1 is confirmed to not have this bug but we can't use it since it requires a newer runtime/c# version; - private static StringReader ReadAndConverteNewLines(string filePath) - { - var text = File.ReadAllText(filePath); - - text = _crOnlyRegex.Replace(text, "\r\n"); - text = _lfOnlyRegex.Replace(text, "\r\n"); - - return new StringReader(text); - } - - class VisitorData - { - public VisitorData() - { - CurrentNamespaces = new Stack(); - } - - public string TargetClassName; - public Stack CurrentNamespaces; - public string DiscoveredNamespace; - } - - class NamespaceVisitor : AbstractAstVisitor - { - public override object VisitNamespaceDeclaration(ICSharpCode.NRefactory.Ast.NamespaceDeclaration namespaceDeclaration, object data) - { - VisitorData visitorData = (VisitorData)data; - visitorData.CurrentNamespaces.Push(namespaceDeclaration.Name); - // Visit children (E.g. TypeDcelarion objects) - namespaceDeclaration.AcceptChildren(this, visitorData); - visitorData.CurrentNamespaces.Pop(); - - return null; - } - - public override object VisitTypeDeclaration(ICSharpCode.NRefactory.Ast.TypeDeclaration typeDeclaration, object data) - { - VisitorData visitorData = (VisitorData)data; - if (typeDeclaration.Name == visitorData.TargetClassName) - { - string fullNamespace = string.Empty; - foreach (string ns in visitorData.CurrentNamespaces) - { - if (fullNamespace == string.Empty) - fullNamespace = ns; - else - fullNamespace = ns + "." + fullNamespace; - } - visitorData.DiscoveredNamespace = fullNamespace; - } - return null; - } - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/Cil2AsOutputParser.cs b/Editor/Mono/Scripting/Compilers/Cil2AsOutputParser.cs deleted file mode 100644 index 9b7e279612..0000000000 --- a/Editor/Mono/Scripting/Compilers/Cil2AsOutputParser.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Text; - -namespace UnityEditor.Scripting.Compilers -{ - class Cil2AsOutputParser : UnityScriptCompilerOutputParser - { - public override IEnumerable Parse(string[] errorOutput, string[] standardOutput, bool compilationHadFailure) - { - var parsingError = false; - var currentErrorBuffer = new StringBuilder(); - foreach (var str in errorOutput) - { - if (str.StartsWith("ERROR: ")) - { - if (parsingError) - { - yield return CompilerErrorFor(currentErrorBuffer); - currentErrorBuffer.Length = 0; - } - currentErrorBuffer.AppendLine(str.Substring("ERROR: ".Length)); - parsingError = true; - } - else - { - if (parsingError) - currentErrorBuffer.AppendLine(str); - } - } - if (parsingError) - yield return CompilerErrorFor(currentErrorBuffer); - } - - private static CompilerMessage CompilerErrorFor(StringBuilder currentErrorBuffer) - { - return new CompilerMessage() { type = CompilerMessageType.Error, message = currentErrorBuffer.ToString() }; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/CommandLineFormatter.cs b/Editor/Mono/Scripting/Compilers/CommandLineFormatter.cs deleted file mode 100644 index f152543aa4..0000000000 --- a/Editor/Mono/Scripting/Compilers/CommandLineFormatter.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using UnityEngine; - -namespace UnityEditor.Scripting.Compilers -{ - static class CommandLineFormatter - { - private static readonly Regex UnsafeCharsWindows = new Regex(@"[^A-Za-z0-9_\-\.\:\,\/\@\\]"); - private static readonly Regex UnescapeableChars = new Regex(@"[\x00-\x08\x10-\x1a\x1c-\x1f\x7f\xff]"); - private static readonly Regex Quotes = new Regex("\""); - - public static string EscapeCharsQuote(string input) - { - if (input.IndexOf('\'') == -1) - return "'" + input + "'"; - if (input.IndexOf('"') == -1) - return "\"" + input + "\""; - return null; - } - - public static string PrepareFileName(string input) - { - input = FileUtil.ResolveSymlinks(input); - if (Application.platform == RuntimePlatform.WindowsEditor) - return EscapeCharsWindows(input); - return EscapeCharsQuote(input); - } - - public static string EscapeCharsWindows(string input) - { - if (input.Length == 0) - return "\"\""; - if (UnescapeableChars.IsMatch(input)) - { - Debug.LogWarning("Cannot escape control characters in string"); - return "\"\""; - } - if (UnsafeCharsWindows.IsMatch(input)) - { - return "\"" + Quotes.Replace(input, "\"\"") + "\""; - } - return input; - } - - internal static string GenerateResponseFile(IEnumerable arguments) - { - string tempFile = FileUtil.GetUniqueTempPathInProject(); - using (var writer = new System.IO.StreamWriter(tempFile)) - { - foreach (var arg in arguments.Where(a => a != null)) - writer.WriteLine(arg); - } - //Debug.Log("ResponseFile: "+System.IO.File.ReadAllText(tempFile)); - return tempFile; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/CompilerOutputParserBase.cs b/Editor/Mono/Scripting/Compilers/CompilerOutputParserBase.cs deleted file mode 100644 index df0218a1cb..0000000000 --- a/Editor/Mono/Scripting/Compilers/CompilerOutputParserBase.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; - -namespace UnityEditor.Scripting.Compilers -{ - internal abstract class CompilerOutputParserBase - { - static protected CompilerMessage CreateInternalCompilerErrorMessage(string[] compileroutput) - { - CompilerMessage message; - message.file = ""; - message.message = String.Join("\n", compileroutput); - message.type = CompilerMessageType.Error; - message.line = 0; - message.column = 0; - message.normalizedStatus = default(NormalizedCompilerStatus); - - return message; - } - - internal static protected CompilerMessage CreateCompilerMessageFromMatchedRegex(string line, Match m, string erroridentifier) - { - CompilerMessage message; - message.file = m.Groups["filename"].Value; - message.message = line; - message.line = Int32.Parse(m.Groups["line"].Value); - message.column = Int32.Parse(m.Groups["column"].Value); - message.type = (m.Groups["type"].Value == erroridentifier) ? CompilerMessageType.Error : CompilerMessageType.Warning; - message.normalizedStatus = default(NormalizedCompilerStatus); - - return message; - } - - public virtual IEnumerable Parse(string[] errorOutput, bool compilationHadFailure) - { - return Parse(errorOutput, new string[0], compilationHadFailure); - } - - public virtual IEnumerable Parse(string[] errorOutput, string[] standardOutput, bool compilationHadFailure) - { - var hasErrors = false; - var msgs = new List(); - var regex = GetOutputRegex(); - var internalErrorRegex = GetInternalErrorOutputRegex(); - - foreach (var line in errorOutput) - { - //Jamplus can fail with enormous lines in the stdout, parsing of which can take 30! seconds. - var line2 = line.Length > 1000 ? line.Substring(0, 100) : line; - - Match m = regex.Match(line2); - if (!m.Success) - { - if (internalErrorRegex != null) - m = internalErrorRegex.Match(line2); - if (!m.Success) - continue; - } - CompilerMessage message = CreateCompilerMessageFromMatchedRegex(line, m, GetErrorIdentifier()); - message.normalizedStatus = NormalizedStatusFor(m); - - if (message.type == CompilerMessageType.Error) - hasErrors = true; - - msgs.Add(message); - } - if (compilationHadFailure && !hasErrors) - { - msgs.Add(CreateInternalCompilerErrorMessage(errorOutput)); - } - return msgs; - } - - protected virtual NormalizedCompilerStatus NormalizedStatusFor(Match match) - { - return default(NormalizedCompilerStatus); - } - - protected abstract string GetErrorIdentifier(); - - protected abstract Regex GetOutputRegex(); - protected virtual Regex GetInternalErrorOutputRegex() { return null; } - - protected static NormalizedCompilerStatus TryNormalizeCompilerStatus(Match match, string idToCheck, Regex messageParser, Func normalizer) - { - var id = match.Groups["id"].Value; - var ret = default(NormalizedCompilerStatus); - if (id != idToCheck) - return ret; - - return normalizer(match, messageParser); - } - - protected static NormalizedCompilerStatus NormalizeMemberNotFoundError(Match outputMatch, Regex messageParser) - { - NormalizedCompilerStatus ret; - ret.code = NormalizedCompilerStatusCode.MemberNotFound; - - var dm = messageParser.Match(outputMatch.Groups["message"].Value); - ret.details = dm.Groups["type_name"].Value + "%" + dm.Groups["member_name"].Value; - - return ret; - } - - protected static NormalizedCompilerStatus NormalizeSimpleUnknownTypeOfNamespaceError(Match outputMatch, Regex messageParser) - { - NormalizedCompilerStatus ret; - ret.code = NormalizedCompilerStatusCode.UnknownTypeOrNamespace; - - var dm = messageParser.Match(outputMatch.Groups["message"].Value); - ret.details = "EntityName=" + dm.Groups["type_name"].Value + "\n" - + "Script=" + outputMatch.Groups["filename"].Value + "\n" - + "Line=" + outputMatch.Groups["line"].Value + "\n" - + "Column=" + outputMatch.Groups["column"].Value; - - return ret; - } - - protected static NormalizedCompilerStatus NormalizeUnknownTypeMemberOfNamespaceError(Match outputMatch, Regex messageParser) - { - NormalizedCompilerStatus ret; - ret.code = NormalizedCompilerStatusCode.UnknownTypeOrNamespace; - - var dm = messageParser.Match(outputMatch.Groups["message"].Value); - ret.details = "EntityName=" + dm.Groups["namespace"].Value + "." + dm.Groups["type_name"].Value + "\n" - + "Script=" + outputMatch.Groups["filename"].Value + "\n" - + "Line=" + outputMatch.Groups["line"].Value + "\n" - + "Column=" + outputMatch.Groups["column"].Value; - - return ret; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/GendarmeOutputParser.cs b/Editor/Mono/Scripting/Compilers/GendarmeOutputParser.cs deleted file mode 100644 index a98f68e5b4..0000000000 --- a/Editor/Mono/Scripting/Compilers/GendarmeOutputParser.cs +++ /dev/null @@ -1,132 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Text; - -namespace UnityEditor.Scripting.Compilers -{ - class GendarmeRuleData - { - public int LastIndex = 0; - public int Line = 0; - public string File = ""; - public string Problem; - public string Details; - public string Severity; - public string Source; - public string Location; - public string Target; - public bool IsAssemblyError; - } - - class GendarmeOutputParser : UnityScriptCompilerOutputParser - { - public override IEnumerable Parse(string[] errorOutput, bool compilationHadFailure) - { - throw new ArgumentException("Gendarme Output Parser needs standard out"); - } - - public override IEnumerable Parse(string[] errorOutput, string[] standardOutput, bool compilationHadFailure) - { - for (var i = 0; i < standardOutput.Length; i++) - { - if (!standardOutput[i].StartsWith("Problem:")) continue; - var grd = GetGendarmeRuleDataFor(standardOutput, i); - var compilerErrorFor = CompilerErrorFor(grd); - yield return compilerErrorFor; - i = grd.LastIndex + 1; - } - } - - private static CompilerMessage CompilerErrorFor(GendarmeRuleData gendarmeRuleData) - { - var messageBuffer = new StringBuilder(); - messageBuffer.AppendLine(gendarmeRuleData.Problem); - messageBuffer.AppendLine(gendarmeRuleData.Details); - - messageBuffer.AppendLine(!string.IsNullOrEmpty(gendarmeRuleData.Location) - ? gendarmeRuleData.Location - : String.Format("{0} at line : {1}", gendarmeRuleData.Source, gendarmeRuleData.Line)); - - var message = messageBuffer.ToString(); - return new CompilerMessage - { - type = CompilerMessageType.Error, - message = message, - file = gendarmeRuleData.File, - line = gendarmeRuleData.Line, - column = 1 - }; - } - - private static GendarmeRuleData GetGendarmeRuleDataFor(IList output, int index) - { - var gendarmeRuleData = new GendarmeRuleData(); - //Read until we hit a non detail line. - for (var i = index; i < output.Count; i++) - { - var currentLine = output[i]; - const string problemString = "Problem:"; - if (currentLine.StartsWith(problemString)) - { - gendarmeRuleData.Problem = currentLine.Substring(currentLine.LastIndexOf(problemString, StringComparison.Ordinal) + problemString.Length); - } - else if (currentLine.StartsWith("* Details")) - { - gendarmeRuleData.Details = currentLine; - } - else if (currentLine.StartsWith("* Source")) - { - gendarmeRuleData.IsAssemblyError = false; - gendarmeRuleData.Source = currentLine; - gendarmeRuleData.Line = GetLineNumberFrom(currentLine); - gendarmeRuleData.File = GetFileNameFrome(currentLine); - } - else if (currentLine.StartsWith("* Severity")) - { - gendarmeRuleData.Severity = currentLine; - } - else if (currentLine.StartsWith("* Location")) - { - gendarmeRuleData.IsAssemblyError = true; - gendarmeRuleData.Location = currentLine; - } - else if (currentLine.StartsWith("* Target")) - { - gendarmeRuleData.Target = currentLine; - } - else - { - gendarmeRuleData.LastIndex = i; - break; - } - } - return gendarmeRuleData; - } - - private static string GetFileNameFrome(string currentLine) - { - const string stringToCheck = "* Source:"; - var beginSourceFile = currentLine.LastIndexOf(stringToCheck) + stringToCheck.Length; - var endSourceFile = currentLine.IndexOf("("); - - if (beginSourceFile != -1 && endSourceFile != -1) - return currentLine.Substring(beginSourceFile, endSourceFile - beginSourceFile).Trim(); - - return ""; - } - - private static int GetLineNumberFrom(string currentLine) - { - var beginLineNumber = currentLine.IndexOf("(") + 2; - var endLineNumber = currentLine.IndexOf(")"); - if (beginLineNumber != -1 && endLineNumber != -1) - return int.Parse(currentLine.Substring(beginLineNumber, endLineNumber - beginLineNumber)); - - return 0; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/Il2CppOutputParser.cs b/Editor/Mono/Scripting/Compilers/Il2CppOutputParser.cs deleted file mode 100644 index dd95bb8834..0000000000 --- a/Editor/Mono/Scripting/Compilers/Il2CppOutputParser.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Text.RegularExpressions; - -namespace UnityEditor.Scripting.Compilers -{ - class Il2CppOutputParser : CompilerOutputParserBase - { - private const string _errorIdentifier = "IL2CPP error"; - private static readonly Regex sErrorRegexWithSourceInformation = new Regex(@"\s*(?.*) in (?.*):(?\d+)"); - - public override IEnumerable Parse(string[] errorOutput, string[] standardOutput, bool compilationHadFailure) - { - // This code is not unit tested, so modify it with caution. - var messages = new List(); - for (int i = 0; i < standardOutput.Length; ++i) - { - var line = standardOutput[i]; - if (line.StartsWith(_errorIdentifier)) - { - var sourceFile = string.Empty; - var sourceLine = 0; - var errorMessage = new StringBuilder(); - - var match = sErrorRegexWithSourceInformation.Match(line); - if (match.Success) - { - sourceFile = match.Groups["filename"].Value; - sourceLine = int.Parse(match.Groups["line"].Value); - errorMessage.AppendFormat("{0} in {1}:{2}", match.Groups["message"].Value, Path.GetFileName(sourceFile), sourceLine); - } - else - { - errorMessage.Append(line); - } - - if (i + 1 < standardOutput.Length && standardOutput[i + 1].StartsWith("Additional information:")) - { - errorMessage.AppendFormat("{0}{1}", Environment.NewLine, standardOutput[i + 1]); - ++i; - } - messages.Add(new CompilerMessage - { - file = sourceFile, - line = sourceLine, - message = errorMessage.ToString(), - type = CompilerMessageType.Error - }); - } - } - - return messages; - } - - protected override string GetErrorIdentifier() - { - return _errorIdentifier; - } - - protected override Regex GetOutputRegex() - { - return sErrorRegexWithSourceInformation; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs deleted file mode 100644 index 47d137de6f..0000000000 --- a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using UnityEditor.Modules; -using UnityEditor.Utils; - -namespace UnityEditor.Scripting.Compilers -{ - internal class MicrosoftCSharpCompiler : ScriptCompilerBase - { - public MicrosoftCSharpCompiler(MonoIsland island, bool runUpdater) : base(island, runUpdater) - { - } - - private BuildTarget BuildTarget { get { return _island._target; } } - - private string[] GetClassLibraries() - { - var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); - if (PlayerSettings.GetScriptingBackend(buildTargetGroup) != ScriptingImplementation.WinRTDotNET) - { - return new string[] {}; - } - - if (BuildTarget != BuildTarget.WSAPlayer) - throw new InvalidOperationException(string.Format("MicrosoftCSharpCompiler cannot build for .NET Scripting backend for BuildTarget.{0}.", BuildTarget)); - - var resolver = new NuGetPackageResolver { ProjectLockFile = @"UWP\project.lock.json" }; - return resolver.Resolve(); - } - - private void FillCompilerOptions(List arguments, out string argsPrefix) - { - // This will ensure that csc.exe won't include csc.rsp - // csc.rsp references .NET 4.5 assemblies which cause conflicts for us - argsPrefix = "/noconfig "; - arguments.Add("/nostdlib+"); - - // Case 755238: Always use english for outputing errors, the same way as Mono compilers do - arguments.Add("/preferreduilang:en-US"); - - var platformSupportModule = ModuleManager.FindPlatformSupportModule(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget)); - var compilationExtension = platformSupportModule.CreateCompilationExtension(); - - arguments.AddRange(GetClassLibraries().Select(r => "/reference:\"" + r + "\"")); - arguments.AddRange(compilationExtension.GetAdditionalAssemblyReferences().Select(r => "/reference:\"" + r + "\"")); - arguments.AddRange(compilationExtension.GetWindowsMetadataReferences().Select(r => "/reference:\"" + r + "\"")); - arguments.AddRange(compilationExtension.GetAdditionalDefines().Select(d => "/define:" + d)); - arguments.AddRange(compilationExtension.GetAdditionalSourceFiles()); - } - - private static void ThrowCompilerNotFoundException(string path) - { - throw new Exception(string.Format("'{0}' not found. Is your Unity installation corrupted?", path)); - } - - private Program StartCompilerImpl(List arguments, string argsPrefix) - { - foreach (string dll in _island._references) - arguments.Add("/reference:" + PrepareFileName(dll)); - - foreach (string define in _island._defines.Distinct()) - arguments.Add("/define:" + define); - - foreach (string source in _island._files) - { - arguments.Add(PrepareFileName(source).Replace('/', '\\')); - } - - var coreRun = Paths.Combine(EditorApplication.applicationContentsPath, "Tools", "Roslyn", "CoreRun.exe").Replace('/', '\\'); - var csc = Paths.Combine(EditorApplication.applicationContentsPath, "Tools", "Roslyn", "csc.exe").Replace('/', '\\'); - - if (!File.Exists(coreRun)) - ThrowCompilerNotFoundException(coreRun); - - if (!File.Exists(csc)) - ThrowCompilerNotFoundException(csc); - - AddCustomResponseFileIfPresent(arguments, "csc.rsp"); - - var responseFile = CommandLineFormatter.GenerateResponseFile(arguments); - - RunAPIUpdaterIfRequired(responseFile); - - var psi = new ProcessStartInfo() { Arguments = "\"" + csc + "\" " + argsPrefix + "@" + responseFile, FileName = coreRun, CreateNoWindow = true }; - var program = new Program(psi); - program.Start(); - return program; - } - - protected override Program StartCompiler() - { - var outputPath = PrepareFileName(_island._output); - - // Always build with "/debug:pdbonly", "/optimize+", because even if the assembly is optimized - // it seems you can still succesfully debug C# scripts in Visual Studio - var arguments = new List - { - "/target:library", - "/nowarn:0169", - "/out:" + outputPath - }; - - if (_island._allowUnsafeCode) - arguments.Add("/unsafe"); - - if (!_island._development_player) - { - arguments.Add("/debug:pdbonly"); - arguments.Add("/optimize+"); - } - else - { - arguments.Add("/debug:full"); - arguments.Add("/optimize-"); - } - - string argsPrefix; - FillCompilerOptions(arguments, out argsPrefix); - return StartCompilerImpl(arguments, argsPrefix); - } - - protected override string[] GetStreamContainingCompilerMessages() - { - return GetStandardOutput(); - } - - protected override CompilerOutputParserBase CreateOutputParser() - { - return new MicrosoftCSharpCompilerOutputParser(); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompilerOutputParser.cs b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompilerOutputParser.cs deleted file mode 100644 index 06e059ef6a..0000000000 --- a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompilerOutputParser.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Text.RegularExpressions; - -namespace UnityEditor.Scripting.Compilers -{ - internal class MicrosoftCSharpCompilerOutputParser : CompilerOutputParserBase - { - private static Regex sCompilerOutput = new Regex(@"\s*(?.*)\((?\d+),(?\d+)\):\s*(?warning|error)\s*(?[^:]*):\s*(?.*)", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - - protected override Regex GetOutputRegex() - { - return sCompilerOutput; - } - - protected override string GetErrorIdentifier() - { - return "error"; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs deleted file mode 100644 index 73d6a07ab1..0000000000 --- a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using System.IO; -using UnityEngine; -using UnityEditor.Utils; -using System.Text; -using UnityEditor.Scripting.ScriptCompilation; - -namespace UnityEditor.Scripting.Compilers -{ - class MonoCSharpCompiler : MonoScriptCompilerBase - { - public static readonly string ReponseFilename = "mcs.rsp"; - - public MonoCSharpCompiler(MonoIsland island, bool runUpdater) : base(island, runUpdater) - { - } - - override protected Program StartCompiler() - { - var arguments = new List - { - "-debug", - "-target:library", - "-nowarn:0169", - "-langversion:" + ((EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) ? "6" : "4"), - "-out:" + PrepareFileName(_island._output), - "-nostdlib", - }; - - if (_island._allowUnsafeCode) - arguments.Add("-unsafe"); - - if (!_island._development_player && !_island._editor) - arguments.Add("-optimize"); - - foreach (string dll in _island._references) - arguments.Add("-r:" + PrepareFileName(dll)); - foreach (string define in _island._defines.Distinct()) - arguments.Add("-define:" + define); - foreach (string source in _island._files) - arguments.Add(PrepareFileName(source)); - - if (!AddCustomResponseFileIfPresent(arguments, ReponseFilename)) - { - if (_island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0_Subset && AddCustomResponseFileIfPresent(arguments, "smcs.rsp")) - Debug.LogWarning(string.Format("Using obsolete custom response file 'smcs.rsp'. Please use '{0}' instead.", ReponseFilename)); - else if (_island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0 && AddCustomResponseFileIfPresent(arguments, "gmcs.rsp")) - Debug.LogWarning(string.Format("Using obsolete custom response file 'gmcs.rsp'. Please use '{0}' instead.", ReponseFilename)); - } - return StartCompiler(_island._target, GetCompilerPath(arguments), arguments, BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level), false, MonoInstallationFinder.GetMonoInstallation(MonoInstallationFinder.MonoBleedingEdgeInstallation)); - } - - private string GetCompilerPath(List arguments) - { - string dir = MonoInstallationFinder.GetProfileDirectory("4.5", MonoInstallationFinder.MonoBleedingEdgeInstallation); - var compilerPath = Path.Combine(dir, "mcs.exe"); - if (File.Exists(compilerPath)) - { - var systemAssemblyDirectory = MonoLibraryHelpers.GetSystemReferenceDirectory(_island._api_compatibility_level); - - if (!string.IsNullOrEmpty(systemAssemblyDirectory) && Directory.Exists(systemAssemblyDirectory)) - arguments.Add("-lib:" + PrepareFileName(systemAssemblyDirectory)); - return compilerPath; - } - - throw new ApplicationException("Unable to find csharp compiler in " + dir); - } - - protected override CompilerOutputParserBase CreateOutputParser() - { - return new MonoCSharpCompilerOutputParser(); - } - - public static string[] Compile(string[] sources, string[] references, string[] defines, string outputFile, bool allowUnsafeCode) - { - var island = new MonoIsland(BuildTarget.StandaloneWindows, ApiCompatibilityLevel.NET_2_0_Subset, allowUnsafeCode, sources, references, defines, outputFile); - using (var c = new MonoCSharpCompiler(island, false)) - { - c.BeginCompiling(); - while (!c.Poll()) - System.Threading.Thread.Sleep(50); - return c.GetCompilerMessages().Select(cm => cm.message).ToArray(); - } - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/MonoCSharpCompilerOutputParser.cs b/Editor/Mono/Scripting/Compilers/MonoCSharpCompilerOutputParser.cs deleted file mode 100644 index 74dd00489d..0000000000 --- a/Editor/Mono/Scripting/Compilers/MonoCSharpCompilerOutputParser.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Text.RegularExpressions; - -namespace UnityEditor.Scripting.Compilers -{ - internal class MonoCSharpCompilerOutputParser : CompilerOutputParserBase - { - private static Regex sCompilerOutput = new Regex(@"\s*(?.*)\((?\d+),(?\d+)(\+{1})?\):\s*(?warning|error)\s*(?[^:]*):\s*(?.*)", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - private static Regex sInternalErrorCompilerOutput = new Regex(@"\s*(?Internal compiler (?error)) at\s*(?.*)\((?\d+),(?\d+)\):\s*(?.*)", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - private static Regex sMissingMember = new Regex(@"[^`]*`(?[^']+)'[^`]+`(?[^']+)'", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - private static Regex sMissingType = new Regex(@"[^`]*`(?[^']+)'[^`]+`(?[^']+)'", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - private static Regex sUnknownTypeOrNamespace = new Regex(@"[^`]*`(?[^']+)'.*", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - - protected override Regex GetOutputRegex() - { - return sCompilerOutput; - } - - protected override Regex GetInternalErrorOutputRegex() - { - return sInternalErrorCompilerOutput; - } - - protected override string GetErrorIdentifier() - { - return "error"; - } - - protected override NormalizedCompilerStatus NormalizedStatusFor(Match match) - { - var status = TryNormalizeCompilerStatus(match, "CS0117", sMissingMember, NormalizeMemberNotFoundError); - if (status.code != NormalizedCompilerStatusCode.NotNormalized) - return status; - - status = TryNormalizeCompilerStatus(match, "CS0246", sUnknownTypeOrNamespace, NormalizeSimpleUnknownTypeOfNamespaceError); - if (status.code != NormalizedCompilerStatusCode.NotNormalized) - return status; - - status = TryNormalizeCompilerStatus(match, "CS0234", sMissingType, NormalizeUnknownTypeMemberOfNamespaceError); - if (status.code != NormalizedCompilerStatusCode.NotNormalized) - return status; - - return TryNormalizeCompilerStatus(match, "CS0103", sUnknownTypeOrNamespace, NormalizeSimpleUnknownTypeOfNamespaceError); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs deleted file mode 100644 index b0fee0cd32..0000000000 --- a/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.IO; -using UnityEditor.Utils; - -namespace UnityEditor.Scripting.Compilers -{ - internal abstract class MonoScriptCompilerBase : ScriptCompilerBase - { - protected MonoScriptCompilerBase(MonoIsland island, bool runUpdater) : base(island, runUpdater) - { - } - - protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments) - { - return StartCompiler(target, compiler, arguments, BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level)); - } - - protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments, string profileDirectory) - { - AddCustomResponseFileIfPresent(arguments, Path.GetFileNameWithoutExtension(compiler) + ".rsp"); - - var monoInstallation = (PlayerSettingsEditor.IsLatestApiCompatibility(_island._api_compatibility_level)) - ? MonoInstallationFinder.GetMonoBleedingEdgeInstallation() - : MonoInstallationFinder.GetMonoInstallation(); - return StartCompiler(target, compiler, arguments, profileDirectory, true, monoInstallation); - } - - protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments, string profileDirectory, bool setMonoEnvironmentVariables, string monodistro) - { - var responseFile = CommandLineFormatter.GenerateResponseFile(arguments); - - RunAPIUpdaterIfRequired(responseFile); - - var program = new ManagedProgram(monodistro, profileDirectory, compiler, " @" + responseFile, setMonoEnvironmentVariables, null); - program.Start(); - - return program; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/NuGetPackageResolver.cs b/Editor/Mono/Scripting/Compilers/NuGetPackageResolver.cs deleted file mode 100644 index 3ad6f81a6c..0000000000 --- a/Editor/Mono/Scripting/Compilers/NuGetPackageResolver.cs +++ /dev/null @@ -1,117 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; - -// Note: this file is externally included included in some tools - SerializationWeaver, AssemblyUpdater, InternalCallReplacer etc. - -namespace UnityEditor.Scripting.Compilers -{ - internal sealed class NuGetPackageResolver - { - public string PackagesDirectory - { - get; - set; - } - - public string ProjectLockFile - { - get; - set; - } - - public string TargetMoniker - { - get; - set; - } - - public string[] ResolvedReferences - { - get; - private set; - } - - public NuGetPackageResolver() - { - TargetMoniker = "UAP,Version=v10.0"; - } - - private string ConvertToWindowsPath(string path) - { - return path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); - } - - public string[] Resolve() - { - var text = File.ReadAllText(ProjectLockFile); - var lockFile = (Dictionary)Json.Deserialize(text); - var targets = (Dictionary)lockFile["targets"]; - var target = FindUWPTarget(targets); - - var references = new List(); - var packagesPath = ConvertToWindowsPath(GetPackagesPath()); - - foreach (var packagePair in target) - { - var package = (Dictionary)packagePair.Value; - - object compileObject; - if (!package.TryGetValue("compile", out compileObject)) - continue; - var compile = (Dictionary)compileObject; - - var parts = packagePair.Key.Split('/'); - var packageId = parts[0]; - var packageVersion = parts[1]; - var packagePath = Path.Combine(Path.Combine(packagesPath, packageId), packageVersion); - if (!Directory.Exists(packagePath)) - throw new Exception(string.Format("Package directory not found: \"{0}\".", packagePath)); - - foreach (var name in compile.Keys) - { - const string emptyFolder = "_._"; - if (string.Equals(Path.GetFileName(name), emptyFolder, StringComparison.InvariantCultureIgnoreCase)) - continue; - var reference = Path.Combine(packagePath, ConvertToWindowsPath(name)); - if (!File.Exists(reference)) - throw new Exception(string.Format("Reference not found: \"{0}\".", reference)); - references.Add(reference); - } - - if (package.ContainsKey("frameworkAssemblies")) - throw new NotImplementedException("Support for \"frameworkAssemblies\" property has not been implemented yet."); - } - - ResolvedReferences = references.ToArray(); - return ResolvedReferences; - } - - private Dictionary FindUWPTarget(Dictionary targets) - { - foreach (var target in targets) - { - if (target.Key.StartsWith(TargetMoniker) && !target.Key.Contains("/")) - return (Dictionary)target.Value; - } - - throw new InvalidOperationException("Could not find suitable target for " + TargetMoniker + " in project.lock.json file."); - } - - private string GetPackagesPath() - { - var value = PackagesDirectory; - if (!string.IsNullOrEmpty(value)) - return value; - value = Environment.GetEnvironmentVariable("NUGET_PACKAGES"); - if (!string.IsNullOrEmpty(value)) - return value; - var userProfile = Environment.GetEnvironmentVariable("USERPROFILE"); - return Path.Combine(Path.Combine(userProfile, ".nuget"), "packages"); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs deleted file mode 100644 index 1ab28462c1..0000000000 --- a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs +++ /dev/null @@ -1,449 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEngine; -using UnityEditor.Utils; - -namespace UnityEditor.Scripting.Compilers -{ - internal abstract class ScriptCompilerBase : IDisposable - { - public class ResponseFileData - { - public class Reference - { - public String Alias; - public String Assembly; - } - - public string[] Defines; - public Reference[] References; - public bool Unsafe; - public string[] Errors; - } - - public class CompilerOption - { - public string Arg; - public string Value; - } - - static readonly char[] CompilerOptionArgumentSeperators = { ';', ',' }; - - private Program process; - private string _responseFile = null; - private bool _runAPIUpdater; - - // ToDo: would be nice to move MonoIsland to MonoScriptCompilerBase - protected MonoIsland _island; - - protected abstract Program StartCompiler(); - - protected abstract CompilerOutputParserBase CreateOutputParser(); - - protected ScriptCompilerBase(MonoIsland island, bool runAPIUpdater) - { - _island = island; - _runAPIUpdater = runAPIUpdater; - } - - protected string[] GetErrorOutput() - { - return process.GetErrorOutput(); - } - - protected string[] GetStandardOutput() - { - return process.GetStandardOutput(); - } - - public void BeginCompiling() - { - if (process != null) - throw new InvalidOperationException("Compilation has already begun!"); - process = StartCompiler(); - } - - public virtual void Dispose() - { - if (process != null) - { - process.Dispose(); - process = null; - } - if (_responseFile != null) - { - File.Delete(_responseFile); - _responseFile = null; - } - } - - public virtual bool Poll() - { - if (process == null) - return true; - - return process.HasExited; - } - - public void WaitForCompilationToFinish() - { - process.WaitForExit(); - } - - protected string GetMonoProfileLibDirectory() - { - var profile = BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level); - - var monoInstall = (PlayerSettingsEditor.IsLatestApiCompatibility(_island._api_compatibility_level)) - ? MonoInstallationFinder.MonoBleedingEdgeInstallation - : MonoInstallationFinder.MonoInstallation; - - return MonoInstallationFinder.GetProfileDirectory(profile, monoInstall); - } - - protected bool AddCustomResponseFileIfPresent(List arguments, string responseFileName) - { - var relativeCustomResponseFilePath = Path.Combine("Assets", responseFileName); - - if (!File.Exists(relativeCustomResponseFilePath)) - return false; - - arguments.Add("@" + relativeCustomResponseFilePath); - - return true; - } - - public static ResponseFileData ParseResponseFileFromFile(string responseFileName) - { - var relativeCustomResponseFilePath = Path.Combine("Assets", responseFileName); - - if (!File.Exists(relativeCustomResponseFilePath)) - { - var empty = new ResponseFileData - { - Defines = new string[0], - References = new ResponseFileData.Reference[0], - Unsafe = false, - Errors = new string[0] - }; - - return empty; - } - - var responseFileText = File.ReadAllText(relativeCustomResponseFilePath); - - return ParseResponseFileText(responseFileText); - } - - // From: - // https://github.com/mono/mono/blob/c106cdc775792ceedda6da58de7471f9f5c0b86c/mcs/mcs/settings.cs - // - // settings.cs: All compiler settings - // - // Author: Miguel de Icaza (miguel@ximian.com) - // Ravi Pratap (ravi@ximian.com) - // Marek Safar (marek.safar@gmail.com) - // - // - // Dual licensed under the terms of the MIT X11 or GNU GPL - // - // Copyright 2001 Ximian, Inc (http://www.ximian.com) - // Copyright 2004-2008 Novell, Inc - // Copyright 2011 Xamarin, Inc (http://www.xamarin.com) - static string[] ResponseFileTextToStrings(string responseFileText) - { - var args = new List(); - - var sb = new System.Text.StringBuilder(); - - var textLines = responseFileText.Split('\n', '\r'); - - foreach (var line in textLines) - { - int t = line.Length; - - for (int i = 0; i < t; i++) - { - char c = line[i]; - - if (c == '"' || c == '\'') - { - char end = c; - - for (i++; i < t; i++) - { - c = line[i]; - - if (c == end) - break; - sb.Append(c); - } - } - else if (c == ' ') - { - if (sb.Length > 0) - { - args.Add(sb.ToString()); - sb.Length = 0; - } - } - else - sb.Append(c); - } - if (sb.Length > 0) - { - args.Add(sb.ToString()); - sb.Length = 0; - } - } - - return args.ToArray(); - } - - public static ResponseFileData ParseResponseFileText(string responseFileText) - { - var compilerOptions = new List(); - - var responseFileStrings = ResponseFileTextToStrings(responseFileText); - - foreach (var line in responseFileStrings) - { - int idx = line.IndexOf(':'); - string arg, value; - - if (idx == -1) - { - arg = line; - value = ""; - } - else - { - arg = line.Substring(0, idx); - value = line.Substring(idx + 1); - } - - if (!string.IsNullOrEmpty(arg) && arg[0] == '-') - arg = '/' + arg.Substring(1); - - compilerOptions.Add(new CompilerOption { Arg = arg, Value = value }); - } - - var defines = new List(); - var references = new List(); - bool unsafeDefined = false; - var errors = new List(); - - foreach (var option in compilerOptions) - { - var arg = option.Arg; - var value = option.Value; - - switch (arg) - { - case "/d": - case "/define": - { - if (value.Length == 0) - { - errors.Add("No value set for define"); - break; - } - - var defs = value.Split(CompilerOptionArgumentSeperators); - foreach (string define in defs) - defines.Add(define.Trim()); - } - break; - - case "/r": - case "/reference": - { - if (value.Length == 0) - { - errors.Add("No value set for reference"); - break; - } - - string[] refs = value.Split(CompilerOptionArgumentSeperators); - - if (refs.Length != 1) - { - errors.Add("Cannot specify multiple aliases using single /reference option"); - break; - } - - foreach (string reference in refs) - { - if (reference.Length == 0) - continue; - - int index = reference.IndexOf('='); - if (index > -1) - { - string alias = reference.Substring(0, index); - string assembly = reference.Substring(index + 1); - - references.Add(new ResponseFileData.Reference { Alias = alias, Assembly = assembly }); - } - else - { - references.Add(new ResponseFileData.Reference { Alias = string.Empty, Assembly = reference }); - } - } - } - break; - - case "/unsafe": - case "/unsafe+": - { - unsafeDefined = true; - } - break; - - case "/unsafe-": - { - unsafeDefined = false; - } - break; - } - } - - var responseFileData = new ResponseFileData - { - Defines = defines.ToArray(), - References = references.ToArray(), - Unsafe = unsafeDefined, - Errors = errors.ToArray() - }; - - return responseFileData; - } - - protected static string PrepareFileName(string fileName) - { - return CommandLineFormatter.PrepareFileName(fileName); - } - - //do not change the returntype, native unity depends on this one. - public virtual CompilerMessage[] GetCompilerMessages() - { - if (!Poll()) - Debug.LogWarning("Compile process is not finished yet. This should not happen."); - - DumpStreamOutputToLog(); - - return CreateOutputParser().Parse(GetStreamContainingCompilerMessages(), CompilationHadFailure()).ToArray(); - } - - protected bool CompilationHadFailure() - { - return (process.ExitCode != 0); - } - - protected virtual string[] GetStreamContainingCompilerMessages() - { - List errors = new List(); - errors.AddRange(GetErrorOutput()); - errors.Add(string.Empty); - errors.AddRange(GetStandardOutput()); - return errors.ToArray(); - } - - private void DumpStreamOutputToLog() - { - bool hadCompilationFailure = CompilationHadFailure(); - - string[] errorOutput = GetErrorOutput(); - - if (hadCompilationFailure || errorOutput.Length != 0) - { - Console.WriteLine(""); - Console.WriteLine("-----Compiler Commandline Arguments:"); - process.LogProcessStartInfo(); - - string[] stdOutput = GetStandardOutput(); - - Console.WriteLine("-----CompilerOutput:-stdout--exitcode: " + process.ExitCode + "--compilationhadfailure: " + hadCompilationFailure + "--outfile: " + _island._output); - foreach (string line in stdOutput) - Console.WriteLine(line); - - Console.WriteLine("-----CompilerOutput:-stderr----------"); - foreach (string line in errorOutput) - Console.WriteLine(line); - Console.WriteLine("-----EndCompilerOutput---------------"); - } - } - - protected void RunAPIUpdaterIfRequired(string responseFile) - { - if (!_runAPIUpdater) - return; - - APIUpdaterHelper.UpdateScripts(responseFile, _island.GetExtensionOfSourceFiles()); - } - } - - /// Normalized 'status' code for a [[CompilerMessage]] - internal enum NormalizedCompilerStatusCode - { - NotNormalized = 0, - - /// Maps to C# CS0117 and Boo BCE0019. - MemberNotFound = 1, // details syntax: TypeNamespaceQualifiedName:MemberName - - // Maps to C# CS0246/CS0234 and Boo XXXX - UnknownTypeOrNamespace // details syntax: typename or namespace.typename - } - - internal struct NormalizedCompilerStatus - { - public NormalizedCompilerStatusCode code; - - /// each normalized compiler status defines the syntax of the details - public string details; - } - - /// Marks the type of a [[CompilerMessage]] - internal enum CompilerMessageType - { - /// The message is an error. The compilation has failed. - Error = 0, - /// The message is an warning only. If there are no error messages, the compilation has completed successfully. - Warning = 1 - } - - /// This struct should be returned from GetCompilerMessages() on ScriptCompilerBase implementations - internal struct CompilerMessage - { - /// The text of the error or warning message - public string message; - /// The path name of the file the message refers to - public string file; - /// The line in the source file the message refers to - public int line; - /// The column of the line the message refers to - public int column; - /// The type of the message. Either Error or Warning - public CompilerMessageType type; - - /// The normalized status. Each class deriving from ScriptCompilerBase must map errors / warning # - /// if it can be mapped to a NormalizedCompilerStatusCode. - public NormalizedCompilerStatus normalizedStatus; - - public CompilerMessage(CompilerMessage cm) - { - message = cm.message; - file = cm.file; - line = cm.line; - column = cm.column; - type = cm.type; - normalizedStatus = cm.normalizedStatus; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs b/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs deleted file mode 100644 index c1ac360e69..0000000000 --- a/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor.Scripting.Compilers -{ - internal abstract class SupportedLanguage - { - public abstract string GetExtensionICanCompile(); - public abstract string GetLanguageName(); - public abstract ScriptCompilerBase CreateCompiler(MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater); - public virtual string GetNamespace(string fileName, string definedSymbols) - { - return string.Empty; - } - - public virtual bool CompilerRequiresAdditionalReferences() - { - return false; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/UWPReferences.cs b/Editor/Mono/Scripting/Compilers/UWPReferences.cs deleted file mode 100644 index ff7433b845..0000000000 --- a/Editor/Mono/Scripting/Compilers/UWPReferences.cs +++ /dev/null @@ -1,308 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -// this file is used by both Editor and AssemblyConverter - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml.Linq; -using Microsoft.Win32; - -namespace UnityEditor.Scripting.Compilers -{ - internal struct UWPExtensionSDK - { - public readonly string Name; - public readonly string Version; - public readonly string ManifestPath; - - public UWPExtensionSDK(string name, string version, string manifestPath) - { - Name = name; - Version = version; - ManifestPath = manifestPath; - } - } - - internal class UWPSDK - { - public readonly Version Version; - public readonly Version MinVSVersion; - - public UWPSDK(Version version, Version minVSVersion) - { - Version = version; - MinVSVersion = minVSVersion; - } - } - - internal static class UWPReferences - { - private sealed class UWPExtension - { - public string Name { get; private set; } - - public string[] References { get; private set; } - - public UWPExtension(string manifest, string windowsKitsFolder, string sdkVersion) - { - var document = XDocument.Load(manifest); - var fileListElement = document.Element("FileList"); - if (fileListElement.Attribute("TargetPlatform").Value != "UAP") - throw new Exception(string.Format("Invalid extension manifest at \"{0}\".", manifest)); - Name = fileListElement.Attribute("DisplayName").Value; - var containedApiContractsElement = fileListElement.Element("ContainedApiContracts"); - References = GetReferences(windowsKitsFolder, sdkVersion, containedApiContractsElement); - } - } - - public static string[] GetReferences(Version sdkVersion) - { - var folder = GetWindowsKit10(); - if (string.IsNullOrEmpty(folder)) - return new string[0]; - - var version = SdkVersionToString(sdkVersion); - var references = new HashSet(StringComparer.InvariantCultureIgnoreCase); - - var windowsWinMd = CombinePaths(folder, "UnionMetadata", version, "Facade", "Windows.winmd"); - if (!File.Exists(windowsWinMd)) - windowsWinMd = CombinePaths(folder, "UnionMetadata", "Facade", "Windows.winmd"); - - references.Add(windowsWinMd); - - foreach (var reference in GetPlatform(folder, version)) - { - references.Add(reference); - } - - foreach (var extension in GetExtensions(folder, version)) - { - foreach (var reference in extension.References) - { - references.Add(reference); - } - } - - return references.ToArray(); - } - - public static IEnumerable GetExtensionSDKs(Version sdkVersion) - { - var windowsKit10Directory = GetWindowsKit10(); - if (string.IsNullOrEmpty(windowsKit10Directory)) - return new UWPExtensionSDK[0]; - - return GetExtensionSDKs(windowsKit10Directory, SdkVersionToString(sdkVersion)); - } - - static string SdkVersionToString(Version version) - { - var sdkVersion = version.ToString(); - - if (version.Minor == -1) - sdkVersion += ".0"; - if (version.Build == -1) - sdkVersion += ".0"; - if (version.Revision == -1) - sdkVersion += ".0"; - - return sdkVersion; - } - - public static IEnumerable GetInstalledSDKs() - { - var windowsKit10Directory = GetWindowsKit10(); - if (string.IsNullOrEmpty(windowsKit10Directory)) - return Enumerable.Empty(); - - var platformsUAP = CombinePaths(windowsKit10Directory, "Platforms", "UAP"); - if (!Directory.Exists(platformsUAP)) - return Enumerable.Empty(); - - var allSDKs = new List(); - - var filesUnderPlatformsUAP = Directory.GetFiles(platformsUAP, "*", SearchOption.AllDirectories); - var allPlatformXmlFiles = filesUnderPlatformsUAP.Where(f => string.Equals("Platform.xml", Path.GetFileName(f), StringComparison.OrdinalIgnoreCase)); - - foreach (var platformXmlFile in allPlatformXmlFiles) - { - XDocument xDocument; - - try - { - xDocument = XDocument.Load(platformXmlFile); - } - catch - { - continue; - } - - foreach (var element in xDocument.Elements("ApplicationPlatform")) - { - Version version; - if (FindVersionInNode(element, out version)) - { - var minVSVersionString = element.Elements("MinimumVisualStudioVersion").Select(e => e.Value).FirstOrDefault(); - allSDKs.Add(new UWPSDK(version, TryParseVersion(minVSVersionString))); - } - } - } - - return allSDKs; - } - - // No Version.TryParse in .NET 3.5 :( - private static Version TryParseVersion(string s) - { - if (!string.IsNullOrEmpty(s)) - { - try - { - return new Version(s); - } - catch - { - } - } - return null; - } - - private static bool FindVersionInNode(XElement node, out Version version) - { - for (var attribute = node.FirstAttribute; attribute != null; attribute = attribute.NextAttribute) - { - if (string.Equals(attribute.Name.LocalName, "version", StringComparison.OrdinalIgnoreCase)) - { - version = TryParseVersion(attribute.Value); - if (version != null) - { - return true; - } - } - } - - version = null; - return false; - } - - private static string[] GetPlatform(string folder, string version) - { - var platformXml = CombinePaths(folder, @"Platforms\UAP", version, "Platform.xml"); - if (!File.Exists(platformXml)) - return new string[0]; - - var document = XDocument.Load(platformXml); - var applicationPlatformElement = document.Element("ApplicationPlatform"); - if (applicationPlatformElement.Attribute("name").Value != "UAP") - throw new Exception(string.Format("Invalid platform manifest at \"{0}\".", platformXml)); - var containedApiContractsElement = applicationPlatformElement.Element("ContainedApiContracts"); - return GetReferences(folder, version, containedApiContractsElement); - } - - private static string CombinePaths(params string[] paths) - { - return UnityEditor.Utils.Paths.Combine(paths); - } - - private static IEnumerable GetExtensionSDKs(string sdkFolder, string sdkVersion) - { - var extensions = new List(); - var extensionsFolder = Path.Combine(sdkFolder, "Extension SDKs"); - - if (!Directory.Exists(extensionsFolder)) - return new UWPExtensionSDK[0]; - - foreach (var extensionFolder in Directory.GetDirectories(extensionsFolder)) - { - var manifest = CombinePaths(extensionFolder, sdkVersion, "SDKManifest.xml"); - var extensionName = Path.GetFileName(extensionFolder); - - if (File.Exists(manifest)) - { - extensions.Add(new UWPExtensionSDK(extensionName, sdkVersion, manifest)); - continue; - } - - if (extensionName == "XboxLive") - { - // Workaround for XboxLive SDK bug: currently, its version is always 1.0. Microsoft said they'll fix it in the future. - manifest = CombinePaths(extensionFolder, "1.0", "SDKManifest.xml"); - - if (File.Exists(manifest)) - { - extensions.Add(new UWPExtensionSDK(extensionName, "1.0", manifest)); - continue; - } - } - } - - return extensions; - } - - private static UWPExtension[] GetExtensions(string windowsKitsFolder, string version) - { - var extensions = new List(); - - foreach (var extensionSDK in GetExtensionSDKs(windowsKitsFolder, version)) - { - try - { - var extension = new UWPExtension(extensionSDK.ManifestPath, windowsKitsFolder, version); - extensions.Add(extension); - } - catch - { - // ignore exceptions - } - } - - return extensions.ToArray(); - } - - private static string[] GetReferences(string windowsKitsFolder, string sdkVersion, XElement containedApiContractsElement) - { - var references = new List(); - foreach (var apiContractElement in containedApiContractsElement.Elements("ApiContract")) - { - var name = apiContractElement.Attribute("name").Value; - var version = apiContractElement.Attribute("version").Value; - var reference = CombinePaths(windowsKitsFolder, "References", sdkVersion, name, version, name + ".winmd"); - if (!File.Exists(reference)) - { - reference = CombinePaths(windowsKitsFolder, "References", name, version, name + ".winmd"); - - if (!File.Exists(reference)) - continue; - } - references.Add(reference); - } - return references.ToArray(); - } - - private static string GetWindowsKit10() - { - var programFilesX86 = - Environment.GetEnvironmentVariable("ProgramFiles(x86)") - ; - var folder = Path.Combine(programFilesX86, @"Windows Kits\10\"); - try - { - const string keyName = @"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0"; - folder = UnityEditorInternal.RegistryUtil.GetRegistryStringValue(keyName, "InstallationFolder", folder, UnityEditorInternal.RegistryView._32); - } - catch - { - // ignore exceptions - } - - if (!Directory.Exists(folder)) - return string.Empty; - - return folder; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs b/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs deleted file mode 100644 index c4221efcee..0000000000 --- a/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Linq; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using UnityEditor.Utils; - -namespace UnityEditor.Scripting.Compilers -{ - class UnityScriptCompiler : MonoScriptCompilerBase - { - private static readonly Regex UnityEditorPattern = new Regex(@"UnityEditor\.dll$", RegexOptions.ExplicitCapture); - const string k_UnityScriptProfileDirectory = "unityscript"; - - public UnityScriptCompiler(MonoIsland island, bool runUpdater) : base(island, runUpdater) - { - } - - protected override CompilerOutputParserBase CreateOutputParser() - { - return new UnityScriptCompilerOutputParser(); - } - - override protected Program StartCompiler() - { - var arguments = new List - { - "-debug", - "-target:library", - "-i:UnityEngine", - "-i:System.Collections", - "-base:UnityEngine.MonoBehaviour", - "-nowarn:BCW0016", - "-nowarn:BCW0003", - "-method:Main", - "-out:" + _island._output, - "-x-type-inference-rule-attribute:" + typeof(UnityEngineInternal.TypeInferenceRuleAttribute) - }; - - if (StrictBuildTarget()) - arguments.Add("-pragmas:strict,downcast"); - - foreach (var define in _island._defines.Distinct()) - arguments.Add("-define:" + define); - - foreach (var dll in _island._references) - arguments.Add("-r:" + PrepareFileName(dll)); - - var compilingEditorScripts = Array.Exists(_island._references, UnityEditorPattern.IsMatch); - if (compilingEditorScripts) - arguments.Add("-i:UnityEditor"); - else if (!BuildPipeline.IsUnityScriptEvalSupported(_island._target)) - arguments.Add(string.Format("-disable-eval:eval is not supported on the current build target ({0}).", _island._target)); - - foreach (string source in _island._files) - arguments.Add(PrepareFileName(source)); - - var compilerPath = Path.Combine(GetUnityScriptCompilerDirectory(), "us.exe"); - return StartCompiler(_island._target, compilerPath, arguments, GetUnityScriptProfileDirectory()); - } - - string GetUnityScriptCompilerDirectory() - { - if (PlayerSettings.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - return GetMonoProfileLibDirectory(); - - return Path.Combine(MonoInstallationFinder.GetProfilesDirectory(MonoInstallationFinder.MonoBleedingEdgeInstallation), k_UnityScriptProfileDirectory); - } - - string GetUnityScriptProfileDirectory() - { - if (PlayerSettings.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - return BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level); - - return k_UnityScriptProfileDirectory; - } - - private bool StrictBuildTarget() - { - return Array.IndexOf(_island._defines, "ENABLE_DUCK_TYPING") == -1; - } - - protected override string[] GetStreamContainingCompilerMessages() - { - return GetStandardOutput(); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/UnityScriptCompilerOutputParser.cs b/Editor/Mono/Scripting/Compilers/UnityScriptCompilerOutputParser.cs deleted file mode 100644 index 9ea0c0ad66..0000000000 --- a/Editor/Mono/Scripting/Compilers/UnityScriptCompilerOutputParser.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Text.RegularExpressions; - -namespace UnityEditor.Scripting.Compilers -{ - class UnityScriptCompilerOutputParser : CompilerOutputParserBase - { - private static Regex sCompilerOutput = new Regex(@"\s*(?.*)\((?\d+),(?\d+)\):\s*[BU]C(?W|E)(?[^:]*):\s*(?.*)", RegexOptions.ExplicitCapture); - - private static Regex sUnknownTypeOrNamespace = new Regex(@"[^']*'(?[^']+)'.*", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - - protected override string GetErrorIdentifier() - { - return "E"; - } - - protected override Regex GetOutputRegex() - { - return sCompilerOutput; - } - - protected override NormalizedCompilerStatus NormalizedStatusFor(Match match) - { - var status = TryNormalizeCompilerStatus(match, "0018", sUnknownTypeOrNamespace, NormalizeSimpleUnknownTypeOfNamespaceError); - if (status.code != NormalizedCompilerStatusCode.NotNormalized) - return status; - - return TryNormalizeCompilerStatus(match, "0005", sUnknownTypeOrNamespace, NormalizeSimpleUnknownTypeOfNamespaceError); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs b/Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs deleted file mode 100644 index 7bcf8c2c41..0000000000 --- a/Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor.Scripting.Compilers -{ - internal class UnityScriptLanguage : SupportedLanguage - { - public override string GetExtensionICanCompile() - { - return "js"; - } - - public override string GetLanguageName() - { - return "UnityScript"; - } - - public override ScriptCompilerBase CreateCompiler(MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) - { - return new UnityScriptCompiler(island, runUpdater); - } - } -} diff --git a/Editor/Mono/Scripting/PragmaFixing30.cs b/Editor/Mono/Scripting/PragmaFixing30.cs deleted file mode 100644 index f4accaaab8..0000000000 --- a/Editor/Mono/Scripting/PragmaFixing30.cs +++ /dev/null @@ -1,148 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System; -using System.IO; -using System.Text; -using System.Text.RegularExpressions; -using System.Collections; -using System.Collections.Generic; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; - -namespace UnityEditor.Scripting -{ - internal class PragmaFixing30 - { - [RequiredByNativeCode] - static void FixJavaScriptPragmas() - { - string[] filesToFix = CollectBadFiles(); - if (filesToFix.Length == 0) - return; - - if (!InternalEditorUtility.inBatchMode) - PragmaFixingWindow.ShowWindow(filesToFix); - else - FixFiles(filesToFix); - } - - public static void FixFiles(string[] filesToFix) - { - foreach (string f in filesToFix) - { - try - { - FixPragmasInFile(f); - } - catch (Exception ex) - { - Debug.LogError("Failed to fix pragmas in file '" + f + "'.\n" + ex.Message); - } - } - } - - static bool FileNeedsPragmaFixing(string fileName) - { - return CheckOrFixPragmas(fileName, true); - } - - static void FixPragmasInFile(string fileName) - { - CheckOrFixPragmas(fileName, false); - } - - static bool CheckOrFixPragmas(string fileName, bool onlyCheck) - { - string oldText = File.ReadAllText(fileName); - StringBuilder text = new StringBuilder(oldText); - - LooseComments(text); - - Match strictMatch = PragmaMatch(text, "strict"); - - if (!strictMatch.Success) - return false; - - bool hasDowncast = PragmaMatch(text, "downcast").Success; - bool hasImplicit = PragmaMatch(text, "implicit").Success; - - if (hasDowncast && hasImplicit) - return false; - - if (!onlyCheck) - DoFixPragmasInFile(fileName, oldText, strictMatch.Index + strictMatch.Length, hasDowncast, hasImplicit); - - return true; - } - - static void DoFixPragmasInFile(string fileName, string oldText, int fixPos, bool hasDowncast, bool hasImplicit) - { - string textToAdd = string.Empty; - string lineEndings = HasWinLineEndings(oldText) ? "\r\n" : "\n"; - - if (!hasImplicit) - textToAdd += lineEndings + "#pragma implicit"; - if (!hasDowncast) - textToAdd += lineEndings + "#pragma downcast"; - - File.WriteAllText(fileName, oldText.Insert(fixPos, textToAdd)); - } - - static bool HasWinLineEndings(string text) - { - return text.IndexOf("\r\n") != -1; - } - - static IEnumerable SearchRecursive(string dir, string mask) - { - foreach (string d in Directory.GetDirectories(dir)) - foreach (string f in SearchRecursive(d, mask)) - yield return f; - foreach (string f in Directory.GetFiles(dir, mask)) - yield return f; - } - - static void LooseComments(StringBuilder sb) - { - // TODO: better comment ignoring? this one sort of does the job, it handles // - // and if it's in multiline comments, our added lines will end up commented as well - Regex r = new Regex("//"); - foreach (Match m in r.Matches(sb.ToString())) - { - int pos = m.Index; - while (pos < sb.Length && sb[pos] != '\n' && sb[pos] != '\r') - sb[pos++] = ' '; - } - } - - static Match PragmaMatch(StringBuilder sb, string pragma) - { - // unity java script, like regex, treats new line as space character as well - return new Regex(@"#\s*pragma\s*" + pragma).Match(sb.ToString()); - } - - static string[] CollectBadFiles() - { - List filesToFix = new List(); - - foreach (string f in SearchRecursive(Path.Combine(Directory.GetCurrentDirectory(), "Assets"), "*.js")) - { - try - { - if (FileNeedsPragmaFixing(f)) - filesToFix.Add(f); - } - catch (Exception ex) - { - Debug.LogError("Failed to fix pragmas in file '" + f + "'.\n" + ex.Message); - } - } - - return filesToFix.ToArray(); - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs b/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs deleted file mode 100644 index 9e045b8d63..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs +++ /dev/null @@ -1,144 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.Scripting.ScriptCompilation; - -namespace UnityEditor.Compilation -{ - public enum AssemblyBuilderStatus - { - NotStarted = 0, - IsCompiling = 1, - Finished = 2, - } - - [Flags] - public enum AssemblyBuilderFlags - { - None = 0, - EditorAssembly = 1, - DevelopmentBuild = 2, - }; - - public class AssemblyBuilder - { - public event Action buildStarted; - public event Action buildFinished; - - public string[] scriptPaths { get; private set; } - public string assemblyPath { get; private set; } - public string[] additionalDefines { get; set; } - public string[] additionalReferences { get; set; } - public string[] excludeReferences { get; set; } - public ScriptCompilerOptions compilerOptions { get; set; } - - public AssemblyBuilderFlags flags { get; set; } - public BuildTargetGroup buildTargetGroup { get; set; } - public BuildTarget buildTarget { get; set; } - - CompilationTask compilationTask; - - public AssemblyBuilder(string assemblyPath, params string[] scriptPaths) - { - if (string.IsNullOrEmpty(assemblyPath)) - throw new ArgumentException("assemblyPath cannot be null or empty"); - - if (scriptPaths == null || scriptPaths.Length == 0) - throw new ArgumentException("scriptPaths cannot be null or empty"); - - this.scriptPaths = scriptPaths; - this.assemblyPath = assemblyPath; - - compilerOptions = new ScriptCompilerOptions(); - flags = AssemblyBuilderFlags.None; - buildTargetGroup = EditorUserBuildSettings.activeBuildTargetGroup; - buildTarget = EditorUserBuildSettings.activeBuildTarget; - } - - public bool Build() - { - return Build(EditorCompilationInterface.Instance); - } - - internal bool Build(EditorCompilation editorCompilation) - { - if (editorCompilation.IsCompilationTaskCompiling()) - return false; - - if (status != AssemblyBuilderStatus.NotStarted) - throw new Exception(string.Format("Cannot start AssemblyBuilder with status {0}. Expected {1}", status, AssemblyBuilderStatus.NotStarted)); - - var scriptAssembly = editorCompilation.CreateScriptAssembly(this); - - compilationTask = new CompilationTask(new ScriptAssembly[] { scriptAssembly }, scriptAssembly.OutputDirectory, - EditorScriptCompilationOptions.BuildingEmpty, CompilationTaskOptions.StopOnFirstError, 1); - - compilationTask.OnCompilationStarted += (assembly, phase) => - { - editorCompilation.InvokeAssemblyCompilationStarted(assemblyPath); - OnCompilationStarted(assembly, phase); - }; - - compilationTask.OnCompilationFinished += (assembly, messages) => - { - editorCompilation.InvokeAssemblyCompilationFinished(assemblyPath, messages); - OnCompilationFinished(assembly, messages); - }; - - compilationTask.Poll(); - - editorCompilation.AddAssemblyBuilder(this); - - return true; - } - - public AssemblyBuilderStatus status - { - get - { - if (compilationTask == null) - return AssemblyBuilderStatus.NotStarted; - - if (compilationTask.IsCompiling) - return compilationTask.Poll() ? AssemblyBuilderStatus.Finished : AssemblyBuilderStatus.IsCompiling; - - return AssemblyBuilderStatus.Finished; - } - } - - void OnCompilationStarted(ScriptAssembly assembly, int phase) - { - if (buildStarted == null) - return; - - try - { - buildStarted(assemblyPath); - } - catch (Exception e) - { - UnityEngine.Debug.LogException(e); - } - } - - void OnCompilationFinished(ScriptAssembly assembly, List messages) - { - if (buildFinished == null) - return; - - var convertedMessages = EditorCompilation.ConvertCompilerMessages(messages); - - try - { - buildFinished(assemblyPath, convertedMessages); - } - catch (Exception e) - { - UnityEngine.Debug.LogException(e); - } - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/AssemblyDefinitionException.cs b/Editor/Mono/Scripting/ScriptCompilation/AssemblyDefinitionException.cs deleted file mode 100644 index 37c221fe12..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/AssemblyDefinitionException.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor.Compilation -{ - public class AssemblyDefinitionException : Exception - { - public string[] filePaths { get; private set; } - - public AssemblyDefinitionException(string message, params string[] filePaths) : base(message) - { - this.filePaths = filePaths; - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/AssemblyFlags.cs b/Editor/Mono/Scripting/ScriptCompilation/AssemblyFlags.cs deleted file mode 100644 index 6e88fdb498..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/AssemblyFlags.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - // Keep in sync with ManagedAssemblyFlags in C++ - [Flags] - enum AssemblyFlags - { - None = 0, - EditorOnly = (1 << 0), - UseForMono = (1 << 1), - UseForDotNet = (1 << 2), - FirstPass = (1 << 3), - ExcludedForRuntimeCode = (1 << 4), - }; -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/AssetPath.cs b/Editor/Mono/Scripting/ScriptCompilation/AssetPath.cs deleted file mode 100644 index 39b5774858..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/AssetPath.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Utils; -using SystemPath = System.IO.Path; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - static class AssetPath - { - public static readonly char Separator = '/'; - - public static string GetFullPath(string path) - { - return ReplaceSeparators(SystemPath.GetFullPath(path.NormalizePath())); - } - - public static string Combine(string path1, string path2) - { - return ReplaceSeparators(SystemPath.Combine(path1, path2)); - } - - public static bool IsPathRooted(string path) - { - return SystemPath.IsPathRooted(path.NormalizePath()); - } - - public static string GetFileName(string path) - { - return SystemPath.GetFileName(path.NormalizePath()); - } - - public static string GetExtension(string path) - { - return SystemPath.GetExtension(path.NormalizePath()); - } - - public static string GetDirectoryName(string path) - { - return ReplaceSeparators(SystemPath.GetDirectoryName(path.NormalizePath())); - } - - public static string ReplaceSeparators(string path) - { - return path.Replace('\\', Separator); - } - - public static string GetAssemblyNameWithoutExtension(string assemblyName) - { - if (AssetPath.GetExtension(assemblyName) == ".dll") - return SystemPath.GetFileNameWithoutExtension(assemblyName.NormalizePath()); - - return SystemPath.GetFileName(assemblyName.NormalizePath()); - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs b/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs deleted file mode 100644 index b249d59b18..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs +++ /dev/null @@ -1,253 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor.Scripting.ScriptCompilation; -using System.Linq; -using sc = UnityEditor.Scripting.ScriptCompilation; - -namespace UnityEditor.Compilation -{ - [Flags] - public enum AssemblyFlags - { - None = 0, - EditorAssembly = (1 << 0) - } - - public class ScriptCompilerOptions - { - public bool AllowUnsafeCode { get; set; } - - public ScriptCompilerOptions() - { - AllowUnsafeCode = false; - } - } - - public class Assembly - { - public string name { get; private set; } - public string outputPath { get; private set; } - public string[] sourceFiles { get; private set; } - public string[] defines { get; private set; } - public Assembly[] assemblyReferences { get; private set; } - public string[] compiledAssemblyReferences { get; private set; } - public AssemblyFlags flags { get; private set; } - public ScriptCompilerOptions compilerOptions { get; private set; } - - public string[] allReferences { get { return assemblyReferences.Select(a => a.outputPath).Concat(compiledAssemblyReferences).ToArray(); } } - - public Assembly(string name, - string outputPath, - string[] sourceFiles, - string[] defines, - Assembly[] assemblyReferences, - string[] compiledAssemblyReferences, - AssemblyFlags flags) - : this(name, - outputPath, - sourceFiles, - defines, - assemblyReferences, - compiledAssemblyReferences, - flags, - new ScriptCompilerOptions()) - { - } - - public Assembly(string name, - string outputPath, - string[] sourceFiles, - string[] defines, - Assembly[] assemblyReferences, - string[] compiledAssemblyReferences, - AssemblyFlags flags, - ScriptCompilerOptions compilerOptions) - { - this.name = name; - this.outputPath = outputPath; - this.sourceFiles = sourceFiles; - this.defines = defines; - this.assemblyReferences = assemblyReferences; - this.compiledAssemblyReferences = compiledAssemblyReferences; - this.flags = flags; - this.compilerOptions = compilerOptions; - } - } - - public struct AssemblyDefinitionPlatform - { - public string Name { get; private set; } - public string DisplayName { get; private set; } - public BuildTarget BuildTarget { get; private set; } - - internal AssemblyDefinitionPlatform(string name, string displayName, BuildTarget buildTarget) : this() - { - Name = name; - DisplayName = displayName; - BuildTarget = buildTarget; - } - } - - public static partial class CompilationPipeline - { - static AssemblyDefinitionPlatform[] assemblyDefinitionPlatforms; - - public static event Action assemblyCompilationStarted; - public static event Action assemblyCompilationFinished; - - static CompilationPipeline() - { - SubscribeToEvents(EditorCompilationInterface.Instance); - } - - internal static void SubscribeToEvents(EditorCompilation editorCompilation) - { - editorCompilation.assemblyCompilationStarted += (assemblyPath) => - { - try - { - if (assemblyCompilationStarted != null) - assemblyCompilationStarted(assemblyPath); - } - catch (Exception e) - { - UnityEngine.Debug.LogException(e); - } - }; - - editorCompilation.assemblyCompilationFinished += (assemblyPath, messages) => - { - try - { - if (assemblyCompilationFinished != null) - assemblyCompilationFinished(assemblyPath, messages); - } - catch (Exception e) - { - UnityEngine.Debug.LogException(e); - } - }; - } - - public static Assembly[] GetAssemblies() - { - var options = EditorCompilationInterface.GetAdditionalEditorScriptCompilationOptions(); - return GetAssemblies(EditorCompilationInterface.Instance, options); - } - - public static string GetAssemblyNameFromScriptPath(string sourceFilePath) - { - return GetAssemblyNameFromScriptPath(EditorCompilationInterface.Instance, sourceFilePath); - } - - public static string GetAssemblyDefinitionFilePathFromScriptPath(string sourceFilePath) - { - return GetAssemblyDefinitionFilePathFromScriptPath(EditorCompilationInterface.Instance, sourceFilePath); - } - - public static string GetAssemblyDefinitionFilePathFromAssemblyName(string assemblyName) - { - return GetAssemblyDefinitionFilePathFromAssemblyName(EditorCompilationInterface.Instance, assemblyName); - } - - public static AssemblyDefinitionPlatform[] GetAssemblyDefinitionPlatforms() - { - if (assemblyDefinitionPlatforms == null) - { - assemblyDefinitionPlatforms = CustomScriptAssembly.Platforms.Select(p => new AssemblyDefinitionPlatform(p.Name, p.DisplayName, p.BuildTarget)).ToArray(); - Array.Sort(assemblyDefinitionPlatforms, CompareAssemblyDefinitionPlatformByDisplayName); - } - - return assemblyDefinitionPlatforms; - } - - internal static Assembly[] GetAssemblies(EditorCompilation editorCompilation, EditorScriptCompilationOptions additionalOptions) - { - var scriptAssemblies = editorCompilation.GetAllEditorScriptAssemblies(additionalOptions); - var assemblies = new Assembly[scriptAssemblies.Length]; - - var scriptAssemblyToAssembly = new Dictionary(); - - for (int i = 0; i < scriptAssemblies.Length; ++i) - scriptAssemblyToAssembly.Add(scriptAssemblies[i], assemblies[i]); - - for (int i = 0; i < scriptAssemblies.Length; ++i) - { - var scriptAssembly = scriptAssemblies[i]; - - var name = AssetPath.GetAssemblyNameWithoutExtension(scriptAssembly.Filename); - var outputPath = scriptAssembly.FullPath; - var sourceFiles = scriptAssembly.Files; - var defines = scriptAssembly.Defines; - var compiledAssemblyReferences = scriptAssembly.References; - var assemblyReferences = scriptAssembly.ScriptAssemblyReferences.Select(a => scriptAssemblyToAssembly[a]).ToArray(); - - var flags = AssemblyFlags.None; - - if ((scriptAssembly.Flags & sc.AssemblyFlags.EditorOnly) == sc.AssemblyFlags.EditorOnly) - flags |= AssemblyFlags.EditorAssembly; - - var compilerOptions = scriptAssembly.CompilerOptions; - - assemblies[i] = new Assembly(name, - outputPath, - sourceFiles, - defines, - assemblyReferences, - compiledAssemblyReferences, - flags, - compilerOptions); - } - - return assemblies; - } - - static int CompareAssemblyDefinitionPlatformByDisplayName(AssemblyDefinitionPlatform p1, AssemblyDefinitionPlatform p2) - { - return string.Compare(p1.DisplayName, p2.DisplayName, StringComparison.OrdinalIgnoreCase); - } - - internal static string GetAssemblyNameFromScriptPath(EditorCompilation editorCompilation, string sourceFilePath) - { - try - { - var targetAssembly = editorCompilation.GetTargetAssembly(sourceFilePath); - return targetAssembly.Name; - } - catch (Exception) - { - return null; - } - } - - internal static string GetAssemblyDefinitionFilePathFromAssemblyName(EditorCompilation editorCompilation, string assemblyName) - { - try - { - var customScriptAssembly = editorCompilation.FindCustomScriptAssemblyFromAssemblyName(assemblyName); - return customScriptAssembly.FilePath; - } - catch (Exception) - { - return null; - } - } - - internal static string GetAssemblyDefinitionFilePathFromScriptPath(EditorCompilation editorCompilation, string sourceFilePath) - { - try - { - var customScriptAssembly = editorCompilation.FindCustomScriptAssemblyFromScriptPath(sourceFilePath); - return customScriptAssembly != null ? customScriptAssembly.FilePath : null; - } - catch (Exception) - { - return null; - } - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs deleted file mode 100644 index 6ade732b00..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs +++ /dev/null @@ -1,257 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using UnityEditor.Scripting.Compilers; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - [Flags] - enum CompilationTaskOptions - { - None = 0, - StopOnFirstError = (1 << 0) - } - - // CompilationTask represents one complete rebuild of all the ScriptAssembly's that are passed in the constructor. - // The ScriptAssembly's are built in correct order according to their ScriptAssembly dependencies. - class CompilationTask - { - HashSet pendingAssemblies; - Dictionary processedAssemblies = new Dictionary(); - Dictionary compilerTasks = new Dictionary(); - string buildOutputDirectory; - int compilePhase = 0; - EditorScriptCompilationOptions options; - CompilationTaskOptions compilationTaskOptions; - int maxConcurrentCompilers; - - public event Action OnCompilationStarted; - public event Action> OnCompilationFinished; - - public bool Stopped { get; private set; } - public bool CompileErrors { get; private set; } - - public CompilationTask(ScriptAssembly[] scriptAssemblies, string buildOutputDirectory, EditorScriptCompilationOptions options, CompilationTaskOptions compilationTaskOptions, int maxConcurrentCompilers) - { - pendingAssemblies = new HashSet(scriptAssemblies); - CompileErrors = false; - this.buildOutputDirectory = buildOutputDirectory; - this.options = options; - this.compilationTaskOptions = compilationTaskOptions; - this.maxConcurrentCompilers = maxConcurrentCompilers; - } - - ~CompilationTask() - { - Stop(); - } - - public bool IsCompiling - { - get { return pendingAssemblies.Count > 0 || compilerTasks.Count > 0; } - } - - public Dictionary CompilerMessages - { - get { return processedAssemblies; } - } - - public void Stop() - { - if (Stopped) - return; - - foreach (var task in compilerTasks) - { - var compiler = task.Value; - compiler.Dispose(); - } - - compilerTasks.Clear(); - - Stopped = true; - } - - // Returns true when compilation is finished due to one of these reasons - // * Was stopped (CompilationTask.Stopped will be true) - // * Compilation had errors (CompilationTask.CompileErrors will be true) - // * Compilation succesfully completed without errors. - public bool Poll() - { - if (Stopped) - return true; - - Dictionary finishedCompilerTasks = null; - - // Check if any compiler processes are finished. - foreach (var task in compilerTasks) - { - var compiler = task.Value; - - // Did compiler task finish? - if (compiler.Poll()) - { - if (finishedCompilerTasks == null) - finishedCompilerTasks = new Dictionary(); - - var assembly = task.Key; - finishedCompilerTasks.Add(assembly, compiler); - } - } - - // Save compiler messages from finished compiler processes and check for compile errors. - if (finishedCompilerTasks != null) - foreach (var task in finishedCompilerTasks) - { - var assembly = task.Key; - var compiler = task.Value; - - var messages = compiler.GetCompilerMessages(); - - // Convert messages to list, OnCompilationFinished callbacks might add - // more messages - var messagesList = messages.ToList(); - - if (OnCompilationFinished != null) - OnCompilationFinished(assembly, messagesList); - - processedAssemblies.Add(assembly, messagesList.ToArray()); - - if (!CompileErrors) - CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); - - compilerTasks.Remove(assembly); - compiler.Dispose(); - } - - // If StopOnFirstError is set, do not queue assemblies for compilation in case of compile errors. - bool stopOnFirstError = (compilationTaskOptions & CompilationTaskOptions.StopOnFirstError) == CompilationTaskOptions.StopOnFirstError; - - if (stopOnFirstError && CompileErrors) - { - // Set empty compiler messages for all pending assemblies. - // Makes handling of messages easier in the editor. - if (pendingAssemblies.Count > 0) - { - foreach (var pendingAssembly in pendingAssemblies) - processedAssemblies.Add(pendingAssembly, new CompilerMessage[0]); - - pendingAssemblies.Clear(); - } - - return compilerTasks.Count == 0; - } - - // Queue pending assemblies for compilation if we have no running compilers or if compilers have finished. - if (compilerTasks.Count == 0 || (finishedCompilerTasks != null && finishedCompilerTasks.Count > 0)) - QueuePendingAssemblies(); - - return pendingAssemblies.Count == 0 && compilerTasks.Count == 0; - } - - void QueuePendingAssemblies() - { - if (pendingAssemblies.Count == 0) - return; - - List assemblyCompileQueue = null; - List removePendingAssemblies = null; - - // Find assemblies that have all their references already compiled. - foreach (var pendingAssembly in pendingAssemblies) - { - bool compileAssembly = true; - - foreach (var reference in pendingAssembly.ScriptAssemblyReferences) - { - CompilerMessage[] messages; - - if (!processedAssemblies.TryGetValue(reference, out messages)) - { - // If a reference is not compiling and not pending - // also remove this assembly from pending. - if (!compilerTasks.ContainsKey(reference) && !pendingAssemblies.Contains(reference)) - { - if (removePendingAssemblies == null) - removePendingAssemblies = new List(); - - removePendingAssemblies.Add(pendingAssembly); - } - - compileAssembly = false; - break; - } - - // If reference has compile errors, do not compile the pending assembly. - bool compileErrors = messages.Any(m => m.type == CompilerMessageType.Error); - - if (compileErrors) - { - if (removePendingAssemblies == null) - removePendingAssemblies = new List(); - - removePendingAssemblies.Add(pendingAssembly); - - compileAssembly = false; - break; - } - } - - if (compileAssembly) - { - if (assemblyCompileQueue == null) - assemblyCompileQueue = new List(); - - assemblyCompileQueue.Add(pendingAssembly); - } - } - - if (removePendingAssemblies != null) - { - foreach (var assembly in removePendingAssemblies) - pendingAssemblies.Remove(assembly); - - // All pending assemblies were removed and no assemblies - // were queued for compilation. - if (assemblyCompileQueue == null) - return; - } - - // No assemblies to compile, need to wait for more references to finish compiling. - if (assemblyCompileQueue == null) - { - if (compilerTasks.Count() == 0) - throw new Exception("No pending assemblies queued for compilation and no compilers running. Compilation will never finish."); - return; - } - - bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; - - // Begin compiling any queued assemblies - foreach (var assembly in assemblyCompileQueue) - { - pendingAssemblies.Remove(assembly); - var island = assembly.ToMonoIsland(options, buildOutputDirectory); - var compiler = ScriptCompilers.CreateCompilerInstance(island, buildingForEditor, island._target, assembly.RunUpdater); - - compilerTasks.Add(assembly, compiler); - - // Start compiler process - compiler.BeginCompiling(); - - if (OnCompilationStarted != null) - OnCompilationStarted(assembly, compilePhase); - - if (compilerTasks.Count == maxConcurrentCompilers) - break; - } - - compilePhase++; - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/CompilerMessage.cs b/Editor/Mono/Scripting/ScriptCompilation/CompilerMessage.cs deleted file mode 100644 index a7eddb93d6..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/CompilerMessage.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor.Compilation -{ - public enum CompilerMessageType - { - Error = 0, - Warning = 1 - } - - public struct CompilerMessage - { - public string message; - public string file; - public int line; - public int column; - public CompilerMessageType type; - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs b/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs deleted file mode 100644 index 2f66b460fa..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs +++ /dev/null @@ -1,293 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Compilation; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - [System.Serializable] - class CustomScriptAssemblyData - { -#pragma warning disable 649 - public string name; - public string[] references; - public string[] optionalUnityReferences; - public string[] includePlatforms; - public string[] excludePlatforms; - public bool allowUnsafeCode; - - public static CustomScriptAssemblyData FromJson(string json) - { - var assemblyData = UnityEngine.JsonUtility.FromJson(json); - - if (assemblyData == null) - throw new System.Exception("Json file does not contain an assembly definition"); - - if (string.IsNullOrEmpty(assemblyData.name)) - throw new System.Exception("Required property 'name' not set"); - - if ((assemblyData.excludePlatforms != null && assemblyData.excludePlatforms.Length > 0) && - (assemblyData.includePlatforms != null && assemblyData.includePlatforms.Length > 0)) - throw new System.Exception("Both 'excludePlatforms' and 'includePlatforms' are set."); - - return assemblyData; - } - - public static string ToJson(CustomScriptAssemblyData data) - { - return UnityEngine.JsonUtility.ToJson(data, true); - } - } - - struct CustomScriptOptinalUnityAssembly - { - public string DisplayName { get; private set; } - public OptionalUnityReferences OptionalUnityReferences { get; private set; } - public string AdditinalInformationWhenEnabled { get; private set; } - - public CustomScriptOptinalUnityAssembly(string displayName, OptionalUnityReferences optionalUnityReferences, string additinalInformationWhenEnabled = "") - : this() - { - DisplayName = displayName; - OptionalUnityReferences = optionalUnityReferences; - AdditinalInformationWhenEnabled = additinalInformationWhenEnabled; - } - } - - struct CustomScriptAssemblyPlatform - { - public string Name { get; private set; } - public string DisplayName { get; private set; } - public BuildTarget BuildTarget { get; private set; } - - public CustomScriptAssemblyPlatform(string name, string displayName, BuildTarget buildTarget) : this() - { - Name = name; - DisplayName = displayName; - BuildTarget = buildTarget; - } - - public CustomScriptAssemblyPlatform(string name, BuildTarget buildTarget) : this(name, name, buildTarget) - { - } - } - - class CustomScriptAssembly - { - public string FilePath { get; set; } - public string PathPrefix { get; set; } - public string Name { get; set; } - public string[] References { get; set; } - public OptionalUnityReferences OptionalUnityReferences { get; set; } - public CustomScriptAssemblyPlatform[] IncludePlatforms { get; set; } - public CustomScriptAssemblyPlatform[] ExcludePlatforms { get; set; } - - public EditorCompilation.PackageAssembly? PackageAssembly { get; set; } - public ScriptCompilerOptions CompilerOptions { get; set; } - - public AssemblyFlags AssemblyFlags - { - get - { - if (IncludePlatforms != null && IncludePlatforms.Length == 1 && IncludePlatforms[0].BuildTarget == BuildTarget.NoTarget) - return AssemblyFlags.EditorOnly; - - return AssemblyFlags.None; - } - } - - public static CustomScriptAssemblyPlatform[] Platforms { get; private set; } - public static CustomScriptAssemblyPlatform[] DeprecatedPlatforms { get; private set; } - - public static CustomScriptOptinalUnityAssembly[] OptinalUnityAssemblies { get; private set; } - - static CustomScriptAssembly() - { - // When removing a platform from Platforms, please add it to DeprecatedPlatforms. - Platforms = new CustomScriptAssemblyPlatform[] - { - new CustomScriptAssemblyPlatform("Editor", "Editor", BuildTarget.NoTarget), - new CustomScriptAssemblyPlatform("macOSStandalone", "macOS", BuildTarget.StandaloneOSX), - new CustomScriptAssemblyPlatform("WindowsStandalone32", "Windows 32-bit", BuildTarget.StandaloneWindows), - new CustomScriptAssemblyPlatform("WindowsStandalone64", "Windows 64-bit", BuildTarget.StandaloneWindows64), - new CustomScriptAssemblyPlatform("LinuxStandalone32", "Linux 32-bit", BuildTarget.StandaloneLinux), - new CustomScriptAssemblyPlatform("LinuxStandalone64", "Linux 64-bit", BuildTarget.StandaloneLinux64), - new CustomScriptAssemblyPlatform("LinuxStandaloneUniversal", "Linux Universal", BuildTarget.StandaloneLinuxUniversal), - new CustomScriptAssemblyPlatform("iOS", BuildTarget.iOS), - new CustomScriptAssemblyPlatform("Android", BuildTarget.Android), - new CustomScriptAssemblyPlatform("WebGL", BuildTarget.WebGL), - new CustomScriptAssemblyPlatform("WSA", "Universal Windows Platform", BuildTarget.WSAPlayer), - new CustomScriptAssemblyPlatform("PSVita", BuildTarget.PSP2), - new CustomScriptAssemblyPlatform("PS4", BuildTarget.PS4), - new CustomScriptAssemblyPlatform("XboxOne", BuildTarget.XboxOne), - new CustomScriptAssemblyPlatform("Nintendo3DS", BuildTarget.N3DS), - new CustomScriptAssemblyPlatform("tvOS", BuildTarget.tvOS), - new CustomScriptAssemblyPlatform("Switch", BuildTarget.Switch), - }; - -#pragma warning disable 0618 - DeprecatedPlatforms = new CustomScriptAssemblyPlatform[] - { - new CustomScriptAssemblyPlatform("PSMobile", BuildTarget.PSM), - new CustomScriptAssemblyPlatform("Tizen", BuildTarget.Tizen), - new CustomScriptAssemblyPlatform("WiiU", BuildTarget.WiiU), - }; -#pragma warning restore 0618 - - OptinalUnityAssemblies = new[] - { - new CustomScriptOptinalUnityAssembly("Test Assemblies", OptionalUnityReferences.TestAssemblies, "Predefined Assemblies (Assembly-CSharp.dll etc) will not reference this assembly.\nThis assembly will only be used for tests and will not be included in player builds."), - }; - } - - public bool IsCompatibleWithEditor() - { - if (ExcludePlatforms != null) - return ExcludePlatforms.All(p => p.BuildTarget != BuildTarget.NoTarget); - - if (IncludePlatforms != null) - return IncludePlatforms.Any(p => p.BuildTarget == BuildTarget.NoTarget); - - return true; - } - - public bool IsCompatibleWith(BuildTarget buildTarget, EditorScriptCompilationOptions options) - { - bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; - - var isTestAssembly = (OptionalUnityReferences & OptionalUnityReferences.TestAssemblies) == OptionalUnityReferences.TestAssemblies; - var isBuildingWithTestAssemblies = (options & EditorScriptCompilationOptions.BuildingIncludingTestAssemblies) == EditorScriptCompilationOptions.BuildingIncludingTestAssemblies; - if (!buildingForEditor && isTestAssembly && !isBuildingWithTestAssemblies) - { - return false; - } - - var isPackage = PackageAssembly.HasValue; - if (isTestAssembly && isPackage && !PackageAssembly.Value.IncludeTestAssemblies) - { - return false; - } - - // Compatible with editor and all platforms. - if (IncludePlatforms == null && ExcludePlatforms == null) - return true; - - if (buildingForEditor) - return IsCompatibleWithEditor(); - - if (buildingForEditor) - buildTarget = BuildTarget.NoTarget; // Editor - - if (ExcludePlatforms != null) - return ExcludePlatforms.All(p => p.BuildTarget != buildTarget); - - return IncludePlatforms.Any(p => p.BuildTarget == buildTarget); - } - - public static CustomScriptAssembly Create(string name, string directory) - { - var customScriptAssembly = new CustomScriptAssembly(); - - var modifiedDirectory = AssetPath.ReplaceSeparators(directory); - - if (modifiedDirectory.Last() != AssetPath.Separator) - modifiedDirectory += AssetPath.Separator; - - customScriptAssembly.Name = name; - customScriptAssembly.FilePath = modifiedDirectory; - customScriptAssembly.PathPrefix = modifiedDirectory; - customScriptAssembly.References = new string[0]; - customScriptAssembly.CompilerOptions = new ScriptCompilerOptions(); - - return customScriptAssembly; - } - - public static CustomScriptAssembly FromCustomScriptAssemblyData(string path, CustomScriptAssemblyData customScriptAssemblyData) - { - if (customScriptAssemblyData == null) - return null; - - var pathPrefix = path.Substring(0, path.Length - AssetPath.GetFileName(path).Length); - - var customScriptAssembly = new CustomScriptAssembly(); - - customScriptAssembly.Name = customScriptAssemblyData.name; - customScriptAssembly.References = customScriptAssemblyData.references; - customScriptAssembly.FilePath = path; - customScriptAssembly.PathPrefix = pathPrefix; - - customScriptAssemblyData.optionalUnityReferences = customScriptAssemblyData.optionalUnityReferences ?? new string[0]; - foreach (var optionalUnityReferenceString in customScriptAssemblyData.optionalUnityReferences) - { - var optionalUnityReference = (OptionalUnityReferences)Enum.Parse(typeof(OptionalUnityReferences), optionalUnityReferenceString); - customScriptAssembly.OptionalUnityReferences |= optionalUnityReference; - } - - if (customScriptAssemblyData.includePlatforms != null && customScriptAssemblyData.includePlatforms.Length > 0) - customScriptAssembly.IncludePlatforms = GetPlatformsFromNames(customScriptAssemblyData.includePlatforms); - - if (customScriptAssemblyData.excludePlatforms != null && customScriptAssemblyData.excludePlatforms.Length > 0) - customScriptAssembly.ExcludePlatforms = GetPlatformsFromNames(customScriptAssemblyData.excludePlatforms); - - var compilerOptions = new ScriptCompilerOptions(); - - compilerOptions.AllowUnsafeCode = customScriptAssemblyData.allowUnsafeCode; - - customScriptAssembly.CompilerOptions = compilerOptions; - - return customScriptAssembly; - } - - public static CustomScriptAssemblyPlatform[] GetPlatformsFromNames(string[] names) - { - var platforms = new List(); - - foreach (var name in names) - { - // Ignore deprecated platforms. - if (IsDeprecatedPlatformName(name)) - continue; - - platforms.Add(GetPlatformFromName(name)); - } - - return platforms.ToArray(); - } - - public static bool IsDeprecatedPlatformName(string name) - { - foreach (var platform in DeprecatedPlatforms) - if (string.Equals(platform.Name, name, System.StringComparison.OrdinalIgnoreCase)) - return true; - - return false; - } - - public static CustomScriptAssemblyPlatform GetPlatformFromName(string name) - { - foreach (var platform in Platforms) - if (string.Equals(platform.Name, name, System.StringComparison.OrdinalIgnoreCase)) - return platform; - - var platformNames = Platforms.Select(p => string.Format("\"{0}\"", p.Name)).ToArray(); - System.Array.Sort(platformNames); - - var platformsString = string.Join(",\n", platformNames); - - throw new System.ArgumentException(string.Format("Platform name '{0}' not supported.\nSupported platform names:\n{1}\n", name, platformsString)); - } - - public static CustomScriptAssemblyPlatform GetPlatformFromBuildTarget(BuildTarget buildTarget) - { - foreach (var platform in Platforms) - if (platform.BuildTarget == buildTarget) - return platform; - - throw new System.ArgumentException(string.Format("No CustomScriptAssemblyPlatform setup for BuildTarget '{0}'", buildTarget)); - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs deleted file mode 100644 index c678da6663..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ /dev/null @@ -1,817 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.Compilation; -using UnityEditor.Scripting.Compilers; -using File = System.IO.File; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - // This class is intentionally immutable, avoid adding mutable state to it. - static class EditorBuildRules - { - [Flags] - internal enum TargetAssemblyType - { - Undefined = 0, - Predefined = 1, - Custom = 2 - } - - internal enum EditorCompatibility - { - NotCompatibleWithEditor = 0, - CompatibleWithEditor = 1 - } - - internal class TargetAssembly - { - public string Filename { get; private set; } - public SupportedLanguage Language { get; set; } - public AssemblyFlags Flags { get; private set; } - public Func PathFilter { get; private set; } - public Func IsCompatibleFunc { get; private set; } - public List References { get; private set; } - public TargetAssemblyType Type { get; private set; } - public OptionalUnityReferences OptionalUnityReferences { get; set; } - public ScriptCompilerOptions CompilerOptions { get; set; } - - public TargetAssembly() - { - References = new List(); - } - - public TargetAssembly(string name, - SupportedLanguage language, - AssemblyFlags flags, - TargetAssemblyType type, - Func pathFilter, - Func compatFunc, - ScriptCompilerOptions compilerOptions) : this() - { - Language = language; - Filename = name; - Flags = flags; - PathFilter = pathFilter; - IsCompatibleFunc = compatFunc; - Type = type; - CompilerOptions = compilerOptions; - } - - public string FilenameWithSuffix(string filenameSuffix) - { - if (!string.IsNullOrEmpty(filenameSuffix)) - return Filename.Replace(".dll", filenameSuffix + ".dll"); - - return Filename; - } - - public string FullPath(string outputDirectory, string filenameSuffix) - { - return AssetPath.Combine(outputDirectory, FilenameWithSuffix(filenameSuffix)); - } - - public EditorCompatibility editorCompatibility - { - get - { - bool isCompatibleWithEditor = IsCompatibleFunc == null || - IsCompatibleFunc(BuildTarget.NoTarget, EditorScriptCompilationOptions.BuildingForEditor); - - return isCompatibleWithEditor - ? EditorCompatibility.CompatibleWithEditor - : EditorCompatibility.NotCompatibleWithEditor; - } - } - } - - public class CompilationAssemblies - { - public PrecompiledAssembly[] UnityAssemblies { get; set; } - public PrecompiledAssembly[] PrecompiledAssemblies { get; set; } - public TargetAssembly[] CustomTargetAssemblies { get; set; } - public TargetAssembly[] PredefinedAssembliesCustomTargetReferences { get; set; } - public string[] EditorAssemblyReferences { get; set; } - } - - public class GenerateChangedScriptAssembliesArgs - { - public IEnumerable AllSourceFiles { get; set; } - public IEnumerable DirtySourceFiles { get; set; } - public string ProjectDirectory { get; set; } - public ScriptAssemblySettings Settings { get; set; } - public CompilationAssemblies Assemblies { get; set; } - public HashSet RunUpdaterAssemblies { get; set; } - public HashSet NotCompiledTargetAssemblies { get; set; } - - public GenerateChangedScriptAssembliesArgs() - { - NotCompiledTargetAssemblies = new HashSet(); - } - } - - static readonly TargetAssembly[] predefinedTargetAssemblies; - - static EditorBuildRules() - { - predefinedTargetAssemblies = CreatePredefinedTargetAssemblies(); - } - - public static TargetAssembly[] GetPredefinedTargetAssemblies() - { - return predefinedTargetAssemblies; - } - - public static PrecompiledAssembly CreateUserCompiledAssembly(string path) - { - var flags = AssemblyFlags.None; - - var lowerPath = path.ToLower(); - if (lowerPath.Contains("/editor/") || lowerPath.Contains(@"\editor\")) - flags |= AssemblyFlags.EditorOnly; - - return new PrecompiledAssembly - { - Path = path, - Flags = flags - }; - } - - public static PrecompiledAssembly CreateEditorCompiledAssembly(string path) - { - return new PrecompiledAssembly - { - Path = path, - Flags = AssemblyFlags.EditorOnly - }; - } - - public static TargetAssembly[] CreateTargetAssemblies(IEnumerable customScriptAssemblies) - { - if (customScriptAssemblies == null) - return null; - - - foreach (var customAssembly in customScriptAssemblies) - { - if (predefinedTargetAssemblies.Any(p => AssetPath.GetAssemblyNameWithoutExtension(p.Filename) == customAssembly.Name)) - { - throw new Exception(string.Format("Assembly cannot be have reserved name '{0}'. Defined in '{1}'", customAssembly.Name, customAssembly.FilePath)); - } - } - - var targetAssemblies = new List(); - var nameToTargetAssembly = new Dictionary(); - - // Create TargetAssemblies - foreach (var customAssembly in customScriptAssemblies) - { - var pathPrefixLowerCase = customAssembly.PathPrefix.ToLower(); - - var targetAssembly = new TargetAssembly(customAssembly.Name + ".dll", - null, - customAssembly.AssemblyFlags, - TargetAssemblyType.Custom, - path => path.StartsWith(pathPrefixLowerCase) ? pathPrefixLowerCase.Length : -1, - (BuildTarget target, EditorScriptCompilationOptions options) => customAssembly.IsCompatibleWith(target, options), - customAssembly.CompilerOptions) - { - OptionalUnityReferences = customAssembly.OptionalUnityReferences, - }; - - targetAssemblies.Add(targetAssembly); - nameToTargetAssembly[customAssembly.Name] = targetAssembly; - } - - var targetAssembliesEnumerator = targetAssemblies.GetEnumerator(); - - // Setup references for TargetAssemblies - foreach (var customAssembly in customScriptAssemblies) - { - targetAssembliesEnumerator.MoveNext(); - var targetAssembly = targetAssembliesEnumerator.Current; - - if (customAssembly.References == null) - continue; - - foreach (var reference in customAssembly.References) - { - TargetAssembly referenceAssembly = null; - - if (!nameToTargetAssembly.TryGetValue(reference, out referenceAssembly)) - { - UnityEngine.Debug.LogWarning(string.Format("Could not find reference '{0}' for assembly '{1}'", reference, customAssembly.Name)); - continue; - } - - targetAssembly.References.Add(referenceAssembly); - } - } - - return targetAssemblies.ToArray(); - } - - public static ScriptAssembly[] GetAllScriptAssemblies(IEnumerable allSourceFiles, string projectDirectory, ScriptAssemblySettings settings, CompilationAssemblies assemblies, TargetAssemblyType onlyIncludeType = TargetAssemblyType.Undefined) - { - if (allSourceFiles == null || allSourceFiles.Count() == 0) - return new ScriptAssembly[0]; - - var targetAssemblyFiles = new Dictionary>(); - - foreach (var scriptFile in allSourceFiles) - { - var targetAssembly = GetTargetAssembly(scriptFile, projectDirectory, assemblies.CustomTargetAssemblies); - - if (!IsCompatibleWithPlatform(targetAssembly, settings)) - continue; - - // Optionally only include specific TargetAssemblyType assemblies. - if (onlyIncludeType != TargetAssemblyType.Undefined && targetAssembly.Type != onlyIncludeType) - continue; - - var scriptExtension = ScriptCompilers.GetExtensionOfSourceFile(scriptFile); - var scriptLanguage = ScriptCompilers.GetLanguageFromExtension(scriptExtension); - - if (targetAssembly.Language == null && targetAssembly.Type == TargetAssemblyType.Custom) - targetAssembly.Language = scriptLanguage; - - HashSet assemblySourceFiles; - - if (!targetAssemblyFiles.TryGetValue(targetAssembly, out assemblySourceFiles)) - { - assemblySourceFiles = new HashSet(); - targetAssemblyFiles[targetAssembly] = assemblySourceFiles; - } - - assemblySourceFiles.Add(AssetPath.Combine(projectDirectory, scriptFile)); - } - - return ToScriptAssemblies(targetAssemblyFiles, settings, assemblies, null); - } - - public static ScriptAssembly[] GenerateChangedScriptAssemblies(GenerateChangedScriptAssembliesArgs args) - { - var dirtyTargetAssemblies = new Dictionary>(); - - var allTargetAssemblies = args.Assemblies.CustomTargetAssemblies == null ? - predefinedTargetAssemblies : - predefinedTargetAssemblies.Concat(args.Assemblies.CustomTargetAssemblies).ToArray(); - - // Mark all assemblies that the script updater must be run on as dirty. - if (args.RunUpdaterAssemblies != null) - foreach (var assemblyFilename in args.RunUpdaterAssemblies) - { - var targetAssembly = allTargetAssemblies.First(a => a.FilenameWithSuffix(args.Settings.FilenameSuffix) == assemblyFilename); - dirtyTargetAssemblies[targetAssembly] = new HashSet(); - } - - // Collect all dirty TargetAssemblies - foreach (var dirtySourceFile in args.DirtySourceFiles) - { - var targetAssembly = GetTargetAssembly(dirtySourceFile, args.ProjectDirectory, args.Assemblies.CustomTargetAssemblies); - - if (!IsCompatibleWithPlatform(targetAssembly, args.Settings)) - continue; - - HashSet assemblySourceFiles; - - var scriptExtension = ScriptCompilers.GetExtensionOfSourceFile(dirtySourceFile); - var scriptLanguage = ScriptCompilers.GetLanguageFromExtension(scriptExtension); - - if (!dirtyTargetAssemblies.TryGetValue(targetAssembly, out assemblySourceFiles)) - { - assemblySourceFiles = new HashSet(); - dirtyTargetAssemblies[targetAssembly] = assemblySourceFiles; - - if (targetAssembly.Type == TargetAssemblyType.Custom) - targetAssembly.Language = scriptLanguage; - } - - assemblySourceFiles.Add(AssetPath.Combine(args.ProjectDirectory, dirtySourceFile)); - - // If there are mixed languages in a custom script folder, mark the assembly to not be compiled. - if (scriptLanguage != targetAssembly.Language) - args.NotCompiledTargetAssemblies.Add(targetAssembly); - } - - bool isAnyCustomScriptAssemblyDirty = dirtyTargetAssemblies.Any(entry => entry.Key.Type == TargetAssemblyType.Custom); - - // If we have any dirty custom target assemblies, then the predefined target assemblies are marked as dirty, - // as the predefined assemblies always reference the custom script assemblies. - if (isAnyCustomScriptAssemblyDirty) - { - foreach (var assembly in predefinedTargetAssemblies) - { - if (!IsCompatibleWithPlatform(assembly, args.Settings)) - continue; - - if (!dirtyTargetAssemblies.ContainsKey(assembly)) - dirtyTargetAssemblies[assembly] = new HashSet(); - } - } - - // Collect any TargetAssemblies that reference the dirty TargetAssemblies, as they will also be dirty. - int dirtyAssemblyCount; - - do - { - dirtyAssemblyCount = 0; - - foreach (var assembly in allTargetAssemblies) - { - if (!IsCompatibleWithPlatform(assembly, args.Settings)) - continue; - - // If already dirty, skip. - if (dirtyTargetAssemblies.ContainsKey(assembly)) - continue; - - foreach (var reference in assembly.References) - if (dirtyTargetAssemblies.ContainsKey(reference)) - { - dirtyTargetAssemblies[assembly] = new HashSet(); - dirtyAssemblyCount++; - break; - } - } - } - while (dirtyAssemblyCount > 0); - - // Add any non-dirty source files that belong to dirty TargetAssemblies - foreach (var sourceFile in args.AllSourceFiles) - { - var targetAssembly = GetTargetAssembly(sourceFile, args.ProjectDirectory, args.Assemblies.CustomTargetAssemblies); - - if (!IsCompatibleWithPlatform(targetAssembly, args.Settings)) - continue; - - HashSet assemblySourceFiles; - - var scriptExtension = ScriptCompilers.GetExtensionOfSourceFile(sourceFile); - var scriptLanguage = ScriptCompilers.GetLanguageFromExtension(scriptExtension); - - if (targetAssembly.Language == null && targetAssembly.Type == TargetAssemblyType.Custom) - targetAssembly.Language = scriptLanguage; - - // If there are mixed languages in a custom script folder, mark the assembly to not be compiled. - if (scriptLanguage != targetAssembly.Language) - args.NotCompiledTargetAssemblies.Add(targetAssembly); - - if (dirtyTargetAssemblies.TryGetValue(targetAssembly, out assemblySourceFiles)) - assemblySourceFiles.Add(AssetPath.Combine(args.ProjectDirectory, sourceFile)); - } - - // Remove any target assemblies which have no source files associated with them. - dirtyTargetAssemblies = dirtyTargetAssemblies.Where(e => e.Value.Count > 0).ToDictionary(e => e.Key, e => e.Value); - - // Remove any target assemblies which have been marked as do not compile. - foreach (var removeAssembly in args.NotCompiledTargetAssemblies) - dirtyTargetAssemblies.Remove(removeAssembly); - - - // Convert TargetAssemblies to ScriptAssembiles - var scriptAssemblies = ToScriptAssemblies(dirtyTargetAssemblies, args.Settings, args.Assemblies, args.RunUpdaterAssemblies); - return scriptAssemblies; - } - - internal static ScriptAssembly[] ToScriptAssemblies(IDictionary> targetAssemblies, ScriptAssemblySettings settings, - CompilationAssemblies assemblies, HashSet runUpdaterAssemblies) - { - var scriptAssemblies = new ScriptAssembly[targetAssemblies.Count]; - - var targetToScriptAssembly = new Dictionary(); - int index = 0; - - bool buildingForEditor = settings.BuildingForEditor; - foreach (var entry in targetAssemblies) - { - var targetAssembly = entry.Key; - var sourceFiles = entry.Value; - var scriptAssembly = new ScriptAssembly(); - - // Setup TargetAssembly -> ScriptAssembly mapping for converting references - scriptAssemblies[index] = scriptAssembly; - targetToScriptAssembly[targetAssembly] = scriptAssemblies[index++]; - - // Setup ScriptAssembly - scriptAssembly.Flags = targetAssembly.Flags; - scriptAssembly.BuildTarget = settings.BuildTarget; - scriptAssembly.Language = targetAssembly.Language; - - var editorOnlyTargetAssembly = (targetAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; - - if (editorOnlyTargetAssembly || (buildingForEditor && settings.ApiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6)) - scriptAssembly.ApiCompatibilityLevel = (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) ? ApiCompatibilityLevel.NET_4_6 : ApiCompatibilityLevel.NET_2_0; - else - scriptAssembly.ApiCompatibilityLevel = settings.ApiCompatibilityLevel; - - if (!string.IsNullOrEmpty(settings.FilenameSuffix)) - { - var basename = AssetPath.GetAssemblyNameWithoutExtension(targetAssembly.Filename); - scriptAssembly.Filename = string.Concat(basename, settings.FilenameSuffix, ".dll"); - } - else - scriptAssembly.Filename = targetAssembly.Filename; - - if (runUpdaterAssemblies != null && runUpdaterAssemblies.Contains(scriptAssembly.Filename)) - scriptAssembly.RunUpdater = true; - - scriptAssembly.OutputDirectory = settings.OutputDirectory; - scriptAssembly.Defines = settings.Defines; - scriptAssembly.Files = sourceFiles.ToArray(); - - if (targetAssembly.Type == TargetAssemblyType.Predefined) - scriptAssembly.CompilerOptions = settings.PredefinedAssembliesCompilerOptions; - else - scriptAssembly.CompilerOptions = targetAssembly.CompilerOptions; - - // Script files must always be passed in the same order to the compiler. - // Otherwise player builds might fail for partial classes. - Array.Sort(scriptAssembly.Files); - } - - // Setup ScriptAssembly references - index = 0; - foreach (var entry in targetAssemblies) - AddScriptAssemblyReferences(ref scriptAssemblies[index++], entry.Key, settings, - assemblies, targetToScriptAssembly, settings.FilenameSuffix); - - return scriptAssemblies; - } - - static bool IsPrecompiledAssemblyCompatibleWithScriptAssembly(PrecompiledAssembly compiledAssembly, ScriptAssembly scriptAssembly) - { - bool useDotNet = WSAHelpers.UseDotNetCore(scriptAssembly); - - if (useDotNet) - { - bool compiledAssemblyCompatibleWithDotNet = (compiledAssembly.Flags & AssemblyFlags.UseForDotNet) == AssemblyFlags.UseForDotNet; - return compiledAssemblyCompatibleWithDotNet; - } - - bool compiledAssemblyCompatibleWithMono = (compiledAssembly.Flags & AssemblyFlags.UseForMono) == AssemblyFlags.UseForMono; - return compiledAssemblyCompatibleWithMono; - } - - internal static void AddScriptAssemblyReferences(ref ScriptAssembly scriptAssembly, TargetAssembly targetAssembly, ScriptAssemblySettings settings, - CompilationAssemblies assemblies, - IDictionary targetToScriptAssembly, string filenameSuffix) - { - var scriptAssemblyReferences = new List(); - var references = new List(); - bool buildingForEditor = settings.BuildingForEditor; - - // Add Unity assemblies (UnityEngine.dll, UnityEditor.dll) referencees. - var unityReferences = GetUnityReferences(scriptAssembly, assemblies.UnityAssemblies, settings.CompilationOptions); - references.AddRange(unityReferences); - - // Setup target assembly references - foreach (var reference in targetAssembly.References) - { - ScriptAssembly scriptAssemblyReference; - - // Add ScriptAssembly references to other dirty script assemblies that also need to be rebuilt. - if (targetToScriptAssembly.TryGetValue(reference, out scriptAssemblyReference)) - { - System.Diagnostics.Debug.Assert(scriptAssemblyReference != null); - scriptAssemblyReferences.Add(scriptAssemblyReference); - } - else - { - // Add string references to other assemblies that do not need to be rebuilt. - var assemblyPath = reference.FullPath(settings.OutputDirectory, filenameSuffix); - - if (File.Exists(assemblyPath)) - references.Add(assemblyPath); - } - } - - // For predefined target assembly add references to custom target assemblies - if (assemblies.CustomTargetAssemblies != null && (targetAssembly.Type & TargetAssemblyType.Predefined) == TargetAssemblyType.Predefined) - { - foreach (var customTargetAssembly in assemblies.PredefinedAssembliesCustomTargetReferences ?? Enumerable.Empty()) - { - ScriptAssembly scriptAssemblyReference; - - // Only add ScriptAssembly reference if the custom target assembly is dirty, e.g. is in targetToScriptAssembly dictionary - // Otherwise just add already compiled custom target assembly as precompiled reference. - if (targetToScriptAssembly.TryGetValue(customTargetAssembly, out scriptAssemblyReference)) - scriptAssemblyReferences.Add(scriptAssemblyReference); - else - { - var customTargetAssemblyPath = customTargetAssembly.FullPath(settings.OutputDirectory, filenameSuffix); - - // File might not exist if there are no scripts in the custom target assembly folder. - if (File.Exists(customTargetAssemblyPath)) - references.Add(customTargetAssemblyPath); - } - } - } - - // Add pre-compiled assemblies as references - PrecompiledAssembly[] precompiledAssembliesForReferences = assemblies.PrecompiledAssemblies ?? new PrecompiledAssembly[] {}; - if (settings.OptionalUnityReferences != OptionalUnityReferences.None) - { - precompiledAssembliesForReferences = precompiledAssembliesForReferences.Where(x => x.OptionalUnityReferences == OptionalUnityReferences.None || ((targetAssembly.OptionalUnityReferences & x.OptionalUnityReferences & settings.OptionalUnityReferences) != 0)).ToArray(); - } - - var precompiledReferences = GetPrecompiledReferences(scriptAssembly, targetAssembly.Type, settings.CompilationOptions, targetAssembly.editorCompatibility, precompiledAssembliesForReferences); - references.AddRange(precompiledReferences); - - if (buildingForEditor && assemblies.EditorAssemblyReferences != null) - references.AddRange(assemblies.EditorAssemblyReferences); - - references.AddRange(MonoLibraryHelpers.GetSystemLibraryReferences(scriptAssembly.ApiCompatibilityLevel, scriptAssembly.BuildTarget, scriptAssembly.Language, buildingForEditor, scriptAssembly.Filename)); - - scriptAssembly.ScriptAssemblyReferences = scriptAssemblyReferences.ToArray(); - scriptAssembly.References = references.ToArray(); - } - - public static List GetUnityReferences(ScriptAssembly scriptAssembly, PrecompiledAssembly[] unityAssemblies, EditorScriptCompilationOptions options) - { - var references = new List(); - - bool assemblyEditorOnly = (scriptAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; - bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; - - // Add Unity assemblies (UnityEngine.dll, UnityEditor.dll) referencees. - if (unityAssemblies != null) - foreach (var unityAssembly in unityAssemblies) - { - var moduleExcludedForRuntimeCode = (unityAssembly.Flags & AssemblyFlags.ExcludedForRuntimeCode) == AssemblyFlags.ExcludedForRuntimeCode; - - // Add Unity editor assemblies (UnityEditor.dll) to all assemblies when building inside the editor - if ((buildingForEditor && !moduleExcludedForRuntimeCode) || assemblyEditorOnly) - { - if ((unityAssembly.Flags & AssemblyFlags.UseForMono) != 0) - references.Add(unityAssembly.Path); - } - else - { - bool unityAssemblyEditorOnly = (unityAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; - - // Add Unity runtime assemblies (UnityEngine.dll) to all assemblies - if (!unityAssemblyEditorOnly && !moduleExcludedForRuntimeCode) - { - if (IsPrecompiledAssemblyCompatibleWithScriptAssembly(unityAssembly, scriptAssembly)) - references.Add(unityAssembly.Path); - } - } - } - - return references; - } - - public static List GetPrecompiledReferences(ScriptAssembly scriptAssembly, TargetAssemblyType targetAssemblyType, EditorScriptCompilationOptions options, EditorCompatibility editorCompatibility, PrecompiledAssembly[] precompiledAssemblies) - { - var references = new List(); - - bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; - bool assemblyEditorOnly = (scriptAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; - bool isCustomAssembly = (targetAssemblyType & TargetAssemblyType.Custom) == TargetAssemblyType.Custom; - - if (precompiledAssemblies != null) - foreach (var precompiledAssembly in precompiledAssemblies) - { - bool compiledAssemblyEditorOnly = (precompiledAssembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly; - - // Add all pre-compiled runtime assemblies as references to all script assemblies. Don't add pre-compiled editor assemblies as dependencies to runtime assemblies. - if (!compiledAssemblyEditorOnly || assemblyEditorOnly || (isCustomAssembly && buildingForEditor && editorCompatibility == EditorCompatibility.CompatibleWithEditor)) - { - if (IsPrecompiledAssemblyCompatibleWithScriptAssembly(precompiledAssembly, scriptAssembly)) - references.Add(precompiledAssembly.Path); - } - } - - return references; - } - - public static List GetCompiledCustomAssembliesReferences(ScriptAssembly scriptAssembly, TargetAssembly[] customTargetAssemblies, string outputDirectory, string filenameSuffix) - { - var references = new List(); - - if (customTargetAssemblies != null) - { - foreach (var customTargetAssembly in customTargetAssemblies) - { - var customTargetAssemblyPath = customTargetAssembly.FullPath(outputDirectory, filenameSuffix); - - // File might not exist if there are no scripts in the custom target assembly folder. - if (File.Exists(customTargetAssemblyPath)) - references.Add(customTargetAssemblyPath); - } - } - - return references; - } - - static bool IsCompatibleWithEditor(BuildTarget buildTarget, EditorScriptCompilationOptions options) - { - return (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; - } - - static bool IsCompatibleWithPlatform(TargetAssembly assembly, ScriptAssemblySettings settings) - { - return assembly.IsCompatibleFunc == null || assembly.IsCompatibleFunc(settings.BuildTarget, settings.CompilationOptions); - } - - internal static TargetAssembly[] CreatePredefinedTargetAssemblies() - { - var runtimeFirstPassAssemblies = new List(); - var runtimeAssemblies = new List(); - var editorFirstPassAssemblies = new List(); - var editorAssemblies = new List(); - - var supportedLanguages = ScriptCompilers.SupportedLanguages; - var assemblies = new List(); - - var scriptCompilerOptions = new ScriptCompilerOptions(); - - // Initialize predefined assembly targets - foreach (var language in supportedLanguages) - { - var languageName = language.GetLanguageName(); - - var runtimeFirstPass = new TargetAssembly("Assembly-" + languageName + "-firstpass" + ".dll", - language, - AssemblyFlags.FirstPass, - TargetAssemblyType.Predefined, - FilterAssemblyInFirstpassFolder, - null, - scriptCompilerOptions); - - var runtime = new TargetAssembly("Assembly-" + languageName + ".dll", - language, - AssemblyFlags.None, - TargetAssemblyType.Predefined, - null, - null, - scriptCompilerOptions); - - var editorFirstPass = new TargetAssembly("Assembly-" + languageName + "-Editor-firstpass" + ".dll", - language, - AssemblyFlags.EditorOnly | AssemblyFlags.FirstPass, - TargetAssemblyType.Predefined, - FilterAssemblyInFirstpassEditorFolder, - IsCompatibleWithEditor, - scriptCompilerOptions) - { - OptionalUnityReferences = OptionalUnityReferences.TestAssemblies, - }; - - var editor = new TargetAssembly("Assembly-" + languageName + "-Editor" + ".dll", - language, - AssemblyFlags.EditorOnly, - TargetAssemblyType.Predefined, - FilterAssemblyInEditorFolder, - IsCompatibleWithEditor, - scriptCompilerOptions) - { - OptionalUnityReferences = OptionalUnityReferences.TestAssemblies, - }; - - runtimeFirstPassAssemblies.Add(runtimeFirstPass); - runtimeAssemblies.Add(runtime); - editorFirstPassAssemblies.Add(editorFirstPass); - editorAssemblies.Add(editor); - - assemblies.Add(runtimeFirstPass); - assemblies.Add(runtime); - assemblies.Add(editorFirstPass); - assemblies.Add(editor); - } - - // Setup dependencies - - // Runtime assemblies depend all first pass runtime assemblies - foreach (var assembly in runtimeAssemblies) - assembly.References.AddRange(runtimeFirstPassAssemblies); - - // First pass editor assemblies depend on all first pass runtime assemblies - foreach (var assembly in editorFirstPassAssemblies) - assembly.References.AddRange(runtimeFirstPassAssemblies); - - // Editor assemblies depend on all previous runtime and editor assemblies - foreach (var assembly in editorAssemblies) - { - assembly.References.AddRange(runtimeFirstPassAssemblies); - assembly.References.AddRange(runtimeAssemblies); - assembly.References.AddRange(editorFirstPassAssemblies); - } - - return assemblies.ToArray(); - } - - internal static TargetAssembly GetTargetAssembly(string scriptPath, string projectDirectory, TargetAssembly[] customTargetAssemblies) - { - TargetAssembly resultAssembly = GetCustomTargetAssembly(scriptPath, projectDirectory, customTargetAssemblies); - - if (resultAssembly != null) - return resultAssembly; - - return GetPredefinedTargetAssembly(scriptPath); - } - - internal static TargetAssembly GetPredefinedTargetAssembly(string scriptPath) - { - TargetAssembly resultAssembly = null; - - var extension = AssetPath.GetExtension(scriptPath).Substring(1).ToLower(); - var lowerPath = "/" + scriptPath.ToLower(); - int highestPathDepth = -1; - - foreach (var assembly in predefinedTargetAssemblies) - { - if (extension != assembly.Language.GetExtensionICanCompile()) - continue; - - var pathFilter = assembly.PathFilter; - int pathDepth = -1; - - if (pathFilter == null) - pathDepth = 0; - else - pathDepth = pathFilter(lowerPath); - - if (pathDepth > highestPathDepth) - { - resultAssembly = assembly; - highestPathDepth = pathDepth; - } - } - - return resultAssembly; - } - - internal static TargetAssembly GetCustomTargetAssembly(string scriptPath, string projectDirectory, TargetAssembly[] customTargetAssemblies) - { - if (customTargetAssemblies == null) - return null; - - int highestPathDepth = -1; - TargetAssembly resultAssembly = null; - - // CustomScriptAssembly paths are absolute, so we convert the scriptPath to an absolute path, if necessary. - bool isPathAbsolute = AssetPath.IsPathRooted(scriptPath); - var lowerFullPath = isPathAbsolute ? AssetPath.GetFullPath(scriptPath).ToLower() : AssetPath.Combine(projectDirectory, scriptPath).ToLower(); - - foreach (var assembly in customTargetAssemblies) - { - int pathDepth = assembly.PathFilter(lowerFullPath); - - if (pathDepth <= highestPathDepth) - continue; - - resultAssembly = assembly; - highestPathDepth = pathDepth; - } - - return resultAssembly; - } - - static int FilterAssemblyInFirstpassFolder(string pathName) - { - int result; - - result = FilterAssemblyPathBeginsWith(pathName, "/assets/plugins/"); - if (result >= 0) return result; - - result = FilterAssemblyPathBeginsWith(pathName, "/assets/standard assets/"); - if (result >= 0) return result; - - result = FilterAssemblyPathBeginsWith(pathName, "/assets/pro standard assets/"); - if (result >= 0) return result; - - result = FilterAssemblyPathBeginsWith(pathName, "/assets/iphone standard assets/"); - if (result >= 0) return result; - - return -1; - } - - static int FilterAssemblyInFirstpassEditorFolder(string pathName) - { - int baseIndex = FilterAssemblyInFirstpassFolder(pathName); - if (baseIndex == -1) return -1; - - return FilterAssemblyInEditorFolder(pathName); - } - - static int FilterAssemblyInEditorFolder(string pathName) - { - const string editorSegment = "/editor/"; - int editorSegmentIndex = pathName.IndexOf(editorSegment); - if (editorSegmentIndex == -1) return -1; - - return editorSegmentIndex + editorSegment.Length; - } - - static int FilterAssemblyPathBeginsWith(string pathName, string prefix) - { - return pathName.StartsWith(prefix) ? prefix.Length : -1; - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs deleted file mode 100644 index b9a72cbf1b..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ /dev/null @@ -1,1270 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using UnityEditor.Modules; -using UnityEditor.Compilation; -using UnityEditor.Scripting.Compilers; -using UnityEditorInternal; -using CompilerMessage = UnityEditor.Scripting.Compilers.CompilerMessage; -using CompilerMessageType = UnityEditor.Scripting.Compilers.CompilerMessageType; -using Directory = System.IO.Directory; -using File = System.IO.File; -using IOException = System.IO.IOException; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - class EditorCompilation - { - public enum CompileStatus - { - Idle, - Compiling, - CompilationStarted, - CompilationFailed, - CompilationComplete - } - - public enum DeleteFileOptions - { - NoLogError = 0, - LogError = 1, - } - - [StructLayout(LayoutKind.Sequential)] - public struct TargetAssemblyInfo - { - public string Name; - public AssemblyFlags Flags; - } - - [StructLayout(LayoutKind.Sequential)] - public struct AssemblyCompilerMessages - { - public string assemblyFilename; - public CompilerMessage[] messages; - } - - [StructLayout(LayoutKind.Sequential)] - public struct PackageAssembly - { - public string DirectoryPath; - public string Name; - public bool IncludeTestAssemblies; - } - - [Flags] - public enum CompilationSetupErrorFlags - { - none = 0, - cyclicReferences = (1 << 0), - loadError = (1 << 0) - } - - bool areAllScriptsDirty; - string projectDirectory = string.Empty; - string assemblySuffix = string.Empty; - private HashSet allScripts = new HashSet(); - HashSet dirtyScripts = new HashSet(); - HashSet runScriptUpdaterAssemblies = new HashSet(); - PrecompiledAssembly[] precompiledAssemblies; - CustomScriptAssembly[] customScriptAssemblies; - CustomScriptAssembly[] packageCustomScriptAssemblies; - EditorBuildRules.TargetAssembly[] customTargetAssemblies; // TargetAssemblies for customScriptAssemblies and packageCustomScriptAssemblies. - PrecompiledAssembly[] unityAssemblies; - CompilationTask compilationTask; - string outputDirectory; - CompilationSetupErrorFlags setupErrorFlags = CompilationSetupErrorFlags.none; - List assemblyBuilders = new List(); - - static readonly string EditorTempPath = "Temp"; - - public Action setupErrorFlagsChanged; - private PackageAssembly[] m_PackageAssemblies; - public event Action assemblyCompilationStarted; - public event Action assemblyCompilationFinished; - - static EditorCompilation() - { - } - - internal string GetAssemblyTimestampPath(string editorAssemblyPath) - { - return AssetPath.Combine(editorAssemblyPath, "BuiltinAssemblies.stamp"); - } - - internal void SetProjectDirectory(string projectDirectory) - { - this.projectDirectory = projectDirectory; - } - - internal void SetAssemblySuffix(string assemblySuffix) - { - this.assemblySuffix = assemblySuffix; - } - - public void SetAllScripts(string[] allScripts) - { - this.allScripts = new HashSet(allScripts); - - foreach (var dirtyScript in dirtyScripts) - this.allScripts.Add(dirtyScript); - } - - public bool IsExtensionSupportedByCompiler(string extension) - { - var languages = ScriptCompilers.SupportedLanguages; - return languages.Count(l => l.GetExtensionICanCompile() == extension) > 0; - } - - public string[] GetExtensionsSupportedByCompiler() - { - var languages = ScriptCompilers.SupportedLanguages; - return languages.Select(language => language.GetExtensionICanCompile()).ToArray(); - } - - public void DirtyPredefinedAssemblyScripts(EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) - { - var scriptAssemblySettings = CreateScriptAssemblySettings(platformGroup, platform, options); - var scriptAssemblies = GetAllScriptAssembliesOfType(scriptAssemblySettings, EditorBuildRules.TargetAssemblyType.Predefined); - - foreach (var assembly in scriptAssemblies) - { - foreach (var script in assembly.Files) - { - dirtyScripts.Add(script); - } - } - } - - public void DirtyAllScripts() - { - areAllScriptsDirty = true; - } - - public void DirtyScript(string path) - { - allScripts.Add(path); - dirtyScripts.Add(path); - } - - public void ClearDirtyScripts() - { - dirtyScripts.Clear(); - areAllScriptsDirty = false; - } - - public void RunScriptUpdaterOnAssembly(string assemblyFilename) - { - runScriptUpdaterAssemblies.Add(assemblyFilename); - } - - public void SetAllUnityAssemblies(PrecompiledAssembly[] unityAssemblies) - { - this.unityAssemblies = unityAssemblies; - } - - public void SetCompileScriptsOutputDirectory(string directory) - { - this.outputDirectory = directory; - } - - public string GetCompileScriptsOutputDirectory() - { - if (string.IsNullOrEmpty(outputDirectory)) - throw new Exception("Must set an output directory through SetCompileScriptsOutputDirectory before compiling"); - return outputDirectory; - } - - public void SetCompilationSetupErrorFlags(CompilationSetupErrorFlags flags) - { - var newFlags = setupErrorFlags | flags; - - if (newFlags != setupErrorFlags) - { - setupErrorFlags = newFlags; - - if (setupErrorFlagsChanged != null) - setupErrorFlagsChanged(setupErrorFlags); - } - } - - public void ClearCompilationSetupErrorFlags(CompilationSetupErrorFlags flags) - { - var newFlags = setupErrorFlags & ~flags; - - if (newFlags != setupErrorFlags) - { - setupErrorFlags = newFlags; - - if (setupErrorFlagsChanged != null) - setupErrorFlagsChanged(setupErrorFlags); - } - } - - public bool HaveSetupErrors() - { - return setupErrorFlags != CompilationSetupErrorFlags.none; - } - - public void SetAllPrecompiledAssemblies(PrecompiledAssembly[] precompiledAssemblies) - { - this.precompiledAssemblies = precompiledAssemblies; - } - - public PrecompiledAssembly[] GetAllPrecompiledAssemblies() - { - return this.precompiledAssemblies; - } - - public TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies() - { - if (customTargetAssemblies == null) - return new TargetAssemblyInfo[0]; - - var customTargetAssemblyCompiledPaths = new Dictionary(); - - foreach (var assembly in customTargetAssemblies) - { - var path = assembly.FullPath(outputDirectory, assemblySuffix); - - // Collect all assemblies that have been compiled (exist on file system) - if (File.Exists(path)) - customTargetAssemblyCompiledPaths.Add(assembly, path); - } - - bool removed; - - do - { - removed = false; - - if (customTargetAssemblyCompiledPaths.Count > 0) - { - foreach (var assembly in customTargetAssemblies) - { - if (!customTargetAssemblyCompiledPaths.ContainsKey(assembly)) - continue; - - // Check for each compiled assembly that all it's references - // have also been compiled. If not, remove it from the list - // of compiled assemblies. - foreach (var reference in assembly.References) - { - if (!customTargetAssemblyCompiledPaths.ContainsKey(reference)) - { - customTargetAssemblyCompiledPaths.Remove(assembly); - removed = true; - break; - } - } - } - } - } - while (removed); - - var count = customTargetAssemblyCompiledPaths.Count; - var targetAssemblies = new TargetAssemblyInfo[customTargetAssemblyCompiledPaths.Count]; - int index = 0; - - foreach (var entry in customTargetAssemblyCompiledPaths) - { - var assembly = entry.Key; - targetAssemblies[index++] = ToTargetAssemblyInfo(assembly); - } - - return targetAssemblies; - } - - static CustomScriptAssembly LoadCustomScriptAssemblyFromJson(string path) - { - var json = File.ReadAllText(path); - - try - { - var customScriptAssemblyData = CustomScriptAssemblyData.FromJson(json); - return CustomScriptAssembly.FromCustomScriptAssemblyData(path, customScriptAssemblyData); - } - catch (Exception e) - { - throw new Compilation.AssemblyDefinitionException(e.Message, path); - } - } - - string[] CustomTargetAssembliesToFilePaths(IEnumerable targetAssemblies) - { - var customAssemblies = targetAssemblies.Select(a => FindCustomTargetAssemblyFromTargetAssembly(a)); - var filePaths = customAssemblies.Select(a => a.FilePath).ToArray(); - return filePaths; - } - - string CustomTargetAssembliesToFilePaths(EditorBuildRules.TargetAssembly targetAssembly) - { - return FindCustomTargetAssemblyFromTargetAssembly(targetAssembly).FilePath; - } - - void CheckCyclicAssemblyReferencesDFS(EditorBuildRules.TargetAssembly visitAssembly, HashSet visited) - { - if (visited.Contains(visitAssembly)) - throw new Compilation.AssemblyDefinitionException("Assembly with cyclic references detected", CustomTargetAssembliesToFilePaths(visited)); - - visited.Add(visitAssembly); - - foreach (var reference in visitAssembly.References) - { - if (reference.Filename == visitAssembly.Filename) - throw new Compilation.AssemblyDefinitionException("Assembly contains a references to itself", CustomTargetAssembliesToFilePaths(visitAssembly)); - - CheckCyclicAssemblyReferencesDFS(reference, visited); - } - - visited.Remove(visitAssembly); - } - - void CheckCyclicAssemblyReferences() - { - if (customTargetAssemblies == null || customTargetAssemblies.Length < 1) - return; - - var visited = new HashSet(); - - try - { - foreach (var assembly in customTargetAssemblies) - CheckCyclicAssemblyReferencesDFS(assembly, visited); - } - catch (Exception e) - { - SetCompilationSetupErrorFlags(CompilationSetupErrorFlags.cyclicReferences); - throw e; - } - } - - void UpdateCustomTargetAssemblies() - { - var allCustomScriptAssemblies = new List(); - - if (customScriptAssemblies != null) - allCustomScriptAssemblies.AddRange(customScriptAssemblies); - - if (packageCustomScriptAssemblies != null) - { - if (customScriptAssemblies == null) - { - // There are no other custom script assemblies, add default customs script assemblies for all packages. - allCustomScriptAssemblies.AddRange(packageCustomScriptAssemblies.Select(a => CustomScriptAssembly.Create(a.Name, a.FilePath))); - } - else - { - foreach (var packageCustomScriptAssembly in packageCustomScriptAssemblies) - { - var packageAssembly = this.m_PackageAssemblies.Single(x => x.Name == packageCustomScriptAssembly.Name); - var pathPrefix = packageCustomScriptAssembly.PathPrefix.ToLowerInvariant(); - - // We have found an assembly definition file in the package directory, do not - // add a default custom script assembly for the package. - var customAssemblyInPackageRoot = customScriptAssemblies.SingleOrDefault(a => a.PathPrefix.ToLowerInvariant() == pathPrefix); - if (customAssemblyInPackageRoot != null) - { - continue; - } - - allCustomScriptAssemblies.Add(CreatePackageCustomScriptAssembly(packageAssembly)); - } - } - } - - foreach (var assembly in allCustomScriptAssemblies) - { - try - { - if (m_PackageAssemblies != null && !assembly.PackageAssembly.HasValue) - { - var pathPrefix = assembly.PathPrefix.ToLowerInvariant(); - - foreach (var packageAssembly in m_PackageAssemblies) - { - var lower = AssetPath.ReplaceSeparators(packageAssembly.DirectoryPath).ToLowerInvariant(); - if (pathPrefix.StartsWith(lower)) - { - assembly.PackageAssembly = packageAssembly; - break; - } - } - } - - foreach (var reference in assembly.References) - { - if (!allCustomScriptAssemblies.Any(a => a.Name == reference)) - throw new Compilation.AssemblyDefinitionException(string.Format("Assembly has reference to non-existent assembly '{0}'", reference), assembly.FilePath); - } - } - catch (Exception e) - { - SetCompilationSetupErrorFlags(CompilationSetupErrorFlags.loadError); - throw e; - } - } - - customTargetAssemblies = EditorBuildRules.CreateTargetAssemblies(allCustomScriptAssemblies); - ClearCompilationSetupErrorFlags(CompilationSetupErrorFlags.cyclicReferences); - } - - public void SetAllCustomScriptAssemblyJsons(string[] paths) - { - var assemblies = new List(); - - ClearCompilationSetupErrorFlags(CompilationSetupErrorFlags.loadError); - - foreach (var path in paths) - { - var fullPath = AssetPath.IsPathRooted(path) ? AssetPath.GetFullPath(path) : AssetPath.Combine(projectDirectory, path); - CustomScriptAssembly loadedCustomScriptAssembly = null; - - try - { - loadedCustomScriptAssembly = LoadCustomScriptAssemblyFromJson(fullPath); - - var duplicates = assemblies.Where(a => string.Equals(a.Name, loadedCustomScriptAssembly.Name, System.StringComparison.OrdinalIgnoreCase)); - - if (duplicates.Any()) - { - var filePaths = new List(); - filePaths.Add(loadedCustomScriptAssembly.FilePath); - filePaths.AddRange(duplicates.Select(a => a.FilePath)); - throw new Compilation.AssemblyDefinitionException(string.Format("Assembly with name '{0}' already exists", loadedCustomScriptAssembly.Name), filePaths.ToArray()); - } - - var samePrefixes = assemblies.Where(a => a.PathPrefix == loadedCustomScriptAssembly.PathPrefix); - - if (samePrefixes.Any()) - { - var filePaths = new List(); - filePaths.Add(loadedCustomScriptAssembly.FilePath); - filePaths.AddRange(samePrefixes.Select(a => a.FilePath)); - throw new Compilation.AssemblyDefinitionException(string.Format("Folder '{0}' contains multiple assembly definition files", loadedCustomScriptAssembly.PathPrefix), filePaths.ToArray()); - } - - if (loadedCustomScriptAssembly.References == null) - loadedCustomScriptAssembly.References = new string[0]; - - if (loadedCustomScriptAssembly.References.Length != loadedCustomScriptAssembly.References.Distinct().Count()) - throw new Compilation.AssemblyDefinitionException("Assembly has duplicate references", loadedCustomScriptAssembly.FilePath); - } - catch (Exception e) - { - SetCompilationSetupErrorFlags(CompilationSetupErrorFlags.loadError); - throw e; - } - - assemblies.Add(loadedCustomScriptAssembly); - } - - customScriptAssemblies = assemblies.ToArray(); - - UpdateCustomTargetAssemblies(); - } - - public void SetAllPackageAssemblies(PackageAssembly[] packageAssemblies) - { - m_PackageAssemblies = packageAssemblies; - this.packageCustomScriptAssemblies = m_PackageAssemblies.Select(CreatePackageCustomScriptAssembly).ToArray(); - UpdateCustomTargetAssemblies(); - } - - private static CustomScriptAssembly CreatePackageCustomScriptAssembly(PackageAssembly packageAssembly) - { - var customScriptAssembly = CustomScriptAssembly.Create(packageAssembly.Name, AssetPath.ReplaceSeparators(packageAssembly.DirectoryPath)); - customScriptAssembly.PackageAssembly = packageAssembly; - return customScriptAssembly; - } - - // Delete all .dll's that aren't used anymore - public void DeleteUnusedAssemblies() - { - string fullEditorAssemblyPath = AssetPath.Combine(projectDirectory, GetCompileScriptsOutputDirectory()); - - if (!Directory.Exists(fullEditorAssemblyPath)) - return; - - var deleteFiles = Directory.GetFiles(fullEditorAssemblyPath).Select(f => AssetPath.ReplaceSeparators(f)).ToList(); - string timestampPath = GetAssemblyTimestampPath(GetCompileScriptsOutputDirectory()); - deleteFiles.Remove(AssetPath.Combine(projectDirectory, timestampPath)); - - var scriptAssemblies = GetAllScriptAssemblies(EditorScriptCompilationOptions.BuildingForEditor); - - foreach (var assembly in scriptAssemblies) - { - if (assembly.Files.Length > 0) - { - string path = AssetPath.Combine(fullEditorAssemblyPath, assembly.Filename); - deleteFiles.Remove(path); - deleteFiles.Remove(MDBPath(path)); - deleteFiles.Remove(PDBPath(path)); - } - } - - foreach (var path in deleteFiles) - DeleteFile(path); - } - - public void CleanScriptAssemblies() - { - string fullEditorAssemblyPath = AssetPath.Combine(projectDirectory, GetCompileScriptsOutputDirectory()); - - if (!Directory.Exists(fullEditorAssemblyPath)) - return; - - foreach (var path in Directory.GetFiles(fullEditorAssemblyPath)) - DeleteFile(path); - } - - static void DeleteFile(string path, DeleteFileOptions fileOptions = DeleteFileOptions.LogError) - { - try - { - File.Delete(path); - } - catch (Exception) - { - if (fileOptions == DeleteFileOptions.LogError) - UnityEngine.Debug.LogErrorFormat("Could not delete file '{0}'\n", path); - } - } - - static bool MoveOrReplaceFile(string sourcePath, string destinationPath) - { - bool fileMoved = true; - try - { - File.Move(sourcePath, destinationPath); - } - catch (IOException) - { - fileMoved = false; - } - if (!fileMoved) - { - fileMoved = true; - var backupFile = destinationPath + ".bak"; - DeleteFile(backupFile, DeleteFileOptions.NoLogError); // Delete any previous backup files. - - try - { - File.Replace(sourcePath, destinationPath, backupFile, true); - } - catch (IOException) - { - fileMoved = false; - } - - // Try to delete backup file. Does not need to exist - // We will eventually delete the file in DeleteUnusedAssemblies. - DeleteFile(backupFile, DeleteFileOptions.NoLogError); - } - return fileMoved; - } - - static string PDBPath(string dllPath) - { - return dllPath.Replace(".dll", ".pdb"); - } - - static string MDBPath(string dllPath) - { - return dllPath + ".mdb"; - } - - static bool CopyAssembly(string sourcePath, string destinationPath) - { - if (!MoveOrReplaceFile(sourcePath, destinationPath)) - return false; - - string sourceMdb = MDBPath(sourcePath); - string destinationMdb = MDBPath(destinationPath); - - if (File.Exists(sourceMdb)) - MoveOrReplaceFile(sourceMdb, destinationMdb); - else if (File.Exists(destinationMdb)) - DeleteFile(destinationMdb); - - string sourcePdb = PDBPath(sourcePath); - string destinationPdb = PDBPath(destinationPath); - - if (File.Exists(sourcePdb)) - MoveOrReplaceFile(sourcePdb, destinationPdb); - else if (File.Exists(destinationPdb)) - DeleteFile(destinationPdb); - - return true; - } - - public CustomScriptAssembly FindCustomScriptAssemblyFromAssemblyName(string assemblyName) - { - List allCustomScriptAssemblies = new List(); - - if (customScriptAssemblies != null) - allCustomScriptAssemblies.AddRange(customScriptAssemblies); - - if (packageCustomScriptAssemblies != null) - allCustomScriptAssemblies.AddRange(packageCustomScriptAssemblies); - - var customScriptAssembly = allCustomScriptAssemblies.Single(a => AssemblyNameWithSuffix(a.Name) == AssetPath.GetAssemblyNameWithoutExtension(assemblyName)); - return customScriptAssembly; - } - - internal CustomScriptAssembly FindCustomScriptAssemblyFromScriptPath(string scriptPath) - { - var customTargetAssembly = EditorBuildRules.GetCustomTargetAssembly(scriptPath, projectDirectory, customTargetAssemblies); - var customScriptAssembly = customTargetAssembly != null ? FindCustomScriptAssemblyFromAssemblyName(customTargetAssembly.Filename) : null; - - return customScriptAssembly; - } - - internal CustomScriptAssembly FindCustomTargetAssemblyFromTargetAssembly(EditorBuildRules.TargetAssembly assembly) - { - var assemblyName = AssetPath.GetAssemblyNameWithoutExtension(assembly.Filename); - return FindCustomScriptAssemblyFromAssemblyName(assemblyName); - } - - public bool CompileScripts(EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) - { - var scriptAssemblySettings = CreateScriptAssemblySettings(platformGroup, platform, options); - - EditorBuildRules.TargetAssembly[] notCompiledTargetAssemblies = null; - bool result = CompileScripts(scriptAssemblySettings, EditorTempPath, options, ref notCompiledTargetAssemblies); - - if (notCompiledTargetAssemblies != null) - foreach (var targetAssembly in notCompiledTargetAssemblies) - { - var customScriptAssembly = customScriptAssemblies.Single(a => a.Name == AssetPath.GetAssemblyNameWithoutExtension(targetAssembly.Filename)); - - var filePath = customScriptAssembly.FilePath; - - if (filePath.StartsWith(projectDirectory)) - filePath = filePath.Substring(projectDirectory.Length); - - UnityEngine.Debug.LogWarning(string.Format("Script assembly '{0}' has not been compiled. Folder containing assembly definition file '{1}' contains script files for different script languages. Folder must only contain script files for one script language.", targetAssembly.Filename, filePath)); - } - - return result; - } - - private static EditorBuildRules.TargetAssembly[] GetCustomAssembliesNotContainingTests(EditorBuildRules.TargetAssembly[] targetAssemblies) - { - return (targetAssemblies ?? Enumerable.Empty()).Where(x => (x.OptionalUnityReferences & OptionalUnityReferences.TestAssemblies) != OptionalUnityReferences.TestAssemblies).ToArray(); - } - - internal bool CompileScripts(ScriptAssemblySettings scriptAssemblySettings, string tempBuildDirectory, EditorScriptCompilationOptions options, ref EditorBuildRules.TargetAssembly[] notCompiledTargetAssemblies) - { - DeleteUnusedAssemblies(); - - IEnumerable allDirtyScripts = areAllScriptsDirty ? allScripts.ToArray() : dirtyScripts.ToArray(); - - areAllScriptsDirty = false; - dirtyScripts.Clear(); - - if (!allDirtyScripts.Any() && runScriptUpdaterAssemblies.Count == 0) - return false; - - var assemblies = new EditorBuildRules.CompilationAssemblies - { - UnityAssemblies = unityAssemblies, - PrecompiledAssemblies = precompiledAssemblies, - CustomTargetAssemblies = customTargetAssemblies, - PredefinedAssembliesCustomTargetReferences = GetCustomAssembliesNotContainingTests(customTargetAssemblies), - EditorAssemblyReferences = ModuleUtils.GetAdditionalReferencesForUserScripts() - }; - - var args = new EditorBuildRules.GenerateChangedScriptAssembliesArgs - { - AllSourceFiles = allScripts, - DirtySourceFiles = allDirtyScripts, - ProjectDirectory = projectDirectory, - Settings = scriptAssemblySettings, - Assemblies = assemblies, - RunUpdaterAssemblies = runScriptUpdaterAssemblies - }; - - var scriptAssemblies = EditorBuildRules.GenerateChangedScriptAssemblies(args); - - notCompiledTargetAssemblies = args.NotCompiledTargetAssemblies.ToArray(); - - if (!scriptAssemblies.Any()) - return false; - - return CompileScriptAssemblies(scriptAssemblies, scriptAssemblySettings, tempBuildDirectory, options, CompilationTaskOptions.StopOnFirstError); - } - - internal bool CompileCustomScriptAssemblies(EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) - { - var scriptAssemblySettings = CreateScriptAssemblySettings(platformGroup, platform, options); - return CompileCustomScriptAssemblies(scriptAssemblySettings, EditorTempPath, options, platformGroup, platform); - } - - internal bool CompileCustomScriptAssemblies(ScriptAssemblySettings scriptAssemblySettings, string tempBuildDirectory, EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) - { - var scriptAssemblies = GetAllScriptAssembliesOfType(scriptAssemblySettings, EditorBuildRules.TargetAssemblyType.Custom); - return CompileScriptAssemblies(scriptAssemblies, scriptAssemblySettings, tempBuildDirectory, options, CompilationTaskOptions.None); - } - - internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, ScriptAssemblySettings scriptAssemblySettings, string tempBuildDirectory, EditorScriptCompilationOptions options, CompilationTaskOptions compilationTaskOptions) - { - StopAllCompilation(); - - // Do no start compilation if there is an setup error. - if (setupErrorFlags != CompilationSetupErrorFlags.none) - return false; - - CheckCyclicAssemblyReferences(); - - DeleteUnusedAssemblies(); - - if (!Directory.Exists(scriptAssemblySettings.OutputDirectory)) - Directory.CreateDirectory(scriptAssemblySettings.OutputDirectory); - - if (!Directory.Exists(tempBuildDirectory)) - Directory.CreateDirectory(tempBuildDirectory); - - // Compile to tempBuildDirectory - compilationTask = new CompilationTask(scriptAssemblies, tempBuildDirectory, options, compilationTaskOptions, UnityEngine.SystemInfo.processorCount); - - compilationTask.OnCompilationStarted += (assembly, phase) => - { - var assemblyOutputPath = AssetPath.Combine(scriptAssemblySettings.OutputDirectory, assembly.Filename); - Console.WriteLine("- Starting compile {0}", assemblyOutputPath); - InvokeAssemblyCompilationStarted(assemblyOutputPath); - }; - - compilationTask.OnCompilationFinished += (assembly, messages) => - { - var assemblyOutputPath = AssetPath.Combine(scriptAssemblySettings.OutputDirectory, assembly.Filename); - Console.WriteLine("- Finished compile {0}", assemblyOutputPath); - - if (runScriptUpdaterAssemblies.Contains(assembly.Filename)) - runScriptUpdaterAssemblies.Remove(assembly.Filename); - - if (messages.Any(m => m.type == CompilerMessageType.Error)) - { - AddUnitySpecificErrorMessages(assembly, messages); - - InvokeAssemblyCompilationFinished(assemblyOutputPath, messages); - return; - } - - var buildingForEditor = scriptAssemblySettings.BuildingForEditor; - string enginePath = InternalEditorUtility.GetEngineCoreModuleAssemblyPath(); - - string unetPath = UnityEditor.EditorApplication.applicationContentsPath + "/UnityExtensions/Unity/Networking/UnityEngine.Networking.dll"; - if (!Serialization.Weaver.WeaveUnetFromEditor(assembly, tempBuildDirectory, tempBuildDirectory, enginePath, unetPath, buildingForEditor)) - { - messages.Add(new CompilerMessage { message = "UNet Weaver failed", type = CompilerMessageType.Error, file = assembly.FullPath, line = -1, column = -1 }); - StopAllCompilation(); - InvokeAssemblyCompilationFinished(assemblyOutputPath, messages); - return; - } - - // Copy from tempBuildDirectory to assembly output directory - if (!CopyAssembly(AssetPath.Combine(tempBuildDirectory, assembly.Filename), assembly.FullPath)) - { - messages.Add(new CompilerMessage { message = string.Format("Copying assembly from directory {0} to {1} failed", tempBuildDirectory, assembly.OutputDirectory), type = CompilerMessageType.Error, file = assembly.FullPath, line = -1, column = -1 }); - StopCompilationTask(); - InvokeAssemblyCompilationFinished(assemblyOutputPath, messages); - return; - } - - InvokeAssemblyCompilationFinished(assemblyOutputPath, messages); - }; - - compilationTask.Poll(); - return true; - } - - void AddUnitySpecificErrorMessages(ScriptAssembly assembly, List messages) - { - // error CS0227: Unsafe code requires the `unsafe' command line option to be specified - if (!messages.Any(m => m.type == CompilerMessageType.Error && m.message.Contains("CS0227"))) - return; - - var assemblyName = AssetPath.GetAssemblyNameWithoutExtension(assembly.Filename); - - string unityUnsafeMessage; - - try - { - var customScriptAssembly = FindCustomScriptAssemblyFromAssemblyName(assemblyName); - unityUnsafeMessage = string.Format("Enable \"Allow 'unsafe' code\" in the inspector for '{0}' to fix this error.", customScriptAssembly.FilePath); - } - catch - { - unityUnsafeMessage = "Enable \"Allow 'unsafe' code\" in Player Settings to fix this error."; - } - - List newMessages = new List(); - - foreach (var message in messages) - { - if (message.type == CompilerMessageType.Error && message.message.Contains("CS0227")) - { - var newMessage = new CompilerMessage(message); - newMessage.message += ". " + unityUnsafeMessage; - newMessages.Add(newMessage); - } - else - { - newMessages.Add(message); - } - } - - messages.Clear(); - messages.AddRange(newMessages); - } - - public void InvokeAssemblyCompilationStarted(string assemblyOutputPath) - { - if (assemblyCompilationStarted != null) - assemblyCompilationStarted(assemblyOutputPath); - } - - public void InvokeAssemblyCompilationFinished(string assemblyOutputPath, List messages) - { - if (assemblyCompilationFinished != null) - { - var convertedMessages = ConvertCompilerMessages(messages); - assemblyCompilationFinished(assemblyOutputPath, convertedMessages); - } - } - - public bool AreAllScriptsDirty() - { - return areAllScriptsDirty; - } - - public bool DoesProjectFolderHaveAnyDirtyScripts() - { - return (areAllScriptsDirty && allScripts.Count > 0) || dirtyScripts.Count > 0; - } - - public bool DoesProjectFolderHaveAnyScripts() - { - return allScripts != null && allScripts.Count > 0; - } - - ScriptAssemblySettings CreateScriptAssemblySettings(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, EditorScriptCompilationOptions options) - { - var defines = InternalEditorUtility.GetCompilationDefines(options, buildTargetGroup, buildTarget); - - var predefinedAssembliesCompilerOptions = new ScriptCompilerOptions(); - - if ((options & EditorScriptCompilationOptions.BuildingPredefinedAssembliesAllowUnsafeCode) == EditorScriptCompilationOptions.BuildingPredefinedAssembliesAllowUnsafeCode) - predefinedAssembliesCompilerOptions.AllowUnsafeCode = true; - - var settings = new ScriptAssemblySettings - { - BuildTarget = buildTarget, - BuildTargetGroup = buildTargetGroup, - OutputDirectory = GetCompileScriptsOutputDirectory(), - Defines = defines, - ApiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup), - CompilationOptions = options, - PredefinedAssembliesCompilerOptions = predefinedAssembliesCompilerOptions, - FilenameSuffix = assemblySuffix, - OptionalUnityReferences = ToOptionalUnityReferences(options), - }; - - return settings; - } - - ScriptAssemblySettings CreateEditorScriptAssemblySettings(EditorScriptCompilationOptions options) - { - return CreateScriptAssemblySettings(EditorUserBuildSettings.activeBuildTargetGroup, EditorUserBuildSettings.activeBuildTarget, options); - } - - public AssemblyCompilerMessages[] GetCompileMessages() - { - if (compilationTask == null) - return null; - - var result = new AssemblyCompilerMessages[compilationTask.CompilerMessages.Count]; - - int index = 0; - foreach (var entry in compilationTask.CompilerMessages) - { - var assembly = entry.Key; - var messages = entry.Value; - - result[index++] = new AssemblyCompilerMessages { assemblyFilename = assembly.Filename, messages = messages }; - } - - // Sort compiler messages by assemby filename to make the order deterministic. - Array.Sort(result, (m1, m2) => String.Compare(m1.assemblyFilename, m2.assemblyFilename)); - - return result; - } - - public bool IsCompilationPending() - { - // If there were any errors in setting up the compilation, then return false. - if (setupErrorFlags != CompilationSetupErrorFlags.none) - return false; - - // If we have dirty scripts or script updater has marked assemblies for updated, - // then compilation will trigger on next TickCompilationPipeline. - return DoesProjectFolderHaveAnyDirtyScripts() || runScriptUpdaterAssemblies.Count() > 0; - } - - public bool IsAnyAssemblyBuilderCompiling() - { - if (assemblyBuilders.Count > 0) - { - bool isCompiling = false; - - var removeAssemblyBuilders = new List(); - - // Check status of compile tasks - foreach (var assemblyBuilder in assemblyBuilders) - { - var status = assemblyBuilder.status; - - if (status == Compilation.AssemblyBuilderStatus.IsCompiling) - isCompiling = true; - else if (status == Compilation.AssemblyBuilderStatus.Finished) - removeAssemblyBuilders.Add(assemblyBuilder); - } - - // Remove all compile tasks that finished compiling. - if (removeAssemblyBuilders.Count > 0) - assemblyBuilders.RemoveAll(t => removeAssemblyBuilders.Contains(t)); - - return isCompiling; - } - - return false; - } - - public bool IsCompiling() - { - // Native code expects IsCompiling to be true after marking scripts as dirty, - // therefore return true if the compilation is pending - return IsCompilationTaskCompiling() || IsCompilationPending() || IsAnyAssemblyBuilderCompiling(); - } - - public bool IsCompilationTaskCompiling() - { - return compilationTask != null && compilationTask.IsCompiling; - } - - public void StopAllCompilation() - { - StopCompilationTask(); - compilationTask = null; - } - - public void StopCompilationTask() - { - if (compilationTask == null) - return; - - compilationTask.Stop(); - } - - internal static OptionalUnityReferences ToOptionalUnityReferences(EditorScriptCompilationOptions editorScriptCompilationOptions) - { - var optinalUnityReferences = OptionalUnityReferences.None; - - var buildingIncludingTestAssemblies = (editorScriptCompilationOptions & EditorScriptCompilationOptions.BuildingIncludingTestAssemblies) == EditorScriptCompilationOptions.BuildingIncludingTestAssemblies; - if (buildingIncludingTestAssemblies) - { - optinalUnityReferences |= OptionalUnityReferences.TestAssemblies; - } - return optinalUnityReferences; - } - - public CompileStatus TickCompilationPipeline(EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) - { - // Return CompileStatus.Compiling if any compile task is still compiling. - // This ensures that the compile tasks finish compiling before any - // scripts in the Assets folder are compiled and a domain reload - // is triggered. - if (IsAnyAssemblyBuilderCompiling()) - return CompileStatus.Compiling; - - // If we are not currently compiling and there are dirty scripts, start compilation. - if (!IsCompilationTaskCompiling() && IsCompilationPending()) - { - if (CompileScripts(options, platformGroup, platform)) - return CompileStatus.CompilationStarted; - } - - return PollCompilation(); - } - - public CompileStatus PollCompilation() - { - if (IsCompilationTaskCompiling()) - { - if (compilationTask.Poll()) // Returns true when compilation finished. - return (compilationTask == null || compilationTask.CompileErrors) ? CompileStatus.CompilationFailed : CompileStatus.CompilationComplete; - - return CompileStatus.Compiling; - } - - return CompileStatus.Idle; - } - - string AssemblyFilenameWithSuffix(string assemblyFilename) - { - if (!string.IsNullOrEmpty(assemblySuffix)) - { - var basename = AssetPath.GetAssemblyNameWithoutExtension(assemblyFilename); - return string.Concat(basename, assemblySuffix, ".dll"); - } - - return assemblyFilename; - } - - string AssemblyNameWithSuffix(string assemblyName) - { - if (!string.IsNullOrEmpty(assemblySuffix)) - { - var basename = AssetPath.GetAssemblyNameWithoutExtension(assemblyName); - return string.Concat(basename, assemblySuffix); - } - - return assemblyName; - } - - public TargetAssemblyInfo[] GetTargetAssemblies() - { - EditorBuildRules.TargetAssembly[] predefindTargetAssemblies = EditorBuildRules.GetPredefinedTargetAssemblies(); - - TargetAssemblyInfo[] targetAssemblyInfo = new TargetAssemblyInfo[predefindTargetAssemblies.Length + (customTargetAssemblies != null ? customTargetAssemblies.Count() : 0)]; - - for (int i = 0; i < predefindTargetAssemblies.Length; ++i) - targetAssemblyInfo[i] = ToTargetAssemblyInfo(predefindTargetAssemblies[i]); - - if (customTargetAssemblies != null) - for (int i = 0; i < customTargetAssemblies.Count(); ++i) - { - int j = predefindTargetAssemblies.Length + i; - targetAssemblyInfo[j] = ToTargetAssemblyInfo(customTargetAssemblies[i]); - } - - return targetAssemblyInfo; - } - - public ScriptAssembly[] GetAllScriptAssembliesForLanguage(EditorScriptCompilationOptions additionalOptions) where T : SupportedLanguage - { - var assemblies = GetAllScriptAssemblies(EditorScriptCompilationOptions.BuildingForEditor).Where(a => a.Language.GetType() == typeof(T)).ToArray(); - return assemblies; - } - - public ScriptAssembly GetScriptAssemblyForLanguage(string assemblyNameOrPath, EditorScriptCompilationOptions additionalOptions) where T : SupportedLanguage - { - var assemblyName = AssetPath.GetAssemblyNameWithoutExtension(assemblyNameOrPath); - var scriptAssemblies = GetAllScriptAssembliesForLanguage(additionalOptions); - return scriptAssemblies.SingleOrDefault(a => String.Compare(assemblyName, AssetPath.GetAssemblyNameWithoutExtension(a.Filename), StringComparison.OrdinalIgnoreCase) == 0); - } - - public EditorBuildRules.TargetAssembly[] GetCustomTargetAssemblies() - { - return customTargetAssemblies; - } - - public PrecompiledAssembly[] GetUnityAssemblies() - { - return unityAssemblies; - } - - public TargetAssemblyInfo GetTargetAssembly(string scriptPath) - { - EditorBuildRules.TargetAssembly targetAssembly = EditorBuildRules.GetTargetAssembly(scriptPath, projectDirectory, customTargetAssemblies); - TargetAssemblyInfo targetAssemblyInfo = ToTargetAssemblyInfo(targetAssembly); - return targetAssemblyInfo; - } - - public EditorBuildRules.TargetAssembly GetTargetAssemblyDetails(string scriptPath) - { - return EditorBuildRules.GetTargetAssembly(scriptPath, projectDirectory, customTargetAssemblies); - } - - public ScriptAssembly[] GetAllEditorScriptAssemblies(EditorScriptCompilationOptions additionalOptions) - { - return GetAllScriptAssemblies(EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies | additionalOptions); - } - - ScriptAssembly[] GetAllScriptAssemblies(EditorScriptCompilationOptions options) - { - return GetAllScriptAssemblies(options, unityAssemblies, precompiledAssemblies); - } - - ScriptAssembly[] GetAllScriptAssemblies(EditorScriptCompilationOptions options, PrecompiledAssembly[] unityAssembliesArg, PrecompiledAssembly[] precompiledAssembliesArg) - { - ScriptAssemblySettings settings = CreateEditorScriptAssemblySettings(options); - - var assemblies = new EditorBuildRules.CompilationAssemblies - { - UnityAssemblies = unityAssembliesArg, - PrecompiledAssemblies = precompiledAssembliesArg, - CustomTargetAssemblies = customTargetAssemblies, - PredefinedAssembliesCustomTargetReferences = GetCustomAssembliesNotContainingTests(customTargetAssemblies), - EditorAssemblyReferences = ModuleUtils.GetAdditionalReferencesForUserScripts() - }; - - return EditorBuildRules.GetAllScriptAssemblies(allScripts, projectDirectory, settings, assemblies); - } - - ScriptAssembly[] GetAllScriptAssembliesOfType(ScriptAssemblySettings settings, EditorBuildRules.TargetAssemblyType type) - { - var assemblies = new EditorBuildRules.CompilationAssemblies - { - UnityAssemblies = unityAssemblies, - PrecompiledAssemblies = precompiledAssemblies, - CustomTargetAssemblies = customTargetAssemblies, - PredefinedAssembliesCustomTargetReferences = GetCustomAssembliesNotContainingTests(customTargetAssemblies), - EditorAssemblyReferences = ModuleUtils.GetAdditionalReferencesForUserScripts() - }; - - return EditorBuildRules.GetAllScriptAssemblies(allScripts, projectDirectory, settings, assemblies, type); - } - - public MonoIsland[] GetAllMonoIslands(EditorScriptCompilationOptions additionalOptions) - { - return GetAllMonoIslands(unityAssemblies, precompiledAssemblies, EditorScriptCompilationOptions.BuildingForEditor | EditorScriptCompilationOptions.BuildingIncludingTestAssemblies | additionalOptions); - } - - public MonoIsland[] GetAllMonoIslands(PrecompiledAssembly[] unityAssembliesArg, PrecompiledAssembly[] precompiledAssembliesArg, EditorScriptCompilationOptions options) - { - var scriptAssemblies = GetAllScriptAssemblies(options, unityAssembliesArg, precompiledAssembliesArg); - var monoIslands = new MonoIsland[scriptAssemblies.Length]; - - for (int i = 0; i < scriptAssemblies.Length; ++i) - monoIslands[i] = scriptAssemblies[i].ToMonoIsland(EditorScriptCompilationOptions.BuildingForEditor, EditorTempPath); - - return monoIslands; - } - - public bool IsRuntimeScriptAssembly(string assemblyNameOrPath) - { - var assemblyFilename = AssetPath.GetFileName(assemblyNameOrPath); - - if (!assemblyFilename.EndsWith(".dll")) - assemblyFilename += ".dll"; - - var predefinedAssemblyTargets = EditorBuildRules.GetPredefinedTargetAssemblies(); - - if (predefinedAssemblyTargets.Any(a => ((a.Flags & AssemblyFlags.EditorOnly) != AssemblyFlags.EditorOnly) && a.Filename == assemblyFilename)) - return true; - - if (customTargetAssemblies != null && customTargetAssemblies.Any(a => ((a.Flags & AssemblyFlags.EditorOnly) != AssemblyFlags.EditorOnly) && a.Filename == assemblyFilename)) - return true; - - return false; - } - - TargetAssemblyInfo ToTargetAssemblyInfo(EditorBuildRules.TargetAssembly targetAssembly) - { - TargetAssemblyInfo targetAssemblyInfo = new TargetAssemblyInfo(); - - targetAssemblyInfo.Name = AssemblyFilenameWithSuffix(targetAssembly.Filename); - targetAssemblyInfo.Flags = targetAssembly.Flags; - - return targetAssemblyInfo; - } - - public ScriptAssembly CreateScriptAssembly(Compilation.AssemblyBuilder assemblyBuilder) - { - EditorScriptCompilationOptions options = EditorScriptCompilationOptions.BuildingEmpty; - AssemblyFlags assemblyFlags = AssemblyFlags.None; - - bool buildingForEditor = false; - - if ((assemblyBuilder.flags & Compilation.AssemblyBuilderFlags.DevelopmentBuild) == Compilation.AssemblyBuilderFlags.DevelopmentBuild) - options |= EditorScriptCompilationOptions.BuildingDevelopmentBuild; - - if ((assemblyBuilder.flags & Compilation.AssemblyBuilderFlags.EditorAssembly) == Compilation.AssemblyBuilderFlags.EditorAssembly) - { - options |= EditorScriptCompilationOptions.BuildingForEditor; - assemblyFlags |= AssemblyFlags.EditorOnly; - buildingForEditor = true; - } - - var scriptFiles = assemblyBuilder.scriptPaths.Select(p => AssetPath.Combine(projectDirectory, p)).ToArray(); - var assemblyPath = AssetPath.Combine(projectDirectory, assemblyBuilder.assemblyPath); - var defines = InternalEditorUtility.GetCompilationDefines(options, assemblyBuilder.buildTargetGroup, assemblyBuilder.buildTarget); - - if (assemblyBuilder.additionalDefines != null) - defines = defines.Concat(assemblyBuilder.additionalDefines).ToArray(); - - var scriptAssembly = new ScriptAssembly(); - scriptAssembly.Flags = assemblyFlags; - scriptAssembly.BuildTarget = assemblyBuilder.buildTarget; - scriptAssembly.ApiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(assemblyBuilder.buildTargetGroup); - scriptAssembly.Language = ScriptCompilers.GetLanguageFromExtension(ScriptCompilers.GetExtensionOfSourceFile(assemblyBuilder.scriptPaths[0])); - scriptAssembly.Files = scriptFiles; - scriptAssembly.Filename = AssetPath.GetFileName(assemblyPath); - scriptAssembly.OutputDirectory = AssetPath.GetDirectoryName(assemblyPath); - scriptAssembly.Defines = defines; - scriptAssembly.CompilerOptions = assemblyBuilder.compilerOptions; - scriptAssembly.ScriptAssemblyReferences = new ScriptAssembly[0]; - - var unityReferences = EditorBuildRules.GetUnityReferences(scriptAssembly, unityAssemblies, options); - var customReferences = EditorBuildRules.GetCompiledCustomAssembliesReferences(scriptAssembly, customTargetAssemblies, GetCompileScriptsOutputDirectory(), assemblySuffix); - var precompiledReferences = EditorBuildRules.GetPrecompiledReferences(scriptAssembly, EditorBuildRules.TargetAssemblyType.Custom, options, EditorBuildRules.EditorCompatibility.CompatibleWithEditor, precompiledAssemblies); - var additionalReferences = MonoLibraryHelpers.GetSystemLibraryReferences(scriptAssembly.ApiCompatibilityLevel, scriptAssembly.BuildTarget, scriptAssembly.Language, buildingForEditor, scriptAssembly.Filename); - string[] editorReferences = buildingForEditor ? ModuleUtils.GetAdditionalReferencesForUserScripts() : new string[0]; - - var references = unityReferences.Concat(customReferences).Concat(precompiledReferences).Concat(editorReferences).Concat(additionalReferences); - - if (assemblyBuilder.additionalReferences != null && assemblyBuilder.additionalReferences.Length > 0) - references = references.Concat(assemblyBuilder.additionalReferences); - - if (assemblyBuilder.excludeReferences != null && assemblyBuilder.excludeReferences.Length > 0) - references = references.Where(r => !assemblyBuilder.excludeReferences.Contains(r)); - - scriptAssembly.References = references.ToArray(); - - return scriptAssembly; - } - - public void AddAssemblyBuilder(UnityEditor.Compilation.AssemblyBuilder assemblyBuilder) - { - assemblyBuilders.Add(assemblyBuilder); - } - - public static UnityEditor.Compilation.CompilerMessage[] ConvertCompilerMessages(List messages) - { - var newMessages = new UnityEditor.Compilation.CompilerMessage[messages.Count]; - - int index = 0; - foreach (var message in messages) - { - var newMessage = new UnityEditor.Compilation.CompilerMessage(); - - newMessage.message = message.message; - newMessage.file = message.file; - newMessage.line = message.line; - newMessage.column = message.column; - - switch (message.type) - { - case CompilerMessageType.Error: - newMessage.type = UnityEditor.Compilation.CompilerMessageType.Error; - break; - - case CompilerMessageType.Warning: - newMessage.type = UnityEditor.Compilation.CompilerMessageType.Warning; - break; - } - - newMessages[index++] = newMessage; - } - - return newMessages; - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs deleted file mode 100644 index 3f03773bc3..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs +++ /dev/null @@ -1,305 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; -using System; -using UnityEditor.Compilation; -using UnityEditor.Scripting.Compilers; -using UnityEditorInternal; -using System.Collections.Generic; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - static class EditorCompilationInterface - { - static EditorCompilation editorCompilation; - - public static EditorCompilation Instance - { - get - { - if (editorCompilation == null) - { - editorCompilation = new EditorCompilation(); - editorCompilation.setupErrorFlagsChanged += ClearErrors; - - // Clear the errors after creating editorCompilation, - // as it is accessed in the CompilationPipeline cctor. - CompilationPipeline.ClearEditorCompilationErrors(); // Clear all errors on domain reload. - } - - return editorCompilation; - } - } - - static void ClearErrors(EditorCompilation.CompilationSetupErrorFlags flags) - { - if (flags == EditorCompilation.CompilationSetupErrorFlags.none) - CompilationPipeline.ClearEditorCompilationErrors(); - } - - static void LogException(Exception exception) - { - var assemblyDefinitionException = exception as AssemblyDefinitionException; - - if (assemblyDefinitionException != null && assemblyDefinitionException.filePaths.Length > 0) - { - foreach (var filePath in assemblyDefinitionException.filePaths) - { - var message = string.Format("{0} ({1})", exception.Message, filePath); - - var asset = AssetDatabase.LoadAssetAtPath(filePath); - var instanceID = asset.GetInstanceID(); - - CompilationPipeline.LogEditorCompilationError(message, instanceID); - } - } - else - { - UnityEngine.Debug.LogException(exception); - } - } - - static void EmitExceptionAsError(Action action) - { - try - { - action(); - } - catch (Exception e) - { - LogException(e); - } - } - - static T EmitExceptionAsError(Func func, T returnValue) - { - try - { - return func(); - } - catch (Exception e) - { - LogException(e); - return returnValue; - } - } - - [RequiredByNativeCode] - public static void SetAssemblySuffix(string suffix) - { - Instance.SetAssemblySuffix(suffix); - } - - [RequiredByNativeCode] - public static void SetAllScripts(string[] allScripts) - { - Instance.SetAllScripts(allScripts); - } - - [RequiredByNativeCode] - public static bool IsExtensionSupportedByCompiler(string extension) - { - return Instance.IsExtensionSupportedByCompiler(extension); - } - - [RequiredByNativeCode] - public static string[] GetExtensionsSupportedByCompiler() - { - return Instance.GetExtensionsSupportedByCompiler(); - } - - [RequiredByNativeCode] - public static void DirtyPredefinedAssemblyScripts(EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) - { - EmitExceptionAsError(() => Instance.DirtyPredefinedAssemblyScripts(options, platformGroup, platform)); - } - - [RequiredByNativeCode] - public static void DirtyAllScripts() - { - Instance.DirtyAllScripts(); - } - - [RequiredByNativeCode] - public static void DirtyScript(string path) - { - Instance.DirtyScript(path); - } - - [RequiredByNativeCode] - public static void ClearDirtyScripts() - { - Instance.ClearDirtyScripts(); - } - - [RequiredByNativeCode] - public static void RunScriptUpdaterOnAssembly(string assemblyFilename) - { - Instance.RunScriptUpdaterOnAssembly(assemblyFilename); - } - - [RequiredByNativeCode] - public static void SetAllPrecompiledAssemblies(PrecompiledAssembly[] precompiledAssemblies) - { - Instance.SetAllPrecompiledAssemblies(precompiledAssemblies); - } - - [RequiredByNativeCode] - public static void SetAllUnityAssemblies(PrecompiledAssembly[] unityAssemblies) - { - Instance.SetAllUnityAssemblies(unityAssemblies); - } - - [RequiredByNativeCode] - public static void SetCompileScriptsOutputDirectory(string directory) - { - Instance.SetCompileScriptsOutputDirectory(directory); - } - - [RequiredByNativeCode] - public static string GetCompileScriptsOutputDirectory() - { - return EmitExceptionAsError(() => Instance.GetCompileScriptsOutputDirectory(), string.Empty); - } - - [RequiredByNativeCode] - public static void SetAllCustomScriptAssemblyJsons(string[] allAssemblyJsons) - { - EmitExceptionAsError(() => Instance.SetAllCustomScriptAssemblyJsons(allAssemblyJsons)); - } - - [RequiredByNativeCode] - public static void SetAllPackageAssemblies(EditorCompilation.PackageAssembly[] packageAssemblies) - { - EmitExceptionAsError(() => Instance.SetAllPackageAssemblies(packageAssemblies)); - } - - [RequiredByNativeCode] - public static EditorCompilation.TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies() - { - return EmitExceptionAsError(() => Instance.GetAllCompiledAndResolvedCustomTargetAssemblies(), new EditorCompilation.TargetAssemblyInfo[0]); - } - - [RequiredByNativeCode] - public static bool HaveSetupErrors() - { - return Instance.HaveSetupErrors(); - } - - [RequiredByNativeCode] - public static void DeleteUnusedAssemblies() - { - EmitExceptionAsError(() => Instance.DeleteUnusedAssemblies()); - } - - [RequiredByNativeCode] - public static bool CompileScripts(EditorScriptCompilationOptions definesOptions, BuildTargetGroup platformGroup, BuildTarget platform) - { - return EmitExceptionAsError(() => Instance.CompileScripts(definesOptions, platformGroup, platform), false); - } - - [RequiredByNativeCode] - public static bool CompileCustomScriptAssemblies(EditorScriptCompilationOptions definesOptions, BuildTargetGroup platformGroup, BuildTarget platform) - { - return EmitExceptionAsError(() => Instance.CompileCustomScriptAssemblies(definesOptions, platformGroup, platform), false); - } - - [RequiredByNativeCode] - public static bool DoesProjectFolderHaveAnyDirtyScripts() - { - return Instance.DoesProjectFolderHaveAnyDirtyScripts(); - } - - [RequiredByNativeCode] - public static bool AreAllScriptsDirty() - { - return Instance.AreAllScriptsDirty(); - } - - [RequiredByNativeCode] - public static bool DoesProjectFolderHaveAnyScripts() - { - return Instance.DoesProjectFolderHaveAnyScripts(); - } - - [RequiredByNativeCode] - public static EditorCompilation.AssemblyCompilerMessages[] GetCompileMessages() - { - return Instance.GetCompileMessages(); - } - - [RequiredByNativeCode] - public static bool IsCompilationPending() - { - return Instance.IsCompilationPending(); - } - - [RequiredByNativeCode] - public static bool IsCompiling() - { - return Instance.IsCompiling(); - } - - [RequiredByNativeCode] - public static void StopAllCompilation() - { - Instance.StopAllCompilation(); - } - - [RequiredByNativeCode] - public static EditorCompilation.CompileStatus TickCompilationPipeline(EditorScriptCompilationOptions options, BuildTargetGroup platformGroup, BuildTarget platform) - { - return EmitExceptionAsError(() => Instance.TickCompilationPipeline(options, platformGroup, platform), EditorCompilation.CompileStatus.Idle); - } - - [RequiredByNativeCode] - public static EditorCompilation.CompileStatus PollCompilation() - { - return EmitExceptionAsError(() => Instance.PollCompilation(), EditorCompilation.CompileStatus.Idle); - } - - [RequiredByNativeCode] - public static EditorCompilation.TargetAssemblyInfo[] GetTargetAssemblies() - { - return Instance.GetTargetAssemblies(); - } - - [RequiredByNativeCode] - public static EditorCompilation.TargetAssemblyInfo GetTargetAssembly(string scriptPath) - { - return Instance.GetTargetAssembly(scriptPath); - } - - [RequiredByNativeCode] - public static MonoIsland[] GetAllMonoIslands() - { - var options = GetAdditionalEditorScriptCompilationOptions(); - return Instance.GetAllMonoIslands(options); - } - - public static EditorScriptCompilationOptions GetAdditionalEditorScriptCompilationOptions() - { - var options = EditorScriptCompilationOptions.BuildingEmpty; - - if (PlayerSettings.allowUnsafeCode) - options |= EditorScriptCompilationOptions.BuildingPredefinedAssembliesAllowUnsafeCode; - - return options; - } - - public static ScriptAssembly[] GetAllScriptAssembliesForLanguage() where T : SupportedLanguage - { - var additionalOptions = GetAdditionalEditorScriptCompilationOptions(); - return Instance.GetAllScriptAssembliesForLanguage(additionalOptions); - } - - public static ScriptAssembly GetScriptAssemblyForLanguage(string assemblyNameOrPath) where T : SupportedLanguage - { - var additionalOptions = GetAdditionalEditorScriptCompilationOptions(); - - return Instance.GetScriptAssemblyForLanguage(assemblyNameOrPath, additionalOptions); - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs deleted file mode 100644 index 54d00b3510..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - // Keep in sync with EditorScriptCompilationOptions in native - [Flags] - enum EditorScriptCompilationOptions - { - BuildingEmpty = 0, - BuildingDevelopmentBuild = 1 << 0, - BuildingForEditor = 1 << 1, - BuildingEditorOnlyAssembly = 1 << 2, - BuildingForIl2Cpp = 1 << 3, - BuildingWithAsserts = 1 << 4, - BuildingIncludingTestAssemblies = 1 << 5, - BuildingPredefinedAssembliesAllowUnsafeCode = (1 << 6) - }; -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs b/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs deleted file mode 100644 index 5613714390..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor.Scripting.Compilers; -using UnityEditor.Utils; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - static class MonoLibraryHelpers - { - class CachedReferences - { - public ApiCompatibilityLevel ApiCompatibilityLevel; - public string[] References; - } - - static CachedReferences cachedReferences; - - public static string[] GetSystemLibraryReferences(ApiCompatibilityLevel apiCompatibilityLevel, BuildTarget buildTarget, SupportedLanguage supportedLanguage, - bool buildingForEditor, string assemblyName) - { - if (WSAHelpers.BuildingForDotNet(buildTarget, buildingForEditor, assemblyName)) - return new string[0]; - - // The language may not be compatible with these additional references - if (supportedLanguage != null && !supportedLanguage.CompilerRequiresAdditionalReferences()) - return new string[0]; - - return GetCachedSystemLibraryReferences(apiCompatibilityLevel); - } - - static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompatibilityLevel) - { - // We cache the references because they are computed by getting files in directories on disk, - // which is very slow. - if (cachedReferences != null && cachedReferences.ApiCompatibilityLevel == apiCompatibilityLevel) - { - return cachedReferences.References; - } - - var references = new List(); - var monoAssemblyDirectory = GetSystemReferenceDirectory(apiCompatibilityLevel); - - if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) - { - references.AddRange(GetNetStandardClassLibraries()); - } - else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) - { - references.AddRange(GetSystemReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); - - // Look in the mono assembly directory for a facade folder and get a list of all the DLL's to be - // used later by the language compilers. - references.AddRange(Directory.GetFiles(Path.Combine(monoAssemblyDirectory, "Facades"), "*.dll")); - - references.AddRange(GetBooAndUsReferences().Select(dll => Path.Combine(MonoInstallationFinder.GetProfileDirectory("unityscript", MonoInstallationFinder.MonoBleedingEdgeInstallation), dll))); - } - else - { - references.AddRange(GetSystemReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); - references.AddRange(GetBooAndUsReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); - } - - cachedReferences = new CachedReferences - { - ApiCompatibilityLevel = apiCompatibilityLevel, - References = references.ToArray() - }; - - - return cachedReferences.References; - } - - public static string GetSystemReferenceDirectory(ApiCompatibilityLevel apiCompatibilityLevel) - { - if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) - return ""; - else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) - return MonoInstallationFinder.GetProfileDirectory("4.7.1-api", MonoInstallationFinder.MonoBleedingEdgeInstallation); - else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_2_0) - return MonoInstallationFinder.GetProfileDirectory("2.0-api", MonoInstallationFinder.MonoBleedingEdgeInstallation); - - return MonoInstallationFinder.GetProfileDirectory(BuildPipeline.CompatibilityProfileToClassLibFolder(apiCompatibilityLevel), MonoInstallationFinder.MonoBleedingEdgeInstallation); - } - - static string[] GetNetStandardClassLibraries() - { - var classLibraries = new List(); - - // Add the .NET Standard 2.0 reference assembly - classLibraries.Add(Path.Combine(NetStandardFinder.GetReferenceDirectory(), "netstandard.dll")); - - // Add the .NET Standard 2.0 compat shims - classLibraries.AddRange(Directory.GetFiles(NetStandardFinder.GetNetStandardCompatShimsDirectory(), "*.dll")); - - // Add the .NET Framework compat shims - classLibraries.AddRange(Directory.GetFiles(NetStandardFinder.GetDotNetFrameworkCompatShimsDirectory(), "*.dll")); - - return classLibraries.ToArray(); - } - - static string[] GetSystemReferences() - { - return new[] - { - "mscorlib.dll", - "System.dll", - "System.Core.dll", - "System.Runtime.Serialization.dll", - "System.Xml.dll", - "System.Xml.Linq.dll", - }; - } - - static string[] GetBooAndUsReferences() - { - return new[] - { - "UnityScript.dll", - "UnityScript.Lang.dll", - "Boo.Lang.dll", - }; - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/OptionalUnityReferences.cs b/Editor/Mono/Scripting/ScriptCompilation/OptionalUnityReferences.cs deleted file mode 100644 index 951ecde961..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/OptionalUnityReferences.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - // Keep in sync with OptionalUnityReferences in C++ - [Flags] - internal enum OptionalUnityReferences - { - None = 0, - TestAssemblies = 1 << 1, - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/PrecompiledAssembly.cs b/Editor/Mono/Scripting/ScriptCompilation/PrecompiledAssembly.cs deleted file mode 100644 index b6db551932..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/PrecompiledAssembly.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Runtime.InteropServices; -using UnityEditor.Compilation; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - [StructLayout(LayoutKind.Sequential)] - struct PrecompiledAssembly - { - public string Path; - public AssemblyFlags Flags; - public OptionalUnityReferences OptionalUnityReferences; - }; -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs b/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs deleted file mode 100644 index f0c2448551..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using UnityEditor.Scripting.Compilers; -using UnityEditor.Compilation; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - // Settings that would be common for a group of ScriptAssembly's created for the same build target. - class ScriptAssemblySettings - { - public BuildTarget BuildTarget { get; set; } - public BuildTargetGroup BuildTargetGroup { get; set; } - public string OutputDirectory { get; set; } - public string[] Defines { get; set; } - public ApiCompatibilityLevel ApiCompatibilityLevel { get; set; } - public EditorScriptCompilationOptions CompilationOptions { get; set; } - public ScriptCompilerOptions PredefinedAssembliesCompilerOptions { get; set; } - - public OptionalUnityReferences OptionalUnityReferences { get; set; } - public string FilenameSuffix { get; set; } - - public ScriptAssemblySettings() - { - BuildTarget = BuildTarget.NoTarget; - BuildTargetGroup = BuildTargetGroup.Unknown; - PredefinedAssembliesCompilerOptions = new ScriptCompilerOptions(); - } - - public bool BuildingForEditor - { - get { return (CompilationOptions & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; } - } - - public bool BuildingDevelopmentBuild - { - get { return (CompilationOptions & EditorScriptCompilationOptions.BuildingDevelopmentBuild) == EditorScriptCompilationOptions.BuildingDevelopmentBuild; } - } - } - - class ScriptAssembly - { - public AssemblyFlags Flags { get; set; } - public BuildTarget BuildTarget { get; set; } - public SupportedLanguage Language { get; set; } - public ApiCompatibilityLevel ApiCompatibilityLevel { get; set; } - public string Filename { get; set; } - public string OutputDirectory { get; set; } - public ScriptAssembly[] ScriptAssemblyReferences { get; set; } // References to dependencies that will be built. - public string[] References { get; set; } // References to dependencies that that will *not* be built. - public string[] AdditionalReferences { get; set; } - public string[] Defines { get; set; } - public string[] Files { get; set; } - public bool RunUpdater { get; set; } - public ScriptCompilerOptions CompilerOptions { get; set; } - - public string FullPath { get { return AssetPath.Combine(OutputDirectory, Filename); } } - - public string[] GetAllReferences() - { - return References.Concat(ScriptAssemblyReferences.Select(a => a.FullPath)).ToArray(); - } - - public MonoIsland ToMonoIsland(EditorScriptCompilationOptions options, string buildOutputDirectory) - { - bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; - bool developmentBuild = (options & EditorScriptCompilationOptions.BuildingDevelopmentBuild) == EditorScriptCompilationOptions.BuildingDevelopmentBuild; - - var references = ScriptAssemblyReferences.Select(a => AssetPath.Combine(a.OutputDirectory, a.Filename)); - - var referencesArray = references.Concat(References).ToArray(); - - var outputPath = AssetPath.Combine(buildOutputDirectory, Filename); - - return new MonoIsland(BuildTarget, - buildingForEditor, - developmentBuild, - CompilerOptions.AllowUnsafeCode, - ApiCompatibilityLevel, - Files, - referencesArray, - Defines, - outputPath); - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs b/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs deleted file mode 100644 index e2d0b0fce5..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Modules; -using UnityEditor.Scripting.Compilers; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - static class WSAHelpers - { - public static bool IsCSharpAssembly(ScriptAssembly scriptAssembly) - { - if (scriptAssembly.Filename.ToLower().Contains("firstpass")) - return false; - - return scriptAssembly.Language == ScriptCompilers.CSharpSupportedLanguage; - } - - public static bool IsCSharpFirstPassAssembly(ScriptAssembly scriptAssembly) - { - if (!scriptAssembly.Filename.ToLower().Contains("firstpass")) - return false; - - return scriptAssembly.Language == ScriptCompilers.CSharpSupportedLanguage; - } - - public static bool UseDotNetCore(ScriptAssembly scriptAssembly) - { - var metroCompilationOverrides = PlayerSettings.WSA.compilationOverrides; - bool dotNetCoreEnabled = scriptAssembly.BuildTarget == BuildTarget.WSAPlayer && metroCompilationOverrides != PlayerSettings.WSACompilationOverrides.None; - bool useDotNetCore = dotNetCoreEnabled && (IsCSharpAssembly(scriptAssembly) || (metroCompilationOverrides != PlayerSettings.WSACompilationOverrides.UseNetCorePartially && IsCSharpFirstPassAssembly(scriptAssembly))); - - return useDotNetCore; - } - - public static bool BuildingForDotNet(BuildTarget buildTarget, bool buildingForEditor, string assemblyName) - { - if (buildTarget != BuildTarget.WSAPlayer) - return false; - - if (CSharpLanguage.GetCSharpCompiler(buildTarget, buildingForEditor, assemblyName) != CSharpCompiler.Microsoft) - return false; - - if (PlayerSettings.GetScriptingBackend(BuildPipeline.GetBuildTargetGroup(buildTarget)) != ScriptingImplementation.WinRTDotNET) - return false; - - return true; - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilers.cs b/Editor/Mono/Scripting/ScriptCompilers.cs deleted file mode 100644 index 37f02f9f16..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilers.cs +++ /dev/null @@ -1,153 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using UnityEditor.Scripting.Compilers; - -namespace UnityEditor.Scripting -{ - internal struct SupportedLanguageStruct - { - public string extension; - public string languageName; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct MonoIsland - { - public readonly BuildTarget _target; - public readonly bool _development_player; - public readonly bool _editor; - public readonly bool _allowUnsafeCode; - public readonly ApiCompatibilityLevel _api_compatibility_level; - public readonly string[] _files; - public readonly string[] _references; - public readonly string[] _defines; - public readonly string _output; - - public MonoIsland(BuildTarget target, ApiCompatibilityLevel api_compatibility_level, bool allowUnsafeCode, string[] files, string[] references, string[] defines, string output) - { - _target = target; - _development_player = false; - _editor = false; - _allowUnsafeCode = allowUnsafeCode; - _api_compatibility_level = api_compatibility_level; - _files = files; - _references = references; - _defines = defines; - _output = output; - } - - public MonoIsland(BuildTarget target, bool editor, bool development_player, bool allowUnsafeCode, ApiCompatibilityLevel api_compatibility_level, string[] files, string[] references, string[] defines, string output) - { - _target = target; - _development_player = development_player; - _editor = editor; - _allowUnsafeCode = allowUnsafeCode; - _api_compatibility_level = api_compatibility_level; - _files = files; - _references = references; - _defines = defines; - _output = output; - } - - public string GetExtensionOfSourceFiles() - { - return _files.Length > 0 ? ScriptCompilers.GetExtensionOfSourceFile(_files[0]) : "NA"; - } - } - - internal static class ScriptCompilers - { - internal static readonly List SupportedLanguages; - internal static readonly SupportedLanguage CSharpSupportedLanguage; - static ScriptCompilers() - { - SupportedLanguages = new List(); - - var types = new List(); - types.Add(typeof(CSharpLanguage)); - types.Add(typeof(BooLanguage)); - types.Add(typeof(UnityScriptLanguage)); - - foreach (var t in types) - { - SupportedLanguages.Add((SupportedLanguage)Activator.CreateInstance(t)); - } - - CSharpSupportedLanguage = SupportedLanguages.Single(l => l.GetType() == typeof(CSharpLanguage)); - } - - internal static SupportedLanguageStruct[] GetSupportedLanguageStructs() - { - //we communicate with the runtime by xforming our SupportedLaanguage class to a struct, because that's - //just a lot easier to marshall between native and managed code. - return SupportedLanguages.Select(lang => new SupportedLanguageStruct - { - extension = lang.GetExtensionICanCompile(), - languageName = lang.GetLanguageName() - }).ToArray(); - } - - internal static string GetNamespace(string file, string definedSymbols) - { - if (string.IsNullOrEmpty(file)) throw new ArgumentException("Invalid file"); - - string extension = GetExtensionOfSourceFile(file); - foreach (var lang in SupportedLanguages) - { - if (lang.GetExtensionICanCompile() == extension) - return lang.GetNamespace(file, definedSymbols); - } - - throw new ApplicationException("Unable to find a suitable compiler"); - } - - internal static SupportedLanguage GetLanguageFromName(string name) - { - foreach (var lang in SupportedLanguages) - { - if (String.Equals(name, lang.GetLanguageName(), StringComparison.OrdinalIgnoreCase)) - return lang; - } - - throw new ApplicationException(string.Format("Script language '{0}' is not supported", name)); - } - - internal static SupportedLanguage GetLanguageFromExtension(string extension) - { - foreach (var lang in SupportedLanguages) - { - if (String.Equals(extension, lang.GetExtensionICanCompile(), StringComparison.OrdinalIgnoreCase)) - return lang; - } - - throw new ApplicationException(string.Format("Script file extension '{0}' is not supported", extension)); - } - - internal static ScriptCompilerBase CreateCompilerInstance(MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) - { - if (island._files.Length == 0) throw new ArgumentException("Cannot compile MonoIsland with no files"); - - foreach (var lang in SupportedLanguages) - { - if (lang.GetExtensionICanCompile() == island.GetExtensionOfSourceFiles()) - return lang.CreateCompiler(island, buildingForEditor, targetPlatform, runUpdater); - } - - throw new ApplicationException(string.Format("Unable to find a suitable compiler for sources with extension '{0}' (Output assembly: {1})", island.GetExtensionOfSourceFiles(), island._output)); - } - - public static string GetExtensionOfSourceFile(string file) - { - var ext = Path.GetExtension(file).ToLower(); - ext = ext.Substring(1); //strip dot - return ext; - } - } -} diff --git a/Editor/Mono/Scripting/ScriptUpdatingManager.bindings.cs b/Editor/Mono/Scripting/ScriptUpdatingManager.bindings.cs deleted file mode 100644 index bc009bf373..0000000000 --- a/Editor/Mono/Scripting/ScriptUpdatingManager.bindings.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditorInternal -{ - //*undocumented* - [NativeHeader("Editor/Src/ScriptUpdatingManager.h")] - [StaticAccessor("ScriptUpdatingManager::GetInstance()", StaticAccessorType.Dot)] - public static class ScriptUpdatingManager - { - public static extern bool WaitForVCSServerConnection(bool reportTimeout); - public static extern void ReportExpectedUpdateFailure(); - public static extern void ReportGroupedAPIUpdaterFailure(string msg); - public static extern int numberOfTimesAsked {[NativeName("NumberOfTimesAsked")] get; } - public static extern void ResetConsentStatus(); - } -} diff --git a/Editor/Mono/Scripting/Serialization/Weaver.cs b/Editor/Mono/Scripting/Serialization/Weaver.cs deleted file mode 100644 index 80176b6584..0000000000 --- a/Editor/Mono/Scripting/Serialization/Weaver.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Linq; -using System.Collections.Generic; -using Mono.Cecil; -using UnityEditor.Modules; -using UnityEngine; -using UnityEditor.Utils; -using UnityEditor.Scripting.ScriptCompilation; - -namespace UnityEditor.Scripting.Serialization -{ - internal static class Weaver - { - private static ManagedProgram SerializationWeaverProgramWith(string arguments, string playerPackage) - { - return ManagedProgramFor(playerPackage + "/SerializationWeaver/SerializationWeaver.exe", arguments); - } - - private static ManagedProgram ManagedProgramFor(string exe, string arguments) - { - return new ManagedProgram(MonoInstallationFinder.GetMonoInstallation("MonoBleedingEdge"), null, exe, arguments, false, null); - } - - private static ICompilationExtension GetCompilationExtension() - { - var target = ModuleManager.GetTargetStringFromBuildTarget(EditorUserBuildSettings.activeBuildTarget); - return ModuleManager.GetCompilationExtension(target); - } - - private static void QueryAssemblyPathsAndResolver(ICompilationExtension compilationExtension, string file, bool editor, out string[] assemblyPaths, out IAssemblyResolver assemblyResolver) - { - assemblyResolver = compilationExtension.GetAssemblyResolver(editor, file, null); - assemblyPaths = compilationExtension.GetCompilerExtraAssemblyPaths(editor, file).ToArray(); - } - - public static bool WeaveUnetFromEditor(ScriptAssembly assembly, string assemblyDirectory, string outputDirectory, string unityEngine, string unityUNet, bool buildingForEditor) - { - if ((assembly.Flags & AssemblyFlags.EditorOnly) == AssemblyFlags.EditorOnly) - return true; - - var assemblyPath = Path.Combine(assemblyDirectory, assembly.Filename); - - ICompilationExtension compilationExtension = GetCompilationExtension(); - IAssemblyResolver assemblyResolver; - string[] assemblyPaths; - QueryAssemblyPathsAndResolver(compilationExtension, assemblyPath, buildingForEditor, out assemblyPaths, out assemblyResolver); - return WeaveInto(assembly, assemblyPath, outputDirectory, unityEngine, unityUNet, assemblyPaths, assemblyResolver); - } - - private static bool WeaveInto(ScriptAssembly assembly, string assemblyPath, string outputDirectory, string unityEngine, string unityUNet, string[] extraAssemblyPaths, IAssemblyResolver assemblyResolver) - { - var dependencies = assembly.GetAllReferences(); - var dependencyPaths = new string[dependencies.Count() + (extraAssemblyPaths != null ? extraAssemblyPaths.Length : 0)]; - - int i = 0; - - foreach (var dependency in dependencies) - dependencyPaths[i++] = Path.GetDirectoryName(dependency); - - if (extraAssemblyPaths != null) - extraAssemblyPaths.CopyTo(dependencyPaths, i); - - try - { - if (!Unity.UNetWeaver.Program.Process(unityEngine, unityUNet, outputDirectory, new[] { assemblyPath }, dependencyPaths, assemblyResolver, UnityEngine.Debug.LogWarning, UnityEngine.Debug.LogError)) - { - UnityEngine.Debug.LogError("Failure generating network code."); - return false; - } - } - catch (Exception ex) - { - UnityEngine.Debug.LogError("Exception generating network code: " + ex.ToString() + " " + ex.StackTrace); - } - return true; - } - - } -} diff --git a/Editor/Mono/SearchUtility.cs b/Editor/Mono/SearchUtility.cs deleted file mode 100644 index 094846680c..0000000000 --- a/Editor/Mono/SearchUtility.cs +++ /dev/null @@ -1,203 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using Object = UnityEngine.Object; -using UnityEditor.Collaboration; -using UnityEditor.Connect; - -namespace UnityEditor -{ - internal class SearchUtility - { - private static void RemoveUnwantedWhitespaces(ref string searchString) - { - // Some users add a whitespace after the colon (remove it) - searchString = searchString.Replace(": ", ":"); - } - - // Supports the following syntax: - // 't:type' syntax (e.g 't:Texture2D' will show Texture2D objects) - // 'l:assetlabel' syntax (e.g 'l:architecture' will show assets with AssetLabel 'architecture') - // 'ref[:id]:path' syntax (e.g 'ref:1234' will show objects that references the object with instanceID 1234) - // 'v:versionState' syntax (e.g 'v:modified' will show objects that are modified locally) - // 's:softLockState' syntax (e.g 's:inprogress' will show objects that are modified by anyone (except you)) - internal static bool ParseSearchString(string searchText, SearchFilter filter) - { - if (string.IsNullOrEmpty(searchText)) - return false; - - filter.ClearSearch(); - - string searchString = string.Copy(searchText); - RemoveUnwantedWhitespaces(ref searchString); - - bool parsed = false; - - // Split filter into separate words with space or tab as seperators - const string kFilterSeparator = " \t,*?"; - - // Skip any separators preceding the filter - int pos = FindFirstPositionNotOf(searchString, kFilterSeparator); - if (pos == -1) - pos = 0; - while (pos < searchString.Length) - { - int endpos = searchString.IndexOfAny(kFilterSeparator.ToCharArray(), pos); - - // Check if we have quotes (may be used for pathnames) inbetween start and a /filter-separator/ - int q1 = searchString.IndexOf('"', pos); - int q2 = -1; - if (q1 != -1) - { - q2 = searchString.IndexOf('"', q1 + 1); - if (q2 != -1) - // Advance to a /filter-separator/ after the quote - endpos = searchString.IndexOfAny(kFilterSeparator.ToCharArray(), q2); - else - // In case we can't find another quote, consume the rest of the string - endpos = -1; - } - - if (endpos == -1) - endpos = searchString.Length; - - if (endpos > pos) - { - string token = searchString.Substring(pos, endpos - pos); - if (CheckForKeyWords(token, filter, q1, q2)) - parsed = true; - else - filter.nameFilter += (string.IsNullOrEmpty(filter.nameFilter) ? "" : " ") + token; // force single space between name tokens - } - pos = endpos + 1; - } - return parsed; - } - - internal static bool CheckForKeyWords(string searchString, SearchFilter filter, int quote1, int quote2) - { - bool parsed = false; - - // Support: 't:type' syntax (e.g 't:Texture2D' will show Texture2D objects) - int index = searchString.IndexOf("t:"); - if (index == 0) - { - string type = searchString.Substring(index + 2); - List tmp = new List(filter.classNames); - tmp.Add(type); - filter.classNames = tmp.ToArray(); - parsed = true; - } - - // Support: 'l:assetlabel' syntax (e.g 'l:architecture' will show assets with AssetLabel 'architecture') - index = searchString.IndexOf("l:"); - if (index == 0) - { - string label = searchString.Substring(index + 2); - List tmp = new List(filter.assetLabels); - tmp.Add(label); - filter.assetLabels = tmp.ToArray(); - parsed = true; - } - - // Support: 'v:versionState' syntax - index = searchString.IndexOf("v:"); - if (index >= 0) - { - string versionStateString = searchString.Substring(index + 2); - List tmp = new List(filter.versionControlStates); - tmp.Add(versionStateString); - filter.versionControlStates = tmp.ToArray(); - parsed = true; - } - - // Support: 's:softLockState' syntax - index = searchString.IndexOf("s:"); - if (index >= 0) - { - string softLockStateString = searchString.Substring(index + 2); - List tmp = new List(filter.softLockControlStates); - tmp.Add(softLockStateString); - filter.softLockControlStates = tmp.ToArray(); - parsed = true; - } - - // Support: 'b:assetBundleName' syntax (e.g 'b:materialAssetBundle' will show assets within assetBundle 'materialAssetBundle') - index = searchString.IndexOf("b:"); - if (index == 0) - { - string assetBundleName = searchString.Substring(index + 2); - List tmp = new List(filter.assetBundleNames); - tmp.Add(assetBundleName); - filter.assetBundleNames = tmp.ToArray(); - parsed = true; - } - - // Support: 'ref[:id]:path' syntax (e.g 'ref:1234' will show objects that references the object with instanceID 1234) - index = searchString.IndexOf("ref:"); - if (index == 0) - { - int instanceID = 0; - - int firstColon = index + 3; - int secondColon = searchString.IndexOf(':', firstColon + 1); - if (secondColon >= 0) - { - // Instead of resolving a passed-in pathname to an instance-id, use a supplied one. - // The pathname is effectively just a UI hint of whose references we're filtering out. - string refString = searchString.Substring(firstColon + 1, secondColon - firstColon - 1); - int id; - if (System.Int32.TryParse(refString, out id)) - instanceID = id; - //else - // Debug.Log ("Not valid refString to case to Integer " + refString); // outcomment for debugging - } - else - { - string assetPath; - if (quote1 != -1 && quote2 != -1) - { - int startIndex = quote1 + 1; - int count = quote2 - quote1 - 1; - if (count < 0 || quote2 == -1) - count = searchString.Length - startIndex; - - // Strip filepath from quotes - assetPath = "Assets/" + searchString.Substring(startIndex, count); - } - else - // Otherwise use string from colon to end - assetPath = "Assets/" + searchString.Substring(firstColon + 1); - - Object obj = AssetDatabase.LoadMainAssetAtPath(assetPath); - if (obj != null) - instanceID = obj.GetInstanceID(); - //else - // Debug.Log ("Not valid assetPath " + assetPath); // outcomment for debugging - } - - filter.referencingInstanceIDs = new[] { instanceID }; - parsed = true; - } - - return parsed; - } - - private static int FindFirstPositionNotOf(string source, string chars) - { - if (source == null) return -1; - if (chars == null) return 0; - if (source.Length == 0) return -1; - if (chars.Length == 0) return 0; - - for (int i = 0; i < source.Length; i++) - { - if (chars.IndexOf(source[i]) == -1) - return i; - } - return -1; - } - } -} diff --git a/Editor/Mono/Selection.bindings.cs b/Editor/Mono/Selection.bindings.cs deleted file mode 100644 index ef5daa3a2a..0000000000 --- a/Editor/Mono/Selection.bindings.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor -{ - // SelectionMode can be used to tweak the selection returned by Selection.GetTransforms. - public enum SelectionMode - { - // Return the whole selection. - Unfiltered = 0, - // Only return the topmost selected transform. A selected child of another selected transform will be filtered out. - TopLevel = 1, - // Return the selection and all child transforms of the selection. - Deep = 2, - // Excludes any prefabs from the selection. - ExcludePrefab = 4, - // Excludes any objects which shall not be modified. - Editable = 8, - // Only return objects that are assets in the Asset directory. - Assets = 16, - // If the selection contains folders, also include all assets and subfolders within that folder in the file hierarchy. - DeepAssets = 32, - // Return a selection that only contains top level selection of all visible assets - //TopLevelAssets = 64, - // renamed to Editable - OnlyUserModifiable = 8 - } - - [NativeHeader("Editor/Src/Selection.bindings.h")] - [NativeHeader("Editor/Src/Gizmos/GizmoUtil.h")] - [NativeHeader("Editor/Src/Selection.h")] - [NativeHeader("Editor/Src/SceneInspector.h")] - public sealed partial class Selection - { - // Returns the top level selection, excluding prefabs. - public extern static Transform[] transforms - { - [NativeMethod("GetTransformSelection", true)] - get; - } - - // Returns the actual game object selection. Includes prefabs, non-modifyable objects. - public extern static Transform activeTransform - { - [NativeMethod("GetActiveTransform", true)] - get; - [NativeMethod("SetActiveObject", true)] - set; - } - - // Returns the actual game object selection. Includes prefabs, non-modifyable objects. - public extern static GameObject[] gameObjects - { - [NativeMethod("GetGameObjectSelection", true)] - get; - } - - // Returns the active game object. (The one shown in the inspector) - public extern static GameObject activeGameObject - { - [NativeMethod("GetActiveGO", true)] - get; - [NativeMethod("SetActiveObject", true)] - set; - } - - // Returns the actual object selection. Includes prefabs, non-modifyable objects. - extern public static Object activeObject - { - [NativeMethod("GetActiveObject", true)] - get; - [NativeMethod("SetActiveObject", true)] - set; - } - - // Returns the active context object - extern public static Object activeContext - { - [NativeMethod("GetActiveContext", true)] - get; - } - - // Returns the instanceID of the actual object selection. Includes prefabs, non-modifyable objects. - [StaticAccessor("Selection", StaticAccessorType.DoubleColon)] - [NativeName("ActiveID")] - extern public static int activeInstanceID { get; set; } - - // The actual unfiltered selection from the Scene. - [StaticAccessor("SelectionBindings", StaticAccessorType.DoubleColon)] - extern public static Object[] objects { get; set; } - - // The actual unfiltered selection from the Scene returned as instance ids instead of ::ref::objects. - [StaticAccessor("SelectionBindings", StaticAccessorType.DoubleColon)] - extern public static int[] instanceIDs { get; set; } - - [StaticAccessor("GetSceneTracker()", StaticAccessorType.Dot)] - [NativeMethod("IsSelected")] - extern public static bool Contains(int instanceID); - - [NativeMethod("SetActiveObjectWithContextInternal", true)] - extern public static void SetActiveObjectWithContext(Object obj, Object context); - - // Allows for fine grained control of the selection type using the [[SelectionMode]] bitmask. - [NativeMethod("GetTransformSelection", true)] - extern public static Transform[] GetTransforms(SelectionMode mode); - - //* undocumented - utility function - [StaticAccessor("SelectionBindings", StaticAccessorType.DoubleColon)] - extern internal static Object[] GetObjectsMode(SelectionMode mode); - - [StaticAccessor("SelectionBindings", StaticAccessorType.DoubleColon)] - extern internal static string[] assetGUIDsDeepSelection - { - [NativeMethod("GetSelectedAssetGUIDStringsDeep")] - get; - } - - [StaticAccessor("SelectionBindings", StaticAccessorType.DoubleColon)] - extern public static string[] assetGUIDs - { - [NativeMethod("GetSelectedAssetGUIDStrings")] - get; - } - } -} diff --git a/Editor/Mono/Selection.cs b/Editor/Mono/Selection.cs deleted file mode 100644 index f72e882bee..0000000000 --- a/Editor/Mono/Selection.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Linq; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - public sealed partial class Selection - { - public static System.Action selectionChanged; - - private static void Internal_CallSelectionChanged() - { - if (selectionChanged != null) - selectionChanged(); - } - - public static bool Contains(Object obj) { return Contains(obj.GetInstanceID()); } - - internal static void Add(int instanceID) - { - var ids = new List(Selection.instanceIDs); - if (ids.IndexOf(instanceID) < 0) - { - ids.Add(instanceID); - Selection.instanceIDs = ids.ToArray(); - } - } - - internal static void Add(Object obj) - { - if (obj != null) - Add(obj.GetInstanceID()); - } - - internal static void Remove(int instanceID) - { - var ids = new List(Selection.instanceIDs); - ids.Remove(instanceID); - Selection.instanceIDs = ids.ToArray(); - } - - internal static void Remove(Object obj) - { - if (obj != null) - Remove(obj.GetInstanceID()); - } - - private static IEnumerable GetFilteredInternal(System.Type type, SelectionMode mode) - { - if (typeof(Component).IsAssignableFrom(type) || type.IsInterface) - return GetTransforms(mode).Select(t => t.GetComponent(type)).Where(c => c != null); - else if (typeof(GameObject).IsAssignableFrom(type)) - return GetTransforms(mode).Select(t => t.gameObject); - else - return GetObjectsMode(mode).Where(o => o != null && type.IsAssignableFrom(o.GetType())); - } - - public static T[] GetFiltered(SelectionMode mode) // no generic constraint because we also want to allow interfaces - { - return GetFilteredInternal(typeof(T), mode).Cast().ToArray(); - } - - public static Object[] GetFiltered(System.Type type, SelectionMode mode) - { - return GetFilteredInternal(type, mode).Cast().ToArray(); - } - } -} diff --git a/Editor/Mono/SerializedObject.cs b/Editor/Mono/SerializedObject.cs deleted file mode 100644 index 7cfa11e50d..0000000000 --- a/Editor/Mono/SerializedObject.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - public partial class SerializedObject - { - // Create SerializedObject for inspected object. - public SerializedObject(Object obj) - { - InternalCreate(new Object[] {obj}, null); - } - - public SerializedObject(Object obj, Object context) - { - InternalCreate(new Object[] {obj}, context); - } - - // Create SerializedObject for inspected object. - public SerializedObject(Object[] objs) - { - InternalCreate(objs, null); - } - - public SerializedObject(Object[] objs, Object context) - { - InternalCreate(objs, context); - } - - ~SerializedObject() { Dispose(); } - - // Get the first serialized property. - public SerializedProperty GetIterator() - { - SerializedProperty i = GetIterator_Internal(); - // This is so the garbage collector won't clean up SerializedObject behind the scenes, - // when we are still iterating properties - i.m_SerializedObject = this; - return i; - } - - // Find serialized property by name. - public SerializedProperty FindProperty(string propertyPath) - { - SerializedProperty i = GetIterator_Internal(); - // This is so the garbage collector won't clean up SerializedObject behind the scenes, - // when we are still iterating properties - i.m_SerializedObject = this; - if (i.FindPropertyInternal(propertyPath)) - return i; - else - return null; - } - } -} diff --git a/Editor/Mono/SerializedProperty.cs b/Editor/Mono/SerializedProperty.cs deleted file mode 100644 index 16af43eee5..0000000000 --- a/Editor/Mono/SerializedProperty.cs +++ /dev/null @@ -1,204 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - -using UnityObject = UnityEngine.Object; - -namespace UnityEditor -{ - public partial class SerializedProperty - { - internal SerializedProperty() {} - ~SerializedProperty() { Dispose(); } - - // [[SerializedObject]] this property belongs to (RO). - public SerializedObject serializedObject { get { return m_SerializedObject; } } - - public UnityObject exposedReferenceValue - { - get - { - if (propertyType != SerializedPropertyType.ExposedReference) - return null; - - var defaultValue = FindPropertyRelative("defaultValue"); - if (defaultValue == null) - return null; - - var returnedValue = defaultValue.objectReferenceValue; - - var exposedPropertyTable = serializedObject.context as IExposedPropertyTable; - if (exposedPropertyTable != null) - { - SerializedProperty exposedName = FindPropertyRelative("exposedName"); - var propertyName = new PropertyName(exposedName.stringValue); - - bool propertyFoundInTable = false; - var objReference = exposedPropertyTable.GetReferenceValue(propertyName, out propertyFoundInTable); - if (propertyFoundInTable == true) - returnedValue = objReference; - } - return returnedValue; - } - - set - { - if (propertyType != SerializedPropertyType.ExposedReference) - { - throw new System.InvalidOperationException("Attempting to set the reference value on a SerializedProperty that is not an ExposedReference"); - } - - var defaultValue = FindPropertyRelative("defaultValue"); - - var exposedPropertyTable = serializedObject.context as IExposedPropertyTable; - if (exposedPropertyTable == null) - { - defaultValue.objectReferenceValue = value; - defaultValue.serializedObject.ApplyModifiedProperties(); - return; - } - - SerializedProperty exposedName = FindPropertyRelative("exposedName"); - - var exposedId = exposedName.stringValue; - if (String.IsNullOrEmpty(exposedId)) - { - exposedId = UnityEditor.GUID.Generate().ToString(); - exposedName.stringValue = exposedId; - } - var propertyName = new PropertyName(exposedId); - exposedPropertyTable.SetReferenceValue(propertyName, value); - } - } - - internal bool isScript - { - get { return type == "PPtr"; } - } - - private bool isUnityAssembly - { - get - { - return EditorUtility.IsUnityAssembly(m_SerializedObject.targetObject); - } - } - - internal string localizedDisplayName - { - get - { - if (!this.isValidDisplayNameCache) - { - this.isValidDisplayNameCache = true; - m_CachedLocalizedDisplayName = isUnityAssembly ? L10n.Tr(displayName) : displayName; - } - return m_CachedLocalizedDisplayName; - } - } - - internal string[] enumLocalizedDisplayNames - { - get - { - string[] names = enumDisplayNames; - if (!isUnityAssembly) - return names; - - var res = new string[names.Length]; - for (var i = 0; i < res.Length; ++i) - { - res[i] = L10n.Tr(names[i]); - } - return res; - } - } - - // 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. - public SerializedProperty Copy() - { - SerializedProperty property = CopyInternal(); - property.m_SerializedObject = m_SerializedObject; - return property; - } - - // Retrieves the SerializedProperty at a relative path to the current property. - public SerializedProperty FindPropertyRelative(string relativePropertyPath) - { - SerializedProperty prop = Copy(); - if (prop.FindPropertyRelativeInternal(relativePropertyPath)) - return prop; - else - return null; - } - - // Retrieves an iterator that allows you to iterator over the current nexting of a serialized property. - public System.Collections.IEnumerator GetEnumerator() - { - if (isArray) - { - for (int i = 0; i < arraySize; i++) - { - yield return GetArrayElementAtIndex(i); - } - } - else - { - var end = GetEndProperty(); - while (NextVisible(true) && !SerializedProperty.EqualContents(this, end)) - { - yield return this; - } - } - } - - // Returns the element at the specified index in the array. - public SerializedProperty GetArrayElementAtIndex(int index) - { - SerializedProperty prop = Copy(); - if (prop.GetArrayElementAtIndexInternal(index)) - return prop; - else - return null; - } - - internal void SetToValueOfTarget(UnityObject target) - { - SerializedProperty targetProperty = new SerializedObject(target).FindProperty(propertyPath); - if (targetProperty == null) - { - Debug.LogError(target.name + " does not have the property " + propertyPath); - return; - } - switch (propertyType) - { - case SerializedPropertyType.Integer: intValue = targetProperty.intValue; break; - case SerializedPropertyType.Boolean: boolValue = targetProperty.boolValue; break; - case SerializedPropertyType.Float: floatValue = targetProperty.floatValue; break; - case SerializedPropertyType.String: stringValue = targetProperty.stringValue; break; - case SerializedPropertyType.Color: colorValue = targetProperty.colorValue; break; - case SerializedPropertyType.ObjectReference: objectReferenceValue = targetProperty.objectReferenceValue; break; - case SerializedPropertyType.LayerMask: intValue = targetProperty.intValue; break; - case SerializedPropertyType.Enum: enumValueIndex = targetProperty.enumValueIndex; break; - case SerializedPropertyType.Vector2: vector2Value = targetProperty.vector2Value; break; - case SerializedPropertyType.Vector3: vector3Value = targetProperty.vector3Value; break; - case SerializedPropertyType.Vector4: vector4Value = targetProperty.vector4Value; break; - case SerializedPropertyType.Vector2Int: vector2IntValue = targetProperty.vector2IntValue; break; - case SerializedPropertyType.Vector3Int: vector3IntValue = targetProperty.vector3IntValue; break; - case SerializedPropertyType.Rect: rectValue = targetProperty.rectValue; break; - case SerializedPropertyType.RectInt: rectIntValue = targetProperty.rectIntValue; break; - case SerializedPropertyType.ArraySize: intValue = targetProperty.intValue; break; - case SerializedPropertyType.Character: intValue = targetProperty.intValue; break; - case SerializedPropertyType.AnimationCurve: animationCurveValue = targetProperty.animationCurveValue; break; - case SerializedPropertyType.Bounds: boundsValue = targetProperty.boundsValue; break; - case SerializedPropertyType.BoundsInt: boundsIntValue = targetProperty.boundsIntValue; break; - case SerializedPropertyType.Gradient: gradientValue = targetProperty.gradientValue; break; - case SerializedPropertyType.ExposedReference: exposedReferenceValue = targetProperty.exposedReferenceValue; break; - } - } - - } -} diff --git a/Editor/Mono/SerializedProperty/SerializedPropertyFilters.cs b/Editor/Mono/SerializedProperty/SerializedPropertyFilters.cs deleted file mode 100644 index 6e82b7ae85..0000000000 --- a/Editor/Mono/SerializedProperty/SerializedPropertyFilters.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - internal class SerializedPropertyFilters - { - internal interface IFilter - { - bool Active(); // returns true if filter is active, false otherwise - bool Filter(SerializedProperty prop); // returns true if filtering passes - void OnGUI(Rect r); // draws the filter control - string SerializeState(); // returns null if there's nothing to serialize - void DeserializeState(string state); // state must not be null - } - - internal abstract class SerializableFilter : IFilter - { - public abstract bool Active(); // returns true if filter is active, false otherwise - public abstract bool Filter(SerializedProperty prop); // returns true if filtering passes - public abstract void OnGUI(Rect r); // draws the filter control - public string SerializeState() { return JsonUtility.ToJson(this); } - public void DeserializeState(string state) { JsonUtility.FromJsonOverwrite(state, this); } - }; - - - internal class String : SerializableFilter - { - static class Styles - { - public static readonly GUIStyle searchField = "SearchTextField"; - public static readonly GUIStyle searchFieldCancelButton = "SearchCancelButton"; - public static readonly GUIStyle searchFieldCancelButtonEmpty = "SearchCancelButtonEmpty"; - } - - [SerializeField] protected string m_Text = ""; - public override bool Active() { return !string.IsNullOrEmpty(m_Text); } - public override bool Filter(SerializedProperty prop) { return prop.stringValue.IndexOf(m_Text, 0, System.StringComparison.OrdinalIgnoreCase) >= 0; } - public override void OnGUI(Rect r) - { - r.width -= 15; - m_Text = EditorGUI.TextField(r, GUIContent.none, m_Text, Styles.searchField); - - // draw the cancel button - r.x += r.width; - r.width = 15; - bool notEmpty = m_Text != ""; - if (GUI.Button(r, GUIContent.none, notEmpty ? Styles.searchFieldCancelButton : Styles.searchFieldCancelButtonEmpty) && notEmpty) - { - m_Text = ""; - GUIUtility.keyboardControl = 0; - } - } - } - - internal sealed class Name : String - { - public bool Filter(string str) { return str.IndexOf(m_Text, 0, System.StringComparison.OrdinalIgnoreCase) >= 0; } - } - - internal sealed class None : IFilter - { - public bool Active() { return false; } - public bool Filter(SerializedProperty prop) { return true; } - public void OnGUI(Rect r) {} - public string SerializeState() { return null; } - public void DeserializeState(string state) {} - } - internal static readonly None s_FilterNone = new None(); - } -} diff --git a/Editor/Mono/SerializedProperty/SerializedPropertyTable.cs b/Editor/Mono/SerializedProperty/SerializedPropertyTable.cs deleted file mode 100644 index 7e1f17eb79..0000000000 --- a/Editor/Mono/SerializedProperty/SerializedPropertyTable.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.IMGUI.Controls; -using UnityEngine.Profiling; - -namespace UnityEditor -{ - internal class SerializedPropertyTable - { - static class Styles - { - public static readonly GUIStyle DragHandle = "RL DragHandle"; - } - - internal delegate SerializedPropertyTreeView.Column[] HeaderDelegate(out string[] propNames); - - SerializedPropertyDataStore.GatherDelegate m_GatherDelegate; - HeaderDelegate m_HeaderDelegate; - bool m_Initialized; - TreeViewState m_TreeViewState; - MultiColumnHeaderState m_MultiColumnHeaderState; - SerializedPropertyTreeView m_TreeView; - SerializedPropertyDataStore m_DataStore; - float m_ColumnHeaderHeight; - float m_TableHeight = 200; - string m_SerializationUID; - static readonly string s_TableHeight = "_TableHeight"; - bool m_DragHandleEnabled = false; - readonly float m_FilterHeight = 20; - readonly float m_DragHeight = 20; - readonly float m_DragWidth = 32; - - public bool dragHandleEnabled { get { return m_DragHandleEnabled; } set { m_DragHandleEnabled = value; } } - - public SerializedPropertyTable(string serializationUID, SerializedPropertyDataStore.GatherDelegate gatherDelegate, HeaderDelegate headerDelegate) - { - m_SerializationUID = serializationUID; - m_GatherDelegate = gatherDelegate; - m_HeaderDelegate = headerDelegate; - - OnEnable(); - } - - void InitIfNeeded() - { - if (m_Initialized) - return; - - if (m_TreeViewState == null) - m_TreeViewState = new TreeViewState(); - - - if (m_MultiColumnHeaderState == null) - { - string[] propNames; - - m_MultiColumnHeaderState = new MultiColumnHeaderState(m_HeaderDelegate(out propNames)); - m_DataStore = new SerializedPropertyDataStore(propNames, m_GatherDelegate); - } - - var header = new MultiColumnHeader(m_MultiColumnHeaderState); - m_ColumnHeaderHeight = header.height; - m_TreeView = new SerializedPropertyTreeView(m_TreeViewState, header, m_DataStore); - - m_TreeView.DeserializeState(m_SerializationUID); - m_TreeView.Reload(); - - m_Initialized = true; - } - - float GetMinHeight() - { - float rowHeight = EditorGUIUtility.singleLineHeight; - float fixedHeight = m_FilterHeight + m_ColumnHeaderHeight + rowHeight + m_DragHeight; - - return fixedHeight + rowHeight * 3; // three rows - } - - public void OnInspectorUpdate() - { - if (m_DataStore != null && m_DataStore.Repopulate() && m_TreeView != null) - { - m_TreeView.FullReload(); - } - else if (m_TreeView != null && m_TreeView.Update()) - { - m_TreeView.Repaint(); - } - } - - public void OnHierarchyChange() - { - if (m_DataStore != null && m_DataStore.Repopulate() && m_TreeView != null) - m_TreeView.FullReload(); - } - - public void OnSelectionChange() - { - OnSelectionChange(Selection.instanceIDs); - } - - public void OnSelectionChange(int[] instanceIDs) - { - if (m_TreeView != null) - { - m_TreeView.SetSelection(instanceIDs); - } - } - - public void OnGUI() - { - Profiler.BeginSample("SerializedPropertyTable.OnGUI"); - InitIfNeeded(); - - Rect r; - - if (dragHandleEnabled) - r = GUILayoutUtility.GetRect(0, 10000, m_TableHeight, m_TableHeight); - else - r = GUILayoutUtility.GetRect(0, float.MaxValue, 0, float.MaxValue); - - if (Event.current.type == EventType.Layout) - return; - - float windowWidth = r.width; - float tableHeight = r.height - m_FilterHeight - (dragHandleEnabled ? m_DragHeight : 0); - // filter rect - float h = r.height; - r.height = m_FilterHeight; - Rect filterRect = r; - // table rect - r.height = tableHeight; - r.y += m_FilterHeight; - Rect tableRect = r; - - // table - Profiler.BeginSample("TreeView.OnGUI"); - m_TreeView.OnGUI(tableRect); - Profiler.EndSample(); - - if (dragHandleEnabled) - { - // separator rect - r.y += tableHeight + 1; - r.height = 1; - Rect sepRect = r; - // drag rect - r.height = 10; - r.y += 10; - r.x += (r.width - m_DragWidth) * 0.5f; - r.width = m_DragWidth; - - m_TableHeight = EditorGUI.HeightResizer(r, m_TableHeight, GetMinHeight(), float.MaxValue); - - // separator (TODO: this doesn't quite work in the case where the vertical bar is visible and the last column overlaps it) - // once trunk is merged again the treeview will provide a routine to draw the separator for us - if (m_MultiColumnHeaderState.widthOfAllVisibleColumns <= windowWidth) - { - Rect uv = new Rect(0, 1f, 1, 1f - 1f / EditorStyles.inspectorTitlebar.normal.background.height); - GUI.DrawTextureWithTexCoords(sepRect, EditorStyles.inspectorTitlebar.normal.background, uv); - } - - if (Event.current.type == EventType.Repaint) - Styles.DragHandle.Draw(r, false, false, false, false); - } - - m_TreeView.OnFilterGUI(filterRect); - - if (m_TreeView.IsFilteredDirty()) - m_TreeView.Reload(); - - Profiler.EndSample(); - } - - public void OnEnable() - { - m_TableHeight = SessionState.GetFloat(m_SerializationUID + s_TableHeight, 200); - } - - public void OnDisable() - { - if (m_TreeView != null) - m_TreeView.SerializeState(m_SerializationUID); - - SessionState.SetFloat(m_SerializationUID + s_TableHeight, m_TableHeight); - } - } -} diff --git a/Editor/Mono/SerializedProperty/SerializedPropertyTreeView.cs b/Editor/Mono/SerializedProperty/SerializedPropertyTreeView.cs deleted file mode 100644 index 091f7bc699..0000000000 --- a/Editor/Mono/SerializedProperty/SerializedPropertyTreeView.cs +++ /dev/null @@ -1,637 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditor.IMGUI.Controls; -using UnityEngine.Profiling; - -namespace UnityEditor -{ - internal class SerializedPropertyDataStore - { - internal class Data - { - UnityEngine.Object m_Object; - SerializedObject m_SerializedObject; - SerializedProperty[] m_Properties; - - public Data(UnityEngine.Object obj, string[] props) - { - m_Object = obj; - m_SerializedObject = new SerializedObject(obj); - m_Properties = new SerializedProperty[props.Length]; - - for (int i = 0; i < props.Length; i++) - m_Properties[i] = m_SerializedObject.FindProperty(props[i]); - } - - public void Dispose() - { - foreach (var prop in m_Properties) - { - if (prop != null) - prop.Dispose(); - } - - m_SerializedObject.Dispose(); - - m_Object = null; - m_SerializedObject = null; - m_Properties = null; - } - - public string name { get { return m_Object != null ? m_Object.name : string.Empty; } } - public SerializedObject serializedObject { get { return m_SerializedObject; } } - public SerializedProperty[] properties { get { return m_Properties; } } - - public int objectId - { - get - { - if (!m_Object) - return 0; - - Component comp = m_Object as Component; - return comp != null ? comp.gameObject.GetInstanceID() : m_Object.GetInstanceID(); - } - } - - public bool Update() { return m_Object != null ? m_SerializedObject.UpdateIfRequiredOrScript() : false; } - public void Store() { if (m_Object != null) { m_SerializedObject.ApplyModifiedProperties(); } } - } - - // LightTreeDataStore members - internal delegate UnityEngine.Object[] GatherDelegate(); - UnityEngine.Object[] m_Objects; - Data[] m_Elements; - string[] m_PropNames; - GatherDelegate m_GatherDel; - - public Data[] GetElements() { return m_Elements; } - - public SerializedPropertyDataStore(string[] propNames, GatherDelegate gatherDel) - { - m_PropNames = propNames; - m_GatherDel = gatherDel; - - Repopulate(); - } - - ~SerializedPropertyDataStore() - { - Clear(); - } - - public bool Repopulate() - { - Profiler.BeginSample("SerializedPropertyDataStore.Repopulate.GatherDelegate"); - UnityEngine.Object[] objs = m_GatherDel(); - Profiler.EndSample(); - - if (m_Objects != null) - { - // If nothing's changed -> bail - if (objs.Length == m_Objects.Length && ArrayUtility.ArrayReferenceEquals(objs, m_Objects)) - return false; - - Clear(); - } - - // Recreate data store - m_Objects = objs; - m_Elements = new Data[objs.Length]; - for (int i = 0; i < objs.Length; i++) - m_Elements[i] = new Data(objs[i], m_PropNames); - - return true; - } - - private void Clear() - { - // Clear current - for (int i = 0; i < m_Elements.Length; i++) - m_Elements[i].Dispose(); - - m_Objects = null; - m_Elements = null; - } - } - - internal class SerializedPropertyTreeView : TreeView - { - internal static class Styles - { - public static readonly GUIStyle entryEven = "OL EntryBackEven"; - public static readonly GUIStyle entryOdd = "OL EntryBackOdd"; - public static readonly string focusHelper = "SerializedPropertyTreeViewFocusHelper"; - public static readonly string serializeFilterSelection = "_FilterSelection"; - public static readonly string serializeFilterDisable = "_FilterDisable"; - public static readonly string serializeFilterInvert = "_FilterInvert"; - public static readonly string serializeTreeViewState = "_TreeViewState"; - public static readonly string serializeColumnHeaderState = "_ColumnHeaderState"; - public static readonly string serializeFilter = "_Filter_"; - public static readonly GUIContent filterSelection = EditorGUIUtility.TrTextContent("Lock Selection", "Limits the table contents to the active selection."); - public static readonly GUIContent filterDisable = EditorGUIUtility.TrTextContent("Disable All", "Disables all filters."); - public static readonly GUIContent filterInvert = EditorGUIUtility.TrTextContent("Invert Result", "Inverts the filtered results."); - } - - // this gets stuffed into the view and displayed on screen. It is a visible subset of the actual data - internal class SerializedPropertyItem : TreeViewItem - { - SerializedPropertyDataStore.Data m_Data; - public SerializedPropertyItem(int id, int depth, SerializedPropertyDataStore.Data ltd) : base(id, depth, ltd != null ? ltd.name : "root") - { - m_Data = ltd; - } - - public SerializedPropertyDataStore.Data GetData() { return m_Data; } - } - - internal class Column : MultiColumnHeaderState.Column - { - public delegate void DrawEntry(Rect r, SerializedProperty prop, SerializedProperty[] dependencies); - public delegate int CompareEntry(SerializedProperty lhs, SerializedProperty rhs); - public delegate void CopyDelegate(SerializedProperty target, SerializedProperty source); - - public string propertyName; - public int[] dependencyIndices; - public DrawEntry drawDelegate; - public CompareEntry compareDelegate; - public CopyDelegate copyDelegate; - public SerializedPropertyFilters.IFilter filter; - }; - - private struct ColumnInternal - { - public SerializedProperty[] dependencyProps; // helper array, must be the same size as dependencyIndices - }; - - internal class DefaultDelegates - { - public static readonly Column.DrawEntry s_DrawDefault = (Rect r, SerializedProperty prop, SerializedProperty[] dependencies) => - { - Profiler.BeginSample("PropDrawDefault"); - EditorGUI.PropertyField(r, prop, GUIContent.none); - Profiler.EndSample(); - }; - public static readonly Column.DrawEntry s_DrawCheckbox = (Rect r, SerializedProperty prop, SerializedProperty[] dependencies) => - { - Profiler.BeginSample("PropDrawCheckbox"); - float off = (r.width / 2) - 8; - r.x += off >= 0 ? off : 0; - EditorGUI.PropertyField(r, prop, GUIContent.none); - Profiler.EndSample(); - }; - public static readonly Column.DrawEntry s_DrawName = (Rect r, SerializedProperty prop, SerializedProperty[] dependencies) => {}; - - public static readonly Column.CompareEntry s_CompareFloat = (SerializedProperty lhs, SerializedProperty rhs) => - { - return lhs.floatValue.CompareTo(rhs.floatValue); - }; - public static readonly Column.CompareEntry s_CompareCheckbox = (SerializedProperty lhs, SerializedProperty rhs) => - { - return lhs.boolValue.CompareTo(rhs.boolValue); - }; - public static readonly Column.CompareEntry s_CompareEnum = (SerializedProperty lhs, SerializedProperty rhs) => - { - return lhs.enumValueIndex.CompareTo(rhs.enumValueIndex); - }; - public static readonly Column.CompareEntry s_CompareInt = (SerializedProperty lhs, SerializedProperty rhs) => - { - return lhs.intValue.CompareTo(rhs.intValue); - }; - public static readonly Column.CompareEntry s_CompareColor = (SerializedProperty lhs, SerializedProperty rhs) => - { - float lh, ls, lv, rh, rs, rv; - Color.RGBToHSV(lhs.colorValue, out lh, out ls, out lv); - Color.RGBToHSV(rhs.colorValue, out rh, out rs, out rv); - return lh.CompareTo(rh); - }; - public static readonly Column.CompareEntry s_CompareName = (SerializedProperty lhs, SerializedProperty rhs) => - { - return 0; - }; - public static readonly Column.CopyDelegate s_CopyDefault = (SerializedProperty target, SerializedProperty source) => - { - target.serializedObject.CopyFromSerializedProperty(source); - }; - } - // reference to the data store (not owned by this class) - SerializedPropertyDataStore m_DataStore; - ColumnInternal[] m_ColumnsInternal; - List m_Items; - int m_ChangedId; - bool m_bFilterSelection; - int[] m_SelectionFilter; - - public SerializedPropertyTreeView(TreeViewState state, MultiColumnHeader multicolumnHeader, SerializedPropertyDataStore dataStore) : base(state, multicolumnHeader) - { - m_DataStore = dataStore; - // initialize internal data for the columns - int colcnt = multiColumnHeader.state.columns.Length; - m_ColumnsInternal = new ColumnInternal[colcnt]; - for (int i = 0; i < colcnt; i++) - { - Column c = Col(i); - if (c.propertyName != null) - m_ColumnsInternal[i].dependencyProps = new SerializedProperty[c.propertyName.Length]; - } - - multiColumnHeader.sortingChanged += OnSortingChanged; - multiColumnHeader.visibleColumnsChanged += OnVisibleColumnChanged; - - showAlternatingRowBackgrounds = true; - showBorder = true; - rowHeight = EditorGUIUtility.singleLineHeight; - } - - public void SerializeState(string uid) - { - SessionState.SetBool(uid + Styles.serializeFilterSelection, m_bFilterSelection); - - for (int i = 0; i < multiColumnHeader.state.columns.Length; i++) - { - var filter = Col(i).filter; - - if (filter == null) - continue; - - string filterState = filter.SerializeState(); - - if (string.IsNullOrEmpty(filterState)) - continue; - - SessionState.SetString(uid + Styles.serializeFilter + i, filterState); - } - - SessionState.SetString(uid + Styles.serializeTreeViewState, JsonUtility.ToJson(state)); - SessionState.SetString(uid + Styles.serializeColumnHeaderState, JsonUtility.ToJson(multiColumnHeader.state)); - } - - public void DeserializeState(string uid) - { - m_bFilterSelection = SessionState.GetBool(uid + Styles.serializeFilterSelection, false); - - for (int i = 0; i < multiColumnHeader.state.columns.Length; i++) - { - var filter = Col(i).filter; - if (filter == null) - continue; - - string filterState = SessionState.GetString(uid + Styles.serializeFilter + i, null); - if (string.IsNullOrEmpty(filterState)) - continue; - - filter.DeserializeState(filterState); - } - - string treeViewState = SessionState.GetString(uid + Styles.serializeTreeViewState, ""); - string columnHeaderState = SessionState.GetString(uid + Styles.serializeColumnHeaderState, ""); - - if (!string.IsNullOrEmpty(treeViewState)) - JsonUtility.FromJsonOverwrite(treeViewState, state); - if (!string.IsNullOrEmpty(columnHeaderState)) - JsonUtility.FromJsonOverwrite(columnHeaderState, multiColumnHeader.state); - } - - public bool IsFilteredDirty() - { - return m_ChangedId != 0 && (m_ChangedId != GUIUtility.keyboardControl || !EditorGUIUtility.editingTextField); - } - - public bool Update() - { - var rows = GetRows(); - int first, last; - - GetFirstAndLastVisibleRows(out first, out last); - - bool changed = false; - - if (last != -1) - { - for (int i = first; i <= last; i++) - { - changed = changed || ((SerializedPropertyItem)rows[i]).GetData().Update(); - } - } - - return changed; - } - - public void FullReload() - { - m_Items = null; - Reload(); - } - - protected override TreeViewItem BuildRoot() - { - return new SerializedPropertyItem(-1, -1, null); - } - - // this gets called whenever someone issues a reload() call to the parent - protected override IList BuildRows(TreeViewItem root) - { - if (m_Items == null) - { - var rawData = m_DataStore.GetElements(); - m_Items = new List(rawData.Length); - - for (int i = 0; i < rawData.Length; i++) - { - var item = new SerializedPropertyItem(rawData[i].objectId, 0, rawData[i]); - m_Items.Add(item); - } - } - - // filtering - IEnumerable tmprows = m_Items; - - if (m_bFilterSelection) - { - if (m_SelectionFilter == null) - m_SelectionFilter = Selection.instanceIDs; - tmprows = m_Items.Where((TreeViewItem item) => { return m_SelectionFilter.Contains(item.id); }); - } - else - m_SelectionFilter = null; - - tmprows = Filter(tmprows); - - var rows = tmprows.ToList(); - - if (multiColumnHeader.sortedColumnIndex >= 0) - Sort(rows, multiColumnHeader.sortedColumnIndex); - - m_ChangedId = 0; - - // We still need to setup the child parent information for the rows since this - // information is used by the TreeView internal logic (navigation, dragging etc) - TreeViewUtility.SetParentAndChildrenForItems(rows, root); - - return rows; - } - - protected override void RowGUI(RowGUIArgs args) - { - var item = (SerializedPropertyItem)args.item; - - for (int i = 0; i < args.GetNumVisibleColumns(); ++i) - { - CellGUI(args.GetCellRect(i), item, args.GetColumn(i), ref args); - } - } - - void CellGUI(Rect cellRect, SerializedPropertyItem item, int columnIndex, ref RowGUIArgs args) - { - Profiler.BeginSample("SerializedPropertyTreeView.CellGUI"); - CenterRectUsingSingleLineHeight(ref cellRect); - var ltd = item.GetData(); - Column column = (Column)this.multiColumnHeader.GetColumn(columnIndex); - - if (column.drawDelegate == DefaultDelegates.s_DrawName) - { - // default drawing - Profiler.BeginSample("SerializedPropertyTreeView.OnItemGUI.LabelField"); - DefaultGUI.Label(cellRect, ltd.name, IsSelected(args.item.id), false); - Profiler.EndSample(); - } - else if (column.drawDelegate != null) - { - SerializedProperty[] props = ltd.properties; - int depcnt = column.dependencyIndices != null ? column.dependencyIndices.Length : 0; - - for (int i = 0; i < depcnt; i++) - m_ColumnsInternal[columnIndex].dependencyProps[i] = props[column.dependencyIndices[i]]; - - // allow to capture tabs - if (args.item.id == state.lastClickedID && HasFocus() && columnIndex == multiColumnHeader.state.visibleColumns[multiColumnHeader.state.visibleColumns[0] == 0 ? 1 : 0]) - GUI.SetNextControlName(Styles.focusHelper); - - SerializedProperty prop = ltd.properties[columnIndex]; - - EditorGUI.BeginChangeCheck(); - - Profiler.BeginSample("SerializedPropertyTreeView.OnItemGUI.drawDelegate"); - - column.drawDelegate(cellRect, prop, m_ColumnsInternal[columnIndex].dependencyProps); - - Profiler.EndSample(); - if (EditorGUI.EndChangeCheck()) - { - // if we changed a value in a filtered column we'll have to reload the table - m_ChangedId = ((column.filter != null) && column.filter.Active()) ? GUIUtility.keyboardControl : m_ChangedId; - // update all selected items if the current row was part of the selection list - ltd.Store(); - - var selIds = GetSelection(); - - if (selIds.Contains(ltd.objectId)) - { - IList rows = FindRows(selIds); - - Undo.RecordObjects(rows.Select(r => ((SerializedPropertyItem)r).GetData().serializedObject.targetObject).ToArray(), "Modify Multiple Properties"); - - foreach (var r in rows) - { - if (r.id == args.item.id) - continue; - - var data = ((SerializedPropertyItem)r).GetData(); - - if (!IsEditable(data.serializedObject.targetObject)) - continue; - - if (column.copyDelegate != null) - column.copyDelegate(data.properties[columnIndex], prop); - else - DefaultDelegates.s_CopyDefault(data.properties[columnIndex], prop); - - data.Store(); - } - } - } - Profiler.EndSample(); - } - } - - private static bool IsEditable(Object target) - { - return ((target.hideFlags & HideFlags.NotEditable) == 0); - } - - protected override void BeforeRowsGUI() - { - var rows = GetRows(); - int first, last; - GetFirstAndLastVisibleRows(out first, out last); - - if (last != -1) - { - for (int i = first; i <= last; i++) - ((SerializedPropertyItem)rows[i]).GetData().Update(); - } - - // don't forget to refresh selected objects that got shoved off screen - var selected = FindRows(GetSelection()); - foreach (SerializedPropertyItem sel in selected) - sel.GetData().Update(); - - base.BeforeRowsGUI(); - } - - public void OnFilterGUI(Rect r) - { - EditorGUI.BeginChangeCheck(); - - float fullWidth = r.width; - float toggleWidth = 16; - - r.width = toggleWidth; - m_bFilterSelection = EditorGUI.Toggle(r, m_bFilterSelection); - r.x += toggleWidth; - r.width = GUI.skin.label.CalcSize(SerializedPropertyTreeView.Styles.filterSelection).x; - EditorGUI.LabelField(r, SerializedPropertyTreeView.Styles.filterSelection); - - r.width = Mathf.Min(fullWidth - (r.x + r.width), 300); - r.x = fullWidth - r.width + 10; - - for (int i = 0; i < multiColumnHeader.state.columns.Length; i++) - { - if (!IsColumnVisible(i)) - continue; - - Column c = Col(i); - - if (c.filter != null && c.filter.GetType().Equals(typeof(SerializedPropertyFilters.Name))) - { - c.filter.OnGUI(r); - } - } - - if (EditorGUI.EndChangeCheck()) - Reload(); - } - - protected override void SelectionChanged(IList selectedIds) - { - Selection.instanceIDs = selectedIds.ToArray(); - } - - protected override void KeyEvent() - { - if (Event.current.type != EventType.KeyDown) - return; - - // We always focus as this callback only fires when the name column is selected. - // Tabbing through the property columns never goes through here. - // Also note that we're not capturing the KeyCode Tab. There are 2 tab events, - // one for the keycode, and one for the character code. The keycode comes first, - // so if we change the focus based on the keycode, we never get the second character code - // event as the treeview loses focus and doesn't fire the callback. The second tab event - // then gets handled as an ordinary tab, leading to a double tab. - if (Event.current.character == '\t') - { - GUI.FocusControl(Styles.focusHelper); - Event.current.Use(); - } - } - - void OnVisibleColumnChanged(MultiColumnHeader header) - { - Reload(); - } - - void OnSortingChanged(MultiColumnHeader multiColumnHeader) - { - var rows = GetRows(); - Sort(rows, multiColumnHeader.sortedColumnIndex); - } - - void Sort(IList rows, int sortIdx) - { - Debug.Assert(sortIdx >= 0); - - bool ascend = multiColumnHeader.IsSortedAscending(sortIdx); - var comp = Col(sortIdx).compareDelegate; - var myRows = rows as List; - - System.Comparison sortAscend, sortDescend; - if (comp == null) - { - return; - } - else if (comp == DefaultDelegates.s_CompareName) // special case for sorting by the object name - { - sortAscend = (TreeViewItem lhs, TreeViewItem rhs) => - { - return EditorUtility.NaturalCompare(((SerializedPropertyItem)lhs).GetData().name, ((SerializedPropertyItem)rhs).GetData().name); - }; - sortDescend = (TreeViewItem lhs, TreeViewItem rhs) => - { - return -EditorUtility.NaturalCompare(((SerializedPropertyItem)lhs).GetData().name, ((SerializedPropertyItem)rhs).GetData().name); - }; - } - else - { - sortAscend = (TreeViewItem lhs, TreeViewItem rhs) => - { - return comp(((SerializedPropertyItem)lhs).GetData().properties[sortIdx], ((SerializedPropertyItem)rhs).GetData().properties[sortIdx]); - }; - sortDescend = (TreeViewItem lhs, TreeViewItem rhs) => - { - return -comp(((SerializedPropertyItem)lhs).GetData().properties[sortIdx], ((SerializedPropertyItem)rhs).GetData().properties[sortIdx]); - }; - } - - myRows.Sort(ascend ? sortAscend : sortDescend); - } - - IEnumerable Filter(IEnumerable rows) - { - var tmp = rows; - int cnt = m_ColumnsInternal.Length; - for (int i = 0; i < cnt; i++) - { - if (!IsColumnVisible(i)) - continue; - - Column c = Col(i); - int idx = i; - if (c.filter != null) - { - if (!c.filter.Active()) - continue; - - if (c.filter.GetType().Equals(typeof(SerializedPropertyFilters.Name))) - { - var f = (SerializedPropertyFilters.Name)c.filter; - tmp = tmp.Where((TreeViewItem item) => { return f.Filter(((SerializedPropertyItem)item).GetData().name); }); - } - else - { - tmp = tmp.Where((TreeViewItem item) => { return c.filter.Filter(((SerializedPropertyItem)item).GetData().properties[idx]); }); - } - } - } - - return tmp; - } - - private bool IsColumnVisible(int idx) - { - for (int i = 0; i < multiColumnHeader.state.visibleColumns.Length; i++) - if (multiColumnHeader.state.visibleColumns[i] == idx) - return true; - - return false; - } - - // casting helper - private Column Col(int idx) { return (Column)multiColumnHeader.state.columns[idx]; } - } -} diff --git a/Editor/Mono/Settings.cs b/Editor/Mono/Settings.cs deleted file mode 100644 index e5d8947d4f..0000000000 --- a/Editor/Mono/Settings.cs +++ /dev/null @@ -1,451 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using System; -using System.Globalization; -using System.Linq; - -namespace UnityEditor -{ - internal interface IPrefType - { - string ToUniqueString(); - void FromUniqueString(string sstr); - void Load(); - } - - internal class PrefColor : IPrefType - { - string m_Name; - Color m_Color; - Color m_DefaultColor; - - bool m_SeparateColors; - Color m_OptionalDarkColor; - Color m_OptionalDarkDefaultColor; - - bool m_Loaded; - - public PrefColor() - { - m_Loaded = true; - } - - public PrefColor(string name, float defaultRed, float defaultGreen, float defaultBlue, float defaultAlpha) - { - this.m_Name = name; - this.m_Color = this.m_DefaultColor = new Color(defaultRed, defaultGreen, defaultBlue, defaultAlpha); - this.m_SeparateColors = false; - this.m_OptionalDarkColor = this.m_OptionalDarkDefaultColor = Color.clear; - Settings.Add(this); - m_Loaded = false; - } - - public PrefColor(string name, float defaultRed, float defaultGreen, float defaultBlue, float defaultAlpha, float defaultRed2, float defaultGreen2, float defaultBlue2, float defaultAlpha2) - { - this.m_Name = name; - this.m_Color = this.m_DefaultColor = new Color(defaultRed, defaultGreen, defaultBlue, defaultAlpha); - this.m_SeparateColors = true; - this.m_OptionalDarkColor = this.m_OptionalDarkDefaultColor = new Color(defaultRed2, defaultGreen2, defaultBlue2, defaultAlpha2); - Settings.Add(this); - m_Loaded = false; - } - - public void Load() - { - if (m_Loaded) - return; - - m_Loaded = true; - - PrefColor pk = Settings.Get(m_Name, this); - this.m_Name = pk.m_Name; - this.m_Color = pk.m_Color; - this.m_SeparateColors = pk.m_SeparateColors; - this.m_OptionalDarkColor = pk.m_OptionalDarkColor; - } - - public Color Color - { - get - { - Load(); - - if (m_SeparateColors && EditorGUIUtility.isProSkin) - return m_OptionalDarkColor; - - return m_Color; - } - set - { - Load(); - - if (m_SeparateColors && EditorGUIUtility.isProSkin) - m_OptionalDarkColor = value; - else - m_Color = value; - } - } - public string Name { get { Load(); return m_Name; } } - - public static implicit operator Color(PrefColor pcolor) { return pcolor.Color; } - - public string ToUniqueString() - { - Load(); - - if (m_SeparateColors) - return String.Format(System.Globalization.CultureInfo.InvariantCulture, "{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); - - return String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0};{1};{2};{3};{4}", m_Name, m_Color.r, m_Color.g, m_Color.b, m_Color.a); - } - - public void FromUniqueString(string s) - { - Load(); - - string[] split = s.Split(';'); - - // PrefColor with a single color should have 5 substrings. - // PrefColor with separate colors should have 9 substrings. - if (split.Length != 5 && split.Length != 9) - { - Debug.LogError("Parsing PrefColor failed"); - return; - } - - m_Name = split[0]; - split[1] = split[1].Replace(',', '.'); - split[2] = split[2].Replace(',', '.'); - split[3] = split[3].Replace(',', '.'); - split[4] = split[4].Replace(',', '.'); - float r, g, b, a; - bool success = float.TryParse(split[1], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out r); - success &= float.TryParse(split[2], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out g); - success &= float.TryParse(split[3], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out b); - success &= float.TryParse(split[4], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out a); - - if (success) - { - m_Color = new Color(r, g, b, a); - } - else - { - Debug.LogError("Parsing PrefColor failed"); - } - - if (split.Length == 9) - { - m_SeparateColors = true; - - split[5] = split[5].Replace(',', '.'); - split[6] = split[6].Replace(',', '.'); - split[7] = split[7].Replace(',', '.'); - split[8] = split[8].Replace(',', '.'); - success = float.TryParse(split[5], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out r); - success &= float.TryParse(split[6], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out g); - success &= float.TryParse(split[7], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out b); - success &= float.TryParse(split[8], NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out a); - - if (success) - { - m_OptionalDarkColor = new Color(r, g, b, a); - } - else - { - Debug.LogError("Parsing PrefColor failed"); - } - } - else - { - m_SeparateColors = false; - m_OptionalDarkColor = Color.clear; - } - } - - internal void ResetToDefault() - { - Load(); - m_Color = m_DefaultColor; - m_OptionalDarkColor = m_OptionalDarkDefaultColor; - } - } - - internal class PrefKey : IPrefType - { - bool m_Loaded; - - public PrefKey() { m_Loaded = true; } - - public PrefKey(string name, string shortcut) - { - this.m_name = name; - this.m_Shortcut = shortcut; - this.m_DefaultShortcut = shortcut; - Settings.Add(this); - m_Loaded = false; - } - - public void Load() - { - if (m_Loaded) - return; - - m_Loaded = true; - - this.m_event = Event.KeyboardEvent(m_Shortcut); - PrefKey pk = Settings.Get(m_name, this); - this.m_name = pk.Name; - this.m_event = pk.KeyboardEvent; - } - - public static implicit operator Event(PrefKey pkey) { pkey.Load(); return pkey.m_event; } - - public string Name { get { Load(); return m_name; } } - - public Event KeyboardEvent - { - get { Load(); return m_event; } - set { Load(); m_event = value; } - } - - private string m_name; - private Event m_event; - private string m_Shortcut; - private string m_DefaultShortcut; - - public string ToUniqueString() - { - Load(); - string s = m_name + ";" + (m_event.alt ? "&" : "") + (m_event.command ? "%" : "") + (m_event.shift ? "#" : "") + (m_event.control ? "^" : "") + m_event.keyCode; - return s; - } - - public bool activated - { - get - { - Load(); - return Event.current.Equals((Event)this) && !GUIUtility.textFieldInput; - } - } - - - public void FromUniqueString(string s) - { - Load(); - int i = s.IndexOf(";"); - if (i < 0) - { - Debug.LogError("Malformed string in Keyboard preferences"); - return; - } - m_name = s.Substring(0, i); - m_event = Event.KeyboardEvent(s.Substring(i + 1)); - } - - internal void ResetToDefault() - { - Load(); - m_event = Event.KeyboardEvent(m_DefaultShortcut); - } - } - - - internal class Settings - { - static List m_AddedPrefs = new List(); - static SortedList m_Prefs = new SortedList(); - - static internal void Add(IPrefType value) - { - m_AddedPrefs.Add(value); - } - - static internal T Get(string name, T defaultValue) - where T : IPrefType, new() - { - Load(); - - if (defaultValue == null) - throw new System.ArgumentException("default can not be null", "defaultValue"); - if (m_Prefs.ContainsKey(name)) - return (T)m_Prefs[name]; - else - { - string sstr = EditorPrefs.GetString(name, ""); - if (sstr == "") - { - Set(name, defaultValue); - return defaultValue; - } - else - { - defaultValue.FromUniqueString(sstr); - Set(name, defaultValue); - return defaultValue; - } - } - } - - static internal void Set(string name, T value) - where T : IPrefType - { - Load(); - - EditorPrefs.SetString(name, value.ToUniqueString()); - m_Prefs[name] = value; - } - - static internal IEnumerable> Prefs() - where T : IPrefType - { - Load(); - - foreach (KeyValuePair kvp in m_Prefs) - { - if (kvp.Value is T) - yield return new KeyValuePair(kvp.Key, (T)kvp.Value); - } - } - - static void Load() - { - if (!m_AddedPrefs.Any()) - return; - - List loadPrefs = new List(m_AddedPrefs); - m_AddedPrefs.Clear(); - - foreach (IPrefType pref in loadPrefs) - pref.Load(); - } - } - - internal class SavedInt - { - int m_Value; - string m_Name; - bool m_Loaded; - - public SavedInt(string name, int value) - { - m_Name = name; - m_Loaded = false; - m_Value = value; - } - - private void Load() - { - if (m_Loaded) - return; - - m_Loaded = true; - m_Value = EditorPrefs.GetInt(m_Name, m_Value); - } - - public int value - { - get { Load(); return m_Value; } - set - { - Load(); - if (m_Value == value) - return; - m_Value = value; - EditorPrefs.SetInt(m_Name, value); - } - } - - public static implicit operator int(SavedInt s) - { - return s.value; - } - } - - internal class SavedFloat - { - float m_Value; - string m_Name; - bool m_Loaded; - - public SavedFloat(string name, float value) - { - m_Name = name; - m_Loaded = false; - m_Value = value; - } - - private void Load() - { - if (m_Loaded) - return; - - m_Loaded = true; - m_Value = EditorPrefs.GetFloat(m_Name, m_Value); - } - - public float value - { - get { Load(); return m_Value; } - set - { - Load(); - if (m_Value == value) - return; - m_Value = value; - EditorPrefs.SetFloat(m_Name, value); - } - } - - public static implicit operator float(SavedFloat s) - { - return s.value; - } - } - - internal class SavedBool - { - bool m_Value; - string m_Name; - bool m_Loaded; - - public SavedBool(string name, bool value) - { - m_Name = name; - m_Loaded = false; - m_Value = value; - } - - private void Load() - { - if (m_Loaded) - return; - - m_Loaded = true; - m_Value = EditorPrefs.GetBool(m_Name, m_Value); - } - - public bool value - { - get { Load(); return m_Value; } - set - { - Load(); - if (m_Value == value) - return; - m_Value = value; - EditorPrefs.SetBool(m_Name, value); - } - } - - public static implicit operator bool(SavedBool s) - { - return s.value; - } - } -} diff --git a/Editor/Mono/SettingsWindow/FogEditor.cs b/Editor/Mono/SettingsWindow/FogEditor.cs deleted file mode 100644 index 34e8ac7a75..0000000000 --- a/Editor/Mono/SettingsWindow/FogEditor.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(RenderSettings))] - internal class FogEditor : Editor - { - internal class Styles - { - 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."); - 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."); - public static readonly GUIContent FogLinearStart = EditorGUIUtility.TrTextContent("Start", "Controls the distance from the camera where the fog will start in the Scene."); - public static readonly GUIContent FogLinearEnd = EditorGUIUtility.TrTextContent("End", "Controls the distance from the camera where the fog will completely obscure objects in the Scene."); - public static readonly GUIContent FogEnable = EditorGUIUtility.TrTextContent("Fog", "Specifies whether fog is used in the Scene or not."); - public static readonly GUIContent FogColor = EditorGUIUtility.TrTextContent("Color", "Controls the color of that fog drawn in the Scene."); - 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."); - } - - protected SerializedProperty m_Fog; - protected SerializedProperty m_FogColor; - protected SerializedProperty m_FogMode; - protected SerializedProperty m_FogDensity; - protected SerializedProperty m_LinearFogStart; - protected SerializedProperty m_LinearFogEnd; - - public virtual void OnEnable() - { - m_Fog = serializedObject.FindProperty("m_Fog"); - m_FogColor = serializedObject.FindProperty("m_FogColor"); - m_FogMode = serializedObject.FindProperty("m_FogMode"); - m_FogDensity = serializedObject.FindProperty("m_FogDensity"); - m_LinearFogStart = serializedObject.FindProperty("m_LinearFogStart"); - m_LinearFogEnd = serializedObject.FindProperty("m_LinearFogEnd"); - } - - public virtual void OnDisable() {} - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_Fog, Styles.FogEnable); - if (m_Fog.boolValue) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_FogColor, Styles.FogColor); - EditorGUILayout.PropertyField(m_FogMode, Styles.FogMode); - - if ((FogMode)m_FogMode.intValue != FogMode.Linear) - { - EditorGUILayout.PropertyField(m_FogDensity, Styles.FogDensity); - } - else - { - EditorGUILayout.PropertyField(m_LinearFogStart, Styles.FogLinearStart); - EditorGUILayout.PropertyField(m_LinearFogEnd, Styles.FogLinearEnd); - } - - if (SceneView.IsUsingDeferredRenderingPath()) - EditorGUILayout.HelpBox(Styles.FogWarning.text, MessageType.Info); - - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs b/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs deleted file mode 100644 index 8b30e40b47..0000000000 --- a/Editor/Mono/SettingsWindow/GraphicsSettingsEditors.cs +++ /dev/null @@ -1,595 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor.Build; -using UnityEngine.Experimental.Rendering; -using UnityEngine.Rendering; -using EditorGraphicsSettings = UnityEditor.Rendering.EditorGraphicsSettings; -using TierSettings = UnityEditor.Rendering.TierSettings; -using GraphicsTier = UnityEngine.Rendering.GraphicsTier; -using ShaderQuality = UnityEditor.Rendering.ShaderQuality; - -// these are smallish editor's we use for GraphicsSettings editing - -namespace UnityEditor -{ - // - // builtin shaders - // - - internal partial class GraphicsSettingsWindow - { - internal class BuiltinShaderSettings - { - internal enum BuiltinShaderMode - { - None = 0, - Builtin, - Custom - } - - readonly SerializedProperty m_Mode; - readonly SerializedProperty m_Shader; - readonly GUIContent m_Label; - - internal BuiltinShaderSettings(string label, string name, SerializedObject serializedObject) - { - m_Mode = serializedObject.FindProperty(name + ".m_Mode"); - m_Shader = serializedObject.FindProperty(name + ".m_Shader"); - m_Label = EditorGUIUtility.TextContent(label); - } - - internal void DoGUI() - { - EditorGUILayout.PropertyField(m_Mode, m_Label); - if (m_Mode.intValue == (int)BuiltinShaderMode.Custom) - EditorGUILayout.PropertyField(m_Shader); - } - } - - internal class BuiltinShadersEditor : Editor - { - BuiltinShaderSettings m_Deferred; - BuiltinShaderSettings m_DeferredReflections; - BuiltinShaderSettings m_LegacyDeferred; - BuiltinShaderSettings m_ScreenSpaceShadows; - BuiltinShaderSettings m_DepthNormals; - BuiltinShaderSettings m_MotionVectors; - BuiltinShaderSettings m_LightHalo; - BuiltinShaderSettings m_LensFlare; - - string deferredString { get { return LocalizationDatabase.GetLocalizedString("Deferred|Shader used for Deferred Shading."); } } - string deferredReflString { get { return LocalizationDatabase.GetLocalizedString("Deferred Reflections|Shader used for Deferred reflection probes."); } } - string legacyDeferredString { get { return LocalizationDatabase.GetLocalizedString("Legacy Deferred|Shader used for Legacy (light prepass) Deferred Lighting."); } } - string screenShadowsString { get { return LocalizationDatabase.GetLocalizedString("Screen Space Shadows|Shader used for screen-space cascaded shadows."); } } - string depthNormalsString { get { return LocalizationDatabase.GetLocalizedString("Depth Normals|Shader used for depth and normals texture when enabled on a Camera."); } } - string motionVectorsString { get { return LocalizationDatabase.GetLocalizedString("Motion Vectors|Shader for generation of Motion Vectors when the rendering camera has renderMotionVectors set to true."); } } - string lightHaloString { get { return LocalizationDatabase.GetLocalizedString("Light Halo|Default Shader used for light halos."); } } - string lensFlareString { get { return LocalizationDatabase.GetLocalizedString("Lens Flare|Default Shader used for lens flares."); } } - - public void OnEnable() - { - m_Deferred = new BuiltinShaderSettings(deferredString, "m_Deferred", serializedObject); - m_DeferredReflections = new BuiltinShaderSettings(deferredReflString, "m_DeferredReflections", serializedObject); - m_LegacyDeferred = new BuiltinShaderSettings(legacyDeferredString, "m_LegacyDeferred", serializedObject); - m_ScreenSpaceShadows = new BuiltinShaderSettings(screenShadowsString, "m_ScreenSpaceShadows", serializedObject); - m_DepthNormals = new BuiltinShaderSettings(depthNormalsString, "m_DepthNormals", serializedObject); - m_MotionVectors = new BuiltinShaderSettings(motionVectorsString, "m_MotionVectors", serializedObject); - m_LightHalo = new BuiltinShaderSettings(lightHaloString, "m_LightHalo", serializedObject); - m_LensFlare = new BuiltinShaderSettings(lensFlareString, "m_LensFlare", serializedObject); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - m_Deferred.DoGUI(); - - // deferred reflections being off affects forward vs deferred style probe rendering; - // need to reload shaders for new platform macro to live update - EditorGUI.BeginChangeCheck(); - m_DeferredReflections.DoGUI(); - if (EditorGUI.EndChangeCheck()) - ShaderUtil.ReloadAllShaders(); - - m_LegacyDeferred.DoGUI(); - m_ScreenSpaceShadows.DoGUI(); - m_DepthNormals.DoGUI(); - m_MotionVectors.DoGUI(); - m_LightHalo.DoGUI(); - m_LensFlare.DoGUI(); - - serializedObject.ApplyModifiedProperties(); - } - } - } - - - // - // always included shaders - // - - - internal partial class GraphicsSettingsWindow - { - internal class AlwaysIncludedShadersEditor : Editor - { - SerializedProperty m_AlwaysIncludedShaders; - - public void OnEnable() - { - m_AlwaysIncludedShaders = serializedObject.FindProperty("m_AlwaysIncludedShaders"); - m_AlwaysIncludedShaders.isExpanded = true; - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_AlwaysIncludedShaders, true); - - serializedObject.ApplyModifiedProperties(); - } - } - } - - - // - // shader stripping - // - - - internal partial class GraphicsSettingsWindow - { - internal class ShaderStrippingEditor : Editor - { - SerializedProperty m_LightmapStripping; - SerializedProperty m_LightmapKeepPlain; - SerializedProperty m_LightmapKeepDirCombined; - SerializedProperty m_LightmapKeepDynamicPlain; - SerializedProperty m_LightmapKeepDynamicDirCombined; - SerializedProperty m_LightmapKeepShadowMask; - SerializedProperty m_LightmapKeepSubtractive; - SerializedProperty m_FogStripping; - SerializedProperty m_FogKeepLinear; - SerializedProperty m_FogKeepExp; - SerializedProperty m_FogKeepExp2; - SerializedProperty m_InstancingStripping; - - public void OnEnable() - { - m_LightmapStripping = serializedObject.FindProperty("m_LightmapStripping"); - m_LightmapKeepPlain = serializedObject.FindProperty("m_LightmapKeepPlain"); - m_LightmapKeepDirCombined = serializedObject.FindProperty("m_LightmapKeepDirCombined"); - m_LightmapKeepDynamicPlain = serializedObject.FindProperty("m_LightmapKeepDynamicPlain"); - m_LightmapKeepDynamicDirCombined = serializedObject.FindProperty("m_LightmapKeepDynamicDirCombined"); - m_LightmapKeepShadowMask = serializedObject.FindProperty("m_LightmapKeepShadowMask"); - m_LightmapKeepSubtractive = serializedObject.FindProperty("m_LightmapKeepSubtractive"); - m_FogStripping = serializedObject.FindProperty("m_FogStripping"); - m_FogKeepLinear = serializedObject.FindProperty("m_FogKeepLinear"); - m_FogKeepExp = serializedObject.FindProperty("m_FogKeepExp"); - m_FogKeepExp2 = serializedObject.FindProperty("m_FogKeepExp2"); - m_InstancingStripping = serializedObject.FindProperty("m_InstancingStripping"); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - bool calcLightmapStripping = false, calcFogStripping = false; - - EditorGUILayout.PropertyField(m_LightmapStripping, Styles.lightmapModes); - - if (m_LightmapStripping.intValue != 0) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_LightmapKeepPlain, Styles.lightmapPlain); - EditorGUILayout.PropertyField(m_LightmapKeepDirCombined, Styles.lightmapDirCombined); - EditorGUILayout.PropertyField(m_LightmapKeepDynamicPlain, Styles.lightmapDynamicPlain); - EditorGUILayout.PropertyField(m_LightmapKeepDynamicDirCombined, Styles.lightmapDynamicDirCombined); - EditorGUILayout.PropertyField(m_LightmapKeepShadowMask, Styles.lightmapKeepShadowMask); - EditorGUILayout.PropertyField(m_LightmapKeepSubtractive, Styles.lightmapKeepSubtractive); - EditorGUILayout.Space(); - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel(GUIContent.Temp(" "), EditorStyles.miniButton); - - if (GUILayout.Button(Styles.lightmapFromScene, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - calcLightmapStripping = true; - - EditorGUILayout.EndHorizontal(); - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - - EditorGUILayout.PropertyField(m_FogStripping, Styles.fogModes); - if (m_FogStripping.intValue != 0) - { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_FogKeepLinear, Styles.fogLinear); - EditorGUILayout.PropertyField(m_FogKeepExp, Styles.fogExp); - EditorGUILayout.PropertyField(m_FogKeepExp2, Styles.fogExp2); - EditorGUILayout.Space(); - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.PrefixLabel(GUIContent.Temp(" "), EditorStyles.miniButton); - - if (GUILayout.Button(Styles.fogFromScene, EditorStyles.miniButton, GUILayout.ExpandWidth(false))) - calcFogStripping = true; - - EditorGUILayout.EndHorizontal(); - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - - EditorGUILayout.PropertyField(m_InstancingStripping, Styles.instancingVariants); - - serializedObject.ApplyModifiedProperties(); - - // need to do these after ApplyModifiedProperties, since it changes their values from native code - if (calcLightmapStripping) - ShaderUtil.CalculateLightmapStrippingFromCurrentScene(); - if (calcFogStripping) - ShaderUtil.CalculateFogStrippingFromCurrentScene(); - } - - internal partial class Styles - { - public static readonly GUIContent shaderSettings = EditorGUIUtility.TrTextContent("Platform shader settings"); - public static readonly GUIContent builtinSettings = EditorGUIUtility.TrTextContent("Built-in shader settings"); - public static readonly GUIContent shaderPreloadSettings = EditorGUIUtility.TrTextContent("Shader preloading"); - - public static readonly GUIContent lightmapModes = EditorGUIUtility.TrTextContent("Lightmap Modes"); - public static readonly GUIContent lightmapPlain = EditorGUIUtility.TrTextContent("Baked Non-Directional", "Include support for baked non-directional lightmaps."); - public static readonly GUIContent lightmapDirCombined = EditorGUIUtility.TrTextContent("Baked Directional", "Include support for baked directional lightmaps."); - public static readonly GUIContent lightmapKeepShadowMask = EditorGUIUtility.TrTextContent("Baked Shadowmask", "Include support for baked shadow occlusion."); - public static readonly GUIContent lightmapKeepSubtractive = EditorGUIUtility.TrTextContent("Baked Subtractive", "Include support for baked substractive lightmaps."); - public static readonly GUIContent lightmapDynamicPlain = EditorGUIUtility.TrTextContent("Realtime Non-Directional", "Include support for realtime non-directional lightmaps."); - public static readonly GUIContent lightmapDynamicDirCombined = EditorGUIUtility.TrTextContent("Realtime Directional", "Include support for realtime directional lightmaps."); - public static readonly GUIContent lightmapFromScene = EditorGUIUtility.TrTextContent("Import From Current Scene", "Calculate lightmap modes used by the current scene."); - - public static readonly GUIContent fogModes = EditorGUIUtility.TrTextContent("Fog Modes"); - public static readonly GUIContent fogLinear = EditorGUIUtility.TrTextContent("Linear", "Include support for Linear fog."); - public static readonly GUIContent fogExp = EditorGUIUtility.TrTextContent("Exponential", "Include support for Exponential fog."); - public static readonly GUIContent fogExp2 = EditorGUIUtility.TrTextContent("Exponential Squared", "Include support for Exponential Squared fog."); - public static readonly GUIContent fogFromScene = EditorGUIUtility.TrTextContent("Import From Current Scene", "Calculate fog modes used by the current scene."); - - public static readonly GUIContent instancingVariants = EditorGUIUtility.TrTextContent("Instancing Variants"); - - public static readonly GUIContent shaderPreloadSave = EditorGUIUtility.TrTextContent("Save to asset...", "Save currently tracked shaders into a Shader Variant Manifest asset."); - public static readonly GUIContent shaderPreloadClear = EditorGUIUtility.TrTextContent("Clear", "Clear currently tracked shader variant information."); - } - } - } - - - // - // preloaded shaders - // - - - internal partial class GraphicsSettingsWindow - { - internal class ShaderPreloadEditor : Editor - { - SerializedProperty m_PreloadedShaders; - - public void OnEnable() - { - m_PreloadedShaders = serializedObject.FindProperty("m_PreloadedShaders"); - m_PreloadedShaders.isExpanded = true; - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - serializedObject.ApplyModifiedProperties(); - - EditorGUILayout.PropertyField(m_PreloadedShaders, true); - - EditorGUILayout.Space(); - GUILayout.Label( - string.Format("Currently tracked: {0} shaders {1} total variants", - ShaderUtil.GetCurrentShaderVariantCollectionShaderCount(), ShaderUtil.GetCurrentShaderVariantCollectionVariantCount() - ) - ); - - EditorGUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button(Styles.shaderPreloadSave, EditorStyles.miniButton)) - { - string message = "Save shader variant collection"; - string assetPath = EditorUtility.SaveFilePanelInProject("Save Shader Variant Collection", "NewShaderVariants", "shadervariants", message, ProjectWindowUtil.GetActiveFolderPath()); - if (!string.IsNullOrEmpty(assetPath)) - ShaderUtil.SaveCurrentShaderVariantCollection(assetPath); - GUIUtility.ExitGUI(); - } - if (GUILayout.Button(Styles.shaderPreloadClear, EditorStyles.miniButton)) - ShaderUtil.ClearCurrentShaderVariantCollection(); - EditorGUILayout.EndHorizontal(); - - serializedObject.ApplyModifiedProperties(); - } - - internal partial class Styles - { - public static readonly GUIContent shaderPreloadSave = EditorGUIUtility.TrTextContent("Save to asset...", "Save currently tracked shaders into a Shader Variant Manifest asset."); - public static readonly GUIContent shaderPreloadClear = EditorGUIUtility.TrTextContent("Clear", "Clear currently tracked shader variant information."); - } - } - } - - - // - // tier settings - // - - - internal partial class GraphicsSettingsWindow - { - internal class TierSettingsEditor : Editor - { - public bool verticalLayout = false; - - internal void OnFieldLabelsGUI(bool vertical) - { - if (!vertical) - EditorGUILayout.LabelField(Styles.standardShaderSettings, EditorStyles.boldLabel); - - bool usingSRP = GraphicsSettings.renderPipelineAsset != null; - if (!usingSRP) - { - EditorGUILayout.LabelField(Styles.standardShaderQuality); - EditorGUILayout.LabelField(Styles.reflectionProbeBoxProjection); - EditorGUILayout.LabelField(Styles.reflectionProbeBlending); - EditorGUILayout.LabelField(Styles.detailNormalMap); - EditorGUILayout.LabelField(Styles.semitransparentShadows); - } - - if (SupportedRenderingFeatures.active.rendererSupportsLightProbeProxyVolumes) - EditorGUILayout.LabelField(Styles.enableLPPV); - - if (!vertical) - { - EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel); - EditorGUILayout.LabelField(Styles.renderingSettings, EditorStyles.boldLabel); - } - - if (!usingSRP) - { - EditorGUILayout.LabelField(Styles.cascadedShadowMaps); - EditorGUILayout.LabelField(Styles.prefer32BitShadowMaps); - EditorGUILayout.LabelField(Styles.useHDR); - } - - EditorGUILayout.LabelField(Styles.hdrMode); - - if (!usingSRP) - { - EditorGUILayout.LabelField(Styles.renderingPath); - } - - if (SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime)) - EditorGUILayout.LabelField(Styles.realtimeGICPUUsage); - } - - // custom enum handling - internal partial class Styles - { - public static readonly GUIContent[] shaderQualityName = - { EditorGUIUtility.TrTextContent("Low"), EditorGUIUtility.TrTextContent("Medium"), EditorGUIUtility.TrTextContent("High") }; - public static readonly int[] shaderQualityValue = - { (int)ShaderQuality.Low, (int)ShaderQuality.Medium, (int)ShaderQuality.High }; - - public static readonly GUIContent[] renderingPathName = - { EditorGUIUtility.TrTextContent("Forward"), EditorGUIUtility.TrTextContent("Deferred"), EditorGUIUtility.TrTextContent("Legacy Vertex Lit"), EditorGUIUtility.TrTextContent("Legacy Deferred (light prepass)") }; - public static readonly int[] renderingPathValue = - { (int)RenderingPath.Forward, (int)RenderingPath.DeferredShading, (int)RenderingPath.VertexLit, (int)RenderingPath.DeferredLighting }; - - public static readonly GUIContent[] hdrModeName = - { EditorGUIUtility.TrTextContent("FP16"), EditorGUIUtility.TrTextContent("R11G11B10") }; - public static readonly int[] hdrModeValue = - { (int)CameraHDRMode.FP16, (int)CameraHDRMode.R11G11B10}; - - public static readonly GUIContent[] realtimeGICPUUsageName = - { EditorGUIUtility.TrTextContent("Low"), EditorGUIUtility.TrTextContent("Medium"), EditorGUIUtility.TrTextContent("High"), EditorGUIUtility.TrTextContent("Unlimited")}; - public static readonly int[] realtimeGICPUUsageValue = - { (int)RealtimeGICPUUsage.Low, (int)RealtimeGICPUUsage.Medium, (int)RealtimeGICPUUsage.High, (int)RealtimeGICPUUsage.Unlimited }; - } - - internal ShaderQuality ShaderQualityPopup(ShaderQuality sq) - { - return (ShaderQuality)EditorGUILayout.IntPopup((int)sq, Styles.shaderQualityName, Styles.shaderQualityValue); - } - - internal RenderingPath RenderingPathPopup(RenderingPath rp) - { - return (RenderingPath)EditorGUILayout.IntPopup((int)rp, Styles.renderingPathName, Styles.renderingPathValue); - } - - internal CameraHDRMode HDRModePopup(CameraHDRMode mode) - { - return (CameraHDRMode)EditorGUILayout.IntPopup((int)mode, Styles.hdrModeName, Styles.hdrModeValue); - } - - internal RealtimeGICPUUsage RealtimeGICPUUsagePopup(RealtimeGICPUUsage usage) - { - return (RealtimeGICPUUsage)EditorGUILayout.IntPopup((int)usage, Styles.realtimeGICPUUsageName, Styles.realtimeGICPUUsageValue); - } - - internal void OnTierGUI(BuildTargetGroup platform, GraphicsTier tier, bool vertical) - { - TierSettings ts = EditorGraphicsSettings.GetTierSettings(platform, tier); - - EditorGUI.BeginChangeCheck(); - - - if (!vertical) - EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel); - - bool usingSRP = GraphicsSettings.renderPipelineAsset != null; - if (!usingSRP) - { - ts.standardShaderQuality = ShaderQualityPopup(ts.standardShaderQuality); - ts.reflectionProbeBoxProjection = EditorGUILayout.Toggle(ts.reflectionProbeBoxProjection); - ts.reflectionProbeBlending = EditorGUILayout.Toggle(ts.reflectionProbeBlending); - ts.detailNormalMap = EditorGUILayout.Toggle(ts.detailNormalMap); - ts.semitransparentShadows = EditorGUILayout.Toggle(ts.semitransparentShadows); - } - - if (SupportedRenderingFeatures.active.rendererSupportsLightProbeProxyVolumes) - ts.enableLPPV = EditorGUILayout.Toggle(ts.enableLPPV); - - if (!vertical) - { - EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel); - EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel); - } - - if (!usingSRP) - { - ts.cascadedShadowMaps = EditorGUILayout.Toggle(ts.cascadedShadowMaps); - ts.prefer32BitShadowMaps = EditorGUILayout.Toggle(ts.prefer32BitShadowMaps); - ts.hdr = EditorGUILayout.Toggle(ts.hdr); - } - - ts.hdrMode = HDRModePopup(ts.hdrMode); - - if (!usingSRP) - ts.renderingPath = RenderingPathPopup(ts.renderingPath); - - if (SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime)) - ts.realtimeGICPUUsage = RealtimeGICPUUsagePopup(ts.realtimeGICPUUsage); - - if (EditorGUI.EndChangeCheck()) - { - // TODO: it should be doable in c# now as we "expose" GraphicsSettings anyway - EditorGraphicsSettings.RegisterUndoForGraphicsSettings(); - EditorGraphicsSettings.SetTierSettings(platform, tier, ts); - } - } - - internal void OnGuiHorizontal(BuildTargetGroup platform) - { - EditorGUILayout.BeginHorizontal(); - - EditorGUILayout.BeginVertical(); - EditorGUIUtility.labelWidth = 140; - EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel); - OnFieldLabelsGUI(false); - EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel); - EditorGUILayout.LabelField(Styles.autoSettings, EditorStyles.boldLabel); - EditorGUILayout.EndVertical(); - - EditorGUIUtility.labelWidth = 50; - foreach (GraphicsTier tier in Enum.GetValues(typeof(GraphicsTier))) - { - bool autoSettings = EditorGraphicsSettings.AreTierSettingsAutomatic(platform, tier); - - EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField(Styles.tierName[(int)tier], EditorStyles.boldLabel); - using (new EditorGUI.DisabledScope(autoSettings)) - OnTierGUI(platform, tier, false); - - EditorGUILayout.LabelField(Styles.empty, EditorStyles.boldLabel); - EditorGUI.BeginChangeCheck(); - autoSettings = EditorGUILayout.Toggle(autoSettings); - if (EditorGUI.EndChangeCheck()) - { - EditorGraphicsSettings.RegisterUndoForGraphicsSettings(); - EditorGraphicsSettings.MakeTierSettingsAutomatic(platform, tier, autoSettings); - EditorGraphicsSettings.OnUpdateTierSettingsImpl(platform, true); - } - EditorGUILayout.EndVertical(); - } - EditorGUIUtility.labelWidth = 0; - - EditorGUILayout.EndHorizontal(); - } - - internal void OnGuiVertical(BuildTargetGroup platform) - { - foreach (GraphicsTier tier in Enum.GetValues(typeof(GraphicsTier))) - { - bool autoSettings = EditorGraphicsSettings.AreTierSettingsAutomatic(platform, tier); - EditorGUI.BeginChangeCheck(); - { - GUILayout.BeginHorizontal(); - EditorGUIUtility.labelWidth = 80; - EditorGUILayout.LabelField(Styles.tierName[(int)tier], EditorStyles.boldLabel); - GUILayout.FlexibleSpace(); - EditorGUIUtility.labelWidth = 75; - autoSettings = EditorGUILayout.Toggle(Styles.autoSettings, autoSettings); - GUILayout.EndHorizontal(); - } - if (EditorGUI.EndChangeCheck()) - { - EditorGraphicsSettings.RegisterUndoForGraphicsSettings(); - EditorGraphicsSettings.MakeTierSettingsAutomatic(platform, tier, autoSettings); - EditorGraphicsSettings.OnUpdateTierSettingsImpl(platform, true); - } - - using (new EditorGUI.DisabledScope(autoSettings)) - { - EditorGUI.indentLevel++; - EditorGUILayout.BeginHorizontal(); - - EditorGUILayout.BeginVertical(); - EditorGUIUtility.labelWidth = 140; - OnFieldLabelsGUI(true); - EditorGUILayout.EndVertical(); - - EditorGUILayout.BeginVertical(); - EditorGUIUtility.labelWidth = 50; - OnTierGUI(platform, tier, true); - EditorGUILayout.EndVertical(); - - GUILayout.EndHorizontal(); - EditorGUI.indentLevel--; - } - } - EditorGUIUtility.labelWidth = 0; - } - - public override void OnInspectorGUI() - { - BuildPlatform[] validPlatforms = BuildPlatforms.instance.GetValidPlatforms().ToArray(); - BuildTargetGroup platform = validPlatforms[EditorGUILayout.BeginPlatformGrouping(validPlatforms, null, GUIStyle.none)].targetGroup; - - if (verticalLayout) OnGuiVertical(platform); - else OnGuiHorizontal(platform); - - EditorGUILayout.EndPlatformGrouping(); - } - - internal partial class Styles - { - public static readonly GUIContent[] tierName = - { EditorGUIUtility.TrTextContent("Low (Tier1)"), EditorGUIUtility.TrTextContent("Medium (Tier 2)"), EditorGUIUtility.TrTextContent("High (Tier 3)") }; - - public static readonly GUIContent empty = EditorGUIUtility.TextContent(""); - public static readonly GUIContent autoSettings = EditorGUIUtility.TrTextContent("Use Defaults"); - - public static readonly GUIContent standardShaderSettings = EditorGUIUtility.TrTextContent("Standard Shader"); - public static readonly GUIContent renderingSettings = EditorGUIUtility.TrTextContent("Rendering"); - - public static readonly GUIContent standardShaderQuality = EditorGUIUtility.TrTextContent("Standard Shader Quality"); - public static readonly GUIContent reflectionProbeBoxProjection = EditorGUIUtility.TrTextContent("Reflection Probes Box Projection"); - public static readonly GUIContent reflectionProbeBlending = EditorGUIUtility.TrTextContent("Reflection Probes Blending"); - public static readonly GUIContent detailNormalMap = EditorGUIUtility.TrTextContent("Detail Normal Map"); - public static readonly GUIContent cascadedShadowMaps = EditorGUIUtility.TrTextContent("Cascaded Shadows"); - public static readonly GUIContent prefer32BitShadowMaps = EditorGUIUtility.TrTextContent("Prefer 32 bit shadow maps"); - public static readonly GUIContent semitransparentShadows = EditorGUIUtility.TrTextContent("Enable Semitransparent Shadows"); - public static readonly GUIContent enableLPPV = EditorGUIUtility.TrTextContent("Enable Light Probe Proxy Volume"); - public static readonly GUIContent renderingPath = EditorGUIUtility.TrTextContent("Rendering Path"); - public static readonly GUIContent useHDR = EditorGUIUtility.TrTextContent("Use HDR"); - public static readonly GUIContent hdrMode = EditorGUIUtility.TrTextContent("HDR Mode"); - public static readonly GUIContent realtimeGICPUUsage = EditorGUIUtility.TrTextContent("Realtime Global Illumination 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."); - } - } - } -} diff --git a/Editor/Mono/SettingsWindow/LightingEditor.cs b/Editor/Mono/SettingsWindow/LightingEditor.cs deleted file mode 100644 index a232f232bf..0000000000 --- a/Editor/Mono/SettingsWindow/LightingEditor.cs +++ /dev/null @@ -1,277 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.Collections.Generic; -using UnityEngine.Rendering; -using UnityEngine.Experimental.Rendering; -using UnityEditor.AnimatedValues; -using System.Linq; - -namespace UnityEditor -{ - internal enum DefaultReflectionMode - { - FromSkybox = 0, - Custom - } - - internal class LightingEditor : Editor - { - internal static class Styles - { - static Styles() {} - - public static readonly GUIContent env_top = EditorGUIUtility.TrTextContent("Environment"); - 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."); - 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."); - public static readonly GUIContent env_amb_top = EditorGUIUtility.TrTextContent("Environment Lighting"); - 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."); - public static readonly GUIContent env_amb_int = EditorGUIUtility.TrTextContent("Intensity Multiplier", "Controls the brightness of the skybox lighting in the Scene."); - public static readonly GUIContent env_refl_top = EditorGUIUtility.TrTextContent("Environment Reflections"); - 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."); - 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."); - 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."); - 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."); - 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."); - public static readonly GUIContent skyboxWarning = EditorGUIUtility.TrTextContent("Shader of this material does not support skybox rendering."); - public static readonly GUIContent createLight = EditorGUIUtility.TrTextContent("Create Light"); - public static readonly GUIContent ambientUp = EditorGUIUtility.TrTextContent("Sky Color", "Controls the color of light emitted from the sky in the Scene."); - public static readonly GUIContent ambientMid = EditorGUIUtility.TrTextContent("Equator Color", "Controls the color of light emitted from the sides of the Scene."); - public static readonly GUIContent ambientDown = EditorGUIUtility.TrTextContent("Ground Color", "Controls the color of light emitted from the ground of the Scene."); - public static readonly GUIContent ambient = EditorGUIUtility.TrTextContent("Ambient Color", "Controls the color of the ambient light contributed to the Scene."); - public static readonly GUIContent customReflection = EditorGUIUtility.TrTextContent("Cubemap", "Specifies the custom cube map used for reflection effects in the Scene."); - public static readonly GUIContent AmbientLightingMode = EditorGUIUtility.TrTextContent("Ambient Mode", "Specifies the Global Illumination mode that should be used for handling ambient light in the Scene. Options are Realtime or Baked. This property is not editable unless both Realtime Global Illumination and Baked Global Illumination are enabled for the scene."); - - public static readonly GUIContent[] kFullAmbientSource = - { - EditorGUIUtility.TrTextContent("Skybox"), - EditorGUIUtility.TrTextContent("Gradient"), - EditorGUIUtility.TrTextContent("Color"), - }; - - public static readonly GUIContent[] AmbientLightingModes = - { - EditorGUIUtility.TrTextContent("Realtime"), - EditorGUIUtility.TrTextContent("Baked") - }; - - public static readonly int[] kFullAmbientSourceValues = { (int)AmbientMode.Skybox, (int)AmbientMode.Trilight, (int)AmbientMode.Flat }; - } - - protected SerializedProperty m_EnabledBakedGI; - protected SerializedProperty m_EnabledRealtimeGI; - - protected SerializedProperty m_Sun; - protected SerializedProperty m_AmbientSource; - protected SerializedProperty m_AmbientSkyColor; - protected SerializedProperty m_AmbientEquatorColor; - protected SerializedProperty m_AmbientGroundColor; - protected SerializedProperty m_AmbientIntensity; - protected SerializedProperty m_AmbientLightingMode; - - protected SerializedProperty m_ReflectionIntensity; - protected SerializedProperty m_ReflectionBounces; - - protected SerializedProperty m_SkyboxMaterial; - protected SerializedProperty m_DefaultReflectionMode; - protected SerializedProperty m_DefaultReflectionResolution; - protected SerializedProperty m_CustomReflection; - protected SerializedProperty m_ReflectionCompression; - - protected SerializedObject m_RenderSettings; - protected SerializedObject m_LightmapSettings; - - private bool m_bShowEnvironment; - private const string kShowEnvironment = "ShowEnvironment"; - - private void InitSettings() - { - m_RenderSettings = new SerializedObject(RenderSettings.GetRenderSettings()); - m_Sun = m_RenderSettings.FindProperty("m_Sun"); - m_AmbientSource = m_RenderSettings.FindProperty("m_AmbientMode"); - m_AmbientSkyColor = m_RenderSettings.FindProperty("m_AmbientSkyColor"); - m_AmbientEquatorColor = m_RenderSettings.FindProperty("m_AmbientEquatorColor"); - m_AmbientGroundColor = m_RenderSettings.FindProperty("m_AmbientGroundColor"); - m_AmbientIntensity = m_RenderSettings.FindProperty("m_AmbientIntensity"); - m_ReflectionIntensity = m_RenderSettings.FindProperty("m_ReflectionIntensity"); - m_ReflectionBounces = m_RenderSettings.FindProperty("m_ReflectionBounces"); - m_SkyboxMaterial = m_RenderSettings.FindProperty("m_SkyboxMaterial"); - m_DefaultReflectionMode = m_RenderSettings.FindProperty("m_DefaultReflectionMode"); - m_DefaultReflectionResolution = m_RenderSettings.FindProperty("m_DefaultReflectionResolution"); - m_CustomReflection = m_RenderSettings.FindProperty("m_CustomReflection"); - - m_LightmapSettings = new SerializedObject(LightmapEditorSettings.GetLightmapSettings()); - m_ReflectionCompression = m_LightmapSettings.FindProperty("m_LightmapEditorSettings.m_ReflectionCompression"); - m_AmbientLightingMode = m_LightmapSettings.FindProperty("m_GISettings.m_EnvironmentLightingMode"); - m_EnabledBakedGI = m_LightmapSettings.FindProperty("m_GISettings.m_EnableBakedLightmaps"); - m_EnabledRealtimeGI = m_LightmapSettings.FindProperty("m_GISettings.m_EnableRealtimeLightmaps"); - - m_bShowEnvironment = SessionState.GetBool(kShowEnvironment, true); - } - - public virtual void OnEnable() - { - InitSettings(); - } - - public virtual void OnDisable() - { - SessionState.SetBool(kShowEnvironment, m_bShowEnvironment); - } - - private void DrawGUI() - { - if (m_RenderSettings == null || m_RenderSettings.targetObject != RenderSettings.GetRenderSettings()) - { - InitSettings(); - } - - m_RenderSettings.UpdateIfRequiredOrScript(); - - Material skyboxMaterial = m_SkyboxMaterial.objectReferenceValue as Material; - - m_bShowEnvironment = EditorGUILayout.FoldoutTitlebar(m_bShowEnvironment, Styles.env_top, true); - - if (m_bShowEnvironment) - { - EditorGUI.indentLevel++; - - EditorGUILayout.PropertyField(m_SkyboxMaterial, Styles.env_skybox_mat); - if (skyboxMaterial && !EditorMaterialUtility.IsBackgroundMaterial(skyboxMaterial)) - { - EditorGUILayout.HelpBox(Styles.skyboxWarning.text, MessageType.Warning); - } - - EditorGUILayout.PropertyField(m_Sun, Styles.env_skybox_sun); - EditorGUILayout.Space(); - - EditorGUILayout.LabelField(Styles.env_amb_top); - EditorGUI.indentLevel++; - - EditorGUILayout.IntPopup(m_AmbientSource, Styles.kFullAmbientSource, Styles.kFullAmbientSourceValues, Styles.env_amb_src); - switch ((AmbientMode)m_AmbientSource.intValue) - { - case AmbientMode.Trilight: - { - EditorGUI.BeginChangeCheck(); - Color newValueUp = EditorGUILayout.ColorField(Styles.ambientUp, m_AmbientSkyColor.colorValue, true, false, true); - Color newValueMid = EditorGUILayout.ColorField(Styles.ambientMid, m_AmbientEquatorColor.colorValue, true, false, true); - Color newValueDown = EditorGUILayout.ColorField(Styles.ambientDown, m_AmbientGroundColor.colorValue, true, false, true); - if (EditorGUI.EndChangeCheck()) - { - m_AmbientSkyColor.colorValue = newValueUp; - m_AmbientEquatorColor.colorValue = newValueMid; - m_AmbientGroundColor.colorValue = newValueDown; - } - } - break; - - case AmbientMode.Flat: - { - EditorGUI.BeginChangeCheck(); - Color newValue = EditorGUILayout.ColorField(Styles.ambient, m_AmbientSkyColor.colorValue, true, false, true); - if (EditorGUI.EndChangeCheck()) - m_AmbientSkyColor.colorValue = newValue; - } - break; - - case AmbientMode.Skybox: - if (skyboxMaterial == null) - { - EditorGUI.BeginChangeCheck(); - Color newValue = EditorGUILayout.ColorField(Styles.ambient, m_AmbientSkyColor.colorValue, true, false, true); - if (EditorGUI.EndChangeCheck()) - m_AmbientSkyColor.colorValue = newValue; - } - else - { - // Ambient intensity - maximum is kEmissiveRGBMMax - EditorGUILayout.Slider(m_AmbientIntensity, 0.0F, 8.0F, Styles.env_amb_int); - } - break; - } - - // ambient GI - realtime / baked - bool realtimeGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Realtime); - bool bakedGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Baked); - - if ((m_EnabledBakedGI.boolValue || m_EnabledRealtimeGI.boolValue) && (bakedGISupported || realtimeGISupported)) - { - int[] modeVals = { 0, 1 }; - - if (m_EnabledBakedGI.boolValue && m_EnabledRealtimeGI.boolValue) - { - // if the user has selected the only state that is supported, then gray it out - using (new EditorGUI.DisabledScope(((m_AmbientLightingMode.intValue == 0) && realtimeGISupported && !bakedGISupported) || ((m_AmbientLightingMode.intValue == 1) && bakedGISupported && !realtimeGISupported))) - { - EditorGUILayout.IntPopup(m_AmbientLightingMode, Styles.AmbientLightingModes, modeVals, Styles.AmbientLightingMode); - } - - // if they have selected a state that isnt supported, show dialog, and still make the box editable - if (((m_AmbientLightingMode.intValue == 0) && !realtimeGISupported) || - ((m_AmbientLightingMode.intValue == 1) && !bakedGISupported)) - { - EditorGUILayout.HelpBox("The following mode is not supported and will fallback on " + (((m_AmbientLightingMode.intValue == 0) && !realtimeGISupported) ? "Baked" : "Realtime"), MessageType.Warning); - } - } - // Show "Baked" if precomputed GI is disabled and "Realtime" if baked GI is disabled (but we don't wanna show the box if the whole mode is not supported.) - else if ((m_EnabledBakedGI.boolValue && bakedGISupported) || (m_EnabledRealtimeGI.boolValue && realtimeGISupported)) - { - using (new EditorGUI.DisabledScope(true)) - { - EditorGUILayout.IntPopup(Styles.AmbientLightingMode, m_EnabledBakedGI.boolValue ? 1 : 0, Styles.AmbientLightingModes, modeVals); - } - } - } - - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - - EditorGUILayout.LabelField(Styles.env_refl_top); - EditorGUI.indentLevel++; - - EditorGUILayout.PropertyField(m_DefaultReflectionMode, Styles.env_refl_src); - - DefaultReflectionMode defReflectionMode = (DefaultReflectionMode)m_DefaultReflectionMode.intValue; - switch (defReflectionMode) - { - case DefaultReflectionMode.FromSkybox: - { - int[] reflectionResolutionValuesArray = null; - GUIContent[] reflectionResolutionTextArray = null; - ReflectionProbeEditor.GetResolutionArray(ref reflectionResolutionValuesArray, ref reflectionResolutionTextArray); - EditorGUILayout.IntPopup(m_DefaultReflectionResolution, reflectionResolutionTextArray, reflectionResolutionValuesArray, Styles.env_refl_res, GUILayout.MinWidth(40)); - } - break; - case DefaultReflectionMode.Custom: - EditorGUILayout.PropertyField(m_CustomReflection, Styles.customReflection); - break; - } - - EditorGUILayout.PropertyField(m_ReflectionCompression, Styles.env_refl_cmp); - EditorGUILayout.Slider(m_ReflectionIntensity, 0.0F, 1.0F, Styles.env_refl_int); - EditorGUILayout.IntSlider(m_ReflectionBounces, 1, 5, Styles.env_refl_bnc); - - EditorGUI.indentLevel--; - - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - - m_RenderSettings.ApplyModifiedProperties(); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - m_LightmapSettings.Update(); - - DrawGUI(); - - serializedObject.ApplyModifiedProperties(); - m_LightmapSettings.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/SettingsWindow/OtherRenderingEditor.cs b/Editor/Mono/SettingsWindow/OtherRenderingEditor.cs deleted file mode 100644 index b4f07afc1d..0000000000 --- a/Editor/Mono/SettingsWindow/OtherRenderingEditor.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - [CustomEditor(typeof(RenderSettings))] - internal class OtherRenderingEditor : Editor - { - internal static class Styles - { - public static readonly GUIContent HaloStrength = EditorGUIUtility.TrTextContent("Halo Strength", "Controls the visibility of the halo effect around lights in the Scene."); - public static readonly GUIContent HaloTexture = EditorGUIUtility.TrTextContent("Halo Texture", "Specifies the Texture used when drawing the halo effect around lights in the Scene"); - public static readonly GUIContent FlareStrength = EditorGUIUtility.TrTextContent("Flare Strength", "Controls the visibility of lens flares from lights in the Scene."); - public static readonly GUIContent FlareFadeSpeed = EditorGUIUtility.TrTextContent("Flare Fade Speed", "Controls the time over which lens flares fade from view after initially appearing."); - 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."); - } - - protected SerializedProperty m_HaloStrength; - protected SerializedProperty m_FlareStrength; - protected SerializedProperty m_FlareFadeSpeed; - protected SerializedProperty m_HaloTexture; - protected SerializedProperty m_SpotCookie; - - public virtual void OnEnable() - { - m_HaloStrength = serializedObject.FindProperty("m_HaloStrength"); - m_FlareStrength = serializedObject.FindProperty("m_FlareStrength"); - m_FlareFadeSpeed = serializedObject.FindProperty("m_FlareFadeSpeed"); - m_HaloTexture = serializedObject.FindProperty("m_HaloTexture"); - m_SpotCookie = serializedObject.FindProperty("m_SpotCookie"); - } - - public virtual void OnDisable() {} - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - EditorGUILayout.PropertyField(m_HaloTexture, Styles.HaloTexture); - EditorGUILayout.Slider(m_HaloStrength, 0.0f, 1.0f, Styles.HaloStrength); - - EditorGUILayout.PropertyField(m_FlareFadeSpeed, Styles.FlareFadeSpeed); - EditorGUILayout.Slider(m_FlareStrength, 0.0f, 1.0f, Styles.FlareStrength); - - EditorGUILayout.PropertyField(m_SpotCookie, Styles.SpotCookie); - - serializedObject.ApplyModifiedProperties(); - } - } -} diff --git a/Editor/Mono/ShaderUtil.bindings.cs b/Editor/Mono/ShaderUtil.bindings.cs deleted file mode 100644 index 08f080301c..0000000000 --- a/Editor/Mono/ShaderUtil.bindings.cs +++ /dev/null @@ -1,148 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEngine; -using System; -using System.Runtime.InteropServices; -using UnityEngine.Assertions; - -namespace UnityEditor -{ - [Serializable] - [RequiredByNativeCode] - [NativeHeader("Editor/Src/ShaderMenu.h")] - public struct ShaderInfo - { - [SerializeField] - [NativeName("name")] - internal string m_Name; - [SerializeField] - [NativeName("supported")] - internal bool m_Supported; - [SerializeField] - [NativeName("hasErrors")] - internal bool m_HasErrors; - - public string name - { - get { return m_Name; } - } - public bool supported - { - get { return m_Supported; } - } - public bool hasErrors - { - get { return m_HasErrors; } - } - } - - public class ShaderData - { - public class Subshader - { - internal ShaderData m_Data; - internal int m_SubshaderIndex; - - internal Subshader(ShaderData data, int subshaderIndex) - { - m_Data = data; - m_SubshaderIndex = subshaderIndex; - } - - internal Shader SourceShader { get { return m_Data.SourceShader; } } - - public int PassCount { get { return ShaderUtil.GetShaderTotalPassCount(m_Data.SourceShader, m_SubshaderIndex); } } - - public Pass GetPass(int passIndex) - { - if (passIndex < 0 || passIndex >= PassCount) - { - Debug.LogErrorFormat("Pass index is incorrect: {0}, shader {1} has {2} passes.", passIndex, SourceShader, PassCount); - return null; - } - - return new Pass(this, passIndex); - } - } - - public class Pass - { - Subshader m_Subshader; - int m_PassIndex; - - internal Pass(Subshader subshader, int passIndex) - { - m_Subshader = subshader; - m_PassIndex = passIndex; - } - - internal Shader SourceShader { get { return m_Subshader.m_Data.SourceShader; } } - internal int SubshaderIndex { get { return m_Subshader.m_SubshaderIndex; } } - - public string SourceCode { get { return ShaderUtil.GetShaderPassSourceCode(SourceShader, SubshaderIndex, m_PassIndex); } } - public string Name { get { return ShaderUtil.GetShaderPassName(SourceShader, SubshaderIndex, m_PassIndex); } } - } - - public int ActiveSubshaderIndex { get { return ShaderUtil.GetShaderActiveSubshaderIndex(SourceShader); } } - public int SubshaderCount { get { return ShaderUtil.GetShaderSubshaderCount(SourceShader); } } - - public Shader SourceShader { get; private set; } - - public Subshader ActiveSubshader - { - get - { - var index = ActiveSubshaderIndex; - if (index < 0 || index >= SubshaderCount) - return null; - - return new Subshader(this, index); - } - } - - internal ShaderData(Shader sourceShader) - { - Assert.IsNotNull(sourceShader); - this.SourceShader = sourceShader; - } - - public Subshader GetSubshader(int index) - { - if (index < 0 || index >= SubshaderCount) - { - Debug.LogErrorFormat("Subshader index is incorrect: {0}, shader {1} has {2} passes.", index, SourceShader, SubshaderCount); - return null; - } - - return new Subshader(this, index); - } - } - - [NativeHeader("Editor/Src/ShaderMenu.h")] - [NativeHeader("Editor/Src/ShaderData.h")] - public partial class ShaderUtil - { - [FreeFunction] - public static extern ShaderInfo[] GetAllShaderInfo(); - - public static ShaderData GetShaderData(Shader shader) - { - return new ShaderData(shader); - } - - [FreeFunction] - internal static extern string GetShaderPassSourceCode([NotNull] Shader shader, int subShaderIndex, int passId); - [FreeFunction] - internal static extern string GetShaderPassName([NotNull] Shader shader, int subShaderIndex, int passId); - [FreeFunction] - internal static extern int GetShaderActiveSubshaderIndex([NotNull] Shader shader); - [FreeFunction] - internal static extern int GetShaderSubshaderCount([NotNull] Shader shader); - [FreeFunction] - internal static extern int GetShaderTotalPassCount([NotNull] Shader shader, int subShaderIndex); - } -} diff --git a/Editor/Mono/ShapeEditor/ShapeEditor.cs b/Editor/Mono/ShapeEditor/ShapeEditor.cs deleted file mode 100644 index 800e2ab117..0000000000 --- a/Editor/Mono/ShapeEditor/ShapeEditor.cs +++ /dev/null @@ -1,1114 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEditor.U2D.Interface; -using UnityEngine; -using UnityEditorInternal; -using UnityEngine.U2D.Interface; -using UnityTexture2D = UnityEngine.Texture2D; - -namespace UnityEditor -{ - internal interface IShapeEditorFactory - { - ShapeEditor CreateShapeEditor(); - } - - internal class ShapeEditorFactory : IShapeEditorFactory - { - public ShapeEditor CreateShapeEditor() - { - return new ShapeEditor(new GUIUtilitySystem(), new EventSystem()); - } - } - - internal class ShapeEditor - { - public delegate float DistanceToControl(Vector3 pos, Quaternion rotation, float handleSize); - - internal enum SelectionType { Normal, Additive, Subtractive } - internal enum Tool { Edit, Create, Break } - internal enum TangentMode { Linear, Continuous, Broken } - - // --- To use this class in your editor, you need to implement these: (see ShapeEditorTests for example) - // --- Data - public Func GetPointPosition = i => Vector3.zero; - public Action SetPointPosition = (i, p) => {}; - public Func GetPointLTangent = i => Vector3.zero; - public Action SetPointLTangent = (i, p) => {}; - public Func GetPointRTangent = i => Vector3.zero; - public Action SetPointRTangent = (i, p) => {}; - public Func GetTangentMode = i => TangentMode.Linear; - public Action SetTangentMode = (i, m) => {}; - public Action InsertPointAt = (i, p) => {}; - public Action RemovePointAt = i => {}; - public Func GetPointsCount = () => 0; - // --- Transforms - public Func ScreenToLocal = i => i; - public Func LocalToScreen = i => i; - public Func LocalToWorldMatrix = () => Matrix4x4.identity; - // --- Distance functions - public Func DistanceToRectangle = () => HandleUtility.DistanceToRectangle; - public Func DistanceToDiamond = () => HandleUtility.DistanceToDiamond; - public Func DistanceToCircle = () => DistanceToCircleInternal; - // --- Other - public Action Repaint = () => {}; - public Action RecordUndo = () => {}; - public Func Snap = i => i; - public Action Frame = b => {}; - public Action OnPointClick = i => {}; - public Func OpenEnded = () => false; - public Func GetHandleSize = () => 5f; - // --- END - - public ITexture2D lineTexture { get; set; } - public int activePoint { get; set; } - public HashSet selectedPoints { get { return m_Selection.indices; } } - public bool inEditMode { get; set; } - public int activeEdge { get { return m_ActiveEdge; } set { m_ActiveEdge = value; } } - // Shape editor needs to reset its state on next OnSceneGUI. Reset can't be called immediately elsewhere, because we need to also reset local sceneview state like GUIUtility.keyboardControl - public bool delayedReset { set { m_DelayedReset = value; } } - - private ShapeEditorSelection m_Selection; - private Vector2 m_MousePositionLastMouseDown; - private int m_ActivePointOnLastMouseDown = -1; - private int m_NewPointIndex = -1; - private Vector3 m_EdgeDragStartMousePosition; - private Vector3 m_EdgeDragStartP0; - private Vector3 m_EdgeDragStartP1; - private bool m_NewPointDragFinished; - private int m_ActiveEdge = -1; - private bool m_DelayedReset = false; - private HashSet m_ShapeEditorListeners = new HashSet(); - private ShapeEditorRectSelectionTool m_RectSelectionTool; - - private int m_MouseClosestEdge = -1; - private float m_MouseClosestEdgeDist = float.MaxValue; - private int m_ShapeEditorRegisteredTo = 0; - private int m_ShapeEditorUpdateDone = 0; - - private static Color handleOutlineColor { get; set; } - private static Color handleFillColor { get; set; } - private Quaternion handleMatrixrotation { get { return Quaternion.LookRotation(handles.matrix.GetColumn(2), handles.matrix.GetColumn(1)); } } - - private IGUIUtility guiUtility { get; set; } - private IEventSystem eventSystem { get; set; } - private IEvent currentEvent { get; set; } - private IGL glSystem { get; set; } - private IHandles handles { get; set; } - - private Dictionary> m_DrawBatch; - private Vector3[][] m_EdgePoints; - - enum ColorEnum - { - EUnselected, - EUnselectedHovered, - ESelected, - ESelectedHovered - } - - private static readonly Color[] k_OutlineColor = new[] { - Color.gray, - Color.white, - new Color(34f / 255f, 171f / 255f, 1f), // #22abff - Color.white - }; - - static readonly Color[] k_FillColor = new[] - { - Color.white, - new Color(131f / 255f, 220f / 255f, 1f), // #83dcff - new Color(34f / 255f, 171f / 255f, 1f), // #22abff - new Color(34f / 255f, 171f / 255f, 1f) // #22abff - }; - private static readonly Color k_TangentColor = new Color(34f / 255f, 171f / 255f, 1f); // #22abff - private static readonly Color k_TangentColorAlternative = new Color(131f / 255f, 220f / 255f, 1f); // #83dcff - private const float k_EdgeHoverDistance = 9f; - private const float k_EdgeWidth = 2f; - private const float k_ActiveEdgeWidth = 6f; - private const float k_MinExistingPointDistanceForInsert = 20f; - private readonly int k_CreatorID; - private readonly int k_EdgeID; - private readonly int k_RightTangentID; - private readonly int k_LeftTangentID; - private const int k_BezierPatch = 40; - - class DrawBatchDataKey - { - public Color color { get; private set; } - public int glMode { get; private set; } - private int m_Hash; - - public DrawBatchDataKey(Color c , int mode) - { - color = c; - glMode = mode; - m_Hash = glMode ^ (color.GetHashCode() << 2); - } - - public override int GetHashCode() - { - return m_Hash; - } - - public override bool Equals(object obj) - { - return m_Hash == obj.GetHashCode(); - } - } - - public ShapeEditor(IGUIUtility gu, IEventSystem es) - { - m_Selection = new ShapeEditorSelection(this); - guiUtility = gu; - eventSystem = es; - k_CreatorID = guiUtility.GetPermanentControlID(); - k_EdgeID = guiUtility.GetPermanentControlID(); - k_RightTangentID = guiUtility.GetPermanentControlID(); - k_LeftTangentID = guiUtility.GetPermanentControlID(); - glSystem = GLSystem.GetSystem(); - handles = HandlesSystem.GetSystem(); - } - - public void SetRectSelectionTool(ShapeEditorRectSelectionTool sers) - { - if (m_RectSelectionTool != null) - { - m_RectSelectionTool.RectSelect -= SelectPointsInRect; - m_RectSelectionTool.ClearSelection -= ClearSelectedPoints; - } - m_RectSelectionTool = sers; - m_RectSelectionTool.RectSelect += SelectPointsInRect; - m_RectSelectionTool.ClearSelection += ClearSelectedPoints; - } - - public void OnDisable() - { - m_RectSelectionTool.RectSelect -= SelectPointsInRect; - m_RectSelectionTool.ClearSelection -= ClearSelectedPoints; - m_RectSelectionTool = null; - } - - private void PrepareDrawBatch() - { - if (currentEvent.type == EventType.Repaint) - { - m_DrawBatch = new Dictionary>(); - } - } - - private void DrawBatch() - { - if (currentEvent.type == EventType.Repaint) - { - HandleUtility.ApplyWireMaterial(); - glSystem.PushMatrix(); - glSystem.MultMatrix(handles.matrix); - foreach (var drawBatch in m_DrawBatch) - { - glSystem.Begin(drawBatch.Key.glMode); - glSystem.Color(drawBatch.Key.color); - foreach (var t in drawBatch.Value) - { - glSystem.Vertex(t); - } - glSystem.End(); - } - glSystem.PopMatrix(); - } - } - - List GetDrawBatchList(DrawBatchDataKey key) - { - List data = null; - if (!m_DrawBatch.ContainsKey(key)) - { - m_DrawBatch.Add(key, new List()); - } - data = m_DrawBatch[key]; - return data; - } - - public void OnGUI() - { - DelayedResetIfNecessary(); - currentEvent = eventSystem.current; - - if (currentEvent.type == EventType.MouseDown) - StoreMouseDownState(); - - var oldColor = handles.color; - var oldMatrix = handles.matrix; - handles.matrix = LocalToWorldMatrix(); - - PrepareDrawBatch(); - - Edges(); - - if (inEditMode) - { - Framing(); - Tangents(); - Points(); - } - - DrawBatch(); - - handles.color = oldColor; - handles.matrix = oldMatrix; - - OnShapeEditorUpdateDone(); - foreach (var se in m_ShapeEditorListeners) - se.OnShapeEditorUpdateDone(); - } - - private void Framing() - { - if (currentEvent.commandName == EventCommandNames.FrameSelected && m_Selection.Count > 0) - { - switch (currentEvent.type) - { - case EventType.ExecuteCommand: - Bounds bounds = new Bounds(GetPointPosition(selectedPoints.First()), Vector3.zero); - - foreach (var index in selectedPoints) - bounds.Encapsulate(GetPointPosition(index)); - - Frame(bounds); - goto case EventType.ValidateCommand; - case EventType.ValidateCommand: - currentEvent.Use(); - break; - } - } - } - - void PrepareEdgePointList() - { - if (m_EdgePoints == null) - { - var total = this.GetPointsCount(); - int loopCount = OpenEnded() ? total - 1 : total; - m_EdgePoints = new Vector3[loopCount][]; - int index = mod(total - 1, loopCount); - for (int loop = mod(index + 1, total); loop < total; index = loop, ++loop) - { - var position0 = this.GetPointPosition(index); - var position1 = this.GetPointPosition(loop); - if (GetTangentMode(index) == TangentMode.Linear && GetTangentMode(loop) == TangentMode.Linear) - { - m_EdgePoints[index] = new[] { position0, position1 }; - } - else - { - var tangent0 = GetPointRTangent(index) + position0; - var tangent1 = GetPointLTangent(loop) + position1; - m_EdgePoints[index] = handles.MakeBezierPoints(position0, position1, tangent0, tangent1, k_BezierPatch); - } - } - } - } - - float DistancePointEdge(Vector3 point, Vector3[] edge) - { - float result = float.MaxValue; - int index = edge.Length - 1; - for (int nextIndex = 0; nextIndex < edge.Length; index = nextIndex, nextIndex++) - { - float dist = HandleUtility.DistancePointLine(point, edge[index], edge[nextIndex]); - if (dist < result) - result = dist; - } - return result; - } - - private float GetMouseClosestEdgeDistance() - { - var mousePosition = ScreenToLocal(eventSystem.current.mousePosition); - var total = this.GetPointsCount(); - if (m_MouseClosestEdge == -1 && total > 0) - { - PrepareEdgePointList(); - m_MouseClosestEdgeDist = float.MaxValue; - - int loopCount = OpenEnded() ? total - 1 : total; - for (int loop = 0; loop < loopCount; loop++) - { - var dist = DistancePointEdge(mousePosition, m_EdgePoints[loop]); - if (dist < m_MouseClosestEdgeDist) - { - m_MouseClosestEdge = loop; - m_MouseClosestEdgeDist = dist; - } - } - } - - if (guiUtility.hotControl == k_CreatorID || guiUtility.hotControl == k_EdgeID) - return float.MinValue; - return m_MouseClosestEdgeDist; - } - - public void Edges() - { - var otherClosestEdgeDistance = float.MaxValue; - if (m_ShapeEditorListeners.Count > 0) - otherClosestEdgeDistance = (from se in m_ShapeEditorListeners select se.GetMouseClosestEdgeDistance()).Max(); - float edgeDistance = GetMouseClosestEdgeDistance(); - bool closestEdgeHighlight = EdgeDragModifiersActive() && edgeDistance < k_EdgeHoverDistance && edgeDistance < otherClosestEdgeDistance; - if (currentEvent.type == EventType.Repaint) - { - Color handlesOldColor = handles.color; - PrepareEdgePointList(); - - var total = this.GetPointsCount(); - int loopCount = OpenEnded() ? total - 1 : total; - - for (int loop = 0; loop < loopCount; loop++) - { - Color edgeColor = loop == m_ActiveEdge ? Color.yellow : Color.white; - float edgeWidth = loop == m_ActiveEdge || (m_MouseClosestEdge == loop && closestEdgeHighlight) ? k_ActiveEdgeWidth : k_EdgeWidth; - - handles.color = edgeColor; - handles.DrawAAPolyLine(lineTexture, edgeWidth, m_EdgePoints[loop]); - } - handles.color = handlesOldColor; - } - - if (inEditMode) - { - if (otherClosestEdgeDistance > edgeDistance) - { - var farEnoughFromExistingPoints = MouseDistanceToPoint(FindClosestPointToMouse()) > k_MinExistingPointDistanceForInsert; - var farEnoughtFromActiveTangents = MouseDistanceToClosestTangent() > k_MinExistingPointDistanceForInsert; - var farEnoughFromExisting = farEnoughFromExistingPoints && farEnoughtFromActiveTangents; - var hoveringEdge = m_MouseClosestEdgeDist < k_EdgeHoverDistance; - var handleEvent = hoveringEdge && farEnoughFromExisting && !m_RectSelectionTool.isSelecting; - - if (GUIUtility.hotControl == k_EdgeID || EdgeDragModifiersActive() && handleEvent) - HandleEdgeDragging(m_MouseClosestEdge); - else if (GUIUtility.hotControl == k_CreatorID || (currentEvent.modifiers == EventModifiers.None && handleEvent)) - HandlePointInsertToEdge(m_MouseClosestEdge, m_MouseClosestEdgeDist); - } - } - - if (guiUtility.hotControl != k_CreatorID && m_NewPointIndex != -1) - { - m_NewPointDragFinished = true; - guiUtility.keyboardControl = 0; - m_NewPointIndex = -1; - } - if (guiUtility.hotControl != k_EdgeID && m_ActiveEdge != -1) - { - m_ActiveEdge = -1; - } - } - - public void Tangents() - { - if (activePoint < 0 || m_Selection.Count > 1 || GetTangentMode(activePoint) == TangentMode.Linear) - return; - - var evt = eventSystem.current; - var p = this.GetPointPosition(activePoint); - var lt = this.GetPointLTangent(activePoint); - var rt = this.GetPointRTangent(activePoint); - - var isHot = (guiUtility.hotControl == k_RightTangentID || guiUtility.hotControl == k_LeftTangentID); - var allZero = lt.sqrMagnitude == 0 && rt.sqrMagnitude == 0; - - if (isHot || !allZero) - { - var m = this.GetTangentMode(activePoint); - var mouseDown = evt.GetTypeForControl(k_RightTangentID) == EventType.MouseDown || evt.GetTypeForControl(k_LeftTangentID) == EventType.MouseDown; - var mouseUp = evt.GetTypeForControl(k_RightTangentID) == EventType.MouseUp || evt.GetTypeForControl(k_LeftTangentID) == EventType.MouseUp; - - var nlt = DoTangent(p, p + lt, k_LeftTangentID, activePoint, k_TangentColor); - var nrt = DoTangent(p, p + rt, k_RightTangentID, activePoint, GetTangentMode(activePoint) == TangentMode.Broken ? k_TangentColorAlternative : k_TangentColor); - - var changed = (nlt != lt || nrt != rt); - allZero = nlt.sqrMagnitude == 0 && nrt.sqrMagnitude == 0; - - // if indeed we are dragging one of the handles and we just shift+mousedown, toggle the point. this happens even without change! - if (isHot && mouseDown) - { - var nm = ((int)m + 1) % 3; - m = (TangentMode)nm; - //m = m == PointMode.Continuous ? PointMode.Broken : PointMode.Continuous; - this.SetTangentMode(activePoint, m); - } - - // make it broken when both tangents are zero - if (mouseUp && allZero) - { - this.SetTangentMode(activePoint, TangentMode.Linear); - changed = true; - } - - // only do something when it's changed - if (changed) - { - RecordUndo(); - this.SetPointLTangent(activePoint, nlt); - this.SetPointRTangent(activePoint, nrt); - RefreshTangents(activePoint, guiUtility.hotControl == k_RightTangentID); - Repaint(); - } - } - } - - public void Points() - { - var wantsDelete = - (UnityEngine.Event.current.type == EventType.ExecuteCommand || UnityEngine.Event.current.type == EventType.ValidateCommand) - && (UnityEngine.Event.current.commandName == EventCommandNames.SoftDelete || UnityEngine.Event.current.commandName == EventCommandNames.Delete); - for (int i = 0; i < this.GetPointsCount(); i++) - { - if (i == m_NewPointIndex) - continue; - - var p0 = this.GetPointPosition(i); - var id = guiUtility.GetControlID(5353, FocusType.Keyboard); - var mouseDown = currentEvent.GetTypeForControl(id) == EventType.MouseDown; - var mouseUp = currentEvent.GetTypeForControl(id) == EventType.MouseUp; - - EditorGUI.BeginChangeCheck(); - - if (currentEvent.type == EventType.Repaint) - { - ColorEnum c = GetColorForPoint(i, id); - handleOutlineColor = k_OutlineColor[(int)c]; - handleFillColor = k_FillColor[(int)c]; - } - - var np = p0; - var hotControlBefore = guiUtility.hotControl; - - if (!currentEvent.alt || guiUtility.hotControl == id) - np = DoSlider(id, p0, Vector3.up, Vector3.right, GetHandleSizeForPoint(i), GetCapForPoint(i)); - else if (currentEvent.type == EventType.Repaint) - GetCapForPoint(i)(id, p0, Quaternion.LookRotation(Vector3.forward, Vector3.up), GetHandleSizeForPoint(i), currentEvent.type); - - var hotcontrolAfter = guiUtility.hotControl; - - if (mouseUp && hotControlBefore == id && hotcontrolAfter == 0 && (currentEvent.mousePosition == m_MousePositionLastMouseDown) && !currentEvent.shift) - HandlePointClick(i); - - if (EditorGUI.EndChangeCheck()) - { - RecordUndo(); - np = Snap(np); - MoveSelections(np - p0); - } - - if (guiUtility.hotControl == id && mouseDown && !m_Selection.Contains(i)) - { - SelectPoint(i, currentEvent.shift ? SelectionType.Additive : SelectionType.Normal); - Repaint(); - } - - if (m_NewPointDragFinished && activePoint == i && id != -1) - { - guiUtility.keyboardControl = id; - m_NewPointDragFinished = false; - } - } - - if (wantsDelete) - { - if (currentEvent.type == EventType.ValidateCommand) - { - currentEvent.Use(); - } - else if (currentEvent.type == EventType.ExecuteCommand) - { - RecordUndo(); - DeleteSelections(); - currentEvent.Use(); - } - } - } - - public void HandlePointInsertToEdge(int closestEdge, float closestEdgeDist) - { - var pointCreatorIsHot = GUIUtility.hotControl == k_CreatorID; - - Vector3 position = pointCreatorIsHot ? GetPointPosition(m_NewPointIndex) : FindClosestPointOnEdge(closestEdge, ScreenToLocal(currentEvent.mousePosition), 100); - - EditorGUI.BeginChangeCheck(); - - handleFillColor = k_FillColor[(int)ColorEnum.ESelectedHovered]; - handleOutlineColor = k_OutlineColor[(int)ColorEnum.ESelectedHovered]; - - if (!pointCreatorIsHot) - { - handleFillColor = handleFillColor.AlphaMultiplied(0.5f); - handleOutlineColor = handleOutlineColor.AlphaMultiplied(0.5f); - } - - int hotControlBefore = GUIUtility.hotControl; - var newPosition = DoSlider(k_CreatorID, position, Vector3.up, Vector3.right, GetHandleSizeForPoint(closestEdge), RectCap); - if (hotControlBefore != k_CreatorID && GUIUtility.hotControl == k_CreatorID) - { - RecordUndo(); - m_NewPointIndex = NextIndex(closestEdge, GetPointsCount()); - InsertPointAt(m_NewPointIndex, newPosition); - SelectPoint(m_NewPointIndex, SelectionType.Normal); - } - else if (EditorGUI.EndChangeCheck()) - { - RecordUndo(); - newPosition = Snap(newPosition); - MoveSelections(newPosition - position); - } - } - - private void HandleEdgeDragging(int closestEdge) - { - switch (currentEvent.type) - { - case EventType.MouseDown: - m_ActiveEdge = closestEdge; - m_EdgeDragStartP0 = GetPointPosition(m_ActiveEdge); - m_EdgeDragStartP1 = GetPointPosition(NextIndex(m_ActiveEdge, GetPointsCount())); - if (currentEvent.shift) - { - RecordUndo(); - InsertPointAt(m_ActiveEdge + 1, m_EdgeDragStartP0); - InsertPointAt(m_ActiveEdge + 2, m_EdgeDragStartP1); - m_ActiveEdge++; - } - m_EdgeDragStartMousePosition = ScreenToLocal(currentEvent.mousePosition); - GUIUtility.hotControl = k_EdgeID; - currentEvent.Use(); - break; - case EventType.MouseDrag: - // This can happen when MouseDown event happen when dragging a point instead of line - if (GUIUtility.hotControl == k_EdgeID) - { - RecordUndo(); - Vector3 mousePos = ScreenToLocal(currentEvent.mousePosition); - Vector3 delta = mousePos - m_EdgeDragStartMousePosition; - - Vector3 position = GetPointPosition(m_ActiveEdge); - Vector3 newPosition = m_EdgeDragStartP0 + delta; - - newPosition = Snap(newPosition); - - Vector3 snappedDelta = newPosition - position; - var i0 = m_ActiveEdge; - var i1 = NextIndex(m_ActiveEdge, GetPointsCount()); - SetPointPosition(m_ActiveEdge, GetPointPosition(i0) + snappedDelta); - SetPointPosition(i1, GetPointPosition(i1) + snappedDelta); - currentEvent.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == k_EdgeID) - { - m_ActiveEdge = -1; - GUIUtility.hotControl = 0; - currentEvent.Use(); - } - break; - } - } - - Vector3 DoTangent(Vector3 p0, Vector3 t0, int cid, int pointIndex, Color color) - { - var handleSize = GetHandleSizeForPoint(pointIndex); - var tangentSize = GetTangentSizeForPoint(pointIndex); - - handles.color = color; - - float distance = HandleUtility.DistanceToCircle(t0, tangentSize); - - if (lineTexture != null) - handles.DrawAAPolyLine(lineTexture, new Vector3[] {p0, t0}); - else - handles.DrawLine(p0, t0); - - handleOutlineColor = distance > 0f ? color : k_OutlineColor[(int)ColorEnum.ESelectedHovered]; - handleFillColor = color; - var delta = DoSlider(cid, t0, Vector3.up, Vector3.right, tangentSize, GetCapForTangent(pointIndex)) - p0; - - return delta.magnitude < handleSize ? Vector3.zero : delta; - } - - public void HandlePointClick(int pointIndex) - { - if (m_Selection.Count > 1) - { - m_Selection.SelectPoint(pointIndex, SelectionType.Normal); - } - else if (!currentEvent.control && !currentEvent.shift && m_ActivePointOnLastMouseDown == activePoint) - { - OnPointClick(pointIndex); - } - } - - public void CycleTangentMode() - { - TangentMode oldMode = GetTangentMode(activePoint); - TangentMode newMode = GetNextTangentMode(oldMode); - SetTangentMode(activePoint, newMode); - RefreshTangentsAfterModeChange(activePoint, oldMode, newMode); - } - - public static TangentMode GetNextTangentMode(TangentMode current) - { - return (TangentMode)((((int)current) + 1) % Enum.GetValues(typeof(TangentMode)).Length); - } - - public void RefreshTangentsAfterModeChange(int pointIndex, TangentMode oldMode, TangentMode newMode) - { - if (oldMode != TangentMode.Linear && newMode == TangentMode.Linear) - { - SetPointLTangent(pointIndex, Vector3.zero); - SetPointRTangent(pointIndex, Vector3.zero); - } - if (newMode == TangentMode.Continuous) - { - if (oldMode == TangentMode.Broken) - { - SetPointRTangent(pointIndex, GetPointLTangent(pointIndex) * -1f); - } - if (oldMode == TangentMode.Linear) - { - FromAllZeroToTangents(pointIndex); - } - } - } - - private ColorEnum GetColorForPoint(int pointIndex, int handleID) - { - bool hovered = MouseDistanceToPoint(pointIndex) <= 0f; - bool selected = m_Selection.Contains(pointIndex); - - if (hovered && selected || GUIUtility.hotControl == handleID) - return ColorEnum.ESelectedHovered; - if (hovered) - return ColorEnum.EUnselectedHovered; - if (selected) - return ColorEnum.ESelected; - - return ColorEnum.EUnselected; - } - - private void FromAllZeroToTangents(int pointIndex) - { - Vector3 p0 = GetPointPosition(pointIndex); - - int prevPointIndex = pointIndex > 0 ? pointIndex - 1 : GetPointsCount() - 1; - - Vector3 lt = (GetPointPosition(prevPointIndex) - p0) * .33f; - Vector3 rt = -lt; - - const float maxScreenLen = 100f; - - float ltScreenLen = (LocalToScreen(p0) - LocalToScreen(p0 + lt)).magnitude; - float rtScreenLen = (LocalToScreen(p0) - LocalToScreen(p0 + rt)).magnitude; - - lt *= Mathf.Min(maxScreenLen / ltScreenLen, 1f); - rt *= Mathf.Min(maxScreenLen / rtScreenLen, 1f); - - this.SetPointLTangent(pointIndex, lt); - this.SetPointRTangent(pointIndex, rt); - } - - private Handles.CapFunction GetCapForTangent(int index) - { - if (GetTangentMode(index) == TangentMode.Continuous) - return CircleCap; - - return DiamondCap; - } - - private DistanceToControl GetDistanceFuncForTangent(int index) - { - if (GetTangentMode(index) == TangentMode.Continuous) - return DistanceToCircle(); - - return HandleUtility.DistanceToDiamond; - } - - private Handles.CapFunction GetCapForPoint(int index) - { - switch (GetTangentMode(index)) - { - case TangentMode.Broken: - return DiamondCap; - case TangentMode.Continuous: - return CircleCap; - case TangentMode.Linear: - return RectCap; - } - return DiamondCap; - } - - private static float DistanceToCircleInternal(Vector3 position, Quaternion rotation, float size) - { - return HandleUtility.DistanceToCircle(position, size); - } - - private float GetHandleSizeForPoint(int index) - { - return Camera.current != null ? HandleUtility.GetHandleSize(GetPointPosition(index)) * 0.075f : GetHandleSize(); - } - - private float GetTangentSizeForPoint(int index) - { - return GetHandleSizeForPoint(index) * 0.8f; - } - - private void RefreshTangents(int index, bool rightIsActive) - { - var m = GetTangentMode(index); - var lt = GetPointLTangent(index); - var rt = GetPointRTangent(index); - - // mirror the change on the other tangent for continuous - if (m == TangentMode.Continuous) - { - if (rightIsActive) - { - lt = -rt; - var mag = lt.magnitude; - lt = lt.normalized * mag; - } - else - { - rt = -lt; - var mag = rt.magnitude; - rt = rt.normalized * mag; - } - } - - this.SetPointLTangent(activePoint, lt); - this.SetPointRTangent(activePoint, rt); - } - - private void StoreMouseDownState() - { - m_MousePositionLastMouseDown = currentEvent.mousePosition; - m_ActivePointOnLastMouseDown = activePoint; - } - - private void DelayedResetIfNecessary() - { - if (m_DelayedReset) - { - guiUtility.hotControl = 0; - guiUtility.keyboardControl = 0; - m_Selection.Clear(); - activePoint = -1; - m_DelayedReset = false; - } - } - - public Vector3 FindClosestPointOnEdge(int edgeIndex, Vector3 position, int iterations) - { - float step = 1f / iterations; - float closestDistance = float.MaxValue; - float closestDistanceIndex = edgeIndex; - - for (float a = 0f; a <= 1f; a += step) - { - Vector3 pos = GetPositionByIndex(edgeIndex + a); - float distance = (position - pos).sqrMagnitude; - if (distance < closestDistance) - { - closestDistance = distance; - closestDistanceIndex = edgeIndex + a; - } - } - - return GetPositionByIndex(closestDistanceIndex); - } - - private Vector3 GetPositionByIndex(float index) - { - int indexA = Mathf.FloorToInt(index); - int indexB = NextIndex(indexA, GetPointsCount()); - float subPosition = index - indexA; - return GetPoint(GetPointPosition(indexA), GetPointPosition(indexB), GetPointRTangent(indexA), GetPointLTangent(indexB), subPosition); - } - - private static Vector3 GetPoint(Vector3 startPosition, Vector3 endPosition, Vector3 startTangent, Vector3 endTangent, float t) - { - t = Mathf.Clamp01(t); - float a = 1f - t; - return a * a * a * startPosition + 3f * a * a * t * (startPosition + startTangent) + 3f * a * t * t * (endPosition + endTangent) + t * t * t * endPosition; - } - - private int FindClosestPointToMouse() - { - Vector3 mousePos = ScreenToLocal(currentEvent.mousePosition); - return FindClosestPointIndex(mousePos); - } - - private float MouseDistanceToClosestTangent() - { - if (activePoint < 0) - return float.MaxValue; - - var lt = GetPointLTangent(activePoint); - var rt = GetPointRTangent(activePoint); - - if (lt.sqrMagnitude == 0f && rt.sqrMagnitude == 0f) - return float.MaxValue; - - var p = GetPointPosition(activePoint); - var tangentSize = GetTangentSizeForPoint(activePoint); - - return Mathf.Min( - HandleUtility.DistanceToRectangle(p + lt, Quaternion.identity, tangentSize), - HandleUtility.DistanceToRectangle(p + rt, Quaternion.identity, tangentSize) - ); - } - - private int FindClosestPointIndex(Vector3 position) - { - float closestDistance = float.MaxValue; - int closestIndex = -1; - for (int i = 0; i < this.GetPointsCount(); i++) - { - var p0 = this.GetPointPosition(i); - var distance = (p0 - position).sqrMagnitude; - if (distance < closestDistance) - { - closestIndex = i; - closestDistance = distance; - } - } - return closestIndex; - } - - private DistanceToControl GetDistanceFuncForPoint(int index) - { - switch (GetTangentMode(index)) - { - case TangentMode.Broken: - return DistanceToDiamond(); - case TangentMode.Continuous: - return DistanceToCircle(); - case TangentMode.Linear: - return DistanceToRectangle(); - } - return DistanceToRectangle(); - } - - private float MouseDistanceToPoint(int index) - { - switch (GetTangentMode(index)) - { - case TangentMode.Broken: - return HandleUtility.DistanceToDiamond(GetPointPosition(index), Quaternion.identity, GetHandleSizeForPoint(index)); - case TangentMode.Linear: - return HandleUtility.DistanceToRectangle(GetPointPosition(index), Quaternion.identity, GetHandleSizeForPoint(index)); - case TangentMode.Continuous: - return HandleUtility.DistanceToCircle(GetPointPosition(index), GetHandleSizeForPoint(index)); - } - return float.MaxValue; - } - - private bool EdgeDragModifiersActive() - { - return currentEvent.modifiers == EventModifiers.Control; - } - - private static Vector3 DoSlider(int id, Vector3 position, Vector3 slide1, Vector3 slide2, float s, Handles.CapFunction cap) - { - return Slider2D.Do(id, position, Vector3.zero, Vector3.Cross(slide1, slide2), slide1, slide2, s, cap, Vector2.zero, false); - } - - public void RectCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - if (eventType == EventType.Layout) - { - HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size * 0.5f)); - } - else if (eventType == EventType.Repaint) - { - Vector3 normal = handles.matrix.GetColumn(2); - Vector3 projectedUp = (ProjectPointOnPlane(normal, position, position + Vector3.up) - position).normalized; - Quaternion localRotation = Quaternion.LookRotation(handles.matrix.GetColumn(2), projectedUp); - Vector3 sideways = localRotation * Vector3.right * size; - Vector3 up = localRotation * Vector3.up * size; - List list = GetDrawBatchList(new DrawBatchDataKey(handleFillColor, GL.TRIANGLES)); - list.Add(position + sideways + up); - list.Add(position + sideways - up); - list.Add(position - sideways - up); - list.Add(position - sideways - up); - list.Add(position - sideways + up); - list.Add(position + sideways + up); - - list = GetDrawBatchList(new DrawBatchDataKey(handleOutlineColor, GL.LINES)); - list.Add(position + sideways + up); - list.Add(position + sideways - up); - list.Add(position + sideways - up); - list.Add(position - sideways - up); - list.Add(position - sideways - up); - list.Add(position - sideways + up); - list.Add(position - sideways + up); - list.Add(position + sideways + up); - } - } - - public void CircleCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - if (eventType == EventType.Layout) - { - HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size * 0.5f)); - } - else if (eventType == EventType.Repaint) - { - Vector3 forward = handleMatrixrotation * rotation * Vector3.forward; - Vector3 tangent = Vector3.Cross(forward, Vector3.up); - if (tangent.sqrMagnitude < .001f) - tangent = Vector3.Cross(forward, Vector3.right); - - Vector3[] points = new Vector3[60]; - handles.SetDiscSectionPoints(points, position, forward, tangent, 360f, size); - - List list = GetDrawBatchList(new DrawBatchDataKey(handleFillColor, GL.TRIANGLES)); - for (int i = 1; i < points.Length; i++) - { - list.Add(position); - list.Add(points[i]); - list.Add(points[i - 1]); - } - - list = GetDrawBatchList(new DrawBatchDataKey(handleOutlineColor, GL.LINES)); - for (int i = 0; i < points.Length - 1; i++) - { - list.Add(points[i]); - list.Add(points[i + 1]); - } - } - } - - public void DiamondCap(int controlID, Vector3 position, Quaternion rotation, float size, EventType eventType) - { - if (eventType == EventType.Layout) - { - HandleUtility.AddControl(controlID, HandleUtility.DistanceToCircle(position, size * 0.5f)); - } - else if (eventType == EventType.Repaint) - { - Vector3 normal = handles.matrix.GetColumn(2); - Vector3 projectedUp = (ProjectPointOnPlane(normal, position, position + Vector3.up) - position).normalized; - Quaternion localRotation = Quaternion.LookRotation(handles.matrix.GetColumn(2), projectedUp); - Vector3 sideways = localRotation * Vector3.right * size * 1.25f; - Vector3 up = localRotation * Vector3.up * size * 1.25f; - - List list = GetDrawBatchList(new DrawBatchDataKey(handleFillColor, GL.TRIANGLES)); - list.Add(position - up); - list.Add(position + sideways); - list.Add(position - sideways); - list.Add(position - sideways); - list.Add(position + up); - list.Add(position + sideways); - - list = GetDrawBatchList(new DrawBatchDataKey(handleOutlineColor, GL.LINES)); - list.Add(position + sideways); - list.Add(position - up); - list.Add(position - up); - list.Add(position - sideways); - list.Add(position - sideways); - list.Add(position + up); - list.Add(position + up); - list.Add(position + sideways); - } - } - - private static int NextIndex(int index, int total) - { - return mod(index + 1, total); - } - - private static int PreviousIndex(int index, int total) - { - return mod(index - 1, total); - } - - private static int mod(int x, int m) - { - int r = x % m; - return r < 0 ? r + m : r; - } - - private static Vector3 ProjectPointOnPlane(Vector3 planeNormal, Vector3 planePoint, Vector3 point) - { - planeNormal.Normalize(); - var distance = -Vector3.Dot(planeNormal.normalized, (point - planePoint)); - return point + planeNormal * distance; - } - - public void RegisterToShapeEditor(ShapeEditor se) - { - ++m_ShapeEditorRegisteredTo; - se.m_ShapeEditorListeners.Add(this); - } - - public void UnregisterFromShapeEditor(ShapeEditor se) - { - --m_ShapeEditorRegisteredTo; - se.m_ShapeEditorListeners.Remove(this); - } - - private void OnShapeEditorUpdateDone() - { - // When all the ShapeEditor we are interested in - // has completed their update, we reset our internal values - ++m_ShapeEditorUpdateDone; - if (m_ShapeEditorUpdateDone >= m_ShapeEditorRegisteredTo) - { - m_ShapeEditorUpdateDone = 0; - m_MouseClosestEdge = -1; - m_MouseClosestEdgeDist = float.MaxValue; - m_EdgePoints = null; - } - } - - private void ClearSelectedPoints() - { - selectedPoints.Clear(); - activePoint = -1; - } - - private void SelectPointsInRect(Rect r, SelectionType st) - { - var localRect = EditorGUIExt.FromToRect(ScreenToLocal(r.min), ScreenToLocal(r.max)); - m_Selection.RectSelect(localRect, st); - } - - private void DeleteSelections() - { - foreach (var se in m_ShapeEditorListeners) - se.m_Selection.DeleteSelection(); - m_Selection.DeleteSelection(); - } - - private void MoveSelections(Vector2 distance) - { - foreach (var se in m_ShapeEditorListeners) - se.m_Selection.MoveSelection(distance); - m_Selection.MoveSelection(distance); - } - - private void SelectPoint(int index, SelectionType st) - { - if (st == SelectionType.Normal) - { - foreach (var se in m_ShapeEditorListeners) - se.ClearSelectedPoints(); - } - m_Selection.SelectPoint(index, st); - } - } -} diff --git a/Editor/Mono/ShapeEditor/ShapeEditorRectSelection.cs b/Editor/Mono/ShapeEditor/ShapeEditorRectSelection.cs deleted file mode 100644 index 7861a37133..0000000000 --- a/Editor/Mono/ShapeEditor/ShapeEditorRectSelection.cs +++ /dev/null @@ -1,232 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using SelectionType = UnityEditor.ShapeEditor.SelectionType; - -namespace UnityEditor -{ - internal class ShapeEditorRectSelectionTool - { - Vector2 m_SelectStartPoint; - Vector2 m_SelectMousePoint; - bool m_RectSelecting; - int m_RectSelectionID; - const float k_MinSelectionSize = 6f; - - public event Action RectSelect = (i, p) => {}; - public event Action ClearSelection = () => {}; - - public ShapeEditorRectSelectionTool(IGUIUtility gu) - { - guiUtility = gu; - m_RectSelectionID = guiUtility.GetPermanentControlID(); - } - - public void OnGUI() - { - Event evt = Event.current; - - Handles.BeginGUI(); - - Vector2 mousePos = evt.mousePosition; - int id = m_RectSelectionID; - - switch (evt.GetTypeForControl(id)) - { - case EventType.Layout: - if (!Tools.viewToolActive) - HandleUtility.AddDefaultControl(id); - break; - - case EventType.MouseDown: - if (HandleUtility.nearestControl == id && evt.button == 0) - { - guiUtility.hotControl = id; - m_SelectStartPoint = mousePos; - } - break; - case EventType.MouseDrag: - if (guiUtility.hotControl == id) - { - if (!m_RectSelecting && (mousePos - m_SelectStartPoint).magnitude > k_MinSelectionSize) - { - m_RectSelecting = true; - } - if (m_RectSelecting) - { - m_SelectMousePoint = mousePos; - - SelectionType type = SelectionType.Normal; - if (Event.current.control) - type = SelectionType.Subtractive; - else if (Event.current.shift) - type = SelectionType.Additive; - RectSelect(EditorGUIExt.FromToRect(m_SelectStartPoint, m_SelectMousePoint), type); - } - evt.Use(); - } - break; - - case EventType.Repaint: - if (guiUtility.hotControl == id && m_RectSelecting) - { - EditorStyles.selectionRect.Draw(EditorGUIExt.FromToRect(m_SelectStartPoint, m_SelectMousePoint), GUIContent.none, - false, false, false, false); - } - break; - - case EventType.MouseUp: - if (guiUtility.hotControl == id && evt.button == 0) - { - guiUtility.hotControl = 0; - guiUtility.keyboardControl = 0; - if (m_RectSelecting) - { - m_SelectMousePoint = new Vector2(mousePos.x, mousePos.y); - - SelectionType type = SelectionType.Normal; - if (Event.current.control) - type = SelectionType.Subtractive; - else if (Event.current.shift) - type = SelectionType.Additive; - - RectSelect(EditorGUIExt.FromToRect(m_SelectStartPoint, m_SelectMousePoint), type); - - m_RectSelecting = false; - } - else - { - ClearSelection(); - } - evt.Use(); - } - break; - } - - Handles.EndGUI(); - } - - public bool isSelecting - { - get { return guiUtility.hotControl == m_RectSelectionID; } - } - - IGUIUtility guiUtility - { - get; set; - } - } - - // TODO: For now we copy-paste from RectSelection. Refactor to avoid duplicate codes. - internal class ShapeEditorSelection : IEnumerable - { - HashSet m_SelectedPoints = new HashSet(); - ShapeEditor m_ShapeEditor; - - public ShapeEditorSelection(ShapeEditor owner) - { - m_ShapeEditor = owner; - } - - public bool Contains(int i) - { - return m_SelectedPoints.Contains(i); - } - - public int Count - { - get { return m_SelectedPoints.Count; } - } - - public void DeleteSelection() - { - var sorted = m_SelectedPoints.OrderByDescending(x => x); - foreach (int selectedIndex in sorted) - { - m_ShapeEditor.RemovePointAt(selectedIndex); - } - if (m_ShapeEditor.activePoint >= m_ShapeEditor.GetPointsCount()) - m_ShapeEditor.activePoint = m_ShapeEditor.GetPointsCount() - 1; - m_SelectedPoints.Clear(); - } - - public void MoveSelection(Vector3 delta) - { - if (delta.sqrMagnitude < float.Epsilon) - return; - - foreach (int selectedIndex in m_SelectedPoints) - { - m_ShapeEditor.SetPointPosition(selectedIndex, m_ShapeEditor.GetPointPosition(selectedIndex) + delta); - } - } - - public void Clear() - { - m_SelectedPoints.Clear(); - if (m_ShapeEditor != null) - m_ShapeEditor.activePoint = -1; - } - - public void SelectPoint(int i, SelectionType type) - { - switch (type) - { - case SelectionType.Additive: - m_ShapeEditor.activePoint = i; - m_SelectedPoints.Add(i); - break; - case SelectionType.Subtractive: - m_ShapeEditor.activePoint = i > 0 ? i - 1 : 0; - m_SelectedPoints.Remove(i); - break; - case SelectionType.Normal: - m_SelectedPoints.Clear(); - m_ShapeEditor.activePoint = i; - m_SelectedPoints.Add(i); - break; - default: - m_ShapeEditor.activePoint = i; break; - } - m_ShapeEditor.Repaint(); - } - - public void RectSelect(Rect rect, SelectionType type) - { - if (type == SelectionType.Normal) - { - m_SelectedPoints.Clear(); - m_ShapeEditor.activePoint = -1; - type = SelectionType.Additive; - } - - for (int i = 0; i < m_ShapeEditor.GetPointsCount(); i++) - { - var p0 = m_ShapeEditor.GetPointPosition(i); - if (rect.Contains(p0)) - { - SelectPoint(i, type); - } - } - m_ShapeEditor.Repaint(); - } - - public HashSet indices { get { return m_SelectedPoints; } } - - public IEnumerator GetEnumerator() - { - return m_SelectedPoints.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} // namespace diff --git a/Editor/Mono/SplashScreenLogo.cs b/Editor/Mono/SplashScreenLogo.cs deleted file mode 100644 index 2f715f8656..0000000000 --- a/Editor/Mono/SplashScreenLogo.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - public partial class PlayerSettings - { - public partial struct SplashScreenLogo - { - private const float k_MinLogoTime = 2.0f; - private static Sprite s_UnityLogo; - private Sprite m_Logo; - private float m_Duration; - - static SplashScreenLogo() - { - s_UnityLogo = Resources.GetBuiltinResource("UnitySplash-cube.png"); - } - - public Sprite logo - { - get { return m_Logo; } - set { m_Logo = value; } - } - - public static Sprite unityLogo - { - get { return s_UnityLogo; } - } - - public float duration - { - get { return Mathf.Max(m_Duration, k_MinLogoTime); } - set { m_Duration = Mathf.Max(value, k_MinLogoTime); } - } - } - } -} diff --git a/Editor/Mono/SpriteEditor/SpriteEditorHandles.cs b/Editor/Mono/SpriteEditor/SpriteEditorHandles.cs deleted file mode 100644 index bb09c5eb45..0000000000 --- a/Editor/Mono/SpriteEditor/SpriteEditorHandles.cs +++ /dev/null @@ -1,370 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - public static class SpriteEditorHandles - { - private static Vector2 s_CurrentMousePosition; - private static Vector2 s_DragStartScreenPosition; - private static Vector2 s_DragScreenOffset; - - static internal Vector2 PointSlider(Vector2 pos, MouseCursor cursor, GUIStyle dragDot, GUIStyle dragDotActive) - { - int id = GUIUtility.GetControlID("Slider1D".GetHashCode(), FocusType.Keyboard); - Vector2 screenVal = Handles.matrix.MultiplyPoint(pos); - Rect handleScreenPos = new Rect( - screenVal.x - dragDot.fixedWidth * .5f, - screenVal.y - dragDot.fixedHeight * .5f, - dragDot.fixedWidth, - dragDot.fixedHeight - ); - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.Repaint: - if (GUIUtility.hotControl == id) - dragDotActive.Draw(handleScreenPos, GUIContent.none, id); - else - dragDot.Draw(handleScreenPos, GUIContent.none, id); - break; - } - return ScaleSlider(pos, cursor, handleScreenPos); - } - - static internal Vector2 ScaleSlider(Vector2 pos, MouseCursor cursor, Rect cursorRect) - { - int id = GUIUtility.GetControlID("Slider1D".GetHashCode(), FocusType.Keyboard); - return ScaleSlider(id, pos, cursor, cursorRect); - } - - static private Vector2 ScaleSlider(int id, Vector2 pos, MouseCursor cursor, Rect cursorRect) - { - Vector2 screenVal = Handles.matrix.MultiplyPoint(pos); - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - // am I closest to the thingy? - if (evt.button == 0 && - cursorRect.Contains(Event.current.mousePosition) && - !evt.alt) - { - GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus - s_CurrentMousePosition = evt.mousePosition; - s_DragStartScreenPosition = evt.mousePosition; - s_DragScreenOffset = s_CurrentMousePosition - screenVal; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_CurrentMousePosition += evt.delta; - Vector2 oldPos = pos; - pos = Handles.inverseMatrix.MultiplyPoint(s_CurrentMousePosition); - if (!Mathf.Approximately((oldPos - pos).magnitude, 0f)) - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.KeyDown: - if (GUIUtility.hotControl == id) - { - if (evt.keyCode == KeyCode.Escape) - { - pos = Handles.inverseMatrix.MultiplyPoint(s_DragStartScreenPosition - s_DragScreenOffset); - GUIUtility.hotControl = 0; - GUI.changed = true; - evt.Use(); - } - } - break; - case EventType.Repaint: - EditorGUIUtility.AddCursorRect(cursorRect, cursor, id); - break; - } - return pos; - } - - static internal Vector2 PivotSlider(Rect sprite, Vector2 pos, GUIStyle pivotDot, GUIStyle pivotDotActive) - { - int id = GUIUtility.GetControlID("Slider1D".GetHashCode(), FocusType.Keyboard); - - // Convert from normalized space to texture space - pos = new Vector2(sprite.xMin + sprite.width * pos.x, sprite.yMin + sprite.height * pos.y); - - Vector2 screenVal = Handles.matrix.MultiplyPoint(pos); - - Rect handleScreenPos = new Rect( - screenVal.x - pivotDot.fixedWidth * .5f, - screenVal.y - pivotDot.fixedHeight * .5f, - pivotDotActive.fixedWidth, - pivotDotActive.fixedHeight - ); - - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - // am I closest to the thingy? - if (evt.button == 0 && handleScreenPos.Contains(Event.current.mousePosition) && !evt.alt) - { - GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus - s_CurrentMousePosition = evt.mousePosition; - s_DragStartScreenPosition = evt.mousePosition; - Vector2 rectScreenCenter = Handles.matrix.MultiplyPoint(pos); - s_DragScreenOffset = s_CurrentMousePosition - rectScreenCenter; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(1); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_CurrentMousePosition += evt.delta; - Vector2 oldPos = pos; - Vector3 scrPos = Handles.inverseMatrix.MultiplyPoint(s_CurrentMousePosition - s_DragScreenOffset); - pos = new Vector2(scrPos.x, scrPos.y); - if (!Mathf.Approximately((oldPos - pos).magnitude, 0f)) - GUI.changed = true; - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.KeyDown: - if (GUIUtility.hotControl == id) - { - if (evt.keyCode == KeyCode.Escape) - { - pos = Handles.inverseMatrix.MultiplyPoint(s_DragStartScreenPosition - s_DragScreenOffset); - GUIUtility.hotControl = 0; - GUI.changed = true; - evt.Use(); - } - } - break; - case EventType.Repaint: - EditorGUIUtility.AddCursorRect(handleScreenPos, MouseCursor.Arrow, id); - - if (GUIUtility.hotControl == id) - pivotDotActive.Draw(handleScreenPos, GUIContent.none, id); - else - pivotDot.Draw(handleScreenPos, GUIContent.none, id); - - break; - } - - // Convert from texture space back to normalized space - pos = new Vector2((pos.x - sprite.xMin) / sprite.width, (pos.y - sprite.yMin) / sprite.height); - - return pos; - } - - static internal Rect SliderRect(Rect pos) - { - int id = GUIUtility.GetControlID("SliderRect".GetHashCode(), FocusType.Keyboard); - - Event evt = Event.current; - - // SpriteEditorWindow is telling us we got selected and so we fake a mousedown on our Repaint event to get "one-click dragging" going on - if (SpriteEditorWindow.s_OneClickDragStarted && evt.type == EventType.Repaint) - { - HandleSliderRectMouseDown(id, evt, pos); - SpriteEditorWindow.s_OneClickDragStarted = false; - } - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - // am I closest to the thingy? - if (evt.button == 0 && pos.Contains(Handles.inverseMatrix.MultiplyPoint(Event.current.mousePosition)) && !evt.alt) - { - HandleSliderRectMouseDown(id, evt, pos); - evt.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_CurrentMousePosition += evt.delta; - - Vector2 oldCenter = pos.center; - pos.center = Handles.inverseMatrix.MultiplyPoint(s_CurrentMousePosition - s_DragScreenOffset); - if (!Mathf.Approximately((oldCenter - pos.center).magnitude, 0f)) - GUI.changed = true; - - evt.Use(); - } - break; - case EventType.MouseUp: - if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2)) - { - GUIUtility.hotControl = 0; - evt.Use(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - break; - case EventType.KeyDown: - if (GUIUtility.hotControl == id) - { - if (evt.keyCode == KeyCode.Escape) - { - pos.center = Handles.inverseMatrix.MultiplyPoint(s_DragStartScreenPosition - s_DragScreenOffset); - GUIUtility.hotControl = 0; - GUI.changed = true; - evt.Use(); - } - } - break; - case EventType.Repaint: - Vector2 topleft = Handles.inverseMatrix.MultiplyPoint(new Vector2(pos.xMin, pos.yMin)); - Vector2 bottomright = Handles.inverseMatrix.MultiplyPoint(new Vector2(pos.xMax, pos.yMax)); - EditorGUIUtility.AddCursorRect(new Rect(topleft.x, topleft.y, bottomright.x - topleft.x, bottomright.y - topleft.y), MouseCursor.Arrow, id); - break; - } - - return pos; - } - - static internal void HandleSliderRectMouseDown(int id, Event evt, Rect pos) - { - GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus - s_CurrentMousePosition = evt.mousePosition; - s_DragStartScreenPosition = evt.mousePosition; - - Vector2 rectScreenCenter = Handles.matrix.MultiplyPoint(pos.center); - s_DragScreenOffset = s_CurrentMousePosition - rectScreenCenter; - - EditorGUIUtility.SetWantsMouseJumping(1); - } - - static int s_RectSelectionID = GUIUtility.GetPermanentControlID(); - - static internal Rect RectCreator(Rect textureArea, GUIStyle rectStyle) - { - Event evt = Event.current; - Vector2 mousePos = evt.mousePosition; - int id = s_RectSelectionID; - Rect result = new Rect(); - - switch (evt.GetTypeForControl(id)) - { - case EventType.MouseDown: - if (evt.button == 0) - { - GUIUtility.hotControl = id; - - // Make sure that the starting position is clamped to inside texture area - Vector2 point = Handles.inverseMatrix.MultiplyPoint(mousePos); - - point.x = Mathf.Min(Mathf.Max(point.x, textureArea.xMin), textureArea.xMax); - point.y = Mathf.Min(Mathf.Max(point.y, textureArea.yMin), textureArea.yMax); - - // Save clamped starting position for later use - s_DragStartScreenPosition = Handles.matrix.MultiplyPoint(point); - - // Actual position - s_CurrentMousePosition = mousePos; - - evt.Use(); - } - break; - case EventType.MouseDrag: - if (GUIUtility.hotControl == id) - { - s_CurrentMousePosition = new Vector2(mousePos.x, mousePos.y); - evt.Use(); - } - break; - - case EventType.Repaint: - if (GUIUtility.hotControl == id && ValidRect(s_DragStartScreenPosition, s_CurrentMousePosition)) - { - // TODO: use rectstyle - //rectStyle.Draw (GetCurrentRect (true, textureWidth, textureHeight, s_DragStartScreenPosition, s_CurrentMousePosition), GUIContent.none, false, false, false, false); - SpriteEditorUtility.BeginLines(Color.green * 1.5f); - SpriteEditorUtility.DrawBox(GetCurrentRect(false, textureArea, s_DragStartScreenPosition, s_CurrentMousePosition)); - SpriteEditorUtility.EndLines(); - } - break; - - case EventType.MouseUp: - if (GUIUtility.hotControl == id && evt.button == 0) - { - if (ValidRect(s_DragStartScreenPosition, s_CurrentMousePosition)) - { - result = GetCurrentRect(false, textureArea, s_DragStartScreenPosition, s_CurrentMousePosition); - GUI.changed = true; - evt.Use(); - } - - GUIUtility.hotControl = 0; - } - break; - case EventType.KeyDown: - if (GUIUtility.hotControl == id) - { - if (evt.keyCode == KeyCode.Escape) - { - GUIUtility.hotControl = 0; - GUI.changed = true; - evt.Use(); - } - } - break; - } - return result; - } - - static internal Rect RectCreator(float textureWidth, float textureHeight, GUIStyle rectStyle) - { - return RectCreator(new Rect(0, 0, textureWidth, textureHeight), rectStyle); - } - - static private bool ValidRect(Vector2 startPoint, Vector2 endPoint) - { - return Mathf.Abs((endPoint - startPoint).x) > 5f && Mathf.Abs((endPoint - startPoint).y) > 5f; - } - - static private Rect GetCurrentRect(bool screenSpace, Rect clampArea, Vector2 startPoint, Vector2 endPoint) - { - Rect r = EditorGUIExt.FromToRect(Handles.inverseMatrix.MultiplyPoint(startPoint), Handles.inverseMatrix.MultiplyPoint(endPoint)); - r = SpriteEditorUtility.ClampedRect(SpriteEditorUtility.RoundToInt(r), clampArea, false); - - if (screenSpace) - { - Vector2 topleft = Handles.matrix.MultiplyPoint(new Vector2(r.xMin, r.yMin)); - Vector2 bottomright = Handles.matrix.MultiplyPoint(new Vector2(r.xMax, r.yMax)); - - r = new Rect(topleft.x, topleft.y, bottomright.x - topleft.x, bottomright.y - topleft.y); - } - return r; - } - } -} diff --git a/Editor/Mono/SpriteEditor/SpriteEditorMenu.cs b/Editor/Mono/SpriteEditor/SpriteEditorMenu.cs deleted file mode 100644 index 47873aa173..0000000000 --- a/Editor/Mono/SpriteEditor/SpriteEditorMenu.cs +++ /dev/null @@ -1,405 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; -using System; -using UnityEditor.Experimental.U2D; -using UnityEngine.U2D.Interface; -using UnityEvent = UnityEngine.Event; - -namespace UnityEditorInternal -{ - [Serializable] - internal class SpriteEditorMenuSetting : ScriptableObject - { - public enum SlicingType { Automatic = 0, GridByCellSize = 1, GridByCellCount = 2 } - - [SerializeField] - public Vector2 gridCellCount = new Vector2(1, 1); - [SerializeField] - public Vector2 gridSpriteSize = new Vector2(64, 64); - [SerializeField] - public Vector2 gridSpriteOffset = new Vector2(0, 0); - [SerializeField] - public Vector2 gridSpritePadding = new Vector2(0, 0); - [SerializeField] - public Vector2 pivot = Vector2.zero; - [SerializeField] - public int autoSlicingMethod = (int)SpriteFrameModule.AutoSlicingMethod.DeleteAll; - [SerializeField] - public int spriteAlignment; - [SerializeField] - public SlicingType slicingType; - } - - internal class SpriteEditorMenu : EditorWindow - { - private static Styles s_Styles; - private static long s_LastClosedTime; - private static SpriteEditorMenuSetting s_Setting; - private ITextureDataProvider m_TextureDataProvider; - private SpriteFrameModule m_SpriteFrameModule; - - private class Styles - { - public GUIStyle background = "grey_border"; - public GUIStyle notice; - - public Styles() - { - notice = new GUIStyle(GUI.skin.label); - notice.alignment = TextAnchor.MiddleCenter; - notice.wordWrap = true; - } - - public readonly GUIContent[] spriteAlignmentOptions = - { - EditorGUIUtility.TrTextContent("Center"), - EditorGUIUtility.TrTextContent("Top Left"), - EditorGUIUtility.TrTextContent("Top"), - EditorGUIUtility.TrTextContent("Top Right"), - EditorGUIUtility.TrTextContent("Left"), - EditorGUIUtility.TrTextContent("Right"), - EditorGUIUtility.TrTextContent("Bottom Left"), - EditorGUIUtility.TrTextContent("Bottom"), - EditorGUIUtility.TrTextContent("Bottom Right"), - EditorGUIUtility.TrTextContent("Custom") - }; - - public readonly GUIContent[] slicingMethodOptions = - { - EditorGUIUtility.TrTextContent("Delete Existing", "Delete all existing sprite assets before the slicing operation"), - EditorGUIUtility.TrTextContent("Smart", "Try to match existing sprite rects to sliced rects from the slicing operation"), - EditorGUIUtility.TrTextContent("Safe", "Keep existing sprite rects intact") - }; - - public readonly GUIContent methodLabel = EditorGUIUtility.TrTextContent("Method"); - public readonly GUIContent pivotLabel = EditorGUIUtility.TrTextContent("Pivot"); - public readonly GUIContent typeLabel = EditorGUIUtility.TrTextContent("Type"); - public readonly GUIContent sliceButtonLabel = EditorGUIUtility.TrTextContent("Slice"); - public readonly GUIContent columnAndRowLabel = EditorGUIUtility.TrTextContent("Column & Row"); - public readonly GUIContent columnLabel = EditorGUIUtility.TextContent("C"); - public readonly GUIContent rowLabel = EditorGUIUtility.TextContent("R"); - public readonly GUIContent pixelSizeLabel = EditorGUIUtility.TrTextContent("Pixel Size"); - public readonly GUIContent xLabel = EditorGUIUtility.TextContent("X"); - public readonly GUIContent yLabel = EditorGUIUtility.TextContent("Y"); - public readonly GUIContent offsetLabel = EditorGUIUtility.TrTextContent("Offset"); - public readonly GUIContent paddingLabel = EditorGUIUtility.TrTextContent("Padding"); - public readonly GUIContent automaticSlicingHintLabel = EditorGUIUtility.TrTextContent("To obtain more accurate slicing results, manual slicing is recommended!"); - public readonly GUIContent customPivotLabel = EditorGUIUtility.TrTextContent("Custom Pivot"); - } - - private void Init(Rect buttonRect, SpriteFrameModule sf, ITextureDataProvider dataProvider) - { - // Create for once if setting was not created before. - if (s_Setting == null) - s_Setting = CreateInstance(); - - m_SpriteFrameModule = sf; - m_TextureDataProvider = dataProvider; - - buttonRect = GUIUtility.GUIToScreenRect(buttonRect); - float windowHeight = 145; - var windowSize = new Vector2(300, windowHeight); - ShowAsDropDown(buttonRect, windowSize, null, ShowMode.PopupMenuWithKeyboardFocus); - - Undo.undoRedoPerformed += UndoRedoPerformed; - } - - private void UndoRedoPerformed() - { - Repaint(); - } - - void OnEnable() - { - AssemblyReloadEvents.beforeAssemblyReload += Close; - } - - private void OnDisable() - { - AssemblyReloadEvents.beforeAssemblyReload -= Close; - Undo.undoRedoPerformed -= UndoRedoPerformed; - s_LastClosedTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - } - - internal static bool ShowAtPosition(Rect buttonRect, SpriteFrameModule sf, ITextureDataProvider textureProvider) - { - // We could not use realtimeSinceStartUp since it is set to 0 when entering/exitting playmode, we assume an increasing time when comparing time. - long nowMilliSeconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; - bool justClosed = nowMilliSeconds < s_LastClosedTime + 50; - if (!justClosed) - { - if (UnityEvent.current != null) // Event.current can be null during integration test - UnityEvent.current.Use(); - - SpriteEditorMenu spriteEditorMenu = CreateInstance(); - spriteEditorMenu.Init(buttonRect, sf, textureProvider); - return true; - } - return false; - } - - private void OnGUI() - { - if (s_Styles == null) - s_Styles = new Styles(); - - // Leave some space above the elements - GUILayout.Space(4); - - EditorGUIUtility.labelWidth = 124f; - EditorGUIUtility.wideMode = true; - - GUI.Label(new Rect(0, 0, position.width, position.height), GUIContent.none, s_Styles.background); - - EditorGUI.BeginChangeCheck(); - SpriteEditorMenuSetting.SlicingType slicingType = s_Setting.slicingType; - slicingType = (SpriteEditorMenuSetting.SlicingType)EditorGUILayout.EnumPopup(s_Styles.typeLabel, slicingType); - if (EditorGUI.EndChangeCheck()) - { - Undo.RegisterCompleteObjectUndo(s_Setting, "Change slicing type"); - s_Setting.slicingType = slicingType; - } - switch (slicingType) - { - case SpriteEditorMenuSetting.SlicingType.GridByCellSize: - case SpriteEditorMenuSetting.SlicingType.GridByCellCount: - OnGridGUI(); - break; - case SpriteEditorMenuSetting.SlicingType.Automatic: - OnAutomaticGUI(); - break; - } - - GUILayout.BeginHorizontal(); - GUILayout.Space(EditorGUIUtility.labelWidth + 4); - if (GUILayout.Button(s_Styles.sliceButtonLabel)) - DoSlicing(); - GUILayout.EndHorizontal(); - } - - private void DoSlicing() - { - DoAnalytics(); - switch (s_Setting.slicingType) - { - case SpriteEditorMenuSetting.SlicingType.GridByCellCount: - case SpriteEditorMenuSetting.SlicingType.GridByCellSize: - DoGridSlicing(); - break; - case SpriteEditorMenuSetting.SlicingType.Automatic: - DoAutomaticSlicing(); - break; - } - } - - private void DoAnalytics() - { - UsabilityAnalytics.Event("Sprite Editor", "Slice", "Type", (int)s_Setting.slicingType); - var texture = m_TextureDataProvider.texture; - if (texture != null) - { - UsabilityAnalytics.Event("Sprite Editor", "Slice", "Texture Width", texture.width); - UsabilityAnalytics.Event("Sprite Editor", "Slice", "Texture Height", texture.height); - } - - if (s_Setting.slicingType == SpriteEditorMenuSetting.SlicingType.Automatic) - { - UsabilityAnalytics.Event("Sprite Editor", "Slice", "Auto Slicing Method", (int)s_Setting.autoSlicingMethod); - } - else - { - UsabilityAnalytics.Event("Sprite Editor", "Slice", "Grid Slicing Size X", (int)s_Setting.gridSpriteSize.x); - UsabilityAnalytics.Event("Sprite Editor", "Slice", "Grid Slicing Size Y", (int)s_Setting.gridSpriteSize.y); - - UsabilityAnalytics.Event("Sprite Editor", "Slice", "Grid Slicing Offset X", (int)s_Setting.gridSpriteOffset.x); - UsabilityAnalytics.Event("Sprite Editor", "Slice", "Grid Slicing Offset Y", (int)s_Setting.gridSpriteOffset.y); - - UsabilityAnalytics.Event("Sprite Editor", "Slice", "Grid Slicing Padding X", (int)s_Setting.gridSpritePadding.x); - UsabilityAnalytics.Event("Sprite Editor", "Slice", "Grid Slicing Padding Y", (int)s_Setting.gridSpritePadding.y); - } - } - - private void TwoIntFields(GUIContent label, GUIContent labelX, GUIContent labelY, ref int x, ref int y) - { - float height = EditorGUI.kSingleLineHeight; - Rect rect = GUILayoutUtility.GetRect(EditorGUILayout.kLabelFloatMinW, EditorGUILayout.kLabelFloatMaxW, height, height, EditorStyles.numberField); - - Rect labelRect = rect; - labelRect.width = EditorGUIUtility.labelWidth; - labelRect.height = EditorGUI.kSingleLineHeight; - - GUI.Label(labelRect, label); - - Rect fieldRect = rect; - fieldRect.width -= EditorGUIUtility.labelWidth; - fieldRect.height = EditorGUI.kSingleLineHeight; - fieldRect.x += EditorGUIUtility.labelWidth; - fieldRect.width /= 2; - fieldRect.width -= 2; - - EditorGUIUtility.labelWidth = 12; - - x = EditorGUI.IntField(fieldRect, labelX, x); - fieldRect.x += fieldRect.width + 3; - y = EditorGUI.IntField(fieldRect, labelY, y); - - EditorGUIUtility.labelWidth = labelRect.width; - } - - private void OnGridGUI() - { - int width, height; - m_TextureDataProvider.GetTextureActualWidthAndHeight(out width, out height); - var texture = m_TextureDataProvider.texture; - int maxWidth = texture != null ? width : 4096; - int maxHeight = texture != null ? height : 4096; - - if (s_Setting.slicingType == SpriteEditorMenuSetting.SlicingType.GridByCellCount) - { - int x = (int)s_Setting.gridCellCount.x; - int y = (int)s_Setting.gridCellCount.y; - - EditorGUI.BeginChangeCheck(); - TwoIntFields(s_Styles.columnAndRowLabel, s_Styles.columnLabel, s_Styles.rowLabel, ref x, ref y); - if (EditorGUI.EndChangeCheck()) - { - Undo.RegisterCompleteObjectUndo(s_Setting, "Change column & row"); - - s_Setting.gridCellCount.x = Mathf.Clamp(x, 1, maxWidth); - s_Setting.gridCellCount.y = Mathf.Clamp(y, 1, maxHeight); - } - } - else - { - int x = (int)s_Setting.gridSpriteSize.x; - int y = (int)s_Setting.gridSpriteSize.y; - - EditorGUI.BeginChangeCheck(); - TwoIntFields(s_Styles.pixelSizeLabel, s_Styles.xLabel, s_Styles.yLabel, ref x, ref y); - if (EditorGUI.EndChangeCheck()) - { - Undo.RegisterCompleteObjectUndo(s_Setting, "Change grid size"); - - s_Setting.gridSpriteSize.x = Mathf.Clamp(x, 1, maxWidth); - s_Setting.gridSpriteSize.y = Mathf.Clamp(y, 1, maxHeight); - } - } - - { - int x = (int)s_Setting.gridSpriteOffset.x; - int y = (int)s_Setting.gridSpriteOffset.y; - - EditorGUI.BeginChangeCheck(); - TwoIntFields(s_Styles.offsetLabel, s_Styles.xLabel, s_Styles.yLabel, ref x, ref y); - if (EditorGUI.EndChangeCheck()) - { - Undo.RegisterCompleteObjectUndo(s_Setting, "Change grid offset"); - - s_Setting.gridSpriteOffset.x = Mathf.Clamp(x, 0, maxWidth - s_Setting.gridSpriteSize.x); - s_Setting.gridSpriteOffset.y = Mathf.Clamp(y, 0, maxHeight - s_Setting.gridSpriteSize.y); - } - } - - { - int x = (int)s_Setting.gridSpritePadding.x; - int y = (int)s_Setting.gridSpritePadding.y; - - EditorGUI.BeginChangeCheck(); - TwoIntFields(s_Styles.paddingLabel, s_Styles.xLabel, s_Styles.yLabel, ref x, ref y); - if (EditorGUI.EndChangeCheck()) - { - Undo.RegisterCompleteObjectUndo(s_Setting, "Change grid padding"); - - s_Setting.gridSpritePadding.x = Mathf.Clamp(x, 0, maxWidth); - s_Setting.gridSpritePadding.y = Mathf.Clamp(y, 0, maxHeight); - } - } - - DoPivotGUI(); - - GUILayout.Space(2f); - } - - private void OnAutomaticGUI() - { - float spacing = 38f; - var texture = m_TextureDataProvider.texture; - if (texture != null && UnityEditor.TextureUtil.IsCompressedTextureFormat(texture.format)) - { - EditorGUILayout.LabelField(s_Styles.automaticSlicingHintLabel, s_Styles.notice); - spacing -= 31f; - } - - DoPivotGUI(); - - EditorGUI.BeginChangeCheck(); - int slicingMethod = s_Setting.autoSlicingMethod; - slicingMethod = EditorGUILayout.Popup(s_Styles.methodLabel, slicingMethod, s_Styles.slicingMethodOptions); - if (EditorGUI.EndChangeCheck()) - { - Undo.RegisterCompleteObjectUndo(s_Setting, "Change Slicing Method"); - s_Setting.autoSlicingMethod = slicingMethod; - } - GUILayout.Space(spacing); - } - - private void DoPivotGUI() - { - EditorGUI.BeginChangeCheck(); - int alignment = s_Setting.spriteAlignment; - alignment = EditorGUILayout.Popup(s_Styles.pivotLabel, alignment, s_Styles.spriteAlignmentOptions); - if (EditorGUI.EndChangeCheck()) - { - Undo.RegisterCompleteObjectUndo(s_Setting, "Change Alignment"); - s_Setting.spriteAlignment = alignment; - s_Setting.pivot = SpriteEditorUtility.GetPivotValue((SpriteAlignment)alignment, s_Setting.pivot); - } - - Vector2 pivot = s_Setting.pivot; - EditorGUI.BeginChangeCheck(); - using (new EditorGUI.DisabledScope(alignment != (int)SpriteAlignment.Custom)) - { - pivot = EditorGUILayout.Vector2Field(s_Styles.customPivotLabel, pivot); - } - if (EditorGUI.EndChangeCheck()) - { - Undo.RegisterCompleteObjectUndo(s_Setting, "Change custom pivot"); - - s_Setting.pivot = pivot; - } - } - - private void DoAutomaticSlicing() - { - // 4 seems to be a pretty nice min size for a automatic sprite slicing. It used to be exposed to the slicing dialog, but it is actually better workflow to slice&crop manually than find a suitable size number - m_SpriteFrameModule.DoAutomaticSlicing(4, s_Setting.spriteAlignment, s_Setting.pivot, (SpriteFrameModule.AutoSlicingMethod)s_Setting.autoSlicingMethod); - } - - private void DoGridSlicing() - { - if (s_Setting.slicingType == SpriteEditorMenuSetting.SlicingType.GridByCellCount) - DetemineGridCellSizeWithCellCount(); - - m_SpriteFrameModule.DoGridSlicing(s_Setting.gridSpriteSize, s_Setting.gridSpriteOffset, s_Setting.gridSpritePadding, s_Setting.spriteAlignment, s_Setting.pivot); - } - - private void DetemineGridCellSizeWithCellCount() - { - int width, height; - m_TextureDataProvider.GetTextureActualWidthAndHeight(out width, out height); - var texture = m_TextureDataProvider.texture; - int maxWidth = texture != null ? width : 4096; - int maxHeight = texture != null ? height : 4096; - - s_Setting.gridSpriteSize.x = (maxWidth - s_Setting.gridSpriteOffset.x - (s_Setting.gridSpritePadding.x * s_Setting.gridCellCount.x)) / s_Setting.gridCellCount.x; - s_Setting.gridSpriteSize.y = (maxHeight - s_Setting.gridSpriteOffset.y - (s_Setting.gridSpritePadding.y * s_Setting.gridCellCount.y)) / s_Setting.gridCellCount.y; - - s_Setting.gridSpriteSize.x = Mathf.Clamp(s_Setting.gridSpriteSize.x, 1, maxWidth); - s_Setting.gridSpriteSize.y = Mathf.Clamp(s_Setting.gridSpriteSize.y, 1, maxHeight); - } - } -} diff --git a/Editor/Mono/SpriteEditor/SpriteEditorUtility.cs b/Editor/Mono/SpriteEditor/SpriteEditorUtility.cs deleted file mode 100644 index cf7b98d36a..0000000000 --- a/Editor/Mono/SpriteEditor/SpriteEditorUtility.cs +++ /dev/null @@ -1,188 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; -using UnityEngine.Assertions; -using Object = UnityEngine.Object; - -namespace UnityEditorInternal -{ - static internal class SpriteEditorUtility - { - public static Vector2 GetPivotValue(SpriteAlignment alignment, Vector2 customOffset) - { - switch (alignment) - { - case SpriteAlignment.BottomLeft: - return new Vector2(0f, 0f); - case SpriteAlignment.BottomCenter: - return new Vector2(0.5f, 0f); - case SpriteAlignment.BottomRight: - return new Vector2(1f, 0f); - - case SpriteAlignment.LeftCenter: - return new Vector2(0f, 0.5f); - case SpriteAlignment.Center: - return new Vector2(0.5f, 0.5f); - case SpriteAlignment.RightCenter: - return new Vector2(1f, 0.5f); - - case SpriteAlignment.TopLeft: - return new Vector2(0f, 1f); - case SpriteAlignment.TopCenter: - return new Vector2(0.5f, 1f); - case SpriteAlignment.TopRight: - return new Vector2(1f, 1f); - - case SpriteAlignment.Custom: - return customOffset; - } - return Vector2.zero; - } - - public static Rect RoundedRect(Rect rect) - { - return new Rect( - Mathf.RoundToInt(rect.xMin), - Mathf.RoundToInt(rect.yMin), - Mathf.RoundToInt(rect.width), - Mathf.RoundToInt(rect.height) - ); - } - - public static Rect RoundToInt(Rect r) - { - r.xMin = Mathf.RoundToInt(r.xMin); - r.yMin = Mathf.RoundToInt(r.yMin); - r.xMax = Mathf.RoundToInt(r.xMax); - r.yMax = Mathf.RoundToInt(r.yMax); - - return r; - } - - public static Rect ClampedRect(Rect rect, Rect clamp, bool maintainSize) - { - Rect r = new Rect(rect); - - if (maintainSize) - { - Vector2 center = rect.center; - if (center.x + Mathf.Abs(rect.width) * .5f > clamp.xMax) - center.x = clamp.xMax - rect.width * .5f; - if (center.x - Mathf.Abs(rect.width) * .5f < clamp.xMin) - center.x = clamp.xMin + rect.width * .5f; - if (center.y + Mathf.Abs(rect.height) * .5f > clamp.yMax) - center.y = clamp.yMax - rect.height * .5f; - if (center.y - Mathf.Abs(rect.height) * .5f < clamp.yMin) - center.y = clamp.yMin + rect.height * .5f; - r.center = center; - } - else - { - if (r.width > 0f) - { - r.xMin = Mathf.Max(rect.xMin, clamp.xMin); - r.xMax = Mathf.Min(rect.xMax, clamp.xMax); - } - else - { - r.xMin = Mathf.Min(rect.xMin, clamp.xMax); - r.xMax = Mathf.Max(rect.xMax, clamp.xMin); - } - if (r.height > 0f) - { - r.yMin = Mathf.Max(rect.yMin, clamp.yMin); - r.yMax = Mathf.Min(rect.yMax, clamp.yMax); - } - else - { - r.yMin = Mathf.Min(rect.yMin, clamp.yMax); - r.yMax = Mathf.Max(rect.yMax, clamp.yMin); - } - } - - r.width = Mathf.Abs(r.width); - r.height = Mathf.Abs(r.height); - - return r; - } - - public static void DrawBox(Rect position) - { - Vector3[] points = new Vector3[5]; - int i = 0; - points[i++] = new Vector3(position.xMin, position.yMin, 0f); - points[i++] = new Vector3(position.xMax, position.yMin, 0f); - points[i++] = new Vector3(position.xMax, position.yMax, 0f); - points[i++] = new Vector3(position.xMin, position.yMax, 0f); - - DrawLine(points[0], points[1]); - DrawLine(points[1], points[2]); - DrawLine(points[2], points[3]); - DrawLine(points[3], points[0]); - } - - public static void DrawLine(Vector3 p1, Vector3 p2) - { - Assert.IsTrue(Event.current.type == EventType.Repaint); - GL.Vertex(p1); - GL.Vertex(p2); - } - - public static void BeginLines(Color color) - { - Assert.IsTrue(Event.current.type == EventType.Repaint); - HandleUtility.ApplyWireMaterial(); - GL.PushMatrix(); - GL.MultMatrix(Handles.matrix); - GL.Begin(GL.LINES); - GL.Color(color); - } - - public static void EndLines() - { - Assert.IsTrue(Event.current.type == EventType.Repaint); - GL.End(); - GL.PopMatrix(); - } - - 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) - { - Rect rect = GUILayoutUtility.GetRect(rectSize.x, rectSize.y); - - Rect labelRect = rect; - labelRect.width = EditorGUIUtility.labelWidth; - labelRect.height = EditorGUI.kSingleLineHeight; - - GUI.Label(labelRect, label); - - Rect fieldRect = rect; - fieldRect.width -= EditorGUIUtility.labelWidth; - fieldRect.height = EditorGUI.kSingleLineHeight; - fieldRect.x += EditorGUIUtility.labelWidth; - fieldRect.width /= 2; - fieldRect.width -= EditorGUI.kSpacingSubLabel; - - float oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = EditorGUI.kMiniLabelW; - - GUI.SetNextControlName("FourIntFields_x"); - x = EditorGUI.IntField(fieldRect, labelX, x); - fieldRect.x += fieldRect.width + EditorGUI.kSpacing; - GUI.SetNextControlName("FourIntFields_y"); - y = EditorGUI.IntField(fieldRect, labelY, y); - fieldRect.y += EditorGUI.kSingleLineHeight + EditorGUI.kVerticalSpacingMultiField; - fieldRect.x -= fieldRect.width + EditorGUI.kSpacing; - GUI.SetNextControlName("FourIntFields_z"); - z = EditorGUI.IntField(fieldRect, labelZ, z); - fieldRect.x += fieldRect.width + EditorGUI.kSpacing; - GUI.SetNextControlName("FourIntFields_w"); - w = EditorGUI.IntField(fieldRect, labelW, w); - - EditorGUIUtility.labelWidth = oldLabelWidth; - } - } -} diff --git a/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs b/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs deleted file mode 100644 index 22667271f1..0000000000 --- a/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs +++ /dev/null @@ -1,885 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using UnityEngine; -using UnityEditorInternal; -using UnityEditor.U2D; -using System.Collections.Generic; -using UnityEditor.Experimental.U2D; -using UnityEditor.U2D.Interface; -using UnityEngine.U2D.Interface; -using UnityTexture2D = UnityEngine.Texture2D; -using System.Linq; -using System.Reflection; - -namespace UnityEditor -{ - internal class SpriteEditorWindow : SpriteUtilityWindow, ISpriteEditor - { - private class SpriteEditorWindowStyles - { - public static readonly GUIContent editingDisableMessageLabel = EditorGUIUtility.TrTextContent("Editing is disabled during play mode"); - public static readonly GUIContent revertButtonLabel = EditorGUIUtility.TrTextContent("Revert"); - public static readonly GUIContent applyButtonLabel = EditorGUIUtility.TrTextContent("Apply"); - - public static readonly GUIContent spriteEditorWindowTitle = EditorGUIUtility.TrTextContent("Sprite Editor"); - - public static readonly GUIContent pendingChangesDialogContent = EditorGUIUtility.TrTextContent("The asset was modified outside of Sprite Editor Window.\nDo you want to apply pending changes?"); - - public static readonly GUIContent applyRevertDialogTitle = EditorGUIUtility.TrTextContent("Unapplied import settings"); - public static readonly GUIContent applyRevertDialogContent = EditorGUIUtility.TrTextContent("Unapplied import settings for '{0}'"); - - public static readonly GUIContent noSelectionWarning = EditorGUIUtility.TrTextContent("No texture or sprite selected"); - public static readonly GUIContent noModuleWarning = EditorGUIUtility.TrTextContent("No Sprite Editor module available"); - public static readonly GUIContent applyRevertModuleDialogTitle = EditorGUIUtility.TrTextContent("Unapplied module changes"); - public static readonly GUIContent applyRevertModuleDialogContent = EditorGUIUtility.TrTextContent("You have unapplied changes from the current module"); - - public static readonly GUIContent loadProgressTitle = EditorGUIUtility.TrTextContent("Loading"); - public static readonly GUIContent loadContentText = EditorGUIUtility.TrTextContent("Loading Sprites {0}/{1}"); - } - - private const float k_MarginForFraming = 0.05f; - private const float k_WarningMessageWidth = 250f; - private const float k_WarningMessageHeight = 40f; - private const float k_ModuleListWidth = 90f; - - public static SpriteEditorWindow s_Instance; - public bool m_ResetOnNextRepaint; - - private List m_RectsCache; - ISpriteEditorDataProvider m_SpriteDataProvider; - - private bool m_RequestRepaint = false; - - public static bool s_OneClickDragStarted = false; - public string m_SelectedAssetPath; - - private IEventSystem m_EventSystem; - private IUndoSystem m_UndoSystem; - private IAssetDatabase m_AssetDatabase; - private IGUIUtility m_GUIUtility; - private UnityTexture2D m_OutlineTexture; - private UnityTexture2D m_ReadableTexture; - private Dictionary m_ModuleRequireSpriteDataProvider = new Dictionary(); - - [SerializeField] - private string m_SelectedSpriteRectGUID; - - public static void GetWindow() - { - EditorWindow.GetWindow(); - } - - public SpriteEditorWindow() - { - m_EventSystem = new EventSystem(); - m_UndoSystem = new UndoSystem(); - m_AssetDatabase = new AssetDatabaseSystem(); - m_GUIUtility = new GUIUtilitySystem(); - } - - void ModifierKeysChanged() - { - if (EditorWindow.focusedWindow == this) - { - Repaint(); - } - } - - private void OnFocus() - { - if (selectedProviderChanged) - OnSelectionChange(); - } - - public void RefreshPropertiesCache() - { - m_SelectedAssetPath = GetSelectionAssetPath(); - m_SpriteDataProvider = AssetImporter.GetAtPath(m_SelectedAssetPath) as ISpriteEditorDataProvider; - if (m_SpriteDataProvider == null) - return; - - m_SpriteDataProvider.InitSpriteEditorDataProvider(); - - var textureProvider = m_SpriteDataProvider.GetDataProvider(); - if (textureProvider != null) - { - int width = 0, height = 0; - textureProvider.GetTextureActualWidthAndHeight(out width, out height); - m_Texture = textureProvider.texture == null ? null : new PreviewTexture2D(textureProvider.texture, width, height); - } - } - - internal string GetSelectionAssetPath() - { - var selection = Selection.activeObject; - - if (Selection.activeGameObject) - { - if (Selection.activeGameObject.GetComponent()) - { - if (Selection.activeGameObject.GetComponent().sprite) - { - selection = UnityEditor.Sprites.SpriteUtility.GetSpriteTexture(Selection.activeGameObject.GetComponent().sprite, false); - } - } - } - return m_AssetDatabase.GetAssetPath(selection); - } - - public void InvalidatePropertiesCache() - { - m_RectsCache = null; - m_SpriteDataProvider = null; - } - - private Rect warningMessageRect - { - get - { - return new Rect( - position.width - k_WarningMessageWidth - k_InspectorWindowMargin - k_ScrollbarMargin, - k_InspectorWindowMargin + k_ScrollbarMargin, - k_WarningMessageWidth, - k_WarningMessageHeight); - } - } - - private bool multipleSprites - { - get - { - return spriteImportMode == SpriteImportMode.Multiple; - } - } - - private bool validSprite - { - get - { - return spriteImportMode != SpriteImportMode.None; - } - } - - public SpriteImportMode spriteImportMode - { - get { return m_SpriteDataProvider == null ? SpriteImportMode.None : m_SpriteDataProvider.spriteImportMode; } - } - - bool activeDataProviderSelected - { - get { return m_SpriteDataProvider != null; } - } - - public bool textureIsDirty - { - get; set; - } - - public bool selectedProviderChanged - { - get { return m_SelectedAssetPath != GetSelectionAssetPath(); } - } - - public bool IsEditingDisabled() - { - return EditorApplication.isPlayingOrWillChangePlaymode; - } - - void OnSelectionChange() - { - // In case of changed of texture/sprite or selected on non texture object - var assetPath = GetSelectionAssetPath(); - var ai = AssetImporter.GetAtPath(assetPath); - var dataProvider = ai as ISpriteEditorDataProvider; - bool updateModules = false; - - if (dataProvider == null || selectedProviderChanged) - { - HandleApplyRevertDialog(SpriteEditorWindowStyles.applyRevertDialogTitle.text, - String.Format(SpriteEditorWindowStyles.applyRevertDialogContent.text, m_SelectedAssetPath)); - ResetWindow(); - RefreshPropertiesCache(); - RefreshRects(); - updateModules = true; - } - - if (m_RectsCache != null) - { - if (Selection.activeObject is Sprite) - UpdateSelectedSpriteRect(Selection.activeObject as Sprite); - else if (Selection.activeGameObject != null && Selection.activeGameObject.GetComponent()) - { - Sprite sprite = Selection.activeGameObject.GetComponent().sprite; - UpdateSelectedSpriteRect(sprite); - } - } - - // We only update modules when data provider changed - if (updateModules) - UpdateAvailableModules(); - Repaint(); - } - - public void ResetWindow() - { - InvalidatePropertiesCache(); - textureIsDirty = false; - m_Zoom = -1; - } - - void OnEnable() - { - minSize = new Vector2(360, 200); - titleContent = SpriteEditorWindowStyles.spriteEditorWindowTitle; - s_Instance = this; - m_UndoSystem.RegisterUndoCallback(UndoRedoPerformed); - EditorApplication.modifierKeysChanged += ModifierKeysChanged; - ResetWindow(); - RefreshPropertiesCache(); - RefreshRects(); - InitModules(); - } - - private void UndoRedoPerformed() - { - // Was selected texture changed by undo? - if (selectedProviderChanged) - OnSelectionChange(); - - InitSelectedSpriteRect(); - - Repaint(); - } - - private void InitSelectedSpriteRect() - { - SpriteRect newSpriteRect = null; - if (m_RectsCache != null && m_RectsCache.Count > 0) - { - if (selectedSpriteRect != null) - newSpriteRect = m_RectsCache.FirstOrDefault(x => x.spriteID == selectedSpriteRect.spriteID) != null ? selectedSpriteRect : m_RectsCache[0]; - else - newSpriteRect = m_RectsCache[0]; - } - - selectedSpriteRect = newSpriteRect; - } - - private void OnDisable() - { - Undo.undoRedoPerformed -= UndoRedoPerformed; - HandleApplyRevertDialog(SpriteEditorWindowStyles.applyRevertDialogTitle.text, - String.Format(SpriteEditorWindowStyles.applyRevertDialogContent.text, m_SelectedAssetPath)); - InvalidatePropertiesCache(); - EditorApplication.modifierKeysChanged -= ModifierKeysChanged; - s_Instance = null; - - if (m_OutlineTexture != null) - { - DestroyImmediate(m_OutlineTexture); - m_OutlineTexture = null; - } - - if (m_ReadableTexture) - { - DestroyImmediate(m_ReadableTexture); - m_ReadableTexture = null; - } - - if (m_CurrentModule != null) - m_CurrentModule.OnModuleDeactivate(); - } - - void HandleApplyRevertDialog(string dialogTitle, string dialogContent) - { - if (textureIsDirty && m_SpriteDataProvider != null) - { - if (EditorUtility.DisplayDialog(dialogTitle, dialogContent, - SpriteEditorWindowStyles.applyButtonLabel.text, SpriteEditorWindowStyles.revertButtonLabel.text)) - DoApply(); - else - DoRevert(); - - SetupModule(m_CurrentModuleIndex); - } - } - - void RefreshRects() - { - m_RectsCache = null; - if (m_SpriteDataProvider != null) - { - m_RectsCache = m_SpriteDataProvider.GetSpriteRects().ToList(); - } - - InitSelectedSpriteRect(); - } - - void OnGUI() - { - InitStyles(); - - if (m_ResetOnNextRepaint || selectedProviderChanged || m_RectsCache == null) - { - m_ResetOnNextRepaint = false; - HandleApplyRevertDialog(SpriteEditorWindowStyles.applyRevertDialogTitle.text, SpriteEditorWindowStyles.pendingChangesDialogContent.text); - ResetWindow(); - RefreshPropertiesCache(); - RefreshRects(); - UpdateAvailableModules(); - SetupModule(m_CurrentModuleIndex); - } - Matrix4x4 oldHandlesMatrix = Handles.matrix; - - if (!activeDataProviderSelected) - { - using (new EditorGUI.DisabledScope(true)) - { - GUILayout.Label(SpriteEditorWindowStyles.noSelectionWarning); - } - return; - } - - if (m_CurrentModule == null) - { - using (new EditorGUI.DisabledScope(true)) - { - GUILayout.Label(SpriteEditorWindowStyles.noModuleWarning); - } - return; - } - - // Top menu bar - DoToolbarGUI(); - DoTextureGUI(); - - // Warning message if applicable - DoEditingDisabledMessage(); - m_CurrentModule.DoPostGUI(); - Handles.matrix = oldHandlesMatrix; - - if (m_RequestRepaint == true) - { - Repaint(); - m_RequestRepaint = false; - } - } - - protected override void DoTextureGUIExtras() - { - HandleFrameSelected(); - - if (m_EventSystem.current.type == EventType.Repaint) - { - SpriteEditorUtility.BeginLines(new Color(1f, 1f, 1f, 0.5f)); - var selectedRect = selectedSpriteRect?.spriteID; - for (int i = 0; i < m_RectsCache.Count; i++) - { - if (m_RectsCache[i].spriteID != selectedRect) - SpriteEditorUtility.DrawBox(m_RectsCache[i].rect); - } - SpriteEditorUtility.EndLines(); - } - - m_CurrentModule.DoMainGUI(); - } - - private void DoToolbarGUI() - { - GUIStyle toolBarStyle = EditorStyles.toolbar; - - Rect toolbarRect = new Rect(0, 0, position.width, k_ToolbarHeight); - if (m_EventSystem.current.type == EventType.Repaint) - { - toolBarStyle.Draw(toolbarRect, false, false, false, false); - } - m_TextureViewRect = new Rect(0f, k_ToolbarHeight, position.width - k_ScrollbarMargin, position.height - k_ScrollbarMargin - k_ToolbarHeight); - - // Top menu bar - - // only show popup if there is more than 1 module. - if (m_RegisteredModules.Count > 1) - { - float moduleWidthPercentage = k_ModuleListWidth / minSize.x; - float moduleListWidth = position.width > minSize.x ? position.width * moduleWidthPercentage : k_ModuleListWidth; - moduleListWidth = Mathf.Min(moduleListWidth, EditorStyles.popup.CalcSize(m_RegisteredModuleNames[m_CurrentModuleIndex]).x); - int module = EditorGUI.Popup(new Rect(0, 0, moduleListWidth, k_ToolbarHeight), m_CurrentModuleIndex, m_RegisteredModuleNames, EditorStyles.toolbarPopup); - if (module != m_CurrentModuleIndex) - { - if (textureIsDirty) - { - // Have pending module edit changes. Ask user if they want to apply or revert - if (EditorUtility.DisplayDialog(SpriteEditorWindowStyles.applyRevertModuleDialogTitle.text, - SpriteEditorWindowStyles.applyRevertModuleDialogContent.text, - SpriteEditorWindowStyles.applyButtonLabel.text, SpriteEditorWindowStyles.revertButtonLabel.text)) - DoApply(); - else - DoRevert(); - } - SetupModule(module); - } - toolbarRect.x = moduleListWidth; - } - - toolbarRect = DoAlphaZoomToolbarGUI(toolbarRect); - - Rect applyRevertDrawArea = toolbarRect; - applyRevertDrawArea.x = applyRevertDrawArea.width; - - using (new EditorGUI.DisabledScope(!textureIsDirty)) - { - applyRevertDrawArea.width = EditorStyles.toolbarButton.CalcSize(SpriteEditorWindowStyles.applyButtonLabel).x; - applyRevertDrawArea.x -= applyRevertDrawArea.width; - if (GUI.Button(applyRevertDrawArea, SpriteEditorWindowStyles.applyButtonLabel, EditorStyles.toolbarButton)) - { - DoApply(); - SetupModule(m_CurrentModuleIndex); - } - - applyRevertDrawArea.width = EditorStyles.toolbarButton.CalcSize(SpriteEditorWindowStyles.revertButtonLabel).x; - applyRevertDrawArea.x -= applyRevertDrawArea.width; - if (GUI.Button(applyRevertDrawArea, SpriteEditorWindowStyles.revertButtonLabel, EditorStyles.toolbarButton)) - { - DoRevert(); - SetupModule(m_CurrentModuleIndex); - } - } - - toolbarRect.width = applyRevertDrawArea.x - toolbarRect.x; - m_CurrentModule.DoToolbarGUI(toolbarRect); - } - - private void DoEditingDisabledMessage() - { - if (IsEditingDisabled()) - { - GUILayout.BeginArea(warningMessageRect); - EditorGUILayout.HelpBox(SpriteEditorWindowStyles.editingDisableMessageLabel.text, MessageType.Warning); - GUILayout.EndArea(); - } - } - - private void DoApply() - { - bool reimport = true; - if (m_CurrentModule != null) - reimport = m_CurrentModule.ApplyRevert(true); - m_SpriteDataProvider.Apply(); - - // Do this so that asset change save dialog will not show - var originalValue = EditorPrefs.GetBool("VerifySavingAssets", false); - EditorPrefs.SetBool("VerifySavingAssets", false); - AssetDatabase.ForceReserializeAssets(new[] {m_SelectedAssetPath}, ForceReserializeAssetsOptions.ReserializeMetadata); - EditorPrefs.SetBool("VerifySavingAssets", originalValue); - - if (reimport) - DoTextureReimport(m_SelectedAssetPath); - Repaint(); - - textureIsDirty = false; - InitSelectedSpriteRect(); - } - - private void DoRevert() - { - textureIsDirty = false; - RefreshRects(); - GUI.FocusControl(""); - if (m_CurrentModule != null) - m_CurrentModule.ApplyRevert(false); - } - - public bool HandleSpriteSelection() - { - bool changed = false; - - if (m_EventSystem.current.type == EventType.MouseDown && m_EventSystem.current.button == 0 && GUIUtility.hotControl == 0 && !m_EventSystem.current.alt) - { - var oldSelected = selectedSpriteRect; - - var triedRect = TrySelect(m_EventSystem.current.mousePosition); - if (triedRect != oldSelected) - { - Undo.RegisterCompleteObjectUndo(this, "Sprite Selection"); - - selectedSpriteRect = triedRect; - changed = true; - } - - if (selectedSpriteRect != null) - s_OneClickDragStarted = true; - else - RequestRepaint(); - - if (changed && selectedSpriteRect != null) - { - m_EventSystem.current.Use(); - } - } - return changed; - } - - private void HandleFrameSelected() - { - UnityEngine.U2D.Interface.IEvent evt = m_EventSystem.current; - - if ((evt.type == EventType.ValidateCommand || evt.type == EventType.ExecuteCommand) - && evt.commandName == EventCommandNames.FrameSelected) - { - if (evt.type == EventType.ExecuteCommand) - { - // Do not do frame if there is none selected - if (selectedSpriteRect == null) - return; - - Rect rect = selectedSpriteRect.rect; - - // Calculate the require pixel to display the frame, then get the zoom needed. - float targetZoom = m_Zoom; - if (rect.width < rect.height) - targetZoom = m_TextureViewRect.height / (rect.height + m_TextureViewRect.height * k_MarginForFraming); - else - targetZoom = m_TextureViewRect.width / (rect.width + m_TextureViewRect.width * k_MarginForFraming); - - // Apply the zoom - m_Zoom = targetZoom; - - // Calculate the scroll values to center the frame - m_ScrollPosition.x = (rect.center.x - (m_Texture.width * 0.5f)) * m_Zoom; - m_ScrollPosition.y = (rect.center.y - (m_Texture.height * 0.5f)) * m_Zoom * -1.0f; - - Repaint(); - } - - evt.Use(); - } - } - - void UpdateSelectedSpriteRect(Sprite sprite) - { - var spriteGUID = sprite.GetSpriteID(); - for (int i = 0; i < m_RectsCache.Count; i++) - { - if (spriteGUID == m_RectsCache[i].spriteID) - { - selectedSpriteRect = m_RectsCache[i]; - return; - } - } - selectedSpriteRect = null; - } - - private SpriteRect TrySelect(Vector2 mousePosition) - { - float selectedSize = float.MaxValue; - SpriteRect currentRect = null; - mousePosition = Handles.inverseMatrix.MultiplyPoint(mousePosition); - - for (int i = 0; i < m_RectsCache.Count; i++) - { - var sr = m_RectsCache[i]; - if (sr.rect.Contains(mousePosition)) - { - // If we clicked inside an already selected spriterect, always persist that selection - if (sr == selectedSpriteRect) - return sr; - - float width = sr.rect.width; - float height = sr.rect.height; - float newSize = width * height; - if (width > 0f && height > 0f && newSize < selectedSize) - { - currentRect = sr; - selectedSize = newSize; - } - } - } - - return currentRect; - } - - public void DoTextureReimport(string path) - { - if (m_SpriteDataProvider != null) - { - try - { - AssetDatabase.StartAssetEditing(); - AssetDatabase.ImportAsset(path); - } - finally - { - AssetDatabase.StopAssetEditing(); - } - } - } - - GUIContent[] m_RegisteredModuleNames; - List m_AllRegisteredModules; - List m_RegisteredModules; - SpriteEditorModuleBase m_CurrentModule = null; - int m_CurrentModuleIndex = 0; - - void SetupModule(int newModuleIndex) - { - if (s_Instance == null) - return; - - if (m_RegisteredModules.Count > newModuleIndex) - { - m_CurrentModuleIndex = newModuleIndex; - if (m_CurrentModule != null) - m_CurrentModule.OnModuleDeactivate(); - - m_CurrentModule = null; - - m_CurrentModule = m_RegisteredModules[newModuleIndex]; - m_CurrentModule.OnModuleActivate(); - } - } - - void UpdateAvailableModules() - { - if (m_AllRegisteredModules == null) - return; - m_RegisteredModules = new List(); - foreach (var module in m_AllRegisteredModules) - { - if (module.CanBeActivated()) - { - RequireSpriteDataProviderAttribute attribute = null; - m_ModuleRequireSpriteDataProvider.TryGetValue(module.GetType(), out attribute); - if (attribute == null || attribute.ContainsAllType(m_SpriteDataProvider)) - m_RegisteredModules.Add(module); - } - } - - m_RegisteredModuleNames = new GUIContent[m_RegisteredModules.Count]; - for (int i = 0; i < m_RegisteredModules.Count; i++) - { - m_RegisteredModuleNames[i] = new GUIContent(m_RegisteredModules[i].moduleName); - } - - if (!(m_RegisteredModules.Contains(m_CurrentModule))) - { - SetupModule(0); - } - else - SetupModule(m_CurrentModuleIndex); - } - - void InitModules() - { - m_AllRegisteredModules = new List(); - m_ModuleRequireSpriteDataProvider.Clear(); - - if (m_OutlineTexture == null) - { - m_OutlineTexture = new UnityTexture2D(1, 16, TextureFormat.RGBA32, false); - m_OutlineTexture.SetPixels(new Color[] - { - new Color(0.5f, 0.5f, 0.5f, 0.5f), new Color(0.5f, 0.5f, 0.5f, 0.5f), new Color(0.8f, 0.8f, 0.8f, 0.8f), new Color(0.8f, 0.8f, 0.8f, 0.8f), - Color.white, Color.white, Color.white, Color.white, - new Color(.8f, .8f, .8f, 1f), new Color(.5f, .5f, .5f, .8f), new Color(0.3f, 0.3f, 0.3f, 0.5f), new Color(0.3f, .3f, 0.3f, 0.5f), - new Color(0.3f, .3f, 0.3f, 0.3f), new Color(0.3f, .3f, 0.3f, 0.3f), new Color(0.1f, 0.1f, 0.1f, 0.1f), new Color(0.1f, .1f, 0.1f, 0.1f) - }); - m_OutlineTexture.Apply(); - m_OutlineTexture.hideFlags = HideFlags.HideAndDontSave; - } - var outlineTexture = new UnityEngine.U2D.Interface.Texture2D(m_OutlineTexture); - - // Add your modules here - RegisterModule(new SpriteFrameModule(this, m_EventSystem, m_UndoSystem, m_AssetDatabase)); - RegisterModule(new SpritePolygonModeModule(this, m_EventSystem, m_UndoSystem, m_AssetDatabase)); - RegisterModule(new SpriteOutlineModule(this, m_EventSystem, m_UndoSystem, m_AssetDatabase, m_GUIUtility, new ShapeEditorFactory(), outlineTexture)); - RegisterModule(new SpritePhysicsShapeModule(this, m_EventSystem, m_UndoSystem, m_AssetDatabase, m_GUIUtility, new ShapeEditorFactory(), outlineTexture)); - RegisterCustomModules(); - UpdateAvailableModules(); - } - - void RegisterModule(SpriteEditorModuleBase module) - { - var type = module.GetType(); - var attributes = type.GetCustomAttributes(typeof(RequireSpriteDataProviderAttribute), false); - if (attributes.Length == 1) - m_ModuleRequireSpriteDataProvider.Add(type, (RequireSpriteDataProviderAttribute)attributes[0]); - m_AllRegisteredModules.Add(module); - } - - void RegisterCustomModules() - { - var type = typeof(SpriteEditorModuleBase); - foreach (var moduleClassType in EditorAssemblies.SubclassesOf(type)) - { - if (!moduleClassType.IsAbstract) - { - bool moduleFound = false; - foreach (var module in m_AllRegisteredModules) - { - if (module.GetType() == moduleClassType) - { - moduleFound = true; - break; - } - } - if (!moduleFound) - { - var constructorType = new Type[0]; - // Get the public instance constructor that takes ISpriteEditorModule parameter. - var constructorInfoObj = moduleClassType.GetConstructor( - BindingFlags.Instance | BindingFlags.Public, null, - CallingConventions.HasThis, constructorType, null); - if (constructorInfoObj != null) - { - try - { - var newInstance = constructorInfoObj.Invoke(new object[0]) as SpriteEditorModuleBase; - if (newInstance != null) - { - newInstance.spriteEditor = this; - RegisterModule(newInstance); - } - } - catch (Exception ex) - { - Debug.LogWarning("Unable to instantiate custom module " + moduleClassType.FullName + ". Exception:" + ex); - } - } - else - Debug.LogWarning(moduleClassType.FullName + " does not have a parameterless constructor"); - } - } - } - } - - internal List activatedModules - { - get { return m_RegisteredModules; } - } - - public List spriteRects - { - set { m_RectsCache = value; } - } - - public SpriteRect selectedSpriteRect - { - get - { - // Always return null if editing is disabled to prevent all possible action to selected frame. - if (editingDisabled || m_RectsCache == null || string.IsNullOrEmpty(m_SelectedSpriteRectGUID)) - return null; - - var guid = new GUID(m_SelectedSpriteRectGUID); - return m_RectsCache.FirstOrDefault(x => x.spriteID == guid); - } - set - { - m_SelectedSpriteRectGUID = value?.spriteID.ToString(); - } - } - - public ISpriteEditorDataProvider spriteEditorDataProvider - { - get { return m_SpriteDataProvider; } - } - - public bool enableMouseMoveEvent - { - set { wantsMouseMove = value; } - } - - public void RequestRepaint() - { - if (focusedWindow != this) - Repaint(); - else - m_RequestRepaint = true; - } - - public void SetDataModified() - { - textureIsDirty = true; - } - - public Rect windowDimension - { - get { return m_TextureViewRect; } - } - - public ITexture2D previewTexture - { - get { return m_Texture; } - } - - public bool editingDisabled - { - get { return EditorApplication.isPlayingOrWillChangePlaymode; } - } - - public void ApplyOrRevertModification(bool apply) - { - if (apply) - DoApply(); - else - DoRevert(); - } - - internal class PreviewTexture2D : UnityEngine.U2D.Interface.Texture2D - { - private int m_ActualWidth = 0; - private int m_ActualHeight = 0; - - public PreviewTexture2D(UnityTexture2D t, int width, int height) - : base(t) - { - m_ActualWidth = width; - m_ActualHeight = height; - } - - public override int width - { - get { return m_ActualWidth; } - } - - public override int height - { - get { return m_ActualHeight; } - } - } - - public T GetDataProvider() where T : class - { - return m_SpriteDataProvider?.GetDataProvider(); - } - - static internal void OnTextureReimport(string path) - { - if (s_Instance != null && s_Instance.m_SelectedAssetPath == path) - { - s_Instance.m_ResetOnNextRepaint = true; - s_Instance.Repaint(); - } - } - } - - internal class SpriteEditorTexturePostprocessor : AssetPostprocessor - { - public override int GetPostprocessOrder() - { - return 1; - } - - static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) - { - foreach (var importedAsset in importedAssets) - { - SpriteEditorWindow.OnTextureReimport(importedAsset); - } - } - } -} diff --git a/Editor/Mono/SpriteEditor/SpriteRect.cs b/Editor/Mono/SpriteEditor/SpriteRect.cs deleted file mode 100644 index c494ea2a0c..0000000000 --- a/Editor/Mono/SpriteEditor/SpriteRect.cs +++ /dev/null @@ -1,174 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Collections.Generic; -using System.Collections; -using UnityEditor.Experimental.U2D; -using UnityEditorInternal; - -namespace UnityEditor -{ - [Serializable] - public class SpriteRect - { - [SerializeField] - string m_Name; - - [SerializeField] - string m_OriginalName; - - [SerializeField] - Vector2 m_Pivot; - - [SerializeField] - SpriteAlignment m_Alignment; - - [SerializeField] - Vector4 m_Border; - - [SerializeField] - Rect m_Rect; - - [SerializeField] - string m_SpriteID; - - GUID m_GUID; - - public string name - { - get { return m_Name; } - set { m_Name = value; } - } - - public Vector2 pivot - { - get { return m_Pivot; } - set { m_Pivot = value; } - } - - public SpriteAlignment alignment - { - get { return m_Alignment; } - set { m_Alignment = value; } - } - - public Vector4 border - { - get { return m_Border; } - set { m_Border = value; } - } - - public Rect rect - { - get { return m_Rect; } - set { m_Rect = value; } - } - - internal string originalName - { - get - { - if (m_OriginalName == null) - { - m_OriginalName = name; - } - return m_OriginalName; - } - - set { m_OriginalName = value; } - } - - public GUID spriteID - { - get - { - ValidateGUID(); - return m_GUID; - } - set - { - m_GUID = value; - m_SpriteID = m_GUID.ToString(); - ValidateGUID(); - } - } - - private void ValidateGUID() - { - if (m_GUID.Empty()) - { - // We can't use ISerializationCallbackReceiver because we will hit into Script serialization errors - m_GUID = new GUID(m_SpriteID); - if (m_GUID.Empty()) - { - m_GUID = GUID.Generate(); - m_SpriteID = m_GUID.ToString(); - } - } - } - - public static GUID GetSpriteIDFromSerializedProperty(SerializedProperty sp) - { - return new GUID(sp.FindPropertyRelative("m_SpriteID").stringValue); - } - } - - internal class SpriteRectCache : ScriptableObject - { - [SerializeField] - public List m_Rects; - - public int Count - { - get { return m_Rects != null ? m_Rects.Count : 0; } - } - - public SpriteRect RectAt(int i) - { - return i >= Count || i < 0 ? null : m_Rects[i]; - } - - public void AddRect(SpriteRect r) - { - if (m_Rects != null) - m_Rects.Add(r); - } - - public void RemoveRect(SpriteRect r) - { - if (m_Rects != null) - m_Rects.RemoveAll(x => x.spriteID == r.spriteID); - } - - public void ClearAll() - { - if (m_Rects != null) - m_Rects.Clear(); - } - - public int GetIndex(SpriteRect spriteRect) - { - if (m_Rects != null && spriteRect != null) - return m_Rects.FindIndex(p => p.spriteID == spriteRect.spriteID); - - return -1; - } - - public bool Contains(SpriteRect spriteRect) - { - if (m_Rects != null && spriteRect != null) - return m_Rects.Find(x => x.spriteID == spriteRect.spriteID) != null; - - return false; - } - - void OnEnable() - { - if (m_Rects == null) - m_Rects = new List(); - } - } -} diff --git a/Editor/Mono/SpritePacker.bindings.cs b/Editor/Mono/SpritePacker.bindings.cs deleted file mode 100644 index 2840cb9a03..0000000000 --- a/Editor/Mono/SpritePacker.bindings.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditor.Sprites -{ - [StructLayout(LayoutKind.Sequential)] - public struct AtlasSettings - { - public TextureFormat format; - public ColorSpace colorSpace; - public int compressionQuality; - public FilterMode filterMode; - public int maxWidth; - public int maxHeight; - public uint paddingPower; - public int anisoLevel; - public bool generateMipMaps; - public bool enableRotation; - public bool allowsAlphaSplitting; - } - - [NativeHeader("Editor/Src/SpritePacker/SpritePacker.h")] - public sealed class PackerJob - { - internal PackerJob() - { - } - - [FreeFunction("SpritePacker::ActiveJob_AddAtlas")] - private static extern void Internal_AddAtlas(string atlasName, AtlasSettings settings); - [FreeFunction("SpritePacker::ActiveJob_AssignToAtlas")] - private static extern void Internal_AssignToAtlas(string atlasName, Sprite sprite, SpritePackingMode packingMode, SpritePackingRotation packingRotation); - - public void AddAtlas(string atlasName, AtlasSettings settings) - { - Internal_AddAtlas(atlasName, settings); - } - - public void AssignToAtlas(string atlasName, Sprite sprite, SpritePackingMode packingMode, SpritePackingRotation packingRotation) - { - Internal_AssignToAtlas(atlasName, sprite, packingMode, packingRotation); - } - } - - [NativeHeader("Editor/Src/SpritePacker/SpritePacker.h")] - public sealed partial class Packer - { - public extern static string[] atlasNames - { - [FreeFunction("SpritePacker::GetAvailableAtlases")] - get; - } - - [FreeFunction("SpritePacker::GetAtlasNameForSprite")] - private static extern string Internal_GetAtlasNameForSprite(Sprite sprite); - [FreeFunction("SpritePacker::GetAtlasTextureSprite")] - private static extern Texture2D Internal_GetAtlasTextureSprite(Sprite sprite); - - [FreeFunction("SpritePacker::GetTexturesForAtlas")] - public static extern Texture2D[] GetTexturesForAtlas(string atlasName); - [FreeFunction("SpritePacker::GetAlphaTexturesForAtlas")] - public static extern Texture2D[] GetAlphaTexturesForAtlas(string atlasName); - [FreeFunction("SpritePacker::RebuildAtlasCacheIfNeededFromScript")] - public static extern void RebuildAtlasCacheIfNeeded(BuildTarget target, bool displayProgressBar, Execution execution); - - public static void RebuildAtlasCacheIfNeeded(BuildTarget target, bool displayProgressBar) - { - RebuildAtlasCacheIfNeeded(target, displayProgressBar, Execution.Normal); - } - - public static void RebuildAtlasCacheIfNeeded(BuildTarget target) - { - RebuildAtlasCacheIfNeeded(target, false, Execution.Normal); - } - - public static void GetAtlasDataForSprite(Sprite sprite, out string atlasName, out Texture2D atlasTexture) - { - atlasName = Internal_GetAtlasNameForSprite(sprite); - atlasTexture = Internal_GetAtlasTextureSprite(sprite); - } - } -} diff --git a/Editor/Mono/Sprites/DefaultSpritePackerPolicy.cs b/Editor/Mono/Sprites/DefaultSpritePackerPolicy.cs deleted file mode 100644 index 49e0708dad..0000000000 --- a/Editor/Mono/Sprites/DefaultSpritePackerPolicy.cs +++ /dev/null @@ -1,152 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor.Sprites -{ - // DefaultPackerPolicy will pack rectangles no matter what Sprite mesh type is unless their packing tag contains "[TIGHT]". - internal class DefaultPackerPolicy : IPackerPolicy - { - protected class Entry - { - public Sprite sprite; - public AtlasSettings settings; - public string atlasName; - public SpritePackingMode packingMode; - public int anisoLevel; - } - - private const uint kDefaultPaddingPower = 3; // Good for base and two mip levels. - - public virtual int GetVersion() { return 1; } - public virtual bool AllowSequentialPacking { get { return false; } } - - protected virtual string TagPrefix { get { return "[TIGHT]"; } } - protected virtual bool AllowTightWhenTagged { get { return true; } } - protected virtual bool AllowRotationFlipping { get { return false; } } - - public void OnGroupAtlases(BuildTarget target, PackerJob job, int[] textureImporterInstanceIDs) - { - List entries = new List(); - - string targetName = ""; - if (target != BuildTarget.NoTarget) - { - targetName = BuildPipeline.GetBuildTargetName(target); - } - - foreach (int instanceID in textureImporterInstanceIDs) - { - TextureImporter ti = EditorUtility.InstanceIDToObject(instanceID) as TextureImporter; - - TextureFormat desiredFormat; - ColorSpace colorSpace; - int compressionQuality; - ti.ReadTextureImportInstructions(target, out desiredFormat, out colorSpace, out compressionQuality); - - TextureImporterSettings tis = new TextureImporterSettings(); - ti.ReadTextureSettings(tis); - - bool hasAlphaSplittingForCompression = (targetName != "" && HasPlatformEnabledAlphaSplittingForCompression(targetName, ti)); - - Sprite[] sprites = AssetDatabase.LoadAllAssetRepresentationsAtPath(ti.assetPath).Select(x => x as Sprite).Where(x => x != null).ToArray(); - foreach (Sprite sprite in sprites) - { - Entry entry = new Entry(); - entry.sprite = sprite; - entry.settings.format = desiredFormat; - entry.settings.colorSpace = colorSpace; - // Use Compression Quality for Grouping later only for Compressed Formats. Otherwise leave it Empty. - entry.settings.compressionQuality = UnityEditor.TextureUtil.IsCompressedTextureFormat(desiredFormat) ? compressionQuality : 0; - entry.settings.filterMode = Enum.IsDefined(typeof(FilterMode), ti.filterMode) ? ti.filterMode : FilterMode.Bilinear; - entry.settings.maxWidth = 2048; - entry.settings.maxHeight = 2048; - entry.settings.generateMipMaps = ti.mipmapEnabled; - entry.settings.enableRotation = AllowRotationFlipping; - entry.settings.allowsAlphaSplitting = TextureImporter.IsTextureFormatETC1Compression(desiredFormat) && hasAlphaSplittingForCompression; - if (ti.mipmapEnabled) - entry.settings.paddingPower = kDefaultPaddingPower; - else - entry.settings.paddingPower = (uint)EditorSettings.spritePackerPaddingPower; - entry.atlasName = ParseAtlasName(ti.spritePackingTag); - entry.packingMode = GetPackingMode(ti.spritePackingTag, tis.spriteMeshType); - entry.anisoLevel = ti.anisoLevel; - - entries.Add(entry); - } - - Resources.UnloadAsset(ti); - } - - // First split sprites into groups based on atlas name - var atlasGroups = - from e in entries - group e by e.atlasName; - foreach (var atlasGroup in atlasGroups) - { - int page = 0; - // Then split those groups into smaller groups based on texture settings - var settingsGroups = - from t in atlasGroup - group t by t.settings; - foreach (var settingsGroup in settingsGroups) - { - string atlasName = atlasGroup.Key; - if (settingsGroups.Count() > 1) - atlasName += string.Format(" (Group {0})", page); - - AtlasSettings settings = settingsGroup.Key; - settings.anisoLevel = 1; - // Use the highest aniso level from all entries in this atlas - if (settings.generateMipMaps) - foreach (Entry entry in settingsGroup) - if (entry.anisoLevel > settings.anisoLevel) - settings.anisoLevel = entry.anisoLevel; - - job.AddAtlas(atlasName, settings); - foreach (Entry entry in settingsGroup) - { - job.AssignToAtlas(atlasName, entry.sprite, entry.packingMode, SpritePackingRotation.None); - } - - ++page; - } - } - } - - protected bool HasPlatformEnabledAlphaSplittingForCompression(string targetName, TextureImporter ti) - { - TextureImporterPlatformSettings platformSettings = ti.GetPlatformTextureSettings(targetName); - return (platformSettings.overridden && platformSettings.allowsAlphaSplitting); - } - - protected bool IsTagPrefixed(string packingTag) - { - packingTag = packingTag.Trim(); - if (packingTag.Length < TagPrefix.Length) - return false; - return (packingTag.Substring(0, TagPrefix.Length) == TagPrefix); - } - - private string ParseAtlasName(string packingTag) - { - string name = packingTag.Trim(); - if (IsTagPrefixed(name)) - name = name.Substring(TagPrefix.Length).Trim(); - return (name.Length == 0) ? "(unnamed)" : name; - } - - private SpritePackingMode GetPackingMode(string packingTag, SpriteMeshType meshType) - { - if (meshType == SpriteMeshType.Tight) - if (IsTagPrefixed(packingTag) == AllowTightWhenTagged) - return SpritePackingMode.Tight; - return SpritePackingMode.Rectangle; - } - } -} diff --git a/Editor/Mono/Sprites/SpritePacker.cs b/Editor/Mono/Sprites/SpritePacker.cs deleted file mode 100644 index 12130789bb..0000000000 --- a/Editor/Mono/Sprites/SpritePacker.cs +++ /dev/null @@ -1,162 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor.Sprites -{ - public sealed partial class Packer - { - public enum Execution - { - Normal = 0, - ForceRegroup - } - - public static string kDefaultPolicy = typeof(DefaultPackerPolicy).Name; - - private static string[] m_policies = null; - public static string[] Policies - { - get - { - RegenerateList(); - return m_policies; - } - } - - private static string m_selectedPolicy = null; - private static void SetSelectedPolicy(string value) - { - m_selectedPolicy = value; - PlayerSettings.spritePackerPolicy = m_selectedPolicy; - } - - public static string SelectedPolicy - { - get - { - RegenerateList(); - return m_selectedPolicy; - } - set - { - RegenerateList(); - if (value == null) - throw new ArgumentNullException(); - if (!m_policies.Contains(value)) - throw new ArgumentException("Specified policy {0} is not in the policy list.", value); - SetSelectedPolicy(value); - } - } - - private static Dictionary m_policyTypeCache = null; - private static void RegenerateList() - { - if (m_policies != null) - return; - - List types = new List(); - - System.Reflection.Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); - foreach (var assembly in assemblies) - { - try - { - Type[] asst = assembly.GetTypes(); - foreach (var t in asst) - { - if (typeof(IPackerPolicy).IsAssignableFrom(t) && (t != typeof(IPackerPolicy))) - types.Add(t); - } - } - catch (Exception ex) - { - Debug.Log(string.Format("SpritePacker failed to get types from {0}. Error: {1}", assembly.FullName, ex.Message)); - } - } - - m_policies = types.Select(t => t.Name).ToArray(); - - m_policyTypeCache = new Dictionary(); - foreach (var t in types) - { - if (m_policyTypeCache.ContainsKey(t.Name)) - { - Type otherT = m_policyTypeCache[t.Name]; - Debug.LogError(string.Format("Duplicate Sprite Packer policies found: {0} and {1}. Please rename one.", t.FullName, otherT.FullName)); - continue; - } - else - m_policyTypeCache[t.Name] = t; - } - - m_selectedPolicy = String.IsNullOrEmpty(PlayerSettings.spritePackerPolicy) ? kDefaultPolicy : PlayerSettings.spritePackerPolicy; - - // Did policies change? - if (!m_policies.Contains(m_selectedPolicy)) - SetSelectedPolicy(kDefaultPolicy); - } - - internal static string GetSelectedPolicyId() - { - RegenerateList(); - - Type t = m_policyTypeCache[m_selectedPolicy]; - IPackerPolicy policy = Activator.CreateInstance(t) as IPackerPolicy; - string versionString = string.Format("{0}::{1}", t.AssemblyQualifiedName, policy.GetVersion()); - - return versionString; - } - - internal static bool AllowSequentialPacking() - { - RegenerateList(); - - Type t = m_policyTypeCache[m_selectedPolicy]; - IPackerPolicy policy = Activator.CreateInstance(t) as IPackerPolicy; - return policy.AllowSequentialPacking; - } - - internal static void ExecuteSelectedPolicy(BuildTarget target, int[] textureImporterInstanceIDs) - { - RegenerateList(); - - Type t = m_policyTypeCache[m_selectedPolicy]; - IPackerPolicy policy = Activator.CreateInstance(t) as IPackerPolicy; - policy.OnGroupAtlases(target, new PackerJob(), textureImporterInstanceIDs); - } - - internal static void SaveUnappliedTextureImporterSettings() - { - foreach (InspectorWindow i in InspectorWindow.GetAllInspectorWindows()) - { - ActiveEditorTracker activeEditor = i.tracker; - foreach (Editor e in activeEditor.activeEditors) - { - TextureImporterInspector inspector = e as TextureImporterInspector; - if (inspector == null) - continue; - if (!inspector.HasModified()) - continue; - TextureImporter importer = inspector.target as TextureImporter; - if (EditorUtility.DisplayDialog("Unapplied import settings", "Unapplied import settings for \'" + importer.assetPath + "\'", "Apply", "Revert")) - { - inspector.ApplyAndImport(); // No way to apply/revert only some assets. Bug: 564192. - } - } - } - } - } - - public interface IPackerPolicy - { - bool AllowSequentialPacking { get; } - void OnGroupAtlases(BuildTarget target, PackerJob job, int[] textureImporterInstanceIDs); - int GetVersion(); - } -} diff --git a/Editor/Mono/Sprites/SpritePackerWindow.cs b/Editor/Mono/Sprites/SpritePackerWindow.cs deleted file mode 100644 index cbc81c10e2..0000000000 --- a/Editor/Mono/Sprites/SpritePackerWindow.cs +++ /dev/null @@ -1,390 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Collections; -using System.Linq; -using UnityEditorInternal; -using UnityEngine; - -namespace UnityEditor.Sprites -{ - internal class PackerWindow : SpriteUtilityWindow - { - private class PackerWindowStyle - { - public static readonly GUIContent packLabel = EditorGUIUtility.TrTextContent("Pack"); - public static readonly GUIContent repackLabel = EditorGUIUtility.TrTextContent("Repack"); - public static readonly GUIContent viewAtlasLabel = EditorGUIUtility.TrTextContent("View Atlas:"); - public static readonly GUIContent windowTitle = EditorGUIUtility.TrTextContent("Sprite Packer"); - public static readonly GUIContent pageContentLabel = EditorGUIUtility.TrTextContent("Page {0}"); - public static readonly GUIContent packingDisabledLabel = EditorGUIUtility.TrTextContent("Legacy sprite packing is disabled. Enable it in Edit > Project Settings > Editor."); - public static readonly GUIContent openProjectSettingButton = EditorGUIUtility.TrTextContent("Open Project Editor Settings"); - } - - struct Edge - { - public UInt16 v0; - public UInt16 v1; - public Edge(UInt16 a, UInt16 b) - { - v0 = a; - v1 = b; - } - - public override bool Equals(object obj) - { - Edge item = (Edge)obj; - return (v0 == item.v0 && v1 == item.v1) || (v0 == item.v1 && v1 == item.v0); - } - - public override int GetHashCode() - { - return (v0 << 16 | v1) ^ (v1 << 16 | v0).GetHashCode(); - } - }; - - private static string[] s_AtlasNamesEmpty = new string[1] { "Sprite atlas cache is empty" }; - private string[] m_AtlasNames = s_AtlasNamesEmpty; - private int m_SelectedAtlas = 0; - - private static string[] s_PageNamesEmpty = new string[0]; - private string[] m_PageNames = s_PageNamesEmpty; - private int m_SelectedPage = 0; - - private Sprite m_SelectedSprite = null; - - - void OnEnable() - { - minSize = new Vector2(400f, 256f); - titleContent = PackerWindowStyle.windowTitle; - - Reset(); - } - - private void Reset() - { - RefreshAtlasNameList(); - RefreshAtlasPageList(); - - m_SelectedAtlas = 0; - m_SelectedPage = 0; - m_SelectedSprite = null; - } - - private void RefreshAtlasNameList() - { - m_AtlasNames = Packer.atlasNames; - - // Validate - if (m_SelectedAtlas >= m_AtlasNames.Length) - m_SelectedAtlas = 0; - } - - private void RefreshAtlasPageList() - { - if (m_AtlasNames.Length > 0) - { - string atlas = m_AtlasNames[m_SelectedAtlas]; - Texture2D[] textures = Packer.GetTexturesForAtlas(atlas); - m_PageNames = new string[textures.Length]; - for (int i = 0; i < textures.Length; ++i) - m_PageNames[i] = string.Format(PackerWindowStyle.pageContentLabel.text, i + 1); - } - else - { - m_PageNames = s_PageNamesEmpty; - } - - // Validate - if (m_SelectedPage >= m_PageNames.Length) - m_SelectedPage = 0; - } - - private void OnAtlasNameListChanged() - { - if (m_AtlasNames.Length > 0) - { - string[] atlasNames = Packer.atlasNames; - string curAtlasName = m_AtlasNames[m_SelectedAtlas]; - string newAtlasName = (atlasNames.Length <= m_SelectedAtlas) ? null : atlasNames[m_SelectedAtlas]; - if (curAtlasName.Equals(newAtlasName)) - { - RefreshAtlasNameList(); - RefreshAtlasPageList(); - m_SelectedSprite = null; - return; - } - } - - Reset(); - } - - private bool ValidateIsPackingEnabled() - { - if (EditorSettings.spritePackerMode != SpritePackerMode.BuildTimeOnly - && EditorSettings.spritePackerMode != SpritePackerMode.AlwaysOn) - { - EditorGUILayout.BeginVertical(); - GUILayout.Label(PackerWindowStyle.packingDisabledLabel); - if (GUILayout.Button(PackerWindowStyle.openProjectSettingButton)) - EditorApplication.ExecuteMenuItem("Edit/Project Settings/Editor"); - EditorGUILayout.EndVertical(); - return false; - } - - return true; - } - - private Rect DoToolbarGUI() - { - Rect toolbarRect = new Rect(0 , 0, position.width, k_ToolbarHeight); - - if (Event.current.type == EventType.Repaint) - { - EditorStyles.toolbar.Draw(toolbarRect, false, false, false, false); - } - - bool wasEnabled = GUI.enabled; - GUI.enabled = m_AtlasNames.Length > 0; - toolbarRect = DoAlphaZoomToolbarGUI(toolbarRect); - GUI.enabled = wasEnabled; - - Rect drawRect = new Rect(EditorGUI.kSpacing, 0, 0, k_ToolbarHeight); - toolbarRect.width -= drawRect.x; - - using (new EditorGUI.DisabledScope(Application.isPlaying)) - { - drawRect.width = EditorStyles.toolbarButton.CalcSize(PackerWindowStyle.packLabel).x; - DrawToolBarWidget(ref drawRect, ref toolbarRect, (adjustedDrawRect) => - { - if (GUI.Button(adjustedDrawRect, PackerWindowStyle.packLabel, EditorStyles.toolbarButton)) - { - Packer.RebuildAtlasCacheIfNeeded(EditorUserBuildSettings.activeBuildTarget, true); - m_SelectedSprite = null; - RefreshAtlasPageList(); - RefreshState(); - } - }); - - using (new EditorGUI.DisabledScope(Packer.SelectedPolicy == Packer.kDefaultPolicy)) - { - drawRect.x += drawRect.width; - drawRect.width = EditorStyles.toolbarButton.CalcSize(PackerWindowStyle.repackLabel).x; - DrawToolBarWidget(ref drawRect, ref toolbarRect, (adjustedDrawRect) => - { - if (GUI.Button(adjustedDrawRect, PackerWindowStyle.repackLabel, EditorStyles.toolbarButton)) - { - Packer.RebuildAtlasCacheIfNeeded(EditorUserBuildSettings.activeBuildTarget, true, Packer.Execution.ForceRegroup); - m_SelectedSprite = null; - RefreshAtlasPageList(); - RefreshState(); - } - }); - } - } - - const float kAtlasNameWidth = 100; - const float kPagesWidth = 70; - const float kPolicyWidth = 100; - - float viewAtlasWidth = GUI.skin.label.CalcSize(PackerWindowStyle.viewAtlasLabel).x; - float totalWidth = viewAtlasWidth + kAtlasNameWidth + kPagesWidth + kPolicyWidth; - - drawRect.x += EditorGUI.kSpacing; // leave some space from previous control for cosmetic - toolbarRect.width -= EditorGUI.kSpacing; - float availableWidth = toolbarRect.width; - - using (new EditorGUI.DisabledScope(m_AtlasNames.Length == 0)) - { - drawRect.x += drawRect.width; - drawRect.width = viewAtlasWidth / totalWidth * availableWidth; - DrawToolBarWidget(ref drawRect, ref toolbarRect, (adjustedDrawArea) => - { - GUI.Label(adjustedDrawArea, PackerWindowStyle.viewAtlasLabel); - }); - - EditorGUI.BeginChangeCheck(); - drawRect.x += drawRect.width; - drawRect.width = kAtlasNameWidth / totalWidth * availableWidth; - DrawToolBarWidget(ref drawRect, ref toolbarRect, (adjustedDrawArea) => - { - m_SelectedAtlas = EditorGUI.Popup(adjustedDrawArea, m_SelectedAtlas, m_AtlasNames, EditorStyles.toolbarPopup); - }); - if (EditorGUI.EndChangeCheck()) - { - RefreshAtlasPageList(); - m_SelectedSprite = null; - } - - EditorGUI.BeginChangeCheck(); - drawRect.x += drawRect.width; - drawRect.width = kPagesWidth / totalWidth * availableWidth; - DrawToolBarWidget(ref drawRect, ref toolbarRect, (adjustedDrawArea) => - { - m_SelectedPage = EditorGUI.Popup(adjustedDrawArea, m_SelectedPage, m_PageNames, EditorStyles.toolbarPopup); - }); - - if (EditorGUI.EndChangeCheck()) - { - m_SelectedSprite = null; - } - } - - EditorGUI.BeginChangeCheck(); - string[] policies = Packer.Policies; - int selectedPolicy = Array.IndexOf(policies, Packer.SelectedPolicy); - drawRect.x += drawRect.width; - drawRect.width = kPolicyWidth / totalWidth * availableWidth; - DrawToolBarWidget(ref drawRect, ref toolbarRect, (adjustedDrawArea) => - { - selectedPolicy = EditorGUI.Popup(adjustedDrawArea, selectedPolicy, policies, EditorStyles.toolbarPopup); - }); - - if (EditorGUI.EndChangeCheck()) - { - Packer.SelectedPolicy = policies[selectedPolicy]; - } - - return toolbarRect; - } - - void OnSelectionChange() - { - if (Selection.activeObject == null) - return; - - Sprite selectedSprite = Selection.activeObject as Sprite; - if (selectedSprite != m_SelectedSprite) - { - if (selectedSprite != null) - { - string selAtlasName; - Texture2D selAtlasTexture; - Packer.GetAtlasDataForSprite(selectedSprite, out selAtlasName, out selAtlasTexture); - - int selAtlasIndex = m_AtlasNames.ToList().FindIndex(delegate(string s) { return selAtlasName == s; }); - if (selAtlasIndex == -1) - return; - int selAtlasPage = Packer.GetTexturesForAtlas(selAtlasName).ToList().FindIndex(delegate(Texture2D t) { return selAtlasTexture == t; }); - if (selAtlasPage == -1) - return; - - m_SelectedAtlas = selAtlasIndex; - m_SelectedPage = selAtlasPage; - RefreshAtlasPageList(); - } - - m_SelectedSprite = selectedSprite; - - Repaint(); - } - } - - private void RefreshState() - { - // Check if atlas name list changed - string[] atlasNames = Packer.atlasNames; - if (!atlasNames.SequenceEqual(m_AtlasNames)) - { - if (atlasNames.Length == 0) - { - Reset(); - return; - } - else - { - OnAtlasNameListChanged(); - } - } - - if (m_AtlasNames.Length == 0) - { - SetNewTexture(null); - return; - } - - // Validate selections - if (m_SelectedAtlas >= m_AtlasNames.Length) - m_SelectedAtlas = 0; - string curAtlasName = m_AtlasNames[m_SelectedAtlas]; - - Texture2D[] textures = Packer.GetTexturesForAtlas(curAtlasName); - if (m_SelectedPage >= textures.Length) - m_SelectedPage = 0; - - SetNewTexture(textures[m_SelectedPage]); - - // check if the atlas has alpha as an external texture (as in ETC1 atlases with alpha) - Texture2D[] alphaTextures = Packer.GetAlphaTexturesForAtlas(curAtlasName); - Texture2D selectedAlphaTexture = (m_SelectedPage < alphaTextures.Length) ? alphaTextures[m_SelectedPage] : null; - SetAlphaTextureOverride(selectedAlphaTexture); - } - - public void OnGUI() - { - if (!ValidateIsPackingEnabled()) - return; - - Matrix4x4 oldHandlesMatrix = Handles.matrix; - InitStyles(); - - RefreshState(); - - // Top menu bar - Rect toolbarRect = DoToolbarGUI(); - - if (m_Texture == null) - return; - - // Texture view - EditorGUILayout.BeginHorizontal(); - m_TextureViewRect = new Rect(0f, toolbarRect.yMax, position.width - k_ScrollbarMargin, position.height - k_ScrollbarMargin - toolbarRect.height); - GUILayout.FlexibleSpace(); - DoTextureGUI(); - string info = string.Format("{1}x{2}, {0}", TextureUtil.GetTextureFormatString(m_Texture.format), m_Texture.width, m_Texture.height); - EditorGUI.DropShadowLabel(new Rect(m_TextureViewRect.x, m_TextureViewRect.y + 10, m_TextureViewRect.width, 20), info); - EditorGUILayout.EndHorizontal(); - - Handles.matrix = oldHandlesMatrix; - } - - private void DrawLineUtility(Vector2 from, Vector2 to) - { - SpriteEditorUtility.DrawLine(new Vector3(from.x * m_Texture.width + 1f / m_Zoom, from.y * m_Texture.height + 1f / m_Zoom, 0.0f), new Vector3(to.x * m_Texture.width + 1f / m_Zoom, to.y * m_Texture.height + 1f / m_Zoom, 0.0f)); - } - - private Edge[] FindUniqueEdges(UInt16[] indices) - { - Edge[] allEdges = new Edge[indices.Length]; - int tris = indices.Length / 3; - for (int i = 0; i < tris; ++i) - { - allEdges[i * 3] = new Edge(indices[i * 3], indices[i * 3 + 1]); - allEdges[i * 3 + 1] = new Edge(indices[i * 3 + 1], indices[i * 3 + 2]); - allEdges[i * 3 + 2] = new Edge(indices[i * 3 + 2], indices[i * 3]); - } - - Edge[] uniqueEdges = allEdges.GroupBy(x => x).Where(x => x.Count() == 1).Select(x => x.First()).ToArray(); - return uniqueEdges; - } - - protected override void DrawGizmos() - { - if (m_SelectedSprite != null && m_Texture != null) - { - Vector2[] uvs = SpriteUtility.GetSpriteUVs(m_SelectedSprite, true); - UInt16[] indices = m_SelectedSprite.triangles; - Edge[] uniqueEdges = FindUniqueEdges(indices); // Assumes that our mesh has no duplicate vertices - - SpriteEditorUtility.BeginLines(new Color(0.3921f, 0.5843f, 0.9294f, 0.75f)); // Cornflower blue :) - foreach (Edge e in uniqueEdges) - DrawLineUtility(uvs[e.v0], uvs[e.v1]); - SpriteEditorUtility.EndLines(); - } - } - } // class -} diff --git a/Editor/Mono/Sprites/SpriteUtility.cs b/Editor/Mono/Sprites/SpriteUtility.cs deleted file mode 100644 index ced2f151b8..0000000000 --- a/Editor/Mono/Sprites/SpriteUtility.cs +++ /dev/null @@ -1,633 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using System.Linq; -using UnityEditorInternal; -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.Experimental.U2D; -using UnityEditor.U2D.Interface; -using UnityEngine.U2D.Interface; -using Object = UnityEngine.Object; -using UnityTexture2D = UnityEngine.Texture2D; - -namespace UnityEditor -{ - internal static class SpriteUtility - { - static class SpriteUtilityStrings - { - public static readonly GUIContent saveAnimDialogMessage = EditorGUIUtility.TrTextContent("Create a new animation for the game object '{0}':"); - public static readonly GUIContent saveAnimDialogTitle = EditorGUIUtility.TrTextContent("Create New Animation"); - public static readonly GUIContent saveAnimDialogName = EditorGUIUtility.TrTextContent("New Animation"); - public static readonly GUIContent unableToFindSpriteRendererWarning = EditorGUIUtility.TrTextContent("There should be a SpriteRenderer in dragged object"); - public static readonly GUIContent unableToAddSpriteRendererWarning = EditorGUIUtility.TrTextContent("Unable to add SpriteRenderer into Gameobject."); - public static readonly GUIContent failedToCreateAnimationError = EditorGUIUtility.TrTextContent("Failed to create animation for dragged object"); - } - - private static Material s_PreviewSpriteDefaultMaterial; - - internal static Material previewSpriteDefaultMaterial - { - get - { - if (s_PreviewSpriteDefaultMaterial == null) - { - Shader shader = Shader.Find("Sprites/Default"); - s_PreviewSpriteDefaultMaterial = new Material(shader); - } - return s_PreviewSpriteDefaultMaterial; - } - } - - static List s_SceneDragObjects; - static DragType s_DragType; - enum DragType { NotInitialized, SpriteAnimation, CreateMultiple } - - public delegate string ShowFileDialogDelegate(string title, string defaultName, string extension, string message, string defaultPath); - public static void OnSceneDrag(SceneView sceneView) - { - HandleSpriteSceneDrag(sceneView, new UnityEngine.U2D.Interface.Event(), DragAndDrop.objectReferences, DragAndDrop.paths, EditorUtility.SaveFilePanelInProject); - } - - public static void HandleSpriteSceneDrag(SceneView sceneView, IEvent evt, Object[] objectReferences, string[] paths, ShowFileDialogDelegate saveFileDialog) - { - if (evt.type != EventType.DragUpdated && evt.type != EventType.DragPerform && evt.type != EventType.DragExited) - return; - - // Return if any of the dragged objects are null, e.g. a MonoBehaviour without a managed instance - if (objectReferences.Any(obj => obj == null)) - return; - - // Regardless of EditorBehaviorMode or SceneView mode we don't handle if texture is dragged over a GO with renderer - if (objectReferences.Length == 1 && objectReferences[0] as UnityTexture2D != null) - { - GameObject go = HandleUtility.PickGameObject(evt.mousePosition, true); - if (go != null) - { - var renderer = go.GetComponent(); - if (renderer != null && !(renderer is SpriteRenderer)) - { - // There is an object where the cursor is - // and we are dragging a texture. Most likely user wants to - // assign texture to the GO - // Case 730444: Proceed only if the go has a renderer - CleanUp(true); - return; - } - } - } - - switch (evt.type) - { - case (EventType.DragUpdated): - DragType newDragType = evt.alt ? DragType.CreateMultiple : DragType.SpriteAnimation; - - if (s_DragType != newDragType || s_SceneDragObjects == null) // Either this is first time we are here OR evt.alt changed during drag - { - if (!ExistingAssets(objectReferences) && PathsAreValidTextures(paths)) // External drag with images that are not in the project - { - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - s_SceneDragObjects = new List(); - s_DragType = newDragType; - } - else // Internal drag with assets from project - { - List assets = GetSpriteFromPathsOrObjects(objectReferences, paths, evt.type); - - if (assets.Count == 0) - return; - - if (s_DragType != DragType.NotInitialized) // evt.alt changed during drag, so we need to cleanup and start over - CleanUp(true); - - s_DragType = newDragType; - CreateSceneDragObjects(assets); - IgnoreForRaycasts(s_SceneDragObjects); - } - } - - PositionSceneDragObjects(s_SceneDragObjects, sceneView, evt.mousePosition); - - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - evt.Use(); - break; - case (EventType.DragPerform): - List sprites = GetSpriteFromPathsOrObjects(objectReferences, paths, evt.type); - - if (sprites.Count > 0 && s_SceneDragObjects != null) - { - // Store current undoIndex to undo all operations done if any part of sprite creation fails - int undoIndex = Undo.GetCurrentGroup(); - - // For external drags, we have delayed all creation to DragPerform because only now we have the imported sprite assets - if (s_SceneDragObjects.Count == 0) - { - CreateSceneDragObjects(sprites); - PositionSceneDragObjects(s_SceneDragObjects, sceneView, evt.mousePosition); - } - - foreach (GameObject dragGO in s_SceneDragObjects) - { - dragGO.hideFlags = HideFlags.None; - Undo.RegisterCreatedObjectUndo(dragGO, "Create Sprite"); - EditorUtility.SetDirty(dragGO); - } - - bool createGameObject = true; - if (s_DragType == DragType.SpriteAnimation && sprites.Count > 1) - { - UsabilityAnalytics.Event("Sprite Drag and Drop", "Drop multiple sprites to scene", "null", 1); - createGameObject = AddAnimationToGO((GameObject)s_SceneDragObjects[0], sprites.ToArray(), saveFileDialog); - } - else - UsabilityAnalytics.Event("Sprite Drag and Drop", "Drop single sprite to scene", "null", 1); - - if (createGameObject) - { - Selection.objects = s_SceneDragObjects.ToArray(); - } - else - { - // Revert all Create Sprite actions if animation failed to be created or was cancelled - Undo.RevertAllDownToGroup(undoIndex); - } - CleanUp(!createGameObject); - evt.Use(); - } - break; - case EventType.DragExited: - if (s_SceneDragObjects != null) - { - CleanUp(true); - evt.Use(); - } - break; - } - } - - private static void IgnoreForRaycasts(List objects) - { - List ignoredTransforms = new List(); - - foreach (GameObject gameObject in objects) - ignoredTransforms.AddRange(gameObject.GetComponentsInChildren()); - - HandleUtility.ignoreRaySnapObjects = ignoredTransforms.ToArray(); - } - - private static void PositionSceneDragObjects(List objects, SceneView sceneView, Vector2 mousePosition) - { - Vector3 position = Vector3.zero; - position = HandleUtility.GUIPointToWorldRay(mousePosition).GetPoint(10); - if (sceneView.in2DMode) - { - position.z = 0f; - } - else - { - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - object hit = HandleUtility.RaySnap(HandleUtility.GUIPointToWorldRay(mousePosition)); - if (hit != null) - { - RaycastHit rh = (RaycastHit)hit; - position = rh.point; - } - } - - if (Selection.activeGameObject != null) - { - Grid grid = Selection.activeGameObject.GetComponentInParent(); - if (grid != null) - { - Vector3Int cell = grid.WorldToCell(position); - position = grid.GetCellCenterWorld(cell); - } - } - - foreach (GameObject gameObject in objects) - { - gameObject.transform.position = position; - } - } - - private static void CreateSceneDragObjects(List sprites) - { - if (s_SceneDragObjects == null) - s_SceneDragObjects = new List(); - - if (s_DragType == DragType.CreateMultiple) - { - foreach (Sprite sprite in sprites) - s_SceneDragObjects.Add(CreateDragGO(sprite, Vector3.zero)); - } - else - { - s_SceneDragObjects.Add(CreateDragGO(sprites[0], Vector3.zero)); - } - } - - private static void CleanUp(bool deleteTempSceneObject) - { - if (s_SceneDragObjects != null) - { - if (deleteTempSceneObject) - { - foreach (GameObject gameObject in s_SceneDragObjects) - Object.DestroyImmediate(gameObject, false); - } - - s_SceneDragObjects.Clear(); - s_SceneDragObjects = null; - } - HandleUtility.ignoreRaySnapObjects = null; - s_DragType = DragType.NotInitialized; - } - - static bool CreateAnimation(GameObject gameObject, Object[] frames, ShowFileDialogDelegate saveFileDialog) - { - saveFileDialog = saveFileDialog ?? EditorUtility.SaveFilePanelInProject; - - // Use same name compare as when we sort in the backend: See AssetDatabase.cpp: SortChildren - System.Array.Sort(frames, (a, b) => EditorUtility.NaturalCompare(a.name, b.name)); - - Animator animator = AnimationWindowUtility.EnsureActiveAnimationPlayer(gameObject) - ? AnimationWindowUtility.GetClosestAnimatorInParents(gameObject.transform) - : null; - - bool createSuccess = animator != null; - - if (animator != null) - { - // Go forward with presenting user a save clip dialog - string message = string.Format(SpriteUtilityStrings.saveAnimDialogMessage.text, gameObject.name); - string newClipDirectory = ProjectWindowUtil.GetActiveFolderPath(); - string newClipPath = saveFileDialog(SpriteUtilityStrings.saveAnimDialogTitle.text, SpriteUtilityStrings.saveAnimDialogName.text, "anim", message, newClipDirectory); - - if (string.IsNullOrEmpty(newClipPath)) - { - Object.DestroyImmediate(animator); - return false; - } - else - { - AnimationClip newClip = AnimationWindowUtility.CreateNewClipAtPath(newClipPath); - if (newClip != null) - { - AddSpriteAnimationToClip(newClip, frames); - createSuccess = AnimationWindowUtility.AddClipToAnimatorComponent(animator, newClip); - } - } - } - - if (createSuccess == false) - Debug.LogError(SpriteUtilityStrings.failedToCreateAnimationError.text); - - return createSuccess; - } - - static void AddSpriteAnimationToClip(AnimationClip newClip, Object[] frames) - { - // TODO Default framerate be exposed to user? - newClip.frameRate = 12; - - // Add keyframes - ObjectReferenceKeyframe[] keyframes = new ObjectReferenceKeyframe[frames.Length]; - - for (int i = 0; i < keyframes.Length; i++) - { - keyframes[i] = new ObjectReferenceKeyframe(); - keyframes[i].value = RemapObjectToSprite(frames[i]); - keyframes[i].time = i / newClip.frameRate; - } - - // Create binding - EditorCurveBinding curveBinding = EditorCurveBinding.PPtrCurve("", typeof(SpriteRenderer), "m_Sprite"); - - // Save curve to clip - AnimationUtility.SetObjectReferenceCurve(newClip, (EditorCurveBinding)curveBinding, keyframes); - } - - public static List GetSpriteFromPathsOrObjects(Object[] objects, string[] paths, EventType currentEventType) - { - List result = new List(); - - foreach (Object obj in objects) - { - if (AssetDatabase.Contains(obj)) - { - if (obj is Sprite) - result.Add(obj as Sprite); - else if (obj is UnityTexture2D) - result.AddRange(TextureToSprites(obj as UnityTexture2D)); - } - } - - // Fix case 742896. If any of the drag objects is already in the AssetDatabase, means we don't have to handle external drags. - // Fix case 857231. We only handle external drag if default behaviour mode is 2D - if (!ExistingAssets(objects) && currentEventType == EventType.DragPerform && EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D) - { - HandleExternalDrag(paths, true, ref result); - } - return result; - } - - public static bool ExistingAssets(Object[] objects) - { - foreach (Object obj in objects) - { - if (AssetDatabase.Contains(obj)) - return true; - } - return false; - } - - private static void HandleExternalDrag(string[] paths, bool perform, ref List result) - { - foreach (var path in paths) - { - if (!ValidPathForTextureAsset(path)) - continue; - - DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - - if (!perform) - continue; - - var newPath = AssetDatabase.GenerateUniqueAssetPath(Path.Combine("Assets", FileUtil.GetLastPathNameComponent(path))); - if (newPath.Length <= 0) - continue; - - FileUtil.CopyFileOrDirectory(path, newPath); - ForcedImportFor(newPath); - - Sprite defaultSprite = GenerateDefaultSprite(AssetDatabase.LoadMainAssetAtPath(newPath) as UnityTexture2D); - if (defaultSprite != null) - result.Add(defaultSprite); - } - } - - private static bool PathsAreValidTextures(string[] paths) - { - if (paths == null || paths.Length == 0) - return false; - - foreach (var path in paths) - { - if (!ValidPathForTextureAsset(path)) - return false; - } - - return true; - } - - private static void ForcedImportFor(string newPath) - { - try - { - AssetDatabase.StartAssetEditing(); - AssetDatabase.ImportAsset(newPath); - } - finally - { - AssetDatabase.StopAssetEditing(); - } - } - - private static Sprite GenerateDefaultSprite(UnityTexture2D texture) - { - string assetPath = AssetDatabase.GetAssetPath(texture); - TextureImporter textureImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter; - if (textureImporter == null) // could be DDS importer or other non-TextureImporter type - return null; - - if (textureImporter.textureType != TextureImporterType.Sprite) - return null; - - if (textureImporter.spriteImportMode == SpriteImportMode.None) - { - textureImporter.spriteImportMode = SpriteImportMode.Single; - AssetDatabase.WriteImportSettingsIfDirty(assetPath); - ForcedImportFor(assetPath); - } - - Object firstSprite = null; - firstSprite = AssetDatabase.LoadAllAssetsAtPath(assetPath).FirstOrDefault(t => t is Sprite); - - return firstSprite as Sprite; - } - - public static GameObject CreateDragGO(Sprite frame, Vector3 position) - { - string name = string.IsNullOrEmpty(frame.name) ? "Sprite" : frame.name; - name = GameObjectUtility.GetUniqueNameForSibling(null, name); - GameObject go = new GameObject(name); - - SpriteRenderer spriteRenderer = go.AddComponent(); - spriteRenderer.sprite = frame; - go.transform.position = position; - go.hideFlags = HideFlags.HideAndDontSave; - return go; - } - - public static bool AddAnimationToGO(GameObject go, Sprite[] frames, ShowFileDialogDelegate saveFileDialog) - { - SpriteRenderer spriteRenderer = go.GetComponent(); - if (spriteRenderer == null) - { - Debug.LogWarning(SpriteUtilityStrings.unableToFindSpriteRendererWarning.text); - spriteRenderer = go.AddComponent(); - if (spriteRenderer == null) - { - Debug.LogWarning(SpriteUtilityStrings.unableToAddSpriteRendererWarning.text); - return false; - } - } - spriteRenderer.sprite = frames[0]; - return CreateAnimation(go, frames, saveFileDialog); - } - - public static GameObject DropSpriteToSceneToCreateGO(Sprite sprite, Vector3 position) - { - GameObject go = new GameObject(string.IsNullOrEmpty(sprite.name) ? "Sprite" : sprite.name); - SpriteRenderer spriteRenderer = go.AddComponent(); - spriteRenderer.sprite = sprite; - go.transform.position = position; - Selection.activeObject = go; - - return go; - } - - public static Sprite RemapObjectToSprite(Object obj) - { - if (obj is Sprite) - return (Sprite)obj; - - if (obj is UnityTexture2D) - { - Object[] assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(obj)); - for (int i = 0; i < assets.Length; i++) - { - if (assets[i].GetType() == typeof(Sprite)) - return assets[i] as Sprite; - } - } - return null; - } - - public static List TextureToSprites(UnityTexture2D tex) - { - Object[] assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(tex)); - List result = new List(); - - for (int i = 0; i < assets.Length; i++) - { - if (assets[i].GetType() == typeof(Sprite)) - result.Add(assets[i] as Sprite); - } - - if (result.Count > 0) - return result; - - Sprite defaultSprite = GenerateDefaultSprite(tex); - if (defaultSprite != null) - result.Add(defaultSprite); - - return result; - } - - public static Sprite TextureToSprite(UnityTexture2D tex) - { - List sprites = TextureToSprites(tex); - if (sprites.Count > 0) - return sprites[0]; - return null; - } - - private static bool ValidPathForTextureAsset(string path) - { - string ext = FileUtil.GetPathExtension(path).ToLower(); - return - ext == "jpg" || - ext == "jpeg" || - ext == "tif" || - ext == "tiff" || - ext == "tga" || - ext == "gif" || - ext == "png" || - ext == "psd" || - ext == "bmp" || - ext == "iff" || - ext == "pict" || - ext == "pic" || - ext == "pct" || - ext == "exr" || - ext == "hdr"; - } - - public static UnityTexture2D RenderStaticPreview(Sprite sprite, Color color, int width, int height) - { - return RenderStaticPreview(sprite, color, width, height, Matrix4x4.identity); - } - - public static UnityTexture2D RenderStaticPreview(Sprite sprite, Color color, int width, int height, Matrix4x4 transform) - { - if (sprite == null) - return null; - - PreviewHelpers.AdjustWidthAndHeightForStaticPreview((int)sprite.rect.width, (int)sprite.rect.height, ref width, ref height); - - SavedRenderTargetState savedRTState = new SavedRenderTargetState(); - - RenderTexture tmp = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Default); - RenderTexture.active = tmp; - GL.Clear(true, true, new Color(0f, 0f, 0f, 0.1f)); - - previewSpriteDefaultMaterial.mainTexture = sprite.texture; - previewSpriteDefaultMaterial.SetPass(0); - - RenderSpriteImmediate(sprite, color, transform); - - UnityTexture2D copy = new UnityTexture2D(width, height, TextureFormat.ARGB32, false); - copy.hideFlags = HideFlags.HideAndDontSave; - copy.ReadPixels(new Rect(0, 0, width, height), 0, 0); - copy.Apply(); - RenderTexture.ReleaseTemporary(tmp); - - savedRTState.Restore(); - return copy; - } - - internal static void RenderSpriteImmediate(Sprite sprite, Color color, Matrix4x4 transform) - { - float spriteWidth = sprite.rect.width; - float spriteHeight = sprite.rect.height; - - float pixelsToUnits = sprite.rect.width / sprite.bounds.size.x; - Vector2[] vertices = sprite.vertices; - Vector2[] uvs = sprite.uv; - ushort[] triangles = sprite.triangles; - Vector2 pivot = sprite.pivot; - - GL.PushMatrix(); - GL.LoadOrtho(); - GL.Begin(GL.TRIANGLES); - for (int i = 0; i < sprite.triangles.Length; ++i) - { - ushort index = triangles[i]; - Vector2 spriteVertex = vertices[index]; - Vector2 uv = uvs[index]; - Vector3 vertex = new Vector3(spriteVertex.x, spriteVertex.y, 0); - vertex = transform.MultiplyPoint(vertex); - vertex.x = (vertex.x * pixelsToUnits + pivot.x) / spriteWidth; - vertex.y = (vertex.y * pixelsToUnits + pivot.y) / spriteHeight; - GL.Color(color); - GL.TexCoord(new Vector3(uv.x, uv.y, 0)); - GL.Vertex3(vertex.x, vertex.y, vertex.z); - } - GL.End(); - GL.PopMatrix(); - } - - public static UnityTexture2D CreateTemporaryDuplicate(UnityTexture2D original, int width, int height) - { - if (!ShaderUtil.hardwareSupportsRectRenderTexture || !original) - return null; - - RenderTexture save = RenderTexture.active; - var savedViewport = ShaderUtil.rawViewportRect; - - RenderTexture tmp = RenderTexture.GetTemporary( - width, - height, - 0, - RenderTextureFormat.Default, - RenderTextureReadWrite.sRGB); - - Graphics.Blit(original, tmp, EditorGUIUtility.GUITextureBlit2SRGBMaterial); - - RenderTexture.active = tmp; - - // If the user system doesn't support this texture size, force it to use mipmap - bool forceUseMipMap = width >= SystemInfo.maxTextureSize || height >= SystemInfo.maxTextureSize; - - UnityTexture2D copy = new UnityTexture2D(width, height, TextureFormat.RGBA32, original.mipmapCount > 1 || forceUseMipMap); - copy.ReadPixels(new Rect(0, 0, width, height), 0, 0); - copy.Apply(); - RenderTexture.ReleaseTemporary(tmp); - - EditorGUIUtility.SetRenderTextureNoViewport(save); - ShaderUtil.rawViewportRect = savedViewport; - - copy.alphaIsTransparency = original.alphaIsTransparency; - return copy; - } - - public static SpriteImportMode GetSpriteImportMode(ISpriteEditorDataProvider dataProvider) - { - return dataProvider == null ? SpriteImportMode.None : dataProvider.spriteImportMode; - } - } -} diff --git a/Editor/Mono/Sprites/SpriteUtilityWindow.cs b/Editor/Mono/Sprites/SpriteUtilityWindow.cs deleted file mode 100644 index 827e411a44..0000000000 --- a/Editor/Mono/Sprites/SpriteUtilityWindow.cs +++ /dev/null @@ -1,388 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal class SpriteUtilityWindow : EditorWindow - { - protected class Styles - { - public readonly GUIStyle dragdot = "U2D.dragDot"; - public readonly GUIStyle dragdotDimmed = "U2D.dragDotDimmed"; - public readonly GUIStyle dragdotactive = "U2D.dragDotActive"; - public readonly GUIStyle createRect = "U2D.createRect"; - public readonly GUIStyle preToolbar = "preToolbar"; - public readonly GUIStyle preButton = "preButton"; - public readonly GUIStyle preLabel = "preLabel"; - public readonly GUIStyle preSlider = "preSlider"; - public readonly GUIStyle preSliderThumb = "preSliderThumb"; - public readonly GUIStyle preBackground = "preBackground"; - public readonly GUIStyle pivotdotactive = "U2D.pivotDotActive"; - public readonly GUIStyle pivotdot = "U2D.pivotDot"; - - public readonly GUIStyle dragBorderdot = new GUIStyle(); - public readonly GUIStyle dragBorderDotActive = new GUIStyle(); - - public readonly GUIStyle toolbar; - public readonly GUIContent alphaIcon; - public readonly GUIContent RGBIcon; - public readonly GUIStyle notice; - - public readonly GUIContent smallMip; - public readonly GUIContent largeMip; - - public Styles() - { - toolbar = new GUIStyle(EditorStyles.inspectorBig); - toolbar.margin.top = 0; - toolbar.margin.bottom = 0; - alphaIcon = EditorGUIUtility.IconContent("PreTextureAlpha"); - RGBIcon = EditorGUIUtility.IconContent("PreTextureRGB"); - preToolbar.border.top = 0; - createRect.border = new RectOffset(3, 3, 3, 3); - - notice = new GUIStyle(GUI.skin.label); - notice.alignment = TextAnchor.MiddleCenter; - notice.normal.textColor = Color.yellow; - - dragBorderdot.fixedHeight = 5f; - dragBorderdot.fixedWidth = 5f; - dragBorderdot.normal.background = EditorGUIUtility.whiteTexture; - - dragBorderDotActive.fixedHeight = dragBorderdot.fixedHeight; - dragBorderDotActive.fixedWidth = dragBorderdot.fixedWidth; - dragBorderDotActive.normal.background = EditorGUIUtility.whiteTexture; - - smallMip = EditorGUIUtility.IconContent("PreTextureMipMapLow"); - largeMip = EditorGUIUtility.IconContent("PreTextureMipMapHigh"); - } - } - - protected void InitStyles() - { - if (m_Styles == null) - m_Styles = new Styles(); - } - - protected Styles m_Styles; - - protected const float k_BorderMargin = 10f; - protected const float k_ScrollbarMargin = 16f; - protected const float k_InspectorWindowMargin = 8f; - protected const float k_InspectorWidth = 330f; - protected const float k_MinZoomPercentage = 0.9f; - protected const float k_MaxZoom = 50f; - protected const float k_WheelZoomSpeed = 0.03f; - protected const float k_MouseZoomSpeed = 0.005f; - protected const float k_ToolbarHeight = 17f; - - protected UnityEngine.U2D.Interface.ITexture2D m_Texture; - protected UnityEngine.U2D.Interface.ITexture2D m_TextureAlphaOverride; - protected Rect m_TextureViewRect; - protected Rect m_TextureRect; - - protected bool m_ShowAlpha = false; - protected float m_Zoom = -1f; - protected float m_MipLevel = 0; - protected Vector2 m_ScrollPosition = new Vector2(); - - protected float GetMinZoom() - { - if (m_Texture == null) - return 1.0f; - // Case 654327: Add k_MaxZoom size to min check to ensure that min zoom is smaller than max zoom - return Mathf.Min(m_TextureViewRect.width / m_Texture.width, m_TextureViewRect.height / m_Texture.height, k_MaxZoom) * k_MinZoomPercentage; - } - - protected void HandleZoom() - { - bool zoomMode = Event.current.alt && Event.current.button == 1; - if (zoomMode) - { - EditorGUIUtility.AddCursorRect(m_TextureViewRect, MouseCursor.Zoom); - } - - if ( - ((Event.current.type == EventType.MouseUp || Event.current.type == EventType.MouseDown) && zoomMode) || - ((Event.current.type == EventType.KeyUp || Event.current.type == EventType.KeyDown) && Event.current.keyCode == KeyCode.LeftAlt) - ) - { - Repaint(); - } - - if (Event.current.type == EventType.ScrollWheel || (Event.current.type == EventType.MouseDrag && Event.current.alt && Event.current.button == 1)) - { - float zoomMultiplier = 1f - Event.current.delta.y * (Event.current.type == EventType.ScrollWheel ? k_WheelZoomSpeed : -k_MouseZoomSpeed); - - // Clamp zoom - float wantedZoom = m_Zoom * zoomMultiplier; - - float currentZoom = Mathf.Clamp(wantedZoom, GetMinZoom(), k_MaxZoom); - - if (currentZoom != m_Zoom) - { - m_Zoom = currentZoom; - - // We need to fix zoomMultiplier if we clamped wantedZoom != currentZoom - if (wantedZoom != currentZoom) - zoomMultiplier /= wantedZoom / currentZoom; - - m_ScrollPosition *= zoomMultiplier; - - // Zooming towards mouse cursor - float xRatio = Event.current.mousePosition.x / m_TextureViewRect.width - 0.5f; - float yRatio = Event.current.mousePosition.y / m_TextureViewRect.height - 0.5f; - float diffX = xRatio * (zoomMultiplier - 1); - float diffY = yRatio * (zoomMultiplier - 1); - - Rect scrollRect = maxScrollRect; - m_ScrollPosition.x += (diffX * (scrollRect.width / 2.0f)); - m_ScrollPosition.y += (diffY * (scrollRect.height / 2.0f)); - - Event.current.Use(); - } - } - } - - protected void HandlePanning() - { - // You can pan by holding ALT and using left button or NOT holding ALT and using right button. ALT + right is reserved for zooming. - bool panMode = (!Event.current.alt && Event.current.button > 0 || Event.current.alt && Event.current.button <= 0); - if (panMode && GUIUtility.hotControl == 0) - { - EditorGUIUtility.AddCursorRect(m_TextureViewRect, MouseCursor.Pan); - - if (Event.current.type == EventType.MouseDrag) - { - m_ScrollPosition -= Event.current.delta; - Event.current.Use(); - } - } - - //We need to repaint when entering or exiting the pan mode, so the mouse cursor gets refreshed. - if ( - ((Event.current.type == EventType.MouseUp || Event.current.type == EventType.MouseDown) && panMode) || - (Event.current.type == EventType.KeyUp || Event.current.type == EventType.KeyDown) && Event.current.keyCode == KeyCode.LeftAlt - ) - { - Repaint(); - } - } - - // Bounding values for scrollbars. Changes with zoom, because we want min/max scroll to stop at texture edges. - protected Rect maxScrollRect - { - get - { - float halfWidth = m_Texture.width * .5f * m_Zoom; - float halfHeight = m_Texture.height * .5f * m_Zoom; - return new Rect(-halfWidth, -halfHeight, m_TextureViewRect.width + halfWidth * 2f, m_TextureViewRect.height + halfHeight * 2f); - } - } - - // Max rect in texture space that can ever be visible - protected Rect maxRect - { - get - { - float marginW = m_TextureViewRect.width * .5f / GetMinZoom(); - float marginH = m_TextureViewRect.height * .5f / GetMinZoom(); - float left = -marginW; - float top = -marginH; - float width = m_Texture.width + marginW * 2f; - float height = m_Texture.height + marginH * 2f; - return new Rect(left, top, width, height); - } - } - - protected void DrawTexturespaceBackground() - { - float size = Mathf.Max(maxRect.width, maxRect.height); - Vector2 offset = new Vector2(maxRect.xMin, maxRect.yMin); - - float halfSize = size * .5f; - float alpha = EditorGUIUtility.isProSkin ? 0.15f : 0.08f; - float gridSize = 8f; - - SpriteEditorUtility.BeginLines(new Color(0f, 0f, 0f, alpha)); - for (float v = 0; v <= size; v += gridSize) - SpriteEditorUtility.DrawLine(new Vector2(-halfSize + v, halfSize + v) + offset, new Vector2(halfSize + v, -halfSize + v) + offset); - SpriteEditorUtility.EndLines(); - } - - private float Log2(float x) - { - return (float)(System.Math.Log(x) / System.Math.Log(2)); - } - - protected void DrawTexture() - { - float mipLevel = Mathf.Min(m_MipLevel, TextureUtil.GetMipmapCount(m_Texture) - 1); - - FilterMode oldFilter = m_Texture.filterMode; - TextureUtil.SetFilterModeNoDirty(m_Texture, FilterMode.Point); - - if (m_ShowAlpha) - { - // check if we have a valid alpha texture - if (m_TextureAlphaOverride != null) - EditorGUI.DrawTextureTransparent(m_TextureRect, m_TextureAlphaOverride, ScaleMode.StretchToFill, 0, mipLevel); - // else use the original texture and display its alpha - else - EditorGUI.DrawTextureAlpha(m_TextureRect, m_Texture, ScaleMode.StretchToFill, 0, mipLevel); - } - else - EditorGUI.DrawTextureTransparent(m_TextureRect, m_Texture, ScaleMode.StretchToFill, 0, mipLevel); - - TextureUtil.SetFilterModeNoDirty(m_Texture, oldFilter); - } - - protected void DrawScreenspaceBackground() - { - if (Event.current.type == EventType.Repaint) - m_Styles.preBackground.Draw(m_TextureViewRect, false, false, false, false); - } - - protected void HandleScrollbars() - { - Rect horizontalScrollBarPosition = new Rect(m_TextureViewRect.xMin, m_TextureViewRect.yMax, m_TextureViewRect.width, k_ScrollbarMargin); - m_ScrollPosition.x = GUI.HorizontalScrollbar(horizontalScrollBarPosition, m_ScrollPosition.x, m_TextureViewRect.width, maxScrollRect.xMin, maxScrollRect.xMax); - - Rect verticalScrollBarPosition = new Rect(m_TextureViewRect.xMax, m_TextureViewRect.yMin, k_ScrollbarMargin, m_TextureViewRect.height); - m_ScrollPosition.y = GUI.VerticalScrollbar(verticalScrollBarPosition, m_ScrollPosition.y, m_TextureViewRect.height, maxScrollRect.yMin, maxScrollRect.yMax); - } - - protected void SetupHandlesMatrix() - { - // Offset from top left to center in view space - Vector3 handlesPos = new Vector3(m_TextureRect.x, m_TextureRect.yMax, 0f); - // We flip Y-scale because Unity texture space is bottom-up - Vector3 handlesScale = new Vector3(m_Zoom, -m_Zoom, 1f); - - // Handle matrix is for converting between view and texture space coordinates, without taking account the scroll position. - // Scroll position is added separately so we can use it with GUIClip. - Handles.matrix = Matrix4x4.TRS(handlesPos, Quaternion.identity, handlesScale); - } - - protected Rect DoAlphaZoomToolbarGUI(Rect area) - { - int mipCount = 1; - if (m_Texture != null) - mipCount = Mathf.Max(mipCount, TextureUtil.GetMipmapCount(m_Texture)); - - Rect drawArea = new Rect(area.width, 0, 0, area.height); - using (new EditorGUI.DisabledScope(mipCount == 1)) - { - drawArea.width = m_Styles.largeMip.image.width; - drawArea.x -= drawArea.width; - GUI.Box(drawArea, m_Styles.largeMip, m_Styles.preLabel); - - drawArea.width = EditorGUI.kSliderMinW; - drawArea.x -= drawArea.width; - m_MipLevel = Mathf.Round(GUI.HorizontalSlider(drawArea, m_MipLevel, mipCount - 1, 0, m_Styles.preSlider, m_Styles.preSliderThumb)); - - drawArea.width = m_Styles.smallMip.image.width; - drawArea.x -= drawArea.width; - GUI.Box(drawArea, m_Styles.smallMip, m_Styles.preLabel); - } - - drawArea.width = EditorGUI.kSliderMinW; - drawArea.x -= drawArea.width; - m_Zoom = GUI.HorizontalSlider(drawArea, m_Zoom, GetMinZoom(), k_MaxZoom, m_Styles.preSlider, m_Styles.preSliderThumb); - - drawArea.width = EditorGUI.kObjectFieldMiniThumbnailWidth; - drawArea.x -= drawArea.width + EditorGUI.kSpacing; - m_ShowAlpha = GUI.Toggle(drawArea, m_ShowAlpha, m_ShowAlpha ? m_Styles.alphaIcon : m_Styles.RGBIcon, "toolbarButton"); - - // Returns the area that is not used - return new Rect(area.x, area.y, drawArea.x, area.height); - } - - protected void DoTextureGUI() - { - if (m_Texture == null) - return; - - // zoom startup init - if (m_Zoom < 0f) - m_Zoom = GetMinZoom(); - - // Texture rect in view space - m_TextureRect = new Rect( - m_TextureViewRect.width / 2f - (m_Texture.width * m_Zoom / 2f), - m_TextureViewRect.height / 2f - (m_Texture.height * m_Zoom / 2f), - (m_Texture.width * m_Zoom), - (m_Texture.height * m_Zoom) - ); - - HandleScrollbars(); - SetupHandlesMatrix(); - DrawScreenspaceBackground(); - - GUIClip.Push(m_TextureViewRect, -m_ScrollPosition, Vector2.zero, false); - - if (Event.current.type == EventType.Repaint) - { - DrawTexturespaceBackground(); - DrawTexture(); - DrawGizmos(); - } - - DoTextureGUIExtras(); - - GUIClip.Pop(); - - // Handle this after DoTextureGUIExtras in case user wants any event that is handled by Zoom or Panning - HandleZoom(); - HandlePanning(); - } - - protected virtual void DoTextureGUIExtras() - { - } - - protected virtual void DrawGizmos() - { - } - - protected void SetNewTexture(Texture2D texture) - { - if (texture != m_Texture) - { - m_Texture = new UnityEngine.U2D.Interface.Texture2D(texture); - m_Zoom = -1; - m_TextureAlphaOverride = null; - } - } - - protected void SetAlphaTextureOverride(Texture2D alphaTexture) - { - if (alphaTexture != m_TextureAlphaOverride) - { - m_TextureAlphaOverride = new UnityEngine.U2D.Interface.Texture2D(alphaTexture); - m_Zoom = -1; - } - } - - internal override void OnResized() - { - if (m_Texture != null && Event.current != null) - HandleZoom(); - } - - internal static void DrawToolBarWidget(ref Rect drawRect, ref Rect toolbarRect, Action drawAction) - { - toolbarRect.width -= drawRect.width; - if (toolbarRect.width < 0) - drawRect.width += toolbarRect.width; - - if (drawRect.width > 0) - drawAction(drawRect); - } - } // class -} diff --git a/Editor/Mono/Sprites/TightRotateEnabledSpritePackerPolicy.cs b/Editor/Mono/Sprites/TightRotateEnabledSpritePackerPolicy.cs deleted file mode 100644 index f0323ebd25..0000000000 --- a/Editor/Mono/Sprites/TightRotateEnabledSpritePackerPolicy.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor.Sprites -{ - // TightRotateEnabledSpritePackerPolicy will tightly pack non-rectangle Sprites unless their packing tag contains "[RECT]" with rotation and flipping for optimal packing. - internal class TightRotateEnabledSpritePackerPolicy : DefaultPackerPolicy - { - protected override string TagPrefix { get { return "[RECT]"; } } - protected override bool AllowTightWhenTagged { get { return false; } } - protected override bool AllowRotationFlipping { get { return true; } } - } -} diff --git a/Editor/Mono/Sprites/TightSpritePackerPolicy.cs b/Editor/Mono/Sprites/TightSpritePackerPolicy.cs deleted file mode 100644 index ef78eec698..0000000000 --- a/Editor/Mono/Sprites/TightSpritePackerPolicy.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using System.Collections.Generic; - -namespace UnityEditor.Sprites -{ - // TightPackerPolicy will tightly pack non-rectangle Sprites unless their packing tag contains "[RECT]". - internal class TightPackerPolicy : DefaultPackerPolicy - { - protected override string TagPrefix { get { return "[RECT]"; } } - protected override bool AllowTightWhenTagged { get { return false; } } - protected override bool AllowRotationFlipping { get { return false; } } - } -} diff --git a/Editor/Mono/StateMachine.bindings.cs b/Editor/Mono/StateMachine.bindings.cs deleted file mode 100644 index 7dd60ce12c..0000000000 --- a/Editor/Mono/StateMachine.bindings.cs +++ /dev/null @@ -1,323 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngineInternal; -using Object = UnityEngine.Object; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Collections; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditor.Animations -{ - public enum AnimatorConditionMode - { - If = 1, - IfNot = 2, - Greater = 3, - Less = 4, - //ExitTime = 5, - Equals = 6, - NotEqual = 7, - } - - public enum TransitionInterruptionSource - { - None, - Source, - Destination, - SourceThenDestination, - DestinationThenSource - } - - [NativeHeader("Editor/Src/Animation/Transition.h")] - public struct AnimatorCondition - { - public AnimatorConditionMode mode { get {return m_ConditionMode; } set {m_ConditionMode = value; } } - public string parameter { get {return m_ConditionEvent; } set {m_ConditionEvent = value; } } - public float threshold { get {return m_EventTreshold; } set {m_EventTreshold = value; } } - - AnimatorConditionMode m_ConditionMode; //eConditionMode - string m_ConditionEvent; - float m_EventTreshold;// m_ParameterThreshold - } - - [NativeHeader("Editor/Src/Animation/Transition.h")] - [NativeHeader("Runtime/Animation/MecanimUtility.h")] - public partial class AnimatorTransitionBase : Object - { - protected AnimatorTransitionBase() {} - - public string GetDisplayName(Object source) - { - return (source is AnimatorState) ? GetDisplayNameStateSource(source as AnimatorState) : GetDisplayNameStateMachineSource(source as AnimatorStateMachine); - } - - [NativeMethod("GetDisplayName")] - extern internal string GetDisplayNameStateSource(AnimatorState source); - - [NativeMethod("GetDisplayName")] - extern internal string GetDisplayNameStateMachineSource(AnimatorStateMachine source); - - [FreeFunction] - extern static internal string BuildTransitionName(string source, string destination); - - extern public bool solo { get; set; } - extern public bool mute { get; set; } - extern public bool isExit { get; set; } - - extern public AnimatorStateMachine destinationStateMachine - { - [NativeMethod("GetDstStateMachine")] - get; - [NativeMethod("SetDstStateMachine")] - set; - } - extern public AnimatorState destinationState - { - [NativeMethod("GetDstState")] - get; - [NativeMethod("SetDstState")] - set; - } - - extern public AnimatorCondition[] conditions - { - get; - set; - } - } - - [NativeHeader("Editor/Src/Animation/Transition.h")] - [NativeHeader("Editor/Src/Animation/StateMachine.bindings.h")] - public class AnimatorTransition : AnimatorTransitionBase - { - public AnimatorTransition() - { - Internal_CreateAnimatorTransition(this); - } - - [FreeFunction("StateMachineBindings::Internal_CreateAnimatorTransition")] - extern private static void Internal_CreateAnimatorTransition([Writable] AnimatorTransition mono); - } - - [NativeHeader("Editor/Src/Animation/Transition.h")] - [NativeHeader("Editor/Src/Animation/StateMachine.bindings.h")] - public class AnimatorStateTransition : AnimatorTransitionBase - { - public AnimatorStateTransition() - { - Internal_CreateAnimatorStateTransition(this); - } - - [FreeFunction("StateMachineBindings::Internal_CreateAnimatorStateTransition")] - extern private static void Internal_CreateAnimatorStateTransition([Writable] AnimatorStateTransition self); - - extern public float duration - { - [NativeMethod("GetTransitionDuration")] - get; - [NativeMethod("SetTransitionDuration")] - set; - } - extern public float offset - { - [NativeMethod("GetTransitionOffset")] - get; - [NativeMethod("SetTransitionOffset")] - set; - } - extern public TransitionInterruptionSource interruptionSource - { - [NativeMethod("GetTransitionInterruptionSource")] - get; - [NativeMethod("SetTransitionInterruptionSource")] - set; - } - extern public bool orderedInterruption { get; set; } - extern public float exitTime { get; set; } - extern public bool hasExitTime { get; set; } - extern public bool hasFixedDuration { get; set; } - extern public bool canTransitionToSelf { get; set; } - } - - [NativeHeader("Editor/Src/Animation/StateMachine.h")] - [NativeHeader("Editor/Src/Animation/StateMachine.bindings.h")] - [NativeHeader("Editor/Src/Animation/StateMachineBehaviourScripting.h")] - public partial class AnimatorState : Object - { - public AnimatorState() - { - Internal_CreateAnimatorState(this); - } - - [FreeFunction("StateMachineBindings::Internal_CreateAnimatorState")] - extern private static void Internal_CreateAnimatorState([Writable] AnimatorState self); - - extern public int nameHash - { - get; - } - extern public Motion motion { get; set; } - extern public float speed { get; set; } - extern public float cycleOffset { get; set; } - extern public bool mirror { get; set; } - extern public bool iKOnFeet { get; set; } - extern public bool writeDefaultValues { get; set; } - extern public string tag { get; set; } - extern public string speedParameter { get; set; } - extern public string cycleOffsetParameter { get; set; } - extern public string mirrorParameter { get; set; } - extern public string timeParameter { get; set; } - extern public bool speedParameterActive - { - [NativeMethod("IsSpeedParameterActive")] - get; - set; - } - extern public bool cycleOffsetParameterActive - { - [NativeMethod("IsCycleOffsetParameterActive")] - get; - set; - } - extern public bool mirrorParameterActive - { - [NativeMethod("IsMirrorParameterActive")] - get; - set; - } - - extern public bool timeParameterActive - { - [NativeMethod("IsTimeParameterActive")] - get; - set; - } - - extern internal void AddBehaviour(int instanceID); - extern internal void RemoveBehaviour(int index); - - extern public AnimatorStateTransition[] transitions { get; set; } - - [FreeFunction(Name = "ScriptingAddStateMachineBehaviourWithType", HasExplicitThis = true)] - extern private ScriptableObject ScriptingAddStateMachineBehaviourWithType(Type stateMachineBehaviourType); - - [TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)] - public StateMachineBehaviour AddStateMachineBehaviour(Type stateMachineBehaviourType) - { - return (StateMachineBehaviour)ScriptingAddStateMachineBehaviourWithType(stateMachineBehaviourType); - } - - public T AddStateMachineBehaviour() where T : StateMachineBehaviour - { - return AddStateMachineBehaviour(typeof(T)) as T; - } - } - - [NativeHeader("Editor/Src/Animation/StateMachine.h")] - [NativeHeader("Editor/Src/Animation/StateMachine.bindings.h")] - [RequiredByNativeCode] - public struct ChildAnimatorState - { - AnimatorState m_State; - Vector3 m_Position; - - public AnimatorState state { get { return m_State; } set { m_State = value; } } - public Vector3 position { get {return m_Position; } set { m_Position = value; } } - } - - - [NativeHeader("Editor/Src/Animation/StateMachine.h")] - [NativeHeader("Editor/Src/Animation/StateMachine.bindings.h")] - [RequiredByNativeCode] - public struct ChildAnimatorStateMachine - { - AnimatorStateMachine m_StateMachine; - Vector3 m_Position; - - public AnimatorStateMachine stateMachine { get { return m_StateMachine; } set { m_StateMachine = value; } } - public Vector3 position { get {return m_Position; } set { m_Position = value; } } - } - - [NativeHeader("Editor/Src/Animation/StateMachine.h")] - [NativeHeader("Editor/Src/Animation/StateMachine.bindings.h")] - [NativeHeader("Editor/Src/Animation/StateMachineBehaviourScripting.h")] - public partial class AnimatorStateMachine : Object - { - public AnimatorStateMachine() - { - Internal_CreateAnimatorStateMachine(this); - } - - [FreeFunction("StateMachineBindings::Internal_CreateAnimatorStateMachine")] - extern private static void Internal_CreateAnimatorStateMachine([Writable] AnimatorStateMachine self); - - extern public ChildAnimatorState[] states { get; set; } - - extern public ChildAnimatorStateMachine[] stateMachines { get; set; } - - extern public AnimatorState defaultState - { - [NativeMethod("DefaultState")] - get; - set; - } - - extern public Vector3 anyStatePosition { get; set; } - extern public Vector3 entryPosition { get; set; } - extern public Vector3 exitPosition { get; set; } - extern public Vector3 parentStateMachinePosition { get; set; } - extern public AnimatorStateTransition[] anyStateTransitions { get; set; } - extern public AnimatorTransition[] entryTransitions { get; set; } - - extern public AnimatorTransition[] GetStateMachineTransitions(AnimatorStateMachine sourceStateMachine); - - extern public void SetStateMachineTransitions(AnimatorStateMachine sourceStateMachine, AnimatorTransition[] transitions); - - extern internal void AddBehaviour(int instanceID); - extern internal void RemoveBehaviour(int index); - - [FreeFunction(Name = "ScriptingAddStateMachineBehaviourWithType", HasExplicitThis = true)] - extern private ScriptableObject ScriptingAddStateMachineBehaviourWithType(Type stateMachineBehaviourType); - - [TypeInferenceRule(TypeInferenceRules.TypeReferencedByFirstArgument)] - public StateMachineBehaviour AddStateMachineBehaviour(Type stateMachineBehaviourType) - { - return (StateMachineBehaviour)ScriptingAddStateMachineBehaviourWithType(stateMachineBehaviourType); - } - - public T AddStateMachineBehaviour() where T : StateMachineBehaviour - { - return AddStateMachineBehaviour(typeof(T)) as T; - } - - extern public string MakeUniqueStateName(string name); - extern public string MakeUniqueStateMachineName(string name); - - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Internals - - extern internal void Clear(); - [NativeMethod("RemoveState")] - extern internal void RemoveStateInternal(AnimatorState state); - [NativeMethod("RemoveStateMachine")] - extern internal void RemoveStateMachineInternal(AnimatorStateMachine stateMachine); - - extern internal void MoveState(AnimatorState state, AnimatorStateMachine target); - extern internal void MoveStateMachine(AnimatorStateMachine stateMachine, AnimatorStateMachine target); - - extern internal bool HasState(AnimatorState state, bool recursive); - extern internal bool HasStateMachine(AnimatorStateMachine state, bool recursive); - - extern internal int transitionCount - { - get; - } - } -} diff --git a/Editor/Mono/StateMachineBehaviourContext.bindings.cs b/Editor/Mono/StateMachineBehaviourContext.bindings.cs deleted file mode 100644 index eeac9a33dd..0000000000 --- a/Editor/Mono/StateMachineBehaviourContext.bindings.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using UnityEditor; -using System.Runtime.InteropServices; - -namespace UnityEditor.Animations -{ - [NativeHeader("Editor/Src/Animation/StateMachineBehaviourContext.h")] - [System.Serializable] - [StructLayout(LayoutKind.Sequential)] - [NativeAsStruct] - public partial class StateMachineBehaviourContext - { - [NativeName("m_AnimatorController")] - public AnimatorController animatorController; - [NativeName("m_AnimatorObject")] - public UnityEngine.Object animatorObject; - [NativeName("m_LayerIndex")] - public int layerIndex; - } -} diff --git a/Editor/Mono/StaticEditorFlags.cs b/Editor/Mono/StaticEditorFlags.cs deleted file mode 100644 index 2601f33a14..0000000000 --- a/Editor/Mono/StaticEditorFlags.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor -{ - // Static Editor Flags - [Flags] - public enum StaticEditorFlags - { - // Considered static for lightmapping. - LightmapStatic = 1, - // Considered static for occlusion. - OccluderStatic = 2, - // Considered static for occlusion. - OccludeeStatic = 16, - // Consider for static batching. - BatchingStatic = 4, - // Considered static for navigation. - NavigationStatic = 8, - // Auto-generate OffMeshLink. - OffMeshLinkGeneration = 32, - ReflectionProbeStatic = 64 - } -} diff --git a/Editor/Mono/StyleSheets/CSSSpec.cs b/Editor/Mono/StyleSheets/CSSSpec.cs deleted file mode 100644 index b46aab7d80..0000000000 --- a/Editor/Mono/StyleSheets/CSSSpec.cs +++ /dev/null @@ -1,120 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Text.RegularExpressions; -using UnityEngine.StyleSheets; - -namespace UnityEditor.StyleSheets -{ - static class CSSSpec - { - static readonly Regex rgx = new Regex( - @"(?#[-]?\w[\w-]*)|(?\.[\w-]+)|(?:[\w-]+(\((?.+)\))?)|(?[^\-]\w+)|(?\*)|\s+", - RegexOptions.IgnoreCase | RegexOptions.Compiled); - - const int typeSelectorWeight = 1; - const int classSelectorWeight = 10; - const int idSelectorWeight = 100; - - public static int GetSelectorSpecificity(string selector) - { - StyleSelectorPart[] parts; - int score = 0; - if (ParseSelector(selector, out parts)) - { - score = GetSelectorSpecificity(parts); - } - return score; - } - - // See https://www.w3.org/TR/selectors/#specificity - // A proper CSS library should provide us with this - public static int GetSelectorSpecificity(StyleSelectorPart[] parts) - { - // always add 1 otherwise we wouldn't be able to distinguish between default C# value for int (0) - // and an actual specificity (0 for *) - int score = 1; - for (int i = 0; i < parts.Length; i++) - { - switch (parts[i].type) - { - case StyleSelectorType.Type: - score += typeSelectorWeight; - break; - case StyleSelectorType.Class: - case StyleSelectorType.PseudoClass: - score += classSelectorWeight; - break; - case StyleSelectorType.RecursivePseudoClass: - throw new ArgumentException("Recursive pseudo classes are not supported"); - case StyleSelectorType.ID: - score += idSelectorWeight; - break; - default: - break; - } - } - return score; - } - - public static bool ParseSelector(string selector, out StyleSelectorPart[] parts) - { - var matches = rgx.Matches(selector); - int count = matches.Count; - - if (count < 1) - { - parts = null; - return false; - } - - parts = new StyleSelectorPart[count]; - - for (int i = 0; i < count; i++) - { - Match match = matches[i]; - StyleSelectorType type = StyleSelectorType.Unknown; - string value = string.Empty; - if (!string.IsNullOrEmpty(match.Groups["wildcard"].Value)) - { - value = "*"; - type = StyleSelectorType.Wildcard; - } - else if (!string.IsNullOrEmpty(match.Groups["id"].Value)) - { - value = match.Groups["id"].Value.Substring(1); - type = StyleSelectorType.ID; - } - else if (!string.IsNullOrEmpty(match.Groups["class"].Value)) - { - value = match.Groups["class"].Value.Substring(1); - type = StyleSelectorType.Class; - } - else if (!string.IsNullOrEmpty(match.Groups["pseudoclass"].Value)) - { - var pseudoClassParam = match.Groups["param"].Value; - if (!string.IsNullOrEmpty(pseudoClassParam)) - { - value = pseudoClassParam; - type = StyleSelectorType.RecursivePseudoClass; - } - else - { - value = match.Groups["pseudoclass"].Value.Substring(1); - type = StyleSelectorType.PseudoClass; - } - } - else if (!string.IsNullOrEmpty(match.Groups["type"].Value)) - { - value = match.Groups["type"].Value; - type = StyleSelectorType.Type; - } - parts[i] = new StyleSelectorPart() { type = type, value = value }; - } - - return true; - } - } -} diff --git a/Editor/Mono/StyleSheets/StyleSheetAssetPostProcessor.cs b/Editor/Mono/StyleSheets/StyleSheetAssetPostProcessor.cs deleted file mode 100644 index f592067887..0000000000 --- a/Editor/Mono/StyleSheets/StyleSheetAssetPostProcessor.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleSheets; -using UnityStyleSheet = UnityEngine.StyleSheets.StyleSheet; - -namespace UnityEditor.StyleSheets -{ - class StyleSheetAssetPostprocessor : AssetPostprocessor - { - private static HashSet s_StyleSheetReferencedAssetPaths; - - public static void ClearReferencedAssets() - { - s_StyleSheetReferencedAssetPaths = null; - } - - public static void AddReferencedAssetPath(string assetPath) - { - if (s_StyleSheetReferencedAssetPaths == null) - s_StyleSheetReferencedAssetPaths = new HashSet(); - - s_StyleSheetReferencedAssetPaths.Add(assetPath); - } - - private static void ProcessAssetPath(string assetPath) - { - if (s_StyleSheetReferencedAssetPaths == null || !s_StyleSheetReferencedAssetPaths.Contains(assetPath)) - return; - - // Clear the style cache to force all USS rules to recompute - // and subsequently reload/reimport all images. - StyleContext.ClearStyleCache(); - - // Force all currently active panels to repaint by marking them dirty. - var iterator = UIElementsUtility.GetPanelsIterator(); - while (iterator.MoveNext()) - { - var panel = iterator.Current.Value; - panel.visualTree.Dirty(ChangeType.Styles | ChangeType.Repaint); - } - } - - private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, - string[] movedFromAssetPaths) - { - if (s_StyleSheetReferencedAssetPaths == null) - return; - - foreach (var deletedAssetPath in deletedAssets) - { - ProcessAssetPath(deletedAssetPath); - } - - for (int i = 0; i < movedAssets.Length; i++) - { - ProcessAssetPath(movedAssets[i]); - ProcessAssetPath(movedFromAssetPaths[i]); - } - } - } -} diff --git a/Editor/Mono/StyleSheets/StyleSheetBuilder.cs b/Editor/Mono/StyleSheets/StyleSheetBuilder.cs deleted file mode 100644 index bfeeb2c056..0000000000 --- a/Editor/Mono/StyleSheets/StyleSheetBuilder.cs +++ /dev/null @@ -1,183 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -//#define ENABLE_STYLE_SHEET_BUILDER_LOGS -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.StyleSheets; - -namespace UnityEditor.StyleSheets -{ - class StyleSheetBuilder - { - public struct ComplexSelectorScope : System.IDisposable - { - StyleSheetBuilder m_Builder; - - public ComplexSelectorScope(StyleSheetBuilder builder) - { - m_Builder = builder; - } - - public void Dispose() - { - m_Builder.EndComplexSelector(); - } - } - - enum BuilderState - { - Init, - Rule, - ComplexSelector, - Property - } - BuilderState m_BuilderState; - - List m_Floats = new List(); - List m_Colors = new List(); - List m_Strings = new List(); - List m_Rules = new List(); - List m_ComplexSelectors = new List(); - - List m_CurrentProperties = new List(); - List m_CurrentValues = new List(); - StyleComplexSelector m_CurrentComplexSelector; - List m_CurrentSelectors = new List(); - string m_CurrentPropertyName; - StyleRule m_CurrentRule; - - public void BeginRule(int ruleLine) - { - Log("Beginning rule"); - Debug.Assert(m_BuilderState == BuilderState.Init); - m_BuilderState = BuilderState.Rule; - - m_CurrentRule = new StyleRule { line = ruleLine }; - } - - public ComplexSelectorScope BeginComplexSelector(int specificity) - { - Log("Begin complex selector with specificity " + specificity); - Debug.Assert(m_BuilderState == BuilderState.Rule); - m_BuilderState = BuilderState.ComplexSelector; - - m_CurrentComplexSelector = new StyleComplexSelector(); - m_CurrentComplexSelector.specificity = specificity; - m_CurrentComplexSelector.ruleIndex = m_Rules.Count; - - return new ComplexSelectorScope(this); - } - - public void AddSimpleSelector(StyleSelectorPart[] parts, StyleSelectorRelationship previousRelationsip) - { - Debug.Assert(m_BuilderState == BuilderState.ComplexSelector); - var selector = new StyleSelector(); - selector.parts = parts; - selector.previousRelationship = previousRelationsip; - - Log("Add simple selector " + selector); - - m_CurrentSelectors.Add(selector); - } - - public void EndComplexSelector() - { - Log("Ending complex selector"); - - Debug.Assert(m_BuilderState == BuilderState.ComplexSelector); - m_BuilderState = BuilderState.Rule; - - if (m_CurrentSelectors.Count > 0) - { - m_CurrentComplexSelector.selectors = m_CurrentSelectors.ToArray(); - m_ComplexSelectors.Add(m_CurrentComplexSelector); - m_CurrentSelectors.Clear(); - } - m_CurrentComplexSelector = null; - } - - public void BeginProperty(string name) - { - Log("Begin property named " + name); - - Debug.Assert(m_BuilderState == BuilderState.Rule); - m_BuilderState = BuilderState.Property; - - m_CurrentPropertyName = name; - } - - public void AddValue(float value) - { - RegisterValue(m_Floats, StyleValueType.Float, value); - } - - public void AddValue(StyleValueKeyword keyword) - { - // for keyword we use the index to store the enum value - m_CurrentValues.Add(new StyleValueHandle((int)keyword, StyleValueType.Keyword)); - } - - public void AddValue(string value, StyleValueType type) - { - RegisterValue(m_Strings, type, value); - } - - public void AddValue(Color value) - { - RegisterValue(m_Colors, StyleValueType.Color, value); - } - - public void EndProperty() - { - Log("Ending property"); - - Debug.Assert(m_BuilderState == BuilderState.Property); - m_BuilderState = BuilderState.Rule; - - StyleProperty property = new StyleProperty(); - property.name = m_CurrentPropertyName; - property.values = m_CurrentValues.ToArray(); - m_CurrentProperties.Add(property); - m_CurrentValues.Clear(); - } - - public int EndRule() - { - Log("Ending rule"); - - Debug.Assert(m_BuilderState == BuilderState.Rule); - m_BuilderState = BuilderState.Init; - - m_CurrentRule.properties = m_CurrentProperties.ToArray(); - m_Rules.Add(m_CurrentRule); - m_CurrentRule = null; - m_CurrentProperties.Clear(); - return m_Rules.Count - 1; - } - - public void BuildTo(StyleSheet writeTo) - { - Debug.Assert(m_BuilderState == BuilderState.Init); - - writeTo.floats = m_Floats.ToArray(); - writeTo.colors = m_Colors.ToArray(); - writeTo.strings = m_Strings.ToArray(); - writeTo.rules = m_Rules.ToArray(); - writeTo.complexSelectors = m_ComplexSelectors.ToArray(); - } - - void RegisterValue(List list, StyleValueType type, T value) - { - Log("Add value of type " + type + " : " + value); - Debug.Assert(m_BuilderState == BuilderState.Property); - list.Add(value); - m_CurrentValues.Add(new StyleValueHandle(list.Count - 1, type)); - } - - static void Log(string msg) - { - } - } -} diff --git a/Editor/Mono/StyleSheets/StyleSheetEditor.cs b/Editor/Mono/StyleSheets/StyleSheetEditor.cs deleted file mode 100644 index b7bf3b5637..0000000000 --- a/Editor/Mono/StyleSheets/StyleSheetEditor.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; -using UnityEngine.StyleSheets; - -namespace UnityEditor.StyleSheets -{ - [CustomEditor(typeof(StyleSheet))] - internal class StyleSheetEditor : Editor - { - private Texture2D m_FileTypeIcon; - - protected void OnEnable() - { - m_FileTypeIcon = EditorGUIUtility.FindTexture("UssScript Icon"); - } - - public override bool HasPreviewGUI() - { - return true; - } - - private void RenderIcon(Rect iconRect) - { - Debug.Assert(m_FileTypeIcon != null); - GUI.DrawTexture(iconRect, m_FileTypeIcon, ScaleMode.ScaleToFit); - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - const int k_IconSize = 64; - - base.OnPreviewGUI(r, background); - if (r.width > k_IconSize || r.height > k_IconSize) - base.OnPreviewGUI(r, background); - else - RenderIcon(r); - } - } -} diff --git a/Editor/Mono/StyleSheets/StyleSheetImportErrors.cs b/Editor/Mono/StyleSheets/StyleSheetImportErrors.cs deleted file mode 100644 index 6e3b542254..0000000000 --- a/Editor/Mono/StyleSheets/StyleSheetImportErrors.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor.StyleSheets -{ - enum StyleSheetImportErrorType - { - Syntax, - Semantic, - Other, - Internal - } - - enum StyleSheetImportErrorCode - { - None, - Internal, - UnsupportedFunction, - UnsupportedParserType, - UnsupportedUnit, - InvalidSelectorListDelimiter, - InvalidComplexSelectorDelimiter, - UnsupportedSelectorFormat, - RecursiveSelectorDetected - } - - class StyleSheetImportErrors - { - struct Error - { - public readonly StyleSheetImportErrorType error; - public readonly StyleSheetImportErrorCode code; - public readonly string context; - - public Error(StyleSheetImportErrorType error, StyleSheetImportErrorCode code, string context) - { - this.error = error; - this.code = code; - this.context = context; - } - - public override string ToString() - { - return string.Format("[StyleSheetImportError: error={0}, code={1}, context={2}]", error, code, context); - } - } - - List m_Errors = new List(); - - public void AddSyntaxError(string context) - { - m_Errors.Add(new Error( - StyleSheetImportErrorType.Syntax, - StyleSheetImportErrorCode.None, - context) - ); - } - - public void AddSemanticError(StyleSheetImportErrorCode code, string context) - { - m_Errors.Add(new Error( - StyleSheetImportErrorType.Semantic, - code, - context) - ); - } - - public void AddInternalError(string context) - { - m_Errors.Add(new Error( - StyleSheetImportErrorType.Internal, - StyleSheetImportErrorCode.None, - context) - ); - } - - public bool hasErrors { get { return m_Errors.Count > 0; } } - - public IEnumerable FormatErrors() - { - return m_Errors.Select(e => e.ToString()); - } - } -} diff --git a/Editor/Mono/StyleSheets/StyleSheetImporter.cs b/Editor/Mono/StyleSheets/StyleSheetImporter.cs deleted file mode 100644 index 732f52078d..0000000000 --- a/Editor/Mono/StyleSheets/StyleSheetImporter.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using System.IO; -using UnityEngine; -using UnityEngine.Experimental.UIElements.StyleSheets; -using UnityEditor.Experimental.AssetImporters; -using UnityEngine.StyleSheets; - -namespace UnityEditor.StyleSheets -{ - [ScriptedImporter(3, "uss", -20)] - class StyleSheetImporter : ScriptedImporter - { - public override void OnImportAsset(AssetImportContext ctx) - { - var importer = new StyleSheetImporterImpl(); - string contents = File.ReadAllText(ctx.assetPath); - StyleSheet asset = ScriptableObject.CreateInstance(); - asset.hideFlags = HideFlags.NotEditable; - - if (importer.Import(asset, contents)) - { - ctx.AddObjectToAsset("stylesheet", asset); - - // Force the pre processor to rebuild its list of referenced asset paths - // as paths may have changed with this import. - StyleSheetAssetPostprocessor.ClearReferencedAssets(); - - // Clear the style cache to force all USS rules to recompute - // and subsequently reload/reimport all images. - StyleContext.ClearStyleCache(); - } - else - { - foreach (string importError in importer.errors.FormatErrors()) - { - Debug.LogError(importError); - } - } - } - } -} diff --git a/Editor/Mono/StyleSheets/StyleSheetImporterImpl.cs b/Editor/Mono/StyleSheets/StyleSheetImporterImpl.cs deleted file mode 100644 index cb80e26721..0000000000 --- a/Editor/Mono/StyleSheets/StyleSheetImporterImpl.cs +++ /dev/null @@ -1,341 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using ParserStyleSheet = ExCSS.StyleSheet; -using ParserStyleRule = ExCSS.StyleRule; -using UnityStyleSheet = UnityEngine.StyleSheets.StyleSheet; -using UnityEngine.StyleSheets; -using ExCSS; - -namespace UnityEditor.StyleSheets -{ - class StyleSheetImporterImpl - { - public StyleSheetImportErrors errors - { - get - { - return m_Errors; - } - } - - Parser m_Parser; - const string k_ResourcePathFunctionName = "resource"; - - StyleSheetBuilder m_Builder; - StyleSheetImportErrors m_Errors; - - public StyleSheetImporterImpl() - { - m_Parser = new Parser(); - m_Builder = new StyleSheetBuilder(); - m_Errors = new StyleSheetImportErrors(); - } - - public bool Import(UnityStyleSheet asset, string contents) - { - ParserStyleSheet styleSheet = m_Parser.Parse(contents); - - if (styleSheet.Errors.Count > 0) - { - foreach (StylesheetParseError error in styleSheet.Errors) - { - m_Errors.AddSyntaxError(error.ToString()); - } - } - else - { - try - { - VisitSheet(styleSheet); - } - catch (Exception exc) - { - m_Errors.AddInternalError(exc.Message); - } - } - - if (!m_Errors.hasErrors) - { - m_Builder.BuildTo(asset); - } - - return !m_Errors.hasErrors; - } - - void VisitSheet(ParserStyleSheet styleSheet) - { - foreach (ParserStyleRule rule in styleSheet.StyleRules) - { - m_Builder.BeginRule(rule.Line); - - // Note: we must rely on recursion to correctly handle parser types here - VisitBaseSelector(rule.Selector); - - foreach (Property property in rule.Declarations) - { - m_Builder.BeginProperty(property.Name); - - // Note: we must rely on recursion to correctly handle parser types here - VisitValue(m_Errors, m_Builder, property.Term); - - m_Builder.EndProperty(); - } - - m_Builder.EndRule(); - } - } - - internal static void VisitValue(StyleSheetImportErrors errors, StyleSheetBuilder ssb, Term term) - { - var primitiveTerm = term as PrimitiveTerm; - var colorTerm = term as HtmlColor; - var funcTerm = term as GenericFunction; - var termList = term as TermList; - - if (term == PrimitiveTerm.Inherit) - { - ssb.AddValue(StyleValueKeyword.Inherit); - } - else if (primitiveTerm != null) - { - string rawStr = term.ToString(); - - switch (primitiveTerm.PrimitiveType) - { - case UnitType.Pixel: - case UnitType.Number: - float? floatValue = primitiveTerm.GetFloatValue(UnitType.Pixel); - ssb.AddValue(floatValue.Value); - break; - case UnitType.Ident: - StyleValueKeyword keyword; - if (TryParseKeyword(rawStr, out keyword)) - { - ssb.AddValue(keyword); - } - else - { - ssb.AddValue(rawStr, StyleValueType.Enum); - } - break; - case UnitType.String: - string unquotedStr = rawStr.Trim('\'', '\"'); - ssb.AddValue(unquotedStr, StyleValueType.String); - break; - default: - errors.AddSemanticError(StyleSheetImportErrorCode.UnsupportedUnit, primitiveTerm.ToString()); - return; - } - } - else if (colorTerm != null) - { - var color = new Color((float)colorTerm.R / 255.0f, (float)colorTerm.G / 255.0f, (float)colorTerm.B / 255.0f, (float)colorTerm.A / 255.0f); - ssb.AddValue(color); - } - else if (funcTerm != null) - { - primitiveTerm = funcTerm.Arguments.FirstOrDefault() as PrimitiveTerm; - if (funcTerm.Name == k_ResourcePathFunctionName && primitiveTerm != null) - { - string path = primitiveTerm.Value as string; - ssb.AddValue(path, StyleValueType.ResourcePath); - } - else - { - errors.AddSemanticError(StyleSheetImportErrorCode.UnsupportedFunction, funcTerm.Name); - } - } - else if (termList != null) - { - foreach (Term childTerm in termList) - { - VisitValue(errors, ssb, childTerm); - } - return; - } - else - { - errors.AddInternalError(term.GetType().Name); - } - } - - void VisitBaseSelector(BaseSelector selector) - { - var selectorList = selector as AggregateSelectorList; - if (selectorList != null) - { - VisitSelectorList(selectorList); - return; - } - - var complexSelector = selector as ComplexSelector; - if (complexSelector != null) - { - VisitComplexSelector(complexSelector); - return; - } - - var simpleSelector = selector as SimpleSelector; - if (simpleSelector != null) - { - VisitSimpleSelector(simpleSelector.ToString()); - } - } - - void VisitSelectorList(AggregateSelectorList selectorList) - { - // OR selectors, just create an entry for each of them - if (selectorList.Delimiter == ",") - { - foreach (BaseSelector selector in selectorList) - { - VisitBaseSelector(selector); - } - } - // Work around a strange parser issue where sometimes simple selectors - // are wrapped inside SelectorList with no delimiter - else if (selectorList.Delimiter == string.Empty) - { - VisitSimpleSelector(selectorList.ToString()); - } - else - { - m_Errors.AddSemanticError(StyleSheetImportErrorCode.InvalidSelectorListDelimiter, selectorList.Delimiter); - } - } - - void VisitComplexSelector(ComplexSelector complexSelector) - { - int fullSpecificity = CSSSpec.GetSelectorSpecificity(complexSelector.ToString()); - - if (fullSpecificity == 0) - { - m_Errors.AddInternalError("Failed to calculate selector specificity " + complexSelector); - return; - } - - using (m_Builder.BeginComplexSelector(fullSpecificity)) - { - StyleSelectorRelationship relationShip = StyleSelectorRelationship.None; - - foreach (CombinatorSelector selector in complexSelector) - { - StyleSelectorPart[] parts; - - string simpleSelector = ExtractSimpleSelector(selector.Selector); - - if (string.IsNullOrEmpty(simpleSelector)) - { - m_Errors.AddInternalError("Expected simple selector inside complex selector " + simpleSelector); - return; - } - - if (CheckSimpleSelector(simpleSelector, out parts)) - { - m_Builder.AddSimpleSelector(parts, relationShip); - - // Read relation for next element - switch (selector.Delimiter) - { - case Combinator.Child: - relationShip = StyleSelectorRelationship.Child; - break; - case Combinator.Descendent: - relationShip = StyleSelectorRelationship.Descendent; - break; - default: - m_Errors.AddSemanticError(StyleSheetImportErrorCode.InvalidComplexSelectorDelimiter, complexSelector.ToString()); - return; - } - } - else - { - return; - } - } - } - } - - void VisitSimpleSelector(string selector) - { - StyleSelectorPart[] parts; - if (CheckSimpleSelector(selector, out parts)) - { - int specificity = CSSSpec.GetSelectorSpecificity(parts); - - if (specificity == 0) - { - m_Errors.AddInternalError("Failed to calculate selector specificity " + selector); - return; - } - - using (m_Builder.BeginComplexSelector(specificity)) - { - m_Builder.AddSimpleSelector(parts, StyleSelectorRelationship.None); - } - } - } - - string ExtractSimpleSelector(BaseSelector selector) - { - SimpleSelector simpleSelector = selector as SimpleSelector; - - if (simpleSelector != null) - { - return selector.ToString(); - } - - AggregateSelectorList selectorList = selector as AggregateSelectorList; - - // Work around a strange parser issue where sometimes simple selectors - // are wrapped inside SelectorList with no delimiter - if (selectorList != null && selectorList.Delimiter == string.Empty) - { - return selectorList.ToString(); - } - - return string.Empty; - } - - static Dictionary s_NameCache; - - static bool TryParseKeyword(string rawStr, out StyleValueKeyword value) - { - if (s_NameCache == null) - { - s_NameCache = new Dictionary(); - foreach (StyleValueKeyword kw in Enum.GetValues(typeof(StyleValueKeyword))) - { - s_NameCache[kw.ToString().ToLower()] = kw; - } - } - return s_NameCache.TryGetValue(rawStr.ToLower(), out value); - } - - bool CheckSimpleSelector(string selector, out StyleSelectorPart[] parts) - { - if (!CSSSpec.ParseSelector(selector, out parts)) - { - m_Errors.AddSemanticError(StyleSheetImportErrorCode.UnsupportedSelectorFormat, selector); - return false; - } - if (parts.Any(p => p.type == StyleSelectorType.Unknown)) - { - m_Errors.AddSemanticError(StyleSheetImportErrorCode.UnsupportedSelectorFormat, selector); - return false; - } - if (parts.Any(p => p.type == StyleSelectorType.RecursivePseudoClass)) - { - m_Errors.AddSemanticError(StyleSheetImportErrorCode.RecursiveSelectorDetected, selector); - return false; - } - return true; - } - } -} diff --git a/Editor/Mono/StyleSheets/StyleSheetResourceUtil.cs b/Editor/Mono/StyleSheets/StyleSheetResourceUtil.cs deleted file mode 100644 index 5f32b7414c..0000000000 --- a/Editor/Mono/StyleSheets/StyleSheetResourceUtil.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System.IO; - -namespace UnityEditor.StyleSheets -{ - internal class StyleSheetResourceUtil - { - internal static Object LoadResource(string pathName, System.Type type) - { - return LoadResource(pathName, type, GUIUtility.pixelsPerPoint > 1.0f); - } - - internal static Object LoadResource(string pathName, System.Type type, bool lookForRetinaAssets) - { - Object resource = null; - string hiResPath = string.Empty; - - lookForRetinaAssets &= (type == typeof(Texture2D)); - - if (lookForRetinaAssets) - { - string ext = Path.GetExtension(pathName); - string fileRenamed = Path.GetFileNameWithoutExtension(pathName) + "@2x" + ext; - hiResPath = Path.Combine(Path.GetDirectoryName(pathName), fileRenamed); - lookForRetinaAssets = !string.IsNullOrEmpty(hiResPath); - } - - if (lookForRetinaAssets) - { - resource = EditorGUIUtility.Load(hiResPath); - } - - if (resource == null) - { - resource = EditorGUIUtility.Load(pathName); - } - - if (resource == null && lookForRetinaAssets) - { - resource = Resources.Load(hiResPath, type); - } - - if (resource == null) - { - resource = Resources.Load(pathName, type); - } - - if (resource == null && lookForRetinaAssets) - { - resource = AssetDatabase.LoadMainAssetAtPath(hiResPath); - } - - if (resource == null) - { - resource = AssetDatabase.LoadMainAssetAtPath(pathName); - } - - if (resource != null) - { - Debug.Assert(type.IsAssignableFrom(resource.GetType()), "Resource type mismatch"); - - // Add to post processor for tracking asset moves/deletes. - var absoluteAssetPath = AssetDatabase.GetAssetPath(resource); - if (type != typeof(UnityEngine.StyleSheets.StyleSheet) && !absoluteAssetPath.StartsWith("Library")) - { - StyleSheetAssetPostprocessor.AddReferencedAssetPath(absoluteAssetPath); - } - } - - return resource; - } - } -} diff --git a/Editor/Mono/SyncProject.cs b/Editor/Mono/SyncProject.cs deleted file mode 100644 index e68103aa66..0000000000 --- a/Editor/Mono/SyncProject.cs +++ /dev/null @@ -1,452 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Linq; -using System.Collections.Generic; -using Microsoft.Win32; -using UnityEditor.Callbacks; -using UnityEditor.VisualStudioIntegration; -using UnityEngine; -using UnityEditorInternal; - -namespace UnityEditor -{ - internal enum VisualStudioVersion - { - Invalid = 0, - VisualStudio2008 = 9, - VisualStudio2010 = 10, - VisualStudio2012 = 11, - VisualStudio2013 = 12, - VisualStudio2015 = 14, - VisualStudio2017 = 15, - } - - internal class VisualStudioPath - { - public string Path { get; set; } - public string Edition { get; set; } - - public VisualStudioPath(string path, string edition = "") - { - Path = path; - Edition = edition; - } - } - - [InitializeOnLoad] - internal class SyncVS : AssetPostprocessor - { - static bool s_AlreadySyncedThisDomainReload; - - static SyncVS() - { - Synchronizer = new SolutionSynchronizer(Directory.GetParent(Application.dataPath).FullName, new SolutionSynchronizationSettings()); - try - { - InstalledVisualStudios = GetInstalledVisualStudios() as Dictionary; - } - catch (Exception ex) - { - Console.WriteLine("Error detecting Visual Studio installations: {0}{1}{2}", ex.Message, Environment.NewLine, ex.StackTrace); - InstalledVisualStudios = new Dictionary(); - } - - SetVisualStudioAsEditorIfNoEditorWasSet(); - } - - private static void SetVisualStudioAsEditorIfNoEditorWasSet() - { - var externalEditor = EditorPrefs.GetString("kScriptsDefaultApp"); - var bestVisualStudio = FindBestVisualStudio(); - if (externalEditor == "" && bestVisualStudio != null) - EditorPrefs.SetString("kScriptsDefaultApp", bestVisualStudio); - } - - public static string FindBestVisualStudio() - { - var vs = InstalledVisualStudios.OrderByDescending(kvp => kvp.Key).Select(kvp2 => kvp2.Value).FirstOrDefault(); - return vs == null ? null : vs.Last().Path; - } - - private static readonly SolutionSynchronizer Synchronizer; - internal static Dictionary InstalledVisualStudios { get; private set; } - - internal class SolutionSynchronizationSettings : DefaultSolutionSynchronizationSettings - { - public override int VisualStudioVersion - { - get - { - var vs = ScriptEditorUtility.GetExternalScriptEditor(); - if (InstalledVisualStudios.ContainsKey(UnityEditor.VisualStudioVersion.VisualStudio2008) && - (vs != String.Empty) && - PathsAreEquivalent(InstalledVisualStudios[UnityEditor.VisualStudioVersion.VisualStudio2008].Last().Path, vs)) - return 9; - - return 10; - } - } - - public override string SolutionTemplate - { - get { return EditorPrefs.GetString("VSSolutionText", base.SolutionTemplate); } - } - - public override string GetProjectHeaderTemplate(ScriptingLanguage language) - { - return EditorPrefs.GetString("VSProjectHeader", base.GetProjectHeaderTemplate(language)); - } - - public override string GetProjectFooterTemplate(ScriptingLanguage language) - { - return EditorPrefs.GetString("VSProjectFooter", base.GetProjectFooterTemplate(language)); - } - - public override string EditorAssemblyPath - { - get { return UnityEditorInternal.InternalEditorUtility.GetEditorAssemblyPath(); } - } - - public override string EngineAssemblyPath - { - get { return UnityEditorInternal.InternalEditorUtility.GetEngineAssemblyPath(); } - } - - public override string[] Defines - { - get { return EditorUserBuildSettings.activeScriptCompilationDefines; } - } - - protected override string FrameworksPath() - { - return EditorApplication.applicationContentsPath; - } - - internal static bool IsOSX - { - get { return System.Environment.OSVersion.Platform == System.PlatformID.Unix; } - } - - internal static bool IsWindows - { - get { return !IsOSX && System.IO.Path.DirectorySeparatorChar == '\\' && System.Environment.NewLine == "\r\n"; } - } - } - - public static bool ProjectExists() - { - return Synchronizer.SolutionExists(); - } - - public static void CreateIfDoesntExist() - { - if (!Synchronizer.SolutionExists()) - { - Synchronizer.Sync(); - } - } - - class BuildTargetChangedHandler : Build.IActiveBuildTargetChanged - { - public int callbackOrder { get { return 0; } } - - public void OnActiveBuildTargetChanged(BuildTarget oldTarget, BuildTarget newTarget) - { - SyncVisualStudioProjectIfItAlreadyExists(); - } - } - - public static void SyncVisualStudioProjectIfItAlreadyExists() - { - if (Synchronizer.SolutionExists()) - { - Synchronizer.Sync(); - } - } - - // For the time being this doesn't use the callback - public static void PostprocessSyncProject( - string[] importedAssets, - string[] addedAssets, - string[] deletedAssets, - string[] movedAssets, - string[] movedFromAssetPaths) - { - Synchronizer.SyncIfNeeded(addedAssets.Union(deletedAssets.Union(movedAssets.Union(movedFromAssetPaths)))); - } - - [MenuItem("Assets/Open C# Project")] - static void SyncAndOpenSolution() - { - SyncSolution(); - OpenProjectFileUnlessInBatchMode(); - } - - public static void SyncSolution() - { - // Ensure that the mono islands are up-to-date - AssetDatabase.Refresh(); - - Synchronizer.Sync(); - } - - public static void SyncIfFirstFileOpenSinceDomainLoad() - { - if (s_AlreadySyncedThisDomainReload) - return; - - s_AlreadySyncedThisDomainReload = true; - Synchronizer.Sync(); - } - - private static void OpenProjectFileUnlessInBatchMode() - { - if (InternalEditorUtility.inBatchMode) - return; - - InternalEditorUtility.OpenFileAtLineExternal("", -1); - } - - /// - /// Detects Visual Studio installations using the Windows registry - /// - /// - /// The detected Visual Studio installations - /// - private static IDictionary GetInstalledVisualStudios() - { - var versions = new Dictionary(); - - if (SolutionSynchronizationSettings.IsWindows) - { - foreach (VisualStudioVersion version in Enum.GetValues(typeof(VisualStudioVersion))) - { - if (version > VisualStudioVersion.VisualStudio2015) - continue; - - try - { - // Try COMNTOOLS environment variable first - string key = Environment.GetEnvironmentVariable(string.Format("VS{0}0COMNTOOLS", (int)version)); - if (!string.IsNullOrEmpty(key)) - { - string path = UnityEditor.Utils.Paths.Combine(key, "..", "IDE", "devenv.exe"); - if (File.Exists(path)) - { - versions[version] = new[] { new VisualStudioPath(path) }; - continue; - } - } - - // Try the proper registry key - key = GetRegistryValue( - string.Format(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\{0}.0", (int)version), "InstallDir"); - - // Try to fallback to the 32bits hive - if (string.IsNullOrEmpty(key)) - key = GetRegistryValue( - string.Format(@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\{0}.0", (int)version), "InstallDir"); - - if (!string.IsNullOrEmpty(key)) - { - string path = UnityEditor.Utils.Paths.Combine(key, "devenv.exe"); - if (File.Exists(path)) - { - versions[version] = new[] { new VisualStudioPath(path) }; - continue; - } - } - - // Fallback to debugger key - key = GetRegistryValue( - // VS uses this key for the local debugger path - string.Format(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\{0}.0\Debugger", (int)version), "FEQARuntimeImplDll"); - if (!string.IsNullOrEmpty(key)) - { - string path = DeriveVisualStudioPath(key); - if (!string.IsNullOrEmpty(path) && File.Exists(path)) - versions[version] = new[] { new VisualStudioPath(DeriveVisualStudioPath(key)) }; - } - } - catch - { - // This can happen with a registry lookup failure - } - } - - var requiredWorkloads = new[] {"Microsoft.VisualStudio.Workload.ManagedGame"}; - var raw = VisualStudioUtil.FindVisualStudioDevEnvPaths((int)VisualStudioVersion.VisualStudio2017, requiredWorkloads); - - var visualStudioPaths = VisualStudioUtil.ParseRawDevEnvPaths(raw) - .Where(vs => !requiredWorkloads.Except(vs.Workloads).Any()) // All required workloads must be present - .Select(vs => new VisualStudioPath(vs.DevEnvPath, vs.Edition)) - .ToArray(); - - if (visualStudioPaths.Length != 0) - { - versions[VisualStudioVersion.VisualStudio2017] = visualStudioPaths; - } - } - - return versions; - } - - static string GetRegistryValue(string path, string key) - { - try - { - return Microsoft.Win32.Registry.GetValue(path, key, null) as string; - } - catch (Exception) - { - return ""; - } - } - - /// - /// Derives the Visual Studio installation path from the debugger path - /// - /// - /// The Visual Studio installation path (to devenv.exe) - /// - /// - /// The debugger path from the windows registry - /// - private static string DeriveVisualStudioPath(string debuggerPath) - { - string startSentinel = DeriveProgramFilesSentinel(); - string endSentinel = "Common7"; - bool started = false; - string[] tokens = debuggerPath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); - - string path = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); - - // Walk directories in debugger path, chop out "Program Files\INSTALLATION\PATH\HERE\Common7" - foreach (var token in tokens) - { - if (!started && string.Equals(startSentinel, token, StringComparison.OrdinalIgnoreCase)) - { - started = true; - continue; - } - if (started) - { - path = Path.Combine(path, token); - if (string.Equals(endSentinel, token, StringComparison.OrdinalIgnoreCase)) - break; - } - } - - return UnityEditor.Utils.Paths.Combine(path, "IDE", "devenv.exe"); - } - - /// - /// Derives the program files sentinel for grabbing the VS installation path. - /// - /// - /// From a path like 'c:\Archivos de programa (x86)', returns 'Archivos de programa' - /// - private static string DeriveProgramFilesSentinel() - { - string path = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) - .Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) - .LastOrDefault(); - - if (!string.IsNullOrEmpty(path)) - { - // This needs to be the "real" Program Files regardless of 64bitness - int index = path.LastIndexOf("(x86)"); - if (0 <= index) - path = path.Remove(index); - return path.TrimEnd(); - } - - return "Program Files"; - } - - /// - /// Checks whether two paths are equivalent - /// - /// - /// Whether the paths are equivalent - /// - /// - /// A path - /// - /// - /// Another path - /// - private static bool PathsAreEquivalent(string aPath, string zPath) - { - if (aPath == null && zPath == null) - return true; - if (string.IsNullOrEmpty(aPath) || string.IsNullOrEmpty(zPath)) - return false; - - aPath = Path.GetFullPath(aPath); - zPath = Path.GetFullPath(zPath); - - StringComparison comparison = StringComparison.OrdinalIgnoreCase; - if (!(SolutionSynchronizationSettings.IsOSX || SolutionSynchronizationSettings.IsWindows)) - comparison = StringComparison.Ordinal; // Linux - - aPath = aPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); - zPath = zPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); - - return string.Equals(aPath, zPath, comparison); - } - - internal static bool CheckVisualStudioVersion(int major, int minor, int build) - { - int haveMinor = -1; - int haveBuild = -1; - - switch (major) - { - case 11: // Visual Studio 2012, getting it's version is different from others - { - // we'll grab version from (replace 11.0 with highest found 11.*): - // HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\DevDiv\vc\Servicing\11.0\RuntimeDebug\Version - Microsoft.Win32.RegistryKey servicing = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\DevDiv\vc\Servicing"); - if (servicing == null) return false; - foreach (string name in servicing.GetSubKeyNames()) - { - if (name.StartsWith("11.") && name.Length > 3) - try - { - int foundMinor = Convert.ToInt32(name.Substring(3)); - if (foundMinor > haveMinor) - haveMinor = foundMinor; - } - catch (System.Exception) - {} - } - if (haveMinor < 0) return false; - Microsoft.Win32.RegistryKey key = servicing.OpenSubKey(string.Format(@"11.{0}\RuntimeDebug", haveMinor)); - if (key == null) return false; - string value = key.GetValue("Version", null) as string; - if (value == null) return false; - string[] components = value.Split('.'); - if (components == null || components.Length < 3) return false; - try - { - haveBuild = Convert.ToInt32(components[2]); - } - catch (System.Exception) - { - return false; - } - } - break; - default: - return false; - } - - return haveMinor > minor || (haveMinor == minor && haveBuild >= build); - } - } -} diff --git a/Editor/Mono/TerrainEditor/Brush.cs b/Editor/Mono/TerrainEditor/Brush.cs deleted file mode 100644 index 962db8f722..0000000000 --- a/Editor/Mono/TerrainEditor/Brush.cs +++ /dev/null @@ -1,135 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -/* -GUILayout.TextureGrid number of horiz elements doesnt work -*/ - -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - internal class Brush - { - float[] m_Strength; - int m_Size; - Texture2D m_Brush; - Texture2D m_Preview; - Projector m_BrushProjector; - - internal const int kMinBrushSize = 3; - - public bool Load(Texture2D brushTex, int size) - { - // Always restore the preview texture before using the brush because: - // 1) The material of the projector might be shared among multiple brushes. - // 2) Tree painter overrides the preview texture. - if (m_BrushProjector != null && m_Preview != null) - m_BrushProjector.material.mainTexture = m_Preview; - - if (m_Brush == brushTex && size == m_Size && m_Strength != null) - return true; - - if (brushTex != null) - { - float fSize = size; - m_Size = size; - m_Strength = new float[m_Size * m_Size]; - if (m_Size > kMinBrushSize) - { - for (int y = 0; y < m_Size; y++) - { - for (int x = 0; x < m_Size; x++) - { - m_Strength[y * m_Size + x] = brushTex.GetPixelBilinear((x + 0.5F) / fSize, (y) / fSize).a; - // m_Strength[y * m_Size + x] = brushTex.GetPixelBilinear(x / fSize, y / fSize).a; - } - } - } - else - { - for (int i = 0; i < m_Strength.Length; i++) - m_Strength[i] = 1.0F; - } - - // Create preview texture - Object.DestroyImmediate(m_Preview); - m_Preview = new Texture2D(m_Size, m_Size, TextureFormat.RGBA32, false); - m_Preview.hideFlags = HideFlags.HideAndDontSave; - m_Preview.wrapMode = TextureWrapMode.Repeat; - m_Preview.filterMode = FilterMode.Point; - Color[] pixels = new Color[m_Size * m_Size]; - for (int i = 0; i < pixels.Length; i++) - pixels[i] = new Color(1, 1, 1, m_Strength[i]); - - m_Preview.SetPixels(0, 0, m_Size, m_Size, pixels, 0); - m_Preview.Apply(); - - if (m_BrushProjector == null) - CreatePreviewBrush(); - - m_BrushProjector.material.mainTexture = m_Preview; - if (GraphicsSettings.renderPipelineAsset != null) - m_BrushProjector.material.renderQueue = GraphicsSettings.renderPipelineAsset.GetTerrainBrushPassIndex(); - m_Brush = brushTex; - - return true; - } - else - { - m_Strength = new float[1]; - m_Strength[0] = 1.0F; - m_Size = 1; - return false; - } - } - - public float GetStrengthInt(int ix, int iy) - { - ix = Mathf.Clamp(ix, 0, m_Size - 1); - iy = Mathf.Clamp(iy, 0, m_Size - 1); - - float s = m_Strength[iy * m_Size + ix]; - - return s; - } - - public void Dispose() - { - if (m_BrushProjector) - { - Object.DestroyImmediate(m_BrushProjector.gameObject); - m_BrushProjector = null; - } - Object.DestroyImmediate(m_Preview); - m_Preview = null; - } - - public Projector GetPreviewProjector() - { - return m_BrushProjector; - } - - private void CreatePreviewBrush() - { - GameObject go = EditorUtility.CreateGameObjectWithHideFlags("TerrainInspectorBrushPreview", HideFlags.HideAndDontSave, typeof(Projector)); - - m_BrushProjector = go.GetComponent(typeof(Projector)) as Projector; - m_BrushProjector.enabled = false; - m_BrushProjector.nearClipPlane = -1000.0f; - m_BrushProjector.farClipPlane = 1000.0f; - m_BrushProjector.orthographic = true; - m_BrushProjector.orthographicSize = 10.0f; - m_BrushProjector.transform.Rotate(90.0f, 0.0f, 0.0f); - - Material mat = EditorGUIUtility.LoadRequired("SceneView/TerrainBrushMaterial.mat") as Material; - mat.SetTexture("_CutoutTex", (Texture2D)EditorGUIUtility.Load(EditorResourcesUtility.brushesPath + "brush_cutout.png")); - m_BrushProjector.material = mat; - } - } -} //namespace diff --git a/Editor/Mono/TerrainEditor/HeightmapFilters.cs b/Editor/Mono/TerrainEditor/HeightmapFilters.cs deleted file mode 100644 index dd180bec7f..0000000000 --- a/Editor/Mono/TerrainEditor/HeightmapFilters.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.IO; - -namespace UnityEditor -{ - internal class HeightmapFilters - { - static void WobbleStuff(float[,] heights, TerrainData terrain) - { - for (int y = 0; y < heights.GetLength(0); y++) - for (int x = 0; x < heights.GetLength(1); x++) - heights[y, x] = (heights[y, x] + 1) / 2; - } - - static void Noise(float[,] heights, TerrainData terrain) - { - for (int y = 0; y < heights.GetLength(0); y++) - for (int x = 0; x < heights.GetLength(1); x++) - heights[y, x] += Random.value * 0.01F; - } - - /* - public static void WobbleStuff () { - int w = GetActiveTerrainData ().heightmapWidth; - int h = GetActiveTerrainData ().heightmapHeight; - - // Grab terrain - float[,] heights = GetActiveTerrainData ().GetHeights(0, 0, w, h); - - // Apply filter - WobbleStuff (heights, GetActiveTerrainData ()); - - // Apply back - GetActiveTerrainData ().SetHeights(0, 0, heights); - FlushHeightmapModification (); - } - */ - public static void Smooth(float[,] heights, TerrainData terrain) - { - float[,] oldHeights = heights.Clone() as float[, ]; - int width = heights.GetLength(1); - int height = heights.GetLength(0); - for (int y = 1; y < height - 1; y++) - { - for (int x = 1; x < width - 1; x++) - { - float h = 0.0F; - h += oldHeights[y, x]; - - h += oldHeights[y, x - 1]; - h += oldHeights[y, x + 1]; - - h += oldHeights[y - 1, x]; - h += oldHeights[y + 1, x]; - - h /= 5.0F; - - heights[y, x] = h; - } - } - } - - public static void Smooth(TerrainData terrain) - { - int w = terrain.heightmapWidth; - int h = terrain.heightmapHeight; - - float[,] heights = terrain.GetHeights(0, 0, w, h); - - Smooth(heights, terrain); - - terrain.SetHeights(0, 0, heights); - } - - public static void Flatten(TerrainData terrain, float height) - { - int w = terrain.heightmapWidth; - int h = terrain.heightmapHeight; - - float[,] heights = new float[h, w]; - for (int y = 0; y < heights.GetLength(0); y++) - { - for (int x = 0; x < heights.GetLength(1); x++) - { - heights[y, x] = height; - } - } - terrain.SetHeights(0, 0, heights); - } - } -} //namespace diff --git a/Editor/Mono/TerrainEditor/TerrainEditorUtility.cs b/Editor/Mono/TerrainEditor/TerrainEditorUtility.cs deleted file mode 100644 index da6ab7e716..0000000000 --- a/Editor/Mono/TerrainEditor/TerrainEditorUtility.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal class TerrainEditorUtility - { - internal static void RemoveSplatTexture(TerrainData terrainData, int index) - { - Undo.RegisterCompleteObjectUndo(terrainData, "Remove texture"); - - int width = terrainData.alphamapWidth; - int height = terrainData.alphamapHeight; - float[,,] alphamap = terrainData.GetAlphamaps(0, 0, width, height); - int alphaCount = alphamap.GetLength(2); - - int newAlphaCount = alphaCount - 1; - float[,,] newalphamap = new float[height, width, newAlphaCount]; - - // move further alphamaps one index below - for (int y = 0; y < height; ++y) - { - for (int x = 0; x < width; ++x) - { - for (int a = 0; a < index; ++a) - newalphamap[y, x, a] = alphamap[y, x, a]; - for (int a = index + 1; a < alphaCount; ++a) - newalphamap[y, x, a - 1] = alphamap[y, x, a]; - } - } - - // normalize weights in new alpha map - for (int y = 0; y < height; ++y) - { - for (int x = 0; x < width; ++x) - { - float sum = 0.0F; - for (int a = 0; a < newAlphaCount; ++a) - sum += newalphamap[y, x, a]; - if (sum >= 0.01) - { - float multiplier = 1.0F / sum; - for (int a = 0; a < newAlphaCount; ++a) - newalphamap[y, x, a] *= multiplier; - } - else - { - // in case all weights sum to pretty much zero (e.g. - // removing splat that had 100% weight), assign - // everything to 1st splat texture (just like - // initial terrain). - for (int a = 0; a < newAlphaCount; ++a) - newalphamap[y, x, a] = (a == 0) ? 1.0f : 0.0f; - } - } - } - - // remove splat from terrain prototypes - SplatPrototype[] splats = terrainData.splatPrototypes; - SplatPrototype[] newSplats = new SplatPrototype[splats.Length - 1]; - for (int a = 0; a < index; ++a) - newSplats[a] = splats[a]; - for (int a = index + 1; a < alphaCount; ++a) - newSplats[a - 1] = splats[a]; - terrainData.splatPrototypes = newSplats; - - // set new alphamaps - terrainData.SetAlphamaps(0, 0, newalphamap); - } - - internal static void RemoveTree(Terrain terrain, int index) - { - TerrainData terrainData = terrain.terrainData; - if (terrainData == null) - return; - Undo.RegisterCompleteObjectUndo(terrainData, "Remove tree"); - terrainData.RemoveTreePrototype(index); - } - - internal static void RemoveDetail(Terrain terrain, int index) - { - TerrainData terrainData = terrain.terrainData; - if (terrainData == null) - return; - Undo.RegisterCompleteObjectUndo(terrainData, "Remove detail object"); - terrainData.RemoveDetailPrototype(index); - } - - internal static bool IsLODTreePrototype(GameObject prefab) - { - return prefab != null && prefab.GetComponent() != null; - } - } -} //namespace diff --git a/Editor/Mono/TerrainEditor/TerrainInspector.cs b/Editor/Mono/TerrainEditor/TerrainInspector.cs deleted file mode 100644 index 1db766409d..0000000000 --- a/Editor/Mono/TerrainEditor/TerrainInspector.cs +++ /dev/null @@ -1,2008 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -/* -GUILayout.TextureGrid number of horiz elements doesnt work -*/ - -using UnityEngine; -using UnityEngine.Rendering; -using UnityEditor; -using UnityEditorInternal; -using UnityEditor.AnimatedValues; -using System.Collections; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal enum TerrainTool - { - None = -1, - PaintHeight = 0, - SetHeight, - SmoothHeight, - PaintTexture, - PlaceTree, - PaintDetail, - TerrainSettings, - TerrainToolCount - } - - internal class SplatPainter - { - public int size; - public float strength; - public Brush brush; - public float target; - public TerrainData terrainData; - public TerrainTool tool; - - float ApplyBrush(float height, float brushStrength) - { - if (target > height) - { - height += brushStrength; - height = Mathf.Min(height, target); - return height; - } - else - { - height -= brushStrength; - height = Mathf.Max(height, target); - return height; - } - } - - // Normalize the alpha map at pixel x,y. - // The alpha of splatIndex will be maintained, while all others will be made to fit - void Normalize(int x, int y, int splatIndex, float[,,] alphamap) - { - float newAlpha = alphamap[y, x, splatIndex]; - float totalAlphaOthers = 0.0F; - int alphaMaps = alphamap.GetLength(2); - for (int a = 0; a < alphaMaps; a++) - { - if (a != splatIndex) - totalAlphaOthers += alphamap[y, x, a]; - } - - if (totalAlphaOthers > 0.01) - { - float adjust = (1.0F - newAlpha) / totalAlphaOthers; - for (int a = 0; a < alphaMaps; a++) - { - if (a != splatIndex) - alphamap[y, x, a] *= adjust; - } - } - else - { - for (int a = 0; a < alphaMaps; a++) - { - alphamap[y, x, a] = a == splatIndex ? 1.0F : 0.0F; - } - } - } - - public void Paint(float xCenterNormalized, float yCenterNormalized, int splatIndex) - { - if (splatIndex >= terrainData.alphamapLayers) - return; - int xCenter = Mathf.FloorToInt(xCenterNormalized * terrainData.alphamapWidth); - int yCenter = Mathf.FloorToInt(yCenterNormalized * terrainData.alphamapHeight); - - int intRadius = Mathf.RoundToInt(size) / 2; - int intFraction = Mathf.RoundToInt(size) % 2; - - int xmin = Mathf.Clamp(xCenter - intRadius, 0, terrainData.alphamapWidth - 1); - int ymin = Mathf.Clamp(yCenter - intRadius, 0, terrainData.alphamapHeight - 1); - - int xmax = Mathf.Clamp(xCenter + intRadius + intFraction, 0, terrainData.alphamapWidth); - int ymax = Mathf.Clamp(yCenter + intRadius + intFraction, 0, terrainData.alphamapHeight); - - int width = xmax - xmin; - int height = ymax - ymin; - - float[,,] alphamap = terrainData.GetAlphamaps(xmin, ymin, width, height); - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - int xBrushOffset = (xmin + x) - (xCenter - intRadius + intFraction); - int yBrushOffset = (ymin + y) - (yCenter - intRadius + intFraction); - float brushStrength = brush.GetStrengthInt(xBrushOffset, yBrushOffset); - - // Paint with brush - float newAlpha = ApplyBrush(alphamap[y, x, splatIndex], brushStrength * strength); - alphamap[y, x, splatIndex] = newAlpha; - Normalize(x, y, splatIndex, alphamap); - } - } - - terrainData.SetAlphamaps(xmin, ymin, alphamap); - } - } - - internal class DetailPainter - { - public int size; - public float opacity; - public float targetStrength; - public Brush brush; - public TerrainData terrainData; - public TerrainTool tool; - public bool randomizeDetails; - public bool clearSelectedOnly; - - public void Paint(float xCenterNormalized, float yCenterNormalized, int detailIndex) - { - if (detailIndex >= terrainData.detailPrototypes.Length) - return; - - int xCenter = Mathf.FloorToInt(xCenterNormalized * terrainData.detailWidth); - int yCenter = Mathf.FloorToInt(yCenterNormalized * terrainData.detailHeight); - - int intRadius = Mathf.RoundToInt(size) / 2; - int intFraction = Mathf.RoundToInt(size) % 2; - - int xmin = Mathf.Clamp(xCenter - intRadius, 0, terrainData.detailWidth - 1); - int ymin = Mathf.Clamp(yCenter - intRadius, 0, terrainData.detailHeight - 1); - - int xmax = Mathf.Clamp(xCenter + intRadius + intFraction, 0, terrainData.detailWidth); - int ymax = Mathf.Clamp(yCenter + intRadius + intFraction, 0, terrainData.detailHeight); - - int width = xmax - xmin; - int height = ymax - ymin; - - int[] layers = { detailIndex }; - if (targetStrength < 0.0F && !clearSelectedOnly) - layers = terrainData.GetSupportedLayers(xmin, ymin, width, height); - - for (int i = 0; i < layers.Length; i++) - { - int[,] alphamap = terrainData.GetDetailLayer(xmin, ymin, width, height, layers[i]); - - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - int xBrushOffset = (xmin + x) - (xCenter - intRadius + intFraction); - int yBrushOffset = (ymin + y) - (yCenter - intRadius + intFraction); - float opa = opacity * brush.GetStrengthInt(xBrushOffset, yBrushOffset); - - float t = targetStrength; - float targetValue = Mathf.Lerp(alphamap[y, x], t, opa); - alphamap[y, x] = Mathf.RoundToInt(targetValue - .5f + Random.value); - } - } - - terrainData.SetDetailLayer(xmin, ymin, layers[i], alphamap); - } - } - } - - internal class TreePainter - { - public static float brushSize = 40; - public static float spacing = .8f; - - public static bool lockWidthToHeight = true; - public static bool randomRotation = true; - - public static bool allowHeightVar = true; - public static bool allowWidthVar = true; - - public static float treeColorAdjustment = .4f; - public static float treeHeight = 1; - public static float treeHeightVariation = .1f; - public static float treeWidth = 1; - public static float treeWidthVariation = .1f; - - public static int selectedTree = -1; - - static Color GetTreeColor() - { - Color c = Color.white * Random.Range(1.0F, 1.0F - treeColorAdjustment); - c.a = 1; - return c; - } - - static float GetTreeHeight() - { - float v = allowHeightVar ? treeHeightVariation : 0.0f; - return treeHeight * Random.Range(1.0F - v, 1.0F + v); - } - - static float GetTreeWidth() - { - float v = allowWidthVar ? treeWidthVariation : 0.0f; - return treeWidth * Random.Range(1.0F - v, 1.0F + v); - } - - static float GetTreeRotation() - { - return randomRotation ? Random.Range(0, 2 * Mathf.PI) : 0; - } - - public static void PlaceTrees(Terrain terrain, float xBase, float yBase) - { - int prototypeCount = TerrainInspectorUtil.GetPrototypeCount(terrain.terrainData); - if (selectedTree == -1 || selectedTree >= prototypeCount) - return; - - if (!TerrainInspectorUtil.PrototypeIsRenderable(terrain.terrainData, selectedTree)) - return; - - int placedTreeCount = 0; - - // Plant a single tree first. At the location of the mouse - TreeInstance instance = new TreeInstance(); - instance.position = new Vector3(xBase, 0, yBase); - instance.color = GetTreeColor(); - instance.lightmapColor = Color.white; - instance.prototypeIndex = selectedTree; - instance.heightScale = GetTreeHeight(); - instance.widthScale = lockWidthToHeight ? instance.heightScale : GetTreeWidth(); - instance.rotation = GetTreeRotation(); - - // When painting single tree - // And just clicking we always place it, so you can do overlapping trees - - bool checkTreeDistance = Event.current.type == EventType.MouseDrag || brushSize > 1; - if (!checkTreeDistance || TerrainInspectorUtil.CheckTreeDistance(terrain.terrainData, instance.position, instance.prototypeIndex, spacing)) - { - terrain.AddTreeInstance(instance); - placedTreeCount++; - } - - Vector3 size = TerrainInspectorUtil.GetPrototypeExtent(terrain.terrainData, selectedTree); - size.y = 0; - float treeCountOneAxis = brushSize / (size.magnitude * spacing * .5f); - int treeCount = (int)((treeCountOneAxis * treeCountOneAxis) * .5f); - treeCount = Mathf.Clamp(treeCount, 0, 100); - // Plant a bunch of trees - for (int i = 1; i < treeCount && placedTreeCount < treeCount; i++) - { - Vector2 randomOffset = Random.insideUnitCircle; - randomOffset.x *= brushSize / terrain.terrainData.size.x; - randomOffset.y *= brushSize / terrain.terrainData.size.z; - Vector3 position = new Vector3(xBase + randomOffset.x, 0, yBase + randomOffset.y); - if (position.x >= 0 && position.x <= 1 && position.z >= 0 && position.z <= 1 - && TerrainInspectorUtil.CheckTreeDistance(terrain.terrainData, position, selectedTree, spacing * .5f)) - { - instance = new TreeInstance(); - - instance.position = position; - - instance.color = GetTreeColor(); - instance.lightmapColor = Color.white; - instance.prototypeIndex = selectedTree; - instance.heightScale = GetTreeHeight(); - instance.widthScale = lockWidthToHeight ? instance.heightScale : GetTreeWidth(); - instance.rotation = GetTreeRotation(); - - terrain.AddTreeInstance(instance); - placedTreeCount++; - } - } - } - - public static void RemoveTrees(Terrain terrain, float xBase, float yBase, bool clearSelectedOnly) - { - float radius = brushSize / terrain.terrainData.size.x; - terrain.RemoveTrees(new Vector2(xBase, yBase), radius, clearSelectedOnly ? selectedTree : -1); - } - - public static void MassPlaceTrees(TerrainData terrainData, int numberOfTrees, bool randomTreeColor, bool keepExistingTrees) - { - int nbPrototypes = terrainData.treePrototypes.Length; - if (nbPrototypes == 0) - { - Debug.Log("Can't place trees because no prototypes are defined"); - return; - } - - Undo.RegisterCompleteObjectUndo(terrainData, "Mass Place Trees"); - - TreeInstance[] instances = new TreeInstance[numberOfTrees]; - int i = 0; - while (i < instances.Length) - { - TreeInstance instance = new TreeInstance(); - instance.position = new Vector3(Random.value, 0, Random.value); - if (terrainData.GetSteepness(instance.position.x, instance.position.z) < 30) - { - instance.color = randomTreeColor ? GetTreeColor() : Color.white; - instance.lightmapColor = Color.white; - instance.prototypeIndex = Random.Range(0, nbPrototypes); - - instance.heightScale = GetTreeHeight(); - instance.widthScale = lockWidthToHeight ? instance.heightScale : GetTreeWidth(); - - instance.rotation = GetTreeRotation(); - - instances[i++] = instance; - } - } - - if (keepExistingTrees) - { - var existingTrees = terrainData.treeInstances; - var allTrees = new TreeInstance[existingTrees.Length + instances.Length]; - System.Array.Copy(existingTrees, 0, allTrees, 0, existingTrees.Length); - System.Array.Copy(instances, 0, allTrees, existingTrees.Length, instances.Length); - instances = allTrees; - } - - terrainData.treeInstances = instances; - terrainData.RecalculateTreePositions(); - } - } - - internal class HeightmapPainter - { - public int size; - public float strength; - public float targetHeight; - public TerrainTool tool; - public Brush brush; - public TerrainData terrainData; - - float Smooth(int x, int y) - { - float h = 0.0F; - float normalizeScale = 1.0F / terrainData.size.y; - h += terrainData.GetHeight(x, y) * normalizeScale; - h += terrainData.GetHeight(x + 1, y) * normalizeScale; - h += terrainData.GetHeight(x - 1, y) * normalizeScale; - h += terrainData.GetHeight(x + 1, y + 1) * normalizeScale * 0.75F; - h += terrainData.GetHeight(x - 1, y + 1) * normalizeScale * 0.75F; - h += terrainData.GetHeight(x + 1, y - 1) * normalizeScale * 0.75F; - h += terrainData.GetHeight(x - 1, y - 1) * normalizeScale * 0.75F; - h += terrainData.GetHeight(x, y + 1) * normalizeScale; - h += terrainData.GetHeight(x, y - 1) * normalizeScale; - h /= 8.0F; - return h; - } - - float ApplyBrush(float height, float brushStrength, int x, int y) - { - if (tool == TerrainTool.PaintHeight) - return height + brushStrength; - else if (tool == TerrainTool.SetHeight) - { - if (targetHeight > height) - { - height += brushStrength; - height = Mathf.Min(height, targetHeight); - return height; - } - else - { - height -= brushStrength; - height = Mathf.Max(height, targetHeight); - return height; - } - } - else if (tool == TerrainTool.SmoothHeight) - { - return Mathf.Lerp(height, Smooth(x, y), brushStrength); - } - else - return height; - } - - public void PaintHeight(float xCenterNormalized, float yCenterNormalized) - { - int xCenter, yCenter; - if (size % 2 == 0) - { - xCenter = Mathf.CeilToInt(xCenterNormalized * (terrainData.heightmapWidth - 1)); - yCenter = Mathf.CeilToInt(yCenterNormalized * (terrainData.heightmapHeight - 1)); - } - else - { - xCenter = Mathf.RoundToInt(xCenterNormalized * (terrainData.heightmapWidth - 1)); - yCenter = Mathf.RoundToInt(yCenterNormalized * (terrainData.heightmapHeight - 1)); - } - - int intRadius = size / 2; - int intFraction = size % 2; - - int xmin = Mathf.Clamp(xCenter - intRadius, 0, terrainData.heightmapWidth - 1); - int ymin = Mathf.Clamp(yCenter - intRadius, 0, terrainData.heightmapHeight - 1); - - int xmax = Mathf.Clamp(xCenter + intRadius + intFraction, 0, terrainData.heightmapWidth); - int ymax = Mathf.Clamp(yCenter + intRadius + intFraction, 0, terrainData.heightmapHeight); - - int width = xmax - xmin; - int height = ymax - ymin; - - float[,] heights = terrainData.GetHeights(xmin, ymin, width, height); - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - int xBrushOffset = (xmin + x) - (xCenter - intRadius); - int yBrushOffset = (ymin + y) - (yCenter - intRadius); - float brushStrength = brush.GetStrengthInt(xBrushOffset, yBrushOffset); - //Debug.Log(xBrushOffset + ", " + yBrushOffset + "=" + brushStrength); - float value = heights[y, x]; - value = ApplyBrush(value, brushStrength * strength, x + xmin, y + ymin); - heights[y, x] = value; - } - } - - terrainData.SetHeightsDelayLOD(xmin, ymin, heights); - } - } - - [CustomEditor(typeof(Terrain))] - internal class TerrainInspector : Editor - { - class Styles - { - public GUIStyle gridList = "GridList"; - public GUIStyle gridListText = "GridListText"; - public GUIStyle largeSquare = "Button"; - public GUIStyle command = "Command"; - public Texture settingsIcon = EditorGUIUtility.IconContent("SettingsIcon").image; - // List of tools supported by the editor - public GUIContent[] toolIcons = - { - EditorGUIUtility.TrIconContent("TerrainInspector.TerrainToolRaise", "Raise/Lower Terrain)"), - EditorGUIUtility.TrIconContent("TerrainInspector.TerrainToolSetHeight", "Paint Height"), - EditorGUIUtility.TrIconContent("TerrainInspector.TerrainToolSmoothHeight", "Smooth Height"), - EditorGUIUtility.TrIconContent("TerrainInspector.TerrainToolSplat", "Paint Texture"), - EditorGUIUtility.TrIconContent("TerrainInspector.TerrainToolTrees", "Paint Trees"), - EditorGUIUtility.TrIconContent("TerrainInspector.TerrainToolPlants", "Paint Details"), - EditorGUIUtility.TrIconContent("TerrainInspector.TerrainToolSettings", "Terrain Settings") - }; - - public GUIContent[] toolNames = - { - EditorGUIUtility.TrTextContent("Raise/Lower Terrain", "Click to raise.\n\nHold shift and click to lower."), - EditorGUIUtility.TrTextContent("Paint Height", "Click to paint height.\n\nHold shift and click to sample target height."), - EditorGUIUtility.TrTextContent("Smooth Height", "Click to average out height."), - EditorGUIUtility.TrTextContent("Paint Texture", "Select a texture below, then click to paint."), - EditorGUIUtility.TrTextContent("Paint Trees", "Click to paint trees.\n\nHold shift and click to erase trees.\n\nHold Ctrl and click to erase only trees of the selected type."), - EditorGUIUtility.TrTextContent("Paint Details", "Click to paint details.\n\nHold shift and click to erase details.\n\nHold Ctrl and click to erase only details of the selected type."), - EditorGUIUtility.TrTextContent("Terrain Settings") - }; - - public GUIContent brushSize = EditorGUIUtility.TrTextContent("Brush Size", "Size of the brush used to paint."); - public GUIContent opacity = EditorGUIUtility.TrTextContent("Opacity", "Strength of the applied effect."); - public GUIContent targetStrength = EditorGUIUtility.TrTextContent("Target Strength", "Maximum opacity you can reach by painting continuously."); - public GUIContent settings = EditorGUIUtility.TrTextContent("Settings"); - public GUIContent brushes = EditorGUIUtility.TrTextContent("Brushes"); - - public GUIContent mismatchedTerrainData = EditorGUIUtility.TrTextContentWithIcon( - "The TerrainData used by the TerrainCollider component is different from this terrain. Would you like to assign the same TerrainData to the TerrainCollider component?", - "console.warnicon"); - - public GUIContent assign = EditorGUIUtility.TrTextContent("Assign"); - - // Textures - public GUIContent textures = EditorGUIUtility.TrTextContent("Textures"); - public GUIContent editTextures = EditorGUIUtility.TrTextContent("Edit Textures..."); - - // Trees - public GUIContent trees = EditorGUIUtility.TrTextContent("Trees"); - public GUIContent noTrees = EditorGUIUtility.TrTextContent("No Trees defined", "Use edit button below to add new tree types."); - public GUIContent editTrees = EditorGUIUtility.TrTextContent("Edit Trees...", "Add/remove tree types."); - public GUIContent treeDensity = EditorGUIUtility.TrTextContent("Tree Density", "How dense trees are you painting"); - public GUIContent treeHeight = EditorGUIUtility.TrTextContent("Tree Height", "Height of the planted trees"); - public GUIContent treeHeightRandomLabel = EditorGUIUtility.TrTextContent("Random?", "Enable random variation in tree height (variation)"); - public GUIContent treeHeightRandomToggle = EditorGUIUtility.TrTextContent("", "Enable random variation in tree height (variation)"); - public GUIContent lockWidth = EditorGUIUtility.TrTextContent("Lock Width to Height", "Let the tree width be the same with height"); - public GUIContent treeWidth = EditorGUIUtility.TrTextContent("Tree Width", "Width of the planted trees"); - public GUIContent treeWidthRandomLabel = EditorGUIUtility.TrTextContent("Random?", "Enable random variation in tree width (variation)"); - public GUIContent treeWidthRandomToggle = EditorGUIUtility.TrTextContent("", "Enable random variation in tree width (variation)"); - public GUIContent treeColorVar = EditorGUIUtility.TrTextContent("Color Variation", "Amount of random shading applied to trees"); - public GUIContent treeRotation = EditorGUIUtility.TrTextContent("Random Tree Rotation", "Enable?"); - public GUIContent massPlaceTrees = EditorGUIUtility.TrTextContent("Mass Place Trees", "The Mass Place Trees button is a very useful way to create an overall covering of trees without painting over the whole landscape. Following a mass placement, you can still use painting to add or remove trees to create denser or sparser areas."); - public GUIContent treeLightmapStatic = EditorGUIUtility.TrTextContent("Tree Lightmap Static", "The state of the Lightmap Static flag for the tree prefab root GameObject. The flag can be changed on the prefab. When disabled, this tree will not be visible to the lightmapper. When enabled, any child GameObjects which also have the static flag enabled, will be present in lightmap calculations. Regardless of the Static flag, each tree instance receives its own light probe and no lightmap texels."); - - // Details - public GUIContent details = EditorGUIUtility.TrTextContent("Details"); - public GUIContent editDetails = EditorGUIUtility.TrTextContent("Edit Details...", "Add/remove detail meshes"); - public GUIContent detailTargetStrength = EditorGUIUtility.TrTextContent("Target Strength", "Target amount"); - - // Heightmaps - public GUIContent height = EditorGUIUtility.TrTextContent("Height", "You can set the Height property manually or you can shift-click on the terrain to sample the height at the mouse position (rather like the \"eyedropper\" tool in an image editor)."); - - public GUIContent heightmap = EditorGUIUtility.TrTextContent("Heightmap"); - public GUIContent importRaw = EditorGUIUtility.TrTextContent("Import Raw...", "The Import Raw button allows you to set the terrain's heightmap from an image file in the RAW grayscale format. RAW format can be generated by third party terrain editing tools (such as Bryce) and can also be opened, edited and saved by Photoshop. This allows for sophisticated generation and editing of terrains outside Unity."); - public GUIContent exportRaw = EditorGUIUtility.TrTextContent("Export Raw...", "The Export Raw button allows you to save the terrain's heightmap to an image file in the RAW grayscale format. RAW format can be generated by third party terrain editing tools (such as Bryce) and can also be opened, edited and saved by Photoshop. This allows for sophisticated generation and editing of terrains outside Unity."); - public GUIContent flatten = EditorGUIUtility.TrTextContent("Flatten", "The Flatten button levels the whole terrain to the chosen height."); - - public GUIContent bakeLightProbesForTrees = EditorGUIUtility.TrTextContent("Bake Light Probes For Trees", "If the option is enabled, Unity will create internal light probes at the position of each tree (these probes are internal and will not affect other renderers in the scene) and apply them to tree renderers for lighting. Otherwise trees are still affected by LightProbeGroups. The option is only effective for trees that have LightProbe enabled on their prototype prefab."); - public GUIContent refresh = EditorGUIUtility.TrTextContent("Refresh", "When you save a tree asset from the modelling app, you will need to click the Refresh button (shown in the inspector when the tree painting tool is selected) in order to see the updated trees on your terrain."); - - // Settings - public GUIContent drawTerrain = EditorGUIUtility.TrTextContent("Draw", "Toggle the rendering of terrain"); - public GUIContent pixelError = EditorGUIUtility.TrTextContent("Pixel Error", "The accuracy of the mapping between the terrain maps (heightmap, textures, etc) and the generated terrain; higher values indicate lower accuracy but lower rendering overhead."); - public GUIContent baseMapDist = EditorGUIUtility.TrTextContent("Base Map Dist.", "The maximum distance at which terrain textures will be displayed at full resolution. Beyond this distance, a lower resolution composite image will be used for efficiency."); - public GUIContent castShadows = EditorGUIUtility.TrTextContent("Cast Shadows", "Does the terrain cast shadows?"); - public GUIContent material = EditorGUIUtility.TrTextContent("Material", "The material used to render the terrain. This will affect how the color channels of a terrain texture are interpreted."); - public GUIContent reflectionProbes = EditorGUIUtility.TrTextContent("Reflection Probes", "How reflection probes are used on terrain. Only effective when using built-in standard material or a custom material which supports rendering with reflection."); - public GUIContent thickness = EditorGUIUtility.TrTextContent("Thickness", "How much the terrain collision volume should extend along the negative Y-axis. Objects are considered colliding with the terrain from the surface to a depth equal to the thickness. This helps prevent high-speed moving objects from penetrating into the terrain without using expensive continuous collision detection."); - - public GUIContent drawTrees = EditorGUIUtility.TrTextContent("Draw", "Should trees, grass and details be drawn?"); - public GUIContent detailObjectDistance = EditorGUIUtility.TrTextContent("Detail Distance", "The distance (from camera) beyond which details will be culled."); - public GUIContent collectDetailPatches = EditorGUIUtility.TrTextContent("Collect Detail Patches", "Should detail patches in the Terrain be removed from memory when not visible?"); - public GUIContent detailObjectDensity = EditorGUIUtility.TrTextContent("Detail Density", "The number of detail/grass objects in a given unit of area. The value can be set lower to reduce rendering overhead."); - public GUIContent treeDistance = EditorGUIUtility.TrTextContent("Tree Distance", "The distance (from camera) beyond which trees will be culled."); - public GUIContent treeBillboardDistance = EditorGUIUtility.TrTextContent("Billboard Start", "The distance (from camera) at which 3D tree objects will be replaced by billboard images."); - public GUIContent treeCrossFadeLength = EditorGUIUtility.TrTextContent("Fade Length", "Distance over which trees will transition between 3D objects and billboards."); - public GUIContent treeMaximumFullLODCount = EditorGUIUtility.TrTextContent("Max Mesh Trees", "The maximum number of visible trees that will be represented as solid 3D meshes. Beyond this limit, trees will be replaced with billboards."); - - public GUIContent wavingGrassStrength = EditorGUIUtility.TrTextContent("Speed", "The speed of the wind as it blows grass."); - public GUIContent wavingGrassSpeed = EditorGUIUtility.TrTextContent("Size", "The size of the \"ripples\" on grassy areas as the wind blows over them."); - public GUIContent wavingGrassAmount = EditorGUIUtility.TrTextContent("Bending", "The degree to which grass objects are bent over by the wind."); - public GUIContent wavingGrassTint = EditorGUIUtility.TrTextContent("Grass Tint", "Overall color tint applied to grass objects."); - } - static Styles styles; - - private const string kDisplayLightingKey = "TerrainInspector.Lighting.ShowSettings"; - - static float PercentSlider(GUIContent content, float valueInPercent, float minVal, float maxVal) - { - EditorGUI.BeginChangeCheck(); - float v = EditorGUILayout.Slider(content, Mathf.Round(valueInPercent * 100f), minVal * 100f, maxVal * 100f); - - if (EditorGUI.EndChangeCheck()) - { - return v / 100f; - } - return valueInPercent; - } - - internal static PrefKey[] s_ToolKeys = - { - new PrefKey("Terrain/Raise Height", "f1"), - new PrefKey("Terrain/Set Height", "f2"), - new PrefKey("Terrain/Smooth Height", "f3"), - new PrefKey("Terrain/Texture Paint", "f4"), - new PrefKey("Terrain/Tree Brush", "f5"), - new PrefKey("Terrain/Detail Brush", "f6") - }; - internal static PrefKey s_PrevBrush = new PrefKey("Terrain/Previous Brush", ","); - internal static PrefKey s_NextBrush = new PrefKey("Terrain/Next Brush", "."); - internal static PrefKey s_PrevTexture = new PrefKey("Terrain/Previous Detail", "#,"); - internal static PrefKey s_NextTexture = new PrefKey("Terrain/Next Detail", "#."); - // Source terrain - Terrain m_Terrain; - TerrainCollider m_TerrainCollider; - - Texture2D[] m_SplatIcons = null; - GUIContent[] m_TreeContents = null; - GUIContent[] m_DetailContents = null; - - float m_TargetHeight; - float m_Strength; - int m_Size; - float m_SplatAlpha; - float m_DetailOpacity; - float m_DetailStrength; - - int m_SelectedBrush = 0; - int m_SelectedSplat = 0; - int m_SelectedDetail = 0; - - const float kHeightmapBrushScale = 0.01F; - const float kMinBrushStrength = (1.1F / ushort.MaxValue) / kHeightmapBrushScale; - Brush m_CachedBrush; - - // TODO: Make an option for letting the user add textures to the brush list. - static Texture2D[] s_BrushTextures = null; - - static int s_TerrainEditorHash = "TerrainEditor".GetHashCode(); - - // The instance ID of the active inspector. - // It's defined as the last inspector that had one of its terrain tools selected. - // If a terrain inspector is the only one when created, it also becomes active. - static int s_activeTerrainInspector = 0; - - List m_BlendInfoList = new List(); - - private AnimBool m_ShowBuiltinSpecularSettings = new AnimBool(); - private AnimBool m_ShowCustomMaterialSettings = new AnimBool(); - private AnimBool m_ShowReflectionProbesGUI = new AnimBool(); - - bool m_LODTreePrototypePresent = false; - - private LightingSettingsInspector m_Lighting; - - void CheckKeys() - { - // If there is an active inspector, hot keys are exclusive to it. - if (s_activeTerrainInspector != 0 && s_activeTerrainInspector != GetInstanceID()) - return; - - for (int i = 0; i < s_ToolKeys.Length; i++) - { - if (s_ToolKeys[i].activated) - { - selectedTool = (TerrainTool)i; - Repaint(); - Event.current.Use(); - } - } - - if (s_PrevBrush.activated) - { - m_SelectedBrush--; - if (m_SelectedBrush < 0) - m_SelectedBrush = s_BrushTextures.Length - 1; - Repaint(); - Event.current.Use(); - } - - if (s_NextBrush.activated) - { - m_SelectedBrush++; - if (m_SelectedBrush >= s_BrushTextures.Length) - m_SelectedBrush = 0; - Repaint(); - Event.current.Use(); - } - int delta = 0; - if (s_NextTexture.activated) - delta = 1; - if (s_PrevTexture.activated) - delta = -1; - - if (delta != 0) - { - switch (selectedTool) - { - case TerrainTool.PaintDetail: - m_SelectedDetail = (int)Mathf.Repeat(m_SelectedDetail + delta, m_Terrain.terrainData.detailPrototypes.Length); - Event.current.Use(); - Repaint(); - break; - case TerrainTool.PlaceTree: - if (TreePainter.selectedTree >= 0) - TreePainter.selectedTree = (int)Mathf.Repeat(TreePainter.selectedTree + delta, m_TreeContents.Length); - else if (delta == -1 && m_TreeContents.Length > 0) - TreePainter.selectedTree = m_TreeContents.Length - 1; - else if (delta == 1 && m_TreeContents.Length > 0) - TreePainter.selectedTree = 0; - Event.current.Use(); - Repaint(); - break; - case TerrainTool.PaintTexture: - m_SelectedSplat = (int)Mathf.Repeat(m_SelectedSplat + delta, m_Terrain.terrainData.splatPrototypes.Length); - Event.current.Use(); - Repaint(); - break; - } - } - } - - void LoadBrushIcons() - { - // Load the textures; - ArrayList arr = new ArrayList(); - int idx = 1; - Texture t = null; - - // Load brushes from editor resources - do - { - t = (Texture2D)EditorGUIUtility.Load(EditorResourcesUtility.brushesPath + "builtin_brush_" + idx + ".png"); - if (t) arr.Add(t); - idx++; - } - while (t); - - // Load user created brushes from the Assets/Gizmos folder - idx = 0; - do - { - t = EditorGUIUtility.FindTexture("brush_" + idx + ".png"); - if (t) arr.Add(t); - idx++; - } - while (t); - - s_BrushTextures = arr.ToArray(typeof(Texture2D)) as Texture2D[]; - } - - void Initialize() - { - m_Terrain = target as Terrain; - // Load brushes - if (s_BrushTextures == null) - LoadBrushIcons(); - } - - void LoadInspectorSettings() - { - m_TargetHeight = EditorPrefs.GetFloat("TerrainBrushTargetHeight", 0.2f); - m_Strength = EditorPrefs.GetFloat("TerrainBrushStrength", 0.5f); - m_Size = EditorPrefs.GetInt("TerrainBrushSize", 25); - m_SplatAlpha = EditorPrefs.GetFloat("TerrainBrushSplatAlpha", 1.0f); - m_DetailOpacity = EditorPrefs.GetFloat("TerrainDetailOpacity", 1.0f); - m_DetailStrength = EditorPrefs.GetFloat("TerrainDetailStrength", 0.8f); - - m_SelectedBrush = EditorPrefs.GetInt("TerrainSelectedBrush", 0); - m_SelectedSplat = EditorPrefs.GetInt("TerrainSelectedSplat", 0); - m_SelectedDetail = EditorPrefs.GetInt("TerrainSelectedDetail", 0); - } - - void SaveInspectorSettings() - { - EditorPrefs.SetInt("TerrainSelectedDetail", m_SelectedDetail); - EditorPrefs.SetInt("TerrainSelectedSplat", m_SelectedSplat); - EditorPrefs.SetInt("TerrainSelectedBrush", m_SelectedBrush); - - EditorPrefs.SetFloat("TerrainDetailStrength", m_DetailStrength); - EditorPrefs.SetFloat("TerrainDetailOpacity", m_DetailOpacity); - EditorPrefs.SetFloat("TerrainBrushSplatAlpha", m_SplatAlpha); - EditorPrefs.SetInt("TerrainBrushSize", m_Size); - EditorPrefs.SetFloat("TerrainBrushStrength", m_Strength); - EditorPrefs.SetFloat("TerrainBrushTargetHeight", m_TargetHeight); - } - - public void OnEnable() - { - // Acquire active inspector ownership if there is no other inspector active. - if (s_activeTerrainInspector == 0) - s_activeTerrainInspector = GetInstanceID(); - - m_ShowBuiltinSpecularSettings.valueChanged.AddListener(Repaint); - m_ShowCustomMaterialSettings.valueChanged.AddListener(Repaint); - m_ShowReflectionProbesGUI.valueChanged.AddListener(Repaint); - - var terrain = target as Terrain; - if (terrain != null) - { - m_ShowBuiltinSpecularSettings.value = terrain.materialType == Terrain.MaterialType.BuiltInLegacySpecular; - m_ShowCustomMaterialSettings.value = terrain.materialType == Terrain.MaterialType.Custom; - m_ShowReflectionProbesGUI.value = terrain.materialType == Terrain.MaterialType.BuiltInStandard || terrain.materialType == Terrain.MaterialType.Custom; - } - - LoadInspectorSettings(); - - SceneView.onPreSceneGUIDelegate += OnPreSceneGUICallback; - SceneView.onSceneGUIDelegate += OnSceneGUICallback; - - InitializeLightingFields(); - } - - public void OnDisable() - { - SceneView.onSceneGUIDelegate -= OnSceneGUICallback; - SceneView.onPreSceneGUIDelegate -= OnPreSceneGUICallback; - - SaveInspectorSettings(); - - m_ShowReflectionProbesGUI.valueChanged.RemoveListener(Repaint); - m_ShowCustomMaterialSettings.valueChanged.RemoveListener(Repaint); - m_ShowBuiltinSpecularSettings.valueChanged.RemoveListener(Repaint); - - if (m_CachedBrush != null) - m_CachedBrush.Dispose(); - - // Return active inspector ownership. - if (s_activeTerrainInspector == GetInstanceID()) - s_activeTerrainInspector = 0; - } - - SavedInt m_SelectedTool = new SavedInt("TerrainSelectedTool", (int)TerrainTool.PaintHeight); - TerrainTool selectedTool - { - get - { - if (Tools.current == Tool.None && GetInstanceID() == s_activeTerrainInspector) - return (TerrainTool)m_SelectedTool.value; - return TerrainTool.None; - } - set - { - if (value != TerrainTool.None) - Tools.current = Tool.None; - m_SelectedTool.value = (int)value; - s_activeTerrainInspector = GetInstanceID(); - } - } - - public void MenuButton(GUIContent title, string menuName, int userData) - { - GUIContent t = new GUIContent(title.text, styles.settingsIcon, title.tooltip); - Rect r = GUILayoutUtility.GetRect(t, styles.largeSquare); - if (GUI.Button(r, t, styles.largeSquare)) - { - MenuCommand context = new MenuCommand(m_Terrain, userData); - EditorUtility.DisplayPopupMenu(new Rect(r.x, r.y, 0, 0), menuName, context); - } - } - - public static int AspectSelectionGrid(int selected, Texture[] textures, int approxSize, GUIStyle style, string emptyString, out bool doubleClick) - { - GUILayout.BeginVertical("box", GUILayout.MinHeight(10)); - int retval = 0; - - doubleClick = false; - - if (textures.Length != 0) - { - float columns = (EditorGUIUtility.currentViewWidth - 20) / approxSize; - int rows = (int)Mathf.Ceil(textures.Length / columns); - Rect r = GUILayoutUtility.GetAspectRect(columns / rows); - - Event evt = Event.current; - if (evt.type == EventType.MouseDown && evt.clickCount == 2 && r.Contains(evt.mousePosition)) - { - doubleClick = true; - evt.Use(); - } - - retval = GUI.SelectionGrid(r, System.Math.Min(selected, textures.Length - 1), textures, Mathf.RoundToInt(EditorGUIUtility.currentViewWidth - 20) / approxSize, style); - } - else - { - GUILayout.Label(emptyString); - } - - GUILayout.EndVertical(); - return retval; - } - - static Rect GetBrushAspectRect(int elementCount, int approxSize, int extraLineHeight, out int xCount) - { - xCount = (int)Mathf.Ceil((EditorGUIUtility.currentViewWidth - 20) / approxSize); - int yCount = elementCount / xCount; - if (elementCount % xCount != 0) - yCount++; - Rect r1 = GUILayoutUtility.GetAspectRect(xCount / (float)yCount); - Rect r2 = GUILayoutUtility.GetRect(10, extraLineHeight * yCount); - r1.height += r2.height; - return r1; - } - - public static int AspectSelectionGridImageAndText(int selected, GUIContent[] textures, int approxSize, GUIStyle style, string emptyString, out bool doubleClick) - { - EditorGUILayout.BeginVertical(GUIContent.none, EditorStyles.helpBox, GUILayout.MinHeight(10)); - int retval = 0; - - doubleClick = false; - - if (textures.Length != 0) - { - int xCount = 0; - Rect rect = GetBrushAspectRect(textures.Length, approxSize, 12, out xCount); - - Event evt = Event.current; - if (evt.type == EventType.MouseDown && evt.clickCount == 2 && rect.Contains(evt.mousePosition)) - { - doubleClick = true; - evt.Use(); - } - retval = GUI.SelectionGrid(rect, System.Math.Min(selected, textures.Length - 1), textures, xCount, style); - } - else - { - GUILayout.Label(emptyString); - } - - GUILayout.EndVertical(); - return retval; - } - - void LoadSplatIcons() - { - // Use asset preview for splat textures so that alpha channel is not shown (used as Smoothness) - SplatPrototype[] splats = m_Terrain.terrainData.splatPrototypes; - - m_SplatIcons = new Texture2D[splats.Length]; - for (int i = 0; i < m_SplatIcons.Length; ++i) - m_SplatIcons[i] = AssetPreview.GetAssetPreview(splats[i].texture) ?? splats[i].texture; - } - - void LoadTreeIcons() - { - // Locate the proto types asset preview textures - TreePrototype[] trees = m_Terrain.terrainData.treePrototypes; - - m_TreeContents = new GUIContent[trees.Length]; - for (int i = 0; i < m_TreeContents.Length; i++) - { - m_TreeContents[i] = new GUIContent(); - Texture tex = AssetPreview.GetAssetPreview(trees[i].prefab); - if (tex != null) - m_TreeContents[i].image = tex; - - if (trees[i].prefab != null) - { - m_TreeContents[i].text = trees[i].prefab.name; - m_TreeContents[i].tooltip = m_TreeContents[i].text; - } - else - m_TreeContents[i].text = "Missing"; - } - } - - void LoadDetailIcons() - { - // Locate the proto types asset preview textures - DetailPrototype[] prototypes = m_Terrain.terrainData.detailPrototypes; - m_DetailContents = new GUIContent[prototypes.Length]; - for (int i = 0; i < m_DetailContents.Length; i++) - { - m_DetailContents[i] = new GUIContent(); - - if (prototypes[i].usePrototypeMesh) - { - Texture tex = AssetPreview.GetAssetPreview(prototypes[i].prototype); - if (tex != null) - m_DetailContents[i].image = tex; - - if (prototypes[i].prototype != null) - m_DetailContents[i].text = prototypes[i].prototype.name; - else - m_DetailContents[i].text = "Missing"; - } - else - { - Texture tex = prototypes[i].prototypeTexture; - if (tex != null) - m_DetailContents[i].image = tex; - if (tex != null) - m_DetailContents[i].text = tex.name; - else - m_DetailContents[i].text = "Missing"; - } - } - } - - public void ShowTrees() - { - LoadTreeIcons(); - - // Tree picker - GUI.changed = false; - - ShowUpgradeTreePrototypeScaleUI(); - - GUILayout.Label(styles.trees, EditorStyles.boldLabel); - bool doubleClick; - TreePainter.selectedTree = AspectSelectionGridImageAndText(TreePainter.selectedTree, m_TreeContents, 64, styles.gridListText, "No trees defined", out doubleClick); - - if (TreePainter.selectedTree >= m_TreeContents.Length) - TreePainter.selectedTree = -1; - - if (doubleClick) - { - TerrainTreeContextMenus.EditTree(new MenuCommand(m_Terrain, TreePainter.selectedTree)); - GUIUtility.ExitGUI(); - } - - GUILayout.BeginHorizontal(); - ShowMassPlaceTrees(); - GUILayout.FlexibleSpace(); - MenuButton(styles.editTrees, "CONTEXT/TerrainEngineTrees", TreePainter.selectedTree); - ShowRefreshPrototypes(); - GUILayout.EndHorizontal(); - - if (TreePainter.selectedTree == -1) - return; - - GUILayout.Label(styles.settings, EditorStyles.boldLabel); - // Placement distance - TreePainter.brushSize = EditorGUILayout.Slider(styles.brushSize, TreePainter.brushSize, 1, 100); // former string formatting: "" - float oldDens = (3.3f - TreePainter.spacing) / 3f; - float newDens = PercentSlider(styles.treeDensity, oldDens, .1f, 1); - // Only set spacing when value actually changes. Otherwise - // it will lose precision because we're constantly doing math - // back and forth with it. - if (newDens != oldDens) - TreePainter.spacing = (1.1f - newDens) * 3f; - - GUILayout.Space(5); - - GUILayout.BeginHorizontal(); - GUILayout.Label(styles.treeHeight, GUILayout.Width(EditorGUIUtility.labelWidth - 6)); - GUILayout.Label(styles.treeHeightRandomLabel, GUILayout.ExpandWidth(false)); - TreePainter.allowHeightVar = GUILayout.Toggle(TreePainter.allowHeightVar, styles.treeHeightRandomToggle, GUILayout.ExpandWidth(false)); - if (TreePainter.allowHeightVar) - { - EditorGUI.BeginChangeCheck(); - float min = TreePainter.treeHeight * (1.0f - TreePainter.treeHeightVariation); - float max = TreePainter.treeHeight * (1.0f + TreePainter.treeHeightVariation); - EditorGUILayout.MinMaxSlider(ref min, ref max, 0.01f, 2.0f); - if (EditorGUI.EndChangeCheck()) - { - TreePainter.treeHeight = (min + max) * 0.5f; - TreePainter.treeHeightVariation = (max - min) / (min + max); - } - } - else - { - TreePainter.treeHeight = EditorGUILayout.Slider(TreePainter.treeHeight, 0.01f, 2.0f); - TreePainter.treeHeightVariation = 0.0f; - } - GUILayout.EndHorizontal(); - - GUILayout.Space(5); - - TreePainter.lockWidthToHeight = EditorGUILayout.Toggle(styles.lockWidth, TreePainter.lockWidthToHeight); - if (TreePainter.lockWidthToHeight) - { - TreePainter.treeWidth = TreePainter.treeHeight; - TreePainter.treeWidthVariation = TreePainter.treeHeightVariation; - TreePainter.allowWidthVar = TreePainter.allowHeightVar; - } - - GUILayout.Space(5); - - using (new EditorGUI.DisabledScope(TreePainter.lockWidthToHeight)) - { - GUILayout.BeginHorizontal(); - GUILayout.Label(styles.treeWidth, GUILayout.Width(EditorGUIUtility.labelWidth - 6)); - GUILayout.Label(styles.treeWidthRandomLabel, GUILayout.ExpandWidth(false)); - TreePainter.allowWidthVar = GUILayout.Toggle(TreePainter.allowWidthVar, styles.treeWidthRandomToggle, GUILayout.ExpandWidth(false)); - if (TreePainter.allowWidthVar) - { - EditorGUI.BeginChangeCheck(); - float min = TreePainter.treeWidth * (1.0f - TreePainter.treeWidthVariation); - float max = TreePainter.treeWidth * (1.0f + TreePainter.treeWidthVariation); - EditorGUILayout.MinMaxSlider(ref min, ref max, 0.01f, 2.0f); - if (EditorGUI.EndChangeCheck()) - { - TreePainter.treeWidth = (min + max) * 0.5f; - TreePainter.treeWidthVariation = (max - min) / (min + max); - } - } - else - { - TreePainter.treeWidth = EditorGUILayout.Slider(TreePainter.treeWidth, 0.01f, 2.0f); - TreePainter.treeWidthVariation = 0.0f; - } - GUILayout.EndHorizontal(); - } - - GUILayout.Space(5); - - if (TerrainEditorUtility.IsLODTreePrototype(m_Terrain.terrainData.treePrototypes[TreePainter.selectedTree].m_Prefab)) - TreePainter.randomRotation = EditorGUILayout.Toggle(styles.treeRotation, TreePainter.randomRotation); - else - TreePainter.treeColorAdjustment = EditorGUILayout.Slider(styles.treeColorVar, TreePainter.treeColorAdjustment, 0, 1); - - GameObject prefab = m_Terrain.terrainData.treePrototypes[TreePainter.selectedTree].m_Prefab; - if (prefab != null) - { - StaticEditorFlags staticEditorFlags = GameObjectUtility.GetStaticEditorFlags(prefab); - bool lightmapStatic = (staticEditorFlags & StaticEditorFlags.LightmapStatic) != 0; - using (new EditorGUI.DisabledScope(true)) // Always disabled, because we don't want to edit the prefab. - lightmapStatic = EditorGUILayout.Toggle(styles.treeLightmapStatic, lightmapStatic); - } - } - - public void ShowDetails() - { - LoadDetailIcons(); - ShowBrushes(); - // Brush size - - // Detail picker - GUI.changed = false; - - GUILayout.Label(styles.details, EditorStyles.boldLabel); - bool doubleClick; - m_SelectedDetail = AspectSelectionGridImageAndText(m_SelectedDetail, m_DetailContents, 64, styles.gridListText, "No Detail Objects defined", out doubleClick); - if (doubleClick) - { - TerrainDetailContextMenus.EditDetail(new MenuCommand(m_Terrain, m_SelectedDetail)); - GUIUtility.ExitGUI(); - } - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - MenuButton(styles.editDetails, "CONTEXT/TerrainEngineDetails", m_SelectedDetail); - ShowRefreshPrototypes(); - GUILayout.EndHorizontal(); - - GUILayout.Label(styles.settings, EditorStyles.boldLabel); - - // Brush size - m_Size = Mathf.RoundToInt(EditorGUILayout.Slider(styles.brushSize, m_Size, 1, 100)); // former string formatting: "" - m_DetailOpacity = EditorGUILayout.Slider(styles.opacity, m_DetailOpacity, 0, 1); // former string formatting: "%" - - // Strength - m_DetailStrength = EditorGUILayout.Slider(styles.detailTargetStrength, m_DetailStrength, 0, 1); // former string formatting: "%" - m_DetailStrength = Mathf.Round(m_DetailStrength * 16.0f) / 16.0f; - } - - public void ShowSettings() - { - TerrainData terrainData = m_Terrain.terrainData; - - EditorGUI.BeginChangeCheck(); - - GUILayout.Label(L10n.Tr("Base Terrain"), EditorStyles.boldLabel); - m_Terrain.drawHeightmap = EditorGUILayout.Toggle(styles.drawTerrain, m_Terrain.drawHeightmap); - m_Terrain.heightmapPixelError = EditorGUILayout.Slider(styles.pixelError, m_Terrain.heightmapPixelError, 1, 200); // former string formatting: "" - m_Terrain.basemapDistance = EditorGUILayout.Slider(styles.baseMapDist, m_Terrain.basemapDistance, 0, 2000); // former string formatting: "" - m_Terrain.castShadows = EditorGUILayout.Toggle(styles.castShadows, m_Terrain.castShadows); - - m_Terrain.materialType = (Terrain.MaterialType)EditorGUILayout.EnumPopup(styles.material, m_Terrain.materialType); - - // Make sure we don't reference any custom material if we are to use a built-in shader. - if (m_Terrain.materialType != Terrain.MaterialType.Custom) - m_Terrain.materialTemplate = null; - - m_ShowBuiltinSpecularSettings.target = m_Terrain.materialType == Terrain.MaterialType.BuiltInLegacySpecular; - m_ShowCustomMaterialSettings.target = m_Terrain.materialType == Terrain.MaterialType.Custom; - m_ShowReflectionProbesGUI.target = m_Terrain.materialType == Terrain.MaterialType.BuiltInStandard || m_Terrain.materialType == Terrain.MaterialType.Custom; - - if (EditorGUILayout.BeginFadeGroup(m_ShowBuiltinSpecularSettings.faded)) - { - EditorGUI.indentLevel++; - m_Terrain.legacySpecular = EditorGUILayout.ColorField("Specular Color", m_Terrain.legacySpecular); - m_Terrain.legacyShininess = EditorGUILayout.Slider("Shininess", m_Terrain.legacyShininess, 0.03f, 1.0f); - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - - if (EditorGUILayout.BeginFadeGroup(m_ShowCustomMaterialSettings.faded)) - { - EditorGUI.indentLevel++; - m_Terrain.materialTemplate = EditorGUILayout.ObjectField("Custom Material", m_Terrain.materialTemplate, typeof(Material), false) as Material; - - // Warn if shader needs tangent basis - if (m_Terrain.materialTemplate != null) - { - Shader s = m_Terrain.materialTemplate.shader; - if (ShaderUtil.HasTangentChannel(s)) - { - GUIContent c = EditorGUIUtility.TrTextContent("Can't use materials with shaders which need tangent geometry on terrain, use shaders in Nature/Terrain instead."); - EditorGUILayout.HelpBox(c.text, MessageType.Warning, false); - } - } - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); - - if (EditorGUILayout.BeginFadeGroup(m_ShowReflectionProbesGUI.faded)) - { - m_Terrain.reflectionProbeUsage = (ReflectionProbeUsage)EditorGUILayout.EnumPopup(styles.reflectionProbes, m_Terrain.reflectionProbeUsage); - if (m_Terrain.reflectionProbeUsage != ReflectionProbeUsage.Off) - { - EditorGUI.indentLevel++; - m_Terrain.GetClosestReflectionProbes(m_BlendInfoList); - RendererEditorBase.Probes.ShowClosestReflectionProbes(m_BlendInfoList); - EditorGUI.indentLevel--; - } - } - EditorGUILayout.EndFadeGroup(); - - terrainData.thickness = EditorGUILayout.FloatField(styles.thickness, terrainData.thickness); - - GUILayout.Label("Tree & Detail Objects", EditorStyles.boldLabel); - m_Terrain.drawTreesAndFoliage = EditorGUILayout.Toggle(styles.drawTrees, m_Terrain.drawTreesAndFoliage); - m_Terrain.bakeLightProbesForTrees = EditorGUILayout.Toggle(styles.bakeLightProbesForTrees, m_Terrain.bakeLightProbesForTrees); - m_Terrain.detailObjectDistance = EditorGUILayout.Slider(styles.detailObjectDistance, m_Terrain.detailObjectDistance, 0, 250); // former string formatting: "" - m_Terrain.collectDetailPatches = EditorGUILayout.Toggle(styles.collectDetailPatches, m_Terrain.collectDetailPatches); - m_Terrain.detailObjectDensity = EditorGUILayout.Slider(styles.detailObjectDensity, m_Terrain.detailObjectDensity, 0.0f, 1.0f); - m_Terrain.treeDistance = EditorGUILayout.Slider(styles.treeDistance, m_Terrain.treeDistance, 0, 2000); // former string formatting: "" - m_Terrain.treeBillboardDistance = EditorGUILayout.Slider(styles.treeBillboardDistance, m_Terrain.treeBillboardDistance, 5, 2000); // former string formatting: "" - m_Terrain.treeCrossFadeLength = EditorGUILayout.Slider(styles.treeCrossFadeLength, m_Terrain.treeCrossFadeLength, 0, 200); // former string formatting: "" - m_Terrain.treeMaximumFullLODCount = EditorGUILayout.IntSlider(styles.treeMaximumFullLODCount, m_Terrain.treeMaximumFullLODCount, 0, 10000); - - // Only do this check once per frame. - if (Event.current.type == EventType.Layout) - { - m_LODTreePrototypePresent = false; - for (int i = 0; i < terrainData.treePrototypes.Length; ++i) - { - if (TerrainEditorUtility.IsLODTreePrototype(terrainData.treePrototypes[i].prefab)) - { - m_LODTreePrototypePresent = true; - break; - } - } - } - - if (m_LODTreePrototypePresent) - EditorGUILayout.HelpBox("Tree Distance, Billboard Start, Fade Length and Max Mesh Trees have no effect on SpeedTree trees. Please use the LOD Group component on the tree prefab to control LOD settings.", MessageType.Info); - - if (EditorGUI.EndChangeCheck()) - { - EditorApplication.SetSceneRepaintDirty(); - EditorUtility.SetDirty(m_Terrain); - - if (!EditorApplication.isPlaying) - SceneManagement.EditorSceneManager.MarkSceneDirty(m_Terrain.gameObject.scene); - } - - EditorGUI.BeginChangeCheck(); - - GUILayout.Label("Wind Settings for Grass", EditorStyles.boldLabel); - float wavingGrassStrength = EditorGUILayout.Slider(styles.wavingGrassStrength, terrainData.wavingGrassStrength, 0, 1); // former string formatting: "%" - float wavingGrassSpeed = EditorGUILayout.Slider(styles.wavingGrassSpeed, terrainData.wavingGrassSpeed, 0, 1); // former string formatting: "%" - float wavingGrassAmount = EditorGUILayout.Slider(styles.wavingGrassAmount, terrainData.wavingGrassAmount, 0, 1); // former string formatting: "%" - Color wavingGrassTint = EditorGUILayout.ColorField(styles.wavingGrassTint, terrainData.wavingGrassTint); - - if (EditorGUI.EndChangeCheck()) - { - // Apply terrain settings only when something has changed. Otherwise we needlessly dirty the object and it will show up as modified. - terrainData.wavingGrassStrength = wavingGrassStrength; - terrainData.wavingGrassSpeed = wavingGrassSpeed; - terrainData.wavingGrassAmount = wavingGrassAmount; - terrainData.wavingGrassTint = wavingGrassTint; - - // In cases where terrain data is embedded in the scene (i.e. it's not an asset), - // we need to dirty the scene if terrainData has changed. - if (!EditorUtility.IsPersistent(terrainData) && !EditorApplication.isPlaying) - SceneManagement.EditorSceneManager.MarkSceneDirty(m_Terrain.gameObject.scene); - } - - ShowResolution(); - ShowHeightmaps(); - } - - public void ShowRaiseHeight() - { - ShowBrushes(); - GUILayout.Label(styles.settings, EditorStyles.boldLabel); - ShowBrushSettings(); - } - - public void ShowSmoothHeight() - { - ShowBrushes(); - GUILayout.Label(styles.settings, EditorStyles.boldLabel); - ShowBrushSettings(); - } - - public void ShowTextures() - { - LoadSplatIcons(); - ShowBrushes(); - - GUILayout.Label(styles.textures, EditorStyles.boldLabel); - GUI.changed = false; - bool doubleClick; - m_SelectedSplat = AspectSelectionGrid(m_SelectedSplat, m_SplatIcons, 64, styles.gridList, "No terrain textures defined.", out doubleClick); - if (doubleClick) - { - TerrainSplatContextMenus.EditSplat(new MenuCommand(m_Terrain, m_SelectedSplat)); - GUIUtility.ExitGUI(); - } - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - MenuButton(styles.editTextures, "CONTEXT/TerrainEngineSplats", m_SelectedSplat); - GUILayout.EndHorizontal(); - - // Brush size - GUILayout.Label(styles.settings, EditorStyles.boldLabel); - ShowBrushSettings(); - m_SplatAlpha = EditorGUILayout.Slider(styles.targetStrength, m_SplatAlpha, 0.0F, 1.0F); // former string formatting: "%" - } - - public void ShowBrushes() - { - GUILayout.Label(styles.brushes, EditorStyles.boldLabel); - bool dummy; - m_SelectedBrush = AspectSelectionGrid(m_SelectedBrush, s_BrushTextures, 32, styles.gridList, "No brushes defined.", out dummy); - } - - public void ShowHeightmaps() - { - GUILayout.Label(styles.heightmap, EditorStyles.boldLabel); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - if (GUILayout.Button(styles.importRaw)) - { - TerrainMenus.ImportRaw(); - } - - if (GUILayout.Button(styles.exportRaw)) - { - TerrainMenus.ExportHeightmapRaw(); - } - GUILayout.EndHorizontal(); - } - - public void ShowResolution() - { - GUILayout.Label("Resolution", EditorStyles.boldLabel); - - float terrainWidth = m_Terrain.terrainData.size.x; - float terrainHeight = m_Terrain.terrainData.size.y; - float terrainLength = m_Terrain.terrainData.size.z; - int heightmapResolution = m_Terrain.terrainData.heightmapResolution; - int detailResolution = m_Terrain.terrainData.detailResolution; - int detailResolutionPerPatch = m_Terrain.terrainData.detailResolutionPerPatch; - int controlTextureResolution = m_Terrain.terrainData.alphamapResolution; - int baseTextureResolution = m_Terrain.terrainData.baseMapResolution; - - EditorGUI.BeginChangeCheck(); - - const int kMaxTerrainSize = 100000; - const int kMaxTerrainHeight = 10000; - terrainWidth = EditorGUILayout.DelayedFloatField(EditorGUIUtility.TrTextContent("Terrain Width", "Size of the terrain object in its X axis (in world units)."), terrainWidth); - if (terrainWidth <= 0) terrainWidth = 1; - if (terrainWidth > kMaxTerrainSize) terrainWidth = kMaxTerrainSize; - - terrainLength = EditorGUILayout.DelayedFloatField(EditorGUIUtility.TrTextContent("Terrain Length", "Size of the terrain object in its Z axis (in world units)."), terrainLength); - if (terrainLength <= 0) terrainLength = 1; - if (terrainLength > kMaxTerrainSize) terrainLength = kMaxTerrainSize; - - terrainHeight = EditorGUILayout.DelayedFloatField(EditorGUIUtility.TrTextContent("Terrain Height", "Difference in Y coordinate between the lowest possible heightmap value and the highest (in world units)."), terrainHeight); - if (terrainHeight <= 0) terrainHeight = 1; - if (terrainHeight > kMaxTerrainHeight) terrainHeight = kMaxTerrainHeight; - - heightmapResolution = EditorGUILayout.DelayedIntField(EditorGUIUtility.TrTextContent("Heightmap Resolution", "Pixel resolution of the terrain's heightmap (should be a power of two plus one, eg, 513 = 512 + 1)."), heightmapResolution); - const int kMinimumResolution = 33; // 33 is the minimum that GetAdjustedSize will allow - const int kMaximumResolution = 4097; // if you want to change the maximum value, also change it in SetResolutionWizard - heightmapResolution = Mathf.Clamp(heightmapResolution, kMinimumResolution, kMaximumResolution); - heightmapResolution = m_Terrain.terrainData.GetAdjustedSize(heightmapResolution); - - detailResolution = EditorGUILayout.DelayedIntField(EditorGUIUtility.TrTextContent("Detail Resolution", "Resolution of the map that determines the separate patches of details/grass. Higher resolution gives smaller and more detailed patches."), detailResolution); - detailResolution = Mathf.Clamp(detailResolution, 0, 4048); - - detailResolutionPerPatch = EditorGUILayout.DelayedIntField(EditorGUIUtility.TrTextContent("Detail Resolution Per Patch", "Length/width of the square of patches renderered with a single draw call."), detailResolutionPerPatch); - detailResolutionPerPatch = Mathf.Clamp(detailResolutionPerPatch, 8, 128); - - controlTextureResolution = EditorGUILayout.DelayedIntField(EditorGUIUtility.TrTextContent("Control Texture Resolution", "Resolution of the \"splatmap\" that controls the blending of the different terrain textures."), controlTextureResolution); - controlTextureResolution = Mathf.Clamp(Mathf.ClosestPowerOfTwo(controlTextureResolution), 16, 2048); - - baseTextureResolution = EditorGUILayout.DelayedIntField(EditorGUIUtility.TrTextContent("Base Texture Resolution", "Resolution of the composite texture used on the terrain when viewed from a distance greater than the Basemap Distance."), baseTextureResolution); - baseTextureResolution = Mathf.Clamp(Mathf.ClosestPowerOfTwo(baseTextureResolution), 16, 2048); - - if (EditorGUI.EndChangeCheck()) - { - ArrayList undoObjects = new ArrayList(); - undoObjects.Add(m_Terrain.terrainData); - undoObjects.AddRange(m_Terrain.terrainData.alphamapTextures); - - Undo.RegisterCompleteObjectUndo(undoObjects.ToArray(typeof(UnityEngine.Object)) as UnityEngine.Object[], "Set Resolution"); - - if (m_Terrain.terrainData.heightmapResolution != heightmapResolution) - m_Terrain.terrainData.heightmapResolution = heightmapResolution; - m_Terrain.terrainData.size = new Vector3(terrainWidth, terrainHeight, terrainLength); - - if (m_Terrain.terrainData.detailResolution != detailResolution || detailResolutionPerPatch != m_Terrain.terrainData.detailResolutionPerPatch) - ResizeDetailResolution(m_Terrain.terrainData, detailResolution, detailResolutionPerPatch); - - if (m_Terrain.terrainData.alphamapResolution != controlTextureResolution) - m_Terrain.terrainData.alphamapResolution = controlTextureResolution; - - if (m_Terrain.terrainData.baseMapResolution != baseTextureResolution) - m_Terrain.terrainData.baseMapResolution = baseTextureResolution; - - m_Terrain.Flush(); - } - - EditorGUILayout.HelpBox("Please note that modifying the resolution of the heightmap, detail map and control texture will clear their contents, respectively.", MessageType.Warning); - } - - void ResizeDetailResolution(TerrainData terrainData, int resolution, int resolutionPerPatch) - { - if (resolution == terrainData.detailResolution) - { - var layers = new List(); - for (int i = 0; i < terrainData.detailPrototypes.Length; i++) - layers.Add(terrainData.GetDetailLayer(0, 0, terrainData.detailWidth, terrainData.detailHeight, i)); - - terrainData.SetDetailResolution(resolution, resolutionPerPatch); - - for (int i = 0; i < layers.Count; i++) - terrainData.SetDetailLayer(0, 0, i, layers[i]); - } - else - { - terrainData.SetDetailResolution(resolution, resolutionPerPatch); - } - } - - public void ShowUpgradeTreePrototypeScaleUI() - { - if (m_Terrain.terrainData != null && m_Terrain.terrainData.NeedUpgradeScaledTreePrototypes()) - { - var msgContent = EditorGUIUtility.TempContent( - "Some of your prototypes have scaling values on the prefab. Since Unity 5.2 these scalings will be applied to terrain tree instances. Do you want to upgrade to this behaviour?", - EditorGUIUtility.GetHelpIcon(MessageType.Warning)); - GUILayout.BeginVertical(EditorStyles.helpBox); - GUILayout.Label(msgContent, EditorStyles.wordWrappedLabel); - GUILayout.Space(3); - if (GUILayout.Button("Upgrade", GUILayout.ExpandWidth(false))) - { - m_Terrain.terrainData.UpgradeScaledTreePrototype(); - TerrainMenus.RefreshPrototypes(); - } - GUILayout.Space(3); - GUILayout.EndVertical(); - } - } - - public void ShowRefreshPrototypes() - { - if (GUILayout.Button(styles.refresh)) - { - TerrainMenus.RefreshPrototypes(); - } - } - - public void ShowMassPlaceTrees() - { - using (new EditorGUI.DisabledScope(TreePainter.selectedTree == -1)) - { - if (GUILayout.Button(styles.massPlaceTrees)) - { - TerrainMenus.MassPlaceTrees(); - } - } - } - - public void ShowBrushSettings() - { - m_Size = Mathf.RoundToInt(EditorGUILayout.Slider(styles.brushSize, m_Size, 1, 100)); - m_Strength = PercentSlider(styles.opacity, m_Strength, kMinBrushStrength, 1); // former string formatting: "0.0%" - } - - public void ShowSetHeight() - { - ShowBrushes(); - GUILayout.Label(styles.settings, EditorStyles.boldLabel); - ShowBrushSettings(); - - GUILayout.BeginHorizontal(); - - GUI.changed = false; - float val = (m_TargetHeight * m_Terrain.terrainData.size.y); - val = EditorGUILayout.Slider(styles.height, val, 0, m_Terrain.terrainData.size.y); - if (GUI.changed) - m_TargetHeight = val / m_Terrain.terrainData.size.y; - - if (GUILayout.Button(styles.flatten, GUILayout.ExpandWidth(false))) - { - Undo.RegisterCompleteObjectUndo(m_Terrain.terrainData, "Flatten Heightmap"); - HeightmapFilters.Flatten(m_Terrain.terrainData, m_TargetHeight); - } - - GUILayout.EndHorizontal(); - } - - public void InitializeLightingFields() - { - m_Lighting = new LightingSettingsInspector(serializedObject); - m_Lighting.showSettings = EditorPrefs.GetBool(kDisplayLightingKey, false); - } - - public void RenderLightingFields() - { - bool oldShowLighting = m_Lighting.showSettings; - - if (m_Lighting.Begin()) - { - m_Lighting.RenderTerrainSettings(); - } - m_Lighting.End(); - - if (m_Lighting.showSettings != oldShowLighting) - EditorPrefs.SetBool(kDisplayLightingKey, m_Lighting.showSettings); - } - - void OnInspectorUpdate() - { - if (AssetPreview.HasAnyNewPreviewTexturesAvailable()) - Repaint(); - } - - public override void OnInspectorGUI() - { - serializedObject.Update(); - - Initialize(); - - if (styles == null) - { - styles = new Styles(); - } - - if (!m_Terrain.terrainData) - { - GUI.enabled = false; - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - GUILayout.Toolbar(-1, styles.toolIcons, styles.command); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - GUI.enabled = true; - GUILayout.BeginVertical(EditorStyles.helpBox); - GUILayout.Label("Terrain Asset Missing"); - m_Terrain.terrainData = EditorGUILayout.ObjectField("Assign:", m_Terrain.terrainData, typeof(TerrainData), false) as TerrainData; - GUILayout.EndVertical(); - return; - } - - if (Event.current.type == EventType.Layout) - m_TerrainCollider = m_Terrain.gameObject.GetComponent(); - - if (m_TerrainCollider && m_TerrainCollider.terrainData != m_Terrain.terrainData) - { - GUILayout.BeginVertical(EditorStyles.helpBox); - GUILayout.Label(styles.mismatchedTerrainData, EditorStyles.wordWrappedLabel); - GUILayout.Space(3); - if (GUILayout.Button(styles.assign, GUILayout.ExpandWidth(false))) - { - Undo.RecordObject(m_TerrainCollider, "Assign TerrainData"); - m_TerrainCollider.terrainData = m_Terrain.terrainData; - } - GUILayout.Space(3); - GUILayout.EndVertical(); - } - - // Show the master tool selector - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - GUI.changed = false; - int tool = (int)selectedTool; - int newlySelectedTool = GUILayout.Toolbar(tool, styles.toolIcons, styles.command); - - if (newlySelectedTool != tool) - { - selectedTool = (TerrainTool)newlySelectedTool; - - // Need to repaint other terrain inspectors as their previously selected tool is now deselected. - InspectorWindow.RepaintAllInspectors(); - - if (Toolbar.get != null) - Toolbar.get.Repaint(); - } - - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - - CheckKeys(); - - GUILayout.BeginVertical(EditorStyles.helpBox); - if (tool >= 0 && tool < styles.toolIcons.Length) - { - GUILayout.Label(styles.toolNames[(int)tool].text); - GUILayout.Label(styles.toolNames[(int)tool].tooltip, EditorStyles.wordWrappedMiniLabel); - } - else - { - // TODO: Fix these somehow sensibly - GUILayout.Label("No tool selected"); - GUILayout.Label("Please select a tool", EditorStyles.wordWrappedMiniLabel); - } - GUILayout.EndVertical(); - - switch ((TerrainTool)tool) - { - case TerrainTool.PaintHeight: - ShowRaiseHeight(); - break; - case TerrainTool.SetHeight: - ShowSetHeight(); - break; - case TerrainTool.SmoothHeight: - ShowSmoothHeight(); - break; - case TerrainTool.PaintTexture: - ShowTextures(); - break; - case TerrainTool.PlaceTree: - ShowTrees(); - break; - case TerrainTool.PaintDetail: - ShowDetails(); - break; - case TerrainTool.TerrainSettings: - ShowSettings(); - break; - } - - RenderLightingFields(); - - GUILayout.Space(5); - } - - Brush GetActiveBrush(int size) - { - if (m_CachedBrush == null) - m_CachedBrush = new Brush(); - - m_CachedBrush.Load(s_BrushTextures[m_SelectedBrush], size); - - return m_CachedBrush; - } - - public bool Raycast(out Vector2 uv, out Vector3 pos) - { - Ray mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); - - RaycastHit hit; - if (m_Terrain.GetComponent().Raycast(mouseRay, out hit, Mathf.Infinity)) - { - uv = hit.textureCoord; - pos = hit.point; - return true; - } - - uv = Vector2.zero; - pos = Vector3.zero; - return false; - } - - public bool HasFrameBounds() - { - // When selecting terrains using Scene search, they may be framed right after selecting, when the editor - // is not initialized yet. Just return empty bounds in that case. - return m_Terrain != null; - } - - public Bounds OnGetFrameBounds() - { - Vector2 uv; - Vector3 pos; - - // It's possible that something other the scene view invoked OnGetFrameBounds (e.g. double clicking the terrain in the hierarchy) - // In this case we can't do a raycast, because there is no active camera. - if (Camera.current && m_Terrain.terrainData && Raycast(out uv, out pos)) - { - // Avoid locking when framing terrain (case 527647) - if (SceneView.lastActiveSceneView != null) - SceneView.lastActiveSceneView.viewIsLockedToObject = false; - - // Use height editing tool for calculating the bounds by default - Bounds bounds = new Bounds(); - float brushSize = selectedTool == TerrainTool.PlaceTree ? TreePainter.brushSize : m_Size; - Vector3 size; - size.x = brushSize / m_Terrain.terrainData.heightmapWidth * m_Terrain.terrainData.size.x; - size.z = brushSize / m_Terrain.terrainData.heightmapHeight * m_Terrain.terrainData.size.z; - size.y = (size.x + size.z) * 0.5F; - bounds.center = pos; - bounds.size = size; - // detail painting needs to be much closer - if (selectedTool == TerrainTool.PaintDetail && m_Terrain.terrainData.detailWidth != 0) - { - size.x = brushSize / m_Terrain.terrainData.detailWidth * m_Terrain.terrainData.size.x * 0.7F; - size.z = brushSize / m_Terrain.terrainData.detailHeight * m_Terrain.terrainData.size.z * 0.7F; - size.y = 0; - bounds.size = size; - } - - return bounds; - } - else - { - // We don't return bounds from the collider, because apparently they are not immediately - // updated after changing the position. So if terrain is repositioned, then bounds will - // still be wrong until after some times PhysX updates them (it gets them through some - // pruning interface and not directly from heightmap shape). - //return m_Terrain.collider.bounds; - - Vector3 position = m_Terrain.transform.position; - - if (m_Terrain.terrainData == null) - { - return new Bounds(position, Vector3.zero); - } - - Vector3 size = m_Terrain.terrainData.size; - - float[,] heights = m_Terrain.terrainData.GetHeights(0, 0, m_Terrain.terrainData.heightmapWidth, m_Terrain.terrainData.heightmapHeight); - - float maxHeight = float.MinValue; - for (int y = 0; y < m_Terrain.terrainData.heightmapHeight; y++) - for (int x = 0; x < m_Terrain.terrainData.heightmapWidth; x++) - maxHeight = Mathf.Max(maxHeight, heights[x, y]); - - size.y = maxHeight * size.y; - - return new Bounds(position + size * 0.5f, size); - } - } - - private bool IsModificationToolActive() - { - if (!m_Terrain) - return false; - TerrainTool st = selectedTool; - if (st == TerrainTool.TerrainSettings) - return false; - if ((int)st < 0 || st >= TerrainTool.TerrainToolCount) - return false; - return true; - } - - bool IsBrushPreviewVisible() - { - if (!IsModificationToolActive()) - return false; - - Vector3 pos; - Vector2 uv; - return Raycast(out uv, out pos); - } - - void DisableProjector() - { - if (m_CachedBrush != null) - m_CachedBrush.GetPreviewProjector().enabled = false; - } - - void UpdatePreviewBrush() - { - if (!IsModificationToolActive() || m_Terrain.terrainData == null) - { - DisableProjector(); - return; - } - - Projector projector = GetActiveBrush(m_Size).GetPreviewProjector(); - float size = 1.0F; - float aspect = m_Terrain.terrainData.size.x / m_Terrain.terrainData.size.z; - - Transform tr = projector.transform; - Vector2 uv; - Vector3 pos; - - bool isValid = true; - if (Raycast(out uv, out pos)) - { - if (selectedTool == TerrainTool.PlaceTree) - { - projector.material.mainTexture = (Texture2D)EditorGUIUtility.Load(EditorResourcesUtility.brushesPath + "builtin_brush_4.png"); - - size = TreePainter.brushSize / 0.80f; - aspect = 1; - } - else if (selectedTool == TerrainTool.PaintHeight || selectedTool == TerrainTool.SetHeight || selectedTool == TerrainTool.SmoothHeight) - { - if (m_Size % 2 == 0) - { - float offset = 0.5F; - uv.x = (Mathf.Floor(uv.x * (m_Terrain.terrainData.heightmapWidth - 1)) + offset) / (m_Terrain.terrainData.heightmapWidth - 1); - uv.y = (Mathf.Floor(uv.y * (m_Terrain.terrainData.heightmapHeight - 1)) + offset) / (m_Terrain.terrainData.heightmapHeight - 1); - } - else - { - uv.x = (Mathf.Round(uv.x * (m_Terrain.terrainData.heightmapWidth - 1))) / (m_Terrain.terrainData.heightmapWidth - 1); - uv.y = (Mathf.Round(uv.y * (m_Terrain.terrainData.heightmapHeight - 1))) / (m_Terrain.terrainData.heightmapHeight - 1); - } - - pos.x = uv.x * m_Terrain.terrainData.size.x; - pos.z = uv.y * m_Terrain.terrainData.size.z; - pos += m_Terrain.transform.position; - - size = m_Size * 0.5f / m_Terrain.terrainData.heightmapWidth * m_Terrain.terrainData.size.x; - } - else if (selectedTool == TerrainTool.PaintTexture || selectedTool == TerrainTool.PaintDetail) - { - float offset = m_Size % 2 == 0 ? 0.0F : 0.5F; - int width, height; - if (selectedTool == TerrainTool.PaintTexture) - { - width = m_Terrain.terrainData.alphamapWidth; - height = m_Terrain.terrainData.alphamapHeight; - } - else - { - width = m_Terrain.terrainData.detailWidth; - height = m_Terrain.terrainData.detailHeight; - } - - if (width == 0 || height == 0) - isValid = false; - - uv.x = (Mathf.Floor(uv.x * width) + offset) / width; - uv.y = (Mathf.Floor(uv.y * height) + offset) / height; - - pos.x = uv.x * m_Terrain.terrainData.size.x; - pos.z = uv.y * m_Terrain.terrainData.size.z; - pos += m_Terrain.transform.position; - - size = m_Size * 0.5f / width * m_Terrain.terrainData.size.x; - aspect = (float)width / (float)height; - } - } - else - isValid = false; - - projector.enabled = isValid; - if (isValid) - { - pos.y = m_Terrain.transform.position.y + m_Terrain.SampleHeight(pos); - tr.position = pos + new Vector3(0.0f, 50.0f, 0.0f); - } - - projector.orthographicSize = size / aspect; - projector.aspectRatio = aspect; - } - - public void OnSceneGUICallback(SceneView sceneView) - { - Initialize(); - - if (m_Terrain == null || m_Terrain.terrainData == null) - return; - - Event e = Event.current; - - CheckKeys(); - - int id = GUIUtility.GetControlID(s_TerrainEditorHash, FocusType.Passive); - switch (e.GetTypeForControl(id)) - { - case EventType.Layout: - if (!IsModificationToolActive()) - return; - HandleUtility.AddDefaultControl(id); - break; - - case EventType.MouseMove: - if (IsBrushPreviewVisible()) - HandleUtility.Repaint(); - break; - - case EventType.MouseDown: - case EventType.MouseDrag: - { - // Don't do anything at all if someone else owns the hotControl. Fixes case 677541. - if (EditorGUIUtility.hotControl != 0 && EditorGUIUtility.hotControl != id) - return; - - // Don't do anything on MouseDrag if we don't own the hotControl. - if (e.GetTypeForControl(id) == EventType.MouseDrag && EditorGUIUtility.hotControl != id) - return; - - // If user is ALT-dragging, we want to return to main routine - if (Event.current.alt) - return; - - // Allow painting with LMB only - if (e.button != 0) - return; - - if (!IsModificationToolActive()) - return; - - if (HandleUtility.nearestControl != id) - return; - - if (e.type == EventType.MouseDown) - EditorGUIUtility.hotControl = id; - - Vector2 uv; - Vector3 pos; - if (Raycast(out uv, out pos)) - { - if (selectedTool == TerrainTool.SetHeight && Event.current.shift) - { - m_TargetHeight = m_Terrain.terrainData.GetInterpolatedHeight(uv.x, uv.y) / m_Terrain.terrainData.size.y; - InspectorWindow.RepaintAllInspectors(); - } - else if (selectedTool == TerrainTool.PlaceTree) - { - if (e.type == EventType.MouseDown) - Undo.RegisterCompleteObjectUndo(m_Terrain.terrainData, "Place Tree"); - - if (!Event.current.shift && !Event.current.control) - TreePainter.PlaceTrees(m_Terrain, uv.x, uv.y); - else - TreePainter.RemoveTrees(m_Terrain, uv.x, uv.y, Event.current.control); - } - else if (selectedTool == TerrainTool.PaintTexture) - { - if (e.type == EventType.MouseDown) - { - var undoableObjects = new List(); - undoableObjects.Add(m_Terrain.terrainData); - undoableObjects.AddRange(m_Terrain.terrainData.alphamapTextures); - - Undo.RegisterCompleteObjectUndo(undoableObjects.ToArray(), "Detail Edit"); - } - - // Setup splat painter - SplatPainter splatPainter = new SplatPainter(); - splatPainter.size = m_Size; - splatPainter.strength = m_Strength; - splatPainter.terrainData = m_Terrain.terrainData; - splatPainter.brush = GetActiveBrush(splatPainter.size); - splatPainter.target = m_SplatAlpha; - splatPainter.tool = selectedTool; - - m_Terrain.editorRenderFlags = TerrainRenderFlags.Heightmap; - splatPainter.Paint(uv.x, uv.y, m_SelectedSplat); - - - // Don't perform basemap calculation while painting - m_Terrain.terrainData.SetBasemapDirty(false); - } - else if (selectedTool == TerrainTool.PaintDetail) - { - if (e.type == EventType.MouseDown) - Undo.RegisterCompleteObjectUndo(m_Terrain.terrainData, "Detail Edit"); - // Setup detail painter - DetailPainter detailPainter = new DetailPainter(); - detailPainter.size = m_Size; - detailPainter.targetStrength = m_DetailStrength * 16F; - detailPainter.opacity = m_DetailOpacity; - if (Event.current.shift || Event.current.control) - detailPainter.targetStrength *= -1; - detailPainter.clearSelectedOnly = Event.current.control; - detailPainter.terrainData = m_Terrain.terrainData; - detailPainter.brush = GetActiveBrush(detailPainter.size); - detailPainter.tool = selectedTool; - detailPainter.randomizeDetails = true; - - detailPainter.Paint(uv.x, uv.y, m_SelectedDetail); - } - else - { - if (e.type == EventType.MouseDown) - Undo.RegisterCompleteObjectUndo(m_Terrain.terrainData, "Heightmap Edit"); - - // Setup painter - HeightmapPainter painter = new HeightmapPainter(); - painter.size = m_Size; - painter.strength = m_Strength * 0.01F; - if (selectedTool == TerrainTool.SmoothHeight) - painter.strength = m_Strength; - painter.terrainData = m_Terrain.terrainData; - painter.brush = GetActiveBrush(m_Size); - painter.targetHeight = m_TargetHeight; - painter.tool = selectedTool; - - m_Terrain.editorRenderFlags = TerrainRenderFlags.Heightmap; - - if (selectedTool == TerrainTool.PaintHeight && Event.current.shift) - painter.strength = -painter.strength; - - painter.PaintHeight(uv.x, uv.y); - } - - e.Use(); - } - } - break; - - case EventType.MouseUp: - { - if (GUIUtility.hotControl != id) - { - return; - } - - // Release hot control - GUIUtility.hotControl = 0; - - if (!IsModificationToolActive()) - return; - - // Perform basemap calculation after all painting has completed! - if (selectedTool == TerrainTool.PaintTexture) - m_Terrain.terrainData.SetBasemapDirty(true); - - m_Terrain.editorRenderFlags = TerrainRenderFlags.All; - m_Terrain.ApplyDelayedHeightmapModification(); - - e.Use(); - } - break; - - case EventType.Repaint: - DisableProjector(); - break; - } - } - - private void OnPreSceneGUICallback(SceneView sceneView) - { - if (Event.current.type == EventType.Repaint) - UpdatePreviewBrush(); - } - } -} //namespace diff --git a/Editor/Mono/TerrainEditor/TerrainMenus.cs b/Editor/Mono/TerrainEditor/TerrainMenus.cs deleted file mode 100644 index 4fcef64748..0000000000 --- a/Editor/Mono/TerrainEditor/TerrainMenus.cs +++ /dev/null @@ -1,267 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.IO; -using UnityEngine.Rendering; - -namespace UnityEditor -{ - internal class TerrainMenus - { - [MenuItem("GameObject/3D Object/Terrain", false, 3000)] - static void CreateTerrain(MenuCommand menuCommand) - { - // Create the storage for the terrain in the project - // (So we can reuse it in multiple scenes) - TerrainData terrainData = new TerrainData(); - const int size = 1025; - terrainData.heightmapResolution = size; - terrainData.size = new Vector3(1000, 600, 1000); - - terrainData.heightmapResolution = 512; - terrainData.baseMapResolution = 1024; - terrainData.SetDetailResolution(1024, terrainData.detailResolutionPerPatch); - - AssetDatabase.CreateAsset(terrainData, AssetDatabase.GenerateUniqueAssetPath("Assets/New Terrain.asset")); - var parent = menuCommand.context as GameObject; - var name = GameObjectUtility.GetUniqueNameForSibling(parent != null ? parent.transform : null, "Terrain"); - GameObject terrain = Terrain.CreateTerrainGameObject(terrainData); - terrain.name = name; - - if (GraphicsSettings.renderPipelineAsset != null) - { - var material = GraphicsSettings.renderPipelineAsset.GetDefaultTerrainMaterial(); - var theTerrain = terrain.GetComponent(); - if (theTerrain && material != null) - { - theTerrain.materialType = Terrain.MaterialType.Custom; - theTerrain.materialTemplate = material; - } - } - GameObjectUtility.SetParentAndAlign(terrain, parent); - Selection.activeObject = terrain; - Undo.RegisterCreatedObjectUndo(terrain, "Create terrain"); - } - - internal static void ImportRaw() - { - string saveLocation = EditorUtility.OpenFilePanel("Import Raw Heightmap", "", "raw"); - if (saveLocation != "") - { - ImportRawHeightmap wizard = TerrainWizard.DisplayTerrainWizard("Import Heightmap", "Import"); - wizard.InitializeImportRaw(GetActiveTerrain(), saveLocation); - } - } - - internal static void ExportHeightmapRaw() - { - ExportRawHeightmap wizard = TerrainWizard.DisplayTerrainWizard("Export Heightmap", "Export"); - wizard.InitializeDefaults(GetActiveTerrain()); - } - - internal static void MassPlaceTrees() - { - PlaceTreeWizard wizard = TerrainWizard.DisplayTerrainWizard("Place Trees", "Place"); - wizard.InitializeDefaults(GetActiveTerrain()); - } - - internal static void Flatten() - { - FlattenHeightmap wizard = TerrainWizard.DisplayTerrainWizard("Flatten Heightmap", "Flatten"); - wizard.InitializeDefaults(GetActiveTerrain()); - } - - internal static void RefreshPrototypes() - { - GetActiveTerrainData().RefreshPrototypes(); - GetActiveTerrain().Flush(); - EditorApplication.SetSceneRepaintDirty(); - } - - static void FlushHeightmapModification() - { - //@TODO GetActiveTerrain().treeDatabase.RecalculateTreePosition(); - GetActiveTerrain().Flush(); - } - - static Terrain GetActiveTerrain() - { - Object[] selection = Selection.GetFiltered(typeof(Terrain), SelectionMode.Editable); - - if (selection.Length != 0) - return selection[0] as Terrain; - else - return Terrain.activeTerrain; - } - - static TerrainData GetActiveTerrainData() - { - if (GetActiveTerrain()) - return GetActiveTerrain().terrainData; - else - return null; - } - } - - class TerrainDetailContextMenus - { - [MenuItem("CONTEXT/TerrainEngineDetails/Add Grass Texture")] - static internal void AddDetailTexture(MenuCommand item) - { - DetailTextureWizard wizard = TerrainWizard.DisplayTerrainWizard("Add Grass Texture", "Add"); - wizard.m_DetailTexture = null; - wizard.InitializeDefaults((Terrain)item.context, -1); - } - - [MenuItem("CONTEXT/TerrainEngineDetails/Add Detail Mesh")] - static internal void AddDetailMesh(MenuCommand item) - { - DetailMeshWizard wizard = TerrainWizard.DisplayTerrainWizard("Add Detail Mesh", "Add"); - wizard.m_Detail = null; - wizard.InitializeDefaults((Terrain)item.context, -1); - } - - [MenuItem("CONTEXT/TerrainEngineDetails/Edit")] - static internal void EditDetail(MenuCommand item) - { - Terrain terrain = (Terrain)item.context; - DetailPrototype prototype = terrain.terrainData.detailPrototypes[item.userData]; - - if (prototype.usePrototypeMesh) - { - DetailMeshWizard wizard = TerrainWizard.DisplayTerrainWizard("Edit Detail Mesh", "Apply"); - wizard.InitializeDefaults((Terrain)item.context, item.userData); - } - else - { - DetailTextureWizard wizard = TerrainWizard.DisplayTerrainWizard("Edit Grass Texture", "Apply"); - wizard.InitializeDefaults((Terrain)item.context, item.userData); - } - } - - [MenuItem("CONTEXT/TerrainEngineDetails/Edit", true)] - static internal bool EditDetailCheck(MenuCommand item) - { - Terrain terrain = (Terrain)item.context; - return item.userData >= 0 && item.userData < terrain.terrainData.detailPrototypes.Length; - } - - [MenuItem("CONTEXT/TerrainEngineDetails/Remove")] - static internal void RemoveDetail(MenuCommand item) - { - Terrain terrain = (Terrain)item.context; - TerrainEditorUtility.RemoveDetail(terrain, item.userData); - } - - [MenuItem("CONTEXT/TerrainEngineDetails/Remove", true)] - static internal bool RemoveDetailCheck(MenuCommand item) - { - Terrain terrain = (Terrain)item.context; - return item.userData >= 0 && item.userData < terrain.terrainData.detailPrototypes.Length; - } - } - - class TerrainSplatContextMenus - { - [MenuItem("CONTEXT/TerrainEngineSplats/Add Texture...")] - static internal void AddSplat(MenuCommand item) - { - TerrainSplatEditor.ShowTerrainSplatEditor("Add Terrain Texture", "Add", (Terrain)item.context, -1); - } - - [MenuItem("CONTEXT/TerrainEngineSplats/Edit Texture...")] - static internal void EditSplat(MenuCommand item) - { - Terrain terrain = (Terrain)item.context; - string title = "Edit Terrain Texture"; - - switch (terrain.materialType) - { - case Terrain.MaterialType.BuiltInLegacyDiffuse: - title += " (Diffuse)"; - break; - case Terrain.MaterialType.BuiltInLegacySpecular: - title += " (Specular)"; - break; - case Terrain.MaterialType.BuiltInStandard: - title += " (Standard)"; - break; - case Terrain.MaterialType.Custom: - title += " (Custom)"; - break; - } - - TerrainSplatEditor.ShowTerrainSplatEditor(title, "Apply", (Terrain)item.context, item.userData); - } - - [MenuItem("CONTEXT/TerrainEngineSplats/Edit Texture...", true)] - static internal bool EditSplatCheck(MenuCommand item) - { - Terrain terrain = (Terrain)item.context; - return item.userData >= 0 && item.userData < terrain.terrainData.splatPrototypes.Length; - } - - [MenuItem("CONTEXT/TerrainEngineSplats/Remove Texture")] - static internal void RemoveSplat(MenuCommand item) - { - Terrain terrain = (Terrain)item.context; - TerrainEditorUtility.RemoveSplatTexture(terrain.terrainData, item.userData); - } - - [MenuItem("CONTEXT/TerrainEngineSplats/Remove Texture", true)] - static internal bool RemoveSplatCheck(MenuCommand item) - { - Terrain terrain = (Terrain)item.context; - return item.userData >= 0 && item.userData < terrain.terrainData.splatPrototypes.Length; - } - } - - class TerrainTreeContextMenus - { - [MenuItem("CONTEXT/TerrainEngineTrees/Add Tree")] - static internal void AddTree(MenuCommand item) - { - TreeWizard wizard = TerrainWizard.DisplayTerrainWizard("Add Tree", "Add"); - wizard.InitializeDefaults((Terrain)item.context, -1); - } - - [MenuItem("CONTEXT/TerrainEngineTrees/Edit Tree")] - static internal void EditTree(MenuCommand item) - { - TreeWizard wizard = TerrainWizard.DisplayTerrainWizard("Edit Tree", "Apply"); - wizard.InitializeDefaults((Terrain)item.context, item.userData); - } - - [MenuItem("CONTEXT/TerrainEngineTrees/Edit Tree", true)] - static internal bool EditTreeCheck(MenuCommand item) - { - return TreePainter.selectedTree >= 0; - } - - [MenuItem("CONTEXT/TerrainEngineTrees/Remove Tree")] - static internal void RemoveTree(MenuCommand item) - { - Terrain terrain = (Terrain)item.context; - TerrainEditorUtility.RemoveTree(terrain, item.userData); - } - - [MenuItem("CONTEXT/TerrainEngineTrees/Remove Tree", true)] - static internal bool RemoveTreeCheck(MenuCommand item) - { - return TreePainter.selectedTree >= 0; - } - } - - /* - [MenuItem ("Terrain/Import Heightmap - Texture...")] - static void ImportHeightmap () { - ImportTextureHeightmap wizard = ScriptableWizard.DisplayWizard("Import Heightmap", "Import"); - wizard.InitializeDefaults(GetActiveTerrain()); - } - */ -} //namespace diff --git a/Editor/Mono/TerrainEditor/TerrainSplatEditor.cs b/Editor/Mono/TerrainEditor/TerrainSplatEditor.cs deleted file mode 100644 index 1262e73c6c..0000000000 --- a/Editor/Mono/TerrainEditor/TerrainSplatEditor.cs +++ /dev/null @@ -1,323 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; - -namespace UnityEditor -{ - internal class TerrainSplatEditor : EditorWindow - { - private string m_ButtonTitle = string.Empty; - private Vector2 m_ScrollPosition; - private Terrain m_Terrain; - private int m_Index = -1; - - public Texture2D m_Texture; - public Texture2D m_NormalMap; - private Vector2 m_TileSize; - private Vector2 m_TileOffset; - private Color m_Specular; - private float m_Metallic; - private float m_Smoothness; - - private bool m_NormalMapHasCorrectTextureType; - - public TerrainSplatEditor() - { - position = new Rect(50, 50, 200, 300); - minSize = new Vector2(200, 300); - } - - static internal void ShowTerrainSplatEditor(string title, string button, Terrain terrain, int index) - { - var editor = GetWindow(true, title); - editor.m_ButtonTitle = button; - editor.InitializeData(terrain, index); - } - - void InitializeData(Terrain terrain, int index) - { - m_Terrain = terrain; - m_Index = index; - - SplatPrototype info; - if (index == -1) - info = new SplatPrototype(); - else - info = m_Terrain.terrainData.splatPrototypes[index]; - - m_Texture = info.texture; - m_NormalMap = info.normalMap; - m_TileSize = info.tileSize; - m_TileOffset = info.tileOffset; - m_Specular = info.specular; - m_Metallic = info.metallic; - m_Smoothness = info.smoothness; - - CheckIfNormalMapHasCorrectTextureType(); - } - - private void CheckIfNormalMapHasCorrectTextureType() - { - string assetPath = AssetDatabase.GetAssetPath(m_NormalMap); - - if (string.IsNullOrEmpty(assetPath)) - { - m_NormalMapHasCorrectTextureType = true; - return; - } - - TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter; - - if (importer == null) - m_NormalMapHasCorrectTextureType = false; // has asset path but no importer - must be built-in resources - else - m_NormalMapHasCorrectTextureType = importer.textureType == TextureImporterType.NormalMap; - } - - void ApplyTerrainSplat() - { - if (m_Terrain == null || m_Terrain.terrainData == null) - return; - - SplatPrototype[] infos = m_Terrain.terrainData.splatPrototypes; - if (m_Index == -1) - { - var newarray = new SplatPrototype[infos.Length + 1]; - System.Array.Copy(infos, 0, newarray, 0, infos.Length); - m_Index = infos.Length; - infos = newarray; - infos[m_Index] = new SplatPrototype(); - } - - infos[m_Index].texture = m_Texture; - infos[m_Index].normalMap = m_NormalMap; - infos[m_Index].tileSize = m_TileSize; - infos[m_Index].tileOffset = m_TileOffset; - infos[m_Index].specular = m_Specular; - infos[m_Index].metallic = m_Metallic; - infos[m_Index].smoothness = m_Smoothness; - - m_Terrain.terrainData.splatPrototypes = infos; - EditorUtility.SetDirty(m_Terrain); - } - - private bool ValidateTerrain() - { - if (m_Terrain == null || m_Terrain.terrainData == null) - { - EditorGUILayout.HelpBox("Terrain does not exist", MessageType.Error); - return false; - } - return true; - } - - private bool ValidateTextures() - { - if (m_Texture == null) - { - EditorGUILayout.HelpBox("Assign a tiling texture", MessageType.Warning); - return false; - } - if (m_Texture.wrapMode != TextureWrapMode.Repeat) - { - // Base map generation does not support TextureWrapMode.Clamp properly - EditorGUILayout.HelpBox("Texture wrap mode must be set to Repeat", MessageType.Warning); - return false; - } - if (m_Texture.width != Mathf.ClosestPowerOfTwo(m_Texture.width) || m_Texture.height != Mathf.ClosestPowerOfTwo(m_Texture.height)) - { - // power of two needed for efficient base map generation - EditorGUILayout.HelpBox("Texture size must be power of two", MessageType.Warning); - return false; - } - if (m_Texture.mipmapCount <= 1) - { - // mip maps needed for efficient base map generation. - // And without mipmaps the terrain will look & work bad anyway. - EditorGUILayout.HelpBox("Texture must have mip maps", MessageType.Warning); - return false; - } - - if (!m_NormalMapHasCorrectTextureType) - { - EditorGUILayout.HelpBox("Normal texture should be imported as Normal Map.", MessageType.Warning); - return false; - } - - return true; - } - - private static void TextureFieldGUI(string label, ref Texture2D texture, float alignmentOffset) - { - GUILayout.Space(6); - GUILayout.BeginVertical(GUILayout.Width(80)); - GUILayout.Label(label); - - System.Type t = typeof(Texture2D); - Rect r = GUILayoutUtility.GetRect(64, 64, 64, 64, GUILayout.MaxWidth(64)); - r.x += alignmentOffset; - texture = EditorGUI.DoObjectField(r, r, EditorGUIUtility.GetControlID(12354, FocusType.Keyboard, r), texture, t, null, null, false) as Texture2D; - - GUILayout.EndVertical(); - } - - private static void SplatSizeGUI(ref Vector2 scale, ref Vector2 offset) - { - GUILayoutOption kWidth10 = GUILayout.Width(10); - GUILayoutOption kMinWidth32 = GUILayout.MinWidth(32); - - GUILayout.Space(6); - - GUILayout.BeginHorizontal(); - - GUILayout.BeginVertical(); - GUILayout.Label("", EditorStyles.miniLabel, kWidth10); - GUILayout.Label("x", EditorStyles.miniLabel, kWidth10); - GUILayout.Label("y", EditorStyles.miniLabel, kWidth10); - GUILayout.EndVertical(); - GUILayout.BeginVertical(); - GUILayout.Label("Size", EditorStyles.miniLabel); - scale.x = EditorGUILayout.FloatField(scale.x, EditorStyles.miniTextField, kMinWidth32); - scale.y = EditorGUILayout.FloatField(scale.y, EditorStyles.miniTextField, kMinWidth32); - GUILayout.EndVertical(); - GUILayout.BeginVertical(); - GUILayout.Label("Offset", EditorStyles.miniLabel); - offset.x = EditorGUILayout.FloatField(offset.x, EditorStyles.miniTextField, kMinWidth32); - offset.y = EditorGUILayout.FloatField(offset.y, EditorStyles.miniTextField, kMinWidth32); - GUILayout.EndVertical(); - - GUILayout.EndHorizontal(); - } - - private static bool IsUsingMetallic(Terrain.MaterialType materialType, Material materialTemplate) - { - return materialType == Terrain.MaterialType.BuiltInStandard - || (materialType == Terrain.MaterialType.Custom && materialTemplate != null && materialTemplate.HasProperty("_Metallic0")); - } - - private static bool IsUsingSpecular(Terrain.MaterialType materialType, Material materialTemplate) - { - return materialType == Terrain.MaterialType.BuiltInStandard - || (materialType == Terrain.MaterialType.Custom && materialTemplate != null && materialTemplate.HasProperty("_Specular0")); - } - - private static bool IsUsingSmoothness(Terrain.MaterialType materialType, Material materialTemplate) - { - return materialType == Terrain.MaterialType.BuiltInStandard - || (materialType == Terrain.MaterialType.Custom && materialTemplate != null && materialTemplate.HasProperty("_Smoothness0")); - } - - private void OnGUI() - { - const float controlSize = 64; - EditorGUIUtility.labelWidth = position.width - controlSize - 20; - - bool isValid = true; - - m_ScrollPosition = EditorGUILayout.BeginVerticalScrollView(m_ScrollPosition, false, GUI.skin.verticalScrollbar, GUI.skin.scrollView); - - isValid &= ValidateTerrain(); - - EditorGUI.BeginChangeCheck(); - - // texture & normal map - GUILayout.BeginHorizontal(); - - string textureLabel = ""; - float alignmentOffset = 0.0f; - - switch (m_Terrain.materialType) - { - case Terrain.MaterialType.BuiltInLegacyDiffuse: - textureLabel = "\n Diffuse (RGB)"; - alignmentOffset = 15.0f; - break; - - case Terrain.MaterialType.BuiltInLegacySpecular: - textureLabel = "Diffuse (RGB)\n Gloss (A)"; - alignmentOffset = 12.0f; - break; - - case Terrain.MaterialType.BuiltInStandard: - textureLabel = " Albedo (RGB)\nSmoothness (A)"; - alignmentOffset = 15.0f; - break; - - case Terrain.MaterialType.Custom: - textureLabel = " \n Splat"; - alignmentOffset = 0.0f; - break; - } - - TextureFieldGUI(textureLabel, ref m_Texture, alignmentOffset); - - Texture2D oldNormalMap = m_NormalMap; - TextureFieldGUI("\nNormal", ref m_NormalMap, -4.0f); - - if (m_NormalMap != oldNormalMap) - CheckIfNormalMapHasCorrectTextureType(); - - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - isValid &= ValidateTextures(); - - // PBR text & settings - if (isValid) - { - if (IsUsingMetallic(m_Terrain.materialType, m_Terrain.materialTemplate)) - { - EditorGUILayout.Space(); - float oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 75.0f; - m_Metallic = EditorGUILayout.Slider("Metallic", m_Metallic, 0.0f, 1.0f); - EditorGUIUtility.labelWidth = oldLabelWidth; - } - else if (IsUsingSpecular(m_Terrain.materialType, m_Terrain.materialTemplate)) - { - m_Specular = EditorGUILayout.ColorField("Specular", m_Specular); - } - - if (IsUsingSmoothness(m_Terrain.materialType, m_Terrain.materialTemplate) && !TextureUtil.HasAlphaTextureFormat(m_Texture.format)) - { - EditorGUILayout.Space(); - float oldLabelWidth = EditorGUIUtility.labelWidth; - EditorGUIUtility.labelWidth = 75.0f; - m_Smoothness = EditorGUILayout.Slider("Smoothness", m_Smoothness, 0.0f, 1.0f); - EditorGUIUtility.labelWidth = oldLabelWidth; - } - } - - // tiling & offset - SplatSizeGUI(ref m_TileSize, ref m_TileOffset); - - bool modified = EditorGUI.EndChangeCheck(); - - EditorGUILayout.EndScrollView(); - - GUILayout.FlexibleSpace(); - - // button - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - GUI.enabled = isValid; - - if (GUILayout.Button(m_ButtonTitle, GUILayout.MinWidth(100))) - { - ApplyTerrainSplat(); - Close(); - GUIUtility.ExitGUI(); - } - GUI.enabled = true; - - GUILayout.EndHorizontal(); - - if (modified && isValid && m_Index != -1) - { - ApplyTerrainSplat(); - } - } - } -} //namespace diff --git a/Editor/Mono/TerrainEditor/TerrainWizards.cs b/Editor/Mono/TerrainEditor/TerrainWizards.cs deleted file mode 100644 index 8c04b9c726..0000000000 --- a/Editor/Mono/TerrainEditor/TerrainWizards.cs +++ /dev/null @@ -1,772 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; - -namespace UnityEditor -{ - internal class TerrainWizard : ScriptableWizard - { - internal const int kMaxResolution = 4097; - - protected Terrain m_Terrain; - protected TerrainData terrainData - { - get - { - if (m_Terrain != null) - return m_Terrain.terrainData; - else - return null; - } - } - - internal virtual void OnWizardUpdate() - { - isValid = true; - errorString = ""; - if (m_Terrain == null || m_Terrain.terrainData == null) - { - isValid = false; - errorString = "Terrain does not exist"; - } - } - - internal void InitializeDefaults(Terrain terrain) - { - m_Terrain = terrain; - OnWizardUpdate(); - } - - internal void FlushHeightmapModification() - { - //@TODO: m_Terrain.treeDatabase.RecalculateTreePosition(); - m_Terrain.Flush(); - } - - internal static T DisplayTerrainWizard(string title, string button) where T : TerrainWizard - { - var treeWizards = Resources.FindObjectsOfTypeAll(); - if (treeWizards.Length > 0) - { - var wizard = (T)treeWizards[0]; - wizard.titleContent = EditorGUIUtility.TextContent(title); - wizard.createButtonName = button; - wizard.otherButtonName = ""; - wizard.Focus(); - return wizard; - } - return ScriptableWizard.DisplayWizard(title, button); - } - } - - internal class ImportRawHeightmap : TerrainWizard - { - internal enum Depth { Bit8 = 1, Bit16 = 2 } - internal enum ByteOrder { Mac = 1, Windows = 2 } - - public Depth m_Depth = Depth.Bit16; - public int m_Width = 1; - public int m_Height = 1; - public ByteOrder m_ByteOrder = ByteOrder.Windows; - public bool m_FlipVertically = false; - public Vector3 m_TerrainSize = new Vector3(2000, 600, 2000); - private string m_Path; - - void PickRawDefaults(string path) - { - FileStream file = File.Open(path, FileMode.Open, FileAccess.Read); - int fileSize = (int)file.Length; - file.Close(); - - m_TerrainSize = terrainData.size; - - if (terrainData.heightmapWidth * terrainData.heightmapHeight == fileSize) - { - m_Width = terrainData.heightmapWidth; - m_Height = terrainData.heightmapHeight; - m_Depth = Depth.Bit8; - } - else if (terrainData.heightmapWidth * terrainData.heightmapHeight * 2 == fileSize) - { - m_Width = terrainData.heightmapWidth; - m_Height = terrainData.heightmapHeight; - m_Depth = Depth.Bit16; - } - else - { - m_Depth = Depth.Bit16; - - int pixels = fileSize / (int)m_Depth; - int width = Mathf.RoundToInt(Mathf.Sqrt(pixels)); - int height = Mathf.RoundToInt(Mathf.Sqrt(pixels)); - if ((width * height * (int)m_Depth) == fileSize) - { - m_Width = width; - m_Height = height; - return; - } - - - m_Depth = Depth.Bit8; - - pixels = fileSize / (int)m_Depth; - width = Mathf.RoundToInt(Mathf.Sqrt(pixels)); - height = Mathf.RoundToInt(Mathf.Sqrt(pixels)); - if ((width * height * (int)m_Depth) == fileSize) - { - m_Width = width; - m_Height = height; - return; - } - - m_Depth = Depth.Bit16; - } - } - - internal void OnWizardCreate() - { - if (m_Terrain == null) - { - isValid = false; - errorString = "Terrain does not exist"; - } - - if (m_Width > kMaxResolution || m_Height > kMaxResolution) - { - isValid = false; - errorString = "Heightmaps above 4097x4097 in resolution are not supported"; - Debug.LogError(errorString); - } - - if (File.Exists(m_Path) && isValid) - { - Undo.RegisterCompleteObjectUndo(terrainData, "Import Raw heightmap"); - - terrainData.heightmapResolution = Mathf.Max(m_Width, m_Height); - terrainData.size = m_TerrainSize; - ReadRaw(m_Path); - - FlushHeightmapModification(); - } - } - - void ReadRaw(string path) - { - // Read data - byte[] data; - using (BinaryReader br = new BinaryReader(File.Open(path, FileMode.Open, FileAccess.Read))) - { - data = br.ReadBytes(m_Width * m_Height * (int)m_Depth); - br.Close(); - } - - int heightmapWidth = terrainData.heightmapWidth; - int heightmapHeight = terrainData.heightmapHeight; - float[,] heights = new float[heightmapHeight, heightmapWidth]; - if (m_Depth == Depth.Bit16) - { - float normalize = 1.0F / (1 << 16); - for (int y = 0; y < heightmapHeight; ++y) - { - for (int x = 0; x < heightmapWidth; ++x) - { - int index = Mathf.Clamp(x, 0, m_Width - 1) + Mathf.Clamp(y, 0, m_Height - 1) * m_Width; - if ((m_ByteOrder == ByteOrder.Mac) == System.BitConverter.IsLittleEndian) - { - // Yay, seems like this is the easiest way to swap bytes in C#. NUTS - byte temp; - temp = data[index * 2]; - data[index * 2 + 0] = data[index * 2 + 1]; - data[index * 2 + 1] = temp; - } - - ushort compressedHeight = System.BitConverter.ToUInt16(data, index * 2); - - float height = compressedHeight * normalize; - int destY = m_FlipVertically ? heightmapHeight - 1 - y : y; - heights[destY, x] = height; - } - } - } - else - { - float normalize = 1.0F / (1 << 8); - for (int y = 0; y < heightmapHeight; ++y) - { - for (int x = 0; x < heightmapWidth; ++x) - { - int index = Mathf.Clamp(x, 0, m_Width - 1) + Mathf.Clamp(y, 0, m_Height - 1) * m_Width; - byte compressedHeight = data[index]; - float height = compressedHeight * normalize; - int destY = m_FlipVertically ? heightmapHeight - 1 - y : y; - heights[destY, x] = height; - } - } - } - - terrainData.SetHeights(0, 0, heights); - } - - internal void InitializeImportRaw(Terrain terrain, string path) - { - m_Terrain = terrain; - m_Path = path; - PickRawDefaults(m_Path); - helpString = "Raw files must use a single channel and be either 8 or 16 bit."; - OnWizardUpdate(); - } - } - - internal class ExportRawHeightmap : TerrainWizard - { - internal enum Depth { Bit8 = 1, Bit16 = 2 } - - public Depth m_Depth = Depth.Bit16; - internal enum ByteOrder { Mac = 1, Windows = 2 } - public ByteOrder m_ByteOrder = ByteOrder.Windows; - public bool m_FlipVertically = false; - - public void OnEnable() - { - minSize = new Vector2(400, 200); - } - - internal void OnWizardCreate() - { - if (m_Terrain == null) - { - isValid = false; - errorString = "Terrain does not exist"; - } - - string saveLocation = EditorUtility.SaveFilePanel("Save Raw Heightmap", "", "terrain", "raw"); - if (saveLocation != "") - { - WriteRaw(saveLocation); - } - } - - internal override void OnWizardUpdate() - { - base.OnWizardUpdate(); - if (terrainData) - helpString = "Width " + terrainData.heightmapWidth + "\nHeight " + terrainData.heightmapHeight; - } - - void WriteRaw(string path) - { - // Write data - int heightmapWidth = terrainData.heightmapWidth; - int heightmapHeight = terrainData.heightmapHeight; - float[,] heights = terrainData.GetHeights(0, 0, heightmapWidth, heightmapHeight); - byte[] data = new byte[heightmapWidth * heightmapHeight * (int)m_Depth]; - - if (m_Depth == Depth.Bit16) - { - float normalize = (1 << 16); - for (int y = 0; y < heightmapHeight; ++y) - { - for (int x = 0; x < heightmapWidth; ++x) - { - int index = x + y * heightmapWidth; - int srcY = m_FlipVertically ? heightmapHeight - 1 - y : y; - int height = Mathf.RoundToInt(heights[srcY, x] * normalize); - ushort compressedHeight = (ushort)Mathf.Clamp(height, 0, ushort.MaxValue); - - byte[] byteData = System.BitConverter.GetBytes(compressedHeight); - // Yay, seems like this is the easiest way to swap bytes in C#. NUTS - if ((m_ByteOrder == ByteOrder.Mac) == System.BitConverter.IsLittleEndian) - { - data[index * 2 + 0] = byteData[1]; - data[index * 2 + 1] = byteData[0]; - } - else - { - data[index * 2 + 0] = byteData[0]; - data[index * 2 + 1] = byteData[1]; - } - } - } - } - else - { - float normalize = (1 << 8); - for (int y = 0; y < heightmapHeight; ++y) - { - for (int x = 0; x < heightmapWidth; ++x) - { - int index = x + y * heightmapWidth; - int srcY = m_FlipVertically ? heightmapHeight - 1 - y : y; - int height = Mathf.RoundToInt(heights[srcY, x] * normalize); - byte compressedHeight = (byte)Mathf.Clamp(height, 0, byte.MaxValue); - data[index] = compressedHeight; - } - } - } - - FileStream fs = new FileStream(path, FileMode.Create); - fs.Write(data, 0, data.Length); - fs.Close(); - } - - new void InitializeDefaults(Terrain terrain) - { - m_Terrain = terrain; - helpString = "Width " + terrain.terrainData.heightmapWidth + " Height " + terrain.terrainData.heightmapHeight; - OnWizardUpdate(); - } - } - - - class TreeWizard : TerrainWizard - { - public GameObject m_Tree; - public float m_BendFactor; - private int m_PrototypeIndex = -1; - private bool m_IsValidTree = false; - - public void OnEnable() - { - minSize = new Vector2(400, 150); - } - - private static bool IsValidTree(GameObject tree, int prototypeIndex, Terrain terrain) - { - if (tree == null) - return false; - var prototypes = terrain.terrainData.treePrototypes; - for (int i = 0; i < prototypes.Length; ++i) - { - if (i != prototypeIndex && prototypes[i].m_Prefab == tree) - return false; - } - return true; - } - - internal void InitializeDefaults(Terrain terrain, int index) - { - m_Terrain = terrain; - m_PrototypeIndex = index; - - if (m_PrototypeIndex == -1) - { - m_Tree = null; - m_BendFactor = 0.0f; - } - else - { - m_Tree = m_Terrain.terrainData.treePrototypes[m_PrototypeIndex].prefab; - m_BendFactor = m_Terrain.terrainData.treePrototypes[m_PrototypeIndex].bendFactor; - } - - m_IsValidTree = IsValidTree(m_Tree, m_PrototypeIndex, terrain); - - OnWizardUpdate(); - } - - void DoApply() - { - if (terrainData == null) - return; - TreePrototype[] trees = m_Terrain.terrainData.treePrototypes; - if (m_PrototypeIndex == -1) - { - TreePrototype[] newTrees = new TreePrototype[trees.Length + 1]; - for (int i = 0; i < trees.Length; i++) - newTrees[i] = trees[i]; - newTrees[trees.Length] = new TreePrototype(); - newTrees[trees.Length].prefab = m_Tree; - newTrees[trees.Length].bendFactor = m_BendFactor; - m_PrototypeIndex = trees.Length; - m_Terrain.terrainData.treePrototypes = newTrees; - TreePainter.selectedTree = m_PrototypeIndex; - } - else - { - trees[m_PrototypeIndex].prefab = m_Tree; - trees[m_PrototypeIndex].bendFactor = m_BendFactor; - - m_Terrain.terrainData.treePrototypes = trees; - } - m_Terrain.Flush(); - EditorUtility.SetDirty(m_Terrain); - } - - void OnWizardCreate() - { - DoApply(); - } - - void OnWizardOtherButton() - { - DoApply(); - } - - protected override bool DrawWizardGUI() - { - EditorGUI.BeginChangeCheck(); - - bool allowSceneObjects = !EditorUtility.IsPersistent(m_Terrain.terrainData); // sometimes user prefers saving terrainData with the scene file - m_Tree = (GameObject)EditorGUILayout.ObjectField("Tree Prefab", m_Tree, typeof(GameObject), allowSceneObjects); - if (!TerrainEditorUtility.IsLODTreePrototype(m_Tree)) - m_BendFactor = EditorGUILayout.FloatField("Bend Factor", m_BendFactor); - - bool changed = EditorGUI.EndChangeCheck(); - - if (changed) - m_IsValidTree = IsValidTree(m_Tree, m_PrototypeIndex, m_Terrain); - return changed; - } - - internal override void OnWizardUpdate() - { - base.OnWizardUpdate(); - - if (m_Tree == null) - { - errorString = "Please assign a tree"; - isValid = false; - } - else if (!m_IsValidTree) - { - errorString = "Tree has already been selected as a prototype"; - isValid = false; - } - else if (m_PrototypeIndex != -1) - { - DoApply(); - } - } - } - - - enum DetailMeshRenderMode - { - VertexLit, - Grass - } - - class DetailMeshWizard : TerrainWizard - { - public GameObject m_Detail; - public float m_NoiseSpread; - public float m_MinWidth; - public float m_MaxWidth; - public float m_MinHeight; - public float m_MaxHeight; - public Color m_HealthyColor; - public Color m_DryColor; - public DetailMeshRenderMode m_RenderMode; - private int m_PrototypeIndex = -1; - - public void OnEnable() - { - minSize = new Vector2(400, 400); - } - - internal void InitializeDefaults(Terrain terrain, int index) - { - m_Terrain = terrain; - - m_PrototypeIndex = index; - DetailPrototype prototype; - if (m_PrototypeIndex == -1) - prototype = new DetailPrototype(); - else - prototype = m_Terrain.terrainData.detailPrototypes[m_PrototypeIndex]; - - m_Detail = prototype.prototype; - - m_NoiseSpread = prototype.noiseSpread; - m_MinWidth = prototype.minWidth; - m_MaxWidth = prototype.maxWidth; - m_MinHeight = prototype.minHeight; - m_MaxHeight = prototype.maxHeight; - m_HealthyColor = prototype.healthyColor; - m_DryColor = prototype.dryColor; - switch (prototype.renderMode) - { - case DetailRenderMode.GrassBillboard: - Debug.LogError("Detail meshes can't be rendered as billboards"); - m_RenderMode = DetailMeshRenderMode.Grass; - break; - case DetailRenderMode.Grass: - m_RenderMode = DetailMeshRenderMode.Grass; - break; - case DetailRenderMode.VertexLit: - m_RenderMode = DetailMeshRenderMode.VertexLit; - break; - } - - OnWizardUpdate(); - } - - void DoApply() - { - if (terrainData == null) - return; - DetailPrototype[] prototypes = m_Terrain.terrainData.detailPrototypes; - - if (m_PrototypeIndex == -1) - { - // Add a new detailprototype to the prototype arrays - DetailPrototype[] newarray = new DetailPrototype[prototypes.Length + 1]; - System.Array.Copy(prototypes, 0, newarray, 0, prototypes.Length); - m_PrototypeIndex = prototypes.Length; - - prototypes = newarray; - prototypes[m_PrototypeIndex] = new DetailPrototype(); - } - prototypes[m_PrototypeIndex].renderMode = DetailRenderMode.VertexLit; - prototypes[m_PrototypeIndex].usePrototypeMesh = true; - prototypes[m_PrototypeIndex].prototype = m_Detail; - prototypes[m_PrototypeIndex].prototypeTexture = null; - prototypes[m_PrototypeIndex].noiseSpread = m_NoiseSpread; - prototypes[m_PrototypeIndex].minWidth = m_MinWidth; - prototypes[m_PrototypeIndex].maxWidth = m_MaxWidth; - prototypes[m_PrototypeIndex].minHeight = m_MinHeight; - prototypes[m_PrototypeIndex].maxHeight = m_MaxHeight; - prototypes[m_PrototypeIndex].healthyColor = m_HealthyColor; - prototypes[m_PrototypeIndex].dryColor = m_DryColor; - - if (m_RenderMode == DetailMeshRenderMode.Grass) - prototypes[m_PrototypeIndex].renderMode = DetailRenderMode.Grass; - else - prototypes[m_PrototypeIndex].renderMode = DetailRenderMode.VertexLit; - - m_Terrain.terrainData.detailPrototypes = prototypes; - EditorUtility.SetDirty(m_Terrain); - } - - void OnWizardCreate() - { - DoApply(); - } - - void OnWizardOtherButton() - { - DoApply(); - } - - internal override void OnWizardUpdate() - { - base.OnWizardUpdate(); - - if (m_Detail == null) - { - errorString = "Please assign a detail prefab"; - isValid = false; - } - else if (m_PrototypeIndex != -1) - { - DoApply(); - } - } - } - - - class DetailTextureWizard : TerrainWizard - { - public Texture2D m_DetailTexture; - public float m_MinWidth; - public float m_MaxWidth; - public float m_MinHeight; - public float m_MaxHeight; - public float m_NoiseSpread; - public Color m_HealthyColor; - public Color m_DryColor; - public bool m_Billboard; - private int m_PrototypeIndex = -1; - - public void OnEnable() - { - minSize = new Vector2(400, 400); - } - - internal void InitializeDefaults(Terrain terrain, int index) - { - m_Terrain = terrain; - - m_PrototypeIndex = index; - DetailPrototype prototype; - if (m_PrototypeIndex == -1) - { - prototype = new DetailPrototype(); - prototype.renderMode = DetailRenderMode.GrassBillboard; - } - else - prototype = m_Terrain.terrainData.detailPrototypes[m_PrototypeIndex]; - - m_DetailTexture = prototype.prototypeTexture; - m_MinWidth = prototype.minWidth; - m_MaxWidth = prototype.maxWidth; - m_MinHeight = prototype.minHeight; - m_MaxHeight = prototype.maxHeight; - - m_NoiseSpread = prototype.noiseSpread; - m_HealthyColor = prototype.healthyColor; - m_DryColor = prototype.dryColor; - m_Billboard = prototype.renderMode == DetailRenderMode.GrassBillboard; - - OnWizardUpdate(); - } - - void DoApply() - { - if (terrainData == null) - return; - - DetailPrototype[] prototypes = m_Terrain.terrainData.detailPrototypes; - if (m_PrototypeIndex == -1) - { - // Add a new detailprototype to the prototype arrays - DetailPrototype[] newarray = new DetailPrototype[prototypes.Length + 1]; - System.Array.Copy(prototypes, 0, newarray, 0, prototypes.Length); - m_PrototypeIndex = prototypes.Length; - prototypes = newarray; - prototypes[m_PrototypeIndex] = new DetailPrototype(); - } - - prototypes[m_PrototypeIndex].prototype = null; - prototypes[m_PrototypeIndex].prototypeTexture = m_DetailTexture; - prototypes[m_PrototypeIndex].minWidth = m_MinWidth; - prototypes[m_PrototypeIndex].maxWidth = m_MaxWidth; - prototypes[m_PrototypeIndex].minHeight = m_MinHeight; - prototypes[m_PrototypeIndex].maxHeight = m_MaxHeight; - prototypes[m_PrototypeIndex].noiseSpread = m_NoiseSpread; - prototypes[m_PrototypeIndex].healthyColor = m_HealthyColor; - prototypes[m_PrototypeIndex].dryColor = m_DryColor; - prototypes[m_PrototypeIndex].renderMode = m_Billboard ? DetailRenderMode.GrassBillboard : DetailRenderMode.Grass; - prototypes[m_PrototypeIndex].usePrototypeMesh = false; - - m_Terrain.terrainData.detailPrototypes = prototypes; - EditorUtility.SetDirty(m_Terrain); - } - - void OnWizardCreate() - { - DoApply(); - } - - void OnWizardOtherButton() - { - DoApply(); - } - - internal override void OnWizardUpdate() - { - m_MinHeight = Mathf.Max(0f, m_MinHeight); - m_MaxHeight = Mathf.Max(m_MinHeight, m_MaxHeight); - m_MinWidth = Mathf.Max(0f, m_MinWidth); - m_MaxWidth = Mathf.Max(m_MinWidth, m_MaxWidth); - base.OnWizardUpdate(); - if (m_DetailTexture == null) - { - errorString = "Please assign a detail texture"; - isValid = false; - } - else if (m_PrototypeIndex != -1) - { - DoApply(); - } - } - } - - - class PlaceTreeWizard : TerrainWizard - { - public int numberOfTrees = 10000; - public bool keepExistingTrees = true; - private const int kMaxNumberOfTrees = 1000000; - - public void OnEnable() - { - minSize = new Vector2(250, 150); - } - - void OnWizardCreate() - { - if (numberOfTrees > kMaxNumberOfTrees) - { - isValid = false; - errorString = String.Format("Mass placing more than {0} trees is not supported", kMaxNumberOfTrees); - Debug.LogError(errorString); - return; - } - TreePainter.MassPlaceTrees(m_Terrain.terrainData, numberOfTrees, true, keepExistingTrees); - m_Terrain.Flush(); - } - } - - class FlattenHeightmap : TerrainWizard - { - public float height = 0.0F; - - internal override void OnWizardUpdate() - { - if (terrainData) - helpString = height + " meters (" + height / terrainData.size.y * 100 + "%)"; - } - - void OnWizardCreate() - { - Undo.RegisterCompleteObjectUndo(terrainData, "Flatten Heightmap"); - HeightmapFilters.Flatten(terrainData, height / terrainData.size.y); - } - } - - ///Shut up - internal class TerrainWizards {} - - /* - - class ImportTextureHeightmap : TerrainWizard - { - public Vector3 m_TerrainSize = new Vector3 (2000, 600, 2000); - public Texture2D m_Heightmap; - - /// Creates a heightmap from a heightmap texture and a given size of the terrrain - static public void ImportHeightmap (TerrainData theTerrain, Texture2D texture, Vector3 importSize) - { - theTerrain.ResetHeightmap(Mathf.Max(texture.width, texture.height)); - - // use clamp wrap mode. Avoid high tesselation at borders - TextureWrapMode wrapMode = texture.wrapMode; - texture.wrapMode = TextureWrapMode.Clamp; - // @TODO: - // if (texture.format != TextureFormat.Alpha8 && texture.format != TextureFormat.RGB24 && texture.format != TextureFormat.ARGB32 && texture.format != TextureFormat.RGBA32) { - // Debug.Log ("Heightmap texture must be an uncompressed texture"); - // return; - // } - - float[,] heights = new float[theTerrain.heightmapHeight, theTerrain.heightmapWidth]; - for (int y=0;y(); - mf.mesh = mesh; - go.AddComponent(); - - // Intialize - if (directions == null) - InitializeDirections(); - - // Calc weights for all directions - Vector4[] weights = new Vector4[directions.Length]; - for (int i = 0; i < directions.Length; i++) - { - weights[i] = new Vector4(GetWeight(1, directions[i]), GetWeight(2, directions[i]), GetWeight(3, directions[i]), GetWeight(0, directions[i])); - } - - Vector3[] verts = mesh.vertices; - Vector4[] sh = new Vector4[verts.Length]; - float totalW = 0; - for (int i = 0; i < verts.Length; i += 1) - { - Vector4 result = Vector4.zero; - Vector3 v = go.transform.TransformPoint(verts[i]); - - for (int j = 0; j < directions.Length; j++) - { - float occ = CountIntersections(v, go.transform.TransformDirection(directions[j]), 3); - occ = Mathf.Pow(occlusion, occ); - - result += weights[j] * occ; - } - result /= directions.Length; - totalW += result.w; - sh[i] = result; - } - totalW /= verts.Length; - for (int i = 0; i < verts.Length; i++) - sh[i].w -= totalW; - mesh.tangents = sh; - - Object.DestroyImmediate(go); - } - - static int CountIntersections(Vector3 v, Vector3 dist, float length) - { - v += dist * .01f; - if (!kDebug) - { - return Physics.RaycastAll(v, dist, length, 1 << kWorkLayer).Length + - Physics.RaycastAll(v + dist * length, -dist, length, 1 << kWorkLayer).Length; - } - - RaycastHit[] hits = Physics.RaycastAll(v, dist, length, 1 << kWorkLayer); - int hitLength = hits.Length; - float maxDist = 0; - if (hitLength > 0) - maxDist = hits[hits.Length - 1].distance; - - hits = Physics.RaycastAll(v + dist * length, -dist, length, 1 << kWorkLayer); - if (hits.Length > 0) - { - float len = length - hits[0].distance; - if (len > maxDist) - { - maxDist = len; - } - } - - return hitLength + hits.Length; - } - - static float GetWeight(int coeff, Vector3 dir) - { - switch (coeff) - { - case 0: // Just the constant - return .5f; // Average of all dimensions. - case 1: - return .5f * dir.x; - case 2: - return .5f * dir.y; - case 3: - return .5f * dir.z; - } - Debug.Log("Only defined up to 3"); - return 0; - } - } - - internal class TreeAOImporter : AssetPostprocessor - { - void OnPostprocessModel(GameObject root) - { - // Check if path contains "AO Tree" - string lowerPath = assetPath.ToLower(); - if (lowerPath.IndexOf("ambient-occlusion") != -1) - { - Component[] filters = root.GetComponentsInChildren(typeof(MeshFilter)); - foreach (MeshFilter filter in filters) - { - if (filter.sharedMesh != null) - { - Mesh mesh = filter.sharedMesh; - - // Calculate AO - TreeAO.CalcSoftOcclusion(mesh); - - // Calculate vertex colors for tree waving - Bounds bounds = mesh.bounds; - Color[] colors = mesh.colors; - Vector3[] vertices = mesh.vertices; - Vector4[] tangents = mesh.tangents; - if (colors.Length == 0) - { - colors = new Color[mesh.vertexCount]; - for (int i = 0; i < colors.Length; i++) - colors[i] = Color.white; - } - - float maxAO = 0.0F; - for (int i = 0; i < tangents.Length; i++) - maxAO = Mathf.Max(tangents[i].w, maxAO); - - float largest = 0.0F; - for (int i = 0; i < colors.Length; i++) - { - Vector2 offset = new Vector2(vertices[i].x, vertices[i].z); - float branch = offset.magnitude; - largest = Mathf.Max(branch, largest); - } - for (int i = 0; i < colors.Length; i++) - { - Vector2 offset = new Vector2(vertices[i].x, vertices[i].z); - float branch = offset.magnitude / largest; - - float height = (vertices[i].y - bounds.min.y) / bounds.size.y; - // colors[i].a = tangents[i].w * maxAO + height; - colors[i].a = (height * branch) * 0.6F + height * 0.5F; - } - mesh.colors = colors; - } - } - } - } - } -} //namespace diff --git a/Editor/Mono/TooltipView/TooltipView.cs b/Editor/Mono/TooltipView/TooltipView.cs deleted file mode 100644 index bd2542e7ad..0000000000 --- a/Editor/Mono/TooltipView/TooltipView.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; - -namespace UnityEditor -{ - class TooltipView : GUIView - { - private const float MAX_WIDTH = 300.0f; - - private GUIContent m_tooltip = new GUIContent(); - private Vector2 m_optimalSize; - private GUIStyle m_Style; - private Rect m_hoverRect; - - ContainerWindow m_tooltipContainer; - static TooltipView s_guiView; - - protected override void OnEnable() - { - base.OnEnable(); - s_guiView = this; - } - - protected override void OnDisable() - { - base.OnDisable(); - s_guiView = null; - } - - protected override void OldOnGUI() - { - if (m_tooltipContainer != null) - { - GUI.Box(new Rect(0, 0, m_optimalSize.x, m_optimalSize.y) , m_tooltip, m_Style); - } - } - - void Setup(string tooltip, Rect rect) - { - m_hoverRect = rect; - m_tooltip.text = tooltip; - - // Calculate size and position tooltip view - m_Style = EditorStyles.tooltip; - - m_Style.wordWrap = false; - m_optimalSize = m_Style.CalcSize(m_tooltip); - - if (m_optimalSize.x > MAX_WIDTH) - { - m_Style.wordWrap = true; - m_optimalSize.x = MAX_WIDTH; - m_optimalSize.y = m_Style.CalcHeight(m_tooltip, MAX_WIDTH); - } - - m_tooltipContainer.position = new Rect( - Mathf.Floor(m_hoverRect.x + (m_hoverRect.width / 2) - (m_optimalSize.x / 2)), - Mathf.Floor(m_hoverRect.y + (m_hoverRect.height) + 10.0f), - m_optimalSize.x, m_optimalSize.y); - - position = new Rect(0, 0, m_optimalSize.x, m_optimalSize.y); - - m_tooltipContainer.ShowPopup(); - m_tooltipContainer.SetAlpha(1.0f); - s_guiView.mouseRayInvisible = true; - - RepaintImmediately(); // Force repaint to fix that the tooltip text did sometimes not update (we did not get a new OnGUI if the rect had the same size) - } - - public static void Show(string tooltip, Rect rect) - { - if (s_guiView == null) - { - s_guiView = ScriptableObject.CreateInstance(); - s_guiView.m_tooltipContainer = ScriptableObject.CreateInstance(); - s_guiView.m_tooltipContainer.m_DontSaveToLayout = true; - s_guiView.m_tooltipContainer.rootView = s_guiView; - s_guiView.m_tooltipContainer.SetMinMaxSizes(new Vector2(10.0f, 10.0f), new Vector2(2000.0f, 2000.0f)); - } - - if (s_guiView.m_tooltip.text == tooltip && rect == s_guiView.m_hoverRect) - return; - - s_guiView.Setup(tooltip, rect); - } - - public static void Close() - { - if (s_guiView != null) - { - s_guiView.m_tooltipContainer.Close(); - } - } - - public static void SetAlpha(float percent) - { - if (s_guiView != null) - s_guiView.m_tooltipContainer.SetAlpha(percent); - } - } -} diff --git a/Editor/Mono/Troubleshooter/TroubleshooterWindow.cs b/Editor/Mono/Troubleshooter/TroubleshooterWindow.cs deleted file mode 100644 index f3a318d0a0..0000000000 --- a/Editor/Mono/Troubleshooter/TroubleshooterWindow.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEditor.Connect; -using UnityEditor.Web; -using UnityEngine; -using System.Diagnostics; -using System.IO; - -internal class TroubleshooterWindow : WebViewEditorWindow, IHasCustomMenu -{ - private WebView m_WebView; - - protected TroubleshooterWindow() : base() - { - m_InitialOpenURL = "https://bugservices.unity3d.com/troubleshooter/"; - } - - public new void OnInitScripting() - { - base.OnInitScripting(); - } - - internal override WebView webView - { - get { return m_WebView; } - set { m_WebView = value; } - } - - [MenuItem("Help/Troubleshoot Issue...", priority = 2000)] - public static void RunTroubleshooter() - { - TroubleshooterWindow window = EditorWindow.GetWindowWithRect(new Rect(100, 100, 990, 680), true, "Troubleshooter") as TroubleshooterWindow; - if (window != null) - { - window.ShowUtility(); - } - } -} diff --git a/Editor/Mono/Tutorial/Highlighter.cs b/Editor/Mono/Tutorial/Highlighter.cs deleted file mode 100644 index dea41cd895..0000000000 --- a/Editor/Mono/Tutorial/Highlighter.cs +++ /dev/null @@ -1,278 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; - - -namespace UnityEditor -{ - public partial class Highlighter - { - private static GUIView s_View; - private static HighlightSearchMode s_SearchMode; - private static float s_HighlightElapsedTime = 0; - private static float s_LastTime = 0; - private static Rect s_RepaintRegion; - - private const float kPulseSpeed = 0.45f; // Pulses per second - private const float kPopupDuration = 0.33f; // How long time in seconds the popup takes - private const int kExpansionMovementSize = 5; // How many pixels the rect expands out in the pulsing movement - - private static bool s_RecursionLock = false; - - private static GUIStyle s_HighlightStyle; - private static GUIStyle highlightStyle - { - get - { - if (s_HighlightStyle == null) - s_HighlightStyle = new GUIStyle("ControlHighlight"); - return s_HighlightStyle; - } - } - - // Public API - - public static void Stop() - { - active = false; - activeVisible = false; - activeText = string.Empty; - activeRect = new Rect(); - - s_LastTime = 0; - s_HighlightElapsedTime = 0; - } - - public static bool Highlight(string windowTitle, string text) - { - return Highlight(windowTitle, text, HighlightSearchMode.Auto); - } - - public static bool Highlight(string windowTitle, string text, HighlightSearchMode mode) - { - bool success = false; - if (s_RecursionLock || searching) - { - Debug.LogWarning("Highlighter recursion detected. You are calling Highlighter.Highlight() with too much abandon. Avoid highlighting during layout and repaint events."); - } - else if (Event.current != null && Event.current.type == EventType.Layout) - { - Debug.LogWarning("You are calling Highlighter.Highlight() inorrectly. Avoid highlighting during layout and repaint events."); - } - else - { - s_RecursionLock = true; - Stop(); - - if (!SetWindow(windowTitle)) - { - Debug.LogWarning("Window " + windowTitle + " not found."); - } - else if (mode != HighlightSearchMode.None) - { - active = true; - activeText = text; - s_SearchMode = mode; - s_LastTime = Time.realtimeSinceStartup; - - success = Search(); - if (success) - { - // Remove first to make sure it's not added more than once. - // Removing is ignored if not already assigned, so causes no harm. - EditorApplication.update -= Update; - EditorApplication.update += Update; - } - else - { - Debug.LogWarning("Item " + text + " not found in window " + windowTitle + "."); - Stop(); - } - - // Repaint all views regardless of success of search. - // Calling Highlight may have stopped a previous highlight in any case. - InternalEditorUtility.RepaintAllViews(); - } - s_RecursionLock = false; - } - return success; - } - - public static bool active { get; private set; } - - public static bool activeVisible - { - get { return internal_get_activeVisible(); } - private set { internal_set_activeVisible(value); } - } - - public static string activeText - { - get { return internal_get_activeText(); } - private set { internal_set_activeText(value); } - } - - public static Rect activeRect - { - get { return internal_get_activeRect(); } - private set { internal_set_activeRect(value); } - } - - public static void HighlightIdentifier(Rect position, string identifier) - { - if (searchMode == HighlightSearchMode.Identifier || - searchMode == HighlightSearchMode.Auto) - { - Handle(position, identifier); - } - } - - // Private API - - private static void Update() - { - Rect prevRect = activeRect; - - if (activeRect.width == 0 || s_View == null) - { - EditorApplication.update -= Update; - Stop(); - InternalEditorUtility.RepaintAllViews(); - return; - } - else - { - Search(); - } - - // Keep elapsed time explicitly rather than measuring time since highlight began. - // This way all views use the same elapsed time even if some realtime elapsed - // between redraws of the different views. - if (activeVisible) - s_HighlightElapsedTime += Time.realtimeSinceStartup - s_LastTime; - s_LastTime = Time.realtimeSinceStartup; - - // Calculate repaint region - Rect r = activeRect; - if (prevRect.width > 0) - { - // If the highlight rect moved, make the repaint region include both the old and new rect. - r.xMin = Mathf.Min(r.xMin, prevRect.xMin); - r.xMax = Mathf.Max(r.xMax, prevRect.xMax); - r.yMin = Mathf.Min(r.yMin, prevRect.yMin); - r.yMax = Mathf.Max(r.yMax, prevRect.yMax); - } - r = highlightStyle.padding.Add(r); - r = highlightStyle.overflow.Add(r); - r = new RectOffset(kExpansionMovementSize + 2, kExpansionMovementSize + 2, kExpansionMovementSize + 2, kExpansionMovementSize + 2).Add(r); - if (s_HighlightElapsedTime < kPopupDuration + 0.1f) - r = new RectOffset((int)r.width / 2, (int)r.width / 2, (int)r.height / 2, (int)r.height / 2).Add(r); - s_RepaintRegion = r; - - // Repaint all views regardless of success of search. - // If control disappeared we still need a repaint to hide it. - foreach (GUIView view in Resources.FindObjectsOfTypeAll(typeof(GUIView))) - { - // Only handle highlight in views in the same window as the view with the highlight is in. - if (view.window == s_View.window) - view.SendEvent(EditorGUIUtility.CommandEvent("HandleControlHighlight")); - } - } - - private static bool SetWindow(string windowTitle) - { - // Get window of type - Object[] views = Resources.FindObjectsOfTypeAll(typeof(GUIView)); - GUIView view = null; - foreach (GUIView currentView in views) - { - if (currentView is HostView) - { - if ((currentView as HostView).actualView.titleContent.text == windowTitle) - { - view = currentView; - break; - } - } - else if (currentView.window && currentView.GetType().Name == windowTitle) - { - view = currentView; - break; - } - } - - s_View = view; - return (view != null); - } - - private static bool Search() - { - searchMode = s_SearchMode; - s_View.RepaintImmediately(); - if (searchMode == HighlightSearchMode.None) - return true; // Success - control was found - - s_SearchMode = HighlightSearchMode.None; - Stop(); - return false; - } - - internal static void ControlHighlightGUI(GUIView self) - { - // Only handle highlight in views in the same window as the view with the highlight is in. - if (s_View == null || self.window != s_View.window) - return; - - if (!activeVisible || searching) - return; - - if (Event.current.type == EventType.ExecuteCommand && Event.current.commandName == "HandleControlHighlight") - { - if (self.screenPosition.Overlaps(s_RepaintRegion)) - self.Repaint(); - return; - } - - if (Event.current.type != EventType.Repaint) - return; - - Rect localRect = GUIUtility.ScreenToGUIRect(activeRect); - localRect = highlightStyle.padding.Add(localRect); - - // Animation calculations - - // Value pulses between 0 and 1 - float pulseValue = (Mathf.Cos(s_HighlightElapsedTime * Mathf.PI * 2 * kPulseSpeed) + 1) * 0.5f; - - // Value expands from 0.01 to 1 and stays at 1 - float popupScale = Mathf.Min(1, 0.01f + s_HighlightElapsedTime / kPopupDuration); - // Value goes from 0.01 towards 1, overshoots a bit, and ends at 1. - popupScale = popupScale + Mathf.Sin(popupScale * Mathf.PI) * 0.5f; - - // Scale calculations - Vector2 pulseScaleAddition = new Vector2( - (localRect.width + kExpansionMovementSize) / localRect.width - 1.0f, - (localRect.height + kExpansionMovementSize) / localRect.height - 1.0f - ) * pulseValue; - Vector2 scale = (Vector2.one + pulseScaleAddition) * popupScale; - - // Cache old values - Matrix4x4 oldMatrix = GUI.matrix; - Color oldColor = GUI.color; - - // Set pulsing values - GUI.color = new Color(1, 1, 1, Mathf.Clamp01(0.8f * popupScale - 0.3f * pulseValue)); - GUIUtility.ScaleAroundPivot(scale, localRect.center); - - // Draw highlight - highlightStyle.Draw(localRect, false, false, false, false); - - // Reset to old values - GUI.color = oldColor; - GUI.matrix = oldMatrix; - } - } -} diff --git a/Editor/Mono/TypeSystem/UnityType.bindings.cs b/Editor/Mono/TypeSystem/UnityType.bindings.cs deleted file mode 100644 index dcb1d5c576..0000000000 --- a/Editor/Mono/TypeSystem/UnityType.bindings.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditor -{ - [NativeHeader("Editor/Mono/TypeSystem/UnityType.bindings.h")] - internal partial class UnityType - { - #pragma warning disable 649 - [UsedByNativeCode] - private struct UnityTypeTransport - { - public uint runtimeTypeIndex; - public uint descendantCount; - public uint baseClassIndex; - public string className; - public string classNamespace; - public string module; - public int persistentTypeID; - public uint flags; - } - private static extern UnityTypeTransport[] Internal_GetAllTypes(); - } -} diff --git a/Editor/Mono/TypeSystem/UnityType.cs b/Editor/Mono/TypeSystem/UnityType.cs deleted file mode 100644 index ffbc649197..0000000000 --- a/Editor/Mono/TypeSystem/UnityType.cs +++ /dev/null @@ -1,130 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using UnityEngine; - -namespace UnityEditor -{ - // NOTE : Corresponds to the native TypeFlags - [Flags] - enum UnityTypeFlags - { - Abstract = 1 << 0, - Sealed = 1 << 1, - EditorOnly = 1 << 2 - } - - sealed partial class UnityType - { - public string name { get; private set; } - public string nativeNamespace { get; private set; } - public string module { get; private set; } - public int persistentTypeID { get; private set; } - public UnityType baseClass { get; private set; } - - public UnityTypeFlags flags { get; private set; } - - public bool isAbstract { get { return (flags & UnityTypeFlags.Abstract) != 0; } } - public bool isSealed { get { return (flags & UnityTypeFlags.Sealed) != 0; } } - public bool isEditorOnly { get { return (flags & UnityTypeFlags.EditorOnly) != 0; } } - - uint runtimeTypeIndex; - uint descendantCount; - - public string qualifiedName - { - get { return hasNativeNamespace ? nativeNamespace + "::" + name : name; } - } - - // NOTE : nativeNamespace == "" for types with no namespace so added this helper for convenience - // in case the caller wasn't sure whether to compare nativeNamespace with null or empty - public bool hasNativeNamespace - { - get { return nativeNamespace.Length > 0; } - } - - public bool IsDerivedFrom(UnityType baseClass) - { - // NOTE : Type indices are ordered so all derived classes are immediately following the - // base class allowing us to test inheritance with only a range check - return (runtimeTypeIndex - baseClass.runtimeTypeIndex) < baseClass.descendantCount; - } - - public static UnityType FindTypeByPersistentTypeID(int persistentTypeId) - { - UnityType result = null; - ms_idToType.TryGetValue(persistentTypeId, out result); - return result; - } - - public static uint TypeCount { get { return (uint)ms_types.Length; } } - - public static UnityType GetTypeByRuntimeTypeIndex(uint index) - { - return ms_types[index]; - } - - public static UnityType FindTypeByName(string name) - { - UnityType result = null; - ms_nameToType.TryGetValue(name, out result); - return result; - } - - public static UnityType FindTypeByNameCaseInsensitive(string name) - { - return ms_types.FirstOrDefault(t => string.Equals(name, t.name, StringComparison.OrdinalIgnoreCase)); - } - - public static ReadOnlyCollection GetTypes() - { - return ms_typesReadOnly; - } - - static UnityType() - { - var types = UnityType.Internal_GetAllTypes(); - - ms_types = new UnityType[types.Length]; - ms_idToType = new Dictionary(); - ms_nameToType = new Dictionary(); - - for (int i = 0; i < types.Length; ++i) - { - // Types are sorted so base < derived and null baseclass is passed from native as 0xffffffff - UnityType baseClass = null; - if (types[i].baseClassIndex < types.Length) - baseClass = ms_types[types[i].baseClassIndex]; - - var newType = new UnityType - { - runtimeTypeIndex = types[i].runtimeTypeIndex, - descendantCount = types[i].descendantCount, - name = types[i].className, - nativeNamespace = types[i].classNamespace, - module = types[i].module, - persistentTypeID = types[i].persistentTypeID, - baseClass = baseClass, - flags = (UnityTypeFlags)types[i].flags - }; - - Debug.Assert(types[i].runtimeTypeIndex == i); - - ms_types[i] = newType; - ms_typesReadOnly = new ReadOnlyCollection(ms_types); - ms_idToType[newType.persistentTypeID] = newType; - ms_nameToType[newType.name] = newType; - } - } - - static UnityType[] ms_types; - static ReadOnlyCollection ms_typesReadOnly; - static Dictionary ms_idToType; - static Dictionary ms_nameToType; - } -} diff --git a/Editor/Mono/UIElements/Controls/BaseCompositeField.cs b/Editor/Mono/UIElements/Controls/BaseCompositeField.cs deleted file mode 100644 index 125385f2f8..0000000000 --- a/Editor/Mono/UIElements/Controls/BaseCompositeField.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - public abstract class BaseCompoundField : BaseValueField - { - public class FieldDescription - { - public delegate void WriteDelegate(ref T val, double fieldValue); - - internal readonly string name; - internal readonly Func read; - internal readonly WriteDelegate write; - - public FieldDescription(string name, Func read, WriteDelegate write) - { - this.name = name; - this.read = read; - this.write = write; - } - } - - protected static FieldDescription[] s_FieldDescriptions; - protected List m_Fields; - - internal abstract FieldDescription[] DescribeFields(); - - protected BaseCompoundField() - { - AddToClassList("compositeField"); - if (s_FieldDescriptions == null) - s_FieldDescriptions = DescribeFields(); - - if (s_FieldDescriptions == null) - { - Debug.LogError("Describe fields MUST return a non null array of field descriptions"); - return; - } - - m_Fields = new List(s_FieldDescriptions.Length); - foreach (FieldDescription desc in s_FieldDescriptions) - { - var fieldContainer = new VisualElement(); - fieldContainer.AddToClassList("field"); - fieldContainer.Add(new Label(desc.name)); - var field = new DoubleField(); - fieldContainer.Add(field); - field.OnValueChanged(e => - { - T cur = value; - desc.write(ref cur, e.newValue); - SetValueAndNotify(cur); - }); - m_Fields.Add(field); - shadow.Add(fieldContainer); - } - UpdateDisplay(); - } - - public override VisualElement contentContainer - { - get { return null; } - } - - protected override void UpdateDisplay() - { - if (s_FieldDescriptions != null) - { - for (int i = 0; i < s_FieldDescriptions.Length; i++) - { - m_Fields[i].value = (s_FieldDescriptions[i].read(m_Value)); - } - } - } - - private DoubleField AddDoubleField(EventCallback> callback) - { - var field = new DoubleField(); - - shadow.Add(field); - field.OnValueChanged(callback); - return field; - } - } -} diff --git a/Editor/Mono/UIElements/Controls/BaseValueField.cs b/Editor/Mono/UIElements/Controls/BaseValueField.cs deleted file mode 100644 index 1b782c265e..0000000000 --- a/Editor/Mono/UIElements/Controls/BaseValueField.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - public abstract class BaseValueField : VisualElement, INotifyValueChanged - { - protected T m_Value; - - public T value - { - get { return m_Value; } - set - { - if (!EqualityComparer.Default.Equals(m_Value, value)) - { - m_Value = value; - UpdateDisplay(); - } - } - } - - protected abstract void UpdateDisplay(); - - public void SetValueAndNotify(T newValue) - { - if (!EqualityComparer.Default.Equals(m_Value, newValue)) - { - using (ChangeEvent evt = ChangeEvent.GetPooled(value, newValue)) - { - evt.target = this; - value = newValue; - UIElementsUtility.eventDispatcher.DispatchEvent(evt, panel); - } - } - } - - public void OnValueChanged(EventCallback> callback) - { - RegisterCallback(callback); - } - } -} diff --git a/Editor/Mono/UIElements/Controls/BoundsField.cs b/Editor/Mono/UIElements/Controls/BoundsField.cs deleted file mode 100644 index 9ced3351b1..0000000000 --- a/Editor/Mono/UIElements/Controls/BoundsField.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - public class BoundsField : BaseValueField - { - private Vector3Field m_CenterField; - private Vector3Field m_ExtentsField; - - public BoundsField() - { - m_CenterField = new Vector3Field(); - - m_CenterField.OnValueChanged(e => - { - Bounds current = value; - current.center = e.newValue; - SetValueAndNotify(current); - }); - - var centerGroup = new VisualElement(); - centerGroup.AddToClassList("group"); - centerGroup.Add(new Label("Center")); - centerGroup.Add(m_CenterField); - this.shadow.Add(centerGroup); - - m_ExtentsField = new Vector3Field(); - - m_ExtentsField.OnValueChanged(e => - { - Bounds current = value; - current.extents = e.newValue; - SetValueAndNotify(current); - }); - - var extentsGroup = new VisualElement(); - extentsGroup.AddToClassList("group"); - extentsGroup.contentContainer.Add(new Label("Extents")); - extentsGroup.contentContainer.Add(m_ExtentsField); - this.shadow.Add(extentsGroup); - } - - protected override void UpdateDisplay() - { - m_CenterField.value = m_Value.center; - m_ExtentsField.value = m_Value.extents; - } - } -} diff --git a/Editor/Mono/UIElements/Controls/ColorField.cs b/Editor/Mono/UIElements/Controls/ColorField.cs deleted file mode 100644 index f697765484..0000000000 --- a/Editor/Mono/UIElements/Controls/ColorField.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - public class ColorField : VisualElement, INotifyValueChanged - { - private Color m_Value; - - public Color value - { - get { return m_Value; } - set - { - m_Value = value; - Dirty(ChangeType.Repaint); - } - } - - public bool showEyeDropper { get; set; } - public bool showAlpha { get; set; } - public bool hdr { get; set; } - - private bool m_SetKbControl; - - public ColorField() - { - showEyeDropper = true; - showAlpha = true; - - var colorField = new IMGUIContainer(OnGUIHandler) { name = "InternalColorField" }; - Add(colorField); - } - - public void SetValueAndNotify(Color newValue) - { - if (value != newValue) - { - using (ChangeEvent evt = ChangeEvent.GetPooled(value, newValue)) - { - evt.target = this; - value = newValue; - UIElementsUtility.eventDispatcher.DispatchEvent(evt, panel); - } - } - } - - public void OnValueChanged(EventCallback> callback) - { - RegisterCallback(callback); - } - - protected internal override void ExecuteDefaultAction(EventBase evt) - { - base.ExecuteDefaultAction(evt); - - if (evt.GetEventTypeId() == FocusEvent.TypeId()) - m_SetKbControl = true; - } - - private void OnGUIHandler() - { - // Dirty repaint on eye dropper update to preview the color under the cursor - if (Event.current.type == EventType.ExecuteCommand && Event.current.commandName == EventCommandNames.EyeDropperUpdate) - { - Dirty(ChangeType.Repaint); - } - - Color newColor = EditorGUILayout.ColorField(GUIContent.none, value, showEyeDropper, showAlpha, hdr); - SetValueAndNotify(newColor); - if (m_SetKbControl) - { - GUIUtility.SetKeyboardControlToFirstControlId(); - m_SetKbControl = false; - } - } - } -} diff --git a/Editor/Mono/UIElements/Controls/CompoundFields.cs b/Editor/Mono/UIElements/Controls/CompoundFields.cs deleted file mode 100644 index a28fa1979e..0000000000 --- a/Editor/Mono/UIElements/Controls/CompoundFields.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor.Experimental.UIElements -{ - public class RectField : BaseCompoundField - { - internal override FieldDescription[] DescribeFields() - { - return new[] - { - new FieldDescription("X", r => r.x, (ref Rect r, double v) => r.x = (float)v), - new FieldDescription("Y", r => r.y, (ref Rect r, double v) => r.y = (float)v), - new FieldDescription("W", r => r.width, (ref Rect r, double v) => r.width = (float)v), - new FieldDescription("H", r => r.height, (ref Rect r, double v) => r.height = (float)v), - }; - } - } - - public class Vector2Field : BaseCompoundField - { - internal override FieldDescription[] DescribeFields() - { - return new[] - { - new FieldDescription("X", r => r.x, (ref Vector2 r, double v) => r.x = (float)v), - new FieldDescription("Y", r => r.y, (ref Vector2 r, double v) => r.y = (float)v), - }; - } - } - - public class Vector3Field : BaseCompoundField - { - internal override FieldDescription[] DescribeFields() - { - return new[] - { - new FieldDescription("X", r => r.x, (ref Vector3 r, double v) => r.x = (float)v), - new FieldDescription("Y", r => r.y, (ref Vector3 r, double v) => r.y = (float)v), - new FieldDescription("Z", r => r.z, (ref Vector3 r, double v) => r.z = (float)v), - }; - } - } - - public class Vector4Field : BaseCompoundField - { - internal override FieldDescription[] DescribeFields() - { - return new[] - { - new FieldDescription("X", r => r.x, (ref Vector4 r, double v) => r.x = (float)v), - new FieldDescription("Y", r => r.y, (ref Vector4 r, double v) => r.y = (float)v), - new FieldDescription("Z", r => r.z, (ref Vector4 r, double v) => r.z = (float)v), - new FieldDescription("W", r => r.w, (ref Vector4 r, double v) => r.w = (float)v), - }; - } - } -} diff --git a/Editor/Mono/UIElements/Controls/CurveField.cs b/Editor/Mono/UIElements/Controls/CurveField.cs deleted file mode 100644 index 7eb7255595..0000000000 --- a/Editor/Mono/UIElements/Controls/CurveField.cs +++ /dev/null @@ -1,233 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleSheets; - -namespace UnityEditor.Experimental.UIElements -{ - public class CurveField : VisualElement, INotifyValueChanged - { - private const string k_CurveColorProperty = "curve-color"; - public Rect ranges { get; set; } - - StyleValue m_CurveColor; - private Color curveColor - { - get - { - return m_CurveColor.GetSpecifiedValueOrDefault(Color.green); - } - } - - private bool m_ValueNull; - private AnimationCurve m_Value; - private bool m_TextureDirty; - - public AnimationCurve value - { - get - { - if (m_ValueNull) return null; - AnimationCurve curveCopy = new AnimationCurve(); - curveCopy.keys = m_Value.keys; - curveCopy.preWrapMode = m_Value.preWrapMode; - curveCopy.postWrapMode = m_Value.postWrapMode; - - return curveCopy; - } - set - { - //I need to have total ownership of the curve, I won't be able to know if it is changed outside. so I'm duplicating it. - - if (value != null || !m_ValueNull) // let's not reinitialize an initialized curve - { - m_ValueNull = value == null; - if (!m_ValueNull) - { - m_Value.keys = value.keys; - m_Value.preWrapMode = value.preWrapMode; - m_Value.postWrapMode = value.postWrapMode; - } - else - { - m_Value.keys = new Keyframe[0]; - m_Value.preWrapMode = WrapMode.Once; - m_Value.postWrapMode = WrapMode.Once; - } - } - m_TextureDirty = true; - - - Dirty(ChangeType.Repaint); - } - } - public CurveField() - { - ranges = Rect.zero; - - VisualElement borderElement = new VisualElement() { name = "border", pickingMode = PickingMode.Ignore }; - Add(borderElement); - - m_Value = new AnimationCurve(new Keyframe[0]); - } - - void OnDetach() - { - if (style.backgroundImage.value != null) - { - Object.DestroyImmediate(style.backgroundImage.value); - style.backgroundImage = null; - m_TextureDirty = true; - } - } - - public void SetValueAndNotify(AnimationCurve newValue) - { - using (ChangeEvent evt = ChangeEvent.GetPooled(value, newValue)) - { - evt.target = this; - value = newValue; - UIElementsUtility.eventDispatcher.DispatchEvent(evt, panel); - } - } - - public void OnValueChanged(EventCallback> callback) - { - RegisterCallback(callback); - } - - protected override void OnStyleResolved(ICustomStyle style) - { - base.OnStyleResolved(style); - - style.ApplyCustomProperty(k_CurveColorProperty, ref m_CurveColor); - } - - void OnCurveClick() - { - if (!enabledInHierarchy) - return; - - CurveEditorSettings settings = new CurveEditorSettings(); - if (m_Value == null) - m_Value = new AnimationCurve(); - CurveEditorWindow.curve = m_Value; - - CurveEditorWindow.color = curveColor; - CurveEditorWindow.instance.Show(OnCurveChanged, settings); - } - - protected internal override void ExecuteDefaultAction(EventBase evt) - { - base.ExecuteDefaultAction(evt); - - if (evt.GetEventTypeId() == MouseDownEvent.TypeId()) - OnCurveClick(); - else if (evt.GetEventTypeId() == DetachFromPanelEvent.TypeId()) - OnDetach(); - } - - void OnCurveChanged(AnimationCurve curve) - { - CurveEditorWindow.curve = m_Value; - SetValueAndNotify(m_Value); - } - - private void SendChangeEvent(AnimationCurve newValue) - { - using (ChangeEvent evt = ChangeEvent.GetPooled(value, newValue)) - { - evt.target = this; - value = newValue; - UIElementsUtility.eventDispatcher.DispatchEvent(evt, panel); - } - } - - public override void OnPersistentDataReady() - { - base.OnPersistentDataReady(); - m_TextureDirty = true; - } - - public override void DoRepaint() - { - if (m_TextureDirty) - { - m_TextureDirty = false; - int previewWidth = (int)layout.width; - int previewHeight = (int)layout.height; - - Rect rangeRect = new Rect(0, 0, 1, 1); - - if (ranges.width > 0 && ranges.height > 0) - { - rangeRect = ranges; - } - else if (!m_ValueNull && m_Value.keys.Length > 1) - { - float xMin = Mathf.Infinity; - float yMin = Mathf.Infinity; - float xMax = -Mathf.Infinity; - float yMax = -Mathf.Infinity; - - for (int i = 0; i < m_Value.keys.Length; ++i) - { - float y = m_Value.keys[i].value; - float x = m_Value.keys[i].time; - if (xMin > x) - { - xMin = x; - } - if (xMax < x) - { - xMax = x; - } - if (yMin > y) - { - yMin = y; - } - if (yMax < y) - { - yMax = y; - } - } - - if (yMin == yMax) - { - yMax = yMin + 1; - } - if (xMin == xMax) - { - xMax = xMin + 1; - } - - rangeRect = Rect.MinMaxRect(xMin, yMin, xMax, yMax); - } - - if (previewHeight > 0 && previewWidth > 0) - { - if (!m_ValueNull) - { - style.backgroundImage = AnimationCurvePreviewCache.GenerateCurvePreview( - previewWidth, - previewHeight, - rangeRect, - m_Value, - curveColor, - style.backgroundImage.value); - } - else - { - style.backgroundImage = null; - } - } - } - - base.DoRepaint(); - } - } -} diff --git a/Editor/Mono/UIElements/Controls/DoubleField.cs b/Editor/Mono/UIElements/Controls/DoubleField.cs deleted file mode 100644 index e3829a318c..0000000000 --- a/Editor/Mono/UIElements/Controls/DoubleField.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor.Experimental.UIElements -{ - public class DoubleField : TextValueField - { - internal static string allowedCharacters - { - get { return EditorGUI.s_AllowedCharactersForFloat; } - } - - public DoubleField() - : this(kMaxLengthNone) {} - - public DoubleField(int maxLength) - : base(maxLength) {} - - internal override bool AcceptCharacter(char c) - { - return c != 0 && allowedCharacters.IndexOf(c) != -1; - } - - public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, double startValue) - { - double sensitivity = NumericFieldDraggerUtility.CalculateFloatDragSensitivity(startValue); - float acceleration = NumericFieldDraggerUtility.Acceleration(speed == DeltaSpeed.Fast, speed == DeltaSpeed.Slow); - double v = value; - v += NumericFieldDraggerUtility.NiceDelta(delta, acceleration) * sensitivity; - v = MathUtils.RoundBasedOnMinimumDifference(v, sensitivity); - SetValueAndNotify(v); - } - - protected override string ValueToString(double v) - { - return v.ToString(formatString); - } - - protected override double StringToValue(string str) - { - double v; - EditorGUI.StringToDouble(str, out v); - return v; - } - } -} diff --git a/Editor/Mono/UIElements/Controls/EnumField.cs b/Editor/Mono/UIElements/Controls/EnumField.cs deleted file mode 100644 index 48796dbb44..0000000000 --- a/Editor/Mono/UIElements/Controls/EnumField.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - public class EnumField : BaseTextElement, INotifyValueChanged - { - private Type m_EnumType; - - private Enum m_Value; - public Enum value - { - get { return m_Value; } - set - { - if (m_Value != value) - { - m_Value = value; - text = m_Value.ToString(); - Dirty(ChangeType.Repaint); - } - } - } - - public EnumField(Enum defaultValue) - { - m_EnumType = defaultValue.GetType(); - value = defaultValue; - } - - public void SetValueAndNotify(Enum newValue) - { - if (value != newValue) - { - using (ChangeEvent evt = ChangeEvent.GetPooled(value, newValue)) - { - evt.target = this; - value = newValue; - UIElementsUtility.eventDispatcher.DispatchEvent(evt, panel); - } - } - } - - public void OnValueChanged(EventCallback> callback) - { - RegisterCallback(callback); - } - - protected internal override void ExecuteDefaultAction(EventBase evt) - { - base.ExecuteDefaultAction(evt); - - if (evt.GetEventTypeId() == MouseDownEvent.TypeId()) - OnMouseDown(); - } - - private void OnMouseDown() - { - var menu = new GenericMenu(); - - foreach (Enum item in Enum.GetValues(m_EnumType)) - { - bool isSelected = item.CompareTo(value) == 0; - menu.AddItem(new GUIContent(item.ToString()), isSelected, - contentView => ChangeValueFromMenu(contentView), - item); - } - - var menuPosition = new Vector2(0.0f, layout.height); - menuPosition = this.LocalToWorld(menuPosition); - var menuRect = new Rect(menuPosition, Vector2.zero); - menu.DropDown(menuRect); - } - - private void ChangeValueFromMenu(object menuItem) - { - SetValueAndNotify(menuItem as Enum); - } - } -} diff --git a/Editor/Mono/UIElements/Controls/GradientField.cs b/Editor/Mono/UIElements/Controls/GradientField.cs deleted file mode 100644 index 2a43ef0038..0000000000 --- a/Editor/Mono/UIElements/Controls/GradientField.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal; -using UnityEngine.Experimental.UIElements; -using UnityEditor.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleEnums; - -namespace UnityEditor.Experimental.UIElements -{ - public class GradientField : VisualElement, INotifyValueChanged - { - private bool m_ValueNull; - Gradient m_Value; - public Gradient value - { - get - { - if (m_ValueNull) return null; - Gradient gradientCopy = new Gradient(); - gradientCopy.colorKeys = m_Value.colorKeys; - gradientCopy.alphaKeys = m_Value.alphaKeys; - gradientCopy.mode = m_Value.mode; - - return m_Value; - } - set - { - if (value != null || !m_ValueNull) // let's not reinitialize an initialized gradient - { - m_ValueNull = value == null; - if (!m_ValueNull) - { - m_Value.colorKeys = value.colorKeys; - m_Value.alphaKeys = value.alphaKeys; - m_Value.mode = value.mode; - } - else // restore the internal gradient to the default state. - { - m_Value.colorKeys = new GradientColorKey[] { new GradientColorKey(Color.white, 0), new GradientColorKey(Color.white, 1) }; - m_Value.alphaKeys = new GradientAlphaKey[] { new GradientAlphaKey(1, 0), new GradientAlphaKey(1, 1) }; - m_Value.mode = GradientMode.Blend; - } - } - - UpdateGradientTexture(); - } - } - - public GradientField() - { - VisualElement borderElement = new VisualElement() { name = "border", pickingMode = PickingMode.Ignore }; - Add(borderElement); - - m_Value = new Gradient(); - } - - protected internal override void ExecuteDefaultAction(EventBase evt) - { - base.ExecuteDefaultAction(evt); - - if (evt.GetEventTypeId() == MouseDownEvent.TypeId()) - OnClick(); - else if (evt.GetEventTypeId() == DetachFromPanelEvent.TypeId()) - OnDetach(); - else if (evt.GetEventTypeId() == AttachToPanelEvent.TypeId()) - OnAttach(); - } - - void OnDetach() - { - if (style.backgroundImage.value != null) - { - Object.DestroyImmediate(style.backgroundImage.value); - style.backgroundImage = null; - } - } - - void OnAttach() - { - UpdateGradientTexture(); - } - - void OnClick() - { - GradientPicker.Show(m_Value, true, OnGradientChanged); - } - - public override void OnPersistentDataReady() - { - base.OnPersistentDataReady(); - UpdateGradientTexture(); - } - - void UpdateGradientTexture() - { - if (m_ValueNull) - { - style.backgroundImage = null; - } - else - { - Texture2D gradientTexture = UnityEditorInternal.GradientPreviewCache.GenerateGradientPreview(value, style.backgroundImage.value); - - style.backgroundImage = gradientTexture; - } - } - - void OnGradientChanged(Gradient newValue) - { - SetValueAndNotify(newValue); - - GradientPreviewCache.ClearCache(); // needed because GradientEditor itself uses the cache and will no invalidate it on changes. - Dirty(ChangeType.Repaint); - } - - public void SetValueAndNotify(Gradient newValue) - { - using (ChangeEvent evt = ChangeEvent.GetPooled(value, newValue)) - { - evt.target = this; - value = newValue; - UIElementsUtility.eventDispatcher.DispatchEvent(evt, panel); - } - } - - public void OnValueChanged(EventCallback> callback) - { - RegisterCallback(callback); - } - - public override void DoRepaint() - { - //Start by drawing the checkerboard background for alpha gradients. - Texture2D backgroundTexture = GradientEditor.GetBackgroundTexture(); - var painter = elementPanel.stylePainter; - var painterParams = painter.GetDefaultTextureParameters(this); - painterParams.texture = backgroundTexture; - painter.DrawTexture(painterParams); - - base.DoRepaint(); - } - } -} diff --git a/Editor/Mono/UIElements/Controls/IntegerField.cs b/Editor/Mono/UIElements/Controls/IntegerField.cs deleted file mode 100644 index 4ce4215572..0000000000 --- a/Editor/Mono/UIElements/Controls/IntegerField.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; - -namespace UnityEditor.Experimental.UIElements -{ - public class IntegerField : TextValueField - { - internal static string allowedCharacters - { - get { return EditorGUI.s_AllowedCharactersForInt; } - } - - public IntegerField() - : this(kMaxLengthNone) {} - - public IntegerField(int maxLength) - : base(maxLength) - { - } - - internal override bool AcceptCharacter(char c) - { - return c != 0 && allowedCharacters.IndexOf(c) != -1; - } - - public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, long startValue) - { - double sensitivity = NumericFieldDraggerUtility.CalculateIntDragSensitivity(startValue); - float acceleration = NumericFieldDraggerUtility.Acceleration(speed == DeltaSpeed.Fast, speed == DeltaSpeed.Slow); - long v = value; - v += (long)Math.Round(NumericFieldDraggerUtility.NiceDelta(delta, acceleration) * sensitivity); - SetValueAndNotify(v); - } - - protected override string ValueToString(long v) - { - return v.ToString(formatString); - } - - protected override long StringToValue(string str) - { - long v; - EditorGUI.StringToLong(text, out v); - return v; - } - } -} diff --git a/Editor/Mono/UIElements/Controls/ObjectField.cs b/Editor/Mono/UIElements/Controls/ObjectField.cs deleted file mode 100644 index 3e1479491c..0000000000 --- a/Editor/Mono/UIElements/Controls/ObjectField.cs +++ /dev/null @@ -1,231 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEngine.Experimental.UIElements; -using Object = UnityEngine.Object; - -namespace UnityEditor.Experimental.UIElements -{ - public class ObjectField : VisualElement, INotifyValueChanged - { - private Object m_Value; - public Object value - { - get - { - return m_Value; - } - set - { - if (m_Value != value) - { - m_Value = value; - m_ObjectFieldDisplay.Update(); - } - } - } - - private Type m_objectType; - - public Type objectType - { - get { return m_objectType; } - set - { - if (m_objectType != value) - { - m_objectType = value; - m_ObjectFieldDisplay.Update(); - } - } - } - - public bool allowSceneObjects { get; set; } - - private class ObjectFieldDisplay : VisualElement - { - private readonly ObjectField m_ObjectField; - private readonly Image m_ObjectIcon; - private readonly Label m_ObjectLabel; - - public ObjectFieldDisplay(ObjectField objectField) - { - m_ObjectIcon = new Image {scaleMode = ScaleMode.ScaleAndCrop, pickingMode = PickingMode.Ignore}; - m_ObjectLabel = new Label {pickingMode = PickingMode.Ignore}; - m_ObjectField = objectField; - - Update(); - - Add(m_ObjectIcon); - Add(m_ObjectLabel); - } - - public void Update() - { - GUIContent content = EditorGUIUtility.ObjectContent(m_ObjectField.value, m_ObjectField.objectType); - m_ObjectIcon.image = content.image; - m_ObjectLabel.text = content.text; - } - - protected internal override void ExecuteDefaultActionAtTarget(EventBase evt) - { - base.ExecuteDefaultActionAtTarget(evt); - - if (evt.GetEventTypeId() == MouseDownEvent.TypeId()) - OnMouseDown(); - else if (evt.GetEventTypeId() == IMGUIEvent.TypeId()) - OnIMGUI(evt); - else if (evt.GetEventTypeId() == MouseLeaveEvent.TypeId()) - OnMouseLeave(); - } - - private void OnMouseLeave() - { - // Make sure we've cleared the accept drop look, whether we we in a drop operation or not. - RemoveFromClassList("acceptDrop"); - } - - private void OnMouseDown() - { - Object actualTargetObject = m_ObjectField.value; - Component com = actualTargetObject as Component; - if (com) - actualTargetObject = com.gameObject; - - // One click shows where the referenced object is, or pops up a preview - if (Event.current.clickCount == 1) - { - PingObject(actualTargetObject); - } - // Double click opens the asset in external app or changes selection to referenced object - else if (Event.current.clickCount == 2) - { - if (actualTargetObject) - { - AssetDatabase.OpenAsset(actualTargetObject); - GUIUtility.ExitGUI(); - } - } - } - - private void OnIMGUI(EventBase evt) - { - if (evt.imguiEvent.type == EventType.DragUpdated || evt.imguiEvent.type == EventType.DragPerform) - { - Object[] references = DragAndDrop.objectReferences; - Object validatedObject = EditorGUI.ValidateObjectFieldAssignment(references, m_ObjectField.objectType, null, EditorGUI.ObjectFieldValidatorOptions.None); - - if (validatedObject != null) - { - // If scene objects are not allowed and object is a scene object then clear - if (!m_ObjectField.allowSceneObjects && !EditorUtility.IsPersistent(validatedObject)) - validatedObject = null; - } - - if (validatedObject != null) - { - DragAndDrop.visualMode = DragAndDropVisualMode.Generic; - if (evt.imguiEvent.type == EventType.DragPerform) - { - m_ObjectField.SetValueAndNotify(validatedObject); - - DragAndDrop.AcceptDrag(); - - evt.StopPropagation(); - - RemoveFromClassList("acceptDrop"); - } - else - { - AddToClassList("acceptDrop"); - } - } - } - } - - private void PingObject(Object targetObject) - { - if (targetObject == null) - return; - - Event evt = Event.current; - // ping object - bool anyModifiersPressed = evt.shift || evt.control; - if (!anyModifiersPressed) - { - EditorGUIUtility.PingObject(targetObject); - } - } - } - - private class ObjectFieldSelector : VisualElement - { - private readonly ObjectField m_ObjectField; - - public ObjectFieldSelector(ObjectField objectField) - { - m_ObjectField = objectField; - } - - protected internal override void ExecuteDefaultAction(EventBase evt) - { - base.ExecuteDefaultAction(evt); - - if (evt.GetEventTypeId() == MouseDownEvent.TypeId()) - OnMouseDown(); - } - - private void OnMouseDown() - { - ObjectSelector.get.Show(m_ObjectField.value, m_ObjectField.objectType, null, m_ObjectField.allowSceneObjects, null, m_ObjectField.OnObjectChanged, m_ObjectField.OnObjectChanged); - } - } - - private readonly ObjectFieldDisplay m_ObjectFieldDisplay; - - public ObjectField() - { - allowSceneObjects = true; - - m_ObjectFieldDisplay = new ObjectFieldDisplay(this) {focusIndex = 0}; - var objectSelector = new ObjectFieldSelector(this); - - Add(m_ObjectFieldDisplay); - Add(objectSelector); - } - - public void SetValueAndNotify(Object newValue) - { - if (newValue != value) - { - using (ChangeEvent evt = ChangeEvent.GetPooled(value, newValue)) - { - evt.target = this; - value = newValue; - UIElementsUtility.eventDispatcher.DispatchEvent(evt, panel); - } - } - } - - public void OnValueChanged(EventCallback> callback) - { - RegisterCallback(callback); - } - - protected internal override void ExecuteDefaultAction(EventBase evt) - { - base.ExecuteDefaultAction(evt); - - if (evt.GetEventTypeId() == FocusEvent.TypeId()) - m_ObjectFieldDisplay.Focus(); - } - - private void OnObjectChanged(Object obj) - { - SetValueAndNotify(obj); - } - } -} diff --git a/Editor/Mono/UIElements/Controls/PopupField.cs b/Editor/Mono/UIElements/Controls/PopupField.cs deleted file mode 100644 index 31b8266d99..0000000000 --- a/Editor/Mono/UIElements/Controls/PopupField.cs +++ /dev/null @@ -1,132 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - public class PopupField : BaseTextElement, INotifyValueChanged - { - private readonly List m_PossibleValues; - - private T m_Value; - public T value - { - get { return m_Value; } - set - { - if (EqualityComparer.Default.Equals(m_Value, value)) - return; - - if (!m_PossibleValues.Contains(value)) - throw new ArgumentException(string.Format("Value {0} is not present in the list of possible values", value)); - - m_Value = value; - m_Index = m_PossibleValues.IndexOf(m_Value); - text = m_Value.ToString(); - Dirty(ChangeType.Repaint); - } - } - - private int m_Index = -1; - public int index - { - get { return m_Index; } - set - { - if (value != m_Index) - { - if (value >= m_PossibleValues.Count || value < 0) - throw new ArgumentException(string.Format("Index {0} is beyond the scope of possible value", value)); - m_Index = value; - this.value = m_PossibleValues[m_Index]; - } - } - } - - private PopupField(List possibleValues) - { - if (possibleValues == null) - throw new ArgumentNullException("possibleValues can't be null"); - - m_PossibleValues = possibleValues; - - AddToClassList("popupField"); - } - - public PopupField(List possibleValues, T defaultValue) : - this(possibleValues) - { - if (defaultValue == null) - throw new ArgumentNullException("defaultValue can't be null"); - - if (!m_PossibleValues.Contains(defaultValue)) - throw new ArgumentException(string.Format("Default value {0} is not present in the list of possible values", defaultValue)); - - // note: idx will be set when setting value - value = defaultValue; - } - - public PopupField(List possibleValues, int defaultIndex) : - this(possibleValues) - { - if (defaultIndex >= m_PossibleValues.Count || defaultIndex < 0) - throw new ArgumentException(string.Format("Default Index {0} is beyond the scope of possible value", value)); - - // note: value will be set when setting idx - index = defaultIndex; - } - - public void SetValueAndNotify(T newValue) - { - if (!EqualityComparer.Default.Equals(newValue, value)) - { - using (ChangeEvent evt = ChangeEvent.GetPooled(value, newValue)) - { - evt.target = this; - value = newValue; - UIElementsUtility.eventDispatcher.DispatchEvent(evt, panel); - } - } - } - - public void OnValueChanged(EventCallback> callback) - { - RegisterCallback(callback); - } - - protected internal override void ExecuteDefaultAction(EventBase evt) - { - base.ExecuteDefaultAction(evt); - - if (evt.GetEventTypeId() == MouseDownEvent.TypeId()) - OnMouseDown(); - } - - private void OnMouseDown() - { - var menu = new GenericMenu(); - - foreach (T item in m_PossibleValues) - { - bool isSelected = EqualityComparer.Default.Equals(item, value); - menu.AddItem(new GUIContent(item.ToString()), isSelected, - () => ChangeValueFromMenu(item)); - } - - var menuPosition = new Vector2(0.0f, layout.height); - menuPosition = this.LocalToWorld(menuPosition); - var menuRect = new Rect(menuPosition, Vector2.zero); - menu.DropDown(menuRect); - } - - private void ChangeValueFromMenu(T menuItem) - { - SetValueAndNotify(menuItem); - } - } -} diff --git a/Editor/Mono/UIElements/Controls/TextValueField.cs b/Editor/Mono/UIElements/Controls/TextValueField.cs deleted file mode 100644 index c7217584c5..0000000000 --- a/Editor/Mono/UIElements/Controls/TextValueField.cs +++ /dev/null @@ -1,102 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - public enum DeltaSpeed - { - Fast, - Normal, - Slow - } - - public interface IValueField - { - T value { get; set; } - - void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, T startValue); - } - - // Implements a control with a value of type T backed by a text. - public abstract class TextValueField : TextInputFieldBase, INotifyValueChanged, IValueField - { - protected TextValueField(int maxLength) - : base(maxLength, Char.MinValue) - { - } - - public void OnValueChanged(EventCallback> callback) - { - RegisterCallback(callback); - } - - protected T m_Value; - - public T value - { - get { return m_Value; } - set - { - m_Value = value; - text = ValueToString(m_Value); - } - } - - public void UpdateValueFromText() - { - T newValue = StringToValue(text); - SetValueAndNotify(newValue); - } - - public void SetValueAndNotify(T newValue) - { - if (!EqualityComparer.Default.Equals(value, newValue)) - { - using (ChangeEvent evt = ChangeEvent.GetPooled(value, newValue)) - { - evt.target = this; - value = newValue; - UIElementsUtility.eventDispatcher.DispatchEvent(evt, panel); - } - } - } - - public string formatString { get; set; } - - public abstract void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, T startValue); - - protected abstract string ValueToString(T value); - - protected abstract T StringToValue(string str); - - protected internal override void ExecuteDefaultActionAtTarget(EventBase evt) - { - base.ExecuteDefaultActionAtTarget(evt); - - if (evt.GetEventTypeId() == KeyDownEvent.TypeId()) - { - KeyDownEvent kde = evt as KeyDownEvent; - if (kde.character == '\n') - { - UpdateValueFromText(); - } - } - } - - protected internal override void ExecuteDefaultAction(EventBase evt) - { - base.ExecuteDefaultAction(evt); - - if (evt.GetEventTypeId() == BlurEvent.TypeId()) - { - UpdateValueFromText(); - } - } - } -} diff --git a/Editor/Mono/UIElements/Controls/UXMLEditorFactories.cs b/Editor/Mono/UIElements/Controls/UXMLEditorFactories.cs deleted file mode 100644 index 7baac68598..0000000000 --- a/Editor/Mono/UIElements/Controls/UXMLEditorFactories.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - internal class UXMLEditorFactories - { - private static bool s_Registered; - - internal static void RegisterAll() - { - if (s_Registered) - return; - - s_Registered = true; - - // Primitives - Factories.RegisterFactory((bag, __) => new DoubleField()); - Factories.RegisterFactory((bag, __) => new IntegerField()); - Factories.RegisterFactory((bag, __) => new CurveField()); - Factories.RegisterFactory((bag, __) => new ObjectField()); - Factories.RegisterFactory((bag, __) => new ColorField()); - - // Compounds - Factories.RegisterFactory((bag, __) => new RectField()); - Factories.RegisterFactory((bag, __) => new Vector2Field()); - Factories.RegisterFactory((bag, __) => new Vector3Field()); - Factories.RegisterFactory((bag, __) => new Vector4Field()); - Factories.RegisterFactory((bag, __) => new BoundsField()); - } - } -} diff --git a/Editor/Mono/UIElements/EditorContextualMenuManager.cs b/Editor/Mono/UIElements/EditorContextualMenuManager.cs deleted file mode 100644 index 1cec1f8f5d..0000000000 --- a/Editor/Mono/UIElements/EditorContextualMenuManager.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - internal class EditorContextualMenuManager : ContextualMenuManager - { - public override void DisplayMenuIfEventMatches(EventBase evt, IEventHandler eventHandler) - { - if (evt.GetEventTypeId() == MouseUpEvent.TypeId()) - { - MouseUpEvent e = evt as MouseUpEvent; - if (e.button == (int)MouseButton.RightMouse) - { - DisplayMenu(evt, eventHandler); - evt.StopPropagation(); - } - } - else if (evt.GetEventTypeId() == KeyUpEvent.TypeId()) - { - KeyUpEvent e = evt as KeyUpEvent; - if (e.keyCode == KeyCode.Menu) - { - DisplayMenu(evt, eventHandler); - evt.StopPropagation(); - } - } - } - - protected override void DoDisplayMenu(ContextualMenu menu, EventBase triggerEvent) - { - var genericMenu = new GenericMenu(); - foreach (var item in menu.MenuItems()) - { - var action = item as ContextualMenu.MenuAction; - if (action != null) - { - if ((action.status & ContextualMenu.MenuAction.StatusFlags.Hidden) == ContextualMenu.MenuAction.StatusFlags.Hidden) - { - continue; - } - - bool isChecked = (action.status & ContextualMenu.MenuAction.StatusFlags.Checked) == ContextualMenu.MenuAction.StatusFlags.Checked; - - if ((action.status & ContextualMenu.MenuAction.StatusFlags.Disabled) == ContextualMenu.MenuAction.StatusFlags.Disabled) - { - genericMenu.AddDisabledItem(new GUIContent(action.name)); - } - else - { - genericMenu.AddItem(new GUIContent(action.name), isChecked, () => - { - action.Execute(triggerEvent); - }); - } - } - else - { - genericMenu.AddSeparator(string.Empty); - } - } - - Vector2 position = Vector2.zero; - if (triggerEvent is IMouseEvent) - { - position = ((IMouseEvent)triggerEvent).mousePosition; - } - else if (triggerEvent.target is VisualElement) - { - position = ((VisualElement)triggerEvent.target).layout.center; - } - - genericMenu.DropDown(new Rect(position, Vector2.zero)); - } - } -} diff --git a/Editor/Mono/UIElements/EditorCursor.cs b/Editor/Mono/UIElements/EditorCursor.cs deleted file mode 100644 index ad61caf205..0000000000 --- a/Editor/Mono/UIElements/EditorCursor.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - internal class EditorCursorManager : ICursorManager - { - public void SetCursor(CursorStyle cursor) - { - if (cursor.texture != null) - { - EditorGUIUtility.SetCurrentViewCursor(cursor.texture, cursor.hotspot, MouseCursor.CustomCursor); - } - else - { - EditorGUIUtility.SetCurrentViewCursor(null, Vector2.zero, (MouseCursor)cursor.defaultCursorId); - } - } - - public void ResetCursor() - { - EditorGUIUtility.ClearCurrentViewCursor(); - } - } -} diff --git a/Editor/Mono/UIElements/EditorWindowPersistentViewData.cs b/Editor/Mono/UIElements/EditorWindowPersistentViewData.cs deleted file mode 100644 index fd08ee761d..0000000000 --- a/Editor/Mono/UIElements/EditorWindowPersistentViewData.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using UnityEditor; -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - [LibraryFolderPath("UIElements/EditorWindows")] - internal class EditorWindowPersistentViewData : ScriptableSingletonDictionary< - EditorWindowPersistentViewData, - SerializableJsonDictionary> - { - public static SerializableJsonDictionary GetEditorData(EditorWindow window) - { - string editorPrefFileName = window.GetType().ToString(); - return instance[editorPrefFileName]; - } - } -} diff --git a/Editor/Mono/UIElements/Events/TooltipEvent.cs b/Editor/Mono/UIElements/Events/TooltipEvent.cs deleted file mode 100644 index 4a7ccfc096..0000000000 --- a/Editor/Mono/UIElements/Events/TooltipEvent.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - class TooltipEvent : EventBase, IPropagatableEvent - { - public string tooltip { get; set; } - public Rect rect { get; set; } - } -} diff --git a/Editor/Mono/UIElements/FieldMouseDragger.cs b/Editor/Mono/UIElements/FieldMouseDragger.cs deleted file mode 100644 index ea625bc514..0000000000 --- a/Editor/Mono/UIElements/FieldMouseDragger.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - public class FieldMouseDragger - { - public FieldMouseDragger(IValueField drivenField) - { - m_DrivenField = drivenField; - m_DragElement = null; - m_DragHotZone = new Rect(0, 0, -1, -1); - dragging = false; - } - - IValueField m_DrivenField; - VisualElement m_DragElement; - Rect m_DragHotZone; - - public bool dragging; - public T startValue; - - public void SetDragZone(VisualElement dragElement) - { - SetDragZone(dragElement, new Rect(0, 0, -1, -1)); - } - - public void SetDragZone(VisualElement dragElement, Rect hotZone) - { - if (m_DragElement != null) - { - m_DragElement.UnregisterCallback(UpdateValueOnMouseDown); - m_DragElement.UnregisterCallback(UpdateValueOnMouseMove); - m_DragElement.UnregisterCallback(UpdateValueOnMouseUp); - m_DragElement.UnregisterCallback(UpdateValueOnKeyDown); - } - - m_DragElement = dragElement; - m_DragHotZone = hotZone; - - if (m_DragElement != null) - { - dragging = false; - m_DragElement.RegisterCallback(UpdateValueOnMouseDown); - m_DragElement.RegisterCallback(UpdateValueOnMouseMove); - m_DragElement.RegisterCallback(UpdateValueOnMouseUp); - m_DragElement.RegisterCallback(UpdateValueOnKeyDown); - } - } - - void UpdateValueOnMouseDown(MouseDownEvent evt) - { - Rect dragHotZone; - if (m_DragHotZone.width < 0 || m_DragHotZone.height < 0) - { - dragHotZone = m_DragElement.localBound; - } - else - { - dragHotZone = m_DragHotZone; - } - - if (evt.button == 0 && dragHotZone.Contains(m_DragElement.WorldToLocal(evt.mousePosition))) - { - m_DragElement.TakeMouseCapture(); - - dragging = true; - startValue = m_DrivenField.value; - - EditorGUIUtility.SetWantsMouseJumping(1); - } - } - - void UpdateValueOnMouseMove(MouseMoveEvent evt) - { - if (dragging) - { - DeltaSpeed s = evt.shiftKey ? DeltaSpeed.Fast : (evt.altKey ? DeltaSpeed.Slow : DeltaSpeed.Normal); - m_DrivenField.ApplyInputDeviceDelta(evt.mouseDelta, s, startValue); - } - } - - void UpdateValueOnMouseUp(MouseUpEvent evt) - { - if (dragging) - { - dragging = false; - MouseCaptureController.ReleaseMouseCapture(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - } - - void UpdateValueOnKeyDown(KeyDownEvent evt) - { - if (dragging && evt.keyCode == KeyCode.Escape) - { - dragging = false; - m_DrivenField.value = startValue; - MouseCaptureController.ReleaseMouseCapture(); - EditorGUIUtility.SetWantsMouseJumping(0); - } - } - } -} diff --git a/Editor/Mono/UIElements/SerializableJsonDictionary.cs b/Editor/Mono/UIElements/SerializableJsonDictionary.cs deleted file mode 100644 index 7f1107f8c5..0000000000 --- a/Editor/Mono/UIElements/SerializableJsonDictionary.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEngine.Experimental.UIElements; - -namespace UnityEditor.Experimental.UIElements -{ - internal class SerializableJsonDictionary : ScriptableObject, ISerializationCallbackReceiver, ISerializableJsonDictionary - { - [SerializeField] - private List m_Keys = new List(); - - [SerializeField] - private List m_Values = new List(); - - [NonSerialized] - private Dictionary m_Dict = new Dictionary(); - - public void Set(string key, T value) where T : class - { - m_Dict[key] = value; - } - - public T Get(string key) where T : class - { - if (!ContainsKey(key)) - return null; - - if (m_Dict[key] is string) - { - T obj = Activator.CreateInstance(); - EditorJsonUtility.FromJsonOverwrite((string)m_Dict[key], obj); - m_Dict[key] = obj; - } - - return m_Dict[key] as T; - } - - public T GetScriptable(string key) where T : ScriptableObject - { - if (!ContainsKey(key)) - return null; - - if (m_Dict[key] is string) - { - var newObject = ScriptableObject.CreateInstance(); - EditorJsonUtility.FromJsonOverwrite((string)m_Dict[key], newObject); - m_Dict[key] = newObject; - } - - return m_Dict[key] as T; - } - - public void Overwrite(object obj, string key) - { - if (!ContainsKey(key)) - return; - - if (m_Dict[key] is string) - { - EditorJsonUtility.FromJsonOverwrite((string)m_Dict[key], obj); - m_Dict[key] = obj; - } - else if (m_Dict[key] != obj) - { - // If the dict. value has already been expanded but it's not - // the same instance as the obj being passed in, we need to - // copy the serialized data from the object in the dict to the - // obj passed in and then fix the dict reference to point - // to the obj. - string json = EditorJsonUtility.ToJson(m_Dict[key]); - EditorJsonUtility.FromJsonOverwrite(json, obj); - m_Dict[key] = obj; - } - } - - public bool ContainsKey(string key) - { - return m_Dict.ContainsKey(key); - } - - public void OnBeforeSerialize() - { - m_Keys.Clear(); - m_Values.Clear(); - - foreach (var data in m_Dict) - { - if (data.Key != null && data.Value != null) - { - m_Keys.Add(data.Key); - m_Values.Add(EditorJsonUtility.ToJson(data.Value)); - } - } - } - - public void OnAfterDeserialize() - { - if (m_Keys.Count == m_Values.Count) - { - m_Dict = Enumerable.Range(0, m_Keys.Count).ToDictionary(i => m_Keys[i], i => m_Values[i] as object); - } - - m_Keys.Clear(); - m_Values.Clear(); - } - } -} diff --git a/Editor/Mono/UIElements/Tooltip.cs b/Editor/Mono/UIElements/Tooltip.cs deleted file mode 100644 index e3bc4b1213..0000000000 --- a/Editor/Mono/UIElements/Tooltip.cs +++ /dev/null @@ -1,91 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleEnums; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; - -namespace UnityEditor.Experimental.UIElements -{ - internal static class TooltipExtension - { - [RequiredByNativeCode] - internal static void SetTooltip(float mouseX, float mouseY) - { - //mouseX,mouseY are screen relative. - GUIView view = GUIView.mouseOverView; - if (view != null && view.visualTree != null && view.visualTree.panel != null) - { - var panel = view.visualTree.panel; - - // Pick expect view relative coordinates. - VisualElement target = panel.Pick(new Vector2(mouseX, mouseY) - view.screenPosition.position); - if (target != null) - { - using (var tooltipEvent = TooltipEvent.GetPooled()) - { - tooltipEvent.target = target; - tooltipEvent.tooltip = null; - tooltipEvent.rect = Rect.zero; - view.visualTree.panel.dispatcher.DispatchEvent(tooltipEvent, panel); - - if (!string.IsNullOrEmpty(tooltipEvent.tooltip)) - { - Rect rect = tooltipEvent.rect; - rect.position += view.screenPosition.position; //SetMouseTooltip expects Screen relative coordinates. - - GUIStyle.SetMouseTooltip(tooltipEvent.tooltip, rect); - } - } - } - } - } - - internal static void AddTooltip(this VisualElement e, string tooltip) - { - if (string.IsNullOrEmpty(tooltip)) - { - RemoveTooltip(e); - return; - } - TooltipElement tooltipElement = e.Query().Children(); - - if (tooltipElement == null) - tooltipElement = new TooltipElement(); - - tooltipElement.style.positionType = PositionType.Absolute; - tooltipElement.style.positionLeft = tooltipElement.style.positionRight = tooltipElement.style.positionTop = tooltipElement.style.positionBottom = 0; - - tooltipElement.tooltip = tooltip; - - e.Add(tooltipElement); - } - - internal static void RemoveTooltip(this VisualElement e) - { - TooltipElement tooltipElement = e.Query().Children(); - if (tooltipElement != null) - e.Remove(tooltipElement); - } - } - - - class TooltipElement : VisualElement - { - public string tooltip { get; set; } - - public TooltipElement() - { - RegisterCallback(OnTooltip); - } - - void OnTooltip(TooltipEvent e) - { - e.tooltip = tooltip; - e.rect = worldBound; - e.StopPropagation(); - } - } -} diff --git a/Editor/Mono/UIElements/UIElementsEditorUtility.cs b/Editor/Mono/UIElements/UIElementsEditorUtility.cs deleted file mode 100644 index c5ce1d09d7..0000000000 --- a/Editor/Mono/UIElements/UIElementsEditorUtility.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Experimental.UIElements; -using UnityEngine.Experimental.UIElements.StyleSheets; -using UnityEngine.StyleSheets; -using StyleSheet = UnityEngine.StyleSheets.StyleSheet; - -namespace UnityEditor.Experimental.UIElements -{ - public static class UIElementsEditorUtility - { - internal static readonly string s_DefaultCommonStyleSheetPath = "StyleSheets/DefaultCommon.uss"; - internal static readonly string s_DefaultCommonDarkStyleSheetPath = "StyleSheets/DefaultCommonDark.uss"; - internal static readonly string s_DefaultCommonLightStyleSheetPath = "StyleSheets/DefaultCommonLight.uss"; - - public static CursorStyle CreateDefaultCursorStyle(MouseCursor mouseCursor) - { - return new CursorStyle() { texture = null, hotspot = Vector2.zero, defaultCursorId = (int)mouseCursor }; - } - - internal static CursorStyle CreateDefaultCursorStyle(StyleSheet sheet, StyleValueHandle handle) - { - int type = StyleSheetCache.GetEnumValue(sheet, handle); - CursorStyle cursor = new CursorStyle() { texture = null, hotspot = Vector2.zero, defaultCursorId = type }; - return cursor; - } - - internal static void AddDefaultEditorStyleSheets(VisualElement p) - { - if (p.styleSheets == null) - { - p.AddStyleSheetPath(s_DefaultCommonStyleSheetPath); - if (EditorGUIUtility.isProSkin) - { - p.AddStyleSheetPath(s_DefaultCommonDarkStyleSheetPath); - } - else - { - p.AddStyleSheetPath(s_DefaultCommonLightStyleSheetPath); - } - } - } - - internal static void ForceDarkStyleSheet(VisualElement ele) - { - if (!EditorGUIUtility.isProSkin) - { - var e = ele; - while (e != null) - { - if (e.HasStyleSheetPath(s_DefaultCommonLightStyleSheetPath)) - { - e.ReplaceStyleSheetPath(s_DefaultCommonLightStyleSheetPath, s_DefaultCommonDarkStyleSheetPath); - break; - } - e = e.parent; - } - } - } - } -} diff --git a/Editor/Mono/UIElements/UIElementsViewImporter.cs b/Editor/Mono/UIElements/UIElementsViewImporter.cs deleted file mode 100644 index 0c4a9a447b..0000000000 --- a/Editor/Mono/UIElements/UIElementsViewImporter.cs +++ /dev/null @@ -1,527 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml; -using System.Xml.Linq; -using ExCSS; -using UnityEditor.Experimental.AssetImporters; -using UnityEditor.StyleSheets; -using UnityEngine; -using UnityEngine.Experimental.UIElements; -using StyleSheet = UnityEngine.StyleSheets.StyleSheet; - -namespace UnityEditor.Experimental.UIElements -{ - [ScriptedImporter(3, "uxml", 0)] - internal class UIElementsViewImporter : ScriptedImporter - { - private const string k_XmlTemplate = "<" + k_TemplateNode + @" xmlns:ui=""UnityEngine.Experimental.UIElements""> - -"; - - [MenuItem("Assets/Create/UIElements View")] - public static void CreateTemplateMenuItem() - { - ProjectWindowUtil.CreateAssetWithContent("New UXML.uxml", k_XmlTemplate, EditorGUIUtility.FindTexture("UxmlScript Icon")); - } - - internal struct Error - { - public readonly Level level; - public readonly ImportErrorType error; - public readonly ImportErrorCode code; - public readonly object context; - public readonly string filePath; - public readonly IXmlLineInfo xmlLineInfo; - - public enum Level - { - Info, - Warning, - Fatal, - } - - public Error(ImportErrorType error, ImportErrorCode code, object context, Level level, string filePath, IXmlLineInfo xmlLineInfo) - { - this.xmlLineInfo = xmlLineInfo; - this.error = error; - this.code = code; - this.context = context; - this.level = level; - this.filePath = filePath; - } - - private static string ErrorMessage(ImportErrorCode errorCode) - { - switch (errorCode) - { - case ImportErrorCode.InvalidXml: - return "Xml is not valid, exception during parsing: {0}"; - case ImportErrorCode.InvalidRootElement: - return "Expected the XML Root element name to be '" + k_TemplateNode + "', found '{0}'"; - case ImportErrorCode.UsingHasEmptyAlias: - return "'" + k_UsingNode + "' declaration requires a non-empty '" + k_UsingAliasAttr + "' attribute"; - case ImportErrorCode.MissingPathAttributeOnUsing: - return "'" + k_UsingNode + "' declaration requires a '" + k_UsingPathAttr + "' attribute referencing another uxml file"; - case ImportErrorCode.DuplicateUsingAlias: - return "Duplicate alias '{0}'"; - case ImportErrorCode.UnknownElement: - return "Unknown element name '{0}'"; - case ImportErrorCode.UnknownAttribute: - return "Unknown attribute: '{0}'"; - case ImportErrorCode.InvalidCssInStyleAttribute: - return "USS in 'style' attribute is invalid: {0}"; - case ImportErrorCode.StyleReferenceEmptyOrMissingPathAttr: - return "USS in 'style' attribute is invalid: {0}"; - case ImportErrorCode.DuplicateSlotDefinition: - return "Slot definition '{0}' is defined more than once"; - case ImportErrorCode.SlotUsageInNonTemplate: - return "Element has an assigned slot, but its parent '{0}' is not a template reference"; - case ImportErrorCode.SlotDefinitionHasEmptyName: - return "Slot definition has an empty name"; - case ImportErrorCode.SlotUsageHasEmptyName: - return "Slot usage has an empty name"; - case ImportErrorCode.DuplicateContentContainer: - return "'contentContainer' attribute must be defined once at most"; - default: - throw new ArgumentOutOfRangeException("Unhandled error code " + errorCode); - } - } - - public override string ToString() - { - string message = ErrorMessage(code); - string lineInfo = xmlLineInfo == null ? "" : string.Format(" ({0},{1})", xmlLineInfo.LineNumber, xmlLineInfo.LinePosition); - return string.Format("{0}{1}: {2} - {3}", filePath, lineInfo, error, string.Format(message, context == null ? "" : context.ToString())); - } - } - - internal class DefaultLogger - { - protected List m_Errors = new List(); - protected string m_Path; - - internal virtual void LogError(ImportErrorType error, ImportErrorCode code, object context, Error.Level level, IXmlLineInfo xmlLineInfo) - { - m_Errors.Add(new Error(error, code, context, level, m_Path, xmlLineInfo)); - } - - internal virtual void BeginImport(string path) - { - m_Path = path; - } - - private void LogError(VisualTreeAsset obj, Error error) - { - try - { - switch (error.level) - { - case Error.Level.Info: - Debug.LogFormat(obj, error.ToString()); - break; - case Error.Level.Warning: - Debug.LogWarningFormat(obj, error.ToString()); - break; - case Error.Level.Fatal: - Debug.LogErrorFormat(obj, error.ToString()); - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - catch (FormatException) - { - switch (error.level) - { - case Error.Level.Info: - Debug.Log(error.ToString()); - break; - case Error.Level.Warning: - Debug.LogWarning(error.ToString()); - break; - case Error.Level.Fatal: - Debug.LogError(error.ToString()); - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - } - - internal virtual void FinishImport() - { - Dictionary cache = new Dictionary(); - - foreach (var error in m_Errors) - { - VisualTreeAsset obj; - if (!cache.TryGetValue(error.filePath, out obj)) - cache.Add(error.filePath, obj = AssetDatabase.LoadAssetAtPath(error.filePath)); - - LogError(obj, error); - } - - m_Errors.Clear(); - } - } - - private const StringComparison k_Comparison = StringComparison.InvariantCulture; - private const string k_TemplateNode = "UXML"; - private const string k_UsingNode = "Using"; - private const string k_UsingAliasAttr = "alias"; - private const string k_UsingPathAttr = "path"; - private const string k_StyleReferenceNode = "Style"; - private const string k_StylePathAttr = "path"; - private const string k_SlotDefinitionAttr = "slot-name"; - private const string k_SlotUsageAttr = "slot"; - - internal static DefaultLogger logger = new DefaultLogger(); - - public override void OnImportAsset(AssetImportContext args) - { - logger.BeginImport(args.assetPath); - VisualTreeAsset vta; - ImportXml(args.assetPath, out vta); - - args.AddObjectToAsset("tree", vta); - args.SetMainObject(vta); - - if (!vta.inlineSheet) - vta.inlineSheet = ScriptableObject.CreateInstance(); - - args.AddObjectToAsset("inlineStyle", vta.inlineSheet); - } - - internal static void ImportXml(string xmlPath, out VisualTreeAsset vta) - { - vta = ScriptableObject.CreateInstance(); - vta.visualElementAssets = new List(); - vta.templateAssets = new List(); - - XDocument doc; - - try - { - doc = XDocument.Load(xmlPath, LoadOptions.SetLineInfo); - } - catch (Exception e) - { - logger.LogError(ImportErrorType.Syntax, ImportErrorCode.InvalidXml, e, Error.Level.Fatal, null); - return; - } - - StyleSheetBuilder ssb = new StyleSheetBuilder(); - LoadXmlRoot(doc, vta, ssb); - - StyleSheet inlineSheet = ScriptableObject.CreateInstance(); - inlineSheet.name = "inlineStyle"; - ssb.BuildTo(inlineSheet); - vta.inlineSheet = inlineSheet; - } - - private static void LoadXmlRoot(XDocument doc, VisualTreeAsset vta, StyleSheetBuilder ssb) - { - XElement elt = doc.Root; - if (!string.Equals(elt.Name.LocalName, k_TemplateNode, k_Comparison)) - { - logger.LogError(ImportErrorType.Semantic, - ImportErrorCode.InvalidRootElement, - elt.Name, - Error.Level.Fatal, - elt); - return; - } - - foreach (var child in elt.Elements()) - { - switch (child.Name.LocalName) - { - case k_UsingNode: - LoadUsingNode(vta, elt, child); - break; - default: - LoadXml(child, null, vta, ssb); - continue; - } - } - } - - private static void LoadUsingNode(VisualTreeAsset vta, XElement elt, XElement child) - { - bool hasPath = false; - string alias = null; - string path = null; - foreach (var xAttribute in child.Attributes()) - { - switch (xAttribute.Name.LocalName) - { - case k_UsingPathAttr: - hasPath = true; - path = xAttribute.Value; - break; - case k_UsingAliasAttr: - alias = xAttribute.Value; - if (alias == String.Empty) - { - logger.LogError(ImportErrorType.Semantic, - ImportErrorCode.UsingHasEmptyAlias, - child, - Error.Level.Fatal, - child - ); - } - break; - default: - logger.LogError(ImportErrorType.Semantic, - ImportErrorCode.UnknownAttribute, - xAttribute.Name.LocalName, - Error.Level.Fatal, - child - ); - break; - } - } - - if (!hasPath) - { - logger.LogError(ImportErrorType.Semantic, - ImportErrorCode.MissingPathAttributeOnUsing, - null, - Error.Level.Fatal, - elt - ); - return; - } - - if (String.IsNullOrEmpty(alias)) - alias = Path.GetFileNameWithoutExtension(path); - - if (vta.AliasExists(alias)) - { - logger.LogError(ImportErrorType.Semantic, - ImportErrorCode.DuplicateUsingAlias, - alias, - Error.Level.Fatal, - elt - ); - return; - } - - vta.RegisterUsing(alias, path); - } - - private static void LoadXml(XElement elt, VisualElementAsset parent, VisualTreeAsset vta, StyleSheetBuilder ssb) - { - VisualElementAsset vea; - - if (!ResolveType(elt, vta, out vea)) - { - logger.LogError(ImportErrorType.Semantic, ImportErrorCode.UnknownElement, elt.Name.LocalName, Error.Level.Fatal, elt); - return; - } - - var parentId = (parent == null ? 0 : parent.id); - - // id includes the parent id, meaning it's dependent on the whole direct hierarchy - int id = (parentId << 1) ^ vea.GetHashCode(); - vea.parentId = parentId; - vea.id = id; - - bool startedRule = ParseAttributes(elt, vea, ssb, vta, parent); - - // each vea will creates 0 or 1 style rule, with one or more properties - // they don't have selectors and are directly referenced by index - // it's then applied during tree cloning - vea.ruleIndex = startedRule ? ssb.EndRule() : -1; - if (vea is TemplateAsset) - vta.templateAssets.Add((TemplateAsset)vea); - else - vta.visualElementAssets.Add(vea); - - if (elt.HasElements) - { - foreach (XElement child in elt.Elements()) - { - if (child.Name.LocalName == k_StyleReferenceNode) - LoadStyleReferenceNode(vea, child); - else - LoadXml(child, vea, vta, ssb); - } - } - } - - private static void LoadStyleReferenceNode(VisualElementAsset vea, XElement styleElt) - { - XAttribute pathAttr = styleElt.Attribute(k_StylePathAttr); - if (pathAttr == null || String.IsNullOrEmpty(pathAttr.Value)) - { - logger.LogError(ImportErrorType.Semantic, ImportErrorCode.StyleReferenceEmptyOrMissingPathAttr, null, Error.Level.Warning, styleElt); - return; - } - vea.stylesheets.Add(pathAttr.Value); - } - - private static bool ResolveType(XElement elt, VisualTreeAsset visualTreeAsset, out VisualElementAsset vea) - { - string fullName; - if (visualTreeAsset.AliasExists(elt.Name.LocalName)) - { - vea = new TemplateAsset(elt.Name.LocalName); - } - else - { - fullName = String.IsNullOrEmpty(elt.Name.NamespaceName) - ? elt.Name.LocalName - : elt.Name.NamespaceName + "." + elt.Name.LocalName; - - // HACK: wait for Theo's PR OR go with that - if (fullName == typeof(VisualElement).FullName) - fullName = typeof(VisualContainer).FullName; - vea = new VisualElementAsset(fullName); - } - - return true; - } - - private static bool ParseAttributes(XElement elt, VisualElementAsset res, StyleSheetBuilder ssb, VisualTreeAsset vta, VisualElementAsset parent) - { - // underscore means "unnamed element but it would not look pretty in the project window without one" - res.name = "_" + res.GetType().Name; - - bool startedRule = false; - - foreach (XAttribute xattr in elt.Attributes()) - { - string attrName = xattr.Name.LocalName; - - // start with special cases - switch (attrName) - { - case "name": - res.name = xattr.Value; - continue; - case "text": - res.text = xattr.Value; - continue; - case "class": - res.classes = xattr.Value.Split(' '); - continue; - case "contentContainer": - if (vta.contentContainerId != 0) - { - logger.LogError(ImportErrorType.Semantic, ImportErrorCode.DuplicateContentContainer, null, Error.Level.Fatal, elt); - continue; - } - vta.contentContainerId = res.id; - continue; - case k_SlotDefinitionAttr: - if (String.IsNullOrEmpty(xattr.Value)) - logger.LogError(ImportErrorType.Semantic, ImportErrorCode.SlotDefinitionHasEmptyName, null, Error.Level.Fatal, elt); - else if (!vta.AddSlotDefinition(xattr.Value, res.id)) - logger.LogError(ImportErrorType.Semantic, ImportErrorCode.DuplicateSlotDefinition, xattr.Value, Error.Level.Fatal, elt); - continue; - case k_SlotUsageAttr: - var templateAsset = parent as TemplateAsset; - if (!(templateAsset != null)) - { - logger.LogError(ImportErrorType.Semantic, ImportErrorCode.SlotUsageInNonTemplate, parent, Error.Level.Fatal, elt); - continue; - } - if (string.IsNullOrEmpty(xattr.Value)) - { - logger.LogError(ImportErrorType.Semantic, ImportErrorCode.SlotUsageHasEmptyName, null, Error.Level.Fatal, elt); - continue; - } - templateAsset.AddSlotUsage(xattr.Value, res.id); - continue; - case "style": - ExCSS.StyleSheet parsed = new Parser().Parse("* { " + xattr.Value + " }"); - if (parsed.Errors.Count != 0) - { - logger.LogError( - ImportErrorType.Semantic, - ImportErrorCode.InvalidCssInStyleAttribute, - parsed.Errors.Aggregate("", (s, error) => s + error.ToString() + "\n"), - Error.Level.Warning, - xattr); - continue; - } - if (parsed.StyleRules.Count != 1) - { - logger.LogError( - ImportErrorType.Semantic, - ImportErrorCode.InvalidCssInStyleAttribute, - "Expected one style rule, found " + parsed.StyleRules.Count, - Error.Level.Warning, - xattr); - continue; - } - ssb.BeginRule(-1); - startedRule = true; - StyleSheetImportErrors errors = new StyleSheetImportErrors(); - foreach (Property prop in parsed.StyleRules[0].Declarations) - { - ssb.BeginProperty(prop.Name); - StyleSheetImporterImpl.VisitValue(errors, ssb, prop.Term); - ssb.EndProperty(); - } - - // Don't call ssb.EndRule() here, it's done in LoadXml to get the rule index at the same time ! - continue; - case "pickingMode": - if (!Enum.IsDefined(typeof(PickingMode), xattr.Value)) - { - Debug.LogErrorFormat("Could not parse value of '{0}', because it isn't defined in the PickingMode enum.", xattr.Value); - continue; - } - res.pickingMode = (PickingMode)Enum.Parse(typeof(PickingMode), xattr.Value); - continue; - } - - res.AddProperty(xattr.Name.LocalName, xattr.Value); - } - return startedRule; - } - } - - internal enum ImportErrorCode - { - InvalidRootElement, - DuplicateUsingAlias, - UnknownElement, - UnknownAttribute, - InvalidXml, - InvalidCssInStyleAttribute, - MissingPathAttributeOnUsing, - UsingHasEmptyAlias, - StyleReferenceEmptyOrMissingPathAttr, - DuplicateSlotDefinition, - SlotUsageInNonTemplate, - SlotDefinitionHasEmptyName, - SlotUsageHasEmptyName, - DuplicateContentContainer - } - - internal enum ImportErrorType - { - Syntax, - Semantic, - Other, - Internal, - } - - static class XmlExtensions - { - public static string AttributeValue(this XElement elt, string attributeName) - { - var attr = elt.Attribute(attributeName); - return attr == null ? null : attr.Value; - } - } -} diff --git a/Editor/Mono/UIElements/VisualTreeAssetEditor.cs b/Editor/Mono/UIElements/VisualTreeAssetEditor.cs deleted file mode 100644 index c6f3f7842a..0000000000 --- a/Editor/Mono/UIElements/VisualTreeAssetEditor.cs +++ /dev/null @@ -1,126 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; -using UnityEngine.Experimental.UIElements; -using Object = UnityEngine.Object; - -namespace UnityEditor.Experimental.UIElements -{ - [CustomEditor(typeof(VisualTreeAsset))] - internal class VisualTreeAssetEditor : Editor - { - private Panel m_Panel; - private VisualElement m_Tree; - private VisualTreeAsset m_LastTree; - private Texture2D m_FileTypeIcon; - - protected void OnEnable() - { - m_FileTypeIcon = EditorGUIUtility.FindTexture("UxmlScript Icon"); - } - - protected void OnDestroy() - { - m_Panel = null; - UIElementsUtility.RemoveCachedPanel(m_LastTree.GetInstanceID()); - } - - // hack to avoid null references when a scriptedImporter runs and replaces the current selection - internal override string targetTitle - { - get - { - if (!target) - { - serializedObject.Update(); - InternalSetTargets(serializedObject.targetObjects); - } - return base.targetTitle; - } - } - - public override bool HasPreviewGUI() - { - return true; - } - - public override GUIContent GetPreviewTitle() - { - return GUIContent.Temp(targetTitle); - } - - private void RenderIcon(Rect iconRect) - { - Debug.Assert(m_FileTypeIcon != null); - GUI.DrawTexture(iconRect, m_FileTypeIcon, ScaleMode.ScaleToFit); - } - - public void Render(VisualTreeAsset vta, Rect r, GUIStyle background) - { - if (Event.current.type != EventType.Repaint || r.width < 100 && r.height < 100) - return; - - bool dirty = false; - if (vta != m_LastTree || !m_LastTree) - { - m_LastTree = vta; - m_Tree = vta.CloneTree(null); - m_Tree.StretchToParentSize(); - dirty = true; - } - - if (m_Panel == null) - { - UXMLEditorFactories.RegisterAll(); - m_Panel = UIElementsUtility.FindOrCreatePanel(m_LastTree, ContextType.Editor, new DataWatchService()); - if (m_Panel.visualTree.styleSheets == null) - { - UIElementsEditorUtility.AddDefaultEditorStyleSheets(m_Panel.visualTree); - m_Panel.visualTree.LoadStyleSheetsFromPaths(); - } - m_Panel.allowPixelCaching = false; - dirty = true; - } - - if (dirty) - { - m_Panel.visualTree.Clear(); - m_Panel.visualTree.Add(m_Tree); - } - - EditorGUI.DrawRect(r, EditorGUIUtility.isProSkin ? EditorGUIUtility.kDarkViewBackground : HostView.kViewColor); - - m_Panel.visualTree.layout = GUIClip.UnclipToWindow(r); - - m_Panel.visualTree.Dirty(ChangeType.Layout); - m_Panel.visualTree.Dirty(ChangeType.Repaint); - - var oldState = SavedGUIState.Create(); - int clips = GUIClip.Internal_GetCount(); - while (clips > 0) - { - GUIClip.Pop(); - clips--; - } - - m_Panel.Repaint(Event.current); - - oldState.ApplyAndForget(); - } - - public override void OnPreviewGUI(Rect r, GUIStyle background) - { - const int k_IconSize = 64; - - base.OnPreviewGUI(r, background); - if (r.width > k_IconSize || r.height > k_IconSize) - Render(target as VisualTreeAsset, r, background); - else - RenderIcon(r); - } - } -} diff --git a/Editor/Mono/Undo/UndoWindow.cs b/Editor/Mono/Undo/UndoWindow.cs deleted file mode 100644 index 62060c04cc..0000000000 --- a/Editor/Mono/Undo/UndoWindow.cs +++ /dev/null @@ -1,91 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections; -using System.Collections.Generic; -using System.IO; - -namespace UnityEditor -{ - internal class UndoWindow : EditorWindow - { - private List undos = new List(); - private List redos = new List(); - - // Used for caching, this way lists won't be recreated every time - private List newUndos = new List(); - private List newRedos = new List(); - - private Vector2 undosScroll = Vector2.zero; - private Vector2 redosScroll = Vector2.zero; - - internal static void Init() - { - EditorWindow wnd = GetWindow(typeof(UndoWindow)); - wnd.titleContent = EditorGUIUtility.TrTextContent("Undo"); - } - - private void Update() - { - Undo.GetRecords(newUndos, newRedos); - bool equal = undos.SequenceEqual(newUndos) && redos.SequenceEqual(newRedos); - - if (equal) - return; - - undos = new List(newUndos); - redos = new List(newRedos); - - Repaint(); - } - - private void OnGUI() - { - GUILayout.Label("(Available only in Developer builds)", EditorStyles.boldLabel); - float height = position.height - 60.0f; - float width = position.width * 0.5f - 5.0f; - int i; - GUILayout.BeginHorizontal(); - - GUILayout.BeginVertical(); - GUILayout.Label("Undos"); - undosScroll = GUILayout.BeginScrollView(undosScroll, EditorStyles.helpBox, new GUILayoutOption[] - { - GUILayout.MinHeight(height), - GUILayout.MinWidth(width) - }); - - i = 0; - foreach (var undo in undos) - { - GUILayout.Label(string.Format("[{0}] - {1}", i++, undo)); - } - GUILayout.EndScrollView(); - GUILayout.EndVertical(); - - GUILayout.BeginVertical(); - GUILayout.Label("Redos"); - redosScroll = GUILayout.BeginScrollView(redosScroll, EditorStyles.helpBox, new GUILayoutOption[] - { - GUILayout.MinHeight(height), - GUILayout.MinWidth(width) - }); - - i = 0; - foreach (var redo in redos) - { - GUILayout.Label(string.Format("[{0}] - {1}", i++, redo)); - } - GUILayout.EndScrollView(); - GUILayout.EndVertical(); - - GUILayout.EndHorizontal(); - } - } -} diff --git a/Editor/Mono/UnityConnect/CloudProjectSettings.cs b/Editor/Mono/UnityConnect/CloudProjectSettings.cs deleted file mode 100644 index 56e5bc4064..0000000000 --- a/Editor/Mono/UnityConnect/CloudProjectSettings.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Connect; - -namespace UnityEditor -{ - public class CloudProjectSettings - { - public static string userId - { - get - { - return UnityConnect.instance.GetUserId(); - } - } - - public static string userName - { - get - { - return UnityConnect.instance.GetUserName(); - } - } - - public static string accessToken - { - get - { - return UnityConnect.instance.GetAccessToken(); - } - } - - public static string projectId - { - get - { - return UnityConnect.instance.GetProjectGUID(); - } - } - - public static string projectName - { - get - { - return UnityConnect.instance.GetProjectName(); - } - } - - public static string organizationId - { - get - { - return UnityConnect.instance.GetOrganizationId(); - } - } - - public static string organizationName - { - get - { - return UnityConnect.instance.GetOrganizationName(); - } - } - } -} diff --git a/Editor/Mono/UnityConnect/Services/AdsAccess.cs b/Editor/Mono/UnityConnect/Services/AdsAccess.cs deleted file mode 100644 index 5ac10b0b00..0000000000 --- a/Editor/Mono/UnityConnect/Services/AdsAccess.cs +++ /dev/null @@ -1,118 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using UnityEditor.Connect; -using UnityEditor.Advertisements; -using UnityEngine; -using UnityEditor; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal class AdsAccess : CloudServiceAccess - { - private const string kServiceName = "Unity Ads"; - private const string kServiceDisplayName = "Ads"; - private const string kServicePackageName = "com.unity.ads"; - private const string kServiceUrl = "https://public-cdn.cloud.unity3d.com/editor/production/cloud/ads"; - - public override string GetServiceName() - { - return kServiceName; - } - - public override string GetServiceDisplayName() - { - return kServiceDisplayName; - } - - public override string GetPackageName() - { - return kServicePackageName; - } - - override public bool IsServiceEnabled() - { - return AdvertisementSettings.enabled; - } - - [Serializable] - public struct AdsServiceState { public bool ads; } - override public void EnableService(bool enabled) - { - if (AdvertisementSettings.enabled != enabled) - { - AdvertisementSettings.SetEnabledServiceWindow(enabled); - EditorAnalytics.SendEventServiceInfo(new AdsServiceState() { ads = enabled }); - } - } - - override public void OnProjectUnbound() - { - AdvertisementSettings.SetEnabledServiceWindow(false); - AdvertisementSettings.SetGameId(RuntimePlatform.IPhonePlayer, ""); - AdvertisementSettings.SetGameId(RuntimePlatform.Android, ""); - AdvertisementSettings.testMode = false; - } - - public bool IsInitializedOnStartup() - { - return AdvertisementSettings.initializeOnStartup; - } - - public void SetInitializedOnStartup(bool enabled) - { - AdvertisementSettings.initializeOnStartup = enabled; - } - - public string GetIOSGameId() - { - return AdvertisementSettings.GetGameId(RuntimePlatform.IPhonePlayer); - } - - public void SetIOSGameId(string value) - { - AdvertisementSettings.SetGameId(RuntimePlatform.IPhonePlayer, value); - } - - public string GetAndroidGameId() - { - return AdvertisementSettings.GetGameId(RuntimePlatform.Android); - } - - public void SetAndroidGameId(string value) - { - AdvertisementSettings.SetGameId(RuntimePlatform.Android, value); - } - - public string GetGameId(string platformName) - { - return AdvertisementSettings.GetPlatformGameId(platformName); - } - - public void SetGameId(string platformName, string value) - { - AdvertisementSettings.SetPlatformGameId(platformName, value); - } - - public bool IsTestModeEnabled() - { - return AdvertisementSettings.testMode; - } - - public void SetTestModeEnabled(bool enabled) - { - AdvertisementSettings.testMode = enabled; - } - - static AdsAccess() - { - var serviceData = new UnityConnectServiceData(kServiceName, kServiceUrl, new AdsAccess(), "unity/project/cloud/ads"); - UnityConnectServiceCollection.instance.AddService(serviceData); - } - } -} - diff --git a/Editor/Mono/UnityConnect/Services/AnalyticsAccess.cs b/Editor/Mono/UnityConnect/Services/AnalyticsAccess.cs deleted file mode 100644 index ed8e854b95..0000000000 --- a/Editor/Mono/UnityConnect/Services/AnalyticsAccess.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using UnityEditor.Connect; -using UnityEngine; -using UnityEditor.Analytics; -using UnityEditor; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - class AnalyticsAccess : CloudServiceAccess - { - private const string kServiceName = "Analytics"; - private const string kServiceDisplayName = "Analytics"; - private const string kServicePackageName = "com.unity.analytics"; - private const string kServiceUrl = "https://public-cdn.cloud.unity3d.com/editor/production/cloud/analytics"; - - public override string GetServiceName() - { - return kServiceName; - } - - public override string GetServiceDisplayName() - { - return kServiceDisplayName; - } - - public override string GetPackageName() - { - return kServicePackageName; - } - - override public bool IsServiceEnabled() - { - return AnalyticsSettings.enabled; - } - - [Serializable] - public struct AnalyticsServiceState { public bool analytics; } - override public void EnableService(bool enabled) - { - if (AnalyticsSettings.enabled != enabled) - { - AnalyticsSettings.SetEnabledServiceWindow(enabled); - EditorAnalytics.SendEventServiceInfo(new AnalyticsServiceState() { analytics = enabled }); - } - } - - public bool IsTestModeEnabled() - { - return AnalyticsSettings.testMode; - } - - public void SetTestModeEnabled(bool enabled) - { - AnalyticsSettings.testMode = enabled; - } - - static AnalyticsAccess() - { - var serviceData = new UnityConnectServiceData(kServiceName, kServiceUrl, new AnalyticsAccess(), "unity/project/cloud/analytics"); - UnityConnectServiceCollection.instance.AddService(serviceData); - } - } -} - diff --git a/Editor/Mono/UnityConnect/Services/BuildAccess.cs b/Editor/Mono/UnityConnect/Services/BuildAccess.cs deleted file mode 100644 index d2bd6dcf0c..0000000000 --- a/Editor/Mono/UnityConnect/Services/BuildAccess.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEditor.Connect; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal class BuildAccess : CloudServiceAccess - { - private const string kServiceName = "Build"; - private const string kServiceDisplayName = "Unity Build"; - private const string kServiceUrl = "https://public-cdn.cloud.unity3d.com/editor/production/cloud/build"; - - public override string GetServiceName() - { - return kServiceName; - } - - public override string GetServiceDisplayName() - { - return kServiceDisplayName; - } - - public void ShowBuildForCommit(string commitId) - { - ShowServicePage(); - - string eventCmd = string.Format("window.unityEvents ? window.unityEvents.broadcast('build.showForCommit', '{0}'): '';", commitId); - var webview = GetWebView(); - webview.ExecuteJavascript(eventCmd); - } - - static BuildAccess() - { - var serviceData = new UnityConnectServiceData(kServiceName, kServiceUrl, new BuildAccess(), "unity/project/cloud/build"); - UnityConnectServiceCollection.instance.AddService(serviceData); - } - } -} - diff --git a/Editor/Mono/UnityConnect/Services/CloudServiceAccess.cs b/Editor/Mono/UnityConnect/Services/CloudServiceAccess.cs deleted file mode 100644 index d42162a646..0000000000 --- a/Editor/Mono/UnityConnect/Services/CloudServiceAccess.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Analytics; - - -namespace UnityEditor.Web -{ - internal abstract class CloudServiceAccess - { - public abstract string GetServiceName(); - - protected WebView GetWebView() - { - return UnityEditor.Connect.UnityConnectServiceCollection.instance.GetWebViewFromServiceName(GetServiceName()); - } - - protected string GetSafeServiceName() - { - return GetServiceName().Replace(' ', '_'); - } - - public virtual string GetServiceDisplayName() - { - return GetServiceName(); - } - - public virtual string GetPackageName() - { - return string.Empty; - } - - public virtual bool IsServiceEnabled() - { - return PlayerSettings.GetCloudServiceEnabled(GetServiceName()); - } - - public virtual void EnableService(bool enabled) - { - PlayerSettings.SetCloudServiceEnabled(GetServiceName(), enabled); - } - - public virtual void OnProjectUnbound() - { - // Do nothing - } - - public void ShowServicePage() - { - UnityEditor.Connect.UnityConnectServiceCollection.instance.ShowService(GetServiceName(), true, "show_service_page"); - } - - public void GoBackToHub() - { - UnityEditor.Connect.UnityConnectServiceCollection.instance.ShowService(UnityEditor.Web.HubAccess.kServiceName, true, "go_back_to_hub"); - } - } -} - diff --git a/Editor/Mono/UnityConnect/Services/CollabAccess.cs b/Editor/Mono/UnityConnect/Services/CollabAccess.cs deleted file mode 100644 index 627a8346af..0000000000 --- a/Editor/Mono/UnityConnect/Services/CollabAccess.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEditor; -using UnityEditorInternal; -using UnityEditor.Connect; -using UnityEditor.Collaboration; -using UnityEngine; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal class CollabAccess : CloudServiceAccess - { - private const string kServiceName = "Collab"; - private const string kServiceDisplayName = "Unity Collab"; - private const string kServiceUrl = "https://public-cdn.cloud.unity3d.com/editor/production/cloud/collab"; - - static private CollabAccess s_instance; - public static CollabAccess Instance - { - get - { - return s_instance; - } - } - - public override string GetServiceName() - { - return kServiceName; - } - - public override string GetServiceDisplayName() - { - return kServiceDisplayName; - } - - public override void EnableService(bool enabled) - { - base.EnableService(enabled); - Collab.instance.SendNotification(); - Collab.instance.SetCollabEnabledForCurrentProject(enabled); - - AssetDatabase.Refresh(); // If auto-refresh was off, make sure we refresh when setting it back on - } - - static CollabAccess() - { - s_instance = new CollabAccess(); - - var serviceData = new UnityConnectServiceData(kServiceName, kServiceUrl, s_instance, "unity/project/cloud/collab"); - UnityConnectServiceCollection.instance.AddService(serviceData); - } - - public bool IsCollabUIAccessible() - { - return true; - } - } -} - diff --git a/Editor/Mono/UnityConnect/Services/CrashReportingAccess.cs b/Editor/Mono/UnityConnect/Services/CrashReportingAccess.cs deleted file mode 100644 index 3468304f28..0000000000 --- a/Editor/Mono/UnityConnect/Services/CrashReportingAccess.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using UnityEditor.Connect; -using UnityEngine; -using UnityEditor.CrashReporting; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal class CrashReportingAccess : CloudServiceAccess - { - private const string kServiceName = "Game Performance"; - private const string kServiceDisplayName = "Game Performance"; - private const string kServiceUrl = "https://public-cdn.cloud.unity3d.com/editor/production/cloud/crash"; - - public override string GetServiceName() - { - return kServiceName; - } - - public override string GetServiceDisplayName() - { - return kServiceDisplayName; - } - - override public bool IsServiceEnabled() - { - return CrashReportingSettings.enabled; - } - - [Serializable] - public struct CrashReportingServiceState { public bool crash_reporting; } - override public void EnableService(bool enabled) - { - if (CrashReportingSettings.enabled != enabled) - { - CrashReportingSettings.SetEnabledServiceWindow(enabled); - EditorAnalytics.SendEventServiceInfo(new CrashReportingServiceState() { crash_reporting = enabled }); - } - } - - static CrashReportingAccess() - { - var serviceData = new UnityConnectServiceData(kServiceName, kServiceUrl, new CrashReportingAccess(), "unity/project/cloud/crashreporting"); - UnityConnectServiceCollection.instance.AddService(serviceData); - } - - public bool GetCaptureEditorExceptions() - { - return CrashReportingSettings.captureEditorExceptions; - } - - public void SetCaptureEditorExceptions(bool captureEditorExceptions) - { - CrashReportingSettings.captureEditorExceptions = captureEditorExceptions; - } - } -} - diff --git a/Editor/Mono/UnityConnect/Services/EditorProjectAccess.bindings.cs b/Editor/Mono/UnityConnect/Services/EditorProjectAccess.bindings.cs deleted file mode 100644 index bed26b37f2..0000000000 --- a/Editor/Mono/UnityConnect/Services/EditorProjectAccess.bindings.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditor.Web -{ - [NativeHeader("Editor/Src/UnityConnect/Services/EditorProjectAccess.h")] - internal partial class EditorProjectAccess : Object - { - public EditorProjectAccess() - { - Internal_Create(this); - } - - extern private static void Internal_Create([Writable] EditorProjectAccess self); - extern public string GetProjectEditorVersion(); - extern public string GetRESTServiceURI(); - } -} diff --git a/Editor/Mono/UnityConnect/Services/EditorProjectAccess.cs b/Editor/Mono/UnityConnect/Services/EditorProjectAccess.cs deleted file mode 100644 index a047daef4a..0000000000 --- a/Editor/Mono/UnityConnect/Services/EditorProjectAccess.cs +++ /dev/null @@ -1,162 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using System.IO; -using UnityEngine; -using UnityEditor; -using UnityEditor.Connect; -using UnityEngine.SceneManagement; -using UnityEditor.SceneManagement; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal partial class EditorProjectAccess - { - const string kCloudServiceKey = "CloudServices"; - const string kCloudEnabled = "CloudEnabled"; - - public void OpenLink(string link) - { - Help.BrowseURL(link); - } - - public bool IsOnline() - { - return UnityConnect.instance.online; - } - - public bool IsLoggedIn() - { - return UnityConnect.instance.loggedIn; - } - - public string GetEnvironment() - { - return UnityConnect.instance.GetEnvironment(); - } - - public string GetUserName() - { - return UnityConnect.instance.userInfo.userName; - } - - public string GetUserDisplayName() - { - return UnityConnect.instance.userInfo.displayName; - } - - public string GetUserPrimaryOrganizationId() - { - return UnityConnect.instance.userInfo.primaryOrg; - } - - public string GetUserAccessToken() - { - return UnityConnect.instance.GetAccessToken(); - } - - public string GetProjectName() - { - string name = UnityConnect.instance.projectInfo.projectName; - if (name != "") - return name; - - return PlayerSettings.productName; - } - - public string GetProjectGUID() - { - return UnityConnect.instance.projectInfo.projectGUID; - } - - - public string GetProjectPath() - { - return Directory.GetCurrentDirectory(); - } - - public string GetProjectIcon() - { - // we should get the real project icon and base64 encode it and return it here - return null; - } - - public string GetOrganizationID() - { - return UnityConnect.instance.projectInfo.organizationId; - } - - - public string GetBuildTarget() - { - return EditorUserBuildSettings.activeBuildTarget.ToString(); - } - - public bool IsProjectBound() - { - return UnityConnect.instance.projectInfo.projectBound; - } - - public void EnableCloud(bool enable) - { - // should store in settings + send info to server - EditorUserSettings.SetConfigValue(kCloudServiceKey + "/" + kCloudEnabled, enable.ToString()); - } - - public void EnterPlayMode() - { - EditorApplication.isPlaying = true; - } - - public bool IsPlayMode() - { - return EditorApplication.isPlaying; - } - - public bool SaveCurrentModifiedScenesIfUserWantsTo() - { - return EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo(); - } - - public int GetEditorSkinIndex() - { - int skinIndex = EditorGUIUtility.skinIndex; - return skinIndex; - } - - static EditorProjectAccess() - { - JSProxyMgr.GetInstance().AddGlobalObject("unity/project", new EditorProjectAccess()); - } - - public void GoToHistory() - { - CollabHistoryWindow.ShowHistoryWindow(); - } - - public static void ShowToolbarDropdown() - { - Toolbar.requestShowCollabToolbar = true; - if (Toolbar.get) - { - Toolbar.get.Repaint(); - } - } - - public void CloseToolbarWindow() - { - CollabToolbarWindow.CloseToolbarWindows(); - } - - public void CloseToolbarWindowImmediately() - { - CollabToolbarWindow.CloseToolbarWindowsImmediately(); - } - - } -} - diff --git a/Editor/Mono/UnityConnect/Services/ErrorHubAccess.cs b/Editor/Mono/UnityConnect/Services/ErrorHubAccess.cs deleted file mode 100644 index 868c95be60..0000000000 --- a/Editor/Mono/UnityConnect/Services/ErrorHubAccess.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEditor.Connect; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal class ErrorHubAccess : CloudServiceAccess - { - public const string kServiceName = "ErrorHub"; - private static string kServiceUrl = "file://" + EditorApplication.userJavascriptPackagesPath + "unityeditor-cloud-hub/dist/index.html?failure=unity_connect"; - - public static ErrorHubAccess instance { get; private set; } - public string errorMessage { get; set; } - - public override string GetServiceName() - { - return kServiceName; - } - - static ErrorHubAccess() - { - instance = new ErrorHubAccess(); - var serviceData = new UnityConnectServiceData(kServiceName, kServiceUrl, instance, "unity/project/cloud/errorhub"); - UnityConnectServiceCollection.instance.AddService(serviceData); - } - } -} - diff --git a/Editor/Mono/UnityConnect/Services/HubAccess.cs b/Editor/Mono/UnityConnect/Services/HubAccess.cs deleted file mode 100644 index f93d2ec3e2..0000000000 --- a/Editor/Mono/UnityConnect/Services/HubAccess.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEditor.Connect; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal class HubAccess : CloudServiceAccess - { - public const string kServiceName = "Hub"; - private const string kServiceDisplayName = "Services"; - private const string kServiceUrl = "https://public-cdn.cloud.unity3d.com/editor/production/cloud/hub"; - - static private HubAccess s_Instance; - public static HubAccess instance - { - get - { - return s_Instance; - } - } - - public override string GetServiceName() - { - return kServiceName; - } - - public override string GetServiceDisplayName() - { - return kServiceDisplayName; - } - - public UnityConnectServiceCollection.ServiceInfo[] GetServices() - { - return UnityConnectServiceCollection.instance.GetAllServiceInfos(); - } - - public void ShowService(string name) - { - UnityConnectServiceCollection.instance.ShowService(name, true, "show_service_method"); - } - - public void EnableCloudService(string name, bool enabled) - { - UnityConnectServiceCollection.instance.EnableService(name, enabled); - } - - static HubAccess() - { - s_Instance = new HubAccess(); - var serviceData = new UnityConnectServiceData(kServiceName, kServiceUrl, s_Instance, "unity/project/cloud/hub"); - UnityConnectServiceCollection.instance.AddService(serviceData); - } - - [MenuItem("Window/Services %0", false, 1999)] - private static void ShowMyWindow() - { - UnityConnectServiceCollection.instance.ShowService(kServiceName, true, "window_menu_item"); - } - } -} - diff --git a/Editor/Mono/UnityConnect/Services/PurchasingAccess.cs b/Editor/Mono/UnityConnect/Services/PurchasingAccess.cs deleted file mode 100644 index 8dbded30ec..0000000000 --- a/Editor/Mono/UnityConnect/Services/PurchasingAccess.cs +++ /dev/null @@ -1,142 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using UnityEngine; -using UnityEditor.Purchasing; -using UnityEngine.Networking; -using UnityEditor.Connect; -using System; -using System.IO; -using System.Net; -using System.Security.Cryptography.X509Certificates; -using System.Net.Security; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal class PurchasingAccess : CloudServiceAccess - { - private const string kServiceName = "Purchasing"; - private const string kServiceDisplayName = "In App Purchasing"; - private const string kServicePackageName = "com.unity.purchasing"; - private const string kServiceUrl = "https://public-cdn.cloud.unity3d.com/editor/production/cloud/purchasing"; - private const string kETagPath = "Assets/Plugins/UnityPurchasing/ETag"; - private const string kUnknownPackageETag = "unknown"; - private static readonly Uri kPackageUri = new Uri("https://public-cdn.cloud.unity3d.com/UnityEngine.Cloud.Purchasing.unitypackage"); - private bool m_InstallInProgress; - - public override string GetServiceName() - { - return kServiceName; - } - - public override string GetServiceDisplayName() - { - return kServiceDisplayName; - } - - public override string GetPackageName() - { - return kServicePackageName; - } - - override public bool IsServiceEnabled() - { - return PurchasingSettings.enabled; - } - - public struct PurchasingServiceState { public bool iap; } - override public void EnableService(bool enabled) - { - if (PurchasingSettings.enabled != enabled) - { - PurchasingSettings.SetEnabledServiceWindow(enabled); - EditorAnalytics.SendEventServiceInfo(new PurchasingServiceState() {iap = enabled}); - } - } - - static PurchasingAccess() - { - var serviceData = new UnityConnectServiceData(kServiceName, kServiceUrl, new PurchasingAccess(), "unity/project/cloud/purchasing"); - UnityConnectServiceCollection.instance.AddService(serviceData); - } - - /// - /// Download and install the Unity IAP Package. - /// - public void InstallUnityPackage() - { - if (m_InstallInProgress) - return; - - var originalCallback = ServicePointManager.ServerCertificateValidationCallback; - // Only OSX supports SSL certificate validation, disable checking on other platforms. - // TODO - fix when a Unity Web framework supports SSL. - if (Application.platform != RuntimePlatform.OSXEditor) - ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true; - - m_InstallInProgress = true; - var location = FileUtil.GetUniqueTempPathInProject(); - // Extension is required for correct Windows import. - location = Path.ChangeExtension(location, ".unitypackage"); - - var client = new WebClient(); - client.DownloadFileCompleted += (sender, args) => - { - // Installation must be done on the main thread. - EditorApplication.CallbackFunction handler = null; - handler = () => - { - ServicePointManager.ServerCertificateValidationCallback = originalCallback; - EditorApplication.update -= handler; - m_InstallInProgress = false; - if (args.Error == null) - { - SaveETag(client); - AssetDatabase.ImportPackage(location, false); - } - else - { - UnityEngine.Debug.LogWarning("Failed to download IAP package. Please check connectivity and retry."); - UnityEngine.Debug.LogException(args.Error); - } - }; - EditorApplication.update += handler; - }; - - client.DownloadFileAsync(kPackageUri, location); - } - - /// - /// Get the ETag of the currently installed IAP package, if any. - /// Called by the Editor IAP window when doing update checks. - /// - public string GetInstalledETag() - { - if (File.Exists(kETagPath)) - { - return File.ReadAllText(kETagPath); - } - else if (Directory.Exists(Path.GetDirectoryName(kETagPath))) - { - // The plugin was installed pre ETag version tracking. - return kUnknownPackageETag; - } - - return null; // No plugin. - } - - private void SaveETag(WebClient client) - { - string etag = client.ResponseHeaders.Get("ETag"); - if (null != etag) - { - Directory.CreateDirectory(Path.GetDirectoryName(kETagPath)); - File.WriteAllText(kETagPath, etag); - } - } - } -} - diff --git a/Editor/Mono/UnityConnect/Services/UnetAccess.cs b/Editor/Mono/UnityConnect/Services/UnetAccess.cs deleted file mode 100644 index 34dba3a5f9..0000000000 --- a/Editor/Mono/UnityConnect/Services/UnetAccess.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - - -using System; -using UnityEditor.Connect; - -namespace UnityEditor.Web -{ - [InitializeOnLoad] - internal class UnetAccess : CloudServiceAccess - { - const string kServiceName = "UNet"; - const string kServiceDisplayName = "Multiplayer"; - const string kServiceUrl = "https://public-cdn.cloud.unity3d.com/editor/production/cloud/unet"; - - public override string GetServiceName() - { - return kServiceName; - } - - public override string GetServiceDisplayName() - { - return kServiceDisplayName; - } - - [Serializable] - public struct UnetServiceState { public bool unet; } - override public void EnableService(bool enabled) - { - if (IsServiceEnabled() != enabled) - { - base.EnableService(enabled); - EditorAnalytics.SendEventServiceInfo(new UnetServiceState() { unet = enabled }); - } - } - - static UnetAccess() - { - var serviceData = new UnityConnectServiceData(kServiceName, kServiceUrl, new UnetAccess(), "unity/project/cloud/networking"); - UnityConnectServiceCollection.instance.AddService(serviceData); - } - - public void SetMultiplayerId(int id) - { - } - } -} - diff --git a/Editor/Mono/UnityConnect/UnityConnect.cs b/Editor/Mono/UnityConnect/UnityConnect.cs deleted file mode 100644 index c3efe4512f..0000000000 --- a/Editor/Mono/UnityConnect/UnityConnect.cs +++ /dev/null @@ -1,269 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditorInternal; -using UnityEditor.Web; -using UnityEngine; - -namespace UnityEditor.Connect -{ - internal delegate void StateChangedDelegate(ConnectInfo state); - internal delegate void ProjectStateChangedDelegate(ProjectInfo state); - internal delegate void UserStateChangedDelegate(UserInfo state); - - public static class UnityOAuth - { - public static event Action UserLoggedIn; - public static event Action UserLoggedOut; - - public struct AuthCodeResponse - { - public string AuthCode { get; set; } - public Exception Exception { get; set; } - } - - public static void GetAuthorizationCodeAsync(string clientId, Action callback) - { - if (string.IsNullOrEmpty(clientId)) - { - throw new ArgumentException("clientId is null or empty.", "clientId"); - } - - if (callback == null) - { - throw new ArgumentNullException("callback"); - } - - if (string.IsNullOrEmpty(UnityConnect.instance.GetAccessToken())) - { - throw new InvalidOperationException("User is not logged in or user status invalid."); - } - - string url = string.Format("{0}/v1/oauth2/authorize", UnityConnect.instance.GetConfigurationURL(CloudConfigUrl.CloudIdentity)); - - AsyncHTTPClient client = new AsyncHTTPClient(url); - client.postData = string.Format("client_id={0}&response_type=code&format=json&access_token={1}&prompt=none", - clientId, - UnityConnect.instance.GetAccessToken()); - client.doneCallback = delegate(AsyncHTTPClient c) { - AuthCodeResponse response = new AuthCodeResponse(); - if (!c.IsSuccess()) - { - response.Exception = new InvalidOperationException("Failed to call Unity ID to get auth code."); - } - else - { - try - { - var json = new JSONParser(c.text).Parse(); - if (json.ContainsKey("code") && !json["code"].IsNull()) - { - response.AuthCode = json["code"].AsString(); - } - else if (json.ContainsKey("message")) - { - response.Exception = new InvalidOperationException(string.Format("Error from server: {0}", json["message"].AsString())); - } - else if (json.ContainsKey("location") && !json["location"].IsNull()) - { - UnityConnectConsentView consentView = UnityConnectConsentView.ShowUnityConnectConsentView(json["location"].AsString()); - if (!string.IsNullOrEmpty(consentView.Code)) - { - response.AuthCode = consentView.Code; - } - else if (!string.IsNullOrEmpty(consentView.Error)) - { - response.Exception = new InvalidOperationException(string.Format("Error from server: {0}", consentView.Error)); - } - else - { - response.Exception = new InvalidOperationException("Consent Windows was closed unexpected."); - } - } - else - { - response.Exception = new InvalidOperationException("Unexpected response from server."); - } - } - catch (JSONParseException) - { - response.Exception = new InvalidOperationException("Unexpected response from server: Failed to parse JSON."); - } - } - - callback(response); - }; - client.Begin(); - } - - private static void OnUserLoggedIn() - { - if (UserLoggedIn != null) - UserLoggedIn(); - } - - private static void OnUserLoggedOut() - { - if (UserLoggedOut != null) - UserLoggedOut(); - } - } - - [InitializeOnLoad] - internal partial class UnityConnect - { - public event StateChangedDelegate StateChanged; - public event ProjectStateChangedDelegate ProjectStateChanged; - public event UserStateChangedDelegate UserStateChanged; - - private static readonly UnityConnect s_Instance; - - [Flags] - internal enum UnityErrorPriority - { - Critical = 0, - Error, - Warning, - Info, - None - }; - - [Flags] - internal enum UnityErrorBehaviour - { - Alert = 0, - Automatic, - Hidden, - ConsoleOnly, - Reconnect - }; - - [Flags] - internal enum UnityErrorFilter - { - ByContext = 1, - ByParent = 2, - ByChild = 4, - All = 7 - }; - - private UnityConnect() - { - } - - public void GoToHub(string page) - { - UnityEditor.Connect.UnityConnectServiceCollection.instance.ShowService(UnityEditor.Web.HubAccess.kServiceName, page, true, "goto_hub_method"); - } - - - public void UnbindProject() - { - UnbindCloudProject(); - UnityConnectServiceCollection.instance.UnbindAllServices(); - } - - // For Javascript Only - public ProjectInfo GetProjectInfo() - { - return projectInfo; - } - - - public UserInfo GetUserInfo() - { - return userInfo; - } - - public ConnectInfo GetConnectInfo() - { - return connectInfo; - } - - public string GetConfigurationUrlByIndex(int index) - { - if (index == 0) - return GetConfigurationURL(CloudConfigUrl.CloudCore); - if (index == 1) - return GetConfigurationURL(CloudConfigUrl.CloudCollab); - if (index == 2) - return GetConfigurationURL(CloudConfigUrl.CloudWebauth); - if (index == 3) - return GetConfigurationURL(CloudConfigUrl.CloudLogin); - // unityeditor-cloud only called this API with index as {0,1,2,3}. - // We add the new URLs in case some module might need them in the future - if (index == 6) - return GetConfigurationURL(CloudConfigUrl.CloudIdentity); - if (index == 7) - return GetConfigurationURL(CloudConfigUrl.CloudPortal); - - return ""; - } - - public string GetCoreConfigurationUrl() - { - return GetConfigurationURL(CloudConfigUrl.CloudCore); - } - - public bool DisplayDialog(string title, string message, string okBtn, string cancelBtn) - { - return EditorUtility.DisplayDialog(title, message, okBtn, cancelBtn); - } - - public bool SetCOPPACompliance(int compliance) - { - return SetCOPPACompliance((COPPACompliance)compliance); - } - - // End for Javascript Only - - [MenuItem("Window/Unity Connect/Computer GoesToSleep", false, 1000, true)] - public static void TestComputerGoesToSleep() - { - instance.ComputerGoesToSleep(); - } - - [MenuItem("Window/Unity Connect/Computer DidWakeUp", false, 1000, true)] - public static void TestComputerDidWakeUp() - { - instance.ComputerDidWakeUp(); - } - - public static UnityConnect instance - { - get - { - return s_Instance; - } - } - - static UnityConnect() - { - s_Instance = new UnityConnect(); - JSProxyMgr.GetInstance().AddGlobalObject("unity/connect", s_Instance); - } - - private static void OnStateChanged() - { - var handler = instance.StateChanged; - if (handler != null) - handler(instance.connectInfo); - } - - private static void OnProjectStateChanged() - { - var handler = instance.ProjectStateChanged; - if (handler != null) - handler(instance.projectInfo); - } - - private static void OnUserStateChanged() - { - var handler = instance.UserStateChanged; - if (handler != null) - handler(instance.userInfo); - } - }; -} diff --git a/Editor/Mono/UnityConnect/UnityConnectConsentView.cs b/Editor/Mono/UnityConnect/UnityConnectConsentView.cs deleted file mode 100644 index 8556770688..0000000000 --- a/Editor/Mono/UnityConnect/UnityConnectConsentView.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using UnityEditor.Web; -using System.Collections.Generic; - -namespace UnityEditor.Connect -{ - [Serializable] - internal class UnityConnectConsentView : WebViewEditorWindow - { - private String code = ""; - private String error = ""; - - public String Code - { - get - { - return code; - } - } - - public String Error - { - get - { - return error; - } - } - - internal override WebView webView - { - get; set; - } - - public static UnityConnectConsentView ShowUnityConnectConsentView(String URL) - { - UnityConnectConsentView consentView = ScriptableObject.CreateInstance(); - - var rect = new Rect(100, 100, 800, 605); - consentView.titleContent = EditorGUIUtility.TrTextContent("Unity Application Consent Window"); - consentView.minSize = new Vector2(rect.width, rect.height); - consentView.maxSize = new Vector2(rect.width, rect.height); - consentView.position = rect; - consentView.m_InitialOpenURL = URL; - consentView.ShowModal(); - - consentView.m_Parent.window.m_DontSaveToLayout = true; - - return consentView; - } - - override public void OnDestroy() - { - OnBecameInvisible(); - } - - override public void OnInitScripting() - { - base.SetScriptObject(); - } - - override public void OnLocationChanged(string url) - { - var location = new Uri(url); - foreach (string item in location.Query.Split('&')) - { - string[] qs = item.Replace("?", String.Empty).Split('='); - if (qs[0] == "code") - { - code = qs[1]; - break; - } - if (qs[0] == "error") - { - error = qs[1]; - break; - } - } - - if (!string.IsNullOrEmpty(code) || !string.IsNullOrEmpty(error)) - { - this.Close(); - return; - } - base.OnLocationChanged(url); - } - } -} diff --git a/Editor/Mono/UnityConnect/UnityConnectEditorWindow.cs b/Editor/Mono/UnityConnect/UnityConnectEditorWindow.cs deleted file mode 100644 index 3af1737c2e..0000000000 --- a/Editor/Mono/UnityConnect/UnityConnectEditorWindow.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using UnityEditor.Web; -using System.Collections.Generic; - -namespace UnityEditor.Connect -{ - [Serializable] - internal class UnityConnectEditorWindow : WebViewEditorWindowTabs - { - private List m_ServiceUrls; - public string ErrorUrl { get; set; } - - private bool m_ClearInitialOpenURL; - public string currentUrl - { - get { return m_InitialOpenURL; } - set - { - m_InitialOpenURL = value; - LoadPage(); - } - } - - public static UnityConnectEditorWindow Create(string title, List serviceUrls) - { - //Pop back the drawer window if it exist we have to look from all the layout - //because window can appear at anytime when a layout get reload - var wins = Resources.FindObjectsOfTypeAll(typeof(UnityConnectEditorWindow)) as UnityConnectEditorWindow[]; - if (wins != null) - { - // cannot test with title anymore since we are addind [env] to the title if not production - foreach (var win in wins.Where(win => win != null /*&& win.title == title*/)) - { - win.titleContent = new GUIContent(title); - return win; - } - } - //Create a new window if it do not exist - var window = GetWindow(title, typeof(UnityEditor.InspectorWindow)); - - //Prevent the reset of the url, we want the reset to happen when the layout is creating this window not in this case - //Here the user ask to see the hub - window.m_ClearInitialOpenURL = false; - //Always select the first service when creating the service drawer - window.initialOpenUrl = serviceUrls[0]; - window.Init(); - return window; - } - - protected UnityConnectEditorWindow() - { - m_ServiceUrls = new List(); - m_ClearInitialOpenURL = true; - } - - public bool UrlsMatch(List referenceUrls) - { - if (m_ServiceUrls.Count != referenceUrls.Count) - return false; - - return !m_ServiceUrls.Where((t, idx) => t != referenceUrls[idx]).Any(); - } - - public new void OnEnable() - { - //Construct the UnityConnectEditor singleton - - m_ServiceUrls = UnityConnectServiceCollection.instance.GetAllServiceUrls(); - base.OnEnable(); - } - - public new void OnInitScripting() - { - base.OnInitScripting(); - } - - public new void ToggleMaximize() - { - base.ToggleMaximize(); - } - - public new void OnLoadError(string url) - { - if (webView == null) - return; - - webView.LoadFile(EditorApplication.userJavascriptPackagesPath + "unityeditor-cloud-hub/dist/index.html?failure=load_error&reload_url=" + WWW.EscapeURL(url)); - if (url.StartsWith("http://") || url.StartsWith("https://")) - UnregisterWebviewUrl(url); - } - - new public void OnGUI() - { - //We must prevent the layout serialization to load a url, we want to load - //the hub when we start the application. - if (m_ClearInitialOpenURL) - { - m_ClearInitialOpenURL = false; - m_InitialOpenURL = m_ServiceUrls.Count > 0 ? UnityConnectServiceCollection.instance.GetUrlForService(HubAccess.kServiceName) : null; - } - base.OnGUI(); - } - } -} diff --git a/Editor/Mono/UnityConnect/UnityConnectPrefs.cs b/Editor/Mono/UnityConnect/UnityConnectPrefs.cs deleted file mode 100644 index c120fce432..0000000000 --- a/Editor/Mono/UnityConnect/UnityConnectPrefs.cs +++ /dev/null @@ -1,175 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; - -namespace UnityEditor.Connect -{ - internal class UnityConnectPrefs - { - public static string[] kEnvironmentFamilies = new string[] {"Production", "Staging", "Dev", "Custom"}; - public const int kProductionEnv = 0; - public const int kCustomEnv = 3; - - public const string kSvcEnvPref = "CloudPanelServer"; - public const string kSvcCustomUrlPref = "CloudPanelCustomUrl"; - public const string kSvcCustomPortPref = "CloudPanelCustomPort"; - - protected class CloudPanelPref - { - public CloudPanelPref(string serviceName) - { - m_ServiceName = serviceName; - m_CloudPanelServer = GetServiceEnv(m_ServiceName); - m_CloudPanelCustomUrl = EditorPrefs.GetString(ServicePrefKey(kSvcCustomUrlPref , m_ServiceName)); - m_CloudPanelCustomPort = EditorPrefs.GetInt(ServicePrefKey(kSvcCustomPortPref , m_ServiceName)); - } - - public void StoreCloudServicePref() - { - EditorPrefs.SetInt(ServicePrefKey(kSvcEnvPref, m_ServiceName), m_CloudPanelServer); - EditorPrefs.SetString(ServicePrefKey(kSvcCustomUrlPref , m_ServiceName), m_CloudPanelCustomUrl); - EditorPrefs.SetInt(ServicePrefKey(kSvcCustomPortPref , m_ServiceName), m_CloudPanelCustomPort); - } - - public string m_ServiceName; - public int m_CloudPanelServer; - public string m_CloudPanelCustomUrl; - public int m_CloudPanelCustomPort; - }; - - protected static CloudPanelPref GetPanelPref(string serviceName) - { - if (m_CloudPanelPref.ContainsKey(serviceName)) - return m_CloudPanelPref[serviceName]; - - CloudPanelPref pref = new CloudPanelPref(serviceName); - m_CloudPanelPref.Add(serviceName, pref); - return pref; - } - - protected static Dictionary m_CloudPanelPref = new Dictionary(); - - public static int GetServiceEnv(string serviceName) - { - if (Unsupported.IsDeveloperMode() || UnityConnect.preferencesEnabled) - return EditorPrefs.GetInt(ServicePrefKey(kSvcEnvPref, serviceName)); - - for (var i = 0; i < kEnvironmentFamilies.Length; i++) - { - var environmentName = kEnvironmentFamilies[i]; - //By using the configuration it should default to production if there is no - //-cloudEnvironment or to the switch value in case it is specified - if (environmentName.Equals(UnityConnect.instance.configuration, StringComparison.InvariantCultureIgnoreCase)) - return i; - } - return 0; //Return production if there is an error - } - - public static string ServicePrefKey(string baseKey, string serviceName) - { - return baseKey + "/" + serviceName; - } - - public static string FixUrl(string url, string serviceName) - { - var fixUrl = url; - var panelEnv = GetServiceEnv(serviceName); - if (panelEnv != kProductionEnv) - { - if (fixUrl.StartsWith("http://") || fixUrl.StartsWith("https://")) - { - if (panelEnv == kCustomEnv) - { - var devUrl = EditorPrefs.GetString(ServicePrefKey(kSvcCustomUrlPref , serviceName)); - var devPort = EditorPrefs.GetInt(ServicePrefKey(kSvcCustomPortPref , serviceName)); - fixUrl = (devPort == 0) ? devUrl : (devUrl + ":" + devPort); - } - else - { - fixUrl = fixUrl.ToLower(); - fixUrl = fixUrl.Replace("/" + kEnvironmentFamilies[kProductionEnv].ToLower() + "/", "/" + kEnvironmentFamilies[panelEnv].ToLower() + "/"); - } - return fixUrl; - } - - if (fixUrl.StartsWith("file://")) - { - fixUrl = fixUrl.Substring(7); - - if (panelEnv == kCustomEnv) - { - var devUrl = EditorPrefs.GetString(ServicePrefKey(kSvcCustomUrlPref , serviceName)); - var devPort = EditorPrefs.GetInt(ServicePrefKey(kSvcCustomPortPref , serviceName)); - fixUrl = devUrl + ":" + devPort; - } - - return fixUrl; - } - - if (!fixUrl.StartsWith("file://") && !fixUrl.StartsWith("http://") && !fixUrl.StartsWith("https://")) - { - fixUrl = "http://" + fixUrl; - return fixUrl; - } - } - - return fixUrl; - } - - static public void ShowPanelPrefUI() - { - List cloudServiceNames = UnityConnectServiceCollection.instance.GetAllServiceNames(); - - bool changed = false; - - foreach (string service in cloudServiceNames) - { - CloudPanelPref pref = GetPanelPref(service); - - int nVal = EditorGUILayout.Popup(service, pref.m_CloudPanelServer, kEnvironmentFamilies); - if (nVal != pref.m_CloudPanelServer) - { - pref.m_CloudPanelServer = nVal; - changed = true; - } - - if (pref.m_CloudPanelServer == kCustomEnv) - { - EditorGUI.indentLevel++; - string nUrl = EditorGUILayout.TextField("Custom server URL", pref.m_CloudPanelCustomUrl); - if (nUrl != pref.m_CloudPanelCustomUrl) - { - pref.m_CloudPanelCustomUrl = nUrl; - changed = true; - } - - Int32.TryParse(EditorGUILayout.TextField("Custom server port", pref.m_CloudPanelCustomPort.ToString()), out nVal); - - if (nVal != pref.m_CloudPanelCustomPort) - { - pref.m_CloudPanelCustomPort = nVal; - changed = true; - } - EditorGUI.indentLevel--; - } - } - - if (changed) - UnityConnectServiceCollection.instance.ReloadServices(); - } - - public static void StorePanelPrefs() - { - if (!Unsupported.IsDeveloperMode() && !UnityConnect.preferencesEnabled) - return; - - foreach (KeyValuePair kvp in m_CloudPanelPref) - { - kvp.Value.StoreCloudServicePref(); - } - } - } -} diff --git a/Editor/Mono/UnityConnect/UnityConnectServiceCollection.cs b/Editor/Mono/UnityConnect/UnityConnectServiceCollection.cs deleted file mode 100644 index 35d68b0985..0000000000 --- a/Editor/Mono/UnityConnect/UnityConnectServiceCollection.cs +++ /dev/null @@ -1,266 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using System.Collections.Generic; -using UnityEditor.Web; -using UnityEditorInternal; -using UnityEditor; - -namespace UnityEditor.Connect -{ - internal class UnityConnectServiceCollection - { - private static UnityConnectServiceCollection s_UnityConnectEditor; //singleton - private static UnityConnectEditorWindow s_UnityConnectEditorWindow; //This is the drawer - private const string kDrawerContainerTitle = "Services"; - - private string m_CurrentServiceName = ""; - private string m_CurrentPageName = ""; - - private readonly Dictionary m_Services; - - private UnityConnectServiceCollection() - { - m_Services = new Dictionary(); - } - - private void Init() - { - //Add this to the v8 global table so javascript can call ShowService("") - JSProxyMgr.GetInstance().AddGlobalObject("UnityConnectEditor", this); - - // We want to show the service window when we create a project, but not every time we open one. - if (Application.HasARGV("createProject")) - ShowService(HubAccess.kServiceName, true, "init_create_project"); - } - - public bool isDrawerOpen - { - get - { - var wins = Resources.FindObjectsOfTypeAll(typeof(UnityConnectEditorWindow)) as UnityConnectEditorWindow[]; - return wins != null && wins.Any(win => win != null); - } - } - private void EnsureDrawerIsVisible(bool forceFocus) - { - //Create the container in case it doesnt exist - if (s_UnityConnectEditorWindow == null || !s_UnityConnectEditorWindow.UrlsMatch(GetAllServiceUrls())) - { - var fixTitle = kDrawerContainerTitle; - - var panelEnv = UnityConnectPrefs.GetServiceEnv(m_CurrentServiceName); - if (panelEnv != UnityConnectPrefs.kProductionEnv) - { - fixTitle += " [" + UnityConnectPrefs.kEnvironmentFamilies[panelEnv] + "]"; - } - - s_UnityConnectEditorWindow = UnityConnectEditorWindow.Create(fixTitle, GetAllServiceUrls()); - s_UnityConnectEditorWindow.ErrorUrl = m_Services[ErrorHubAccess.kServiceName].serviceUrl; - s_UnityConnectEditorWindow.minSize = new Vector2(275, 50); - } - //Since s_UnityConnectEditorWindow.currentUrl is a property that load a page we must build the url before changing it - var newUrl = m_Services[m_CurrentServiceName].serviceUrl; - if (m_CurrentPageName.Length > 0) - { - newUrl += ("/#/" + m_CurrentPageName); - } - s_UnityConnectEditorWindow.currentUrl = newUrl; - s_UnityConnectEditorWindow.ShowTab(); - - if (InternalEditorUtility.isApplicationActive && forceFocus) - s_UnityConnectEditorWindow.Focus(); - } - - public void CloseServices() - { - if (s_UnityConnectEditorWindow != null) - { - s_UnityConnectEditorWindow.Close(); - s_UnityConnectEditorWindow = null; - } - - UnityConnect.instance.ClearCache(); - } - - public void ReloadServices() - { - if (s_UnityConnectEditorWindow != null) - { - s_UnityConnectEditorWindow.Reload(); - } - } - - public static UnityConnectServiceCollection instance - { - get - { - if (s_UnityConnectEditor == null) - { - s_UnityConnectEditor = new UnityConnectServiceCollection(); - s_UnityConnectEditor.Init(); - } - return s_UnityConnectEditor; - } - } - - public static void StaticEnableService(string serviceName, bool enabled) - { - instance.EnableService(serviceName, enabled); - } - - public bool AddService(UnityConnectServiceData cloudService) - { - if (m_Services.ContainsKey(cloudService.serviceName)) - return false; - - m_Services[cloudService.serviceName] = cloudService; - return true; - } - - public bool RemoveService(string serviceName) - { - if (!m_Services.ContainsKey(serviceName)) - return false; - - return m_Services.Remove(serviceName); - } - - public bool ServiceExist(string serviceName) - { - return m_Services.ContainsKey(serviceName); - } - - public bool ShowService(string serviceName, bool forceFocus, string atReferrer) - { - return ShowService(serviceName, "", forceFocus, atReferrer); - } - - [Serializable] - public struct ShowServiceState - { - public string service; - public string page; - public string referrer; - } - - public bool ShowService(string serviceName, string atPage, bool forceFocus, string atReferrer) - { - if (!m_Services.ContainsKey(serviceName)) - { - return false; - } - - ConnectInfo state = UnityConnect.instance.connectInfo; - m_CurrentServiceName = GetActualServiceName(serviceName, state); - m_CurrentPageName = atPage; - EditorAnalytics.SendEventShowService(new ShowServiceState() { service = m_CurrentServiceName, page = atPage, referrer = atReferrer}); - EnsureDrawerIsVisible(forceFocus); - return true; - } - - private string GetActualServiceName(string desiredServiceName, ConnectInfo state) - { - if (!state.online) - return ErrorHubAccess.kServiceName; - - if (!state.ready) - return HubAccess.kServiceName; - - if (state.maintenance) - return ErrorHubAccess.kServiceName; - - if ((desiredServiceName != HubAccess.kServiceName) && (state.online && !state.loggedIn)) - { - return HubAccess.kServiceName; - } - - if ((desiredServiceName == ErrorHubAccess.kServiceName) && state.online) - { - return HubAccess.kServiceName; - } - - if (string.IsNullOrEmpty(desiredServiceName)) - { - return HubAccess.kServiceName; - } - - return desiredServiceName; - } - - public void EnableService(string name, bool enabled) - { - if (!m_Services.ContainsKey(name)) - return; - - m_Services[name].EnableService(enabled); - } - - public string GetUrlForService(string serviceName) - { - return m_Services.ContainsKey(serviceName) ? m_Services[serviceName].serviceUrl : String.Empty; - } - - public UnityConnectServiceData GetServiceFromUrl(string searchUrl) - { - return m_Services.FirstOrDefault(kvp => kvp.Value.serviceUrl == searchUrl).Value; - } - - public List GetAllServiceNames() - { - return m_Services.Keys.ToList(); - } - - public List GetAllServiceUrls() - { - return m_Services.Values.Select(unityConnectData => unityConnectData.serviceUrl).ToList(); - } - - public class ServiceInfo - { - public ServiceInfo(string name, string url, string unityPath, bool enabled) - { - this.name = name; - this.url = url; - this.unityPath = unityPath; - this.enabled = enabled; - } - - public string name; - public string url; - public string unityPath; - public bool enabled; - } - - public ServiceInfo[] GetAllServiceInfos() - { - return m_Services.Select(item => new ServiceInfo(item.Value.serviceName, item.Value.serviceUrl, item.Value.serviceJsGlobalObjectName, item.Value.serviceJsGlobalObject.IsServiceEnabled())).ToArray(); - } - - public WebView GetWebViewFromServiceName(string serviceName) - { - if (s_UnityConnectEditorWindow == null || !s_UnityConnectEditorWindow.UrlsMatch(GetAllServiceUrls())) - return null; - - if (!m_Services.ContainsKey(serviceName)) - return null; - - ConnectInfo state = UnityConnect.instance.connectInfo; - string actualName = GetActualServiceName(serviceName, state); - var url = m_Services[actualName].serviceUrl; - return s_UnityConnectEditorWindow.GetWebViewFromURL(url); - } - - public void UnbindAllServices() - { - foreach (var service in m_Services.Values) - { - service.OnProjectUnbound(); - } - } - } -} diff --git a/Editor/Mono/UnityConnect/UnityConnectServiceData.cs b/Editor/Mono/UnityConnect/UnityConnectServiceData.cs deleted file mode 100644 index 468478fbb2..0000000000 --- a/Editor/Mono/UnityConnect/UnityConnectServiceData.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor.Web; - -namespace UnityEditor.Connect -{ - internal class UnityConnectServiceData - { - private readonly string m_ServiceName; - private readonly string m_HtmlSourcePath; - private readonly CloudServiceAccess m_JavascriptGlobalObject; - private readonly string m_JsGlobalObjectName; - public string serviceName { get { return m_ServiceName; }} - public string serviceUrl - { - get - { - return UnityConnectPrefs.FixUrl(m_HtmlSourcePath, m_ServiceName); - } - } - public CloudServiceAccess serviceJsGlobalObject { get { return m_JavascriptGlobalObject; }} - public string serviceJsGlobalObjectName {get { return m_JsGlobalObjectName; }} - - - public UnityConnectServiceData(string serviceName, string htmlSourcePath, CloudServiceAccess jsGlobalObject, string jsGlobalObjectName) - { - if (string.IsNullOrEmpty(serviceName)) - throw new ArgumentNullException("serviceName"); - - if (string.IsNullOrEmpty(htmlSourcePath)) - throw new ArgumentNullException("htmlSourcePath"); - - m_ServiceName = serviceName; - m_HtmlSourcePath = htmlSourcePath; - m_JavascriptGlobalObject = jsGlobalObject; - m_JsGlobalObjectName = jsGlobalObjectName; - if (m_JavascriptGlobalObject != null) - { - //If no name is specified use the service name - if (string.IsNullOrEmpty(m_JsGlobalObjectName)) - m_JsGlobalObjectName = m_ServiceName; - - JSProxyMgr.GetInstance().AddGlobalObject(m_JsGlobalObjectName, m_JavascriptGlobalObject); - } - } - - public void EnableService(bool enabled) - { - if (m_JavascriptGlobalObject != null) - { - m_JavascriptGlobalObject.EnableService(enabled); - } - } - - public void OnProjectUnbound() - { - if (m_JavascriptGlobalObject != null) - { - m_JavascriptGlobalObject.OnProjectUnbound(); - } - } - } -} diff --git a/Editor/Mono/Utils/AssemblyReferenceChecker.cs b/Editor/Mono/Utils/AssemblyReferenceChecker.cs deleted file mode 100644 index e908b6e719..0000000000 --- a/Editor/Mono/Utils/AssemblyReferenceChecker.cs +++ /dev/null @@ -1,309 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using Mono.Cecil; -using Mono.Cecil.Cil; - -namespace UnityEditor -{ - internal class AssemblyReferenceChecker - { - private readonly HashSet _referencedMethods = new HashSet(); - private HashSet _referencedTypes = new HashSet(); - private readonly HashSet _userReferencedMethods = new HashSet(); - private readonly HashSet _definedMethods = new HashSet(); - private HashSet _assemblyDefinitions = new HashSet(); - private readonly HashSet _assemblyFileNames = new HashSet(); - - private DateTime _startTime = DateTime.MinValue; - private float _progressValue = 0.0f; - - private Action _updateProgressAction; - - public bool HasMouseEvent { get; private set; } - - public AssemblyReferenceChecker() - { - HasMouseEvent = false; - _updateProgressAction = DisplayProgress; - } - - public static AssemblyReferenceChecker AssemblyReferenceCheckerWithUpdateProgressAction(Action action) - { - var checker = new AssemblyReferenceChecker(); - checker._updateProgressAction = action; - return checker; - } - - // Follows actually referenced libraries only - private void CollectReferencesFromRootsRecursive(string dir, IEnumerable roots, bool ignoreSystemDlls) - { - var resolver = AssemblyResolverFor(dir); - - foreach (var assemblyFileName in roots) - { - var fileName = Path.Combine(dir, assemblyFileName); - if (_assemblyFileNames.Contains(assemblyFileName)) - continue; - - var assemblyDefinition = AssemblyDefinition.ReadAssembly(fileName, new ReaderParameters { AssemblyResolver = resolver }); - - if (ignoreSystemDlls && IsIgnoredSystemDll(assemblyDefinition)) - continue; - - _assemblyFileNames.Add(assemblyFileName); - _assemblyDefinitions.Add(assemblyDefinition); - - foreach (var reference in assemblyDefinition.MainModule.AssemblyReferences) - { - var refFileName = reference.Name + ".dll"; - if (_assemblyFileNames.Contains(refFileName)) - continue; - CollectReferencesFromRootsRecursive(dir, new string[] {refFileName}, ignoreSystemDlls); - } - } - } - - // Follows actually referenced libraries only - public void CollectReferencesFromRoots(string dir, IEnumerable roots, bool collectMethods, float progressValue, bool ignoreSystemDlls) - { - _progressValue = progressValue; - - CollectReferencesFromRootsRecursive(dir, roots, ignoreSystemDlls); - - var assemblyDefinitionsAsArray = _assemblyDefinitions.ToArray(); - _referencedTypes = MonoAOTRegistration.BuildReferencedTypeList(assemblyDefinitionsAsArray); - - if (collectMethods) - CollectReferencedAndDefinedMethods(assemblyDefinitionsAsArray); - } - - public void CollectReferences(string path, bool collectMethods, float progressValue, bool ignoreSystemDlls) - { - _progressValue = progressValue; - - _assemblyDefinitions = new HashSet(); - - var filePaths = Directory.Exists(path) ? Directory.GetFiles(path) : new string[0]; - - var resolver = AssemblyResolverFor(path); - - foreach (var filePath in filePaths) - { - if (Path.GetExtension(filePath) != ".dll") - continue; - - var assembly = AssemblyDefinition.ReadAssembly(filePath, new ReaderParameters { AssemblyResolver = resolver }); - - if (ignoreSystemDlls && IsIgnoredSystemDll(assembly)) - continue; - - _assemblyFileNames.Add(Path.GetFileName(filePath)); - _assemblyDefinitions.Add(assembly); - } - - var assemblyDefinitionsAsArray = _assemblyDefinitions.ToArray(); - _referencedTypes = MonoAOTRegistration.BuildReferencedTypeList(assemblyDefinitionsAsArray); - - if (collectMethods) - CollectReferencedAndDefinedMethods(assemblyDefinitionsAsArray); - } - - private void CollectReferencedAndDefinedMethods(IEnumerable assemblyDefinitions) - { - foreach (var assembly in assemblyDefinitions) - { - bool boolIsSystem = IsIgnoredSystemDll(assembly); - foreach (var type in assembly.MainModule.Types) - CollectReferencedAndDefinedMethods(type, boolIsSystem); - } - } - - internal void CollectReferencedAndDefinedMethods(TypeDefinition type) - { - CollectReferencedAndDefinedMethods(type, false); - } - - internal void CollectReferencedAndDefinedMethods(TypeDefinition type, bool isSystem) - { - if (_updateProgressAction != null) - _updateProgressAction(); - - foreach (var nestedType in type.NestedTypes) - CollectReferencedAndDefinedMethods(nestedType, isSystem); - - foreach (var method in type.Methods) - { - if (!method.HasBody) - continue; - - foreach (var instr in method.Body.Instructions) - { - if (OpCodes.Call == instr.OpCode) - { - var name = instr.Operand.ToString(); - if (!isSystem) - { - _userReferencedMethods.Add(name); - } - _referencedMethods.Add(name); - } - } - _definedMethods.Add(method.ToString()); - - HasMouseEvent |= MethodIsMouseEvent(method); - } - } - - private bool MethodIsMouseEvent(MethodDefinition method) - { - var methodNameIsMouseEvent = - method.Name == "OnMouseDown" - || method.Name == "OnMouseDrag" - || method.Name == "OnMouseEnter" - || method.Name == "OnMouseExit" - || method.Name == "OnMouseOver" - || method.Name == "OnMouseUp" - || method.Name == "OnMouseUpAsButton"; - - if (!methodNameIsMouseEvent) - return false; - - if (method.Parameters.Count != 0) - return false; - - bool isInUnityEngineBehavior = InheritsFromMonoBehaviour(method.DeclaringType); - - if (!isInUnityEngineBehavior) - return false; - - return true; - } - - private bool InheritsFromMonoBehaviour(TypeReference type) - { - // Case 833157: StagingArea\Data\Managed contains user and dependency assemblies, but doesn't contain UnityEngine.dll. This applies for all platforms - // Thus we wouldn't be able to load UnityEngine.dll when Resolve() is called. That's why we're delaying Resolve() as much as possible - if (type.Namespace == "UnityEngine" && type.Name == "MonoBehaviour") - return true; - - try - { - var typeDefinition = type.Resolve(); - if (typeDefinition.BaseType != null) - return InheritsFromMonoBehaviour(typeDefinition.BaseType); - } - catch (AssemblyResolutionException) - { - // We weren't able to resolve the base type - let's assume it's not a monobehaviour - } - - return false; - } - - private void DisplayProgress() - { - var elapsedTime = DateTime.Now - _startTime; - var progressStrings = new[] - { - "Fetching assembly references", - "Building list of referenced assemblies..." - }; - - if (elapsedTime.TotalMilliseconds >= 100) - { - if (EditorUtility.DisplayCancelableProgressBar(progressStrings[0], progressStrings[1], _progressValue)) - throw new OperationCanceledException(); - - _startTime = DateTime.Now; - } - } - - public bool HasReferenceToMethod(string methodName) - { - return HasReferenceToMethod(methodName, false); - } - - public bool HasReferenceToMethod(string methodName, bool ignoreSystemDlls) - { - return !ignoreSystemDlls? _referencedMethods.Any(item => item.Contains(methodName)) : _userReferencedMethods.Any(item => item.Contains(methodName)); - } - - public bool HasDefinedMethod(string methodName) - { - return _definedMethods.Any(item => item.Contains(methodName)); - } - - public bool HasReferenceToType(string typeName) - { - return _referencedTypes.Any(item => item.StartsWith(typeName)); - } - - public AssemblyDefinition[] GetAssemblyDefinitions() - { - return _assemblyDefinitions.ToArray(); - } - - public string[] GetAssemblyFileNames() - { - return _assemblyFileNames.ToArray(); - } - - public string WhoReferencesClass(string klass, bool ignoreSystemDlls) - { - foreach (var assembly in _assemblyDefinitions) - { - if (ignoreSystemDlls && IsIgnoredSystemDll(assembly)) - continue; - - var assemblyDefinitionsAsArray = new[] {assembly}; - var types = MonoAOTRegistration.BuildReferencedTypeList(assemblyDefinitionsAsArray); - - if (types.Any(item => item.StartsWith(klass))) - return assembly.Name.Name; - } - - return null; - } - - public static bool IsIgnoredSystemDll(AssemblyDefinition assembly) - { - if (AssemblyHelper.IsUnityEngineModule(assembly)) - return true; - var name = assembly.Name.Name; - return name.StartsWith("System") - || name.Equals("UnityEngine") - || name.Equals("UnityEngine.Networking") - || name.Equals("Mono.Posix") - || name.Equals("Moq"); - } - - public static bool GetScriptsHaveMouseEvents(string path) - { - var checker = new AssemblyReferenceChecker(); - checker.CollectReferences(path, true, 0.0f, true); - - return checker.HasMouseEvent; - } - - private static DefaultAssemblyResolver AssemblyResolverFor(string path) - { - var resolver = new DefaultAssemblyResolver(); - if (File.Exists(path) || Directory.Exists(path)) - { - var attributes = File.GetAttributes(path); - if ((attributes & FileAttributes.Directory) != FileAttributes.Directory) - path = Path.GetDirectoryName(path); - resolver.AddSearchDirectory(Path.GetFullPath(path)); - } - - return resolver; - } - } -} diff --git a/Editor/Mono/Utils/EditorExtensionMethods.cs b/Editor/Mono/Utils/EditorExtensionMethods.cs deleted file mode 100644 index 4d8e311798..0000000000 --- a/Editor/Mono/Utils/EditorExtensionMethods.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; -using System.Linq; -using System.Collections.Generic; - -namespace UnityEditor -{ - internal static class EditorExtensionMethods - { - // Use this method when checking if user hit Space or Return in order to activate the main action - // for a control, such as opening a popup menu or color picker. - internal static bool MainActionKeyForControl(this UnityEngine.Event evt, int controlId) - { - if (EditorGUIUtility.keyboardControl != controlId) - return false; - - bool anyModifiers = (evt.alt || evt.shift || evt.command || evt.control); - - // Block window maximize (on OSX ML, we need to show the menu as part of the KeyCode event, so we can't do the usual check) - if (evt.type == EventType.KeyDown && evt.character == ' ' && !anyModifiers) - { - evt.Use(); - return false; - } - - // Space or return is action key - return evt.type == EventType.KeyDown && - (evt.keyCode == KeyCode.Space || evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter) && - !anyModifiers; - } - - internal static bool IsArrayOrList(this Type listType) - { - if (listType.IsArray) - { - return true; - } - else if (listType.IsGenericType && listType.GetGenericTypeDefinition() == typeof(List<>)) - { - return true; - } - return false; - } - - internal static Type GetArrayOrListElementType(this Type listType) - { - if (listType.IsArray) - { - return listType.GetElementType(); - } - else if (listType.IsGenericType && listType.GetGenericTypeDefinition() == typeof(List<>)) - { - return listType.GetGenericArguments()[0]; - } - return null; - } - - internal static List EnumGetNonObsoleteValues(this Type type) - { - // each enum value has the same position in both values and names arrays - string[] names = Enum.GetNames(type); - Enum[] values = Enum.GetValues(type).Cast().ToArray(); - var result = new List(); - for (int i = 0; i < names.Length; i++) - { - var info = type.GetMember(names[i]); - var attrs = info[0].GetCustomAttributes(typeof(ObsoleteAttribute), false); - var isObsolete = false; - foreach (var attr in attrs) - { - if (attr is ObsoleteAttribute) - isObsolete = true; - } - if (!isObsolete) - result.Add(values[i]); - } - return result; - } - } -} diff --git a/Editor/Mono/Utils/ExpressionEvaluator.cs b/Editor/Mono/Utils/ExpressionEvaluator.cs deleted file mode 100644 index 46e39fad99..0000000000 --- a/Editor/Mono/Utils/ExpressionEvaluator.cs +++ /dev/null @@ -1,434 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Globalization; - -namespace UnityEditor -{ - // Evaluates simple expressions, supports int & float and operators: + - * / % ^ ( ) - public class ExpressionEvaluator - { - private readonly static Operator[] s_Operators = - { - new Operator('-', 2, 2, Associativity.Left), - new Operator('+', 2, 2, Associativity.Left), - new Operator('/', 3, 2, Associativity.Left), - new Operator('*', 3, 2, Associativity.Left), - new Operator('%', 3, 2, Associativity.Left), - new Operator('^', 4, 2, Associativity.Right), - new Operator('u', 4, 1, Associativity.Left) // unary minus trick. For example we convert 2/-7+(-9*8)*2^-9-5 to 2/u7+(u9*8)*2^u9-5 before evaluation - }; - - private enum Associativity { Left, Right } - - private struct Operator - { - public char character; - public int presedence; - public Associativity associativity; - public int inputs; - - public Operator(char character, int presedence, int inputs, Associativity associativity) - { - this.character = character; - this.presedence = presedence; - this.inputs = inputs; - this.associativity = associativity; - } - } - - public static T Evaluate(string expression) - { - T result = default(T); - - if (!TryParse(expression, out result)) - { - expression = PreFormatExpression(expression); - string[] infixTokens = ExpressionToTokens(expression); - infixTokens = FixUnaryOperators(infixTokens); - string[] RPNTokens = InfixToRPN(infixTokens); - result = Evaluate(RPNTokens); - } - - return result; - } - - // Evaluate RPN tokens (http://en.wikipedia.org/wiki/Reverse_Polish_notation) - private static T Evaluate(string[] tokens) - { - Stack stack = new Stack(); - - foreach (string token in tokens) - { - if (IsOperator(token)) - { - Operator oper = CharToOperator(token[0]); - List values = new List(); - bool parsed = true; - - while (stack.Count > 0 && !IsCommand(stack.Peek()) && values.Count < oper.inputs) - { - T newValue; - parsed &= TryParse(stack.Pop(), out newValue); - values.Add(newValue); - } - - values.Reverse(); - - if (parsed && values.Count == oper.inputs) - stack.Push(Evaluate(values.ToArray(), token[0]).ToString()); - else // Can't parse values or too few values for the operator -> exit - return default(T); - } - else - { - stack.Push(token); - } - } - - if (stack.Count == 1) - { - T resultT; - if (TryParse(stack.Pop(), out resultT)) - return resultT; - } - - return default(T); - } - - // Translate tokens from infix into RPN (http://en.wikipedia.org/wiki/Shunting-yard_algorithm) - private static string[] InfixToRPN(string[] tokens) - { - Stack operatorStack = new Stack(); - Queue outputQueue = new Queue(); - - foreach (string token in tokens) - { - if (IsCommand(token)) - { - char command = token[0]; - - if (command == '(') // Bracket open - { - operatorStack.Push(command); - } - else if (command == ')') // Bracket close - { - while (operatorStack.Count > 0 && operatorStack.Peek() != '(') - outputQueue.Enqueue(operatorStack.Pop().ToString()); - - if (operatorStack.Count > 0) - operatorStack.Pop(); - } - else // All the other operators - { - Operator o = CharToOperator(command); - - while (NeedToPop(operatorStack, o)) - outputQueue.Enqueue(operatorStack.Pop().ToString()); - - operatorStack.Push(command); - } - } - else // Not a command, just a regular number - { - outputQueue.Enqueue(token); - } - } - while (operatorStack.Count > 0) - outputQueue.Enqueue(operatorStack.Pop().ToString()); - - return outputQueue.ToArray(); - } - - // While there is an operator (topOfStack) at the top of the operators stack and - // either (newOperator) is left-associative and its precedence is less or equal to that of (topOfStack), or - // (newOperator) is right-associative and its precedence is less than (topOfStack) - private static bool NeedToPop(Stack operatorStack, Operator newOperator) - { - if (operatorStack.Count > 0) - { - Operator topOfStack = CharToOperator(operatorStack.Peek()); - - if (IsOperator(topOfStack.character)) - { - if (newOperator.associativity == Associativity.Left && newOperator.presedence <= topOfStack.presedence || - newOperator.associativity == Associativity.Right && newOperator.presedence < topOfStack.presedence) - { - return true; - } - } - } - return false; - } - - // Splits expression to meaningful tokens - private static string[] ExpressionToTokens(string expression) - { - List result = new List(); - string currentString = ""; - - for (int c = 0; c < expression.Length; c++) - { - char currentChar = expression[c]; - if (IsCommand(currentChar)) - { - if (currentString.Length > 0) - result.Add(currentString); - - result.Add(currentChar.ToString()); - currentString = ""; - } - else - { - if (currentChar != ' ') - currentString += currentChar; - } - } - - if (currentString.Length > 0) - result.Add(currentString); - - return result.ToArray(); - } - - private static bool IsCommand(string token) - { - if (token.Length != 1) - return false; - - return IsCommand(token[0]); - } - - private static bool IsCommand(char character) - { - if (character == '(' || character == ')') - return true; - - return IsOperator(character); - } - - private static bool IsOperator(string token) - { - if (token.Length != 1) - return false; - - return IsOperator(token[0]); - } - - private static bool IsOperator(char character) - { - foreach (Operator o in s_Operators) - if (o.character == character) - return true; - - return false; - } - - private static Operator CharToOperator(char character) - { - foreach (Operator o in s_Operators) - if (o.character == character) - return o; - - return new Operator(); - } - - // Clean up the expression before any parsing - private static string PreFormatExpression(string expression) - { - string result = expression; - result = result.Trim(); - - if (result.Length == 0) - return result; - - char lastChar = result[result.Length - 1]; - - // remove trailing operator for niceness (user is middle of typing, and we don't want to evaluate to zero) - if (IsOperator(lastChar)) - result = result.TrimEnd(lastChar); - - return result; - } - - // Turn unary minus into an operator. For example: - ( 1 - 2 ) * - 3 becomes: u ( 1 - 2 ) * u 3 - private static string[] FixUnaryOperators(string[] tokens) - { - if (tokens.Length == 0) - return tokens; - - if (tokens[0] == "-") - tokens[0] = "u"; - - for (int i = 1; i < tokens.Length - 1; i++) - { - string token = tokens[i]; - string previousToken = tokens[i - 1]; - string nextToken = tokens[i - 1]; - - if (token == "-" && (IsCommand(previousToken) || nextToken == "(" || nextToken == ")")) - tokens[i] = "u"; - } - return tokens; - } - - // According to internetz, there are many bad ways to do arithmetics with generics. This is one of them. - private static T Evaluate(T[] values, char oper) - { - if (typeof(T) == typeof(float)) - { - if (values.Length == 1) - { - switch (oper) - { - case 'u': - return (T)(object)((float)(object)values[0] * -1.0f); - } - } - else if (values.Length == 2) - { - switch (oper) - { - case '+': - return (T)(object)((float)(object)values[0] + (float)(object)values[1]); - case '-': - return (T)(object)((float)(object)values[0] - (float)(object)values[1]); - case '*': - return (T)(object)((float)(object)values[0] * (float)(object)values[1]); - case '/': - return (T)(object)((float)(object)values[0] / (float)(object)values[1]); - case '%': - return (T)(object)((float)(object)values[0] % (float)(object)values[1]); - case '^': - return (T)(object)UnityEngine.Mathf.Pow((float)(object)values[0], (float)(object)values[1]); - } - } - } - else if (typeof(T) == typeof(int)) - { - if (values.Length == 1) - { - switch (oper) - { - case 'u': - return (T)(object)((int)(object)values[0] * -1); - } - } - else if (values.Length == 2) - { - switch (oper) - { - case '+': - return (T)(object)((int)(object)values[0] + (int)(object)values[1]); - case '-': - return (T)(object)((int)(object)values[0] - (int)(object)values[1]); - case '*': - return (T)(object)((int)(object)values[0] * (int)(object)values[1]); - case '/': - return (T)(object)((int)(object)values[0] / (int)(object)values[1]); - case '%': - return (T)(object)((int)(object)values[0] % (int)(object)values[1]); - case '^': - return (T)(object)(int)Math.Pow((int)(object)values[0], (int)(object)values[1]); - } - } - } - if (typeof(T) == typeof(double)) - { - if (values.Length == 1) - { - switch (oper) - { - case 'u': - return (T)(object)((double)(object)values[0] * -1.0f); - } - } - else if (values.Length == 2) - { - switch (oper) - { - case '+': - return (T)(object)((double)(object)values[0] + (double)(object)values[1]); - case '-': - return (T)(object)((double)(object)values[0] - (double)(object)values[1]); - case '*': - return (T)(object)((double)(object)values[0] * (double)(object)values[1]); - case '/': - return (T)(object)((double)(object)values[0] / (double)(object)values[1]); - case '%': - return (T)(object)((double)(object)values[0] % (double)(object)values[1]); - case '^': - return (T)(object)System.Math.Pow((double)(object)values[0], (double)(object)values[1]); - } - } - } - else if (typeof(T) == typeof(long)) - { - if (values.Length == 1) - { - switch (oper) - { - case 'u': - return (T)(object)((long)(object)values[0] * -1); - } - } - else if (values.Length == 2) - { - switch (oper) - { - case '+': - return (T)(object)((long)(object)values[0] + (long)(object)values[1]); - case '-': - return (T)(object)((long)(object)values[0] - (long)(object)values[1]); - case '*': - return (T)(object)((long)(object)values[0] * (long)(object)values[1]); - case '/': - return (T)(object)((long)(object)values[0] / (long)(object)values[1]); - case '%': - return (T)(object)((long)(object)values[0] % (long)(object)values[1]); - case '^': - return (T)(object)(long)System.Math.Pow((long)(object)values[0], (long)(object)values[1]); - } - } - } - return default(T); - } - - private static bool TryParse(string expression, out T result) - { - expression = expression.Replace(',', '.'); - - bool success = false; - result = default(T); - if (typeof(T) == typeof(float)) - { - float temp = 0.0f; - success = float.TryParse(expression, NumberStyles.Float, CultureInfo.InvariantCulture.NumberFormat, out temp); - result = (T)(object)temp; - } - else if (typeof(T) == typeof(int)) - { - int temp = 0; - success = int.TryParse(expression, NumberStyles.Integer, CultureInfo.InvariantCulture.NumberFormat, out temp); - result = (T)(object)temp; - } - else if (typeof(T) == typeof(double)) - { - double temp = 0; - success = double.TryParse(expression, NumberStyles.Float, CultureInfo.InvariantCulture.NumberFormat, out temp); - result = (T)(object)temp; - } - else if (typeof(T) == typeof(long)) - { - long temp = 0; - success = long.TryParse(expression, NumberStyles.Integer, CultureInfo.InvariantCulture.NumberFormat, out temp); - result = (T)(object)temp; - } - return success; - } - } -} diff --git a/Editor/Mono/Utils/IDeviceUtils.cs b/Editor/Mono/Utils/IDeviceUtils.cs deleted file mode 100644 index a855a393a8..0000000000 --- a/Editor/Mono/Utils/IDeviceUtils.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEditor.Modules; - - -namespace UnityEditor -{ - internal static class IDeviceUtils - { - // API for native calls - internal static RemoteAddress StartRemoteSupport(string deviceId) - { - IDevice device = ModuleManager.GetDevice(deviceId); - return device.StartRemoteSupport(); - } - - // API for native calls - internal static void StopRemoteSupport(string deviceId) - { - IDevice device = ModuleManager.GetDevice(deviceId); - device.StopRemoteSupport(); - } - - // API for native calls - internal static RemoteAddress StartPlayerConnectionSupport(string deviceId) - { - IDevice device = ModuleManager.GetDevice(deviceId); - return device.StartPlayerConnectionSupport(); - } - - // API for native calls - internal static void StopPlayerConnectionSupport(string deviceId) - { - IDevice device = ModuleManager.GetDevice(deviceId); - device.StopPlayerConnectionSupport(); - } - } -} diff --git a/Editor/Mono/Utils/LightProbeGroupSelection.cs b/Editor/Mono/Utils/LightProbeGroupSelection.cs deleted file mode 100644 index 5fcd207883..0000000000 --- a/Editor/Mono/Utils/LightProbeGroupSelection.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - internal class LightProbeGroupSelection : ScriptableObject - { - public List m_Selection = new List(); - } -} diff --git a/Editor/Mono/Utils/ManagedProgram.cs b/Editor/Mono/Utils/ManagedProgram.cs deleted file mode 100644 index 475c8d3377..0000000000 --- a/Editor/Mono/Utils/ManagedProgram.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Diagnostics; -using System.IO; -using UnityEditor.Scripting.Compilers; -using UnityEditor.Utils; -using UnityEngine; - -namespace UnityEditor.Scripting -{ - internal class ManagedProgram : Program - { - public ManagedProgram(string monodistribution, string profile, string executable, string arguments, Action setupStartInfo) : - this(monodistribution, profile, executable, arguments, true, setupStartInfo) - { - } - - public ManagedProgram(string monodistribution, string profile, string executable, string arguments, bool setMonoEnvironmentVariables, Action setupStartInfo) - { - var monoexe = PathCombine(monodistribution, "bin", "mono"); - if (Application.platform == RuntimePlatform.WindowsEditor) - monoexe = CommandLineFormatter.PrepareFileName(monoexe + ".exe"); - - var startInfo = new ProcessStartInfo - { - Arguments = CommandLineFormatter.PrepareFileName(executable) + " " + arguments, - CreateNoWindow = true, - FileName = monoexe, - RedirectStandardError = true, - RedirectStandardOutput = true, - WorkingDirectory = Application.dataPath + "/..", - UseShellExecute = false - }; - - if (setMonoEnvironmentVariables) - { - var profileAbspath = PathCombine(monodistribution, "lib", "mono", profile); - startInfo.EnvironmentVariables["MONO_PATH"] = profileAbspath; - startInfo.EnvironmentVariables["MONO_CFG_DIR"] = PathCombine(monodistribution, "etc"); - } - - // if you ever need to debug assembly loading, uncomment the following two lines - //startInfo.EnvironmentVariables["MONO_LOG_LEVEL"] = "info"; - //startInfo.EnvironmentVariables["MONO_LOG_MASK"] = "asm"; - - if (setupStartInfo != null) - setupStartInfo(startInfo); - - _process.StartInfo = startInfo; - } - - static string PathCombine(params string[] parts) - { - var path = parts[0]; - for (var i = 1; i < parts.Length; ++i) - path = Path.Combine(path, parts[i]); - return path; - } - } -} diff --git a/Editor/Mono/Utils/MathUtils.cs b/Editor/Mono/Utils/MathUtils.cs deleted file mode 100644 index a15e92e725..0000000000 --- a/Editor/Mono/Utils/MathUtils.cs +++ /dev/null @@ -1,498 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - public class MathUtils - { - // We cannot round to more decimals than 15 according to docs for System.Math.Round. - private const int kMaxDecimals = 15; - - internal static float ClampToFloat(double value) - { - if (double.IsPositiveInfinity(value)) - return float.PositiveInfinity; - - if (double.IsNegativeInfinity(value)) - return float.NegativeInfinity; - - if (value < float.MinValue) - return float.MinValue; - - if (value > float.MaxValue) - return float.MaxValue; - - return (float)value; - } - - internal static int ClampToInt(long value) - { - if (value < int.MinValue) - return int.MinValue; - - if (value > int.MaxValue) - return int.MaxValue; - - return (int)value; - } - - internal static float RoundToMultipleOf(float value, float roundingValue) - { - if (roundingValue == 0) - return value; - return Mathf.Round(value / roundingValue) * roundingValue; - } - - internal static float GetClosestPowerOfTen(float positiveNumber) - { - if (positiveNumber <= 0) - return 1; - return Mathf.Pow(10, Mathf.RoundToInt(Mathf.Log10(positiveNumber))); - } - - internal static int GetNumberOfDecimalsForMinimumDifference(float minDifference) - { - return Mathf.Clamp(-Mathf.FloorToInt(Mathf.Log10(Mathf.Abs(minDifference))), 0, kMaxDecimals); - } - - internal static int GetNumberOfDecimalsForMinimumDifference(double minDifference) - { - return (int)System.Math.Max(0.0, -System.Math.Floor(System.Math.Log10(System.Math.Abs(minDifference)))); - } - - internal static float RoundBasedOnMinimumDifference(float valueToRound, float minDifference) - { - if (minDifference == 0) - return DiscardLeastSignificantDecimal(valueToRound); - return (float)System.Math.Round(valueToRound, GetNumberOfDecimalsForMinimumDifference(minDifference), System.MidpointRounding.AwayFromZero); - } - - internal static double RoundBasedOnMinimumDifference(double valueToRound, double minDifference) - { - if (minDifference == 0) - return DiscardLeastSignificantDecimal(valueToRound); - return System.Math.Round(valueToRound, GetNumberOfDecimalsForMinimumDifference(minDifference), System.MidpointRounding.AwayFromZero); - } - - internal static float DiscardLeastSignificantDecimal(float v) - { - int decimals = Mathf.Clamp((int)(5 - Mathf.Log10(Mathf.Abs(v))), 0, kMaxDecimals); - return (float)System.Math.Round(v, decimals, System.MidpointRounding.AwayFromZero); - } - - internal static double DiscardLeastSignificantDecimal(double v) - { - int decimals = System.Math.Max(0, (int)(5 - System.Math.Log10(System.Math.Abs(v)))); - try - { - return System.Math.Round(v, decimals); - } - catch (System.ArgumentOutOfRangeException) - { - // This can happen for very small numbers. - return 0; - } - } - - public static float GetQuatLength(Quaternion q) - { - return Mathf.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w); - } - - public static Quaternion GetQuatConjugate(Quaternion q) - { - return new Quaternion(-q.x, -q.y, -q.z, q.w); - } - - public static Matrix4x4 OrthogonalizeMatrix(Matrix4x4 m) - { - Matrix4x4 n = Matrix4x4.identity; - - Vector3 i = m.GetColumn(0); - Vector3 j = m.GetColumn(1); - Vector3 k = m.GetColumn(2); - k = k.normalized; - i = Vector3.Cross(j, k).normalized; - j = Vector3.Cross(k, i).normalized; - - n.SetColumn(0, i); - n.SetColumn(1, j); - n.SetColumn(2, k); - - return n; - } - - public static void QuaternionNormalize(ref Quaternion q) - { - float invMag = 1.0f / Mathf.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w); - q.x *= invMag; - q.y *= invMag; - q.z *= invMag; - q.w *= invMag; - } - - public static Quaternion QuaternionFromMatrix(Matrix4x4 m) - { - // Adapted from: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm - Quaternion q = new Quaternion(); - q.w = Mathf.Sqrt(Mathf.Max(0, 1 + m[0, 0] + m[1, 1] + m[2, 2])) / 2; - q.x = Mathf.Sqrt(Mathf.Max(0, 1 + m[0, 0] - m[1, 1] - m[2, 2])) / 2; - q.y = Mathf.Sqrt(Mathf.Max(0, 1 - m[0, 0] + m[1, 1] - m[2, 2])) / 2; - q.z = Mathf.Sqrt(Mathf.Max(0, 1 - m[0, 0] - m[1, 1] + m[2, 2])) / 2; - q.x *= Mathf.Sign(q.x * (m[2, 1] - m[1, 2])); - q.y *= Mathf.Sign(q.y * (m[0, 2] - m[2, 0])); - q.z *= Mathf.Sign(q.z * (m[1, 0] - m[0, 1])); - // normalize - QuaternionNormalize(ref q); - return q; - } - - /// - /// Logarithm of a unit quaternion. The result is not necessary a unit quaternion. - /// - public static Quaternion GetQuatLog(Quaternion q) - { - Quaternion res = q; - res.w = 0; - - if (Mathf.Abs(q.w) < 1.0f) - { - float theta = Mathf.Acos(q.w); - float sin_theta = Mathf.Sin(theta); - - if (Mathf.Abs(sin_theta) > 0.0001) - { - float coef = theta / sin_theta; - res.x = q.x * coef; - res.y = q.y * coef; - res.z = q.z * coef; - } - } - - return res; - } - - public static Quaternion GetQuatExp(Quaternion q) - { - Quaternion res = q; - - float fAngle = Mathf.Sqrt(q.x * q.x + q.y * q.y + q.z * q.z); - float fSin = Mathf.Sin(fAngle); - - res.w = Mathf.Cos(fAngle); - - if (Mathf.Abs(fSin) > 0.0001) - { - float coef = fSin / fAngle; - res.x = coef * q.x; - res.y = coef * q.y; - res.z = coef * q.z; - } - - return res; - } - - /// - /// SQUAD Spherical Quadrangle interpolation [Shoe87] - /// - public static Quaternion GetQuatSquad(float t, Quaternion q0, Quaternion q1, Quaternion a0, Quaternion a1) - { - float slerpT = 2.0f * t * (1.0f - t); - - Quaternion slerpP = Slerp(q0, q1, t); - Quaternion slerpQ = Slerp(a0, a1, t); - Quaternion slerp = Slerp(slerpP, slerpQ, slerpT); - - // normalize quaternion - float l = Mathf.Sqrt(slerp.x * slerp.x + slerp.y * slerp.y + slerp.z * slerp.z + slerp.w * slerp.w); - slerp.x /= l; - slerp.y /= l; - slerp.z /= l; - slerp.w /= l; - - return slerp; - } - - public static Quaternion GetSquadIntermediate(Quaternion q0, Quaternion q1, Quaternion q2) - { - Quaternion q1Inv = GetQuatConjugate(q1); - Quaternion p0 = GetQuatLog(q1Inv * q0); - Quaternion p2 = GetQuatLog(q1Inv * q2); - Quaternion sum = new Quaternion(-0.25f * (p0.x + p2.x), -0.25f * (p0.y + p2.y), -0.25f * (p0.z + p2.z), -0.25f * (p0.w + p2.w)); - - return q1 * GetQuatExp(sum); - } - - /// - /// Smooths the input parameter t. - /// If less than k1 ir greater than k2, it uses a sin. - /// Between k1 and k2 it uses linear interp. - /// - public static float Ease(float t, float k1, float k2) - { - float f; float s; - - f = k1 * 2 / Mathf.PI + k2 - k1 + (1.0f - k2) * 2 / Mathf.PI; - - if (t < k1) - { - s = k1 * (2 / Mathf.PI) * (Mathf.Sin((t / k1) * Mathf.PI / 2 - Mathf.PI / 2) + 1); - } - else if (t < k2) - { - s = (2 * k1 / Mathf.PI + t - k1); - } - else - { - s = 2 * k1 / Mathf.PI + k2 - k1 + ((1 - k2) * (2 / Mathf.PI)) * Mathf.Sin(((t - k2) / (1.0f - k2)) * Mathf.PI / 2); - } - - return (s / f); - } - - /// - /// We need this because Quaternion.Slerp always uses the shortest arc. - /// - public static Quaternion Slerp(Quaternion p, Quaternion q, float t) - { - Quaternion ret; - - float fCos = Quaternion.Dot(p, q); - - if ((1.0f + fCos) > 0.00001) - { - float fCoeff0, fCoeff1; - - if ((1.0f - fCos) > 0.00001) - { - float omega = Mathf.Acos(fCos); - float invSin = 1.0f / Mathf.Sin(omega); - fCoeff0 = Mathf.Sin((1.0f - t) * omega) * invSin; - fCoeff1 = Mathf.Sin(t * omega) * invSin; - } - else - { - fCoeff0 = 1.0f - t; - fCoeff1 = t; - } - - ret.x = fCoeff0 * p.x + fCoeff1 * q.x; - ret.y = fCoeff0 * p.y + fCoeff1 * q.y; - ret.z = fCoeff0 * p.z + fCoeff1 * q.z; - ret.w = fCoeff0 * p.w + fCoeff1 * q.w; - } - else - { - float fCoeff0 = Mathf.Sin((1.0f - t) * Mathf.PI * 0.5f); - float fCoeff1 = Mathf.Sin(t * Mathf.PI * 0.5f); - - ret.x = fCoeff0 * p.x - fCoeff1 * p.y; - ret.y = fCoeff0 * p.y + fCoeff1 * p.x; - ret.z = fCoeff0 * p.z - fCoeff1 * p.w; - ret.w = p.z; - } - - return ret; - } - - // intersect_RayTriangle(): intersect a ray with a 3D triangle - // Input: a ray R, and 3 vector3 forming a triangle - // Output: *I = intersection point (when it exists) - // Return: null = no intersection - // RaycastHit = intersection - - // -1 = triangle is degenerate (a segment or point) - // 0 = disjoint (no intersect) - // 1 = intersect in unique point I1 - // 2 = are in the same plane - public static object IntersectRayTriangle(Ray ray, Vector3 v0, Vector3 v1, Vector3 v2, bool bidirectional) - { - Vector3 ab = v1 - v0; - Vector3 ac = v2 - v0; - - // Compute triangle normal. Can be precalculated or cached if - // intersecting multiple segments against the same triangle - Vector3 n = Vector3.Cross(ab, ac); - - // Compute denominator d. If d <= 0, segment is parallel to or points - // away from triangle, so exit early - float d = Vector3.Dot(-ray.direction, n); - if (d <= 0.0f) return null; - - // Compute intersection t value of pq with plane of triangle. A ray - // intersects iff 0 <= t. Segment intersects iff 0 <= t <= 1. Delay - // dividing by d until intersection has been found to pierce triangle - Vector3 ap = ray.origin - v0; - float t = Vector3.Dot(ap, n); - if ((t < 0.0f) && (!bidirectional)) return null; - //if (t > d) return null; // For segment; exclude this code line for a ray test - - // Compute barycentric coordinate components and test if within bounds - Vector3 e = Vector3.Cross(-ray.direction, ap); - float v = Vector3.Dot(ac, e); - if (v < 0.0f || v > d) return null; - - float w = -Vector3.Dot(ab, e); - if (w < 0.0f || v + w > d) return null; - - // Segment/ray intersects triangle. Perform delayed division and - // compute the last barycentric coordinate component - float ood = 1.0f / d; - t *= ood; - v *= ood; - w *= ood; - float u = 1.0f - v - w; - - RaycastHit hit = new RaycastHit(); - - hit.point = ray.origin + t * ray.direction; - hit.distance = t; - hit.barycentricCoordinate = new Vector3(u, v, w); - hit.normal = Vector3.Normalize(n); - - return hit; - } - - // Returns closest point on segment - // squaredDist = squared distance between the two closest points - // s = offset along segment - public static Vector3 ClosestPtSegmentRay(Vector3 p1, Vector3 q1, Ray ray, out float squaredDist, out float s, out Vector3 closestRay) - { - Vector3 p2 = ray.origin; - Vector3 q2 = ray.GetPoint(10000.0f); - - Vector3 d1 = q1 - p1; // Direction vector of segment S1 - Vector3 d2 = q2 - p2; // Direction vector of segment S2 - Vector3 r = p1 - p2; - float a = Vector3.Dot(d1, d1); // Squared length of segment S1, always nonnegative - float e = Vector3.Dot(d2, d2); // Squared length of segment S2, always nonnegative - float f = Vector3.Dot(d2, r); - - float t = 0.0f; - - // Check if either or both segments degenerate into points - if (a <= Mathf.Epsilon && e <= Mathf.Epsilon) - { - // Both segments degenerate into points - squaredDist = Vector3.Dot(p1 - p2, p1 - p2); - s = 0.0f; - closestRay = p2; - return p1; - } - - if (a <= Mathf.Epsilon) - { - // First segment degenerates into a point - s = 0.0f; - t = f / e; // s = 0 => t = (b*s + f) / e = f / e - t = Mathf.Clamp(t, 0.0f, 1.0f); - } - else - { - float c = Vector3.Dot(d1, r); - if (e <= Mathf.Epsilon) - { - // Second segment degenerates into a point - t = 0.0f; - s = Mathf.Clamp(-c / a, 0.0f, 1.0f); // t = 0 => s = (b*t - c) / a = -c / a - } - else - { - // The general nondegenerate case starts here - float b = Vector3.Dot(d1, d2); - float denom = a * e - b * b; // Always nonnegative - - // If segments not parallel, compute closest point on L1 to L2, and - // clamp to segment S1. Else pick arbitrary s (here 0) - if (denom != 0.0f) - { - s = Mathf.Clamp((b * f - c * e) / denom, 0.0f, 1.0f); - } - else s = 0.0f; - - // Compute point on L2 closest to S1(s) using - // t = Dot((P1+D1*s)-P2,D2) / Dot(D2,D2) = (b*s + f) / e - t = (b * s + f) / e; - - // If t in [0,1] done. Else clamp t, recompute s for the new value - // of t using s = Dot((P2+D2*t)-P1,D1) / Dot(D1,D1)= (t*b - c) / a - // and clamp s to [0, 1] - if (t < 0.0f) - { - t = 0.0f; - s = Mathf.Clamp(-c / a, 0.0f, 1.0f); - } - else if (t > 1.0f) - { - t = 1.0f; - s = Mathf.Clamp((b - c) / a, 0.0f, 1.0f); - } - } - } - - Vector3 c1 = p1 + d1 * s; - Vector3 c2 = p2 + d2 * t; - squaredDist = Vector3.Dot(c1 - c2, c1 - c2); - closestRay = c2; - return c1; - } - - public static bool IntersectRaySphere(Ray ray, Vector3 sphereOrigin, float sphereRadius, ref float t, ref Vector3 q) - { - Vector3 m = ray.origin - sphereOrigin; - float b = Vector3.Dot(m, ray.direction); - float c = Vector3.Dot(m, m) - (sphereRadius * sphereRadius); - // Exit if r�s origin outside s (c > 0)and r pointing away from s (b > 0) - if ((c > 0.0f) && (b > 0.0f)) return false; - float discr = (b * b) - c; - - // A negative discriminant corresponds to ray missing sphere - if (discr < 0.0f) return false; - - // Ray now found to intersect sphere, compute smallest t value of intersection - t = -b - Mathf.Sqrt(discr); - - // If t is negative, ray started inside sphere so clamp t to zero - if (t < 0.0f) t = 0.0f; - q = ray.origin + t * ray.direction; - return true; - } - - // Closest point - public static bool ClosestPtRaySphere(Ray ray, Vector3 sphereOrigin, float sphereRadius, ref float t, ref Vector3 q) - { - Vector3 m = ray.origin - sphereOrigin; - float b = Vector3.Dot(m, ray.direction); - float c = Vector3.Dot(m, m) - (sphereRadius * sphereRadius); - // Exit if r�s origin outside s (c > 0)and r pointing away from s (b > 0) - if ((c > 0.0f) && (b > 0.0f)) - { - // ray origin is closest - t = 0.0f; - q = ray.origin; - return true; - } - - float discr = (b * b) - c; - - // A negative discriminant corresponds to ray missing sphere - if (discr < 0.0f) - { - discr = 0.0f; - } - - // Ray now found to intersect sphere, compute smallest t value of intersection - t = -b - Mathf.Sqrt(discr); - - // If t is negative, ray started inside sphere so clamp t to zero - if (t < 0.0f) t = 0.0f; - q = ray.origin + t * ray.direction; - return true; - } - } -} diff --git a/Editor/Mono/Utils/MenuUtils.cs b/Editor/Mono/Utils/MenuUtils.cs deleted file mode 100644 index f41528fd1a..0000000000 --- a/Editor/Mono/Utils/MenuUtils.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using System.Collections.Generic; -using Object = UnityEngine.Object; - -namespace UnityEditor -{ - internal class MenuUtils - { - public static void MenuCallback(object callbackObject) - { - MenuCallbackObject menuCallBackObject = callbackObject as MenuCallbackObject; - - if (menuCallBackObject.onBeforeExecuteCallback != null) - menuCallBackObject.onBeforeExecuteCallback(menuCallBackObject.menuItemPath, menuCallBackObject.temporaryContext, menuCallBackObject.userData); - - if (menuCallBackObject.temporaryContext != null) - { - EditorApplication.ExecuteMenuItemWithTemporaryContext(menuCallBackObject.menuItemPath, menuCallBackObject.temporaryContext); - } - else - { - EditorApplication.ExecuteMenuItem(menuCallBackObject.menuItemPath); - } - - if (menuCallBackObject.onAfterExecuteCallback != null) - menuCallBackObject.onAfterExecuteCallback(menuCallBackObject.menuItemPath, menuCallBackObject.temporaryContext, menuCallBackObject.userData); - } - - public static void ExtractSubMenuWithPath(string path, GenericMenu menu, string replacementPath, Object[] temporaryContext) - { - HashSet menusWithCommands = new HashSet(Unsupported.GetSubmenus(path)); - string[] menus = Unsupported.GetSubmenusIncludingSeparators(path); - for (int i = 0; i < menus.Length; i++) - { - string menuString = menus[i]; - string replacedMenuString = replacementPath + menuString.Substring(path.Length); - if (menusWithCommands.Contains(menuString)) - { - ExtractMenuItemWithPath(menuString, menu, replacedMenuString, temporaryContext, -1, null, null); - } - //else // Comment back in when GenericMenu can handle separators - // menu.AddSeparator(replacedMenuString); - } - } - - public static void ExtractMenuItemWithPath(string menuString, GenericMenu menu, string replacementMenuString, Object[] temporaryContext, int userData, Action onBeforeExecuteCallback, Action onAfterExecuteCallback) - { - MenuCallbackObject callbackObject = new MenuCallbackObject(); - callbackObject.menuItemPath = menuString; - callbackObject.temporaryContext = temporaryContext; - callbackObject.onBeforeExecuteCallback = onBeforeExecuteCallback; - callbackObject.onAfterExecuteCallback = onAfterExecuteCallback; - callbackObject.userData = userData; - menu.AddItem(new GUIContent(L10n.TrPath(replacementMenuString)), false, MenuCallback, callbackObject); - } - - private class MenuCallbackObject - { - public string menuItemPath; - public Object[] temporaryContext; - public Action onBeforeExecuteCallback; // - public Action onAfterExecuteCallback; // - public int userData; - } - } -} diff --git a/Editor/Mono/Utils/MetroCertificatePasswordWindow.cs b/Editor/Mono/Utils/MetroCertificatePasswordWindow.cs deleted file mode 100644 index 6eddac1699..0000000000 --- a/Editor/Mono/Utils/MetroCertificatePasswordWindow.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - internal class MetroCertificatePasswordWindow : EditorWindow - { - private static readonly GUILayoutOption kLabelWidth = GUILayout.Width(110); - private static readonly GUILayoutOption kButtonWidth = GUILayout.Width(110); - private const float kSpace = 5; - private const char kPasswordChar = '\u25cf'; - private const string kPasswordId = "password"; - - private string path; - private string password; - private GUIContent message; - private GUIStyle messageStyle; - private string focus; - - public static void Show(string path) - { - var windows = (MetroCertificatePasswordWindow[])Resources.FindObjectsOfTypeAll(typeof(MetroCertificatePasswordWindow)); - var window = ((windows.Length > 0) ? windows[0] : ScriptableObject.CreateInstance()); - - window.path = path; - window.password = string.Empty; - window.message = GUIContent.none; - - window.messageStyle = new GUIStyle(GUI.skin.label); - window.messageStyle.fontStyle = FontStyle.Italic; - - window.focus = kPasswordId; - - if (windows.Length > 0) - { - window.Focus(); - } - else - { - window.titleContent = EditorGUIUtility.TrTextContent("Enter Windows Store Certificate Password"); - - window.position = new Rect(100, 100, 350, 90); - window.minSize = new Vector2(window.position.width, window.position.height); - window.maxSize = window.minSize; - - window.ShowUtility(); - } - } - - public void OnGUI() - { - var e = Event.current; - var close = false; - var enter = false; - - if (e.type == EventType.KeyDown) - { - close = (e.keyCode == KeyCode.Escape); - enter = ((e.keyCode == KeyCode.Return) || (e.keyCode == KeyCode.KeypadEnter)); - } - - using (HorizontalLayout.DoLayout()) - { - GUILayout.Space(kSpace * 2); - - using (VerticalLayout.DoLayout()) - { - GUILayout.FlexibleSpace(); - - using (HorizontalLayout.DoLayout()) - { - GUILayout.Label(EditorGUIUtility.TrTextContent("Password", "Certificate password."), kLabelWidth); - GUI.SetNextControlName(kPasswordId); - password = GUILayout.PasswordField(password, kPasswordChar); - } - - GUILayout.Space(kSpace * 2); - - using (HorizontalLayout.DoLayout()) - { - GUILayout.Label(message, messageStyle); - - GUILayout.FlexibleSpace(); - - if (GUILayout.Button(EditorGUIUtility.TrTextContent("Ok"), kButtonWidth) || enter) - { - message = GUIContent.none; - - try - { - if (PlayerSettings.WSA.SetCertificate(path, password)) - { - close = true; - } - else - { - message = EditorGUIUtility.TrTextContent("Invalid password."); - } - } - catch (UnityException ex) - { - Debug.LogError(ex.Message); - } - } - } - - GUILayout.FlexibleSpace(); - } - - GUILayout.Space(kSpace * 2); - } - - if (close) - { - Close(); - } - else if (focus != null) - { - EditorGUI.FocusTextInControl(focus); - focus = null; - } - } - } -} diff --git a/Editor/Mono/Utils/MetroCreateTestCertificateWindow.cs b/Editor/Mono/Utils/MetroCreateTestCertificateWindow.cs deleted file mode 100644 index 2d63000e67..0000000000 --- a/Editor/Mono/Utils/MetroCreateTestCertificateWindow.cs +++ /dev/null @@ -1,231 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Text.RegularExpressions; -using UnityEngine; -using UnityEditor; - -namespace UnityEditor -{ - internal sealed class HorizontalLayout : IDisposable - { - private static readonly HorizontalLayout instance = new HorizontalLayout(); - - public static IDisposable DoLayout() - { - GUILayout.BeginHorizontal(); - return instance; - } - - private HorizontalLayout() - { - } - - void IDisposable.Dispose() - { - GUILayout.EndHorizontal(); - } - } - internal sealed class VerticalLayout : IDisposable - { - private static readonly VerticalLayout instance = new VerticalLayout(); - - public static IDisposable DoLayout() - { - GUILayout.BeginVertical(); - return instance; - } - - private VerticalLayout() - { - } - - void IDisposable.Dispose() - { - GUILayout.EndVertical(); - } - } - - internal class MetroCreateTestCertificateWindow : EditorWindow - { - private static readonly GUILayoutOption kLabelWidth = GUILayout.Width(110); - private static readonly GUILayoutOption kButtonWidth = GUILayout.Width(110); - private const float kSpace = 5; - private const char kPasswordChar = '\u25cf'; - private const string kPublisherId = "publisher"; - private const string kPasswordId = "password"; - private const string kConfirmId = "confirm"; - - private string path; - private string publisher; - private string password; - private string confirm; - private GUIContent message; - private GUIStyle messageStyle; - private string focus; - - /*private static readonly Regex publisherRegex = new Regex(@"^[A-Za-z0-9\.\-]+$", (RegexOptions.Compiled | RegexOptions.CultureInvariant)); - - private static bool IsValidPublisher(string value) - { - return publisherRegex.IsMatch(value); - }*/ - - public static void Show(string publisher) - { - var windows = (MetroCreateTestCertificateWindow[])Resources.FindObjectsOfTypeAll(typeof(MetroCreateTestCertificateWindow)); - var window = ((windows.Length > 0) ? windows[0] : ScriptableObject.CreateInstance()); - - window.path = Path.Combine(Application.dataPath, "WSATestCertificate.pfx").Replace('\\', '/'); - window.publisher = publisher; - window.password = string.Empty; - window.confirm = window.password; - window.message = (File.Exists(window.path) ? EditorGUIUtility.TrTextContent("Current file will be overwritten.") : GUIContent.none); - - window.messageStyle = new GUIStyle(GUI.skin.label); - window.messageStyle.fontStyle = FontStyle.Italic; - - window.focus = kPublisherId; - - if (windows.Length > 0) - { - window.Focus(); - } - else - { - window.titleContent = EditorGUIUtility.TrTextContent("Create Test Certificate for Windows Store"); - - window.position = new Rect(100, 100, 350, 140); - window.minSize = new Vector2(window.position.width, window.position.height); - window.maxSize = window.minSize; - - window.ShowUtility(); - } - } - - public void OnGUI() - { - var e = Event.current; - var close = false; - var enter = false; - - if (e.type == EventType.KeyDown) - { - close = (e.keyCode == KeyCode.Escape); - enter = ((e.keyCode == KeyCode.Return) || (e.keyCode == KeyCode.KeypadEnter)); - } - - using (HorizontalLayout.DoLayout()) - { - GUILayout.Space(kSpace * 2); - - using (VerticalLayout.DoLayout()) - { - GUILayout.FlexibleSpace(); - - using (HorizontalLayout.DoLayout()) - { - GUILayout.Label(EditorGUIUtility.TrTextContent("Publisher", "Publisher of the package."), kLabelWidth); - GUI.SetNextControlName(kPublisherId); - publisher = GUILayout.TextField(publisher); - } - - GUILayout.Space(kSpace); - - using (HorizontalLayout.DoLayout()) - { - GUILayout.Label(EditorGUIUtility.TrTextContent("Password", "Certificate password."), kLabelWidth); - GUI.SetNextControlName(kPasswordId); - password = GUILayout.PasswordField(password, kPasswordChar); - } - - GUILayout.Space(kSpace); - - using (HorizontalLayout.DoLayout()) - { - GUILayout.Label(EditorGUIUtility.TrTextContent("Confirm password", "Re-enter certificate password."), kLabelWidth); - GUI.SetNextControlName(kConfirmId); - confirm = GUILayout.PasswordField(confirm, kPasswordChar); - } - - GUILayout.Space(kSpace * 2); - - using (HorizontalLayout.DoLayout()) - { - GUILayout.Label(message, messageStyle); - - GUILayout.FlexibleSpace(); - - if (GUILayout.Button(EditorGUIUtility.TrTextContent("Create"), kButtonWidth) || enter) - { - message = GUIContent.none; - - if (string.IsNullOrEmpty(publisher)) - { - message = EditorGUIUtility.TrTextContent("Publisher must be specified."); - focus = kPublisherId; - } - /*else if (!IsValidPublisher(publisher)) - { - message = EditorGUIUtility.TrTextContent("Invalid publisher."); - focus = kPublisherId; - }*/ - else if (password != confirm) - { - if (string.IsNullOrEmpty(confirm)) - { - message = EditorGUIUtility.TrTextContent("Confirm the password."); - focus = kConfirmId; - } - else - { - message = EditorGUIUtility.TrTextContent("Passwords do not match."); - password = string.Empty; - confirm = password; - focus = kPasswordId; - } - } - else - { - try - { - EditorUtility.WSACreateTestCertificate(path, publisher, password, true); - - AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); - - if (!PlayerSettings.WSA.SetCertificate(FileUtil.GetProjectRelativePath(path), password)) - { - message = EditorGUIUtility.TrTextContent("Invalid password."); - } - - close = true; - } - catch (UnityException ex) - { - Debug.LogError(ex.Message); - } - } - } - } - - GUILayout.FlexibleSpace(); - } - - GUILayout.Space(kSpace * 2); - } - - if (close) - { - Close(); - } - else if (focus != null) - { - EditorGUI.FocusTextInControl(focus); - focus = null; - } - } - } -} diff --git a/Editor/Mono/Utils/MonoInstallationFinder.cs b/Editor/Mono/Utils/MonoInstallationFinder.cs deleted file mode 100644 index a85ea382ec..0000000000 --- a/Editor/Mono/Utils/MonoInstallationFinder.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using UnityEngine; - -namespace UnityEditor.Utils -{ - class MonoInstallationFinder - { - public const string MonoInstallation = "Mono"; - public const string MonoBleedingEdgeInstallation = "MonoBleedingEdge"; - - public static string GetFrameWorksFolder() - { - var editorAppPath = FileUtil.NiceWinPath(EditorApplication.applicationPath); - if (Application.platform == RuntimePlatform.WindowsEditor) - return Path.Combine(Path.GetDirectoryName(editorAppPath), "Data"); - else if (Application.platform == RuntimePlatform.OSXEditor) - return Path.Combine(editorAppPath, "Contents"); - else // Linux...? - return Path.Combine(Path.GetDirectoryName(editorAppPath), "Data"); - } - - public static string GetProfileDirectory(string profile) - { - var monoprefix = GetMonoInstallation(); - return Path.Combine(monoprefix, Path.Combine("lib", Path.Combine("mono", profile))); - } - - public static string GetProfileDirectory(string profile, string monoInstallation) - { - var monoprefix = GetMonoInstallation(monoInstallation); - return Path.Combine(monoprefix, Path.Combine("lib", Path.Combine("mono", profile))); - } - - public static string GetProfilesDirectory(string monoInstallation) - { - var monoprefix = GetMonoInstallation(monoInstallation); - return Path.Combine(monoprefix, Path.Combine("lib", "mono")); - } - - public static string GetEtcDirectory(string monoInstallation) - { - var monoprefix = GetMonoInstallation(monoInstallation); - return Path.Combine(monoprefix, Path.Combine("etc", "mono")); - } - - public static string GetMonoInstallation() - { - return GetMonoInstallation(MonoInstallation); - } - - public static string GetMonoBleedingEdgeInstallation() - { - return GetMonoInstallation(MonoBleedingEdgeInstallation); - } - - public static string GetMonoInstallation(string monoName) - { - return Path.Combine(GetFrameWorksFolder(), monoName); - } - } -} diff --git a/Editor/Mono/Utils/NetCoreProgram.cs b/Editor/Mono/Utils/NetCoreProgram.cs deleted file mode 100644 index 2ee9f74814..0000000000 --- a/Editor/Mono/Utils/NetCoreProgram.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using UnityEditor.Scripting.Compilers; -using UnityEditor.Utils; -using UnityEngine; -using Debug = UnityEngine.Debug; - -namespace UnityEditor.Scripting -{ - internal class NetCoreProgram : Program - { - public NetCoreProgram(string executable, string arguments, Action setupStartInfo) - { - if (!IsNetCoreAvailable()) - { - Debug.LogError("Creating NetCoreProgram, but IsNetCoreAvailable() == false; fix the caller!"); - // let it happen anyway to preserve previous behaviour - } - - var startInfo = CreateDotNetCoreStartInfoForArgs(CommandLineFormatter.PrepareFileName(executable) + " " + arguments); - - if (setupStartInfo != null) - setupStartInfo(startInfo); - - _process.StartInfo = startInfo; - } - - private static ProcessStartInfo CreateDotNetCoreStartInfoForArgs(string arguments) - { - var dotnetExe = Paths.Combine(GetSdkRoot(), "dotnet"); - if (Application.platform == RuntimePlatform.WindowsEditor) - dotnetExe = CommandLineFormatter.PrepareFileName(dotnetExe + ".exe"); - - var startInfo = new ProcessStartInfo - { - Arguments = arguments, - CreateNoWindow = true, - FileName = dotnetExe, - WorkingDirectory = Application.dataPath + "/..", - }; - - if (Application.platform == RuntimePlatform.OSXEditor) - { - // .NET Core needs to be able to find the newer openssl libraries that it requires on OSX - var nativeDepsPath = Path.Combine(Path.Combine(Path.Combine(GetNetCoreRoot(), "NativeDeps"), "osx"), "lib"); - - if (startInfo.EnvironmentVariables.ContainsKey("DYLD_LIBRARY_PATH")) - startInfo.EnvironmentVariables["DYLD_LIBRARY_PATH"] = string.Format("{0}:{1}", nativeDepsPath, startInfo.EnvironmentVariables["DYLD_LIBRARY_PATH"]); - else - startInfo.EnvironmentVariables.Add("DYLD_LIBRARY_PATH", nativeDepsPath); - } - - return startInfo; - } - - private static string GetSdkRoot() - { - return Path.Combine(GetNetCoreRoot(), "Sdk"); - } - - private static string GetNetCoreRoot() - { - return Path.Combine(MonoInstallationFinder.GetFrameWorksFolder(), "NetCore"); - } - - private static bool s_NetCoreAvailableChecked = false; - private static bool s_NetCoreAvailable = false; - public static bool IsNetCoreAvailable() - { - if (!s_NetCoreAvailableChecked) - { - s_NetCoreAvailableChecked = true; - - var startInfo = CreateDotNetCoreStartInfoForArgs("--version"); - var getVersionProg = new Program(startInfo); - try - { - getVersionProg.Start(); - } - catch (Exception ex) - { - Debug.LogWarningFormat("Disabling CoreCLR, got exception trying to run with --version: {0}", ex); - return false; - } - - getVersionProg.WaitForExit(5000); - if (!getVersionProg.HasExited) - { - getVersionProg.Kill(); - Debug.LogWarning("Disabling CoreCLR, timed out trying to run with --version"); - return false; - } - - if (getVersionProg.ExitCode != 0) - { - Debug.LogWarningFormat("Disabling CoreCLR, got non-zero exit code: {0}, stderr: '{1}'", - getVersionProg.ExitCode, getVersionProg.GetErrorOutputAsString()); - return false; - } - - s_NetCoreAvailable = true; - } - return s_NetCoreAvailable; - } - } -} diff --git a/Editor/Mono/Utils/NetStandardFinder.cs b/Editor/Mono/Utils/NetStandardFinder.cs deleted file mode 100644 index c4d148a13c..0000000000 --- a/Editor/Mono/Utils/NetStandardFinder.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using UnityEngine; - -namespace UnityEditor.Utils -{ - class NetStandardFinder - { - public const string NetStandardInstallation = "NetStandard"; - - public static string GetReferenceDirectory() - { - var prefix = GetNetStandardInstallation(); - return Path.Combine(prefix, Path.Combine("ref", "2.0.0")); - } - - public static string GetCompatShimsDirectory() - { - return Path.Combine("compat", Path.Combine("2.0.0", "shims")); - } - - public static string GetNetStandardCompatShimsDirectory() - { - var prefix = GetNetStandardInstallation(); - return Path.Combine(prefix, Path.Combine(GetCompatShimsDirectory(), "netstandard")); - } - - public static string GetDotNetFrameworkCompatShimsDirectory() - { - var prefix = GetNetStandardInstallation(); - return Path.Combine(prefix, Path.Combine(GetCompatShimsDirectory(), "netfx")); - } - - public static string GetNetStandardInstallation() - { - return Path.Combine(MonoInstallationFinder.GetFrameWorksFolder(), NetStandardInstallation); - } - } -} diff --git a/Editor/Mono/Utils/Paths.cs b/Editor/Mono/Utils/Paths.cs deleted file mode 100644 index 5600cfe7de..0000000000 --- a/Editor/Mono/Utils/Paths.cs +++ /dev/null @@ -1,269 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; - -namespace UnityEditor.Utils -{ - internal static class Paths - { - public static string Combine(params string[] components) - { - if (components.Length < 1) - throw new ArgumentException("At least one component must be provided!"); - - string path = components[0]; - for (int i = 1; i < components.Length; i++) - path = Path.Combine(path, components[i]); - return path; - } - - public static string[] Split(string path) - { - List result = new List(path.Split(Path.DirectorySeparatorChar)); - - for (int i = 0; i < result.Count;) - { - result[i] = result[i].Trim(); - if (result[i].Equals("")) - { - result.RemoveAt(i); - } - else - { - i++; - } - } - - return result.ToArray(); - } - - public static string GetFileOrFolderName(string path) - { - string name; - - if (File.Exists(path)) - { - name = Path.GetFileName(path); - } - else if (Directory.Exists(path)) - { - string[] pathSplit = Split(path); - name = pathSplit[pathSplit.Length - 1]; - } - else - { - throw new ArgumentException("Target '" + path + "' does not exist."); - } - - return name; - } - - public static string CreateTempDirectory() - { - for (int i = 0; i < 32; ++i) - { - string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - - if (File.Exists(tempDirectory) || Directory.Exists(tempDirectory)) - continue; - - Directory.CreateDirectory(tempDirectory); - - return tempDirectory; - } - throw new IOException("CreateTempDirectory failed"); - } - - public static string NormalizePath(this string path) - { - if (Path.DirectorySeparatorChar == '\\') - return path.Replace('/', Path.DirectorySeparatorChar); - return path.Replace('\\', Path.DirectorySeparatorChar); - } - - public static string ConvertSeparatorsToWindows(this string path) - { - return path.Replace('/', '\\'); - } - - public static string ConvertSeparatorsToUnity(this string path) - { - return path.Replace('\\', '/'); - } - - public static string SkipPathPrefix(string path, string prefix) - { - if (path.StartsWith(prefix)) - return path.Substring(prefix.Length + 1); - return path; - } - - public static string UnifyDirectorySeparator(string path) - { - return path.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar); - } - - public static bool AreEqual(string pathA, string pathB, bool ignoreCase) - { - if (pathA == "" && pathB == "") - return true; - - if (String.IsNullOrEmpty(pathA) || String.IsNullOrEmpty(pathB)) - { - // GetFullPath will throw otherwise. - return false; - } - - return string.Compare(Path.GetFullPath(pathA), Path.GetFullPath(pathB), ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) == 0; - } - - public static bool CheckValidAssetPathAndThatDirectoryExists(string assetFilePath, string requiredExtensionWithDot) - { - if (!IsValidAssetPathWithErrorLogging(assetFilePath, requiredExtensionWithDot)) - return false; - - string dir = Path.GetDirectoryName(assetFilePath); - if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) - { - UnityEngine.Debug.LogError("Parent directory must exist before creating asset at: " + assetFilePath); - return false; - } - - return true; - } - - public static bool IsValidAssetPathWithErrorLogging(string assetPath, string requiredExtensionWithDot) - { - string errorMsg; - if (!IsValidAssetPath(assetPath, requiredExtensionWithDot, out errorMsg)) - { - UnityEngine.Debug.LogError(errorMsg); - return false; - } - return true; - } - - public static bool IsValidAssetPath(string assetPath) - { - const string requiredExtension = null; - return IsValidAssetPath(assetPath, requiredExtension); - } - - public static bool IsValidAssetPath(string assetPath, string requiredExtensionWithDot) - { - string errorMsg = null; - return CheckIfAssetPathIsValid(assetPath, requiredExtensionWithDot, ref errorMsg); - } - - public static bool IsValidAssetPath(string assetPath, string requiredExtensionWithDot, out string errorMsg) - { - errorMsg = string.Empty; - return CheckIfAssetPathIsValid(assetPath, requiredExtensionWithDot, ref errorMsg); - } - - // If an error message is wanted then input an empty string for 'errorMsg'. If 'errorMsg' is null then no error string is allocated. - static bool CheckIfAssetPathIsValid(string assetPath, string requiredExtensionWithDot, ref string errorMsg) - { - try - { - if (string.IsNullOrEmpty(assetPath)) - { - if (errorMsg != null) - SetFullErrorMessage("Asset path is empty", assetPath, ref errorMsg); - return false; - } - - string fileName = Path.GetFileName(assetPath); // Will throw an ArgumentException if the path contains one or more of the invalid characters defined in GetInvalidPathChars - - if (fileName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) - { - if (errorMsg != null) - SetFullErrorMessage("Filename contains invalid characters", assetPath, ref errorMsg); - return false; - } - - if (fileName.StartsWith(".")) - { - if (errorMsg != null) - SetFullErrorMessage("Do not prefix asset name with '.'", assetPath, ref errorMsg); - return false; - } - - if (fileName.StartsWith(" ")) - { - if (errorMsg != null) - SetFullErrorMessage("Do not prefix asset name with white space", assetPath, ref errorMsg); - return false; - } - - if (!string.IsNullOrEmpty(requiredExtensionWithDot)) - { - string extension = Path.GetExtension(assetPath); - if (!String.Equals(extension, requiredExtensionWithDot, StringComparison.OrdinalIgnoreCase)) - { - if (errorMsg != null) - SetFullErrorMessage(string.Format("Incorrect extension. Required extension is: '{0}'", requiredExtensionWithDot), assetPath, ref errorMsg); - return false; - } - } - } - catch (Exception e) - { - if (errorMsg != null) - SetFullErrorMessage(e.Message, assetPath, ref errorMsg); - return false; - } - return true; - } - - static void SetFullErrorMessage(string error, string assetPath, ref string errorMsg) - { - errorMsg = string.Format("Asset path error: '{0}' is not valid: {1}", ToLiteral(assetPath), error); - } - - /// Escapes a string so that escape sequences of ASCII and unicode characters are shown. Taken from http://stackoverflow.com/a/14087738 - static string ToLiteral(string input) - { - if (string.IsNullOrEmpty(input)) - return string.Empty; - - var literal = new System.Text.StringBuilder(input.Length + 2); - foreach (var c in input) - { - switch (c) - { - case '\'': literal.Append(@"\'"); break; - case '\"': literal.Append("\\\""); break; - case '\\': literal.Append(@"\\"); break; - case '\0': literal.Append(@"\0"); break; - case '\a': literal.Append(@"\a"); break; - case '\b': literal.Append(@"\b"); break; - case '\f': literal.Append(@"\f"); break; - case '\n': literal.Append(@"\n"); break; - case '\r': literal.Append(@"\r"); break; - case '\t': literal.Append(@"\t"); break; - case '\v': literal.Append(@"\v"); break; - default: - // ASCII printable character - if (c >= 0x20 && c <= 0x7e) - { - literal.Append(c); - } - // As UTF16 escaped character - else - { - literal.Append(@"\u"); - literal.Append(((int)c).ToString("x4")); - } - break; - } - } - return literal.ToString(); - } - } -} diff --git a/Editor/Mono/Utils/PerformanceChecks.cs b/Editor/Mono/Utils/PerformanceChecks.cs deleted file mode 100644 index 77dc8dee3e..0000000000 --- a/Editor/Mono/Utils/PerformanceChecks.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using System; - -namespace UnityEditor.Utils -{ - internal class PerformanceChecks - { - static readonly string[] kShadersWithMobileVariants = - { - "VertexLit", - "Diffuse", - "Bumped Diffuse", - "Bumped Specular", - "Particles/Additive", - "Particles/VertexLit Blended", - "Particles/Alpha Blended", - "Particles/Multiply", - "RenderFX/Skybox" - }; - - private static bool IsMobileBuildTarget(BuildTarget target) - { - return target == BuildTarget.iOS || target == BuildTarget.Android || target == BuildTarget.Tizen; - } - - private static string FormattedTextContent(string localeString, params object[] args) - { - var content = EditorGUIUtility.TextContent(localeString); - return string.Format(content.text, args); - } - - public static string CheckMaterial(Material mat, BuildTarget buildTarget) - { - if (mat == null || mat.shader == null) - return null; - string shaderName = mat.shader.name; - int shaderLOD = ShaderUtil.GetLOD(mat.shader); - bool hasMobileVariant = Array.Exists(kShadersWithMobileVariants, s => s == shaderName); - bool isMobileTarget = IsMobileBuildTarget(buildTarget); - - // Skip all performance-related checks if shader explicitly indicated that via a PerformanceChecks=False tag. - bool noPerfChecks = (mat.GetTag("PerformanceChecks", true).ToLower() == "false"); - if (!noPerfChecks) - { - // shaders that have faster / simpler equivalents already - if (hasMobileVariant) - { - // has default white color? - if (isMobileTarget && mat.HasProperty("_Color") && mat.GetColor("_Color") == new Color(1.0f, 1.0f, 1.0f, 1.0f)) - { - return FormattedTextContent("Shader is using white color which does nothing; Consider using {0} shader for performance.", "Mobile/" + shaderName); - } - - // recommend Mobile particle shaders on mobile platforms - if (isMobileTarget && shaderName.StartsWith("Particles/")) - { - return FormattedTextContent("Consider using {0} shader on this platform for performance.", "Mobile/" + shaderName); - } - - // has default skybox tint color? - if (shaderName == "RenderFX/Skybox" && mat.HasProperty("_Tint") && mat.GetColor("_Tint") == new Color(0.5f, 0.5f, 0.5f, 0.5f)) - { - return FormattedTextContent("Skybox shader is using gray color which does nothing; Consider using {0} shader for performance.", "Mobile/Skybox"); - } - } - - // recommend "something simpler" for complex shaders on mobile platforms - if (shaderLOD >= 300 && isMobileTarget && !shaderName.StartsWith("Mobile/")) - { - return FormattedTextContent("Shader might be expensive on this platform. Consider switching to a simpler shader; look under Mobile shaders."); - } - - // vertex lit shader with max. emission: recommend Unlit shaders - if (shaderName.Contains("VertexLit") && mat.HasProperty("_Emission")) - { - bool isColor = false; - - Shader shader = mat.shader; - int count = ShaderUtil.GetPropertyCount(shader); - - for (int i = 0; i < count; i++) - { - if (ShaderUtil.GetPropertyName(shader, i) == "_Emission") - { - isColor = (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.Color); - break; - } - } - - if (isColor) - { - Color col = mat.GetColor("_Emission"); - if (col.r >= 0.5f && col.g >= 0.5f && col.b >= 0.5f) - { - return FormattedTextContent("Looks like you're using VertexLit shader to simulate an unlit object (white emissive). Use one of Unlit shaders instead for performance."); - } - } - } - - // normalmapped shader without a normalmap: recommend non-normal mapped one - if (mat.HasProperty("_BumpMap") && mat.GetTexture("_BumpMap") == null) - { - return FormattedTextContent("Normal mapped shader without a normal map. Consider using a non-normal mapped shader for performance."); - } - } - - return null; - } - } -} diff --git a/Editor/Mono/Utils/ProcessOutputStreamReader.cs b/Editor/Mono/Utils/ProcessOutputStreamReader.cs deleted file mode 100644 index 705f254413..0000000000 --- a/Editor/Mono/Utils/ProcessOutputStreamReader.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Threading; - -namespace UnityEditor.Utils -{ - internal class ProcessOutputStreamReader - { - private readonly Func hostProcessExited; - private readonly StreamReader stream; - internal List lines; - private Thread thread; - - internal ProcessOutputStreamReader(Process p, StreamReader stream) : this(() => p.HasExited, stream) - { - } - - internal ProcessOutputStreamReader(Func hostProcessExited, StreamReader stream) - { - this.hostProcessExited = hostProcessExited; - this.stream = stream; - lines = new List(); - - thread = new Thread(ThreadFunc); - thread.Start(); - } - - private void ThreadFunc() - { - if (hostProcessExited()) return; - try - { - while (true) - { - if (stream.BaseStream == null) return; - string line = stream.ReadLine(); - if (line == null) - return; - lock (lines) - { - lines.Add(line); - } - } - } - catch (ObjectDisposedException) - { - // We have had this throw in a run on Katana in what appears to be a case of a very short running - // process exiting between the check to hostProcessExited() and the call to stream.ReadLine(); - // So catch this case to avoid this from happening again. - lock (lines) - { - lines.Add("Could not read output because an ObjectDisposedException was thrown."); - } - } - } - - internal string[] GetOutput() - { - if (hostProcessExited()) - thread.Join(); - lock (lines) - { - return lines.ToArray(); - } - } - } -} diff --git a/Editor/Mono/Utils/Program.cs b/Editor/Mono/Utils/Program.cs deleted file mode 100644 index c200bfd662..0000000000 --- a/Editor/Mono/Utils/Program.cs +++ /dev/null @@ -1,187 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Diagnostics; -using System.IO; - -namespace UnityEditor.Utils -{ - internal class Program : IDisposable - { - private ProcessOutputStreamReader _stdout; - private ProcessOutputStreamReader _stderr; - private Stream _stdin; - public Process _process; - - protected Program() - { - _process = new Process(); - } - - public Program(ProcessStartInfo si) - : this() - { - _process.StartInfo = si; - } - - public void Start() - { - Start(null); - } - - public void Start(EventHandler exitCallback) - { - if (exitCallback != null) - { - _process.EnableRaisingEvents = true; - _process.Exited += exitCallback; - } - - _process.StartInfo.RedirectStandardInput = true; - _process.StartInfo.RedirectStandardError = true; - _process.StartInfo.RedirectStandardOutput = true; - _process.StartInfo.UseShellExecute = false; - - _process.Start(); - _stdout = new ProcessOutputStreamReader(_process, _process.StandardOutput); - _stderr = new ProcessOutputStreamReader(_process, _process.StandardError); - _stdin = _process.StandardInput.BaseStream; - } - - public ProcessStartInfo GetProcessStartInfo() - { - return _process.StartInfo; - } - - public void LogProcessStartInfo() - { - if (_process != null) - LogProcessStartInfo(_process.StartInfo); - else - Console.WriteLine("Failed to retrieve process startInfo"); - } - - //please dont kill this code. - private static void LogProcessStartInfo(ProcessStartInfo si) - { - Console.WriteLine("Filename: " + si.FileName); - Console.WriteLine("Arguments: " + si.Arguments); - - foreach (DictionaryEntry envVar in si.EnvironmentVariables) - if (envVar.Key.ToString().StartsWith("MONO")) - Console.WriteLine("{0}: {1}", envVar.Key, envVar.Value); - - int responsefileindex = si.Arguments.IndexOf("Temp/UnityTempFile"); - Console.WriteLine("index: " + responsefileindex); - - if (responsefileindex > 0) - { - var responsefile = si.Arguments.Substring(responsefileindex); - Console.WriteLine("Responsefile: " + responsefile + " Contents: "); - Console.WriteLine(System.IO.File.ReadAllText(responsefile)); - } - } - - public string GetAllOutput() - { - var sb = new System.Text.StringBuilder(); - sb.AppendLine("stdout:"); - foreach (var s in GetStandardOutput()) - sb.AppendLine(s); - sb.AppendLine("stderr:"); - foreach (var s in GetErrorOutput()) - sb.AppendLine(s); - return sb.ToString(); - } - - public bool HasExited - { - get - { - if (_process == null) - throw new InvalidOperationException("You cannot call HasExited before calling Start"); - try - { - return _process.HasExited; - } - catch (InvalidOperationException) - { - return true; - } - } - } - - public int ExitCode - { - get { return _process.ExitCode; } - } - - public int Id - { - get { return _process.Id; } - } - - public void Dispose() - { - Kill(); - _process.Dispose(); - } - - public void Kill() - { - if (!HasExited) - { - _process.Kill(); - _process.WaitForExit(); - } - } - - public Stream GetStandardInput() - { - return _stdin; - } - - public string[] GetStandardOutput() - { - return _stdout.GetOutput(); - } - - public string GetStandardOutputAsString() - { - var output = GetStandardOutput(); - return GetOutputAsString(output); - } - - public string[] GetErrorOutput() - { - return _stderr.GetOutput(); - } - - public string GetErrorOutputAsString() - { - var output = GetErrorOutput(); - return GetOutputAsString(output); - } - - private static string GetOutputAsString(string[] output) - { - var sb = new System.Text.StringBuilder(); - foreach (var t in output) - sb.AppendLine(t); - return sb.ToString(); - } - - public void WaitForExit() - { - _process.WaitForExit(); - } - - public bool WaitForExit(int milliseconds) - { - return _process.WaitForExit(milliseconds); - } - } -} diff --git a/Editor/Mono/Utils/ProgressBarUtils.cs b/Editor/Mono/Utils/ProgressBarUtils.cs deleted file mode 100644 index 24a98fdd49..0000000000 --- a/Editor/Mono/Utils/ProgressBarUtils.cs +++ /dev/null @@ -1,109 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UnityEditor -{ - // Class used as a callback handler for progress bar notifications. - // Supports clamping to a sub range of a complete process (defined from 0.0f to 1.0f). - // When using a ProgressHandler with a sub range, processes can refer to their local completion rate - // and the ProgressHandler will report back progress within that sub range. - internal class ProgressHandler - { - public delegate void ProgressCallback(string title, string message, float globalProgress); - private ProgressCallback m_ProgressCallback; - private string m_Title; - private float m_ProgressRangeMin; - private float m_ProgressRangeMax; - - public ProgressHandler(string title, ProgressCallback callback, float progressRangeMin = 0.0f, float progressRangeMax = 1.0f) - { - m_Title = title; - m_ProgressCallback += callback; - m_ProgressRangeMin = progressRangeMin; - m_ProgressRangeMax = progressRangeMax; - } - - private float CalcGlobalProcess(float localProcess) - { - return Mathf.Clamp(m_ProgressRangeMin * (1.0f - localProcess) + m_ProgressRangeMax * localProcess, 0.0f, 1.0f); - } - - public void OnProgress(string message, float progress) - { - m_ProgressCallback(m_Title, message, CalcGlobalProcess(progress)); - } - - public ProgressHandler SpawnFromLocalSubRange(float localRangeMin, float localRangeMax) - { - return new ProgressHandler(m_Title, m_ProgressCallback, CalcGlobalProcess(localRangeMin), CalcGlobalProcess(localRangeMax)); - } - } - - // A helper class that attaches to a ProgressHandler - // Supports queueing tasks which will automatically notify the ProgressHandler when executed - internal class ProgressTaskManager - { - private ProgressHandler m_Handler; - private List m_Tasks = new List(); - private int m_ProgressUpdatesForCurrentTask; - private int m_StartedTasks; - - public ProgressTaskManager(ProgressHandler handler) - { - m_Handler = handler; - } - - public void AddTask(Action task) - { - m_Tasks.Add(task); - } - - public void Run() - { - // Run should not be run within a previous run - System.Diagnostics.Debug.Assert(m_StartedTasks == 0); - - foreach (var task in m_Tasks) - { - m_StartedTasks++; - m_ProgressUpdatesForCurrentTask = 0; - task(); - } - } - - public void UpdateProgress(string message) - { - if (m_Handler != null) - { - // Get some movement of the bar, even for unknown number of progress updates - float taskProgress = 1.0f - Mathf.Pow(0.85f, m_ProgressUpdatesForCurrentTask); - int totalTasks = m_Tasks.Count; - if (totalTasks <= m_StartedTasks) - totalTasks = m_StartedTasks; - float taskStep = 1.0f / totalTasks; - float runProgress = (m_StartedTasks - 1) * taskStep + taskProgress * taskStep; - m_Handler.OnProgress(message, runProgress); - } - - m_ProgressUpdatesForCurrentTask++; - } - - public ProgressHandler SpawnProgressHandlerFromCurrentTask() - { - if (m_Handler != null) - { - int totalTasks = m_Tasks.Count; - float taskStep = 1.0f / totalTasks; - float minRange = (m_StartedTasks - 1) * taskStep; - float maxRange = m_StartedTasks * taskStep; - return m_Handler.SpawnFromLocalSubRange(minRange, maxRange); - } - return null; - } - } -} diff --git a/Editor/Mono/Utils/SimpleProfiler.cs b/Editor/Mono/Utils/SimpleProfiler.cs deleted file mode 100644 index 3faa890586..0000000000 --- a/Editor/Mono/Utils/SimpleProfiler.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -//#define SIMPLE_PROFILER -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; - -namespace UnityEditor -{ - // Simple profiler that can measure time spend inside code blocks. - // If the same code block is hit multiple times, the times are summed up. - // Measured blocks may be nested, although the profiler does not do anything intelligent with it. - // Ie. you can measure a big code block as well as smaller code blocks within it. - // All measured times are printed when calling PrintTimes, at which point the timer is also reset. - - // Note, out built-in profiler in Unity did not catch the code I needed to profile, - // hence I had to make this one. - internal class SimpleProfiler - { - // Lazy coding with parallel stacks - private static Stack m_Names = new Stack(); - private static Stack m_StartTime = new Stack(); - private static Dictionary m_Timers = new Dictionary(); - private static Dictionary m_Calls = new Dictionary(); - - [System.Diagnostics.Conditional("SIMPLE_PROFILER")] - public static void Begin(string label) - { - m_Names.Push(label); - m_StartTime.Push(Time.realtimeSinceStartup); - } - - [System.Diagnostics.Conditional("SIMPLE_PROFILER")] - public static void End() - { - string str = m_Names.Pop(); - float duration = (Time.realtimeSinceStartup - m_StartTime.Pop()); - if (m_Timers.ContainsKey(str)) - m_Timers[str] += duration; - else - m_Timers[str] = duration; - - if (m_Calls.ContainsKey(str)) - m_Calls[str] += 1; - else - m_Calls[str] = 1; - } - - [System.Diagnostics.Conditional("SIMPLE_PROFILER")] - public static void PrintTimes() - { - string str = "Measured execution times:\n----------------------------\n"; - foreach (KeyValuePair kvp in m_Timers) - str += string.Format("{0,6:0.0} ms: {1} in {2} calls\n", kvp.Value * 1000, kvp.Key, m_Calls[kvp.Key]); - Debug.Log(str); - m_Names.Clear(); - m_StartTime.Clear(); - m_Timers.Clear(); - m_Calls.Clear(); - } - } -} diff --git a/Editor/Mono/Utils/TickTimerHelper.cs b/Editor/Mono/Utils/TickTimerHelper.cs deleted file mode 100644 index fc67f3329d..0000000000 --- a/Editor/Mono/Utils/TickTimerHelper.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor -{ - internal class TickTimerHelper - { - double m_NextTick; - double m_Interval; - - public TickTimerHelper(double intervalBetweenTicksInSeconds) - { - m_Interval = intervalBetweenTicksInSeconds; - } - - public bool DoTick() - { - if (EditorApplication.timeSinceStartup > m_NextTick) - { - m_NextTick = EditorApplication.timeSinceStartup + m_Interval; - return true; - } - return false; - } - - public void Reset() - { - m_NextTick = 0; - } - } -} diff --git a/Editor/Mono/Utils/TimeAgo.cs b/Editor/Mono/Utils/TimeAgo.cs deleted file mode 100644 index 30dafb4119..0000000000 --- a/Editor/Mono/Utils/TimeAgo.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor -{ - internal static class TimeAgo - { - const int k_Second = 1; - const int k_Minute = 60 * k_Second; - const int k_Hour = 60 * k_Minute; - const int k_Day = 24 * k_Hour; - const int k_Month = 30 * k_Day; - - public static string GetString(DateTime dateTime) - { - var ts = new TimeSpan(DateTime.UtcNow.Ticks - dateTime.ToUniversalTime().Ticks); - double delta = Math.Abs(ts.TotalSeconds); - - if (delta < 1 * k_Minute) - return "less than a minute ago"; - - if (delta < 2 * k_Minute) - return "a minute ago"; - - if (delta < 45 * k_Minute) - return ts.Minutes + " minutes ago"; - - if (delta < 90 * k_Minute) - return "an hour ago"; - - if (delta < 24 * k_Hour) - return ts.Hours + " hours ago"; - - if (delta < 48 * k_Hour) - return "yesterday"; - - if (delta < 30 * k_Day) - return ts.Days + " days ago"; - - if (delta < 12 * k_Month) - { - int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30)); - return months <= 1 ? "a month ago" : months + " months ago"; - } - - int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365)); - return years <= 1 ? "one year ago" : years + " years ago"; - } - } -} diff --git a/Editor/Mono/Utils/TimeHelper.cs b/Editor/Mono/Utils/TimeHelper.cs deleted file mode 100644 index 4124908c2f..0000000000 --- a/Editor/Mono/Utils/TimeHelper.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor -{ - // Silly helper to get proper deltatime inside events - internal struct TimeHelper - { - public float deltaTime; - long lastTime; - - public void Begin() - { - lastTime = System.DateTime.Now.Ticks; - } - - public float Update() - { - deltaTime = (System.DateTime.Now.Ticks - lastTime) / 10000000.0f; - lastTime = System.DateTime.Now.Ticks; - return deltaTime; - } - } -} diff --git a/Editor/Mono/Utils/UnityEventTools.cs b/Editor/Mono/Utils/UnityEventTools.cs deleted file mode 100644 index 68f0d0f074..0000000000 --- a/Editor/Mono/Utils/UnityEventTools.cs +++ /dev/null @@ -1,171 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine.Events; -using Object = UnityEngine.Object; - -namespace UnityEditor.Events -{ - public static class UnityEventTools - { - public static void AddPersistentListener(UnityEventBase unityEvent) - { - unityEvent.AddPersistentListener(); - } - - public static void RemovePersistentListener(UnityEventBase unityEvent, int index) - { - unityEvent.RemovePersistentListener(index); - } - - // Add functions - public static void AddPersistentListener(UnityEvent unityEvent, UnityAction call) - { - unityEvent.AddPersistentListener(call); - } - - public static void AddPersistentListener(UnityEvent unityEvent, UnityAction call) - { - unityEvent.AddPersistentListener(call); - } - - public static void AddPersistentListener(UnityEvent unityEvent, UnityAction call) - { - unityEvent.AddPersistentListener(call); - } - - public static void AddPersistentListener(UnityEvent unityEvent, UnityAction call) - { - unityEvent.AddPersistentListener(call); - } - - public static void AddPersistentListener(UnityEvent unityEvent, UnityAction call) - { - unityEvent.AddPersistentListener(call); - } - - // register functions - public static void RegisterPersistentListener(UnityEvent unityEvent, int index, UnityAction call) - { - unityEvent.RegisterPersistentListener(index, call); - } - - public static void RegisterPersistentListener(UnityEvent unityEvent, int index, UnityAction call) - { - unityEvent.RegisterPersistentListener(index, call); - } - - public static void RegisterPersistentListener(UnityEvent unityEvent, int index, UnityAction call) - { - unityEvent.RegisterPersistentListener(index, call); - } - - public static void RegisterPersistentListener(UnityEvent unityEvent, int index, UnityAction call) - { - unityEvent.RegisterPersistentListener(index, call); - } - - public static void RegisterPersistentListener(UnityEvent unityEvent, int index, UnityAction call) - { - unityEvent.RegisterPersistentListener(index, call); - } - - // Removal functions - public static void RemovePersistentListener(UnityEventBase unityEvent, UnityAction call) - { - unityEvent.RemovePersistentListener(call.Target as Object, call.Method); - } - - public static void RemovePersistentListener(UnityEventBase unityEvent, UnityAction call) - { - unityEvent.RemovePersistentListener(call.Target as Object, call.Method); - } - - public static void RemovePersistentListener(UnityEventBase unityEvent, UnityAction call) - { - unityEvent.RemovePersistentListener(call.Target as Object, call.Method); - } - - public static void RemovePersistentListener(UnityEventBase unityEvent, UnityAction call) - { - unityEvent.RemovePersistentListener(call.Target as Object, call.Method); - } - - public static void RemovePersistentListener(UnityEventBase unityEvent, UnityAction call) - { - unityEvent.RemovePersistentListener(call.Target as Object, call.Method); - } - - public static void UnregisterPersistentListener(UnityEventBase unityEvent, int index) - { - unityEvent.UnregisterPersistentListener(index); - } - - // void - public static void AddVoidPersistentListener(UnityEventBase unityEvent, UnityAction call) - { - unityEvent.AddVoidPersistentListener(call); - } - - public static void RegisterVoidPersistentListener(UnityEventBase unityEvent, int index, UnityAction call) - { - unityEvent.RegisterVoidPersistentListener(index, call); - } - - // int - public static void AddIntPersistentListener(UnityEventBase unityEvent, UnityAction call, int argument) - { - unityEvent.AddIntPersistentListener(call, argument); - } - - public static void RegisterIntPersistentListener(UnityEventBase unityEvent, int index, UnityAction call, int argument) - { - unityEvent.RegisterIntPersistentListener(index, call, argument); - } - - // float - public static void AddFloatPersistentListener(UnityEventBase unityEvent, UnityAction call, float argument) - { - unityEvent.AddFloatPersistentListener(call, argument); - } - - public static void RegisterFloatPersistentListener(UnityEventBase unityEvent, int index, UnityAction call, float argument) - { - unityEvent.RegisterFloatPersistentListener(index, call, argument); - } - - // bool - public static void AddBoolPersistentListener(UnityEventBase unityEvent, UnityAction call, bool argument) - { - unityEvent.AddBoolPersistentListener(call, argument); - } - - public static void RegisterBoolPersistentListener(UnityEventBase unityEvent, int index, UnityAction call, bool argument) - { - unityEvent.RegisterBoolPersistentListener(index, call, argument); - } - - // string - public static void AddStringPersistentListener(UnityEventBase unityEvent, UnityAction call, string argument) - { - unityEvent.AddStringPersistentListener(call, argument); - } - - public static void RegisterStringPersistentListener(UnityEventBase unityEvent, int index, UnityAction call, string argument) - { - unityEvent.RegisterStringPersistentListener(index, call, argument); - } - - // object - public static void AddObjectPersistentListener(UnityEventBase unityEvent, UnityAction call, T argument) where T : Object - { - unityEvent.AddObjectPersistentListener(call, argument); - } - - public static void RegisterObjectPersistentListener(UnityEventBase unityEvent, int index, UnityAction call, T argument) where T : Object - { - unityEvent.RegisterObjectPersistentListener(index, call, argument); - } - } -} diff --git a/Editor/Mono/VersionControl/Common/VCAsset.cs b/Editor/Mono/VersionControl/Common/VCAsset.cs deleted file mode 100644 index 47e71f0bcf..0000000000 --- a/Editor/Mono/VersionControl/Common/VCAsset.cs +++ /dev/null @@ -1,162 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; - -namespace UnityEditor.VersionControl -{ - public partial class Asset - { - internal static bool IsState(Asset.States isThisState, Asset.States partOfThisState) - { - return (isThisState & partOfThisState) != 0; - } - - public bool IsState(Asset.States state) - { - return IsState(this.state, state); - } - - public bool IsOneOfStates(Asset.States[] states) - { - foreach (Asset.States st in states) - { - if ((this.state & st) != 0) return true; - } - return false; - } - - internal bool IsUnderVersionControl - { - get { return IsState(Asset.States.Synced) || IsState(Asset.States.OutOfSync) || IsState(Asset.States.AddedLocal); } - } - - public void Edit() - { - UnityEngine.Object load = Load(); - - if (load != null) - AssetDatabase.OpenAsset(load); - } - - public UnityEngine.Object Load() - { - if (state == States.DeletedLocal || isMeta) - { - return null; - } - - // Standard asset loading - return AssetDatabase.LoadAssetAtPath(path, typeof(UnityEngine.Object)); - } - - internal static string StateToString(Asset.States state) - { - if (IsState(state, Asset.States.AddedLocal)) - return "Added Local"; - - if (IsState(state, Asset.States.AddedRemote)) - return "Added Remote"; - - if (IsState(state, Asset.States.CheckedOutLocal) && !IsState(state, Asset.States.LockedLocal)) - return "Checked Out Local"; - - if (IsState(state, Asset.States.CheckedOutRemote) && !IsState(state, Asset.States.LockedRemote)) - return "Checked Out Remote"; - - if (IsState(state, Asset.States.Conflicted)) - return "Conflicted"; - - if (IsState(state, Asset.States.DeletedLocal)) - return "Deleted Local"; - - if (IsState(state, Asset.States.DeletedRemote)) - return "Deleted Remote"; - - if (IsState(state, Asset.States.Local)) - return "Local"; - - if (IsState(state, Asset.States.LockedLocal)) - return "Locked Local"; - - if (IsState(state, Asset.States.LockedRemote)) - return "Locked Remote"; - - if (IsState(state, Asset.States.OutOfSync)) - return "Out Of Sync"; - - if (IsState(state, Asset.States.Updating)) - return "Updating Status"; - - return ""; - } - - internal static string AllStateToString(Asset.States state) - { - var sb = new System.Text.StringBuilder(); - - if (IsState(state, Asset.States.AddedLocal)) - sb.AppendLine("Added Local"); - - if (IsState(state, Asset.States.AddedRemote)) - sb.AppendLine("Added Remote"); - - if (IsState(state, Asset.States.CheckedOutLocal)) - sb.AppendLine("Checked Out Local"); - - if (IsState(state, Asset.States.CheckedOutRemote)) - sb.AppendLine("Checked Out Remote"); - - if (IsState(state, Asset.States.Conflicted)) - sb.AppendLine("Conflicted"); - - if (IsState(state, Asset.States.DeletedLocal)) - sb.AppendLine("Deleted Local"); - - if (IsState(state, Asset.States.DeletedRemote)) - sb.AppendLine("Deleted Remote"); - - if (IsState(state, Asset.States.Local)) - sb.AppendLine("Local"); - - if (IsState(state, Asset.States.LockedLocal)) - sb.AppendLine("Locked Local"); - - if (IsState(state, Asset.States.LockedRemote)) - sb.AppendLine("Locked Remote"); - - if (IsState(state, Asset.States.OutOfSync)) - sb.AppendLine("Out Of Sync"); - - if (IsState(state, Asset.States.Synced)) - sb.AppendLine("Synced"); - - if (IsState(state, Asset.States.Missing)) - sb.AppendLine("Missing"); - - if (IsState(state, Asset.States.ReadOnly)) - sb.AppendLine("ReadOnly"); - - return sb.ToString(); - } - - internal string AllStateToString() - { - return AllStateToString(this.state); - } - - internal string StateToString() - { - return StateToString(this.state); - } - - public string prettyPath - { - get - { - return path; - } - } - } -} diff --git a/Editor/Mono/VersionControl/Common/VCAssetList.cs b/Editor/Mono/VersionControl/Common/VCAssetList.cs deleted file mode 100644 index f73b8ef34c..0000000000 --- a/Editor/Mono/VersionControl/Common/VCAssetList.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; - -namespace UnityEditor.VersionControl -{ - // A class which encapsualtes a list of VC assets. This class was made to add some extra functionaility - // for filtering and counting items in the list of certain types. - public class AssetList : List - { - public AssetList() {} - public AssetList(AssetList src) - { - // Deep Copy - //foreach (Asset asset in src) - // Add(new Asset(asset)); - } - - // Filter a list of assets by a given set of states - public AssetList Filter(bool includeFolder, params Asset.States[] states) - { - AssetList filter = new AssetList(); - - if (includeFolder == false && (states == null || states.Length == 0)) - return filter; - - foreach (Asset asset in this) - { - if (asset.isFolder) - { - if (includeFolder) - filter.Add(asset); - } - else - { - if (asset.IsOneOfStates(states)) - { - filter.Add(asset); - } - } - } - - return filter; - } - - // Count the list of assets by given a set of states. - // TODO: This is called quite often so it may be an idea to cache this - public int FilterCount(bool includeFolder, params Asset.States[] states) - { - int count = 0; - - if (includeFolder == false && states == null) - return this.Count; - - foreach (Asset asset in this) - { - if (asset.isFolder) - ++count; - else - { - if (asset.IsOneOfStates(states)) - { - ++count; - } - } - } - - return count; - } - - // Create an optimised list of assets by removing children of folders in the same list - public AssetList FilterChildren() - { - AssetList unique = new AssetList(); - unique.AddRange(this); - - foreach (Asset asset in this) - unique.RemoveAll(p => p.IsChildOf(asset)); - - return unique; - } - } -} diff --git a/Editor/Mono/VersionControl/Common/VCAssetModificationHooks.cs b/Editor/Mono/VersionControl/Common/VCAssetModificationHooks.cs deleted file mode 100644 index 71632b8633..0000000000 --- a/Editor/Mono/VersionControl/Common/VCAssetModificationHooks.cs +++ /dev/null @@ -1,129 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEngine; - -using UnityEditor.VersionControl; - -namespace UnityEditorInternal.VersionControl -{ - // Monitor the behavior of assets. This is where general unity asset operations are handled - public class AssetModificationHook - { - private enum CachedStatusMode - { - Sync, - Async - }; - - private static Asset GetStatusCachedIfPossible(string from, CachedStatusMode mode) - { - Asset asset = Provider.CacheStatus(from); - if (asset == null || asset.IsState(Asset.States.Updating)) - { - if (mode == CachedStatusMode.Sync) - { - // Fetch status - Task statusTask = Provider.Status(from, false); - statusTask.Wait(); - if (statusTask.success) - asset = Provider.CacheStatus(from); - else - asset = null; - } - } - return asset; - } - - private static Asset GetStatusForceUpdate(string from) - { - Task statusTask = Provider.Status(from); - statusTask.Wait(); - return statusTask.assetList.Count > 0 ? statusTask.assetList[0] : null; - } - - // Handle asset moving - public static AssetMoveResult OnWillMoveAsset(string from, string to) - { - if (!Provider.enabled) - return AssetMoveResult.DidNotMove; - - Asset asset = GetStatusCachedIfPossible(from, CachedStatusMode.Sync); - - if (asset == null || !asset.IsUnderVersionControl) - return AssetMoveResult.DidNotMove; - - if (asset.IsState(Asset.States.OutOfSync)) - { - Debug.LogError("Cannot move version controlled file that is not up to date. Please get latest changes from server"); - return AssetMoveResult.FailedMove; - } - else if (asset.IsState(Asset.States.DeletedRemote)) - { - Debug.LogError("Cannot move version controlled file that is deleted on server. Please get latest changes from server"); - return AssetMoveResult.FailedMove; - } - else if (asset.IsState(Asset.States.CheckedOutRemote)) - { - Debug.LogError("Cannot move version controlled file that is checked out on server. Please get latest changes from server"); - return AssetMoveResult.FailedMove; - } - else if (asset.IsState(Asset.States.LockedRemote)) - { - Debug.LogError("Cannot move version controlled file that is locked on server. Please get latest changes from server"); - return AssetMoveResult.FailedMove; - } - - // Perform the actual move - Task task = Provider.Move(from, to); - task.Wait(); - - return task.success ? (AssetMoveResult)task.resultCode : AssetMoveResult.FailedMove; - } - - // Handle asset deletion - public static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions option) - { - if (!Provider.enabled) - return AssetDeleteResult.DidNotDelete; - - Task task = Provider.Delete(assetPath); - task.SetCompletionAction(CompletionAction.UpdatePendingWindow); - task.Wait(); - - // Using DidNotDelete on success to force unity to clean up local files - return task.success ? AssetDeleteResult.DidNotDelete : AssetDeleteResult.FailedDelete; - } - - public static bool IsOpenForEdit(string assetPath, out string message, StatusQueryOptions statusOptions) - { - message = ""; - - if (!Provider.enabled) - return true; - - if (string.IsNullOrEmpty(assetPath)) - return true; - - Asset asset = null; - if (statusOptions == StatusQueryOptions.UseCachedIfPossible || statusOptions == StatusQueryOptions.UseCachedAsync) - { - CachedStatusMode mode = statusOptions == StatusQueryOptions.UseCachedAsync ? CachedStatusMode.Async : CachedStatusMode.Sync; - asset = GetStatusCachedIfPossible(assetPath, mode); - } - else - asset = GetStatusForceUpdate(assetPath); - - if (asset == null) - { - if (Provider.onlineState == OnlineState.Offline && Provider.offlineReason != string.Empty) - message = Provider.offlineReason; - return false; - } - - return Provider.IsOpenForEdit(asset); - } - } -} diff --git a/Editor/Mono/VersionControl/Common/VCChangeSet.cs b/Editor/Mono/VersionControl/Common/VCChangeSet.cs deleted file mode 100644 index c30a565e79..0000000000 --- a/Editor/Mono/VersionControl/Common/VCChangeSet.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor.VersionControl -{ - public partial class ChangeSet - { - public static string defaultID = "-1"; - - public ChangeSet() - { - InternalCreate(); - } - - public ChangeSet(string description) - { - InternalCreateFromString(description); - } - - public ChangeSet(string description, string revision) - { - InternalCreateFromStringString(description, revision); - } - - public ChangeSet(ChangeSet other) - { - InternalCopyConstruct(other); - } - - ~ChangeSet() - { - Dispose(); - } - } -} diff --git a/Editor/Mono/VersionControl/Common/VCChangeSets.cs b/Editor/Mono/VersionControl/Common/VCChangeSets.cs deleted file mode 100644 index da803255ab..0000000000 --- a/Editor/Mono/VersionControl/Common/VCChangeSets.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; - -namespace UnityEditor.VersionControl -{ - public class ChangeSets : List - { - } -} diff --git a/Editor/Mono/VersionControl/Common/VCMessage.cs b/Editor/Mono/VersionControl/Common/VCMessage.cs deleted file mode 100644 index 960c12c142..0000000000 --- a/Editor/Mono/VersionControl/Common/VCMessage.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor.VersionControl -{ - // Shared message class to give plugin messages consistency - public partial class Message - { - public void Show() - { - Message.Info(message); - } - - private static void Info(string message) - { - Debug.Log("Version control:\n" + message); - } - } -} diff --git a/Editor/Mono/VersionControl/Common/VCProvider.cs b/Editor/Mono/VersionControl/Common/VCProvider.cs deleted file mode 100644 index 6e9a2dd22c..0000000000 --- a/Editor/Mono/VersionControl/Common/VCProvider.cs +++ /dev/null @@ -1,374 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -namespace UnityEditor.VersionControl -{ - [System.Flags] - public enum CheckoutMode { Asset = 1, Meta = 2, Both = 3, Exact = 4 }; - - [System.Flags] - public enum ResolveMethod { UseMine = 1, UseTheirs = 2, UseMerged }; - - [System.Flags] - public enum MergeMethod - { - MergeNone = 0, - MergeAll = 1, - [System.Obsolete("This member is no longer supported (UnityUpgradable) -> MergeNone", true)] - MergeNonConflicting = 2 - }; - - [System.Flags] - public enum OnlineState { Updating = 0, Online = 1, Offline = 2 }; - - [System.Flags] - public enum RevertMode { Normal = 0, Unchanged = 1, KeepModifications = 2 }; - - [System.Flags] - public enum FileMode { None = 0, Binary = 1, Text = 2 }; - - public partial class Provider - { - //*Undocumented - static internal Asset CacheStatus(string assetPath) - { - return Internal_CacheStatus(assetPath); - } - - static public Task Status(AssetList assets) - { - return Internal_Status(assets.ToArray(), true); - } - - static public Task Status(Asset asset) - { - return Internal_Status(new Asset[] { asset }, true); - } - - static public Task Status(AssetList assets, bool recursively) - { - return Internal_Status(assets.ToArray(), recursively); - } - - static public Task Status(Asset asset, bool recursively) - { - return Internal_Status(new Asset[] { asset }, recursively); - } - - static public Task Status(string[] assets) - { - return Internal_StatusStrings(assets, true); - } - - static public Task Status(string[] assets, bool recursively) - { - return Internal_StatusStrings(assets, recursively); - } - - static public Task Status(string asset) - { - return Internal_StatusStrings(new string[] { asset }, true); - } - - static public Task Status(string asset, bool recursively) - { - return Internal_StatusStrings(new string[] { asset }, recursively); - } - - static public Task Move(string from, string to) - { - return Internal_MoveAsStrings(from, to); - } - - static public bool CheckoutIsValid(AssetList assets) - { - return CheckoutIsValid(assets, CheckoutMode.Exact); - } - - static public bool CheckoutIsValid(AssetList assets, CheckoutMode mode) - { - return Internal_CheckoutIsValid(assets.ToArray(), mode); - } - - static public Task Checkout(AssetList assets, CheckoutMode mode) - { - return Internal_Checkout(assets.ToArray(), mode); - } - - static public Task Checkout(string[] assets, CheckoutMode mode) - { - return Internal_CheckoutStrings(assets, mode); - } - - static public Task Checkout(UnityEngine.Object[] assets, CheckoutMode mode) - { - AssetList assetList = new AssetList(); - foreach (Object o in assets) - { - string path = AssetDatabase.GetAssetPath(o); - Asset asset = GetAssetByPath(path); - assetList.Add(asset); - } - - return Internal_Checkout(assetList.ToArray(), mode); - } - - static public bool CheckoutIsValid(Asset asset) - { - return CheckoutIsValid(asset, CheckoutMode.Exact); - } - - static public bool CheckoutIsValid(Asset asset, CheckoutMode mode) - { - return Internal_CheckoutIsValid(new Asset[] { asset }, mode); - } - - static public Task Checkout(Asset asset, CheckoutMode mode) - { - return Internal_Checkout(new Asset[] { asset }, mode); - } - - static public Task Checkout(string asset, CheckoutMode mode) - { - return Internal_CheckoutStrings(new string[] { asset }, mode); - } - - static public Task Checkout(UnityEngine.Object asset, CheckoutMode mode) - { - string path = AssetDatabase.GetAssetPath(asset); - Asset vcasset = GetAssetByPath(path); - return Internal_Checkout(new Asset[] { vcasset }, mode); - } - - //*Undocumented - static internal bool PromptAndCheckoutIfNeeded(string[] assets, string promptIfCheckoutIsNeeded) - { - return Internal_PromptAndCheckoutIfNeeded(assets, promptIfCheckoutIsNeeded); - } - - static public Task Delete(string assetProjectPath) - { - return Internal_DeleteAtProjectPath(assetProjectPath); - } - - static public Task Delete(AssetList assets) - { - return Internal_Delete(assets.ToArray()); - } - - static public Task Delete(Asset asset) - { - return Internal_Delete(new Asset[] { asset }); - } - - static public bool AddIsValid(AssetList assets) - { - return Internal_AddIsValid(assets.ToArray()); - } - - static public Task Add(AssetList assets, bool recursive) - { - return Internal_Add(assets.ToArray(), recursive); - } - - static public Task Add(Asset asset, bool recursive) - { - return Internal_Add(new Asset[] { asset }, recursive); - } - - static public bool DeleteChangeSetsIsValid(ChangeSets changesets) - { - return Internal_DeleteChangeSetsIsValid(changesets.ToArray()); - } - - static public Task DeleteChangeSets(ChangeSets changesets) - { - return Internal_DeleteChangeSets(changesets.ToArray()); - } - - static internal Task RevertChangeSets(ChangeSets changesets, RevertMode mode) - { - return Internal_RevertChangeSets(changesets.ToArray(), mode); - } - - static public bool SubmitIsValid(ChangeSet changeset, AssetList assets) - { - return Internal_SubmitIsValid(changeset, assets != null ? assets.ToArray() : null); - } - - static public Task Submit(ChangeSet changeset, AssetList list, string description, bool saveOnly) - { - return Internal_Submit(changeset, list != null ? list.ToArray() : null, description, saveOnly); - } - - static public bool DiffIsValid(AssetList assets) - { - Asset[] a = assets.ToArray(); - return Internal_DiffIsValid(a); - } - - static public Task DiffHead(AssetList assets, bool includingMetaFiles) - { - return Internal_DiffHead(assets.ToArray(), includingMetaFiles); - } - - static public bool ResolveIsValid(AssetList assets) - { - Asset[] a = assets.ToArray(); - return Internal_ResolveIsValid(a); - } - - static public Task Resolve(AssetList assets, ResolveMethod resolveMethod) - { - return Internal_Resolve(assets.ToArray(), resolveMethod); - } - - static public Task Merge(AssetList assets, MergeMethod method) - { - return Internal_Merge(assets.ToArray(), method); - } - - static public bool LockIsValid(AssetList assets) - { - return Internal_LockIsValid(assets.ToArray()); - } - - static public bool LockIsValid(Asset asset) - { - return Internal_LockIsValid(new Asset[] { asset }); - } - - static public bool UnlockIsValid(AssetList assets) - { - return Internal_UnlockIsValid(assets.ToArray()); - } - - static public bool UnlockIsValid(Asset asset) - { - return Internal_UnlockIsValid(new Asset[] { asset }); - } - - static public Task Lock(AssetList assets, bool locked) - { - return Internal_Lock(assets.ToArray(), locked); - } - - static public Task Lock(Asset asset, bool locked) - { - return Internal_Lock(new Asset[] { asset }, locked); - } - - static public bool RevertIsValid(AssetList assets, RevertMode mode) - { - return Internal_RevertIsValid(assets.ToArray(), mode); - } - - static public Task Revert(AssetList assets, RevertMode mode) - { - return Internal_Revert(assets.ToArray(), mode); - } - - static public bool RevertIsValid(Asset asset, RevertMode mode) - { - return Internal_RevertIsValid(new Asset[] { asset }, mode); - } - - static public Task Revert(Asset asset, RevertMode mode) - { - return Internal_Revert(new Asset[] { asset }, mode); - } - - static public bool GetLatestIsValid(AssetList assets) - { - return Internal_GetLatestIsValid(assets.ToArray()); - } - - static public bool GetLatestIsValid(Asset asset) - { - return Internal_GetLatestIsValid(new Asset[] { asset }); - } - - static public Task GetLatest(AssetList assets) - { - return Internal_GetLatest(assets.ToArray()); - } - - static public Task GetLatest(Asset asset) - { - return Internal_GetLatest(new Asset[] { asset }); - } - - static internal Task SetFileMode(AssetList assets, FileMode mode) - { - return Internal_SetFileMode(assets.ToArray(), mode); - } - - static internal Task SetFileMode(string[] assets, FileMode mode) - { - return Internal_SetFileModeStrings(assets, mode); - } - - static public Task ChangeSetDescription(ChangeSet changeset) - { - return Internal_ChangeSetDescription(changeset); - } - - static public Task ChangeSetStatus(ChangeSet changeset) - { - return Internal_ChangeSetStatus(changeset); - } - - static public Task ChangeSetStatus(string changesetID) - { - ChangeSet cl = new ChangeSet("", changesetID); - return Internal_ChangeSetStatus(cl); - } - - static public Task IncomingChangeSetAssets(ChangeSet changeset) - { - return Internal_IncomingChangeSetAssets(changeset); - } - - static public Task IncomingChangeSetAssets(string changesetID) - { - ChangeSet cl = new ChangeSet("", changesetID); - return Internal_IncomingChangeSetAssets(cl); - } - - static public Task ChangeSetMove(AssetList assets, ChangeSet changeset) - { - return Internal_ChangeSetMove(assets.ToArray(), changeset); - } - - static public Task ChangeSetMove(Asset asset, ChangeSet changeset) - { - return Internal_ChangeSetMove(new Asset[] { asset }, changeset); - } - - static public Task ChangeSetMove(AssetList assets, string changesetID) - { - ChangeSet cl = new ChangeSet("", changesetID); - return Internal_ChangeSetMove(assets.ToArray(), cl); - } - - static public Task ChangeSetMove(Asset asset, string changesetID) - { - ChangeSet cl = new ChangeSet("", changesetID); - return Internal_ChangeSetMove(new Asset[] { asset }, cl); - } - - static public AssetList GetAssetListFromSelection() - { - AssetList list = new AssetList(); - Asset[] assets = Internal_GetAssetArrayFromSelection(); - foreach (Asset asset in assets) - { - list.Add(asset); - } - - return list; - } - } -} diff --git a/Editor/Mono/VersionControl/Common/VCTask.cs b/Editor/Mono/VersionControl/Common/VCTask.cs deleted file mode 100644 index 99485be0f0..0000000000 --- a/Editor/Mono/VersionControl/Common/VCTask.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -namespace UnityEditor.VersionControl -{ - public partial class Task - { - public AssetList assetList - { - get - { - AssetList list = new AssetList(); - Asset[] assets = Internal_GetAssetList(); - foreach (Asset asset in assets) - { - list.Add(asset); - } - - return list; - } - } - - public ChangeSets changeSets - { - get - { - ChangeSets list = new ChangeSets(); - ChangeSet[] changes = Internal_GetChangeSets(); - foreach (ChangeSet change in changes) - { - list.Add(change); - } - - return list; - } - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCListControl.cs b/Editor/Mono/VersionControl/UI/VCListControl.cs deleted file mode 100644 index 8ced2497e6..0000000000 --- a/Editor/Mono/VersionControl/UI/VCListControl.cs +++ /dev/null @@ -1,1343 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; -using System; -using System.Collections.Generic; - -using UnityEditor.VersionControl; - -// List control that manages VCAssets. This is used in a number of places in the plugin to display and manipulate asset lists. -namespace UnityEditorInternal.VersionControl -{ - [System.Serializable] - public class ListControl - { - public enum SelectDirection - { - Up, - Down, - Current - } - - // List state persisted - [System.Serializable] - public class ListState - { - [SerializeField] public float Scroll = 0; - [SerializeField] public List Expanded = new List(); - } - - // List item explansion event - public delegate void ExpandDelegate(ChangeSet expand, ListItem item); - ExpandDelegate expandDelegate; - - // Drag and drop completion event - public delegate void DragDelegate(ChangeSet target); - DragDelegate dragDelegate; - - public delegate void ActionDelegate(ListItem item, int actionIdx); - ActionDelegate actionDelegate; - - ListItem root = new ListItem(); - ListItem active = null; - List visibleList = new List(); - Texture2D blueTex = null; - Texture2D greyTex = null; - Texture2D yellowTex = null; - [SerializeField] ListState m_listState; - Dictionary pathSearch = new Dictionary(); - Texture2D defaultIcon = null; - bool readOnly = false; - bool scrollVisible = false; - string menuFolder = null; - string menuDefault = null; - bool dragAcceptOnly = false; - ListItem dragTarget = null; - int dragCount = 0; - SelectDirection dragAdjust = SelectDirection.Current; - Dictionary selectList = new Dictionary(); - ListItem singleSelect = null; - GUIContent calcSizeTmpContent = new GUIContent(); - - const float c_lineHeight = 16; - const float c_scrollWidth = 14; - - const string c_changeKeyPrefix = "_chkeyprfx_"; // Workaround to make path mapping refresh work with changesets - const string c_metaSuffix = ".meta"; - internal const string c_emptyChangeListMessage = "Empty change list"; - - // Handle unique id access to the list. This was added to enable us to pass the list as - // an integer. If the unity pop up menu could handle passing simple C# objects then we - // would not need this. This is not thread safe and feels like a bad workaround. - [System.NonSerialized] - int uniqueID = 0; - static int s_uniqueIDCount = 1; - static Dictionary s_uniqueIDList = new Dictionary(); - static public ListControl FromID(int id) { try { return s_uniqueIDList[id]; } catch { return null; } } - - public ListState listState - { - get - { - if (m_listState == null) - m_listState = new ListState(); - return m_listState; - } - } - - // Delegate for handling list expansion events - public ExpandDelegate ExpandEvent - { - get { return expandDelegate; } - set { expandDelegate = value; } - } - - // Delegate for handling drag and drop events - public DragDelegate DragEvent - { - get { return dragDelegate; } - set { dragDelegate = value; } - } - - // Delegate for handling action button clicks - public ActionDelegate ActionEvent - { - get { return actionDelegate; } - set { actionDelegate = value; } - } - - // Root item in the list - public ListItem Root - { - get { return root; } - } - - public AssetList SelectedAssets - { - get - { - AssetList list = new AssetList(); - foreach (KeyValuePair listItem in selectList) - if ((listItem.Value.Item as Asset) != null) - list.Add(listItem.Value.Item as Asset); - - return list; - } - } - - public ChangeSets SelectedChangeSets - { - get - { - ChangeSets list = new ChangeSets(); - foreach (KeyValuePair listItem in selectList) - if (listItem.Value != null && (listItem.Value.Item as ChangeSet) != null) - list.Add(listItem.Value.Item as ChangeSet); - - return list; - } - } - - public ChangeSets EmptyChangeSets - { - get - { - ListItem cur = root.FirstChild; - ChangeSets list = new ChangeSets(); - while (cur != null) - { - ChangeSet c = cur.Change; - bool hasEmptyChangeNotice = - c != null && - cur.HasChildren && - cur.FirstChild.Item == null && - cur.FirstChild.Name == c_emptyChangeListMessage; - - if (hasEmptyChangeNotice) - list.Add(c); - - cur = cur.Next; - } - return list; - } - } - - // Is the list read only? - public bool ReadOnly - { - get { return readOnly; } - set { readOnly = value; } - } - - // Context menu overide for folders - public string MenuFolder - { - get { return menuFolder; } - set { menuFolder = value; } - } - - // Default context menu - public string MenuDefault - { - get { return menuDefault; } - set { menuDefault = value; } - } - - // Folder postfix - public bool DragAcceptOnly - { - get { return dragAcceptOnly; } - set { dragAcceptOnly = value; } - } - - public int Size - { - get { return visibleList.Count; } - } - - public ListControl() - { - // Assign a unique id. A workaround to pass the class as an int - uniqueID = s_uniqueIDCount++; - s_uniqueIDList.Add(uniqueID, this); - - // Set the active list - active = root; - Clear(); - } - - ~ListControl() - { - s_uniqueIDList.Remove(uniqueID); - } - - public ListItem FindItemWithIdentifier(int identifier) - { - ListItem result = root.FindWithIdentifierRecurse(identifier); - //if (result == null) - // Debug.Log("Failed to find identifier: " + identifier); - - return result; - } - - public ListItem Add(ListItem parent, string name, Asset asset) - { - ListItem insert = (parent != null) ? parent : root; - ListItem item = new ListItem(); - item.Name = name; - // Can this be null - item.Asset = asset; - insert.Add(item); - - // Meta files that are next to their asset file are collapsed into - // the asset file when rendered but only if they are the same state. - ListItem twinAsset = GetTwinAsset(item); - if (twinAsset != null && item.Asset != null && - twinAsset.Asset.state == (item.Asset.state & ~Asset.States.MetaFile)) - item.Hidden = true; - - if (item.Asset == null) - return item; - - // Create a lookup table - if (item.Asset.path.Length > 0) - pathSearch[item.Asset.path.ToLower()] = item; - return item; - } - - public ListItem Add(ListItem parent, string name, ChangeSet change) - { - ListItem insert = (parent != null) ? parent : root; - ListItem item = new ListItem(); - item.Name = name; - item.Change = change ?? new ChangeSet(name); - insert.Add(item); - - // Create a lookup table - pathSearch[c_changeKeyPrefix + change.id.ToString()] = item; - - return item; - } - - internal ListItem GetChangeSetItem(ChangeSet change) - { - if (change == null) - return null; - - ListItem i = root.FirstChild; - while (i != null) - { - ChangeSet c = i.Item as ChangeSet; - if (c != null && c.id == change.id) - { - return i; - } - i = i.Next; - } - return null; - } - - public void Clear() - { - root.Clear(); - pathSearch.Clear(); - - // Ensure the root nodes are expanded - root.Name = "ROOT"; - root.Expanded = true; - } - - public void Refresh() - { - Refresh(true); - } - - public void Refresh(bool updateExpanded) - { - if (updateExpanded) - { - // Update the expanded state - LoadExpanded(root); - - // Ensure the root nodes are expanded - root.Name = "ROOT"; - root.Expanded = true; - - listState.Expanded.Clear(); - CallExpandedEvent(root, false); - } - - SelectedRefresh(); - } - - // Synchronise selection from Unity - public void Sync() - { - SelectedClear(); - - foreach (UnityEngine.Object obj in Selection.objects) - { - if (AssetDatabase.IsMainAsset(obj)) - { - string projectPath = Application.dataPath.Substring(0, Application.dataPath.Length - 6); - string path = projectPath + AssetDatabase.GetAssetPath(obj); - ListItem item = PathSearchFind(path); - - if (item != null) - { - SelectedAdd(item); - } - } - } - } - - public bool OnGUI(Rect area, bool focus) - { - bool repaint = false; - - // Late init here for now - CreateResources(); - - Event e = Event.current; - int open = active.OpenCount; - int max = (int)(area.height / c_lineHeight); - - // Scroll up/down - if (e.type == EventType.ScrollWheel) - { - repaint = true; - listState.Scroll += e.delta.y; - listState.Scroll = Mathf.Clamp(listState.Scroll, 0, open - max); - } - - // Draw the scrollbar if required - if (open > max) - { - Rect scrollRect = new Rect(area.x + area.width - 14, area.y, 14, area.height); - area.width -= c_scrollWidth; - float tmp = listState.Scroll; - - listState.Scroll = GUI.VerticalScrollbar(scrollRect, listState.Scroll, max, 0, open); - listState.Scroll = Mathf.Clamp(listState.Scroll, 0, open - max); - - if (tmp != listState.Scroll) - repaint = true; - - // Seems to be some sort of bug with focus when the scrollbar 1st appears - // This is a work around for that so on the first update we clear the hot control. - if (!scrollVisible) - { - //GUIUtility.hotControl = 0; - scrollVisible = true; - } - } - else - { - if (scrollVisible) - { - //GUIUtility.hotControl = 0; - scrollVisible = false; - } - } - - // Update the visible list - UpdateVisibleList(area, listState.Scroll); - - // Only do the following in non read only mode - if (focus && !readOnly) - { - // Key Handling - if (e.isKey) - { - repaint = true; - HandleKeyInput(e); - } - - HandleSelectAll(); - - repaint = HandleMouse(area) || repaint; - - // Adjust scroll position when dragging - if (e.type == EventType.DragUpdated && area.Contains(e.mousePosition)) - { - if (e.mousePosition.y < area.y + c_lineHeight) - { - listState.Scroll = Mathf.Clamp(listState.Scroll - 1, 0, open - max); - } - else if (e.mousePosition.y > area.y + area.height - c_lineHeight) - { - listState.Scroll = Mathf.Clamp(listState.Scroll + 1, 0, open - max); - } - } - } - - DrawItems(area, focus); - - return repaint; - } - - private bool HandleMouse(Rect area) - { - Event e = Event.current; - bool repaint = false; - - // Handle mouse down clicks - bool mouseInArea = area.Contains(e.mousePosition); - if (e.type == EventType.MouseDown && mouseInArea) - { - repaint = true; - dragCount = 0; - GUIUtility.keyboardControl = 0; - singleSelect = GetItemAt(area, e.mousePosition); - - // Ensure a valid selection - if (singleSelect != null && !singleSelect.Dummy) - { - // Double click handling - if (e.button == 0 && e.clickCount > 1 && singleSelect.Asset != null) - singleSelect.Asset.Edit(); - - // Expand/Contract - if (e.button < 2) - { - float x = area.x + ((singleSelect.Indent - 1) * 18); - if (e.mousePosition.x >= x && e.mousePosition.x < x + 16 && singleSelect.CanExpand) - { - singleSelect.Expanded = !singleSelect.Expanded; - CallExpandedEvent(singleSelect, true); - singleSelect = null; - } - else if (e.control || e.command) - { - // Right clicking can never de-toggle something - if (e.button == 1) - SelectedAdd(singleSelect); - else - SelectedToggle(singleSelect); - singleSelect = null; - } - else if (e.shift) - { - SelectionFlow(singleSelect); - singleSelect = null; - } - else - { - if (!IsSelected(singleSelect)) - { - SelectedSet(singleSelect); - // Do not set singleSelect to null in order for drag to - // know what is dragged - singleSelect = null; - } - } - } - } - else if (e.button == 0) - { - // Clear selection when a click was made on nothing - SelectedClear(); - singleSelect = null; - } - } - // Handle mouse up clicks - else if ((e.type == EventType.MouseUp || e.type == EventType.ContextClick) && mouseInArea) - { - GUIUtility.keyboardControl = 0; - singleSelect = GetItemAt(area, e.mousePosition); - dragCount = 0; - repaint = true; - - if (singleSelect != null && !singleSelect.Dummy) - { - // right click menus - we pass the static index of the list so the menu can find what is selected - if (e.type == EventType.ContextClick) - { - singleSelect = null; - - if (!IsSelectedAsset() && !string.IsNullOrEmpty(menuFolder)) - { - s_uniqueIDList[uniqueID] = this; - EditorUtility.DisplayPopupMenu(new Rect(e.mousePosition.x, e.mousePosition.y, 0, 0), menuFolder, new MenuCommand(null, uniqueID)); - } - else if (!string.IsNullOrEmpty(menuDefault)) - { - s_uniqueIDList[uniqueID] = this; - EditorUtility.DisplayPopupMenu(new Rect(e.mousePosition.x, e.mousePosition.y, 0, 0), menuDefault, new MenuCommand(null, uniqueID)); - } - } - // Left click up should set selection if singleSelect is in selection since - // this is the case where the user has clicked and hold on a selection (which may start a drag or not) - // and then released it. - else if (e.type != EventType.ContextClick && e.button == 0 && !(e.control || e.command || e.shift)) - { - if (IsSelected(singleSelect)) - { - SelectedSet(singleSelect); - singleSelect = null; - } - } - } - } - - if (e.type == EventType.MouseDrag && mouseInArea) - { - // Ive added this to stop the accidental drag messages that pop up - // you only seem to get one when its not intentional so this should - // give a better effect. - ++dragCount; - - if (dragCount > 2 && Selection.objects.Length > 0) - { - DragAndDrop.PrepareStartDrag(); - if (singleSelect != null) - { - DragAndDrop.objectReferences = new UnityEngine.Object[] { singleSelect.Asset.Load() }; - } - else - { - DragAndDrop.objectReferences = Selection.objects; - } - DragAndDrop.StartDrag("Move"); - } - } - - // Drag has been updated - if (e.type == EventType.DragUpdated) - { - repaint = true; - DragAndDrop.visualMode = DragAndDropVisualMode.Move; - dragTarget = GetItemAt(area, e.mousePosition); - - // Dont target selected items - if (dragTarget != null) - { - if (IsSelected(dragTarget)) - { - dragTarget = null; - } - else - { - if (dragAcceptOnly) - { - if (!dragTarget.CanAccept) - dragTarget = null; - } - else - { - bool canPrev = !dragTarget.CanAccept || dragTarget.PrevOpenVisible != dragTarget.Parent; - bool canNext = !dragTarget.CanAccept || dragTarget.NextOpenVisible != dragTarget.FirstChild; - float size = dragTarget.CanAccept ? 2 : c_lineHeight / 2; - int index = (int)((e.mousePosition.y - area.y) / c_lineHeight); - float pos = area.y + (index * c_lineHeight); - dragAdjust = SelectDirection.Current; - - if (canPrev && e.mousePosition.y <= pos + size) - dragAdjust = SelectDirection.Up; - else if (canNext && e.mousePosition.y >= pos + c_lineHeight - size) - dragAdjust = SelectDirection.Down; - } - } - } - } - - // Drag and drop completion - if (e.type == EventType.DragPerform) - { - if (dragTarget != null) - { - ListItem drag = dragAdjust == SelectDirection.Current ? dragTarget : dragTarget.Parent; - if (dragDelegate != null && drag != null && drag.CanAccept) - dragDelegate(drag.Change); - - dragTarget = null; - } - } - - if (e.type == EventType.DragExited) - dragTarget = null; - return repaint; - } - - private void DrawItems(Rect area, bool focus) - { - float y = area.y; - foreach (ListItem it in visibleList) - { - float x = area.x + ((it.Indent - 1) * 18); - bool isSelected = readOnly ? false : IsSelected(it); - - if (it.Parent != null && it.Parent.Parent != null && it.Parent.Parent.Parent == null) - x -= 16; - - DrawItem(it, area, x, y, focus, isSelected); - y += c_lineHeight; - } - } - - private void HandleSelectAll() - { - if (Event.current.type == EventType.ValidateCommand && Event.current.commandName == EventCommandNames.SelectAll) - { - Event.current.Use(); - } - else if (Event.current.type == EventType.ExecuteCommand && Event.current.commandName == EventCommandNames.SelectAll) - { - SelectedAll(); - Event.current.Use(); - } - } - - // Late resource creation - void CreateResources() - { - if (blueTex == null) - { - blueTex = new Texture2D(1, 1); - blueTex.SetPixel(0, 0, new Color(0.23f, 0.35f, 0.55f)); - blueTex.hideFlags = HideFlags.HideAndDontSave; - blueTex.name = "BlueTex"; - blueTex.Apply(); - } - - if (greyTex == null) - { - greyTex = new Texture2D(1, 1); - greyTex.SetPixel(0, 0, new Color(0.3f, 0.3f, 0.3f)); - greyTex.hideFlags = HideFlags.HideAndDontSave; - greyTex.name = "GrayTex"; - greyTex.Apply(); - } - - if (yellowTex == null) - { - yellowTex = new Texture2D(1, 1); - yellowTex.SetPixel(0, 0, new Color(0.5f, 0.5f, 0.2f)); - yellowTex.name = "YellowTex"; - yellowTex.hideFlags = HideFlags.HideAndDontSave; - yellowTex.Apply(); - } - - if (defaultIcon == null) - { - defaultIcon = EditorGUIUtility.LoadIcon("vcs_document"); - defaultIcon.hideFlags = HideFlags.HideAndDontSave; - } - } - - // Parse all key input supported by the list here - void HandleKeyInput(Event e) - { - // Only handle blip events in here on - if (e.type != EventType.KeyDown) - return; - - // Nothing selected? - if (selectList.Count == 0) - return; - - // Arrow key up - if (e.keyCode == KeyCode.UpArrow || e.keyCode == KeyCode.DownArrow) - { - ListItem sel = null; - - if (e.keyCode == KeyCode.UpArrow) - { - sel = SelectedFirstIn(active); - if (sel != null) sel = sel.PrevOpenSkip; - } - else - { - sel = SelectedLastIn(active); - if (sel != null) sel = sel.NextOpenSkip; - } - - if (sel != null) - { - // Ensure that the item is in view - linear search but handles all the corner cases - if (!ScrollUpTo(sel)) - ScrollDownTo(sel); - - if (e.shift) - { - SelectionFlow(sel); - } - else - { - SelectedSet(sel); - } - } - } - - // Expand/contract on left/right arrow keys - if (e.keyCode == KeyCode.LeftArrow || e.keyCode == KeyCode.RightArrow) - { - ListItem sel = SelectedCurrentIn(active); - sel.Expanded = (e.keyCode == KeyCode.RightArrow); - CallExpandedEvent(sel, true); - } - - // Edit on return key - if (e.keyCode == KeyCode.Return && GUIUtility.keyboardControl == 0) - { - ListItem sel = SelectedCurrentIn(active); - sel.Asset.Edit(); - } - } - - // Draw a list item. A few too many magic numbers in here so will need to tidy this a bit - void DrawItem(ListItem item, Rect area, float x, float y, bool focus, bool selected) - { - bool drag = (item == dragTarget); - bool highlight = selected; - - if (selected) - { - Texture2D selectTex = focus ? blueTex : greyTex; - GUI.DrawTexture(new Rect(area.x, y, area.width, c_lineHeight), selectTex, ScaleMode.StretchToFill, false); - } - else if (drag) - { - switch (dragAdjust) - { - case SelectDirection.Up: - if (item.PrevOpenVisible != item.Parent) - { - GUI.DrawTexture(new Rect(x, y - 1, area.width, 2), yellowTex, ScaleMode.StretchToFill, false); - } - break; - case SelectDirection.Down: - GUI.DrawTexture(new Rect(x, y + c_lineHeight - 1, area.width, 2), yellowTex, ScaleMode.StretchToFill, false); - break; - default: - if (item.CanAccept) - { - GUI.DrawTexture(new Rect(area.x, y, area.width, c_lineHeight), yellowTex, ScaleMode.StretchToFill, false); - highlight = true; - } - break; - } - } - else if (dragTarget != null && item == dragTarget.Parent && dragAdjust != SelectDirection.Current) - { - GUI.DrawTexture(new Rect(area.x, y, area.width, c_lineHeight), yellowTex, ScaleMode.StretchToFill, false); - highlight = true; - } - - if (item.HasActions) - { - // Draw any actions available - for (int i = 0; i < item.Actions.Length; ++i) - { - calcSizeTmpContent.text = item.Actions[i]; - Vector2 sz = GUI.skin.button.CalcSize(calcSizeTmpContent); - if (GUI.Button(new Rect(x, y, sz.x, c_lineHeight), item.Actions[i])) - { - // Action performed. Callback delegate - actionDelegate(item, i); - } - x += sz.x + 4; // offset by 4 px - } - } - - if (item.CanExpand) - { - EditorGUI.Foldout(new Rect(x, y, 16, c_lineHeight), item.Expanded, GUIContent.none); - } - - Texture icon = item.Icon; - Color tmpColor = GUI.color; - Color tmpContentColor = GUI.contentColor; - - // We grey the items when we dont know the state or its a dummy item - if (/*item.Asset.State == Asset.States.Local ||*/ item.Dummy) //< Locals shown with icon for now - GUI.color = new Color(0.65f, 0.65f, 0.65f); - - // This should not be an else statement as the previous if can set icon - if (!item.Dummy) - { - // If there is no icon set then we look for cached items - if (icon == null) - { - icon = InternalEditorUtility.GetIconForFile(item.Name); - // icon = defaultIcon; - } - - var iconRect = new Rect(x + 14, y, 16, c_lineHeight); - - if (icon != null) - GUI.DrawTexture(iconRect, icon); - - if (item.Asset != null) - { - Rect overlayRect = iconRect; - overlayRect.width += 12; - overlayRect.x -= 6; - Overlay.DrawOverlay(item.Asset, overlayRect); - } - } - - string displayName = DisplayName(item); - Vector2 displayNameSize = EditorStyles.label.CalcSize(EditorGUIUtility.TempContent(displayName)); - float labelOffsetX = x + 32; - - if (highlight) - { - GUI.contentColor = new Color(3, 3, 3); - GUI.Label(new Rect(labelOffsetX, y, area.width - labelOffsetX, c_lineHeight + 2), displayName); - } - else - { - GUI.Label(new Rect(labelOffsetX, y, area.width - labelOffsetX, c_lineHeight + 2), displayName); - } - - if (HasHiddenMetaFile(item)) - { - GUI.color = new Color(0.55f, 0.55f, 0.55f); - float spaceBefore = labelOffsetX + displayNameSize.x + 2; - GUI.Label(new Rect(spaceBefore, y, area.width - spaceBefore, c_lineHeight + 2), "+meta"); - } - GUI.contentColor = tmpContentColor; - GUI.color = tmpColor; - } - - void UpdateVisibleList(Rect area, float scrollPos) - { - float y = area.y; - float h = area.y + area.height - c_lineHeight; - ListItem first = active.NextOpenVisible; // Skip the root node - - visibleList.Clear(); - - // Move to the first visible item - for (float i = 0; i < scrollPos; ++i) - { - if (first == null) - return; - - first = first.NextOpenVisible; - } - - for (ListItem it = first; it != null && y < h; it = it.NextOpenVisible) - { - visibleList.Add(it); - y += c_lineHeight; - } - } - - ListItem GetItemAt(Rect area, Vector2 pos) - { - int index = (int)((pos.y - area.y) / c_lineHeight); - - if (index >= 0 && index < visibleList.Count) - return visibleList[index]; - - return null; - } - - // Scroll up towards a target item - bool ScrollUpTo(ListItem item) - { - int count = (int)listState.Scroll; - - ListItem find = visibleList.Count > 0 ? visibleList[0] : null; - while (find != null && count >= 0) - { - if (find == item) - { - listState.Scroll = count; - return true; - } - - --count; - find = find.PrevOpenVisible; - } - - return false; - } - - // Scroll up towards a target item - bool ScrollDownTo(ListItem item) - { - int count = (int)listState.Scroll; - - ListItem find = visibleList.Count > 0 ? visibleList[visibleList.Count - 1] : null; - while (find != null && count >= 0) - { - if (find == item) - { - listState.Scroll = count; - return true; - } - - ++count; - find = find.NextOpenVisible; - } - - return false; - } - - // Load the expanded list state - void LoadExpanded(ListItem item) - { - if (item.Change != null) - item.Expanded = listState.Expanded.Contains(item.Change.id); - - ListItem en = item.FirstChild; - while (en != null) - { - LoadExpanded(en); - en = en.Next; - } - } - - internal void ExpandLastItem() - { - if (root.LastChild != null) - { - root.LastChild.Expanded = true; - CallExpandedEvent(root.LastChild, true); - } - } - - // Parameter added for removing entries as this isnt necessary when updating the full list - void CallExpandedEvent(ListItem item, bool remove) - { - if (item.Change != null) - { - if (item.Expanded) - { - if (expandDelegate != null) - expandDelegate(item.Change, item); - - listState.Expanded.Add(item.Change.id); - } - else if (remove) - { - listState.Expanded.Remove(item.Change.id); - } - } - - ListItem en = item.FirstChild; - while (en != null) - { - CallExpandedEvent(en, remove); - en = en.Next; - } - } - - // Find an item in the list given a path - ListItem PathSearchFind(string path) - { - try { return pathSearch[path.ToLower()]; } - catch { return null; } - } - - // Recursively update items for path search mapping - void PathSearchUpdate(ListItem item) - { - if (item.Asset != null && item.Asset.path.Length > 0) - pathSearch.Add(item.Asset.path.ToLower(), item); - else if (item.Change != null) - { - pathSearch.Add(c_changeKeyPrefix + item.Change.id.ToString(), item); - return; - } - ListItem en = item.FirstChild; - while (en != null) - { - PathSearchUpdate(en); - en = en.Next; - } - } - - // Is the item selected? - bool IsSelected(ListItem item) - { - if (item.Asset != null) - return selectList.ContainsKey(item.Asset.path.ToLower()); - if (item.Change != null) - return selectList.ContainsKey(c_changeKeyPrefix + item.Change.id.ToString()); - - return false; - } - - // Is an asset selected in the list - bool IsSelectedAsset() - { - foreach (KeyValuePair de in selectList) - { - if (de.Value != null && de.Value.Asset != null) - { - return true; - } - } - - return false; - } - - // Clear the current selection list - void SelectedClear() - { - selectList.Clear(); - Selection.activeObject = null; - Selection.instanceIDs = new int[0]; - } - - // Single selection - clears all previous selections - void SelectedRefresh() - { - Dictionary newSelect = new Dictionary(); - - foreach (KeyValuePair de in selectList) - { - newSelect[de.Key] = PathSearchFind(de.Key); - } - - selectList = newSelect; - } - - // Single selection - clears all previous selections - public void SelectedSet(ListItem item) - { - // Dont select or do anything with invalid entries - if (item.Dummy) - return; - - SelectedClear(); - if (item.Asset != null) - { - SelectedAdd(item); - } - else if (item.Change != null) - { - selectList[c_changeKeyPrefix + item.Change.id.ToString()] = item; - } - } - - public void SelectedAll() - { - SelectedClear(); - SelectedAllHelper(Root); - } - - void SelectedAllHelper(ListItem _root) - { - ListItem cur = _root.FirstChild; - while (cur != null) - { - if (cur.HasChildren) - { - // Recurse - SelectedAllHelper(cur); - } - - if (cur.Asset != null) - { - SelectedAdd(cur); - } - cur = cur.Next; - } - } - - ListItem GetTwinAsset(ListItem item) - { - ListItem prev = item.Prev; - if (item.Name.EndsWith(c_metaSuffix) && - prev != null && - prev.Asset != null && - AssetDatabase.GetTextMetaFilePathFromAssetPath(prev.Asset.path).ToLower() == item.Asset.path.ToLower()) - return prev; - return null; - } - - ListItem GetTwinMeta(ListItem item) - { - ListItem next = item.Next; - if (!item.Name.EndsWith(c_metaSuffix) && - next != null && - next.Asset != null && - next.Asset.path.ToLower() == AssetDatabase.GetTextMetaFilePathFromAssetPath(item.Asset.path).ToLower()) - return next; - return null; - } - - ListItem GetTwin(ListItem item) - { - ListItem a = GetTwinAsset(item); - if (a != null) - return a; - return GetTwinMeta(item); - } - - // Add a selection to the list - public void SelectedAdd(ListItem item) - { - // Dont select or do anything with invalid entries - if (item.Dummy) - return; - - ListItem current = SelectedCurrentIn(active); - - // Handle exclusive selections - if (item.Exclusive || (current != null && current.Exclusive)) - { - SelectedSet(item); - return; - } - - // - string name = item.Asset.path.ToLower(); - int selectListPrevCount = selectList.Count; - selectList[name] = item; - - // Auto select meta files together with asset - ListItem twin = GetTwin(item); - - if (twin != null) - selectList[twin.Asset.path.ToLower()] = twin; - - if (selectListPrevCount == selectList.Count) - return; // The items were already present - - // Update core selection list... Only non-meta files can be selectable - int[] sel = Selection.instanceIDs; - - int arrayLen = 0; - if (sel != null) arrayLen = sel.Length; - - // UnityEngine.Object tmpObj = item.Asset.Load (); - - name = name.EndsWith(c_metaSuffix) ? name.Substring(0, name.Length - 5) : name; - int itemID = AssetDatabase.GetMainAssetInstanceID(name.TrimEnd('/')); - if (itemID != 0) - { - int[] newSel = new int[arrayLen + 1]; - newSel[arrayLen] = itemID; - Array.Copy(sel, newSel, arrayLen); - Selection.instanceIDs = newSel; - } - } - - void SelectedRemove(ListItem item) - { - string name = item.Asset.path.ToLower(); - // Remove item and twin - selectList.Remove(name); - selectList.Remove(name.EndsWith(c_metaSuffix) ? name.Substring(0, name.Length - 5) : name + c_metaSuffix); - - // Sync with core selection list. - name = name.EndsWith(c_metaSuffix) ? name.Substring(0, name.Length - 5) : name; - int itemID = AssetDatabase.GetMainAssetInstanceID(name.TrimEnd('/')); - int[] sel = Selection.instanceIDs; - if (itemID != 0 && sel.Length > 0) - { - int idx = Array.IndexOf(sel, itemID); - if (idx < 0) - return; - - int[] newSel = new int[sel.Length - 1]; - Array.Copy(sel, newSel, idx); - if (idx < (sel.Length - 1)) - Array.Copy(sel, idx + 1, newSel, idx, sel.Length - idx - 1); - - Selection.instanceIDs = newSel; - } - } - - // Toggle the selected state of the item - void SelectedToggle(ListItem item) - { - if (IsSelected(item)) - SelectedRemove(item); - else - SelectedAdd(item); - } - - // Selection flow. Flows all selection towards the item. Used for SHIFT selection. - void SelectionFlow(ListItem item) - { - if (selectList.Count == 0) - { - SelectedSet(item); - } - else - { - if (!SelectionFlowDown(item)) - SelectionFlowUp(item); - } - } - - // Select all items up the list - bool SelectionFlowUp(ListItem item) - { - ListItem it; - ListItem limit = item; - - for (it = item; it != null; it = it.PrevOpenVisible) - { - if (IsSelected(it)) - limit = it; - } - - if (item == limit) - return false; - - SelectedClear(); - SelectedAdd(limit); - - for (it = item; it != limit; it = it.PrevOpenVisible) - SelectedAdd(it); - - return true; - } - - // Select all items down the list - bool SelectionFlowDown(ListItem item) - { - ListItem it; - ListItem limit = item; - - for (it = item; it != null; it = it.NextOpenVisible) - { - if (IsSelected(it)) - limit = it; - } - - if (item == limit) - return false; - - SelectedClear(); - SelectedAdd(limit); - - for (it = item; it != limit; it = it.NextOpenVisible) - SelectedAdd(it); - - return true; - } - - // Utility function to return the 1st selected item in a list item hierarchy - ListItem SelectedCurrentIn(ListItem root) - { - foreach (KeyValuePair de in selectList) - { - if (de.Value.IsChildOf(root)) - return de.Value; - } - - return null; - } - - ListItem SelectedFirstIn(ListItem root) - { - ListItem item = SelectedCurrentIn(root); - ListItem find = item; - - while (find != null) - { - if (IsSelected(find)) - item = find; - - find = find.PrevOpenVisible; - } - - return item; - } - - ListItem SelectedLastIn(ListItem root) - { - ListItem item = SelectedCurrentIn(root); - ListItem find = item; - - while (find != null) - { - if (IsSelected(find)) - item = find; - - find = find.NextOpenVisible; - } - - return item; - } - - // Display name rules for items. - string DisplayName(ListItem item) - { - string name = item.Name; - - // Select first nonblank line - string n = ""; - while (n == "") - { - int i = name.IndexOf('\n'); - if (i < 0) break; - n = name.Substring(0, i).Trim(); - name = name.Substring(i + 1); - } - - if (n != "") - name = n; - - name = name.Trim(); - - if (name == "") - { - if (item.Change != null) - { - name = item.Change.id.ToString() + " " + item.Change.description; - } - } - - return name; - } - - private bool HasHiddenMetaFile(ListItem item) - { - ListItem twinMeta = GetTwinMeta(item); - return twinMeta != null && twinMeta.Hidden; - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCListItem.cs b/Editor/Mono/VersionControl/UI/VCListItem.cs deleted file mode 100644 index 5e3bae9171..0000000000 --- a/Editor/Mono/VersionControl/UI/VCListItem.cs +++ /dev/null @@ -1,454 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor; - -using UnityEditor.VersionControl; - -namespace UnityEditorInternal.VersionControl -{ - // This is a custom nested, double linked list. This provides flexibility to search quickly up and down - // the list. Particularly when parts of the list are expanded or not. - public class ListItem - { - ///@TODO: Violation of unity convention.... m_ on member variables... - - ListItem parent; - ListItem firstChild; - ListItem lastChild; - ListItem prev; - ListItem next; - - Texture icon; - string name; - int indent; - bool expanded; - bool exclusive; - bool dummy; - bool hidden; - bool accept; - object item; - string[] actions; - int identifier; - - public ListItem() - { - Clear(); - identifier = (int)(VCSProviderIdentifier.UnsetIdentifier); - } - - ~ListItem() - { - Clear(); - } - - public Texture Icon - { - get - { - Asset asset = item as Asset; - if (icon == null && asset != null) - return AssetDatabase.GetCachedIcon(asset.path); - - return icon; - } - set { icon = value; } - } - - public int Identifier - { - get - { - if (identifier == (int)(VCSProviderIdentifier.UnsetIdentifier)) - { - identifier = Provider.GenerateID(); - } - return identifier; - } - } - - public string Name - { - get { return name; } - set { name = value; } - } - - public int Indent - { - get { return indent; } - set { SetIntent(this, value); } - } - - public object Item - { - get { return item; } - set { item = value; } - } - - public Asset Asset - { - get { return item as Asset; } - set { item = value; } - } - - public bool HasPath() - { - Asset a = item as Asset; - return a != null && a.path != null; - } - - public ChangeSet Change - { - get { return item as ChangeSet; } - set { item = value; } - } - - public bool Expanded - { - get { return expanded; } - set { expanded = value; } - } - - public bool Exclusive - { - get { return exclusive; } - set { exclusive = value; } - } - - public bool Dummy - { - get { return dummy; } - set { dummy = value; } - } - - public bool Hidden - { - get { return hidden; } - set { hidden = value; } - } - - public bool HasChildren - { - get { return FirstChild != null; } - } - - public bool HasActions - { - get { return actions != null && actions.Length != 0; } - } - - public string[] Actions - { - get { return actions; } - set { actions = value; } - } - - public bool CanExpand - { - get - { - // Asset asset = item as Asset; - ChangeSet change = item as ChangeSet; - // return ((asset != null && asset.isFolder) || - // change != null || - // HasChildren); - return (change != null || HasChildren); - } - } - - public bool CanAccept - { - get { return accept; } - set { accept = value; } - } - - public int OpenCount - { - get - { - if (!Expanded) - return 0; - - int count = 0; - ListItem listItem = firstChild; - - while (listItem != null) - { - if (!listItem.Hidden) - { - ++count; - count += listItem.OpenCount; - } - - listItem = listItem.next; - } - - return count; - } - } - - public int ChildCount - { - get - { - int count = 0; - ListItem listItem = firstChild; - - while (listItem != null) - { - ++count; - listItem = listItem.next; - } - - return count; - } - } - - public ListItem Parent - { - get { return parent; } - } - - public ListItem FirstChild - { - get { return firstChild; } - } - - public ListItem LastChild - { - get { return lastChild; } - } - - public ListItem Prev - { - get { return prev; } - } - - public ListItem Next - { - get { return next; } - } - - public ListItem PrevOpen - { - get - { - // Previous sibbling or its last open child - ListItem enumChild = prev; - - while (enumChild != null) - { - if (enumChild.lastChild == null || !enumChild.Expanded) - return enumChild; - - enumChild = enumChild.lastChild; - } - - // Move to parent as long as its not the root - if (parent != null && parent.parent != null) - return parent; - - return null; - } - } - - public ListItem NextOpen - { - get - { - // Next child - if (Expanded && firstChild != null) - return firstChild; - - // Next sibbling - if (next != null) - return next; - - // Find a parent with a next - ListItem enumParent = parent; - - while (enumParent != null) - { - if (enumParent.Next != null) - return enumParent.Next; - - enumParent = enumParent.parent; - } - - return null; - } - } - - public ListItem PrevOpenSkip - { - get - { - ListItem listItem = PrevOpen; - while (listItem != null && (listItem.Dummy || listItem.Hidden)) - listItem = listItem.PrevOpen; - - return listItem; - } - } - - public ListItem NextOpenSkip - { - get - { - ListItem listItem = NextOpen; - while (listItem != null && (listItem.Dummy || listItem.Hidden)) - listItem = listItem.NextOpen; - - return listItem; - } - } - - public ListItem PrevOpenVisible - { - get - { - ListItem listItem = PrevOpen; - while (listItem != null && listItem.Hidden) - listItem = listItem.PrevOpen; - - return listItem; - } - } - - public ListItem NextOpenVisible - { - get - { - ListItem listItem = NextOpen; - while (listItem != null && listItem.Hidden) - listItem = listItem.NextOpen; - - return listItem; - } - } - - public bool IsChildOf(ListItem listItem) - { - ListItem it = Parent; - - while (it != null) - { - if (it == listItem) - return true; - - it = it.Parent; - } - - return false; - } - - public void Clear() - { - parent = null; - firstChild = null; - lastChild = null; - prev = null; - next = null; - - icon = null; - name = string.Empty; - indent = 0; - expanded = false; - exclusive = false; - dummy = false; - accept = false; - item = null; - } - - public void Add(ListItem listItem) - { - listItem.parent = this; - listItem.next = null; - listItem.prev = lastChild; - - // recursively update the indent - listItem.Indent = indent + 1; - - if (firstChild == null) - firstChild = listItem; - - if (lastChild != null) - lastChild.next = listItem; - - lastChild = listItem; - } - - public bool Remove(ListItem listItem) - { - if (listItem == null) - return false; - - // Can only remove children of this item - if (listItem.parent != this) - return false; - - if (listItem == firstChild) - firstChild = listItem.next; - - if (listItem == lastChild) - lastChild = listItem.prev; - - if (listItem.prev != null) - listItem.prev.next = listItem.next; - - if (listItem.next != null) - listItem.next.prev = listItem.prev; - - listItem.parent = null; - listItem.prev = null; - listItem.next = null; - - return true; - } - - public void RemoveAll() - { - ListItem en = firstChild; - while (en != null) - { - en.parent = null; - en = en.next; - } - - firstChild = null; - lastChild = null; - } - - public ListItem FindWithIdentifierRecurse(int inIdentifier) - { - if (Identifier == inIdentifier) - return this; - - ListItem listItem = firstChild; - while (listItem != null) - { - ListItem found = listItem.FindWithIdentifierRecurse(inIdentifier); - if (found != null) - return found; - - listItem = listItem.next; - } - return null; - } - - void SetIntent(ListItem listItem, int indent) - { - listItem.indent = indent; - - // Update children - ListItem en = listItem.FirstChild; - while (en != null) - { - SetIntent(en, indent + 1); - en = en.Next; - } - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCMenuChange.cs b/Editor/Mono/VersionControl/UI/VCMenuChange.cs deleted file mode 100644 index b64ade19ec..0000000000 --- a/Editor/Mono/VersionControl/UI/VCMenuChange.cs +++ /dev/null @@ -1,149 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using UnityEditor.VersionControl; - -namespace UnityEditorInternal.VersionControl -{ - // Menu used when right clicking on change lists only. As they are single select they will not get mixed up with asset selections. - public class ChangeSetContextMenu - { - // Get the selected change list. Only one valid at a time - static ChangeSet GetChangeSet(ChangeSets changes) - { - if (changes.Count == 0) - return null; - - return changes[0]; - } - - //[MenuItem ("CONTEXT/Change/Submit...", true)] - static bool SubmitTest(int userData) - { - ChangeSets sets = ListControl.FromID(userData).SelectedChangeSets; - return (sets.Count > 0 && Provider.SubmitIsValid(sets[0], null)); - } - - //[MenuItem ("CONTEXT/Change/Submit...", false, 100)] - static void Submit(int userData) - { - ChangeSets set = ListControl.FromID(userData).SelectedChangeSets; - ChangeSet change = GetChangeSet(set); - - if (change != null) - WindowChange.Open(change, new AssetList(), true); - } - - //[MenuItem ("CONTEXT/Change/Revert...", true)] - static bool RevertTest(int userData) - { - ChangeSets list = ListControl.FromID(userData).SelectedChangeSets; - return list.Count > 0; - } - - //[MenuItem ("CONTEXT/Change/Revert...", false, 200)] - static void Revert(int userData) - { - ChangeSets set = ListControl.FromID(userData).SelectedChangeSets; - ChangeSet change = GetChangeSet(set); - - if (change != null) - WindowRevert.Open(change); - } - - //[MenuItem ("CONTEXT/Change/Revert Unchanged", true)] - static bool RevertUnchangedTest(int userData) - { - ChangeSets sets = ListControl.FromID(userData).SelectedChangeSets; - return sets.Count > 0; - } - - //[MenuItem ("CONTEXT/Change/Revert Unchanged", false, 201)] - static void RevertUnchanged(int userData) - { - ChangeSets sets = ListControl.FromID(userData).SelectedChangeSets; - Provider.RevertChangeSets(sets, RevertMode.Unchanged).SetCompletionAction(CompletionAction.UpdatePendingWindow); - Provider.InvalidateCache(); - } - - //[MenuItem ("CONTEXT/Change/Resolve Conflicts...", true)] - private static bool ResolveTest(int userData) - { - return ListControl.FromID(userData).SelectedChangeSets.Count > 0; - } - - //[MenuItem ("CONTEXT/Change/Resolve Conflicts...", false, 202)] - private static void Resolve(int userData) - { - ChangeSets set = ListControl.FromID(userData).SelectedChangeSets; - ChangeSet change = GetChangeSet(set); - - if (change != null) - WindowResolve.Open(change); - } - - //[MenuItem ("CONTEXT/Change/New Changeset...", true)] - static bool NewChangeSetTest(int userDatad) - { - return Provider.isActive; - } - - //[MenuItem ("CONTEXT/Change/New Changeset...", false, 300)] - static void NewChangeSet(int userData) - { - WindowChange.Open(new AssetList(), false); - } - - //[MenuItem ("CONTEXT/Change/Edit Changeset...", true)] - static bool EditChangeSetTest(int userData) - { - ChangeSets set = ListControl.FromID(userData).SelectedChangeSets; - if (set.Count == 0) return false; - ChangeSet change = GetChangeSet(set); - return (change.id != "-1" && Provider.SubmitIsValid(set[0], null)); - } - - //[MenuItem ("CONTEXT/Change/Edit Changeset...", false, 301)] - static void EditChangeSet(int userData) - { - ChangeSets set = ListControl.FromID(userData).SelectedChangeSets; - ChangeSet change = GetChangeSet(set); - - if (change != null) - WindowChange.Open(change, new AssetList(), false); - } - - //[MenuItem ("CONTEXT/Change/Delete Empty Changeset", true)] - static bool DeleteChangeSetTest(int userData) - { - ListControl l = ListControl.FromID(userData); - ChangeSets set = l.SelectedChangeSets; - if (set.Count == 0) return false; - ChangeSet change = GetChangeSet(set); - - if (change.id == "-1") - return false; - - ListItem item = l.GetChangeSetItem(change); - // TODO: Make changelist cache nonmanaged side to fix this! - bool hasAssets = item != null && item.HasChildren && item.FirstChild.Asset != null && item.FirstChild.Name != ListControl.c_emptyChangeListMessage; - if (!hasAssets) - { - Task task = Provider.ChangeSetStatus(change); - task.Wait(); - hasAssets = task.assetList.Count != 0; - } - - return !hasAssets && Provider.DeleteChangeSetsIsValid(set); - } - - //[MenuItem ("CONTEXT/Change/Delete Empty Changeset", false, 302)] - static void DeleteChangeSet(int userData) - { - ChangeSets set = ListControl.FromID(userData).SelectedChangeSets; - Provider.DeleteChangeSets(set).SetCompletionAction(CompletionAction.UpdatePendingWindow); - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCMenuPending.cs b/Editor/Mono/VersionControl/UI/VCMenuPending.cs deleted file mode 100644 index 8b1436bf9d..0000000000 --- a/Editor/Mono/VersionControl/UI/VCMenuPending.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; - -using UnityEditor.VersionControl; - -namespace UnityEditorInternal.VersionControl -{ - // Standard menu used in the change list window when selecting assets. - public class PendingWindowContextMenu - { - //[MenuItem("CONTEXT/Pending/Submit...", true, 100)] - static bool SubmitTest(int userData) - { - return Provider.SubmitIsValid(null, ListControl.FromID(userData).SelectedAssets); - } - - //[MenuItem ("CONTEXT/Pending/Submit...", false, 100)] - static void Submit(int userData) - { - WindowChange.Open(ListControl.FromID(userData).SelectedAssets, true); - } - - //[MenuItem("CONTEXT/Pending/Revert...", true, 200)] - static bool RevertTest(int userData) - { - return Provider.RevertIsValid(ListControl.FromID(userData).SelectedAssets, RevertMode.Normal); - } - - //[MenuItem ("CONTEXT/Pending/Revert...", false, 200)] - static void Revert(int userData) - { - WindowRevert.Open(ListControl.FromID(userData).SelectedAssets); - } - - //[MenuItem ("CONTEXT/Pending/Revert Unchanged", true, 201)] - static bool RevertUnchangedTest(int userData) - { - return Provider.RevertIsValid(ListControl.FromID(userData).SelectedAssets, RevertMode.Normal); - } - - //[MenuItem ("CONTEXT/Pending/Revert Unchanged", false, 201)] - static void RevertUnchanged(int userData) - { - AssetList list = ListControl.FromID(userData).SelectedAssets; - Provider.Revert(list, RevertMode.Unchanged).SetCompletionAction(CompletionAction.UpdatePendingWindow); - Provider.Status(list); - } - - //[MenuItem("CONTEXT/Pending/Resolve Conflicts...", true, 202)] - static bool ResolveTest(int userData) - { - return Provider.ResolveIsValid(ListControl.FromID(userData).SelectedAssets); - } - - //[MenuItem ("CONTEXT/Pending/Resolve Conflicts...", false, 202)] - static void Resolve(int userData) - { - WindowResolve.Open(ListControl.FromID(userData).SelectedAssets); - } - - //[MenuItem("CONTEXT/Pending/Lock", true, 300)] - static bool LockTest(int userData) - { - return Provider.LockIsValid(ListControl.FromID(userData).SelectedAssets); - } - - //[MenuItem ("CONTEXT/Pending/Lock", false, 300)] - static void Lock(int userData) - { - AssetList list = ListControl.FromID(userData).SelectedAssets; - Provider.Lock(list, true).SetCompletionAction(CompletionAction.UpdatePendingWindow); - } - - //[MenuItem("CONTEXT/Pending/Unlock", true, 301)] - static bool UnlockTest(int userData) - { - return Provider.UnlockIsValid(ListControl.FromID(userData).SelectedAssets); - } - - //[MenuItem ("CONTEXT/Pending/Unlock", false, 301)] - static void Unlock(int userData) - { - AssetList list = ListControl.FromID(userData).SelectedAssets; - Provider.Lock(list, false).SetCompletionAction(CompletionAction.UpdatePendingWindow); - } - - //[MenuItem("CONTEXT/Pending/Diff/Against Head...", true, 400)] - static bool DiffHeadTest(int userData) - { - return Provider.DiffIsValid(ListControl.FromID(userData).SelectedAssets); - } - - //[MenuItem ("CONTEXT/Pending/Diff/Against Head...", false, 400)] - static void DiffHead(int userData) - { - Provider.DiffHead(ListControl.FromID(userData).SelectedAssets, false); - } - - //[MenuItem("CONTEXT/Pending/Diff/Against Head with .meta...", true, 401)] - static bool DiffHeadWithMetaTest(int userData) - { - return Provider.DiffIsValid(ListControl.FromID(userData).SelectedAssets); - } - - //[MenuItem ("CONTEXT/Pending/Diff/Against Head with .meta...", false, 401)] - static void DiffHeadWithMeta(int userData) - { - Provider.DiffHead(ListControl.FromID(userData).SelectedAssets, true); - } - - //[MenuItem("CONTEXT/Pending/Reveal in Finder", true, 402)] - static bool ShowInExplorerTest(int userData) - { - return (ListControl.FromID(userData)).SelectedAssets.Count > 0; - } - - //[MenuItem ("CONTEXT/Pending/Reveal in Finder", false, 402)] - static void ShowInExplorer(int userData) - { - if (System.Environment.OSVersion.Platform == System.PlatformID.MacOSX || - System.Environment.OSVersion.Platform == System.PlatformID.Unix) - { - EditorApplication.ExecuteMenuItem("Assets/Reveal in Finder"); - } - else - { - EditorApplication.ExecuteMenuItem("Assets/Show in Explorer"); - } - } - - //[MenuItem("CONTEXT/Pending/New Changeset...", true, 501)] - static bool NewChangeSetTest(int userData) - { - return Provider.isActive; - } - - //[MenuItem ("CONTEXT/Pending/New Changeset...", false, 501)] - static void NewChangeSet(int userData) - { - WindowChange.Open(ListControl.FromID(userData).SelectedAssets, false); - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCMenuProject.cs b/Editor/Mono/VersionControl/UI/VCMenuProject.cs deleted file mode 100644 index e61a5863bc..0000000000 --- a/Editor/Mono/VersionControl/UI/VCMenuProject.cs +++ /dev/null @@ -1,213 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; - -using UnityEditor.VersionControl; - -namespace UnityEditorInternal.VersionControl -{ - // Menu popup for the main unity project window. Items are greyed out when not available to help with usability. - public class ProjectContextMenu - { - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Get Latest" menu handler - static bool GetLatestTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.GetLatestIsValid(selected); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Get Latest" menu handler - static void GetLatest(MenuCommand cmd) - { - AssetList list = Provider.GetAssetListFromSelection(); - Provider.GetLatest(list).SetCompletionAction(CompletionAction.UpdatePendingWindow); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Submit..." menu handler - static bool SubmitTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.SubmitIsValid(null, selected); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Submit..." menu handler - static void Submit(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - WindowChange.Open(selected, true); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Check Out" menu handler - static bool CheckOutTest(MenuCommand cmd) - { - // TODO: Retrieve CheckoutMode from settings (depends on asset type; native vs. imported) - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.CheckoutIsValid(selected, CheckoutMode.Both); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Check Out" menu handler - static void CheckOut(MenuCommand cmd) - { - // TODO: Retrieve CheckoutMode from settings (depends on asset type; native vs. imported) - AssetList list = Provider.GetAssetListFromSelection(); - Provider.Checkout(list, CheckoutMode.Both); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Check Out (Other)/Only asset file" menu handler - static bool CheckOutAssetTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.CheckoutIsValid(selected, CheckoutMode.Asset); - } - - /// Called from native class VCSAssetMenuHandler as "Assets/Version Control/Check Out (Other)/Only asset file" menu handler - static void CheckOutAsset(MenuCommand cmd) - { - AssetList list = Provider.GetAssetListFromSelection(); - Provider.Checkout(list, CheckoutMode.Asset); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Check Out (Other)/Only .meta file" menu handler - static bool CheckOutMetaTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.CheckoutIsValid(selected, CheckoutMode.Meta); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Check Out (Other)/Only .meta file" menu handler - static void CheckOutMeta(MenuCommand cmd) - { - AssetList list = Provider.GetAssetListFromSelection(); - Provider.Checkout(list, CheckoutMode.Meta); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Check Out (Other)/Both" menu handler - static bool CheckOutBothTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.CheckoutIsValid(selected, CheckoutMode.Both); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Check Out (Other)/Both" menu handler - static void CheckOutBoth(MenuCommand cmd) - { - AssetList list = Provider.GetAssetListFromSelection(); - Provider.Checkout(list, CheckoutMode.Both); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Mark Add" menu handler - static bool MarkAddTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.AddIsValid(selected); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Mark Add" menu handler - static void MarkAdd(MenuCommand cmd) - { - AssetList list = Provider.GetAssetListFromSelection(); - Provider.Add(list, true).SetCompletionAction(CompletionAction.UpdatePendingWindow); - } - - /// Called from native class VCSAssetMenuHandler as "Assets/Version Control/Revert..." menu handler - static bool RevertTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.RevertIsValid(selected, RevertMode.Normal); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Revert..." menu handler - static void Revert(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - WindowRevert.Open(selected); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Revert Unchanged" menu handler - static bool RevertUnchangedTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.RevertIsValid(selected, RevertMode.Normal); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Revert Unchanged" menu handler - static void RevertUnchanged(MenuCommand cmd) - { - AssetList list = Provider.GetAssetListFromSelection(); - Provider.Revert(list, RevertMode.Unchanged).SetCompletionAction(CompletionAction.UpdatePendingWindow); - Provider.Status(list); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Diff Against Head..." menu handler - static bool ResolveTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.ResolveIsValid(selected); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Diff Against Head..." menu handler - static void Resolve(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - WindowResolve.Open(selected); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Lock" menu handler - static bool LockTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.LockIsValid(selected); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Lock" menu handler - static void Lock(MenuCommand cmd) - { - AssetList list = Provider.GetAssetListFromSelection(); - Provider.Lock(list, true).SetCompletionAction(CompletionAction.UpdatePendingWindow); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Unlock" menu handler - static bool UnlockTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.UnlockIsValid(selected); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Unlock" menu handler - static void Unlock(MenuCommand cmd) - { - AssetList list = Provider.GetAssetListFromSelection(); - Provider.Lock(list, false).SetCompletionAction(CompletionAction.UpdatePendingWindow); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Diff/Against Head..." menu handler - static bool DiffHeadTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.DiffIsValid(selected); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Diff/Against Head..." menu handler - static void DiffHead(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - Provider.DiffHead(selected, false); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Diff/Against Head with .meta..." menu handler - static bool DiffHeadWithMetaTest(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.DiffIsValid(selected); - } - - // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Diff/Against Head with .meta..." menu handler - static void DiffHeadWithMeta(MenuCommand cmd) - { - AssetList selected = Provider.GetAssetListFromSelection(); - Provider.DiffHead(selected, true); - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCOverlay.cs b/Editor/Mono/VersionControl/UI/VCOverlay.cs deleted file mode 100644 index cca79a3ed2..0000000000 --- a/Editor/Mono/VersionControl/UI/VCOverlay.cs +++ /dev/null @@ -1,284 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; - -using UnityEditor.VersionControl; - -namespace UnityEditorInternal.VersionControl -{ - public class Overlay - { - private static Texture2D s_BlueLeftParan; - private static Texture2D s_BlueRightParan; - private static Texture2D s_RedLeftParan; - private static Texture2D s_RedRightParan; - - public static Rect GetOverlayRect(Rect itemRect) - { - if (itemRect.width > itemRect.height) - { - itemRect.x += 16; - itemRect.width = 20; - } - else - { - itemRect.width = 12; - } - itemRect.height = itemRect.width; - return itemRect; - } - - public static void DrawOverlay(Asset asset, Rect itemRect) - { - if (asset == null) - return; - - if (Event.current.type != EventType.Repaint) - return; - - string vcsType = EditorSettings.externalVersionControl; - if (vcsType == ExternalVersionControl.Disabled || - vcsType == ExternalVersionControl.AutoDetect || - vcsType == ExternalVersionControl.Generic) - return; // no icons for these version control systems - - DrawOverlays(asset, null, itemRect); - } - - public static void DrawOverlay(Asset asset, Asset metaAsset, Rect itemRect) - { - if (asset == null || metaAsset == null) - return; - - if (Event.current.type != EventType.Repaint) - return; - - string vcsType = EditorSettings.externalVersionControl; - if (vcsType == ExternalVersionControl.Disabled || - vcsType == ExternalVersionControl.AutoDetect || - vcsType == ExternalVersionControl.Generic) - return; // no icons for these version control systems - - DrawOverlays(asset, metaAsset, itemRect); - } - - private static void DrawMetaOverlay(Rect iconRect, bool isRemote) - { - iconRect.y -= 1; - if (isRemote) - { - iconRect.x -= 5; - GUI.DrawTexture(iconRect, s_BlueLeftParan); - iconRect.x += 8; - GUI.DrawTexture(iconRect, s_BlueRightParan); - } - else - { - iconRect.x -= 5; - GUI.DrawTexture(iconRect, s_RedLeftParan); - iconRect.x += 8; - GUI.DrawTexture(iconRect, s_RedRightParan); - } - } - - static void DrawOverlay(Asset.States state, Rect iconRect) - { - Rect atlasUV = Provider.GetAtlasRectForState((int)state); - if (atlasUV.width == 0f) - return; // no overlay - - Texture2D atlas = Provider.overlayAtlas; - if (atlas == null) - return; - - GUI.DrawTextureWithTexCoords(iconRect, atlas, atlasUV); - } - - static void DrawOverlays(Asset asset, Asset metaAsset, Rect itemRect) - { - CreateStaticResources(); - float iconWidth = 16; - float offsetX = 1f; // offset to compensate that icons are 16x16 with 8x8 content - float offsetY = 4f; - float syncOffsetX = -4f; // offset to compensate that icons are 16x16 with 8x8 content and sync overlay pos - - Rect topLeft = new Rect(itemRect.x - offsetX, itemRect.y - offsetY, iconWidth, iconWidth); - Rect topRight = new Rect(itemRect.xMax - iconWidth + offsetX, itemRect.y - offsetY, iconWidth, iconWidth); - Rect bottomLeft = new Rect(itemRect.x - offsetX, itemRect.yMax - iconWidth + offsetY, iconWidth, iconWidth); - Rect bottomRight = new Rect(itemRect.xMax - iconWidth + offsetX, itemRect.yMax - iconWidth + offsetY, iconWidth, iconWidth); - Rect syncRect = new Rect(itemRect.xMax - iconWidth + syncOffsetX, itemRect.yMax - iconWidth + offsetY, iconWidth, iconWidth); - - Asset.States unmodifiedState = Asset.States.Local | Asset.States.MetaFile | Asset.States.ReadOnly | Asset.States.Synced; - bool isMetaUnmodifiedState = metaAsset == null || (metaAsset.state & unmodifiedState) == unmodifiedState; - - Asset.States localMetaState = metaAsset == null ? Asset.States.None : metaAsset.state & (Asset.States.AddedLocal | Asset.States.CheckedOutLocal | Asset.States.DeletedLocal | Asset.States.LockedLocal); - Asset.States remoteMetaState = metaAsset == null ? Asset.States.None : metaAsset.state & (Asset.States.AddedRemote | Asset.States.CheckedOutRemote | Asset.States.DeletedRemote | Asset.States.LockedRemote); - - bool keepFolderMetaParans = asset.isFolder && Provider.isVersioningFolders; - - // Local state overlay - if (asset.IsState(Asset.States.AddedLocal)) - { - DrawOverlay(Asset.States.AddedLocal, topLeft); - - // Meta overlay if meta file is not added or already in repo and unmodified. - if (metaAsset != null && (localMetaState & Asset.States.AddedLocal) == 0 && !isMetaUnmodifiedState) - DrawMetaOverlay(topLeft, false); - } - else if (asset.IsState(Asset.States.DeletedLocal)) - { - DrawOverlay(Asset.States.DeletedLocal, topLeft); - - // Meta overlay if meta file is not deleted but asset is and meta file is still present or missing (ie. should have been there) - if (metaAsset != null && (localMetaState & Asset.States.DeletedLocal) == 0 && metaAsset.IsState(Asset.States.Local | Asset.States.Missing)) - DrawMetaOverlay(topLeft, false); - } - else if (asset.IsState(Asset.States.LockedLocal)) - { - DrawOverlay(Asset.States.LockedLocal, topLeft); - - // Meta overlay if meta file is not locked or unmodified. - if (metaAsset != null && (localMetaState & Asset.States.LockedLocal) == 0 && !isMetaUnmodifiedState) - DrawMetaOverlay(topLeft, false); - } - else if (asset.IsState(Asset.States.CheckedOutLocal)) - { - DrawOverlay(Asset.States.CheckedOutLocal, topLeft); - - // Meta overlay if meta file is not checked out or unmodified. - if (metaAsset != null && (localMetaState & Asset.States.CheckedOutLocal) == 0 && !isMetaUnmodifiedState) - DrawMetaOverlay(topLeft, false); - } - else if (asset.IsState(Asset.States.Local) && !(asset.IsState(Asset.States.OutOfSync) || asset.IsState(Asset.States.Synced))) - { - DrawOverlay(Asset.States.Local, bottomLeft); - - // Meta overlay if meta file is not local only or unmodified. - if (metaAsset != null && (metaAsset.IsUnderVersionControl || !metaAsset.IsState(Asset.States.Local))) - DrawMetaOverlay(bottomLeft, false); - } - // From here the local asset have no state that need a local state overlay. We use the meta state if there is one instead. - else if (metaAsset != null && metaAsset.IsState(Asset.States.AddedLocal)) - { - DrawOverlay(Asset.States.AddedLocal, topLeft); - if (keepFolderMetaParans) - DrawMetaOverlay(topLeft, false); - } - else if (metaAsset != null && metaAsset.IsState(Asset.States.DeletedLocal)) - { - DrawOverlay(Asset.States.DeletedLocal, topLeft); - if (keepFolderMetaParans) - DrawMetaOverlay(topLeft, false); - } - else if (metaAsset != null && metaAsset.IsState(Asset.States.LockedLocal)) - { - DrawOverlay(Asset.States.LockedLocal, topLeft); - if (keepFolderMetaParans) - DrawMetaOverlay(topLeft, false); - } - else if (metaAsset != null && metaAsset.IsState(Asset.States.CheckedOutLocal)) - { - DrawOverlay(Asset.States.CheckedOutLocal, topLeft); - if (keepFolderMetaParans) - DrawMetaOverlay(topLeft, false); - } - else if (metaAsset != null && metaAsset.IsState(Asset.States.Local) && !(metaAsset.IsState(Asset.States.OutOfSync) || metaAsset.IsState(Asset.States.Synced)) - && !(asset.IsState(Asset.States.Conflicted) || (metaAsset != null && metaAsset.IsState(Asset.States.Conflicted)))) - { - DrawOverlay(Asset.States.Local, bottomLeft); - if (keepFolderMetaParans) - DrawMetaOverlay(bottomLeft, false); - } - - if (asset.IsState(Asset.States.Conflicted) || (metaAsset != null && metaAsset.IsState(Asset.States.Conflicted))) - DrawOverlay(Asset.States.Conflicted, bottomLeft); - - if ((asset.isFolder == false && asset.IsState(Asset.States.Updating)) || (metaAsset != null && metaAsset.IsState(Asset.States.Updating))) - DrawOverlay(Asset.States.Updating, bottomRight); - - // Remote state overlay - if (asset.IsState(Asset.States.AddedRemote)) - { - DrawOverlay(Asset.States.AddedRemote, topRight); - - // Meta overlay if meta file is not added or already in repo and unmodified. - if (metaAsset != null && (remoteMetaState & Asset.States.AddedRemote) == 0) - DrawMetaOverlay(topRight, true); - } - else if (asset.IsState(Asset.States.DeletedRemote)) - { - DrawOverlay(Asset.States.DeletedRemote, topRight); - - // Meta overlay if meta file is not deleted but asset is and meta file is still present or missing (ie. should have been there) - if (metaAsset != null && (remoteMetaState & Asset.States.DeletedRemote) == 0) - DrawMetaOverlay(topRight, true); - } - else if (asset.IsState(Asset.States.LockedRemote)) - { - DrawOverlay(Asset.States.LockedRemote, topRight); - - // Meta overlay if meta file is not locked or unmodified. - if (metaAsset != null && (remoteMetaState & Asset.States.LockedRemote) == 0) - DrawMetaOverlay(topRight, true); - } - else if (asset.IsState(Asset.States.CheckedOutRemote)) - { - DrawOverlay(Asset.States.CheckedOutRemote, topRight); - - // Meta overlay if meta file is not checked out or unmodified. - if (metaAsset != null && (remoteMetaState & Asset.States.CheckedOutRemote) == 0) - DrawMetaOverlay(topRight, true); - } - // From here the remote asset have no state that need a remote state overlay. We use the meta state if there is one instead. - else if (metaAsset != null && metaAsset.IsState(Asset.States.AddedRemote)) - { - DrawOverlay(Asset.States.AddedRemote, topRight); - if (keepFolderMetaParans) - DrawMetaOverlay(topRight, true); - } - else if (metaAsset != null && metaAsset.IsState(Asset.States.DeletedRemote)) - { - DrawOverlay(Asset.States.DeletedRemote, topRight); - if (keepFolderMetaParans) - DrawMetaOverlay(topRight, true); - } - else if (metaAsset != null && metaAsset.IsState(Asset.States.LockedRemote)) - { - DrawOverlay(Asset.States.LockedRemote, topRight); - if (keepFolderMetaParans) - DrawMetaOverlay(topRight, true); - } - else if (metaAsset != null && metaAsset.IsState(Asset.States.CheckedOutRemote)) - { - DrawOverlay(Asset.States.CheckedOutRemote, topRight); - if (keepFolderMetaParans) - DrawMetaOverlay(topRight, true); - } - - if (asset.IsState(Asset.States.OutOfSync) || (metaAsset != null && metaAsset.IsState(Asset.States.OutOfSync))) - DrawOverlay(Asset.States.OutOfSync, syncRect); - } - - private static void CreateStaticResources() - { - if (s_BlueLeftParan == null) - { - s_BlueLeftParan = EditorGUIUtility.LoadIcon("P4_BlueLeftParenthesis"); - s_BlueLeftParan.hideFlags = HideFlags.HideAndDontSave; - - s_BlueRightParan = EditorGUIUtility.LoadIcon("P4_BlueRightParenthesis"); - s_BlueRightParan.hideFlags = HideFlags.HideAndDontSave; - - s_RedLeftParan = EditorGUIUtility.LoadIcon("P4_RedLeftParenthesis"); - s_RedLeftParan.hideFlags = HideFlags.HideAndDontSave; - - s_RedRightParan = EditorGUIUtility.LoadIcon("P4_RedRightParenthesis"); - s_RedRightParan.hideFlags = HideFlags.HideAndDontSave; - } - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCProjectHooks.cs b/Editor/Mono/VersionControl/UI/VCProjectHooks.cs deleted file mode 100644 index 5618ac6f9a..0000000000 --- a/Editor/Mono/VersionControl/UI/VCProjectHooks.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditor.VersionControl; - -namespace UnityEditorInternal.VersionControl -{ - // Display hooks for the main project window. Icons are overlayed to show the version control state. - internal class ProjectHooks - { - // GUI callback for each item visible in the project window - public static void OnProjectWindowItem(string guid, Rect drawRect) - { - if (!Provider.isActive) - return; - - Asset asset = Provider.GetAssetByGUID(guid); - if (asset != null) - { - string metaPath = asset.path.Trim('/') + ".meta"; - Asset metaAsset = Provider.GetAssetByPath(metaPath); - Overlay.DrawOverlay(asset, metaAsset, drawRect); - } - } - - public static Rect GetOverlayRect(Rect drawRect) - { - return Overlay.GetOverlayRect(drawRect); - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCWindowChange.cs b/Editor/Mono/VersionControl/UI/VCWindowChange.cs deleted file mode 100644 index f20d602ebc..0000000000 --- a/Editor/Mono/VersionControl/UI/VCWindowChange.cs +++ /dev/null @@ -1,449 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal.VersionControl; -using UnityEditor.VersionControl; -using UnityEditor; - -namespace UnityEditor.VersionControl -{ - // Change window used for either submitting a window, editing a change list or creating a new change list. - internal class WindowChange : EditorWindow - { - ListControl submitList = new ListControl(); - AssetList assetList = new AssetList(); - ChangeSet changeSet = new ChangeSet(); - string description = string.Empty; - bool allowSubmit = false; - Task taskStatus = null; - Task taskDesc = null; - Task taskStat = null; - Task taskSubmit = null; - Task taskAdd = null; - - const int kSubmitNotStartedResultCode = 256; - const int kSubmitRunningResultCode = 0; - int submitResultCode = kSubmitNotStartedResultCode; - string submitErrorMessage = null; - - int m_TextAreaControlID = 0; - - const string c_defaultDescription = ""; - - public void OnEnable() - { - position = new Rect(100, 100, 700, 395); - minSize = new Vector2(700, 395); - - submitList.ReadOnly = true; - taskStatus = null; - taskDesc = null; - taskStat = null; - taskSubmit = null; - submitResultCode = kSubmitNotStartedResultCode; - submitErrorMessage = null; - } - - public void OnDisable() - { - m_TextAreaControlID = 0; - } - - // Open the change list window for a list of files only - static public void Open(AssetList list, bool submit) - { - Open(null, list, submit); - } - - // Perform the actual window open - static public void Open(ChangeSet change, AssetList assets, bool submit) - { - WindowChange win = EditorWindow.GetWindow(true, "Version Control Changeset"); - win.allowSubmit = submit; - win.DoOpen(change, assets); - } - - private string SanitizeDescription(string desc) - { - if (Provider.GetActivePlugin() != null && Provider.GetActivePlugin().name != "Perforce") - return desc; - - // The format of the desc is "on 2013/02/03 by foo@bar *pending* 'The real description'" - // Extract the part between ' and ' - int idx = desc.IndexOf('\''); - if (idx == -1) - return desc; - idx++; - int idx2 = desc.IndexOf('\'', idx); - if (idx2 == -1) - return desc; - return desc.Substring(idx, idx2 - idx).Trim(' ', '\t'); - } - - // Open the change list window for one of 2 modes. File list or exisiting change list. - // If changeID is null then a list of files is assumed and the user can sumbit them - // as a new change list. - void DoOpen(ChangeSet change, AssetList assets) - { - taskSubmit = null; - submitResultCode = kSubmitNotStartedResultCode; - submitErrorMessage = null; - changeSet = change; - description = change == null ? c_defaultDescription : SanitizeDescription(change.description); - assetList = null; - - // Refresh the assets or changeset states - if (change == null) - { - taskStatus = Provider.Status(assets); - } - else - { - taskDesc = Provider.ChangeSetDescription(change); - taskStat = Provider.ChangeSetStatus(change); - } - } - - void RefreshList() - { - submitList.Clear(); - - foreach (Asset it in assetList) - submitList.Add(null, it.prettyPath, it); - - if (assetList.Count == 0) - { - ChangeSet change = new ChangeSet(ListControl.c_emptyChangeListMessage); - ListItem item = submitList.Add(null, change.description, change); - item.Dummy = true; - } - - submitList.Refresh(); - Repaint(); - } - - internal static void OnSubmitted(Task task) - { - var winsChange = Resources.FindObjectsOfTypeAll(typeof(WindowChange)) as WindowChange[]; - if (winsChange.Length == 0) - return; // user closed submit window before submit finished. Just ignore the status callback. - var win = winsChange[0]; - win.assetList = task.assetList; - win.submitResultCode = task.resultCode; - win.submitErrorMessage = null; - - if ((task.resultCode & (int)SubmitResult.Error) != 0) - { - string delim = ""; - foreach (Message msg in task.messages) - { - if (msg.severity == Message.Severity.Error) - win.submitErrorMessage += delim + msg.message; - } - } - - if ((task.resultCode & ((int)SubmitResult.OK | (int)SubmitResult.Error)) != 0) - { - WindowPending.UpdateAllWindows(); - bool isNewChangeSet = win.changeSet == null; - if (isNewChangeSet) - { - // When change list becomes empty we open it to make "delete empty changessets" button visible - Task flushTask = Provider.Status(""); // Make a dummy task and wait for it since that will guarantee up to date lists - flushTask.Wait(); - WindowPending.ExpandLatestChangeSet(); - } - } - - if ((task.resultCode & (int)SubmitResult.OK) != 0) - win.ResetAndClose(); - else - win.RefreshList(); - } - - internal static void OnAdded(Task task) - { - var winsChange = Resources.FindObjectsOfTypeAll(typeof(WindowChange)) as WindowChange[]; - if (winsChange.Length == 0) - return; // user closed submit window before submit finished. Just ignore the status callback. - var win = winsChange[0]; - win.taskSubmit = null; - win.submitResultCode = kSubmitNotStartedResultCode; - win.submitErrorMessage = null; - win.taskAdd = null; - - // Refetch status - win.taskStatus = Provider.Status(win.assetList, false); - win.assetList = null; - WindowPending.UpdateAllWindows(); // reflect newly added assets in pending window - } - - void OnGUI() - { - if ((submitResultCode & (int)SubmitResult.ConflictingFiles) != 0) - OnConflictingFilesGUI(); - else if ((submitResultCode & (int)SubmitResult.UnaddedFiles) != 0) - OnUnaddedFilesGUI(); - else if ((submitResultCode & (int)SubmitResult.Error) != 0) - OnErrorGUI(); - else - OnSubmitGUI(); - } - - void OnSubmitGUI() - { - bool isSubmitting = submitResultCode != kSubmitNotStartedResultCode; - if (isSubmitting) - GUI.enabled = false; - - Event evt = Event.current; - if (evt.isKey && evt.keyCode == KeyCode.Escape) - Close(); - - GUILayout.Label("Description", EditorStyles.boldLabel); - - if (taskStatus != null && taskStatus.resultCode != 0) - { - const bool includeFolders = true; - assetList = taskStatus.assetList.Filter(includeFolders, - Asset.States.CheckedOutLocal, - Asset.States.DeletedLocal, - Asset.States.AddedLocal/*, - Asset.States.Branch, - Asset.States.Integrate*/); - RefreshList(); - taskStatus = null; - } - else if (taskDesc != null && taskDesc.resultCode != 0) - { - description = taskDesc.text.Length > 0 ? taskDesc.text : c_defaultDescription; - if (description.Trim() == "") - description = string.Empty; - taskDesc = null; - } - else if (taskStat != null && taskStat.resultCode != 0) - { - assetList = taskStat.assetList; - RefreshList(); - taskStat = null; - } - - Task progressTask = taskStatus != null && taskStatus.resultCode == 0 ? taskStatus : - taskDesc != null && taskDesc.resultCode == 0 ? taskDesc : - taskStat != null && taskStat.resultCode == 0 ? taskStat : taskSubmit; - - GUI.enabled = (taskDesc == null || taskDesc.resultCode != 0) && submitResultCode == kSubmitNotStartedResultCode; - { - description = EditorGUILayout.TextArea(description, GUILayout.Height(150)).Trim(); - if (m_TextAreaControlID == 0) - m_TextAreaControlID = EditorGUIUtility.s_LastControlID; - if (m_TextAreaControlID != 0) - { - EditorGUIUtility.keyboardControl = m_TextAreaControlID; - EditorGUIUtility.editingTextField = true; - } - } - GUI.enabled = true; - - GUILayout.Label("Files", EditorStyles.boldLabel); - GUILayout.FlexibleSpace(); - - // I would use GUIUtility.GetLastRect() here after the box but that seems to have wierd side effects. - Rect r1 = new Rect(6, 206, position.width - 12, position.height - 248); - GUILayout.BeginArea(r1); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - GUILayout.EndArea(); - submitList.OnGUI(new Rect(r1.x + 2, r1.y + 2, r1.width - 4, r1.height - 4), true); - - GUILayout.FlexibleSpace(); - GUILayout.BeginHorizontal(); - - - if (submitResultCode == kSubmitNotStartedResultCode) - { - if (progressTask != null) - { - // It is possible to have a progressTask for getting description text. - GUIContent c = GUIContent.Temp("Getting info"); - c.image = WindowPending.StatusWheel.image; - GUILayout.Label(c); - c.image = null; - } - - GUILayout.FlexibleSpace(); - - if (GUILayout.Button("Cancel")) - ResetAndClose(); - - GUI.enabled = progressTask == null && !string.IsNullOrEmpty(description); - - bool keyboardShortcutActivated = evt.isKey && evt.shift && evt.keyCode == KeyCode.Return; - bool saveByShortcut = keyboardShortcutActivated && !allowSubmit; - - if (Provider.hasChangelistSupport && (GUILayout.Button("Save") || saveByShortcut)) - Save(false); - - if (allowSubmit) - { - bool origEnabled = GUI.enabled; - GUI.enabled = assetList != null && assetList.Count > 0 && !string.IsNullOrEmpty(description); - - if (GUILayout.Button("Submit") || keyboardShortcutActivated) - Save(true); - - GUI.enabled = origEnabled; - } - } - else - { - // submit finished successfully or running - - bool finished = (submitResultCode & (int)SubmitResult.OK) != 0; - GUI.enabled = finished; - - string msg = ""; - if (finished) - { - msg = "Finished successfully"; - } - else if (progressTask != null) - { - GUILayout.Label(WindowPending.StatusWheel); - msg = progressTask.progressMessage; - if (msg.Length == 0) - msg = "Running..."; - } - - GUILayout.Label(msg); - GUILayout.FlexibleSpace(); - if (GUILayout.Button("Close")) - ResetAndClose(); - } - - GUI.enabled = true; - - GUILayout.EndHorizontal(); - GUILayout.Space(12); - - if (progressTask != null) - Repaint(); - } - - void OnErrorGUI() - { - GUILayout.Label("Submit failed", EditorStyles.boldLabel); - - string msg = ""; - if (!string.IsNullOrEmpty(submitErrorMessage)) - msg = submitErrorMessage + "\n"; - - msg += "See console for details. You can get more details by increasing log level in EditorSettings."; - - GUILayout.Label(msg); - - GUILayout.FlexibleSpace(); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - if (GUILayout.Button("Close")) - { - ResetAndClose(); - - // The error message may be telling that the plugin is opening a window - // to handle conflicts. After that has been handled and we close this window - // we want to update our state. - WindowPending.UpdateAllWindows(); - } - GUILayout.EndHorizontal(); - } - - void OnConflictingFilesGUI() - { - string files = ""; - - foreach (Asset a in assetList) - { - if (a.IsState(Asset.States.Conflicted)) - { - files += a.prettyPath + "\n"; - } - } - - GUILayout.Label("Conflicting files", EditorStyles.boldLabel); - GUILayout.Label("Some files need to be resolved before submitting:"); - GUI.enabled = false; - GUILayout.TextArea(files, GUILayout.ExpandHeight(true)); - GUI.enabled = true; - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - if (GUILayout.Button("Close")) - ResetAndClose(); - - GUILayout.EndHorizontal(); - } - - void OnUnaddedFilesGUI() - { - AssetList toAdd = new AssetList(); - string files = ""; - - foreach (Asset a in assetList) - { - if (!a.IsState(Asset.States.OutOfSync) && !a.IsState(Asset.States.Synced) && !a.IsState(Asset.States.AddedLocal)) - { - files += a.prettyPath + "\n"; - toAdd.Add(a); - } - } - - GUILayout.Label("Files to add", EditorStyles.boldLabel); - GUILayout.Label("Some additional files need to be added:"); - GUI.enabled = false; - GUILayout.TextArea(files); - GUI.enabled = true; - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - if (GUILayout.Button("Add files")) - { - taskAdd = Provider.Add(toAdd, false); - taskAdd.SetCompletionAction(CompletionAction.OnAddedChangeWindow); - } - - if (GUILayout.Button("Abort")) - ResetAndClose(); - - GUILayout.EndHorizontal(); - } - - private void ResetAndClose() - { - taskSubmit = null; - submitResultCode = kSubmitNotStartedResultCode; - submitErrorMessage = null; - Close(); - } - - void Save(bool submit) - { - if (description.Trim() == c_defaultDescription) - { - Debug.LogError("Version control: Please enter a valid change description"); - return; - } - - UnityEditor.AssetDatabase.SaveAssets(); - - // Submit the change list. Last parameter is "save only" so invert the submit flag - - taskSubmit = Provider.Submit(changeSet, assetList, description, !submit); - submitResultCode = kSubmitRunningResultCode; - submitErrorMessage = null; - taskSubmit.SetCompletionAction(CompletionAction.OnSubmittedChangeWindow); // TODO: make it CompletionAction.OnChangeSetsPendingWindow - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCWindowCheckoutFailure.cs b/Editor/Mono/VersionControl/UI/VCWindowCheckoutFailure.cs deleted file mode 100644 index 60f6ccab5f..0000000000 --- a/Editor/Mono/VersionControl/UI/VCWindowCheckoutFailure.cs +++ /dev/null @@ -1,156 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal.VersionControl; - -namespace UnityEditor.VersionControl -{ - // Window allowing you to review files that could not be checked out. - internal class WindowCheckoutFailure : EditorWindow - { - private AssetList assetList = new AssetList(); - private ListControl checkoutSuccessList = new ListControl(); - private ListControl checkoutFailureList = new ListControl(); - - public void OnEnable() - { - position = new Rect(100, 100, 700, 230); - minSize = new Vector2(700, 230); - - checkoutSuccessList.ReadOnly = true; - checkoutFailureList.ReadOnly = true; - } - - public static void OpenIfCheckoutFailed(AssetList assets) - { - Object[] windows = Resources.FindObjectsOfTypeAll(typeof(WindowCheckoutFailure)); - WindowCheckoutFailure window = (windows.Length > 0 ? windows[0] as WindowCheckoutFailure : null); - - bool alreadyOpen = (window != null); - bool shouldOpen = alreadyOpen; - - if (!shouldOpen) - { - foreach (var asset in assets) - { - if (!asset.IsState(Asset.States.CheckedOutLocal)) - { - shouldOpen = true; - break; - } - } - } - - if (shouldOpen) - GetWindow().DoOpen(assets, alreadyOpen); - } - - private static WindowCheckoutFailure GetWindow() - { - return EditorWindow.GetWindow(true, "Version Control Check Out Failed"); - } - - private void DoOpen(AssetList assets, bool alreadyOpen) - { - if (alreadyOpen) - { - foreach (var asset in assets) - { - bool found = false; - int count = assetList.Count; - - for (int i = 0; i < count; i++) - { - if (assetList[i].path == asset.path) - { - found = true; - assetList[i] = asset; - break; - } - } - - if (!found) - assetList.Add(asset); - } - } - else - assetList.AddRange(assets); - - RefreshList(); - } - - private void RefreshList() - { - checkoutSuccessList.Clear(); - checkoutFailureList.Clear(); - - foreach (var asset in assetList) - { - if (asset.IsState(Asset.States.CheckedOutLocal)) - checkoutSuccessList.Add(null, asset.prettyPath, asset); - else - checkoutFailureList.Add(null, asset.prettyPath, asset); - } - - checkoutSuccessList.Refresh(); - checkoutFailureList.Refresh(); - - Repaint(); - } - - public void OnGUI() - { - float h = (position.height - 122) / 2; - - // TODO: Show the reason: Who has the exclusive lock? - GUILayout.Label("Some files could not be checked out:", EditorStyles.boldLabel); - - Rect r1 = new Rect(6, 40, position.width - 12, h); - GUILayout.BeginArea(r1); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - GUILayout.EndArea(); - checkoutFailureList.OnGUI(new Rect(r1.x + 2, r1.y + 2, r1.width - 4, r1.height - 4), true); - - GUILayout.Space(20 + h); - GUILayout.Label("The following files were successfully checked out:", EditorStyles.boldLabel); - - Rect r2 = new Rect(6, 40 + h + 40, position.width - 12, h); - GUILayout.BeginArea(r2); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - GUILayout.EndArea(); - checkoutSuccessList.OnGUI(new Rect(r2.x + 2, r2.y + 2, r2.width - 4, r2.height - 4), true); - - GUILayout.FlexibleSpace(); - GUILayout.BeginHorizontal(); - - EditorUserSettings.showFailedCheckout = !GUILayout.Toggle(!EditorUserSettings.showFailedCheckout, "Don't show this window again."); - - GUILayout.FlexibleSpace(); - - bool enabled = GUI.enabled; - GUI.enabled = checkoutFailureList.Size > 0; - - if (GUILayout.Button("Retry Check Out")) - Provider.Checkout(assetList, CheckoutMode.Exact); - - GUI.enabled = checkoutSuccessList.Size > 0; - - if (GUILayout.Button("Revert Unchanged")) - { - Provider.Revert(assetList, RevertMode.Unchanged).SetCompletionAction(CompletionAction.UpdatePendingWindow); - Provider.Status(assetList); - Close(); - } - - GUI.enabled = enabled; - - if (GUILayout.Button("OK")) - Close(); - - GUILayout.EndHorizontal(); - GUILayout.Space(12); - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCWindowPending.cs b/Editor/Mono/VersionControl/UI/VCWindowPending.cs deleted file mode 100644 index 9fa797df78..0000000000 --- a/Editor/Mono/VersionControl/UI/VCWindowPending.cs +++ /dev/null @@ -1,649 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal.VersionControl; - -namespace UnityEditor.VersionControl -{ - // Pending change list window which shows all the change lists for the version control system. This is - // agnostic of any version control system as long as it supports the VCInterface interface. - // - // This window now works in an async manner but the method of update should now be improved to hide - // the refreshing - [EditorWindowTitle(title = "Version Control", icon = "UnityEditor.VersionControl")] - internal class WindowPending : EditorWindow - { - internal class Styles - { - public GUIStyle box = "CN Box"; - public GUIStyle bottomBarBg = "ProjectBrowserBottomBarBg"; - } - static Styles s_Styles = null; - - static Texture2D changeIcon = null; - Texture2D syncIcon = null; - Texture2D refreshIcon = null; - GUIStyle header; - [SerializeField] ListControl pendingList; - [SerializeField] ListControl incomingList; - - bool m_ShowIncoming = false; - const float k_ResizerHeight = 17f; - const float k_MinIncomingAreaHeight = 50f; - const float k_BottomBarHeight = 17f; - float s_ToolbarButtonsWidth = 0f; - float s_SettingsButtonWidth = 0f; - float s_DeleteChangesetsButtonWidth = 0f; - - static GUIContent[] sStatusWheel; - - // Workaround to reload vcs info upon domain reload. TODO: Fix VersionControl.ListControl to get rid of this - static bool s_DidReload = false; // defaults to false after domain reload - - void InitStyles() - { - if (s_Styles == null) - { - s_Styles = new Styles(); - } - } - - static internal GUIContent StatusWheel - { - get - { - if (sStatusWheel == null) - { - sStatusWheel = new GUIContent[12]; - for (int i = 0; i < 12; i++) - { - GUIContent gc = new GUIContent(); - gc.image = EditorGUIUtility.LoadIcon("WaitSpin" + i.ToString("00")) as Texture2D; - //EditorGUIUtility.LoadIconForSkin( - //gc.image = tex != null ? tex : EditorGUIUtility.LoadIcon("Builtin Skins/Icons/ WaitSpin" + i.ToString("00") + ".png") as Texture2D; - gc.image.hideFlags = HideFlags.HideAndDontSave; - gc.image.name = "Spinner"; - sStatusWheel[i] = gc; - } - } - int frame = (int)Mathf.Repeat(Time.realtimeSinceStartup * 10, 11.99f); - return sStatusWheel[frame]; - } - } - - void OnEnable() - { - titleContent = GetLocalizedTitleContent(); - - if (pendingList == null) - pendingList = new ListControl(); - - pendingList.ExpandEvent += OnExpand; - pendingList.DragEvent += OnDrop; - pendingList.MenuDefault = "CONTEXT/Pending"; - pendingList.MenuFolder = "CONTEXT/Change"; - pendingList.DragAcceptOnly = true; - - if (incomingList == null) - incomingList = new ListControl(); - - incomingList.ExpandEvent += OnExpandIncoming; - UpdateWindow(); - } - - // Watch for selections from another window - public void OnSelectionChange() - { - if (!hasFocus) - { - pendingList.Sync(); - Repaint(); - } - } - - // Handle drag events from the list - void OnDrop(ChangeSet targetItem) - { - AssetList list = pendingList.SelectedAssets; - Task moveTask = Provider.ChangeSetMove(list, targetItem); - moveTask.SetCompletionAction(CompletionAction.UpdatePendingWindow); - } - - static public void ExpandLatestChangeSet() - { - var wins = Resources.FindObjectsOfTypeAll(typeof(WindowPending)) as WindowPending[]; - - foreach (WindowPending win in wins) - { - win.pendingList.ExpandLastItem(); - } - } - - // Handle list elements being expanded - void OnExpand(ChangeSet change, ListItem item) - { - if (!Provider.isActive) - return; - - Task task = Provider.ChangeSetStatus(change); - task.userIdentifier = item.Identifier; - task.SetCompletionAction(CompletionAction.OnChangeContentsPendingWindow); - - if (!item.HasChildren) - { - Asset asset = new Asset("Updating..."); - ListItem changeItem = pendingList.Add(item, asset.prettyPath, asset); - changeItem.Dummy = true; - pendingList.Refresh(false); //true here would cause recursion - Repaint(); - } - } - - void OnExpandIncoming(ChangeSet change, ListItem item) - { - if (!Provider.isActive) - return; - - Task task = Provider.IncomingChangeSetAssets(change); - - task.userIdentifier = item.Identifier; - task.SetCompletionAction(CompletionAction.OnChangeContentsPendingWindow); - if (!item.HasChildren) - { - Asset asset = new Asset("Updating..."); - ListItem changeItem = incomingList.Add(item, asset.prettyPath, asset); - changeItem.Dummy = true; - incomingList.Refresh(false); //true here would cause recursion - Repaint(); - } - } - - // called to update the status - void UpdateWindow() - { - if (!Provider.isActive) - { - pendingList.Clear(); - Provider.UpdateSettings(); // Try to resend the settings if we by chance has become online again - Repaint(); - return; - } - - if (Provider.onlineState == OnlineState.Online) - { - Task changesTask = Provider.ChangeSets(); - changesTask.SetCompletionAction(CompletionAction.OnChangeSetsPendingWindow); - - Task incomingTask = Provider.Incoming(); - incomingTask.SetCompletionAction(CompletionAction.OnIncomingPendingWindow); - } - } - - void OnGotLatest(Task t) - { - UpdateWindow(); - } - - static void OnVCTaskCompletedEvent(Task task, CompletionAction completionAction) - { - var wins = Resources.FindObjectsOfTypeAll(typeof(WindowPending)) as WindowPending[]; - - foreach (WindowPending win in wins) - { - switch (completionAction) - { - case CompletionAction.UpdatePendingWindow: // fallthrough - case CompletionAction.OnCheckoutCompleted: - win.UpdateWindow(); - break; - case CompletionAction.OnChangeContentsPendingWindow: - win.OnChangeContents(task); - break; - case CompletionAction.OnIncomingPendingWindow: - win.OnIncoming(task); - break; - case CompletionAction.OnChangeSetsPendingWindow: - win.OnChangeSets(task); - break; - case CompletionAction.OnGotLatestPendingWindow: - win.OnGotLatest(task); - break; - } - } - - switch (completionAction) - { - case CompletionAction.OnSubmittedChangeWindow: - WindowChange.OnSubmitted(task); - break; - case CompletionAction.OnAddedChangeWindow: - WindowChange.OnAdded(task); - break; - case CompletionAction.OnCheckoutCompleted: - if (EditorUserSettings.showFailedCheckout) - WindowCheckoutFailure.OpenIfCheckoutFailed(task.assetList); - break; - } - - task.Dispose(); - } - - public static void OnStatusUpdated() - { - UpdateAllWindows(); - } - - public static void UpdateAllWindows() - { - var wins = Resources.FindObjectsOfTypeAll(typeof(WindowPending)) as WindowPending[]; - - foreach (WindowPending win in wins) - { - win.UpdateWindow(); - } - } - - public static void CloseAllWindows() - { - var wins = Resources.FindObjectsOfTypeAll(typeof(WindowPending)) as WindowPending[]; - WindowPending win = wins.Length > 0 ? wins[0] : null; - if (win != null) - { - win.Close(); - } - } - - // Incoming Change Lists have been updated - void OnIncoming(Task task) - { - CreateStaticResources(); - PopulateListControl(incomingList, task, syncIcon); - } - - // Change lists have been updated - void OnChangeSets(Task task) - { - CreateStaticResources(); - PopulateListControl(pendingList, task, changeIcon); - } - - void PopulateListControl(ListControl list, Task task, Texture2D icon) - { - // We try to correct the existing list by removing/adding entries. - // This way the entries will keep their children while the children are updated - // and will prevent flicker - - // list.Clear (); - - // Remove from existing list entries not in the incoming one - ChangeSets css = task.changeSets; - - ListItem it = list.Root.FirstChild; - while (it != null) - { - ChangeSet cs = it.Item as ChangeSet; - if (css.Find(elm => elm.id == cs.id) == null) - { - // Found an list item that was not in the incoming list. - // Lets remove it. - ListItem rm = it; - it = it.Next; - list.Root.Remove(rm); - } - else - { - it = it.Next; - } - } - - // Update the existing ones with the new content or add new ones - foreach (ChangeSet change in css) - { - ListItem changeItem = list.GetChangeSetItem(change); - if (changeItem != null) - { - changeItem.Item = change; - changeItem.Name = change.description; - } - else - { - changeItem = list.Add(null, change.description, change); - } - changeItem.Exclusive = true; // Single selection only - changeItem.CanAccept = true; // Accept drag and drop - changeItem.Icon = icon; // changeset icon - } - - // Refresh here will trigger the expand events to ensure the same change lists - // are kept open. This will in turn trigger change list contents update requests - list.Refresh(); - Repaint(); - } - - // Change list contents have been updated - void OnChangeContents(Task task) - { - ListItem pendingItem = pendingList.FindItemWithIdentifier(task.userIdentifier); - ListItem item = pendingItem == null ? incomingList.FindItemWithIdentifier(task.userIdentifier) : pendingItem; - - if (item == null) - return; - - ListControl list = pendingItem == null ? incomingList : pendingList; - - item.RemoveAll(); - - AssetList assetList = task.assetList; - - // Add all files to the list - if (assetList.Count == 0) - { - // Can only happen for pendingList since incoming lists are frozen by design. - ListItem empty = list.Add(item, ListControl.c_emptyChangeListMessage, (Asset)null); - empty.Dummy = true; - } - else - { - foreach (Asset a in assetList) - list.Add(item, a.prettyPath, a); - } - - list.Refresh(false); // false means the expanded events are not called - Repaint(); - } - - private ChangeSets GetEmptyChangeSetsCandidates() - { - ListControl l = pendingList; - ChangeSets set = l.EmptyChangeSets; - ChangeSets toDelete = new ChangeSets(); - set - .FindAll(item => item.id != ChangeSet.defaultID) - .ForEach(delegate(ChangeSet s) { toDelete.Add(s); }); - return toDelete; - } - - private bool HasEmptyPendingChangesets() - { - ChangeSets changeSets = GetEmptyChangeSetsCandidates(); - return Provider.DeleteChangeSetsIsValid(changeSets); - } - - private void DeleteEmptyPendingChangesets() - { - ChangeSets changeSets = GetEmptyChangeSetsCandidates(); - Provider.DeleteChangeSets(changeSets).SetCompletionAction(CompletionAction.UpdatePendingWindow); - } - - // Editor window GUI paint - void OnGUI() - { - InitStyles(); - - if (!s_DidReload) - { - s_DidReload = true; - UpdateWindow(); - } - - CreateResources(); - - Event e = Event.current; - float toolBarHeight = EditorStyles.toolbar.fixedHeight; - bool refresh = false; - - GUILayout.BeginArea(new Rect(0, 0, position.width, toolBarHeight)); - - - GUILayout.BeginHorizontal(EditorStyles.toolbar); - - EditorGUI.BeginChangeCheck(); - - int incomingChangesetCount = incomingList.Root == null ? 0 : incomingList.Root.ChildCount; - m_ShowIncoming = !GUILayout.Toggle(!m_ShowIncoming, "Outgoing", EditorStyles.toolbarButton); - - GUIContent cont = GUIContent.Temp("Incoming" + (incomingChangesetCount == 0 ? "" : " (" + incomingChangesetCount.ToString() + ")")); - m_ShowIncoming = GUILayout.Toggle(m_ShowIncoming, cont, EditorStyles.toolbarButton); - - if (EditorGUI.EndChangeCheck()) - refresh = true; - - GUILayout.FlexibleSpace(); - - // Global context custom commands goes here - using (new EditorGUI.DisabledScope(Provider.activeTask != null)) - { - foreach (CustomCommand c in Provider.customCommands) - { - if (c.context == CommandContext.Global && GUILayout.Button(c.label, EditorStyles.toolbarButton)) - c.StartTask(); - } - } - - bool showDeleteEmptyChangesetsButton = - Mathf.FloorToInt(position.width - s_ToolbarButtonsWidth - s_SettingsButtonWidth - s_DeleteChangesetsButtonWidth) > 0 && - HasEmptyPendingChangesets(); - if (showDeleteEmptyChangesetsButton && GUILayout.Button("Delete Empty Changesets", EditorStyles.toolbarButton)) - { - DeleteEmptyPendingChangesets(); - } - - bool showSettingsButton = Mathf.FloorToInt(position.width - s_ToolbarButtonsWidth - s_SettingsButtonWidth) > 0; - if (showSettingsButton && GUILayout.Button("Settings", EditorStyles.toolbarButton)) - { - EditorApplication.ExecuteMenuItem("Edit/Project Settings/Editor"); - EditorWindow.FocusWindowIfItsOpen(); - GUIUtility.ExitGUI(); - } - - Color origColor = GUI.color; - GUI.color = new Color(1, 1, 1, 1 * .5f); - bool refreshButtonClicked = GUILayout.Button(refreshIcon, EditorStyles.toolbarButton); - refresh = refresh || refreshButtonClicked; - GUI.color = origColor; - - if (e.isKey && GUIUtility.keyboardControl == 0) - { - if (e.type == EventType.KeyDown && e.keyCode == KeyCode.F5) - { - // TODO handle refresh different - refresh = true; - e.Use(); - } - } - - if (refresh) - { - if (refreshButtonClicked) - Provider.InvalidateCache(); - UpdateWindow(); - } - - GUILayout.EndArea(); - - Rect rect = new Rect(0, toolBarHeight, position.width, position.height - toolBarHeight - k_BottomBarHeight); - - bool repaint = false; - - GUILayout.EndHorizontal(); - - // Disabled Window view - if (!Provider.isActive) - { - Color tmpColor = GUI.color; - GUI.color = new Color(0.8f, 0.5f, 0.5f); - rect.height = toolBarHeight; - GUILayout.BeginArea(rect); - - GUILayout.BeginHorizontal(EditorStyles.toolbar); - GUILayout.FlexibleSpace(); - string msg = "DISABLED"; - if (Provider.enabled) - { - if (Provider.onlineState == OnlineState.Updating) - { - GUI.color = new Color(0.8f, 0.8f, 0.5f); - msg = "CONNECTING..."; - } - else - msg = "OFFLINE"; - } - - GUILayout.Label(msg, EditorStyles.miniLabel); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - GUILayout.EndArea(); - - rect.y += rect.height; - if (!string.IsNullOrEmpty(Provider.offlineReason)) - GUI.Label(rect, Provider.offlineReason); - - GUI.color = tmpColor; - repaint = false; - } - else - { - if (m_ShowIncoming) - { - repaint |= incomingList.OnGUI(rect, hasFocus); - } - else - { - repaint |= pendingList.OnGUI(rect, hasFocus); - } - - - rect.y += rect.height; - rect.height = k_BottomBarHeight; - - // Draw separation line over the button - GUI.Label(rect, GUIContent.none, s_Styles.bottomBarBg); - - var content = EditorGUIUtility.TrTextContent("Apply All Incoming Changes"); - var buttonSize = EditorStyles.miniButton.CalcSize(content); - Rect progressRect = new Rect(rect.x, rect.y - 2, rect.width - buttonSize.x - 5f, rect.height); - ProgressGUI(progressRect, Provider.activeTask, false); - - if (m_ShowIncoming) - { - // Draw "apply incoming" button - var buttonRect = rect; - buttonRect.width = buttonSize.x; - buttonRect.height = buttonSize.y; - buttonRect.y = rect.y + 2f; - buttonRect.x = position.width - buttonSize.x - 5f; - - using (new EditorGUI.DisabledScope(incomingList.Size == 0)) - { - if (GUI.Button(buttonRect, content, EditorStyles.miniButton)) - { - Asset root = new Asset(""); - Task t = Provider.GetLatest(new AssetList() { root }); - t.SetCompletionAction(CompletionAction.OnGotLatestPendingWindow); - } - } - } - } - - if (repaint) - Repaint(); - } - - /* Keep for future description area - void ResizeHandling (float width, float height) - { - // We add a horizontal size controller to adjust incoming vs outgoing area - float headersHeight = 26f + k_ResizerHeight + EditorStyles.toolbarButton.fixedHeight; - Rect dragRect = new Rect (0f, m_IncomingAreaHeight + headersHeight, width, k_ResizerHeight); - - if (Event.current.type == EventType.Repaint) - EditorGUIUtility.AddCursorRect (dragRect, MouseCursor.ResizeVertical); - - // Drag internal splitter - float deltaY = EditorGUI.MouseDeltaReader(dragRect, true).y; - if (deltaY != 0f) - { - m_IncomingAreaHeight += deltaY; - - } - float maxHeight = height - k_MinIncomingAreaHeight - headersHeight; - m_IncomingAreaHeight = Mathf.Clamp (m_IncomingAreaHeight, k_MinIncomingAreaHeight, maxHeight); - } - */ - - internal static bool ProgressGUI(Rect rect, Task activeTask, bool descriptionTextFirst) - { - if (activeTask != null && (activeTask.progressPct != -1 || activeTask.secondsSpent != -1 || activeTask.progressMessage.Length != 0)) - { - string msg = activeTask.progressMessage; - Rect sr = rect; - GUIContent cont = StatusWheel; - sr.width = sr.height; - sr.x += 4; - sr.y += 4; - GUI.Label(sr, cont); - - rect.x += sr.width + 4; - - msg = msg.Length == 0 ? activeTask.description : msg; - - if (activeTask.progressPct == -1) - { - rect.width -= sr.width + 4; - rect.y += 4; - GUI.Label(rect, msg, EditorStyles.miniLabel); - } - else - { - rect.width = 120; - EditorGUI.ProgressBar(rect, activeTask.progressPct, msg); - } - return true; - } - return false; - } - - void CreateResources() - { - if (refreshIcon == null) - { - refreshIcon = EditorGUIUtility.LoadIcon("Refresh"); - refreshIcon.hideFlags = HideFlags.HideAndDontSave; - refreshIcon.name = "RefreshIcon"; - } - - if (header == null) - header = "OL Title"; - - CreateStaticResources(); - - if (s_ToolbarButtonsWidth == 0f) - { - s_ToolbarButtonsWidth = EditorStyles.toolbarButton.CalcSize(EditorGUIUtility.TrTextContent("Incoming (xx)")).x; - s_ToolbarButtonsWidth += EditorStyles.toolbarButton.CalcSize(EditorGUIUtility.TrTextContent("Outgoing")).x; - s_ToolbarButtonsWidth += EditorStyles.toolbarButton.CalcSize(new GUIContent(refreshIcon)).x; - - s_SettingsButtonWidth = EditorStyles.toolbarButton.CalcSize(EditorGUIUtility.TrTextContent("Settings")).x; - s_DeleteChangesetsButtonWidth = EditorStyles.toolbarButton.CalcSize(EditorGUIUtility.TrTextContent("Delete Empty Changesets")).x; - } - } - - void CreateStaticResources() - { - if (syncIcon == null) - { - syncIcon = EditorGUIUtility.LoadIcon("vcs_incoming"); - syncIcon.hideFlags = HideFlags.HideAndDontSave; - syncIcon.name = "SyncIcon"; - } - if (changeIcon == null) - { - changeIcon = EditorGUIUtility.LoadIcon("vcs_change"); - changeIcon.hideFlags = HideFlags.HideAndDontSave; - changeIcon.name = "ChangeIcon"; - } - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCWindowResolve.cs b/Editor/Mono/VersionControl/UI/VCWindowResolve.cs deleted file mode 100644 index 901c11cd75..0000000000 --- a/Editor/Mono/VersionControl/UI/VCWindowResolve.cs +++ /dev/null @@ -1,204 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEditorInternal.VersionControl; - -namespace UnityEditor.VersionControl -{ - // Window allowing you to review files who will be resolved. As this may be throwing changes away this - // window gives you the opportunty to see what will change and if required the user can apply or cancel. - internal class WindowResolve : EditorWindow - { - ListControl resolveList = new ListControl(); - AssetList assetList = new AssetList(); - bool cancelled = false; - - public void OnEnable() - { - position = new Rect(100, 100, 650, 330); - minSize = new Vector2(650, 330); - } - - public void OnDisable() - { - if (!cancelled) - WindowPending.UpdateAllWindows(); - } - - // Resolve all files within a change list - static public void Open(ChangeSet change) - { - Task task = Provider.ChangeSetStatus(change); - task.Wait(); - WindowResolve win = GetWindow(); - win.DoOpen(task.assetList); - } - - // Resolve a list of files - static public void Open(AssetList assets) - { - Task task = Provider.Status(assets); - task.Wait(); - WindowResolve win = GetWindow(); - win.DoOpen(task.assetList); - } - - static private WindowResolve GetWindow() - { - return EditorWindow.GetWindow(true, "Version Control Resolve"); - } - - void DoOpen(AssetList resolve) - { - bool includeFolders = true; - assetList = resolve.Filter(includeFolders, Asset.States.Conflicted); - RefreshList(); - } - - void RefreshList() - { - resolveList.Clear(); - - bool first = true; - foreach (Asset it in assetList) - { - ListItem newItem = resolveList.Add(null, it.prettyPath, it); - if (first) - { - resolveList.SelectedSet(newItem); - first = false; - } - else - { - resolveList.SelectedAdd(newItem); - } - } - - // Show a dummy entry if there is nothing to do - if (assetList.Count == 0) - { - ChangeSet change = new ChangeSet("no files to resolve"); - ListItem item = resolveList.Add(null, change.description, change); - item.Dummy = true; - } - - resolveList.Refresh(); - Repaint(); - } - - void OnGUI() - { - cancelled = false; - GUILayout.Label("Conflicting files to resolve", EditorStyles.boldLabel); - GUILayout.FlexibleSpace(); - - // I would use GUIUtility.GetLastRect() here after the box but that seems to have wierd side effects. - Rect r1 = new Rect(6, 40, position.width - 12, position.height - 112); // 82 - GUILayout.BeginArea(r1); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - GUILayout.EndArea(); - - bool repaint = resolveList.OnGUI(new Rect(r1.x + 2, r1.y + 2, r1.width - 4, r1.height - 4), true); - - GUILayout.FlexibleSpace(); - - GUILayout.BeginHorizontal(); - GUI.enabled = assetList.Count > 0; - - GUILayout.Label("Resolve selection by:"); - if (GUILayout.Button("using local version")) - { - AssetList selAssets = resolveList.SelectedAssets; - Provider.Resolve(selAssets, ResolveMethod.UseMine).Wait(); - AssetDatabase.Refresh(); - Close(); - } - - if (GUILayout.Button("using incoming version")) - { - AssetList selAssets = resolveList.SelectedAssets; - Provider.Resolve(selAssets, ResolveMethod.UseTheirs).Wait(); - AssetDatabase.Refresh(); - Close(); - } - - MergeMethod mergeMethod = MergeMethod.MergeNone; - if (GUILayout.Button("merging")) - { - mergeMethod = MergeMethod.MergeAll; - } - - if (mergeMethod != MergeMethod.MergeNone) - { - Task t = Provider.Merge(resolveList.SelectedAssets, mergeMethod); - t.Wait(); - - if (t.success) - { - t = Provider.Resolve(t.assetList, ResolveMethod.UseMerged); - t.Wait(); - if (t.success) - { - // Check that there are not more conflicts for the specified - // asset. This is possible in e.g. perforce where you handle - // one version conflict at a time. - t = Provider.Status(assetList); - t.Wait(); - - DoOpen(t.assetList); - - if (t.success && assetList.Count == 0) - Close(); - - // The view will be updated with the new conflicts - } - else - { - EditorUtility.DisplayDialog("Error resolving", "Error during resolve of files. Inspect log for details", "Close"); - AssetDatabase.Refresh(); - } - } - else - { - EditorUtility.DisplayDialog("Error merging", "Error during merge of files. Inspect log for details", "Close"); - AssetDatabase.Refresh(); - } - } - - GUILayout.FlexibleSpace(); - - GUILayout.EndHorizontal(); - GUILayout.Space(12); - - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - - GUI.enabled = true; - - if (GUILayout.Button("Cancel")) - { - cancelled = true; - Close(); - } - /* - GUI.enabled = assetList.Count > 0; - - - if (GUILayout.Button ("Resolve")) - { - Provider.Resolve (assetList, true).Wait (); - VCCache.Invalidate (assetList); - AssetDatabase.Refresh (); - Close (); - } - */ - GUILayout.EndHorizontal(); - GUILayout.Space(12); - //GUI.enabled = true; - if (repaint) - Repaint(); - } - } -} diff --git a/Editor/Mono/VersionControl/UI/VCWindowRevert.cs b/Editor/Mono/VersionControl/UI/VCWindowRevert.cs deleted file mode 100644 index de6cd73d53..0000000000 --- a/Editor/Mono/VersionControl/UI/VCWindowRevert.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEditorInternal.VersionControl; - -namespace UnityEditor.VersionControl -{ - // Window allowing you to review files who will be reverted. As this may be throwing changes away this - // window gives you the opportunty to see what will change and if required the user can apply or cancel. - internal class WindowRevert : EditorWindow - { - ListControl revertList = new ListControl(); - AssetList assetList = new AssetList(); - - public void OnEnable() - { - position = new Rect(100, 100, 700, 230); - minSize = new Vector2(700, 230); - - revertList.ReadOnly = true; - } - - // Revert all files within a change list - static public void Open(ChangeSet change) - { - Task task = Provider.ChangeSetStatus(change); - task.Wait(); - - GetWindow().DoOpen(task.assetList); - } - - // Revert a list of files - static public void Open(AssetList assets) - { - Task task = Provider.Status(assets); - task.Wait(); - - const bool includeFolders = true; - AssetList revert = task.assetList.Filter(includeFolders, - Asset.States.CheckedOutLocal, - Asset.States.DeletedLocal, - Asset.States.AddedLocal, - //Asset.States.Branch, - //Asset.States.Integrate, - Asset.States.Missing); - - GetWindow().DoOpen(revert); - } - - static private WindowRevert GetWindow() - { - return EditorWindow.GetWindow(true, "Version Control Revert"); - } - - void DoOpen(AssetList revert) - { - assetList = revert; - RefreshList(); - } - - void RefreshList() - { - revertList.Clear(); - - foreach (Asset it in assetList) - revertList.Add(null, it.prettyPath, it); - - // Show a dummy entry if there is nothing to do - if (assetList.Count == 0) - { - ChangeSet change = new ChangeSet("no files to revert"); - ListItem item = revertList.Add(null, change.description, change); - item.Dummy = true; - } - - revertList.Refresh(); - Repaint(); - } - - void OnGUI() - { - GUILayout.Label("Revert Files", EditorStyles.boldLabel); - GUILayout.FlexibleSpace(); - - // I would use GUIUtility.GetLastRect() here after the box but that seems to have wierd side effects. - Rect r1 = new Rect(6, 40, position.width - 12, position.height - 82); - GUILayout.BeginArea(r1); - GUILayout.Box("", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); - GUILayout.EndArea(); - revertList.OnGUI(new Rect(r1.x + 2, r1.y + 2, r1.width - 4, r1.height - 4), true); - - GUILayout.FlexibleSpace(); - GUILayout.BeginHorizontal(); - - GUILayout.FlexibleSpace(); - - if (GUILayout.Button("Cancel")) - Close(); - - if (assetList.Count > 0 && GUILayout.Button("Revert")) - { - string openScenes = ""; - foreach (Asset a in assetList) - { - Scene openScene = SceneManager.GetSceneByPath(a.path); - if ((openScene.IsValid()) && (openScene.isLoaded)) - { - openScenes += openScene.path + "\n"; - } - } - - if (openScenes.Length > 0) - { - bool continueRevert = EditorUtility.DisplayDialog("Revert open scene(s)?", - "You are about to revert your currently open scene(s):\n\n" + - openScenes + "\nContinuing will remove all unsaved changes.", - "Continue", "Cancel"); - if (!continueRevert) - { - Close(); - return; - } - } - - Provider.Revert(assetList, RevertMode.Normal).Wait(); - WindowPending.UpdateAllWindows(); - AssetDatabase.Refresh(); - Close(); - } - - GUILayout.EndHorizontal(); - GUILayout.Space(12); - } - } -} diff --git a/Editor/Mono/VersionControl/VCProvider.bindings.cs b/Editor/Mono/VersionControl/VCProvider.bindings.cs deleted file mode 100644 index 60a7b89191..0000000000 --- a/Editor/Mono/VersionControl/VCProvider.bindings.cs +++ /dev/null @@ -1,284 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Bindings; -using UnityEngine.Scripting; -using System.Runtime.InteropServices; - -namespace UnityEditor.VersionControl -{ - // This MUST be kept synchronized with the VCS_PROVIDER_UNSET_IDENTIFIER enum in VCProvider.cpp - enum VCSProviderIdentifier - { - UnsetIdentifier = -1 - } - - // Keep internal and undocumented until we expose more functionality - [NativeHeader("Editor/Src/VersionControl/VCProvider_bindings.h")] - public partial class Provider - { - [StaticAccessor("GetVCProvider()", StaticAccessorType.Dot)] - public static extern bool enabled - { - [NativeMethod("Enabled")] - get; - } - - [StaticAccessor("GetVCProvider()", StaticAccessorType.Dot)] - public static extern bool isActive - { - [NativeMethod("IsActive")] - get; - } - - [UsedByNativeCode] - [StructLayout(LayoutKind.Sequential)] - private struct Traits - { - public bool requiresNetwork; - public bool enablesCheckout; - public bool enablesVersioningFolders; - public bool enablesChangelists; - } - - private static extern Traits activeTraits - { - [FreeFunction("VersionControlBindings::VCProvider::GetActiveTraits")] - get; - } - - public static bool requiresNetwork - { - get { return activeTraits.requiresNetwork; } - } - - public static bool hasChangelistSupport - { - get { return activeTraits.enablesChangelists; } - } - - public static bool hasCheckoutSupport - { - get { return activeTraits.enablesCheckout; } - } - - public static bool isVersioningFolders - { - get { return activeTraits.enablesVersioningFolders; } - } - - [StaticAccessor("GetVCProvider()", StaticAccessorType.Dot)] - public static extern OnlineState onlineState - { - [NativeMethod("GetOnlineState")] - get; - } - - [StaticAccessor("GetVCProvider()", StaticAccessorType.Dot)] - public static extern string offlineReason - { - [NativeMethod("OfflineReason")] - get; - } - - public static extern Task activeTask - { - [FreeFunction("VersionControlBindings::VCProvider::GetActiveTask")] - get; - } - - [StaticAccessor("GetVCProvider()", StaticAccessorType.Dot)] - internal static extern Texture2D overlayAtlas - { - [NativeMethod("GetOverlayAtlas")] - get; - } - - [FreeFunction("VersionControlBindings::VCProvider::GetAtlasRectForState")] - internal static extern Rect GetAtlasRectForState(int state); - - [FreeFunction("VersionControlBindings::VCProvider::GetActivePlugin")] - public static extern Plugin GetActivePlugin(); - - [FreeFunction("VersionControlBindings::VCProvider::GetActiveConfigFields")] - public static extern ConfigField[] GetActiveConfigFields(); - - [StaticAccessor("GetVCProvider()", StaticAccessorType.Dot)] - internal static extern bool IsCustomCommandEnabled(string name); - - [StaticAccessor("GetVCProvider()", StaticAccessorType.Dot)] - internal static extern CustomCommand[] customCommands - { - [NativeMethod("GetMonoCustomCommands")] - get; - } - - [FreeFunction("VersionControlBindings::VCProvider::Internal_CacheStatus")] - private static extern Asset Internal_CacheStatus(string assetPath); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_Status")] - private static extern Task Internal_Status(Asset[] assets, bool recursively); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_StatusStrings")] - private static extern Task Internal_StatusStrings(string[] assetsProjectPaths, bool recursively); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_StatusAbsolutePath")] - private static extern Task Internal_StatusAbsolutePath(string assetPath); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_CheckoutIsValid")] - private static extern bool Internal_CheckoutIsValid(Asset[] assets, CheckoutMode mode); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_Checkout")] - private static extern Task Internal_Checkout(Asset[] assets, CheckoutMode mode); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_CheckoutStrings")] - private static extern Task Internal_CheckoutStrings(string[] assets, CheckoutMode mode); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_PromptAndCheckoutIfNeeded")] - private static extern bool Internal_PromptAndCheckoutIfNeeded(string[] assets, string promptIfCheckoutIsNeeded); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_Delete")] - private static extern Task Internal_Delete(Asset[] assets); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_DeleteAtProjectPath")] - private static extern Task Internal_DeleteAtProjectPath([NotNull] string assetProjectPath); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_MoveAsStrings")] - private static extern Task Internal_MoveAsStrings([NotNull] string from, [NotNull] string to); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_AddIsValid")] - private static extern bool Internal_AddIsValid(Asset[] assets); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_Add")] - private static extern Task Internal_Add(Asset[] assets, bool recursive); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_DeleteChangeSetsIsValid")] - private static extern bool Internal_DeleteChangeSetsIsValid(ChangeSet[] changesets); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_DeleteChangeSets")] - private static extern Task Internal_DeleteChangeSets(ChangeSet[] changesets); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_RevertChangeSets")] - private static extern Task Internal_RevertChangeSets(ChangeSet[] changesets, RevertMode mode); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_SubmitIsValid")] - private static extern bool Internal_SubmitIsValid(ChangeSet changeset, Asset[] assets); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_Submit")] - private static extern Task Internal_Submit(ChangeSet changeset, Asset[] assets, string description, bool saveOnly); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_DiffIsValid")] - private static extern bool Internal_DiffIsValid(Asset[] assets); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_DiffHead")] - private static extern Task Internal_DiffHead(Asset[] assets, bool includingMetaFiles); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_ResolveIsValid")] - private static extern bool Internal_ResolveIsValid(Asset[] assets); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_Resolve")] - private static extern Task Internal_Resolve(Asset[] assets, ResolveMethod resolveMethod); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_Merge")] - private static extern Task Internal_Merge(Asset[] assets, MergeMethod mergeMethod); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_LockIsValid")] - private static extern bool Internal_LockIsValid(Asset[] assets); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_UnlockIsValid")] - private static extern bool Internal_UnlockIsValid(Asset[] assets); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_Lock")] - private static extern Task Internal_Lock(Asset[] assets, bool locked); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_RevertIsValid")] - private static extern bool Internal_RevertIsValid(Asset[] assets, RevertMode revertMode); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_Revert")] - private static extern Task Internal_Revert(Asset[] assets, RevertMode revertMode); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_GetLatestIsValid")] - private static extern bool Internal_GetLatestIsValid(Asset[] assets); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_GetLatest")] - private static extern Task Internal_GetLatest(Asset[] assets); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_SetFileMode")] - private static extern Task Internal_SetFileMode(Asset[] assets, FileMode fileMode); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_SetFileModeStrings")] - private static extern Task Internal_SetFileModeStrings(string[] assets, FileMode fileMode); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_ChangeSetDescription")] - private static extern Task Internal_ChangeSetDescription([NotNull] ChangeSet changeset); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_ChangeSetStatus")] - private static extern Task Internal_ChangeSetStatus([NotNull] ChangeSet changeset); - - [FreeFunction("VersionControlBindings::VCProvider::ChangeSets")] - public static extern Task ChangeSets(); - - [NativeThrows] - [FreeFunction("VersionControlBindings::VCProvider::Internal_ChangeSetMove")] - private static extern Task Internal_ChangeSetMove(Asset[] assets, [NotNull] ChangeSet target); - - [FreeFunction("VersionControlBindings::VCProvider::Incoming")] - public static extern Task Incoming(); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_IncomingChangeSetAssets")] - private static extern Task Internal_IncomingChangeSetAssets([NotNull] ChangeSet changeset); - - [FreeFunction("VersionControlBindings::VCProvider::UpdateSettings")] - public static extern Task UpdateSettings(); - - [FreeFunction("VersionControlBindings::VCProvider::GetAssetByPath")] - public static extern Asset GetAssetByPath(string unityPath); - - [FreeFunction("VersionControlBindings::VCProvider::GetAssetByGUID")] - public static extern Asset GetAssetByGUID(string guid); - - [FreeFunction("VersionControlBindings::VCProvider::Internal_GetAssetArrayFromSelection")] - private static extern Asset[] Internal_GetAssetArrayFromSelection(); - - [FreeFunction("VersionControlBindings::VCProvider::IsOpenForEdit")] - public static extern bool IsOpenForEdit([NotNull] Asset asset); - - [StaticAccessor("GetVCProvider()", StaticAccessorType.Dot)] - internal static extern int GenerateID(); - - [StaticAccessor("GetVCCache()", StaticAccessorType.Dot)] - [NativeMethod("Clear")] - public static extern void ClearCache(); - - [StaticAccessor("GetVCCache()", StaticAccessorType.Dot)] - [NativeMethod("Invalidate")] - internal static extern void InvalidateCache(); - - } -} diff --git a/Editor/Mono/View.cs b/Editor/Mono/View.cs deleted file mode 100644 index 0e0ca1d58b..0000000000 --- a/Editor/Mono/View.cs +++ /dev/null @@ -1,249 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; -using UnityEngine.Scripting; -using UnityEditor; -using System.Collections; -using System.Linq; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using IntPtr = System.IntPtr; -using System; - -namespace UnityEditor -{ - [StructLayout(LayoutKind.Sequential)] - [UsedByNativeCode] - internal partial class View : ScriptableObject - { - internal virtual void Reflow() - { - foreach (View c in children) - c.Reflow(); - } - - internal string DebugHierarchy(int level) - { - string prefix = "", s = ""; - for (int i = 0; i < level; i++) - { - prefix = prefix + " "; - } - s = s + prefix + this.ToString() + " p:" + position; - if (children.Length > 0) - { - s += " {\n"; - foreach (View child in children) - { - s += child.DebugHierarchy(level + 2); - } - s += prefix + " }\n"; - } - else - s += "\n"; - return s; - } - - // Can be used by concrete subclasses to store C++ objects - [SerializeField] - MonoReloadableIntPtr m_ViewPtr; - [SerializeField] - View[] m_Children = new View[0]; - [System.NonSerialized] - View m_Parent; - [System.NonSerialized] - ContainerWindow m_Window; - - // Workaround for nonserialized stuff above - internal virtual void Initialize(ContainerWindow win) - { - SetWindow(win); - foreach (View i in m_Children) - { - i.m_Parent = this; - i.Initialize(win); - } - } - - [SerializeField] - Rect m_Position = new Rect(0, 0, 100, 100); - - [SerializeField] - internal Vector2 m_MinSize; - [SerializeField] - internal Vector2 m_MaxSize; - - public Vector2 minSize { get { return m_MinSize; } } - public Vector2 maxSize { get { return m_MaxSize; } } - - internal void SetMinMaxSizes(Vector2 min, Vector2 max) - { - if (minSize == min && maxSize == max) - { - return; - } - m_MinSize = min; - m_MaxSize = max; - if (m_Parent) - m_Parent.ChildrenMinMaxChanged(); - if (window && window.rootView == this) - window.SetMinMaxSizes(min, max); - } - - // Notification so other views can respond to this. - protected virtual void ChildrenMinMaxChanged() {} - - // Get all children of this view, using bottom-first recursion - public View[] allChildren - { - get - { - ArrayList arr = new ArrayList(); - foreach (View i in m_Children) - { - arr.AddRange(i.allChildren); - } - arr.Add(this); - return (View[])arr.ToArray(typeof(View)); - } - } - - private void __internalAwake() - { - hideFlags = HideFlags.DontSave; - } - - // position in the parent's space. - public Rect position - { - get { return m_Position; } - set { SetPosition(value); } - } - - // Override to resize subviews - protected virtual void SetPosition(Rect newPos) - { - m_Position = newPos; - } - - // Only set the position. - internal void SetPositionOnly(Rect newPos) - { - m_Position = newPos; - } - - // position in the window - public Rect windowPosition - { - get - { - if (m_Parent == null) - return position; - - Rect p = parent.windowPosition; - return new Rect(p.x + position.x, p.y + position.y, position.width, position.height); - } - } - - // absolute screen position - public Rect screenPosition - { - get - { - Rect r = windowPosition; - if (window != null) - { - Vector2 p = window.WindowToScreenPoint(Vector2.zero); - r.x += p.x; r.y += p.y; - } - return r; - } - } - - // Which window we're inside. don't set this directly, but change use AddChild, RemoveChild instead. - public ContainerWindow window { get { return m_Window; } } - // The parent view. - public View parent { get { return m_Parent; } } - - // please don't modify this array directly. use AddChild or set the child's parent view - public View[] children { get { return m_Children; } } - public int IndexOfChild(View child) - { - int i = 0; - foreach (View c in m_Children) - { - if (c == child) - return i; - i++; - } - return -1; - } - - protected virtual void OnDestroy() - { - foreach (View v in m_Children) - { - UnityEngine.Object.DestroyImmediate(v, true); - } - } - - // Add/remove child views - public void AddChild(View child) - {AddChild(child, m_Children.Length); } - public virtual void AddChild(View child, int idx) - { - System.Array.Resize(ref m_Children, m_Children.Length + 1); - if (idx != m_Children.Length - 1) - System.Array.Copy(m_Children, idx, m_Children, idx + 1, m_Children.Length - idx - 1); - - m_Children[idx] = child; - - if (child.m_Parent) - child.m_Parent.RemoveChild(child); - child.m_Parent = this; - child.SetWindowRecurse(window); - ChildrenMinMaxChanged(); - } - - public virtual void RemoveChild(View child) - { - int idx = System.Array.IndexOf(m_Children, child); - if (idx == -1) - Debug.LogError("Unable to remove child - it's not IN the view"); - else - RemoveChild(idx); - } - - public virtual void RemoveChild(int idx) - { - View child = m_Children[idx]; - child.m_Parent = null; - child.SetWindowRecurse(null); - System.Array.Copy(m_Children, idx + 1, m_Children, idx, m_Children.Length - idx - 1); - System.Array.Resize(ref m_Children, m_Children.Length - 1); - ChildrenMinMaxChanged(); - } - - protected virtual void SetWindow(ContainerWindow win) - { - m_Window = win; - } - - internal void SetWindowRecurse(ContainerWindow win) - { - SetWindow(win); - foreach (View i in m_Children) - { - i.SetWindowRecurse(win); - } - } - - virtual protected bool OnFocus() - { - return true; - } - } -} //namespace diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs deleted file mode 100644 index 251006e60d..0000000000 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizationSettings.cs +++ /dev/null @@ -1,277 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security; -using System.Security.Cryptography; -using System.Xml; -using System.Text; -using System.Text.RegularExpressions; -namespace UnityEditor.VisualStudioIntegration -{ - interface ISolutionSynchronizationSettings - { - int VisualStudioVersion { get; } - string SolutionTemplate { get; } - string SolutionProjectEntryTemplate { get; } - string SolutionProjectConfigurationTemplate { get; } - string EditorAssemblyPath { get; } - string EngineAssemblyPath { get; } - string MonoLibFolder { get; } - string[] Defines { get; } - string GetProjectHeaderTemplate(ScriptingLanguage language); - string GetProjectFooterTemplate(ScriptingLanguage language); - } - - internal class DefaultSolutionSynchronizationSettings : ISolutionSynchronizationSettings - { - public virtual int VisualStudioVersion - { - get { return 9; } - } - - public virtual string SolutionTemplate - { - get - { - return string.Join("\r\n", new[] { - @"", - @"Microsoft Visual Studio Solution File, Format Version {0}", - @"# Visual Studio {1}", - @"{2}", - @"Global", - @" GlobalSection(SolutionConfigurationPlatforms) = preSolution", - @" Debug|Any CPU = Debug|Any CPU", - @" Release|Any CPU = Release|Any CPU", - @" EndGlobalSection", - @" GlobalSection(ProjectConfigurationPlatforms) = postSolution", - @"{3}", - @" EndGlobalSection", - @" GlobalSection(SolutionProperties) = preSolution", - @" HideSolutionNode = FALSE", - @" EndGlobalSection", - @"{4}", - @"EndGlobal", - @"" - }).Replace(" ", "\t"); - } - } - - public virtual string SolutionProjectEntryTemplate - { - get - { - return string.Join("\r\n", new[] { - @"Project(""{{{0}}}"") = ""{1}"", ""{2}"", ""{{{3}}}""", - @"EndProject" - }).Replace(" ", "\t"); - } - } - - public virtual string SolutionProjectConfigurationTemplate - { - get - { - return string.Join("\r\n", new[] { - @" {{{0}}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", - @" {{{0}}}.Debug|Any CPU.Build.0 = Debug|Any CPU", - @" {{{0}}}.Release|Any CPU.ActiveCfg = Release|Any CPU", - @" {{{0}}}.Release|Any CPU.Build.0 = Release|Any CPU" - }).Replace(" ", "\t"); - } - } - - public virtual string GetProjectHeaderTemplate(ScriptingLanguage language) - { - var header = new[] { - @"", - @"", - @" ", - @" {10}", - @" ", - @" ", - @" Debug", - @" AnyCPU", - @" {1}", - @" 2.0", - @" {8}", - @" {{{2}}}", - @" Library", - @" Properties", - @" {7}", - @" {9}", - @" 512", - @" {11}", - @" ", - @" ", - @" true", - @" full", - @" false", - @" Temp\bin\Debug\", - @" {5}", - @" prompt", - @" 4", - @" 0169", - @" {12}", - @" ", - @" ", - @" pdbonly", - @" true", - @" Temp\bin\Release\", - @" prompt", - @" 4", - @" 0169", - @" {12}", - @" ", - }; - - var forceExplicitReferences = new string[] { - @" ", - @" true", - @" true", - @" false", - @" ", - }; - - var itemGroupStart = new[] { - @" ", - }; - - var systemReferences = new string[] { - @" ", - @" ", - @" ", - @" ", - @" ", - }; - - var footer = new string[] { - @" ", - @" {3}", - @" ", - @" ", - @" {4}", - @" ", - @" ", - @" ", - @"" - }; - - string[] text; - - if (language == ScriptingLanguage.CSharp) - text = header.Concat(forceExplicitReferences).Concat(itemGroupStart).Concat(footer).ToArray(); - else - text = header.Concat(itemGroupStart).Concat(systemReferences).Concat(footer).ToArray(); - - return string.Join("\r\n", text); - } - - public virtual string GetProjectFooterTemplate(ScriptingLanguage language) - { - return string.Join("\r\n", new[] { - @" ", - @" ", - @" ", - @" {0}", - @"", - @"" - }); - } - - public virtual string EditorAssemblyPath - { - get { return "/Managed/UnityEditor.dll"; } - } - - public virtual string EngineAssemblyPath - { - get { return "/Managed/UnityEngine.dll"; } - } - - public virtual string MonoLibFolder - { - get { return FrameworksPath() + "/Mono/lib/mono/unity/"; } - } - - public virtual string[] Defines - { - get { return new string[0]; } - } - - protected virtual string FrameworksPath() - { - return string.Empty; - } - } - - static class VSCodeTemplates - { - public static string SettingsJson = @"{ - ""files.exclude"": - { - ""**/.DS_Store"":true, - ""**/.git"":true, - ""**/.gitignore"":true, - ""**/.gitmodules"":true, - ""**/*.booproj"":true, - ""**/*.pidb"":true, - ""**/*.suo"":true, - ""**/*.user"":true, - ""**/*.userprefs"":true, - ""**/*.unityproj"":true, - ""**/*.dll"":true, - ""**/*.exe"":true, - ""**/*.pdf"":true, - ""**/*.mid"":true, - ""**/*.midi"":true, - ""**/*.wav"":true, - ""**/*.gif"":true, - ""**/*.ico"":true, - ""**/*.jpg"":true, - ""**/*.jpeg"":true, - ""**/*.png"":true, - ""**/*.psd"":true, - ""**/*.tga"":true, - ""**/*.tif"":true, - ""**/*.tiff"":true, - ""**/*.3ds"":true, - ""**/*.3DS"":true, - ""**/*.fbx"":true, - ""**/*.FBX"":true, - ""**/*.lxo"":true, - ""**/*.LXO"":true, - ""**/*.ma"":true, - ""**/*.MA"":true, - ""**/*.obj"":true, - ""**/*.OBJ"":true, - ""**/*.asset"":true, - ""**/*.cubemap"":true, - ""**/*.flare"":true, - ""**/*.mat"":true, - ""**/*.meta"":true, - ""**/*.prefab"":true, - ""**/*.unity"":true, - ""build/"":true, - ""Build/"":true, - ""Library/"":true, - ""library/"":true, - ""obj/"":true, - ""Obj/"":true, - ""ProjectSettings/"":true, - ""temp/"":true, - ""Temp/"":true - } -}"; - } -} diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs deleted file mode 100644 index d78bd30bc3..0000000000 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ /dev/null @@ -1,837 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security; -using System.Security.Cryptography; -using System.Xml; -using System.Text; -using System.Text.RegularExpressions; - -using UnityEditor.Scripting; -using UnityEditor.Scripting.ScriptCompilation; -using UnityEditor.Utils; -using UnityEditorInternal; -using UnityEditor.Scripting.Compilers; - -using Mono.Cecil; -using UnityEditor.Compilation; - -namespace UnityEditor.VisualStudioIntegration -{ - enum ScriptingLanguage - { - None, - Boo, - CSharp, - UnityScript, - } - - class SolutionSynchronizer - { - enum Mode - { - UnityScriptAsUnityProj, - UnityScriptAsPrecompiledAssembly - } - - public static readonly ISolutionSynchronizationSettings DefaultSynchronizationSettings = - new DefaultSolutionSynchronizationSettings(); - - static readonly string WindowsNewline = "\r\n"; - - /// - /// Map source extensions to ScriptingLanguages - /// - static internal readonly Dictionary BuiltinSupportedExtensions = new Dictionary - { - {"cs", ScriptingLanguage.CSharp}, - {"js", ScriptingLanguage.UnityScript}, - {"boo", ScriptingLanguage.Boo}, - {"uxml", ScriptingLanguage.None}, - {"uss", ScriptingLanguage.None}, - {"shader", ScriptingLanguage.None}, - {"compute", ScriptingLanguage.None}, - {"cginc", ScriptingLanguage.None}, - {"hlsl", ScriptingLanguage.None}, - {"glslinc", ScriptingLanguage.None}, - }; - - string[] ProjectSupportedExtensions = new string[0]; - - /// - /// Map ScriptingLanguages to project extensions - /// - static readonly Dictionary ProjectExtensions = new Dictionary - { - { ScriptingLanguage.Boo, ".booproj" }, - { ScriptingLanguage.CSharp, ".csproj" }, - { ScriptingLanguage.UnityScript, ".unityproj" }, - { ScriptingLanguage.None, ".csproj" }, - }; - - static readonly Regex _MonoDevelopPropertyHeader = new Regex(@"^\s*GlobalSection\(MonoDevelopProperties.*\)"); - public static readonly string MSBuildNamespaceUri = "http://schemas.microsoft.com/developer/msbuild/2003"; - - private readonly string _projectDirectory; - private readonly ISolutionSynchronizationSettings _settings; - private readonly string _projectName; - - - private static readonly string DefaultMonoDevelopSolutionProperties = string.Join("\r\n", new[] { - " GlobalSection(MonoDevelopProperties) = preSolution", - " StartupItem = Assembly-CSharp.csproj", - " EndGlobalSection", - }).Replace(" ", "\t"); - - public SolutionSynchronizer(string projectDirectory, ISolutionSynchronizationSettings settings) - { - _projectDirectory = projectDirectory; - _settings = settings; - _projectName = Path.GetFileName(_projectDirectory); - } - - public SolutionSynchronizer(string projectDirectory) : this(projectDirectory, DefaultSynchronizationSettings) - { - } - - private void SetupProjectSupportedExtensions() - { - ProjectSupportedExtensions = EditorSettings.projectGenerationUserExtensions; - } - - public bool ShouldFileBePartOfSolution(string file) - { - string extension = Path.GetExtension(file); - - // Exclude files coming from packages except if they are internalized. - if (IsNonInternalizedPackagePath(file)) - { - return false; - } - - // Dll's are not scripts but still need to be included.. - if (extension == ".dll") - return true; - - if (file.ToLower().EndsWith(".asmdef")) - return true; - - return IsSupportedExtension(extension); - } - - private bool IsSupportedExtension(string extension) - { - extension = extension.TrimStart('.'); - if (BuiltinSupportedExtensions.ContainsKey(extension)) - return true; - if (ProjectSupportedExtensions.Contains(extension)) - return true; - return false; - } - - private static ScriptingLanguage ScriptingLanguageFor(MonoIsland island) - { - return ScriptingLanguageFor(island.GetExtensionOfSourceFiles()); - } - - private static ScriptingLanguage ScriptingLanguageFor(string extension) - { - ScriptingLanguage result; - if (BuiltinSupportedExtensions.TryGetValue(extension.TrimStart('.'), out result)) - return result; - - return ScriptingLanguage.None; - } - - public bool ProjectExists(MonoIsland island) - { - return File.Exists(ProjectFile(island)); - } - - public bool SolutionExists() - { - return File.Exists(SolutionFile()); - } - - private static void DumpIsland(MonoIsland island) - { - Console.WriteLine("{0} ({1})", island._output, island._api_compatibility_level); - Console.WriteLine("Files: "); - Console.WriteLine(string.Join("\n", island._files)); - Console.WriteLine("References: "); - Console.WriteLine(string.Join("\n", island._references)); - Console.WriteLine(""); - } - - /// - /// Syncs the scripting solution if any affected files are relevant. - /// - /// - /// Whether the solution was synced. - /// - /// - /// A set of files whose status has changed - /// - public bool SyncIfNeeded(IEnumerable affectedFiles) - { - SetupProjectSupportedExtensions(); - - // Don't sync if we haven't synced before - if (SolutionExists() && affectedFiles.Any(ShouldFileBePartOfSolution)) - { - Sync(); - return true; - } - - return false; - } - - public void Sync() - { - SetupProjectSupportedExtensions(); - - bool externalCodeAlreadyGeneratedProjects = AssetPostprocessingInternal.OnPreGeneratingCSProjectFiles(); - - if (!externalCodeAlreadyGeneratedProjects) - { - var scriptEditor = ScriptEditorUtility.GetScriptEditorFromPreferences(); - - // Do not generate .sln and .csproj for unsupported code editors. - if (scriptEditor == ScriptEditorUtility.ScriptEditor.SystemDefault || scriptEditor == ScriptEditorUtility.ScriptEditor.Other) - return; - - GenerateAndWriteSolutionAndProjects(scriptEditor); - } - - AssetPostprocessingInternal.CallOnGeneratedCSProjectFiles(); - } - - internal void GenerateAndWriteSolutionAndProjects(ScriptEditorUtility.ScriptEditor scriptEditor) - { - // Only synchronize islands that have associated source files and ones that we actually want in the project. - // This also filters out DLLs coming from .asmdef files in packages. - IEnumerable islands = EditorCompilationInterface.GetAllMonoIslands(). - Where(i => 0 < i._files.Length && i._files.Any(f => ShouldFileBePartOfSolution(f))); - - var allAssetProjectParts = GenerateAllAssetProjectParts(); - - var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ReponseFilename); - - var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile(Path.Combine(_projectDirectory, responseFilePath)); - - if (responseFileData.Errors.Length > 0) - { - foreach (var error in responseFileData.Errors) - UnityEngine.Debug.LogErrorFormat("{0} Parse Error : {1}", responseFilePath, error); - } - - SyncSolution(islands); - var allProjectIslands = RelevantIslandsForMode(islands, ModeForCurrentExternalEditor()).ToList(); - foreach (MonoIsland island in allProjectIslands) - SyncProject(island, allAssetProjectParts, responseFileData, allProjectIslands); - - if (scriptEditor == ScriptEditorUtility.ScriptEditor.VisualStudioCode) - WriteVSCodeSettingsFiles(); - } - - Dictionary GenerateAllAssetProjectParts() - { - Dictionary stringBuilders = new Dictionary(); - - foreach (string asset in AssetDatabase.GetAllAssetPaths()) - { - // Exclude files coming from packages except if they are internalized. - if (IsNonInternalizedPackagePath(asset)) - { - continue; - } - - string extension = Path.GetExtension(asset); - if (IsSupportedExtension(extension) && ScriptingLanguage.None == ScriptingLanguageFor(extension)) - { - // Find assembly the asset belongs to by adding script extension and using compilation pipeline. - var assemblyName = CompilationPipeline.GetAssemblyNameFromScriptPath(asset + ".cs"); - assemblyName = assemblyName ?? CompilationPipeline.GetAssemblyNameFromScriptPath(asset + ".js"); - assemblyName = assemblyName ?? CompilationPipeline.GetAssemblyNameFromScriptPath(asset + ".boo"); - - assemblyName = Path.GetFileNameWithoutExtension(assemblyName); - - StringBuilder projectBuilder = null; - - if (!stringBuilders.TryGetValue(assemblyName, out projectBuilder)) - { - projectBuilder = new StringBuilder(); - stringBuilders[assemblyName] = projectBuilder; - } - - projectBuilder.AppendFormat(" {1}", EscapedRelativePathFor(asset), WindowsNewline); - } - } - - var result = new Dictionary(); - - foreach (var entry in stringBuilders) - result[entry.Key] = entry.Value.ToString(); - - return result; - } - - bool IsNonInternalizedPackagePath(string file) - { - if (AssetDatabase.IsPackagedAssetPath(file)) - { - //@TODO: After 2018.1 this should be done using AssetDatabase.GetAssetFolderInfo - var absolutePath = Path.GetFullPath(file).ConvertSeparatorsToUnity(); - return !absolutePath.StartsWith(_projectDirectory.ConvertSeparatorsToUnity()); - } - return false; - } - - - void SyncProject(MonoIsland island, - Dictionary allAssetsProjectParts, - ScriptCompilerBase.ResponseFileData responseFileData, - List allProjectIslands) - { - SyncProjectFileIfNotChanged(ProjectFile(island), ProjectText(island, ModeForCurrentExternalEditor(), allAssetsProjectParts, responseFileData, allProjectIslands)); - } - - static void SyncProjectFileIfNotChanged(string path, string newContents) - { - if (Path.GetExtension(path) == ".csproj") - { - newContents = AssetPostprocessingInternal.CallOnGeneratedCSProject(path, newContents); - } - - SyncFileIfNotChanged(path, newContents); - } - - static void SyncSolutionFileIfNotChanged(string path, string newContents) - { - newContents = AssetPostprocessingInternal.CallOnGeneratedSlnSolution(path, newContents); - - SyncFileIfNotChanged(path, newContents); - } - - private static void SyncFileIfNotChanged(string filename, string newContents) - { - if (File.Exists(filename) && - newContents == File.ReadAllText(filename)) - { - return; - } - File.WriteAllText(filename, newContents, Encoding.UTF8); - } - - void WriteVSCodeSettingsFiles() - { - string vsCodeDirectory = Path.Combine(_projectDirectory, ".vscode"); - - if (!Directory.Exists(vsCodeDirectory)) - Directory.CreateDirectory(vsCodeDirectory); - - string vsCodeSettingsJson = Path.Combine(vsCodeDirectory, "settings.json"); - - if (!File.Exists(vsCodeSettingsJson)) - File.WriteAllText(vsCodeSettingsJson, VSCodeTemplates.SettingsJson); - } - - public static readonly Regex scriptReferenceExpression = new Regex( - @"^Library.ScriptAssemblies.(?(?.*)\.dll$)", - RegexOptions.Compiled | RegexOptions.IgnoreCase); - - static bool IsAdditionalInternalAssemblyReference(bool isBuildingEditorProject, string reference) - { - if (isBuildingEditorProject) - return Modules.ModuleUtils.GetAdditionalReferencesForEditorCsharpProject().Contains(reference); - return false; - } - - string ProjectText(MonoIsland island, - Mode mode, - Dictionary allAssetsProjectParts, - ScriptCompilerBase.ResponseFileData responseFileData, - List allProjectIslands) - { - var projectBuilder = new StringBuilder(ProjectHeader(island, responseFileData)); - var references = new List(); - var projectReferences = new List(); - Match match; - bool isBuildingEditorProject = island._output.EndsWith("-Editor.dll"); - - foreach (string file in island._files) - { - if (!ShouldFileBePartOfSolution(file)) - continue; - - var extension = Path.GetExtension(file).ToLower(); - var fullFile = EscapedRelativePathFor(file); - if (".dll" != extension) - { - var tagName = "Compile"; - projectBuilder.AppendFormat(" <{0} Include=\"{1}\" />{2}", tagName, fullFile, WindowsNewline); - } - else - { - references.Add(fullFile); - } - } - - string additionalAssetsForProject; - var assemblyName = Path.GetFileNameWithoutExtension(island._output); - - // Append additional non-script files that should be included in project generation. - if (allAssetsProjectParts.TryGetValue(assemblyName, out additionalAssetsForProject)) - projectBuilder.Append(additionalAssetsForProject); - - var allAdditionalReferenceFilenames = new List(); - - foreach (string reference in references.Union(island._references).Union(responseFileData.References.Select(r => r.Assembly))) - { - if (reference.EndsWith("/UnityEditor.dll") || reference.EndsWith("/UnityEngine.dll") || reference.EndsWith("\\UnityEditor.dll") || reference.EndsWith("\\UnityEngine.dll")) - continue; - - match = scriptReferenceExpression.Match(reference); - if (match.Success) - { - var language = ScriptCompilers.GetLanguageFromExtension(island.GetExtensionOfSourceFiles()); - var targetLanguage = (ScriptingLanguage)Enum.Parse(typeof(ScriptingLanguage), language.GetLanguageName(), true); - if (mode == Mode.UnityScriptAsUnityProj || ScriptingLanguage.CSharp == targetLanguage) - { - // Add a reference to a project except if it's a reference to a script assembly - // that we are not generating a project for. This will be the case for assemblies - // coming from .assembly.json files in non-internalized packages. - var dllName = match.Groups["dllname"].Value; - if (allProjectIslands.Any(i => Path.GetFileName(i._output) == dllName)) - { - projectReferences.Add(match); - continue; - } - } - } - - string fullReference = Path.IsPathRooted(reference) ? reference : Path.Combine(_projectDirectory, reference); - if (!AssemblyHelper.IsManagedAssembly(fullReference)) - continue; - if (AssemblyHelper.IsInternalAssembly(fullReference)) - { - if (!IsAdditionalInternalAssemblyReference(isBuildingEditorProject, fullReference)) - continue; - var referenceName = Path.GetFileName(fullReference); - if (allAdditionalReferenceFilenames.Contains(referenceName)) - continue; - allAdditionalReferenceFilenames.Add(referenceName); - } - - //replace \ with / and \\ with / - fullReference = fullReference.Replace("\\", "/"); - fullReference = fullReference.Replace("\\\\", "/"); - projectBuilder.AppendFormat(" {1}", Path.GetFileNameWithoutExtension(fullReference), WindowsNewline); - projectBuilder.AppendFormat(" {0}{1}", fullReference, WindowsNewline); - projectBuilder.AppendFormat(" {0}", WindowsNewline); - } - - if (0 < projectReferences.Count) - { - string referencedProject; - projectBuilder.AppendLine(" "); - projectBuilder.AppendLine(" "); - foreach (Match reference in projectReferences) - { - var targetAssembly = EditorCompilationInterface.Instance.GetTargetAssemblyDetails(reference.Groups["dllname"].Value); - ScriptingLanguage targetLanguage = ScriptingLanguage.None; - if (targetAssembly != null) - targetLanguage = (ScriptingLanguage)Enum.Parse(typeof(ScriptingLanguage), targetAssembly.Language.GetLanguageName(), true); - referencedProject = reference.Groups["project"].Value; - projectBuilder.AppendFormat(" {2}", referencedProject, - GetProjectExtension(targetLanguage), WindowsNewline); - projectBuilder.AppendFormat(" {{{0}}}", ProjectGuid(Path.Combine("Temp", reference.Groups["project"].Value + ".dll")), WindowsNewline); - projectBuilder.AppendFormat(" {0}", referencedProject, WindowsNewline); - projectBuilder.AppendLine(" "); - } - } - - projectBuilder.Append(ProjectFooter(island)); - return projectBuilder.ToString(); - } - - public string ProjectFile(MonoIsland island) - { - ScriptingLanguage language = ScriptingLanguageFor(island); - return Path.Combine(_projectDirectory, string.Format("{0}{1}", Path.GetFileNameWithoutExtension(island._output), ProjectExtensions[language])); - } - - internal string SolutionFile() - { - return Path.Combine(_projectDirectory, string.Format("{0}.sln", _projectName)); - } - - private string ProjectHeader(MonoIsland island, - ScriptCompilerBase.ResponseFileData responseFileData) - { - string targetframeworkversion = "v3.5"; - string targetLanguageVersion = "4"; - string toolsversion = "4.0"; - string productversion = "10.0.20506"; - string baseDirectory = "."; - ScriptingLanguage language = ScriptingLanguageFor(island); - - if (PlayerSettingsEditor.IsLatestApiCompatibility(island._api_compatibility_level)) - { - targetframeworkversion = "v4.6"; - targetLanguageVersion = "6"; - } - else if (ScriptEditorUtility.GetScriptEditorFromPreferences() == ScriptEditorUtility.ScriptEditor.Rider) - { - targetframeworkversion = "v4.5"; - } - else if (_settings.VisualStudioVersion == 9) - { - toolsversion = "3.5"; - productversion = "9.0.21022"; - } - - var arguments = new object[] - { - toolsversion, productversion, ProjectGuid(island._output), - _settings.EngineAssemblyPath, - _settings.EditorAssemblyPath, - string.Join(";", new[] { "DEBUG", "TRACE"}.Concat(_settings.Defines).Concat(island._defines).Concat(responseFileData.Defines).Distinct().ToArray()), - MSBuildNamespaceUri, - Path.GetFileNameWithoutExtension(island._output), - EditorSettings.projectGenerationRootNamespace, - targetframeworkversion, - targetLanguageVersion, - baseDirectory, - island._allowUnsafeCode | responseFileData.Unsafe - }; - - try - { - return string.Format(_settings.GetProjectHeaderTemplate(language), arguments); - } - catch (Exception) - { - throw new System.NotSupportedException("Failed creating c# project because the c# project header did not have the correct amount of arguments, which is " + arguments.Length); - } - } - - private void SyncSolution(IEnumerable islands) - { - SyncSolutionFileIfNotChanged(SolutionFile(), SolutionText(islands, ModeForCurrentExternalEditor())); - } - - private static Mode ModeForCurrentExternalEditor() - { - var scriptEditor = ScriptEditorUtility.GetScriptEditorFromPreferences(); - - if (scriptEditor == ScriptEditorUtility.ScriptEditor.VisualStudio || - scriptEditor == ScriptEditorUtility.ScriptEditor.VisualStudioExpress || - scriptEditor == ScriptEditorUtility.ScriptEditor.VisualStudioCode) - return Mode.UnityScriptAsPrecompiledAssembly; - - return EditorPrefs.GetBool("kExternalEditorSupportsUnityProj", false) ? Mode.UnityScriptAsUnityProj : Mode.UnityScriptAsPrecompiledAssembly; - } - - private string SolutionText(IEnumerable islands, Mode mode) - { - var fileversion = "11.00"; - var vsversion = "2010"; - if (_settings.VisualStudioVersion == 9) - { - fileversion = "10.00"; - vsversion = "2008"; - } - var relevantIslands = RelevantIslandsForMode(islands, mode); - string projectEntries = GetProjectEntries(relevantIslands); - string projectConfigurations = string.Join(WindowsNewline, relevantIslands.Select(i => GetProjectActiveConfigurations(ProjectGuid(i._output))).ToArray()); - return string.Format(_settings.SolutionTemplate, fileversion, vsversion, projectEntries, projectConfigurations, ReadExistingMonoDevelopSolutionProperties()); - } - - private static IEnumerable RelevantIslandsForMode(IEnumerable islands, Mode mode) - { - IEnumerable relevantIslands = islands.Where(i => (mode == Mode.UnityScriptAsUnityProj || ScriptingLanguage.CSharp == ScriptingLanguageFor(i))); - return relevantIslands; - } - - /// - /// Get a Project("{guid}") = "MyProject", "MyProject.unityproj", "{projectguid}" - /// entry for each relevant language - /// - private string GetProjectEntries(IEnumerable islands) - { - var projectEntries = islands.Select(i => string.Format( - DefaultSynchronizationSettings.SolutionProjectEntryTemplate, - SolutionGuid(i), _projectName, Path.GetFileName(ProjectFile(i)), ProjectGuid(i._output) - )); - - return string.Join(WindowsNewline, projectEntries.ToArray()); - } - - /// - /// Generate the active configuration string for a given project guid - /// - private string GetProjectActiveConfigurations(string projectGuid) - { - return string.Format( - DefaultSynchronizationSettings.SolutionProjectConfigurationTemplate, - projectGuid); - } - - private string EscapedRelativePathFor(string file) - { - if (AssetDatabase.IsPackagedAssetPath(file.ConvertSeparatorsToUnity())) - file = Path.GetFullPath(file.ConvertSeparatorsToUnity()).ConvertSeparatorsToWindows(); - - var projectDir = _projectDirectory.ConvertSeparatorsToWindows(); - file = Paths.SkipPathPrefix(file.ConvertSeparatorsToWindows(), projectDir); - - return SecurityElement.Escape(file); - } - - string ProjectGuid(string assembly) - { - return SolutionGuidGenerator.GuidForProject(_projectName + Path.GetFileNameWithoutExtension(assembly)); - } - - string SolutionGuid(MonoIsland island) - { - return SolutionGuidGenerator.GuidForSolution(_projectName, island.GetExtensionOfSourceFiles()); - } - - string ProjectFooter(MonoIsland island) - { - return string.Format(_settings.GetProjectFooterTemplate(ScriptingLanguageFor(island)), ReadExistingMonoDevelopProjectProperties(island)); - } - - string ReadExistingMonoDevelopSolutionProperties() - { - if (!SolutionExists()) return DefaultMonoDevelopSolutionProperties; - string[] lines; - try - { - lines = File.ReadAllLines(SolutionFile()); - } - catch (IOException) - { - return DefaultMonoDevelopSolutionProperties; - } - - StringBuilder existingOptions = new StringBuilder(); - bool collecting = false; - - foreach (string line in lines) - { - if (_MonoDevelopPropertyHeader.IsMatch(line)) - { - collecting = true; - } - if (collecting) - { - if (line.Contains("EndGlobalSection")) - { - existingOptions.Append(line); - collecting = false; - } - else - existingOptions.AppendFormat("{0}{1}", line, WindowsNewline); - } - } - - if (0 < existingOptions.Length) - { - return existingOptions.ToString(); - } - - return DefaultMonoDevelopSolutionProperties; - } - - string ReadExistingMonoDevelopProjectProperties(MonoIsland island) - { - if (!ProjectExists(island)) return string.Empty; - XmlDocument doc = new XmlDocument(); - XmlNamespaceManager manager; - try - { - doc.Load(ProjectFile(island)); - manager = new XmlNamespaceManager(doc.NameTable); - manager.AddNamespace("msb", MSBuildNamespaceUri); - } - catch (Exception ex) - { - if (ex is IOException || - ex is XmlException) - return string.Empty; - throw; - } - - XmlNodeList nodes = doc.SelectNodes("/msb:Project/msb:ProjectExtensions", manager); - if (0 == nodes.Count) return string.Empty; - - StringBuilder sb = new StringBuilder(); - foreach (XmlNode node in nodes) - { - sb.AppendLine(node.OuterXml); - } - return sb.ToString(); - } - - [Obsolete("Use AssemblyHelper.IsManagedAssembly")] - public static bool IsManagedAssembly(string file) - { - return AssemblyHelper.IsManagedAssembly(file); - } - - public static string GetProjectExtension(ScriptingLanguage language) - { - if (!ProjectExtensions.ContainsKey(language)) - throw new ArgumentException("Unsupported language", "language"); - - return ProjectExtensions[language]; - } - } - - /// - /// SolutionPostProcessor inherit from AssetPostprocessor in order to be called by AssetPostprocessingInternal.CallOnGeneratedCSProjectFiles(). - /// - /// This is a temporary solution until Visual Studio Tool for Unity (VSTU) is modified. - /// - /// - internal class SolutionPostProcessor : AssetPostprocessor - { - /// - /// Get SolutionPostProcessor process order. - /// - /// int.MaxValue to make sure we are the last one called. - public override int GetPostprocessOrder() - { - return int.MaxValue; - } - - /// - /// Replaces 'Include' attribute value with the appropiate path in the specifed node. - /// - /// The XML node. - /// The Unity project directory. - /// true if node was updated, false otherwise. - private static bool ReplacePathInNode(XmlNode node, string projectDir) - { - var path = node.Attributes["Include"].Value; - if (AssetDatabase.IsPackagedAssetPath(path.ConvertSeparatorsToUnity())) - { - var absolutePath = Path.GetFullPath(path).ConvertSeparatorsToWindows(); - var newPath = Paths.SkipPathPrefix(absolutePath, projectDir); - if (newPath != path) - { - node.Attributes["Include"].Value = newPath; - return true; - } - } - return false; - } - - /// - /// Replace paths in specified CSProj file if exists. - /// - /// This method will look in all 'Compile' and 'None' XML tags in the CSProj file and - /// replaces 'Include' attribute value with the appropiate path. Finally, CSProj file will be rewriten on disk if necessay. - /// - /// - /// The CSProj file path. - /// The Unity project directory. - internal static void ReplacePathsInProjectFile(string projectFile, string projectDir) - { - XmlDocument doc = new XmlDocument(); - XmlNamespaceManager manager; - try - { - var updated = false; - doc.Load(projectFile); - - manager = new XmlNamespaceManager(doc.NameTable); - manager.AddNamespace("msb", SolutionSynchronizer.MSBuildNamespaceUri); - - XmlNodeList compileNodes = doc.SelectNodes("//msb:Compile[@Include]", manager); - foreach (XmlNode node in compileNodes) - updated |= ReplacePathInNode(node, projectDir); - - XmlNodeList noneNodes = doc.SelectNodes("//msb:None[@Include]", manager); - foreach (XmlNode node in noneNodes) - updated |= ReplacePathInNode(node, projectDir); - - if (updated) - doc.Save(projectFile); - } - catch (Exception e) - { - UnityEngine.Debug.LogWarning("Post processing of CS project file " + projectFile + " failed, reason: " + e.Message); - } - } - - /// - /// Callback from AssetPostprocessor which is called after CSProj file(s) are generated. - /// - public static void OnGeneratedCSProjectFiles() - { - if (!UnityVSSupport.IsUnityVSEnabled()) - return; - - try - { - var projectDir = Directory.GetCurrentDirectory(); - var projectFiles = Directory.GetFiles(projectDir, string.Format("*{0}", SolutionSynchronizer.GetProjectExtension(ScriptingLanguage.CSharp)), SearchOption.TopDirectoryOnly); - foreach (string projectFile in projectFiles) - { - var file = projectFile.Substring(projectDir.Length + 1); - ReplacePathsInProjectFile(file, projectDir); - } - } - catch (Exception e) - { - UnityEngine.Debug.LogWarning("Post processing of CS project files failed, reason: " + e.Message); - } - } - } - - public static class SolutionGuidGenerator - { - public static string GuidForProject(string projectName) - { - return ComputeGuidHashFor(projectName + "salt"); - } - - public static string GuidForSolution(string projectName, string sourceFileExtension) - { - if (sourceFileExtension.ToLower() == "cs") - // GUID for a C# class library: http://www.codeproject.com/Reference/720512/List-of-Visual-Studio-Project-Type-GUIDs - return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"; - - return ComputeGuidHashFor(projectName); - } - - private static string ComputeGuidHashFor(string input) - { - var hash = MD5.Create().ComputeHash(Encoding.Default.GetBytes(input)); - return HashAsGuid(HashToString(hash)); - } - - private static string HashAsGuid(string hash) - { - var guid = hash.Substring(0, 8) + "-" + hash.Substring(8, 4) + "-" + hash.Substring(12, 4) + "-" + hash.Substring(16, 4) + "-" + hash.Substring(20, 12); - return guid.ToUpper(); - } - - private static string HashToString(byte[] bs) - { - var sb = new StringBuilder(); - foreach (byte b in bs) - sb.Append(b.ToString("x2")); - return sb.ToString(); - } - } -} diff --git a/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs b/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs deleted file mode 100644 index dedc4a100e..0000000000 --- a/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs +++ /dev/null @@ -1,356 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Microsoft.Win32; -using UnityEditorInternal; -using UnityEngine; -using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; - -namespace UnityEditor.VisualStudioIntegration -{ - internal class UnityVSSupport - { - private static bool m_ShouldUnityVSBeActive; - public static string s_UnityVSBridgeToLoad; - private static bool? s_IsUnityVSEnabled; - private static string s_AboutLabel; - - [RequiredByNativeCode] - public static void InitializeUnityVSSupport() - { - Initialize(null); - } - - public static void Initialize(string editorPath) - { - var externalEditor = editorPath ?? ScriptEditorUtility.GetExternalScriptEditor(); - - if (Application.platform == RuntimePlatform.OSXEditor) - { - InitializeVSForMac(externalEditor); - return; - } - - if (Application.platform == RuntimePlatform.WindowsEditor) - InitializeVisualStudio(externalEditor); - } - - private static void InitializeVSForMac(string externalEditor) - { - Version vsfmVersion; - if (!IsVSForMac(externalEditor, out vsfmVersion)) - return; - - m_ShouldUnityVSBeActive = true; - - var bridgeFile = GetVSForMacBridgeAssembly(externalEditor, vsfmVersion); - if (string.IsNullOrEmpty(bridgeFile) || !File.Exists(bridgeFile)) - { - Console.WriteLine("Unable to find Tools for Unity bridge dll for Visual Studio for Mac " + externalEditor); - return; - } - - s_UnityVSBridgeToLoad = bridgeFile; - InternalEditorUtility.RegisterPrecompiledAssembly(Path.GetFileNameWithoutExtension(bridgeFile), bridgeFile); - } - - private static bool IsVSForMac(string externalEditor, out Version vsfmVersion) - { - vsfmVersion = null; - - if (!externalEditor.ToLower().EndsWith("visual studio.app")) - return false; - - // We need to extract the version used by VS for Mac - // to lookup its addin registry - try - { - return GetVSForMacVersion(externalEditor, out vsfmVersion); - } - catch (Exception e) - { - Console.WriteLine("Failed to read Visual Studio for Mac information: {0}", e); - return false; - } - } - - private static bool GetVSForMacVersion(string externalEditor, out Version vsfmVersion) - { - vsfmVersion = null; - - // Read the full VS for Mac version from the plist, it will look like this: - // - // CFBundleShortVersionString - // X.X.X.X - - var plist = Path.Combine(externalEditor, "Contents/Info.plist"); - if (!File.Exists(plist)) - return false; - - const string versionStringRegex = @"\CFBundleShortVersionString\\s+\(?\d+\.\d+\.\d+\.\d+?)\"; - - var file = File.ReadAllText(plist); - var match = Regex.Match(file, versionStringRegex); - var versionGroup = match.Groups["version"]; - if (!versionGroup.Success) - return false; - - vsfmVersion = new Version(versionGroup.Value); - return true; - } - - private static string GetVSForMacBridgeAssembly(string externalEditor, Version vsfmVersion) - { - // Check first if we're overriden - // Useful when developing UnityVS for Mac - var bridge = Environment.GetEnvironmentVariable("VSTUM_BRIDGE"); - if (!string.IsNullOrEmpty(bridge) && File.Exists(bridge)) - return bridge; - - // Look for installed addin - const string addinBridge = "Editor/SyntaxTree.VisualStudio.Unity.Bridge.dll"; - const string addinName = "MonoDevelop.Unity"; - - // Check if we're installed in the user addins repository - // ~/Library/Application Support/VisualStudio/X.0/LocalInstall/Addins - var localAddins = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.Personal), - "Library/Application Support/VisualStudio/" + vsfmVersion.Major + ".0" + "/LocalInstall/Addins"); - - // In the user addins repository, the addins are suffixed by their versions, like `MonoDevelop.Unity.1.0` - // When installing another local user addin, MD will remove files inside the folder - // So we browse all VSTUM addins, and return the one with a bridge, which is the one MD will load - if (Directory.Exists(localAddins)) - { - foreach (var folder in Directory.GetDirectories(localAddins, addinName + "*", SearchOption.TopDirectoryOnly)) - { - bridge = Path.Combine(folder, addinBridge); - if (File.Exists(bridge)) - return bridge; - } - } - - // Check in Visual Studio.app/ - // In that case the name of the addin is used - bridge = Path.Combine(externalEditor, "Contents/Resources/lib/monodevelop/AddIns/" + addinName + "/" + addinBridge); - if (File.Exists(bridge)) - return bridge; - - return null; - } - - private static void InitializeVisualStudio(string externalEditor) - { - if (externalEditor.EndsWith("UnityVS.OpenFile.exe")) - { - externalEditor = SyncVS.FindBestVisualStudio(); - if (externalEditor != null) - ScriptEditorUtility.SetExternalScriptEditor(externalEditor); - } - - VisualStudioVersion vsVersion; - if (!IsVisualStudio(externalEditor, out vsVersion)) - return; - - m_ShouldUnityVSBeActive = true; - - var bridgeFile = GetVstuBridgeAssembly(vsVersion); - if (bridgeFile == null) - { - Console.WriteLine("Unable to find bridge dll in registry for Microsoft Visual Studio Tools for Unity for " + externalEditor); - return; - } - if (!File.Exists(bridgeFile)) - { - Console.WriteLine("Unable to find bridge dll on disk for Microsoft Visual Studio Tools for Unity for " + bridgeFile); - return; - } - s_UnityVSBridgeToLoad = bridgeFile; - InternalEditorUtility.RegisterPrecompiledAssembly(Path.GetFileNameWithoutExtension(bridgeFile), bridgeFile); - } - - static bool IsVisualStudio(string externalEditor, out VisualStudioVersion vsVersion) - { - if (string.IsNullOrEmpty(externalEditor)) - { - vsVersion = VisualStudioVersion.Invalid; - return false; - } - - // If it's a VS found through envvars or the registry - var matches = SyncVS.InstalledVisualStudios.Where(kvp => kvp.Value.Any(v => UnityEditor.Utils.Paths.AreEqual(v.Path, externalEditor, true))).ToArray(); - if (matches.Length > 0) - { - vsVersion = matches[0].Key; - return true; - } - - // If it's a side-by-side VS selected manually - if (externalEditor.EndsWith("devenv.exe", StringComparison.OrdinalIgnoreCase)) - { - if (TryGetVisualStudioVersion(externalEditor, out vsVersion)) - return true; - } - - vsVersion = VisualStudioVersion.Invalid; - return false; - } - - private static bool TryGetVisualStudioVersion(string externalEditor, out VisualStudioVersion vsVersion) - { - switch (ProductVersion(externalEditor).Major) - { - case 9: - vsVersion = VisualStudioVersion.VisualStudio2008; - return true; - case 10: - vsVersion = VisualStudioVersion.VisualStudio2010; - return true; - case 11: - vsVersion = VisualStudioVersion.VisualStudio2012; - return true; - case 12: - vsVersion = VisualStudioVersion.VisualStudio2013; - return true; - case 14: - vsVersion = VisualStudioVersion.VisualStudio2015; - return true; - case 15: - vsVersion = VisualStudioVersion.VisualStudio2017; - return true; - } - - vsVersion = VisualStudioVersion.Invalid; - return false; - } - - private static Version ProductVersion(string externalEditor) - { - try - { - return new Version(System.Diagnostics.FileVersionInfo.GetVersionInfo(externalEditor).ProductVersion); - } - catch (Exception) - { - return new Version(0, 0); - } - } - - //Called by UnityVS through reflection - static public bool ShouldUnityVSBeActive() - { - return m_ShouldUnityVSBeActive; - } - - static string GetAssemblyLocation(System.Reflection.Assembly a) - { - try - { - return a.Location; - } - catch (NotSupportedException) - { - return null; - } - } - - [RequiredByNativeCode] - static public bool IsUnityVSEnabled() - { - if (!s_IsUnityVSEnabled.HasValue) - s_IsUnityVSEnabled = m_ShouldUnityVSBeActive && AppDomain.CurrentDomain.GetAssemblies().Any(a => GetAssemblyLocation(a) == s_UnityVSBridgeToLoad); - - return s_IsUnityVSEnabled.Value; - } - - private static string GetVstuBridgeAssembly(VisualStudioVersion version) - { - try - { - var vsVersion = string.Empty; - - switch (version) - { - // Starting with VS 15, the registry key is using the VS version - // to avoid taking a dependency on the product name - case VisualStudioVersion.VisualStudio2017: - vsVersion = "15.0"; - break; - // VS 2015 and under are still installed in the registry - // using their project names - case VisualStudioVersion.VisualStudio2015: - vsVersion = "2015"; - break; - case VisualStudioVersion.VisualStudio2013: - vsVersion = "2013"; - break; - case VisualStudioVersion.VisualStudio2012: - vsVersion = "2012"; - break; - case VisualStudioVersion.VisualStudio2010: - vsVersion = "2010"; - break; - } - - // search first for the current user with a fallback to machine wide setting - return GetVstuBridgePathFromRegistry(vsVersion, true) - ?? GetVstuBridgePathFromRegistry(vsVersion, false); - } - catch (Exception) - { - return null; - } - } - - private static string GetVstuBridgePathFromRegistry(string vsVersion, bool currentUser) - { - var registryKey = string.Format(@"{0}\Software\Microsoft\Microsoft Visual Studio {1} Tools for Unity", - currentUser ? "HKEY_CURRENT_USER" : "HKEY_LOCAL_MACHINE", - vsVersion); - - return (string)Registry.GetValue(registryKey, "UnityExtensionPath", null); - } - - public static void ScriptEditorChanged(string editorPath) - { - if (Application.platform != RuntimePlatform.OSXEditor && Application.platform != RuntimePlatform.WindowsEditor) - return; - - // We reload the domain because selecting a different editor requires loading a different UnityVS - Initialize(editorPath); - - InternalEditorUtility.RequestScriptReload(); - } - - public static string GetAboutWindowLabel() - { - if (s_AboutLabel != null) - return s_AboutLabel; - - s_AboutLabel = CalculateAboutWindowLabel(); - return s_AboutLabel; - } - - private static string CalculateAboutWindowLabel() - { - if (!IsUnityVSEnabled()) - return ""; - - var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => GetAssemblyLocation(a) == s_UnityVSBridgeToLoad); - if (assembly == null) - return ""; - - var sb = new StringBuilder("Microsoft Visual Studio Tools for Unity "); - sb.Append(assembly.GetName().Version); - sb.Append(" enabled"); - - return sb.ToString(); - } - } -} diff --git a/Editor/Mono/VisualStudioUtil.bindings.cs b/Editor/Mono/VisualStudioUtil.bindings.cs deleted file mode 100644 index 213aa65f2c..0000000000 --- a/Editor/Mono/VisualStudioUtil.bindings.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.Bindings; - -namespace UnityEditorInternal -{ - //*undocumented* - [NativeType(Header = "Editor/Platform/Windows/VisualStudioUtilities.h")] - internal static class VisualStudioUtil - { - public class VisualStudio - { - public readonly string DevEnvPath; - public readonly string Edition; - public readonly Version Version; - public readonly string[] Workloads; - - internal VisualStudio(string devEnvPath, string edition, Version version, string[] workloads) - { - DevEnvPath = devEnvPath; - Edition = edition; - Version = version; - Workloads = workloads; - } - } - - public static IEnumerable ParseRawDevEnvPaths(string[] rawDevEnvPaths) - { - if (rawDevEnvPaths != null) - { - for (int i = 0; i < rawDevEnvPaths.Length / 4; i++) - { - yield return new VisualStudio( - devEnvPath: rawDevEnvPaths[i * 4], - edition: rawDevEnvPaths[i * 4 + 1], - version: new Version(rawDevEnvPaths[i * 4 + 2]), - workloads: rawDevEnvPaths[i * 4 + 3].Split('|')); - } - } - } - - [FreeFunction("VisualStudioUtilities::FindVisualStudioDevEnvPaths")] - [NativeConditional("UNITY_WIN")] - internal extern static string[] FindVisualStudioDevEnvPaths(int visualStudioVersion, string[] requiredWorkloads); - } -} diff --git a/Editor/Mono/WebViewEditorWindow/WebViewEditorStaticWindow.cs b/Editor/Mono/WebViewEditorWindow/WebViewEditorStaticWindow.cs deleted file mode 100644 index 4085f6d7c6..0000000000 --- a/Editor/Mono/WebViewEditorWindow/WebViewEditorStaticWindow.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using System.Text; -using System.IO; -using System; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor.Web -{ - internal abstract class WebViewEditorStaticWindow : WebViewEditorWindow , IHasCustomMenu - { - protected object m_GlobalObject = null; - - // In order to use this class as a parent - // You must copy paste the section below in the child class. - // - //static internal WebView s_WebView; - //internal override WebView webView - //{ - // get {return s_WebView;} - // set {s_WebView = value;} - //} - - - // Use EditorWindow.GetWindow to get/create an instance of this class; - protected WebViewEditorStaticWindow() - { - m_GlobalObject = null; - } - - override public void OnDestroy() - { - OnBecameInvisible(); - m_GlobalObject = null; - } - - override public void OnInitScripting() - { - base.SetScriptObject(); - } - } -} diff --git a/Editor/Mono/WebViewEditorWindow/WebViewEditorWindow.cs b/Editor/Mono/WebViewEditorWindow/WebViewEditorWindow.cs deleted file mode 100644 index 35b3dab8de..0000000000 --- a/Editor/Mono/WebViewEditorWindow/WebViewEditorWindow.cs +++ /dev/null @@ -1,446 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using System.Text; -using System.IO; -using System; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor.Web -{ - internal abstract class WebViewEditorWindow : EditorWindow , IHasCustomMenu - { - [SerializeField] - protected string m_InitialOpenURL; - - [SerializeField] - protected string m_GlobalObjectTypeName; - - internal WebScriptObject scriptObject; - - protected bool m_SyncingFocus; - protected bool m_HasDelayedRefresh; - - // Use EditorWindow.GetWindow to get/create an instance of this class; - protected WebViewEditorWindow() - { - m_HasDelayedRefresh = false; - } - - // if isFileUrl set to true, it will prepend your path with file:// - // else it will prepend nothing and expects the user to set the http:// or - // https:// or file:// prefix like a big kid. - public static T Create(string title, - string sourcesPath, - int minWidth, - int minHeight, - int maxWidth, - int maxHeight) where T : WebViewEditorWindow - { - var window = CreateInstance(); - window.m_GlobalObjectTypeName = typeof(T).FullName; - CreateWindowCommon(window as T, title, sourcesPath, minWidth, minHeight, maxWidth, maxHeight); - window.Show(); - return window; - } - - public static T CreateUtility(string title, - string sourcesPath, - int minWidth, - int minHeight, - int maxWidth, - int maxHeight) where T : WebViewEditorWindow - { - var window = CreateInstance(); - window.m_GlobalObjectTypeName = typeof(T).FullName; - CreateWindowCommon(window as T, title, sourcesPath, minWidth, minHeight, maxWidth, maxHeight); - window.ShowUtility(); - return window; - } - - // if isFileUrl set to true, it will prepend your path with file:// - // else it will prepend nothing and expects the user to set the http:// or - // https:// or file:// prefix like a big kid. - public static T CreateBase(string title, - string sourcesPath, - int minWidth, - int minHeight, - int maxWidth, - int maxHeight) where T : WebViewEditorWindow - { - var window = GetWindow(title); - CreateWindowCommon(window as T, title, sourcesPath, minWidth, minHeight, maxWidth, maxHeight); - window.Show(); - return window; - } - - public virtual void AddItemsToMenu(GenericMenu menu) - { - menu.AddItem(EditorGUIUtility.TrTextContent("Reload"), false, Reload); - if (Unsupported.IsDeveloperMode()) - menu.AddItem(EditorGUIUtility.TrTextContent("About"), false, About); - } - - // Reloads the web view - public void Reload() - { - if (webView == null) - return; - webView.Reload(); - } - - // About the web view - public void About() - { - if (webView == null) - return; - webView.LoadURL("chrome://version"); - } - - public void OnLoadError(string url) - { - if (!webView) - return; - } - - public virtual void OnLocationChanged(string url) - { - } - - public void ToggleMaximize() - { - maximized = !maximized; - Refresh(); - SetFocus(true); - } - - virtual public void Init() - { - } - - public void OnGUI() - { - var m_WebViewRect = GUIClip.Unclip(new Rect(0, 0, position.width, position.height)); - - GUILayout.BeginArea(m_WebViewRect); - GUILayout.BeginHorizontal(); - GUILayout.FlexibleSpace(); - GUILayout.BeginVertical(); - GUILayout.FlexibleSpace(); - GUILayout.Label("Loading...", EditorStyles.label); - GUILayout.FlexibleSpace(); - GUILayout.EndVertical(); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - GUILayout.EndArea(); - - // TODO workaround for Mac - if (Event.current.type == EventType.Repaint) - { - if (m_HasDelayedRefresh) - { - Refresh(); - m_HasDelayedRefresh = false; - } - } - - // If we haven't initialize our embedded webview yet, - // do so now. - if (m_InitialOpenURL != null) - { - if (!webView) - { - InitWebView(m_WebViewRect); - } - if (Event.current.type == EventType.Repaint) - { - webView.SetHostView(m_Parent); - webView.SetSizeAndPosition((int)m_WebViewRect.x, (int)m_WebViewRect.y, (int)m_WebViewRect.width, (int)m_WebViewRect.height); - } - } - } - - public void OnBatchMode() - { - var m_WebViewRect = GUIClip.Unclip(new Rect(0, 0, position.width, position.height)); - - // If we haven't initialize our embedded webview yet, - // do so now. - if (m_InitialOpenURL != null) - { - if (!webView) - { - InitWebView(m_WebViewRect); - } - } - } - - public void Refresh() - { - if (webView == null) - return; - webView.Hide(); - webView.Show(); - } - - public void OnFocus() - { - SetFocus(true); - } - - public void OnLostFocus() - { - SetFocus(false); - } - - public virtual void OnEnable() - { - Init(); - } - - public void OnBecameInvisible() - { - if (!webView) - return; - - // Either our tab put into the background or we've been removed from our - // dock and are about to be moved to some other dock. Whatever the case, - // unparent our WebView native window from the current dock's native window. - // This will implicitly hide the window. - webView.SetHostView(null); - } - - public virtual void OnDestroy() - { - if (webView != null) - { - DestroyImmediate(webView); - } - } - - System.Timers.Timer m_PostLoadTimer; - const int k_RepaintTimerDelay = 30; - - void DoPostLoadTask() - { - EditorApplication.update -= DoPostLoadTask; - RepaintImmediately(); - } - - void RaisePostLoadCondition(object obj, System.Timers.ElapsedEventArgs args) - { - m_PostLoadTimer.Stop(); - m_PostLoadTimer = null; - EditorApplication.update += DoPostLoadTask; - } - - protected void LoadUri() - { - if (m_InitialOpenURL.StartsWith("http")) - { - webView.LoadURL(m_InitialOpenURL); - m_PostLoadTimer = new System.Timers.Timer(k_RepaintTimerDelay); - m_PostLoadTimer.Elapsed += RaisePostLoadCondition; - m_PostLoadTimer.Enabled = true; - } - else if (m_InitialOpenURL.StartsWith("file")) - { - webView.LoadFile(m_InitialOpenURL); - } - else - { - // Load the startup file. - var filePath = Path.Combine(System.Uri.EscapeUriString(Path.Combine(EditorApplication.applicationContentsPath, "Resources")), m_InitialOpenURL); - webView.LoadFile(filePath); - } - } - - virtual protected void InitWebView(Rect m_WebViewRect) - { - if (!webView) - { - var x = (int)m_WebViewRect.x; - var y = (int)m_WebViewRect.y; - var width = (int)m_WebViewRect.width; - var height = (int)m_WebViewRect.height; - - // Create WebView. - webView = CreateInstance(); - webView.InitWebView(m_Parent, x, y, width, height, false); - webView.hideFlags = HideFlags.HideAndDontSave; - - // Sync focus. - SetFocus(hasFocus); - } - - // Direct WebView event callbacks to us. - webView.SetDelegateObject(this); - - LoadUri(); - SetFocus(true); - } - - virtual public void OnInitScripting() - { - SetScriptObject(); - } - - protected void NotifyVisibility(bool visible) - { - if (webView == null) - { - return; - } - - string eventCmd = "document.dispatchEvent(new CustomEvent('showWebView',{ detail: { visible:"; - - eventCmd += (visible ? "true" : "false"); - eventCmd += "}, bubbles: true, cancelable: false }));"; - - webView.ExecuteJavascript(eventCmd); - } - - protected virtual void LoadPage() - { - if (!webView) - return; - - NotifyVisibility(false); - LoadUri(); - webView.Show(); - } - - protected void SetScriptObject() - { - if (!webView) - return; - - CreateScriptObject(); - webView.DefineScriptObject("window.webScriptObject", scriptObject); - } - - private static void CreateWindowCommon(T window, - string title, - string sourcesPath, - int minWidth, - int minHeight, - int maxWidth, - int maxHeight) where T : WebViewEditorWindow - { - window.titleContent = new GUIContent(title); - window.minSize = new Vector2(minWidth, minHeight); - window.maxSize = new Vector2(maxWidth, maxHeight); - window.m_InitialOpenURL = sourcesPath; - window.Init(); - } - - private void CreateScriptObject() - { - if (scriptObject != null) - return; - - scriptObject = CreateInstance(); - scriptObject.hideFlags = HideFlags.HideAndDontSave; - scriptObject.webView = webView; - } - - private void InvokeJSMethod(string objectName, string name, params object[] args) - { - if (!webView) - return; - - var scriptCodeBuffer = new StringBuilder(); - scriptCodeBuffer.Append(objectName); - scriptCodeBuffer.Append('.'); - scriptCodeBuffer.Append(name); - scriptCodeBuffer.Append('('); - - var isFirst = true; - foreach (var arg in args) - { - if (!isFirst) - scriptCodeBuffer.Append(','); - - // Quote strings. This is pretty simple-minded as we don't escape - // things within the string. - var isString = arg is string; - if (isString) - scriptCodeBuffer.Append('"'); - - scriptCodeBuffer.Append(arg); - - if (isString) - scriptCodeBuffer.Append('"'); - - isFirst = false; - } - - scriptCodeBuffer.Append(");"); - - webView.ExecuteJavascript(scriptCodeBuffer.ToString()); - } - - private void SetFocus(bool value) - { - // Giving the focus to the browser's native window will cause our GuiView's - // native window to lose focus. If we blindly pass on our focus state to - // the browser, we will end up making it lose focus while we try to make it - // have focus. However, we generally *do* want to pass on focus. - // - // So, what we do is to simply prevent recursion here. Allows us to just - // hand the focus over. - - if (m_SyncingFocus) - return; - - m_SyncingFocus = true; - - if (webView != null) - { - // If we're being focused, sync up our current native parent window and force - // the browser window to be visible. We're doing this here rather than in - // OnBecameVisible since this way it will also work when maximizing our - // EditorWindow (which goes through some really whacky logic). We'll be - // setting this state more often than otherwise, but that doesn't really - // hurt. - if (value) - { - webView.SetHostView(m_Parent); - if (Application.platform != RuntimePlatform.WindowsEditor) - { - // TODO investigate why a Show () so close to a reparenting causes issues on Mac - m_HasDelayedRefresh = true; - } - else - { - webView.Show(); - } - } - //We have to check if the parent have the focus and also if we have the focus in the tab to - //know if we have the application focus. The application focus is use by the CefFocusHandler - //To know if the focus request is coming from unity editor or from cef browser. If the focus - //came from cefBrowser we will refuse it so unity editor active window stay active. - webView.SetApplicationFocus(m_Parent != null && m_Parent.hasFocus && hasFocus); - webView.SetFocus(value); - } - - m_SyncingFocus = false; - } - - public string initialOpenUrl - { - set { m_InitialOpenURL = value; } - get { return m_InitialOpenURL; } - } - - internal abstract WebView webView - { - get; - set; - } - } -} diff --git a/Editor/Mono/WebViewEditorWindow/WebViewEditorWindowsTabs.cs b/Editor/Mono/WebViewEditorWindow/WebViewEditorWindowsTabs.cs deleted file mode 100644 index b47719a678..0000000000 --- a/Editor/Mono/WebViewEditorWindow/WebViewEditorWindowsTabs.cs +++ /dev/null @@ -1,197 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Collections.Generic; -using UnityEngine; -using System.Text; -using System.IO; -using System; -using UnityEditor; -using UnityEditorInternal; - -namespace UnityEditor.Web -{ - // This class is used to create a window that has an array of webViews which can be toggled - // visible/hidden. They will appear as one window (such as the services tab). - internal class WebViewEditorWindowTabs : WebViewEditorWindow , IHasCustomMenu, ISerializationCallbackReceiver - { - protected object m_GlobalObject = null; - - internal WebView m_WebView; - - [SerializeField] - private List m_RegisteredViewURLs; - - [SerializeField] - private List m_RegisteredViewInstances; - - private Dictionary m_RegisteredViews; - - // Use EditorWindow.GetWindow to get/create an instance of this class; - protected WebViewEditorWindowTabs() - { - m_RegisteredViewURLs = new List(); - m_RegisteredViewInstances = new List(); - m_RegisteredViews = new Dictionary(); - m_GlobalObject = null; - } - - public override void Init() - { - if (m_GlobalObject == null && !string.IsNullOrEmpty(m_GlobalObjectTypeName)) - { - var instanceType = Type.GetType(m_GlobalObjectTypeName); - if (instanceType != null) - { - m_GlobalObject = ScriptableObject.CreateInstance(instanceType); - JSProxyMgr.GetInstance().AddGlobalObject(m_GlobalObject.GetType().Name, m_GlobalObject); - } - } - } - - public override void OnDestroy() - { - if (webView != null) - { - DestroyImmediate(webView); - } - - m_GlobalObject = null; - - foreach (WebView view in m_RegisteredViews.Values) - { - if (view != null) - DestroyImmediate(view); - } - - m_RegisteredViews.Clear(); - m_RegisteredViewURLs.Clear(); - m_RegisteredViewInstances.Clear(); - } - - public void OnBeforeSerialize() - { - m_RegisteredViewURLs = new List(); - m_RegisteredViewInstances = new List(); - foreach (var kvp in m_RegisteredViews) - { - m_RegisteredViewURLs.Add(kvp.Key); - m_RegisteredViewInstances.Add(kvp.Value); - } - } - - public void OnAfterDeserialize() - { - m_RegisteredViews = new Dictionary(); - for (int i = 0; i != Math.Min(m_RegisteredViewURLs.Count, m_RegisteredViewInstances.Count); i++) - { - m_RegisteredViews.Add(m_RegisteredViewURLs[i], m_RegisteredViewInstances[i]); - } - } - - static string MakeUrlKey(string webViewUrl) - { - string result; - int index = webViewUrl.IndexOf("#"); - if (index != -1) - { - result = webViewUrl.Substring(0, index); - } - else - { - result = webViewUrl; - } - - index = result.LastIndexOf("/"); - if (index == (result.Length - 1)) - { - return result.Substring(0, index); - } - - return result; - } - - protected void UnregisterWebviewUrl(string webViewUrl) - { - var url = MakeUrlKey(webViewUrl); - m_RegisteredViews[url] = null; - } - - private void RegisterWebviewUrl(string webViewUrl, WebView view) - { - var url = MakeUrlKey(webViewUrl); - m_RegisteredViews[url] = view; - } - - private bool FindWebView(string webViewUrl, out WebView webView) - { - webView = null; - var url = MakeUrlKey(webViewUrl); - return m_RegisteredViews.TryGetValue(url, out webView); - } - - public WebView GetWebViewFromURL(string url) - { - var urlKey = MakeUrlKey(url); - return m_RegisteredViews[urlKey]; - } - - public override void OnInitScripting() - { - base.SetScriptObject(); - } - - protected override void InitWebView(Rect webViewRect) - { - base.InitWebView(webViewRect); - if (m_InitialOpenURL != null && webView != null) - { - RegisterWebviewUrl(m_InitialOpenURL, webView); - } - } - - protected override void LoadPage() - { - if (!webView) - return; - - WebView tmpWebView; - - if (!FindWebView(m_InitialOpenURL, out tmpWebView) || tmpWebView == null) - { - NotifyVisibility(false); - //We have to create a webview cache for this url - webView.SetHostView(null); - webView = null; - var webViewRect = GUIClip.Unclip(new Rect(0, 0, position.width, position.height)); - InitWebView(webViewRect); - RegisterWebviewUrl(m_InitialOpenURL, webView); - NotifyVisibility(true); - } - else - { - if (tmpWebView != webView) - { - NotifyVisibility(false); - - tmpWebView.SetHostView(m_Parent); - webView.SetHostView(null); - webView = tmpWebView; - NotifyVisibility(true); - webView.Show(); - } - - //This load Uri causes the flashing. We have NotifyVisibilty we can use to - //to tell the javascript it's being shown - LoadUri(); - } - } - - internal override WebView webView - { - get {return m_WebView; } - set {m_WebView = value; } - } - } -} diff --git a/Editor/Mono/WebViewEditorWindow/WebViewTestFunctions.cs b/Editor/Mono/WebViewEditorWindow/WebViewTestFunctions.cs deleted file mode 100644 index fc9a673fbe..0000000000 --- a/Editor/Mono/WebViewEditorWindow/WebViewTestFunctions.cs +++ /dev/null @@ -1,138 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Linq; -using Debug = UnityEngine.Debug; - -namespace UnityEditor.Web -{ - internal class WebViewTestFunctions - { - public int ReturnInt() - { - return 5; - } - - public string ReturnString() - { - return "Five"; - } - - public bool ReturnBool() - { - return true; - } - - public int[] ReturnNumberArray() - { - return new[] {1, 2, 3}; - } - - public string[] ReturnStringArray() - { - return new[] {"One", "Two", "Three"}; - } - - public bool[] ReturnBoolArray() - { - return new[] {true, false, true}; - } - - public TestObject ReturnObject() - { - TestObject testObject = new TestObject {NumberProperty = 5, StringProperty = "Five", BoolProperty = true}; - return testObject; - } - - public void AcceptInt(int passedInt) - { - Debug.Log("A value was passed from JS: " + passedInt); - } - - public void AcceptString(string passedString) - { - Debug.Log("A value was passed from JS: " + passedString); - } - - public void AcceptBool(bool passedBool) - { - Debug.Log("A value was passed from JS: " + passedBool); - } - - public void AcceptIntArray(int[] passedArray) - { - Debug.Log("An array was passed from the JS. Array elements were:"); - for (int i = 0; i <= passedArray.Length; i++) - { - Debug.Log("Element at index " + i + ": " + passedArray[i]); - } - } - - public void AcceptStringArray(string[] passedArray) - { - Debug.Log("An array was passed from the JS. Array elements were:"); - for (int i = 0; i <= passedArray.Length; i++) - { - Debug.Log("Element at index " + i + ": " + passedArray[i]); - } - } - - public void AcceptBoolArray(bool[] passedArray) - { - Debug.Log("An array was passed from the JS. Array elements were:"); - for (int i = 1; i <= passedArray.Length; i++) - { - Debug.Log("Element at index " + i + ": " + passedArray[i]); - } - } - - public void AcceptTestObject(TestObject passedObject) - { - Debug.Log("An object was passed from the JS. Properties were:"); - Debug.Log("StringProperty: " + passedObject.StringProperty); - Debug.Log("NumberProperty: " + passedObject.NumberProperty); - Debug.Log("BoolProperty: " + passedObject.BoolProperty); - } - - //For testing function calls with no parameters or return value - public void VoidMethod(string logMessage) - { - Debug.Log("A method was called from the CEF: " + logMessage); - } - - //For testing access control on CEF function calls - private string APrivateMethod(string input) - { - return "This method is private and not for CEF"; - } - - //For testing function calls that supply and expect an array of strings - public string[] ArrayReverse(string[] input) - { - var outputStrings = (string[])input.Reverse(); - return outputStrings; - } - - public void LogMessage(string message) - { - Debug.Log(message); - } - - public static void RunTestScript(string path) - { - var url = "file:///" + path; - - JSProxyMgr.GetInstance().AddGlobalObject("WebViewTestFunctions", new WebViewTestFunctions()); - var window = WebViewEditorWindowTabs.Create("Test Window", url, 0, 0, 0, 0); - window.OnBatchMode(); - } - } - - internal class TestObject - { - public string StringProperty { get; set; } - public int NumberProperty { get; set; } - public bool BoolProperty { get; set; } - } -} diff --git a/Editor/Src/TextRendering/TextRenderingCommands.cs b/Editor/Src/TextRendering/TextRenderingCommands.cs deleted file mode 100644 index 2bbe852c36..0000000000 --- a/Editor/Src/TextRendering/TextRenderingCommands.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditor -{ - static class TextRenderingCommands - { - [MenuItem("GameObject/3D Object/3D Text", priority = 4000)] - static void Create3DText(MenuCommand command) - { - var parent = command.context as GameObject; - var go = GOCreationCommands.CreateGameObject(parent, "New Text", typeof(MeshRenderer), typeof(TextMesh)); - - var font = Selection.activeObject as Font ?? Font.GetDefault(); - TextMesh tm = go.GetComponent(); - tm.text = "Hello World"; - tm.font = font; - go.GetComponent().material = font.material; - - GOCreationCommands.Place(go, parent); - } - } -} diff --git a/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs b/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs deleted file mode 100644 index 37d8e993cf..0000000000 --- a/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs +++ /dev/null @@ -1,286 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEditor.XR.Daydream; -using UnityEngine; -using System.Linq; - -namespace UnityEditorInternal.VR -{ - internal class VRCustomOptionsGoogleVR : VRCustomOptions - { - static GUIContent[] s_DepthOptions = - { - EditorGUIUtility.TrTextContent("16-bit depth"), - EditorGUIUtility.TrTextContent("24-bit depth"), - EditorGUIUtility.TrTextContent("24-bit depth | 8-bit stencil") - }; - static GUIContent s_DepthFormatLabel = EditorGUIUtility.TrTextContent("Depth Format"); - - SerializedProperty m_DepthFormat; - - public override void Initialize(SerializedObject settings, string propertyName) - { - base.Initialize(settings, propertyName); - m_DepthFormat = FindPropertyAssert("depthFormat"); - } - - public override Rect Draw(Rect rect) - { - rect.y += EditorGUIUtility.standardVerticalSpacing; - rect.height = EditorGUIUtility.singleLineHeight; - - GUIContent label = EditorGUI.BeginProperty(rect, s_DepthFormatLabel, m_DepthFormat); - EditorGUI.BeginChangeCheck(); - int intValue = EditorGUI.Popup(rect, label, m_DepthFormat.intValue, s_DepthOptions); - if (EditorGUI.EndChangeCheck()) - { - m_DepthFormat.intValue = intValue; - } - EditorGUI.EndProperty(); - - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - - return rect; - } - - public override float GetHeight() - { - return EditorGUIUtility.singleLineHeight + (EditorGUIUtility.standardVerticalSpacing * 2.0f); - } - } - - internal class VRCustomOptionsCardboard : VRCustomOptionsGoogleVR - { - static GUIContent s_EnableTransitionViewLabel = EditorGUIUtility.TrTextContent("Enable Transition View"); - SerializedProperty m_EnableTransitionView; - - public override void Initialize(SerializedObject settings) - { - Initialize(settings, "cardboard"); - } - - public override void Initialize(SerializedObject settings, string propertyName) - { - base.Initialize(settings, propertyName); - m_EnableTransitionView = FindPropertyAssert("enableTransitionView"); - } - - public override Rect Draw(Rect rect) - { - rect = base.Draw(rect); - - rect.height = EditorGUIUtility.singleLineHeight; - GUIContent label = EditorGUI.BeginProperty(rect, s_EnableTransitionViewLabel, m_EnableTransitionView); - EditorGUI.BeginChangeCheck(); - bool boolValue = EditorGUI.Toggle(rect, label, m_EnableTransitionView.boolValue); - if (EditorGUI.EndChangeCheck()) - { - m_EnableTransitionView.boolValue = boolValue; - } - EditorGUI.EndProperty(); - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - - return rect; - } - - public override float GetHeight() - { - return base.GetHeight() + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - } - } - - internal class VRCustomOptionsDaydream : VRCustomOptionsGoogleVR - { - const int kDisabled = 0; - const int kSupported = 1; - const int kRequired = 2; - - const int kThreeDoFHeadTracking = (int)SupportedHeadTracking.ThreeDoF; - const int kSixDoFHeadTracking = (int)SupportedHeadTracking.SixDoF; - - const float s_Indent = 10.0f; - - static GUIContent s_ForegroundIconLabel = EditorGUIUtility.TrTextContent("Foreground Icon", "Icon should be a Texture with dimensions of 512px by 512px and a 1:1 aspect ratio."); - static GUIContent s_BackgroundIconLabel = EditorGUIUtility.TrTextContent("Background Icon", "Icon should be a Texture with dimensions of 512px by 512px and a 1:1 aspect ratio."); - static GUIContent s_SustainedPerformanceModeLabel = EditorGUIUtility.TrTextContent("Sustained Performance", "Sustained Performance mode is intended to provide a consistent level of performance for a prolonged amount of time"); - static GUIContent s_EnableVideoLayer = EditorGUIUtility.TrTextContent("Video Surface", "Enable the use of the video surface integrated with Daydream asynchronous reprojection."); - static GUIContent s_UseProtectedVideoMemoryLabel = EditorGUIUtility.TrTextContent("Protected Memory", "Enable the use of DRM protection. Only usable if all content is DRM Protected."); - static GUIContent s_MinimumTargetHeadTracking = EditorGUIUtility.TrTextContent("Positional Head Tracking", "Requested head tracking support of target devices to run the application on."); - - static GUIContent[] s_TargetHeadTrackingOptions = - { - EditorGUIUtility.TrTextContent("Disabled", "Will run on any device and provides no head tracking."), - EditorGUIUtility.TrTextContent("Supported", "Will run on any device and will provide head tracking on devices that support head tracking."), - EditorGUIUtility.TrTextContent("Required", "Will only run on devices with full 6 DoF head tracking support."), - }; - - SerializedProperty m_DaydreamIcon; - SerializedProperty m_DaydreamIconBackground; - SerializedProperty m_DaydreamUseSustainedPerformanceMode; - SerializedProperty m_DaydreamEnableVideoLayer; - SerializedProperty m_DaydreamUseProtectedMemory; - SerializedProperty m_MinimumSupportedHeadTracking; - SerializedProperty m_MaximumSupportedHeadTracking; - - public override void Initialize(SerializedObject settings) - { - Initialize(settings, "daydream"); - } - - public override void Initialize(SerializedObject settings, string propertyName) - { - base.Initialize(settings, propertyName); - m_DaydreamIcon = FindPropertyAssert("daydreamIconForeground"); - m_DaydreamIconBackground = FindPropertyAssert("daydreamIconBackground"); - m_DaydreamUseSustainedPerformanceMode = FindPropertyAssert("useSustainedPerformanceMode"); - m_DaydreamEnableVideoLayer = FindPropertyAssert("enableVideoLayer"); - m_DaydreamUseProtectedMemory = FindPropertyAssert("useProtectedVideoMemory"); - m_MinimumSupportedHeadTracking = FindPropertyAssert("minimumSupportedHeadTracking"); - m_MaximumSupportedHeadTracking = FindPropertyAssert("maximumSupportedHeadTracking"); - } - - private Rect DrawTextureUI(Rect rect, GUIContent propLabel, SerializedProperty prop) - { - rect.height = EditorGUI.kObjectFieldThumbnailHeight; - GUIContent label = EditorGUI.BeginProperty(rect, propLabel, prop); - - EditorGUI.BeginChangeCheck(); - Texture2D objectReferenceValue = EditorGUI.ObjectField(rect, label, (Texture2D)prop.objectReferenceValue, typeof(Texture2D), false) as Texture2D; - if (EditorGUI.EndChangeCheck()) - { - prop.objectReferenceValue = objectReferenceValue; - } - - EditorGUI.EndProperty(); - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - return rect; - } - - // While the public C# API has a min/max range for target head tracking, there currently are only - // two actual values for the range. To simplify the UI we replace setting of the range with a simple - // dropdown that only allows you to select currently valid ranges. When there are more values added - // to the range then we can switch over to a two dropdown (or whatever) range selector instead of - // using this mapping. - private int GetHeadTrackingValue() - { - int retValue = kDisabled; - if (m_MinimumSupportedHeadTracking.intValue == kThreeDoFHeadTracking && m_MaximumSupportedHeadTracking.intValue == kThreeDoFHeadTracking) - { - retValue = kDisabled; - } - else if (m_MinimumSupportedHeadTracking.intValue == kThreeDoFHeadTracking && m_MaximumSupportedHeadTracking.intValue == kSixDoFHeadTracking) - { - retValue = kSupported; - } - else if (m_MinimumSupportedHeadTracking.intValue == kSixDoFHeadTracking && m_MaximumSupportedHeadTracking.intValue == kSixDoFHeadTracking) - { - retValue = kRequired; - } - return retValue; - } - - private void SetHeadTrackingValue(int headTrackingValue) - { - switch (headTrackingValue) - { - case kDisabled: - m_MinimumSupportedHeadTracking.intValue = kThreeDoFHeadTracking; - m_MaximumSupportedHeadTracking.intValue = kThreeDoFHeadTracking; - break; - case kSupported: - m_MinimumSupportedHeadTracking.intValue = kThreeDoFHeadTracking; - m_MaximumSupportedHeadTracking.intValue = kSixDoFHeadTracking; - break; - case kRequired: - m_MinimumSupportedHeadTracking.intValue = kSixDoFHeadTracking; - m_MaximumSupportedHeadTracking.intValue = kSixDoFHeadTracking; - break; - } - } - - public override Rect Draw(Rect rect) - { - rect = base.Draw(rect); - - rect = DrawTextureUI(rect, s_ForegroundIconLabel, m_DaydreamIcon); - rect = DrawTextureUI(rect, s_BackgroundIconLabel, m_DaydreamIconBackground); - - rect.height = EditorGUIUtility.singleLineHeight; - GUIContent label = EditorGUI.BeginProperty(rect, s_SustainedPerformanceModeLabel, m_DaydreamUseSustainedPerformanceMode); - EditorGUI.BeginChangeCheck(); - bool boolValue = EditorGUI.Toggle(rect, label, m_DaydreamUseSustainedPerformanceMode.boolValue); - if (EditorGUI.EndChangeCheck()) - { - m_DaydreamUseSustainedPerformanceMode.boolValue = boolValue; - } - EditorGUI.EndProperty(); - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - - rect.height = EditorGUIUtility.singleLineHeight; - label = EditorGUI.BeginProperty(rect, s_EnableVideoLayer, m_DaydreamEnableVideoLayer); - EditorGUI.BeginChangeCheck(); - boolValue = EditorGUI.Toggle(rect, label, m_DaydreamEnableVideoLayer.boolValue); - if (EditorGUI.EndChangeCheck()) - { - m_DaydreamEnableVideoLayer.boolValue = boolValue; - if (!boolValue) m_DaydreamUseProtectedMemory.boolValue = false; - } - EditorGUI.EndProperty(); - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - - if (m_DaydreamEnableVideoLayer.boolValue) - { - rect.x += s_Indent; - rect.width -= s_Indent; - rect.height = EditorGUIUtility.singleLineHeight; - label = EditorGUI.BeginProperty(rect, s_UseProtectedVideoMemoryLabel, m_DaydreamUseProtectedMemory); - EditorGUI.BeginChangeCheck(); - boolValue = EditorGUI.Toggle(rect, label, m_DaydreamUseProtectedMemory.boolValue); - if (EditorGUI.EndChangeCheck()) - { - m_DaydreamUseProtectedMemory.boolValue = boolValue; - } - EditorGUI.EndProperty(); - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - rect.x -= s_Indent; - rect.width += s_Indent; - } - - rect.y += EditorGUIUtility.standardVerticalSpacing; - rect.height = EditorGUIUtility.singleLineHeight; - - EditorGUI.BeginChangeCheck(); - int intValue = EditorGUI.Popup(rect, s_MinimumTargetHeadTracking, GetHeadTrackingValue(), s_TargetHeadTrackingOptions); - if (EditorGUI.EndChangeCheck()) - { - SetHeadTrackingValue(intValue); - } - - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - - - return rect; - } - - public override float GetHeight() - { - float singleLineCount = 5.0f; - float thumbnailCount = 2.0f; - float verticalSpacingCount = 4.0f; - - if (m_DaydreamEnableVideoLayer.boolValue) - { - singleLineCount += 1.0f; - verticalSpacingCount += 1.0f; - } - - return base.GetHeight() + (EditorGUIUtility.singleLineHeight * singleLineCount) + - (EditorGUI.kObjectFieldThumbnailHeight * thumbnailCount) + - (EditorGUIUtility.standardVerticalSpacing * verticalSpacingCount); - } - } -} diff --git a/Editor/Src/VR/Mono/HolographicEmulation.cs b/Editor/Src/VR/Mono/HolographicEmulation.cs deleted file mode 100644 index d4142f3581..0000000000 --- a/Editor/Src/VR/Mono/HolographicEmulation.cs +++ /dev/null @@ -1,169 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEngine; - -namespace UnityEditorInternal.VR -{ - public class SimulatedBody - { - // Require use of HolographicEmulation.simulatedBody to get instance - internal SimulatedBody() {} - - public Vector3 position - { - get - { - return Vector3.zero; - } - set - { - } - } - - public float rotation - { - get - { - return 0; - } - set - { - } - } - - public float height - { - get - { - return 0; - } - set - { - } - } - } - - public class SimulatedHead - { - // Require use of HolographicEmulation.simulatedHead to get instance - internal SimulatedHead() {} - - public float diameter - { - get - { - return 0; - } - set - { - } - } - - public Vector3 eulerAngles - { - get - { - return Vector3.zero; - } - set - { - } - } - } - - public class SimulatedHand - { - - // Require use of HolographicEmulation.simulatedLeftHand or HolographicEmulation.simulatedRightHand to get instance - internal SimulatedHand(GestureHand hand) - { - } - - public Vector3 position - { - get - { - return Vector3.zero; - } - set - { - } - } - - public bool activated - { - get - { - return false; - } - set - { - } - } - - public bool visible - { - get - { - return false; - } - } - - public void EnsureVisible() - { - } - - public void PerformGesture(SimulatedGesture gesture) - { - } - } - - public sealed partial class HolographicEmulation - { - static SimulatedBody s_Body = new SimulatedBody(); - static SimulatedHead s_Head = new SimulatedHead(); - static SimulatedHand s_LeftHand = new SimulatedHand(GestureHand.Left); - static SimulatedHand s_RightHand = new SimulatedHand(GestureHand.Right); - - public static SimulatedBody simulatedBody { get { return s_Body; } } - public static SimulatedHead simulatedHead { get { return s_Head; } } - public static SimulatedHand simulatedLeftHand { get { return s_LeftHand; } } - public static SimulatedHand simulatedRightHand { get { return s_RightHand; } } - } - - public static class HolographicEmulationHelpers - { - public const float k_DefaultBodyHeight = 1.776f; - public const float k_DefaultHeadDiameter = 0.2319999f; - public const float k_ForwardOffset = 0.0985f; - - // this method uses the experimentally-found constants above to adjust - // transform data in order to account for an emulator with different - // settings for height, head size, and offset from the center of the head - // to where the eyes are actually located (the respective constants are - // defined above) - public static Vector3 CalcExpectedCameraPosition(SimulatedHead head, SimulatedBody body) - { - Vector3 adjustedCameraPosition = body.position; - - // account for body height difference and offset for head size - adjustedCameraPosition.y += body.height - k_DefaultBodyHeight; - - adjustedCameraPosition.y -= head.diameter / 2f; - adjustedCameraPosition.y += k_DefaultHeadDiameter / 2f; - - // get total effective head rotation and convert to quaternion... - var angles = head.eulerAngles; - angles.y += body.rotation; - var rotation = Quaternion.Euler(angles); - - // ...to account for the experimentally found forward-offset between the - // center of the simulated head and average position of the eyes - adjustedCameraPosition += rotation * (k_ForwardOffset * Vector3.forward); - - return adjustedCameraPosition; - } - } -} diff --git a/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs b/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs deleted file mode 100644 index 5a949a85d7..0000000000 --- a/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; -using System.Linq; - -namespace UnityEditorInternal.VR -{ - internal class VRCustomOptionsOculus : VRCustomOptions - { - static GUIContent s_SharedDepthBufferLabel = EditorGUIUtility.TextContent("Shared Depth Buffer|Enable depth buffer submission to allow for overlay depth occlusion, etc."); - static GUIContent s_DashSupportLabel = EditorGUIUtility.TextContent("Dash Support|If enabled, pressing the home button brings up Dash, otherwise it brings up the older universal menu."); - - SerializedProperty m_SharedDepthBuffer; - SerializedProperty m_DashSupport; - - public override void Initialize(SerializedObject settings) - { - Initialize(settings, "oculus"); - } - - public override void Initialize(SerializedObject settings, string propertyName) - { - base.Initialize(settings, propertyName); - m_SharedDepthBuffer = FindPropertyAssert("sharedDepthBuffer"); - m_DashSupport = FindPropertyAssert("dashSupport"); - } - - public override Rect Draw(Rect rect) - { - rect.y += EditorGUIUtility.standardVerticalSpacing; - - rect.height = EditorGUIUtility.singleLineHeight; - GUIContent label = EditorGUI.BeginProperty(rect, s_SharedDepthBufferLabel, m_SharedDepthBuffer); - EditorGUI.BeginChangeCheck(); - bool boolValue = EditorGUI.Toggle(rect, label, m_SharedDepthBuffer.boolValue); - if (EditorGUI.EndChangeCheck()) - { - m_SharedDepthBuffer.boolValue = boolValue; - } - EditorGUI.EndProperty(); - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - - rect.height = EditorGUIUtility.singleLineHeight; - label = EditorGUI.BeginProperty(rect, s_DashSupportLabel, m_DashSupport); - EditorGUI.BeginChangeCheck(); - boolValue = EditorGUI.Toggle(rect, label, m_DashSupport.boolValue); - if (EditorGUI.EndChangeCheck()) - { - m_DashSupport.boolValue = boolValue; - } - EditorGUI.EndProperty(); - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - - return rect; - } - - public override float GetHeight() - { - return (EditorGUIUtility.singleLineHeight * 2.0f) + (EditorGUIUtility.standardVerticalSpacing * 3.0f); - } - } -} diff --git a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs deleted file mode 100644 index 779fb53b4e..0000000000 --- a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs +++ /dev/null @@ -1,601 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using UnityEditor; -using UnityEditor.Callbacks; -using UnityEditor.Modules; -using UnityEditorInternal; -using UnityEngine; -using GraphicsDeviceType = UnityEngine.Rendering.GraphicsDeviceType; - -namespace UnityEditorInternal.VR -{ - internal class PlayerSettingsEditorVR - { - static class Styles - { - public static readonly GUIContent singlepassAndroidWarning = EditorGUIUtility.TrTextContent("Single Pass stereo rendering requires OpenGL ES 3. Please make sure that it's the first one listed under Graphics APIs."); - public static readonly GUIContent singlepassAndroidWarning2 = EditorGUIUtility.TrTextContent("Multi Pass will be used on Android devices that don't support Single Pass."); - public static readonly GUIContent singlePassInstancedWarning = EditorGUIUtility.TrTextContent("Single Pass Instanced is only supported on Windows. Multi Pass will be used on other platforms."); - - public static readonly GUIContent[] kDefaultStereoRenderingPaths = - { - EditorGUIUtility.TrTextContent("Multi Pass"), - EditorGUIUtility.TrTextContent("Single Pass"), - EditorGUIUtility.TrTextContent("Single Pass Instanced (Preview)") - }; - - public static readonly GUIContent[] kMultiviewStereoRenderingPaths = - { - EditorGUIUtility.TrTextContent("Multi Pass"), - EditorGUIUtility.TrTextContent("Single Pass (Preview)"), - }; - - public static readonly GUIContent xrSettingsTitle = EditorGUIUtility.TrTextContent("XR Settings"); - - public static readonly GUIContent supportedCheckbox = EditorGUIUtility.TrTextContent("Virtual Reality Supported"); - public static readonly GUIContent listHeader = EditorGUIUtility.TrTextContent("Virtual Reality SDKs"); - public static readonly GUIContent stereo360CaptureCheckbox = EditorGUIUtility.TrTextContent("360 Stereo Capture"); - } - - private PlayerSettingsEditor m_Settings; - - private Dictionary m_AllVRDevicesForBuildTarget = new Dictionary(); - private Dictionary m_VRDeviceActiveUI = new Dictionary(); - - private Dictionary m_MapVRDeviceKeyToUIString = new Dictionary(); - private Dictionary m_MapVRUIStringToDeviceKey = new Dictionary(); - - private Dictionary m_CustomOptions = new Dictionary(); - private SerializedProperty m_StereoRenderingPath; - - private SerializedProperty m_AndroidEnableTango; - private SerializedProperty m_Enable360StereoCapture; - - private bool m_InstallsRequired = false; - private bool m_VuforiaInstalled = false; - - internal int GUISectionIndex { get; set; } - - public PlayerSettingsEditorVR(PlayerSettingsEditor settingsEditor) - { - m_Settings = settingsEditor; - m_StereoRenderingPath = m_Settings.serializedObject.FindProperty("m_StereoRenderingPath"); - - m_AndroidEnableTango = m_Settings.FindPropertyAssert("AndroidEnableTango"); - - SerializedProperty property = m_Settings.serializedObject.FindProperty("vrSettings"); - if (property != null) - m_Enable360StereoCapture = property.FindPropertyRelative("enable360StereoCapture"); - } - - private void RefreshVRDeviceList(BuildTargetGroup targetGroup) - { - VRDeviceInfoEditor[] deviceInfos = VREditor.GetAllVRDeviceInfo(targetGroup); - deviceInfos = deviceInfos.OrderBy(d => d.deviceNameUI).ToArray(); - m_AllVRDevicesForBuildTarget[targetGroup] = deviceInfos; - - for (int i = 0; i < deviceInfos.Length; ++i) - { - VRDeviceInfoEditor deviceInfo = deviceInfos[i]; - m_MapVRDeviceKeyToUIString[deviceInfo.deviceNameKey] = deviceInfo.deviceNameUI; - m_MapVRUIStringToDeviceKey[deviceInfo.deviceNameUI] = deviceInfo.deviceNameKey; - - // Create custom UI options if they exist for this sdk - VRCustomOptions customOptions; - if (!m_CustomOptions.TryGetValue(deviceInfo.deviceNameKey, out customOptions)) - { - Type optionsType = Type.GetType("UnityEditorInternal.VR.VRCustomOptions" + deviceInfo.deviceNameKey, false, true); - if (optionsType != null) - { - customOptions = (VRCustomOptions)Activator.CreateInstance(optionsType); - } - else - { - customOptions = new VRCustomOptionsNone(); - } - customOptions.Initialize(m_Settings.serializedObject); - m_CustomOptions.Add(deviceInfo.deviceNameKey, customOptions); - } - } - } - - internal bool TargetGroupSupportsVirtualReality(BuildTargetGroup targetGroup) - { - if (!m_AllVRDevicesForBuildTarget.ContainsKey(targetGroup)) - { - RefreshVRDeviceList(targetGroup); - } - - VRDeviceInfoEditor[] supportedDevices = m_AllVRDevicesForBuildTarget[targetGroup]; - - return supportedDevices.Length > 0; - } - - internal bool TargetGroupSupportsAugmentedReality(BuildTargetGroup targetGroup) - { - return TargetGroupSupportsTango(targetGroup) || - TargetGroupSupportsVuforia(targetGroup); - } - - internal void XRSectionGUI(BuildTargetGroup targetGroup, int sectionIndex) - { - GUISectionIndex = sectionIndex; - - if (!TargetGroupSupportsVirtualReality(targetGroup) && !TargetGroupSupportsAugmentedReality(targetGroup)) - return; - - if (VREditor.IsDeviceListDirty(targetGroup)) - { - VREditor.ClearDeviceListDirty(targetGroup); - m_VRDeviceActiveUI[targetGroup].list = VREditor.GetVREnabledDevicesOnTargetGroup(targetGroup); - } - - // Check to see if any devices require an install and need their GUI hidden - CheckDevicesRequireInstall(targetGroup); - - if (m_Settings.BeginSettingsBox(sectionIndex, Styles.xrSettingsTitle)) - { - if (EditorApplication.isPlaying) - { - EditorGUILayout.HelpBox("Changing XRSettings in not allowed in play mode.", MessageType.Info); - } - - using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) // switching VR flags in play mode is not supported - { - DevicesGUI(targetGroup); - - ErrorOnVRDeviceIncompatibility(targetGroup); - - SinglePassStereoGUI(targetGroup, m_StereoRenderingPath); - - TangoGUI(targetGroup); - - VuforiaGUI(targetGroup); - - Stereo360CaptureGUI(targetGroup); - - ErrorOnARDeviceIncompatibility(targetGroup); - } - - InstallGUI(targetGroup); - } - m_Settings.EndSettingsBox(); - } - - private void DevicesGUI(BuildTargetGroup targetGroup) - { - if (!TargetGroupSupportsVirtualReality(targetGroup)) - return; - - bool vrSupported = VREditor.GetVREnabledOnTargetGroup(targetGroup); - - EditorGUI.BeginChangeCheck(); - vrSupported = EditorGUILayout.Toggle(Styles.supportedCheckbox, vrSupported); - if (EditorGUI.EndChangeCheck()) - { - VREditor.SetVREnabledOnTargetGroup(targetGroup, vrSupported); - } - - if (vrSupported) - { - VRDevicesGUIOneBuildTarget(targetGroup); - } - } - - private void InstallGUI(BuildTargetGroup targetGroup) - { - if (!m_InstallsRequired) - return; - - EditorGUILayout.Space(); - GUILayout.Label("XR Support Installers", EditorStyles.boldLabel); - EditorGUI.indentLevel++; - - if (!m_VuforiaInstalled) - { - if (EditorGUILayout.LinkLabel("Vuforia Augmented Reality")) - { - string downloadUrl = BuildPlayerWindow.GetPlaybackEngineDownloadURL("Vuforia-AR"); - Application.OpenURL(downloadUrl); - } - } - - EditorGUI.indentLevel--; - EditorGUILayout.Space(); - } - - private void CheckDevicesRequireInstall(BuildTargetGroup targetGroup) - { - // Reset - m_InstallsRequired = false; - - if (!m_VuforiaInstalled) - { - VRDeviceInfoEditor[] deviceInfos = VREditor.GetAllVRDeviceInfo(targetGroup); - - for (int i = 0; i < deviceInfos.Length; ++i) - { - if (deviceInfos[i].deviceNameKey.ToLower() == "vuforia") - { - m_VuforiaInstalled = true; - break; - } - } - - if (!m_VuforiaInstalled) - m_InstallsRequired = true; - } - } - - // Keep these in sync with BuildTargetPlatformSpecific.cpp - private static bool DoesBuildTargetSupportSinglePassStereoRendering(BuildTargetGroup targetGroup) - { - switch (targetGroup) - { - case BuildTargetGroup.Standalone: - case BuildTargetGroup.PS4: - case BuildTargetGroup.WSA: - case BuildTargetGroup.Android: - return true; - default: - return false; - } - } - - // Keep these in sync with BuildTargetPlatformSpecific.cpp - private static bool DoesBuildTargetSupportStereoInstancingRendering(BuildTargetGroup targetGroup) - { - switch (targetGroup) - { - case BuildTargetGroup.Standalone: - case BuildTargetGroup.PS4: - case BuildTargetGroup.WSA: - return true; - default: - return false; - } - } - - // Keep these in sync with BuildTargetPlatformSpecific.cpp - private static bool DoesBuildTargetSupportStereoMultiviewRendering(BuildTargetGroup targetGroup) - { - switch (targetGroup) - { - case BuildTargetGroup.Android: - return true; - default: - return false; - } - } - - // Keep these in sync with BuildTargetPlatformSpecific.cpp - private static bool DoesBuildTargetSupportStereo360Capture(BuildTargetGroup targetGroup) - { - switch (targetGroup) - { - case BuildTargetGroup.Standalone: - return true; - default: - return false; - } - } - - private static GUIContent[] GetStereoRenderingPaths(BuildTargetGroup targetGroup) - { - return DoesBuildTargetSupportStereoMultiviewRendering(targetGroup) ? Styles.kMultiviewStereoRenderingPaths : Styles.kDefaultStereoRenderingPaths; - } - - private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedProperty stereoRenderingPath) - { - if (!PlayerSettings.virtualRealitySupported) - return; - - bool supportsSinglePass = DoesBuildTargetSupportSinglePassStereoRendering(targetGroup); - bool supportsSinglePassInstanced = DoesBuildTargetSupportStereoInstancingRendering(targetGroup); - - // populate the dropdown with the valid options based on target platform. - int validStereoRenderingOptionsCount = 1 + (supportsSinglePass ? 1 : 0) + (supportsSinglePassInstanced ? 1 : 0); - var validStereoRenderingPaths = new GUIContent[validStereoRenderingOptionsCount]; - var validStereoRenderingValues = new int[validStereoRenderingOptionsCount]; - - GUIContent[] stereoRenderingPaths = GetStereoRenderingPaths(targetGroup); - - int addedStereoRenderingOptionsCount = 0; - validStereoRenderingPaths[addedStereoRenderingOptionsCount] = stereoRenderingPaths[(int)StereoRenderingPath.MultiPass]; - validStereoRenderingValues[addedStereoRenderingOptionsCount++] = (int)StereoRenderingPath.MultiPass; - - if (supportsSinglePass) - { - validStereoRenderingPaths[addedStereoRenderingOptionsCount] = stereoRenderingPaths[(int)StereoRenderingPath.SinglePass]; - validStereoRenderingValues[addedStereoRenderingOptionsCount++] = (int)StereoRenderingPath.SinglePass; - } - - if (supportsSinglePassInstanced) - { - validStereoRenderingPaths[addedStereoRenderingOptionsCount] = stereoRenderingPaths[(int)StereoRenderingPath.Instancing]; - validStereoRenderingValues[addedStereoRenderingOptionsCount++] = (int)StereoRenderingPath.Instancing; - } - - // setup fallbacks - if (!supportsSinglePassInstanced && (stereoRenderingPath.intValue == (int)StereoRenderingPath.Instancing)) - stereoRenderingPath.intValue = (int)StereoRenderingPath.SinglePass; - - if (!supportsSinglePass && (stereoRenderingPath.intValue == (int)StereoRenderingPath.SinglePass)) - stereoRenderingPath.intValue = (int)StereoRenderingPath.MultiPass; - - EditorGUILayout.IntPopup(stereoRenderingPath, validStereoRenderingPaths, validStereoRenderingValues, EditorGUIUtility.TrTextContent("Stereo Rendering Method*")); - - if ((stereoRenderingPath.intValue == (int)StereoRenderingPath.SinglePass) && (targetGroup == BuildTargetGroup.Android)) - { - var apisAndroid = PlayerSettings.GetGraphicsAPIs(BuildTarget.Android); - if ((apisAndroid.Length > 0) && (apisAndroid[0] == GraphicsDeviceType.OpenGLES3)) - { - EditorGUILayout.HelpBox(Styles.singlepassAndroidWarning2.text, MessageType.Info); - } - else - { - EditorGUILayout.HelpBox(Styles.singlepassAndroidWarning.text, MessageType.Warning); - } - } - else if ((stereoRenderingPath.intValue == (int)StereoRenderingPath.Instancing) && (targetGroup == BuildTargetGroup.Standalone)) - { - EditorGUILayout.HelpBox(Styles.singlePassInstancedWarning.text, MessageType.Warning); - } - } - - private void Stereo360CaptureGUI(BuildTargetGroup targetGroup) - { - if (DoesBuildTargetSupportStereo360Capture(targetGroup)) - EditorGUILayout.PropertyField(m_Enable360StereoCapture, Styles.stereo360CaptureCheckbox); - } - - private void AddVRDeviceMenuSelected(object userData, string[] options, int selected) - { - BuildTargetGroup target = (BuildTargetGroup)userData; - var enabledDevices = VREditor.GetVREnabledDevicesOnTargetGroup(target).ToList(); - - string deviceKey; - if (!m_MapVRUIStringToDeviceKey.TryGetValue(options[selected], out deviceKey)) - deviceKey = options[selected]; - - enabledDevices.Add(deviceKey); - - ApplyChangedVRDeviceList(target, enabledDevices.ToArray()); - } - - private void AddVRDeviceElement(BuildTargetGroup target, Rect rect, ReorderableList list) - { - VRDeviceInfoEditor[] allDevices = m_AllVRDevicesForBuildTarget[target]; - - var enabledDevices = VREditor.GetVREnabledDevicesOnTargetGroup(target).ToList(); - - var names = allDevices.Select(d => d.deviceNameUI).ToArray(); - var enabled = allDevices.Select(d => !enabledDevices.Any(enabledDeviceName => d.deviceNameKey == enabledDeviceName)).ToArray(); - - EditorUtility.DisplayCustomMenu(rect, names, enabled, null, AddVRDeviceMenuSelected, target); - } - - private void RemoveVRDeviceElement(BuildTargetGroup target, ReorderableList list) - { - var devices = VREditor.GetVREnabledDevicesOnTargetGroup(target).ToList(); - devices.RemoveAt(list.index); - ApplyChangedVRDeviceList(target, devices.ToArray()); - } - - private void ReorderVRDeviceElement(BuildTargetGroup target, ReorderableList list) - { - var devices = list.list.Cast().ToArray(); - - ApplyChangedVRDeviceList(target, devices); - } - - private void ApplyChangedVRDeviceList(BuildTargetGroup target, string[] devices) - { - if (!m_VRDeviceActiveUI.ContainsKey(target)) - return; - - if (target == BuildTargetGroup.iOS) - { - // Set a sensible default if cardboard is enabled, as it uses that feature and - // the setting is mandatory on iOS - if (devices.Contains("cardboard") && PlayerSettings.iOS.cameraUsageDescription == "") - { - PlayerSettings.iOS.cameraUsageDescription = "Used to scan QR codes"; - } - } - - VREditor.SetVREnabledDevicesOnTargetGroup(target, devices); - m_VRDeviceActiveUI[target].list = devices; - } - - private void DrawVRDeviceElement(BuildTargetGroup target, Rect rect, int index, bool selected, bool focused) - { - string name = (string)m_VRDeviceActiveUI[target].list[index]; - - string uiName; - if (!m_MapVRDeviceKeyToUIString.TryGetValue(name, out uiName)) - uiName = name + " (missing from build)"; - - VRCustomOptions customOptions; - if (m_CustomOptions.TryGetValue(name, out customOptions)) - { - // Draw the foldout if we have extra options - if (!(customOptions is VRCustomOptionsNone)) - { - Rect foldoutRect = new Rect(rect); - foldoutRect.width = EditorStyles.foldout.border.left; - foldoutRect.height = EditorStyles.foldout.border.top; - bool oldHierarchyMode = EditorGUIUtility.hierarchyMode; - EditorGUIUtility.hierarchyMode = false; - customOptions.IsExpanded = EditorGUI.Foldout(foldoutRect, customOptions.IsExpanded, "", false, EditorStyles.foldout); - EditorGUIUtility.hierarchyMode = oldHierarchyMode; - } - } - - // Draw - rect.xMin += EditorStyles.foldout.border.left; - GUI.Label(rect, uiName, EditorStyles.label); - rect.y += EditorGUIUtility.singleLineHeight + EditorGUI.kControlVerticalSpacing; - - if (customOptions != null && customOptions.IsExpanded) - { - customOptions.Draw(rect); - } - } - - private float GetVRDeviceElementHeight(BuildTargetGroup target, int index) - { - ReorderableList list = (ReorderableList)m_VRDeviceActiveUI[target]; - string name = (string)list.list[index]; - - float customOptionsHeight = 0.0f; - VRCustomOptions customOptions; - if (m_CustomOptions.TryGetValue(name, out customOptions)) - { - customOptionsHeight = customOptions.IsExpanded ? customOptions.GetHeight() + EditorGUI.kControlVerticalSpacing : 0.0f; - } - - return list.elementHeight + customOptionsHeight; - } - - private void SelectVRDeviceElement(BuildTargetGroup target, ReorderableList list) - { - string name = (string)m_VRDeviceActiveUI[target].list[list.index]; - VRCustomOptions customOptions; - if (m_CustomOptions.TryGetValue(name, out customOptions)) - { - customOptions.IsExpanded = false; - } - } - - private bool GetVRDeviceElementIsInList(BuildTargetGroup target, string deviceName) - { - var enabledDevices = VREditor.GetVREnabledDevicesOnTargetGroup(target); - - if (enabledDevices.Contains(deviceName)) - return true; - - return false; - } - - private void VRDevicesGUIOneBuildTarget(BuildTargetGroup targetGroup) - { - // create reorderable list for this target if needed - if (!m_VRDeviceActiveUI.ContainsKey(targetGroup)) - { - var rlist = new ReorderableList(VREditor.GetVREnabledDevicesOnTargetGroup(targetGroup), typeof(VRDeviceInfoEditor), true, true, true, true); - rlist.onAddDropdownCallback = (rect, list) => AddVRDeviceElement(targetGroup, rect, list); - rlist.onRemoveCallback = (list) => RemoveVRDeviceElement(targetGroup, list); - rlist.onReorderCallback = (list) => ReorderVRDeviceElement(targetGroup, list); - rlist.drawElementCallback = (rect, index, isActive, isFocused) => DrawVRDeviceElement(targetGroup, rect, index, isActive, isFocused); - rlist.drawHeaderCallback = (rect) => GUI.Label(rect, Styles.listHeader, EditorStyles.label); - rlist.elementHeightCallback = (index) => GetVRDeviceElementHeight(targetGroup, index); - rlist.onSelectCallback = (list) => SelectVRDeviceElement(targetGroup, list); - m_VRDeviceActiveUI.Add(targetGroup, rlist); - } - - m_VRDeviceActiveUI[targetGroup].DoLayoutList(); - - if (m_VRDeviceActiveUI[targetGroup].list.Count == 0) - { - EditorGUILayout.HelpBox("Must add at least one Virtual Reality SDK.", MessageType.Warning); - } - } - - private void ErrorOnVRDeviceIncompatibility(BuildTargetGroup targetGroup) - { - if (!PlayerSettings.GetVirtualRealitySupported(targetGroup)) - return; - - if (targetGroup == BuildTargetGroup.Android) - { - List enabledDevices = VREditor.GetVREnabledDevicesOnTargetGroup(targetGroup).ToList(); - if (enabledDevices.Contains("Oculus") && enabledDevices.Contains("daydream")) - { - EditorGUILayout.HelpBox("To avoid initialization conflicts on devices which support both Daydream and Oculus based VR, build separate APKs with different package names, targeting only the Daydream or Oculus VR SDK in the respective APK.", MessageType.Warning); - } - } - } - - private void ErrorOnARDeviceIncompatibility(BuildTargetGroup targetGroup) - { - if (targetGroup == BuildTargetGroup.Android) - { - if (PlayerSettings.Android.androidTangoEnabled && PlayerSettings.GetPlatformVuforiaEnabled(targetGroup)) - { - EditorGUILayout.HelpBox("Both ARCore and Vuforia XR Device support cannot be selected at the same time. Please select only one XR Device that will manage the Android device.", MessageType.Error); - } - } - } - - internal bool TargetGroupSupportsTango(BuildTargetGroup targetGroup) - { - return targetGroup == BuildTargetGroup.Android; - } - - internal bool TargetGroupSupportsVuforia(BuildTargetGroup targetGroup) - { - return targetGroup == BuildTargetGroup.Standalone || - targetGroup == BuildTargetGroup.Android || - targetGroup == BuildTargetGroup.iOS || - targetGroup == BuildTargetGroup.WSA; - } - - internal void TangoGUI(BuildTargetGroup targetGroup) - { - if (!TargetGroupSupportsTango(targetGroup)) - return; - - // Google Tango settings - EditorGUILayout.PropertyField(m_AndroidEnableTango, EditorGUIUtility.TrTextContent("ARCore Supported")); - - if (PlayerSettings.Android.androidTangoEnabled) - { - EditorGUI.indentLevel++; - - if ((int)PlayerSettings.Android.minSdkVersion < 24) - { - GUIContent tangoAndroidWarning = EditorGUIUtility.TrTextContent("ARCore requires 'Minimum API Level' to be at least Android 7.0"); - EditorGUILayout.HelpBox(tangoAndroidWarning.text, MessageType.Warning); - } - EditorGUI.indentLevel--; - } - } - - internal void VuforiaGUI(BuildTargetGroup targetGroup) - { - if (!TargetGroupSupportsVuforia(targetGroup) || !m_VuforiaInstalled) - return; - - // Disable toggle when Vuforia is in the VRDevice list and VR Supported == true - bool vuforiaEnabled; - var shouldDisableScope = VREditor.GetVREnabledOnTargetGroup(targetGroup) && GetVRDeviceElementIsInList(targetGroup, "Vuforia"); - using (new EditorGUI.DisabledScope(shouldDisableScope)) - { - if (shouldDisableScope && !PlayerSettings.GetPlatformVuforiaEnabled(targetGroup)) // Force Vuforia AR on if Vuforia is in the VRDevice List - PlayerSettings.SetPlatformVuforiaEnabled(targetGroup, true); - - vuforiaEnabled = PlayerSettings.GetPlatformVuforiaEnabled(targetGroup); - - EditorGUI.BeginChangeCheck(); - vuforiaEnabled = EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Vuforia Augmented Reality Supported"), vuforiaEnabled); - if (EditorGUI.EndChangeCheck()) - { - PlayerSettings.SetPlatformVuforiaEnabled(targetGroup, vuforiaEnabled); - } - } - - if (shouldDisableScope) - { - EditorGUILayout.HelpBox("Vuforia Augmented Reality is required when using the Vuforia Virtual Reality SDK.", MessageType.Info); - } - } - } -} diff --git a/Editor/Src/VR/Mono/VRCustomOptions.cs b/Editor/Src/VR/Mono/VRCustomOptions.cs deleted file mode 100644 index 1410549b7b..0000000000 --- a/Editor/Src/VR/Mono/VRCustomOptions.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEngine; -using UnityEditor; - -namespace UnityEditorInternal.VR -{ - internal abstract class VRCustomOptions - { - SerializedProperty editorSettings; - SerializedProperty playerSettings; - - internal SerializedProperty FindPropertyAssert(string name) - { - SerializedProperty property = null; - if (editorSettings == null && playerSettings == null) - { - Debug.LogError("No existing VR settings. Failed to find:" + name); - } - else - { - bool found = false; - if (editorSettings != null) - { - property = editorSettings.FindPropertyRelative(name); - if (property != null) - found = true; - } - if (!found && playerSettings != null) - { - property = playerSettings.FindPropertyRelative(name); - if (property != null) - found = true; - } - if (!found) - { - Debug.LogError("Failed to find property:" + name); - } - } - return property; - } - - public bool IsExpanded { get; set; } - public virtual void Initialize(SerializedObject settings) - { - Initialize(settings, ""); - } - - public virtual void Initialize(SerializedObject settings, string propertyName) - { - editorSettings = settings.FindProperty("vrEditorSettings"); - if (editorSettings != null && !string.IsNullOrEmpty(propertyName)) - { - editorSettings = editorSettings.FindPropertyRelative(propertyName); - } - - playerSettings = settings.FindProperty("vrSettings"); - if (playerSettings != null && !string.IsNullOrEmpty(propertyName)) - { - playerSettings = playerSettings.FindPropertyRelative(propertyName); - } - } - - abstract public Rect Draw(Rect rect); - abstract public float GetHeight(); - } - - internal class VRCustomOptionsNone : VRCustomOptions - { - public override Rect Draw(Rect rect) { return rect; } - public override float GetHeight() { return 0.0f; } - } -} diff --git a/Editor/Src/VR/Mono/VREditor.cs b/Editor/Src/VR/Mono/VREditor.cs deleted file mode 100644 index b43f4464ea..0000000000 --- a/Editor/Src/VR/Mono/VREditor.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditor; -using UnityEditorInternal.VR; - -namespace UnityEditorInternal.VR -{ - partial class VREditor - { - private static Dictionary dirtyDeviceLists = new Dictionary(); - - public static bool IsDeviceListDirty(BuildTargetGroup targetGroup) - { - if (dirtyDeviceLists.ContainsKey(targetGroup)) - return dirtyDeviceLists[targetGroup]; - - return false; - } - - private static void SetDeviceListDirty(BuildTargetGroup targetGroup) - { - if (dirtyDeviceLists.ContainsKey(targetGroup)) - dirtyDeviceLists[targetGroup] = true; - else - dirtyDeviceLists.Add(targetGroup, true); - } - - public static void ClearDeviceListDirty(BuildTargetGroup targetGroup) - { - if (dirtyDeviceLists.ContainsKey(targetGroup)) - dirtyDeviceLists[targetGroup] = false; - } - - public static VRDeviceInfoEditor[] GetEnabledVRDeviceInfo(BuildTargetGroup targetGroup) - { - string[] enabledVRDevices = GetVREnabledDevicesOnTargetGroup(targetGroup); - return GetAllVRDeviceInfo(targetGroup).Where(d => enabledVRDevices.Contains(d.deviceNameKey)).ToArray(); - } - - public static VRDeviceInfoEditor[] GetEnabledVRDeviceInfo(BuildTarget target) - { - string[] enabledVRDevices = GetVREnabledDevicesOnTarget(target); - return GetAllVRDeviceInfoByTarget(target).Where(d => enabledVRDevices.Contains(d.deviceNameKey)).ToArray(); - } - - public static bool IsVRDeviceEnabledForBuildTarget(BuildTarget target, string deviceName) - { - string[] vrDevices = GetVREnabledDevicesOnTarget(target); - foreach (string device in vrDevices) - { - if (device == deviceName) - return true; - } - return false; - } - - public static string[] GetAvailableVirtualRealitySDKs(BuildTargetGroup targetGroup) - { - VRDeviceInfoEditor[] deviceInfos = GetAllVRDeviceInfo(targetGroup); - string[] sdks = new string[deviceInfos.Length]; - - for (int i = 0; i < deviceInfos.Length; ++i) - { - sdks[i] = deviceInfos[i].deviceNameKey; - } - - return sdks; - } - - // APIs Exposed to PlayerSettings for Scripting Reference - public static string[] GetVirtualRealitySDKs(BuildTargetGroup targetGroup) - { - return GetVREnabledDevicesOnTargetGroup(targetGroup); - } - - public static void SetVirtualRealitySDKs(BuildTargetGroup targetGroup, string[] sdks) - { - SetVREnabledDevicesOnTargetGroup(targetGroup, sdks); - SetDeviceListDirty(targetGroup); - } - } -} - -namespace UnityEditor -{ - partial class PlayerSettings - { - public static string[] GetAvailableVirtualRealitySDKs(BuildTargetGroup targetGroup) - { - return VREditor.GetAvailableVirtualRealitySDKs(targetGroup); - } - - public static bool GetVirtualRealitySupported(BuildTargetGroup targetGroup) - { - return VREditor.GetVREnabledOnTargetGroup(targetGroup); - } - - public static void SetVirtualRealitySupported(BuildTargetGroup targetGroup, bool value) - { - VREditor.SetVREnabledOnTargetGroup(targetGroup, value); - } - - public static string[] GetVirtualRealitySDKs(BuildTargetGroup targetGroup) - { - return VREditor.GetVirtualRealitySDKs(targetGroup); - } - - public static void SetVirtualRealitySDKs(BuildTargetGroup targetGroup, string[] sdks) - { - VREditor.SetVirtualRealitySDKs(targetGroup, sdks); - } - } -} diff --git a/Editor/Src/VR/Mono/VRModule.cs b/Editor/Src/VR/Mono/VRModule.cs deleted file mode 100644 index 16749cb2a3..0000000000 --- a/Editor/Src/VR/Mono/VRModule.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using UnityEngine; -using UnityEditor; - -namespace UnityEditorInternal.VR -{ - public class VRModule - { - private static bool IsTargetingCardboardOnIOS(BuildTarget target) - { - return PlayerSettings.virtualRealitySupported && target == BuildTarget.iOS && - UnityEditorInternal.VR.VREditor.IsVRDeviceEnabledForBuildTarget(target, "cardboard"); - } - - public static void SetupBuildSettings(BuildTarget target, int osVerMajor) - { - if (IsTargetingCardboardOnIOS(target) && osVerMajor < 8) - { - Debug.LogWarning(string.Format("Deployment target version is set to {0}, but Cardboard supports only versions starting from 8.0.", osVerMajor)); - } - } - - public static bool ShouldInjectVRDependenciesForBuildTarget(BuildTarget target) - { - if (!PlayerSettings.virtualRealitySupported) - return false; - - bool shouldInjectForTarget = false; - var targetGroup = UnityEditor.BuildPipeline.GetBuildTargetGroup(target); - - switch (targetGroup) - { - case BuildTargetGroup.iOS: - shouldInjectForTarget = VREditor.IsVRDeviceEnabledForBuildTarget(target, "cardboard"); - break; - - default: - shouldInjectForTarget = false; - break; - } - - return shouldInjectForTarget; - } - } -} diff --git a/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs b/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs deleted file mode 100644 index e5859c2977..0000000000 --- a/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using UnityEditor; -using UnityEngine; -using System.Linq; - - -namespace UnityEditorInternal.VR -{ - internal class VRCustomOptionsWindowsMR : VRCustomOptions - { - static GUIContent[] s_DepthOptions = - { - EditorGUIUtility.TrTextContent("16-bit depth"), - EditorGUIUtility.TrTextContent("24-bit depth") - }; - - static GUIContent s_DepthFormatLabel = EditorGUIUtility.TrTextContent("Depth Format"); - static GUIContent s_DepthBufferSharingLabel = EditorGUIUtility.TrTextContent("Enable Depth Buffer Sharing"); - - SerializedProperty m_DepthFormat; - SerializedProperty m_DepthBufferSharingEnabled; - - public override void Initialize(SerializedObject settings, string propertyName) - { - base.Initialize(settings, "hololens"); - m_DepthFormat = FindPropertyAssert("depthFormat"); - m_DepthBufferSharingEnabled = FindPropertyAssert("depthBufferSharingEnabled"); - } - - public override Rect Draw(Rect rect) - { - rect.y += EditorGUIUtility.standardVerticalSpacing; - rect.height = EditorGUIUtility.singleLineHeight; - - GUIContent label = EditorGUI.BeginProperty(rect, s_DepthFormatLabel, m_DepthFormat); - EditorGUI.BeginChangeCheck(); - int intValue = EditorGUI.Popup(rect, label, m_DepthFormat.intValue, s_DepthOptions); - if (EditorGUI.EndChangeCheck()) - { - m_DepthFormat.intValue = intValue; - } - EditorGUI.EndProperty(); - - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - - label = EditorGUI.BeginProperty(rect, s_DepthBufferSharingLabel, m_DepthBufferSharingEnabled); - EditorGUI.BeginChangeCheck(); - bool depthBufferSharingEnabled = EditorGUI.Toggle(rect, s_DepthBufferSharingLabel, m_DepthBufferSharingEnabled.boolValue); - if (EditorGUI.EndChangeCheck()) - { - m_DepthBufferSharingEnabled.boolValue = depthBufferSharingEnabled; - } - EditorGUI.EndProperty(); - - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - - return rect; - } - - public override float GetHeight() - { - return EditorGUIUtility.singleLineHeight * 2.0f; - } - } -} diff --git a/Editor/Src/VR/ScriptBindings/VREditor.bindings.cs b/Editor/Src/VR/ScriptBindings/VREditor.bindings.cs deleted file mode 100644 index 7e52bbb98b..0000000000 --- a/Editor/Src/VR/ScriptBindings/VREditor.bindings.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor; -using System.Runtime.InteropServices; -using UnityEngine.Bindings; -using UnityEngine.Scripting; - -namespace UnityEditorInternal.VR -{ - [RequiredByNativeCode] - [StructLayout(LayoutKind.Sequential)] - [NativeType(CodegenOptions = CodegenOptions.Custom)] - public partial struct VRDeviceInfoEditor - { - public string deviceNameKey; - public string deviceNameUI; - public string externalPluginName; - public bool supportsEditorMode; - public bool inListByDefault; - } - - [NativeHeader("Editor/Src/VR/VREditor.bindings.h")] - public sealed partial class VREditor - { - extern public static VRDeviceInfoEditor[] GetAllVRDeviceInfo(BuildTargetGroup targetGroup); - - extern public static VRDeviceInfoEditor[] GetAllVRDeviceInfoByTarget(BuildTarget target); - - extern public static bool GetVREnabledOnTargetGroup(BuildTargetGroup targetGroup); - - extern public static void SetVREnabledOnTargetGroup(BuildTargetGroup targetGroup, bool value); - - extern public static string[] GetVREnabledDevicesOnTargetGroup(BuildTargetGroup targetGroup); - - extern public static string[] GetVREnabledDevicesOnTarget(BuildTarget target); - - extern public static void SetVREnabledDevicesOnTargetGroup(BuildTargetGroup targetGroup, string[] devices); - } -} - -namespace UnityEditorInternal -{ - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] - internal class PlayerSettingsOculus - { - public static extern bool sharedDepthBuffer - { - [NativeMethod("GetOculusSharedDepthBufferEnabled")] - get; - [NativeMethod("SetOculusSharedDepthBufferEnabled")] - set; - } - - public static extern bool dashSupport - { - [NativeMethod("GetOculusDashSupportEnabled")] - get; - [NativeMethod("SetOculusDashSupportEnabled")] - set; - } - } - - - [NativeHeader("Runtime/Misc/PlayerSettings.h")] - [StaticAccessor("GetPlayerSettings()", StaticAccessorType.Dot)] - internal class PlayerSettings360StereoCapture - { - public static extern bool enable360StereoCapture - { - get; - set; - } - } -} - -// When Nested classes is supported for bindings, the above Internal only class should be removed and -// the below class should be updated with the proper PlayerSettings calls. -namespace UnityEditor -{ - partial class PlayerSettings - { - public class VROculus - { - public static bool sharedDepthBuffer - { - get { return UnityEditorInternal.PlayerSettingsOculus.sharedDepthBuffer; } - set { UnityEditorInternal.PlayerSettingsOculus.sharedDepthBuffer = value; } - } - public static bool dashSupport - { - get { return UnityEditorInternal.PlayerSettingsOculus.dashSupport; } - set { UnityEditorInternal.PlayerSettingsOculus.dashSupport = value; } - } - } - - public static bool enable360StereoCapture - { - get { return UnityEditorInternal.PlayerSettings360StereoCapture.enable360StereoCapture; } - set { UnityEditorInternal.PlayerSettings360StereoCapture.enable360StereoCapture = value; } - } - } -} diff --git a/Extensions/Networking/Weaver/AssemblyInfo.cs b/Extensions/Networking/Weaver/AssemblyInfo.cs deleted file mode 100644 index da8f1d8e11..0000000000 --- a/Extensions/Networking/Weaver/AssemblyInfo.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Reflection; -using System.Runtime.CompilerServices; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. - -[assembly: AssemblyTitle("Unity.UNetWeaver")] -[assembly: AssemblyDescription("UNET assembly post processor for code generation.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Unity Technologies")] -[assembly: AssemblyProduct("Unity.UNetWeaver")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: InternalsVisibleTo("Assembly-CSharp-Editor-testable")] - -// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". -// The form "{Major}.{Minor}.*" will automatically update the build and revision, -// and "{Major}.{Minor}.{Build}.*" will update just the revision. - -[assembly: AssemblyVersion("1.0.*")] - -// The following attributes are used to specify the signing key for the assembly, -// if desired. See the Mono documentation for more information about signing. - -//[assembly: AssemblyDelaySign(false)] -//[assembly: AssemblyKeyFile("")] diff --git a/Extensions/Networking/Weaver/Helpers.cs b/Extensions/Networking/Weaver/Helpers.cs deleted file mode 100644 index 8a6151310c..0000000000 --- a/Extensions/Networking/Weaver/Helpers.cs +++ /dev/null @@ -1,231 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Cecil.Mdb; -using Mono.Cecil.Pdb; - -namespace Unity.UNetWeaver -{ - class Helpers - { - // This code is taken from SerializationWeaver - - class AddSearchDirectoryHelper - { - delegate void AddSearchDirectoryDelegate(string directory); - readonly AddSearchDirectoryDelegate _addSearchDirectory; - - public AddSearchDirectoryHelper(IAssemblyResolver assemblyResolver) - { - // reflection is used because IAssemblyResolver doesn't implement AddSearchDirectory but both DefaultAssemblyResolver and NuGetAssemblyResolver do - var addSearchDirectory = assemblyResolver.GetType().GetMethod("AddSearchDirectory", BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(string) }, null); - if (addSearchDirectory == null) - throw new Exception("Assembly resolver doesn't implement AddSearchDirectory method."); - _addSearchDirectory = (AddSearchDirectoryDelegate)Delegate.CreateDelegate(typeof(AddSearchDirectoryDelegate), assemblyResolver, addSearchDirectory); - } - - public void AddSearchDirectory(string directory) - { - _addSearchDirectory(directory); - } - } - - public static string UnityEngineDLLDirectoryName() - { - var directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase); - return directoryName != null ? directoryName.Replace(@"file:\", "") : null; - } - - public static ISymbolReaderProvider GetSymbolReaderProvider(string inputFile) - { - string nakedFileName = inputFile.Substring(0, inputFile.Length - 4); - if (File.Exists(nakedFileName + ".pdb")) - { - Console.WriteLine("Symbols will be read from " + nakedFileName + ".pdb"); - return new PdbReaderProvider(); - } - if (File.Exists(nakedFileName + ".dll.mdb")) - { - Console.WriteLine("Symbols will be read from " + nakedFileName + ".dll.mdb"); - return new MdbReaderProvider(); - } - Console.WriteLine("No symbols for " + inputFile); - return null; - } - - public static bool InheritsFromSyncList(TypeReference typeRef) - { - try - { - // value types cant inherit from SyncList - if (typeRef.IsValueType) - { - return false; - } - - foreach (var type in ResolveInheritanceHierarchy(typeRef)) - { - // only need to check for generic instances, as we're looking for SyncList - if (type.IsGenericInstance) - { - // resolves the instance type to it's generic type definition, for example SyncList to SyncList - var typeDef = type.Resolve(); - if (typeDef.HasGenericParameters && typeDef.FullName == Weaver.SyncListType.FullName) - { - return true; - } - } - } - } - catch - { - // sometimes this will fail if we reference a weird library that can't be resolved, so we just swallow that exception and return false - } - - return false; - } - - public static IEnumerable ResolveInheritanceHierarchy(TypeReference type) - { - // for value types the hierarchy is pre-defined as " : System.ValueType : System.Object" - if (type.IsValueType) - { - yield return type; - yield return Weaver.valueTypeType; - yield return Weaver.objectType; - yield break; - } - - // resolve entire hierarchy from to System.Object - while (type != null && type.FullName != Weaver.objectType.FullName) - { - yield return type; - - try - { - var typeDef = type.Resolve(); - if (typeDef == null) - { - break; - } - else - { - type = typeDef.BaseType; - } - } - catch - { - // when calling type.Resolve() we can sometimes get an exception if some dependant library - // could not be loaded (for whatever reason) so just swallow it and break out of the loop - break; - } - } - - - yield return Weaver.objectType; - } - - public static string DestinationFileFor(string outputDir, string assemblyPath) - { - var fileName = Path.GetFileName(assemblyPath); - Debug.Assert(fileName != null, "fileName != null"); - - return Path.Combine(outputDir, fileName); - } - - public static string PrettyPrintType(TypeReference type) - { - // generic instances, such as List - if (type.IsGenericInstance) - { - var giType = (GenericInstanceType)type; - return giType.Name.Substring(0, giType.Name.Length - 2) + "<" + String.Join(", ", giType.GenericArguments.Select(PrettyPrintType).ToArray()) + ">"; - } - - // generic types, such as List - if (type.HasGenericParameters) - { - return type.Name.Substring(0, type.Name.Length - 2) + "<" + String.Join(", ", type.GenericParameters.Select(x => x.Name).ToArray()) + ">"; - } - - // non-generic type such as Int - return type.Name; - } - - public static ReaderParameters ReaderParameters(string assemblyPath, IEnumerable extraPaths, IAssemblyResolver assemblyResolver, string unityEngineDLLPath, string unityUNetDLLPath) - { - var parameters = new ReaderParameters(); - if (assemblyResolver == null) - assemblyResolver = new DefaultAssemblyResolver(); - var helper = new AddSearchDirectoryHelper(assemblyResolver); - helper.AddSearchDirectory(Path.GetDirectoryName(assemblyPath)); - helper.AddSearchDirectory(Helpers.UnityEngineDLLDirectoryName()); - helper.AddSearchDirectory(Path.GetDirectoryName(unityEngineDLLPath)); - helper.AddSearchDirectory(Path.GetDirectoryName(unityUNetDLLPath)); - if (extraPaths != null) - { - foreach (var path in extraPaths) - helper.AddSearchDirectory(path); - } - parameters.AssemblyResolver = assemblyResolver; - parameters.SymbolReaderProvider = GetSymbolReaderProvider(assemblyPath); - return parameters; - } - - public static WriterParameters GetWriterParameters(ReaderParameters readParams) - { - var writeParams = new WriterParameters(); - if (readParams.SymbolReaderProvider is PdbReaderProvider) - { - //Log("Will export symbols of pdb format"); - writeParams.SymbolWriterProvider = new PdbWriterProvider(); - } - else if (readParams.SymbolReaderProvider is MdbReaderProvider) - { - //Log("Will export symbols of mdb format"); - writeParams.SymbolWriterProvider = new MdbWriterProvider(); - } - return writeParams; - } - - public static TypeReference MakeGenericType(TypeReference self, params TypeReference[] arguments) - { - if (self.GenericParameters.Count != arguments.Length) - throw new ArgumentException(); - - var instance = new GenericInstanceType(self); - foreach (var argument in arguments) - instance.GenericArguments.Add(argument); - - return instance; - } - - // used to get a specialized method on a generic class, such as SyncList::HandleMsg() - public static MethodReference MakeHostInstanceGeneric(MethodReference self, params TypeReference[] arguments) - { - var reference = new MethodReference(self.Name, self.ReturnType, MakeGenericType(self.DeclaringType, arguments)) - { - HasThis = self.HasThis, - ExplicitThis = self.ExplicitThis, - CallingConvention = self.CallingConvention - }; - - foreach (var parameter in self.Parameters) - reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType)); - - foreach (var genericParameter in self.GenericParameters) - reference.GenericParameters.Add(new GenericParameter(genericParameter.Name, reference)); - - return reference; - } - } -} diff --git a/Extensions/Networking/Weaver/MessageClassProcessor.cs b/Extensions/Networking/Weaver/MessageClassProcessor.cs deleted file mode 100644 index 3819b19f07..0000000000 --- a/Extensions/Networking/Weaver/MessageClassProcessor.cs +++ /dev/null @@ -1,156 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using Mono.Cecil; -using Mono.Cecil.Cil; - -namespace Unity.UNetWeaver -{ - class MessageClassProcessor - { - TypeDefinition m_td; - - public MessageClassProcessor(TypeDefinition td) - { - Weaver.DLog(td, "MessageClassProcessor for " + td.Name); - m_td = td; - } - - public void Process() - { - Weaver.DLog(m_td, "MessageClassProcessor Start"); - - Weaver.ResetRecursionCount(); - - GenerateSerialization(); - if (Weaver.fail) - { - return; - } - - GenerateDeSerialization(); - Weaver.DLog(m_td, "MessageClassProcessor Done"); - } - - void GenerateSerialization() - { - Weaver.DLog(m_td, " GenerateSerialization"); - foreach (var m in m_td.Methods) - { - if (m.Name == "Serialize") - return; - } - - if (m_td.Fields.Count == 0) - { - return; - } - - // check for self-referencing types - foreach (var field in m_td.Fields) - { - if (field.FieldType.FullName == m_td.FullName) - { - Weaver.fail = true; - Log.Error("GenerateSerialization for " + m_td.Name + " [" + field.FullName + "]. [MessageBase] member cannot be self referencing."); - return; - } - } - - MethodDefinition serializeFunc = new MethodDefinition("Serialize", MethodAttributes.Public | - MethodAttributes.Virtual | - MethodAttributes.HideBySig, - Weaver.voidType); - - serializeFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType))); - ILProcessor serWorker = serializeFunc.Body.GetILProcessor(); - - foreach (var field in m_td.Fields) - { - if (field.IsStatic || field.IsPrivate || field.IsSpecialName) - continue; - - if (field.FieldType.Resolve().HasGenericParameters) - { - Weaver.fail = true; - Log.Error("GenerateSerialization for " + m_td.Name + " [" + field.FieldType + "/" + field.FieldType.FullName + "]. [MessageBase] member cannot have generic parameters."); - return; - } - - if (field.FieldType.Resolve().IsInterface) - { - Weaver.fail = true; - Log.Error("GenerateSerialization for " + m_td.Name + " [" + field.FieldType + "/" + field.FieldType.FullName + "]. [MessageBase] member cannot be an interface."); - return; - } - - MethodReference writeFunc = Weaver.GetWriteFunc(field.FieldType); - if (writeFunc != null) - { - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldfld, field)); - serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc)); - } - else - { - Weaver.fail = true; - Log.Error("GenerateSerialization for " + m_td.Name + " unknown type [" + field.FieldType + "/" + field.FieldType.FullName + "]. [MessageBase] member variables must be basic types."); - return; - } - } - serWorker.Append(serWorker.Create(OpCodes.Ret)); - - m_td.Methods.Add(serializeFunc); - } - - void GenerateDeSerialization() - { - Weaver.DLog(m_td, " GenerateDeserialization"); - foreach (var m in m_td.Methods) - { - if (m.Name == "Deserialize") - return; - } - - if (m_td.Fields.Count == 0) - { - return; - } - - MethodDefinition serializeFunc = new MethodDefinition("Deserialize", MethodAttributes.Public | - MethodAttributes.Virtual | - MethodAttributes.HideBySig, - Weaver.voidType); - - serializeFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType))); - ILProcessor serWorker = serializeFunc.Body.GetILProcessor(); - - foreach (var field in m_td.Fields) - { - if (field.IsStatic || field.IsPrivate || field.IsSpecialName) - continue; - - MethodReference readerFunc = Weaver.GetReadFunc(field.FieldType); - if (readerFunc != null) - { - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc)); - serWorker.Append(serWorker.Create(OpCodes.Stfld, field)); - } - else - { - Weaver.fail = true; - Log.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + field.FieldType + "]. [SyncVar] member variables must be basic types."); - return; - } - } - serWorker.Append(serWorker.Create(OpCodes.Ret)); - - m_td.Methods.Add(serializeFunc); - } - } -} diff --git a/Extensions/Networking/Weaver/MonoBehaviourProcessor.cs b/Extensions/Networking/Weaver/MonoBehaviourProcessor.cs deleted file mode 100644 index 1b72059ed6..0000000000 --- a/Extensions/Networking/Weaver/MonoBehaviourProcessor.cs +++ /dev/null @@ -1,99 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using Mono.Cecil; - -namespace Unity.UNetWeaver -{ - class MonoBehaviourProcessor - { - TypeDefinition m_td; - - public MonoBehaviourProcessor(TypeDefinition td) - { - m_td = td; - } - - public void Process() - { - ProcessSyncVars(); - ProcessMethods(); - } - - void ProcessSyncVars() - { - // find syncvars - foreach (FieldDefinition fd in m_td.Fields) - { - foreach (var ca in fd.CustomAttributes) - { - if (ca.AttributeType.FullName == Weaver.SyncVarType.FullName) - { - Log.Error("Script " + m_td.FullName + " uses [SyncVar] " + fd.Name + " but is not a NetworkBehaviour."); - Weaver.fail = true; - } - } - - if (Helpers.InheritsFromSyncList(fd.FieldType)) - { - Log.Error(string.Format("Script {0} defines field {1} with type {2}, but it's not a NetworkBehaviour", m_td.FullName, fd.Name, Helpers.PrettyPrintType(fd.FieldType))); - Weaver.fail = true; - } - } - } - - void ProcessMethods() - { - // find command and RPC functions - foreach (MethodDefinition md in m_td.Methods) - { - foreach (var ca in md.CustomAttributes) - { - if (ca.AttributeType.FullName == Weaver.CommandType.FullName) - { - Log.Error("Script " + m_td.FullName + " uses [Command] " + md.Name + " but is not a NetworkBehaviour."); - Weaver.fail = true; - } - - if (ca.AttributeType.FullName == Weaver.ClientRpcType.FullName) - { - Log.Error("Script " + m_td.FullName + " uses [ClientRpc] " + md.Name + " but is not a NetworkBehaviour."); - Weaver.fail = true; - } - - if (ca.AttributeType.FullName == Weaver.TargetRpcType.FullName) - { - Log.Error("Script " + m_td.FullName + " uses [TargetRpc] " + md.Name + " but is not a NetworkBehaviour."); - Weaver.fail = true; - } - - var attrName = ca.Constructor.DeclaringType.ToString(); - - if (attrName == "UnityEngine.Networking.ServerAttribute") - { - Log.Error("Script " + m_td.FullName + " uses the attribute [Server] on the method " + md.Name + " but is not a NetworkBehaviour."); - Weaver.fail = true; - } - else if (attrName == "UnityEngine.Networking.ServerCallbackAttribute") - { - Log.Error("Script " + m_td.FullName + " uses the attribute [ServerCallback] on the method " + md.Name + " but is not a NetworkBehaviour."); - Weaver.fail = true; - } - else if (attrName == "UnityEngine.Networking.ClientAttribute") - { - Log.Error("Script " + m_td.FullName + " uses the attribute [Client] on the method " + md.Name + " but is not a NetworkBehaviour."); - Weaver.fail = true; - } - else if (attrName == "UnityEngine.Networking.ClientCallbackAttribute") - { - Log.Error("Script " + m_td.FullName + " uses the attribute [ClientCallback] on the method " + md.Name + " but is not a NetworkBehaviour."); - Weaver.fail = true; - } - } - } - } - }; -} diff --git a/Extensions/Networking/Weaver/Program.cs b/Extensions/Networking/Weaver/Program.cs deleted file mode 100644 index 0cb8ef3639..0000000000 --- a/Extensions/Networking/Weaver/Program.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using Mono.Cecil; - -namespace Unity.UNetWeaver -{ - public static class Log - { - public static Action WarningMethod; - public static Action ErrorMethod; - - public static void Warning(string msg) - { - WarningMethod("UNetWeaver warning: " + msg); - } - - public static void Error(string msg) - { - ErrorMethod("UNetWeaver error: " + msg); - } - } - - public class Program - { - public static bool Process(string unityEngine, string unetDLL, string outputDirectory, string[] assemblies, string[] extraAssemblyPaths, IAssemblyResolver assemblyResolver, Action printWarning, Action printError) - { - CheckDLLPath(unityEngine); - CheckDLLPath(unetDLL); - CheckOutputDirectory(outputDirectory); - CheckAssemblies(assemblies); - Log.WarningMethod = printWarning; - Log.ErrorMethod = printError; - return Weaver.WeaveAssemblies(assemblies, extraAssemblyPaths, assemblyResolver, outputDirectory, unityEngine, unetDLL); - } - - private static void CheckDLLPath(string path) - { - if (!File.Exists(path)) - throw new Exception("dll could not be located at " + path + "!"); - } - - private static void CheckAssemblies(IEnumerable assemblyPaths) - { - foreach (var assemblyPath in assemblyPaths) - CheckAssemblyPath(assemblyPath); - } - - private static void CheckAssemblyPath(string assemblyPath) - { - if (!File.Exists(assemblyPath)) - throw new Exception("Assembly " + assemblyPath + " does not exist!"); - } - - private static void CheckOutputDirectory(string outputDir) - { - if (!Directory.Exists(outputDir)) - Directory.CreateDirectory(outputDir); - } - } -} diff --git a/Extensions/Networking/Weaver/SyncListStructProcessor.cs b/Extensions/Networking/Weaver/SyncListStructProcessor.cs deleted file mode 100644 index 85f25c48e5..0000000000 --- a/Extensions/Networking/Weaver/SyncListStructProcessor.cs +++ /dev/null @@ -1,357 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using Mono.Cecil; -using Mono.Cecil.Cil; - -namespace Unity.UNetWeaver -{ - class SyncListStructProcessor - { - TypeDefinition m_TypeDef; - TypeReference m_ItemType; - - public SyncListStructProcessor(TypeDefinition typeDef) - { - Weaver.DLog(typeDef, "SyncListStructProcessor for " + typeDef.Name); - m_TypeDef = typeDef; - } - - public void Process() - { - // find item type - var gt = (GenericInstanceType)m_TypeDef.BaseType; - if (gt.GenericArguments.Count == 0) - { - Weaver.fail = true; - Log.Error("SyncListStructProcessor no generic args"); - return; - } - m_ItemType = Weaver.scriptDef.MainModule.ImportReference(gt.GenericArguments[0]); - - Weaver.DLog(m_TypeDef, "SyncListStructProcessor Start item:" + m_ItemType.FullName); - - Weaver.ResetRecursionCount(); - var writeItemFunc = GenerateSerialization(); - if (Weaver.fail) - { - return; - } - - var readItemFunc = GenerateDeserialization(); - - if (readItemFunc == null || writeItemFunc == null) - return; - - GenerateReadFunc(readItemFunc); - GenerateWriteFunc(writeItemFunc); - - Weaver.DLog(m_TypeDef, "SyncListStructProcessor Done"); - } - - /* deserialization of entire list. generates code like: - * - static public void ReadStructBuf(NetworkReader reader, SyncListBuf instance) - { - ushort count = reader.ReadUInt16(); - instance.Clear() - for (ushort i = 0; i < count; i++) - { - instance.AddInternal(instance.DeserializeItem(reader)); - } - } - */ - void GenerateReadFunc(MethodReference readItemFunc) - { - var functionName = "_ReadStruct" + m_TypeDef.Name + "_"; - if (m_TypeDef.DeclaringType != null) - { - functionName += m_TypeDef.DeclaringType.Name; - } - else - { - functionName += "None"; - } - - // create new reader for this type - MethodDefinition readerFunc = new MethodDefinition(functionName, - MethodAttributes.Public | - MethodAttributes.Static | - MethodAttributes.HideBySig, - Weaver.voidType); - - readerFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType))); - readerFunc.Parameters.Add(new ParameterDefinition("instance", ParameterAttributes.None, m_TypeDef)); - - readerFunc.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type)); - readerFunc.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type)); - readerFunc.Body.InitLocals = true; - - ILProcessor worker = readerFunc.Body.GetILProcessor(); - - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Callvirt, Weaver.NetworkReadUInt16)); - worker.Append(worker.Create(OpCodes.Stloc_0)); - - // Call Clear() from the base class - worker.Append(worker.Create(OpCodes.Ldarg_1)); - MethodReference genericClearMethod = Helpers.MakeHostInstanceGeneric(Weaver.SyncListClear, m_ItemType); - worker.Append(worker.Create(OpCodes.Callvirt, genericClearMethod)); - - worker.Append(worker.Create(OpCodes.Ldc_I4_0)); - worker.Append(worker.Create(OpCodes.Stloc_1)); - var loopCheckLabel = worker.Create(OpCodes.Nop); - worker.Append(worker.Create(OpCodes.Br, loopCheckLabel)); - - // loop body - var loopHeadLabel = worker.Create(OpCodes.Nop); - worker.Append(loopHeadLabel); - - worker.Append(worker.Create(OpCodes.Ldarg_1)); - worker.Append(worker.Create(OpCodes.Ldarg_1)); - - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Callvirt, readItemFunc)); - - // call the generic AddInternal from the base class - var addInternal = Weaver.ResolveMethod(Weaver.SyncListStructType, "AddInternal"); - var addInternalTyped = Helpers.MakeHostInstanceGeneric(addInternal, m_ItemType); - worker.Append(worker.Create(OpCodes.Callvirt, addInternalTyped)); - - worker.Append(worker.Create(OpCodes.Ldloc_1)); - worker.Append(worker.Create(OpCodes.Ldc_I4_1)); - worker.Append(worker.Create(OpCodes.Add)); - worker.Append(worker.Create(OpCodes.Conv_U2)); - worker.Append(worker.Create(OpCodes.Stloc_1)); - - // loop check - worker.Append(loopCheckLabel); - worker.Append(worker.Create(OpCodes.Ldloc_1)); - worker.Append(worker.Create(OpCodes.Ldloc_0)); - worker.Append(worker.Create(OpCodes.Blt, loopHeadLabel)); - - // done - //worker.Append(worker.Create(OpCodes.Ldloc_1)); - worker.Append(worker.Create(OpCodes.Ret)); - - Weaver.RegisterReadByReferenceFunc(m_TypeDef.FullName, readerFunc); - } - - /*serialization of entire list. generates code like: - * - static public void WriteStructBuf(NetworkWriter writer, SyncListBuf items) - { - ushort count = (ushort)items.Count; - writer.Write(count); - for (ushort i=0; i < count; i++) - { - items.SerializeItem(writer, items.GetItem(i)); - } - } - */ - void GenerateWriteFunc(MethodReference writeItemFunc) - { - var functionName = "_WriteStruct" + m_TypeDef.GetElementType().Name + "_"; - if (m_TypeDef.DeclaringType != null) - { - functionName += m_TypeDef.DeclaringType.Name; - } - else - { - functionName += "None"; - } - - // create new writer for this type - MethodDefinition writerFunc = new MethodDefinition(functionName, - MethodAttributes.Public | - MethodAttributes.Static | - MethodAttributes.HideBySig, - Weaver.voidType); - - writerFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType))); - writerFunc.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(m_TypeDef))); - - writerFunc.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type)); - writerFunc.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type)); - writerFunc.Body.InitLocals = true; - - ILProcessor worker = writerFunc.Body.GetILProcessor(); - - worker.Append(worker.Create(OpCodes.Ldarg_1)); - - // call the generic Count from the base class - var getCount = Weaver.ResolveMethod(Weaver.SyncListStructType, "get_Count"); - var getCountTyped = Helpers.MakeHostInstanceGeneric(getCount, m_ItemType); - worker.Append(worker.Create(OpCodes.Callvirt, getCountTyped)); - - worker.Append(worker.Create(OpCodes.Stloc_0)); - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Ldloc_0)); - worker.Append(worker.Create(OpCodes.Callvirt, Weaver.NetworkWriteUInt16)); - worker.Append(worker.Create(OpCodes.Ldc_I4_0)); - worker.Append(worker.Create(OpCodes.Stloc_1)); - - var loopCheckLabel = worker.Create(OpCodes.Nop); - worker.Append(worker.Create(OpCodes.Br, loopCheckLabel)); - - //loop start - var loopStartLabel = worker.Create(OpCodes.Nop); - worker.Append(loopStartLabel); - - worker.Append(worker.Create(OpCodes.Ldarg_1)); - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Ldarg_1)); - worker.Append(worker.Create(OpCodes.Ldloc_1)); - - // call the generic [] from the base class - var getItem = Weaver.ResolveMethod(Weaver.SyncListStructType, "GetItem"); - var getItemTyped = Helpers.MakeHostInstanceGeneric(getItem, m_ItemType); - worker.Append(worker.Create(OpCodes.Callvirt, getItemTyped)); - worker.Append(worker.Create(OpCodes.Callvirt, writeItemFunc)); - - worker.Append(worker.Create(OpCodes.Ldloc_1)); - worker.Append(worker.Create(OpCodes.Ldc_I4_1)); - worker.Append(worker.Create(OpCodes.Add)); - worker.Append(worker.Create(OpCodes.Conv_U2)); - worker.Append(worker.Create(OpCodes.Stloc_1)); - - worker.Append(loopCheckLabel); - worker.Append(worker.Create(OpCodes.Ldloc_1)); - worker.Append(worker.Create(OpCodes.Ldloc_0)); - worker.Append(worker.Create(OpCodes.Blt, loopStartLabel)); - - worker.Append(worker.Create(OpCodes.Ret)); - - Weaver.RegisterWriteFunc(m_TypeDef.FullName, writerFunc); - } - - // serialization of individual element - MethodReference GenerateSerialization() - { - Weaver.DLog(m_TypeDef, " GenerateSerialization"); - foreach (var m in m_TypeDef.Methods) - { - if (m.Name == "SerializeItem") - return m; - } - - MethodDefinition serializeFunc = new MethodDefinition("SerializeItem", MethodAttributes.Public | - MethodAttributes.Virtual | - MethodAttributes.Public | - MethodAttributes.HideBySig, - Weaver.voidType); - - serializeFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType))); - serializeFunc.Parameters.Add(new ParameterDefinition("item", ParameterAttributes.None, m_ItemType)); - ILProcessor serWorker = serializeFunc.Body.GetILProcessor(); - - if (m_ItemType.IsGenericInstance) - { - Weaver.fail = true; - Log.Error("GenerateSerialization for " + Helpers.PrettyPrintType(m_ItemType) + " failed. Struct passed into SyncListStruct can't have generic parameters"); - return null; - } - - foreach (var field in m_ItemType.Resolve().Fields) - { - if (field.IsStatic || field.IsPrivate || field.IsSpecialName) - continue; - - var importedField = Weaver.scriptDef.MainModule.ImportReference(field); - var ft = importedField.FieldType.Resolve(); - - if (ft.HasGenericParameters) - { - Weaver.fail = true; - Log.Error("GenerateSerialization for " + m_TypeDef.Name + " [" + ft + "/" + ft.FullName + "]. UNet [MessageBase] member cannot have generic parameters."); - return null; - } - - if (ft.IsInterface) - { - Weaver.fail = true; - Log.Error("GenerateSerialization for " + m_TypeDef.Name + " [" + ft + "/" + ft.FullName + "]. UNet [MessageBase] member cannot be an interface."); - return null; - } - - MethodReference writeFunc = Weaver.GetWriteFunc(field.FieldType); - if (writeFunc != null) - { - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); - serWorker.Append(serWorker.Create(OpCodes.Ldfld, importedField)); - serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc)); - } - else - { - Weaver.fail = true; - Log.Error("GenerateSerialization for " + m_TypeDef.Name + " unknown type [" + ft + "/" + ft.FullName + "]. UNet [MessageBase] member variables must be basic types."); - return null; - } - } - serWorker.Append(serWorker.Create(OpCodes.Ret)); - - m_TypeDef.Methods.Add(serializeFunc); - return serializeFunc; - } - - MethodReference GenerateDeserialization() - { - Weaver.DLog(m_TypeDef, " GenerateDeserialization"); - foreach (var m in m_TypeDef.Methods) - { - if (m.Name == "DeserializeItem") - return m; - } - - MethodDefinition serializeFunc = new MethodDefinition("DeserializeItem", MethodAttributes.Public | - MethodAttributes.Virtual | - MethodAttributes.Public | - MethodAttributes.HideBySig, - m_ItemType); - - serializeFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType))); - - ILProcessor serWorker = serializeFunc.Body.GetILProcessor(); - - serWorker.Body.InitLocals = true; - serWorker.Body.Variables.Add(new VariableDefinition(m_ItemType)); - - // init item instance - serWorker.Append(serWorker.Create(OpCodes.Ldloca, 0)); - serWorker.Append(serWorker.Create(OpCodes.Initobj, m_ItemType)); - - - foreach (var field in m_ItemType.Resolve().Fields) - { - if (field.IsStatic || field.IsPrivate || field.IsSpecialName) - continue; - - var importedField = Weaver.scriptDef.MainModule.ImportReference(field); - var ft = importedField.FieldType.Resolve(); - - MethodReference readerFunc = Weaver.GetReadFunc(field.FieldType); - if (readerFunc != null) - { - serWorker.Append(serWorker.Create(OpCodes.Ldloca, 0)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc)); - serWorker.Append(serWorker.Create(OpCodes.Stfld, importedField)); - } - else - { - Weaver.fail = true; - Log.Error("GenerateDeserialization for " + m_TypeDef.Name + " unknown type [" + ft + "]. UNet [SyncVar] member variables must be basic types."); - return null; - } - } - serWorker.Append(serWorker.Create(OpCodes.Ldloc_0)); - serWorker.Append(serWorker.Create(OpCodes.Ret)); - - m_TypeDef.Methods.Add(serializeFunc); - return serializeFunc; - } - } -} diff --git a/Extensions/Networking/Weaver/UNetBehaviourProcessor.cs b/Extensions/Networking/Weaver/UNetBehaviourProcessor.cs deleted file mode 100644 index 4bcdf3b19b..0000000000 --- a/Extensions/Networking/Weaver/UNetBehaviourProcessor.cs +++ /dev/null @@ -1,2341 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Linq; -using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; - -namespace Unity.UNetWeaver -{ - class NetworkBehaviourProcessor - { - List m_SyncVars = new List(); - List m_SyncLists = new List(); - List m_SyncVarNetIds = new List(); - List m_Cmds = new List(); - List m_Rpcs = new List(); - List m_TargetRpcs = new List(); - List m_Events = new List(); - List m_SyncListStaticFields = new List(); - List m_CmdInvocationFuncs = new List(); - List m_SyncListInvocationFuncs = new List(); - List m_RpcInvocationFuncs = new List(); - List m_TargetRpcInvocationFuncs = new List(); - List m_EventInvocationFuncs = new List(); - - List m_CmdCallFuncs = new List(); - List m_RpcCallFuncs = new List(); - List m_TargetRpcCallFuncs = new List(); - - const int k_SyncVarLimit = 32; - int m_QosChannel; - - TypeDefinition m_td; - int m_NetIdFieldCounter; - - const string k_CmdPrefix = "InvokeCmd"; - const string k_RpcPrefix = "InvokeRpc"; - const string k_TargetRpcPrefix = "InvokeTargetRpc"; - - public NetworkBehaviourProcessor(TypeDefinition td) - { - Weaver.DLog(td, "NetworkBehaviourProcessor"); - m_td = td; - } - - public void Process() - { - if (m_td.HasGenericParameters) - { - Weaver.fail = true; - Log.Error("NetworkBehaviour " + m_td.Name + " cannot have generic parameters"); - return; - } - Weaver.DLog(m_td, "Process Start"); - ProcessVersion(); - ProcessSyncVars(); - Weaver.ResetRecursionCount(); - - ProcessMethods(); - - ProcessEvents(); - if (Weaver.fail) - { - return; - } - GenerateNetworkSettings(); - GenerateConstants(); - - Weaver.ResetRecursionCount(); - GenerateSerialization(); - if (Weaver.fail) - { - return; - } - - GenerateDeSerialization(); - GeneratePreStartClient(); - Weaver.DLog(m_td, "Process Done"); - } - - static void WriteClientActiveCheck(ILProcessor worker, string mdName, Instruction label, string errString) - { - // client active check - worker.Append(worker.Create(OpCodes.Call, Weaver.NetworkClientGetActive)); - worker.Append(worker.Create(OpCodes.Brtrue, label)); - - worker.Append(worker.Create(OpCodes.Ldstr, errString + " " + mdName + " called on server.")); - worker.Append(worker.Create(OpCodes.Call, Weaver.logErrorReference)); - worker.Append(worker.Create(OpCodes.Ret)); - worker.Append(label); - } - - static void WriteServerActiveCheck(ILProcessor worker, string mdName, Instruction label, string errString) - { - // server active check - worker.Append(worker.Create(OpCodes.Call, Weaver.NetworkServerGetActive)); - worker.Append(worker.Create(OpCodes.Brtrue, label)); - - worker.Append(worker.Create(OpCodes.Ldstr, errString + " " + mdName + " called on client.")); - worker.Append(worker.Create(OpCodes.Call, Weaver.logErrorReference)); - worker.Append(worker.Create(OpCodes.Ret)); - worker.Append(label); - } - - static void WriteSetupLocals(ILProcessor worker) - { - worker.Body.InitLocals = true; - worker.Body.Variables.Add(new VariableDefinition(Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType))); - } - - static void WriteCreateWriter(ILProcessor worker) - { - // create writer - worker.Append(worker.Create(OpCodes.Newobj, Weaver.NetworkWriterCtor)); - worker.Append(worker.Create(OpCodes.Stloc_0)); - worker.Append(worker.Create(OpCodes.Ldloc_0)); - } - - static void WriteMessageSize(ILProcessor worker) - { - //write size - worker.Append(worker.Create(OpCodes.Ldc_I4_0)); - worker.Append(worker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteInt16)); - } - - static void WriteMessageId(ILProcessor worker, int msgId) - { - // write msg id - worker.Append(worker.Create(OpCodes.Ldloc_0)); - worker.Append(worker.Create(OpCodes.Ldc_I4, msgId)); - worker.Append(worker.Create(OpCodes.Conv_U2)); - worker.Append(worker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteInt16)); - } - - static bool WriteArguments(ILProcessor worker, MethodDefinition md, string errString, bool skipFirst) - { - // write each argument - short argNum = 1; - foreach (ParameterDefinition pd in md.Parameters) - { - if (argNum == 1 && skipFirst) - { - argNum += 1; - continue; - } - - MethodReference writeFunc = Weaver.GetWriteFunc(pd.ParameterType); - if (writeFunc == null) - { - Log.Error("WriteArguments for " + md.Name + " type " + pd.ParameterType + " not supported"); - Weaver.fail = true; - return false; - } - // use built-in writer func on writer object - worker.Append(worker.Create(OpCodes.Ldloc_0)); // writer object - worker.Append(worker.Create(OpCodes.Ldarg, argNum)); // argument - worker.Append(worker.Create(OpCodes.Call, writeFunc));// call writer func on writer object - argNum += 1; - } - return true; - } - - void ProcessVersion() - { - foreach (MethodDefinition md in m_td.Methods) - { - if (md.Name == "UNetVersion") - { - return; - } - } - - MethodDefinition versionMethod = new MethodDefinition("UNetVersion", MethodAttributes.Private, Weaver.voidType); - ILProcessor worker = versionMethod.Body.GetILProcessor(); - worker.Append(worker.Create(OpCodes.Ret)); - m_td.Methods.Add(versionMethod); - } - - void GenerateConstants() - { - if (m_Cmds.Count == 0 && m_Rpcs.Count == 0 && m_TargetRpcs.Count == 0 && m_Events.Count == 0 && m_SyncLists.Count == 0) - return; - - Weaver.DLog(m_td, " GenerateConstants "); - - // find static constructor - MethodDefinition cctor = null; - bool cctorFound = false; - foreach (MethodDefinition md in m_td.Methods) - { - if (md.Name == ".cctor") - { - cctor = md; - cctorFound = true; - } - } - if (cctor != null) - { - // remove the return opcode from end of function. will add our own later. - if (cctor.Body.Instructions.Count != 0) - { - Instruction ret = cctor.Body.Instructions[cctor.Body.Instructions.Count - 1]; - if (ret.OpCode == OpCodes.Ret) - { - cctor.Body.Instructions.RemoveAt(cctor.Body.Instructions.Count - 1); - } - else - { - Log.Error("No cctor for " + m_td.Name); - Weaver.fail = true; - return; - } - } - } - else - { - // make one! - cctor = new MethodDefinition(".cctor", MethodAttributes.Private | - MethodAttributes.HideBySig | - MethodAttributes.SpecialName | - MethodAttributes.RTSpecialName | - MethodAttributes.Static, - Weaver.voidType); - } - - // find instance constructor - MethodDefinition ctor = null; - - foreach (MethodDefinition md in m_td.Methods) - { - if (md.Name == ".ctor") - { - ctor = md; - - var ret = ctor.Body.Instructions[ctor.Body.Instructions.Count - 1]; - if (ret.OpCode == OpCodes.Ret) - { - ctor.Body.Instructions.RemoveAt(ctor.Body.Instructions.Count - 1); - } - else - { - Weaver.fail = true; - Log.Error("No ctor for " + m_td.Name); - return; - } - - break; - } - } - - if (ctor == null) - { - Weaver.fail = true; - Log.Error("No ctor for " + m_td.Name); - return; - } - - ILProcessor ctorWorker = ctor.Body.GetILProcessor(); - ILProcessor cctorWorker = cctor.Body.GetILProcessor(); - - int cmdIndex = 0; - foreach (MethodDefinition md in m_Cmds) - { - FieldReference cmdConstant = Weaver.ResolveField(m_td, "kCmd" + md.Name); - - int cmdHash = GetHashCode(m_td.Name + ":Cmd:" + md.Name); - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldc_I4, cmdHash)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Stsfld, cmdConstant)); - //Weaver.DLog(m_td, " Constant " + m_td.Name + ":Cmd:" + md.Name); - - GenerateCommandDelegate(cctorWorker, Weaver.registerCommandDelegateReference, m_CmdInvocationFuncs[cmdIndex], cmdConstant); - cmdIndex += 1; - } - - int rpcIndex = 0; - foreach (MethodDefinition md in m_Rpcs) - { - FieldReference rpcConstant = Weaver.ResolveField(m_td, "kRpc" + md.Name); - - int rpcHash = GetHashCode(m_td.Name + ":Rpc:" + md.Name); - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldc_I4, rpcHash)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Stsfld, rpcConstant)); - //Weaver.DLog(m_td, " Constant " + m_td.Name + ":Rpc:" + md.Name); - - GenerateCommandDelegate(cctorWorker, Weaver.registerRpcDelegateReference, m_RpcInvocationFuncs[rpcIndex], rpcConstant); - rpcIndex += 1; - } - - int targetRpcIndex = 0; - foreach (MethodDefinition md in m_TargetRpcs) - { - FieldReference targetRpcConstant = Weaver.ResolveField(m_td, "kTargetRpc" + md.Name); - - int targetRpcHash = GetHashCode(m_td.Name + ":TargetRpc:" + md.Name); - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldc_I4, targetRpcHash)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Stsfld, targetRpcConstant)); - //Weaver.DLog(m_td, " Constant " + m_td.Name + ":Rpc:" + md.Name); - - GenerateCommandDelegate(cctorWorker, Weaver.registerRpcDelegateReference, m_TargetRpcInvocationFuncs[targetRpcIndex], targetRpcConstant); - targetRpcIndex += 1; - } - - int eventIndex = 0; - foreach (EventDefinition ed in m_Events) - { - FieldReference eventConstant = Weaver.ResolveField(m_td, "kEvent" + ed.Name); - - int eventHash = GetHashCode(m_td.Name + ":Event:" + ed.Name); - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldc_I4, eventHash)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Stsfld, eventConstant)); - //Weaver.DLog(m_td, " Constant " + m_td.Name + ":Event:" + ed.Name); - - GenerateCommandDelegate(cctorWorker, Weaver.registerEventDelegateReference, m_EventInvocationFuncs[eventIndex], eventConstant); - eventIndex += 1; - } - - int syncListIndex = 0; - foreach (FieldDefinition fd in m_SyncLists) - { - FieldReference listConstant = Weaver.ResolveField(m_td, "kList" + fd.Name); - - int listHash = GetHashCode(m_td.Name + ":List:" + fd.Name); - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldc_I4, listHash)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Stsfld, listConstant)); - //Weaver.DLog(m_td, " Constant " + m_td.Name + ":List:" + fd.Name); - - - GenerateSyncListInstanceInitializer(ctorWorker, fd); - - GenerateCommandDelegate(cctorWorker, Weaver.registerSyncListDelegateReference, m_SyncListInvocationFuncs[syncListIndex], listConstant); - syncListIndex += 1; - } - - // register CRC entry - // "NetworkCRC.RegisterBehaviour('MyScript', 2);" - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldstr, m_td.Name)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Ldc_I4, m_QosChannel)); - cctorWorker.Append(cctorWorker.Create(OpCodes.Call, Weaver.RegisterBehaviourReference)); - - cctorWorker.Append(cctorWorker.Create(OpCodes.Ret)); - if (!cctorFound) - { - m_td.Methods.Add(cctor); - } - - // finish ctor - ctorWorker.Append(ctorWorker.Create(OpCodes.Ret)); - - // in case class had no cctor, it might have BeforeFieldInit, so injected cctor would be called too late - m_td.Attributes = m_td.Attributes & ~TypeAttributes.BeforeFieldInit; - - if (m_SyncLists.Count == 0) - return; - - // find constructor - MethodDefinition awake = null; - bool awakeFound = false; - foreach (MethodDefinition md in m_td.Methods) - { - if (md.Name == "Awake") - { - awake = md; - awakeFound = true; - } - } - if (awake != null) - { - // remove the return opcode from end of function. will add our own later. - if (awake.Body.Instructions.Count != 0) - { - Instruction ret = awake.Body.Instructions[awake.Body.Instructions.Count - 1]; - if (ret.OpCode == OpCodes.Ret) - { - awake.Body.Instructions.RemoveAt(awake.Body.Instructions.Count - 1); - } - else - { - Log.Error("No awake for " + m_td.Name); - Weaver.fail = true; - return; - } - } - } - else - { - awake = new MethodDefinition("Awake", MethodAttributes.Private, Weaver.voidType); - } - - ILProcessor awakeWorker = awake.Body.GetILProcessor(); - - if (!awakeFound) - { - // if we're not directly inheriting from NetworkBehaviour, we have to - // go up the inheritance chain and check for awake calls that we are overriding by "mistake" - CheckForCustomBaseClassAwakeMethod(awakeWorker); - } - - int syncListFieldOffset = 0; - foreach (FieldDefinition fd in m_SyncLists) - { - GenerateSyncListInitializer(awakeWorker, fd, syncListFieldOffset); - syncListFieldOffset += 1; - } - awakeWorker.Append(awakeWorker.Create(OpCodes.Ret)); - if (!awakeFound) - { - m_td.Methods.Add(awake); - } - } - - void CheckForCustomBaseClassAwakeMethod(ILProcessor awakeWorker) - { - // start from base type - var t = m_td.BaseType; - - // as long as basetype is not NetworkBehaviour - while (t.FullName != Weaver.NetworkBehaviourType.FullName) - { - // check for the first Awake() method in the hierarchy - var awake = t.Resolve().Methods.FirstOrDefault(x => x.Name == "Awake" && !x.HasParameters); - if (awake != null) - { - // if found, invoke it so we don't loose the behaviour by implicitly overriding Awake - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldarg_0)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Call, awake)); - return; - } - t = t.Resolve().BaseType; - } - } - - void GenerateSyncListInstanceInitializer(ILProcessor ctorWorker, FieldDefinition fd) - { - // check the ctor's instructions for an Stfld op-code for this specific sync list field. - foreach (var ins in ctorWorker.Body.Instructions) - { - if (ins.OpCode.Code == Code.Stfld) - { - var field = (FieldDefinition)ins.Operand; - if (field.DeclaringType == fd.DeclaringType && field.Name == fd.Name) - { - // Already initialized by the user in the field definition, e.g: - // public SyncListInt Foo = new SyncListInt(); - return; - } - } - } - - // Not initialized by the user in the field definition, e.g: - // public SyncListInt Foo; - var listCtor = Weaver.scriptDef.MainModule.ImportReference(fd.FieldType.Resolve().Methods.First(x => x.Name == ".ctor" && !x.HasParameters)); - - ctorWorker.Append(ctorWorker.Create(OpCodes.Ldarg_0)); - ctorWorker.Append(ctorWorker.Create(OpCodes.Newobj, listCtor)); - ctorWorker.Append(ctorWorker.Create(OpCodes.Stfld, fd)); - } - - /* - // This generates code like: - NetworkBehaviour.RegisterCommandDelegate(base.GetType(), ShipControl.kCmdCmdThrust, new NetworkBehaviour.CmdDelegate(ShipControl.InvokeCmdCmdThrust)); - */ - void GenerateCommandDelegate(ILProcessor awakeWorker, MethodReference registerMethod, MethodDefinition func, FieldReference field) - { - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldtoken, m_td)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldsfld, field)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldnull)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldftn, func)); - - awakeWorker.Append(awakeWorker.Create(OpCodes.Newobj, Weaver.CmdDelegateConstructor)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Call, registerMethod)); - } - - /* - // generates code like: - m_sizes.InitializeBehaviour(this, km_sizesCmdHash); - */ - void GenerateSyncListInitializer(ILProcessor awakeWorker, FieldReference fd, int index) - { - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldarg_0)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldfld, fd)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldarg_0)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldsfld, m_SyncListStaticFields[index])); - - GenericInstanceType syncListGeneric = (GenericInstanceType)fd.FieldType.Resolve().BaseType; - syncListGeneric = (GenericInstanceType)Weaver.scriptDef.MainModule.ImportReference(syncListGeneric); - - TypeReference listValueType = syncListGeneric.GenericArguments[0]; - MethodReference genericInitBehaviourMethod = Helpers.MakeHostInstanceGeneric(Weaver.SyncListInitBehaviourReference, listValueType); - awakeWorker.Append(awakeWorker.Create(OpCodes.Callvirt, genericInitBehaviourMethod)); - - Weaver.scriptDef.MainModule.ImportReference(genericInitBehaviourMethod); - } - - void GenerateSerialization() - { - Weaver.DLog(m_td, " GenerateSerialization"); - - foreach (var m in m_td.Methods) - { - if (m.Name == "OnSerialize") - return; - } - - MethodDefinition serialize = new MethodDefinition("OnSerialize", MethodAttributes.Public | - MethodAttributes.Virtual | - MethodAttributes.HideBySig, - Weaver.boolType); - - serialize.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType))); - serialize.Parameters.Add(new ParameterDefinition("forceAll", ParameterAttributes.None, Weaver.boolType)); - ILProcessor serWorker = serialize.Body.GetILProcessor(); - - - serialize.Body.InitLocals = true; - VariableDefinition dirtyLocal = new VariableDefinition(Weaver.boolType); - - serialize.Body.Variables.Add(dirtyLocal); - - // call base class - bool baseClassSerialize = false; - if (m_td.BaseType.FullName != Weaver.NetworkBehaviourType.FullName) - { - MethodReference baseSerialize = Weaver.ResolveMethod(m_td.BaseType, "OnSerialize"); - if (baseSerialize != null) - { - VariableDefinition baseResult = new VariableDefinition(Weaver.boolType); - serialize.Body.Variables.Add(baseResult); - - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // writer - serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // forceAll - serWorker.Append(serWorker.Create(OpCodes.Call, baseSerialize)); - serWorker.Append(serWorker.Create(OpCodes.Stloc_1)); // set baseResult to result of base.OnSerialize() - baseClassSerialize = true; - } - } - - if (m_SyncVars.Count == 0) - { - if (baseClassSerialize) - { - serWorker.Append(serWorker.Create(OpCodes.Ldloc_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldloc_1)); - serWorker.Append(serWorker.Create(OpCodes.Or)); - } - else - { - serWorker.Append(serWorker.Create(OpCodes.Ldloc_0)); - } - serWorker.Append(serWorker.Create(OpCodes.Ret)); - m_td.Methods.Add(serialize); - return; - } - - // Generates: if (initialState); - Instruction initialStateLabel = serWorker.Create(OpCodes.Nop); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); - serWorker.Append(serWorker.Create(OpCodes.Brfalse, initialStateLabel)); - - foreach (FieldDefinition syncVar in m_SyncVars) - { - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldfld, syncVar)); - MethodReference writeFunc = Weaver.GetWriteFunc(syncVar.FieldType); - if (writeFunc != null) - { - serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc)); - } - else - { - Weaver.fail = true; - Log.Error("GenerateSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. UNet [SyncVar] member variables must be basic types."); - return; - } - } - - serWorker.Append(serWorker.Create(OpCodes.Ldc_I4_1)); - serWorker.Append(serWorker.Create(OpCodes.Ret)); - - // Generates: end if (initialState); - serWorker.Append(initialStateLabel); - - // Generates: dirty = 0; - serWorker.Append(serWorker.Create(OpCodes.Ldc_I4_0)); - serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); - - // write syncvars - int dirtyBit = Weaver.GetSyncVarStart(m_td.BaseType.FullName); // start at number of syncvars in parent - foreach (FieldDefinition syncVar in m_SyncVars) - { - Instruction varLabel = serWorker.Create(OpCodes.Nop); - - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference)); - serWorker.Append(serWorker.Create(OpCodes.Ldc_I4, 1 << dirtyBit)); - serWorker.Append(serWorker.Create(OpCodes.And)); - serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel)); - - WriteDirtyCheck(serWorker, true); - - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldfld, syncVar)); - - MethodReference writeFunc = Weaver.GetWriteFunc(syncVar.FieldType); - if (writeFunc != null) - { - serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc)); - } - else - { - Log.Error("GenerateSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. UNet [SyncVar] member variables must be basic types."); - Weaver.fail = true; - return; - } - serWorker.Append(varLabel); - dirtyBit += 1; - } - - WriteDirtyCheck(serWorker, false); - - if (Weaver.generateLogErrors) - { - serWorker.Append(serWorker.Create(OpCodes.Ldstr, "Injected Serialize " + m_td.Name)); - serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.logErrorReference)); - } - - if (baseClassSerialize) - { - serWorker.Append(serWorker.Create(OpCodes.Ldloc_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldloc_1)); - serWorker.Append(serWorker.Create(OpCodes.Or)); - } - else - { - serWorker.Append(serWorker.Create(OpCodes.Ldloc_0)); - } - serWorker.Append(serWorker.Create(OpCodes.Ret)); - m_td.Methods.Add(serialize); - } - - static void WriteDirtyCheck(ILProcessor serWorker, bool reset) - { - //Weaver.DLog(m_td, " GenerateSerialization dirtyCheck"); - - // Generates: if (!dirty) { write dirty bits, set dirty bool } - Instruction dirtyLabel = serWorker.Create(OpCodes.Nop); - serWorker.Append(serWorker.Create(OpCodes.Ldloc_0)); - - serWorker.Append(serWorker.Create(OpCodes.Brtrue, dirtyLabel)); - - // write dirty bits - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference)); - serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); - if (reset) - { - serWorker.Append(serWorker.Create(OpCodes.Ldc_I4_1)); - serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); - } - - // Generates: end if (!dirty) - serWorker.Append(dirtyLabel); - } - - static int GetChannelId(FieldDefinition field) - { - int channel = 0; - foreach (var ca in field.CustomAttributes) - { - if (ca.AttributeType.FullName == Weaver.SyncVarType.FullName) - { - foreach (CustomAttributeNamedArgument customField in ca.Fields) - { - if (customField.Name == "channel") - { - channel = (int)customField.Argument.Value; - break; - } - } - } - } - return channel; - } - - // returns false for error, not for no-hook-exists - bool CheckForHookFunction(FieldDefinition syncVar, out MethodDefinition foundMethod) - { - foundMethod = null; - foreach (var ca in syncVar.CustomAttributes) - { - if (ca.AttributeType.FullName == Weaver.SyncVarType.FullName) - { - foreach (CustomAttributeNamedArgument customField in ca.Fields) - { - if (customField.Name == "hook") - { - string hookFunctionName = customField.Argument.Value as string; - - foreach (var m in m_td.Methods) - { - if (m.Name == hookFunctionName) - { - if (m.Parameters.Count == 1) - { - if (m.Parameters[0].ParameterType != syncVar.FieldType) - { - Log.Error("SyncVar Hook function " + hookFunctionName + " has wrong type signature for " + m_td.Name); - Weaver.fail = true; - return false; - } - foundMethod = m; - return true; - } - Log.Error("SyncVar Hook function " + hookFunctionName + " must have one argument " + m_td.Name); - Weaver.fail = true; - return false; - } - } - Log.Error("SyncVar Hook function " + hookFunctionName + " not found for " + m_td.Name); - Weaver.fail = true; - return false; - } - } - } - } - return true; - } - - void GenerateNetworkChannelSetting(int channel) - { - MethodDefinition meth = new MethodDefinition("GetNetworkChannel", MethodAttributes.Public | - MethodAttributes.Virtual | - MethodAttributes.HideBySig, - Weaver.int32Type); - - ILProcessor worker = meth.Body.GetILProcessor(); - - worker.Append(worker.Create(OpCodes.Ldc_I4, channel)); - worker.Append(worker.Create(OpCodes.Ret)); - m_td.Methods.Add(meth); - } - - void GenerateNetworkIntervalSetting(float interval) - { - MethodDefinition meth = new MethodDefinition("GetNetworkSendInterval", MethodAttributes.Public | - MethodAttributes.Virtual | - MethodAttributes.HideBySig, - Weaver.singleType); - - ILProcessor worker = meth.Body.GetILProcessor(); - - worker.Append(worker.Create(OpCodes.Ldc_R4, interval)); - worker.Append(worker.Create(OpCodes.Ret)); - m_td.Methods.Add(meth); - } - - void GenerateNetworkSettings() - { - // look for custom attribute - foreach (var ca in m_td.CustomAttributes) - { - if (ca.AttributeType.FullName == Weaver.NetworkSettingsType.FullName) - { - // generate virtual functions - foreach (var field in ca.Fields) - { - if (field.Name == "channel") - { - // 0 is Channels.DefaultChannel - if ((int)field.Argument.Value == 0) - continue; - - if (HasMethod("GetNetworkChannel")) - { - Log.Error( - "GetNetworkChannel, is already implemented, please make sure you either use NetworkSettings or GetNetworkChannel"); - Weaver.fail = true; - return; - } - m_QosChannel = (int)field.Argument.Value; - GenerateNetworkChannelSetting(m_QosChannel); - } - if (field.Name == "sendInterval") - { - const float stdValue = 0.1f; - const float epsilon = 0.00001f; - - if ((Math.Abs((float)field.Argument.Value - stdValue) <= epsilon)) - continue; - - if (HasMethod("GetNetworkSendInterval")) - { - Log.Error( - "GetNetworkSendInterval, is already implemented, please make sure you either use NetworkSettings or GetNetworkSendInterval"); - Weaver.fail = true; - return; - } - GenerateNetworkIntervalSetting((float)field.Argument.Value); - } - } - } - } - } - - void GeneratePreStartClient() - { - m_NetIdFieldCounter = 0; - MethodDefinition preStartMethod = null; - ILProcessor serWorker = null; - - foreach (var m in m_td.Methods) - { - if (m.Name == "PreStartClient") - return; - } - - foreach (FieldDefinition syncVar in m_SyncVars) - { - if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName) - { - if (preStartMethod == null) - { - preStartMethod = new MethodDefinition("PreStartClient", MethodAttributes.Public | - MethodAttributes.Virtual | - MethodAttributes.HideBySig, - Weaver.voidType); - - serWorker = preStartMethod.Body.GetILProcessor(); - } - - FieldDefinition netIdField = m_SyncVarNetIds[m_NetIdFieldCounter]; - m_NetIdFieldCounter += 1; - - // Generates: if (!_crateNetId.IsEmpty()) { crate = ClientScene.FindLocalObject(_crateNetId); } - Instruction nullLabel = serWorker.Create(OpCodes.Nop); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldflda, netIdField)); - serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkInstanceIsEmpty)); - serWorker.Append(serWorker.Create(OpCodes.Brtrue, nullLabel)); - - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldfld, netIdField)); - serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.FindLocalObjectReference)); - - // return value of FindLocalObjectReference is on stack, assign it to the syncvar - serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar)); - - // Generates: end crateNetId != 0 - serWorker.Append(nullLabel); - } - } - if (preStartMethod != null) - { - serWorker.Append(serWorker.Create(OpCodes.Ret)); - m_td.Methods.Add(preStartMethod); - } - } - - void GenerateDeSerialization() - { - Weaver.DLog(m_td, " GenerateDeSerialization"); - m_NetIdFieldCounter = 0; - - foreach (var m in m_td.Methods) - { - if (m.Name == "OnDeserialize") - return; - } - - MethodDefinition serialize = new MethodDefinition("OnDeserialize", MethodAttributes.Public | - MethodAttributes.Virtual | - MethodAttributes.HideBySig, - Weaver.voidType); - - serialize.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType))); - serialize.Parameters.Add(new ParameterDefinition("initialState", ParameterAttributes.None, Weaver.boolType)); - ILProcessor serWorker = serialize.Body.GetILProcessor(); - - // call base class - if (m_td.BaseType.FullName != Weaver.NetworkBehaviourType.FullName) - { - MethodReference baseDeserialize = Weaver.ResolveMethod(m_td.BaseType, "OnDeserialize"); - if (baseDeserialize != null) - { - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); // base - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); // reader - serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); // initialState - serWorker.Append(serWorker.Create(OpCodes.Call, baseDeserialize)); - } - } - - if (m_SyncVars.Count == 0) - { - serWorker.Append(serWorker.Create(OpCodes.Ret)); - m_td.Methods.Add(serialize); - return; - } - - // Generates: if (initialState); - Instruction initialStateLabel = serWorker.Create(OpCodes.Nop); - - serWorker.Append(serWorker.Create(OpCodes.Ldarg_2)); - serWorker.Append(serWorker.Create(OpCodes.Brfalse, initialStateLabel)); - - foreach (var syncVar in m_SyncVars) - { - MethodReference readByReferenceFunc = Weaver.GetReadByReferenceFunc(syncVar.FieldType); - if (readByReferenceFunc != null) - { - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldfld, syncVar)); - serWorker.Append(serWorker.Create(OpCodes.Call, readByReferenceFunc)); - } - else - { - // assign value - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - - if (syncVar.FieldType.FullName == Weaver.gameObjectType.FullName) - { - // GameObject SyncVar - assign to generated netId var - FieldDefinition netIdField = m_SyncVarNetIds[m_NetIdFieldCounter]; - m_NetIdFieldCounter += 1; - - serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadNetworkInstanceId)); - serWorker.Append(serWorker.Create(OpCodes.Stfld, netIdField)); - } - else - { - MethodReference readFunc = Weaver.GetReadFunc(syncVar.FieldType); - if (readFunc != null) - { - serWorker.Append(serWorker.Create(OpCodes.Call, readFunc)); - } - else - { - Log.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. UNet [SyncVar] member variables must be basic types."); - Weaver.fail = true; - return; - } - serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar)); - } - } - } - - serWorker.Append(serWorker.Create(OpCodes.Ret)); - - // Generates: end if (initialState); - serWorker.Append(initialStateLabel); - - - // setup local for dirty bits - serialize.Body.InitLocals = true; - VariableDefinition dirtyBitsLocal = new VariableDefinition(Weaver.int32Type); - serialize.Body.Variables.Add(dirtyBitsLocal); - - // get dirty bits - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked32)); - serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); - - // conditionally read each syncvar - int dirtyBit = Weaver.GetSyncVarStart(m_td.BaseType.FullName); // start at number of syncvars in parent - foreach (FieldDefinition syncVar in m_SyncVars) - { - Instruction varLabel = serWorker.Create(OpCodes.Nop); - - // check if dirty bit is set - serWorker.Append(serWorker.Create(OpCodes.Ldloc_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldc_I4, 1 << dirtyBit)); - serWorker.Append(serWorker.Create(OpCodes.And)); - serWorker.Append(serWorker.Create(OpCodes.Brfalse, varLabel)); - - MethodReference readByReferenceFunc = Weaver.GetReadByReferenceFunc(syncVar.FieldType); - if (readByReferenceFunc != null) - { - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldfld, syncVar)); - serWorker.Append(serWorker.Create(OpCodes.Call, readByReferenceFunc)); - } - else - { - MethodReference readFunc = Weaver.GetReadFunc(syncVar.FieldType); - if (readFunc == null) - { - Log.Error("GenerateDeSerialization for " + m_td.Name + " unknown type [" + syncVar.FieldType + "]. UNet [SyncVar] member variables must be basic types."); - Weaver.fail = true; - return; - } - - // check for Hook function - MethodDefinition foundMethod; - if (!CheckForHookFunction(syncVar, out foundMethod)) - { - return; - } - - if (foundMethod == null) - { - // just assign value - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Call, readFunc)); - serWorker.Append(serWorker.Create(OpCodes.Stfld, syncVar)); - } - else - { - // call hook instead - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Call, readFunc)); - serWorker.Append(serWorker.Create(OpCodes.Call, foundMethod)); - } - } - serWorker.Append(varLabel); - dirtyBit += 1; - } - - if (Weaver.generateLogErrors) - { - serWorker.Append(serWorker.Create(OpCodes.Ldstr, "Injected Deserialize " + m_td.Name)); - serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.logErrorReference)); - } - - serWorker.Append(serWorker.Create(OpCodes.Ret)); - m_td.Methods.Add(serialize); - } - - bool ProcessNetworkReaderParameters(MethodDefinition md, ILProcessor worker, bool skipFirst) - { - int count = 0; - - // read cmd args from NetworkReader - foreach (ParameterDefinition arg in md.Parameters) - { - if (count++ == 0 && skipFirst) - { - continue; - } - MethodReference readFunc = Weaver.GetReadFunc(arg.ParameterType); //? - - if (readFunc != null) - { - worker.Append(worker.Create(OpCodes.Ldarg_1)); - worker.Append(worker.Create(OpCodes.Call, readFunc)); - - // conversion.. is this needed? - if (arg.ParameterType.FullName == Weaver.singleType.FullName) - { - worker.Append(worker.Create(OpCodes.Conv_R4)); - } - else if (arg.ParameterType.FullName == Weaver.doubleType.FullName) - { - worker.Append(worker.Create(OpCodes.Conv_R8)); - } - } - else - { - Log.Error("ProcessNetworkReaderParameters for " + m_td.Name + ":" + md.Name + " type " + arg.ParameterType + " not supported"); - Weaver.fail = true; - return false; - } - } - return true; - } - - /* - // generates code like: - protected static void InvokeCmdCmdThrust(NetworkBehaviour obj, NetworkReader reader) - { - if (!NetworkServer.active) - { - return; - } - ((ShipControl)obj).CmdThrust(reader.ReadSingle(), (int)reader.ReadPackedUInt32()); - } - */ - MethodDefinition ProcessCommandInvoke(MethodDefinition md) - { - MethodDefinition cmd = new MethodDefinition(k_CmdPrefix + md.Name, MethodAttributes.Family | - MethodAttributes.Static | - MethodAttributes.HideBySig, - Weaver.voidType); - - ILProcessor cmdWorker = cmd.Body.GetILProcessor(); - Instruction label = cmdWorker.Create(OpCodes.Nop); - - WriteServerActiveCheck(cmdWorker, md.Name, label, "Command"); - - // setup for reader - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Castclass, m_td)); - - if (!ProcessNetworkReaderParameters(md, cmdWorker, false)) - return null; - - // invoke actual command function - cmdWorker.Append(cmdWorker.Create(OpCodes.Callvirt, md)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ret)); - - AddInvokeParameters(cmd.Parameters); - - return cmd; - } - - static void AddInvokeParameters(ICollection collection) - { - collection.Add(new ParameterDefinition("obj", ParameterAttributes.None, Weaver.NetworkBehaviourType2)); - collection.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType))); - } - - /* - // generates code like: - public void CallCmdThrust(float thrusting, int spin) - { - Debug.LogError("Call Command function CmdThrust"); - if (!NetworkClient.active) - { - Debug.LogError("Command function CmdThrust called on server."); - return; - } - - if (isServer) - { - // we are ON the server, invoke directly - CmdThrust(thrusting, spin); - return; - } - - NetworkWriter networkWriter = new NetworkWriter(); - networkWriter.Write(0); - networkWriter.Write((ushort)MsgType.SYSTEM_COMMAND); - networkWriter.WritePackedUInt32((uint)ShipControl.kCmdCmdThrust); - networkWriter.WritePackedUInt32((uint)playerId); - networkWriter.Write(thrusting); - networkWriter.WritePackedUInt32((uint)spin); - base.SendCommandInternal(networkWriter); - } - */ - MethodDefinition ProcessCommandCall(MethodDefinition md, CustomAttribute ca) - { - MethodDefinition cmd = new MethodDefinition("Call" + md.Name, MethodAttributes.Public | - MethodAttributes.HideBySig, - Weaver.voidType); - - // add paramters - foreach (ParameterDefinition pd in md.Parameters) - { - cmd.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType)); - } - - ILProcessor cmdWorker = cmd.Body.GetILProcessor(); - Instruction label = cmdWorker.Create(OpCodes.Nop); - - WriteSetupLocals(cmdWorker); - - if (Weaver.generateLogErrors) - { - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, "Call Command function " + md.Name)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.logErrorReference)); - } - - WriteClientActiveCheck(cmdWorker, md.Name, label, "Command function"); - - // local client check - - Instruction localClientLabel = cmdWorker.Create(OpCodes.Nop); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.UBehaviourIsServer)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Brfalse, localClientLabel)); - - // call the cmd function directly. - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); - for (int i = 0; i < md.Parameters.Count; i++) - { - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg, i + 1)); - } - cmdWorker.Append(cmdWorker.Create(OpCodes.Call, md)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ret)); - cmdWorker.Append(localClientLabel); - - WriteCreateWriter(cmdWorker); - - WriteMessageSize(cmdWorker); - - WriteMessageId(cmdWorker, 5); //UNetwork.SYSTEM_COMMAND - - // create the command id constant - FieldDefinition cmdConstant = new FieldDefinition("kCmd" + md.Name, - FieldAttributes.Static | FieldAttributes.Private, - Weaver.int32Type); - m_td.Fields.Add(cmdConstant); - - // write command constant - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldloc_0)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldsfld, cmdConstant)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); - - // write playerId from this NetworkBehaviour - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldloc_0)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); - // load unetviewfield - cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.getComponentReference)); - // load and write netId field - cmdWorker.Append(cmdWorker.Create(OpCodes.Callvirt, Weaver.getUNetIdReference)); - - var writeFunc = Weaver.GetWriteFunc(Weaver.NetworkInstanceIdType); - cmdWorker.Append(cmdWorker.Create(OpCodes.Callvirt, writeFunc)); - - if (!WriteArguments(cmdWorker, md, "Command", false)) - return null; - - // find channel for Command - int channel = 0; - foreach (var field in ca.Fields) - { - if (field.Name == "channel") - { - channel = (int)field.Argument.Value; - } - } - - var cmdName = md.Name; - int index = cmdName.IndexOf(k_CmdPrefix); - if (index > -1) - { - cmdName = cmdName.Substring(k_CmdPrefix.Length); - } - - // invoke interal send and return - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldloc_0)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldc_I4, channel)); // QoS transport channel (reliable/unreliable) - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldstr, cmdName)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Call, Weaver.sendCommandInternal)); - - cmdWorker.Append(cmdWorker.Create(OpCodes.Ret)); - - return cmd; - } - - MethodDefinition ProcessTargetRpcInvoke(MethodDefinition md) - { - MethodDefinition rpc = new MethodDefinition(k_RpcPrefix + md.Name, MethodAttributes.Family | - MethodAttributes.Static | - MethodAttributes.HideBySig, - Weaver.voidType); - - ILProcessor rpcWorker = rpc.Body.GetILProcessor(); - Instruction label = rpcWorker.Create(OpCodes.Nop); - - WriteClientActiveCheck(rpcWorker, md.Name, label, "TargetRPC"); - - // setup for reader - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Castclass, m_td)); - - //ClientScene.readyconnection - rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.ReadyConnectionReference)); - - if (!ProcessNetworkReaderParameters(md, rpcWorker, true)) - return null; - - // invoke actual command function - rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, md)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Ret)); - - AddInvokeParameters(rpc.Parameters); - - return rpc; - } - - MethodDefinition ProcessRpcInvoke(MethodDefinition md) - { - MethodDefinition rpc = new MethodDefinition(k_RpcPrefix + md.Name, MethodAttributes.Family | - MethodAttributes.Static | - MethodAttributes.HideBySig, - Weaver.voidType); - - ILProcessor rpcWorker = rpc.Body.GetILProcessor(); - Instruction label = rpcWorker.Create(OpCodes.Nop); - - WriteClientActiveCheck(rpcWorker, md.Name, label, "RPC"); - - // setup for reader - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Castclass, m_td)); - - if (!ProcessNetworkReaderParameters(md, rpcWorker, false)) - return null; - - // invoke actual command function - rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, md)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Ret)); - - AddInvokeParameters(rpc.Parameters); - - return rpc; - } - - MethodDefinition ProcessTargetRpcCall(MethodDefinition md, CustomAttribute ca) - { - MethodDefinition rpc = new MethodDefinition("Call" + md.Name, MethodAttributes.Public | - MethodAttributes.HideBySig, - Weaver.voidType); - - // add paramters - foreach (ParameterDefinition pd in md.Parameters) - { - rpc.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType)); - } - - ILProcessor rpcWorker = rpc.Body.GetILProcessor(); - Instruction label = rpcWorker.Create(OpCodes.Nop); - - WriteSetupLocals(rpcWorker); - - WriteServerActiveCheck(rpcWorker, md.Name, label, "TargetRPC Function"); - - Instruction labelConnectionCheck = rpcWorker.Create(OpCodes.Nop); - - // check specifically for ULocalConnectionToServer so a host is not trying to send - // an TargetRPC to the "server" from it's local client. - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_1)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Isinst, Weaver.ULocalConnectionToServerType)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Brfalse, labelConnectionCheck)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, string.Format("TargetRPC Function {0} called on connection to server", md.Name))); - rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.logErrorReference)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Ret)); - rpcWorker.Append(labelConnectionCheck); - - WriteCreateWriter(rpcWorker); - - WriteMessageSize(rpcWorker); - - WriteMessageId(rpcWorker, 2); // UNetwork.SYSTEM_RPC - - // create the command id constant - FieldDefinition rpcConstant = new FieldDefinition("kTargetRpc" + md.Name, - FieldAttributes.Static | FieldAttributes.Private, - Weaver.int32Type); - m_td.Fields.Add(rpcConstant); - - // write command constant - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldsfld, rpcConstant)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); - - // write this.unetView.netId - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); - // load unetviewfield - rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.getComponentReference)); - // load and write netId field - rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.getUNetIdReference)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteNetworkInstanceId)); - - if (!WriteArguments(rpcWorker, md, "TargetRPC", true)) - return null; - - // find channel for SyncEvent - int channel = 0; - foreach (var field in ca.Fields) - { - if (field.Name == "channel") - { - channel = (int)field.Argument.Value; - } - } - - var rpcName = md.Name; - int index = rpcName.IndexOf(k_TargetRpcPrefix); - if (index > -1) - { - rpcName = rpcName.Substring(k_TargetRpcPrefix.Length); - } - - // invoke SendInternal and return - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); // this - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_1)); // connection - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0)); // writer - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, channel)); // QoS transport channel (reliable/unreliable) - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendTargetRpcInternal)); - - rpcWorker.Append(rpcWorker.Create(OpCodes.Ret)); - - return rpc; - } - - MethodDefinition ProcessRpcCall(MethodDefinition md, CustomAttribute ca) - { - MethodDefinition rpc = new MethodDefinition("Call" + md.Name, MethodAttributes.Public | - MethodAttributes.HideBySig, - Weaver.voidType); - - // add paramters - foreach (ParameterDefinition pd in md.Parameters) - { - rpc.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType)); - } - - ILProcessor rpcWorker = rpc.Body.GetILProcessor(); - Instruction label = rpcWorker.Create(OpCodes.Nop); - - WriteSetupLocals(rpcWorker); - - WriteServerActiveCheck(rpcWorker, md.Name, label, "RPC Function"); - - WriteCreateWriter(rpcWorker); - - WriteMessageSize(rpcWorker); - - WriteMessageId(rpcWorker, 2); // UNetwork.SYSTEM_RPC - - // create the command id constant - FieldDefinition rpcConstant = new FieldDefinition("kRpc" + md.Name, - FieldAttributes.Static | FieldAttributes.Private, - Weaver.int32Type); - m_td.Fields.Add(rpcConstant); - - // write command constant - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldsfld, rpcConstant)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); - - // write this.unetView.netId - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); - // load unetviewfield - rpcWorker.Append(rpcWorker.Create(OpCodes.Call, Weaver.getComponentReference)); - // load and write netId field - rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.getUNetIdReference)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteNetworkInstanceId)); - - if (!WriteArguments(rpcWorker, md, "RPC", false)) - return null; - - // find channel for SyncEvent - int channel = 0; - foreach (var field in ca.Fields) - { - if (field.Name == "channel") - { - channel = (int)field.Argument.Value; - } - } - - var rpcName = md.Name; - int index = rpcName.IndexOf(k_RpcPrefix); - if (index > -1) - { - rpcName = rpcName.Substring(k_RpcPrefix.Length); - } - - // invoke SendInternal and return - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldarg_0)); // this - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldloc_0)); // writer - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldc_I4, channel)); // QoS transport channel (reliable/unreliable) - rpcWorker.Append(rpcWorker.Create(OpCodes.Ldstr, rpcName)); - rpcWorker.Append(rpcWorker.Create(OpCodes.Callvirt, Weaver.sendRpcInternal)); - - rpcWorker.Append(rpcWorker.Create(OpCodes.Ret)); - - return rpc; - } - - bool ProcessMethodsValidateFunction(MethodReference md, CustomAttribute ca, string actionType) - { - if (md.ReturnType.FullName == Weaver.IEnumeratorType.FullName) - { - Log.Error(actionType + " function [" + m_td.FullName + ":" + md.Name + "] cannot be a coroutine"); - Weaver.fail = true; - return false; - } - if (md.ReturnType.FullName != Weaver.voidType.FullName) - { - Log.Error(actionType + " function [" + m_td.FullName + ":" + md.Name + "] must have a void return type."); - Weaver.fail = true; - return false; - } - if (md.HasGenericParameters) - { - Log.Error(actionType + " [" + m_td.FullName + ":" + md.Name + "] cannot have generic parameters"); - Weaver.fail = true; - return false; - } - return true; - } - - bool ProcessMethodsValidateParameters(MethodReference md, CustomAttribute ca, string actionType) - { - for (int i = 0; i < md.Parameters.Count; ++i) - { - var p = md.Parameters[i]; - if (p.IsOut) - { - Log.Error(actionType + " function [" + m_td.FullName + ":" + md.Name + "] cannot have out parameters"); - Weaver.fail = true; - return false; - } - if (p.IsOptional) - { - Log.Error(actionType + "function [" + m_td.FullName + ":" + md.Name + "] cannot have optional parameters"); - Weaver.fail = true; - return false; - } - if (p.ParameterType.Resolve().IsAbstract) - { - Log.Error(actionType + " function [" + m_td.FullName + ":" + md.Name + "] cannot have abstract parameters"); - Weaver.fail = true; - return false; - } - if (p.ParameterType.IsByReference) - { - Log.Error(actionType + " function [" + m_td.FullName + ":" + md.Name + "] cannot have ref parameters"); - Weaver.fail = true; - return false; - } - // TargetRPC is an exception to this rule and can have a NetworkConnection as first parameter - if (p.ParameterType.FullName == Weaver.NetworkConnectionType.FullName && - !(ca.AttributeType.FullName == Weaver.TargetRpcType.FullName && i == 0)) - { - Log.Error(actionType + " [" + m_td.FullName + ":" + md.Name + "] cannot use a NetworkConnection as a parameter. To access a player object's connection on the server use connectionToClient"); - Log.Error("Name: " + ca.AttributeType.FullName + " parameter: " + md.Parameters[0].ParameterType.FullName); - Weaver.fail = true; - return false; - } - if (Weaver.IsDerivedFrom(p.ParameterType.Resolve(), Weaver.ComponentType)) - { - if (p.ParameterType.FullName != Weaver.NetworkIdentityType.FullName) - { - Log.Error(actionType + " function [" + m_td.FullName + ":" + md.Name + "] parameter [" + p.Name + - "] is of the type [" + - p.ParameterType.Name + - "] which is a Component. You cannot pass a Component to a remote call. Try passing data from within the component."); - Weaver.fail = true; - return false; - } - } - } - return true; - } - - private bool ProcessMethodsValidateCommand(MethodDefinition md, CustomAttribute ca) - { - if (md.Name.Length > 2 && md.Name.Substring(0, 3) != "Cmd") - { - Log.Error("Command function [" + m_td.FullName + ":" + md.Name + "] doesnt have 'Cmd' prefix"); - Weaver.fail = true; - return false; - } - - if (md.IsStatic) - { - Log.Error("Command function [" + m_td.FullName + ":" + md.Name + "] cant be a static method"); - Weaver.fail = true; - return false; - } - - if (!ProcessMethodsValidateFunction(md, ca, "Command")) - { - return false; - } - - if (!ProcessMethodsValidateParameters(md, ca, "Command")) - { - return false; - } - return true; - } - - bool ProcessMethodsValidateTargetRpc(MethodDefinition md, CustomAttribute ca) - { - const string targetPrefix = "Target"; - int prefixLen = targetPrefix.Length; - - if (md.Name.Length > prefixLen && md.Name.Substring(0, prefixLen) != targetPrefix) - { - Log.Error("Target Rpc function [" + m_td.FullName + ":" + md.Name + "] doesnt have 'Target' prefix"); - Weaver.fail = true; - return false; - } - - if (md.IsStatic) - { - Log.Error("TargetRpc function [" + m_td.FullName + ":" + md.Name + "] cant be a static method"); - Weaver.fail = true; - return false; - } - - if (!ProcessMethodsValidateFunction(md, ca, "Target Rpc")) - { - return false; - } - - if (md.Parameters.Count < 1) - { - Log.Error("Target Rpc function [" + m_td.FullName + ":" + md.Name + "] must have a NetworkConnection as the first parameter"); - Weaver.fail = true; - return false; - } - - if (md.Parameters[0].ParameterType.FullName != Weaver.NetworkConnectionType.FullName) - { - Log.Error("Target Rpc function [" + m_td.FullName + ":" + md.Name + "] first parameter must be a NetworkConnection"); - Weaver.fail = true; - return false; - } - - if (!ProcessMethodsValidateParameters(md, ca, "Target Rpc")) - { - return false; - } - return true; - } - - bool ProcessMethodsValidateRpc(MethodDefinition md, CustomAttribute ca) - { - if (md.Name.Length > 2 && md.Name.Substring(0, 3) != "Rpc") - { - Log.Error("Rpc function [" + m_td.FullName + ":" + md.Name + "] doesnt have 'Rpc' prefix"); - Weaver.fail = true; - return false; - } - - if (md.IsStatic) - { - Log.Error("ClientRpc function [" + m_td.FullName + ":" + md.Name + "] cant be a static method"); - Weaver.fail = true; - return false; - } - - if (!ProcessMethodsValidateFunction(md, ca, "Rpc")) - { - return false; - } - - if (!ProcessMethodsValidateParameters(md, ca, "Rpc")) - { - return false; - } - return true; - } - - void ProcessMethods() - { - HashSet names = new HashSet(); - - // find command and RPC functions - foreach (MethodDefinition md in m_td.Methods) - { - Weaver.ResetRecursionCount(); - foreach (var ca in md.CustomAttributes) - { - if (ca.AttributeType.FullName == Weaver.CommandType.FullName) - { - if (!ProcessMethodsValidateCommand(md, ca)) - return; - - if (names.Contains(md.Name)) - { - Log.Error("Duplicate Command name [" + m_td.FullName + ":" + md.Name + "]"); - Weaver.fail = true; - return; - } - names.Add(md.Name); - m_Cmds.Add(md); - - MethodDefinition cmdFunc = ProcessCommandInvoke(md); - if (cmdFunc != null) - { - m_CmdInvocationFuncs.Add(cmdFunc); - } - - MethodDefinition cmdCallFunc = ProcessCommandCall(md, ca); - if (cmdCallFunc != null) - { - m_CmdCallFuncs.Add(cmdCallFunc); - Weaver.lists.replacedMethods.Add(md); - Weaver.lists.replacementMethods.Add(cmdCallFunc); - } - break; - } - - if (ca.AttributeType.FullName == Weaver.TargetRpcType.FullName) - { - if (!ProcessMethodsValidateTargetRpc(md, ca)) - return; - - if (names.Contains(md.Name)) - { - Log.Error("Duplicate Target Rpc name [" + m_td.FullName + ":" + md.Name + "]"); - Weaver.fail = true; - return; - } - names.Add(md.Name); - m_TargetRpcs.Add(md); - - MethodDefinition rpcFunc = ProcessTargetRpcInvoke(md); - if (rpcFunc != null) - { - m_TargetRpcInvocationFuncs.Add(rpcFunc); - } - - MethodDefinition rpcCallFunc = ProcessTargetRpcCall(md, ca); - if (rpcCallFunc != null) - { - m_TargetRpcCallFuncs.Add(rpcCallFunc); - Weaver.lists.replacedMethods.Add(md); - Weaver.lists.replacementMethods.Add(rpcCallFunc); - } - break; - } - - if (ca.AttributeType.FullName == Weaver.ClientRpcType.FullName) - { - if (!ProcessMethodsValidateRpc(md, ca)) - return; - - if (names.Contains(md.Name)) - { - Log.Error("Duplicate ClientRpc name [" + m_td.FullName + ":" + md.Name + "]"); - Weaver.fail = true; - return; - } - names.Add(md.Name); - m_Rpcs.Add(md); - - MethodDefinition rpcFunc = ProcessRpcInvoke(md); - if (rpcFunc != null) - { - m_RpcInvocationFuncs.Add(rpcFunc); - } - - MethodDefinition rpcCallFunc = ProcessRpcCall(md, ca); - if (rpcCallFunc != null) - { - m_RpcCallFuncs.Add(rpcCallFunc); - Weaver.lists.replacedMethods.Add(md); - Weaver.lists.replacementMethods.Add(rpcCallFunc); - } - break; - } - } - } - - // cmds - foreach (MethodDefinition md in m_CmdInvocationFuncs) - { - m_td.Methods.Add(md); - } - foreach (MethodDefinition md in m_CmdCallFuncs) - { - m_td.Methods.Add(md); - } - - // rpcs - foreach (MethodDefinition md in m_RpcInvocationFuncs) - { - m_td.Methods.Add(md); - } - foreach (MethodDefinition md in m_TargetRpcInvocationFuncs) - { - m_td.Methods.Add(md); - } - foreach (MethodDefinition md in m_RpcCallFuncs) - { - m_td.Methods.Add(md); - } - foreach (MethodDefinition md in m_TargetRpcCallFuncs) - { - m_td.Methods.Add(md); - } - } - - MethodDefinition ProcessEventInvoke(EventDefinition ed) - { - // find the field that matches the event - FieldDefinition eventField = null; - foreach (FieldDefinition fd in m_td.Fields) - { - if (fd.FullName == ed.FullName) - { - eventField = fd; - break; - } - } - if (eventField == null) - { - Weaver.DLog(m_td, "ERROR: no event field?!"); - Weaver.fail = true; - return null; - } - - MethodDefinition cmd = new MethodDefinition("InvokeSyncEvent" + ed.Name, MethodAttributes.Family | - MethodAttributes.Static | - MethodAttributes.HideBySig, - Weaver.voidType); - - ILProcessor cmdWorker = cmd.Body.GetILProcessor(); - Instruction label1 = cmdWorker.Create(OpCodes.Nop); - Instruction label2 = cmdWorker.Create(OpCodes.Nop); - - WriteClientActiveCheck(cmdWorker, ed.Name, label1, "Event"); - - // null event check - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Castclass, m_td)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldfld, eventField)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Brtrue, label2)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ret)); - cmdWorker.Append(label2); - - // setup reader - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldarg_0)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Castclass, m_td)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ldfld, eventField)); - - // read the event arguments - MethodReference invoke = Weaver.ResolveMethod(eventField.FieldType, "Invoke"); - if (!ProcessNetworkReaderParameters(invoke.Resolve(), cmdWorker, false)) - return null; - - // invoke actual event delegate function - cmdWorker.Append(cmdWorker.Create(OpCodes.Callvirt, invoke)); - cmdWorker.Append(cmdWorker.Create(OpCodes.Ret)); - - AddInvokeParameters(cmd.Parameters); - - return cmd; - } - - MethodDefinition ProcessEventCall(EventDefinition ed, CustomAttribute ca) - { - MethodReference invoke = Weaver.ResolveMethod(ed.EventType, "Invoke"); - MethodDefinition evt = new MethodDefinition("Call" + ed.Name, MethodAttributes.Public | - MethodAttributes.HideBySig, - Weaver.voidType); - // add paramters - foreach (ParameterDefinition pd in invoke.Parameters) - { - evt.Parameters.Add(new ParameterDefinition(pd.Name, ParameterAttributes.None, pd.ParameterType)); - } - - ILProcessor evtWorker = evt.Body.GetILProcessor(); - Instruction label = evtWorker.Create(OpCodes.Nop); - - WriteSetupLocals(evtWorker); - - WriteServerActiveCheck(evtWorker, ed.Name, label, "Event"); - - WriteCreateWriter(evtWorker); - - WriteMessageSize(evtWorker); - - WriteMessageId(evtWorker, 7); //UNetwork.SYSTEM_SYNCEVENT - - // create the command id constant - FieldDefinition evtConstant = new FieldDefinition("kEvent" + ed.Name, - FieldAttributes.Static | FieldAttributes.Private, - Weaver.int32Type); - m_td.Fields.Add(evtConstant); - - // write command constant - evtWorker.Append(evtWorker.Create(OpCodes.Ldloc_0)); // networkWriter - evtWorker.Append(evtWorker.Create(OpCodes.Ldsfld, evtConstant)); - evtWorker.Append(evtWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); - - // write this.unetView.netId - evtWorker.Append(evtWorker.Create(OpCodes.Ldloc_0)); // networkWriter - evtWorker.Append(evtWorker.Create(OpCodes.Ldarg_0)); // this - evtWorker.Append(evtWorker.Create(OpCodes.Call, Weaver.getComponentReference)); // unetView - // load and write netId field - evtWorker.Append(evtWorker.Create(OpCodes.Callvirt, Weaver.getUNetIdReference)); // netId - evtWorker.Append(evtWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteNetworkInstanceId)); // networkWriter.Write(this.unetView.netId) - - if (!WriteArguments(evtWorker, invoke.Resolve(), "SyncEvent", false)) - return null; - - // find channel for ClientRpc - int channel = 0; - foreach (var field in ca.Fields) - { - if (field.Name == "channel") - { - channel = (int)field.Argument.Value; - } - } - - // invoke interal send and return - evtWorker.Append(evtWorker.Create(OpCodes.Ldarg_0)); // this - evtWorker.Append(evtWorker.Create(OpCodes.Ldloc_0)); // writer - evtWorker.Append(evtWorker.Create(OpCodes.Ldc_I4, channel)); // QoS transport channel (reliable/unreliable) - evtWorker.Append(evtWorker.Create(OpCodes.Ldstr, ed.Name)); - evtWorker.Append(evtWorker.Create(OpCodes.Call, Weaver.sendEventInternal)); - - evtWorker.Append(evtWorker.Create(OpCodes.Ret)); - - return evt; - } - - void ProcessEvents() - { - // find events - foreach (EventDefinition ed in m_td.Events) - { - foreach (var ca in ed.CustomAttributes) - { - if (ca.AttributeType.FullName == Weaver.SyncEventType.FullName) - { - if (ed.Name.Length > 4 && ed.Name.Substring(0, 5) != "Event") - { - Log.Error("Event [" + m_td.FullName + ":" + ed.FullName + "] doesnt have 'Event' prefix"); - Weaver.fail = true; - return; - } - - if (ed.EventType.Resolve().HasGenericParameters) - { - Log.Error("Event [" + m_td.FullName + ":" + ed.FullName + "] cannot have generic parameters"); - Weaver.fail = true; - return; - } - - m_Events.Add(ed); - MethodDefinition eventFunc = ProcessEventInvoke(ed); - if (eventFunc == null) - { - return; - } - - m_td.Methods.Add(eventFunc); - m_EventInvocationFuncs.Add(eventFunc); - - Weaver.DLog(m_td, "ProcessEvent " + ed); - - MethodDefinition eventCallFunc = ProcessEventCall(ed, ca); - m_td.Methods.Add(eventCallFunc); - - Weaver.lists.replacedEvents.Add(ed); - Weaver.lists.replacementEvents.Add(eventCallFunc); - - Weaver.DLog(m_td, " Event: " + ed.Name); - break; - } - } - } - } - - static MethodDefinition ProcessSyncVarGet(FieldDefinition fd, string originalName) - { - //Create the get method - MethodDefinition get = new MethodDefinition( - "get_Network" + originalName, MethodAttributes.Public | - MethodAttributes.SpecialName | - MethodAttributes.HideBySig, - fd.FieldType); - - ILProcessor getWorker = get.Body.GetILProcessor(); - - getWorker.Append(getWorker.Create(OpCodes.Ldarg_0)); - getWorker.Append(getWorker.Create(OpCodes.Ldfld, fd)); - getWorker.Append(getWorker.Create(OpCodes.Ret)); - - get.Body.Variables.Add(new VariableDefinition(fd.FieldType)); - get.Body.InitLocals = true; - get.SemanticsAttributes = MethodSemanticsAttributes.Getter; - - return get; - } - - MethodDefinition ProcessSyncVarSet(FieldDefinition fd, string originalName, int dirtyBit, FieldDefinition netFieldId) - { - //Create the set method - MethodDefinition set = new MethodDefinition("set_Network" + originalName, MethodAttributes.Public | - MethodAttributes.SpecialName | - MethodAttributes.HideBySig, - Weaver.voidType); - - ILProcessor setWorker = set.Body.GetILProcessor(); - - // this - setWorker.Append(setWorker.Create(OpCodes.Ldarg_0)); - - // new value to set - setWorker.Append(setWorker.Create(OpCodes.Ldarg_1)); - - // reference to field to set - setWorker.Append(setWorker.Create(OpCodes.Ldarg_0)); - setWorker.Append(setWorker.Create(OpCodes.Ldflda, fd)); - - // dirty bit - setWorker.Append(setWorker.Create(OpCodes.Ldc_I4, dirtyBit)); - - MethodDefinition hookFunctionMethod; - CheckForHookFunction(fd, out hookFunctionMethod); - - if (hookFunctionMethod != null) - { - //if (NetworkServer.localClientActive && !syncVarHookGuard) - Instruction label = setWorker.Create(OpCodes.Nop); - setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.NetworkServerGetLocalClientActive)); - setWorker.Append(setWorker.Create(OpCodes.Brfalse, label)); - setWorker.Append(setWorker.Create(OpCodes.Ldarg_0)); - setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.getSyncVarHookGuard)); - setWorker.Append(setWorker.Create(OpCodes.Brtrue, label)); - - // syncVarHookGuard = true; - setWorker.Append(setWorker.Create(OpCodes.Ldarg_0)); - setWorker.Append(setWorker.Create(OpCodes.Ldc_I4_1)); - setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarHookGuard)); - - // call hook - setWorker.Append(setWorker.Create(OpCodes.Ldarg_0)); - setWorker.Append(setWorker.Create(OpCodes.Ldarg_1)); - setWorker.Append(setWorker.Create(OpCodes.Call, hookFunctionMethod)); - - // syncVarHookGuard = false; - setWorker.Append(setWorker.Create(OpCodes.Ldarg_0)); - setWorker.Append(setWorker.Create(OpCodes.Ldc_I4_0)); - setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarHookGuard)); - - setWorker.Append(label); - } - - if (fd.FieldType.FullName == Weaver.gameObjectType.FullName) - { - // reference to netId Field to set - setWorker.Append(setWorker.Create(OpCodes.Ldarg_0)); - setWorker.Append(setWorker.Create(OpCodes.Ldflda, netFieldId)); - - setWorker.Append(setWorker.Create(OpCodes.Call, Weaver.setSyncVarGameObjectReference)); - } - else - { - // make generic version of SetSyncVar with field type - GenericInstanceMethod gm = new GenericInstanceMethod(Weaver.setSyncVarReference); - gm.GenericArguments.Add(fd.FieldType); - - // invoke SetSyncVar - setWorker.Append(setWorker.Create(OpCodes.Call, gm)); - } - - setWorker.Append(setWorker.Create(OpCodes.Ret)); - - set.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.In, fd.FieldType)); - set.SemanticsAttributes = MethodSemanticsAttributes.Setter; - - return set; - } - - void ProcessSyncVar(FieldDefinition fd, int dirtyBit) - { - string originalName = fd.Name; - - Weaver.lists.replacedFields.Add(fd); - Weaver.DLog(m_td, "Sync Var " + fd.Name + " " + fd.FieldType + " " + Weaver.gameObjectType); - - // GameObject SyncVars have a new field for netId - FieldDefinition netFieldId = null; - if (fd.FieldType.FullName == Weaver.gameObjectType.FullName) - { - netFieldId = new FieldDefinition("___" + fd.Name + "NetId", - FieldAttributes.Private, - Weaver.NetworkInstanceIdType); - - m_SyncVarNetIds.Add(netFieldId); - Weaver.lists.netIdFields.Add(netFieldId); - } - - var get = ProcessSyncVarGet(fd, originalName); - var set = ProcessSyncVarSet(fd, originalName, dirtyBit, netFieldId); - - //NOTE: is property even needed? Could just use a setter function? - //create the property - PropertyDefinition propertyDefinition = new PropertyDefinition("Network" + originalName, PropertyAttributes.None, fd.FieldType) - { - GetMethod = get, SetMethod = set - }; - - //add the methods and property to the type. - m_td.Methods.Add(get); - m_td.Methods.Add(set); - m_td.Properties.Add(propertyDefinition); - Weaver.lists.replacementProperties.Add(set); - } - - /* - Generates code like: - // SyncListTestPlayerBehaviour - protected static void InvokeSyncListm_ints(NetworkBehaviour obj, NetworkReader reader) - { - if (!NetworkClient.active) - { - Debug.LogError("SyncList m_ints called on server."); - return; - } - ((SyncListTestPlayerBehaviour)obj).m_ints.HandleMsg(reader); - } - */ - static MethodDefinition ProcessSyncListInvoke(FieldDefinition fd) - { - MethodDefinition cmd = new MethodDefinition("InvokeSyncList" + fd.Name, MethodAttributes.Family | - MethodAttributes.Static | - MethodAttributes.HideBySig, - Weaver.voidType); - - ILProcessor syncList = cmd.Body.GetILProcessor(); - Instruction label = syncList.Create(OpCodes.Nop); - - - WriteClientActiveCheck(syncList, fd.Name, label, "SyncList"); - - - syncList.Append(syncList.Create(OpCodes.Ldarg_0)); //this - syncList.Append(syncList.Create(OpCodes.Castclass, fd.DeclaringType)); - syncList.Append(syncList.Create(OpCodes.Ldfld, fd)); // list field - syncList.Append(syncList.Create(OpCodes.Ldarg_1)); // reader - - // make specialized version of HandleMsg - GenericInstanceType syncListGeneric = (GenericInstanceType)fd.FieldType.Resolve().BaseType; - syncListGeneric = (GenericInstanceType)Weaver.scriptDef.MainModule.ImportReference(syncListGeneric); - TypeReference listValueType = syncListGeneric.GenericArguments[0]; - MethodReference genericHandleMsgMethod = Helpers.MakeHostInstanceGeneric(Weaver.SyncListInitHandleMsg, listValueType); - syncList.Append(syncList.Create(OpCodes.Callvirt, genericHandleMsgMethod)); - - syncList.Append(syncList.Create(OpCodes.Ret)); - - AddInvokeParameters(cmd.Parameters); - - return cmd; - } - - FieldDefinition ProcessSyncList(FieldDefinition fd, int dirtyBit) - { - MethodDefinition syncListFunc = ProcessSyncListInvoke(fd); - m_SyncListInvocationFuncs.Add(syncListFunc); - - // create the command id constant - return new FieldDefinition("kList" + fd.Name, - FieldAttributes.Static | FieldAttributes.Private, - Weaver.int32Type); - } - - void ProcessSyncVars() - { - int numSyncVars = 0; - - // the mapping of dirtybits to sync-vars is implicit in the order of the fields here. this order is recorded in m_replacementProperties. - // start assigning syncvars at the place the base class stopped, if any - int dirtyBitCounter = Weaver.GetSyncVarStart(m_td.BaseType.FullName); - - m_SyncVarNetIds.Clear(); - List listFields = new List(); - - // find syncvars - foreach (FieldDefinition fd in m_td.Fields) - { - foreach (var ca in fd.CustomAttributes) - { - if (ca.AttributeType.FullName == Weaver.SyncVarType.FullName) - { - var resolvedField = fd.FieldType.Resolve(); - - if (Weaver.IsDerivedFrom(resolvedField, Weaver.NetworkBehaviourType)) - { - Log.Error("SyncVar [" + fd.FullName + "] cannot be derived from NetworkBehaviour."); - Weaver.fail = true; - return; - } - - if (Weaver.IsDerivedFrom(resolvedField, Weaver.ScriptableObjectType)) - { - Log.Error("SyncVar [" + fd.FullName + "] cannot be derived from ScriptableObject."); - Weaver.fail = true; - return; - } - - if ((fd.Attributes & FieldAttributes.Static) != 0) - { - Log.Error("SyncVar [" + fd.FullName + "] cannot be static."); - Weaver.fail = true; - return; - } - - if (resolvedField.HasGenericParameters) - { - Log.Error("SyncVar [" + fd.FullName + "] cannot have generic parameters."); - Weaver.fail = true; - return; - } - - if (resolvedField.IsInterface) - { - Log.Error("SyncVar [" + fd.FullName + "] cannot be an interface."); - Weaver.fail = true; - return; - } - - var fieldModuleName = resolvedField.Module.Name; - if (fieldModuleName != Weaver.scriptDef.MainModule.Name && - fieldModuleName != Weaver.m_UnityAssemblyDefinition.MainModule.Name && - fieldModuleName != Weaver.m_UNetAssemblyDefinition.MainModule.Name && - fieldModuleName != Weaver.corLib.Name && - fieldModuleName != "netstandard.dll" && - fieldModuleName != "System.Runtime.dll" // this is only for Metro, built-in types are not in corlib on metro - ) - { - Log.Error("SyncVar [" + fd.FullName + "] from " + resolvedField.Module.ToString() + " cannot be a different module."); - Weaver.fail = true; - return; - } - - if (fd.FieldType.IsArray) - { - Log.Error("SyncVar [" + fd.FullName + "] cannot be an array. Use a SyncList instead."); - Weaver.fail = true; - return; - } - - if (Helpers.InheritsFromSyncList(fd.FieldType)) - { - Log.Warning(string.Format("Script class [{0}] has [SyncVar] attribute on SyncList field {1}, SyncLists should not be marked with SyncVar.", m_td.FullName, fd.Name)); - break; - } - - m_SyncVars.Add(fd); - - ProcessSyncVar(fd, 1 << dirtyBitCounter); - dirtyBitCounter += 1; - numSyncVars += 1; - - if (dirtyBitCounter == k_SyncVarLimit) - { - Log.Error("Script class [" + m_td.FullName + "] has too many SyncVars (" + k_SyncVarLimit + "). (This could include base classes)"); - Weaver.fail = true; - return; - } - break; - } - } - - if (fd.FieldType.FullName.Contains("UnityEngine.Networking.SyncListStruct")) - { - Log.Error("SyncListStruct member variable [" + fd.FullName + "] must use a dervied class, like \"class MySyncList : SyncListStruct {}\"."); - Weaver.fail = true; - return; - } - - if (Weaver.IsDerivedFrom(fd.FieldType.Resolve(), Weaver.SyncListType)) - { - if (fd.IsStatic) - { - Log.Error("SyncList [" + m_td.FullName + ":" + fd.FullName + "] cannot be a static"); - Weaver.fail = true; - return; - } - - m_SyncVars.Add(fd); - m_SyncLists.Add(fd); - listFields.Add(ProcessSyncList(fd, 1 << dirtyBitCounter)); - dirtyBitCounter += 1; - numSyncVars += 1; - - if (dirtyBitCounter == k_SyncVarLimit) - { - Log.Error("Script class [" + m_td.FullName + "] has too many SyncVars (" + k_SyncVarLimit + "). (This could include base classes)"); - Weaver.fail = true; - return; - } - } - } - - foreach (FieldDefinition fd in listFields) - { - m_td.Fields.Add(fd); - m_SyncListStaticFields.Add(fd); - } - - foreach (FieldDefinition fd in m_SyncVarNetIds) - { - m_td.Fields.Add(fd); - } - - foreach (var func in m_SyncListInvocationFuncs) - { - m_td.Methods.Add(func); - } - - Weaver.SetNumSyncVars(m_td.FullName, numSyncVars); - } - - // Copy of Mono string.GetHashCode(), so that we generate same hashes regardless of runtime (mono/MS .NET) - private static int GetHashCode(string s) - { - unsafe - { - int length = s.Length; - fixed(char* c = s) - { - char* cc = c; - char* end = cc + length - 1; - int h = 0; - for (; cc < end; cc += 2) - { - h = (h << 5) - h + *cc; - h = (h << 5) - h + cc[1]; - } - ++end; - if (cc < end) - h = (h << 5) - h + *cc; - return h; - } - } - } - - bool HasMethod(string name) - { - foreach (var method in m_td.Methods) - { - if (method.Name == name) - { - return true; - } - } - return false; - } - }; -} diff --git a/Extensions/Networking/Weaver/UNetWeaver.cs b/Extensions/Networking/Weaver/UNetWeaver.cs deleted file mode 100644 index 838c8a8269..0000000000 --- a/Extensions/Networking/Weaver/UNetWeaver.cs +++ /dev/null @@ -1,1907 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using Mono.Cecil; -using Mono.Cecil.Cil; -using System.Linq; -using Mono.Cecil.Pdb; -using Mono.Cecil.Mdb; - -namespace Unity.UNetWeaver -{ - public enum OutSymbolsFormat - { - None, - Pdb, - Mdb - } - - // This data is flushed each time - if we are run multiple times in the same process/domain - class WeaverLists - { - // [SyncVar] member variables that should be replaced - public List replacedFields = new List(); - // setter functions that replace [SyncVar] member variable references - public List replacementProperties = new List(); - // GameObject SyncVar generated netId fields - public List netIdFields = new List(); - - // [Command]/[ClientRpc] functions that should be replaced - public List replacedMethods = new List(); - // remote call functions that replace [Command]/[ClientRpc] references - public List replacementMethods = new List(); - - public HashSet replacementMethodNames = new HashSet(); - - // [SyncEvent] invoke functions that should be replaced - public List replacedEvents = new List(); - // remote call functions that replace [SyncEvent] references - public List replacementEvents = new List(); - - public Dictionary readFuncs; - public Dictionary readByReferenceFuncs; - public Dictionary writeFuncs; - - public List generatedReadFunctions = new List(); - public List generatedWriteFunctions = new List(); - - public TypeDefinition generateContainerClass; - public Dictionary numSyncVars = new Dictionary(); - } - - class Weaver - { - // UNetwork types - public static TypeReference NetworkBehaviourType; - public static TypeReference NetworkBehaviourType2; - public static TypeReference MonoBehaviourType; - public static TypeReference ScriptableObjectType; - public static TypeReference NetworkConnectionType; - public static TypeReference ULocalConnectionToServerType; - public static TypeReference ULocalConnectionToClientType; - - public static TypeReference MessageBaseType; - public static TypeReference SyncListStructType; - - public static MethodReference NetworkBehaviourDirtyBitsReference; - public static TypeReference NetworkClientType; - public static TypeReference NetworkServerType; - public static TypeReference NetworkCRCType; - - public static TypeReference NetworkReaderType; - public static TypeDefinition NetworkReaderDef; - - public static TypeReference NetworkWriterType; - public static TypeDefinition NetworkWriterDef; - - public static MethodReference NetworkWriterCtor; - public static MethodReference NetworkReaderCtor; - public static TypeReference MemoryStreamType; - public static MethodReference MemoryStreamCtor; - public static MethodReference getComponentReference; - public static MethodReference getUNetIdReference; - public static MethodReference getPlayerIdReference; - public static TypeReference NetworkIdentityType; - public static TypeReference NetworkInstanceIdType; - public static TypeReference NetworkSceneIdType; - public static TypeReference IEnumeratorType; - - public static TypeReference ClientSceneType; - public static MethodReference FindLocalObjectReference; - public static MethodReference RegisterBehaviourReference; - public static MethodReference ReadyConnectionReference; - - public static TypeReference ComponentType; - - public static TypeReference CmdDelegateReference; - public static MethodReference CmdDelegateConstructor; - - public static MethodReference NetworkReaderReadInt32; - - public static MethodReference NetworkWriterWriteInt32; - public static MethodReference NetworkWriterWriteInt16; - - public static MethodReference NetworkServerGetActive; - public static MethodReference NetworkServerGetLocalClientActive; - public static MethodReference NetworkClientGetActive; - public static MethodReference UBehaviourIsServer; - public static MethodReference NetworkReaderReadPacked32; - public static MethodReference NetworkReaderReadPacked64; - public static MethodReference NetworkReaderReadByte; - public static MethodReference NetworkWriterWritePacked32; - public static MethodReference NetworkWriterWritePacked64; - - public static MethodReference NetworkWriterWriteNetworkInstanceId; - public static MethodReference NetworkWriterWriteNetworkSceneId; - - public static MethodReference NetworkReaderReadNetworkInstanceId; - public static MethodReference NetworkReaderReadNetworkSceneId; - public static MethodReference NetworkInstanceIsEmpty; - - public static MethodReference NetworkReadUInt16; - public static MethodReference NetworkWriteUInt16; - - // custom attribute types - public static TypeReference SyncVarType; - public static TypeReference CommandType; - public static TypeReference ClientRpcType; - public static TypeReference TargetRpcType; - public static TypeReference SyncEventType; - public static TypeReference SyncListType; - public static MethodReference SyncListInitBehaviourReference; - public static MethodReference SyncListInitHandleMsg; - public static MethodReference SyncListClear; - public static TypeReference NetworkSettingsType; - - // sync list types - public static TypeReference SyncListFloatType; - public static TypeReference SyncListIntType; - public static TypeReference SyncListUIntType; - public static TypeReference SyncListBoolType; - public static TypeReference SyncListStringType; - - public static MethodReference SyncListFloatReadType; - public static MethodReference SyncListIntReadType; - public static MethodReference SyncListUIntReadType; - public static MethodReference SyncListStringReadType; - public static MethodReference SyncListBoolReadType; - - public static MethodReference SyncListFloatWriteType; - public static MethodReference SyncListIntWriteType; - public static MethodReference SyncListUIntWriteType; - public static MethodReference SyncListBoolWriteType; - public static MethodReference SyncListStringWriteType; - - // system types - public static TypeReference voidType; - public static TypeReference singleType; - public static TypeReference doubleType; - public static TypeReference decimalType; - public static TypeReference boolType; - public static TypeReference stringType; - public static TypeReference int64Type; - public static TypeReference uint64Type; - public static TypeReference int32Type; - public static TypeReference uint32Type; - public static TypeReference int16Type; - public static TypeReference uint16Type; - public static TypeReference byteType; - public static TypeReference sbyteType; - public static TypeReference charType; - public static TypeReference objectType; - public static TypeReference valueTypeType; - public static TypeReference vector2Type; - public static TypeReference vector3Type; - public static TypeReference vector4Type; - public static TypeReference colorType; - public static TypeReference color32Type; - public static TypeReference quaternionType; - public static TypeReference rectType; - public static TypeReference rayType; - public static TypeReference planeType; - public static TypeReference matrixType; - public static TypeReference hashType; - public static TypeReference typeType; - public static TypeReference gameObjectType; - public static TypeReference transformType; - public static TypeReference unityObjectType; - public static MethodReference gameObjectInequality; - - public static MethodReference setSyncVarReference; - public static MethodReference setSyncVarHookGuard; - public static MethodReference getSyncVarHookGuard; - public static MethodReference setSyncVarGameObjectReference; - public static MethodReference registerCommandDelegateReference; - public static MethodReference registerRpcDelegateReference; - public static MethodReference registerEventDelegateReference; - public static MethodReference registerSyncListDelegateReference; - public static MethodReference getTypeReference; - public static MethodReference getTypeFromHandleReference; - public static MethodReference logErrorReference; - public static MethodReference logWarningReference; - public static MethodReference sendCommandInternal; - public static MethodReference sendRpcInternal; - public static MethodReference sendTargetRpcInternal; - public static MethodReference sendEventInternal; - - public static WeaverLists lists; - - public static AssemblyDefinition scriptDef; - public static ModuleDefinition corLib; - public static AssemblyDefinition m_UnityAssemblyDefinition; - public static AssemblyDefinition m_UNetAssemblyDefinition; - - static bool m_DebugFlag = true; - - public static bool fail; - public static bool generateLogErrors = false; - - // this is used to prevent stack overflows when generating serialization code when there are self-referencing types. - // All the utility classes use GetWriteFunc() to generate serialization code, so the recursion check is implemented there instead of in each utility class. - // A NetworkBehaviour with the max SyncVars (32) can legitimately increment this value to 65 - so max must be higher than that - const int MaxRecursionCount = 128; - static int s_RecursionCount; - public static void ResetRecursionCount() - { - s_RecursionCount = 0; - } - - public static bool CanBeResolved(TypeReference parent) - { - while (parent != null) - { - if (parent.Scope.Name == "Windows") - { - return false; - } - - if (parent.Scope.Name == "mscorlib") - { - var resolved = parent.Resolve(); - return resolved != null; - } - - try - { - parent = parent.Resolve().BaseType; - } - catch - { - return false; - } - } - return true; - } - - public static bool IsArrayType(TypeReference variable) - { - if ((variable.IsArray && ((ArrayType)variable).ElementType.IsArray) || // jagged array - (variable.IsArray && ((ArrayType)variable).Rank > 1)) // multidimensional array - return false; - return true; - } - - public static void DLog(TypeDefinition td, string fmt, params object[] args) - { - if (!m_DebugFlag) - return; - - Console.WriteLine("[" + td.Name + "] " + String.Format(fmt, args)); - } - - public static int GetSyncVarStart(string className) - { - if (lists.numSyncVars.ContainsKey(className)) - { - int num = lists.numSyncVars[className]; - return num; - } - // start at zero - return 0; - } - - public static void SetNumSyncVars(string className, int num) - { - lists.numSyncVars[className] = num; - } - - public static MethodReference GetWriteFunc(TypeReference variable) - { - if (s_RecursionCount++ > MaxRecursionCount) - { - Log.Error("GetWriteFunc recursion depth exceeded for " + variable.Name + ". Check for self-referencing member variables."); - fail = true; - return null; - } - - if (lists.writeFuncs.ContainsKey(variable.FullName)) - { - var foundFunc = lists.writeFuncs[variable.FullName]; - if (foundFunc.Parameters[0].ParameterType.IsArray == variable.IsArray) - { - return foundFunc; - } - } - - if (variable.IsByReference) - { - // error?? - Log.Error("GetWriteFunc variable.IsByReference error."); - return null; - } - - MethodDefinition newWriterFunc; - - if (variable.IsArray) - { - var elementType = variable.GetElementType(); - var elemenWriteFunc = GetWriteFunc(elementType); - if (elemenWriteFunc == null) - { - return null; - } - newWriterFunc = GenerateArrayWriteFunc(variable, elemenWriteFunc); - } - else - { - if (variable.Resolve().IsEnum) - { - return NetworkWriterWriteInt32; - } - - newWriterFunc = GenerateWriterFunction(variable); - } - - if (newWriterFunc == null) - { - return null; - } - - RegisterWriteFunc(variable.FullName, newWriterFunc); - return newWriterFunc; - } - - static public void RegisterWriteFunc(string name, MethodDefinition newWriterFunc) - { - lists.writeFuncs[name] = newWriterFunc; - lists.generatedWriteFunctions.Add(newWriterFunc); - - ConfirmGeneratedCodeClass(scriptDef.MainModule); - lists.generateContainerClass.Methods.Add(newWriterFunc); - } - - public static MethodReference GetReadByReferenceFunc(TypeReference variable) - { - if (lists.readByReferenceFuncs.ContainsKey(variable.FullName)) - { - return lists.readByReferenceFuncs[variable.FullName]; - } - return null; - } - - public static MethodReference GetReadFunc(TypeReference variable) - { - if (lists.readFuncs.ContainsKey(variable.FullName)) - { - var foundFunc = lists.readFuncs[variable.FullName]; - if (foundFunc.ReturnType.IsArray == variable.IsArray) - { - return foundFunc; - } - } - - var td = variable.Resolve(); - if (td == null) - { - Log.Error("GetReadFunc unsupported type " + variable.FullName); - return null; - } - - if (variable.IsByReference) - { - // error?? - Log.Error("GetReadFunc variable.IsByReference error."); - return null; - } - - MethodDefinition newReaderFunc; - - if (variable.IsArray) - { - var elementType = variable.GetElementType(); - var elementReadFunc = GetReadFunc(elementType); - if (elementReadFunc == null) - { - return null; - } - newReaderFunc = GenerateArrayReadFunc(variable, elementReadFunc); - } - else - { - if (td.IsEnum) - { - return NetworkReaderReadInt32; - } - - newReaderFunc = GenerateReadFunction(variable); - } - - if (newReaderFunc == null) - { - Log.Error("GetReadFunc unable to generate function for:" + variable.FullName); - return null; - } - RegisterReadFunc(variable.FullName, newReaderFunc); - return newReaderFunc; - } - - static public void RegisterReadByReferenceFunc(string name, MethodDefinition newReaderFunc) - { - lists.readByReferenceFuncs[name] = newReaderFunc; - lists.generatedReadFunctions.Add(newReaderFunc); - - ConfirmGeneratedCodeClass(scriptDef.MainModule); - lists.generateContainerClass.Methods.Add(newReaderFunc); - } - - static public void RegisterReadFunc(string name, MethodDefinition newReaderFunc) - { - lists.readFuncs[name] = newReaderFunc; - lists.generatedReadFunctions.Add(newReaderFunc); - - ConfirmGeneratedCodeClass(scriptDef.MainModule); - lists.generateContainerClass.Methods.Add(newReaderFunc); - } - - static MethodDefinition GenerateArrayReadFunc(TypeReference variable, MethodReference elementReadFunc) - { - if (!IsArrayType(variable)) - { - Log.Error(variable.FullName + " is an unsupported array type. Jagged and multidimensional arrays are not supported"); - return null; - } - var functionName = "_ReadArray" + variable.GetElementType().Name + "_"; - if (variable.DeclaringType != null) - { - functionName += variable.DeclaringType.Name; - } - else - { - functionName += "None"; - } - - // create new reader for this type - MethodDefinition readerFunc = new MethodDefinition(functionName, - MethodAttributes.Public | - MethodAttributes.Static | - MethodAttributes.HideBySig, - variable); - - readerFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, scriptDef.MainModule.ImportReference(NetworkReaderType))); - - readerFunc.Body.Variables.Add(new VariableDefinition(int32Type)); - readerFunc.Body.Variables.Add(new VariableDefinition(variable)); - readerFunc.Body.Variables.Add(new VariableDefinition(int32Type)); - readerFunc.Body.InitLocals = true; - - ILProcessor worker = readerFunc.Body.GetILProcessor(); - - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Call, NetworkReadUInt16)); - worker.Append(worker.Create(OpCodes.Stloc_0)); - worker.Append(worker.Create(OpCodes.Ldloc_0)); - - Instruction labelEmptyArray = worker.Create(OpCodes.Nop); - worker.Append(worker.Create(OpCodes.Brtrue, labelEmptyArray)); - - // return empty array - worker.Append(worker.Create(OpCodes.Ldc_I4_0)); - worker.Append(worker.Create(OpCodes.Newarr, variable.GetElementType())); - worker.Append(worker.Create(OpCodes.Ret)); - - // create the actual array - worker.Append(labelEmptyArray); - worker.Append(worker.Create(OpCodes.Ldloc_0)); - worker.Append(worker.Create(OpCodes.Newarr, variable.GetElementType())); - worker.Append(worker.Create(OpCodes.Stloc_1)); - worker.Append(worker.Create(OpCodes.Ldc_I4_0)); - worker.Append(worker.Create(OpCodes.Stloc_2)); - - // loop start - Instruction labelHead = worker.Create(OpCodes.Nop); - worker.Append(worker.Create(OpCodes.Br, labelHead)); - - // loop body - Instruction labelBody = worker.Create(OpCodes.Nop); - worker.Append(labelBody); - worker.Append(worker.Create(OpCodes.Ldloc_1)); - worker.Append(worker.Create(OpCodes.Ldloc_2)); - worker.Append(worker.Create(OpCodes.Ldelema, variable.GetElementType())); - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Call, elementReadFunc)); - worker.Append(worker.Create(OpCodes.Stobj, variable.GetElementType())); - worker.Append(worker.Create(OpCodes.Ldloc_2)); - worker.Append(worker.Create(OpCodes.Ldc_I4_1)); - worker.Append(worker.Create(OpCodes.Add)); - worker.Append(worker.Create(OpCodes.Stloc_2)); - - // loop while check - worker.Append(labelHead); - worker.Append(worker.Create(OpCodes.Ldloc_2)); - worker.Append(worker.Create(OpCodes.Ldloc_0)); - worker.Append(worker.Create(OpCodes.Blt, labelBody)); - - worker.Append(worker.Create(OpCodes.Ldloc_1)); - worker.Append(worker.Create(OpCodes.Ret)); - return readerFunc; - } - - static MethodDefinition GenerateArrayWriteFunc(TypeReference variable, MethodReference elementWriteFunc) - { - if (!IsArrayType(variable)) - { - Log.Error(variable.FullName + " is an unsupported array type. Jagged and multidimensional arrays are not supported"); - return null; - } - var functionName = "_WriteArray" + variable.GetElementType().Name + "_"; - if (variable.DeclaringType != null) - { - functionName += variable.DeclaringType.Name; - } - else - { - functionName += "None"; - } - - // create new writer for this type - MethodDefinition writerFunc = new MethodDefinition(functionName, - MethodAttributes.Public | - MethodAttributes.Static | - MethodAttributes.HideBySig, - voidType); - - writerFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, scriptDef.MainModule.ImportReference(NetworkWriterType))); - writerFunc.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, scriptDef.MainModule.ImportReference(variable))); - - writerFunc.Body.Variables.Add(new VariableDefinition(uint16Type)); - writerFunc.Body.Variables.Add(new VariableDefinition(uint16Type)); - writerFunc.Body.InitLocals = true; - - ILProcessor worker = writerFunc.Body.GetILProcessor(); - - // null check - Instruction labelNull = worker.Create(OpCodes.Nop); - worker.Append(worker.Create(OpCodes.Ldarg_1)); - worker.Append(worker.Create(OpCodes.Brtrue, labelNull)); - - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Ldc_I4_0)); - worker.Append(worker.Create(OpCodes.Call, NetworkWriteUInt16)); - worker.Append(worker.Create(OpCodes.Ret)); - - // setup array length local variable - worker.Append(labelNull); - worker.Append(worker.Create(OpCodes.Ldarg_1)); - worker.Append(worker.Create(OpCodes.Ldlen)); - worker.Append(worker.Create(OpCodes.Conv_I4)); - worker.Append(worker.Create(OpCodes.Conv_U2)); - worker.Append(worker.Create(OpCodes.Stloc_0)); - - //write length - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Ldloc_0)); - worker.Append(worker.Create(OpCodes.Call, NetworkWriteUInt16)); - - // start loop - worker.Append(worker.Create(OpCodes.Ldc_I4_0)); - worker.Append(worker.Create(OpCodes.Stloc_1)); - Instruction labelHead = worker.Create(OpCodes.Nop); - worker.Append(worker.Create(OpCodes.Br, labelHead)); - - // loop body - Instruction labelBody = worker.Create(OpCodes.Nop); - worker.Append(labelBody); - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Ldarg_1)); - worker.Append(worker.Create(OpCodes.Ldloc_1)); - worker.Append(worker.Create(OpCodes.Ldelema, variable.GetElementType())); - worker.Append(worker.Create(OpCodes.Ldobj, variable.GetElementType())); - worker.Append(worker.Create(OpCodes.Call, elementWriteFunc)); - worker.Append(worker.Create(OpCodes.Ldloc_1)); - worker.Append(worker.Create(OpCodes.Ldc_I4_1)); - worker.Append(worker.Create(OpCodes.Add)); - worker.Append(worker.Create(OpCodes.Conv_U2)); - worker.Append(worker.Create(OpCodes.Stloc_1)); - - // loop while check - worker.Append(labelHead); - worker.Append(worker.Create(OpCodes.Ldloc_1)); - worker.Append(worker.Create(OpCodes.Ldarg_1)); - worker.Append(worker.Create(OpCodes.Ldlen)); - worker.Append(worker.Create(OpCodes.Conv_I4)); - worker.Append(worker.Create(OpCodes.Blt, labelBody)); - - worker.Append(worker.Create(OpCodes.Ret)); - return writerFunc; - } - - static MethodDefinition GenerateWriterFunction(TypeReference variable) - { - if (!IsValidTypeToGenerate(variable.Resolve())) - { - return null; - } - - var functionName = "_Write" + variable.Name + "_"; - if (variable.DeclaringType != null) - { - functionName += variable.DeclaringType.Name; - } - else - { - functionName += "None"; - } - // create new writer for this type - MethodDefinition writerFunc = new MethodDefinition(functionName, - MethodAttributes.Public | - MethodAttributes.Static | - MethodAttributes.HideBySig, - voidType); - - writerFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, scriptDef.MainModule.ImportReference(NetworkWriterType))); - writerFunc.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, scriptDef.MainModule.ImportReference(variable))); - - ILProcessor worker = writerFunc.Body.GetILProcessor(); - - uint fields = 0; - foreach (var field in variable.Resolve().Fields) - { - if (field.IsStatic || field.IsPrivate) - continue; - - if (field.FieldType.Resolve().HasGenericParameters) - { - Weaver.fail = true; - Log.Error("WriteReadFunc for " + field.Name + " [" + field.FieldType + "/" + field.FieldType.FullName + "]. Cannot have generic parameters."); - return null; - } - - if (field.FieldType.Resolve().IsInterface) - { - Weaver.fail = true; - Log.Error("WriteReadFunc for " + field.Name + " [" + field.FieldType + "/" + field.FieldType.FullName + "]. Cannot be an interface."); - return null; - } - - var writeFunc = GetWriteFunc(field.FieldType); - if (writeFunc != null) - { - fields++; - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Ldarg_1)); - worker.Append(worker.Create(OpCodes.Ldfld, field)); - worker.Append(worker.Create(OpCodes.Call, writeFunc)); - } - else - { - Log.Error("WriteReadFunc for " + field.Name + " type " + field.FieldType + " no supported"); - fail = true; - return null; - } - } - if (fields == 0) - { - Log.Warning("The class / struct " + variable.Name + " has no public or non-static fields to serialize"); - } - worker.Append(worker.Create(OpCodes.Ret)); - return writerFunc; - } - - static MethodDefinition GenerateReadFunction(TypeReference variable) - { - if (!IsValidTypeToGenerate(variable.Resolve())) - { - return null; - } - - var functionName = "_Read" + variable.Name + "_"; - if (variable.DeclaringType != null) - { - functionName += variable.DeclaringType.Name; - } - else - { - functionName += "None"; - } - - // create new reader for this type - MethodDefinition readerFunc = new MethodDefinition(functionName, - MethodAttributes.Public | - MethodAttributes.Static | - MethodAttributes.HideBySig, - variable); - - // create local for return value - readerFunc.Body.Variables.Add(new VariableDefinition(variable)); - readerFunc.Body.InitLocals = true; - - readerFunc.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, scriptDef.MainModule.ImportReference(NetworkReaderType))); - - ILProcessor worker = readerFunc.Body.GetILProcessor(); - - if (variable.IsValueType) - { - // structs are created with Initobj - worker.Append(worker.Create(OpCodes.Ldloca, 0)); - worker.Append(worker.Create(OpCodes.Initobj, variable)); - } - else - { - // classes are created with their constructor - - var ctor = ResolveDefaultPublicCtor(variable); - if (ctor == null) - { - Log.Error("The class " + variable.Name + " has no default constructor or it's private, aborting."); - return null; - } - - worker.Append(worker.Create(OpCodes.Newobj, ctor)); - worker.Append(worker.Create(OpCodes.Stloc_0)); - } - - uint fields = 0; - foreach (var field in variable.Resolve().Fields) - { - if (field.IsStatic || field.IsPrivate) - continue; - - // mismatched ldloca/ldloc for struct/class combinations is invalid IL, which causes crash at runtime - if (variable.IsValueType) - { - worker.Append(worker.Create(OpCodes.Ldloca, 0)); - } - else - { - worker.Append(worker.Create(OpCodes.Ldloc, 0)); - } - - var readFunc = GetReadFunc(field.FieldType); - if (readFunc != null) - { - worker.Append(worker.Create(OpCodes.Ldarg_0)); - worker.Append(worker.Create(OpCodes.Call, readFunc)); - } - else - { - Log.Error("GetReadFunc for " + field.Name + " type " + field.FieldType + " no supported"); - fail = true; - return null; - } - - worker.Append(worker.Create(OpCodes.Stfld, field)); - fields++; - } - if (fields == 0) - { - Log.Warning("The class / struct " + variable.Name + " has no public or non-static fields to serialize"); - } - - worker.Append(worker.Create(OpCodes.Ldloc_0)); - worker.Append(worker.Create(OpCodes.Ret)); - return readerFunc; - } - - static Instruction GetEventLoadInstruction(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, int iCount, FieldReference foundEventField) - { - // go backwards until find a ldfld instruction for this event field - while (iCount > 0) - { - iCount -= 1; - Instruction inst = md.Body.Instructions[iCount]; - if (inst.OpCode == OpCodes.Ldfld) - { - if (inst.Operand == foundEventField) - { - DLog(td, " " + inst.Operand); - return inst; - } - } - } - return null; - } - - static void ProcessInstructionMethod(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, Instruction instr, MethodReference opMethodRef, int iCount) - { - //DLog(td, "ProcessInstructionMethod " + opMethod.Name); - if (opMethodRef.Name == "Invoke") - { - // Events use an "Invoke" method to call the delegate. - // this code replaces the "Invoke" instruction with the generated "Call***" instruction which send the event to the server. - // but the "Invoke" instruction is called on the event field - where the "call" instruction is not. - // so the earlier instruction that loads the event field is replaced with a Noop. - - // go backwards until find a ldfld instruction that matches ANY event - bool found = false; - while (iCount > 0 && !found) - { - iCount -= 1; - Instruction inst = md.Body.Instructions[iCount]; - if (inst.OpCode == OpCodes.Ldfld) - { - var opField = inst.Operand as FieldReference; - - // find replaceEvent with matching name - for (int n = 0; n < lists.replacedEvents.Count; n++) - { - EventDefinition foundEvent = lists.replacedEvents[n]; - if (foundEvent.Name == opField.Name) - { - instr.Operand = lists.replacementEvents[n]; - inst.OpCode = OpCodes.Nop; - found = true; - break; - } - } - } - } - } - else - { - if (lists.replacementMethodNames.Contains(opMethodRef.FullName)) - { - for (int n = 0; n < lists.replacedMethods.Count; n++) - { - MethodDefinition foundMethod = lists.replacedMethods[n]; - if (opMethodRef.FullName == foundMethod.FullName) - { - //DLog(td, " replacing " + md.Name + ":" + i); - instr.Operand = lists.replacementMethods[n]; - //DLog(td, " replaced " + md.Name + ":" + i); - break; - } - } - } - } - } - - static void ConfirmGeneratedCodeClass(ModuleDefinition moduleDef) - { - if (lists.generateContainerClass == null) - { - lists.generateContainerClass = new TypeDefinition("Unity", "GeneratedNetworkCode", - TypeAttributes.BeforeFieldInit | TypeAttributes.Class | TypeAttributes.AnsiClass | TypeAttributes.Public | TypeAttributes.AutoClass, - objectType); - - const MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; - var method = new MethodDefinition(".ctor", methodAttributes, voidType); - method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); - method.Body.Instructions.Add(Instruction.Create(OpCodes.Call, ResolveMethod(objectType, ".ctor"))); - method.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); - - lists.generateContainerClass.Methods.Add(method); - } - } - - static void ProcessInstructionField(TypeDefinition td, MethodDefinition md, Instruction i, FieldDefinition opField) - { - // dont replace property call sites in constructors or deserialize - if (md.Name == ".ctor" || md.Name == "OnDeserialize") - return; - - // does it set a field that we replaced? - for (int n = 0; n < lists.replacedFields.Count; n++) - { - FieldDefinition fd = lists.replacedFields[n]; - if (opField == fd) - { - //replace with property - //DLog(td, " replacing " + md.Name + ":" + i); - i.OpCode = OpCodes.Call; - i.Operand = lists.replacementProperties[n]; - //DLog(td, " replaced " + md.Name + ":" + i); - break; - } - } - } - - static void ProcessInstruction(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, Instruction i, int iCount) - { - if (i.OpCode == OpCodes.Call || i.OpCode == OpCodes.Callvirt) - { - MethodReference opMethod = i.Operand as MethodReference; - if (opMethod != null) - { - ProcessInstructionMethod(moduleDef, td, md, i, opMethod, iCount); - } - } - - if (i.OpCode == OpCodes.Stfld) - { - // this instruction sets the value of a field. cache the field reference. - FieldDefinition opField = i.Operand as FieldDefinition; - if (opField != null) - { - ProcessInstructionField(td, md, i, opField); - } - } - } - - // this is required to early-out from a function with "ref" or "out" parameters - static void InjectGuardParameters(MethodDefinition md, ILProcessor worker, Instruction top) - { - int offset = md.Resolve().IsStatic ? 0 : 1; - for (int index = 0; index < md.Parameters.Count; index++) - { - var param = md.Parameters[index]; - if (param.IsOut) - { - var elementType = param.ParameterType.GetElementType(); - if (elementType.IsPrimitive) - { - worker.InsertBefore(top, worker.Create(OpCodes.Ldarg, index + offset)); - worker.InsertBefore(top, worker.Create(OpCodes.Ldc_I4_0)); - worker.InsertBefore(top, worker.Create(OpCodes.Stind_I4)); - } - else - { - md.Body.Variables.Add(new VariableDefinition(elementType)); - md.Body.InitLocals = true; - - worker.InsertBefore(top, worker.Create(OpCodes.Ldarg, index + offset)); - worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, (byte)(md.Body.Variables.Count - 1))); - worker.InsertBefore(top, worker.Create(OpCodes.Initobj, elementType)); - worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, md.Body.Variables.Count - 1)); - worker.InsertBefore(top, worker.Create(OpCodes.Stobj, elementType)); - } - } - } - } - - // this is required to early-out from a function with a return value. - static void InjectGuardReturnValue(MethodDefinition md, ILProcessor worker, Instruction top) - { - if (md.ReturnType.FullName != voidType.FullName) - { - if (md.ReturnType.IsPrimitive) - { - worker.InsertBefore(top, worker.Create(OpCodes.Ldc_I4_0)); - } - else - { - md.Body.Variables.Add(new VariableDefinition(md.ReturnType)); - md.Body.InitLocals = true; - - worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, (byte)(md.Body.Variables.Count - 1))); - worker.InsertBefore(top, worker.Create(OpCodes.Initobj, md.ReturnType)); - worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, md.Body.Variables.Count - 1)); - } - } - } - - static void InjectServerGuard(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, bool logWarning) - { - if (!IsNetworkBehaviour(td)) - { - Log.Error("[Server] guard on non-NetworkBehaviour script at [" + md.FullName + "]"); - return; - } - ILProcessor worker = md.Body.GetILProcessor(); - Instruction top = md.Body.Instructions[0]; - - worker.InsertBefore(top, worker.Create(OpCodes.Call, NetworkServerGetActive)); - worker.InsertBefore(top, worker.Create(OpCodes.Brtrue, top)); - if (logWarning) - { - worker.InsertBefore(top, worker.Create(OpCodes.Ldstr, "[Server] function '" + md.FullName + "' called on client")); - worker.InsertBefore(top, worker.Create(OpCodes.Call, logWarningReference)); - } - InjectGuardParameters(md, worker, top); - InjectGuardReturnValue(md, worker, top); - worker.InsertBefore(top, worker.Create(OpCodes.Ret)); - } - - static void InjectClientGuard(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, bool logWarning) - { - if (!IsNetworkBehaviour(td)) - { - Log.Error("[Client] guard on non-NetworkBehaviour script at [" + md.FullName + "]"); - return; - } - ILProcessor worker = md.Body.GetILProcessor(); - Instruction top = md.Body.Instructions[0]; - - worker.InsertBefore(top, worker.Create(OpCodes.Call, NetworkClientGetActive)); - worker.InsertBefore(top, worker.Create(OpCodes.Brtrue, top)); - if (logWarning) - { - worker.InsertBefore(top, worker.Create(OpCodes.Ldstr, "[Client] function '" + md.FullName + "' called on server")); - worker.InsertBefore(top, worker.Create(OpCodes.Call, logWarningReference)); - } - - InjectGuardParameters(md, worker, top); - InjectGuardReturnValue(md, worker, top); - worker.InsertBefore(top, worker.Create(OpCodes.Ret)); - } - - static void ProcessSiteMethod(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md) - { - // process all references to replaced members with properties - //Weaver.DLog(td, " ProcessSiteMethod " + md); - - if (md.Name == ".cctor" || md.Name == "OnUnserializeVars") - return; - - string prefix = md.Name.Substring(0, Math.Min(md.Name.Length, 4)); - - if (prefix == "UNet") - return; - - prefix = md.Name.Substring(0, Math.Min(md.Name.Length, 7)); - if (prefix == "CallCmd") - return; - - prefix = md.Name.Substring(0, Math.Min(md.Name.Length, 9)); - if (prefix == "InvokeCmd" || prefix == "InvokeRpc" || prefix == "InvokeSyn") - return; - - if (md.Body != null && md.Body.Instructions != null) - { - foreach (CustomAttribute attr in md.CustomAttributes) - { - if (attr.Constructor.DeclaringType.ToString() == "UnityEngine.Networking.ServerAttribute") - { - InjectServerGuard(moduleDef, td, md, true); - } - else if (attr.Constructor.DeclaringType.ToString() == "UnityEngine.Networking.ServerCallbackAttribute") - { - InjectServerGuard(moduleDef, td, md, false); - } - else if (attr.Constructor.DeclaringType.ToString() == "UnityEngine.Networking.ClientAttribute") - { - InjectClientGuard(moduleDef, td, md, true); - } - else if (attr.Constructor.DeclaringType.ToString() == "UnityEngine.Networking.ClientCallbackAttribute") - { - InjectClientGuard(moduleDef, td, md, false); - } - } - - int iCount = 0; - foreach (Instruction i in md.Body.Instructions) - { - ProcessInstruction(moduleDef, td, md, i, iCount); - iCount += 1; - } - } - } - - static void ProcessSiteClass(ModuleDefinition moduleDef, TypeDefinition td) - { - //Console.WriteLine(" ProcessSiteClass " + td); - foreach (MethodDefinition md in td.Methods) - { - ProcessSiteMethod(moduleDef, td, md); - } - - foreach (var nested in td.NestedTypes) - { - ProcessSiteClass(moduleDef, nested); - } - } - - static void ProcessSitesModule(ModuleDefinition moduleDef) - { - var startTime = System.DateTime.Now; - - //Search through the types - foreach (TypeDefinition td in moduleDef.Types) - { - if (td.IsClass) - { - ProcessSiteClass(moduleDef, td); - } - } - if (lists.generateContainerClass != null) - { - moduleDef.Types.Add(lists.generateContainerClass); - scriptDef.MainModule.ImportReference(lists.generateContainerClass); - - foreach (var f in lists.generatedReadFunctions) - { - scriptDef.MainModule.ImportReference(f); - } - - foreach (var f in lists.generatedWriteFunctions) - { - scriptDef.MainModule.ImportReference(f); - } - } - Console.WriteLine(" ProcessSitesModule " + moduleDef.Name + " elapsed time:" + (System.DateTime.Now - startTime)); - } - - static void ProcessPropertySites() - { - ProcessSitesModule(scriptDef.MainModule); - } - - static bool ProcessMessageType(TypeDefinition td) - { - var proc = new MessageClassProcessor(td); - proc.Process(); - return true; - } - - static bool ProcessSyncListStructType(TypeDefinition td) - { - var proc = new SyncListStructProcessor(td); - proc.Process(); - return true; - } - - static void ProcessMonoBehaviourType(TypeDefinition td) - { - var proc = new MonoBehaviourProcessor(td); - proc.Process(); - } - - static bool ProcessNetworkBehaviourType(TypeDefinition td) - { - foreach (var md in td.Resolve().Methods) - { - if (md.Name == "UNetVersion") - { - DLog(td, " Already processed"); - return false; // did no work - } - } - DLog(td, "Found NetworkBehaviour " + td.FullName); - - NetworkBehaviourProcessor proc = new NetworkBehaviourProcessor(td); - proc.Process(); - return true; - } - - public static MethodReference ResolveMethod(TypeReference t, string name) - { - //Console.WriteLine("ResolveMethod " + t.ToString () + " " + name); - if (t == null) - { - Log.Error("Type missing for " + name); - fail = true; - return null; - } - foreach (var methodRef in t.Resolve().Methods) - { - if (methodRef.Name == name) - { - return scriptDef.MainModule.ImportReference(methodRef); - } - } - Log.Error("ResolveMethod failed " + t.Name + "::" + name + " " + t.Resolve()); - - // why did it fail!? - foreach (var methodRef in t.Resolve().Methods) - { - Log.Error("Method " + methodRef.Name); - } - - fail = true; - return null; - } - - static MethodReference ResolveMethodWithArg(TypeReference t, string name, TypeReference argType) - { - foreach (var methodRef in t.Resolve().Methods) - { - if (methodRef.Name == name) - { - if (methodRef.Parameters.Count == 1) - { - if (methodRef.Parameters[0].ParameterType.FullName == argType.FullName) - { - return scriptDef.MainModule.ImportReference(methodRef); - } - } - } - } - Log.Error("ResolveMethodWithArg failed " + t.Name + "::" + name + " " + argType); - fail = true; - return null; - } - - static MethodDefinition ResolveDefaultPublicCtor(TypeReference variable) - { - foreach (MethodDefinition methodRef in variable.Resolve().Methods) - { - if (methodRef.Name == ".ctor" && - methodRef.Resolve().IsPublic && - methodRef.Parameters.Count == 0) - { - return methodRef; - } - } - return null; - } - - static GenericInstanceMethod ResolveMethodGeneric(TypeReference t, string name, TypeReference genericType) - { - foreach (var methodRef in t.Resolve().Methods) - { - if (methodRef.Name == name) - { - if (methodRef.Parameters.Count == 0) - { - if (methodRef.GenericParameters.Count == 1) - { - MethodReference tmp = scriptDef.MainModule.ImportReference(methodRef); - GenericInstanceMethod gm = new GenericInstanceMethod(tmp); - gm.GenericArguments.Add(genericType); - if (gm.GenericArguments[0].FullName == genericType.FullName) - { - return gm; - } - } - } - } - } - - Log.Error("ResolveMethodGeneric failed " + t.Name + "::" + name + " " + genericType); - fail = true; - return null; - } - - public static FieldReference ResolveField(TypeReference t, string name) - { - foreach (FieldDefinition fd in t.Resolve().Fields) - { - if (fd.Name == name) - { - return scriptDef.MainModule.ImportReference(fd); - } - } - return null; - } - - public static MethodReference ResolveProperty(TypeReference t, string name) - { - foreach (var fd in t.Resolve().Properties) - { - if (fd.Name == name) - { - return scriptDef.MainModule.ImportReference(fd.GetMethod); - } - } - return null; - } - - static void SetupUnityTypes() - { - vector2Type = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Vector2"); - vector3Type = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Vector3"); - vector4Type = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Vector4"); - colorType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Color"); - color32Type = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Color32"); - quaternionType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Quaternion"); - rectType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Rect"); - planeType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Plane"); - rayType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Ray"); - matrixType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Matrix4x4"); - gameObjectType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.GameObject"); - transformType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Transform"); - unityObjectType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Object"); - - hashType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkHash128"); - NetworkClientType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkClient"); - NetworkServerType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkServer"); - NetworkCRCType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkCRC"); - - SyncVarType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncVarAttribute"); - CommandType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.CommandAttribute"); - ClientRpcType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.ClientRpcAttribute"); - TargetRpcType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.TargetRpcAttribute"); - SyncEventType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncEventAttribute"); - SyncListType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncList`1"); - NetworkSettingsType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkSettingsAttribute"); - - SyncListFloatType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListFloat"); - SyncListIntType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListInt"); - SyncListUIntType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListUInt"); - SyncListBoolType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListBool"); - SyncListStringType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListString"); - } - - static void SetupCorLib() - { - var name = AssemblyNameReference.Parse("mscorlib"); - var parameters = new ReaderParameters - { - AssemblyResolver = scriptDef.MainModule.AssemblyResolver, - }; - corLib = scriptDef.MainModule.AssemblyResolver.Resolve(name, parameters).MainModule; - } - - static TypeReference ImportCorLibType(string fullName) - { - var type = corLib.GetType(fullName) ?? corLib.ExportedTypes.First(t => t.FullName == fullName).Resolve(); - return scriptDef.MainModule.ImportReference(type); - } - - static void SetupTargetTypes() - { - // system types - SetupCorLib(); - voidType = ImportCorLibType("System.Void"); - singleType = ImportCorLibType("System.Single"); - doubleType = ImportCorLibType("System.Double"); - decimalType = ImportCorLibType("System.Decimal"); - boolType = ImportCorLibType("System.Boolean"); - stringType = ImportCorLibType("System.String"); - int64Type = ImportCorLibType("System.Int64"); - uint64Type = ImportCorLibType("System.UInt64"); - int32Type = ImportCorLibType("System.Int32"); - uint32Type = ImportCorLibType("System.UInt32"); - int16Type = ImportCorLibType("System.Int16"); - uint16Type = ImportCorLibType("System.UInt16"); - byteType = ImportCorLibType("System.Byte"); - sbyteType = ImportCorLibType("System.SByte"); - charType = ImportCorLibType("System.Char"); - objectType = ImportCorLibType("System.Object"); - valueTypeType = ImportCorLibType("System.ValueType"); - typeType = ImportCorLibType("System.Type"); - IEnumeratorType = ImportCorLibType("System.Collections.IEnumerator"); - MemoryStreamType = ImportCorLibType("System.IO.MemoryStream"); - - NetworkReaderType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkReader"); - NetworkReaderDef = NetworkReaderType.Resolve(); - - NetworkReaderCtor = ResolveMethod(NetworkReaderDef, ".ctor"); - - NetworkWriterType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkWriter"); - NetworkWriterDef = NetworkWriterType.Resolve(); - - NetworkWriterCtor = ResolveMethod(NetworkWriterDef, ".ctor"); - - MemoryStreamCtor = ResolveMethod(MemoryStreamType, ".ctor"); - - NetworkInstanceIdType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkInstanceId"); - NetworkSceneIdType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkSceneId"); - - NetworkInstanceIdType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkInstanceId"); - NetworkSceneIdType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkSceneId"); - - NetworkServerGetActive = ResolveMethod(NetworkServerType, "get_active"); - NetworkServerGetLocalClientActive = ResolveMethod(NetworkServerType, "get_localClientActive"); - NetworkClientGetActive = ResolveMethod(NetworkClientType, "get_active"); - - NetworkReaderReadInt32 = ResolveMethod(NetworkReaderType, "ReadInt32"); - - NetworkWriterWriteInt32 = ResolveMethodWithArg(NetworkWriterType, "Write", int32Type); - NetworkWriterWriteInt16 = ResolveMethodWithArg(NetworkWriterType, "Write", int16Type); - - NetworkReaderReadPacked32 = ResolveMethod(NetworkReaderType, "ReadPackedUInt32"); - NetworkReaderReadPacked64 = ResolveMethod(NetworkReaderType, "ReadPackedUInt64"); - NetworkReaderReadByte = ResolveMethod(NetworkReaderType, "ReadByte"); - - NetworkWriterWritePacked32 = ResolveMethod(NetworkWriterType, "WritePackedUInt32"); - NetworkWriterWritePacked64 = ResolveMethod(NetworkWriterType, "WritePackedUInt64"); - - NetworkWriterWriteNetworkInstanceId = ResolveMethodWithArg(NetworkWriterType, "Write", NetworkInstanceIdType); - NetworkWriterWriteNetworkSceneId = ResolveMethodWithArg(NetworkWriterType, "Write", NetworkSceneIdType); - - NetworkReaderReadNetworkInstanceId = ResolveMethod(NetworkReaderType, "ReadNetworkId"); - NetworkReaderReadNetworkSceneId = ResolveMethod(NetworkReaderType, "ReadSceneId"); - NetworkInstanceIsEmpty = ResolveMethod(NetworkInstanceIdType, "IsEmpty"); - - NetworkReadUInt16 = ResolveMethod(NetworkReaderType, "ReadUInt16"); - NetworkWriteUInt16 = ResolveMethodWithArg(NetworkWriterType, "Write", uint16Type); - - CmdDelegateReference = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkBehaviour/CmdDelegate"); - CmdDelegateConstructor = ResolveMethod(CmdDelegateReference, ".ctor"); - scriptDef.MainModule.ImportReference(gameObjectType); - scriptDef.MainModule.ImportReference(transformType); - - TypeReference unetViewTmp = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkIdentity"); - NetworkIdentityType = scriptDef.MainModule.ImportReference(unetViewTmp); - - NetworkInstanceIdType = scriptDef.MainModule.ImportReference(NetworkInstanceIdType); - - SyncListFloatReadType = ResolveMethod(SyncListFloatType, "ReadReference"); - SyncListIntReadType = ResolveMethod(SyncListIntType, "ReadReference"); - SyncListUIntReadType = ResolveMethod(SyncListUIntType, "ReadReference"); - SyncListBoolReadType = ResolveMethod(SyncListBoolType, "ReadReference"); - SyncListStringReadType = ResolveMethod(SyncListStringType, "ReadReference"); - - SyncListFloatWriteType = ResolveMethod(SyncListFloatType, "WriteInstance"); - SyncListIntWriteType = ResolveMethod(SyncListIntType, "WriteInstance"); - SyncListUIntWriteType = ResolveMethod(SyncListUIntType, "WriteInstance"); - SyncListBoolWriteType = ResolveMethod(SyncListBoolType, "WriteInstance"); - SyncListStringWriteType = ResolveMethod(SyncListStringType, "WriteInstance"); - - - NetworkBehaviourType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkBehaviour"); - NetworkBehaviourType2 = scriptDef.MainModule.ImportReference(NetworkBehaviourType); - NetworkConnectionType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkConnection"); - - MonoBehaviourType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.MonoBehaviour"); - ScriptableObjectType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.ScriptableObject"); - - NetworkConnectionType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkConnection"); - NetworkConnectionType = scriptDef.MainModule.ImportReference(NetworkConnectionType); - - ULocalConnectionToServerType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.ULocalConnectionToServer"); - ULocalConnectionToServerType = scriptDef.MainModule.ImportReference(ULocalConnectionToServerType); - - ULocalConnectionToClientType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.ULocalConnectionToClient"); - ULocalConnectionToClientType = scriptDef.MainModule.ImportReference(ULocalConnectionToClientType); - - MessageBaseType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.MessageBase"); - SyncListStructType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListStruct`1"); - - NetworkBehaviourDirtyBitsReference = ResolveProperty(NetworkBehaviourType, "syncVarDirtyBits"); - - ComponentType = m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Component"); - ClientSceneType = m_UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.ClientScene"); - FindLocalObjectReference = ResolveMethod(ClientSceneType, "FindLocalObject"); - RegisterBehaviourReference = ResolveMethod(NetworkCRCType, "RegisterBehaviour"); - ReadyConnectionReference = ResolveMethod(ClientSceneType, "get_readyConnection"); - - // get specialized GetComponent() - getComponentReference = ResolveMethodGeneric(ComponentType, "GetComponent", NetworkIdentityType); - - getUNetIdReference = ResolveMethod(unetViewTmp, "get_netId"); - - gameObjectInequality = ResolveMethod(unityObjectType, "op_Inequality"); - - UBehaviourIsServer = ResolveMethod(NetworkBehaviourType, "get_isServer"); - getPlayerIdReference = ResolveMethod(NetworkBehaviourType, "get_playerControllerId"); - setSyncVarReference = ResolveMethod(NetworkBehaviourType, "SetSyncVar"); - setSyncVarHookGuard = ResolveMethod(NetworkBehaviourType, "set_syncVarHookGuard"); - getSyncVarHookGuard = ResolveMethod(NetworkBehaviourType, "get_syncVarHookGuard"); - - setSyncVarGameObjectReference = ResolveMethod(NetworkBehaviourType, "SetSyncVarGameObject"); - registerCommandDelegateReference = ResolveMethod(NetworkBehaviourType, "RegisterCommandDelegate"); - registerRpcDelegateReference = ResolveMethod(NetworkBehaviourType, "RegisterRpcDelegate"); - registerEventDelegateReference = ResolveMethod(NetworkBehaviourType, "RegisterEventDelegate"); - registerSyncListDelegateReference = ResolveMethod(NetworkBehaviourType, "RegisterSyncListDelegate"); - getTypeReference = ResolveMethod(objectType, "GetType"); - getTypeFromHandleReference = ResolveMethod(typeType, "GetTypeFromHandle"); - logErrorReference = ResolveMethod(m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Debug"), "LogError"); - logWarningReference = ResolveMethod(m_UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Debug"), "LogWarning"); - sendCommandInternal = ResolveMethod(NetworkBehaviourType, "SendCommandInternal"); - sendRpcInternal = ResolveMethod(NetworkBehaviourType, "SendRPCInternal"); - sendTargetRpcInternal = ResolveMethod(NetworkBehaviourType, "SendTargetRPCInternal"); - sendEventInternal = ResolveMethod(NetworkBehaviourType, "SendEventInternal"); - - SyncListType = scriptDef.MainModule.ImportReference(SyncListType); - SyncListInitBehaviourReference = ResolveMethod(SyncListType, "InitializeBehaviour"); - SyncListInitHandleMsg = ResolveMethod(SyncListType, "HandleMsg"); - SyncListClear = ResolveMethod(SyncListType, "Clear"); - } - - static void SetupReadFunctions() - { - lists.readFuncs = new Dictionary - { - { singleType.FullName, ResolveMethod(NetworkReaderType, "ReadSingle") }, - { doubleType.FullName, ResolveMethod(NetworkReaderType, "ReadDouble") }, - { boolType.FullName, ResolveMethod(NetworkReaderType, "ReadBoolean") }, - { stringType.FullName, ResolveMethod(NetworkReaderType, "ReadString") }, - { int64Type.FullName, NetworkReaderReadPacked64 }, - { uint64Type.FullName, NetworkReaderReadPacked64 }, - { int32Type.FullName, NetworkReaderReadPacked32 }, - { uint32Type.FullName, NetworkReaderReadPacked32 }, - { int16Type.FullName, NetworkReaderReadPacked32 }, - { uint16Type.FullName, NetworkReaderReadPacked32 }, - { byteType.FullName, NetworkReaderReadPacked32 }, - { sbyteType.FullName, NetworkReaderReadPacked32 }, - { charType.FullName, NetworkReaderReadPacked32 }, - { decimalType.FullName, ResolveMethod(NetworkReaderType, "ReadDecimal") }, - { vector2Type.FullName, ResolveMethod(NetworkReaderType, "ReadVector2") }, - { vector3Type.FullName, ResolveMethod(NetworkReaderType, "ReadVector3") }, - { vector4Type.FullName, ResolveMethod(NetworkReaderType, "ReadVector4") }, - { colorType.FullName, ResolveMethod(NetworkReaderType, "ReadColor") }, - { color32Type.FullName, ResolveMethod(NetworkReaderType, "ReadColor32") }, - { quaternionType.FullName, ResolveMethod(NetworkReaderType, "ReadQuaternion") }, - { rectType.FullName, ResolveMethod(NetworkReaderType, "ReadRect") }, - { planeType.FullName, ResolveMethod(NetworkReaderType, "ReadPlane") }, - { rayType.FullName, ResolveMethod(NetworkReaderType, "ReadRay") }, - { matrixType.FullName, ResolveMethod(NetworkReaderType, "ReadMatrix4x4") }, - { hashType.FullName, ResolveMethod(NetworkReaderType, "ReadNetworkHash128") }, - { gameObjectType.FullName, ResolveMethod(NetworkReaderType, "ReadGameObject") }, - { NetworkIdentityType.FullName, ResolveMethod(NetworkReaderType, "ReadNetworkIdentity") }, - { NetworkInstanceIdType.FullName, NetworkReaderReadNetworkInstanceId }, - { NetworkSceneIdType.FullName, NetworkReaderReadNetworkSceneId }, - { transformType.FullName, ResolveMethod(NetworkReaderType, "ReadTransform") }, - { "System.Byte[]", ResolveMethod(NetworkReaderType, "ReadBytesAndSize") }, - }; - - lists.readByReferenceFuncs = new Dictionary - { - {SyncListFloatType.FullName, SyncListFloatReadType}, - {SyncListIntType.FullName, SyncListIntReadType}, - {SyncListUIntType.FullName, SyncListUIntReadType}, - {SyncListBoolType.FullName, SyncListBoolReadType}, - {SyncListStringType.FullName, SyncListStringReadType} - }; - } - - static void SetupWriteFunctions() - { - lists.writeFuncs = new Dictionary - { - { singleType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", singleType) }, - { doubleType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", doubleType) }, - { boolType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", boolType) }, - { stringType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", stringType) }, - { int64Type.FullName, NetworkWriterWritePacked64 }, - { uint64Type.FullName, NetworkWriterWritePacked64 }, - { int32Type.FullName, NetworkWriterWritePacked32 }, - { uint32Type.FullName, NetworkWriterWritePacked32 }, - { int16Type.FullName, NetworkWriterWritePacked32 }, - { uint16Type.FullName, NetworkWriterWritePacked32 }, - { byteType.FullName, NetworkWriterWritePacked32 }, - { sbyteType.FullName, NetworkWriterWritePacked32 }, - { charType.FullName, NetworkWriterWritePacked32 }, - { decimalType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", decimalType) }, - { vector2Type.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", vector2Type) }, - { vector3Type.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", vector3Type) }, - { vector4Type.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", vector4Type) }, - { colorType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", colorType) }, - { color32Type.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", color32Type) }, - { quaternionType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", quaternionType) }, - { rectType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", rectType) }, - { planeType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", planeType) }, - { rayType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", rayType) }, - { matrixType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", matrixType) }, - { hashType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", hashType) }, - { gameObjectType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", gameObjectType) }, - { NetworkIdentityType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", NetworkIdentityType) }, - { NetworkInstanceIdType.FullName, NetworkWriterWriteNetworkInstanceId }, - { NetworkSceneIdType.FullName, NetworkWriterWriteNetworkSceneId }, - { transformType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", transformType) }, - { "System.Byte[]", ResolveMethod(NetworkWriterType, "WriteBytesFull") }, - { SyncListFloatType.FullName, SyncListFloatWriteType }, - { SyncListIntType.FullName, SyncListIntWriteType }, - { SyncListUIntType.FullName, SyncListUIntWriteType }, - { SyncListBoolType.FullName, SyncListBoolWriteType }, - { SyncListStringType.FullName, SyncListStringWriteType } - }; - } - - static bool IsNetworkBehaviour(TypeDefinition td) - { - if (!td.IsClass) - return false; - - // are ANY parent clasess unetbehaviours - TypeReference parent = td.BaseType; - while (parent != null) - { - if (parent.FullName == NetworkBehaviourType.FullName) - { - return true; - } - try - { - parent = parent.Resolve().BaseType; - } - catch (AssemblyResolutionException) - { - // this can happen for pluins. - //Console.WriteLine("AssemblyResolutionException: "+ ex.ToString()); - break; - } - } - return false; - } - - static public bool IsDerivedFrom(TypeDefinition td, TypeReference baseClass) - { - if (!td.IsClass) - return false; - - // are ANY parent clasess unetbehaviours - TypeReference parent = td.BaseType; - while (parent != null) - { - var parentName = parent.FullName; - - // strip generic parameters - int index = parentName.IndexOf('<'); - if (index != -1) - { - parentName = parentName.Substring(0, index); - } - - if (parentName == baseClass.FullName) - { - return true; - } - try - { - parent = parent.Resolve().BaseType; - } - catch (AssemblyResolutionException) - { - // this can happen for pluins. - //Console.WriteLine("AssemblyResolutionException: "+ ex.ToString()); - break; - } - } - return false; - } - - static public bool IsValidTypeToGenerate(TypeDefinition variable) - { - // a valid type is a simple class or struct. so we generate only code for types we dont know, and if they are not inside - // this assembly it must mean that we are trying to serialize a variable outside our scope. and this will fail. - - string assembly = Weaver.scriptDef.MainModule.Name; - if (variable.Module.Name != assembly) - { - Log.Error("parameter [" + variable.Name + - "] is of the type [" + - variable.FullName + - "] is not a valid type, please make sure to use a valid type."); - Weaver.fail = true; - fail = true; - return false; - } - return true; - } - - static void CheckMonoBehaviour(TypeDefinition td) - { - if (IsDerivedFrom(td, MonoBehaviourType)) - { - ProcessMonoBehaviourType(td); - } - } - - static bool CheckNetworkBehaviour(TypeDefinition td) - { - if (!td.IsClass) - return false; - - if (!IsNetworkBehaviour(td)) - { - CheckMonoBehaviour(td); - return false; - } - - // process this and base classes from parent to child order - - List behClasses = new List(); - - TypeDefinition parent = td; - while (parent != null) - { - if (parent.FullName == NetworkBehaviourType.FullName) - { - break; - } - try - { - behClasses.Insert(0, parent); - parent = parent.BaseType.Resolve(); - } - catch (AssemblyResolutionException) - { - // this can happen for pluins. - //Console.WriteLine("AssemblyResolutionException: "+ ex.ToString()); - break; - } - } - - bool didWork = false; - foreach (var beh in behClasses) - { - didWork |= ProcessNetworkBehaviourType(beh); - } - return didWork; - } - - static bool CheckMessageBase(TypeDefinition td) - { - if (!td.IsClass) - return false; - - bool didWork = false; - - // are ANY parent clasess MessageBase - TypeReference parent = td.BaseType; - while (parent != null) - { - if (parent.FullName == MessageBaseType.FullName) - { - didWork |= ProcessMessageType(td); - break; - } - try - { - parent = parent.Resolve().BaseType; - } - catch (AssemblyResolutionException) - { - // this can happen for pluins. - //Console.WriteLine("AssemblyResolutionException: "+ ex.ToString()); - break; - } - } - - // check for embedded types - foreach (var embedded in td.NestedTypes) - { - didWork |= CheckMessageBase(embedded); - } - - return didWork; - } - - static bool CheckSyncListStruct(TypeDefinition td) - { - if (!td.IsClass) - return false; - - bool didWork = false; - - // are ANY parent clasess SyncListStruct - TypeReference parent = td.BaseType; - while (parent != null) - { - if (parent.FullName.Contains("SyncListStruct")) - { - didWork |= ProcessSyncListStructType(td); - break; - } - try - { - parent = parent.Resolve().BaseType; - } - catch (AssemblyResolutionException) - { - // this can happen for pluins. - //Console.WriteLine("AssemblyResolutionException: "+ ex.ToString()); - break; - } - } - - // check for embedded types - foreach (var embedded in td.NestedTypes) - { - didWork |= CheckSyncListStruct(embedded); - } - - return didWork; - } - - static bool Weave(string assName, IEnumerable dependencies, IAssemblyResolver assemblyResolver, string unityEngineDLLPath, string unityUNetDLLPath, string outputDir) - { - var readParams = Helpers.ReaderParameters(assName, dependencies, assemblyResolver, unityEngineDLLPath, unityUNetDLLPath); - scriptDef = AssemblyDefinition.ReadAssembly(assName, readParams); - - SetupTargetTypes(); - SetupReadFunctions(); - SetupWriteFunctions(); - - ModuleDefinition moduleDefinition = scriptDef.MainModule; - Console.WriteLine("Script Module: {0}", moduleDefinition.Name); - - // Process each NetworkBehaviour - bool didWork = false; - - // We need to do 2 passes, because SyncListStructs might be referenced from other modules, so we must make sure we generate them first. - for (int pass = 0; pass < 2; pass++) - { - var watch = System.Diagnostics.Stopwatch.StartNew(); - foreach (TypeDefinition td in moduleDefinition.Types) - { - if (td.IsClass && CanBeResolved(td.BaseType)) - { - try - { - if (pass == 0) - { - didWork |= CheckSyncListStruct(td); - } - else - { - didWork |= CheckNetworkBehaviour(td); - didWork |= CheckMessageBase(td); - } - } - catch (Exception ex) - { - if (scriptDef.MainModule.SymbolReader != null) - scriptDef.MainModule.SymbolReader.Dispose(); - fail = true; - throw ex; - } - } - - if (fail) - { - if (scriptDef.MainModule.SymbolReader != null) - scriptDef.MainModule.SymbolReader.Dispose(); - return false; - } - } - watch.Stop(); - Console.WriteLine("Pass: " + pass + " took " + watch.ElapsedMilliseconds + " milliseconds"); - } - - if (didWork) - { - // build replacementMethods hash to speed up code site scan - foreach (var m in lists.replacedMethods) - { - lists.replacementMethodNames.Add(m.FullName); - } - - // this must be done for ALL code, not just NetworkBehaviours - try - { - ProcessPropertySites(); - } - catch (Exception e) - { - Log.Error("ProcessPropertySites exception: " + e); - if (scriptDef.MainModule.SymbolReader != null) - scriptDef.MainModule.SymbolReader.Dispose(); - return false; - } - - - if (fail) - { - //Log.Error("Failed phase II."); - if (scriptDef.MainModule.SymbolReader != null) - scriptDef.MainModule.SymbolReader.Dispose(); - return false; - } - - string dest = Helpers.DestinationFileFor(outputDir, assName); - //Console.WriteLine ("Output:" + dest); - //Console.WriteLine ("Output:" + options.OutSymbolsFormat); - - var writeParams = Helpers.GetWriterParameters(readParams); - - // PdbWriterProvider uses ISymUnmanagedWriter2 COM interface but Mono can't invoke a method on it and crashes (actually it first throws the following exception and then crashes). - // One solution would be to convert UNetWeaver to exe file and run it on .NET on Windows (I have tested that and it works). - // However it's much more simple to just write mdb file. - // System.NullReferenceException: Object reference not set to an instance of an object - // at(wrapper cominterop - invoke) Mono.Cecil.Pdb.ISymUnmanagedWriter2:DefineDocument(string, System.Guid &, System.Guid &, System.Guid &, Mono.Cecil.Pdb.ISymUnmanagedDocumentWriter &) - // at Mono.Cecil.Pdb.SymWriter.DefineDocument(System.String url, Guid language, Guid languageVendor, Guid documentType)[0x00000] in < filename unknown >:0 - if (writeParams.SymbolWriterProvider is PdbWriterProvider) - { - writeParams.SymbolWriterProvider = new MdbWriterProvider(); - // old pdb file is out of date so delete it. symbols will be stored in mdb - var pdb = Path.ChangeExtension(assName, ".pdb"); - File.Delete(pdb); - } - - scriptDef.Write(dest, writeParams); - } - - if (scriptDef.MainModule.SymbolReader != null) - scriptDef.MainModule.SymbolReader.Dispose(); - - return true; - } - - public static bool WeaveAssemblies(IEnumerable assemblies, IEnumerable dependencies, IAssemblyResolver assemblyResolver, string outputDir, string unityEngineDLLPath, string unityUNetDLLPath) - { - fail = false; - lists = new WeaverLists(); - - m_UnityAssemblyDefinition = AssemblyDefinition.ReadAssembly(unityEngineDLLPath); - m_UNetAssemblyDefinition = AssemblyDefinition.ReadAssembly(unityUNetDLLPath); - - SetupUnityTypes(); - - try - { - foreach (string ass in assemblies) - { - if (!Weave(ass, dependencies, assemblyResolver, unityEngineDLLPath, unityUNetDLLPath, outputDir)) - { - return false; - } - } - } - catch (Exception e) - { - Log.Error("Exception :" + e); - return false; - } - corLib = null; - return true; - } - } -} diff --git a/Extensions/Networking/Weaver/UNetWeaver.csproj b/Extensions/Networking/Weaver/UNetWeaver.csproj deleted file mode 100644 index c12be774bd..0000000000 --- a/Extensions/Networking/Weaver/UNetWeaver.csproj +++ /dev/null @@ -1,59 +0,0 @@ - - - - Debug - AnyCPU - {709222FD-15C2-497D-8B31-366ADCC074CD} - Library - Unity.UNetWeaver - Unity.UNetWeaver - v3.5 - 12.0.0 - 2.0 - - - True - full - False - bin\Debug - DEBUG; - prompt - 4 - true - true - - - none - True - bin\Release - prompt - 4 - true - - - - - - ..\..\..\External\Unity.Cecil\builds\lib\net35\Unity.Cecil.dll - - - ..\..\..\External\Unity.Cecil\builds\lib\net35\Unity.Cecil.Mdb.dll - - - ..\..\..\External\Unity.Cecil\builds\lib\net35\Unity.Cecil.Pdb.dll - - - - - - - - - - Code - - - - - - diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSAlign.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSAlign.cs deleted file mode 100644 index 56f891ab25..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSAlign.cs +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSAlign - { - Auto, - FlexStart, - Center, - FlexEnd, - Stretch, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSConstants.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSConstants.cs deleted file mode 100644 index b079de73e7..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSConstants.cs +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal static class CSSConstants - { - public const float Undefined = float.NaN; - - public static bool IsUndefined(float value) - { - return float.IsNaN(value); - } - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSDIrection.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSDIrection.cs deleted file mode 100644 index 0684608676..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSDIrection.cs +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSDirection - { - Inherit, - LTR, - RTL, - [System.Obsolete("Use LTR instead")] - LeftToRight = LTR, - [System.Obsolete("Use RTL instead")] - RightToLeft = RTL, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSDimension.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSDimension.cs deleted file mode 100644 index 6e6b9b24b7..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSDimension.cs +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSDimension - { - Width, - Height, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSEdge.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSEdge.cs deleted file mode 100644 index f7b6d3216b..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSEdge.cs +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSEdge - { - Left, - Top, - Right, - Bottom, - Start, - End, - Horizontal, - Vertical, - All, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSExperimentalFeature.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSExperimentalFeature.cs deleted file mode 100644 index ff195bbe03..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSExperimentalFeature.cs +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-21-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSExperimentalFeature - { - Rounding, - WebFlexBasis, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSFlexDirection.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSFlexDirection.cs deleted file mode 100644 index b6fa145ee9..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSFlexDirection.cs +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSFlexDirection - { - Column, - ColumnReverse, - Row, - RowReverse, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSJustify.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSJustify.cs deleted file mode 100644 index c51c8429dc..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSJustify.cs +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSJustify - { - FlexStart, - Center, - FlexEnd, - SpaceBetween, - SpaceAround, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSLogLevel.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSLogLevel.cs deleted file mode 100644 index 0daf89b584..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSLogLevel.cs +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSLogLevel - { - Error, - Warn, - Info, - Debug, - Verbose, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSLogger.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSLogger.cs deleted file mode 100644 index 6ebc0d96ce..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSLogger.cs +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -using System; -using System.Runtime.InteropServices; - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal static class CSSLogger - { -// TODO we don't support the logging feature yet - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void Func(CSSLogLevel level, string message); -// -// private static bool _initialized; -// private static Func _managedLogger = null; -// - public static Func Logger = null; - - public static void Initialize() - { -// if (!_initialized) -// { -// _managedLogger = (level, message) => { -// if (Logger != null) -// { -// Logger(level, message); -// } -// -// if (level == CSSLogLevel.Error) -// { -// throw new InvalidOperationException(message); -// } -// }; -// Native.CSSInteropSetLogger(_managedLogger); -// _initialized = true; -// } - } - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSMeasureFunc.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSMeasureFunc.cs deleted file mode 100644 index df67f629e0..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSMeasureFunc.cs +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -using System; -using System.Runtime.InteropServices; - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate CSSSize CSSMeasureFunc( - IntPtr node, - float width, - CSSMeasureMode widthMode, - float height, - CSSMeasureMode heightMode); -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSMeasureMode.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSMeasureMode.cs deleted file mode 100644 index f8305cea6f..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSMeasureMode.cs +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSMeasureMode - { - Undefined, - Exactly, - AtMost, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSNode.Create.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSNode.Create.cs deleted file mode 100644 index 632089a0de..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSNode.Create.cs +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -using System; - -// BEGIN_UNITY @joce 11-21-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ -// BEGIN_UNITY @joce 11-21-2016 CompileForC#Bindings - //public partial class CSSNode - internal partial class CSSNode -// END_UNITY - { - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSNode.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSNode.cs deleted file mode 100644 index 4671519a4b..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSNode.cs +++ /dev/null @@ -1,598 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ -// BEGIN_UNITY @joce 11-21-2016 CompileForC#Bindings - //public partial class CSSNode : IEnumerable - internal partial class CSSNode : IEnumerable -// END_UNITY - { - private IntPtr _cssNode; - private WeakReference _parent; - private List _children; - private MeasureFunction _measureFunction; - private CSSMeasureFunc _cssMeasureFunc; - private object _data; - - public CSSNode() - { - CSSLogger.Initialize(); - - _cssNode = Native.CSSNodeNew(); - if (_cssNode == IntPtr.Zero) - { - throw new InvalidOperationException("Failed to allocate native memory"); - } - } - - ~CSSNode() - { - Native.CSSNodeFree(_cssNode); - } - - public void Reset() - { - _measureFunction = null; - _data = null; - - Native.CSSNodeReset(_cssNode); - } - - public bool IsDirty - { - get - { - return Native.CSSNodeIsDirty(_cssNode); - } - } - - public virtual void MarkDirty() - { - Native.CSSNodeMarkDirty(_cssNode); - } - - public bool HasNewLayout - { - get - { - return Native.CSSNodeGetHasNewLayout(_cssNode); - } - } - - public void MarkHasNewLayout() - { - Native.CSSNodeSetHasNewLayout(_cssNode, true); - } - - public CSSNode Parent - { - get - { - return _parent != null ? _parent.Target as CSSNode : null; - } - } - - public bool IsMeasureDefined - { - get - { - return _measureFunction != null; - } - } - - public void CopyStyle(CSSNode srcNode) - { - Native.CSSNodeCopyStyle(_cssNode, srcNode._cssNode); - } - - public CSSDirection StyleDirection - { - get - { - return Native.CSSNodeStyleGetDirection(_cssNode); - } - - set - { - Native.CSSNodeStyleSetDirection(_cssNode, value); - } - } - - public CSSFlexDirection FlexDirection - { - get - { - return Native.CSSNodeStyleGetFlexDirection(_cssNode); - } - - set - { - Native.CSSNodeStyleSetFlexDirection(_cssNode, value); - } - } - - public CSSJustify JustifyContent - { - get - { - return Native.CSSNodeStyleGetJustifyContent(_cssNode); - } - - set - { - Native.CSSNodeStyleSetJustifyContent(_cssNode, value); - } - } - - public CSSAlign AlignItems - { - get - { - return Native.CSSNodeStyleGetAlignItems(_cssNode); - } - - set - { - Native.CSSNodeStyleSetAlignItems(_cssNode, value); - } - } - - public CSSAlign AlignSelf - { - get - { - return Native.CSSNodeStyleGetAlignSelf(_cssNode); - } - - set - { - Native.CSSNodeStyleSetAlignSelf(_cssNode, value); - } - } - - public CSSAlign AlignContent - { - get - { - return Native.CSSNodeStyleGetAlignContent(_cssNode); - } - - set - { - Native.CSSNodeStyleSetAlignContent(_cssNode, value); - } - } - - public CSSPositionType PositionType - { - get - { - return Native.CSSNodeStyleGetPositionType(_cssNode); - } - - set - { - Native.CSSNodeStyleSetPositionType(_cssNode, value); - } - } - - public CSSWrap Wrap - { - get - { - return Native.CSSNodeStyleGetFlexWrap(_cssNode); - } - - set - { - Native.CSSNodeStyleSetFlexWrap(_cssNode, value); - } - } - - public float Flex - { - set - { - Native.CSSNodeStyleSetFlex(_cssNode, value); - } - } - - public float FlexGrow - { - get - { - return Native.CSSNodeStyleGetFlexGrow(_cssNode); - } - - set - { - Native.CSSNodeStyleSetFlexGrow(_cssNode, value); - } - } - - public float FlexShrink - { - get - { - return Native.CSSNodeStyleGetFlexShrink(_cssNode); - } - - set - { - Native.CSSNodeStyleSetFlexShrink(_cssNode, value); - } - } - - public float FlexBasis - { - get - { - return Native.CSSNodeStyleGetFlexBasis(_cssNode); - } - - set - { - Native.CSSNodeStyleSetFlexBasis(_cssNode, value); - } - } - - public float GetMargin(CSSEdge edge) - { - return Native.CSSNodeStyleGetMargin(_cssNode, edge); - } - - public void SetMargin(CSSEdge edge, float value) - { - Native.CSSNodeStyleSetMargin(_cssNode, edge, value); - } - - public float GetPadding(CSSEdge edge) - { - return Native.CSSNodeStyleGetPadding(_cssNode, edge); - } - - public void SetPadding(CSSEdge edge, float padding) - { - Native.CSSNodeStyleSetPadding(_cssNode, edge, padding); - } - - public float GetBorder(CSSEdge edge) - { - return Native.CSSNodeStyleGetBorder(_cssNode, edge); - } - - public void SetBorder(CSSEdge edge, float border) - { - Native.CSSNodeStyleSetBorder(_cssNode, edge, border); - } - - public float GetPosition(CSSEdge edge) - { - return Native.CSSNodeStyleGetPosition(_cssNode, edge); - } - - public void SetPosition(CSSEdge edge, float position) - { - Native.CSSNodeStyleSetPosition(_cssNode, edge, position); - } - - public float Width - { - get - { - return Native.CSSNodeStyleGetWidth(_cssNode); - } - - set - { - Native.CSSNodeStyleSetWidth(_cssNode, value); - } - } - - public float Height - { - get - { - return Native.CSSNodeStyleGetHeight(_cssNode); - } - - set - { - Native.CSSNodeStyleSetHeight(_cssNode, value); - } - } - - public float MaxWidth - { - get - { - return Native.CSSNodeStyleGetMaxWidth(_cssNode); - } - - set - { - Native.CSSNodeStyleSetMaxWidth(_cssNode, value); - } - } - - public float MaxHeight - { - get - { - return Native.CSSNodeStyleGetMaxHeight(_cssNode); - } - - set - { - Native.CSSNodeStyleSetMaxHeight(_cssNode, value); - } - } - - public float MinWidth - { - get - { - return Native.CSSNodeStyleGetMinWidth(_cssNode); - } - - set - { - Native.CSSNodeStyleSetMinWidth(_cssNode, value); - } - } - - public float MinHeight - { - get - { - return Native.CSSNodeStyleGetMinHeight(_cssNode); - } - - set - { - Native.CSSNodeStyleSetMinHeight(_cssNode, value); - } - } - - public float AspectRatio - { - get - { - return Native.CSSNodeStyleGetAspectRatio(_cssNode); - } - - set - { - Native.CSSNodeStyleSetAspectRatio(_cssNode, value); - } - } - - public float LayoutX - { - get - { - return Native.CSSNodeLayoutGetLeft(_cssNode); - } - } - - public float LayoutY - { - get - { - return Native.CSSNodeLayoutGetTop(_cssNode); - } - } - - public float LayoutWidth - { - get - { - return Native.CSSNodeLayoutGetWidth(_cssNode); - } - } - - public float LayoutHeight - { - get - { - return Native.CSSNodeLayoutGetHeight(_cssNode); - } - } - - public CSSDirection LayoutDirection - { - get - { - return Native.CSSNodeLayoutGetDirection(_cssNode); - } - } - - public CSSOverflow Overflow - { - get - { - return Native.CSSNodeStyleGetOverflow(_cssNode); - } - - set - { - Native.CSSNodeStyleSetOverflow(_cssNode, value); - } - } - - public object Data - { - get - { - return _data; - } - - set - { - _data = value; - } - } - - public CSSNode this[int index] - { - get - { - return _children[index]; - } - } - - public int Count - { - get - { - return _children != null ? _children.Count : 0; - } - } - - public void MarkLayoutSeen() - { - Native.CSSNodeSetHasNewLayout(_cssNode, false); - } - - public bool ValuesEqual(float f1, float f2) - { - if (float.IsNaN(f1) || float.IsNaN(f2)) - { - return float.IsNaN(f1) && float.IsNaN(f2); - } - - return Math.Abs(f2 - f1) < float.Epsilon; - } - - public void Insert(int index, CSSNode node) - { - if (_children == null) - { - _children = new List(4); - } - _children.Insert(index, node); - node._parent = new WeakReference(this); - Native.CSSNodeInsertChild(_cssNode, node._cssNode, (uint)index); - } - - public void RemoveAt(int index) - { - var child = _children[index]; - child._parent = null; - _children.RemoveAt(index); - Native.CSSNodeRemoveChild(_cssNode, child._cssNode); - } - - public void Clear() - { - if (_children != null) - { - while (_children.Count > 0) - { - RemoveAt(_children.Count-1); - } - } - } - - public int IndexOf(CSSNode node) - { - return _children != null ? _children.IndexOf(node) : -1; - } - - public void SetMeasureFunction(MeasureFunction measureFunction) - { - _measureFunction = measureFunction; - _cssMeasureFunc = measureFunction != null ? MeasureInternal : (CSSMeasureFunc)null; - Native.CSSNodeSetMeasureFunc(_cssNode, _cssMeasureFunc); - } - - public void CalculateLayout() - { - Native.CSSNodeCalculateLayout( - _cssNode, - CSSConstants.Undefined, - CSSConstants.Undefined, - Native.CSSNodeStyleGetDirection(_cssNode)); - } - - private CSSSize MeasureInternal( - IntPtr node, - float width, - CSSMeasureMode widthMode, - float height, - CSSMeasureMode heightMode) - { - if (_measureFunction == null) - { - throw new InvalidOperationException("Measure function is not defined."); - } - - long output = _measureFunction(this, width, widthMode, height, heightMode); - return new CSSSize { width = MeasureOutput.GetWidth(output), height = MeasureOutput.GetHeight(output) }; - } - -// BEGIN_UNITY @joce CompileForC#Bindings - Default arguments are not supported on all Unity platforms - //public string Print(CSSPrintOptions options = - // CSSPrintOptions.Layout|CSSPrintOptions.Style|CSSPrintOptions.Children) - public string Print() - { - return Print(CSSPrintOptions.Layout|CSSPrintOptions.Style|CSSPrintOptions.Children); - } - - public string Print(CSSPrintOptions options) - { -// END_UNITY - StringBuilder sb = new StringBuilder(); - CSSLogger.Func orig = CSSLogger.Logger; - CSSLogger.Logger = (level, message) => {sb.Append(message);}; - Native.CSSNodePrint(_cssNode, options); - CSSLogger.Logger = orig; - return sb.ToString(); - } - - public IEnumerator GetEnumerator() - { - return _children != null ? ((IEnumerable)_children).GetEnumerator() : - System.Linq.Enumerable.Empty().GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return _children != null ? ((IEnumerable)_children).GetEnumerator() : - System.Linq.Enumerable.Empty().GetEnumerator(); - } - - public static int GetInstanceCount() - { - return Native.CSSNodeGetInstanceCount(); - } - - public static void SetExperimentalFeatureEnabled( - CSSExperimentalFeature feature, - bool enabled) - { - Native.CSSLayoutSetExperimentalFeatureEnabled(feature, enabled); - } - - public static bool IsExperimentalFeatureEnabled(CSSExperimentalFeature feature) - { - return Native.CSSLayoutIsExperimentalFeatureEnabled(feature); - } - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSOverflow.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSOverflow.cs deleted file mode 100644 index 81d75a50db..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSOverflow.cs +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSOverflow - { - Visible, - Hidden, - Scroll, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSPositionType.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSPositionType.cs deleted file mode 100644 index 469144e51c..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSPositionType.cs +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSPositionType - { - Relative, - Absolute, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSPrintOptions.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSPrintOptions.cs deleted file mode 100644 index 9d44f44dda..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSPrintOptions.cs +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSPrintOptions - { - Layout = 1, - Style = 2, - Children = 4, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSSize.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSSize.cs deleted file mode 100644 index 79d27e3422..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSSize.cs +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -using System.Runtime.InteropServices; - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - [StructLayout(LayoutKind.Sequential)] - internal struct CSSSize - { - public float width; - public float height; - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSWrap.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/CSSWrap.cs deleted file mode 100644 index 01dd52b2e9..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/CSSWrap.cs +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal enum CSSWrap - { - NoWrap, - Wrap, - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/ConcurrentDictionary.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/ConcurrentDictionary.cs deleted file mode 100644 index 9dd20fd55f..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/ConcurrentDictionary.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; - -namespace UnityEngine.CSSLayout -{ - internal class LockDictionary - { - object _cacheLock = new object(); - Dictionary _cacheItemDictionary = new Dictionary(); - - public void Set(TKey key, TValue value) - { - lock (_cacheLock) - { - _cacheItemDictionary[key] = value; - } - } - - public bool TryGetValue(TKey key, out TValue cacheItem) - { - bool found; - - lock (_cacheLock) - { - found = _cacheItemDictionary.TryGetValue(key, out cacheItem); - } - - if (!found) - { - cacheItem = default(TValue); - } - - return found; - } - - public bool ContainsKey(TKey key) - { - bool found = false; - - lock (_cacheLock) - { - found = _cacheItemDictionary.ContainsKey(key); - } - - return found; - } - - public void Remove(TKey key) - { - lock (_cacheLock) - { - _cacheItemDictionary.Remove(key); - } - } - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/MeasureFunction.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/MeasureFunction.cs deleted file mode 100644 index c87b41e7c3..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/MeasureFunction.cs +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ -// BEGIN_UNITY @joce 11-21-2016 CompileForC#Bindings - //internal delegate long MeasureFunction( - internal delegate long MeasureFunction( -// END_UNITY - CSSNode node, - float width, - CSSMeasureMode widthMode, - float height, - CSSMeasureMode heightMode); -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/MeasureOutput.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/MeasureOutput.cs deleted file mode 100644 index ad45256b2d..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/MeasureOutput.cs +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-07-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ - internal class MeasureOutput - { - public static long Make(double width, double height) - { - return Make((int) width, (int) height); - } - - public static long Make(int width, int height) - { - return (long)(((ulong) width) << 32 | ((uint) height)); - } - - public static int GetWidth(long measureOutput) - { - return (int) (0xFFFFFFFF & (measureOutput >> 32)); - } - - public static int GetHeight(long measureOutput) - { - return (int) (0xFFFFFFFF & measureOutput); - } - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/Native.bindings.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/Native.bindings.cs deleted file mode 100644 index 72f40d5acb..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/Native.bindings.cs +++ /dev/null @@ -1,329 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -using System; -using UnityEngine.Scripting; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Threading; -using UnityEngine.Bindings; - -namespace UnityEngine.CSSLayout -{ - [NativeHeader("External/CSSLayout/CSSLayout/Native.bindings.h")] - internal static partial class Native - { - private const string DllName = "CSSLayout"; - - static LockDictionary s_MeasureFunctions = new LockDictionary(); - -// BEGIN_UNITY -// TODO we don't support the logging feature yet -// [DllImport(DllName)] -// public static extern void CSSInteropSetLogger( -// [MarshalAs(UnmanagedType.FunctionPtr)] CSSLogger.Func func); -// END_UNITY - [FreeFunction] - public static extern IntPtr CSSNodeNew(); - - [FreeFunction] - public static extern void CSSNodeInit(IntPtr cssNode); - - public static void CSSNodeFree(IntPtr cssNode) - { - if (cssNode == IntPtr.Zero) return; - CSSNodeSetMeasureFunc(cssNode, null); - CSSNodeFreeInternal(cssNode); - } - - [NativeMethod(Name = "CSSNodeFree", IsFreeFunction = true, IsThreadSafe = true)] - static extern void CSSNodeFreeInternal(IntPtr cssNode); - - public static void CSSNodeReset(IntPtr cssNode) - { - CSSNodeSetMeasureFunc(cssNode, null); - CSSNodeResetInternal(cssNode); - } - - [NativeMethod(Name = "CSSNodeReset", IsFreeFunction = true)] - static extern void CSSNodeResetInternal(IntPtr cssNode); - - [FreeFunction] - public static extern int CSSNodeGetInstanceCount(); - - [FreeFunction] - public static extern void CSSLayoutSetExperimentalFeatureEnabled( - CSSExperimentalFeature feature, - bool enabled); - - [FreeFunction] - public static extern bool CSSLayoutIsExperimentalFeatureEnabled( - CSSExperimentalFeature feature); - - [FreeFunction] - public static extern void CSSNodeInsertChild(IntPtr node, IntPtr child, uint index); - - [FreeFunction] - public static extern void CSSNodeRemoveChild(IntPtr node, IntPtr child); - - [FreeFunction] - public static extern IntPtr CSSNodeGetChild(IntPtr node, uint index); - - [FreeFunction] - public static extern uint CSSNodeChildCount(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeCalculateLayout(IntPtr node, - float availableWidth, - float availableHeight, - CSSDirection parentDirection); - - [FreeFunction] - public static extern void CSSNodeMarkDirty(IntPtr node); - - [FreeFunction] - public static extern bool CSSNodeIsDirty(IntPtr node); - - [FreeFunction] - public static extern void CSSNodePrint(IntPtr node, CSSPrintOptions options); - - [FreeFunction] - public static extern bool CSSValueIsUndefined(float value); - - [FreeFunction] - public static extern void CSSNodeCopyStyle(IntPtr dstNode, IntPtr srcNode); - - #region CSS_NODE_PROPERTY - - [FreeFunction] - public static extern void CSSNodeSetContext(IntPtr node, IntPtr context); - - [FreeFunction] - public static extern IntPtr CSSNodeGetContext(IntPtr node); - - public static void CSSNodeSetMeasureFunc(IntPtr node, CSSMeasureFunc measureFunc) - { - if (measureFunc != null) - { - s_MeasureFunctions.Set(node, new WeakReference(measureFunc)); - CSSLayoutCallbacks.RegisterWrapper(node); - } - else if (s_MeasureFunctions.ContainsKey(node)) - { - s_MeasureFunctions.Remove(node); - CSSLayoutCallbacks.UnegisterWrapper(node); - } - } - - public static CSSMeasureFunc CSSNodeGetMeasureFunc(IntPtr node) - { - WeakReference reference = null; - if (s_MeasureFunctions.TryGetValue(node, out reference) && reference.IsAlive) - { - return reference.Target as CSSMeasureFunc; - } - else - { - return null; - } - } - - [RequiredByNativeCode] - unsafe public static void CSSNodeMeasureInvoke(IntPtr node, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode, IntPtr returnValueAddress) - { - CSSMeasureFunc func = CSSNodeGetMeasureFunc(node); - if (func != null) - { - (*(CSSSize*)returnValueAddress) = func.Invoke(node, width, widthMode, height, heightMode); - } - } - - [FreeFunction] - public static extern void CSSNodeSetHasNewLayout(IntPtr node, bool hasNewLayout); - - [FreeFunction] - public static extern bool CSSNodeGetHasNewLayout(IntPtr node); - - #endregion - - #region CSS_NODE_STYLE_PROPERTY - - [FreeFunction] - public static extern void CSSNodeStyleSetDirection(IntPtr node, CSSDirection direction); - - [FreeFunction] - public static extern CSSDirection CSSNodeStyleGetDirection(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetFlexDirection(IntPtr node, CSSFlexDirection flexDirection); - - [FreeFunction] - public static extern CSSFlexDirection CSSNodeStyleGetFlexDirection(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetJustifyContent(IntPtr node, CSSJustify justifyContent); - - [FreeFunction] - public static extern CSSJustify CSSNodeStyleGetJustifyContent(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetAlignContent(IntPtr node, CSSAlign alignContent); - - [FreeFunction] - public static extern CSSAlign CSSNodeStyleGetAlignContent(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetAlignItems(IntPtr node, CSSAlign alignItems); - - [FreeFunction] - public static extern CSSAlign CSSNodeStyleGetAlignItems(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetAlignSelf(IntPtr node, CSSAlign alignSelf); - - [FreeFunction] - public static extern CSSAlign CSSNodeStyleGetAlignSelf(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetPositionType(IntPtr node, CSSPositionType positionType); - - [FreeFunction] - public static extern CSSPositionType CSSNodeStyleGetPositionType(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetFlexWrap(IntPtr node, CSSWrap flexWrap); - - [FreeFunction] - public static extern CSSWrap CSSNodeStyleGetFlexWrap(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetOverflow(IntPtr node, CSSOverflow flexWrap); - - [FreeFunction] - public static extern CSSOverflow CSSNodeStyleGetOverflow(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetFlex(IntPtr node, float flex); - - [FreeFunction] - public static extern void CSSNodeStyleSetFlexGrow(IntPtr node, float flexGrow); - - [FreeFunction] - public static extern float CSSNodeStyleGetFlexGrow(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetFlexShrink(IntPtr node, float flexShrink); - - [FreeFunction] - public static extern float CSSNodeStyleGetFlexShrink(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetFlexBasis(IntPtr node, float flexBasis); - - [FreeFunction] - public static extern float CSSNodeStyleGetFlexBasis(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetWidth(IntPtr node, float width); - - [FreeFunction] - public static extern float CSSNodeStyleGetWidth(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetHeight(IntPtr node, float height); - - [FreeFunction] - public static extern float CSSNodeStyleGetHeight(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetMinWidth(IntPtr node, float minWidth); - - [FreeFunction] - public static extern float CSSNodeStyleGetMinWidth(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetMinHeight(IntPtr node, float minHeight); - - [FreeFunction] - public static extern float CSSNodeStyleGetMinHeight(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetMaxWidth(IntPtr node, float maxWidth); - - [FreeFunction] - public static extern float CSSNodeStyleGetMaxWidth(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetMaxHeight(IntPtr node, float maxHeight); - - [FreeFunction] - public static extern float CSSNodeStyleGetMaxHeight(IntPtr node); - - [FreeFunction] - public static extern void CSSNodeStyleSetAspectRatio(IntPtr node, float aspectRatio); - - [FreeFunction] - public static extern float CSSNodeStyleGetAspectRatio(IntPtr node); - - #endregion - - #region CSS_NODE_STYLE_EDGE_PROPERTY - - [FreeFunction] - public static extern void CSSNodeStyleSetPosition(IntPtr node, CSSEdge edge, float position); - - [FreeFunction] - public static extern float CSSNodeStyleGetPosition(IntPtr node, CSSEdge edge); - - [FreeFunction] - public static extern void CSSNodeStyleSetMargin(IntPtr node, CSSEdge edge, float margin); - - [FreeFunction] - public static extern float CSSNodeStyleGetMargin(IntPtr node, CSSEdge edge); - - [FreeFunction] - public static extern void CSSNodeStyleSetPadding(IntPtr node, CSSEdge edge, float padding); - - [FreeFunction] - public static extern float CSSNodeStyleGetPadding(IntPtr node, CSSEdge edge); - - [FreeFunction] - public static extern void CSSNodeStyleSetBorder(IntPtr node, CSSEdge edge, float border); - - [FreeFunction] - public static extern float CSSNodeStyleGetBorder(IntPtr node, CSSEdge edge); - - #endregion - - #region CSS_NODE_LAYOUT_PROPERTY - - [FreeFunction] - public static extern float CSSNodeLayoutGetLeft(IntPtr node); - - [FreeFunction] - public static extern float CSSNodeLayoutGetTop(IntPtr node); - - [FreeFunction] - public static extern float CSSNodeLayoutGetRight(IntPtr node); - - [FreeFunction] - public static extern float CSSNodeLayoutGetBottom(IntPtr node); - - [FreeFunction] - public static extern float CSSNodeLayoutGetWidth(IntPtr node); - - [FreeFunction] - public static extern float CSSNodeLayoutGetHeight(IntPtr node); - - [FreeFunction] - public static extern CSSDirection CSSNodeLayoutGetDirection(IntPtr node); - - #endregion - } -} diff --git a/External/CSSLayout/csharp/Facebook.CSSLayout/Spacing.cs b/External/CSSLayout/csharp/Facebook.CSSLayout/Spacing.cs deleted file mode 100644 index 91be328059..0000000000 --- a/External/CSSLayout/csharp/Facebook.CSSLayout/Spacing.cs +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// BEGIN_UNITY @joce 11-21-2016 CompileForC#Bindings -//namespace Facebook.CSSLayout -namespace UnityEngine.CSSLayout -// END_UNITY -{ -} diff --git a/External/ExCSS/builds/builds/lib/net35/ExCSS.Unity.dll b/External/ExCSS/builds/builds/lib/net35/ExCSS.Unity.dll deleted file mode 100644 index 04fbb296f198af482580261e6355300633cc8bdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90624 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 diff --git a/External/JsonParsers/MiniJson/MiniJSON.cs b/External/JsonParsers/MiniJson/MiniJSON.cs deleted file mode 100644 index b12d913d9f..0000000000 --- a/External/JsonParsers/MiniJson/MiniJSON.cs +++ /dev/null @@ -1,638 +0,0 @@ -/* - * Copyright (c) 2013 Calvin Rien - * - * Based on the JSON parser by Patrick van Bergen - * http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html - * - * Simplified it so that it doesn't throw exceptions - * and can be used in Unity iPhone with maximum code stripping. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Text; - -namespace UnityEditor -{ - // Example usage: - // - // using UnityEngine; - // using UnityEditor; - // using System.Collections; - // using System.Collections.Generic; - // - // public class MiniJSONTest : MonoBehaviour { - // void Start () { - // var jsonString = "{ \"array\": [1.44,2,3], " + - // "\"object\": {\"key1\":\"value1\", \"key2\":256}, " + - // "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " + - // "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " + - // "\"int\": 65536, " + - // "\"float\": 3.1415926, " + - // "\"bool\": true, " + - // "\"null\": null }"; - // - // var dict = Json.Deserialize (jsonString) as Dictionary; - // - // Debug.Log ("deserialized: " + dict.GetType ()); - // Debug.Log ("dict['array'][0]: " + ((List) dict["array"])[0]); - // Debug.Log ("dict['string']: " + (string) dict["string"]); - // Debug.Log ("dict['float']: " + (double) dict["float"]); // floats come out as doubles - // Debug.Log ("dict['int']: " + (long) dict["int"]); // ints come out as longs - // Debug.Log ("dict['unicode']: " + (string) dict["unicode"]); - // - // var str = Json.Serialize (dict); - // - // Debug.Log ("serialized: " + str); - // } - // } - - /// - /// This class encodes and decodes JSON strings. - /// Spec. details, see http://www.json.org/ - /// - /// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary. - /// All numbers are parsed to doubles. - /// - internal static class Json - { - /// - /// Parses the string json into a value - /// - /// A JSON string. - /// An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false - public static object Deserialize (string json) - { - // save the string for debug information - if (json == null) - { - return null; - } - - return Parser.Parse (json); - } - - sealed class Parser : IDisposable - { - const string WORD_BREAK = "{}[],:\""; - - public static bool IsWordBreak (char c) - { - return Char.IsWhiteSpace (c) || WORD_BREAK.IndexOf (c) != -1; - } - - enum TOKEN - { - NONE, - CURLY_OPEN, - CURLY_CLOSE, - SQUARED_OPEN, - SQUARED_CLOSE, - COLON, - COMMA, - STRING, - NUMBER, - TRUE, - FALSE, - NULL - }; - - StringReader json; - - Parser (string jsonString) - { - json = new StringReader (jsonString); - } - - public static object Parse (string jsonString) - { - using (var instance = new Parser (jsonString)) - { - return instance.ParseValue (); - } - } - - public void Dispose () - { - json.Dispose (); - json = null; - } - - Dictionary ParseObject () - { - Dictionary table = new Dictionary (); - - // ditch opening brace - json.Read (); - - // { - while (true) - { - switch (NextToken) - { - case TOKEN.NONE: - return null; - case TOKEN.COMMA: - continue; - case TOKEN.CURLY_CLOSE: - return table; - default: - // name - string name = ParseString (); - if (name == null) - { - return null; - } - - // : - if (NextToken != TOKEN.COLON) - { - return null; - } - // ditch the colon - json.Read (); - - // value - table[name] = ParseValue (); - break; - } - } - } - - List ParseArray () - { - List array = new List (); - - // ditch opening bracket - json.Read (); - - // [ - var parsing = true; - while (parsing) - { - TOKEN nextToken = NextToken; - - switch (nextToken) - { - case TOKEN.NONE: - return null; - case TOKEN.COMMA: - continue; - case TOKEN.SQUARED_CLOSE: - parsing = false; - break; - default: - object value = ParseByToken (nextToken); - - array.Add (value); - break; - } - } - - return array; - } - - object ParseValue () - { - TOKEN nextToken = NextToken; - return ParseByToken (nextToken); - } - - object ParseByToken (TOKEN token) - { - switch (token) - { - case TOKEN.STRING: - return ParseString (); - case TOKEN.NUMBER: - return ParseNumber (); - case TOKEN.CURLY_OPEN: - return ParseObject (); - case TOKEN.SQUARED_OPEN: - return ParseArray (); - case TOKEN.TRUE: - return true; - case TOKEN.FALSE: - return false; - case TOKEN.NULL: - return null; - default: - return null; - } - } - - string ParseString () - { - StringBuilder s = new StringBuilder (); - char c; - - // ditch opening quote - json.Read (); - - bool parsing = true; - while (parsing) - { - - if (json.Peek () == -1) - { - parsing = false; - break; - } - - c = NextChar; - switch (c) - { - case '"': - parsing = false; - break; - case '\\': - if (json.Peek () == -1) - { - parsing = false; - break; - } - - c = NextChar; - switch (c) - { - case '"': - case '\\': - case '/': - s.Append (c); - break; - case 'b': - s.Append ('\b'); - break; - case 'f': - s.Append ('\f'); - break; - case 'n': - s.Append ('\n'); - break; - case 'r': - s.Append ('\r'); - break; - case 't': - s.Append ('\t'); - break; - case 'u': - var hex = new char[4]; - - for (int i=0; i< 4; i++) - { - hex[i] = NextChar; - } - - s.Append ((char) Convert.ToInt32 (new string (hex), 16)); - break; - } - break; - default: - s.Append (c); - break; - } - } - - return s.ToString (); - } - - object ParseNumber () - { - string number = NextWord; - - if (number.IndexOf ('.') == -1) - { - long parsedInt; - Int64.TryParse (number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedInt); - return parsedInt; - } - - double parsedDouble; - Double.TryParse (number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedDouble); - return parsedDouble; - } - - void EatWhitespace () - { - while (Char.IsWhiteSpace (PeekChar)) - { - json.Read (); - - if (json.Peek () == -1) - { - break; - } - } - } - - char PeekChar - { - get - { - return Convert.ToChar (json.Peek ()); - } - } - - char NextChar - { - get - { - return Convert.ToChar (json.Read ()); - } - } - - string NextWord - { - get - { - StringBuilder word = new StringBuilder (); - - while (!IsWordBreak (PeekChar)) - { - word.Append (NextChar); - - if (json.Peek () == -1) - { - break; - } - } - - return word.ToString (); - } - } - - TOKEN NextToken - { - get - { - EatWhitespace (); - - if (json.Peek () == -1) - { - return TOKEN.NONE; - } - - switch (PeekChar) - { - case '{': - return TOKEN.CURLY_OPEN; - case '}': - json.Read (); - return TOKEN.CURLY_CLOSE; - case '[': - return TOKEN.SQUARED_OPEN; - case ']': - json.Read (); - return TOKEN.SQUARED_CLOSE; - case ',': - json.Read (); - return TOKEN.COMMA; - case '"': - return TOKEN.STRING; - case ':': - return TOKEN.COLON; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - return TOKEN.NUMBER; - } - - switch (NextWord) - { - case "false": - return TOKEN.FALSE; - case "true": - return TOKEN.TRUE; - case "null": - return TOKEN.NULL; - } - - return TOKEN.NONE; - } - } - } - - /// - /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string - /// - /// A Dictionary<string, object> / List<object> - /// A JSON encoded string, or null if object 'json' is not serializable - public static string Serialize (object obj) - { - return Serializer.Serialize (obj); - } - - sealed class Serializer - { - StringBuilder builder; - - Serializer () - { - builder = new StringBuilder (); - } - - public static string Serialize (object obj) - { - var instance = new Serializer (); - - instance.SerializeValue (obj); - - return instance.builder.ToString (); - } - - void SerializeValue (object value) - { - IList asList; - IDictionary asDict; - string asStr; - - if (value == null) - { - builder.Append ("null"); - } - else if ((asStr = value as string) != null) - { - SerializeString (asStr); - } - else if (value is bool) - { - builder.Append ((bool) value ? "true" : "false"); - } - else if ((asList = value as IList) != null) - { - SerializeArray (asList); - } - else if ((asDict = value as IDictionary) != null) - { - SerializeObject (asDict); - } - else if (value is char) - { - SerializeString (new string ((char) value, 1)); - } - else - { - SerializeOther (value); - } - } - - void SerializeObject (IDictionary obj) - { - bool first = true; - - builder.Append ('{'); - - foreach (object e in obj.Keys) - { - if (!first) - { - builder.Append (','); - } - - SerializeString (e.ToString ()); - builder.Append (':'); - - SerializeValue (obj[e]); - - first = false; - } - - builder.Append ('}'); - } - - void SerializeArray (IList anArray) - { - builder.Append ('['); - - bool first = true; - - foreach (object obj in anArray) - { - if (!first) - { - builder.Append (','); - } - - SerializeValue (obj); - - first = false; - } - - builder.Append (']'); - } - - void SerializeString (string str) - { - builder.Append ('\"'); - - char[] charArray = str.ToCharArray (); - foreach (var c in charArray) - { - switch (c) - { - case '"': - builder.Append ("\\\""); - break; - case '\\': - builder.Append ("\\\\"); - break; - case '\b': - builder.Append ("\\b"); - break; - case '\f': - builder.Append ("\\f"); - break; - case '\n': - builder.Append ("\\n"); - break; - case '\r': - builder.Append ("\\r"); - break; - case '\t': - builder.Append ("\\t"); - break; - default: - int codepoint = Convert.ToInt32 (c); - if ((codepoint >= 32) && (codepoint <= 126)) - { - builder.Append (c); - } - else - { - builder.Append ("\\u"); - builder.Append (codepoint.ToString ("x4")); - } - break; - } - } - - builder.Append ('\"'); - } - - void SerializeOther (object value) - { - // NOTE: decimals lose precision during serialization. - // They always have, I'm just letting you know. - // Previously floats and doubles lost precision too. - if (value is float) - { - builder.Append (((float) value).ToString ("R", System.Globalization.CultureInfo.InvariantCulture)); - } - else if (value is int || value is uint || value is long || value is sbyte || value is byte || value is short || value is ushort || value is ulong) - { - builder.Append (value); - } - else if (value is double || value is decimal) - { - builder.Append (Convert.ToDouble (value).ToString ("R", System.Globalization.CultureInfo.InvariantCulture)); - } - else - { - Dictionary map = new Dictionary (); - List fields = value.GetType ().GetFields (BindingFlags.Instance | BindingFlags.Public).ToList (); - foreach (FieldInfo field in fields) - { - map.Add (field.Name, field.GetValue (value)); - } - List properties = value.GetType ().GetProperties (BindingFlags.Instance | BindingFlags.Public).ToList (); - foreach (PropertyInfo property in properties) - { - map.Add (property.Name, property.GetValue (value, null)); - } - SerializeObject (map); - } - } - } - } -} diff --git a/External/JsonParsers/SimpleJson/SimpleJson.cs b/External/JsonParsers/SimpleJson/SimpleJson.cs deleted file mode 100644 index 51d1b1d94e..0000000000 --- a/External/JsonParsers/SimpleJson/SimpleJson.cs +++ /dev/null @@ -1,1664 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) 2011, The Outercurve Foundation. -// -// Licensed under the MIT License (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.opensource.org/licenses/mit-license.php -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// Nathan Totten (ntotten.com), Jim Zimmerman (jimzimmerman.com) and Prabir Shrestha (prabir.me) -// https://github.com/facebook-csharp-sdk/simple-json -//----------------------------------------------------------------------- - -// VERSION: - -// NOTE: uncomment the following line to make SimpleJson class internal. - -// NOTE: uncomment the following line to make JsonArray and JsonObject class internal. - -// NOTE: uncomment the following line to enable dynamic support. -//#define SIMPLE_JSON_DYNAMIC - -// NOTE: uncomment the following line to enable DataContract support. -//#define SIMPLE_JSON_DATACONTRACT - -// NOTE: uncomment the following line to disable linq expressions/compiled lambda (better performance) instead of method.invoke(). -// define if you are using .net framework <= 3.0 or < WP7.5 - -// NOTE: uncomment the following line if you are compiling under Window Metro style application/library. -// usually already defined in properties -//#define NETFX_CORE; - -// original json parsing code from http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html - - -using System; -using System.CodeDom.Compiler; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Reflection; -using System.Runtime.Serialization; -using System.Text; -using SimpleJson.Reflection; -using UnityEngine.Bindings; - -// ReSharper disable LoopCanBeConvertedToQuery -// ReSharper disable RedundantExplicitArrayCreation -// ReSharper disable SuggestUseVarKeywordEvident -namespace SimpleJson -{ -/// -/// Represents the json array. -/// -[GeneratedCode ("simple-json", "1.0.0")] -[EditorBrowsable (EditorBrowsableState.Never)] -[SuppressMessage ("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] -internal -class JsonArray : List -{ - /// - /// Initializes a new instance of the class. - /// - public JsonArray () { } - - /// - /// Initializes a new instance of the class. - /// - /// The capacity of the json array. - public JsonArray (int capacity) : base (capacity) { } - - /// - /// The json representation of the array. - /// - /// The json representation of the array. - public override string ToString () - { - return SimpleJson.SerializeObject (this) ?? string.Empty; - } -} - -/// -/// Represents the json object. -/// -[GeneratedCode ("simple-json", "1.0.0")] -[EditorBrowsable (EditorBrowsableState.Never)] -[SuppressMessage ("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] -internal -class JsonObject : - IDictionary -{ - /// - /// The internal member dictionary. - /// - private readonly Dictionary _members; - - /// - /// Initializes a new instance of . - /// - public JsonObject () - { - _members = new Dictionary (); - } - - /// - /// Initializes a new instance of . - /// - /// The implementation to use when comparing keys, or null to use the default for the type of the key. - public JsonObject (IEqualityComparer comparer) - { - _members = new Dictionary (comparer); - } - - /// - /// Gets the at the specified index. - /// - /// - public object this[int index] - { - get - { - return GetAtIndex (_members, index); - } - } - - internal static object GetAtIndex (IDictionary obj, int index) - { - if (obj == null) - throw new ArgumentNullException ("obj"); - if (index >= obj.Count) - throw new ArgumentOutOfRangeException ("index"); - int i = 0; - foreach (KeyValuePair o in obj) - if (i++ == index) return o.Value; - return null; - } - - /// - /// Adds the specified key. - /// - /// The key. - /// The value. - public void Add (string key, object value) - { - _members.Add (key, value); - } - - /// - /// Determines whether the specified key contains key. - /// - /// The key. - /// - /// true if the specified key contains key; otherwise, false. - /// - public bool ContainsKey (string key) - { - return _members.ContainsKey (key); - } - - /// - /// Gets the keys. - /// - /// The keys. - public ICollection Keys - { - get - { - return _members.Keys; - } - } - - /// - /// Removes the specified key. - /// - /// The key. - /// - public bool Remove (string key) - { - return _members.Remove (key); - } - - /// - /// Tries the get value. - /// - /// The key. - /// The value. - /// - public bool TryGetValue (string key, out object value) - { - return _members.TryGetValue (key, out value); - } - - /// - /// Gets the values. - /// - /// The values. - public ICollection Values - { - get - { - return _members.Values; - } - } - - /// - /// Gets or sets the with the specified key. - /// - /// - public object this[string key] - { - get - { - return _members[key]; - } - set - { - _members[key] = value; - } - } - - /// - /// Adds the specified item. - /// - /// The item. - public void Add (KeyValuePair item) - { - _members.Add (item.Key, item.Value); - } - - /// - /// Clears this instance. - /// - public void Clear () - { - _members.Clear (); - } - - /// - /// Determines whether [contains] [the specified item]. - /// - /// The item. - /// - /// true if [contains] [the specified item]; otherwise, false. - /// - public bool Contains (KeyValuePair item) - { - return _members.ContainsKey (item.Key) && _members[item.Key] == item.Value; - } - - /// - /// Copies to. - /// - /// The array. - /// Index of the array. - public void CopyTo (KeyValuePair[] array, int arrayIndex) - { - if (array == null) throw new ArgumentNullException ("array"); - int num = Count; - foreach (KeyValuePair kvp in this) - { - array[arrayIndex++] = kvp; - if (--num <= 0) - return; - } - } - - /// - /// Gets the count. - /// - /// The count. - public int Count - { - get - { - return _members.Count; - } - } - - /// - /// Gets a value indicating whether this instance is read only. - /// - /// - /// true if this instance is read only; otherwise, false. - /// - public bool IsReadOnly - { - get - { - return false; - } - } - - /// - /// Removes the specified item. - /// - /// The item. - /// - public bool Remove (KeyValuePair item) - { - return _members.Remove (item.Key); - } - - /// - /// Gets the enumerator. - /// - /// - public IEnumerator> GetEnumerator () - { - return _members.GetEnumerator (); - } - - /// - /// Returns an enumerator that iterates through a collection. - /// - /// - /// An object that can be used to iterate through the collection. - /// - IEnumerator IEnumerable.GetEnumerator () - { - return _members.GetEnumerator (); - } - - /// - /// Returns a json that represents the current . - /// - /// - /// A json that represents the current . - /// - public override string ToString () - { - return SimpleJson.SerializeObject (this); - } - -} -} - -namespace SimpleJson -{ -/// -/// This class encodes and decodes JSON strings. -/// Spec. details, see http://www.json.org/ -/// -/// JSON uses Arrays and Objects. These correspond here to the datatypes JsonArray(IList<object>) and JsonObject(IDictionary<string,object>). -/// All numbers are parsed to doubles. -/// -[GeneratedCode ("simple-json", "1.0.0")] -[VisibleToOtherModules] -internal -static class SimpleJson -{ - private const int TOKEN_NONE = 0; - private const int TOKEN_CURLY_OPEN = 1; - private const int TOKEN_CURLY_CLOSE = 2; - private const int TOKEN_SQUARED_OPEN = 3; - private const int TOKEN_SQUARED_CLOSE = 4; - private const int TOKEN_COLON = 5; - private const int TOKEN_COMMA = 6; - private const int TOKEN_STRING = 7; - private const int TOKEN_NUMBER = 8; - private const int TOKEN_TRUE = 9; - private const int TOKEN_FALSE = 10; - private const int TOKEN_NULL = 11; - private const int BUILDER_CAPACITY = 2000; - - /// - /// Parses the string json into a value - /// - /// A JSON string. - /// An IList<object>, a IDictionary<string,object>, a double, a string, null, true, or false - public static object DeserializeObject (string json) - { - object obj; - if (TryDeserializeObject (json, out obj)) - return obj; - throw new SerializationException ("Invalid JSON string"); - } - - /// - /// Try parsing the json string into a value. - /// - /// - /// A JSON string. - /// - /// - /// The object. - /// - /// - /// Returns true if successfull otherwise false. - /// - [SuppressMessage ("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification="Need to support .NET 2")] - public static bool TryDeserializeObject (string json, out object obj) - { - bool success = true; - if (json != null) - { - char[] charArray = json.ToCharArray (); - int index = 0; - obj = ParseValue (charArray, ref index, ref success); - } - else - obj = null; - - return success; - } - - public static object DeserializeObject (string json, Type type, IJsonSerializerStrategy jsonSerializerStrategy) - { - object jsonObject = DeserializeObject (json); - return type == null || jsonObject != null && ReflectionUtils.IsAssignableFrom (jsonObject.GetType (), type) - ? jsonObject - : (jsonSerializerStrategy ?? CurrentJsonSerializerStrategy).DeserializeObject (jsonObject, type); - } - - public static object DeserializeObject (string json, Type type) - { - return DeserializeObject (json, type, null); - } - - public static T DeserializeObject (string json, IJsonSerializerStrategy jsonSerializerStrategy) - { - return (T)DeserializeObject (json, typeof (T), jsonSerializerStrategy); - } - - public static T DeserializeObject (string json) - { - return (T)DeserializeObject (json, typeof (T), null); - } - - /// - /// Converts a IDictionary<string,object> / IList<object> object into a JSON string - /// - /// A IDictionary<string,object> / IList<object> - /// Serializer strategy to use - /// A JSON encoded string, or null if object 'json' is not serializable - public static string SerializeObject (object json, IJsonSerializerStrategy jsonSerializerStrategy) - { - StringBuilder builder = new StringBuilder (BUILDER_CAPACITY); - bool success = SerializeValue (jsonSerializerStrategy, json, builder); - return (success ? builder.ToString () : null); - } - - public static string SerializeObject (object json) - { - return SerializeObject (json, CurrentJsonSerializerStrategy); - } - - public static string EscapeToJavascriptString (string jsonString) - { - if (string.IsNullOrEmpty (jsonString)) - return jsonString; - - StringBuilder sb = new StringBuilder (); - char c; - - for (int i = 0; i < jsonString.Length; ) - { - c = jsonString[i++]; - - if (c == '\\') - { - int remainingLength = jsonString.Length - i; - if (remainingLength >= 2) - { - char lookahead = jsonString[i]; - if (lookahead == '\\') - { - sb.Append ('\\'); - ++i; - } - else if (lookahead == '"') - { - sb.Append ("\""); - ++i; - } - else if (lookahead == 't') - { - sb.Append ('\t'); - ++i; - } - else if (lookahead == 'b') - { - sb.Append ('\b'); - ++i; - } - else if (lookahead == 'n') - { - sb.Append ('\n'); - ++i; - } - else if (lookahead == 'r') - { - sb.Append ('\r'); - ++i; - } - } - } - else - { - sb.Append (c); - } - } - return sb.ToString (); - } - - static IDictionary ParseObject (char[] json, ref int index, ref bool success) - { - IDictionary table = new JsonObject (); - int token; - - // { - NextToken (json, ref index); - - bool done = false; - while (!done) - { - token = LookAhead (json, index); - if (token == TOKEN_NONE) - { - success = false; - return null; - } - else if (token == TOKEN_COMMA) - NextToken (json, ref index); - else if (token == TOKEN_CURLY_CLOSE) - { - NextToken (json, ref index); - return table; - } - else - { - // name - string name = ParseString (json, ref index, ref success); - if (!success) - { - success = false; - return null; - } - // : - token = NextToken (json, ref index); - if (token != TOKEN_COLON) - { - success = false; - return null; - } - // value - object value = ParseValue (json, ref index, ref success); - if (!success) - { - success = false; - return null; - } - table[name] = value; - } - } - return table; - } - - static JsonArray ParseArray (char[] json, ref int index, ref bool success) - { - JsonArray array = new JsonArray (); - - // [ - NextToken (json, ref index); - - bool done = false; - while (!done) - { - int token = LookAhead (json, index); - if (token == TOKEN_NONE) - { - success = false; - return null; - } - else if (token == TOKEN_COMMA) - NextToken (json, ref index); - else if (token == TOKEN_SQUARED_CLOSE) - { - NextToken (json, ref index); - break; - } - else - { - object value = ParseValue (json, ref index, ref success); - if (!success) - return null; - array.Add (value); - } - } - return array; - } - - static object ParseValue (char[] json, ref int index, ref bool success) - { - switch (LookAhead (json, index)) - { - case TOKEN_STRING: - return ParseString (json, ref index, ref success); - case TOKEN_NUMBER: - return ParseNumber (json, ref index, ref success); - case TOKEN_CURLY_OPEN: - return ParseObject (json, ref index, ref success); - case TOKEN_SQUARED_OPEN: - return ParseArray (json, ref index, ref success); - case TOKEN_TRUE: - NextToken (json, ref index); - return true; - case TOKEN_FALSE: - NextToken (json, ref index); - return false; - case TOKEN_NULL: - NextToken (json, ref index); - return null; - case TOKEN_NONE: - break; - } - success = false; - return null; - } - - static string ParseString (char[] json, ref int index, ref bool success) - { - StringBuilder s = new StringBuilder (BUILDER_CAPACITY); - char c; - - EatWhitespace (json, ref index); - - // " - c = json[index++]; - bool complete = false; - while (!complete) - { - if (index == json.Length) - break; - - c = json[index++]; - if (c == '"') - { - complete = true; - break; - } - else if (c == '\\') - { - if (index == json.Length) - break; - c = json[index++]; - if (c == '"') - s.Append ('"'); - else if (c == '\\') - s.Append ('\\'); - else if (c == '/') - s.Append ('/'); - else if (c == 'b') - s.Append ('\b'); - else if (c == 'f') - s.Append ('\f'); - else if (c == 'n') - s.Append ('\n'); - else if (c == 'r') - s.Append ('\r'); - else if (c == 't') - s.Append ('\t'); - else if (c == 'u') - { - int remainingLength = json.Length - index; - if (remainingLength >= 4) - { - // parse the 32 bit hex into an integer codepoint - uint codePoint; - if (! (success = UInt32.TryParse (new string (json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codePoint))) - return ""; - - // convert the integer codepoint to a unicode char and add to string - if (0xD800 <= codePoint && codePoint <= 0xDBFF) // if high surrogate - { - index += 4; // skip 4 chars - remainingLength = json.Length - index; - if (remainingLength >= 6) - { - uint lowCodePoint; - if (new string (json, index, 2) == "\\u" && UInt32.TryParse (new string (json, index + 2, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out lowCodePoint)) - { - if (0xDC00 <= lowCodePoint && lowCodePoint <= 0xDFFF) // if low surrogate - { - s.Append ((char)codePoint); - s.Append ((char)lowCodePoint); - index += 6; // skip 6 chars - continue; - } - } - } - success = false; // invalid surrogate pair - return ""; - } - s.Append (ConvertFromUtf32 ((int)codePoint)); - // skip 4 chars - index += 4; - } - else - break; - } - } - else - s.Append (c); - } - if (!complete) - { - success = false; - return null; - } - return s.ToString (); - } - - private static string ConvertFromUtf32 (int utf32) - { - // http://www.java2s.com/Open-Source/CSharp/2.6.4-mono-.net-core/System/System/Char.cs.htm - if (utf32 < 0 || utf32 > 0x10FFFF) - throw new ArgumentOutOfRangeException ("utf32", "The argument must be from 0 to 0x10FFFF."); - if (0xD800 <= utf32 && utf32 <= 0xDFFF) - throw new ArgumentOutOfRangeException ("utf32", "The argument must not be in surrogate pair range."); - if (utf32 < 0x10000) - return new string ((char)utf32, 1); - utf32 -= 0x10000; - return new string (new char[] { (char) ((utf32 >> 10) + 0xD800), (char) (utf32 % 0x0400 + 0xDC00) }); - } - - static object ParseNumber (char[] json, ref int index, ref bool success) - { - EatWhitespace (json, ref index); - int lastIndex = GetLastIndexOfNumber (json, index); - int charLength = (lastIndex - index) + 1; - object returnNumber; - string str = new string (json, index, charLength); - if (str.IndexOf (".", StringComparison.OrdinalIgnoreCase) != -1 || str.IndexOf ("e", StringComparison.OrdinalIgnoreCase) != -1) - { - double number; - success = double.TryParse (new string (json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number); - returnNumber = number; - } - else - { - long number; - success = long.TryParse (new string (json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number); - returnNumber = number; - } - index = lastIndex + 1; - return returnNumber; - } - - static int GetLastIndexOfNumber (char[] json, int index) - { - int lastIndex; - for (lastIndex = index; lastIndex < json.Length; lastIndex++) - if ("0123456789+-.eE".IndexOf (json[lastIndex]) == -1) break; - return lastIndex - 1; - } - - static void EatWhitespace (char[] json, ref int index) - { - for (; index < json.Length; index++) - if (" \t\n\r\b\f".IndexOf (json[index]) == -1) break; - } - - static int LookAhead (char[] json, int index) - { - int saveIndex = index; - return NextToken (json, ref saveIndex); - } - - [SuppressMessage ("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] - static int NextToken (char[] json, ref int index) - { - EatWhitespace (json, ref index); - if (index == json.Length) - return TOKEN_NONE; - char c = json[index]; - index++; - switch (c) - { - case '{': - return TOKEN_CURLY_OPEN; - case '}': - return TOKEN_CURLY_CLOSE; - case '[': - return TOKEN_SQUARED_OPEN; - case ']': - return TOKEN_SQUARED_CLOSE; - case ',': - return TOKEN_COMMA; - case '"': - return TOKEN_STRING; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - return TOKEN_NUMBER; - case ':': - return TOKEN_COLON; - } - index--; - int remainingLength = json.Length - index; - // false - if (remainingLength >= 5) - { - if (json[index] == 'f' && json[index + 1] == 'a' && json[index + 2] == 'l' && json[index + 3] == 's' && json[index + 4] == 'e') - { - index += 5; - return TOKEN_FALSE; - } - } - // true - if (remainingLength >= 4) - { - if (json[index] == 't' && json[index + 1] == 'r' && json[index + 2] == 'u' && json[index + 3] == 'e') - { - index += 4; - return TOKEN_TRUE; - } - } - // null - if (remainingLength >= 4) - { - if (json[index] == 'n' && json[index + 1] == 'u' && json[index + 2] == 'l' && json[index + 3] == 'l') - { - index += 4; - return TOKEN_NULL; - } - } - return TOKEN_NONE; - } - - static bool SerializeValue (IJsonSerializerStrategy jsonSerializerStrategy, object value, StringBuilder builder) - { - bool success = true; - string stringValue = value as string; - if (stringValue != null) - success = SerializeString (stringValue, builder); - else - { - IDictionary dict = value as IDictionary; - if (dict != null) - { - success = SerializeObject (jsonSerializerStrategy, dict.Keys, dict.Values, builder); - } - else - { - IDictionary stringDictionary = value as IDictionary; - if (stringDictionary != null) - { - success = SerializeObject (jsonSerializerStrategy, stringDictionary.Keys, stringDictionary.Values, builder); - } - else - { - IEnumerable enumerableValue = value as IEnumerable; - if (enumerableValue != null) - success = SerializeArray (jsonSerializerStrategy, enumerableValue, builder); - else if (IsNumeric (value)) - success = SerializeNumber (value, builder); - else if (value is bool) - builder.Append ((bool)value ? "true" : "false"); - else if (value == null) - builder.Append ("null"); - else - { - object serializedObject; - success = jsonSerializerStrategy.TrySerializeNonPrimitiveObject (value, out serializedObject); - if (success) - SerializeValue (jsonSerializerStrategy, serializedObject, builder); - } - } - } - } - return success; - } - - static bool SerializeObject (IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable keys, IEnumerable values, StringBuilder builder) - { - builder.Append ("{"); - IEnumerator ke = keys.GetEnumerator (); - IEnumerator ve = values.GetEnumerator (); - bool first = true; - while (ke.MoveNext () && ve.MoveNext ()) - { - object key = ke.Current; - object value = ve.Current; - if (!first) - builder.Append (","); - string stringKey = key as string; - if (stringKey != null) - SerializeString (stringKey, builder); - else if (!SerializeValue (jsonSerializerStrategy, value, builder)) return false; - builder.Append (":"); - if (!SerializeValue (jsonSerializerStrategy, value, builder)) - return false; - first = false; - } - builder.Append ("}"); - return true; - } - - static bool SerializeArray (IJsonSerializerStrategy jsonSerializerStrategy, IEnumerable anArray, StringBuilder builder) - { - builder.Append ("["); - bool first = true; - foreach (object value in anArray) - { - if (!first) - builder.Append (","); - if (!SerializeValue (jsonSerializerStrategy, value, builder)) - return false; - first = false; - } - builder.Append ("]"); - return true; - } - - static bool SerializeString (string aString, StringBuilder builder) - { - builder.Append ("\""); - char[] charArray = aString.ToCharArray (); - for (int i = 0; i < charArray.Length; i++) - { - char c = charArray[i]; - if (c == '"') - builder.Append ("\\\""); - else if (c == '\\') - builder.Append ("\\\\"); - else if (c == '\b') - builder.Append ("\\b"); - else if (c == '\f') - builder.Append ("\\f"); - else if (c == '\n') - builder.Append ("\\n"); - else if (c == '\r') - builder.Append ("\\r"); - else if (c == '\t') - builder.Append ("\\t"); - else - builder.Append (c); - } - builder.Append ("\""); - return true; - } - - static bool SerializeNumber (object number, StringBuilder builder) - { - if (number is long) - builder.Append (((long)number).ToString (CultureInfo.InvariantCulture)); - else if (number is ulong) - builder.Append (((ulong)number).ToString (CultureInfo.InvariantCulture)); - else if (number is int) - builder.Append (((int)number).ToString (CultureInfo.InvariantCulture)); - else if (number is uint) - builder.Append (((uint)number).ToString (CultureInfo.InvariantCulture)); - else if (number is decimal) - builder.Append (((decimal)number).ToString (CultureInfo.InvariantCulture)); - else if (number is float) - builder.Append (((float)number).ToString (CultureInfo.InvariantCulture)); - else - builder.Append (Convert.ToDouble (number, CultureInfo.InvariantCulture).ToString ("r", CultureInfo.InvariantCulture)); - return true; - } - - /// - /// Determines if a given object is numeric in any way - /// (can be integer, double, null, etc). - /// - static bool IsNumeric (object value) - { - if (value is sbyte) return true; - if (value is byte) return true; - if (value is short) return true; - if (value is ushort) return true; - if (value is int) return true; - if (value is uint) return true; - if (value is long) return true; - if (value is ulong) return true; - if (value is float) return true; - if (value is double) return true; - if (value is decimal) return true; - return false; - } - - private static IJsonSerializerStrategy _currentJsonSerializerStrategy; - public static IJsonSerializerStrategy CurrentJsonSerializerStrategy - { - get - { - return _currentJsonSerializerStrategy ?? - (_currentJsonSerializerStrategy = - PocoJsonSerializerStrategy - ); - } - set - { - _currentJsonSerializerStrategy = value; - } - } - - private static PocoJsonSerializerStrategy _pocoJsonSerializerStrategy; - [EditorBrowsable (EditorBrowsableState.Advanced)] - public static PocoJsonSerializerStrategy PocoJsonSerializerStrategy - { - get - { - return _pocoJsonSerializerStrategy ?? (_pocoJsonSerializerStrategy = new PocoJsonSerializerStrategy ()); - } - } - -} - -[GeneratedCode ("simple-json", "1.0.0")] -internal -interface IJsonSerializerStrategy -{ - [SuppressMessage ("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification="Need to support .NET 2")] - bool TrySerializeNonPrimitiveObject (object input, out object output); - object DeserializeObject (object value, Type type); -} - -[GeneratedCode ("simple-json", "1.0.0")] -internal -class PocoJsonSerializerStrategy : IJsonSerializerStrategy -{ - internal IDictionary ConstructorCache; - internal IDictionary> GetCache; - internal IDictionary>> SetCache; - - internal static readonly Type[] EmptyTypes = new Type[0]; - internal static readonly Type[] ArrayConstructorParameterTypes = new Type[] { typeof (int) }; - - private static readonly string[] Iso8601Format = new string[] - { - @"yyyy-MM-dd\THH:mm:ss.FFFFFFF\Z", - @"yyyy-MM-dd\THH:mm:ss\Z", - @"yyyy-MM-dd\THH:mm:ssK" - }; - - public PocoJsonSerializerStrategy () - { - ConstructorCache = new ReflectionUtils.ThreadSafeDictionary (ContructorDelegateFactory); - GetCache = new ReflectionUtils.ThreadSafeDictionary> (GetterValueFactory); - SetCache = new ReflectionUtils.ThreadSafeDictionary>> (SetterValueFactory); - } - - protected virtual string MapClrMemberNameToJsonFieldName (string clrPropertyName) - { - return clrPropertyName; - } - - internal virtual ReflectionUtils.ConstructorDelegate ContructorDelegateFactory (Type key) - { - return ReflectionUtils.GetContructor (key, key.IsArray ? ArrayConstructorParameterTypes : EmptyTypes); - } - - internal virtual IDictionary GetterValueFactory (Type type) - { - IDictionary result = new Dictionary (); - foreach (PropertyInfo propertyInfo in ReflectionUtils.GetProperties (type)) - { - if (propertyInfo.CanRead) - { - MethodInfo getMethod = ReflectionUtils.GetGetterMethodInfo (propertyInfo); - if (getMethod.IsStatic || !getMethod.IsPublic) - continue; - result[MapClrMemberNameToJsonFieldName (propertyInfo.Name)] = ReflectionUtils.GetGetMethod (propertyInfo); - } - } - foreach (FieldInfo fieldInfo in ReflectionUtils.GetFields (type)) - { - if (fieldInfo.IsStatic || !fieldInfo.IsPublic) - continue; - result[MapClrMemberNameToJsonFieldName (fieldInfo.Name)] = ReflectionUtils.GetGetMethod (fieldInfo); - } - return result; - } - - internal virtual IDictionary> SetterValueFactory (Type type) - { - IDictionary> result = new Dictionary> (); - foreach (PropertyInfo propertyInfo in ReflectionUtils.GetProperties (type)) - { - if (propertyInfo.CanWrite) - { - MethodInfo setMethod = ReflectionUtils.GetSetterMethodInfo (propertyInfo); - if (setMethod.IsStatic || !setMethod.IsPublic) - continue; - result[MapClrMemberNameToJsonFieldName (propertyInfo.Name)] = new KeyValuePair (propertyInfo.PropertyType, ReflectionUtils.GetSetMethod (propertyInfo)); - } - } - foreach (FieldInfo fieldInfo in ReflectionUtils.GetFields (type)) - { - if (fieldInfo.IsInitOnly || fieldInfo.IsStatic || !fieldInfo.IsPublic) - continue; - result[MapClrMemberNameToJsonFieldName (fieldInfo.Name)] = new KeyValuePair (fieldInfo.FieldType, ReflectionUtils.GetSetMethod (fieldInfo)); - } - return result; - } - - public virtual bool TrySerializeNonPrimitiveObject (object input, out object output) - { - return TrySerializeKnownTypes (input, out output) || TrySerializeUnknownTypes (input, out output); - } - - [SuppressMessage ("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] - public virtual object DeserializeObject (object value, Type type) - { - if (type == null) throw new ArgumentNullException ("type"); - string str = value as string; - - if (type == typeof (Guid) && string.IsNullOrEmpty (str)) - return default (Guid); - - if (value == null) - return null; - - object obj = null; - - if (str != null) - { - if (str.Length != 0) // We know it can't be null now. - { - if (type == typeof (DateTime) || (ReflectionUtils.IsNullableType (type) && Nullable.GetUnderlyingType (type) == typeof (DateTime))) - return DateTime.ParseExact (str, Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); - if (type == typeof (DateTimeOffset) || (ReflectionUtils.IsNullableType (type) && Nullable.GetUnderlyingType (type) == typeof (DateTimeOffset))) - return DateTimeOffset.ParseExact (str, Iso8601Format, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); - if (type == typeof (Guid) || (ReflectionUtils.IsNullableType (type) && Nullable.GetUnderlyingType (type) == typeof (Guid))) - return new Guid (str); - return str; - } - else - { - if (type == typeof (Guid)) - obj = default (Guid); - else if (ReflectionUtils.IsNullableType (type) && Nullable.GetUnderlyingType (type) == typeof (Guid)) - obj = null; - else - obj = str; - } - // Empty string case - if (!ReflectionUtils.IsNullableType (type) && Nullable.GetUnderlyingType (type) == typeof (Guid)) - return str; - } - else if (value is bool) - return value; - - bool valueIsLong = value is long; - bool valueIsDouble = value is double; - if ((valueIsLong && type == typeof (long)) || (valueIsDouble && type == typeof (double))) - return value; - if ((valueIsDouble && type != typeof (double)) || (valueIsLong && type != typeof (long))) - { - obj = - typeof (IConvertible).IsAssignableFrom (type) - ? Convert.ChangeType (value, type, CultureInfo.InvariantCulture) : value; - } - else - { - IDictionary objects = value as IDictionary; - if (objects != null) - { - IDictionary jsonObject = objects; - - if (ReflectionUtils.IsTypeDictionary (type)) - { - // if dictionary then - Type[] types = ReflectionUtils.GetGenericTypeArguments (type); - Type keyType = types[0]; - Type valueType = types[1]; - - Type genericType = typeof (Dictionary<,>).MakeGenericType (keyType, valueType); - - IDictionary dict = (IDictionary)ConstructorCache[genericType] (null); - - foreach (KeyValuePair kvp in jsonObject) - dict.Add (kvp.Key, DeserializeObject (kvp.Value, valueType)); - - obj = dict; - } - else - { - if (type == typeof (object)) - obj = value; - else - { - obj = ConstructorCache[type] (null); - foreach (KeyValuePair> setter in SetCache[type]) - { - object jsonValue; - if (jsonObject.TryGetValue (setter.Key, out jsonValue)) - { - jsonValue = DeserializeObject (jsonValue, setter.Value.Key); - setter.Value.Value (obj, jsonValue); - } - } - } - } - } - else - { - IList valueAsList = value as IList; - if (valueAsList != null) - { - IList jsonObject = valueAsList; - IList list = null; - - if (type.IsArray) - { - list = (IList)ConstructorCache[type] (jsonObject.Count); - int i = 0; - foreach (object o in jsonObject) - list[i++] = DeserializeObject (o, type.GetElementType ()); - } - else if (ReflectionUtils.IsTypeGenericeCollectionInterface (type) || ReflectionUtils.IsAssignableFrom (typeof (IList), type)) - { - Type innerType = ReflectionUtils.GetGenericTypeArguments (type)[0]; - Type genericType = typeof (List<>).MakeGenericType (innerType); - list = (IList)ConstructorCache[genericType] (jsonObject.Count); - foreach (object o in jsonObject) - list.Add (DeserializeObject (o, innerType)); - } - obj = list; - } - } - return obj; - } - if (ReflectionUtils.IsNullableType (type)) - return ReflectionUtils.ToNullableType (obj, type); - return obj; - } - - protected virtual object SerializeEnum (Enum p) - { - return Convert.ToDouble (p, CultureInfo.InvariantCulture); - } - - [SuppressMessage ("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification="Need to support .NET 2")] - protected virtual bool TrySerializeKnownTypes (object input, out object output) - { - bool returnValue = true; - if (input is DateTime) - output = ((DateTime)input).ToUniversalTime ().ToString (Iso8601Format[0], CultureInfo.InvariantCulture); - else if (input is DateTimeOffset) - output = ((DateTimeOffset)input).ToUniversalTime ().ToString (Iso8601Format[0], CultureInfo.InvariantCulture); - else if (input is Guid) - output = ((Guid)input).ToString ("D"); - else if (input is Uri) - output = input.ToString (); - else - { - Enum inputEnum = input as Enum; - if (inputEnum != null) - output = SerializeEnum (inputEnum); - else - { - returnValue = false; - output = null; - } - } - return returnValue; - } - [SuppressMessage ("Microsoft.Design", "CA1007:UseGenericsWhereAppropriate", Justification="Need to support .NET 2")] - protected virtual bool TrySerializeUnknownTypes (object input, out object output) - { - if (input == null) throw new ArgumentNullException ("input"); - output = null; - Type type = input.GetType (); - if (type.FullName == null) - return false; - IDictionary obj = new JsonObject (); - IDictionary getters = GetCache[type]; - foreach (KeyValuePair getter in getters) - { - if (getter.Value != null) - obj.Add (MapClrMemberNameToJsonFieldName (getter.Key), getter.Value (input)); - } - output = obj; - return true; - } -} - - -namespace Reflection -{ -// This class is meant to be copied into other libraries. So we want to exclude it from Code Analysis rules -// that might be in place in the target project. -[GeneratedCode ("reflection-utils", "1.0.0")] -internal -class ReflectionUtils -{ - private static readonly object[] EmptyObjects = new object[] { }; - - public delegate object GetDelegate (object source); - public delegate void SetDelegate (object source, object value); - public delegate object ConstructorDelegate (params object[] args); - - public delegate TValue ThreadSafeDictionaryValueFactory (TKey key); - - public static Attribute GetAttribute (MemberInfo info, Type type) - { - if (info == null || type == null || !Attribute.IsDefined (info, type)) - return null; - return Attribute.GetCustomAttribute (info, type); - } - - public static Attribute GetAttribute (Type objectType, Type attributeType) - { - - if (objectType == null || attributeType == null || !Attribute.IsDefined (objectType, attributeType)) - return null; - return Attribute.GetCustomAttribute (objectType, attributeType); - } - - public static Type[] GetGenericTypeArguments (Type type) - { - return type.GetGenericArguments (); - } - - public static bool IsTypeGenericeCollectionInterface (Type type) - { - if (!type.IsGenericType) - return false; - - Type genericDefinition = type.GetGenericTypeDefinition (); - - return (genericDefinition == typeof (IList<>) || genericDefinition == typeof (ICollection<>) || genericDefinition == typeof (IEnumerable<>)); - } - - public static bool IsAssignableFrom (Type type1, Type type2) - { - return type1.IsAssignableFrom (type2); - } - - public static bool IsTypeDictionary (Type type) - { - if (typeof (System.Collections.IDictionary).IsAssignableFrom (type)) - return true; - - if (!type.IsGenericType) - return false; - Type genericDefinition = type.GetGenericTypeDefinition (); - return genericDefinition == typeof (IDictionary<,>); - } - - public static bool IsNullableType (Type type) - { - return - type.IsGenericType - && type.GetGenericTypeDefinition () == typeof (Nullable<>); - } - - public static object ToNullableType (object obj, Type nullableType) - { - return obj == null ? null : Convert.ChangeType (obj, Nullable.GetUnderlyingType (nullableType), CultureInfo.InvariantCulture); - } - - public static bool IsValueType (Type type) - { - return type.IsValueType; - } - - public static IEnumerable GetConstructors (Type type) - { - return type.GetConstructors (); - } - - public static ConstructorInfo GetConstructorInfo (Type type, params Type[] argsType) - { - IEnumerable constructorInfos = GetConstructors (type); - int i; - bool matches; - foreach (ConstructorInfo constructorInfo in constructorInfos) - { - ParameterInfo[] parameters = constructorInfo.GetParameters (); - if (argsType.Length != parameters.Length) - continue; - - i = 0; - matches = true; - foreach (ParameterInfo parameterInfo in constructorInfo.GetParameters ()) - { - if (parameterInfo.ParameterType != argsType[i]) - { - matches = false; - break; - } - } - - if (matches) - return constructorInfo; - } - - return null; - } - - public static IEnumerable GetProperties (Type type) - { - return type.GetProperties (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - } - - public static IEnumerable GetFields (Type type) - { - return type.GetFields (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - } - - public static MethodInfo GetGetterMethodInfo (PropertyInfo propertyInfo) - { - return propertyInfo.GetGetMethod (true); - } - - public static MethodInfo GetSetterMethodInfo (PropertyInfo propertyInfo) - { - return propertyInfo.GetSetMethod (true); - } - - public static ConstructorDelegate GetContructor (ConstructorInfo constructorInfo) - { - return GetConstructorByReflection (constructorInfo); - } - - public static ConstructorDelegate GetContructor (Type type, params Type[] argsType) - { - return GetConstructorByReflection (type, argsType); - } - - public static ConstructorDelegate GetConstructorByReflection (ConstructorInfo constructorInfo) - { - return delegate (object[] args) - { - return constructorInfo.Invoke (args); - }; - } - - public static ConstructorDelegate GetConstructorByReflection (Type type, params Type[] argsType) - { - ConstructorInfo constructorInfo = GetConstructorInfo (type, argsType); - return constructorInfo == null ? null : GetConstructorByReflection (constructorInfo); - } - - - public static GetDelegate GetGetMethod (PropertyInfo propertyInfo) - { - return GetGetMethodByReflection (propertyInfo); - } - - public static GetDelegate GetGetMethod (FieldInfo fieldInfo) - { - return GetGetMethodByReflection (fieldInfo); - } - - public static GetDelegate GetGetMethodByReflection (PropertyInfo propertyInfo) - { - MethodInfo methodInfo = GetGetterMethodInfo (propertyInfo); - return delegate (object source) - { - return methodInfo.Invoke (source, EmptyObjects); - }; - } - - public static GetDelegate GetGetMethodByReflection (FieldInfo fieldInfo) - { - return delegate (object source) - { - return fieldInfo.GetValue (source); - }; - } - - - public static SetDelegate GetSetMethod (PropertyInfo propertyInfo) - { - return GetSetMethodByReflection (propertyInfo); - } - - public static SetDelegate GetSetMethod (FieldInfo fieldInfo) - { - return GetSetMethodByReflection (fieldInfo); - } - - public static SetDelegate GetSetMethodByReflection (PropertyInfo propertyInfo) - { - MethodInfo methodInfo = GetSetterMethodInfo (propertyInfo); - return delegate (object source, object value) - { - methodInfo.Invoke (source, new object[] - { - value - }); - }; - } - - public static SetDelegate GetSetMethodByReflection (FieldInfo fieldInfo) - { - return delegate (object source, object value) - { - fieldInfo.SetValue (source, value); - }; - } - - - public sealed class ThreadSafeDictionary : IDictionary - { - private readonly object _lock = new object (); - private readonly ThreadSafeDictionaryValueFactory _valueFactory; - private Dictionary _dictionary; - - public ThreadSafeDictionary (ThreadSafeDictionaryValueFactory valueFactory) - { - _valueFactory = valueFactory; - } - - private TValue Get (TKey key) - { - if (_dictionary == null) - return AddValue (key); - TValue value; - if (!_dictionary.TryGetValue (key, out value)) - return AddValue (key); - return value; - } - - private TValue AddValue (TKey key) - { - TValue value = _valueFactory (key); - lock (_lock) - { - if (_dictionary == null) - { - _dictionary = new Dictionary (); - _dictionary[key] = value; - } - else - { - TValue val; - if (_dictionary.TryGetValue (key, out val)) - return val; - Dictionary dict = new Dictionary (_dictionary); - dict[key] = value; - _dictionary = dict; - } - } - return value; - } - - public void Add (TKey key, TValue value) - { - throw new NotImplementedException (); - } - - public bool ContainsKey (TKey key) - { - return _dictionary.ContainsKey (key); - } - - public ICollection Keys - { - get - { - return _dictionary.Keys; - } - } - - public bool Remove (TKey key) - { - throw new NotImplementedException (); - } - - public bool TryGetValue (TKey key, out TValue value) - { - value = this[key]; - return true; - } - - public ICollection Values - { - get - { - return _dictionary.Values; - } - } - - public TValue this[TKey key] - { - get - { - return Get (key); - } - set - { - throw new NotImplementedException (); - } - } - - public void Add (KeyValuePair item) - { - throw new NotImplementedException (); - } - - public void Clear () - { - throw new NotImplementedException (); - } - - public bool Contains (KeyValuePair item) - { - throw new NotImplementedException (); - } - - public void CopyTo (KeyValuePair[] array, int arrayIndex) - { - throw new NotImplementedException (); - } - - public int Count - { - get - { - return _dictionary.Count; - } - } - - public bool IsReadOnly - { - get - { - throw new NotImplementedException (); - } - } - - public bool Remove (KeyValuePair item) - { - throw new NotImplementedException (); - } - - public IEnumerator> GetEnumerator () - { - return _dictionary.GetEnumerator (); - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () - { - return _dictionary.GetEnumerator (); - } - } - -} -} -} -// ReSharper restore LoopCanBeConvertedToQuery -// ReSharper restore RedundantExplicitArrayCreation -// ReSharper restore SuggestUseVarKeywordEvident diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Compiler.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Compiler.dll deleted file mode 100644 index a7752ccdc678887d2230b671a529cd69505ec432..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 934912 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 _gx4S1KK+x}d_V3sCR-HO^>eQ)Ir?zwN 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

O>|(KZ(qMei6xmejUk$ej8Z~{V}ov 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

tMeSOt$N{KGlLv=w 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'T~D7_=F(Y`h)&oAouojTJ{bwbtYK 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­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 CW1koR diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.dll deleted file mode 100644 index b66b75a25ff6ddc9011fc25858023de075808b70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 126976 zcmcG13w#yD+5YVAIeRX-kVC>rAV3lXT!UZ$#U$LK0s?}fcnJs!2ns5!CZLkT35gb~AnU2IVNFBDlW%QmOlK=dVHNzb0)6F0A-zp}IHmOx69?v}dYLUA&~Z z@}egHyr%g}E61g?rWMO7mn^HCaMH}mrT)T2!wL$L0}bmL6P21~IjY>d zZFZ2`9#vSCXSqtfZ7GGD{3=1^vf*gZZa677f5BbNgD0cl$8srEB>y|^21=MxWtB>u zM0cgF`sSFJK;9Z`l^=rtsk5k3sdy;zLg2|EJZ$-*%a#LIzJ)R(Ov-BH4x+((-ms?T zrgPvSvOz}C$2&+9`ZYkxVNHuJ^bt{Hh0Kb){&GOPV?)Wr`Q@OZN~F*I8Y;DOwz(6X z2sg{q{qOAK{H6&PUO0XJl4WXX^ErOgqD8|NUU;DjIO%fRDyq~DrM8`6sX(gFzo+YM zn`5iC?wS9e`u4XyWSy)ou1ToF!5JWBdr(wzR~{7Rp}izMw1MPu!ekS|FLM2{(76ZU zlhr}`{&ogIk?H|2*``o9}VEFK)bT?BXTQ<*Y$v3q7FGIJD%`R z|8BJt@xe1$*TJ~7x>wBc!7@3!+Kq^#S{2unD0VssmU4V>O(r99%c~s<@0bs!Nh6Q# z`bnUeP#^kn^W*if<~lZF+x1e2UCS~!%rIGfY%5iW!XZ4F-fvOI#2y3N=d%%g84ChrJfWr zm-a&KGXa0OGBs78l{ACDv=11YWOW}(o~%|QY_BIA22s{t>U^X{ky6dY2ua#n-7%3M z-zaVbqZmb(AlBeoX6iaVZpp!&LQECyVNp`lAzEd?4~17AcGXzh$Cf3(@8a7X)8DB+Syr_inva8Hg9%zo<{R|8&t7Bdlnqk zBkbnifT3TeML^lp>NezuR+h5ssnMp9R9tU_w>aA4gq(-%_P!CD(1Y}-! zCK9re*;or|4*@cj9QURn+%EC^A*49srXn%FKb)xaJX7J%b*b=ZD#{9vYHihmrE=V~ zkNQly)j{1)hHovdHe5m7m!seO2pHYtpk>t!*R{BUvTb+LW6+3I)1@dt z)Aw15D&*E;m##+xu?D4`tsaD9_mH-6H17NzSf^56=ei~J!tNomOIbN~jyC{otJSck zDte+OlP&*=8~v_7DjN2qLY;$rlWdm*aZkGbAlw{(FsOEy`iJJ+Y2VAaOZ~$_Zj>Y! ze@M=4`-h8rDCl66wzwv)P;;~eDckXo6?%d{452>yOES;(YjBG}E=Qr=aU4!HuQ&bW z9NkeC2R-Cm_7J7cx6@;!C)`983`hEwwCzDQ$xrt?^wU)H4TjGWGH|lzYj(ay7xBh^ zw-gS^zaII+h^3mhNV-V&Vx0g38k0Bk7Rg?wJy&Ya7T(C^5;!2+B-?{lUEPUck!VMX zYoZE;RXwPK>z1rX`?p|nYk^^~?AT@x`f#_i%f%2r{v9+;w;6gd<)L2C7*fr*oAO{7 zr2)Aj$h%$V4ZF!YmQIdrbGEi#kKY(+VeKI#B?9&B>y{i9Ii&Pm>666EQM4on)Dw~jQ>haN7|)t!^R zilmqk1oFc4rvgdVW7roZ(l|qjB4BK@j9gliF2wyKHCdgstEr1otc~KDh=O@nNQOBK zm?Z6bkmYU`28;F8p)c)$d5btG2ii6Je5$z)ag%5cXf#PQj?v`gW_WY=yJK)` z#=OS$Fbg6}*zt%$&(-+~yCmv^Y$JXvBJS2!PJCWRg22|GJ<2!=d!L&Zx9YMO>p#>+ zCy?O)3}Ln+m~Um|-lr8zQQzh0TQrO)cS^jHb{j(+oipNMc0mth9OTRC11lEBOECg} z=i1HVA#fJ;70ETJq-3EM*n=|YlM%;jK$PW(Ql2Gd**n6HIUuaOrcC`DagYz{mYjEi zW4X*JdnzBpZn91Uyq(_FI*NZBy!{Cv`L(E3)zkJS0_4Rw5h|~PQAFeF%q!+kLX4Pj zDUR%(rc)gczxtn}k?e-uQSo)4<$74NGhh{gsZc`-66=I5n~mKeo%Z!0g`22Ov7mwO z*teKL8!qzYk9H7J%MUZLDa;ssK{bs>^+9V>;n92oNQ;&naVW4YO4SoPaYlS_MvLlb zqsRf7vt6S#sWQ*PoZWKvpb-c7OKORFD*^Sbd+%A4o?dIuV zo&_-V%Xv+P&_7XfRR`emnqsvKxu5}}{&G?CYSBM16Fv#alDlBMf*SQ^z{fusq>fFi zr}9pr$1-$*+Zio?H+zYhpFPN$p{0*u!lBL4>m?GcIv&zDbqx7rPR`i;ouY+tBF!_& z|5T8{NTP;$r@_g^%aH03-Z)gAtY3yOY=G@FHzJhoap+8#G$pYvnL{t?7ZswQ(NyzX z_^{KTg*$8`BV^B}yQj6k7m8IL%gzI|GvoksFdsK<4$yyGH^V?=(ou&fxzwSnI0luA zF6qZQ`qs|Ex6kDE`ax- zWR{^AX4HTl%3G|(%8eU+JeO($znDV*;y9iXm0@{BJvU`&dX^$pi_4|aki6JB*qQQr z$f25kg1}vbdVL7tlR9n;+2!)+Z~H#8JzZ9fyQ(_HN5nu!>1>lohxXVE$2ttMEGqa2 zu4WnfG^6JwTVzei*r+?kl{IB?jm^HHb>av!G5qA?nrKsvQER;fsj`=XRHGeumywm@ zt;B6`^$&F%%=SbB*nu%K5ZhUQD0oRStZy@tTB(1U_*!9AjIM2UM8;UBmTVk<6{0Wq za_KSsGaN>wg>Bn%!*4Joxn3k;+5NB4yV`al-g@nMiftptS^)1Vl8uajEYP;S4aPm& zc5bJv{&nyeZ2Mout#lU43O;K946}Nq5x9==s?{ii{jUInX%1hT!~PX;t|N1VBfaM5 zUnvnN`!#T}BPOxHJ>AYw$!RBIXQ(glY7m66{hkh)(P&eFqK9@UTH-phMK7F2p^d@Z z3nxwl$Z2+np-iis@tjN8ZmGXo=P>}5VUu=#<_}9Xt9&-R?cn-##iS>0eIUs}bnxu?h zm8=u9*#Y|kOPxdvX-=5`=oV$HHz$6(doqq*rpIB#%@Vs~o)JU%VYnze!|)uOs8Z|2{7}w82q2wjq+ZFALERNe@3%ya8 z-k8lgv%+Bu82>AXBkLPi)?Z--eTNzz>F*^E+(*?O>~`&igi; zY&ZFA+w$uY&5r1Cf@w@_*z8^~0JQJ>E!im~_U`Dw>@OH)6=gLcNw?Q%ngUpHnmDb4 zc8XnE9m$nIJkr(WH9gcRhz!N2?9ScG{|-{;*OntR?%xS_o)h!Gi@WTIVE;~rtGM2U zq&b(VVaTem!31+~tkJ}#OvIhNnm@|UIk>LhE`1$}XGb#KNEbrq&U$u(m8sMlJ5n#| zHmb%Len^fI2lW=xXgb7wF~f03+SMV(eSGK27E_b1>tERzx25-#C-tK24FDi})yP zDmQ?!1;IR`eTjfwnpK{gA8OO_o{nzQ32D=^4$;ZROPh9OP?9+!=bh7xUW{4E9(eiqwWsjiRfmPlom&BoF}Tw?GgucVp|&gev`ptfe| zv03tPxI@AI2~a#oBHAUf%630_FECfObhUUVI>eYJA<`~ zlf7R!)Y}<4u#|s5@Cds#0yF9TR1h*mUpf~&G5^3`6ymt1mEV_Z<&OU|M9!7gooid6$+4W$!G{{Ekg|Gxe)P zGA+;Yq{xF=%fpZX6Kvl8Z{)##<|AO1(--EW5$_l9fq?z(W~h<-*-=GdhCt@vd6?}q zu&wZ6U^$vG=cVA|V(jUwwjltshXdo<{x8AV5o(5Z$A1)Fd9_oKraR^PI}u#ZMw-sw zJq0&Y8$spxk0D%-{U#DEt*NH(b*`p@1ZKwxz4ug#-Hl)zL%G!1xULoUAoy{9%yA6! z4)j%9q|BFX*tpEb^ISXTKaRZTC(UU2R*+d-rsCnuFlYvO(J0WS9)SyXOMcil{S`RL zoa_lY;LG{huZ>&kVIdkPo~f<4{P-C_vVT4>%8*b(np;5rTnO~1(XDeUY> zFxOd9L*aVw(+*U6|5aVsRT>L}+>!L9oMchkgGlzCM~rvU-&5 zy@L##puU@S4F+RjVf(*Dj1vDj(B)*o{Mj!53}a5Ww9EH3pp8Ji$x<#C{of%YS+Vsq2M&yp>4(XL-p-`S>06B<1GS~s z3uT;W{2e8ztUqLhs%=D52 z47T@I@V{E4RZ7)d(b^<>JlDYl@ooC5@_Y-(E zzl;bTYyx%w(F*PI{oLcm7{?r)&1|^f+!}r!D}!&xQ|BR8x*Geil*7Sd;~&iRH6u@P zO+WQ0_ztJ7@IFLP-2xWP`yV**=z1S+d1$8V(W9;WbU`gDL&X!e_ZI{tHhGj#)aoQQ z+X*R=$AP@oK|J_vPn0$mBx2)#jkX<+IWgD!CsJ&WoATC8L9}#nr1oe=Phq>8d{Ys_ zIIVp*+o?#1HS84QZr+}Xls59*1GeeLKa32_`n(R|BUqm6mSE-+amAQ%3zzI-wi9pM z91$Vo@`zn;!LzF+$MaBy%z4fJA}rD{s0}-qNAMQS*6>ys$qtu$G&=%!)(iGS8PWfZ zY4=m@jHJjgg0~-q()+it$!esuXIjHjQR|?zy}cS`Fj~f3&BkMFw-jD7J!3}#f8q3k z;g2!-3o!KpJQYp&OL#O7L_WCa|!T`I!mo)8)dvBa< zVlI+uhJ}-T^*3O}Lg*K`4PP!dA`JV;sq$wvu z&+0fF^k8~i0Wa>owtkKzUcS^xQ_k=mg+ifSjp8kuJ=&CeSaT1=YokJFbHqE)6KzkR zUnj%#KH5Oi$&iPSHkO?4NQ�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�O1Kx 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 diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Mono.Posix.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Mono.Posix.dll deleted file mode 100644 index 667d06c94e03b438bebbc1ed0afbf34f23fb41e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184320 zcmce<37i~fasS=hJ<~JOdsw4g&8$|Ic5S0|du$6~Y_q$vrS*v|8)NxGGGNQXmloS2 zW@Ip0?XrM5Y-EFha0nZSg1K)9kPs3=2v>j@LVzSzFbPSVKnTenk`TatzrT9AXL?4f zBZSYp(sVyvPd)Wi)l*MBXFvV4t6$>gBls_KqeTM!SOfJhvE|j3zNCuR;6{7hh1kAIz;nn3}iBpS1w=6A01O8hMnw zb4Uoua!|)IqTwyoE%%VPC#v*Lh-O#_mKQeHOT^t@sBZ2pg!gXW@K29F{&*Y#3hQJU z^%ccWD0+R~B_u+Ivcy&>K`E}@q%Spev*$<$%FkGn*5UBJ`EG1E)IJ~*KIV|31 zz+!cCUr~Ae19=rtNGiiA3C*KO>GYKIjv+Z3DhId2haZJgFyK{cp-JuVO-sU0^}S+k zuXiWUq$vAKy%+CPj&{{Usq_j?8XzE_O` zKi&et@8xsuK9HNFbi9H5Kmw>l`&R-8Co5cor&*SHcN<9V52Kuvhas?HerNDgI{mG{ z9@lZl+R84wD2!n+#3ZD$Xi~Mj5I+q@`bu<%{ zqIVs4o|7^eYL!PWUIv-|QrIpIe=xWI$)J}CZCC(oR4`+N2kCP^_ST{Fhs)H8w!9Rz z)q_pkg{r^QP6pTJJq$p8v+U>cLHr+q7b5zN$SE49_(5f+G7}GzgPv8Vp2(dVQ}$hr zoov-uzmCSD-laV;Dvl1ImeLw&(JFYyr+GVCRM({T`}GgO!a-?ZPAz`cLqmVg)dY1k z8CBP*dN&YxN8>&bMd@-GV`^~6%4A!|SfU4?OR~AM&5a=IZiQw)9LTFkcK7^|uIG;? z&*OejjgNDT$e*d6>d&vvZG?_Lk2JZtixiBjWabCCm`Z4T*LbMLtLyfuD=l zwB#+AT^%}~##<0MK8ZBdB*#JOm~?&Ubh)lHMGt-tlLnzMh_EB2vy)SgB<e5_fdD8<__?ItE1?UFI9SQ~l!$&bdSY&H|P z3XdIojk_SJRx@mTM8p#_c2<>hb~Y;$tISm6%gJ#j3YX2S15IZ5RLMrRk?OE-c=7ol zjVIx&2~Q=s7c7E%(Lr!81UDhESt$Eaf;YY>uM&)!iT|+nOg>nDa%`{U_i27gj34V! z9ilYs&-Z7=kTv{4bscWm3zk3Db7D{R#GcBWqQDRv4r90*Ls70QbLQW0)#V^Q#>ctQ z3&AUg<5mw>1@Rcb+ThxpM}3ihEMw8fW)ORWk!k#zm#a?8;TNXFOyi4`M�+#WOyZ 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 Yu_y!WyJ$}#4g5pTBcGd`tB@@m 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 diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/System.Xml.Linq.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/System.Xml.Linq.dll deleted file mode 100644 index a90ba6fad4f65432521853030593889b90499963..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106496 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 diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/System.Xml.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/System.Xml.dll deleted file mode 100644 index ba5a20c10ebcaad13008353e87e8029029b060a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1270272 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

B zPLg+^g0?qQnlsp>g<80e;GuHg`?dzk441QZb& zM4bjv76Ap3#HtxqrmO++LIf0XcaaqjRyC*>5ieduyvQV<8C$&Yva3x%Hkx3^30O{IE-%a)5TYm$ zcv)-d?3=;Vt`OUas&$laB6rw~{ti^Joyi;!Jl&zTBI z3QH$C+>=r=^l<90MJ^Cixu2xkKQb^f7?yTlw0mLqV*M@f!W}>VOeGMy9WysLRBZn6 z6zAcfKK9R^Txvk*8vvpHW~7#sUp84tMxuLRzl*R{I~-QgNou#SrC@ClVe2}K zR#R(8VQJ*dcME-!gRq%6SxODak~Cb`a>{e4IPj=3yEVm3mCs_I>2U2(!R`nk93 zX8t9uRUd@y7yRGVtF4wNc<{d1Jm>;@cG*PZXy0Bb# ztXR43_@0yoSi$=o2eQ!3I}F1MXQ>wotrIfkTle(Dln=|K|G`B=C5my7CP^ze_BJ`{ zW%z3R9RUgIQm1g3`;c!|m1WNBlc`s^Vzj#bdOL|dy9d&jTOesXuLsOhSq7!qYe*kY zYpn>`Vp}uI(^bq_vy}NlT~O%Miwl%+uy4VF9nOMrD7L(O!S?*HFPLT0H>>(u2%jvf z-C|MS4sLNh@T)U0&B^Bjq$(h{a}gB@UK^G%FztO1d1Gqt_LuR>^4R0n&mvNJ>{PXZ z2IuZ!^USsfR(~t9Ys}EsVb^@)LuufR43tFFe0S#iHu_q}_%Zr!!}m7K%~l5=1RVBT zwo2DMV7lF6TJ>!_ml@g`Y-w!&S&2KwaQn|5z_79Xoo+{sXQOMeFUo`m=zuRH9{VA- zQ$`p{ImMU>j8+BX@zUAL$rP*A>1K~~00*GqbrZo7v{TzJ%0b`jwiiF_3yOB4-J&W; z6$*pK$B2Sk*QLs&zZ#dJXEQ~N@IP%N6(MB~=wD~0;S^a= zp*_06V-e?(C7p7wQn2hrU{3iV2T=kx0xg|wkUVx}zyjnMUbjBL@z>xRl5e;@&JBHM zW~7m^3+H?0^z5snWFE2Ob_J0NJvg-#!j3& z8a$@^oi^ajzd%!vhiS+6Al^V@Uw+j8m9=3Vnrl+Wzb~st7ZouPHMeR!cIxaQ@-zKc z@_0ZQgpCy<;I{|Y-;FOP2T6oWYLI@?m5CC1FI%>(!n+Tm#XAsx0-9YfHs*qD!-H2Z zJ$!s{L0NKxmo0b&smT`eC5cJwIoI|qoE2vl9D5E5ZUg%Nt$N}jnJH*mFUB-4877vR zaM(Is@)G!(N0huGbr+J$Q+F}BB6Y*O;#KK~t>7is<~%5wB`?c)aB`l!Hs?XjK=QiO zgZFB+4#u2=JJ-ql$z$+QN}&BjS#Y-Ed-VI1O2+nC3@Bi#k5S8^U1iGhv@aA{|7hzW zW|bEm?cC8^YU5PR|DKC*{`%lo89Ur~?d9ed zTnx|q8L(6)g)8V~3y5DCJI%QJ#RC3L03YmIWhOlLM^gXCE<$lC=SZe6&uPtTbF~C& znV9zMIRkGTN?^@(!6MhgHumiC21-hp59=jN*L?K;bxI{Y%Vov~SNRtiO^-ejE>%fNk@5D>Q+#UG9OuZgmcu z$Gr&+?_J2l@*B1M>P+5zm*fcMl^}=vgueS-Yfzjkv5y$!r&gvA-VBhH6(bQy++A;oI2%xruQUMY3e_`2R z3}Xv8T&*Wo3bEU#>D&BNM(z*LLuFfOyZpr$e%#7qe|Z{nm90Dbp`22w6U{Xwb!s`V_$0#sh@q=Ns+a7IK7#Vh}e%O7ZyYdbzE7e!Ol$b?Py zq}EBOzjtH8$I>yu%+30-fZabA1WaTRtJ(-&_G-ZR{eUO&r(CkzI8C!qF3sL90hE(_ zRLAhTTEI0Y$!NM>dOjAXq_9j9%W~EPcxO593DD*Gi#RnC4>sQcSo2wV9**2c6l(Mm zj)j1F53Di`h3SSXjwfRQ*5HFXHJ(uP;jt8nKyG)d+fb=WAE;>0)pTwZ>iiF6t56kN z@EWgG+!|PZ>8m1%t~R(7iqU;oU*=I6o3`CTI%g=|3=K-5GYlY<(-xDH@CNFdozjT5 z?b9rCd!tq-Y&tYl>`O+lN&zvVP~Aw`9cQw+c;SPg6kzx!H)Lksn`@gfh|gh$r*N$= z+x0t}3PYt$SWO^7hODj!xR*aaMwO!VPholLvuLQzyFd@WWEQ1Mfsv!ksJptWd1C<6 zU6j&FKF%_;(3@W_RJ{#oUkJxU3>}9lBeE{;rQw>``Ze;IW!A4>wCIAGTZN4BaCCIc zX6Cx+Rd5G&7hi6yEsgDQIEUYojP6Vo;cR>l)Q(E)HLtMp-HJ?>`Aqyu=Z;G?I=@ub zO}zq;9UkW)r*Dz}#A8^tSR?tegie>89v99rf{GqL&xC{puvzgRzC-`jChMG3rZqvUlt80HcifvnKB?uW0 z`+dut;hTG|JeOdTSUll)*Qu?lwi#8u??OxUT6oB22XgrtR1Gw%1=FC}#h_V%QzH`4 zmw&Ktsdm@)K^LMC=iMk`*jyBP0S7x7i#ncHp6ntWRx34xkGFX~4-0F2nJKri!>>0H z#KOjhc^ZttY~Y-EWYJ#F+_0DT-__n9;S5}zdwns}`v&QiT!4>>6sd~MsWRx5+pkx% zv%D&6=I_M0etyttZWGS+lw1N`L0+7>9b3R)#tMDzaPU=lf1A9QKs8cwb7|Wsx zutrhviBa^QktR=3BR%LR4N@2V8VTb%uetF-QLV4KQH|PqE1UjkIldozI6qEWXaiSm zPW!@aM;64i*t!C0VbdL&-Fve{!pX)_;PaDG`;+&HxF1F7P-K+3qP@;5IR3PMh%k3# zolb21;c{VhW*zeg+f3@%oBm31y8gadjW_K41@3q^q9x!qIwW*L@hg%dWEgi2LwSs{LEGdK&zMe!2e+!)L^_jB3; zIv9`VVQ{e27GH6gt6#@z$~tYs`?l)@N<1Wyc$kjI@lpBQvsD^fIuE$ z+hswt+*K{guD|hYg359#UpG)uCd+2I7!|geq9RD{HkAWX@39Hn0p}tK6N_X%W9uzk zO~?wi@oM&`7L2`N1fJ~;%cIJ3{K6TzvF^t4w(*W!iK=6uqpTg^<62)yYv0DR13H6) zWGF=XadNi>}y{ zi%O6wuyYS*Lyv*dg7>eQiJ8wEOnyHAEkXS&J>OroZ)fwRHd6n(JfJ5rlPYzKAR9F@ zg7ak`UNC@n=o|eM^OcnqcytOV0MO3alCgNOFXiGDTLNPtwYif@&%`k{NSg)VY#~_CHAq^tvnSQ=(yg)WzmS?%|3mt)}468Z#A{LJ$Apv+pHdH(u znqbVsIkV^cEceZQ%AB0?=d$1k?CR;aIpndg1`uC6FH&SThl(gsvcb>+Z|n^2?{jcB z?hx)D5Mq>zk{Jir^9a{qSiXhu`C~5K#XadRa^KWF9Kk~4hlay~*4+)LM6S-faos7N zcK+Plx^uKH__(=~@p#WF@z{BJ|BR@f367vU<@F==wQxBeLYOcAQ7+!j^Ld!D9J5g; z&NjNUdcgLVH2xD5-_!Sam)}D44Ux*@^&}V1r`xoXbh?bz@ySU&=}z8BI^I?5^LuJf zx>I(Nu98c4>Q3V6u3U%LX)YdY5vk)e^&XwLmVp=FIz$S|C5pKaeRL77gZE+wkLPl! z;o{GM)}U{F#{dB58}$uJb-9bEy)G7UFvTEwmf{>{eMx$8b^84xYv9u^++SebJzo4& z<3*b0C6?wBE?-Uo!!`#Wcfxx$bJzF~B`-x>Xqj+LuEt!B1(d7#bIB#7D7iBmBPu2% z0OEKwN}h*8cujy2eBn$jBRA%pX4&|Bq>Z(FIODV2QCmxM85NTA9&Ju+(|x(~B4USy zv9lrbm7s_(OI3t%_|A3XYw|S7YT8Y!*;9MzN9MV12F zLOHyym{p5SRsn42QzJK?Rez$#+mJX^NQk}n$?y@vYH`A#k+GDZO%P2>dpXC{C<-mwqL(!EKunbowKMJMRTcC96 z@Vl{}P@*$Teu5Oq4G7X1&E|nn3Yn*YkyQ)>yT-kb|^4;Fupp2i8xV@Ii7+0Rl=Cd*Q%!P@7~ z!J)p=oLII^)@JR6pG}wc5!3D2ovyX3>GtYQw`Et;jd!Q}gt(J@_Xy>i=uY>^T}`)l zce+pQYPx!Nx=*`wsMml+<$S-2Dm0m@7W^kF;~un`qWa3rdgPL*n0;7FxfvX3_h&>2 zju*w^=H{Q_+pI?jIukX%ElS>opyn(*Y*!_>VnxZ@;i>txd9oe!ri7IEWk9I!j{+>K z)mraBlF6w4PQ2opVw`=_tsHD&e<6Sf?>3E z98>ttGP>J*y3>EM8NPzPwNA}mtN1c~)*f)OESx(RTeqVybzXEoY2RN@ziBIdE#l^F zrSqFjs@-E$KZXd{rO(%>*EgI!zpfUstw1ac{sfBz%ui!{&K9d$qGL?fZj^AgCFsq6O{;h^_(+Zi zcT@oBIV=$4z|MG*8jySmOe3kld=F zJ`!H!Bs_|;pKkR+s^yypr|ICRmGtHkWY}isHYuB_#hmVAHGHSlBS5bSnzt?*fyhGN zu+69D>}%jiZ~&UwJ_1dtj>(rt>KV38_NL(BLhxk3_zwHI94qWqKr_Zh1{!f^#JF^{ zU;XfJ;z+k{Emhk`*^>rab8*fkwvdR1x>HN+{N@U0w@Qr$G`CjJ`TbI z>vZZG!q$19_5<;azP$n&e^(Oi}-3!4%LYMw$0f@b=9uIjN>;BI_NAljBe- z+EQc_hAqWU;??*biI*IK5KYvX2gN{JKdcRe$yo@3(O{WmrK(2SQ8|EC}NsarW9dK~eHw@*rx6 z*RK=o&Z1yEfDV(Dl6=-!6z!`|Jjbjl((&=+o(rL1mrCWIJwg8@*tYzu^+^zfWj(y!7BKBT9HaHot z%Yy*a?2QOGEc7a_(2=+?VIvmpM1bK=#+)NBfJ!mQnHrglS_`{RPMb zx{p>9Z_I$wG!>0mJ4;h7wOUM6tG`OA4hvgb@<7gybc~_JQY~2&Mp5z^xGeH1Jz-XA zlLy!boK9T3lNVa|B6(bj>aLKu>*W$=%smP(K^iP}51F1aN+{M(q0hk?sVJdP7bTRD zqlAKH@?Ios9Es4#Uox8QH0DTM#oyM;qU703z}r*ocx@#4I(Z8{5DO64+fBcpdjyg< z5*@UKmBGCTB0iDL?B{TxuX!aNEjP1ww|K5^BVK8A{VVwz8?t@W|BMeiBNgeSl!oy7 z)qox8T#>$|*|Kv+IbRp+R^*hA#qUUG2s2nZrV}L`|7^pJ~_?D3#!*RM*33y%edeU2IkQv$4Y=YH~vIa;9Gw`fE0B4(u0@y?4iGzs0BB$ zU>|_9sF+2Eh+-BU9u_kQ4DSyj^3L)0@u3Te{f88JUmYw| zh~pk8ueu#U!g$XKLi2hcX2)d>Jv-G>N1E8Igjxd(o6oI-uf;G%6WfZJ(dVpS7(ML8 zYIhQs?`4rMWC5T@z^P(PQTmYMx%j^hf6|*08;7_x_)}KnZZ&odjZdTdX#5u+|A_}` zA>7UP1njd8^Y_CO(Lh?@d zN6G8p<(l5La85K1Hvn4%Akp&$cqZi0Xf$~(+*20-L}42J4q$$g9@OQSGdT}e#Z4Wq zJdzBE>cJ|Tgpf%|P0*r*d1#-H;j8wHjQ$DU)BmJCL5M}ktC`a#q~2-PlI)^f)=@(I z^T3mTAncp-uy=tnQF1;JV10)P+oSLglN-Ds3?g&-fI z8g5cGP`xz89&plzih;_}yCb8MQ5j^O8}WY|{vX2sv-r=!|66!J;M|MwO+Wq*!T$jK zABX>w@n^gS0WCB_saBJdm^&AsuoWA-0I~nn)-qiO?eyIS2PgrSij&1}&zPOmsGLBtEZ1np%f;og{qu^aiU>^TS5`WG-s7bP6@xz&i zODI-_B#A|Z#bc{iRQ>1eh=CoX{V=m7|WZxYM88x#f5rko?HoJkb7|m~qZ?3>0 z4Oo$~VVee|HppX{5kRKWZ;$~guZ|Z3OiqR)(TK*aNtAyC{6Lw(+#_mp-k&u!$ve;L zkHtL9_pAK=C3?a9_X$1WC-;0`(DQw6?t8_$ncyG5yFU`|s&Ctbg1EkIE4CRfa+^Q4 z(5-A6&q0D{DJP|-` zHC3oiBIF1NZeWUlHfz@7eJ0+7#UI|80PM-{S*)ZAnXf6yNw0nkZ}>4I`N?5^%vFAJm>;v3pB&~#T;wN*`4K7k$zguPZu0C%)4*od zu%W6{i0~llN+*Y#p}hxxHk@{_~-R6>;HKp!Rt!j1`}(b1|F2n%&sVj}%HUu6C9 zhoNCQ#(Vq0NGSziK{LhrcMvx$;HtRJ282LI^jN&=-=lA>v!2;VCjfn-e(*e;@oJro ze2sRF;0w2`Kp_=&j^&4K_?MZC>E01)>WL!0n0%CpxDu5s2nLwfYZO zb%o?Bcv+1Pf_xIC%(FwH7n0kVM3Btgc{1yuklX?P&WYy!G~Ki2{s!Hu>_T!E-N(Tn z<7Ktl`d75eOUPH^xmf2lu>K6$jJ;elt4nt;Ow=KdMO!h4^4)DO1kd2Y?uRdk~Y>Oc?mMufGJThJ#o49_whT}lvqhlMd zzvK|4TIu2+=Hp*-D10Yzcghp-&esI*)vTdi(4Ti%lYcQ^EvNgBQ@d~Xfm`c)KzQ8- z#Kq=Oj`W-wg>7-YV6^^?#bhm5U&Roun<~lMMuvF=31>SCT{W231C8Liuzd`?Bu$SvyY_0$@~+KY*FFWoutl7US6wjP zsfq`Di5&3l*WH+4{RQTw;=g9Q-S0B%fP_!PZohRZbtDS_}9u&-S9scDZ@7VG#gme|0Vy9Dsl^H zFjlytqasmfn|hLVC@VWd)S=33t*W_DHMKW2y+a-W8SsSkxYQJM~1bi*Kc^; zc<@xnB0okO>H>KSLGCF&YqRx3*14u$fl z6vhL|&8dgX=q^{w=_3GhlwuE_e3*{~GmfV0%n_;DyzUV|7N%kpPo24!4Rr%Ad~2XiLg&j4Qcz}ps-0%DY&Idd=J#;RgQ@18#jvW5 zg^#^ZmOT8|=GmhdRB;X(Mf@vv); zP5n=*N`{Qiawu|ybM0+;nr8n1hGm2M)Ap7hr!AZ0IiS_F7CYOVLnNp?EI5$0Li0cm z5<@UZ1LMZI3M7)raR`(W1qSF~kC)tPQTr0~-WF6gDT7>58<6Bk%MpD!kTai!fKai) zz>34%$_X^GI3+J~2+!&UEe^v-#e33>FyBsdg3SrFUEHLl`+{k-$_xWz-i^Jcd4+=Y z-w&bn$6YbTHsqKy*CWG5ZmqsD9T;*U*|kO~31^OwK%{Sxm+K(a z`d?7195>g(mX>#OeT>@dpQd%VP@lOHNcypptmpcvgXwMJkz*M(Zg+#2u}>WtnziyS zCd!lG0#5=rsH#_4?uNvrDzloD<9^;ELL|!9q1RS->k^!%N)uK8<9V(tD7D$xT*a(T zBRKDDZ0YJ0N^LgHT)p{`#yH=4f%M!yhjGZS)4?^+v7C|0BHe94#E@x=E@|+EDPg+? zplV!{w%<6La&XOcYO*}*Zks~cW6c<~Qm|xEV;yOo-9)7UEPpc}b`f7Mt63M7)ahm;z%{GM^{Mq8HAC5{>6ZmjQ3op*=!sZnypOpmX zAz~*ex!QOvQ^@_Ohef-?$+tIkCRm!RKMV%v=*_9GtwGeQU>`f?Z*qOEH#6DiuNW)H zVLNK4C9N?>IpfF|kq~XnTKqAI{XvNizikm)LCF**EAC*uMb`YfWiKdDZjMUWAklv8W=?9vi{RK{N@gYUePH z&FCf}uh?Y(B(g@7n)<>1a?v=|QkAD5FStZeIoW_@UD3-nFhQ>bwss+94NWB#A}rSG zxC~WQnH#DsM;pT;_G7e3@*%#_=4{qK;uj$)HDHrBOXStO#0`6B`x`HTqZ#)vN^kA3 z_U!E!`I|fT0S3U12$Yidp?YlmI0C5+XL}~33M?e!nH++L#p1G`g@a-=3E%-e0hM2x zq(y_q3(-lV4EqKT0=1u|{qHi9S(__?q3?6aamE(2w;(b!d{nK7Ma)~P@xYc$F@;TM z$eg_5T3U@ox0a^=QLI8R3$mlwN^=FLFSrD4}$D?)imih!9&ET46hy-|Ae zrv6U%I(C;Vqe96{IAlZ|s7$d%Z9f^AO^+k_sP0@F?9(M{)dcFHJR6+7>?GEx#WLnPdcZSR1F4XV z+*`_xra9pyCx0#vKFa9$`MLF8d#7`2$H;py)Ou_f?9!xVe>bhWIL$ROBe;8`{Z?^E z92hkB8}umI=`$V%~(Jxz>kq4!R;>Yv9k9BU1)= z!6_@5&Gx%=2QN*LEtqZKd`Z?JE7x+Hza^Hrp{5Jp8$3>if7b*kKkLtnIm*se6o(D7 zeCwyzDBECgq7^MITUHXQ7Ihj?{RL2k_)7-XEKZ5vycF(QwU#5SAqM$rfHuwb>k@^+ z=Cw#ut*<~;M9u9q^(cDGSk1mQ18x%c1MsjSMDr8y=CsdC>xhQC6DHY> z(bN?caE0A~uksF|*Cb7Fg{$Onz_~o~(H1jWZGmC|Mg%^Jfe6>Aqe9KOhu4h+KSdq| zw8*0FUDDNVg$-o!f-FdFU_U5VgoR76lP-|nsJT>gFXU*3X;fi`6_HfbS~(i zXJoe|u>TL6Z%>n$5lrj)Xu57;iBC@HC?Ot;vZ{!MAbsLl;t4*h>iy|K=frC%BR7YGmVZMSO&S0N|rTf`ry5Tp9GETbn6rHD3hgSul(KgcU-LHd%eU0wSD3&*;4 zi#+aOqI4D8Igs3jFC#*J!xt8j7wErj>sK~+a!nZRDyAJw{oJ}y@yC8&1T1_J!zlRx zSfg;b6?7QE^)*0dTd}I^%w2GCvx{)wX+8pY=M1!;VtqG6m*Z7nfE>O1vb*HcXw7Rt zGHbu^Gj7rTMXhO2kmfG~+k8tJpPpHZA0u0^-=N6MUoOpikjDBa$Bs~$evI5c$+dzS zQcke#FHPO&hv)(6KRs_Yf;{5jGQbBNq0{EFl|Q%c7I9(;FNJCC6_WA^HxN^Iq&@by zGrKky!z3dwaxnDWp)fYtu+5b>wM$s=Gaa4zb0tgu&ej&ix@hyvJ%Cb!{bidwS)b_E zKh%~70tzL0{rl0J6tY+^#Qy~Rp??U@#vctq|3(WAthj0k1iD`+SFjI$IV;ua7s(n$ z2(t8-Lfi(R2D|KniPs0h+4vBU>jqG#3Q}y{<=;STn$Ep^ClX9e`Ztc>J1G;(g~A5M z6M?m6Fw!_Em@1Hc%DCc_3?G(D<*Uvq%?YkM_r&n5e^?rP9Em?q zT;oC!b0D-~bTAsPu;B=U)NN=?Hljs^YkEhvQb9&aT{9~ca7l^sU2r@?`hnfUM;w!i zfKuB$w**7;X3z>#&kIq`@g-sP@MnYkrE*u6WtSyrvnJrSt^Y~O0@L(+!6T|%GuY?N zkJAcw{>NIQU*A}4=EwKRMHo~7?2<=_72{9#;#+my_#}c$73@9&nW9p~k=bbBhC}3S zcUjm$8mvl%9C!6WB!kT;U?uPcp$%tWjG!IHWXEM*J)DsQN z$2=nS%=(z-lTuGa40OjTS}Er4B$-VKW?AA!4Pc%NPJm>&<@!}^4NY;7 zkYd$`EQo!qD^JQZ-@uh*;4N31U@J8m+WcQBjZM_THaG}O**Di<^4}P}@O@#}d;yB( zgwreT0|87Fq*@kL;?KGG_qp|1q`Tx9sAahl?1GIiISrrK2eO@SZq`xO+4s%OIlk1=(vy=$DQw@S;^q{2UPHw9LMTg5WW+Wk0$?L2v*w$ z^XJg41x-rE&C}?O)tMOLv3XM-&UqK2tIjFTX*I2R79+Eh*oI2WlZBnUqXkv2P>N9g z@F$3k`j%j>Sib-OP$S}70f`D_yG`CoS++73%A1#j#WIG?Qh75s@^DYpjR3m|;~_T4 z+qj-VxdxWK<5~0@G)&AYbF>QEO?*frWhji!>3(YasLerYIb7V;4?bj6*lM;Uq>}UV zkzo{^X2KP(H=7)roC!u-YCN`20BbD4FM;!}@>mZK@JuT~!^9Gl%{YK;y4QghWO8{2g?t{Mp^#^$Kpj%P zsNRBwCZjX4;d9kF{blvW1G*`rR6%ZU21zC; z11B6u#s{Z=L|ISgfjP$3{{!I|B`_xiZ#SEtNyn#)K(lJiwo7toBOguIA)6sOZnMFg zZJ{2#3S9du;y5;IqsE1ZjDch;U)!0ovqe5(n;{@MU)ZY8F17Rb3~KYaR2!Mh?X*qx zSzr}QC%on%WWWAoJcf#E9;Ta(9k;q1zMgtxc>a=}r{U26#n25{TBVy6cj_)j;bO9X zwevz`+xT)mHX)muwfd9E@~K%dx?0>0hlnZ@Ic!M_DPjHO(? zP}=b{hZ7TE>K5Jx*RR!fjK@g!ja=I8s*>>m^v?{cT#dGGoQX@VDgK~QiD64%S%RqJ zR37}u*XWH5XpWWp%S%;$ySD-3@VMe&7*W(xhjDk9x5-6M271s95Fb95d_vHD zUX=L=%YT2yeN$FN|19|eda4ZnxeYciF}ku2sSQ&l8Gjb7W{Yv-Y05p96a#;RoK~59m4iB;*C;m;Qi;4K0)N&DNg0iG-wR_d z#@!gyl|-d;59b8Z@sFD3xzXmYUwy8Fga~uky-#o+P5Z(e#L!Nlj39xR+rh*D`^5{j zYJC%W2$Z2uH!dNEz@3QL20XF$zMU^SC=(T`MOf=T9SJ&Zcmo#kek>E==d^50XPcQ0 z#Tkp_*@zvs<@p@6+v)~h7ZSFaUSVvj{lO-rSJ~^E5g&)`*B=QVv;rh~#Jgq|zFOv4 z00c`v#Ia8{1t_1|>IX0N;B+d)l08O|xc(Hxl{&CA^An&)oCZ^!x?%57hOB|%FR8+w zO6%otN69icYqe?@S&%*so`f8%K2_K=Sui`@@91$H(r+b^L`|20qM>UPetEk6mzuN6 z69?C(uwMj1+F6QrhjkK$^`{}H4nIP9X^~^*87!}TKm6?=*l;|**Kn;P7i(@TK4Y^b z6_mK7HIW$(WF@W1Y*0HM7a$9qa|vo4qGG_nPlenacTZ>0(LpmpX%g+51ZiK42kU2J zo;@B4eR%SBNX2j$KRLsFqc0;<>a39*h{HN2X8c7XVf|FZ4eQUqvvmvR+LP~dEL`X? zR|qGU@Kx+w%GcsT=OuaGOpavIS7xM&`@)N4$_ImL<14{0(VrAmw~TI z^@GJ_2fsx7pMN2#SO*6o9)AlTFnJk(`2!|n=>e0M!`En#Tu3;}xBshrI4+zL>e#iP z1}E1d0_?rgpGT(W`FnfuFX5ObaIpBu6Y>2p8o*(@yezXmP%>~*B9*k`K-;pC%Mo8J zUeZ~3Tnx`_r@w^;p&b!GmUk6X>iZ4H`zU!iQ?NcpC-L<%|5csDRaxm5Mn1zR(yPCe zT#1NfJ@Fz8m1h}kH*D>o;-#T;xcrKZ)5XH(O@?x3X4x=hs83tLmP-!Z zuCUl5F-JM4Z^O?Jsc*QbKub3PMco{=c0+{?yyi)xyi4a}D7nLS>bp5CD#N9&e6U!; zJ)GP^xq*G0$ER<&+?8b+@ybKxG@e!0GKrXFRoyaoK@+AED25TrugE0-NUHr9@N1JU zw%SDvmBwlx&A}Pn85|wSH#iICBRd5azB;P^5uhh0Xbt2+x_G|@>ivaqCvAD)X#Gg? zA`1gc6h`XX^+9`Q6s&&5v0*EY_|h0u1s+kM^}{6`i8vPY1&71yx8SX4%UO(5RGd=s zb(m&=I(@ni!C|rWd!&Gw3J4(`K*v_GSR(BbozZG8JO7Z&Jl=IsuyozknL1j&SsJa8KnOWlx)hWO(2|I-e)mKIOQ;VOx z3f?=59(*L4ngAKC7r@q1RYI;0sZB=KjLB~312f*b%<<4+!E4a>{4V8>lora zQ(T-O60v(r%dPX-zPdKq zmkhyYnpfFb*NncB!tW5))pj)@HnEctrnwKEc2E}wM=@*sZ0MSzs2iPbU+ zQZNq=92^|f2i-1Y#9OF)wv~ek48O2`H8PqSr!x=FC9kV1w6gf*T%)*(OmmC|Ipf*s z-ysW)VSR#qvBpaFmN9JeaF8rHjv!>1ezgMn501MWg1PTq=2+M_&`paebZ7iZ8cx#2 z@<{y+7Rb2^3y|yE3i-YbotZkKesmXEzf%mTUHd)wz3T)j%y~tv%fNi~8ws7~ERIFI zKd@cc*;;OYamruwco{kSLa^AjqL#;N+INFpyM-25AJ<+(EN{Ig1qu2`vWNS>fZ6&i z4)){5<<4*VArnQN-}4oA{%Bu+;%j{Dq0S%RnB+Rhn}Afc^$R>l)VGs1gvUPgkA(MC z2k$|H@DN{x&cl3#oe=U7GJ$PsdKUO1bgZ=4JgAV)gC4o8=*8-9nTHMQqMNQOM2+Qt z1G;)hJEALW#cBl^yzjvu?XAN4@M~Fn z!_CS4iTE?_6JU=KI7uEo(vR&J?rjujJ&pwDBHn|<^F`pNII^=^qw3D18rI#BiE&rI z0UD^No2p4=SFz!vQdSdEe~7NNBEv})Gr`mWScJ1#sf!|=xQBvzj}NHL5kY5lUE3=jA#K85MhK0d*JZ7^ev7m#2|@U)v*E^zk;x{mzCtWBpcq*v zE3vgUi5|@L2X6+@`g`!0#Qck+>J6y}`^=-e%cNeol<(xEz{_`@9I$hvo%!Mt6zo}F5~iDvY)-I?vlN^4kXv1esiAXo0_&h{(Bv@M;Dn{9jrzsh zu!l*BQ8v3e4_k<7qslzG3EOxjfXGfh%mIlM;G=5r#*`L*Sjh3>BhIxRbtwue1<*_< zS}4U%tFl4UU2HEE+4#thaoR_VJ=&rXnL2EZL}1M3`%$Bz7~=};5D3le3-jvw#>~)SnRw2K|U45fApYm$BWNaDj%aW@F8Yq6rLOpJDyr z_O*SupyOJYGDAzb5iho*i3o!%t)}6FcV)d7et$upBXML0R5+2godKL^_lITePO??L z5Q-Y@^d5^hw=PkKrQK^KU0cvRhUYt94DX4OE&&Uu^xck}GjBhrb;Qu6|OUzmEA znwR!^yu8Q57J-J>?G->H6g)(FiQE)MWw4G_!asSCe@>PBe-+&PH^%so8biHPt$r&> zoEOd^vfK=Y? z*ANsUGMiS?0HYnKmPL63XT%kq7_oWWTEyoM7r>AmRNB#5PWZqDKO^3Fe}!)p7(&$w zoP(#~w1-pL=)!tWm$Q)YQ~2NR{*61}Sa~I;|BJ?}p^VPK2$(tCzJ8KXyGo5SFu27q z4`u@74dct2mpqwozq25O9Ne^G=p#+{L^ZsVwE$6D$q7wsD7ck$T zy1O6nnY@5@6)AdHkiLbn*-lgZ%rp4|Y&=W)8G-F=14jDi5~H_+d75>r0*Ft+ zBGAjpd$r`plIke+wZ<`4Vt+z%6F!nlLE}L!JN6|Qh+*t&_pts_IPiKIUOHXmEPPSx z5BU*lF&OshGoFZ~L3aXWd8FFvLq_!r@tE{{!io7h{GWzDQ}gH7FF3EMe~E~E6%V%W zO2GJ`>iWy@i?zX`1oHqlfjJ|SKWSC5WEOm7A54Rd0|6MZ=0iCc=<~E zwZ{|$XjaLk`8xAu8pOT^xvD9c$)u7Mo4nx5$H9iI%}&*~17E%!y?L)TclA;Bu^tS@ z;C(w;gMhT1P)KWDj!xgA^^T%W{b`bm6Hf0YDNTTJJ|yI1^J{=&mo8{NX>`AfK`4Jo z`WBfe8RBu@u`QZX|`~KgCZU(xCZVvYUp`01+KN0S} zJ)}Hh-YJjx@Zoj41zSO%eES%k({6n~ig0nQ_b;VX^Wc*_pF?Qju!7g~@p2nd{NzAN zmj>sQCB;G~CQ+D^TeffR-Ps#&G)t`I#}Fp5=JX0kf!Hv{ek@FW37`|Qq*|DF9O+>}FhWuw+DV)DK}Ti_Xc* z?Jb??h%-(=7&6$n1($q;y001&iFk4%92xOCb?J>BR8^pS#ejQXBJ{O|7NTN(4>Uk= zORX=XwEb9KxC8I9@-_SOlF=Ww^wYRl{wm^aLDVQY+&gFP?-pzW)8YbV#Syly*PwYJLpIFg=h59Mf zpI{4|az8$GkJOzT`pZL%FA(=h77jo0$^or4DC{NgVP4deVyPUo#yp$&RtB0lySC_CId}%s%p% zT3PE#&}>_1CUMzGhq8z}8JekCG5C!T#}>sUy7e=wUiEh(CDsjyc4+2ysbL7s+AgF9 z269~?6m>N%54Vus{be;11dtRud=RQ}k6}w72vOgMoY_K0iRm=DNUY|??QR#Xgj=aD0n;Ks||ORA62^VhuH)^x7K64WtvP!2MN8RgLyjw{MwiO zfrq6jY;O7qb9MxI;9~Qfq33QvbJ6`cs)z0`uKx=ju&}2tANQ+k3IQszqx=We;PtC z`zF6=JAy0M|2{m4E)P@pc4e`CjoGPwP7{7fEZA>emL*yeX6{dzaL;GH<#r{Sah z8tInJvUm4BA+o^cksK5@Il?}_c?)o{pahLBZhql4;7`;?Jh@~1KQj;i_d5Kax!lu+lKcihBFHgwL!{{W&HF@86>x|2 zq$J>L{(ZnC&l|r;X)AsJA6^)?8Ohn~q*J8RjGVF=$BbhEk^2xVs?=Dn+|=)&?kyXx z(4?1ok_YB@c#4m5?7x(Jq1<+<9PjTb$I(ciHaC`m5nLJQ>@EY_TX#7aCtnUKwNVbs zW*5q#_$bG#R1W31OXc`LPdVP%RSx2bvM`b>3!U9%=`IJu^X0g}%3;~;LOB#a_(by_ zm7_Of7AaE(<{B^fA#1;Re*0ig`R-q+e2nDEM`w5WUK_UQnJ<*q`^-B^7Nvd59#!&? zAoS3l`Z_LSpCUbbuA8=|U<<%$V2Ru)+2OCz~ z;$VUmZ+RX@P+{+8Hkve944K%Q`7)Zac+X_cD*(qIiXa$8f>Ax~y~JKr`c;w?v=!D4 zaJUnTTyXLyB-l1r1n&Y;&qg^7ZmD?=ie*W#m6Sv%)n|cg^9>1X6L-JQ;;zWj{l%6~O#a;e04M+Nd+C72Zz za&-8Wr-QO&YvjcuDIJut`TpPOP^|fO>-pfLK)8zzAA^VJfVQ_iY%@Gh2L|Wp(67D% z*DYdvV^k}99JU$HKDfz*v>2#VH-NiMT!4gHNnQ_eb1zd3mgDYFB9d6TD& z(3nRXA+sQD)&%H7^-KGWb@+7s2It!Oeq&Adcdj$}&v^v94F&5W*vC~;buN6kt4^%9 z$-12XM67hIm_>g4g>6DJ@*bdX0<&-GrouLpxgn5F1)0cYebcgl7bOjfCkZR1zhMQ< ze5w8wbWW}Zdte49q%<}SB#{UU_Puu0kGR_8q~t0K#Nn!|S4_kh6>F+S5T@cTJd zffhMR(i{gW%4aHrmjRiaW3gdd@mH8fdNAk=kM0?dghJm2D z+ofEW5s448Y32{2_yJ?v(^iz?) zIu&K)3(Z-T8(MZCmwmFQ9IfthnB2)ot{imsmSZ@8$|qPXo>WvThk>S87SAh(Ey2oa z@H3GXm+EjzFY_2{)^osz6^uR^i`Tuf)P}(k&r-brGr|*iRi-#8s}7WPIJLTwad5cI z$tl=VDS<`ChK-MA{t=RjThv8duSbIuXAP+58Lu{P^xw56S1u0is* zEBz033Az3#*ZSl4;Zag$Z5%9=4gvJ_d}oEt~_52dkLls>u!)EA}omjsv(d_VBBM zldD+E*nzurJ<-9Q{nFv=8u}_jcC5)Nts%cOkt&kA`^g_e#hLe@9__d#+uDMCK-wHs ze%~BYxkFT#*9V9e=G)T;taX*Dwhb8)>*oK9=9tPpoby}>k4Sdie9e7ERLc5@!DabA z0{sIcxOPQnZ@Y?h2PTS$dSm!>70z65P~R`b!6M*>K(sc8Rn|8gi+t5LC=*YNJpX3+ zvomvpruwzH6lY(m&jJ(D0lIlQg*3mPX5WSb^t+xo86F*vhte&C2X$XYM`iwsG;?IY zd6)mMt{L>@&37S+>CAHJZkd-3{V~(7uKINMDqS{L?Jf5&QxLw~pL6AoRsU^%re(+a zUhT~;%*!)h46oYHts54xkJz+Y)v^7rm)59y zokC$48uZBMx^%g#U*WV6UAy=fv;hD9f#^E*qsE4t=JD_6g?Glkdmx`ox59RZ;^-H) z8CR2C?h?~i@*4o`(BFOk7T?nx=0mrh_+EIl-UN=FJlCSQ=@`=_jP3d)TPtBkE*htS z4k(MEEmf)10Mc;mB@oxP1dnRXobD>$wirIIZBeOh^f6c_={SmIw4d{|S0)S5o;+r> z?d7p^QhItG`vNc_{%Bitru^m4yDU+^%pgV~Tc8YzkShbfT^X37w+z4W zWl*|DSB8h@mEp@-8R$&Qz&ZN9s1N?a9$hU2*Z41%M$f5Cr#cV@Gye=^d1Wir>F?Y+YFXUcOST5NA&HWOd+6_kxD z`SB%RONAh-i`#)gt_;6OSd{~eFeP6bsYxk zJT+4g7mRUAO*g{jjkhvHpThV$E5>l{|2hG0+<^_<&esuSYr;|ePJ*}CZaL_ly%F&q zFi0@*&~hyv^35qu+?2%UOup~Z`TY;anKHd|CxP3R2*4bW-e!b6 zz2$6BA};7f-FHJ7F}hQIKNsPHeWms{>2+P%y_26IBek&z35E)j(ujv`CNyRHhp3@$ z|2MwNdTLh$H;mWTvxDL(#vm>h}bu1$sn?t;Fj7_p>+xu zE!hWf;e}{3w!Y~- zq#r*Sk*H6Ov_S~%pX5jRuz12m^|t~NMr8`mVVn5q=z1k=GtX1dSMwdViPb5kay6Ig z6xx*lA!59(>*t;!?sZ_l!#z}^$k&40{jr!3X)iLw3p*teCcg*EU`HioBa?CRbAN0= zzc7?|Wra}yu63s47-5k~{prq>B>o77{nSz!jsK}lGBpnVc=x5kJ>EP*L-(*?2 zsiQprp;XXmR~9=`pNx7f7|h4eg;!T{Sz7=QU0M*ee#^0`T>mo>Wj`M@pMrf;p)|0i zD_~U7?4-J;ruupgqv7Y;Cm9?ko^3l8KVUb*Hk9#W89q>#i`+J*m@S(A+>)lvW&Bt^ z+59Kv`b6+Z@-{r`AW-ZwT|Cy8+LoeT?E6fS(YL?6Y?h-3C@B>uuC7soG{VN^71C9f zRK))BKt%?zNdI&3=NM0U=|cP)m*P>f4P$J>B{guIkw<4|-B4)@o%LB_`F1=eeH7b( zMr!YgKYkC)^hoXwJKLgFQq%Hol0h5F%%gc5NRiRI7Q7GeR#L_yet60&f<8bBRrtQg|a_km78By6!;VxPonOKW&j<)0_jyDZ<0H~Zy^@k7c@Zh;H z4LNvI7IeLrF{t%}PqRI1ket8APPEYZK3;(LTFme0W1_pl!ZyRqgD&)>s1g^A${MG< zQ7o^#p^oTi#N%&8y2n6}F9S`XlpI^5?Rz>;)(0f9Jf3L!;bjXAgo zbei!%!nrWVcP&v|Vge}1!Kw5PbpzKZ>LtbKnhOIXKN$kIfZ zl=1RvFR6sJS9GLxEdWf8wBE=U;!|fx9br~S)R)?~hGcil`#eN$djA*+dpDNCOE?W0 zPRpBL8^``m;MNzcLl}RC)D(LJM=7eR^QGrEO7BLKOD&c|hW#S#>yb?6Mf|(-{QNHF znWw1bSzRbkw@0Qo&m+0Fo8^Sfs~-Rx;xWALF~O-2%J|C>AHBL&{I5{5FGXD%Di`NW_DR#?gYUnO@! zg~hjz{?ZC3@UlT$w_+nYh6s~{jf*&Z*f>~PF2S@Gmz|>@c0xGlVK99ah3#cp{IgsJ zEayQ??#l5{pFU^EXmQiE&B#11ygH<@i7|8AQ6+H>$JOC}-9I=K15Ce7#yAA!s^8<( zkJYsPq5h#ho0xqbPyz6}DAn}8z>P6!)GB7w4zoBWAelW6(4C{T9T+T6XC04G+eatm zbJ0Cpk&r$L-8o#*>`+eHP{1WI2%5w`=~rU{W_LB=QWxiUjr{U`6#Ht*BK*1jP)*b_ zl`L<0%9)G0u=s+)u?{&2zV5i#1j7Z#-1&Z%E!$O$-|P zXc?okRLVHkhsf`G?cp-+q}7Iduq5~0SLzcaSITr{jZ|Q0HVmdx%jmPcj9t8S5O{E? z&(ceXu1$JYxr5C3RsaA?U+>_Er(@&kep$=_o8@_x@Fa^k#&&G?--Jco*-)Ho0E|35 zP#qp@h_3)@P<$;Rd1ydY=aCu&PY(_ag7eX(#4}$ZPshg7?+{Nrsb)T33JjR-jG`2^ zA;>|VAnW-c8w1yh<-mtDXfPR6qXMiyy74g$d%gH^Ey9ZE+R4M>%`}`hVOv@bYTaRP zO4CO9v`z-Gxohs8qb@mwLb6|5coRH~OSR@Hkd(dIW}vgzH|G-k{#x!^1_Rh3;P=37E`Th*K;4~S z!PW@QvQ_{c9AP^@oefc5oEI=Jf0l>mMleTuD!Dr9+{Z!`IzPe-kvK=9k4=db7Pc8? z9&~Ar#5Fe#KK!{9oX|AijAOel0l#&agn9e@$E!8|5N@jTCrtb3$IT9{({=XaBMzv| zhlGIULsGsOhWwVH5;rFj+POKA66NMZ3eU}n6z=Cl)O$_=&#@H0trugy9$Q)D#wkY1 zGG!g%Ds*Od=LG1=sQMcss@q8jRe9W?z~wwt?YYR(Ss5Ehpe*Ac zx2V%%%z=ty5Y)Hw%khVh&GCo6bNr$BIsQ<%=MR$$O0qL(JizEXAiJb=EA{Tpm1 zgF&ES;W`xcV6@c`B|K)Rb?->W*`=C;Ju*pE6S;*b>`c89>MOUV)%qnN0-W1-#W(Kl zz>E@V#Ll098}o^RHOS}pJd4w&A8kicnORz$t;a2!9L0(p?Ymvq6ZdHHGnHUe6S9uD z9hB{r;{vPbK>VqQT#x?|_#cb^lkjhxfJgHuRAMy$r02>By4UG>xSl8J`9eLf(DS`| zeoD`;>G>l)V_btg*}4-F_BO3Mt8m2k?Z_oxwiI9JrKKdL5|6xA$Dg{_DMN_)W=Jip5J+S6Wp+iPEY4cO~YdxiEo&|XXI^*^j8hx`e? zKW<$F-_C=qq}5?tZ?4r*xBn|p+PtEqgIM717RI;74PGFSpM6?%liu^7kI&YyMn7v>)#$WzrCC93@-Y0 z6?~hqzs~Y*hZ}un>fiaZ*dO-bqPoHg=JTiSZ)m;#f{4W_swxVrq!(#^6p~k=egz;l ze*vdt2GiM32A77gEy=v1HggbAxCum%Ot$C?&M@pzkBlZ@7`y3SHM=*$LM731P^tMB ziF$<5j8-B;uwrbxxl7GHdZ7FB+DL2d?G_8&`8LJrB_H8G0^7CZTKtB^dVN=JJXohUACE8msn1A77BQG*`U- z@^ZU*k(~lp9rRRQ0VFa zii$~67K)F_lW>U$3Aw2-vI%#B(EDW8$xW`_i`pGmEF?3qCYAggtqOLzYn_J?4+HZ< zc+qBk$}{u;k1)8a?&+`CsCx#w7$#S;yWy|5!ooI_DQ91G+(V;Ghu4kCSR9Jw=$T{Y zlu}BMm5}`X#H>>XnIQ!k;Ni;*DsEDn`&W^-q3= zYb{_4eFglR`;$Ymu-w8P@Q|fS4o}u5mIfb268=yxX*)eRhq|q4tKRduvQ(QItovwW zQ$dk7;iAju!y}h>F7Z-Y~ z^f6&gVPTtL=0TTaXVf(VB~Q%)G5*rCjL!xswS8QWC{OYD!*k?|vy1{~zRT4R)3c04 zty9^U!L&}+f<(kLt&?ovK%XhVUe@W-MHqBy>a|M1l?g@82|~)>3qrsfvX!DpmZOZ| zP|RfIg6wFToW!VJPO2cX$;yfgdpPrgZI8;mE%gl&dta#`n+ zJ|du8sUPEm#scJIAqP7W?DNAm9aAylX-m6yD>k)Booh$jyUssgC;?#e?YG#c{u#~% z!9{#IPH8@_&ebHJyi+7A>9>~Gxj<) zf62x5HovWBK@S4T#VhR3e&s&E#I?M%KdQY3TR&hE0*XLkn*i0yaf^|l`~)0h_tAJC zwm=uiu0a;K6N`2*U^Jf(E{zh1B`yQ)(y+YbD;)jpJ#h^=C)|+>7Yp`?l@B*-hyw(!*6jw}URLgB zgs2naRnP`8^vX`WbMChw&T{Ae5Zo)A z`*fJBU+LTjy*9XDm2*E2aaKF`GWcTyk7afd0>)zZ@oI+jyN`q)1McHgehj*g8GbBw zA9oPIZtmk2hAeR(Ph`lD`}hq%c6T2%nKU-+K4>**Y{Y$h^8kD-bst|q;m15x{+*yb zSzbkGo-U{I!xLtZ(HvziA)!U>((b4q5O?ZOP`z?A#RQ6KoSl%JcXc{;I^sSD|MT(R zivNr7e+mAV<9{{&*W&*s{NINEd+^6RI`}C5ja%`ET8EI;qZUk^^EG3yqwRIPy*AnF zY4$qRUZ>mZEPI`6uf$$k>~)d7w%h9^_PWeoud&zb>~*cZ-e|A4+Uq^``hdMYY_I>Y z*QfYOIT`%FBzQH7vp3qG*qzst*(y7miQ5NCD;NWLnU16`H4i)zrhYgU#Mo`h4#_^8 zX$dtm^dj-hd(nWGr<+FD7B!4;(@5QK8qt1{eeBEa5Xr`uSoYk|qhPL+g1wTP%ZM(! z>=MS29)xXe`;GIkq46EpN3IR(;Glg7H>!UFO*>M6{&cuxzQ!-XoY zXF3hvLv}~TigfLJ2-le&&I;j?%Gbf0GcmZ~U7N$V0mrH{R+Y@43D0dtL!~4_iH9q+ zTU5CLd#E>a17Hr7nX5smas`8*R@Yw&G_;RyyEiJ?UJP1v_`nopH@f+tycL7X(Csov zvW^_w*Ka;RM0+>;wN{0NZS=i&1DUBYpdQLZRVank9By(i)eZ;d?*0UJzSLxKJir*D z{0LVL_+h{0_YmxNqKqpB>`*csVi)+m5-<~REAre8XhPpLgqQSvcIe7P3F;QcbRHVf zffQ*lbvB%^DrnRq-?@9x& zO?)>P_owZpPMIe`AH+>oJAlnuvr7jAH$s2#Eo2R{EMWzl4d%X6-)(-Y)D}V-w(dg^ z_1Fp{DM(xYO=S7aeuDA@e^`d3prAaQUXjW^2#&)5pK26Y`szli0+2w3rU|Xi5K&S+ z96@0CIrO47gQO)1?ZBV;$cR>hEMVV)0ES~`%8~e;l$Kf1T`t7CoI69!BvUq-WnP|3 zssa<%>h}U=%uMRvB}t%%F{LRr0JwlU6n>rEkuYrY$$Y_k_4^gut^fYaJ|?iQy8csh z911`?S9878zVB?>3nr87vR7lIl!> zZXO_FkzNry8^AgxRJ5$7m1SXdQN*)}Zm0IhSPg^q1%B04$9SIzWFXw@j(A#wudsSQigW;K=qE&%?I2yy7?en;5cMBE(vbJx8cZ8 zr;7`fc6u{uRx=PgE`lWUnt)SDr=nhgl1!L8Y!e-A0TktHliHo-BI+i;1t7RoG`ed0 zNPGqyL)f-b9?#Qer4{h|IUc81hmWYe0#7@mV(tz-K%3=^!iS?x)o8O==guK>4!OCG zqPGc43>r76cnSr!Bp)|zQboJr>{=9H`c4evXp2mrP#*J{kvF-FqVZS3V(G9x3JgNw z<(XAvH4wO2n#kfdaRXE`x#BPgWBvjjz$A?>v;1!*{DgkZmYB;fFuBPT;U zd_?Wlcsh$cawm5|owEgXxv0Y+5Ox(K^MSm;bE`bhJrgiXsR$1BM*6ty=EtSAEDRsUH+3t^u;p&dTJ#}jn(0rxoFd^nzl#KG}=N$?3^b%w@OhI&3w+G+L4H3MPH zpcWnL)Mw)mq|6ULVr4h{5LP;XsjRdF=}hEjY;`M(>$+niZC46Y{UKomHY_PhmZo3R z8!tbWSzdlD+X=rs#>(8MC2hb(A1`s03wy4ju4XH?ipp2^KW5&Kz>`=NGC7IM=KRgi z;Rhc{7jmy9L2c9pr)LaUZ-UbFv$~bF!{tMQz5is2nRc7*4UycM&Jsw5nKP zowJ{?EjXIj@G4YC0_ROpdHPGJ0^)@^X->wcyqHUjaLCVs#ThVpt+yQeS~(_J4vyLE z9r??|Q3iGR0NXNlu6X>6+WX<@2TQth5%?*26-FIc4@-j^41A#NF`)refmq96(Xg$o zEP$JYJA@HhCSMfaDG#QZ`k21=M+B{XA+f@;`5=QD2eCM9I`iQi)nv|P;Z)>b=m3}s zc&`jT2_XAQmy?_BX!~;K0A^xLOJ`1KGoi_yl2%{RW(*DF?%oY~RI`y39V4S;=9_V1 zko)M&+o{Yb4-G&qrkgpqHy-AlJbyws|{)uI~B`@?(n5Li~6j5JI~;2rtlm zFnGOk0LT<&#>lZ4KchAzx|9d$&PCuSSeFn5HfkT7i%fU&ZAy30+AQku6Oj*LWIm$y zp?G@k{(tPfcbpu>wKhEJnVqyjTJ5sCk`TKRNHl}MOAyTNA|z~*$r)jiz!)$Xx0uy} z(J*U)0~mvI#2H^X$Lou;uXDWiHI6tSU)v<7>x45l{+{PKRoy*dB@z6-?;qd%em#Ba zbcIt@r%s)!I#oqD6*HZ#tWGfg9?x73K3=81kHKU4O(G_(9z}mM%agXCt`A~)kv#iu ztZGl+1=2)S^;Q+E=-me7(4iD*fie>jF??1TtjzEE=ts;D7hxKT%3=Qp*y@uNO1V;1 z1{B2VZW?e&b!`d_vdn#^59kwf} zb0bqM#_Bs2Lbb1q1TH%$F%&9OOqUQcw>hTDwhnNP)DclVGmcCZgIyRFF{5#`{1_3J zQk6HgJHr^Fl&U@p!r-Nd)rXYfF;kd)^Furux_aL~aQS4XJ|NCK81%N5zH2q<$Tbeq z%Vx402g5;LZXO%?sXc~BF}@89v(f z;`Y#-gO?s;_lDS2d3zE$hQFrd1Egu+$(gDL>W?B#?fD?G=dg0luDN5q$hVu^f-IEN z_svH-H^&>%0BReNG|#W)8WUEm>3LY8cn`Fjhow9Ahw?w0<$sw;kN>>(g_Yb1g{4F0Iwm;zij zp~m5SWpyY);|P7f61iMSS<#h&&7|^a$EzKS&!ZK$ZZ)B%V!juS?Vmyq)M)1o--Bbc3GkHcQlsHF&_iR; z$7A$xjh5g*kBo7x&--3fqiHzMi^r(>d-ReTZN-7!bqp)cF?wl@#^XTmHg;$VJzAqR zInZNc>r&`twKD8ofnGj_jfx6nf9vz7|P1c6188 zSM404w;YFB#`vGh;j^sqSt4*@#jOV18Z81B=SQ%jDg^GK`3_p4@ylMuzFTo4C}!0%n+_av+i zd#PQFT)F8yBfx@d<~bD{X_u8Yvk-(&2Swpk_;V6p(;`6_v2CQk{v3JdeuO1Di?59N z9J^nmN=w7M1+YVmU8t)Wr{tE>z^zrZ^>6aI6JhOw47=J23(AR>FhWE2W6s8P9VR*otoWzXz!nM)#TG9C=}M z-zjdLFNDh&<(EZ}WR|}*gnYCr^AS*lIB`efCQwioFWbS6&_3BG6}FyhHOwiu?A`NWFSim!EsnIZ zjxEc7l(CGNDOx#_5CkR39K1}juKXf??P#Qg<$EmokLdnw7zC73wl0p##aF!n?i82# zqv9=%hB~urte5dCyGZ3)=3zC-sXq~{Guf2E**Jqw>zqNxc^CrQagl);_9RJKQYfhg zBGM3`SgF0fQ&jCiRSJljdxDnX&0jD&Hl?{290WgK?lM#w;(K|yAg6JlLywNHMXdrk z@lb#b({69!!1zpNeO6~Ef*;6{Wf*IYE<5XpF?jxOl*xJQmhpQDVE;Q4xJ7X9gXcm# z6z6x~;|X}vhK3DyXMeXjkFXNTd=%jy#KYe`c#5NE+m3;|h00|9OyrQpt;Nx6r>=+J zD)k2S;uQ=$jzMjC7BVsNIJ;@hcy26*5S6hk|C_z-+vKfa9wh51m+bDva3eqnxf))T zF$^GDBbi(WF~K#}6d7YBB{@&No4<5-!1Z*%^$F*4Fu#L`1!)ic9XwFoZz-O!C8 zjP2Q;oH6ofv+w2dy;8ozY1Uw1uY9N)R*SK!&6`Xvf{gs=`Rg=66V4z=cTfn~`Z3Il zOQ%rLFt~OH8?bd4G$BuQ7}Ph9K>+@sSBf_VO`rzhGZ0{^V`Pl6Eg9+(iE_|`5e!Pz@*QMAPHjR6Q%Uc@vYKOCUUY^7= z460h=aX25(zOaAl8Vqk`And)9+VSHKgzS4u-E$itIg55{y4uq=fr& z_K9P<&$&#?fu}8@TX{G$lAL=MtC=830Zf0 zfNuV3Uyi-x1=-P#dqO{G@SJ4`@H@k4lnrK&t)5>Bwy?d`?x?!6QAH zHzCZPsK46fNI8537@!PtCT;>3cT6< z7q>8!f)*BL&ANXbqA0~1GFj`IPopTKs4j0g1wnLPafrDl=j8Zcc+1KB0!ZVjCFtJ{ z2Mi?x`;%(#k15{9rSg?riEyJujBILm@-vF0to=XJZ)btz!!H35ehPox1)c5AFwpBV z3-EBFi!s3ncHVN>SF+4lrkoe%ediF^M1{AzvQ6=&P;fVSq3l7~W)5H*#4HEJbq*p1 zjU(R`egd)Nhc1g&<3oOUaQYi)c0Aj}%QlzTr!BD~V>~3A!?pSSWCyX0kPoa|g0DDVKDd zuBZ@aIm5N0U#K70A^puVcg{>S3*A)xf0m`Y1ZBoPLjCo~qUrmL1*QjlH#G=0V5U1r zOD`)+2v1Fha@NaA*a8iPpSSv3g7N;d@QrdF$2G_f>|Y@7F_uk>+`;f`p6sHUS21$h zhNqh&vm^1$r08ZJJ{bPD2nU=?!N4;{J4epLlaA*H!!PTbcjuft)&3Nia$cM!IiKq? zInT;dyGm!E%O!_(Bh$z>U29^;puIVG$%t}Y=4%3grbm@%#gG|5p4w6S27VSF_E#(*WY)rpp4rKr8vjMaE z@4_?I!!1AbjEf*>^Yusgg-m6;r*x+ zJ6$WQU0oNme;V?zHH{)PZ>kSDp2sxTaae`hfHi*?3d&}Cbpk6S)(qiuzLJfPYK z@t4Ih{<-k?7KZJ*D||o>#q~GC?;lM67K%%_qHJk0eGgMMQ^xTZpv`mlX0#d}v)X|b z-EUEd->E(D2XEZFX`XZ1qXnK*7crR1OAH?w=vw7$ZfI!G(@Op4Sc?wRfk%;pv$eZ_ zn%Nj(BBI=Q650X~e~l4m8)C)X@PRqra^oCB{0)u75a$9xJ}abb>M?NW>*~vge?%_2 zLd^G549c2BVr&A^8Nk|Kd`lw>qt#QuoS7Ndh=M%uq?(Jz1f$Ez$NCu#FO$@d)@Lz?L)R zx>6&rBu?5IO~4m_;X1U6!{qAxKp(-V^PXj60*gGtR3i{%0!zgq z$OINebfSEa2`o7wn8pd{JD7e}1T@4PXn!}uKWMgbMzX*90{Dcb$c3Z|Go7)rzCnlq zC`0>*N~p!tP*w9=&cg=>o)2)Af5Qz%<3JZxX7Mb&;;dHTHK#yd6`aGz$gvR4yelNj zQo&lj2?v^gH;CrTz20j)E&f8hvDa<65|NFDTWWZXVXu2;%d{YLPg^$e)7mXFcuf~c z{6;`5qs6lZ^^KO}v;DR22@A5<&)!~g^CNd)ZpQ|!l{*lh0};M&v`4b+A0!O!V<1-u zPhT^T$>022$m1}ll;5*bxXySm=r{;+ho1-WnR|da2bwS3 zYLrpv)G8~znj#a+JeE6o;xZy`E`!~-lh12f@_7p4w8JBs^Z5i&(J`NEnUlWJZajNz zC!NhL>CDcN&J(wr4)=BRjjni9>7Z;xGx@o1bme0c7tY=!ZEf{@HcQ9VGvStc4m;E{ z$1<$vKbNr55m)RlRIxGbi%I*QO|-|~cxFi_S}sn}Lb!#N?eUzrL_GJN?eSc5o8OHz z?$$&jbsH~_e7pB=v~7lu+xFsF3Q5M%1K#RGJW}1Dc9l8jiMDsOGUVl2_+1p(&GcjI z{oJjgdG8r%f1It!87OUAieS#v!C#=?Dd&e|{<2F2TY9PdasnPKVrS<-ez8m?1B38N zCfqj~cA)7x(L_Cmg2+PRnj3Hm85L@hXjS*&jx(LBsV%!z$2F zZlU4kW*Y7y4fNAW196T9fkp$t+*ba_G$g2I8g4Wi_5lqXN0|Jya(GEI4L>9e^wUa% zh9XuD0*wZOIgL$X8WL194KFYn_5}@53k|Porr}4VfqsmJ!%^b=WoL++VDriuxQf`V z#6C4=ub7H7vY8IY6ORKOt?l6T&2*&N0qXHqqkkOXI95uR;hUSo{gL$3Piq+x=ju_Q zl_9~L#$Pe@3FAB><1d2+CszIn`!t1X`r808i;c=2s9c9=C<-brXfK! z)3DWO*dH`-?3pfy_cqh;0BN9~RvL(NGzc^r2^wUZMagGLoMgzgzR{qB{B&cQ@96uZg8d~}2W6d-)^O57fy*h;Z)b_%C-11!M z5bpDHhHLE$`bOtN=cKCa8G_UiF0Ks(8`ivZY%%e zvP@7Zo@%9WF8caL7a;GPIZ4y_gJv4@`w8Jv6tUXac{?sFx7p+Y1Qqi@N#kKzdN(&?E^mnNghOnHN$t)_I)tz5__M#^h z)`O14!RQ*^j&M~lx_Qk2J}a}qi&Z)rA(=7H#nMZDjHKFi<#v9tu~FaXV(1ba8zp6Q zkkgaGzkx51{xO#Ek+a?VTo7ex{i0)9sCTEAml5|;#JvlK7RG;^Q#y*Jm&}d61{^Vc z6)ItKmra(wKSpG`hQr5m1{9N@oK}hkF#EI;4oyYL0RoMd-;ow3G(FAH4C;^vHn!)R z!{AEhP#eR7j0|!=1Uh>`CzQ;lcJf!mS&7H4;aAyC=m+iJ>tuXGQS-b`eBbDY#jNSl_O<2bark_cAf9L7VX2U!XVV69UU-tr${NdD=JYHEHVp01JO37w0 zau_3r7*dxpS?~BcnhK&Fg` zZ$6rr(jlVGt1JsA^of1!P{oD_Yq<*v5)t=XWM`Nsn}1dIa99y@f^xxL50V%4TJu7g z$z3_d-dVXc`_3|#%i$ni&>-9E(#d3%c|Xb=Gty1*&8{{m~EQT$j%7Mr*_R zFL4w5f&83-rlS*^+p0KGJ8|*Nt)r6{PzvCM9wyv3dQbUHq5<=3kpT;8OHm;3(_ed~VHVcjYrsJ5%LWYA?loYSTDGDHhibbU zFkCx=z?N$$Qeyo=ZEc`KT^y;pfNax%bC#h7hr+W{mC@Yh9{alRH1>_|(t*AcntA07 z|5{#Y<&%WA;SRK&-b~v+{%_GX)Pc5hnrXZ9{}yeFI?(pyX4;+#e*G7=|GDdQqyuf2 zHPg2GzJIA~!rWG4v+MiOuL_*a&QJ@o!Y03XHMS(Q@B`P1_=RtMIy4CXfkj46=f8&3q};DJNCP`_xs!(`y3Vm*4b;Ed_1;sT?Gw!bBFTm@$o#bHJ(Fo z_FpE0>6!i=$780GA&kGuy`@EG9l;U$C3t31j~_Ge%~eP~{QfvRn8L_#;CdDw;*P~r z#e5x>H#HZV3&mJ)aaJf7iVfk?v_dE*gi8}4p;!#AG5Hh&23g%7oeRZo_(t6#7mB&z z;)u<$es<;vIAH3z1&QNiHMGXzb(;v!U~XfcE`bX2n+Oj@haufhJvq7=Wmf;JcSSRoM z!Y$Ux-8omd#X9-dS3|K*4$XyDxWzhoFy{)sSSKg>qAu2NfUChjnS-L?5>6WKL9qQ| z8=ihOTRipgT{B+-xogOGL*WO2E$2D>ECP8l9x}IQaDe)GeBKug(;^S?H|8F~Yw_fV zr&L>`OQ%kRv$`ICLG&IZWXl9W^lrjrEu3}xUczGrzXLE(?;?sE1o)kV$v=SKZlCE3 z*Q|0{qB4!4d3p10L8PD@w{iV+ccjRlK86H~kM~o{w)Vk05*- z;zn^e24J>#!NcD^?jekJfPE=@PjMiVA6+%I8t>{8@YhUlIv;aoIbAH4eN`yws$|{- z`G9$;gs#2L(hWt|Au0d760m>f!sSQHcAd=)@XX&9JT&U%?@;#;Mzh1*8KXfZ>P(AQ z&qJ;(Tj9aG!8)AGSACXYnZfYL7<+|bnbq*L7|Rn_5CiKuye!5ZW>{uF+!$l`CRY57 z`XL|d<^$u>?t-rtR>_fgnC%PjT#JXlz3~)KE$`5K)zl~Ou6_%DXabB(GRiW*PY!G2 zD-v|r=>oTvr`2?F7lx$UBeUNP?*|?KaKHIQb0O!#^{!W zPL&b@*~uSPR1*cpk}kE0<-pXghBBTi#nGOdPll0ZxF=f7^wn%OwV%U>w=lA{5*?4W z0b3($9SVTqv$YH7TI3?SE!-oH3CXb?-Ho@}k=hp85!jBzU5SUkr{E!JoKIs<#CDUP zxSapPQy1}t+FPafs;P0jO{Pkuf*~k9!zZHf08@5`CmKvy89v2eO40CggDEw`^#+q| z!)pvCFPLGY2?e^_WnB5)5HiA-Rhy3>FT=~}gazc}`fJzkU1;aU90*6C&H;H5ZS@pwlzn!Ps`yqMItOiGXWDkYF7^c_tcyvKx07`d9$>_( zLXI(*6@t8|E-o>Y>f#E6RTob(SoxhbSarb$lg=;QbL4mBzcjy10$u8ncrRRS#45kX z87u}o#b9OnsRlFCCDY(pu(HyEt^mRs^m_Z<1fEo7Z|Z%F4DwelX@+B6>iF2TdL z#`--QkJaxLfWV6v^Ofqr)YfW12A1E0j9BIOc!QPSQw?T*kw<3rvXJ?{%;)$V^Pn8x zXs~iT){Qx?zHghgetkFyHq<^z; zu$bb0o}!1n-7p@uU6vbv5gwEl{a2rjzmzFNYV|a=xOazo1x#v|D|d_`i?-y#l^qX4 z6nYS=10KvJAltqRrryUQgH&2+Hk)LH2w{`Da_A+)FpQ8 zPAquQHEXqeDAB>Tvl5D|Y^l^DX1c&PCra8WRpnTJDQ zUP^GN@v;Q-3WC$i;Ir{+`}k8>2Rh8H`gkxuzBmD2l7KHyz*i>VYZCCa04uV2B^9)n z6gfa~ZG_|qC%|wdNH_t8BfY{2Fx=}rPJrRw;Bf*B$6RrqfO)Ba$L~S*W{*Pcg@3e( z3VdUZ=!co)TU6uC?9u%yzDc_P#Ov=p28b5@6GW*_2ucXyJML%cldqyR_}esswb{n& z5eJTr7TwDp2}G%F|azl1}_(1$?$?4&POQO-598q?x9237;tl)zS@2ca9*b3QSQSc6ikqX`F>aUT~G6nPF6St zY2yrBcUJ~#6MS@adZgL5r#tLwcqDrdAIZZX`l-!-&(p0LZTDjmd}@F zUI3YZ)qS+(@8EmTRWCs_eha^X5R;T;LDmA+Ha-qSK(dt` zji02q|4Mr!ruM65ZzgKqj50tS>)3%h9ag1Q)6ojhxU#LLzhyN&CK`A*qUzPEdu9NN zcUSm5B-mExUuU?U>Wc%=uC$8cklxbFUpbvgnO)jMFdIZgbbA9i7|-7gHt5f-Z}43` z1wl(Q|DbP{R%sJK&SN0NX$+C~A@UZYKR?MKR1kg+1mSL+uIM;;%Z6V<=~Q!y?V%(# zg1S#9h%RDmMIT$y#a48&eV(!5;+^QiB(@Ktag}BY$iAbE;6SOr1lqpO*vdY(vWu;3 zu}R4F!=n^$N86=}4ZVCYajbGmaG<-td#JG+T1S63Vl5*R13f<09v5qmqwx!*5dqS% zE>x@wl2{22^!E2+&j8E07qQ~d;QTXb*UEw0@if&Wtcts}+I+ z^ZVx`w#ymY0w3D~7uy0C+gBMIJVuu$u{~X};Y?Q_8^MA8{(i)k2R{xh^sy~;u`P75 zeT}i<7j>y=sgB1GTXwK^#`wIAC5^D7=+ z_Atn%!LpOG%MhV~+CyU(r)qE|IXjJUZn=!30&JgsVK96O5Hf%*M1Mj*mu$bm-q4FO z*=z>qD`fina+6Sp!1}eXf>fL{fLbpnw5nx8a?k9F!YJeO$tbW%D#3Z19USa-$cfWY z$AdkCy$ z%HTkugnPZ-1bF(J*k7#%9{v=i(Y9p6t7DelzEhh3$>S2Blzbcp24*TJ0}(4gUK?n}tc*w12-1C-eF;IvO1iXn|RhbQ>uPcwudFr#G z)%Y^W%_ZB|aTKhi!QCwBoRxGolGelcdaER)r1*MrMdQ?xMZ&8t6^W}Z^gfKF%Wsp; z9EPb8=Jy;td*IoEhl%n>JnBO$8azYB;~#Ill8s(~)ZLoh5{!o~gP+5xLz$Wyvtmzm zZ+s~xjEFS__J!F9TjcWUO0hyALDIWzPkG%yX8VdKzSyY*1}i1VN59XTdg?knC*$#S zdYX>dNt)QBI-1!2|D`k?xsx=puX8l9pZu57bkt7L#9rOeMEUtIqUj9S4Q4V&lO`Ld zHSUGXHZ3Ze0^>-`byt_6#%&o&nwZyc^60A1fXZY2vs=XCX@TiB)zja@=Fnr!AqdF< zN!-1P+X+x|gx7P5i2EsV+)gycal57l1%+|<`nXwYN!;k7*xb+(C7xN1DOD5k?}i*Y z-J&bnz~*oViI?o{vi8u|-^UdCdGhN)FEg3b{*e~VXlKKchRr@kK zPefmyfU208{twhbPcewj!J=P-T1zn>{SyA79+WrWUlHyz_}7FN2+oFgBVaySh~$yx zAMr&)s6@ z^frAIm}@iUAlB$?;$x8itR-CSMq%Q1YJ|lJLa#*O&;A>-FnIx@TAXIxgV7oZDSmW)=c5iU8b|dh1qjItKnq&Qq%Ec{AMM=dc4lPFFr6bt0 zVQ8%N7Z&f!@q8W+`Qv^(RaRh-U6=`f0Gc%=mY<;Zg7Y`#p(tx_LxR$J^Hy3FL`(lQ zQa<|ujK#w5F(fC>?Dj91j30p7bpHR=6hEiUn&U4X)Exg;oPU+T?7zqHa}uso{I|-# zXw{@x^?4}-XXL8TNI|jr;B;K|5+JhCgP_`mFycKn2CKN*1IOWD5-1-wJ~f}Ut8jg_ zaVh5tP&%yR+C`pv$4e}3OiO$l->Lu+;~<;EFEpSU7{54kF2*~@Cj633H36om0c1Kw zA@@~GY(K+O%K_(VA4j?_EH5s$5FsZ2%SH(9u==Gqk%30%uiH;CB+X6Hs+wz+gBcZb zqiS{;`7lD~hu7Shgv&nH7r+>ix$sqJ1YmOM)OAj77TiGPN~NsCrfz5n^fCm36-E-s z>5MvA)aB@UP-I2zQo0Jw6xZ1&fl4kVOfjH{mD0=NK)V}xWzIQpSO#?%Ln+R>LV>lR z6gBMp$ePdKHG*9!ir^is5iCHFaBd|XL6?i*1qkWFeX2Fw&zUd=eCcq040lEn?t87_ zu0YXnaF!0|i*&an+&!(~E@pZdUZunNQoWC5Vfh=!S!GtLu7D0S<#JULE~xribm2N(RTwdYsM@?l- zNSAHuf+P09@Mn zKug9C$$S%)aU9z4^xCEHlG93RF4`B{WqPXYbKPhohhbQEp>{H)w9S(2hHr&Lx+p*S z0-DVM2pT;ekrks26gwaDs-hcww5me8pd=^0jo5;aV01Ww4jua01n~qQdP@UcL%2bE z8PJ&d%ilVX!_kG>+Jl!i^)N|HNUSHf_IF{!7xhTV#DT)_Kyeu3_$MLs5bo6;=pGvA zsd6NSIklc!S^pMQ!FXc{zSJ^L%WUi~$@E9}7b+I@ul+qp1$EfpjZ{90RQjhwGU(>%tB@gsk31L2O zFdRZrafUA+&Bu4_r$#LOeL~-rwG%C&hq*E7yHLkN@IetlpZr1C$g=K4yf4J#^(WX^ z{%lup8qa_o1pavNMs5bX-Y`7LYW5>~8`7>Uo_;G|*l!a)9c|AoZM_wOiThaU0`Ptt z5lh^C7$+bunE7+XA&7p1EJZeqr%k*P+$hQo*S$K9dir#Lu~X!c*r8`B}|{+*?8+mz?UBRZ-rMJVj7);w^1;pS74VZk~+U_9MSM_#+t}=f!Mkwql}&?a(;>(wwMM3LH19xfl4#&X3p zq%c*=Ia>rv*m3PgKrZ@Lo?~?uzQf)Od;9*zsjKYFpYg(ZSt@EAfQ(ZqH=&Fxg$ee6 zL4la)TqNjjwJ=OLLqC1)TIpQvh9|fhf~BX+3mShA$2eqko`nR(}tK^L5nWAOV>vYrDPobqcC(8>bk! zY^P!6+4R>1e+3OIwU$zSM-tDQI>vL7kEh4SbGwhHn2P5@#nWMc=ZI_`;H67clyiWG z_%*1!)XWgl=;eVZ}n56BQ*pITI-2ii%#f>4)s*M z1>Z`;YoL&za9hSWtlyDdC;y zXagkb)j>qPIxxL@HCUOtH1#9?D1*rdxHe96N6<$AWilVdL;Qc?VTBV9{fGuYv?X~5 zbsO5R2*7vX-tKV%fO`ZsE$>7eu}updAXPRksSnuuY=%g-^8X(BLi+Fa=?gHL^zjkU z@!m8Yba*;aA1b%btz1dplJ3BL$+B@jHG?}0GpA7w1Q>bkj2zGqDkTSA*NML#mK?Yd z#j;&FkOOJe$FSX%j&$;2&USYNII>f_8|ohHss0Z1+PWr8ayThtY`ikiEF>mG&H!$> zx5knh$l0Bq#ev))4xF$CgL5QQfb6ldwX;Eu%l;Pu;$t$^QnD@jH^HOb(rImV8#92~ zFHf++Va9A;IKhE)(%{Hraf4e&PZsij+d~%7r^HhV`MN^-DTQ=X{T;ITs#} zb{7QGFPjJb@IT0ov}N9kv`z;<&AuO)$(O@5-3`*V&?#K)LkHq`PYP{0O)rQ}^X|dH zi0Zg`ojwX)`w(2tIujXgoI20NB=_{wPz()h4zSpT8!5{_W^WM`_d+y%9B!QA-E2Q- zqyJ9YDK`Wd?gJht065sFG5I=EXE^UZt;G!sfu`@6lxcF4(sXzdmv*1*+`MOsgKqxj zY|=KvAB63r8W9_W11L(ZLN^$%%L2j41&Wth(wN-7`>~J<-HYObO8N>^a8PGK*cFoc zx=6*U@wY{5K7@6;b9$HpxjQWT{WGXrN#9P7MZ_b1Sde!-fJ8~3c*|+@Fy|ss;t9a> z39FKW@FDa~>Y#wfNI4(P!=KmeRnOAj2ga+J-yrX}`N->(v8ovMBS=2t|2nQA1mQv< z_`hzm5CcN+f8A4s7!-p4>(&b~Bn1E0v8N0|4iZdj*I-r${@aiVS3cmIVL8Wv`2+-u zFfD?mju_NcVmj)B2DIj<5J4|?o(wjL0%7jY@<>It_KRq>IP>68D^MPKht&hSW8)Zv zV4XPq+Dy63w_jccKfxt)a`*>^*ZIIUEfZ4!u0KLA(b|ssGfk(xTt&0YQ@r` zaE}2wf>m;-akCdUjl0VK0NUFfZLH{uws-VglpW^VE z{S--yG~f)uNRJZ+Seaz6mM_gA39d0o!1fxCgFlKwR9hB+(BQw1c$@&>2F8!gY({r* zHv8wHQ>G8xNfy)4BgJCZb;{qvVzD)##9Al+Rk1knJF!ip~9DRhPCD6Xy*Cr*afUc&PDN zWD~oVzQWh+^<7YWznp+yNWd=wq%IfsLoJ)3{p;XES<3MLzaa7vJUgQYBgBu!xjn7=Q1oB+cyH}WUIaLh|(b5Q>(-fp`l z!RUCDDCXBc&d-?+-%qgbpU`*E`Y8f4(wpaLv$wCW`mH32>zTpo2?yoEEtvAGj3bJH@`mc zrUZRV3Y|U9`%d>`pC`>(98_>RyjFi5Cp4&IeXLtcQr0q+RqgN;C6K|B%K_%1+tKq6 zuNxw|H3^+XX!m+rzcGfV|H(0-;vtWIZ-P$BJX?D(L6ce1B~~Y*sl-k_-j@Mx z5>b{r3?>K0&&{kr-^gFr1g~Wc!pEa@tc%Xp-rystas*=E!mm66LClnMv~>t z$PqcVVcCeM3Tl5C_bUAc#mH>ep1YqP`W%}euZ@vf__1>QE`zIwSeE!aI`)Y#tb!Sk z;hM%Fh+lnv5FSd<`S^Q_53VQ&p&AS&uz|yNAV;=VJ1LH@Z8ijzit*?LnF}Cy&q03& zmf~Vp*tWK3b;+?^TrWK+^_3_o)^dZQsah7lrKD0fP@+;2KW)0T{&;t zmmCLv#gkj5f}5XEQQ0bS^C}=FK9uUql0^OvD%AKVG>M~gNz79edkVh}x+nIb+lUDN z=`&yw)<)df+VYbG&-0P23X}ahEuZ`u~J9M$7A5-K|5qV%@4HiPY~}1!CU?``Cz= z6ExU80l^n0v>pU%rKU1^vbANW&fAz;Q?f34VkOBz2-0RzuxBHNZx=^{y`19d&DP$A zcx;@kH7;usREP2unbyg4TWoeb?qb}ZUdKbyi2jPI72rx z7;2-T+S%j@!cuj}N`Y8s68#h*_`hzIe4Ho*|1CCkg5gQR^4}yDJCz}9J*R#=o4F41 z;#`iuCgEXc#$PgLgZT1mqeWAxfjdiL$~@VC9jH`C%mthBgu9Z znk-fQT;i(&V=D9I=40lWi7qw4=JD5?7$0?QH~xBN63KQZtjWM(JjSIqafPOTlbAJAsddlv2j>kh; z$={Ok12dmQJ2{VfOPk#s=LX#55{8bPWD4p(;|N9inD1AaG4!h!flQ}j+GY{;XBJ=+ zw*fWivD0c&_#|eW7Ab*1&7dVx2I|~f!ARC8n*3#eCYAfIu?J}s7EfvrVj4AzKCoh5 z%+y>Cgh37-m*gN_=$FH5Y_6vb?8|`3Yui+^wJE1v?9TR%x^jNzpUAX&?))Z#y)L~H zlDaHT%G>Fkex}Q!Gx@m*teM_()x3|f!>}b@rx-?kZUF&Ugo*7udFI6XfIHvxQy$RJ zuAkOfL6g$+t(v9a2?WVYG0=pnDrc%b6$qcXv1=u_T9aMN!SuoK-e9}%rL0DR3zV$_ zf@|4U0)-w5{|6$_@lJbpKY+c~FGNSRfqms!ihajxDKa%r^_A~O@jkk_%J-o7c05;k zW8$lG*F@>@SWYvpSnv9pIVJf~Z8KNYLty38U40x_B%U_fPo!(QFeyC~~hp^*o@kps9V`X3t(Si80veAGA~6E{I$zj)(2KV{d)VQNU>>*O@zkzvKNOu95~C% zLz^0+2OGhIucqyvKgVf5%NRoU19$J>#Dgt~JGZe8s_Tip8U*Wg3ItRKZAW0!6e6e`I#y~j%)KWC7wtr7@Trp z@9C5S*F?Y1L^*rwI{X*2!>3->zWbq5Z=cvDoQ*Ko;Q2Nluh$KXpP1Q(c6_1qx^~^Ts81bPkyk`+Tbo7U z9Cpl-K3kZD2xH#mcGK_i7Ky49@}}Jfpnl2tVjVJz0p;BL3c}P@fmHk47vY^5_}p6s z0tIe1`KQg#+}zq`?C-}Q+-C6vJT*KCuP({l4)>G6tKLq?hCwL<{H$sgdp5N=(q@NW zNbdqry&jGj3+X)$!ZN>R9hKgRG9oNFBaNjb8LrU6e|QLnL{~N2_-{VjHDB5IFB#t@ z^G5i;NbQY6)5UZ;r)z8+MQp{;=vCtuC?Vv~)iX(neWMWS(H6L(oq56v!ffGr!1v}$ z;mM4dG?vOm+dmZ_rO@%<4@~uvf_%KE=QxDrK<;`x9DMQT_b7;$5<0rIMv-O|$TaRz zxDdoVR(llM(j-x>X+}>@QhZc<6t2$HF#q-x>NzHIc08u|DXTm+ruZ$~k511Sfy8qf z%y#sg-=iFyuSaE{^^PQ-M`fRNq2hT==AlkI2Sv*Hzd1)Q+u5V=HkDrcG*nVgrZT-A ziL}*Ibq1jy;T{DJo3KY=xzg8wX~%mMs4m4O)4x^;DrB;kT4NY)jCgjl$+SXxlj;9R zLModYyu=}|M&}vt!_Lp=4j0!morVj z7u$vOW3@KZvg2*o6wlv3oV^(P2h+bTV4QOe5(EjEm*C)zXMpT*GY~=jhbZ9Sq5O;B zn0_M;_0=Jr^fwuV5R*74vq3Kv=tL{(cLBzy>{YK-qgSsMp{F-6d5lxLbvEfGh!e9jEEXN10%KsFHm1G`OCdZAthyXDWo4USAG0PK zsRP#r!C}*ffsZ$1$I%W-~bp_e45#x0@Fs;+=0du)9{h zz7nCPUu=Bv87ocOTWqa77rhD6pvqR4i(W(~W=3<-3jl6rS-@u19|cBsQ}C2$5QHYUgxnO+f(Cft}s2nG?u> zpZISA^sWA5j}rjgz<5cr1R$n;++O?FAqG>RBZ9V$z_z_2(+wuNO#H$r;0}A_>pbak z!qjB$d2s6y1nm^aKyjv`PoupB%$wQ4aBOQQ*eJ+M9)i|Zq2=C0cY1H~$3d$bB0rwl zu~1ztq3G^*bIJwC+IJ_RC_^y!^`K9DC+EH>^NwHv;y0)5hFdBSO-MD_N9{s1Z*4|d zpUra4T#mAyz7-_y%skr7=QZn>?|{2aZwaF1*t)rsdte{-JlbyOd(FVDan1|B%jHS( zVDmg$g+8gdJ@)fxm-?vZR0_8K}qTec)n$k`R*ObD~Ad$Aht$rAxABpAc48x7A zxm1ZuuRCaiFG=?Gi)eBCDe!^jrfpF&*I+Bwu`6!-+zIVr-p??p>1YenrdO3YaR8Zv zbnj~G4G}1(3+(n&P_WM^^N=Zl{f*Q7dQr{9JXo4R7Ho%W+meA`|hk*{RYjVDhQl3Aa&wCfz-_v$1>!1W;N}#i> z3tMP+vM!v1cKhtc!}oKBL_=6RP!CJlJWwz1kL+tHEg$v2p;($G|A}at{J)S~BH?P2 z|Mbu_`TuX;Ltyl$rXmdk0hV6tjC0egU7+qr)S?~M&5|wJVcmWyub<1kJhR(LYYNYz zt#+Dku6AM>-ee|D_-kj%!=oxWQ4CFc%1#5z7puFzC+cd6P~ zh?@Wnc=ff{Vw?Wk@U+iWw?2VLrnlDnJ0_r#l>?kqA#JQ zqeXO{vu7n*j^2U9+ZWM)1sk(`#p^7#hW-mA=G2#;12mn5Na-g6kU_|f{vk*O}&Z02wI*Y>0 zrL!mum6K-uLt*C9Srn#SXHl5{%Q}mizHj%}2O(*)b2SAztze}yWI>zvef`tf*Z(_w z?@V8>VOy%NUvW`~?&z`Z>zTFx$NKvBA>Z3ynAy%4e6GGeDO~I8b5H3|xc`UydiEX< zx35>2huPOF%){*K73Puj^^}f}tgmMe`Y8MQk09~6`g)#AwH9rYKkRzK)ROD#e~om5 zG2O5CJA!6E`Wu3FMC2a`26es~f5cxUb4Klj;2#|)C-dGde;2xK@9MyKA;Xa$f3pw5 z&*ZBBO@A6>ZlO~+#T6X`f)ZyEbz?KOs?6SwKOBVQVoAu-MIs6o_8`&*X_Qlc3CZR~ zJBF@id`x_}@n`RQQRA;3KE0I34Uq7hDj;TT>x0fu|P;{+J)FCHhra4dDE z^}qg`0Q*K__)Ue4_wSvXbwWJW;*#%6#>X-*K)9y)p#MT)INge%SE9a_pb2{P9SNGC zM}Hmgqf)uzwYT-4k7Hr#zJ5HoWc;<6y)la!b(|;SLV>q`w+d~LECY8Fo#xBm zNRM;PA+==8D@}7`Y`gjxbaKvw`14xBmJ;?+x0J9)e-=gQHmGTz@t-(a37-g_cgFVw zQ=`Ow<_h~=(aO@s_w?0dd_V7E?}3AU>k3&^vc?QTHk1uzB76i2^yZC)xl zat17Lm9(a)EQWNv@PYC=7MZhn&Pv>^Ik*NCS1~u^{Od9RU9+|BOMS$CdkN!!a+erT24edetjO}< z+LV1QdBh! zLx^dnM1s>Pp={>(%0bFXmq(g#;TZGln0Q`BT%0nnc~#CM_IKIDYQayHazQIKv3j)p z*vzW)uc_74Z81$#t0N>l3oDajQMk2tu_(doHn$1_bU)TKC){YVitE}|WpEW4jGrd$ZTp)$S)clO$MrevGeKm(!JCot$9YHEqmm(Ci-*mPzX7Zn$O4j}Z)tX*^ z#0RWy*Tpf92aLX+aP%9Lr-`S;9sLSOyNypLS_6kt(yc zxbY0KmU@&S!8*@y13vL*Jnime%Z1yRKP~cvcL8*I&#+FfmiA-avRS{CrZpvq(_^wBI-W;*yscEf9-p z7(WZp}a|N6Pks9kkGvFFWA65Z#F+txgK6S1UV#!|SNJ1di3h zAJZp`q&MYy*aH^Abn-GT6XwrAy$^Ff)rx z_@54p8E>mZi&2Ed9y6V0OF) zna9~MY6CLf&Thg@wL$b6e3Y&3qRI&D#~z>g5qNN#d7f*%CA|#}d@Ux#`))*pg`@C? ze4F}56CR@O0jlcT!B6%5Tlk+~8JV~+`Jp4uarqo~QnnrUZauVg{>TiBk~vM$-OqMNR=)-&#D==*v^_CdUp{;-sxp$&iO@vcS}S#&fS z6HCPiuH|S8ciwWNB}$KcR7cy>>Fs{KPZ$JC?z6KKH(-~@X4-b*##>PC_O0c_4bI(v zFmp15?hNxQ!eMP0_rB@_z&{Cs@}nn>kZzbpm})pU&^3sgr^EB89ykX7im(2>F+^VH zbTl|*uO7)#Y3&R&a6*<1zip%$54vhQd?P3EITr=JD(yM>-yiM zwAd9eMw^#i;iFA-*XoP#tu#rAg(Bdd1&dcKl-wuaqge9v4pAH*hq6k+pg&`~eRevV z&Bwri{EJACkw2;UI2ge?;#7iPw2n<2o}_avPvB?++FueA;bG#fh@8&?&*)1}R9P{SYLUkDS2C;?iGElv->}BGzm&n#!=Zsve~`Rfatads1cCXZgmx zqAWq((QB8ROP=@R*3r}j_PF0vMf4cw<2-U-K8vPvr~pmZ|A>_7ra{XyuIsmVv?kL1tjk z@y1*=fmU*@1Pxj4&bg*->gBEbTo}F zf_32LOeL!;)NvK7IrF-5B#>OUF5vtL^&+|2H_*)O!_9r@)M^i~*~hXr2v0M4vqVXiW+>x>n-o*<-!Z5&0ZsO7w>{$$b9ae?jY3EEA&TPBuLN(_PN@PS9B<8Wqq(Kutubt2ZyarQmEla&`iZBI#8SDveV76e-Vfs}AVkGF|h0oNsX zNMWLf_UP{1XRuDCjXu3il`M@ACKR3x9&7H43 zjG4a!l_W!JN^YQFQJJIIU+6DtHkd#(gslY=D5eYoq62djo-;ECg{9~uL_0whttikC zwg<-r{>fZ{tDL&dO6F<;)j(H%)bzTd{Smt~qplP>`T<6KzH!c3c&>4tfW2O61K8HZ z3wA~mlO#lPYRcLvvA&(&bd~2~n+M`IBh|H2H)n-P=G-CMicPXy286ZS;i-L;Rkqbd z>sT(X9a8R z1?|9O#G9X5Q~i> zyf+~zG zL1~m}VM-R};|K$D%uPwqW=l{7UC-qFwa590>u(s_?Z6ULA)m&O{^H}jW~8uEl(Ga} zGPfnDD)0bCz#EW_>YnHuK(t$jG-L@%8wZ`IRH40Q89P+@c-%3;G}aHxjc%;e_&sz3 zqh05ZXX!5ur;6Ehcm&p(TVG zgmxu#J)xz9ZX~oDp%)MuCG;{vV}x!cw2aV)2rVb{212_N+Dd2-LhmHBg3$X3tt9ku zLVFVWG@+2t7YOY|=o^G8gzh4=H=zdzts?Xgp?wJTfakaDOQ=HVafA*cG)`zOq5TNm z%Mkk$`d>l^5PBlN9!TgULaPa#N$4O#=Mg%X&{GIupq86n#IRtX-1HJclY~b2b&Ak3 zLWcl?6rhbviJ_hV?GQeAt0Z!X|0H4E$qouQsAld$*rq4%N!5AhEF*+9g z9ATl-7)pnqnx)AD(_L#ph!&plC`9aR)im zrFP$+I|8Ccg~wG*jtkgX>K2Dt@@!?6{92hMuU2Nor-RsgkNdSJ4o1k?wZKopY$`Ll zkEiTiDa!VHNhYT3FYnC6lwF3>ag^1}7QL8hZ~NzF@vUhcB6*(&3Bd?{xUG z*>wdRzHmZ1eCZrS$Ec&=*cT(GW6p6Bzbtc(^XORa92@D_-8rtOV-M%JnT{3C@d`Rt zI>#rv5cQtU@eY0oo#RtiQP8EQZ@W~h^|#>46B!|-ro>v%k;;yDWs=52Jy0%tF-#B(*C2A*f(c^;k@;(0lq z*Wh^*p10z8H=YmR`3Rm*;`uzD|HAVPJa^*RhUacPKgUBs@JBok;^Cxk0Z%WUY9Ib) z*@ahT*?m`L*>zWD*=<*5*=1K|*;Y*)3OQ*(FzI z*&SDA*%eo2*$r1_*#%c-+5J{#+4WXt+3i+l+2vMd*=1H{*y&UQ^n)jQoB+ce?{NZv8yG(+ z^G1~Jwdn77PtQC^=$#pA>Y~roP;<%V4nu>7WhVb*P~%2to$u*kHma21&KFqCjTR_$ zVK2(dnH$Vl(``PtfU=Y!JIqRX^YKgAcli^abn|f^BXPI+WKjx__BJ2J5#Qz$!11VW z^P#T$Bv8p;pvCmY#mKF@DRnG^YHXZLgn?%ewDYV_A!ysH&Pl-Y67YP2VHs3{ub2+! zy7_aVF68&Y#s<=e`)QUb?Dv zcQ{9V8GKlYh6KGO`R;%pjU~CCLkHWc%VgKc)hYg#jDIWhd<=0LkfU>+@2dtDIKA*h5bn{>O3){#(6@W^uH~T4b}J)n zGiJy)$d+#0qHmOH_HD?%arV)|X~u7Z{=HTB{XT9G&*1s<6)32){n>prbvDm*`3ccf ze#c%Lm!HCEaz#;Sb);!KozSu@!V+_G%Tjfn$YgN4m}d{V{pu~zn+jMsLYVJk+}V5t zz}6)B6s@ZiArVHaswf;q-8b!{{A(OIT#9clqY5lUIxsyn1wOG6XPi<>jisl$1u5GR zl--4y!$Ec0$fvN0802FECS6@VPDFsh%0nPHxRcn9l9<00!J%`=r=$?XzT8 z8(6FS|JfY1L$-d{Y>wHI8&Rm3Cpi#x&M9YO^)Z&TwcGw&2VUpc2!6%v&3@ateNXc% zc3;vIZyUdZ4q5BVF{#6HzSkt^bmw(>g6`ZwNVAg$>D$|jlOQQ+C+XHM znLieLR?qHo>Wn!AD1wm+31IV9w~u ziMsDl)T!p3tivQaYre->26Z^#yu-QvhaCr^kSGSa8rowJ72By0{~^o=ydLk( zl)=GMw#}hw+!UE>KZy!8--T!;QkZ0q=Mh>_vEc5!R-81+BCe{41HrDOxmV&eghgkE zSzr|jXCjBn#?k0EiOVNcin#pn`f}brso2(j3-rLRNC8)50E-Ijktpj7&}XWisb^21 z@G+Gx$(pKA2qe_L)u)6m>$42P8741#j=TnhL4@io({6dm`13NygK+elbDvcngo}`Y zh6ap5*iBet$kz19utA-PVKTJ@2hIErg!h#+CRbm`sR8gD;RZ)k)l8b@^5{YBN0`OjAc*>tSF6cl~L!7bCGT<5R2HbGLF--ua--E z_v@;|2nFlw`ouP_{HJ9)W=Jgse;7#gsT^Bd?qV!#>CMqw^a2uIDujAwmTv16aTHPxaOlfA@!}( zR*Tri?ak=3_C;#nz}xp}1LK!uzJ#WK9pp|{lHZ+@jB9t)_t;LDQ08@#E8&^!H)MJz zthVpa_Z}$1e8hjdB2rQ?Bxm7_Zv3y4YL_Tj`6$-4un7SqRs6LU^5d?xpf=EBUQ?Lf zqBMh&{w=vFL{W@xL_*QWz>uW`lgRIhNeo zWxktmFrZLE*gwkj%)ZR>;cvZ2CAao1UAMrn(_%QmZC7DklBiE-%5p-bu(99L!&u6h;6p`74#nc(~Ih8zD z8+ev$svz2Q^)b>WP!{Kj*Keo1T6*UqJ(uIG%2c!(7=%e7Q)ngeeC^qBl3CTD)#e6! zL8zoXzv4M5&ukGBFUR*lO+-==y*1?#O!*{_DJW4Yv~qVSxFjUcO~O%7q86D_!NSE> z$y#SOoEZ`_a&udvE%d$kxiNjbiWPcox0b%1t+J0v0+p=jymoF(qHZ!cP@TItvcu~^ z;6tOH%y)(PXqKc2GCQ6DU1|ojf}jSj|S=W zkh#60pvpc|ukDnnA1E58IC%rWAqcZw;E0A{)(VNknI6cM5x9CwX&MwUmE7ST9fSZ+ zi{NSU>v6A=vypGJZFh0I#Bgd>Yeh&OM5NQ}VMf%6chy$k=xawJ!90g(=~hwBj`iFY zJJ#lHf3DVp=uk3*-xt3t>Wh;4OuT&`M4?GV{oTO*1P^(czk%@qEwNJH_B;f;@x1S* zs2Vh-Ql%`j&c-pghE}=S(DQtLAXHr@$fIMKlabzY$=~XXWxkEsS87~RLC~^T1qG>8 z=o#0+;Xbo<_7r97&RZUar+V?NzvN6`oGN=K5>Cv`)t{FKd-MKg>*E+*xC`6GVKEpz zVJRkBXiu$6Zn#V5)`46J^^d*F+{z(+XYVp#j9qAU)87TF7+!J{*yQ;##)bJgDm!+g zH5VO#;A^ntF2x>%uYp3gw&o^iY-Uc%0VDD!&B#YWheg7b2}HtIb0o!V?YoR5b+D3kdD9^(Iu$K#ibeXH%hFXs`m zwbP!D>Xt!k(*oziI3N6dP?6kn>Rk4{Js_^x*tONZ_wpo?x$Jv6hhp}p>+rjNVy*{4XeLSgK-m9-o;^}O= zJc5F)UX}PN-wbLb#yLllScWfdeT{tAh@d~ax{ zL}%%80iZdOXSY!D)+Ca)YrgF&$!M%CJMlH&kNpw&zxDLZY0rJc-&-vhz(>?2(b>LB z<=Sr0od^(i7}?q(w{#F7)oTzMs(t#3?Uxi^#E$;@PO z?9NVhlHCAVjty1I#e)|8APkOrgRn@DiSFc{Zx?ag8t?P4Nat))r z1v*fAV4+){cj1gxUH;yzdB^E@y~te{oaLMfqVW$ass6s$$ctI46$l^9gL+*#75opt zlRw3_;}!6%oTh-kMSws73!X%X{TSj+3RnpoYqy0~=%aNXCBUdYvsC?D_}byEErWRM0`UZrU19&^u! z@-$;X(Hr7W%(J$na~x8B3_(0SWV<<{sBtZ*`njtXbf?bCA?j5NdRo-sF9%%H!4v_> zXVQ7vN(XZrBnzU$Mf!zE@JSNZpdt(NtOu6fa*$!2@g6kr?*U*LWnXuktQ%my3;?pP zJ5K5b2TBOCuaemS$i7PF;2;S>_SFgy01`!-;XcYy)(`ihi9_-;J`%#jp|ElY69-_l zYdVBC|8R8^yoWH1WRg=>hjAt9bJ7>_%yov*H0ef=@6NkY3RuFq&-h2l=E!)%4&Zg)$-ow7(c(kNu z`i7P7OZE+`@m(X`rqwt6k+hl4QM_1HPwJS*p$JLM?s;a`(lKB14(8B{rs`l^4q+3U zPf;UO-5TEl9#?^OFrPspHC3>|Zvp4|4f}rk3x!L;XXl4}CJyDj3qqJU6ebZ6{(bbT zcUPHzA}UZPZN;g3^~k4#jt3ove~tIky$+GX)wJr}ZOqxEyW4!muG!tj9J`X05b?mp zs86|W=U`?=`~um~Mm0shF&0OtK(_5^0NDs<2UwR3fJGFU4{q+77tGkM8gly zRn<)@j3DP{ts7f3&Tt$jd45(Bk@K^(D1(j=L(UeBla@HvAnb=S2!q@^fK5a9&tHUk zls;D+1>E&bWWR{{ zkPRAcY@cxHr_fDMCnyYV<=lq%d1w=!SU$AYF84!gR^t+8d2hPQnQ|{YR|<9ai7Xl# zR9L56$im6>?`Bn!g~QZ7V_A@nY^xeJVMkURFbjYY>ZP}$D6-bV`^EP~7_4jOO<8Fq zx2;4awC1jFuCbVVqW-PBzGutbaOYEYDt$FgD7rOink6~0HdSn2x2*(`W$y2w4AxCm z9kj$98sd)E)&{bXT?bA*mhezP<{Uo%Fg8lH6r=0pQMX4p$AV}VAaBK7u}v3#+LbZX zkR?T171;;3VnWa(w zP{21KFba4wURkrwCse_%C`i~N+cH=X;nI=P6;or8P~qH{n2oC{|6MWuaH+&%prtpW z3~YR%Ow)rvmxMA+92`d|#Bok^{c$vJqm|JaP)n0DXBWHUmm;EUS5aqh62r3H<4~)3 zs>~|NF+hMD>u;&b`+=*T1{7_*W}fVug~kbx&Aqy-$SW6)GQ`#0Z$3>+CicRX(Vywg zmOA?*3xiuYKV&BH*HEuY1>Zmio$fdIJZJVXo-h+L39+Pu~|#?tJXg8&BPeL6;MHG8 znWh3%CY{01vg^hw_b?YvYpJn6p&B`OHJZ1zJ+jMkTf0Fuu(c&r0bN}I_xP7649rC% zlCPpEKR?LNxVt%+AeE(?!0JO1sQGbn|1t##7H7SO$X{EiF-$ zBhqZn8HRB#&>J?XlNQUSP6#W?69DJ@^mGcGdGQWAoGQ z@q=&zDdsLNr;GigI1nGOH6ctK3S(r>?Mh6%ui$sx^NHu6?U>$`&hUJq?AcSzlw#dn zo@%`9ONFUSs=>qdER@i!o(PEaPSS#^?E!c~y|XZQxU)UlF52%T=M&FHZo+Agcs}KN z;88L(m`^#M0bHN4Yvxl(ja2Y0(pV@H>68r1XCu;WIId5+h9!9v=rr`+%&7QvSFXdBgz!L~fY5>7hJm!1;gBj8 zE8dDmqm6tOom+)9tFtA=CE95|$+~v^XxC+!boR0^>5Gvx##3iX4j9gip1AK48wN!a z(D@ebI*&7w)jY7A%2L_P$Q|rqZ^w^pN(8}gir}v?Q4$KNy)Ne}9-|WqS|@@&(wHAxs>A6$W1gmT;Vl*;ibMn9cMRi{6a|Kx-c7 zE*7g=dQ8iH-6JI1Wb@2NAZsOIa1C`sf1Nc*DXAO}Gq@fdtP?6Yl(;sai0;1}^~ag) zhAWkuvI^^o=(bX$mCBgLI@_}fiPX?|eO4;p&(hZjXI-gG@Xtp>UJ-}zimq3`pS*Hu zlf2@co#d5A>Xlb@kwNgwc4B749>H(dv)|`z&F!cx1t@Cyb_wEZFA=qnRWNb^~FwZ)Cwf zPZ(`0S+Fk_)<9oymfIk+5e_^A_wT!e|1?f_;fF+DNisHxounM;7cB!e|P~ zg53%j^^wA0i`d1wg!%`DH6tHoJ5L8! zXuokE19!LFa8qtyGh@{VW@2-&Bq8CB;vQ#pz6MS?9gQ<-{@0Ka&R)p?HtpZVFE^t{ z0lNK9;$T#ify7_DOW_DA4lc5lOatDEDl=R2Y6$jN!= z$y}_&PF6WSgBd7TBOBWYFWEMQo|!XT??cil-K>PxfnCrDFY}G}K)CAxP_qFVvp+ll zno)HxtJ7#yaHWIg2H8|_5wK|%FmWWu`OGHfBZ!SdL1QT!XO4(0(j7rUCcguoz3^}_ z&H*j|2&ew>MLhT6Ar}4>2D7rSm2Ow+u>8cf*eoLSNn^2H2k)^@c>KzV-;cbgwWOi69qXjg9P_(49Be;(iYUu95Q}y$Q9;{F(!z~6)9yg2;I=; z2`3xgisw8$Vg2_GE_VJGa`SSOr7PFf)`bgKqzSU!$v(ZWAoRo?DE#n3xaNv|JMO^~ zK2ck4_;?Q5l-hE`#|7JmHtzD-)r>0f^O@PLYIE<6K$LIY)5D9C*yJNF%a&wqHfA-8 z2}LLIKLMJRwn9jgM~aE^*+@*A9@TiSJK&bp(kF=TqxeZ{1$h2v0j3Q34Bn6${-^K` z3tLa#a5-c%5L~R;bJkrZY%^|aOUl0nag71hU6BStUW?g+#C^6FrB$Jy^oou=fb9NmYWo-5>#L%3-r4eyC-a~1$O|2!L=7wm-;{OiIj zdtJf40FV!R5$BzFuK_JmJ`XFR)Z{*C{{w0#AG3FowWE<)b&jEbarLZ1s%_n#2)~Zl z`qP2jM#qCs(NQE`T^QecILlp!fM_DT1W`{1UWUrl!p$}VG1 zXe=^3JwatpuK{G&m>tLri|o~E5V5cDk;jliA(chBXtp||r+v8u%?3X5JNlv-qG->- ziN!FSK8GVaF!Ch5GJs?Rk``_fTI5J4=q*2&fUPmgqz5Ji{uon+ef0v_PjjWvhC~TZ z;=K|G)4~B#->6;bOfxP14G4w$C3B3i=1{-lm2L4quU>Me5vSDjV4SXIi75rJkR(Fx zMUB4~Vcb^#bBNY~D-giNA}6HgUkks9JJ~YXn$`R(iz-^A=_Fdpv;Z4^tY&D5l26SB zCJ37$>Ot5}E;5oi@=P-Gk))g}13>ne!w;>XcW^uB4Ul6W7J9@PLUjzi8X+d`s>%?Q zFFQkOlGbD>vznnLNaXp|d-N#ixP41_`3`Z;{MaLr*qNy53m z4q0+-eI96ZF@ zt#mRi+A}brLQ1m%Zru(U0aqT+?%{_~_fXdY4NgKM>#`n*iwUKMg9U)dib`5FpUv?N zW5ArBWyAP09?al5TUz}H;TPc94-ePlLLH+p*dewqJ|guL$skZ}7D5^PYzrk~^kQKI zRi8Qw+QElE6iT6tX6FwGp6QY{2RT3Bv?3oL75tG%0{+v8U$5|FXQxh!!%O=J^y6q9 zrq|{iUOFHk7RYka&;Uhj>w|m?z)T*STmEA8^cEgw5Gb z=>zzIdh!)uf*893d}Ov{uu>FI)a80Gx?2KYaWe)CNyyMLpGx^(VlL$?-I|&`W47Dk z-vW?bP_;CZ_HT;emm#nHi7@RzJy7;OjKMDkl({oY{U8Qlg~7d?o00BSEW6elBb$zJ z_|FJZGe)6erYrg$3Ma~#NX<3|)+WPmNG|rND!6$H=VbU#++8InsolqxyYXQO?(AxY zmMF18&(v|Lfz&9+JII43q&k-5WC`F_r)@GKYXlpU zB4}>x5Uh}4r$wBoU+MU8R$lha3{!@q3u6ic5Rs86l3tnO3dYeXG=B!J(5zD|g(0aQ zv9CA%6hfwh-$x-Sk@9IHl2C^k*$;WO$fT(Ig-l{8p`v~W&0N$~j94Cm8x6J>d&IJ+ z_m4{)nk16mq)kjICiYdysp9sm8QPTh1q;FIEmT4uHDShY#FvhG?W zZ`Pr%3Hul`osb+j%86E3w-dR+(V&^&kY-}Q95)3$tgjt`w$*}K@npmrY=ls}-aA4k z%D)@NVFEf2;HfbtW5*~QyOL@r;5ijf+^_UH@5lE_)LRj)qiXhHZ+IzC&DU$v%(4y_ zH;eswO4-gDDkCR)W_M0X<^|o%el-TNdZI{HJXC05@JQMea6W1oxp?& zMJ zI_AwgVZ!QAG(Uv0=%5U50M*?Or#7V5payjS9{!QR_~3p8)8kREW!J_oq_he@2Axb^ zY7e$i652OY!6aOXLwWX!ovF?ioS9-TA=|>xqgD3|CB2D3nul~1rHfGM80H8>`fU+{ zqFS=>^MM<9Q!BcUJgl>&cxZJx(m^Hp2{C$MZ{-5KKM9^xb88lZ*xE=sCab5tBsJT1 z*}Y?~Wf2((z~=c_W65 zsK#=E8djAB!>6P&dFeeyjiO3Zl|^sM@L9ddohfEb_%9)(f?3XvkA{kFFU~H`LHVyE zUBIo@Isge zt_~s0I_8!uKyW_{_d1rZpHN)0_a~IEe}Zd4@V&9x_fhfXst|lHt@iyseA_k$6g#nh zdw*s(3cpPFz4vZHC9Vn~F4g-9t{TBj`IyMV!;%Wuir~9lweKIqm#aqbGvXmh6 zn>HC8_+?Hu5j#wbGq6>dxD<;cM_iN;-KHq=_;XTDPQ~e(S`H>Fv1(LYG7pKE z6*gVH>bKU|21dS!OtyQf!v{LkEc1?Da65dm-N9G+>IuGtm(m*s%0RIGtlS5MBfj^c zw3LlShirZW^3mdn9jx+WkV2kpJ@VqMM_$#|qxf)aN=z`7=YI^#=i1xuON9trXq}+- z(MocV(d>=oz;c^L%g97dx+^26lrwTZdF1QNT6*LG$)W6kh;rse;sZ)EAtIHxKBtNNDu4&OhjPfP#6;vm^c*1Lbs$_V`~P#P5mU&}k2ozIiM9|x?NJxgLQ0>Ur6b8~C5 zLhYWVY1rhs9$7Z~jOy=0`4`A66GkRf-Lq%GyHS7*xf|(R6m0U{NR#YCDMC!vJ9`#W zkHXO_f2$t#N>9RXea@bJl<|5NFT~3nCENNc6aum`H?%2$JQh|K(A}7!j1Qo_hopNg zBhOuYL>zfZ6nVKsPK)V9QGswY9iF;R3pgbtaYmCrX)(hXj%jN5Nj;9`I|^Bx(I8)% zO{m`{E3@5*gZ!%yX-jMA$^G8PA~*b_SRgB7rij53$0i6!9Gkd-g^^ROItXEa#IcFT z!T`F{5qYD$y2!$KSf5GX|H0W#cHq5Ac23cz5bCI zn{1DvwAXLOp(bgspNc~r{PB=g2LTkTO6$N;!U4%$>qj#rblK3V(n>+HL3WAX5Tb6l z1#yzI>~kA5`nU?T(f=KZ)Ko#~7bwO0Tq}DuR$rUhj#qqf~YX4*aaXR*_e!$GakM#C4$*S~C% zuV;ThxgYY_Pt+mmw9Y_Jo3HmwH%@lRX@%0F9ts!kQW zi2T#pw+#A(+K2fPdFQuH^3I2mQJZ&esh9DWdB^b14xfGzcqgs`<(+eoNKNy7ad=1j zt$DHBxtYB4hbDQ)y(Y;!MSRy}{AJ!Tyz`>;TX7XA@0?q&3SJ!EG5r?j>|*}8h5YlU zCi&<2D*oxY_GSLTFhSPfb)?Jj9SpvTA;ybAoekb^#Z{pE^K`u`cyaj$qrjMdZYBTx zwMqV2d0kTeoQ3a~vjtcfL&C`A3tyb00El z>pefJm+_bTE+cym{OpUsJ8=~#?|c}E)HL50hj(~xoM+j7h#4uFZx#oHEnq(iVd7BO z|AsJeDC{x9XoKWe_~u_@TX!#jDZ^vM@!9Of5{D@_IGZiAd#=yeHD|M#y6ext(nyGS z_VuWvcvevS{D;t=$Sfx&PL_oM+;J8|FJTa8BG@TWusYY&$%$snCxT9LZn`k|YKQ0a zzQVTme3NYtyXz8dufh4xY0SI-our&{9`BJjRNZ;J3hTl?QG5qUfzsy0V2!bATp?fB zbNJt?8;T^}kaPHtF_lTh_dhTnHO&*naZP9w9Qa(LCb&Lx_*~RY7|GTX#o?UC#byy} zWGOC_sQd)<3Qej`U=LTW@-sj{eDc~lIyr|f4u$vx1sF>Nq{ zeR8=o9pu%Y4G)ul7Eban4y1jeF<;QFCJVe&m)qs{YJ_d|Ya@Pbi-mzM<73 zsJZChixxfr8#nshZN6z|md`?W{O3s9^Pj`&EHYCVoEe?_!|o9lBWTAD+$=}XscsfB zm?ds$=M`z}LQj7;6cDmg-&ph59p7HC2YyGl#bP=0qOer3CxapnCd^*)8Gmn#-9X4w z9DWl4?4aRCuw)_hi{kfHho3J12C|34%P{VoIdh7|kwcM8g(WPlM)+yxj4|Cr&WKxcc6*$&u#{3L_Dk+K zDWPhNZa|eng3K%f%R6wOJ99={V*g;a1^7vA&~|YNVfp991yQ2S0?^e$b1P|y+sl%; z2qrGF1>aFT&1>hO}yMdm3 zfbMHP5_bKn7)dj~vMHG3!n|_~lHs2kr}NaFBs%}xFjr>Pq@=|Xyh2ho6KNTY z$;m_5x|pr_QoYfzmWsFl5I*P+nO~d{FE}5=_id!%I7Nji^x?!I>)-+%P%utjyJ|U5 zDrodCkb=Q)F*s?{3K}h;N0t4u*x;o{%&-y5Y;hIFYsWUsW0A5L$;6G3Vtzn2;xfZ^ z_qjqwFk{lUhI?F*J=uHv4!jwWf3%Cgl{(P`Sr1kP4j16#O41f|s~MmM^$xo~R-5-? zlXoBoA%CFfF3KUcC$IShG}xBz zt~`a9c>Mw|b8JQqQ?h%gW4`+s92Y2oMBmw)v>@St`vKc<~>?>mu1E%(lsEiSUlBzZ*^`aa%|h0XFEsKvA} zmpSNA`UxO)uf{?o-iw7D?r|h@_@H!M94UD<79#OpEbLy3BZVh$PLCsrWkzs%ZfJ7? zJ^xfRlX!cYWH8#Ewj_@CGxCrf??fafXWnFci^glXz2z#iy#;#C$nS9dj(-MNm+g%@ zGtWZs&mDP12U?{=gM1^G0evMyrwn>LIrm)7o$IU`L1|#+$E&=6_TGrI?tmQW$^p*QN50+84$({d=O99x7&%`j+$0AtV0jVs z^H_%Y2>W`7B4<9H&G0ZJ|2P&o81FX#H!zdz{!gKYU|;ubc!}W)IcV z(|(q!Y`NtgpaJQEhzzaGI+%oCXrnQ*~ zjs#?wCpWPp9a?&>KP#in;kDr*9%J_g+qG!-rp4I3(IfIHQ6tePBD@_q04f;*@OYwr zoOm!>g97VWdmQ5=qO>B4&%9F)-wF?pEigR)NJI7o!+7?`6Y5MyXzo4DvFl%gO2P4Y z)ZHG={SY{Jfd;OB9-vAIY;qUgeF8bc_EEqC7dj{ma?-h!;m9aBZbf2sl$ej!xKOy< z^=?)V2aj2;HjD$vZJFQ^c(iI!9|}ok^uhLgJ4@Q0AX$sdR)UTZ$tYri`++7{#N3>L z927E2ShJ~L4)gIm?2f2%8aPJ~i?HT^X-B?;$#rOQNI`;K9MRtxC+N&~GFWFKSFLL6 zz$!D15NT0^$C0|SJa+iY@eLY_jawVe za~sR>jN=LUjC+UK4*BQ$Jdz^J;`%&YVw|**B2MAIg-!waxEuWERn=)*X%k?vY8328 zj4%&@T20I4$fjz)A2O1u*<_RPf_oCo(jkaV)$y!LyXG$&?2n!zD~L_)MTkx1CGDko z!F>tDuzfIwS-@W*W~^O(ll>)t;&R&vwVN8%X<)}gy)}l z>^e9Z-#g;D5>HqMta}dI2&cXm!h139WcYj7);<4XHLPC0r={Xo$ zr<9eTp7z)rDt5Q8+d@Jf&t~;?(mvKd?bDS-+*}dMcjjX$p2P4kJpXzJbIu`nOP=hk za2#%((1EF@WwlBF?^H=geM>vgabk)*8>WppN0uF?aWSEX9=iH_g(vf5V&+WjEGawEvK*y{G*3O11Zbq{DFD$?7fjoAHP zMslxn1)c~d)A30gAyI3O*UB73*uO)53r}8zcUT9#gFViz(=U$@{u!vx#!RF1Tw%u9 zPV9_(nPm+~-mplwg^X2OB&|eIVm!6R!B!KNac{T}z{5T{EF<(R@)`7v*>XmWbr-ci z-hxDcOYXRDEn7>}+YZ;!`So!1qIY;2z$c4+n5XKaxC4WU8 zq{pwyV1c%_Ax12q^0%=Jpk7D0vwqWBpIFHlW{;d6n}@DpcvEqruXe?%rJmE4Mx7q}JGvz~2xu1M zco)aUz^?0ZIt%BO5B>s1Qe0a%rREuZOBUOv+;N8oiz2I+(eayz4wTDp!E+0qkPd~x zL!9rSZ@!QGT6>*`Rs$mD#D0*@Oj>hpdY_BTrCHZ!40ywbBaOtR9Iqq}<{)t?hd^IJ zXq-~_vYrT_R&ivqQSZeXFbCJu!O@@y45PCWHL`WBRC`uKw`V15Y8~No2$_{*@so>mQ2oz%)v55t!6k2s|#1;2lDOG|L+7Zc+&>J zk$7WSJ)x)5j?%jUzYuQ{hksa0I1Z&4IM$r8z8W9K`EkN~u_xk0gxdiHPBc6K5)BW1 z1FMAh@1$+cl~tn_1QzpErt#g~xbdMNVZTUynYs*wpViiuITs`U51_5d^i@ujmo{;? zi(43&j%pRGcT)=cmOvr?!1T!SG!#L$&?oQ7T~3C* z{;fL|-|Un<$9a(ar8a27dnkDDRJWglF>_-1*vxjzrJMxHCGB2$o15y)sZVP?q6cJ~ zde7b;KnD|Qiff$Ouu*uWaX+|#j{fI zY>)%Gmx6?o@910CXh&a1>C-~J+O?0kp4eD%%X+G0 zxCoLsWBUSh@X~gS+OwFM$gec8z&ksY(z2N$(WET zdIDDlCt;sh`eGb2zE?JiDfi0KwxKR=NSfiY&6#n`_;%SS<|onYIIC#K4A*X!#WCM? zY)v^gBZ*+6)s7i1;MDAXJisidgm+zGqF3gRI4`#`l0m-VQu#m`{dGJc9DUfa8=*Kz%N~mZML(>t5A$3FP@FAXN_bhd~YSGRoT?IuD0PUgT1<{(jj z4cuPv5I6?f->VTZBV*kTG5c+%1fN0{FoQiOi$+V^@w$#6iDqGX92m^(;5R6^DG^O~ zP(AH<6Oz&G%;nV1Ggiq=5;8)te=T#fT5@wUzUPz1i@4Yw5eXL*v$H}|pb3#8)=NXtOw|vEZj%L^kzQza&rS%Xgh8H{#LOr>jVrXj= zfTN(0ufwQgr}QWMB*0R)Yq8hT)GT^1tRV_66LFNDW!@{J=0CwWp8+LAW+nnE zDi|$ojEbIRUQ`sJ`Ycf$S3g$^CqqTgGS_k=RM!(#S55wvLBk$fb1Y-Cr97hViDjgr ztEnks;`lvyD+m&a!$u|BDb-*tE0tnx5Qc2DvScEP&R?eVi!%5*W)Ry>lPM^w#gn0; zXZc#YtTzzVqf*CKnu>~Z=?!y5&+|vuB7PDhcZmlU`&t$ZsXPI3`gzAe##U4IUu}Z7VWT@y_=9+wj>L#L6Zmr1` zHm)`%J3Y(XPamQB5>Xj$wQw13ZNY2=RCUdy zCE(R>Fh29LCj~qg1m@%E$HTv^^%ebcPz0;WvlelhAm1W}_7-vaNLDpOW(}0TED0ZY zJd$CGd2^ymK4bD$@-$`WnaBBo&)f_9!~|&rFcr8#*g0O z5)2{(ee(nKKe_(WHG~VTlJJWJPUGjHGQ)x6B*kOpkmBQmpN#509W;@Bz4M1?M!{cJJU$&XVTn8F$Cc)AQ{A zDteZAv!kK?`z$J7+zgfDxt6zqi>qa5@8FrvV~~O0nwoE8U8Q+CfAXcLb8;Qa!>7sHkcbB`d^e14YT`5mv}*t(RV^N9+ahJS|ys zyK{P~sWuR+!_BvWbvqhWw2thC&C?e{c2~CnYc$2>L?gR74`ieY4`3K5XPH7dA3|YI z6ryHGh5+S<-y8)HXbxgU>=%n^QL$bus9<>%k?is2rf0-sQ~KFs$eB!lvxRQCbZI2* z2sOy^Rmk3NA)}v-tPmrkVJ}l0LJhJx44{MHfm2Ls9Jw=uHDIRody^?1m^F9^HF)MS zfRZJ5UX+kP8Xkr6%KULW^~I~-Zw9w9-5?&ev#x;wQgBoK3Pp}U(Cy!Cbu7)wotL<0R3V) zfF{(aRme3~%TbqMs~}*MfHH>*5ubdSm3xA;3W>6`Itl@0jy$3$Uttt&ND>8W#Zg0& zR0xnkOcdp-h*HH7;riIykan%kcC^z9ovn$nMm$l{JU{&5Ka(F|>>HhBZ5KhPVT~nm z088u>Y62`{fLgIna4hyAgkxFH`$vsvw#D`y1Y2U;7R_?UV&vz^Rgfmp6W$g}aNZE< z--eo3^o@8GOuP?5*3OMpF%0-*a-KQJ`8i}r6MBBE=rzwXJ$E!7pQe%h7h!xliH_ru zv^wS80_V^ZAPzP9`=uchl<1wVtp;nC^3Uq&JS*ZTJuwSOFE)Of>n# ze5Dm)l%D0^*r>inRHjR@LRNPv^wKV6ORNt}mmiLGaP*`Zeu%a8=J{dSB>eCq^(m9^ zgQfFYP5ad$mrT-699_#k1l3_53#@e>i(b(Wy}$|~x7pU2qgM8@0xGH(syWdLF-p(m z#PS^$`&c2X*@s>+`+x|?0Z`t4UyG;j1g7co)o#vLA!nNCo8l33^L(}HrRS?@>ng9K zYA&l-jbyqPoQN>G4Un5cL3;w^uydK~vyo?8C+|x>>U1|ZUXB+Zny=#vUivzow(M9hebfu?r8v>y zqBV*ZXrtjG4yz!Nt?=5TX!^wpuNOQRC$PzJ(Rfs#jS`qd`b9S>g)B$FXo@U%-mw<{ z+#9o;M8WRHh~*>-0p%CoVnw+RQS`ws*385bt=SnUZK@fl7eO2KCskea58jkx| zVsV@NudBPgB5)3?vf{i-EzITSzHY61&c9dD%V-cPL@JTv5+op z2{DDsXw@^HULyik_EMB*Vn?62`t!Kom)lr06t+|FNFnx=Mf)jmmbv^!lw3q}J~h=~ zYFB1tPo!MLnG_>;3B#6r?r&?b*pbJf4RHR*}FMihEv7Ut^d_8ef>A5 z%iIuF59)dj=+|7&*^Q7>&ty*C&pqyJ3fb3${<3U6=zZ5qPw(dRm;J3(%FUXl_ZD^O z4MUrN4}BX)AgHO_gtvkc1D4CH!8*!-Wt-$wCUJ!t4n51fk|EM?9z+8y9Z(+?>|QoT zMb9!VWJjnTA}Y5&DwqXrjEbIRUT_ql`Z`hJs*hy3wSe7|p`vGb<@>B$eS@e@sgG*Q z$xzX=%&SkLTz!+Mbn~o5RLvDkqc$!eJMbGl>_EPCuqS8$-HK=x*3>7`g&Rtfn9wsVXR<1z>+o_EUNY65@_D2Q$ z4pCi;?jz9%l^; z4~o}Sn%8097*e@Lhjq(Ot%!!oJ7aD_v;{BN1kxN*y7`nS8uEj!|L??Zj1rG$!Vr|d5+A`kayW_6ePl;#7Rt((>yFK62R{Qnpo#Lw zi$Tqo|J>%vpW+x+4^Uv|Z8(9D4xwJ)a)_!_q4UM1O7Gwf4s8H6u@(@oa5PVoTN={D z3tpr(rsi}bd!hJ^0|ilj}ew=b+~3`j2SksCl|R`=3fzYZvSmaYOHCL)SI^ z-hJZf9D@DtL5NO1dZ;G+~7BFZ}oK6U1Pk(T*D)?XB8cOHe}P zR4u~-YbP8NQ@!hG8d}44hm)SnOQcoL%Uwxnbl`hdslr*E5C3=ZM zKyq{K4-lnV%bRK~t>la}SC7L;Zo2ij;y<(=8|!W`vy>iNL{e|g@v;{XFiJqOc77Pw zjzrm&QB3Vf6atd9^P@VoGkF^urcKOd#*}dv*t|Y*#(!wtl$$@RlRRH?2FLyzeEhkC zvtx60z$NeLwvP|}XV!rie1)^-dPM2V$fL{`DRe`QF?Vr}X^yt>OnmeFecyj3ZQU~O z3NZvdI-agNmeW!JUi|4^Okzqmcb3uw*P!@)1t!v=2;@#FUX^{~O~Azr#|z8>y)xgIunJ;dwY z&DX=9U#^D@UJvo6f#&OB>w91Br#G~|6z{lbz8;Q$xgIundx*EIG+z&wyj%|(ydL7c zKF!y|Loe6E2Cs*Bqg386@oYTo|QA4zc+WzpQ|m?ovYmk ztRagtFWs8d^!H1DoMfGP4%`bqiGYc-r35ruEx!aaS0;*mwp5}tI9qx`9EHou;cALR zX|T?$Yh98t`yjVOseh2$3qFlpR~<(sD6wteTFHt9)}`YVb{HX>2%HX>0PwUL{V>#8g`oVl!k4VcRcF$Hs3A*-2-UJ2%U3V^AZ zYw|UoSu^@^Tf{?CpB>-^g6Z}OmvH~iqcu~3zss_iy^h{R`s(4+s z4yp#n!}Ls74XSu)unsDE);S)gXS!-o#j9I&P&GInrf0fpP{k8)bx<`p@}y_FYEZ>% zJ#|nuIBBN4t!q%l%N2D{(X-A;Gu=5_gDRfcs)LH2bq-?b&e0lF@#K9SR1FTTT`M|n z4XSvarw%H5Hayc+gDRe?sDo6|p?ibjLw6%rrIyZ!u#L%1INm6s*hl%Dv+l9{2NE+kuI?6v(k*vZENWJ5CRPUbwEjAd zB{}!X*M^DLyEnGp#jJ(FHfK+y$UofN$~!UrntM4HjPrg@%{r2`F5T1^iCZ*D-&e}L zgpYt`Bab1ExXyDnE+*@DgU0u((K?jgf5fUmNnl_~?>)1w2y=s9Vh>i=0P5@4JowlS z{O0f zLt6X^Ig?v{al2z%>1oMF?R{o3UGzS)i;zeST}n40cBXsr_JZVZEOLCG8RwaL+RS}s zxCJzWZ`^Vrmzk9ruV?Y=<9NKSL`lVXa~baiP_v^|LqBoAFNfQ}dk4Fm%5W&%FO+ zHXi=<;*OagV~!NsL}U3e{uG+m5bMJAd49^|kM4l`jDSu7^$!8IiVBf9uY7s62PI1z^Iu<1h~zwCg(VU~9VM+HAZzK4a2yz&jFK$J;w%3nPM zF)*{CwPFfycPoX#H#naM5g%or@+1n;OrIj62~-I0?EL(z>d4M%-P!p~7GC=lj^0%6 z;Z7q+FWfG*4)hWEl^GIYZSLc|U?mENbq{kN=S$x)y_xmF40Opwp5}&b{}E&tG7w$i zu-~X-YA@{oj&y_CjwvRtc1%wpk=l;w1<)otS;y3FI;NjMuYxROl@o8gFz{ zdM^O5hw+XC`$<332}nAiRKajpZ`mA=WAfIus+gxRCRP&6y_M`rpiXPd<%pS`yBLib z<(8yr6F2VS<}v9Vi2#yR?vcbhcp8b9YPz_)&6StVRf#@sF48l7TzBl82PgXw$OHzE z{!SbU>j`1vP?$tPcw(WhTMWa917UJS_J#ADH^ZIi3ptHo`WZUipq1RRnf z)bxL&i;VPj5|=XYb$H@Fa)sleZU4J{WL4h7KC(gHr`1PtdM43F5-@2WDHA#k`beRD zqK_m5(m97Z2>VDWO(GB>2xNDpQQ2Plj`WnTqfxvl9ckE)4ngv;AAJDtu)mz7AC;z} z{pdWWA8}Sq(vQ01Y(;XHvpPZ8c2K_`T^oJ0?|T@jYhx7M)Zddz5k(XFG$t2z!^~ZS z-j%_o>|Gfs(Yp$u+1^!h(x7*x-_*S;$80w`*P)B}KKs|-fzg`jUuCRd^{)$FSEmb@ z)|jn{{*@*A59?oVK)Khuf883EwCnY+F>$qj{Q=rrZU6c=%;>I9|N14y>#;jIPASKo z++22Yv(O+C<2bgA(m12eU3?3gqUj%LFDmX}CF);ra>wdm*-u3s>@X0Rm^8#x74z?m z$(~g@^>K-rHeIt5$E3Nds+i9*W_$s*#0)RMzAw%#ZEjV?{5@mF7hp@w@B-}f;+V8R zRTXn@k|@3aTVjS6U>_RCq{*h6!lIt z%X~hs2xJB}pEn2^YL*gHG|Sof*(PZ!X8GAB=5k~@+iN$vq-MEMq*)g71*2IOg1@3L zwVLIF|B%U(VYj=o3DR)=eLyXaA(uM)L8APCa@+wZH`0aQwoLip1!fs+q{M+(5zurd z$ne!wIUOj{n^flWwR$7`mOr!kj8$E}3-8sN@_YM>VQGUvg>6RIeitQRn-lgE1hK+x zLD)u2I*z-5Fh2?FC+yfHY)iscC1E~c=OtmUAnff)*Z^VICSh9<_DB-8HDPxoVcQV) zY!bFDVLwU2wj=BVNf@S6|>ve#!0+jYU z6LvE0C=w5aEhNl84KR8rY!||=CB7I|BJ2UyQ4AX<>^p?fL*p(Y>}1BJhr)IxY*iAr zn6Pt`u%(3kj`+w78h1Hi{uY4ILt(oSb|7K&P}uH-ImvK)5SAm19vTi;HK)q638RO? z_9AQ(!swx}y$L&wusGd)2)l$ZdT6+P3A>&!dMIoKVfPV64~6YV*iQ+ghr;$J?4N|i z_zoa!kThVOcNcw+E$JXa_a~HI-Q5a3kkB_0$_5aIJ%rG6s-Xu1D(!mp61v#7+p`m_ zg`fxS2|}~dsx{OyD-`QRLlJ6+8nQx>Lo^hj8fw59aJ`}yf-)xSoD5O+L&%tvT6=hG zvl*-O`p473ez}%<&^F0Yd)7^h1ge|~^xhB$fmtsjApg}Ug2*L8Qjttukq~fd;&f0k2qdvw8m4c z$QsBvh3(K$NXhki2}n3adcrrr4c(N~GP$Lmu3rEoxD9h&agkj=zQNAS(A^kEW``(< z!{ww;9T6g?`9k&czk!s)0Dp@DG?#K)Mz1XAx>82(72$++X5OML_}XOA#(d#^a}H`s zo8rfn2$i>>$)$o@QSA1tCdNs{tR^OCC94)%E*-c< z#fV$bu@oiI)5j?Y5U0eSdQ-7A)mk|eIdugb66q~b_C70ESp8$mFl{;{_M+!i&R`U? z&LuHN>5D<3kC0|%PABLks@wx8Q8%d*mA;6&aU6A*I8~YfAEKRXw{KRRxb#Nc-J-ad z4E-6F04n@(Wg(7pL|nH!4ey08Q>jJO;v5iVfL01__@ZtJ`YjQYQ9FAe6Y-SIxAA$94M?+nRr3IL^r z-YBTw2E^KqhwRA?Y1yEIwbtk#jG$5qOnhrL<9xfZFJ{7Nb0iZSD5zPp$7y)5>9-7< zy5oe;TgI_fMjLS^$g+?WA4&xcBLIuU?V8k((uH|a<;*7yJF-JFNw3zd*jPsSI+zLJ zs4=pI45xNL5KL6|!b{2{10^;)43T2?GQ#1lQI?BJw7P4qy@MNx&6>whC!P|?^;sU` zp0|irEAlOyEIL@;Xx!h2qqHX~F+J1+XIjazNYZR6|2j-FEf!MKLdtoDiY?_gd^>FH z9x$Ya-USS3DUfyTrNiLP20Ot$+J*AAWyZL_W_W9WGh^HUG)$3_8RG_?VP-2c#vMjj zZlaTWCWbH#;b;xClz$Z_mDQD+kA*8W*)gD;!GR)IYSOw=QyM|k)X*FGEBS$WYtG|> z*inu;TH^#;CrJ=-WNqjUrYQ7FX_CpsArVUhPB>@P0fMYRim$?(k@$zM#W@SlNqBya zC!EVF3~ughiE!)Kjy$O&Pa4`H62tSk1_LSNINbxLO4A}Zv^tbKj~gPk&Xh8Es$5xX zs-`%geClbP3U_)2Te7imkq^5GT8cp@_(fKvyAe5Lo=p~UAf9gl(@4dz!`5sXY(jzb z(Efm@r3v-TTDDX^$jfr6YJhf@?x3-83jWr7YE8SFMT)+aVrYV^6*hK%1e(WXdMYlH zvqakxvKthD6aD<_ox4G!AA^QE-ig-N8}BucsSdDuxGr?!`|C`tOlw`}4=9#d7vg=i zIvm}OM8LXGS+1!40_2MS1LQf_A3qtXFt5Dm;Tfwkx+-&hjDvSBC=ON*6qR_tg0-uG z_h;0GS^?}Ea#zC@$l>IZTVCVEqdu^Ay~(Y(26S@kH%O#*a_bosetjmlu3@~M#UB!a z$_h@rt3fs?aGX61IwdBzs6v+5rM-s-F5jpFn%4wsFx2!;(quL{F_QgmWX=1$>-e=vQ84N z4IlL#P>71ME5URvI1Uze)HfxAC3FLc2;IP5Es;AY?B$mHccXN8{U;R4wRm~{gDh07 zO2xJJ6=2rKC)H_4&0KnzA`rS5=`AY&p;EFbiK9v+R|B}7U{-U|6;izP5uqOA)hr2! zf+c~tBSMkuk^to^RwWoq$3qOIRR|u2pI1Hsg*7429q1x@iCRXO%bL}J8>1NIi}Bb2An4R-ILQ>WW7>3n8C>Lix~ zg2cA3$z*IXSKyJBF)k2MUL)Uho>MSWJ+Wjw?Pt1OM>ns9cl<4wgI_HOPp?ld(kC^WIi7x(7rNmi-pT zIj2Hb{^?|W35JGSA#Im`b4D;O%PlD6E3ZYW`8-`KBi9L$>v(Zhj>D@fXDGl?y$s=M z%Pl1abxQRmWz)h?b{=m(&D*S<)Igo6?&3sAb;C>z5{DJ%Rbn^%9 z6Y1s;+;5o<*iHfrc~?56|d?5z5RD&)=50;j|F4%mXp9s78|T z!}GU+H^?gXAca^9gvkx1j~8aoo1+F=qk7cf!hgN+LhDd3@Vc#QA#G>Kk+J|2thq6K z_6nb3YWsuagnX)Q5OOs90`Nla{0{(!a&@7##H(%HapCyZHHBPPp{-bGFBUpV_p%_l zd`Ey1<@%0Z_Br_u&<*GExL#%nwZkqfl_E&@krJqYb-=#e7wy4-g}!|kNed|Sy><~r zDO;bg&@H@oBzIxf#UBaZMSCx92o#xWMj-Dg2bc~#F88{EdMU17}KvrWRnk~x2RSye+T-U*l=?;WYy~9%NIgcYVI=RwEBmaQPxEf7>@{${tX;0Bu)Q4*+ zs(S7e#Sz6HBM(jzwhU2mi?n{`HQt9+VkZQxUrG>b{hEK$2Jv*?Ekji841%)N3n}vx z1lt94@rHf~m#5S>PZ%hKSlko+xqlN2#fU75oYeBaLuECs^K589H+wWn` z@P{*2S=sl&1eyims)3MK*c050=QccydJ6KpUUYa>H66}I1}32cdsstK0X%;zJ}UL%BMcY(KS^j zA$0j&_>MboLuC!7`77VZ5EOEfx^kP^xdldt{5FP%YiTjREpRS|JkoZ@qnWAhI_208 z9-2nIVnB{jzr#fRzD&jy)y{tgEq91w!87D|zW3 zho_0&Y)4lW)K03l4ydJS9lY|#b{)8)xY|vLbXBOKf@G7OAS(3Th^#fEk|I%e4-@mG zb$1dfA;4qT-MRSIx_bv)$}M(&@|tqYkvk*Ulr`BC)g*QD>D44-RM#X}LJ$dM?K<1$ z@y0As4^dcW^h*%Gw$7sH<)0#vxZP;I*fd)IIxGHUsyaIXi&k_Ln4y4qB3roFDN zU^e7pn>~zUjZ_cga4HJxEbh>z@XP9&E~4%XWO5)c)3J_vY*&XUPwP71?#Bm5C?a+; z1Fca%hry0>G@k##!+_L@3WFWa61bm=>A(>s#5)E<7!q*_M@Gjb5YOp?DwM+;id2ig zkmVN_BsAw~dIwu%Z~sbYYy#f}@Z37;RGP73ZXMJy%@`tt{VzbGqft+b^R=;q0iN?T z@+DhnRAIu}S$dR%eyCqvARiZ$Csek7CYQ=j#%ZAYc5_1dJI^pW8VKj>6GH9$=D9{kV_f0CwDF88IB>tQ5-8%dU1T|@_fs;3ApF@yzo*b*n3TeIa z(-UK#HCP8D8x^uej66i4&*Zatc$&Pmh9UfiQ5nKAVHP8$nq@?m?vgAiWx^}Enbp$( zuN7$2TH))XD?lZ%b5!x9@oO7*GCT#jsyJbIiV0g7B*W9!7ullWal*3>zoD+zm*08^ zmpgxj!um_L1Ldg|tdShJYAaTWa8PEAPLi1qTwo4nQljSMu2kWlh@>G6cK(a=L&}l9Il~irF7AULThH`~myAKOG zjL|fw=DLNiYdMd1w&t@osa3n84K28 zx;5pes0<#1pF(R9yS`gx_>2K}Yx!2(#}`~gA8gE?vxq`4-`0H;{d8)e{V05)jd6Hn zCn7m*Gjxc@PGN(p9$ZN9oCzKeF~Z=S*)hvKoSHEO4aRFGt@3Dj|RZBWK_U?;d2(XA{?e8!kjR9X=Yi5 z<(G!VPVhOHGoavhWwJ3w$ZTpLZ2In2gtH=qoR5kT@=L>Fe|NV**gcS+J-|I2{96Dy zz}|0Xyjhs9qZ)1a?gq|rVqx$j&Yw`Zzk=KtnNRuC#QuZ$Xa^@wymA@pOU>%{i@Uzn z==3UQ1(NGq)u&fiBFk#XLGEkOu8)15SvmXT{+Qr_nv@$>V7v_jGCL_ByC- z&B5^)>SIE+TXQ37NLc1L3hGkr`5N{4f_}4qQK=$bUTJ$~c zt<@Dr|2fW!p2B>yosKe}SgmT8cjV;Csg%EP+G-eHYBa~sNP9!M?BIal^ z3+nodK{>#5rIsBGrhI=ICKX1J^Q>3lBoMTCjdHgFVEu#D;ZF7HH^?%!4?2Y5imP%C@d) z!wO<56VKGk-YhAyu^U25An_LBdjq{Bz9EuNow}_x zBjX0FTgtXpj@Y?eYStwBxhN*65J2{@ewUm@Wjk+dz+k0^tkq^%D;+GsK&HahsBLm+ z6%$nV1t*=)1S)K^#X`2U7rmtA=Cf8@}dx5F{ zJ>AQduH)}We=<8$E`0Fxil%is;{pc{$necmKzx_^W*)== zLPG4@om6M73)sL@bK&D??;%g}S+RQ}OJ!*nScA6rG zJZcjhuGvJ|p7aA^<3r93Vs%_gcO-)3Se8TG?q#I96ch-!S(W-K_dRoSEdSg9hb_|O z3tu0yK4;V2DivTT#=?31Fm3dTdCZh|>n4oqFduh1&_XVN+%f24<>87bVa&6ihmVPI z5MY?o|MNzM(X4P>o2NvJ0pwLKqlZO}n{N`QV)J6ck?y_@^TD&+eVyimhq(J@nh&1d?we&kcx<~b zZ$5ZlyKlDn;6d%ag8ASH?Y=Ja!IRZ}bIb?NWcP(s;bH8)kSt&3M@W|kK$pIdFg$YI z7gC0Yu=_&N@bqmy@?$ge!L!wU zo0|_Fs_xsueDE}N-vaZ&^VNO*=7Z;*`?fS6JOSP3n-89%?t6v#;PL6c0rSCg(|uc+ z51yp%+gd+Xlcj{OA{PE81Y&m2ZNPrjEW9ybPx{()x(a-6}#eR`!%{7h^rO=~mx-CTaRklzLJ+b_Rc%C9fKv}Q0c zLHh**6SP<`FtN4#ZX>_j%I|jaOIrg26Wh!04)RM20s|8}$?wkcyHI|2k>8U1Qq~Sk z49o8#`Q2517t1ftj}J^Nm0!x}fr;hvyPN#(F28%o@1F9zm;CN6zx&AV0rJc9^aB$- zK|e6TGxGxz`}3FL6Y?|TEXA9D?%3C%?uvkwK4HKeyC(ujR^71&BY@=2I(k4|Ydhy3 zAhVIhd+q|9&Vl0sJX_(}9uIL*Chv}iz5YRX4#)EvJSX6J1D;dy zjNo|-p10z87oPXxxd_i?c&@~AHJ)qmd=Ae|c)o(?PCWPH`6iz4;`t$-$MO6e&#&?P z9?xI!{0k2cS+?StiKj#ZkzJwKRuTT6!&{BGO8IHJoYa7aCX~YxT^9IYro$yQ{<#5F zg>c<1I0PR!0nAPeb2{SZg$E(^E9D8zdk++el-UGs3_@9a2#AFT$K^5 z4eE+2wxA+@8|I7XnIVs3Oz@ey(4 zB~j$%5;+~5gMe~y!Yi+Uryd6aP6agrgVx9Om?7FrO8Pt`;J72N z=)h^3bII5;=T^Cp&WU&6xAMLidXYFUn1Qet$I$o3&P!tF2gKP6J+yKeopUN{^mPSa z*s+dX1777Eexxez;j5)`Hea2o%6WLR4ed}op9XUVmoLe?d~}1aW;%MU`~6K(@MdS@Ej(e zWB@)6A7;uiIG!F~L&K5@Xk!K$Gn67G#)(fCj6%)mmHk-kjkdtU{2hQNq!;aal=1yX z-*Xpfi&C?8F*FJQk6LbYMzQ$J#6vTJhb;2^MtL{A3? z!zm}EJTogS+nzF*V15`x#oiM(@!$zy0`aaji9WbvoG6>87n}vzZb5xkevUCx)$ z8!|)g2sD>;g?w)O-wJ=TZNLgYVQ?>aD#Gnm-pg42n^6Gti!((pM&Th~0UP{PfHwoOx)eEXR(I^f-UD2GdW+ z1x}@(PyYttMm~<8&Xj+aCRiBUM8*>y+lj{d$ia@OcY|h&2u({3-X0;Bml8Wem}zIr zPfK%`&Culm#7*0jF(G7`AXUC#`*7BdjES+nRcr%MVFbG`=^;!nfU89~VYh2qjC)iI zD|5&&)q*l!!ZNz$@9c_1NMNyb-YR=5fC&pCsg^GM`4b^6wsH<-HREq;T7(tVBb?Hy ztnPNE{cC}(Gb5buc4qwR@ac}TUououfnk?aS<4rmX+z?MJKl#f+P&d8`>^8Dyo4Yh zx&m2DW^~6d2S5|;^4B0u(Eu-GURp4oL5R+l7XQ=yHo-ukPfFgThZM%%l|vJ>F5+q# z+7}<#Nl5SF^Z1_;JOa7dVkpiU34UY&-b27+1at*I;HwyXN53A$3rvd~b@{82B;0Is zR0N^BK<5?lvP=^9{I@YvrWp#|lzMXFsr#s4B?N{|ypVB75M|G6$*(G*7D%zWkE+m@ z=WSxLErU|)KtCW+OAF|3L|@8z%r;zUy{pkVbe- zdEdwKnv5PP8C@q?la>--lWguW-LuM)@{fyhd>D#<)DNfw{)w{SS&;=^WjB!p{8gfG ze%wfNNP^#nlE8mQSRX~_Zs7QHEdRIoWh6bq+7O{?OGD*Ic5*gpml%ewRwIUvLBMqI z9dr!s*={iqlkHJ^UqYzz4oFg3YH3G7Nfl1cakXWD3r5A46amlptFob-x1zv@)$~Cr zP)L)%kS4z~G}&Ef!ryu{`F%u_cPUMvmxbh^9lEZfe~x%?^Kt0rT=yUn-UWQzVuo$2 z5Nb$BfKHBzpX;9nP*-Z?^LRnSXz|Y_BD9C1x>$#;&i=rIu_O)vO8xsW9#`~F8CiN~ zdR}lK8dORqFS=!aba4cG{(xD6X`1QaV<->$wv@96DT6<4XWk;@)wq=m?_@>89yb&?ScQ3?>@Vqu8+HqFocFA=V;2|24>> zaE=Bu+Aom=XCnsE-y}M(V?^3g>S^j$=EZV3(Ov|!ii$&MRFp}X0&kdllOpE;`#kts zIjv6BRgo@n{ErY*(N6FA83r>oZT3SSBUg|Y_H;fB{`o6-*MwkqXL>gOVuTVS8&v z3FNM;&B|)`GU)=f(o}w*Nc>vxXxM@?_rfQ_P}$)79I*TxxZ32bqJ^(#nP!g)mfs!+ z(~ef42O_%~SyRbWsJBa92v+hD2F!2l~v(k*Yi zDB&k*<($2c*5Bi_SXd0tL|&BFgnG_^xtc|-ynznvi%K&5QVk*F`R_-1f^)I+2zc!u z!083|Qe{_U-&<^20T!@AH6LBCQS%Q)z`4t)->RNJJReTCd=gB$z|IsrE$c2)pPNh2 z>d^sbLEUkV@2iIhmtu&ZKEiH#Lr^?3P?GdCK)vCiP9F$n=|N3P zO3w0&Hi3QQBujW)BhPaXBP_B?jQ>a7o50CcRQuzddvD)fW=T3dnVuyZOTuLcFal!F z1d;*SWeaQABrGBzda))WNHY;oM3K!6G>Q-NT%L%EKA!?A&t1SR;x5Jo_Z`>givRET zoT_`Pdu9^w{r+2jKHXh=ojP@@>eQ)Irw+~GtoGNtn&>Fr;O>IjOMolO4jLA<5za9vfHP)lst+;y31<4(lpSU9(C$7NsuDR za$iYqMcSa!iyJwwg$p9~;n6jPDbUhCgqDa;9rxzFC@2)NP#q;UJrhD_qyMy%5wLnAXp+(-7;3ar!6JtqbD~c#t8G z{YN>u4ux(*Vq24_51~0jEV8l?w&|+m-Y@~=VT_?YEmy)eW zBDbRh^CJMDtyEa!B%(vN7TIM^iV|W9OVarw|D{ZX zpEL2TU<%$r}V2{jyuq-2EwJQL;y%eZb#iEIi&m?u3QoHaFvJN#(-ZjswMR4dW6r zwzA!y?vbqx-U`n^xBkk?M;lo%6`Hf&)S>GskKc&WDl)fMWKQc=le%8Q5)x9LtI_x; zpH9uj#_Ii$xmFxdg#)tc3bL}}vCoe0`b)>blMr1pWvpJ6#UTpUIZno}g;W~6y4|0y zVuOhVpKp;+J&@2+kKEs}Yn5`Gyb*ok#+eKbguR8tsofNgZ9sWo%R4r;VV`VeLmzSE zTV+2RrjGy;oukUR{V|Qxy>6&`T@=H;E=J<;=xE`xpiuZH`aeP+hhuxf7Z=li0IA)W z4**lWuhuuT`dy%sTA#Ic*#~QvUju|qJS>MX8Y7jOZ;i{FJ`jPK#khvy7-;K-9MC0b zi48LidmVjeeeCjjkvfwUIaaK?q<3vX_<>UphgpRuPq?^O#ySW?7a|#NQ6irH4Ulfx z#t{M)O7kP2xmMLVbQQv6B9*&m0dI2&(bOt}|CLV5k|s4bVHK*Cx|)0C4dQjxdRJMD zlRy=8f~c6^Utb^;S({&5u$lLBT$_4T&9ewl$!`Em2$(y-?Ak_JSh$`^4=(Sl=erHH`GEKeLfoSqhdJ(Pmb#kHMY`sN__5u>+p%>%)o_G_ z9nWqM#PbmbAd1E}Pj`4s#!C)WaoUyfgL$T#Dk03V4KG5i?# zxh`C2!(I9<2xI<_;Y+e$`0(f+uxeGH4g~l|p=#Wh8d{CXyil8Osd_%B`oqZ3{60cG zs_rS~L|v`ql-y3S;!&BDbG?Qv8O10gfT3p_%bpg<;NVSz2RLk|hc`<%`s^xns z6z+jf$*7hur3mL=>y3_gi0El2zFEnZg9*zf>2{sa?Z`n#BM6@(fHs~loP~d%zLvsI zri&aJ!ySEH1vkStmxD@*5xn7;O_N-gKQ3f)dsoQpch=?N&h6Mp#xq+qeC8!^6Rb#_|~ z3Nq9003T9k4dtt7lZT3vUqm>@O4OC!e5=nvVfK>{4n#(SKy1;@Z9gm8U{iFhZHDl0Z^Uv9`rneRa1aqA{J^ zL_h{&lcQKUAq~e!SlX(_dNtB0P3(<&i@h=0%TwR<%P3GT`S%2sm13Dz%gr z*#jz8E+zjCSmaa^mEA0nX~m5jMQBz)%tZGAboK-21IQs=p&vK~>m_oB*q@RVBwWWPuGN$vPF7v>m8p!y?IYvgk0z;M7DL+WfDAy;92{sRs|tpRqh0@y}NEkA!a#LXrD-TLDsRb z@O!`p<`3%(r=qc+z}x&1e$?Nu-LoA2YTSApL(iW7o{iC~0p?2_$T;a&(KUAotC2s% z!1S0!W%)R4A?5fca)ct^P{{_?*QzJkD9Hvh>Y`vl*8^^J9-kMA#Zni>H6ncgh_&*W z)u7Z!f!W0Y;~K&7Xy@7zoc#wbMOWrFRE`H&q>YR4C5T+hsn5nq?Ev7WuZroOvw9;r z7;8wEe*=z_ndrz@n`A3XYIeF?oP2<%+APD374}BVrPx*1!D|xd^DyqcH5m#$$y<@a zn$ZhPG{zGF417f^Y~^q(2QesyoWGcheHC1@!HAI*7;;OHqAYAI#D6IBY&+u~iz0eBGrfiFA#GFJgHNRFSLpvvzYhM7|zya`G6f`N@*PqNOHpNA=pu zk{pb1Pr0A~4v4yf&}m_ts*%3It@7UPFj{>W;?-78v6OxVNZha>EXsp7x-gmHrftcH zzOhk^rMdQv4KKPpwj5=ZBUt_U5z3jl$Tp8dygm>iZCwFxEkgQ+Jm|1;+k6Dzar9a- zUzlY<3xz#ap|mb&&(45ywh(S(Vfd1{U^#AYav|KHvBC@R&DZF~qEq&wT-HMF4%#TY zqkGi2g!u!64<6B^yCO>Dg3_%cq3%SmepVOE3(a2%5O{;?7?-eEMG?br2Ik9<%g2)4 zY@onB8@{-<$RQ^RXOWz`L=8DHCyy}Y@excn<(6?TVlZQdvB!Zv|P-W1fGFaTV zbrhtoIy^x)PT1(xiDB|#_`5K~sfCt23Q=WuZtbWf=YplQ2fB6NE<65)%O%Gtcs4n& zAny1X9$iw{6YES!xTIn|lIw$#XS#}^XiJkYO<{J?iK=9C5zd3maP*UBt93dbX^YKI6D1rD% z3f#sSMvBvit;R_eF*0vX?*{^82GJOX`2wOU%91K$u@&i#q4+vhDu+`nseuC~J+u;i zBiz{&_J`MDPsfB;vbzXRs|b7}#SQpO;Y*qLb@(pF*X?H*whCWz8^jR9sh4&$+|exf z#yqB2U`JuD&yi5JI6ycSW=M!$nnAC2T31G@FggO8+yeP7%|jkOb((0 z;i6%3uzJRW5E?gqeNl3V1RPA|8fDdO2<)P|u;frl!*ldva+tWKti!b|aUZ8{>PEgD zRL=UK8!1k}avEcMmo3Mdpm!dNz~|%#NkiG?JKj81>s?q2 zTb*VuOZJxScI^CrK2P=kqdSkg{2C%%uBLOo2JkQ3dCa?j5~$Ejp_2b6?mU8aL9z&^#KOU;Gky9J zOw-u^33mha$Urj3vaz=3;CmosERp!K`kR29*_}9_3S&#*@pbZ3fyah}2cO%hqw=H!)(P3RXsx1qyj_CxzH_@|2mQ zh4Ix)9*32va#{*rpgR3WRN4F!0`oA~7vYF@9kIKcF7 z({~t|mDvnkKuXCqDZ380r+CPCTLMsy@1Lk*CdYRy5@SR7uUT7(rKX>trXc+(e#b8d zj4^CT$h|M&iMSW5f@Wn@6~jsHM5=Mr8;b^QS1?ZCO6e`w9E!46DZL5KD{zGwE$W3$ zCDE$oUPR0MmO1CQ=#X1cs`=shR%me5e}P06U-do`3V*J8KYkkG+;G)@!p-}`!-cP* zOn&f2+yUeqKL&T$`Z2C*%1wu`^;0?pTSfC~R1=B7LM_X4;D*Ra729bh3~&es)+&~h zNE@Mr?XPt(6DFzs?4Z+rixf4lJ+?8B{<8)>351qqxLnXCV9)53>y{~6{loSW7!oSVikoSPOd zoSOzNoSXJ7oSWt?oSW7yoSViioSU{Socm7CO>-J9oK{Aho8~W^JAt_g=ce%s=cXMC z=ceTf=ceHb=ce5X=cd^T=cd^U=cWw}=cWk_=cWY>=cWM->%NNQA~dr-!o!&9Es!*w2`-Z=cYcFmp9`Mq4EeCAsb_AVeqzN1M~NOg|8sy6pZ0eq?|=L?!Xw4xmuJ(7hoW8T&oAu z8TO~RY&rD^^gu%)d(1;YQ{T?hiBr>Iw}^E7b?H9ObnCH) zh^EBJ7Co zL2yB*>-niqFnmD5KhAKTC`41AVyIG4lqU(MvLu0@#Cm3wB4xW$q(~-dE5%C^Onrv6 zat@EC9>@U*)T7~&M2l3WBC?}^^sRR~yE)z(YQ?*M+4$`PDb9MT6eMxuDEDj=Sw^*( zOnmgHj1sQ94Y3E)!*cYJxTiEFti4F*M=0cP(5$6lt19~R7mlsmW}z3s{JIa_h_$-~ zF27~beb)QodaXGQN|lms4s{3C=x&m_%VU@l@JK?XOL$<_MiIHj+G_x}>YSIP_ZkA- zivD2BNO^oEa+Lx}cmRdyaY-(t2l^5SI5mt(t5h@FF*|{*kM1lsP)_68pFWeTsThk! zoV5#`QgRohry(jx&%6Jz7#tC(Unzuf_oZ&@h!vQOlkmo7p&GxQO+12~iQrF8}#b)O47 z9DxEEv+v1zfuS&>-%YC>h8ujE56JoW7Wi;}t65v8rKQDhu165+opK7<|*7 zNZJcp3j5Y6yvgS(1ioAD>~G@?*%g-7^>^p5Y-Hz7h=ZC2>>T1t%rP;@2P-@exiB>3CW+kgprX*G zd&retjMA3qz7jV#1PWb-VS}HLs97#}?t@3oa=~-#24}Af9-0j9Q9?CJ#eQ6!v75MIp??Lz;hc88h&1d7M++R$-2@33P zK8HSOsS7!cAr0rlk_uzw&UYYvL(az~s=Usl`3XFpP8p*O6P*MTQDDl z>QKp}Q-U0pO!E(JL#q8yMjtFj)HZS!b;_jHEr$>Gx*5jR7B3sUcf{nBq!?@pd-67sIUTLa)Y6{U~X9Jv%~tK8L;m4 z@f_9(xE-vg!0ljVu1)-TBCrBF!U~XySAeXr{%|I&w-%EW|^XKMT!7L=1~-ZKvVu76vZK= z{j5b*8k@VCoM8hQK$;V&@wAZGXXq|NZz(N2AA?~L;Ono#6acxB-s15h--etqS|^KE zS5eHP^fY%y+KO0v#)D9pRP{CDA7d2t)ghG}+X>mB;Bp}p1A621T>K@6fY!$-FX@F? zTGoEB6p|wSHe@Lxs@@CHQEN*HRELu&ln|Qz&?1{Iw@|Heh1wB&c=qx0|;zBwKFI0U3TUaYLJ|a)tqR~22jrU z3h-TR*14f0N4q;!Yu{!idRZ_1(c1RdKTuy>qe=NwP}KS=6$Pcr^(agXLnG4M!+z0- zTw0YS1vu4}9?B{{%07S!khK$K8ZrmUcpq{*DC1p8mNyH^BOaDN1s*Oo{4o6M_(HZ- zcnn|CEI$m#P%k_UWASv3T?XRA^Xf~~iERgkpP}0o$>mB_=9UB6Ae|r<&VOZ|S zc9cXofccB9pfT68Fc!Sa=Gapgnje&^PU0xhWUw6qMxxs24$>PCx>B=I&1~?rL)lWS z-}1#@_E`=WwkN%Mn88)PX!+|=lASz%AlnA)q?pOx4^P*j2E9U^Zh*6~`Z^2@T-92F zTtRv!g7h-fh-KH?!o;S`^1?MJufaKA3}Y2#7(zJ5*2E)G`ZeIsVn98xqVfZdY;CTF zrF$Y(L#|G0z(|;0iH(VtCes0s${ZzIq~sXzbEq71=feAt3L7r$cc7rAa6q7tj?j}J zE=c!+Q~50Rw%l%m?3JOp2!>hqU>4GXixuJ^6pY=Sv7G&)yet6`qRVO%7(`90kS0#S zLRKR^xzNn2k1w(5>4;qWFwl-?>_OMDaHuyE{^T&=A4(b@#?lRwZ6Cp3IQ1u{ z>4Zs*^e528n7$veBd|e{itZ1$HG1+SDof&>Xq zLYl6p7NM+hKL1A)OFbvyUui_@3DQ3zy&VWz8wNQnpQPfMP_lUpX_OxdQo3VZ?xez0 z>i8k*Ag-k|uD7U^6-+?Qk=A7KfM%{VM4U?ldv)x)^a!+*@H_vJ9sc7w{Kt3rIoAFB zCv^Bv?C_u5;pZI1{QE0BVS0)NWd2jtKW^irbiD*PcqwA=>!)zR_p={;KW87`&)L)W zQ<~xX&+hPZLi6Lf5%K-!cle*x;lIH8v-VLYhXOKxOA}=NE7hO3e_8@u`|(ttoZC46 zRkr**{WTJjm3Or!$ov#o`1QY}!+)*%^YUIQ0j|E6X>>+EFYoYQ-{F5nho7sFkG~r` z{5M&DUjHo;lEHtoCUEe)vLpYiI{dHh@W00T^YU+%kgWXIY64gOZ5{a^= zVz$qnZ=#&XIqr_e?BR#g?h*aqbumZpiCDbKE&{}40!1W;fJ|<{sxdEah=@*jbY$33 zzC-8C*C#4l16X4NkpNEOL=oF@kqkZ6%2NL9C ziAChXJO5cG{#93i`p(!33Uav4ABeiS{z5CW8)c7yODzQR=OuX0yP68i zisLJ=vDNBAMO*T0^imchDS#TEQqoOFAwU^6R)vE}$>wu$zH0P}4KQOHx^k~+B%Zfu3PgN;+X+)+*Y@Ph&Vd_)8x zHdhX`Rq>Ku z;pJ=sB8M@!MT>;0#yOvbmHLxoSxPB6AAeRS>wfkbc~$!q9yXkwC1MBLO@M9kIO&iu zR#?z6-$MDxr6?<2Uf2N3JI5md_<9Tg1QaF;={mOkgzdDwqkF%I0>kvHES7z&&atxr zojUU_UA+28gn}ZNSc3Z#gDgF93iS|}RyYa2D{VCKAmSREzTeV~)J$yyv_1qX1C!Dj@U{ zXv!NIR7{=;keZh+T9e0mS>^24SrGo%s6U zJj2}&-{bIg^T6p?5+-3>rdr%|Dt=+e@>Hpu>lapk`2^5a)H$g=5$%FpoWcHScDLG60I^bLDUy0JQ__sXRVAEE*Dvf%v z!V!lE{GE-z$qo1^Po9I{I&3(c%a~~LJjR@lpY&Py!Qj3?!=If6$q89h%m8wg#9h6S zAXSXz262f;H0fnPObIIC>~{sZq#&0d+uE&g4_dyHtiw@q3X-5fTy}9kntLCa0I@Vi zkg;CQg5|rSAZ`b&XKBohj8L42E__`g$ydV@Dxtl-|ZXYvByStzB;6 z)*jGaG~aODka8cAoFuS$WE-bfBWPrw00%c{CZXdRP{$qB*WiDLZHkIm)XzY!S=+=B z^nVMy!=uX!cLP40m4VMOCyPR~bc1XQ<}@ve-2I?@i& zEM3OFckprE;raB@_&WHwhY|)9VIE(s#FjorY;x*@Dw(i0W4-WLo(C`Qu=PC4Xvm$3 zUA2vN`r&#hvuxEHEy>x)5~cSbPMPor*==a79SZE^Vt=v$sb+7?KA0ytd|Rv9QK;2Oq!I-6xMpyI2h_q`hNdx0oNP~ya>P$Zl&c9m@G-5$?dNV5TX8AD|$=+gm zCF-!*p2}vcTiIbQP(iDXc~UJt**M|+)UA|f86xBQ&A#E=-fvNgy+bS(uA(%AvnL2E zIese2q!KrTtFd12liM@z1}v|`_bvFkejOeiD%=47N*PbG-yy1jh73pDO%j6T^@$@G z2p1elW7R!-V{M!?R^8fIy8(Cy8@rHY3scln!LnS@RXH0gT+`0M_l5W}DL*_@*jt^L z3a=#Xv1#ZLboewnqk$uvO$^4=$lzkSNkSq2u8&TLEw`b^}Y+2Dig# zq!(h!=GGzGfY`zCkm9A6{lhg}mjUxj%)*lwap}1jKP$Ilq0~*5tl^W-K_DihOYmp@ zV;o7J3)kfH@RO$aS!tsN{xUO4D=2HZ>e>3fnWbyI?EGFt9Q2gZ`GAoY3uDnlfOedsGexhetEVbc)>d!d-kdFC`D)18di6tpP& z@C$nm!rc+s$hkA(og@!TmwL^iVbEo9}FosY^h zbmt?Xq4tByhFBgy!S*sllLkn1*&u@pl{lbv0Te)%n9~Z&WBf)$P1^Wl;h%y(68=a- zIc`ptn$ZT)RSms^M6N7BiZ{!uW`EFIV-hAcA%elr$|g|Z;*LgKXwJp29N+oL2*<^c zSddi;T9h-TFGO~%ek_D--%0M_Bp7?MjRZ_ObB+WXHQPvlDPfc!E2`8p_eiku_s%s^ zw%#{02J@Z3b;T^hP|GW2{X`v7Zszz2l>-_T=NmxV!V^YvDbKuwIKJ@?)V2ba;7IwC zEi_}xya z7g(X?Adq35Lv*S{7-OdY#t)(5tA-IsTBRI&6&sH|W@O%oYx6~SB+YzwDw0#+mIPQq zKXnw{)bW0VtHYDAaR(rSZvl=I>cClh{cJ*8{SuJXUzWK@ z>Yueta9&xN8Ejgn2b(c}LT`lW16V4}{(q&?=NYc66+cT0lnab-txR8pt{&5+a{Lg4 z2Fv#A+jJEIHxZxd)o|$}LFqMg?!+YNi|OQg7$`t%P>X8iC8!A}N-seIYkm1{5L|j2 zDbmaE^^Oc;x#wC}L7YMc)K{0yKZIO^>iTPFL;% ztb3rni=AG4I>B=QVv{NfRCAz8LJB)>E_6_IY^jKlf>A=UVRIfz-IBE6s|INolJY{q z9w@rpzlN+zEVk-Y4IEnFo6~MroQ7rB3_b^FV^L(#2({FxTI8V;Ykubv^T1+sg`Ed> z!ooaFzlNfHD=E#r8RJUY8VP?7V4SRf52jT$dfei5PRJGDlyd@Hes`fyrBe?U!s&hK ziKh3&AJ+C#w#L{o_%D{*xbZa@L6{u3v{e9jhevlQ;EGXU75WKw!Y5yb4(^)#CfW3I zBmFM^%UdB8us7C!2>;~I7gG_cltv)+jf|^qBR!PTmm}}DLs`akIL?!{*73I2VQA0T z3s8?b>v2D1b7#QMR|v#BZtDmp;n5N_Ch1PDM{)JaHb|lHSbz5Q>N6T#98DwlQY?61&{$%Pkcp|VkYxIoT{VGXd72cxtI?;fa7)O_2Gqk1)jDe4HRJ6;oHuwV#EVFQ*@W`&+Q*|-qhH|6 zrV4KPRTo*p`+EB75%h-p>Tw^R&kz76^3sn406i9%qu{0ln`v6lpa*VVs*uG-dQi}Uxn5!e-9F|{aUMTo?Z!vgBE}FFbcQ# zpxX=6>kLu`U;2I@NylH6v$seLHLT|h+R_x`pp$H{6PPM9pIQU_>{S#bL@?NkTMRU{1*LnbYB{b;&A} ze4m&&2+3W#OY?M>ccxpLrxOUK4`e;C&&~Q;tY11}BS!5!3fjlXgUT`lpPvjf1^0h7 zoZ&F5UPN>DM%`Fm`}jX#3$>g=XSQ1JZGzt`;FN{uH1b|*y=P&MYLrWL^8<4O;6)hZ z+Eu}b9sD0X4TJ2rXs6P?eg0L3!7-?OoO4W2sm)LBW*Xf_$+V#ZO@xIyYK~>{DwAV= zou9m}BRzs{W03hIYy4e%EI{ADiG2)XTaR>l_57&)3ZMgBMjw6$M*kh zy#c%Soq0JRpJ3iw3W2M4**rKEu)LmG2_O_HC9Hh#Ne9fWa^Ofj^;CjNiz7*<3p2(N zu^*_)%sBmYL(>+OlHMJXZpSO3J3rpn5aK5(Q1J9CJj#G8&Z@ zTTQdg$4bCprNy}b46r$u0mAprXr4Dj%%w=yQTD!}Et|c;vJaO4l+F2rWuL)-*~^|4 zb->mJAY}a0;3ahIL^^ibk3$1<9tu`)m3rb9CsXrc26I0&6F0xla+s4Nm)YE#IsLY- zD7vYCIc^pU*>omOGb~Y=bRn#?9j~v|;Kx zBTX<58OdCW)F2t~j6$oQ!s5fueU}6eBG~ory$s2F7v)Lky(OFY;@KuXf7Ub~bC9)# z?qGlg=4Z^N^MQv>ukq)UvjnfFlLOZ_zO0S6vT=?}uv%H;=T)@vrP&)_%7#s6G3AsM_B6sy4pr^?W67{Iy8U zp0~4<>-i5#@F0S9A{sKEVTjlB)y|%;YR}`T7dC$3ERFw?gRBiDJM8(eE5n($K1{k$ z+sEC_7m&cay=Ky4I_X&%yi*Y!n71OE4fgoFS7Yfj|H%?%ZBb0$nEkfAFI?(xi|1i#PEU;;v78`#@CiVajQNfu#l*SrQ& za1odXkpd!jzX9R0g$*Q^7Iq&B3zByca~hny zmhPN1C|5nG@KxaZDa5zgvld`~BO3~`BIa=Tb8NPu>}*EKNRi!$4q@KD41(m_sKwmK zvebDy)8;HdzKO$WL#E<6v|7)Kvw*<~Id(K}&ub#;8WX3mzcayNocsXQkvIDy5@J=v zxiOELlgA`@P(*~3D#oIFYJ-Q(Hm1(!%jUCKYMeYu3@x!NpQ$XA*|)vO0bAr?dyzxt zL`gl2U^XK8wE(c#oWo$RrUO`$VvQSB-PxL}kxCKjZDNznD5FU{n2#Xdz7XCb9#lMO zzMEysyVc|5xnH0>_742>6Q=hAH)GF-Gw?8*HMmjN28TWl^9HN_uEpVySu3fBL0yCh zn##Cpf`eJb{9VqK?buUoEWj3IVISGs$T>QXgdwi( z>yGsx^*9olc@eUN<~shSpC`64=~QJ$-4&QOAh=|{$Wmo4_&qAby@^B7>Pr6_-KJA? zwQN=T0b~nW;@R2r#Ayw3-^%6``>ghOxlp0ekg&arLrk)pM^If_WpeWaf@OZe-wxnl zBK>a&E_VWltqG-Au#GwwcyYQA5Y?iamlMSkZ0*IAcIN<^M<}bL-@SyRc>pF^pc!C# zi&@5N?a^oZKlzbR?|@k?A%pfbnCldG5eG5U>so&{JqB^IF!n>k^E|XFA5YKG;@b)v zFqdf+Fd)Mg7B{nkX$j+4Vn-k_qbkbnysDig4$W=P#x1E_#mdbq9Xx^gcRF=_FD@dD z?2Q*x$~rfZNGy&HLY#+K4_q(QoZ6mh+3rd|Dp>pjN^35c`k#w*UJ>Tc@cXlBwv2c) zvpg34udu{BSu>x&lrROTiWw%}Jge~^4@ z&NAEE#G;2M_L4^Z_DN-@VmjuLGX^tEkZtsd=-(KXF*@LzT~fR&^*q!FeJ`M?}3;!vd+V%a5GpB&8&>ziE1>}@Gfly3G^O`)Y zZG-$CX6Q)ejn}}$OI+dpO5J3rW;;E1W@z+F$S`sj5`wkCIkc>Cy0H4oG4ESs%W)@0 z@(JFfb=WaD?NH1ng#_O*d?|^<;#rX85oF5+1OTNQYo;>G%1*le}6z7H|yq`ZP#k~^= z2~Wo&7ihsn^NraGj`Nm2W(yYa(9&gWHpD|LQE&0L$Tuk63#hS4kjMiy!`TIrxlxmn zxJ;rX5g>M=D)|dw4)izYL2-_yyxpt>E>wYciGf)jR*o$NI-%%xIiRaon%_a^xl0ss zaibjIB~n4W>JWc~y;~~-{lpiZ`W3fy1ur0YUD4Iq6*$wNqB#EKc0#p3`F9r4o%1L+ zX~R)wx&7dN(pd`rquWT7U9(l(f=Y$(y%nsrj9k{kKzUt#>060-`%mj$aI}yb-wn zZ7~%s=98#IZ`jC`%5zi{p5MFqIs+6@vPW-B>;QLf)(r0k7RDYx10&&Jgv#-*Z)(Xe zfJW(E50|w?DrS38M%9Z{%r;aTB2^D5RX0D6b~Nh!ZD0>HZ$W5nzyrIHZSrgVW1RnG zH0X)deL6^GT0~Q7HJ-(MS^|e^4b?B#y~?mqb6ay7fladg=JW%^0d3LwS&Ig=MZ>jW zwrJS4h=bg0MfFy(WWgN6e!doWHjOS(L{^)x#VxKaW^s${u$MVv#NC7XD@f^WNPGtv zI%eVr)K+*p!e4>^FW}z~KLn%uo%sHyBYlKSe?a;_RamHjrmSTq>B zO7_0(XOW&?E`DD?zCNTC%6<_X&`3oFX=<2W2&eRo^b+>W%1l$?1nM9_jayl;h%_K* zvAhgen~RatdI#Y(@cMFuA@hTCxa0dXr;?+jxaG_L4;A-GPJ|ZHQ5FrYXEsEE3PnFZ z6l&78Ds;&^2+BdTq!$G8UITQSQH)ryo3oTVS<1nLK*%`im-qH*jhX;sdO+m6^zf>y)V&Qy+!LM; z6g@KGUWMu=vE!&-0lDFl!lwYk-L#jiyRJ78B;EK#$y-q`?i%H!T84$;dCA)l>|1Vq z3i7yl%Dhc_sv!)p+Q=G&J*^?bt+%cxJ^I?K0*}WeA4iUCAgO(0o#q;W`P047jIfhl z#f}IJBhr-zmK#AM0Hi*8WZ?|Vx%S03Z>c~&1c>S_WF2<1MbD_`vw z?<}i5pdK)GGaxK{=K?SJy7PP!nhzQe+3rMIKI^WeY)(M(TowTtF+d%sq9$an>=eC2 zXdi_ajs)hqorqm@eDRVs>w1CII|vOQnT0L7hRkaud>CmKn>UGj3DbCly42g>;D)Qc zwTMk+wQ<@6wvABQRIV0_R}~55IS;q1QrR(C9aSPTA4eU~lVe)hv5U;tD|77#_yIeg z>5iWKNZCAud^sZA!ZOURF^?gxY!>h0r?BT!Mv?bb2|mV;~6z z9}@Q<+(YJDbbA64*`lds39m?=0ae6a3YrU@PCH_BUj!M{Ur|ad`5|!><#;lyYy(Q8hOB*H;sn%=d-(_BFTDmvbisy-+Cy|dRC%C zEp!WT;xm>**B#7&PG$iMoy-Dl(0xUrL&SEVE9cPRo-nV$&V=r@z|dB#IWwWVRB*?I zs3(`H{8;L3Xlbc#%m(azkHHEDlrB#eiJj|HSgiET1&MG1e?|FXRr(4HsNvCL3b>n4 z!25`pZ{+^1ECi3^?eTOTM!?uzfH53<8-6hh{2KvY*5%fteO5{@!@^f~Fr~Q&=22V_|v~yoA z8zTFbY}Qs=iOj0clVS$#9N8jNe z^v32bD7Rwn!Ee48*qh9`l+tR5JxJZgML^H2CX^iZzk#xfGgiV}XZY7B;2?Cs-k?1e z#!r28q(D8F6EP2=X}ci^6IE|9%+}W=$#+V)sVBSK0&>8>_KT1j_u@NNmAzPoS%YjD zs~K5NsR4U2mcu^Ess5fFlrghS168AjU5{$Za4C+ zZgMwPfgx*Dn7c+<#xO;O>1&ZtEg?bz$7M}T18CSM91L`YJM+lZ%QC}8q zwTir&fKD!m5l!4%5*dniN)Pj6i}h|mr<-Va-UAPc*Z{nYzc-V(T6J?A6A`$Q0!JS2 zAP9;u)fWDU?`ilR3;a8|Cd0|kUW@Ph@XhDr#f3M(&krU7XfuHM78G3pbmgn6uj_^s zzR(2Z!-l991jz@(0b!ob8HFfqU7@m`Ar+Y5UTZGU^f*2b$sCjaZ^CJ1Q%?xaeGAtD z@1n1{WA)6}v>~}oJ+nQ^$G>@ixpX*va8>5aN0wQ%XBL|6_I&M8RV3XT8ef4ZlK$)Z zn(sw_&!Vq6L2~l+HDwIMxJ`5S^`F3rmE@M2z*hvxK`fgX*{ z3i|#MykpRxhjiL27IaFL>}masX61x#ykvKF6d~Jp+tXXKI1@d^)npF>&`)TypvqT2 zecw#<_=K02u5@=(foD(SvIY*JiZHzoE0S;r=9#RrFQdCWtJMVk5-8Tv`VdLZoS(ty zD;ItPp`I|cgB=gd=svDx=D%|1&vIvuw;Y7P4DXv|%lp;b%uw07n+Nj*`7rUups(8W zlPoQyX_=miS+XBE{r=>?Wc2O}kL{P)A)2k0=G%c8uSn=m{|Q9R+s((K14~v}{395r zJ(cwJh#Kb=#EP;*V)t%mc63ExF{c6s8%HxJ^7c(5xexH^ZD`dZf1AiUKa|6pBPb*M zTb`4v!cC1 zp5VxuwXb#}re`)rX&k!JN(jnMQHT+kY=BDl;7ntz@G5lpYK|vK*O)k(2{W``0-(8t z&lUS9wV02m>O^{({18~9*y2j2(>*qqQBl~esxp_6^&ym`9czQkkPzzT{rxW}jJ7L? zT1d$Q!p4M}bUq$U;*EZ4?T}l%7+*4z`obq3HT*cc=KX+M9{GdujkuBA4=*m*lHJp3 ztJFD*uVoaB0)L7bIST0cG(9V<=QH#SSkGta5n0mLP@T$>W}oV;jwkQozP)fY<~!Q* z4NSXctZk@hwZ2)Z$ot3?o`wdYsdfo&Q=0uU;E?O*K|V>3xZanW1NN|ZfQ97ixIdYl zz^IPxhvl_Q7L{j^xx;d`BAYXJA(cl|GBG?kfX&io2E!H3X^WISIq;^k!_^Cjo?L&m zsY}u8kjZh{cd`I-+8uoy=7zMp#6+%dKsg^JFC25LvcFw2Z*p1cv=ND*`9>5Cr-N8yue< zVV3hcoY7u+LZ#=k6g$i4bd=45UbSMBNFGmeYS0-gG2(4t0`qFrF@uDJCUe3IOt{)n zi5J>7XNoqeT{OKkR;@Iz9MHSF`&VPmyaE0ma1`tgeuhWy48Mv^-~kw`PgKXWUyM`s zMtF&q%MYGXI}auKK>G~BzFAXZTFgv7h%7oa6+6gwj%mePu{@5`Ycq8JI6I909$Zvk zkJ_Ie`x`*&Eso<%SkLVQ z7RYL`nBq>~Pxj$yND5;+LGnG+yak(c%+l5VHFBaF$@(ty0ySWfY_mC$Sm3NgdnK?$ zQ$#%*;2pmq+s|8J!$@s}`}q+aAX&-FQK2~prNCkdr$|~Xi4=kPjF}^)uU_t}SNiIZ z?Eeqo9fNf(+~ucJm={4n9j6!_Ar#CGsA;K-jH^KwE0v zw#i*ylc8zKB%94;S(|a`uhx@%gPn9Bh!AFqPy&xawgk}56qyvo-m*e7a+mXLXv6`!i)2tq6jUvU(OoQHDCvnhbqaT8j&A)P7ukZX!?bK|25n6jRYQ3nwz zKLq##q{-BcbfUt^;;&inu%_Z>ovAYA5}OJIPz}XZ)n|T$;wrAnSEGc@s$s&>43*nj zp9}<-;28+@G^QVk+-f@x>*Z|w3kmd*aO;dwUjzom63Nd{6Nsd?h}`{O#53s1WyO{# zhRiVsBB8w0r<8z1Jb~9st>$FJ&d6pa5vu!g+33bL1^(pt%}ztBfSkbGh_u9w9O82( z6Jc}59=u6`J5#YQU}eg73TMCCB4OiZ8SDzE^2pi5HU3mgqW;yJ?EzO?BtzNNH^+?C zJVAiV(~5?I2&P$W@^Os38FSPVXi7Gqzt1jkeYMjXdZ5qb;UM|B9o$z-ip~~?!44MOj``a!fHXO7LgY>uSqLoaHUCM0#*ZOA?Zu8L`Oiy2Zdtf#?z!bEgWG?S>L)9>y3v45! z_x29hE)CZjGuz;BRfAsq?0vFQnSD&uOWE9xS??D_SGE#1_rlbMa%3i!Suel$@dc#{ zM#<%l`anjbV5J7q4xI7g=O+JK#b5JzpD<4BNG71+V`oZwr zjT*4@+p5}%%at1%lGSc-@-*fj?G5Fd@of#w?~r`nYbZnOxYwin9}TmPUBt9ceC zj<$B@*IDrF8+RW&rV7gxUCIev2lbF6J6WAv`PsQ`WA)*LcE%bw^d#57W{br@O{!xp zm2!$}XU@;^EP*{l%`SHZ`cAFtRxCCLO1>oyXm9FX+PMZJjjZgtNq-_saFc>CtC~90 zaVLN{%cfBoVKP33=2%vnubSE8R4PF!)Z`gES=}-o*{Sv6Y^DWA+OS$p1GwhGLDVsC zdAdL|7-t_&8K&(NMfrkvT?Q1SLZD3IU;EM|88d98zrLilM4p4GFRd+=m$qw56pzG!-21I9mCJc)85(cG64saDi5{sF zh+E>LR|svHYU5yeP{|*Rtbq(png}ix`?*1FnPQ{9Jg{}4Cu}i!fwkqGvz<-SiTFo| zISY>>|G~V8LhU=%cIv#cSl_v}v$D4$rOaU+VQICUisnkdONU*tbJYq<;!Vo3+l1!S za<1Tr#z1y#1KY%POK;(O+B1`Q}l;j``gsRt9g-{8EC4m}c0XDRBVX!ndqg zVgr{3E~iv;6YL=;zX1xNj#)9?2a%;lt(mB0SDP9brl@5c9ABZWfES?v*}kIOVr`}E z3AB3yN*VuqW)N|OUgF!Mwg)9zdsvB9bxbS=%#OmO`A624cqrTrDBR6M;a8YoH<@`= zkKhvws3J(%r26i`vJ88>``Fvf7kK2@LmD4@wwN~T*_=-Rd+r8N+cKfRddoyj>g*J% zB#OU(X821Kf2(S%h`&`O0DEz3IQ9z^tj<(Kxl!|d2yt3hyei+5E#SSy z!)BA2kWf@jVIZjZ7u*MpswoU1_${1#l-ZeieHJDVWIsv!5kaLGn6Ch6Jw~p`-TMBv zdCN-bv&pKr*nfgk@;W#Z3R@+w4h^(9+F*X2p^Y+&NKHPxgYaO!|2=^h2r*d|io(Qb zXs(9n+hTB6qD2Nbez0(aYBJ$?db}ya+=>9ZCoGzW>B;-fs%+%E%N*aMHRm>?Hp=UA#>?i!3;J5zST`wu6avOlWRA81JV&kC&$cfgRi~uRc28bTN zc_EYWB&}@?H7|C#o5FhxJVD;WTR=Q#*=}#jDhR)r@Ofi4I|+LiDg`xq!-1^*Hzjn? zLESkO4b7Ox%SCCcTPD4l%%O)mqzKMsjsQQ!G5-d9d7YlN2Hlvij}8}JiLf;o^HKU2 zU~%kPc-4vL@#Of~+125>3C@Sg3cg)JbnTl!CgtCQa>gcHMp&@ISeZh(Xj>@aY6pD2 z#`{KfUXD>h*!kYme)#7H_ZF)7E2jU>P2l76M%;5vg0NQrcHxY(cs_kzAMGo=OL9y8 zL*T@0fk_U6=sCgCW1@k>RZz=GyXKS$4tQ8hF zl9v{&YVGTZtTWtFt!-Z@ZxIlDtKBOt-Iq%==5w6x=L|+M`4vcfL8x!n$-#n_F;e&- zlIq*iBEzI2LiV;ankDZb4C8+_z8rZN-v!-5>W$}y?6+~}EBP?0z`vC;bzWOnS(b}O zvUUktu6)KM1jT#=ZC0l&4SMFzp*mvnd#<2?m4!P1)5)0jZEE6SYkujhfmnOL8Zvh9 z*N5@G*iHPk!6F85SE2Oo-KP=l@uWCtCQRD6hD_%pdRq_I2biN|{@R|SS9-lmBMJ+;u#e!iphA!2=rH(ImM?H-0$qlXKf3_~iL|e{Oj6t%W~; zjMs9l&PB*j4j0|42QgA%FDR4oih!~k1L$Rd#fEbfjq#)@8b6Z|iilzX?@UX!?9eXK zTZ$QJmaUzK^8uVL3{Yjq$sFt(%pysaUDJ##qPY;M-o4!LiOlsZE}tw^?(V@do7i1d z5ugbs>+%!I5{(4@33jI9W{(X|AtsjEdr>k$JgWS;2MI^GWzUgf*xUigaSaYi6(0A! z#N5STZzZ*h6)`Utz#>8+k1QSz3+q0|ka1WUYWcMjv&MBeEZ~{9a zAKEGl^(=#3!F(uCxKV2vjHTnsaYu<2b0q}5L1gYn3fz+>+?_mNuPBP59IV?SoH+o_tlRAk{!mcPzW*FbV&8}U zV&q%G8!_dh0IpgksVv5oY=Wz_&?RpgYF)x=N`=Bw(S(c5s@wQH>+tBR!atA+W__Tu z%jezf`^c0%T9qq2=80<*u^a^BJ|r(8mCZr`;&EX4_CGMkA_@!YT<7inysfFsBgkQ$ zzhSwcYNsahPx^ILJ^2|@F6FuTWv0&l$Y)-!9;?%}iVM*~HcSLKZ4VD4)am1O!~Gq6 ze~vFx^Fx~xz_onry#wVcR0OP3SVlV>GyU>*F*ATm0OZ<;tn>d9L7-^#b(@l>E;b|q z??Tp0bB}uSK_M`6X-_I$(ZdUuV2*k^=~xpve%gPc`EdXin_W<#EI+ic)6Ou*W?x2n1ej}+n^PI3 zwD<}*{k&gfRM!7(#eRLZq+SI-$xA)(*sKDt+85`cpM|q*zR7^RGLPiVuky4R$Kefx za={RB2s_SOyja7mu9CJ}Wmm5ud1l``yX zzYe3{H?Exx#T9@QLs95+Qrw+&bQ*@Y+kp(jx<-B)4dDlG%jDO0t|J1KX0o>D?3lZN z)o~BSUBK#?1w2)6E%Cc3+@nI>gKJdIW|)^9pMj7;JQpAR6_*xcdU$ld0pKn*Vd9SP8xb(u9br8e*o0VXw3+e@eMrFz7??Oyu=s1hlHCn&yF1LQ#NPZk z0B^QkwkIfqrgt5twX$9mA?9SnwB08@ZSM78c5)BQNhs9sPDQq$Rh-_?$kr2{sJ<6p zt|@Lk86G{b@NVGtFj;r0YH8Qq%MjR(I=;Ek_juS{9>@6rPCI$4F`u<`pSKxcVK*xG zgJV(0GG1Cd$HtdRDf6_aI{*DG&yLk_wda6&WG1nq)#J?M0VFM`= z{!;UW^tCB#!(bnZ1H+u@9hmD`KEz-uT{L%e#^3Ma>*cZ>=Hl^3k(a@&E@e#hG6Kv` zj)G2cxvZMFGA5n&c8fjBJyp$WZ&zv+p4C+BS&cVk<~`=FML6RcHY=2NnYF4}F)rLa zZYs^(jPIG~GPi%Dtd{)44G4Q3zU(r7e11TAXz#wM2)M#LK&%&-PXY%)019R`qu_D7=^LHtPr)Vtg%;KPKOU*)L5uJ!)xsXGUbzQ8&aUgn z)g?YaIMi@8r;j6ps1)}<9&n!Tl0Dbq!e>OqzW(G9B)}8Pa1V%kjF%0>-_W?m$mCy< zrW%LSkk3SMaT@O#MmQ*+Ud{h#`T+a|E%rk!=*5^>X9hL@Y%|Xx1^vJGsZ0` zt;Mozg)(>VRQNvfA0hJ#o7C365GGxUebP4U<)|=iqwx|qJl)M}kk=aKIS*BKm0;Ip z9wuu%9V?Uo%7aQ14sQN?S(dYJl|Y=9Q^ zFty_(t&;o+D6{5nCYhKc$(p-qmmf9I+-yuze*1KMZ^zdkll#JtmK7et*Nw^d*+*?S zq3X@N{H33Kf*moOTv-R-evA?pIWPHNmve`d z^R_w4nV-oywvQjZ$u=I#|r#G<)<}MV`{QI$q>;>z+!NA{Cg(FyV+Q0-B;QJ4%Cb z;VDwHCqS|fvub|su4$+iyKC%Z+N4IvN4lRgek+#UmQpSjk6l}Okq`dI@ z=-R@rXvR^PYr^qd3KdRqK9DOuhISIe6sKBMahfJ-kjY5A!n=-yQy8Q3#&$&$%o;-Q zR{HCeg_Y!$U`B3O4xb*fk()&F#aZ$*B{}`|>cVRBs#%kRR&41nmE`o-yB2mO&&L`z zvvi#N%^MpAFyULpStVS5Z5Hgi#I!>L7Nw_W2gN_%+_TU9*0w40OrZ+8g8VsFPT6|DezJiOP@*rBd24`$$n!+ zYXsv6s{;Q{(&peCP|9dKv==_X&SH$pGiiACow+98gDSn}utIU` z*eVvDhV=Ywr#dN3b7{%4b4Wn~;BWs`7&JG>XJ6q~)Q{Pww#(gt`AsZg323G&1_9#y?rAkH$=p{J!^9NEd=@p5 z55EF}N50qw3v&O134MkXeNB6x<1O<9vr2Ww|9H@tJ^{UKqXBERa1a3FCu*EMMotD> zm6MQ!R!w`0$v?S%L<3pW$sJMVYZy*yR{?psfBWUULg8q%U9KHgL*bb59vE@(5Tb~K z;y9U$Qfoa58zax5PQ?tGTUCvl+mO82n9#JRmViVSSj@zd4jW86c=2rrA5D2 z6lPyP251-ZkWyZi$DPSiu4wn)bW#7BXCtULYNRkUhbavA!ZC}L`s?K;hbtzV^5%MM zD`pXp5j+DpR&deWJr=DlBVhv@l^Qd^N(?8vS_uSrKM1f^)G3dNpeH2^Uq+#OLJSaR zbas6>j$IO_2lnhp*qBfsI}BS!_QgoS(WU_{J_jL6i$OSjF+I`rMUslN)Kz#r3d2f> zGZ#jN@~gPv+Rtq$O9(@y})P#0!PN$C785x{y2F zINP-{Mcm@A4|&jH0kQnHqmT8*E&jHJ$4LZuM+*A{S{5GV!R*a;l?zzN3czkHpb{LL z<-uLW)_fU)T(dCk6Yfj#2e>PR!;$wmfg6_0e7Kn+Zt=GrZWa)?_&XPTk|&3+r?3%q z94~l}drJZ!Ab37X0BsrmL87ox{)^L7_}Bi3i#J_VkFXP;KriDA6k!@&6Pw;F>y#qR_@_;Zh`CCvCjAt&MSuwXNuqN_9I(0w!d!{I<2QMNnh; z%?O)S#4Y}|CAFP}zG76`1K8PD7-yI{t0Uw34GY;sKuzqJf3A4 zIm%8DDtmjOK(K!h>hw7*WLmf&XfXnN=42^Cbl?44pdY}F+q6-#L=v-)nhF|*`;2U& z`elNX-Ky4}q?lp|S4VaZqsg~x)sX+Ie(4G9b8|Z~YFjm9N)b?3^H5Z%(q0h&RW)*9 zL4-g#xZR-(BEK)?EL(1Q$S~atHCpMb?DQA1&>3g6p^rSIaQl4ndX)PZe3_Gea^z|q}YHVI02`=?A(>;A9Gan^!&-dc!o}OmhUJ_>*N8TF?$tDJaJ4bz& zXThb7bWgtsaoLbP8bg+AP>T=>&58p#5k@pfm^d_yz(|-lG>kwkP% zm^cu|H=BQef2{1FmA8Ae!dzoiqYRf_q#dpxY6At@FdYB^1T6w$gXs*@BPE!y*kC%t z^jHaI)i#*UFnzfMvxRbG5Q>aWNw&EL04N%!-i)pqC!*D_+o`*=yvcL1dV%ZS`)r(z z3fF2!cpLRW;MEo`THQGuh^IDtH}x&+wfy;u>qt< zuABU1MF?{`i3Kw+2Z8`Rv+`6ah403^7U@p{4M*vF0jeB}RLy%huCex1!GrcAL6p7| zkx_aVesxk6UM#%?Ni=Q}(@1sldH6|F{H%9G=Un6&38qO37pM|VjYNCky2e}<%? zJ=x1p?#XDU={m)>4M+ME64@iqn*gphjpHL0kgU}05)`7X3dKNG2TQ7H&2cDKwtTTJj17G8O@P!`ouC!^jE9FWXpZoGMUeP)!vd2lxmLJ z}c6bk&B-|1Z$Q0@(u-N0F!;z{C`l6a*ub zSew6Py=-y+z%KJJj3iaw;1E|@l*}L_Giy(U?#+$w#mtmkEVMV1$GKVt3V4^RIKfe( z=6DbhN>zF$$k^Q|5p}Z25%dm2I#vjaHx6IJ3T&NPTFh zIM_}N0seyI2EZGHlgEPhoxTpxyHpulgG`P08mlx!x@vGEO~Kq-IGjz z!rbZ0S^M+yd!xzYXV0-lTY$+lJsl}VJpXz0ADqSar{^*Na37Y1VXJQghbDK&+pD zG{68y%g&9yV>Y2taRBC(L0?~T5oR(ZmbEx@_k}LJJ{lEHWyjzXs7Y-cGU2TI8ua?~ zjdThmR{vav)AaQSZp!995_hP|>63$~Yx?C`WGLjlx}sI|cJen0%&!Ye4g`VY?C1>VQ|cc4NL`X>*iZfgIg&3GOrk zP9<$rZcM%d%kvhweuaE%w}K1A;VuMR@#MXT`M=nE6DYf?D*ylG&F|Hayu3r z$98D7yY1iSyZ5=nt16K0->=vDul4`c%F8{&KJz~N?6c24`wSsVRHNh1;c1P=U*J=o ze<>kT8LgaR+jwQ=J{63h@_}(S-FmTL$&N z+IRxc`m5MAuH^g!O50|iB@C+U`ed5C*ug{jNlYl=l$xVyZQC2hEt;iD13h7re9tl;ni2S{9?=3J$TF+Zvn|TlOMK^= zZzF)A-Io(!@~PywlhektXKSC=D2!9%zdTNZ+-FkO<$0lKwK>~XIU1^R-O#vU<8(+# zuZ^5cf7aS#10#dpPZe8?SJ4z1dzsdb&hv4*nUF z&_=9r%s!q?GmYjcXZN&}@qT=!c95iL&iIA$Z|?UOm^D__B4j(HdXZA?m&eIpNTp3+ z0n(=xI$|n3em?&V)N`VPWT#TC&)x=KIn-*z-_`k_O_^2@2qOEal~$4EDK7Z_hmmWr+ zJvN^|VLI3Yr2TVY_CM(jjyrV&V2FdGUvQPh-zn{zAfB=?Kf=ryY0W-~3=IEug(rSB z`Alhr?I2)_uf|u6w5G++B(@_RM_uvpjowo%C^_wBZqJ-)Zfj=zbaRizvwUYSMeFM6+ zru1|YKhFAAslxloJNRTh4g73Ua?JUfR+)Yc>isZq_fa{OPd+f)0T|s z@+2-LgZF^a)uY!kV+T1wyz~o@9ZUsR?fLk6vs2v}zmB+WO-}l^wo76)d(guPla8l# zs3cO}X^ifiQ+#|P%@y=We6@%dx??M%8OAPty)tXIKm+Hslx?RuJIZikSD2F|@Ixn= z&olD%sg%hXjo+Yztp*yWvqJzoQO@UT7&J}$F!;VU?^imJK6^ZU7S0zpjKpswtAU2K z@=es5%Iq9$#@7()2Ujm9uo=He{(a5)W}L=E+2Xv;UNULM3ibO(;%(fdq_65tW5i+! zn}xT=HZ^UnHuZpffk5kml1`*!JiAV9b_GjFw=P6>1Pp!BqE8+{pH!&-wG^yw@3uyv z-A^J9Z0xjmvJ!alXb&h$FCY8F(~=X?$zm3|_zNr4MvF0UQoV(YI|E*Y!8&V^R{=%5 zu59e84p(Yim;)ChLobz1H(b=J2l=auf7Uua*ogPyGqoE%-?T1UyJd=k+&#ACKDZ4V zlK+6gSsQE*@GL1ApvQqN1yWxV9Z4IU=dJka~o;=so;5*y0cn4Uc^k@Lc|jU#$AbGL84gx*4@=_9jAIcVqSjIYXQGvkIyC z@zMGZfmYidAxlfkqP#RGmeqRGi89z1GSb@S&iI%tBX6!{p}?Rzl6RevzE0CXdzKDhZb|<$1v<| zt3@zw52j}g1BQ~l(*IDHSMZOFtq$swm^agV`Si0e-7S^7AIyqkNV zRe$A9>$`6R*4kknN8^rcCRN|Uo-E9tPm@(Tf2#Q@J(I|{4L*t5b)QBdlU$>TNozQq zG?2=hjuY%|L|fWZlDS1QxRT+=7Ru0to^iC#t| z`Rgn{hYR8CAusc2ovkR^WE19~HiTKUWKAg?vJT}~V1GP-B1~=UUG09880hQC`uIGiqfBtCJ>qz7RkV^bku*j*_85HTgq~qkP z1T$P)c&)ybg)8i1M0nv9?iLbl*cW}Uw~@udD+#Rmq0HFAKj7(ILSdEoAmuM)DX;b5 z?YMV6I$fZ_bFy)OaR)d_030#;3SI=*%>lHn@msZaFJ>3$>oSZY>^g@vdCq!smm@L1 zro&e*N8%)16#XGw3sq^qSg}nZR&DlOF={=}fJk@L)4|_{ho$cWf92VF8FwtX&*P+fxHg%x@4Dnj`>szOYTxnXk@np!(Pd%X&wiTu z_ef4WTRNrKIM{9hJQVzVcMSM*dz&^4CYO51Q1W_r3@10ZV`XxaJ60vPxuaw1l4Q6# zdBsVp*@kZNWse$3?sUhR|p5)auYxyl`zlDD~IbMk(7 z+$;ILS3XK^^N@Qd-*U%9@_l#goBYZh`z3#I$9|=$_B)e@g$C1fR9(7dmNp~Ebe8C+LNWS5YW0HU3 zh=a0@P1>IPxa7wk^}uAcha8_op5X~e$wMBL9B`#o}7J9)6#IO3OLY*V8Su4Oe*j&C5v)JxP{Bj(eRu~|t-faA9l zSuClw;m~jtAHSQZZfz99GNNE?UF$m$`gX8Zq>izQrR8^cNKzZujs(pTt+Y0oo-it< zEW+*9hQmG6R#5$QTSLZX7{A753oz{mGJG=nAD19X3zmw;l-Klj!Fiuh(!Lh|lk>>=5Qir9*t6X{k0Ec2^{0 ziliZ1zd*?>Z8>JkEd5d=_Y;_r(#Clms&TYEoQ^Ew7rkV|k6pK>3#bYi4RsR_V+8?xb9r9t&a`9*p~^bi zV17w-VjC)7m<&w)bx>)N5qz@n-=?aI>-T0#2Nq-g<*J#jxaOP~X{Ws@;i1o5XH@@z zR0ZL3sJR)r&_=2p0xkoe7nE!7y|6mFj!7F8qQz&}+8p4cw@~#>?WwPk#jcZ=0k&?7 zX26N$qtsw5>;Xe|;(o&ZPwew~;VHDb*FX%r14eJA7zAn?2}x$2fWEW!hqvtI_>0FN z4co9=77mvD6A)vUO5V9?v}_%9O^mKDf{3Hdt`vjqG$!^4LIC#XON8)$Tfe4RR1C~6CnE0Kd5C}Vr%_>N;yp5tz2#)V@l}*f0 zsPsh?;Z5>NyBoajlybb@nPZ8Z6QG>vxZPnhoG3@yi5LB*k{8oe42kID_p{siY)-6JDGTu_`OtIv~n#GYD&40P7l?y zp4apHR?kPJXTu9`q-)p|U85cg z7!|!}mL36&{x}O{1#73oY{Yynk9N1kNX=A5RqX#6)!PfKSh2oARNcpve-i5T7ENZE zzHnHZda4_=&g+7kJIdyksY-MT$fM0!&v#0Hg_(aE{c5Yr1#hBkb4Bl?truL2cZb5< zE0=k9LG^ualDm=zT~XRLHhVE`N90^;J0SA80GPRqfm#Ci%nUGdC7*$>S_0V405g{{ zX-fdl%m6c2^3LUQ+?WAoE@SDI=MAtU}bK)GWlq2nIY8uHj_H<%3Q|i7IK_@#wc>Ldh%~i zg1kO%4QH1^m0c{*A!X)DUjAe#zei`;xmN9Sm^$@Y?d=Qr!%tCp)m&!giT;VP9UUk;Rp&WLadc>u~81N+^T9J1V~WpaUB zLXccdPc6yu4-f>;F>@vF><9Fj{N{A7+AU@dy3S=z4)t_K*7DOv_4nWo!NHr->rLzS za6kE*5JbD79_}Z@%j%plyryZXk_&0ct{ffZE%vr@PA=((k#`Bqr>TD-A9n!gQnCo|ziglKE3Czv?F!C;ek-A-> z?eZ>x`Nw`3d6&RM=k(P_-X$=?#BBkvNJbNXTA zT>|s!{yvm<3CzX)F!C;ed8NiZpQ!RKfjO%`A9f8<>Pb6S5s@)lqUti@YIpF|?;+67u2 z4~8-Yt&U)MBQ>@mLS^U6l6r7DCt~H9Y9BoozZU-vRGpyj z(Qi5jMk&>KxBy=0NdW$kuM+4_%+^mJ^V)&0g#fWx8sWq^UwzoxY*t1d?h68HUU{oM zqUAz>iOSSXK>O9$skh4+y^sFsa^1_emakM^Y;V+;TV8@^hnT!zCBu4}gR3bTOm|HL zIJc{5H#U`2{U2#3;+5&vJPZ2!TI=?S?9He@fFf}Bo?f!rgP)>+brs#`e?Ww=%%0fu zy>q8JVJmdm+P*y#_(v_?gh$i{0G$L(?=+{R zHKTPC+H7zcjR|G!Kr%Uss@c}7%iS>(BDF`m1HFflk^|U*o!u5X3oWaJzmVDTQSJz! zj32Na(*;E24BBdc{I9_DmYFK+x@yT!AYBE-mP=$*0yWl)C~ztG-J0Cx%z9C z+zky)o5Eav604~?(CEv=wCIxu(r*}$RPXIg|IYUK@4WiNv5O0(QaT^lhwhTzS-GHX zSGJ1yeB#K~4&E@AAz9T2XinK>RrS(vn$}cOZ5Q13^T~E8B2ItF1**?z%m%d`&FH^l zK!8ic>y`aJxtZx=Pg*N!UO~?~Wka5}jhvo$>udxUEi-Y&@OEU@S& zo40xTqz^8Hll}D`t$nW``_A}6Qaj^I-IQ-h4(H_N29;a!EC`oZvIbSh&J@i-2i#Ig zzC;(~hk?o=I}B9Li#6fZ-smW`?}T!6G~Y@L(QMD{0HbyO>0#CQ7=fV29AJ($Z|=t! zHPN|$gZuOJ8!aG9zvtrkJuE=BQ^?xyJlp+_X`Mt)RFZFJ&ElrA#u`hrw}Zx&`1AbF zD1+jb;D{fBSH;T(8n^e*^5VGVetPvC>P3@B$kjJ4A1tci&4uUmq!e?z28h-M}efADoxu zaH*SqyHUy2m*yZJ!rq^TnZv_ApfJsan{WVbeqiO*T(BA{pHNlh^T9M9bC8c@UN7dW zKknuB^|i{%`dSst`dT&1J9xRiR%OPbUaZd5zoCgc% z6wrrDo`d63>IUw^i{TWI;%4dwFFvYZ;fguH1;Rd-hMB{|tOkM$RRMp7OJ@st_^Twt zS)XXGDqV&@s#JzQD&_9+M|E>>&_{(W!jUVpwd&(U(l?*br?&7(eK_F1g|FI4I|QKl zAP9X0qOXDQ{gnJ_lQ~EO-Iv@l*mnH1qIF-zmfdJAs^Vn))bhL{q?kD_t@6D{Fn5um zD73?2tI>J`?!RBYB$?}v6z`W8L6*H=zQNx2ISc-#lB~`8+^ZDsm!C#MiucR8Mh;E& zIu3?A&Kw@6o>H88!s5)~ zaq0#OGlz$%4=l_a9;UWim^nO5ZMHCTc$nI1VdfxA_o1HxQq2D1V37tIF9e^+J$yq`mX>gh`SW-CxV7lP%ixLKTebzTUT zvl2fVtW2K4s&D5 zIY55*eSGpkrCY$ur?VCn>?#aYibqfnOm6qICI!u;YAbwRn(Ik2(KWPR4i5P zxepV~@%j0b=2q{L3)3dJRe+wg>(gmqyA|&McKUeoDBKrs`8!Q{Ra^Ez(_I+>c!xSA z2Tt2XrB0_((~sBMW-`6-ZY6?1Ep828+eIZ zmIYU+fuAC9Y1JgFp9ZR!I0ZaUZNp3wa|6Hc@JnTsf6qRJ>}}K{*{2XMYr+!@mp#b* z-N^@*9u1yE;7M|-sns&@c6_|pZ>Yg(DA_}yh&ZPb>t zyD@x5+Q%sYFiZbZ_qaQ|8`xAhgOq(X6}r4<@E2-f_APGC@(u6w{!g0ZxQ>w0 ze_-dsuE8*MH7ITfW6!*)BWGcL-OPb_{4=r!`kQm9O~3+Ti2kEI#plqfwafOR z$1U57HG7|Hs*t-7cWm*r`JXUYBAJ9JsoM&9r^ZCAUa|*0(!ZuDuCS)1f=gjeegtR-D6AtGUm@4RqEnc_9@ht)4^V*1 z(7bMgx9kA<18O!v1{{lGQ%SXAZ%7pVbzFLZ>ZR41n`7*)OkuHYOo**+J>+Z3Kp;;l}9U zh3ap7I(2JY(w1gN-U)rFI20^ch3Zar&2FU8oM}?~1SmAGI5>;QM**tP3F$0>&m1kC zL1~tE&RA8Qu`0}bH^j4O8RYP!XdPEMdcOqv+7BFu_Z;S2*^a|TCS0+-EDgeqL^WGi z4AfVzNDid1Xod+HeSnmHf|2cizX4|&blB;~YH1}2IX3287_p5dlEq5d>r5W`W3GPv z4ht#j(Y?y+qTdELaq+!*3onh+*o;J{g|X?Beg}L^J-vSDV-A!D*Vv`nlT})$`bxW^ z)2R;ijwGPzcWZURthn;y_5aMh@YYS;-Hh4QQ|pEGif$gmW^&tGfKPq=V0t^aal{*F zUDLSf+LTV*qOVJ<_P~#=$nL_GFWJZ(;?TENP~tq#;d*pjrf=+Ug{!7s8QZe9)@;!r z)hn$~le9-ALx?`FZsIHBGWvc&U!5%;Mw&y)^mS$}e4|?nm*E)=L>*%jJEJGik#1l{ zw!L+@XUdcH=t(qMV?mxb2`BjeK9uoPb-u>v9~Iy*7A6_ux%js+9;0WqmlPdtJ4?I4 zZaY_+CX&<+WXh`4sa?B~9y`5l_Z4bWB1&$)+{`2-+vv1rHDb8JmE3eRbSL<2!Zy|O zGohYms-F1!zTL?um41ih^qJJrtvru#!9s`CoCI?!S=#YcO}SB)oDFMc*{X0%Y3iJ# zF-pMghHKmfw=T`B4Q^>5t_yCdf2|L0sd~KZ4d2V@x~rXPy_^nHAALyPGDhh<@O1=3rLd zM!A3F;j!F5b@!ff|I*#hl>682rVCa?zjF6Bxqt3%x@kr9Pv$NVVlgk3Im#Y)YFt@9 z?u(YrUgF_Z0>tL`zz{z=>3BKD$(r>v+ZXl zD$$qa)+E6FUEE(WRgQ^@Q{qcB4LEbxQaTd-9;8o0gz$YK(btue(4L&WA-B*T_jlwL z+J_R13B-Me!Z&*O_v9AZ6aIa zpot1JSXx+ib)e$zi1P*JEq$rG1IN%C`YXpf1t%4>?B$L0tzBtV-NF*#Z;)=&(uQu; zw-u7TFse`uPj_;*^x}%ogOKMC!Ik8ffSWGLsukI~aDM=Id|mV6TE=_B#{ai2B*k?h zxgK>)?#uWBDMmc=NclGNNXs_!TwF{e-O(&YN}`!Znx2_QDxH}}x|^9tw@p*e1sW+E zu56k<%ckiX1{mZvS>axMwUHAi_%MEt<@XGJJNRA9Pr8BE@Ovk}kMsKizi;sSAwSg3 zOLcNw%Wplu-WdNS!oo`OSE0||C1Gx|+cN?xO(bXItR&|vz#@}f7Vz&`KqWc(oD{l} zd^&Rnz%Qh4Tuv+rD3)_i-2bf%mPvGItR`8-pmA#NHH$--z1bv9-!sxA{WE~6>f^|^ zYxuPsaWo5cXs$iyTq?+Zjy5)4$)b32zNQJqs5vppc=3-AZCBzqIgGP1W#8kaopU!-}PLwS3M z^4_;}hNz+BaIWrETliib6k<@uakGdz7F_rZad!ObkIcLOvnp-7o%6oM3eL{V3kMW~nB2;W z8m>->(_)NNSkntzr4Tzo^laIHlt^^8>SX1LF(V+WWJsr_hG4VZc$bv~K%()5->LyR z4=tDH)nVRpFI9CZ&kMpIe;PAr=Ks8U*m{&|nxk~eS6`Jm!Miu|+XKkL)9&Qzk|dV!ryZVawYV#2gXJB65D^^Lt@BW`|Dbfm zz^k+~5|f*31`q4W`X+)?EuVJfy`Gi%D)LoYWMdx}S9FvQ#K`DqC6Zlf#YtymY_yj7 zWq;))!e@nxC=`AIIHue0XoGAP{R>~SRNLn1JpIytDwBS688$jEFmKX<{#R9{y6|VkTE8nm{hfX- zM)T`04x+I!C*R*INO9({zM20+8fFd;`(qkr4iEcN8fFd)^SV(-o9mK&3!U|ssf4Z= zu#OwoD!sl+udk&y z`|98IfyRw6A$9ZaNpP#qr+Jmpb2OvsgXF>LIHZqTTpyOx+S+Gky+v?pX-n?Z%=#$B zEVQ%8in$r9MPGP$d{n==v* z*PiM@VH}s(D_ml~y! zd0yzTs!}T$aj&?^!OVL5!DOdhpeTtp?>cm6R+W0%u?rcZUs9oVPn&mnd9?kv7LdjN z&b$v!!T-g)ho|1(oA?FdyE;m~kvkJE3Pm`=(p3jD#dunct z{~izj08EcWU@S_SBDKbB1D~6D&v5{Q#gybYz(vM8kOr3SnB>2~Xoh+uo1dK@D~0;y zW^9_Xe?g>n-W`CW(uRHO-Q+5jU=&MI_dS=N@?ynY(VaZL^zZn$Gp55bEIl^Fg8^W{ zzfpd-=HpkfgOgPZnHilvjf)?}*|vPw2;?x(1;NE6)gX)HA+Pb>xuq@L3iyMF;(0R@ew?xH9=VOzy{ zpcNE97U-ecpg)gUjn~LTDBb2}4&84l2CMOU;>-$?JJE6+Bcxj^n9FWA{L&%XTvDR6 ztGrwGPz@U6{?@04s9CRo6+fV440mbdTZ^S$Q^F_r!~z@&vbeg3jUq{1|X= znNfV%{ffT_prdeR_E+?@ZpS*hr|2X=_VInvi3W{NzEZmErDrML5Ewp1D}_wn*P>rD zD*bl8ouJu-&ul}ZjT-#|NX+0Xsm$PinaY?M{1DVICA<*+0@REa+r|GA>2tgIk~YvJ zRJ}LjRFe%C03=G?0FIJ=rGqM(+PIae`VRh-dqrI}T zQu>@LgI)XF+VsrRRKa;8F-Gmo>58iZc7%$RW$OZ%LLSOat?9RG(T}Nh3=iJk42Tu` zm8{qSH>ba2>|G-`D3^t-)QJoMsB`VU4|47u-p_wyA-r649vM&KU#3wY|aJvjeHO!8F?k^k< zmr-x}BUv}&zbd+=xp-0E+?K-@9o8(4a=Rs4p1e3}I5laqMMpk; zshGwgl~7`bSeruS0evBrNK>di(E$vLUjuJIqfey6Nq8x=c#7|5_-YT7{{0%qUi`3q zW)GcElNEx$nBT4Z9$J9^KYN=%W3=RLf*%ohH*XW{SNa)scs8_QWbxYsTI9kTBytv( ziT<|V&wfWGIOU>_xtqwodT~VFg05&Dp*Ls5x-WIK&sVE^@)ZrD)bvW!KT4$ zmEmO>TdD&6)+W-OUPvSJPt*!Bs2cRLX?KMd(Mx;%PJD^e%rBQdQf0l(X{Nn?0QnQM z=d^Lmo)1C0Pesk{t}4+?x`| zhL*`$>Dhx4!h^mf#%BAQ61Dhe%G=lg>r6FRLB|rMs%l|T zxgCY@C=7r~EH&Uxd-@~PdBhRLhoaRo6UiN{ z$Lq<;MQz?wO>7m~Oqm1-w$Rv?i*c+C7!h%SjP&Ha4XZ6pz)p!mya}z^6ym5-tzgmK z-q>jI;6*-OK3G+Ptho&uqK7s@d&Umu0J)S5KL?`$o949}-PBz(cCzhDJ8N8Rk@c?4 zqXb8)7S)1W%HAE2?8vcwAg{LD%xL#S2UrqKk5G0!y6v&DWY-kK_!uZ8tp|V4r!8J3lmO!LZ zr4VC>x~%*Sdt#!#>k8&-;k}DF4)4dis|pqyBaz~6XSBPzr~c`z>a5-wU#GBcrxTvh z>83;IXtbI-tnRGttU`P0b`@>hS7)UfDHdyS?v@LDh^JmTk>10IDG%kh64oWMwMlP$ zim`f5PUAfLyW|UXC+RM^K<6r4j+n6@+TlVBuR=JMGeuiOFL@Nk9`k8BYr#4yJW#=iTEr7U+9;9x5+|hryf!U%~>1hfz%CGSqZ~zB?&D z81&V|u-8!C? zVEX3D&&Ut|Yf6WYx|!ZqddD8fF#iteV-T zqK3(O*aZ<4qD~~MSXbhqgk6^#tagzC{=z;`>~#R=W3SM3XG_|vv#y3B;+6P2LoBgA zde%Pil%3(Gt+q!zfwuH+S4b05X_fr6D!Hb!CavV#6uXj2u1qVrrclYz&Zt*%jaL$X zp^}NxuJLDq#Qx%5{4S7o`XSiuL|G-RbzV-0?2LNr#yVq!Xk^pYjTKvGE81!* zY^He($mzJJpOo<*9p^vRcGimjSR43{A&6wUM(oc(UdQii{cFUEM^m{4=7sOdxsuuU zeh-5-CCbHfHaO!uAlu_@ur*3S(50B+mhQC`@OnV|AJ zS-M8NLB%~3P_Km>a6aceq<%D{ZB~_wG1sIqW*lMmR@jQR-&VYx7_Ut4IA~}i-cvbW zVhxcq+;o{=RMZRS)1ox3mn~{ZCElN=F=gr5Pf`ht!q=*;M)Vhzq-Skfp;~tW8>;ng zSdm72UsX%&^6X~-lX$M(d!@x}Qp}?muSPr}rzC~$40X58yZ(GKWH%aKLF)1@j}pdJ z{U<(n+W5el%RKxEBo8S9>SZLBvYJ1bElqZVZ2B`t8oKNWpOk;Oo+KfQwyL+)s%K@( zA1-{Lk4B{}v`J{dl&uSCFLY{S@msC%LSFH;g!CkN(4$3JVgoGr$7XES*D&-Z_(6mB zO^X72@B)0D!u?$&p62Y`j~S4@xg-f|psgi6<<`&srkg{I#yS~~FX2B&W!t1R z;)4j7lCZ)jiCgNZ??@Xt`!T8`lYzFyj6Z>o{olv=z-i|1Q`MTbx8#Cv^k)@g40j3{ z+r2BHQb@|@o%rIi*mAJ`zO=*Mj*@)LHlBufokn;73T7hIZc|p#_#4b#-z{l@2vb~v z_MkwaZoYR&bJ&;z8$Bo_mcMUDS@v;A_jirad~cW4sF40UY5H`(7%E)=5y`P4#%wzp z0Cvyof zbGw$tsRxl(%%?meLbkfOV4>=)g~(6x9`XoTCSSvCN83R@;Wp|AZ2P9H#245SJ}_Jh z8|n8@^M)^ownZ?*i86z(jgw0-KMz;RGnN|7WW@#LZRBJNb25&nP#isyP0{H`0qu+9 zv>HNxRc+^xgTw}4Tzhk|n6bZM_cIMJSx&Qe zIFtm8GUiB{JtmwMeek|(7_I05#C64PYq-Yyd~^Wu1+k1?)N91gR~MLgrR|prw`?Sp zMZK_)pWMayrKB%XQaz9f*Qa}nQxCS3EldJ@zCIJ^5O{P?*AudC+9 zFj*YaOFjYCdhAT)?yYdzaU=oJ48Td{dF5>>3I-5L@~6-!gS^-E6wq8RWtRde+4YizGX|V7N%K)05z?!@-aqx~oqy zp2Ad}+mVGN5%CCgRc`1|mrhM=|6#Q*|f8!_CMt|MOBTKy8QM!QsqoZs=KM+6c z$@{5t2#Ozxd+G$>oxY&#7#+}<(H?y6)_DCOP zTLll9!ajn6bCQ8D-lnb>t{yG~tle^Sf52{A4(tzDHzTwONn}gJTCtng^QBom1AxtW zTYk&c5iV?JQxjXq3mVSRc%DxsytX>Q8x+Ro=g)LkVi6&G@n(E-y!1s1AE%#}=tB58 zTJh~hovV3h-`kA}4sSPx1AlFdMh|}$IfsC6Gj-=$T7tBV9q4KA<#x{IK4VKvE)&cJ zS2L3P`oqB-v)iI%I2KHp>G_a5#5}tRvq9OQ4<_i@on-s0vvEI!-_864tv~629M1Q7 zYIiQnSnhpEi5aCQc%5k6zw=+FtQFpu)Vssyk=G;c!8?)p6OY(X(dMg~Kk+yKqe;F0 zOHVuwHhuQFZjkF(C7J$LSHo3Z7}2M;Fvdsya#!)AAs(Hm)pAP5$Q-00Oqp4jIXp}` zTbMaKY)u+w4#J*Qo>$fZk2cci1^GRc3aOm5Y+zN*0IMS&tG0&**t8wgX>D4TIVekZ zAJ65hze@6R=1y)xR&8;uU=&f+2vxrZ-=xeXTRX8j20F9CQM3Hg>rxbl~Aq#^`-SmfwHGS>f zaFB)h371#8ZoBKNyv;%0(hWO-ul_2@@B8{oFy2MjCsQHr!9JO4<{r$ms*EMd*0P^G zLY{3_@o-PR9_@ypC|uQkNQ$F&2)D2Yc~HN2Pavd|DSy0%wOQ>yHu#OH`ycU=1pQcRpEz>V{#>S$1tH#jJ z$qP%5Moe&_=!u(+(%CJK2M*^0k}9|2+f6~5(pRb*-p(l_0@QGCLf7VcZR0L7blUS)GnO`C1;x{A&(1Jqi) z9rm$%@pWhzX$RMh*ShHxXeT_y<3&0IW$y4YUGItV1$IQr%wnTmv-)~Uf#EYfTxmE> zy=GCPx;nT5LR#0+VYEdrRB!()!)999I@MCGlNX-GmE(gH4-@AC`CqcYTbC%v0IZo< zMUOvEFU;QOxI;?&AIbK~NA50^W`$)7%i zesGUknGm{+0*0}_8ZG3fh*(v3Ld91`2P$;sNSD{%l%W()C*`J=Am!Sj#P|Ov90VNvr!uN#zvV9DxmKa^XF;oq{qJlKLuwC~ zjZeO=^bI^ORNE`XwpXm}p>s`i4GQ={+RUlS-VVhAhpBDFG90FO^z}0u6!h#h_JNr+ zWiM?%f<4?$rz0HfI1Yk9Ife`xks4zAWT*Qg#Z4m&EhjyN1;AuCQm>l2maJ#LD+*R? zL4`v-N z`y~#H?knGGEt^7dOIso7N?uaSm)4=x!&XoW;-|H>1!2?LirE!Yg>!qWR#*XzpuMK> zvdTqD+Nwwe!8a?8N|IERJ1eaNA&sX)^rxjd;A$wVTzJ5FoUmziz^3d?nG3;l?L#m_ znb9)MgK2)+BF*y4_rxnp+N58!h{veAD&Jm2dAHaz9bsHOGD5pWIzRl=x&KNl^Dgoc zSq%9go@L&Gks?4 zcjOzM8Pgg#SaYqnTGQ(3%z$>KOT9J`Im+0{$r%h8%h8b>dJoKmjKg^; zL8R0zFi$D|$zl4^2Y%tP4xTT{;t^B80teBw6?&{bdm?>mtMumH#^pg%Ag$P&!_#Ti zR4@{rPGcGgGunlY`BIGryhhddUsO0V*c1ha>$7_^Yqs{Ra`lm| ztjh<}PZaS?Mp#FM(x*$;Wrb_NWE(&yA}KD9vrl^h;n@8%udtM%q1~|W$vY;?Fr^)SGDq5?cc zN}xTJ>#*@_#Hp+8^>y)s0MpsZo0U+kt~*VrXbX$m=o~Yxp~`?gK}4AbZo8IB0~U`V zcP{ES<;s}^xy475bwwg~i-=mcq z)zQL4t@F^9Hg_owznpn=0{-t6=F?I1so_X%#7L6hkIlk3e$j4%!12j1mwpS=^iuGv z>QsiT(dw?VEN(H7#=tSl(nkB}ZhO0oP3H7+qY zbG~gO*`?{6L>7cekk+xEy?quaPcloL8(R3u-s z!=r_06Nroi>36w_QTnEDE;aEtHzqobOgEMLYqm~*ns2&Jk58^QyFQnQE=)OPg_O3Z z)Vpj-Bmyv+Hf{6Gjl5d*zy+SQia!ZJSjX?9u1MGM-9ScDt*+0>8DFmcb?PWgHqyv- z1ZL;-XGIz{^L!y6YSE&W)5Y1Bk!-LD0q5(51+f=(Na>fnv*v_xbRmMyp#o3RzP9vIu7&dH! zA#zLk2bO-!_cGE};vcC9ZGJ1ZeK&@R&Q-8YV`?F{X%1B4ALAT}j*&1&SO}m(Y>uUF z$y#F3o(Zp*vEN*oGvR>t6-Jf^o5|-6TCvRrEk{eQcj(3?jp%9nY>m=BSNRzZ#KX2A zs>NZm%krr06fy@9B5!lsOufBK{l(46dV6++|EZQO)9+?l4Wf;#nOCUNC?Mq3&`0{A z_bUB{8eA@XG&MUGq{BtGi@NK+fQb`@VxpzsOBtre;Yc-WJ!R40!&r1b<^%RCZ~Y0+ z^F54aG?JSR#`$nLCuW~PQ|PWNwwcGmRWTuW{@_3|r&6ck>wEsdD6^PKOf8U2xzh5| z0=pgFCb%VIx5L{6{Tx6umvg<0ti-2&gI_vNyOV=nPleSs~2O3K%7;l29Av zO3@@;6jae?4`W(LeoozF1lb-yZ+f*u0j&2YYt`57`y+0p$6E0)kVb}W>U5h{MQy@R zt5JiS2vpYMXh8B6V73LARNi`xbyDKsvh;Gp6RYIss3h`16Mlb=(WEO8Vh-QwO z49BEiCIx#hlZ6iAWmA(CbsEVpkiwe`)~VHv0N7?oYWML?_-M7u{F})MH}}DcVdou4 z>gF-)Ke}RD{L>~SsPkO?%x(6!X_LLunQKTiOc);T33#VDcIi(cBAZ4#t!v^H%C%EX zl$-H2D0I>p1*w3EgLpE1$dh5V%tGM z#m){`OpSfGkqO+cm{7?djUGK*1cE{R7%_z{5-ib2EX2 ztX!EN#HNvBS7m-kZo{d{{IJ}@B&9*eVt+ZMV_^=$ghbuRLrbT#=)OYh@s0~?(w`7x z|7_yzh5|Rn?c_8zh2>la&GjNpquC_h5E*T*12pp)iZeDEy$sB7{kySCuVktWG)6tY z0PfWaMtf#&f@xu53F9lfB;7Rmc>FOknR8*MKi+*Hl%$e8ivR6ZY(KRvH=~yV=n&@^ z#0&Z%%nrqn%}nlE#h+sl=+(TgVj-=$l}tv`wtEmv8-cwVrcRvD?Xy ztZk(i_qE;^J`zM>IN+x*vn^Ado^A})>2?*10J1t`>kaGoXd6L2ZT9-Ru;n)ZbygLf2S_=3rv6V00l&tluTONxKK&-@90orZ!&Qf-TLtLT7 zU6kGOvcs{GmEGhnrk5SgUestWJ4j#qk2)yHs(5h*7LFA9Rev?lQyUcjid)i>z3Jd| zk0y-xJiiP0ovHYG z(Qwb5j>$cp7u8)W1YXO99bl_XeGgwW{|B3

n$oX_UAi?`WtqYYuYHg@h>re~WM_9 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 D)S4Y(ihfmL zz^R)%qBJcr;FPg5R$)FpW_fV>KpfOa=@%wQ=_ez@OedUm`>E{nIdfBH*nv=Xad| zlyVt>m(F~-+y5xahXG1{6yU8hA$t%z?}^p^$;yA;o)ZesDx4j-YR`#dGTgj984AxT zl>Cg>B|l@2{~NGb_1^gs5}&(vzC;w@3xV#v5(7>>us2p=35AlM2(+@V;+NZ-tgy=7 z6AJ6?O$U_yTZW>W?)86D=A-T2Fu;IQ&nlc9*mrLf(9&+Pe?VDZ6Ez+7mXxouHwy69 znRyxmb|(XU>CF3kPXNmB85;eMOZj?x!vJrciQ9+RSmXI!NEgs_`rgD7QhxisWWZZz z4r*lkPbhxV{TYhicpqZ=Uc|PVUtpjA+cI3hZp3+e!+@6QiUE}Qj|B`k)pUP?rV{~g zoq>22w%w0dU>{=ReaVVHZ!coN?h`;ueNpegIc8w7?Ggh{joKfpaH_)Dfv@gJRP^?J z5~W-+;H@)r_amOze?rmedlB1ey1+i9A%Dt$-d;q=&q<6o3{cuPN@J|XM2*QB{oh5o z6M(WFNtE>{15nkk_au%<2?LbrlPL2M1t`-mG2j&B2T;~8iL%}$DttCYqLfS4{t^RD zmDqbi@yG0t7;viG-VEhmY`a8RZ~WiK_#_6Lnx7J;u-@J%g{xCy6*k?Q2zcvE-Cc-c zSF)n>96;Qgf_ORQ1n^aT`vc1Q>VFFPVH%?}W}KGs);r+;f%XSf?H5qC{{+DJhpX&J zRQ&!2k^xouDZ0eo426)7GctW`_aj2RQ#90TK-GRUCIia)e?rs#XC+-_Zy4aMGtV7} zQh4A%ET9aRto*+`Z~{>FGZ`AAKGglb#zc+D8c%4<(CB{-<-;^a0S26M9gO`5<4;sr z@L;mSQU^}}Dm!ZQ|5)2cW0b~3!13oGo#&;Vu!AQQ);*X3D8u`IikJwf%1@!#g>>9* z#Fa$vO4jlxG-haw`b>szybm!>V*!olcOgH0Z>*AQc@S~V!9<{C`%YGT=$91E+j{~~ zwp;(t(LW6E(wTP;MgiVBGwW5vw=}vAA>B;l42=gg-qKj3tV?tqU0w6%K3#vNv{Ev{c*CUPiV~0=zj_2VlT^h@*k1-0`ya9*Dzev z-%y|bcZdnM_4o!T;|aTinDGl@)USw%8pD1^nlt!9AJP*H81SJxB~oF*lo*92Qr5V+ zN@tqJbd78Lq&%cYVfmDFg>_Tp#jb!4Tc!jn?3og&@UfH_g-@m=0Lu8_6A+9SFyOT)R05=VmSb2WcWZNQlU<#7>yeO_WvBg7<)sTwZ=%KkXIG5Sx@ zn52<6(RKg~_;AyaNQL{4#3+2@NP@yMN7g9({770WcoFYRGyd7vF>N6=ZsCZAz=c1iQc3#d1Tb~n+;UJ@!_ zL4>D~j{X3#$v22o2>+(}-yy=Wqzb?Od!h2(#DW*<0>3{pFwju+dX3TL;g_hT{VE|Q zRn~M%jqo9z^iR?l)EDU{8lyF)4n+P%z)ME4?M((D&4wbT!bKRVCuo?#b{XxCrUFVj zb+qP>(cv^s(a6RkKYAj{P0<)VP172aG^T32sF6+A`U#gHow^k9qQ;=rNVBzCUSkuD z(Hf^{Ow|~)4&|Ew%6zA8)ZsrdRCzbi7_D)N##D_LH3ps6@*1NxPSKdE@uJ3{Pqn

$ig5512)FwZBpsM`) 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

HL8%C`zG@~wtX`_{lEzP0c< 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 diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/System.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/System.dll deleted file mode 100644 index 78f786694971158b62e4a1fafbbc9c3a0d06b377..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1679360 zcmd3P37lL-wf>!Zdv15%nMu;=p(n{eW(XwdOhOp;o=HfCB`krkgM=-FJqX-TogieG z7#0PQMR3E2h*1=AM@2ndJ-rGH$1p$Bm{!LGxI(6#Q zsZ*y;Ew`%fveRDW1)k^S@O|bP&-*BT`5BS_+y1u!(G&U}n&5q?__bX>+IIBUc0K8$ zRrUVWCceujxPM{C>0cvi?<<^&fidiT#(x=bb;lt1H^wvOaE!=N;V^ zcyF2cw$og0Kkz2(+R+wz-knobFh=y-@27#IbPW4xH09UNG{F;Qxjb)@{H4D(C~=-Q zrQh?8B@Dh#XaXB!e||94>ukjAP-s%W=M^%P=OKJVCOm)5`B$z%c=y+%JcyIBqCDA8 zzvrDj-_*^yK#FWEI}5szI!HewP{@39{v|O8MOMg6-FSD8qdPcFrO-1oC-ozJ@)_w@ z@HG3&&@q5np4Oighs5U4OD1B&%5Lj&vDXn`(C^EnmF<%9X`=( zvyArLSoF^Rmgl|g!KvPc*36$*?66-&){!5K;U_oXP4`CynC@4ht!NOFWz){!}AA{eHe0O&Y6OPtE?zZZ2fI18EBmc}_k)(P&up4%T^y~Sr zdIEyOXeeHmaPq{h5JJ!_p|YK~HR_!}ZO%ZfW;G94)lbB~bp>;0k_JW2t>-@#g=th2 z^T4)f%#-9R=~BJ}OZ}kdmVIIJGb_1G@nq3v?_l2B8(dMbrC_)Nkf}`aR@dPTqIG_d ztL_4_XiEtZTi9lT_@Z_%jDL%NPqIP}+F6?r3Cj5HjxXu>k^HD^$*+6I^6PoN@~iAv ze$)T`{CWrP^1g@i;cvX|a;nT(i857l^&6qNsQ&Y^7j`(?JqWtW$1}UVP)s3yB_Iu( zt0P;FW*CfuoL`**d8;t=uzC`zD82@?wQ9n^jDRe|pdp12`}Ji7FC5zqHs#k(28%Ip z%$cP~S3L#6&cZNy6pxZboz)jHk5l6c!8o6Sa`W*~z|Yz;0@mgBQv2G^w|Ra!EQLd}fiagsYRx3R33R0}{?SCJ^e6ns zqSQ~vzjaSf+X7{1&pfjQ_6;^`i)dfvQmM2@+moeIj8ODs2?B$xvS>e&k$8eiJh?QP5>Hl%&0VOEQfG{o5Sgnym?GRjR6h&<)&=nj2r;w*Sy_1iM&*g6 ziSgM0zIhAO+*Y1cnpm1tDNVX{RlE||Sz&2XcMzXW@y|gxzKNxp$eusiGLceG9730b z9~GcRpA{4TF*fX$bmHf(RzGJ@6^jt{e*BUTKk%L2pYd-W{IXMI&G19~0RA0~ z-z)H&#Xkx4?gsob_@x24&#MroEO+5|1iyQ-aD$P@s^ljZKU#t|<^c3ZXE1yoi>nr< zk?|R*Nnj-Qe8jTf?H%0Uy#%tMcPvRYMt*!I^-9Mb8ova$AvLC&FgquRCLhp|7ax$% z_<+zX0(CyVKqQG*lPw#0Xifp%7leykndW(Al7-Flo&@2?7n4pZ#e6A)z6|KfVi*UQ z|3sJ*b2IvuHkSiUb_m^<=Zp1o>So@J4+q6u3G#Z=sXm^HsBou zM*uhA?T&wY;P-g^W_`jp(dLP7Yr-E5{6WCqf?r2p9z4K131LWB^3Crk+$t7}{JRHy zZ2;1VSHaTZ>kCoCk@-8w`#S5J=3o$#_v0_(7kzgTKf^2)EbcJSg_ZaS{s@=&P=W&j z7tGho$nQeXS1%@W@gW&(ycEQi^!tsZqT+%{v2dnQJd)D?wk3Uv75algUob(pm7=R? zb^@#=6{pc7qSxq!iUuRA)heiJ2TAvGNwr)Bvm`-C(FbN>>>K|Y*}zUP_lSR`ApGdA zUJ-f^q4#m)Wjp4>Xu%GkbGNR#1x~ju3S#<wnFG_5F|;PUJFR;kVAkPod}3&H_rc zcnCcFAdGcXpUwkrMuzOGK7+5b)!xC9_f`tB4V|qTud_-=jh%j&S4HJpD=Kdlg}Gd! zrmkWxzcG#>Z&8Hb(gi-nA=DX^CS@#0Y4Sa%cH~)_JGC?%b)drCoCdAgL;1XQ_>u!Z znByJ^)%caMS*XW>Bpi&*lyG@4=Y5lAhELydQu#A0=B&V5y=i8TSuMX)%+>Nc)m$&X z)65<6+iUKW-<{3<^1F-qko-Z6oTk7|<{Sko<`M;Z%sK_8m>U(CYF?wjG;@~%z2@Bt z>})=vz%FL90@KY86zDTgDbR0VWfXN+)7dV-3^PT6-OO|ab~hLZlV+w_q`)i#??TLM zbA|#{bDjco%oPd@n5z|-Yi?3to_U=DdziN?FyB0=z@FyI3JjVj6xho=rNG|ip9<__ zCWMmdzNTA&{me84_BT}p4lw&FP&11Z7&0d*Fl^3JV1cU&XA1p*cbFDZTBL}H{-F&2b`bN*>flNz5;~7p zlMjmU1th;Vf_gqH3k zlTte5OxQf$l=6~dBj@{?!cCG$ZO5oJtQ1z)LT!}2cW@W)M*O0tODH+yKpk(U^uVC* zXRu6)F_=BBu2h$^RKiOK8goDw#NS{NIP9pSrt@ob9?=>s+WC=>c{g&)$FR9*_($x_ z*w1TU*2$jCb!0)jhGIE?ei*1=#2)%Hk16;m4|aK!n;%=XUq!Li0)zO+6oWOVaeZ^F z8Au(SgET093%f@Nf8kPwScgwF;yk?JXsR9}MpM1U}xU&+I` zm2<;V5YP45&XkjyPy;6ofZZI>rR-SF@?g=!N{M_DviS|U4z#3s5=|<@sysN+8w8h( z%_G14nIBt_Yhb|b2VDGs;A|smo%S#a(Uf)xaE)n~s?b4PfjqVWw&r&o^W7V&bQJ(u zUY5#YYqC7p=V1mdpCG;&@iOTGE#dK%l<4dxMkh5D#J7^Q+BilL)|SAA_$n4ptgz+5 zvWIqT^D80JT6veXord|yR#r(%oLlb!^SSHZ%id+JulIsxw_%_PKqAHLudqQKU%zg zaU{?IBQi!{en;8qS=9$jm*mYPjXwG#G$MAw=1-vRsKNVs=AQ)NYuTHJeab(G zKL*myN>>e20!+k;GF_LfE!@{Nf`u!us0+e9%NOp1P@&j!s!r@9%=a+e-j%79bxjFe zG@QMQL830pXYuXu^`Z1Qu>XmomrVTy@f}d6tnXq$3k&BWG?YQKC?ibuP}9-IWRj(N zIly}iIisvjFIc^+iI8+#NQ?9_<9ZE?;xVXjf7-=gQ{l#;8!u=4} zpA1Hvwxu4l)S-+gwOFmP&9}%gbe6=v`AqM6v<9qOy7FnJ9ifc+x6U|-M`%#3%5xC? zFia)ts@)3R6=UhBQTu);vu4Ti+bPt%M8$>p9Z(MjY44=^#M@ySfws48br<4ywN`gg z#|Rg4j6e%3>UkZ?{@j6Rt#EnZ%M1Gtf z{{>%4$q(&&F@7`l4NE?X#gsnMEKHOZ#LFDo&v?8radzazwdqD)Cn8Y{G_-qYhS$lC z*Y?sES@D|wm`wT(8j5z~&e?K|)ihSXf}%^qVb362Xwtc5nkm}(RPSUe1fND1sUAIu z4?|j81Dt-C^T?P@+L7zjA&8Hlcfk0G<4?lk*3}=Dy%T`XjO9S`Z4?AQ-(qRI$n+MNdR7!=X1 z!}lOQ5h4v+-L6AKd=@ld<$utLr({DE35q=#NfZ-5j1=Z`APeGa0LsIkm<_+ip{k|D zk3=SQq3lyNqr7{0UqpgQ;@>iIuSn&VvSPxL72g(YXXYjG4Oy}0tL=-pAZE!rd_3!8 z;qrXeg`XG?#b_vJp*#%TJ<17d>QClI4xV3GSOz^(spx-cRb7i%fIMP zGWyQgNlSePag1EdUm%JzAXROZH8qSr1IoS_B*S!v;}niwQ=iYdI>?mL^_rRd2)@P+_XS7+(u6s6`9b@rj?ZS@!d}W14 zDr^ym)u&VnkJq!dT2sJt=bkD&L{y!Nf5ZDp@~g-^Lb$Ss{6aGsWa`R-SRz&NI&qZc z{KhsW_140WwKA}0!Zll|r=h(hyoN&S_-{J%qdf;Pp3pjM)nRLQrU?!b0ryS>Y>_K0 zqYf@Dnvbhin~m~<**L%5VyP>LuiiE<*T30CuymYP9=zDQhHe@k+b+2juWrt|@{CJt z^o43L8UOA3)#b2$=>yHd5V;Bm9=S?NT8DKI$v`cLzsCWFRxW#ROK_OetrdTYUD?x4 z=$J$$HvPEirAwxz4&v|s8@Zg8$wks{Czof}gtee)b--WG^6p?|;Pb5OL-q1D%qANu z;sRDgPf`)Bjd3eJrdh!9;4<$}*h@JxFK9Fhb?#h~#8Thc^p7z0ao+O+_TBWJL3}EE zE6xfq)!{PT(9uYn*SW!JaOn(<7=pB4U6ZX%A4l>D-!%{=u}gm3OoIF+J38T3)l<6y z+=BQV$g#_co)K;BvmC!*4aQ@BS7`p^Fn%$F3Zi&g81EV0vK-|Aj-jtX(Z#P&|Hy< zm`{h!tyF>WT$ji6=uEM8NQPLCfus;!819I0|IS}n*vUePK^J8bh{{X$&2=@9+mm>mYlCBY31>Wt{UZbWJy8vvJ4aZjKvg-NI!H-! zTK#!$6=O?y5q{c-pk9}MVn4FXphC&8yr2`(4Q|m|H%@dFF&(u}Cc~j4z^6rS>InEO zPIBL|{F1eA)SGt`zOTlYa~FQfgEPf1^(1u~h#vapVvGc%uufhp&n;rFr@y5ZqflG+ zVc-<1E@xAh7_Pk+wO88>cv~GwJ8nUzT!tTGo7S9?HTGi^0R>;oENE5(>x2H^f$@sI zN!aO_WRNUZ!q$u4k%+*=p%h^F6opflFA0EX$CqnT)9|eg;GdO^o>f@O5|l-LC_#cy z+H!etC+}l`g>SzH8Nj-qQ;h{&&IQ;HkmC!0g8&yOI0A5qg2w?oR>89YE(cg!g?~2B zN0K~GN|FDaAh{S|De)Y^ikvA&xASD#awHC~hSatkCGTFqQ>}hF@;%F!u}k1jLJqiklt zS()d0r=ov?c&T5cXYa`GvZAxFgfpg@__7H6vLWt=FLC@X!M6tOqlKpm8If?RHPjj6 z(@N-*k0V#%N33whs?PtD6_ak1=Jd%{=4MKG~sg&1aNz{5o<@@?q zY?IUX5^@?*zMmU3SJ(^-ZZ$mLzX6dBozzKd}_^ zrKQV0Wb^k70uQ2An;iZ*iin5_8ALY`Qxb%*2<5+wTVT57!2>-!dh&XiXN;~mTnks! zHbfIaqbK5CBC6*?^|d@GEfox*ZKw(=OT@5UEt%};Bm+%d-B<1F3Ef&`)HcMXVAC<& zp*B9bP1C^)vTn~zX8~B1wHuOjYq3($z=z>Z%g0wf@B|HfW+Z&rkZn28`!KA0lKumt&*6gfZ1=;jnDHYt=ZNs;?HN)<8anA~Qt7`0k8xKEhN6CJPM5Yft~*ncHZ5i&%v?L z459b~OclhxC44&S!*aHdcchy{^luQIj<~okq+>MUtHTB3x(blL0{sW^oem2T_FHtV5Rx`sOvE^OXaCjzI>ta%3W8&q8_dEbmnqBVfo=q6}P) z?8uAt#PCHCHr``DJQiQp&tZXoj$HdD>9$ksNj2+HOuOy0XzoP7ZaXcS2N0N|dr+}; z3xTOF@Du{mT)^-0R`BhXiLq3aonTxb(R9WL}RL!B=4 z9frDG=r0USaG}XOG&RwNHn6Nx;8J07qz)Q;rO0_ z@0s{sgfFIp9=kWz`)lxhGrsrZTYEqL$xfxHR)K0|LsC@hAjsWHQH=_hEm2YJ&v10I z^C_xfgM=r0mZBPF?w)L(ifY_BD;t=i+M@)yfhwv!Optq^qS^-ua)VSZbSlFl?ez4Y&vG1ycz#AF9(m!1dDThtOcqCO0Yiw{O z?119w6_sEi8wj^`l700+{2Tr*OdA=N!ctCoRna)2avsg-b1>&ZDPM(02M02>TsWU| zLPEfa+2H&U1`C)7pufU74l7QV44t#SgKbU*oHe)f54RT#FL= zvMbvU*AT8=4#qXOYYeeY%fu0`8pd(pYDQqi^+UjOon2{pJ2KwN<|;UJ_xv)Cv>a!^ zJ7?yWbG?rsyes6?-pgFVHp0GJ!?4T;IG0?B>@#R{Mf!k(s{}#(UQl&S4$P~NzKTA) zVO;eZ$25rF54s`rJ{VmQEhW^a94gbjdnlrQBX)H&be_ERq(lL!6}aSi+-lc&vXfW#qW2 z)DE`^_nQ%W@h71hm2ilai>;q6nJM$D-2|zTELq>NRm;^_sS&ZLaPimR=ki0SqNYVZ zw%@7V^}x?W&gKb}y?z+$-YrbcLX=&YT8+dVe7<-w8^{7s%?h=u1-2_mUw19E#Y)o5 z_;92`{U3p!Ftj05{E-anp%mAK*`t83w+vsx{FDcKJPho(Bv5Ks<5W|{umpnx^F3Cb z2s4oDTc{mH&WD#1{ikBX$-%UcK&na-fGlh#6OY%vn5PqR5K{Ub%u7RAcSL$`8xEF@ z()$jhWgP%YE!CHz%p1^XbL-KIaYfkHg|-+U+AHA&`-me zEcoN(7xLW32(Fplfh^EAlQZxyL-_eR0}rp0ThD)b`V%wk?9q0Uo`EM#!F0`nUp<~G zo`*0rB4@ubkI=K`*GXBnd)E9GkUcMF&7leCZoB#2{Cwqi!;a;5>%X60@8DwZwWw@Z zusy#Sn%Pjgw!a-c%emEamH)<}$qsvH5(mh5K$nLmZ$kODa%i&B>B|wQp$lM13c3@N zdjNx>GEXkyAlCsXRQ5qJ$4NbSTr>k`)|$>xev!Tp6Evi5b&jbZ8&X1ZZbnVpKUEo& z!%8`?r~7amdSe-fDc=eX$ze)#vgLdUqwl8Eed&1UzaSDuQCC9kn@5&aJmk2 z#;u;OJKwtn#m6{ltLN*sd8fjz5U11KtiVZxo_-f!mbn;VJ^fT)zbpmdmWvyq(<=Hs zd!YhGd^VkVKgyU%XKCds1?9ZGTM9Dw5Mb)1_Yh!6BKuUw-9ym6?RyAz$C3RQ)9DCj zX?PET+&zFvVR9KkK9;)&ddld}Zbhr?895n6sg%QloXn43$|7#Szpi4rP$?H>bXh8t ziW_Ou)mK0b<){?N(8XRw5ZS8;uo0I>a7zW){g=`5N}&wvlq$w(FC5}jM)Q@O7FL7> z80%03d30B)n1`UzLj6D_D0ehncMuN2C1d>F^29%m)W&B+bbI1o?i;9-y3!N>UE@#u zcVcNbuGLC;schHAk{vCtw~UICDt-<<^e#O&HT2EUvo^8?VEg!WAp z%*Jn-Nc;I5emn8qjPD4(d!pO!9qjjVpbNKQ=i59-`Y|wSagKB|n~3yTV5WJC z0<+9J6_{;4r9jnuUV%C0aRmkp#tq~%*Zf?8dFIaw>|y?;z*r@&rj zt^#|T{S?^89HhX$=6D76Gs_j&-(0A`0p=44XGAu)w@afraM73LI!Y zufQVn6$KWXA1W|ney_km=KmBp*c7LT%!in%3LI+oP+*DKM}fl(7P?sW!_6TI9ATCz zaHM&W0!z(G1&%ToDsZ%k6q7sPBW(~aJpHgz!_##fiulD3Y=wbQ(%R8s{&`6 zk1Md!d|iQa%uf|K*Zf(5^Gtr4)TxLF?Kx{sxz-sd~1ui$=Qoxv>Do{6nRA7yHMuD}at5*cO!t^Te5;IeQ zE6tt?TxAYaV4XQ$fl;$ufve4n6&N#k?8)k0Z>~|`rRD|!`ZvG>ncEe6Df5a4HV_U8Qw$qMRM%#so)sXjad8J zd4wasAbvUEwJ$>Nj9aZrg1ITd)YxVBbQEMEw;)fOyPs~G+g8EmsPhn|Ib%jLm-$Kl zdAsOKCbBHAImlM-q8S=T$LuW~lPH}%cjunxUaDm;W1rGv$hClSXwEoCy~J^BeU5qw zr7XnXLC+JKV;ybdIvduHWOHNV>9Wj$>9d*XHV;fI|10xW3p;#f+AMb>p>hthD`j*Q zqDU z0zw>$Ui>qPjA(1a-X3j;!6$px`h8Gp_N=vr)3eqZZgtjLVq~nVXRVboJ!`Gu^sKdp z)3eqZPS09PI9+3fTK*f)ea&^$6ISP<>gyot5X$LRqThlT-;q7qKvsP{Xk+XHaBb-s zMq{oO)%sHgyX|6;w$6@h3}?=lbjW#Xq~zn;JE<~zwEM+KGNt-e!BlZc1S8}uHtT!@ z^c`6{zlIsGa)THfY`EQ#L#LK!r1gljT2SLT(`R!gI^IG(Fh|-=%k$1W6P+PzN%JJv znNwD+&mm(Ijyn*QoSe;^iB8TTw>qPho{7%vIt}8?v1qqhZmHJQj-HF&gz{(3IJ7z! zojs?_v(WCGGGTjog$w`oIE7}9TIRXv2A$|0L#P@4m}i`a&S%{!Jf4r@*PaWKp?(sI z=ciPIWm-OrV~7UptpA!n!8VrqwHXhUZvxtrHJ z`wX=N^AM$=2s*qoNfnVPk(_7}BU3>_DTE;Oq2F^nwhh_Go!d@&3@BL6ZPQI^_VyYA zL~Q-s_M~L39b~dErD7Yg?o0VPx#_+X-F_1P4=~z>j`cRck3u!jW4f1X2&%EWtuQri zi*SBQpRBwOI(3__)}bNFc9e8Sdu@L(vy7(Eook0Kd%_rQ+HSQcIAm09{_JY3_P>b$ zEw_I)ZMPb1;`5J$&)ZWzsP49*Ou-m-&%q|=bk`9cR5b|HHr=|o8tp2(|Ld?MeD5w~ z)NU1&cPTVHxm_9W-N?9UG$Fggn)V~@>K^pbUk)QTeu9|i@@2&a6-qdWh# zMmX6+^texkv^=oysN5YfoZ9HHks04hhvN=W;v3LATy>^4;!JWPLgAeBTZrs** zmi_>g!=9zT3iqA3v-JPJoS`3q?8Q`edxm}nu%TI;se<$jy_DM?pXUt6>2y!;VWdKz z>hypyX@)`O?EH&}=Agq>kv#&mqo?Ni)IF3Ld@C-k4#CTEe)fPph96lLcu3%6f^qf^ z9^!Sw{a|vEmgRCsFiz<0AC2#%vvxxvm*abd#4u?|C`%F8;KomFKs1#@#*$ zzMBt2c49XAECg%KJma3ro^i+H`v_{UESfLH=aNM$4HjD+U^B093P{cr&~sga?*sTU zXMVVk7``uSQ)s~3JGZVSR=+UAdr4Dz?J(Zp6ox~?9Gl5lf|EM%7sOlXxuh$W1Px$+svMs*CX@d zv9h|Wc*i&Cu5sR{r{(2{ypE&Bx590nlh<=i4KjV*sRa6#9j4zwHDoSqK&8^(E`?kT zWBwmz(($Ohp0pSH-_9ZXq`>9DUF9w(u(p0&lxM5>S4jq94!9+O{TRpmmSAF^_4yhO z;$ulLDat?YQPxQYd=b?Mt=!(amW6b}dxdRii^o%^V zz5WCdRx>A1#z-15##6L?V(ekOZ?FaI541gLk3lWG+)){ZJg2V<2JRTNCT*}Jo>#mJ zNhgW_%akK?XjC+koTInp&4M7f<~ z^VR~AIZwmc_^BS9EkEEZmlQbZI9)O4y9yiU$G3S}(!AcKS3=97+8`tH2>q6=e>X!WN^q;10o#l{AY9iUaijAeYQ^J z{JqqvZ4Ic?A3;%4r(vc}lU9<}sYM0VpCQ4xQ}yiq?7?~U5jxI!##Is)VW?t0Sksf} z!%9%9sn`@)&);{< zg7`{?8+;uxyr^#5XqK-jCD35K#4zx0>KL>J{gV1pXwzbp$ z=2$9?reqbYjQKcV#~5FYva}qPt#FK;EN;3Jy9oNLWgfThVdUxj6)Si<_W_LWn{36s zA~App`9gYLK5H)%P|rnOL{lxLuE7e&ZbVb0gRt6uFll(7 z|7IpAf0GFIegKMK@Ao;JdeEB*)C{rQf^wyqX{6o0$}Dx9;aZknXQm zhfD3IBnuqQ;4WC~s>uzZo{%w*ipteCxQ6@FgfSX`zMxDz=~?EK$-^W23q5a>8SV#& zy+T>il__bvorb5g8Stjy?zl*%xQoxj1Th&p!-mS<t8N7GT1CjYRzZ9~5z8UI+_-H%ON7>*-4G8(T#MQlzx<#QU(E#@seJ9u zgZO@WZ$oqte-T9j(fu0w5<=Mjs`vllL4j)nfx9b#`p!#1sux4MvW^^@Z$k{RPVASW zXKAcMG;he%=`F-Bb)w9$3_KqQ-MXaArX%cbmNH)Ij5Nmt3|IM;RCjLqbHtn4SJyB7Z zvVcnnwSEedW}CUxK~%+6;N%?p!GN`{F2WQZbyWpI@3g2aN*4mMV-wTsssUzov77jd zZeO6g5WYqg?*_q|RorwJ0_nDK7XqI@9SSa3{w?8%Z*rxw7Rh7~gQ5 zdz1sQsXElM_;_Qg%xD<&=lSSgrdq;_Ri$%^#kyj^3ZWOmX zx!p=fS^tCt7I}R_iK&M}%IO;pooZMYa7b?U(&V2^k!kY#QY5!eDdnqEB=;LCGSgbQ zze&T+C^TsUM$iuN>}YvUCsgfHiOSsju_TE) z0a0@Ahq609i5OypG)#Au$AvDg@rI8Z96B^_aiFyQwcvnpBz$lrJ~(@}(7ex);&|Z# zX4U#Yojq@8AGH=TC-Vx`Cs2MpZn&7PRSnfn@LA8iL-a}fqUVDQJeMbe1adS`#)UmK zSiM)lDc1(slHqvRlRf1pH#*VUA@Uwu7a6@e^UCYlvhO${GZHL*1mapTW`j{^2zCG;5-86V^HxV+}Or7M?WWzPi3Y70lC7FKIn$B(tC~= zCE0=R9FHCVJs*5MCz9}U0~N!7ZPF^L@S7Da}cX{QD6%G4BE>2`6xic?Gt#$XQo1Od;3Jr3?X1| zpU9aPAz*Kx$eB6<_V$UKxeWn(`$W#X0|9&cM9zE$0ekyI&U_aEd;3Jr{22jz`$W!^ zXX5CRy?r8Q<}ze&pU9cR8M3!e_1}{lUZlB1RH!x&xpU9aHGh}a{$ZcR* zrNG6>?U~Cb+MmbEC%Cyhs_d;4DQJ zDhK`&rl_q_(b&nuxhtEtwR28fwrb}vP+WV^Xx%)IjB5()T?G}n?*qLVd>9{bX_qGd zN0_>2AQ!I$-d<#|3@Ce%!HdxnaFM}L_`%*?j@)V-wiSW}REsV+*_B|l#YnDrv&LuRm4RaV&ad6U{TzH>jxPt`{PYf1ybt3SdfBmZ zoD1T{axBf1V+mplYcBw1n3^uEMgQRs??CDJ9Hd3*?%00m(sL;+-<9~@g|920+ee8o z%Ew29l8dT$KrwPDPT%~#6>>2kx*@sTNACdbK?SIf)c1ZUpG4Y(k37fWI^(nAlhkR# zhnO9aCwqUgJIC#Qrlx5@AHpn4Ww1U%r*ULy^RHA0_UkTXf> z!JsERs0yps0gn}z>+z!(HDev;WeDJ$I9f6eLgRf|0;G5}P{j+7;?YVJF96cPIC6aN z`IrExuap)JLumzY^3B&n?reC@yd<9-KO&Vt-Y2CnOY265r;!k&Y0aE-K4ljVK%kto!a=#lY7>7n@ z1T4ldU1s+{dl+MzCtgzn1CH+j)RDI_`S{@J&|p3u!B1B{J`_LYTtTKJ1zivoXQ_OO z;xygMyhHFVYDW>zA^TsD{Xg?ygo`))(K8{YtkJWPM7)cr7{3aTUkb+oQC|QgJ zpr~i$A|L{J1Et?BB;5l+^$uzfGfrGhgxf;$AQ8FBx%z8}#7$ep__csag+h$(7Qa~1 zemwwgFJ~whzX5<>DhNxgyVv$(K2pXYQ^uWvRZ($h)rneEQ3J#wrTGJjXhq%#rqws{ z-#q-|8CbjobKfaa$*xXp`#Osi#`l~(4mOKXKkYJ~32Y_cNeno^=&r_(d74_h3s6UX zC+YIK2f``0z+<+}tn~H2X=YDf@lElYG=9NkFvQ$t1VLpYXH>c)H30O3T5;&y6YLH131j;G4#^=9|VlzI=!1Z0Ld?fAnms5M8S0r#ngNX(EXq z5Pg!8I=sRkUCBfpOjPfNZpIi^EC|rIh&EXVR;|QIp@_3;lY039ykdJl$!!!@v*cA?-9{CGNFi2wEU&vG@Jqd6~;ASD!#dNo>2uqC5;*J$5D0f`vTHlLP=Mhj1j$vKBf1mdbGt zS`OO?e=(Ik3!0O=ux)sSgqQkNOgQj_Z4>^lffe{dBe-1rR9ATydGd~%h5mj(4yS!xLd2VcJT;HF7!-3 z)`Lz52W4Xye|V)L%b&<}ugZjSTAAP8DDyj-@HGu62=Pm!XCN_f96x48|_8bw*z3iRH5$@&@i` zvzO8iIw(W^RAf8Guwr2huoGs{U?(om3t$t3eWg*4PZ5z0b|aAMpXj%Kl(uc@|BUNP z#$s~Gja|;4_OaE(Q4}R7)Cw6T$NoO%%^Lk&Mjt0{3>6I z*B;NY_0c%4AQL;TfXa1;s*WodlaDeXN7g25%&twn5BY!ZC&w zD{ZM7alnT5!e8X@3P$I~ZsJe-*emfvTY^0jBW*(f#Yr^fa&(Z33>xGjf;>p)V6@$D zF<;mpe-U$wP(i<$Fyy#d6C;0t$it$j114(7OSx!X4j$j9d`4_Nwf#pV+-Un)DtJEo z`%fc_=Vtp4gF{u=yzsU!V?XG}j{Rxrus_QG8joqN zi~kq-GwhG@zs6$*+z`*OKg$1zhwX?i;H#}JFgM0n`@7(jv#puWMP{MQ{A`uXuYLzf z5(fZ#CL?K20w68QifOi!McOLEid9)L9dC$d*dOJ8#8bcju=<59uVlM2g(?=BuN5r# zWA^US%UpzE#VUVH>>J`4_DA{O@^8mOAAr=0^s}%L+wWm107U4c2#o8ah}0LVxIBbfqBIYNNe@54qz!(;@uGb?7#;hMXz&5N781}1w5ZlmsFm#R;g$A86tXK$#JcSA6P;Q#%&ztg0#}{vA z^4!=x_|f!4h|B^&X7H3)^0Z`9j$foafzFNv0=i){&3;*>koZo@!b5O z2M$$X^TPW>@l~!(^#^C;^1xBiCha3^Y7=Q)VdBWT!t9H61v@0vV23tJ`bGz%{+Lke zQ~*zH;+I>kKee^A{(4)~-^lY@e^Z}x{q?Z^gw21b{+us|p469DXNsPnZ%pP@-vU^D z|I_Ll^)BsOhTLPARHHJ}I({3%sAEO5?Fq!TXHmqFNa|An%m1mgKBbRI<=V^1^>(Ja zqv3*c_LL@FQ$RjKWO@E8 zuna3!Tp!^Y8h=6cKF#O-Nj^k06ZP`A7=pW0OKp)vK5dbn^l7(DBnIpvD+h ztm@_gvSeBTz#IMN2bpFPVBO!V^GG5!O8ZZSMHc8XpZYk-7iHovxPF+aa(0NpzEJVX zvLP~!llg8#9Lo41W=A;%P&r96PEJWU%Ks{-LR#mACOOaXXO2D$%0Qoz9f;Z07{e@A z8i(0Zv}Rn~r<&3+?9ypmnl2mn>85lHyL1|trgL$e4-R?y@kbv-is9J^`E{vMhJ7iA zzDYnpe|;Td$7^U>l7e|O^7%;0=LxjEF^2t7%4+!#Y~Vu*@2+v z!-_>beL=CwE|BIkX&MoTVZ|a1*Ky|}Z+`sIM@TwdKvKyAE+y4dR8RZ3*UG-$+yQcg;o96e$G(Upd$&U&BQAw`(Npj6klDqs+{?9R!jNf2b zu@DIHpHJh(coR#dus_QGR^H#F@-~h+#{Nr)z*hk3K`~lRFRh1rXtL>8 z^No-{J9oHC!Wc7QIP0FB90!4($7d%Sk;QYHJKPBlRblfV8hb)toI^mXkBgq!_k0Ub zwqIhHwv@)*02OM#l#ToErgRLubQ+hY%f@}XDILQuoyMi-Gr0%Z*44Z&gjK}pn$cfq0Ny@UANQF4}O(6Sgo{1H%D zF)%d4D|`0@v3)ZN#l|apzXC}^y?%Z&B5f{t$zaQTAuk~5@E5p0juhixk>Vt~MPzb! zH}4MGL-D-`U#8=SdjN05FXhEz#b=OrqreaT=LL51&V*c)cNM-)UhdIwHt{|w9qU|` zi$hg{aq(0zZN`P24J~z*L7R~};xoPp@;=pr)4CRulISSc;WWz1iK*5k&j%zxOVFy* ziekQ8%LG69WZy5SyzFsFjJ~4bKG0;bfmF5=^AjMMCHC0P^Jm^6v@PkGGIQ5}o8~7X zmal&C!z%4PdF#tB2K)-i0E2!I@i|9~KI0ssg5rUVW4ZAFr_4udIww)NZ8wxsN^6&-Vr{aC0Vj{uZMF`DjoP3cmd{RHWtv!7}vkeyJ2>^4edcQEo{ zLMgWZR=(diI)A2l|6KD1Pa=e;0IEyIHppYiMIHyE?Z|iesTCdTC3?=U>OjjBS{|p!%(( zMA`nA0MiMeWn*MR*_2vs%)uyIQ(gZ~c%rTdG^E!UO`pK1gFmKq&@}J(z2iloftSW8 zF9$;wS${(L?E2FmTzUcx=`}{vCop8`NOg5jqrcOq^Qr$E5UCse-8nnt@AmhD`fhYY zv$fzmyf2LO&&~hM1P94>)(h|dq|b$I{gIVG+Y$h_1)Kg8>qGk~dG5-vVqwUL|8rA3 z!-_?`vpKfkKdB0dYqFicAc^$x0x*BYpw5xbPwQFIacsj;3qQ7*R!6`)kmtC5^&r5x zSog(nKl@xI-3~35wUN#}*hRVinwCq}l^9m6mizyj;u-cw`CsGzmd3x1lPre)QT|6f z%N5vi!7f+A#C+48KI3J4XIk!i8twZi(PV1hM@zWTzA@5%KKt{f$l|%#^AX@s6*e!h zJrDamWB;VG)y3fXKsJn-#EWw7kEGd}B1O6zB*Vn&d$Vad;;E(k58>q%s5 z)ZITIrq$ggsLL^i{ZZ=K>W*N8?nq(FNZpB#6F|%DfnIO|0EhOEs|uXoleK7u6$?gJ z_*Fc+!@1d0@!!lq!vsMAah^Ap z7cIix1z>-p7^(LH>p}ZFSsY{7ALW0k_t9b+FJpR!eZeB0yok^`8jT1NCjjaeW37qaXuL#_o^%d|y>yT+)9*5@Se2u*DV||}l>ZU$`d!$e9oKhB1onPuSm!c=OmQ-Y z5ghE1zvJwYNR3i^6k^Jb{_4+Sagz5vjkbBa#H9Vz9TMK(tu4Qe)N*G3Er5dh8xb87 zISYH~cW@v6ZAkOnZ1GNTs0y1G-WH{t@g@{;&1EgyBmR z7{iKHyO@~9i+wWekMh6R#VB5>r#2}7>JBzZ<_$Kfxv5P$7&0~0t3K^W>-Albr+M%3 z>Xzkeu6wMVibYnf17(=j=)yZ}2a^6d`J{W3Y+qnI7+1&D&xro`UQ^zWb12sX#SH9< z+rjK+&_hJ)g7{PT8JdFH!|fNJ20S*I)jVZv3Vv#sN#lt5XGl^~lBtfQ_9cmXgmHC^ z`z&C&M^|_R@#hfcir!&}=89gZne9sI>gOP0C^^b%WZ4 zPb$gzJ&>XRN-D+9$>TqNlvUApc8uqbQDxyQQq2^cISCc0DwOBHa;R2bktz~1Z}dqb zF8cx}H*nOC^dka*j_>eZfM0$zi5i1Y+DDS9_Rz^triKt})p zH%A_b_yF%1-i<-Lij}Wg?K^!ro*c(R-;4=%+r{X@z?<(bT9t+(zy|NjC5MVv!%;9MO)CQ2lL0}o*2iq!z6?vt6?OJ8L zXg~bQ&HE@pJB&6y+Z#O_2AAj^2=ZO^Ip#uvWgy|x!)oZP!>fLVyymkT!Af;P+~ zOIAP$?`75k)(}eATjmcw4dy!opQu}h542DpRUs{H0CpTghU3^v&63=urof73;v|iT<6X zYH0non4%vCW6VdP$Bp@IvM$xpk*e_Jbn?OU}8lz*21O~7FOY277 zUO0>Iv+mIh1fG(Cr)J=38MrqC@2v1rKj^t-Ul{MqN^VoEOnL`*^{`Oop^q!&Ze1lW zjpeHj<@kL4WW2U`Qd=NzSMSV~b2zOpmqL|trS^?oVZQnmG%7#d3H*6EaI`6Oue{|U zetjo!z8F7-WuKu_k&A-*a`s}4YgeVByqvvU!0G&W1&%w&p?(I=KwuW4*AdB9y@hVK zRMc0H;1E4uK@#aJNc>_cU;itli0_BQXu%jvMsNV<;)jD5=OtLg#f!lUM^-DKhVKVPJ zuRjUB#jEfy#}N-bD@Q!~c4I6C{suA00Om)?Ok>*PUm{}tu8^-w{^M0uaW~Xzc$q7P z6%|?rdJ()DTC%9$2zuH^sa-it4)9j1Hv$>ohJVGTH;HR+RVhdE)+oFnJlY8Fjnsv> zADl}OoIkHqpbEYRsi34+k{7zFXt)c7C}A;_Z{e1gZkOQk+_OQBU9JJak)V-&GV*U- z)sgR6vG0eiTCB#yfU74Rn6KXL+mi((ze8 z{55crdEUWD%};#_B;T+b+=e+71E$UE*%?*1;C+YgSYY_@7;dnNX&}TvJ z7ZCfB(TjN(UR18LJ57fXIBurVG_yqEems|)AM!Q9CmR#UR4*m><6TJ%d)t9Jc^^rs zGjx;k*-9217-zHSM>@RW7wf+Rl~(DS$|Uc`%ck#ZOut>*dB4i3bjOIzV#D=#oBd#x zZX34!0n#08Zh}SmJQI4! z&G4w|rSQ`E&1a{9DVr}y15-Eep9ZFFM$30;dN-rXa)F&U!!BH4m(3TYf$5tMOadF` zP#PIW#Shb{AP>fU@uw{OfS+rxej0&bEoMZ%T?$x3IDQk*_I1f|-O?ZI=rO6~rI6&8 z!Ns?Y$H`j(o9L>av2>K>kqrFV4E*^F`~?eR>^hqz!tX5pVrsF zDdI`r5Kn}Q$KE2`)su@q!b(P2_SbL_e^e1)w&~f>_z*?XF2^8LUU{tHwX2}5?xzD- zIA3{;wE-b>=z$Ab@!-X@$gpJ`Z~5O^9A625IFx@TGl+U#%6@i~9@@ zM*Oj8e|jHzN3D#oy`B&2IzDewyd2bdy)2L;C)qBjmj!kfForGY5EdD^J$LN-s`&1S z?__-W=^dQyajuP3d+ZU6*Mg_M4jHRb5gO*urHItK4m)M~YxgtGfe;-K;^L&l23_sy z_zP51zWP3*!}!JcvG4l(97W{#&%WyqBT){t+wDMGE$J&rjhDbu7wG#U3~RfQ0{1^b z^k@xa^t=3`v=iV8zzzR^Y-IqS(*ZojfaDumzV;Q)-a(w7fY+<>rS3n8uN#XK-;Xcm zDjs}E=8i$_L4A6;ug81>2mL4676%1+h^4H`Y3g>8e zVw=7x6=O?%1uJEA_R(-|I*9*D<{u!dCKLQSBAjDs;yW?Rw-;kCcvJb-x>IlLkI`ni+9EU z5b*Jc3iL%8Ku0@d*fMKq^@d33^;OVA5Wfq;#$Uj{uG&G!q^S0C0yN)Qh#v)B?`u&w zeg$<`i0{Bpi`bihE~;^T$l0u&9B$QS;n43VQ@s8iKcWk3Z)ZT9Q}BHNUzUR(+FK{S zY>ONZIDGHm6q(;aZs;f}Q-_qvHhz`~O*1W%!dj+K%G4s3WwNe9$}}0dwsaMVub_OC z`y6~p%}+0E9CJ@E68Vx=+E9mVqjXN}%XY*$Ip37khs%%e16UzBv;F;&)d(MB!N#V@ z$oTzQ1-~LJ?L*)C96v;SLtBx6eH%1A7RPXVc&DHbgn>i%e*z1P(p6ICXh)!|zO_cnIG&*sp`LzZW15!ywt3O+3F#@vVIr|1`TWhD}7` z5@L9%NHVT{EQvQ)p&crbfO<7IOHzAHLga^QxWEv9(n(&sl5yd^C{|m17qGPp6)}N` zF(O#ypnw}{i?1XCYt&ArHE8W^-6|9wj98&KB^8_*gG@cQz_>A5%gfsJrs_1%)qC-8 z9U2AJs@UH;Uk7iYJlI}1Zyv!fKS4Z+g9MrcS`=Y5Z(D1ViC|aVf{unhuvGI2;$BBN zApP7o!SE!h-+dVYGfsWEVCbKNcrQe{%n3{8!CF`%THerXN>x1#lpTJhdOCh#?f2kk z3;HA6ge|Bi_l^}j8I41XJ>*z{i?1(go*K;($;-gnU#YRJvu<1QLxKTE&^(TV# z&6CVq5ZM>ca8=aG=|-y@6Q2hTFQROC4G}mtzA7h^t&RK~E$z+Uzb?!?1K}Zif zDi2QgUJE={kW23MSo*@W#-h<-+aiphGV#_Q8D-TnMOM5k8s`e`@T<&_XmK?-Rci@u z)}VZB=^vod8(w`35g}vVqnC!mEd~9*1GJ)VlDyH9NGu;9GVj)-GNJRZow|)51^VSZjvunW{rx{399tJVoL_u&v9-QX~!pTjVEOA@56(uSqChog#6x)h5pv;#~iZK;5bKuge4DTA*vbh)%I3!1MZg^69fL22yZrDyi`cv5q3xD} zUC`E-8sd^BY~`8aXwlX(_ZJ3R zn_A>_rU15l&M_Om{OH}`@;ni**}=nyXV4GTKa9R%j1uADxGYP-7Dm0f@ZuP&p|2g| zvKek8=Tcn|Uq5aPC>R~NUd>2aPQ#Q8Zl&dV5jARGF40-)5+d1oDh>cOdYLay{2o zaVz>pnMh%^!J7-R(@MEh@7CQPr5wVGAA_eNOZie^V;NIA zs-#@xZSI6h#UVDuQu}a?KSeEt^tv_>a~uu$Iu?lqs4Q~Pf|B)_t&bT?;o6H(U~UT; zLYX|j)GmWaTSv9e5hp@rtBIp=?6jhUie@fYpGqpL+)=|E&ntE4ss*d7jLYI9S>OY< z06~ZO6jIl@I&>wZtJK9R>(VL%KdCbEd}o-+ga=z0zka2A^`=;$nM3kbXt z9y{_@`%)gYa2vL!sPyurT|v>qFdLRFm}H(UsaOrwZ3!|e&yuBTw{{-HZ%3jQ7N}F8 z3>!N=OgP~F_oFGj=Z(N*=*v#PFH4LT(FV}_DQssReoF{Y!H&P5x;H zJ(0ZE3KPoRz|e6mgNj63`!ZJ-N4WXRIEN#g%~3XT`tq)>#V>=2$$5q=Fu>=t1lg!! zX2JLAS!4(z^LV!|$uTtcrb6}zO<({9E@MXmcsdRSh{sq`!xuD#FKh~5(iFb5DSTN| z_^PJxx~A}GQ~2tp@P?-F^-bZIH-&F*3gfX+*VZ2f)1t!Ho@^l_3glCMtd$q%vQw zHuAYU!-wtPd=v=fB@2UGCzA|Gh$j?e(@LJtW%y8@N-KFtv>kbVkl`cp{2ho^@{rKU z107PvKokP|#C;GF&TU=Z+?+=JwUn1cS$VOqfpx=uE8kRoc4h8zCkku)9T?T%3b!u) zv{xtcXF{%8lHc}f8NaB9oxHu#&+udVk;!HZaG-Gi}wvfmWD zbNyS8W5aw#kBnzMMWgp*^ioE1+*QpXNkuk7r(wQ-KB`Qsf15w`C&+XVsYJld*P~OE zRNdX(JsPez8}GoOQ1dRR`Su ziVLd$14)&J*)`J;m!+W$%{0ViX((7T4RKi-N-H$?QlZFyslT4MK)08xP>`F&P+nA_ z%1vCtYj3~W4I7DHMni#pOcT|~zNYW6WaYuh-X~x?%is%C-TNSU9gkn^b)g za2`eS6dDd7yOf z6z9j3OB4|Q0yHw-(`w9Ph}CDCSEYS5u3a4?4kM-SB$s5i~G>H zNV<~cqZPzIK&;yiE!$7SyhP;VA0lRy&32Ovu(A>K8A%{SQh<7(Ypk{m=9xIx)9i*2tl(G`V*Nznwfy~5w-b0nB~s)$*(`k z46sMfA7vKOM{b%q#UEu(HZ(QdG;>dh>v!VlmlrgywC}tbd*tW0timWe_XFS0bzdp(L+Fn9I-%)D-IaILJs|6^>@;@X1&1MYRb?Btn`1iD_JUMj>F%--3{!(E0v1w}rm2ai`zfFwkPtBft@|}Oo zIDOh*|1BujDGTt$IGKXjy`sz~FXz|JMg7Tf3p@;^=axCW?yQebgKfx>KP=KPP7r|U z)#DhE;-9;`iy^~#(x#RH2}bM=hK`mJ5RCr-Q7VfT01@`M?V9lWy)um46#o&?@UARM z-fa+2CY$0vA#M%zHV{_-oWPVnC(o~!A>Ux_H6XByFu@uIqEOUfYhw>2gbuJDkvfY1 zqCpRHC3a}Z@wNqeyp3}xdf9RK3w(K5=Gd`_^miINjz4M@p7+Ss;{3Y2Oyg)0kMe&I zpNW$t5C>%lWo-!{?i{!kQjKT5mE>rkM}gOX_xFDyTTt`md5ks$QZ+l zMLc;CLEWMZ#}Fh=0L8KD1Sf#vSdW4eKyk-AoB+Tf?-PK_%Equ_RkjnG;u-cw`5*D= zyiuRmf~99JN4sr3hdT+WWKpdt+RoulMzqcVP64!D{xOM8nj}aPJ88n)gOSbi7~+z- z2WXh0nTEK8W}0M_&PV2}2rmK+-YdKY^^qBKT*o%6v_GdMd!-odM(ZumE*Cy24fX%xH`RN~Y%w8D?78KG|E_PqPy&2+-C} zBPrXO07wJe=?*7=@}X?mHYBo+@;~@6y#<+`LJCg-l&2Jjbgo=(U55P`*X%DsJ#T}6LJ&Ut9OBL6x8iqaW!)zuj-xPguM2~^E(E~7(wh?SAlRMKv2DddwXpd6k_yUzdnI`;@dMYp2b=EAii7Rqws%LKHeQa?Z?&Mgskx{<{1b< z010*#pAPQ^y8cgyTK^aRaV8o+4WJM+0)b}`$j2ul)fUQ}kN*fEf!PO`Cq+L_zi&h| z+Y^RH9!dE*C9&oeFbQ;hXRE!iJ`X@Vo-$$#N@U$@L#4{O3KU}wa>d(ufsdi;XlBPS z-|Q)G1=d52Pp0n#=6HQKe7Pxx?TjDfiyGpyi5JliI*vP>drj?{1YeIhzJ! zJcfg~T@fxmwDB&Sx8Y;__`9edm#RQ?6K*ET-;67^po?1IX0=G$(SokC1+J?F4(1RI zoX{Y1E}lR_=%*P!(c({Oq;HQWX~Z~uN%0qC>17vwT8S5D;8YNoe7*=Rh9oM@4b4}UEK*Z-Kh=mO=HT>w z&j;=7d-3vhNjXR4?A!~`p8R~{l7IA&gUKSCaQzv`HBMTBd^w<_(xsyGfT;a*4L>Ug z%Fa{igx&LK|Epq-Byi#IWQTsYIbvsaR!xl9xM_QwSM6H5ll*IqnK!`AhMgPF4gs5K z9CTj7*Ey7c{4oC9FMbqzlsDqm*m^^FKNYh&PCNUc@E7sJ9HX`Q1zLyyKJF(QA6^J% zGn+(RIj6E!WYAoU?wH+2`O%--=u~c4s*|+%O%LOl9OcWW1y^nI(zcK;QsF`4%$R zuB>LIQ4M8BQtTpbD{<3QFs-)O^P|J|A2XInfM!+@IaeyR^~TXmnAD~-rrH}1!=Xae zz+`rmvYP10Gc|Af;(XL^VTxbBGieOT+F}T~F2nY~Qja}R%bKYv6;XB#5O+=$x{Ls% zSLj#h6sillt6DC3btSz+F`K;;oT3x;idrk1y_0aIJ?u{*&(Yc`q2cChD45D}M&FcB(6AV5V%iGHdM&VGwK8mNZv6mY=}%ToGkLj#QnZ zSD!W#(*HSr+_JwM0z4(g{z5mp40E}VwEsXC;hTk!to;69QJ$=AVIOO5AXR3`Gj@{{&#E zOWFC)6v`xyyJz9(oXua8yQ0MO$qSA5_*4=2tUk;}ZvBJu^Ylq}4iE*BD1RWny&(Zd z!_G+!(jco@Gu}51v~3B=I!RQN_T*-8l0Ei;gy@+=mm}UcT?2>{L+p6hJK9=o1@-J_ zCDhy*gTbaby~Nx`mSyH3`_2(56Zu|`b<_KeCx*$UJlq(DMF*AsKr5FcuH>qbvNk>pU%*!v?E&{(ovHxneiC-7n#)v4xwnd*QF3$dz=5F$NI`Mrz zhGneQ)P4)n9J5z*3q8iNT`m3Rn7n-9Y;r2KHqc}`VB+;vu+bi6KY4S&7n-Csa5fk> zuT3~Bfq|@fsdY_l?EFYS@Hur_N!gt+K5_Pc8`I?;ief6`>tbg7r4$#-PtaFXq zuY+yr4t2q1PtVUMUEIEn(8&6(`~o2gG)lMX7%uhiGh&rlyPJllf(7$gbA$KmbC;su zECO`O#Ri+frRac6x#t&x!n#dHTIJ?6q&iDc^uO4Zw2jFI`YDDl%tuYzV<_8r(T<9K zI&{qIy<@gsx>!At$QJ$An9AhbG?BJGX0RWRb8J#Z4|}AnPmm)N`0YThOT5)$tb8uR7tU0wlF z1Iw=ae3aHFv}};Y!1N!hGB_KMtVxCGBZwJh0~gf*H>JA z$0q8E8e{oH=ZQFJrAMj@B`E3mFqggSF{niK_DVTbcdD>T}WDnt!+{Fun} zKoLC;%>mVfNuKJizaRK1U{IMGwUvb1cvTp!uMurYPY_WQp$oThrM-@&P@ajcty`Y+ zrKuaJmaUbr9@%SA5(Nz6vnC@xMha`x6`+B+GwLeX(L@taAaCjb6Ft#KVJ?asGcQ9D zhlrbF4-Xkq5@Dys8&thWE?w6!VVl=`M*4J-y#l%$__G$}p+!eB(6&9Pne`n_HI*_f zQkhNBn65dabH7?2@3*-S?f;~-mTq|!q^Q2;`c>bWQ!$Q=ZTcWdT$rCqMpNc*PHa}N zbfMcVzz*G*D}NeLk^P@6^)bqyt^k8qUKi0c-$z=c>;t@zGQA`t<2BiZu>&v$3S#zD zyveL|s;Dc%H=xKZi}PoIkE1h*qcPCQ`~j3_5TzrT%8n+6dP%dGGbAHitJ@_#m!4k7 zYjkM#u)Su|U}qCbSUQ?!_vOXz5AEgA+@eCK1~%@HDl@{Sf5gbdXk(Vn9qm11Zqi2} zxqL9;PqT7bv6!+m)LTJDrjH^njT<`BEAq_RAeCjPW%^U2`w=){dSRpcQJf=<**oZ+ zZ2f|<$rz{EQ_K1?56I7e0+>I}oiaBN_jK}(TWejr&rTq6ZC|scgtMxQ5i?aSzpCq|u;g^3N`7-B@14n#Mn#l@*EvD z(ia*v?j}fF1D_~Nh7480F(Hr)&;Ffra{QR3wQWR;PxX2b7;ZcQCU_5Y`DtRf7Z=l{ zXVs$V8gAvlV4@jQy_V#+)uP&KM77&VU#f9+#UqTSqop2|b(lkOQfQ zap%H#!gvCI#hRgE1GBT%p5F9mcaA3oFsndJY8=*9jh;~t9m_4*!nH8b>;w-+L-GWLu?yha^~7z zl->CJ<&vsFKC6L^AG56XOfYr_`5c77Y)>(VuZ{1XsST{G3ZG1_Q)P)JM@q1U^<4g+ zE?rM6F)b%lUdv+3bdK|dluZ55vf7)V<+?#yLdVA1poxxkp5(uV{E>(<)~j1OtjmOB z7I#DKN_}^yBPt4ViVA|oPyH2Y?eJTWo0(i%)eqZ;voJ84r(97zTDiCu@sN#_% zURw0XCL#+PE{3}njMq~q5hoXW&KwG^vDE5r$O*Kj*BG)^*Wk9On*>pxIne-TkLESx zU628$0nj@tOO!S|hO`f}w6mUeCZtu-YZa#> z#kR4ev05EP!$YxrT5uFErA6wlNAWs|4|0YKVNEshH~BlHhDul4WIPO&S>a;Cc*oMM z>VBbfCtU}}>BH40*~wRTdWEmHC{a0HZ;aLZw2##TPY6^>E6G?rwZe|oDXr?EF%J_B z+)Ko6WxH+0p+e@$teUy7kEiTYuH-|7D3}A16^hc-i4fM1c}ZE3z`)DQ1A`kLFqWjo z_OxL8aA5nA0k#J@Y;ZKSU^}v#*;#1XenobR##Bl%*Gy@krM|5!jde@m(L53{xzN_A z<`Li4!a-39q(||*G(uv-XpAQ>Osv~qXM>ve+(~%R#v0bUCh_F@VcUh^k`a^$s}K!s zNjy}*UFdLL4ukXN7~+>)n3^kIav@`PUAmAxixRsZe^FvAu6sAX-*Lsj6-MuMOx0@A z+cm;XYeJU9R&f>)6CsjpgAEa?<1#`X(`(wNmRPM_G|Ktr^bv;8#vyjwYdDGwi75!t zRAgDP&~AbI*QR&STal!gvn=U-j7;nsv~o;dGRd`@#H*ar74<~%jFq8l5SLnmjm)!r z*CiqSDi4@^9El&o-PqV59N(o5pu3J9?&xaKWG219N%Kz(tjr`z9%52;VE_>e20;{3 z1+kP^x!59?U=VQTB7?57AnO5?sy-X_$-eS9=+> zZbtqCr~z2#8g-S8E1nTROdvbYBB5nfiEK`53K%dy8-T(feV6f5NjtYwKNvt(cZepJpD+N!Jqy$5TF~RB8tiuI#s{qW9p?ZGmKmkql zdV3Y1xU00al_7Fj?|D#XZ9s+7g_iU$O8PKhu8rbK0^pW$J_H+G?Rw)WjB5tV z>+ta;G0SVbkpY<{7i+T|zXy%Y^IDkY`pDv()!$~&adQ^Cnxkx<+rm3sU}yVbL``KQ zdw);N{fUrVKc1g}^k~1^t-J~6es2v*otwdjDL8*A@6#>hWeV|tWPQ|qF9E6m*ZN`g0w>17t<{$aU**L|Jf@o!UEPvfp*YVoHQ;BaO(|br}XYs zomT-~UOuQbIX$QIyNKWG_z4UX&jMR}Vz$d%_a&s+!u+;aqZ;tbR&g?Em~$}?6`8Gq z{_Gaf<_mWsFvVo>8ohfe73$(^c`>2YYf9e<7Y}a`54T8GX3xg!xsRA4%dWN80oqJG zTC>H;@nk2nZf$6LJyEmYMc%EX4I|i>_omM)5iOj~1RWcq(ft+-8LC|^<>z+)0xRVa zoMHV+fpxfowKX+Hw^!bg`AFc`@Ow2s@lcPNw=`-Q&cx#){DP{G=uV5bBF^BFE%b4~ zJ z6+ORRd(o+?r$D)p={QsEOZ2tfBGEc)uh`g?hxcI1)g4*y=p7jRP-M$LB@+n1HfqfE zI4@IKVbxY)_9>-jUtQeu-mx{K-a8a&Wsl8vh?BlRp;1@x231)n zF48LvZCnk@+JgM6Dv{#lV+iv)-wVF3s9C;i-Iy{Cd5UtU(qb2{MvnB|A%RY=r;6oB z7u#Lkc9XH!o!YCO$N*d3O$MQ~vbbcLQ&~*Xp9&K%3sbwG_bWkfy7JLMg0-J^B6}zC zD(B5%vq7A_n~>gn_=9r2I!7?R_ihVttnp7|x4TF8=v_eCXG^vcLsf0fasFQ5yuWJX zXlyj$18Uj(aqwagZRS`4+2u(;)0~wpW1h_j#a;>N!^iMDhhH()AO{}?f#l&sdS4K6 zHKfqA(E!gsGjOp)t@UpHc;e~lsS@wsN z;b=3>Er%=lZh4}asj@Y`XncE)_>q5sKp$+Ym6rq?pN-lHQ}<$YE{APP=<;YIY1EaB zrY%TTYI!#QB7R^V0?e#5=`dKm3hwQ`7e#V5%kRbf zim{_VE)Vi-E)UU3CCJj+P1f-nsj^;5F4V52gFV;!NJX(l7DKF4?uMn#X9>PG?S3xc zP#TS8N)vB6k|MgwxVBWmJQK`Y@UB3W^osOzWmj{A)4=zrWw(Lv_)VMd`{D0oEb zYv^Z^YumDB@Ue|AMHyKpwKB4I%L_(hJ0hI&lCE|!c|M;!O^yR@tHaT0iT44n=o=?S zuq|8p_1&DNpFUi;)06}D8K@SuC%|fP$kqqE7F$!pFu7>Q(gD<-9>TAvN1c0oCH{TL zqih@69Z(fUZ5D75zWb8s;`btId|9e{wVT(=xerM!=sy=CB!@5HSI|#gs?BOIobwn; z3m$8oI>4h7dUUfCh$OW=`qF09VjDJJb|Jf70mZi)YPCNF6~8ZE@kWz68Q$72r2gX_ z^4k)Bb`etGJ0;@n3iY*zGXd2TZxn8`RK>F_jMR3>@0$a@rK&ZYcNxwyW&o!`?OV3! z^C_e7w^e-Yhp+fqWeLJA-AZ--Ldmu_s;H|ZTmWxxOOGK&VUdX#`%LX^D6qR3rgJ=% zLv+4ldA2>wTA)W*-`DxB#oGK7)l-XW-uh3=zDG>w`}}RbGr(MC6MDAT8f`{VzB9z# zEAIS2&TGRV3`=fSpG`khcx0%I7a^a2v6M?YKjnQb=hXduQq)yMod3+C8K`xJ-Q&A{j(Adv!1dPA}^W?*jpsZMccQpd5Q8yrT^;B zch4tA=G|)Br=L~XY%rvoll?<}E2I49pp>fB8_RpYz%|9W((B}KLrV8oIDNc6E`&cQ z^x5!Dk<3ko`g;aEsdcvqoJ=MmRXNsr!%<3PtibuufU~ew#l2q(bt!{|EF!0hh=V#J zefYQdx11DYvnscPa{6z8{Z(?RgadLa0{TpwSDCOzYK{K?R!)s6$f@3)-|$xyd{9pJ zSk^tu={`%jXE{~3_!f2J|2sKVnW}PHmT`AEy$ev2Q#pd1{vM}soO4CjS$IWG6*)&v z4P;PGEvPT2DpyY_T}~~wkki3-^9P}qEdD1BQzS+68Sd}P0)a)C1`KaiWmsPU1&%TZ zX;vx2e<>5$9m@SV4l-B2;g?Yrmxu>Li4k0c`}QL(3x8cjtBCIEz0HsPaqGQ z!`WV$plCc(*_bU6OnCydqeC^uUCioI+%~Ig;9yoa#48`>Z*Q}@V!S}4ZBF+n-o>2m z(B=DY{-d+Q_IvC5Z^ayFQ@rt1T7emVC#Ir!yL|Zp+OdN7BA9kW%m$X*jn_`ox2NbuYmR~ z=rvKkgs}PgKkwSivY9Z1`F4rB`rNgI8r#;d5fj?$Pb?Upuo>n+u#VbxfT3K>X8D)d zQ}aclt#Q5n!+pKF=EdgE^MAYN(V%8dX=7KxYnv~t;+PYc6$ihxr{aFV(j(b?Ss+=9 zzh>H6yMl;pIUYV)&VOo@Tq8o_d<6misWF>#Q$6$Jknryfhka|4-7m|)H#tS^h^DBf ziS<@!>Ksfs7UAB#M1b@QW0SSr7BG4=9j=H%E1LusM7LKbxfOY09CdlJg0^-gDhGHD zjh1u{@}$sExAWEF%RK71$>svml&F>(ovpQIuk+$~Ste?40`8`}D>q@kw9CgwB|2#6 zrA>Vg66G`Z-Gs_{)lB@-Sf=HYsx2l?2-b+r%EOKFKSZQNFM5c?AO5Cx#>C3M#fobZ z+nQF(W{DxN!XN6qlvn~F3;P2(yT9-hN{B$W+Hael@Ou4-$J?{{~2mmcp|}Hh|b#JzIyA06VfGJi(ABI8;FC z8cmTLcA>)#rw%r3VCrk;^f_Iwjcrctx!k3Q)^6StZ|2Bm(I&8ojCBqLyV}HIylE5S z*D=tz*Sad?Q(8-p*5r-ANj@r7U0m*h}qvmb_X+(qgUTLbC$&0?rc-na%TNE2jvu;b`#`r$) za>R8$a3C~@$jELY(rD4!u{Y1Hef5)yzBp}|-$*X_609~pWSG!`YX`cwyIGBP^UFha#@A01{AZzwf-3ICA zv_>7qG-zv9CWc`=(_M((K1OslRd$C$hMj$3D=3Y5l#XekeV}D%_`=D@^7&}%zS)3f z)tpHsit{7+*OAiM7;G$oj@4TyH_gdOX}jf&9a`%b4h^sQ09g-RLFUpSE(1i*o^*({ z#4Rg?^{*8YCiN2<0kKL zNNc-b#LLgnz28e^aSoo`ANIW~H%?8p54&GcRd*+iddfLzG@hy9=_!_~dUU;X=BAYQ zR-4;;h2F_>C%sej%GdBerL(C^vY^Nv-98&~Hm_BLY?GA59&VH)$k1`89L{y>&bY-5 zr){Lz^Z;Dp;L76O{qeASJqn#*wbHXYv2#XrDf`K^$yM9JltxZw?IVbprJ60XnxhW{z<1c`g=aj8@n=^gm-NQ*Uo$jOaW{O^$;N@@If6b>7O zOMZA1^;_k~zEF0Rs?QJQ?fftjEw%;kr|2KixywbGRQ5YYPk(fm)E}whiQ+mre_PHi>qKEz=uju-pHn9mR;d&DF*kUf^zVtQ z_xB8;$^$are#{HWxwjDn%1`@Xp3j>-72(c~pxIUTV_pOt`!ShAGS$wXM$+EX`D2rf zURz6qbnn93%Adjiw3eIV{92r&b`ohQ@8Z_k>g#w1(_gtubI|lxuDO%7?bGb>Rs+>z zHdR`P=F776>G7OrmX=Po<82}vZL<`S*)#bIGa}paVUuQGA2S5}i68oD485Gali2Kg zq}uXmuPWK_2mI29RY*M{f2~LdCiv^7D}DQ9%Q?2Pdp#JL!RV#DwuOZ1EZiBl0>u>f zh&g+zQhlr3o={6Ss=fjxw( zRu7(B|7O*~JG`75D zhpO&BRFsLj?LU0B0AYf7a1OcXadb1sm{Z_bJw(%>)niQ26qrvxy6OqOL-@U5S5#nzLU}=~aKo^G!In6!mF3Q;1aA9|MeR zQG3PLRf4{HV0nsir_y3e^+2Ge9>_7E9>B-SnSM((s45s4TiObq=7+?sEZI z<~m{l@?Ypbr)7vrGoy^n&bvZAvZme-e2ELyK-kS5cC;sZseG$wE7>Mz67IO~=8nV= zu6?<(2D7eH+;x`p5{lv93ds2EYPg-C8A4uOhK$6^o2S??kak{4HocT|rXodgBkhQy zUY#JxKkI`xi4yS;S*&eWeqAN-JEXb-Y^JvP&cki)x0y8gD^wWL6l>6Wa|TLrVl9;*QL#$!ko<2cKXxd^ zny#cCMo+NkwR#O=SZl}pr}Jj4&FjT(0%{TZ_0=>@eiwC(Zt&BzG+G(&I@Eo-+YZsyxuDv(;o;&7W2dSJ9nWfNWmh$Y zPcHsWjP@1O_}qtmeGOPQ?Wg834DRq#DEv?Q9>ymhBFM-`y> z00=sB*}l+i=jP}3o^;lF;D(8bOU@{;oVu5^^z_%5u<{j>vwptZ+oeHYEfP&Y9N`NT zO0Tl&{%p!a+h3%J*u<_kCU^esz@rz~0u7QZ5Cd>K=X+Me4O8KyuQhDHJ1FUM{*IJU zcYnacD6pTLWMq3PwIJ$;-UCXtkZ>=G(s&8wf}?_UR0aFA7uqtI^vH>xKq<^|QGPoa zn@Fl`(pCEXV1*{Lr2ScS=?bV(sxs8=ejU^{#?0G5W!)H7A_M4(b%jBmKE4D{UWMPK zvU+bid#J?s@q)�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

`2^+eVn(z?mk(^kbv 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�Ar>ie-XP$ZoJ&wt%8&Zh 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

Qe}v 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

4>blBUC!}0^3Z)K(6dBruekqb`jHxVCit1Wq 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

WYxH;ud6$3v1>Q!GKe&LKNn zu)Wc`jWi!<#WoANYlc$3VeZC=Ihjo#Kh=1NnsbWw_JxOH@7R;)SsxUsUr?kJ&W7xs zfSP!Li#H~cW}!&h$FVUuw|m`7tznz_C5&a$WyDMK@|=U^+v}9=eCD}oUpahEUBJI= z!-~yh+jkD1A&PB!d#QyNQL^J_x6-?5{*|7;s4z*t-lpn;d{a0X*K`8h3kgzajPSo;S1kw^WIEKSzX@hikuN7D9u zvOTf$;coFVr8F>Fc@t3?y&a!jCJj%R;qJ6a(1hItz%Gnc8yRhh&Mq}uIW;>D-U9E< zuc_BKPyHK9p_NhGm2ATtf-y0`LLNg%TU;e;>Ae~`s%1wXj0Scir9R#h>9^GpEfU$; zc>)a(;ZFB9=+1$wY;0I1qmgMDt#6f^1tw8X!@C*`j5r-&2>3 zQ<_AQ`;iP^qKO`x)r>WDW`yw(%1UuFXNx5It%u38F9IYT9^W-xjl@%73#@ibYHJCN zu?)4i=vH@uP+U9J;vpRt?hF@uFqGH^2jOMe|$%kewl#KhB~=J)gY7f)ba0&$m3&~WK|ie4)?eA@S4lf`}SLE70K zKTy=tQUrZKRnW9-0b8b^V=?zKpqgz zWN~ImstGnD|ERx8TgnNQpX+DDLqzk#wvQs`tf)3*HTDpl7{1Mq^eFvypB%|BTtx06 z1L!gx+q+r&rDWJQUG-;*4`UEkIleXJ-PZO;*9n(shr)LWW>%>7gzxZ#OR*i)`{Ji* z%SlYNTI*?kJ>{QgK2L-X*QzHK&lbCkJ-%dhO}2}RPIg`Wx|`XUyDba+jM*DfE*Q3Z zEA!jL79SE16rm*eP60l1NSDlB@IB>rFJ49Sw;JKe0!G-`_@QD!E8FgA3+xXzX+J8%ZsPmwQ(I+Pfw=IRnYv}xb6T)gb;mnc2mhx7c-v^uV zr~IUqMq%~az2Kp&?)8OaE6F|i`a-r?Qd~S=^~n|sQo|PO--0SXW&3x%RNDXGPxeuI zMLy}(+M$FEI&l7zAUXBEfPQA%-S5C;%2F0Nm8vcXzXs0cNyN96*t7I+w@u()4Cjg6 z<^As?l{eB=o)Tv*{cg3qe?3xpJ9L$\$fUFD%85>5i!FeYoFNBV)#zdO=EIr+e5 z-~VTXW#Q-iG9YD>s^zUdS@7|st5pUbnX=6^vsi9}{SJe<>qAku!wK72d$v8c3>cj=kj7Q-xe zRO~M)*3K-XR+K{}hp!rc2G?29BxBav4BpIHBPMuyHd4;>cy#E=b0*}7edS3ezm1M5 zlshR5lhaasU|Nc*UtB>E%v^~GWsqcodH9vEsyJwP(B=fal;bae*zU(I8}Jj7+J=$Z zexsJ8mn{64+^x@{$yS zk~TjAKgKz9%R)>KAgi4k99>g+wfRCw$Lv;LDzW_#rV26d#RFj#djg|^SF)}CuMxc! z(FZBo$zp0fDiP#`I*IU+82$>}WYC#isZXvY-!S#b>{Lr|b)Sy<*8KX<3a|1+SRDEN zq1KR=e_Ol#;X3kH464a5Nhh!j_{=VVGQWimTI+?sP~|{4b`watd~*Wz}%i2rSsA8OB{@ie_cgd zQdHm|mtCi;Nj6xmHG0--J?zawTPF8oG9t8%#b1e*Z2PNj4#NiPy;z!im6H!i(}1rh zT4TFvac-e;0Vn zY@_N(UDtMAQC4^2l&rH-liadX=~>kFBBLj6H@$$DO1eds4Rp*AjwygiAer-uuFkAk zUtyr!0gF?X>h~TjnFUy9n^8pR*PViwSAZ9z$tRX}g??T<3;odYmw+of00}Bb&KPIL zDDfns*W%DC+6rX7PDL!fw9Ns*t7m*n93(wrUV8L0M^-ly+m+&6%SKZF}dPFzdD3Djw+vmqO)YOF5m}j z^kywR_c!lCfEw_G=Gr3efvE0W>Ut`WSIYHsyj8vNP_6T0LlWL|`}P|QFEs$n?b}lmnM9X0_o9i|w=0@L@Xv0J^M!YBXxx)_ zGQSU)JtV>KElc8pmF;S$lr3Y?D&egNeAfIiUubxm zp60)xic$6JfXUaYGYgox(lnOPTA>@o$@xfT_|ICRx-;VAD4j0R3tgf=(4e)P`H=uW zb?}pgUdPu$?l0Rw{EfnoxtK8Lc9BDU$bHWwrWTP#a54HkywKqS>tGm(cdE7(>K+hJ zCA7VR+||WHdF0ZGb#hv_H?YLVtGUKWHS#<`$|h-{-cr713%MfhL((K!UQ4%{QP=dv zN4IRr;-&N|zPW5EyVxUmziHOC$V51`#bMBX3yX|gl$C_AWrf}K36HYz=+rk*lF`gd zsjnRO1$JGJeKH~3G=p~MMKoznuOn-M&|WsT`l--NoHt1gheuZH)81Y?yMgGMiQENqNnhBzgW zQFh;5F}oAP*&afmFonkh38}?B>GqoY!)opiB<+4^DGMgj8DEu+w?0{TrRZH}h>NpG zH!I}Ga-!jy-L!=jrDVOoV4xTt10Iq#h^-`~S;n1o2!~J}GaUH*C3I9As>@n+Di4du zm5v;FNW7K-RSioC=Qa@LP_$mP_$#v7*q@_wTy~a=dd>0e^m-qbtz_B#-cFCGwrmG*h$9np4%&d#G|kbc%0AC+a*SaP^in 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%0DKZ9lk%@N zmxKPDS#7=v{HvMieFykICeM5iSm=>Hh!U5BaX7FzEHytxJ37a!GWP-3qJKROZ1mb} z|5%I>K5B>ev5a0m>-~jdF|RBXP8pZH-jcl1nr^Uh#dQ0hxVUN?LSwk-Zpb8 z>uvrL zf4zAc{7L?OYInVP74+f$Hd7cHQ-gftfwj2zlJaghCxSlS@6OnNALvv39xX?&mSek( z!-dEv<3*qP)1S$A8uG1x{wU7h_fIirf&QUCkVzN4YfKaP8~s6tA9|5LQTZ=HdQ|>P zfq(JS-Zj9#L+|&1A2l!8d|~ja*#x>USZW>zmIc+G)Z0??w58*Ek@~6jWL&BCr2eWs zslOWUcaVS7)OddazBQ<|et4!%={ijp{s~BzdZ_dM1^Kn6)|2|EQ+}-%jpHW;bzVVE z)IMswDZo>L(casErvan!_cZ8{alF=hC-|QXs=SW@KLdV*=K|}29`wt&DELL_6?&rg zd8A(&%u#>mc+vQLEod2!=P7@l^5-eP*839j-4fJ$a{Z|Dz6$zY*o&|e`o9g_5*+XS z5ZDdAT(=s$dsHq;za?l?|Lbh}Vz18Y1iuBi1=tDv1#l1aF+R_NJ_-8v0)HPg**M&b zbcxTYUTzBGeUNAEn6TC>1pQIe!$jbyunzM?V@iP%w>%T^f2{4H2y#b(t_+45V^uA=r?7k*OZn$`amnqKE!2>DgW{}qdEo?PeJG=A+?&NFQq*Ea9# zkZUpRO1FC(L4PQ0_qG9_L?k4Cr{?d{{GBS_srkELVVRb@P3_A#?qMz+jh~A%*R9wO z>J=>0__V1%Wg4e8^`p#}{#BhRxAf;Wy&lvkzt-B@f$OJ?8P=ol;1}E z%I{Eqhw?j>-=+L6<##K;NBKRG)Qs<4c`$9dPxybl(Av>m1Lhr%%V#J{{NkhK%p-c$mCSxcaEq#dhttf-PQ$ zj@#)V>W`~TyT+&8mw8aTFW3JL%ReD-^^snq^Nq4V=9!g>v-E!aAj*B`!8p9JIK=Jy zK>L9!pN)3=6X}s*tM)6w7Oz$NQLFZ&R_#Y^PCsh5_oW{0&!g*P3)Tr_d}=q^|BUp% z<(Yi+Kj~Ms_CLWEuUhBb)jFTA)_MGjjGkovPG>yq)bX%W$HUIdc({N2?V0@4o0Mx; zeeJ5RJ)>{`@*Gz>HLij!UZ=*jQ{&pHaqY^KOYC-NTm>=C={jMx&POJC9hhGfq?Ve8 zfQP0!H0~W5_YRGFeMWE6&o-5h+a=S9$?~&2{W;NmXEC0@3ic}YD0VA$DRwG$D7GuM zDYh!ER$QUDT(McPNwHC}L9t$Op5h$E*@|_FwTd;0)ryshWr}IVP;oGnatUU8n{9L3p+b&9o$HHy`Wm5ODG zX~j@+(9UlcdjpF7ihYW`iamf0}I8X6Y zdH31t&u0+d*U!)NZuMWV#p_o8yVd`0^}k2`@78sc?o55qj>Mx|uP@yi=k6ib7s|Wn z)*sVdzDrY1a8R$mf-T;lUUvuey1QD-!ScuTKt0sIe{Auh_33km#J4p|JX$p#ts0M3 zjmJPvG|#|&yTukf#h3ZUK#t5e26AM5WFSZ89fLOggrH38OR&Xj(EElmt*yw$U>!*8wrT&JH%$KQ@k`o?<%GY>l#epz>b%X~bl^&~+h`qgb>3a(SkOi0 zF8iFrGqTQmLta@**0U;8a$mGNd?)1A<<+D%AbuY;H7Qx2Zq#*-Q~YRNdq*B|sd*pd zAIMv0<^nh8?G6_JAI+q@bg!;IF@Kw`7gDY+CG}R9l6CdEl-y^{w*03v`YBJWR=uQI zj+hp|I(;cmrFIDO0CB>ji=bb^Fy`U!Sd<6IZvPGtufK_livJJOnd!ztpbxn}Tke-!q@|zX^U}L6fCR3wo5_tNM2r zcObo{-~#_C;JXTT7yrT1d%P(HSYIrtGBbdu6!h78TkQ2a`34+%w3ffce>d`dzThhV zGr&5tO0iDIfz9?g++#UwY+Q@XI{!K=w_fE2t==ucpthI6)B{LwE(mj@e!Ih?-!1+Y zYiG094P1%qX7oIEb-_}z%j%Q$(;Ex6nP;Q){Po_8z#kUe<^LV%nY;WT9gRPC`G){+ zFSyTt8?X-a@s@7!=U95P_etQ&ye9RdN83jacELsMx<}*Flal9!oBfNd{5Jnvz*@h> zUjzJnLE8H7nRKp<<}~|QpeRgE!XVaJmjB}o}+T}RIc9owb-lI^g1nn zy~@?u@;{wdr+(Ju%6L(iTLpc!>4w~o!M}5Z1}lGRx-M7Z-lTRL)lRc5AI2GtLt}0u z>SwKKQakmUPv)9YM}7Es!Ex0bt0`%90F+YWDM@iXxIxim43^-NcOX}un+@bf@m*zR1b+h_UN|H0i=y@;`#~-+bNw>V z$C=}Uqk%PrYfQA?;ts@J+R1?RZ?QL+E8`W%^Kg`uJ3UJJ(@DX{t=^LYxsD8Kxdv^! zeH!zevyi?yuS?q>%Rwv~6^(AzzijKm@IWjNe z@{5~odE)+5Wu689u;PiH?B9v~-wXZ;#mk4tzXX0mag`YaE-G%Z^R>mraXu;cibTFu z#j73K3y&Oa%-zMU3I4X?HcNY^Bf)0em?Pu&9PMAT6?=6*P`%Pkifo5- z!{RZx|0!7%Q~;L#wI+@ZSgek$vdXGkQ)^{fokFNdH91CxfSeMW!Wu&dRrh{T7#o(Y~$u z(DP^IzpVIAi;KdbH1a3*Z#-zvEDEP99B?i^e(b=OSo9^5>5Xa5WB3y zsGg68+_x-$jadV{u%t`d1?RtO?0WO{8jqipEHTObEG^-UHh)Wai{fpHcPVaA>{Q&O z*rm8tv0L#e#s5-#&SJfeqY~GLOX^2O?d0jamheTD8&Din49lc^#fqgCyY;%$5+17j z!xfLTDE0nWN%yF?gU0v}&eHVv@00!v;&z(y=PG{8qPs5F5}v8)^A#Hu7b-R?p09YZ z#p%IUfNRb4U={Gik}A^YVR zshAq8aZwy^aZNA@7|9=LX^BI6bW3=g%DrnJ{y6a8D|~Mba5CtR?~`5)`bMRPh1DE{o!K9rQh+{2q(dx}T|6$ETLCcOUsV zkpHcvtIYGjd85~uzX1PZbYGVKFfl9`XUvk({Z9IT&Nr5Z(RKY6=q-m_)X$>!dUVNX zuL|_~(Jet#FAoAYU>tY?$m`R`kiK^)9WGQo=PO>UxJw2VY#1f;hlWuy&Nqzu6Zor4!>E^mi@inRG2<~FjcEyI1CK6wK8*Hb9XsZw@J!Ih zj+q#q1w3I)llIez;RT>S0Qx%HPhSnAdDE64&(3o{KIT<(E7H##la~{%TW!I9);mF; zrS!Q-kLDwdN-r*!dB_DyUxf7gAb*L{%Rp}ieYw(CgMJM3N~KqW-VS<=(l>(M1^Nd{ z-wHaK@7$*JPc{8#%I^e5{%!_Fem)9}{CgZ2&5wQojQsf(F!JNqz{vi80VBJ8V_prT zdD-)b-yc9n?cpzq|4@8QF`7U|>Cuf)g!zhN6(=c9SA4tTyAkd#zgGNj#eT(?6<<>vHBrhnTCrSls$z}ev5N0jJVo&% ziXXT5Qcw?kVN5y?>aji{_b;o8Ukc6v|6gOuhVU-{zofKs2)`Nps?zEq{42pfrnF`V z|J&fdr?hqm|NG!SSXeiN|6}mG3uh1E-wS?Y>6{__hr!=cIBy95N${^KtslaF2KnJ3Yl^9Ip~oneD;}6Wu7bZ=NC%n22UaXE2UMY4~TVzyy$+=FKfz^>s`+% zq34Ftym@q4vzC|lKhuL3k?(C~RmQJ~@>iKdfyZHf7>)Nc!9Nc4d&-t)@|_I&qh)i$ zX#Tzk>F)>KRJOuNpRMEFY#ryS%qOf~!K;z)Y|z&NzhwDy!|wpEFT;Eo*ao~)@nMT| z!#?0o%BF{Zwe<85uTDWu=C}8kofKAq?k+o3ac+1r=%+z{7`O*`Ca}amHCzVVi+u9F z$K3F4(0@j{;DVgTt=xi~J-|I>3v$X1L3|;94DesDBl#zW9|c`Bc5e7-i&f@}z-V55 z39!VM`YRth(e9Ia+t@B$&&RwG=@*u?<;i_Pd!F2XcWC_F`Q;w(YRI2EcC*(CT$#sp z#yXv^k#5!Xgih7B-G37D7mXGC+Ss{4UzC6BM7^)rrT62z{8zv)GQ0e|LlOV6SLGZ5 ze16O>|5)Jn$L{h^2HpaGG>$~;K_3EL>u>YV0k$ju?y)V}PS;qxf9#r^B}m^4Tn5}S z_S9e{uyc$&SEw^0k9BKZuV~ZuQf0maxgBG-2kU?@mb7X6nd?XE8^0dAF6Zaq*O@Mj z-(3G`&>zK{Daq$E-8P<{S)cPF(tllWm-TChx7{zAg!e}fmqRVymm}-c-Fb4I@6Njp zt?L$CUm&*Y zdQrQ17VC;91v5;v&iLMO>%HiUF&`Y4&KEz+@~M9X_;;lHjI6VTzF?(I|GUrmcDve( z$B$?p^|f(*e7`9(zgi1@w~ecbE~~hos#UDZ;0EyVTr6L(PoF2u&X@Mvr~cRE%lh%0 zd>MCYRlYV~?vHEp<$k(0U+$-C@+IDNny=2%v&=j#r>qMNj3c(`J|Di9DD~WlH)zcXmmb-PAg2Ws?1u0hN9e9jS*qxH-<tXAtpM&2vzD@mW zSM0F3*lSn6+7vr2e}~tRA3Yy<-hd`uUz+TfVd>Tvy@e-tq1EGT&#r>(My&Y8;o^`+rl=>&g3k?0>{EU*6{` z^JSlWpO%;Y^f~p=moMw1efhFp+USeke$Dq1-n7DXX2O8_&GzqF%ub{vFS&EsTb$G5H?Zf%igw6g3q34+i6H^VqJrlN@3xK~@{PTo1y-rqZIpultYZC--PGfx= z@;MW03Z%bxrQ~^4nJ>?G=IA&q&k;@tTz?rKBI8tR%Z+ihK*u}PKU@8nqx3wb>y>U$ z`r5p2z^_kFBsQwPMyqcYo;$lR*b`eVyNw&`O*nW@l)5-;e&Wd?%$!r(m2eKgrg|p0bltwV=0^pPD)u_*8kdj;CEI8K>u{op}~l znQDCxuUgle=cZ&{TCe46(DKo)%)Gm#2vmzvXG^zpJ%AHsmcpIUmgLs9dYcwJF`M z^a`zyL4E(VQ|+>U6Fb#@XIjSX&a{l%Qm&XXHKIdK*9N(@?nq zi(4uN($V#Lcg`9k^Vq?3Ez0$z2@8qu1daDh)AAm0SSXk-l=fd%DD_)eDE+OvP{zON z!r91o{rKua8ULzPuDVd#MRlR{N7}6}lzB>x@@oqvezk=UqrP_M)TzBHeQrI`n+yF% zR8I7weH1e*XIs1R^Tat0U902HJmqs7sn5{zUVo*|pBoB43H>dV4TYZuK4}^X8-dqU zHY&eS`HdOA+~+qIHbd^)$hQ)>H*Cz{8qjs7u~5df#zJWajfI!l>t?g{V@+jqq3Bs* zY0s=ye$Ob;+p7L@-JoZb_}Nw{?Y+&$_vyTzQDU#%k?(NmPSxL~cDvO7F7>ag@JI05 zFY8vhZk6j+xgO>BTEzEL3#DK6YyI_W{SDakxPERexD$F$KV(qzg+kbeNaiuiRsRab)oQ0z z{cTnMn~I`-dT-FCc3A)I4&C9sV>C<@jX?gmJqWk4P9Ln!V^jo|269&}oK#|O62i4C(Tdu#FuvqH9 zN5|`)w8Xi`UT=2iq>Hz~-zQC32LBWEv`OjWUBDTW$};#I=(Ui06}WeNS#i1=-_Mv- zT`bS@Ypk8pf-XD$E%x&4^Xna6nLiG4AD`5f7CW_8E^b#f#nQiOilu$lX*%y0XBSJm zleld`{G^_{izKf7`4Yb}e+ukeHYwEoE^{>Bykcpu?RsBUpV2SZ={fd3VzDG&w)M@H1T54 zjb3Z-Hyuu41`9_bATw^AE%N>f}`^ z*?-xkcB;%I@S}C(w*o&3oT>DOfqStIQLl7VztMNE7Ad_%@k+&SE3N}Za<>D2Il0Pg z0ycV8=1JhL$!h}nK2M*PgK=9E>_U3vhhTs4-$6fV`n4YVi-W_X>*9dY1DZaN;mdWa zzqk}~GbRmWFxt<09P~(kAIPBe_krTckbiCRK(Vx!fnsToVM#Quq^iOa@gppecCsco z2J+ay6`ZIzNAa_Y5}!4}1xhbdTw!r~a3c`wlEH1tm*?RNQjc5yf|RV2t_gkvdP3DY zyFc&Hs`aU8U&R!l%*(=(mu>#AMA~;+{Y|T%Y4v+eD(47mFI5hlQMD#@gyL}))2gRT z^OtG(EkKBdexf0 zTJu+H{%Xy?ASLx%qvfp8^cpSa_MmcFq?{_&MA@WK%L^e5}D7=(ex^F8uYI<^K3p3DA$Gh5*gp? zN@QNqp!`PV&ryDp@|%_4;?IY^MsInE%(w4KT@L!6RV!4k%1FIdnH#{bGpp6_R`t78 z{c0_V-b{^~W3WW7x4k7guPBMePkc{gw8SetTH@81mU&Xy=%^pZ-{0bO zm-CEDP46v4Z3`4Hmp;-FBbg)a&MhF+tQwyJv#bw_>;ib6mzHJz8Lg4 z;CrXebMiHej@sX1uTk?gjXo4|7f)@}{Eed}|DeWwx#s76&I*S{MDnS{#TEdej@uxN~){VdOw(!b&XEV7uTcA zLpTrM`tR{UG=HnE?o#<~izig~DBY`cpZY(j?RK!_lkjh`*K6bEP3;{W)oVmc{dOz% z+x)n186Ew?$raW8qoXf(?+yD$N5AZJE$GXXze@RQl)v3G<~vB2?|Ge49L-~HsP0yK zwFOc8x}$o)>hJUhMoT-F^+!A>QUB#R3i{8OC~k|r^q8of<2`^e(f7k5jQT_Ugt9Tx zAIiqa{JCY$tgalh0r)CV%27E+{H#&^m1D&J$}v*Dnv5PP zXH7<*l(#0MXAAVUm>RWHqjqXkU#-<&T2Nb-W#o>?;S1as~!H&4tpu6LB9V!tTCbQ zx%5lHJHQVQZ%XhFIsB#I{ovOf-kji{3I0Oxk11upz`8%^uN}TTAs6L8AN(5*UyA_c_>ufd@Ouw$P4HhkJhrnQ>4jcfB0bs%FYEc3pCbM0JU1ROEpjm}@rr3l ze<>C1_gZm8%on*jt*@>z(fEgb-HJWdpVER}^{da~l~eka9#Fb(jPy5o|0fLktUhll z`^$jR{I1}j=4by8OT})Fwx1q6xwh}sjFJ0zu5ae${u6OH&Wz5T@m6Dsr}Y&??d;y5 ztd!RcS&yyE&~o2VouQ-s`YU|ejmII$S6g~E^#0YZhZ04fOtXT4x4j9O_p8daPe3RQHzt z0CJjY%*gEq zerWox;8(zT)7OQ&Exjh}SA1&?p1)2XES34gUHTr(eZleIe_{IW;!A){)59`p2fK@J z1ic*mjldsGPdofFrK|P19p$UbWZbGzJjuS7@n6$VRh(<_x#@Twb|l`T0v-m8o`*$t z|1!PS>U{6g^*I(@#h zFpSEzJzN+@<@`i`SD9S5I?Hq(tlvfC_bK_EOVWJriSI%2`=;*qPP5T`j#sDay)NCO z{&cH9e4m#4V!4jZb!|ScbD!Ul=6V{}*SL=8t}Bw}b1yyzo}xyhV_^AhtuoSV%Dab9Ll$9cK=7|vIkPvN}6doV(0TIBzw#;M{F~ zjPozd9XR)x4xD$I`*7|x8*$!kevWgW*^2XC^90WQ=9f6XXr9J-!1Ut$irItnonBPN z4lgR>1}`dOrx%qD-+;%t%#ZjJ{D_Y)D&joZkIGo>N1h*@6Uo%(L^9{w|C{XpOL8Ll z=A0;2%W|Sz%X6YwU6~WbYDG>It7~&2J*#t~SY4kJ#i}(Yiq%ayQLNf>qFCLU6UC}M zC#tVIb0Ui!IZ>=O&M6r4$CyLczP82JXieeR}qF9YeJ%@8T^+%jb zQZM3MmUN_}JpSl6( z*3|cLzA4p)b6aXX&bOv+$GJUqH_msaHsIWmdJyLgsfTgyOl`q=Q>q*1uGDs%x2B%L zxjXd?&c8_Q#<@2YwUFKR+?R^lNx%L7Mf?9iDrzUMq@s3WawEwwH?UL}lL4}rj`RtH5_+!!Lnl-fkd6b0 z5>XL5mXCwjP!T(Jf6twH?(dUte#gJx^FN&Pyzcv%+vd)lJF~;=CSJ~y67llr$KvHN zx;tL(XG=Z&{p9d(46o*=)UmghcHTE+4^f?S+;2r8-DX5bt)pA^hibQS457+ z0}(kI4@Kl?REfx**NDh5sU4AJ>qlhIce^?Fxp|(7$gw&ckz;i%BFE}fM2?jmkz@6I zM2^+Ph#aezBXX=>i^#EhGcpt{z8e_@{U9